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