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