Commit | Line | Data |
---|---|---|
6b5eacd2 | 1 | /* |
62a2aae7 KB |
2 | * Copyright (c) 1992, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
6b5eacd2 CT |
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 | * | |
62a2aae7 | 16 | * @(#)mkioconf.c 8.1 (Berkeley) %G% |
6b5eacd2 CT |
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 | } | |
9cf45c42 | 250 | return (fputs("\t{0}\n};\n", fp) < 0); |
6b5eacd2 CT |
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 | ||
19e0980e | 289 | if (fputs("\n/* pseudo-devices */\n", fp) < 0) |
6b5eacd2 CT |
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; | |
a6ea7586 | 299 | if (fprintf(fp, "\t{ %sattach, %d },\n", |
6b5eacd2 CT |
300 | d->d_name, d->d_umax) < 0) |
301 | return (1); | |
302 | } | |
19e0980e | 303 | return (fputs("\t{ 0, 0 }\n};\n", fp) < 0); |
6b5eacd2 CT |
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 | } |