diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:32:59 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:32:59 -0800 |
commit | 64064216a8433360745f69edddce19a606659163 (patch) | |
tree | 8560eb8064c57863da51b30c99e054b8123fd33c /sta_dk_4_0_4_32/pform/linux/src | |
parent | ba13e298dff123b5a281d6e2704fcdc684b324fa (diff) | |
download | ti-64064216a8433360745f69edddce19a606659163.tar.gz |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'sta_dk_4_0_4_32/pform/linux/src')
19 files changed, 7130 insertions, 0 deletions
diff --git a/sta_dk_4_0_4_32/pform/linux/src/bmtrace.c b/sta_dk_4_0_4_32/pform/linux/src/bmtrace.c new file mode 100644 index 0000000..0a6dea9 --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/bmtrace.c @@ -0,0 +1,183 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/proc_fs.h> + +#include "osApi.h" +#include "esta_drv.h" +#include "bmtrace.h" + +#define OS_READ_REG(drv,reg,p_val) \ + os_hwReadMemRegisterUINT32(drv, (UINT32 *)((unsigned long)drv->acx_reg.va + reg), p_val) + +typedef struct { + unsigned long loc;/* trace entry identification */ + unsigned long ts;/* Timestamp */ + unsigned long p1; /* Parameter 1 */ + unsigned long p2; /* Parameter 2 */ +} bm_entry_t; + +typedef struct { + int pos; + int count; + int print_pos; + int nusers; + unsigned long self_delay; + tiwlan_net_dev_t *drv; + bm_entry_t entry[1]; /* Array of entries */ +} bm_control_t; + +static bm_control_t *bm_control; + +static inline int bm_control_size(void) +{ + return offsetof(bm_control_t, entry) + sizeof(bm_entry_t)*BM_NUM_ENTRIES; +} + +static int bm_res_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int i; + int len=0; + int limit=count-80; + int entry_count; + unsigned long prev=0; + int print_pos; + + print_pos = bm_control->print_pos++; /* It will disable tracing as well */ + + entry_count = (bm_control->count > BM_NUM_ENTRIES) ? BM_NUM_ENTRIES : bm_control->count; + + /* Skip off entries */ + if ( print_pos >= entry_count) /* paranoid */ + { + bm_control->pos = bm_control->count = bm_control->print_pos = 0; + *eof = 1; + return 0; + } + + if (!off) + { + len = sprintf(page, "Events stored: %u discarded: %u\n", + entry_count, bm_control->count-entry_count); + len += sprintf(page+len, "loc delta ts p1 p2\n"); + } + + /* Initial index */ + if (bm_control->count > BM_NUM_ENTRIES) + i = (bm_control->pos+print_pos-1)%BM_NUM_ENTRIES; + else + i = bm_control->print_pos-1; + + for(; (print_pos<entry_count) && (len<=limit); print_pos++) + { + bm_entry_t *bme= &bm_control->entry[i]; + len += sprintf(page+len, + "%-3lu %-10lu %-10lu %-10lu %-10lu\n", + bme->loc, + ((bme->ts-prev)>bm_control->self_delay)?bme->ts-prev-bm_control->self_delay:0, + bme->ts, + bme->p1, bme->p2); + prev = bme->ts; + ++i; + i %= BM_NUM_ENTRIES; + } + if (print_pos >= entry_count) + { + *eof = 1; + bm_control->pos = bm_control->count = bm_control->print_pos = 0; + } + else + bm_control->print_pos = print_pos; + return len; +} + + +/* Initialization */ +int bm_init(struct tiwlan_net_dev *drv) +{ + if (bm_control) + { + ++bm_control->nusers; + return 0; + } + bm_control = (bm_control_t *)kmalloc(bm_control_size(), GFP_KERNEL); + if (!bm_control) + return -ENOMEM; + memset(bm_control, 0, offsetof(bm_control_t, entry) + sizeof(bm_entry_t)*BM_NUM_ENTRIES); + bm_control->nusers = 1; + bm_control->drv = drv; + + create_proc_read_entry("bmtrace", 0, NULL, bm_res_read_proc, NULL); + /* Measure self-delay */ + bm_trace(0, 0, 0); + bm_trace(0, 0, 0); + bm_control->self_delay = bm_control->entry[1].ts - bm_control->entry[0].ts; + bm_control->pos = bm_control->count = 0; + print_info("%s: self_delay=%lu\n", __FUNCTION__, bm_control->self_delay); + return 0; +} + +/* De-initialization */ +void bm_destroy(void) +{ + if (--bm_control->nusers) + return; + remove_proc_entry("bmtrace", NULL); + kfree( bm_control ); +} + + +/* Add trace entry. not safe, but will do */ +void bm_trace(int loc, unsigned long p1, unsigned long p2) +{ + int pos; + if (!bm_control || bm_control->print_pos) + return; + pos = bm_control->pos; + bm_control->pos = (pos+1) % BM_NUM_ENTRIES; + ++bm_control->count; + + bm_control->entry[pos].ts = os_timeStampUs(NULL); + bm_control->entry[pos].loc= loc; + bm_control->entry[pos].p1 = p1; + bm_control->entry[pos].p2 = p2; +} + diff --git a/sta_dk_4_0_4_32/pform/linux/src/chip_stat.c b/sta_dk_4_0_4_32/pform/linux/src/chip_stat.c new file mode 100755 index 0000000..531c055 --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/chip_stat.c @@ -0,0 +1,176 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/version.h> + +#include "mmc_tnetw1150_api.h" +#include "esta_drv.h" +#include "srcApi.h" +#include "osApi.h" +#include "whalHwRegs.h" + +#include "tiwlnif.h" +#include "osUtil.h" + +#ifdef TIWLAN_MSM7000 +struct sdio_func *SDIO_GetFunc( void ); +#endif + +/* Module parameters */ +static char tiwlan_chip_id[10] = "na"; +module_param_string(chip_id, tiwlan_chip_id, sizeof(tiwlan_chip_id), S_IWUSR | S_IRUGO); +MODULE_PARM_DESC(tiwlan_chip_id, "WiFi chip id"); +static char fw_version[10] = "na"; +module_param_string(fw_version, fw_version, sizeof(fw_version), S_IWUSR | S_IRUGO); +MODULE_PARM_DESC(fw_version, "WiFi firmware version"); + +/* export_wifi_fw_version + Exports WiFi firmware version to /sys/module/wlan/parameters/fw_version + Returns 0 if OK +*/ +int export_wifi_fw_version( tiwlan_net_dev_t *drv ) +{ + TIWLN_VERSION swVer; + unsigned long swLen; + int ret; + + if (!drv) + return -EINVAL; + + swLen = sizeof(swVer); + memset(&swVer, 0, swLen); + ret = UtilGetSwVersion(&drv->adapter, (unsigned char *)&swVer, &swLen); + if (ret != 0) + return -EINVAL; + + fw_version[0] = swVer.FWVersion.major + 48; + fw_version[1] = '.'; + fw_version[2] = swVer.FWVersion.minor + 48; + fw_version[3] = '.'; + fw_version[4] = swVer.FWVersion.bugfix + 48; + fw_version[5] = '.'; + fw_version[6] = swVer.FWVersion.subld + 48; + fw_version[7] = '.'; + fw_version[8] = swVer.FWVersion.build + 48; + fw_version[9] = '\0'; + return ret; +} + +/* print_wifi_chip_id + Reads WiFi chip id (0x07030101) and prints it + Returns 0 if OK +*/ +int export_wifi_chip_id( void ) +{ + unsigned char chip_id[4]; + unsigned long amap; +#ifdef TIWLAN_MSM7000 + SDIO_Request_t req; + struct sdio_func *func; + + func = SDIO_GetFunc(); + if (!func) + return -EINVAL; + + /* configure partition */ + amap = SDIO_DOWNLOAD_PARTITION_START; + req.buffer = (unsigned char *)&amap; + req.buffer_len = 4; + req.peripheral_addr = 0x1ffc4; + SDIO_SyncWrite(func, &req); + + amap = SDIO_DOWNLOAD_PARTITION_SIZE; + req.buffer = (unsigned char *)&amap; + req.buffer_len = 4; + req.peripheral_addr = 0x1ffc0; + SDIO_SyncWrite(func, &req); + + amap = SDIO_REG_PARTITION_START; + req.buffer = (unsigned char *)&amap; + req.buffer_len = 4; + req.peripheral_addr = 0x1ffcc; + SDIO_SyncWrite(func, &req); + + amap = SDIO_REG_PARTITION_SIZE; + req.buffer = (unsigned char *)&amap; + req.buffer_len = 4; + req.peripheral_addr = 0x1ffc8; + SDIO_SyncWrite(func, &req); + + /* get TIWLAN1251 ID */ + memset(chip_id, 0, 4); + req.buffer = chip_id; + req.buffer_len = 4; + req.peripheral_addr = SDIO_DOWNLOAD_PARTITION_SIZE + CHIP_ID; /* 0x1BE74 */ + SDIO_SyncRead(func, &req); +#endif +#ifdef TIWLAN_OMAP1610 + /* Can not be read on this stage - SDIO stack is not initialized yet */ + amap = TNETW1251_CHIP_ID_PG1_2; + memcpy(chip_id, &amap, 4); +#endif + + if ((chip_id[2] >= 1) && (chip_id[2] <= 3)){ + tiwlan_chip_id[0] = '1'; + tiwlan_chip_id[1] = '2'; + tiwlan_chip_id[2] = '5'; + tiwlan_chip_id[3] = '1'; + tiwlan_chip_id[4] = 'P'; + tiwlan_chip_id[5] = 'G'; + tiwlan_chip_id[6] = '1'; + tiwlan_chip_id[7] = '.'; + } + switch(chip_id[2]){ + case 1: + tiwlan_chip_id[8] = '0'; + printk("TIWLAN: 1251 PG 1.0\n"); + break; + case 2: + tiwlan_chip_id[8] = '1'; + printk("TIWLAN: 1251 PG 1.1\n"); + break; + case 3: + tiwlan_chip_id[8] = '2'; + printk("TIWLAN: 1251 PG 1.2\n"); + break; + default: + printk("TIWLAN: invalid chip id = 0x%2x%2x%2x%2x!\n", + chip_id[3], chip_id[2], chip_id[1], chip_id[0]); + return -EINVAL; + }; + return 0; +} diff --git a/sta_dk_4_0_4_32/pform/linux/src/env_tst.c b/sta_dk_4_0_4_32/pform/linux/src/env_tst.c new file mode 100644 index 0000000..2c5ddf6 --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/env_tst.c @@ -0,0 +1,106 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + + +#include <linux/errno.h> +#include <linux/string.h> + +#include "arch_ti.h" +#include "osTIType.h" +#include "osApi.h" +#include "ioctl_init.h" + +#include "802_11Defs.h" +#include "mlmeApi.h" + +/****************************************************************************/ +/* */ +/* Definition of Constants */ +/* */ +/****************************************************************************/ +#define SIZEOF_DOT11_MGMT_HEADER 0x18 +#define SIZEOF_MLME_FRAME_INFO 0x60 +#ifdef EXC_MODULE_INCLUDED +#define SIZEOF_BEACON_FRM 0x57 +#else +#define SIZEOF_BEACON_FRM 0x53 +#endif +#define SIZEOF_ELEMENT_HDR 0x02 +#define SIZEOF_MGMT_FRAME 0x920 +#define SIZEOF_ASSOC_RSP_TYPE 0x26 +#define SIZEOF_AUTH_MSG_TYPE 0x0a +#define SIZEOF_DEATUH_MSG_TYPE 0x02 +#define SIZEOF_DISASSOC_MSG_TYPE 0x02 + +#define CHECK_STRUCT_SIZE(_type,_size) \ +{ \ + if (sizeof(_type) != _size) \ + { \ + print_info(KERN_INFO"\n.... ERROR in size of %s struct 0x%08x should be 0x%08x.....\n", \ + #_type, (int)sizeof(_type),(int)_size); \ + rc = -EINVAL; \ + } \ +} + +/************************************************************************ + * packed_strct_tst * + ************************************************************************ +DESCRIPTION: Used to test structures for the correct packed size + +INPUT: Void + +OUTPUT: Print Debug statements if the structures are not the expected size + +RETURN: 0=success + -EINVAL - failure + +************************************************************************/ +int packed_struct_tst (void) +{ + int rc = 0; + print_info("\nTIWLAN: Testing sizes of packed structures...\n"); + CHECK_STRUCT_SIZE(dot11_mgmtHeader_t, SIZEOF_DOT11_MGMT_HEADER); + CHECK_STRUCT_SIZE(dot11_eleHdr_t, SIZEOF_ELEMENT_HDR); + CHECK_STRUCT_SIZE(beacon_probeRsp_t, SIZEOF_BEACON_FRM); + CHECK_STRUCT_SIZE(assocRsp_t, SIZEOF_ASSOC_RSP_TYPE ); + CHECK_STRUCT_SIZE(authMsg_t, SIZEOF_AUTH_MSG_TYPE); + CHECK_STRUCT_SIZE(deAuth_t, SIZEOF_DEATUH_MSG_TYPE); + CHECK_STRUCT_SIZE(disAssoc_t, SIZEOF_DISASSOC_MSG_TYPE); + CHECK_STRUCT_SIZE(dot11_mgmtFrame_t, SIZEOF_MGMT_FRAME); + CHECK_STRUCT_SIZE(mlmeFrameInfo_t,SIZEOF_MLME_FRAME_INFO); + print_info("TIWLAN: packet structure size test %s\n", rc?"failed":"passed"); + + return rc; +} diff --git a/sta_dk_4_0_4_32/pform/linux/src/esta_drv.c b/sta_dk_4_0_4_32/pform/linux/src/esta_drv.c new file mode 100644 index 0000000..a802b35 --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/esta_drv.c @@ -0,0 +1,2060 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/version.h> +#include <net/sock.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/netdevice.h> +#include <linux/ioctl.h> +#include <linux/wireless.h> +#include <linux/etherdevice.h> +#include <linux/netlink.h> +#include <linux/completion.h> + +#ifdef TIWLAN_CARDBUS +#include <linux/pci.h> +#else +#ifdef TIWLAN_OMAP1610 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) +#include <asm/arch-omap/tc.h> +#else +#include <mach/tc.h> +#endif +#endif +#ifdef TIWLAN_MSM7000 +#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(2,6,27) +#include <asm/arch/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/irqs.h> +#else +#include <mach/io.h> +#include <mach/hardware.h> +#include <mach/irqs.h> +#endif +#endif /* !TIWLAN_CARDBUS */ + +#include <linux/list.h> +#include <linux/spinlock.h> +#include <linux/if_arp.h> +#include <linux/proc_fs.h> +#include <linux/mm.h> +#include <linux/delay.h> +#include <linux/vmalloc.h> +#include <linux/irq.h> + +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/pgtable.h> + +#include "esta_drv.h" +#include "srcApi.h" +#include "osApi.h" +#include "whalHwRegs.h" + +#if defined(DEBUG_UNKNOWN_INTERRUPT) +#define _STRING_H +#include "configMgr.h" +#include "whalCtrl.h" +#endif + +#include "bmtrace.h" +#include "osrgstry_parser.h" +#include "osClsfr.h" +#include "TI_IPC_Api.h" +#include "802_11Defs.h" +#include "Ethernet.h" +#include "tiwlan_profile.h" + +#if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK) +#define RX_RATE_INTERVAL_SEC 10 +unsigned long num_rx_pkt_new = 0; +static unsigned long num_rx_pkt_last = 0; +#endif + +#ifdef TIWLAN_MSM7000 +extern unsigned char *get_wifi_nvs_ram(void); +extern void SDIO_SetFunc( struct sdio_func * ); +static struct proc_dir_entry *tiwlan_calibration; +static struct completion sdio_wait; +#ifdef CONFIG_WIFI_CONTROL_FUNC +static struct wifi_platform_data *wifi_control_data = NULL; +#endif +#endif + +/* WiFi chip information functions */ +int export_wifi_fw_version( tiwlan_net_dev_t *drv ); +int export_wifi_chip_id( void ); + +/* Drivers list */ +static LIST_HEAD(tiwlan_drv_list); + +/* debug memory access */ +static struct proc_dir_entry *tiwlan_deb_entry; +static __u32 memdebug_addr; +static __u32 memdebug_size=1; +static __u32 memdebug_trans_size; + +#define DRV_SHUTDOWN_TEST_DELAY_INTERVAL 100 /* Time in msec to "delay"(/sleep) while waiting for SME to shutdown */ +#define DRV_SHUTDOWN_TEST_MAX_COUNTER 20 /* How many delay/sleep iterations to perform while waiting for SME to shutdown) */ + +MODULE_DESCRIPTION("TI WLAN Embedded Station Driver"); +MODULE_LICENSE("GPL"); + +extern int packed_struct_tst(void); +extern int proc_stat_init(TI_HANDLE); +extern int proc_stat_destroy(void); + +typedef void (* tiwlan_drv_isr_t)(int, void *, struct pt_regs *); + +/* network device driver interface */ +static int tiwlan_drv_net_open(struct net_device * dev); +static int tiwlan_drv_net_stop(struct net_device * dev); +static int tiwlan_drv_net_xmit(struct sk_buff * skb, struct net_device * dev); +static struct net_device_stats * tiwlan_drv_net_get_stats(struct net_device * dev); + +#define OS_WRITE_REG(drv,reg,val) \ + os_hwWriteMemRegisterUINT32(drv, (UINT32 *)((unsigned long)drv->acx_reg.va + reg), (__u32)(val)) + +#define OS_READ_REG(drv,reg,val) \ + os_hwReadMemRegisterUINT32(drv, (UINT32 *)((unsigned long)drv->acx_reg.va + reg), &val) + +#ifdef TIWLAN_OMAP1610 +static void omap_memif_init(void) +{ + printk ("First function offset is: %p\n", omap_memif_init); +#if defined(TIWLAN_OMAP1610_INNOVATOR) + print_info("Setting CS1 Ref Clock = TC/4. \n"); + omap_writel(0x00000004, 0xFFFECC40 ); /* wlan change for cs2 to dynamic wait state */ + omap_writel(0x0000113a, 0xFFFECC18 ); /* EMIFS (nCS2) configuration */ +#elif defined(TIWLAN_OMAP1610_WIPP) || defined(TIWLAN_OMAP1610_CRTWIPP) + +#if defined(TIWLAN_OMAP1610_CRTWIPP) + /* + Init the GPIO to output*/ + + /* Set OMAP pin H19 to GPIO57*/ + + omap_writel(omap_readl(0xFFFE1014) | 0x00E00000, 0xFFFE1014 ); + + /*ELP_REQ (GPIO_57) by GPIO_DIRECTION - set it as output*/ + omap_writel(omap_readl(0xFFFBBC34) & (~0x00000200), 0xFFFBBC34 ); +#endif /* TIWLAN_OMAP1610_CRTWIPP */ + +/* The below configuration enables GPIO25 and GPIO_27 as output GPIOs - for debug purposes */ +#if defined(TIWLAN_OMAP1610_CRTWIPP_GPIO_DEBUG) + + omap_writel(omap_readl(0xFFFE1030) | 0x00000E00, 0xFFFE1030 );/* enable GPIO25 */ + omap_writel(omap_readl(0xFFFE1030) | 0x00000038, 0xFFFE1030 );/* enable GPIO27 */ + + omap_writel(omap_readl(0xFFFBEC34) & (~0x00000200), 0xFFFBEC34 );/* Setting direction (as output) for GPIO25 */ + omap_writel(omap_readl(0xFFFBEC34) & (~0x00000800), 0xFFFBEC34 );/* Setting direction (as output) for GPIO27 */ +#endif /* TIWLAN_OMAP1610_CRTWIPP_GPIO_DEBUG */ + + + /* RECOVERY*/ + print_info("Hard reset,perform PMEN toggle\n"); + os_hardResetTnetw(); + + print_info("Setting CS2 Ref Clock = TC/2. \n"); + __raw_writel(0x1, TIWLAN_OMAP1610_REGBASE+0x4cc); /* CLK=80MHz */ + omap_writel(0x20, EMIF_CFG_DYNAMIC_WS); /* Full handshake on CS2 */ + omap_writel(0x2441, EMIFS_CS2_CONFIG); /* 0x2021 on reworked board */ + omap_writel(0, EMIFS_ACS2); + + print_info("%x=0x%lx\n", 0xFFFECC40, omap_readl(0xFFFECC40) ); + print_info("%x=0x%lx\n", 0xFFFECC18, omap_readl(0xFFFECC18) ); + print_info("%x=0x%lx\n", 0xFFFECC58, omap_readl(0xFFFECC58) ); +#endif /* WIPP, CRTWIPP */ +} +#endif + +static int tiwlan_register_events(tiwlan_net_dev_t *drv) +{ + IPC_EVENT_PARAMS evParams; + int i = 0; + + evParams.uDeliveryType = DELIVERY_PUSH; + evParams.uProcessID = 0; + evParams.uEventID = 0; + evParams.hUserParam = drv; + evParams.pfEventCallback = os_IndicateEvent; + + + for (;i < IPC_EVENT_MAX_OS_EVENT;i++) + { + evParams.uEventType = i; + + configMgr_RegisterEvent(drv->adapter.CoreHalCtx,(PUCHAR) &evParams,sizeof(IPC_EVENT_PARAMS)); + } + + return OK; +} + +static int tiwlan_deb_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + __u32 addr=memdebug_addr; + __u32 size=memdebug_size; + __u32 trans_size=memdebug_trans_size; + __u32 end; + int in_line=0, max_in_line; + int limit=count-80; + int i=0; + static int toggle; + + *eof = 1; + if (!addr || !trans_size) + return 0; + + /* fixme: add address validation */ + + if (!size) + size=1; + + end = addr + size*trans_size; + if (trans_size==4) + max_in_line = 4; + else if (trans_size==2) + max_in_line = 8; + else + max_in_line = 16; + + while(i<limit && addr<end) + { + if (!in_line) + i += sprintf(page+i, "0x%08x: ", addr); + if (trans_size==4) + { + i += sprintf(page+i, "0x%08x", *(__u32 *)addr); + addr += 4; + } + else if (trans_size==2) + { + i += sprintf(page+i, "0x%04x", *(__u16 *)addr); + addr += 2; + } + else + { + i += sprintf(page+i, "0x%02x", *(__u8 *)addr); + addr += 1; + } + if (++in_line < max_in_line) + *(page+i++)=' '; + else + { + *(page+i++)='\n'; + in_line = 0; + } + } + *(page+i++)='\n'; + /* For some reason read proc is get called twice for + each "cat" operation + */ + if (toggle) + memdebug_addr = addr; + toggle = !toggle; + + return i; +} + +static char *rm_get_token(const char **p_buffer, unsigned long *p_buffer_len, + char *token, unsigned long token_len, + char del) +{ + const char *buffer=*p_buffer; + __u32 buffer_len = *p_buffer_len; + + while(buffer_len && token_len && *buffer!=del && *buffer) + { + *token++ = *buffer++; + --buffer_len; + --token_len; + } + while (buffer_len && *buffer==del) + { + ++buffer; + --buffer_len; + } + *token = 0; + *p_buffer = buffer; + *p_buffer_len = buffer_len; + return token; +} + +static int tiwlan_deb_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + __u32 addr, size; + char token[15]; + __u32 value; + char *end; + int buflen=count; + + /* buffer format is: + d{w,h,b} addr[/size] + s{w,h,b} addr=value + */ + /* Parse string */ + rm_get_token(&buffer, &count, token, sizeof(token)-1, ' '); + if (token[0]=='d') + { + /* Display */ + if (!strcmp(token, "dw")) + memdebug_trans_size = 4; + else if (!strcmp(token, "dh")) + memdebug_trans_size = 2; + else if (!strcmp(token, "db")) + memdebug_trans_size = 1; + else + { + printk(KERN_INFO "rm: mem file write op is dw|dh|db|sw|sh|sb\n"); + return buflen; + } + /* Get address */ + rm_get_token(&buffer, &count, token, sizeof(token)-1, '/'); + addr = simple_strtoul(token, &end, 0); + if ((end && *end) /* || !iopa(addr)*/) + { + printk(KERN_INFO "rm: address <%s> is invalid\n", token); + return buflen; + } + if ((addr & (memdebug_trans_size-1))) + { + printk(KERN_INFO "rm: warning: address 0x%x is not aligned to size %u\n", + addr, memdebug_trans_size); + } + memdebug_addr = addr; + if (count) + { + /* Get size */ + rm_get_token(&buffer, &count, token, sizeof(token)-1, ' '); + size = simple_strtoul(token, &end, 0); + if (end && *end) + { + printk(KERN_INFO "rm: size <%s> is invalid. end=<%s>\n", + token, end); + return buflen; + } + memdebug_size = size; + } + return buflen; + } + if (token[0]=='s') + { + /* Display */ + if (!strcmp(token, "sw")) + size = 4; + else if (!strcmp(token, "sh")) + size = 2; + else if (!strcmp(token, "sb")) + size = 1; + else + { + printk(KERN_INFO "rm: mem file write op is dw|dh|db|sw|sh|sb\n"); + return buflen; + } + /* Get address */ + rm_get_token(&buffer, &count, token, sizeof(token)-1, ' '); + addr = simple_strtoul(token, &end, 0); + if ((end && *end) /*|| !iopa(addr)*/) + { + printk(KERN_INFO "rm: address <%s> is invalid\n", token); + return buflen; + } + if ((addr & (size-1))) + { + printk(KERN_INFO "rm: warning: address 0x%x is not aligned to size %u\n", + addr, size); + } + + /* Get value */ + rm_get_token(&buffer, &count, token, sizeof(token)-1, ' '); + value = simple_strtoul(token, &end, 0); + if (end && *end) + { + printk(KERN_INFO "rm: value <%s> is invalid. end <%s>\n", + token, end); + return buflen; + } + if (size==4) + *(__u32 *)addr = value; + else if (size==2) + { + if (value > 0xffff) + { + printk(KERN_INFO "rm: value <%s> is out of range\n", token); + return buflen; + } + *(__u16 *)addr = value; + } + else + { + if (value > 0xff) + { + printk(KERN_INFO "rm: value <%s> is out of range\n", token); + return buflen; + } + *(__u8 *)addr = value; + } + memdebug_addr = addr; + memdebug_size = 1; + memdebug_trans_size = size; + } + else + printk(KERN_INFO "rm: operation <%s> is not supported\n", token); + return buflen; +} + +#ifdef TIWLAN_MSM7000 +#define WIFI_NVS_LEN_OFFSET 0x0C +#define WIFI_NVS_DATA_OFFSET 0x40 +#define WIFI_NVS_MAX_SIZE 0x800UL + +static unsigned long tiwlan_get_nvs_size( void ) +{ + unsigned char *ptr; + unsigned long len; + + ptr = get_wifi_nvs_ram(); + if( ptr == NULL ) { + return 0; + } + /* Size in format LE assumed */ + memcpy( (void *)&len, (void *)(ptr + WIFI_NVS_LEN_OFFSET), sizeof(len) ); + len = min( len, (WIFI_NVS_MAX_SIZE-WIFI_NVS_DATA_OFFSET) ); + return len; +} + +static int tiwlan_calibration_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + unsigned char *ptr; + unsigned long len; + + ptr = get_wifi_nvs_ram(); + if( ptr == NULL ) { + return 0; + } + len = tiwlan_get_nvs_size(); + /* i += sprintf(page+i, "WiFi Calibration Size = %lu %x bytes\n", len); */ + memcpy( (void *)page, (void *)(ptr + WIFI_NVS_DATA_OFFSET), len ); + return len; +} + +static int tiwlan_calibration_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + return 0; +} +#endif + +/*********************************************************************************************/ +/* Impelementation */ +/*********************************************************************************************/ + +static int tiwlan_drv_net_open(struct net_device * dev) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)dev->priv; + + ti_nodprintf(TIWLAN_LOG_INFO, "tiwlan_drv_net_open()\n"); + + if (!drv->adapter.CoreHalCtx) + return -ENODEV; + + netif_start_queue(dev); + + return 0; +} + + +static int tiwlan_drv_net_stop(struct net_device * dev) +{ + ti_nodprintf(TIWLAN_LOG_ERROR, "tiwlan_drv_net_stop()\n"); + + netif_stop_queue(dev); + + return 0; +} + + +/* dummy send packet from Linux TCP/IP stack to WLAN + Used when driver is not initialized + */ +static int tiwlan_drv_dummy_net_xmit(struct sk_buff *skb, struct net_device *dev) +{ + /* Network stack takes care of deallocation */ + return -ENODEV; +} + +void sendFreeFunc(TI_HANDLE pSkb, TI_HANDLE dummy1, TI_STATUS status) +{ + struct sk_buff *skb = (struct sk_buff *) pSkb; + + /* print_deb("^^^ free %p %d bytes (%s)\n", skb->data, skb->len, (status==OK) ? "OK" : "ERROR" ); */ + dev_kfree_skb(skb); +} + +#ifdef DM_USE_WORKQUEUE +void tiwlan_add_msdu(tiwlan_net_dev_t *drv, mem_MSDU_T *pMsdu) +{ + if( pMsdu == NULL ) + return; + pMsdu->msdu_next = NULL; + if( drv->txmit_msdu_next != NULL ) { + drv->txmit_msdu_last->msdu_next = pMsdu; + } + else { + drv->txmit_msdu_next = pMsdu; + } + drv->txmit_msdu_last = pMsdu; +} + +mem_MSDU_T *tiwlan_del_msdu(tiwlan_net_dev_t *drv) +{ + mem_MSDU_T *pMsdu = NULL; + + if( drv->txmit_msdu_next != NULL ) { + pMsdu = drv->txmit_msdu_next; + drv->txmit_msdu_next = pMsdu->msdu_next; + if( drv->txmit_msdu_next == NULL ) { /* Last MSDU */ + drv->txmit_msdu_last = NULL; + } + } + return( pMsdu ); +} + +static void tiwlan_xmit_handler( struct work_struct *work ) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( work, struct tiwlan_net_dev, txmit ); + mem_MSDU_T *pMsdu; + unsigned long flags; + + /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */ + do { + spin_lock_irqsave(&drv->lock, flags); + pMsdu = tiwlan_del_msdu(drv); + spin_unlock_irqrestore(&drv->lock, flags); + if( pMsdu ) { + configMgr_sendMsdu(drv->adapter.CoreHalCtx, pMsdu, 0); + } + } while( pMsdu != NULL ); +#ifdef CONFIG_ANDROID_POWER + android_unlock_suspend( &drv->xmit_wake_lock ); +#endif +} +#endif + +/* send packet from Linux TCP/IP stack to WLAN + */ +static int tiwlan_drv_net_xmit(struct sk_buff *skb, struct net_device *dev) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)dev->priv; + int status; + mem_MSDU_T *pMsdu; + UINT32 packetHeaderLength; + +#ifndef NO_COPY_SKB + char *pMsduData; +#else + mem_BD_T *pCurBd=0; +#endif + +#ifdef DRIVER_PROFILE + os_profile (drv, 0, 0); +#endif + bm_trace(20, skb->len, 0); + +#ifdef NO_COPY_SKB + + status = configMgr_allocMSDUBufferOnly(drv->adapter.CoreHalCtx, &pMsdu, OS_ABS_TX_MODULE); + if(status != OK) + { + ti_dprintf(TIWLAN_LOG_ERROR, " configMgr_allocMSDUBufferOnly failed !!!\n"); + ++drv->alloc_msdu_failures; + return -ENOMEM; + } + /* print_deb("$$$ configMgr_allocMSDUBufferOnly()=OK pMsdu=%p\n", pMsdu ); */ + + status = configMgr_allocBDs(drv->adapter.CoreHalCtx, 1, &pCurBd); + + if(status != OK) { + ++drv->alloc_msdu_failures; + ti_dprintf(TIWLAN_LOG_ERROR, " configMgr_allocBDs failed !!!\n"); + configMgr_memMngrFreeMSDU(drv->adapter.CoreHalCtx, pMsdu->handle); + return -ENOMEM; + } + /* print_deb("$$$ configMgr_allocBDs()=OK pCurBd=%p first=%p\n", pCurBd, pMsdu->firstBDPtr ); */ + + pMsdu->freeFunc = sendFreeFunc; + pMsdu->freeArgs[0] = (UINT32) skb; + pMsdu->dataLen = skb->len; + pMsdu->firstBDPtr = pCurBd; + pCurBd->dataOffset = skb->data-skb->head; + pCurBd->length = skb->len; + pCurBd->data = skb->head; + + drv->stats.tx_packets++; + drv->stats.tx_bytes += skb->len; + +#else /* NO_COPY_SKB */ + + /* + * Retrieve the Packet Header length + * from QoS Manager (through configMgr) + * (Header type is determined upon association) + */ + packetHeaderLength = configMgr_getPacketHeaderLength(drv->adapter.CoreHalCtx,skb->data,TX_DATA_DATA_MSDU); + + /* + * need to reserve enough space for header translation + * in the same first Bd. + * Allocate enough place also for 802.11 header (24 bytes or 26 for QoS) and LLC (8 bytes) + * to replace the Ethernet header (14 bytes) + */ + status = configMgr_allocMSDU(drv->adapter.CoreHalCtx, &pMsdu, + skb->len + packetHeaderLength, OS_ABS_TX_MODULE); + + if(status != OK) + { + /*ti_dprintf(TIWLAN_LOG_ERROR, " configMgr_allocMSDU failed !!!\n");*/ + ++drv->alloc_msdu_failures; + return -ENOMEM; + } + + /* + * case 1: only legacy wlan header + * + * case 2: only QoS wlan header + * + * case 3: only legacy wlan header with new snap + * + * case 4: only QoS wlan header with new snap + */ + pMsdu->firstBDPtr->dataOffset = packetHeaderLength - ETHERNET_HDR_LEN; + pMsduData = pMsdu->firstBDPtr->data + pMsdu->firstBDPtr->dataOffset; + memcpy(pMsduData, skb->data, skb->len); + pMsdu->dataLen = skb->len; + pMsdu->firstBDPtr->length = pMsdu->dataLen + pMsdu->firstBDPtr->dataOffset; + + drv->stats.tx_packets++; + drv->stats.tx_bytes += skb->len; + dev_kfree_skb(skb); +#endif /* NO_COPY_SKB */ + + pMsdu->txFlags |= TX_DATA_FROM_OS; + pMsdu->qosTag = 0; + status = OK; + +#ifdef TI_DBG + /* Set packet-os-in time stamp */ + /* TODO: the skb time stamp is not good */ + /* printk ("\n### sec=%u, usec=%u", skb->stamp.tv_sec, skb->stamp.tv_usec);*/ + /* pMsdu->timeStamp[0] = skb->stamp.tv_sec * 1000000 + skb->stamp.tv_usec; */ + /* pMsdu->timeStampNum = 1; */ +#endif + + bm_trace(21, 0, 0); + /* + * Propagate Msdu through Config Manager. + * Set DTag to zero + * (note that classification is further handled in the Core) + */ + if (status == OK) { +#ifdef DM_USE_WORKQUEUE + unsigned long flags; + + spin_lock_irqsave(&drv->lock, flags); + tiwlan_add_msdu(drv, pMsdu); + spin_unlock_irqrestore(&drv->lock, flags); + /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */ + if( queue_work( drv->tiwlan_wq, &drv->txmit ) != 0 ) { +#ifdef CONFIG_ANDROID_POWER + android_lock_suspend( &drv->xmit_wake_lock ); +#endif + } +#else + status = configMgr_sendMsdu(drv->adapter.CoreHalCtx, pMsdu, 0); +#endif + } + else + configMgr_memMngrFreeMSDU (drv->adapter.CoreHalCtx, (UINT32) pMsdu); /* If status != OK , we won't send the MSDU, so we need to free it */ + + if(unlikely(status != OK)) + { + drv->stats.tx_errors++; +#ifdef NO_COPY_SKB + dev_kfree_skb(skb); +#endif + } + + bm_trace(22, 0, 0); +#ifdef DRIVER_PROFILE + os_profile (drv, 1, 0); +#endif + + return 0; +} + +struct net_device_stats * tiwlan_drv_net_get_stats(struct net_device * dev) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)dev->priv; + ti_dprintf(TIWLAN_LOG_OTHER, "tiwlan_drv_net_get_stats()\n"); + + return &drv->stats; +} + + +static int setup_netif(tiwlan_net_dev_t *drv) +{ + struct net_device *dev; + int res; + + dev = alloc_etherdev(0); + if (dev == NULL) + { + ti_dprintf(TIWLAN_LOG_ERROR, "alloc_etherdev() failed\n"); + return -ENOMEM; + } + ether_setup(dev); + dev->priv = drv; + drv->netdev = dev; + strcpy(dev->name, TIWLAN_DRV_IF_NAME); + netif_carrier_off(dev); + 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; + dev->tx_queue_len = 100; + + res = tiwlan_ioctl_init(dev); + if( res < 0 ) + { + ti_dprintf(TIWLAN_LOG_ERROR, "tiwlan_ioctl_init() failed : %d\n", res); + kfree(dev); + return res; + } + + res = register_netdev(dev); + if (res != 0) + { + ti_dprintf(TIWLAN_LOG_ERROR, "register_netdev() failed : %d\n", res); + kfree(dev); + return res; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + SET_MODULE_OWNER(dev); +#endif + return 0; +} + + +/* tiwlan_interrupt + TIWLAN interrupt handler. Disables interrupts and awakes tasklet. +*/ +#if !(defined(HW_ACCESS_SDIO)||defined(HW_ACCESS_WSPI)) +static irqreturn_t tiwlan_interrupt (int irq, void *netdrv, struct pt_regs *cpu_regs) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)netdrv; + + /* + * Workaround for the Linux 2.6 pending IRQ bug: + * If a pending IRQ is handled on a WLAN ISR, the ISR is called again + * even though it disabled itself in the first call. To protect against + * re-entrance, this flag is checked, and if it is already set (meaning + * that the ISR is called twice before the tasklet was called) nothing is done. + */ + if (drv->interrupt_pending == 0) + { + UINT32 interruptVector; + + interruptVector = configMgr_checkInterrupts(drv->adapter.CoreHalCtx); + if (interruptVector != 0) + { + configMgr_disableInterrupts(drv->adapter.CoreHalCtx); + drv->interrupt_pending = 1; + tasklet_schedule (&drv->tl); + } + else + { +#if DEBUG_UNKNOWN_INTERRUPT + ti_dprintf (TIWLAN_LOG_ERROR, + "%s - ERROR - interrupt isn't TNET interrupt! interrupt vector = 0x%08X\n", + __FUNCTION__, interruptVector); +#endif + } + } + return IRQ_HANDLED; +} + +#else + +static irqreturn_t tiwlan_interrupt (int irq, void *netdrv, struct pt_regs *cpu_regs) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)netdrv; + + drv->interrupt_pending = 1; + /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */ +#ifdef DM_USE_WORKQUEUE + if( queue_work( drv->tiwlan_wq, &drv->tirq ) != 0 ) { +#ifdef CONFIG_ANDROID_POWER + android_lock_suspend( &drv->irq_wake_lock ); +#endif + } + /* disable_irq( drv->irq ); Dm: No need, we can loose IRQ */ +#else + tasklet_schedule( &drv->tl ); +#endif + return IRQ_HANDLED; +} +#endif + + +static void tiwlan_poll_irq_handler(unsigned long parm) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)parm; + bm_trace(2, 0, 0); + + tiwlan_interrupt(0, drv, NULL); + mod_timer(&drv->poll_timer, jiffies + TIWLAN_IRQ_POLL_INTERVAL); +} + +static void tiwlan_handle_control_requests( tiwlan_net_dev_t *drv ) +{ + bm_trace(4, 0, 0); + + /* Handle control requests (timers, ioctls) */ + while(!list_empty(&drv->request_q)) + { + struct list_head *entry = drv->request_q.next; + tiwlan_req_t *req = list_entry(entry, tiwlan_req_t, list); + tiwlan_req_t tmp_req; + unsigned long flags; + + spin_lock_irqsave(&drv->lock, flags); + list_del_init(entry); + spin_unlock_irqrestore(&drv->lock, flags); + + ti_nodprintf(TIWLAN_LOG_INFO, "%s: f=0x%x req=0x%x reply_expected=%d\n", + __FUNCTION__, req->u.req.f, req, req->u.req.reply_expected); + + tmp_req.u.req.p1 = 0x1234; + tmp_req.u.req.p2 = 0x4321; + tmp_req.u.req.p3 = 0x1221; + tmp_req.u.req.p4 = 0x4334; + tmp_req.u.req.reply_expected = 0x50; + + req->u.reply = req->u.req.f(req); + + if ((tmp_req.u.req.p1 != 0x1234) || (tmp_req.u.req.p2 != 0x4321) || (tmp_req.u.req.p3 != 0x1221) || (tmp_req.u.req.p4 != 0x4334) || (tmp_req.u.req.reply_expected != 0x50)) + { + printk("\n\n !!! ERROR: STACK CORRUPTION !!! : \nf=%p\n", tmp_req.u.req.f); + if (!req->u.req.reply_expected) + printk("timer handler: %p\n", (void *)tmp_req.u.req.p1); + } + + ti_nodprintf(TIWLAN_LOG_INFO, "%s: f=0x%x req=0x%x reply_expected=%d reply=%d\n", + __FUNCTION__, req->u.req.f, req, req->u.req.reply_expected, req->u.reply); + if (req->u.req.reply_expected) + { + ti_nodprintf(TIWLAN_LOG_INFO, "%s: about to awake task\n", __FUNCTION__); + complete(&req->u.req.comp); + } + } + + bm_trace(5, 0, 0); + + /* DbgCB_Insert(0, DBG_MODULE_OS, DBG_TYPE_TASKLET, 1)*/ +} + +#ifdef DM_USE_WORKQUEUE +static void tiwlan_irq_handler( struct work_struct *work ) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( work, struct tiwlan_net_dev, tirq ); + + /* if the driver was unloaded by that time we need to ignore all the timers */ + if (drv->unload_driver) { +#ifdef CONFIG_ANDROID_POWER + android_unlock_suspend( &drv->irq_wake_lock ); +#endif + /* enable_irq( drv->irq ); */ + return; + } + /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */ + configMgr_handleInterrupts( drv->adapter.CoreHalCtx ); + tiwlan_handle_control_requests( drv ); +#ifdef CONFIG_ANDROID_POWER + if( drv->receive_packet ) { + drv->receive_packet = 0; + /* Keep awake for 500 ms to give a chance to network stack */ + android_lock_suspend_auto_expire( &drv->rx_wake_lock, (HZ >> 1) ); + } + android_unlock_suspend( &drv->irq_wake_lock ); +#endif + /* enable_irq( drv->irq ); */ +} +#endif + +/* tiwlan_tasklet_handler + WLAN protocol tasklet. Most of work happens in the + context of this tasklet. +*/ +#ifdef DM_USE_WORKQUEUE +static void tiwlan_work_handler( struct work_struct *work ) +#else +static void tiwlan_tasklet_handler( unsigned long netdrv ) +#endif +{ +#ifdef DM_USE_WORKQUEUE + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( work, struct tiwlan_net_dev, tw ); +#else + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)netdrv; +#endif +#ifdef STACK_PROFILE + unsigned int curr1, base1; + unsigned int curr2, base2; + static unsigned int maximum_stack = 0; +#endif + + /* if the driver was unloaded by that time we need to ignore all the timers */ + if (drv->unload_driver) { +#ifdef CONFIG_ANDROID_POWER + android_unlock_suspend( &drv->timer_wake_lock ); +#endif + return; + } + /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */ +#if 0 + ti_dprintf(TIWLAN_LOG_INFO, "%s in\n" , __FUNCTION__); +#endif + +#ifdef DRIVER_PROFILE + os_profile (drv, 0, 0); +#endif + bm_trace(3, 0, 0); + +#ifdef STACK_PROFILE + curr1 = check_stack_start(&base1); +#endif + + /* Handle bus transaction interrupts */ + if (drv->dma_done) + { + drv->dma_done = 0; + configMgr_HandleBusTxn_Complete(drv->adapter.CoreHalCtx); + } + + /* don't call for "Handle interrupts, timers, ioctls" while recovery process */ + if (configMgr_areInputsFromOsDisabled(drv->adapter.CoreHalCtx) == TRUE) { +#ifdef CONFIG_ANDROID_POWER + android_unlock_suspend( &drv->timer_wake_lock ); +#endif + return; + } + + /* Handle firmware interrupts */ +#ifndef DM_USE_WORKQUEUE + if (drv->interrupt_pending) + { + drv->interrupt_pending = 0; + configMgr_handleInterrupts(drv->adapter.CoreHalCtx); + } +#endif + + tiwlan_handle_control_requests( drv ); + +#ifdef STACK_PROFILE + curr2 = check_stack_stop(&base2); + + if (base2 == base1) + { + /* if the current measurement is bigger then the maximum store it and print*/ + if ((curr1 - curr2) > maximum_stack) + { + printk("STACK PROFILER GOT THE LOCAL MAXIMMUM!!!! \n"); + printk("current operation stack use =%d \n",(curr1 - curr2)); + printk("total stack use=%d \n",8192 - curr2 + base2); + printk("total stack usage= %d percent \n",100 * (8192 - curr2 + base2) / 8192); + maximum_stack = curr1 - curr2; + } + } +#endif + +#ifdef DRIVER_PROFILE + os_profile (drv, 1, 0); +#endif + +#if 0 + ti_dprintf(TIWLAN_LOG_INFO, "%s out\n" , __FUNCTION__); +#endif +#ifdef CONFIG_ANDROID_POWER + android_unlock_suspend( &drv->timer_wake_lock ); +#endif +} + +#if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK) +static void tiwlan_rx_watchdog(struct work_struct *work) +{ + struct delayed_work *dwork = (struct delayed_work *) container_of(work, struct delayed_work, work); + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( dwork, struct tiwlan_net_dev, trxw ); + + unsigned long num_rx_pkts = num_rx_pkt_new - num_rx_pkt_last; + /* Contribute 10mA (200mA x 5%) for 1 pkt/sec, and plus 8mA base. */ + unsigned percent = (5 * num_rx_pkts / RX_RATE_INTERVAL_SEC) + PWRSINK_WIFI_PERCENT_BASE; + + + if (drv->unload_driver) + return; + + percent = (percent > 100) ? 100 : percent; + /* printk(KERN_INFO "num_rx_pkts=%ld, percent=%d\n", num_rx_pkts, percent); */ +#ifdef CONFIG_HTC_PWRSINK + htc_pwrsink_set(PWRSINK_WIFI, percent); +#else + trout_pwrsink_set(PWRSINK_WIFI, percent); +#endif + + num_rx_pkt_last = num_rx_pkt_new; + + if (drv && drv->tiwlan_wq) + queue_delayed_work(drv->tiwlan_wq, &drv->trxw, msecs_to_jiffies(MSEC_PER_SEC * RX_RATE_INTERVAL_SEC)); +} +#endif + +/* tiwlan_send_wait_reply + This internal interface function creates request and sends + it to the control tasklet for processing. + The calling process is blocked until the request is replied. + Function f is being called in the context of the control tasklet. + The request block that is passed to the function as a parameter + contains p1, p2, p3, p4. + The function return code is propagated back to the caller. + tiwlan_send_req_and_wait returns (*f) return code or + -ENOMEM if failed to allocate a request. +*/ +int tiwlan_send_wait_reply(tiwlan_net_dev_t *drv, + int (*f)(tiwlan_req_t *req), + unsigned long p1, + unsigned long p2, + unsigned long p3, + unsigned long p4) +{ + tiwlan_req_t req; + unsigned long flags; + + /* Send request to tiwlan_tasklet and wait for reply */ + + req.drv = drv; + req.u.req.f = f; + req.u.req.p1 = p1; + req.u.req.p2 = p2; + req.u.req.p3 = p3; + req.u.req.p4 = p4; + req.u.req.reply_expected = 1; + init_completion(&req.u.req.comp); + + spin_lock_irqsave(&drv->lock, flags); + list_add_tail(&req.list, &drv->request_q); + spin_unlock_irqrestore(&drv->lock, flags); + +#ifdef DM_USE_WORKQUEUE + /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */ + if( queue_work( drv->tiwlan_wq, &drv->tw ) != 0 ) { +#ifdef CONFIG_ANDROID_POWER + android_lock_suspend( &drv->timer_wake_lock ); +#endif + } +#else + tasklet_schedule( &drv->tl ); +#endif + wait_for_completion(&req.u.req.comp); + + return req.u.reply; +} + + +#define WLAN_PCMCIA_CFG_REG 0x0524 +/* tiwlan_set_hw_access */ +static int tiwlan_set_hw_access(tiwlan_net_dev_t *drv) +{ +#ifdef TIWLAN_OMAP1610 + OS_WRITE_REG(drv, HI_CFG, 0x00000a00); + +#if ! ((defined(HW_ACCESS_SDIO)||defined(HW_ACCESS_WSPI)) && defined(TNETW1150)) + OS_WRITE_REG(drv, WLAN_PCMCIA_CFG_REG, 0xC6880000); + OS_WRITE_REG(drv, PCI_ARB_CFG, 0x2); +#endif + +#endif + return 0; +} + + +/* tiwlan_free_drv + Unmap h/w regions and free driver's structure +*/ +static void tiwlan_free_drv(tiwlan_net_dev_t *drv) +{ +#ifdef TIWLAN_OMAP1610 + if (drv->acx_mem.pa && drv->acx_mem.va) + iounmap(drv->acx_mem.va); + if (drv->acx_reg.pa && drv->acx_reg.va && drv->acx_reg.va != drv->acx_reg.va) + iounmap(drv->acx_reg.va); +#endif + kfree(drv); +} + + +/* tiwlan_alloc_drv + Allocate driver's structure and map h/w regions +*/ +static tiwlan_net_dev_t * +tiwlan_alloc_drv(unsigned long reg_start, unsigned long reg_size, + unsigned long mem_start, unsigned long mem_size, + int map_io, int irq) +{ + static tiwlan_net_dev_t *drv; + drv = kmalloc(sizeof(tiwlan_net_dev_t), GFP_KERNEL); +#ifdef TI_MEM_ALLOC_TRACE + os_printf("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, sizeof(tiwlan_net_dev_t), GFP_KERNEL, sizeof(tiwlan_net_dev_t)); +#endif/*I_MEM_ALLOC_TRACE*/ + + if (!drv) + return NULL; + memset(drv, 0, sizeof(tiwlan_net_dev_t)); + drv->acx_mem.size = mem_size; + drv->acx_reg.size = reg_size; +#ifdef TIWLAN_OMAP1610 + if (map_io) + { + drv->acx_mem.pa = mem_start; + drv->acx_reg.pa = reg_start; + drv->acx_mem.va = ioremap(drv->acx_mem.pa, drv->acx_mem.size); + if (drv->acx_mem.pa!=drv->acx_reg.pa || drv->acx_mem.size!=drv->acx_reg.size) + drv->acx_reg.va = ioremap(drv->acx_reg.pa, drv->acx_reg.size); + else + drv->acx_reg.va = drv->acx_mem.va; + } + else + { + /* Memory is already mapped */ + drv->acx_mem.va = (void *)mem_start; + drv->acx_reg.va = (void *)reg_start; + } +#endif /* Dm: */ + drv->irq = irq; + return drv; +} + + +/* tiwlan_init_drv + Called in process context + */ +int tiwlan_init_drv (tiwlan_net_dev_t *drv, tiwlan_dev_init_t *init_info) +{ + initTable_t *init_table; + int rc; + void *pWLAN_Images[4]; + + /* printk("%s\n", __FUNCTION__); */ + /* It is OK if already initialized */ + if (drv->adapter.CoreHalCtx) + return 0; + + init_table = os_memoryAlloc (drv, sizeof(initTable_t)); + +#ifdef TI_MEM_ALLOC_TRACE + osPrintf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, sizeof(initTable_t), GFP_KERNEL, sizeof(initTable_t)); +#endif/*I_MEM_ALLOC_TRACE*/ + if (!init_table) + { + ti_dprintf(TIWLAN_LOG_ERROR, "Cannot allocate init_table\n"); + return -ENOMEM; + } + + if (init_info) + { + drv->eeprom_image.size = init_info->eeprom_image_length; + if (drv->eeprom_image.size) + { + drv->eeprom_image.va = os_memoryAlloc (drv, drv->eeprom_image.size); + +#ifdef TI_MEM_ALLOC_TRACE + osPrintf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, drv->eeprom_image.size, GFP_KERNEL, drv->eeprom_image.size); +#endif + if (!drv->eeprom_image.va) + { + ti_dprintf (TIWLAN_LOG_ERROR, "Cannot allocate buffer for eeprom image\n"); + drv->eeprom_image.size = 0; + return -ENOMEM; + } + memcpy (drv->eeprom_image.va, &init_info->data[0], drv->eeprom_image.size ); + } + +#ifdef FIRMWARE_DYNAMIC_LOAD + drv->firmware_image.size = init_info->firmware_image_length; + if (!drv->firmware_image.size) + { + ti_dprintf (TIWLAN_LOG_ERROR, "No firmware image\n"); + return -EINVAL; + } + drv->firmware_image.va = os_memoryAlloc (drv,drv->firmware_image.size); +#ifdef TI_MEM_ALLOC_TRACE + osPrintf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, drv->firmware_image.size, GFP_KERNEL, drv->firmware_image.size); +#endif + if (!drv->firmware_image.va) + { + ti_dprintf(TIWLAN_LOG_ERROR, "Cannot allocate buffer for firmware image\n"); + drv->firmware_image.size = 0; + if (drv->eeprom_image.va) + os_memoryFree (drv, drv->eeprom_image.va, drv->eeprom_image.size); + return -ENOMEM; + } + memcpy (drv->firmware_image.va, + &init_info->data[init_info->eeprom_image_length], + drv->firmware_image.size); +#else + extern unsigned char tiwlan_fwimage[]; + extern unsigned int sizeof_tiwlan_fwimage; + + drv->firmware_image.size = sizeof_tiwlan_fwimage; + drv->firmware_image.va = tiwlan_fwimage; +#endif + } + + print_deb ("--------- Eeeprom=%p(%lu), Firmware=%p(%lu)\n", + drv->eeprom_image.va, + drv->eeprom_image.size, + drv->firmware_image.va, + drv->firmware_image.size); + + /* Init defaults */ + if ((rc = osInitTable_IniFile (drv, + init_table, + (init_info && init_info->init_file_length) ? + &init_info->data[init_info->eeprom_image_length+init_info->firmware_image_length] : NULL, + init_info ? init_info->init_file_length : 0))) + { + ti_dprintf (TIWLAN_LOG_ERROR, "osInitTable_IniFile failed :cannot initialize defaults\n"); + os_memoryFree (drv, init_table, sizeof(initTable_t)); + +#ifdef TI_MEM_ALLOC_TRACE + os_printf("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, sizeof(initTable_t), -sizeof(initTable_t)); +#endif + return rc; + } + + pWLAN_Images[0] = (void *)drv->firmware_image.va; + pWLAN_Images[1] = (void *)drv->firmware_image.size; + pWLAN_Images[2] = (void *)drv->eeprom_image.va; + pWLAN_Images[3] = (void *)drv->eeprom_image.size; + + drv->adapter.CoreHalCtx = configMgr_create (drv, + pWLAN_Images, + init_table, + (macAddress_t *) &drv->adapter.CurrentAddr); + if (!(drv->adapter.CoreHalCtx)) + { +#ifdef FIRMWARE_DYNAMIC_LOAD + os_memoryFree(drv,drv->firmware_image.va, drv->firmware_image.size); + os_memoryFree (drv, drv->eeprom_image.va, drv->eeprom_image.size); +#endif + os_memoryFree (drv, init_table, sizeof(initTable_t)); + ti_dprintf(TIWLAN_LOG_ERROR, "Cannot allocate CoreHalCtx\n"); + return -ENOMEM; + } + + drv->interrupt_pending = 0; + drv->dma_done = 0; + + if (drv->irq) + { +#ifndef PRIODIC_INTERRUPT +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) + unsigned long flags; + /* + * Disable all interrupts for not to catch the tiwlan irq + * between request_irq and disable_irq + */ + spin_lock_irqsave (&(drv->lock), flags); + if ((rc = request_irq (drv->irq, tiwlan_interrupt, SA_SHIRQ, drv->netdev->name, drv))) +#else + if ((rc = request_irq (drv->irq, (irq_handler_t)tiwlan_interrupt, IRQF_SHARED | IRQF_TRIGGER_FALLING /*Dm:*/, drv->netdev->name, drv))) +#endif + { + print_err ("TIWLAN: Failed to register interrupt handler\n"); + configMgr_stop (drv->adapter.CoreHalCtx); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) + spin_unlock_irqrestore (&drv->lock, flags); +#endif + return rc; + } +#ifdef CONFIG_ANDROID_POWER + set_irq_wake(drv->irq, 1); +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) + set_irq_type (drv->irq, IRQT_FALLING); +#else + set_irq_type (drv->irq, IRQ_TYPE_EDGE_FALLING); +#endif + disable_irq (drv->irq); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) + spin_unlock_irqrestore (&drv->lock, flags); +#endif +#else + printk (" tiwlan_init_drv :PRIODIC_INTERRUPT drv->irq %x\n",drv->irq); +#endif + } + else + { + /* Debug mode: polling */ + mod_timer (&drv->poll_timer, jiffies + TIWLAN_IRQ_POLL_INTERVAL); + } + + /* + * Now that all parts of the driver have been created and handles linked + * proceed to download the FW code + */ + configMgr_init (drv, + drv->adapter.CoreHalCtx, + pWLAN_Images, + init_table, + (macAddress_t *) &drv->adapter.CurrentAddr); + + /* Wait for the download to complete */ + os_WaitComplete ((void *)drv); + + os_memoryFree (drv, init_table, sizeof(initTable_t)); + + if (rc == OK) + { + proc_stat_init (drv->adapter.CoreHalCtx); +#ifdef TI_MEM_ALLOC_TRACE + osPrintf ("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, sizeof(initTable_t), -sizeof(initTable_t)); +#endif/*I_MEM_ALLOC_TRACE*/ + + if (drv->adapter.CoreHalCtx == NULL) + { + ti_dprintf (TIWLAN_LOG_ERROR, "configMgr_create failed\n"); + return -ENODEV; + } + + /* eeprom buffer is going to be deallocated by the caller. It is no longer needed anyway */ +#if 0 + drv->eeprom_image.va = NULL; + drv->eeprom_image.size = 0; +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) + drv->wl_sock = netlink_kernel_create(NETLINK_USERSOCK, 0, NULL, THIS_MODULE); /* Dm: */ +#else + drv->wl_sock = netlink_kernel_create(NETLINK_USERSOCK, 0, NULL, NULL, THIS_MODULE); /* Dm: */ +#endif +#else + drv->wl_sock = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 0, NULL, NULL, THIS_MODULE); /* Dm: */ +#endif + if (drv->wl_sock == NULL) + { + ti_dprintf(TIWLAN_LOG_ERROR, "netlink_kernel_create() failed !\n"); + /* TODO: free in destroy */ + return -EINVAL; + } + + /* Finalize network interface setup */ + drv->netdev->hard_start_xmit = tiwlan_drv_net_xmit; + memcpy (drv->netdev->dev_addr, drv->adapter.CurrentAddr, MAC_ADDR_LEN); + drv->netdev->addr_len = MAC_ADDR_LEN; + + /* Register the relevant events with the event handler */ + tiwlan_register_events (drv); + + /* Mark that init stage has succeded */ + drv->initialized = 1; + + return 0; + } + + return -ENODEV; +} + +#ifdef CONFIG_ANDROID_POWER +#ifndef CONFIG_HAS_WAKELOCK +/* Wrapper for Init wake lock */ +static void android_init_suspend_wakelock(android_suspend_lock_t *lp,char *nm) +{ + lp->name = nm; + android_init_suspend_lock( lp ); +} +#endif +#endif + +/* tiwlan_start_drv +*/ +int tiwlan_start_drv(tiwlan_net_dev_t *drv) +{ + /* printk("%s\n", __FUNCTION__); */ + if (!drv->initialized) + { + ti_dprintf(TIWLAN_LOG_ERROR, "Attempt to start driver before initilization has succeeded\n"); + return -ENODEV; + } + if (!drv->adapter.CoreHalCtx) + { + ti_dprintf(TIWLAN_LOG_ERROR, "Attempt to start driver before creating config_manager\n"); + return -ENODEV; + } + if (drv->started) + { + /*ti_dprintf(TIWLAN_LOG_ERROR, "Attempt to start driver that has already started\n");*/ + return -EALREADY; + } + if (configMgr_start(drv->adapter.CoreHalCtx) != OK) + { + print_err("TIWLAN: Failed to start config manager\n"); + return -EINVAL; + } + drv->started = 1; + +#ifdef SDIO_INTERRUPT_HANDLING_ON + configMgr_SlaveAckMaskNotification(drv->adapter.CoreHalCtx); +#endif + if (drv->netdev) + netif_start_queue(drv->netdev); +#ifdef CONFIG_TROUT_PWRSINK + trout_pwrsink_set(PWRSINK_WIFI, PWRSINK_WIFI_PERCENT_BASE); +#endif +#ifdef CONFIG_HTC_PWRSINK + htc_pwrsink_set(PWRSINK_WIFI, PWRSINK_WIFI_PERCENT_BASE); +#endif + export_wifi_fw_version(drv); + return 0; +} + + +/* tiwlan_destroy_drc +*/ +static void tiwlan_destroy_drv(tiwlan_net_dev_t *drv) +{ + int waitShutdownCounter; + + /* close the ipc_kernel socket*/ + if (drv && drv->wl_sock) { + sock_release(drv->wl_sock->sk_socket); + } + + bm_destroy(); + + tiwlan_stop_and_destroy_drv(drv); +#ifdef DM_USE_WORKQUEUE + while( tiwlan_del_msdu(drv) != NULL ); +#endif + if (drv->adapter.CoreHalCtx) + { + /* Delay return to OS until all driver components (HAL/SME) are shutdown */ + for (waitShutdownCounter=1; waitShutdownCounter<=DRV_SHUTDOWN_TEST_MAX_COUNTER; waitShutdownCounter++) + { + /* Check if HAL/SME are stopped - If so - exit loop and return to OS */ + if (configMgr_DriverShutdownStatus(drv->adapter.CoreHalCtx) == DRIVER_SHUTDOWN_COMPLETE) + { + break; + } + /* Delay of 100ms between shutdown test */ + mdelay ( DRV_SHUTDOWN_TEST_DELAY_INTERVAL ); + } + + /* If driver was not shutdown properly - destroy all timers "manually" and exit*/ + if ( waitShutdownCounter == DRV_SHUTDOWN_TEST_MAX_COUNTER+1 ) + { + os_printf("Timeout while waiting for driver to shutdown...Shutdown status flag=0x%x\n",configMgr_DriverShutdownStatus(drv->adapter.CoreHalCtx)); + } + + drv->unload_driver = 1; + + proc_stat_destroy(); + if (drv->irq) { +#ifdef CONFIG_ANDROID_POWER + set_irq_wake(drv->irq, 0); +#endif + free_irq(drv->irq, drv); + } + else + del_timer_sync(&drv->poll_timer); + + /* Unload all modules (free memory) & destroy timers */ + configMgr_UnloadModules (drv->adapter.CoreHalCtx); + +#ifdef FIRMWARE_DYNAMIC_LOAD + if( drv->firmware_image.va ) { + os_memoryFree(drv,drv->firmware_image.va, drv->firmware_image.size); +#ifdef TI_MEM_ALLOC_TRACE + os_printf("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, drv->firmware_image.size, -drv->firmware_image.size); +#endif /*I_MEM_ALLOC_TRACE*/ + } + if( drv->eeprom_image.va ) + { + os_memoryFree (drv, drv->eeprom_image.va, drv->eeprom_image.size); +#ifdef TI_MEM_ALLOC_TRACE + os_printf("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, drv->eeprom_image.size, -drv->eeprom_image.size); +#endif /*I_MEM_ALLOC_TRACE*/ + } +#endif /*FIRMWARE_DYNAMIC_LOAD*/ + } +#ifdef DM_USE_WORKQUEUE +#if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK) + cancel_delayed_work_sync(&drv->trxw); +#endif + destroy_workqueue(drv->tiwlan_wq); +#endif +#ifdef CONFIG_TROUT_PWRSINK + trout_pwrsink_set(PWRSINK_WIFI, 0); +#endif +#ifdef CONFIG_HTC_PWRSINK + htc_pwrsink_set(PWRSINK_WIFI, 0); +#endif +#ifdef CONFIG_ANDROID_POWER + android_uninit_suspend_lock(&drv->irq_wake_lock); + android_uninit_suspend_lock(&drv->xmit_wake_lock); + android_uninit_suspend_lock(&drv->timer_wake_lock); + android_uninit_suspend_lock(&drv->rx_wake_lock); +#endif + unregister_netdev(drv->netdev); + tiwlan_free_drv(drv); +} + + +/* tiwlan_create_dev + Create tiwlan device instance. + Returns 0 if OK +*/ +static int +tiwlan_create_drv(unsigned long reg_start, unsigned long reg_size, + unsigned long mem_start, unsigned long mem_size, + int map_io, int irq, + void *priv, tiwlan_net_dev_t **p_drv) +{ + tiwlan_net_dev_t *drv; + int rc; + + /* printk("%s\n", __FUNCTION__); */ + /* Allocate device and map h/w regions */ + drv = tiwlan_alloc_drv(reg_start, reg_size, mem_start, mem_size, map_io, irq); + if (!drv) + return -ENOMEM; + + /* Check h/w access */ + if (tiwlan_set_hw_access(drv)) + { + tiwlan_free_drv(drv); + return -ENODEV; + } + +#ifdef DM_USE_WORKQUEUE +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + drv->tiwlan_wq = create_singlethread_workqueue("tiwlan_wifi_wq"); +#else + drv->tiwlan_wq = create_freezeable_workqueue("tiwlan_wifi_wq"); +#endif + if( !(drv->tiwlan_wq) ) { + tiwlan_free_drv(drv); + printk(KERN_ERR "Failed to create workqueue\n"); + return -EINVAL; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) + INIT_WORK( &drv->tw, tiwlan_work_handler, &drv->tw ); + INIT_WORK( &drv->txmit, tiwlan_xmit_handler, &drv->txmit ); + INIT_WORK( &drv->tirq, tiwlan_irq_handler, &drv->tirq ); +#else + INIT_WORK( &drv->tw, tiwlan_work_handler ); + INIT_WORK( &drv->txmit, tiwlan_xmit_handler ); + INIT_WORK( &drv->tirq, tiwlan_irq_handler ); +#endif + drv->txmit_msdu_next = drv->txmit_msdu_last = NULL; +#else + tasklet_init( &drv->tl, tiwlan_tasklet_handler, (unsigned long)drv ); +#endif + +#if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) + INIT_DELAYED_WORK( &drv->trxw, tiwlan_rx_watchdog, &drv->trxw ); +#else + INIT_DELAYED_WORK( &drv->trxw, tiwlan_rx_watchdog ); +#endif +#endif + +#ifdef CONFIG_ANDROID_POWER + drv->receive_packet = 0; + android_init_suspend_wakelock(&drv->irq_wake_lock,"tiwlan_irq_wake"); + android_init_suspend_wakelock(&drv->xmit_wake_lock,"tiwlan_xmit_wake"); + android_init_suspend_wakelock(&drv->timer_wake_lock,"tiwlan_timer_wake"); + android_init_suspend_wakelock(&drv->rx_wake_lock,"tiwlan_rx_wake"); +#endif + spin_lock_init(&drv->lock); + INIT_LIST_HEAD(&drv->request_q); + init_timer(&drv->poll_timer); + drv->poll_timer.function = tiwlan_poll_irq_handler; + drv->poll_timer.data = (unsigned long)drv; + + /* Init the completion obhect needed for init async purpose */ + init_completion(&drv->comp); + + /* Register network device */ + rc = setup_netif(drv); + if (rc) + { + tiwlan_free_drv(drv); + return rc; + } + drv->priv = priv; + + list_add(&drv->list, &tiwlan_drv_list); + if (p_drv) + *p_drv = drv; + + drv->initialized = 0; + + /* Profiler */ +#ifdef DRIVER_PROFILING + tiwlan_profile_create (drv); +#endif + + bm_init(drv); + +#ifdef NO_USERMODE_WORKAROUND + rc = tiwlan_init_drv(drv, NULL); + rc = rc ? rc : tiwlan_start_drv(drv); +#endif + + return 0; +} + +/* tiwlan_stop_driver +*/ +int tiwlan_stop_drv(tiwlan_net_dev_t *drv) +{ + if (!drv->adapter.CoreHalCtx) + return 0; + + if (drv->netdev) + netif_stop_queue(drv->netdev); + + drv->started = 0; + configMgr_stop(drv->adapter.CoreHalCtx); + +#ifdef CONFIG_TROUT_PWRSINK + trout_pwrsink_set(PWRSINK_WIFI, 0); +#endif +#ifdef CONFIG_HTC_PWRSINK + htc_pwrsink_set(PWRSINK_WIFI, 0); +#endif + return 0; +} + +/* tiwlan_stop__and_destroy_driver +*/ +int tiwlan_stop_and_destroy_drv(tiwlan_net_dev_t *drv) +{ + if (!drv->adapter.CoreHalCtx) + return 0; + + if (drv->netdev) + netif_stop_queue(drv->netdev); + + /* Start unload process by calling smeSm_stop, and halting the HAL */ + /* SmeSm_stop finish notification will be one by setting flags */ + configMgr_InitiateUnload(drv->adapter.CoreHalCtx); + drv->started = 0; + return 0; +} + +void *wifi_kernel_prealloc(int section, unsigned long size) +{ +#ifdef CONFIG_WIFI_CONTROL_FUNC + if( wifi_control_data && wifi_control_data->mem_prealloc ) + return wifi_control_data->mem_prealloc( section, size ); + else +#endif + return NULL; +} + +#ifdef TIWLAN_CARDBUS + +static struct pci_device_id tnetw1130_pci_tbl[] __devinitdata = +{ + { VENDOR_ID_TI, DEVICE_ID_TI_WLAN, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0, } +}; + +static int __devinit +tnetw1130_pci_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) +{ + tiwlan_net_dev_t *drv; + int rc; + + print_info("tnetw1130_pci_init_one:\n"); + /* IT: for some reason interrupt doesn't work. + use poling mode for now (comments around + pcidev->irq below) + */ + rc = tiwlan_create_drv(pcidev->resource[0].start, + pcidev->resource[0].end - pcidev->resource[0].start, + pcidev->resource[1].start, + pcidev->resource[1].end - pcidev->resource[1].start, + 1, + 0/*pcidev->irq*/, pcidev, &drv); + if (!rc) + pcidev->driver_data = drv; + return rc; +} + +void tnetw1130_pci_remove(struct pci_dev *dev) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)dev->driver_data; + if (drv) + { + dev->driver_data = NULL; + tiwlan_destroy_drv(drv); + } +} + +static struct pci_driver tnetw1130_pci_driver = { + .name = "tnetw1130", + .id_table = tnetw1130_pci_tbl, + .probe = tnetw1130_pci_init_one, + .remove = tnetw1130_pci_remove +}; + +#endif /* #ifdef TIWLAN_CARDBUS */ + +#ifdef TIWLAN_OMAP1610 +int omap1610_drv_create(void) +{ + 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); +} +#endif /* #ifdef TIWLAN_OMAP1610 */ + +#ifdef TIWLAN_MSM7000 + +#define TROUT_IRQ MSM_GPIO_TO_INT(29) + +static void tiwlan_sdio_irq(struct sdio_func *func) +{ + printk("%s:\n", __FUNCTION__); +} + +static const struct sdio_device_id tiwlan_sdio_ids[] = { + { SDIO_DEVICE_CLASS(SDIO_CLASS_WLAN) }, + { }, +}; + +MODULE_DEVICE_TABLE(sdio, tiwlan_sdio_ids); + +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); + +#ifdef CONFIG_TROUT_PWRSINK + trout_pwrsink_set(PWRSINK_WIFI, PWRSINK_WIFI_PERCENT_BASE); +#endif +#ifdef CONFIG_HTC_PWRSINK + htc_pwrsink_set(PWRSINK_WIFI, PWRSINK_WIFI_PERCENT_BASE); +#endif + + sdio_claim_host(func); + + rc = tiwlan_sdio_init(func); + if (rc) + goto err2; + + rc = sdio_claim_irq(func, tiwlan_sdio_irq); + if (rc) + goto err1; + + SDIO_SetFunc( func ); + + rc = tiwlan_create_drv(0, 0, 0, 0, 0, TROUT_IRQ, NULL, NULL); + + printk(KERN_INFO "TIWLAN: Driver initialized (rc %d)\n", rc); + complete(&sdio_wait); + return rc; +err1: + sdio_disable_func(func); +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_release_irq(func); + sdio_disable_func(func); + sdio_release_host(func); + printk(KERN_DEBUG "TIWLAN: SDIO resources released\n"); +} + +static struct sdio_driver tiwlan_sdio_drv = { + .probe = tiwlan_sdio_probe, + .remove = tiwlan_sdio_remove, + .name = "sdio_tiwlan", + .id_table = tiwlan_sdio_ids, +}; + +#ifdef CONFIG_WIFI_CONTROL_FUNC +static int wifi_probe( struct platform_device *pdev ) +{ + struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data); + + printk("%s\n", __FUNCTION__); + if( wifi_ctrl ) { + wifi_control_data = wifi_ctrl; + if( wifi_ctrl->set_power ) + wifi_ctrl->set_power(1); /* Power On */ + if( wifi_ctrl->set_reset ) + wifi_ctrl->set_reset(0); /* Reset clear */ + if( wifi_ctrl->set_carddetect ) + wifi_ctrl->set_carddetect(1); /* CardDetect (0->1) */ + } + return 0; +} + +static int wifi_remove( struct platform_device *pdev ) +{ + struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data); + + printk("%s\n", __FUNCTION__); + if( wifi_ctrl ) { + if( wifi_ctrl->set_carddetect ) + wifi_ctrl->set_carddetect(0); /* CardDetect (1->0) */ + if( wifi_ctrl->set_reset ) + wifi_ctrl->set_reset(1); /* Reset active */ + if( wifi_ctrl->set_power ) + wifi_ctrl->set_power(0); /* Power Off */ + } + return 0; +} + +static struct platform_driver wifi_device = { + .probe = wifi_probe, + .remove = wifi_remove, + .suspend = NULL, + .resume = NULL, + .driver = { + .name = "msm_wifi", + }, +}; + +static int wifi_add_dev( void ) +{ + return platform_driver_register( &wifi_device ); +} + +static void wifi_del_dev( void ) +{ + platform_driver_unregister( &wifi_device ); +} + +int msm_wifi_power( int on ) +{ + printk("%s\n", __FUNCTION__); + if( wifi_control_data && wifi_control_data->set_power ) { + wifi_control_data->set_power(on); + } + return 0; +} + +int msm_wifi_reset( int on ) +{ + printk("%s\n", __FUNCTION__); + if( wifi_control_data && wifi_control_data->set_reset ) { + wifi_control_data->set_reset(on); + } + return 0; +} +#endif +#endif /* TIWLAN_MSM7000 */ + +static int __init tiwlan_module_init(void) +{ + int rc = 0; + + printk(KERN_INFO "TIWLAN: Driver loading\n"); + /* Check sizes of basic structures to ensure that compilation + options are OK + */ + if (packed_struct_tst()) + ;/*IT: return -EINVAL; */ + + tiwlan_deb_entry = create_proc_entry(TIWLAN_DBG_PROC, 0644, NULL); + if (tiwlan_deb_entry == NULL) + return -EINVAL; + tiwlan_deb_entry->read_proc = tiwlan_deb_read_proc; + tiwlan_deb_entry->write_proc = tiwlan_deb_write_proc; +#ifdef TIWLAN_MSM7000 + init_completion(&sdio_wait); +#endif +#ifdef TIWLAN_CARDBUS + if ((rc=pci_register_driver(&tnetw1130_pci_driver)) < 0) + print_err("TIWLAN: PCMCIA driver failed to register\n"); + remove_proc_entry(TIWLAN_DBG_PROC, NULL); + return rc; + } + printk(KERN_INFO "TIWLAN: Driver loaded\n"); + return 0; + +#elif defined(TIWLAN_OMAP1610) + rc = omap1610_drv_create(); + export_wifi_chip_id(); + printk(KERN_INFO "TIWLAN: Driver loaded\n"); + return rc; + +#elif defined(TIWLAN_MSM7000) +#ifdef CONFIG_WIFI_CONTROL_FUNC + wifi_add_dev(); +#else + trout_wifi_power(1); /* Power On */ + trout_wifi_reset(0); /* Reset clear */ + trout_wifi_set_carddetect(1); /* CardDetect (0->1) */ +#endif + + /* Register ourselves as an SDIO driver */ + rc = sdio_register_driver(&tiwlan_sdio_drv); + if (rc < 0) { + printk(KERN_ERR "sdio register failed (%d)\n", rc); + remove_proc_entry(TIWLAN_DBG_PROC, NULL); + return rc; + } + /* rc = tiwlan_create_drv(0, 0, 0, 0, 0, TROUT_IRQ, NULL, NULL); -- Called in probe */ + + tiwlan_calibration = create_proc_entry("calibration", 0644, NULL); + if (tiwlan_calibration == NULL) { + remove_proc_entry(TIWLAN_DBG_PROC, NULL); + return -EINVAL; + } + tiwlan_calibration->size = tiwlan_get_nvs_size(); + tiwlan_calibration->read_proc = tiwlan_calibration_read_proc; + tiwlan_calibration->write_proc = tiwlan_calibration_write_proc; + + if (!wait_for_completion_timeout(&sdio_wait, msecs_to_jiffies(10000))) { + printk(KERN_ERR "%s: Timed out waiting for device detect\n", __func__); + remove_proc_entry(TIWLAN_DBG_PROC, NULL); + remove_proc_entry("calibration", NULL); + sdio_unregister_driver(&tiwlan_sdio_drv); +#ifdef CONFIG_WIFI_CONTROL_FUNC + wifi_del_dev(); +#else + trout_wifi_set_carddetect(0); /* CardDetect (1->0) */ + trout_wifi_reset(1); /* Reset active */ + trout_wifi_power(0); /* Power Off */ +#endif + return -ENODEV; + } + export_wifi_chip_id(); + printk(KERN_INFO "TIWLAN: Driver loaded\n"); + return 0; + +#else + +#error Either TIWLAN_CARDBUS, TIWLAN_OMAP1610 or TIWLAN_MSM7000 must be defined + +#endif +} + +static void __exit tiwlan_module_cleanup(void) +{ + struct list_head *l; + struct list_head *tmp; + + printk(KERN_INFO "TIWLAN: Driver unloading\n"); +#ifdef TIWLAN_CARDBUS + pci_unregister_driver(&tnetw1130_pci_driver); +#endif + list_for_each_safe(l, tmp, &tiwlan_drv_list) + { + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)list_entry(l, tiwlan_net_dev_t, list); + list_del(l); + tiwlan_destroy_drv(drv); + } + remove_proc_entry(TIWLAN_DBG_PROC, NULL); +#ifdef TIWLAN_MSM7000 + remove_proc_entry("calibration", NULL); + sdio_unregister_driver(&tiwlan_sdio_drv); +#ifdef CONFIG_WIFI_CONTROL_FUNC + wifi_del_dev(); +#else + trout_wifi_set_carddetect(0); /* CardDetect (1->0) */ + trout_wifi_reset(1); /* Reset active */ + trout_wifi_power(0); /* Power Off */ +#endif +#endif + printk(KERN_INFO "TIWLAN: Driver unloaded\n"); +} + +module_init(tiwlan_module_init); +module_exit(tiwlan_module_cleanup); diff --git a/sta_dk_4_0_4_32/pform/linux/src/ioctl_list.c b/sta_dk_4_0_4_32/pform/linux/src/ioctl_list.c new file mode 100644 index 0000000..5c3fa32 --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/ioctl_list.c @@ -0,0 +1,263 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + + +#include "arch_ti.h" + +#include <asm/uaccess.h> /* copy_to_user() */ +#include <linux/netdevice.h> +#include <linux/ioctl.h> +#include <linux/completion.h> +#include <linux/vmalloc.h> + +#include "esta_drv.h" +#include "tiwlan_profile.h" +#include "ioctl_init.h" +#include "ioctl_utils.h" +#include "tiioctl.h" +#include "ipc_k.h" + + +void print_priv_ioctl_params(struct net_device *dev, tiioctl_req_t *req, char *extra) +{ + print_deb(" priv_ioctl_params(*dev:%p,*req:%p, *extra:%p)\n", dev, req, extra); + print_deb(" wrqu.point: user_data=%p, length=%ld, cmd=%ld\n", (void *) req->user_data_pointer, + req->length, req->cmd ); + print_deb(" wrqu dump: "); + print_memory_dump((char *) req, sizeof(*req) ); + print_deb("\n"); + + if( extra ) + { + print_deb(" extra (%p) :", extra ); + print_memory_dump(extra, req->length ); + print_deb("\n"); + } +} + +/*sends complete to the user after to signal the completion of the asynchronous */ +/*operation (need to set *pIoCompleteFlag = FALSE, at osCmd.c).*/ + +void os_IoctlComplete(PTIWLN_ADAPTER_T pAdapter, TI_STATUS ReturnStatus ) +{ + *pAdapter->pCompleteReply = (int)ReturnStatus; + complete(pAdapter->IoctlComp); +} + + +NTSTATUS DispatchCommand(PTIWLN_ADAPTER_T pAdapter,ULONG ioControlCode,PULONG outBufLen, + ULONG inBufLen,PVOID ioBuffer,PUINT8 pIoCompleteFlag); + +int ti1610_ioctl_priv_proc_tl(tiwlan_req_t *req_data) +{ + struct net_device *dev = req_data->drv->netdev; + tiioctl_req_t *req = (tiioctl_req_t *) req_data->u.req.p1; + static unsigned int drv_started = 0; + static UINT8 IoCompleteFlag ; + + ULONG *data = (ULONG *) req_data->u.req.p2; + + int res = -EINVAL; + + print_deb("priv_ioctl_proc(): cmd=%ld, data=%p (user_data=%lx), lenght=%ld\n", + req->cmd, data, req->user_data_pointer, req->length); + if( !drv_started && (req->cmd != TIWLN_DRIVER_STATUS_SET)) { /* Dm: Fix */ + return res; + } + + switch( req->cmd ) { + case TIWLN_DRIVER_STATUS_SET: + if(*data) + res = tiwlan_start_drv( (tiwlan_net_dev_t *)dev->priv ); + else + res = tiwlan_stop_drv( (tiwlan_net_dev_t *)dev->priv ); + + if( res == OK ) + drv_started = !drv_started; + break; + + case TIWLN_SEND_EAPOL_PACKET: + res = os_sendPacket(dev, data, req->length); + break; +#ifdef TI_DBG + case TIWLN_DRIVER_DEBUG_PRINT: + res = util_hal_debug_print(dev, data); + break; +#endif /* TI_DBG */ + default: + { + res = DispatchCommand(&req_data->drv->adapter, req->cmd, &req->length, req->length, data,&IoCompleteFlag ); + /* If we do not have to send complete to user back then set the Falg to FALSE + The Complete will be sent from another contect of command completion from FW */ + if(IoCompleteFlag == FALSE) + { + req_data->u.req.reply_expected = FALSE; + /****** TO DO - This solution will have a problem in case of two async ioctrls (in case of two utility adapters). ******/ + /* Store the semaphore for later competion */ + (req_data->drv->adapter).IoctlComp = &(req_data->u.req.comp); + /* Store the pointer of the result status for later competion */ + (req_data->drv->adapter).pCompleteReply = &(req_data->u.reply); + } + + } + } + return res; +} + +int ti1610_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + tiioctl_req_t *req = (tiioctl_req_t *) &rq->ifr_ifru; + char *extra, *kbuf = NULL; + int res, aval_data_size = ((char *) req + sizeof(*req)) - (char *)&req->user_data_pointer; /* = ~4 bytes */ + /*int is_get_cmd = (req->cmd_type & IOCTL_GET);*/ + + print_deb("ti1610_do_ioctl(cmd=%lu(%s%s)) - user_data_pointer=0x%lx, len = %lu, aval_data_size=%d\n", + req->cmd, + (req->cmd_type & IOCTL_GET) ? "GET" : "", (req->cmd_type & IOCTL_SET) ? "SET" : "", + req->user_data_pointer, req->length, aval_data_size ); + + /* driver is already initialized */ + if ((req->cmd == TIWLN_SET_INIT_INFO) && (((tiwlan_net_dev_t *)dev->priv)->adapter.CoreHalCtx)) + { + return 0; + } + + if( req->length > aval_data_size ) + { + if( req->user_data_pointer == 0 ) + return -EFAULT; + + print_deb("ti1610_do_ioctl() - alloc %ld bytes\n", req->length ); + kbuf = extra = os_memoryAlloc(NULL,req->length); +#ifdef TI_MEM_ALLOC_TRACE + os_printf("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, req->length, GFP_KERNEL, req->length); +#endif/*I_MEM_ALLOC_TRACE*/ + + if( !extra ) + return -ENOBUFS; + if( req->cmd_type & IOCTL_SET ) + { + if( copy_from_user(extra, (void *) req->user_data_pointer, req->length) ) + return -EFAULT; + } + else { + os_memoryZero( NULL, extra, req->length ); + } + } else + extra = (char *) &req->user_data_pointer; + + /* Driver initialization must be performed in process context. + The rest is handled in the context of dedicated tasklet + */ + if (req->cmd == TIWLN_SET_INIT_INFO) + { + tiwlan_dev_init_t *init_info = (tiwlan_dev_init_t *)extra; + print_deb("TIWLN_SET_INIT_INFO: el=%d il=%d, fl=%d\n", + init_info?init_info->eeprom_image_length:0, + init_info?init_info->init_file_length:0, + init_info?init_info->firmware_image_length:0 ); + res = tiwlan_init_drv((tiwlan_net_dev_t *)dev->priv, init_info); + } + +#ifdef DRIVER_PROFILING + else if (req->cmd == TIWLAN_PROFILING_REPORT) + { + res = tiwlan_profile_report((tiwlan_net_dev_t *)dev->priv); + } + else if (req->cmd == TIWLAN_PROFILING_CPU_ESTIMATOR_CMD) { + /* get the command cpu estimator command parameter */ + unsigned int command_param = *((unsigned int *)extra); + /* extract the command type which is the MSB byte of the command param*/ + unsigned int command_type = 0xFF & (command_param >> 24); + /* extract the data of the command which are the 3 LSB bytes of the command param */ + unsigned int command_data = 0xFFFFFF & command_param; + /* execute the command according to its type */ + switch (command_type) + { + case TIWLAN_PROFILING_CPU_ESTIMATOR_CMD_START: + res = tiwlan_profile_cpu_usage_estimator_start((tiwlan_net_dev_t *)dev->priv, + /* the data in this case is the estimator + resolution in milliseconds */ + command_data * 1000); + break; + case TIWLAN_PROFILING_CPU_ESTIMATOR_CMD_STOP: + res = tiwlan_profile_cpu_usage_estimator_stop((tiwlan_net_dev_t *)dev->priv); + break; + case TIWLAN_PROFILING_CPU_ESTIMATOR_CMD_RESET: + res =tiwlan_profile_cpu_usage_estimator_reset((tiwlan_net_dev_t *)dev->priv); + break; + default: + res = 0; + printk("\n\n%s: cpu usage estimator unknow command: param = %x\n\n\n", + __FUNCTION__, command_param); + } + } +#endif + + else + { + res = tiwlan_send_wait_reply((tiwlan_net_dev_t *)dev->priv, ti1610_ioctl_priv_proc_tl, + (unsigned long)req, (unsigned long)extra, 0, 0); + } + + if( !res ) + { + if( (req->cmd_type & IOCTL_GET) && kbuf /*req->length > aval_data_size*/ ) + { + print_deb("ti1610_do_ioctl(): ...copy from %p to %p %ld bytes\n\n", extra, (void *) req->user_data_pointer, req->length ); + print_memory_dump(extra, min(32,(int) req->length) ); + if( copy_to_user( (void *) req->user_data_pointer, extra, req->length ) ) + return -EFAULT; + } + } + print_deb("ti1610_do_ioctl() = %d (req = %p, user_data_pointer=0x%lx, extra=%p)\n\n", res, req, req->user_data_pointer, extra ); + + if( kbuf ){ + os_memoryFree(NULL,kbuf,sizeof(kbuf)); +#ifdef TI_MEM_ALLOC_TRACE + os_printf("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, kbuf, -req->length); +#endif/*I_MEM_ALLOC_TRACE*/ + } + return res; +} + + +int tiwlan_ioctl_init( struct net_device *dev ) +{ + dev->do_ioctl = ti1610_do_ioctl; + + return 0; +} + diff --git a/sta_dk_4_0_4_32/pform/linux/src/ioctl_utils.c b/sta_dk_4_0_4_32/pform/linux/src/ioctl_utils.c new file mode 100644 index 0000000..54f4ac5 --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/ioctl_utils.c @@ -0,0 +1,164 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + + +#include "ioctl_init.h" +#include "esta_drv.h" + +#include "ioctl_utils.h" + +#include "report.h" +#include "osClsfr.h" + +#define CONFIG_MGR(dev) ((configMgr_t *) \ + ((dev && dev->priv) ? ((tiwlan_net_dev_t *) dev->priv)->adapter.CoreHalCtx : NULL ) ) + + +typedef struct +{ + int err_code; + char *desc; +} +configMgr_error_desc_t; + + +static configMgr_error_desc_t configMgr_error_desc[] = +{ + { OK, "OK" }, + { NOK, "NOK" }, + { PARAM_NOT_SUPPORTED, "PARAM_NOT_SUPPORTED" }, + { PARAM_VALUE_NOT_VALID, "PARAM_VALUE_NOT_VALID" }, + { CONFIGURATION_NOT_VALID, "CONFIGURATION_NOT_VALID" }, + { NO_SITE_SELECTED_YET, "NO_SITE_SELECTED_YET" }, + { RE_SCAN_NEEDED, "RE_SCAN_NEEDED" }, + { EXTERNAL_SET_PARAM_DENIED, "EXTERNAL_SET_PARAM_DENIED" }, + { EXTERNAL_GET_PARAM_DENIED, "EXTERNAL_GET_PARAM_DENIED" }, + { PARAM_MODULE_NUMBER_INVALID, "PARAM_MODULE_NUMBER_INVALID" }, + { STATION_IS_NOT_RUNNING, "STATION_IS_NOT_RUNNING" }, + { CARD_IS_NOT_INSTALLED, "CARD_IS_NOT_INSTALLED" }, + /* Data path section */ + /* { RX_BSS_TYPE_ERROR ,*/ + /* { RX_BSS_ID_ERROR ,*/ + /* { TX_QUEUE_SELECTED_OK ,*/ + /* { NO_TX_QUEUE_SELECTED ,*/ + /* { TX_STATUS_PENDING ,*/ + /* { TX_STATUS_NO_RESOURCES ,*/ + /* { TX_STATUS_FAILURE ,*/ + /* { TX_STATUS_OK ,*/ + + /* 4x section */ + /* { MAKE_CONCATENATION ,*/ + /* { SEND_ONE_MSDU ,*/ + /* { DO_NOT_SEND_MSDU ,*/ + /* { FOUR_X_DISABLE ,*/ + /**/ + /* (Scanning section) */ + /* { NO_COUNTRY ,*/ + /**/ + /* (Setting power after select) */ + /* { TX_POWER_SHOULD_NOT_BE_SET ,*/ + /* (changing service channel) */ + /* { CHANNEL_CHANGED ,*/ + /* { SUPPORT_IMMEDIATE_MEASUREMENT_ONLY,*/ + /* { MEASUREMENT_TYPE_NOT_SUPPORT,*/ + /* { MEASUREMENT_CAN_NOT_EXECUTED_IN_PARALLEL,*/ + /* { MEASUREMENT_REQUEST_IGNORED,*/ + /* { CANNOT_SET_MEASUREMENT_PARAM_WHEN_ACTIVATED,*/ + /* { REGULATORY_DOMAIN_SET_TX_POWER_PARAM,*/ + /* { CANNOT_SET_CHANNEL_THAT_IS_NOT_SUPPORTED,*/ +}; + + +int print_err_desc(int err) +{ + int i; + for( i=0; i<SIZE_ARR(configMgr_error_desc);i++ ) + { + if(configMgr_error_desc[i].err_code == err ) + { + print_err("---err(%d) configMgr() = %s\n", err, configMgr_error_desc[i].desc ); + return -err; + } + } + print_err("---err(%d) configMgr failed\n", err); + return -err; +} + +void print_memory_dump(char *addr, int size ) +{ +#ifdef DEBUG_MESSAGES + int i; + char buf[4096]; + + if( size * 4 > sizeof(buf) ) { + print_err("print_memory_dump(): buffer too small\n"); + return; + } + + buf[0] = 0; + for(i=0; i<size; i++ ) { + if( !(i % 16) ) + sprintf(&buf[strlen(buf)], "%s%p: ", (i) ? "\n" : "", addr+i ); + sprintf(&buf[strlen(buf)], "%02x ", (unsigned char)addr[i] ); + } + print_info("%s\n", buf); +#endif /* DEBUG_MESSAGES */ +} + +#ifdef TI_DBG +#ifndef TIWLAN_MSM7000 +TI_STATUS debugFunction(TI_HANDLE hConfigMgr, + UINT32 functionNumber, + void *pParam); +#endif +#endif +int util_hal_debug_print(struct net_device *dev, ULONG *data) +{ + hal_print_param_t *p = (hal_print_param_t *) data; + UINT32 opt_data = 0; + + if( p->optional_param ) + { + if( copy_from_user(&opt_data, p->optional_param, sizeof(opt_data) ) ) + return -EFAULT; + } + + print_deb("HAL_DEBUG_PRINT: func_id=%d, param=%x\n", p->func_id, opt_data ); +#ifdef TI_DBG + debugFunction(CONFIG_MGR(dev), p->func_id, &opt_data ); +#endif + return 0; +} + diff --git a/sta_dk_4_0_4_32/pform/linux/src/ioctl_utils.h b/sta_dk_4_0_4_32/pform/linux/src/ioctl_utils.h new file mode 100644 index 0000000..05dd459 --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/ioctl_utils.h @@ -0,0 +1,95 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + + +#ifndef TI1610_IOCTL_UTILS +#define TI1610_IOCTL_UTILS + +#include <linux/netdevice.h> +#include <asm/uaccess.h> /* copy_from_user() */ + +#include "osTIType.h" + +void print_memory_dump(char *addr, int size ); + +int util_get_statistics(struct net_device *dev, ULONG *statistic_data, ULONG *length ); + +int util_get_param( struct net_device *dev, UINT32 param_type, ULONG *data, UINT32 max_param_len); +int util_set_param( struct net_device *dev, UINT32 param_type, ULONG *data, UINT32 max_param_len ); +int util_get_report_param( struct net_device *dev, UINT32 param_type, ULONG *data, UINT32 max_param_len); +int util_set_report_param( struct net_device *dev, UINT32 param_type, ULONG *data, UINT32 max_param_len); + +/*int util_get_bssid(struct net_device *dev, int cmd, union iwreq_data *wrqu );*/ +int util_get_network_type_in_use(struct net_device *dev, /*int cmd, */ULONG *data ); +int util_write_hw_register(struct net_device *dev, ULONG *data ); +int util_read_hw_register(struct net_device *dev, ULONG *data ); +int util_hal_debug_print(struct net_device *dev, ULONG *data); +int util_get_sw_version(struct net_device *dev, ULONG *data ); +int util_get_network_types_supported(struct net_device *dev, ULONG *data ); +int util_get_number_of_antennas(struct net_device *dev, ULONG *data ); +int util_get_rssi(struct net_device *dev, ULONG *data ); +int util_get_bssid_list(struct net_device *dev, ULONG *data, ULONG *length ); +int util_set_privacy_filter(struct net_device *dev, ULONG *data ); +int util_get_privacy_filter(struct net_device *dev, ULONG *data, ULONG *length ); +int util_disassociate(struct net_device *dev); +int util_set_ssid(struct net_device *dev, void *buf, ULONG length); /* data - pointer to OS_802_11_SSID */ +int util_get_ssid(struct net_device *dev, ULONG configMgr_param, void *data, ULONG *length); +/*int util_get_ssid(struct net_device *dev, void *data, ULONG *length); ( data - pointer to OS_802_11_SSID) */ + +int util_get_desired_channel(struct net_device *dev, ULONG *data); +int util_get_authentication_mode(struct net_device *dev, ULONG *data); +int util_get_rts_threshold(struct net_device *dev, ULONG *data); +int util_get_short_preamble(struct net_device *dev, ULONG *data); + +int util_poll_ap_packets (struct net_device *dev); +int util_config_tx_classifier(struct net_device *dev,UINT8 *inParamsBuff,UINT32 inParamsBuffLen); + + +int util_get_fragmentation_threshold(struct net_device *dev, ULONG *data); +int util_get_infrastructure_mode(struct net_device *dev, ULONG *data); +int util_get_desired_infrastructure_mode(struct net_device *dev, ULONG *data); +int util_get_wep_status(struct net_device *dev, ULONG *data); +int util_get_power_mode(struct net_device *dev, ULONG *data); +int util_get_tx_antenna(struct net_device *dev, ULONG *data); +int util_get_rx_antenna(struct net_device *dev, ULONG *data); +int util_get_short_preamble(struct net_device *dev, ULONG *data); +int util_get_enable_leap(struct net_device *dev, ULONG *data); +int util_set_wep_status(struct net_device *dev, ULONG *data); +int util_add_wep(struct net_device *dev, void *data, ULONG length); +int util_add_key(struct net_device *dev, void *data, ULONG length); +int util_remove_key(struct net_device *dev, void *data, ULONG length); +int util_remove_wep(struct net_device *dev, void *data, ULONG length); +int util_get_association_info(struct net_device *dev, ULONG *data, ULONG *length ); +#endif diff --git a/sta_dk_4_0_4_32/pform/linux/src/ipc_k.c b/sta_dk_4_0_4_32/pform/linux/src/ipc_k.c new file mode 100644 index 0000000..9975c75 --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/ipc_k.c @@ -0,0 +1,120 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/stddef.h> +#include <linux/netdevice.h> +#include <linux/rtnetlink.h> +#include <linux/netlink.h> + +#include "osTIType.h" +#include "esta_drv.h" +#include "osApi.h" +#include "ioctl_init.h" +#include "cli_cu_common.h" +#include "TI_IPC_Api.h" + +UINT32 IPCKernelInit (TI_HANDLE hAdapter,TI_HANDLE hIPCEv) +{ + return 0; +} + +UINT32 IPCKernelDeInit (TI_HANDLE hAdapter) +{ + return 0; +} + + +/*******************************************************/ +INT32 IPC_EventSend(TI_HANDLE hAdapter, tiUINT8* pEvData, UINT32 EvDataSize) +{ + struct sk_buff *skb; + int res; + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *) hAdapter; + UINT32 realSize = 0; + UINT32 msgSize; + struct nlmsghdr *nlh; + tiUINT8 *msg; + + /* This event is targetted to the OS process Id 0 is not a valid pId for LINUX*/ + + if ((( IPC_EVENT_PARAMS *) pEvData) ->uProcessID == 0) + { + (( IPC_EVENT_PARAMS *) pEvData) ->pfEventCallback(( IPC_EV_DATA *) pEvData); + return 0; + } + + /* set the payload size */ + msgSize = (( IPC_EV_DATA *) pEvData) ->uBufferSize + offsetof(IPC_EV_DATA,uBuffer); + + /* add the netlink header size */ + realSize = NLMSG_SPACE(msgSize); + + /* allocate the complete message */ + skb = dev_alloc_skb(realSize); + if (!skb) { + printk(KERN_ERR "Failed to allocate new skb with size=%u.\n",realSize); + return -1; + } + + /* set the netlink header params */ + nlh = NLMSG_PUT(skb, 0, 0, NLMSG_DONE, realSize - sizeof(*nlh)); + + /* get the payload pointer */ + msg = (char *)NLMSG_DATA(nlh); + + /* copy the data to the payload */ + memcpy(msg,pEvData,msgSize); + + NETLINK_CB(skb).pid = 0; /* from kernel */ + NETLINK_CB(skb).dst_group = RTNLGRP_LINK; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) + NETLINK_CB(skb).dst_pid = (( IPC_EVENT_PARAMS *) pEvData) ->uProcessID; /* Dm: */ +#endif + + /* send the message*/ + res = netlink_unicast(drv->wl_sock, skb, (( IPC_EVENT_PARAMS *) pEvData) ->uProcessID, MSG_DONTWAIT); + + /* Sanity checks. As far as we're concerned this error is unrecovarable.*/ + if (res >= 0) + { + return 0; + } + +nlmsg_failure: + ti_dprintf(TIWLAN_LOG_INFO,"IPC kernel: did not send the netlink message\n"); + return -1; +} diff --git a/sta_dk_4_0_4_32/pform/linux/src/ipc_k.h b/sta_dk_4_0_4_32/pform/linux/src/ipc_k.h new file mode 100644 index 0000000..e0b442f --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/ipc_k.h @@ -0,0 +1,46 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + + +#ifndef _IPC_K +#define _IPC_K + +#include "osTIType.h" + + +/*INT32 IPC_EventSend(struct net_device *dev, sk_buff *skb, UINT32 pid);*/ +#endif + + diff --git a/sta_dk_4_0_4_32/pform/linux/src/mmc_tnetw1150_api.c b/sta_dk_4_0_4_32/pform/linux/src/mmc_tnetw1150_api.c new file mode 100755 index 0000000..4efee19 --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/mmc_tnetw1150_api.c @@ -0,0 +1,545 @@ +/* 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 TIWLAN_MSM7000 + +#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; + + *(u8*)data = sdio_readb_ext(func, br_offset, &rc, 0x01); + 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_4_0_4_32/pform/linux/src/osRgstry_parser.c b/sta_dk_4_0_4_32/pform/linux/src/osRgstry_parser.c new file mode 100644 index 0000000..88c99d1 --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/osRgstry_parser.c @@ -0,0 +1,232 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + +#include "osrgstry_parser.h" + +extern VOID regReadLastDbgState(PTIWLN_ADAPTER_T pAdapter); + +static char *init_file = NULL; +static int init_file_length= 0; +static PNDIS_CONFIGURATION_PARAMETER pNdisParm; + +extern int osInitTable_IniFile(tiwlan_net_dev_t *drv, initTable_t *InitTable, char *file_buf, int file_length) +{ + NDIS_CONFIGURATION_PARAMETER parm; + + init_file = file_buf; + init_file_length = file_length; + pNdisParm = &parm; + + regFillInitTable( &drv->adapter, InitTable ); +#ifdef TI_DBG + regReadLastDbgState(&drv->adapter); +#endif + + return 0; +} + +unsigned long TiDebugFlag; + +/* void PRINT( char * type, char *format, ... )*/ +/* {*/ +/* return ;*/ +/* }*/ + +NDIS_STATUS NdisUnicodeStringToAnsiString( IN OUT PANSI_STRING DestinationString, + IN PUNICODE_STRING SourceString ) +{ + if( DestinationString->MaximumLength < SourceString->Length ) + return NDIS_STATUS_BUFFER_TOO_SHORT; + + DestinationString->Length = SourceString->Length; + os_memoryCopy( NULL, DestinationString->Buffer, SourceString->Buffer, SourceString->Length ); + return NDIS_STATUS_SUCCESS; + +} + +#ifndef tolower +#define tolower(c) ( (c) | 0x20) +#endif + + /* Search sub-string in memory buffer */ + /* From '#' to EOL ---- remarks */ +char *mem_str(char *buf, char *str, char *end_buf) +{ + int i; + + for( ; buf <= end_buf; buf++ ) + { + if( *buf == '#' ) + { + buf = strchr(buf+1, '\n' ); + if( !buf ) + return NULL; + + } + for( i=0; &buf[i] <= end_buf && buf[i] && str[i] && (tolower(buf[i]) == tolower(str[i])); i++ ) ; + + if ((!str[i]) && (!((tolower(*(buf-1))>='a') && (tolower(*(buf-1))<='z')))) + return buf; + } + return NULL; +} + +char * ltrim(char *s ) +{ + while( *s == ' ' || *s == '\t' ) s++; + return s; +} + +VOID NdisReadConfiguration( OUT PNDIS_STATUS status, OUT PNDIS_CONFIGURATION_PARAMETER *param_value, + IN NDIS_HANDLE config_handle, IN PNDIS_STRING keyword, IN NDIS_PARAMETER_TYPE param_type ) +{ +#ifdef USE_INIT_FILE + char *name = keyword->Buffer; + char *s, *buf = init_file, *end_buf = init_file + init_file_length; + static int count = 0; + + *status = NDIS_STATUS_FAILURE; + *param_value = pNdisParm; + + if( !count ) + { + print_deb("\n++++++++++++\n%s+++++++++++\n", init_file); + count++; + } + + if( !name || !*name || !init_file || !init_file_length ) + return ; + + memset(pNdisParm, 0, sizeof(NDIS_CONFIGURATION_PARAMETER)); + + while(buf < end_buf) + { + buf = ltrim(buf); + if( !(s = mem_str(buf, name, end_buf)) ) + break; + + buf = ltrim(s + strlen(name)); + if( *buf == '=' ) + buf++; + else { + /*print_err("\n...init_config err: delim not found (=): ** %s **\n", buf );*/ + buf = s + 1; /*strlen(name);*/ + continue; + } + buf = ltrim(buf); + if( param_type == NdisParameterString ) + { + char *remark = NULL; + + s = strchr(buf, '\n'); + if( !s ) + s = buf+strlen(buf); + + remark = memchr(buf, '#', s - buf); /* skip remarks */ + if( remark ) + { + do { /* remove whitespace */ + remark--; + } while( *remark == ' ' || *remark == '\t' ); + + pNdisParm->ParameterData.StringData.Length = remark - buf + 1; + } + else + pNdisParm->ParameterData.StringData.Length = s - buf; + + pNdisParm->ParameterData.StringData.Buffer = (PUCHAR)&pNdisParm->StringBuffer[0]; + pNdisParm->ParameterData.StringData.MaximumLength = NDIS_MAX_STRING_LEN; + if( !pNdisParm->ParameterData.StringData.Length > NDIS_MAX_STRING_LEN ) + { + *status = NDIS_STATUS_BUFFER_TOO_SHORT; + return; + } + memcpy(pNdisParm->ParameterData.StringData.Buffer, buf, pNdisParm->ParameterData.StringData.Length); + print_info("NdisReadConfiguration(): %s = (%d)'%s'\n", name, pNdisParm->ParameterData.StringData.Length, pNdisParm->ParameterData.StringData.Buffer); + } + else if( param_type == NdisParameterInteger ) + { + char *end_p; + pNdisParm->ParameterData.IntegerData = simple_strtol(buf, &end_p, 0); + if (end_p && *end_p && *end_p!=' ' && *end_p!='\n' + && *end_p!='\r' && *end_p!='\t') + { + print_err("\n...init_config: invalid int value for <%s> : %s\n", name, buf ); + return; + } + /*print_deb(" NdisReadConfiguration(): buf = %p (%.20s)\n", buf, buf );*/ + print_info("NdisReadConfiguration(): %s = %d\n", name, (INT32) pNdisParm->ParameterData.IntegerData); + } + else + { + print_err("NdisReadConfiguration(): unknow parameter type %d for %s\n", param_type, name ); + return; + } + *status = NDIS_STATUS_SUCCESS; + return; + + } +/* print_deb("NdisReadConfiguration(%d): (%c)%s - not found\n", init_file_length,*/ +/* (param_type == NdisParameterString) ? 'S' : 'D', name );*/ +#else + /* No init file support */ + *status = NDIS_STATUS_FAILURE; + +#endif + return ; +} + +VOID NdisWriteConfiguration( OUT PNDIS_STATUS Status, + IN NDIS_HANDLE ConfigurationHandle, + IN PNDIS_STRING Keyword, + IN PNDIS_CONFIGURATION_PARAMETER ParameterValue ) +{ + print_err(" NdisWriteConfiguration(): ** not implemented yet ...\n"); +} + +VOID NdisReadNetworkAddress( OUT PNDIS_STATUS Status, OUT PVOID *NetworkAddress, OUT PUINT NetworkAddressLength, + IN NDIS_HANDLE ConfigurationHandle ) +{ + print_err(" NdisReadNetworkAddress(): ** not implemented yet ...\n"); +} + +VOID NdisMIndicateStatus( + NDIS_HANDLE MiniportAdapterHandle, + NDIS_STATUS GeneralStatus, + PVOID StatusBuffer, + UINT StatusBufferSize +) +{ +} diff --git a/sta_dk_4_0_4_32/pform/linux/src/osapi.c b/sta_dk_4_0_4_32/pform/linux/src/osapi.c new file mode 100644 index 0000000..c90e717 --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/osapi.c @@ -0,0 +1,1765 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + + +#include "arch_ti.h" + +#include <linux/stddef.h> +#include <linux/string.h> +#include <linux/time.h> +#include <linux/timer.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/vmalloc.h> +#include <linux/string.h> +#include <linux/delay.h> +#include <linux/time.h> +#include <linux/list.h> +#include <asm/io.h> + +#include "debug_module.h" +#include "esta_drv.h" +#ifdef DRIVER_PROFILING +#include "tiwlan_profile.h" +#endif +#include "osApi.h" +#include "osTIType.h" +#include "srcApi.h" +#include "whalHwRegs.h" +#include "bmtrace.h" +#include "TI_IPC_Api.h" +#include "whalBus_Defs.h" +#include "802_11Defs.h" +#include "Ethernet.h" + +#define OS_PROTECT_HANDLE 0xffffeee0 +/*#define DEBUG_REG_ACCESS*/ + +#ifdef DEBUG_REG_ACCESS +#define PRINT_REG(fmt, args...) print_info(fmt, args) +#else +#define PRINT_REG(fmt, args...) +#endif +#define NOPRINT_REG(fmt, args...) + +#ifdef ESTA_TIMER_DEBUG +#define esta_timer_log(fmt,args...) printk(fmt, ## args) +#else +#define esta_timer_log(fmt,args...) +#endif + +#define FRAG_SIZE 200 + +/* Wlan chip reset defines */ +#define GPIO_16 16 +#define GPIO_16_DIRECTION_OUTPUT 0 +#define GPIO_16_CLEAR 0 +#define GPIO_16_SET 1 + +#define GPIO1_IRQSTATUS1 0xFFFBE418 +#define GPIO1_DATAIN 0xFFFBE42C + +/********************* LOCAL DECLARATIONS ************************/ +static inline void os_timer_dec_use_count(timer_obj_t *tmr); +static int os_tl_timerHandlr(struct tiwlan_req *req); +static void os_timerHandlr(unsigned long parm); +static void send_frag(char* msg, int message_len, int level, int module); + +BOOL use_debug_module = FALSE; + +/**************************************************************************************** + * * + * OS Report API * + * * + ****************************************************************************************/ + +/**************************************************************************************** + * os_setDebugMode() + **************************************************************************************** +DESCRIPTION: Set the Debug Mode + +INPUT: + +RETURN: None + +NOTES: +*****************************************************************************************/ +void os_setDebugMode(BOOL enable) +{ + use_debug_module = enable; +} + + +/**************************************************************************************** + * os_printf() + **************************************************************************************** +DESCRIPTION: Print formatted output. + +INPUT: format - Specifies the string, to be printed + +RETURN: None + +NOTES: +*****************************************************************************************/ +void os_printf(const char *format ,...) +{ + static int from_new_line = 1; /* Used to save the last message EOL */ + static UINT8 module = 0; /* Used to save the last message module */ + static UINT8 level = 0; /* Used to save the last message level */ + va_list ap; + static char msg[500]; + char *p_msg = msg; /* Pointer to the message */ + UINT16 message_len; + UINT32 sec = 0; + UINT32 uSec = 0; + + /* Format the message and keep the message length */ + va_start(ap,format); + message_len = vsnprintf(&msg[1], sizeof(msg) - 1, format, ap); + + + if (use_debug_module) + { + /*********************/ + /* Use debug module */ + /*******************/ + + if (msg[1] == '$') + { + /************************************ + Message format: "$XX" + ||| + message prefix ----||| + module index -------|| + severity index ------| + ************************************/ + + level = (msg[2] - 'A'); + module = (msg[3] - 'A'); + } + else + { + send_frag(msg, message_len, level, module); + } + } + else + { + /***********************/ + /* Use regular printk */ + /*********************/ + + if( from_new_line ) + { + if (msg[1] == '$') + { + p_msg += 4; + } + + sec = os_timeStampUs(NULL); + uSec = sec % 1000000; + sec /= 1000000; + + printk(KERN_INFO DRIVER_NAME ": %d.%06d: %s",sec,uSec,p_msg); + } + else + { + printk(&msg[1]); + } + + from_new_line = ( msg[message_len] == '\n' ); + } +} + +static void send_frag(char* msg, int message_len, int level, int module) +{ +#ifdef TIWLAN_OMAP1610 /* Dm: */ + int return_value; + int offset = 1; + int TmpLen; + char* FragMsg; + + do + { + TmpLen = min(message_len - offset, FRAG_SIZE); + FragMsg = msg + offset - 1; + FragMsg[0] = module; + + return_value = debug_module_enqueue_message(DEBUG_MODULE_TRACE_QUEUE_ID, level, FragMsg, TmpLen+1, CONTROL_CODE_TYPE_MESSAGE); + + if (return_value) + { + /* Message overrun */ + + /* Send the overrun indication to the debug module */ + os_memoryCopy(NULL, &msg[1], "*** Message Overrun ***", strlen("*** Message Overrun ***")); + msg[0] = 0; + debug_module_enqueue_message(DEBUG_MODULE_TRACE_QUEUE_ID, 0, msg, (strlen("*** Message Overrun ***") + 1), CONTROL_CODE_TYPE_MESSAGE); + + /* Print overrun indication to the terminal */ + /*printk(KERN_INFO DRIVER_NAME ": %d.%06d: %s\n", sec, uSec, "**** Debug module message overrun! ****\n");*/ + } + offset += TmpLen; + }while (offset < message_len); + +#endif +} + +/**************************************************************************************** + * * + * OS DMA CALLBACK API * + ****************************************************************************************/ + +/**************************************************************************************** + * os_TNETWIF_BusTxn_Complete() + **************************************************************************************** +DESCRIPTION: Callback directly called at an IRQ context from the SPI modue + This should triger a tasklet_schedule so that the End of DMA will be handled + in a tasklet context and then be directed to the TNETWIF to call the Client callback. + +INPUT: OsContext - our adapter context. + +RETURN: None + +NOTES: +*****************************************************************************************/ +void os_TNETWIF_BusTxn_Complete(TI_HANDLE OsContext,int status) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)OsContext; + + drv->dma_done = 1; +#ifdef DM_USE_WORKQUEUE + /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */ + if( queue_work( drv->tiwlan_wq, &drv->tw ) != 0 ) { +#ifdef CONFIG_ANDROID_POWER + android_lock_suspend( &drv->timer_wake_lock ); +#endif + } +#else + tasklet_schedule(&drv->tl); +#endif +} + +/**************************************************************************************** + * * + * OS TIMER API * + * * + ****************************************************************************************/ + +/**************************************************************************************** + * os_timerCreate() + **************************************************************************************** +DESCRIPTION: This function creates and initializes a timer object associated with a + caller's pRoutine function. + +ARGUMENTS: + +RETURN: A handle of the created timer. + TI_HANDLE_INVALID if there is insufficient memory available + +NOTES: Using the Kernel timer feature, problem is that kernel timers are one-shots. + For timers that are periodic this abstraction layer will have to mediate + between the callback function and the re-submission of a timer request. + +*****************************************************************************************/ +TI_HANDLE +os_timerCreate( + TI_HANDLE OsContext, + PTIMER_FUNCTION pRoutine, + TI_HANDLE Context + ) +{ + timer_obj_t *tmr; + +#ifdef ESTA_TIMER_DEBUG + esta_timer_log("\n\n%s:%d ::os_timerCreate(%p,%p,%p)",__FUNCTION__, __LINE__,OsContext,pRoutine,Context); +#endif + ti_nodprintf(TIWLAN_LOG_INFO, "\n----> os_timerCreate function = 0x%08x , context= 0x%08x", + (int)pRoutine, (int)Context); + + os_profile (OsContext, 6, 0); + + tmr = os_memoryAlloc (OsContext, sizeof(timer_obj_t)); + if (tmr == NULL) + return(TI_HANDLE_INVALID); + + memset (tmr,0,sizeof(timer_obj_t)); + + init_timer(&tmr->timer); + INIT_LIST_HEAD(&tmr->req.list); + tmr->timer.function = os_timerHandlr; + tmr->timer.data = (int)tmr; + tmr->req.drv = (tiwlan_net_dev_t *)OsContext; + tmr->req.u.req.p1 = (UINT32)pRoutine; + tmr->req.u.req.p2 = (UINT32)Context; + tmr->req.u.req.f = os_tl_timerHandlr; + tmr->use_count = 1; + + esta_timer_log("=%p\n\n", tmr); + + return (TI_HANDLE)tmr; +} + + +/**************************************************************************************** + * os_timerDestroy() + **************************************************************************************** +DESCRIPTION: This function destroy the timer object. + +ARGUMENTS: + +RETURN: + +NOTES: Returning the Kernel level timer_list memory allocation and the + abstraction level timer object. +*****************************************************************************************/ +VOID +os_timerDestroy( + TI_HANDLE OsContext, + TI_HANDLE TimerHandle + ) +{ + timer_obj_t *tmr = TimerHandle; + + os_profile (OsContext, 6, 0); + + os_timerStop (OsContext, TimerHandle); + os_timer_dec_use_count (tmr); +} + + +/**************************************************************************************** + * os_timerStart() + **************************************************************************************** +DESCRIPTION: This function start the timer object. + +ARGUMENTS: + +RETURN: + +NOTES: +*****************************************************************************************/ +VOID +os_timerStart( + TI_HANDLE OsContext, + TI_HANDLE TimerHandle, + UINT32 DelayMs, + BOOL bPeriodic + ) +{ + timer_obj_t *tmr= (timer_obj_t *)TimerHandle; + + UINT32 jiffie_cnt = msecs_to_jiffies(DelayMs); + +#ifdef ESTA_TIMER_DEBUG + esta_timer_log("\n\n%s:%d ::os_timerStart(%p,%p,%u,%d)\n\n",__FUNCTION__, __LINE__,OsContext,TimerHandle,DelayMs,bPeriodic); +#endif + + tmr->req.u.req.p3 = bPeriodic; + tmr->req.u.req.p4 = jiffie_cnt; + tmr->timer.data = (unsigned long)tmr; + mod_timer(&tmr->timer, jiffies + jiffie_cnt); + + + return; +} + +/**************************************************************************************** + * os_stopTimer() + **************************************************************************************** +DESCRIPTION: This function stop the timer object. + +ARGUMENTS: + +RETURN: + +NOTES: +*****************************************************************************************/ +VOID +os_timerStop( + TI_HANDLE OsContext, + TI_HANDLE TimerHandle + ) +{ + timer_obj_t *tmr= (timer_obj_t *)TimerHandle; + + del_timer_sync(&tmr->timer); + tmr->req.u.req.p3 = 0; /* Turn "periodic" off */ + list_del_init(&tmr->req.list); + + return; +} + +/**************************************************************************************** + * os_periodicIntrTimerStart() + **************************************************************************************** +DESCRIPTION: This function starts the periodic interrupt mechanism. This mode is used + when interrupts that usually received from the Fw is now masked, and we are + checking for any need of Fw handling in time periods. + +ARGUMENTS: + +RETURN: + +NOTES: Power level of the CHIP should be always awake in this mode (no ELP) +*****************************************************************************************/ +VOID +os_periodicIntrTimerStart( + TI_HANDLE OsContext + ) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)OsContext; + + mod_timer (&drv->poll_timer, jiffies + TIWLAN_IRQ_POLL_INTERVAL); +} + +/**************************************************************************************** + * os_timeStampMs() + **************************************************************************************** +DESCRIPTION: This function returns the number of milliseconds that have elapsed since + the system was booted. + +ARGUMENTS: OsContext - our adapter context. + +RETURN: + +NOTES: +*****************************************************************************************/ +UINT32 +os_timeStampMs( + TI_HANDLE OsContext + ) +{ + struct timeval tv; + do_gettimeofday(&tv); + return tv.tv_sec*1000 + tv.tv_usec/1000; +} + +/**************************************************************************************** + * os_timeStampUs() + **************************************************************************************** +DESCRIPTION: This function returns the number of microseconds that have elapsed since + the system was booted. + +ARGUMENTS: OsContext - our adapter context. + Note that sometimes this function will be called with NULL(!!!) as argument! + +RETURN: + +NOTES: +*****************************************************************************************/ +UINT32 +os_timeStampUs( + TI_HANDLE OsContext + ) +{ + struct timeval tv; + do_gettimeofday(&tv); + return tv.tv_sec*1000000 + tv.tv_usec; +} + +/**************************************************************************************** + * os_StalluSec() + **************************************************************************************** +DESCRIPTION: This function make delay in microseconds. + +ARGUMENTS: OsContext - our adapter context. + uSec - delay time in microseconds + +RETURN: + +NOTES: +*****************************************************************************************/ +VOID +os_StalluSec( + TI_HANDLE OsContext, + UINT32 uSec + ) +{ + /*UINT32 usec_now = os_timeStampUs(OsContext); + while(os_timeStampUs(OsContext) - usec_now < uSec) + ; + */ + udelay(uSec); +} + +/**************************************************************************************** + * os_WaitComplete() + **************************************************************************************** +DESCRIPTION: This function start waiting for the complete + +ARGUMENTS: + +RETURN: + +NOTES: can be called only from process context, and not from tasklet +*****************************************************************************************/ +VOID +os_WaitComplete( + TI_HANDLE OsContext + ) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)OsContext; + + /* ti_dprintf(TIWLAN_LOG_INFO, "os_WaitComplete drv %x drv->comp %x\n",(UINT32)drv,(UINT32)&drv->comp); */ + + /* + he tasklet should them send back the user (here)the completion event so the user could + go through the configuration phase + */ + wait_for_completion(&drv->comp); +} + +/**************************************************************************************** + * os_Complete() + **************************************************************************************** +DESCRIPTION: This function signals to the waiting process that completion occured + +ARGUMENTS: + +RETURN: + +NOTES: +*****************************************************************************************/ +VOID +os_Complete( + TI_HANDLE OsContext + ) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)OsContext; + + /* ti_dprintf(TIWLAN_LOG_INFO, "os_Complete drv %x drv->comp %x\n",(UINT32)drv, (UINT32)&drv->comp); */ + + /* + Call the completion routine that will unblock the caller that was waiting on that object + */ + complete(&drv->comp); +} + + + +/**************************************************************************************** + * * + * Hardware access functions API * + * * + ****************************************************************************************/ + +/**************************************************************************************** + * os_clearWlanReady() + **************************************************************************************** +DESCRIPTION: Clear the WLAN Ready Interrupt Line stored in the PIC Controller + +INPUT: None + +RETURN: None + +NOTES: +*****************************************************************************************/ + +__inline__ VOID +os_clearWlanReady( + void) +{ +#ifdef TIWLAN_OMAP1610 + omap_writel(4,GPIO1_IRQSTATUS1); +#endif +} + + +/**************************************************************************************** + * os_senseIrqLine() + **************************************************************************************** +DESCRIPTION: Read the WLAN_IRQ line + +INPUT: void + +RETURN: Read value + +NOTES: +*****************************************************************************************/ + +__inline__ UINT32 +os_senseIrqLine( + TI_HANDLE OsContext + ) +{ +#ifdef TIWLAN_OMAP1610 + return (omap_readl(GPIO1_DATAIN) & 0x4); +#else + return 0; +#endif +} + + + +/**************************************************************************************** + * os_hwGetRegistersAddr() + **************************************************************************************** +DESCRIPTION: + +ARGUMENTS: + +RETURN: + +NOTES: +*****************************************************************************************/ +PVOID +os_hwGetRegistersAddr( + TI_HANDLE OsContext + ) +{ + return (PVOID)OS_API_REG_ADRR; +} + +/**************************************************************************************** + * os_hwGetMemoryAddr() + **************************************************************************************** +DESCRIPTION: + +ARGUMENTS: + +RETURN: + +NOTES: +*****************************************************************************************/ +PVOID +os_hwGetMemoryAddr( + TI_HANDLE OsContext + ) +{ + return (PVOID)OS_API_MEM_ADRR; +} + +/**************************************************************************************** + * os_memoryGetPhysicalLow() + **************************************************************************************** +DESCRIPTION: return the lower 32 bits of a 64bit number / address * + +ARGUMENTS: + +RETURN: + +NOTES: +*****************************************************************************************/ +UINT32 os_memoryGetPhysicalLow (OS_PHYSICAL_ADDRESS pAddr) +{ + UINT32 res; + res = pAddr & 0xffffffff; + ti_dprintf(TIWLAN_LOG_ERROR, "\n 64bit low. Got 0x%x; Returning 0x%x \n", (UINT32)pAddr, res); + return res; +} + +/**************************************************************************************** + * os_memoryGetPhysicalHigh() + **************************************************************************************** +DESCRIPTION: return the higher order 32 bits of a 64bit number / address * + +ARGUMENTS: + +RETURN: + +NOTES: +*****************************************************************************************/ +UINT32 os_memoryGetPhysicalHigh (OS_PHYSICAL_ADDRESS pAddr) +{ + UINT32 res; + res = pAddr >> 32; + ti_dprintf(TIWLAN_LOG_ERROR, "\n 64bit high. Got 0x%x; Returning 0x%x \n", (UINT32)pAddr, res); + return res; +} + + +/**************************************************************************************** + * * + * Protection services API * + * * + **************************************************************************************** + * OS protection is implemented as dummy functions because * + * all driver code is executed in context of a single tasklet, * + * except IOCTL handlers and xmition. * + * Protection in IOCTL handlers and hard_start_xmit is done by different * + * means. * + ****************************************************************************************/ + + +/**************************************************************************************** + * os_protectCreate() + **************************************************************************************** +DESCRIPTION: + +ARGUMENTS: OsContext - our adapter context. + +RETURN: A handle of the created mutex/spinlock. + TI_HANDLE_INVALID if there is insufficient memory available or problems + initializing the mutex + +NOTES: +*****************************************************************************************/ +TI_HANDLE +os_protectCreate( + TI_HANDLE OsContext + ) +{ + return (TI_HANDLE)OS_PROTECT_HANDLE; +} + + + +/**************************************************************************************** + * os_protectDestroy() + **************************************************************************************** +DESCRIPTION: + +ARGUMENTS: OsContext - our adapter context. + +RETURN: None - This had better work since there is not a return value to the user + +NOTES: +*****************************************************************************************/ +VOID +os_protectDestroy( + TI_HANDLE OsContext, + TI_HANDLE ProtectCtx + ) +{ + return; +} + + +/**************************************************************************************** + * os_protectLock() + **************************************************************************************** +DESCRIPTION: + +ARGUMENTS: OsContext - our adapter context. + +RETURN: None - This had better work since there is not a return value to the user + +NOTES: +*****************************************************************************************/ +VOID +os_protectLock( + TI_HANDLE OsContext, + TI_HANDLE ProtectContext + ) +{ +#if 1 /* uncomment for work in INDIRECT mode (HwACXAccessMethod=0) */ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)OsContext; + spin_lock_irqsave(&drv->lock, drv->flags); +#endif +} + + +/**************************************************************************************** + * os_protectUnlock() + **************************************************************************************** +DESCRIPTION: + +ARGUMENTS: OsContext - our adapter context. + +RETURN: None - This had better work since there is not a return value to the user + +NOTES: +*****************************************************************************************/ +VOID +os_protectUnlock( + TI_HANDLE OsContext, + TI_HANDLE ProtectContext + ) +{ +#if 1 /* uncomment for work in INDIRECT mode (HwACXAccessMethod=0) */ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)OsContext; + spin_unlock_irqrestore(&drv->lock, drv->flags); +#endif +} + + +/*----------------------------------------------------------------------------- + +Routine Name: + + os_resetWakeOnGpio + +Routine Description: + + set the GPIO to low after awaking the TNET from ELP. + +Arguments: + + OsContext - our adapter context. + + +Return Value: + + None + +-----------------------------------------------------------------------------*/ +VOID +os_hardResetTnetw( void ) +{ +/* + * Define the OMAP GPIO registers, the TNETW reset is currently connected + * to GPIO 16, this logic assumes that the loading code had muxed the + * GPIO 16 to the Y1 pinout. + */ + /* direction out */ +#ifdef TIWLAN_OMAP1610 + omap_set_gpio_direction(GPIO_16, GPIO_16_DIRECTION_OUTPUT); + + /* clear reset WLAN chip */ + omap_set_gpio_dataout(GPIO_16, GPIO_16_CLEAR); + + /* wait for 50msec */ + mdelay(50); + omap_set_gpio_dataout(GPIO_16, GPIO_16_SET); + + /* wait for 50msec */ + mdelay(50); +#endif /* Dm: */ +#ifdef TIWLAN_MSM7000 + msm_wifi_reset(1); /* Reset active */ + msm_wifi_power(0); /* Power disable */ + msm_wifi_power(1); /* Power enable */ + msm_wifi_reset(0); /* Reset clear */ +#endif +} + + +#ifndef GWSI_DRIVER + +/**************************************************************************************** + START OF TI DRIVER API +*****************************************************************************************/ + +/**************************************************************************************** + * os_setWakeOnGpio() + **************************************************************************************** +DESCRIPTION: set the GPIO to high for awaking the TNET from ELP. + +ARGUMENTS: OsContext - our adapter context. + +RETURN: None + +NOTES: +*****************************************************************************************/ +VOID +os_setWakeOnGpio( + TI_HANDLE OsContext + ) +{ +#ifdef TIWLAN_OMAP1610 + /* + Clear ELP_REQ by GPIO_CLEAR_DATAOUT + */ + os_resetWakeOnGpio(OsContext); + + /* + Rising edge on ELP_REQ by GPIO_SET_DATAOUT + */ + omap_writel(0x00000200, 0xFFFBBCF0); +#endif +} + +/**************************************************************************************** + * os_resetWakeOnGpio() + **************************************************************************************** +DESCRIPTION: set the GPIO to low after awaking the TNET from ELP. + +ARGUMENTS: OsContext - our adapter context. + +RETURN: None + +NOTES: +*****************************************************************************************/ +VOID +os_resetWakeOnGpio( + TI_HANDLE OsContext + ) +{ + /* + Clear ELP_REQ by GPIO_CLEAR_DATAOUT + */ +#ifdef TIWLAN_OMAP1610 + omap_writel(0x00000200, 0xFFFBBCB0); +#endif +} + +/**************************************************************************************** + * _os_memorySharedFree() + **************************************************************************************** +DESCRIPTION: + +ARGUMENTS: + +RETURN: + +NOTES: +*****************************************************************************************/ +VOID +_os_memorySharedFree( + TI_HANDLE OsContext, + PVOID pVirtual, + UINT32 Size, + OS_PHYSICAL_ADDRESS pPhysical + ) +{ + ti_dprintf(TIWLAN_LOG_ERROR, "\n\n\n %s is not implemented\n\n\n", __FUNCTION__); +} + +/**************************************************************************************** + * _os_memorySharedAlloc() + **************************************************************************************** +DESCRIPTION: + +ARGUMENTS: + +RETURN: + +NOTES: +*****************************************************************************************/ +PVOID +_os_memorySharedAlloc( + TI_HANDLE OsContext, + UINT32 Size, + OS_PHYSICAL_ADDRESS *pPhysical + ) +{ + ti_dprintf(TIWLAN_LOG_ERROR, "\n\n\n %s is not implemented\n\n\n", __FUNCTION__); + return NULL; +} + +/**************************************************************************************** + * os_powerStateBusy() + **************************************************************************************** +DESCRIPTION: notify to the host that the TI_WLAN application is busy. + +ARGUMENTS: OsContext - our adapter context. + +RETURN: + +NOTES: +*****************************************************************************************/ +VOID +os_powerStateBusy( + TI_HANDLE OsContext + ) +{ +#if 0 + ti_dprintf(TIWLAN_LOG_INFO, + "%s(%d) - os_powerStateBusy: TI_WLAN is busy!\n", + __FILE__,__LINE__); +#endif +} + +/**************************************************************************************** + * os_powerStateIdle() + **************************************************************************************** +DESCRIPTION: notify to the host that the TI_WLAN application is idle. + +ARGUMENTS: OsContext - our adapter context. + +RETURN: + +NOTES: +*****************************************************************************************/ +VOID +os_powerStateIdle( + TI_HANDLE OsContext + ) +{ +#if 0 + ti_dprintf(TIWLAN_LOG_INFO, + "%s(%d) - os_powerStateIdle: TI_WLAN is idle!\n", + __FILE__,__LINE__); +#endif +} + +/**************************************************************************************** + * os_memoryMove() + **************************************************************************************** +DESCRIPTION: Move memory block from pSource to pDestination + +ARGUMENTS: OsContext - Our adapter context. + pDestination - destination + pSource - source + Size - Number of characters +RETURN: + +NOTES: +*****************************************************************************************/ +VOID +os_memoryMove( + TI_HANDLE pOsContext, + PVOID pDestination, + PVOID pSource, + UINT32 Size + ) +{ + memmove(pDestination, pSource, Size); +} + + +/**************************************************************************************** + * os_memoryMoveToHw() + **************************************************************************************** +DESCRIPTION: This function copies data from a system-space buffer to device memory. + +ARGUMENTS: OsContext - Our adapter context. + + pTarget - Specifies the base address within a device memory range where + the copy should begin. + + pSource - Pointer to a system-space buffer from which this function copies + data to the destination range. + + Size - Specifies the number of bytes to copy. + +RETURN: None + +NOTES: +*****************************************************************************************/ +VOID +os_memoryMoveToHw( + TI_HANDLE OsContext, + PVOID pTarget, + PVOID pSource, + UINT32 Size + ) +{ + print_info("\nos_memoryMoveToHw pTarget 0x%08x pSource 0x%08x Size 0x%08x",(int)pTarget, (int)pSource,(int)Size); + print_info("\n-------------------------> Not Implemented <--------------------------------------------------- "); +} + +/**************************************************************************************** + * os_memoryMoveFromHw() + **************************************************************************************** +DESCRIPTION: This function copies data from a system-space buffer to device memory. + +ARGUMENTS: OsContext - Our adapter context. + + pTarget - Pointer to a system-space buffer into which this function copies + data from device memory. + + pSource - Specifies the base virtual address within device memory from + which to copy the data. + + Size - Specifies the number of bytes to copy. + +RETURN: None + +NOTES: +*****************************************************************************************/ +VOID +os_memoryMoveFromHw( + TI_HANDLE OsContext, + PVOID pTarget, + PVOID pSource, + UINT32 Size + ) +{ + print_info("\nos_memoryMoveFromHw pTarget 0x%08x pSource 0x%08x Size 0x%08x",(int)pTarget, (int)pSource,(int)Size); + print_info("\n-------------------------> Not Implemented <--------------------------------------------------- "); +} + +/**************************************************************************************** + * os_hwReadMemRegisterUINT8() + **************************************************************************************** +DESCRIPTION: Reads a UINT8 from a memory-mapped device register. + +ARGUMENTS: OsContext - our adapter context. + + Register - Pointer to the memory-mapped register. + + Data - Pointer to the caller-supplied variable in which this function + returns the UINT8 read from Register. + +RETURN: None + +NOTES: +*****************************************************************************************/ +VOID +os_hwReadMemRegisterUINT8( + TI_HANDLE OsContext, + PUCHAR Register, + PUINT8 Data + ) +{ + *Data = *Register; + PRINT_REG("R8: %p=0x%x\n", Register, *Data); + return; +} + +/**************************************************************************************** + * os_hwWriteMemRegisterUINT16() + **************************************************************************************** +DESCRIPTION: Writes a 'unsigned short' to a memory-mapped device register. + +ARGUMENTS: OsContext - our adapter context. + + Register - Pointer to the memory-mapped register. + + Data - Specifies the caller-supplied UINT16 that this function transfers + to the Register. + +RETURN: None + +NOTES: +*****************************************************************************************/ +VOID +os_hwWriteMemRegisterUINT16( + TI_HANDLE OsContext, + PUINT16 Register, + UINT16 Data + ) +{ + PRINT_REG("W16: %p=0x%x\n", Register, Data); + *Register = Data; + return; +} + +/**************************************************************************************** + * os_hwReadMemRegisterUINT16() + **************************************************************************************** +DESCRIPTION: Reads a UINT16 from a memory-mapped device register. + +ARGUMENTS: OsContext - our adapter context. + + Register - Pointer to the memory-mapped register. + + Data - Pointer to the caller-supplied variable in which this function + returns the UINT16 read from Register. + +RETURN: None + +NOTES: +*****************************************************************************************/ +VOID +os_hwReadMemRegisterUINT16( + TI_HANDLE OsContext, + PUINT16 Register, + PUINT16 Data + ) +{ + *Data = *Register; + PRINT_REG("R16: %p=0x%x\n", Register, *Data); + return; +} + +/**************************************************************************************** + * os_hwWriteMemRegisterUINT32() + **************************************************************************************** +DESCRIPTION: Writes a 'unsigned long' to a memory-mapped device register. + +ARGUMENTS: OsContext - our adapter context. + + Register - Pointer to the memory-mapped register. + + Data - Specifies the caller-supplied UINT32 that this function transfers + to the Register. + +RETURN: None + +NOTES: +*****************************************************************************************/ +VOID +os_hwWriteMemRegisterUINT32( + TI_HANDLE OsContext, + PUINT32 Register, + UINT32 Data + ) +{ + PRINT_REG("W32: %p=0x%x\n", Register, Data); + *Register = Data; + return; +} + + +/**************************************************************************************** + * os_hwReadMemRegisterUINT32() + **************************************************************************************** +DESCRIPTION: Reads a UINT32 from a memory-mapped device register. + +ARGUMENTS: OsContext - our adapter context. + + Register - Pointer to the memory-mapped register. + + Data - Pointer to the caller-supplied variable in which this function + returns the UINT32 read from Register. + +RETURN: None + +NOTES: +*****************************************************************************************/ +VOID +os_hwReadMemRegisterUINT32( + TI_HANDLE OsContext, + PUINT32 Register, + PUINT32 Data + ) +{ + *Data = *Register; + PRINT_REG("R32: %p=0x%x\n", Register, *Data); + return; +} + + +/**************************************************************************************** + * os_receivePacket() + **************************************************************************************** +DESCRIPTION: + +ARGUMENTS: + +RETURN: + +NOTES: +*****************************************************************************************/ +BOOL +os_receivePacket( + TI_HANDLE OsContext, + PVOID pPacket, + UINT16 Length + ) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)OsContext; + struct sk_buff *skb; + mem_MSDU_T* pMsdu = (mem_MSDU_T*)pPacket; + mem_BD_T *pCurBd; + ti_nodprintf(TIWLAN_LOG_INFO, "os_receivePacket - Received EAPOL len-%d\n", pMsdu->firstBDPtr->length ); + + bm_trace(10, Length, 0); + + if (pMsdu->firstBDPtr->length > Length) { /* Dm: Security fix */ + ti_dprintf(TIWLAN_LOG_ERROR, " TI: %s - Security Error\n", __FUNCTION__); + return FALSE; + } + + skb = dev_alloc_skb(Length+2); + if(!skb) { + print_deb(" os_receivePacket() : dev_alloc_skb failed!\n"); + configMgr_memMngrFreeMSDU(drv->adapter.CoreHalCtx, memMgr_MsduHandle(pPacket)); + drv->stats.rx_dropped++; + return FALSE; + } + skb_reserve(skb, 2); + + pCurBd = pMsdu->firstBDPtr; + while (pCurBd) { + memcpy(skb_put(skb,pCurBd->length),pCurBd->data+pCurBd->dataOffset,pCurBd->length); + pCurBd = pCurBd->nextBDPtr; + } + + skb->dev = drv->netdev; + skb->protocol = eth_type_trans(skb, drv->netdev); + skb->ip_summed = CHECKSUM_NONE; + + drv->stats.rx_packets++; + drv->stats.rx_bytes += skb->len; + + bm_trace(11, Length, 0); +#ifdef CONFIG_ANDROID_POWER + drv->receive_packet = 1; /* Remember to stay awake */ +#endif + netif_rx(skb); + + configMgr_memMngrFreeMSDU(drv->adapter.CoreHalCtx, memMgr_MsduHandle(pPacket)); + + bm_trace(12, Length, 0); + + return TRUE; +} + +/**************************************************************************************** + * os_sendPacket() + **************************************************************************************** +DESCRIPTION: send EAPOL packet from Supplicant + +ARGUMENTS: + +RETURN: + +NOTES: +*****************************************************************************************/ +INT32 +os_sendPacket( + TI_HANDLE OsContext, + PVOID pPacket, + UINT16 Length + ) +{ + struct net_device *dev = (struct net_device *)OsContext; + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)dev->priv; + + INT32 status; + mem_MSDU_T* pMsdu; + char *pMsduData; + UINT32 packetHeaderLength; + + ti_nodprintf(TIWLAN_LOG_INFO, "os_sendPacket - Transmit EAPOL len-%x\n",Length ); + + /* + * Allocate enough place also for 802.11 header (24 bytes) and LLC (8 bytes) + * to replace the Ethernet header (14 bytes) + */ + if(!Length) + { + ti_dprintf(TIWLAN_LOG_ERROR, " EAPOL Packet Length = 0 \n"); + return -1; + } + /* + * Retrieve the Packet Header length + * from QoS Manager (through configMgr) and RSN + */ + packetHeaderLength = configMgr_getPacketHeaderLength(drv->adapter.CoreHalCtx,pPacket,TX_DATA_EAPOL_MSDU); + + /* + * need to reserve enough space for header translation + * in the same first Bd. + * Allocate enough place also for 802.11 header (24 bytes or 26 for QoS) and LLC (8 bytes) + * to replace the Ethernet header (14 bytes) + */ + + status = configMgr_allocMSDU(drv->adapter.CoreHalCtx, &pMsdu, + Length + packetHeaderLength , OS_ABS_TX_MODULE); + if(status != OK) + { + ti_dprintf(TIWLAN_LOG_ERROR, " configMgr_allocMSDU failed !!!\n"); + ++drv->alloc_msdu_failures; + return -ENOMEM; + } + + /* + * case 1: only legacy wlan header + * + * case 2: only QoS wlan header + * + * case 3: only legacy wlan header with new snap + * + * case 4: only QoS wlan header with new snap + */ + pMsdu->firstBDPtr->dataOffset = packetHeaderLength - ETHERNET_HDR_LEN; + pMsduData = pMsdu->firstBDPtr->data + pMsdu->firstBDPtr->dataOffset; + memcpy(pMsduData, pPacket, Length); + pMsdu->dataLen = Length; + pMsdu->firstBDPtr->length = pMsdu->dataLen + pMsdu->firstBDPtr->dataOffset; + pMsdu->freeFunc = 0; + pMsdu->freeArgs[0] = 0; + pMsdu->freeArgs[1] = 0; + + /* + * Propagate Msdu through Config Manager. + * Set DTag to 0 + * (note that classification is further handled in the Core) + */ + status = configMgr_sendMsdu(drv->adapter.CoreHalCtx, pMsdu, 0); + + return status; +} + + +#endif /* NDEF GWSI_DRIVER*/ + + + +/******************************************************************************************************* + + LOCAL FUNCTIONS + +********************************************************************************************************/ + +/*----------------------------------------------------------------------------- +Routine Name: + + os_timer_dec_use_count + +Routine Description: + + This function is decrements timer use count. + When use_count becomes 0, the timer block is destroyed +-----------------------------------------------------------------------------*/ +static inline void os_timer_dec_use_count(timer_obj_t *tmr) +{ + if (unlikely(!tmr->use_count)) { + ti_dprintf(TIWLAN_LOG_ERROR, "\n\n\n %s: attempt to delete a deleted timer %p\n\n\n", __FUNCTION__, tmr); + tmr->use_count = 1; + } + if (!(--tmr->use_count)) + os_memoryFree(tmr->req.drv, tmr, sizeof(timer_obj_t)); +} + + +/*----------------------------------------------------------------------------- + +Routine Name: + + os_tl_timerHandlr + +Routine Description: + + This function is called in context of the control tasklet. + It evokes user timer handler and restarts the timer if periodic + +Arguments: + p1 - user handler + p2 - user parameter + p3 - periodic + p4 - jiffies + +Return Value: + + None. + +Notes: + +-----------------------------------------------------------------------------*/ +static int os_tl_timerHandlr(struct tiwlan_req *req) +{ + timer_obj_t *tmr= (timer_obj_t *)req; + PTIMER_FUNCTION f = (PTIMER_FUNCTION)req->u.req.p1; + TI_HANDLE parm = (TI_HANDLE)req->u.req.p2; + + esta_timer_log("%s: req=0x%x f=0x%p parm=0x%p\n", __FUNCTION__, req, f, parm); + ++tmr->use_count; + f(parm); + if (req->u.req.p3) /* Periodic ? */ + mod_timer(&tmr->timer, jiffies + req->u.req.p4); + os_timer_dec_use_count(tmr); + + return 0; +} + + +/*----------------------------------------------------------------------------- + +Routine Name: + + os_timerHandlr + +Routine Description: + + This function is called on timer expiration in context of + softIsr. It delegates the timer handling to the control tasklet. + +Arguments: + parm - timer object handle + +Return Value: + + None. + +Notes: + +-----------------------------------------------------------------------------*/ +static void os_timerHandlr(unsigned long parm) +{ + timer_obj_t *tmr= (timer_obj_t *)parm; + tiwlan_net_dev_t *drv = tmr->req.drv; + unsigned long flags; + + esta_timer_log("%s: drv=%p f=0x%x ctx=0x%x\n", + __FUNCTION__, tmr->req.drv, tmr->req.u.req.p1, tmr->req.u.req.p2); + + spin_lock_irqsave(&drv->lock, flags); + list_del(&tmr->req.list); + list_add_tail(&tmr->req.list, &drv->request_q); + spin_unlock_irqrestore(&drv->lock, flags); +#ifdef DM_USE_WORKQUEUE + /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */ + if( queue_work( drv->tiwlan_wq, &drv->tw ) != 0 ) { +#ifdef CONFIG_ANDROID_POWER + android_lock_suspend( &drv->timer_wake_lock ); +#endif + } +#else + tasklet_schedule(&drv->tl); +#endif +} + + +/*----------------------------------------------------------------------------- + +Routine Name: + + os_connectionStatus + +Routine Description: + +The eSTA-DK will call this API so the OS stack is aware that the +WLAN layer is ready to function. + +Arguments: +cStatus = 1; WLAN in ready for network packets +cStatus = 0; WLAN in not ready for network packets + +Return Value: + + None + +-----------------------------------------------------------------------------*/ + +tiINT32 +os_IndicateEvent(IPC_EV_DATA* pData) +{ + IPC_EVENT_PARAMS * pInParam = (IPC_EVENT_PARAMS *)pData; + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)(pInParam->hUserParam); + /*UCHAR AuthBuf[sizeof(ULONG) + sizeof(OS_802_11_AUTHENTICATION_REQUEST)];*/ + + ti_nodprintf(TIWLAN_LOG_INFO, "\n os_ConnectionStatus Event 0x%08x \n", CsStatus->Event); + + switch(pInParam->uEventType) + { + case IPC_EVENT_ASSOCIATED: + if (drv->netdev != NULL) { + netif_carrier_on(drv->netdev); +#if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK) + queue_delayed_work(drv->tiwlan_wq, &drv->trxw, 0); +#endif + } + break; + + case IPC_EVENT_DISASSOCIATED: + if (drv->netdev != NULL) { +#if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK) + unsigned percent; + + cancel_delayed_work_sync(&drv->trxw); + percent = ( drv->started ) ? PWRSINK_WIFI_PERCENT_BASE : 0; +#ifdef CONFIG_HTC_PWRSINK + htc_pwrsink_set(PWRSINK_WIFI, percent); +#else + trout_pwrsink_set(PWRSINK_WIFI, percent); +#endif +#endif + netif_carrier_off(drv->netdev); + } + break; + + case IPC_EVENT_LINK_SPEED: + drv->adapter.LinkSpeed = (*(PULONG)pData->uBuffer * 10000) / 2; + ti_nodprintf(TIWLAN_LOG_INFO, "\n Link Speed = 0x%08x \n",drv->adapter.LinkSpeed); + break; + + case IPC_EVENT_AUTH_SUCC: +/* *(PULONG)AuthBuf = os802_11StatusType_Authentication; + memcpy((PUCHAR)&AuthBuf[sizeof(ULONG)], pData->uBuffer,sizeof(OS_802_11_AUTHENTICATION_REQUEST));*/ + ti_dprintf(TIWLAN_LOG_OTHER, "\n Auth Succ Event from Driver to another BSSID. \n"); + break; + + case IPC_EVENT_SCAN_COMPLETE: + ti_dprintf(TIWLAN_LOG_OTHER, "\n Driver Event = Scan Complete. \n"); + break; + + case IPC_EVENT_TIMEOUT: + ti_dprintf(TIWLAN_LOG_OTHER, "\n Driver Event = Timeout. \n"); + break; + + case IPC_EVENT_CCKM_START: + ti_dprintf(TIWLAN_LOG_OTHER, "\n Driver Event = IPC_EVENT_CCKM_START \n"); + break; + + default: + ti_dprintf(TIWLAN_LOG_ERROR, "\n Unrecognized driver event. \n"); + break; + + } + + return OK; +} + + +/****************************************************************************/ +/* The following 4 functions are debug functions that enable the user + to set/reset GPIO_25 and GPIO_27 in the OMAP - for debug purposes. + Note: In order to enable GPIO_25/GPIO_27 the user must enable the define + TIWLAN_OMAP1610_CRTWIPP_GPIO_DEBUG in the esta_drv.c/osapi.c files. */ + +void os_ToggleDebugGPIO(int count) +{ +#if 0 + int i,j; + + omap_writel(0x00000200, 0xFFFBBCB0 );/* 0 */ + for(i=0;i<count;i++) + { + omap_writel(0x00000200, 0xFFFBBCF0 );/* 1 */ + for(j=0;j<100;j++); + omap_writel(0x00000200, 0xFFFBBCB0 );/* 0 */ + for(j=0;j<100;j++); + } +#endif +} +#ifdef TIWLAN_OMAP1610_CRTWIPP_GPIO_DEBUG +VOID +os_SetGpio_25( + TI_HANDLE OsContext + ) +{ + /* + Setting GPIO_25 by GPIO_SET_DATAOUT + */ + omap_writel(0x00000200, 0xFFFBECF0 ); +} + + +VOID +os_ResetGpio25( + TI_HANDLE OsContext + ) +{ + /* + Clear GPIO_25 by GPIO_CLEAR_DATAOUT + */ + omap_writel(0x00000200, 0xFFFBECB0 ); +} + + +VOID +os_SetGpio27( + TI_HANDLE OsContext + ) +{ + /* + Setting GPIO_27 by GPIO_SET_DATAOUT + */ + omap_writel(0x00000800, 0xFFFBECF0 ); +} + + +VOID +os_ResetGpio27( + TI_HANDLE OsContext + ) +{ + /* + Clear GPIO_27 by GPIO_CLEAR_DATAOUT + */ + omap_writel(0x00000800, 0xFFFBECB0 ); +} +#endif +/******************************************************************************/ + +VOID +os_disableIrq( TI_HANDLE OsContext) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)OsContext; + disable_irq (drv->irq); +} + +VOID +os_enableIrq( TI_HANDLE OsContext) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)OsContext; + enable_irq (drv->irq); +} + +int +os_getFirmwareImage( + TI_HANDLE OsContext, + PUINT8 *pBuffer, + PUINT32 Length, + UINT8 RadioType + ) +{ + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)OsContext; + + *pBuffer = drv->firmware_image.va; + *Length = drv->firmware_image.size; + + return OK; +} + + +/*----------------------------------------------------------------------------- + +Routine Name: + + os_getRadioImage + +Routine Description: + + +Arguments: + + +Return Value: + + OK + +-----------------------------------------------------------------------------*/ +int +os_getRadioImage( + TI_HANDLE OsContext, + PUINT8 *pBuffer, + PUINT32 Length, + UINT8 RadioType + ) +{ + +#ifdef FIRMWARE_DYNAMIC_LOAD + tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)OsContext; + + *pBuffer = drv->eeprom_image.va; + *Length = drv->eeprom_image.size; +#else + extern unsigned char tiwlan_radimage[]; + extern unsigned int sizeof_tiwlan_radimage; + *pBuffer = (PUINT8)tiwlan_radimage; + *Length = sizeof_tiwlan_radimage; +#endif + ti_dprintf(TIWLAN_LOG_INFO, "%s: radio type: 0x%x\n", __FUNCTION__, RadioType); + + return OK; +} + + +#ifdef DRIVER_PROFILING +void _os_profile (TI_HANDLE OsContext, UINT32 fn, UINT32 par) +{ + tiwlan_profile (OsContext, fn, par); +} +#endif + +VOID +os_closeFirmwareImage( TI_HANDLE OsContext ) +{ + return; +} + +VOID +os_closeRadioImage( TI_HANDLE OsContext ) +{ + return; +} diff --git a/sta_dk_4_0_4_32/pform/linux/src/osmemapi.c b/sta_dk_4_0_4_32/pform/linux/src/osmemapi.c new file mode 100644 index 0000000..d22eacb --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/osmemapi.c @@ -0,0 +1,483 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + + +#include "arch_ti.h" + +#include <linux/stddef.h> +#include <linux/string.h> +#include <linux/time.h> +#include <linux/timer.h> + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/vmalloc.h> +#include <linux/string.h> +#include <linux/delay.h> +#include <linux/time.h> +#include <linux/list.h> + +#include "osApi.h" +#include "osTIType.h" +#include "esta_drv.h" + +typedef void (*os_free)(void *); +struct os_mem_block +{ + struct list_head blk_list; + os_free f_free; + __u32 size; + __u32 signature; +}; +#define MEM_BLOCK_START (('m'<<24) | ('e'<<16) | ('m'<<8) | 's') +#define MEM_BLOCK_END (('m'<<24) | ('e'<<16) | ('m'<<8) | 'e') + +/**************************************************************************************** + * * + * OS Memory API * + * * + ****************************************************************************************/ + +/**************************************************************************************** + * os_memoryAlloc() + **************************************************************************************** +DESCRIPTION: Allocates resident (nonpaged) system-space memory. + +ARGUMENTS: OsContext - our adapter context. + Size - Specifies the size, in bytes, to be allocated. + +RETURN: Pointer to the allocated memory. + NULL if there is insufficient memory available. + +NOTES: With the call to vmalloc it is assumed that this function will + never be called in an interrupt context. vmalloc has the potential to + sleep the caller while waiting for memory to become available. + +*****************************************************************************************/ +PVOID +os_memoryAlloc( + TI_HANDLE OsContext, + UINT32 Size + ) +{ + struct os_mem_block *blk; + __u32 total_size = Size + sizeof(struct os_mem_block) + sizeof(__u32); + +#ifdef TI_MEM_ALLOC_TRACE + os_printf("MTT:%s:%d ::os_memoryAlloc(0x%p, %lu) : %lu\n",__FUNCTION__, __LINE__,OsContext,Size,total_size); +#endif + if( total_size < Size ) { /* Dm: Security fix */ + return NULL; + } + /* + memory optimization issue. Allocate 8 kB and less from the SLAB allocator (2^n) + otherwise allocate from virtual pool. + */ + /* 2 pages */ + if (Size <= 2 * 4096) + { + if (in_atomic()) + blk = kmalloc(total_size, GFP_ATOMIC); + else + blk = kmalloc(total_size, GFP_KERNEL); + if (!blk) + return NULL; + blk->f_free = (os_free)kfree; + } + else + { + /* We expect that the big allocations should be made outside the interrupt, + otherwise fail + */ + if (in_atomic()) + return NULL; + blk = vmalloc(total_size); + if (!blk) + return NULL; + blk->f_free = (os_free)vfree; + } + + os_profile (OsContext, 4, total_size); + + /*list_add(&blk->blk_list, &drv->mem_blocks);*/ + blk->size = Size; + blk->signature = MEM_BLOCK_START; + *(__u32 *)((unsigned char *)blk + total_size - sizeof(__u32)) = MEM_BLOCK_END; + return (PVOID)((char *)blk + sizeof(struct os_mem_block)); +} + +/**************************************************************************************** + * os_memoryPreFree() + **************************************************************************************** +DESCRIPTION: Frees preallocated by the kernel memory. + +ARGUMENTS: ptr - pointer to memory +*****************************************************************************************/ +void os_memoryPreFree( void *ptr ) +{ +} + +/**************************************************************************************** + * os_memoryPreAlloc() + **************************************************************************************** +DESCRIPTION: Gets system-space memory preallocated by kernel. + +ARGUMENTS: OsContext - our adapter context. + section - section number + Size - Specifies the size, in bytes, to be allocated. + +RETURN: Pointer to the allocated memory. + NULL if there is insufficient memory available. +*****************************************************************************************/ +PVOID +os_memoryPreAlloc( + TI_HANDLE OsContext, + int section, + UINT32 Size + ) +{ + struct os_mem_block *blk; + __u32 total_size = Size + sizeof(struct os_mem_block) + sizeof(__u32); + +#ifdef TI_MEM_ALLOC_TRACE + os_printf("MTT:%s:%d ::os_memoryPreAlloc(0x%p, %lu) : %lu\n",__FUNCTION__, __LINE__,OsContext,Size,total_size); +#endif + if( total_size < Size ) { /* Dm: Security fix */ + return NULL; + } + + blk = (struct os_mem_block *)wifi_kernel_prealloc( section, total_size ); + if( !blk ) { + return os_memoryAlloc(OsContext, Size); + } + blk->f_free = (os_free)os_memoryPreFree; + + os_profile (OsContext, 4, total_size); + + /*list_add(&blk->blk_list, &drv->mem_blocks);*/ + blk->size = Size; + blk->signature = MEM_BLOCK_START; + *(__u32 *)((unsigned char *)blk + total_size - sizeof(__u32)) = MEM_BLOCK_END; + return (PVOID)((char *)blk + sizeof(struct os_mem_block)); +} + + +/**************************************************************************************** + * os_memoryCAlloc() + **************************************************************************************** +DESCRIPTION: Allocates an array in memory with elements initialized to 0. + +ARGUMENTS: OsContext - our adapter context. + Number - Number of elements + Size - Length in bytes of each element + +RETURN: None + +NOTES: +*****************************************************************************************/ +PVOID +os_memoryCAlloc( + TI_HANDLE OsContext, + UINT32 Number, + UINT32 Size + ) +{ + PVOID pAllocatedMem; + ULONG MemSize; + +#ifdef TI_MEM_ALLOC_TRACE + os_printf("MTT:%s:%d ::os_memoryCAlloc(0x%p, %lu, %lu) : %lu\n",__FUNCTION__,__LINE__,OsContext,Number,Size,Number*Size); +#endif + MemSize = Number * Size; + + if( (Number > 0) && (Size >= (0xFFFFFFFFUL / Number)) ) { /* Dm: Security fix */ + return NULL; + } + + pAllocatedMem = os_memoryAlloc(OsContext, MemSize); + + if(!pAllocatedMem) + return NULL; + + memset(pAllocatedMem,0,MemSize); + + return pAllocatedMem; +} + +/**************************************************************************************** + * os_memoryFree() + **************************************************************************************** +DESCRIPTION: This function releases a block of memory previously allocated with the + os_memoryAlloc function. + + +ARGUMENTS: OsContext - our adapter context. + pMemPtr - Pointer to the base virtual address of the allocated memory. + This address was returned by the os_memoryAlloc function. + Size - Specifies the size, in bytes, of the memory block to be released. + This parameter must be identical to the Length that was passed to + os_memoryAlloc. + +RETURN: None + +NOTES: +*****************************************************************************************/ +VOID +os_memoryFree( + TI_HANDLE OsContext, + PVOID pMemPtr, + UINT32 Size + ) +{ + struct os_mem_block *blk = + (struct os_mem_block *)((char *)pMemPtr - sizeof(struct os_mem_block)); + +#ifdef TI_MEM_ALLOC_TRACE + os_printf("MTT:%s:%d ::os_memoryFree(0x%p, 0x%p, %lu) : %d\n",__FUNCTION__,__LINE__,OsContext,pMemPtr,Size,-Size); +#endif + if (blk->signature != MEM_BLOCK_START) + { + printk("\n\n%s: memory block signature is incorrect - 0x%x\n\n\n", + __FUNCTION__, blk->signature); + return; + } + *(char *)(&blk->signature) = '~'; + if (*(__u32 *)((unsigned char *)blk + blk->size + sizeof(struct os_mem_block)) + != MEM_BLOCK_END) + { + printk("\n\n%s: memory block corruption. Size=%u\n\n\n", + __FUNCTION__, blk->size); + } + + os_profile (OsContext, 5, blk->size + sizeof(struct os_mem_block) + sizeof(__u32)); + + blk->f_free(blk); +} + + +/**************************************************************************************** + * os_memorySet() + **************************************************************************************** +DESCRIPTION: This function fills a block of memory with given value. + +ARGUMENTS: OsContext - our adapter context. + pMemPtr - Specifies the base address of a block of memory + Value - Specifies the value to set + Length - Specifies the size, in bytes, to copy. + +RETURN: None + +NOTES: +*****************************************************************************************/ +VOID +os_memorySet( + TI_HANDLE OsContext, + PVOID pMemPtr, + INT32 Value, + UINT32 Length + ) +{ + memset(pMemPtr,Value,Length); +} + +/**************************************************************************************** + * _os_memoryAlloc4HwDma() + **************************************************************************************** +DESCRIPTION: Allocates resident (nonpaged) system-space memory for DMA operations. + +ARGUMENTS: OsContext - our adapter context. + Size - Specifies the size, in bytes, to be allocated. + +RETURN: Pointer to the allocated memory. + NULL if there is insufficient memory available. + +NOTES: + +*****************************************************************************************/ +PVOID +os_memoryAlloc4HwDma( + TI_HANDLE pOsContext, + UINT32 Size + ) +{ + struct os_mem_block *blk; + __u32 total_size = Size + sizeof(struct os_mem_block) + sizeof(__u32); + /* + if the size is greater than 2 pages then we cant allocate the memory through kmalloc so the function fails + */ + if (Size < 2 * OS_PAGE_SIZE) + { + blk = kmalloc(total_size, GFP_ATOMIC); + if (!blk) + return NULL; + blk->f_free = (os_free)kfree; + } + else + { + printk("\n\n%s: memory cant be allocated-Size = %d\n\n\n", + __FUNCTION__, Size); + return NULL; + } + + blk->size = Size; + blk->signature = MEM_BLOCK_START; + *(__u32 *)((unsigned char *)blk + total_size - sizeof(__u32)) = MEM_BLOCK_END; + return (PVOID)((char *)blk + sizeof(struct os_mem_block)); +} + +/**************************************************************************************** + * _os_memory4HwDmaFree() + **************************************************************************************** +DESCRIPTION: This function releases a block of memory previously allocated with the + _os_memoryAlloc4HwDma function. + + +ARGUMENTS: OsContext - our adapter context. + pMemPtr - Pointer to the base virtual address of the allocated memory. + This address was returned by the os_memoryAlloc function. + Size - Specifies the size, in bytes, of the memory block to be released. + This parameter must be identical to the Length that was passed to + os_memoryAlloc. + +RETURN: None + +NOTES: +*****************************************************************************************/ +void +os_memory4HwDmaFree( + TI_HANDLE pOsContext, + PVOID pMem_ptr, + UINT32 Size + ) +{ + struct os_mem_block *blk = + (struct os_mem_block *)((char *)pMem_ptr - sizeof(struct os_mem_block)); + + if (blk->signature != MEM_BLOCK_START) + { + printk("\n\n%s: memory block signature is incorrect - 0x%x\n\n\n", + __FUNCTION__, blk->signature); + return; + } + *(char *)(&blk->signature) = '~'; + if (*(__u32 *)((unsigned char *)blk + blk->size + sizeof(struct os_mem_block)) + != MEM_BLOCK_END) + { + printk("\n\n%s: memory block corruption. Size=%u\n\n\n", + __FUNCTION__, blk->size); + } + + blk->f_free(blk); +} + +/**************************************************************************************** + * os_memoryZero() + **************************************************************************************** +DESCRIPTION: This function fills a block of memory with 0s. + +ARGUMENTS: OsContext - our adapter context. + pMemPtr - Specifies the base address of a block of memory + Length - Specifies how many bytes to fill with 0s. + +RETURN: None + +NOTES: +*****************************************************************************************/ +VOID +os_memoryZero( + TI_HANDLE OsContext, + PVOID pMemPtr, + UINT32 Length + ) +{ + memset(pMemPtr,0,Length); +} + + +/**************************************************************************************** + * os_memoryCopy() + **************************************************************************************** +DESCRIPTION: This function copies a specified number of bytes from one caller-supplied + location to another. + +ARGUMENTS: OsContext - our adapter context. + pDstPtr - Destination buffer + pSrcPtr - Source buffer + Size - Specifies the size, in bytes, to copy. + +RETURN: None + +NOTES: +*****************************************************************************************/ +VOID +os_memoryCopy( + TI_HANDLE OsContext, + PVOID pDstPtr, + PVOID pSrcPtr, + UINT32 Size + ) +{ + memcpy(pDstPtr,pSrcPtr,Size); +} + +/**************************************************************************************** + * os_memoryCompare() + **************************************************************************************** +DESCRIPTION: Compare characters in two buffers. + +ARGUMENTS: OsContext - our adapter context. + Buf1 - First buffer + Buf2 - Second buffer + Count - Number of characters + +RETURN: The return value indicates the relationship between the buffers: + < 0 Buf1 less than Buf2 + 0 Buf1 identical to Buf2 + > 0 Buf1 greater than Buf2 + +NOTES: +*****************************************************************************************/ +INT32 +os_memoryCompare( + TI_HANDLE OsContext, + PUINT8 Buf1, + PUINT8 Buf2, + INT32 Count + ) +{ + return memcmp(Buf1, Buf2, Count); +} diff --git a/sta_dk_4_0_4_32/pform/linux/src/proc_stat.c b/sta_dk_4_0_4_32/pform/linux/src/proc_stat.c new file mode 100644 index 0000000..3c2c1fe --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/proc_stat.c @@ -0,0 +1,105 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + + +/* Dm: #include <linux/config.h> */ +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/proc_fs.h> + +#include "healthMonitor.h" +#include "whalCtrl.h" +#include "osTIType.h" +#include "configMgr.h" + +int proc_stat_res_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data); +static struct proc_dir_entry *res; + +int proc_stat_init(TI_HANDLE *pHandle) +{ + configMgr_t *pConfigManager = (configMgr_t *)pHandle; + res = proc_mkdir("tiwlan", NULL); + create_proc_read_entry("tiwlan0_proc_stat", 0, res, proc_stat_res_read_proc, pConfigManager->hHealthMonitor); + return 0; +} + +int proc_stat_res_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len=0; + healthMonitor_t *pHealthMonitor = (healthMonitor_t*) data; + WHAL_CTRL *pWhalCtrl = (WHAL_CTRL *)pHealthMonitor->hHalCtrl; + whalCtrl_hwStatus_t *pHwStatus = &pWhalCtrl->pHwCtrl->HwStatus; + + count -= 80; /* some reserve */ + + len += (len<count)?sprintf(page+len,"-------------- STA Health Configuration ---------------\n"):0; + len += (len<count)?sprintf(page+len,"Full recovery enabled = %d\n",pHealthMonitor->bFullRecoveryEnable):0; + len += (len<count)?sprintf(page+len,"Timer interval = %d msec\n",pHealthMonitor->timerInterval):0; + len += (len<count)?sprintf(page+len,"\n"):0; + + + len += (len<count)?sprintf(page+len,"-------------- STA Health Failure Statistics ---------------\n"):0; + len += (len<count)?sprintf(page+len,"Health test perfomred = %d\n",pHealthMonitor->numOfHealthTests):0; + len += (len<count)?sprintf(page+len,"Full recovery performed = %d\n",pHealthMonitor->numOfRecoveryPerformed):0; + len += (len<count)?sprintf(page+len,"No scan complete failure = %d\n",pHealthMonitor->recoveryTriggersNumber[ NO_SCAN_COMPLETE_FAILURE ]):0; + len += (len<count)?sprintf(page+len,"Mailbox failure = %d\n",pHealthMonitor->recoveryTriggersNumber[ MBOX_FAILURE ]):0; + len += (len<count)?sprintf(page+len,"HW awake failure = %d\n",pHealthMonitor->recoveryTriggersNumber[ HW_AWAKE_FAILURE ]):0; + len += (len<count)?sprintf(page+len,"Bus error = %d\n",pHealthMonitor->recoveryTriggersNumber[ BUS_ERROR ]):0; + len += (len<count)?sprintf(page+len,"Device error = %d\n",pHealthMonitor->recoveryTriggersNumber[ DEVICE_ERROR ]):0; + len += (len<count)?sprintf(page+len,"Tx Stuck Errors = %d\n",pHealthMonitor->recoveryTriggersNumber[ TX_STUCK ]):0; + len += (len<count)?sprintf(page+len,"Disconnect timeouts = %d\n",pHealthMonitor->recoveryTriggersNumber[ DISCONNECT_TIMEOUT ]):0; + len += (len<count)?sprintf(page+len,"Power save failures = %d\n",pHealthMonitor->recoveryTriggersNumber[ POWER_SAVE_FAILURE ]):0; + len += (len<count)?sprintf(page+len,"measurement failures = %d\n",pHealthMonitor->recoveryTriggersNumber[ MEASUREMENT_FAILURE ]):0; + + len += (len<count)?sprintf(page+len,"--------------- whalCtrl_PrintHwStatus ---------------\n\n"):0; + len += (len<count)?sprintf(page+len,"NumMboxErrDueToPeriodicBuiltInTestCheck = %d\n", pHwStatus->NumMboxErrDueToPeriodicBuiltInTestCheck):0; + len += (len<count)?sprintf(page+len,"NumMboxFailures = %d\n", pHwStatus->NumMboxFailures):0; + len += (len<count)?sprintf(page+len, "\n"):0; + *eof = 1; + return len; +} + +int proc_stat_destroy(void) +{ + remove_proc_entry("tiwlan0_proc_stat", res); + remove_proc_entry("tiwlan", NULL); + return 0; +} + + + + + diff --git a/sta_dk_4_0_4_32/pform/linux/src/stack_profile.c b/sta_dk_4_0_4_32/pform/linux/src/stack_profile.c new file mode 100644 index 0000000..fbe5839 --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/stack_profile.c @@ -0,0 +1,87 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + + +#include <linux/stddef.h> + +unsigned long check_stack(unsigned long *base) +{ + + register unsigned long sp asm ("sp"); + unsigned long retval = sp; + *base = ((sp & ~0x1fff) + 0x380); + return retval; +} + +unsigned long check_stack_start(unsigned long *base) +{ + unsigned long i; + unsigned long from,to; + + to = check_stack(&from); + *base = from; + + /* run from the stack pointer down to the base */ + for (i = from;i<to;i+=4) + { + /* fill up the pattern */ + *(long *)i = 0xdeadbeef; + } +/* printk("check_stack_start: from =%x to=%x data=%x\n",from,to,*(long *)(from+4));*/ + return to; +} + +unsigned long check_stack_stop(unsigned long *base) +{ + unsigned long i; + unsigned long from,to; + + to = check_stack(&from); + *base = from; + + /* run from the stack pointer down to the base */ + for (i = from;i<to;i+=4) + { + /* check up the pattern */ + if ((*(long *)i) != 0xdeadbeef) + break; + } + + /*printk("check_stack_stop: from =%x to=%x data=%x data=%x i=0x%x\n",from,to,*(long *)from,*(long *)(from+4),i);*/ + /* return the first time when the pattern doesn't match */ + return i; +} + + diff --git a/sta_dk_4_0_4_32/pform/linux/src/string.c b/sta_dk_4_0_4_32/pform/linux/src/string.c new file mode 100644 index 0000000..9b22807 --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/string.c @@ -0,0 +1,69 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + + +/** + * memcmp - Compare two areas of memory + * @cs: One area of memory + * @ct: Another area of memory + * @count: The size of the area. + */ +int memcmp(const void * cs,const void * ct, unsigned int count) +{ + const unsigned char *su1, *su2; + int res = 0; + + for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) + if ((res = *su1 - *su2) != 0) + break; + return res; +} + +/** + * strcmp - Compare two strings + * @cs: One string + * @ct: Another string + */ +int strcmp(const char * cs,const char * ct) +{ + register signed char __res; + + while (1) { + if ((__res = *cs - *ct++) != 0 || !*cs++) + break; + } + + return __res; +} diff --git a/sta_dk_4_0_4_32/pform/linux/src/tiwlan_profile.c b/sta_dk_4_0_4_32/pform/linux/src/tiwlan_profile.c new file mode 100644 index 0000000..fca59ea --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/tiwlan_profile.c @@ -0,0 +1,344 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + + + +#include "esta_drv.h" + + +static void tiwlan_profile_bus_access_start (void *os, unsigned); +static void tiwlan_profile_bus_access_end (void *os, unsigned); +static void tiwlan_profile_driver_entry_start (void *os, unsigned); +static void tiwlan_profile_driver_entry_end (void *os, unsigned); +static void tiwlan_profile_memory_alloc (void *os, unsigned); +static void tiwlan_profile_memory_free (void *os, unsigned); +static void tiwlan_profile_buf_alloc (void * os, unsigned); +static void tiwlan_profile_timer_create (void * os, unsigned); +static void tiwlan_profile_timer_destroy (void * os, unsigned); + + +int tiwlan_profile_create (tiwlan_net_dev_t *drv) +{ + drv->fpro [0] = NULL; + drv->fpro [1] = NULL; + drv->fpro [2] = NULL; + drv->fpro [3] = NULL; + drv->fpro [4] = tiwlan_profile_memory_alloc; + drv->fpro [5] = tiwlan_profile_memory_free; + drv->fpro [6] = tiwlan_profile_timer_create; + drv->fpro [7] = tiwlan_profile_timer_destroy; + drv->fpro [8] = tiwlan_profile_buf_alloc; + + drv->cpu_usage_estimator_start_time = 0; + drv->cpu_usage_estimator_stop_time = 0; + drv->max_heap_bytes_allocated = 0; + drv->max_buf_bytes_allocated = 0; + drv->cur_heap_bytes_allocated = 0; + drv->max_number_of_timers = 0; + drv->cur_number_of_timers = 0; + + return 0; +} + + +/* Call register profiler banchmark */ +int tiwlan_profile (tiwlan_net_dev_t *drv, unsigned bm, unsigned par) +{ + if (drv && bm < MAX_PROFILE_BM && drv->fpro [bm]) + { + (*drv->fpro [bm]) (drv, par); + } + + return 0; +} + + +/* Stop CPU estimation for a driver entry and maintains the resolution of the estimator */ +void tiwlan_profile_bus_access_start (void * os, unsigned par) +{ + tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os; + + if (drv != NULL) + { + /* Save the current entry's start time */ + drv->bus_driver_entry_start_time = os_timeStampUs (drv); + } +} + + +/* Starts CPU estimation for a bus driver entry */ +void tiwlan_profile_bus_access_end (void * os, unsigned par) +{ + tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os; + unsigned current_entry_cpu_usage; + + if (drv != NULL) + { + /* Save the current entry's start time */ + current_entry_cpu_usage = os_timeStampUs (drv) - drv->bus_driver_entry_start_time; + + /* Make sure that it is not a negative value */ + if ((int)current_entry_cpu_usage < 0) + { + printk("\n\n%s: cpu usage estimation corrupted. entry_start=%u, entry_cpu_time = %d\n\n\n", + __FUNCTION__, drv->bus_driver_entry_start_time, current_entry_cpu_usage); + } + /* Update the total time of driver CPU usage */ + else + { + drv->total_us_of_bus_access_cpu_time += current_entry_cpu_usage; + } + } +} + + +/* Starts CPU estimation for a driver entry */ +void tiwlan_profile_driver_entry_start (void * os, unsigned par) +{ + tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os; + + if (drv != NULL) + { + drv->driver_entry_start_time = os_timeStampUs (drv); + } +} + + +/* Stop CPU estimation for a driver entry and maintains the resolution of the estimator */ +void tiwlan_profile_driver_entry_end (void * os, unsigned par) +{ + tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os; + unsigned current_entry_cpu_usage, driver_entry_end_time; + + if (drv == NULL) + return; + + /* Get the current entry's end time */ + driver_entry_end_time = os_timeStampUs (drv); + + /* Calculate the current entries CPU run time */ + current_entry_cpu_usage = driver_entry_end_time - drv->driver_entry_start_time; + + /* Make sure that it is not a negative value */ + if ((int)current_entry_cpu_usage < 0) + { + printk("\n\n%s: cpu usage estimation corrupted. entry_start=%u, entry_end=%u, entry_cpu_time = %d\n\n\n", + __FUNCTION__, drv->driver_entry_start_time, driver_entry_end_time, current_entry_cpu_usage); + } + /* Update the total time of driver CPU usage */ + else + { + drv->total_us_of_cpu_time += current_entry_cpu_usage; + } +} + + +void tiwlan_profile_memory_alloc (void * os, unsigned size) +{ + tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os; + + if (drv != NULL) + { + /* Increase current heap allocation counter */ + drv->cur_heap_bytes_allocated += size; + /* Update maximum if execceded */ + if (drv->max_heap_bytes_allocated < drv->cur_heap_bytes_allocated) + { + drv->max_heap_bytes_allocated = drv->cur_heap_bytes_allocated; + } + } +} + + +void tiwlan_profile_memory_free (void * os, unsigned size) +{ + tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os; + + if (drv != NULL) + { + /* Decrease amount from heap allocation counter */ + drv->cur_heap_bytes_allocated -= size; + /* Check for overflow */ + if ((int)drv->cur_heap_bytes_allocated < 0) + { + printk("\n\n%s: memory heap allocation calculation corrupted. Size=%u, Current allocation = %d\n\n\n", + __FUNCTION__, size, drv->cur_heap_bytes_allocated); + drv->cur_heap_bytes_allocated = 0; + } + } +} + + +void tiwlan_profile_buf_alloc (void * os, unsigned size) +{ + tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os; + + if (drv != NULL) + { + drv->max_buf_bytes_allocated += size; + } +} + + +void tiwlan_profile_timer_create (void * os, unsigned par) +{ + tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os; + + if (drv) + { + /* Increase the current active timer counter */ + drv->cur_number_of_timers ++; + /* Update maximum if execceded */ + if (drv->max_number_of_timers < drv->cur_number_of_timers) + { + drv->max_number_of_timers = drv->cur_number_of_timers; + } + } +} + + +void tiwlan_profile_timer_destroy (void * os, unsigned par) +{ + tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os; + + if (drv) + { + /* Decrease the current active timer counter */ + drv->cur_number_of_timers --; + } +} + + +/* + * Start CPU estimator + * NOTE: this function does not run in a driver context + */ +int tiwlan_profile_cpu_usage_estimator_start (tiwlan_net_dev_t * drv, unsigned int resolution) +{ + /* + * Reset estimation parameters - no need for spin lock since + * estimator is not running + */ + drv->total_us_of_cpu_time = 0; + drv->total_us_of_bus_access_cpu_time = 0; + drv->cpu_usage_estimator_start_time = os_timeStampUs (drv); + drv->cpu_usage_estimator_stop_time = 0; + + /* Set the new resolution */ + drv->cpu_usage_estimator_resolution = resolution; + + /* Register profiler banchmarks */ + drv->fpro [0] = tiwlan_profile_driver_entry_start; + drv->fpro [1] = tiwlan_profile_driver_entry_end; + drv->fpro [2] = tiwlan_profile_bus_access_start; + drv->fpro [3] = tiwlan_profile_bus_access_end; + + return 0; +} + + +/* + * Stop CPU estimator and save the last CPU estimation + * NOTE: this function does not run in a driver context + */ +int tiwlan_profile_cpu_usage_estimator_stop (tiwlan_net_dev_t * drv) +{ + drv->cpu_usage_estimator_stop_time = os_timeStampUs (drv); + + /* Unregister profiler banchmarks */ + drv->fpro [0] = NULL; + drv->fpro [1] = NULL; + drv->fpro [2] = NULL; + drv->fpro [3] = NULL; + + return 0; +} + + +/* + * Reset CPU estimation + * NOTE: this function is not run in a driver context + */ +int tiwlan_profile_cpu_usage_estimator_reset (tiwlan_net_dev_t * drv) +{ + /* Reset accumulated driver time and the last estimation */ + drv->total_us_of_cpu_time = 0; + drv->total_us_of_bus_access_cpu_time = 0; + drv->cpu_usage_estimator_start_time = 0; + drv->cpu_usage_estimator_stop_time = 0; + + return 0; +} + + +/* Print to the screen the latest resource usage and CPU estimation */ +int tiwlan_profile_report (tiwlan_net_dev_t *drv) +{ + unsigned total_time, drv_cpu_usage = 0, bus_cpu_usage = 0; + + printk ("\nDriver Resource Usage"); + printk ("\n====================="); + printk ("\nMaximum Heap Memory Allocated: %u (bytes)", drv->max_heap_bytes_allocated); + printk ("\nCurrent Heap Memory Allocated: %u (bytes)", drv->cur_heap_bytes_allocated); + printk ("\nBuffer Memory Allocated: %u (bytes)", drv->max_buf_bytes_allocated); + printk ("\nFirmware Image Memory Allocated: %u (bytes)", (unsigned)drv->firmware_image.size); + printk ("\nEEPROM Image Memory Allocated: %u (bytes)", (unsigned)drv->eeprom_image.size); + printk ("\nMaximum Active Timers: %u", drv->max_number_of_timers); + printk ("\nCurrent Active Timers: %u", drv->cur_number_of_timers); + + /* Check that the estimation has been started and stopped stopped */ + if (drv->cpu_usage_estimator_stop_time != 0) + { + total_time = drv->cpu_usage_estimator_stop_time - drv->cpu_usage_estimator_start_time; + + total_time /= 100; + + if ((int)total_time > 0) + { + drv_cpu_usage = drv->total_us_of_cpu_time / total_time; + bus_cpu_usage = drv->total_us_of_bus_access_cpu_time / total_time; + + printk ("\nTotal Test Run Time: %u (usec)", total_time); + printk ("\nTotal Driver Run Time: %u (usec)", drv->total_us_of_cpu_time); + printk ("\nTotal Bus Access Time: %u (usec)", drv->total_us_of_bus_access_cpu_time); + printk ("\nTotal CPU Usage: %u%%", drv_cpu_usage); + printk ("\nBus Access CPU Usage: %u%%", bus_cpu_usage); + printk ("\n"); + } + } + + return 0; +} + diff --git a/sta_dk_4_0_4_32/pform/linux/src/tiwlan_profile.h b/sta_dk_4_0_4_32/pform/linux/src/tiwlan_profile.h new file mode 100644 index 0000000..b9bb34f --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/tiwlan_profile.h @@ -0,0 +1,52 @@ +/**************************************************************************** +**+-----------------------------------------------------------------------+** +**| |** +**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** +**| All rights reserved. |** +**| |** +**| Redistribution and use in source and binary forms, with or without |** +**| modification, are permitted provided that the following conditions |** +**| are met: |** +**| |** +**| * Redistributions of source code must retain the above copyright |** +**| notice, this list of conditions and the following disclaimer. |** +**| * Redistributions in binary form must reproduce the above copyright |** +**| notice, this list of conditions and the following disclaimer in |** +**| the documentation and/or other materials provided with the |** +**| distribution. |** +**| * Neither the name Texas Instruments nor the names of its |** +**| contributors may be used to endorse or promote products derived |** +**| from this software without specific prior written permission. |** +**| |** +**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** +**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** +**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** +**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** +**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** +**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** +**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** +**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** +**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** +**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** +**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** +**| |** +**+-----------------------------------------------------------------------+** +****************************************************************************/ + + +#ifndef TIWLAN_PROFILE +#define TIWLAN_PROFILE + +#ifdef DRIVER_PROFILING + +int tiwlan_profile_create (tiwlan_net_dev_t *drv); +int tiwlan_profile_cpu_usage_estimator_start (tiwlan_net_dev_t * drv, unsigned int resolution); +int tiwlan_profile_cpu_usage_estimator_stop (tiwlan_net_dev_t * drv); +int tiwlan_profile_cpu_usage_estimator_reset (tiwlan_net_dev_t * drv); +int tiwlan_profile_report (tiwlan_net_dev_t * drv); +int tiwlan_profile (tiwlan_net_dev_t * drv, unsigned bm, unsigned par); + + +#endif + +#endif diff --git a/sta_dk_4_0_4_32/pform/linux/src/tnetw_sdio.c b/sta_dk_4_0_4_32/pform/linux/src/tnetw_sdio.c new file mode 100755 index 0000000..bc88b9c --- /dev/null +++ b/sta_dk_4_0_4_32/pform/linux/src/tnetw_sdio.c @@ -0,0 +1,235 @@ +/* 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 TIWLAN_MSM7000 +#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 +#define DMA_THRESHOLD_SIZE 64 +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) +{ + struct sdio_func *func = (struct sdio_func *)Handle; + + /* printk("%s:\n", __FUNCTION__); */ + if( func && func->card ) { + sdio_reset_comm(func->card); + } + 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( Req->buffer_len < DMA_THRESHOLD_SIZE ) { + 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( Req->buffer_len < DMA_THRESHOLD_SIZE ) { + 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 |