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