Staging: rt2870: remove dead QOS_DLS_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 #ifdef LEAP_SUPPORT
973                   || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
974 #endif // LEAP_SUPPORT //
975                   )
976                   && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
977                   && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
978                   )
979         {
980                 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
981                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
982
983                 return (NDIS_STATUS_FAILURE);
984         }
985
986
987         // STEP 1. Decide number of fragments required to deliver this MSDU.
988         //         The estimation here is not very accurate because difficult to
989         //         take encryption overhead into consideration here. The result
990         //         "NumberOfFrag" is then just used to pre-check if enough free
991         //         TXD are available to hold this MSDU.
992
993
994         if (*pSrcBufVA & 0x01)  // fragmentation not allowed on multicast & broadcast
995                 NumberOfFrag = 1;
996         else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
997                 NumberOfFrag = 1;       // Aggregation overwhelms fragmentation
998         else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
999                 NumberOfFrag = 1;       // Aggregation overwhelms fragmentation
1000 #ifdef DOT11_N_SUPPORT
1001         else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1002                 NumberOfFrag = 1;       // MIMO RATE overwhelms fragmentation
1003 #endif // DOT11_N_SUPPORT //
1004         else
1005         {
1006                 // The calculated "NumberOfFrag" is a rough estimation because of various
1007                 // encryption/encapsulation overhead not taken into consideration. This number is just
1008                 // used to make sure enough free TXD are available before fragmentation takes place.
1009                 // In case the actual required number of fragments of an NDIS packet
1010                 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1011                 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1012                 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1013                 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1014
1015                 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1016                 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1017                 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1018                 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1019                 {
1020                         NumberOfFrag--;
1021                 }
1022         }
1023
1024         // Save fragment number to Ndis packet reserved field
1025         RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1026
1027
1028         // STEP 2. Check the requirement of RTS:
1029         //         If multiple fragment required, RTS is required only for the first fragment
1030         //         if the fragment size large than RTS threshold
1031         //     For RT28xx, Let ASIC send RTS/CTS
1032         RTMP_SET_PACKET_RTS(pPacket, 0);
1033         RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1034
1035         //
1036         // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1037         //
1038         UserPriority = 0;
1039         QueIdx           = QID_AC_BE;
1040         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1041                 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
1042         {
1043                 USHORT Protocol;
1044                 UCHAR  LlcSnapLen = 0, Byte0, Byte1;
1045                 do
1046                 {
1047                         // get Ethernet protocol field
1048                         Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1049                         if (Protocol <= 1500)
1050                         {
1051                                 // get Ethernet protocol field from LLC/SNAP
1052                                 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1053                                         break;
1054
1055                                 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1056                                 LlcSnapLen = 8;
1057                         }
1058
1059                         // always AC_BE for non-IP packet
1060                         if (Protocol != 0x0800)
1061                                 break;
1062
1063                         // get IP header
1064                         if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1065                                 break;
1066
1067                         // return AC_BE if packet is not IPv4
1068                         if ((Byte0 & 0xf0) != 0x40)
1069                                 break;
1070
1071                         FlgIsIP = 1;
1072                         UserPriority = (Byte1 & 0xe0) >> 5;
1073                         QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1074
1075                         // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1076                         // TODO: downgrade UP & QueIdx before passing ACM
1077                         if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1078                         {
1079                                 UserPriority = 0;
1080                                 QueIdx           = QID_AC_BE;
1081                         }
1082                 } while (FALSE);
1083         }
1084
1085         RTMP_SET_PACKET_UP(pPacket, UserPriority);
1086
1087
1088
1089         // Make sure SendTxWait queue resource won't be used by other threads
1090         RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1091         if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1092         {
1093                 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1094                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1095
1096                 return NDIS_STATUS_FAILURE;
1097         }
1098         else
1099         {
1100                 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1101         }
1102         RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1103
1104 #ifdef DOT11_N_SUPPORT
1105     if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1106         IS_HT_STA(pEntry))
1107         {
1108             //PMAC_TABLE_ENTRY pMacEntry = &pAd->MacTab.Content[BSSID_WCID];
1109                 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1110             ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1111             (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1112                          // For IOT compatibility, if
1113                          // 1. It is Ralink chip or
1114                          // 2. It is OPEN or AES mode,
1115                          // then BA session can be bulit.
1116                          && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1117                                  (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1118                         )
1119                 {
1120                         BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1121                 }
1122         }
1123 #endif // DOT11_N_SUPPORT //
1124
1125         pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1126         return NDIS_STATUS_SUCCESS;
1127 }
1128
1129
1130 /*
1131         ========================================================================
1132
1133         Routine Description:
1134                 This subroutine will scan through releative ring descriptor to find
1135                 out avaliable free ring descriptor and compare with request size.
1136
1137         Arguments:
1138                 pAd Pointer to our adapter
1139                 QueIdx          Selected TX Ring
1140
1141         Return Value:
1142                 NDIS_STATUS_FAILURE     Not enough free descriptor
1143                 NDIS_STATUS_SUCCESS     Enough free descriptor
1144
1145         IRQL = PASSIVE_LEVEL
1146         IRQL = DISPATCH_LEVEL
1147
1148         Note:
1149
1150         ========================================================================
1151 */
1152
1153 #ifdef RT2870
1154 /*
1155         Actually, this function used to check if the TxHardware Queue still has frame need to send.
1156         If no frame need to send, go to sleep, else, still wake up.
1157 */
1158 NDIS_STATUS RTMPFreeTXDRequest(
1159         IN              PRTMP_ADAPTER   pAd,
1160         IN              UCHAR                   QueIdx,
1161         IN              UCHAR                   NumberRequired,
1162         IN              PUCHAR                  FreeNumberIs)
1163 {
1164         //ULONG         FreeNumber = 0;
1165         NDIS_STATUS     Status = NDIS_STATUS_FAILURE;
1166         unsigned long   IrqFlags;
1167         HT_TX_CONTEXT   *pHTTXContext;
1168
1169         switch (QueIdx)
1170         {
1171                 case QID_AC_BK:
1172                 case QID_AC_BE:
1173                 case QID_AC_VI:
1174                 case QID_AC_VO:
1175                 case QID_HCCA:
1176                         {
1177                                 pHTTXContext = &pAd->TxContext[QueIdx];
1178                                 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1179                                 if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) ||
1180                                         (pHTTXContext->IRPPending == TRUE))
1181                                 {
1182                                         Status = NDIS_STATUS_FAILURE;
1183                                 }
1184                                 else
1185                                 {
1186                                         Status = NDIS_STATUS_SUCCESS;
1187                                 }
1188                                 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1189                         }
1190                         break;
1191
1192                 case QID_MGMT:
1193                         if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1194                                 Status = NDIS_STATUS_FAILURE;
1195                         else
1196                                 Status = NDIS_STATUS_SUCCESS;
1197                         break;
1198
1199                 default:
1200                         DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1201                         break;
1202         }
1203
1204         return (Status);
1205
1206 }
1207 #endif // RT2870 //
1208
1209
1210 VOID RTMPSendDisassociationFrame(
1211         IN      PRTMP_ADAPTER   pAd)
1212 {
1213 }
1214
1215 VOID    RTMPSendNullFrame(
1216         IN      PRTMP_ADAPTER   pAd,
1217         IN      UCHAR                   TxRate,
1218         IN      BOOLEAN                 bQosNull)
1219 {
1220         UCHAR   NullFrame[48];
1221         ULONG   Length;
1222         PHEADER_802_11  pHeader_802_11;
1223
1224     // WPA 802.1x secured port control
1225     if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1226          (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1227          (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1228          (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1229 #ifdef WPA_SUPPLICANT_SUPPORT
1230                           || (pAd->StaCfg.IEEE8021X == TRUE)
1231 #endif
1232         ) &&
1233        (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1234         {
1235                 return;
1236         }
1237
1238         NdisZeroMemory(NullFrame, 48);
1239         Length = sizeof(HEADER_802_11);
1240
1241         pHeader_802_11 = (PHEADER_802_11) NullFrame;
1242
1243         pHeader_802_11->FC.Type = BTYPE_DATA;
1244         pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1245         pHeader_802_11->FC.ToDs = 1;
1246         COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1247         COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1248         COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1249
1250         if (pAd->CommonCfg.bAPSDForcePowerSave)
1251         {
1252                 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1253         }
1254         else
1255         {
1256                 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1257         }
1258         pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1259
1260         pAd->Sequence++;
1261         pHeader_802_11->Sequence = pAd->Sequence;
1262
1263         // Prepare QosNull function frame
1264         if (bQosNull)
1265         {
1266                 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1267
1268                 // copy QOS control bytes
1269                 NullFrame[Length]       =  0;
1270                 NullFrame[Length+1] =  0;
1271                 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1272         }
1273
1274         HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1275
1276 }
1277
1278 // IRQL = DISPATCH_LEVEL
1279 VOID    RTMPSendRTSFrame(
1280         IN      PRTMP_ADAPTER   pAd,
1281         IN      PUCHAR                  pDA,
1282         IN      unsigned int    NextMpduSize,
1283         IN      UCHAR                   TxRate,
1284         IN      UCHAR                   RTSRate,
1285         IN      USHORT                  AckDuration,
1286         IN      UCHAR                   QueIdx,
1287         IN      UCHAR                   FrameGap)
1288 {
1289 }
1290
1291
1292
1293 // --------------------------------------------------------
1294 //  FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1295 //              Find the WPA key, either Group or Pairwise Key
1296 //              LEAP + TKIP also use WPA key.
1297 // --------------------------------------------------------
1298 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1299 // In Cisco CCX 2.0 Leap Authentication
1300 //                 WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1301 //                 Instead of the SharedKey, SharedKey Length may be Zero.
1302 VOID STAFindCipherAlgorithm(
1303         IN      PRTMP_ADAPTER   pAd,
1304         IN      TX_BLK                  *pTxBlk)
1305 {
1306         NDIS_802_11_ENCRYPTION_STATUS   Cipher;                         // To indicate cipher used for this packet
1307         UCHAR                                                   CipherAlg = CIPHER_NONE;                // cipher alogrithm
1308         UCHAR                                                   KeyIdx = 0xff;
1309         PUCHAR                                                  pSrcBufVA;
1310         PCIPHER_KEY                                             pKey = NULL;
1311
1312         pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1313
1314         {
1315             // Select Cipher
1316             if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1317                 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1318             else
1319                 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1320
1321                 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1322                 {
1323                         ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1324
1325                         // 4-way handshaking frame must be clear
1326                         if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1327                                 (pAd->SharedKey[BSS0][0].KeyLen))
1328                         {
1329                                 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1330                                 KeyIdx = 0;
1331                         }
1332                 }
1333                 else if (Cipher == Ndis802_11Encryption1Enabled)
1334                 {
1335 #ifdef LEAP_SUPPORT
1336                         if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on
1337                         {
1338                                 if (LEAP_CCKM_ON(pAd))
1339                                 {
1340                                         if (((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))))
1341                                                 KeyIdx = 1;
1342                                         else
1343                                                 KeyIdx = 0;
1344                                 }
1345                                 else
1346                                         KeyIdx = pAd->StaCfg.DefaultKeyId;
1347                         }
1348                         else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC
1349                                 KeyIdx = pAd->StaCfg.DefaultKeyId;
1350                         else if (LEAP_CCKM_ON(pAd))
1351                         {
1352                                 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1353                                         KeyIdx = 1;
1354                                 else
1355                                         KeyIdx = 0;
1356                         }
1357                         else    // standard WEP64 or WEP128
1358 #endif // LEAP_SUPPORT //
1359                                 KeyIdx = pAd->StaCfg.DefaultKeyId;
1360                 }
1361                 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1362                                  (Cipher == Ndis802_11Encryption3Enabled))
1363                 {
1364                         if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1365                                 KeyIdx = pAd->StaCfg.DefaultKeyId;
1366                         else if (pAd->SharedKey[BSS0][0].KeyLen)
1367                                 KeyIdx = 0;
1368                         else
1369                                 KeyIdx = pAd->StaCfg.DefaultKeyId;
1370                 }
1371
1372                 if (KeyIdx == 0xff)
1373                         CipherAlg = CIPHER_NONE;
1374                 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1375                         CipherAlg = CIPHER_NONE;
1376 #ifdef WPA_SUPPLICANT_SUPPORT
1377             else if ( pAd->StaCfg.WpaSupplicantUP &&
1378                      (Cipher == Ndis802_11Encryption1Enabled) &&
1379                      (pAd->StaCfg.IEEE8021X == TRUE) &&
1380                      (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1381                 CipherAlg = CIPHER_NONE;
1382 #endif // WPA_SUPPLICANT_SUPPORT //
1383                 else
1384                 {
1385                         //Header_802_11.FC.Wep = 1;
1386                         CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1387                         pKey = &pAd->SharedKey[BSS0][KeyIdx];
1388                 }
1389         }
1390
1391         pTxBlk->CipherAlg = CipherAlg;
1392         pTxBlk->pKey = pKey;
1393 }
1394
1395
1396 VOID STABuildCommon802_11Header(
1397         IN  PRTMP_ADAPTER   pAd,
1398         IN  TX_BLK          *pTxBlk)
1399 {
1400         HEADER_802_11   *pHeader_802_11;
1401
1402         //
1403         // MAKE A COMMON 802.11 HEADER
1404         //
1405
1406         // normal wlan header size : 24 octets
1407         pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1408
1409         pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1410
1411         NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1412
1413         pHeader_802_11->FC.FrDs = 0;
1414         pHeader_802_11->FC.Type = BTYPE_DATA;
1415         pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1416
1417     if (pTxBlk->pMacEntry)
1418         {
1419                 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1420                 {
1421                         pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1422                         pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1423                 }
1424                 else
1425                 {
1426             pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1427             pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1428         }
1429         }
1430         else
1431         {
1432                 pHeader_802_11->Sequence = pAd->Sequence;
1433                 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1434         }
1435
1436         pHeader_802_11->Frag = 0;
1437
1438         pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1439
1440         {
1441                 if (INFRA_ON(pAd))
1442                 {
1443                         {
1444                         COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1445                         COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1446                         COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1447                         pHeader_802_11->FC.ToDs = 1;
1448                 }
1449                 }
1450                 else if (ADHOC_ON(pAd))
1451                 {
1452                         COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1453                         COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1454                         COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1455                         pHeader_802_11->FC.ToDs = 0;
1456                 }
1457         }
1458
1459         if (pTxBlk->CipherAlg != CIPHER_NONE)
1460                 pHeader_802_11->FC.Wep = 1;
1461
1462         // -----------------------------------------------------------------
1463         // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1464         // -----------------------------------------------------------------
1465         if (pAd->CommonCfg.bAPSDForcePowerSave)
1466         pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1467         else
1468         pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1469 }
1470
1471 #ifdef DOT11_N_SUPPORT
1472 VOID STABuildCache802_11Header(
1473         IN RTMP_ADAPTER         *pAd,
1474         IN TX_BLK                       *pTxBlk,
1475         IN UCHAR                        *pHeader)
1476 {
1477         MAC_TABLE_ENTRY *pMacEntry;
1478         PHEADER_802_11  pHeader80211;
1479
1480         pHeader80211 = (PHEADER_802_11)pHeader;
1481         pMacEntry = pTxBlk->pMacEntry;
1482
1483         //
1484         // Update the cached 802.11 HEADER
1485         //
1486
1487         // normal wlan header size : 24 octets
1488         pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1489
1490         // More Bit
1491         pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1492
1493         // Sequence
1494         pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1495     pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1496
1497         {
1498                 // The addr3 of normal packet send from DS is Dest Mac address.
1499                 if (ADHOC_ON(pAd))
1500                         COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1501                 else
1502                         COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1503         }
1504
1505         // -----------------------------------------------------------------
1506         // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1507         // -----------------------------------------------------------------
1508         if (pAd->CommonCfg.bAPSDForcePowerSave)
1509         pHeader80211->FC.PwrMgmt = PWR_SAVE;
1510         else
1511         pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1512 }
1513 #endif // DOT11_N_SUPPORT //
1514
1515 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1516         IN RTMP_ADAPTER *pAd,
1517         IN TX_BLK               *pTxBlk)
1518 {
1519         PUCHAR                  pHeaderBufPtr;
1520         HEADER_802_11   *pHeader_802_11;
1521         PNDIS_PACKET    pNextPacket;
1522         UINT32                  nextBufLen;
1523         PQUEUE_ENTRY    pQEntry;
1524
1525         STAFindCipherAlgorithm(pAd, pTxBlk);
1526         STABuildCommon802_11Header(pAd, pTxBlk);
1527
1528
1529         pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1530         pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1531
1532         // steal "order" bit to mark "aggregation"
1533         pHeader_802_11->FC.Order = 1;
1534
1535         // skip common header
1536         pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1537
1538         if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1539         {
1540                 //
1541                 // build QOS Control bytes
1542                 //
1543                 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1544
1545                 *(pHeaderBufPtr+1) = 0;
1546                 pHeaderBufPtr +=2;
1547                 pTxBlk->MpduHeaderLen += 2;
1548         }
1549
1550         // padding at front of LLC header. LLC header should at 4-bytes aligment.
1551         pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1552         pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1553         pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1554
1555         // For RA Aggregation,
1556         // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1557         pQEntry = pTxBlk->TxPacketList.Head;
1558         pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1559         nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1560         if (RTMP_GET_PACKET_VLAN(pNextPacket))
1561                 nextBufLen -= LENGTH_802_1Q;
1562
1563         *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1564         *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1565
1566         pHeaderBufPtr += 2;
1567         pTxBlk->MpduHeaderLen += 2;
1568
1569         return pHeaderBufPtr;
1570
1571 }
1572
1573 #ifdef DOT11_N_SUPPORT
1574 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1575         IN RTMP_ADAPTER *pAd,
1576         IN TX_BLK               *pTxBlk)
1577 {
1578         PUCHAR                  pHeaderBufPtr;//, pSaveBufPtr;
1579         HEADER_802_11   *pHeader_802_11;
1580
1581
1582         STAFindCipherAlgorithm(pAd, pTxBlk);
1583         STABuildCommon802_11Header(pAd, pTxBlk);
1584
1585         pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1586         pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1587
1588         // skip common header
1589         pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1590
1591         //
1592         // build QOS Control bytes
1593         //
1594         *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1595
1596         //
1597         // A-MSDU packet
1598         //
1599         *pHeaderBufPtr |= 0x80;
1600
1601         *(pHeaderBufPtr+1) = 0;
1602         pHeaderBufPtr +=2;
1603         pTxBlk->MpduHeaderLen += 2;
1604
1605         //pSaveBufPtr = pHeaderBufPtr;
1606
1607         //
1608         // padding at front of LLC header
1609         // LLC header should locate at 4-octets aligment
1610         //
1611         // @@@ MpduHeaderLen excluding padding @@@
1612         //
1613         pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1614         pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1615         pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1616
1617         return pHeaderBufPtr;
1618
1619 }
1620
1621
1622 VOID STA_AMPDU_Frame_Tx(
1623         IN      PRTMP_ADAPTER   pAd,
1624         IN      TX_BLK                  *pTxBlk)
1625 {
1626         HEADER_802_11   *pHeader_802_11;
1627         PUCHAR                  pHeaderBufPtr;
1628         USHORT                  FreeNumber;
1629         MAC_TABLE_ENTRY *pMacEntry;
1630         BOOLEAN                 bVLANPkt;
1631         PQUEUE_ENTRY    pQEntry;
1632
1633         ASSERT(pTxBlk);
1634
1635         while(pTxBlk->TxPacketList.Head)
1636         {
1637                 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1638                 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1639                 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1640                 {
1641                         RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1642                         continue;
1643                 }
1644
1645                 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1646
1647                 pMacEntry = pTxBlk->pMacEntry;
1648                 if (pMacEntry->isCached)
1649                 {
1650                         // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1651                         NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1652                         pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1653                         STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1654                 }
1655                 else
1656                 {
1657                         STAFindCipherAlgorithm(pAd, pTxBlk);
1658                         STABuildCommon802_11Header(pAd, pTxBlk);
1659
1660                         pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1661                 }
1662
1663
1664                 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1665
1666                 // skip common header
1667                 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1668
1669                 //
1670                 // build QOS Control bytes
1671                 //
1672                 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1673                 *(pHeaderBufPtr+1) = 0;
1674                 pHeaderBufPtr +=2;
1675                 pTxBlk->MpduHeaderLen += 2;
1676
1677                 //
1678                 // build HTC+
1679                 // HTC control filed following QoS field
1680                 //
1681                 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1682                 {
1683                         if (pMacEntry->isCached == FALSE)
1684                         {
1685                                 // mark HTC bit
1686                                 pHeader_802_11->FC.Order = 1;
1687
1688                                 NdisZeroMemory(pHeaderBufPtr, 4);
1689                                 *(pHeaderBufPtr+3) |= 0x80;
1690                         }
1691                         pHeaderBufPtr += 4;
1692                         pTxBlk->MpduHeaderLen += 4;
1693                 }
1694
1695                 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1696                 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1697
1698                 // skip 802.3 header
1699                 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1700                 pTxBlk->SrcBufLen  -= LENGTH_802_3;
1701
1702                 // skip vlan tag
1703                 if (bVLANPkt)
1704                 {
1705                         pTxBlk->pSrcBufData     += LENGTH_802_1Q;
1706                         pTxBlk->SrcBufLen       -= LENGTH_802_1Q;
1707                 }
1708
1709                 //
1710                 // padding at front of LLC header
1711                 // LLC header should locate at 4-octets aligment
1712                 //
1713                 // @@@ MpduHeaderLen excluding padding @@@
1714                 //
1715                 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1716                 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1717                 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1718
1719                 {
1720
1721                         //
1722                         // Insert LLC-SNAP encapsulation - 8 octets
1723                         //
1724                         EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1725                         if (pTxBlk->pExtraLlcSnapEncap)
1726                         {
1727                                 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1728                                 pHeaderBufPtr += 6;
1729                                 // get 2 octets (TypeofLen)
1730                                 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1731                                 pHeaderBufPtr += 2;
1732                                 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1733                         }
1734
1735                 }
1736
1737                 if (pMacEntry->isCached)
1738                 {
1739             RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1740                 }
1741                 else
1742                 {
1743                         RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1744
1745                         NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1746                         NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1747                         pMacEntry->isCached = TRUE;
1748                 }
1749
1750                 // calculate Transmitted AMPDU count and ByteCount
1751                 {
1752                         pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1753                         pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1754                 }
1755
1756                 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1757
1758                 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1759
1760                 //
1761                 // Kick out Tx
1762                 //
1763                 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1764
1765                 pAd->RalinkCounters.KickTxCount++;
1766                 pAd->RalinkCounters.OneSecTxDoneCount++;
1767         }
1768
1769 }
1770
1771
1772 VOID STA_AMSDU_Frame_Tx(
1773         IN      PRTMP_ADAPTER   pAd,
1774         IN      TX_BLK                  *pTxBlk)
1775 {
1776         PUCHAR                  pHeaderBufPtr;
1777         USHORT                  FreeNumber;
1778         USHORT                  subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1779         USHORT                  totalMPDUSize=0;
1780         UCHAR                   *subFrameHeader;
1781         UCHAR                   padding = 0;
1782         USHORT                  FirstTx = 0, LastTxIdx = 0;
1783         BOOLEAN                 bVLANPkt;
1784         int                     frameNum = 0;
1785         PQUEUE_ENTRY    pQEntry;
1786
1787
1788         ASSERT(pTxBlk);
1789
1790         ASSERT((pTxBlk->TxPacketList.Number > 1));
1791
1792         while(pTxBlk->TxPacketList.Head)
1793         {
1794                 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1795                 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1796                 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1797                 {
1798                         RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1799                         continue;
1800                 }
1801
1802                 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1803
1804                 // skip 802.3 header
1805                 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1806                 pTxBlk->SrcBufLen  -= LENGTH_802_3;
1807
1808                 // skip vlan tag
1809                 if (bVLANPkt)
1810                 {
1811                         pTxBlk->pSrcBufData     += LENGTH_802_1Q;
1812                         pTxBlk->SrcBufLen       -= LENGTH_802_1Q;
1813                 }
1814
1815                 if (frameNum == 0)
1816                 {
1817                         pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1818
1819                         // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1820                         RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1821                 }
1822                 else
1823                 {
1824                         pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1825                         padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1826                         NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1827                         pHeaderBufPtr += padding;
1828                         pTxBlk->MpduHeaderLen = padding;
1829                 }
1830
1831                 //
1832                 // A-MSDU subframe
1833                 //   DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1834                 //
1835                 subFrameHeader = pHeaderBufPtr;
1836                 subFramePayloadLen = pTxBlk->SrcBufLen;
1837
1838                 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1839
1840
1841                 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1842                 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1843
1844
1845                 //
1846                 // Insert LLC-SNAP encapsulation - 8 octets
1847                 //
1848                 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1849
1850                 subFramePayloadLen = pTxBlk->SrcBufLen;
1851
1852                 if (pTxBlk->pExtraLlcSnapEncap)
1853                 {
1854                         NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1855                         pHeaderBufPtr += 6;
1856                         // get 2 octets (TypeofLen)
1857                         NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1858                         pHeaderBufPtr += 2;
1859                         pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1860                         subFramePayloadLen += LENGTH_802_1_H;
1861                 }
1862
1863                 // update subFrame Length field
1864                 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1865                 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1866
1867                 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1868
1869                 if (frameNum ==0)
1870                         FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1871                 else
1872                         LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1873
1874                 frameNum++;
1875
1876                 pAd->RalinkCounters.KickTxCount++;
1877                 pAd->RalinkCounters.OneSecTxDoneCount++;
1878
1879                 // calculate Transmitted AMSDU Count and ByteCount
1880                 {
1881                         pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
1882                         pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
1883                 }
1884
1885         }
1886
1887         HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1888         HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1889
1890         //
1891         // Kick out Tx
1892         //
1893         HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1894 }
1895 #endif // DOT11_N_SUPPORT //
1896
1897 VOID STA_Legacy_Frame_Tx(
1898         IN      PRTMP_ADAPTER   pAd,
1899         IN      TX_BLK                  *pTxBlk)
1900 {
1901         HEADER_802_11   *pHeader_802_11;
1902         PUCHAR                  pHeaderBufPtr;
1903         USHORT                  FreeNumber;
1904         BOOLEAN                 bVLANPkt;
1905         PQUEUE_ENTRY    pQEntry;
1906
1907         ASSERT(pTxBlk);
1908
1909
1910         pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1911         pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1912         if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1913         {
1914                 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1915                 return;
1916         }
1917
1918         if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
1919         {
1920                 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1921         }
1922
1923         if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1924                 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1925         else
1926                 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1927
1928         bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1929
1930         if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1931                 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1932
1933         STAFindCipherAlgorithm(pAd, pTxBlk);
1934         STABuildCommon802_11Header(pAd, pTxBlk);
1935
1936
1937         // skip 802.3 header
1938         pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1939         pTxBlk->SrcBufLen  -= LENGTH_802_3;
1940
1941         // skip vlan tag
1942         if (bVLANPkt)
1943         {
1944                 pTxBlk->pSrcBufData     += LENGTH_802_1Q;
1945                 pTxBlk->SrcBufLen       -= LENGTH_802_1Q;
1946         }
1947
1948         pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1949         pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1950
1951         // skip common header
1952         pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1953
1954         if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1955         {
1956                 //
1957                 // build QOS Control bytes
1958                 //
1959                 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1960                 *(pHeaderBufPtr+1) = 0;
1961                 pHeaderBufPtr +=2;
1962                 pTxBlk->MpduHeaderLen += 2;
1963         }
1964
1965         // The remaining content of MPDU header should locate at 4-octets aligment
1966         pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1967         pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1968         pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1969
1970         {
1971
1972                 //
1973                 // Insert LLC-SNAP encapsulation - 8 octets
1974                 //
1975                 //
1976                 // if original Ethernet frame contains no LLC/SNAP,
1977                 // then an extra LLC/SNAP encap is required
1978                 //
1979                 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
1980                 if (pTxBlk->pExtraLlcSnapEncap)
1981                 {
1982                         UCHAR vlan_size;
1983
1984                         NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1985                         pHeaderBufPtr += 6;
1986                         // skip vlan tag
1987                         vlan_size =  (bVLANPkt) ? LENGTH_802_1Q : 0;
1988                         // get 2 octets (TypeofLen)
1989                         NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
1990                         pHeaderBufPtr += 2;
1991                         pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1992                 }
1993
1994         }
1995
1996         //
1997         // prepare for TXWI
1998         // use Wcid as Key Index
1999         //
2000
2001         RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2002
2003         //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2004
2005         HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2006
2007         pAd->RalinkCounters.KickTxCount++;
2008         pAd->RalinkCounters.OneSecTxDoneCount++;
2009
2010         //
2011         // Kick out Tx
2012         //
2013         HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2014 }
2015
2016
2017 VOID STA_ARalink_Frame_Tx(
2018         IN      PRTMP_ADAPTER   pAd,
2019         IN      TX_BLK                  *pTxBlk)
2020 {
2021         PUCHAR                  pHeaderBufPtr;
2022         USHORT                  FreeNumber;
2023         USHORT                  totalMPDUSize=0;
2024         USHORT                  FirstTx, LastTxIdx;
2025         int                     frameNum = 0;
2026         BOOLEAN                 bVLANPkt;
2027         PQUEUE_ENTRY    pQEntry;
2028
2029
2030         ASSERT(pTxBlk);
2031
2032         ASSERT((pTxBlk->TxPacketList.Number== 2));
2033
2034
2035         FirstTx = LastTxIdx = 0;  // Is it ok init they as 0?
2036         while(pTxBlk->TxPacketList.Head)
2037         {
2038                 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2039                 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2040
2041                 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2042                 {
2043                         RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2044                         continue;
2045                 }
2046
2047                 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2048
2049                 // skip 802.3 header
2050                 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2051                 pTxBlk->SrcBufLen  -= LENGTH_802_3;
2052
2053                 // skip vlan tag
2054                 if (bVLANPkt)
2055                 {
2056                         pTxBlk->pSrcBufData     += LENGTH_802_1Q;
2057                         pTxBlk->SrcBufLen       -= LENGTH_802_1Q;
2058                 }
2059
2060                 if (frameNum == 0)
2061                 {       // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2062
2063                         pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2064
2065                         // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2066                         //      will be updated after final frame was handled.
2067                         RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2068
2069
2070                         //
2071                         // Insert LLC-SNAP encapsulation - 8 octets
2072                         //
2073                         EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2074
2075                         if (pTxBlk->pExtraLlcSnapEncap)
2076                         {
2077                                 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2078                                 pHeaderBufPtr += 6;
2079                                 // get 2 octets (TypeofLen)
2080                                 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2081                                 pHeaderBufPtr += 2;
2082                                 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2083                         }
2084                 }
2085                 else
2086                 {       // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2087
2088                         pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2089                         pTxBlk->MpduHeaderLen = 0;
2090
2091                         // A-Ralink sub-sequent frame header is the same as 802.3 header.
2092                         //   DA(6)+SA(6)+FrameType(2)
2093                         NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2094                         pHeaderBufPtr += 12;
2095                         // get 2 octets (TypeofLen)
2096                         NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2097                         pHeaderBufPtr += 2;
2098                         pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2099                 }
2100
2101                 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2102
2103                 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2104                 if (frameNum ==0)
2105                         FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2106                 else
2107                         LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2108
2109                 frameNum++;
2110
2111                 pAd->RalinkCounters.OneSecTxAggregationCount++;
2112                 pAd->RalinkCounters.KickTxCount++;
2113                 pAd->RalinkCounters.OneSecTxDoneCount++;
2114
2115         }
2116
2117         HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2118         HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2119
2120         //
2121         // Kick out Tx
2122         //
2123         HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2124
2125 }
2126
2127
2128 VOID STA_Fragment_Frame_Tx(
2129         IN RTMP_ADAPTER *pAd,
2130         IN TX_BLK               *pTxBlk)
2131 {
2132         HEADER_802_11   *pHeader_802_11;
2133         PUCHAR                  pHeaderBufPtr;
2134         USHORT                  FreeNumber;
2135         UCHAR                   fragNum = 0;
2136         PACKET_INFO             PacketInfo;
2137         USHORT                  EncryptionOverhead = 0;
2138         UINT32                  FreeMpduSize, SrcRemainingBytes;
2139         USHORT                  AckDuration;
2140         UINT                    NextMpduSize;
2141         BOOLEAN                 bVLANPkt;
2142         PQUEUE_ENTRY    pQEntry;
2143
2144
2145         ASSERT(pTxBlk);
2146
2147         pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2148         pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2149         if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2150         {
2151                 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2152                 return;
2153         }
2154
2155         ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2156         bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2157
2158         STAFindCipherAlgorithm(pAd, pTxBlk);
2159         STABuildCommon802_11Header(pAd, pTxBlk);
2160
2161         if (pTxBlk->CipherAlg == CIPHER_TKIP)
2162         {
2163                 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2164                 if (pTxBlk->pPacket == NULL)
2165                         return;
2166                 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2167         }
2168
2169         // skip 802.3 header
2170         pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2171         pTxBlk->SrcBufLen  -= LENGTH_802_3;
2172
2173
2174         // skip vlan tag
2175         if (bVLANPkt)
2176         {
2177                 pTxBlk->pSrcBufData     += LENGTH_802_1Q;
2178                 pTxBlk->SrcBufLen       -= LENGTH_802_1Q;
2179         }
2180
2181         pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2182         pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2183
2184
2185         // skip common header
2186         pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2187
2188         if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2189         {
2190                 //
2191                 // build QOS Control bytes
2192                 //
2193                 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2194
2195                 *(pHeaderBufPtr+1) = 0;
2196                 pHeaderBufPtr +=2;
2197                 pTxBlk->MpduHeaderLen += 2;
2198         }
2199
2200         //
2201         // padding at front of LLC header
2202         // LLC header should locate at 4-octets aligment
2203         //
2204         pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2205         pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2206         pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2207
2208
2209
2210         //
2211         // Insert LLC-SNAP encapsulation - 8 octets
2212         //
2213         //
2214         // if original Ethernet frame contains no LLC/SNAP,
2215         // then an extra LLC/SNAP encap is required
2216         //
2217         EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2218         if (pTxBlk->pExtraLlcSnapEncap)
2219         {
2220                 UCHAR vlan_size;
2221
2222                 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2223                 pHeaderBufPtr += 6;
2224                 // skip vlan tag
2225                 vlan_size =  (bVLANPkt) ? LENGTH_802_1Q : 0;
2226                 // get 2 octets (TypeofLen)
2227                 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2228                 pHeaderBufPtr += 2;
2229                 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2230         }
2231
2232
2233         // If TKIP is used and fragmentation is required. Driver has to
2234         //      append TKIP MIC at tail of the scatter buffer
2235         //      MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2236         if (pTxBlk->CipherAlg == CIPHER_TKIP)
2237         {
2238
2239                 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2240                 //                      to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2241                 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2242                 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2243                 pTxBlk->SrcBufLen += 8;
2244                 pTxBlk->TotalFrameLen += 8;
2245                 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2246         }
2247
2248         //
2249         // calcuate the overhead bytes that encryption algorithm may add. This
2250         // affects the calculate of "duration" field
2251         //
2252         if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2253                 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2254         else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2255                 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2256         else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2257                 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2258         else if (pTxBlk->CipherAlg == CIPHER_AES)
2259                 EncryptionOverhead = 16;        // AES: IV[4] + EIV[4] + MIC[8]
2260         else
2261                 EncryptionOverhead = 0;
2262
2263         // decide how much time an ACK/CTS frame will consume in the air
2264         AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2265
2266         // Init the total payload length of this frame.
2267         SrcRemainingBytes = pTxBlk->SrcBufLen;
2268
2269         pTxBlk->TotalFragNum = 0xff;
2270
2271         do {
2272
2273                 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2274
2275                 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2276
2277                 if (SrcRemainingBytes <= FreeMpduSize)
2278                 {       // this is the last or only fragment
2279
2280                         pTxBlk->SrcBufLen = SrcRemainingBytes;
2281
2282                         pHeader_802_11->FC.MoreFrag = 0;
2283                         pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2284
2285                         // Indicate the lower layer that this's the last fragment.
2286                         pTxBlk->TotalFragNum = fragNum;
2287                 }
2288                 else
2289                 {       // more fragment is required
2290
2291                         pTxBlk->SrcBufLen = FreeMpduSize;
2292
2293                         NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2294                         pHeader_802_11->FC.MoreFrag = 1;
2295                         pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2296                 }
2297
2298                 if (fragNum == 0)
2299                         pTxBlk->FrameGap = IFS_HTTXOP;
2300                 else
2301                         pTxBlk->FrameGap = IFS_SIFS;
2302
2303                 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2304
2305                 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2306
2307                 pAd->RalinkCounters.KickTxCount++;
2308                 pAd->RalinkCounters.OneSecTxDoneCount++;
2309
2310                 // Update the frame number, remaining size of the NDIS packet payload.
2311
2312                 // space for 802.11 header.
2313                 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2314                         pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2315
2316                 fragNum++;
2317                 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2318                 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2319
2320                 pHeader_802_11->Frag++;  // increase Frag #
2321
2322         }while(SrcRemainingBytes > 0);
2323
2324         //
2325         // Kick out Tx
2326         //
2327         HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2328 }
2329
2330
2331 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status)                                                                               \
2332                 while(_pTxBlk->TxPacketList.Head)                                                                                                               \
2333                 {                                                                                                                                                                               \
2334                         _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList);                                                                     \
2335                         RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status);    \
2336                 }
2337
2338
2339 /*
2340         ========================================================================
2341
2342         Routine Description:
2343                 Copy frame from waiting queue into relative ring buffer and set
2344         appropriate ASIC register to kick hardware encryption before really
2345         sent out to air.
2346
2347         Arguments:
2348                 pAd     Pointer to our adapter
2349                 PNDIS_PACKET    Pointer to outgoing Ndis frame
2350                 NumberOfFrag    Number of fragment required
2351
2352         Return Value:
2353                 None
2354
2355         IRQL = DISPATCH_LEVEL
2356
2357         Note:
2358
2359         ========================================================================
2360 */
2361 NDIS_STATUS STAHardTransmit(
2362         IN PRTMP_ADAPTER        pAd,
2363         IN TX_BLK                       *pTxBlk,
2364         IN      UCHAR                   QueIdx)
2365 {
2366         NDIS_PACKET             *pPacket;
2367         PQUEUE_ENTRY    pQEntry;
2368
2369         // ---------------------------------------------
2370         // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2371         // ---------------------------------------------
2372         //
2373         ASSERT(pTxBlk->TxPacketList.Number);
2374         if (pTxBlk->TxPacketList.Head == NULL)
2375         {
2376                 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2377                 return NDIS_STATUS_FAILURE;
2378         }
2379
2380         pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2381
2382         // ------------------------------------------------------------------
2383         // STEP 1. WAKE UP PHY
2384         //              outgoing frame always wakeup PHY to prevent frame lost and
2385         //              turn off PSM bit to improve performance
2386         // ------------------------------------------------------------------
2387         // not to change PSM bit, just send this frame out?
2388         if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2389         {
2390             DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2391                 AsicForceWakeup(pAd, TRUE);
2392         }
2393
2394         // It should not change PSM bit, when APSD turn on.
2395         if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2396                 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2397                 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2398         {
2399                 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2400             (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2401                         MlmeSetPsmBit(pAd, PWR_ACTIVE);
2402         }
2403
2404         switch (pTxBlk->TxFrameType)
2405         {
2406 #ifdef DOT11_N_SUPPORT
2407                 case TX_AMPDU_FRAME:
2408                                 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2409                         break;
2410                 case TX_AMSDU_FRAME:
2411                                 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2412                         break;
2413 #endif // DOT11_N_SUPPORT //
2414                 case TX_LEGACY_FRAME:
2415                                 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2416                         break;
2417                 case TX_MCAST_FRAME:
2418                                 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2419                         break;
2420                 case TX_RALINK_FRAME:
2421                                 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2422                         break;
2423                 case TX_FRAG_FRAME:
2424                                 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2425                         break;
2426                 default:
2427                         {
2428                                 // It should not happened!
2429                                 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2430                                 while(pTxBlk->TxPacketList.Number)
2431                                 {
2432                                         pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2433                                         pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2434                                         if (pPacket)
2435                                                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2436                                 }
2437                         }
2438                         break;
2439         }
2440
2441         return (NDIS_STATUS_SUCCESS);
2442
2443 }
2444
2445 ULONG  HashBytesPolynomial(UCHAR *value, unsigned int len)
2446 {
2447    unsigned char *word = value;
2448    unsigned int ret = 0;
2449    unsigned int i;
2450
2451    for(i=0; i < len; i++)
2452    {
2453           int mod = i % 32;
2454           ret ^=(unsigned int) (word[i]) << mod;
2455           ret ^=(unsigned int) (word[i]) >> (32 - mod);
2456    }
2457    return ret;
2458 }
2459
2460 VOID Sta_Announce_or_Forward_802_3_Packet(
2461         IN      PRTMP_ADAPTER   pAd,
2462         IN      PNDIS_PACKET    pPacket,
2463         IN      UCHAR                   FromWhichBSSID)
2464 {
2465         if (TRUE
2466                 )
2467         {
2468                 announce_802_3_packet(pAd, pPacket);
2469         }
2470         else
2471         {
2472                 // release packet
2473                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2474         }
2475 }
2476