summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-03-04 18:51:36 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-04 18:51:36 +0300
commita2e28fc1164e56d37a56e3c53bd3e5a64462fd02 (patch)
tree144dfddbd6d619db549bf43e43ddc116f29e9774
parent03a2c4d76c9e99b80d74ab8a4f344e135a5ae44b (diff)
parenta3f916f2c84f2b9e1d32cc0dbfe326a9e380dbfb (diff)
downloadlinux-a2e28fc1164e56d37a56e3c53bd3e5a64462fd02.tar.xz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6: pcmcia: disable pcmcia ioctl for !ARM, prepare for removal pcmcia: CodingStyle fixes pcmcia: alchemy: fixup wrong comments pcmcia: remove irq_list parameter from pd6729 yenta_socket: ENE CB712 CardBus bridge needs special treatment with Echo Audio Indigo soundcards
-rw-r--r--Documentation/feature-removal-schedule.txt12
-rw-r--r--drivers/pcmcia/Kconfig14
-rw-r--r--drivers/pcmcia/cardbus.c2
-rw-r--r--drivers/pcmcia/cistpl.c1908
-rw-r--r--drivers/pcmcia/db1xxx_ss.c19
-rw-r--r--drivers/pcmcia/pd6729.c18
-rw-r--r--drivers/pcmcia/rsrc_mgr.c3
-rw-r--r--drivers/pcmcia/xxs1500_ss.c16
-rw-r--r--drivers/pcmcia/yenta_socket.c8
9 files changed, 973 insertions, 1027 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 73ef30dbe612..03497909539e 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -117,19 +117,25 @@ Who: Mauro Carvalho Chehab <mchehab@infradead.org>
---------------------------
What: PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl])
-When: November 2005
+When: 2.6.35/2.6.36
Files: drivers/pcmcia/: pcmcia_ioctl.c
Why: With the 16-bit PCMCIA subsystem now behaving (almost) like a
normal hotpluggable bus, and with it using the default kernel
infrastructure (hotplug, driver core, sysfs) keeping the PCMCIA
control ioctl needed by cardmgr and cardctl from pcmcia-cs is
- unnecessary, and makes further cleanups and integration of the
+ unnecessary and potentially harmful (it does not provide for
+ proper locking), and makes further cleanups and integration of the
PCMCIA subsystem into the Linux kernel device driver model more
difficult. The features provided by cardmgr and cardctl are either
handled by the kernel itself now or are available in the new
pcmciautils package available at
http://kernel.org/pub/linux/utils/kernel/pcmcia/
-Who: Dominik Brodowski <linux@brodo.de>
+
+ For all architectures except ARM, the associated config symbol
+ has been removed from kernel 2.6.34; for ARM, it will be likely
+ be removed from kernel 2.6.35. The actual code will then likely
+ be removed from kernel 2.6.36.
+Who: Dominik Brodowski <linux@dominikbrodowski.net>
---------------------------
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 0a6601c76809..d189e4743e69 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -51,17 +51,23 @@ config PCMCIA_LOAD_CIS
config PCMCIA_IOCTL
bool "PCMCIA control ioctl (obsolete)"
- depends on PCMCIA
+ depends on PCMCIA && ARM && !SMP && !PREEMPT
default y
help
If you say Y here, the deprecated ioctl interface to the PCMCIA
- subsystem will be built. It is needed by cardmgr and cardctl
- (pcmcia-cs) to function properly.
+ subsystem will be built. It is needed by the deprecated pcmcia-cs
+ tools (cardmgr, cardctl) to function properly.
You should use the new pcmciautils package instead (see
<file:Documentation/Changes> for location and details).
- If unsure, say Y.
+ This config option will most likely be removed from kernel 2.6.35,
+ the associated code from kernel 2.6.36.
+
+ As the PCMCIA ioctl is not locking safe, it depends on !SMP and
+ !PREEMPT.
+
+ If unsure, say N.
config CARDBUS
bool "32-bit CardBus support"
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index ac0686efbf75..e6ab2a47d8cb 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -71,7 +71,7 @@ int __ref cb_alloc(struct pcmcia_socket *s)
unsigned int max, pass;
s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
- pci_fixup_cardbus(bus);
+ pci_fixup_cardbus(bus);
max = bus->secondary;
for (pass = 0; pass < 2; pass++)
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 2f3622dd4b69..f230f6543bff 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -54,46 +54,44 @@ static const u_int exponent[] = {
/* Upper limit on reasonable # of tuples */
#define MAX_TUPLES 200
-/*====================================================================*/
-
-/* Parameters that can be set with 'insmod' */
-
/* 16-bit CIS? */
static int cis_width;
module_param(cis_width, int, 0444);
void release_cis_mem(struct pcmcia_socket *s)
{
- mutex_lock(&s->ops_mutex);
- if (s->cis_mem.flags & MAP_ACTIVE) {
- s->cis_mem.flags &= ~MAP_ACTIVE;
- s->ops->set_mem_map(s, &s->cis_mem);
- if (s->cis_mem.res) {
- release_resource(s->cis_mem.res);
- kfree(s->cis_mem.res);
- s->cis_mem.res = NULL;
+ mutex_lock(&s->ops_mutex);
+ if (s->cis_mem.flags & MAP_ACTIVE) {
+ s->cis_mem.flags &= ~MAP_ACTIVE;
+ s->ops->set_mem_map(s, &s->cis_mem);
+ if (s->cis_mem.res) {
+ release_resource(s->cis_mem.res);
+ kfree(s->cis_mem.res);
+ s->cis_mem.res = NULL;
+ }
+ iounmap(s->cis_virt);
+ s->cis_virt = NULL;
}
- iounmap(s->cis_virt);
- s->cis_virt = NULL;
- }
- mutex_unlock(&s->ops_mutex);
+ mutex_unlock(&s->ops_mutex);
}
-/*
- * Map the card memory at "card_offset" into virtual space.
+/**
+ * set_cis_map() - map the card memory at "card_offset" into virtual space.
+ *
* If flags & MAP_ATTRIB, map the attribute space, otherwise
* map the memory space.
*
* Must be called with ops_mutex held.
*/
-static void __iomem *
-set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags)
+static void __iomem *set_cis_map(struct pcmcia_socket *s,
+ unsigned int card_offset, unsigned int flags)
{
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);
+ mem->res = pcmcia_find_mem_region(0, s->map_size,
+ s->map_size, 0, s);
if (mem->res == NULL) {
dev_printk(KERN_NOTICE, &s->dev,
"cs: unable to map card memory!\n");
@@ -124,165 +122,170 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
return s->cis_virt;
}
-/*======================================================================
-
- Low-level functions to read and write CIS memory. I think the
- write routine is only useful for writing one-byte registers.
-
-======================================================================*/
/* Bits in attr field */
#define IS_ATTR 1
#define IS_INDIRECT 8
+/**
+ * pcmcia_read_cis_mem() - low-level function to read CIS memory
+ */
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;
-
- dev_dbg(&s->dev, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
-
- mutex_lock(&s->ops_mutex);
- 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;
- }
+ void __iomem *sys, *end;
+ unsigned char *buf = ptr;
- sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0));
- if (!sys) {
- dev_dbg(&s->dev, "could not map memory\n");
- memset(ptr, 0xff, len);
- mutex_unlock(&s->ops_mutex);
- return -1;
- }
+ dev_dbg(&s->dev, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
- writeb(flags, sys+CISREG_ICTRL0);
- writeb(addr & 0xff, sys+CISREG_IADDR0);
- writeb((addr>>8) & 0xff, sys+CISREG_IADDR1);
- writeb((addr>>16) & 0xff, sys+CISREG_IADDR2);
- writeb((addr>>24) & 0xff, sys+CISREG_IADDR3);
- for ( ; len > 0; len--, buf++)
- *buf = readb(sys+CISREG_IDATA0);
- } else {
- u_int inc = 1, card_offset, flags;
-
- if (addr > CISTPL_MAX_CIS_SIZE)
- dev_dbg(&s->dev, "attempt to read CIS mem at addr %#x", addr);
-
- flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
- if (attr) {
- flags |= MAP_ATTRIB;
- inc++;
- addr *= 2;
- }
+ mutex_lock(&s->ops_mutex);
+ 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;
+ }
- card_offset = addr & ~(s->map_size-1);
- while (len) {
- sys = set_cis_map(s, card_offset, flags);
- if (!sys) {
- dev_dbg(&s->dev, "could not map memory\n");
- memset(ptr, 0xff, len);
- mutex_unlock(&s->ops_mutex);
- return -1;
- }
- end = sys + s->map_size;
- sys = sys + (addr & (s->map_size-1));
- for ( ; len > 0; len--, buf++, sys += inc) {
- if (sys == end)
- break;
- *buf = readb(sys);
- }
- card_offset += s->map_size;
- addr = 0;
+ sys = set_cis_map(s, 0, MAP_ACTIVE |
+ ((cis_width) ? MAP_16BIT : 0));
+ if (!sys) {
+ dev_dbg(&s->dev, "could not map memory\n");
+ memset(ptr, 0xff, len);
+ mutex_unlock(&s->ops_mutex);
+ return -1;
+ }
+
+ writeb(flags, sys+CISREG_ICTRL0);
+ writeb(addr & 0xff, sys+CISREG_IADDR0);
+ writeb((addr>>8) & 0xff, sys+CISREG_IADDR1);
+ writeb((addr>>16) & 0xff, sys+CISREG_IADDR2);
+ writeb((addr>>24) & 0xff, sys+CISREG_IADDR3);
+ for ( ; len > 0; len--, buf++)
+ *buf = readb(sys+CISREG_IDATA0);
+ } else {
+ u_int inc = 1, card_offset, flags;
+
+ if (addr > CISTPL_MAX_CIS_SIZE)
+ dev_dbg(&s->dev,
+ "attempt to read CIS mem at addr %#x", addr);
+
+ flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
+ if (attr) {
+ flags |= MAP_ATTRIB;
+ inc++;
+ addr *= 2;
+ }
+
+ card_offset = addr & ~(s->map_size-1);
+ while (len) {
+ sys = set_cis_map(s, card_offset, flags);
+ if (!sys) {
+ dev_dbg(&s->dev, "could not map memory\n");
+ memset(ptr, 0xff, len);
+ mutex_unlock(&s->ops_mutex);
+ return -1;
+ }
+ end = sys + s->map_size;
+ sys = sys + (addr & (s->map_size-1));
+ for ( ; len > 0; len--, buf++, sys += inc) {
+ if (sys == end)
+ break;
+ *buf = readb(sys);
+ }
+ card_offset += s->map_size;
+ addr = 0;
+ }
}
- }
- mutex_unlock(&s->ops_mutex);
- dev_dbg(&s->dev, " %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
- *(u_char *)(ptr+0), *(u_char *)(ptr+1),
- *(u_char *)(ptr+2), *(u_char *)(ptr+3));
- return 0;
+ mutex_unlock(&s->ops_mutex);
+ dev_dbg(&s->dev, " %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
+ *(u_char *)(ptr+0), *(u_char *)(ptr+1),
+ *(u_char *)(ptr+2), *(u_char *)(ptr+3));
+ return 0;
}
+/**
+ * pcmcia_write_cis_mem() - low-level function to write CIS memory
+ *
+ * Probably only useful for writing one-byte registers.
+ */
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;
-
- dev_dbg(&s->dev, "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
-
- mutex_lock(&s->ops_mutex);
- 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;
- }
+ void __iomem *sys, *end;
+ unsigned char *buf = ptr;
- sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0));
- if (!sys) {
- dev_dbg(&s->dev, "could not map memory\n");
- mutex_unlock(&s->ops_mutex);
- return; /* FIXME: Error */
- }
+ dev_dbg(&s->dev,
+ "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
- writeb(flags, sys+CISREG_ICTRL0);
- writeb(addr & 0xff, sys+CISREG_IADDR0);
- writeb((addr>>8) & 0xff, sys+CISREG_IADDR1);
- writeb((addr>>16) & 0xff, sys+CISREG_IADDR2);
- writeb((addr>>24) & 0xff, sys+CISREG_IADDR3);
- for ( ; len > 0; len--, buf++)
- writeb(*buf, sys+CISREG_IDATA0);
- } else {
- u_int inc = 1, card_offset, flags;
-
- flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
- if (attr & IS_ATTR) {
- flags |= MAP_ATTRIB;
- inc++;
- addr *= 2;
- }
+ mutex_lock(&s->ops_mutex);
+ 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;
+ }
- card_offset = addr & ~(s->map_size-1);
- while (len) {
- sys = set_cis_map(s, card_offset, flags);
- if (!sys) {
- dev_dbg(&s->dev, "could not map memory\n");
- mutex_unlock(&s->ops_mutex);
- return; /* FIXME: error */
- }
-
- end = sys + s->map_size;
- sys = sys + (addr & (s->map_size-1));
- for ( ; len > 0; len--, buf++, sys += inc) {
- if (sys == end)
- break;
- writeb(*buf, sys);
- }
- card_offset += s->map_size;
- addr = 0;
- }
- }
- mutex_unlock(&s->ops_mutex);
-}
+ sys = set_cis_map(s, 0, MAP_ACTIVE |
+ ((cis_width) ? MAP_16BIT : 0));
+ if (!sys) {
+ dev_dbg(&s->dev, "could not map memory\n");
+ mutex_unlock(&s->ops_mutex);
+ return; /* FIXME: Error */
+ }
+
+ writeb(flags, sys+CISREG_ICTRL0);
+ writeb(addr & 0xff, sys+CISREG_IADDR0);
+ writeb((addr>>8) & 0xff, sys+CISREG_IADDR1);
+ writeb((addr>>16) & 0xff, sys+CISREG_IADDR2);
+ writeb((addr>>24) & 0xff, sys+CISREG_IADDR3);
+ for ( ; len > 0; len--, buf++)
+ writeb(*buf, sys+CISREG_IDATA0);
+ } else {
+ u_int inc = 1, card_offset, flags;
+ flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
+ if (attr & IS_ATTR) {
+ flags |= MAP_ATTRIB;
+ inc++;
+ addr *= 2;
+ }
-/*======================================================================
+ card_offset = addr & ~(s->map_size-1);
+ while (len) {
+ sys = set_cis_map(s, card_offset, flags);
+ if (!sys) {
+ dev_dbg(&s->dev, "could not map memory\n");
+ mutex_unlock(&s->ops_mutex);
+ return; /* FIXME: error */
+ }
- This is a wrapper around read_cis_mem, with the same interface,
- but which caches information, for cards whose CIS may not be
- readable all the time.
+ end = sys + s->map_size;
+ sys = sys + (addr & (s->map_size-1));
+ for ( ; len > 0; len--, buf++, sys += inc) {
+ if (sys == end)
+ break;
+ writeb(*buf, sys);
+ }
+ card_offset += s->map_size;
+ addr = 0;
+ }
+ }
+ mutex_unlock(&s->ops_mutex);
+}
-======================================================================*/
+/**
+ * read_cis_cache() - read CIS memory or its associated cache
+ *
+ * This is a wrapper around read_cis_mem, with the same interface,
+ * but which caches information, for cards whose CIS may not be
+ * readable all the time.
+ */
static int read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
size_t len, void *ptr)
{
@@ -353,7 +356,6 @@ remove_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, u_int len)
* This destroys the CIS cache but keeps any fake CIS alive. Must be
* called with ops_mutex held.
*/
-
void destroy_cis_cache(struct pcmcia_socket *s)
{
struct list_head *l, *n;
@@ -366,13 +368,9 @@ void destroy_cis_cache(struct pcmcia_socket *s)
}
}
-/*======================================================================
-
- This verifies if the CIS of a card matches what is in the CIS
- cache.
-
-======================================================================*/
-
+/**
+ * verify_cis_cache() - does the CIS match what is in the CIS cache?
+ */
int verify_cis_cache(struct pcmcia_socket *s)
{
struct cis_cache_entry *cis;
@@ -404,13 +402,12 @@ int verify_cis_cache(struct pcmcia_socket *s)
return 0;
}
-/*======================================================================
-
- For really bad cards, we provide a facility for uploading a
- replacement CIS.
-
-======================================================================*/
-
+/**
+ * pcmcia_replace_cis() - use a replacement CIS instead of the card's CIS
+ *
+ * For really bad cards, we provide a facility for uploading a
+ * replacement CIS.
+ */
int pcmcia_replace_cis(struct pcmcia_socket *s,
const u8 *data, const size_t len)
{
@@ -433,17 +430,13 @@ int pcmcia_replace_cis(struct pcmcia_socket *s,
return 0;
}
-/*======================================================================
-
- The high-level CIS tuple services
-
-======================================================================*/
+/* The high-level CIS tuple services */
typedef struct tuple_flags {
- u_int link_space:4;
- u_int has_link:1;
- u_int mfc_fn:3;
- u_int space:4;
+ u_int link_space:4;
+ u_int has_link:1;
+ u_int mfc_fn:3;
+ u_int space:4;
} tuple_flags;
#define LINK_SPACE(f) (((tuple_flags *)(&(f)))->link_space)
@@ -451,982 +444,961 @@ typedef struct tuple_flags {
#define MFC_FN(f) (((tuple_flags *)(&(f)))->mfc_fn)
#define SPACE(f) (((tuple_flags *)(&(f)))->space)
-int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple_t *tuple)
+int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function,
+ tuple_t *tuple)
{
- if (!s)
- return -EINVAL;
-
- if (!(s->state & SOCKET_PRESENT) || (s->state & SOCKET_CARDBUS))
- return -ENODEV;
- tuple->TupleLink = tuple->Flags = 0;
-
- /* Assume presence of a LONGLINK_C to address 0 */
- tuple->CISOffset = tuple->LinkOffset = 0;
- SPACE(tuple->Flags) = HAS_LINK(tuple->Flags) = 1;
-
- if ((s->functions > 1) && !(tuple->Attributes & TUPLE_RETURN_COMMON)) {
- cisdata_t req = tuple->DesiredTuple;
- tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
- if (pccard_get_next_tuple(s, function, tuple) == 0) {
- tuple->DesiredTuple = CISTPL_LINKTARGET;
- if (pccard_get_next_tuple(s, function, tuple) != 0)
- return -ENOSPC;
- } else
- tuple->CISOffset = tuple->TupleLink = 0;
- tuple->DesiredTuple = req;
- }
- return pccard_get_next_tuple(s, function, tuple);
+ if (!s)
+ return -EINVAL;
+
+ if (!(s->state & SOCKET_PRESENT) || (s->state & SOCKET_CARDBUS))
+ return -ENODEV;
+ tuple->TupleLink = tuple->Flags = 0;
+
+ /* Assume presence of a LONGLINK_C to address 0 */
+ tuple->CISOffset = tuple->LinkOffset = 0;
+ SPACE(tuple->Flags) = HAS_LINK(tuple->Flags) = 1;
+
+ if ((s->functions > 1) && !(tuple->Attributes & TUPLE_RETURN_COMMON)) {
+ cisdata_t req = tuple->DesiredTuple;
+ tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
+ if (pccard_get_next_tuple(s, function, tuple) == 0) {
+ tuple->DesiredTuple = CISTPL_LINKTARGET;
+ if (pccard_get_next_tuple(s, function, tuple) != 0)
+ return -ENOSPC;
+ } else
+ tuple->CISOffset = tuple->TupleLink = 0;
+ tuple->DesiredTuple = req;
+ }
+ return pccard_get_next_tuple(s, function, tuple);
}
static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
{
- u_char link[5];
- u_int ofs;
- int ret;
-
- if (MFC_FN(tuple->Flags)) {
- /* Get indirect link from the MFC tuple */
- ret = read_cis_cache(s, LINK_SPACE(tuple->Flags),
- tuple->LinkOffset, 5, link);
- if (ret)
+ u_char link[5];
+ u_int ofs;
+ int ret;
+
+ if (MFC_FN(tuple->Flags)) {
+ /* Get indirect link from the MFC tuple */
+ ret = read_cis_cache(s, LINK_SPACE(tuple->Flags),
+ tuple->LinkOffset, 5, link);
+ if (ret)
+ return -1;
+ ofs = get_unaligned_le32(link + 1);
+ SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR);
+ /* Move to the next indirect link */
+ tuple->LinkOffset += 5;
+ MFC_FN(tuple->Flags)--;
+ } else if (HAS_LINK(tuple->Flags)) {
+ ofs = tuple->LinkOffset;
+ SPACE(tuple->Flags) = LINK_SPACE(tuple->Flags);
+ HAS_LINK(tuple->Flags) = 0;
+ } else
return -1;
- ofs = get_unaligned_le32(link + 1);
- SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR);
- /* Move to the next indirect link */
- tuple->LinkOffset += 5;
- MFC_FN(tuple->Flags)--;
- } else if (HAS_LINK(tuple->Flags)) {
- ofs = tuple->LinkOffset;
- SPACE(tuple->Flags) = LINK_SPACE(tuple->Flags);
- HAS_LINK(tuple->Flags) = 0;
- } else {
- return -1;
- }
- if (SPACE(tuple->Flags)) {
- /* This is ugly, but a common CIS error is to code the long
- link offset incorrectly, so we check the right spot... */
+
+ if (SPACE(tuple->Flags)) {
+ /* This is ugly, but a common CIS error is to code the long
+ link offset incorrectly, so we check the right spot... */
+ ret = read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
+ if (ret)
+ return -1;
+ if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
+ (strncmp(link+2, "CIS", 3) == 0))
+ return ofs;
+ remove_cis_cache(s, SPACE(tuple->Flags), ofs, 5);
+ /* Then, we try the wrong spot... */
+ ofs = ofs >> 1;
+ }
ret = read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
if (ret)
return -1;
if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
- (strncmp(link+2, "CIS", 3) == 0))
- return ofs;
+ (strncmp(link+2, "CIS", 3) == 0))
+ return ofs;
remove_cis_cache(s, SPACE(tuple->Flags), ofs, 5);
- /* Then, we try the wrong spot... */
- ofs = ofs >> 1;
- }
- ret = read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
- if (ret)
- return -1;
- if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
- (strncmp(link+2, "CIS", 3) == 0))
- return ofs;
- remove_cis_cache(s, SPACE(tuple->Flags), ofs, 5);
- return -1;
+ return -1;
}
-int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_t *tuple)
+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;
- }
- }
+ u_char link[2], tmp;
+ int ofs, i, attr;
+ int ret;
- /* 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;
- }
+ if (!s)
+ return -EINVAL;
+ if (!(s->state & SOCKET_PRESENT) || (s->state & SOCKET_CARDBUS))
+ return -ENODEV;
- /* 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;
+ 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;
+ }
}
- 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;
-}
+ /* 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;
+ }
-#define _MIN(a, b) (((a) < (b)) ? (a) : (b))
+ tuple->TupleCode = link[0];
+ tuple->TupleLink = link[1];
+ tuple->CISOffset = ofs + 2;
+ return 0;
+}
int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple)
{
- u_int len;
- int ret;
+ u_int len;
+ int ret;
- if (!s)
- return -EINVAL;
+ if (!s)
+ return -EINVAL;
- if (tuple->TupleLink < tuple->TupleOffset)
- return -ENOSPC;
- len = tuple->TupleLink - tuple->TupleOffset;
- tuple->TupleDataLen = tuple->TupleLink;
- if (len == 0)
+ if (tuple->TupleLink < tuple->TupleOffset)
+ return -ENOSPC;
+ len = tuple->TupleLink - tuple->TupleOffset;
+ tuple->TupleDataLen = tuple->TupleLink;
+ if (len == 0)
+ return 0;
+ ret = read_cis_cache(s, SPACE(tuple->Flags),
+ tuple->CISOffset + tuple->TupleOffset,
+ min(len, (u_int) tuple->TupleDataMax),
+ tuple->TupleData);
+ if (ret)
+ return -1;
return 0;
- ret = read_cis_cache(s, SPACE(tuple->Flags),
- tuple->CISOffset + tuple->TupleOffset,
- _MIN(len, tuple->TupleDataMax), tuple->TupleData);
- if (ret)
- return -1;
- return 0;
}
-/*======================================================================
-
- Parsing routines for individual tuples
-
-======================================================================*/
+/* 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;
+ int i;
+ u_char scale;
+ u_char *p, *q;
- p = (u_char *)tuple->TupleData;
- q = p + tuple->TupleDataLen;
+ p = (u_char *)tuple->TupleData;
+ q = p + tuple->TupleDataLen;
- device->ndev = 0;
- for (i = 0; i < CISTPL_MAX_DEVICES; i++) {
+ 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 -EINVAL;
- device->dev[i].speed = SPEED_CVT(*p);
- while (*p & 0x80)
+ 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 -EINVAL;
- break;
- default:
- return -EINVAL;
- }
+ device->dev[i].speed = SPEED_CVT(*p);
+ while (*p & 0x80)
+ if (++p == q)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
- if (++p == q)
- return -EINVAL;
- if (*p == 0xff)
- break;
- scale = *p & 7;
- if (scale == 7)
- return -EINVAL;
- device->dev[i].size = ((*p >> 3) + 1) * (512 << (scale*2));
- device->ndev++;
- if (++p == q)
- break;
- }
+ if (++p == q)
+ return -EINVAL;
+ if (*p == 0xff)
+ break;
+ scale = *p & 7;
+ if (scale == 7)
+ return -EINVAL;
+ device->dev[i].size = ((*p >> 3) + 1) * (512 << (scale*2));
+ device->ndev++;
+ if (++p == q)
+ break;
+ }
- return 0;
+ return 0;
}
-/*====================================================================*/
static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
{
- u_char *p;
- if (tuple->TupleDataLen < 5)
- return -EINVAL;
- p = (u_char *) tuple->TupleData;
- csum->addr = tuple->CISOffset + get_unaligned_le16(p) - 2;
- csum->len = get_unaligned_le16(p + 2);
- csum->sum = *(p + 4);
- return 0;
+ u_char *p;
+ if (tuple->TupleDataLen < 5)
+ return -EINVAL;
+ p = (u_char *) tuple->TupleData;
+ csum->addr = tuple->CISOffset + get_unaligned_le16(p) - 2;
+ csum->len = get_unaligned_le16(p + 2);
+ csum->sum = *(p + 4);
+ return 0;
}
-/*====================================================================*/
static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
{
- if (tuple->TupleDataLen < 4)
- return -EINVAL;
- link->addr = get_unaligned_le32(tuple->TupleData);
- return 0;
+ if (tuple->TupleDataLen < 4)
+ return -EINVAL;
+ link->addr = get_unaligned_le32(tuple->TupleData);
+ return 0;
}
-/*====================================================================*/
-static int parse_longlink_mfc(tuple_t *tuple,
- cistpl_longlink_mfc_t *link)
+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 -EINVAL;
- for (i = 0; i < link->nfn; i++) {
- link->fn[i].space = *p; p++;
- link->fn[i].addr = get_unaligned_le32(p);
- p += 4;
- }
- return 0;
+ u_char *p;
+ int i;
+
+ p = (u_char *)tuple->TupleData;
+
+ link->nfn = *p; p++;
+ if (tuple->TupleDataLen <= link->nfn*5)
+ return -EINVAL;
+ for (i = 0; i < link->nfn; i++) {
+ link->fn[i].space = *p; p++;
+ link->fn[i].addr = get_unaligned_le32(p);
+ p += 4;
+ }
+ return 0;
}
-/*====================================================================*/
static int parse_strings(u_char *p, u_char *q, int max,
char *s, u_char *ofs, u_char *found)
{
- int i, j, ns;
+ int i, j, ns;
- if (p == q)
- return -EINVAL;
- 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 -EINVAL;
+ if (p == q)
+ return -EINVAL;
+ 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 -EINVAL;
+ }
+ if ((*p == 0xff) || (++p == q))
+ break;
}
- if ((*p == 0xff) || (++p == q))
- break;
- }
- if (found) {
- *found = ns;
- return 0;
- } else {
+ if (found) {
+ *found = ns;
+ return 0;
+ }
+
return (ns == max) ? 0 : -EINVAL;
- }
}
-/*====================================================================*/
static int parse_vers_1(tuple_t *tuple, cistpl_vers_1_t *vers_1)
{
- u_char *p, *q;
+ u_char *p, *q;
- p = (u_char *)tuple->TupleData;
- q = p + tuple->TupleDataLen;
+ p = (u_char *)tuple->TupleData;
+ q = p + tuple->TupleDataLen;
- vers_1->major = *p; p++;
- vers_1->minor = *p; p++;
- if (p >= q)
- return -EINVAL;
+ vers_1->major = *p; p++;
+ vers_1->minor = *p; p++;
+ if (p >= q)
+ return -EINVAL;
- return parse_strings(p, q, CISTPL_VERS_1_MAX_PROD_STRINGS,
- vers_1->str, vers_1->ofs, &vers_1->ns);
+ 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;
+ u_char *p, *q;
- p = (u_char *)tuple->TupleData;
- q = p + tuple->TupleDataLen;
+ p = (u_char *)tuple->TupleData;
+ q = p + tuple->TupleDataLen;
- return parse_strings(p, q, CISTPL_MAX_ALTSTR_STRINGS,
- altstr->str, altstr->ofs, &altstr->ns);
+ 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;
+ u_char *p, *q;
+ int nid;
- p = (u_char *)tuple->TupleData;
- q = p + tuple->TupleDataLen;
+ 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 0;
+ 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 0;
}
-/*====================================================================*/
static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
{
- if (tuple->TupleDataLen < 4)
- return -EINVAL;
- m->manf = get_unaligned_le16(tuple->TupleData);
- m->card = get_unaligned_le16(tuple->TupleData + 2);
- return 0;
+ if (tuple->TupleDataLen < 4)
+ return -EINVAL;
+ m->manf = get_unaligned_le16(tuple->TupleData);
+ m->card = get_unaligned_le16(tuple->TupleData + 2);
+ return 0;
}
-/*====================================================================*/
static int parse_funcid(tuple_t *tuple, cistpl_funcid_t *f)
{
- u_char *p;
- if (tuple->TupleDataLen < 2)
- return -EINVAL;
- p = (u_char *)tuple->TupleData;
- f->func = p[0];
- f->sysinit = p[1];
- return 0;
+ u_char *p;
+ if (tuple->TupleDataLen < 2)
+ return -EINVAL;
+ p = (u_char *)tuple->TupleData;
+ f->func = p[0];
+ f->sysinit = p[1];
+ return 0;
}
-/*====================================================================*/
static int parse_funce(tuple_t *tuple, cistpl_funce_t *f)
{
- u_char *p;
- int i;
- if (tuple->TupleDataLen < 1)
- return -EINVAL;
- p = (u_char *)tuple->TupleData;
- f->type = p[0];
- for (i = 1; i < tuple->TupleDataLen; i++)
- f->data[i-1] = p[i];
- return 0;
+ u_char *p;
+ int i;
+ if (tuple->TupleDataLen < 1)
+ return -EINVAL;
+ p = (u_char *)tuple->TupleData;
+ f->type = p[0];
+ for (i = 1; i < tuple->TupleDataLen; i++)
+ f->data[i-1] = p[i];
+ return 0;
}
-/*====================================================================*/
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 -EINVAL;
- 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 0;
+ 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 -EINVAL;
+ 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 0;
}
-/*======================================================================
+/* 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;
- The following routines are all used to parse the nightmarish
- config table entries.
+ 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_power(u_char *p, u_char *q,
- cistpl_power_t *pwr)
+static u_char *parse_timing(u_char *p, u_char *q, cistpl_timing_t *timing)
{
- 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) {
+ u_char scale;
+
+ if (p == q)
+ return NULL;
+ scale = *p;
+ if ((scale & 3) != 3) {
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;
+ 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_timing(u_char *p, u_char *q,
- cistpl_timing_t *timing)
+static u_char *parse_io(u_char *p, u_char *q, cistpl_io_t *io)
{
- u_char scale;
+ int i, j, bsz, lsz;
- 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)
+ if (p == q)
return NULL;
- timing->ready = SPEED_CVT(*p);
- timing->rdyscale = exponent[scale & 7];
- } else
- timing->ready = 0;
- scale >>= 3;
- if (scale != 7) {
+ 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;
- timing->reserved = SPEED_CVT(*p);
- timing->rsvscale = exponent[scale];
- } else
- timing->reserved = 0;
- p++;
- return p;
-}
-
-/*====================================================================*/
+ io->nwin = (*p & 0x0f) + 1;
+ bsz = (*p & 0x30) >> 4;
+ if (bsz == 3)
+ bsz++;
+ lsz = (*p & 0xc0) >> 6;
+ if (lsz == 3)
+ lsz++;
+ 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);
+ 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;
+ 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);
+ 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);
+ }
+ 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;
}
- 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;
+ 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)
+ if (p == q)
return NULL;
- irq->IRQInfo2 = (p[1]<<8) + p[0];
- p += 2;
- }
- return p;
+ 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 -EINVAL;
- if (*p & 0x10)
- entry->flags |= CISTPL_CFTABLE_BVDS;
- if (*p & 0x20)
- entry->flags |= CISTPL_CFTABLE_WP;
+ 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_RDYBSY;
- if (*p & 0x80)
- entry->flags |= CISTPL_CFTABLE_MWAIT;
- entry->interface = *p & 0x0f;
- } else
- entry->interface = 0;
-
- /* Process optional features */
- if (++p == q)
- return -EINVAL;
- features = *p; p++;
-
- /* Power options */
- if ((features & 3) > 0) {
- p = parse_power(p, q, &entry->vcc);
- if (p == NULL)
- return -EINVAL;
- } else
- entry->vcc.present = 0;
- if ((features & 3) > 1) {
- p = parse_power(p, q, &entry->vpp1);
- if (p == NULL)
- return -EINVAL;
- } else
- entry->vpp1.present = 0;
- if ((features & 3) > 2) {
- p = parse_power(p, q, &entry->vpp2);
- if (p == NULL)
- return -EINVAL;
- } else
- entry->vpp2.present = 0;
+ entry->flags |= CISTPL_CFTABLE_DEFAULT;
+ if (*p & 0x80) {
+ if (++p == q)
+ return -EINVAL;
+ 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;
- /* Timing options */
- if (features & 0x04) {
- p = parse_timing(p, q, &entry->timing);
- if (p == NULL)
- return -EINVAL;
- } 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)
+ /* Process optional features */
+ if (++p == q)
return -EINVAL;
- } else
- entry->io.nwin = 0;
+ features = *p; p++;
- /* Interrupt options */
- if (features & 0x10) {
- p = parse_irq(p, q, &entry->irq);
- if (p == NULL)
- return -EINVAL;
- } 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 = get_unaligned_le16(p) << 8;
- entry->mem.win[0].card_addr = 0;
- entry->mem.win[0].host_addr = 0;
- p += 2;
- if (p > q)
- return -EINVAL;
- break;
- case 0x40:
- entry->mem.nwin = 1;
- entry->mem.win[0].len = get_unaligned_le16(p) << 8;
- entry->mem.win[0].card_addr = get_unaligned_le16(p + 2) << 8;
- entry->mem.win[0].host_addr = 0;
- p += 4;
- if (p > q)
- return -EINVAL;
- break;
- case 0x60:
- p = parse_mem(p, q, &entry->mem);
- if (p == NULL)
- return -EINVAL;
- break;
- }
+ /* Power options */
+ if ((features & 3) > 0) {
+ p = parse_power(p, q, &entry->vcc);
+ if (p == NULL)
+ return -EINVAL;
+ } else
+ entry->vcc.present = 0;
+ if ((features & 3) > 1) {
+ p = parse_power(p, q, &entry->vpp1);
+ if (p == NULL)
+ return -EINVAL;
+ } else
+ entry->vpp1.present = 0;
+ if ((features & 3) > 2) {
+ p = parse_power(p, q, &entry->vpp2);
+ if (p == NULL)
+ return -EINVAL;
+ } else
+ entry->vpp2.present = 0;
- /* Misc features */
- if (features & 0x80) {
- if (p == q)
- return -EINVAL;
- entry->flags |= (*p << 8);
- while (*p & 0x80)
- if (++p == q)
- return -EINVAL;
- p++;
- }
+ /* Timing options */
+ if (features & 0x04) {
+ p = parse_timing(p, q, &entry->timing);
+ if (p == NULL)
+ return -EINVAL;
+ } else {
+ entry->timing.wait = 0;
+ entry->timing.ready = 0;
+ entry->timing.reserved = 0;
+ }
- entry->subtuples = q-p;
+ /* I/O window options */
+ if (features & 0x08) {
+ p = parse_io(p, q, &entry->io);
+ if (p == NULL)
+ return -EINVAL;
+ } else
+ entry->io.nwin = 0;
+
+ /* Interrupt options */
+ if (features & 0x10) {
+ p = parse_irq(p, q, &entry->irq);
+ if (p == NULL)
+ return -EINVAL;
+ } 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 = get_unaligned_le16(p) << 8;
+ entry->mem.win[0].card_addr = 0;
+ entry->mem.win[0].host_addr = 0;
+ p += 2;
+ if (p > q)
+ return -EINVAL;
+ break;
+ case 0x40:
+ entry->mem.nwin = 1;
+ entry->mem.win[0].len = get_unaligned_le16(p) << 8;
+ entry->mem.win[0].card_addr = get_unaligned_le16(p + 2) << 8;
+ entry->mem.win[0].host_addr = 0;
+ p += 4;
+ if (p > q)
+ return -EINVAL;
+ break;
+ case 0x60:
+ p = parse_mem(p, q, &entry->mem);
+ if (p == NULL)
+ return -EINVAL;
+ break;
+ }
+
+ /* Misc features */
+ if (features & 0x80) {
+ if (p == q)
+ return -EINVAL;
+ entry->flags |= (*p << 8);
+ while (*p & 0x80)
+ if (++p == q)
+ return -EINVAL;
+ p++;
+ }
+
+ entry->subtuples = q-p;
- return 0;
+ return 0;
}
-/*====================================================================*/
static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo)
{
- u_char *p, *q;
- int n;
+ u_char *p, *q;
+ int n;
- p = (u_char *)tuple->TupleData;
- q = p + tuple->TupleDataLen;
+ 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 0;
+ 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 0;
}
-/*====================================================================*/
static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
{
- u_char *p, *q;
-
- if (tuple->TupleDataLen < 10)
- return -EINVAL;
-
- p = tuple->TupleData;
- q = p + tuple->TupleDataLen;
-
- v2->vers = p[0];
- v2->comply = p[1];
- v2->dindex = get_unaligned_le16(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);
+ u_char *p, *q;
+
+ if (tuple->TupleDataLen < 10)
+ return -EINVAL;
+
+ p = tuple->TupleData;
+ q = p + tuple->TupleDataLen;
+
+ v2->vers = p[0];
+ v2->comply = p[1];
+ v2->dindex = get_unaligned_le16(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 -EINVAL;
- org->data_org = *p;
- if (++p == q)
- return -EINVAL;
- for (i = 0; i < 30; i++) {
- org->desc[i] = *p;
- if (*p == '\0')
- break;
+ u_char *p, *q;
+ int i;
+
+ p = tuple->TupleData;
+ q = p + tuple->TupleDataLen;
+ if (p == q)
+ return -EINVAL;
+ org->data_org = *p;
if (++p == q)
return -EINVAL;
- }
- return 0;
+ for (i = 0; i < 30; i++) {
+ org->desc[i] = *p;
+ if (*p == '\0')
+ break;
+ if (++p == q)
+ return -EINVAL;
+ }
+ return 0;
}
-/*====================================================================*/
static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
{
- u_char *p;
+ u_char *p;
- if (tuple->TupleDataLen < 10)
- return -EINVAL;
+ if (tuple->TupleDataLen < 10)
+ return -EINVAL;
- p = tuple->TupleData;
+ p = tuple->TupleData;
- fmt->type = p[0];
- fmt->edc = p[1];
- fmt->offset = get_unaligned_le32(p + 2);
- fmt->length = get_unaligned_le32(p + 6);
+ fmt->type = p[0];
+ fmt->edc = p[1];
+ fmt->offset = get_unaligned_le32(p + 2);
+ fmt->length = get_unaligned_le32(p + 6);
- return 0;
+ return 0;
}
-/*====================================================================*/
int pcmcia_parse_tuple(tuple_t *tuple, cisparse_t *parse)
{
- int ret = 0;
-
- if (tuple->TupleDataLen > tuple->TupleDataMax)
- return -EINVAL;
- switch (tuple->TupleCode) {
- case CISTPL_DEVICE:
- case CISTPL_DEVICE_A:
- ret = parse_device(tuple, &parse->device);
- break;
- 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 = 0;
- break;
- default:
- ret = -EINVAL;
- break;
- }
- if (ret)
- pr_debug("parse_tuple failed %d\n", ret);
- return ret;
+ int ret = 0;
+
+ if (tuple->TupleDataLen > tuple->TupleDataMax)
+ return -EINVAL;
+ switch (tuple->TupleCode) {
+ case CISTPL_DEVICE:
+ case CISTPL_DEVICE_A:
+ ret = parse_device(tuple, &parse->device);
+ break;
+ 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 = 0;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ if (ret)
+ pr_debug("parse_tuple failed %d\n", ret);
+ return ret;
}
EXPORT_SYMBOL(pcmcia_parse_tuple);
-/*======================================================================
- This is used internally by Card Services to look up CIS stuff.
-
-======================================================================*/
-
-int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse)
+/**
+ * pccard_read_tuple() - internal CIS tuple access
+ * @s: the struct pcmcia_socket where the card is inserted
+ * @function: the device function we loop for
+ * @code: which CIS code shall we look for?
+ * @parse: buffer where the tuple shall be parsed (or NULL, if no parse)
+ *
+ * pccard_read_tuple() reads out one tuple and attempts to parse it
+ */
+int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function,
+ cisdata_t code, void *parse)
{
- tuple_t tuple;
- cisdata_t *buf;
- int ret;
-
- buf = kmalloc(256, GFP_KERNEL);
- if (buf == NULL) {
- dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n");
- return -ENOMEM;
- }
- tuple.DesiredTuple = code;
- tuple.Attributes = 0;
- if (function == BIND_FN_ALL)
- tuple.Attributes = TUPLE_RETURN_COMMON;
- ret = pccard_get_first_tuple(s, function, &tuple);
- if (ret != 0)
- goto done;
- tuple.TupleData = buf;
- tuple.TupleOffset = 0;
- tuple.TupleDataMax = 255;
- ret = pccard_get_tuple_data(s, &tuple);
- if (ret != 0)
- goto done;
- ret = pcmcia_parse_tuple(&tuple, parse);
+ tuple_t tuple;
+ cisdata_t *buf;
+ int ret;
+
+ buf = kmalloc(256, GFP_KERNEL);
+ if (buf == NULL) {
+ dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n");
+ return -ENOMEM;
+ }
+ tuple.DesiredTuple = code;
+ tuple.Attributes = 0;
+ if (function == BIND_FN_ALL)
+ tuple.Attributes = TUPLE_RETURN_COMMON;
+ ret = pccard_get_first_tuple(s, function, &tuple);
+ if (ret != 0)
+ goto done;
+ tuple.TupleData = buf;
+ tuple.TupleOffset = 0;
+ tuple.TupleDataMax = 255;
+ ret = pccard_get_tuple_data(s, &tuple);
+ if (ret != 0)
+ goto done;
+ ret = pcmcia_parse_tuple(&tuple, parse);
done:
- kfree(buf);
- return ret;
+ kfree(buf);
+ return ret;
}
diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c
index 3889cf07d6ce..9254ab0b29b1 100644
--- a/drivers/pcmcia/db1xxx_ss.c
+++ b/drivers/pcmcia/db1xxx_ss.c
@@ -42,7 +42,6 @@ struct db1x_pcmcia_sock {
int nr; /* socket number */
void *virt_io;
- /* the "pseudo" addresses of the PCMCIA space. */
phys_addr_t phys_io;
phys_addr_t phys_attr;
phys_addr_t phys_mem;
@@ -437,7 +436,7 @@ static int __devinit db1x_pcmcia_socket_probe(struct platform_device *pdev)
* This includes IRQs for Carddetection/ejection, the card
* itself and optional status change detection.
* Also, the memory areas covered by a socket. For these
- * we require the 32bit "pseudo" addresses (see the au1000.h
+ * we require the real 36bit addresses (see the au1000.h
* header for more information).
*/
@@ -459,11 +458,7 @@ static int __devinit db1x_pcmcia_socket_probe(struct platform_device *pdev)
ret = -ENODEV;
- /*
- * pseudo-attr: The 32bit address of the PCMCIA attribute space
- * for this socket (usually the 36bit address shifted 4 to the
- * right).
- */
+ /* 36bit PCMCIA Attribute area address */
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-attr");
if (!r) {
printk(KERN_ERR "pcmcia%d has no 'pseudo-attr' resource!\n",
@@ -472,10 +467,7 @@ static int __devinit db1x_pcmcia_socket_probe(struct platform_device *pdev)
}
sock->phys_attr = r->start;
- /*
- * pseudo-mem: The 32bit address of the PCMCIA memory space for
- * this socket (usually the 36bit address shifted 4 to the right)
- */
+ /* 36bit PCMCIA Memory area address */
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-mem");
if (!r) {
printk(KERN_ERR "pcmcia%d has no 'pseudo-mem' resource!\n",
@@ -484,10 +476,7 @@ static int __devinit db1x_pcmcia_socket_probe(struct platform_device *pdev)
}
sock->phys_mem = r->start;
- /*
- * pseudo-io: The 32bit address of the PCMCIA IO space for this
- * socket (usually the 36bit address shifted 4 to the right).
- */
+ /* 36bit PCMCIA IO area address */
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-io");
if (!r) {
printk(KERN_ERR "pcmcia%d has no 'pseudo-io' resource!\n",
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index e1741cd875aa..7c204910a777 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -48,23 +48,13 @@ MODULE_AUTHOR("Jun Komuro <komurojun-mbn@nifty.com>");
* Specifies the interrupt delivery mode. The default (1) is to use PCI
* interrupts; a value of 0 selects ISA interrupts. This must be set for
* correct operation of PCI card readers.
- *
- * irq_list=i,j,...
- * This list limits the set of interrupts that can be used by PCMCIA
- * cards.
- * The default list is 3,4,5,7,9,10,11.
- * (irq_list parameter is not used, if irq_mode = 1)
*/
static int irq_mode = 1; /* 0 = ISA interrupt, 1 = PCI interrupt */
-static int irq_list[16];
-static unsigned int irq_list_count = 0;
module_param(irq_mode, int, 0444);
-module_param_array(irq_list, int, &irq_list_count, 0444);
MODULE_PARM_DESC(irq_mode,
"interrupt delivery mode. 0 = ISA, 1 = PCI. default is 1");
-MODULE_PARM_DESC(irq_list, "interrupts that can be used by PCMCIA cards");
static DEFINE_SPINLOCK(port_lock);
@@ -605,13 +595,7 @@ static u_int __devinit pd6729_isa_scan(void)
return 0;
}
- if (irq_list_count == 0)
- mask0 = 0xffff;
- else
- for (i = mask0 = 0; i < irq_list_count; i++)
- mask0 |= (1<<irq_list[i]);
-
- mask0 &= PD67_MASK;
+ mask0 = PD67_MASK;
/* just find interrupts that aren't in use */
for (i = 0; i < 16; i++)
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index e6f7d410aed6..452c83b512c4 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -79,9 +79,8 @@ static resource_size_t pcmcia_align(void *align_data,
#ifdef CONFIG_X86
if (res->flags & IORESOURCE_IO) {
- if (start & 0x300) {
+ if (start & 0x300)
start = (start + 0x3ff) & ~0x3ff;
- }
}
#endif
diff --git a/drivers/pcmcia/xxs1500_ss.c b/drivers/pcmcia/xxs1500_ss.c
index 61560cd6e287..f9009d34254b 100644
--- a/drivers/pcmcia/xxs1500_ss.c
+++ b/drivers/pcmcia/xxs1500_ss.c
@@ -218,11 +218,7 @@ static int __devinit xxs1500_pcmcia_probe(struct platform_device *pdev)
ret = -ENODEV;
- /*
- * pseudo-attr: The 32bit address of the PCMCIA attribute space
- * for this socket (usually the 36bit address shifted 4 to the
- * right).
- */
+ /* 36bit PCMCIA Attribute area address */
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-attr");
if (!r) {
dev_err(&pdev->dev, "missing 'pcmcia-attr' resource!\n");
@@ -230,10 +226,7 @@ static int __devinit xxs1500_pcmcia_probe(struct platform_device *pdev)
}
sock->phys_attr = r->start;
- /*
- * pseudo-mem: The 32bit address of the PCMCIA memory space for
- * this socket (usually the 36bit address shifted 4 to the right)
- */
+ /* 36bit PCMCIA Memory area address */
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-mem");
if (!r) {
dev_err(&pdev->dev, "missing 'pcmcia-mem' resource!\n");
@@ -241,10 +234,7 @@ static int __devinit xxs1500_pcmcia_probe(struct platform_device *pdev)
}
sock->phys_mem = r->start;
- /*
- * pseudo-io: The 32bit address of the PCMCIA IO space for this
- * socket (usually the 36bit address shifted 4 to the right).
- */
+ /* 36bit PCMCIA IO area address */
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-io");
if (!r) {
dev_err(&pdev->dev, "missing 'pcmcia-io' resource!\n");
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index b85375f87622..967c766f53ba 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -1408,10 +1408,10 @@ static struct pci_device_id yenta_table[] = {
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7510, TI12XX),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7610, TI12XX),
- CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_710, TI12XX),
- CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_712, TI12XX),
- CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_720, TI12XX),
- CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_722, TI12XX),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_710, ENE),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_712, ENE),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_720, ENE),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_722, ENE),
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE),
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE),
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE),