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