port to 3.2
authornotaz <notasas@gmail.com>
Mon, 9 Feb 2015 00:03:24 +0000 (02:03 +0200)
committernotaz <notasas@gmail.com>
Mon, 9 Feb 2015 00:03:48 +0000 (02:03 +0200)
sta_dk/pform/linux/build/Makefile
sta_dk/pform/linux/inc/esta_drv.h
sta_dk/pform/linux/src/esta_drv.c
sta_dk/pform/linux/src/ioctl_list.c
sta_dk/pform/linux/src/mmc_tnetw1150_api.c [new file with mode: 0644]
sta_dk/pform/linux/src/tnetw_sdio.c [new file with mode: 0644]

index ee32f2f..ce1a5c2 100644 (file)
@@ -10,6 +10,7 @@ NO_ARCH_STRCMP ?= y
 NO_USERMODE_WORKAROUND ?= n
 MEM_ALLOC_TRACE ?= n
 TIWLAN_INIT_FILE_SUPPORT ?= y
+USE_SDIO_DRIVER ?= y
 
 
 
@@ -62,7 +63,9 @@ OS_SRCS += \
     $(DK_ROOT)/pform/linux/src/ioctl_utils.c \
     $(DK_ROOT)/pform/linux/src/osRgstry_parser.c \
     $(DK_ROOT)/pform/linux/src/ipc_k.c \
-    $(DK_ROOT)/pform/linux/src/proc_stat.c
+    $(DK_ROOT)/pform/linux/src/proc_stat.c \
+    $(DK_ROOT)/pform/linux/src/tnetw_sdio.c \
+    $(DK_ROOT)/pform/linux/src/mmc_tnetw1150_api.c
 
 ifeq ($(DRIVER_PROFILING),y)
     OS_SRCS += $(DK_ROOT)/pform/linux/src/tiwlan_profile.c
@@ -141,6 +144,10 @@ ifeq ($(MEM_ALLOC_TRACE),y)
     EXTRA_CFLAGS += -D TI_MEM_ALLOC_TRACE
 endif
 
+ifeq ($(USE_SDIO_DRIVER),y)
+    EXTRA_CFLAGS += -D USE_SDIO_DRIVER
+endif
+
 
 
 
index 635e870..3b23559 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/completion.h>
 #include <linux/netdevice.h>
 #include <linux/version.h>
+#include <linux/interrupt.h>
 
 //#include <asm/arch/gpio.h>
 
index 2066302..a77a3cb 100644 (file)
 #include "Ethernet.h"
 #include "tiwlan_profile.h"
 
+#ifdef USE_SDIO_DRIVER
+#include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
+#include <linux/wl12xx.h>
+#endif
+
+#if 0
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)
 #define io_p2v(pa)              ((pa) + IO_OFFSET)/* Works for the entire IO Map */
 typedef struct { volatile u32 offset[4096]; } __regbase32;
@@ -188,6 +200,7 @@ typedef struct { volatile u32 offset[4096]; } __regbase32;
 #define GPIO3_LEVELDETECT0     GPIO3_REG32(0x040)
 #define GPIO3_DEBOUNCENABLE    GPIO3_REG32(0x050)
 #define GPIO3_DEBOUNCINGTIME   GPIO3_REG32(0x054)
+#endif
 
 /* Drivers list */
 static LIST_HEAD(tiwlan_drv_list);
@@ -695,6 +708,17 @@ struct net_device_stats * tiwlan_drv_net_get_stats(struct net_device * dev)
    return &drv->stats;
 }
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+extern int ti1610_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+
+static struct net_device_ops netdev_ops = {
+    .ndo_open = tiwlan_drv_net_open,
+    .ndo_stop = tiwlan_drv_net_stop,
+    .ndo_start_xmit = tiwlan_drv_dummy_net_xmit,
+    .ndo_get_stats = tiwlan_drv_net_get_stats,
+    .ndo_do_ioctl = ti1610_do_ioctl,
+};
+#endif
 
 static int setup_netif(tiwlan_net_dev_t *drv)
 {
@@ -715,10 +739,14 @@ static int setup_netif(tiwlan_net_dev_t *drv)
 #ifndef mike
    tiwlan_iwhandler_init(dev);
 #endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+   dev->netdev_ops = &netdev_ops;
+#else
    dev->open = tiwlan_drv_net_open;
    dev->stop = tiwlan_drv_net_stop;
    dev->hard_start_xmit = tiwlan_drv_dummy_net_xmit;
    dev->get_stats = tiwlan_drv_net_get_stats;
+#endif
    dev->tx_queue_len = 100;
 
    res = tiwlan_ioctl_init(dev);
@@ -1140,6 +1168,11 @@ int tiwlan_init_drv (tiwlan_net_dev_t *drv, tiwlan_dev_init_t *init_info)
                                                 pWLAN_Images,
                                                 init_table, 
                                                 (macAddress_t *) &drv->adapter.CurrentAddr);
+    if (drv->adapter.CoreHalCtx == NULL)
+    {
+        printk("configMgr_create failed\n");
+        return -1;
+    }
 
     drv->interrupt_pending = 0;   
     drv->dma_done = 0;
@@ -1167,8 +1200,10 @@ int tiwlan_init_drv (tiwlan_net_dev_t *drv, tiwlan_dev_init_t *init_info)
         }
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
         set_irq_type (drv->irq, IRQT_FALLING);
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
+        set_irq_type (drv->irq, IRQ_TYPE_EDGE_FALLING);
 #else
-       set_irq_type (drv->irq, IRQ_TYPE_EDGE_FALLING);
+        irq_set_irq_type(drv->irq, IRQ_TYPE_EDGE_FALLING);
 #endif
         disable_irq (drv->irq);
         spin_unlock_irqrestore (&drv->lock, flags);
@@ -1229,7 +1264,11 @@ int tiwlan_init_drv (tiwlan_net_dev_t *drv, tiwlan_dev_init_t *init_info)
     }
 
     /* Finalize network interface setup */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+    netdev_ops.ndo_start_xmit = tiwlan_drv_net_xmit;
+#else
     drv->netdev->hard_start_xmit = tiwlan_drv_net_xmit;
+#endif
     memcpy (drv->netdev->dev_addr, drv->adapter.CurrentAddr, MAC_ADDR_LEN);
     drv->netdev->addr_len = MAC_ADDR_LEN;
 
