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