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