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