Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.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         WLAN_FR_PROBEREQ    sFrame;
248
249         pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
250         memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_PROBEREQ_FR_MAXLEN);
251         pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
252         sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
253         sFrame.len = WLAN_PROBEREQ_FR_MAXLEN;
254         vMgrEncodeProbeRequest(&sFrame);
255         sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
256                 (
257                         WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
258                         WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PROBEREQ)
259 ));
260         memcpy(sFrame.pHdr->sA3.abyAddr1, pScanBSSID, WLAN_ADDR_LEN);
261         memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
262         memcpy(sFrame.pHdr->sA3.abyAddr3, pScanBSSID, WLAN_BSSID_LEN);
263         // Copy the SSID, pSSID->len=0 indicate broadcast SSID
264         sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len);
265         sFrame.len += pSSID->len + WLAN_IEHDR_LEN;
266         memcpy(sFrame.pSSID, pSSID, pSSID->len + WLAN_IEHDR_LEN);
267         sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
268         sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN;
269         memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN);
270         // Copy the extension rate set
271         if (pDevice->eCurrentPHYType == PHY_TYPE_11G) {
272                 sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
273                 sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN;
274                 memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN);
275         }
276         pTxPacket->cbMPDULen = sFrame.len;
277         pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
278
279         return pTxPacket;
280 }
281
282 void
283 vCommandTimerWait(
284         void *hDeviceContext,
285         unsigned int MSecond
286 )
287 {
288         struct vnt_private *pDevice = hDeviceContext;
289
290         init_timer(&pDevice->sTimerCommand);
291         pDevice->sTimerCommand.data = (unsigned long) pDevice;
292         pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer;
293         // RUN_AT :1 msec ~= (HZ/1024)
294         pDevice->sTimerCommand.expires = (unsigned int)RUN_AT((MSecond * HZ) >> 10);
295         add_timer(&pDevice->sTimerCommand);
296 }
297
298 void
299 vCommandTimer(
300         void *hDeviceContext
301 )
302 {
303         struct vnt_private *pDevice = hDeviceContext;
304         PSMgmtObject    pMgmt = pDevice->pMgmt;
305         PWLAN_IE_SSID   pItemSSID;
306         PWLAN_IE_SSID   pItemSSIDCurr;
307         CMD_STATUS      Status;
308         unsigned int ii;
309         unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
310         struct sk_buff  *skb;
311
312         if (pDevice->dwDiagRefCount != 0)
313                 return;
314         if (!pDevice->bCmdRunning)
315                 return;
316
317         spin_lock_irq(&pDevice->lock);
318
319         switch (pDevice->eCommandState) {
320         case WLAN_CMD_SCAN_START:
321
322                 pDevice->byReAssocCount = 0;
323                 if (pDevice->bRadioOff) {
324                         s_bCommandComplete(pDevice);
325                         spin_unlock_irq(&pDevice->lock);
326                         return;
327                 }
328
329                 if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
330                         s_bCommandComplete(pDevice);
331                         CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_AP);
332                         spin_unlock_irq(&pDevice->lock);
333                         return;
334                 }
335
336                 pr_debug("eCommandState= WLAN_CMD_SCAN_START\n");
337                 pItemSSID = (PWLAN_IE_SSID)pMgmt->abyScanSSID;
338                 // wait all Data TD complete
339                 if (pDevice->iTDUsed[TYPE_AC0DMA] != 0) {
340                         spin_unlock_irq(&pDevice->lock);
341                         vCommandTimerWait((void *)pDevice, 10);
342                         return;
343                 }
344
345                 if (pMgmt->uScanChannel == 0) {
346                         pMgmt->uScanChannel = pDevice->byMinChannel;
347                         // Set Baseband to be more sensitive.
348
349                 }
350                 if (pMgmt->uScanChannel > pDevice->byMaxChannel) {
351                         pMgmt->eScanState = WMAC_NO_SCANNING;
352
353                         // Set Baseband's sensitivity back.
354                         // Set channel back
355                         set_channel(pMgmt->pAdapter, pMgmt->uCurrChannel);
356                         pr_debug("Scanning, set back to channel: [%d]\n",
357                                  pMgmt->uCurrChannel);
358                         if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)
359                                 CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_ADHOC);
360                         else
361                                 CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_STATION);
362
363                         vAdHocBeaconRestart(pDevice);
364                         s_bCommandComplete(pDevice);
365
366                 } else {
367 //2008-8-4 <add> by chester
368                         if (!is_channel_valid(pMgmt->uScanChannel)) {
369                                 pr_debug("Invalid channel pMgmt->uScanChannel = %d\n",
370                                          pMgmt->uScanChannel);
371                                 s_bCommandComplete(pDevice);
372                                 spin_unlock_irq(&pDevice->lock);
373                                 return;
374                         }
375                         if (pMgmt->uScanChannel == pDevice->byMinChannel) {
376                                 pMgmt->abyScanBSSID[0] = 0xFF;
377                                 pMgmt->abyScanBSSID[1] = 0xFF;
378                                 pMgmt->abyScanBSSID[2] = 0xFF;
379                                 pMgmt->abyScanBSSID[3] = 0xFF;
380                                 pMgmt->abyScanBSSID[4] = 0xFF;
381                                 pMgmt->abyScanBSSID[5] = 0xFF;
382                                 pItemSSID->byElementID = WLAN_EID_SSID;
383                                 pMgmt->eScanState = WMAC_IS_SCANNING;
384
385                         }
386
387                         vAdHocBeaconStop(pDevice);
388
389                         if (set_channel(pMgmt->pAdapter, pMgmt->uScanChannel))
390                                 pr_debug("SCAN Channel: %d\n",
391                                          pMgmt->uScanChannel);
392                         else
393                                 pr_debug("SET SCAN Channel Fail: %d\n",
394                                          pMgmt->uScanChannel);
395
396                         CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_UNSPECIFIED);
397                         pMgmt->uScanChannel++;
398 //2008-8-4 <modify> by chester
399                         if (!is_channel_valid(pMgmt->uScanChannel) &&
400                             pMgmt->uScanChannel <= pDevice->byMaxChannel) {
401                                 pMgmt->uScanChannel = pDevice->byMaxChannel + 1;
402                                 pMgmt->eCommandState = WLAN_CMD_SCAN_END;
403
404                         }
405
406                         if (!pMgmt->b11hEnable ||
407                             (pMgmt->uScanChannel < CB_MAX_CHANNEL_24G)) {
408                                 s_vProbeChannel(pDevice);
409                                 spin_unlock_irq(&pDevice->lock);
410                                 vCommandTimerWait((void *)pDevice, WCMD_ACTIVE_SCAN_TIME);
411                                 return;
412                         } else {
413                                 spin_unlock_irq(&pDevice->lock);
414                                 vCommandTimerWait((void *)pDevice, WCMD_PASSIVE_SCAN_TIME);
415                                 return;
416                         }
417
418                 }
419
420                 break;
421
422         case WLAN_CMD_SCAN_END:
423
424                 // Set Baseband's sensitivity back.
425                 // Set channel back
426                 set_channel(pMgmt->pAdapter, pMgmt->uCurrChannel);
427                 pr_debug("Scanning, set back to channel: [%d]\n",
428                          pMgmt->uCurrChannel);
429                 if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)
430                         CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_ADHOC);
431                 else
432                         CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_STATION);
433
434                 pMgmt->eScanState = WMAC_NO_SCANNING;
435                 vAdHocBeaconRestart(pDevice);
436 //2008-0409-07, <Add> by Einsn Liu
437 #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
438                 if (pMgmt->eScanType == WMAC_SCAN_PASSIVE) {
439                         //send scan event to wpa_Supplicant
440                         union iwreq_data wrqu;
441
442                         memset(&wrqu, 0, sizeof(wrqu));
443                         wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL);
444                 }
445 #endif
446                 s_bCommandComplete(pDevice);
447                 break;
448
449         case WLAN_CMD_DISASSOCIATE_START:
450                 pDevice->byReAssocCount = 0;
451                 if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
452                     (pMgmt->eCurrState != WMAC_STATE_ASSOC)) {
453                         s_bCommandComplete(pDevice);
454                         spin_unlock_irq(&pDevice->lock);
455                         return;
456                 } else {
457                         pr_debug("Send Disassociation Packet..\n");
458                         // reason = 8 : disassoc because sta has left
459                         vMgrDisassocBeginSta((void *)pDevice, pMgmt, pMgmt->abyCurrBSSID, (8), &Status);
460                         pDevice->bLinkPass = false;
461                         // unlock command busy
462                         pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
463                         pItemSSID->len = 0;
464                         memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN);
465                         pMgmt->eCurrState = WMAC_STATE_IDLE;
466                         pMgmt->sNodeDBTable[0].bActive = false;
467                 }
468                 netif_stop_queue(pDevice->dev);
469                 pDevice->eCommandState = WLAN_DISASSOCIATE_WAIT;
470                 // wait all Control TD complete
471                 if (pDevice->iTDUsed[TYPE_TXDMA0] != 0) {
472                         vCommandTimerWait((void *)pDevice, 10);
473                         spin_unlock_irq(&pDevice->lock);
474                         return;
475                 }
476                 pr_debug(" CARDbRadioPowerOff\n");
477                 //2008-09-02  <mark>    by chester
478                 s_bCommandComplete(pDevice);
479                 break;
480
481         case WLAN_DISASSOCIATE_WAIT:
482                 // wait all Control TD complete
483                 if (pDevice->iTDUsed[TYPE_TXDMA0] != 0) {
484                         vCommandTimerWait((void *)pDevice, 10);
485                         spin_unlock_irq(&pDevice->lock);
486                         return;
487                 }
488 //2008-09-02  <mark> by chester
489                 s_bCommandComplete(pDevice);
490                 break;
491
492         case WLAN_CMD_SSID_START:
493                 pDevice->byReAssocCount = 0;
494                 if (pDevice->bRadioOff) {
495                         s_bCommandComplete(pDevice);
496                         spin_unlock_irq(&pDevice->lock);
497                         return;
498                 }
499                 pr_debug("chester-abyDesireSSID=%s\n", ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySSID);
500                 pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
501                 pItemSSIDCurr = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
502                 pr_debug(" cmd: desire ssid = %s\n", pItemSSID->abySSID);
503                 pr_debug(" cmd: curr ssid = %s\n", pItemSSIDCurr->abySSID);
504
505                 if (pMgmt->eCurrState == WMAC_STATE_ASSOC) {
506                         pr_debug(" Cmd pMgmt->eCurrState == WMAC_STATE_ASSOC\n");
507                         pr_debug(" pItemSSID->len =%d\n", pItemSSID->len);
508                         pr_debug(" pItemSSIDCurr->len = %d\n",
509                                  pItemSSIDCurr->len);
510                         pr_debug(" desire ssid = %s\n", pItemSSID->abySSID);
511                         pr_debug(" curr ssid = %s\n", pItemSSIDCurr->abySSID);
512                 }
513
514                 if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) ||
515                     ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) {
516                         if (pItemSSID->len == pItemSSIDCurr->len) {
517                                 if (memcmp(pItemSSID->abySSID, pItemSSIDCurr->abySSID, pItemSSID->len) == 0) {
518                                         s_bCommandComplete(pDevice);
519                                         spin_unlock_irq(&pDevice->lock);
520                                         return;
521                                 }
522                         }
523
524                         netif_stop_queue(pDevice->dev);
525                         pDevice->bLinkPass = false;
526                 }
527                 // set initial state
528                 pMgmt->eCurrState = WMAC_STATE_IDLE;
529                 pMgmt->eCurrMode = WMAC_MODE_STANDBY;
530                 PSvDisablePowerSaving((void *)pDevice);
531                 BSSvClearNodeDBTable(pDevice, 0);
532
533                 vMgrJoinBSSBegin((void *)pDevice, &Status);
534                 // if Infra mode
535                 if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED)) {
536                         // Call mgr to begin the deauthentication
537                         // reason = (3) because sta has left ESS
538                         if (pMgmt->eCurrState >= WMAC_STATE_AUTH)
539                                 vMgrDeAuthenBeginSta((void *)pDevice, pMgmt, pMgmt->abyCurrBSSID, (3), &Status);
540
541                         // Call mgr to begin the authentication
542                         vMgrAuthenBeginSta((void *)pDevice, pMgmt, &Status);
543                         if (Status == CMD_STATUS_SUCCESS) {
544                                 pDevice->byLinkWaitCount = 0;
545                                 pDevice->eCommandState = WLAN_AUTHENTICATE_WAIT;
546                                 vCommandTimerWait((void *)pDevice, AUTHENTICATE_TIMEOUT);
547                                 spin_unlock_irq(&pDevice->lock);
548                                 pr_debug(" Set eCommandState = WLAN_AUTHENTICATE_WAIT\n");
549                                 return;
550                         }
551                 }
552                 // if Adhoc mode
553                 else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
554                         if (pMgmt->eCurrState == WMAC_STATE_JOINTED) {
555                                 if (netif_queue_stopped(pDevice->dev))
556                                         netif_wake_queue(pDevice->dev);
557
558                                 pDevice->bLinkPass = true;
559
560                                 pMgmt->sNodeDBTable[0].bActive = true;
561                                 pMgmt->sNodeDBTable[0].uInActiveCount = 0;
562                                 bClearBSSID_SCAN(pDevice);
563                         } else {
564                                 // start own IBSS
565                                 vMgrCreateOwnIBSS((void *)pDevice, &Status);
566                                 if (Status != CMD_STATUS_SUCCESS)
567                                         pr_debug(" WLAN_CMD_IBSS_CREATE fail !\n");
568
569                                 BSSvAddMulticastNode(pDevice);
570                         }
571                 }
572                 // if SSID not found
573                 else if (pMgmt->eCurrMode == WMAC_MODE_STANDBY) {
574                         if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA ||
575                             pMgmt->eConfigMode == WMAC_CONFIG_AUTO) {
576                                 // start own IBSS
577                                 vMgrCreateOwnIBSS((void *)pDevice, &Status);
578                                 if (Status != CMD_STATUS_SUCCESS)
579                                         pr_debug(" WLAN_CMD_IBSS_CREATE fail !\n");
580
581                                 BSSvAddMulticastNode(pDevice);
582                                 if (netif_queue_stopped(pDevice->dev))
583                                         netif_wake_queue(pDevice->dev);
584
585                                 pDevice->bLinkPass = true;
586                         } else {
587                                 pr_debug("Disconnect SSID none\n");
588 #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
589                                 {
590                                         union iwreq_data  wrqu;
591
592                                         memset(&wrqu, 0, sizeof(wrqu));
593                                         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
594                                         pr_debug("wireless_send_event--->SIOCGIWAP(disassociated:vMgrJoinBSSBegin Fail !!)\n");
595                                         wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
596                                 }
597 #endif
598
599                         }
600                 }
601                 s_bCommandComplete(pDevice);
602                 break;
603
604         case WLAN_AUTHENTICATE_WAIT:
605                 pr_debug("eCommandState == WLAN_AUTHENTICATE_WAIT\n");
606                 if (pMgmt->eCurrState == WMAC_STATE_AUTH) {
607                         // Call mgr to begin the association
608                         pDevice->byLinkWaitCount = 0;
609                         pr_debug("eCurrState == WMAC_STATE_AUTH\n");
610                         vMgrAssocBeginSta((void *)pDevice, pMgmt, &Status);
611                         if (Status == CMD_STATUS_SUCCESS) {
612                                 pDevice->byLinkWaitCount = 0;
613                                 pr_debug("eCommandState = WLAN_ASSOCIATE_WAIT\n");
614                                 pDevice->eCommandState = WLAN_ASSOCIATE_WAIT;
615                                 vCommandTimerWait((void *)pDevice, ASSOCIATE_TIMEOUT);
616                                 spin_unlock_irq(&pDevice->lock);
617                                 return;
618                         }
619                 }
620
621                 else if (pMgmt->eCurrState < WMAC_STATE_AUTHPENDING) {
622                         pr_debug("WLAN_AUTHENTICATE_WAIT:Authen Fail???\n");
623                 } else if (pDevice->byLinkWaitCount <= 4) {    //mike add:wait another 2 sec if authenticated_frame delay!
624                         pDevice->byLinkWaitCount++;
625                         pr_debug("WLAN_AUTHENTICATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount);
626                         spin_unlock_irq(&pDevice->lock);
627                         vCommandTimerWait((void *)pDevice, AUTHENTICATE_TIMEOUT/2);
628                         return;
629                 }
630                 pDevice->byLinkWaitCount = 0;
631                 s_bCommandComplete(pDevice);
632                 break;
633
634         case WLAN_ASSOCIATE_WAIT:
635                 if (pMgmt->eCurrState == WMAC_STATE_ASSOC) {
636                         pr_debug("eCurrState == WMAC_STATE_ASSOC\n");
637                         if (pDevice->ePSMode != WMAC_POWER_CAM)
638                                 PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval);
639
640                         if (pMgmt->eAuthenMode >= WMAC_AUTH_WPA)
641                                 KeybRemoveAllKey(&(pDevice->sKey), pDevice->abyBSSID, pDevice->PortOffset);
642
643                         pDevice->bLinkPass = true;
644                         pDevice->byLinkWaitCount = 0;
645                         pDevice->byReAssocCount = 0;
646                         bClearBSSID_SCAN(pDevice);
647                         if (pDevice->byFOETuning) {
648                                 BBvSetFOE(pDevice->PortOffset);
649                                 PSbSendNullPacket(pDevice);
650                         }
651                         if (netif_queue_stopped(pDevice->dev))
652                                 netif_wake_queue(pDevice->dev);
653
654                         if (pDevice->IsTxDataTrigger) {    //TxDataTimer is not triggered at the first time
655                                 del_timer(&pDevice->sTimerTxData);
656                                 init_timer(&pDevice->sTimerTxData);
657                                 pDevice->sTimerTxData.data = (unsigned long) pDevice;
658                                 pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData;
659                                 pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
660                                 pDevice->fTxDataInSleep = false;
661                                 pDevice->nTxDataTimeCout = 0;
662                         }
663
664                         pDevice->IsTxDataTrigger = true;
665                         add_timer(&pDevice->sTimerTxData);
666
667                 } else if (pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) {
668                         printk("WLAN_ASSOCIATE_WAIT:Association Fail???\n");
669                 } else if (pDevice->byLinkWaitCount <= 4) {    //mike add:wait another 2 sec if associated_frame delay!
670                         pDevice->byLinkWaitCount++;
671                         pr_debug("WLAN_ASSOCIATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount);
672                         spin_unlock_irq(&pDevice->lock);
673                         vCommandTimerWait((void *)pDevice, ASSOCIATE_TIMEOUT/2);
674                         return;
675                 }
676                 pDevice->byLinkWaitCount = 0;
677
678                 s_bCommandComplete(pDevice);
679                 break;
680
681         case WLAN_CMD_AP_MODE_START:
682                 pr_debug("eCommandState == WLAN_CMD_AP_MODE_START\n");
683
684                 if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
685                         del_timer(&pMgmt->sTimerSecondCallback);
686                         pMgmt->eCurrState = WMAC_STATE_IDLE;
687                         pMgmt->eCurrMode = WMAC_MODE_STANDBY;
688                         pDevice->bLinkPass = false;
689                         if (pDevice->bEnableHostWEP)
690                                 BSSvClearNodeDBTable(pDevice, 1);
691                         else
692                                 BSSvClearNodeDBTable(pDevice, 0);
693                         pDevice->uAssocCount = 0;
694                         pMgmt->eCurrState = WMAC_STATE_IDLE;
695                         pDevice->bFixRate = false;
696
697                         vMgrCreateOwnIBSS((void *)pDevice, &Status);
698                         if (Status != CMD_STATUS_SUCCESS)
699                                 pr_debug(" vMgrCreateOwnIBSS fail !\n");
700
701                         // alway turn off unicast bit
702                         MACvRegBitsOff(pDevice->PortOffset, MAC_REG_RCR, RCR_UNICAST);
703                         pDevice->byRxMode &= ~RCR_UNICAST;
704                         pr_debug("wcmd: rx_mode = %x\n", pDevice->byRxMode);
705                         BSSvAddMulticastNode(pDevice);
706                         if (netif_queue_stopped(pDevice->dev))
707                                 netif_wake_queue(pDevice->dev);
708
709                         pDevice->bLinkPass = true;
710                         add_timer(&pMgmt->sTimerSecondCallback);
711                 }
712                 s_bCommandComplete(pDevice);
713                 break;
714
715         case WLAN_CMD_TX_PSPACKET_START:
716                 // DTIM Multicast tx
717                 if (pMgmt->sNodeDBTable[0].bRxPSPoll) {
718                         while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[0].sTxPSQueue)) != NULL) {
719                                 if (skb_queue_empty(&pMgmt->sNodeDBTable[0].sTxPSQueue)) {
720                                         pMgmt->abyPSTxMap[0] &= ~byMask[0];
721                                         pDevice->bMoreData = false;
722                                 } else {
723                                         pDevice->bMoreData = true;
724                                 }
725                                 if (!device_dma0_xmit(pDevice, skb, 0))
726                                         pr_debug("Multicast ps tx fail\n");
727
728                                 pMgmt->sNodeDBTable[0].wEnQueueCnt--;
729                         }
730                 }
731
732                 // PS nodes tx
733                 for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) {
734                         if (pMgmt->sNodeDBTable[ii].bActive &&
735                             pMgmt->sNodeDBTable[ii].bRxPSPoll) {
736                                 pr_debug("Index=%d Enqueu Cnt= %d\n",
737                                          ii,
738                                          pMgmt->sNodeDBTable[ii].wEnQueueCnt);
739                                 while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) != NULL) {
740                                         if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) {
741                                                 // clear tx map
742                                                 pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &=
743                                                         ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7];
744                                                 pDevice->bMoreData = false;
745                                         } else {
746                                                 pDevice->bMoreData = true;
747                                         }
748                                         if (!device_dma0_xmit(pDevice, skb, ii))
749                                                 pr_debug("sta ps tx fail\n");
750
751                                         pMgmt->sNodeDBTable[ii].wEnQueueCnt--;
752                                         // check if sta ps enabled, and wait next pspoll.
753                                         // if sta ps disable, then send all pending buffers.
754                                         if (pMgmt->sNodeDBTable[ii].bPSEnable)
755                                                 break;
756                                 }
757                                 if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) {
758                                         // clear tx map
759                                         pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &=
760                                                 ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7];
761                                         pr_debug("Index=%d PS queue clear\n",
762                                                  ii);
763                                 }
764                                 pMgmt->sNodeDBTable[ii].bRxPSPoll = false;
765                         }
766                 }
767
768                 s_bCommandComplete(pDevice);
769                 break;
770
771         case WLAN_CMD_RADIO_START:
772                 pr_debug("eCommandState == WLAN_CMD_RADIO_START\n");
773                 if (pDevice->bRadioCmd)
774                         CARDbRadioPowerOn(pDevice);
775                 else
776                         CARDbRadioPowerOff(pDevice);
777
778                 s_bCommandComplete(pDevice);
779                 break;
780
781         case WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE:
782                 // wait all TD complete
783                 if (pDevice->iTDUsed[TYPE_AC0DMA] != 0) {
784                         vCommandTimerWait((void *)pDevice, 10);
785                         spin_unlock_irq(&pDevice->lock);
786                         return;
787                 }
788                 if (pDevice->iTDUsed[TYPE_TXDMA0] != 0) {
789                         vCommandTimerWait((void *)pDevice, 10);
790                         spin_unlock_irq(&pDevice->lock);
791                         return;
792                 }
793                 pDevice->byBBVGACurrent = pDevice->byBBVGANew;
794                 BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent);
795                 pr_debug("SetVGAGainOffset %02X\n", pDevice->byBBVGACurrent);
796                 s_bCommandComplete(pDevice);
797                 break;
798
799         default:
800                 s_bCommandComplete(pDevice);
801                 break;
802
803         } //switch
804         spin_unlock_irq(&pDevice->lock);
805 }
806
807 static
808 bool
809 s_bCommandComplete(
810         struct vnt_private *pDevice
811 )
812 {
813         PWLAN_IE_SSID pSSID;
814         bool bRadioCmd = false;
815         bool bForceSCAN = true;
816         PSMgmtObject  pMgmt = pDevice->pMgmt;
817
818         pDevice->eCommandState = WLAN_CMD_IDLE;
819         if (pDevice->cbFreeCmdQueue == CMD_Q_SIZE) {
820                 //Command Queue Empty
821                 pDevice->bCmdRunning = false;
822                 return true;
823         } else {
824                 pDevice->eCommand = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].eCmd;
825                 pSSID = (PWLAN_IE_SSID)pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].abyCmdDesireSSID;
826                 bRadioCmd = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bRadioCmd;
827                 bForceSCAN = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bForceSCAN;
828                 ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdDequeueIdx, CMD_Q_SIZE);
829                 pDevice->cbFreeCmdQueue++;
830                 pDevice->bCmdRunning = true;
831                 switch (pDevice->eCommand) {
832                 case WLAN_CMD_BSSID_SCAN:
833                         pr_debug("eCommandState= WLAN_CMD_BSSID_SCAN\n");
834                         pDevice->eCommandState = WLAN_CMD_SCAN_START;
835                         pMgmt->uScanChannel = 0;
836                         if (pSSID->len != 0)
837                                 memcpy(pMgmt->abyScanSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
838                         else
839                                 memset(pMgmt->abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
840
841                         break;
842                 case WLAN_CMD_SSID:
843                         pDevice->eCommandState = WLAN_CMD_SSID_START;
844                         if (pSSID->len > WLAN_SSID_MAXLEN)
845                                 pSSID->len = WLAN_SSID_MAXLEN;
846                         if (pSSID->len != 0)
847                                 memcpy(pDevice->pMgmt->abyDesireSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
848                         pr_debug("eCommandState= WLAN_CMD_SSID_START\n");
849                         break;
850                 case WLAN_CMD_DISASSOCIATE:
851                         pDevice->eCommandState = WLAN_CMD_DISASSOCIATE_START;
852                         break;
853                 case WLAN_CMD_RX_PSPOLL:
854                         pDevice->eCommandState = WLAN_CMD_TX_PSPACKET_START;
855                         break;
856                 case WLAN_CMD_RUN_AP:
857                         pDevice->eCommandState = WLAN_CMD_AP_MODE_START;
858                         break;
859                 case WLAN_CMD_RADIO:
860                         pDevice->eCommandState = WLAN_CMD_RADIO_START;
861                         pDevice->bRadioCmd = bRadioCmd;
862                         break;
863                 case WLAN_CMD_CHANGE_BBSENSITIVITY:
864                         pDevice->eCommandState = WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE;
865                         break;
866
867                 default:
868                         break;
869
870                 }
871
872                 vCommandTimerWait((void *)pDevice, 0);
873         }
874
875         return true;
876 }
877
878 bool bScheduleCommand(
879         void *hDeviceContext,
880         CMD_CODE    eCommand,
881         unsigned char *pbyItem0
882 )
883 {
884         struct vnt_private *pDevice = hDeviceContext;
885
886         if (pDevice->cbFreeCmdQueue == 0)
887                 return false;
888
889         pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].eCmd = eCommand;
890         pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = true;
891         memset(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, 0 , WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
892
893         if (pbyItem0 != NULL) {
894                 switch (eCommand) {
895                 case WLAN_CMD_BSSID_SCAN:
896                         memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID,
897                                pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
898                         pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = false;
899                         break;
900
901                 case WLAN_CMD_SSID:
902                         memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID,
903                                pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
904                         break;
905
906                 case WLAN_CMD_DISASSOCIATE:
907                         pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bNeedRadioOFF = *((int *)pbyItem0);
908                         break;
909
910                 case WLAN_CMD_RX_PSPOLL:
911                         break;
912
913                 case WLAN_CMD_RADIO:
914                         pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bRadioCmd = *((int *)pbyItem0);
915                         break;
916
917                 case WLAN_CMD_CHANGE_BBSENSITIVITY:
918                         pDevice->eCommandState = WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE;
919                         break;
920
921                 default:
922                         break;
923                 }
924         }
925
926         ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdEnqueueIdx, CMD_Q_SIZE);
927         pDevice->cbFreeCmdQueue--;
928
929         if (!pDevice->bCmdRunning)
930                 s_bCommandComplete(pDevice);
931
932         return true;
933 }
934
935 /*
936  * Description:
937  *      Clear BSSID_SCAN cmd in CMD Queue
938  *
939  * Parameters:
940  *  In:
941  *      hDeviceContext  - Pointer to the adapter
942  *      eCommand        - Command
943  *  Out:
944  *      none
945  *
946  * Return Value: true if success; otherwise false
947  *
948  */
949 bool bClearBSSID_SCAN(
950         void *hDeviceContext
951 )
952 {
953         struct vnt_private *pDevice = hDeviceContext;
954         unsigned int uCmdDequeueIdx = pDevice->uCmdDequeueIdx;
955         unsigned int ii;
956
957         if ((pDevice->cbFreeCmdQueue < CMD_Q_SIZE) && (uCmdDequeueIdx != pDevice->uCmdEnqueueIdx)) {
958                 for (ii = 0; ii < (CMD_Q_SIZE - pDevice->cbFreeCmdQueue); ii++) {
959                         if (pDevice->eCmdQueue[uCmdDequeueIdx].eCmd == WLAN_CMD_BSSID_SCAN)
960                                 pDevice->eCmdQueue[uCmdDequeueIdx].eCmd = WLAN_CMD_IDLE;
961                         ADD_ONE_WITH_WRAP_AROUND(uCmdDequeueIdx, CMD_Q_SIZE);
962                         if (uCmdDequeueIdx == pDevice->uCmdEnqueueIdx)
963                                 break;
964                 }
965         }
966         return true;
967 }
968
969 //mike add:reset command timer
970 void
971 vResetCommandTimer(
972         void *hDeviceContext
973 )
974 {
975         struct vnt_private *pDevice = hDeviceContext;
976
977         //delete timer
978         del_timer(&pDevice->sTimerCommand);
979         //init timer
980         init_timer(&pDevice->sTimerCommand);
981         pDevice->sTimerCommand.data = (unsigned long) pDevice;
982         pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer;
983         pDevice->sTimerCommand.expires = RUN_AT(HZ);
984         pDevice->cbFreeCmdQueue = CMD_Q_SIZE;
985         pDevice->uCmdDequeueIdx = 0;
986         pDevice->uCmdEnqueueIdx = 0;
987         pDevice->eCommandState = WLAN_CMD_IDLE;
988         pDevice->bCmdRunning = false;
989         pDevice->bCmdClear = false;
990 }
991
992 void
993 BSSvSecondTxData(
994         void *hDeviceContext
995 )
996 {
997         struct vnt_private *pDevice = hDeviceContext;
998         PSMgmtObject  pMgmt = &(pDevice->sMgmtObj);
999
1000         pDevice->nTxDataTimeCout++;
1001
1002         if (pDevice->nTxDataTimeCout < 4)     //don't tx data if timer less than 40s
1003         {
1004                 pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
1005                 add_timer(&pDevice->sTimerTxData);
1006                 return;
1007         }
1008
1009         spin_lock_irq(&pDevice->lock);
1010
1011         /* open && sharekey linking */
1012         if ((pDevice->bLinkPass && (pMgmt->eAuthenMode < WMAC_AUTH_WPA)) ||
1013             pDevice->fWPA_Authened) {   /* wpa linking */
1014                 pDevice->fTxDataInSleep = true;
1015                 PSbSendNullPacket(pDevice);     /* send null packet */
1016                 pDevice->fTxDataInSleep = false;
1017         }
1018
1019         spin_unlock_irq(&pDevice->lock);
1020
1021         pDevice->sTimerTxData.expires = RUN_AT(10*HZ); /* 10s callback */
1022         add_timer(&pDevice->sTimerTxData);
1023 }