OSEC

Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com
pcmcia: support for indirect CIS

From: Miod Vallat (miodonline.fr)
Date: Wed Sep 01 2010 - 08:53:44 CDT


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)))))