The following diff adds support for PCMCIA cards with indirect CIS data
(the regular CIS data only contains a device tuple and an ``indirect''
tuple).

These cards currently aren't recognized correctly and ``attach'' as
this:
com3 at pcmcia0 function 0: can't allocate i/o space

If you have such pcmcia cards, you might want to give this diff a try.

Miod

Index: pcmcia_cis.c
===================================================================
RCS file: /cvs/src/sys/dev/pcmcia/pcmcia_cis.c,v
retrieving revision 1.15
diff -u -p -r1.15 pcmcia_cis.c
--- pcmcia_cis.c        11 Sep 2007 13:39:34 -0000      1.15
+++ pcmcia_cis.c        1 Sep 2010 13:52:29 -0000
@@ -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 {
Index: pcmciareg.h
===================================================================
RCS file: /cvs/src/sys/dev/pcmcia/pcmciareg.h,v
retrieving revision 1.6
diff -u -p -r1.6 pcmciareg.h
--- pcmciareg.h 26 Jun 2003 00:35:07 -0000      1.6
+++ pcmciareg.h 1 Sep 2010 13:52:29 -0000
@@ -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
Index: pcmciavar.h
===================================================================
RCS file: /cvs/src/sys/dev/pcmcia/pcmciavar.h,v
retrieving revision 1.20
diff -u -p -r1.20 pcmciavar.h
--- pcmciavar.h 23 Nov 2005 11:39:37 -0000      1.20
+++ pcmciavar.h 1 Sep 2010 13:52:29 -0000
@@ -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 pcmc
 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)))))

Reply via email to