📄 cistpl.c
字号:
socket_info_t *s; u_char link[2], tmp; int ofs, i, attr; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; s = SOCKET(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; 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 { read_cis_cache(s, attr, ofs, 2, link); if (link[0] == CISTPL_NULL) { ofs++; continue; } } /* End of chain? Follow long link if possible */ if (link[0] == CISTPL_END) { if ((ofs = follow_link(s, tuple)) < 0) return CS_NO_MORE_ITEMS; attr = SPACE(tuple->Flags); read_cis_cache(s, attr, ofs, 2, link); } /* 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; read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset); break; case CISTPL_LONGLINK_C: HAS_LINK(tuple->Flags) = 1; LINK_SPACE(tuple->Flags) = attr & ~IS_ATTR; read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset); 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 (handle->Function == BIND_FN_ALL) { /* Follow all the MFC links */ read_cis_cache(s, attr, ofs+2, 1, &tmp); MFC_FN(tuple->Flags) = tmp; } else { /* Follow exactly one of the links */ MFC_FN(tuple->Flags) = 1; tuple->LinkOffset += handle->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) { DEBUG(1, "cs: overrun in get_next_tuple for socket %d\n", handle->Socket); return CS_NO_MORE_ITEMS; } tuple->TupleCode = link[0]; tuple->TupleLink = link[1]; tuple->CISOffset = ofs + 2; return CS_SUCCESS;}/*====================================================================*/#define _MIN(a, b) (((a) < (b)) ? (a) : (b))int get_tuple_data(client_handle_t handle, tuple_t *tuple){ socket_info_t *s; u_int len; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; s = SOCKET(handle); if (tuple->TupleLink < tuple->TupleOffset) return CS_NO_MORE_ITEMS; len = tuple->TupleLink - tuple->TupleOffset; tuple->TupleDataLen = tuple->TupleLink; if (len == 0) return CS_SUCCESS; read_cis_cache(s, SPACE(tuple->Flags), tuple->CISOffset + tuple->TupleOffset, _MIN(len, tuple->TupleDataMax), tuple->TupleData); return CS_SUCCESS;}/*====================================================================== Parsing routines for individual tuples ======================================================================*/static int parse_device(tuple_t *tuple, cistpl_device_t *device){ int i; u_char scale; u_char *p, *q; p = (u_char *)tuple->TupleData; q = p + tuple->TupleDataLen; device->ndev = 0; for (i = 0; i < CISTPL_MAX_DEVICES; i++) { if (*p == 0xff) break; device->dev[i].type = (*p >> 4); device->dev[i].wp = (*p & 0x08) ? 1 : 0; switch (*p & 0x07) { case 0: device->dev[i].speed = 0; break; case 1: device->dev[i].speed = 250; break; case 2: device->dev[i].speed = 200; break; case 3: device->dev[i].speed = 150; break; case 4: device->dev[i].speed = 100; break; case 7: if (++p == q) return CS_BAD_TUPLE; device->dev[i].speed = SPEED_CVT(*p); while (*p & 0x80) if (++p == q) return CS_BAD_TUPLE; break; default: return CS_BAD_TUPLE; } if (++p == q) return CS_BAD_TUPLE; if (*p == 0xff) break; scale = *p & 7; if (scale == 7) return CS_BAD_TUPLE; device->dev[i].size = ((*p >> 3) + 1) * (512 << (scale*2)); device->ndev++; if (++p == q) break; } return CS_SUCCESS;}/*====================================================================*/static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum){ u_char *p; if (tuple->TupleDataLen < 5) return CS_BAD_TUPLE; p = (u_char *)tuple->TupleData; csum->addr = tuple->CISOffset+(short)le16_to_cpu(*(u_short *)p)-2; csum->len = le16_to_cpu(*(u_short *)(p + 2)); csum->sum = *(p+4); return CS_SUCCESS;}/*====================================================================*/static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link){ if (tuple->TupleDataLen < 4) return CS_BAD_TUPLE; link->addr = le32_to_cpu(*(u_int *)tuple->TupleData); return CS_SUCCESS;}/*====================================================================*/static int parse_longlink_mfc(tuple_t *tuple, cistpl_longlink_mfc_t *link){ u_char *p; int i; p = (u_char *)tuple->TupleData; link->nfn = *p; p++; if (tuple->TupleDataLen <= link->nfn*5) return CS_BAD_TUPLE; for (i = 0; i < link->nfn; i++) { link->fn[i].space = *p; p++; link->fn[i].addr = le32_to_cpu(*(u_int *)p); p += 4; } return CS_SUCCESS;}/*====================================================================*/static int parse_strings(u_char *p, u_char *q, int max, char *s, u_char *ofs, u_char *found){ int i, j, ns; if (p == q) return CS_BAD_TUPLE; ns = 0; j = 0; for (i = 0; i < max; i++) { if (*p == 0xff) break; ofs[i] = j; ns++; for (;;) { s[j++] = (*p == 0xff) ? '\0' : *p; if ((*p == '\0') || (*p == 0xff)) break; if (++p == q) return CS_BAD_TUPLE; } if ((*p == 0xff) || (++p == q)) break; } if (found) { *found = ns; return CS_SUCCESS; } else { return (ns == max) ? CS_SUCCESS : CS_BAD_TUPLE; }}/*====================================================================*/static int parse_vers_1(tuple_t *tuple, cistpl_vers_1_t *vers_1){ u_char *p, *q; p = (u_char *)tuple->TupleData; q = p + tuple->TupleDataLen; vers_1->major = *p; p++; vers_1->minor = *p; p++; if (p >= q) return CS_BAD_TUPLE; return parse_strings(p, q, CISTPL_VERS_1_MAX_PROD_STRINGS, vers_1->str, vers_1->ofs, &vers_1->ns);}/*====================================================================*/static int parse_altstr(tuple_t *tuple, cistpl_altstr_t *altstr){ u_char *p, *q; p = (u_char *)tuple->TupleData; q = p + tuple->TupleDataLen; return parse_strings(p, q, CISTPL_MAX_ALTSTR_STRINGS, altstr->str, altstr->ofs, &altstr->ns);}/*====================================================================*/static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec){ u_char *p, *q; int nid; p = (u_char *)tuple->TupleData; q = p + tuple->TupleDataLen; for (nid = 0; nid < CISTPL_MAX_DEVICES; nid++) { if (p > q-2) break; jedec->id[nid].mfr = p[0]; jedec->id[nid].info = p[1]; p += 2; } jedec->nid = nid; return CS_SUCCESS;}/*====================================================================*/static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m){ u_short *p; if (tuple->TupleDataLen < 4) return CS_BAD_TUPLE; p = (u_short *)tuple->TupleData; m->manf = le16_to_cpu(p[0]); m->card = le16_to_cpu(p[1]); return CS_SUCCESS;}/*====================================================================*/static int parse_funcid(tuple_t *tuple, cistpl_funcid_t *f){ u_char *p; if (tuple->TupleDataLen < 2) return CS_BAD_TUPLE; p = (u_char *)tuple->TupleData; f->func = p[0]; f->sysinit = p[1]; return CS_SUCCESS;}/*====================================================================*/static int parse_funce(tuple_t *tuple, cistpl_funce_t *f){ u_char *p; int i; if (tuple->TupleDataLen < 1) return CS_BAD_TUPLE; p = (u_char *)tuple->TupleData; f->type = p[0]; for (i = 1; i < tuple->TupleDataLen; i++) f->data[i-1] = p[i]; return CS_SUCCESS;}/*====================================================================*/static int parse_config(tuple_t *tuple, cistpl_config_t *config){ int rasz, rmsz, i; u_char *p; p = (u_char *)tuple->TupleData; rasz = *p & 0x03; rmsz = (*p & 0x3c) >> 2; if (tuple->TupleDataLen < rasz+rmsz+4) return CS_BAD_TUPLE; config->last_idx = *(++p); p++; config->base = 0; for (i = 0; i <= rasz; i++) config->base += p[i] << (8*i); p += rasz+1; for (i = 0; i < 4; i++) config->rmask[i] = 0; for (i = 0; i <= rmsz; i++) config->rmask[i>>2] += p[i] << (8*(i%4)); config->subtuples = tuple->TupleDataLen - (rasz+rmsz+4); return CS_SUCCESS;}/*====================================================================== The following routines are all used to parse the nightmarish config table entries. ======================================================================*/static u_char *parse_power(u_char *p, u_char *q, cistpl_power_t *pwr){ int i; u_int scale; if (p == q) return NULL; pwr->present = *p; pwr->flags = 0; p++; for (i = 0; i < 7; i++) if (pwr->present & (1<<i)) { if (p == q) return NULL; pwr->param[i] = POWER_CVT(*p); scale = POWER_SCALE(*p); while (*p & 0x80) { if (++p == q) return NULL; if ((*p & 0x7f) < 100) pwr->param[i] += (*p & 0x7f) * scale / 100; else if (*p == 0x7d) pwr->flags |= CISTPL_POWER_HIGHZ_OK; else if (*p == 0x7e) pwr->param[i] = 0; else if (*p == 0x7f) pwr->flags |= CISTPL_POWER_HIGHZ_REQ; else return NULL; } p++; } return p;}/*====================================================================*/static u_char *parse_timing(u_char *p, u_char *q, cistpl_timing_t *timing){ u_char scale; if (p == q) return NULL; scale = *p; if ((scale & 3) != 3) { if (++p == q) return NULL; timing->wait = SPEED_CVT(*p); timing->waitscale = exponent[scale & 3]; } else timing->wait = 0; scale >>= 2; if ((scale & 7) != 7) { if (++p == q) return NULL; timing->ready = SPEED_CVT(*p); timing->rdyscale = exponent[scale & 7]; } else timing->ready = 0; scale >>= 3; if (scale != 7) { if (++p == q) return NULL; timing->reserved = SPEED_CVT(*p); timing->rsvscale = exponent[scale]; } else timing->reserved = 0; p++; return p;}/*====================================================================*/static u_char *parse_io(u_char *p, u_char *q, cistpl_io_t *io){ int i, j, bsz, lsz; if (p == q) return NULL; io->flags = *p; if (!(*p & 0x80)) { io->nwin = 1; io->win[0].base = 0; io->win[0].len = (1 << (io->flags & CISTPL_IO_LINES_MASK)); return p+1; } if (++p == q) return NULL; io->nwin = (*p & 0x0f) + 1; bsz = (*p & 0x30) >> 4; if (bsz == 3) bsz++; lsz = (*p & 0xc0) >> 6; if (lsz == 3) lsz++; p++; for (i = 0; i < io->nwin; i++) { io->win[i].base = 0; io->win[i].len = 1; for (j = 0; j < bsz; j++, p++) { if (p == q) return NULL; io->win[i].base += *p << (j*8); } for (j = 0; j < lsz; j++, p++) { if (p == q) return NULL; io->win[i].len += *p << (j*8); } } return p;}/*====================================================================*/static u_char *parse_mem(u_char *p, u_char *q, cistpl_mem_t *mem){ int i, j, asz, lsz, has_ha; u_int len, ca, ha; if (p == q) return NULL; mem->nwin = (*p & 0x07) + 1; lsz = (*p & 0x18) >> 3; asz = (*p & 0x60) >> 5; has_ha = (*p & 0x80); if (++p == q) return NULL; for (i = 0; i < mem->nwin; i++) { len = ca = ha = 0; for (j = 0; j < lsz; j++, p++) { if (p == q) return NULL; len += *p << (j*8); } for (j = 0; j < asz; j++, p++) { if (p == q) return NULL; ca += *p << (j*8); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -