⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 autoconf.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * All advertising materials mentioning features or use of this software * must display the following acknowledgement: *	This product includes software developed by the University of *	California, Lawrence Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)autoconf.c	8.4 (Berkeley) 10/1/93 * * from: $Header: autoconf.c,v 1.38 93/10/01 21:24:51 torek Exp $ (LBL) */#include <sys/param.h>#include <sys/map.h>#include <sys/buf.h>#include <sys/disklabel.h>#include <sys/device.h>#include <sys/disk.h>#include <sys/dkstat.h>#include <sys/conf.h>#include <sys/dmap.h>#include <sys/reboot.h>#include <sys/socket.h>#include <sys/systm.h>#include <net/if.h>#include <machine/autoconf.h>#include <machine/bsd_openprom.h>#include <machine/cpu.h>/* * The following several variables are related to * the configuration process, and are used in initializing * the machine. */int	cold;		/* if 1, still working on cold-start */int	dkn;		/* number of iostat dk numbers assigned so far */int	fbnode;		/* node ID of ROM's console frame buffer */int	optionsnode;	/* node ID of ROM's options */extern	struct promvec *promvec;static	int rootnode;int	findroot __P((void));void	setroot __P((void));static	int getstr __P((char *, int));static	int findblkmajor __P((struct dkdevice *));static	struct device *getdisk __P((char *, int, int, dev_t *));struct	bootpath bootpath[8];/* * Most configuration on the SPARC is done by matching OPENPROM Forth * device names with our internal names. */intmatchbyname(parent, cf, aux)	struct device *parent;	struct cfdata *cf;	void *aux;{	return (strcmp(cf->cf_driver->cd_name, *(char **)aux) == 0);}/* * Convert hex ASCII string to a value.  Returns updated pointer. * Depends on ASCII order (this *is* machine-dependent code, you know). */static char *str2hex(str, vp)	register char *str;	register int *vp;{	register int v, c;	for (v = 0;; v = v * 16 + c, str++) {		c = *(u_char *)str;		if (c <= '9') {			if ((c -= '0') < 0)				break;		} else if (c <= 'F') {			if ((c -= 'A' - 10) < 10)				break;		} else if (c <= 'f') {			if ((c -= 'a' - 10) < 10)				break;		} else			break;	}	*vp = v;	return (str);}/* * locore.s code calls bootstrap() just before calling main(), after double * mapping the kernel to high memory and setting up the trap base register. * We must finish mapping the kernel properly and glean any bootstrap info. */voidbootstrap(){	register char *cp, *pp;	register struct bootpath *bp;	int v0val[3];	int nmmu, ncontext, node;#ifdef KGDB	extern int kgdb_debug_panic;#endif	node = findroot();	nmmu = getpropint(node, "mmu-npmg", 128);	ncontext = getpropint(node, "mmu-nctx", 8);	pmap_bootstrap(nmmu, ncontext);#ifdef KGDB	zs_kgdb_init();			/* XXX */#endif	/*	 * On SS1s, promvec->pv_v0bootargs->ba_argv[1] contains the flags	 * that were given after the boot command.  On SS2s, pv_v0bootargs	 * is NULL but *promvec->pv_v2bootargs.v2_bootargs points to	 * "vmunix -s" or whatever.	 * ###	DO THIS BEFORE pmap_boostrap?	 */	bp = bootpath;	if (promvec->pv_romvec_vers < 2) {		/* Grab boot device name and values. */		cp = (*promvec->pv_v0bootargs)->ba_argv[0];		if (cp != NULL) {			/* Kludge something up */			pp = cp + 2;			v0val[0] = v0val[1] = v0val[2] = 0;			if (*pp == '(' &&			    *(pp = str2hex(++pp, &v0val[0])) == ',' &&			    *(pp = str2hex(++pp, &v0val[1])) == ',')				(void)str2hex(++pp, &v0val[2]);			/* Assume sbus0 */			strcpy(bp->name, "sbus");			bp->val[0] = 0;			++bp;			if (cp[0] == 'l' && cp[1] == 'e') {				/* le */				strcpy(bp->name, "le");				bp->val[0] = -1;				bp->val[1] = v0val[0];			} else {				/* sd or maybe st; assume espN */				strcpy(bp->name, "esp");				bp->val[0] = -1;				bp->val[1] = v0val[0];/* XXX map target 0 to 3, 3 to 0. Should really see how the prom is configed */#define CRAZYMAP(v) ((v) == 3 ? 0 : (v) == 0 ? 3 : (v))				++bp;				bp->name[0] = cp[0];				bp->name[1] = cp[1];				bp->name[2] = '\0';				bp->val[0] = CRAZYMAP(v0val[1]);				bp->val[1] = v0val[2];			}		}		/* Setup pointer to boot flags */		cp = (*promvec->pv_v0bootargs)->ba_argv[1];		if (cp == NULL || *cp != '-')			return;	} else {		/* Grab boot path */		cp = *promvec->pv_v2bootargs.v2_bootpath;		while (cp != NULL && *cp == '/') {			/* Step over '/' */			++cp;			/* Extract name */			pp = bp->name;			while (*cp != '@' && *cp != '/' && *cp != '\0')				*pp++ = *cp++;			*pp = '\0';			if (*cp == '@') {				cp = str2hex(++cp, &bp->val[0]);				if (*cp == ',')					cp = str2hex(++cp, &bp->val[1]);			}			++bp;		}		/* Setup pointer to boot flags */		cp = *promvec->pv_v2bootargs.v2_bootargs;		if (cp == NULL)			return;		while (*cp != '-')			if (*cp++ == '\0')				return;	}	for (;;) {		switch (*++cp) {		case '\0':			return;		case 'a':			boothowto |= RB_ASKNAME;			break;		case 'b':			boothowto |= RB_DFLTROOT;			break;		case 'd':	/* kgdb - always on zs	XXX */#ifdef KGDB			boothowto |= RB_KDB;	/* XXX unused */			kgdb_debug_panic = 1;			kgdb_connect(1);#else			printf("kernel not compiled with KGDB\n");#endif			break;		case 's':			boothowto |= RB_SINGLE;			break;		}	}}/* * Determine mass storage and memory configuration for a machine. * We get the PROM's root device and make sure we understand it, then * attach it as `mainbus0'.  We also set up to handle the PROM `sync' * command. */configure(){	register int node;	register char *cp;	struct romaux ra;	void sync_crash();	node = findroot();	cp = getpropstring(node, "device_type");	if (strcmp(cp, "cpu") != 0) {		printf("PROM root device type = %s\n", cp);		panic("need CPU as root");	}	*promvec->pv_synchook = sync_crash;	ra.ra_node = node;	ra.ra_name = cp = "mainbus";	if (!config_rootfound(cp, (void *)&ra))		panic("mainbus not configured");	(void)spl0();	if (bootdv)		printf("Found boot device %s\n", bootdv->dv_xname);	cold = 0;	setroot();	swapconf();	dumpconf();}/* * Console `sync' command.  SunOS just does a `panic: zero' so I guess * no one really wants anything fancy... */voidsync_crash(){	panic("PROM sync command");}char *clockfreq(freq)	register int freq;{	register char *p;	static char buf[10];	freq /= 1000;	sprintf(buf, "%d", freq / 1000);	freq %= 1000;	if (freq) {		freq += 1000;	/* now in 1000..1999 */		p = buf + strlen(buf);		sprintf(p, "%d", freq);		*p = '.';	/* now buf = %d.%3d */	}	return (buf);}/* ARGSUSED */static intmbprint(aux, name)	void *aux;	char *name;{	register struct romaux *ra = aux;	if (name)		printf("%s at %s", ra->ra_name, name);	if (ra->ra_paddr)		printf(" %saddr 0x%x", ra->ra_iospace ? "io" : "",		    (int)ra->ra_paddr);	return (UNCONF);}intfindroot(){	register int node;	if ((node = rootnode) == 0 && (node = nextsibling(0)) == 0)		panic("no PROM root device");	rootnode = node;	return (node);}/* * Given a `first child' node number, locate the node with the given name. * Return the node number, or 0 if not found. */intfindnode(first, name)	int first;	register char *name;{	register int node;	for (node = first; node; node = nextsibling(node))		if (strcmp(getpropstring(node, "name"), name) == 0)			return (node);	return (0);}/* * Fill in a romaux.  Returns 1 on success, 0 if the register property * was not the right size. */intromprop(rp, cp, node)	register struct romaux *rp;	const char *cp;	register int node;{	register int len;	union { char regbuf[64]; int ireg[3]; } u;	static const char pl[] = "property length";	len = getprop(node, "reg", (void *)u.regbuf, sizeof u.regbuf);	if (len < 12) {		printf("%s \"reg\" %s = %d (need 12)\n", cp, pl, len);		return (0);	}	if (len > 12)		printf("warning: %s \"reg\" %s %d > 12, excess ignored\n",		    cp, pl, len);	rp->ra_node = node;	rp->ra_name = cp;	rp->ra_iospace = u.ireg[0];	rp->ra_paddr = (caddr_t)u.ireg[1];	rp->ra_len = u.ireg[2];	rp->ra_vaddr = (caddr_t)getpropint(node, "address", 0);	len = getprop(node, "intr", (void *)&rp->ra_intr, sizeof rp->ra_intr);	if (len == -1)		len = 0;	if (len & 7) {		printf("%s \"intr\" %s = %d (need multiple of 8)\n",		    cp, pl, len);		len = 0;	}	rp->ra_nintr = len >>= 3;	/* SPARCstation interrupts are not hardware-vectored */	while (--len >= 0) {		if (rp->ra_intr[len].int_vec) {			printf("WARNING: %s interrupt %d has nonzero vector\n",			    cp, len);			break;		}	}	return (1);}/* * Attach the mainbus. * * Our main job is to attach the CPU (the root node we got in configure()) * and iterate down the list of `mainbus devices' (children of that node). * We also record the `node id' of the default frame buffer, if any. */static voidmainbus_attach(parent, dev, aux)	struct device *parent, *dev;	void *aux;{	register int node0, node;	register const char *cp, *const *ssp, *sp;#define L1A_HACK		/* XXX hack to allow L1-A during autoconf */#ifdef L1A_HACK	int nzs = 0, audio = 0;#endif	struct romaux ra;	static const char *const special[] = {		/* find these first (end with empty string) */		"memory-error",	/* as early as convenient, in case of error */		"eeprom",		"counter-timer",		"",		/* ignore these (end with NULL) */		"aliases",		"interrupt-enable",		"memory",		"openprom",		"options",		"packages",		"virtual-memory",		NULL	};	printf("\n");	/* configure the cpu */	node = ((struct romaux *)aux)->ra_node;	ra.ra_node = node;	ra.ra_name = cp = "cpu";	ra.ra_paddr = 0;	config_found(dev, (void *)&ra, mbprint);	/* remember which frame buffer, if any, is to be /dev/fb */	fbnode = getpropint(node, "fb", 0);	/* Find the "options" node */	node0 = firstchild(node);	optionsnode = findnode(node0, "options");	if (optionsnode == 0)		panic("no options in OPENPROM");	/* Start at the beginning of the bootpath */	ra.ra_bp = bootpath;	/*	 * Locate and configure the ``early'' devices.  These must be	 * configured before we can do the rest.  For instance, the	 * EEPROM contains the Ethernet address for the LANCE chip.	 * If the device cannot be located or configured, panic.	 */	for (ssp = special; *(sp = *ssp) != 0; ssp++) {		if ((node = findnode(node0, sp)) == 0) {			printf("could not find %s in OPENPROM\n", sp);			panic(sp);		}		if (!romprop(&ra, sp, node) ||		    !config_found(dev, (void *)&ra, mbprint))			panic(sp);	}	/*	 * Configure the rest of the devices, in PROM order.  Skip	 * PROM entries that are not for devices, or which must be	 * done before we get here.	 */	for (node = node0; node; node = nextsibling(node)) {		cp = getpropstring(node, "name");		for (ssp = special; (sp = *ssp) != NULL; ssp++)			if (strcmp(cp, sp) == 0)				break;		if (sp == NULL && romprop(&ra, cp, node)) {#ifdef L1A_HACK			if (strcmp(cp, "audio") == 0)				audio = 1;			if (strcmp(cp, "zs") == 0)				nzs++;			if (audio && nzs >= 2)				(void) splx(11 << 8);	/* XXX */#endif			(void) config_found(dev, (void *)&ra, mbprint);		}	}}struct cfdriver mainbuscd =    { NULL, "mainbus", matchbyname, mainbus_attach,      DV_DULL, sizeof(struct device) };/* * findzs() is called from the zs driver (which is, at least in theory, * generic to any machine with a Zilog ZSCC chip).  It should return the * address of the corresponding zs channel.  It may not fail, and it * may be called before the VM code can be used.  Here we count on the * FORTH PROM to map in the required zs chips. */void *findzs(zs)	int zs;{	register int node, addr;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -