cis.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This is a collection of routines that make up the Card Information
* Structure (CIS) interpreter. The algorigthms used are based
* on the Release 2.01 PCMCIA standard.
*
* Note that a bunch of comments are not indented correctly with the
* code that they are commenting on. This is because cstyle is
* inflexible concerning 4-column indenting.
*/
#include <sys/autoconf.h>
#include <sys/sservice.h>
/*
* Function declarations
*/
static int (*cis_card_services)(int, ...) = NULL;
cis_info_t *, cisparse_t *);
extern cistpl_callout_t cistpl_std_callout[];
#ifdef CIS_DEBUG
int cis_debug = 0;
#endif
/*
* cisp_init - initialize the CIS parser
*/
void
{
#ifdef XXX
/*
* Fill out the function for CISSetAddress
*/
/*
* We have to call SS instead of CS to register because we
* can't do a _depends_on for CS
*/
#endif /* XXX */
}
/*
* cis_deinit - deinitialize the CIS parser
*/
void
{
/*
* Tell CS that we're gone.
*/
if (cis_card_services)
return;
}
/*
* CISParser - this is the entrypoint for all of the CIS Interpreter
* functions
*/
void *
{
void *retcode = (void *)CS_UNSUPPORTED_FUNCTION;
#if defined(CIS_DEBUG)
if (cis_debug > 1) {
function);
}
#endif
/*
* ...and here's the CIS Interpreter waterfall
*/
switch (function) {
case CISP_CIS_SETUP: {
/*
* Tell CS that we're here and what our
* entrypoint address is.
*/
} /* CISP_CIS_SETUP */
break;
case CISP_CIS_LIST_CREATE: {
retcode = (void *)
}
break;
case CISP_CIS_LIST_DESTROY: {
}
break;
case CISP_CIS_GET_LTUPLE: {
int flags;
}
break;
case CISP_CIS_PARSE_TUPLE: {
int flags;
void *arg;
}
break;
case CISP_CIS_CONV_DEVSPEED:
break;
case CISP_CIS_CONV_DEVSIZE:
break;
default:
break;
}
return (retcode);
}
/*
* cis_list_lcreate - read a PC card's CIS and create a local linked CIS list
*
* cistpl_callout_t *cistpl_callout - pointer to callout structure
* array to use to find tuples.
* cisptr_t cisptr - pointer to a structure containing the handle and
* offset from where we should start reading
* CIS bytes as well as misc flags.
* cis_info_t *cis_info - pointer to a cis_info_t structure; pass
* the cis_info->cis member as a NULL pointer
* if you want to create a new list.
* cisparse_t *cisparse - pointer to a cisparse_t struture to put
* parsed longlink tuple data into.
* cs_socket_t *sp - pointer to a cs_socket_t structure that describes
* the socket and card in this socket.
*
* We return the a count of the number of tuples that we saw, not including
* any CISTPL_END or CISTPL_NULL tuples if there were no problems
* processing the CIS. If a tuple handler returns an error, we
* immediately return with the error code from the handler. An
* error return code will always have the HANDTPL_ERROR bit set
* to allow the caller to distinguish an error from a valid tuple
* count.
*
* The nchains and ntuples counters in the cis_info_t structure are also
* updated to reflect the number of chains and number of tuples in
* this chain.
*
* XXX need to add CISTPL_END and CISTPL_NULL tuples to the list, and need
* to be sure that the tuple count reflects these tuples
*
* If we attempt to read beyond the end of the mapped in CIS address space,
* the BAD_CIS_ADDR error code is returned.
*
* This function only interprets the CISTPL_END and CISTPL_NULL tuples as
* well as any tuple with a link field of CISTPL_END.
*
* Tuples of type CISTPL_END or CISTPL_NULL are not added to the list.
*
* To append tuples to end of a local linked CIS list, pass a pointer to the
* address of the last element in the list that you want tuples appended
* to. This pointer should be passed in cis_info->cis.
*
* To process tuple chains with any long link targets, call this routine
* for each tuple chain you want to process using the list append method
* described above. The caller is responsible for vaildating any link
* target tuples to be sure that they describe a valid CIS chain.
*
* The cis_info->flags member is updated as follows:
*
* CW_VALID_CIS - if the CIS is valid
* CW_LONGLINK_MFC_FOUND - if a CISTPL_LONGLINK_MFC tuple
* was seen
* CW_LONGLINK_A_FOUND - if a CISTPL_LONGLINK_A tuple was
* seen
* CW_LONGLINK_C_FOUND - if a CISTPL_LONGLINK_C tuple was
* seen
*
* If a CISTPL_LONGLINK_MFC, CISTPL_LONGLINK_A or CISTPL_LONGLINK_C
* tuple is seen, the *cisparse argument will return an appropriate
* parsed longlink structure as follows:
*
* CW_LONGLINK_MFC_FOUND:
* *cisparse --> cistpl_longlink_mfc_t *
* CW_LONGLINK_A_FOUND, CW_LONGLINK_C_FOUND:
* *cisparse --> cistpl_longlink_ac_t *
*
* These flags are set and the tuples are parsed so that the caller does
* not have to traverse the CIS list to find out if any of these tuples
* have been seen.
*
* For each tuple that we see, the following flags in the tuple_t->flags member
*
* CISTPLF_COPYOK - OK to copy tuple data
* CISTPLF_GLOBAL_CIS - tuple from global CIS
* CISTPLF_MF_CIS - tuple from MF CIS chain
* CISTPLF_FROM_AM - tuple read from AM space
* CISTPLF_FROM_CM - tuple read from CM space
* CISTPLF_LINK_INVALID - tuple link is invalid
* CISTPLF_PARAMS_INVALID - tuple body is invalid
* CISTPLF_AM_SPACE - this tuple is in AM space
* CISTPLF_CM_SPACE - this tuple is in CM space
* CISTPLF_LM_SPACE - this tuple is in local memory
*/
{
/*
* If we were passed a non-NULL list base, that means that we should
* parse the CIS and add any tuples we find to the end of the list
* we were handed a pointer to.
*/
}
"cis_list_lcreate: socket %d SS_GetSocket failed\n",
sp->socket_num);
return (CS_BAD_SOCKET);
}
/*
* If this is primary CIS chain, the first tuple must be one
* from the following list.
* Ref. PC Card 95, Metaformat Specification, Page 7.
* XXX Need to think this out a bit more to deal with 3.3V
* cards and the description of where a CISTPL_DEVICE
* can show up.
*/
#if defined(CIS_DEBUG)
if (cis_debug > 1) {
}
#endif
case CISTPL_DEVICE:
case CISTPL_END:
case CISTPL_LINKTARGET:
break;
case CISTPL_NULL:
/*
* Magicram memory cards without attribute memory
* do not have a CIS and return CISTPL_NULL.
*/
return (0);
break;
default:
return (0);
} /* switch */
} /* CW_CHECK_PRIMARY_CHAIN */
/*
* Update the number of chains counter
*/
/*
* The main tuple processing loop. We'll exit this loop when either
* a tuple's link field is CISTPL_END or we've seen a tuple type
* field of CISTPL_END.
*
* Note that we also silently throw away CISTPL_NULL tuples, and don't
* include them in the tuple count that we return.
*/
(cisdata_t)CISTPL_END)) {
#if defined(CIS_DEBUG)
"offset=0x%x\n",
}
#endif
/*
* Ignore CISTPL_NULL tuples
*/
/*
* point to tuple link field and get the link value
*/
if (!NEXT_CIS_ADDR(cisptr))
return ((uint32_t)BAD_CIS_ADDR);
/*
* This is an ugly PCMCIA hack - ugh! since the standard allows
* a link byte of CISTPL_END to signify that this is the
* last tuple. The problem is that this tuple might
* actually contain useful information, but we don't know
* the size of it.
* We do know that it can't be more than CIS_MAX_TUPLE_DATA_LEN
* bytes in length, however. So, we pretend that the link
* byte is CIS_MAX_TUPLE_DATA_LEN and also set a flag so
* that when we're done processing this tuple, we will
* break out of the while loop.
*/
done = 1;
}
/*
* point to first byte of tuple data, allocate a new list
* element and diddle with the list base and list
* control pointers
*/
if (!NEXT_CIS_ADDR(cisptr))
return ((uint32_t)BAD_CIS_ADDR);
/*
* if we're not the first in the list, point to our
* next
*/
if (tp)
/*
* will be NULL if we're the first element of the
* list
*/
/*
* if this is the first element, save it's address
*/
/*
* Save the address in CIS space that this tuple
* begins at, as well as set tuple flags.
*/
/*
* If this tuple has tuple data, we might need to
* copy it.
* Note that the tuple data pointer (tp->data) will
* be set to NULL for a tuple with no data.
*/
#ifdef XXX
if (tl) {
#endif
/*
* Read the data in the tuple and store it
* away locally if we're allowed to. If
* the CISTPLF_COPYOK flag is set, it means
* that it's OK to touch the data portion
* of the tuple.
*
* We need to make this check since some
* tuples might contain active registers
* that can alter the device state if they
* are read before the card is correctly
* initialized. What a stupid thing to
* allow in a standard, BTW.
*
* We first give the tuple handler a chance
* to set any tuple flags that it wants
* to, then we (optionally) do the data
* copy, and give the tuple handler another
* shot at the tuple.
*
* ref. PC Card Standard Release 2.01 in the
* Card Metaformat section, section 5.2.6,
* page 5-12.
*/
HANDTPL_SET_FLAGS, NULL, 0)) &
return (err);
if (tl > (unsigned)0) {
/*
* if we're supposed to make a local copy of
* the tuple data, allocate space for it,
* otherwise just record the PC card
* starting address of this tuple.
* The address was saved by cis_store_cis_addr.
*/
} else {
}
while (tl--) {
if (!NEXT_CIS_ADDR(cisptr))
return ((uint32_t)BAD_CIS_ADDR);
}
/*
* If we made a local copy of the tuple data,
* then clear the AM and CM flags; if the
* tuple data is still on the card, then
* leave the flags alone.
*/
}
/*
* This is a tuple with no data in it's body, so
* we just set the data pointer to NULL.
*/
} else {
/*
* tp->flags &= ~(CISTPLF_SPACE_MASK |
* CISTPLF_FROM_MASK);
*/
} /* if (tl > 0) */
/*
* The main idea behind this call is to give
* the handler a chance to validate the
* tuple.
*/
HANDTPL_COPY_DONE, NULL, 0)) &
return (err);
#ifdef XXX
} else { /* if (tl) */
}
#endif
/*
* Check to see if this is a longlink tuple and if
* so, do the necessary processing.
*/
cisparse)) &
return (err);
} else { /* if (td == CISTPL_NULL) */
/*
* If we're a CISTPL_NULL we need to skip to
* the beginning of the next tuple.
*/
if (!NEXT_CIS_ADDR(cisptr))
return ((uint32_t)BAD_CIS_ADDR);
}
} /* while (!done && !CISTPL_END) */
#if defined(CIS_DEBUG)
if (cis_debug > 1) {
}
#endif
}
/*
* cis_process_longlink - processes longlink tuples
*
* This function examines the passed-in tuple type and if it is a
* longlink tuple, the tuple is parsed and the appropriate flags in
* cis_info->flags are set.
*
* If there is an error parsing the tuple, HANDTPL_ERROR is returned
* and the CW_LONGLINK_FOUND flags in cis_info->flags are cleared.
*/
static int
{
/*
* If this is a CISTPL_LONGLINK_A, CISTPL_LONGLINK_C
* or CISTPL_LONGLINK_MFC tuple, parse the tuple
* and set appropriate CW_LONGLINK_XXX_FOUND flags.
* If this is a CISTPL_NO_LINK tuple, or if there is an
* error parsing the tuple, clear all the
* CW_LONGLINK_XXX_FOUND flags.
*/
case CISTPL_LONGLINK_A:
case CISTPL_LONGLINK_C:
case CISTPL_LONGLINK_MFC:
return (HANDTPL_ERROR);
case CISTPL_LONGLINK_A:
break;
case CISTPL_LONGLINK_C:
break;
case CISTPL_LONGLINK_MFC:
break;
} /* switch (tp->type) */
break;
case CISTPL_NO_LINK:
break;
} /* switch (tp->type) */
return (HANDTPL_NOERROR);
}
/*
* cis_list_ldestroy - function to destroy a linked tuple list
*
* cistpl_t *cistplbase - pointer to a pointer to the base of a
* local linked CIS list to destroy; the
* data that this pointer points to is
* also destroyed
*
* Once this function returns, cistplbase is set to NULL.
*/
{
int tpcnt = 0;
/*
* First, check to see if we've got a
* non-NULL list pointer.
*/
return (0);
while (tp) {
/*
* Free any data that may be allocated
*/
/*
* Free this tuple
*/
tpcnt++;
}
/*
* Now clear the pointer to the non-existant
* linked list.
*/
*cistplbase = NULL;
return (tpcnt);
}
/*
* cis_get_ltuple - function to walk local linked CIS list and return
* a tuple based on various criteria
*
* cistpl_t *tp - pointer to any valid tuple in the list
* cisdata_t type - type of tuple to search for
* int flags - type of action to perform (each is mutually exclusive)
* GET_FIRST_LTUPLEF, GET_LAST_LTUPLEF:
* Returns the {first|last} tuple in the list.
* FIND_LTUPLE_FWDF, FIND_LTUPLE_BACKF:
* FIND_NEXT_LTUPLEF, FIND_PREV_LTUPLEF:
* Returns the first tuple that matches the passed tuple type,
* searching the list {forward|backward}.
* GET_NEXT_LTUPLEF, GET_PREV_LTUPLEF:
* Returns the {next|previous} tuple in the list.
*
* The following bits can be set in the flags parameter:
* CIS_GET_LTUPLE_IGNORE - return tuples with
* CISTPLF_IGNORE_TUPLE set in cistpl_t->flags
*
* Note on searching:
* When using the FIND_LTUPLE_FWDF and FIND_LTUPLE_BACKF flags,
* the search starts at the passed tuple. Continually calling this
* function with a tuple that is the same type as the passed type will
* continually return the same tuple.
*
* When using the FIND_NEXT_LTUPLEF and FIND_PREV_LTUPLEF flags,
* the search starts at the {next|previous} tuple from the passed tuple.
*
* returns:
* cistpl_t * - pointer to tuple in list
* NULL - if error while processing list or tuple not found
*/
cistpl_t *
{
if (!tp)
return (NULL);
switch (flags & CIS_GET_LTUPLE_OPMASK) {
case GET_FIRST_LTUPLEF: /* return first tuple in list */
do {
if (!(flags & CIS_GET_LTUPLE_IGNORE))
break;
case GET_LAST_LTUPLEF: /* return last tuple in list */
do {
if (!(flags & CIS_GET_LTUPLE_IGNORE))
break;
case FIND_LTUPLE_FWDF: /* find tuple, fwd search from tp */
do {
if ((flags & CIS_GET_LTUPLE_IGNORE) ||
return (tp); /* note return here */
break;
case FIND_LTUPLE_BACKF:
/* find tuple, backward search from tp */
do {
if ((flags & CIS_GET_LTUPLE_IGNORE) ||
return (tp); /* note return here */
break;
case FIND_NEXT_LTUPLEF: /* find tuple, fwd search from tp+1 */
if ((flags & CIS_GET_LTUPLE_IGNORE) ||
return (tp); /* note return here */
} /* while */
break;
case FIND_PREV_LTUPLEF:
/* find tuple, backward search from tp-1 */
if ((flags & CIS_GET_LTUPLE_IGNORE) ||
return (tp); /* note return here */
} /* while */
break;
case GET_NEXT_LTUPLEF: /* return next tuple in list */
(!(flags & CIS_GET_LTUPLE_IGNORE)) &&
;
break;
case GET_PREV_LTUPLEF: /* return prev tuple in list */
(!(flags & CIS_GET_LTUPLE_IGNORE)) &&
;
break;
default: /* ltp is already NULL in the initialization */
break;
} /* switch */
return (ltp);
}
/*
* cis_convert_devspeed - converts a devspeed value to nS or nS
* to a devspeed entry
*/
{
/*
* Convert nS to a devspeed value
*/
/*
* There is no device speed code for 0nS
*/
return (CS_BAD_SPEED);
/*
* Handle any nS value below 10nS specially since the code
* below only works for nS values >= 10. Now, why anyone
* would want to specify a nS value less than 10 is
* certainly questionable, but it is allowed by the spec.
*/
}
/* find the exponent */
for (i = 0; i < CISTPL_DEVSPEED_MAX_EXP; i++) {
(mantissa == CISTPL_DEVSPEED_MAX_MAN)) {
/* find the mantissa */
mantissa++) {
return (CS_SUCCESS);
}
} /* for (mantissa<CISTPL_DEVSPEED_MAX_MAN) */
} else {
exponent = i + 1;
} /* if (!tnS) */
} /* for (i<CISTPL_DEVSPEED_MAX_EXP) */
/*
* Convert a devspeed value to nS
*/
return (CS_BAD_SPEED);
return (CS_SUCCESS);
} else {
return (CS_BAD_SPEED);
return (CS_SUCCESS);
}
} else {
return (CS_BAD_ATTRIBUTE);
}
return (CS_BAD_SPEED);
}
/*
* This array is for the cis_convert_devsize function.
*/
{ 512, 2*1024, 8*1024, 32*1024, 128*1024, 512*1024, 2*1024*1024, 0 };
/*
* cis_convert_devsize - converts a devsize value to a size in bytes value
* or a size in bytes value to a devsize value
*/
{
int i;
return (CS_BAD_SIZE);
for (i = 6; i >= 0; i--)
break;
(i & 7));
return (CS_BAD_SIZE);
} else {
return (CS_BAD_ATTRIBUTE);
}
return (CS_SUCCESS);
}
/*
* cis_list_create - reads the card's CIS and creates local CIS lists for
* each function on the card
*
* This function will read the CIS on the card, follow all CISTPL_LONGLINK_A,
* CISTPL_LONGLINK_C and CISTPL_LONGLINK_MFC tuples and create local CIS
* lists for each major CIS chain on the card.
*
* If there are no errors, the parameters returned are:
* For a non-multifunction card:
* sp->cis_flags - CW_VALID_CIS set
* sp->nfuncs - set to 0x0
* sp->cis[CS_GLOBAL_CIS] - contains CIS list
* sp->cis[CS_GLOBAL_CIS].cis_flags - CW_VALID_CIS set
*
* For a multifunction card:
* Global CIS values:
* sp->cis_flags - CW_VALID_CIS & CW_MULTI_FUNCTION_CIS set
* sp->nfuncs - set to number of functions specified in
* the CISTPL_LONGLINK_MFC tuple
* sp->cis[CS_GLOBAL_CIS] - contains global CIS list
* sp->cis[CS_GLOBAL_CIS].cis_flags - CW_VALID_CIS set
* Function-specific CIS values:
* sp->cis[0..sp->nfuncs-1] - contains function-specific CIS lists
* sp->cis[0..sp->nfuncs-1].cis_flags - CW_VALID_CIS &
* CW_MULTI_FUNCTION_CIS set
*
* returns:
* CS_SUCCESS - if no errors
* CS_NO_CIS - if no CIS on card
* CS_BAD_WINDOW or CS_GENERAL_FAILURE - if CIS window could
* not be setup
* CS_BAD_CIS - if error creating CIS chains
* CS_BAD_OFFSET - if cis_list_lcreate tried to read past the
* boundries of the allocated CIS window
*/
extern cistpl_ignore_list_t cistpl_ignore_list[];
{
/*
* Initialize the CIS structures
*/
/*
* Start reading the primary CIS chain at offset 0x0 of AM. Assume
* that there is a CISTPL_LONGLINK_C tuple that points to
* offset 0x0 of CM space.
* Since this is the primary CIS chain, set CW_CHECK_PRIMARY_CHAIN
* so that we'll check for a valid first tuple.
*/
cistpl_longlink_ac->tpll_addr = 0;
CS_SUCCESS) {
return (ret);
} /* cis_create_cis_chain */
/*
* If there are no tuples in the primary CIS chain, it means that
* this card doesn't have a CIS on it.
*/
return (CS_NO_CIS);
/*
* Mark this CIS list as being valid.
*/
/*
* Mark this socket as having at least one valid CIS chain.
*/
/*
* If the primary CIS chain specified that there are function-specific
* CIS chains, we need to create each of these chains. If not,
* then we're all done and we can return.
*/
return (CS_SUCCESS);
/*
* Mark this socket as having a multi-function CIS.
*/
/*
* At this point, cis_create_cis_chain has told us that the primary
* CIS chain says that there are function-specific CIS chains
* on the card that we need to follow. The cisparse variable now
* contains the parsed output of the CISTPL_LONGLINK_MFC
* tuple. We need to save that information and then process
* each function-specific CIS chain.
*/
sizeof (cistpl_longlink_mfc_t));
/*
* Go through and create a CIS list for each function-specific
* CIS chain on the card. Set CW_CHECK_LINKTARGET since all
* function-specific CIS chains must begin with a valid
* CISTPL_LINKTARGET tuple. Also set CW_RET_ON_LINKTARGET_ERROR
* since we want to return an error if the CISTPL_LINKTARGET
* tuple is invalid or missing.
*/
/*
* If the function-specific CIS chain starts
* in AM space, then multiply address by
* 2 since only even bytes are counted in
* the CIS when AM addresses are specified,
* otherwise use the
* address as specified.
*/
} else {
}
CS_SUCCESS) {
"cis_list_create: socket %d ERROR_MFC = 0x%x\n",
return (ret);
} /* cis_create_cis_chain */
/*
* Mark this CIS list as being valid and as being a
* function-specific CIS list.
*/
/*
* Check for tuples that we want to ignore
* in the global CIS. If the tuple exists
* in the global CIS and in at least one
* of the function-specific CIS lists, then
* we flag the tuple
* in the global CIS to be ignored.
*/
cil = &cistpl_ignore_list[0];
CIS_GET_LTUPLE_IGNORE) != NULL) {
CIS_GET_LTUPLE_IGNORE)) != NULL) {
} /* while */
} /* if (cis_get_ltuple(cis[fn])) */
cil++;
} /* while */
} /* for */
return (CS_SUCCESS);
}
/*
* cis_create_cis_chain - creates a single CIS chain
*
* This function reads the CIS on a card and follows any CISTPL_LONGLINK_A
* and CISTPL_LONGLINK_C link tuples to create a single CIS chain. We
* keep reading the CIS and following any CISTPL_LONGLINK_A and
* CISTPL_LONGLINK_C tuples until we don't see anymore. If we see a
* CISTPL_LONGLINK_MFC tuple, we return - the caller is responsible
* for following CIS chains on a per-function level.
*
* The following parameters must be initialized by the caller:
*
* sp - pointer to a cs_socket_t structure that describes the socket
* and card in this socket
* cistpl_callout - pointer to a cistpl_callout_t array of structures
* cisptr->flags - either CISTPLF_AM_SPACE or CISTPLF_CM_SPACE
* cisptr->size - size of CIS window
* cisptr->offset - offset in AM or CM space on card to start
* reading tuples from
* cis_info - pointer to a cis_info_t structure where this list will
* be anchored on
* cisparse - pointer to a cisparse_t structure where the last longlink
* parsed tuple data will be returned
*
* To check the CISTPL_LINKTARGET tuple at the beginning of the first
* CIS chain that this function encounters, set CW_CHECK_LINKTARGET
* in cis_info->flags before calling this function.
*
* This function returns:
*
* CS_SUCCESS - if CIS chain was created sucessfully or there
* were no tuples found on the first CIS chain
* CS_BAD_WINDOW or CS_GENERAL_FAILURE - if CIS window could
* not be setup
* CS_BAD_CIS - if error creating CIS chain
* CS_BAD_OFFSET - if cis_list_lcreate tried to read past the
* boundries of the allocated CIS window
*
* Note that if the first tuple of the target CIS chain is supposed
* to contain a CISTPL_LINKTARGET and the target chain does not
* contain that tuple (or that tuple is invalid in some way) and
* the CW_RET_ON_LINKTARGET_ERROR flag is not set, we don't flag
* this as an error, we just return. This is to handle the case
* where the target chain is in uninitialized memory and will be
* initialized later.
* To return an error if an invalid CISTPL_LINKTARGET tuple is seen,
* set the CW_RET_ON_LINKTARGET_ERROR flag in cis_info->flags
* before calling this function.
*/
static int
{
do {
return (ret);
/*
* If we're pointing at a CIS chain that
* is the target of a longlink tuple,
* we need to validate the target chain
* before we try to process it. If the
* CISTPL_LINKTARGET tuple is invalid,
* and the CW_RET_ON_LINKTARGET_ERROR
* is not set, don't flag it as an error,
* just return.
*/
return (CS_BAD_CIS);
} else {
return (CS_SUCCESS);
} /* CW_RET_ON_LINKTARGET_ERROR */
} /* cis_validate_longlink_acm */
} /* CW_CHECK_LINKTARGET */
sp);
#if defined(CIS_DEBUG)
if (cis_debug > 1) {
" BAD_CIS_ADDR=0x%x CS_BAD_SOCKET=0x%x\n",
}
#endif
return (CS_BAD_OFFSET);
else
return (CS_BAD_CIS);
}
/*
* If we're creating the primary CIS chain
* and we haven't seen any tuples,
* then return CS_SUCCESS. The caller will
* have to check cis_info->ntuples to find
* out if any tuples were found.
* If we're processing the target of a longlink
* tuple, then by now we have already validated
* the CISTPL_LINKTARGET tuple so that we
* know we'll have at least one tuple in
* our list.
*/
return (CS_SUCCESS);
/*
* If we've just created a new list, we need to
* save the pointer to the start of the list.
*/
case CW_LONGLINK_A_FOUND:
/*
* Multiply address by 2 since only
* even bytes are counted in the CIS
* when AM addresses are specified.
*/
/*
* Point to the last tuple in the list.
*/
break;
case CW_LONGLINK_C_FOUND:
/*
* Point to the last tuple in the list.
*/
break;
case CW_LONGLINK_MFC_FOUND:
break;
default:
break;
} /* switch (cis_info->flags) */
/*
* If we needed to save a pointer to the start of the list because
* we saw a longlink tuple, restore the list head pointer now.
*/
return (CS_SUCCESS);
}
/*
* cis_list_destroy - destroys the local CIS list
*/
{
int fn;
/*
* Destroy any CIS list that we may have created. It's OK to pass
* a non-existant CIS list pointer to cis_list_ldestroy since
* that function will not do anything if there is nothing in
* the passed CIS list to cleanup.
*/
/*
* Clear out any remaining state.
*/
return (CS_SUCCESS);
}
/*
* cis_store_cis_addr - saves the current CIS address and space type
* of the beginning of the tuple into the passed linked list element.
* Note that this function will decrement the CIS address by two
* elements prior to storing it to the linked list element to point
* to the tuple type byte.
*
* This function also sets the following flags in tp->flags if they are set
* in ptr->flags:
*
* CISTPLF_GLOBAL_CIS - tuple in global CIS
* CISTPLF_MF_CIS - tuple in function-specific CIS
*/
static void
{
else
}