1*57491Storek /*
2*57491Storek  * Copyright (c) 1992 The Regents of the University of California.
3*57491Storek  * All rights reserved.
4*57491Storek  *
5*57491Storek  * This software was developed by the Computer Systems Engineering group
6*57491Storek  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7*57491Storek  * contributed to Berkeley.
8*57491Storek  *
9*57491Storek  * All advertising materials mentioning features or use of this software
10*57491Storek  * must display the following acknowledgement:
11*57491Storek  *	This product includes software developed by the University of
12*57491Storek  *	California, Lawrence Berkeley Laboratories.
13*57491Storek  *
14*57491Storek  * %sccs.include.redist.c%
15*57491Storek  *
16*57491Storek  *	@(#)mkioconf.c	5.1 (Berkeley) 01/12/93
17*57491Storek  *
18*57491Storek  * from: $Header: mkioconf.c,v 1.2 92/12/08 19:34:31 torek Exp $
19*57491Storek  */
20*57491Storek 
21*57491Storek #include <sys/param.h>
22*57491Storek #include <errno.h>
23*57491Storek #include <stdio.h>
24*57491Storek #include <stdlib.h>
25*57491Storek #include <string.h>
26*57491Storek #include "config.h"
27*57491Storek 
28*57491Storek /*
29*57491Storek  * Make ioconf.c.
30*57491Storek  */
31*57491Storek static int cforder __P((const void *, const void *));
32*57491Storek static int emitcfdata __P((FILE *));
33*57491Storek static int emitexterns __P((FILE *));
34*57491Storek static int emithdr __P((FILE *));
35*57491Storek static int emitloc __P((FILE *));
36*57491Storek static int emitpseudo __P((FILE *));
37*57491Storek static int emitpv __P((FILE *));
38*57491Storek static int emitroots __P((FILE *));
39*57491Storek static int emitvec __P((FILE *));
40*57491Storek static char *vecname __P((char *, const char *, int));
41*57491Storek 
42*57491Storek static const char *s_i386;
43*57491Storek 
44*57491Storek #define	SEP(pos, max)	(((u_int)(pos) % (max)) == 0 ? "\n\t" : " ")
45*57491Storek 
46*57491Storek /*
47*57491Storek  * NEWLINE can only be used in the emitXXX functions.
48*57491Storek  * In most cases it can be subsumed into an fprintf.
49*57491Storek  */
50*57491Storek #define	NEWLINE		if (putc('\n', fp) < 0) return (1)
51*57491Storek 
52*57491Storek int
53*57491Storek mkioconf()
54*57491Storek {
55*57491Storek 	register FILE *fp;
56*57491Storek 	register char *fname;
57*57491Storek 	int v;
58*57491Storek 
59*57491Storek 	s_i386 = intern("i386");
60*57491Storek 
61*57491Storek 	fname = path("ioconf.c");
62*57491Storek 	qsort(packed, npacked, sizeof *packed, cforder);
63*57491Storek 	if ((fp = fopen(fname, "w")) == NULL) {
64*57491Storek 		(void)fprintf(stderr, "config: cannot write %s: %s\n",
65*57491Storek 		    fname, strerror(errno));
66*57491Storek 		return (1);
67*57491Storek 	}
68*57491Storek 	v = emithdr(fp);
69*57491Storek 	if (v != 0 || emitvec(fp) || emitexterns(fp) || emitloc(fp) ||
70*57491Storek 	    emitpv(fp) || emitcfdata(fp) || emitroots(fp) || emitpseudo(fp)) {
71*57491Storek 		if (v >= 0)
72*57491Storek 			(void)fprintf(stderr,
73*57491Storek 			    "config: error writing %s: %s\n",
74*57491Storek 			    fname, strerror(errno));
75*57491Storek 		(void)fclose(fp);
76*57491Storek 		/* (void)unlink(fname); */
77*57491Storek 		free(fname);
78*57491Storek 		return (1);
79*57491Storek 	}
80*57491Storek 	(void)fclose(fp);
81*57491Storek 	free(fname);
82*57491Storek 	return (0);
83*57491Storek }
84*57491Storek 
85*57491Storek static int
86*57491Storek cforder(a, b)
87*57491Storek 	const void *a, *b;
88*57491Storek {
89*57491Storek 	register int n1, n2;
90*57491Storek 
91*57491Storek 	n1 = (*(struct devi **)a)->i_cfindex;
92*57491Storek 	n2 = (*(struct devi **)b)->i_cfindex;
93*57491Storek 	return (n1 - n2);
94*57491Storek }
95*57491Storek 
96*57491Storek static int
97*57491Storek emithdr(ofp)
98*57491Storek 	register FILE *ofp;
99*57491Storek {
100*57491Storek 	register FILE *ifp;
101*57491Storek 	register int n;
102*57491Storek 	char ifn[200], buf[BUFSIZ];
103*57491Storek 
104*57491Storek 	if (fprintf(ofp, "\
105*57491Storek /*\n\
106*57491Storek  * MACHINE GENERATED: DO NOT EDIT\n\
107*57491Storek  *\n\
108*57491Storek  * ioconf.c, from \"%s\"\n\
109*57491Storek  */\n\n", conffile) < 0)
110*57491Storek 		return (1);
111*57491Storek 	(void)sprintf(ifn, "ioconf.incl.%s", machine);
112*57491Storek 	if ((ifp = fopen(ifn, "r")) != NULL) {
113*57491Storek 		while ((n = fread(buf, 1, sizeof(buf), ifp)) > 0)
114*57491Storek 			if (fwrite(buf, 1, n, ofp) != n)
115*57491Storek 				return (1);
116*57491Storek 		if (ferror(ifp)) {
117*57491Storek 			(void)fprintf(stderr, "config: error reading %s: %s\n",
118*57491Storek 			    ifn, strerror(errno));
119*57491Storek 			(void)fclose(ifp);
120*57491Storek 			return (-1);
121*57491Storek 		}
122*57491Storek 		(void)fclose(ifp);
123*57491Storek 	} else {
124*57491Storek 		if (fputs("\
125*57491Storek #include <sys/param.h>\n\
126*57491Storek #include <sys/device.h>\n", ofp) < 0)
127*57491Storek 			return (1);
128*57491Storek 	}
129*57491Storek 	return (0);
130*57491Storek }
131*57491Storek 
132*57491Storek static int
133*57491Storek emitexterns(fp)
134*57491Storek 	register FILE *fp;
135*57491Storek {
136*57491Storek 	register struct devbase *d;
137*57491Storek 
138*57491Storek 	NEWLINE;
139*57491Storek 	for (d = allbases; d != NULL; d = d->d_next) {
140*57491Storek 		if (d->d_ihead == NULL)
141*57491Storek 			continue;
142*57491Storek 		if (fprintf(fp, "extern struct cfdriver %scd;\n",
143*57491Storek 			    d->d_name) < 0)
144*57491Storek 			return (1);
145*57491Storek 	}
146*57491Storek 	NEWLINE;
147*57491Storek 	return (0);
148*57491Storek }
149*57491Storek 
150*57491Storek static int
151*57491Storek emitloc(fp)
152*57491Storek 	register FILE *fp;
153*57491Storek {
154*57491Storek 	register int i;
155*57491Storek 
156*57491Storek 	if (fprintf(fp, "\n/* locators */\n\
157*57491Storek static int loc[%d] = {", locators.used) < 0)
158*57491Storek 		return (1);
159*57491Storek 	for (i = 0; i < locators.used; i++)
160*57491Storek 		if (fprintf(fp, "%s%s,", SEP(i, 8), locators.vec[i]) < 0)
161*57491Storek 			return (1);
162*57491Storek 	return (fprintf(fp, "\n};\n") < 0);
163*57491Storek }
164*57491Storek 
165*57491Storek /*
166*57491Storek  * Emit global parents-vector.
167*57491Storek  */
168*57491Storek static int
169*57491Storek emitpv(fp)
170*57491Storek 	register FILE *fp;
171*57491Storek {
172*57491Storek 	register int i;
173*57491Storek 
174*57491Storek 	if (fprintf(fp, "\n/* parent vectors */\n\
175*57491Storek static short pv[%d] = {", parents.used) < 0)
176*57491Storek 		return (1);
177*57491Storek 	for (i = 0; i < parents.used; i++)
178*57491Storek 		if (fprintf(fp, "%s%d,", SEP(i, 16), parents.vec[i]) < 0)
179*57491Storek 			return (1);
180*57491Storek 	return (fprintf(fp, "\n};\n") < 0);
181*57491Storek }
182*57491Storek 
183*57491Storek /*
184*57491Storek  * Emit the cfdata array.
185*57491Storek  */
186*57491Storek static int
187*57491Storek emitcfdata(fp)
188*57491Storek 	register FILE *fp;
189*57491Storek {
190*57491Storek 	register struct devi **p, *i, **par;
191*57491Storek 	register int unit, v;
192*57491Storek 	register const char *vs, *state, *basename;
193*57491Storek 	register struct nvlist *nv;
194*57491Storek 	register struct attr *a;
195*57491Storek 	char *loc;
196*57491Storek 	char locbuf[20];
197*57491Storek 
198*57491Storek 	if (fprintf(fp, "\n\
199*57491Storek #define NORM FSTATE_NOTFOUND\n\
200*57491Storek #define STAR FSTATE_STAR\n\
201*57491Storek \n\
202*57491Storek struct cfdata cfdata[] = {\n\
203*57491Storek \t/* driver     unit state    loc     flags parents ivstubs */\n") < 0)
204*57491Storek 		return (1);
205*57491Storek 	for (p = packed; (i = *p) != NULL; p++) {
206*57491Storek 		/* the description */
207*57491Storek 		if (fprintf(fp, "/*%3d: %s at ", i->i_cfindex, i->i_name) < 0)
208*57491Storek 			return (1);
209*57491Storek 		par = i->i_parents;
210*57491Storek 		for (v = 0; v < i->i_pvlen; v++)
211*57491Storek 			if (fprintf(fp, "%s%s", v == 0 ? "" : "|",
212*57491Storek 			    i->i_parents[v]->i_name) < 0)
213*57491Storek 				return (1);
214*57491Storek 		if (v == 0 && fputs("root", fp) < 0)
215*57491Storek 			return (1);
216*57491Storek 		a = i->i_atattr;
217*57491Storek 		nv = a->a_locs;
218*57491Storek 		for (nv = a->a_locs, v = 0; nv != NULL; nv = nv->nv_next, v++)
219*57491Storek 			if (fprintf(fp, " %s %s",
220*57491Storek 			    nv->nv_name, i->i_locs[v]) < 0)
221*57491Storek 				return (1);
222*57491Storek 		if (fputs(" */\n", fp) < 0)
223*57491Storek 			return (-1);
224*57491Storek 
225*57491Storek 		/* then the actual defining line */
226*57491Storek 		basename = i->i_base->d_name;
227*57491Storek 		if (i->i_unit == STAR) {
228*57491Storek 			unit = i->i_base->d_umax;
229*57491Storek 			state = "STAR";
230*57491Storek 		} else {
231*57491Storek 			unit = i->i_unit;
232*57491Storek 			state = "NORM";
233*57491Storek 		}
234*57491Storek 		if (i->i_ivoff < 0) {
235*57491Storek 			vs = "";
236*57491Storek 			v = 0;
237*57491Storek 		} else {
238*57491Storek 			vs = "vec+";
239*57491Storek 			v = i->i_ivoff;
240*57491Storek 		}
241*57491Storek 		if (i->i_locoff >= 0) {
242*57491Storek 			(void)sprintf(locbuf, "loc+%3d", i->i_locoff);
243*57491Storek 			loc = locbuf;
244*57491Storek 		} else
245*57491Storek 			loc = "loc";
246*57491Storek 		if (fprintf(fp, "\
247*57491Storek \t{&%scd,%s%2d, %s, %7s, %#6x, pv+%2d, %s%d},\n",
248*57491Storek 		    basename, strlen(basename) < 3 ? "\t\t" : "\t", unit,
249*57491Storek 		    state, loc, i->i_cfflags, i->i_pvoff, vs, v) < 0)
250*57491Storek 			return (1);
251*57491Storek 	}
252*57491Storek 	return (fputs("\t0\n};\n", fp) < 0);
253*57491Storek }
254*57491Storek 
255*57491Storek /*
256*57491Storek  * Emit the table of potential roots.
257*57491Storek  */
258*57491Storek static int
259*57491Storek emitroots(fp)
260*57491Storek 	register FILE *fp;
261*57491Storek {
262*57491Storek 	register struct devi **p, *i;
263*57491Storek 
264*57491Storek 	if (fputs("\nshort cfroots[] = {\n", fp) < 0)
265*57491Storek 		return (1);
266*57491Storek 	for (p = packed; (i = *p) != NULL; p++) {
267*57491Storek 		if (i->i_at != NULL)
268*57491Storek 			continue;
269*57491Storek 		if (i->i_unit != 0 &&
270*57491Storek 		    (i->i_unit != STAR || i->i_base->d_umax != 0))
271*57491Storek 			(void)fprintf(stderr,
272*57491Storek 			    "config: warning: `%s at root' is not unit 0\n",
273*57491Storek 			    i->i_name);
274*57491Storek 		if (fprintf(fp, "\t%2d /* %s */,\n",
275*57491Storek 		    i->i_cfindex, i->i_name) < 0)
276*57491Storek 			return (1);
277*57491Storek 	}
278*57491Storek 	return (fputs("\t-1\n};\n", fp) < 0);
279*57491Storek }
280*57491Storek 
281*57491Storek /*
282*57491Storek  * Emit pseudo-device initialization.
283*57491Storek  */
284*57491Storek static int
285*57491Storek emitpseudo(fp)
286*57491Storek 	register FILE *fp;
287*57491Storek {
288*57491Storek 	register struct devi *i;
289*57491Storek 	register struct devbase *d;
290*57491Storek 
291*57491Storek 	if (fputs("\n#ifdef notyet\n", fp) < 0)
292*57491Storek 		return (1);
293*57491Storek 	for (i = allpseudo; i != NULL; i = i->i_next)
294*57491Storek 		if (fprintf(fp, "extern void %sattach __P((int));\n",
295*57491Storek 		    i->i_base->d_name) < 0)
296*57491Storek 			return (1);
297*57491Storek 	if (fputs("\nstruct pdevinit pdevinit[] = {\n", fp) < 0)
298*57491Storek 		return (1);
299*57491Storek 	for (i = allpseudo; i != NULL; i = i->i_next) {
300*57491Storek 		d = i->i_base;
301*57491Storek 		if (fprintf(fp, "\t{ %sattach, %d }\n",
302*57491Storek 		    d->d_name, d->d_umax) < 0)
303*57491Storek 			return (1);
304*57491Storek 	}
305*57491Storek 	return (fputs("\t{ 0, 0 }\n};\n#endif\n", fp) < 0);
306*57491Storek }
307*57491Storek 
308*57491Storek /*
309*57491Storek  * Emit interrupt vector declarations, and calculate offsets.
310*57491Storek  */
311*57491Storek static int
312*57491Storek emitvec(fp)
313*57491Storek 	register FILE *fp;
314*57491Storek {
315*57491Storek 	register struct nvlist *head, *nv;
316*57491Storek 	register struct devi **p, *i;
317*57491Storek 	register int j, nvec, unit;
318*57491Storek 	char buf[200];
319*57491Storek 
320*57491Storek 	nvec = 0;
321*57491Storek 	for (p = packed; (i = *p) != NULL; p++) {
322*57491Storek 		if ((head = i->i_base->d_vectors) == NULL)
323*57491Storek 			continue;
324*57491Storek 		if ((unit = i->i_unit) == STAR)
325*57491Storek 			panic("emitvec unit==STAR");
326*57491Storek 		if (nvec == 0)
327*57491Storek 			NEWLINE;
328*57491Storek 		for (j = 0, nv = head; nv != NULL; j++, nv = nv->nv_next)
329*57491Storek 			if (fprintf(fp,
330*57491Storek 			    "/* IVEC %s %d */ extern void %s();\n",
331*57491Storek 			    nv->nv_name, unit,
332*57491Storek 			    vecname(buf, nv->nv_name, unit)) < 0)
333*57491Storek 				return (1);
334*57491Storek 		nvec += j + 1;
335*57491Storek 	}
336*57491Storek 	if (nvec == 0)
337*57491Storek 		return (0);
338*57491Storek 	if (fprintf(fp, "\nstatic void (*vec[%d]) __P((void)) = {", nvec) < 0)
339*57491Storek 		return (1);
340*57491Storek 	nvec = 0;
341*57491Storek 	for (p = packed; (i = *p) != NULL; p++) {
342*57491Storek 		if ((head = i->i_base->d_vectors) == NULL)
343*57491Storek 			continue;
344*57491Storek 		i->i_ivoff = nvec;
345*57491Storek 		unit = i->i_unit;
346*57491Storek 		for (nv = head; nv != NULL; nv = nv->nv_next)
347*57491Storek 			if (fprintf(fp, "%s%s,",
348*57491Storek 			    SEP(nvec++, 4),
349*57491Storek 			    vecname(buf, nv->nv_name, unit)) < 0)
350*57491Storek 				return (1);
351*57491Storek 		if (fprintf(fp, "%s0,", SEP(nvec++, 4)) < 0)
352*57491Storek 			return (1);
353*57491Storek 	}
354*57491Storek 	return (fputs("\n};\n", fp) < 0);
355*57491Storek }
356*57491Storek 
357*57491Storek static char *
358*57491Storek vecname(buf, name, unit)
359*57491Storek 	char *buf;
360*57491Storek 	const char *name;
361*57491Storek 	int unit;
362*57491Storek {
363*57491Storek 
364*57491Storek 	/* @#%* 386 uses a different name format */
365*57491Storek 	if (machine == s_i386) {
366*57491Storek 		(void)sprintf(buf, "V%s%d", name, unit);
367*57491Storek 		return (buf);
368*57491Storek 	}
369*57491Storek 	(void)sprintf(buf, "X%s%d", name, unit);
370*57491Storek 	return (buf);
371*57491Storek }
372