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