Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[sfrench/cifs-2.6.git] / drivers / staging / rt2860 / common / cmm_data.c
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26 */
27
28 #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 #ifdef RALINK_ATE
1775 #ifdef RALINK_28xx_QA
1776                 PHEADER_802_11  pHeader80211;
1777
1778                 if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE))
1779                 {
1780                         if (pAd->ate.QID == QueIdx)
1781                         {
1782                                 pAd->ate.TxDoneCount++;
1783                                 //pAd->ate.Repeat++;
1784                                 pAd->RalinkCounters.KickTxCount++;
1785
1786                                 /* always use QID_AC_BE and FIFO_EDCA */
1787                                 ASSERT(pAd->ate.QID == 0);
1788                                 pAd->ate.TxAc0++;
1789
1790                                 FREE++;
1791 #ifndef RT_BIG_ENDIAN
1792                                 pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1793                                 pOriTxD = pTxD;
1794                         NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
1795                                 pTxD = &TxD;
1796 #else
1797                         pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1798                         pOriTxD = pDestTxD ;
1799                         TxD = *pDestTxD;
1800                         pTxD = &TxD;
1801                         RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1802 #endif
1803                                 pTxD->DMADONE = 0;
1804
1805                                 pHeader80211 = pTxRing->Cell[pTxRing->TxSwFreeIdx].DmaBuf.AllocVa + sizeof(TXWI_STRUC);
1806 #ifdef RT_BIG_ENDIAN
1807                                 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_READ, FALSE);
1808 #endif
1809                                 pHeader80211->Sequence = ++pAd->ate.seq;
1810 #ifdef RT_BIG_ENDIAN
1811                                 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE);
1812 #endif
1813
1814                                 if  ((pAd->ate.bQATxStart == TRUE) && (pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.TxDoneCount < pAd->ate.TxCount))
1815                                 {
1816                                         pAd->RalinkCounters.TransmittedByteCount +=  (pTxD->SDLen1 + pTxD->SDLen0);
1817                                         pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
1818                                         INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
1819                                         /* get tx_tdx_idx again */
1820                                         RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF ,  &pTxRing->TxDmaIdx);
1821                                         goto kick_out;
1822                                 }
1823                                 else if ((pAd->ate.TxStatus == 1)/* or (pAd->ate.bQATxStart == TRUE) ??? */ && (pAd->ate.TxDoneCount == pAd->ate.TxCount))//<========================PETER
1824                                 {
1825                                         DBGPRINT(RT_DEBUG_TRACE,("all Tx is done\n"));
1826                                         // Tx status enters idle mode.
1827                                         pAd->ate.TxStatus = 0;
1828                                 }
1829                                 else if (!(pAd->ate.Mode & ATE_TXFRAME))
1830                                 {
1831                                         /* not complete sending yet, but someone press the Stop TX botton. */
1832                                         DBGPRINT(RT_DEBUG_ERROR,("not complete sending yet, but someone pressed the Stop TX bottom\n"));
1833                                         DBGPRINT(RT_DEBUG_ERROR,("pAd->ate.Mode = 0x%02x\n", pAd->ate.Mode));
1834                                 }
1835                                 else
1836                                 {
1837                                         DBGPRINT(RT_DEBUG_OFF,("pTxRing->TxSwFreeIdx = %d\n", pTxRing->TxSwFreeIdx));
1838                                 }
1839 #ifndef RT_BIG_ENDIAN
1840                         NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
1841 #else
1842                         RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1843                         *pDestTxD = TxD;
1844 #endif // RT_BIG_ENDIAN //
1845
1846                                 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
1847                                 continue;
1848                         }
1849                 }
1850 #endif // RALINK_28xx_QA //
1851 #endif // RALINK_ATE //
1852
1853                 // static rate also need NICUpdateFifoStaCounters() function.
1854                 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1855                         NICUpdateFifoStaCounters(pAd);
1856
1857                 /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */
1858                 FREE++;
1859 #ifndef RT_BIG_ENDIAN
1860                 pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1861                 pOriTxD = pTxD;
1862                 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
1863                 pTxD = &TxD;
1864 #else
1865         pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1866         pOriTxD = pDestTxD ;
1867         TxD = *pDestTxD;
1868         pTxD = &TxD;
1869         RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1870 #endif
1871
1872                 pTxD->DMADONE = 0;
1873
1874
1875 #ifdef RALINK_ATE
1876                 /* Execution of this block is not allowed when ATE is running. */
1877                 if (!(ATE_ON(pAd)))
1878 #endif // RALINK_ATE //
1879 /*====================================================================*/
1880                 {
1881                         pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket;
1882                         if (pPacket)
1883                         {
1884 #ifdef CONFIG_5VT_ENHANCE
1885                                 if (RTMP_GET_PACKET_5VT(pPacket))
1886                                         PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
1887                                 else
1888 #endif // CONFIG_5VT_ENHANCE //
1889                                         PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1890                                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1891                         }
1892                         //Always assign pNdisPacket as NULL after clear
1893                         pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL;
1894
1895                         pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket;
1896
1897                         ASSERT(pPacket == NULL);
1898                         if (pPacket)
1899                         {
1900 #ifdef CONFIG_5VT_ENHANCE
1901                                 if (RTMP_GET_PACKET_5VT(pPacket))
1902                                         PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
1903                                 else
1904 #endif // CONFIG_5VT_ENHANCE //
1905                                         PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1906                                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1907                         }
1908                         //Always assign pNextNdisPacket as NULL after clear
1909                         pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
1910                 }
1911 /*====================================================================*/
1912
1913                 pAd->RalinkCounters.TransmittedByteCount +=  (pTxD->SDLen1 + pTxD->SDLen0);
1914                 pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
1915                 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
1916                 /* get tx_tdx_idx again */
1917                 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF ,  &pTxRing->TxDmaIdx);
1918 #ifdef RT_BIG_ENDIAN
1919         RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1920         *pDestTxD = TxD;
1921 #else
1922         NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
1923 #endif
1924
1925 #ifdef RALINK_ATE
1926 #ifdef RALINK_28xx_QA
1927 kick_out:
1928 #endif // RALINK_28xx_QA //
1929
1930                 //
1931                 // ATE_TXCONT mode also need to send some normal frames, so let it in.
1932                 // ATE_STOP must be changed not to be 0xff
1933                 // to prevent it from running into this block.
1934                 //
1935                 if ((pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.QID == QueIdx))
1936                 {
1937                         // TxDoneCount++ has been done if QA is used.
1938                         if (pAd->ate.bQATxStart == FALSE)
1939                         {
1940                                 pAd->ate.TxDoneCount++;
1941                         }
1942                         if (((pAd->ate.TxCount - pAd->ate.TxDoneCount + 1) >= TX_RING_SIZE))
1943                         {
1944                                 /* Note : We increase TxCpuIdx here, not TxSwFreeIdx ! */
1945                                 INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
1946 #ifndef RT_BIG_ENDIAN//<==========================PETER
1947                                 pTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa);
1948                                 pOriTxD = pTxD;
1949                         NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
1950                                 pTxD = &TxD;
1951 #else
1952                         pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa);
1953                         pOriTxD = pDestTxD ;
1954                         TxD = *pDestTxD;
1955                         pTxD = &TxD;
1956                         RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1957 #endif
1958                                 pTxD->DMADONE = 0;
1959 #ifndef RT_BIG_ENDIAN//<==========================PETER
1960                         NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
1961 #else
1962                         RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1963                         *pDestTxD = TxD;
1964 #endif
1965                                 // kick Tx-Ring.
1966                                 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx * RINGREG_DIFF, pAd->TxRing[QueIdx].TxCpuIdx);
1967                                 pAd->RalinkCounters.KickTxCount++;
1968                         }
1969                 }
1970 #endif // RALINK_ATE //
1971         }
1972
1973
1974         return  bReschedule;
1975
1976 }
1977
1978
1979 /*
1980         ========================================================================
1981
1982         Routine Description:
1983                 Process TX Rings DMA Done interrupt, running in DPC level
1984
1985         Arguments:
1986                 Adapter         Pointer to our adapter
1987
1988         Return Value:
1989                 None
1990
1991         IRQL = DISPATCH_LEVEL
1992
1993         ========================================================================
1994 */
1995 BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(
1996         IN      PRTMP_ADAPTER   pAd,
1997         IN      INT_SOURCE_CSR_STRUC TxRingBitmap)
1998 {
1999     unsigned long       IrqFlags;
2000         BOOLEAN                 bReschedule = FALSE;
2001
2002         // Make sure Tx ring resource won't be used by other threads
2003
2004         RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
2005
2006         if (TxRingBitmap.field.Ac0DmaDone)
2007                 bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE);
2008
2009         if (TxRingBitmap.field.HccaDmaDone)
2010                 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_HCCA);
2011
2012         if (TxRingBitmap.field.Ac3DmaDone)
2013                 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO);
2014
2015         if (TxRingBitmap.field.Ac2DmaDone)
2016                 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI);
2017
2018         if (TxRingBitmap.field.Ac1DmaDone)
2019                 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK);
2020
2021         // Make sure to release Tx ring resource
2022         RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
2023
2024         // Dequeue outgoing frames from TxSwQueue[] and process it
2025         RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
2026
2027         return  bReschedule;
2028 }
2029
2030
2031 /*
2032         ========================================================================
2033
2034         Routine Description:
2035                 Process MGMT ring DMA done interrupt, running in DPC level
2036
2037         Arguments:
2038                 pAd     Pointer to our adapter
2039
2040         Return Value:
2041                 None
2042
2043         IRQL = DISPATCH_LEVEL
2044
2045         Note:
2046
2047         ========================================================================
2048 */
2049 VOID    RTMPHandleMgmtRingDmaDoneInterrupt(
2050         IN      PRTMP_ADAPTER   pAd)
2051 {
2052         PTXD_STRUC       pTxD;
2053 #ifdef RT_BIG_ENDIAN
2054     PTXD_STRUC      pDestTxD;
2055     TXD_STRUC       TxD;
2056 #endif
2057         PNDIS_PACKET pPacket;
2058         UCHAR   FREE = 0;
2059         PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing;
2060
2061         NdisAcquireSpinLock(&pAd->MgmtRingLock);
2062
2063         RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx);
2064         while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx)
2065         {
2066                 FREE++;
2067 #ifdef RT_BIG_ENDIAN
2068         pDestTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
2069         TxD = *pDestTxD;
2070         pTxD = &TxD;
2071                 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
2072 #else
2073                 pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
2074 #endif
2075                 pTxD->DMADONE = 0;
2076                 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket;
2077
2078
2079                 if (pPacket)
2080                 {
2081                         PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
2082                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
2083                 }
2084                 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL;
2085
2086                 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket;
2087                 if (pPacket)
2088                 {
2089                         PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
2090                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
2091                 }
2092                 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL;
2093                 INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE);
2094
2095 #ifdef RT_BIG_ENDIAN
2096         RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
2097         WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD);
2098 #endif
2099         }
2100         NdisReleaseSpinLock(&pAd->MgmtRingLock);
2101
2102 }
2103
2104
2105 /*
2106         ========================================================================
2107
2108         Routine Description:
2109         Arguments:
2110                 Adapter         Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon.
2111
2112         IRQL = DISPATCH_LEVEL
2113
2114         ========================================================================
2115 */
2116 VOID    RTMPHandleTBTTInterrupt(
2117         IN PRTMP_ADAPTER pAd)
2118 {
2119         {
2120                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2121                 {
2122                 }
2123         }
2124 }
2125
2126
2127 /*
2128         ========================================================================
2129
2130         Routine Description:
2131         Arguments:
2132                 Adapter         Pointer to our adapter. Rewrite beacon content before next send-out.
2133
2134         IRQL = DISPATCH_LEVEL
2135
2136         ========================================================================
2137 */
2138 VOID    RTMPHandlePreTBTTInterrupt(
2139         IN PRTMP_ADAPTER pAd)
2140 {
2141         {
2142                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2143                 {
2144                         DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt...\n"));
2145                 }
2146         }
2147
2148
2149 }
2150
2151 VOID    RTMPHandleRxCoherentInterrupt(
2152         IN      PRTMP_ADAPTER   pAd)
2153 {
2154         WPDMA_GLO_CFG_STRUC     GloCfg;
2155
2156         if (pAd == NULL)
2157         {
2158                 DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n"));
2159                 return;
2160         }
2161
2162         DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n"));
2163
2164         RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word);
2165
2166         GloCfg.field.EnTXWriteBackDDONE = 0;
2167         GloCfg.field.EnableRxDMA = 0;
2168         GloCfg.field.EnableTxDMA = 0;
2169         RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
2170
2171         RTMPRingCleanUp(pAd, QID_AC_BE);
2172         RTMPRingCleanUp(pAd, QID_AC_BK);
2173         RTMPRingCleanUp(pAd, QID_AC_VI);
2174         RTMPRingCleanUp(pAd, QID_AC_VO);
2175         RTMPRingCleanUp(pAd, QID_HCCA);
2176         RTMPRingCleanUp(pAd, QID_MGMT);
2177         RTMPRingCleanUp(pAd, QID_RX);
2178
2179         RTMPEnableRxTx(pAd);
2180
2181         DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n"));
2182 }
2183
2184
2185 VOID DBGPRINT_TX_RING(
2186         IN PRTMP_ADAPTER  pAd,
2187         IN UCHAR          QueIdx)
2188 {
2189         UINT32          Ac0Base;
2190         UINT32          Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx;
2191         int                     i;
2192         PULONG  ptemp;
2193
2194         DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n "  ));
2195         switch (QueIdx)
2196         {
2197                 case QID_AC_BE:
2198                         RTMP_IO_READ32(pAd, TX_BASE_PTR0, &Ac0Base);
2199                         RTMP_IO_READ32(pAd, TX_CTX_IDX0, &Ac0SwIdx);
2200                         RTMP_IO_READ32(pAd, TX_DTX_IDX0, &Ac0HwIdx);
2201                         DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BE DESCRIPTOR  \n "  ));
2202                         for (i=0;i<TX_RING_SIZE;i++)
2203                         {
2204                                 ptemp= (PULONG)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa;
2205                                 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d]  %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2206                         }
2207                         DBGPRINT_RAW(RT_DEBUG_TRACE, ("  \n "  ));
2208                         break;
2209                 case QID_AC_BK:
2210                         RTMP_IO_READ32(pAd, TX_BASE_PTR1, &Ac0Base);
2211                         RTMP_IO_READ32(pAd, TX_CTX_IDX1, &Ac0SwIdx);
2212                         RTMP_IO_READ32(pAd, TX_DTX_IDX1, &Ac0HwIdx);
2213                         DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BK DESCRIPTOR  \n "  ));
2214                         for (i=0;i<TX_RING_SIZE;i++)
2215                         {
2216                                 ptemp= (PULONG)pAd->TxRing[QID_AC_BK].Cell[i].AllocVa;
2217                                 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d]  %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2218                         }
2219                         DBGPRINT_RAW(RT_DEBUG_TRACE, ("  \n "  ));
2220                         break;
2221                 case QID_AC_VI:
2222                         RTMP_IO_READ32(pAd, TX_BASE_PTR2, &Ac0Base);
2223                         RTMP_IO_READ32(pAd, TX_CTX_IDX2, &Ac0SwIdx);
2224                         RTMP_IO_READ32(pAd, TX_DTX_IDX2, &Ac0HwIdx);
2225                         DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VI DESCRIPTOR \n "  ));
2226                         for (i=0;i<TX_RING_SIZE;i++)
2227                         {
2228                                 ptemp= (PULONG)pAd->TxRing[QID_AC_VI].Cell[i].AllocVa;
2229                                 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d]  %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2230                         }
2231                         DBGPRINT_RAW(RT_DEBUG_TRACE, ("  \n "  ));
2232                         break;
2233                 case QID_AC_VO:
2234                         RTMP_IO_READ32(pAd, TX_BASE_PTR3, &Ac0Base);
2235                         RTMP_IO_READ32(pAd, TX_CTX_IDX3, &Ac0SwIdx);
2236                         RTMP_IO_READ32(pAd, TX_DTX_IDX3, &Ac0HwIdx);
2237                         DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VO DESCRIPTOR \n "  ));
2238                         for (i=0;i<TX_RING_SIZE;i++)
2239                         {
2240                                 ptemp= (PULONG)pAd->TxRing[QID_AC_VO].Cell[i].AllocVa;
2241                                 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d]  %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2242                         }
2243                         DBGPRINT_RAW(RT_DEBUG_TRACE, ("  \n "  ));
2244                         break;
2245                 case QID_MGMT:
2246                         RTMP_IO_READ32(pAd, TX_BASE_PTR5, &Ac0Base);
2247                         RTMP_IO_READ32(pAd, TX_CTX_IDX5, &Ac0SwIdx);
2248                         RTMP_IO_READ32(pAd, TX_DTX_IDX5, &Ac0HwIdx);
2249                         DBGPRINT_RAW(RT_DEBUG_TRACE, (" All QID_MGMT  DESCRIPTOR \n "  ));
2250                         for (i=0;i<MGMT_RING_SIZE;i++)
2251                         {
2252                                 ptemp= (PULONG)pAd->MgmtRing.Cell[i].AllocVa;
2253                                 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d]  %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2254                         }
2255                         DBGPRINT_RAW(RT_DEBUG_TRACE, ("  \n "  ));
2256                         break;
2257
2258                 default:
2259                         DBGPRINT_ERR(("DBGPRINT_TX_RING(Ring %d) not supported\n", QueIdx));
2260                         break;
2261         }
2262         AC0freeIdx = pAd->TxRing[QueIdx].TxSwFreeIdx;
2263
2264         DBGPRINT(RT_DEBUG_TRACE,("TxRing%d, TX_DTX_IDX=%d, TX_CTX_IDX=%d\n", QueIdx, Ac0HwIdx, Ac0SwIdx));
2265         DBGPRINT_RAW(RT_DEBUG_TRACE,("  TxSwFreeIdx[%d]", AC0freeIdx));
2266         DBGPRINT_RAW(RT_DEBUG_TRACE,("  pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
2267
2268
2269 }
2270
2271
2272 VOID DBGPRINT_RX_RING(
2273         IN PRTMP_ADAPTER  pAd)
2274 {
2275         UINT32          Ac0Base;
2276         UINT32          Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx;
2277         int                     i;
2278         UINT32  *ptemp;
2279
2280         DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n "  ));
2281         RTMP_IO_READ32(pAd, RX_BASE_PTR, &Ac0Base);
2282         RTMP_IO_READ32(pAd, RX_CRX_IDX, &Ac0SwIdx);
2283         RTMP_IO_READ32(pAd, RX_DRX_IDX, &Ac0HwIdx);
2284         AC0freeIdx = pAd->RxRing.RxSwReadIdx;
2285
2286         DBGPRINT_RAW(RT_DEBUG_TRACE, ("All RX DSP  \n "  ));
2287         for (i=0;i<RX_RING_SIZE;i++)
2288         {
2289                 ptemp = (UINT32 *)pAd->RxRing.Cell[i].AllocVa;
2290                 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d]  %08x: %08x: %08x: %08x\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2291         }
2292         DBGPRINT(RT_DEBUG_TRACE,("RxRing, RX_DRX_IDX=%d, RX_CRX_IDX=%d \n", Ac0HwIdx, Ac0SwIdx));
2293         DBGPRINT_RAW(RT_DEBUG_TRACE,("  RxSwReadIdx [%d]=", AC0freeIdx));
2294         DBGPRINT_RAW(RT_DEBUG_TRACE,("  pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
2295 }
2296
2297 /*
2298         ========================================================================
2299
2300         Routine Description:
2301                 Suspend MSDU transmission
2302
2303         Arguments:
2304                 pAd     Pointer to our adapter
2305
2306         Return Value:
2307                 None
2308
2309         Note:
2310
2311         ========================================================================
2312 */
2313 VOID    RTMPSuspendMsduTransmission(
2314         IN      PRTMP_ADAPTER   pAd)
2315 {
2316         DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
2317
2318
2319         //
2320         // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
2321         // use Lowbound as R66 value on ScanNextChannel(...)
2322         //
2323         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
2324
2325         // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
2326         RTMPSetAGCInitValue(pAd, BW_20);
2327
2328         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
2329 }
2330
2331
2332 /*
2333         ========================================================================
2334
2335         Routine Description:
2336                 Resume MSDU transmission
2337
2338         Arguments:
2339                 pAd     Pointer to our adapter
2340
2341         Return Value:
2342                 None
2343
2344         IRQL = DISPATCH_LEVEL
2345
2346         Note:
2347
2348         ========================================================================
2349 */
2350 VOID RTMPResumeMsduTransmission(
2351         IN      PRTMP_ADAPTER   pAd)
2352 {
2353         DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
2354
2355
2356         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
2357
2358         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
2359         RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
2360 }
2361
2362
2363 UINT deaggregate_AMSDU_announce(
2364         IN      PRTMP_ADAPTER   pAd,
2365         PNDIS_PACKET            pPacket,
2366         IN      PUCHAR                  pData,
2367         IN      ULONG                   DataSize)
2368 {
2369         USHORT                  PayloadSize;
2370         USHORT                  SubFrameSize;
2371         PHEADER_802_3   pAMSDUsubheader;
2372         UINT                    nMSDU;
2373     UCHAR                       Header802_3[14];
2374
2375         PUCHAR                  pPayload, pDA, pSA, pRemovedLLCSNAP;
2376         PNDIS_PACKET    pClonePacket;
2377
2378
2379
2380         nMSDU = 0;
2381
2382         while (DataSize > LENGTH_802_3)
2383         {
2384
2385                 nMSDU++;
2386
2387                 pAMSDUsubheader = (PHEADER_802_3)pData;
2388                 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
2389                 SubFrameSize = PayloadSize + LENGTH_802_3;
2390
2391
2392                 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
2393                 {
2394                         break;
2395                 }
2396
2397                 pPayload = pData + LENGTH_802_3;
2398                 pDA = pData;
2399                 pSA = pData + MAC_ADDR_LEN;
2400
2401                 // convert to 802.3 header
2402         CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
2403
2404 #ifdef CONFIG_STA_SUPPORT
2405                 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
2406                 {
2407                     // avoid local heap overflow, use dyanamic allocation
2408                    MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
2409                    memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
2410                    Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
2411                    WpaEAPOLKeyAction(pAd, Elem);
2412                    kfree(Elem);
2413                 }
2414 #endif // CONFIG_STA_SUPPORT //
2415
2416 #ifdef CONFIG_STA_SUPPORT
2417                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2418                 {
2419                         if (pRemovedLLCSNAP)
2420                         {
2421                                 pPayload -= LENGTH_802_3;
2422                                 PayloadSize += LENGTH_802_3;
2423                                 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
2424                         }
2425                 }
2426 #endif // CONFIG_STA_SUPPORT //
2427
2428                 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
2429                 if (pClonePacket)
2430                 {
2431 #ifdef CONFIG_STA_SUPPORT
2432                         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2433                                 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
2434 #endif // CONFIG_STA_SUPPORT //
2435                 }
2436
2437
2438                 // A-MSDU has padding to multiple of 4 including subframe header.
2439                 // align SubFrameSize up to multiple of 4
2440                 SubFrameSize = (SubFrameSize+3)&(~0x3);
2441
2442
2443                 if (SubFrameSize > 1528 || SubFrameSize < 32)
2444                 {
2445                         break;
2446                 }
2447
2448                 if (DataSize > SubFrameSize)
2449                 {
2450                         pData += SubFrameSize;
2451                         DataSize -= SubFrameSize;
2452                 }
2453                 else
2454                 {
2455                         // end of A-MSDU
2456                         DataSize = 0;
2457                 }
2458         }
2459
2460         // finally release original rx packet
2461         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
2462
2463         return nMSDU;
2464 }
2465
2466
2467 UINT BA_Reorder_AMSDU_Annnounce(
2468         IN      PRTMP_ADAPTER   pAd,
2469         IN      PNDIS_PACKET    pPacket)
2470 {
2471         PUCHAR                  pData;
2472         USHORT                  DataSize;
2473         UINT                    nMSDU = 0;
2474
2475         pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
2476         DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
2477
2478         nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
2479
2480         return nMSDU;
2481 }
2482
2483
2484 /*
2485         ==========================================================================
2486         Description:
2487                 Look up the MAC address in the MAC table. Return NULL if not found.
2488         Return:
2489                 pEntry - pointer to the MAC entry; NULL is not found
2490         ==========================================================================
2491 */
2492 MAC_TABLE_ENTRY *MacTableLookup(
2493         IN PRTMP_ADAPTER pAd,
2494         PUCHAR pAddr)
2495 {
2496         ULONG HashIdx;
2497         MAC_TABLE_ENTRY *pEntry = NULL;
2498
2499         HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2500         pEntry = pAd->MacTab.Hash[HashIdx];
2501
2502         while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
2503         {
2504                 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2505                 {
2506                         break;
2507                 }
2508                 else
2509                         pEntry = pEntry->pNext;
2510         }
2511
2512         return pEntry;
2513 }
2514
2515 MAC_TABLE_ENTRY *MacTableInsertEntry(
2516         IN  PRTMP_ADAPTER   pAd,
2517         IN  PUCHAR                      pAddr,
2518         IN      UCHAR                   apidx,
2519         IN BOOLEAN      CleanAll)
2520 {
2521         UCHAR HashIdx;
2522         int i, FirstWcid;
2523         MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
2524
2525         // if FULL, return
2526         if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
2527                 return NULL;
2528
2529         FirstWcid = 1;
2530 #ifdef CONFIG_STA_SUPPORT
2531         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2532         if (pAd->StaCfg.BssType == BSS_INFRA)
2533                 FirstWcid = 2;
2534 #endif // CONFIG_STA_SUPPORT //
2535
2536         // allocate one MAC entry
2537         NdisAcquireSpinLock(&pAd->MacTabLock);
2538         for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++)   // skip entry#0 so that "entry index == AID" for fast lookup
2539         {
2540                 // pick up the first available vacancy
2541                 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
2542                         (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
2543                         (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
2544                         (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
2545 #ifdef CONFIG_STA_SUPPORT
2546 #ifdef QOS_DLS_SUPPORT
2547                         && (pAd->MacTab.Content[i].ValidAsDls == FALSE)
2548 #endif // QOS_DLS_SUPPORT //
2549 #endif // CONFIG_STA_SUPPORT //
2550                         )
2551                 {
2552                         pEntry = &pAd->MacTab.Content[i];
2553                         if (CleanAll == TRUE)
2554                         {
2555                                 pEntry->MaxSupportedRate = RATE_11;
2556                                 pEntry->CurrTxRate = RATE_11;
2557                                 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2558                                 pEntry->PairwiseKey.KeyLen = 0;
2559                                 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
2560                         }
2561 #ifdef CONFIG_STA_SUPPORT
2562 #ifdef QOS_DLS_SUPPORT
2563                         if (apidx >= MIN_NET_DEVICE_FOR_DLS)
2564                         {
2565                                 pEntry->ValidAsCLI = FALSE;
2566                                 pEntry->ValidAsWDS = FALSE;
2567                                 pEntry->ValidAsApCli = FALSE;
2568                                 pEntry->ValidAsMesh = FALSE;
2569                                 pEntry->ValidAsDls = TRUE;
2570                                 pEntry->isCached = FALSE;
2571                         }
2572                         else
2573 #endif // QOS_DLS_SUPPORT //
2574 #endif // CONFIG_STA_SUPPORT //
2575                         {
2576
2577 #ifdef CONFIG_STA_SUPPORT
2578                                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2579                                 {
2580                                         pEntry->ValidAsCLI = TRUE;
2581                                         pEntry->ValidAsWDS = FALSE;
2582                                         pEntry->ValidAsApCli = FALSE;
2583                                         pEntry->ValidAsMesh = FALSE;
2584                                         pEntry->ValidAsDls = FALSE;
2585                                 }
2586 #endif // CONFIG_STA_SUPPORT //
2587                         }
2588
2589                         pEntry->bIAmBadAtheros = FALSE;
2590                         pEntry->pAd = pAd;
2591                         pEntry->CMTimerRunning = FALSE;
2592                         pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2593                         pEntry->RSNIE_Len = 0;
2594                         NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
2595                         pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
2596
2597                         if (pEntry->ValidAsMesh)
2598                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
2599                         else if (pEntry->ValidAsApCli)
2600                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
2601                         else if (pEntry->ValidAsWDS)
2602                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
2603 #ifdef CONFIG_STA_SUPPORT
2604 #ifdef QOS_DLS_SUPPORT
2605                         else if (pEntry->ValidAsDls)
2606                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_DLS);
2607 #endif // QOS_DLS_SUPPORT //
2608 #endif // CONFIG_STA_SUPPORT //
2609                         else
2610                                 pEntry->apidx = apidx;
2611
2612                         {
2613
2614 #ifdef CONFIG_STA_SUPPORT
2615                                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2616                                 {
2617                                         pEntry->AuthMode = pAd->StaCfg.AuthMode;
2618                                         pEntry->WepStatus = pAd->StaCfg.WepStatus;
2619                                         pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
2620                                         AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)i);
2621                                 }
2622 #endif // CONFIG_STA_SUPPORT //
2623                         }
2624
2625                         pEntry->GTKState = REKEY_NEGOTIATING;
2626                         pEntry->PairwiseKey.KeyLen = 0;
2627                         pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
2628 #ifdef CONFIG_STA_SUPPORT
2629                         if ((pAd->OpMode == OPMODE_STA) &&
2630                                 (pAd->StaCfg.BssType == BSS_ADHOC))
2631                                 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
2632                         else
2633 #ifdef QOS_DLS_SUPPORT
2634                         if (pEntry->ValidAsDls == TRUE)
2635                                 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
2636                         else
2637 #endif //QOS_DLS_SUPPORT
2638 #endif // CONFIG_STA_SUPPORT //
2639                         pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
2640                         pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
2641                         COPY_MAC_ADDR(pEntry->Addr, pAddr);
2642                         pEntry->Sst = SST_NOT_AUTH;
2643                         pEntry->AuthState = AS_NOT_AUTH;
2644                         pEntry->Aid = (USHORT)i;  //0;
2645                         pEntry->CapabilityInfo = 0;
2646                         pEntry->PsMode = PWR_ACTIVE;
2647                         pEntry->PsQIdleCount = 0;
2648                         pEntry->NoDataIdleCount = 0;
2649                         pEntry->ContinueTxFailCnt = 0;
2650                         InitializeQueueHeader(&pEntry->PsQueue);
2651
2652
2653                         pAd->MacTab.Size ++;
2654                         // Add this entry into ASIC RX WCID search table
2655                         RT28XX_STA_ENTRY_ADD(pAd, pEntry);
2656
2657
2658
2659                         DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
2660                         break;
2661                 }
2662         }
2663
2664         // add this MAC entry into HASH table
2665         if (pEntry)
2666         {
2667                 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2668                 if (pAd->MacTab.Hash[HashIdx] == NULL)
2669                 {
2670                         pAd->MacTab.Hash[HashIdx] = pEntry;
2671                 }
2672                 else
2673                 {
2674                         pCurrEntry = pAd->MacTab.Hash[HashIdx];
2675                         while (pCurrEntry->pNext != NULL)
2676                                 pCurrEntry = pCurrEntry->pNext;
2677                         pCurrEntry->pNext = pEntry;
2678                 }
2679         }
2680
2681         NdisReleaseSpinLock(&pAd->MacTabLock);
2682         return pEntry;
2683 }
2684
2685 /*
2686         ==========================================================================
2687         Description:
2688                 Delete a specified client from MAC table
2689         ==========================================================================
2690  */
2691 BOOLEAN MacTableDeleteEntry(
2692         IN PRTMP_ADAPTER pAd,
2693         IN USHORT wcid,
2694         IN PUCHAR pAddr)
2695 {
2696         USHORT HashIdx;
2697         MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
2698         BOOLEAN Cancelled;
2699
2700         if (wcid >= MAX_LEN_OF_MAC_TABLE)
2701                 return FALSE;
2702
2703         NdisAcquireSpinLock(&pAd->MacTabLock);
2704
2705         HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2706         pEntry = &pAd->MacTab.Content[wcid];
2707
2708         if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
2709 #ifdef CONFIG_STA_SUPPORT
2710 #ifdef QOS_DLS_SUPPORT
2711                 || pEntry->ValidAsDls
2712 #endif // QOS_DLS_SUPPORT //
2713 #endif // CONFIG_STA_SUPPORT //
2714                 ))
2715         {
2716                 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2717                 {
2718
2719                         // Delete this entry from ASIC on-chip WCID Table
2720                         RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
2721
2722 #ifdef DOT11_N_SUPPORT
2723                         // free resources of BA
2724                         BASessionTearDownALL(pAd, pEntry->Aid);
2725 #endif // DOT11_N_SUPPORT //
2726
2727
2728                         pPrevEntry = NULL;
2729                         pProbeEntry = pAd->MacTab.Hash[HashIdx];
2730                         ASSERT(pProbeEntry);
2731
2732                         // update Hash list
2733                         do
2734                         {
2735                                 if (pProbeEntry == pEntry)
2736                                 {
2737                                         if (pPrevEntry == NULL)
2738                                         {
2739                                                 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
2740                                         }
2741                                         else
2742                                         {
2743                                                 pPrevEntry->pNext = pEntry->pNext;
2744                                         }
2745                                         break;
2746                                 }
2747
2748                                 pPrevEntry = pProbeEntry;
2749                                 pProbeEntry = pProbeEntry->pNext;
2750                         } while (pProbeEntry);
2751
2752                         // not found !!!
2753                         ASSERT(pProbeEntry != NULL);
2754
2755                         RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
2756
2757
2758                 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
2759                 {
2760                         RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
2761                         pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2762                 }
2763
2764
2765                         NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2766                         pAd->MacTab.Size --;
2767                         DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
2768                 }
2769                 else
2770                 {
2771                         printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
2772                 }
2773         }
2774
2775         NdisReleaseSpinLock(&pAd->MacTabLock);
2776
2777         //Reset operating mode when no Sta.
2778         if (pAd->MacTab.Size == 0)
2779         {
2780 #ifdef DOT11_N_SUPPORT
2781                 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
2782 #endif // DOT11_N_SUPPORT //
2783                 AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
2784         }
2785
2786         return TRUE;
2787 }
2788
2789
2790 /*
2791         ==========================================================================
2792         Description:
2793                 This routine reset the entire MAC table. All packets pending in
2794                 the power-saving queues are freed here.
2795         ==========================================================================
2796  */
2797 VOID MacTableReset(
2798         IN  PRTMP_ADAPTER  pAd)
2799 {
2800         int         i;
2801
2802         DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
2803         //NdisAcquireSpinLock(&pAd->MacTabLock);
2804
2805         for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
2806         {
2807                 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2808                 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
2809            {
2810
2811 #ifdef DOT11_N_SUPPORT
2812                         // free resources of BA
2813                         BASessionTearDownALL(pAd, i);
2814 #endif // DOT11_N_SUPPORT //
2815
2816                         pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2817
2818
2819
2820
2821                         //AsicDelWcidTab(pAd, i);
2822                 }
2823         }
2824
2825         return;
2826 }
2827
2828 /*
2829         ==========================================================================
2830         Description:
2831
2832         IRQL = DISPATCH_LEVEL
2833
2834         ==========================================================================
2835 */
2836 VOID AssocParmFill(
2837         IN PRTMP_ADAPTER pAd,
2838         IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2839         IN PUCHAR                     pAddr,
2840         IN USHORT                     CapabilityInfo,
2841         IN ULONG                      Timeout,
2842         IN USHORT                     ListenIntv)
2843 {
2844         COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2845         // Add mask to support 802.11b mode only
2846         AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2847         AssocReq->Timeout = Timeout;
2848         AssocReq->ListenIntv = ListenIntv;
2849 }
2850
2851
2852 /*
2853         ==========================================================================
2854         Description:
2855
2856         IRQL = DISPATCH_LEVEL
2857
2858         ==========================================================================
2859 */
2860 VOID DisassocParmFill(
2861         IN PRTMP_ADAPTER pAd,
2862         IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2863         IN PUCHAR pAddr,
2864         IN USHORT Reason)
2865 {
2866         COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2867         DisassocReq->Reason = Reason;
2868 }
2869
2870
2871 /*
2872         ========================================================================
2873
2874         Routine Description:
2875                 Check the out going frame, if this is an DHCP or ARP datagram
2876         will be duplicate another frame at low data rate transmit.
2877
2878         Arguments:
2879                 pAd             Pointer to our adapter
2880                 pPacket         Pointer to outgoing Ndis frame
2881
2882         Return Value:
2883                 TRUE            To be duplicate at Low data rate transmit. (1mb)
2884                 FALSE           Do nothing.
2885
2886         IRQL = DISPATCH_LEVEL
2887
2888         Note:
2889
2890                 MAC header + IP Header + UDP Header
2891                   14 Bytes        20 Bytes
2892
2893                 UDP Header
2894                 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2895                                                 Source Port
2896                 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2897                                         Destination Port
2898
2899                 port 0x43 means Bootstrap Protocol, server.
2900                 Port 0x44 means Bootstrap Protocol, client.
2901
2902         ========================================================================
2903 */
2904
2905 BOOLEAN RTMPCheckDHCPFrame(
2906         IN      PRTMP_ADAPTER   pAd,
2907         IN      PNDIS_PACKET    pPacket)
2908 {
2909         PACKET_INFO     PacketInfo;
2910         ULONG                   NumberOfBytesRead = 0;
2911         ULONG                   CurrentOffset = 0;
2912         PVOID                   pVirtualAddress = NULL;
2913         UINT                    NdisBufferLength;
2914         PUCHAR                  pSrc;
2915         USHORT                  Protocol;
2916         UCHAR                   ByteOffset36 = 0;
2917         UCHAR                   ByteOffset38 = 0;
2918         BOOLEAN                 ReadFirstParm = TRUE;
2919
2920         RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2921
2922         NumberOfBytesRead += NdisBufferLength;
2923         pSrc = (PUCHAR) pVirtualAddress;
2924         Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2925
2926         //
2927         // Check DHCP & BOOTP protocol
2928         //
2929         while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2930         {
2931                 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2932                 {
2933                         CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2934                         ByteOffset36 = *(pSrc + CurrentOffset);
2935                         ReadFirstParm = FALSE;
2936                 }
2937
2938                 if (NumberOfBytesRead >= 37)
2939                 {
2940                         CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2941                         ByteOffset38 = *(pSrc + CurrentOffset);
2942                         //End of Read
2943                         break;
2944                 }
2945                 return FALSE;
2946         }
2947
2948         // Check for DHCP & BOOTP protocol
2949         if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2950                 {
2951                 //
2952                 // 2054 (hex 0806) for ARP datagrams
2953                 // if this packet is not ARP datagrams, then do nothing
2954                 // ARP datagrams will also be duplicate at 1mb broadcast frames
2955                 //
2956                 if (Protocol != 0x0806 )
2957                         return FALSE;
2958                 }
2959
2960         return TRUE;
2961 }
2962
2963
2964 BOOLEAN RTMPCheckEtherType(
2965         IN      PRTMP_ADAPTER   pAd,
2966         IN      PNDIS_PACKET    pPacket)
2967 {
2968         USHORT  TypeLen;
2969         UCHAR   Byte0, Byte1;
2970         PUCHAR  pSrcBuf;
2971         UINT32  pktLen;
2972         UINT16  srcPort, dstPort;
2973         BOOLEAN status = TRUE;
2974
2975
2976         pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2977         pktLen = GET_OS_PKT_LEN(pPacket);
2978
2979         ASSERT(pSrcBuf);
2980
2981         RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2982
2983         // get Ethernet protocol field
2984         TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2985
2986         pSrcBuf += LENGTH_802_3;        // Skip the Ethernet Header.
2987
2988         if (TypeLen <= 1500)
2989         {       // 802.3, 802.3 LLC
2990                 /*
2991                         DestMAC(6) + SrcMAC(6) + Lenght(2) +
2992                         DSAP(1) + SSAP(1) + Control(1) +
2993                         if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2994                                 => + SNAP (5, OriginationID(3) + etherType(2))
2995                 */
2996                 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2997                 {
2998                         Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2999                         RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
3000                         TypeLen = (USHORT)((Byte0 << 8) + Byte1);
3001                         pSrcBuf += 8; // Skip this LLC/SNAP header
3002                 }
3003                 else
3004                 {
3005                         //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
3006                 }
3007         }
3008
3009         // If it's a VLAN packet, get the real Type/Length field.
3010         if (TypeLen == 0x8100)
3011         {
3012                 /* 0x8100 means VLAN packets */
3013
3014                 /* Dest. MAC Address (6-bytes) +
3015                    Source MAC Address (6-bytes) +
3016                    Length/Type = 802.1Q Tag Type (2-byte) +
3017                    Tag Control Information (2-bytes) +
3018                    Length / Type (2-bytes) +
3019                    data payload (0-n bytes) +
3020                    Pad (0-p bytes) +
3021                    Frame Check Sequence (4-bytes) */
3022
3023                 RTMP_SET_PACKET_VLAN(pPacket, 1);
3024                 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
3025                 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
3026
3027                 pSrcBuf += 4; // Skip the VLAN Header.
3028         }
3029
3030         switch (TypeLen)
3031         {
3032                 case 0x0800:
3033                         {
3034                                 ASSERT((pktLen > 34));
3035                                 if (*(pSrcBuf + 9) == 0x11)
3036                                 {       // udp packet
3037                                         ASSERT((pktLen > 34));  // 14 for ethernet header, 20 for IP header
3038
3039                                         pSrcBuf += 20;  // Skip the IP header
3040                                         srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
3041                                         dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
3042
3043                                         if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
3044                                         {       //It's a BOOTP/DHCP packet
3045                                                 RTMP_SET_PACKET_DHCP(pPacket, 1);
3046                                         }
3047                                 }
3048                         }
3049                         break;
3050                 case 0x0806:
3051                         {
3052                                 //ARP Packet.
3053                                 RTMP_SET_PACKET_DHCP(pPacket, 1);
3054                         }
3055                         break;
3056                 case 0x888e:
3057                         {
3058                                 // EAPOL Packet.
3059                                 RTMP_SET_PACKET_EAPOL(pPacket, 1);
3060                         }
3061                         break;
3062                 default:
3063                         status = FALSE;
3064                         break;
3065         }
3066
3067         return status;
3068
3069 }
3070
3071
3072
3073 VOID Update_Rssi_Sample(
3074         IN PRTMP_ADAPTER        pAd,
3075         IN RSSI_SAMPLE          *pRssi,
3076         IN PRXWI_STRUC          pRxWI)
3077                 {
3078         CHAR    rssi0 = pRxWI->RSSI0;
3079         CHAR    rssi1 = pRxWI->RSSI1;
3080         CHAR    rssi2 = pRxWI->RSSI2;
3081
3082         if (rssi0 != 0)
3083         {
3084                 pRssi->LastRssi0        = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
3085                 pRssi->AvgRssi0X8       = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
3086                 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
3087         }
3088
3089         if (rssi1 != 0)
3090         {
3091                 pRssi->LastRssi1        = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
3092                 pRssi->AvgRssi1X8       = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
3093                 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
3094         }
3095
3096         if (rssi2 != 0)
3097         {
3098                 pRssi->LastRssi2        = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
3099                 pRssi->AvgRssi2X8  = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
3100                 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
3101         }
3102 }
3103
3104
3105
3106 // Normal legacy Rx packet indication
3107 VOID Indicate_Legacy_Packet(
3108         IN      PRTMP_ADAPTER   pAd,
3109         IN      RX_BLK                  *pRxBlk,
3110         IN      UCHAR                   FromWhichBSSID)
3111 {
3112         PNDIS_PACKET    pRxPacket = pRxBlk->pRxPacket;
3113         UCHAR                   Header802_3[LENGTH_802_3];
3114
3115         // 1. get 802.3 Header
3116         // 2. remove LLC
3117         //              a. pointer pRxBlk->pData to payload
3118         //      b. modify pRxBlk->DataSize
3119 #ifdef CONFIG_STA_SUPPORT
3120         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3121                 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
3122 #endif // CONFIG_STA_SUPPORT //
3123
3124         if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
3125         {
3126
3127                 // release packet
3128                 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
3129                 return;
3130         }
3131
3132
3133         STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
3134
3135
3136         wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
3137
3138         //
3139         // pass this 802.3 packet to upper layer or forward this packet to WM directly
3140         //
3141 #ifdef CONFIG_STA_SUPPORT
3142         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3143                 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
3144 #endif // CONFIG_STA_SUPPORT //
3145
3146 }
3147
3148
3149 // Normal, AMPDU or AMSDU
3150 VOID CmmRxnonRalinkFrameIndicate(
3151         IN      PRTMP_ADAPTER   pAd,
3152         IN      RX_BLK                  *pRxBlk,
3153         IN      UCHAR                   FromWhichBSSID)
3154 {
3155 #ifdef DOT11_N_SUPPORT
3156         if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
3157         {
3158                 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
3159         }
3160         else
3161 #endif // DOT11_N_SUPPORT //
3162         {
3163 #ifdef DOT11_N_SUPPORT
3164                 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
3165                 {
3166                         // handle A-MSDU
3167                         Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
3168                 }
3169                 else
3170 #endif // DOT11_N_SUPPORT //
3171                 {
3172                         Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
3173                 }
3174         }
3175 }
3176
3177
3178 VOID CmmRxRalinkFrameIndicate(
3179         IN      PRTMP_ADAPTER   pAd,
3180         IN      MAC_TABLE_ENTRY *pEntry,
3181         IN      RX_BLK                  *pRxBlk,
3182         IN      UCHAR                   FromWhichBSSID)
3183 {
3184         UCHAR                   Header802_3[LENGTH_802_3];
3185         UINT16                  Msdu2Size;
3186         UINT16                  Payload1Size, Payload2Size;
3187         PUCHAR                  pData2;
3188         PNDIS_PACKET    pPacket2 = NULL;
3189
3190
3191
3192         Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
3193
3194         if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
3195         {
3196                 /* skip two byte MSDU2 len */
3197                 pRxBlk->pData += 2;
3198                 pRxBlk->DataSize -= 2;
3199         }
3200         else
3201         {
3202                 // release packet
3203                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
3204                 return;
3205         }
3206
3207         // get 802.3 Header and  remove LLC
3208 #ifdef CONFIG_STA_SUPPORT
3209         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3210                 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
3211 #endif // CONFIG_STA_SUPPORT //
3212
3213
3214         ASSERT(pRxBlk->pRxPacket);
3215
3216         // Ralink Aggregation frame
3217         pAd->RalinkCounters.OneSecRxAggregationCount ++;
3218         Payload1Size = pRxBlk->DataSize - Msdu2Size;
3219         Payload2Size = Msdu2Size - LENGTH_802_3;
3220
3221         pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
3222 #ifdef CONFIG_STA_SUPPORT
3223         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3224                 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
3225 #endif // CONFIG_STA_SUPPORT //
3226
3227         if (!pPacket2)
3228         {
3229                 // release packet
3230                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
3231                 return;
3232         }
3233
3234         // update payload size of 1st packet
3235         pRxBlk->DataSize = Payload1Size;
3236         wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
3237
3238 #ifdef CONFIG_STA_SUPPORT
3239         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3240                 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
3241 #endif // CONFIG_STA_SUPPORT //
3242
3243         if (pPacket2)
3244         {
3245 #ifdef CONFIG_STA_SUPPORT
3246                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3247                         ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
3248 #endif // CONFIG_STA_SUPPORT //
3249         }
3250 }
3251
3252
3253 #define RESET_FRAGFRAME(_fragFrame) \
3254         {                                                               \
3255                 _fragFrame.RxSize = 0;          \
3256                 _fragFrame.Sequence = 0;        \
3257                 _fragFrame.LastFrag = 0;        \
3258                 _fragFrame.Flags = 0;           \
3259         }
3260
3261
3262 PNDIS_PACKET RTMPDeFragmentDataFrame(
3263         IN      PRTMP_ADAPTER   pAd,
3264         IN      RX_BLK                  *pRxBlk)
3265 {
3266         PHEADER_802_11  pHeader = pRxBlk->pHeader;
3267         PNDIS_PACKET    pRxPacket = pRxBlk->pRxPacket;
3268         UCHAR                   *pData = pRxBlk->pData;
3269         USHORT                  DataSize = pRxBlk->DataSize;
3270         PNDIS_PACKET    pRetPacket = NULL;
3271         UCHAR                   *pFragBuffer = NULL;
3272         BOOLEAN                 bReassDone = FALSE;
3273         UCHAR                   HeaderRoom = 0;
3274
3275
3276         ASSERT(pHeader);
3277
3278         HeaderRoom = pData - (UCHAR *)pHeader;
3279
3280         // Re-assemble the fragmented packets
3281         if (pHeader->Frag == 0)         // Frag. Number is 0 : First frag or only one pkt
3282         {
3283                 // the first pkt of fragment, record it.
3284                 if (pHeader->FC.MoreFrag)
3285                 {
3286                         ASSERT(pAd->FragFrame.pFragPacket);
3287                         pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
3288                         pAd->FragFrame.RxSize   = DataSize + HeaderRoom;
3289                         NdisMoveMemory(pFragBuffer,      pHeader, pAd->FragFrame.RxSize);
3290                         pAd->FragFrame.Sequence = pHeader->Sequence;
3291                         pAd->FragFrame.LastFrag = pHeader->Frag;           // Should be 0
3292                         ASSERT(pAd->FragFrame.LastFrag == 0);
3293                         goto done;      // end of processing this frame
3294                 }
3295         }
3296         else    //Middle & End of fragment
3297         {
3298                 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
3299                         (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
3300                 {
3301                         // Fragment is not the same sequence or out of fragment number order
3302                         // Reset Fragment control blk
3303                         RESET_FRAGFRAME(pAd->FragFrame);
3304                         DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
3305                         goto done; // give up this frame
3306                 }
3307                 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
3308                 {
3309                         // Fragment frame is too large, it exeeds the maximum frame size.
3310                         // Reset Fragment control blk
3311                         RESET_FRAGFRAME(pAd->FragFrame);
3312                         DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
3313                         goto done; // give up this frame
3314                 }
3315
3316         //
3317                 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
3318                 // In this case, we will dropt it.
3319                 //
3320                 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
3321                 {
3322                         DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
3323                         goto done; // give up this frame
3324                 }
3325
3326                 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
3327
3328                 // concatenate this fragment into the re-assembly buffer
3329                 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
3330                 pAd->FragFrame.RxSize  += DataSize;
3331                 pAd->FragFrame.LastFrag = pHeader->Frag;           // Update fragment number
3332
3333                 // Last fragment
3334                 if (pHeader->FC.MoreFrag == FALSE)
3335                 {
3336                         bReassDone = TRUE;
3337                 }
3338         }
3339
3340 done:
3341         // always release rx fragmented packet
3342         RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
3343
3344         // return defragmented packet if packet is reassembled completely
3345         // otherwise return NULL
3346         if (bReassDone)
3347         {
3348                 PNDIS_PACKET pNewFragPacket;
3349
3350                 // allocate a new packet buffer for fragment
3351                 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
3352                 if (pNewFragPacket)
3353                 {
3354                         // update RxBlk
3355                         pRetPacket = pAd->FragFrame.pFragPacket;
3356                         pAd->FragFrame.pFragPacket = pNewFragPacket;
3357                         pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
3358                         pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
3359                         pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
3360                         pRxBlk->pRxPacket = pRetPacket;
3361                 }
3362                 else
3363                 {
3364                         RESET_FRAGFRAME(pAd->FragFrame);
3365                 }
3366         }
3367
3368         return pRetPacket;
3369 }
3370
3371
3372 VOID Indicate_AMSDU_Packet(
3373         IN      PRTMP_ADAPTER   pAd,
3374         IN      RX_BLK                  *pRxBlk,
3375         IN      UCHAR                   FromWhichBSSID)
3376 {
3377         UINT                    nMSDU;
3378
3379         update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
3380         RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
3381         nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
3382 }
3383
3384 VOID Indicate_EAPOL_Packet(
3385         IN      PRTMP_ADAPTER   pAd,
3386         IN      RX_BLK                  *pRxBlk,
3387         IN      UCHAR                   FromWhichBSSID)
3388 {
3389         MAC_TABLE_ENTRY *pEntry = NULL;
3390
3391
3392 #ifdef CONFIG_STA_SUPPORT
3393         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3394         {
3395                 pEntry = &pAd->MacTab.Content[BSSID_WCID];
3396                 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
3397                 return;
3398         }
3399 #endif // CONFIG_STA_SUPPORT //
3400
3401         if (pEntry == NULL)
3402         {
3403                 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
3404                 // release packet
3405                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
3406                 return;
3407         }
3408 }
3409
3410 #define BCN_TBTT_OFFSET         64      //defer 64 us
3411 VOID ReSyncBeaconTime(
3412         IN  PRTMP_ADAPTER   pAd)
3413 {
3414
3415         UINT32  Offset;
3416
3417
3418         Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
3419
3420         pAd->TbttTickCount++;
3421
3422         //
3423         // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
3424         // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
3425         //
3426         if (Offset == (BCN_TBTT_OFFSET-2))
3427         {
3428                 BCN_TIME_CFG_STRUC csr;
3429                 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
3430                 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ;     // ASIC register in units of 1/16 TU = 64us
3431                 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
3432         }
3433         else
3434         {
3435                 if (Offset == (BCN_TBTT_OFFSET-1))
3436                 {
3437                         BCN_TIME_CFG_STRUC csr;
3438
3439                         RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
3440                         csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
3441                         RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
3442                 }
3443         }
3444 }
3445