1 %union { 2 char *str; 3 int val; 4 struct file_list *file; 5 } 6 7 %token ANY 8 %token ARCH 9 %token AT 10 %token BUS 11 %token COMMA 12 %token CONFIG 13 %token CONFLICTS 14 %token CONTROLLER 15 %token CPU 16 %token DEVICE 17 %token DISABLE 18 %token DISK 19 %token DRIVE 20 %token DRQ 21 %token EQUALS 22 %token FLAGS 23 %token IDENT 24 %token IOMEM 25 %token IOSIZ 26 %token IRQ 27 %token MAXUSERS 28 %token MINUS 29 %token NEXUS 30 %token OPTIONS 31 %token MAKEOPTIONS 32 %token PORT 33 %token PSEUDO_DEVICE 34 %token SEMICOLON 35 %token TARGET 36 %token TTY 37 %token UNIT 38 %token VECTOR 39 40 %token <str> ID 41 %token <val> NUMBER 42 %token <val> FPNUMBER 43 44 %type <str> Save_id 45 %type <str> Opt_value 46 %type <str> Dev 47 %type <str> device_name 48 49 %{ 50 51 /* 52 * Copyright (c) 1988, 1993 53 * The Regents of the University of California. All rights reserved. 54 * 55 * Redistribution and use in source and binary forms, with or without 56 * modification, are permitted provided that the following conditions 57 * are met: 58 * 1. Redistributions of source code must retain the above copyright 59 * notice, this list of conditions and the following disclaimer. 60 * 2. Redistributions in binary form must reproduce the above copyright 61 * notice, this list of conditions and the following disclaimer in the 62 * documentation and/or other materials provided with the distribution. 63 * 3. All advertising materials mentioning features or use of this software 64 * must display the following acknowledgement: 65 * This product includes software developed by the University of 66 * California, Berkeley and its contributors. 67 * 4. Neither the name of the University nor the names of its contributors 68 * may be used to endorse or promote products derived from this software 69 * without specific prior written permission. 70 * 71 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 72 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 73 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 74 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 75 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 76 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 77 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 78 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 79 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 80 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 81 * SUCH DAMAGE. 82 * 83 * @(#)config.y 8.1 (Berkeley) 6/6/93 84 * $FreeBSD$ 85 */ 86 87 #include <ctype.h> 88 #include <err.h> 89 #include <stdio.h> 90 #include <string.h> 91 92 #include "config.h" 93 94 static struct device cur; 95 static struct device *curp = 0; 96 97 struct device *dtab; 98 char *ident; 99 int yyline; 100 struct file_list *ftab; 101 char errbuf[80]; 102 int maxusers; 103 104 int seen_scbus; 105 106 #define ns(s) strdup(s) 107 108 static struct device *connect __P((char *, int)); 109 static struct device *huhcon __P((char *)); 110 static void yyerror __P((char *s)); 111 112 113 %} 114 %% 115 Configuration: 116 Many_specs 117 ; 118 119 Many_specs: 120 Many_specs Spec 121 | 122 /* lambda */ 123 ; 124 125 Spec: 126 Device_spec SEMICOLON 127 = { newdev(&cur); } | 128 Config_spec SEMICOLON 129 | 130 SEMICOLON 131 | 132 error SEMICOLON 133 ; 134 135 Config_spec: 136 ARCH Save_id 137 = { 138 if (!strcmp($2, "i386")) { 139 machine = MACHINE_I386; 140 machinename = "i386"; 141 } else if (!strcmp($2, "pc98")) { 142 machine = MACHINE_PC98; 143 machinename = "pc98"; 144 } else if (!strcmp($2, "alpha")) { 145 machine = MACHINE_ALPHA; 146 machinename = "alpha"; 147 } else 148 yyerror("Unknown machine type"); 149 } | 150 CPU Save_id 151 = { 152 struct cputype *cp = 153 (struct cputype *)malloc(sizeof (struct cputype)); 154 memset(cp, 0, sizeof(*cp)); 155 cp->cpu_name = $2; 156 cp->cpu_next = cputype; 157 cputype = cp; 158 } | 159 OPTIONS Opt_list 160 | 161 MAKEOPTIONS Mkopt_list 162 | 163 IDENT ID 164 = { ident = $2; } | 165 System_spec 166 | 167 MAXUSERS NUMBER 168 = { maxusers = $2; }; 169 170 System_spec: 171 CONFIG System_id System_parameter_list 172 = { warnx("line %d: root/dump/swap specifications obsolete", yyline);} 173 | 174 CONFIG System_id 175 ; 176 177 System_id: 178 Save_id 179 = { 180 struct opt *op = (struct opt *)malloc(sizeof (struct opt)); 181 memset(op, 0, sizeof(*op)); 182 op->op_name = ns("KERNEL"); 183 op->op_ownfile = 0; 184 op->op_next = mkopt; 185 op->op_value = $1; 186 op->op_line = yyline + 1; 187 mkopt = op; 188 }; 189 190 System_parameter_list: 191 System_parameter_list ID 192 | ID 193 ; 194 195 device_name: 196 Save_id 197 = { $$ = $1; } 198 | Save_id NUMBER 199 = { 200 char buf[80]; 201 202 (void) snprintf(buf, sizeof(buf), "%s%d", $1, $2); 203 $$ = ns(buf); free($1); 204 } 205 | Save_id NUMBER ID 206 = { 207 char buf[80]; 208 209 (void) snprintf(buf, sizeof(buf), "%s%d%s", $1, $2, $3); 210 $$ = ns(buf); free($1); 211 } 212 | Save_id NUMBER ID NUMBER 213 = { 214 char buf[80]; 215 216 (void) snprintf(buf, sizeof(buf), "%s%d%s%d", 217 $1, $2, $3, $4); 218 $$ = ns(buf); free($1); 219 } 220 | Save_id NUMBER ID NUMBER ID 221 = { 222 char buf[80]; 223 224 (void) snprintf(buf, sizeof(buf), "%s%d%s%d%s", 225 $1, $2, $3, $4, $5); 226 $$ = ns(buf); free($1); 227 } 228 ; 229 230 Opt_list: 231 Opt_list COMMA Option 232 | 233 Option 234 ; 235 236 Option: 237 Save_id 238 = { 239 struct opt *op = (struct opt *)malloc(sizeof (struct opt)); 240 char *s; 241 memset(op, 0, sizeof(*op)); 242 op->op_name = $1; 243 op->op_next = opt; 244 op->op_value = 0; 245 /* 246 * op->op_line is 1-based; yyline is 0-based but is now 1 247 * larger than when `Save_id' was lexed. 248 */ 249 op->op_line = yyline; 250 opt = op; 251 if ((s = strchr(op->op_name, '='))) { 252 warnx("line %d: The `=' in options should not be quoted", yyline); 253 *s = '\0'; 254 op->op_value = ns(s + 1); 255 } 256 } | 257 Save_id EQUALS Opt_value 258 = { 259 struct opt *op = (struct opt *)malloc(sizeof (struct opt)); 260 memset(op, 0, sizeof(*op)); 261 op->op_name = $1; 262 op->op_next = opt; 263 op->op_value = $3; 264 op->op_line = yyline + 1; 265 opt = op; 266 } ; 267 268 Opt_value: 269 ID 270 = { $$ = $1; } | 271 NUMBER 272 = { 273 char buf[80]; 274 275 (void) snprintf(buf, sizeof(buf), "%d", $1); 276 $$ = ns(buf); 277 } ; 278 279 Save_id: 280 ID 281 = { $$ = $1; } 282 ; 283 284 Mkopt_list: 285 Mkopt_list COMMA Mkoption 286 | 287 Mkoption 288 ; 289 290 Mkoption: 291 Save_id EQUALS Opt_value 292 = { 293 struct opt *op = (struct opt *)malloc(sizeof (struct opt)); 294 memset(op, 0, sizeof(*op)); 295 op->op_name = $1; 296 op->op_ownfile = 0; /* for now */ 297 op->op_next = mkopt; 298 op->op_value = $3; 299 op->op_line = yyline + 1; 300 mkopt = op; 301 } ; 302 303 Dev: 304 ID 305 = { $$ = $1; } 306 ; 307 308 Device_spec: 309 DEVICE Dev_name Dev_info 310 = { cur.d_type = DEVICE; } | 311 DISK Dev_name Dev_info 312 = { cur.d_dk = 1; cur.d_type = DEVICE; } | 313 CONTROLLER Dev_name Dev_info 314 = { cur.d_type = CONTROLLER; } | 315 PSEUDO_DEVICE Init_dev Dev 316 = { 317 cur.d_name = $3; 318 cur.d_type = PSEUDO_DEVICE; 319 } | 320 PSEUDO_DEVICE Init_dev Dev NUMBER 321 = { 322 cur.d_name = $3; 323 cur.d_type = PSEUDO_DEVICE; 324 cur.d_count = $4; 325 } ; 326 327 Dev_name: 328 Init_dev Dev NUMBER 329 = { 330 cur.d_name = $2; 331 if (eq($2, "scbus")) 332 seen_scbus = 1; 333 cur.d_unit = $3; 334 }; 335 336 Init_dev: 337 /* lambda */ 338 = { init_dev(&cur); }; 339 340 Dev_info: 341 Con_info Info_list 342 | 343 /* lambda */ 344 ; 345 346 Con_info: 347 AT Dev NUMBER 348 = { 349 if (eq(cur.d_name, "mba") || eq(cur.d_name, "uba")) { 350 (void) snprintf(errbuf, sizeof(errbuf), 351 "%s must be connected to a nexus", cur.d_name); 352 yyerror(errbuf); 353 } 354 cur.d_conn = connect($2, $3); 355 } | 356 AT NEXUS NUMBER 357 = { cur.d_conn = TO_NEXUS; }; 358 359 Info_list: 360 Info_list Info 361 | 362 /* lambda */ 363 ; 364 365 Info: 366 BUS NUMBER /* controller scbus1 at ahc0 bus 1 - twin channel */ 367 = { 368 if (cur.d_conn != 0 && cur.d_conn->d_type == CONTROLLER) 369 cur.d_slave = $2; 370 else 371 yyerror("can't specify a bus to something " 372 "other than a controller"); 373 } | 374 TARGET NUMBER 375 = { cur.d_target = $2; } | 376 UNIT NUMBER 377 = { cur.d_lun = $2; } | 378 DRIVE NUMBER 379 = { cur.d_drive = $2; } | 380 IRQ NUMBER 381 = { cur.d_irq = $2; } | 382 DRQ NUMBER 383 = { cur.d_drq = $2; } | 384 IOMEM NUMBER 385 = { cur.d_maddr = $2; } | 386 IOSIZ NUMBER 387 = { cur.d_msize = $2; } | 388 PORT device_name 389 = { cur.d_port = $2; } | 390 PORT NUMBER 391 = { cur.d_portn = $2; } | 392 FLAGS NUMBER 393 = { cur.d_flags = $2; } | 394 DISABLE 395 = { cur.d_disabled = 1; } | 396 CONFLICTS 397 = { cur.d_conflicts = 1; }; 398 399 %% 400 401 static void 402 yyerror(s) 403 char *s; 404 { 405 406 warnx("line %d: %s", yyline + 1, s); 407 } 408 409 /* 410 * add a device to the list of devices 411 */ 412 static void 413 newdev(dp) 414 register struct device *dp; 415 { 416 register struct device *np, *xp; 417 418 if (dp->d_unit >= 0) { 419 for (xp = dtab; xp != 0; xp = xp->d_next) { 420 if ((xp->d_unit == dp->d_unit) && 421 eq(xp->d_name, dp->d_name)) { 422 warnx("line %d: already seen device %s%d", 423 yyline, xp->d_name, xp->d_unit); 424 } 425 } 426 } 427 np = (struct device *) malloc(sizeof *np); 428 memset(np, 0, sizeof(*np)); 429 *np = *dp; 430 np->d_next = 0; 431 if (curp == 0) 432 dtab = np; 433 else 434 curp->d_next = np; 435 curp = np; 436 } 437 438 439 /* 440 * find the pointer to connect to the given device and number. 441 * returns 0 if no such device and prints an error message 442 */ 443 static struct device * 444 connect(dev, num) 445 register char *dev; 446 register int num; 447 { 448 register struct device *dp; 449 450 if (num == QUES) 451 return (huhcon(dev)); 452 for (dp = dtab; dp != 0; dp = dp->d_next) { 453 if ((num != dp->d_unit) || !eq(dev, dp->d_name)) 454 continue; 455 if (dp->d_type != CONTROLLER) { 456 (void) snprintf(errbuf, sizeof(errbuf), 457 "%s connected to non-controller", dev); 458 yyerror(errbuf); 459 return (0); 460 } 461 return (dp); 462 } 463 (void) snprintf(errbuf, sizeof(errbuf), "%s %d not defined", dev, num); 464 yyerror(errbuf); 465 return (0); 466 } 467 468 /* 469 * connect to an unspecific thing 470 */ 471 static struct device * 472 huhcon(dev) 473 register char *dev; 474 { 475 register struct device *dp, *dcp; 476 struct device rdev; 477 int oldtype; 478 479 /* 480 * First make certain that there are some of these to wildcard on 481 */ 482 for (dp = dtab; dp != 0; dp = dp->d_next) 483 if (eq(dp->d_name, dev)) 484 break; 485 if (dp == 0) { 486 (void) snprintf(errbuf, sizeof(errbuf), "no %s's to wildcard", 487 dev); 488 yyerror(errbuf); 489 return (0); 490 } 491 oldtype = dp->d_type; 492 dcp = dp->d_conn; 493 /* 494 * Now see if there is already a wildcard entry for this device 495 * (e.g. Search for a "uba ?") 496 */ 497 for (; dp != 0; dp = dp->d_next) 498 if (eq(dev, dp->d_name) && dp->d_unit == -1) 499 break; 500 /* 501 * If there isn't, make one because everything needs to be connected 502 * to something. 503 */ 504 if (dp == 0) { 505 dp = &rdev; 506 init_dev(dp); 507 dp->d_unit = QUES; 508 dp->d_name = ns(dev); 509 dp->d_type = oldtype; 510 newdev(dp); 511 dp = curp; 512 /* 513 * Connect it to the same thing that other similar things are 514 * connected to, but make sure it is a wildcard unit 515 * (e.g. up connected to sc ?, here we make connect sc? to a 516 * uba?). If other things like this are on the NEXUS or 517 * if they aren't connected to anything, then make the same 518 * connection, else call ourself to connect to another 519 * unspecific device. 520 */ 521 if (dcp == TO_NEXUS || dcp == 0) 522 dp->d_conn = dcp; 523 else 524 dp->d_conn = connect(dcp->d_name, QUES); 525 } 526 return (dp); 527 } 528 529 void 530 init_dev(dp) 531 register struct device *dp; 532 { 533 534 dp->d_name = "OHNO!!!"; 535 dp->d_type = DEVICE; 536 dp->d_conn = 0; 537 dp->d_conflicts = 0; 538 dp->d_disabled = 0; 539 dp->d_flags = dp->d_dk = 0; 540 dp->d_slave = dp->d_lun = dp->d_target = dp->d_drive = dp->d_unit = \ 541 dp->d_count = UNKNOWN; 542 dp->d_port = (char *)0; 543 dp->d_portn = -1; 544 dp->d_irq = -1; 545 dp->d_drq = -1; 546 dp->d_maddr = 0; 547 dp->d_msize = 0; 548 } 549