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