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