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