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