Commit | Line | Data |
---|---|---|
0bf41cfc | 1 | %token MACHINE |
b1e602f2 MT |
2 | %token CPU IDENT CONFIG ANY DEVICE UBA MBA NEXUS CSR DRIVE VECTOR OPTIONS |
3 | %token CONTROLLER PSEUDO_DEVICE FLAGS ID SEMICOLON NUMBER FPNUMBER TRACE | |
0bf41cfc | 4 | %token DISK SLAVE AT HZ TIMEZONE DST MAXUSERS MASTER PRIORITY COMMA MINUS EQUALS |
2f47f1cc | 5 | %{ |
0bf41cfc BJ |
6 | |
7 | /* config.y 1.14 82/10/24 */ | |
8 | ||
2f47f1cc MT |
9 | #include "config.h" |
10 | #include <stdio.h> | |
11 | struct device cur; | |
b1e602f2 | 12 | struct device *curp = NULL; |
2f47f1cc | 13 | char *temp_id; |
841254c0 | 14 | char *val_id; |
2f47f1cc MT |
15 | %} |
16 | %% | |
17 | Configuration: | |
18 | Many_specs | |
19 | ; | |
20 | ||
21 | Many_specs: | |
22 | Many_specs Spec | |
23 | | | |
24 | ; | |
25 | ||
26 | Spec: | |
27 | Device_spec SEMICOLON = { newdev(&cur); } | | |
28 | Config_spec SEMICOLON | | |
29 | TRACE SEMICOLON = { do_trace = ! do_trace; } | | |
30 | SEMICOLON | | |
31 | error SEMICOLON | |
32 | ; | |
33 | ||
34 | Config_spec: | |
0bf41cfc BJ |
35 | MACHINE Save_id = { |
36 | if (!strcmp($2, "vax")) { | |
37 | machine = MACHINE_VAX; | |
38 | machinename = "vax"; | |
39 | } else if (!strcmp($2, "sun")) { | |
40 | machine = MACHINE_SUN; | |
41 | machinename = "sun"; | |
42 | } else | |
43 | yyerror("Unknown machine type"); | |
44 | } | | |
dea0cacc | 45 | CPU Save_id = { |
a5e18d6b | 46 | struct cputype *cp = malloc(sizeof (struct cputype)); |
dea0cacc | 47 | cp->cpu_name = ns($2); |
a5e18d6b MT |
48 | cp->cpu_next = cputype; |
49 | cputype = cp; | |
d5429061 BJ |
50 | free(temp_id); |
51 | } | | |
b1e602f2 | 52 | OPTIONS Opt_list | |
0bf41cfc | 53 | IDENT ID = { ident = ns($2); } | |
a5e18d6b MT |
54 | CONFIG Save_id ID = { mkconf(temp_id, $3); free(temp_id); } | |
55 | HZ NUMBER = { | |
8c310d10 BJ |
56 | yyerror("HZ specification obsolete; delete"); |
57 | hz = 60; | |
a5e18d6b MT |
58 | } | |
59 | TIMEZONE NUMBER = { timezone = 60 * $2; check_tz(); } | | |
60 | TIMEZONE NUMBER DST = { timezone = 60 * $2; dst = 1; check_tz(); } | | |
61 | TIMEZONE FPNUMBER = { timezone = $2; check_tz(); } | | |
62 | TIMEZONE FPNUMBER DST = { timezone = $2; dst = 1; check_tz(); } | | |
45305f56 | 63 | TIMEZONE MINUS NUMBER = |
57b7808b | 64 | { timezone = -60 * $3; check_tz(); } | |
45305f56 | 65 | TIMEZONE MINUS NUMBER DST = |
57b7808b | 66 | { timezone = -60 * $3; dst = 1; check_tz(); } | |
45305f56 | 67 | TIMEZONE MINUS FPNUMBER = |
57b7808b | 68 | { timezone = -$3; check_tz(); } | |
45305f56 | 69 | TIMEZONE MINUS FPNUMBER DST = |
57b7808b | 70 | { timezone = -$3; dst = 1; check_tz(); } | |
a5e18d6b | 71 | MAXUSERS NUMBER = { maxusers = $2; } |
2f47f1cc MT |
72 | ; |
73 | ||
b1e602f2 MT |
74 | Opt_list: |
75 | Opt_list COMMA Option | | |
76 | Option | |
77 | ; | |
78 | ||
79 | Option: | |
80 | Save_id = { | |
81 | struct opt *op = malloc(sizeof (struct opt)); | |
82 | op->op_name = ns($1); | |
83 | op->op_next = opt; | |
841254c0 | 84 | op->op_value = NULL; |
b1e602f2 MT |
85 | opt = op; |
86 | free(temp_id); | |
841254c0 RE |
87 | } | |
88 | Save_id EQUALS Opt_value = { | |
89 | struct opt *op = malloc(sizeof (struct opt)); | |
90 | op->op_name = ns($1); | |
91 | op->op_next = opt; | |
92 | op->op_value = ns($3); | |
93 | opt = op; | |
94 | free(temp_id); | |
95 | free(val_id); | |
b1e602f2 MT |
96 | } |
97 | ; | |
98 | ||
841254c0 RE |
99 | Opt_value: |
100 | ID = { $$ = val_id = ns($1); } | | |
101 | NUMBER = { char nb[16]; sprintf(nb, "%d", $1); $$ = val_id = ns(nb); } | |
102 | ; | |
103 | ||
104 | ||
2f47f1cc MT |
105 | Save_id: |
106 | ID = { $$ = temp_id = ns($1); } | |
107 | ; | |
108 | ||
109 | Dev: | |
110 | UBA = { $$ = ns("uba"); } | | |
111 | MBA = { $$ = ns("mba"); } | | |
112 | ID = { $$ = ns($1); } | |
113 | ; | |
114 | ||
115 | Device_spec: | |
116 | DEVICE Dev_name Dev_info Int_spec = { cur.d_type = DEVICE; } | | |
b1e602f2 | 117 | MASTER Dev_name Dev_info Int_spec = { cur.d_type = MASTER; } | |
2f47f1cc MT |
118 | DISK Dev_name Dev_info Int_spec = |
119 | { cur.d_dk = 1; cur.d_type = DEVICE; } | | |
120 | CONTROLLER Dev_name Dev_info Int_spec = { cur.d_type = CONTROLLER; } | | |
841254c0 RE |
121 | PSEUDO_DEVICE Init_dev Dev = { |
122 | cur.d_name = $3; | |
123 | cur.d_type = PSEUDO_DEVICE; | |
124 | } | | |
125 | PSEUDO_DEVICE Init_dev Dev NUMBER = { | |
126 | cur.d_name = $3; | |
127 | cur.d_type = PSEUDO_DEVICE; | |
128 | cur.d_slave = $4; | |
129 | } | |
2f47f1cc MT |
130 | ; |
131 | ||
132 | Dev_name: | |
133 | Init_dev Dev NUMBER = { | |
134 | cur.d_name = $2; | |
135 | if (eq($2, "mba")) | |
136 | seen_mba = TRUE; | |
137 | else if (eq($2, "uba")) | |
138 | seen_uba = TRUE; | |
139 | cur.d_unit = $3; | |
140 | } | |
141 | ; | |
142 | ||
143 | Init_dev: | |
f6f4af06 | 144 | = { init_dev(&cur); } |
2f47f1cc MT |
145 | ; |
146 | ||
147 | Dev_info: | |
148 | Con_info Info_list | |
149 | | | |
150 | ; | |
151 | ||
152 | Con_info: | |
b1e602f2 MT |
153 | AT Dev NUMBER = { |
154 | if (eq(cur.d_name, "mba") || eq(cur.d_name, "uba")) | |
155 | yyerror(sprintf(errbuf, | |
156 | "%s must be connected to a nexus", cur.d_name)); | |
157 | cur.d_conn = connect($2, $3); | |
158 | } | | |
159 | AT NEXUS NUMBER = { check_nexus(&cur, $3); cur.d_conn = TO_NEXUS; } | |
2f47f1cc MT |
160 | ; |
161 | ||
162 | Info_list: | |
163 | Info_list Info | |
164 | | | |
165 | ; | |
166 | ||
167 | Info: | |
168 | CSR NUMBER = { cur.d_addr = $2; } | | |
169 | DRIVE NUMBER = { cur.d_drive = $2; } | | |
b1e602f2 MT |
170 | SLAVE NUMBER = |
171 | { | |
172 | if (cur.d_conn != NULL && cur.d_conn != TO_NEXUS | |
173 | && cur.d_conn->d_type == MASTER) | |
174 | cur.d_slave = $2; | |
175 | else | |
176 | yyerror("can't specify slave--not to master"); | |
177 | } | | |
2f47f1cc MT |
178 | FLAGS NUMBER = { cur.d_flags = $2; } |
179 | ; | |
180 | ||
181 | Int_spec: | |
0bf41cfc BJ |
182 | VECTOR Id_list = { cur.d_vec = $2; } | |
183 | PRIORITY NUMBER = { cur.d_pri = $2; } | | |
184 | ; | |
08f9a943 BJ |
185 | |
186 | Id_list: | |
187 | Save_id = | |
188 | { struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst)); | |
189 | a->id = $1; a->id_next = 0; $$ = a; } | | |
190 | Save_id Id_list = | |
191 | { struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst)); | |
192 | a->id = $1; a->id_next = $2; $$ = a; } ; | |
2f47f1cc MT |
193 | %% |
194 | ||
195 | yyerror(s) | |
196 | char *s; | |
197 | { | |
198 | fprintf(stderr, "config: %s at line %d\n", s, yyline); | |
199 | } | |
200 | ||
201 | /* | |
202 | * ns: | |
203 | * Return the passed string in a new space | |
204 | */ | |
205 | ||
206 | char * | |
207 | ns(str) | |
208 | register char *str; | |
209 | { | |
210 | register char *cp; | |
211 | ||
212 | cp = malloc(strlen(str)+1); | |
213 | strcpy(cp, str); | |
214 | return cp; | |
215 | } | |
216 | ||
217 | /* | |
218 | * newdev | |
219 | * Add a device to the list | |
220 | */ | |
221 | ||
222 | newdev(dp) | |
223 | register struct device *dp; | |
224 | { | |
225 | register struct device *np; | |
226 | ||
227 | np = (struct device *) malloc(sizeof *np); | |
228 | *np = *dp; | |
b1e602f2 MT |
229 | if (curp == NULL) |
230 | dtab = np; | |
231 | else | |
232 | curp->d_next = np; | |
233 | curp = np; | |
2f47f1cc MT |
234 | } |
235 | ||
236 | /* | |
237 | * mkconf | |
238 | * Note that a configuration should be made | |
239 | */ | |
240 | ||
241 | mkconf(dev, sysname) | |
242 | char *dev, *sysname; | |
243 | { | |
244 | register struct file_list *fl; | |
245 | ||
246 | fl = (struct file_list *) malloc(sizeof *fl); | |
247 | fl->f_fn = ns(dev); | |
248 | fl->f_needs = ns(sysname); | |
249 | if (confp == NULL) | |
250 | conf_list = fl; | |
251 | else | |
252 | confp->f_next = fl; | |
253 | confp = fl; | |
254 | } | |
255 | ||
256 | /* | |
257 | * Connect: | |
258 | * Find the pointer to connect to the given device and number. | |
259 | * returns NULL if no such device and prints an error message | |
260 | */ | |
261 | ||
f6f4af06 | 262 | struct device *connect(dev, num) |
2f47f1cc MT |
263 | register char *dev; |
264 | register int num; | |
265 | { | |
266 | register struct device *dp; | |
f6f4af06 | 267 | struct device *huhcon(); |
2f47f1cc | 268 | |
a5e18d6b | 269 | if (num == QUES) |
f6f4af06 | 270 | return huhcon(dev); |
2f47f1cc | 271 | for (dp = dtab; dp != NULL; dp = dp->d_next) |
b1e602f2 MT |
272 | if ((num == dp->d_unit) && eq(dev, dp->d_name)) |
273 | if (dp->d_type != CONTROLLER && dp->d_type != MASTER) | |
a5e18d6b MT |
274 | { |
275 | yyerror(sprintf(errbuf, | |
276 | "%s connected to non-controller", dev)); | |
277 | return NULL; | |
278 | } | |
279 | else | |
2f47f1cc MT |
280 | return dp; |
281 | yyerror(sprintf(errbuf, "%s %d not defined", dev, num)); | |
a5e18d6b | 282 | return NULL; |
2f47f1cc | 283 | } |
f6f4af06 MT |
284 | |
285 | /* | |
286 | * huhcon | |
287 | * Connect to an unspecific thing | |
288 | */ | |
289 | ||
290 | struct device *huhcon(dev) | |
291 | register char *dev; | |
292 | { | |
293 | register struct device *dp, *dcp; | |
294 | struct device rdev; | |
b1e602f2 | 295 | int oldtype; |
f6f4af06 MT |
296 | |
297 | /* | |
298 | * First make certain that there are some of these to wildcard on | |
299 | */ | |
300 | for (dp = dtab; dp != NULL; dp = dp->d_next) | |
301 | if (eq(dp->d_name, dev)) | |
302 | break; | |
303 | if (dp == NULL) | |
304 | { | |
305 | yyerror(sprintf(errbuf, "no %s's to wildcard", dev)); | |
306 | return NULL; | |
307 | } | |
b1e602f2 | 308 | oldtype = dp->d_type; |
f6f4af06 MT |
309 | dcp = dp->d_conn; |
310 | /* | |
311 | * Now see if there is already a wildcard entry for this device | |
a5e18d6b | 312 | * (e.g. Search for a "uba ?") |
f6f4af06 MT |
313 | */ |
314 | for (; dp != NULL; dp = dp->d_next) | |
315 | if (eq(dev, dp->d_name) && dp->d_unit == -1) | |
316 | break; | |
317 | /* | |
a5e18d6b MT |
318 | * If there isn't, make one becuase everything needs to be connected |
319 | * to something. | |
f6f4af06 MT |
320 | */ |
321 | if (dp == NULL) | |
322 | { | |
323 | dp = &rdev; | |
324 | init_dev(dp); | |
a5e18d6b | 325 | dp->d_unit = QUES; |
f6f4af06 | 326 | dp->d_name = ns(dev); |
b1e602f2 | 327 | dp->d_type = oldtype; |
f6f4af06 | 328 | newdev(dp); |
b1e602f2 | 329 | dp = curp; |
f6f4af06 MT |
330 | /* |
331 | * Connect it to the same thing that other similar things are | |
332 | * connected to, but make sure it is a wildcard unit | |
a5e18d6b MT |
333 | * (e.g. up connected to sc ?, here we make connect sc? to a uba?) |
334 | * If other things like this are on the NEXUS or if the aren't | |
335 | * connected to anything, then make the same connection, else | |
336 | * call ourself to connect to another unspecific device. | |
f6f4af06 | 337 | */ |
a5e18d6b | 338 | if (dcp == TO_NEXUS || dcp == NULL) |
f6f4af06 MT |
339 | dp->d_conn = dcp; |
340 | else | |
a5e18d6b | 341 | dp->d_conn = connect(dcp->d_name, QUES); |
f6f4af06 MT |
342 | } |
343 | return dp; | |
344 | } | |
345 | ||
a5e18d6b MT |
346 | /* |
347 | * init_dev: | |
348 | * Set up the fields in the current device to their | |
349 | * default values. | |
350 | */ | |
351 | ||
f6f4af06 MT |
352 | init_dev(dp) |
353 | register struct device *dp; | |
354 | { | |
355 | dp->d_name = "OHNO!!!"; | |
356 | dp->d_type = DEVICE; | |
357 | dp->d_conn = NULL; | |
08f9a943 | 358 | dp->d_vec = NULL; |
0bf41cfc | 359 | dp->d_addr = dp->d_pri = dp->d_flags = dp->d_dk = 0; |
a5e18d6b MT |
360 | dp->d_slave = dp->d_drive = dp->d_unit = UNKNOWN; |
361 | } | |
362 | ||
363 | /* | |
364 | * Check_nexus: | |
365 | * Make certain that this is a reasonable type of thing to put | |
366 | * on the nexus. | |
367 | */ | |
368 | ||
369 | check_nexus(dev, num) | |
370 | register struct device *dev; | |
371 | int num; | |
372 | { | |
0bf41cfc BJ |
373 | switch (machine) { |
374 | case MACHINE_VAX: | |
375 | if (!eq(dev->d_name, "uba") && !eq(dev->d_name, "mba")) | |
376 | yyerror("only uba's and mba's should be connected to the nexus"); | |
377 | if (num != QUES) | |
378 | yyerror("can't give specific nexus numbers"); | |
379 | break; | |
380 | ||
381 | case MACHINE_SUN: | |
382 | if (!eq(dev->d_name, "mb")) | |
383 | yyerror("only mb's should be connected to the nexus"); | |
384 | break; | |
385 | } | |
f6f4af06 | 386 | } |
b1e602f2 MT |
387 | |
388 | /* | |
389 | * Check the timezone to make certain it is sensible | |
390 | */ | |
391 | ||
392 | check_tz() | |
393 | { | |
841254c0 | 394 | if (abs(timezone) > 12 * 60) |
b1e602f2 MT |
395 | yyerror("timezone is unreasonable"); |
396 | else | |
397 | hadtz = TRUE; | |
398 | } |