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