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