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