patch-2.4.0-test8 linux/drivers/pcmcia/cistpl.c
Next file: linux/drivers/pcmcia/cs.c
Previous file: linux/drivers/pcmcia/cb_enabler.c
Back to the patch index
Back to the overall index
- Lines: 264
- Date:
Sat Sep 2 00:13:49 2000
- Orig file:
v2.4.0-test7/linux/drivers/pcmcia/cistpl.c
- Orig date:
Fri Jan 21 18:19:16 2000
diff -u --recursive --new-file v2.4.0-test7/linux/drivers/pcmcia/cistpl.c linux/drivers/pcmcia/cistpl.c
@@ -2,7 +2,7 @@
PCMCIA Card Information Structure parser
- cistpl.c 1.77 2000/01/16 19:19:01
+ cistpl.c 1.90 2000/08/30 20:23:47
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
@@ -15,7 +15,7 @@
rights and limitations under the License.
The initial developer of the original code is David A. Hinds
- <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ <dahinds@users.sourceforge.net>. 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
@@ -77,6 +77,14 @@
/* Upper limit on reasonable # of tuples */
#define MAX_TUPLES 200
+/*====================================================================*/
+
+/* Parameters that can be set with 'insmod' */
+
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
+
+INT_MODULE_PARM(cis_width, 0); /* 16-bit CIS? */
+
/*======================================================================
Low-level functions to read and write CIS memory. I think the
@@ -88,6 +96,17 @@
#define IS_ATTR 1
#define IS_INDIRECT 8
+static void set_cis_map(socket_info_t *s, pccard_mem_map *mem)
+{
+ s->ss_entry->set_mem_map(s->sock, mem);
+ if (s->cap.features & SS_CAP_STATIC_MAP) {
+ if (s->cis_virt)
+ bus_iounmap(s->cap.bus, s->cis_virt);
+ s->cis_virt = bus_ioremap(s->cap.bus, mem->sys_start,
+ s->cap.map_size);
+ }
+}
+
void read_cis_mem(socket_info_t *s, int attr, u_int addr,
u_int len, void *ptr)
{
@@ -99,16 +118,17 @@
memset(ptr, 0xff, len);
return;
}
- mem->flags |= MAP_ACTIVE; mem->flags &= ~MAP_ATTRIB;
- sys = s->cis_virt;
+ mem->flags = MAP_ACTIVE;
+ if (cis_width) mem->flags |= MAP_16BIT;
if (attr & IS_INDIRECT) {
/* Indirect accesses use a bunch of special registers at fixed
locations in common memory */
u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; }
- mem->card_start = 0;
- s->ss_entry->set_mem_map(s->sock, mem);
+ mem->card_start = 0; mem->flags = MAP_ACTIVE;
+ set_cis_map(s, mem);
+ sys = s->cis_virt;
bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0);
bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0);
bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1);
@@ -121,14 +141,15 @@
if (attr) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
sys += (addr & (s->cap.map_size-1));
mem->card_start = addr & ~(s->cap.map_size-1);
-
- for (; len > 0; sys = s->cis_virt) {
- s->ss_entry->set_mem_map(s->sock, mem);
+ while (len) {
+ set_cis_map(s, mem);
+ sys = s->cis_virt + (addr & (s->cap.map_size-1));
for ( ; len > 0; len--, buf++, sys += inc) {
if (sys == s->cis_virt+s->cap.map_size) break;
*buf = bus_readb(s->cap.bus, sys);
}
mem->card_start += s->cap.map_size;
+ addr = 0;
}
}
DEBUG(3, "cs: %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
@@ -144,16 +165,17 @@
DEBUG(3, "cs: write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
if (setup_cis_mem(s) != 0) return;
- mem->flags |= MAP_ACTIVE; mem->flags &= ~MAP_ATTRIB;
- sys = s->cis_virt;
+ mem->flags = MAP_ACTIVE;
+ if (cis_width) mem->flags |= MAP_16BIT;
if (attr & IS_INDIRECT) {
/* Indirect accesses use a bunch of special registers at fixed
locations in common memory */
u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; }
- mem->card_start = 0;
- s->ss_entry->set_mem_map(s->sock, mem);
+ mem->card_start = 0; mem->flags = MAP_ACTIVE;
+ set_cis_map(s, mem);
+ sys = s->cis_virt;
bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0);
bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0);
bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1);
@@ -164,16 +186,16 @@
} else {
int inc = 1;
if (attr & IS_ATTR) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
- sys += (addr & (s->cap.map_size-1));
mem->card_start = addr & ~(s->cap.map_size-1);
-
- for (; len > 0; sys = s->cis_virt) {
- s->ss_entry->set_mem_map(s->sock, mem);
+ while (len) {
+ set_cis_map(s, mem);
+ sys = s->cis_virt + (addr & (s->cap.map_size-1));
for ( ; len > 0; len--, buf++, sys += inc) {
if (sys == s->cis_virt+s->cap.map_size) break;
bus_writeb(s->cap.bus, *buf, sys);
}
mem->card_start += s->cap.map_size;
+ addr = 0;
}
}
}
@@ -238,7 +260,8 @@
int setup_cis_mem(socket_info_t *s)
{
- if (s->cis_mem.sys_start == 0) {
+ if (!(s->cap.features & SS_CAP_STATIC_MAP) &&
+ (s->cis_mem.sys_start == 0)) {
int low = !(s->cap.features & SS_CAP_PAGE_REGS);
vs = s;
validate_mem(cis_readable, checksum_match, low);
@@ -262,9 +285,11 @@
if (s->cis_mem.sys_start != 0) {
s->cis_mem.flags &= ~MAP_ACTIVE;
s->ss_entry->set_mem_map(s->sock, &s->cis_mem);
- release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
+ if (!(s->cap.features & SS_CAP_STATIC_MAP))
+ release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
bus_iounmap(s->cap.bus, s->cis_virt);
s->cis_mem.sys_start = 0;
+ s->cis_virt = NULL;
}
}
@@ -1278,6 +1303,25 @@
/*====================================================================*/
+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 pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
{
int ret = CS_SUCCESS;
@@ -1345,6 +1389,10 @@
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;
@@ -1395,34 +1443,36 @@
{
tuple_t tuple;
cisparse_t p;
- int ret, reserved, errors;
-
+ int ret, reserved, dev_ok = 0, ident_ok = 0;
+
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
-
- info->Chains = reserved = errors = 0;
+
+ info->Chains = reserved = 0;
tuple.DesiredTuple = RETURN_FIRST_TUPLE;
tuple.Attributes = TUPLE_RETURN_COMMON;
ret = pcmcia_get_first_tuple(handle, &tuple);
if (ret != CS_SUCCESS)
return CS_SUCCESS;
- /* First tuple should be DEVICE */
- if (tuple.TupleCode != CISTPL_DEVICE)
- errors++;
- /* All cards should have a MANFID tuple */
- if (read_tuple(handle, CISTPL_MANFID, &p) != CS_SUCCESS)
- errors++;
- /* All cards should have either a VERS_1 or a VERS_2 tuple. But
- at worst, we'll accept a CFTABLE_ENTRY that parses. */
- if ((read_tuple(handle, CISTPL_VERS_1, &p) != CS_SUCCESS) &&
- (read_tuple(handle, CISTPL_VERS_2, &p) != CS_SUCCESS) &&
- (read_tuple(handle, CISTPL_CFTABLE_ENTRY, &p) != CS_SUCCESS) &&
- (read_tuple(handle, CISTPL_CFTABLE_ENTRY_CB, &p) != CS_SUCCESS))
- errors++;
- if (errors > 1)
+ /* 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 = pcmcia_get_next_tuple(handle, &tuple);
if (ret != CS_SUCCESS) break;
@@ -1431,9 +1481,10 @@
((tuple.TupleCode > 0x90) && (tuple.TupleCode < 0xff)))
reserved++;
}
- if ((info->Chains == MAX_TUPLES) || (reserved > 5))
+ if ((info->Chains == MAX_TUPLES) || (reserved > 5) ||
+ ((!dev_ok || !ident_ok) && (info->Chains > 10)))
info->Chains = 0;
-
+
return CS_SUCCESS;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)