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