📄 cistpl.c
字号:
if (has_ha) for (j = 0; j < asz; j++, p++) { if (p == q) return NULL; ha += *p << (j*8); } mem->win[i].len = len << 8; mem->win[i].card_addr = ca << 8; mem->win[i].host_addr = ha << 8; } return p;}/*====================================================================*/static u_char *parse_irq(u_char *p, u_char *q, cistpl_irq_t *irq){ if (p == q) return NULL; irq->IRQInfo1 = *p; p++; if (irq->IRQInfo1 & IRQ_INFO2_VALID) { if (p+2 > q) return NULL; irq->IRQInfo2 = (p[1]<<8) + p[0]; p += 2; } return p;}/*====================================================================*/static int parse_cftable_entry(tuple_t *tuple, cistpl_cftable_entry_t *entry){ u_char *p, *q, features; p = tuple->TupleData; q = p + tuple->TupleDataLen; entry->index = *p & 0x3f; entry->flags = 0; if (*p & 0x40) entry->flags |= CISTPL_CFTABLE_DEFAULT; if (*p & 0x80) { if (++p == q) return CS_BAD_TUPLE; if (*p & 0x10) entry->flags |= CISTPL_CFTABLE_BVDS; if (*p & 0x20) entry->flags |= CISTPL_CFTABLE_WP; if (*p & 0x40) entry->flags |= CISTPL_CFTABLE_RDYBSY; if (*p & 0x80) entry->flags |= CISTPL_CFTABLE_MWAIT; entry->interface = *p & 0x0f; } else entry->interface = 0; /* Process optional features */ if (++p == q) return CS_BAD_TUPLE; features = *p; p++; /* Power options */ if ((features & 3) > 0) { p = parse_power(p, q, &entry->vcc); if (p == NULL) return CS_BAD_TUPLE; } else entry->vcc.present = 0; if ((features & 3) > 1) { p = parse_power(p, q, &entry->vpp1); if (p == NULL) return CS_BAD_TUPLE; } else entry->vpp1.present = 0; if ((features & 3) > 2) { p = parse_power(p, q, &entry->vpp2); if (p == NULL) return CS_BAD_TUPLE; } else entry->vpp2.present = 0; /* Timing options */ if (features & 0x04) { p = parse_timing(p, q, &entry->timing); if (p == NULL) return CS_BAD_TUPLE; } else { entry->timing.wait = 0; entry->timing.ready = 0; entry->timing.reserved = 0; } /* I/O window options */ if (features & 0x08) { p = parse_io(p, q, &entry->io); if (p == NULL) return CS_BAD_TUPLE; } else entry->io.nwin = 0; /* Interrupt options */ if (features & 0x10) { p = parse_irq(p, q, &entry->irq); if (p == NULL) return CS_BAD_TUPLE; } else entry->irq.IRQInfo1 = 0; switch (features & 0x60) { case 0x00: entry->mem.nwin = 0; break; case 0x20: entry->mem.nwin = 1; entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8; entry->mem.win[0].card_addr = 0; entry->mem.win[0].host_addr = 0; p += 2; if (p > q) return CS_BAD_TUPLE; break; case 0x40: entry->mem.nwin = 1; entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8; entry->mem.win[0].card_addr = le16_to_cpu(*(u_short *)(p+2)) << 8; entry->mem.win[0].host_addr = 0; p += 4; if (p > q) return CS_BAD_TUPLE; break; case 0x60: p = parse_mem(p, q, &entry->mem); if (p == NULL) return CS_BAD_TUPLE; break; } /* Misc features */ if (features & 0x80) { if (p == q) return CS_BAD_TUPLE; entry->flags |= (*p << 8); while (*p & 0x80) if (++p == q) return CS_BAD_TUPLE; p++; } entry->subtuples = q-p; return CS_SUCCESS;}/*====================================================================*/#ifdef CONFIG_CARDBUSstatic int parse_bar(tuple_t *tuple, cistpl_bar_t *bar){ u_char *p; if (tuple->TupleDataLen < 6) return CS_BAD_TUPLE; p = (u_char *)tuple->TupleData; bar->attr = *p; p += 2; bar->size = le32_to_cpu(*(u_int *)p); return CS_SUCCESS;}static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config){ u_char *p; p = (u_char *)tuple->TupleData; if ((*p != 3) || (tuple->TupleDataLen < 6)) return CS_BAD_TUPLE; config->last_idx = *(++p); p++; config->base = le32_to_cpu(*(u_int *)p); config->subtuples = tuple->TupleDataLen - 6; return CS_SUCCESS;}static int parse_cftable_entry_cb(tuple_t *tuple, cistpl_cftable_entry_cb_t *entry){ u_char *p, *q, features; p = tuple->TupleData; q = p + tuple->TupleDataLen; entry->index = *p & 0x3f; entry->flags = 0; if (*p & 0x40) entry->flags |= CISTPL_CFTABLE_DEFAULT; /* Process optional features */ if (++p == q) return CS_BAD_TUPLE; features = *p; p++; /* Power options */ if ((features & 3) > 0) { p = parse_power(p, q, &entry->vcc); if (p == NULL) return CS_BAD_TUPLE; } else entry->vcc.present = 0; if ((features & 3) > 1) { p = parse_power(p, q, &entry->vpp1); if (p == NULL) return CS_BAD_TUPLE; } else entry->vpp1.present = 0; if ((features & 3) > 2) { p = parse_power(p, q, &entry->vpp2); if (p == NULL) return CS_BAD_TUPLE; } else entry->vpp2.present = 0; /* I/O window options */ if (features & 0x08) { if (p == q) return CS_BAD_TUPLE; entry->io = *p; p++; } else entry->io = 0; /* Interrupt options */ if (features & 0x10) { p = parse_irq(p, q, &entry->irq); if (p == NULL) return CS_BAD_TUPLE; } else entry->irq.IRQInfo1 = 0; if (features & 0x20) { if (p == q) return CS_BAD_TUPLE; entry->mem = *p; p++; } else entry->mem = 0; /* Misc features */ if (features & 0x80) { if (p == q) return CS_BAD_TUPLE; entry->flags |= (*p << 8); if (*p & 0x80) { if (++p == q) return CS_BAD_TUPLE; entry->flags |= (*p << 16); } while (*p & 0x80) if (++p == q) return CS_BAD_TUPLE; p++; } entry->subtuples = q-p; return CS_SUCCESS;}#endif/*====================================================================*/static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo){ u_char *p, *q; int n; p = (u_char *)tuple->TupleData; q = p + tuple->TupleDataLen; for (n = 0; n < CISTPL_MAX_DEVICES; n++) { if (p > q-6) break; geo->geo[n].buswidth = p[0]; geo->geo[n].erase_block = 1 << (p[1]-1); geo->geo[n].read_block = 1 << (p[2]-1); geo->geo[n].write_block = 1 << (p[3]-1); geo->geo[n].partition = 1 << (p[4]-1); geo->geo[n].interleave = 1 << (p[5]-1); p += 6; } geo->ngeo = n; return CS_SUCCESS;}/*====================================================================*/static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2){ u_char *p, *q; if (tuple->TupleDataLen < 10) return CS_BAD_TUPLE; p = tuple->TupleData; q = p + tuple->TupleDataLen; v2->vers = p[0]; v2->comply = p[1]; v2->dindex = le16_to_cpu(*(u_short *)(p+2)); v2->vspec8 = p[6]; v2->vspec9 = p[7]; v2->nhdr = p[8]; p += 9; return parse_strings(p, q, 2, v2->str, &v2->vendor, NULL);}/*====================================================================*/static int parse_org(tuple_t *tuple, cistpl_org_t *org){ u_char *p, *q; int i; p = tuple->TupleData; q = p + tuple->TupleDataLen; if (p == q) return CS_BAD_TUPLE; org->data_org = *p; if (++p == q) return CS_BAD_TUPLE; for (i = 0; i < 30; i++) { org->desc[i] = *p; if (*p == '\0') break; if (++p == q) return CS_BAD_TUPLE; } return CS_SUCCESS;}/*====================================================================*/static int parse_format(tuple_t *tuple, cistpl_format_t *fmt){ u_char *p; if (tuple->TupleDataLen < 10) return CS_BAD_TUPLE; p = tuple->TupleData; fmt->type = p[0]; fmt->edc = p[1]; fmt->offset = le32_to_cpu(*(u_int *)(p+2)); fmt->length = le32_to_cpu(*(u_int *)(p+6)); return CS_SUCCESS;}/*====================================================================*/int parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse){ int ret = CS_SUCCESS; if (tuple->TupleDataLen > tuple->TupleDataMax) return CS_BAD_TUPLE; switch (tuple->TupleCode) { case CISTPL_DEVICE: case CISTPL_DEVICE_A: ret = parse_device(tuple, &parse->device); break;#ifdef CONFIG_CARDBUS case CISTPL_BAR: ret = parse_bar(tuple, &parse->bar); break; case CISTPL_CONFIG_CB: ret = parse_config_cb(tuple, &parse->config); break; case CISTPL_CFTABLE_ENTRY_CB: ret = parse_cftable_entry_cb(tuple, &parse->cftable_entry_cb); break;#endif case CISTPL_CHECKSUM: ret = parse_checksum(tuple, &parse->checksum); break; case CISTPL_LONGLINK_A: case CISTPL_LONGLINK_C: ret = parse_longlink(tuple, &parse->longlink); break; case CISTPL_LONGLINK_MFC: ret = parse_longlink_mfc(tuple, &parse->longlink_mfc); break; case CISTPL_VERS_1: ret = parse_vers_1(tuple, &parse->version_1); break; case CISTPL_ALTSTR: ret = parse_altstr(tuple, &parse->altstr); break; case CISTPL_JEDEC_A: case CISTPL_JEDEC_C: ret = parse_jedec(tuple, &parse->jedec); break; case CISTPL_MANFID: ret = parse_manfid(tuple, &parse->manfid); break; case CISTPL_FUNCID: ret = parse_funcid(tuple, &parse->funcid); break; case CISTPL_FUNCE: ret = parse_funce(tuple, &parse->funce); break; case CISTPL_CONFIG: ret = parse_config(tuple, &parse->config); break; case CISTPL_CFTABLE_ENTRY: ret = parse_cftable_entry(tuple, &parse->cftable_entry); break; case CISTPL_DEVICE_GEO: case CISTPL_DEVICE_GEO_A: ret = parse_device_geo(tuple, &parse->device_geo); break; case CISTPL_VERS_2: ret = parse_vers_2(tuple, &parse->vers_2); break; case CISTPL_ORG: ret = parse_org(tuple, &parse->org); break; case CISTPL_FORMAT: case CISTPL_FORMAT_A: ret = parse_format(tuple, &parse->format); break; case CISTPL_NO_LINK: case CISTPL_LINKTARGET: ret = CS_SUCCESS; break; default: ret = CS_UNSUPPORTED_FUNCTION; break; } return ret;}/*====================================================================== This is used internally by Card Services to look up CIS stuff. ======================================================================*/int read_tuple(client_handle_t handle, cisdata_t code, void *parse){ tuple_t tuple; cisdata_t buf[255]; int ret; tuple.DesiredTuple = code; tuple.Attributes = TUPLE_RETURN_COMMON; ret = CardServices(GetFirstTuple, handle, &tuple, NULL); if (ret != CS_SUCCESS) return ret; tuple.TupleData = buf; tuple.TupleOffset = 0; tuple.TupleDataMax = sizeof(buf); ret = CardServices(GetTupleData, handle, &tuple, NULL); if (ret != CS_SUCCESS) return ret; ret = CardServices(ParseTuple, handle, &tuple, parse); return ret;}/*====================================================================== This tries to determine if a card has a sensible CIS. It returns the number of tuples in the CIS, or 0 if the CIS looks bad. The checks include making sure several critical tuples are present and valid; seeing if the total number of tuples is reasonable; and looking for tuples that use reserved codes. ======================================================================*/int validate_cis(client_handle_t handle, cisinfo_t *info){ tuple_t tuple; cisparse_t p; int ret, reserved, dev_ok = 0, ident_ok = 0; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; info->Chains = reserved = 0; tuple.DesiredTuple = RETURN_FIRST_TUPLE; tuple.Attributes = TUPLE_RETURN_COMMON; ret = get_first_tuple(handle, &tuple); if (ret != CS_SUCCESS) return CS_SUCCESS; /* First tuple should be DEVICE; we should really have either that or a CFTABLE_ENTRY of some sort */ if ((tuple.TupleCode == CISTPL_DEVICE) || (read_tuple(handle, CISTPL_CFTABLE_ENTRY, &p) == CS_SUCCESS) || (read_tuple(handle, CISTPL_CFTABLE_ENTRY_CB, &p) == CS_SUCCESS)) dev_ok++; /* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2 tuple, for card identification. Certain old D-Link and Linksys cards have only a broken VERS_2 tuple; hence the bogus test. */ if ((read_tuple(handle, CISTPL_MANFID, &p) == CS_SUCCESS) || (read_tuple(handle, CISTPL_VERS_1, &p) == CS_SUCCESS) || (read_tuple(handle, CISTPL_VERS_2, &p) != CS_NO_MORE_ITEMS)) ident_ok++; if (!dev_ok && !ident_ok) return CS_SUCCESS; for (info->Chains = 1; info->Chains < MAX_TUPLES; info->Chains++) { ret = get_next_tuple(handle, &tuple); if (ret != CS_SUCCESS) break; if (((tuple.TupleCode > 0x23) && (tuple.TupleCode < 0x40)) || ((tuple.TupleCode > 0x47) && (tuple.TupleCode < 0x80)) || ((tuple.TupleCode > 0x90) && (tuple.TupleCode < 0xff))) reserved++; } if ((info->Chains == MAX_TUPLES) || (reserved > 5) || ((!dev_ok || !ident_ok) && (info->Chains > 10))) info->Chains = 0; return CS_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -