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