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