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