1 /* $OpenBSD: mkioconf.c,v 1.31 2011/10/02 22:20:50 edd 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 46 #include <errno.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 51 #include "config.h" 52 53 /* 54 * Make ioconf.c. 55 */ 56 static int cforder(const void *, const void *); 57 static int emitcfdata(FILE *); 58 static int emitexterns(FILE *); 59 static int emithdr(FILE *); 60 static int emitloc(FILE *); 61 static int emitlocnames(FILE *); 62 static int emitpseudo(FILE *); 63 static int emitpv(FILE *); 64 static int emitroots(FILE *); 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 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 103 cforder(const void *a, const void *b) 104 { 105 int n1, n2; 106 107 n1 = (*(struct devi **)a)->i_cfindex; 108 n2 = (*(struct devi **)b)->i_cfindex; 109 return (n1 - n2); 110 } 111 112 static int 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 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 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 char **locnames; 196 197 short 198 addlocname(const char *name) 199 { 200 int i; 201 202 if (locnames == NULL || nlocnames+1 > maxlocnames) { 203 maxlocnames *= 4; 204 locnames = (char **)erealloc(locnames, maxlocnames * sizeof(char *)); 205 } 206 for (i = 0; i < nlocnames; i++) 207 if (strcmp(name, locnames[i]) == 0) 208 return (i); 209 /*printf("adding %s at %d\n", name, nlocnames);*/ 210 locnames[nlocnames++] = (char *)name; 211 return (nlocnames - 1); 212 } 213 214 static int nlocnami, maxlocnami = 8; 215 static short *locnami; 216 217 void 218 addlocnami(short index) 219 { 220 if (locnami == NULL || nlocnami+1 > maxlocnami) { 221 maxlocnami *= 4; 222 locnami = (short *)erealloc(locnami, maxlocnami * sizeof(short)); 223 } 224 locnami[nlocnami++] = index; 225 } 226 227 228 /* 229 * Emit locator names 230 * XXX the locnamp[] table is not compressed like it should be! 231 */ 232 static int 233 emitlocnames(FILE *fp) 234 { 235 struct devi **p, *i; 236 struct nvlist *nv; 237 struct attr *a; 238 int added, start; 239 int v, j, x; 240 241 #if 1 242 addlocnami(-1); 243 for (p = packed; (i = *p) != NULL; p++) { 244 /*printf("child %s\n", i->i_name);*/ 245 246 /* initialize all uninitialized parents */ 247 for (x = 0; x < i->i_pvlen; x++) { 248 if (i->i_parents[x]->i_plocnami) 249 continue; 250 start = nlocnami; 251 252 /* add all the names */ 253 a = i->i_atattr; 254 nv = a->a_locs; 255 added = 0; 256 for (nv = a->a_locs, v = 0; nv != NULL; 257 nv = nv->nv_next, v++) { 258 addlocnami(addlocname(nv->nv_name)); 259 added = 1; 260 } 261 /* terminate list of names */ 262 if (added) 263 addlocnami(-1); 264 else 265 start--; 266 267 /*printf("bus %s starts at %d\n", i->i_parents[x]->i_name, 268 start);*/ 269 i->i_parents[x]->i_plocnami = start; 270 271 } 272 } 273 for (p = packed; (i = *p) != NULL; p++) 274 if (i->i_pvlen) 275 i->i_locnami = i->i_parents[0]->i_plocnami; 276 #else 277 addlocnami(-1); 278 for (p = packed; (i = *p) != NULL; p++) { 279 280 i->i_locnami = nlocnami; 281 282 /* add all the names */ 283 a = i->i_atattr; 284 nv = a->a_locs; 285 for (nv = a->a_locs, v = 0; nv != NULL; nv = nv->nv_next, v++) 286 addlocnami(addlocname(nv->nv_name)); 287 288 /* terminate list of names */ 289 addlocnami(-1); 290 291 } 292 #endif 293 if (fprintf(fp, "\nchar *locnames[] = {\n") < 0) 294 return (1); 295 for (j = 0; j < nlocnames; j++) 296 if (fprintf(fp, "\t\"%s\",\n", locnames[j]) < 0) 297 return (1); 298 if (fprintf(fp, "};\n\n") < 0) 299 return (1); 300 301 if (fprintf(fp, 302 "/* each entry is an index into locnames[]; -1 terminates */\n") < 0) 303 return (1); 304 if (fprintf(fp, "short locnamp[] = {") < 0) 305 return (1); 306 for (j = 0; j < nlocnami; j++) 307 if (fprintf(fp, "%s%d,", SEP(j, 8), locnami[j]) < 0) 308 return (1); 309 return (fprintf(fp, "\n};\n") < 0); 310 } 311 312 313 /* 314 * Emit global parents-vector. 315 */ 316 static int 317 emitpv(FILE *fp) 318 { 319 int i; 320 321 if (fprintf(fp, "\n/* size of parent vectors */\n\ 322 int pv_size = %d;\n", parents.used) < 0) 323 return (1); 324 if (fprintf(fp, "\n/* parent vectors */\n\ 325 short pv[%d] = {", parents.used) < 0) 326 return (1); 327 for (i = 0; i < parents.used; i++) 328 if (fprintf(fp, "%s%d,", SEP(i, 16), parents.vec[i]) < 0) 329 return (1); 330 return (fprintf(fp, "\n};\n") < 0); 331 } 332 333 /* 334 * Emit the cfdata array. 335 */ 336 static int 337 emitcfdata(FILE *fp) 338 { 339 struct devi **p, *i; 340 int unit, v; 341 const char *state, *basename, *attachment; 342 struct nvlist *nv; 343 struct attr *a; 344 char *loc; 345 char locbuf[20]; 346 347 if (fprintf(fp, "\n\ 348 #define NORM FSTATE_NOTFOUND\n\ 349 #define STAR FSTATE_STAR\n\ 350 #define DNRM FSTATE_DNOTFOUND\n\ 351 #define DSTR FSTATE_DSTAR\n\ 352 \n\ 353 struct cfdata cfdata[] = {\n\ 354 /* attachment driver unit state loc flags parents nm starunit1 */\n") < 0) 355 return (1); 356 for (p = packed; (i = *p) != NULL; p++) { 357 /* the description */ 358 if (fprintf(fp, "/*%3d: %s at ", i->i_cfindex, i->i_name) < 0) 359 return (1); 360 for (v = 0; v < i->i_pvlen; v++) 361 if (fprintf(fp, "%s%s", v == 0 ? "" : "|", 362 i->i_parents[v]->i_name) < 0) 363 return (1); 364 if (v == 0 && fputs("root", fp) < 0) 365 return (1); 366 a = i->i_atattr; 367 nv = a->a_locs; 368 for (nv = a->a_locs, v = 0; nv != NULL; nv = nv->nv_next, v++) 369 if (fprintf(fp, " %s %s", 370 nv->nv_name, i->i_locs[v]) < 0) 371 return (1); 372 if (fputs(" */\n", fp) < 0) 373 return (-1); 374 375 /* then the actual defining line */ 376 basename = i->i_base->d_name; 377 attachment = i->i_atdeva->d_name; 378 if (i->i_unit == STAR) { 379 unit = i->i_base->d_umax; 380 if (i->i_disable) { 381 state = "DSTR"; 382 } else { 383 state = "STAR"; 384 } 385 } else { 386 unit = i->i_unit; 387 if (i->i_disable) { 388 state = "DNRM"; 389 } else { 390 state = "NORM"; 391 } 392 } 393 if (i->i_locoff >= 0) { 394 (void)snprintf(locbuf, sizeof locbuf, "loc+%3d", 395 i->i_locoff); 396 loc = locbuf; 397 } else 398 loc = "loc"; 399 if (fprintf(fp, "\ 400 {&%s_ca,%s&%s_cd,%s%2d, %s, %7s, %#4x, pv+%2d, %d, %4d},\n", 401 attachment, strlen(attachment) < 6 ? "\t\t" : "\t", 402 basename, strlen(basename) < 3 ? "\t\t" : "\t", unit, 403 state, loc, i->i_cfflags, i->i_pvoff, i->i_locnami, 404 unit) < 0) 405 return (1); 406 } 407 if (fprintf(fp, " {0},\n {0},\n {0},\n {0},\n") < 0) 408 return (1); 409 if (fprintf(fp, " {0},\n {0},\n {0},\n {0},\n") < 0) 410 return (1); 411 return (fputs(" {(struct cfattach *)-1}\n};\n", fp) < 0); 412 } 413 414 /* 415 * Emit the table of potential roots. 416 */ 417 static int 418 emitroots(FILE *fp) 419 { 420 struct devi **p, *i; 421 int cnt = 0; 422 423 if (fputs("\nshort cfroots[] = {\n", fp) < 0) 424 return (1); 425 for (p = packed; (i = *p) != NULL; p++) { 426 if (i->i_at != NULL) 427 continue; 428 if (i->i_unit != 0 && 429 (i->i_unit != STAR || i->i_base->d_umax != 0)) 430 (void)fprintf(stderr, 431 "config: warning: `%s at root' is not unit 0\n", 432 i->i_name); 433 if (fprintf(fp, "\t%2d /* %s */,\n", 434 i->i_cfindex, i->i_name) < 0) 435 return (1); 436 cnt++; 437 } 438 if (fputs("\t-1\n};\n", fp) < 0) 439 return (1); 440 441 return(fprintf(fp, "\nint cfroots_size = %d;\n", cnt+1) < 0); 442 } 443 444 /* 445 * Emit pseudo-device initialization. 446 */ 447 static int 448 emitpseudo(FILE *fp) 449 { 450 struct devi *i; 451 struct devbase *d; 452 int cnt = 0, umax; 453 454 if (fputs("\n/* pseudo-devices */\n", fp) < 0) 455 return (1); 456 for (i = allpseudo; i != NULL; i = i->i_next) 457 if (fprintf(fp, "extern void %sattach(int);\n", 458 i->i_base->d_name) < 0) 459 return (1); 460 if (fputs("\nchar *pdevnames[] = {\n", fp) < 0) 461 return (1); 462 for (i = allpseudo; i != NULL; i = i->i_next) { 463 d = i->i_base; 464 if (fprintf(fp, "\t\"%s\",\n", d->d_name) < 0) 465 return (1); 466 cnt++; 467 } 468 if (fputs("};\n", fp) < 0) 469 return (1); 470 if (fprintf(fp, "\nint pdevnames_size = %d;\n", cnt) < 0) 471 return (1); 472 if (fputs("\nstruct pdevinit pdevinit[] = {\n", fp) < 0) 473 return (1); 474 for (i = allpseudo; i != NULL; i = i->i_next) { 475 d = i->i_base; 476 umax = d->d_umax; 477 if (i->i_disable) 478 umax*=-1; 479 if (fprintf(fp, "\t{ %sattach, %d },\n", 480 d->d_name, umax) < 0) 481 return (1); 482 } 483 return (fputs("\t{ NULL, 0 }\n};\n", fp) < 0); 484 } 485