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