157491Storek /*
2*61818Sbostic  * Copyright (c) 1992, 1993
3*61818Sbostic  *	The Regents of the University of California.  All rights reserved.
457491Storek  *
557491Storek  * This software was developed by the Computer Systems Engineering group
657491Storek  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
757491Storek  * contributed to Berkeley.
857491Storek  *
957491Storek  * All advertising materials mentioning features or use of this software
1057491Storek  * must display the following acknowledgement:
1157491Storek  *	This product includes software developed by the University of
1257491Storek  *	California, Lawrence Berkeley Laboratories.
1357491Storek  *
1457491Storek  * %sccs.include.redist.c%
1557491Storek  *
16*61818Sbostic  *	@(#)mkioconf.c	8.1 (Berkeley) 06/06/93
1757491Storek  */
1857491Storek 
1957491Storek #include <sys/param.h>
2057491Storek #include <errno.h>
2157491Storek #include <stdio.h>
2257491Storek #include <stdlib.h>
2357491Storek #include <string.h>
2457491Storek #include "config.h"
2557491Storek 
2657491Storek /*
2757491Storek  * Make ioconf.c.
2857491Storek  */
2957491Storek static int cforder __P((const void *, const void *));
3057491Storek static int emitcfdata __P((FILE *));
3157491Storek static int emitexterns __P((FILE *));
3257491Storek static int emithdr __P((FILE *));
3357491Storek static int emitloc __P((FILE *));
3457491Storek static int emitpseudo __P((FILE *));
3557491Storek static int emitpv __P((FILE *));
3657491Storek static int emitroots __P((FILE *));
3757491Storek static int emitvec __P((FILE *));
3857491Storek static char *vecname __P((char *, const char *, int));
3957491Storek 
4057491Storek static const char *s_i386;
4157491Storek 
4257491Storek #define	SEP(pos, max)	(((u_int)(pos) % (max)) == 0 ? "\n\t" : " ")
4357491Storek 
4457491Storek /*
4557491Storek  * NEWLINE can only be used in the emitXXX functions.
4657491Storek  * In most cases it can be subsumed into an fprintf.
4757491Storek  */
4857491Storek #define	NEWLINE		if (putc('\n', fp) < 0) return (1)
4957491Storek 
5057491Storek int
mkioconf()5157491Storek mkioconf()
5257491Storek {
5357491Storek 	register FILE *fp;
5457491Storek 	register char *fname;
5557491Storek 	int v;
5657491Storek 
5757491Storek 	s_i386 = intern("i386");
5857491Storek 
5957491Storek 	fname = path("ioconf.c");
6057491Storek 	qsort(packed, npacked, sizeof *packed, cforder);
6157491Storek 	if ((fp = fopen(fname, "w")) == NULL) {
6257491Storek 		(void)fprintf(stderr, "config: cannot write %s: %s\n",
6357491Storek 		    fname, strerror(errno));
6457491Storek 		return (1);
6557491Storek 	}
6657491Storek 	v = emithdr(fp);
6757491Storek 	if (v != 0 || emitvec(fp) || emitexterns(fp) || emitloc(fp) ||
6857491Storek 	    emitpv(fp) || emitcfdata(fp) || emitroots(fp) || emitpseudo(fp)) {
6957491Storek 		if (v >= 0)
7057491Storek 			(void)fprintf(stderr,
7157491Storek 			    "config: error writing %s: %s\n",
7257491Storek 			    fname, strerror(errno));
7357491Storek 		(void)fclose(fp);
7457491Storek 		/* (void)unlink(fname); */
7557491Storek 		free(fname);
7657491Storek 		return (1);
7757491Storek 	}
7857491Storek 	(void)fclose(fp);
7957491Storek 	free(fname);
8057491Storek 	return (0);
8157491Storek }
8257491Storek 
8357491Storek static int
cforder(a,b)8457491Storek cforder(a, b)
8557491Storek 	const void *a, *b;
8657491Storek {
8757491Storek 	register int n1, n2;
8857491Storek 
8957491Storek 	n1 = (*(struct devi **)a)->i_cfindex;
9057491Storek 	n2 = (*(struct devi **)b)->i_cfindex;
9157491Storek 	return (n1 - n2);
9257491Storek }
9357491Storek 
9457491Storek static int
emithdr(ofp)9557491Storek emithdr(ofp)
9657491Storek 	register FILE *ofp;
9757491Storek {
9857491Storek 	register FILE *ifp;
9957491Storek 	register int n;
10057491Storek 	char ifn[200], buf[BUFSIZ];
10157491Storek 
10257491Storek 	if (fprintf(ofp, "\
10357491Storek /*\n\
10457491Storek  * MACHINE GENERATED: DO NOT EDIT\n\
10557491Storek  *\n\
10657491Storek  * ioconf.c, from \"%s\"\n\
10757491Storek  */\n\n", conffile) < 0)
10857491Storek 		return (1);
10957491Storek 	(void)sprintf(ifn, "ioconf.incl.%s", machine);
11057491Storek 	if ((ifp = fopen(ifn, "r")) != NULL) {
11157491Storek 		while ((n = fread(buf, 1, sizeof(buf), ifp)) > 0)
11257491Storek 			if (fwrite(buf, 1, n, ofp) != n)
11357491Storek 				return (1);
11457491Storek 		if (ferror(ifp)) {
11557491Storek 			(void)fprintf(stderr, "config: error reading %s: %s\n",
11657491Storek 			    ifn, strerror(errno));
11757491Storek 			(void)fclose(ifp);
11857491Storek 			return (-1);
11957491Storek 		}
12057491Storek 		(void)fclose(ifp);
12157491Storek 	} else {
12257491Storek 		if (fputs("\
12357491Storek #include <sys/param.h>\n\
12457491Storek #include <sys/device.h>\n", ofp) < 0)
12557491Storek 			return (1);
12657491Storek 	}
12757491Storek 	return (0);
12857491Storek }
12957491Storek 
13057491Storek static int
emitexterns(fp)13157491Storek emitexterns(fp)
13257491Storek 	register FILE *fp;
13357491Storek {
13457491Storek 	register struct devbase *d;
13557491Storek 
13657491Storek 	NEWLINE;
13757491Storek 	for (d = allbases; d != NULL; d = d->d_next) {
13857491Storek 		if (d->d_ihead == NULL)
13957491Storek 			continue;
14057491Storek 		if (fprintf(fp, "extern struct cfdriver %scd;\n",
14157491Storek 			    d->d_name) < 0)
14257491Storek 			return (1);
14357491Storek 	}
14457491Storek 	NEWLINE;
14557491Storek 	return (0);
14657491Storek }
14757491Storek 
14857491Storek static int
emitloc(fp)14957491Storek emitloc(fp)
15057491Storek 	register FILE *fp;
15157491Storek {
15257491Storek 	register int i;
15357491Storek 
15457491Storek 	if (fprintf(fp, "\n/* locators */\n\
15557491Storek static int loc[%d] = {", locators.used) < 0)
15657491Storek 		return (1);
15757491Storek 	for (i = 0; i < locators.used; i++)
15857491Storek 		if (fprintf(fp, "%s%s,", SEP(i, 8), locators.vec[i]) < 0)
15957491Storek 			return (1);
16057491Storek 	return (fprintf(fp, "\n};\n") < 0);
16157491Storek }
16257491Storek 
16357491Storek /*
16457491Storek  * Emit global parents-vector.
16557491Storek  */
16657491Storek static int
emitpv(fp)16757491Storek emitpv(fp)
16857491Storek 	register FILE *fp;
16957491Storek {
17057491Storek 	register int i;
17157491Storek 
17257491Storek 	if (fprintf(fp, "\n/* parent vectors */\n\
17357491Storek static short pv[%d] = {", parents.used) < 0)
17457491Storek 		return (1);
17557491Storek 	for (i = 0; i < parents.used; i++)
17657491Storek 		if (fprintf(fp, "%s%d,", SEP(i, 16), parents.vec[i]) < 0)
17757491Storek 			return (1);
17857491Storek 	return (fprintf(fp, "\n};\n") < 0);
17957491Storek }
18057491Storek 
18157491Storek /*
18257491Storek  * Emit the cfdata array.
18357491Storek  */
18457491Storek static int
emitcfdata(fp)18557491Storek emitcfdata(fp)
18657491Storek 	register FILE *fp;
18757491Storek {
18857491Storek 	register struct devi **p, *i, **par;
18957491Storek 	register int unit, v;
19057491Storek 	register const char *vs, *state, *basename;
19157491Storek 	register struct nvlist *nv;
19257491Storek 	register struct attr *a;
19357491Storek 	char *loc;
19457491Storek 	char locbuf[20];
19557491Storek 
19657491Storek 	if (fprintf(fp, "\n\
19757491Storek #define NORM FSTATE_NOTFOUND\n\
19857491Storek #define STAR FSTATE_STAR\n\
19957491Storek \n\
20057491Storek struct cfdata cfdata[] = {\n\
20157491Storek \t/* driver     unit state    loc     flags parents ivstubs */\n") < 0)
20257491Storek 		return (1);
20357491Storek 	for (p = packed; (i = *p) != NULL; p++) {
20457491Storek 		/* the description */
20557491Storek 		if (fprintf(fp, "/*%3d: %s at ", i->i_cfindex, i->i_name) < 0)
20657491Storek 			return (1);
20757491Storek 		par = i->i_parents;
20857491Storek 		for (v = 0; v < i->i_pvlen; v++)
20957491Storek 			if (fprintf(fp, "%s%s", v == 0 ? "" : "|",
21057491Storek 			    i->i_parents[v]->i_name) < 0)
21157491Storek 				return (1);
21257491Storek 		if (v == 0 && fputs("root", fp) < 0)
21357491Storek 			return (1);
21457491Storek 		a = i->i_atattr;
21557491Storek 		nv = a->a_locs;
21657491Storek 		for (nv = a->a_locs, v = 0; nv != NULL; nv = nv->nv_next, v++)
21757491Storek 			if (fprintf(fp, " %s %s",
21857491Storek 			    nv->nv_name, i->i_locs[v]) < 0)
21957491Storek 				return (1);
22057491Storek 		if (fputs(" */\n", fp) < 0)
22157491Storek 			return (-1);
22257491Storek 
22357491Storek 		/* then the actual defining line */
22457491Storek 		basename = i->i_base->d_name;
22557491Storek 		if (i->i_unit == STAR) {
22657491Storek 			unit = i->i_base->d_umax;
22757491Storek 			state = "STAR";
22857491Storek 		} else {
22957491Storek 			unit = i->i_unit;
23057491Storek 			state = "NORM";
23157491Storek 		}
23257491Storek 		if (i->i_ivoff < 0) {
23357491Storek 			vs = "";
23457491Storek 			v = 0;
23557491Storek 		} else {
23657491Storek 			vs = "vec+";
23757491Storek 			v = i->i_ivoff;
23857491Storek 		}
23957491Storek 		if (i->i_locoff >= 0) {
24057491Storek 			(void)sprintf(locbuf, "loc+%3d", i->i_locoff);
24157491Storek 			loc = locbuf;
24257491Storek 		} else
24357491Storek 			loc = "loc";
24457491Storek 		if (fprintf(fp, "\
24557491Storek \t{&%scd,%s%2d, %s, %7s, %#6x, pv+%2d, %s%d},\n",
24657491Storek 		    basename, strlen(basename) < 3 ? "\t\t" : "\t", unit,
24757491Storek 		    state, loc, i->i_cfflags, i->i_pvoff, vs, v) < 0)
24857491Storek 			return (1);
24957491Storek 	}
25059881Storek 	return (fputs("\t{0}\n};\n", fp) < 0);
25157491Storek }
25257491Storek 
25357491Storek /*
25457491Storek  * Emit the table of potential roots.
25557491Storek  */
25657491Storek static int
emitroots(fp)25757491Storek emitroots(fp)
25857491Storek 	register FILE *fp;
25957491Storek {
26057491Storek 	register struct devi **p, *i;
26157491Storek 
26257491Storek 	if (fputs("\nshort cfroots[] = {\n", fp) < 0)
26357491Storek 		return (1);
26457491Storek 	for (p = packed; (i = *p) != NULL; p++) {
26557491Storek 		if (i->i_at != NULL)
26657491Storek 			continue;
26757491Storek 		if (i->i_unit != 0 &&
26857491Storek 		    (i->i_unit != STAR || i->i_base->d_umax != 0))
26957491Storek 			(void)fprintf(stderr,
27057491Storek 			    "config: warning: `%s at root' is not unit 0\n",
27157491Storek 			    i->i_name);
27257491Storek 		if (fprintf(fp, "\t%2d /* %s */,\n",
27357491Storek 		    i->i_cfindex, i->i_name) < 0)
27457491Storek 			return (1);
27557491Storek 	}
27657491Storek 	return (fputs("\t-1\n};\n", fp) < 0);
27757491Storek }
27857491Storek 
27957491Storek /*
28057491Storek  * Emit pseudo-device initialization.
28157491Storek  */
28257491Storek static int
emitpseudo(fp)28357491Storek emitpseudo(fp)
28457491Storek 	register FILE *fp;
28557491Storek {
28657491Storek 	register struct devi *i;
28757491Storek 	register struct devbase *d;
28857491Storek 
28959148Storek 	if (fputs("\n/* pseudo-devices */\n", fp) < 0)
29057491Storek 		return (1);
29157491Storek 	for (i = allpseudo; i != NULL; i = i->i_next)
29257491Storek 		if (fprintf(fp, "extern void %sattach __P((int));\n",
29357491Storek 		    i->i_base->d_name) < 0)
29457491Storek 			return (1);
29557491Storek 	if (fputs("\nstruct pdevinit pdevinit[] = {\n", fp) < 0)
29657491Storek 		return (1);
29757491Storek 	for (i = allpseudo; i != NULL; i = i->i_next) {
29857491Storek 		d = i->i_base;
29957563Storek 		if (fprintf(fp, "\t{ %sattach, %d },\n",
30057491Storek 		    d->d_name, d->d_umax) < 0)
30157491Storek 			return (1);
30257491Storek 	}
30359148Storek 	return (fputs("\t{ 0, 0 }\n};\n", fp) < 0);
30457491Storek }
30557491Storek 
30657491Storek /*
30757491Storek  * Emit interrupt vector declarations, and calculate offsets.
30857491Storek  */
30957491Storek static int
emitvec(fp)31057491Storek emitvec(fp)
31157491Storek 	register FILE *fp;
31257491Storek {
31357491Storek 	register struct nvlist *head, *nv;
31457491Storek 	register struct devi **p, *i;
31557491Storek 	register int j, nvec, unit;
31657491Storek 	char buf[200];
31757491Storek 
31857491Storek 	nvec = 0;
31957491Storek 	for (p = packed; (i = *p) != NULL; p++) {
32057491Storek 		if ((head = i->i_base->d_vectors) == NULL)
32157491Storek 			continue;
32257491Storek 		if ((unit = i->i_unit) == STAR)
32357491Storek 			panic("emitvec unit==STAR");
32457491Storek 		if (nvec == 0)
32557491Storek 			NEWLINE;
32657491Storek 		for (j = 0, nv = head; nv != NULL; j++, nv = nv->nv_next)
32757491Storek 			if (fprintf(fp,
32857491Storek 			    "/* IVEC %s %d */ extern void %s();\n",
32957491Storek 			    nv->nv_name, unit,
33057491Storek 			    vecname(buf, nv->nv_name, unit)) < 0)
33157491Storek 				return (1);
33257491Storek 		nvec += j + 1;
33357491Storek 	}
33457491Storek 	if (nvec == 0)
33557491Storek 		return (0);
33657491Storek 	if (fprintf(fp, "\nstatic void (*vec[%d]) __P((void)) = {", nvec) < 0)
33757491Storek 		return (1);
33857491Storek 	nvec = 0;
33957491Storek 	for (p = packed; (i = *p) != NULL; p++) {
34057491Storek 		if ((head = i->i_base->d_vectors) == NULL)
34157491Storek 			continue;
34257491Storek 		i->i_ivoff = nvec;
34357491Storek 		unit = i->i_unit;
34457491Storek 		for (nv = head; nv != NULL; nv = nv->nv_next)
34557491Storek 			if (fprintf(fp, "%s%s,",
34657491Storek 			    SEP(nvec++, 4),
34757491Storek 			    vecname(buf, nv->nv_name, unit)) < 0)
34857491Storek 				return (1);
34957491Storek 		if (fprintf(fp, "%s0,", SEP(nvec++, 4)) < 0)
35057491Storek 			return (1);
35157491Storek 	}
35257491Storek 	return (fputs("\n};\n", fp) < 0);
35357491Storek }
35457491Storek 
35557491Storek static char *
vecname(buf,name,unit)35657491Storek vecname(buf, name, unit)
35757491Storek 	char *buf;
35857491Storek 	const char *name;
35957491Storek 	int unit;
36057491Storek {
36157491Storek 
36257491Storek 	/* @#%* 386 uses a different name format */
36357491Storek 	if (machine == s_i386) {
36457491Storek 		(void)sprintf(buf, "V%s%d", name, unit);
36557491Storek 		return (buf);
36657491Storek 	}
36757491Storek 	(void)sprintf(buf, "X%s%d", name, unit);
36857491Storek 	return (buf);
36957491Storek }
370