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