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