]> git.saurik.com Git - apple/xnu.git/blob - SETUP/config/parser.y
xnu-1699.22.73.tar.gz
[apple/xnu.git] / SETUP / config / parser.y
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
123 struct device cur;
124 struct device *curp = 0;
125 char *temp_id;
126 char *val_id;
127 /* char *malloc(); */
128
129 int yylex(void);
130
131 int finddev(dev_t dev);
132 int alreadychecked(dev_t dev, dev_t list[], dev_t *last);
133 void deverror(const char *systemname, const char *devtype);
134 void mkconf(char *sysname);
135 struct file_list *newswap(void);
136 void mkswap(struct file_list *syslist, struct file_list *fl, int size);
137 struct device *huhcon(const char *dev);
138 void check_nexus(struct device *dev, int num);
139 void check_slot(struct device *dev, int num);
140 void checksystemspec(struct file_list *fl);
141 void verifysystemspecs(void);
142 dev_t *verifyswap(struct file_list *fl, dev_t checked[], dev_t *pchecked);
143 struct device *dconnect(const char *dev, int num);
144
145 %}
146 %%
147 Configuration:
148 Many_specs
149 { verifysystemspecs(); }
150 ;
151
152 Many_specs:
153 Many_specs Spec
154 |
155 /* lambda */
156 ;
157
158 Spec:
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
170 Config_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
283 System_spec:
284 System_id
285 { checksystemspec(*confp); }
286 | System_id System_parameter_list
287 { checksystemspec(*confp); }
288 ;
289
290 System_id:
291 CONFIG Save_id
292 { mkconf($2); }
293 ;
294
295 System_parameter_list:
296 System_parameter_list System_parameter
297 | System_parameter
298 ;
299
300 System_parameter:
301 swap_spec
302 | root_spec
303 | dump_spec
304 | arg_spec
305 ;
306
307 swap_spec:
308 SWAP optional_on swap_device_list
309 ;
310
311 swap_device_list:
312 swap_device_list AND swap_device
313 | swap_device
314 ;
315
316 swap_device:
317 swap_device_spec optional_size
318 { mkswap(*confp, $1, $2); }
319 ;
320
321 swap_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
344 root_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
356 root_device_spec:
357 device_name
358 { $$ = nametodev($1, 0, 'a'); }
359 | major_minor
360 ;
361
362 dump_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
375 dump_device_spec:
376 device_name
377 { $$ = nametodev($1, 0, 'b'); }
378 | major_minor
379 ;
380
381 arg_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
393 arg_device_spec:
394 device_name
395 { $$ = nametodev($1, 0, 'b'); }
396 | major_minor
397 ;
398
399 major_minor:
400 MAJOR NUMBER MINOR NUMBER
401 { $$ = makedev($2, $4); }
402 ;
403
404 optional_on:
405 ON
406 | /* empty */
407 ;
408
409 optional_size:
410 SIZE NUMBER
411 { $$ = $2; }
412 | /* empty */
413 { $$ = 0; }
414 ;
415
416 device_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
435 Opt_list:
436 Opt_list COMMA Option
437 |
438 Option
439 ;
440
441 Option:
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
471 Opt_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
483 Save_id:
484 ID
485 { $$ = temp_id = ns($1); }
486 ;
487
488 Mkopt_list:
489 Mkopt_list COMMA Mkoption
490 |
491 Mkoption
492 ;
493
494 Mkoption:
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
520 Dev:
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
580 Device_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
617 Dev_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
632 Init_dev:
633 /* lambda */
634 { init_dev(&cur); };
635
636 Dev_info:
637 Con_info Info_list
638 |
639 /* lambda */
640 ;
641
642 Con_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
665 Info_list:
666 Info_list Info
667 |
668 /* lambda */
669 ;
670
671 Info:
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
733 Value:
734 NUMBER
735 |
736 MINUS NUMBER
737 { $$ = -($2); }
738 ;
739
740 Int_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
752 Vec_spec:
753 VECTOR Id_list
754 { cur.d_vec = $2; };
755
756
757 Id_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
785 void
786 yyerror(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 */
794 char *
795 ns(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 */
807 void
808 newdev(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 */
825 void
826 mkconf(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
844 struct file_list *
845 newswap(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 */
861 void
862 mkswap(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 */
900 struct device *
901 dconnect(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 */
926 struct device *
927 huhcon(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
984 void
985 init_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 */
1008 void
1009 check_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
1080 void
1081 check_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 */
1114 void
1115 checksystemspec(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 */
1194 void
1195 verifysystemspecs(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 */
1226 dev_t *
1227 verifyswap(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 */
1247 int
1248 alreadychecked(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
1258 void
1259 deverror(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*/
1272 int
1273 finddev(__unused dev_t dev)
1274 {
1275
1276 /* punt on this right now */
1277 return (1);
1278 }