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