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