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