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