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