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