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