1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This file contains the tuple handlers that are called by the CIS 31 * parser. 32 * 33 * XXX - how about a better explaination?? 34 */ 35 36 #include <sys/types.h> 37 #include <sys/systm.h> 38 #include <sys/user.h> 39 #include <sys/buf.h> 40 #include <sys/file.h> 41 #include <sys/uio.h> 42 #include <sys/conf.h> 43 #include <sys/stat.h> 44 #include <sys/autoconf.h> 45 #include <sys/vtoc.h> 46 #include <sys/dkio.h> 47 #include <sys/ddi.h> 48 #include <sys/sunddi.h> 49 #include <sys/debug.h> 50 #include <sys/ddi_impldefs.h> 51 #include <sys/kstat.h> 52 #include <sys/kmem.h> 53 #include <sys/modctl.h> 54 #include <sys/kobj.h> 55 #include <sys/callb.h> 56 57 #include <sys/pctypes.h> 58 #include <pcmcia/sys/cs_types.h> 59 #include <pcmcia/sys/cis.h> 60 #include <pcmcia/sys/cis_handlers.h> 61 #include <pcmcia/sys/cs.h> 62 #include <pcmcia/sys/cs_priv.h> 63 #include <pcmcia/sys/cis_protos.h> 64 65 /* 66 * Function prototypes 67 */ 68 static void cistpl_pd_parse(cistpl_t *, cistpl_cftable_entry_pwr_t *); 69 static void cis_return_name(cistpl_callout_t *, cistpl_get_tuple_name_t *); 70 71 /* 72 * Fetch data functions. 73 */ 74 uint16_t 75 cis_get_short(cistpl_t *tp) 76 { 77 uint16_t result; 78 79 if (tp->flags & CISTPLF_AM_SPACE) { 80 result = GET_AM_BYTE(tp); 81 result |= GET_AM_BYTE(tp) << 8; 82 } else { 83 result = GET_CM_BYTE(tp); 84 result |= GET_CM_BYTE(tp) << 8; 85 } 86 return (result); 87 } 88 89 uint16_t 90 cis_get_be_short(cistpl_t *tp) 91 { 92 uint16_t result; 93 94 if (tp->flags & CISTPLF_AM_SPACE) { 95 result = GET_AM_BYTE(tp) << 8; 96 result |= GET_AM_BYTE(tp); 97 } else { 98 result = GET_CM_BYTE(tp) << 8; 99 result |= GET_CM_BYTE(tp); 100 } 101 return (result); 102 } 103 104 uint32_t 105 cis_get_int24(cistpl_t *tp) 106 { 107 uint32_t result = cis_get_short(tp); 108 109 result |= GET_BYTE(tp) << 16; 110 return (result); 111 } 112 113 uint32_t 114 cis_get_long(cistpl_t *tp) 115 { 116 uint32_t result = cis_get_short(tp); 117 118 result |= cis_get_short(tp) << 16; 119 return (result); 120 } 121 122 /* 123 * cis_tuple_handler - call the handler for the tuple described by the 124 * tuple pointer 125 * 126 * cistpl_callout_t *co - pointer to callout structure 127 * array to use to find this tuple 128 * cistpl_t *tp - pointer to a tuple structure 129 * int flags - action for the handler to perform 130 * XXX - we need a description of the flags passed to the tuple handler 131 * void *arg - argument to pass on to tuple handler 132 * 133 * If the tuple is not recognized but is is a vendor-specific tuple, we 134 * set the CISTPLF_VENDOR_SPECIFIC flag in the tuple. 135 * 136 * We return CISTPLF_UNKNOWN if this is an unrecognized tuple as well as 137 * set the CISTPLF_UNKNOWN flag in the tuple list structure. Note 138 * that encountering an unknown tuple is not necessarily an error, 139 * so we don't set the HANDTPL_ERROR flag on the return code. It 140 * is up to the caller to determine what an unrecognized tuple means. 141 * 142 * If this is a recognized tuple, the apropriate tuple handler is called and 143 * the return value from the handler is returned directly to the caller. 144 * 145 * The void *arg is optional, and it's meaning is dependent on the 146 * particular tuple handler called and the flags parameter. 147 * 148 * For the special case of HANDTPL_RETURN_NAME, we don't bother calling the 149 * tuple handler and just return the tuple name to the caller. 150 */ 151 uint32_t 152 cis_tuple_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags, 153 void *arg, cisdata_t subtype) 154 { 155 /* 156 * Check to see if this is a vendor-specific tuple. 157 */ 158 if (CISTPL_IS_VENDOR_SPECIFIC(tp->type)) 159 tp->flags |= CISTPLF_VENDOR_SPECIFIC; 160 161 /* 162 * Scan the callout list until we find the tuple passed to us, or we 163 * encounter a CISTPL_END in the callout list, which signals that 164 * there are no more tuples in the callout list. 165 */ 166 while (co->type != (cisdata_t)CISTPL_END) { 167 if (co->type == tp->type && 168 ((tp->type != CISTPL_FUNCE) || 169 (tp->type == CISTPL_FUNCE && co->subtype == subtype))) { 170 tp->flags &= ~CISTPLF_UNKNOWN; 171 if (flags & HANDTPL_RETURN_NAME) { 172 cis_return_name(co, (cistpl_get_tuple_name_t *)arg); 173 return (CISTPLF_NOERROR); 174 } else { 175 return ((*co->handler) (co, tp, flags, arg)); 176 } /* HANDTPL_RETURN_NAME */ 177 } /* if */ 178 co++; 179 } /* while */ 180 181 /* 182 * If we didn't recognize the tuple and the caller wants the tuple 183 * name back, then return the "unknown tuple" string. At this 184 * point, "co" will be pointing to the last entry in the 185 * callout list. It's not an error to not recognize the tuple 186 * when the operation is HANDTPL_RETURN_NAME. 187 */ 188 if (flags & HANDTPL_RETURN_NAME) { 189 cis_return_name(co, (cistpl_get_tuple_name_t *)arg); 190 return (CISTPLF_NOERROR); 191 } 192 193 tp->flags |= CISTPLF_UNKNOWN; 194 return (CISTPLF_UNKNOWN); 195 } 196 197 /* 198 * cis_no_tuple_handler - this generic tuple handler is used if no special 199 * tuple processing is required for the passed 200 * tuple 201 * 202 * cistpl_callout_t *co - pointer to this tuple's entry in the 203 * tuple callout structure 204 * cistpl_t *tp - pointer to this tuple's entry in the local linked list 205 * int flags - action to perform 206 * 207 * This handler will set the CISTPLF_COPYOK flag if the tuple link is greater 208 * than zero, indicating that it's OK to copy the tuple data body. It 209 * will also set whatever flags are specified in the callout structure. 210 * 211 * We always set the CISTPLF_VALID when we're called with HANDTPL_COPY_DONE. 212 * 213 * We return CISTPLF_UNKNOWN if we're being called to parse the tuple. 214 * 215 * We return CISTPLF_NOERROR in every other case to indicate that this is a 216 * recognized tuple. 217 */ 218 /*ARGSUSED*/ 219 uint32_t 220 cis_no_tuple_handler(cistpl_callout_t *co, cistpl_t *tp, 221 uint32_t flags, void *arg) 222 { 223 if (flags & HANDTPL_SET_FLAGS) { 224 tp->flags |= co->flags; /* XXX - is = the right thing here? */ 225 if (tp->len > 0) 226 tp->flags |= CISTPLF_COPYOK; 227 } 228 229 if (flags & HANDTPL_COPY_DONE) 230 tp->flags |= CISTPLF_VALID; 231 232 if (flags & HANDTPL_PARSE_LTUPLE) 233 return (CISTPLF_UNKNOWN); 234 235 return (CISTPLF_NOERROR); 236 } 237 238 /* 239 * cis_unknown_tuple_handler - this generic tuple handler is used if we don't 240 * understand this tuple 241 * 242 * cistpl_callout_t *co - pointer to this tuple's entry in the 243 * tuple callout structure 244 * cistpl_t *tp - pointer to this tuple's entry in the local linked list 245 * int flags - action to perform 246 * 247 * This handler will not set the CISTPLF_COPYOK flag since we don't know the 248 * contents of a vendor-specific tuple. 249 * 250 * We always set the CISTPLF_VALID when we're called with HANDTPL_COPY_DONE 251 * to specify that we understand this tuple's code, but not it's data 252 * body. 253 * 254 * We return CISTPLF_UNKNOWN if we're being called to parse the tuple or to 255 * perform any other operation. 256 */ 257 /*ARGSUSED*/ 258 uint32_t 259 cis_unknown_tuple_handler(cistpl_callout_t *co, cistpl_t *tp, 260 uint32_t flags, void *arg) 261 { 262 if (flags & HANDTPL_SET_FLAGS) { 263 tp->flags |= co->flags; /* XXX - is = the right thing here? */ 264 return (CISTPLF_NOERROR); 265 } 266 267 if (flags & HANDTPL_COPY_DONE) { 268 tp->flags |= CISTPLF_VALID; 269 return (CISTPLF_NOERROR); 270 } 271 272 return (CISTPLF_UNKNOWN); 273 } 274 275 /* 276 * cistpl_vers_1_handler - handler for the CISTPL_VERS_1 tuple 277 * 278 * void *arg - points to a cistpl_vers_1_t * where the 279 * information is stuffed into 280 */ 281 uint32_t 282 cistpl_vers_1_handler(cistpl_callout_t *co, cistpl_t *tp, 283 uint32_t flags, void *arg) 284 { 285 /* 286 * nothing special about our flags, so just call the 287 * generic handler for this 288 */ 289 if (flags & HANDTPL_SET_FLAGS) 290 return (cis_no_tuple_handler(co, tp, flags, arg)); 291 292 /* 293 * We don't currently validate this tuple. This call will 294 * always set tp->flags |= CISTPLF_VALID. 295 */ 296 if (flags & HANDTPL_COPY_DONE) 297 return (cis_no_tuple_handler(co, tp, flags, arg)); 298 299 if (flags & HANDTPL_PARSE_LTUPLE) { 300 cistpl_vers_1_t *cs = (cistpl_vers_1_t *)arg; 301 302 303 RESET_TP(tp); 304 305 cs->major = GET_BYTE(tp); 306 cs->minor = GET_BYTE(tp); 307 for (cs->ns = 0; GET_LEN(tp) > 0 && 308 /* CSTYLED */ 309 cs->ns < CISTPL_VERS_1_MAX_PROD_STRINGS; ) { 310 (void) strcpy(cs->pi[cs->ns++], cis_getstr(tp)); 311 } /* for */ 312 } /* HANDTPL_PARSE_LTUPLE */ 313 314 return (CISTPLF_NOERROR); 315 } 316 317 /* 318 * cistpl_config_handler - handler for the CISTPL_CONFIG tuple 319 * 320 * void *arg - points to a XXX where the information is stuffed into 321 * 322 * For the first ten config registers we set the present flags in the 323 * cistpl_config_t if the register exists. The flags that we use 324 * for this are the same as the flags reguired for the Card Services 325 * RequestConfiguration function and they can be used by clients 326 * directly without requiring any remapping of values. 327 * 328 * XXX we don't handle TPCC_SBTPL subtuples yet 329 */ 330 331 uint32_t config_regs_present_map[] = { 332 CONFIG_OPTION_REG_PRESENT, /* COR present */ 333 CONFIG_STATUS_REG_PRESENT, /* STAT reg present */ 334 CONFIG_PINREPL_REG_PRESENT, /* PRR present */ 335 CONFIG_COPY_REG_PRESENT, /* COPY reg present */ 336 CONFIG_EXSTAT_REG_PRESENT, /* EXSTAT reg present */ 337 CONFIG_IOBASE0_REG_PRESENT, /* IOBASE0 reg present */ 338 CONFIG_IOBASE1_REG_PRESENT, /* IOBASE1 reg present */ 339 CONFIG_IOBASE2_REG_PRESENT, /* IOBASE2 reg present */ 340 CONFIG_IOBASE3_REG_PRESENT, /* IOBASE3 reg present */ 341 CONFIG_IOLIMIT_REG_PRESENT, /* IOLIMIT reg present */ 342 }; 343 344 uint32_t 345 cistpl_config_handler(cistpl_callout_t *co, cistpl_t *tp, 346 uint32_t flags, void *arg) 347 { 348 cisdata_t tpcc_sz; 349 int i, n, nrb, na, hr = 0; 350 351 /* 352 * nothing special about our flags, so just call the 353 * generic handler for this 354 */ 355 if (flags & HANDTPL_SET_FLAGS) 356 return (cis_no_tuple_handler(co, tp, flags, arg)); 357 358 /* 359 * We don't currently validate this tuple. This call will 360 * always set tp->flags |= CISTPLF_VALID. 361 */ 362 if (flags & HANDTPL_COPY_DONE) 363 return (cis_no_tuple_handler(co, tp, flags, arg)); 364 365 if (flags & HANDTPL_PARSE_LTUPLE) { 366 cistpl_config_t *cr = (cistpl_config_t *)arg; 367 int crn = 0; 368 369 RESET_TP(tp); 370 371 tpcc_sz = GET_BYTE(tp); /* config regs size fields */ 372 cr->last = GET_BYTE(tp); /* last config index */ 373 374 na = (tpcc_sz&3)+1; /* config regs address bytes */ 375 nrb = ((tpcc_sz>>2)&0x0f)+1; /* number of bytes in config */ 376 /* regs presence mask */ 377 378 /* 379 * Construct the base offset address for the config registers. 380 * We jump through these hoops because the base address 381 * can be between one and four bytes in length. 382 */ 383 cr->base = 0; 384 n = na; 385 while (n--) 386 cr->base |= ((GET_BYTE(tp) & 0x0ff) << 387 (8 * (na - (n+1)))); 388 389 /* 390 * Go through the config register presense mask bit by bit and 391 * figure out which config registers are present and which 392 * aren't. 393 * For the first ten config registers, set the appropriate 394 * bits in the cr->present member so that the caller 395 * doesn't have to do this. 396 */ 397 cr->nr = 0; 398 cr->present = 0; 399 n = nrb; 400 while (n--) { 401 for (i = 0; i < 8; i++, crn++) { 402 if (LOOK_BYTE(tp) & (1<<i)) { 403 if (crn < (sizeof (config_regs_present_map)/ 404 sizeof (uint32_t))) 405 cr->present |= 406 config_regs_present_map[crn]; 407 cr->nr++; 408 cr->hr = hr; 409 cr->regs[hr] = MAKE_CONFIG_REG_ADDR( 410 cr->base, hr); 411 } /* LOOK_BYTE */ 412 hr++; 413 } /* for */ 414 (void) GET_BYTE(tp); 415 } /* while */ 416 } 417 418 return (CISTPLF_NOERROR); 419 } 420 421 /* 422 * cistpl_device_handler - handler for the CISTPL_DEVICE, CISTPL_DEVICE_A, 423 * CISTPL_DEVICE_OC and CISTPL_DEVICE_OA tuples 424 * 425 * void *arg - points to a cistpl_device_t * where the 426 * information is stuffed into 427 * 428 * XXX - we only handle CISTPL_DEVICE_MAX_DEVICES device descriptions 429 * described in the tuple 430 */ 431 uint32_t 432 cistpl_device_handler(cistpl_callout_t *co, cistpl_t *tp, 433 uint32_t flags, void *arg) 434 { 435 cisdata_t dev_id; 436 437 /* 438 * nothing special about our flags, so just call the 439 * generic handler for this 440 */ 441 if (flags & HANDTPL_SET_FLAGS) 442 return (cis_no_tuple_handler(co, tp, flags, arg)); 443 444 /* 445 * We don't currently validate this tuple. This call will 446 * always set tp->flags |= CISTPLF_VALID. 447 */ 448 if (flags & HANDTPL_COPY_DONE) 449 return (cis_no_tuple_handler(co, tp, flags, arg)); 450 451 if (flags & HANDTPL_PARSE_LTUPLE) { 452 convert_speed_t convert_speed; 453 cistpl_device_t *dt = (cistpl_device_t *)arg; 454 cistpl_device_node_t *cdn; 455 456 /* 457 * XXX - fix this to look for more than one device definition 458 * XXX - fix this to handle the OC fields for 459 * CISTPL_DEVICE_OC and CISTPL_DEVICE_OA 460 */ 461 dt->num_devices = 1; 462 cdn = &dt->devnode[0]; 463 464 cdn->flags = 0; 465 466 RESET_TP(tp); 467 468 dev_id = GET_BYTE(tp); 469 470 /* 471 * Get the device speed code. If it's 7, then there is an 472 * extended speed code table in use, so parse that. 473 * If it's anything else, get the speed information 474 * directly from the device speed code. 475 */ 476 if ((dev_id & 7) == 7) { 477 cdn->nS_speed = cistpl_devspeed(tp, 0, CISTPL_DEVSPEED_EXT); 478 } else { 479 cdn->nS_speed = cistpl_devspeed(NULL, dev_id, 480 CISTPL_DEVSPEED_TABLE); 481 } 482 483 /* 484 * Convert the speed in nS to a device speed code. 485 * XXX - should check return code from cis_convert_devspeed() 486 */ 487 convert_speed.Attributes = CONVERT_NS_TO_DEVSPEED; 488 convert_speed.nS = cdn->nS_speed; 489 (void) cis_convert_devspeed(&convert_speed); 490 cdn->speed = convert_speed.devspeed; 491 492 if (dev_id & 8) 493 cdn->flags |= CISTPL_DEVICE_WPS; 494 495 /* 496 * Set the device type. Note that we take the raw value 497 * from the tuple and pass it back to the caller. 498 * If the device type codes in the standard change, 499 * we will have to change our flags as well. 500 */ 501 cdn->type = (dev_id>>4) & 0x0f; 502 503 /* 504 * XXX - what about the device_size byte? Is the spec wrong? 505 */ 506 cdn->size = GET_BYTE(tp); 507 /* check for end of list */ 508 if (cdn->size != 0x0ff) { 509 convert_size_t convert_size; 510 511 convert_size.devsize = cdn->size; 512 convert_size.Attributes = CONVERT_DEVSIZE_TO_BYTES; 513 (void) cis_convert_devsize(&convert_size); 514 cdn->size_in_bytes = convert_size.bytes; 515 } 516 } 517 518 return (CISTPLF_NOERROR); 519 } 520 521 /* 522 * cistpl_cftable_handler - handler for the CISTPL_CFTABLE_ENTRY tuple 523 * 524 * void *arg - points to a XXX where the information is stuffed into 525 * 526 * Return: CISTPLF_NOERROR - if no error parsing tuple 527 * HANDTPL_ERROR - if error parsing tuple 528 */ 529 extern uint32_t cistpl_cftable_io_size_table[]; 530 extern uint32_t cistpl_cftable_shift_table[]; 531 532 uint32_t 533 cistpl_cftable_handler(cistpl_callout_t *co, cistpl_t *tp, 534 uint32_t flags, void *arg) 535 { 536 cisdata_t tpce_indx, tpce_fs, tpce_td, sf, tpce_io, nr; 537 cisdata_t ior_desc, tpce_ir, tpce_msd; 538 int i, j; 539 540 /* 541 * nothing special about our flags, so just call the 542 * generic handler for this 543 */ 544 if (flags & HANDTPL_SET_FLAGS) 545 return (cis_no_tuple_handler(co, tp, flags, arg)); 546 547 /* 548 * We don't currently validate this tuple. This call will 549 * always set tp->flags |= CISTPLF_VALID. 550 */ 551 if (flags & HANDTPL_COPY_DONE) 552 return (cis_no_tuple_handler(co, tp, flags, arg)); 553 554 if (flags & HANDTPL_PARSE_LTUPLE) { 555 cistpl_cftable_entry_t *ce = (cistpl_cftable_entry_t *)arg; 556 557 RESET_TP(tp); 558 559 /* 560 * Check to see if we have an interface description byte. If 561 * we do, grab it and give it directly to the caller, and 562 * set a flag so the caller knows that it's there. 563 * We also setup the appropriate values in the ce->pin member 564 * so that clients can feed this value directly to the 565 * Card Services RequestConfiguration call. 566 */ 567 if ((tpce_indx = GET_BYTE(tp)) & CISTPL_CFTABLE_TPCE_IFM) { 568 ce->ifc = GET_BYTE(tp); 569 570 ce->pin = 0; 571 572 if (ce->ifc & CISTPL_CFTABLE_TPCE_IF_BVD) 573 ce->pin |= (PRR_BVD1_STATUS | PRR_BVD2_STATUS | 574 PRR_BVD1_EVENT | PRR_BVD2_EVENT); 575 if (ce->ifc & CISTPL_CFTABLE_TPCE_IF_WP) 576 ce->pin |= (PRR_WP_STATUS | PRR_WP_EVENT); 577 if (ce->ifc & CISTPL_CFTABLE_TPCE_IF_RDY) 578 ce->pin |= (PRR_READY_STATUS | PRR_READY_EVENT); 579 580 ce->flags |= CISTPL_CFTABLE_TPCE_IF; 581 } 582 583 /* 584 * Return the configuration index to the caller, and set the 585 * default configuration flag if this is a default 586 * configuration. 587 */ 588 ce->index = tpce_indx & CISTPL_CFTABLE_TPCE_CFGENTRYM; 589 if (tpce_indx & CISTPL_CFTABLE_TPCE_DEFAULTM) 590 ce->flags |= CISTPL_CFTABLE_TPCE_DEFAULT; 591 592 /* 593 * Feature selection flags. 594 */ 595 tpce_fs = GET_BYTE(tp); 596 597 /* 598 * See what types of power information are available, 599 * and if there is any, set the global power 600 * information flag as well as a flag for each 601 * power description available. 602 */ 603 if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_PWRM) { 604 cistpl_cftable_entry_pd_t *pd = &ce->pd; 605 606 ce->flags |= CISTPL_CFTABLE_TPCE_FS_PWR; 607 608 switch (tpce_fs & CISTPL_CFTABLE_TPCE_FS_PWRM) { 609 case CISTPL_CFTABLE_TPCE_FS_PWR_VPP2M: 610 pd->flags |= CISTPL_CFTABLE_TPCE_FS_PWR_VPP2; 611 /* FALLTHROUGH */ 612 case CISTPL_CFTABLE_TPCE_FS_PWR_VPP1M: 613 pd->flags |= CISTPL_CFTABLE_TPCE_FS_PWR_VPP1; 614 /* FALLTHROUGH */ 615 case CISTPL_CFTABLE_TPCE_FS_PWR_VCCM: 616 pd->flags |= CISTPL_CFTABLE_TPCE_FS_PWR_VCC; 617 } /* switch */ 618 } /* if (CISTPL_CFTABLE_TPCE_FS_PWRM) */ 619 620 /* 621 * Set up the global memory information flag. 622 */ 623 if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_MEMM) 624 ce->flags |= CISTPL_CFTABLE_TPCE_FS_MEM; 625 626 /* 627 * Parse the various power description structures. 628 */ 629 if (ce->flags & CISTPL_CFTABLE_TPCE_FS_PWR) { 630 cistpl_cftable_entry_pd_t *pd = &ce->pd; 631 cistpl_cftable_entry_pwr_t *pwr; 632 /* 633 * Collect any Vcc information. 634 */ 635 if (pd->flags & CISTPL_CFTABLE_TPCE_FS_PWR_VCC) { 636 pwr = &pd->pd_vcc; 637 cistpl_pd_parse(tp, pwr); 638 } 639 /* 640 * Collect any Vpp1 information. 641 */ 642 if (pd->flags & CISTPL_CFTABLE_TPCE_FS_PWR_VPP1) { 643 pwr = &pd->pd_vpp1; 644 cistpl_pd_parse(tp, pwr); 645 } 646 /* 647 * Collect any Vpp2 information. 648 */ 649 if (pd->flags & CISTPL_CFTABLE_TPCE_FS_PWR_VPP2) { 650 pwr = &pd->pd_vpp2; 651 cistpl_pd_parse(tp, pwr); 652 } 653 } /* if (CISTPL_CFTABLE_TPCE_FS_PWR) */ 654 655 /* 656 * Check to see if there's any timing information, and if 657 * so, parse the tuple data and store it in the 658 * caller's structure. Set a flag in the global 659 * flag field indicating that there is timing information. 660 */ 661 if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_TDM) { 662 convert_speed_t convert_speed; 663 cistpl_cftable_entry_speed_t *sp = &ce->speed; 664 ce->flags |= CISTPL_CFTABLE_TPCE_FS_TD; 665 tpce_td = GET_BYTE(tp); 666 /* 667 * Parse TPCE_TD to get the various timing 668 * scale factors. Each scale factor has 669 * a value that indicates that the particular 670 * timing parameter doesn't exist. 671 */ 672 if ((sf = (tpce_td & 673 CISTPL_CFTABLE_TPCE_FS_TD_WAITM)) != 674 CISTPL_CFTABLE_TPCE_FS_TD_WAITM) { 675 sp->nS_wait = cistpl_devspeed(tp, 676 GET_TPCE_FS_TD_WAITS(sf), 677 CISTPL_DEVSPEED_EXT); 678 convert_speed.Attributes = 679 CONVERT_NS_TO_DEVSPEED; 680 convert_speed.nS = sp->nS_wait; 681 (void) cis_convert_devspeed(&convert_speed); 682 sp->wait = convert_speed.devspeed; 683 sp->flags |= CISTPL_CFTABLE_TPCE_FS_TD_WAIT; 684 } 685 686 if ((sf = (tpce_td & CISTPL_CFTABLE_TPCE_FS_TD_RDYM)) != 687 CISTPL_CFTABLE_TPCE_FS_TD_RDYM) { 688 sp->nS_rdybsy = cistpl_devspeed(tp, 689 GET_TPCE_FS_TD_RDYS(sf), 690 CISTPL_DEVSPEED_EXT); 691 convert_speed.Attributes = 692 CONVERT_NS_TO_DEVSPEED; 693 convert_speed.nS = sp->nS_rdybsy; 694 (void) cis_convert_devspeed(&convert_speed); 695 sp->rdybsy = convert_speed.devspeed; 696 sp->flags |= CISTPL_CFTABLE_TPCE_FS_TD_RDY; 697 } 698 699 if ((sf = (tpce_td & 700 CISTPL_CFTABLE_TPCE_FS_TD_RSVDM)) != 701 CISTPL_CFTABLE_TPCE_FS_TD_RSVDM) { 702 sp->nS_rsvd = cistpl_devspeed(tp, 703 GET_TPCE_FS_TD_RSVDS(sf), 704 CISTPL_DEVSPEED_EXT); 705 convert_speed.Attributes = 706 CONVERT_NS_TO_DEVSPEED; 707 convert_speed.nS = sp->nS_rsvd; 708 (void) cis_convert_devspeed(&convert_speed); 709 sp->rsvd = convert_speed.devspeed; 710 sp->flags |= CISTPL_CFTABLE_TPCE_FS_TD_RSVD; 711 } 712 } /* if (CISTPL_CFTABLE_TPCE_FS_TDM) */ 713 714 715 /* 716 * Parse any I/O address information. If there is I/O 717 * inforamtion, set a flag in the global flag field 718 * to let the caller know. 719 */ 720 if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_IOM) { 721 cistpl_cftable_entry_io_t *io = &ce->io; 722 723 ce->flags |= CISTPL_CFTABLE_TPCE_FS_IO; 724 tpce_io = GET_BYTE(tp); 725 /* 726 * Pass any I/O flags that are in the tuple directly 727 * to the caller. 728 */ 729 io->flags = tpce_io; 730 io->addr_lines = tpce_io & 731 CISTPL_CFTABLE_TPCE_FS_IO_ALM; 732 /* 733 * If there are any ranges, extract the number of 734 * ranges and the range descriptions. 735 */ 736 if (tpce_io & CISTPL_CFTABLE_TPCE_FS_IO_RANGEM) { 737 cistpl_cftable_entry_io_range_t *ior; 738 ior_desc = GET_BYTE(tp); 739 /* 740 * Number of I/O ranges is the value specified 741 * in the tuple plus one, so there's 742 * always at least one I/O range if the 743 * CISTPL_CFTABLE_TPCE_FS_IO_RANGEM bit 744 * in the I/O flags register is set. 745 */ 746 nr = (ior_desc & 0x0f) + 1; 747 io->ranges = nr; 748 /* 749 * Cycle through each I/O range. 750 */ 751 for (i = 0; i < (int)nr; i++) { 752 ior = &io->range[i]; 753 ior->addr = 0; 754 ior->length = 0; 755 /* 756 * Gather the address information. 757 * It's OK if there's no address 758 * information in which case this 759 * loop will never execute. 760 */ 761 for (j = 0; j < 762 cistpl_cftable_io_size_table[ 763 (ior_desc>>4)&3]; 764 j++) 765 ior->addr |= (GET_BYTE(tp) << 766 cistpl_cftable_shift_table[j]); 767 /* 768 * Gather the length information. 769 * It's OK if there's no length 770 * information in which case this 771 * loop will never execute. 772 */ 773 for (j = 0; j < 774 cistpl_cftable_io_size_table[ 775 (ior_desc>>6)&3]; 776 j++) 777 ior->length |= (GET_BYTE(tp) << 778 cistpl_cftable_shift_table[j]); 779 } /* for (nr) */ 780 } /* if (CISTPL_CFTABLE_TPCE_FS_IO_RANGEM) */ 781 } /* if (CISTPL_CFTABLE_TPCE_FS_IOM) */ 782 783 /* 784 * Parse any IRQ information. If there is IRQ inforamtion, 785 * set a flag in the global flag field to let the 786 * caller know. 787 */ 788 if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_IRQM) { 789 cistpl_cftable_entry_irq_t *irq = &ce->irq; 790 791 ce->flags |= CISTPL_CFTABLE_TPCE_FS_IRQ; 792 tpce_ir = GET_BYTE(tp); 793 /* 794 * Pass any IRQ flags that are in the tuple directly 795 * to the caller. 796 */ 797 irq->flags = tpce_ir; 798 /* 799 * Check for and parse the extended IRQ bitmask 800 * if it exists. 801 */ 802 if (tpce_ir & CISTPL_CFTABLE_TPCE_FS_IRQ_MASKM) { 803 irq->irqs = GET_BYTE(tp) & 0x0ff; 804 irq->irqs |= (GET_BYTE(tp) << 8)&0x0ff00; 805 } else { 806 irq->irqs = (1<< (tpce_ir&0x0f)); 807 } 808 } /* if (CISTPL_CFTABLE_TPCE_FS_IRQM) */ 809 810 /* 811 * Parse any memory information. 812 * 813 * XXX - should be a cleaner way to parse this information. 814 */ 815 if (ce->flags & CISTPL_CFTABLE_TPCE_FS_MEM) { 816 cistpl_cftable_entry_mem_t *mem = &ce->mem; 817 cistpl_cftable_entry_mem_window_t *win; 818 /* 819 * Switch on the type of memory description 820 * information that is available. 821 */ 822 switch (tpce_fs & CISTPL_CFTABLE_TPCE_FS_MEMM) { 823 /* 824 * variable length memory space description 825 */ 826 case CISTPL_CFTABLE_TPCE_FS_MEM3M: 827 mem->flags |= CISTPL_CFTABLE_TPCE_FS_MEM3; 828 /* memory space descriptor */ 829 tpce_msd = GET_BYTE(tp); 830 mem->windows = ((tpce_msd & 831 (CISTPL_CFTABLE_ENTRY_MAX_MEM_WINDOWS - 832 1)) + 1); 833 /* 834 * If there's host address information, let 835 * the caller know. 836 */ 837 if (tpce_msd & CISTPL_CFTABLE_TPCE_FS_MEM_HOSTM) 838 mem->flags |= 839 CISTPL_CFTABLE_TPCE_FS_MEM_HOST; 840 /* 841 * Cycle through each window space description 842 * and collect all the interesting bits. 843 */ 844 for (i = 0; i < mem->windows; i++) { 845 win = &mem->window[i]; 846 win->length = 0; 847 win->card_addr = 0; 848 win->host_addr = 0; 849 /* 850 * Gather the length information. 851 * It's OK if there's no length 852 * information in which case this 853 * loop will never execute. 854 */ 855 for (j = 0; j < 856 (int)((tpce_msd>>3)&3); j++) 857 win->length |= (GET_BYTE(tp) << 858 cistpl_cftable_shift_table[j]); 859 /* 860 * Gather the card address information. 861 * It's OK if there's no card 862 * address information in which 863 * case this loop will never 864 * execute. 865 */ 866 for (j = 0; j < 867 (int)((tpce_msd>>5)&3); j++) 868 win->card_addr |= 869 (GET_BYTE(tp) << 870 cistpl_cftable_shift_table[j]); 871 /* 872 * If there's a host address 873 * description, grab that 874 * as well. 875 */ 876 if (mem->flags & 877 CISTPL_CFTABLE_TPCE_FS_MEM_HOST) { 878 /* 879 * Gather the host address 880 * information. It's OK 881 * if there's no host 882 * address information in 883 * which case this loop 884 * will never execute. 885 * Note that we use the card 886 * address size to 887 * determine how many 888 * bytes of host address 889 * are present. 890 */ 891 for (j = 0; j < 892 (int)((tpce_msd>>5)&3); 893 j++) 894 win->host_addr |= 895 (GET_BYTE(tp) << 896 cistpl_cftable_shift_table[j]); 897 } else { 898 /* 899 * No host address information, 900 * so the host address is 901 * equal to the card 902 * address. 903 */ 904 win->host_addr = win->card_addr; 905 } 906 } /* for (i<mem->windows) */ 907 break; 908 /* 909 * single length and card base address specified 910 */ 911 case CISTPL_CFTABLE_TPCE_FS_MEM2M: 912 mem->flags |= CISTPL_CFTABLE_TPCE_FS_MEM2; 913 win = &mem->window[0]; 914 mem->windows = 1; 915 /* 916 * Construct the size of the window. 917 */ 918 win->length = GET_BYTE(tp); 919 win->length |= (GET_BYTE(tp)<<8); 920 win->length *= 921 CISTPL_CFTABLE_TPCE_FS_MEM_PGSIZE; 922 923 /* 924 * Construct the card base address. 925 */ 926 win->card_addr = GET_BYTE(tp); 927 win->card_addr |= (GET_BYTE(tp)<<8); 928 win->card_addr *= 929 CISTPL_CFTABLE_TPCE_FS_MEM_PGSIZE; 930 931 /* 932 * In this mode, both the host base address 933 * and the card base address are equal. 934 */ 935 win->host_addr = win->card_addr; 936 break; 937 /* 938 * single length specified 939 */ 940 case CISTPL_CFTABLE_TPCE_FS_MEM1M: 941 mem->flags |= CISTPL_CFTABLE_TPCE_FS_MEM1; 942 win = &mem->window[0]; 943 mem->windows = 1; 944 win->card_addr = 0; 945 win->host_addr = 0; 946 /* 947 * Construct the size of the window. 948 */ 949 win->length = GET_BYTE(tp); 950 win->length |= (GET_BYTE(tp)<<8); 951 win->length *= 952 CISTPL_CFTABLE_TPCE_FS_MEM_PGSIZE; 953 break; 954 } /* switch (CISTPL_CFTABLE_TPCE_FS_MEMM) */ 955 } /* if (CISTPL_CFTABLE_TPCE_FS_MEM) */ 956 957 /* 958 * Check for and parse any miscellaneous information. 959 * 960 * We only understand how to parse the first 961 * CISTPL_CFTABLE_TPCE_FS_MISC_MAX extension 962 * bytes specified in the PC Card 95 standard; 963 * we throw away any other extension bytes that 964 * are past these bytes. 965 * XXX Note that the assumption here is that the 966 * size of cistpl_cftable_entry_misc_t->flags 967 * is at least CISTPL_CFTABLE_TPCE_FS_MISC_MAX 968 * bytes in length. 969 */ 970 if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_MISCM) { 971 cistpl_cftable_entry_misc_t *misc = &ce->misc; 972 int mb = CISTPL_CFTABLE_TPCE_FS_MISC_MAX; 973 974 ce->flags |= CISTPL_CFTABLE_TPCE_FS_MISC; 975 misc->flags = 0; 976 977 do { 978 if (mb) { 979 misc->flags = (misc->flags << 8) | LOOK_BYTE(tp); 980 mb--; 981 } 982 } while ((GET_BYTE(tp) & CISTPL_EXT_BIT) && 983 (!(tp->flags & CISTPLF_MEM_ERR))); 984 985 /* 986 * Check to see if we tried to read past the 987 * end of the tuple data; if we have, 988 * there's no point in trying to parse 989 * any more of the tuple. 990 */ 991 if (tp->flags & CISTPLF_MEM_ERR) 992 return (HANDTPL_ERROR); 993 } /* if (CISTPL_CFTABLE_TPCE_FS_MISCM) */ 994 995 /* 996 * Check for and parse any additional subtuple 997 * information. We know that there is 998 * additional information if we haven't 999 * reached the end of the tuple data area 1000 * and if the additional information is 1001 * in standard tuple format. 1002 * If we don't recognize the additional info, 1003 * then just silently ignore it, don't 1004 * flag it as an error. 1005 */ 1006 #ifdef PARSE_STCE_TUPLES 1007 if (GET_LEN(tp) > 0) { 1008 1009 ce->flags |= CISTPL_CFTABLE_TPCE_FS_STCE_EV 1010 ce->flags |= CISTPL_CFTABLE_TPCE_FS_STCE_PD 1011 #endif 1012 1013 } /* if (HANDTPL_PARSE_LTUPLE) */ 1014 1015 return (CISTPLF_NOERROR); 1016 } 1017 1018 /* 1019 * cistpl_pd_parse - read and parse a power description structure 1020 * 1021 * cisdata_t **ddp - pointer to pointer tuple data area 1022 * cistpl_cftable_entry_pwr_t *pd - pointer to local power description 1023 * structure 1024 */ 1025 static void 1026 cistpl_pd_parse(cistpl_t *tp, cistpl_cftable_entry_pwr_t *pd) 1027 { 1028 cisdata_t pdesc; 1029 1030 pdesc = GET_BYTE(tp); /* power description selector */ 1031 1032 /* nominal supply voltage */ 1033 if (pdesc & CISTPL_CFTABLE_PD_NOMV) { 1034 pd->nomV = cistpl_expd_parse(tp, &pd->nomV_flags) / 100; 1035 pd->nomV_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS); 1036 } 1037 1038 /* minimum supply voltage */ 1039 if (pdesc & CISTPL_CFTABLE_PD_MINV) { 1040 pd->minV = cistpl_expd_parse(tp, &pd->minV_flags) / 100; 1041 pd->minV_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS); 1042 } 1043 1044 /* maximum supply voltage */ 1045 if (pdesc & CISTPL_CFTABLE_PD_MAXV) { 1046 pd->maxV = cistpl_expd_parse(tp, &pd->maxV_flags) / 100; 1047 pd->maxV_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS); 1048 } 1049 1050 /* continuous supply current */ 1051 if (pdesc & CISTPL_CFTABLE_PD_STATICI) { 1052 pd->staticI_flags |= CISTPL_CFTABLE_PD_MUL10; 1053 pd->staticI = cistpl_expd_parse(tp, &pd->staticI_flags); 1054 pd->staticI_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS); 1055 } 1056 1057 /* maximum current required averaged over 1 second */ 1058 if (pdesc & CISTPL_CFTABLE_PD_AVGI) { 1059 pd->avgI_flags |= CISTPL_CFTABLE_PD_MUL10; 1060 pd->avgI = cistpl_expd_parse(tp, &pd->avgI_flags); 1061 pd->avgI_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS); 1062 } 1063 1064 /* maximum current required averaged over 10mS */ 1065 if (pdesc & CISTPL_CFTABLE_PD_PEAKI) { 1066 pd->peakI_flags |= CISTPL_CFTABLE_PD_MUL10; 1067 pd->peakI = cistpl_expd_parse(tp, &pd->peakI_flags); 1068 pd->peakI_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS); 1069 } 1070 1071 /* power down supply curent required */ 1072 if (pdesc & CISTPL_CFTABLE_PD_PDOWNI) { 1073 pd->pdownI_flags |= CISTPL_CFTABLE_PD_MUL10; 1074 pd->pdownI = cistpl_expd_parse(tp, &pd->pdownI_flags); 1075 pd->pdownI_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS); 1076 } 1077 } 1078 1079 /* 1080 * cistpl_expd_parse - read and parse an extended power description structure 1081 * 1082 * cistpl_t *tp - pointer to pointer tuple data area 1083 * int *flags - flags that get for this parameter: 1084 * CISTPL_CFTABLE_PD_NC_SLEEP - no connection on 1085 * sleep/power down 1086 * CISTPL_CFTABLE_PD_ZERO - zero value required 1087 * CISTPL_CFTABLE_PD_NC - no connection ever 1088 * 1089 * The power consumption is returned in the following units: 1090 * 1091 * voltage - milliVOLTS 1092 * current - microAMPS 1093 */ 1094 extern cistpl_pd_struct_t cistpl_pd_struct; 1095 1096 uint32_t 1097 cistpl_expd_parse(cistpl_t *tp, uint32_t *flags) 1098 { 1099 cisdata_t pdesc; 1100 uint32_t exponent, mantisa, val, digits = 0; 1101 1102 /* 1103 * Get the power description parameter byte and break it up 1104 * into mantissa and exponent. 1105 */ 1106 pdesc = GET_BYTE(tp); 1107 exponent = pdesc&7; 1108 mantisa = (pdesc>>3)&0x0f; 1109 1110 if (pdesc & CISTPL_EXT_BIT) { 1111 do { 1112 if (LOOK_BYTE(tp) <= 0x63) 1113 digits = LOOK_BYTE(tp); 1114 if (LOOK_BYTE(tp) == CISTPL_CFTABLE_PD_NC_SLEEPM) 1115 *flags |= CISTPL_CFTABLE_PD_NC_SLEEP; 1116 if (LOOK_BYTE(tp) == CISTPL_CFTABLE_PD_ZEROM) 1117 *flags |= CISTPL_CFTABLE_PD_ZERO; 1118 if (LOOK_BYTE(tp) == CISTPL_CFTABLE_PD_NCM) 1119 *flags |= CISTPL_CFTABLE_PD_NC; 1120 } while (GET_BYTE(tp) & CISTPL_EXT_BIT); 1121 } 1122 1123 val = CISTPL_PD_MAN(mantisa) * CISTPL_PD_EXP(exponent); 1124 1125 /* 1126 * If we have to multiply the power value by ten, then just 1127 * don't bother dividing. 1128 */ 1129 if (! (*flags & CISTPL_CFTABLE_PD_MUL10)) 1130 val = val/10; /* do this since our mantissa table is X 10 */ 1131 1132 /* 1133 * If we need to add some digits to the right of the decimal, do 1134 * that here. 1135 */ 1136 if (exponent) 1137 val = val + (digits * CISTPL_PD_EXP(exponent-1)); 1138 1139 val /= 1000; 1140 1141 return (val); 1142 } 1143 1144 /* 1145 * cistpl_devspeed - returns device speed in nS 1146 * 1147 * cistpl_t *tp - tuple pointer. 1148 * cisdata_t spindex - device speed table index 1149 * int flags - operation flags 1150 * CISTPL_DEVSPEED_TABLE: 1151 * Use the spindex argument as an index into a simple 1152 * device speed table. ref: PCMCIA Release 2.01 1153 * Card Metaformat pg. 5-14 table 5-12. 1154 * When this flag is set, the spindex argument is ignored. 1155 * CISTPL_DEVSPEED_EXT: 1156 * Use the tp argument to access the 1157 * tuple data area containing an extended speed 1158 * code table. ref: PCMCIA Release 2.01 Card 1159 * Metaformat pg. 5-15 table 5-13. 1160 * The tp->read argument must point to the first byte of 1161 * an extended speed code table. 1162 * When this flag is set, the spindex argument is 1163 * used as a power-of-10 scale factor. We only allow 1164 * a maximum scale factor of 10^16. 1165 * 1166 * The device speed is returned in nS for all combinations of flags and 1167 * speed table entries. 1168 * 1169 * Note if you pass the CISTPL_DEVSPEED_TABLE with a spindex index that 1170 * refers to an extended speed table, you will get back an undefined 1171 * speed value. 1172 */ 1173 extern cistpl_devspeed_struct_t cistpl_devspeed_struct; 1174 1175 uint32_t 1176 cistpl_devspeed(cistpl_t *tp, cisdata_t spindex, uint32_t flags) 1177 { 1178 int scale = 1, first; 1179 cisdata_t exspeed; 1180 int exponent, mantisa; 1181 uint32_t speed; 1182 1183 switch (flags) { 1184 case CISTPL_DEVSPEED_TABLE: 1185 speed = CISTPL_DEVSPEED_TBL(spindex); 1186 break; 1187 case CISTPL_DEVSPEED_EXT: 1188 do { 1189 exspeed = GET_BYTE(tp); 1190 first = 1; 1191 if (first) { 1192 /* 1193 * XXX - ugh! we don't understand additional 1194 * exspeed bytes 1195 */ 1196 first = 0; 1197 exponent = (exspeed & 0x07); 1198 mantisa = (exspeed >> 3) & 0x0f; 1199 spindex &= 0x0f; /* only allow 10^16 */ 1200 while (spindex--) 1201 scale *= 10; 1202 } /* if (first) */ 1203 } while (exspeed & CISTPL_EXT_BIT); 1204 speed = scale * CISTPL_DEVSPEED_MAN(mantisa) * 1205 CISTPL_DEVSPEED_EXP(exponent); 1206 speed = speed/10; /* XXX - mantissa table is all X 10 */ 1207 break; 1208 default: 1209 break; 1210 } 1211 1212 return (speed); 1213 } 1214 1215 /* 1216 * cistpl_vers_2_handler - handler for the CISTPL_VERS_2 tuple 1217 * 1218 * void *arg - points to a XXX where the information is stuffed into 1219 */ 1220 uint32_t 1221 cistpl_vers_2_handler(cistpl_callout_t *co, cistpl_t *tp, 1222 uint32_t flags, void *arg) 1223 { 1224 /* 1225 * nothing special about our flags, so just call the 1226 * generic handler for this 1227 */ 1228 if (flags & HANDTPL_SET_FLAGS) 1229 return (cis_no_tuple_handler(co, tp, flags, arg)); 1230 1231 /* 1232 * We don't currently validate this tuple. This call will 1233 * always set tp->flags |= CISTPLF_VALID. 1234 */ 1235 if (flags & HANDTPL_COPY_DONE) 1236 return (cis_no_tuple_handler(co, tp, flags, arg)); 1237 1238 if (flags & HANDTPL_PARSE_LTUPLE) { 1239 cistpl_vers_2_t *cs = (cistpl_vers_2_t *)arg; 1240 1241 RESET_TP(tp); 1242 1243 cs->vers = GET_BYTE(tp); 1244 cs->comply = GET_BYTE(tp); 1245 cs->dindex = GET_SHORT(tp); 1246 1247 cs->reserved = GET_SHORT(tp); 1248 1249 cs->vspec8 = GET_BYTE(tp); 1250 cs->vspec9 = GET_BYTE(tp); 1251 cs->nhdr = GET_BYTE(tp); 1252 1253 (void) strcpy(cs->oem, cis_getstr(tp)); 1254 1255 if (GET_LEN(tp) > 0) 1256 (void) strcpy(cs->info, cis_getstr(tp)); 1257 else 1258 (void) strcpy(cs->info, "(no info)"); 1259 } 1260 1261 return (CISTPLF_NOERROR); 1262 } 1263 1264 /* 1265 * cistpl_jedec_handler - handler for JEDEC C and JEDEC A tuples 1266 * 1267 * void *arg - points to a XXX where the information is stuffed into 1268 */ 1269 uint32_t 1270 cistpl_jedec_handler(cistpl_callout_t *co, cistpl_t *tp, 1271 uint32_t flags, void *arg) 1272 { 1273 /* 1274 * nothing special about our flags, so just call the 1275 * generic handler for this 1276 */ 1277 if (flags & HANDTPL_SET_FLAGS) 1278 return (cis_no_tuple_handler(co, tp, flags, arg)); 1279 1280 /* 1281 * We don't currently validate this tuple. This call will 1282 * always set tp->flags |= CISTPLF_VALID. 1283 */ 1284 if (flags & HANDTPL_COPY_DONE) 1285 return (cis_no_tuple_handler(co, tp, flags, arg)); 1286 1287 if (flags & HANDTPL_PARSE_LTUPLE) { 1288 int nid; 1289 cistpl_jedec_t *cs = (cistpl_jedec_t *)arg; 1290 1291 RESET_TP(tp); 1292 1293 for (nid = 0; GET_LEN(tp) > 0 && 1294 nid < CISTPL_JEDEC_MAX_IDENTIFIERS && 1295 LOOK_BYTE(tp) != 0xFF; nid++) { 1296 cs->jid[nid].id = GET_BYTE(tp); 1297 cs->jid[nid].info = GET_BYTE(tp); 1298 } 1299 cs->nid = nid; 1300 } 1301 1302 return (CISTPLF_NOERROR); 1303 } 1304 1305 /* 1306 * cistpl_format_handler - handler for the CISTPL_FORMAT and 1307 * CISTPL_FORMAT_A tuples 1308 */ 1309 uint32_t 1310 cistpl_format_handler(cistpl_callout_t *co, cistpl_t *tp, 1311 uint32_t flags, void *arg) 1312 { 1313 /* 1314 * nothing special about our flags, so just call the 1315 * generic handler for this 1316 */ 1317 if (flags & HANDTPL_SET_FLAGS) 1318 return (cis_no_tuple_handler(co, tp, flags, arg)); 1319 1320 /* 1321 * We don't currently validate this tuple. This call will 1322 * always set tp->flags |= CISTPLF_VALID. 1323 */ 1324 if (flags & HANDTPL_COPY_DONE) 1325 return (cis_no_tuple_handler(co, tp, flags, arg)); 1326 1327 if (flags & HANDTPL_PARSE_LTUPLE) { 1328 cistpl_format_t *cs = (cistpl_format_t *)arg; 1329 1330 RESET_TP(tp); 1331 1332 cs->type = GET_BYTE(tp); 1333 cs->edc_length = LOOK_BYTE(tp) & EDC_LENGTH_MASK; 1334 cs->edc_type = ((uint32_t)GET_BYTE(tp) >> EDC_TYPE_SHIFT) & 1335 EDC_TYPE_MASK; 1336 cs->offset = GET_LONG(tp); 1337 cs->nbytes = GET_LONG(tp); 1338 1339 switch (cs->type) { 1340 case TPLFMTTYPE_DISK: 1341 cs->dev.disk.bksize = GET_SHORT(tp); 1342 cs->dev.disk.nblocks = GET_LONG(tp); 1343 cs->dev.disk.edcloc = GET_LONG(tp); 1344 break; 1345 1346 case TPLFMTTYPE_MEM: 1347 cs->dev.mem.flags = GET_BYTE(tp); 1348 cs->dev.mem.reserved = GET_BYTE(tp); 1349 cs->dev.mem.address = (caddr_t)(uintptr_t)GET_LONG(tp); 1350 cs->dev.disk.edcloc = GET_LONG(tp); 1351 break; 1352 default: 1353 /* don't know about any other type */ 1354 break; 1355 } 1356 } 1357 1358 return (CISTPLF_NOERROR); 1359 } 1360 1361 /* 1362 * cistpl_geometry_handler - handler for the CISTPL_GEOMETRY tuple 1363 * 1364 * void *arg - points to a XXX where the information is stuffed into 1365 */ 1366 uint32_t 1367 cistpl_geometry_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags, 1368 void *arg) 1369 { 1370 /* 1371 * nothing special about our flags, so just call the 1372 * generic handler for this 1373 */ 1374 if (flags & HANDTPL_SET_FLAGS) 1375 return (cis_no_tuple_handler(co, tp, flags, arg)); 1376 1377 /* 1378 * We don't currently validate this tuple. This call will 1379 * always set tp->flags |= CISTPLF_VALID. 1380 */ 1381 if (flags & HANDTPL_COPY_DONE) 1382 return (cis_no_tuple_handler(co, tp, flags, arg)); 1383 1384 if (flags & HANDTPL_PARSE_LTUPLE) { 1385 cistpl_geometry_t *cs = (cistpl_geometry_t *)arg; 1386 1387 RESET_TP(tp); 1388 cs->spt = GET_BYTE(tp); 1389 cs->tpc = GET_BYTE(tp); 1390 cs->ncyl = GET_SHORT(tp); 1391 } 1392 return (CISTPLF_NOERROR); 1393 } 1394 1395 /* 1396 * cistpl_byteorder_handler - handler for the CISTPL_BYTEORDER tuple 1397 * 1398 * void *arg - points to a XXX where the information is stuffed into 1399 */ 1400 uint32_t 1401 cistpl_byteorder_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags, 1402 void *arg) 1403 { 1404 /* 1405 * nothing special about our flags, so just call the 1406 * generic handler for this 1407 */ 1408 if (flags & HANDTPL_SET_FLAGS) 1409 return (cis_no_tuple_handler(co, tp, flags, arg)); 1410 1411 /* 1412 * We don't currently validate this tuple. This call will 1413 * always set tp->flags |= CISTPLF_VALID. 1414 */ 1415 if (flags & HANDTPL_COPY_DONE) 1416 return (cis_no_tuple_handler(co, tp, flags, arg)); 1417 1418 if (flags & HANDTPL_PARSE_LTUPLE) { 1419 cistpl_byteorder_t *cs = (cistpl_byteorder_t *)arg; 1420 1421 RESET_TP(tp); 1422 cs->order = GET_BYTE(tp); 1423 cs->map = GET_BYTE(tp); 1424 } 1425 return (CISTPLF_NOERROR); 1426 } 1427 1428 /* 1429 * cistpl_date_handler - handler for CISTPL_DATE card format tuple 1430 * 1431 * void *arg - points to a cistpl_date_t * where the 1432 * information is stuffed into 1433 */ 1434 uint32_t 1435 cistpl_date_handler(cistpl_callout_t *co, cistpl_t *tp, 1436 uint32_t flags, void *arg) 1437 { 1438 /* 1439 * nothing special about our flags, so just call the 1440 * generic handler for this 1441 */ 1442 if (flags & HANDTPL_SET_FLAGS) 1443 return (cis_no_tuple_handler(co, tp, flags, arg)); 1444 1445 /* 1446 * We don't currently validate this tuple. This call will 1447 * always set tp->flags |= CISTPLF_VALID. 1448 */ 1449 if (flags & HANDTPL_COPY_DONE) 1450 return (cis_no_tuple_handler(co, tp, flags, arg)); 1451 1452 if (flags & HANDTPL_PARSE_LTUPLE) { 1453 cistpl_date_t *cs = (cistpl_date_t *)arg; 1454 1455 RESET_TP(tp); 1456 cs->time = GET_SHORT(tp); 1457 cs->day = GET_SHORT(tp); 1458 } 1459 return (CISTPLF_NOERROR); 1460 } 1461 1462 /* 1463 * cistpl_battery_handler - handler for CISTPL_BATTERY battery replacement 1464 * date tuple 1465 * 1466 * void *arg - points to a cistpl_battery_t * where the 1467 * information is stuffed into 1468 */ 1469 uint32_t 1470 cistpl_battery_handler(cistpl_callout_t *co, cistpl_t *tp, 1471 uint32_t flags, void *arg) 1472 { 1473 /* 1474 * nothing special about our flags, so just call the 1475 * generic handler for this 1476 */ 1477 if (flags & HANDTPL_SET_FLAGS) 1478 return (cis_no_tuple_handler(co, tp, flags, arg)); 1479 1480 /* 1481 * We don't currently validate this tuple. This call will 1482 * always set tp->flags |= CISTPLF_VALID. 1483 */ 1484 if (flags & HANDTPL_COPY_DONE) 1485 return (cis_no_tuple_handler(co, tp, flags, arg)); 1486 1487 if (flags & HANDTPL_PARSE_LTUPLE) { 1488 cistpl_battery_t *cs = (cistpl_battery_t *)arg; 1489 1490 RESET_TP(tp); 1491 cs->rday = GET_SHORT(tp); 1492 cs->xday = GET_SHORT(tp); 1493 } 1494 return (CISTPLF_NOERROR); 1495 } 1496 1497 /* 1498 * cistpl_org_handler - handler for CISTPL_ORG data organization tuple 1499 * 1500 * void *arg - points to a cistpl_org_t * where the 1501 * information is stuffed into 1502 */ 1503 uint32_t 1504 cistpl_org_handler(cistpl_callout_t *co, cistpl_t *tp, 1505 uint32_t flags, void *arg) 1506 { 1507 /* 1508 * nothing special about our flags, so just call the 1509 * generic handler for this 1510 */ 1511 if (flags & HANDTPL_SET_FLAGS) 1512 return (cis_no_tuple_handler(co, tp, flags, arg)); 1513 1514 /* 1515 * We don't currently validate this tuple. This call will 1516 * always set tp->flags |= CISTPLF_VALID. 1517 */ 1518 if (flags & HANDTPL_COPY_DONE) 1519 return (cis_no_tuple_handler(co, tp, flags, arg)); 1520 1521 if (flags & HANDTPL_PARSE_LTUPLE) { 1522 cistpl_org_t *cs = (cistpl_org_t *)arg; 1523 1524 RESET_TP(tp); 1525 cs->type = GET_BYTE(tp); 1526 1527 (void) strcpy(cs->desc, cis_getstr(tp)); 1528 } 1529 1530 return (CISTPLF_NOERROR); 1531 } 1532 1533 1534 /* 1535 * cistpl_manfid_handler - handler for CISTPL_MANFID, the manufacturer ID tuple 1536 * 1537 * void *arg - points to a XXX where the information is stuffed into 1538 */ 1539 uint32_t 1540 cistpl_manfid_handler(cistpl_callout_t *co, cistpl_t *tp, 1541 uint32_t flags, void *arg) 1542 { 1543 /* 1544 * nothing special about our flags, so just call the 1545 * generic handler for this 1546 */ 1547 if (flags & HANDTPL_SET_FLAGS) 1548 return (cis_no_tuple_handler(co, tp, flags, arg)); 1549 1550 /* 1551 * We don't currently validate this tuple. This call will 1552 * always set tp->flags |= CISTPLF_VALID. 1553 */ 1554 if (flags & HANDTPL_COPY_DONE) 1555 return (cis_no_tuple_handler(co, tp, flags, arg)); 1556 1557 if (flags & HANDTPL_PARSE_LTUPLE) { 1558 cistpl_manfid_t *cs = (cistpl_manfid_t *)arg; 1559 1560 RESET_TP(tp); 1561 cs->manf = GET_SHORT(tp); 1562 cs->card = GET_SHORT(tp); 1563 } 1564 return (CISTPLF_NOERROR); 1565 } 1566 1567 /* 1568 * cistpl_funcid_handler - handler for CISTPL_FUNCID 1569 * 1570 * void *arg - points to a XXX where the information is stuffed into 1571 */ 1572 uint32_t 1573 cistpl_funcid_handler(cistpl_callout_t *co, cistpl_t *tp, 1574 uint32_t flags, void *arg) 1575 { 1576 /* 1577 * nothing special about our flags, so just call the 1578 * generic handler for this 1579 */ 1580 if (flags & HANDTPL_SET_FLAGS) 1581 return (cis_no_tuple_handler(co, tp, flags, arg)); 1582 1583 /* 1584 * We don't currently validate this tuple. This call will 1585 * always set tp->flags |= CISTPLF_VALID. 1586 */ 1587 if (flags & HANDTPL_COPY_DONE) 1588 return (cis_no_tuple_handler(co, tp, flags, arg)); 1589 1590 if (flags & HANDTPL_PARSE_LTUPLE) { 1591 cistpl_funcid_t *cs = (cistpl_funcid_t *)arg; 1592 1593 RESET_TP(tp); 1594 1595 cs->function = GET_BYTE(tp); 1596 cs->sysinit = GET_BYTE(tp); 1597 } 1598 return (CISTPLF_NOERROR); 1599 } 1600 1601 1602 /* 1603 * cistpl_funce_serial_handler - handler for the CISTPL_FUNCE/SERIAL tuple 1604 * 1605 * void *arg - points to a XXX where the information is stuffed into 1606 */ 1607 uint32_t 1608 cistpl_funce_serial_handler(cistpl_callout_t *co, cistpl_t *tp, 1609 uint32_t flags, void *arg) 1610 { 1611 int subfunction; 1612 1613 /* 1614 * nothing special about our flags, so just call the 1615 * generic handler for this 1616 */ 1617 if (flags & HANDTPL_SET_FLAGS) 1618 return (cis_no_tuple_handler(co, tp, flags, arg)); 1619 1620 /* 1621 * We don't currently validate this tuple. This call will 1622 * always set tp->flags |= CISTPLF_VALID. 1623 */ 1624 if (flags & HANDTPL_COPY_DONE) 1625 return (cis_no_tuple_handler(co, tp, flags, arg)); 1626 1627 if (flags & HANDTPL_PARSE_LTUPLE) { 1628 cistpl_funce_t *cs = (cistpl_funce_t *)arg; 1629 1630 RESET_TP(tp); 1631 1632 cs->function = TPLFUNC_SERIAL; 1633 cs->subfunction = subfunction = GET_BYTE(tp); 1634 switch (subfunction & 0xF) { 1635 case TPLFE_SUB_SERIAL: 1636 case TPLFE_CAP_SERIAL_DATA: 1637 case TPLFE_CAP_SERIAL_FAX: 1638 case TPLFE_CAP_SERIAL_VOICE: 1639 cs->data.serial.ua = GET_BYTE(tp); 1640 cs->data.serial.uc = GET_SHORT(tp); 1641 break; 1642 case TPLFE_SUB_MODEM_COMMON: 1643 case TPLFE_CAP_MODEM_DATA: 1644 case TPLFE_CAP_MODEM_FAX: 1645 case TPLFE_CAP_MODEM_VOICE: 1646 cs->data.modem.fc = GET_BYTE(tp); 1647 cs->data.modem.cb = (GET_BYTE(tp) + 1) * 4; 1648 cs->data.modem.eb = GET_INT24(tp); 1649 cs->data.modem.tb = GET_INT24(tp); 1650 break; 1651 case TPLFE_SUB_MODEM_DATA: 1652 cs->data.data_modem.ud = GET_BE_SHORT(tp) * 75; 1653 cs->data.data_modem.ms = GET_SHORT(tp); 1654 cs->data.data_modem.em = GET_BYTE(tp); 1655 cs->data.data_modem.dc = GET_BYTE(tp); 1656 cs->data.data_modem.cm = GET_BYTE(tp); 1657 cs->data.data_modem.ex = GET_BYTE(tp); 1658 cs->data.data_modem.dy = GET_BYTE(tp); 1659 cs->data.data_modem.ef = GET_BYTE(tp); 1660 for (cs->data.data_modem.ncd = 0; 1661 GET_LEN(tp) > 0 && cs->data.data_modem.ncd < 16; 1662 cs->data.data_modem.ncd++) 1663 if (LOOK_BYTE(tp) != 255) { 1664 cs->data.data_modem.cd[ 1665 cs->data.data_modem.ncd] = 1666 GET_BYTE(tp); 1667 } else { 1668 GET_BYTE(tp); 1669 break; 1670 } 1671 break; 1672 case TPLFE_SUB_MODEM_FAX: 1673 cs->data.fax.uf = GET_BE_SHORT(tp) * 75; 1674 cs->data.fax.fm = GET_BYTE(tp); 1675 cs->data.fax.fy = GET_BYTE(tp); 1676 cs->data.fax.fs = GET_SHORT(tp); 1677 for (cs->data.fax.ncf = 0; 1678 GET_LEN(tp) > 0 && cs->data.fax.ncf < 16; 1679 cs->data.fax.ncf++) 1680 if (LOOK_BYTE(tp) != 255) { 1681 cs->data.fax.cf[cs->data.fax.ncf] = 1682 GET_BYTE(tp); 1683 } else { 1684 GET_BYTE(tp); 1685 break; 1686 } 1687 break; 1688 case TPLFE_SUB_VOICE: 1689 cs->data.voice.uv = GET_BE_SHORT(tp) * 75; 1690 for (cs->data.voice.nsr = 0; LOOK_BYTE(tp) != 0 && 1691 GET_LEN(tp) >= 2; 1692 cs->data.voice.nsr++) { 1693 cs->data.voice.sr[cs->data.voice.nsr] = 1694 GET_BYTE(tp) * 1000; 1695 cs->data.voice.sr[cs->data.voice.nsr] += 1696 GET_BYTE(tp) * 100; 1697 } 1698 for (cs->data.voice.nss = 0; LOOK_BYTE(tp) != 0 && 1699 GET_LEN(tp) >= 2; 1700 cs->data.voice.nss++) { 1701 cs->data.voice.ss[cs->data.voice.nss] = 1702 GET_BYTE(tp) * 10; 1703 cs->data.voice.ss[cs->data.voice.nss] += 1704 GET_BYTE(tp); 1705 } 1706 for (cs->data.voice.nsc = 0; LOOK_BYTE(tp) != 0 && 1707 GET_LEN(tp) >= 1; 1708 cs->data.voice.nsc++) { 1709 cs->data.voice.sc[cs->data.voice.nsc] = 1710 GET_BYTE(tp); 1711 } 1712 break; 1713 default: 1714 break; 1715 } 1716 } 1717 return (CISTPLF_NOERROR); 1718 } 1719 1720 /* 1721 * cistpl_funce_lan_handler - handler for the CISTPL_FUNCE/LAN tuple 1722 * 1723 * void *arg - points to a XXX where the information is stuffed into 1724 */ 1725 uint32_t 1726 cistpl_funce_lan_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags, 1727 void *arg) 1728 { 1729 int subfunction; 1730 1731 /* 1732 * nothing special about our flags, so just call the 1733 * generic handler for this 1734 */ 1735 if (flags & HANDTPL_SET_FLAGS) 1736 return (cis_no_tuple_handler(co, tp, flags, arg)); 1737 1738 /* 1739 * We don't currently validate this tuple. This call will 1740 * always set tp->flags |= CISTPLF_VALID. 1741 */ 1742 if (flags & HANDTPL_COPY_DONE) 1743 return (cis_no_tuple_handler(co, tp, flags, arg)); 1744 1745 if (flags & HANDTPL_PARSE_LTUPLE) { 1746 int i; 1747 cistpl_funce_t *cs = (cistpl_funce_t *)arg; 1748 1749 RESET_TP(tp); 1750 1751 cs->function = TPLFUNC_LAN; 1752 cs->subfunction = subfunction = GET_BYTE(tp); 1753 1754 switch (subfunction) { 1755 case TPLFE_NETWORK_INFO: 1756 cs->data.lan.tech = GET_BYTE(tp); 1757 cs->data.lan.speed = GET_BYTE(tp); 1758 i = GET_BYTE(tp); 1759 if (i < 24) { 1760 cs->data.lan.speed <<= i; 1761 } else { 1762 /* 1763 * if speed is too large a value 1764 * to hold in a uint32 flag it and 1765 * store as [mantissa][exponent] 1766 * in least significant 16 bits 1767 */ 1768 cs->data.lan.speed = 0x80000000 | 1769 (cs->data.lan.speed << 8) | i; 1770 } 1771 cs->data.lan.media = GET_BYTE(tp); 1772 cs->data.lan.con = GET_BYTE(tp); 1773 cs->data.lan.id_sz = GET_BYTE(tp); 1774 if (cs->data.lan.id_sz <= 16) { 1775 for (i = 0; i < cs->data.lan.id_sz; i++) 1776 cs->data.lan.id[i] = GET_BYTE(tp); 1777 } 1778 break; 1779 default: 1780 /* unknown LAN tuple type */ 1781 return (CISTPLF_UNKNOWN); 1782 } 1783 } 1784 return (CISTPLF_NOERROR); 1785 } 1786 1787 /* 1788 * cistpl_linktarget_handler - handler for CISTPL_LINKTARGET tuple 1789 * 1790 * void *arg - points to a cistpl_linktarget_t * where the 1791 * information is stuffed into 1792 * 1793 * If HANDTPL_COPY_DONE is set, we just validate the tuple but 1794 * do not return any values. 1795 * If HANDTPL_PARSE_LTUPLE is set, we validate the tuple and 1796 * return the parsed tuple data if the tuple is valid. 1797 * 1798 * If the tuple link field is invalid, the CISTPLF_LINK_INVALID flag 1799 * will be set in the tp->flags field and HANDTPL_ERROR 1800 * will be returned. 1801 * 1802 * If the tuple data body is invalid, the CISTPLF_PARAMS_INVALID flag 1803 * will be set in the tp->flags field and HANDTPL_ERROR 1804 * will be returned. 1805 * 1806 * The tuple is considered invalid if it's link field is less than 1807 * MIN_LINKTARGET_LENGTH or if the data body of the tuple 1808 * does not contain the pattern CISTPL_LINKTARGET_MAGIC. 1809 * 1810 * XXX At some point we should revisit this to see if we can call 1811 * cis_validate_longlink_acm instead of doing the validation 1812 * in both places. 1813 */ 1814 uint32_t 1815 cistpl_linktarget_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags, 1816 void *arg) 1817 { 1818 /* 1819 * nothing special about our flags, so just call the 1820 * generic handler for this 1821 */ 1822 if (flags & HANDTPL_SET_FLAGS) 1823 return (cis_no_tuple_handler(co, tp, flags, arg)); 1824 1825 /* 1826 * Validate the tuple for both the HANDTPL_COPY_DONE case and 1827 * the HANDTPL_PARSE_LTUPLE case. Only return data in 1828 * the HANDTPL_PARSE_LTUPLE case. 1829 */ 1830 if (flags & (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE)) { 1831 uchar_t *cp; 1832 cisdata_t tl; 1833 1834 if ((tl = tp->len) >= (cisdata_t)MIN_LINKTARGET_LENGTH) { 1835 cisdata_t *ltm = (cisdata_t *)CISTPL_LINKTARGET_MAGIC; 1836 int i; 1837 1838 RESET_TP(tp); 1839 1840 /* 1841 * Save the start address of this string in case 1842 * the tuple turns out to be OK since we 1843 * need to pass this address to the caller. 1844 */ 1845 cp = GET_BYTE_ADDR(tp); 1846 1847 /* 1848 * Check each byte of the tuple body to see if it 1849 * matches what should be in a valid tuple. 1850 * Note that we can't assume that this magic 1851 * pattern is a string and we also only need 1852 * to be sure that MIN_LINKTARGET_LENGTH bytes 1853 * match; all bytes following this magic number 1854 * in this tuple are ignored. 1855 */ 1856 for (i = 0; i < MIN_LINKTARGET_LENGTH; i++) { 1857 if (GET_BYTE(tp) != *ltm++) { 1858 tp->flags |= CISTPLF_PARAMS_INVALID; 1859 return (HANDTPL_ERROR); 1860 } 1861 } /* MIN_LINKTARGET_LENGTH */ 1862 1863 /* 1864 * This tuple is valid. 1865 */ 1866 if (flags & HANDTPL_COPY_DONE) 1867 tp->flags |= CISTPLF_VALID; 1868 1869 /* 1870 * If we're also parsing this tuple, then 1871 * setup the return values. 1872 */ 1873 if (flags & HANDTPL_PARSE_LTUPLE) { 1874 cistpl_linktarget_t *cs = 1875 (cistpl_linktarget_t *)arg; 1876 1877 cs->length = tl; 1878 (void) strncpy(cs->tpltg_tag, (char *)cp, 1879 cs->length); 1880 cs->tpltg_tag[cs->length] = NULL; 1881 1882 } /* HANDTPL_PARSE_LTUPLE */ 1883 1884 } else { 1885 1886 tp->flags |= CISTPLF_LINK_INVALID; 1887 return (HANDTPL_ERROR); 1888 1889 } /* CISTPL_LINKTARGET */ 1890 1891 } /* (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE) */ 1892 1893 return (CISTPLF_NOERROR); 1894 } 1895 1896 /* 1897 * cistpl_longlink_ac_handler - handler for CISTPL_LONGLINK_A and 1898 * CISTPL_LONGLINK_C tuples 1899 * 1900 * void *arg - points to a cistpl_longlink_ac_t * where the 1901 * information is stuffed into 1902 * 1903 * If the passed in tuple is CISTPL_LONGLINK_A the CISTPL_LONGLINK_AC_AM 1904 * flag in cistpl_longlink_ac_t->flags is set. 1905 * If the passed in tuple is CISTPL_LONGLINK_C the CISTPL_LONGLINK_AC_CM 1906 * flag in cistpl_longlink_ac_t->flags is set. 1907 * 1908 * If HANDTPL_COPY_DONE is set, we just validate the tuple but 1909 * do not return any values. 1910 * If HANDTPL_PARSE_LTUPLE is set, we validate the tuple and 1911 * return the parsed tuple data if the tuple is valid. 1912 * 1913 * If the tuple link field is invalid, the CISTPLF_LINK_INVALID flag 1914 * will be set in the tp->flags field and HANDTPL_ERROR 1915 * will be returned. 1916 * 1917 * The tuple is considered invalid if it's link field is less than 1918 * MIN_LONGLINK_AC_LENGTH. 1919 */ 1920 uint32_t 1921 cistpl_longlink_ac_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags, 1922 void *arg) 1923 { 1924 /* 1925 * nothing special about our flags, so just call the 1926 * generic handler for this 1927 */ 1928 if (flags & HANDTPL_SET_FLAGS) 1929 return (cis_no_tuple_handler(co, tp, flags, arg)); 1930 1931 /* 1932 * Validate the tuple for both the HANDTPL_COPY_DONE case and 1933 * the HANDTPL_PARSE_LTUPLE case. Only return data in 1934 * the HANDTPL_PARSE_LTUPLE case. 1935 */ 1936 if (flags & (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE)) { 1937 1938 if (tp->len >= (cisdata_t)MIN_LONGLINK_AC_LENGTH) { 1939 1940 /* 1941 * This tuple is valid. 1942 */ 1943 if (flags & HANDTPL_COPY_DONE) 1944 tp->flags |= CISTPLF_VALID; 1945 1946 if (flags & HANDTPL_PARSE_LTUPLE) { 1947 cistpl_longlink_ac_t *cs = 1948 (cistpl_longlink_ac_t *)arg; 1949 1950 switch (tp->type) { 1951 case CISTPL_LONGLINK_A: 1952 cs->flags = CISTPL_LONGLINK_AC_AM; 1953 break; 1954 1955 case CISTPL_LONGLINK_C: 1956 cs->flags = CISTPL_LONGLINK_AC_CM; 1957 break; 1958 default: 1959 break; 1960 } /* switch */ 1961 1962 RESET_TP(tp); 1963 1964 cs->tpll_addr = GET_LONG(tp); 1965 1966 } /* HANDTPL_PARSE_LTUPLE */ 1967 1968 } else { 1969 tp->flags |= CISTPLF_LINK_INVALID; 1970 return (HANDTPL_ERROR); 1971 } /* MIN_LONGLINK_AC_LENGTH */ 1972 1973 } /* (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE) */ 1974 1975 return (CISTPLF_NOERROR); 1976 } 1977 1978 /* 1979 * cistpl_longlink_mfc_handler - handler for CISTPL_LONGLINK_MFC tuples 1980 * 1981 * void *arg - points to a cistpl_longlink_mfc_t * where the 1982 * information is stuffed into 1983 * 1984 * If HANDTPL_COPY_DONE is set, we just validate the tuple but 1985 * do not return any values. 1986 * If HANDTPL_PARSE_LTUPLE is set, we validate the tuple and 1987 * return the parsed tuple data if the tuple is valid. 1988 * 1989 * If the tuple link field is invalid, the CISTPLF_LINK_INVALID flag 1990 * will be set in the tp->flags field and HANDTPL_ERROR 1991 * will be returned. 1992 * 1993 * If the number of register sets is invalid, the CISTPLF_PARAMS_INVALID 1994 * flag be set in the tp->flags field and HANDTPL_ERROR will be 1995 * returned. 1996 * 1997 * The tuple is considered invalid if it's link field is less than 1998 * MIN_LONGLINK_MFC_LENGTH or if the number of register sets 1999 * is not in the range [MIN_LONGLINK_MFC_NREGS..CIS_MAX_FUNCTIONS] 2000 */ 2001 uint32_t 2002 cistpl_longlink_mfc_handler(cistpl_callout_t *co, cistpl_t *tp, 2003 uint32_t flags, void *arg) 2004 { 2005 /* 2006 * nothing special about our flags, so just call the 2007 * generic handler for this 2008 */ 2009 if (flags & HANDTPL_SET_FLAGS) 2010 return (cis_no_tuple_handler(co, tp, flags, arg)); 2011 2012 /* 2013 * Validate the tuple for both the HANDTPL_COPY_DONE case and 2014 * the HANDTPL_PARSE_LTUPLE case. Only return data in 2015 * the HANDTPL_PARSE_LTUPLE case. 2016 */ 2017 if (flags & (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE)) { 2018 2019 if (tp->len >= (cisdata_t)MIN_LONGLINK_MFC_LENGTH) { 2020 2021 /* 2022 * This tuple is valid. 2023 */ 2024 if (flags & HANDTPL_COPY_DONE) 2025 tp->flags |= CISTPLF_VALID; 2026 2027 if (flags & HANDTPL_PARSE_LTUPLE) { 2028 cistpl_longlink_mfc_t *cs = 2029 (cistpl_longlink_mfc_t *)arg; 2030 int fn; 2031 2032 RESET_TP(tp); 2033 2034 /* 2035 * Get the number of register sets described 2036 * by this tuple. The number of register 2037 * sets must be greter than or equal to 2038 * MIN_LONGLINK_MFC_NREGS and less than 2039 * CIS_MAX_FUNCTIONS. 2040 * Note that the number of functions is equal 2041 * to the number of register sets. 2042 */ 2043 cs->nregs = GET_BYTE(tp); 2044 cs->nfuncs = cs->nregs; 2045 2046 if ((cs->nregs < MIN_LONGLINK_MFC_NREGS) || 2047 (cs->nregs > CIS_MAX_FUNCTIONS)) { 2048 tp->flags |= CISTPLF_PARAMS_INVALID; 2049 return (HANDTPL_ERROR); 2050 } 2051 2052 /* 2053 * Cycle through each function and setup 2054 * the appropriate parameter values. 2055 */ 2056 for (fn = 0; fn < cs->nregs; fn++) { 2057 cs->function[fn].tas = GET_BYTE(tp); 2058 cs->function[fn].addr = GET_LONG(tp); 2059 } /* for (fn) */ 2060 2061 } /* HANDTPL_PARSE_LTUPLE */ 2062 2063 } else { 2064 tp->flags |= CISTPLF_LINK_INVALID; 2065 return (HANDTPL_ERROR); 2066 } /* MIN_LONGLINK_MFC_LENGTH */ 2067 2068 } /* (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE) */ 2069 2070 return (CISTPLF_NOERROR); 2071 } 2072 2073 /* 2074 * cis_validate_longlink_acm - Validates the secondary tuple chain pointed 2075 * to by cisptr and specified by a previous 2076 * CISTPL_LONGLINK_A, CISTPL_LONGLINK_C or 2077 * CISTPL_LONGLINK_MFC tuple. 2078 * 2079 * cisptr->offset must be the offset to the first byte in the secondary 2080 * tuple chain to validate 2081 * cisptr->flags must be setup to specify the correct address space 2082 * 2083 * The cisptr->offset member is not updated after this function returns. 2084 * 2085 * BAD_CIS_ADDR is returned is the raw CIS data cound not be read. 2086 * HANDTPL_ERROR is returned if the secondary tuple chain does not 2087 * contain a valid CISTPL_LINKTARGET tuple. 2088 */ 2089 uint32_t 2090 cis_validate_longlink_acm(cisptr_t *cisptr) 2091 { 2092 uchar_t cb[MIN_LINKTARGET_LENGTH + LINKTARGET_AC_HEADER_LENGTH]; 2093 cisptr_t t_cisptr, *cpt; 2094 int tl; 2095 2096 /* 2097 * Since the NEXT_CIS_ADDR macro increments the cisptr_t->offset 2098 * member, make a local copy of the cisptr and use the local 2099 * copy to read data from the card. 2100 */ 2101 cpt = &t_cisptr; 2102 bcopy((caddr_t)cisptr, (caddr_t)cpt, sizeof (cisptr_t)); 2103 2104 for (tl = 0; tl < MIN_LINKTARGET_LENGTH + 2105 LINKTARGET_AC_HEADER_LENGTH; tl++) { 2106 2107 cb[tl] = GET_CIS_DATA(cpt); 2108 if (!NEXT_CIS_ADDR(cpt)) 2109 return ((uint32_t)BAD_CIS_ADDR); 2110 2111 } /* for */ 2112 2113 if ((cb[0] == CISTPL_LINKTARGET) && (cb[1] >= MIN_LINKTARGET_LENGTH)) { 2114 cisdata_t *ltm = (cisdata_t *)CISTPL_LINKTARGET_MAGIC; 2115 2116 for (tl = 0; tl < MIN_LINKTARGET_LENGTH; tl++, ltm++) { 2117 if (cb[tl + LINKTARGET_AC_HEADER_LENGTH] != *ltm) 2118 return (HANDTPL_ERROR); 2119 } 2120 return (CISTPLF_NOERROR); 2121 2122 } /* if */ 2123 2124 return (HANDTPL_ERROR); 2125 } 2126 2127 /* 2128 * cis_getstr (tp) 2129 * we want the address of the first character returned 2130 * but need to skip past the string in the cistpl_t structure 2131 */ 2132 char * 2133 cis_getstr(cistpl_t *tp) 2134 { 2135 uchar_t *cp, *cpp; 2136 uchar_t x; 2137 2138 cp = tp->read.byte; 2139 cpp = cp; 2140 2141 while ((x = LOOK_BYTE(tp)) != 0 && x != 0xff) { 2142 x = GET_BYTE(tp); 2143 } 2144 2145 (void) GET_BYTE(tp); /* get past that last byte */ 2146 2147 while ((*cpp != 0) && (*cpp != 0xff)) 2148 cpp++; 2149 2150 *cpp = NULL; 2151 2152 return ((char *)cp); 2153 } 2154 2155 /* 2156 * cis_return_name - returns name of tuple 2157 * 2158 * calling: co - pointer to cistpl_callout_t entry that contains 2159 * tuple name to return 2160 * gtn - pointer to cistpl_get_tuple_name_t to return 2161 * name into 2162 */ 2163 static void 2164 cis_return_name(cistpl_callout_t *co, cistpl_get_tuple_name_t *gtn) 2165 { 2166 (void) strncpy(gtn->name, co->text, CIS_MAX_TUPLE_NAME_LEN); 2167 gtn->name[CIS_MAX_TUPLE_NAME_LEN - 1] = NULL; 2168 } 2169 2170 /* 2171 * cis_malloc/cis_free 2172 * wrappers around kmem_alloc()/kmem_free() that 2173 * provide malloc/free style usage 2174 */ 2175 2176 caddr_t 2177 cis_malloc(size_t len) 2178 { 2179 caddr_t addr; 2180 2181 addr = kmem_zalloc(len + sizeof (size_t), KM_SLEEP); 2182 *(size_t *)addr = len + sizeof (size_t); 2183 addr += sizeof (size_t); 2184 return (addr); 2185 } 2186 2187 void 2188 cis_free(caddr_t addr) 2189 { 2190 size_t len; 2191 addr -= sizeof (size_t); 2192 len = *(size_t *)addr; 2193 kmem_free(addr, len); 2194 }