config.y revision 6814
1%union { 2 char *str; 3 int val; 4 struct file_list *file; 5 struct idlst *lst; 6} 7 8%token AND 9%token ANY 10%token ARGS 11%token AT 12%token BIO 13%token COMMA 14%token CONFIG 15%token CONTROLLER 16%token CPU 17%token CSR 18%token DEVICE 19%token DISK 20%token DRIVE 21%token DRQ 22%token DST 23%token DUMPS 24%token EQUALS 25%token FLAGS 26%token HZ 27%token IDENT 28%token INTERLEAVE 29%token IOMEM 30%token IOSIZ 31%token IRQ 32%token MACHINE 33%token MAJOR 34%token MASTER 35%token MAXUSERS 36%token MINOR 37%token MINUS 38%token NET 39%token NEXUS 40%token ON 41%token OPTIONS 42%token MAKEOPTIONS 43%token PORT 44%token PRIORITY 45%token PSEUDO_DEVICE 46%token ROOT 47%token SEMICOLON 48%token SEQUENTIAL 49%token SIZE 50%token SLAVE 51%token SWAP 52%token TARGET 53%token TIMEZONE 54%token TTY 55%token TRACE 56%token UNIT 57%token VECTOR 58 59%token <str> ID 60%token <val> NUMBER 61%token <val> FPNUMBER 62 63%type <str> Save_id 64%type <str> Opt_value 65%type <str> Dev 66%type <lst> Id_list 67%type <val> optional_size 68%type <val> optional_sflag 69%type <str> device_name 70%type <val> major_minor 71%type <val> arg_device_spec 72%type <val> root_device_spec root_device_specs 73%type <val> dump_device_spec 74%type <file> swap_device_spec 75%type <file> comp_device_spec 76 77%{ 78 79/* 80 * Copyright (c) 1988, 1993 81 * The Regents of the University of California. All rights reserved. 82 * 83 * Redistribution and use in source and binary forms, with or without 84 * modification, are permitted provided that the following conditions 85 * are met: 86 * 1. Redistributions of source code must retain the above copyright 87 * notice, this list of conditions and the following disclaimer. 88 * 2. Redistributions in binary form must reproduce the above copyright 89 * notice, this list of conditions and the following disclaimer in the 90 * documentation and/or other materials provided with the distribution. 91 * 3. All advertising materials mentioning features or use of this software 92 * must display the following acknowledgement: 93 * This product includes software developed by the University of 94 * California, Berkeley and its contributors. 95 * 4. Neither the name of the University nor the names of its contributors 96 * may be used to endorse or promote products derived from this software 97 * without specific prior written permission. 98 * 99 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 100 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 101 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 102 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 103 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 104 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 105 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 106 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 107 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 108 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 109 * SUCH DAMAGE. 110 * 111 * @(#)config.y 8.1 (Berkeley) 6/6/93 112 */ 113 114#include "config.h" 115 116#include <sys/disklabel.h> 117#include <sys/diskslice.h> 118 119#include <ctype.h> 120#include <stdio.h> 121#include <err.h> 122 123struct device cur; 124struct device *curp = 0; 125char *temp_id; 126char *val_id; 127 128%} 129%% 130Configuration: 131 Many_specs 132 = { verifysystemspecs(); } 133 ; 134 135Many_specs: 136 Many_specs Spec 137 | 138 /* lambda */ 139 ; 140 141Spec: 142 Device_spec SEMICOLON 143 = { newdev(&cur); } | 144 Config_spec SEMICOLON 145 | 146 TRACE SEMICOLON 147 = { do_trace = !do_trace; } | 148 SEMICOLON 149 | 150 error SEMICOLON 151 ; 152 153Config_spec: 154 MACHINE Save_id 155 = { 156 if (!strcmp($2, "vax")) { 157 machine = MACHINE_VAX; 158 machinename = "vax"; 159 } else if (!strcmp($2, "tahoe")) { 160 machine = MACHINE_TAHOE; 161 machinename = "tahoe"; 162 } else if (!strcmp($2, "hp300")) { 163 machine = MACHINE_HP300; 164 machinename = "hp300"; 165 } else if (!strcmp($2, "i386")) { 166 machine = MACHINE_I386; 167 machinename = "i386"; 168 } else if (!strcmp($2, "mips")) { 169 machine = MACHINE_MIPS; 170 machinename = "mips"; 171 } else if (!strcmp($2, "pmax")) { 172 machine = MACHINE_PMAX; 173 machinename = "pmax"; 174 } else if (!strcmp($2, "luna68k")) { 175 machine = MACHINE_LUNA68K; 176 machinename = "luna68k"; 177 } else if (!strcmp($2, "news3400")) { 178 machine = MACHINE_NEWS3400; 179 machinename = "news3400"; 180 } else 181 yyerror("Unknown machine type"); 182 } | 183 CPU Save_id 184 = { 185 struct cputype *cp = 186 (struct cputype *)malloc(sizeof (struct cputype)); 187 cp->cpu_name = ns($2); 188 cp->cpu_next = cputype; 189 cputype = cp; 190 free(temp_id); 191 } | 192 OPTIONS Opt_list 193 | 194 MAKEOPTIONS Mkopt_list 195 | 196 IDENT ID 197 = { ident = ns($2); } | 198 System_spec 199 | 200 HZ NUMBER 201 = { yyerror("HZ specification obsolete; delete"); } | 202 TIMEZONE NUMBER 203 = { zone = 60 * $2; check_tz(); } | 204 TIMEZONE NUMBER DST NUMBER 205 = { zone = 60 * $2; dst = $4; check_tz(); } | 206 TIMEZONE NUMBER DST 207 = { zone = 60 * $2; dst = 1; check_tz(); } | 208 TIMEZONE FPNUMBER 209 = { zone = $2; check_tz(); } | 210 TIMEZONE FPNUMBER DST NUMBER 211 = { zone = $2; dst = $4; check_tz(); } | 212 TIMEZONE FPNUMBER DST 213 = { zone = $2; dst = 1; check_tz(); } | 214 TIMEZONE MINUS NUMBER 215 = { zone = -60 * $3; check_tz(); } | 216 TIMEZONE MINUS NUMBER DST NUMBER 217 = { zone = -60 * $3; dst = $5; check_tz(); } | 218 TIMEZONE MINUS NUMBER DST 219 = { zone = -60 * $3; dst = 1; check_tz(); } | 220 TIMEZONE MINUS FPNUMBER 221 = { zone = -$3; check_tz(); } | 222 TIMEZONE MINUS FPNUMBER DST NUMBER 223 = { zone = -$3; dst = $5; check_tz(); } | 224 TIMEZONE MINUS FPNUMBER DST 225 = { zone = -$3; dst = 1; check_tz(); } | 226 MAXUSERS NUMBER 227 = { maxusers = $2; }; 228 229System_spec: 230 System_id System_parameter_list 231 = { checksystemspec(*confp); } 232 ; 233 234System_id: 235 CONFIG Save_id 236 = { mkconf($2); } 237 ; 238 239System_parameter_list: 240 System_parameter_list System_parameter 241 | System_parameter 242 ; 243 244System_parameter: 245 addr_spec 246 | swap_spec 247 | root_spec 248 | dump_spec 249 | arg_spec 250 ; 251 252addr_spec: 253 AT NUMBER 254 = { loadaddress = $2; } 255 ; 256 257swap_spec: 258 SWAP optional_on swap_device_list 259 ; 260 261swap_device_list: 262 swap_device_list AND swap_device 263 | swap_device 264 ; 265 266swap_device: 267 swap_device_spec optional_size optional_sflag 268 = { mkswap(*confp, $1, $2, $3); } 269 ; 270 271swap_device_spec: 272 device_name 273 = { 274 struct file_list *fl = newflist(SWAPSPEC); 275 276 if (eq($1, "generic")) 277 fl->f_fn = $1; 278 else { 279 fl->f_swapdev = nametodev($1, 0, 280 COMPATIBILITY_SLICE, 'b'); 281 fl->f_fn = devtoname(fl->f_swapdev); 282 } 283 $$ = fl; 284 } 285 | major_minor 286 = { 287 struct file_list *fl = newflist(SWAPSPEC); 288 289 fl->f_swapdev = $1; 290 fl->f_fn = devtoname($1); 291 $$ = fl; 292 } 293 ; 294 295root_spec: 296 ROOT optional_on root_device_specs 297 = { 298 struct file_list *fl = *confp; 299 300 if (fl && fl->f_rootdev != NODEV) 301 yyerror("extraneous root device specification"); 302 else 303 fl->f_rootdev = $3; 304 } 305 ; 306 307root_device_specs: 308 root_device_spec AND root_device_specs 309 = { 310 warnx("extraneous root devices ignored"); 311 $$ = $1; 312 } 313 | root_device_spec 314 ; 315 316root_device_spec: 317 device_name 318 = { $$ = nametodev($1, 0, COMPATIBILITY_SLICE, 'a'); } 319 | major_minor 320 ; 321 322dump_spec: 323 DUMPS optional_on dump_device_spec 324 = { 325 struct file_list *fl = *confp; 326 327 if (fl && fl->f_dumpdev != NODEV) 328 yyerror("extraneous dump device specification"); 329 else 330 fl->f_dumpdev = $3; 331 } 332 333 ; 334 335dump_device_spec: 336 device_name 337 = { $$ = nametodev($1, 0, COMPATIBILITY_SLICE, 'b'); } 338 | major_minor 339 ; 340 341arg_spec: 342 ARGS optional_on arg_device_spec 343 = { yyerror("arg device specification obsolete, ignored"); } 344 ; 345 346arg_device_spec: 347 device_name 348 = { $$ = nametodev($1, 0, COMPATIBILITY_SLICE, 'b'); } 349 | major_minor 350 ; 351 352major_minor: 353 MAJOR NUMBER MINOR NUMBER 354 = { $$ = makedev($2, $4); } 355 ; 356 357optional_on: 358 ON 359 | /* empty */ 360 ; 361 362optional_size: 363 SIZE NUMBER 364 = { $$ = $2; } 365 | /* empty */ 366 = { $$ = 0; } 367 ; 368 369optional_sflag: 370 SEQUENTIAL 371 = { $$ = 2; } 372 | /* empty */ 373 = { $$ = 0; } 374 ; 375 376device_name: 377 Save_id 378 = { $$ = $1; } 379 | Save_id NUMBER 380 = { 381 char buf[80]; 382 383 (void) sprintf(buf, "%s%d", $1, $2); 384 $$ = ns(buf); free($1); 385 } 386 | Save_id NUMBER ID 387 = { 388 char buf[80]; 389 390 (void) sprintf(buf, "%s%d%s", $1, $2, $3); 391 $$ = ns(buf); free($1); 392 } 393 | Save_id NUMBER ID NUMBER 394 = { 395 char buf[80]; 396 397 (void) sprintf(buf, "%s%d%s%d", $1, $2, $3, $4); 398 $$ = ns(buf); free($1); 399 } 400 | Save_id NUMBER ID NUMBER ID 401 = { 402 char buf[80]; 403 404 (void) sprintf(buf, "%s%d%s%d%s", $1, $2, $3, $4, $5); 405 $$ = ns(buf); free($1); 406 } 407 ; 408 409Opt_list: 410 Opt_list COMMA Option 411 | 412 Option 413 ; 414 415Option: 416 Save_id 417 = { 418 struct opt *op = (struct opt *)malloc(sizeof (struct opt)); 419 op->op_name = ns($1); 420 op->op_next = opt; 421 op->op_value = 0; 422 opt = op; 423 free(temp_id); 424 } | 425 Save_id EQUALS Opt_value 426 = { 427 struct opt *op = (struct opt *)malloc(sizeof (struct opt)); 428 op->op_name = ns($1); 429 op->op_next = opt; 430 op->op_value = ns($3); 431 opt = op; 432 free(temp_id); 433 free(val_id); 434 } ; 435 436Opt_value: 437 ID 438 = { $$ = val_id = ns($1); } | 439 NUMBER 440 = { 441 char nb[16]; 442 (void) sprintf(nb, "%d", $1); 443 $$ = val_id = ns(nb); 444 } ; 445 446 447Save_id: 448 ID 449 = { $$ = temp_id = ns($1); } 450 ; 451 452Mkopt_list: 453 Mkopt_list COMMA Mkoption 454 | 455 Mkoption 456 ; 457 458Mkoption: 459 Save_id EQUALS Opt_value 460 = { 461 struct opt *op = (struct opt *)malloc(sizeof (struct opt)); 462 op->op_name = ns($1); 463 op->op_next = mkopt; 464 op->op_value = ns($3); 465 mkopt = op; 466 free(temp_id); 467 free(val_id); 468 } ; 469 470Dev: 471 ID 472 = { $$ = ns($1); } 473 ; 474 475Device_spec: 476 DEVICE Dev_name Dev_info Int_spec 477 = { cur.d_type = DEVICE; } | 478 MASTER Dev_name Dev_info Int_spec 479 = { cur.d_type = MASTER; } | 480 DISK Dev_name Dev_info Int_spec 481 = { cur.d_dk = 1; cur.d_type = DEVICE; } | 482 CONTROLLER Dev_name Dev_info Int_spec 483 = { cur.d_type = CONTROLLER; } | 484 PSEUDO_DEVICE Init_dev Dev 485 = { 486 cur.d_name = $3; 487 cur.d_type = PSEUDO_DEVICE; 488 } | 489 PSEUDO_DEVICE Init_dev Dev NUMBER 490 = { 491 cur.d_name = $3; 492 cur.d_type = PSEUDO_DEVICE; 493 cur.d_slave = $4; 494 } | 495 PSEUDO_DEVICE Dev_name Cdev_init Cdev_info 496 = { 497 if (!eq(cur.d_name, "cd")) 498 yyerror("improper spec for pseudo-device"); 499 seen_cd = 1; 500 cur.d_type = DEVICE; 501 verifycomp(*compp); 502 }; 503 504Cdev_init: 505 /* lambda */ 506 = { mkcomp(&cur); }; 507 508Cdev_info: 509 optional_on comp_device_list comp_option_list 510 ; 511 512comp_device_list: 513 comp_device_list AND comp_device 514 | comp_device 515 ; 516 517comp_device: 518 comp_device_spec 519 = { addcomp(*compp, $1); } 520 ; 521 522comp_device_spec: 523 device_name 524 = { 525 struct file_list *fl = newflist(COMPSPEC); 526 527 fl->f_compdev = nametodev($1, 0, COMPATIBILITY_SLICE, 528 'c'); 529 fl->f_fn = devtoname(fl->f_compdev); 530 $$ = fl; 531 } 532 | major_minor 533 = { 534 struct file_list *fl = newflist(COMPSPEC); 535 536 fl->f_compdev = $1; 537 fl->f_fn = devtoname($1); 538 $$ = fl; 539 } 540 ; 541 542comp_option_list: 543 comp_option_list comp_option 544 | 545 /* lambda */ 546 ; 547 548comp_option: 549 INTERLEAVE NUMBER 550 = { cur.d_pri = $2; } | 551 FLAGS NUMBER 552 = { cur.d_flags = $2; }; 553 554Dev_name: 555 Init_dev Dev NUMBER 556 = { 557 cur.d_name = $2; 558 if (eq($2, "mba")) 559 seen_mba = 1; 560 else if (eq($2, "uba")) 561 seen_uba = 1; 562 else if (eq($2, "vba")) 563 seen_vba = 1; 564 else if (eq($2, "isa")) 565 seen_isa = 1; 566 else if (eq($2, "scbus")) 567 seen_scbus = 1; 568 cur.d_unit = $3; 569 }; 570 571Init_dev: 572 /* lambda */ 573 = { init_dev(&cur); }; 574 575Dev_info: 576 Con_info Info_list 577 | 578 /* lambda */ 579 ; 580 581Con_info: 582 AT Dev NUMBER 583 = { 584 if (eq(cur.d_name, "mba") || eq(cur.d_name, "uba")) { 585 (void) sprintf(errbuf, 586 "%s must be connected to a nexus", cur.d_name); 587 yyerror(errbuf); 588 } 589 cur.d_conn = connect($2, $3); 590 } | 591 AT NEXUS NUMBER 592 = { check_nexus(&cur, $3); cur.d_conn = TO_NEXUS; }; 593 594Info_list: 595 Info_list Info 596 | 597 /* lambda */ 598 ; 599 600Info: 601 CSR NUMBER 602 = { cur.d_addr = $2; } | 603 TARGET NUMBER 604 = { cur.d_target = $2; } | 605 UNIT NUMBER 606 = { cur.d_lun = $2; } | 607 DRIVE NUMBER 608 = { cur.d_drive = $2; } | 609 SLAVE NUMBER 610 = { 611 if (cur.d_conn != 0 && cur.d_conn != TO_NEXUS && 612 cur.d_conn->d_type == MASTER) 613 cur.d_slave = $2; 614 else 615 yyerror("can't specify slave--not to master"); 616 } | 617 IRQ NUMBER 618 = { cur.d_irq = $2; } | 619 DRQ NUMBER 620 = { cur.d_drq = $2; } | 621 IOMEM NUMBER 622 = { cur.d_maddr = $2; } | 623 IOSIZ NUMBER 624 = { cur.d_msize = $2; } | 625 PORT device_name 626 = { cur.d_port = ns($2); } | 627 PORT NUMBER 628 = { cur.d_portn = $2; } | 629 TTY 630 = { cur.d_mask = "tty"; } | 631 BIO 632 = { cur.d_mask = "bio"; } | 633 NET 634 = { cur.d_mask = "net"; } | 635 FLAGS NUMBER 636 = { cur.d_flags = $2; }; 637 638Int_spec: 639 VECTOR Id_list 640 = { cur.d_vec = $2; } | 641 PRIORITY NUMBER 642 = { cur.d_pri = $2; } | 643 /* lambda */ 644 ; 645 646Id_list: 647 Save_id 648 = { 649 struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst)); 650 a->id = $1; a->id_next = 0; $$ = a; 651 } | 652 Save_id Id_list = 653 { 654 struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst)); 655 a->id = $1; a->id_next = $2; $$ = a; 656 }; 657 658%% 659 660yyerror(s) 661 char *s; 662{ 663 664 fprintf(stderr, "config: line %d: %s\n", yyline + 1, s); 665} 666 667/* 668 * return the passed string in a new space 669 */ 670char * 671ns(str) 672 register char *str; 673{ 674 register char *cp; 675 676 cp = malloc((unsigned)(strlen(str)+1)); 677 (void) strcpy(cp, str); 678 return (cp); 679} 680 681/* 682 * add a device to the list of devices 683 */ 684newdev(dp) 685 register struct device *dp; 686{ 687 register struct device *np; 688 689 np = (struct device *) malloc(sizeof *np); 690 *np = *dp; 691 np->d_next = 0; 692 if (curp == 0) 693 dtab = np; 694 else 695 curp->d_next = np; 696 curp = np; 697} 698 699/* 700 * note that a configuration should be made 701 */ 702mkconf(sysname) 703 char *sysname; 704{ 705 register struct file_list *fl, **flp; 706 707 fl = (struct file_list *) malloc(sizeof *fl); 708 fl->f_type = SYSTEMSPEC; 709 fl->f_needs = sysname; 710 fl->f_rootdev = NODEV; 711 fl->f_dumpdev = NODEV; 712 fl->f_fn = 0; 713 fl->f_next = 0; 714 for (flp = confp; *flp; flp = &(*flp)->f_next) 715 ; 716 *flp = fl; 717 confp = flp; 718} 719 720struct file_list * 721newflist(ftype) 722 u_char ftype; 723{ 724 struct file_list *fl = (struct file_list *)malloc(sizeof (*fl)); 725 726 fl->f_type = ftype; 727 fl->f_next = 0; 728 fl->f_swapdev = NODEV; 729 fl->f_swapsize = 0; 730 fl->f_needs = 0; 731 fl->f_fn = 0; 732 return (fl); 733} 734 735/* 736 * Add a swap device to the system's configuration 737 */ 738mkswap(system, fl, size, flag) 739 struct file_list *system, *fl; 740 int size, flag; 741{ 742 register struct file_list **flp; 743 char name[80]; 744 745 if (system == 0 || system->f_type != SYSTEMSPEC) { 746 yyerror("\"swap\" spec precedes \"config\" specification"); 747 return; 748 } 749 if (size < 0) { 750 yyerror("illegal swap partition size"); 751 return; 752 } 753 /* 754 * Append swap description to the end of the list. 755 */ 756 flp = &system->f_next; 757 for (; *flp && (*flp)->f_type == SWAPSPEC; flp = &(*flp)->f_next) 758 ; 759 fl->f_next = *flp; 760 *flp = fl; 761 fl->f_swapsize = size; 762 fl->f_swapflag = flag; 763 /* 764 * If first swap device for this system, 765 * set up f_fn field to insure swap 766 * files are created with unique names. 767 */ 768 if (system->f_fn) 769 return; 770 if (eq(fl->f_fn, "generic")) 771 system->f_fn = ns(fl->f_fn); 772 else 773 system->f_fn = ns(system->f_needs); 774} 775 776mkcomp(dp) 777 register struct device *dp; 778{ 779 register struct file_list *fl, **flp; 780 char buf[80]; 781 782 fl = (struct file_list *) malloc(sizeof *fl); 783 fl->f_type = COMPDEVICE; 784 fl->f_compinfo = dp->d_unit; 785 fl->f_fn = ns(dp->d_name); 786 (void) sprintf(buf, "%s%d", dp->d_name, dp->d_unit); 787 fl->f_needs = ns(buf); 788 fl->f_next = 0; 789 for (flp = compp; *flp; flp = &(*flp)->f_next) 790 ; 791 *flp = fl; 792 compp = flp; 793} 794 795addcomp(compdev, fl) 796 struct file_list *compdev, *fl; 797{ 798 register struct file_list **flp; 799 char name[80]; 800 801 if (compdev == 0 || compdev->f_type != COMPDEVICE) { 802 yyerror("component spec precedes device specification"); 803 return; 804 } 805 /* 806 * Append description to the end of the list. 807 */ 808 flp = &compdev->f_next; 809 for (; *flp && (*flp)->f_type == COMPSPEC; flp = &(*flp)->f_next) 810 ; 811 fl->f_next = *flp; 812 *flp = fl; 813} 814 815/* 816 * find the pointer to connect to the given device and number. 817 * returns 0 if no such device and prints an error message 818 */ 819struct device * 820connect(dev, num) 821 register char *dev; 822 register int num; 823{ 824 register struct device *dp; 825 struct device *huhcon(); 826 827 if (num == QUES) 828 return (huhcon(dev)); 829 for (dp = dtab; dp != 0; dp = dp->d_next) { 830 if ((num != dp->d_unit) || !eq(dev, dp->d_name)) 831 continue; 832 if (dp->d_type != CONTROLLER && dp->d_type != MASTER) { 833 (void) sprintf(errbuf, 834 "%s connected to non-controller", dev); 835 yyerror(errbuf); 836 return (0); 837 } 838 return (dp); 839 } 840 (void) sprintf(errbuf, "%s %d not defined", dev, num); 841 yyerror(errbuf); 842 return (0); 843} 844 845/* 846 * connect to an unspecific thing 847 */ 848struct device * 849huhcon(dev) 850 register char *dev; 851{ 852 register struct device *dp, *dcp; 853 struct device rdev; 854 int oldtype; 855 856 /* 857 * First make certain that there are some of these to wildcard on 858 */ 859 for (dp = dtab; dp != 0; dp = dp->d_next) 860 if (eq(dp->d_name, dev)) 861 break; 862 if (dp == 0) { 863 (void) sprintf(errbuf, "no %s's to wildcard", dev); 864 yyerror(errbuf); 865 return (0); 866 } 867 oldtype = dp->d_type; 868 dcp = dp->d_conn; 869 /* 870 * Now see if there is already a wildcard entry for this device 871 * (e.g. Search for a "uba ?") 872 */ 873 for (; dp != 0; dp = dp->d_next) 874 if (eq(dev, dp->d_name) && dp->d_unit == -1) 875 break; 876 /* 877 * If there isn't, make one because everything needs to be connected 878 * to something. 879 */ 880 if (dp == 0) { 881 dp = &rdev; 882 init_dev(dp); 883 dp->d_unit = QUES; 884 dp->d_name = ns(dev); 885 dp->d_type = oldtype; 886 newdev(dp); 887 dp = curp; 888 /* 889 * Connect it to the same thing that other similar things are 890 * connected to, but make sure it is a wildcard unit 891 * (e.g. up connected to sc ?, here we make connect sc? to a 892 * uba?). If other things like this are on the NEXUS or 893 * if they aren't connected to anything, then make the same 894 * connection, else call ourself to connect to another 895 * unspecific device. 896 */ 897 if (dcp == TO_NEXUS || dcp == 0) 898 dp->d_conn = dcp; 899 else 900 dp->d_conn = connect(dcp->d_name, QUES); 901 } 902 return (dp); 903} 904 905init_dev(dp) 906 register struct device *dp; 907{ 908 909 dp->d_name = "OHNO!!!"; 910 dp->d_type = DEVICE; 911 dp->d_conn = 0; 912 dp->d_vec = 0; 913 dp->d_addr = dp->d_flags = dp->d_dk = 0; 914 dp->d_pri = -1; 915 dp->d_slave = dp->d_lun = dp->d_target = dp->d_drive = dp->d_unit = UNKNOWN; 916 dp->d_port = (char *)0; 917 dp->d_portn = 0; 918 dp->d_irq = -1; 919 dp->d_drq = -1; 920 dp->d_maddr = 0; 921 dp->d_msize = 0; 922 dp->d_mask = "null"; 923} 924 925/* 926 * make certain that this is a reasonable type of thing to connect to a nexus 927 */ 928check_nexus(dev, num) 929 register struct device *dev; 930 int num; 931{ 932 933 switch (machine) { 934 935 case MACHINE_VAX: 936 if (!eq(dev->d_name, "uba") && !eq(dev->d_name, "mba") && 937 !eq(dev->d_name, "bi")) 938 yyerror("only uba's, mba's, and bi's should be connected to the nexus"); 939 if (num != QUES) 940 yyerror("can't give specific nexus numbers"); 941 break; 942 943 case MACHINE_TAHOE: 944 if (!eq(dev->d_name, "vba")) 945 yyerror("only vba's should be connected to the nexus"); 946 break; 947 948 case MACHINE_HP300: 949 case MACHINE_LUNA68K: 950 if (num != QUES) 951 dev->d_addr = num; 952 break; 953 954 case MACHINE_I386: 955 if (!eq(dev->d_name, "isa")) 956 yyerror("only isa's should be connected to the nexus"); 957 break; 958 959 case MACHINE_NEWS3400: 960 if (!eq(dev->d_name, "iop") && !eq(dev->d_name, "hb") && 961 !eq(dev->d_name, "vme")) 962 yyerror("only iop's, hb's and vme's should be connected to the nexus"); 963 break; 964 } 965} 966 967/* 968 * Check the timezone to make certain it is sensible 969 */ 970 971check_tz() 972{ 973 if (zone != 0 || dst != 0) 974 yyerror("timezone specification is no longer permitted"); 975 else 976 hadtz = 1; 977} 978 979/* 980 * Check system specification and apply defaulting 981 * rules on root, argument, dump, and swap devices. 982 */ 983checksystemspec(fl) 984 register struct file_list *fl; 985{ 986 char buf[BUFSIZ]; 987 register struct file_list *swap; 988 int generic; 989 990 if (fl == 0 || fl->f_type != SYSTEMSPEC) { 991 yyerror("internal error, bad system specification"); 992 exit(1); 993 } 994 swap = fl->f_next; 995 generic = swap && swap->f_type == SWAPSPEC && eq(swap->f_fn, "generic"); 996 if (fl->f_rootdev == NODEV && !generic) { 997 yyerror("no root device specified"); 998 exit(1); 999 } 1000 /* 1001 * Default swap area to be in 'b' partition of root's 1002 * device. If root specified to be other than on 'a' 1003 * partition, give warning, something probably amiss. 1004 */ 1005 if (swap == 0 || swap->f_type != SWAPSPEC) { 1006 dev_t dev; 1007 1008 swap = newflist(SWAPSPEC); 1009 dev = fl->f_rootdev; 1010 if (dkpart(dev) != 0) { 1011 (void) sprintf(buf, 1012"Warning, swap defaulted to 'b' partition with root on '%c' partition", 1013 dkpart(dev) + 'a'); 1014 yyerror(buf); 1015 } 1016 swap->f_swapdev = dkmodpart(dev, SWAP_PART); 1017 swap->f_fn = devtoname(swap->f_swapdev); 1018 mkswap(fl, swap, 0); 1019 } 1020 /* 1021 * Make sure a generic swap isn't specified, along with 1022 * other stuff (user must really be confused). 1023 */ 1024 if (generic) { 1025 if (fl->f_rootdev != NODEV) 1026 yyerror("root device specified with generic swap"); 1027 if (fl->f_dumpdev != NODEV) 1028 yyerror("dump device specified with generic swap"); 1029 return; 1030 } 1031 /* 1032 * Default dump device and warn if place is not a 1033 * swap area. 1034 */ 1035 if (fl->f_dumpdev == NODEV) 1036 fl->f_dumpdev = swap->f_swapdev; 1037 if (fl->f_dumpdev != swap->f_swapdev) { 1038 struct file_list *p = swap->f_next; 1039 1040 for (; p && p->f_type == SWAPSPEC; p = p->f_next) 1041 if (fl->f_dumpdev == p->f_swapdev) 1042 return; 1043 (void) sprintf(buf, 1044 "Warning: dump device is not a swap partition"); 1045 yyerror(buf); 1046 } 1047} 1048 1049/* 1050 * Verify all devices specified in the system specification 1051 * are present in the device specifications. 1052 */ 1053verifysystemspecs() 1054{ 1055 register struct file_list *fl; 1056 dev_t checked[50], *verifyswap(); 1057 register dev_t *pchecked = checked; 1058 1059 for (fl = conf_list; fl; fl = fl->f_next) { 1060 if (fl->f_type != SYSTEMSPEC) 1061 continue; 1062 if (!finddev(fl->f_rootdev)) 1063 deverror(fl->f_needs, "root"); 1064 *pchecked++ = fl->f_rootdev; 1065 pchecked = verifyswap(fl->f_next, checked, pchecked); 1066 if (!alreadychecked(fl->f_dumpdev, checked, pchecked)) { 1067 if (!finddev(fl->f_dumpdev)) 1068 deverror(fl->f_needs, "dump"); 1069 *pchecked++ = fl->f_dumpdev; 1070 } 1071 } 1072} 1073 1074/* 1075 * Do as above, but for swap devices. 1076 */ 1077dev_t * 1078verifyswap(fl, checked, pchecked) 1079 register struct file_list *fl; 1080 dev_t checked[]; 1081 register dev_t *pchecked; 1082{ 1083 1084 for (;fl && fl->f_type == SWAPSPEC; fl = fl->f_next) { 1085 if (eq(fl->f_fn, "generic")) 1086 continue; 1087 if (alreadychecked(fl->f_swapdev, checked, pchecked)) 1088 continue; 1089 if (!finddev(fl->f_swapdev)) 1090 fprintf(stderr, 1091 "config: swap device %s not configured", fl->f_fn); 1092 *pchecked++ = fl->f_swapdev; 1093 } 1094 return (pchecked); 1095} 1096 1097/* 1098 * Verify that components of a compound device have themselves been config'ed 1099 */ 1100verifycomp(fl) 1101 register struct file_list *fl; 1102{ 1103 char *dname = fl->f_needs; 1104 1105 for (fl = fl->f_next; fl; fl = fl->f_next) { 1106 if (fl->f_type != COMPSPEC || finddev(fl->f_compdev)) 1107 continue; 1108 fprintf(stderr, 1109 "config: %s: component device %s not configured\n", 1110 dname, fl->f_needs); 1111 } 1112} 1113 1114/* 1115 * Has a device already been checked 1116 * for its existence in the configuration? 1117 */ 1118alreadychecked(dev, list, last) 1119 dev_t dev, list[]; 1120 register dev_t *last; 1121{ 1122 register dev_t *p; 1123 1124 for (p = list; p < last; p++) 1125 if (dkmodpart(*p, 0) != dkmodpart(dev, 0)) 1126 return (1); 1127 return (0); 1128} 1129 1130deverror(systemname, devtype) 1131 char *systemname, *devtype; 1132{ 1133 1134 fprintf(stderr, "config: %s: %s device not configured\n", 1135 systemname, devtype); 1136} 1137 1138/* 1139 * Look for the device in the list of 1140 * configured hardware devices. Must 1141 * take into account stuff wildcarded. 1142 */ 1143/*ARGSUSED*/ 1144finddev(dev) 1145 dev_t dev; 1146{ 1147 1148 /* punt on this right now */ 1149 return (1); 1150} 1151