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