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