cis_handlers.c revision 5f9e250aa611c12bbaccc0be612e5b97ccca2762
* cis_tuple_handler - call the handler for the tuple described by the * cistpl_callout_t *co - pointer to callout structure * array to use to find this tuple * cistpl_t *tp - pointer to a tuple structure * int flags - action for the handler to perform * XXX - we need a description of the flags passed to the tuple handler * void *arg - argument to pass on to tuple handler * If the tuple is not recognized but is is a vendor-specific tuple, we * set the CISTPLF_VENDOR_SPECIFIC flag in the tuple. * We return CISTPLF_UNKNOWN if this is an unrecognized tuple as well as * set the CISTPLF_UNKNOWN flag in the tuple list structure. Note * that encountering an unknown tuple is not necessarily an error, * so we don't set the HANDTPL_ERROR flag on the return code. It * is up to the caller to determine what an unrecognized tuple means. * If this is a recognized tuple, the apropriate tuple handler is called and * the return value from the handler is returned directly to the caller. * The void *arg is optional, and it's meaning is dependent on the * particular tuple handler called and the flags parameter. * For the special case of HANDTPL_RETURN_NAME, we don't bother calling the * tuple handler and just return the tuple name to the caller. * Check to see if this is a vendor-specific tuple. * Scan the callout list until we find the tuple passed to us, or we * encounter a CISTPL_END in the callout list, which signals that * there are no more tuples in the callout list. }
/* HANDTPL_RETURN_NAME */ * If we didn't recognize the tuple and the caller wants the tuple * name back, then return the "unknown tuple" string. At this * point, "co" will be pointing to the last entry in the * callout list. It's not an error to not recognize the tuple * when the operation is HANDTPL_RETURN_NAME. * cis_no_tuple_handler - this generic tuple handler is used if no special * tuple processing is required for the passed * cistpl_callout_t *co - pointer to this tuple's entry in the * tuple callout structure * cistpl_t *tp - pointer to this tuple's entry in the local linked list * int flags - action to perform * This handler will set the CISTPLF_COPYOK flag if the tuple link is greater * than zero, indicating that it's OK to copy the tuple data body. It * will also set whatever flags are specified in the callout structure. * We always set the CISTPLF_VALID when we're called with HANDTPL_COPY_DONE. * We return CISTPLF_UNKNOWN if we're being called to parse the tuple. * We return CISTPLF_NOERROR in every other case to indicate that this is a * cis_unknown_tuple_handler - this generic tuple handler is used if we don't * cistpl_callout_t *co - pointer to this tuple's entry in the * tuple callout structure * cistpl_t *tp - pointer to this tuple's entry in the local linked list * int flags - action to perform * This handler will not set the CISTPLF_COPYOK flag since we don't know the * contents of a vendor-specific tuple. * We always set the CISTPLF_VALID when we're called with HANDTPL_COPY_DONE * to specify that we understand this tuple's code, but not it's data * We return CISTPLF_UNKNOWN if we're being called to parse the tuple or to * perform any other operation. * cistpl_vers_1_handler - handler for the CISTPL_VERS_1 tuple * void *arg - points to a cistpl_vers_1_t * where the * information is stuffed into * nothing special about our flags, so just call the * generic handler for this * We don't currently validate this tuple. This call will * always set tp->flags |= CISTPLF_VALID. }
/* HANDTPL_PARSE_LTUPLE */ * cistpl_config_handler - handler for the CISTPL_CONFIG tuple * void *arg - points to a XXX where the information is stuffed into * For the first ten config registers we set the present flags in the * cistpl_config_t if the register exists. The flags that we use * for this are the same as the flags reguired for the Card Services * RequestConfiguration function and they can be used by clients * directly without requiring any remapping of values. * XXX we don't handle TPCC_SBTPL subtuples yet * nothing special about our flags, so just call the * generic handler for this * We don't currently validate this tuple. This call will * always set tp->flags |= CISTPLF_VALID. na = (
tpcc_sz&
3)+
1;
/* config regs address bytes */ nrb = ((
tpcc_sz>>
2)&
0x0f)+
1;
/* number of bytes in config */ * Construct the base offset address for the config registers. * We jump through these hoops because the base address * can be between one and four bytes in length. * Go through the config register presense mask bit by bit and * figure out which config registers are present and which * For the first ten config registers, set the appropriate * bits in the cr->present member so that the caller * doesn't have to do this. for (i = 0; i <
8; i++,
crn++) {
* cistpl_device_handler - handler for the CISTPL_DEVICE, CISTPL_DEVICE_A, * CISTPL_DEVICE_OC and CISTPL_DEVICE_OA tuples * void *arg - points to a cistpl_device_t * where the * information is stuffed into * XXX - we only handle CISTPL_DEVICE_MAX_DEVICES device descriptions * nothing special about our flags, so just call the * generic handler for this * We don't currently validate this tuple. This call will * always set tp->flags |= CISTPLF_VALID. * XXX - fix this to look for more than one device definition * XXX - fix this to handle the OC fields for * CISTPL_DEVICE_OC and CISTPL_DEVICE_OA * Get the device speed code. If it's 7, then there is an * extended speed code table in use, so parse that. * If it's anything else, get the speed information * directly from the device speed code. * Convert the speed in nS to a device speed code. * XXX - should check return code from cis_convert_devspeed() * Set the device type. Note that we take the raw value * from the tuple and pass it back to the caller. * If the device type codes in the standard change, * we will have to change our flags as well. * XXX - what about the device_size byte? Is the spec wrong? /* check for end of list */ * cistpl_cftable_handler - handler for the CISTPL_CFTABLE_ENTRY tuple * void *arg - points to a XXX where the information is stuffed into * Return: CISTPLF_NOERROR - if no error parsing tuple * HANDTPL_ERROR - if error parsing tuple * nothing special about our flags, so just call the * generic handler for this * We don't currently validate this tuple. This call will * always set tp->flags |= CISTPLF_VALID. * Check to see if we have an interface description byte. If * we do, grab it and give it directly to the caller, and * set a flag so the caller knows that it's there. * We also setup the appropriate values in the ce->pin member * so that clients can feed this value directly to the * Card Services RequestConfiguration call. * Return the configuration index to the caller, and set the * default configuration flag if this is a default * Feature selection flags. * See what types of power information are available, * and if there is any, set the global power * information flag as well as a flag for each * power description available. }
/* if (CISTPL_CFTABLE_TPCE_FS_PWRM) */ * Set up the global memory information flag. * Parse the various power description structures. * Collect any Vcc information. * Collect any Vpp1 information. * Collect any Vpp2 information. }
/* if (CISTPL_CFTABLE_TPCE_FS_PWR) */ * Check to see if there's any timing information, and if * so, parse the tuple data and store it in the * caller's structure. Set a flag in the global * flag field indicating that there is timing information. * Parse TPCE_TD to get the various timing * scale factors. Each scale factor has * a value that indicates that the particular * timing parameter doesn't exist. }
/* if (CISTPL_CFTABLE_TPCE_FS_TDM) */ * Parse any I/O address information. If there is I/O * inforamtion, set a flag in the global flag field * to let the caller know. * Pass any I/O flags that are in the tuple directly * If there are any ranges, extract the number of * ranges and the range descriptions. * Number of I/O ranges is the value specified * in the tuple plus one, so there's * always at least one I/O range if the * CISTPL_CFTABLE_TPCE_FS_IO_RANGEM bit * in the I/O flags register is set. * Cycle through each I/O range. for (i = 0; i < (
int)
nr; i++) {
* Gather the address information. * It's OK if there's no address * information in which case this * loop will never execute. * Gather the length information. * It's OK if there's no length * information in which case this * loop will never execute. }
/* if (CISTPL_CFTABLE_TPCE_FS_IO_RANGEM) */ }
/* if (CISTPL_CFTABLE_TPCE_FS_IOM) */ * Parse any IRQ information. If there is IRQ inforamtion, * set a flag in the global flag field to let the * Pass any IRQ flags that are in the tuple directly * Check for and parse the extended IRQ bitmask }
/* if (CISTPL_CFTABLE_TPCE_FS_IRQM) */ * Parse any memory information. * XXX - should be a cleaner way to parse this information. * Switch on the type of memory description * information that is available. * variable length memory space description /* memory space descriptor */ * If there's host address information, let * Cycle through each window space description * and collect all the interesting bits. * Gather the length information. * It's OK if there's no length * information in which case this * loop will never execute. * Gather the card address information. * It's OK if there's no card * address information in which * case this loop will never * If there's a host address * Gather the host address * Note that we use the card * No host address information, }
/* for (i<mem->windows) */ * single length and card base address specified * Construct the size of the window. * Construct the card base address. * In this mode, both the host base address * and the card base address are equal. * single length specified * Construct the size of the window. }
/* switch (CISTPL_CFTABLE_TPCE_FS_MEMM) */ }
/* if (CISTPL_CFTABLE_TPCE_FS_MEM) */ * Check for and parse any miscellaneous information. * We only understand how to parse the first * CISTPL_CFTABLE_TPCE_FS_MISC_MAX extension * bytes specified in the PC Card 95 standard; * we throw away any other extension bytes that * XXX Note that the assumption here is that the * size of cistpl_cftable_entry_misc_t->flags * is at least CISTPL_CFTABLE_TPCE_FS_MISC_MAX * Check to see if we tried to read past the * end of the tuple data; if we have, * there's no point in trying to parse }
/* if (CISTPL_CFTABLE_TPCE_FS_MISCM) */ * Check for and parse any additional subtuple * information. We know that there is * additional information if we haven't * reached the end of the tuple data area * and if the additional information is * in standard tuple format. * If we don't recognize the additional info, * then just silently ignore it, don't }
/* if (HANDTPL_PARSE_LTUPLE) */ * cistpl_pd_parse - read and parse a power description structure * cisdata_t **ddp - pointer to pointer tuple data area * cistpl_cftable_entry_pwr_t *pd - pointer to local power description /* nominal supply voltage */ /* minimum supply voltage */ /* maximum supply voltage */ /* continuous supply current */ /* maximum current required averaged over 1 second */ /* maximum current required averaged over 10mS */ /* power down supply curent required */ * cistpl_expd_parse - read and parse an extended power description structure * cistpl_t *tp - pointer to pointer tuple data area * int *flags - flags that get for this parameter: * CISTPL_CFTABLE_PD_NC_SLEEP - no connection on * CISTPL_CFTABLE_PD_ZERO - zero value required * CISTPL_CFTABLE_PD_NC - no connection ever * The power consumption is returned in the following units: * Get the power description parameter byte and break it up * into mantissa and exponent. * If we have to multiply the power value by ten, then just val =
val/
10;
/* do this since our mantissa table is X 10 */ * If we need to add some digits to the right of the decimal, do * cistpl_devspeed - returns device speed in nS * cistpl_t *tp - tuple pointer. * cisdata_t spindex - device speed table index * int flags - operation flags * Use the spindex argument as an index into a simple * device speed table. ref: PCMCIA Release 2.01 * Card Metaformat pg. 5-14 table 5-12. * When this flag is set, the spindex argument is ignored. * Use the tp argument to access the * tuple data area containing an extended speed * code table. ref: PCMCIA Release 2.01 Card * Metaformat pg. 5-15 table 5-13. * The tp->read argument must point to the first byte of * an extended speed code table. * When this flag is set, the spindex argument is * used as a power-of-10 scale factor. We only allow * a maximum scale factor of 10^16. * The device speed is returned in nS for all combinations of flags and * Note if you pass the CISTPL_DEVSPEED_TABLE with a spindex index that * refers to an extended speed table, you will get back an undefined * XXX - ugh! we don't understand additional spindex &=
0x0f;
/* only allow 10^16 */ speed =
speed/
10;
/* XXX - mantissa table is all X 10 */ * cistpl_vers_2_handler - handler for the CISTPL_VERS_2 tuple * void *arg - points to a XXX where the information is stuffed into * nothing special about our flags, so just call the * generic handler for this * We don't currently validate this tuple. This call will * always set tp->flags |= CISTPLF_VALID. * cistpl_jedec_handler - handler for JEDEC C and JEDEC A tuples * void *arg - points to a XXX where the information is stuffed into * nothing special about our flags, so just call the * generic handler for this * We don't currently validate this tuple. This call will * always set tp->flags |= CISTPLF_VALID. * cistpl_format_handler - handler for the CISTPL_FORMAT and * nothing special about our flags, so just call the * generic handler for this * We don't currently validate this tuple. This call will * always set tp->flags |= CISTPLF_VALID. /* don't know about any other type */ * cistpl_geometry_handler - handler for the CISTPL_GEOMETRY tuple * void *arg - points to a XXX where the information is stuffed into * nothing special about our flags, so just call the * generic handler for this * We don't currently validate this tuple. This call will * always set tp->flags |= CISTPLF_VALID. * cistpl_byteorder_handler - handler for the CISTPL_BYTEORDER tuple * void *arg - points to a XXX where the information is stuffed into * nothing special about our flags, so just call the * generic handler for this * We don't currently validate this tuple. This call will * always set tp->flags |= CISTPLF_VALID. * cistpl_date_handler - handler for CISTPL_DATE card format tuple * void *arg - points to a cistpl_date_t * where the * information is stuffed into * nothing special about our flags, so just call the * generic handler for this * We don't currently validate this tuple. This call will * always set tp->flags |= CISTPLF_VALID. * cistpl_battery_handler - handler for CISTPL_BATTERY battery replacement * void *arg - points to a cistpl_battery_t * where the * information is stuffed into * nothing special about our flags, so just call the * generic handler for this * We don't currently validate this tuple. This call will * always set tp->flags |= CISTPLF_VALID. * cistpl_org_handler - handler for CISTPL_ORG data organization tuple * void *arg - points to a cistpl_org_t * where the * information is stuffed into * nothing special about our flags, so just call the * generic handler for this * We don't currently validate this tuple. This call will * always set tp->flags |= CISTPLF_VALID. * cistpl_manfid_handler - handler for CISTPL_MANFID, the manufacturer ID tuple * void *arg - points to a XXX where the information is stuffed into * nothing special about our flags, so just call the * generic handler for this * We don't currently validate this tuple. This call will * always set tp->flags |= CISTPLF_VALID. * cistpl_funcid_handler - handler for CISTPL_FUNCID * void *arg - points to a XXX where the information is stuffed into * nothing special about our flags, so just call the * generic handler for this * We don't currently validate this tuple. This call will * always set tp->flags |= CISTPLF_VALID. * void *arg - points to a XXX where the information is stuffed into * nothing special about our flags, so just call the * generic handler for this * We don't currently validate this tuple. This call will * always set tp->flags |= CISTPLF_VALID. * void *arg - points to a XXX where the information is stuffed into * nothing special about our flags, so just call the * generic handler for this * We don't currently validate this tuple. This call will * always set tp->flags |= CISTPLF_VALID. * if speed is too large a value * to hold in a uint32 flag it and * store as [mantissa][exponent] * in least significant 16 bits /* unknown LAN tuple type */ * cistpl_linktarget_handler - handler for CISTPL_LINKTARGET tuple * void *arg - points to a cistpl_linktarget_t * where the * information is stuffed into * If HANDTPL_COPY_DONE is set, we just validate the tuple but * do not return any values. * If HANDTPL_PARSE_LTUPLE is set, we validate the tuple and * return the parsed tuple data if the tuple is valid. * If the tuple link field is invalid, the CISTPLF_LINK_INVALID flag * will be set in the tp->flags field and HANDTPL_ERROR * If the tuple data body is invalid, the CISTPLF_PARAMS_INVALID flag * will be set in the tp->flags field and HANDTPL_ERROR * The tuple is considered invalid if it's link field is less than * MIN_LINKTARGET_LENGTH or if the data body of the tuple * does not contain the pattern CISTPL_LINKTARGET_MAGIC. * XXX At some point we should revisit this to see if we can call * cis_validate_longlink_acm instead of doing the validation * nothing special about our flags, so just call the * generic handler for this * Validate the tuple for both the HANDTPL_COPY_DONE case and * the HANDTPL_PARSE_LTUPLE case. Only return data in * the HANDTPL_PARSE_LTUPLE case. * Save the start address of this string in case * the tuple turns out to be OK since we * need to pass this address to the caller. * Check each byte of the tuple body to see if it * matches what should be in a valid tuple. * Note that we can't assume that this magic * pattern is a string and we also only need * to be sure that MIN_LINKTARGET_LENGTH bytes * match; all bytes following this magic number * in this tuple are ignored. }
/* MIN_LINKTARGET_LENGTH */ * If we're also parsing this tuple, then * setup the return values. }
/* HANDTPL_PARSE_LTUPLE */ }
/* CISTPL_LINKTARGET */ }
/* (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE) */ * cistpl_longlink_ac_handler - handler for CISTPL_LONGLINK_A and * CISTPL_LONGLINK_C tuples * void *arg - points to a cistpl_longlink_ac_t * where the * information is stuffed into * If the passed in tuple is CISTPL_LONGLINK_A the CISTPL_LONGLINK_AC_AM * flag in cistpl_longlink_ac_t->flags is set. * If the passed in tuple is CISTPL_LONGLINK_C the CISTPL_LONGLINK_AC_CM * flag in cistpl_longlink_ac_t->flags is set. * If HANDTPL_COPY_DONE is set, we just validate the tuple but * do not return any values. * If HANDTPL_PARSE_LTUPLE is set, we validate the tuple and * return the parsed tuple data if the tuple is valid. * If the tuple link field is invalid, the CISTPLF_LINK_INVALID flag * will be set in the tp->flags field and HANDTPL_ERROR * The tuple is considered invalid if it's link field is less than * MIN_LONGLINK_AC_LENGTH. * nothing special about our flags, so just call the * generic handler for this * Validate the tuple for both the HANDTPL_COPY_DONE case and * the HANDTPL_PARSE_LTUPLE case. Only return data in * the HANDTPL_PARSE_LTUPLE case. }
/* HANDTPL_PARSE_LTUPLE */ }
/* MIN_LONGLINK_AC_LENGTH */ }
/* (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE) */ * cistpl_longlink_mfc_handler - handler for CISTPL_LONGLINK_MFC tuples * void *arg - points to a cistpl_longlink_mfc_t * where the * information is stuffed into * If HANDTPL_COPY_DONE is set, we just validate the tuple but * do not return any values. * If HANDTPL_PARSE_LTUPLE is set, we validate the tuple and * return the parsed tuple data if the tuple is valid. * If the tuple link field is invalid, the CISTPLF_LINK_INVALID flag * will be set in the tp->flags field and HANDTPL_ERROR * If the number of register sets is invalid, the CISTPLF_PARAMS_INVALID * flag be set in the tp->flags field and HANDTPL_ERROR will be * The tuple is considered invalid if it's link field is less than * MIN_LONGLINK_MFC_LENGTH or if the number of register sets * is not in the range [MIN_LONGLINK_MFC_NREGS..CIS_MAX_FUNCTIONS] * nothing special about our flags, so just call the * generic handler for this * Validate the tuple for both the HANDTPL_COPY_DONE case and * the HANDTPL_PARSE_LTUPLE case. Only return data in * the HANDTPL_PARSE_LTUPLE case. * Get the number of register sets described * by this tuple. The number of register * sets must be greter than or equal to * MIN_LONGLINK_MFC_NREGS and less than * Note that the number of functions is equal * to the number of register sets. * Cycle through each function and setup * the appropriate parameter values. }
/* HANDTPL_PARSE_LTUPLE */ }
/* MIN_LONGLINK_MFC_LENGTH */ }
/* (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE) */ * cis_validate_longlink_acm - Validates the secondary tuple chain pointed * to by cisptr and specified by a previous * CISTPL_LONGLINK_A, CISTPL_LONGLINK_C or * CISTPL_LONGLINK_MFC tuple. * cisptr->offset must be the offset to the first byte in the secondary * tuple chain to validate * cisptr->flags must be setup to specify the correct address space * The cisptr->offset member is not updated after this function returns. * BAD_CIS_ADDR is returned is the raw CIS data cound not be read. * HANDTPL_ERROR is returned if the secondary tuple chain does not * contain a valid CISTPL_LINKTARGET tuple. * Since the NEXT_CIS_ADDR macro increments the cisptr_t->offset * member, make a local copy of the cisptr and use the local * copy to read data from the card. * we want the address of the first character returned * but need to skip past the string in the cistpl_t structure (
void)
GET_BYTE(
tp);
/* get past that last byte */ while ((*
cpp != 0) && (*
cpp !=
0xff))
* cis_return_name - returns name of tuple * calling: co - pointer to cistpl_callout_t entry that contains * gtn - pointer to cistpl_get_tuple_name_t to return * wrappers around kmem_alloc()/kmem_free() that