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