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