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