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