xref: /openbsd-src/usr.sbin/config/mkioconf.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: mkioconf.c,v 1.16 2001/02/04 20:42:12 maja Exp $	*/
2 /*	$NetBSD: mkioconf.c,v 1.41 1996/11/11 14:18:49 mycroft Exp $	*/
3 
4 /*
5  * Copyright (c) 1992, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This software was developed by the Computer Systems Engineering group
9  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
10  * contributed to Berkeley.
11  *
12  * All advertising materials mentioning features or use of this software
13  * must display the following acknowledgement:
14  *	This product includes software developed by the University of
15  *	California, Lawrence Berkeley Laboratories.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  * 1. Redistributions of source code must retain the above copyright
21  *    notice, this list of conditions and the following disclaimer.
22  * 2. Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the
24  *    documentation and/or other materials provided with the distribution.
25  * 3. All advertising materials mentioning features or use of this software
26  *    must display the following acknowledgement:
27  *	This product includes software developed by the University of
28  *	California, Berkeley and its contributors.
29  * 4. Neither the name of the University nor the names of its contributors
30  *    may be used to endorse or promote products derived from this software
31  *    without specific prior written permission.
32  *
33  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
34  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
37  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43  * SUCH DAMAGE.
44  *
45  *	from: @(#)mkioconf.c	8.1 (Berkeley) 6/6/93
46  */
47 
48 #include <sys/param.h>
49 #include <errno.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include "config.h"
54 
55 /*
56  * Make ioconf.c.
57  */
58 static int cforder __P((const void *, const void *));
59 static int emitcfdata __P((FILE *));
60 static int emitexterns __P((FILE *));
61 static int emithdr __P((FILE *));
62 static int emitloc __P((FILE *));
63 static int emitlocnames __P((FILE *));
64 static int emitpseudo __P((FILE *));
65 static int emitpv __P((FILE *));
66 static int emitroots __P((FILE *));
67 
68 #define	SEP(pos, max)	(((u_int)(pos) % (max)) == 0 ? "\n\t" : " ")
69 
70 /*
71  * NEWLINE can only be used in the emitXXX functions.
72  * In most cases it can be subsumed into an fprintf.
73  */
74 #define	NEWLINE		if (putc('\n', fp) < 0) return (1)
75 
76 int
77 mkioconf()
78 {
79 	register FILE *fp;
80 	int v;
81 
82 	qsort(packed, npacked, sizeof *packed, cforder);
83 	if ((fp = fopen("ioconf.c", "w")) == NULL) {
84 		(void)fprintf(stderr, "config: cannot write ioconf.c: %s\n",
85 		    strerror(errno));
86 		return (1);
87 	}
88 	v = emithdr(fp);
89 	if (v != 0 || emitexterns(fp) || emitloc(fp) ||
90 	    emitlocnames(fp) || emitpv(fp) || emitcfdata(fp) ||
91 	    emitroots(fp) || emitpseudo(fp)) {
92 		if (v >= 0)
93 			(void)fprintf(stderr,
94 			    "config: error writing ioconf.c: %s\n",
95 			    strerror(errno));
96 		(void)fclose(fp);
97 		/* (void)unlink("ioconf.c"); */
98 		return (1);
99 	}
100 	(void)fclose(fp);
101 	return (0);
102 }
103 
104 static int
105 cforder(a, b)
106 	const void *a, *b;
107 {
108 	register int n1, n2;
109 
110 	n1 = (*(struct devi **)a)->i_cfindex;
111 	n2 = (*(struct devi **)b)->i_cfindex;
112 	return (n1 - n2);
113 }
114 
115 static int
116 emithdr(ofp)
117 	register FILE *ofp;
118 {
119 	register FILE *ifp;
120 	register size_t n;
121 	char ifn[200], buf[BUFSIZ];
122 
123 	if (fprintf(ofp, "\
124 /*\n\
125  * MACHINE GENERATED: DO NOT EDIT\n\
126  *\n\
127  * ioconf.c, from \"%s\"\n\
128  */\n\n", conffile) < 0)
129 		return (1);
130 	(void)sprintf(ifn, "ioconf.incl.%s", machine);
131 	if ((ifp = fopen(ifn, "r")) != NULL) {
132 		while ((n = fread(buf, 1, sizeof(buf), ifp)) > 0)
133 			if (fwrite(buf, 1, n, ofp) != n)
134 				return (1);
135 		if (ferror(ifp)) {
136 			(void)fprintf(stderr, "config: error reading %s: %s\n",
137 			    ifn, strerror(errno));
138 			(void)fclose(ifp);
139 			return (-1);
140 		}
141 		(void)fclose(ifp);
142 	} else {
143 		if (fputs("\
144 #include <sys/param.h>\n\
145 #include <sys/device.h>\n", ofp) < 0)
146 			return (1);
147 	}
148 	return (0);
149 }
150 
151 static int
152 emitexterns(fp)
153 	register FILE *fp;
154 {
155 	register struct devbase *d;
156 	register struct deva *da;
157 
158 	NEWLINE;
159 	for (d = allbases; d != NULL; d = d->d_next) {
160 		if (!devbase_has_instances(d, WILD))
161 			continue;
162 		if (fprintf(fp, "extern struct cfdriver %s_cd;\n",
163 			    d->d_name) < 0)
164 			return (1);
165 	}
166 	NEWLINE;
167 	for (da = alldevas; da != NULL; da = da->d_next) {
168 		if (!deva_has_instances(da, WILD))
169 			continue;
170 		if (fprintf(fp, "extern struct cfattach %s_ca;\n",
171 			    da->d_name) < 0)
172 			return (1);
173 	}
174 	NEWLINE;
175 	return (0);
176 }
177 
178 static int
179 emitloc(fp)
180 	register FILE *fp;
181 {
182 	register int i;
183 
184 	if (fprintf(fp, "\n/* locators */\n\
185 static int loc[%d] = {", locators.used) < 0)
186 		return (1);
187 	for (i = 0; i < locators.used; i++)
188 		if (fprintf(fp, "%s%s,", SEP(i, 8), locators.vec[i]) < 0)
189 			return (1);
190 	if (fprintf(fp, "\n};\n") < 0)
191 		return(1);
192 	return (fprintf(fp, "\n#ifndef MAXEXTRALOC\n\
193 #define MAXEXTRALOC 32\n\
194 #endif\n\
195 int extraloc[MAXEXTRALOC];\n\
196 int nextraloc = MAXEXTRALOC;\n\
197 int uextraloc = 0;\n") < 0);
198 }
199 
200 static int nlocnames, maxlocnames = 8;
201 static char **locnames;
202 
203 short
204 addlocname(name)
205 	char *name;
206 {
207 	int i;
208 
209 	if (locnames == NULL || nlocnames+1 > maxlocnames) {
210 		maxlocnames *= 4;
211 		locnames = (char **)realloc(locnames, maxlocnames * sizeof(char *));
212 	}
213 	for (i = 0; i < nlocnames; i++)
214 		if (strcmp(name, locnames[i]) == 0)
215 			return (i);
216 	/*printf("adding %s at %d\n", name, nlocnames);*/
217 	locnames[nlocnames++] = name;
218 	return (nlocnames - 1);
219 }
220 
221 static int nlocnami, maxlocnami = 8;
222 static short *locnami;
223 
224 void
225 addlocnami(index)
226 	short index;
227 {
228 	if (locnami == NULL || nlocnami+1 > maxlocnami) {
229 		maxlocnami *= 4;
230 		locnami = (short *)realloc(locnami, maxlocnami * sizeof(short));
231 	}
232 	locnami[nlocnami++] = index;
233 }
234 
235 
236 /*
237  * Emit locator names
238  * XXX the locnamp[] table is not compressed like it should be!
239  */
240 static int
241 emitlocnames(fp)
242 	register FILE *fp;
243 {
244 	register struct devi **p, *i;
245 	register struct nvlist *nv;
246 	register struct attr *a;
247 	int added, start;
248 	int v, j, x;
249 
250 #if 1
251 	addlocnami(-1);
252 	for (p = packed; (i = *p) != NULL; p++) {
253 		/*printf("child %s\n", i->i_name);*/
254 
255 		/* initialize all uninitialized parents */
256 		for (x = 0; x < i->i_pvlen; x++) {
257 			if (i->i_parents[x]->i_plocnami)
258 				continue;
259 			start = nlocnami;
260 
261 			/* add all the names */
262 			a = i->i_atattr;
263 			nv = a->a_locs;
264 			added = 0;
265 			for (nv = a->a_locs, v = 0; nv != NULL;
266 			    nv = nv->nv_next, v++) {
267 				addlocnami(addlocname(nv->nv_name));
268 				added = 1;
269 			}
270 			/* terminate list of names */
271 			if (added)
272 				addlocnami(-1);
273 			else
274 				start--;
275 
276 			/*printf("bus %s starts at %d\n", i->i_parents[x]->i_name,
277 			    start);*/
278 			i->i_parents[x]->i_plocnami = start;
279 
280 		}
281 	}
282 	for (p = packed; (i = *p) != NULL; p++)
283 		if (i->i_pvlen)
284 			i->i_locnami = i->i_parents[0]->i_plocnami;
285 #else
286 	addlocnami(-1);
287 	for (p = packed; (i = *p) != NULL; p++) {
288 
289 		i->i_locnami = nlocnami;
290 
291 		/* add all the names */
292 		a = i->i_atattr;
293 		nv = a->a_locs;
294 		for (nv = a->a_locs, v = 0; nv != NULL; nv = nv->nv_next, v++)
295 			addlocnami(addlocname(nv->nv_name));
296 
297 		/* terminate list of names */
298 		addlocnami(-1);
299 
300 	}
301 #endif
302 	if (fprintf(fp, "\nchar *locnames[] = {\n") < 0)
303 		return (1);
304 	for (j = 0; j < nlocnames; j++)
305 		if (fprintf(fp, "\t\"%s\",\n", locnames[j]) < 0)
306 			return (1);
307 	if (fprintf(fp, "};\n\n") < 0)
308 		return (1);
309 
310 	if (fprintf(fp,
311 	    "/* each entry is an index into locnames[]; -1 terminates */\n") < 0)
312 		return (1);
313 	if (fprintf(fp, "short locnamp[] = {") < 0)
314 		return (1);
315 	for (j = 0; j < nlocnami; j++)
316 		if (fprintf(fp, "%s%d,", SEP(j, 8), locnami[j]) < 0)
317 			return (1);
318 	return (fprintf(fp, "\n};\n") < 0);
319 }
320 
321 
322 /*
323  * Emit global parents-vector.
324  */
325 static int
326 emitpv(fp)
327 	register FILE *fp;
328 {
329 	register int i;
330 
331 	if (fprintf(fp, "\n/* size of parent vectors */\n\
332 int pv_size = %d;\n", parents.used) < 0)
333 		return (1);
334 	if (fprintf(fp, "\n/* parent vectors */\n\
335 short pv[%d] = {", parents.used) < 0)
336 		return (1);
337 	for (i = 0; i < parents.used; i++)
338 		if (fprintf(fp, "%s%d,", SEP(i, 16), parents.vec[i]) < 0)
339 			return (1);
340 	return (fprintf(fp, "\n};\n") < 0);
341 }
342 
343 /*
344  * Emit the cfdata array.
345  */
346 static int
347 emitcfdata(fp)
348 	register FILE *fp;
349 {
350 	register struct devi **p, *i, **par;
351 	register int unit, v;
352 	register const char *vs, *state, *basename, *attachment;
353 	register struct nvlist *nv;
354 	register struct attr *a;
355 	char *loc;
356 	char locbuf[20];
357 
358 	if (fprintf(fp, "\n\
359 #define NORM FSTATE_NOTFOUND\n\
360 #define STAR FSTATE_STAR\n\
361 #define DNRM FSTATE_DNOTFOUND\n\
362 #define DSTR FSTATE_DSTAR\n\
363 \n\
364 struct cfdata cfdata[] = {\n\
365     /* attachment       driver        unit  state loc     flags parents nm ivstubs starunit1 */\n") < 0)
366 		return (1);
367 	for (p = packed; (i = *p) != NULL; p++) {
368 		/* the description */
369 		if (fprintf(fp, "/*%3d: %s at ", i->i_cfindex, i->i_name) < 0)
370 			return (1);
371 		par = i->i_parents;
372 		for (v = 0; v < i->i_pvlen; v++)
373 			if (fprintf(fp, "%s%s", v == 0 ? "" : "|",
374 			    i->i_parents[v]->i_name) < 0)
375 				return (1);
376 		if (v == 0 && fputs("root", fp) < 0)
377 			return (1);
378 		a = i->i_atattr;
379 		nv = a->a_locs;
380 		for (nv = a->a_locs, v = 0; nv != NULL; nv = nv->nv_next, v++)
381 			if (fprintf(fp, " %s %s",
382 			    nv->nv_name, i->i_locs[v]) < 0)
383 				return (1);
384 		if (fputs(" */\n", fp) < 0)
385 			return (-1);
386 
387 		/* then the actual defining line */
388 		basename = i->i_base->d_name;
389 		attachment = i->i_atdeva->d_name;
390 		if (i->i_unit == STAR) {
391 			unit = i->i_base->d_umax;
392 			if (i->i_disable) {
393 				state = "DSTR";
394 			} else {
395 				state = "STAR";
396 			}
397 		} else {
398 			unit = i->i_unit;
399 			if (i->i_disable) {
400 				state = "DNRM";
401 			} else {
402 				state = "NORM";
403 			}
404 		}
405 		vs = "";
406 		v = 0;
407 		if (i->i_locoff >= 0) {
408 			(void)sprintf(locbuf, "loc+%3d", i->i_locoff);
409 			loc = locbuf;
410 		} else
411 			loc = "loc";
412 		if (fprintf(fp, "\
413     {&%s_ca,%s&%s_cd,%s%2d, %s, %7s, %#4x, pv+%2d, %d, %s%d, %4d},\n",
414 		    attachment, strlen(attachment) < 6 ? "\t\t" : "\t",
415 		    basename, strlen(basename) < 3 ? "\t\t" : "\t", unit,
416 		    state, loc, i->i_cfflags, i->i_pvoff, i->i_locnami,
417 		    vs, v, unit) < 0)
418 			  return (1);
419 	}
420 	if (fprintf(fp, "    {0},\n    {0},\n    {0},\n    {0},\n") < 0)
421 		return (1);
422 	if (fprintf(fp, "    {0},\n    {0},\n    {0},\n    {0},\n") < 0)
423 		return (1);
424 	return (fputs("    {(struct cfattach *)-1}\n};\n", fp) < 0);
425 }
426 
427 /*
428  * Emit the table of potential roots.
429  */
430 static int
431 emitroots(fp)
432 	register FILE *fp;
433 {
434 	register struct devi **p, *i;
435 	int cnt = 0;
436 
437 	if (fputs("\nshort cfroots[] = {\n", fp) < 0)
438 		return (1);
439 	for (p = packed; (i = *p) != NULL; p++) {
440 		if (i->i_at != NULL)
441 			continue;
442 		if (i->i_unit != 0 &&
443 		    (i->i_unit != STAR || i->i_base->d_umax != 0))
444 			(void)fprintf(stderr,
445 			    "config: warning: `%s at root' is not unit 0\n",
446 			    i->i_name);
447 		if (fprintf(fp, "\t%2d /* %s */,\n",
448 		    i->i_cfindex, i->i_name) < 0)
449 			return (1);
450 		cnt++;
451 	}
452 	if (fputs("\t-1\n};\n", fp) < 0)
453 		return (1);
454 
455 	return(fprintf(fp, "\nint cfroots_size = %d;\n", cnt+1) < 0);
456 }
457 
458 /*
459  * Emit pseudo-device initialization.
460  */
461 static int
462 emitpseudo(fp)
463 	register FILE *fp;
464 {
465 	register struct devi *i;
466 	register struct devbase *d;
467 	int cnt = 0;
468 
469 	if (fputs("\n/* pseudo-devices */\n", fp) < 0)
470 		return (1);
471 	for (i = allpseudo; i != NULL; i = i->i_next)
472 		if (fprintf(fp, "extern void %sattach __P((int));\n",
473 		    i->i_base->d_name) < 0)
474 			return (1);
475 	if (fputs("\nchar *pdevnames[] = {\n", fp) < 0)
476 		return (1);
477 	for (i = allpseudo; i != NULL; i = i->i_next) {
478 		d = i->i_base;
479 		if (fprintf(fp, "\t\"%s\",\n", d->d_name) < 0)
480 			return (1);
481 		cnt++;
482 	}
483 	if (fputs("};\n", fp) < 0)
484 		return (1);
485 	if (fprintf(fp, "\nint pdevnames_size = %d;\n", cnt) < 0)
486 		return (1);
487 	if (fputs("\nstruct pdevinit pdevinit[] = {\n", fp) < 0)
488 		return (1);
489 	for (i = allpseudo; i != NULL; i = i->i_next) {
490 		d = i->i_base;
491 		if (fprintf(fp, "\t{ %sattach, %d },\n",
492 		    d->d_name, d->d_umax) < 0)
493 			return (1);
494 	}
495 	return (fputs("\t{ 0, 0 }\n};\n", fp) < 0);
496 }
497