summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2010-09-04 12:59:28 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2010-09-04 12:59:28 +0000
commitad1edb83deb5874b8ae4b9eca158419b9f618b71 (patch)
tree242532775217c9eec6959bfc2b647487c904eb3c
parent5882b5104fd69b5de0d8442a9caf28aa6644954d (diff)
Add support for indirect CIS data (CISTPL_INDIRECT tuple).
-rw-r--r--sys/dev/pcmcia/pcmcia_cis.c69
-rw-r--r--sys/dev/pcmcia/pcmciareg.h16
-rw-r--r--sys/dev/pcmcia/pcmciavar.h11
3 files changed, 81 insertions, 15 deletions
diff --git a/sys/dev/pcmcia/pcmcia_cis.c b/sys/dev/pcmcia/pcmcia_cis.c
index e3db1547070..de0e9f436d8 100644
--- a/sys/dev/pcmcia/pcmcia_cis.c
+++ b/sys/dev/pcmcia/pcmcia_cis.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcmcia_cis.c,v 1.15 2007/09/11 13:39:34 gilles Exp $ */
+/* $OpenBSD: pcmcia_cis.c,v 1.16 2010/09/04 12:59:27 miod Exp $ */
/* $NetBSD: pcmcia_cis.c,v 1.9 1998/08/22 23:41:48 msaitoh Exp $ */
/*
@@ -59,6 +59,28 @@ struct cis_state {
int pcmcia_parse_cis_tuple(struct pcmcia_tuple *, void *);
+uint8_t
+pcmcia_cis_read_1(struct pcmcia_tuple *tuple, bus_size_t idx)
+{
+ if (tuple->flags & PTF_INDIRECT) {
+ bus_space_write_1(tuple->memt, tuple->memh,
+ tuple->indirect_ptr + PCMCIA_INDR_CONTROL, PCMCIA_ICR_ATTR);
+ idx <<= tuple->addrshift;
+ bus_space_write_1(tuple->memt, tuple->memh,
+ tuple->indirect_ptr + PCMCIA_INDR_ADDRESS + 0, idx >> 0);
+ bus_space_write_1(tuple->memt, tuple->memh,
+ tuple->indirect_ptr + PCMCIA_INDR_ADDRESS + 1, idx >> 8);
+ bus_space_write_1(tuple->memt, tuple->memh,
+ tuple->indirect_ptr + PCMCIA_INDR_ADDRESS + 2, idx >> 16);
+ bus_space_write_1(tuple->memt, tuple->memh,
+ tuple->indirect_ptr + PCMCIA_INDR_ADDRESS + 3, idx >> 24);
+ return bus_space_read_1(tuple->memt, tuple->memh,
+ tuple->indirect_ptr + PCMCIA_INDR_DATA);
+ } else
+ return bus_space_read_1(tuple->memt, tuple->memh,
+ idx << tuple->addrshift);
+}
+
void
pcmcia_read_cis(sc)
struct pcmcia_softc *sc;
@@ -99,6 +121,7 @@ pcmcia_scan_cis(dev, fct, arg)
int window;
struct pcmcia_mem_handle pcmh;
struct pcmcia_tuple tuple;
+ int indirect_present;
int longlink_present;
int longlink_common;
u_long longlink_addr;
@@ -140,8 +163,10 @@ pcmcia_scan_cis(dev, fct, arg)
DPRINTF(("cis mem map %x\n", (unsigned int) tuple.memh));
- tuple.mult = 2;
+ tuple.addrshift = 1;
+ tuple.flags = 0;
+ indirect_present = 0;
longlink_present = 1;
longlink_common = 1;
longlink_addr = 0;
@@ -159,8 +184,8 @@ pcmcia_scan_cis(dev, fct, arg)
* (This check may not be sufficient for
* malicious cards.)
*/
- if (tuple.mult * tuple.ptr >= PCMCIA_CIS_SIZE - 1
- - 32 /* ad hoc value */ ) {
+ if ((tuple.ptr << tuple.addrshift) >=
+ PCMCIA_CIS_SIZE - 1 - 32 /* ad hoc value */) {
DPRINTF(("CISTPL_END (too long CIS)\n"));
tuple.code = PCMCIA_CISTPL_END;
goto cis_end;
@@ -194,6 +219,10 @@ pcmcia_scan_cis(dev, fct, arg)
tuple.length = pcmcia_cis_read_1(&tuple, tuple.ptr + 1);
switch (tuple.code) {
+ case PCMCIA_CISTPL_INDIRECT:
+ indirect_present = 1;
+ DPRINTF(("CISTPL_INDIRECT\n"));
+ break;
case PCMCIA_CISTPL_LONGLINK_A:
case PCMCIA_CISTPL_LONGLINK_C:
if (tuple.length < 4) {
@@ -253,8 +282,8 @@ pcmcia_scan_cis(dev, fct, arg)
for (i = 0; i < length; i++)
sum +=
bus_space_read_1(tuple.memt,
- tuple.memh,
- addr + tuple.mult * i);
+ tuple.memh, addr +
+ (i << tuple.addrshift));
if (cksum != (sum & 0xff)) {
DPRINTF((" failed sum=%x\n",
sum));
@@ -386,7 +415,29 @@ pcmcia_scan_cis(dev, fct, arg)
while (1) {
pcmcia_chip_mem_unmap(pct, pch, window);
- if (longlink_present) {
+ if (indirect_present) {
+ /*
+ * Indirect CIS data needs to be obtained
+ * from specific registers accessible at
+ * a fixed location in the common window,
+ * but otherwise is similar to longlink
+ * in attribute memory.
+ */
+
+ pcmcia_chip_mem_map(pct, pch, PCMCIA_MEM_COMMON,
+ 0, PCMCIA_INDR_SIZE,
+ &pcmh, &tuple.indirect_ptr, &window);
+
+ DPRINTF(("cis mem map %x ind %x\n",
+ (unsigned int) tuple.memh,
+ (unsigned int) tuple.indirect_ptr));
+
+ tuple.addrshift = 1;
+ tuple.flags |= PTF_INDIRECT;
+ tuple.ptr = 0;
+ longlink_present = 0;
+ indirect_present = 0;
+ } else if (longlink_present) {
/*
* if the longlink is to attribute memory,
* then it is unindexed. That is, if the
@@ -411,7 +462,7 @@ pcmcia_scan_cis(dev, fct, arg)
DPRINTF(("cis mem map %x\n",
(unsigned int) tuple.memh));
- tuple.mult = longlink_common ? 1 : 2;
+ tuple.addrshift = longlink_common ? 0 : 1;
longlink_present = 0;
longlink_common = 1;
longlink_addr = 0;
@@ -433,7 +484,7 @@ pcmcia_scan_cis(dev, fct, arg)
/* set parse state, and point at the next one */
- tuple.mult = mfc[mfc_index].common ? 1 : 2;
+ tuple.addrshift = mfc[mfc_index].common ? 0 : 1;
mfc_index++;
} else {
diff --git a/sys/dev/pcmcia/pcmciareg.h b/sys/dev/pcmcia/pcmciareg.h
index f28bfaff063..53af0d262e7 100644
--- a/sys/dev/pcmcia/pcmciareg.h
+++ b/sys/dev/pcmcia/pcmciareg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcmciareg.h,v 1.6 2003/06/26 00:35:07 mickey Exp $ */
+/* $OpenBSD: pcmciareg.h,v 1.7 2010/09/04 12:59:27 miod Exp $ */
/* $NetBSD: pcmciareg.h,v 1.6 1998/08/13 15:00:02 nathanw Exp $ */
/*
@@ -241,3 +241,17 @@
#define PCMCIA_CCR_IOSIZE 0x12
#define PCMCIA_CCR_SIZE 0x14
+
+/*
+ * Indirect CIS registers (in common space)
+ */
+
+#define PCMCIA_INDR_CONTROL 0x02
+#define PCMCIA_ICR_ATTR 0x00
+#define PCMCIA_ICR_COMMON 0x01
+#define PCMCIA_ICR_AUTOINCREMENT 0x02
+#define PCMCIA_ICR_BYTELANE 0x04
+#define PCMCIA_INDR_ADDRESS 0x04
+#define PCMCIA_INDR_DATA 0x08
+
+#define PCMCIA_INDR_SIZE 0x0a
diff --git a/sys/dev/pcmcia/pcmciavar.h b/sys/dev/pcmcia/pcmciavar.h
index e4751dee4f1..ad1562797a4 100644
--- a/sys/dev/pcmcia/pcmciavar.h
+++ b/sys/dev/pcmcia/pcmciavar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcmciavar.h,v 1.20 2005/11/23 11:39:37 mickey Exp $ */
+/* $OpenBSD: pcmciavar.h,v 1.21 2010/09/04 12:59:27 miod Exp $ */
/* $NetBSD: pcmciavar.h,v 1.5 1998/07/19 17:28:17 christos Exp $ */
/*
@@ -193,7 +193,10 @@ struct pcmcia_attach_args {
struct pcmcia_tuple {
unsigned int code;
unsigned int length;
- u_long mult;
+ unsigned int addrshift;
+ unsigned int flags;
+#define PTF_INDIRECT 0x01
+ bus_size_t indirect_ptr;
bus_size_t ptr;
bus_space_tag_t memt;
bus_space_handle_t memh;
@@ -204,9 +207,7 @@ void pcmcia_check_cis_quirks(struct pcmcia_softc *);
void pcmcia_print_cis(struct pcmcia_softc *);
int pcmcia_scan_cis(struct device * dev,
int (*) (struct pcmcia_tuple *, void *), void *);
-
-#define pcmcia_cis_read_1(tuple, idx0) \
- (bus_space_read_1((tuple)->memt, (tuple)->memh, (tuple)->mult*(idx0)))
+uint8_t pcmcia_cis_read_1(struct pcmcia_tuple *, bus_size_t);
#define pcmcia_tuple_read_1(tuple, idx1) \
(pcmcia_cis_read_1((tuple), ((tuple)->ptr+(2+(idx1)))))