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