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