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