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