summaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/cistpl.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-16 01:07:24 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-16 01:07:24 +0000
commit95db6b748fc86297827fbd9c9ef174d491c9ad89 (patch)
tree27a92a942821cde1edda9a1b088718d436b3efe4 /drivers/pcmcia/cistpl.c
parent45b27b0a0652331d104c953a5b192d843fff88f8 (diff)
Merge with Linux 2.3.40.
Diffstat (limited to 'drivers/pcmcia/cistpl.c')
-rw-r--r--drivers/pcmcia/cistpl.c112
1 files changed, 78 insertions, 34 deletions
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index eb287bee9..acca17316 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -2,7 +2,7 @@
PCMCIA Card Information Structure parser
- cistpl.c 1.74 1999/11/08 20:47:02
+ cistpl.c 1.77 2000/01/16 19:19:01
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
@@ -52,6 +52,7 @@
#include <pcmcia/ss.h>
#include <pcmcia/cs.h>
#include <pcmcia/bulkmem.h>
+#include <pcmcia/cisreg.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
#include "rsrc_mgr.h"
@@ -83,12 +84,15 @@ static const u_int exponent[] = {
======================================================================*/
+/* Bits in attr field */
+#define IS_ATTR 1
+#define IS_INDIRECT 8
+
void read_cis_mem(socket_info_t *s, int attr, u_int addr,
u_int len, void *ptr)
{
pccard_mem_map *mem = &s->cis_mem;
- u_char *sys;
- u_int inc = 1;
+ u_char *sys, *buf = ptr;
DEBUG(3, "cs: read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
if (setup_cis_mem(s) != 0) {
@@ -96,47 +100,81 @@ void read_cis_mem(socket_info_t *s, int attr, u_int addr,
return;
}
mem->flags |= MAP_ACTIVE; mem->flags &= ~MAP_ATTRIB;
- if (attr) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
- sys = s->cis_virt + (addr & (s->cap.map_size-1));
- mem->card_start = addr & ~(s->cap.map_size-1);
-
- for (; len > 0; sys = s->cis_virt) {
+ sys = s->cis_virt;
+
+ 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);
- DEBUG(3, "cs: %#2.2x %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
- bus_readb(s->cap.bus, sys),
- bus_readb(s->cap.bus, sys+inc),
- bus_readb(s->cap.bus, sys+2*inc),
- bus_readb(s->cap.bus, sys+3*inc),
- bus_readb(s->cap.bus, sys+4*inc));
- for ( ; len > 0; len--, ((u_char *)ptr)++, sys += inc) {
- if (sys == s->cis_virt+s->cap.map_size) break;
- *(u_char *)ptr = bus_readb(s->cap.bus, sys);
+ 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);
+ bus_writeb(s->cap.bus, (addr>>16) & 0xff, sys+CISREG_IADDR2);
+ bus_writeb(s->cap.bus, (addr>>24) & 0xff, sys+CISREG_IADDR3);
+ for ( ; len > 0; len--, buf++)
+ *buf = bus_readb(s->cap.bus, sys+CISREG_IDATA0);
+ } else {
+ u_int inc = 1;
+ 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);
+ 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;
}
- mem->card_start += s->cap.map_size;
}
+ DEBUG(3, "cs: %#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));
}
void write_cis_mem(socket_info_t *s, int attr, u_int addr,
u_int len, void *ptr)
{
pccard_mem_map *mem = &s->cis_mem;
- u_char *sys;
- int inc = 1;
+ u_char *sys, *buf = ptr;
DEBUG(3, "cs: write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
if (setup_cis_mem(s) != 0) return;
- mem->flags &= ~MAP_ATTRIB;
- if (attr) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
- sys = s->cis_virt + (addr & (s->cap.map_size-1));
- mem->card_start = addr & ~(s->cap.map_size-1);
-
- for (; len > 0; sys = s->cis_virt) {
+ mem->flags |= MAP_ACTIVE; mem->flags &= ~MAP_ATTRIB;
+ sys = s->cis_virt;
+
+ 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);
- for ( ; len > 0; len--, ((u_char *)ptr)++, sys += inc) {
- if (sys == s->cis_virt+s->cap.map_size) break;
- bus_writeb(s->cap.bus, *(u_char *)ptr, sys);
+ 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);
+ bus_writeb(s->cap.bus, (addr>>16) & 0xff, sys+CISREG_IADDR2);
+ bus_writeb(s->cap.bus, (addr>>24) & 0xff, sys+CISREG_IADDR3);
+ for ( ; len > 0; len--, buf++)
+ bus_writeb(s->cap.bus, *buf, sys+CISREG_IDATA0);
+ } 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);
+ 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;
}
- mem->card_start += s->cap.map_size;
}
}
@@ -342,10 +380,10 @@ int pcmcia_replace_cis(client_handle_t handle, cisdump_t *cis)
======================================================================*/
typedef struct tuple_flags {
- u_int link_space:3;
+ u_int link_space:4;
u_int has_link:1;
u_int mfc_fn:3;
- u_int space:3;
+ u_int space:4;
} tuple_flags;
#define LINK_SPACE(f) (((tuple_flags *)(&(f)))->link_space)
@@ -469,18 +507,24 @@ int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple)
(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) = 1;
+ LINK_SPACE(tuple->Flags) = attr | IS_ATTR;
read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
break;
case CISTPL_LONGLINK_C:
HAS_LINK(tuple->Flags) = 1;
- LINK_SPACE(tuple->Flags) = 0;
+ LINK_SPACE(tuple->Flags) = attr & ~IS_ATTR;
read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
break;
+ case CISTPL_INDIRECT:
+ HAS_LINK(tuple->Flags) = 1;
+ LINK_SPACE(tuple->Flags) = IS_ATTR | IS_INDIRECT;
+ tuple->LinkOffset = 0;
+ break;
case CISTPL_LONGLINK_MFC:
tuple->LinkOffset = ofs + 3;
LINK_SPACE(tuple->Flags) = attr;