1/*
2 * Mach Operating System
3 * Copyright (c) 1990 Carnegie-Mellon University
4 * Copyright (c) 1989 Carnegie-Mellon University
5 * Copyright (c) 1988 Carnegie-Mellon University
6 * Copyright (c) 1987 Carnegie-Mellon University
7 * All rights reserved.  The CMU software License Agreement specifies
8 * the terms and conditions for use and redistribution.
9 */
10
11/*
12 * Copyright (c) 1988 Regents of the University of California.
13 * All rights reserved.
14 *
15 * Redistribution and use in source and binary forms are permitted
16 * provided that the above copyright notice and this paragraph are
17 * duplicated in all such forms and that any documentation,
18 * advertising materials, and other materials related to such
19 * distribution and use acknowledge that the software was developed
20 * by the University of California, Berkeley.  The name of the
21 * University may not be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
25 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26 *
27 *	@(#)config.y	5.8 (Berkeley) 6/18/88
28 */
29
30%union {
31	char	*str;
32	int	val;
33	struct	file_list *file;
34	struct	idlst *lst;
35}
36
37%token	ADDRMOD
38%token	AND
39%token	ANY
40%token	ARGS
41%token	AT
42%token	BIN
43%token	BUILDDIR
44%token	COMMA
45%token	CONFIG
46%token	CONFIGDIR
47%token	CONTROLLER
48%token	CPU
49%token	CSR
50%token	DEVICE
51%token	DISK
52%token	DRIVE
53%token	DST
54%token	DUMPS
55%token	EQUALS
56%token	FLAGS
57%token	HZ
58%token	IDENT
59%token	INIT
60%token	MACHINE
61%token	MAJOR
62%token	MASTER
63%token	MAXUSERS
64%token	MAXDSIZ
65%token	MBA
66%token	MBII
67%token	MINOR
68%token	MINUS
69%token	NEXUS
70%token	OBJECTDIR
71%token	ON
72%token	OPTIONS
73%token	MAKEOPTIONS
74%token	PRIORITY
75%token	PROFILE
76%token	PSEUDO_DEVICE
77%token	ROOT
78%token	SEMICOLON
79%token	SIZE
80%token	SLAVE
81%token	SOURCEDIR
82%token	SWAP
83%token	TIMEZONE
84%token	TRACE
85%token	UBA
86%token	VECTOR
87%token	VME
88%token  VME16D16
89%token  VME24D16
90%token  VME32D16
91%token  VME16D32
92%token  VME24D32
93%token  VME32D32
94
95/* following 3 are unique to CMU */
96%token	LUN
97%token	SLOT
98%token	TAPE
99
100%token	<str>	ID
101%token	<val>	NUMBER
102%token	<val>	FPNUMBER
103
104%type	<str>	Save_id
105%type	<str>	Opt_value
106%type	<str>	Dev
107%type	<lst>	Id_list
108%type	<val>	optional_size
109%type	<str>	device_name
110%type	<val>	major_minor
111%type	<val>	arg_device_spec
112%type	<val>	root_device_spec
113%type	<val>	dump_device_spec
114%type	<file>	swap_device_spec
115%type	<val>	Value
116
117%{
118
119#include "config.h"
120#include <ctype.h>
121#include <stdio.h>
122
123struct	device cur;
124struct	device *curp = 0;
125char	*temp_id;
126char	*val_id;
127/* char	*malloc(); */
128
129int yylex(void);
130
131int finddev(dev_t dev);
132int alreadychecked(dev_t dev, dev_t list[], dev_t *last);
133void deverror(const char *systemname, const char *devtype);
134void mkconf(char *sysname);
135struct file_list *newswap(void);
136void mkswap(struct file_list *syslist, struct file_list *fl, int size);
137struct device *huhcon(const char *dev);
138void check_nexus(struct device *dev, int num);
139void check_slot(struct device *dev, int num);
140void checksystemspec(struct file_list *fl);
141void verifysystemspecs(void);
142dev_t *verifyswap(struct file_list *fl, dev_t checked[], dev_t *pchecked);
143struct device *dconnect(const char *dev, int num);
144
145%}
146%%
147Configuration:
148	Many_specs
149		{ verifysystemspecs(); }
150		;
151
152Many_specs:
153	Many_specs Spec
154		|
155	/* lambda */
156		;
157
158Spec:
159	Device_spec SEMICOLON
160	      { newdev(&cur); } |
161	Config_spec SEMICOLON
162		|
163	TRACE SEMICOLON
164	      { do_trace = !do_trace; } |
165	SEMICOLON
166		|
167	error SEMICOLON
168		;
169
170Config_spec:
171	MACHINE Save_id
172	    {
173		if (!strcmp($2, "vax")) {
174			machine = MACHINE_VAX;
175			machinename = "vax";
176		} else if (!strcmp($2, "sun")) {
177			/* default to Sun 3 */
178			machine = MACHINE_SUN3;
179			machinename = "sun3";
180		} else if (!strcmp($2, "sun2")) {
181			machine = MACHINE_SUN2;
182			machinename = "sun2";
183		} else if (!strcmp($2, "sun3")) {
184			machine = MACHINE_SUN3;
185			machinename = "sun3";
186		} else if (!strcmp($2, "sun4")) {
187			machine = MACHINE_SUN4;
188			machinename = "sun4";
189		} else if (!strcmp($2, "romp")) {
190			machine = MACHINE_ROMP;
191			machinename = "romp";
192		} else if (!strcmp($2, "ca")) {
193			machine = MACHINE_ROMP;
194			machinename = "ca";
195		} else if (!strcmp($2, "mmax")) {
196			machine = MACHINE_MMAX;
197			machinename = "mmax";
198		} else if (!strcmp($2, "sqt")) {
199			machine = MACHINE_SQT;
200			machinename = "sqt";
201		} else if (!strcmp($2, "i")) {
202			machine = MACHINE_I386;
203			machinename = "i386";
204		} else if (!strcmp($2, "i386")) {
205			machine = MACHINE_I386;
206			machinename = "i386";
207		} else if (!strcmp($2, "ix")) {
208			machine = MACHINE_IX;
209			machinename = "ix";
210		} else if (!strcmp($2, "mipsy")) {
211			machine = MACHINE_MIPSY;
212			machinename = "mipsy";
213		} else if (!strcmp($2, "mips")) {
214			machine = MACHINE_MIPS;
215			machinename = "mips";
216		} else if (!strcmp($2, "i860")) {
217			machine = MACHINE_I860;
218			machinename = "i860";
219		} else if (!strcmp($2, "m68k")) {
220			machine = MACHINE_M68K;
221			machinename = "m68k";
222		} else if (!strcmp($2, "m88k")) {
223			machine = MACHINE_M88K;
224			machinename = "m88k";
225		} else if (!strcmp($2, "m98k")) {
226			machine = MACHINE_M98K;
227			machinename = "m98k";
228		} else if (!strcmp($2, "hppa")) {
229			machine = MACHINE_HPPA;
230			machinename = "hppa";
231		} else if (!strcmp($2, "sparc")) {
232			machine = MACHINE_SPARC;
233			machinename = "sparc";
234		} else if (!strcmp($2, "ppc")) {
235			machine = MACHINE_PPC;
236			machinename = "ppc";
237		} else if (!strcmp($2, "arm")) {
238			machine = MACHINE_ARM;
239			machinename = "arm";
240		} else if (!strcmp($2, "x86_64")) {
241			machine = MACHINE_X86_64;
242			machinename = "x86_64";
243		} else
244			yyerror("Unknown machine type");
245	      } |
246	CPU Save_id
247	      {
248		struct cputype *cp =
249		    (struct cputype *)malloc(sizeof (struct cputype));
250		cp->cpu_name = ns($2);
251		cp->cpu_next = cputype;
252		cputype = cp;
253		free(temp_id);
254	      } |
255	OPTIONS Opt_list
256		|
257	MAKEOPTIONS Mkopt_list
258		|
259	IDENT ID
260	      { ident = ns($2); }
261		|
262	System_spec
263		|
264	MAXUSERS NUMBER
265	      { maxusers = $2; }
266		|
267	BUILDDIR Save_id
268		{ build_directory = ns($2); }
269		|
270	CONFIGDIR Save_id
271		{ config_directory = ns($2); }
272		|
273	OBJECTDIR Save_id
274		{ object_directory = ns($2); }
275		|
276	SOURCEDIR Save_id
277		{ source_directory = ns($2); }
278		|
279	PROFILE
280		{ profiling++; }
281		;
282
283System_spec:
284	  System_id
285		{ checksystemspec(*confp); }
286	| System_id System_parameter_list
287		{ checksystemspec(*confp); }
288	;
289
290System_id:
291	  CONFIG Save_id
292		{ mkconf($2); }
293	;
294
295System_parameter_list:
296	  System_parameter_list System_parameter
297	| System_parameter
298	;
299
300System_parameter:
301	  swap_spec
302	| root_spec
303	| dump_spec
304	| arg_spec
305	;
306
307swap_spec:
308	  SWAP optional_on swap_device_list
309	;
310
311swap_device_list:
312	  swap_device_list AND swap_device
313	| swap_device
314	;
315
316swap_device:
317	  swap_device_spec optional_size
318	      { mkswap(*confp, $1, $2); }
319	;
320
321swap_device_spec:
322	  device_name
323		{
324			struct file_list *fl = newswap();
325
326			if (eq($1, "generic"))
327				fl->f_fn = $1;
328			else {
329				fl->f_swapdev = nametodev($1, 0, 'b');
330				fl->f_fn = devtoname(fl->f_swapdev);
331			}
332			$$ = fl;
333		}
334	| major_minor
335		{
336			struct file_list *fl = newswap();
337
338			fl->f_swapdev = $1;
339			fl->f_fn = devtoname($1);
340			$$ = fl;
341		}
342	;
343
344root_spec:
345	  ROOT optional_on root_device_spec
346		{
347			struct file_list *fl = *confp;
348
349			if (fl && fl->f_rootdev != NODEV)
350				yyerror("extraneous root device specification");
351			else
352				fl->f_rootdev = $3;
353		}
354	;
355
356root_device_spec:
357	  device_name
358		{ $$ = nametodev($1, 0, 'a'); }
359	| major_minor
360	;
361
362dump_spec:
363	  DUMPS optional_on dump_device_spec
364		{
365			struct file_list *fl = *confp;
366
367			if (fl && fl->f_dumpdev != NODEV)
368				yyerror("extraneous dump device specification");
369			else
370				fl->f_dumpdev = $3;
371		}
372
373	;
374
375dump_device_spec:
376	  device_name
377		{ $$ = nametodev($1, 0, 'b'); }
378	| major_minor
379	;
380
381arg_spec:
382	  ARGS optional_on arg_device_spec
383		{
384			struct file_list *fl = *confp;
385
386			if (fl && fl->f_argdev != NODEV)
387				yyerror("extraneous arg device specification");
388			else
389				fl->f_argdev = $3;
390		}
391	;
392
393arg_device_spec:
394	  device_name
395		{ $$ = nametodev($1, 0, 'b'); }
396	| major_minor
397	;
398
399major_minor:
400	  MAJOR NUMBER MINOR NUMBER
401		{ $$ = makedev($2, $4); }
402	;
403
404optional_on:
405	  ON
406	| /* empty */
407	;
408
409optional_size:
410	  SIZE NUMBER
411	      { $$ = $2; }
412	| /* empty */
413	      { $$ = 0; }
414	;
415
416device_name:
417	  Save_id
418		{ $$ = $1; }
419	| Save_id NUMBER
420		{
421			char buf[80];
422
423			(void) sprintf(buf, "%s%d", $1, $2);
424			$$ = ns(buf); free($1);
425		}
426	| Save_id NUMBER ID
427		{
428			char buf[80];
429
430			(void) sprintf(buf, "%s%d%s", $1, $2, $3);
431			$$ = ns(buf); free($1);
432		}
433	;
434
435Opt_list:
436	Opt_list COMMA Option
437		|
438	Option
439		;
440
441Option:
442	Save_id
443	      {
444		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
445		op->op_name = ns($1);
446		op->op_next = (struct opt *) 0;
447		op->op_value = 0;
448		if (opt == (struct opt *) 0)
449			opt = op;
450		else
451			opt_tail->op_next = op;
452		opt_tail = op;
453		free(temp_id);
454	      } |
455	Save_id EQUALS Opt_value
456	      {
457		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
458		op->op_name = ns($1);
459		op->op_next = (struct opt *) 0;
460		op->op_value = ns($3);
461		if (opt == (struct opt *) 0)
462			opt = op;
463		else
464			opt_tail->op_next = op;
465		opt_tail = op;
466		free(temp_id);
467		if (val_id)
468			free(val_id);
469	      } ;
470
471Opt_value:
472	ID
473	      { $$ = val_id = ns($1); } |
474	NUMBER
475	      { char nb[16];
476	          (void) sprintf(nb, "%u", $1);
477	      	  $$ = val_id = ns(nb);
478	      } |
479	/* lambda from MIPS -- WHY */
480	      { $$ = val_id = ns(""); }
481	      ;
482
483Save_id:
484	ID
485	      { $$ = temp_id = ns($1); }
486	;
487
488Mkopt_list:
489	Mkopt_list COMMA Mkoption
490		|
491	Mkoption
492		;
493
494Mkoption:
495	Save_id
496	      {
497		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
498		op->op_name = ns($1);
499		op->op_next =  (struct opt *) 0;
500		op->op_value = 0;
501		mkopt = op;
502		free(temp_id);
503	      } |
504	Save_id EQUALS Opt_value
505	      {
506		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
507		op->op_name = ns($1);
508		op->op_next =  (struct opt *) 0;
509		op->op_value = ns($3);
510		if (mkopt == (struct opt *) 0)
511			mkopt = op;
512		else
513			mkopt_tail->op_next = op;
514		mkopt_tail = op;
515		free(temp_id);
516		if (val_id)
517			free(val_id);
518	      } ;
519
520Dev:
521	UBA
522	      { $$ = ns("uba"); } |
523	MBA
524	      { $$ = ns("mba"); } |
525        VME16D16
526	      {
527		if (machine != MACHINE_SUN2 && machine != MACHINE_SUN3
528		    && machine != MACHINE_SUN4)
529			yyerror("wrong machine type for vme16d16");
530		$$ = ns("vme16d16");
531		} |
532	VME24D16
533	      {
534		if (machine != MACHINE_SUN2 && machine != MACHINE_SUN3
535		    && machine != MACHINE_SUN4)
536			yyerror("wrong machine type for vme24d16");
537			$$ = ns("vme24d16");
538		} |
539	VME32D16
540	      {
541		if (machine != MACHINE_SUN3 && machine != MACHINE_SUN4)
542
543                        yyerror("wrong machine type for vme32d16");
544                $$ = ns("vme32d16");
545                } |
546        VME16D32
547              {
548                if (machine != MACHINE_SUN3  && machine != MACHINE_SUN4)
549                        yyerror("wrong machine type for vme16d32");
550                $$ = ns("vme16d32");
551                } |
552        VME24D32
553              {
554		if (machine != MACHINE_SUN3 && machine != MACHINE_SUN4)
555			yyerror("wrong machine type for vme24d32");
556		$$ = ns("vme24d32");
557		} |
558        VME32D32
559	      {
560		if (machine != MACHINE_SUN3 && machine != MACHINE_SUN4)
561			yyerror("wrong machine type for vme32d32");
562		$$ = ns("vme32d32");
563		} |
564	VME
565	      {
566		if (machine != MACHINE_MIPSY && machine != MACHINE_MIPS)
567			yyerror("wrong machine type for vme");
568			$$ = ns("vme");
569		} |
570	MBII
571	      {
572		if (machine != MACHINE_MIPSY && machine != MACHINE_MIPS)
573			yyerror("wrong machine type for mbii");
574			$$ = ns("mbii");
575		} |
576	ID
577	      { $$ = ns($1); }
578	;
579
580Device_spec:
581	DEVICE Dev_name Dev_info Int_spec
582	      { cur.d_type = DEVICE; } |
583	MASTER Dev_name Dev_info Int_spec
584	      { cur.d_type = MASTER; } |
585	DISK Dev_name Dev_info Int_spec
586	      { cur.d_dk = 1; cur.d_type = DEVICE; } |
587/* TAPE rule is unique to CMU */
588	TAPE Dev_name Dev_info Int_spec
589	      { cur.d_type = DEVICE; } |
590	CONTROLLER Dev_name Dev_info Int_spec
591	      { cur.d_type = CONTROLLER; } |
592	PSEUDO_DEVICE Init_dev Dev
593	      {
594		cur.d_name = $3;
595		cur.d_type = PSEUDO_DEVICE;
596		} |
597	PSEUDO_DEVICE Init_dev Dev NUMBER
598	      {
599		cur.d_name = $3;
600		cur.d_type = PSEUDO_DEVICE;
601		cur.d_slave = $4;
602		} |
603	PSEUDO_DEVICE Init_dev Dev INIT ID
604	      {
605		cur.d_name = $3;
606		cur.d_type = PSEUDO_DEVICE;
607		cur.d_init = ns($5);
608		} |
609	PSEUDO_DEVICE Init_dev Dev NUMBER INIT ID
610	      {
611		cur.d_name = $3;
612		cur.d_type = PSEUDO_DEVICE;
613		cur.d_slave = $4;
614		cur.d_init = ns($6);
615		};
616
617Dev_name:
618	Init_dev Dev NUMBER
619	      {
620		cur.d_name = $2;
621		if (eq($2, "mba"))
622			seen_mba = 1;
623		else if (eq($2, "uba"))
624			seen_uba = 1;
625		else if (eq($2, "mbii"))
626			seen_mbii = 1;
627		else if (eq($2, "vme"))
628			seen_vme = 1;
629		cur.d_unit = $3;
630		};
631
632Init_dev:
633	/* lambda */
634	      { init_dev(&cur); };
635
636Dev_info:
637	Con_info Info_list
638		|
639	/* lambda */
640		;
641
642Con_info:
643	AT Dev NUMBER
644	      {
645		if (eq(cur.d_name, "mba") || eq(cur.d_name, "uba")
646		    || eq(cur.d_name, "mbii") || eq(cur.d_name, "vme")) {
647			(void) sprintf(errbuf,
648			    "%s must be connected to a nexus", cur.d_name);
649			yyerror(errbuf);
650		}
651		cur.d_conn = dconnect($2, $3);
652		if (machine == MACHINE_SQT)
653			dev_param(&cur, "index", cur.d_unit);
654		} |
655/* AT SLOT NUMBER rule is unique to CMU */
656	AT SLOT NUMBER
657	      {
658		check_slot(&cur, $3);
659		cur.d_addr = $3;
660		cur.d_conn = TO_SLOT;
661		 } |
662	AT NEXUS NUMBER
663	      { check_nexus(&cur, $3); cur.d_conn = TO_NEXUS; };
664
665Info_list:
666	Info_list Info
667		|
668	/* lambda */
669		;
670
671Info:
672	CSR NUMBER
673	      {
674		cur.d_addr = $2;
675		if (machine == MACHINE_SQT) {
676			dev_param(&cur, "csr", $2);
677		}
678		} |
679	DRIVE NUMBER
680	      {
681			cur.d_drive = $2;
682			if (machine == MACHINE_SQT) {
683				dev_param(&cur, "drive", $2);
684			}
685		} |
686	SLAVE NUMBER
687	      {
688		if (cur.d_conn != 0 && cur.d_conn != TO_NEXUS &&
689		    cur.d_conn->d_type == MASTER)
690			cur.d_slave = $2;
691		else
692			yyerror("can't specify slave--not to master");
693		} |
694/* MIPS */
695	ADDRMOD NUMBER
696	      { cur.d_addrmod = $2; } |
697/* LUN NUMBER rule is unique to CMU */
698	LUN NUMBER
699	      {
700		if ((cur.d_conn != 0) && (cur.d_conn != TO_SLOT) &&
701			(cur.d_conn->d_type == CONTROLLER)) {
702			cur.d_addr = $2;
703		}
704		else {
705			yyerror("device requires controller card");
706		    }
707		} |
708	FLAGS NUMBER
709	      {
710		cur.d_flags = $2;
711		if (machine == MACHINE_SQT) {
712			dev_param(&cur, "flags", $2);
713		}
714	      } |
715	BIN NUMBER
716	      {
717		 if (machine != MACHINE_SQT)
718			yyerror("bin specification only valid on Sequent Balance");
719		 if ($2 < 1 || $2 > 7)
720			yyerror("bogus bin number");
721		 else {
722			cur.d_bin = $2;
723			dev_param(&cur, "bin", $2);
724		}
725	       } |
726	Dev Value
727	      {
728		if (machine != MACHINE_SQT)
729			yyerror("bad device spec");
730		dev_param(&cur, $1, $2);
731		};
732
733Value:
734	NUMBER
735	      |
736	MINUS NUMBER
737	      { $$ = -($2); }
738	;
739
740Int_spec:
741        Vec_spec
742	      { cur.d_pri = 0; } |
743	PRIORITY NUMBER
744	      { cur.d_pri = $2; } |
745        PRIORITY NUMBER Vec_spec
746	      { cur.d_pri = $2; } |
747        Vec_spec PRIORITY NUMBER
748	      { cur.d_pri = $3; } |
749	/* lambda */
750		;
751
752Vec_spec:
753        VECTOR Id_list
754	      { cur.d_vec = $2; };
755
756
757Id_list:
758	Save_id
759	      {
760		struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
761		a->id = $1; a->id_next = 0; $$ = a;
762		a->id_vec = 0;
763		} |
764	Save_id Id_list
765		{
766		struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
767	        a->id = $1; a->id_next = $2; $$ = a;
768		a->id_vec = 0;
769		} |
770        Save_id NUMBER
771	      {
772		struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
773		a->id_next = 0; a->id = $1; $$ = a;
774		a->id_vec = $2;
775		} |
776        Save_id NUMBER Id_list
777	      {
778		struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
779		a->id_next = $3; a->id = $1; $$ = a;
780		a->id_vec = $2;
781		};
782
783%%
784
785void
786yyerror(const char *s)
787{
788	fprintf(stderr, "config: line %d: %s\n", yyline, s);
789}
790
791/*
792 * return the passed string in a new space
793 */
794char *
795ns(const char *str)
796{
797	register char *cp;
798
799	cp = malloc((unsigned)(strlen(str)+1));
800	(void) strcpy(cp, str);
801	return (cp);
802}
803
804/*
805 * add a device to the list of devices
806 */
807void
808newdev(struct device *dp)
809{
810	register struct device *np;
811
812	np = (struct device *) malloc(sizeof *np);
813	*np = *dp;
814	if (curp == 0)
815		dtab = np;
816	else
817		curp->d_next = np;
818	curp = np;
819	curp->d_next = 0;
820}
821
822/*
823 * note that a configuration should be made
824 */
825void
826mkconf(char *sysname)
827{
828	register struct file_list *fl, **flp;
829
830	fl = (struct file_list *) malloc(sizeof *fl);
831	fl->f_type = SYSTEMSPEC;
832	fl->f_needs = sysname;
833	fl->f_rootdev = NODEV;
834	fl->f_argdev = NODEV;
835	fl->f_dumpdev = NODEV;
836	fl->f_fn = 0;
837	fl->f_next = 0;
838	for (flp = confp; *flp; flp = &(*flp)->f_next)
839		;
840	*flp = fl;
841	confp = flp;
842}
843
844struct file_list *
845newswap(void)
846{
847	struct file_list *fl = (struct file_list *)malloc(sizeof (*fl));
848
849	fl->f_type = SWAPSPEC;
850	fl->f_next = 0;
851	fl->f_swapdev = NODEV;
852	fl->f_swapsize = 0;
853	fl->f_needs = 0;
854	fl->f_fn = 0;
855	return (fl);
856}
857
858/*
859 * Add a swap device to the system's configuration
860 */
861void
862mkswap(struct file_list *syslist, struct file_list *fl, int size)
863{
864	register struct file_list **flp;
865
866	if (syslist == 0 || syslist->f_type != SYSTEMSPEC) {
867		yyerror("\"swap\" spec precedes \"config\" specification");
868		return;
869	}
870	if (size < 0) {
871		yyerror("illegal swap partition size");
872		return;
873	}
874	/*
875	 * Append swap description to the end of the list.
876	 */
877	flp = &syslist->f_next;
878	for (; *flp && (*flp)->f_type == SWAPSPEC; flp = &(*flp)->f_next)
879		;
880	fl->f_next = *flp;
881	*flp = fl;
882	fl->f_swapsize = size;
883	/*
884	 * If first swap device for this system,
885	 * set up f_fn field to insure swap
886	 * files are created with unique names.
887	 */
888	if (syslist->f_fn)
889		return;
890	if (eq(fl->f_fn, "generic"))
891		syslist->f_fn = ns(fl->f_fn);
892	else
893		syslist->f_fn = ns(syslist->f_needs);
894}
895
896/*
897 * find the pointer to connect to the given device and number.
898 * returns 0 if no such device and prints an error message
899 */
900struct device *
901dconnect(const char *dev, int num)
902{
903	register struct device *dp;
904
905	if (num == QUES)
906		return (huhcon(dev));
907	for (dp = dtab; dp != 0; dp = dp->d_next) {
908		if ((num != dp->d_unit) || !eq(dev, dp->d_name))
909			continue;
910		if (dp->d_type != CONTROLLER && dp->d_type != MASTER) {
911			(void) sprintf(errbuf,
912			    "%s connected to non-controller", dev);
913			yyerror(errbuf);
914			return (0);
915		}
916		return (dp);
917	}
918	(void) sprintf(errbuf, "%s %d not defined", dev, num);
919	yyerror(errbuf);
920	return (0);
921}
922
923/*
924 * connect to an unspecific thing
925 */
926struct device *
927huhcon(const char *dev)
928{
929	register struct device *dp, *dcp;
930	struct device rdev;	/* only used if dp is NULL */
931	int oldtype;
932
933	memset(&rdev, 0, sizeof rdev);
934
935	/*
936	 * First make certain that there are some of these to wildcard on
937	 */
938	for (dp = dtab; dp != 0; dp = dp->d_next)
939		if (eq(dp->d_name, dev))
940			break;
941	if (dp == 0) {
942		(void) sprintf(errbuf, "no %s's to wildcard", dev);
943		yyerror(errbuf);
944		return (0);
945	}
946	oldtype = dp->d_type;
947	dcp = dp->d_conn;
948	/*
949	 * Now see if there is already a wildcard entry for this device
950	 * (e.g. Search for a "uba ?")
951	 */
952	for (; dp != 0; dp = dp->d_next)
953		if (eq(dev, dp->d_name) && dp->d_unit == -1)
954			break;
955	/*
956	 * If there isn't, make one because everything needs to be connected
957	 * to something.
958	 */
959	if (dp == 0) {
960		dp = &rdev;
961		init_dev(dp);
962		dp->d_unit = QUES;
963		dp->d_name = ns(dev);
964		dp->d_type = oldtype;
965		newdev(dp);
966		dp = curp;
967		/*
968		 * Connect it to the same thing that other similar things are
969		 * connected to, but make sure it is a wildcard unit
970		 * (e.g. up connected to sc ?, here we make connect sc? to a
971		 * uba?).  If other things like this are on the NEXUS or
972		 * if they aren't connected to anything, then make the same
973		 * connection, else call ourself to connect to another
974		 * unspecific device.
975		 */
976		if (dcp == TO_NEXUS || dcp == 0)
977			dp->d_conn = dcp;
978		else
979			dp->d_conn = dconnect(dcp->d_name, QUES);
980	}
981	return (dp);
982}
983
984void
985init_dev(struct device *dp)
986{
987
988	dp->d_name = "OHNO!!!";
989	dp->d_type = DEVICE;
990	dp->d_conn = 0;
991	dp->d_vec = 0;
992	dp->d_addr = dp->d_pri = dp->d_flags = dp->d_dk = 0;
993	dp->d_slave = dp->d_drive = dp->d_unit = UNKNOWN;
994	if (machine == MACHINE_SUN2 || machine == MACHINE_SUN3
995	    || machine == MACHINE_SUN4){
996		dp->d_addr = UNKNOWN;
997		dp->d_mach = dp->d_bus = 0;
998	}
999	if (machine == MACHINE_MIPSY || machine == MACHINE_MIPS){
1000		dp->d_addrmod = 0;
1001	}
1002	dp->d_init = 0;
1003}
1004
1005/*
1006 * make certain that this is a reasonable type of thing to connect to a nexus
1007 */
1008void
1009check_nexus(struct device *dev, int num)
1010{
1011
1012	switch (machine) {
1013
1014	case MACHINE_VAX:
1015		if (!eq(dev->d_name, "uba") && !eq(dev->d_name, "mba"))
1016			yyerror("only uba's and mba's should be connected to the nexus");
1017		if (num != QUES)
1018			yyerror("can't give specific nexus numbers");
1019		break;
1020
1021	case MACHINE_SUN:
1022		if (!eq(dev->d_name, "mb"))
1023			yyerror("only mb's should be connected to the nexus");
1024		break;
1025
1026	case MACHINE_ROMP:
1027		if (!eq(dev->d_name, "iocc"))
1028			yyerror("only iocc's should be connected to the nexus");
1029		break;
1030        case MACHINE_SUN2:
1031		if (!eq(dev->d_name, "virtual") &&
1032		    !eq(dev->d_name, "obmem") &&
1033		    !eq(dev->d_name, "obio") &&
1034		    !eq(dev->d_name, "mbmem") &&
1035		    !eq(dev->d_name, "mbio") &&
1036		    !eq(dev->d_name, "vme16d16") &&
1037		    !eq(dev->d_name, "vme24d16")) {
1038			(void)sprintf(errbuf,
1039			    "unknown bus type `%s' for nexus connection on %s",
1040			    dev->d_name, machinename);
1041			yyerror(errbuf);
1042		}
1043
1044	case MACHINE_MMAX:
1045		yyerror("don't grok 'nexus' on mmax -- try 'slot'.");
1046		break;
1047        case MACHINE_SUN3:
1048        case MACHINE_SUN4:
1049		if (!eq(dev->d_name, "virtual") &&
1050		    !eq(dev->d_name, "obmem") &&
1051		    !eq(dev->d_name, "obio") &&
1052		    !eq(dev->d_name, "mbmem") &&
1053		    !eq(dev->d_name, "mbio") &&
1054		    !eq(dev->d_name, "vme16d16") &&
1055		    !eq(dev->d_name, "vme24d16") &&
1056                    !eq(dev->d_name, "vme32d16") &&
1057		    !eq(dev->d_name, "vme16d32") &&
1058		    !eq(dev->d_name, "vme24d32") &&
1059		    !eq(dev->d_name, "vme32d32")) {
1060			(void)sprintf(errbuf,
1061			    "unknown bus type `%s' for nexus connection on %s",
1062			    dev->d_name, machinename);
1063			yyerror(errbuf);
1064		}
1065		break;
1066	case MACHINE_MIPSY:
1067	case MACHINE_MIPS:
1068		if (!eq(dev->d_name, "vme") && !eq(dev->d_name, "mbii"))
1069			yyerror("only vme's and mbii's should be connected to the nexus");
1070		if (num != QUES)
1071			yyerror("can't give specific nexus numbers");
1072		break;
1073	}
1074}
1075
1076/*
1077 * make certain that this is a reasonable type of thing to connect to a slot
1078 */
1079
1080void
1081check_slot(struct device *dev, int num)
1082{
1083
1084	switch (machine) {
1085
1086	case MACHINE_MMAX:
1087		if (!eq(dev->d_name, "emc"))
1088			yyerror("only emc's plug into backplane slots.");
1089		if (num == QUES)
1090			yyerror("specific slot numbers must be given");
1091		break;
1092
1093	case MACHINE_SQT:
1094		if (!eq(dev->d_name, "mbad") &&
1095		    !eq(dev->d_name, "zdc") &&
1096		    !eq(dev->d_name, "sec")) {
1097			(void)sprintf(errbuf,
1098			    "unknown bus type `%s' for slot on %s",
1099			    dev->d_name, machinename);
1100			yyerror(errbuf);
1101		}
1102		break;
1103
1104	default:
1105		yyerror("don't grok 'slot' for this machine -- try 'nexus'.");
1106		break;
1107	}
1108}
1109
1110/*
1111 * Check system specification and apply defaulting
1112 * rules on root, argument, dump, and swap devices.
1113 */
1114void
1115checksystemspec(struct file_list *fl)
1116{
1117	char buf[BUFSIZ];
1118	register struct file_list *swap;
1119	int generic;
1120
1121	if (fl == 0 || fl->f_type != SYSTEMSPEC) {
1122		yyerror("internal error, bad system specification");
1123		exit(1);
1124	}
1125	swap = fl->f_next;
1126	generic = swap && swap->f_type == SWAPSPEC && eq(swap->f_fn, "generic");
1127	if (fl->f_rootdev == NODEV && !generic) {
1128		yyerror("no root device specified");
1129		exit(1);
1130	}
1131	/*
1132	 * Default swap area to be in 'b' partition of root's
1133	 * device.  If root specified to be other than on 'a'
1134	 * partition, give warning, something probably amiss.
1135	 */
1136	if (swap == 0 || swap->f_type != SWAPSPEC) {
1137		dev_t dev;
1138
1139		swap = newswap();
1140		dev = fl->f_rootdev;
1141		if (minor(dev) & DEV_MASK) {
1142			(void) sprintf(buf,
1143"Warning, swap defaulted to 'b' partition with root on '%c' partition",
1144				(minor(dev) & DEV_MASK) + 'a');
1145			yyerror(buf);
1146		}
1147		swap->f_swapdev =
1148		   makedev(major(dev), (minor(dev) &~ DEV_MASK) | ('b' - 'a'));
1149		swap->f_fn = devtoname(swap->f_swapdev);
1150		mkswap(fl, swap, 0);
1151	}
1152	/*
1153	 * Make sure a generic swap isn't specified, along with
1154	 * other stuff (user must really be confused).
1155	 */
1156	if (generic) {
1157		if (fl->f_rootdev != NODEV)
1158			yyerror("root device specified with generic swap");
1159		if (fl->f_argdev != NODEV)
1160			yyerror("arg device specified with generic swap");
1161		if (fl->f_dumpdev != NODEV)
1162			yyerror("dump device specified with generic swap");
1163		return;
1164	}
1165	/*
1166	 * Default argument device and check for oddball arrangements.
1167	 */
1168	if (fl->f_argdev == NODEV)
1169		fl->f_argdev = swap->f_swapdev;
1170	if (fl->f_argdev != swap->f_swapdev)
1171		yyerror("Warning, arg device different than primary swap");
1172	/*
1173	 * Default dump device and warn if place is not a
1174	 * swap area or the argument device partition.
1175	 */
1176	if (fl->f_dumpdev == NODEV)
1177		fl->f_dumpdev = swap->f_swapdev;
1178	if (fl->f_dumpdev != swap->f_swapdev && fl->f_dumpdev != fl->f_argdev) {
1179		struct file_list *p = swap->f_next;
1180
1181		for (; p && p->f_type == SWAPSPEC; p = p->f_next)
1182			if (fl->f_dumpdev == p->f_swapdev)
1183				return;
1184		(void) sprintf(buf, "Warning, orphaned dump device, %s",
1185			"do you know what you're doing");
1186		yyerror(buf);
1187	}
1188}
1189
1190/*
1191 * Verify all devices specified in the system specification
1192 * are present in the device specifications.
1193 */
1194void
1195verifysystemspecs(void)
1196{
1197	register struct file_list *fl;
1198	dev_t checked[50];
1199	register dev_t *pchecked = checked;
1200
1201	for (fl = conf_list; fl; fl = fl->f_next) {
1202		if (fl->f_type != SYSTEMSPEC)
1203			continue;
1204		if (!finddev(fl->f_rootdev))
1205			deverror(fl->f_needs, "root");
1206		*pchecked++ = fl->f_rootdev;
1207		pchecked = verifyswap(fl->f_next, checked, pchecked);
1208#define	samedev(dev1, dev2) \
1209	((minor(dev1) &~ DEV_MASK) != (minor(dev2) &~ DEV_MASK))
1210		if (!alreadychecked(fl->f_dumpdev, checked, pchecked)) {
1211			if (!finddev(fl->f_dumpdev))
1212				deverror(fl->f_needs, "dump");
1213			*pchecked++ = fl->f_dumpdev;
1214		}
1215		if (!alreadychecked(fl->f_argdev, checked, pchecked)) {
1216			if (!finddev(fl->f_argdev))
1217				deverror(fl->f_needs, "arg");
1218			*pchecked++ = fl->f_argdev;
1219		}
1220	}
1221}
1222
1223/*
1224 * Do as above, but for swap devices.
1225 */
1226dev_t *
1227verifyswap(struct file_list *fl, dev_t checked[], dev_t *pchecked)
1228{
1229
1230	for (;fl && fl->f_type == SWAPSPEC; fl = fl->f_next) {
1231		if (eq(fl->f_fn, "generic"))
1232			continue;
1233		if (alreadychecked(fl->f_swapdev, checked, pchecked))
1234			continue;
1235		if (!finddev(fl->f_swapdev))
1236			fprintf(stderr,
1237			   "config: swap device %s not configured", fl->f_fn);
1238		*pchecked++ = fl->f_swapdev;
1239	}
1240	return (pchecked);
1241}
1242
1243/*
1244 * Has a device already been checked
1245 * for it's existence in the configuration?
1246 */
1247int
1248alreadychecked(dev_t dev, dev_t list[], dev_t *last)
1249{
1250	register dev_t *p;
1251
1252	for (p = list; p < last; p++)
1253		if (samedev(*p, dev))
1254			return (1);
1255	return (0);
1256}
1257
1258void
1259deverror(const char *systemname, const char *devtype)
1260{
1261
1262	fprintf(stderr, "config: %s: %s device not configured\n",
1263		systemname, devtype);
1264}
1265
1266/*
1267 * Look for the device in the list of
1268 * configured hardware devices.  Must
1269 * take into account stuff wildcarded.
1270 */
1271/*ARGSUSED*/
1272int
1273finddev(__unused dev_t dev)
1274{
1275
1276	/* punt on this right now */
1277	return (1);
1278}
1279