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