1/* 2 * Mach Operating System 3 * Copyright (c) 1990 Carnegie-Mellon University 4 * Copyright (c) 1989 Carnegie-Mellon University 5 * Copyright (c) 1988 Carnegie-Mellon University 6 * Copyright (c) 1987 Carnegie-Mellon University 7 * All rights reserved. The CMU software License Agreement specifies 8 * the terms and conditions for use and redistribution. 9 */ 10 11/* 12 * Copyright (c) 1988 Regents of the University of California. 13 * All rights reserved. 14 * 15 * Redistribution and use in source and binary forms are permitted 16 * provided that the above copyright notice and this paragraph are 17 * duplicated in all such forms and that any documentation, 18 * advertising materials, and other materials related to such 19 * distribution and use acknowledge that the software was developed 20 * by the University of California, Berkeley. The name of the 21 * University may not be used to endorse or promote products derived 22 * from this software without specific prior written permission. 23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 25 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 26 * 27 * @(#)config.y 5.8 (Berkeley) 6/18/88 28 */ 29 30%union { 31 char *str; 32 int val; 33 struct file_list *file; 34 struct idlst *lst; 35} 36 37%token ADDRMOD 38%token AND 39%token ANY 40%token ARGS 41%token AT 42%token BIN 43%token BUILDDIR 44%token COMMA 45%token CONFIG 46%token CONFIGDIR 47%token CONTROLLER 48%token CPU 49%token CSR 50%token DEVICE 51%token DISK 52%token DRIVE 53%token DST 54%token DUMPS 55%token EQUALS 56%token FLAGS 57%token HZ 58%token IDENT 59%token INIT 60%token MACHINE 61%token MAJOR 62%token MASTER 63%token MAXUSERS 64%token MAXDSIZ 65%token MBA 66%token MBII 67%token MINOR 68%token MINUS 69%token NEXUS 70%token OBJECTDIR 71%token ON 72%token OPTIONS 73%token MAKEOPTIONS 74%token PRIORITY 75%token PROFILE 76%token PSEUDO_DEVICE 77%token ROOT 78%token SEMICOLON 79%token SIZE 80%token SLAVE 81%token SOURCEDIR 82%token SWAP 83%token TIMEZONE 84%token TRACE 85%token UBA 86%token VECTOR 87%token VME 88%token VME16D16 89%token VME24D16 90%token VME32D16 91%token VME16D32 92%token VME24D32 93%token VME32D32 94 95/* following 3 are unique to CMU */ 96%token LUN 97%token SLOT 98%token TAPE 99 100%token <str> ID 101%token <val> NUMBER 102%token <val> FPNUMBER 103 104%type <str> Save_id 105%type <str> Opt_value 106%type <str> Dev 107%type <lst> Id_list 108%type <val> optional_size 109%type <str> device_name 110%type <val> major_minor 111%type <val> arg_device_spec 112%type <val> root_device_spec 113%type <val> dump_device_spec 114%type <file> swap_device_spec 115%type <val> Value 116 117%{ 118 119#include "config.h" 120#include <ctype.h> 121#include <stdio.h> 122 123struct device cur; 124struct device *curp = 0; 125char *temp_id; 126char *val_id; 127/* char *malloc(); */ 128 129int yylex(void); 130 131int finddev(dev_t dev); 132int alreadychecked(dev_t dev, dev_t list[], dev_t *last); 133void deverror(const char *systemname, const char *devtype); 134void mkconf(char *sysname); 135struct file_list *newswap(void); 136void mkswap(struct file_list *syslist, struct file_list *fl, int size); 137struct device *huhcon(const char *dev); 138void check_nexus(struct device *dev, int num); 139void check_slot(struct device *dev, int num); 140void checksystemspec(struct file_list *fl); 141void verifysystemspecs(void); 142dev_t *verifyswap(struct file_list *fl, dev_t checked[], dev_t *pchecked); 143struct device *dconnect(const char *dev, int num); 144 145%} 146%% 147Configuration: 148 Many_specs 149 { verifysystemspecs(); } 150 ; 151 152Many_specs: 153 Many_specs Spec 154 | 155 /* lambda */ 156 ; 157 158Spec: 159 Device_spec SEMICOLON 160 { newdev(&cur); } | 161 Config_spec SEMICOLON 162 | 163 TRACE SEMICOLON 164 { do_trace = !do_trace; } | 165 SEMICOLON 166 | 167 error SEMICOLON 168 ; 169 170Config_spec: 171 MACHINE Save_id 172 { 173 if (!strcmp($2, "vax")) { 174 machine = MACHINE_VAX; 175 machinename = "vax"; 176 } else if (!strcmp($2, "sun")) { 177 /* default to Sun 3 */ 178 machine = MACHINE_SUN3; 179 machinename = "sun3"; 180 } else if (!strcmp($2, "sun2")) { 181 machine = MACHINE_SUN2; 182 machinename = "sun2"; 183 } else if (!strcmp($2, "sun3")) { 184 machine = MACHINE_SUN3; 185 machinename = "sun3"; 186 } else if (!strcmp($2, "sun4")) { 187 machine = MACHINE_SUN4; 188 machinename = "sun4"; 189 } else if (!strcmp($2, "romp")) { 190 machine = MACHINE_ROMP; 191 machinename = "romp"; 192 } else if (!strcmp($2, "ca")) { 193 machine = MACHINE_ROMP; 194 machinename = "ca"; 195 } else if (!strcmp($2, "mmax")) { 196 machine = MACHINE_MMAX; 197 machinename = "mmax"; 198 } else if (!strcmp($2, "sqt")) { 199 machine = MACHINE_SQT; 200 machinename = "sqt"; 201 } else if (!strcmp($2, "i")) { 202 machine = MACHINE_I386; 203 machinename = "i386"; 204 } else if (!strcmp($2, "i386")) { 205 machine = MACHINE_I386; 206 machinename = "i386"; 207 } else if (!strcmp($2, "ix")) { 208 machine = MACHINE_IX; 209 machinename = "ix"; 210 } else if (!strcmp($2, "mipsy")) { 211 machine = MACHINE_MIPSY; 212 machinename = "mipsy"; 213 } else if (!strcmp($2, "mips")) { 214 machine = MACHINE_MIPS; 215 machinename = "mips"; 216 } else if (!strcmp($2, "i860")) { 217 machine = MACHINE_I860; 218 machinename = "i860"; 219 } else if (!strcmp($2, "m68k")) { 220 machine = MACHINE_M68K; 221 machinename = "m68k"; 222 } else if (!strcmp($2, "m88k")) { 223 machine = MACHINE_M88K; 224 machinename = "m88k"; 225 } else if (!strcmp($2, "m98k")) { 226 machine = MACHINE_M98K; 227 machinename = "m98k"; 228 } else if (!strcmp($2, "hppa")) { 229 machine = MACHINE_HPPA; 230 machinename = "hppa"; 231 } else if (!strcmp($2, "sparc")) { 232 machine = MACHINE_SPARC; 233 machinename = "sparc"; 234 } else if (!strcmp($2, "ppc")) { 235 machine = MACHINE_PPC; 236 machinename = "ppc"; 237 } else if (!strcmp($2, "arm")) { 238 machine = MACHINE_ARM; 239 machinename = "arm"; 240 } else if (!strcmp($2, "x86_64")) { 241 machine = MACHINE_X86_64; 242 machinename = "x86_64"; 243 } else 244 yyerror("Unknown machine type"); 245 } | 246 CPU Save_id 247 { 248 struct cputype *cp = 249 (struct cputype *)malloc(sizeof (struct cputype)); 250 cp->cpu_name = ns($2); 251 cp->cpu_next = cputype; 252 cputype = cp; 253 free(temp_id); 254 } | 255 OPTIONS Opt_list 256 | 257 MAKEOPTIONS Mkopt_list 258 | 259 IDENT ID 260 { ident = ns($2); } 261 | 262 System_spec 263 | 264 MAXUSERS NUMBER 265 { maxusers = $2; } 266 | 267 BUILDDIR Save_id 268 { build_directory = ns($2); } 269 | 270 CONFIGDIR Save_id 271 { config_directory = ns($2); } 272 | 273 OBJECTDIR Save_id 274 { object_directory = ns($2); } 275 | 276 SOURCEDIR Save_id 277 { source_directory = ns($2); } 278 | 279 PROFILE 280 { profiling++; } 281 ; 282 283System_spec: 284 System_id 285 { checksystemspec(*confp); } 286 | System_id System_parameter_list 287 { checksystemspec(*confp); } 288 ; 289 290System_id: 291 CONFIG Save_id 292 { mkconf($2); } 293 ; 294 295System_parameter_list: 296 System_parameter_list System_parameter 297 | System_parameter 298 ; 299 300System_parameter: 301 swap_spec 302 | root_spec 303 | dump_spec 304 | arg_spec 305 ; 306 307swap_spec: 308 SWAP optional_on swap_device_list 309 ; 310 311swap_device_list: 312 swap_device_list AND swap_device 313 | swap_device 314 ; 315 316swap_device: 317 swap_device_spec optional_size 318 { mkswap(*confp, $1, $2); } 319 ; 320 321swap_device_spec: 322 device_name 323 { 324 struct file_list *fl = newswap(); 325 326 if (eq($1, "generic")) 327 fl->f_fn = $1; 328 else { 329 fl->f_swapdev = nametodev($1, 0, 'b'); 330 fl->f_fn = devtoname(fl->f_swapdev); 331 } 332 $$ = fl; 333 } 334 | major_minor 335 { 336 struct file_list *fl = newswap(); 337 338 fl->f_swapdev = $1; 339 fl->f_fn = devtoname($1); 340 $$ = fl; 341 } 342 ; 343 344root_spec: 345 ROOT optional_on root_device_spec 346 { 347 struct file_list *fl = *confp; 348 349 if (fl && fl->f_rootdev != NODEV) 350 yyerror("extraneous root device specification"); 351 else 352 fl->f_rootdev = $3; 353 } 354 ; 355 356root_device_spec: 357 device_name 358 { $$ = nametodev($1, 0, 'a'); } 359 | major_minor 360 ; 361 362dump_spec: 363 DUMPS optional_on dump_device_spec 364 { 365 struct file_list *fl = *confp; 366 367 if (fl && fl->f_dumpdev != NODEV) 368 yyerror("extraneous dump device specification"); 369 else 370 fl->f_dumpdev = $3; 371 } 372 373 ; 374 375dump_device_spec: 376 device_name 377 { $$ = nametodev($1, 0, 'b'); } 378 | major_minor 379 ; 380 381arg_spec: 382 ARGS optional_on arg_device_spec 383 { 384 struct file_list *fl = *confp; 385 386 if (fl && fl->f_argdev != NODEV) 387 yyerror("extraneous arg device specification"); 388 else 389 fl->f_argdev = $3; 390 } 391 ; 392 393arg_device_spec: 394 device_name 395 { $$ = nametodev($1, 0, 'b'); } 396 | major_minor 397 ; 398 399major_minor: 400 MAJOR NUMBER MINOR NUMBER 401 { $$ = makedev($2, $4); } 402 ; 403 404optional_on: 405 ON 406 | /* empty */ 407 ; 408 409optional_size: 410 SIZE NUMBER 411 { $$ = $2; } 412 | /* empty */ 413 { $$ = 0; } 414 ; 415 416device_name: 417 Save_id 418 { $$ = $1; } 419 | Save_id NUMBER 420 { 421 char buf[80]; 422 423 (void) sprintf(buf, "%s%d", $1, $2); 424 $$ = ns(buf); free($1); 425 } 426 | Save_id NUMBER ID 427 { 428 char buf[80]; 429 430 (void) sprintf(buf, "%s%d%s", $1, $2, $3); 431 $$ = ns(buf); free($1); 432 } 433 ; 434 435Opt_list: 436 Opt_list COMMA Option 437 | 438 Option 439 ; 440 441Option: 442 Save_id 443 { 444 struct opt *op = (struct opt *)malloc(sizeof (struct opt)); 445 op->op_name = ns($1); 446 op->op_next = (struct opt *) 0; 447 op->op_value = 0; 448 if (opt == (struct opt *) 0) 449 opt = op; 450 else 451 opt_tail->op_next = op; 452 opt_tail = op; 453 free(temp_id); 454 } | 455 Save_id EQUALS Opt_value 456 { 457 struct opt *op = (struct opt *)malloc(sizeof (struct opt)); 458 op->op_name = ns($1); 459 op->op_next = (struct opt *) 0; 460 op->op_value = ns($3); 461 if (opt == (struct opt *) 0) 462 opt = op; 463 else 464 opt_tail->op_next = op; 465 opt_tail = op; 466 free(temp_id); 467 if (val_id) 468 free(val_id); 469 } ; 470 471Opt_value: 472 ID 473 { $$ = val_id = ns($1); } | 474 NUMBER 475 { char nb[16]; 476 (void) sprintf(nb, "%u", $1); 477 $$ = val_id = ns(nb); 478 } | 479 /* lambda from MIPS -- WHY */ 480 { $$ = val_id = ns(""); } 481 ; 482 483Save_id: 484 ID 485 { $$ = temp_id = ns($1); } 486 ; 487 488Mkopt_list: 489 Mkopt_list COMMA Mkoption 490 | 491 Mkoption 492 ; 493 494Mkoption: 495 Save_id 496 { 497 struct opt *op = (struct opt *)malloc(sizeof (struct opt)); 498 op->op_name = ns($1); 499 op->op_next = (struct opt *) 0; 500 op->op_value = 0; 501 mkopt = op; 502 free(temp_id); 503 } | 504 Save_id EQUALS Opt_value 505 { 506 struct opt *op = (struct opt *)malloc(sizeof (struct opt)); 507 op->op_name = ns($1); 508 op->op_next = (struct opt *) 0; 509 op->op_value = ns($3); 510 if (mkopt == (struct opt *) 0) 511 mkopt = op; 512 else 513 mkopt_tail->op_next = op; 514 mkopt_tail = op; 515 free(temp_id); 516 if (val_id) 517 free(val_id); 518 } ; 519 520Dev: 521 UBA 522 { $$ = ns("uba"); } | 523 MBA 524 { $$ = ns("mba"); } | 525 VME16D16 526 { 527 if (machine != MACHINE_SUN2 && machine != MACHINE_SUN3 528 && machine != MACHINE_SUN4) 529 yyerror("wrong machine type for vme16d16"); 530 $$ = ns("vme16d16"); 531 } | 532 VME24D16 533 { 534 if (machine != MACHINE_SUN2 && machine != MACHINE_SUN3 535 && machine != MACHINE_SUN4) 536 yyerror("wrong machine type for vme24d16"); 537 $$ = ns("vme24d16"); 538 } | 539 VME32D16 540 { 541 if (machine != MACHINE_SUN3 && machine != MACHINE_SUN4) 542 543 yyerror("wrong machine type for vme32d16"); 544 $$ = ns("vme32d16"); 545 } | 546 VME16D32 547 { 548 if (machine != MACHINE_SUN3 && machine != MACHINE_SUN4) 549 yyerror("wrong machine type for vme16d32"); 550 $$ = ns("vme16d32"); 551 } | 552 VME24D32 553 { 554 if (machine != MACHINE_SUN3 && machine != MACHINE_SUN4) 555 yyerror("wrong machine type for vme24d32"); 556 $$ = ns("vme24d32"); 557 } | 558 VME32D32 559 { 560 if (machine != MACHINE_SUN3 && machine != MACHINE_SUN4) 561 yyerror("wrong machine type for vme32d32"); 562 $$ = ns("vme32d32"); 563 } | 564 VME 565 { 566 if (machine != MACHINE_MIPSY && machine != MACHINE_MIPS) 567 yyerror("wrong machine type for vme"); 568 $$ = ns("vme"); 569 } | 570 MBII 571 { 572 if (machine != MACHINE_MIPSY && machine != MACHINE_MIPS) 573 yyerror("wrong machine type for mbii"); 574 $$ = ns("mbii"); 575 } | 576 ID 577 { $$ = ns($1); } 578 ; 579 580Device_spec: 581 DEVICE Dev_name Dev_info Int_spec 582 { cur.d_type = DEVICE; } | 583 MASTER Dev_name Dev_info Int_spec 584 { cur.d_type = MASTER; } | 585 DISK Dev_name Dev_info Int_spec 586 { cur.d_dk = 1; cur.d_type = DEVICE; } | 587/* TAPE rule is unique to CMU */ 588 TAPE Dev_name Dev_info Int_spec 589 { cur.d_type = DEVICE; } | 590 CONTROLLER Dev_name Dev_info Int_spec 591 { cur.d_type = CONTROLLER; } | 592 PSEUDO_DEVICE Init_dev Dev 593 { 594 cur.d_name = $3; 595 cur.d_type = PSEUDO_DEVICE; 596 } | 597 PSEUDO_DEVICE Init_dev Dev NUMBER 598 { 599 cur.d_name = $3; 600 cur.d_type = PSEUDO_DEVICE; 601 cur.d_slave = $4; 602 } | 603 PSEUDO_DEVICE Init_dev Dev INIT ID 604 { 605 cur.d_name = $3; 606 cur.d_type = PSEUDO_DEVICE; 607 cur.d_init = ns($5); 608 } | 609 PSEUDO_DEVICE Init_dev Dev NUMBER INIT ID 610 { 611 cur.d_name = $3; 612 cur.d_type = PSEUDO_DEVICE; 613 cur.d_slave = $4; 614 cur.d_init = ns($6); 615 }; 616 617Dev_name: 618 Init_dev Dev NUMBER 619 { 620 cur.d_name = $2; 621 if (eq($2, "mba")) 622 seen_mba = 1; 623 else if (eq($2, "uba")) 624 seen_uba = 1; 625 else if (eq($2, "mbii")) 626 seen_mbii = 1; 627 else if (eq($2, "vme")) 628 seen_vme = 1; 629 cur.d_unit = $3; 630 }; 631 632Init_dev: 633 /* lambda */ 634 { init_dev(&cur); }; 635 636Dev_info: 637 Con_info Info_list 638 | 639 /* lambda */ 640 ; 641 642Con_info: 643 AT Dev NUMBER 644 { 645 if (eq(cur.d_name, "mba") || eq(cur.d_name, "uba") 646 || eq(cur.d_name, "mbii") || eq(cur.d_name, "vme")) { 647 (void) sprintf(errbuf, 648 "%s must be connected to a nexus", cur.d_name); 649 yyerror(errbuf); 650 } 651 cur.d_conn = dconnect($2, $3); 652 if (machine == MACHINE_SQT) 653 dev_param(&cur, "index", cur.d_unit); 654 } | 655/* AT SLOT NUMBER rule is unique to CMU */ 656 AT SLOT NUMBER 657 { 658 check_slot(&cur, $3); 659 cur.d_addr = $3; 660 cur.d_conn = TO_SLOT; 661 } | 662 AT NEXUS NUMBER 663 { check_nexus(&cur, $3); cur.d_conn = TO_NEXUS; }; 664 665Info_list: 666 Info_list Info 667 | 668 /* lambda */ 669 ; 670 671Info: 672 CSR NUMBER 673 { 674 cur.d_addr = $2; 675 if (machine == MACHINE_SQT) { 676 dev_param(&cur, "csr", $2); 677 } 678 } | 679 DRIVE NUMBER 680 { 681 cur.d_drive = $2; 682 if (machine == MACHINE_SQT) { 683 dev_param(&cur, "drive", $2); 684 } 685 } | 686 SLAVE NUMBER 687 { 688 if (cur.d_conn != 0 && cur.d_conn != TO_NEXUS && 689 cur.d_conn->d_type == MASTER) 690 cur.d_slave = $2; 691 else 692 yyerror("can't specify slave--not to master"); 693 } | 694/* MIPS */ 695 ADDRMOD NUMBER 696 { cur.d_addrmod = $2; } | 697/* LUN NUMBER rule is unique to CMU */ 698 LUN NUMBER 699 { 700 if ((cur.d_conn != 0) && (cur.d_conn != TO_SLOT) && 701 (cur.d_conn->d_type == CONTROLLER)) { 702 cur.d_addr = $2; 703 } 704 else { 705 yyerror("device requires controller card"); 706 } 707 } | 708 FLAGS NUMBER 709 { 710 cur.d_flags = $2; 711 if (machine == MACHINE_SQT) { 712 dev_param(&cur, "flags", $2); 713 } 714 } | 715 BIN NUMBER 716 { 717 if (machine != MACHINE_SQT) 718 yyerror("bin specification only valid on Sequent Balance"); 719 if ($2 < 1 || $2 > 7) 720 yyerror("bogus bin number"); 721 else { 722 cur.d_bin = $2; 723 dev_param(&cur, "bin", $2); 724 } 725 } | 726 Dev Value 727 { 728 if (machine != MACHINE_SQT) 729 yyerror("bad device spec"); 730 dev_param(&cur, $1, $2); 731 }; 732 733Value: 734 NUMBER 735 | 736 MINUS NUMBER 737 { $$ = -($2); } 738 ; 739 740Int_spec: 741 Vec_spec 742 { cur.d_pri = 0; } | 743 PRIORITY NUMBER 744 { cur.d_pri = $2; } | 745 PRIORITY NUMBER Vec_spec 746 { cur.d_pri = $2; } | 747 Vec_spec PRIORITY NUMBER 748 { cur.d_pri = $3; } | 749 /* lambda */ 750 ; 751 752Vec_spec: 753 VECTOR Id_list 754 { cur.d_vec = $2; }; 755 756 757Id_list: 758 Save_id 759 { 760 struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst)); 761 a->id = $1; a->id_next = 0; $$ = a; 762 a->id_vec = 0; 763 } | 764 Save_id Id_list 765 { 766 struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst)); 767 a->id = $1; a->id_next = $2; $$ = a; 768 a->id_vec = 0; 769 } | 770 Save_id NUMBER 771 { 772 struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst)); 773 a->id_next = 0; a->id = $1; $$ = a; 774 a->id_vec = $2; 775 } | 776 Save_id NUMBER Id_list 777 { 778 struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst)); 779 a->id_next = $3; a->id = $1; $$ = a; 780 a->id_vec = $2; 781 }; 782 783%% 784 785void 786yyerror(const char *s) 787{ 788 fprintf(stderr, "config: line %d: %s\n", yyline, s); 789} 790 791/* 792 * return the passed string in a new space 793 */ 794char * 795ns(const char *str) 796{ 797 register char *cp; 798 799 cp = malloc((unsigned)(strlen(str)+1)); 800 (void) strcpy(cp, str); 801 return (cp); 802} 803 804/* 805 * add a device to the list of devices 806 */ 807void 808newdev(struct device *dp) 809{ 810 register struct device *np; 811 812 np = (struct device *) malloc(sizeof *np); 813 *np = *dp; 814 if (curp == 0) 815 dtab = np; 816 else 817 curp->d_next = np; 818 curp = np; 819 curp->d_next = 0; 820} 821 822/* 823 * note that a configuration should be made 824 */ 825void 826mkconf(char *sysname) 827{ 828 register struct file_list *fl, **flp; 829 830 fl = (struct file_list *) malloc(sizeof *fl); 831 fl->f_type = SYSTEMSPEC; 832 fl->f_needs = sysname; 833 fl->f_rootdev = NODEV; 834 fl->f_argdev = NODEV; 835 fl->f_dumpdev = NODEV; 836 fl->f_fn = 0; 837 fl->f_next = 0; 838 for (flp = confp; *flp; flp = &(*flp)->f_next) 839 ; 840 *flp = fl; 841 confp = flp; 842} 843 844struct file_list * 845newswap(void) 846{ 847 struct file_list *fl = (struct file_list *)malloc(sizeof (*fl)); 848 849 fl->f_type = SWAPSPEC; 850 fl->f_next = 0; 851 fl->f_swapdev = NODEV; 852 fl->f_swapsize = 0; 853 fl->f_needs = 0; 854 fl->f_fn = 0; 855 return (fl); 856} 857 858/* 859 * Add a swap device to the system's configuration 860 */ 861void 862mkswap(struct file_list *syslist, struct file_list *fl, int size) 863{ 864 register struct file_list **flp; 865 866 if (syslist == 0 || syslist->f_type != SYSTEMSPEC) { 867 yyerror("\"swap\" spec precedes \"config\" specification"); 868 return; 869 } 870 if (size < 0) { 871 yyerror("illegal swap partition size"); 872 return; 873 } 874 /* 875 * Append swap description to the end of the list. 876 */ 877 flp = &syslist->f_next; 878 for (; *flp && (*flp)->f_type == SWAPSPEC; flp = &(*flp)->f_next) 879 ; 880 fl->f_next = *flp; 881 *flp = fl; 882 fl->f_swapsize = size; 883 /* 884 * If first swap device for this system, 885 * set up f_fn field to insure swap 886 * files are created with unique names. 887 */ 888 if (syslist->f_fn) 889 return; 890 if (eq(fl->f_fn, "generic")) 891 syslist->f_fn = ns(fl->f_fn); 892 else 893 syslist->f_fn = ns(syslist->f_needs); 894} 895 896/* 897 * find the pointer to connect to the given device and number. 898 * returns 0 if no such device and prints an error message 899 */ 900struct device * 901dconnect(const char *dev, int num) 902{ 903 register struct device *dp; 904 905 if (num == QUES) 906 return (huhcon(dev)); 907 for (dp = dtab; dp != 0; dp = dp->d_next) { 908 if ((num != dp->d_unit) || !eq(dev, dp->d_name)) 909 continue; 910 if (dp->d_type != CONTROLLER && dp->d_type != MASTER) { 911 (void) sprintf(errbuf, 912 "%s connected to non-controller", dev); 913 yyerror(errbuf); 914 return (0); 915 } 916 return (dp); 917 } 918 (void) sprintf(errbuf, "%s %d not defined", dev, num); 919 yyerror(errbuf); 920 return (0); 921} 922 923/* 924 * connect to an unspecific thing 925 */ 926struct device * 927huhcon(const char *dev) 928{ 929 register struct device *dp, *dcp; 930 struct device rdev; /* only used if dp is NULL */ 931 int oldtype; 932 933 memset(&rdev, 0, sizeof rdev); 934 935 /* 936 * First make certain that there are some of these to wildcard on 937 */ 938 for (dp = dtab; dp != 0; dp = dp->d_next) 939 if (eq(dp->d_name, dev)) 940 break; 941 if (dp == 0) { 942 (void) sprintf(errbuf, "no %s's to wildcard", dev); 943 yyerror(errbuf); 944 return (0); 945 } 946 oldtype = dp->d_type; 947 dcp = dp->d_conn; 948 /* 949 * Now see if there is already a wildcard entry for this device 950 * (e.g. Search for a "uba ?") 951 */ 952 for (; dp != 0; dp = dp->d_next) 953 if (eq(dev, dp->d_name) && dp->d_unit == -1) 954 break; 955 /* 956 * If there isn't, make one because everything needs to be connected 957 * to something. 958 */ 959 if (dp == 0) { 960 dp = &rdev; 961 init_dev(dp); 962 dp->d_unit = QUES; 963 dp->d_name = ns(dev); 964 dp->d_type = oldtype; 965 newdev(dp); 966 dp = curp; 967 /* 968 * Connect it to the same thing that other similar things are 969 * connected to, but make sure it is a wildcard unit 970 * (e.g. up connected to sc ?, here we make connect sc? to a 971 * uba?). If other things like this are on the NEXUS or 972 * if they aren't connected to anything, then make the same 973 * connection, else call ourself to connect to another 974 * unspecific device. 975 */ 976 if (dcp == TO_NEXUS || dcp == 0) 977 dp->d_conn = dcp; 978 else 979 dp->d_conn = dconnect(dcp->d_name, QUES); 980 } 981 return (dp); 982} 983 984void 985init_dev(struct device *dp) 986{ 987 988 dp->d_name = "OHNO!!!"; 989 dp->d_type = DEVICE; 990 dp->d_conn = 0; 991 dp->d_vec = 0; 992 dp->d_addr = dp->d_pri = dp->d_flags = dp->d_dk = 0; 993 dp->d_slave = dp->d_drive = dp->d_unit = UNKNOWN; 994 if (machine == MACHINE_SUN2 || machine == MACHINE_SUN3 995 || machine == MACHINE_SUN4){ 996 dp->d_addr = UNKNOWN; 997 dp->d_mach = dp->d_bus = 0; 998 } 999 if (machine == MACHINE_MIPSY || machine == MACHINE_MIPS){ 1000 dp->d_addrmod = 0; 1001 } 1002 dp->d_init = 0; 1003} 1004 1005/* 1006 * make certain that this is a reasonable type of thing to connect to a nexus 1007 */ 1008void 1009check_nexus(struct device *dev, int num) 1010{ 1011 1012 switch (machine) { 1013 1014 case MACHINE_VAX: 1015 if (!eq(dev->d_name, "uba") && !eq(dev->d_name, "mba")) 1016 yyerror("only uba's and mba's should be connected to the nexus"); 1017 if (num != QUES) 1018 yyerror("can't give specific nexus numbers"); 1019 break; 1020 1021 case MACHINE_SUN: 1022 if (!eq(dev->d_name, "mb")) 1023 yyerror("only mb's should be connected to the nexus"); 1024 break; 1025 1026 case MACHINE_ROMP: 1027 if (!eq(dev->d_name, "iocc")) 1028 yyerror("only iocc's should be connected to the nexus"); 1029 break; 1030 case MACHINE_SUN2: 1031 if (!eq(dev->d_name, "virtual") && 1032 !eq(dev->d_name, "obmem") && 1033 !eq(dev->d_name, "obio") && 1034 !eq(dev->d_name, "mbmem") && 1035 !eq(dev->d_name, "mbio") && 1036 !eq(dev->d_name, "vme16d16") && 1037 !eq(dev->d_name, "vme24d16")) { 1038 (void)sprintf(errbuf, 1039 "unknown bus type `%s' for nexus connection on %s", 1040 dev->d_name, machinename); 1041 yyerror(errbuf); 1042 } 1043 1044 case MACHINE_MMAX: 1045 yyerror("don't grok 'nexus' on mmax -- try 'slot'."); 1046 break; 1047 case MACHINE_SUN3: 1048 case MACHINE_SUN4: 1049 if (!eq(dev->d_name, "virtual") && 1050 !eq(dev->d_name, "obmem") && 1051 !eq(dev->d_name, "obio") && 1052 !eq(dev->d_name, "mbmem") && 1053 !eq(dev->d_name, "mbio") && 1054 !eq(dev->d_name, "vme16d16") && 1055 !eq(dev->d_name, "vme24d16") && 1056 !eq(dev->d_name, "vme32d16") && 1057 !eq(dev->d_name, "vme16d32") && 1058 !eq(dev->d_name, "vme24d32") && 1059 !eq(dev->d_name, "vme32d32")) { 1060 (void)sprintf(errbuf, 1061 "unknown bus type `%s' for nexus connection on %s", 1062 dev->d_name, machinename); 1063 yyerror(errbuf); 1064 } 1065 break; 1066 case MACHINE_MIPSY: 1067 case MACHINE_MIPS: 1068 if (!eq(dev->d_name, "vme") && !eq(dev->d_name, "mbii")) 1069 yyerror("only vme's and mbii's should be connected to the nexus"); 1070 if (num != QUES) 1071 yyerror("can't give specific nexus numbers"); 1072 break; 1073 } 1074} 1075 1076/* 1077 * make certain that this is a reasonable type of thing to connect to a slot 1078 */ 1079 1080void 1081check_slot(struct device *dev, int num) 1082{ 1083 1084 switch (machine) { 1085 1086 case MACHINE_MMAX: 1087 if (!eq(dev->d_name, "emc")) 1088 yyerror("only emc's plug into backplane slots."); 1089 if (num == QUES) 1090 yyerror("specific slot numbers must be given"); 1091 break; 1092 1093 case MACHINE_SQT: 1094 if (!eq(dev->d_name, "mbad") && 1095 !eq(dev->d_name, "zdc") && 1096 !eq(dev->d_name, "sec")) { 1097 (void)sprintf(errbuf, 1098 "unknown bus type `%s' for slot on %s", 1099 dev->d_name, machinename); 1100 yyerror(errbuf); 1101 } 1102 break; 1103 1104 default: 1105 yyerror("don't grok 'slot' for this machine -- try 'nexus'."); 1106 break; 1107 } 1108} 1109 1110/* 1111 * Check system specification and apply defaulting 1112 * rules on root, argument, dump, and swap devices. 1113 */ 1114void 1115checksystemspec(struct file_list *fl) 1116{ 1117 char buf[BUFSIZ]; 1118 register struct file_list *swap; 1119 int generic; 1120 1121 if (fl == 0 || fl->f_type != SYSTEMSPEC) { 1122 yyerror("internal error, bad system specification"); 1123 exit(1); 1124 } 1125 swap = fl->f_next; 1126 generic = swap && swap->f_type == SWAPSPEC && eq(swap->f_fn, "generic"); 1127 if (fl->f_rootdev == NODEV && !generic) { 1128 yyerror("no root device specified"); 1129 exit(1); 1130 } 1131 /* 1132 * Default swap area to be in 'b' partition of root's 1133 * device. If root specified to be other than on 'a' 1134 * partition, give warning, something probably amiss. 1135 */ 1136 if (swap == 0 || swap->f_type != SWAPSPEC) { 1137 dev_t dev; 1138 1139 swap = newswap(); 1140 dev = fl->f_rootdev; 1141 if (minor(dev) & DEV_MASK) { 1142 (void) sprintf(buf, 1143"Warning, swap defaulted to 'b' partition with root on '%c' partition", 1144 (minor(dev) & DEV_MASK) + 'a'); 1145 yyerror(buf); 1146 } 1147 swap->f_swapdev = 1148 makedev(major(dev), (minor(dev) &~ DEV_MASK) | ('b' - 'a')); 1149 swap->f_fn = devtoname(swap->f_swapdev); 1150 mkswap(fl, swap, 0); 1151 } 1152 /* 1153 * Make sure a generic swap isn't specified, along with 1154 * other stuff (user must really be confused). 1155 */ 1156 if (generic) { 1157 if (fl->f_rootdev != NODEV) 1158 yyerror("root device specified with generic swap"); 1159 if (fl->f_argdev != NODEV) 1160 yyerror("arg device specified with generic swap"); 1161 if (fl->f_dumpdev != NODEV) 1162 yyerror("dump device specified with generic swap"); 1163 return; 1164 } 1165 /* 1166 * Default argument device and check for oddball arrangements. 1167 */ 1168 if (fl->f_argdev == NODEV) 1169 fl->f_argdev = swap->f_swapdev; 1170 if (fl->f_argdev != swap->f_swapdev) 1171 yyerror("Warning, arg device different than primary swap"); 1172 /* 1173 * Default dump device and warn if place is not a 1174 * swap area or the argument device partition. 1175 */ 1176 if (fl->f_dumpdev == NODEV) 1177 fl->f_dumpdev = swap->f_swapdev; 1178 if (fl->f_dumpdev != swap->f_swapdev && fl->f_dumpdev != fl->f_argdev) { 1179 struct file_list *p = swap->f_next; 1180 1181 for (; p && p->f_type == SWAPSPEC; p = p->f_next) 1182 if (fl->f_dumpdev == p->f_swapdev) 1183 return; 1184 (void) sprintf(buf, "Warning, orphaned dump device, %s", 1185 "do you know what you're doing"); 1186 yyerror(buf); 1187 } 1188} 1189 1190/* 1191 * Verify all devices specified in the system specification 1192 * are present in the device specifications. 1193 */ 1194void 1195verifysystemspecs(void) 1196{ 1197 register struct file_list *fl; 1198 dev_t checked[50]; 1199 register dev_t *pchecked = checked; 1200 1201 for (fl = conf_list; fl; fl = fl->f_next) { 1202 if (fl->f_type != SYSTEMSPEC) 1203 continue; 1204 if (!finddev(fl->f_rootdev)) 1205 deverror(fl->f_needs, "root"); 1206 *pchecked++ = fl->f_rootdev; 1207 pchecked = verifyswap(fl->f_next, checked, pchecked); 1208#define samedev(dev1, dev2) \ 1209 ((minor(dev1) &~ DEV_MASK) != (minor(dev2) &~ DEV_MASK)) 1210 if (!alreadychecked(fl->f_dumpdev, checked, pchecked)) { 1211 if (!finddev(fl->f_dumpdev)) 1212 deverror(fl->f_needs, "dump"); 1213 *pchecked++ = fl->f_dumpdev; 1214 } 1215 if (!alreadychecked(fl->f_argdev, checked, pchecked)) { 1216 if (!finddev(fl->f_argdev)) 1217 deverror(fl->f_needs, "arg"); 1218 *pchecked++ = fl->f_argdev; 1219 } 1220 } 1221} 1222 1223/* 1224 * Do as above, but for swap devices. 1225 */ 1226dev_t * 1227verifyswap(struct file_list *fl, dev_t checked[], dev_t *pchecked) 1228{ 1229 1230 for (;fl && fl->f_type == SWAPSPEC; fl = fl->f_next) { 1231 if (eq(fl->f_fn, "generic")) 1232 continue; 1233 if (alreadychecked(fl->f_swapdev, checked, pchecked)) 1234 continue; 1235 if (!finddev(fl->f_swapdev)) 1236 fprintf(stderr, 1237 "config: swap device %s not configured", fl->f_fn); 1238 *pchecked++ = fl->f_swapdev; 1239 } 1240 return (pchecked); 1241} 1242 1243/* 1244 * Has a device already been checked 1245 * for it's existence in the configuration? 1246 */ 1247int 1248alreadychecked(dev_t dev, dev_t list[], dev_t *last) 1249{ 1250 register dev_t *p; 1251 1252 for (p = list; p < last; p++) 1253 if (samedev(*p, dev)) 1254 return (1); 1255 return (0); 1256} 1257 1258void 1259deverror(const char *systemname, const char *devtype) 1260{ 1261 1262 fprintf(stderr, "config: %s: %s device not configured\n", 1263 systemname, devtype); 1264} 1265 1266/* 1267 * Look for the device in the list of 1268 * configured hardware devices. Must 1269 * take into account stuff wildcarded. 1270 */ 1271/*ARGSUSED*/ 1272int 1273finddev(__unused dev_t dev) 1274{ 1275 1276 /* punt on this right now */ 1277 return (1); 1278} 1279