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