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