1/****************************************************************************
2**+-----------------------------------------------------------------------+**
3**|                                                                       |**
4**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved.      |**
5**| All rights reserved.                                                  |**
6**|                                                                       |**
7**| Redistribution and use in source and binary forms, with or without    |**
8**| modification, are permitted provided that the following conditions    |**
9**| are met:                                                              |**
10**|                                                                       |**
11**|  * Redistributions of source code must retain the above copyright     |**
12**|    notice, this list of conditions and the following disclaimer.      |**
13**|  * Redistributions in binary form must reproduce the above copyright  |**
14**|    notice, this list of conditions and the following disclaimer in    |**
15**|    the documentation and/or other materials provided with the         |**
16**|    distribution.                                                      |**
17**|  * Neither the name Texas Instruments nor the names of its            |**
18**|    contributors may be used to endorse or promote products derived    |**
19**|    from this software without specific prior written permission.      |**
20**|                                                                       |**
21**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |**
22**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |**
23**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |**
24**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |**
25**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |**
26**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |**
27**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |**
28**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |**
29**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |**
30**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |**
31**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |**
32**|                                                                       |**
33**+-----------------------------------------------------------------------+**
34****************************************************************************/
35
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/version.h>
39#include <net/sock.h>
40#include <linux/init.h>
41#include <linux/fs.h>
42#include <linux/netdevice.h>
43#include <linux/ioctl.h>
44#include <linux/wireless.h>
45#include <linux/etherdevice.h>
46#include <linux/netlink.h>
47#include <linux/completion.h>
48
49#ifdef TIWLAN_CARDBUS
50#include <linux/pci.h>
51#else
52#ifdef TIWLAN_OMAP1610
53#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
54#include <asm/arch-omap/tc.h>
55#else
56#include <mach/tc.h>
57#endif
58#endif
59#ifdef TIWLAN_MSM7000
60#include <linux/mmc/core.h>
61#include <linux/mmc/card.h>
62#include <linux/mmc/sdio_func.h>
63#include <linux/mmc/sdio_ids.h>
64#endif
65#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
66#include <asm/arch/io.h>
67#include <asm/arch/hardware.h>
68#include <asm/arch/irqs.h>
69#else
70#include <mach/io.h>
71#include <mach/hardware.h>
72#include <mach/irqs.h>
73#endif
74#endif   /* !TIWLAN_CARDBUS */
75
76#include <linux/list.h>
77#include <linux/spinlock.h>
78#include <linux/if_arp.h>
79#include <linux/proc_fs.h>
80#include <linux/mm.h>
81#include <linux/delay.h>
82#include <linux/vmalloc.h>
83#include <linux/irq.h>
84
85#include <asm/io.h>
86#include <asm/uaccess.h>
87#include <asm/pgtable.h>
88
89#include "esta_drv.h"
90#include "srcApi.h"
91#include "osApi.h"
92#include "whalHwRegs.h"
93
94#if defined(DEBUG_UNKNOWN_INTERRUPT)
95#define _STRING_H
96#include "configMgr.h"
97#include "whalCtrl.h"
98#endif
99
100#include "bmtrace.h"
101#include "osrgstry_parser.h"
102#include "osClsfr.h"
103#include "TI_IPC_Api.h"
104#include "802_11Defs.h"
105#include "Ethernet.h"
106#include "tiwlan_profile.h"
107
108#if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK)
109#define RX_RATE_INTERVAL_SEC 10
110unsigned long num_rx_pkt_new = 0;
111static unsigned long num_rx_pkt_last = 0;
112#endif
113
114#ifdef TIWLAN_MSM7000
115extern unsigned char *get_wifi_nvs_ram(void);
116extern void SDIO_SetFunc( struct sdio_func * );
117#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29))
118static struct proc_dir_entry *tiwlan_calibration;
119#endif
120static struct completion sdio_wait;
121#ifdef CONFIG_WIFI_CONTROL_FUNC
122static struct wifi_platform_data *wifi_control_data = NULL;
123#endif
124#endif
125
126/* WiFi chip information functions */
127int export_wifi_fw_version( tiwlan_net_dev_t *drv );
128int export_wifi_chip_id( void );
129
130/* Drivers list */
131static LIST_HEAD(tiwlan_drv_list);
132
133/* debug memory access */
134static struct proc_dir_entry *tiwlan_deb_entry;
135static __u32 memdebug_addr;
136static __u32 memdebug_size=1;
137static __u32 memdebug_trans_size;
138
139#define DRV_SHUTDOWN_TEST_DELAY_INTERVAL 100       /* Time in msec to "delay"(/sleep) while waiting for SME to shutdown */
140#define DRV_SHUTDOWN_TEST_MAX_COUNTER  20          /* How many delay/sleep iterations to perform while waiting for SME to shutdown) */
141
142MODULE_DESCRIPTION("TI WLAN Embedded Station Driver");
143MODULE_LICENSE("GPL");
144
145extern int packed_struct_tst(void);
146extern int proc_stat_init(TI_HANDLE);
147extern int proc_stat_destroy(void);
148
149typedef void (* tiwlan_drv_isr_t)(int, void *, struct pt_regs *);
150
151/* network device driver interface */
152static int tiwlan_drv_net_open(struct net_device * dev);
153static int tiwlan_drv_net_stop(struct net_device * dev);
154static int tiwlan_drv_net_xmit(struct sk_buff * skb, struct net_device * dev);
155static int tiwlan_drv_dummy_net_xmit(struct sk_buff * skb, struct net_device * dev);
156static struct net_device_stats * tiwlan_drv_net_get_stats(struct net_device * dev);
157int ti1610_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
158
159#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 31))
160static struct net_device_ops tiwlan_ops_pri = {
161	.ndo_open = tiwlan_drv_net_open,
162	.ndo_stop = tiwlan_drv_net_stop,
163	.ndo_get_stats = tiwlan_drv_net_get_stats,
164	.ndo_do_ioctl = ti1610_do_ioctl,
165	.ndo_start_xmit = tiwlan_drv_net_xmit,
166};
167
168static struct net_device_ops tiwlan_ops_dummy = {
169	.ndo_open = tiwlan_drv_net_open,
170	.ndo_stop = tiwlan_drv_net_stop,
171	.ndo_get_stats = tiwlan_drv_net_get_stats,
172	.ndo_do_ioctl = ti1610_do_ioctl,
173	.ndo_start_xmit = tiwlan_drv_dummy_net_xmit,
174};
175#endif
176
177#define OS_WRITE_REG(drv,reg,val)   \
178    os_hwWriteMemRegisterUINT32(drv, (UINT32 *)((unsigned long)drv->acx_reg.va + reg), (__u32)(val))
179
180#define OS_READ_REG(drv,reg,val)    \
181    os_hwReadMemRegisterUINT32(drv, (UINT32 *)((unsigned long)drv->acx_reg.va + reg), &val)
182
183#ifdef TIWLAN_OMAP1610
184static void omap_memif_init(void)
185{
186    printk ("First function offset is: %p\n", omap_memif_init);
187#if defined(TIWLAN_OMAP1610_INNOVATOR)
188    print_info("Setting CS1 Ref Clock = TC/4. \n");
189    omap_writel(0x00000004, 0xFFFECC40 ); /* wlan change for cs2 to dynamic wait state */
190    omap_writel(0x0000113a, 0xFFFECC18 ); /* EMIFS (nCS2) configuration */
191#elif defined(TIWLAN_OMAP1610_WIPP) || defined(TIWLAN_OMAP1610_CRTWIPP)
192
193#if defined(TIWLAN_OMAP1610_CRTWIPP)
194    /*
195    Init the GPIO to output*/
196
197    /* Set OMAP pin H19 to GPIO57*/
198
199    omap_writel(omap_readl(0xFFFE1014) | 0x00E00000, 0xFFFE1014 );
200
201    /*ELP_REQ (GPIO_57) by GPIO_DIRECTION - set it as output*/
202    omap_writel(omap_readl(0xFFFBBC34) & (~0x00000200), 0xFFFBBC34 );
203#endif  /* TIWLAN_OMAP1610_CRTWIPP */
204
205/* The below configuration enables GPIO25 and GPIO_27 as output GPIOs - for debug purposes */
206#if defined(TIWLAN_OMAP1610_CRTWIPP_GPIO_DEBUG)
207
208    omap_writel(omap_readl(0xFFFE1030) | 0x00000E00, 0xFFFE1030 );/* enable GPIO25 */
209    omap_writel(omap_readl(0xFFFE1030) | 0x00000038, 0xFFFE1030 );/* enable GPIO27 */
210
211    omap_writel(omap_readl(0xFFFBEC34) & (~0x00000200), 0xFFFBEC34 );/* Setting direction (as output) for GPIO25 */
212    omap_writel(omap_readl(0xFFFBEC34) & (~0x00000800), 0xFFFBEC34 );/* Setting direction (as output) for GPIO27 */
213#endif   /* TIWLAN_OMAP1610_CRTWIPP_GPIO_DEBUG */
214
215
216    /* RECOVERY*/
217    print_info("Hard reset,perform PMEN toggle\n");
218    os_hardResetTnetw();
219
220    print_info("Setting CS2 Ref Clock = TC/2. \n");
221    __raw_writel(0x1, TIWLAN_OMAP1610_REGBASE+0x4cc); /* CLK=80MHz */
222    omap_writel(0x20, EMIF_CFG_DYNAMIC_WS); /* Full handshake on CS2 */
223    omap_writel(0x2441, EMIFS_CS2_CONFIG); /* 0x2021 on reworked board */
224    omap_writel(0, EMIFS_ACS2);
225
226    print_info("%x=0x%lx\n", 0xFFFECC40, omap_readl(0xFFFECC40) );
227    print_info("%x=0x%lx\n", 0xFFFECC18, omap_readl(0xFFFECC18) );
228    print_info("%x=0x%lx\n", 0xFFFECC58, omap_readl(0xFFFECC58) );
229#endif /* WIPP, CRTWIPP */
230}
231#endif
232
233static int tiwlan_register_events(tiwlan_net_dev_t *drv)
234{
235    IPC_EVENT_PARAMS evParams;
236    int i = 0;
237
238    evParams.uDeliveryType      = DELIVERY_PUSH;
239    evParams.uProcessID         = 0;
240    evParams.uEventID           = 0;
241    evParams.hUserParam        = drv;
242    evParams.pfEventCallback    = os_IndicateEvent;
243
244
245    for (;i < IPC_EVENT_MAX_OS_EVENT;i++)
246    {
247        evParams.uEventType = i;
248
249        configMgr_RegisterEvent(drv->adapter.CoreHalCtx,(PUCHAR) &evParams,sizeof(IPC_EVENT_PARAMS));
250    }
251
252    return OK;
253}
254
255static int tiwlan_deb_read_proc(char *page, char **start, off_t off,
256                                int count, int *eof, void *data)
257{
258    __u32 addr=memdebug_addr;
259    __u32 size=memdebug_size;
260    __u32 trans_size=memdebug_trans_size;
261    __u32 end;
262    int in_line=0, max_in_line;
263    int limit=count-80;
264    int i=0;
265    static int toggle;
266
267    *eof = 1;
268    if (!addr || !trans_size)
269        return 0;
270
271    /* fixme: add address validation */
272
273    if (!size)
274        size=1;
275
276    end = addr + size*trans_size;
277    if (trans_size==4)
278        max_in_line = 4;
279    else if (trans_size==2)
280        max_in_line = 8;
281    else
282        max_in_line = 16;
283
284    while(i<limit && addr<end)
285    {
286        if (!in_line)
287            i += sprintf(page+i, "0x%08x: ", addr);
288        if (trans_size==4)
289        {
290            i += sprintf(page+i, "0x%08x", *(__u32 *)addr);
291            addr += 4;
292        }
293        else if (trans_size==2)
294        {
295            i += sprintf(page+i, "0x%04x", *(__u16 *)addr);
296            addr += 2;
297        }
298        else
299        {
300            i += sprintf(page+i, "0x%02x", *(__u8 *)addr);
301            addr += 1;
302        }
303        if (++in_line < max_in_line)
304            *(page+i++)=' ';
305        else
306        {
307            *(page+i++)='\n';
308            in_line = 0;
309        }
310    }
311    *(page+i++)='\n';
312    /* For some reason read proc is get called twice for
313       each "cat" operation
314    */
315    if (toggle)
316        memdebug_addr = addr;
317    toggle = !toggle;
318
319    return i;
320}
321
322static char *rm_get_token(const char **p_buffer, unsigned long *p_buffer_len,
323                          char *token, unsigned long token_len,
324                          char del)
325{
326    const char *buffer=*p_buffer;
327    __u32 buffer_len = *p_buffer_len;
328
329    while(buffer_len && token_len && *buffer!=del && *buffer)
330    {
331        *token++ = *buffer++;
332        --buffer_len;
333        --token_len;
334    }
335    while (buffer_len && *buffer==del)
336    {
337        ++buffer;
338        --buffer_len;
339    }
340    *token = 0;
341    *p_buffer = buffer;
342    *p_buffer_len = buffer_len;
343    return token;
344}
345
346static int tiwlan_deb_write_proc(struct file *file, const char *buffer,
347                                 unsigned long count, void *data)
348{
349    __u32 addr, size;
350    char token[15];
351    __u32 value;
352    char *end;
353    int buflen=count;
354
355    /* buffer format is:
356       d{w,h,b} addr[/size]
357       s{w,h,b} addr=value
358    */
359    /* Parse string */
360    rm_get_token(&buffer, &count, token, sizeof(token)-1, ' ');
361    if (token[0]=='d')
362    {
363        /* Display */
364        if (!strcmp(token, "dw"))
365            memdebug_trans_size = 4;
366        else if (!strcmp(token, "dh"))
367            memdebug_trans_size = 2;
368        else if (!strcmp(token, "db"))
369            memdebug_trans_size = 1;
370        else
371        {
372            printk(KERN_INFO "rm: mem file write op is dw|dh|db|sw|sh|sb\n");
373            return buflen;
374        }
375        /* Get address */
376        rm_get_token(&buffer, &count, token, sizeof(token)-1, '/');
377        addr = simple_strtoul(token, &end, 0);
378        if ((end && *end) /* || !iopa(addr)*/)
379        {
380            printk(KERN_INFO "rm: address <%s> is invalid\n", token);
381            return buflen;
382        }
383        if ((addr & (memdebug_trans_size-1)))
384        {
385            printk(KERN_INFO "rm: warning: address 0x%x is not aligned to size %u\n",
386                   addr, memdebug_trans_size);
387        }
388        memdebug_addr = addr;
389        if (count)
390        {
391            /* Get size */
392            rm_get_token(&buffer, &count, token, sizeof(token)-1, ' ');
393            size = simple_strtoul(token, &end, 0);
394            if (end && *end)
395            {
396                printk(KERN_INFO "rm: size <%s> is invalid. end=<%s>\n",
397                       token, end);
398                return buflen;
399            }
400            memdebug_size = size;
401        }
402        return buflen;
403    }
404    if (token[0]=='s')
405    {
406        /* Display */
407        if (!strcmp(token, "sw"))
408            size = 4;
409        else if (!strcmp(token, "sh"))
410            size = 2;
411        else if (!strcmp(token, "sb"))
412            size = 1;
413        else
414        {
415            printk(KERN_INFO "rm: mem file write op is dw|dh|db|sw|sh|sb\n");
416            return buflen;
417        }
418        /* Get address */
419        rm_get_token(&buffer, &count, token, sizeof(token)-1, ' ');
420        addr = simple_strtoul(token, &end, 0);
421        if ((end && *end) /*|| !iopa(addr)*/)
422        {
423            printk(KERN_INFO "rm: address <%s> is invalid\n", token);
424            return buflen;
425        }
426        if ((addr & (size-1)))
427        {
428            printk(KERN_INFO "rm: warning: address 0x%x is not aligned to size %u\n",
429                   addr, size);
430        }
431
432        /* Get value */
433        rm_get_token(&buffer, &count, token, sizeof(token)-1, ' ');
434        value = simple_strtoul(token, &end, 0);
435        if (end && *end)
436        {
437            printk(KERN_INFO "rm: value <%s> is invalid. end <%s>\n",
438                   token, end);
439            return buflen;
440        }
441        if (size==4)
442            *(__u32 *)addr = value;
443        else if (size==2)
444        {
445            if (value > 0xffff)
446            {
447                printk(KERN_INFO "rm: value <%s> is out of range\n", token);
448                return buflen;
449            }
450            *(__u16 *)addr = value;
451        }
452        else
453        {
454            if (value > 0xff)
455            {
456                printk(KERN_INFO "rm: value <%s> is out of range\n", token);
457                return buflen;
458            }
459            *(__u8 *)addr = value;
460        }
461        memdebug_addr = addr;
462        memdebug_size = 1;
463        memdebug_trans_size = size;
464    }
465    else
466        printk(KERN_INFO "rm: operation <%s> is not supported\n", token);
467    return buflen;
468}
469
470#ifdef TIWLAN_MSM7000
471#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29))
472#define WIFI_NVS_LEN_OFFSET     0x0C
473#define WIFI_NVS_DATA_OFFSET    0x40
474#define WIFI_NVS_MAX_SIZE       0x800UL
475
476static unsigned long tiwlan_get_nvs_size( void )
477{
478    unsigned char *ptr;
479    unsigned long len;
480
481    ptr = get_wifi_nvs_ram();
482    if( ptr == NULL ) {
483        return 0;
484    }
485    /* Size in format LE assumed */
486    memcpy( (void *)&len, (void *)(ptr + WIFI_NVS_LEN_OFFSET), sizeof(len) );
487    len = min( len, (WIFI_NVS_MAX_SIZE-WIFI_NVS_DATA_OFFSET) );
488    return len;
489}
490
491static int tiwlan_calibration_read_proc(char *page, char **start, off_t off,
492                                int count, int *eof, void *data)
493{
494    unsigned char *ptr;
495    unsigned long len;
496
497    ptr = get_wifi_nvs_ram();
498    if( ptr == NULL ) {
499        return 0;
500    }
501    len = tiwlan_get_nvs_size();
502    /* i += sprintf(page+i, "WiFi Calibration Size = %lu %x bytes\n", len); */
503    memcpy( (void *)page, (void *)(ptr + WIFI_NVS_DATA_OFFSET), len );
504    return len;
505}
506
507static int tiwlan_calibration_write_proc(struct file *file, const char *buffer,
508                                 unsigned long count, void *data)
509{
510    return 0;
511}
512#endif
513#endif
514
515/*********************************************************************************************/
516/*                                      Impelementation                                      */
517/*********************************************************************************************/
518
519static int tiwlan_drv_net_open(struct net_device * dev)
520{
521   tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev);
522
523   ti_nodprintf(TIWLAN_LOG_INFO, "tiwlan_drv_net_open()\n");
524
525   if (!drv->adapter.CoreHalCtx)
526      return -ENODEV;
527
528   netif_start_queue(dev);
529
530   return 0;
531}
532
533
534static int tiwlan_drv_net_stop(struct net_device * dev)
535{
536   ti_nodprintf(TIWLAN_LOG_ERROR, "tiwlan_drv_net_stop()\n");
537
538   netif_stop_queue(dev);
539
540   return 0;
541}
542
543
544/* dummy send packet from Linux TCP/IP stack to WLAN
545   Used when driver is not initialized
546 */
547static int tiwlan_drv_dummy_net_xmit(struct sk_buff *skb, struct net_device *dev)
548{
549   /* Network stack takes care of deallocation */
550   return -ENODEV;
551}
552
553void sendFreeFunc(TI_HANDLE pSkb, TI_HANDLE dummy1, TI_STATUS status)
554{
555    struct sk_buff *skb = (struct sk_buff *) pSkb;
556
557    /* print_deb("^^^ free %p %d  bytes (%s)\n", skb->data, skb->len, (status==OK) ? "OK" : "ERROR" ); */
558    dev_kfree_skb(skb);
559}
560
561#ifdef DM_USE_WORKQUEUE
562void tiwlan_add_msdu(tiwlan_net_dev_t *drv, mem_MSDU_T *pMsdu)
563{
564    if( pMsdu == NULL )
565        return;
566    pMsdu->msdu_next = NULL;
567    if( drv->txmit_msdu_next != NULL ) {
568        drv->txmit_msdu_last->msdu_next = pMsdu;
569    }
570    else {
571        drv->txmit_msdu_next = pMsdu;
572    }
573    drv->txmit_msdu_last = pMsdu;
574}
575
576mem_MSDU_T *tiwlan_del_msdu(tiwlan_net_dev_t *drv)
577{
578    mem_MSDU_T *pMsdu = NULL;
579
580    if( drv->txmit_msdu_next != NULL ) {
581        pMsdu = drv->txmit_msdu_next;
582        drv->txmit_msdu_next = pMsdu->msdu_next;
583        if( drv->txmit_msdu_next == NULL ) { /* Last MSDU */
584            drv->txmit_msdu_last = NULL;
585        }
586    }
587    return( pMsdu );
588}
589
590static void tiwlan_xmit_handler( struct work_struct *work )
591{
592    tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( work, struct tiwlan_net_dev, txmit );
593    mem_MSDU_T *pMsdu;
594    unsigned long flags;
595
596#ifdef CONFIG_ANDROID_POWER
597    android_lock_suspend( &drv->exec_wake_lock );
598    android_unlock_suspend( &drv->xmit_wake_lock );
599#endif
600    /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
601    do {
602        spin_lock_irqsave(&drv->lock, flags);
603        pMsdu = tiwlan_del_msdu(drv);
604        spin_unlock_irqrestore(&drv->lock, flags);
605        if( pMsdu ) {
606            configMgr_sendMsdu(drv->adapter.CoreHalCtx, pMsdu, 0);
607        }
608    } while( pMsdu != NULL );
609#ifdef CONFIG_ANDROID_POWER
610    android_unlock_suspend( &drv->exec_wake_lock );
611#endif
612}
613#endif
614
615/* send packet from Linux TCP/IP stack to WLAN
616 */
617static int tiwlan_drv_net_xmit(struct sk_buff *skb, struct net_device *dev)
618{
619    tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev);
620    int status;
621    mem_MSDU_T *pMsdu;
622    UINT32      packetHeaderLength;
623
624#ifndef NO_COPY_SKB
625    char *pMsduData;
626#else
627    mem_BD_T *pCurBd=0;
628#endif
629
630#ifdef DRIVER_PROFILE
631    os_profile (drv, 0, 0);
632#endif
633    bm_trace(20, skb->len, 0);
634
635#ifdef NO_COPY_SKB
636
637    status = configMgr_allocMSDUBufferOnly(drv->adapter.CoreHalCtx, &pMsdu, OS_ABS_TX_MODULE);
638    if(status != OK)
639    {
640        ti_dprintf(TIWLAN_LOG_ERROR, " configMgr_allocMSDUBufferOnly failed !!!\n");
641        ++drv->alloc_msdu_failures;
642        return -ENOMEM;
643    }
644    /* print_deb("$$$ configMgr_allocMSDUBufferOnly()=OK pMsdu=%p\n", pMsdu ); */
645
646    status = configMgr_allocBDs(drv->adapter.CoreHalCtx, 1, &pCurBd);
647
648    if(status != OK) {
649        ++drv->alloc_msdu_failures;
650        ti_dprintf(TIWLAN_LOG_ERROR, "  configMgr_allocBDs failed !!!\n");
651        configMgr_memMngrFreeMSDU(drv->adapter.CoreHalCtx, pMsdu->handle);
652        return -ENOMEM;
653    }
654    /* print_deb("$$$ configMgr_allocBDs()=OK pCurBd=%p first=%p\n", pCurBd, pMsdu->firstBDPtr ); */
655
656    pMsdu->freeFunc = sendFreeFunc;
657    pMsdu->freeArgs[0] = (UINT32) skb;
658    pMsdu->dataLen = skb->len;
659    pMsdu->firstBDPtr = pCurBd;
660    pCurBd->dataOffset = skb->data-skb->head;
661    pCurBd->length = skb->len;
662    pCurBd->data = skb->head;
663
664    drv->stats.tx_packets++;
665    drv->stats.tx_bytes += skb->len;
666
667#else /* NO_COPY_SKB */
668
669    /*
670     * Retrieve the Packet Header length
671     * from QoS Manager (through configMgr)
672     * (Header type is determined upon association)
673     */
674    packetHeaderLength = configMgr_getPacketHeaderLength(drv->adapter.CoreHalCtx,skb->data,TX_DATA_DATA_MSDU);
675
676   /*
677    * need to reserve enough space for header translation
678    * in the same first Bd.
679    * Allocate enough place also for 802.11 header (24 bytes or 26 for QoS) and LLC (8 bytes)
680    * to replace the Ethernet header (14 bytes)
681    */
682    status = configMgr_allocMSDU(drv->adapter.CoreHalCtx, &pMsdu,
683                                     skb->len + packetHeaderLength, OS_ABS_TX_MODULE);
684
685    if(status != OK)
686    {
687        /*ti_dprintf(TIWLAN_LOG_ERROR, " configMgr_allocMSDU failed !!!\n");*/
688        ++drv->alloc_msdu_failures;
689        return -ENOMEM;
690    }
691
692    /*
693     * case 1: only legacy wlan header
694     *
695     * case 2: only QoS wlan header
696     *
697     * case 3: only legacy wlan header with new snap
698     *
699     * case 4: only QoS wlan header with new snap
700     */
701    pMsdu->firstBDPtr->dataOffset = packetHeaderLength - ETHERNET_HDR_LEN;
702    pMsduData = pMsdu->firstBDPtr->data + pMsdu->firstBDPtr->dataOffset;
703    memcpy(pMsduData, skb->data, skb->len);
704    pMsdu->dataLen = skb->len;
705    pMsdu->firstBDPtr->length = pMsdu->dataLen + pMsdu->firstBDPtr->dataOffset;
706
707    drv->stats.tx_packets++;
708    drv->stats.tx_bytes += skb->len;
709    dev_kfree_skb(skb);
710#endif /* NO_COPY_SKB */
711
712    pMsdu->txFlags |= TX_DATA_FROM_OS;
713    pMsdu->qosTag = 0;
714    status = OK;
715
716#ifdef TI_DBG
717    /* Set packet-os-in time stamp */
718    /* TODO: the skb time stamp is not good */
719    /* printk ("\n### sec=%u, usec=%u", skb->stamp.tv_sec, skb->stamp.tv_usec);*/
720    /* pMsdu->timeStamp[0] = skb->stamp.tv_sec * 1000000 + skb->stamp.tv_usec; */
721    /* pMsdu->timeStampNum = 1; */
722#endif
723
724    bm_trace(21, 0, 0);
725   /*
726    * Propagate Msdu through Config Manager.
727    * Set DTag to zero
728    * (note that classification is further handled in the Core)
729    */
730    if (status == OK) {
731#ifdef DM_USE_WORKQUEUE
732        unsigned long flags;
733
734        spin_lock_irqsave(&drv->lock, flags);
735        tiwlan_add_msdu(drv, pMsdu);
736        spin_unlock_irqrestore(&drv->lock, flags);
737        /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
738#ifdef CONFIG_ANDROID_POWER
739        android_lock_suspend( &drv->xmit_wake_lock );
740#endif
741        queue_work( drv->tiwlan_wq, &drv->txmit );
742#else
743        status = configMgr_sendMsdu(drv->adapter.CoreHalCtx, pMsdu, 0);
744#endif
745    }
746    else
747        configMgr_memMngrFreeMSDU (drv->adapter.CoreHalCtx, (UINT32) pMsdu); /* If status != OK , we won't send the MSDU, so we need to free it */
748
749    if(unlikely(status != OK))
750    {
751        drv->stats.tx_errors++;
752#ifdef NO_COPY_SKB
753        dev_kfree_skb(skb);
754#endif
755    }
756
757    bm_trace(22, 0, 0);
758#ifdef DRIVER_PROFILE
759    os_profile (drv, 1, 0);
760#endif
761
762    return 0;
763}
764
765struct net_device_stats * tiwlan_drv_net_get_stats(struct net_device * dev)
766{
767    tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev);
768    ti_dprintf(TIWLAN_LOG_OTHER, "tiwlan_drv_net_get_stats()\n");
769
770    return &drv->stats;
771}
772
773
774static int setup_netif(tiwlan_net_dev_t *drv)
775{
776    struct net_device *dev;
777    int res;
778
779    dev = alloc_etherdev(0);
780    if (dev == NULL)
781    {
782        ti_dprintf(TIWLAN_LOG_ERROR, "alloc_etherdev() failed\n");
783        return -ENOMEM;
784    }
785    ether_setup(dev);
786    NETDEV_SET_PRIVATE(dev, drv);
787    drv->netdev = dev;
788    strcpy(dev->name, TIWLAN_DRV_IF_NAME);
789    netif_carrier_off(dev);
790#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
791    dev->open = tiwlan_drv_net_open;
792    dev->stop = tiwlan_drv_net_stop;
793    dev->hard_start_xmit = tiwlan_drv_dummy_net_xmit;
794    dev->get_stats = tiwlan_drv_net_get_stats;
795#else
796    dev->netdev_ops = &tiwlan_ops_dummy;
797#endif
798    dev->tx_queue_len = 100;
799
800    res = tiwlan_ioctl_init(dev);
801    if( res < 0 )
802    {
803        ti_dprintf(TIWLAN_LOG_ERROR, "tiwlan_ioctl_init() failed : %d\n", res);
804        kfree(dev);
805        return res;
806    }
807
808    res = register_netdev(dev);
809    if (res != 0)
810    {
811        ti_dprintf(TIWLAN_LOG_ERROR, "register_netdev() failed : %d\n", res);
812        kfree(dev);
813        return res;
814    }
815#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
816    SET_MODULE_OWNER(dev);
817#endif
818    return 0;
819}
820
821
822/* tiwlan_interrupt
823   TIWLAN interrupt handler. Disables interrupts and awakes tasklet.
824*/
825#if !(defined(HW_ACCESS_SDIO)||defined(HW_ACCESS_WSPI))
826static irqreturn_t tiwlan_interrupt (int irq, void *netdrv, struct pt_regs *cpu_regs)
827{
828    tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)netdrv;
829
830    /*
831     * Workaround for the Linux 2.6 pending IRQ bug:
832     * If a pending IRQ is handled on a WLAN ISR, the ISR is called again
833     * even though it disabled itself in the first call. To protect against
834     * re-entrance, this flag is checked, and if it is already set (meaning
835     * that the ISR is called twice before the tasklet was called) nothing is done.
836     */
837    if (drv->interrupt_pending == 0)
838    {
839        UINT32 interruptVector;
840
841        interruptVector = configMgr_checkInterrupts(drv->adapter.CoreHalCtx);
842        if (interruptVector != 0)
843        {
844            configMgr_disableInterrupts(drv->adapter.CoreHalCtx);
845            drv->interrupt_pending = 1;
846            tasklet_schedule (&drv->tl);
847        }
848        else
849        {
850#if DEBUG_UNKNOWN_INTERRUPT
851            ti_dprintf (TIWLAN_LOG_ERROR,
852                        "%s - ERROR - interrupt isn't TNET interrupt! interrupt vector = 0x%08X\n",
853                        __FUNCTION__, interruptVector);
854#endif
855        }
856    }
857    return IRQ_HANDLED;
858}
859
860#else
861
862static irqreturn_t tiwlan_interrupt (int irq, void *netdrv, struct pt_regs *cpu_regs)
863{
864    tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)netdrv;
865
866    /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
867    drv->interrupt_pending = 1;
868#ifdef DM_USE_WORKQUEUE
869#ifdef CONFIG_ANDROID_POWER
870    android_lock_suspend( &drv->irq_wake_lock );
871#endif
872    queue_work( drv->tiwlan_wq, &drv->tirq );
873    /* disable_irq( drv->irq ); Dm: No need, we can loose IRQ */
874#else
875    tasklet_schedule( &drv->tl );
876#endif
877    return IRQ_HANDLED;
878}
879#endif
880
881
882static void tiwlan_poll_irq_handler(unsigned long parm)
883{
884    tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)parm;
885    bm_trace(2, 0, 0);
886
887    tiwlan_interrupt(0, drv, NULL);
888    mod_timer(&drv->poll_timer, jiffies + TIWLAN_IRQ_POLL_INTERVAL);
889}
890
891static void tiwlan_handle_control_requests( tiwlan_net_dev_t *drv )
892{
893    bm_trace(4, 0, 0);
894
895    /* Handle control requests (timers, ioctls) */
896    while(!list_empty(&drv->request_q))
897    {
898       struct list_head *entry = drv->request_q.next;
899       tiwlan_req_t *req = list_entry(entry, tiwlan_req_t, list);
900       tiwlan_req_t tmp_req;
901       unsigned long flags;
902
903       spin_lock_irqsave(&drv->lock, flags);
904       list_del_init(entry);
905       spin_unlock_irqrestore(&drv->lock, flags);
906
907       ti_nodprintf(TIWLAN_LOG_INFO, "%s: f=0x%x req=0x%x reply_expected=%d\n",
908                  __FUNCTION__, req->u.req.f, req, req->u.req.reply_expected);
909
910       tmp_req.u.req.p1 = 0x1234;
911       tmp_req.u.req.p2 = 0x4321;
912       tmp_req.u.req.p3 = 0x1221;
913       tmp_req.u.req.p4 = 0x4334;
914       tmp_req.u.req.reply_expected = 0x50;
915
916       req->u.reply = req->u.req.f(req);
917
918       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))
919       {
920               printk("\n\n !!! ERROR: STACK CORRUPTION !!! : \nf=%p\n", tmp_req.u.req.f);
921               if (!req->u.req.reply_expected)
922                       printk("timer handler: %p\n", (void *)tmp_req.u.req.p1);
923       }
924
925       ti_nodprintf(TIWLAN_LOG_INFO, "%s: f=0x%x req=0x%x reply_expected=%d reply=%d\n",
926                  __FUNCTION__, req->u.req.f, req, req->u.req.reply_expected, req->u.reply);
927       if (req->u.req.reply_expected)
928       {
929          ti_nodprintf(TIWLAN_LOG_INFO, "%s: about to awake task\n", __FUNCTION__);
930          complete(&req->u.req.comp);
931       }
932    }
933
934    bm_trace(5, 0, 0);
935
936    /* DbgCB_Insert(0, DBG_MODULE_OS, DBG_TYPE_TASKLET, 1)*/
937}
938
939#ifdef DM_USE_WORKQUEUE
940static void tiwlan_irq_handler( struct work_struct *work )
941{
942    tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( work, struct tiwlan_net_dev, tirq );
943
944    /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
945#ifdef CONFIG_ANDROID_POWER
946    android_lock_suspend( &drv->exec_wake_lock );
947    android_unlock_suspend( &drv->irq_wake_lock );
948#endif
949    /* if the driver was unloaded by that time we need to ignore all the timers */
950    if (drv->unload_driver) {
951#ifdef CONFIG_ANDROID_POWER
952        android_unlock_suspend( &drv->exec_wake_lock );
953#endif
954        /* enable_irq( drv->irq ); */
955        return;
956    }
957    configMgr_handleInterrupts( drv->adapter.CoreHalCtx );
958    tiwlan_handle_control_requests( drv );
959#ifdef CONFIG_ANDROID_POWER
960    if( drv->receive_packet ) {
961        drv->receive_packet = 0;
962        /* Keep awake for 500 ms to give a chance to network stack */
963        android_lock_suspend_auto_expire( &drv->rx_wake_lock, HZ );
964    }
965    android_unlock_suspend( &drv->exec_wake_lock );
966#endif
967    /* enable_irq( drv->irq ); */
968}
969#endif
970
971/* tiwlan_tasklet_handler
972   WLAN protocol tasklet. Most of work happens in the
973   context of this tasklet.
974*/
975#ifdef DM_USE_WORKQUEUE
976static void tiwlan_work_handler( struct work_struct *work )
977#else
978static void tiwlan_tasklet_handler( unsigned long netdrv )
979#endif
980{
981#ifdef DM_USE_WORKQUEUE
982    tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( work, struct tiwlan_net_dev, tw );
983#else
984    tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)netdrv;
985#endif
986#ifdef STACK_PROFILE
987    unsigned int curr1, base1;
988    unsigned int curr2, base2;
989    static unsigned int maximum_stack = 0;
990#endif
991
992    /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
993#ifdef CONFIG_ANDROID_POWER
994    android_lock_suspend( &drv->exec_wake_lock );
995    android_unlock_suspend( &drv->timer_wake_lock );
996#endif
997
998    /* if the driver was unloaded by that time we need to ignore all the timers */
999    if (drv->unload_driver) {
1000#ifdef CONFIG_ANDROID_POWER
1001        android_unlock_suspend( &drv->exec_wake_lock );
1002#endif
1003        return;
1004    }
1005#if 0
1006    ti_dprintf(TIWLAN_LOG_INFO, "%s in\n" , __FUNCTION__);
1007#endif
1008
1009#ifdef DRIVER_PROFILE
1010    os_profile (drv, 0, 0);
1011#endif
1012    bm_trace(3, 0, 0);
1013
1014#ifdef STACK_PROFILE
1015    curr1 = check_stack_start(&base1);
1016#endif
1017
1018    /* Handle bus transaction interrupts */
1019    if (drv->dma_done)
1020    {
1021        drv->dma_done = 0;
1022        configMgr_HandleBusTxn_Complete(drv->adapter.CoreHalCtx);
1023    }
1024
1025    /* don't call for "Handle interrupts, timers, ioctls" while recovery process */
1026    if (configMgr_areInputsFromOsDisabled(drv->adapter.CoreHalCtx) == TRUE) {
1027#ifdef CONFIG_ANDROID_POWER
1028        android_unlock_suspend( &drv->exec_wake_lock );
1029#endif
1030        return;
1031    }
1032
1033    /* Handle firmware interrupts */
1034#ifndef DM_USE_WORKQUEUE
1035    if (drv->interrupt_pending)
1036    {
1037        drv->interrupt_pending = 0;
1038        configMgr_handleInterrupts(drv->adapter.CoreHalCtx);
1039    }
1040#endif
1041
1042    tiwlan_handle_control_requests( drv );
1043
1044#ifdef STACK_PROFILE
1045    curr2 = check_stack_stop(&base2);
1046
1047    if (base2 == base1)
1048    {
1049       /* if the current measurement is bigger then the maximum store it and print*/
1050        if ((curr1 - curr2) > maximum_stack)
1051        {
1052            printk("STACK PROFILER GOT THE LOCAL MAXIMMUM!!!! \n");
1053            printk("current operation stack use =%d \n",(curr1 - curr2));
1054            printk("total stack use=%d \n",8192 - curr2 + base2);
1055            printk("total stack usage= %d percent \n",100 * (8192 - curr2 + base2) / 8192);
1056                maximum_stack = curr1 - curr2;
1057       }
1058    }
1059#endif
1060
1061#ifdef DRIVER_PROFILE
1062    os_profile (drv, 1, 0);
1063#endif
1064
1065#if 0
1066    ti_dprintf(TIWLAN_LOG_INFO, "%s out\n" , __FUNCTION__);
1067#endif
1068#ifdef CONFIG_ANDROID_POWER
1069    android_unlock_suspend( &drv->exec_wake_lock );
1070#endif
1071}
1072
1073#if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK)
1074static void tiwlan_rx_watchdog(struct work_struct *work)
1075{
1076    struct delayed_work *dwork = (struct delayed_work *) container_of(work, struct delayed_work, work);
1077    tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( dwork, struct tiwlan_net_dev, trxw );
1078
1079    unsigned long num_rx_pkts = num_rx_pkt_new - num_rx_pkt_last;
1080    /* Contribute 10mA (200mA x 5%) for 1 pkt/sec, and plus 8mA base. */
1081    unsigned percent = (5 * num_rx_pkts  / RX_RATE_INTERVAL_SEC) + PWRSINK_WIFI_PERCENT_BASE;
1082
1083    if (drv->unload_driver)
1084        return;
1085
1086    percent = (percent > 100) ? 100 : percent;
1087    /* printk(KERN_INFO "num_rx_pkts=%ld, percent=%d\n", num_rx_pkts, percent); */
1088#ifdef CONFIG_HTC_PWRSINK
1089    htc_pwrsink_set(PWRSINK_WIFI, percent);
1090#else
1091    trout_pwrsink_set(PWRSINK_WIFI, percent);
1092#endif
1093
1094    num_rx_pkt_last = num_rx_pkt_new;
1095
1096    if (drv && drv->tiwlan_wq)
1097        queue_delayed_work(drv->tiwlan_wq, &drv->trxw, msecs_to_jiffies(MSEC_PER_SEC * RX_RATE_INTERVAL_SEC));
1098}
1099#endif
1100
1101/* tiwlan_send_wait_reply
1102   This internal interface function creates request and sends
1103   it to the control tasklet for processing.
1104   The calling process is blocked until the request is replied.
1105   Function f is being called in the context of the control tasklet.
1106   The request block that is passed to the function as a parameter
1107   contains p1, p2, p3, p4.
1108   The function return code is propagated back to the caller.
1109   tiwlan_send_req_and_wait returns (*f) return code or
1110   -ENOMEM if failed to allocate a request.
1111*/
1112int tiwlan_send_wait_reply(tiwlan_net_dev_t *drv,
1113                           int (*f)(tiwlan_req_t *req),
1114                           unsigned long p1,
1115                           unsigned long p2,
1116                           unsigned long p3,
1117                           unsigned long p4)
1118{
1119    tiwlan_req_t req;
1120    unsigned long flags;
1121
1122    /* Send request to tiwlan_tasklet and wait for reply */
1123    if (!drv->adapter.CoreHalCtx) {
1124        return STATION_IS_NOT_RUNNING;
1125    }
1126
1127    req.drv = drv;
1128    req.u.req.f = f;
1129    req.u.req.p1 = p1;
1130    req.u.req.p2 = p2;
1131    req.u.req.p3 = p3;
1132    req.u.req.p4 = p4;
1133    req.u.req.reply_expected = 1;
1134    init_completion(&req.u.req.comp);
1135
1136    spin_lock_irqsave(&drv->lock, flags);
1137    list_add_tail(&req.list, &drv->request_q);
1138    spin_unlock_irqrestore(&drv->lock, flags);
1139
1140#ifdef DM_USE_WORKQUEUE
1141    /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
1142#ifdef CONFIG_ANDROID_POWER
1143    android_lock_suspend( &drv->timer_wake_lock );
1144#endif
1145    queue_work( drv->tiwlan_wq, &drv->tw );
1146#else
1147    tasklet_schedule( &drv->tl );
1148#endif
1149    wait_for_completion(&req.u.req.comp);
1150
1151    return req.u.reply;
1152}
1153
1154
1155#define WLAN_PCMCIA_CFG_REG       0x0524
1156/* tiwlan_set_hw_access */
1157static int tiwlan_set_hw_access(tiwlan_net_dev_t *drv)
1158{
1159#ifdef TIWLAN_OMAP1610
1160    OS_WRITE_REG(drv, HI_CFG, 0x00000a00);
1161
1162#if ! ((defined(HW_ACCESS_SDIO)||defined(HW_ACCESS_WSPI)) && defined(TNETW1150))
1163    OS_WRITE_REG(drv, WLAN_PCMCIA_CFG_REG, 0xC6880000);
1164    OS_WRITE_REG(drv, PCI_ARB_CFG, 0x2);
1165#endif
1166
1167#endif
1168    return 0;
1169}
1170
1171
1172/* tiwlan_free_drv
1173   Unmap h/w regions and free driver's structure
1174*/
1175static void tiwlan_free_drv(tiwlan_net_dev_t *drv)
1176{
1177#ifdef TIWLAN_OMAP1610
1178    if (drv->acx_mem.pa && drv->acx_mem.va)
1179        iounmap(drv->acx_mem.va);
1180    if (drv->acx_reg.pa && drv->acx_reg.va && drv->acx_reg.va != drv->acx_reg.va)
1181        iounmap(drv->acx_reg.va);
1182#endif
1183    kfree(drv);
1184}
1185
1186
1187/* tiwlan_alloc_drv
1188   Allocate driver's structure and map h/w regions
1189*/
1190static tiwlan_net_dev_t *
1191tiwlan_alloc_drv(unsigned long reg_start, unsigned long reg_size,
1192                 unsigned long mem_start, unsigned long mem_size,
1193                 int map_io, int irq)
1194{
1195    static tiwlan_net_dev_t *drv;
1196    drv = kmalloc(sizeof(tiwlan_net_dev_t), GFP_KERNEL);
1197#ifdef TI_MEM_ALLOC_TRACE
1198    os_printf("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, sizeof(tiwlan_net_dev_t), GFP_KERNEL, sizeof(tiwlan_net_dev_t));
1199#endif/*I_MEM_ALLOC_TRACE*/
1200
1201    if (!drv)
1202        return NULL;
1203    memset(drv, 0, sizeof(tiwlan_net_dev_t));
1204    drv->acx_mem.size = mem_size;
1205    drv->acx_reg.size = reg_size;
1206#ifdef TIWLAN_OMAP1610
1207    if (map_io)
1208    {
1209        drv->acx_mem.pa = mem_start;
1210        drv->acx_reg.pa = reg_start;
1211        drv->acx_mem.va = ioremap(drv->acx_mem.pa, drv->acx_mem.size);
1212        if (drv->acx_mem.pa!=drv->acx_reg.pa || drv->acx_mem.size!=drv->acx_reg.size)
1213            drv->acx_reg.va = ioremap(drv->acx_reg.pa, drv->acx_reg.size);
1214        else
1215            drv->acx_reg.va = drv->acx_mem.va;
1216    }
1217    else
1218    {
1219        /* Memory is already mapped */
1220        drv->acx_mem.va = (void *)mem_start;
1221        drv->acx_reg.va = (void *)reg_start;
1222    }
1223#endif /* Dm: */
1224    drv->irq = irq;
1225    return drv;
1226}
1227
1228
1229/* tiwlan_init_drv
1230   Called in process context
1231 */
1232int tiwlan_init_drv (tiwlan_net_dev_t *drv, tiwlan_dev_init_t *init_info)
1233{
1234    initTable_t *init_table;
1235    int rc;
1236    void *pWLAN_Images[4];
1237
1238    /* printk("%s\n", __FUNCTION__); */
1239    /* It is OK if already initialized */
1240    if (drv->adapter.CoreHalCtx)
1241        return 0;
1242
1243    init_table = os_memoryAlloc (drv, sizeof(initTable_t));
1244
1245#ifdef TI_MEM_ALLOC_TRACE
1246    osPrintf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, sizeof(initTable_t), GFP_KERNEL, sizeof(initTable_t));
1247#endif/*I_MEM_ALLOC_TRACE*/
1248    if (!init_table)
1249    {
1250        ti_dprintf(TIWLAN_LOG_ERROR, "Cannot allocate init_table\n");
1251        return -ENOMEM;
1252    }
1253
1254    if (init_info)
1255    {
1256        drv->eeprom_image.size = init_info->eeprom_image_length;
1257        if (drv->eeprom_image.size)
1258        {
1259            drv->eeprom_image.va = os_memoryAlloc (drv, drv->eeprom_image.size);
1260
1261#ifdef TI_MEM_ALLOC_TRACE
1262            osPrintf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, drv->eeprom_image.size, GFP_KERNEL, drv->eeprom_image.size);
1263#endif
1264            if (!drv->eeprom_image.va)
1265            {
1266                ti_dprintf (TIWLAN_LOG_ERROR, "Cannot allocate buffer for eeprom image\n");
1267                drv->eeprom_image.size = 0;
1268                return -ENOMEM;
1269            }
1270            memcpy (drv->eeprom_image.va, &init_info->data[0], drv->eeprom_image.size );
1271        }
1272
1273#ifdef FIRMWARE_DYNAMIC_LOAD
1274        drv->firmware_image.size = init_info->firmware_image_length;
1275        if (!drv->firmware_image.size)
1276        {
1277            ti_dprintf (TIWLAN_LOG_ERROR, "No firmware image\n");
1278            return -EINVAL;
1279        }
1280        drv->firmware_image.va = os_memoryAlloc (drv,drv->firmware_image.size);
1281#ifdef TI_MEM_ALLOC_TRACE
1282        osPrintf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, drv->firmware_image.size, GFP_KERNEL, drv->firmware_image.size);
1283#endif
1284        if (!drv->firmware_image.va)
1285        {
1286            ti_dprintf(TIWLAN_LOG_ERROR, "Cannot allocate buffer for firmware image\n");
1287            drv->firmware_image.size = 0;
1288            if (drv->eeprom_image.va)
1289                os_memoryFree (drv, drv->eeprom_image.va, drv->eeprom_image.size);
1290            return -ENOMEM;
1291        }
1292        memcpy (drv->firmware_image.va,
1293                &init_info->data[init_info->eeprom_image_length],
1294                drv->firmware_image.size);
1295#else
1296        extern unsigned char tiwlan_fwimage[];
1297        extern unsigned int sizeof_tiwlan_fwimage;
1298
1299        drv->firmware_image.size = sizeof_tiwlan_fwimage;
1300        drv->firmware_image.va = tiwlan_fwimage;
1301#endif
1302    }
1303
1304    print_deb ("--------- Eeeprom=%p(%lu), Firmware=%p(%lu)\n",
1305                drv->eeprom_image.va,
1306                drv->eeprom_image.size,
1307                drv->firmware_image.va,
1308                drv->firmware_image.size);
1309
1310    /* Init defaults */
1311    if ((rc = osInitTable_IniFile (drv,
1312                                   init_table,
1313                                   (init_info && init_info->init_file_length) ?
1314                                   &init_info->data[init_info->eeprom_image_length+init_info->firmware_image_length] : NULL,
1315                                   init_info ? init_info->init_file_length : 0)))
1316    {
1317        ti_dprintf (TIWLAN_LOG_ERROR, "osInitTable_IniFile failed :cannot initialize defaults\n");
1318        os_memoryFree (drv, init_table, sizeof(initTable_t));
1319
1320#ifdef TI_MEM_ALLOC_TRACE
1321        os_printf("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, sizeof(initTable_t), -sizeof(initTable_t));
1322#endif
1323        return rc;
1324    }
1325
1326    pWLAN_Images[0] = (void *)drv->firmware_image.va;
1327    pWLAN_Images[1] = (void *)drv->firmware_image.size;
1328    pWLAN_Images[2] = (void *)drv->eeprom_image.va;
1329    pWLAN_Images[3] = (void *)drv->eeprom_image.size;
1330
1331    drv->adapter.CoreHalCtx = configMgr_create (drv,
1332                                                pWLAN_Images,
1333                                                init_table,
1334                                                (macAddress_t *) &drv->adapter.CurrentAddr);
1335    if (!(drv->adapter.CoreHalCtx))
1336    {
1337#ifdef FIRMWARE_DYNAMIC_LOAD
1338        os_memoryFree(drv,drv->firmware_image.va, drv->firmware_image.size);
1339        os_memoryFree (drv, drv->eeprom_image.va, drv->eeprom_image.size);
1340#endif
1341        os_memoryFree (drv, init_table, sizeof(initTable_t));
1342        ti_dprintf(TIWLAN_LOG_ERROR, "Cannot allocate CoreHalCtx\n");
1343        return -ENOMEM;
1344    }
1345
1346    drv->interrupt_pending = 0;
1347    drv->dma_done = 0;
1348
1349    if (drv->irq)
1350    {
1351#ifndef PRIODIC_INTERRUPT
1352#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
1353        unsigned long flags;
1354        /*
1355         * Disable all interrupts for not to catch the tiwlan irq
1356         * between request_irq and disable_irq
1357         */
1358        spin_lock_irqsave (&(drv->lock), flags);
1359        if ((rc = request_irq (drv->irq, tiwlan_interrupt, SA_SHIRQ, drv->netdev->name, drv)))
1360#else
1361        if ((rc = request_irq (drv->irq, (irq_handler_t)tiwlan_interrupt, IRQF_SHARED | IRQF_TRIGGER_FALLING /*Dm:*/, drv->netdev->name, drv)))
1362#endif
1363        {
1364            print_err ("TIWLAN: Failed to register interrupt handler\n");
1365            configMgr_stop (drv->adapter.CoreHalCtx);
1366#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
1367            spin_unlock_irqrestore (&drv->lock, flags);
1368#endif
1369            return rc;
1370        }
1371#ifdef CONFIG_ANDROID_POWER
1372        set_irq_wake(drv->irq, 1);
1373#endif
1374#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
1375        set_irq_type (drv->irq, IRQT_FALLING);
1376#else
1377        set_irq_type (drv->irq, IRQ_TYPE_EDGE_FALLING);
1378#endif
1379        disable_irq (drv->irq);
1380#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
1381        spin_unlock_irqrestore (&drv->lock, flags);
1382#endif
1383#else
1384        printk (" tiwlan_init_drv :PRIODIC_INTERRUPT drv->irq %x\n",drv->irq);
1385#endif
1386    }
1387    else
1388    {
1389        /* Debug mode: polling */
1390        mod_timer (&drv->poll_timer, jiffies + TIWLAN_IRQ_POLL_INTERVAL);
1391    }
1392
1393    /*
1394     * Now that all parts of the driver have been created and handles linked
1395     * proceed to download the FW code
1396     */
1397    configMgr_init (drv,
1398                    drv->adapter.CoreHalCtx,
1399                    pWLAN_Images,
1400                    init_table,
1401                    (macAddress_t *) &drv->adapter.CurrentAddr);
1402
1403    /* Wait for the download to complete */
1404    os_WaitComplete ((void *)drv);
1405
1406    os_memoryFree (drv, init_table, sizeof(initTable_t));
1407
1408    if (rc == OK)
1409    {
1410        proc_stat_init (drv->adapter.CoreHalCtx);
1411#ifdef TI_MEM_ALLOC_TRACE
1412        osPrintf ("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, sizeof(initTable_t), -sizeof(initTable_t));
1413#endif/*I_MEM_ALLOC_TRACE*/
1414
1415       if (drv->adapter.CoreHalCtx == NULL)
1416       {
1417           ti_dprintf (TIWLAN_LOG_ERROR, "configMgr_create failed\n");
1418           return -ENODEV;
1419       }
1420
1421       /* eeprom buffer is going to be deallocated by the caller. It is no longer needed anyway */
1422#if 0
1423        drv->eeprom_image.va = NULL;
1424        drv->eeprom_image.size = 0;
1425#endif
1426#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
1427#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
1428        drv->wl_sock = netlink_kernel_create(NETLINK_USERSOCK, 0, NULL, THIS_MODULE); /* Dm: */
1429#else
1430        drv->wl_sock = netlink_kernel_create(NETLINK_USERSOCK, 0, NULL, NULL, THIS_MODULE); /* Dm: */
1431#endif
1432#else
1433        drv->wl_sock = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 0, NULL, NULL, THIS_MODULE); /* Dm: */
1434#endif
1435        if (drv->wl_sock == NULL)
1436        {
1437            ti_dprintf(TIWLAN_LOG_ERROR, "netlink_kernel_create() failed !\n");
1438            /* TODO: free in destroy */
1439            return -EINVAL;
1440        }
1441
1442        /* Finalize network interface setup */
1443#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
1444        drv->netdev->hard_start_xmit = tiwlan_drv_net_xmit;
1445#else
1446        drv->netdev->netdev_ops = &tiwlan_ops_pri;
1447#endif
1448        memcpy (drv->netdev->dev_addr, drv->adapter.CurrentAddr, MAC_ADDR_LEN);
1449        drv->netdev->addr_len = MAC_ADDR_LEN;
1450
1451        /* Register the relevant events with the event handler */
1452        tiwlan_register_events (drv);
1453
1454        /* Mark that init stage has succeded */
1455        drv->initialized = 1;
1456
1457        return 0;
1458    }
1459
1460    return -ENODEV;
1461}
1462
1463#ifdef CONFIG_ANDROID_POWER
1464#ifndef CONFIG_HAS_WAKELOCK
1465/* Wrapper for Init wake lock */
1466static void android_init_suspend_wakelock(android_suspend_lock_t *lp,char *nm)
1467{
1468    lp->name = nm;
1469    android_init_suspend_lock( lp );
1470}
1471#endif
1472#endif
1473
1474/* tiwlan_start_drv
1475*/
1476int tiwlan_start_drv(tiwlan_net_dev_t *drv)
1477{
1478    /* printk("%s\n", __FUNCTION__); */
1479    if (!drv->initialized)
1480    {
1481        ti_dprintf(TIWLAN_LOG_ERROR, "Attempt to start driver before initilization has succeeded\n");
1482        return -ENODEV;
1483    }
1484    if (!drv->adapter.CoreHalCtx)
1485    {
1486        ti_dprintf(TIWLAN_LOG_ERROR, "Attempt to start driver before creating config_manager\n");
1487        return -ENODEV;
1488    }
1489    if (drv->started)
1490    {
1491        /*ti_dprintf(TIWLAN_LOG_ERROR, "Attempt to start driver that has already started\n");*/
1492        return -EALREADY;
1493    }
1494    if (configMgr_start(drv->adapter.CoreHalCtx) != OK)
1495    {
1496        print_err("TIWLAN: Failed to start config manager\n");
1497        return -EINVAL;
1498    }
1499    drv->started = 1;
1500
1501#ifdef SDIO_INTERRUPT_HANDLING_ON
1502    configMgr_SlaveAckMaskNotification(drv->adapter.CoreHalCtx);
1503#endif
1504    if (drv->netdev)
1505        netif_start_queue(drv->netdev);
1506#ifdef CONFIG_TROUT_PWRSINK
1507    trout_pwrsink_set(PWRSINK_WIFI, PWRSINK_WIFI_PERCENT_BASE);
1508#endif
1509#ifdef CONFIG_HTC_PWRSINK
1510    htc_pwrsink_set(PWRSINK_WIFI, PWRSINK_WIFI_PERCENT_BASE);
1511#endif
1512    export_wifi_fw_version(drv);
1513    return 0;
1514}
1515
1516
1517/* tiwlan_destroy_drc
1518*/
1519static void tiwlan_destroy_drv(tiwlan_net_dev_t *drv)
1520{
1521    int waitShutdownCounter;
1522
1523    /* close the ipc_kernel socket*/
1524    if (drv && drv->wl_sock) {
1525        sock_release(drv->wl_sock->sk_socket);
1526    }
1527
1528    bm_destroy();
1529
1530    if (drv->started)
1531        tiwlan_send_wait_reply(drv, tiwlan_stop_and_destroy_drv_request, 0, 0, 0, 0);
1532    else
1533        tiwlan_stop_and_destroy_drv(drv);
1534
1535#ifdef DM_USE_WORKQUEUE
1536    while( tiwlan_del_msdu(drv) != NULL );
1537#endif
1538    if (drv->adapter.CoreHalCtx)
1539    {
1540        /* Delay return to OS until all driver components (HAL/SME) are shutdown */
1541        for (waitShutdownCounter=1; waitShutdownCounter<=DRV_SHUTDOWN_TEST_MAX_COUNTER; waitShutdownCounter++)
1542        {
1543            /* Check if HAL/SME are stopped - If so - exit loop and return to OS */
1544            if (configMgr_DriverShutdownStatus(drv->adapter.CoreHalCtx) == DRIVER_SHUTDOWN_COMPLETE)
1545            {
1546                break;
1547            }
1548            /* Delay of 100ms between shutdown test */
1549            mdelay ( DRV_SHUTDOWN_TEST_DELAY_INTERVAL );
1550        }
1551
1552        /* If driver was not shutdown properly - destroy all timers "manually" and exit*/
1553        if ( waitShutdownCounter == DRV_SHUTDOWN_TEST_MAX_COUNTER+1 )
1554        {
1555            os_printf("Timeout while waiting for driver to shutdown...Shutdown status flag=0x%x\n",configMgr_DriverShutdownStatus(drv->adapter.CoreHalCtx));
1556        }
1557
1558        /* drv->unload_driver = 1; Dm: moved to tiwlan_stop_and_destroy_drv */
1559
1560        proc_stat_destroy();
1561        if (drv->irq) {
1562#ifdef CONFIG_ANDROID_POWER
1563            set_irq_wake(drv->irq, 0);
1564#endif
1565            free_irq(drv->irq, drv);
1566        }
1567        else
1568            del_timer_sync(&drv->poll_timer);
1569#ifdef DM_USE_WORKQUEUE
1570        flush_work(&drv->tirq);
1571        flush_work(&drv->tw);
1572        flush_work(&drv->txmit);
1573#if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK)
1574        cancel_delayed_work_sync(&drv->trxw);
1575#endif
1576#endif
1577        /* Unload all modules (free memory) & destroy timers */
1578        configMgr_UnloadModules (drv->adapter.CoreHalCtx);
1579
1580#ifdef FIRMWARE_DYNAMIC_LOAD
1581        if( drv->firmware_image.va ) {
1582            os_memoryFree(drv,drv->firmware_image.va, drv->firmware_image.size);
1583#ifdef TI_MEM_ALLOC_TRACE
1584            os_printf("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, drv->firmware_image.size, -drv->firmware_image.size);
1585#endif /*I_MEM_ALLOC_TRACE*/
1586        }
1587        if( drv->eeprom_image.va )
1588        {
1589            os_memoryFree (drv, drv->eeprom_image.va, drv->eeprom_image.size);
1590#ifdef TI_MEM_ALLOC_TRACE
1591            os_printf("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, drv->eeprom_image.size, -drv->eeprom_image.size);
1592#endif /*I_MEM_ALLOC_TRACE*/
1593        }
1594#endif /*FIRMWARE_DYNAMIC_LOAD*/
1595    }
1596#ifdef DM_USE_WORKQUEUE
1597#if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK)
1598    cancel_delayed_work_sync(&drv->trxw);
1599#endif
1600    destroy_workqueue(drv->tiwlan_wq);
1601#endif
1602#ifdef CONFIG_TROUT_PWRSINK
1603    trout_pwrsink_set(PWRSINK_WIFI, 0);
1604#endif
1605#ifdef CONFIG_HTC_PWRSINK
1606    htc_pwrsink_set(PWRSINK_WIFI, 0);
1607#endif
1608#ifdef CONFIG_ANDROID_POWER
1609    android_uninit_suspend_lock(&drv->irq_wake_lock);
1610    android_uninit_suspend_lock(&drv->xmit_wake_lock);
1611    android_uninit_suspend_lock(&drv->timer_wake_lock);
1612    android_uninit_suspend_lock(&drv->rx_wake_lock);
1613    android_uninit_suspend_lock(&drv->exec_wake_lock);
1614#endif
1615    unregister_netdev(drv->netdev);
1616    tiwlan_free_drv(drv);
1617}
1618
1619
1620/* tiwlan_create_dev
1621   Create tiwlan device instance.
1622   Returns 0 if OK
1623*/
1624static int
1625tiwlan_create_drv(unsigned long reg_start, unsigned long reg_size,
1626                  unsigned long mem_start, unsigned long mem_size,
1627                  int map_io, int irq,
1628                  void *priv, tiwlan_net_dev_t **p_drv)
1629{
1630    tiwlan_net_dev_t *drv;
1631    int rc;
1632
1633    /* printk("%s\n", __FUNCTION__); */
1634    /* Allocate device and map h/w regions */
1635    drv = tiwlan_alloc_drv(reg_start, reg_size, mem_start, mem_size, map_io, irq);
1636    if (!drv)
1637        return -ENOMEM;
1638
1639    /* Check h/w access */
1640    if (tiwlan_set_hw_access(drv))
1641    {
1642        tiwlan_free_drv(drv);
1643        return -ENODEV;
1644    }
1645
1646#ifdef DM_USE_WORKQUEUE
1647#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
1648    drv->tiwlan_wq = create_singlethread_workqueue("tiwlan_wifi_wq");
1649#else
1650    drv->tiwlan_wq = create_freezeable_workqueue("tiwlan_wifi_wq");
1651#endif
1652    if( !(drv->tiwlan_wq) ) {
1653        tiwlan_free_drv(drv);
1654        printk(KERN_ERR "Failed to create workqueue\n");
1655        return -EINVAL;
1656    }
1657#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
1658    INIT_WORK( &drv->tw, tiwlan_work_handler, &drv->tw );
1659    INIT_WORK( &drv->txmit, tiwlan_xmit_handler, &drv->txmit );
1660    INIT_WORK( &drv->tirq, tiwlan_irq_handler, &drv->tirq );
1661#else
1662    INIT_WORK( &drv->tw, tiwlan_work_handler );
1663    INIT_WORK( &drv->txmit, tiwlan_xmit_handler );
1664    INIT_WORK( &drv->tirq, tiwlan_irq_handler );
1665#endif
1666    drv->txmit_msdu_next = drv->txmit_msdu_last = NULL;
1667#else
1668    tasklet_init( &drv->tl, tiwlan_tasklet_handler, (unsigned long)drv );
1669#endif
1670
1671#if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK)
1672#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
1673    INIT_DELAYED_WORK( &drv->trxw, tiwlan_rx_watchdog, &drv->trxw );
1674#else
1675    INIT_DELAYED_WORK( &drv->trxw, tiwlan_rx_watchdog );
1676#endif
1677#endif
1678
1679#ifdef CONFIG_ANDROID_POWER
1680    drv->receive_packet = 0;
1681    android_init_suspend_wakelock(&drv->irq_wake_lock,"tiwlan_irq_wake");
1682    android_init_suspend_wakelock(&drv->xmit_wake_lock,"tiwlan_xmit_wake");
1683    android_init_suspend_wakelock(&drv->timer_wake_lock,"tiwlan_timer_wake");
1684    android_init_suspend_wakelock(&drv->rx_wake_lock,"tiwlan_rx_wake");
1685    android_init_suspend_wakelock(&drv->exec_wake_lock,"tiwlan_exec_wake");
1686#endif
1687    spin_lock_init(&drv->lock);
1688    INIT_LIST_HEAD(&drv->request_q);
1689    init_timer(&drv->poll_timer);
1690    drv->poll_timer.function = tiwlan_poll_irq_handler;
1691    drv->poll_timer.data   = (unsigned long)drv;
1692
1693    /* Init the completion obhect needed for init async purpose */
1694    init_completion(&drv->comp);
1695
1696    /* Register network device */
1697    rc = setup_netif(drv);
1698    if (rc)
1699    {
1700        tiwlan_free_drv(drv);
1701        return rc;
1702    }
1703    drv->priv = priv;
1704
1705    list_add(&drv->list, &tiwlan_drv_list);
1706    if (p_drv)
1707        *p_drv = drv;
1708
1709    drv->initialized = 0;
1710
1711    /* Profiler */
1712#ifdef DRIVER_PROFILING
1713    tiwlan_profile_create (drv);
1714#endif
1715
1716    bm_init(drv);
1717
1718#ifdef NO_USERMODE_WORKAROUND
1719    rc = tiwlan_init_drv(drv, NULL);
1720    rc = rc ? rc : tiwlan_start_drv(drv);
1721#endif
1722
1723    return 0;
1724}
1725
1726/* tiwlan_stop_driver
1727*/
1728int tiwlan_stop_drv(tiwlan_net_dev_t *drv)
1729{
1730    /* printk("%s\n", __FUNCTION__); */
1731    if (!drv->adapter.CoreHalCtx)
1732        return 0;
1733
1734    if (drv->netdev)
1735        netif_stop_queue(drv->netdev);
1736
1737    drv->started = 0;
1738    configMgr_stop(drv->adapter.CoreHalCtx);
1739
1740#ifdef CONFIG_TROUT_PWRSINK
1741    trout_pwrsink_set(PWRSINK_WIFI, 0);
1742#endif
1743#ifdef CONFIG_HTC_PWRSINK
1744    htc_pwrsink_set(PWRSINK_WIFI, 0);
1745#endif
1746    return 0;
1747}
1748
1749/* tiwlan_stop__and_destroy_driver
1750*/
1751int tiwlan_stop_and_destroy_drv(tiwlan_net_dev_t *drv)
1752{
1753    if (!drv->adapter.CoreHalCtx)
1754        return 0;
1755
1756    if (drv->netdev)
1757        netif_stop_queue(drv->netdev);
1758
1759    /* Start unload process by calling smeSm_stop, and halting the HAL */
1760    /* SmeSm_stop finish notification will be one by setting flags */
1761    configMgr_InitiateUnload(drv->adapter.CoreHalCtx);
1762    drv->started = 0;
1763    drv->unload_driver = 1;
1764    return 0;
1765}
1766
1767/* tiwlan_stop__and_destroy_driver from workqueue
1768*/
1769int tiwlan_stop_and_destroy_drv_request(tiwlan_req_t *req)
1770{
1771    tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)(req->drv);
1772    printk("%s: Called\n",__FUNCTION__);
1773    return tiwlan_stop_and_destroy_drv(drv);
1774}
1775
1776void *wifi_kernel_prealloc(int section, unsigned long size)
1777{
1778#ifdef CONFIG_WIFI_CONTROL_FUNC
1779    if( wifi_control_data && wifi_control_data->mem_prealloc )
1780        return wifi_control_data->mem_prealloc( section, size );
1781    else
1782#endif
1783    return NULL;
1784}
1785
1786#ifdef TIWLAN_CARDBUS
1787
1788static struct pci_device_id tnetw1130_pci_tbl[] __devinitdata =
1789{
1790    { VENDOR_ID_TI, DEVICE_ID_TI_WLAN, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
1791    { 0, }
1792};
1793
1794static int __devinit
1795tnetw1130_pci_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
1796{
1797    tiwlan_net_dev_t *drv;
1798    int rc;
1799
1800    print_info("tnetw1130_pci_init_one:\n");
1801    /* IT: for some reason interrupt doesn't work.
1802       use poling mode for now (comments around
1803       pcidev->irq below)
1804    */
1805    rc = tiwlan_create_drv(pcidev->resource[0].start,
1806                           pcidev->resource[0].end - pcidev->resource[0].start,
1807                           pcidev->resource[1].start,
1808                           pcidev->resource[1].end - pcidev->resource[1].start,
1809                           1,
1810                           0/*pcidev->irq*/, pcidev, &drv);
1811    if (!rc)
1812        pcidev->driver_data = drv;
1813    return rc;
1814}
1815
1816void tnetw1130_pci_remove(struct pci_dev *dev)
1817{
1818    tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)dev->driver_data;
1819    if (drv)
1820    {
1821        dev->driver_data = NULL;
1822        tiwlan_destroy_drv(drv);
1823    }
1824}
1825
1826static struct pci_driver tnetw1130_pci_driver = {
1827    .name =      "tnetw1130",
1828    .id_table =  tnetw1130_pci_tbl,
1829    .probe = tnetw1130_pci_init_one,
1830    .remove =    tnetw1130_pci_remove
1831};
1832
1833#endif /* #ifdef TIWLAN_CARDBUS */
1834
1835#ifdef TIWLAN_OMAP1610
1836int omap1610_drv_create(void)
1837{
1838    omap_memif_init();
1839    return tiwlan_create_drv(TIWLAN_OMAP1610_REGBASE, TIWLAN_OMAP1610_REGSIZE,
1840                             TIWLAN_OMAP1610_MEMBASE, TIWLAN_OMAP1610_MEMSIZE,
1841                             0, TIWLAN_OMAP1610_IRQ, NULL, NULL);
1842}
1843#endif /* #ifdef TIWLAN_OMAP1610 */
1844
1845#ifdef TIWLAN_MSM7000
1846
1847#define TROUT_IRQ MSM_GPIO_TO_INT(29)
1848
1849#ifdef SDIO_INTERRUPT_HANDLING_ON
1850static void tiwlan_sdio_irq(struct sdio_func *func)
1851{
1852    printk("%s:\n", __FUNCTION__);
1853}
1854#endif
1855
1856static const struct sdio_device_id tiwlan_sdio_ids[] = {
1857    { SDIO_DEVICE_CLASS(SDIO_CLASS_WLAN)    },
1858    {                                       },
1859};
1860
1861MODULE_DEVICE_TABLE(sdio, tiwlan_sdio_ids);
1862
1863int tiwlan_sdio_init(struct sdio_func *func)
1864{
1865    int rc;
1866
1867    rc = sdio_enable_func(func);
1868    if (rc)
1869        return rc;
1870
1871    rc = sdio_set_block_size(func, 512);
1872    if( rc ) {
1873        sdio_disable_func(func);
1874    }
1875    return rc;
1876}
1877
1878static int tiwlan_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
1879{
1880    int rc;
1881
1882    SDIO_SetFunc( NULL );
1883    if (func->vendor != VENDOR_ID_TI || func->device != DEVICE_ID_TI_WLAN)
1884        return -ENODEV;
1885
1886    printk(KERN_INFO
1887           "TIWLAN: Found SDIO controller (vendor 0x%x, device 0x%x)\n",
1888           func->vendor, func->device);
1889
1890#ifdef CONFIG_TROUT_PWRSINK
1891    trout_pwrsink_set(PWRSINK_WIFI, PWRSINK_WIFI_PERCENT_BASE);
1892#endif
1893#ifdef CONFIG_HTC_PWRSINK
1894    htc_pwrsink_set(PWRSINK_WIFI, PWRSINK_WIFI_PERCENT_BASE);
1895#endif
1896
1897    sdio_claim_host(func);
1898
1899    rc = tiwlan_sdio_init(func);
1900    if (rc)
1901        goto err2;
1902#ifdef SDIO_INTERRUPT_HANDLING_ON
1903    rc = sdio_claim_irq(func, tiwlan_sdio_irq);
1904    if (rc)
1905        goto err1;
1906#endif
1907    SDIO_SetFunc( func );
1908
1909    rc = tiwlan_create_drv(0, 0, 0, 0, 0, TROUT_IRQ, NULL, NULL);
1910
1911    printk(KERN_INFO "TIWLAN: Driver initialized (rc %d)\n", rc);
1912    complete(&sdio_wait);
1913    return rc;
1914#ifdef SDIO_INTERRUPT_HANDLING_ON
1915err1:
1916    sdio_disable_func(func);
1917#endif
1918err2:
1919    sdio_release_host(func);
1920    complete(&sdio_wait);
1921    printk(KERN_ERR "TIWLAN: SDIO failure (err %d)\n", rc);
1922    return rc;
1923}
1924
1925static void tiwlan_sdio_remove(struct sdio_func *func)
1926{
1927    printk(KERN_DEBUG "TIWLAN: Releasing SDIO resources\n");
1928#ifdef SDIO_INTERRUPT_HANDLING_ON
1929    sdio_release_irq(func);
1930#endif
1931    sdio_disable_func(func);
1932    sdio_release_host(func);
1933    printk(KERN_DEBUG "TIWLAN: SDIO resources released\n");
1934}
1935
1936static struct sdio_driver tiwlan_sdio_drv = {
1937    .probe          = tiwlan_sdio_probe,
1938    .remove         = tiwlan_sdio_remove,
1939    .name           = "sdio_tiwlan",
1940    .id_table       = tiwlan_sdio_ids,
1941};
1942
1943#ifdef CONFIG_WIFI_CONTROL_FUNC
1944static int wifi_probe( struct platform_device *pdev )
1945{
1946    struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data);
1947
1948    printk("%s\n", __FUNCTION__);
1949    if( wifi_ctrl ) {
1950        wifi_control_data = wifi_ctrl;
1951        if( wifi_ctrl->set_power )
1952            wifi_ctrl->set_power(1);		/* Power On */
1953        if( wifi_ctrl->set_reset )
1954            wifi_ctrl->set_reset(0);		/* Reset clear */
1955        if( wifi_ctrl->set_carddetect )
1956            wifi_ctrl->set_carddetect(1);	/* CardDetect (0->1) */
1957    }
1958    return 0;
1959}
1960
1961static int wifi_remove( struct platform_device *pdev )
1962{
1963    struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data);
1964
1965    printk("%s\n", __FUNCTION__);
1966    if( wifi_ctrl ) {
1967        if( wifi_ctrl->set_carddetect )
1968            wifi_ctrl->set_carddetect(0);	/* CardDetect (1->0) */
1969        if( wifi_ctrl->set_reset )
1970            wifi_ctrl->set_reset(1);		/* Reset active */
1971        if( wifi_ctrl->set_power )
1972            wifi_ctrl->set_power(0);		/* Power Off */
1973    }
1974    return 0;
1975}
1976
1977static struct platform_driver wifi_device = {
1978    .probe          = wifi_probe,
1979    .remove         = wifi_remove,
1980    .suspend        = NULL,
1981    .resume         = NULL,
1982    .driver         = {
1983        .name   = "msm_wifi",
1984    },
1985};
1986
1987static int wifi_add_dev( void )
1988{
1989    return platform_driver_register( &wifi_device );
1990}
1991
1992static void wifi_del_dev( void )
1993{
1994    platform_driver_unregister( &wifi_device );
1995}
1996
1997int msm_wifi_power( int on )
1998{
1999    printk("%s\n", __FUNCTION__);
2000    if( wifi_control_data && wifi_control_data->set_power ) {
2001        wifi_control_data->set_power(on);
2002    }
2003    return 0;
2004}
2005
2006int msm_wifi_reset( int on )
2007{
2008    printk("%s\n", __FUNCTION__);
2009    if( wifi_control_data && wifi_control_data->set_reset ) {
2010        wifi_control_data->set_reset(on);
2011    }
2012    return 0;
2013}
2014#endif
2015#endif /* TIWLAN_MSM7000 */
2016
2017static int __init tiwlan_module_init(void)
2018{
2019    int rc = 0;
2020
2021    printk(KERN_INFO "TIWLAN: Driver loading\n");
2022   /* Check sizes of basic structures to ensure that compilation
2023      options are OK
2024   */
2025    if (packed_struct_tst())
2026        ;/*IT: return -EINVAL; */
2027
2028    tiwlan_deb_entry = create_proc_entry(TIWLAN_DBG_PROC, 0644, NULL);
2029    if (tiwlan_deb_entry == NULL)
2030        return -EINVAL;
2031    tiwlan_deb_entry->read_proc = tiwlan_deb_read_proc;
2032    tiwlan_deb_entry->write_proc = tiwlan_deb_write_proc;
2033#ifdef TIWLAN_MSM7000
2034    init_completion(&sdio_wait);
2035#endif
2036#ifdef TIWLAN_CARDBUS
2037    if ((rc=pci_register_driver(&tnetw1130_pci_driver)) <  0)
2038        print_err("TIWLAN: PCMCIA driver failed to register\n");
2039        remove_proc_entry(TIWLAN_DBG_PROC, NULL);
2040        return rc;
2041    }
2042    printk(KERN_INFO "TIWLAN: Driver loaded\n");
2043    return 0;
2044
2045#elif defined(TIWLAN_OMAP1610)
2046    rc = omap1610_drv_create();
2047    export_wifi_chip_id();
2048    printk(KERN_INFO "TIWLAN: Driver loaded\n");
2049    return rc;
2050
2051#elif defined(TIWLAN_MSM7000)
2052#ifdef CONFIG_WIFI_CONTROL_FUNC
2053    wifi_add_dev();
2054#else
2055    trout_wifi_power(1);          /* Power On */
2056    trout_wifi_reset(0);          /* Reset clear */
2057    trout_wifi_set_carddetect(1); /* CardDetect (0->1) */
2058#endif
2059
2060    /* Register ourselves as an SDIO driver */
2061    rc = sdio_register_driver(&tiwlan_sdio_drv);
2062    if (rc < 0) {
2063        printk(KERN_ERR "sdio register failed (%d)\n", rc);
2064        remove_proc_entry(TIWLAN_DBG_PROC, NULL);
2065        return rc;
2066    }
2067    /* rc = tiwlan_create_drv(0, 0, 0, 0, 0, TROUT_IRQ, NULL, NULL); -- Called in probe */
2068#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29))
2069    tiwlan_calibration = create_proc_entry("calibration", 0644, NULL);
2070    if (tiwlan_calibration) {
2071        tiwlan_calibration->size = tiwlan_get_nvs_size();
2072        tiwlan_calibration->read_proc = tiwlan_calibration_read_proc;
2073        tiwlan_calibration->write_proc = tiwlan_calibration_write_proc;
2074    }
2075#endif
2076    if (!wait_for_completion_timeout(&sdio_wait, msecs_to_jiffies(10000))) {
2077        printk(KERN_ERR "%s: Timed out waiting for device detect\n", __func__);
2078        remove_proc_entry(TIWLAN_DBG_PROC, NULL);
2079#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29))
2080	if (tiwlan_calibration)
2081            remove_proc_entry("calibration", NULL);
2082#endif
2083        sdio_unregister_driver(&tiwlan_sdio_drv);
2084#ifdef CONFIG_WIFI_CONTROL_FUNC
2085        wifi_del_dev();
2086#else
2087        trout_wifi_set_carddetect(0); /* CardDetect (1->0) */
2088        trout_wifi_reset(1);          /* Reset active */
2089        trout_wifi_power(0);          /* Power Off */
2090#endif
2091        return -ENODEV;
2092    }
2093    export_wifi_chip_id();
2094    printk(KERN_INFO "TIWLAN: Driver loaded\n");
2095    return 0;
2096
2097#else
2098
2099#error Either TIWLAN_CARDBUS, TIWLAN_OMAP1610 or TIWLAN_MSM7000 must be defined
2100
2101#endif
2102}
2103
2104static void __exit tiwlan_module_cleanup(void)
2105{
2106    struct list_head *l;
2107    struct list_head *tmp;
2108
2109    printk(KERN_INFO "TIWLAN: Driver unloading\n");
2110#ifdef TIWLAN_CARDBUS
2111    pci_unregister_driver(&tnetw1130_pci_driver);
2112#endif
2113    list_for_each_safe(l, tmp, &tiwlan_drv_list)
2114    {
2115        tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)list_entry(l, tiwlan_net_dev_t, list);
2116        list_del(l);
2117        tiwlan_destroy_drv(drv);
2118    }
2119    remove_proc_entry(TIWLAN_DBG_PROC, NULL);
2120#ifdef TIWLAN_MSM7000
2121#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29))
2122    if(tiwlan_calibration)
2123        remove_proc_entry("calibration", NULL);
2124#endif
2125    sdio_unregister_driver(&tiwlan_sdio_drv);
2126#ifdef CONFIG_WIFI_CONTROL_FUNC
2127    wifi_del_dev();
2128#else
2129    trout_wifi_set_carddetect(0); /* CardDetect (1->0) */
2130    trout_wifi_reset(1);          /* Reset active */
2131    trout_wifi_power(0);          /* Power Off */
2132#endif
2133#endif
2134    printk(KERN_INFO "TIWLAN: Driver unloaded\n");
2135}
2136
2137module_init(tiwlan_module_init);
2138module_exit(tiwlan_module_cleanup);
2139