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