X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fpcmcia%2Fcistpl.c;h=912c03e5eb0a3d66448da64a26416d3d8a546dcf;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=317ca50a3db3b86e9729820237916cfe6fd3f4cd;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 317ca50a3..912c03e5e 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -1,37 +1,17 @@ -/*====================================================================== - - PCMCIA Card Information Structure parser - - cistpl.c 1.99 2002/10/24 06:11:48 - - The contents of this file are subject to the Mozilla Public - License Version 1.1 (the "License"); you may not use this file - except in compliance with the License. You may obtain a copy of - the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - implied. See the License for the specific language governing - rights and limitations under the License. - - The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU General Public License version 2 (the "GPL"), in - which case the provisions of the GPL are applicable instead of the - above. If you wish to allow the use of your version of this file - only under the terms of the GPL and not to allow others to use - your version of this file under the MPL, indicate your decision - by deleting the provisions above and replace them with the notice - and other provisions required by the GPL. If you do not delete - the provisions above, a recipient may use your version of this - file under either the MPL or the GPL. - -======================================================================*/ +/* + * cistpl.c -- 16-bit PCMCIA Card Information Structure parser + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * + * (C) 1999 David A. Hinds + */ -#include #include #include #include @@ -79,9 +59,9 @@ static const u_int exponent[] = { /* Parameters that can be set with 'insmod' */ -#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444) - -INT_MODULE_PARM(cis_width, 0); /* 16-bit CIS? */ +/* 16-bit CIS? */ +static int cis_width; +module_param(cis_width, int, 0444); void release_cis_mem(struct pcmcia_socket *s) { @@ -97,6 +77,7 @@ void release_cis_mem(struct pcmcia_socket *s) s->cis_virt = NULL; } } +EXPORT_SYMBOL(release_cis_mem); /* * Map the card memory at "card_offset" into virtual space. @@ -106,25 +87,38 @@ void release_cis_mem(struct pcmcia_socket *s) static void __iomem * set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags) { - pccard_mem_map *mem = &s->cis_mem; - if (!(s->features & SS_CAP_STATIC_MAP) && mem->res == NULL) { - mem->res = find_mem_region(0, s->map_size, s->map_size, 0, - "card services", s); - if (mem->res == NULL) { - printk(KERN_NOTICE "cs: unable to map card memory!\n"); - return NULL; + pccard_mem_map *mem = &s->cis_mem; + int ret; + + if (!(s->features & SS_CAP_STATIC_MAP) && (mem->res == NULL)) { + mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 0, s); + if (mem->res == NULL) { + printk(KERN_NOTICE "cs: unable to map card memory!\n"); + return NULL; + } + s->cis_virt = NULL; } - s->cis_virt = ioremap(mem->res->start, s->map_size); - } - mem->card_start = card_offset; - mem->flags = flags; - s->ops->set_mem_map(s, mem); - if (s->features & SS_CAP_STATIC_MAP) { - if (s->cis_virt) - iounmap(s->cis_virt); - s->cis_virt = ioremap(mem->static_start, s->map_size); - } - return s->cis_virt; + + if (!(s->features & SS_CAP_STATIC_MAP) && (!s->cis_virt)) + s->cis_virt = ioremap(mem->res->start, s->map_size); + + mem->card_start = card_offset; + mem->flags = flags; + + ret = s->ops->set_mem_map(s, mem); + if (ret) { + iounmap(s->cis_virt); + s->cis_virt = NULL; + return NULL; + } + + if (s->features & SS_CAP_STATIC_MAP) { + if (s->cis_virt) + iounmap(s->cis_virt); + s->cis_virt = ioremap(mem->static_start, s->map_size); + } + + return s->cis_virt; } /*====================================================================== @@ -138,13 +132,13 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag #define IS_ATTR 1 #define IS_INDIRECT 8 -int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, +int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, u_int len, void *ptr) { void __iomem *sys, *end; unsigned char *buf = ptr; - cs_dbg(s, 3, "read_cis_mem(%d, %#x, %u)\n", attr, addr, len); + cs_dbg(s, 3, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len); if (attr & IS_INDIRECT) { /* Indirect accesses use a bunch of special registers at fixed @@ -201,14 +195,16 @@ int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, *(u_char *)(ptr+2), *(u_char *)(ptr+3)); return 0; } +EXPORT_SYMBOL(pcmcia_read_cis_mem); -void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, + +void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, u_int len, void *ptr) { void __iomem *sys, *end; unsigned char *buf = ptr; - cs_dbg(s, 3, "write_cis_mem(%d, %#x, %u)\n", attr, addr, len); + cs_dbg(s, 3, "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len); if (attr & IS_INDIRECT) { /* Indirect accesses use a bunch of special registers at fixed @@ -258,6 +254,8 @@ void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, } } } +EXPORT_SYMBOL(pcmcia_write_cis_mem); + /*====================================================================== @@ -293,7 +291,7 @@ static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, ret = read_cb_mem(s, attr, addr, len, ptr); else #endif - ret = read_cis_mem(s, attr, addr, len, ptr); + ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr); if (ret == 0) { /* Copy data into the cache */ @@ -331,7 +329,14 @@ void destroy_cis_cache(struct pcmcia_socket *s) list_del(&cis->node); kfree(cis); } + + /* + * If there was a fake CIS, destroy that as well. + */ + kfree(s->fake_cis); + s->fake_cis = NULL; } +EXPORT_SYMBOL(destroy_cis_cache); /*====================================================================== @@ -358,7 +363,7 @@ int verify_cis_cache(struct pcmcia_socket *s) read_cb_mem(s, cis->attr, cis->addr, len, buf); else #endif - read_cis_mem(s, cis->attr, cis->addr, len, buf); + pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf); if (memcmp(buf, cis->cache, len) != 0) { kfree(buf); @@ -376,16 +381,10 @@ int verify_cis_cache(struct pcmcia_socket *s) ======================================================================*/ -int pcmcia_replace_cis(client_handle_t handle, cisdump_t *cis) +int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis) { - struct pcmcia_socket *s; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); - if (s->fake_cis != NULL) { - kfree(s->fake_cis); - s->fake_cis = NULL; - } + kfree(s->fake_cis); + s->fake_cis = NULL; if (cis->Length > CISTPL_MAX_CIS_SIZE) return CS_BAD_SIZE; s->fake_cis = kmalloc(cis->Length, GFP_KERNEL); @@ -395,6 +394,7 @@ int pcmcia_replace_cis(client_handle_t handle, cisdump_t *cis) memcpy(s->fake_cis, cis->Data, cis->Length); return CS_SUCCESS; } +EXPORT_SYMBOL(pcmcia_replace_cis); /*====================================================================== @@ -414,14 +414,12 @@ typedef struct tuple_flags { #define MFC_FN(f) (((tuple_flags *)(&(f)))->mfc_fn) #define SPACE(f) (((tuple_flags *)(&(f)))->space) -int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple); +int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int func, tuple_t *tuple); -int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple) +int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple_t *tuple) { - struct pcmcia_socket *s; - if (CHECK_HANDLE(handle)) + if (!s) return CS_BAD_HANDLE; - s = SOCKET(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; tuple->TupleLink = tuple->Flags = 0; @@ -443,16 +441,17 @@ int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple) !(tuple->Attributes & TUPLE_RETURN_COMMON)) { cisdata_t req = tuple->DesiredTuple; tuple->DesiredTuple = CISTPL_LONGLINK_MFC; - if (pcmcia_get_next_tuple(handle, tuple) == CS_SUCCESS) { + if (pccard_get_next_tuple(s, function, tuple) == CS_SUCCESS) { tuple->DesiredTuple = CISTPL_LINKTARGET; - if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS) + if (pccard_get_next_tuple(s, function, tuple) != CS_SUCCESS) return CS_NO_MORE_ITEMS; } else tuple->CISOffset = tuple->TupleLink = 0; tuple->DesiredTuple = req; } - return pcmcia_get_next_tuple(handle, tuple); + return pccard_get_next_tuple(s, function, tuple); } +EXPORT_SYMBOL(pccard_get_first_tuple); static int follow_link(struct pcmcia_socket *s, tuple_t *tuple) { @@ -463,7 +462,7 @@ static int follow_link(struct pcmcia_socket *s, tuple_t *tuple) /* Get indirect link from the MFC tuple */ read_cis_cache(s, LINK_SPACE(tuple->Flags), tuple->LinkOffset, 5, link); - ofs = le32_to_cpu(*(u_int *)(link+1)); + ofs = le32_to_cpu(*(__le32 *)(link+1)); SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR); /* Move to the next indirect link */ tuple->LinkOffset += 5; @@ -494,15 +493,13 @@ static int follow_link(struct pcmcia_socket *s, tuple_t *tuple) return -1; } -int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple) +int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_t *tuple) { - struct pcmcia_socket *s; u_char link[2], tmp; int ofs, i, attr; - - if (CHECK_HANDLE(handle)) + + if (!s) return CS_BAD_HANDLE; - s = SOCKET(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; @@ -554,14 +551,14 @@ int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple) case CISTPL_LONGLINK_MFC: tuple->LinkOffset = ofs + 3; LINK_SPACE(tuple->Flags) = attr; - if (handle->Function == BIND_FN_ALL) { + if (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; + tuple->LinkOffset += function * 5; } break; case CISTPL_NO_LINK: @@ -589,20 +586,18 @@ int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple) tuple->CISOffset = ofs + 2; return CS_SUCCESS; } +EXPORT_SYMBOL(pccard_get_next_tuple); /*====================================================================*/ #define _MIN(a, b) (((a) < (b)) ? (a) : (b)) -int pcmcia_get_tuple_data(client_handle_t handle, tuple_t *tuple) +int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple) { - struct pcmcia_socket *s; u_int len; - - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); + if (!s) + return CS_BAD_HANDLE; if (tuple->TupleLink < tuple->TupleOffset) return CS_NO_MORE_ITEMS; @@ -615,6 +610,8 @@ int pcmcia_get_tuple_data(client_handle_t handle, tuple_t *tuple) _MIN(len, tuple->TupleDataMax), tuple->TupleData); return CS_SUCCESS; } +EXPORT_SYMBOL(pccard_get_tuple_data); + /*====================================================================== @@ -673,8 +670,8 @@ static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum) 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->addr = tuple->CISOffset+(short)le16_to_cpu(*(__le16 *)p)-2; + csum->len = le16_to_cpu(*(__le16 *)(p + 2)); csum->sum = *(p+4); return CS_SUCCESS; } @@ -685,7 +682,7 @@ 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); + link->addr = le32_to_cpu(*(__le32 *)tuple->TupleData); return CS_SUCCESS; } @@ -704,7 +701,7 @@ static int parse_longlink_mfc(tuple_t *tuple, 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; + link->fn[i].addr = le32_to_cpu(*(__le32 *)p); p += 4; } return CS_SUCCESS; } @@ -791,10 +788,10 @@ static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec) static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m) { - u_short *p; + __le16 *p; if (tuple->TupleDataLen < 4) return CS_BAD_TUPLE; - p = (u_short *)tuple->TupleData; + p = (__le16 *)tuple->TupleData; m->manf = le16_to_cpu(p[0]); m->card = le16_to_cpu(p[1]); return CS_SUCCESS; @@ -1095,7 +1092,7 @@ static int parse_cftable_entry(tuple_t *tuple, break; case 0x20: entry->mem.nwin = 1; - entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8; + entry->mem.win[0].len = le16_to_cpu(*(__le16 *)p) << 8; entry->mem.win[0].card_addr = 0; entry->mem.win[0].host_addr = 0; p += 2; @@ -1103,9 +1100,9 @@ static int parse_cftable_entry(tuple_t *tuple, break; case 0x40: entry->mem.nwin = 1; - entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8; + entry->mem.win[0].len = le16_to_cpu(*(__le16 *)p) << 8; entry->mem.win[0].card_addr = - le16_to_cpu(*(u_short *)(p+2)) << 8; + le16_to_cpu(*(__le16 *)(p+2)) << 8; entry->mem.win[0].host_addr = 0; p += 4; if (p > q) return CS_BAD_TUPLE; @@ -1142,7 +1139,7 @@ static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar) p = (u_char *)tuple->TupleData; bar->attr = *p; p += 2; - bar->size = le32_to_cpu(*(u_int *)p); + bar->size = le32_to_cpu(*(__le32 *)p); return CS_SUCCESS; } @@ -1155,7 +1152,7 @@ static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config) return CS_BAD_TUPLE; config->last_idx = *(++p); p++; - config->base = le32_to_cpu(*(u_int *)p); + config->base = le32_to_cpu(*(__le32 *)p); config->subtuples = tuple->TupleDataLen - 6; return CS_SUCCESS; } @@ -1271,7 +1268,7 @@ static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2) v2->vers = p[0]; v2->comply = p[1]; - v2->dindex = le16_to_cpu(*(u_short *)(p+2)); + v2->dindex = le16_to_cpu(*(__le16 *)(p+2)); v2->vspec8 = p[6]; v2->vspec9 = p[7]; v2->nhdr = p[8]; @@ -1312,15 +1309,15 @@ static int parse_format(tuple_t *tuple, cistpl_format_t *fmt) 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)); + fmt->offset = le32_to_cpu(*(__le32 *)(p+2)); + fmt->length = le32_to_cpu(*(__le32 *)(p+6)); return CS_SUCCESS; } /*====================================================================*/ -int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +int pccard_parse_tuple(tuple_t *tuple, cisparse_t *parse) { int ret = CS_SUCCESS; @@ -1401,6 +1398,7 @@ int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse } return ret; } +EXPORT_SYMBOL(pccard_parse_tuple); /*====================================================================== @@ -1408,7 +1406,7 @@ int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse ======================================================================*/ -int read_tuple(client_handle_t handle, cisdata_t code, void *parse) +int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse) { tuple_t tuple; cisdata_t *buf; @@ -1419,18 +1417,19 @@ int read_tuple(client_handle_t handle, cisdata_t code, void *parse) return CS_OUT_OF_RESOURCE; tuple.DesiredTuple = code; tuple.Attributes = TUPLE_RETURN_COMMON; - ret = pcmcia_get_first_tuple(handle, &tuple); + ret = pccard_get_first_tuple(s, function, &tuple); if (ret != CS_SUCCESS) goto done; tuple.TupleData = buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; - ret = pcmcia_get_tuple_data(handle, &tuple); + ret = pccard_get_tuple_data(s, &tuple); if (ret != CS_SUCCESS) goto done; - ret = pcmcia_parse_tuple(handle, &tuple, parse); + ret = pccard_parse_tuple(&tuple, parse); done: kfree(buf); return ret; } +EXPORT_SYMBOL(pccard_read_tuple); /*====================================================================== @@ -1442,14 +1441,15 @@ done: ======================================================================*/ -int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info) +int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, cisinfo_t *info) { tuple_t *tuple; cisparse_t *p; int ret, reserved, dev_ok = 0, ident_ok = 0; - if (CHECK_HANDLE(handle)) + if (!s) return CS_BAD_HANDLE; + tuple = kmalloc(sizeof(*tuple), GFP_KERNEL); if (tuple == NULL) return CS_OUT_OF_RESOURCE; @@ -1462,30 +1462,30 @@ int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info) info->Chains = reserved = 0; tuple->DesiredTuple = RETURN_FIRST_TUPLE; tuple->Attributes = TUPLE_RETURN_COMMON; - ret = pcmcia_get_first_tuple(handle, tuple); + ret = pccard_get_first_tuple(s, function, tuple); if (ret != CS_SUCCESS) goto done; /* 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)) + (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY, p) == CS_SUCCESS) || + (pccard_read_tuple(s, function, 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)) + if ((pccard_read_tuple(s, function, CISTPL_MANFID, p) == CS_SUCCESS) || + (pccard_read_tuple(s, function, CISTPL_VERS_1, p) == CS_SUCCESS) || + (pccard_read_tuple(s, function, CISTPL_VERS_2, p) != CS_NO_MORE_ITEMS)) ident_ok++; if (!dev_ok && !ident_ok) goto done; for (info->Chains = 1; info->Chains < MAX_TUPLES; info->Chains++) { - ret = pcmcia_get_next_tuple(handle, tuple); + ret = pccard_get_next_tuple(s, function, tuple); if (ret != CS_SUCCESS) break; if (((tuple->TupleCode > 0x23) && (tuple->TupleCode < 0x40)) || ((tuple->TupleCode > 0x47) && (tuple->TupleCode < 0x80)) || @@ -1501,4 +1501,4 @@ done: kfree(p); return CS_SUCCESS; } - +EXPORT_SYMBOL(pccard_validate_cis);