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