Root/target/linux/s3c24xx/files-2.6.30/drivers/ar6000/ar6000/ar6000_drv.c

1/*
2 *
3 * Copyright (c) 2004-2007 Atheros Communications Inc.
4 * All rights reserved.
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation;
10 *
11 * Software distributed under the License is distributed on an "AS
12 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
13 * implied. See the License for the specific language governing
14 * rights and limitations under the License.
15 *
16 *
17 *
18 */
19
20/*
21 * This driver is a pseudo ethernet driver to access the Atheros AR6000
22 * WLAN Device
23 */
24static const char athId[] __attribute__ ((unused)) = "$Id: //depot/sw/releases/olca2.0-GPL/host/os/linux/ar6000_drv.c#2 $";
25
26#include "ar6000_drv.h"
27#include "htc.h"
28
29MODULE_LICENSE("GPL and additional rights");
30
31#ifndef REORG_APTC_HEURISTICS
32#undef ADAPTIVE_POWER_THROUGHPUT_CONTROL
33#endif /* REORG_APTC_HEURISTICS */
34
35#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
36#define APTC_TRAFFIC_SAMPLING_INTERVAL 100 /* msec */
37#define APTC_UPPER_THROUGHPUT_THRESHOLD 3000 /* Kbps */
38#define APTC_LOWER_THROUGHPUT_THRESHOLD 2000 /* Kbps */
39
40typedef struct aptc_traffic_record {
41    A_BOOL timerScheduled;
42    struct timeval samplingTS;
43    unsigned long bytesReceived;
44    unsigned long bytesTransmitted;
45} APTC_TRAFFIC_RECORD;
46
47A_TIMER aptcTimer;
48APTC_TRAFFIC_RECORD aptcTR;
49#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
50
51unsigned int bypasswmi = 0;
52unsigned int debuglevel = 0;
53int tspecCompliance = 1;
54unsigned int busspeedlow = 0;
55unsigned int onebitmode = 0;
56unsigned int skipflash = 0;
57unsigned int wmitimeout = 2;
58unsigned int wlanNodeCaching = 1;
59unsigned int enableuartprint = 0;
60unsigned int logWmiRawMsgs = 0;
61unsigned int enabletimerwar = 0;
62unsigned int mbox_yield_limit = 99;
63int reduce_credit_dribble = 1 + HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF;
64int allow_trace_signal = 0;
65#ifdef CONFIG_HOST_TCMD_SUPPORT
66unsigned int testmode =0;
67#endif
68
69#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
70module_param(bypasswmi, int, 0644);
71module_param(debuglevel, int, 0644);
72module_param(tspecCompliance, int, 0644);
73module_param(onebitmode, int, 0644);
74module_param(busspeedlow, int, 0644);
75module_param(skipflash, int, 0644);
76module_param(wmitimeout, int, 0644);
77module_param(wlanNodeCaching, int, 0644);
78module_param(logWmiRawMsgs, int, 0644);
79module_param(enableuartprint, int, 0644);
80module_param(enabletimerwar, int, 0644);
81module_param(mbox_yield_limit, int, 0644);
82module_param(reduce_credit_dribble, int, 0644);
83module_param(allow_trace_signal, int, 0644);
84#ifdef CONFIG_HOST_TCMD_SUPPORT
85module_param(testmode, int, 0644);
86#endif
87#else
88
89#define __user
90/* for linux 2.4 and lower */
91MODULE_PARM(bypasswmi,"i");
92MODULE_PARM(debuglevel, "i");
93MODULE_PARM(onebitmode,"i");
94MODULE_PARM(busspeedlow, "i");
95MODULE_PARM(skipflash, "i");
96MODULE_PARM(wmitimeout, "i");
97MODULE_PARM(wlanNodeCaching, "i");
98MODULE_PARM(enableuartprint,"i");
99MODULE_PARM(logWmiRawMsgs, "i");
100MODULE_PARM(enabletimerwar,"i");
101MODULE_PARM(mbox_yield_limit,"i");
102MODULE_PARM(reduce_credit_dribble,"i");
103MODULE_PARM(allow_trace_signal,"i");
104#ifdef CONFIG_HOST_TCMD_SUPPORT
105MODULE_PARM(testmode, "i");
106#endif
107#endif
108
109#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
110/* in 2.6.10 and later this is now a pointer to a uint */
111unsigned int _mboxnum = HTC_MAILBOX_NUM_MAX;
112#define mboxnum &_mboxnum
113#else
114unsigned int mboxnum = HTC_MAILBOX_NUM_MAX;
115#endif
116
117#ifdef CONFIG_AR6000_WLAN_RESET
118unsigned int resetok = 1;
119#else
120unsigned int resetok = 0;
121#endif
122
123#ifdef DEBUG
124A_UINT32 g_dbg_flags = DBG_DEFAULTS;
125unsigned int debugflags = 0;
126int debugdriver = 1;
127unsigned int debughtc = 128;
128unsigned int debugbmi = 1;
129unsigned int debughif = 2;
130unsigned int txcreditsavailable[HTC_MAILBOX_NUM_MAX] = {0};
131unsigned int txcreditsconsumed[HTC_MAILBOX_NUM_MAX] = {0};
132unsigned int txcreditintrenable[HTC_MAILBOX_NUM_MAX] = {0};
133unsigned int txcreditintrenableaggregate[HTC_MAILBOX_NUM_MAX] = {0};
134
135#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
136module_param(debugflags, int, 0644);
137module_param(debugdriver, int, 0644);
138module_param(debughtc, int, 0644);
139module_param(debugbmi, int, 0644);
140module_param(debughif, int, 0644);
141module_param(resetok, int, 0644);
142module_param_array(txcreditsavailable, int, mboxnum, 0644);
143module_param_array(txcreditsconsumed, int, mboxnum, 0644);
144module_param_array(txcreditintrenable, int, mboxnum, 0644);
145module_param_array(txcreditintrenableaggregate, int, mboxnum, 0644);
146#else
147/* linux 2.4 and lower */
148MODULE_PARM(debugflags,"i");
149MODULE_PARM(debugdriver, "i");
150MODULE_PARM(debughtc, "i");
151MODULE_PARM(debugbmi, "i");
152MODULE_PARM(debughif, "i");
153MODULE_PARM(resetok, "i");
154MODULE_PARM(txcreditsavailable, "0-3i");
155MODULE_PARM(txcreditsconsumed, "0-3i");
156MODULE_PARM(txcreditintrenable, "0-3i");
157MODULE_PARM(txcreditintrenableaggregate, "0-3i");
158#endif
159
160#endif /* DEBUG */
161
162unsigned int tx_attempt[HTC_MAILBOX_NUM_MAX] = {0};
163unsigned int tx_post[HTC_MAILBOX_NUM_MAX] = {0};
164unsigned int tx_complete[HTC_MAILBOX_NUM_MAX] = {0};
165unsigned int hifBusRequestNumMax = 40;
166unsigned int war23838_disabled = 0;
167#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
168unsigned int enableAPTCHeuristics = 1;
169#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
170#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
171module_param_array(tx_attempt, int, mboxnum, 0644);
172module_param_array(tx_post, int, mboxnum, 0644);
173module_param_array(tx_complete, int, mboxnum, 0644);
174module_param(hifBusRequestNumMax, int, 0644);
175module_param(war23838_disabled, int, 0644);
176#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
177module_param(enableAPTCHeuristics, int, 0644);
178#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
179#else
180MODULE_PARM(tx_attempt, "0-3i");
181MODULE_PARM(tx_post, "0-3i");
182MODULE_PARM(tx_complete, "0-3i");
183MODULE_PARM(hifBusRequestNumMax, "i");
184MODULE_PARM(war23838_disabled, "i");
185#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
186MODULE_PARM(enableAPTCHeuristics, "i");
187#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
188#endif
189
190#ifdef BLOCK_TX_PATH_FLAG
191int blocktx = 0;
192#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
193module_param(blocktx, int, 0644);
194#else
195MODULE_PARM(blocktx, "i");
196#endif
197#endif /* BLOCK_TX_PATH_FLAG */
198
199// TODO move to arsoft_c
200USER_RSSI_THOLD rssi_map[12];
201
202int reconnect_flag = 0;
203
204DECLARE_WAIT_QUEUE_HEAD(ar6000_scan_queue);
205
206/* Function declarations */
207static int ar6000_init_module(void);
208static void ar6000_cleanup_module(void);
209
210int ar6000_init(struct net_device *dev);
211static int ar6000_open(struct net_device *dev);
212static int ar6000_close(struct net_device *dev);
213static int ar6000_cleanup(struct net_device *dev);
214static void ar6000_init_control_info(AR_SOFTC_T *ar);
215static int ar6000_data_tx(struct sk_buff *skb, struct net_device *dev);
216
217static void ar6000_destroy(struct net_device *dev, unsigned int unregister);
218static void ar6000_detect_error(unsigned long ptr);
219static struct net_device_stats *ar6000_get_stats(struct net_device *dev);
220static struct iw_statistics *ar6000_get_iwstats(struct net_device * dev);
221
222/*
223 * HTC service connection handlers
224 */
225static void ar6000_avail_ev(HTC_HANDLE HTCHandle);
226
227static void ar6000_unavail_ev(void *Instance);
228
229static void ar6000_target_failure(void *Instance, A_STATUS Status);
230
231static void ar6000_rx(void *Context, HTC_PACKET *pPacket);
232
233static void ar6000_rx_refill(void *Context,HTC_ENDPOINT_ID Endpoint);
234
235static void ar6000_tx_complete(void *Context, HTC_PACKET *pPacket);
236
237static void ar6000_tx_queue_full(void *Context, HTC_ENDPOINT_ID Endpoint);
238
239static void ar6000_tx_queue_avail(void *Context, HTC_ENDPOINT_ID Endpoint);
240
241/*
242 * Static variables
243 */
244
245static struct net_device *ar6000_devices[MAX_AR6000];
246extern struct iw_handler_def ath_iw_handler_def;
247DECLARE_WAIT_QUEUE_HEAD(arEvent);
248static void ar6000_cookie_init(AR_SOFTC_T *ar);
249static void ar6000_cookie_cleanup(AR_SOFTC_T *ar);
250static void ar6000_free_cookie(AR_SOFTC_T *ar, struct ar_cookie * cookie);
251static struct ar_cookie *ar6000_alloc_cookie(AR_SOFTC_T *ar);
252static void ar6000_TxDataCleanup(AR_SOFTC_T *ar);
253
254#ifdef USER_KEYS
255static A_STATUS ar6000_reinstall_keys(AR_SOFTC_T *ar,A_UINT8 key_op_ctrl);
256#endif
257
258
259static struct ar_cookie s_ar_cookie_mem[MAX_COOKIE_NUM];
260
261#define HOST_INTEREST_ITEM_ADDRESS(ar, item) \
262((ar->arTargetType == TARGET_TYPE_AR6001) ? \
263   AR6001_HOST_INTEREST_ITEM_ADDRESS(item) : \
264   AR6002_HOST_INTEREST_ITEM_ADDRESS(item))
265
266
267/* Debug log support */
268
269/*
270 * Flag to govern whether the debug logs should be parsed in the kernel
271 * or reported to the application.
272 */
273#ifdef DEBUG
274#define REPORT_DEBUG_LOGS_TO_APP
275#endif
276
277A_STATUS
278ar6000_set_host_app_area(AR_SOFTC_T *ar)
279{
280    A_UINT32 address, data;
281    struct host_app_area_s host_app_area;
282
283    /* Fetch the address of the host_app_area_s instance in the host interest area */
284    address = HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest);
285    if (ar6000_ReadRegDiag(ar->arHifDevice, &address, &data) != A_OK) {
286        return A_ERROR;
287    }
288    address = data;
289    host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION;
290    if (ar6000_WriteDataDiag(ar->arHifDevice, address,
291                             (A_UCHAR *)&host_app_area,
292                             sizeof(struct host_app_area_s)) != A_OK)
293    {
294        return A_ERROR;
295    }
296
297    return A_OK;
298}
299
300A_UINT32
301dbglog_get_debug_hdr_ptr(AR_SOFTC_T *ar)
302{
303    A_UINT32 param;
304    A_UINT32 address;
305    A_STATUS status;
306
307    address = HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbglog_hdr);
308    if ((status = ar6000_ReadDataDiag(ar->arHifDevice, address,
309                                      (A_UCHAR *)&param, 4)) != A_OK)
310    {
311        param = 0;
312    }
313
314    return param;
315}
316
317/*
318 * The dbglog module has been initialized. Its ok to access the relevant
319 * data stuctures over the diagnostic window.
320 */
321void
322ar6000_dbglog_init_done(AR_SOFTC_T *ar)
323{
324    ar->dbglog_init_done = TRUE;
325}
326
327A_UINT32
328dbglog_get_debug_fragment(A_INT8 *datap, A_UINT32 len, A_UINT32 limit)
329{
330    A_INT32 *buffer;
331    A_UINT32 count;
332    A_UINT32 numargs;
333    A_UINT32 length;
334    A_UINT32 fraglen;
335
336    count = fraglen = 0;
337    buffer = (A_INT32 *)datap;
338    length = (limit >> 2);
339
340    if (len <= limit) {
341        fraglen = len;
342    } else {
343        while (count < length) {
344            numargs = DBGLOG_GET_NUMARGS(buffer[count]);
345            fraglen = (count << 2);
346            count += numargs + 1;
347        }
348    }
349
350    return fraglen;
351}
352
353void
354dbglog_parse_debug_logs(A_INT8 *datap, A_UINT32 len)
355{
356    A_INT32 *buffer;
357    A_UINT32 count;
358    A_UINT32 timestamp;
359    A_UINT32 debugid;
360    A_UINT32 moduleid;
361    A_UINT32 numargs;
362    A_UINT32 length;
363
364    count = 0;
365    buffer = (A_INT32 *)datap;
366    length = (len >> 2);
367    while (count < length) {
368        debugid = DBGLOG_GET_DBGID(buffer[count]);
369        moduleid = DBGLOG_GET_MODULEID(buffer[count]);
370        numargs = DBGLOG_GET_NUMARGS(buffer[count]);
371        timestamp = DBGLOG_GET_TIMESTAMP(buffer[count]);
372        switch (numargs) {
373            case 0:
374            AR_DEBUG_PRINTF("%d %d (%d)\n", moduleid, debugid, timestamp);
375            break;
376
377            case 1:
378            AR_DEBUG_PRINTF("%d %d (%d): 0x%x\n", moduleid, debugid,
379                            timestamp, buffer[count+1]);
380            break;
381
382            case 2:
383            AR_DEBUG_PRINTF("%d %d (%d): 0x%x, 0x%x\n", moduleid, debugid,
384                            timestamp, buffer[count+1], buffer[count+2]);
385            break;
386
387            default:
388            AR_DEBUG_PRINTF("Invalid args: %d\n", numargs);
389        }
390        count += numargs + 1;
391    }
392}
393
394int
395ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar)
396{
397    struct dbglog_hdr_s debug_hdr;
398    struct dbglog_buf_s debug_buf;
399    A_UINT32 address;
400    A_UINT32 length;
401    A_UINT32 dropped;
402    A_UINT32 firstbuf;
403    A_UINT32 debug_hdr_ptr;
404
405    if (!ar->dbglog_init_done) return A_ERROR;
406
407#ifndef CONFIG_AR6000_WLAN_DEBUG
408    return 0;
409#endif
410
411    AR6000_SPIN_LOCK(&ar->arLock, 0);
412
413    if (ar->dbgLogFetchInProgress) {
414        AR6000_SPIN_UNLOCK(&ar->arLock, 0);
415        return A_EBUSY;
416    }
417
418        /* block out others */
419    ar->dbgLogFetchInProgress = TRUE;
420
421    AR6000_SPIN_UNLOCK(&ar->arLock, 0);
422
423    debug_hdr_ptr = dbglog_get_debug_hdr_ptr(ar);
424    printk("debug_hdr_ptr: 0x%x\n", debug_hdr_ptr);
425
426    /* Get the contents of the ring buffer */
427    if (debug_hdr_ptr) {
428        address = debug_hdr_ptr;
429        length = sizeof(struct dbglog_hdr_s);
430        ar6000_ReadDataDiag(ar->arHifDevice, address,
431                            (A_UCHAR *)&debug_hdr, length);
432        address = (A_UINT32)debug_hdr.dbuf;
433        firstbuf = address;
434        dropped = debug_hdr.dropped;
435        length = sizeof(struct dbglog_buf_s);
436        ar6000_ReadDataDiag(ar->arHifDevice, address,
437                            (A_UCHAR *)&debug_buf, length);
438
439        do {
440            address = (A_UINT32)debug_buf.buffer;
441            length = debug_buf.length;
442            if ((length) && (debug_buf.length <= debug_buf.bufsize)) {
443                /* Rewind the index if it is about to overrun the buffer */
444                if (ar->log_cnt > (DBGLOG_HOST_LOG_BUFFER_SIZE - length)) {
445                    ar->log_cnt = 0;
446                }
447                if(A_OK != ar6000_ReadDataDiag(ar->arHifDevice, address,
448                                    (A_UCHAR *)&ar->log_buffer[ar->log_cnt], length))
449                {
450                    break;
451                }
452                ar6000_dbglog_event(ar, dropped, &ar->log_buffer[ar->log_cnt], length);
453                ar->log_cnt += length;
454            } else {
455                AR_DEBUG_PRINTF("Length: %d (Total size: %d)\n",
456                                debug_buf.length, debug_buf.bufsize);
457            }
458
459            address = (A_UINT32)debug_buf.next;
460            length = sizeof(struct dbglog_buf_s);
461            if(A_OK != ar6000_ReadDataDiag(ar->arHifDevice, address,
462                                (A_UCHAR *)&debug_buf, length))
463            {
464                break;
465            }
466
467        } while (address != firstbuf);
468    }
469
470    ar->dbgLogFetchInProgress = FALSE;
471
472    return A_OK;
473}
474
475void
476ar6000_dbglog_event(AR_SOFTC_T *ar, A_UINT32 dropped,
477                    A_INT8 *buffer, A_UINT32 length)
478{
479#ifdef REPORT_DEBUG_LOGS_TO_APP
480    #define MAX_WIRELESS_EVENT_SIZE 252
481    /*
482     * Break it up into chunks of MAX_WIRELESS_EVENT_SIZE bytes of messages.
483     * There seems to be a limitation on the length of message that could be
484     * transmitted to the user app via this mechanism.
485     */
486    A_UINT32 send, sent;
487
488    sent = 0;
489    send = dbglog_get_debug_fragment(&buffer[sent], length - sent,
490                                     MAX_WIRELESS_EVENT_SIZE);
491    while (send) {
492        ar6000_send_event_to_app(ar, WMIX_DBGLOG_EVENTID, &buffer[sent], send);
493        sent += send;
494        send = dbglog_get_debug_fragment(&buffer[sent], length - sent,
495                                         MAX_WIRELESS_EVENT_SIZE);
496    }
497#else
498    AR_DEBUG_PRINTF("Dropped logs: 0x%x\nDebug info length: %d\n",
499                    dropped, length);
500
501    /* Interpret the debug logs */
502    dbglog_parse_debug_logs(buffer, length);
503#endif /* REPORT_DEBUG_LOGS_TO_APP */
504}
505
506
507
508static int __init
509ar6000_init_module(void)
510{
511    static int probed = 0;
512    A_STATUS status;
513    HTC_INIT_INFO initInfo;
514
515    A_MEMZERO(&initInfo,sizeof(initInfo));
516    initInfo.AddInstance = ar6000_avail_ev;
517    initInfo.DeleteInstance = ar6000_unavail_ev;
518    initInfo.TargetFailure = ar6000_target_failure;
519
520
521#ifdef DEBUG
522    /* Set the debug flags if specified at load time */
523    if(debugflags != 0)
524    {
525        g_dbg_flags = debugflags;
526    }
527#endif
528
529    if (probed) {
530        return -ENODEV;
531    }
532    probed++;
533
534#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
535    memset(&aptcTR, 0, sizeof(APTC_TRAFFIC_RECORD));
536#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
537
538#ifdef CONFIG_HOST_GPIO_SUPPORT
539    ar6000_gpio_init();
540#endif /* CONFIG_HOST_GPIO_SUPPORT */
541
542    status = HTCInit(&initInfo);
543    if(status != A_OK)
544        return -ENODEV;
545
546    return 0;
547}
548
549static void __exit
550ar6000_cleanup_module(void)
551{
552    int i = 0;
553    struct net_device *ar6000_netdev;
554
555#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
556    /* Delete the Adaptive Power Control timer */
557    if (timer_pending(&aptcTimer)) {
558        del_timer_sync(&aptcTimer);
559    }
560#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
561
562    for (i=0; i < MAX_AR6000; i++) {
563        if (ar6000_devices[i] != NULL) {
564            ar6000_netdev = ar6000_devices[i];
565            ar6000_devices[i] = NULL;
566            ar6000_destroy(ar6000_netdev, 1);
567        }
568    }
569
570        /* shutting down HTC will cause the HIF layer to detach from the
571         * underlying bus driver which will cause the subsequent deletion of
572         * all HIF and HTC instances */
573    HTCShutDown();
574
575    AR_DEBUG_PRINTF("ar6000_cleanup: success\n");
576}
577
578#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
579void
580aptcTimerHandler(unsigned long arg)
581{
582    A_UINT32 numbytes;
583    A_UINT32 throughput;
584    AR_SOFTC_T *ar;
585    A_STATUS status;
586
587    ar = (AR_SOFTC_T *)arg;
588    A_ASSERT(ar != NULL);
589    A_ASSERT(!timer_pending(&aptcTimer));
590
591    AR6000_SPIN_LOCK(&ar->arLock, 0);
592
593    /* Get the number of bytes transferred */
594    numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived;
595    aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0;
596
597    /* Calculate and decide based on throughput thresholds */
598    throughput = ((numbytes * 8)/APTC_TRAFFIC_SAMPLING_INTERVAL); /* Kbps */
599    if (throughput < APTC_LOWER_THROUGHPUT_THRESHOLD) {
600        /* Enable Sleep and delete the timer */
601        A_ASSERT(ar->arWmiReady == TRUE);
602        AR6000_SPIN_UNLOCK(&ar->arLock, 0);
603        status = wmi_powermode_cmd(ar->arWmi, REC_POWER);
604        AR6000_SPIN_LOCK(&ar->arLock, 0);
605        A_ASSERT(status == A_OK);
606        aptcTR.timerScheduled = FALSE;
607    } else {
608        A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0);
609    }
610
611    AR6000_SPIN_UNLOCK(&ar->arLock, 0);
612}
613#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
614
615
616
617/* set HTC block size, assume BMI is already initialized */
618A_STATUS ar6000_SetHTCBlockSize(AR_SOFTC_T *ar)
619{
620    A_STATUS status;
621    A_UINT32 blocksizes[HTC_MAILBOX_NUM_MAX];
622
623    do {
624            /* get the block sizes */
625        status = HIFConfigureDevice(ar->arHifDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
626                                    blocksizes, sizeof(blocksizes));
627
628        if (A_FAILED(status)) {
629            AR_DEBUG_PRINTF("Failed to get block size info from HIF layer...\n");
630            break;
631        }
632            /* note: we actually get the block size for mailbox 1, for SDIO the block
633             * size on mailbox 0 is artificially set to 1 */
634            /* must be a power of 2 */
635        A_ASSERT((blocksizes[1] & (blocksizes[1] - 1)) == 0);
636
637            /* set the host interest area for the block size */
638        status = BMIWriteMemory(ar->arHifDevice,
639                                HOST_INTEREST_ITEM_ADDRESS(ar, hi_mbox_io_block_sz),
640                                (A_UCHAR *)&blocksizes[1],
641                                4);
642
643        if (A_FAILED(status)) {
644            AR_DEBUG_PRINTF("BMIWriteMemory for IO block size failed \n");
645            break;
646        }
647
648        AR_DEBUG_PRINTF("Block Size Set: %d (target address:0x%X)\n",
649                blocksizes[1], HOST_INTEREST_ITEM_ADDRESS(ar, hi_mbox_io_block_sz));
650
651            /* set the host interest area for the mbox ISR yield limit */
652        status = BMIWriteMemory(ar->arHifDevice,
653                                HOST_INTEREST_ITEM_ADDRESS(ar, hi_mbox_isr_yield_limit),
654                                (A_UCHAR *)&mbox_yield_limit,
655                                4);
656
657        if (A_FAILED(status)) {
658            AR_DEBUG_PRINTF("BMIWriteMemory for yield limit failed \n");
659            break;
660        }
661
662    } while (FALSE);
663
664    return status;
665}
666
667static void free_raw_buffers(AR_SOFTC_T *ar)
668{
669    int i, j;
670
671    for (i = 0; i != HTC_RAW_STREAM_NUM_MAX; i++) {
672    for (j = 0; j != RAW_HTC_READ_BUFFERS_NUM; j++)
673        kfree(ar->raw_htc_read_buffer[i][j]);
674    for (j = 0; j != RAW_HTC_WRITE_BUFFERS_NUM; j++)
675        kfree(ar->raw_htc_write_buffer[i][j]);
676    }
677}
678
679static int alloc_raw_buffers(AR_SOFTC_T *ar)
680{
681    int i, j;
682    raw_htc_buffer *b;
683
684    for (i = 0; i != HTC_RAW_STREAM_NUM_MAX; i++) {
685    for (j = 0; j != RAW_HTC_READ_BUFFERS_NUM; j++) {
686        b = kzalloc(sizeof(*b), GFP_KERNEL);
687        if (!b)
688        return -ENOMEM;
689        ar->raw_htc_read_buffer[i][j] = b;
690    }
691    for (j = 0; j != RAW_HTC_WRITE_BUFFERS_NUM; j++) {
692        b = kzalloc(sizeof(*b), GFP_KERNEL);
693        if (!b)
694        return -ENOMEM;
695        ar->raw_htc_write_buffer[i][j] = b;
696    }
697    }
698    return 0;
699}
700
701static const struct net_device_ops ar6000_netdev_ops = {
702    .ndo_init = &ar6000_init,
703    .ndo_open = &ar6000_open,
704    .ndo_stop = &ar6000_close,
705    .ndo_start_xmit = &ar6000_data_tx,
706    .ndo_get_stats = &ar6000_get_stats,
707    .ndo_do_ioctl = &ar6000_ioctl,
708};
709/*
710 * HTC Event handlers
711 */
712static void
713ar6000_avail_ev(HTC_HANDLE HTCHandle)
714{
715    int i;
716    struct net_device *dev;
717    AR_SOFTC_T *ar;
718    int device_index = 0;
719
720    AR_DEBUG_PRINTF("ar6000_available\n");
721
722    for (i=0; i < MAX_AR6000; i++) {
723        if (ar6000_devices[i] == NULL) {
724            break;
725        }
726    }
727
728    if (i == MAX_AR6000) {
729        AR_DEBUG_PRINTF("ar6000_available: max devices reached\n");
730        return;
731    }
732
733    /* Save this. It gives a bit better readability especially since */
734    /* we use another local "i" variable below. */
735    device_index = i;
736
737    A_ASSERT(HTCHandle != NULL);
738
739    dev = alloc_etherdev(sizeof(AR_SOFTC_T));
740    if (dev == NULL) {
741        AR_DEBUG_PRINTF("ar6000_available: can't alloc etherdev\n");
742        return;
743    }
744
745    ether_setup(dev);
746
747    if (netdev_priv(dev) == NULL) {
748        printk(KERN_CRIT "ar6000_available: Could not allocate memory\n");
749        return;
750    }
751
752    A_MEMZERO(netdev_priv(dev), sizeof(AR_SOFTC_T));
753
754    ar = (AR_SOFTC_T *)netdev_priv(dev);
755    ar->arNetDev = dev;
756    ar->arHtcTarget = HTCHandle;
757    ar->arHifDevice = HTCGetHifDevice(HTCHandle);
758    ar->arWlanState = WLAN_ENABLED;
759    ar->arRadioSwitch = WLAN_ENABLED;
760    ar->arDeviceIndex = device_index;
761
762    A_INIT_TIMER(&ar->arHBChallengeResp.timer, ar6000_detect_error, dev);
763    ar->arHBChallengeResp.seqNum = 0;
764    ar->arHBChallengeResp.outstanding = FALSE;
765    ar->arHBChallengeResp.missCnt = 0;
766    ar->arHBChallengeResp.frequency = AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT;
767    ar->arHBChallengeResp.missThres = AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAULT;
768
769    ar6000_init_control_info(ar);
770    init_waitqueue_head(&arEvent);
771    sema_init(&ar->arSem, 1);
772
773    if (alloc_raw_buffers(ar)) {
774    free_raw_buffers(ar);
775    /*
776     * @@@ Clean up our own mess, but for anything else, cheerfully mimick
777     * the beautiful error non-handling of the rest of this function.
778     */
779    return;
780    }
781
782#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
783    A_INIT_TIMER(&aptcTimer, aptcTimerHandler, ar);
784#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
785
786    /*
787     * If requested, perform some magic which requires no cooperation from
788     * the Target. It causes the Target to ignore flash and execute to the
789     * OS from ROM.
790     *
791     * This is intended to support recovery from a corrupted flash on Targets
792     * that support flash.
793     */
794    if (skipflash)
795    {
796        ar6000_reset_device_skipflash(ar->arHifDevice);
797            }
798
799    BMIInit();
800    {
801        struct bmi_target_info targ_info;
802
803        if (BMIGetTargetInfo(ar->arHifDevice, &targ_info) != A_OK) {
804            return;
805        }
806
807        ar->arVersion.target_ver = targ_info.target_ver;
808        ar->arTargetType = targ_info.target_type;
809    }
810
811    if (enableuartprint) {
812        A_UINT32 param;
813        param = 1;
814        if (BMIWriteMemory(ar->arHifDevice,
815                           HOST_INTEREST_ITEM_ADDRESS(ar, hi_serial_enable),
816                           (A_UCHAR *)&param,
817                           4)!= A_OK)
818        {
819             AR_DEBUG_PRINTF("BMIWriteMemory for enableuartprint failed \n");
820             return ;
821        }
822        AR_DEBUG_PRINTF("Serial console prints enabled\n");
823    }
824#ifdef CONFIG_HOST_TCMD_SUPPORT
825    if(testmode) {
826        ar->arTargetMode = AR6000_TCMD_MODE;
827    }else {
828        ar->arTargetMode = AR6000_WLAN_MODE;
829    }
830#endif
831    if (enabletimerwar) {
832        A_UINT32 param;
833
834        if (BMIReadMemory(ar->arHifDevice,
835            HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
836            (A_UCHAR *)&param,
837            4)!= A_OK)
838        {
839            AR_DEBUG_PRINTF("BMIReadMemory for enabletimerwar failed \n");
840            return;
841        }
842
843        param |= HI_OPTION_TIMER_WAR;
844
845        if (BMIWriteMemory(ar->arHifDevice,
846            HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
847            (A_UCHAR *)&param,
848            4) != A_OK)
849        {
850            AR_DEBUG_PRINTF("BMIWriteMemory for enabletimerwar failed \n");
851            return;
852        }
853        AR_DEBUG_PRINTF("Timer WAR enabled\n");
854    }
855
856
857        /* since BMIInit is called in the driver layer, we have to set the block
858         * size here for the target */
859
860    if (A_FAILED(ar6000_SetHTCBlockSize(ar))) {
861        return;
862    }
863
864    spin_lock_init(&ar->arLock);
865
866    dev->netdev_ops = &ar6000_netdev_ops;
867    dev->watchdog_timeo = AR6000_TX_TIMEOUT;
868    ar6000_ioctl_iwsetup(&ath_iw_handler_def);
869    dev->wireless_handlers = &ath_iw_handler_def;
870    ath_iw_handler_def.get_wireless_stats = ar6000_get_iwstats; /*Displayed via proc fs */
871
872    /*
873     * We need the OS to provide us with more headroom in order to
874     * perform dix to 802.3, WMI header encap, and the HTC header
875     */
876    dev->hard_header_len = ETH_HLEN + sizeof(ATH_LLC_SNAP_HDR) +
877        sizeof(WMI_DATA_HDR) + HTC_HEADER_LEN;
878
879    /* This runs the init function */
880    SET_NETDEV_DEV(dev, HIFGetOSDevice(ar->arHifDevice));
881    if (register_netdev(dev)) {
882        AR_DEBUG_PRINTF("ar6000_avail: register_netdev failed\n");
883        ar6000_destroy(dev, 0);
884        return;
885    }
886
887    HTCSetInstance(ar->arHtcTarget, ar);
888
889    /* We only register the device in the global list if we succeed. */
890    /* If the device is in the global list, it will be destroyed */
891    /* when the module is unloaded. */
892    ar6000_devices[device_index] = dev;
893
894    AR_DEBUG_PRINTF("ar6000_avail: name=%s htcTarget=0x%x, dev=0x%x (%d), ar=0x%x\n",
895                    dev->name, (A_UINT32)HTCHandle, (A_UINT32)dev, device_index,
896                    (A_UINT32)ar);
897}
898
899static void ar6000_target_failure(void *Instance, A_STATUS Status)
900{
901    AR_SOFTC_T *ar = (AR_SOFTC_T *)Instance;
902    WMI_TARGET_ERROR_REPORT_EVENT errEvent;
903    static A_BOOL sip = FALSE;
904
905    if (Status != A_OK) {
906        if (timer_pending(&ar->arHBChallengeResp.timer)) {
907            A_UNTIMEOUT(&ar->arHBChallengeResp.timer);
908        }
909
910        /* try dumping target assertion information (if any) */
911        ar6000_dump_target_assert_info(ar->arHifDevice,ar->arTargetType);
912
913        /*
914         * Fetch the logs from the target via the diagnostic
915         * window.
916         */
917        ar6000_dbglog_get_debug_logs(ar);
918
919        /* Report the error only once */
920        if (!sip) {
921            sip = TRUE;
922            errEvent.errorVal = WMI_TARGET_COM_ERR |
923                                WMI_TARGET_FATAL_ERR;
924#ifdef SEND_EVENT_TO_APP
925            ar6000_send_event_to_app(ar, WMI_ERROR_REPORT_EVENTID,
926                                     (A_UINT8 *)&errEvent,
927                                     sizeof(WMI_TARGET_ERROR_REPORT_EVENT));
928#endif
929        }
930    }
931}
932
933static void
934ar6000_unavail_ev(void *Instance)
935{
936    AR_SOFTC_T *ar = (AR_SOFTC_T *)Instance;
937        /* NULL out it's entry in the global list */
938    ar6000_devices[ar->arDeviceIndex] = NULL;
939    ar6000_destroy(ar->arNetDev, 1);
940}
941
942/*
943 * We need to differentiate between the surprise and planned removal of the
944 * device because of the following consideration:
945 * - In case of surprise removal, the hcd already frees up the pending
946 * for the device and hence there is no need to unregister the function
947 * driver inorder to get these requests. For planned removal, the function
948 * driver has to explictly unregister itself to have the hcd return all the
949 * pending requests before the data structures for the devices are freed up.
950 * Note that as per the current implementation, the function driver will
951 * end up releasing all the devices since there is no API to selectively
952 * release a particular device.
953 * - Certain commands issued to the target can be skipped for surprise
954 * removal since they will anyway not go through.
955 */
956static void
957ar6000_destroy(struct net_device *dev, unsigned int unregister)
958{
959    AR_SOFTC_T *ar;
960
961    AR_DEBUG_PRINTF("+ar6000_destroy \n");
962
963    if((dev == NULL) || ((ar = netdev_priv(dev)) == NULL))
964    {
965        AR_DEBUG_PRINTF("%s(): Failed to get device structure.\n", __func__);
966        return;
967    }
968
969    /* Clear the tx counters */
970    memset(tx_attempt, 0, sizeof(tx_attempt));
971    memset(tx_post, 0, sizeof(tx_post));
972    memset(tx_complete, 0, sizeof(tx_complete));
973
974    /* Free up the device data structure */
975    if (unregister) {
976    unregister_netdev(dev);
977    } else {
978    ar6000_close(dev);
979    ar6000_cleanup(dev);
980    }
981
982    free_raw_buffers(ar);
983
984#ifndef free_netdev
985    kfree(dev);
986#else
987    free_netdev(dev);
988#endif
989
990    AR_DEBUG_PRINTF("-ar6000_destroy \n");
991}
992
993static void ar6000_detect_error(unsigned long ptr)
994{
995    struct net_device *dev = (struct net_device *)ptr;
996    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
997    WMI_TARGET_ERROR_REPORT_EVENT errEvent;
998
999    AR6000_SPIN_LOCK(&ar->arLock, 0);
1000
1001    if (ar->arHBChallengeResp.outstanding) {
1002        ar->arHBChallengeResp.missCnt++;
1003    } else {
1004        ar->arHBChallengeResp.missCnt = 0;
1005    }
1006
1007    if (ar->arHBChallengeResp.missCnt > ar->arHBChallengeResp.missThres) {
1008        /* Send Error Detect event to the application layer and do not reschedule the error detection module timer */
1009        ar->arHBChallengeResp.missCnt = 0;
1010        ar->arHBChallengeResp.seqNum = 0;
1011        errEvent.errorVal = WMI_TARGET_COM_ERR | WMI_TARGET_FATAL_ERR;
1012        AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1013#ifdef SEND_EVENT_TO_APP
1014        ar6000_send_event_to_app(ar, WMI_ERROR_REPORT_EVENTID,
1015                                 (A_UINT8 *)&errEvent,
1016                                 sizeof(WMI_TARGET_ERROR_REPORT_EVENT));
1017#endif
1018        return;
1019    }
1020
1021    /* Generate the sequence number for the next challenge */
1022    ar->arHBChallengeResp.seqNum++;
1023    ar->arHBChallengeResp.outstanding = TRUE;
1024
1025    AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1026
1027    /* Send the challenge on the control channel */
1028    if (wmi_get_challenge_resp_cmd(ar->arWmi, ar->arHBChallengeResp.seqNum, DRV_HB_CHALLENGE) != A_OK) {
1029        AR_DEBUG_PRINTF("Unable to send heart beat challenge\n");
1030    }
1031
1032
1033    /* Reschedule the timer for the next challenge */
1034    A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0);
1035}
1036
1037void ar6000_init_profile_info(AR_SOFTC_T *ar)
1038{
1039    ar->arSsidLen = 0;
1040    A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1041    ar->arNetworkType = INFRA_NETWORK;
1042    ar->arDot11AuthMode = OPEN_AUTH;
1043    ar->arAuthMode = NONE_AUTH;
1044    ar->arPairwiseCrypto = NONE_CRYPT;
1045    ar->arPairwiseCryptoLen = 0;
1046    ar->arGroupCrypto = NONE_CRYPT;
1047    ar->arGroupCryptoLen = 0;
1048    A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList));
1049    A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
1050    A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
1051    ar->arBssChannel = 0;
1052}
1053
1054static void
1055ar6000_init_control_info(AR_SOFTC_T *ar)
1056{
1057    ar->arWmiEnabled = FALSE;
1058    ar6000_init_profile_info(ar);
1059    ar->arDefTxKeyIndex = 0;
1060    A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList));
1061    ar->arChannelHint = 0;
1062    ar->arListenInterval = MAX_LISTEN_INTERVAL;
1063    ar->arVersion.host_ver = AR6K_SW_VERSION;
1064    ar->arRssi = 0;
1065    ar->arTxPwr = 0;
1066    ar->arTxPwrSet = FALSE;
1067    ar->arSkipScan = 0;
1068    ar->arBeaconInterval = 0;
1069    ar->arBitRate = 0;
1070    ar->arMaxRetries = 0;
1071    ar->arWmmEnabled = TRUE;
1072}
1073
1074static int
1075ar6000_open(struct net_device *dev)
1076{
1077    /* Wake up the queues */
1078    netif_start_queue(dev);
1079
1080    return 0;
1081}
1082
1083static int
1084ar6000_close(struct net_device *dev)
1085{
1086    /* Stop the transmit queues */
1087    netif_stop_queue(dev);
1088    return 0;
1089}
1090
1091static int
1092ar6000_cleanup(struct net_device *dev)
1093{
1094    AR_SOFTC_T *ar = netdev_priv(dev);
1095
1096    /* Stop the transmit queues */
1097    netif_stop_queue(dev);
1098
1099    /* Disable the target and the interrupts associated with it */
1100    if (ar->arWmiReady == TRUE)
1101    {
1102        if (!bypasswmi)
1103        {
1104            if (ar->arConnected == TRUE || ar->arConnectPending == TRUE)
1105            {
1106                AR_DEBUG_PRINTF("%s(): Disconnect\n", __func__);
1107                AR6000_SPIN_LOCK(&ar->arLock, 0);
1108                ar6000_init_profile_info(ar);
1109                AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1110                wmi_disconnect_cmd(ar->arWmi);
1111            }
1112
1113            ar6000_dbglog_get_debug_logs(ar);
1114            ar->arWmiReady = FALSE;
1115            ar->arConnected = FALSE;
1116            ar->arConnectPending = FALSE;
1117            wmi_shutdown(ar->arWmi);
1118            ar->arWmiEnabled = FALSE;
1119            ar->arWmi = NULL;
1120            ar->arWlanState = WLAN_ENABLED;
1121#ifdef USER_KEYS
1122            ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
1123            ar->user_key_ctrl = 0;
1124#endif
1125        }
1126
1127         AR_DEBUG_PRINTF("%s(): WMI stopped\n", __func__);
1128    }
1129    else
1130    {
1131        AR_DEBUG_PRINTF("%s(): WMI not ready 0x%08x 0x%08x\n",
1132            __func__, (unsigned int) ar, (unsigned int) ar->arWmi);
1133
1134        /* Shut down WMI if we have started it */
1135        if(ar->arWmiEnabled == TRUE)
1136        {
1137            AR_DEBUG_PRINTF("%s(): Shut down WMI\n", __func__);
1138            wmi_shutdown(ar->arWmi);
1139            ar->arWmiEnabled = FALSE;
1140            ar->arWmi = NULL;
1141        }
1142    }
1143
1144    /* stop HTC */
1145    HTCStop(ar->arHtcTarget);
1146
1147    /* set the instance to NULL so we do not get called back on remove incase we
1148     * we're explicity destroyed by module unload */
1149    HTCSetInstance(ar->arHtcTarget, NULL);
1150
1151    if (resetok) {
1152        /* try to reset the device if we can
1153         * The driver may have been configure NOT to reset the target during
1154         * a debug session */
1155        AR_DEBUG_PRINTF(" Attempting to reset target on instance destroy.... \n");
1156        ar6000_reset_device(ar->arHifDevice, ar->arTargetType);
1157    } else {
1158        AR_DEBUG_PRINTF(" Host does not want target reset. \n");
1159    }
1160
1161       /* Done with cookies */
1162    ar6000_cookie_cleanup(ar);
1163
1164    /* Cleanup BMI */
1165    BMIInit();
1166
1167    return 0;
1168}
1169
1170/* connect to a service */
1171static A_STATUS ar6000_connectservice(AR_SOFTC_T *ar,
1172                                      HTC_SERVICE_CONNECT_REQ *pConnect,
1173                                      WMI_PRI_STREAM_ID WmiStreamID,
1174                                      char *pDesc)
1175{
1176    A_STATUS status;
1177    HTC_SERVICE_CONNECT_RESP response;
1178
1179    do {
1180
1181        A_MEMZERO(&response,sizeof(response));
1182
1183        status = HTCConnectService(ar->arHtcTarget,
1184                                   pConnect,
1185                                   &response);
1186
1187        if (A_FAILED(status)) {
1188            AR_DEBUG_PRINTF(" Failed to connect to %s service status:%d \n", pDesc, status);
1189            break;
1190        }
1191
1192        if (WmiStreamID == WMI_NOT_MAPPED) {
1193                /* done */
1194            break;
1195        }
1196
1197            /* set endpoint mapping for the WMI stream in the driver layer */
1198        arSetWMIStream2EndpointIDMap(ar,WmiStreamID,response.Endpoint);
1199
1200    } while (FALSE);
1201
1202    return status;
1203}
1204
1205static void ar6000_TxDataCleanup(AR_SOFTC_T *ar)
1206{
1207        /* flush all the data (non-control) streams
1208         * we only flush packets that are tagged as data, we leave any control packets that
1209         * were in the TX queues alone */
1210    HTCFlushEndpoint(ar->arHtcTarget,
1211                     arWMIStream2EndpointID(ar,WMI_BEST_EFFORT_PRI),
1212                     AR6K_DATA_PKT_TAG);
1213    HTCFlushEndpoint(ar->arHtcTarget,
1214                     arWMIStream2EndpointID(ar,WMI_LOW_PRI),
1215                     AR6K_DATA_PKT_TAG);
1216    HTCFlushEndpoint(ar->arHtcTarget,
1217                     arWMIStream2EndpointID(ar,WMI_HIGH_PRI),
1218                     AR6K_DATA_PKT_TAG);
1219    HTCFlushEndpoint(ar->arHtcTarget,
1220                     arWMIStream2EndpointID(ar,WMI_HIGHEST_PRI),
1221                     AR6K_DATA_PKT_TAG);
1222}
1223
1224/* This function does one time initialization for the lifetime of the device */
1225int ar6000_init(struct net_device *dev)
1226{
1227    AR_SOFTC_T *ar;
1228    A_STATUS status;
1229    A_INT32 timeleft;
1230
1231    if((ar = netdev_priv(dev)) == NULL)
1232    {
1233        return(-EIO);
1234    }
1235
1236    /* Do we need to finish the BMI phase */
1237    if(BMIDone(ar->arHifDevice) != A_OK)
1238    {
1239        return -EIO;
1240    }
1241
1242    if (!bypasswmi)
1243    {
1244#if 0 /* TBDXXX */
1245        if (ar->arVersion.host_ver != ar->arVersion.target_ver) {
1246            A_PRINTF("WARNING: Host version 0x%x does not match Target "
1247                    " version 0x%x!\n",
1248                    ar->arVersion.host_ver, ar->arVersion.target_ver);
1249        }
1250#endif
1251
1252        /* Indicate that WMI is enabled (although not ready yet) */
1253        ar->arWmiEnabled = TRUE;
1254        if ((ar->arWmi = wmi_init((void *) ar)) == NULL)
1255        {
1256            AR_DEBUG_PRINTF("%s() Failed to initialize WMI.\n", __func__);
1257            return(-EIO);
1258        }
1259
1260        AR_DEBUG_PRINTF("%s() Got WMI @ 0x%08x.\n", __func__,
1261            (unsigned int) ar->arWmi);
1262    }
1263
1264    do {
1265        HTC_SERVICE_CONNECT_REQ connect;
1266
1267            /* the reason we have to wait for the target here is that the driver layer
1268             * has to init BMI in order to set the host block size,
1269             */
1270        status = HTCWaitTarget(ar->arHtcTarget);
1271
1272        if (A_FAILED(status)) {
1273            break;
1274        }
1275
1276        A_MEMZERO(&connect,sizeof(connect));
1277            /* meta data is unused for now */
1278        connect.pMetaData = NULL;
1279        connect.MetaDataLength = 0;
1280            /* these fields are the same for all service endpoints */
1281        connect.EpCallbacks.pContext = ar;
1282        connect.EpCallbacks.EpTxComplete = ar6000_tx_complete;
1283        connect.EpCallbacks.EpRecv = ar6000_rx;
1284        connect.EpCallbacks.EpRecvRefill = ar6000_rx_refill;
1285        connect.EpCallbacks.EpSendFull = ar6000_tx_queue_full;
1286        connect.EpCallbacks.EpSendAvail = ar6000_tx_queue_avail;
1287            /* set the max queue depth so that our ar6000_tx_queue_full handler gets called.
1288             * Linux has the peculiarity of not providing flow control between the
1289             * NIC and the network stack. There is no API to indicate that a TX packet
1290             * was sent which could provide some back pressure to the network stack.
1291             * Under linux you would have to wait till the network stack consumed all sk_buffs
1292             * before any back-flow kicked in. Which isn't very friendly.
1293             * So we have to manage this ourselves */
1294        connect.MaxSendQueueDepth = 32;
1295
1296            /* connect to control service */
1297        connect.ServiceID = WMI_CONTROL_SVC;
1298        status = ar6000_connectservice(ar,
1299                                       &connect,
1300                                       WMI_CONTROL_PRI,
1301                                       "WMI CONTROL");
1302        if (A_FAILED(status)) {
1303            break;
1304        }
1305
1306            /* for the remaining data services set the connection flag to reduce dribbling,
1307             * if configured to do so */
1308        if (reduce_credit_dribble) {
1309            connect.ConnectionFlags |= HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE;
1310            /* the credit dribble trigger threshold is (reduce_credit_dribble - 1) for a value
1311             * of 0-3 */
1312            connect.ConnectionFlags &= ~HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK;
1313            connect.ConnectionFlags |=
1314                        ((A_UINT16)reduce_credit_dribble - 1) & HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK;
1315        }
1316            /* connect to best-effort service */
1317        connect.ServiceID = WMI_DATA_BE_SVC;
1318
1319        status = ar6000_connectservice(ar,
1320                                       &connect,
1321                                       WMI_BEST_EFFORT_PRI,
1322                                       "WMI DATA BE");
1323        if (A_FAILED(status)) {
1324            break;
1325        }
1326
1327            /* connect to back-ground
1328             * map this to WMI LOW_PRI */
1329        connect.ServiceID = WMI_DATA_BK_SVC;
1330        status = ar6000_connectservice(ar,
1331                                       &connect,
1332                                       WMI_LOW_PRI,
1333                                       "WMI DATA BK");
1334        if (A_FAILED(status)) {
1335            break;
1336        }
1337
1338            /* connect to Video service, map this to
1339             * to HI PRI */
1340        connect.ServiceID = WMI_DATA_VI_SVC;
1341        status = ar6000_connectservice(ar,
1342                                       &connect,
1343                                       WMI_HIGH_PRI,
1344                                       "WMI DATA VI");
1345        if (A_FAILED(status)) {
1346            break;
1347        }
1348
1349            /* connect to VO service, this is currently not
1350             * mapped to a WMI priority stream due to historical reasons.
1351             * WMI originally defined 3 priorities over 3 mailboxes
1352             * We can change this when WMI is reworked so that priorities are not
1353             * dependent on mailboxes */
1354        connect.ServiceID = WMI_DATA_VO_SVC;
1355        status = ar6000_connectservice(ar,
1356                                       &connect,
1357                                       WMI_HIGHEST_PRI,
1358                                       "WMI DATA VO");
1359        if (A_FAILED(status)) {
1360            break;
1361        }
1362
1363        A_ASSERT(arWMIStream2EndpointID(ar,WMI_CONTROL_PRI) != 0);
1364        A_ASSERT(arWMIStream2EndpointID(ar,WMI_BEST_EFFORT_PRI) != 0);
1365        A_ASSERT(arWMIStream2EndpointID(ar,WMI_LOW_PRI) != 0);
1366        A_ASSERT(arWMIStream2EndpointID(ar,WMI_HIGH_PRI) != 0);
1367        A_ASSERT(arWMIStream2EndpointID(ar,WMI_HIGHEST_PRI) != 0);
1368    } while (FALSE);
1369
1370    if (A_FAILED(status)) {
1371        return (-EIO);
1372    }
1373
1374    /*
1375     * give our connected endpoints some buffers
1376     */
1377    ar6000_rx_refill(ar, arWMIStream2EndpointID(ar,WMI_CONTROL_PRI));
1378
1379    ar6000_rx_refill(ar, arWMIStream2EndpointID(ar,WMI_BEST_EFFORT_PRI));
1380
1381    /*
1382     * We will post the receive buffers only for SPE testing and so we are
1383     * making it conditional on the 'bypasswmi' flag.
1384     */
1385    if (bypasswmi) {
1386        ar6000_rx_refill(ar,arWMIStream2EndpointID(ar,WMI_LOW_PRI));
1387        ar6000_rx_refill(ar,arWMIStream2EndpointID(ar,WMI_HIGH_PRI));
1388    }
1389
1390        /* setup credit distribution */
1391    ar6000_setup_credit_dist(ar->arHtcTarget, &ar->arCreditStateInfo);
1392
1393    /* Since cookies are used for HTC transports, they should be */
1394    /* initialized prior to enabling HTC. */
1395    ar6000_cookie_init(ar);
1396
1397    /* start HTC */
1398    status = HTCStart(ar->arHtcTarget);
1399
1400    if (status != A_OK) {
1401        if (ar->arWmiEnabled == TRUE) {
1402            wmi_shutdown(ar->arWmi);
1403            ar->arWmiEnabled = FALSE;
1404            ar->arWmi = NULL;
1405        }
1406        ar6000_cookie_cleanup(ar);
1407        return -EIO;
1408    }
1409
1410    if (!bypasswmi) {
1411        /* Wait for Wmi event to be ready */
1412        timeleft = wait_event_interruptible_timeout(arEvent,
1413            (ar->arWmiReady == TRUE), wmitimeout * HZ);
1414
1415        if(!timeleft || signal_pending(current))
1416        {
1417            AR_DEBUG_PRINTF("WMI is not ready or wait was interrupted\n");
1418#if defined(DWSIM) /* TBDXXX */
1419            AR_DEBUG_PRINTF(".....but proceed anyway.\n");
1420#else
1421            return -EIO;
1422#endif
1423        }
1424
1425        AR_DEBUG_PRINTF("%s() WMI is ready\n", __func__);
1426
1427        /* Communicate the wmi protocol verision to the target */
1428        if ((ar6000_set_host_app_area(ar)) != A_OK) {
1429            AR_DEBUG_PRINTF("Unable to set the host app area\n");
1430        }
1431    }
1432
1433    ar->arNumDataEndPts = 1;
1434
1435    return(0);
1436}
1437
1438
1439void
1440ar6000_bitrate_rx(void *devt, A_INT32 rateKbps)
1441{
1442    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
1443
1444    ar->arBitRate = rateKbps;
1445    wake_up(&arEvent);
1446}
1447
1448void
1449ar6000_ratemask_rx(void *devt, A_UINT16 ratemask)
1450{
1451    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
1452
1453    ar->arRateMask = ratemask;
1454    wake_up(&arEvent);
1455}
1456
1457void
1458ar6000_txPwr_rx(void *devt, A_UINT8 txPwr)
1459{
1460    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
1461
1462    ar->arTxPwr = txPwr;
1463    wake_up(&arEvent);
1464}
1465
1466
1467void
1468ar6000_channelList_rx(void *devt, A_INT8 numChan, A_UINT16 *chanList)
1469{
1470    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
1471
1472    A_MEMCPY(ar->arChannelList, chanList, numChan * sizeof (A_UINT16));
1473    ar->arNumChannels = numChan;
1474
1475    wake_up(&arEvent);
1476}
1477
1478A_UINT8
1479ar6000_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, A_UINT32 * mapNo)
1480{
1481    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1482    A_UINT8 *datap;
1483    ATH_MAC_HDR *macHdr;
1484    A_UINT32 i, eptMap;
1485
1486    (*mapNo) = 0;
1487    datap = A_NETBUF_DATA(skb);
1488    macHdr = (ATH_MAC_HDR *)(datap + sizeof(WMI_DATA_HDR));
1489    if (IEEE80211_IS_MULTICAST(macHdr->dstMac)) {
1490        return ENDPOINT_2;
1491    }
1492
1493    eptMap = -1;
1494    for (i = 0; i < ar->arNodeNum; i ++) {
1495        if (IEEE80211_ADDR_EQ(macHdr->dstMac, ar->arNodeMap[i].macAddress)) {
1496            (*mapNo) = i + 1;
1497            ar->arNodeMap[i].txPending ++;
1498            return ar->arNodeMap[i].epId;
1499        }
1500
1501        if ((eptMap == -1) && !ar->arNodeMap[i].txPending) {
1502            eptMap = i;
1503        }
1504    }
1505
1506    if (eptMap == -1) {
1507        eptMap = ar->arNodeNum;
1508        ar->arNodeNum ++;
1509        A_ASSERT(ar->arNodeNum <= MAX_NODE_NUM);
1510    }
1511
1512    A_MEMCPY(ar->arNodeMap[eptMap].macAddress, macHdr->dstMac, IEEE80211_ADDR_LEN);
1513
1514    for (i = ENDPOINT_2; i <= ENDPOINT_5; i ++) {
1515        if (!ar->arTxPending[i]) {
1516            ar->arNodeMap[eptMap].epId = i;
1517            break;
1518        }
1519        // No free endpoint is available, start redistribution on the inuse endpoints.
1520        if (i == ENDPOINT_5) {
1521            ar->arNodeMap[eptMap].epId = ar->arNexEpId;
1522            ar->arNexEpId ++;
1523            if (ar->arNexEpId > ENDPOINT_5) {
1524                ar->arNexEpId = ENDPOINT_2;
1525            }
1526        }
1527    }
1528
1529    (*mapNo) = eptMap + 1;
1530    ar->arNodeMap[eptMap].txPending ++;
1531
1532    return ar->arNodeMap[eptMap].epId;
1533}
1534
1535#ifdef DEBUG
1536static void ar6000_dump_skb(struct sk_buff *skb)
1537{
1538   u_char *ch;
1539   for (ch = A_NETBUF_DATA(skb);
1540        (A_UINT32)ch < ((A_UINT32)A_NETBUF_DATA(skb) +
1541        A_NETBUF_LEN(skb)); ch++)
1542    {
1543         AR_DEBUG_PRINTF("%2.2x ", *ch);
1544    }
1545    AR_DEBUG_PRINTF("\n");
1546}
1547#endif
1548
1549static int
1550ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
1551{
1552    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1553    WMI_PRI_STREAM_ID streamID = WMI_NOT_MAPPED;
1554    A_UINT32 mapNo = 0;
1555    int len;
1556    struct ar_cookie *cookie;
1557    A_BOOL checkAdHocPsMapping = FALSE;
1558
1559#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
1560    skb->list = NULL;
1561#endif
1562
1563    AR_DEBUG2_PRINTF("ar6000_data_tx start - skb=0x%x, data=0x%x, len=0x%x\n",
1564                     (A_UINT32)skb, (A_UINT32)A_NETBUF_DATA(skb),
1565                     A_NETBUF_LEN(skb));
1566#ifdef CONFIG_HOST_TCMD_SUPPORT
1567     /* TCMD doesnt support any data, free the buf and return */
1568    if(ar->arTargetMode == AR6000_TCMD_MODE) {
1569        A_NETBUF_FREE(skb);
1570        return 0;
1571    }
1572#endif
1573    do {
1574
1575        if (ar->arWmiReady == FALSE && bypasswmi == 0) {
1576            break;
1577        }
1578
1579#ifdef BLOCK_TX_PATH_FLAG
1580        if (blocktx) {
1581            break;
1582        }
1583#endif /* BLOCK_TX_PATH_FLAG */
1584
1585        if (ar->arWmiEnabled) {
1586            if (A_NETBUF_HEADROOM(skb) < dev->hard_header_len) {
1587                struct sk_buff *newbuf;
1588                /*
1589                 * We really should have gotten enough headroom but sometimes
1590                 * we still get packets with not enough headroom. Copy the packet.
1591                 */
1592                len = A_NETBUF_LEN(skb);
1593                newbuf = A_NETBUF_ALLOC(len);
1594                if (newbuf == NULL) {
1595                    break;
1596                }
1597                A_NETBUF_PUT(newbuf, len);
1598                A_MEMCPY(A_NETBUF_DATA(newbuf), A_NETBUF_DATA(skb), len);
1599                A_NETBUF_FREE(skb);
1600                skb = newbuf;
1601                /* fall through and assemble header */
1602            }
1603
1604            if (wmi_dix_2_dot3(ar->arWmi, skb) != A_OK) {
1605                AR_DEBUG_PRINTF("ar6000_data_tx - wmi_dix_2_dot3 failed\n");
1606                break;
1607            }
1608
1609            if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE) != A_OK) {
1610                AR_DEBUG_PRINTF("ar6000_data_tx - wmi_data_hdr_add failed\n");
1611                break;
1612            }
1613
1614            if ((ar->arNetworkType == ADHOC_NETWORK) &&
1615                ar->arIbssPsEnable && ar->arConnected) {
1616                    /* flag to check adhoc mapping once we take the lock below: */
1617                checkAdHocPsMapping = TRUE;
1618
1619            } else {
1620                    /* get the stream mapping */
1621                if (ar->arWmmEnabled) {
1622                    streamID = wmi_get_stream_id(ar->arWmi,
1623                                    wmi_implicit_create_pstream(ar->arWmi, skb, UPLINK_TRAFFIC, UNDEFINED_PRI));
1624                } else {
1625                    streamID = WMI_BEST_EFFORT_PRI;
1626                }
1627            }
1628
1629        } else {
1630            struct iphdr *ipHdr;
1631            /*
1632             * the endpoint is directly based on the TOS field in the IP
1633             * header **** only for testing ******
1634             */
1635            ipHdr = A_NETBUF_DATA(skb) + sizeof(ATH_MAC_HDR);
1636                /* here we map the TOS field to an endpoint number, this is for
1637                 * the endpointping test application */
1638            streamID = IP_TOS_TO_WMI_PRI(ipHdr->tos);
1639        }
1640
1641    } while (FALSE);
1642
1643        /* did we succeed ? */
1644    if ((streamID == WMI_NOT_MAPPED) && !checkAdHocPsMapping) {
1645            /* cleanup and exit */
1646        A_NETBUF_FREE(skb);
1647        AR6000_STAT_INC(ar, tx_dropped);
1648        AR6000_STAT_INC(ar, tx_aborted_errors);
1649        return 0;
1650    }
1651
1652    cookie = NULL;
1653
1654        /* take the lock to protect driver data */
1655    AR6000_SPIN_LOCK(&ar->arLock, 0);
1656
1657    do {
1658
1659        if (checkAdHocPsMapping) {
1660            streamID = ar6000_ibss_map_epid(skb, dev, &mapNo);
1661        }
1662
1663        A_ASSERT(streamID != WMI_NOT_MAPPED);
1664
1665            /* validate that the endpoint is connected */
1666        if (arWMIStream2EndpointID(ar,streamID) == 0) {
1667            AR_DEBUG_PRINTF("Stream %d is NOT mapped!\n",streamID);
1668            break;
1669        }
1670            /* allocate resource for this packet */
1671        cookie = ar6000_alloc_cookie(ar);
1672
1673        if (cookie != NULL) {
1674                /* update counts while the lock is held */
1675            ar->arTxPending[streamID]++;
1676            ar->arTotalTxDataPending++;
1677        }
1678
1679    } while (FALSE);
1680
1681    AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1682
1683    if (cookie != NULL) {
1684        cookie->arc_bp[0] = (A_UINT32)skb;
1685        cookie->arc_bp[1] = mapNo;
1686        SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt,
1687                               cookie,
1688                               A_NETBUF_DATA(skb),
1689                               A_NETBUF_LEN(skb),
1690                               arWMIStream2EndpointID(ar,streamID),
1691                               AR6K_DATA_PKT_TAG);
1692
1693#ifdef DEBUG
1694        if (debugdriver >= 3) {
1695            ar6000_dump_skb(skb);
1696        }
1697#endif
1698            /* HTC interface is asynchronous, if this fails, cleanup will happen in
1699             * the ar6000_tx_complete callback */
1700        HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt);
1701    } else {
1702            /* no packet to send, cleanup */
1703        A_NETBUF_FREE(skb);
1704        AR6000_STAT_INC(ar, tx_dropped);
1705        AR6000_STAT_INC(ar, tx_aborted_errors);
1706    }
1707
1708    return 0;
1709}
1710
1711#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
1712static void
1713tvsub(register struct timeval *out, register struct timeval *in)
1714{
1715    if((out->tv_usec -= in->tv_usec) < 0) {
1716        out->tv_sec--;
1717        out->tv_usec += 1000000;
1718    }
1719    out->tv_sec -= in->tv_sec;
1720}
1721
1722void
1723applyAPTCHeuristics(AR_SOFTC_T *ar)
1724{
1725    A_UINT32 duration;
1726    A_UINT32 numbytes;
1727    A_UINT32 throughput;
1728    struct timeval ts;
1729    A_STATUS status;
1730
1731    AR6000_SPIN_LOCK(&ar->arLock, 0);
1732
1733    if ((enableAPTCHeuristics) && (!aptcTR.timerScheduled)) {
1734        do_gettimeofday(&ts);
1735        tvsub(&ts, &aptcTR.samplingTS);
1736        duration = ts.tv_sec * 1000 + ts.tv_usec / 1000; /* ms */
1737        numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived;
1738
1739        if (duration > APTC_TRAFFIC_SAMPLING_INTERVAL) {
1740            /* Initialize the time stamp and byte count */
1741            aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0;
1742            do_gettimeofday(&aptcTR.samplingTS);
1743
1744            /* Calculate and decide based on throughput thresholds */
1745            throughput = ((numbytes * 8) / duration);
1746            if (throughput > APTC_UPPER_THROUGHPUT_THRESHOLD) {
1747                /* Disable Sleep and schedule a timer */
1748                A_ASSERT(ar->arWmiReady == TRUE);
1749                AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1750                status = wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER);
1751                AR6000_SPIN_LOCK(&ar->arLock, 0);
1752                A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0);
1753                aptcTR.timerScheduled = TRUE;
1754            }
1755        }
1756    }
1757
1758    AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1759}
1760#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
1761
1762static void
1763ar6000_tx_queue_full(void *Context, HTC_ENDPOINT_ID Endpoint)
1764{
1765    AR_SOFTC_T *ar = (AR_SOFTC_T *) Context;
1766
1767    if (Endpoint == arWMIStream2EndpointID(ar,WMI_CONTROL_PRI)) {
1768        if (!bypasswmi) {
1769                /* under normal WMI if this is getting full, then something is running rampant
1770                 * the host should not be exhausting the WMI queue with too many commands
1771                 * the only exception to this is during testing using endpointping */
1772
1773            AR6000_SPIN_LOCK(&ar->arLock, 0);
1774                /* set flag to handle subsequent messages */
1775            ar->arWMIControlEpFull = TRUE;
1776            AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1777            AR_DEBUG_PRINTF("WMI Control Endpoint is FULL!!! \n");
1778        }
1779    } else {
1780        /* one of the data endpoints queues is getting full..need to stop network stack
1781         * the queue will resume after credits received */
1782        netif_stop_queue(ar->arNetDev);
1783    }
1784}
1785
1786static void
1787ar6000_tx_queue_avail(void *Context, HTC_ENDPOINT_ID Endpoint)
1788{
1789    AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
1790
1791    if (Endpoint == arWMIStream2EndpointID(ar,WMI_CONTROL_PRI)) {
1792        /* FIXME: what do for it? */
1793    } else {
1794        /* Wake up interface, rescheduling prevented. */
1795        if (ar->arConnected == TRUE || bypasswmi)
1796            netif_wake_queue(ar->arNetDev);
1797    }
1798}
1799
1800static void
1801ar6000_tx_complete(void *Context, HTC_PACKET *pPacket)
1802{
1803    AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
1804    void *cookie = (void *)pPacket->pPktContext;
1805    struct sk_buff *skb = NULL;
1806    A_UINT32 mapNo = 0;
1807    A_STATUS status;
1808    struct ar_cookie * ar_cookie;
1809    WMI_PRI_STREAM_ID streamID;
1810    A_BOOL wakeEvent = FALSE;
1811
1812    status = pPacket->Status;
1813    ar_cookie = (struct ar_cookie *)cookie;
1814    skb = (struct sk_buff *)ar_cookie->arc_bp[0];
1815    streamID = arEndpoint2WMIStreamID(ar,pPacket->Endpoint);
1816    mapNo = ar_cookie->arc_bp[1];
1817
1818    A_ASSERT(skb);
1819    A_ASSERT(pPacket->pBuffer == A_NETBUF_DATA(skb));
1820
1821    if (A_SUCCESS(status)) {
1822        A_ASSERT(pPacket->ActualLength == A_NETBUF_LEN(skb));
1823    }
1824
1825    AR_DEBUG2_PRINTF("ar6000_tx_complete skb=0x%x data=0x%x len=0x%x sid=%d ",
1826                     (A_UINT32)skb, (A_UINT32)pPacket->pBuffer,
1827                     pPacket->ActualLength,
1828                     streamID);
1829
1830        /* lock the driver as we update internal state */
1831    AR6000_SPIN_LOCK(&ar->arLock, 0);
1832
1833    ar->arTxPending[streamID]--;
1834
1835    if ((streamID != WMI_CONTROL_PRI) || bypasswmi) {
1836        ar->arTotalTxDataPending--;
1837    }
1838
1839    if (streamID == WMI_CONTROL_PRI)
1840    {
1841        if (ar->arWMIControlEpFull) {
1842                /* since this packet completed, the WMI EP is no longer full */
1843            ar->arWMIControlEpFull = FALSE;
1844        }
1845
1846        if (ar->arTxPending[streamID] == 0) {
1847            wakeEvent = TRUE;
1848        }
1849    }
1850
1851    if (A_FAILED(status)) {
1852        AR_DEBUG_PRINTF("%s() -TX ERROR, status: 0x%x\n", __func__,
1853                        status);
1854        AR6000_STAT_INC(ar, tx_errors);
1855    } else {
1856        AR_DEBUG2_PRINTF("OK\n");
1857        AR6000_STAT_INC(ar, tx_packets);
1858        ar->arNetStats.tx_bytes += A_NETBUF_LEN(skb);
1859#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
1860        aptcTR.bytesTransmitted += a_netbuf_to_len(skb);
1861        applyAPTCHeuristics(ar);
1862#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
1863    }
1864
1865    // TODO this needs to be looked at
1866    if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable
1867        && (streamID != WMI_CONTROL_PRI) && mapNo)
1868    {
1869        mapNo --;
1870        ar->arNodeMap[mapNo].txPending --;
1871
1872        if (!ar->arNodeMap[mapNo].txPending && (mapNo == (ar->arNodeNum - 1))) {
1873            A_UINT32 i;
1874            for (i = ar->arNodeNum; i > 0; i --) {
1875                if (!ar->arNodeMap[i - 1].txPending) {
1876                    A_MEMZERO(&ar->arNodeMap[i - 1], sizeof(struct ar_node_mapping));
1877                    ar->arNodeNum --;
1878                } else {
1879                    break;
1880                }
1881            }
1882        }
1883    }
1884
1885    /* Freeing a cookie should not be contingent on either of */
1886    /* these flags, just if we have a cookie or not. */
1887    /* Can we even get here without a cookie? Fix later. */
1888    if (ar->arWmiReady == TRUE || (bypasswmi))
1889    {
1890        ar6000_free_cookie(ar, cookie);
1891    }
1892
1893    AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1894
1895    /* lock is released, we can freely call other kernel APIs */
1896
1897        /* this indirectly frees the HTC_PACKET */
1898    A_NETBUF_FREE(skb);
1899
1900    if (wakeEvent) {
1901        wake_up(&arEvent);
1902    }
1903}
1904
1905/*
1906 * Receive event handler. This is called by HTC when a packet is received
1907 */
1908int pktcount;
1909static void
1910ar6000_rx(void *Context, HTC_PACKET *pPacket)
1911{
1912    AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
1913    struct sk_buff *skb = (struct sk_buff *)pPacket->pPktContext;
1914    int minHdrLen;
1915    A_STATUS status = pPacket->Status;
1916    WMI_PRI_STREAM_ID streamID = arEndpoint2WMIStreamID(ar,pPacket->Endpoint);
1917    HTC_ENDPOINT_ID ept = pPacket->Endpoint;
1918
1919    A_ASSERT((status != A_OK) || (pPacket->pBuffer == (A_NETBUF_DATA(skb) + HTC_HEADER_LEN)));
1920
1921    AR_DEBUG2_PRINTF("ar6000_rx ar=0x%x sid=%d, skb=0x%x, data=0x%x, len=0x%x ",
1922                    (A_UINT32)ar, streamID, (A_UINT32)skb, (A_UINT32)pPacket->pBuffer,
1923                    pPacket->ActualLength);
1924    if (status != A_OK) {
1925        AR_DEBUG2_PRINTF("ERR\n");
1926    } else {
1927        AR_DEBUG2_PRINTF("OK\n");
1928    }
1929
1930        /* take lock to protect buffer counts
1931         * and adaptive power throughput state */
1932    AR6000_SPIN_LOCK(&ar->arLock, 0);
1933
1934    ar->arRxBuffers[streamID]--;
1935
1936    if (A_SUCCESS(status)) {
1937        AR6000_STAT_INC(ar, rx_packets);
1938        ar->arNetStats.rx_bytes += pPacket->ActualLength;
1939#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
1940        aptcTR.bytesReceived += a_netbuf_to_len(skb);
1941        applyAPTCHeuristics(ar);
1942#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
1943
1944        A_NETBUF_PUT(skb, pPacket->ActualLength + HTC_HEADER_LEN);
1945        A_NETBUF_PULL(skb, HTC_HEADER_LEN);
1946
1947#ifdef DEBUG
1948        if (debugdriver >= 2) {
1949            ar6000_dump_skb(skb);
1950        }
1951#endif /* DEBUG */
1952    }
1953
1954    AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1955
1956    if (status != A_OK) {
1957        AR6000_STAT_INC(ar, rx_errors);
1958        A_NETBUF_FREE(skb);
1959    } else if (ar->arWmiEnabled == TRUE) {
1960        if (streamID == WMI_CONTROL_PRI) {
1961           /*
1962            * this is a wmi control msg
1963            */
1964            wmi_control_rx(ar->arWmi, skb);
1965        } else {
1966            WMI_DATA_HDR *dhdr = (WMI_DATA_HDR *)A_NETBUF_DATA(skb);
1967            if (WMI_DATA_HDR_IS_MSG_TYPE(dhdr, CNTL_MSGTYPE)) {
1968                /*
1969                 * this is a wmi control msg
1970                 */
1971                /* strip off WMI hdr */
1972                wmi_data_hdr_remove(ar->arWmi, skb);
1973                wmi_control_rx(ar->arWmi, skb);
1974            } else {
1975                /*
1976                 * this is a wmi data packet
1977                 */
1978                minHdrLen = sizeof (WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) +
1979                            sizeof(ATH_LLC_SNAP_HDR);
1980
1981                if ((pPacket->ActualLength < minHdrLen) ||
1982                    (pPacket->ActualLength > AR6000_BUFFER_SIZE))
1983                {
1984                    /*
1985                     * packet is too short or too long
1986                     */
1987                    AR_DEBUG_PRINTF("TOO SHORT or TOO LONG\n");
1988                    AR6000_STAT_INC(ar, rx_errors);
1989                    AR6000_STAT_INC(ar, rx_length_errors);
1990                    A_NETBUF_FREE(skb);
1991                } else {
1992                    if (ar->arWmmEnabled) {
1993                        wmi_implicit_create_pstream(ar->arWmi, skb,
1994                            DNLINK_TRAFFIC, UNDEFINED_PRI);
1995                    }
1996#if 0
1997                    /* Access RSSI values here */
1998                    AR_DEBUG_PRINTF("RSSI %d\n",
1999                        ((WMI_DATA_HDR *) A_NETBUF_DATA(skb))->rssi);
2000#endif
2001                    wmi_data_hdr_remove(ar->arWmi, skb);
2002                    wmi_dot3_2_dix(ar->arWmi, skb);
2003
2004#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
2005                    /*
2006                     * extra push and memcpy, for eth_type_trans() of 2.4 kernel
2007                     * will pull out hard_header_len bytes of the skb.
2008                     */
2009                    A_NETBUF_PUSH(skb, sizeof(WMI_DATA_HDR) + sizeof(ATH_LLC_SNAP_HDR) + HTC_HEADER_LEN);
2010                    A_MEMCPY(A_NETBUF_DATA(skb), A_NETBUF_DATA(skb) + sizeof(WMI_DATA_HDR) +
2011                             sizeof(ATH_LLC_SNAP_HDR) + HTC_HEADER_LEN, sizeof(ATH_MAC_HDR));
2012#endif
2013                    if ((ar->arNetDev->flags & IFF_UP) == IFF_UP)
2014                    {
2015                        skb->dev = ar->arNetDev;
2016                        skb->protocol = eth_type_trans(skb, ar->arNetDev);
2017                        netif_rx(skb);
2018                    }
2019                    else
2020                    {
2021                        A_NETBUF_FREE(skb);
2022                    }
2023                }
2024            }
2025        }
2026    } else {
2027        if ((ar->arNetDev->flags & IFF_UP) == IFF_UP)
2028        {
2029            skb->dev = ar->arNetDev;
2030            skb->protocol = eth_type_trans(skb, ar->arNetDev);
2031            netif_rx(skb);
2032        }
2033        else
2034        {
2035            A_NETBUF_FREE(skb);
2036        }
2037    }
2038
2039    if (status != A_ECANCELED) {
2040        /*
2041         * HTC provides A_ECANCELED status when it doesn't want to be refilled
2042         * (probably due to a shutdown)
2043         */
2044        ar6000_rx_refill(Context, ept);
2045    }
2046
2047
2048}
2049
2050static void
2051ar6000_rx_refill(void *Context, HTC_ENDPOINT_ID Endpoint)
2052{
2053    AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
2054    void *osBuf;
2055    int RxBuffers;
2056    int buffersToRefill;
2057    HTC_PACKET *pPacket;
2058    WMI_PRI_STREAM_ID streamId = arEndpoint2WMIStreamID(ar,Endpoint);
2059
2060    buffersToRefill = (int)AR6000_MAX_RX_BUFFERS -
2061                                    (int)ar->arRxBuffers[streamId];
2062
2063    if (buffersToRefill <= 0) {
2064            /* fast return, nothing to fill */
2065        return;
2066    }
2067
2068    AR_DEBUG2_PRINTF("ar6000_rx_refill: providing htc with %d buffers at eid=%d\n",
2069                    buffersToRefill, Endpoint);
2070
2071    for (RxBuffers = 0; RxBuffers < buffersToRefill; RxBuffers++) {
2072        osBuf = A_NETBUF_ALLOC(AR6000_BUFFER_SIZE);
2073        if (NULL == osBuf) {
2074            break;
2075        }
2076            /* the HTC packet wrapper is at the head of the reserved area
2077             * in the skb */
2078        pPacket = (HTC_PACKET *)(A_NETBUF_HEAD(osBuf));
2079            /* set re-fill info */
2080        SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_BUFFER_SIZE,Endpoint);
2081            /* add this packet */
2082        HTCAddReceivePkt(ar->arHtcTarget, pPacket);
2083    }
2084
2085        /* update count */
2086    AR6000_SPIN_LOCK(&ar->arLock, 0);
2087    ar->arRxBuffers[streamId] += RxBuffers;
2088    AR6000_SPIN_UNLOCK(&ar->arLock, 0);
2089}
2090
2091static struct net_device_stats *
2092ar6000_get_stats(struct net_device *dev)
2093{
2094    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
2095    return &ar->arNetStats;
2096}
2097
2098static struct iw_statistics *
2099ar6000_get_iwstats(struct net_device * dev)
2100{
2101    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
2102    TARGET_STATS *pStats = &ar->arTargetStats;
2103    struct iw_statistics * pIwStats = &ar->arIwStats;
2104
2105    if ((ar->arWmiReady == FALSE)
2106    /*
2107     * The in_atomic function is used to determine if the scheduling is
2108     * allowed in the current context or not. This was introduced in 2.6
2109     * From what I have read on the differences between 2.4 and 2.6, the
2110     * 2.4 kernel did not support preemption and so this check might not
2111     * be required for 2.4 kernels.
2112     */
2113#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
2114        || (in_atomic())
2115#endif
2116       )
2117    {
2118        pIwStats->status = 0;
2119        pIwStats->qual.qual = 0;
2120        pIwStats->qual.level =0;
2121        pIwStats->qual.noise = 0;
2122        pIwStats->discard.code =0;
2123        pIwStats->discard.retries=0;
2124        pIwStats->miss.beacon =0;
2125        return pIwStats;
2126    }
2127    if (down_interruptible(&ar->arSem)) {
2128        pIwStats->status = 0;
2129        return pIwStats;
2130    }
2131
2132
2133    ar->statsUpdatePending = TRUE;
2134
2135    if(wmi_get_stats_cmd(ar->arWmi) != A_OK) {
2136        up(&ar->arSem);
2137        pIwStats->status = 0;
2138        return pIwStats;
2139    }
2140
2141    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
2142
2143    if (signal_pending(current)) {
2144        AR_DEBUG_PRINTF("ar6000 : WMI get stats timeout \n");
2145        up(&ar->arSem);
2146        pIwStats->status = 0;
2147        return pIwStats;
2148    }
2149    pIwStats->status = 1 ;
2150    pIwStats->qual.qual = pStats->cs_aveBeacon_rssi;
2151    pIwStats->qual.level =pStats->cs_aveBeacon_rssi + 161; /* noise is -95 dBm */
2152    pIwStats->qual.noise = pStats->noise_floor_calibation;
2153    pIwStats->discard.code = pStats->rx_decrypt_err;
2154    pIwStats->discard.retries = pStats->tx_retry_cnt;
2155    pIwStats->miss.beacon = pStats->cs_bmiss_cnt;
2156    up(&ar->arSem);
2157    return pIwStats;
2158}
2159
2160void
2161ar6000_ready_event(void *devt, A_UINT8 *datap, A_UINT8 phyCap)
2162{
2163    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
2164    struct net_device *dev = ar->arNetDev;
2165
2166    ar->arWmiReady = TRUE;
2167    wake_up(&arEvent);
2168    A_MEMCPY(dev->dev_addr, datap, AR6000_ETH_ADDR_LEN);
2169    AR_DEBUG_PRINTF("mac address = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
2170        dev->dev_addr[0], dev->dev_addr[1],
2171        dev->dev_addr[2], dev->dev_addr[3],
2172        dev->dev_addr[4], dev->dev_addr[5]);
2173
2174    ar->arPhyCapability = phyCap;
2175}
2176
2177A_UINT8
2178ar6000_iptos_to_userPriority(A_UINT8 *pkt)
2179{
2180    struct iphdr *ipHdr = (struct iphdr *)pkt;
2181    A_UINT8 userPriority;
2182
2183    /*
2184     * IP Tos format :
2185     * (Refer Pg 57 WMM-test-plan-v1.2)
2186     * IP-TOS - 8bits
2187     * : DSCP(6-bits) ECN(2-bits)
2188     * : DSCP - P2 P1 P0 X X X
2189     * where (P2 P1 P0) form 802.1D
2190     */
2191    userPriority = ipHdr->tos >> 5;
2192    return (userPriority & 0x7);
2193}
2194
2195void
2196ar6000_connect_event(AR_SOFTC_T *ar, A_UINT16 channel, A_UINT8 *bssid,
2197                     A_UINT16 listenInterval, A_UINT16 beaconInterval,
2198                     NETWORK_TYPE networkType, A_UINT8 beaconIeLen,
2199                     A_UINT8 assocReqLen, A_UINT8 assocRespLen,
2200                     A_UINT8 *assocInfo)
2201{
2202    union iwreq_data wrqu;
2203    int i, beacon_ie_pos, assoc_resp_ie_pos, assoc_req_ie_pos;
2204    static const char *tag1 = "ASSOCINFO(ReqIEs=";
2205    static const char *tag2 = "ASSOCRESPIE=";
2206    static const char *beaconIetag = "BEACONIE=";
2207    char buf[WMI_CONTROL_MSG_MAX_LEN * 2 + sizeof(tag1)];
2208    char *pos;
2209    A_UINT8 key_op_ctrl;
2210
2211    A_MEMCPY(ar->arBssid, bssid, sizeof(ar->arBssid));
2212    ar->arBssChannel = channel;
2213
2214    A_PRINTF("AR6000 connected event on freq %d ", channel);
2215    A_PRINTF("with bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
2216            " listenInterval=%d, beaconInterval = %d, beaconIeLen = %d assocReqLen=%d"
2217            " assocRespLen =%d\n",
2218             bssid[0], bssid[1], bssid[2],
2219             bssid[3], bssid[4], bssid[5],
2220             listenInterval, beaconInterval,
2221             beaconIeLen, assocReqLen, assocRespLen);
2222    if (networkType & ADHOC_NETWORK) {
2223        if (networkType & ADHOC_CREATOR) {
2224            A_PRINTF("Network: Adhoc (Creator)\n");
2225        } else {
2226            A_PRINTF("Network: Adhoc (Joiner)\n");
2227        }
2228    } else {
2229        A_PRINTF("Network: Infrastructure\n");
2230    }
2231
2232    if (beaconIeLen && (sizeof(buf) > (9 + beaconIeLen * 2))) {
2233        AR_DEBUG_PRINTF("\nBeaconIEs= ");
2234
2235        beacon_ie_pos = 0;
2236        A_MEMZERO(buf, sizeof(buf));
2237        sprintf(buf, "%s", beaconIetag);
2238        pos = buf + 9;
2239        for (i = beacon_ie_pos; i < beacon_ie_pos + beaconIeLen; i++) {
2240            AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]);
2241            sprintf(pos, "%2.2x", assocInfo[i]);
2242            pos += 2;
2243        }
2244        AR_DEBUG_PRINTF("\n");
2245
2246        A_MEMZERO(&wrqu, sizeof(wrqu));
2247        wrqu.data.length = strlen(buf);
2248        wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
2249    }
2250
2251    if (assocRespLen && (sizeof(buf) > (12 + (assocRespLen * 2))))
2252    {
2253        assoc_resp_ie_pos = beaconIeLen + assocReqLen +
2254                            sizeof(A_UINT16) + /* capinfo*/
2255                            sizeof(A_UINT16) + /* status Code */
2256                            sizeof(A_UINT16) ; /* associd */
2257        A_MEMZERO(buf, sizeof(buf));
2258        sprintf(buf, "%s", tag2);
2259        pos = buf + 12;
2260        AR_DEBUG_PRINTF("\nAssocRespIEs= ");
2261        /*
2262         * The Association Response Frame w.o. the WLAN header is delivered to
2263         * the host, so skip over to the IEs
2264         */
2265        for (i = assoc_resp_ie_pos; i < assoc_resp_ie_pos + assocRespLen - 6; i++)
2266        {
2267            AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]);
2268            sprintf(pos, "%2.2x", assocInfo[i]);
2269            pos += 2;
2270        }
2271        AR_DEBUG_PRINTF("\n");
2272
2273        A_MEMZERO(&wrqu, sizeof(wrqu));
2274        wrqu.data.length = strlen(buf);
2275        wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
2276    }
2277
2278    if (assocReqLen && (sizeof(buf) > (17 + (assocReqLen * 2)))) {
2279        /*
2280         * assoc Request includes capability and listen interval. Skip these.
2281         */
2282        assoc_req_ie_pos = beaconIeLen +
2283                            sizeof(A_UINT16) + /* capinfo*/
2284                            sizeof(A_UINT16); /* listen interval */
2285
2286        A_MEMZERO(buf, sizeof(buf));
2287        sprintf(buf, "%s", tag1);
2288        pos = buf + 17;
2289        AR_DEBUG_PRINTF("AssocReqIEs= ");
2290        for (i = assoc_req_ie_pos; i < assoc_req_ie_pos + assocReqLen - 4; i++) {
2291            AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]);
2292            sprintf(pos, "%2.2x", assocInfo[i]);
2293            pos += 2;;
2294        }
2295        AR_DEBUG_PRINTF("\n");
2296
2297        A_MEMZERO(&wrqu, sizeof(wrqu));
2298        wrqu.data.length = strlen(buf);
2299        wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
2300    }
2301
2302#ifdef USER_KEYS
2303    if (ar->user_savedkeys_stat == USER_SAVEDKEYS_STAT_RUN &&
2304        ar->user_saved_keys.keyOk == TRUE)
2305    {
2306
2307        key_op_ctrl = KEY_OP_VALID_MASK & ~KEY_OP_INIT_TSC;
2308        if (ar->user_key_ctrl & AR6000_USER_SETKEYS_RSC_UNCHANGED) {
2309            key_op_ctrl &= ~KEY_OP_INIT_RSC;
2310        } else {
2311            key_op_ctrl |= KEY_OP_INIT_RSC;
2312        }
2313        ar6000_reinstall_keys(ar, key_op_ctrl);
2314    }
2315#endif /* USER_KEYS */
2316
2317        /* flush data queues */
2318    ar6000_TxDataCleanup(ar);
2319
2320    netif_start_queue(ar->arNetDev);
2321
2322    if ((OPEN_AUTH == ar->arDot11AuthMode) &&
2323        (NONE_AUTH == ar->arAuthMode) &&
2324        (WEP_CRYPT == ar->arPairwiseCrypto))
2325    {
2326        if (!ar->arConnected) {
2327            ar6000_install_static_wep_keys(ar);
2328        }
2329    }
2330
2331    ar->arConnected = TRUE;
2332    ar->arConnectPending = FALSE;
2333
2334    reconnect_flag = 0;
2335
2336    A_MEMZERO(&wrqu, sizeof(wrqu));
2337    A_MEMCPY(wrqu.addr.sa_data, bssid, IEEE80211_ADDR_LEN);
2338    wrqu.addr.sa_family = ARPHRD_ETHER;
2339    wireless_send_event(ar->arNetDev, SIOCGIWAP, &wrqu, NULL);
2340    if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable) {
2341        A_MEMZERO(ar->arNodeMap, sizeof(ar->arNodeMap));
2342        ar->arNodeNum = 0;
2343        ar->arNexEpId = ENDPOINT_2;
2344    }
2345
2346}
2347
2348void ar6000_set_numdataendpts(AR_SOFTC_T *ar, A_UINT32 num)
2349{
2350    A_ASSERT(num <= (HTC_MAILBOX_NUM_MAX - 1));
2351    ar->arNumDataEndPts = num;
2352}
2353
2354void
2355ar6000_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason, A_UINT8 *bssid,
2356                        A_UINT8 assocRespLen, A_UINT8 *assocInfo, A_UINT16 protocolReasonStatus)
2357{
2358    A_UINT8 i;
2359
2360    A_PRINTF("AR6000 disconnected");
2361    if (bssid[0] || bssid[1] || bssid[2] || bssid[3] || bssid[4] || bssid[5]) {
2362        A_PRINTF(" from %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",
2363                 bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
2364    }
2365    A_PRINTF("\n");
2366
2367    AR_DEBUG_PRINTF("\nDisconnect Reason is %d", reason);
2368    AR_DEBUG_PRINTF("\nProtocol Reason/Status Code is %d", protocolReasonStatus);
2369    AR_DEBUG_PRINTF("\nAssocResp Frame = %s",
2370                    assocRespLen ? " " : "NULL");
2371    for (i = 0; i < assocRespLen; i++) {
2372        if (!(i % 0x10)) {
2373            AR_DEBUG_PRINTF("\n");
2374        }
2375        AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]);
2376    }
2377    AR_DEBUG_PRINTF("\n");
2378    /*
2379     * If the event is due to disconnect cmd from the host, only they the target
2380     * would stop trying to connect. Under any other condition, target would
2381     * keep trying to connect.
2382     *
2383     */
2384    if( reason == DISCONNECT_CMD)
2385    {
2386        ar->arConnectPending = FALSE;
2387    } else {
2388        ar->arConnectPending = TRUE;
2389        if (((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x11)) ||
2390            ((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x0) && (reconnect_flag == 1))) {
2391            ar->arConnected = TRUE;
2392            return;
2393        }
2394    }
2395    ar->arConnected = FALSE;
2396
2397    if( (reason != CSERV_DISCONNECT) || (reconnect_flag != 1) ) {
2398        reconnect_flag = 0;
2399    }
2400
2401#ifdef USER_KEYS
2402    if (reason != CSERV_DISCONNECT)
2403    {
2404        ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
2405        ar->user_key_ctrl = 0;
2406    }
2407#endif /* USER_KEYS */
2408
2409    netif_stop_queue(ar->arNetDev);
2410    A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
2411    ar->arBssChannel = 0;
2412    ar->arBeaconInterval = 0;
2413
2414    ar6000_TxDataCleanup(ar);
2415}
2416
2417void
2418ar6000_regDomain_event(AR_SOFTC_T *ar, A_UINT32 regCode)
2419{
2420    A_PRINTF("AR6000 Reg Code = 0x%x\n", regCode);
2421    ar->arRegCode = regCode;
2422}
2423
2424void
2425ar6000_neighborReport_event(AR_SOFTC_T *ar, int numAps, WMI_NEIGHBOR_INFO *info)
2426{
2427    static const char *tag = "PRE-AUTH";
2428    char buf[128];
2429    union iwreq_data wrqu;
2430    int i;
2431
2432    AR_DEBUG_PRINTF("AR6000 Neighbor Report Event\n");
2433    for (i=0; i < numAps; info++, i++) {
2434        AR_DEBUG_PRINTF("bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",
2435            info->bssid[0], info->bssid[1], info->bssid[2],
2436            info->bssid[3], info->bssid[4], info->bssid[5]);
2437        if (info->bssFlags & WMI_PREAUTH_CAPABLE_BSS) {
2438            AR_DEBUG_PRINTF("preauth-cap");
2439        }
2440        if (info->bssFlags & WMI_PMKID_VALID_BSS) {
2441            AR_DEBUG_PRINTF(" pmkid-valid\n");
2442            continue; /* we skip bss if the pmkid is already valid */
2443        }
2444        AR_DEBUG_PRINTF("\n");
2445        snprintf(buf, sizeof(buf), "%s%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
2446                 tag,
2447                 info->bssid[0], info->bssid[1], info->bssid[2],
2448                 info->bssid[3], info->bssid[4], info->bssid[5],
2449                 i, info->bssFlags);
2450        A_MEMZERO(&wrqu, sizeof(wrqu));
2451        wrqu.data.length = strlen(buf);
2452        wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
2453    }
2454}
2455
2456void
2457ar6000_tkip_micerr_event(AR_SOFTC_T *ar, A_UINT8 keyid, A_BOOL ismcast)
2458{
2459    static const char *tag = "MLME-MICHAELMICFAILURE.indication";
2460    char buf[128];
2461    union iwreq_data wrqu;
2462
2463    A_PRINTF("AR6000 TKIP MIC error received for keyid %d %scast\n",
2464             keyid, ismcast ? "multi": "uni");
2465    snprintf(buf, sizeof(buf), "%s(keyid=%d %scat)", tag, keyid,
2466             ismcast ? "multi" : "uni");
2467    memset(&wrqu, 0, sizeof(wrqu));
2468    wrqu.data.length = strlen(buf);
2469    wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
2470}
2471
2472void
2473ar6000_scanComplete_event(AR_SOFTC_T *ar, A_STATUS status)
2474{
2475    AR_DEBUG_PRINTF("AR6000 scan complete: %d\n", status);
2476
2477    ar->scan_complete = 1;
2478    wake_up_interruptible(&ar6000_scan_queue);
2479}
2480
2481void
2482ar6000_targetStats_event(AR_SOFTC_T *ar, WMI_TARGET_STATS *pTarget)
2483{
2484    TARGET_STATS *pStats = &ar->arTargetStats;
2485    A_UINT8 ac;
2486
2487    /*A_PRINTF("AR6000 updating target stats\n");*/
2488    pStats->tx_packets += pTarget->txrxStats.tx_stats.tx_packets;
2489    pStats->tx_bytes += pTarget->txrxStats.tx_stats.tx_bytes;
2490    pStats->tx_unicast_pkts += pTarget->txrxStats.tx_stats.tx_unicast_pkts;
2491    pStats->tx_unicast_bytes += pTarget->txrxStats.tx_stats.tx_unicast_bytes;
2492    pStats->tx_multicast_pkts += pTarget->txrxStats.tx_stats.tx_multicast_pkts;
2493    pStats->tx_multicast_bytes += pTarget->txrxStats.tx_stats.tx_multicast_bytes;
2494    pStats->tx_broadcast_pkts += pTarget->txrxStats.tx_stats.tx_broadcast_pkts;
2495    pStats->tx_broadcast_bytes += pTarget->txrxStats.tx_stats.tx_broadcast_bytes;
2496    pStats->tx_rts_success_cnt += pTarget->txrxStats.tx_stats.tx_rts_success_cnt;
2497    for(ac = 0; ac < WMM_NUM_AC; ac++)
2498        pStats->tx_packet_per_ac[ac] += pTarget->txrxStats.tx_stats.tx_packet_per_ac[ac];
2499    pStats->tx_errors += pTarget->txrxStats.tx_stats.tx_errors;
2500    pStats->tx_failed_cnt += pTarget->txrxStats.tx_stats.tx_failed_cnt;
2501    pStats->tx_retry_cnt += pTarget->txrxStats.tx_stats.tx_retry_cnt;
2502    pStats->tx_rts_fail_cnt += pTarget->txrxStats.tx_stats.tx_rts_fail_cnt;
2503    pStats->tx_unicast_rate = wmi_get_rate(pTarget->txrxStats.tx_stats.tx_unicast_rate);
2504
2505    pStats->rx_packets += pTarget->txrxStats.rx_stats.rx_packets;
2506    pStats->rx_bytes += pTarget->txrxStats.rx_stats.rx_bytes;
2507    pStats->rx_unicast_pkts += pTarget->txrxStats.rx_stats.rx_unicast_pkts;
2508    pStats->rx_unicast_bytes += pTarget->txrxStats.rx_stats.rx_unicast_bytes;
2509    pStats->rx_multicast_pkts += pTarget->txrxStats.rx_stats.rx_multicast_pkts;
2510    pStats->rx_multicast_bytes += pTarget->txrxStats.rx_stats.rx_multicast_bytes;
2511    pStats->rx_broadcast_pkts += pTarget->txrxStats.rx_stats.rx_broadcast_pkts;
2512    pStats->rx_broadcast_bytes += pTarget->txrxStats.rx_stats.rx_broadcast_bytes;
2513    pStats->rx_fragment_pkt += pTarget->txrxStats.rx_stats.rx_fragment_pkt;
2514    pStats->rx_errors += pTarget->txrxStats.rx_stats.rx_errors;
2515    pStats->rx_crcerr += pTarget->txrxStats.rx_stats.rx_crcerr;
2516    pStats->rx_key_cache_miss += pTarget->txrxStats.rx_stats.rx_key_cache_miss;
2517    pStats->rx_decrypt_err += pTarget->txrxStats.rx_stats.rx_decrypt_err;
2518    pStats->rx_duplicate_frames += pTarget->txrxStats.rx_stats.rx_duplicate_frames;
2519    pStats->rx_unicast_rate = wmi_get_rate(pTarget->txrxStats.rx_stats.rx_unicast_rate);
2520
2521
2522    pStats->tkip_local_mic_failure
2523                                += pTarget->txrxStats.tkipCcmpStats.tkip_local_mic_failure;
2524    pStats->tkip_counter_measures_invoked
2525                                += pTarget->txrxStats.tkipCcmpStats.tkip_counter_measures_invoked;
2526    pStats->tkip_replays += pTarget->txrxStats.tkipCcmpStats.tkip_replays;
2527    pStats->tkip_format_errors += pTarget->txrxStats.tkipCcmpStats.tkip_format_errors;
2528    pStats->ccmp_format_errors += pTarget->txrxStats.tkipCcmpStats.ccmp_format_errors;
2529    pStats->ccmp_replays += pTarget->txrxStats.tkipCcmpStats.ccmp_replays;
2530
2531
2532    pStats->power_save_failure_cnt += pTarget->pmStats.power_save_failure_cnt;
2533    pStats->noise_floor_calibation = pTarget->noise_floor_calibation;
2534
2535    pStats->cs_bmiss_cnt += pTarget->cservStats.cs_bmiss_cnt;
2536    pStats->cs_lowRssi_cnt += pTarget->cservStats.cs_lowRssi_cnt;
2537    pStats->cs_connect_cnt += pTarget->cservStats.cs_connect_cnt;
2538    pStats->cs_disconnect_cnt += pTarget->cservStats.cs_disconnect_cnt;
2539    pStats->cs_aveBeacon_snr = pTarget->cservStats.cs_aveBeacon_snr;
2540    pStats->cs_aveBeacon_rssi = pTarget->cservStats.cs_aveBeacon_rssi;
2541    pStats->cs_lastRoam_msec = pTarget->cservStats.cs_lastRoam_msec;
2542    pStats->cs_snr = pTarget->cservStats.cs_snr;
2543    pStats->cs_rssi = pTarget->cservStats.cs_rssi;
2544
2545    pStats->lq_val = pTarget->lqVal;
2546
2547    pStats->wow_num_pkts_dropped += pTarget->wowStats.wow_num_pkts_dropped;
2548    pStats->wow_num_host_pkt_wakeups += pTarget->wowStats.wow_num_host_pkt_wakeups;
2549    pStats->wow_num_host_event_wakeups += pTarget->wowStats.wow_num_host_event_wakeups;
2550    pStats->wow_num_events_discarded += pTarget->wowStats.wow_num_events_discarded;
2551
2552    ar->statsUpdatePending = FALSE;
2553    wake_up(&arEvent);
2554}
2555
2556void
2557ar6000_rssiThreshold_event(AR_SOFTC_T *ar, WMI_RSSI_THRESHOLD_VAL newThreshold, A_INT16 rssi)
2558{
2559    USER_RSSI_THOLD userRssiThold;
2560
2561    userRssiThold.tag = rssi_map[newThreshold].tag;
2562    userRssiThold.rssi = rssi;
2563    AR_DEBUG2_PRINTF("rssi Threshold range = %d tag = %d rssi = %d\n", newThreshold, userRssiThold.tag, rssi);
2564#ifdef SEND_EVENT_TO_APP
2565    ar6000_send_event_to_app(ar, WMI_RSSI_THRESHOLD_EVENTID,(A_UINT8 *)&userRssiThold, sizeof(USER_RSSI_THOLD));
2566#endif
2567}
2568
2569
2570void
2571ar6000_hbChallengeResp_event(AR_SOFTC_T *ar, A_UINT32 cookie, A_UINT32 source)
2572{
2573    if (source == APP_HB_CHALLENGE) {
2574        /* Report it to the app in case it wants a positive acknowledgement */
2575#ifdef SEND_EVENT_TO_APP
2576        ar6000_send_event_to_app(ar, WMIX_HB_CHALLENGE_RESP_EVENTID,
2577                                 (A_UINT8 *)&cookie, sizeof(cookie));
2578#endif
2579    } else {
2580        /* This would ignore the replys that come in after their due time */
2581        if (cookie == ar->arHBChallengeResp.seqNum) {
2582            ar->arHBChallengeResp.outstanding = FALSE;
2583        }
2584    }
2585}
2586
2587
2588void
2589ar6000_reportError_event(AR_SOFTC_T *ar, WMI_TARGET_ERROR_VAL errorVal)
2590{
2591    char *errString[] = {
2592                [WMI_TARGET_PM_ERR_FAIL] "WMI_TARGET_PM_ERR_FAIL",
2593                [WMI_TARGET_KEY_NOT_FOUND] "WMI_TARGET_KEY_NOT_FOUND",
2594                [WMI_TARGET_DECRYPTION_ERR] "WMI_TARGET_DECRYPTION_ERR",
2595                [WMI_TARGET_BMISS] "WMI_TARGET_BMISS",
2596                [WMI_PSDISABLE_NODE_JOIN] "WMI_PSDISABLE_NODE_JOIN"
2597                };
2598
2599    A_PRINTF("AR6000 Error on Target. Error = 0x%x\n", errorVal);
2600
2601    /* One error is reported at a time, and errorval is a bitmask */
2602    if(errorVal & (errorVal - 1))
2603       return;
2604
2605    A_PRINTF("AR6000 Error type = ");
2606    switch(errorVal)
2607    {
2608        case WMI_TARGET_PM_ERR_FAIL:
2609        case WMI_TARGET_KEY_NOT_FOUND:
2610        case WMI_TARGET_DECRYPTION_ERR:
2611        case WMI_TARGET_BMISS:
2612        case WMI_PSDISABLE_NODE_JOIN:
2613            A_PRINTF("%s\n", errString[errorVal]);
2614            break;
2615        default:
2616            A_PRINTF("INVALID\n");
2617            break;
2618    }
2619
2620}
2621
2622
2623void
2624ar6000_cac_event(AR_SOFTC_T *ar, A_UINT8 ac, A_UINT8 cacIndication,
2625                 A_UINT8 statusCode, A_UINT8 *tspecSuggestion)
2626{
2627    WMM_TSPEC_IE *tspecIe;
2628
2629    /*
2630     * This is the TSPEC IE suggestion from AP.
2631     * Suggestion provided by AP under some error
2632     * cases, could be helpful for the host app.
2633     * Check documentation.
2634     */
2635    tspecIe = (WMM_TSPEC_IE *)tspecSuggestion;
2636
2637    /*
2638     * What do we do, if we get TSPEC rejection? One thought
2639     * that comes to mind is implictly delete the pstream...
2640     */
2641    A_PRINTF("AR6000 CAC notification. "
2642                "AC = %d, cacIndication = 0x%x, statusCode = 0x%x\n",
2643                 ac, cacIndication, statusCode);
2644}
2645
2646#define AR6000_PRINT_BSSID(_pBss) do { \
2647        A_PRINTF("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",\
2648                 (_pBss)[0],(_pBss)[1],(_pBss)[2],(_pBss)[3],\
2649                 (_pBss)[4],(_pBss)[5]); \
2650} while(0)
2651
2652void
2653ar6000_roam_tbl_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_TBL *pTbl)
2654{
2655    A_UINT8 i;
2656
2657    A_PRINTF("ROAM TABLE NO OF ENTRIES is %d ROAM MODE is %d\n",
2658              pTbl->numEntries, pTbl->roamMode);
2659    for (i= 0; i < pTbl->numEntries; i++) {
2660        A_PRINTF("[%d]bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", i,
2661            pTbl->bssRoamInfo[i].bssid[0], pTbl->bssRoamInfo[i].bssid[1],
2662            pTbl->bssRoamInfo[i].bssid[2],
2663            pTbl->bssRoamInfo[i].bssid[3],
2664            pTbl->bssRoamInfo[i].bssid[4],
2665            pTbl->bssRoamInfo[i].bssid[5]);
2666        A_PRINTF("RSSI %d RSSIDT %d LAST RSSI %d UTIL %d ROAM_UTIL %d"
2667                 " BIAS %d\n",
2668            pTbl->bssRoamInfo[i].rssi,
2669            pTbl->bssRoamInfo[i].rssidt,
2670            pTbl->bssRoamInfo[i].last_rssi,
2671            pTbl->bssRoamInfo[i].util,
2672            pTbl->bssRoamInfo[i].roam_util,
2673            pTbl->bssRoamInfo[i].bias);
2674    }
2675}
2676
2677void
2678ar6000_wow_list_event(struct ar6_softc *ar, A_UINT8 num_filters, WMI_GET_WOW_LIST_REPLY *wow_reply)
2679{
2680    A_UINT8 i,j;
2681
2682    /*Each event now contains exactly one filter, see bug 26613*/
2683    A_PRINTF("WOW pattern %d of %d patterns\n", wow_reply->this_filter_num, wow_reply->num_filters);
2684    A_PRINTF("wow mode = %s host mode = %s\n",
2685            (wow_reply->wow_mode == 0? "disabled":"enabled"),
2686            (wow_reply->host_mode == 1 ? "awake":"asleep"));
2687
2688
2689    /*If there are no patterns, the reply will only contain generic
2690      WoW information. Pattern information will exist only if there are
2691      patterns present. Bug 26716*/
2692
2693   /* If this event contains pattern information, display it*/
2694    if (wow_reply->this_filter_num) {
2695        i=0;
2696        A_PRINTF("id=%d size=%d offset=%d\n",
2697                    wow_reply->wow_filters[i].wow_filter_id,
2698                    wow_reply->wow_filters[i].wow_filter_size,
2699                    wow_reply->wow_filters[i].wow_filter_offset);
2700       A_PRINTF("wow pattern = ");
2701       for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) {
2702             A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_pattern[j]);
2703        }
2704
2705        A_PRINTF("\nwow mask = ");
2706        for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) {
2707            A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_mask[j]);
2708        }
2709        A_PRINTF("\n");
2710    }
2711}
2712
2713/*
2714 * Report the Roaming related data collected on the target
2715 */
2716void
2717ar6000_display_roam_time(WMI_TARGET_ROAM_TIME *p)
2718{
2719    A_PRINTF("Disconnect Data : BSSID: ");
2720    AR6000_PRINT_BSSID(p->disassoc_bssid);
2721    A_PRINTF(" RSSI %d DISASSOC Time %d NO_TXRX_TIME %d\n",
2722             p->disassoc_bss_rssi,p->disassoc_time,
2723             p->no_txrx_time);
2724    A_PRINTF("Connect Data: BSSID: ");
2725    AR6000_PRINT_BSSID(p->assoc_bssid);
2726    A_PRINTF(" RSSI %d ASSOC Time %d TXRX_TIME %d\n",
2727             p->assoc_bss_rssi,p->assoc_time,
2728             p->allow_txrx_time);
2729    A_PRINTF("Last Data Tx Time (b4 Disassoc) %d "\
2730             "First Data Tx Time (after Assoc) %d\n",
2731             p->last_data_txrx_time, p->first_data_txrx_time);
2732}
2733
2734void
2735ar6000_roam_data_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_DATA *p)
2736{
2737    switch (p->roamDataType) {
2738        case ROAM_DATA_TIME:
2739            ar6000_display_roam_time(&p->u.roamTime);
2740            break;
2741        default:
2742            break;
2743    }
2744}
2745
2746void
2747ar6000_bssInfo_event_rx(AR_SOFTC_T *ar, A_UINT8 *datap, int len)
2748{
2749    struct sk_buff *skb;
2750    WMI_BSS_INFO_HDR *bih = (WMI_BSS_INFO_HDR *)datap;
2751
2752
2753    if (!ar->arMgmtFilter) {
2754        return;
2755    }
2756    if (((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_BEACON) &&
2757        (bih->frameType != BEACON_FTYPE)) ||
2758        ((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_PROBE_RESP) &&
2759        (bih->frameType != PROBERESP_FTYPE)))
2760    {
2761        return;
2762    }
2763
2764    if ((skb = A_NETBUF_ALLOC_RAW(len)) != NULL) {
2765
2766        A_NETBUF_PUT(skb, len);
2767        A_MEMCPY(A_NETBUF_DATA(skb), datap, len);
2768        skb->dev = ar->arNetDev;
2769    printk("MAC RAW...\n");
2770// skb->mac.raw = A_NETBUF_DATA(skb);
2771        skb->ip_summed = CHECKSUM_NONE;
2772        skb->pkt_type = PACKET_OTHERHOST;
2773        skb->protocol = __constant_htons(0x0019);
2774        netif_rx(skb);
2775    }
2776}
2777
2778A_UINT32 wmiSendCmdNum;
2779
2780A_STATUS
2781ar6000_control_tx(void *devt, void *osbuf, WMI_PRI_STREAM_ID streamID)
2782{
2783    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
2784    A_STATUS status = A_OK;
2785    struct ar_cookie *cookie = NULL;
2786    int i;
2787
2788        /* take lock to protect ar6000_alloc_cookie() */
2789    AR6000_SPIN_LOCK(&ar->arLock, 0);
2790
2791    do {
2792
2793        AR_DEBUG2_PRINTF("ar_contrstatus = ol_tx: skb=0x%x, len=0x%x, sid=%d\n",
2794                         (A_UINT32)osbuf, A_NETBUF_LEN(osbuf), streamID);
2795
2796        if ((streamID == WMI_CONTROL_PRI) && (ar->arWMIControlEpFull)) {
2797                /* control endpoint is full, don't allocate resources, we
2798                 * are just going to drop this packet */
2799            cookie = NULL;
2800            AR_DEBUG_PRINTF(" WMI Control EP full, dropping packet : 0x%X, len:%d \n",
2801                    (A_UINT32)osbuf, A_NETBUF_LEN(osbuf));
2802        } else {
2803            cookie = ar6000_alloc_cookie(ar);
2804        }
2805
2806        if (cookie == NULL) {
2807            status = A_NO_MEMORY;
2808            break;
2809        }
2810
2811        if(logWmiRawMsgs) {
2812            A_PRINTF("WMI cmd send, msgNo %d :", wmiSendCmdNum);
2813            for(i = 0; i < a_netbuf_to_len(osbuf); i++)
2814                A_PRINTF("%x ", ((A_UINT8 *)a_netbuf_to_data(osbuf))[i]);
2815            A_PRINTF("\n");
2816        }
2817
2818        wmiSendCmdNum++;
2819
2820    } while (FALSE);
2821
2822    if (cookie != NULL) {
2823            /* got a structure to send it out on */
2824        ar->arTxPending[streamID]++;
2825
2826        if (streamID != WMI_CONTROL_PRI) {
2827            ar->arTotalTxDataPending++;
2828        }
2829    }
2830
2831    AR6000_SPIN_UNLOCK(&ar->arLock, 0);
2832
2833    if (cookie != NULL) {
2834        cookie->arc_bp[0] = (A_UINT32)osbuf;
2835        cookie->arc_bp[1] = 0;
2836        SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt,
2837                               cookie,
2838                               A_NETBUF_DATA(osbuf),
2839                               A_NETBUF_LEN(osbuf),
2840                               arWMIStream2EndpointID(ar,streamID),
2841                               AR6K_CONTROL_PKT_TAG);
2842            /* this interface is asynchronous, if there is an error, cleanup will happen in the
2843             * TX completion callback */
2844        HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt);
2845        status = A_OK;
2846    }
2847
2848    return status;
2849}
2850
2851/* indicate tx activity or inactivity on a WMI stream */
2852void ar6000_indicate_tx_activity(void *devt, A_UINT8 TrafficClass, A_BOOL Active)
2853{
2854    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
2855    WMI_PRI_STREAM_ID streamid;
2856
2857    if (ar->arWmiEnabled) {
2858        streamid = wmi_get_stream_id(ar->arWmi, TrafficClass);
2859    } else {
2860            /* for mbox ping testing, the traffic class is mapped directly as a stream ID,
2861             * see handling of AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE in ioctl.c */
2862        streamid = (WMI_PRI_STREAM_ID)TrafficClass;
2863    }
2864
2865        /* notify HTC, this may cause credit distribution changes */
2866
2867    HTCIndicateActivityChange(ar->arHtcTarget,
2868                              arWMIStream2EndpointID(ar,streamid),
2869                              Active);
2870
2871}
2872
2873module_init(ar6000_init_module);
2874module_exit(ar6000_cleanup_module);
2875
2876/* Init cookie queue */
2877static void
2878ar6000_cookie_init(AR_SOFTC_T *ar)
2879{
2880    A_UINT32 i;
2881
2882    ar->arCookieList = NULL;
2883    A_MEMZERO(s_ar_cookie_mem, sizeof(s_ar_cookie_mem));
2884
2885    for (i = 0; i < MAX_COOKIE_NUM; i++) {
2886        ar6000_free_cookie(ar, &s_ar_cookie_mem[i]);
2887    }
2888}
2889
2890/* cleanup cookie queue */
2891static void
2892ar6000_cookie_cleanup(AR_SOFTC_T *ar)
2893{
2894    /* It is gone .... */
2895    ar->arCookieList = NULL;
2896}
2897
2898/* Init cookie queue */
2899static void
2900ar6000_free_cookie(AR_SOFTC_T *ar, struct ar_cookie * cookie)
2901{
2902    /* Insert first */
2903    A_ASSERT(ar != NULL);
2904    A_ASSERT(cookie != NULL);
2905    cookie->arc_list_next = ar->arCookieList;
2906    ar->arCookieList = cookie;
2907}
2908
2909/* cleanup cookie queue */
2910static struct ar_cookie *
2911ar6000_alloc_cookie(AR_SOFTC_T *ar)
2912{
2913    struct ar_cookie *cookie;
2914
2915    cookie = ar->arCookieList;
2916    if(cookie != NULL)
2917    {
2918        ar->arCookieList = cookie->arc_list_next;
2919    }
2920
2921    return cookie;
2922}
2923
2924#ifdef SEND_EVENT_TO_APP
2925/*
2926 * This function is used to send event which come from taget to
2927 * the application. The buf which send to application is include
2928 * the event ID and event content.
2929 */
2930#define EVENT_ID_LEN 2
2931void ar6000_send_event_to_app(AR_SOFTC_T *ar, A_UINT16 eventId,
2932                              A_UINT8 *datap, int len)
2933{
2934
2935#if (WIRELESS_EXT >= 15)
2936
2937/* note: IWEVCUSTOM only exists in wireless extensions after version 15 */
2938
2939    char *buf;
2940    A_UINT16 size;
2941    union iwreq_data wrqu;
2942
2943    size = len + EVENT_ID_LEN;
2944
2945    if (size > IW_CUSTOM_MAX) {
2946        AR_DEBUG_PRINTF("WMI event ID : 0x%4.4X, len = %d too big for IWEVCUSTOM (max=%d) \n",
2947                eventId, size, IW_CUSTOM_MAX);
2948        return;
2949    }
2950
2951    buf = A_MALLOC_NOWAIT(size);
2952    A_MEMZERO(buf, size);
2953    A_MEMCPY(buf, &eventId, EVENT_ID_LEN);
2954    A_MEMCPY(buf+EVENT_ID_LEN, datap, len);
2955
2956    //AR_DEBUG_PRINTF("event ID = %d,len = %d\n",*(A_UINT16*)buf, size);
2957    A_MEMZERO(&wrqu, sizeof(wrqu));
2958    wrqu.data.length = size;
2959    wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
2960
2961    A_FREE(buf);
2962#endif
2963
2964
2965}
2966#endif
2967
2968
2969void
2970ar6000_tx_retry_err_event(void *devt)
2971{
2972    AR_DEBUG2_PRINTF("Tx retries reach maximum!\n");
2973}
2974
2975void
2976ar6000_snrThresholdEvent_rx(void *devt, WMI_SNR_THRESHOLD_VAL newThreshold, A_UINT8 snr)
2977{
2978    AR_DEBUG2_PRINTF("snr threshold range %d, snr %d\n", newThreshold, snr);
2979}
2980
2981void
2982ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL newThreshold, A_UINT8 lq)
2983{
2984    AR_DEBUG2_PRINTF("lq threshold range %d, lq %d\n", newThreshold, lq);
2985}
2986
2987
2988
2989A_UINT32
2990a_copy_to_user(void *to, const void *from, A_UINT32 n)
2991{
2992    return(copy_to_user(to, from, n));
2993}
2994
2995A_UINT32
2996a_copy_from_user(void *to, const void *from, A_UINT32 n)
2997{
2998    return(copy_from_user(to, from, n));
2999}
3000
3001
3002A_STATUS
3003ar6000_get_driver_cfg(struct net_device *dev,
3004                        A_UINT16 cfgParam,
3005                        void *result)
3006{
3007
3008    A_STATUS ret = 0;
3009
3010    switch(cfgParam)
3011    {
3012        case AR6000_DRIVER_CFG_GET_WLANNODECACHING:
3013           *((A_UINT32 *)result) = wlanNodeCaching;
3014           break;
3015        case AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS:
3016           *((A_UINT32 *)result) = logWmiRawMsgs;
3017            break;
3018        default:
3019           ret = EINVAL;
3020           break;
3021    }
3022
3023    return ret;
3024}
3025
3026void
3027ar6000_keepalive_rx(void *devt, A_UINT8 configured)
3028{
3029    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
3030
3031    ar->arKeepaliveConfigured = configured;
3032    wake_up(&arEvent);
3033}
3034
3035void
3036ar6000_pmkid_list_event(void *devt, A_UINT8 numPMKID, WMI_PMKID *pmkidList)
3037{
3038    A_UINT8 i, j;
3039
3040    A_PRINTF("Number of Cached PMKIDs is %d\n", numPMKID);
3041
3042    for (i = 0; i < numPMKID; i++) {
3043        A_PRINTF("\nPMKID %d ", i);
3044            for (j = 0; j < WMI_PMKID_LEN; j++) {
3045                A_PRINTF("%2.2x", pmkidList->pmkid[j]);
3046            }
3047        pmkidList++;
3048    }
3049}
3050
3051#ifdef USER_KEYS
3052static A_STATUS
3053
3054ar6000_reinstall_keys(AR_SOFTC_T *ar, A_UINT8 key_op_ctrl)
3055{
3056    A_STATUS status = A_OK;
3057    struct ieee80211req_key *uik = &ar->user_saved_keys.ucast_ik;
3058    struct ieee80211req_key *bik = &ar->user_saved_keys.bcast_ik;
3059    CRYPTO_TYPE keyType = ar->user_saved_keys.keyType;
3060
3061    if (IEEE80211_CIPHER_CCKM_KRK != uik->ik_type) {
3062        if (NONE_CRYPT == keyType) {
3063            goto _reinstall_keys_out;
3064        }
3065
3066        if (uik->ik_keylen) {
3067            status = wmi_addKey_cmd(ar->arWmi, uik->ik_keyix,
3068                    ar->user_saved_keys.keyType, PAIRWISE_USAGE,
3069                    uik->ik_keylen, (A_UINT8 *)&uik->ik_keyrsc,
3070                    uik->ik_keydata, key_op_ctrl, SYNC_BEFORE_WMIFLAG);
3071        }
3072
3073    } else {
3074        status = wmi_add_krk_cmd(ar->arWmi, uik->ik_keydata);
3075    }
3076
3077    if (IEEE80211_CIPHER_CCKM_KRK != bik->ik_type) {
3078        if (NONE_CRYPT == keyType) {
3079            goto _reinstall_keys_out;
3080        }
3081
3082        if (bik->ik_keylen) {
3083            status = wmi_addKey_cmd(ar->arWmi, bik->ik_keyix,
3084                    ar->user_saved_keys.keyType, GROUP_USAGE,
3085                    bik->ik_keylen, (A_UINT8 *)&bik->ik_keyrsc,
3086                    bik->ik_keydata, key_op_ctrl, NO_SYNC_WMIFLAG);
3087        }
3088    } else {
3089        status = wmi_add_krk_cmd(ar->arWmi, bik->ik_keydata);
3090    }
3091
3092_reinstall_keys_out:
3093    ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
3094    ar->user_key_ctrl = 0;
3095
3096    return status;
3097}
3098#endif /* USER_KEYS */
3099
3100
3101void
3102ar6000_dset_open_req(
3103    void *context,
3104    A_UINT32 id,
3105    A_UINT32 targHandle,
3106    A_UINT32 targReplyFn,
3107    A_UINT32 targReplyArg)
3108{
3109}
3110
3111void
3112ar6000_dset_close(
3113    void *context,
3114    A_UINT32 access_cookie)
3115{
3116    return;
3117}
3118
3119void
3120ar6000_dset_data_req(
3121   void *context,
3122   A_UINT32 accessCookie,
3123   A_UINT32 offset,
3124   A_UINT32 length,
3125   A_UINT32 targBuf,
3126   A_UINT32 targReplyFn,
3127   A_UINT32 targReplyArg)
3128{
3129}
3130

Archive Download this file



interactive