in cistpl.c [521:631]
int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function,
tuple_t *tuple)
{
u_char link[2], tmp;
int ofs, i, attr;
int ret;
if (!s)
return -EINVAL;
if (!(s->state & SOCKET_PRESENT) || (s->state & SOCKET_CARDBUS))
return -ENODEV;
link[1] = tuple->TupleLink;
ofs = tuple->CISOffset + tuple->TupleLink;
attr = SPACE(tuple->Flags);
for (i = 0; i < MAX_TUPLES; i++) {
if (link[1] == 0xff)
link[0] = CISTPL_END;
else {
ret = read_cis_cache(s, attr, ofs, 2, link);
if (ret)
return -1;
if (link[0] == CISTPL_NULL) {
ofs++;
continue;
}
}
/* End of chain? Follow long link if possible */
if (link[0] == CISTPL_END) {
ofs = follow_link(s, tuple);
if (ofs < 0)
return -ENOSPC;
attr = SPACE(tuple->Flags);
ret = read_cis_cache(s, attr, ofs, 2, link);
if (ret)
return -1;
}
/* Is this a link tuple? Make a note of it */
if ((link[0] == CISTPL_LONGLINK_A) ||
(link[0] == CISTPL_LONGLINK_C) ||
(link[0] == CISTPL_LONGLINK_MFC) ||
(link[0] == CISTPL_LINKTARGET) ||
(link[0] == CISTPL_INDIRECT) ||
(link[0] == CISTPL_NO_LINK)) {
switch (link[0]) {
case CISTPL_LONGLINK_A:
HAS_LINK(tuple->Flags) = 1;
LINK_SPACE(tuple->Flags) = attr | IS_ATTR;
ret = read_cis_cache(s, attr, ofs+2, 4,
&tuple->LinkOffset);
if (ret)
return -1;
break;
case CISTPL_LONGLINK_C:
HAS_LINK(tuple->Flags) = 1;
LINK_SPACE(tuple->Flags) = attr & ~IS_ATTR;
ret = read_cis_cache(s, attr, ofs+2, 4,
&tuple->LinkOffset);
if (ret)
return -1;
break;
case CISTPL_INDIRECT:
HAS_LINK(tuple->Flags) = 1;
LINK_SPACE(tuple->Flags) = IS_ATTR |
IS_INDIRECT;
tuple->LinkOffset = 0;
break;
case CISTPL_LONGLINK_MFC:
tuple->LinkOffset = ofs + 3;
LINK_SPACE(tuple->Flags) = attr;
if (function == BIND_FN_ALL) {
/* Follow all the MFC links */
ret = read_cis_cache(s, attr, ofs+2,
1, &tmp);
if (ret)
return -1;
MFC_FN(tuple->Flags) = tmp;
} else {
/* Follow exactly one of the links */
MFC_FN(tuple->Flags) = 1;
tuple->LinkOffset += function * 5;
}
break;
case CISTPL_NO_LINK:
HAS_LINK(tuple->Flags) = 0;
break;
}
if ((tuple->Attributes & TUPLE_RETURN_LINK) &&
(tuple->DesiredTuple == RETURN_FIRST_TUPLE))
break;
} else
if (tuple->DesiredTuple == RETURN_FIRST_TUPLE)
break;
if (link[0] == tuple->DesiredTuple)
break;
ofs += link[1] + 2;
}
if (i == MAX_TUPLES) {
dev_dbg(&s->dev, "cs: overrun in pcmcia_get_next_tuple\n");
return -ENOSPC;
}
tuple->TupleCode = link[0];
tuple->TupleLink = link[1];
tuple->CISOffset = ofs + 2;
return 0;
}