3c980806a5155713073e04cbf5a88b76cec134e5
[firefly-linux-kernel-4.4.55.git] / drivers / staging / vt6655 / wcmd.c
1 /*
2  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3  * All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * File: wcmd.c
20  *
21  * Purpose: Handles the management command interface functions
22  *
23  * Author: Lyndon Chen
24  *
25  * Date: May 8, 2003
26  *
27  * Functions:
28  *      s_vProbeChannel - Active scan channel
29  *      s_MgrMakeProbeRequest - Make ProbeRequest packet
30  *      CommandTimer - Timer function to handle command
31  *      s_bCommandComplete - Command Complete function
32  *      bScheduleCommand - Push Command and wait Command Scheduler to do
33  *      vCommandTimer- Command call back functions
34  *      vCommandTimerWait- Call back timer
35  *      bClearBSSID_SCAN- Clear BSSID_SCAN cmd in CMD Queue
36  *
37  * Revision History:
38  *
39  */
40
41 #include "ttype.h"
42 #include "tmacro.h"
43 #include "device.h"
44 #include "mac.h"
45 #include "card.h"
46 #include "80211hdr.h"
47 #include "wcmd.h"
48 #include "wmgr.h"
49 #include "power.h"
50 #include "wctl.h"
51 #include "baseband.h"
52 #include "rxtx.h"
53 #include "rf.h"
54 #include "iowpa.h"
55 #include "channel.h"
56
57 /*---------------------  Static Definitions -------------------------*/
58
59 /*---------------------  Static Classes  ----------------------------*/
60
61 /*---------------------  Static Functions  --------------------------*/
62
63 static
64 void
65 s_vProbeChannel(
66         struct vnt_private *pDevice
67 );
68
69 static
70 PSTxMgmtPacket
71 s_MgrMakeProbeRequest(
72         struct vnt_private *pDevice,
73         PSMgmtObject pMgmt,
74         unsigned char *pScanBSSID,
75         PWLAN_IE_SSID pSSID,
76         PWLAN_IE_SUPP_RATES pCurrRates,
77         PWLAN_IE_SUPP_RATES pCurrExtSuppRates
78 );
79
80 static
81 bool
82 s_bCommandComplete(
83         struct vnt_private *pDevice
84 );
85
86 /*---------------------  Export Variables  --------------------------*/
87
88 /*---------------------  Export Functions  --------------------------*/
89
90 /*
91  * Description:
92  *      Stop AdHoc beacon during scan process
93  *
94  * Parameters:
95  *  In:
96  *      pDevice     - Pointer to the adapter
97  *  Out:
98  *      none
99  *
100  * Return Value: none
101  *
102  */
103 static
104 void
105 vAdHocBeaconStop(struct vnt_private *pDevice)
106 {
107         PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
108         bool bStop;
109
110         /*
111          * temporarily stop Beacon packet for AdHoc Server
112          * if all of the following conditions are met:
113          *  (1) STA is in AdHoc mode
114          *  (2) VT3253 is programmed as automatic Beacon Transmitting
115          *  (3) One of the following conditions is met
116          *      (3.1) AdHoc channel is in B/G band and the
117          *      current scan channel is in A band
118          *      or
119          *      (3.2) AdHoc channel is in A mode
120          */
121         bStop = false;
122         if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) &&
123             (pMgmt->eCurrState >= WMAC_STATE_STARTED)) {
124                 if ((pMgmt->uIBSSChannel <=  CB_MAX_CHANNEL_24G) &&
125                     (pMgmt->uScanChannel > CB_MAX_CHANNEL_24G)) {
126                         bStop = true;
127                 }
128                 if (pMgmt->uIBSSChannel >  CB_MAX_CHANNEL_24G)
129                         bStop = true;
130
131         }
132
133         if (bStop)
134                 MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
135 } /* vAdHocBeaconStop */
136
137 /*
138  * Description:
139  *      Restart AdHoc beacon after scan process complete
140  *
141  * Parameters:
142  *  In:
143  *      pDevice     - Pointer to the adapter
144  *  Out:
145  *      none
146  *
147  * Return Value: none
148  *
149  */
150 static
151 void
152 vAdHocBeaconRestart(struct vnt_private *pDevice)
153 {
154         PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
155
156         /*
157          * Restart Beacon packet for AdHoc Server
158          * if all of the following coditions are met:
159          *  (1) STA is in AdHoc mode
160          *  (2) VT3253 is programmed as automatic Beacon Transmitting
161          */
162         if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) &&
163             (pMgmt->eCurrState >= WMAC_STATE_STARTED)) {
164                 MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
165         }
166 }
167
168 /*+
169  *
170  * Routine Description:
171  *   Prepare and send probe request management frames.
172  *
173  *
174  * Return Value:
175  *    none.
176  *
177  -*/
178
179 static
180 void
181 s_vProbeChannel(
182         struct vnt_private *pDevice
183 )
184 {
185         //1M,   2M,   5M,   11M,  18M,  24M,  36M,  54M
186         unsigned char abyCurrSuppRatesG[] = {WLAN_EID_SUPP_RATES, 8, 0x02, 0x04, 0x0B, 0x16, 0x24, 0x30, 0x48, 0x6C};
187         unsigned char abyCurrExtSuppRatesG[] = {WLAN_EID_EXTSUPP_RATES, 4, 0x0C, 0x12, 0x18, 0x60};
188         //6M,   9M,   12M,  48M
189         unsigned char abyCurrSuppRatesA[] = {WLAN_EID_SUPP_RATES, 8, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
190         unsigned char abyCurrSuppRatesB[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16};
191         unsigned char *pbyRate;
192         PSTxMgmtPacket  pTxPacket;
193         PSMgmtObject    pMgmt = pDevice->pMgmt;
194         unsigned int ii;
195
196         if (pDevice->eCurrentPHYType == PHY_TYPE_11A)
197                 pbyRate = &abyCurrSuppRatesA[0];
198         else if (pDevice->eCurrentPHYType == PHY_TYPE_11B)
199                 pbyRate = &abyCurrSuppRatesB[0];
200         else
201                 pbyRate = &abyCurrSuppRatesG[0];
202
203         // build an assocreq frame and send it
204         pTxPacket = s_MgrMakeProbeRequest
205                 (
206                         pDevice,
207                         pMgmt,
208                         pMgmt->abyScanBSSID,
209                         (PWLAN_IE_SSID)pMgmt->abyScanSSID,
210                         (PWLAN_IE_SUPP_RATES)pbyRate,
211                         (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRatesG
212                         );
213
214         if (pTxPacket != NULL) {
215                 for (ii = 0; ii < 2; ii++) {
216                         if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING)
217                                 pr_debug("Probe request sending fail..\n");
218                         else
219                                 pr_debug("Probe request is sending..\n");
220                 }
221         }
222 }
223
224 /*+
225  *
226  * Routine Description:
227  *  Constructs an probe request frame
228  *
229  *
230  * Return Value:
231  *    A ptr to Tx frame or NULL on allocation failure
232  *
233  -*/
234
235 static PSTxMgmtPacket
236 s_MgrMakeProbeRequest(
237         struct vnt_private *pDevice,
238         PSMgmtObject pMgmt,
239         unsigned char *pScanBSSID,
240         PWLAN_IE_SSID pSSID,
241         PWLAN_IE_SUPP_RATES pCurrRates,
242         PWLAN_IE_SUPP_RATES pCurrExtSuppRates
243
244 )
245 {
246         PSTxMgmtPacket      pTxPacket = NULL;
247
248         pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
249         memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_PROBEREQ_FR_MAXLEN);
250         pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
251
252         return pTxPacket;
253 }
254
255 void
256 vCommandTimerWait(
257         void *hDeviceContext,
258         unsigned int MSecond
259 )
260 {
261         struct vnt_private *pDevice = hDeviceContext;
262
263         init_timer(&pDevice->sTimerCommand);
264         pDevice->sTimerCommand.data = (unsigned long) pDevice;
265         pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer;
266         // RUN_AT :1 msec ~= (HZ/1024)
267         pDevice->sTimerCommand.expires = (unsigned int)RUN_AT((MSecond * HZ) >> 10);
268         add_timer(&pDevice->sTimerCommand);
269 }
270
271 void
272 vCommandTimer(
273         void *hDeviceContext
274 )
275 {
276         struct vnt_private *pDevice = hDeviceContext;
277         PSMgmtObject    pMgmt = pDevice->pMgmt;
278         PWLAN_IE_SSID   pItemSSID;
279         PWLAN_IE_SSID   pItemSSIDCurr;
280         unsigned int ii;
281         unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
282         struct sk_buff  *skb;
283
284         if (pDevice->dwDiagRefCount != 0)
285                 return;
286         if (!pDevice->bCmdRunning)
287                 return;
288
289         spin_lock_irq(&pDevice->lock);
290
291         switch (pDevice->eCommandState) {
292         case WLAN_CMD_SCAN_START:
293
294                 pDevice->byReAssocCount = 0;
295                 if (pDevice->bRadioOff) {
296                         s_bCommandComplete(pDevice);
297                         spin_unlock_irq(&pDevice->lock);
298                         return;
299                 }
300
301                 if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
302                         s_bCommandComplete(pDevice);
303                         CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_AP);
304                         spin_unlock_irq(&pDevice->lock);
305                         return;
306                 }
307
308                 pr_debug("eCommandState= WLAN_CMD_SCAN_START\n");
309                 pItemSSID = (PWLAN_IE_SSID)pMgmt->abyScanSSID;
310                 // wait all Data TD complete
311                 if (pDevice->iTDUsed[TYPE_AC0DMA] != 0) {
312                         spin_unlock_irq(&pDevice->lock);
313                         vCommandTimerWait((void *)pDevice, 10);
314                         return;
315                 }
316
317                 if (pMgmt->uScanChannel == 0) {
318                         pMgmt->uScanChannel = pDevice->byMinChannel;
319                         // Set Baseband to be more sensitive.
320
321                 }
322                 if (pMgmt->uScanChannel > pDevice->byMaxChannel) {
323                         pMgmt->eScanState = WMAC_NO_SCANNING;
324
325                         // Set Baseband's sensitivity back.
326                         // Set channel back
327                         set_channel(pMgmt->pAdapter, pMgmt->uCurrChannel);
328                         pr_debug("Scanning, set back to channel: [%d]\n",
329                                  pMgmt->uCurrChannel);
330                         if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)
331                                 CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_ADHOC);
332                         else
333                                 CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_STATION);
334
335                         vAdHocBeaconRestart(pDevice);
336                         s_bCommandComplete(pDevice);
337
338                 } else {
339 //2008-8-4 <add> by chester
340                         if (!is_channel_valid(pMgmt->uScanChannel)) {
341                                 pr_debug("Invalid channel pMgmt->uScanChannel = %d\n",
342                                          pMgmt->uScanChannel);
343                                 s_bCommandComplete(pDevice);
344                                 spin_unlock_irq(&pDevice->lock);
345                                 return;
346                         }
347                         if (pMgmt->uScanChannel == pDevice->byMinChannel) {
348                                 pMgmt->abyScanBSSID[0] = 0xFF;
349                                 pMgmt->abyScanBSSID[1] = 0xFF;
350                                 pMgmt->abyScanBSSID[2] = 0xFF;
351                                 pMgmt->abyScanBSSID[3] = 0xFF;
352                                 pMgmt->abyScanBSSID[4] = 0xFF;
353                                 pMgmt->abyScanBSSID[5] = 0xFF;
354                                 pItemSSID->byElementID = WLAN_EID_SSID;
355                                 pMgmt->eScanState = WMAC_IS_SCANNING;
356
357                         }
358
359                         vAdHocBeaconStop(pDevice);
360
361                         if (set_channel(pMgmt->pAdapter, pMgmt->uScanChannel))
362                                 pr_debug("SCAN Channel: %d\n",
363                                          pMgmt->uScanChannel);
364                         else
365                                 pr_debug("SET SCAN Channel Fail: %d\n",
366                                          pMgmt->uScanChannel);
367
368                         CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_UNSPECIFIED);
369                         pMgmt->uScanChannel++;
370 //2008-8-4 <modify> by chester
371                         if (!is_channel_valid(pMgmt->uScanChannel) &&
372                             pMgmt->uScanChannel <= pDevice->byMaxChannel) {
373                                 pMgmt->uScanChannel = pDevice->byMaxChannel + 1;
374                                 pMgmt->eCommandState = WLAN_CMD_SCAN_END;
375
376                         }
377
378                         if (!pMgmt->b11hEnable ||
379                             (pMgmt->uScanChannel < CB_MAX_CHANNEL_24G)) {
380                                 s_vProbeChannel(pDevice);
381                                 spin_unlock_irq(&pDevice->lock);
382                                 vCommandTimerWait((void *)pDevice, WCMD_ACTIVE_SCAN_TIME);
383                                 return;
384                         } else {
385                                 spin_unlock_irq(&pDevice->lock);
386                                 vCommandTimerWait((void *)pDevice, WCMD_PASSIVE_SCAN_TIME);
387                                 return;
388                         }
389
390                 }
391
392                 break;
393
394         case WLAN_CMD_SCAN_END:
395
396                 // Set Baseband's sensitivity back.
397                 // Set channel back
398                 set_channel(pMgmt->pAdapter, pMgmt->uCurrChannel);
399                 pr_debug("Scanning, set back to channel: [%d]\n",
400                          pMgmt->uCurrChannel);
401                 if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)
402                         CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_ADHOC);
403                 else
404                         CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_STATION);
405
406                 pMgmt->eScanState = WMAC_NO_SCANNING;
407                 vAdHocBeaconRestart(pDevice);
408 //2008-0409-07, <Add> by Einsn Liu
409 #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
410                 if (pMgmt->eScanType == WMAC_SCAN_PASSIVE) {
411                         //send scan event to wpa_Supplicant
412                         union iwreq_data wrqu;
413
414                         memset(&wrqu, 0, sizeof(wrqu));
415                         wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL);
416                 }
417 #endif
418                 s_bCommandComplete(pDevice);
419                 break;
420
421         case WLAN_CMD_DISASSOCIATE_START:
422                 pDevice->byReAssocCount = 0;
423                 if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
424                     (pMgmt->eCurrState != WMAC_STATE_ASSOC)) {
425                         s_bCommandComplete(pDevice);
426                         spin_unlock_irq(&pDevice->lock);
427                         return;
428                 } else {
429                         pr_debug("Send Disassociation Packet..\n");
430                         // reason = 8 : disassoc because sta has left
431                         pDevice->bLinkPass = false;
432                         // unlock command busy
433                         pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
434                         pItemSSID->len = 0;
435                         memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN);
436                         pMgmt->eCurrState = WMAC_STATE_IDLE;
437                         pMgmt->sNodeDBTable[0].bActive = false;
438                 }
439                 netif_stop_queue(pDevice->dev);
440                 pDevice->eCommandState = WLAN_DISASSOCIATE_WAIT;
441                 // wait all Control TD complete
442                 if (pDevice->iTDUsed[TYPE_TXDMA0] != 0) {
443                         vCommandTimerWait((void *)pDevice, 10);
444                         spin_unlock_irq(&pDevice->lock);
445                         return;
446                 }
447                 pr_debug(" CARDbRadioPowerOff\n");
448                 //2008-09-02  <mark>    by chester
449                 s_bCommandComplete(pDevice);
450                 break;
451
452         case WLAN_DISASSOCIATE_WAIT:
453                 // wait all Control TD complete
454                 if (pDevice->iTDUsed[TYPE_TXDMA0] != 0) {
455                         vCommandTimerWait((void *)pDevice, 10);
456                         spin_unlock_irq(&pDevice->lock);
457                         return;
458                 }
459 //2008-09-02  <mark> by chester
460                 s_bCommandComplete(pDevice);
461                 break;
462
463         case WLAN_CMD_SSID_START:
464                 pDevice->byReAssocCount = 0;
465                 if (pDevice->bRadioOff) {
466                         s_bCommandComplete(pDevice);
467                         spin_unlock_irq(&pDevice->lock);
468                         return;
469                 }
470                 pr_debug("chester-abyDesireSSID=%s\n", ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySSID);
471                 pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
472                 pItemSSIDCurr = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
473                 pr_debug(" cmd: desire ssid = %s\n", pItemSSID->abySSID);
474                 pr_debug(" cmd: curr ssid = %s\n", pItemSSIDCurr->abySSID);
475
476                 if (pMgmt->eCurrState == WMAC_STATE_ASSOC) {
477                         pr_debug(" Cmd pMgmt->eCurrState == WMAC_STATE_ASSOC\n");
478                         pr_debug(" pItemSSID->len =%d\n", pItemSSID->len);
479                         pr_debug(" pItemSSIDCurr->len = %d\n",
480                                  pItemSSIDCurr->len);
481                         pr_debug(" desire ssid = %s\n", pItemSSID->abySSID);
482                         pr_debug(" curr ssid = %s\n", pItemSSIDCurr->abySSID);
483                 }
484
485                 if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) ||
486                     ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) {
487                         if (pItemSSID->len == pItemSSIDCurr->len) {
488                                 if (memcmp(pItemSSID->abySSID, pItemSSIDCurr->abySSID, pItemSSID->len) == 0) {
489                                         s_bCommandComplete(pDevice);
490                                         spin_unlock_irq(&pDevice->lock);
491                                         return;
492                                 }
493                         }
494
495                         netif_stop_queue(pDevice->dev);
496                         pDevice->bLinkPass = false;
497                 }
498                 // set initial state
499                 pMgmt->eCurrState = WMAC_STATE_IDLE;
500                 pMgmt->eCurrMode = WMAC_MODE_STANDBY;
501                 PSvDisablePowerSaving((void *)pDevice);
502                 BSSvClearNodeDBTable(pDevice, 0);
503
504                 // if Infra mode
505                 if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED)) {
506                         // Call mgr to begin the deauthentication
507                         // reason = (3) because sta has left ESS
508
509                         // Call mgr to begin the authentication
510                 }
511                 // if Adhoc mode
512                 else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
513                         if (pMgmt->eCurrState == WMAC_STATE_JOINTED) {
514                                 if (netif_queue_stopped(pDevice->dev))
515                                         netif_wake_queue(pDevice->dev);
516
517                                 pDevice->bLinkPass = true;
518
519                                 pMgmt->sNodeDBTable[0].bActive = true;
520                                 pMgmt->sNodeDBTable[0].uInActiveCount = 0;
521                                 bClearBSSID_SCAN(pDevice);
522                         } else {
523                                 // start own IBSS
524
525                                 BSSvAddMulticastNode(pDevice);
526                         }
527                 }
528                 // if SSID not found
529                 else if (pMgmt->eCurrMode == WMAC_MODE_STANDBY) {
530                         if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA ||
531                             pMgmt->eConfigMode == WMAC_CONFIG_AUTO) {
532                                 // start own IBSS
533
534                                 BSSvAddMulticastNode(pDevice);
535                                 if (netif_queue_stopped(pDevice->dev))
536                                         netif_wake_queue(pDevice->dev);
537
538                                 pDevice->bLinkPass = true;
539                         } else {
540                                 pr_debug("Disconnect SSID none\n");
541 #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
542                                 {
543                                         union iwreq_data  wrqu;
544
545                                         memset(&wrqu, 0, sizeof(wrqu));
546                                         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
547                                         pr_debug("wireless_send_event--->SIOCGIWAP(disassociated:vMgrJoinBSSBegin Fail !!)\n");
548                                         wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
549                                 }
550 #endif
551
552                         }
553                 }
554                 s_bCommandComplete(pDevice);
555                 break;
556
557         case WLAN_AUTHENTICATE_WAIT:
558                 pr_debug("eCommandState == WLAN_AUTHENTICATE_WAIT\n");
559                 if (pMgmt->eCurrState == WMAC_STATE_AUTH) {
560                         // Call mgr to begin the association
561                         pDevice->byLinkWaitCount = 0;
562                         pr_debug("eCurrState == WMAC_STATE_AUTH\n");
563                 }
564
565                 else if (pMgmt->eCurrState < WMAC_STATE_AUTHPENDING) {
566                         pr_debug("WLAN_AUTHENTICATE_WAIT:Authen Fail???\n");
567                 } else if (pDevice->byLinkWaitCount <= 4) {    //mike add:wait another 2 sec if authenticated_frame delay!
568                         pDevice->byLinkWaitCount++;
569                         pr_debug("WLAN_AUTHENTICATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount);
570                         spin_unlock_irq(&pDevice->lock);
571                         vCommandTimerWait((void *)pDevice, AUTHENTICATE_TIMEOUT/2);
572                         return;
573                 }
574                 pDevice->byLinkWaitCount = 0;
575                 s_bCommandComplete(pDevice);
576                 break;
577
578         case WLAN_ASSOCIATE_WAIT:
579                 if (pMgmt->eCurrState == WMAC_STATE_ASSOC) {
580                         pr_debug("eCurrState == WMAC_STATE_ASSOC\n");
581                         if (pDevice->ePSMode != WMAC_POWER_CAM)
582                                 PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval);
583
584                         if (pMgmt->eAuthenMode >= WMAC_AUTH_WPA)
585                                 KeybRemoveAllKey(&(pDevice->sKey), pDevice->abyBSSID, pDevice->PortOffset);
586
587                         pDevice->bLinkPass = true;
588                         pDevice->byLinkWaitCount = 0;
589                         pDevice->byReAssocCount = 0;
590                         bClearBSSID_SCAN(pDevice);
591                         if (pDevice->byFOETuning) {
592                                 BBvSetFOE(pDevice->PortOffset);
593                         }
594                         if (netif_queue_stopped(pDevice->dev))
595                                 netif_wake_queue(pDevice->dev);
596
597                         if (pDevice->IsTxDataTrigger) {    //TxDataTimer is not triggered at the first time
598                                 del_timer(&pDevice->sTimerTxData);
599                                 init_timer(&pDevice->sTimerTxData);
600                                 pDevice->sTimerTxData.data = (unsigned long) pDevice;
601                                 pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData;
602                                 pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
603                                 pDevice->fTxDataInSleep = false;
604                                 pDevice->nTxDataTimeCout = 0;
605                         }
606
607                         pDevice->IsTxDataTrigger = true;
608                         add_timer(&pDevice->sTimerTxData);
609
610                 } else if (pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) {
611                         netdev_err(pDevice->dev,
612                                    "WLAN_ASSOCIATE_WAIT:Association Fail???\n");
613                 } else if (pDevice->byLinkWaitCount <= 4) {    //mike add:wait another 2 sec if associated_frame delay!
614                         pDevice->byLinkWaitCount++;
615                         pr_debug("WLAN_ASSOCIATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount);
616                         spin_unlock_irq(&pDevice->lock);
617                         vCommandTimerWait((void *)pDevice, ASSOCIATE_TIMEOUT/2);
618                         return;
619                 }
620                 pDevice->byLinkWaitCount = 0;
621
622                 s_bCommandComplete(pDevice);
623                 break;
624
625         case WLAN_CMD_AP_MODE_START:
626                 pr_debug("eCommandState == WLAN_CMD_AP_MODE_START\n");
627
628                 if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
629                         del_timer(&pMgmt->sTimerSecondCallback);
630                         pMgmt->eCurrState = WMAC_STATE_IDLE;
631                         pMgmt->eCurrMode = WMAC_MODE_STANDBY;
632                         pDevice->bLinkPass = false;
633                         if (pDevice->bEnableHostWEP)
634                                 BSSvClearNodeDBTable(pDevice, 1);
635                         else
636                                 BSSvClearNodeDBTable(pDevice, 0);
637                         pDevice->uAssocCount = 0;
638                         pMgmt->eCurrState = WMAC_STATE_IDLE;
639                         pDevice->bFixRate = false;
640
641                         // alway turn off unicast bit
642                         MACvRegBitsOff(pDevice->PortOffset, MAC_REG_RCR, RCR_UNICAST);
643                         pDevice->byRxMode &= ~RCR_UNICAST;
644                         pr_debug("wcmd: rx_mode = %x\n", pDevice->byRxMode);
645                         BSSvAddMulticastNode(pDevice);
646                         if (netif_queue_stopped(pDevice->dev))
647                                 netif_wake_queue(pDevice->dev);
648
649                         pDevice->bLinkPass = true;
650                         add_timer(&pMgmt->sTimerSecondCallback);
651                 }
652                 s_bCommandComplete(pDevice);
653                 break;
654
655         case WLAN_CMD_TX_PSPACKET_START:
656                 // DTIM Multicast tx
657                 if (pMgmt->sNodeDBTable[0].bRxPSPoll) {
658                         while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[0].sTxPSQueue)) != NULL) {
659                                 if (skb_queue_empty(&pMgmt->sNodeDBTable[0].sTxPSQueue)) {
660                                         pMgmt->abyPSTxMap[0] &= ~byMask[0];
661                                         pDevice->bMoreData = false;
662                                 } else {
663                                         pDevice->bMoreData = true;
664                                 }
665
666                                 pMgmt->sNodeDBTable[0].wEnQueueCnt--;
667                         }
668                 }
669
670                 // PS nodes tx
671                 for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) {
672                         if (pMgmt->sNodeDBTable[ii].bActive &&
673                             pMgmt->sNodeDBTable[ii].bRxPSPoll) {
674                                 pr_debug("Index=%d Enqueu Cnt= %d\n",
675                                          ii,
676                                          pMgmt->sNodeDBTable[ii].wEnQueueCnt);
677                                 while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) != NULL) {
678                                         if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) {
679                                                 // clear tx map
680                                                 pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &=
681                                                         ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7];
682                                                 pDevice->bMoreData = false;
683                                         } else {
684                                                 pDevice->bMoreData = true;
685                                         }
686
687                                         pMgmt->sNodeDBTable[ii].wEnQueueCnt--;
688                                         // check if sta ps enabled, and wait next pspoll.
689                                         // if sta ps disable, then send all pending buffers.
690                                         if (pMgmt->sNodeDBTable[ii].bPSEnable)
691                                                 break;
692                                 }
693                                 if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) {
694                                         // clear tx map
695                                         pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &=
696                                                 ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7];
697                                         pr_debug("Index=%d PS queue clear\n",
698                                                  ii);
699                                 }
700                                 pMgmt->sNodeDBTable[ii].bRxPSPoll = false;
701                         }
702                 }
703
704                 s_bCommandComplete(pDevice);
705                 break;
706
707         case WLAN_CMD_RADIO_START:
708                 pr_debug("eCommandState == WLAN_CMD_RADIO_START\n");
709                 if (pDevice->bRadioCmd)
710                         CARDbRadioPowerOn(pDevice);
711                 else
712                         CARDbRadioPowerOff(pDevice);
713
714                 s_bCommandComplete(pDevice);
715                 break;
716
717         case WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE:
718                 // wait all TD complete
719                 if (pDevice->iTDUsed[TYPE_AC0DMA] != 0) {
720                         vCommandTimerWait((void *)pDevice, 10);
721                         spin_unlock_irq(&pDevice->lock);
722                         return;
723                 }
724                 if (pDevice->iTDUsed[TYPE_TXDMA0] != 0) {
725                         vCommandTimerWait((void *)pDevice, 10);
726                         spin_unlock_irq(&pDevice->lock);
727                         return;
728                 }
729                 pDevice->byBBVGACurrent = pDevice->byBBVGANew;
730                 BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent);
731                 pr_debug("SetVGAGainOffset %02X\n", pDevice->byBBVGACurrent);
732                 s_bCommandComplete(pDevice);
733                 break;
734
735         default:
736                 s_bCommandComplete(pDevice);
737                 break;
738
739         } //switch
740         spin_unlock_irq(&pDevice->lock);
741 }
742
743 static
744 bool
745 s_bCommandComplete(
746         struct vnt_private *pDevice
747 )
748 {
749         PWLAN_IE_SSID pSSID;
750         bool bRadioCmd = false;
751         bool bForceSCAN = true;
752         PSMgmtObject  pMgmt = pDevice->pMgmt;
753
754         pDevice->eCommandState = WLAN_CMD_IDLE;
755         if (pDevice->cbFreeCmdQueue == CMD_Q_SIZE) {
756                 //Command Queue Empty
757                 pDevice->bCmdRunning = false;
758                 return true;
759         } else {
760                 pDevice->eCommand = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].eCmd;
761                 pSSID = (PWLAN_IE_SSID)pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].abyCmdDesireSSID;
762                 bRadioCmd = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bRadioCmd;
763                 bForceSCAN = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bForceSCAN;
764                 ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdDequeueIdx, CMD_Q_SIZE);
765                 pDevice->cbFreeCmdQueue++;
766                 pDevice->bCmdRunning = true;
767                 switch (pDevice->eCommand) {
768                 case WLAN_CMD_BSSID_SCAN:
769                         pr_debug("eCommandState= WLAN_CMD_BSSID_SCAN\n");
770                         pDevice->eCommandState = WLAN_CMD_SCAN_START;
771                         pMgmt->uScanChannel = 0;
772                         if (pSSID->len != 0)
773                                 memcpy(pMgmt->abyScanSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
774                         else
775                                 memset(pMgmt->abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
776
777                         break;
778                 case WLAN_CMD_SSID:
779                         pDevice->eCommandState = WLAN_CMD_SSID_START;
780                         if (pSSID->len > WLAN_SSID_MAXLEN)
781                                 pSSID->len = WLAN_SSID_MAXLEN;
782                         if (pSSID->len != 0)
783                                 memcpy(pDevice->pMgmt->abyDesireSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
784                         pr_debug("eCommandState= WLAN_CMD_SSID_START\n");
785                         break;
786                 case WLAN_CMD_DISASSOCIATE:
787                         pDevice->eCommandState = WLAN_CMD_DISASSOCIATE_START;
788                         break;
789                 case WLAN_CMD_RX_PSPOLL:
790                         pDevice->eCommandState = WLAN_CMD_TX_PSPACKET_START;
791                         break;
792                 case WLAN_CMD_RUN_AP:
793                         pDevice->eCommandState = WLAN_CMD_AP_MODE_START;
794                         break;
795                 case WLAN_CMD_RADIO:
796                         pDevice->eCommandState = WLAN_CMD_RADIO_START;
797                         pDevice->bRadioCmd = bRadioCmd;
798                         break;
799                 case WLAN_CMD_CHANGE_BBSENSITIVITY:
800                         pDevice->eCommandState = WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE;
801                         break;
802
803                 default:
804                         break;
805
806                 }
807
808                 vCommandTimerWait((void *)pDevice, 0);
809         }
810
811         return true;
812 }
813
814 bool bScheduleCommand(
815         void *hDeviceContext,
816         CMD_CODE    eCommand,
817         unsigned char *pbyItem0
818 )
819 {
820         struct vnt_private *pDevice = hDeviceContext;
821
822         if (pDevice->cbFreeCmdQueue == 0)
823                 return false;
824
825         pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].eCmd = eCommand;
826         pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = true;
827         memset(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, 0 , WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
828
829         if (pbyItem0 != NULL) {
830                 switch (eCommand) {
831                 case WLAN_CMD_BSSID_SCAN:
832                         memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID,
833                                pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
834                         pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = false;
835                         break;
836
837                 case WLAN_CMD_SSID:
838                         memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID,
839                                pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
840                         break;
841
842                 case WLAN_CMD_DISASSOCIATE:
843                         pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bNeedRadioOFF = *((int *)pbyItem0);
844                         break;
845
846                 case WLAN_CMD_RX_PSPOLL:
847                         break;
848
849                 case WLAN_CMD_RADIO:
850                         pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bRadioCmd = *((int *)pbyItem0);
851                         break;
852
853                 case WLAN_CMD_CHANGE_BBSENSITIVITY:
854                         pDevice->eCommandState = WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE;
855                         break;
856
857                 default:
858                         break;
859                 }
860         }
861
862         ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdEnqueueIdx, CMD_Q_SIZE);
863         pDevice->cbFreeCmdQueue--;
864
865         if (!pDevice->bCmdRunning)
866                 s_bCommandComplete(pDevice);
867
868         return true;
869 }
870
871 /*
872  * Description:
873  *      Clear BSSID_SCAN cmd in CMD Queue
874  *
875  * Parameters:
876  *  In:
877  *      hDeviceContext  - Pointer to the adapter
878  *      eCommand        - Command
879  *  Out:
880  *      none
881  *
882  * Return Value: true if success; otherwise false
883  *
884  */
885 bool bClearBSSID_SCAN(
886         void *hDeviceContext
887 )
888 {
889         struct vnt_private *pDevice = hDeviceContext;
890         unsigned int uCmdDequeueIdx = pDevice->uCmdDequeueIdx;
891         unsigned int ii;
892
893         if ((pDevice->cbFreeCmdQueue < CMD_Q_SIZE) && (uCmdDequeueIdx != pDevice->uCmdEnqueueIdx)) {
894                 for (ii = 0; ii < (CMD_Q_SIZE - pDevice->cbFreeCmdQueue); ii++) {
895                         if (pDevice->eCmdQueue[uCmdDequeueIdx].eCmd == WLAN_CMD_BSSID_SCAN)
896                                 pDevice->eCmdQueue[uCmdDequeueIdx].eCmd = WLAN_CMD_IDLE;
897                         ADD_ONE_WITH_WRAP_AROUND(uCmdDequeueIdx, CMD_Q_SIZE);
898                         if (uCmdDequeueIdx == pDevice->uCmdEnqueueIdx)
899                                 break;
900                 }
901         }
902         return true;
903 }
904
905 //mike add:reset command timer
906 void
907 vResetCommandTimer(
908         void *hDeviceContext
909 )
910 {
911         struct vnt_private *pDevice = hDeviceContext;
912
913         //delete timer
914         del_timer(&pDevice->sTimerCommand);
915         //init timer
916         init_timer(&pDevice->sTimerCommand);
917         pDevice->sTimerCommand.data = (unsigned long) pDevice;
918         pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer;
919         pDevice->sTimerCommand.expires = RUN_AT(HZ);
920         pDevice->cbFreeCmdQueue = CMD_Q_SIZE;
921         pDevice->uCmdDequeueIdx = 0;
922         pDevice->uCmdEnqueueIdx = 0;
923         pDevice->eCommandState = WLAN_CMD_IDLE;
924         pDevice->bCmdRunning = false;
925         pDevice->bCmdClear = false;
926 }
927
928 void
929 BSSvSecondTxData(
930         void *hDeviceContext
931 )
932 {
933         struct vnt_private *pDevice = hDeviceContext;
934         PSMgmtObject  pMgmt = &(pDevice->sMgmtObj);
935
936         pDevice->nTxDataTimeCout++;
937
938         if (pDevice->nTxDataTimeCout < 4)     //don't tx data if timer less than 40s
939         {
940                 pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
941                 add_timer(&pDevice->sTimerTxData);
942                 return;
943         }
944
945         spin_lock_irq(&pDevice->lock);
946
947         /* open && sharekey linking */
948         if ((pDevice->bLinkPass && (pMgmt->eAuthenMode < WMAC_AUTH_WPA)) ||
949             pDevice->fWPA_Authened) {   /* wpa linking */
950                 pDevice->fTxDataInSleep = true;
951                 pDevice->fTxDataInSleep = false;
952         }
953
954         spin_unlock_irq(&pDevice->lock);
955
956         pDevice->sTimerTxData.expires = RUN_AT(10*HZ); /* 10s callback */
957         add_timer(&pDevice->sTimerTxData);
958 }