1 %{ 2 /* 3 * yacc_cis.y 1.13 2001/08/24 12:21:41 4 * 5 * The contents of this file are subject to the Mozilla Public License 6 * Version 1.1 (the "License"); you may not use this file except in 7 * compliance with the License. You may obtain a copy of the License 8 * at http://www.mozilla.org/MPL/ 9 * 10 * Software distributed under the License is distributed on an "AS IS" 11 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 12 * the License for the specific language governing rights and 13 * limitations under the License. 14 * 15 * The initial developer of the original code is David A. Hinds 16 * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds 17 * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. 18 * 19 * Alternatively, the contents of this file may be used under the 20 * terms of the GNU General Public License version 2 (the "GPL"), in 21 * which case the provisions of the GPL are applicable instead of the 22 * above. If you wish to allow the use of your version of this file 23 * only under the terms of the GPL and not to allow others to use 24 * your version of this file under the MPL, indicate your decision by 25 * deleting the provisions above and replace them with the notice and 26 * other provisions required by the GPL. If you do not delete the 27 * provisions above, a recipient may use your version of this file 28 * under either the MPL or the GPL. 29 */ 30 31 #include <sys/types.h> 32 #include <stdlib.h> 33 #include <stdio.h> 34 #include <string.h> 35 #include <stdarg.h> 36 #include <math.h> 37 38 #include <pcmcia/cs_types.h> 39 #include <pcmcia/cs.h> 40 #include <pcmcia/cistpl.h> 41 42 #include "pack_cis.h" 43 44 /* If bison: generate nicer error messages */ 45 #define YYERROR_VERBOSE 1 46 47 extern int current_lineno; 48 49 void yyerror(char *msg, ...); 50 static tuple_info_t *new_tuple(u_char type, cisparse_t *parse); 51 52 %} 53 54 %token STRING NUMBER FLOAT VOLTAGE CURRENT SIZE 55 %token VERS_1 MANFID FUNCID CONFIG CFTABLE MFC CHECKSUM 56 %token POST ROM BASE LAST_INDEX CJEDEC AJEDEC 57 %token DEV_INFO ATTR_DEV_INFO NO_INFO 58 %token TIME TIMING WAIT READY RESERVED 59 %token VNOM VMIN VMAX ISTATIC IAVG IPEAK IDOWN 60 %token VCC VPP1 VPP2 IO MEM 61 %token DEFAULT BVD WP RDYBSY MWAIT AUDIO READONLY PWRDOWN 62 %token BIT8 BIT16 LINES RANGE 63 %token IRQ_NO MASK LEVEL PULSE SHARED 64 65 %union { 66 char *str; 67 u_long num; 68 float flt; 69 cistpl_power_t pwr; 70 cisparse_t *parse; 71 tuple_info_t *tuple; 72 } 73 74 %type <str> STRING 75 %type <num> NUMBER SIZE VOLTAGE CURRENT TIME 76 %type <flt> FLOAT 77 %type <pwr> pwr pwrlist 78 %type <parse> vers_1 manfid funcid config cftab io mem irq timing 79 %type <parse> dev_info attr_dev_info checksum cjedec ajedec 80 %type <tuple> tuple chain cis; 81 %% 82 83 cis: chain 84 { cis_root = $1; } 85 | chain mfc 86 { cis_root = $1; } 87 ; 88 89 chain: /* nothing */ 90 { $$ = NULL; } 91 | chain tuple 92 { 93 if ($1 == NULL) { 94 $$ = $2; 95 } else if ($2 == NULL) { 96 $$ = $1; 97 } else { 98 tuple_info_t *tail = $1; 99 while (tail->next != NULL) tail = tail->next; 100 tail->next = $2; 101 $$ = $1; 102 } 103 } 104 ; 105 106 mfc: MFC '{' chain '}' 107 { mfc[nf++] = $3; } 108 | mfc ',' '{' chain '}' 109 { mfc[nf++] = $4; } 110 ; 111 112 tuple: dev_info 113 { $$ = new_tuple(CISTPL_DEVICE, $1); } 114 | attr_dev_info 115 { $$ = new_tuple(CISTPL_DEVICE_A, $1); } 116 | vers_1 117 { $$ = new_tuple(CISTPL_VERS_1, $1); } 118 | manfid 119 { $$ = new_tuple(CISTPL_MANFID, $1); } 120 | funcid 121 { $$ = new_tuple(CISTPL_FUNCID, $1); } 122 | config 123 { $$ = new_tuple(CISTPL_CONFIG, $1); } 124 | cftab 125 { $$ = new_tuple(CISTPL_CFTABLE_ENTRY, $1); } 126 | checksum 127 { $$ = NULL; } 128 | error 129 { $$ = NULL; } 130 | cjedec 131 { $$ = new_tuple(CISTPL_JEDEC_C, $1); } 132 | ajedec 133 { $$ = new_tuple(CISTPL_JEDEC_A, $1); } 134 ; 135 136 dev_info: DEV_INFO 137 { $$ = calloc(1, sizeof(cisparse_t)); } 138 | dev_info NUMBER TIME ',' SIZE 139 { 140 $$->device.dev[$$->device.ndev].type = $2; 141 $$->device.dev[$$->device.ndev].speed = $3; 142 $$->device.dev[$$->device.ndev].size = $5; 143 $$->device.ndev++; 144 } 145 | dev_info NO_INFO 146 ; 147 148 attr_dev_info: ATTR_DEV_INFO 149 { $$ = calloc(1, sizeof(cisparse_t)); } 150 | attr_dev_info NUMBER TIME ',' SIZE 151 { 152 $$->device.dev[$$->device.ndev].type = $2; 153 $$->device.dev[$$->device.ndev].speed = $3; 154 $$->device.dev[$$->device.ndev].size = $5; 155 $$->device.ndev++; 156 } 157 | attr_dev_info NO_INFO 158 ; 159 160 vers_1: VERS_1 FLOAT 161 { 162 $$ = calloc(1, sizeof(cisparse_t)); 163 $$->version_1.major = $2; 164 $2 -= floor($2+0.01); 165 while (fabs($2 - floor($2+0.5)) > 0.01) { 166 $2 *= 10; 167 } 168 $$->version_1.minor = $2+0.01; 169 } 170 | vers_1 ',' STRING 171 { 172 cistpl_vers_1_t *v = &$$->version_1; 173 u_int pos = 0; 174 if (v->ns) { 175 pos = v->ofs[v->ns-1]; 176 pos += strlen(v->str+pos)+1; 177 } 178 v->ofs[v->ns] = pos; 179 strcpy(v->str+pos, $3); 180 v->ns++; 181 } 182 ; 183 184 manfid: MANFID NUMBER ',' NUMBER 185 { 186 $$ = calloc(1, sizeof(cisparse_t)); 187 $$->manfid.manf = $2; 188 $$->manfid.card = $4; 189 } 190 ; 191 192 funcid: FUNCID NUMBER 193 { 194 $$ = calloc(1, sizeof(cisparse_t)); 195 $$->funcid.func = $2; 196 } 197 | funcid POST 198 { $$->funcid.sysinit |= CISTPL_SYSINIT_POST; } 199 | funcid ROM 200 { $$->funcid.sysinit |= CISTPL_SYSINIT_ROM; } 201 ; 202 203 cjedec: CJEDEC NUMBER NUMBER 204 { 205 $$ = calloc(1, sizeof(cisparse_t)); 206 $$->jedec.id[0].mfr = $2; 207 $$->jedec.id[0].info = $3; 208 $$->jedec.nid = 1; 209 } 210 | cjedec ',' NUMBER NUMBER 211 { 212 $$->jedec.id[$$->jedec.nid].mfr = $3; 213 $$->jedec.id[$$->jedec.nid++].info = $4; 214 } 215 ; 216 217 ajedec: AJEDEC NUMBER NUMBER 218 { 219 $$ = calloc(1, sizeof(cisparse_t)); 220 $$->jedec.id[0].mfr = $2; 221 $$->jedec.id[0].info = $3; 222 $$->jedec.nid = 1; 223 } 224 | ajedec ',' NUMBER NUMBER 225 { 226 $$->jedec.id[$$->jedec.nid].mfr = $3; 227 $$->jedec.id[$$->jedec.nid++].info = $4; 228 } 229 ; 230 231 config: CONFIG BASE NUMBER MASK NUMBER LAST_INDEX NUMBER 232 { 233 $$ = calloc(1, sizeof(cisparse_t)); 234 $$->config.base = $3; 235 $$->config.rmask[0] = $5; 236 $$->config.last_idx = $7; 237 } 238 ; 239 240 pwr: VNOM VOLTAGE 241 { 242 $$.present = CISTPL_POWER_VNOM; 243 $$.param[0] = $2; 244 } 245 | VMIN VOLTAGE 246 { 247 $$.present = CISTPL_POWER_VMIN; 248 $$.param[0] = $2; 249 } 250 | VMAX VOLTAGE 251 { 252 $$.present = CISTPL_POWER_VMAX; 253 $$.param[0] = $2; 254 } 255 | ISTATIC CURRENT 256 { 257 $$.present = CISTPL_POWER_ISTATIC; 258 $$.param[0] = $2; 259 } 260 | IAVG CURRENT 261 { 262 $$.present = CISTPL_POWER_IAVG; 263 $$.param[0] = $2; 264 } 265 | IPEAK CURRENT 266 { 267 $$.present = CISTPL_POWER_IPEAK; 268 $$.param[0] = $2; 269 } 270 | IDOWN CURRENT 271 { 272 $$.present = CISTPL_POWER_IDOWN; 273 $$.param[0] = $2; 274 } 275 ; 276 277 pwrlist: /* nothing */ 278 { 279 $$.present = 0; 280 } 281 | pwrlist pwr 282 { 283 $$.present |= 1<<($2.present); 284 $$.param[$2.present] = $2.param[0]; 285 } 286 ; 287 288 timing: cftab TIMING 289 | timing WAIT TIME 290 | timing READY TIME 291 | timing RESERVED TIME 292 ; 293 294 io: cftab IO NUMBER '-' NUMBER 295 { 296 int n = $$->cftable_entry.io.nwin; 297 $$->cftable_entry.io.win[n].base = $3; 298 $$->cftable_entry.io.win[n].len = $5-$3+1; 299 $$->cftable_entry.io.nwin++; 300 } 301 | io ',' NUMBER '-' NUMBER 302 { 303 int n = $$->cftable_entry.io.nwin; 304 $$->cftable_entry.io.win[n].base = $3; 305 $$->cftable_entry.io.win[n].len = $5-$3+1; 306 $$->cftable_entry.io.nwin++; 307 } 308 | io BIT8 309 { $$->cftable_entry.io.flags |= CISTPL_IO_8BIT; } 310 | io BIT16 311 { $$->cftable_entry.io.flags |= CISTPL_IO_16BIT; } 312 | io LINES '=' NUMBER ']' 313 { $$->cftable_entry.io.flags |= $4; } 314 | io RANGE 315 ; 316 317 mem: cftab MEM NUMBER '-' NUMBER '@' NUMBER 318 { 319 int n = $$->cftable_entry.mem.nwin; 320 $$->cftable_entry.mem.win[n].card_addr = $3; 321 $$->cftable_entry.mem.win[n].host_addr = $7; 322 $$->cftable_entry.mem.win[n].len = $5-$3+1; 323 $$->cftable_entry.mem.nwin++; 324 } 325 | mem ',' NUMBER '-' NUMBER '@' NUMBER 326 { 327 int n = $$->cftable_entry.mem.nwin; 328 $$->cftable_entry.mem.win[n].card_addr = $3; 329 $$->cftable_entry.mem.win[n].host_addr = $7; 330 $$->cftable_entry.mem.win[n].len = $5-$3+1; 331 $$->cftable_entry.mem.nwin++; 332 } 333 | mem BIT8 334 { $$->cftable_entry.io.flags |= CISTPL_IO_8BIT; } 335 | mem BIT16 336 { $$->cftable_entry.io.flags |= CISTPL_IO_16BIT; } 337 ; 338 339 irq: cftab IRQ_NO NUMBER 340 { $$->cftable_entry.irq.IRQInfo1 = ($3 & 0x0f); } 341 | cftab IRQ_NO MASK NUMBER 342 { 343 $$->cftable_entry.irq.IRQInfo1 = IRQ_INFO2_VALID; 344 $$->cftable_entry.irq.IRQInfo2 = $4; 345 } 346 | irq PULSE 347 { $$->cftable_entry.irq.IRQInfo1 |= IRQ_PULSE_ID; } 348 | irq LEVEL 349 { $$->cftable_entry.irq.IRQInfo1 |= IRQ_LEVEL_ID; } 350 | irq SHARED 351 { $$->cftable_entry.irq.IRQInfo1 |= IRQ_SHARE_ID; } 352 ; 353 354 cftab: CFTABLE NUMBER 355 { 356 $$ = calloc(1, sizeof(cisparse_t)); 357 $$->cftable_entry.index = $2; 358 } 359 | cftab DEFAULT 360 { $$->cftable_entry.flags |= CISTPL_CFTABLE_DEFAULT; } 361 | cftab BVD 362 { $$->cftable_entry.flags |= CISTPL_CFTABLE_BVDS; } 363 | cftab WP 364 { $$->cftable_entry.flags |= CISTPL_CFTABLE_WP; } 365 | cftab RDYBSY 366 { $$->cftable_entry.flags |= CISTPL_CFTABLE_RDYBSY; } 367 | cftab MWAIT 368 { $$->cftable_entry.flags |= CISTPL_CFTABLE_MWAIT; } 369 | cftab AUDIO 370 { $$->cftable_entry.flags |= CISTPL_CFTABLE_AUDIO; } 371 | cftab READONLY 372 { $$->cftable_entry.flags |= CISTPL_CFTABLE_READONLY; } 373 | cftab PWRDOWN 374 { $$->cftable_entry.flags |= CISTPL_CFTABLE_PWRDOWN; } 375 | cftab VCC pwrlist 376 { $$->cftable_entry.vcc = $3; } 377 | cftab VPP1 pwrlist 378 { $$->cftable_entry.vpp1 = $3; } 379 | cftab VPP2 pwrlist 380 { $$->cftable_entry.vpp2 = $3; } 381 | io 382 | mem 383 | irq 384 | timing 385 ; 386 387 checksum: CHECKSUM NUMBER '-' NUMBER '=' NUMBER 388 { $$ = NULL; } 389 390 %% 391 392 static tuple_info_t *new_tuple(u_char type, cisparse_t *parse) 393 { 394 tuple_info_t *t = calloc(1, sizeof(tuple_info_t)); 395 t->type = type; 396 t->parse = parse; 397 t->next = NULL; 398 } 399 400 void yyerror(char *msg, ...) 401 { 402 va_list ap; 403 char str[256]; 404 405 va_start(ap, msg); 406 sprintf(str, "error at line %d: ", current_lineno); 407 vsprintf(str+strlen(str), msg, ap); 408 fprintf(stderr, "%s\n", str); 409 va_end(ap); 410 } 411 412 #ifdef DEBUG 413 void main(int argc, char *argv[]) 414 { 415 if (argc > 1) 416 parse_cis(argv[1]); 417 } 418 #endif 419