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.10 81/05/18 */ 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 Save_id = { cur.d_vec1 = $2; } | 146 VECTOR Save_id ID = { cur.d_vec1 = $2; cur.d_vec2 = ns($3); } | 147 ; 148 %% 149 150 yyerror(s) 151 char *s; 152 { 153 fprintf(stderr, "config: %s at line %d\n", s, yyline); 154 } 155 156 /* 157 * ns: 158 * Return the passed string in a new space 159 */ 160 161 char * 162 ns(str) 163 register char *str; 164 { 165 register char *cp; 166 167 cp = malloc(strlen(str)+1); 168 strcpy(cp, str); 169 return cp; 170 } 171 172 /* 173 * newdev 174 * Add a device to the list 175 */ 176 177 newdev(dp) 178 register struct device *dp; 179 { 180 register struct device *np; 181 182 np = (struct device *) malloc(sizeof *np); 183 *np = *dp; 184 if (curp == NULL) 185 dtab = np; 186 else 187 curp->d_next = np; 188 curp = np; 189 } 190 191 /* 192 * mkconf 193 * Note that a configuration should be made 194 */ 195 196 mkconf(dev, sysname) 197 char *dev, *sysname; 198 { 199 register struct file_list *fl; 200 201 fl = (struct file_list *) malloc(sizeof *fl); 202 fl->f_fn = ns(dev); 203 fl->f_needs = ns(sysname); 204 if (confp == NULL) 205 conf_list = fl; 206 else 207 confp->f_next = fl; 208 confp = fl; 209 } 210 211 /* 212 * Connect: 213 * Find the pointer to connect to the given device and number. 214 * returns NULL if no such device and prints an error message 215 */ 216 217 struct device *connect(dev, num) 218 register char *dev; 219 register int num; 220 { 221 register struct device *dp; 222 struct device *huhcon(); 223 224 if (num == QUES) 225 return huhcon(dev); 226 for (dp = dtab; dp != NULL; dp = dp->d_next) 227 if ((num == dp->d_unit) && eq(dev, dp->d_name)) 228 if (dp->d_type != CONTROLLER && dp->d_type != MASTER) 229 { 230 yyerror(sprintf(errbuf, 231 "%s connected to non-controller", dev)); 232 return NULL; 233 } 234 else 235 return dp; 236 yyerror(sprintf(errbuf, "%s %d not defined", dev, num)); 237 return NULL; 238 } 239 240 /* 241 * huhcon 242 * Connect to an unspecific thing 243 */ 244 245 struct device *huhcon(dev) 246 register char *dev; 247 { 248 register struct device *dp, *dcp; 249 struct device rdev; 250 int oldtype; 251 252 /* 253 * First make certain that there are some of these to wildcard on 254 */ 255 for (dp = dtab; dp != NULL; dp = dp->d_next) 256 if (eq(dp->d_name, dev)) 257 break; 258 if (dp == NULL) 259 { 260 yyerror(sprintf(errbuf, "no %s's to wildcard", dev)); 261 return NULL; 262 } 263 oldtype = dp->d_type; 264 dcp = dp->d_conn; 265 /* 266 * Now see if there is already a wildcard entry for this device 267 * (e.g. Search for a "uba ?") 268 */ 269 for (; dp != NULL; dp = dp->d_next) 270 if (eq(dev, dp->d_name) && dp->d_unit == -1) 271 break; 272 /* 273 * If there isn't, make one becuase everything needs to be connected 274 * to something. 275 */ 276 if (dp == NULL) 277 { 278 dp = &rdev; 279 init_dev(dp); 280 dp->d_unit = QUES; 281 dp->d_name = ns(dev); 282 dp->d_type = oldtype; 283 newdev(dp); 284 dp = curp; 285 /* 286 * Connect it to the same thing that other similar things are 287 * connected to, but make sure it is a wildcard unit 288 * (e.g. up connected to sc ?, here we make connect sc? to a uba?) 289 * If other things like this are on the NEXUS or if the aren't 290 * connected to anything, then make the same connection, else 291 * call ourself to connect to another unspecific device. 292 */ 293 if (dcp == TO_NEXUS || dcp == NULL) 294 dp->d_conn = dcp; 295 else 296 dp->d_conn = connect(dcp->d_name, QUES); 297 } 298 return dp; 299 } 300 301 /* 302 * init_dev: 303 * Set up the fields in the current device to their 304 * default values. 305 */ 306 307 init_dev(dp) 308 register struct device *dp; 309 { 310 dp->d_name = "OHNO!!!"; 311 dp->d_type = DEVICE; 312 dp->d_conn = NULL; 313 dp->d_vec1 = dp->d_vec2 = NULL; 314 dp->d_addr = dp->d_flags = dp->d_dk = 0; 315 dp->d_slave = dp->d_drive = dp->d_unit = UNKNOWN; 316 } 317 318 /* 319 * Check_nexus: 320 * Make certain that this is a reasonable type of thing to put 321 * on the nexus. 322 */ 323 324 check_nexus(dev, num) 325 register struct device *dev; 326 int num; 327 { 328 if (!eq(dev->d_name, "uba") && !eq(dev->d_name, "mba")) 329 yyerror("only uba's and mba's should be connected to the nexus"); 330 if (num != QUES) 331 yyerror("can't give specific nexus numbers"); 332 } 333 334 /* 335 * Check the timezone to make certain it is sensible 336 */ 337 338 check_tz() 339 { 340 if (timezone > 24 * 60) 341 yyerror("timezone is unreasonable"); 342 else 343 hadtz = TRUE; 344 } 345