linux/drivers/staging/vt6655/wcmd.c
<<
>>
Prefs
   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
  63static
  64void
  65s_vProbeChannel(
  66        struct vnt_private *pDevice
  67);
  68
  69static
  70PSTxMgmtPacket
  71s_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
  80static
  81bool
  82s_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 */
 103static
 104void
 105vAdHocBeaconStop(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 */
 150static
 151void
 152vAdHocBeaconRestart(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
 179static
 180void
 181s_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
 235static PSTxMgmtPacket
 236s_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
 282void
 283vCommandTimerWait(
 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
 298void
 299vCommandTimer(
 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
 807static
 808bool
 809s_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
 878bool 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 */
 949bool 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
 970void
 971vResetCommandTimer(
 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
 992void
 993BSSvSecondTxData(
 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}
1024