config.y revision 53047
1%union {
2	char	*str;
3	int	val;
4	struct	file_list *file;
5}
6
7%token	ANY
8%token	ARCH
9%token	AT
10%token	BUS
11%token	COMMA
12%token	CONFIG
13%token	CONFLICTS
14%token	CONTROLLER
15%token	CPU
16%token	DEVICE
17%token	DISABLE
18%token	DISK
19%token	DRIVE
20%token	DRQ
21%token	EQUALS
22%token	FLAGS
23%token	IDENT
24%token	IOMEM
25%token	IOSIZ
26%token	IRQ
27%token	MAXUSERS
28%token	MINUS
29%token	NEXUS
30%token	OPTIONS
31%token	MAKEOPTIONS
32%token	PORT
33%token	PSEUDO_DEVICE
34%token	SEMICOLON
35%token	TAPE
36%token	TARGET
37%token	TTY
38%token	UNIT
39%token	VECTOR
40
41%token	<str>	ID
42%token	<val>	NUMBER
43%token	<val>	FPNUMBER
44
45%type	<str>	Save_id
46%type	<str>	Opt_value
47%type	<str>	Dev
48%type	<str>	device_name
49
50%{
51
52/*
53 * Copyright (c) 1988, 1993
54 *	The Regents of the University of California.  All rights reserved.
55 *
56 * Redistribution and use in source and binary forms, with or without
57 * modification, are permitted provided that the following conditions
58 * are met:
59 * 1. Redistributions of source code must retain the above copyright
60 *    notice, this list of conditions and the following disclaimer.
61 * 2. Redistributions in binary form must reproduce the above copyright
62 *    notice, this list of conditions and the following disclaimer in the
63 *    documentation and/or other materials provided with the distribution.
64 * 3. All advertising materials mentioning features or use of this software
65 *    must display the following acknowledgement:
66 *	This product includes software developed by the University of
67 *	California, Berkeley and its contributors.
68 * 4. Neither the name of the University nor the names of its contributors
69 *    may be used to endorse or promote products derived from this software
70 *    without specific prior written permission.
71 *
72 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
73 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
74 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
75 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
76 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
77 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
78 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
79 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
80 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
81 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
82 * SUCH DAMAGE.
83 *
84 *	@(#)config.y	8.1 (Berkeley) 6/6/93
85 * $FreeBSD: head/usr.sbin/config/config.y 53047 1999-11-09 07:20:22Z peter $
86 */
87
88#include <ctype.h>
89#include <err.h>
90#include <stdio.h>
91#include <string.h>
92
93#include "config.h"
94
95static struct	device cur;
96static struct	device *curp = 0;
97
98struct  device *dtab;
99char	*ident;
100int	yyline;
101struct  file_list *ftab;
102char	errbuf[80];
103int	maxusers;
104
105int	seen_scbus;
106
107#define ns(s)	strdup(s)
108
109static struct device *connect __P((char *, int));
110static struct device *huhcon __P((char *));
111static void yyerror __P((char *s));
112
113
114%}
115%%
116Configuration:
117	Many_specs
118		;
119
120Many_specs:
121	Many_specs Spec
122		|
123	/* lambda */
124		;
125
126Spec:
127	Device_spec SEMICOLON
128	      = { newdev(&cur); } |
129	Config_spec SEMICOLON
130		|
131	SEMICOLON
132		|
133	error SEMICOLON
134		;
135
136Config_spec:
137	ARCH Save_id
138	    = {
139		if (!strcmp($2, "i386")) {
140			machine = MACHINE_I386;
141			machinename = "i386";
142		} else if (!strcmp($2, "pc98")) {
143			machine = MACHINE_PC98;
144			machinename = "pc98";
145		} else if (!strcmp($2, "alpha")) {
146			machine = MACHINE_ALPHA;
147			machinename = "alpha";
148		} else
149			yyerror("Unknown machine type");
150	      } |
151	CPU Save_id
152	      = {
153		struct cputype *cp =
154		    (struct cputype *)malloc(sizeof (struct cputype));
155		memset(cp, 0, sizeof(*cp));
156		cp->cpu_name = $2;
157		cp->cpu_next = cputype;
158		cputype = cp;
159	      } |
160	OPTIONS Opt_list
161		|
162	MAKEOPTIONS Mkopt_list
163		|
164	IDENT ID
165	      = { ident = $2; } |
166	System_spec
167		|
168	MAXUSERS NUMBER
169	      = { maxusers = $2; };
170
171System_spec:
172	CONFIG System_id System_parameter_list
173	  = { warnx("line %d: root/dump/swap specifications obsolete", yyline);}
174	  |
175	CONFIG System_id
176	  ;
177
178System_id:
179	Save_id
180	      = {
181		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
182		memset(op, 0, sizeof(*op));
183		op->op_name = ns("KERNEL");
184		op->op_ownfile = 0;
185		op->op_next = mkopt;
186		op->op_value = $1;
187		op->op_line = yyline + 1;
188		mkopt = op;
189	      };
190
191System_parameter_list:
192	  System_parameter_list ID
193	| ID
194	;
195
196device_name:
197	  Save_id
198		= { $$ = $1; }
199	| Save_id NUMBER
200		= {
201			char buf[80];
202
203			(void) snprintf(buf, sizeof(buf), "%s%d", $1, $2);
204			$$ = ns(buf); free($1);
205		}
206	| Save_id NUMBER ID
207		= {
208			char buf[80];
209
210			(void) snprintf(buf, sizeof(buf), "%s%d%s", $1, $2, $3);
211			$$ = ns(buf); free($1);
212		}
213	| Save_id NUMBER ID NUMBER
214		= {
215			char buf[80];
216
217			(void) snprintf(buf, sizeof(buf), "%s%d%s%d",
218			     $1, $2, $3, $4);
219			$$ = ns(buf); free($1);
220		}
221	| Save_id NUMBER ID NUMBER ID
222		= {
223			char buf[80];
224
225			(void) snprintf(buf, sizeof(buf), "%s%d%s%d%s",
226			     $1, $2, $3, $4, $5);
227			$$ = ns(buf); free($1);
228		}
229	;
230
231Opt_list:
232	Opt_list COMMA Option
233		|
234	Option
235		;
236
237Option:
238	Save_id
239	      = {
240		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
241		char *s;
242		memset(op, 0, sizeof(*op));
243		op->op_name = $1;
244		op->op_next = opt;
245		op->op_value = 0;
246		/*
247		 * op->op_line is 1-based; yyline is 0-based but is now 1
248		 * larger than when `Save_id' was lexed.
249		 */
250		op->op_line = yyline;
251		opt = op;
252		if ((s = strchr(op->op_name, '='))) {
253			warnx("line %d: The `=' in options should not be quoted", yyline);
254			*s = '\0';
255			op->op_value = ns(s + 1);
256		}
257	      } |
258	Save_id EQUALS Opt_value
259	      = {
260		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
261		memset(op, 0, sizeof(*op));
262		op->op_name = $1;
263		op->op_next = opt;
264		op->op_value = $3;
265		op->op_line = yyline + 1;
266		opt = op;
267	      } ;
268
269Opt_value:
270	ID
271		= { $$ = $1; } |
272	NUMBER
273		= {
274			char buf[80];
275
276			(void) snprintf(buf, sizeof(buf), "%d", $1);
277			$$ = ns(buf);
278		} ;
279
280Save_id:
281	ID
282	      = { $$ = $1; }
283	;
284
285Mkopt_list:
286	Mkopt_list COMMA Mkoption
287		|
288	Mkoption
289		;
290
291Mkoption:
292	Save_id EQUALS Opt_value
293	      = {
294		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
295		memset(op, 0, sizeof(*op));
296		op->op_name = $1;
297		op->op_ownfile = 0;	/* for now */
298		op->op_next = mkopt;
299		op->op_value = $3;
300		op->op_line = yyline + 1;
301		mkopt = op;
302	      } ;
303
304Dev:
305	ID
306	      = { $$ = $1; }
307	;
308
309Device_spec:
310	DEVICE Dev_name Dev_info
311	      = { cur.d_type = DEVICE; } |
312	DISK Dev_name Dev_info
313	      = {
314		warnx("line %d: Obsolete keyword 'disk' found - use 'device'", yyline);
315		cur.d_type = DEVICE;
316		} |
317	TAPE Dev_name Dev_info
318	      = {
319		warnx("line %d: Obsolete keyword 'tape' found - use 'device'", yyline);
320		cur.d_type = DEVICE;
321		} |
322	CONTROLLER Dev_name Dev_info
323	      = { cur.d_type = CONTROLLER; } |
324	PSEUDO_DEVICE Init_dev Dev
325	      = {
326		cur.d_name = $3;
327		cur.d_type = PSEUDO_DEVICE;
328		} |
329	PSEUDO_DEVICE Init_dev Dev NUMBER
330	      = {
331		cur.d_name = $3;
332		cur.d_type = PSEUDO_DEVICE;
333		cur.d_count = $4;
334		} ;
335
336Dev_name:
337	Init_dev Dev NUMBER
338	      = {
339		cur.d_name = $2;
340		if (eq($2, "scbus"))
341			seen_scbus = 1;
342		cur.d_unit = $3;
343		};
344
345Init_dev:
346	/* lambda */
347	      = { init_dev(&cur); };
348
349Dev_info:
350	Con_info Info_list
351		|
352	/* lambda */
353		;
354
355Con_info:
356	AT Dev NUMBER
357	      = {
358		if (eq(cur.d_name, "mba") || eq(cur.d_name, "uba")) {
359			(void) snprintf(errbuf, sizeof(errbuf),
360				"%s must be connected to a nexus", cur.d_name);
361			yyerror(errbuf);
362		}
363		cur.d_conn = connect($2, $3);
364		} |
365	AT NEXUS NUMBER
366	      = { cur.d_conn = TO_NEXUS; };
367
368Info_list:
369	Info_list Info
370		|
371	/* lambda */
372		;
373
374Info:
375	BUS NUMBER	/* controller scbus1 at ahc0 bus 1 - twin channel */
376	      = {
377		if (cur.d_conn != 0 && cur.d_conn->d_type == CONTROLLER)
378			cur.d_slave = $2;
379		else
380			yyerror("can't specify a bus to something "
381				 "other than a controller");
382		} |
383	TARGET NUMBER
384	      = { cur.d_target = $2; } |
385	UNIT NUMBER
386	      = { cur.d_lun = $2; } |
387	DRIVE NUMBER
388	      = { cur.d_drive = $2; } |
389	IRQ NUMBER
390	      = { cur.d_irq = $2; } |
391	DRQ NUMBER
392	      = { cur.d_drq = $2; } |
393	IOMEM NUMBER
394	      = { cur.d_maddr = $2; } |
395	IOSIZ NUMBER
396	      = { cur.d_msize = $2; } |
397	PORT device_name
398	      = { cur.d_port = $2; } |
399	PORT NUMBER
400	      = { cur.d_portn = $2; } |
401	FLAGS NUMBER
402	      = { cur.d_flags = $2; } |
403	DISABLE
404	      = { cur.d_disabled = 1; } |
405	CONFLICTS
406	      = { cur.d_conflicts = 1; };
407
408%%
409
410static void
411yyerror(s)
412	char *s;
413{
414
415	warnx("line %d: %s", yyline + 1, s);
416}
417
418/*
419 * add a device to the list of devices
420 */
421static void
422newdev(dp)
423	register struct device *dp;
424{
425	register struct device *np, *xp;
426
427	if (dp->d_unit >= 0) {
428		for (xp = dtab; xp != 0; xp = xp->d_next) {
429			if ((xp->d_unit == dp->d_unit) &&
430			    eq(xp->d_name, dp->d_name)) {
431				warnx("line %d: already seen device %s%d",
432				    yyline, xp->d_name, xp->d_unit);
433			}
434		}
435	}
436	np = (struct device *) malloc(sizeof *np);
437	memset(np, 0, sizeof(*np));
438	*np = *dp;
439	np->d_next = 0;
440	if (curp == 0)
441		dtab = np;
442	else
443		curp->d_next = np;
444	curp = np;
445}
446
447
448/*
449 * find the pointer to connect to the given device and number.
450 * returns 0 if no such device and prints an error message
451 */
452static struct device *
453connect(dev, num)
454	register char *dev;
455	register int num;
456{
457	register struct device *dp;
458
459	if (num == QUES)
460		return (huhcon(dev));
461	for (dp = dtab; dp != 0; dp = dp->d_next) {
462		if ((num != dp->d_unit) || !eq(dev, dp->d_name))
463			continue;
464		if (dp->d_type != CONTROLLER) {
465			(void) snprintf(errbuf, sizeof(errbuf),
466			    "%s connected to non-controller", dev);
467			yyerror(errbuf);
468			return (0);
469		}
470		return (dp);
471	}
472	(void) snprintf(errbuf, sizeof(errbuf), "%s %d not defined", dev, num);
473	yyerror(errbuf);
474	return (0);
475}
476
477/*
478 * connect to an unspecific thing
479 */
480static struct device *
481huhcon(dev)
482	register char *dev;
483{
484	register struct device *dp, *dcp;
485	struct device rdev;
486	int oldtype;
487
488	/*
489	 * First make certain that there are some of these to wildcard on
490	 */
491	for (dp = dtab; dp != 0; dp = dp->d_next)
492		if (eq(dp->d_name, dev))
493			break;
494	if (dp == 0) {
495		(void) snprintf(errbuf, sizeof(errbuf), "no %s's to wildcard",
496		   dev);
497		yyerror(errbuf);
498		return (0);
499	}
500	oldtype = dp->d_type;
501	dcp = dp->d_conn;
502	/*
503	 * Now see if there is already a wildcard entry for this device
504	 * (e.g. Search for a "uba ?")
505	 */
506	for (; dp != 0; dp = dp->d_next)
507		if (eq(dev, dp->d_name) && dp->d_unit == -1)
508			break;
509	/*
510	 * If there isn't, make one because everything needs to be connected
511	 * to something.
512	 */
513	if (dp == 0) {
514		dp = &rdev;
515		init_dev(dp);
516		dp->d_unit = QUES;
517		dp->d_name = ns(dev);
518		dp->d_type = oldtype;
519		newdev(dp);
520		dp = curp;
521		/*
522		 * Connect it to the same thing that other similar things are
523		 * connected to, but make sure it is a wildcard unit
524		 * (e.g. up connected to sc ?, here we make connect sc? to a
525		 * uba?).  If other things like this are on the NEXUS or
526		 * if they aren't connected to anything, then make the same
527		 * connection, else call ourself to connect to another
528		 * unspecific device.
529		 */
530		if (dcp == TO_NEXUS || dcp == 0)
531			dp->d_conn = dcp;
532		else
533			dp->d_conn = connect(dcp->d_name, QUES);
534	}
535	return (dp);
536}
537
538void
539init_dev(dp)
540	register struct device *dp;
541{
542
543	dp->d_name = "OHNO!!!";
544	dp->d_type = DEVICE;
545	dp->d_conn = 0;
546	dp->d_conflicts = 0;
547	dp->d_disabled = 0;
548	dp->d_flags = 0;
549	dp->d_slave = dp->d_lun = dp->d_target = dp->d_drive = dp->d_unit = \
550		dp->d_count = UNKNOWN;
551	dp->d_port = (char *)0;
552	dp->d_portn = -1;
553	dp->d_irq = -1;
554	dp->d_drq = -1;
555	dp->d_maddr = 0;
556	dp->d_msize = 0;
557}
558