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