@@ -1504,15 +1543,120 @@ static struct pci_driver tnetw1130_pci_driver = {
 #ifdef TIWLAN_OMAP1610
 int omap1610_drv_create(void)
 {
+   int irq = TIWLAN_OMAP1610_IRQ;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
+   const struct wl12xx_platform_data *wl12xx_board_data;
+   irq = -1;
+   wl12xx_board_data = wl12xx_get_platform_data();
+   if (!IS_ERR(wl12xx_board_data))
+      irq = wl12xx_board_data->irq;
+   if (irq < 0)
+      return -1;
+#endif
+
    omap_memif_init();
 
    return tiwlan_create_drv(TIWLAN_OMAP1610_REGBASE, TIWLAN_OMAP1610_REGSIZE,
                             TIWLAN_OMAP1610_MEMBASE, TIWLAN_OMAP1610_MEMSIZE,
-                            0, TIWLAN_OMAP1610_IRQ, NULL, NULL);
+                            0, irq, NULL, NULL);
 
 }
 #endif /* #ifdef TIWLAN_OMAP1610 */
 
+#ifdef USE_SDIO_DRIVER
+extern void SDIO_SetFunc( struct sdio_func * );
+
+int tiwlan_sdio_init(struct sdio_func *func)
+{
+   int rc;
+
+   rc = sdio_enable_func(func);
+   if (rc)
+      return rc;
+
+   rc = sdio_set_block_size(func, 512);
+   if( rc ) {
+      sdio_disable_func(func);
+   }
+   return rc;
+}
+
+static int tiwlan_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
+{
+       int rc;
+
+       SDIO_SetFunc( NULL );
+       if (func->vendor != VENDOR_ID_TI || func->device != DEVICE_ID_TI_WLAN)
+               return -ENODEV;
+
+       printk(KERN_INFO
+              "TIWLAN: Found SDIO controller (vendor 0x%x, device 0x%x)\n",
+              func->vendor, func->device);
+
+       sdio_claim_host(func);
+
+       rc = tiwlan_sdio_init(func);
+       if (rc)
+               goto err2;
+
+       SDIO_SetFunc( func );
+
+       rc = omap1610_drv_create();
+
+       printk(KERN_INFO "TIWLAN: Driver initialized (rc %d)\n", rc);
+       //complete(&sdio_wait);
+       return rc;
+
+err2:
+       sdio_release_host(func);
+       //complete(&sdio_wait);
+       printk(KERN_ERR "TIWLAN: SDIO failure (err %d)\n", rc);
+       return rc;
+}
+
+static void tiwlan_sdio_remove(struct sdio_func *func)
+{
+       printk(KERN_DEBUG "TIWLAN: Releasing SDIO resources\n");
+       sdio_disable_func(func);
+       sdio_release_host(func);
+       printk(KERN_DEBUG "TIWLAN: SDIO resources released\n");
+}
+
+static const struct sdio_device_id tiwlan_sdio_ids[] = {
+    { SDIO_DEVICE(VENDOR_ID_TI, DEVICE_ID_TI_WLAN) },
+    {                                              },
+};
+
+MODULE_DEVICE_TABLE(sdio, tiwlan_sdio_ids);
+
+static int tiwlan_suspend(struct device *dev)
+{
+    /*
+     * Tell MMC/SDIO core it's OK to power down the card
+     * (if it isn't already), but not to remove it completely.
+     */
+    return 0;
+}
+
+static int tiwlan_resume(struct device *dev)
+{
+    return 0;
+}
+
+static const struct dev_pm_ops tiwlan_sdio_pm_ops = {
+    .suspend        = tiwlan_suspend,
+    .resume         = tiwlan_resume,
+};
+
+static struct sdio_driver tiwlan_sdio_drv = {
+    .probe          = tiwlan_sdio_probe,
+    .remove         = tiwlan_sdio_remove,
+    .name           = "sdio_tiwlan",
+    .id_table       = tiwlan_sdio_ids,
+    .drv.pm         = &tiwlan_sdio_pm_ops,
+};
+#endif
+
 #define PANDORA_WIFI_GPIO 23
 extern void omap_mmc_fake_detect_mmc3(int is_in);
 
@@ -1524,10 +1668,12 @@ static int __init tiwlan_module_init(void)
    if (packed_struct_tst())
       ;/*IT: return -EINVAL; */
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)
    gpio_set_value(PANDORA_WIFI_GPIO, 1);
    msleep(100);
    omap_mmc_fake_detect_mmc3(1);
    msleep(100);
+#endif
 
    tiwlan_deb_entry=create_proc_entry("mem", 0644, NULL);
    if (tiwlan_deb_entry == NULL)
@@ -1535,7 +1681,16 @@ static int __init tiwlan_module_init(void)
    tiwlan_deb_entry->read_proc=tiwlan_deb_read_proc;
    tiwlan_deb_entry->write_proc=tiwlan_deb_write_proc;
 
-#ifdef TIWLAN_CARDBUS
+#ifdef USE_SDIO_DRIVER
+   {
+      int rc = 0;
+      rc = sdio_register_driver(&tiwlan_sdio_drv);
+      if (rc < 0)
+         printk(KERN_ERR "sdio register failed (%d)\n", rc);
+      /* omap1610_drv_create() called by probe */
+      return rc;
+   }
+#elif defined(TIWLAN_CARDBUS)
    {
       int rc = 0;
       if ((rc=pci_register_driver(&tnetw1130_pci_driver)) <  0)
@@ -1564,6 +1719,9 @@ static void __exit tiwlan_module_cleanup(void)
 
 #ifdef TIWLAN_CARDBUS
    pci_unregister_driver(&tnetw1130_pci_driver);
+#endif
+#ifdef USE_SDIO_DRIVER
+   sdio_unregister_driver(&tiwlan_sdio_drv);
 #endif
    list_for_each_safe(l, tmp, &tiwlan_drv_list)
    {
@@ -1572,9 +1730,12 @@ static void __exit tiwlan_module_cleanup(void)
    }
    remove_proc_entry("mem", NULL);
    printk(KERN_INFO "TI WLAN: driver unloaded\n");
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)
    gpio_set_value(PANDORA_WIFI_GPIO, 0);
    msleep(100);
    omap_mmc_fake_detect_mmc3(0);
+#endif
 }
 
 module_init(tiwlan_module_init);
index 971b779..89ee550 100644 (file)
@@ -251,7 +251,9 @@ if( !extra )
 
 int tiwlan_ioctl_init( struct net_device *dev )
 {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29))
         dev->do_ioctl       = ti1610_do_ioctl;
+#endif
 
         return 0;
 }
