36969134696b9b0da3703540a938c35f78e6d868
[firefly-linux-kernel-4.4.55.git] / drivers / staging / rt2860 / common / cmm_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
28
29 #include "../rt_config.h"
30
31
32 UCHAR   SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
33 UCHAR   SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
34 // Add Cisco Aironet SNAP heade for CCX2 support
35 UCHAR   SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00};
36 UCHAR   CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02};
37 UCHAR   EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e};
38 UCHAR   EAPOL[] = {0x88, 0x8e};
39 UCHAR   TPID[] = {0x81, 0x00}; /* VLAN related */
40
41 UCHAR   IPX[] = {0x81, 0x37};
42 UCHAR   APPLE_TALK[] = {0x80, 0xf3};
43 UCHAR   RateIdToPlcpSignal[12] = {
44          0, /* RATE_1 */        1, /* RATE_2 */         2, /* RATE_5_5 */       3, /* RATE_11 */        // see BBP spec
45         11, /* RATE_6 */   15, /* RATE_9 */    10, /* RATE_12 */   14, /* RATE_18 */    // see IEEE802.11a-1999 p.14
46          9, /* RATE_24 */  13, /* RATE_36 */    8, /* RATE_48 */   12  /* RATE_54 */ }; // see IEEE802.11a-1999 p.14
47
48 UCHAR    OfdmSignalToRateId[16] = {
49         RATE_54,  RATE_54,      RATE_54,  RATE_54,      // OFDM PLCP Signal = 0,  1,  2,  3 respectively
50         RATE_54,  RATE_54,      RATE_54,  RATE_54,      // OFDM PLCP Signal = 4,  5,  6,  7 respectively
51         RATE_48,  RATE_24,      RATE_12,  RATE_6,       // OFDM PLCP Signal = 8,  9,  10, 11 respectively
52         RATE_54,  RATE_36,      RATE_18,  RATE_9,       // OFDM PLCP Signal = 12, 13, 14, 15 respectively
53 };
54
55 UCHAR    OfdmRateToRxwiMCS[12] = {
56         0,  0,  0,  0,
57         0,  1,  2,  3,  // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
58         4,  5,  6,  7,  // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
59 };
60 UCHAR    RxwiMCSToOfdmRate[12] = {
61         RATE_6,  RATE_9,        RATE_12,  RATE_18,
62         RATE_24,  RATE_36,      RATE_48,  RATE_54,      // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
63         4,  5,  6,  7,  // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
64 };
65
66 char*   MCSToMbps[] = {"1Mbps","2Mbps","5.5Mbps","11Mbps","06Mbps","09Mbps","12Mbps","18Mbps","24Mbps","36Mbps","48Mbps","54Mbps","MM-0","MM-1","MM-2","MM-3","MM-4","MM-5","MM-6","MM-7","MM-8","MM-9","MM-10","MM-11","MM-12","MM-13","MM-14","MM-15","MM-32","ee1","ee2","ee3"};
67
68 UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2};
69 //UCHAR default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1};
70 UCHAR default_sta_aifsn[]={3,7,2,2};
71
72 UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO};
73
74
75 /*
76         ========================================================================
77
78         Routine Description:
79                 API for MLME to transmit management frame to AP (BSS Mode)
80         or station (IBSS Mode)
81
82         Arguments:
83                 pAd Pointer to our adapter
84                 pData           Pointer to the outgoing 802.11 frame
85                 Length          Size of outgoing management frame
86
87         Return Value:
88                 NDIS_STATUS_FAILURE
89                 NDIS_STATUS_PENDING
90                 NDIS_STATUS_SUCCESS
91
92         IRQL = PASSIVE_LEVEL
93         IRQL = DISPATCH_LEVEL
94
95         Note:
96
97         ========================================================================
98 */
99 NDIS_STATUS MiniportMMRequest(
100         IN      PRTMP_ADAPTER   pAd,
101         IN      UCHAR                   QueIdx,
102         IN      PUCHAR                  pData,
103         IN      UINT                    Length)
104 {
105         PNDIS_PACKET    pPacket;
106         NDIS_STATUS     Status = NDIS_STATUS_SUCCESS;
107         ULONG                   FreeNum;
108         UCHAR                   rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
109 #ifdef RTMP_MAC_PCI
110         unsigned long   IrqFlags = 0;
111         UCHAR                   IrqState;
112 #endif // RTMP_MAC_PCI //
113         BOOLEAN                 bUseDataQ = FALSE;
114         int                     retryCnt = 0;
115
116         ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
117
118         if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG)
119         {
120                 bUseDataQ = TRUE;
121                 QueIdx &= (~MGMT_USE_QUEUE_FLAG);
122         }
123
124 #ifdef RTMP_MAC_PCI
125         // 2860C use Tx Ring
126         IrqState = pAd->irq_disabled;
127         if (pAd->MACVersion == 0x28600100)
128         {
129                 QueIdx = (bUseDataQ ==TRUE ? QueIdx : 3);
130                 bUseDataQ = TRUE;
131         }
132         if (bUseDataQ && (!IrqState))
133                 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
134 #endif // RTMP_MAC_PCI //
135
136         do
137         {
138                 // Reset is in progress, stop immediately
139                 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
140                          RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
141                          !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
142                 {
143                         Status = NDIS_STATUS_FAILURE;
144                         break;
145                 }
146
147                 // Check Free priority queue
148                 // Since we use PBF Queue2 for management frame.  Its corresponding DMA ring should be using TxRing.
149 #ifdef RTMP_MAC_PCI
150                 if (bUseDataQ)
151                 {
152                         retryCnt = MAX_DATAMM_RETRY;
153                         // free Tx(QueIdx) resources
154                         RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
155                         FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
156                 }
157                 else
158 #endif // RTMP_MAC_PCI //
159                 {
160                         FreeNum = GET_MGMTRING_FREENO(pAd);
161                 }
162
163                 if ((FreeNum > 0))
164                 {
165                         // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
166                         NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
167                         Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
168                         if (Status != NDIS_STATUS_SUCCESS)
169                         {
170                                 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
171                                 break;
172                         }
173
174                         //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
175                         //pAd->CommonCfg.MlmeRate = RATE_2;
176
177
178 #ifdef RTMP_MAC_PCI
179                         if (bUseDataQ)
180                         {
181                                 Status = MlmeDataHardTransmit(pAd, QueIdx, pPacket);
182                                 retryCnt--;
183                         }
184                         else
185 #endif // RTMP_MAC_PCI //
186                         Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
187                         if (Status == NDIS_STATUS_SUCCESS)
188                                 retryCnt = 0;
189                         else
190                                 RTMPFreeNdisPacket(pAd, pPacket);
191                 }
192                 else
193                 {
194                         pAd->RalinkCounters.MgmtRingFullCount++;
195 #ifdef RTMP_MAC_PCI
196                         if (bUseDataQ)
197                         {
198                                 retryCnt--;
199                                 DBGPRINT(RT_DEBUG_TRACE, ("retryCnt %d\n", retryCnt));
200                                 if (retryCnt == 0)
201                                 {
202                                         DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n",
203                                                                                         QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
204                                 }
205                         }
206 #endif // RTMP_MAC_PCI //
207                         DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
208                                                                                 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
209                 }
210         } while (retryCnt > 0);
211
212
213 #ifdef RTMP_MAC_PCI
214         if (bUseDataQ && (!IrqState))
215                 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
216 #endif // RTMP_MAC_PCI //
217
218         return Status;
219 }
220
221
222
223
224 /*
225         ========================================================================
226
227         Routine Description:
228                 Copy frame from waiting queue into relative ring buffer and set
229         appropriate ASIC register to kick hardware transmit function
230
231         Arguments:
232                 pAd Pointer to our adapter
233                 pBuffer         Pointer to      memory of outgoing frame
234                 Length          Size of outgoing management frame
235
236         Return Value:
237                 NDIS_STATUS_FAILURE
238                 NDIS_STATUS_PENDING
239                 NDIS_STATUS_SUCCESS
240
241         IRQL = PASSIVE_LEVEL
242         IRQL = DISPATCH_LEVEL
243
244         Note:
245
246         ========================================================================
247 */
248 NDIS_STATUS MlmeHardTransmit(
249         IN      PRTMP_ADAPTER   pAd,
250         IN      UCHAR                   QueIdx,
251         IN      PNDIS_PACKET    pPacket)
252 {
253         PACKET_INFO     PacketInfo;
254         PUCHAR                  pSrcBufVA;
255         UINT                    SrcBufLen;
256         PHEADER_802_11  pHeader_802_11;
257
258         if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
259                 )
260         {
261                 return NDIS_STATUS_FAILURE;
262         }
263
264         RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
265         if (pSrcBufVA == NULL)
266                 return NDIS_STATUS_FAILURE;
267
268         pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE);
269
270
271 #ifdef RTMP_MAC_PCI
272         if ( pAd->MACVersion == 0x28600100 )
273                 return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket);
274         else
275 #endif // RTMP_MAC_PCI //
276                 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
277
278 }
279
280
281 NDIS_STATUS MlmeHardTransmitMgmtRing(
282         IN      PRTMP_ADAPTER   pAd,
283         IN      UCHAR   QueIdx,
284         IN      PNDIS_PACKET    pPacket)
285 {
286         PACKET_INFO     PacketInfo;
287         PUCHAR                  pSrcBufVA;
288         UINT                    SrcBufLen;
289         PHEADER_802_11  pHeader_802_11;
290         BOOLEAN                 bAckRequired, bInsertTimestamp;
291         UCHAR                   MlmeRate;
292         PTXWI_STRUC     pFirstTxWI;
293         MAC_TABLE_ENTRY *pMacEntry = NULL;
294         UCHAR                   PID;
295
296         RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
297
298         // Make sure MGMT ring resource won't be used by other threads
299         RTMP_SEM_LOCK(&pAd->MgmtRingLock);
300         if (pSrcBufVA == NULL)
301         {
302                 // The buffer shouldn't be NULL
303                 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
304                 return NDIS_STATUS_FAILURE;
305         }
306
307         {
308         // outgoing frame always wakeup PHY to prevent frame lost
309         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
310                 AsicForceWakeup(pAd, TRUE);
311         }
312
313         pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA +  TXINFO_SIZE);
314         pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
315
316         if (pHeader_802_11->Addr1[0] & 0x01)
317         {
318                 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
319         }
320         else
321         {
322                 MlmeRate = pAd->CommonCfg.MlmeRate;
323         }
324
325         // Verify Mlme rate for a / g bands.
326         if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
327                 MlmeRate = RATE_6;
328
329         if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
330                 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
331         {
332                 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
333         }
334
335         {
336                 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
337                 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
338                         || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
339                 )
340                 {
341                         if (pAd->LatchRfRegs.Channel > 14)
342                                 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
343                         else
344                                 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
345                 }
346         }
347
348         //
349         // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
350         // Snice it's been set to 0 while on MgtMacHeaderInit
351         // By the way this will cause frame to be send on PWR_SAVE failed.
352         //
353         pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; // (pAd->StaCfg.Psm == PWR_SAVE);
354
355         //
356         // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
357     // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
358 //      if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
359         {
360                 if ((pHeader_802_11->FC.SubType == SUBTYPE_ACTION) ||
361                         ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
362                         ((pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL) ||
363                         (pHeader_802_11->FC.SubType == SUBTYPE_NULL_FUNC))))
364                 {
365                         if (pAd->StaCfg.Psm == PWR_SAVE)
366                         pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
367                 else
368                                 pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave;
369         }
370         }
371
372
373
374
375
376         bInsertTimestamp = FALSE;
377         if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
378         {
379                 //Set PM bit in ps-poll, to fix WLK 1.2  PowerSaveMode_ext failure issue.
380                 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
381                 {
382                         pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
383                 }
384                 bAckRequired = FALSE;
385         }
386         else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
387         {
388                 //pAd->Sequence++;
389                 //pHeader_802_11->Sequence = pAd->Sequence;
390
391                 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
392                 {
393                         bAckRequired = FALSE;
394                         pHeader_802_11->Duration = 0;
395                 }
396                 else
397                 {
398                         bAckRequired = TRUE;
399                         pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
400                         if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) && (pHeader_802_11->FC.Type == BTYPE_MGMT))
401                         {
402                                 bInsertTimestamp = TRUE;
403                                 bAckRequired = FALSE; // Disable ACK to prevent retry 0x1f for Probe Response
404                         }
405                         else if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) && (pHeader_802_11->FC.Type == BTYPE_MGMT))
406                         {
407                                 bAckRequired = FALSE; // Disable ACK to prevent retry 0x1f for Probe Request
408                         }
409                 }
410         }
411
412         pHeader_802_11->Sequence = pAd->Sequence++;
413         if (pAd->Sequence >0xfff)
414                 pAd->Sequence = 0;
415
416         // Before radar detection done, mgmt frame can not be sent but probe req
417         // Because we need to use probe req to trigger driver to send probe req in passive scan
418         if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
419                 && (pAd->CommonCfg.bIEEE80211H == 1)
420                 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
421         {
422                 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
423 //              if (!IrqState)
424                 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
425                 return (NDIS_STATUS_FAILURE);
426         }
427
428
429         //
430         // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
431         // should always has only one physical buffer, and the whole frame size equals
432         // to the first scatter buffer size
433         //
434
435         // Initialize TX Descriptor
436         // For inter-frame gap, the number is for this frame and next frame
437         // For MLME rate, we will fix as 2Mb to match other vendor's implement
438 //      pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
439
440 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
441         PID = PID_MGMT;
442
443
444         if (pMacEntry == NULL)
445         {
446                 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
447                 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID, 0,  (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
448         }
449         else
450         {
451                 /* dont use low rate to send QoS Null data frame */
452                 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
453                                         bInsertTimestamp, FALSE, bAckRequired, FALSE,
454                                         0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
455                                         pMacEntry->MaxHTPhyMode.field.MCS, 0,
456                                         (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
457                                         IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
458         }
459
460         // Now do hardware-depened kick out.
461         HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
462
463         // Make sure to release MGMT ring resource
464 //      if (!IrqState)
465         RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
466         return NDIS_STATUS_SUCCESS;
467 }
468
469
470 /********************************************************************************
471
472         New DeQueue Procedures.
473
474  ********************************************************************************/
475
476 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags)                               \
477                         do{                                                                                                     \
478                                 if (bIntContext == FALSE)                                               \
479                                 RTMP_IRQ_LOCK((lock), IrqFlags);                \
480                         }while(0)
481
482 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags)                             \
483                         do{                                                                                                     \
484                                 if (bIntContext == FALSE)                                               \
485                                         RTMP_IRQ_UNLOCK((lock), IrqFlags);      \
486                         }while(0)
487
488 /*
489         ========================================================================
490         Tx Path design algorithm:
491                 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
492                 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
493                                 Classification Rule=>
494                                         Multicast: (*addr1 & 0x01) == 0x01
495                                         Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
496                                         11N Rate : If peer support HT
497                                                                 (1).AMPDU  -- If TXBA is negotiated.
498                                                                 (2).AMSDU  -- If AMSDU is capable for both peer and ourself.
499                                                                                         *). AMSDU can embedded in a AMPDU, but now we didn't support it.
500                                                                 (3).Normal -- Other packets which send as 11n rate.
501
502                                         B/G Rate : If peer is b/g only.
503                                                                 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
504                                                                 (2).Normal -- Other packets which send as b/g rate.
505                                         Fragment:
506                                                                 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
507
508                                 Classified Packet Handle Rule=>
509                                         Multicast:
510                                                                 No ACK,                 //pTxBlk->bAckRequired = FALSE;
511                                                                 No WMM,                 //pTxBlk->bWMM = FALSE;
512                                                                 No piggyback,   //pTxBlk->bPiggyBack = FALSE;
513                                                                 Force LowRate,  //pTxBlk->bForceLowRate = TRUE;
514                                         Specific :      Basically, for specific packet, we should handle it specifically, but now all specific packets are use
515                                                                         the same policy to handle it.
516                                                                 Force LowRate,  //pTxBlk->bForceLowRate = TRUE;
517
518                                         11N Rate :
519                                                                 No piggyback,   //pTxBlk->bPiggyBack = FALSE;
520
521                                                                 (1).AMSDU
522                                                                         pTxBlk->bWMM = TRUE;
523                                                                 (2).AMPDU
524                                                                         pTxBlk->bWMM = TRUE;
525                                                                 (3).Normal
526
527                                         B/G Rate :
528                                                                 (1).ARALINK
529
530                                                                 (2).Normal
531         ========================================================================
532 */
533 static UCHAR TxPktClassification(
534         IN RTMP_ADAPTER *pAd,
535         IN PNDIS_PACKET  pPacket)
536 {
537         UCHAR                   TxFrameType = TX_UNKOWN_FRAME;
538         UCHAR                   Wcid;
539         MAC_TABLE_ENTRY *pMacEntry = NULL;
540         BOOLEAN                 bHTRate = FALSE;
541
542         Wcid = RTMP_GET_PACKET_WCID(pPacket);
543         if (Wcid == MCAST_WCID)
544         {       // Handle for RA is Broadcast/Multicast Address.
545                 return TX_MCAST_FRAME;
546         }
547
548         // Handle for unicast packets
549         pMacEntry = &pAd->MacTab.Content[Wcid];
550         if (RTMP_GET_PACKET_LOWRATE(pPacket))
551         {       // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
552                 TxFrameType = TX_LEGACY_FRAME;
553         }
554         else if (IS_HT_RATE(pMacEntry))
555         {       // it's a 11n capable packet
556
557                 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
558                 //      Currently didn't support A-MSDU embedded in A-MPDU
559                 bHTRate = TRUE;
560                 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
561                         TxFrameType = TX_LEGACY_FRAME;
562                 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
563                         return TX_AMPDU_FRAME;
564                 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
565                         return TX_AMSDU_FRAME;
566                 else
567                         TxFrameType = TX_LEGACY_FRAME;
568         }
569         else
570         {       // it's a legacy b/g packet.
571                 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
572                         (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
573                         (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
574                 {       // if peer support Ralink Aggregation, we use it.
575                         TxFrameType = TX_RALINK_FRAME;
576                 }
577                 else
578                 {
579                         TxFrameType = TX_LEGACY_FRAME;
580                 }
581         }
582
583         // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
584         if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
585                 TxFrameType = TX_FRAG_FRAME;
586
587         return TxFrameType;
588 }
589
590
591 BOOLEAN RTMP_FillTxBlkInfo(
592         IN RTMP_ADAPTER *pAd,
593         IN TX_BLK *pTxBlk)
594 {
595         PACKET_INFO                     PacketInfo;
596         PNDIS_PACKET            pPacket;
597         PMAC_TABLE_ENTRY        pMacEntry = NULL;
598
599         pPacket = pTxBlk->pPacket;
600         RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
601
602         pTxBlk->Wcid                            = RTMP_GET_PACKET_WCID(pPacket);
603         pTxBlk->apidx                           = RTMP_GET_PACKET_IF(pPacket);
604         pTxBlk->UserPriority            = RTMP_GET_PACKET_UP(pPacket);
605         pTxBlk->FrameGap = IFS_HTTXOP;          // ASIC determine Frame Gap
606
607         if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
608                 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
609         else
610                 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
611
612         // Default to clear this flag
613         TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
614
615
616         if (pTxBlk->Wcid == MCAST_WCID)
617         {
618                 pTxBlk->pMacEntry = NULL;
619                 {
620                                 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
621                 }
622
623                 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);    // AckRequired = FALSE, when broadcast packet in Adhoc mode.
624                 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
625                 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
626                 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
627                 if (RTMP_GET_PACKET_MOREDATA(pPacket))
628                 {
629                         TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
630                 }
631
632         }
633         else
634         {
635                 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
636                 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
637
638                 pMacEntry = pTxBlk->pMacEntry;
639
640
641                 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
642                 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
643                         TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
644                 else
645                         TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
646
647                 if ((pAd->OpMode == OPMODE_STA) &&
648                         (ADHOC_ON(pAd)) &&
649                         (RX_FILTER_TEST_FLAG(pAd, fRX_FILTER_ACCEPT_PROMISCUOUS)))
650                 {
651                         if(pAd->CommonCfg.PSPXlink)
652                                 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
653                 }
654
655                 {
656                 {
657
658                         // If support WMM, enable it.
659                         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
660                                 CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
661                                 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
662
663 //                              if (pAd->StaCfg.bAutoTxRateSwitch)
664 //                                      TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch);
665                         }
666                 }
667
668                 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
669                 {
670                         if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
671                 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
672                         {       // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
673                                 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
674
675                                 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
676                                 if (IS_HT_STA(pTxBlk->pMacEntry) &&
677                                         (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
678                                         ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
679                                 {
680                                         TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
681                                         TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
682                                 }
683                         }
684
685                         if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
686                                 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
687                         {       // Currently piggy-back only support when peer is operate in b/g mode.
688                                 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
689                         }
690
691                         if (RTMP_GET_PACKET_MOREDATA(pPacket))
692                         {
693                                 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
694                         }
695                 }
696                 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
697                 {
698                         TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
699                 }
700
701                 pMacEntry->DebugTxCount++;
702         }
703
704         return TRUE;
705 }
706
707
708 BOOLEAN CanDoAggregateTransmit(
709         IN RTMP_ADAPTER *pAd,
710         IN NDIS_PACKET *pPacket,
711         IN TX_BLK               *pTxBlk)
712 {
713
714         //DBGPRINT(RT_DEBUG_TRACE, ("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType));
715
716         if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
717                 return FALSE;
718
719         if (RTMP_GET_PACKET_DHCP(pPacket) ||
720                 RTMP_GET_PACKET_EAPOL(pPacket) ||
721                 RTMP_GET_PACKET_WAI(pPacket))
722                 return FALSE;
723
724         if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
725                 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
726         {       // For AMSDU, allow the packets with total length < max-amsdu size
727                 return FALSE;
728         }
729
730         if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
731                 (pTxBlk->TxPacketList.Number == 2))
732         {       // For RALINK-Aggregation, allow two frames in one batch.
733                 return FALSE;
734         }
735
736         if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
737                 return TRUE;
738         else
739                 return FALSE;
740
741 }
742
743
744 /*
745         ========================================================================
746
747         Routine Description:
748                 To do the enqueue operation and extract the first item of waiting
749                 list. If a number of available shared memory segments could meet
750                 the request of extracted item, the extracted item will be fragmented
751                 into shared memory segments.
752
753         Arguments:
754                 pAd Pointer to our adapter
755                 pQueue          Pointer to Waiting Queue
756
757         Return Value:
758                 None
759
760         IRQL = DISPATCH_LEVEL
761
762         Note:
763
764         ========================================================================
765 */
766 VOID RTMPDeQueuePacket(
767         IN  PRTMP_ADAPTER   pAd,
768         IN  BOOLEAN         bIntContext,
769         IN  UCHAR                       QIdx, /* BulkOutPipeId */
770         IN  UCHAR           Max_Tx_Packets)
771 {
772         PQUEUE_ENTRY    pEntry = NULL;
773         PNDIS_PACKET    pPacket;
774         NDIS_STATUS     Status = NDIS_STATUS_SUCCESS;
775         UCHAR           Count=0;
776         PQUEUE_HEADER   pQueue;
777         ULONG           FreeNumber[NUM_OF_TX_RING];
778         UCHAR                   QueIdx, sQIdx, eQIdx;
779         unsigned long   IrqFlags = 0;
780         BOOLEAN                 hasTxDesc = FALSE;
781         TX_BLK                  TxBlk;
782         TX_BLK                  *pTxBlk;
783
784
785
786         if (QIdx == NUM_OF_TX_RING)
787         {
788                 sQIdx = 0;
789                 eQIdx = 3;      // 4 ACs, start from 0.
790         }
791         else
792         {
793                 sQIdx = eQIdx = QIdx;
794         }
795
796         for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
797         {
798                 Count=0;
799
800                 RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags);
801
802
803                 while (1)
804                 {
805                         if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
806                                                                                 fRTMP_ADAPTER_RADIO_OFF |
807                                                                                 fRTMP_ADAPTER_RESET_IN_PROGRESS |
808                                                                                 fRTMP_ADAPTER_HALT_IN_PROGRESS |
809                                                                                 fRTMP_ADAPTER_NIC_NOT_EXIST))))
810                         {
811                                 RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
812                                 return;
813                         }
814
815                         if (Count >= Max_Tx_Packets)
816                                 break;
817
818                         DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
819                         if (&pAd->TxSwQueue[QueIdx] == NULL)
820                         {
821                                 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
822                                 break;
823                         }
824
825 #ifdef RTMP_MAC_PCI
826                         FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
827
828
829                         if (FreeNumber[QueIdx] <= 5)
830                         {
831                                 // free Tx(QueIdx) resources
832                                 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
833                                 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
834                         }
835 #endif // RTMP_MAC_PCI //
836
837                         // probe the Queue Head
838                         pQueue = &pAd->TxSwQueue[QueIdx];
839                         if ((pEntry = pQueue->Head) == NULL)
840                         {
841                                 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
842                                 break;
843                         }
844
845                         pTxBlk = &TxBlk;
846                         NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
847                         //InitializeQueueHeader(&pTxBlk->TxPacketList);         // Didn't need it because we already memzero it.
848                         pTxBlk->QueIdx = QueIdx;
849
850                         pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
851
852
853                         // Early check to make sure we have enoguh Tx Resource.
854                         hasTxDesc = RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
855                         if (!hasTxDesc)
856                         {
857                                 pAd->PrivateInfo.TxRingFullCnt++;
858
859                                 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
860
861                                 break;
862                         }
863
864                         pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
865                         pEntry = RemoveHeadQueue(pQueue);
866                         pTxBlk->TotalFrameNum++;
867                         pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket);     // The real fragment number maybe vary
868                         pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
869                         pTxBlk->pPacket = pPacket;
870                         InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
871
872                         if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
873                         {
874                                 // Enhance SW Aggregation Mechanism
875                                 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
876                                 {
877                                         InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
878                                         DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
879                                         break;
880                                 }
881
882                                 do{
883                                         if((pEntry = pQueue->Head) == NULL)
884                                                 break;
885
886                                         // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
887                                         pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
888                                         FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
889                                         hasTxDesc = RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
890                                         if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
891                                                 break;
892
893                                         //Remove the packet from the TxSwQueue and insert into pTxBlk
894                                         pEntry = RemoveHeadQueue(pQueue);
895                                         ASSERT(pEntry);
896                                         pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
897                                         pTxBlk->TotalFrameNum++;
898                                         pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket);     // The real fragment number maybe vary
899                                         pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
900                                         InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
901                                 }while(1);
902
903                                 if (pTxBlk->TxPacketList.Number == 1)
904                                         pTxBlk->TxFrameType = TX_LEGACY_FRAME;
905                         }
906
907 #ifdef RTMP_MAC_USB
908                         DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
909 #endif // RTMP_MAC_USB //
910                         Count += pTxBlk->TxPacketList.Number;
911
912                         // Do HardTransmit now.
913                         Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
914
915 #ifdef RTMP_MAC_PCI
916                         DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
917                         // static rate also need NICUpdateFifoStaCounters() function.
918                         //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
919                                 NICUpdateFifoStaCounters(pAd);
920 #endif // RTMP_MAC_PCI //
921
922                 }
923
924                 RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
925
926 #ifdef RTMP_MAC_USB
927                 if (!hasTxDesc)
928                         RTUSBKickBulkOut(pAd);
929 #endif // RTMP_MAC_USB //
930         }
931
932 }
933
934
935 /*
936         ========================================================================
937
938         Routine Description:
939                 Calculates the duration which is required to transmit out frames
940         with given size and specified rate.
941
942         Arguments:
943                 pAd     Pointer to our adapter
944                 Rate                    Transmit rate
945                 Size                    Frame size in units of byte
946
947         Return Value:
948                 Duration number in units of usec
949
950         IRQL = PASSIVE_LEVEL
951         IRQL = DISPATCH_LEVEL
952
953         Note:
954
955         ========================================================================
956 */
957 USHORT  RTMPCalcDuration(
958         IN      PRTMP_ADAPTER   pAd,
959         IN      UCHAR                   Rate,
960         IN      ULONG                   Size)
961 {
962         ULONG   Duration = 0;
963
964         if (Rate < RATE_FIRST_OFDM_RATE) // CCK
965         {
966                 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
967                         Duration = 96;  // 72+24 preamble+plcp
968                 else
969                         Duration = 192; // 144+48 preamble+plcp
970
971                 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
972                 if ((Size << 4) % RateIdTo500Kbps[Rate])
973                         Duration ++;
974         }
975         else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
976         {
977                 Duration = 20 + 6;              // 16+4 preamble+plcp + Signal Extension
978                 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
979                 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
980                         Duration += 4;
981         }
982         else    //mimo rate
983         {
984                 Duration = 20 + 6;              // 16+4 preamble+plcp + Signal Extension
985         }
986
987         return (USHORT)Duration;
988 }
989
990
991 /*
992         ========================================================================
993
994         Routine Description:
995                 Calculates the duration which is required to transmit out frames
996         with given size and specified rate.
997
998         Arguments:
999                 pTxWI           Pointer to head of each MPDU to HW.
1000                 Ack             Setting for Ack requirement bit
1001                 Fragment        Setting for Fragment bit
1002                 RetryMode       Setting for retry mode
1003                 Ifs             Setting for IFS gap
1004                 Rate            Setting for transmit rate
1005                 Service         Setting for service
1006                 Length          Frame length
1007                 TxPreamble      Short or Long preamble when using CCK rates
1008                 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1009
1010         Return Value:
1011                 None
1012
1013         IRQL = PASSIVE_LEVEL
1014         IRQL = DISPATCH_LEVEL
1015
1016     See also : BASmartHardTransmit()    !!!
1017
1018         ========================================================================
1019 */
1020 VOID RTMPWriteTxWI(
1021         IN      PRTMP_ADAPTER   pAd,
1022         IN      PTXWI_STRUC     pOutTxWI,
1023         IN      BOOLEAN                 FRAG,
1024         IN      BOOLEAN                 CFACK,
1025         IN      BOOLEAN                 InsTimestamp,
1026         IN      BOOLEAN                 AMPDU,
1027         IN      BOOLEAN                 Ack,
1028         IN      BOOLEAN                 NSeq,           // HW new a sequence.
1029         IN      UCHAR                   BASize,
1030         IN      UCHAR                   WCID,
1031         IN      ULONG                   Length,
1032         IN      UCHAR                   PID,
1033         IN      UCHAR                   TID,
1034         IN      UCHAR                   TxRate,
1035         IN      UCHAR                   Txopmode,
1036         IN      BOOLEAN                 CfAck,
1037         IN      HTTRANSMIT_SETTING      *pTransmit)
1038 {
1039         PMAC_TABLE_ENTRY        pMac = NULL;
1040         TXWI_STRUC              TxWI;
1041         PTXWI_STRUC     pTxWI;
1042
1043         if (WCID < MAX_LEN_OF_MAC_TABLE)
1044                 pMac = &pAd->MacTab.Content[WCID];
1045
1046         //
1047         // Always use Long preamble before verifiation short preamble functionality works well.
1048         // Todo: remove the following line if short preamble functionality works
1049         //
1050         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1051         NdisZeroMemory(&TxWI, TXWI_SIZE);
1052         pTxWI = &TxWI;
1053
1054         pTxWI->FRAG= FRAG;
1055
1056         pTxWI->CFACK = CFACK;
1057         pTxWI->TS= InsTimestamp;
1058         pTxWI->AMPDU = AMPDU;
1059         pTxWI->ACK = Ack;
1060         pTxWI->txop= Txopmode;
1061
1062         pTxWI->NSEQ = NSeq;
1063         // John tune the performace with Intel Client in 20 MHz performance
1064         BASize = pAd->CommonCfg.TxBASize;
1065         if (pAd->MACVersion == 0x28720200)
1066         {
1067                 if( BASize >13 )
1068                         BASize =13;
1069         }
1070         else
1071         {
1072         if( BASize >7 )
1073                 BASize =7;
1074         }
1075         pTxWI->BAWinSize = BASize;
1076         pTxWI->ShortGI = pTransmit->field.ShortGI;
1077         pTxWI->STBC = pTransmit->field.STBC;
1078
1079         pTxWI->WirelessCliID = WCID;
1080         pTxWI->MPDUtotalByteCount = Length;
1081         pTxWI->PacketId = PID;
1082
1083         // If CCK or OFDM, BW must be 20
1084         pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1085
1086         pTxWI->MCS = pTransmit->field.MCS;
1087         pTxWI->PHYMODE = pTransmit->field.MODE;
1088         pTxWI->CFACK = CfAck;
1089
1090         if (pMac)
1091         {
1092                 if (pAd->CommonCfg.bMIMOPSEnable)
1093                 {
1094                         if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1095                         {
1096                                 // Dynamic MIMO Power Save Mode
1097                                 pTxWI->MIMOps = 1;
1098                         }
1099                         else if (pMac->MmpsMode == MMPS_STATIC)
1100                         {
1101                                 // Static MIMO Power Save Mode
1102                                 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1103                                 {
1104                                         pTxWI->MCS = 7;
1105                                         pTxWI->MIMOps = 0;
1106                                 }
1107                         }
1108                 }
1109                 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1110                 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1111                 {
1112                         pTxWI->MpduDensity = 7;
1113                 }
1114                 else
1115                 {
1116                         pTxWI->MpduDensity = pMac->MpduDensity;
1117                 }
1118         }
1119
1120         pTxWI->PacketId = pTxWI->MCS;
1121         NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1122 }
1123
1124
1125 VOID RTMPWriteTxWI_Data(
1126         IN      PRTMP_ADAPTER           pAd,
1127         IN      OUT PTXWI_STRUC         pTxWI,
1128         IN      TX_BLK                          *pTxBlk)
1129 {
1130         HTTRANSMIT_SETTING      *pTransmit;
1131         PMAC_TABLE_ENTRY        pMacEntry;
1132         UCHAR                           BASize;
1133
1134         ASSERT(pTxWI);
1135
1136         pTransmit = pTxBlk->pTransmit;
1137         pMacEntry = pTxBlk->pMacEntry;
1138
1139
1140         //
1141         // Always use Long preamble before verifiation short preamble functionality works well.
1142         // Todo: remove the following line if short preamble functionality works
1143         //
1144         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1145         NdisZeroMemory(pTxWI, TXWI_SIZE);
1146
1147         pTxWI->FRAG             = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1148         pTxWI->ACK              = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1149         pTxWI->txop             = pTxBlk->FrameGap;
1150
1151                 pTxWI->WirelessCliID            = pTxBlk->Wcid;
1152
1153         pTxWI->MPDUtotalByteCount       = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1154         pTxWI->CFACK                            = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1155
1156         // If CCK or OFDM, BW must be 20
1157         pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1158         pTxWI->AMPDU    = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1159
1160         // John tune the performace with Intel Client in 20 MHz performance
1161         BASize = pAd->CommonCfg.TxBASize;
1162         if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1163         {
1164                 UCHAR           RABAOriIdx = 0; //The RA's BA Originator table index.
1165
1166                 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1167                 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1168         }
1169
1170         pTxWI->TxBF = pTransmit->field.TxBF;
1171         pTxWI->BAWinSize = BASize;
1172         pTxWI->ShortGI = pTransmit->field.ShortGI;
1173         pTxWI->STBC = pTransmit->field.STBC;
1174
1175         pTxWI->MCS = pTransmit->field.MCS;
1176         pTxWI->PHYMODE = pTransmit->field.MODE;
1177
1178         if (pMacEntry)
1179         {
1180                 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1181                 {
1182                         // Dynamic MIMO Power Save Mode
1183                         pTxWI->MIMOps = 1;
1184                 }
1185                 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1186                 {
1187                         // Static MIMO Power Save Mode
1188                         if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1189                         {
1190                                 pTxWI->MCS = 7;
1191                                 pTxWI->MIMOps = 0;
1192                         }
1193                 }
1194
1195                 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1196                 {
1197                         pTxWI->MpduDensity = 7;
1198                 }
1199                 else
1200                 {
1201                         pTxWI->MpduDensity = pMacEntry->MpduDensity;
1202                 }
1203         }
1204
1205
1206         // for rate adapation
1207         pTxWI->PacketId = pTxWI->MCS;
1208 }
1209
1210
1211 VOID RTMPWriteTxWI_Cache(
1212         IN      PRTMP_ADAPTER           pAd,
1213         IN      OUT PTXWI_STRUC         pTxWI,
1214         IN      TX_BLK                          *pTxBlk)
1215 {
1216         PHTTRANSMIT_SETTING     /*pTxHTPhyMode,*/ pTransmit;
1217         PMAC_TABLE_ENTRY        pMacEntry;
1218
1219         //
1220         // update TXWI
1221         //
1222         pMacEntry = pTxBlk->pMacEntry;
1223         pTransmit = pTxBlk->pTransmit;
1224
1225         //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1226         //if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry))
1227         //if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch))
1228         if (pMacEntry->bAutoTxRateSwitch)
1229         {
1230                 pTxWI->txop = IFS_HTTXOP;
1231
1232                 // If CCK or OFDM, BW must be 20
1233                 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1234                 pTxWI->ShortGI = pTransmit->field.ShortGI;
1235                 pTxWI->STBC = pTransmit->field.STBC;
1236
1237                 pTxWI->MCS = pTransmit->field.MCS;
1238                 pTxWI->PHYMODE = pTransmit->field.MODE;
1239
1240                 // set PID for TxRateSwitching
1241                 pTxWI->PacketId = pTransmit->field.MCS;
1242         }
1243
1244         pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1245         pTxWI->MIMOps = 0;
1246
1247         if (pAd->CommonCfg.bMIMOPSEnable)
1248         {
1249                 // MIMO Power Save Mode
1250                 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1251                 {
1252                         // Dynamic MIMO Power Save Mode
1253                         pTxWI->MIMOps = 1;
1254                 }
1255                 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1256                 {
1257                         // Static MIMO Power Save Mode
1258                         if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1259                         {
1260                                 pTxWI->MCS = 7;
1261                                 pTxWI->MIMOps = 0;
1262                         }
1263                 }
1264         }
1265
1266
1267         pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1268
1269 }
1270
1271
1272 // should be called only when -
1273 // 1. MEADIA_CONNECTED
1274 // 2. AGGREGATION_IN_USED
1275 // 3. Fragmentation not in used
1276 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1277 BOOLEAN TxFrameIsAggregatible(
1278         IN      PRTMP_ADAPTER   pAd,
1279         IN      PUCHAR                  pPrevAddr1,
1280         IN      PUCHAR                  p8023hdr)
1281 {
1282
1283         // can't aggregate EAPOL (802.1x) frame
1284         if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1285                 return FALSE;
1286
1287         // can't aggregate multicast/broadcast frame
1288         if (p8023hdr[0] & 0x01)
1289                 return FALSE;
1290
1291         if (INFRA_ON(pAd)) // must be unicast to AP
1292                 return TRUE;
1293         else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1294                 return TRUE;
1295         else
1296                 return FALSE;
1297 }
1298
1299
1300 /*
1301         ========================================================================
1302
1303         Routine Description:
1304            Check the MSDU Aggregation policy
1305         1.HT aggregation is A-MSDU
1306         2.legaacy rate aggregation is software aggregation by Ralink.
1307
1308         Arguments:
1309
1310         Return Value:
1311
1312         Note:
1313
1314         ========================================================================
1315 */
1316 BOOLEAN PeerIsAggreOn(
1317         IN      PRTMP_ADAPTER   pAd,
1318         IN      ULONG              TxRate,
1319         IN      PMAC_TABLE_ENTRY pMacEntry)
1320 {
1321         ULONG   AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1322
1323         if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1324         {
1325                 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1326                 {
1327                         return TRUE;
1328                 }
1329
1330 #ifdef AGGREGATION_SUPPORT
1331                 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1332                 {       // legacy  Ralink Aggregation support
1333                         return TRUE;
1334                 }
1335 #endif // AGGREGATION_SUPPORT //
1336         }
1337
1338         return FALSE;
1339
1340 }
1341
1342
1343 /*
1344         ========================================================================
1345
1346         Routine Description:
1347                 Check and fine the packet waiting in SW queue with highest priority
1348
1349         Arguments:
1350                 pAd Pointer to our adapter
1351
1352         Return Value:
1353                 pQueue          Pointer to Waiting Queue
1354
1355         IRQL = DISPATCH_LEVEL
1356
1357         Note:
1358
1359         ========================================================================
1360 */
1361 PQUEUE_HEADER   RTMPCheckTxSwQueue(
1362         IN      PRTMP_ADAPTER   pAd,
1363         OUT PUCHAR                      pQueIdx)
1364 {
1365
1366         ULONG   Number;
1367         // 2004-11-15 to be removed. test aggregation only
1368 //      if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2))
1369 //               return NULL;
1370
1371         Number = pAd->TxSwQueue[QID_AC_BK].Number
1372                          + pAd->TxSwQueue[QID_AC_BE].Number
1373                          + pAd->TxSwQueue[QID_AC_VI].Number
1374                          + pAd->TxSwQueue[QID_AC_VO].Number;
1375
1376         if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1377         {
1378                 *pQueIdx = QID_AC_VO;
1379                 return (&pAd->TxSwQueue[QID_AC_VO]);
1380         }
1381         else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1382         {
1383                 *pQueIdx = QID_AC_VI;
1384                 return (&pAd->TxSwQueue[QID_AC_VI]);
1385         }
1386         else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1387         {
1388                 *pQueIdx = QID_AC_BE;
1389                 return (&pAd->TxSwQueue[QID_AC_BE]);
1390         }
1391         else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1392         {
1393                 *pQueIdx = QID_AC_BK;
1394                 return (&pAd->TxSwQueue[QID_AC_BK]);
1395         }
1396
1397         // No packet pending in Tx Sw queue
1398         *pQueIdx = QID_AC_BK;
1399
1400         return (NULL);
1401 }
1402
1403
1404 /*
1405         ========================================================================
1406
1407         Routine Description:
1408                 Suspend MSDU transmission
1409
1410         Arguments:
1411                 pAd     Pointer to our adapter
1412
1413         Return Value:
1414                 None
1415
1416         Note:
1417
1418         ========================================================================
1419 */
1420 VOID    RTMPSuspendMsduTransmission(
1421         IN      PRTMP_ADAPTER   pAd)
1422 {
1423         DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1424
1425
1426         //
1427         // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1428         // use Lowbound as R66 value on ScanNextChannel(...)
1429         //
1430         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1431
1432         // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1433         //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
1434         RTMPSetAGCInitValue(pAd, BW_20);
1435
1436         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1437         //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000);                // abort all TX rings
1438 }
1439
1440
1441 /*
1442         ========================================================================
1443
1444         Routine Description:
1445                 Resume MSDU transmission
1446
1447         Arguments:
1448                 pAd     Pointer to our adapter
1449
1450         Return Value:
1451                 None
1452
1453         IRQL = DISPATCH_LEVEL
1454
1455         Note:
1456
1457         ========================================================================
1458 */
1459 VOID RTMPResumeMsduTransmission(
1460         IN      PRTMP_ADAPTER   pAd)
1461 {
1462 //    UCHAR                     IrqState;
1463
1464         DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1465
1466
1467         // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value
1468         // R66 should not be 0
1469         if (pAd->BbpTuning.R66CurrentValue == 0)
1470         {
1471                 pAd->BbpTuning.R66CurrentValue = 0x38;
1472                 DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
1473         }
1474
1475         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1476
1477         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1478 // sample, for IRQ LOCK to SEM LOCK
1479 //    IrqState = pAd->irq_disabled;
1480 //      if (IrqState)
1481 //              RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1482 //    else
1483         RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1484 }
1485
1486
1487 UINT deaggregate_AMSDU_announce(
1488         IN      PRTMP_ADAPTER   pAd,
1489         PNDIS_PACKET            pPacket,
1490         IN      PUCHAR                  pData,
1491         IN      ULONG                   DataSize)
1492 {
1493         USHORT                  PayloadSize;
1494         USHORT                  SubFrameSize;
1495         PHEADER_802_3   pAMSDUsubheader;
1496         UINT                    nMSDU;
1497     UCHAR                       Header802_3[14];
1498
1499         PUCHAR                  pPayload, pDA, pSA, pRemovedLLCSNAP;
1500         PNDIS_PACKET    pClonePacket;
1501
1502
1503
1504         nMSDU = 0;
1505
1506         while (DataSize > LENGTH_802_3)
1507         {
1508
1509                 nMSDU++;
1510
1511                 //hex_dump("subheader", pData, 64);
1512                 pAMSDUsubheader = (PHEADER_802_3)pData;
1513                 //pData += LENGTH_802_3;
1514                 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1515                 SubFrameSize = PayloadSize + LENGTH_802_3;
1516
1517
1518                 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
1519                 {
1520                         break;
1521                 }
1522
1523                 //DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n",  nMSDU, PayloadSize));
1524
1525                 pPayload = pData + LENGTH_802_3;
1526                 pDA = pData;
1527                 pSA = pData + MAC_ADDR_LEN;
1528
1529                 // convert to 802.3 header
1530         CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
1531
1532                 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
1533                 {
1534                         /* avoid local heap overflow, use dyanamic allocation */
1535                    MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1536                         if (Elem != NULL)
1537                         {
1538                    memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
1539                    Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
1540                                 //WpaEAPOLKeyAction(pAd, Elem);
1541                                 REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID, Elem->Msg, Elem->MsgLen, 0, 0, 0, 0);
1542                    kfree(Elem);
1543                 }
1544                 }
1545
1546                 {
1547                         if (pRemovedLLCSNAP)
1548                         {
1549                                 pPayload -= LENGTH_802_3;
1550                                 PayloadSize += LENGTH_802_3;
1551                                 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
1552                         }
1553                 }
1554
1555                 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1556                 if (pClonePacket)
1557                 {
1558                         ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
1559                 }
1560
1561
1562                 // A-MSDU has padding to multiple of 4 including subframe header.
1563                 // align SubFrameSize up to multiple of 4
1564                 SubFrameSize = (SubFrameSize+3)&(~0x3);
1565
1566
1567                 if (SubFrameSize > 1528 || SubFrameSize < 32)
1568                 {
1569                         break;
1570                 }
1571
1572                 if (DataSize > SubFrameSize)
1573                 {
1574                         pData += SubFrameSize;
1575                         DataSize -= SubFrameSize;
1576                 }
1577                 else
1578                 {
1579                         // end of A-MSDU
1580                         DataSize = 0;
1581                 }
1582         }
1583
1584         // finally release original rx packet
1585         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1586
1587         return nMSDU;
1588 }
1589
1590
1591 UINT BA_Reorder_AMSDU_Annnounce(
1592         IN      PRTMP_ADAPTER   pAd,
1593         IN      PNDIS_PACKET    pPacket)
1594 {
1595         PUCHAR                  pData;
1596         USHORT                  DataSize;
1597         UINT                    nMSDU = 0;
1598
1599         pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1600         DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1601
1602         nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1603
1604         return nMSDU;
1605 }
1606
1607
1608 /*
1609         ==========================================================================
1610         Description:
1611                 Look up the MAC address in the MAC table. Return NULL if not found.
1612         Return:
1613                 pEntry - pointer to the MAC entry; NULL is not found
1614         ==========================================================================
1615 */
1616 MAC_TABLE_ENTRY *MacTableLookup(
1617         IN PRTMP_ADAPTER pAd,
1618         PUCHAR pAddr)
1619 {
1620         ULONG HashIdx;
1621         MAC_TABLE_ENTRY *pEntry = NULL;
1622
1623         HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1624         pEntry = pAd->MacTab.Hash[HashIdx];
1625
1626         while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
1627         {
1628                 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1629                 {
1630                         break;
1631                 }
1632                 else
1633                         pEntry = pEntry->pNext;
1634         }
1635
1636         return pEntry;
1637 }
1638
1639 MAC_TABLE_ENTRY *MacTableInsertEntry(
1640         IN  PRTMP_ADAPTER   pAd,
1641         IN  PUCHAR                      pAddr,
1642         IN      UCHAR                   apidx,
1643         IN BOOLEAN      CleanAll)
1644 {
1645         UCHAR HashIdx;
1646         int i, FirstWcid;
1647         MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1648 //      USHORT  offset;
1649 //      ULONG   addr;
1650
1651         // if FULL, return
1652         if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1653                 return NULL;
1654
1655         FirstWcid = 1;
1656
1657         if (pAd->StaCfg.BssType == BSS_INFRA)
1658                 FirstWcid = 2;
1659
1660         // allocate one MAC entry
1661         NdisAcquireSpinLock(&pAd->MacTabLock);
1662         for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++)   // skip entry#0 so that "entry index == AID" for fast lookup
1663         {
1664                 // pick up the first available vacancy
1665                 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1666                         (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1667                         (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
1668                         (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1669                         )
1670                 {
1671                         pEntry = &pAd->MacTab.Content[i];
1672                         if (CleanAll == TRUE)
1673                         {
1674                                 pEntry->MaxSupportedRate = RATE_11;
1675                                 pEntry->CurrTxRate = RATE_11;
1676                                 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1677                                 pEntry->PairwiseKey.KeyLen = 0;
1678                                 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1679                         }
1680                         {
1681                                 {
1682                                         pEntry->ValidAsCLI = TRUE;
1683                                         pEntry->ValidAsWDS = FALSE;
1684                                         pEntry->ValidAsApCli = FALSE;
1685                                         pEntry->ValidAsMesh = FALSE;
1686                                         pEntry->ValidAsDls = FALSE;
1687                                 }
1688                         }
1689
1690                         pEntry->bIAmBadAtheros = FALSE;
1691                         pEntry->pAd = pAd;
1692                         pEntry->CMTimerRunning = FALSE;
1693                         pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1694                         pEntry->RSNIE_Len = 0;
1695                         NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
1696                         pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1697
1698                         if (pEntry->ValidAsMesh)
1699                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
1700                         else if (pEntry->ValidAsApCli)
1701                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
1702                         else if (pEntry->ValidAsWDS)
1703                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
1704                         else
1705                                 pEntry->apidx = apidx;
1706
1707                         {
1708                                 {
1709                                         pEntry->AuthMode = pAd->StaCfg.AuthMode;
1710                                         pEntry->WepStatus = pAd->StaCfg.WepStatus;
1711                                         pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1712 #ifdef RTMP_MAC_PCI
1713                                         AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)i);
1714 #endif // RTMP_MAC_PCI //
1715                                 }
1716                         }
1717
1718                         pEntry->GTKState = REKEY_NEGOTIATING;
1719                         pEntry->PairwiseKey.KeyLen = 0;
1720                         pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1721                         pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1722
1723                         pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1724                         COPY_MAC_ADDR(pEntry->Addr, pAddr);
1725                         pEntry->Sst = SST_NOT_AUTH;
1726                         pEntry->AuthState = AS_NOT_AUTH;
1727                         pEntry->Aid = (USHORT)i;  //0;
1728                         pEntry->CapabilityInfo = 0;
1729                         pEntry->PsMode = PWR_ACTIVE;
1730                         pEntry->PsQIdleCount = 0;
1731                         pEntry->NoDataIdleCount = 0;
1732                         pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT;
1733                         pEntry->ContinueTxFailCnt = 0;
1734                         InitializeQueueHeader(&pEntry->PsQueue);
1735
1736
1737                         pAd->MacTab.Size ++;
1738                         // Add this entry into ASIC RX WCID search table
1739                         RTMP_STA_ENTRY_ADD(pAd, pEntry);
1740
1741
1742
1743                         DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
1744                         break;
1745                 }
1746         }
1747
1748         // add this MAC entry into HASH table
1749         if (pEntry)
1750         {
1751                 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1752                 if (pAd->MacTab.Hash[HashIdx] == NULL)
1753                 {
1754                         pAd->MacTab.Hash[HashIdx] = pEntry;
1755                 }
1756                 else
1757                 {
1758                         pCurrEntry = pAd->MacTab.Hash[HashIdx];
1759                         while (pCurrEntry->pNext != NULL)
1760                                 pCurrEntry = pCurrEntry->pNext;
1761                         pCurrEntry->pNext = pEntry;
1762                 }
1763         }
1764
1765         NdisReleaseSpinLock(&pAd->MacTabLock);
1766         return pEntry;
1767 }
1768
1769 /*
1770         ==========================================================================
1771         Description:
1772                 Delete a specified client from MAC table
1773         ==========================================================================
1774  */
1775 BOOLEAN MacTableDeleteEntry(
1776         IN PRTMP_ADAPTER pAd,
1777         IN USHORT wcid,
1778         IN PUCHAR pAddr)
1779 {
1780         USHORT HashIdx;
1781         MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1782         BOOLEAN Cancelled;
1783         //USHORT        offset; // unused variable
1784         //UCHAR j;                      // unused variable
1785
1786         if (wcid >= MAX_LEN_OF_MAC_TABLE)
1787                 return FALSE;
1788
1789         NdisAcquireSpinLock(&pAd->MacTabLock);
1790
1791         HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1792         //pEntry = pAd->MacTab.Hash[HashIdx];
1793         pEntry = &pAd->MacTab.Content[wcid];
1794
1795         if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
1796                 ))
1797         {
1798                 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1799                 {
1800
1801                         // Delete this entry from ASIC on-chip WCID Table
1802                         RTMP_STA_ENTRY_MAC_RESET(pAd, wcid);
1803
1804                         // free resources of BA
1805                         BASessionTearDownALL(pAd, pEntry->Aid);
1806
1807                         pPrevEntry = NULL;
1808                         pProbeEntry = pAd->MacTab.Hash[HashIdx];
1809                         ASSERT(pProbeEntry);
1810
1811                         // update Hash list
1812                         do
1813                         {
1814                                 if (pProbeEntry == pEntry)
1815                                 {
1816                                         if (pPrevEntry == NULL)
1817                                         {
1818                                                 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
1819                                         }
1820                                         else
1821                                         {
1822                                                 pPrevEntry->pNext = pEntry->pNext;
1823                                         }
1824                                         break;
1825                                 }
1826
1827                                 pPrevEntry = pProbeEntry;
1828                                 pProbeEntry = pProbeEntry->pNext;
1829                         } while (pProbeEntry);
1830
1831                         // not found !!!
1832                         ASSERT(pProbeEntry != NULL);
1833
1834                         RTMP_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1835
1836
1837                 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
1838                 {
1839                         RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
1840                         pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1841                 }
1842
1843
1844                         NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1845                         pAd->MacTab.Size --;
1846                         DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
1847                 }
1848                 else
1849                 {
1850                         DBGPRINT(RT_DEBUG_OFF, ("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid));
1851                 }
1852         }
1853
1854         NdisReleaseSpinLock(&pAd->MacTabLock);
1855
1856         //Reset operating mode when no Sta.
1857         if (pAd->MacTab.Size == 0)
1858         {
1859                 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
1860                 //AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
1861                 RTMP_UPDATE_PROTECT(pAd);  // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet
1862         }
1863
1864         return TRUE;
1865 }
1866
1867
1868 /*
1869         ==========================================================================
1870         Description:
1871                 This routine reset the entire MAC table. All packets pending in
1872                 the power-saving queues are freed here.
1873         ==========================================================================
1874  */
1875 VOID MacTableReset(
1876         IN  PRTMP_ADAPTER  pAd)
1877 {
1878         int         i;
1879
1880         DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
1881         //NdisAcquireSpinLock(&pAd->MacTabLock);
1882
1883
1884         for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
1885         {
1886 #ifdef RTMP_MAC_PCI
1887                 RTMP_STA_ENTRY_MAC_RESET(pAd, i);
1888 #endif // RTMP_MAC_PCI //
1889                 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
1890            {
1891
1892
1893                         // free resources of BA
1894                         BASessionTearDownALL(pAd, i);
1895
1896                         pAd->MacTab.Content[i].ValidAsCLI = FALSE;
1897
1898 #ifdef RTMP_MAC_USB
1899                         NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
1900                         RTMP_STA_ENTRY_MAC_RESET(pAd, i);
1901 #endif // RTMP_MAC_USB //
1902
1903                         //AsicDelWcidTab(pAd, i);
1904                 }
1905         }
1906
1907         return;
1908 }
1909
1910 /*
1911         ==========================================================================
1912         Description:
1913
1914         IRQL = DISPATCH_LEVEL
1915
1916         ==========================================================================
1917 */
1918 VOID AssocParmFill(
1919         IN PRTMP_ADAPTER pAd,
1920         IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
1921         IN PUCHAR                     pAddr,
1922         IN USHORT                     CapabilityInfo,
1923         IN ULONG                      Timeout,
1924         IN USHORT                     ListenIntv)
1925 {
1926         COPY_MAC_ADDR(AssocReq->Addr, pAddr);
1927         // Add mask to support 802.11b mode only
1928         AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
1929         AssocReq->Timeout = Timeout;
1930         AssocReq->ListenIntv = ListenIntv;
1931 }
1932
1933
1934 /*
1935         ==========================================================================
1936         Description:
1937
1938         IRQL = DISPATCH_LEVEL
1939
1940         ==========================================================================
1941 */
1942 VOID DisassocParmFill(
1943         IN PRTMP_ADAPTER pAd,
1944         IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
1945         IN PUCHAR pAddr,
1946         IN USHORT Reason)
1947 {
1948         COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
1949         DisassocReq->Reason = Reason;
1950 }
1951
1952
1953 /*
1954         ========================================================================
1955
1956         Routine Description:
1957                 Check the out going frame, if this is an DHCP or ARP datagram
1958         will be duplicate another frame at low data rate transmit.
1959
1960         Arguments:
1961                 pAd             Pointer to our adapter
1962                 pPacket         Pointer to outgoing Ndis frame
1963
1964         Return Value:
1965                 TRUE            To be duplicate at Low data rate transmit. (1mb)
1966                 FALSE           Do nothing.
1967
1968         IRQL = DISPATCH_LEVEL
1969
1970         Note:
1971
1972                 MAC header + IP Header + UDP Header
1973                   14 Bytes        20 Bytes
1974
1975                 UDP Header
1976                 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
1977                                                 Source Port
1978                 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
1979                                         Destination Port
1980
1981                 port 0x43 means Bootstrap Protocol, server.
1982                 Port 0x44 means Bootstrap Protocol, client.
1983
1984         ========================================================================
1985 */
1986
1987 BOOLEAN RTMPCheckDHCPFrame(
1988         IN      PRTMP_ADAPTER   pAd,
1989         IN      PNDIS_PACKET    pPacket)
1990 {
1991         PACKET_INFO     PacketInfo;
1992         ULONG                   NumberOfBytesRead = 0;
1993         ULONG                   CurrentOffset = 0;
1994         PVOID                   pVirtualAddress = NULL;
1995         UINT                    NdisBufferLength;
1996         PUCHAR                  pSrc;
1997         USHORT                  Protocol;
1998         UCHAR                   ByteOffset36 = 0;
1999         UCHAR                   ByteOffset38 = 0;
2000         BOOLEAN                 ReadFirstParm = TRUE;
2001
2002         RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2003
2004         NumberOfBytesRead += NdisBufferLength;
2005         pSrc = (PUCHAR) pVirtualAddress;
2006         Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2007
2008         //
2009         // Check DHCP & BOOTP protocol
2010         //
2011         while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2012         {
2013                 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2014                 {
2015                         CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2016                         ByteOffset36 = *(pSrc + CurrentOffset);
2017                         ReadFirstParm = FALSE;
2018                 }
2019
2020                 if (NumberOfBytesRead >= 37)
2021                 {
2022                         CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2023                         ByteOffset38 = *(pSrc + CurrentOffset);
2024                         //End of Read
2025                         break;
2026                 }
2027                 return FALSE;
2028         }
2029
2030         // Check for DHCP & BOOTP protocol
2031         if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2032                 {
2033                 //
2034                 // 2054 (hex 0806) for ARP datagrams
2035                 // if this packet is not ARP datagrams, then do nothing
2036                 // ARP datagrams will also be duplicate at 1mb broadcast frames
2037                 //
2038                 if (Protocol != 0x0806 )
2039                         return FALSE;
2040                 }
2041
2042         return TRUE;
2043 }
2044
2045
2046 BOOLEAN RTMPCheckEtherType(
2047         IN      PRTMP_ADAPTER   pAd,
2048         IN      PNDIS_PACKET    pPacket)
2049 {
2050         USHORT  TypeLen;
2051         UCHAR   Byte0, Byte1;
2052         PUCHAR  pSrcBuf;
2053         UINT32  pktLen;
2054         UINT16  srcPort, dstPort;
2055         BOOLEAN status = TRUE;
2056
2057
2058         pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2059         pktLen = GET_OS_PKT_LEN(pPacket);
2060
2061         ASSERT(pSrcBuf);
2062
2063         RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2064
2065         // get Ethernet protocol field
2066         TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13];
2067
2068         pSrcBuf += LENGTH_802_3;        // Skip the Ethernet Header.
2069
2070         if (TypeLen <= 1500)
2071         {       // 802.3, 802.3 LLC
2072                 /*
2073                         DestMAC(6) + SrcMAC(6) + Lenght(2) +
2074                         DSAP(1) + SSAP(1) + Control(1) +
2075                         if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2076                                 => + SNAP (5, OriginationID(3) + etherType(2))
2077                 */
2078                 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2079                 {
2080                         Sniff2BytesFromNdisBuffer((PNDIS_BUFFER)pSrcBuf, 6, &Byte0, &Byte1);
2081                         RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2082                         TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2083                         pSrcBuf += 8; // Skip this LLC/SNAP header
2084                 }
2085                 else
2086                 {
2087                         //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2088                 }
2089         }
2090
2091         // If it's a VLAN packet, get the real Type/Length field.
2092         if (TypeLen == 0x8100)
2093         {
2094                 /* 0x8100 means VLAN packets */
2095
2096                 /* Dest. MAC Address (6-bytes) +
2097                    Source MAC Address (6-bytes) +
2098                    Length/Type = 802.1Q Tag Type (2-byte) +
2099                    Tag Control Information (2-bytes) +
2100                    Length / Type (2-bytes) +
2101                    data payload (0-n bytes) +
2102                    Pad (0-p bytes) +
2103                    Frame Check Sequence (4-bytes) */
2104
2105                 RTMP_SET_PACKET_VLAN(pPacket, 1);
2106                 Sniff2BytesFromNdisBuffer((PNDIS_BUFFER)pSrcBuf, 2, &Byte0, &Byte1);
2107                 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2108
2109                 pSrcBuf += 4; // Skip the VLAN Header.
2110         }
2111
2112         switch (TypeLen)
2113         {
2114                 case 0x0800:
2115                         {
2116                                 ASSERT((pktLen > 34));
2117                                 if (*(pSrcBuf + 9) == 0x11)
2118                                 {       // udp packet
2119                                         ASSERT((pktLen > 34));  // 14 for ethernet header, 20 for IP header
2120
2121                                         pSrcBuf += 20;  // Skip the IP header
2122                                         srcPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf)));
2123                                         dstPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf+2)));
2124
2125                                         if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2126                                         {       //It's a BOOTP/DHCP packet
2127                                                 RTMP_SET_PACKET_DHCP(pPacket, 1);
2128                                         }
2129                                 }
2130                         }
2131                         break;
2132                 case 0x0806:
2133                         {
2134                                 //ARP Packet.
2135                                 RTMP_SET_PACKET_DHCP(pPacket, 1);
2136                         }
2137                         break;
2138                 case 0x888e:
2139                         {
2140                                 // EAPOL Packet.
2141                                 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2142                         }
2143                         break;
2144                 default:
2145                         status = FALSE;
2146                         break;
2147         }
2148
2149         return status;
2150
2151 }
2152
2153
2154
2155 VOID Update_Rssi_Sample(
2156         IN PRTMP_ADAPTER        pAd,
2157         IN RSSI_SAMPLE          *pRssi,
2158         IN PRXWI_STRUC          pRxWI)
2159                 {
2160         CHAR    rssi0 = pRxWI->RSSI0;
2161         CHAR    rssi1 = pRxWI->RSSI1;
2162         CHAR    rssi2 = pRxWI->RSSI2;
2163
2164         if (rssi0 != 0)
2165         {
2166                 pRssi->LastRssi0        = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2167                 pRssi->AvgRssi0X8       = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2168                 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2169         }
2170
2171         if (rssi1 != 0)
2172         {
2173                 pRssi->LastRssi1        = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2174                 pRssi->AvgRssi1X8       = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2175                 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2176         }
2177
2178         if (rssi2 != 0)
2179         {
2180                 pRssi->LastRssi2        = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2181                 pRssi->AvgRssi2X8  = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2182                 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2183         }
2184 }
2185
2186
2187
2188 // Normal legacy Rx packet indication
2189 VOID Indicate_Legacy_Packet(
2190         IN      PRTMP_ADAPTER   pAd,
2191         IN      RX_BLK                  *pRxBlk,
2192         IN      UCHAR                   FromWhichBSSID)
2193 {
2194         PNDIS_PACKET    pRxPacket = pRxBlk->pRxPacket;
2195         UCHAR                   Header802_3[LENGTH_802_3];
2196
2197         // 1. get 802.3 Header
2198         // 2. remove LLC
2199         //              a. pointer pRxBlk->pData to payload
2200         //      b. modify pRxBlk->DataSize
2201         RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2202
2203         if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2204         {
2205
2206                 // release packet
2207                 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2208                 return;
2209         }
2210
2211
2212         STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2213
2214 #ifdef RTMP_MAC_USB
2215         if (pAd->CommonCfg.bDisableReordering == 0)
2216         {
2217                 PBA_REC_ENTRY           pBAEntry;
2218                 ULONG                           Now32;
2219                 UCHAR                           Wcid = pRxBlk->pRxWI->WirelessCliID;
2220                 UCHAR                           TID = pRxBlk->pRxWI->TID;
2221                 USHORT                          Idx;
2222
2223 #define REORDERING_PACKET_TIMEOUT               ((100 * OS_HZ)/1000)    // system ticks -- 100 ms
2224
2225                 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2226                 {
2227                         Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2228                         if (Idx != 0)
2229                         {
2230                                 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2231                                 // update last rx time
2232                                 NdisGetSystemUpTime(&Now32);
2233                                 if ((pBAEntry->list.qlen > 0) &&
2234                                          RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2235                                         )
2236                                 {
2237                                         DBGPRINT(RT_DEBUG_OFF, ("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n",
2238                                                                                                 pRxBlk->Flags, pRxBlk->pRxWI->TID, pRxBlk->RxD.AMPDU));
2239                                         hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2240                                         ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2241                                 }
2242                         }
2243                 }
2244         }
2245 #endif // RTMP_MAC_USB //
2246
2247         wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2248
2249         //
2250         // pass this 802.3 packet to upper layer or forward this packet to WM directly
2251         //
2252         ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2253 }
2254
2255
2256 // Normal, AMPDU or AMSDU
2257 VOID CmmRxnonRalinkFrameIndicate(
2258         IN      PRTMP_ADAPTER   pAd,
2259         IN      RX_BLK                  *pRxBlk,
2260         IN      UCHAR                   FromWhichBSSID)
2261 {
2262         if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2263         {
2264                 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2265         }
2266         else
2267         {
2268                 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2269                 {
2270                         // handle A-MSDU
2271                         Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2272                 }
2273                 else
2274                 {
2275                         Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2276                 }
2277         }
2278 }
2279
2280
2281 VOID CmmRxRalinkFrameIndicate(
2282         IN      PRTMP_ADAPTER   pAd,
2283         IN      MAC_TABLE_ENTRY *pEntry,
2284         IN      RX_BLK                  *pRxBlk,
2285         IN      UCHAR                   FromWhichBSSID)
2286 {
2287         UCHAR                   Header802_3[LENGTH_802_3];
2288         UINT16                  Msdu2Size;
2289         UINT16                  Payload1Size, Payload2Size;
2290         PUCHAR                  pData2;
2291         PNDIS_PACKET    pPacket2 = NULL;
2292
2293
2294
2295         Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2296
2297         if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2298         {
2299                 /* skip two byte MSDU2 len */
2300                 pRxBlk->pData += 2;
2301                 pRxBlk->DataSize -= 2;
2302         }
2303         else
2304         {
2305                 // release packet
2306                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2307                 return;
2308         }
2309
2310         // get 802.3 Header and  remove LLC
2311         RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2312
2313         ASSERT(pRxBlk->pRxPacket);
2314
2315         // Ralink Aggregation frame
2316         pAd->RalinkCounters.OneSecRxAggregationCount ++;
2317         Payload1Size = pRxBlk->DataSize - Msdu2Size;
2318         Payload2Size = Msdu2Size - LENGTH_802_3;
2319
2320         pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2321
2322         pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2323
2324         if (!pPacket2)
2325         {
2326                 // release packet
2327                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2328                 return;
2329         }
2330
2331         // update payload size of 1st packet
2332         pRxBlk->DataSize = Payload1Size;
2333         wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2334
2335         ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2336
2337         if (pPacket2)
2338         {
2339                 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2340         }
2341 }
2342
2343
2344 #define RESET_FRAGFRAME(_fragFrame) \
2345         {                                                               \
2346                 _fragFrame.RxSize = 0;          \
2347                 _fragFrame.Sequence = 0;        \
2348                 _fragFrame.LastFrag = 0;        \
2349                 _fragFrame.Flags = 0;           \
2350         }
2351
2352
2353 PNDIS_PACKET RTMPDeFragmentDataFrame(
2354         IN      PRTMP_ADAPTER   pAd,
2355         IN      RX_BLK                  *pRxBlk)
2356 {
2357         PHEADER_802_11  pHeader = pRxBlk->pHeader;
2358         PNDIS_PACKET    pRxPacket = pRxBlk->pRxPacket;
2359         UCHAR                   *pData = pRxBlk->pData;
2360         USHORT                  DataSize = pRxBlk->DataSize;
2361         PNDIS_PACKET    pRetPacket = NULL;
2362         UCHAR                   *pFragBuffer = NULL;
2363         BOOLEAN                 bReassDone = FALSE;
2364         UCHAR                   HeaderRoom = 0;
2365
2366
2367         ASSERT(pHeader);
2368
2369         HeaderRoom = pData - (UCHAR *)pHeader;
2370
2371         // Re-assemble the fragmented packets
2372         if (pHeader->Frag == 0)         // Frag. Number is 0 : First frag or only one pkt
2373         {
2374                 // the first pkt of fragment, record it.
2375                 if (pHeader->FC.MoreFrag)
2376                 {
2377                         ASSERT(pAd->FragFrame.pFragPacket);
2378                         pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2379                         pAd->FragFrame.RxSize   = DataSize + HeaderRoom;
2380                         NdisMoveMemory(pFragBuffer,      pHeader, pAd->FragFrame.RxSize);
2381                         pAd->FragFrame.Sequence = pHeader->Sequence;
2382                         pAd->FragFrame.LastFrag = pHeader->Frag;           // Should be 0
2383                         ASSERT(pAd->FragFrame.LastFrag == 0);
2384                         goto done;      // end of processing this frame
2385                 }
2386         }
2387         else    //Middle & End of fragment
2388         {
2389                 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2390                         (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2391                 {
2392                         // Fragment is not the same sequence or out of fragment number order
2393                         // Reset Fragment control blk
2394                         RESET_FRAGFRAME(pAd->FragFrame);
2395                         DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2396                         goto done; // give up this frame
2397                 }
2398                 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2399                 {
2400                         // Fragment frame is too large, it exeeds the maximum frame size.
2401                         // Reset Fragment control blk
2402                         RESET_FRAGFRAME(pAd->FragFrame);
2403                         DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2404                         goto done; // give up this frame
2405                 }
2406
2407         //
2408                 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2409                 // In this case, we will dropt it.
2410                 //
2411                 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2412                 {
2413                         DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2414                         goto done; // give up this frame
2415                 }
2416
2417                 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2418
2419                 // concatenate this fragment into the re-assembly buffer
2420                 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2421                 pAd->FragFrame.RxSize  += DataSize;
2422                 pAd->FragFrame.LastFrag = pHeader->Frag;           // Update fragment number
2423
2424                 // Last fragment
2425                 if (pHeader->FC.MoreFrag == FALSE)
2426                 {
2427                         bReassDone = TRUE;
2428                 }
2429         }
2430
2431 done:
2432         // always release rx fragmented packet
2433         RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2434
2435         // return defragmented packet if packet is reassembled completely
2436         // otherwise return NULL
2437         if (bReassDone)
2438         {
2439                 PNDIS_PACKET pNewFragPacket;
2440
2441                 // allocate a new packet buffer for fragment
2442                 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2443                 if (pNewFragPacket)
2444                 {
2445                         // update RxBlk
2446                         pRetPacket = pAd->FragFrame.pFragPacket;
2447                         pAd->FragFrame.pFragPacket = pNewFragPacket;
2448                         pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2449                         pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2450                         pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2451                         pRxBlk->pRxPacket = pRetPacket;
2452                 }
2453                 else
2454                 {
2455                         RESET_FRAGFRAME(pAd->FragFrame);
2456                 }
2457         }
2458
2459         return pRetPacket;
2460 }
2461
2462
2463 VOID Indicate_AMSDU_Packet(
2464         IN      PRTMP_ADAPTER   pAd,
2465         IN      RX_BLK                  *pRxBlk,
2466         IN      UCHAR                   FromWhichBSSID)
2467 {
2468         UINT                    nMSDU;
2469
2470         update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2471         RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2472         nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2473 }
2474
2475 VOID Indicate_EAPOL_Packet(
2476         IN      PRTMP_ADAPTER   pAd,
2477         IN      RX_BLK                  *pRxBlk,
2478         IN      UCHAR                   FromWhichBSSID)
2479 {
2480         MAC_TABLE_ENTRY *pEntry = NULL;
2481
2482         {
2483                 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2484                 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2485                 return;
2486         }
2487
2488         if (pEntry == NULL)
2489         {
2490                 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2491                 // release packet
2492                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2493                 return;
2494         }
2495 }
2496
2497 #define BCN_TBTT_OFFSET         64      //defer 64 us
2498 VOID ReSyncBeaconTime(
2499         IN  PRTMP_ADAPTER   pAd)
2500 {
2501
2502         UINT32  Offset;
2503
2504
2505         Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2506
2507         pAd->TbttTickCount++;
2508
2509         //
2510         // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2511         // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2512         //
2513         if (Offset == (BCN_TBTT_OFFSET-2))
2514         {
2515                 BCN_TIME_CFG_STRUC csr;
2516                 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2517                 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ;     // ASIC register in units of 1/16 TU = 64us
2518                 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2519         }
2520         else
2521         {
2522                 if (Offset == (BCN_TBTT_OFFSET-1))
2523                 {
2524                         BCN_TIME_CFG_STRUC csr;
2525
2526                         RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2527                         csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
2528                         RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2529                 }
2530         }
2531 }
2532