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