diff --git a/sta_dk/pform/linux/src/mmc_tnetw1150_api.c b/sta_dk/pform/linux/src/mmc_tnetw1150_api.c
new file mode 100644 (file)
index 0000000..5915f6a
--- /dev/null
@@ -0,0 +1,550 @@
+/* mmc_tnetw1150_api.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Copyright © Texas Instruments Incorporated (Oct 2005)
+ * THIS CODE/PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDED BUT NOT LIMITED TO , THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * This program has been modified from its original operation by Texas
+ * Instruments Incorporated. These changes are covered under version 2
+ * of the GNU General Public License, dated June 1991.
+ *
+ * Copyright © Google Inc (Feb 2008)
+ */
+/*-------------------------------------------------------------------*/
+#ifdef USE_SDIO_DRIVER
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include "mmc_tnetw1150_api.h"
+#include <linux/mmc/core.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+
+#define SDIO_INVALID_PERIPHERAL_ADDRESS             0x1FFFF
+
+/* CCCR                                                 0x000000 - 0x0000ff          */
+/* Function Basic Register (Function 1)                 0x000100 - 0x0001ff          */
+       /* 0x101          - Function 1 Extended standard I/O device type code        */
+       /* 0x102          - RFU[4-0] EnableHighPower Supports High-Power[1-0] SHP[0] */
+       /* 0x103 - 0x108  - RFU                                                      */
+       /* 0x109 - 0x10b  - Pointer to Function 1 Card Information Structure         */
+       /* 0x10c - 0x10e  - Pointer to Function 1 Code Storage Area                  */
+       /* 0x10f          - Data access window to Function 1 Code Storage Area       */
+       /* 0x110 - 0x111  - I/O block size for Function 1                            */
+       /* 0x112 - 0x1ff  - RFU                                                      */
+/* Function Basic Register (Function 2)                 0x000200 - 0x0002ff          */
+/* Function Basic Register (Function 3)                 0x000300 - 0x0003ff          */
+/* Function Basic Register (Function 4)                 0x000400 - 0x0004ff          */
+/* Function Basic Register (Function 5)                 0x000500 - 0x0005ff          */
+/* Function Basic Register (Function 6)                 0x000600 - 0x0006ff          */
+/* Function Basic Register (Function 7)                 0x000700 - 0x0007ff          */
+/* RFU                                                 0x000800 - 0x000fff          */
+/* CIS common and per-function area                     0x001000 - 0x017fff          */
+/* RFU                                                  0x018000 - 0x01ffff          */
+#define SDIO_FUNC1_OFFSET    0x1FFC0
+
+typedef struct
+{
+       Peripheral_Address mem_start_addr;
+       Peripheral_Address mem_part_size;
+       Peripheral_Address mem_end_addr;
+       Peripheral_Address reg_start_addr;
+       Peripheral_Address reg_part_size;
+       Peripheral_Address reg_end_addr;
+} SDIO_TNETW_partitions;
+static SDIO_TNETW_partitions TNETW_table;
+
+static SDIO_TNETWConfigParams TNETW_params;
+
+#ifdef CONFIG_MMC_TNET_INFO
+typedef struct {
+       u8  scr_space[SDIO_FUNC1_OFFSET];       /* 0x000000 - 0x01ffbf;
+                                                  131072B(128kB)-64B=131008B(0x01ffc0) */
+       u32 amap_size1;                         /* 0x01ffc0 */
+       u32 amap_offset1;                       /* 0x01ffc4 */
+       u32 amap_size2;                         /* 0x01ffc8 */
+       u32 amap_offset2;                       /* 0x01ffcc */
+       u32 amap_size3;                         /* 0x01ffd0 */
+       u32 amap_offset3;                       /* 0x01ffd4 */
+       u32 amap_offset4;                       /* 0x01ffd8 */
+       u32 cis_offset;                         /* 0x01ffdc - Card Information Structure */
+       u32 csa_offset;                         /* 0x01ffe0 - Code Storage Area */
+       u8  filler[16];                         /* 0x01ffe4 - 0x01fff3 */
+       u32 wr_err_len;                         /* 0x01fff4 */
+       u32 wr_err_addr;                        /* 0x01fff8 */
+       u32 status;                             /* 0x01fffc */
+} SDIO_FUNC1AddressMap;
+SDIO_FUNC1AddressMap mapping;
+
+int sdio_tnetw1150_dump(int count)
+{
+       unsigned long from;
+       unsigned long br_offset;
+       unsigned long offset=0;
+       unsigned long p1_offset=0;
+       unsigned long p2_offset=0;
+       struct mmc_request request;
+       int lines;
+       int i=0;
+       int second_part=0;
+
+       printk("%s:\n", __FUNCTION__);
+#define TNETW1150_OFFSET 1024
+       from=TNETW1150_OFFSET*count;
+       if((from+TNETW1150_OFFSET)>(SDIO_FUNC1_OFFSET+64))
+               return -1;
+       br_offset=TNETW1150_OFFSET*count;
+       if(br_offset>=TNETW_params.map_reg[0].reg_size) {
+               second_part=1;
+               p2_offset = SDIO_DRIVER_REG_PARTITION_START;
+               offset = TNETW_params.map_reg[1].scr_offset - TNETW_params.map_reg[0].reg_size;
+       }
+       else {
+               p1_offset += SDIO_DOWNLOAD_PARTITION_START;
+               offset = TNETW_params.map_reg[0].scr_offset;
+       }
+
+       request.cmd=SD_IO_RW_DIRECT;
+       request.buffer_len=1;
+       request.nob=0;
+       request.block_len=0;
+       request.buffer=&mapping.scr_space[from];
+    printk(" TNETW1150 try br_offset:0x%08lx offset:0x%08lx):\n", br_offset, offset);
+       do {
+               request.arg = SDIO_CMD52_READ(0,FUNCTION_SELECT_1,0,br_offset);
+               if(__submit_control_request(omap_mmc_dev_get_handle(), &request)!=SDIO_SUCCESS)
+                       return SDIO_FAILURE;
+               udelay(1);
+               *request.buffer = (char)omap_readw(OMAP_MMC_RSP6);
+               i++;
+               request.buffer++;
+               br_offset++;
+       } while(i<TNETW1150_OFFSET);
+
+    printk(" TNETW1150 SCR Address Space (start:0x%08lx  end:0x%08lx part:%d offset:0x%08lx):\n", from, from+TNETW1150_OFFSET-1, second_part+1, (!second_part)?p1_offset:p2_offset);
+
+       lines=TNETW1150_OFFSET/16;
+       for(i=0; i<lines;i++, from+=16)
+        printk("SDIO:0x%04lx(SCR:0x%04lx): %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", from, (!second_part)?(from+p1_offset):(from-p2_offset+SDIO_REG_PARTITION_START), mapping.scr_space[from], mapping.scr_space[from+1], mapping.scr_space[from+2], mapping.scr_space[from+3], mapping.scr_space[from+4], mapping.scr_space[from+5], mapping.scr_space[from+6], mapping.scr_space[from+7], mapping.scr_space[from+8], mapping.scr_space[from+9], mapping.scr_space[from+10], mapping.scr_space[from+11], mapping.scr_space[from+12], mapping.scr_space[from+13], mapping.scr_space[from+14], mapping.scr_space[from+15]);
+
+    return 0;
+}
+EXPORT_SYMBOL(sdio_tnetw1150_dump);
+
+int sdio_tnetw1150_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+    int len=0;
+       int br_offset = SDIO_FUNC1_OFFSET;
+       struct mmc_request request;
+       u8 buf[64];
+       u8 buf3[3];
+       int bytes_to_read=64;
+       int i;
+#define CCCR_SIZE 17
+       u8 buf_ccr[CCCR_SIZE];
+       u8 buf_ccr_offset[CCCR_SIZE] = {
+               CCCR_SDIO_REVISION, CCCR_SD_SPECIFICATION_REVISION, CCCR_IO_ENABLE,
+               CCCR_IO_READY, CCCR_INT_ENABLE, CCCR_INT_PENDING,
+               CCCR_IO_ABORT, CCCR_BUS_INTERFACE_CONTOROL, CCCR_CARD_CAPABILITY,
+               CCCR_COMMON_CIS_POINTER, CCCR_COMMON_CIS_POINTER+1, CCCR_COMMON_CIS_POINTER+2,
+               CCCR_BUS_SUSPEND, CCCR_FUNCTION_SELECT, CCCR_EXEC_FLAGS,
+               CCCR_READY_FLAGS, CCCR_FNO_BLOCK_SIZE,
+       };
+#define FBR_SIZE 9
+       u8 buf_fbr[FBR_SIZE];
+       u16 buf_fbr_offset[FBR_SIZE] = {
+               FBR_PTR_F1_CIS, FBR_PTR_F1_CIS+1, FBR_PTR_F1_CIS+2,
+               FBR_PTR_F1_CSA, FBR_PTR_F1_CSA+1, FBR_PTR_F1_CSA+2,
+               FBR_WIN_F1_CSA, FBR_F1_IO_BLK_SIZE, FBR_F1_IO_BLK_SIZE+1,
+       };
+
+       request.cmd=SD_IO_RW_DIRECT;
+       request.buffer_len=1;
+       request.nob=0;
+       request.block_len=0;
+       request.buffer=&buf[0];
+       for (i=0; i<bytes_to_read;i++,request.buffer++,br_offset++) {
+               request.arg = SDIO_CMD52_READ(0,FUNCTION_SELECT_1,0,br_offset);
+               if(__submit_control_request(omap_mmc_dev_get_handle(), &request)!=SDIO_SUCCESS)
+                       return SDIO_FAILURE;
+               *request.buffer = (char)omap_readw(OMAP_MMC_RSP6);
+       }
+       memcpy(&mapping.amap_size1, &buf, 64);
+
+    count -= 80; /* some reserve */
+    len += (len<count)?sprintf(page+len, " TNETW1150 partitions:\n"):0;
+    len += (len<count)?sprintf(page+len, " Memory:      "):0;
+       len += (len<count)?sprintf(page+len, " start:0x%08lx  end:0x%08lx  size:0x%08lx bytes\n", TNETW_table.mem_start_addr, TNETW_table.mem_end_addr, TNETW_table.mem_part_size):0;
+    len += (len<count)?sprintf(page+len, " Registers:   "):0;
+       len += (len<count)?sprintf(page+len, " start:0x%08lx  end:0x%08lx  size:0x%08lx bytes\n", TNETW_table.reg_start_addr, TNETW_table.reg_end_addr, TNETW_table.reg_part_size):0;
+
+    len += (len<count)?sprintf(page+len, " SDIO Function 1 Address Map:\n"):0;
+       len += (len<count)?sprintf(page+len, " amap_size1:0x%08x  amap_offset1:0x%08x\n", mapping.amap_size1, mapping.amap_offset1):0;
+       len += (len<count)?sprintf(page+len, " amap_size2:0x%08x  amap_offset2:0x%08x\n", mapping.amap_size2, mapping.amap_offset2):0;
+       len += (len<count)?sprintf(page+len, " amap_size3:0x%08x  amap_offset3:0x%08x\n", mapping.amap_size3, mapping.amap_offset3):0;
+       len += (len<count)?sprintf(page+len, "                        amap_offset4:0x%08x\n", mapping.amap_offset4):0;
+       len += (len<count)?sprintf(page+len, " cis_offset:0x%08x  csa_offset  :0x%08x\n", mapping.cis_offset, mapping.csa_offset):0;
+       len += (len<count)?sprintf(page+len, " wr_err_len:0x%08x  wr_err_addr :0x%08x\n", mapping.wr_err_len, mapping.wr_err_addr):0;
+       len += (len<count)?sprintf(page+len, " status    :0x%08x\n", mapping.status):0;
+
+       request.cmd=SD_IO_RW_DIRECT;
+       request.buffer_len=1;
+       request.nob=0;
+       request.block_len=0;
+       request.buffer=&buf_ccr[0];
+       for (i=0; i<CCCR_SIZE;i++,request.buffer++) {
+               request.arg = SDIO_CMD52_READ(0,FUNCTION_SELECT_0,0,buf_ccr_offset[i]);
+               if(__submit_control_request(omap_mmc_dev_get_handle(), &request)!=SDIO_SUCCESS)
+                       return SDIO_FAILURE;
+               *request.buffer = (char)omap_readw(OMAP_MMC_RSP6);
+       }
+
+    len += (len<count)?sprintf(page+len, "\n Card Common Control Registers:\n"):0;
+       len += (len<count)?sprintf(page+len, " \
+ REVISION             :0x%02x  SD_SPEC_REVISION       :0x%02x   IO_ENABLE            :0x%02x\n \
+ IO_READY             :0x%02x  INT_ENABLE             :0x%02x   INT_PENDING          :0x%02x\n \
+ IO_ABORT             :0x%02x  BUS_INTERFACE_CONTOROL :0x%02x   CARD_CAPABILITY      :0x%02x\n \
+ COMMON_CIS_POINTER[2]:0x%02x  COMMON_CIS_POINTER[1]  :0x%02x   COMMON_CIS_POINTER[0]:0x%02x\n \
+ BUS_SUSPEND          :0x%02x  FUNCTION_SELECT        :0x%02x   EXEC_FLAGS           :0x%02x\n \
+ READY_FLAGS          :0x%02x  FNO_BLOCK_SIZE         :0x%02x\n" , buf_ccr[0], buf_ccr[1], buf_ccr[2], buf_ccr[3], buf_ccr[4], buf_ccr[5], buf_ccr[6], buf_ccr[7], buf_ccr[8], buf_ccr[11], buf_ccr[10], buf_ccr[9], buf_ccr[12], buf_ccr[13], buf_ccr[14], buf_ccr[15], buf_ccr[16]):0;
+
+       request.cmd=SD_IO_RW_DIRECT;
+       request.buffer_len=1;
+       request.nob=0;
+       request.block_len=0;
+
+       request.buffer=&buf3[0];
+       for (i=0; i<3;i++,request.buffer++) {
+               request.arg = SDIO_CMD52_READ(0,FUNCTION_SELECT_1,0,FBR_PTR_F1_IO_DEV);
+               if(__submit_control_request(omap_mmc_dev_get_handle(), &request)!=SDIO_SUCCESS)
+                       return SDIO_FAILURE;
+               *request.buffer = (char)omap_readw(OMAP_MMC_RSP6);
+       }
+
+       request.buffer=&buf_fbr[0];
+       for (i=0; i<FBR_SIZE;i++,request.buffer++) {
+               request.arg = SDIO_CMD52_READ(0,FUNCTION_SELECT_1,0,buf_fbr_offset[i]);
+               if(__submit_control_request(omap_mmc_dev_get_handle(), &request)!=SDIO_SUCCESS)
+                       return SDIO_FAILURE;
+               *request.buffer = (char)omap_readw(OMAP_MMC_RSP6);
+       }
+
+    len += (len<count)?sprintf(page+len, "\n Function Basic Registers(Func 1):\n"):0;
+       len += (len<count)?sprintf(page+len, " \
+ Func 1 CSA enable and CSA support              :     0x%02x 0x%02x\n \
+ Func 1 Ext stand. I/O device i/f and type code :     0x%02x 0x%02x\n \
+ EHP|SHP[1]|SHP[0]                              :          0x%02x\n \
+ Pointer to Func 1 Card Information Structure   :0x%02x 0x%02x 0x%02x\n \
+ Pointer to Func 1 Code Storage Area            :0x%02x 0x%02x 0x%02x\n \
+ Data access window to Func 1 Code Storage Area :          0x%02x\n \
+ I/O block size for Func 1                      :     0x%02x 0x%02x\n", ((buf3[0]&0x80)>>7), ((buf3[0]&0x40)>>6), (buf3[1]&0x0f), buf3[1], (buf3[2]&0x07), buf_fbr[2], buf_fbr[1], buf_fbr[0], buf_fbr[5], buf_fbr[4], buf_fbr[3], buf_fbr[6], buf_fbr[8], buf_fbr[7]):0;
+
+    *eof = 1;
+    return len;
+}
+#endif /*CONFIG_MMC_TNET_STATISTICS*/
+
+
+/*
+  Initialization of TNETW memory configuration.
+*/
+extern int debug_level;
+SDIO_Status SDIO_TNETWInit(SDIO_TNETWConfigParams *params)
+{
+    /* debug_level=3;    */   
+       /* printk("%s\n", __FUNCTION__); */
+
+       memset(&TNETW_params, 0, sizeof(SDIO_TNETWConfigParams));
+
+    if(!params) {
+               /* printk("%s set to default\n", __FUNCTION__); */
+               /* set to default value in case params is not presented */
+               TNETW_params.num_of_parts = 2;
+               /* First time initialization */
+               TNETW_params.map_reg[0].reg_size = SDIO_DOWNLOAD_PARTITION_SIZE;
+               TNETW_params.map_reg[0].scr_offset = SDIO_DOWNLOAD_PARTITION_START;
+               /* After firmware has been downloaded, data memory region
+                  has to be re-initialized as following:
+               TNETW_params.map_reg[0].reg_size = SDIO_MEM_PARTITION_START;
+               TNETW_params.map_reg[0].scr_offset = SDIO_MEM_PARTITION_SIZE;
+               */
+               TNETW_params.map_reg[1].reg_size = SDIO_REG_PARTITION_SIZE;
+               TNETW_params.map_reg[1].scr_offset = SDIO_REG_PARTITION_START;
+       }
+       else {
+               /* printk("%s: params->num_of_parts=%d\n", __FUNCTION__, params->num_of_parts); */
+               /* validate input parameters */
+               switch(params->num_of_parts) {
+               case 1:
+                       if(params->map_reg[0].reg_size > AMAP_ONE_REGION)
+                               return SDIO_FAILURE;
+                       break;
+               case 2:
+                       if((params->map_reg[0].reg_size + params->map_reg[1].reg_size) > AMAP_ONE_REGION)
+                               return SDIO_FAILURE;
+                       break;
+               case 3:
+                       if((params->map_reg[0].reg_size + params->map_reg[1].reg_size + params->map_reg[2].reg_size) > AMAP_ONE_REGION)
+                               return SDIO_FAILURE;
+                       break;
+               case 4:
+                       if((params->map_reg[0].reg_size + params->map_reg[1].reg_size + params->map_reg[2].reg_size + params->map_reg[3].reg_size) > AMAP_ONE_REGION)
+                               return SDIO_FAILURE;
+                       break;
+               default:
+                       return SDIO_FAILURE;
+               }
+               memcpy(&TNETW_params, params, sizeof(SDIO_TNETWConfigParams));
+       }
+
+#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_MMC_TNET_INFO
+       create_proc_read_entry("sdio_tnetw1150", 0, NULL, sdio_tnetw1150_read_proc, NULL);
+#endif
+#endif
+
+       /* printk("%s completed\n", __FUNCTION__); */
+
+       return SDIO_SUCCESS;
+}
+
+SDIO_Status SDIO_TNETWReset(SDIO_TNETWConfigParams *params)
+{
+       /* printk("%s\n", __FUNCTION__); */
+
+       memset(&TNETW_params, 0, sizeof(SDIO_TNETWConfigParams));
+
+       if(!params) {
+               /* printk("%s set to default\n", __FUNCTION__); */
+               /* set to default value in case params is not presented */
+               TNETW_params.num_of_parts = 2;
+
+               /* After firmware has been downloaded, data memory region
+                  has to be re-initialized as following */
+               TNETW_params.map_reg[0].reg_size = SDIO_MEM_PARTITION_START;
+               TNETW_params.map_reg[0].scr_offset = SDIO_MEM_PARTITION_SIZE;
+               TNETW_params.map_reg[1].reg_size = SDIO_REG_PARTITION_SIZE;
+               TNETW_params.map_reg[1].scr_offset = SDIO_REG_PARTITION_START;
+       }
+       else {
+               /* printk("%s: params->num_of_parts=%d\n", __FUNCTION__, params->num_of_parts); */
+               /* validate input parameters */
+               switch(params->num_of_parts) {
+               case 1:
+                       if(params->map_reg[0].reg_size > AMAP_ONE_REGION)
+                               return SDIO_FAILURE;
+                       break;
+               case 2:
+                       if((params->map_reg[0].reg_size + params->map_reg[1].reg_size) > AMAP_ONE_REGION)
+                               return SDIO_FAILURE;
+                       break;
+               case 3:
+                       if((params->map_reg[0].reg_size + params->map_reg[1].reg_size + params->map_reg[2].reg_size) > AMAP_ONE_REGION)
+                               return SDIO_FAILURE;
+                       break;
+               case 4:
+                       if((params->map_reg[0].reg_size + params->map_reg[1].reg_size + params->map_reg[2].reg_size + params->map_reg[3].reg_size) > AMAP_ONE_REGION)
+                               return SDIO_FAILURE;
+                       break;
+               default:
+                       return SDIO_FAILURE;
+               }
+               memcpy(&TNETW_params, params, sizeof(SDIO_TNETWConfigParams));
+       }
+
+       /* printk("%s completed\n", __FUNCTION__); */
+
+       return SDIO_SUCCESS;
+}
+
+
+static SDIO_Status config_partition(SDIO_Handle sdioHandle, int partition_no, Peripheral_Address start_addr, SDIO_BufferLength part_size)
+{
+       struct sdio_func *func = (struct sdio_func *) sdioHandle;
+       u8 data;
+       int br_offset = SDIO_FUNC1_OFFSET + (partition_no-1)*8;
+       int i, rc;
+
+       /* printk("%s: partition_no=%d\n", __FUNCTION__, partition_no); */
+
+       /* Set size - write out 4 bytes by 4 requests */
+       if (partition_no < AMAP_MAX_REGIONS)
+       {
+               for(i=0;i<4;i++,br_offset++) {
+                       data = (part_size>>(8*i))&0xFF;
+
+                       /* put R/W Flag (1 for write); Function Number(1), RAW Flag(0),
+                          Register Address - the address of the byte of data inside
+                          of the selected function that will be written
+                          (br_offset for func1),
+                          Write Data - for a direct write command, this is the byte=data,
+                          that will be written to the selected address=br_offset).
+                       */
+                       sdio_writeb(func, data, br_offset, &rc);
+                       if (rc < 0) {
+                               printk(KERN_ERR "%s: Error writing size\n", __FUNCTION__);
+                               return SDIO_FAILURE;
+                       }
+            /* printk("%s: offset byte=%d data=0x%08x at=0x%08x\n", __FUNCTION__, i, data, br_offset); */
+               }
+
+        /* Set offset - write out 4 bytes by 4 requests */
+        for(i=0;i<4;i++,br_offset++) {
+            data = (start_addr>>(8*i))&0xFF;
+            sdio_writeb(func, data, br_offset, &rc);
+            if (rc < 0) {
+                printk(KERN_ERR "%s: Error writing offset\n", __FUNCTION__);
+                return SDIO_FAILURE;
+            }
+            /* printk("%s: offset byte=%d data=0x%08x at=0x%08x\n", __FUNCTION__, i, data, br_offset); */
+        }
+    }
+#if 0
+    if( partition_no == 2 ) {
+        unsigned long id1;
+        for(i=0,br_offset=0x1ce34;i<4;i++,br_offset++) {
+            data = sdio_readb(func, br_offset, &rc);
+            if (rc < 0) {
+                printk(KERN_ERR "%s: Error reading offset\n", __FUNCTION__);
+                return SDIO_FAILURE;
+            }
+            printk("%s: offset byte=%d data=0x%08x at=0x%08x\n", __FUNCTION__, i, data, br_offset);
+        }
+        rc = sdio_memcpy_fromio(func, &id1, 0x1ce34, 4); /* Dm: Important - DO NOT REMOVE !!! */
+        if (rc < 0) {
+            printk(KERN_ERR "%s: Error reading offset\n", __FUNCTION__);
+            return SDIO_FAILURE;
+        }
+        printk("%s: data=0x%08x at=0x%08x\n", __FUNCTION__, id1, br_offset);
+    }
+#endif
+    return SDIO_SUCCESS;
+}
+
+/*
+  This function configures the slave SDIO device for the required
+  operation mode.
+*/
+SDIO_Status SDIO_TNETWConfig(SDIO_Handle sdioHandle, Peripheral_ConfigParams **peripheral_info)
+{
+       SDIO_Status rc;
+
+       /* printk("%s\n", __FUNCTION__); */
+
+       TNETW_table.mem_start_addr = TNETW_params.map_reg[0].scr_offset;
+       TNETW_table.mem_part_size = TNETW_params.map_reg[0].reg_size;
+       TNETW_table.mem_end_addr = TNETW_table.mem_start_addr + TNETW_table.mem_part_size - 1;
+
+       TNETW_table.reg_start_addr = TNETW_params.map_reg[1].scr_offset;
+       TNETW_table.reg_part_size = TNETW_params.map_reg[1].reg_size;
+       TNETW_table.reg_end_addr = TNETW_table.reg_start_addr + TNETW_table.reg_part_size - 1;
+#if 0
+       printk("%s: memory area: start_addr=0x%08lx end_addr=0x%08lx part_size=0x%08lx\n", __FUNCTION__, TNETW_table.mem_start_addr, TNETW_table.mem_end_addr, TNETW_table.mem_part_size);
+       printk("%s: register area: start_addr=0x%08lx end_addr=0x%08lx part_size=0x%08lx\n", __FUNCTION__, TNETW_table.reg_start_addr, TNETW_table.reg_end_addr, TNETW_table.reg_part_size);
+#endif
+       /* Configure 17-bits address range in peripheral */
+       rc=config_partition(sdioHandle, 1, TNETW_table.mem_start_addr, TNETW_table.mem_part_size);
+       rc = (rc==SDIO_SUCCESS)?config_partition(sdioHandle, 2, TNETW_table.reg_start_addr, TNETW_table.reg_part_size):rc;
+
+       if(*peripheral_info)
+               *peripheral_info = (void *)&TNETW_table;
+
+    /* printk("%s: TNETW1150 partitions:\n", __FUNCTION__);
+       printk("Memory   : start:0x%08lx  end:0x%08lx  size:0x%08lx bytes\n", TNETW_table.mem_start_addr, TNETW_table.mem_end_addr, TNETW_table.mem_part_size);
+       printk("Registers: start:0x%08lx  end:0x%08lx  size:0x%08lx bytes\n", TNETW_table.reg_start_addr, TNETW_table.reg_end_addr, TNETW_table.reg_part_size);
+    */
+
+       return rc;
+}
+
+/*
+  This function performs convertion of peripheral adddress into 17 bits
+  SDIO address. If found that the memory partition configuration must be
+  changed, the memory is re-mapped in accordance to requested address.
+*/
+SDIO_Address SDIO_ConvertTNETWToSDIOMaster(Peripheral_Address in_tnetw_address, SDIO_BufferLength packet_size)
+{
+       SDIO_Address out_sdio_address;
+
+#ifdef CONFIG_SDIO_ADDRESS_MAPPING_BY_APPLICATION
+       out_sdio_address = in_tnetw_address;
+#else
+       Peripheral_Address tnetw_last_address = in_tnetw_address + packet_size - 1;
+
+       /* printk("%s:\n", __FUNCTION__); */
+
+       if ((in_tnetw_address >= TNETW_table.mem_start_addr) && (tnetw_last_address <= TNETW_table.mem_end_addr)) {
+               /* printk("%s part1 from=0x%08lx to 0x%08lx\n", __FUNCTION__, in_tnetw_address, tnetw_last_address); */
+               /* address in the 1-st partition range (data memory space) */
+               out_sdio_address = in_tnetw_address - TNETW_table.mem_start_addr;
+       }
+       else if ((in_tnetw_address >= TNETW_table.reg_start_addr) && (tnetw_last_address <= TNETW_table.reg_end_addr)) {
+               /* printk("%s part2 from=0x%08lx to 0x%08lx\n", __FUNCTION__, in_tnetw_address, tnetw_last_address); */
+               /* address in the 2-nd partition range (register memory space) */
+               out_sdio_address = in_tnetw_address - TNETW_table.reg_start_addr + TNETW_table.mem_part_size;
+       }
+       else {
+               /* printk("%s peripheral addresses from=0x%08lx to 0x%08lx is out of range\n", __FUNCTION__, in_tnetw_address, tnetw_last_address); */
+               /* invalid address */
+               return SDIO_INVALID_PERIPHERAL_ADDRESS;
+       }
+       /* printk("%s: in_tnetw_addr=0x%08lx out_sdio_addr=0x%08lx\n", __FUNCTION__, in_tnetw_address, out_sdio_address); */
+
+#endif /* CONFIG_SDIO_ADDRESS_MAPPING_BY_APPLICATION */
+
+       return out_sdio_address;
+}
+
+SDIO_Status SDIO_TNETW_Set_ELP_Reg(SDIO_Handle sdioHandle, Peripheral_Address start_addr, unsigned int data)
+{
+       struct sdio_func *func = (struct sdio_func *) sdioHandle;
+       u8 data1 = 0;
+       int br_offset = start_addr;
+       int i, rc;
+
+       /* Set size - write out 4 bytes by 4 requests */
+       for(i=0;i<1;i++,br_offset++) {
+               data1 = (data>>(8*i))&0xFF;
+
+               /* put R/W Flag (1 for write); Function Number(1), RAW Flag(0),
+                          Register Address - the address of the byte of data inside
+                          of the selected function that will be written
+                          (br_offset for func1),
+                          Write Data - for a direct write command, this is the byte=data,
+                          that will be written to the selected address=br_offset).
+               */
+               sdio_writeb(func, data1, br_offset, &rc);
+               if (rc < 0) {
+                       printk(KERN_ERR "%s: Error writing size\n", __FUNCTION__);
+                       return SDIO_FAILURE;
+               }
+       }
+       return SDIO_SUCCESS;
+}
+
+SDIO_Status SDIO_TNETW_Get_ELP_Reg(SDIO_Handle sdioHandle, Peripheral_Address start_addr, unsigned int *data)
+{
+       struct sdio_func *func = (struct sdio_func *) sdioHandle;
+       int br_offset = start_addr;
+       int rc;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
+       // 0x01 - ELPCTRL_WAKE_UP
+       *(u8*)data = sdio_writeb_readb(func, 0x01, br_offset, &rc);
+#else
+       *(u8*)data = sdio_readb_ext(func, br_offset, &rc, 0x01);
+#endif
+       if (rc) {
+               printk(KERN_ERR "%s: Error reading sdio register (%d)\n", __FUNCTION__, rc);
+               return SDIO_FAILURE;
+       }
+       return SDIO_SUCCESS;
+}
+
+#endif /* TIWLAN_MSM7000 */
diff --git a/sta_dk/pform/linux/src/tnetw_sdio.c b/sta_dk/pform/linux/src/tnetw_sdio.c
new file mode 100644 (file)
index 0000000..4d0219b
--- /dev/null
@@ -0,0 +1,237 @@
+/* tnetw_sdio.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Copyright © Texas Instruments Incorporated (Oct 2005)
+ * THIS CODE/PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDED BUT NOT LIMITED TO , THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * This program has been modified from its original operation by Texas
+ * Instruments Incorporated. These changes are covered under version 2
+ * of the GNU General Public License, dated June 1991.
+ *
+ * Copyright © Google Inc (Feb 2008)
+ */
+/*-------------------------------------------------------------------*/
+#ifdef USE_SDIO_DRIVER
+#include <linux/delay.h>
+#include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include "esta_drv.h"
+#include "mmc_omap_api.h"
+#include "osApi.h"
+#define DM_DMA_WORKAROUND
+/*-------------------------------------------------------------------*/
+extern int tiwlan_sdio_init(struct sdio_func *func);
+extern int sdio_reset_comm(struct mmc_card *card);
+/*-------------------------------------------------------------------*/
+static struct sdio_func *tiwlan_func = NULL;
+static int sdio_reset_flag = 0;
+#ifdef DM_DMA_WORKAROUND
+static void *sdio_dma_ptr = NULL;
+#endif
+/*-------------------------------------------------------------------*/
+void SDIO_SetFunc( struct sdio_func *func )
+{
+       tiwlan_func = func;
+}
+
+struct sdio_func *SDIO_GetFunc( void )
+{
+       return( tiwlan_func );
+}
+
+SDIO_Status SDIO_Init(SDIO_ConfigParams *ConfigParams, SDIO_Handle *Handle)
+{
+       if( Handle == NULL ) {
+               printk(KERN_ERR "Error: SDIO_Init() called with NULL!\n");
+               return SDIO_FAILURE;
+       }
+       *Handle = (SDIO_Handle)SDIO_GetFunc();
+       if( (*Handle) == NULL ) {
+               printk(KERN_ERR "Error: SDIO_Init() called before SDIO probe completed!\n");
+               return SDIO_FAILURE;
+       }
+#ifdef DM_DMA_WORKAROUND
+    if( !sdio_dma_ptr ) {
+        sdio_dma_ptr = kmalloc( PAGE_SIZE, GFP_KERNEL );
+        if( !sdio_dma_ptr )
+            return SDIO_FAILURE;
+    }
+#endif
+       return SDIO_SUCCESS;
+}
+
+SDIO_Status SDIO_Shutdown(SDIO_Handle Handle)
+{
+       /* printk("%s:\n", __FUNCTION__); */
+#ifdef DM_DMA_WORKAROUND
+    if( sdio_dma_ptr ) {
+        kfree( sdio_dma_ptr );
+        sdio_dma_ptr = NULL;
+    }
+#endif
+       return SDIO_SUCCESS;
+}
+
+SDIO_Status SDIO_Start(SDIO_Handle Handle)
+{
+       struct sdio_func *func = (struct sdio_func *)Handle;
+
+       /* printk("%s:\n", __FUNCTION__); */
+       if( func ) {
+               if( sdio_reset_flag ) {
+                       sdio_reset_flag = 0;
+                       if( tiwlan_sdio_init(func) ) {
+                               printk("TI: tiwlan_sdio_init Error !\n");
+                               return SDIO_FAILURE;
+                       }
+               }
+       }
+       return SDIO_SUCCESS;
+}
+
+SDIO_Status SDIO_Reset(SDIO_Handle Handle)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)
+       struct sdio_func *func = (struct sdio_func *)Handle;
+
+       /* printk("%s:\n", __FUNCTION__); */
+       if( func && func->card ) {
+               sdio_reset_comm(func->card);
+       }
+#endif
+       printk("%s:\n", __FUNCTION__);
+       return SDIO_SUCCESS;
+}
+
+SDIO_Status SDIO_Stop(SDIO_Handle Handle, unsigned long Wait_Window)
+{
+       /* printk("%s:\n", __FUNCTION__); */
+       sdio_reset_flag = 1;
+       return SDIO_Reset( Handle );
+}
+
+static int read_direct(struct sdio_func *func, unsigned char *buf, 
+                            unsigned long addr, unsigned len)
+{
+       unsigned i;
+       int rc0, rc = 0;
+
+       for(i=0;( i < len );i++,addr++) {
+               *buf++ = (unsigned char)sdio_readb(func, addr, &rc0);
+               if( rc0 != 0 )
+                       rc = rc0;
+       }
+       return rc;
+}
+
+static int write_direct(struct sdio_func *func, unsigned long addr,
+                       unsigned char *buf, unsigned len)
+{
+       unsigned i;
+       int rc0, rc = 0;
+
+       for(i=0;( i < len );i++,addr++) {
+               sdio_writeb(func, *buf++, addr, &rc0);
+               if( rc0 != 0 )
+                       rc = rc0;
+       }
+       return rc;
+}
+
+SDIO_Status SDIO_SyncRead(SDIO_Handle Handle, SDIO_Request_t *Req)
+{
+       struct sdio_func *func = (struct sdio_func *)Handle;
+       int rc, retries = 5;
+
+#if 0
+       printk("%s: p_addr = 0x%.8lx, sz = %d\n",
+              __FUNCTION__,
+              Req->peripheral_addr,
+              Req->buffer_len);
+#endif
+
+       while(retries) {
+        if( retries > 2 )
+#ifdef DM_DMA_WORKAROUND
+            if( virt_addr_valid(Req->buffer) ) {
+                rc = sdio_memcpy_fromio(func, Req->buffer, Req->peripheral_addr, Req->buffer_len);
+            }
+            else {
+                rc = sdio_memcpy_fromio(func, sdio_dma_ptr, Req->peripheral_addr, Req->buffer_len);
+                memcpy( Req->buffer, sdio_dma_ptr, Req->buffer_len );
+            }
+#else
+            rc = sdio_memcpy_fromio(func, Req->buffer, Req->peripheral_addr, Req->buffer_len);
+#endif
+        else
+            rc = read_direct(func, Req->buffer, Req->peripheral_addr, Req->buffer_len);
+
+               if (rc) {
+                       printk(KERN_ERR "%s: Read operation failed (%d) (retries = %d)\n",
+                               __FUNCTION__, rc, retries);
+                       retries--;
+                       continue;
+               }
+               if (retries != 5)
+                       printk(KERN_ERR "%s: Retry succeeded\n", __FUNCTION__);
+               return SDIO_SUCCESS;
+       }
+       printk(KERN_ERR "%s: Giving up\n", __FUNCTION__);
+       return SDIO_FAILURE;
+}
+
+SDIO_Status SDIO_SyncWrite(SDIO_Handle Handle, SDIO_Request_t *Req)
+{
+       struct sdio_func *func = (struct sdio_func *)Handle;
+       int rc, retries = 5;
+#ifdef DM_DMA_WORKAROUND
+    void *dma_ptr;
+#endif
+
+#if 0
+       printk("%s: p_addr = 0x%.8lx, sz = %d\n",
+              __FUNCTION__,
+              Req->peripheral_addr,
+              Req->buffer_len);
+#endif
+
+       while(retries) {
+        if( retries > 2 ) {
+#ifdef DM_DMA_WORKAROUND
+            if( virt_addr_valid(Req->buffer) ) {
+                dma_ptr = Req->buffer;
+            }
+            else {
+                dma_ptr = sdio_dma_ptr;
+                memcpy( dma_ptr, Req->buffer, Req->buffer_len );
+            }
+            rc = sdio_memcpy_toio(func, Req->peripheral_addr, dma_ptr, Req->buffer_len);
+#else
+            rc = sdio_memcpy_toio(func, Req->peripheral_addr, Req->buffer, Req->buffer_len);
+#endif
+        }
+        else
+            rc = write_direct(func, Req->peripheral_addr, Req->buffer, Req->buffer_len);
+
+               if (rc) {
+                       printk(KERN_ERR "%s: Write operation failed (%d) (retries = %d)\n",
+                       __FUNCTION__, rc, retries);
+                       retries--;
+                       continue;
+               }
+
+               if (retries != 5)
+                       printk(KERN_ERR "%s: Retry succeeded\n", __FUNCTION__);
+               return SDIO_SUCCESS;
+       }
+       printk(KERN_ERR "%s: Giving up\n", __FUNCTION__);
+       return SDIO_FAILURE;
+}
+#endif