linux/drivers/staging/rt2860/sta/rtmp_data.c
<<
>>
Prefs
   1/*
   2 *************************************************************************
   3 * Ralink Tech Inc.
   4 * 5F., No.36, Taiyuan St., Jhubei City,
   5 * Hsinchu County 302,
   6 * Taiwan, R.O.C.
   7 *
   8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
   9 *
  10 * This program is free software; you can redistribute it and/or modify  *
  11 * it under the terms of the GNU General Public License as published by  *
  12 * the Free Software Foundation; either version 2 of the License, or     *
  13 * (at your option) any later version.                                   *
  14 *                                                                       *
  15 * This program is distributed in the hope that it will be useful,       *
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  18 * GNU General Public License for more details.                          *
  19 *                                                                       *
  20 * You should have received a copy of the GNU General Public License     *
  21 * along with this program; if not, write to the                         *
  22 * Free Software Foundation, Inc.,                                       *
  23 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  24 *                                                                       *
  25 *************************************************************************
  26
  27        Module Name:
  28        rtmp_data.c
  29
  30        Abstract:
  31        Data path subroutines
  32
  33        Revision History:
  34        Who             When                    What
  35        --------        ----------              ----------------------------------------------
  36        John                  Aug/17/04         major modification for RT2561/2661
  37        Jan Lee       Mar/17/06         major modification for RT2860 New Ring Design
  38*/
  39#include "../rt_config.h"
  40
  41
  42
  43VOID STARxEAPOLFrameIndicate(
  44        IN      PRTMP_ADAPTER   pAd,
  45        IN      MAC_TABLE_ENTRY *pEntry,
  46        IN      RX_BLK                  *pRxBlk,
  47        IN      UCHAR                   FromWhichBSSID)
  48{
  49        PRT28XX_RXD_STRUC       pRxD = &(pRxBlk->RxD);
  50        PRXWI_STRUC             pRxWI = pRxBlk->pRxWI;
  51        UCHAR                   *pTmpBuf;
  52
  53        if (pAd->StaCfg.WpaSupplicantUP)
  54        {
  55                // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
  56                // TBD : process fragmented EAPol frames
  57                {
  58                        // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
  59                        if ( pAd->StaCfg.IEEE8021X == TRUE &&
  60                                 (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
  61                        {
  62                                PUCHAR  Key;
  63                                UCHAR   CipherAlg;
  64                                int     idx = 0;
  65
  66                                DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
  67                                STA_PORT_SECURED(pAd);
  68
  69                if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
  70                {
  71                    idx = pAd->StaCfg.DesireSharedKeyId;
  72                    CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
  73                                        Key = pAd->StaCfg.DesireSharedKey[idx].Key;
  74
  75                    if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
  76                                {
  77#ifdef RT2860
  78                                                MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID];
  79
  80                                                // Set key material and cipherAlg to Asic
  81                                                AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
  82
  83                                                // Assign group key info
  84                                                RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
  85
  86                                                // Assign pairwise key info
  87                                                RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry);
  88
  89                        pAd->IndicateMediaState = NdisMediaStateConnected;
  90                        pAd->ExtraInfo = GENERAL_LINK_UP;
  91#endif
  92#ifdef RT2870
  93                                                union
  94                                                {
  95                                                        char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1];
  96                                                        NDIS_802_11_WEP keyinfo;
  97                                                }  WepKey;
  98                                                int len;
  99
 100
 101                                                NdisZeroMemory(&WepKey, sizeof(WepKey));
 102                                                len =pAd->StaCfg.DesireSharedKey[idx].KeyLen;
 103
 104                                                NdisMoveMemory(WepKey.keyinfo.KeyMaterial,
 105                                                        pAd->StaCfg.DesireSharedKey[idx].Key,
 106                                                        pAd->StaCfg.DesireSharedKey[idx].KeyLen);
 107
 108                                                WepKey.keyinfo.KeyIndex = 0x80000000 + idx;
 109                                                WepKey.keyinfo.KeyLength = len;
 110                                                pAd->SharedKey[BSS0][idx].KeyLen =(UCHAR) (len <= 5 ? 5 : 13);
 111
 112                                                pAd->IndicateMediaState = NdisMediaStateConnected;
 113                                                pAd->ExtraInfo = GENERAL_LINK_UP;
 114                                                // need to enqueue cmd to thread
 115                                                RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1);
 116#endif // RT2870 //
 117                                                // For Preventing ShardKey Table is cleared by remove key procedure.
 118                                        pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
 119                                                pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
 120                                                NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
 121                                                                           pAd->StaCfg.DesireSharedKey[idx].Key,
 122                                                                           pAd->StaCfg.DesireSharedKey[idx].KeyLen);
 123                                }
 124                                }
 125                        }
 126
 127                        Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
 128                        return;
 129                }
 130        }
 131        else
 132        {
 133                // Special DATA frame that has to pass to MLME
 134                //       1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
 135                //       2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
 136                {
 137                        pTmpBuf = pRxBlk->pData - LENGTH_802_11;
 138                        NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
 139                        REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
 140                        DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
 141                }
 142        }
 143
 144        RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
 145        return;
 146
 147}
 148
 149VOID STARxDataFrameAnnounce(
 150        IN      PRTMP_ADAPTER   pAd,
 151        IN      MAC_TABLE_ENTRY *pEntry,
 152        IN      RX_BLK                  *pRxBlk,
 153        IN      UCHAR                   FromWhichBSSID)
 154{
 155
 156        // non-EAP frame
 157        if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
 158        {
 159                {
 160                        // drop all non-EAP DATA frame before
 161                        // this client's Port-Access-Control is secured
 162                        if (pRxBlk->pHeader->FC.Wep)
 163                        {
 164                                // unsupported cipher suite
 165                                if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
 166                                {
 167                                        // release packet
 168                                        RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
 169                                        return;
 170                                }
 171                        }
 172                        else
 173                        {
 174                                // encryption in-use but receive a non-EAPOL clear text frame, drop it
 175                                if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
 176                                        (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
 177                                {
 178                                        // release packet
 179                                        RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
 180                                        return;
 181                                }
 182                        }
 183                }
 184                RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
 185                if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
 186                {
 187                        // Normal legacy, AMPDU or AMSDU
 188                        CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
 189
 190                }
 191                else
 192                {
 193                        // ARALINK
 194                        CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
 195                }
 196        }
 197        else
 198        {
 199                RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
 200
 201                if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
 202                {
 203                        Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
 204                }
 205                else
 206                {
 207                        // Determin the destination of the EAP frame
 208                        //  to WPA state machine or upper layer
 209                        STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
 210                }
 211        }
 212}
 213
 214
 215// For TKIP frame, calculate the MIC value
 216BOOLEAN STACheckTkipMICValue(
 217        IN      PRTMP_ADAPTER   pAd,
 218        IN      MAC_TABLE_ENTRY *pEntry,
 219        IN      RX_BLK                  *pRxBlk)
 220{
 221        PHEADER_802_11  pHeader = pRxBlk->pHeader;
 222        UCHAR                   *pData = pRxBlk->pData;
 223        USHORT                  DataSize = pRxBlk->DataSize;
 224        UCHAR                   UserPriority = pRxBlk->UserPriority;
 225        PCIPHER_KEY             pWpaKey;
 226        UCHAR                   *pDA, *pSA;
 227
 228        pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
 229
 230        pDA = pHeader->Addr1;
 231        if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
 232        {
 233                pSA = pHeader->Addr3;
 234        }
 235        else
 236        {
 237                pSA = pHeader->Addr2;
 238        }
 239
 240        if (RTMPTkipCompareMICValue(pAd,
 241                                                                pData,
 242                                                                pDA,
 243                                                                pSA,
 244                                                                pWpaKey->RxMic,
 245                                                                UserPriority,
 246                                                                DataSize) == FALSE)
 247        {
 248                DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
 249
 250                if (pAd->StaCfg.WpaSupplicantUP)
 251                {
 252                        WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
 253                }
 254                else
 255                {
 256                        RTMPReportMicError(pAd, pWpaKey);
 257                }
 258
 259                // release packet
 260                RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
 261                return FALSE;
 262        }
 263
 264        return TRUE;
 265}
 266
 267
 268//
 269// All Rx routines use RX_BLK structure to hande rx events
 270// It is very important to build pRxBlk attributes
 271//  1. pHeader pointer to 802.11 Header
 272//  2. pData pointer to payload including LLC (just skip Header)
 273//  3. set payload size including LLC to DataSize
 274//  4. set some flags with RX_BLK_SET_FLAG()
 275//
 276VOID STAHandleRxDataFrame(
 277        IN      PRTMP_ADAPTER   pAd,
 278        IN      RX_BLK                  *pRxBlk)
 279{
 280        PRT28XX_RXD_STRUC                               pRxD = &(pRxBlk->RxD);
 281        PRXWI_STRUC                                             pRxWI = pRxBlk->pRxWI;
 282        PHEADER_802_11                                  pHeader = pRxBlk->pHeader;
 283        PNDIS_PACKET                                    pRxPacket = pRxBlk->pRxPacket;
 284        BOOLEAN                                                 bFragment = FALSE;
 285        MAC_TABLE_ENTRY                         *pEntry = NULL;
 286        UCHAR                                                   FromWhichBSSID = BSS0;
 287        UCHAR                           UserPriority = 0;
 288
 289        {
 290                // before LINK UP, all DATA frames are rejected
 291                if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
 292                {
 293                        // release packet
 294                        RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
 295                        return;
 296                }
 297
 298                // Drop not my BSS frames
 299                if (pRxD->MyBss == 0)
 300                {
 301                        {
 302                                // release packet
 303                                RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
 304                                return;
 305                        }
 306                }
 307
 308                pAd->RalinkCounters.RxCountSinceLastNULL++;
 309                if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
 310                {
 311                        UCHAR *pData;
 312                        DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
 313
 314                        // Qos bit 4
 315                        pData = (PUCHAR)pHeader + LENGTH_802_11;
 316                        if ((*pData >> 4) & 0x01)
 317                        {
 318                                DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
 319                                pAd->CommonCfg.bInServicePeriod = FALSE;
 320
 321                                // Force driver to fall into sleep mode when rcv EOSP frame
 322                                if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
 323                                {
 324                                        USHORT  TbttNumToNextWakeUp;
 325                                        USHORT  NextDtim = pAd->StaCfg.DtimPeriod;
 326                                        ULONG   Now;
 327
 328                                        NdisGetSystemUpTime(&Now);
 329                                        NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
 330
 331                                        TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
 332                                        if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
 333                                                TbttNumToNextWakeUp = NextDtim;
 334
 335                                        MlmeSetPsmBit(pAd, PWR_SAVE);
 336                                        // if WMM-APSD is failed, try to disable following line
 337                                        AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
 338                                }
 339                        }
 340
 341                        if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
 342                        {
 343                                DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
 344                        }
 345                }
 346
 347                // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
 348                if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
 349                {
 350                        // release packet
 351                        RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
 352                        return;
 353                }
 354
 355            // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
 356
 357                if (INFRA_ON(pAd))
 358                {
 359                        // Infrastructure mode, check address 2 for BSSID
 360                        if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
 361                        {
 362                                // Receive frame not my BSSID
 363                    // release packet
 364                    RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
 365                                return;
 366                        }
 367                }
 368                else    // Ad-Hoc mode or Not associated
 369                {
 370                        // Ad-Hoc mode, check address 3 for BSSID
 371                        if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
 372                        {
 373                                // Receive frame not my BSSID
 374                    // release packet
 375                    RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
 376                                return;
 377                        }
 378                }
 379
 380                //
 381                // find pEntry
 382                //
 383                if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
 384                {
 385                        pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
 386                }
 387                else
 388                {
 389                        // 1. release packet if infra mode
 390                        // 2. new a pEntry if ad-hoc mode
 391                        RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
 392                        return;
 393                }
 394
 395                // infra or ad-hoc
 396                if (INFRA_ON(pAd))
 397                {
 398                        RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
 399                        ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
 400                }
 401
 402                // check Atheros Client
 403                if ((pEntry->bIAmBadAtheros == FALSE) &&  (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
 404                {
 405                        pEntry->bIAmBadAtheros = TRUE;
 406                        pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
 407                        pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
 408                        if (!STA_AES_ON(pAd))
 409                        {
 410                                AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
 411                        }
 412                }
 413        }
 414
 415        pRxBlk->pData = (UCHAR *)pHeader;
 416
 417        //
 418        // update RxBlk->pData, DataSize
 419        // 802.11 Header, QOS, HTC, Hw Padding
 420        //
 421
 422        // 1. skip 802.11 HEADER
 423        {
 424                pRxBlk->pData += LENGTH_802_11;
 425                pRxBlk->DataSize -= LENGTH_802_11;
 426        }
 427
 428        // 2. QOS
 429        if (pHeader->FC.SubType & 0x08)
 430        {
 431                RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
 432                UserPriority = *(pRxBlk->pData) & 0x0f;
 433                // bit 7 in QoS Control field signals the HT A-MSDU format
 434                if ((*pRxBlk->pData) & 0x80)
 435                {
 436                        RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
 437                }
 438
 439                // skip QOS contorl field
 440                pRxBlk->pData += 2;
 441                pRxBlk->DataSize -=2;
 442        }
 443        pRxBlk->UserPriority = UserPriority;
 444
 445        // 3. Order bit: A-Ralink or HTC+
 446        if (pHeader->FC.Order)
 447        {
 448#ifdef AGGREGATION_SUPPORT
 449                if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
 450                {
 451                        RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
 452                }
 453                else
 454#endif
 455                {
 456                        RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
 457                        // skip HTC contorl field
 458                        pRxBlk->pData += 4;
 459                        pRxBlk->DataSize -= 4;
 460                }
 461        }
 462
 463        // 4. skip HW padding
 464        if (pRxD->L2PAD)
 465        {
 466                // just move pData pointer
 467                // because DataSize excluding HW padding
 468                RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
 469                pRxBlk->pData += 2;
 470        }
 471
 472        if (pRxD->BA)
 473        {
 474                RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
 475        }
 476
 477        //
 478        // Case I  Process Broadcast & Multicast data frame
 479        //
 480        if (pRxD->Bcast || pRxD->Mcast)
 481        {
 482                INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
 483
 484                // Drop Mcast/Bcast frame with fragment bit on
 485                if (pHeader->FC.MoreFrag)
 486                {
 487                        // release packet
 488                        RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
 489                        return;
 490                }
 491
 492                // Filter out Bcast frame which AP relayed for us
 493                if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
 494                {
 495                        // release packet
 496                        RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
 497                        return;
 498                }
 499
 500                Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
 501                return;
 502        }
 503        else if (pRxD->U2M)
 504        {
 505                pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
 506
 507                if (ADHOC_ON(pAd))
 508                {
 509                        pEntry = MacTableLookup(pAd, pHeader->Addr2);
 510                        if (pEntry)
 511                                Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
 512                }
 513
 514
 515                Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
 516
 517                pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
 518                pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
 519
 520                pAd->RalinkCounters.OneSecRxOkDataCnt++;
 521
 522
 523        if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
 524        {
 525                // re-assemble the fragmented packets
 526                // return complete frame (pRxPacket) or NULL
 527                bFragment = TRUE;
 528                pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
 529        }
 530
 531        if (pRxPacket)
 532        {
 533                        pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
 534
 535                // process complete frame
 536                if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
 537                {
 538                                // Minus MIC length
 539                                pRxBlk->DataSize -= 8;
 540
 541                        // For TKIP frame, calculate the MIC value
 542                        if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
 543                        {
 544                                return;
 545                        }
 546                }
 547
 548                STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
 549                        return;
 550        }
 551        else
 552        {
 553                // just return
 554                // because RTMPDeFragmentDataFrame() will release rx packet,
 555                // if packet is fragmented
 556                return;
 557        }
 558        }
 559
 560        ASSERT(0);
 561        // release packet
 562        RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
 563}
 564
 565VOID STAHandleRxMgmtFrame(
 566        IN      PRTMP_ADAPTER   pAd,
 567        IN      RX_BLK                  *pRxBlk)
 568{
 569        PRT28XX_RXD_STRUC       pRxD = &(pRxBlk->RxD);
 570        PRXWI_STRUC             pRxWI = pRxBlk->pRxWI;
 571        PHEADER_802_11  pHeader = pRxBlk->pHeader;
 572        PNDIS_PACKET    pRxPacket = pRxBlk->pRxPacket;
 573
 574        do
 575        {
 576
 577                // We should collect RSSI not only U2M data but also my beacon
 578                if (pAd->RxAnt.EvaluatePeriod == 0 &&
 579                    pHeader->FC.SubType == SUBTYPE_BEACON &&
 580                    MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)) {
 581                        Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
 582
 583                        pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
 584                        pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
 585                }
 586
 587#ifdef RT2870
 588                // collect rssi information for antenna diversity
 589                if (pAd->NicConfig2.field.AntDiversity)
 590                {
 591                        if ((pRxD->U2M) || ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))))
 592                        {
 593                                        COLLECT_RX_ANTENNA_AVERAGE_RSSI(pAd, ConvertToRssi(pAd, (UCHAR)pRxWI->RSSI0, RSSI_0), 0); //Note: RSSI2 not used on RT73
 594                                        pAd->StaCfg.NumOfAvgRssiSample ++;
 595                        }
 596                }
 597#endif
 598
 599                // First check the size, it MUST not exceed the mlme queue size
 600                if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
 601                {
 602                        DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
 603                        break;
 604                }
 605
 606                REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
 607                                                                        pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
 608        } while (FALSE);
 609
 610        RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
 611}
 612
 613VOID STAHandleRxControlFrame(
 614        IN      PRTMP_ADAPTER   pAd,
 615        IN      RX_BLK                  *pRxBlk)
 616{
 617        PRXWI_STRUC             pRxWI = pRxBlk->pRxWI;
 618        PHEADER_802_11  pHeader = pRxBlk->pHeader;
 619        PNDIS_PACKET    pRxPacket = pRxBlk->pRxPacket;
 620
 621        switch (pHeader->FC.SubType)
 622        {
 623                case SUBTYPE_BLOCK_ACK_REQ:
 624                        {
 625                                CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
 626                        }
 627                        break;
 628                case SUBTYPE_BLOCK_ACK:
 629                case SUBTYPE_ACK:
 630                default:
 631                        break;
 632        }
 633
 634        RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
 635}
 636
 637
 638/*
 639        ========================================================================
 640
 641        Routine Description:
 642                Process RxDone interrupt, running in DPC level
 643
 644        Arguments:
 645                pAd Pointer to our adapter
 646
 647        Return Value:
 648                None
 649
 650        IRQL = DISPATCH_LEVEL
 651
 652        Note:
 653                This routine has to maintain Rx ring read pointer.
 654                Need to consider QOS DATA format when converting to 802.3
 655        ========================================================================
 656*/
 657BOOLEAN STARxDoneInterruptHandle(
 658        IN      PRTMP_ADAPTER   pAd,
 659        IN      BOOLEAN                 argc)
 660{
 661        NDIS_STATUS                     Status;
 662        UINT32                  RxProcessed, RxPending;
 663        BOOLEAN                 bReschedule = FALSE;
 664        RT28XX_RXD_STRUC        *pRxD;
 665        UCHAR                   *pData;
 666        PRXWI_STRUC             pRxWI;
 667        PNDIS_PACKET    pRxPacket;
 668        PHEADER_802_11  pHeader;
 669        RX_BLK                  RxCell;
 670
 671        RxProcessed = RxPending = 0;
 672
 673        // process whole rx ring
 674        while (1)
 675        {
 676
 677                if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
 678                                                                fRTMP_ADAPTER_RESET_IN_PROGRESS |
 679                                                                fRTMP_ADAPTER_HALT_IN_PROGRESS |
 680                                                                fRTMP_ADAPTER_NIC_NOT_EXIST) ||
 681                        !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
 682                {
 683                        break;
 684                }
 685
 686#ifdef RT2860
 687                if (RxProcessed++ > MAX_RX_PROCESS_CNT)
 688                {
 689                        // need to reschedule rx handle
 690                        bReschedule = TRUE;
 691                        break;
 692                }
 693#endif
 694
 695                RxProcessed ++; // test
 696
 697                // 1. allocate a new data packet into rx ring to replace received packet
 698                //    then processing the received packet
 699                // 2. the callee must take charge of release of packet
 700                // 3. As far as driver is concerned ,
 701                //    the rx packet must
 702                //      a. be indicated to upper layer or
 703                //      b. be released if it is discarded
 704                pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
 705                if (pRxPacket == NULL)
 706                {
 707                        // no more packet to process
 708                        break;
 709                }
 710
 711                // get rx ring descriptor
 712                pRxD = &(RxCell.RxD);
 713                // get rx data buffer
 714                pData   = GET_OS_PKT_DATAPTR(pRxPacket);
 715                pRxWI   = (PRXWI_STRUC) pData;
 716                pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
 717
 718                // build RxCell
 719                RxCell.pRxWI = pRxWI;
 720                RxCell.pHeader = pHeader;
 721                RxCell.pRxPacket = pRxPacket;
 722                RxCell.pData = (UCHAR *) pHeader;
 723                RxCell.DataSize = pRxWI->MPDUtotalByteCount;
 724                RxCell.Flags = 0;
 725
 726                // Increase Total receive byte counter after real data received no mater any error or not
 727                pAd->RalinkCounters.ReceivedByteCount +=  pRxWI->MPDUtotalByteCount;
 728                pAd->RalinkCounters.RxCount ++;
 729
 730                INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
 731
 732                if (pRxWI->MPDUtotalByteCount < 14)
 733                        Status = NDIS_STATUS_FAILURE;
 734
 735        if (MONITOR_ON(pAd))
 736                {
 737            send_monitor_packets(pAd, &RxCell);
 738                        break;
 739                }
 740                /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
 741
 742                // Check for all RxD errors
 743                Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
 744
 745                // Handle the received frame
 746                if (Status == NDIS_STATUS_SUCCESS)
 747                {
 748                        switch (pHeader->FC.Type)
 749                        {
 750                                // CASE I, receive a DATA frame
 751                                case BTYPE_DATA:
 752                                {
 753                                        // process DATA frame
 754                                        STAHandleRxDataFrame(pAd, &RxCell);
 755                                }
 756                                break;
 757                                // CASE II, receive a MGMT frame
 758                                case BTYPE_MGMT:
 759                                {
 760                                        STAHandleRxMgmtFrame(pAd, &RxCell);
 761                                }
 762                                break;
 763                                // CASE III. receive a CNTL frame
 764                                case BTYPE_CNTL:
 765                                {
 766                                        STAHandleRxControlFrame(pAd, &RxCell);
 767                                }
 768                                break;
 769                                // discard other type
 770                                default:
 771                                        RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
 772                                        break;
 773                        }
 774                }
 775                else
 776                {
 777                        pAd->Counters8023.RxErrors++;
 778                        // discard this frame
 779                        RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
 780                }
 781        }
 782
 783#ifdef RT2860
 784        // fRTMP_PS_GO_TO_SLEEP_NOW is set if receiving beacon.
 785        if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW) && (INFRA_ON(pAd)))
 786        {
 787                RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
 788                AsicSleepThenAutoWakeup(pAd, pAd->ThisTbttNumToNextWakeUp);
 789                bReschedule = FALSE;
 790        }
 791#endif
 792        return bReschedule;
 793}
 794
 795/*
 796        ========================================================================
 797
 798        Routine Description:
 799        Arguments:
 800                pAd     Pointer to our adapter
 801
 802        IRQL = DISPATCH_LEVEL
 803
 804        ========================================================================
 805*/
 806VOID    RTMPHandleTwakeupInterrupt(
 807        IN PRTMP_ADAPTER pAd)
 808{
 809#ifdef RT2860
 810        AsicForceWakeup(pAd, DOT11POWERSAVE);
 811#endif
 812#ifdef RT2870
 813        AsicForceWakeup(pAd, FALSE);
 814#endif
 815}
 816
 817/*
 818========================================================================
 819Routine Description:
 820    Early checking and OS-depened parsing for Tx packet send to our STA driver.
 821
 822Arguments:
 823    NDIS_HANDLE         MiniportAdapterContext  Pointer refer to the device handle, i.e., the pAd.
 824        PPNDIS_PACKET   ppPacketArray                   The packet array need to do transmission.
 825        UINT                    NumberOfPackets                 Number of packet in packet array.
 826
 827Return Value:
 828        NONE
 829
 830Note:
 831        This function do early checking and classification for send-out packet.
 832        You only can put OS-depened & STA related code in here.
 833========================================================================
 834*/
 835VOID STASendPackets(
 836        IN      NDIS_HANDLE             MiniportAdapterContext,
 837        IN      PPNDIS_PACKET   ppPacketArray,
 838        IN      UINT                    NumberOfPackets)
 839{
 840        UINT                    Index;
 841        PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
 842        PNDIS_PACKET    pPacket;
 843        BOOLEAN                 allowToSend = FALSE;
 844
 845
 846        for (Index = 0; Index < NumberOfPackets; Index++)
 847        {
 848                pPacket = ppPacketArray[Index];
 849
 850                do
 851                {
 852                        if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
 853                                RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
 854                                RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
 855                        {
 856                                // Drop send request since hardware is in reset state
 857                                        break;
 858                        }
 859                        else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
 860                        {
 861                                // Drop send request since there are no physical connection yet
 862                                        break;
 863                        }
 864                        else
 865                        {
 866                                // Record that orignal packet source is from NDIS layer,so that
 867                                // later on driver knows how to release this NDIS PACKET
 868                                RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
 869                                RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
 870                                NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
 871                                pAd->RalinkCounters.PendingNdisPacketCount++;
 872
 873                                allowToSend = TRUE;
 874                        }
 875                } while(FALSE);
 876
 877                if (allowToSend == TRUE)
 878                        STASendPacket(pAd, pPacket);
 879                else
 880                        RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
 881        }
 882
 883        // Dequeue outgoing frames from TxSwQueue[] and process it
 884        RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
 885
 886}
 887
 888
 889/*
 890========================================================================
 891Routine Description:
 892        This routine is used to do packet parsing and classification for Tx packet
 893        to STA device, and it will en-queue packets to our TxSwQueue depends on AC
 894        class.
 895
 896Arguments:
 897        pAd             Pointer to our adapter
 898        pPacket         Pointer to send packet
 899
 900Return Value:
 901        NDIS_STATUS_SUCCESS                     If succes to queue the packet into TxSwQueue.
 902        NDIS_STATUS_FAILURE                     If failed to do en-queue.
 903
 904Note:
 905        You only can put OS-indepened & STA related code in here.
 906========================================================================
 907*/
 908NDIS_STATUS STASendPacket(
 909        IN      PRTMP_ADAPTER   pAd,
 910        IN      PNDIS_PACKET    pPacket)
 911{
 912        PACKET_INFO     PacketInfo;
 913        PUCHAR                  pSrcBufVA;
 914        UINT                    SrcBufLen;
 915        UINT                    AllowFragSize;
 916        UCHAR                   NumberOfFrag;
 917        UCHAR                   QueIdx, UserPriority;
 918        MAC_TABLE_ENTRY *pEntry = NULL;
 919        unsigned int    IrqFlags;
 920        UCHAR                   FlgIsIP = 0;
 921        UCHAR                   Rate;
 922
 923        // Prepare packet information structure for buffer descriptor
 924        // chained within a single NDIS packet.
 925        RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
 926
 927        if (pSrcBufVA == NULL)
 928        {
 929                DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
 930                // Resourece is low, system did not allocate virtual address
 931                // return NDIS_STATUS_FAILURE directly to upper layer
 932                RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
 933                return NDIS_STATUS_FAILURE;
 934        }
 935
 936
 937        if (SrcBufLen < 14)
 938        {
 939                DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
 940                RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
 941                return (NDIS_STATUS_FAILURE);
 942        }
 943
 944        // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
 945        // Note multicast packets in adhoc also use BSSID_WCID index.
 946        {
 947                if(INFRA_ON(pAd))
 948                {
 949                        {
 950                        pEntry = &pAd->MacTab.Content[BSSID_WCID];
 951                        RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
 952                        Rate = pAd->CommonCfg.TxRate;
 953                }
 954                }
 955                else if (ADHOC_ON(pAd))
 956                {
 957                        if (*pSrcBufVA & 0x01)
 958                        {
 959                                RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
 960                                pEntry = &pAd->MacTab.Content[MCAST_WCID];
 961                        }
 962                        else
 963                        {
 964                                pEntry = MacTableLookup(pAd, pSrcBufVA);
 965                        }
 966                        Rate = pAd->CommonCfg.TxRate;
 967                }
 968        }
 969
 970        if (!pEntry)
 971        {
 972                DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
 973                // Resourece is low, system did not allocate virtual address
 974                // return NDIS_STATUS_FAILURE directly to upper layer
 975                RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
 976                return NDIS_STATUS_FAILURE;
 977        }
 978
 979        if (ADHOC_ON(pAd)
 980                )
 981        {
 982                RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
 983        }
 984
 985        //
 986        // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
 987        //              Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
 988        RTMPCheckEtherType(pAd, pPacket);
 989
 990
 991
 992        //
 993        // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
 994        //
 995        if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
 996                 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
 997                 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
 998                 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
 999                  || (pAd->StaCfg.IEEE8021X == TRUE)
1000                  )
1001                  && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
1002                  && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
1003                  )
1004        {
1005                DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
1006                RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1007
1008                return (NDIS_STATUS_FAILURE);
1009        }
1010
1011
1012        // STEP 1. Decide number of fragments required to deliver this MSDU.
1013        //         The estimation here is not very accurate because difficult to
1014        //         take encryption overhead into consideration here. The result
1015        //         "NumberOfFrag" is then just used to pre-check if enough free
1016        //         TXD are available to hold this MSDU.
1017
1018
1019        if (*pSrcBufVA & 0x01)  // fragmentation not allowed on multicast & broadcast
1020                NumberOfFrag = 1;
1021        else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1022                NumberOfFrag = 1;       // Aggregation overwhelms fragmentation
1023        else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1024                NumberOfFrag = 1;       // Aggregation overwhelms fragmentation
1025        else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1026                NumberOfFrag = 1;       // MIMO RATE overwhelms fragmentation
1027        else
1028        {
1029                // The calculated "NumberOfFrag" is a rough estimation because of various
1030                // encryption/encapsulation overhead not taken into consideration. This number is just
1031                // used to make sure enough free TXD are available before fragmentation takes place.
1032                // In case the actual required number of fragments of an NDIS packet
1033                // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1034                // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1035                // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1036                // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1037
1038                AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1039                NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1040                // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1041                if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1042                {
1043                        NumberOfFrag--;
1044                }
1045        }
1046
1047        // Save fragment number to Ndis packet reserved field
1048        RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1049
1050
1051        // STEP 2. Check the requirement of RTS:
1052        //         If multiple fragment required, RTS is required only for the first fragment
1053        //         if the fragment size large than RTS threshold
1054        //     For RT28xx, Let ASIC send RTS/CTS
1055        RTMP_SET_PACKET_RTS(pPacket, 0);
1056        RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1057
1058        //
1059        // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1060        //
1061        UserPriority = 0;
1062        QueIdx           = QID_AC_BE;
1063#ifdef RT2860
1064        if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
1065#endif
1066#ifdef RT2870
1067        if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1068                CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
1069#endif
1070        {
1071                USHORT Protocol;
1072                UCHAR  LlcSnapLen = 0, Byte0, Byte1;
1073                do
1074                {
1075                        // get Ethernet protocol field
1076                        Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1077                        if (Protocol <= 1500)
1078                        {
1079                                // get Ethernet protocol field from LLC/SNAP
1080                                if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1081                                        break;
1082
1083                                Protocol = (USHORT)((Byte0 << 8) + Byte1);
1084                                LlcSnapLen = 8;
1085                        }
1086
1087                        // always AC_BE for non-IP packet
1088                        if (Protocol != 0x0800)
1089                                break;
1090
1091                        // get IP header
1092                        if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1093                                break;
1094
1095                        // return AC_BE if packet is not IPv4
1096                        if ((Byte0 & 0xf0) != 0x40)
1097                                break;
1098
1099                        FlgIsIP = 1;
1100                        UserPriority = (Byte1 & 0xe0) >> 5;
1101                        QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1102
1103                        // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1104                        // TODO: downgrade UP & QueIdx before passing ACM
1105                        if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1106                        {
1107                                UserPriority = 0;
1108                                QueIdx           = QID_AC_BE;
1109                        }
1110                } while (FALSE);
1111        }
1112
1113        RTMP_SET_PACKET_UP(pPacket, UserPriority);
1114
1115
1116
1117        // Make sure SendTxWait queue resource won't be used by other threads
1118        RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1119        if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1120        {
1121                RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1122                RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1123
1124                return NDIS_STATUS_FAILURE;
1125        }
1126        else
1127        {
1128                InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1129        }
1130        RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1131
1132    if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1133#ifdef RT2860
1134        (pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE))
1135#endif
1136#ifdef RT2870
1137        IS_HT_STA(pEntry))
1138#endif
1139        {
1140                if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1141            ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1142            (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1143                         // For IOT compatibility, if
1144                         // 1. It is Ralink chip or
1145                         // 2. It is OPEN or AES mode,
1146                         // then BA session can be bulit.
1147                         && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1148                                 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1149                        )
1150                {
1151                        BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1152                }
1153        }
1154
1155        pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1156        return NDIS_STATUS_SUCCESS;
1157}
1158
1159
1160/*
1161        ========================================================================
1162
1163        Routine Description:
1164                This subroutine will scan through releative ring descriptor to find
1165                out avaliable free ring descriptor and compare with request size.
1166
1167        Arguments:
1168                pAd Pointer to our adapter
1169                QueIdx          Selected TX Ring
1170
1171        Return Value:
1172                NDIS_STATUS_FAILURE     Not enough free descriptor
1173                NDIS_STATUS_SUCCESS     Enough free descriptor
1174
1175        IRQL = PASSIVE_LEVEL
1176        IRQL = DISPATCH_LEVEL
1177
1178        Note:
1179
1180        ========================================================================
1181*/
1182
1183#ifdef RT2870
1184/*
1185        Actually, this function used to check if the TxHardware Queue still has frame need to send.
1186        If no frame need to send, go to sleep, else, still wake up.
1187*/
1188#endif
1189NDIS_STATUS RTMPFreeTXDRequest(
1190        IN              PRTMP_ADAPTER   pAd,
1191        IN              UCHAR                   QueIdx,
1192        IN              UCHAR                   NumberRequired,
1193        IN              PUCHAR                  FreeNumberIs)
1194{
1195#ifdef RT2860
1196        ULONG           FreeNumber = 0;
1197#endif
1198        NDIS_STATUS     Status = NDIS_STATUS_FAILURE;
1199#ifdef RT2870
1200        unsigned long   IrqFlags;
1201        HT_TX_CONTEXT   *pHTTXContext;
1202#endif
1203
1204        switch (QueIdx)
1205        {
1206                case QID_AC_BK:
1207                case QID_AC_BE:
1208                case QID_AC_VI:
1209                case QID_AC_VO:
1210                case QID_HCCA:
1211#ifdef RT2860
1212                        if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx)
1213                                FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1214                        else
1215                                FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1216
1217                        if (FreeNumber >= NumberRequired)
1218                                Status = NDIS_STATUS_SUCCESS;
1219#endif
1220#ifdef RT2870
1221                        {
1222                                pHTTXContext = &pAd->TxContext[QueIdx];
1223                                RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1224                                if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) ||
1225                                        (pHTTXContext->IRPPending == TRUE))
1226                                {
1227                                        Status = NDIS_STATUS_FAILURE;
1228                                }
1229                                else
1230                                {
1231                                        Status = NDIS_STATUS_SUCCESS;
1232                                }
1233                                RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1234                        }
1235#endif
1236                        break;
1237
1238                case QID_MGMT:
1239#ifdef RT2860
1240                        if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
1241                                FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1;
1242                        else
1243                                FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1;
1244
1245                        if (FreeNumber >= NumberRequired)
1246                                Status = NDIS_STATUS_SUCCESS;
1247#endif
1248#ifdef RT2870
1249                        if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1250                                Status = NDIS_STATUS_FAILURE;
1251                        else
1252                                Status = NDIS_STATUS_SUCCESS;
1253#endif
1254                        break;
1255
1256                default:
1257                        DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1258                        break;
1259        }
1260#ifdef RT2860
1261        *FreeNumberIs = (UCHAR)FreeNumber;
1262#endif
1263
1264        return (Status);
1265}
1266
1267
1268
1269VOID RTMPSendDisassociationFrame(
1270        IN      PRTMP_ADAPTER   pAd)
1271{
1272}
1273
1274VOID    RTMPSendNullFrame(
1275        IN      PRTMP_ADAPTER   pAd,
1276        IN      UCHAR                   TxRate,
1277        IN      BOOLEAN                 bQosNull)
1278{
1279        UCHAR   NullFrame[48];
1280        ULONG   Length;
1281        PHEADER_802_11  pHeader_802_11;
1282
1283    // WPA 802.1x secured port control
1284    if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1285         (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1286         (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1287         (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1288                          || (pAd->StaCfg.IEEE8021X == TRUE)
1289        ) &&
1290       (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1291        {
1292                return;
1293        }
1294
1295        NdisZeroMemory(NullFrame, 48);
1296        Length = sizeof(HEADER_802_11);
1297
1298        pHeader_802_11 = (PHEADER_802_11) NullFrame;
1299
1300        pHeader_802_11->FC.Type = BTYPE_DATA;
1301        pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1302        pHeader_802_11->FC.ToDs = 1;
1303        COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1304        COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1305        COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1306
1307        if (pAd->CommonCfg.bAPSDForcePowerSave)
1308        {
1309                pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1310        }
1311        else
1312        {
1313                pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1314        }
1315        pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1316
1317        pAd->Sequence++;
1318        pHeader_802_11->Sequence = pAd->Sequence;
1319
1320        // Prepare QosNull function frame
1321        if (bQosNull)
1322        {
1323                pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1324
1325                // copy QOS control bytes
1326                NullFrame[Length]       =  0;
1327                NullFrame[Length+1] =  0;
1328                Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1329        }
1330
1331        HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1332
1333}
1334
1335// IRQL = DISPATCH_LEVEL
1336VOID    RTMPSendRTSFrame(
1337        IN      PRTMP_ADAPTER   pAd,
1338        IN      PUCHAR                  pDA,
1339        IN      unsigned int    NextMpduSize,
1340        IN      UCHAR                   TxRate,
1341        IN      UCHAR                   RTSRate,
1342        IN      USHORT                  AckDuration,
1343        IN      UCHAR                   QueIdx,
1344        IN      UCHAR                   FrameGap)
1345{
1346}
1347
1348
1349
1350// --------------------------------------------------------
1351//  FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1352//              Find the WPA key, either Group or Pairwise Key
1353//              LEAP + TKIP also use WPA key.
1354// --------------------------------------------------------
1355// Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1356// In Cisco CCX 2.0 Leap Authentication
1357//                 WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1358//                 Instead of the SharedKey, SharedKey Length may be Zero.
1359VOID STAFindCipherAlgorithm(
1360        IN      PRTMP_ADAPTER   pAd,
1361        IN      TX_BLK                  *pTxBlk)
1362{
1363        NDIS_802_11_ENCRYPTION_STATUS   Cipher;                         // To indicate cipher used for this packet
1364        UCHAR                                                   CipherAlg = CIPHER_NONE;                // cipher alogrithm
1365        UCHAR                                                   KeyIdx = 0xff;
1366        PUCHAR                                                  pSrcBufVA;
1367        PCIPHER_KEY                                             pKey = NULL;
1368
1369        pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1370
1371        {
1372            // Select Cipher
1373            if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1374                Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1375            else
1376                Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1377
1378                if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1379                {
1380                        ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1381
1382                        // 4-way handshaking frame must be clear
1383                        if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1384                                (pAd->SharedKey[BSS0][0].KeyLen))
1385                        {
1386                                CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1387                                KeyIdx = 0;
1388                        }
1389                }
1390                else if (Cipher == Ndis802_11Encryption1Enabled)
1391                {
1392                                KeyIdx = pAd->StaCfg.DefaultKeyId;
1393                }
1394                else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1395                                 (Cipher == Ndis802_11Encryption3Enabled))
1396                {
1397                        if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1398                                KeyIdx = pAd->StaCfg.DefaultKeyId;
1399                        else if (pAd->SharedKey[BSS0][0].KeyLen)
1400                                KeyIdx = 0;
1401                        else
1402                                KeyIdx = pAd->StaCfg.DefaultKeyId;
1403                }
1404
1405                if (KeyIdx == 0xff)
1406                        CipherAlg = CIPHER_NONE;
1407                else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1408                        CipherAlg = CIPHER_NONE;
1409            else if ( pAd->StaCfg.WpaSupplicantUP &&
1410                     (Cipher == Ndis802_11Encryption1Enabled) &&
1411                     (pAd->StaCfg.IEEE8021X == TRUE) &&
1412                     (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1413                CipherAlg = CIPHER_NONE;
1414                else
1415                {
1416                        //Header_802_11.FC.Wep = 1;
1417                        CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1418                        pKey = &pAd->SharedKey[BSS0][KeyIdx];
1419                }
1420        }
1421
1422        pTxBlk->CipherAlg = CipherAlg;
1423        pTxBlk->pKey = pKey;
1424}
1425
1426
1427VOID STABuildCommon802_11Header(
1428        IN  PRTMP_ADAPTER   pAd,
1429        IN  TX_BLK          *pTxBlk)
1430{
1431        HEADER_802_11   *pHeader_802_11;
1432
1433        //
1434        // MAKE A COMMON 802.11 HEADER
1435        //
1436
1437        // normal wlan header size : 24 octets
1438        pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1439
1440        pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1441
1442        NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1443
1444        pHeader_802_11->FC.FrDs = 0;
1445        pHeader_802_11->FC.Type = BTYPE_DATA;
1446        pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1447
1448    if (pTxBlk->pMacEntry)
1449        {
1450                if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1451                {
1452                        pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1453                        pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1454                }
1455                else
1456                {
1457                        {
1458            pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1459            pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1460        }
1461        }
1462        }
1463        else
1464        {
1465                pHeader_802_11->Sequence = pAd->Sequence;
1466                pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1467        }
1468
1469        pHeader_802_11->Frag = 0;
1470
1471        pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1472
1473        {
1474                if (INFRA_ON(pAd))
1475                {
1476                        {
1477                        COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1478                        COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1479                        COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1480                        pHeader_802_11->FC.ToDs = 1;
1481                }
1482                }
1483                else if (ADHOC_ON(pAd))
1484                {
1485                        COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1486                        COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1487                        COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1488                        pHeader_802_11->FC.ToDs = 0;
1489                }
1490        }
1491
1492        if (pTxBlk->CipherAlg != CIPHER_NONE)
1493                pHeader_802_11->FC.Wep = 1;
1494
1495        // -----------------------------------------------------------------
1496        // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1497        // -----------------------------------------------------------------
1498        if (pAd->CommonCfg.bAPSDForcePowerSave)
1499        pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1500        else
1501        pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1502}
1503
1504VOID STABuildCache802_11Header(
1505        IN RTMP_ADAPTER         *pAd,
1506        IN TX_BLK                       *pTxBlk,
1507        IN UCHAR                        *pHeader)
1508{
1509        MAC_TABLE_ENTRY *pMacEntry;
1510        PHEADER_802_11  pHeader80211;
1511
1512        pHeader80211 = (PHEADER_802_11)pHeader;
1513        pMacEntry = pTxBlk->pMacEntry;
1514
1515        //
1516        // Update the cached 802.11 HEADER
1517        //
1518
1519        // normal wlan header size : 24 octets
1520        pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1521
1522        // More Bit
1523        pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1524
1525        // Sequence
1526        pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1527    pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1528
1529        {
1530                // The addr3 of normal packet send from DS is Dest Mac address.
1531                if (ADHOC_ON(pAd))
1532                        COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1533                else
1534                        COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1535        }
1536
1537        // -----------------------------------------------------------------
1538        // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1539        // -----------------------------------------------------------------
1540        if (pAd->CommonCfg.bAPSDForcePowerSave)
1541        pHeader80211->FC.PwrMgmt = PWR_SAVE;
1542        else
1543        pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1544}
1545
1546static inline PUCHAR STA_Build_ARalink_Frame_Header(
1547        IN RTMP_ADAPTER *pAd,
1548        IN TX_BLK               *pTxBlk)
1549{
1550        PUCHAR                  pHeaderBufPtr;
1551        HEADER_802_11   *pHeader_802_11;
1552        PNDIS_PACKET    pNextPacket;
1553        UINT32                  nextBufLen;
1554        PQUEUE_ENTRY    pQEntry;
1555
1556        STAFindCipherAlgorithm(pAd, pTxBlk);
1557        STABuildCommon802_11Header(pAd, pTxBlk);
1558
1559
1560        pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1561        pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1562
1563        // steal "order" bit to mark "aggregation"
1564        pHeader_802_11->FC.Order = 1;
1565
1566        // skip common header
1567        pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1568
1569        if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1570        {
1571                //
1572                // build QOS Control bytes
1573                //
1574                *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1575
1576                *(pHeaderBufPtr+1) = 0;
1577                pHeaderBufPtr +=2;
1578                pTxBlk->MpduHeaderLen += 2;
1579        }
1580
1581        // padding at front of LLC header. LLC header should at 4-bytes aligment.
1582        pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1583        pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1584        pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1585
1586        // For RA Aggregation,
1587        // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1588        pQEntry = pTxBlk->TxPacketList.Head;
1589        pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1590        nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1591        if (RTMP_GET_PACKET_VLAN(pNextPacket))
1592                nextBufLen -= LENGTH_802_1Q;
1593
1594        *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1595        *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1596
1597        pHeaderBufPtr += 2;
1598        pTxBlk->MpduHeaderLen += 2;
1599
1600        return pHeaderBufPtr;
1601
1602}
1603
1604static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1605        IN RTMP_ADAPTER *pAd,
1606        IN TX_BLK               *pTxBlk)
1607{
1608        PUCHAR                  pHeaderBufPtr;//, pSaveBufPtr;
1609        HEADER_802_11   *pHeader_802_11;
1610
1611
1612        STAFindCipherAlgorithm(pAd, pTxBlk);
1613        STABuildCommon802_11Header(pAd, pTxBlk);
1614
1615        pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1616        pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1617
1618        // skip common header
1619        pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1620
1621        //
1622        // build QOS Control bytes
1623        //
1624        *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1625
1626        //
1627        // A-MSDU packet
1628        //
1629        *pHeaderBufPtr |= 0x80;
1630
1631        *(pHeaderBufPtr+1) = 0;
1632        pHeaderBufPtr +=2;
1633        pTxBlk->MpduHeaderLen += 2;
1634
1635        //pSaveBufPtr = pHeaderBufPtr;
1636
1637        //
1638        // padding at front of LLC header
1639        // LLC header should locate at 4-octets aligment
1640        //
1641        // @@@ MpduHeaderLen excluding padding @@@
1642        //
1643        pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1644        pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1645        pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1646
1647        return pHeaderBufPtr;
1648
1649}
1650
1651
1652VOID STA_AMPDU_Frame_Tx(
1653        IN      PRTMP_ADAPTER   pAd,
1654        IN      TX_BLK                  *pTxBlk)
1655{
1656        HEADER_802_11   *pHeader_802_11;
1657        PUCHAR                  pHeaderBufPtr;
1658        USHORT                  FreeNumber;
1659        MAC_TABLE_ENTRY *pMacEntry;
1660        BOOLEAN                 bVLANPkt;
1661        PQUEUE_ENTRY    pQEntry;
1662
1663        ASSERT(pTxBlk);
1664
1665        while(pTxBlk->TxPacketList.Head)
1666        {
1667                pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1668                pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1669                if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1670                {
1671                        RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1672                        continue;
1673                }
1674
1675                bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1676
1677                pMacEntry = pTxBlk->pMacEntry;
1678                if (pMacEntry->isCached)
1679                {
1680                        // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1681                        NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1682                        pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1683                        STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1684                }
1685                else
1686                {
1687                        STAFindCipherAlgorithm(pAd, pTxBlk);
1688                        STABuildCommon802_11Header(pAd, pTxBlk);
1689
1690                        pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1691                }
1692
1693
1694                pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1695
1696                // skip common header
1697                pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1698
1699                //
1700                // build QOS Control bytes
1701                //
1702                *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1703                *(pHeaderBufPtr+1) = 0;
1704                pHeaderBufPtr +=2;
1705                pTxBlk->MpduHeaderLen += 2;
1706
1707                //
1708                // build HTC+
1709                // HTC control filed following QoS field
1710                //
1711                if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1712                {
1713                        if (pMacEntry->isCached == FALSE)
1714                        {
1715                                // mark HTC bit
1716                                pHeader_802_11->FC.Order = 1;
1717
1718                                NdisZeroMemory(pHeaderBufPtr, 4);
1719                                *(pHeaderBufPtr+3) |= 0x80;
1720                        }
1721                        pHeaderBufPtr += 4;
1722                        pTxBlk->MpduHeaderLen += 4;
1723                }
1724
1725                //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1726                ASSERT(pTxBlk->MpduHeaderLen >= 24);
1727
1728                // skip 802.3 header
1729                pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1730                pTxBlk->SrcBufLen  -= LENGTH_802_3;
1731
1732                // skip vlan tag
1733                if (bVLANPkt)
1734                {
1735                        pTxBlk->pSrcBufData     += LENGTH_802_1Q;
1736                        pTxBlk->SrcBufLen       -= LENGTH_802_1Q;
1737                }
1738
1739                //
1740                // padding at front of LLC header
1741                // LLC header should locate at 4-octets aligment
1742                //
1743                // @@@ MpduHeaderLen excluding padding @@@
1744                //
1745                pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1746                pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1747                pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1748
1749                {
1750
1751                        //
1752                        // Insert LLC-SNAP encapsulation - 8 octets
1753                        //
1754                        EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1755                        if (pTxBlk->pExtraLlcSnapEncap)
1756                        {
1757                                NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1758                                pHeaderBufPtr += 6;
1759                                // get 2 octets (TypeofLen)
1760                                NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1761                                pHeaderBufPtr += 2;
1762                                pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1763                        }
1764
1765                }
1766
1767                if (pMacEntry->isCached)
1768                {
1769            RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1770                }
1771                else
1772                {
1773                        RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1774
1775                        NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1776                        NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1777                        pMacEntry->isCached = TRUE;
1778                }
1779
1780                // calculate Transmitted AMPDU count and ByteCount
1781                {
1782                        pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1783                        pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1784                }
1785
1786                //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1787
1788                HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1789
1790                //
1791                // Kick out Tx
1792                //
1793#ifdef RT2860
1794                if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1795#endif
1796                        HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1797
1798                pAd->RalinkCounters.KickTxCount++;
1799                pAd->RalinkCounters.OneSecTxDoneCount++;
1800        }
1801
1802}
1803
1804
1805VOID STA_AMSDU_Frame_Tx(
1806        IN      PRTMP_ADAPTER   pAd,
1807        IN      TX_BLK                  *pTxBlk)
1808{
1809        PUCHAR                  pHeaderBufPtr;
1810        USHORT                  FreeNumber;
1811        USHORT                  subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1812        USHORT                  totalMPDUSize=0;
1813        UCHAR                   *subFrameHeader;
1814        UCHAR                   padding = 0;
1815        USHORT                  FirstTx = 0, LastTxIdx = 0;
1816        BOOLEAN                 bVLANPkt;
1817        int                     frameNum = 0;
1818        PQUEUE_ENTRY    pQEntry;
1819
1820
1821        ASSERT(pTxBlk);
1822
1823        ASSERT((pTxBlk->TxPacketList.Number > 1));
1824
1825        while(pTxBlk->TxPacketList.Head)
1826        {
1827                pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1828                pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1829                if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1830                {
1831                        RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1832                        continue;
1833                }
1834
1835                bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1836
1837                // skip 802.3 header
1838                pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1839                pTxBlk->SrcBufLen  -= LENGTH_802_3;
1840
1841                // skip vlan tag
1842                if (bVLANPkt)
1843                {
1844                        pTxBlk->pSrcBufData     += LENGTH_802_1Q;
1845                        pTxBlk->SrcBufLen       -= LENGTH_802_1Q;
1846                }
1847
1848                if (frameNum == 0)
1849                {
1850                        pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1851
1852                        // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1853                        RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1854                }
1855                else
1856                {
1857                        pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1858                        padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1859                        NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1860                        pHeaderBufPtr += padding;
1861                        pTxBlk->MpduHeaderLen = padding;
1862                }
1863
1864                //
1865                // A-MSDU subframe
1866                //   DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1867                //
1868                subFrameHeader = pHeaderBufPtr;
1869                subFramePayloadLen = pTxBlk->SrcBufLen;
1870
1871                NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1872
1873
1874                pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1875                pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1876
1877
1878                //
1879                // Insert LLC-SNAP encapsulation - 8 octets
1880                //
1881                EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1882
1883                subFramePayloadLen = pTxBlk->SrcBufLen;
1884
1885                if (pTxBlk->pExtraLlcSnapEncap)
1886                {
1887                        NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1888                        pHeaderBufPtr += 6;
1889                        // get 2 octets (TypeofLen)
1890                        NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1891                        pHeaderBufPtr += 2;
1892                        pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1893                        subFramePayloadLen += LENGTH_802_1_H;
1894                }
1895
1896                // update subFrame Length field
1897                subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1898                subFrameHeader[13] = subFramePayloadLen & 0xFF;
1899
1900                totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1901
1902                if (frameNum ==0)
1903                        FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1904                else
1905                        LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1906
1907                frameNum++;
1908
1909                pAd->RalinkCounters.KickTxCount++;
1910                pAd->RalinkCounters.OneSecTxDoneCount++;
1911
1912                // calculate Transmitted AMSDU Count and ByteCount
1913                {
1914                        pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
1915                        pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
1916                }
1917
1918        }
1919
1920        HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1921        HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1922
1923        //
1924        // Kick out Tx
1925        //
1926#ifdef RT2860
1927        if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1928#endif
1929                HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1930}
1931
1932VOID STA_Legacy_Frame_Tx(
1933        IN      PRTMP_ADAPTER   pAd,
1934        IN      TX_BLK                  *pTxBlk)
1935{
1936        HEADER_802_11   *pHeader_802_11;
1937        PUCHAR                  pHeaderBufPtr;
1938        USHORT                  FreeNumber;
1939        BOOLEAN                 bVLANPkt;
1940        PQUEUE_ENTRY    pQEntry;
1941
1942        ASSERT(pTxBlk);
1943
1944
1945        pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1946        pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1947        if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1948        {
1949                RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1950                return;
1951        }
1952
1953        if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
1954        {
1955                INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1956        }
1957
1958        if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1959                TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1960        else
1961                TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1962
1963        bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1964
1965        if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1966                pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1967
1968        STAFindCipherAlgorithm(pAd, pTxBlk);
1969        STABuildCommon802_11Header(pAd, pTxBlk);
1970
1971
1972        // skip 802.3 header
1973        pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1974        pTxBlk->SrcBufLen  -= LENGTH_802_3;
1975
1976        // skip vlan tag
1977        if (bVLANPkt)
1978        {
1979                pTxBlk->pSrcBufData     += LENGTH_802_1Q;
1980                pTxBlk->SrcBufLen       -= LENGTH_802_1Q;
1981        }
1982
1983        pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1984        pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1985
1986        // skip common header
1987        pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1988
1989        if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1990        {
1991                //
1992                // build QOS Control bytes
1993                //
1994                *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1995                *(pHeaderBufPtr+1) = 0;
1996                pHeaderBufPtr +=2;
1997                pTxBlk->MpduHeaderLen += 2;
1998        }
1999
2000        // The remaining content of MPDU header should locate at 4-octets aligment
2001        pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2002        pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2003        pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2004
2005        {
2006
2007                //
2008                // Insert LLC-SNAP encapsulation - 8 octets
2009                //
2010                //
2011                // if original Ethernet frame contains no LLC/SNAP,
2012                // then an extra LLC/SNAP encap is required
2013                //
2014                EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2015                if (pTxBlk->pExtraLlcSnapEncap)
2016                {
2017                        UCHAR vlan_size;
2018
2019                        NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2020                        pHeaderBufPtr += 6;
2021                        // skip vlan tag
2022                        vlan_size =  (bVLANPkt) ? LENGTH_802_1Q : 0;
2023                        // get 2 octets (TypeofLen)
2024                        NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2025                        pHeaderBufPtr += 2;
2026                        pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2027                }
2028
2029        }
2030
2031        //
2032        // prepare for TXWI
2033        // use Wcid as Key Index
2034        //
2035
2036        RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2037
2038        //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2039
2040        HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2041
2042        pAd->RalinkCounters.KickTxCount++;
2043        pAd->RalinkCounters.OneSecTxDoneCount++;
2044
2045        //
2046        // Kick out Tx
2047        //
2048#ifdef RT2860
2049        if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2050#endif
2051                HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2052}
2053
2054
2055VOID STA_ARalink_Frame_Tx(
2056        IN      PRTMP_ADAPTER   pAd,
2057        IN      TX_BLK                  *pTxBlk)
2058{
2059        PUCHAR                  pHeaderBufPtr;
2060        USHORT                  FreeNumber;
2061        USHORT                  totalMPDUSize=0;
2062        USHORT                  FirstTx, LastTxIdx;
2063        int                     frameNum = 0;
2064        BOOLEAN                 bVLANPkt;
2065        PQUEUE_ENTRY    pQEntry;
2066
2067
2068        ASSERT(pTxBlk);
2069
2070        ASSERT((pTxBlk->TxPacketList.Number== 2));
2071
2072
2073        FirstTx = LastTxIdx = 0;  // Is it ok init they as 0?
2074        while(pTxBlk->TxPacketList.Head)
2075        {
2076                pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2077                pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2078
2079                if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2080                {
2081                        RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2082                        continue;
2083                }
2084
2085                bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2086
2087                // skip 802.3 header
2088                pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2089                pTxBlk->SrcBufLen  -= LENGTH_802_3;
2090
2091                // skip vlan tag
2092                if (bVLANPkt)
2093                {
2094                        pTxBlk->pSrcBufData     += LENGTH_802_1Q;
2095                        pTxBlk->SrcBufLen       -= LENGTH_802_1Q;
2096                }
2097
2098                if (frameNum == 0)
2099                {       // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2100
2101                        pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2102
2103                        // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2104                        //      will be updated after final frame was handled.
2105                        RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2106
2107
2108                        //
2109                        // Insert LLC-SNAP encapsulation - 8 octets
2110                        //
2111                        EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2112
2113                        if (pTxBlk->pExtraLlcSnapEncap)
2114                        {
2115                                NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2116                                pHeaderBufPtr += 6;
2117                                // get 2 octets (TypeofLen)
2118                                NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2119                                pHeaderBufPtr += 2;
2120                                pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2121                        }
2122                }
2123                else
2124                {       // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2125
2126                        pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2127                        pTxBlk->MpduHeaderLen = 0;
2128
2129                        // A-Ralink sub-sequent frame header is the same as 802.3 header.
2130                        //   DA(6)+SA(6)+FrameType(2)
2131                        NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2132                        pHeaderBufPtr += 12;
2133                        // get 2 octets (TypeofLen)
2134                        NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2135                        pHeaderBufPtr += 2;
2136                        pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2137                }
2138
2139                totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2140
2141                //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2142                if (frameNum ==0)
2143                        FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2144                else
2145                        LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2146
2147                frameNum++;
2148
2149                pAd->RalinkCounters.OneSecTxAggregationCount++;
2150                pAd->RalinkCounters.KickTxCount++;
2151                pAd->RalinkCounters.OneSecTxDoneCount++;
2152
2153        }
2154
2155        HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2156        HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2157
2158        //
2159        // Kick out Tx
2160        //
2161#ifdef RT2860
2162        if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2163#endif
2164                HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2165
2166}
2167
2168
2169VOID STA_Fragment_Frame_Tx(
2170        IN RTMP_ADAPTER *pAd,
2171        IN TX_BLK               *pTxBlk)
2172{
2173        HEADER_802_11   *pHeader_802_11;
2174        PUCHAR                  pHeaderBufPtr;
2175        USHORT                  FreeNumber;
2176        UCHAR                   fragNum = 0;
2177        PACKET_INFO             PacketInfo;
2178        USHORT                  EncryptionOverhead = 0;
2179        UINT32                  FreeMpduSize, SrcRemainingBytes;
2180        USHORT                  AckDuration;
2181        UINT                    NextMpduSize;
2182        BOOLEAN                 bVLANPkt;
2183        PQUEUE_ENTRY    pQEntry;
2184
2185
2186        ASSERT(pTxBlk);
2187
2188        pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2189        pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2190        if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2191        {
2192                RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2193                return;
2194        }
2195
2196        ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2197        bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2198
2199        STAFindCipherAlgorithm(pAd, pTxBlk);
2200        STABuildCommon802_11Header(pAd, pTxBlk);
2201
2202        if (pTxBlk->CipherAlg == CIPHER_TKIP)
2203        {
2204                pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2205                if (pTxBlk->pPacket == NULL)
2206                        return;
2207                RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2208        }
2209
2210        // skip 802.3 header
2211        pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2212        pTxBlk->SrcBufLen  -= LENGTH_802_3;
2213
2214
2215        // skip vlan tag
2216        if (bVLANPkt)
2217        {
2218                pTxBlk->pSrcBufData     += LENGTH_802_1Q;
2219                pTxBlk->SrcBufLen       -= LENGTH_802_1Q;
2220        }
2221
2222        pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2223        pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2224
2225
2226        // skip common header
2227        pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2228
2229        if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2230        {
2231                //
2232                // build QOS Control bytes
2233                //
2234                *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2235
2236                *(pHeaderBufPtr+1) = 0;
2237                pHeaderBufPtr +=2;
2238                pTxBlk->MpduHeaderLen += 2;
2239        }
2240
2241        //
2242        // padding at front of LLC header
2243        // LLC header should locate at 4-octets aligment
2244        //
2245        pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2246        pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2247        pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2248
2249
2250
2251        //
2252        // Insert LLC-SNAP encapsulation - 8 octets
2253        //
2254        //
2255        // if original Ethernet frame contains no LLC/SNAP,
2256        // then an extra LLC/SNAP encap is required
2257        //
2258        EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2259        if (pTxBlk->pExtraLlcSnapEncap)
2260        {
2261                UCHAR vlan_size;
2262
2263                NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2264                pHeaderBufPtr += 6;
2265                // skip vlan tag
2266                vlan_size =  (bVLANPkt) ? LENGTH_802_1Q : 0;
2267                // get 2 octets (TypeofLen)
2268                NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2269                pHeaderBufPtr += 2;
2270                pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2271        }
2272
2273
2274        // If TKIP is used and fragmentation is required. Driver has to
2275        //      append TKIP MIC at tail of the scatter buffer
2276        //      MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2277        if (pTxBlk->CipherAlg == CIPHER_TKIP)
2278        {
2279
2280                // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2281                //                      to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2282                NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2283                //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2284                pTxBlk->SrcBufLen += 8;
2285                pTxBlk->TotalFrameLen += 8;
2286                pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2287        }
2288
2289        //
2290        // calcuate the overhead bytes that encryption algorithm may add. This
2291        // affects the calculate of "duration" field
2292        //
2293        if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2294                EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2295        else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2296                EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2297        else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2298                EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2299        else if (pTxBlk->CipherAlg == CIPHER_AES)
2300                EncryptionOverhead = 16;        // AES: IV[4] + EIV[4] + MIC[8]
2301        else
2302                EncryptionOverhead = 0;
2303
2304        // decide how much time an ACK/CTS frame will consume in the air
2305        AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2306
2307        // Init the total payload length of this frame.
2308        SrcRemainingBytes = pTxBlk->SrcBufLen;
2309
2310        pTxBlk->TotalFragNum = 0xff;
2311
2312        do {
2313
2314                FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2315
2316                FreeMpduSize -= pTxBlk->MpduHeaderLen;
2317
2318                if (SrcRemainingBytes <= FreeMpduSize)
2319                {       // this is the last or only fragment
2320
2321                        pTxBlk->SrcBufLen = SrcRemainingBytes;
2322
2323                        pHeader_802_11->FC.MoreFrag = 0;
2324                        pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2325
2326                        // Indicate the lower layer that this's the last fragment.
2327                        pTxBlk->TotalFragNum = fragNum;
2328                }
2329                else
2330                {       // more fragment is required
2331
2332                        pTxBlk->SrcBufLen = FreeMpduSize;
2333
2334                        NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2335                        pHeader_802_11->FC.MoreFrag = 1;
2336                        pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2337                }
2338
2339                if (fragNum == 0)
2340                        pTxBlk->FrameGap = IFS_HTTXOP;
2341                else
2342                        pTxBlk->FrameGap = IFS_SIFS;
2343
2344                RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2345
2346                HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2347
2348                pAd->RalinkCounters.KickTxCount++;
2349                pAd->RalinkCounters.OneSecTxDoneCount++;
2350
2351                // Update the frame number, remaining size of the NDIS packet payload.
2352
2353                // space for 802.11 header.
2354                if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2355                        pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2356
2357                fragNum++;
2358                SrcRemainingBytes -= pTxBlk->SrcBufLen;
2359                pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2360
2361                pHeader_802_11->Frag++;  // increase Frag #
2362
2363        }while(SrcRemainingBytes > 0);
2364
2365        //
2366        // Kick out Tx
2367        //
2368        HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2369}
2370
2371
2372#define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status)                                                                               \
2373                while(_pTxBlk->TxPacketList.Head)                                                                                                               \
2374                {                                                                                                                                                                               \
2375                        _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList);                                                                     \
2376                        RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status);    \
2377                }
2378
2379
2380/*
2381        ========================================================================
2382
2383        Routine Description:
2384                Copy frame from waiting queue into relative ring buffer and set
2385        appropriate ASIC register to kick hardware encryption before really
2386        sent out to air.
2387
2388        Arguments:
2389                pAd     Pointer to our adapter
2390                PNDIS_PACKET    Pointer to outgoing Ndis frame
2391                NumberOfFrag    Number of fragment required
2392
2393        Return Value:
2394                None
2395
2396        IRQL = DISPATCH_LEVEL
2397
2398        Note:
2399
2400        ========================================================================
2401*/
2402NDIS_STATUS STAHardTransmit(
2403        IN PRTMP_ADAPTER        pAd,
2404        IN TX_BLK                       *pTxBlk,
2405        IN      UCHAR                   QueIdx)
2406{
2407        NDIS_PACKET             *pPacket;
2408        PQUEUE_ENTRY    pQEntry;
2409
2410        // ---------------------------------------------
2411        // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2412        // ---------------------------------------------
2413        //
2414        ASSERT(pTxBlk->TxPacketList.Number);
2415        if (pTxBlk->TxPacketList.Head == NULL)
2416        {
2417                DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2418                return NDIS_STATUS_FAILURE;
2419        }
2420
2421        pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2422
2423        // ------------------------------------------------------------------
2424        // STEP 1. WAKE UP PHY
2425        //              outgoing frame always wakeup PHY to prevent frame lost and
2426        //              turn off PSM bit to improve performance
2427        // ------------------------------------------------------------------
2428        // not to change PSM bit, just send this frame out?
2429        if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2430        {
2431            DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2432#ifdef RT2860
2433                AsicForceWakeup(pAd, FROM_TX);
2434#endif
2435#ifdef RT2870
2436                AsicForceWakeup(pAd, TRUE);
2437#endif
2438        }
2439
2440        // It should not change PSM bit, when APSD turn on.
2441        if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2442                || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2443                || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2444        {
2445                if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2446            (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2447                        MlmeSetPsmBit(pAd, PWR_ACTIVE);
2448        }
2449
2450        switch (pTxBlk->TxFrameType)
2451        {
2452                case TX_AMPDU_FRAME:
2453                                STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2454                        break;
2455                case TX_AMSDU_FRAME:
2456                                STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2457                        break;
2458                case TX_LEGACY_FRAME:
2459                                STA_Legacy_Frame_Tx(pAd, pTxBlk);
2460                        break;
2461                case TX_MCAST_FRAME:
2462                                STA_Legacy_Frame_Tx(pAd, pTxBlk);
2463                        break;
2464                case TX_RALINK_FRAME:
2465                                STA_ARalink_Frame_Tx(pAd, pTxBlk);
2466                        break;
2467                case TX_FRAG_FRAME:
2468                                STA_Fragment_Frame_Tx(pAd, pTxBlk);
2469                        break;
2470                default:
2471                        {
2472                                // It should not happened!
2473                                DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2474                                while(pTxBlk->TxPacketList.Number)
2475                                {
2476                                        pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2477                                        pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2478                                        if (pPacket)
2479                                                RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2480                                }
2481                        }
2482                        break;
2483        }
2484
2485        return (NDIS_STATUS_SUCCESS);
2486
2487}
2488
2489ULONG  HashBytesPolynomial(UCHAR *value, unsigned int len)
2490{
2491   unsigned char *word = value;
2492   unsigned int ret = 0;
2493   unsigned int i;
2494
2495   for(i=0; i < len; i++)
2496   {
2497          int mod = i % 32;
2498          ret ^=(unsigned int) (word[i]) << mod;
2499          ret ^=(unsigned int) (word[i]) >> (32 - mod);
2500   }
2501   return ret;
2502}
2503
2504VOID Sta_Announce_or_Forward_802_3_Packet(
2505        IN      PRTMP_ADAPTER   pAd,
2506        IN      PNDIS_PACKET    pPacket,
2507        IN      UCHAR                   FromWhichBSSID)
2508{
2509        if (TRUE
2510                )
2511        {
2512                announce_802_3_packet(pAd, pPacket);
2513        }
2514        else
2515        {
2516                // release packet
2517                RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2518        }
2519}
2520
2521