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