]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/rt2870/common/cmm_data.c
4477a8e64a29898594ba6871639efadf39674e21
[net-next-2.6.git] / 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 FillTxBlkErr:
714         return FALSE;
715 }
716
717
718 BOOLEAN CanDoAggregateTransmit(
719         IN RTMP_ADAPTER *pAd,
720         IN NDIS_PACKET *pPacket,
721         IN TX_BLK               *pTxBlk)
722 {
723
724         //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
725
726         if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
727                 return FALSE;
728
729         if (RTMP_GET_PACKET_DHCP(pPacket) ||
730                 RTMP_GET_PACKET_EAPOL(pPacket) ||
731                 RTMP_GET_PACKET_WAI(pPacket))
732                 return FALSE;
733
734         if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
735                 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
736         {       // For AMSDU, allow the packets with total length < max-amsdu size
737                 return FALSE;
738         }
739
740         if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
741                 (pTxBlk->TxPacketList.Number == 2))
742         {       // For RALINK-Aggregation, allow two frames in one batch.
743                 return FALSE;
744         }
745
746 #ifdef CONFIG_STA_SUPPORT
747         if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
748                 return TRUE;
749         else
750 #endif // CONFIG_STA_SUPPORT //
751                 return FALSE;
752
753 }
754
755
756 /*
757         ========================================================================
758
759         Routine Description:
760                 To do the enqueue operation and extract the first item of waiting
761                 list. If a number of available shared memory segments could meet
762                 the request of extracted item, the extracted item will be fragmented
763                 into shared memory segments.
764
765         Arguments:
766                 pAd Pointer to our adapter
767                 pQueue          Pointer to Waiting Queue
768
769         Return Value:
770                 None
771
772         IRQL = DISPATCH_LEVEL
773
774         Note:
775
776         ========================================================================
777 */
778 VOID RTMPDeQueuePacket(
779         IN  PRTMP_ADAPTER   pAd,
780         IN  BOOLEAN         bIntContext,
781         IN  UCHAR                       QIdx, /* BulkOutPipeId */
782         IN  UCHAR           Max_Tx_Packets)
783 {
784         PQUEUE_ENTRY    pEntry = NULL;
785         PNDIS_PACKET    pPacket;
786         NDIS_STATUS     Status = NDIS_STATUS_SUCCESS;
787         UCHAR           Count=0;
788         PQUEUE_HEADER   pQueue;
789         ULONG           FreeNumber[NUM_OF_TX_RING];
790         UCHAR                   QueIdx, sQIdx, eQIdx;
791         unsigned long   IrqFlags = 0;
792         BOOLEAN                 hasTxDesc = FALSE;
793         TX_BLK                  TxBlk;
794         TX_BLK                  *pTxBlk;
795
796 #ifdef DBG_DIAGNOSE
797         BOOLEAN                 firstRound;
798         RtmpDiagStruct  *pDiagStruct = &pAd->DiagStruct;
799 #endif
800
801
802         if (QIdx == NUM_OF_TX_RING)
803         {
804                 sQIdx = 0;
805                 eQIdx = 3;      // 4 ACs, start from 0.
806         }
807         else
808         {
809                 sQIdx = eQIdx = QIdx;
810         }
811
812         for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
813         {
814                 Count=0;
815
816                 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
817
818 #ifdef DBG_DIAGNOSE
819                 firstRound = ((QueIdx == 0) ? TRUE : FALSE);
820 #endif // DBG_DIAGNOSE //
821
822                 while (1)
823                 {
824                         if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
825                                                                                 fRTMP_ADAPTER_RADIO_OFF |
826                                                                                 fRTMP_ADAPTER_RESET_IN_PROGRESS |
827                                                                                 fRTMP_ADAPTER_HALT_IN_PROGRESS |
828                                                                                 fRTMP_ADAPTER_NIC_NOT_EXIST))))
829                         {
830                                 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
831                                 return;
832                         }
833
834                         if (Count >= Max_Tx_Packets)
835                                 break;
836
837                         DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
838                         if (&pAd->TxSwQueue[QueIdx] == NULL)
839                         {
840 #ifdef DBG_DIAGNOSE
841                                 if (firstRound == TRUE)
842                                         pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
843 #endif // DBG_DIAGNOSE //
844                                 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
845                                 break;
846                         }
847
848
849                         // probe the Queue Head
850                         pQueue = &pAd->TxSwQueue[QueIdx];
851                         if ((pEntry = pQueue->Head) == NULL)
852                         {
853                                 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
854                                 break;
855                         }
856
857                         pTxBlk = &TxBlk;
858                         NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
859                         //InitializeQueueHeader(&pTxBlk->TxPacketList);         // Didn't need it because we already memzero it.
860                         pTxBlk->QueIdx = QueIdx;
861
862                         pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
863
864                         // Early check to make sure we have enoguh Tx Resource.
865                         hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
866                         if (!hasTxDesc)
867                         {
868                                 pAd->PrivateInfo.TxRingFullCnt++;
869
870                                 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
871
872                                 break;
873                         }
874
875                         pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
876                         pEntry = RemoveHeadQueue(pQueue);
877                         pTxBlk->TotalFrameNum++;
878                         pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket);     // The real fragment number maybe vary
879                         pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
880                         pTxBlk->pPacket = pPacket;
881                         InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
882
883                         if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
884                         {
885                                 // Enhance SW Aggregation Mechanism
886                                 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
887                                 {
888                                         InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
889                                         DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
890                                         break;
891                                 }
892
893                                 do{
894                                         if((pEntry = pQueue->Head) == NULL)
895                                                 break;
896
897                                         // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
898                                         pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
899                                         FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
900                                         hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
901                                         if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
902                                                 break;
903
904                                         //Remove the packet from the TxSwQueue and insert into pTxBlk
905                                         pEntry = RemoveHeadQueue(pQueue);
906                                         ASSERT(pEntry);
907                                         pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
908                                         pTxBlk->TotalFrameNum++;
909                                         pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket);     // The real fragment number maybe vary
910                                         pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
911                                         InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
912                                 }while(1);
913
914                                 if (pTxBlk->TxPacketList.Number == 1)
915                                         pTxBlk->TxFrameType = TX_LEGACY_FRAME;
916                         }
917
918 #ifdef RT2870
919                         DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
920 #endif // RT2870 //
921
922                         Count += pTxBlk->TxPacketList.Number;
923
924                                 // Do HardTransmit now.
925 #ifdef CONFIG_STA_SUPPORT
926                         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
927                                 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
928 #endif // CONFIG_STA_SUPPORT //
929
930
931 #if 0   // We should not break if HardTransmit failed. Well, at least now we should not!
932                         if (Status != NDIS_STATUS_SUCCESS)
933                         {
934                                 DBGPRINT(RT_DEBUG_TRACE /*RT_DEBUG_INFO*/,("RTMPHardTransmit return failed!!!\n"));
935                                 break;
936                         }
937 #endif
938                 }
939
940                 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
941
942 #ifdef RT2870
943                 if (!hasTxDesc)
944                         RTUSBKickBulkOut(pAd);
945 #endif // RT2870 //
946
947 #ifdef BLOCK_NET_IF
948                 if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE)
949                         && (pAd->TxSwQueue[QueIdx].Number < 1))
950                 {
951                         releaseNetIf(&pAd->blockQueueTab[QueIdx]);
952                 }
953 #endif // BLOCK_NET_IF //
954
955         }
956
957 }
958
959
960 /*
961         ========================================================================
962
963         Routine Description:
964                 Calculates the duration which is required to transmit out frames
965         with given size and specified rate.
966
967         Arguments:
968                 pAd     Pointer to our adapter
969                 Rate                    Transmit rate
970                 Size                    Frame size in units of byte
971
972         Return Value:
973                 Duration number in units of usec
974
975         IRQL = PASSIVE_LEVEL
976         IRQL = DISPATCH_LEVEL
977
978         Note:
979
980         ========================================================================
981 */
982 USHORT  RTMPCalcDuration(
983         IN      PRTMP_ADAPTER   pAd,
984         IN      UCHAR                   Rate,
985         IN      ULONG                   Size)
986 {
987         ULONG   Duration = 0;
988
989         if (Rate < RATE_FIRST_OFDM_RATE) // CCK
990         {
991                 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
992                         Duration = 96;  // 72+24 preamble+plcp
993                 else
994                         Duration = 192; // 144+48 preamble+plcp
995
996                 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
997                 if ((Size << 4) % RateIdTo500Kbps[Rate])
998                         Duration ++;
999         }
1000         else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
1001         {
1002                 Duration = 20 + 6;              // 16+4 preamble+plcp + Signal Extension
1003                 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
1004                 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
1005                         Duration += 4;
1006         }
1007         else    //mimo rate
1008         {
1009                 Duration = 20 + 6;              // 16+4 preamble+plcp + Signal Extension
1010         }
1011
1012         return (USHORT)Duration;
1013 }
1014
1015
1016 /*
1017         ========================================================================
1018
1019         Routine Description:
1020                 Calculates the duration which is required to transmit out frames
1021         with given size and specified rate.
1022
1023         Arguments:
1024                 pTxWI           Pointer to head of each MPDU to HW.
1025                 Ack             Setting for Ack requirement bit
1026                 Fragment        Setting for Fragment bit
1027                 RetryMode       Setting for retry mode
1028                 Ifs             Setting for IFS gap
1029                 Rate            Setting for transmit rate
1030                 Service         Setting for service
1031                 Length          Frame length
1032                 TxPreamble      Short or Long preamble when using CCK rates
1033                 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1034
1035         Return Value:
1036                 None
1037
1038         IRQL = PASSIVE_LEVEL
1039         IRQL = DISPATCH_LEVEL
1040
1041     See also : BASmartHardTransmit()    !!!
1042
1043         ========================================================================
1044 */
1045 VOID RTMPWriteTxWI(
1046         IN      PRTMP_ADAPTER   pAd,
1047         IN      PTXWI_STRUC     pOutTxWI,
1048         IN      BOOLEAN                 FRAG,
1049         IN      BOOLEAN                 CFACK,
1050         IN      BOOLEAN                 InsTimestamp,
1051         IN      BOOLEAN                 AMPDU,
1052         IN      BOOLEAN                 Ack,
1053         IN      BOOLEAN                 NSeq,           // HW new a sequence.
1054         IN      UCHAR                   BASize,
1055         IN      UCHAR                   WCID,
1056         IN      ULONG                   Length,
1057         IN      UCHAR                   PID,
1058         IN      UCHAR                   TID,
1059         IN      UCHAR                   TxRate,
1060         IN      UCHAR                   Txopmode,
1061         IN      BOOLEAN                 CfAck,
1062         IN      HTTRANSMIT_SETTING      *pTransmit)
1063 {
1064         PMAC_TABLE_ENTRY        pMac = NULL;
1065         TXWI_STRUC              TxWI;
1066         PTXWI_STRUC     pTxWI;
1067
1068         if (WCID < MAX_LEN_OF_MAC_TABLE)
1069                 pMac = &pAd->MacTab.Content[WCID];
1070
1071         //
1072         // Always use Long preamble before verifiation short preamble functionality works well.
1073         // Todo: remove the following line if short preamble functionality works
1074         //
1075         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1076         NdisZeroMemory(&TxWI, TXWI_SIZE);
1077         pTxWI = &TxWI;
1078
1079         pTxWI->FRAG= FRAG;
1080
1081         pTxWI->CFACK = CFACK;
1082         pTxWI->TS= InsTimestamp;
1083         pTxWI->AMPDU = AMPDU;
1084         pTxWI->ACK = Ack;
1085         pTxWI->txop= Txopmode;
1086
1087         pTxWI->NSEQ = NSeq;
1088         // John tune the performace with Intel Client in 20 MHz performance
1089 #ifdef DOT11_N_SUPPORT
1090         BASize = pAd->CommonCfg.TxBASize;
1091
1092         if( BASize >7 )
1093                 BASize =7;
1094         pTxWI->BAWinSize = BASize;
1095         pTxWI->ShortGI = pTransmit->field.ShortGI;
1096         pTxWI->STBC = pTransmit->field.STBC;
1097 #endif // DOT11_N_SUPPORT //
1098
1099         pTxWI->WirelessCliID = WCID;
1100         pTxWI->MPDUtotalByteCount = Length;
1101         pTxWI->PacketId = PID;
1102
1103         // If CCK or OFDM, BW must be 20
1104         pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1105 #ifdef DOT11N_DRAFT3
1106         if (pTxWI->BW)
1107                 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1108 #endif // DOT11N_DRAFT3 //
1109
1110         pTxWI->MCS = pTransmit->field.MCS;
1111         pTxWI->PHYMODE = pTransmit->field.MODE;
1112         pTxWI->CFACK = CfAck;
1113
1114 #ifdef DOT11_N_SUPPORT
1115         if (pMac)
1116         {
1117                 if (pAd->CommonCfg.bMIMOPSEnable)
1118                 {
1119                         if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1120                         {
1121                                 // Dynamic MIMO Power Save Mode
1122                                 pTxWI->MIMOps = 1;
1123                         }
1124                         else if (pMac->MmpsMode == MMPS_STATIC)
1125                         {
1126                                 // Static MIMO Power Save Mode
1127                                 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1128                                 {
1129                                         pTxWI->MCS = 7;
1130                                         pTxWI->MIMOps = 0;
1131                                 }
1132                         }
1133                 }
1134                 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1135                 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1136                 {
1137                         pTxWI->MpduDensity = 7;
1138                 }
1139                 else
1140                 {
1141                         pTxWI->MpduDensity = pMac->MpduDensity;
1142                 }
1143         }
1144 #endif // DOT11_N_SUPPORT //
1145
1146         pTxWI->PacketId = pTxWI->MCS;
1147         NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1148 }
1149
1150
1151 VOID RTMPWriteTxWI_Data(
1152         IN      PRTMP_ADAPTER           pAd,
1153         IN      OUT PTXWI_STRUC         pTxWI,
1154         IN      TX_BLK                          *pTxBlk)
1155 {
1156         HTTRANSMIT_SETTING      *pTransmit;
1157         PMAC_TABLE_ENTRY        pMacEntry;
1158 #ifdef DOT11_N_SUPPORT
1159         UCHAR                           BASize;
1160 #endif // DOT11_N_SUPPORT //
1161
1162
1163         ASSERT(pTxWI);
1164
1165         pTransmit = pTxBlk->pTransmit;
1166         pMacEntry = pTxBlk->pMacEntry;
1167
1168
1169         //
1170         // Always use Long preamble before verifiation short preamble functionality works well.
1171         // Todo: remove the following line if short preamble functionality works
1172         //
1173         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1174         NdisZeroMemory(pTxWI, TXWI_SIZE);
1175
1176         pTxWI->FRAG             = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1177         pTxWI->ACK              = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1178         pTxWI->txop             = pTxBlk->FrameGap;
1179
1180 #ifdef CONFIG_STA_SUPPORT
1181 #ifdef QOS_DLS_SUPPORT
1182         if (pMacEntry &&
1183                 (pAd->StaCfg.BssType == BSS_INFRA) &&
1184                 (pMacEntry->ValidAsDls == TRUE))
1185                 pTxWI->WirelessCliID = BSSID_WCID;
1186         else
1187 #endif // QOS_DLS_SUPPORT //
1188 #endif // CONFIG_STA_SUPPORT //
1189                 pTxWI->WirelessCliID            = pTxBlk->Wcid;
1190
1191         pTxWI->MPDUtotalByteCount       = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1192         pTxWI->CFACK                            = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1193
1194         // If CCK or OFDM, BW must be 20
1195         pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1196 #ifdef DOT11_N_SUPPORT
1197 #ifdef DOT11N_DRAFT3
1198         if (pTxWI->BW)
1199                 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1200 #endif // DOT11N_DRAFT3 //
1201         pTxWI->AMPDU    = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1202
1203         // John tune the performace with Intel Client in 20 MHz performance
1204         BASize = pAd->CommonCfg.TxBASize;
1205         if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1206         {
1207                 UCHAR           RABAOriIdx = 0; //The RA's BA Originator table index.
1208
1209                 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1210                 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1211         }
1212
1213 #if 0 // 3*3
1214         if (BASize > 7)
1215                 BASize = 7;
1216 #endif
1217
1218         pTxWI->TxBF = pTransmit->field.TxBF;
1219         pTxWI->BAWinSize = BASize;
1220         pTxWI->ShortGI = pTransmit->field.ShortGI;
1221         pTxWI->STBC = pTransmit->field.STBC;
1222 #endif // DOT11_N_SUPPORT //
1223
1224         pTxWI->MCS = pTransmit->field.MCS;
1225         pTxWI->PHYMODE = pTransmit->field.MODE;
1226
1227 #ifdef DOT11_N_SUPPORT
1228         if (pMacEntry)
1229         {
1230                 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1231                 {
1232                         // Dynamic MIMO Power Save Mode
1233                         pTxWI->MIMOps = 1;
1234                 }
1235                 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1236                 {
1237                         // Static MIMO Power Save Mode
1238                         if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1239                         {
1240                                 pTxWI->MCS = 7;
1241                                 pTxWI->MIMOps = 0;
1242                         }
1243                 }
1244
1245                 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1246                 {
1247                         pTxWI->MpduDensity = 7;
1248                 }
1249                 else
1250                 {
1251                         pTxWI->MpduDensity = pMacEntry->MpduDensity;
1252                 }
1253         }
1254 #endif // DOT11_N_SUPPORT //
1255
1256 #ifdef DBG_DIAGNOSE
1257                 if (pTxBlk->QueIdx== 0)
1258                 {
1259                         pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1260                         pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1261                 }
1262 #endif // DBG_DIAGNOSE //
1263
1264         // for rate adapation
1265         pTxWI->PacketId = pTxWI->MCS;
1266 }
1267
1268
1269 VOID RTMPWriteTxWI_Cache(
1270         IN      PRTMP_ADAPTER           pAd,
1271         IN      OUT PTXWI_STRUC         pTxWI,
1272         IN      TX_BLK                          *pTxBlk)
1273 {
1274         PHTTRANSMIT_SETTING     /*pTxHTPhyMode,*/ pTransmit;
1275         PMAC_TABLE_ENTRY        pMacEntry;
1276
1277         //
1278         // update TXWI
1279         //
1280         pMacEntry = pTxBlk->pMacEntry;
1281         pTransmit = pTxBlk->pTransmit;
1282
1283         if (pMacEntry->bAutoTxRateSwitch)
1284         {
1285                 pTxWI->txop = IFS_HTTXOP;
1286
1287                 // If CCK or OFDM, BW must be 20
1288                 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1289                 pTxWI->ShortGI = pTransmit->field.ShortGI;
1290                 pTxWI->STBC = pTransmit->field.STBC;
1291
1292                 pTxWI->MCS = pTransmit->field.MCS;
1293                 pTxWI->PHYMODE = pTransmit->field.MODE;
1294
1295                 // set PID for TxRateSwitching
1296                 pTxWI->PacketId = pTransmit->field.MCS;
1297         }
1298
1299 #ifdef DOT11_N_SUPPORT
1300         pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1301         pTxWI->MIMOps = 0;
1302
1303 #ifdef DOT11N_DRAFT3
1304         if (pTxWI->BW)
1305                 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1306 #endif // DOT11N_DRAFT3 //
1307
1308         if (pAd->CommonCfg.bMIMOPSEnable)
1309         {
1310                 // MIMO Power Save Mode
1311                 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1312                 {
1313                         // Dynamic MIMO Power Save Mode
1314                         pTxWI->MIMOps = 1;
1315                 }
1316                 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1317                 {
1318                         // Static MIMO Power Save Mode
1319                         if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1320                         {
1321                                 pTxWI->MCS = 7;
1322                                 pTxWI->MIMOps = 0;
1323                         }
1324                 }
1325         }
1326 #endif // DOT11_N_SUPPORT //
1327
1328 #ifdef DBG_DIAGNOSE
1329         if (pTxBlk->QueIdx== 0)
1330         {
1331                 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1332                 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1333         }
1334 #endif // DBG_DIAGNOSE //
1335
1336         pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1337
1338 }
1339
1340
1341 /*
1342         ========================================================================
1343
1344         Routine Description:
1345                 Calculates the duration which is required to transmit out frames
1346         with given size and specified rate.
1347
1348         Arguments:
1349                 pTxD            Pointer to transmit descriptor
1350                 Ack             Setting for Ack requirement bit
1351                 Fragment        Setting for Fragment bit
1352                 RetryMode       Setting for retry mode
1353                 Ifs             Setting for IFS gap
1354                 Rate            Setting for transmit rate
1355                 Service         Setting for service
1356                 Length          Frame length
1357                 TxPreamble      Short or Long preamble when using CCK rates
1358                 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1359
1360         Return Value:
1361                 None
1362
1363         IRQL = PASSIVE_LEVEL
1364         IRQL = DISPATCH_LEVEL
1365
1366         ========================================================================
1367 */
1368 VOID RTMPWriteTxDescriptor(
1369         IN      PRTMP_ADAPTER   pAd,
1370         IN      PTXD_STRUC              pTxD,
1371         IN      BOOLEAN                 bWIV,
1372         IN      UCHAR                   QueueSEL)
1373 {
1374         //
1375         // Always use Long preamble before verifiation short preamble functionality works well.
1376         // Todo: remove the following line if short preamble functionality works
1377         //
1378         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1379
1380         pTxD->WIV       = (bWIV) ? 1: 0;
1381         pTxD->QSEL= (QueueSEL);
1382         //RT2860c??  fixed using EDCA queue for test...  We doubt Queue1 has problem.  2006-09-26 Jan
1383         //pTxD->QSEL= FIFO_EDCA;
1384         if (pAd->bGenOneHCCA == TRUE)
1385                 pTxD->QSEL= FIFO_HCCA;
1386         pTxD->DMADONE = 0;
1387 }
1388
1389
1390 // should be called only when -
1391 // 1. MEADIA_CONNECTED
1392 // 2. AGGREGATION_IN_USED
1393 // 3. Fragmentation not in used
1394 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1395 BOOLEAN TxFrameIsAggregatible(
1396         IN      PRTMP_ADAPTER   pAd,
1397         IN      PUCHAR                  pPrevAddr1,
1398         IN      PUCHAR                  p8023hdr)
1399 {
1400
1401         // can't aggregate EAPOL (802.1x) frame
1402         if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1403                 return FALSE;
1404
1405         // can't aggregate multicast/broadcast frame
1406         if (p8023hdr[0] & 0x01)
1407                 return FALSE;
1408
1409         if (INFRA_ON(pAd)) // must be unicast to AP
1410                 return TRUE;
1411         else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1412                 return TRUE;
1413         else
1414                 return FALSE;
1415 }
1416
1417
1418 /*
1419         ========================================================================
1420
1421         Routine Description:
1422            Check the MSDU Aggregation policy
1423         1.HT aggregation is A-MSDU
1424         2.legaacy rate aggregation is software aggregation by Ralink.
1425
1426         Arguments:
1427
1428         Return Value:
1429
1430         Note:
1431
1432         ========================================================================
1433 */
1434 BOOLEAN PeerIsAggreOn(
1435         IN      PRTMP_ADAPTER   pAd,
1436         IN      ULONG              TxRate,
1437         IN      PMAC_TABLE_ENTRY pMacEntry)
1438 {
1439         ULONG   AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1440
1441         if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1442         {
1443 #ifdef DOT11_N_SUPPORT
1444                 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1445                 {
1446                         return TRUE;
1447                 }
1448 #endif // DOT11_N_SUPPORT //
1449
1450 #ifdef AGGREGATION_SUPPORT
1451                 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1452                 {       // legacy  Ralink Aggregation support
1453                         return TRUE;
1454                 }
1455 #endif // AGGREGATION_SUPPORT //
1456         }
1457
1458         return FALSE;
1459
1460 }
1461
1462 /*
1463         ========================================================================
1464
1465         Routine Description:
1466                 Check and fine the packet waiting in SW queue with highest priority
1467
1468         Arguments:
1469                 pAd Pointer to our adapter
1470
1471         Return Value:
1472                 pQueue          Pointer to Waiting Queue
1473
1474         IRQL = DISPATCH_LEVEL
1475
1476         Note:
1477
1478         ========================================================================
1479 */
1480 PQUEUE_HEADER   RTMPCheckTxSwQueue(
1481         IN      PRTMP_ADAPTER   pAd,
1482         OUT PUCHAR                      pQueIdx)
1483 {
1484
1485         ULONG   Number;
1486         // 2004-11-15 to be removed. test aggregation only
1487 //      if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2))
1488 //               return NULL;
1489
1490         Number = pAd->TxSwQueue[QID_AC_BK].Number
1491                          + pAd->TxSwQueue[QID_AC_BE].Number
1492                          + pAd->TxSwQueue[QID_AC_VI].Number
1493                          + pAd->TxSwQueue[QID_AC_VO].Number
1494                          + pAd->TxSwQueue[QID_HCCA].Number;
1495
1496         if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1497         {
1498                 *pQueIdx = QID_AC_VO;
1499                 return (&pAd->TxSwQueue[QID_AC_VO]);
1500         }
1501         else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1502         {
1503                 *pQueIdx = QID_AC_VI;
1504                 return (&pAd->TxSwQueue[QID_AC_VI]);
1505         }
1506         else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1507         {
1508                 *pQueIdx = QID_AC_BE;
1509                 return (&pAd->TxSwQueue[QID_AC_BE]);
1510         }
1511         else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1512         {
1513                 *pQueIdx = QID_AC_BK;
1514                 return (&pAd->TxSwQueue[QID_AC_BK]);
1515         }
1516         else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1517         {
1518                 *pQueIdx = QID_HCCA;
1519                 return (&pAd->TxSwQueue[QID_HCCA]);
1520         }
1521
1522         // No packet pending in Tx Sw queue
1523         *pQueIdx = QID_AC_BK;
1524
1525         return (NULL);
1526 }
1527
1528
1529
1530 /*
1531         ========================================================================
1532
1533         Routine Description:
1534                 Suspend MSDU transmission
1535
1536         Arguments:
1537                 pAd     Pointer to our adapter
1538
1539         Return Value:
1540                 None
1541
1542         Note:
1543
1544         ========================================================================
1545 */
1546 VOID    RTMPSuspendMsduTransmission(
1547         IN      PRTMP_ADAPTER   pAd)
1548 {
1549         DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1550
1551
1552         //
1553         // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1554         // use Lowbound as R66 value on ScanNextChannel(...)
1555         //
1556         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1557
1558         // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1559         //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
1560         RTMPSetAGCInitValue(pAd, BW_20);
1561
1562         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1563         //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000);                // abort all TX rings
1564 }
1565
1566
1567 /*
1568         ========================================================================
1569
1570         Routine Description:
1571                 Resume MSDU transmission
1572
1573         Arguments:
1574                 pAd     Pointer to our adapter
1575
1576         Return Value:
1577                 None
1578
1579         IRQL = DISPATCH_LEVEL
1580
1581         Note:
1582
1583         ========================================================================
1584 */
1585 VOID RTMPResumeMsduTransmission(
1586         IN      PRTMP_ADAPTER   pAd)
1587 {
1588 //    UCHAR                     IrqState;
1589
1590         DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1591
1592
1593         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1594
1595         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1596 // sample, for IRQ LOCK to SEM LOCK
1597 //    IrqState = pAd->irq_disabled;
1598 //      if (IrqState)
1599 //              RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1600 //    else
1601         RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1602 }
1603
1604
1605 UINT deaggregate_AMSDU_announce(
1606         IN      PRTMP_ADAPTER   pAd,
1607         PNDIS_PACKET            pPacket,
1608         IN      PUCHAR                  pData,
1609         IN      ULONG                   DataSize)
1610 {
1611         USHORT                  PayloadSize;
1612         USHORT                  SubFrameSize;
1613         PHEADER_802_3   pAMSDUsubheader;
1614         UINT                    nMSDU;
1615     UCHAR                       Header802_3[14];
1616
1617         PUCHAR                  pPayload, pDA, pSA, pRemovedLLCSNAP;
1618         PNDIS_PACKET    pClonePacket;
1619
1620
1621
1622         nMSDU = 0;
1623
1624         while (DataSize > LENGTH_802_3)
1625         {
1626
1627                 nMSDU++;
1628
1629                 //hex_dump("subheader", pData, 64);
1630                 pAMSDUsubheader = (PHEADER_802_3)pData;
1631                 //pData += LENGTH_802_3;
1632                 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1633                 SubFrameSize = PayloadSize + LENGTH_802_3;
1634
1635
1636                 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
1637                 {
1638                         break;
1639                 }
1640
1641                 //printk("%d subframe: Size = %d\n",  nMSDU, PayloadSize);
1642
1643                 pPayload = pData + LENGTH_802_3;
1644                 pDA = pData;
1645                 pSA = pData + MAC_ADDR_LEN;
1646
1647                 // convert to 802.3 header
1648         CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
1649
1650 #ifdef CONFIG_STA_SUPPORT
1651                 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
1652                 {
1653                     // avoid local heap overflow, use dyanamic allocation
1654                    MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1655                    memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
1656                    Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
1657                    WpaEAPOLKeyAction(pAd, Elem);
1658                    kfree(Elem);
1659                 }
1660 #endif // CONFIG_STA_SUPPORT //
1661
1662 #ifdef CONFIG_STA_SUPPORT
1663                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1664                 {
1665                         if (pRemovedLLCSNAP)
1666                         {
1667                                 pPayload -= LENGTH_802_3;
1668                                 PayloadSize += LENGTH_802_3;
1669                                 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
1670                         }
1671                 }
1672 #endif // CONFIG_STA_SUPPORT //
1673
1674                 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1675                 if (pClonePacket)
1676                 {
1677 #ifdef CONFIG_STA_SUPPORT
1678                         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1679                                 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
1680 #endif // CONFIG_STA_SUPPORT //
1681                 }
1682
1683
1684                 // A-MSDU has padding to multiple of 4 including subframe header.
1685                 // align SubFrameSize up to multiple of 4
1686                 SubFrameSize = (SubFrameSize+3)&(~0x3);
1687
1688
1689                 if (SubFrameSize > 1528 || SubFrameSize < 32)
1690                 {
1691                         break;
1692                 }
1693
1694                 if (DataSize > SubFrameSize)
1695                 {
1696                         pData += SubFrameSize;
1697                         DataSize -= SubFrameSize;
1698                 }
1699                 else
1700                 {
1701                         // end of A-MSDU
1702                         DataSize = 0;
1703                 }
1704         }
1705
1706         // finally release original rx packet
1707         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1708
1709         return nMSDU;
1710 }
1711
1712
1713 UINT BA_Reorder_AMSDU_Annnounce(
1714         IN      PRTMP_ADAPTER   pAd,
1715         IN      PNDIS_PACKET    pPacket)
1716 {
1717         PUCHAR                  pData;
1718         USHORT                  DataSize;
1719         UINT                    nMSDU = 0;
1720
1721         pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1722         DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1723
1724         nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1725
1726         return nMSDU;
1727 }
1728
1729
1730 /*
1731         ==========================================================================
1732         Description:
1733                 Look up the MAC address in the MAC table. Return NULL if not found.
1734         Return:
1735                 pEntry - pointer to the MAC entry; NULL is not found
1736         ==========================================================================
1737 */
1738 MAC_TABLE_ENTRY *MacTableLookup(
1739         IN PRTMP_ADAPTER pAd,
1740         PUCHAR pAddr)
1741 {
1742         ULONG HashIdx;
1743         MAC_TABLE_ENTRY *pEntry = NULL;
1744
1745         HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1746         pEntry = pAd->MacTab.Hash[HashIdx];
1747
1748         while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
1749         {
1750                 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1751                 {
1752                         break;
1753                 }
1754                 else
1755                         pEntry = pEntry->pNext;
1756         }
1757
1758         return pEntry;
1759 }
1760
1761 MAC_TABLE_ENTRY *MacTableInsertEntry(
1762         IN  PRTMP_ADAPTER   pAd,
1763         IN  PUCHAR                      pAddr,
1764         IN      UCHAR                   apidx,
1765         IN BOOLEAN      CleanAll)
1766 {
1767         UCHAR HashIdx;
1768         int i, FirstWcid;
1769         MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1770
1771         // if FULL, return
1772         if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1773                 return NULL;
1774
1775         FirstWcid = 1;
1776 #ifdef CONFIG_STA_SUPPORT
1777         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1778         if (pAd->StaCfg.BssType == BSS_INFRA)
1779                 FirstWcid = 2;
1780 #endif // CONFIG_STA_SUPPORT //
1781
1782         // allocate one MAC entry
1783         NdisAcquireSpinLock(&pAd->MacTabLock);
1784         for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++)   // skip entry#0 so that "entry index == AID" for fast lookup
1785         {
1786                 // pick up the first available vacancy
1787                 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1788                         (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1789                         (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
1790                         (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1791 #ifdef CONFIG_STA_SUPPORT
1792 #ifdef QOS_DLS_SUPPORT
1793                         && (pAd->MacTab.Content[i].ValidAsDls == FALSE)
1794 #endif // QOS_DLS_SUPPORT //
1795 #endif // CONFIG_STA_SUPPORT //
1796                         )
1797                 {
1798                         pEntry = &pAd->MacTab.Content[i];
1799                         if (CleanAll == TRUE)
1800                         {
1801                                 pEntry->MaxSupportedRate = RATE_11;
1802                                 pEntry->CurrTxRate = RATE_11;
1803                                 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1804                                 pEntry->PairwiseKey.KeyLen = 0;
1805                                 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1806                         }
1807 #ifdef CONFIG_STA_SUPPORT
1808 #ifdef QOS_DLS_SUPPORT
1809                         if (apidx >= MIN_NET_DEVICE_FOR_DLS)
1810                         {
1811                                 pEntry->ValidAsCLI = FALSE;
1812                                 pEntry->ValidAsWDS = FALSE;
1813                                 pEntry->ValidAsApCli = FALSE;
1814                                 pEntry->ValidAsMesh = FALSE;
1815                                 pEntry->ValidAsDls = TRUE;
1816                                 pEntry->isCached = FALSE;
1817                         }
1818                         else
1819 #endif // QOS_DLS_SUPPORT //
1820 #endif // CONFIG_STA_SUPPORT //
1821                         {
1822
1823 #ifdef CONFIG_STA_SUPPORT
1824                                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1825                                 {
1826                                         pEntry->ValidAsCLI = TRUE;
1827                                         pEntry->ValidAsWDS = FALSE;
1828                                         pEntry->ValidAsApCli = FALSE;
1829                                         pEntry->ValidAsMesh = FALSE;
1830                                         pEntry->ValidAsDls = FALSE;
1831                                 }
1832 #endif // CONFIG_STA_SUPPORT //
1833                         }
1834
1835                         pEntry->bIAmBadAtheros = FALSE;
1836                         pEntry->pAd = pAd;
1837                         pEntry->CMTimerRunning = FALSE;
1838                         pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1839                         pEntry->RSNIE_Len = 0;
1840                         NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
1841                         pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1842
1843                         if (pEntry->ValidAsMesh)
1844                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
1845                         else if (pEntry->ValidAsApCli)
1846                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
1847                         else if (pEntry->ValidAsWDS)
1848                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
1849 #ifdef CONFIG_STA_SUPPORT
1850 #ifdef QOS_DLS_SUPPORT
1851                         else if (pEntry->ValidAsDls)
1852                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_DLS);
1853 #endif // QOS_DLS_SUPPORT //
1854 #endif // CONFIG_STA_SUPPORT //
1855                         else
1856                                 pEntry->apidx = apidx;
1857
1858                         {
1859
1860 #ifdef CONFIG_STA_SUPPORT
1861                                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1862                                 {
1863                                         pEntry->AuthMode = pAd->StaCfg.AuthMode;
1864                                         pEntry->WepStatus = pAd->StaCfg.WepStatus;
1865                                         pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1866                                 }
1867 #endif // CONFIG_STA_SUPPORT //
1868                         }
1869
1870                         pEntry->GTKState = REKEY_NEGOTIATING;
1871                         pEntry->PairwiseKey.KeyLen = 0;
1872                         pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1873 #ifdef CONFIG_STA_SUPPORT
1874 #ifdef QOS_DLS_SUPPORT
1875                         if (pEntry->ValidAsDls == TRUE)
1876                                 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1877 #endif //QOS_DLS_SUPPORT
1878 #endif // CONFIG_STA_SUPPORT //
1879                         pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1880                         pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1881                         COPY_MAC_ADDR(pEntry->Addr, pAddr);
1882                         pEntry->Sst = SST_NOT_AUTH;
1883                         pEntry->AuthState = AS_NOT_AUTH;
1884                         pEntry->Aid = (USHORT)i;  //0;
1885                         pEntry->CapabilityInfo = 0;
1886                         pEntry->PsMode = PWR_ACTIVE;
1887                         pEntry->PsQIdleCount = 0;
1888                         pEntry->NoDataIdleCount = 0;
1889                         pEntry->ContinueTxFailCnt = 0;
1890                         InitializeQueueHeader(&pEntry->PsQueue);
1891
1892
1893                         pAd->MacTab.Size ++;
1894                         // Add this entry into ASIC RX WCID search table
1895                         RT28XX_STA_ENTRY_ADD(pAd, pEntry);
1896
1897                         DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
1898                         break;
1899                 }
1900         }
1901
1902         // add this MAC entry into HASH table
1903         if (pEntry)
1904         {
1905                 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1906                 if (pAd->MacTab.Hash[HashIdx] == NULL)
1907                 {
1908                         pAd->MacTab.Hash[HashIdx] = pEntry;
1909                 }
1910                 else
1911                 {
1912                         pCurrEntry = pAd->MacTab.Hash[HashIdx];
1913                         while (pCurrEntry->pNext != NULL)
1914                                 pCurrEntry = pCurrEntry->pNext;
1915                         pCurrEntry->pNext = pEntry;
1916                 }
1917         }
1918
1919         NdisReleaseSpinLock(&pAd->MacTabLock);
1920         return pEntry;
1921 }
1922
1923 /*
1924         ==========================================================================
1925         Description:
1926                 Delete a specified client from MAC table
1927         ==========================================================================
1928  */
1929 BOOLEAN MacTableDeleteEntry(
1930         IN PRTMP_ADAPTER pAd,
1931         IN USHORT wcid,
1932         IN PUCHAR pAddr)
1933 {
1934         USHORT HashIdx;
1935         MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1936         BOOLEAN Cancelled;
1937         //USHORT        offset; // unused variable
1938         //UCHAR j;                      // unused variable
1939
1940         if (wcid >= MAX_LEN_OF_MAC_TABLE)
1941                 return FALSE;
1942
1943         NdisAcquireSpinLock(&pAd->MacTabLock);
1944
1945         HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1946         //pEntry = pAd->MacTab.Hash[HashIdx];
1947         pEntry = &pAd->MacTab.Content[wcid];
1948
1949         if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
1950 #ifdef CONFIG_STA_SUPPORT
1951 #ifdef QOS_DLS_SUPPORT
1952                 || pEntry->ValidAsDls
1953 #endif // QOS_DLS_SUPPORT //
1954 #endif // CONFIG_STA_SUPPORT //
1955                 ))
1956         {
1957                 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1958                 {
1959
1960                         // Delete this entry from ASIC on-chip WCID Table
1961                         RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
1962
1963 #ifdef DOT11_N_SUPPORT
1964                         // free resources of BA
1965                         BASessionTearDownALL(pAd, pEntry->Aid);
1966 #endif // DOT11_N_SUPPORT //
1967
1968
1969                         pPrevEntry = NULL;
1970                         pProbeEntry = pAd->MacTab.Hash[HashIdx];
1971                         ASSERT(pProbeEntry);
1972
1973                         // update Hash list
1974                         do
1975                         {
1976                                 if (pProbeEntry == pEntry)
1977                                 {
1978                                         if (pPrevEntry == NULL)
1979                                         {
1980                                                 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
1981                                         }
1982                                         else
1983                                         {
1984                                                 pPrevEntry->pNext = pEntry->pNext;
1985                                         }
1986                                         break;
1987                                 }
1988
1989                                 pPrevEntry = pProbeEntry;
1990                                 pProbeEntry = pProbeEntry->pNext;
1991                         } while (pProbeEntry);
1992
1993                         // not found !!!
1994                         ASSERT(pProbeEntry != NULL);
1995
1996                         RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1997
1998
1999                 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
2000                 {
2001                         RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
2002                         pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2003                 }
2004
2005
2006                         NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2007                         pAd->MacTab.Size --;
2008                         DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
2009                 }
2010                 else
2011                 {
2012                         printk("\n%s: Impossible Wcid = %d !!!!!\n", __FUNCTION__, wcid);
2013                 }
2014         }
2015
2016         NdisReleaseSpinLock(&pAd->MacTabLock);
2017
2018         //Reset operating mode when no Sta.
2019         if (pAd->MacTab.Size == 0)
2020         {
2021 #ifdef DOT11_N_SUPPORT
2022                 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
2023 #endif // DOT11_N_SUPPORT //
2024                 AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
2025         }
2026
2027         return TRUE;
2028 }
2029
2030
2031 /*
2032         ==========================================================================
2033         Description:
2034                 This routine reset the entire MAC table. All packets pending in
2035                 the power-saving queues are freed here.
2036         ==========================================================================
2037  */
2038 VOID MacTableReset(
2039         IN  PRTMP_ADAPTER  pAd)
2040 {
2041         int         i;
2042
2043         DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
2044         //NdisAcquireSpinLock(&pAd->MacTabLock);
2045
2046         for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
2047         {
2048                 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
2049            {
2050
2051 #ifdef DOT11_N_SUPPORT
2052                         // free resources of BA
2053                         BASessionTearDownALL(pAd, i);
2054 #endif // DOT11_N_SUPPORT //
2055
2056                         pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2057
2058
2059
2060 #ifdef RT2870
2061                         NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
2062                         RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2063 #endif // RT2870 //
2064
2065                         //AsicDelWcidTab(pAd, i);
2066                 }
2067         }
2068
2069         return;
2070 }
2071
2072 /*
2073         ==========================================================================
2074         Description:
2075
2076         IRQL = DISPATCH_LEVEL
2077
2078         ==========================================================================
2079 */
2080 VOID AssocParmFill(
2081         IN PRTMP_ADAPTER pAd,
2082         IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2083         IN PUCHAR                     pAddr,
2084         IN USHORT                     CapabilityInfo,
2085         IN ULONG                      Timeout,
2086         IN USHORT                     ListenIntv)
2087 {
2088         COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2089         // Add mask to support 802.11b mode only
2090         AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2091         AssocReq->Timeout = Timeout;
2092         AssocReq->ListenIntv = ListenIntv;
2093 }
2094
2095
2096 /*
2097         ==========================================================================
2098         Description:
2099
2100         IRQL = DISPATCH_LEVEL
2101
2102         ==========================================================================
2103 */
2104 VOID DisassocParmFill(
2105         IN PRTMP_ADAPTER pAd,
2106         IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2107         IN PUCHAR pAddr,
2108         IN USHORT Reason)
2109 {
2110         COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2111         DisassocReq->Reason = Reason;
2112 }
2113
2114
2115 /*
2116         ========================================================================
2117
2118         Routine Description:
2119                 Check the out going frame, if this is an DHCP or ARP datagram
2120         will be duplicate another frame at low data rate transmit.
2121
2122         Arguments:
2123                 pAd             Pointer to our adapter
2124                 pPacket         Pointer to outgoing Ndis frame
2125
2126         Return Value:
2127                 TRUE            To be duplicate at Low data rate transmit. (1mb)
2128                 FALSE           Do nothing.
2129
2130         IRQL = DISPATCH_LEVEL
2131
2132         Note:
2133
2134                 MAC header + IP Header + UDP Header
2135                   14 Bytes        20 Bytes
2136
2137                 UDP Header
2138                 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2139                                                 Source Port
2140                 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2141                                         Destination Port
2142
2143                 port 0x43 means Bootstrap Protocol, server.
2144                 Port 0x44 means Bootstrap Protocol, client.
2145
2146         ========================================================================
2147 */
2148
2149 BOOLEAN RTMPCheckDHCPFrame(
2150         IN      PRTMP_ADAPTER   pAd,
2151         IN      PNDIS_PACKET    pPacket)
2152 {
2153         PACKET_INFO     PacketInfo;
2154         ULONG                   NumberOfBytesRead = 0;
2155         ULONG                   CurrentOffset = 0;
2156         PVOID                   pVirtualAddress = NULL;
2157         UINT                    NdisBufferLength;
2158         PUCHAR                  pSrc;
2159         USHORT                  Protocol;
2160         UCHAR                   ByteOffset36 = 0;
2161         UCHAR                   ByteOffset38 = 0;
2162         BOOLEAN                 ReadFirstParm = TRUE;
2163
2164         RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2165
2166         NumberOfBytesRead += NdisBufferLength;
2167         pSrc = (PUCHAR) pVirtualAddress;
2168         Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2169
2170         //
2171         // Check DHCP & BOOTP protocol
2172         //
2173         while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2174         {
2175                 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2176                 {
2177                         CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2178                         ByteOffset36 = *(pSrc + CurrentOffset);
2179                         ReadFirstParm = FALSE;
2180                 }
2181
2182                 if (NumberOfBytesRead >= 37)
2183                 {
2184                         CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2185                         ByteOffset38 = *(pSrc + CurrentOffset);
2186                         //End of Read
2187                         break;
2188                 }
2189                 return FALSE;
2190         }
2191
2192         // Check for DHCP & BOOTP protocol
2193         if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2194                 {
2195                 //
2196                 // 2054 (hex 0806) for ARP datagrams
2197                 // if this packet is not ARP datagrams, then do nothing
2198                 // ARP datagrams will also be duplicate at 1mb broadcast frames
2199                 //
2200                 if (Protocol != 0x0806 )
2201                         return FALSE;
2202                 }
2203
2204         return TRUE;
2205 }
2206
2207
2208 BOOLEAN RTMPCheckEtherType(
2209         IN      PRTMP_ADAPTER   pAd,
2210         IN      PNDIS_PACKET    pPacket)
2211 {
2212         USHORT  TypeLen;
2213         UCHAR   Byte0, Byte1;
2214         PUCHAR  pSrcBuf;
2215         UINT32  pktLen;
2216         UINT16  srcPort, dstPort;
2217         BOOLEAN status = TRUE;
2218
2219
2220         pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2221         pktLen = GET_OS_PKT_LEN(pPacket);
2222
2223         ASSERT(pSrcBuf);
2224
2225         RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2226
2227         // get Ethernet protocol field
2228         TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2229
2230         pSrcBuf += LENGTH_802_3;        // Skip the Ethernet Header.
2231
2232         if (TypeLen <= 1500)
2233         {       // 802.3, 802.3 LLC
2234                 /*
2235                         DestMAC(6) + SrcMAC(6) + Lenght(2) +
2236                         DSAP(1) + SSAP(1) + Control(1) +
2237                         if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2238                                 => + SNAP (5, OriginationID(3) + etherType(2))
2239                 */
2240                 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2241                 {
2242                         Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2243                         RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2244                         TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2245                         pSrcBuf += 8; // Skip this LLC/SNAP header
2246                 }
2247                 else
2248                 {
2249                         //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2250                 }
2251         }
2252
2253         // If it's a VLAN packet, get the real Type/Length field.
2254         if (TypeLen == 0x8100)
2255         {
2256                 /* 0x8100 means VLAN packets */
2257
2258                 /* Dest. MAC Address (6-bytes) +
2259                    Source MAC Address (6-bytes) +
2260                    Length/Type = 802.1Q Tag Type (2-byte) +
2261                    Tag Control Information (2-bytes) +
2262                    Length / Type (2-bytes) +
2263                    data payload (0-n bytes) +
2264                    Pad (0-p bytes) +
2265                    Frame Check Sequence (4-bytes) */
2266
2267                 RTMP_SET_PACKET_VLAN(pPacket, 1);
2268                 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2269                 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2270
2271                 pSrcBuf += 4; // Skip the VLAN Header.
2272         }
2273
2274         switch (TypeLen)
2275         {
2276                 case 0x0800:
2277                         {
2278                                 ASSERT((pktLen > 34));
2279                                 if (*(pSrcBuf + 9) == 0x11)
2280                                 {       // udp packet
2281                                         ASSERT((pktLen > 34));  // 14 for ethernet header, 20 for IP header
2282
2283                                         pSrcBuf += 20;  // Skip the IP header
2284                                         srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2285                                         dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2286
2287                                         if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2288                                         {       //It's a BOOTP/DHCP packet
2289                                                 RTMP_SET_PACKET_DHCP(pPacket, 1);
2290                                         }
2291                                 }
2292                         }
2293                         break;
2294                 case 0x0806:
2295                         {
2296                                 //ARP Packet.
2297                                 RTMP_SET_PACKET_DHCP(pPacket, 1);
2298                         }
2299                         break;
2300                 case 0x888e:
2301                         {
2302                                 // EAPOL Packet.
2303                                 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2304                         }
2305                         break;
2306                 default:
2307                         status = FALSE;
2308                         break;
2309         }
2310
2311         return status;
2312
2313 }
2314
2315
2316
2317 VOID Update_Rssi_Sample(
2318         IN PRTMP_ADAPTER        pAd,
2319         IN RSSI_SAMPLE          *pRssi,
2320         IN PRXWI_STRUC          pRxWI)
2321                 {
2322         CHAR    rssi0 = pRxWI->RSSI0;
2323         CHAR    rssi1 = pRxWI->RSSI1;
2324         CHAR    rssi2 = pRxWI->RSSI2;
2325
2326         if (rssi0 != 0)
2327         {
2328                 pRssi->LastRssi0        = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2329                 pRssi->AvgRssi0X8       = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2330                 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2331         }
2332
2333         if (rssi1 != 0)
2334         {
2335                 pRssi->LastRssi1        = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2336                 pRssi->AvgRssi1X8       = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2337                 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2338         }
2339
2340         if (rssi2 != 0)
2341         {
2342                 pRssi->LastRssi2        = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2343                 pRssi->AvgRssi2X8  = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2344                 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2345         }
2346 }
2347
2348
2349
2350 // Normal legacy Rx packet indication
2351 VOID Indicate_Legacy_Packet(
2352         IN      PRTMP_ADAPTER   pAd,
2353         IN      RX_BLK                  *pRxBlk,
2354         IN      UCHAR                   FromWhichBSSID)
2355 {
2356         PNDIS_PACKET    pRxPacket = pRxBlk->pRxPacket;
2357         UCHAR                   Header802_3[LENGTH_802_3];
2358
2359         // 1. get 802.3 Header
2360         // 2. remove LLC
2361         //              a. pointer pRxBlk->pData to payload
2362         //      b. modify pRxBlk->DataSize
2363 #ifdef CONFIG_STA_SUPPORT
2364         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2365                 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2366 #endif // CONFIG_STA_SUPPORT //
2367
2368         if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2369         {
2370 #if 0 // sample take off, for multiple card design
2371                 static int err_size;
2372
2373                 err_size++;
2374                 if (err_size > 20)
2375                 {
2376                          printk("Legacy DataSize = %d\n", pRxBlk->DataSize);
2377                          hex_dump("802.3 Header", Header802_3, LENGTH_802_3);
2378                          hex_dump("Payload", pRxBlk->pData, 64);
2379                          err_size = 0;
2380                 }
2381 #endif
2382
2383                 // release packet
2384                 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2385                 return;
2386         }
2387
2388
2389         STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2390
2391 #ifdef RT2870
2392 #ifdef DOT11_N_SUPPORT
2393         if (pAd->CommonCfg.bDisableReordering == 0)
2394         {
2395                 PBA_REC_ENTRY           pBAEntry;
2396                 ULONG                           Now32;
2397                 UCHAR                           Wcid = pRxBlk->pRxWI->WirelessCliID;
2398                 UCHAR                           TID = pRxBlk->pRxWI->TID;
2399                 USHORT                          Idx;
2400
2401 #define REORDERING_PACKET_TIMEOUT               ((100 * HZ)/1000)       // system ticks -- 100 ms
2402
2403                 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2404                 {
2405                         Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2406                         if (Idx != 0)
2407                         {
2408                                 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2409                                 // update last rx time
2410                                 NdisGetSystemUpTime(&Now32);
2411                                 if ((pBAEntry->list.qlen > 0) &&
2412                                          RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2413                                         )
2414                                 {
2415                                         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);
2416                                         hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2417                                         ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2418                                 }
2419                         }
2420                 }
2421         }
2422 #endif // DOT11_N_SUPPORT //
2423 #endif // RT2870 //
2424
2425         wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2426
2427         //
2428         // pass this 802.3 packet to upper layer or forward this packet to WM directly
2429         //
2430 #ifdef CONFIG_STA_SUPPORT
2431         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2432                 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2433 #endif // CONFIG_STA_SUPPORT //
2434
2435 }
2436
2437
2438 // Normal, AMPDU or AMSDU
2439 VOID CmmRxnonRalinkFrameIndicate(
2440         IN      PRTMP_ADAPTER   pAd,
2441         IN      RX_BLK                  *pRxBlk,
2442         IN      UCHAR                   FromWhichBSSID)
2443 {
2444 #ifdef DOT11_N_SUPPORT
2445         if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2446         {
2447                 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2448         }
2449         else
2450 #endif // DOT11_N_SUPPORT //
2451         {
2452 #ifdef DOT11_N_SUPPORT
2453                 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2454                 {
2455                         // handle A-MSDU
2456                         Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2457                 }
2458                 else
2459 #endif // DOT11_N_SUPPORT //
2460                 {
2461                         Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2462                 }
2463         }
2464 }
2465
2466
2467 VOID CmmRxRalinkFrameIndicate(
2468         IN      PRTMP_ADAPTER   pAd,
2469         IN      MAC_TABLE_ENTRY *pEntry,
2470         IN      RX_BLK                  *pRxBlk,
2471         IN      UCHAR                   FromWhichBSSID)
2472 {
2473         UCHAR                   Header802_3[LENGTH_802_3];
2474         UINT16                  Msdu2Size;
2475         UINT16                  Payload1Size, Payload2Size;
2476         PUCHAR                  pData2;
2477         PNDIS_PACKET    pPacket2 = NULL;
2478
2479
2480
2481         Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2482
2483         if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2484         {
2485                 /* skip two byte MSDU2 len */
2486                 pRxBlk->pData += 2;
2487                 pRxBlk->DataSize -= 2;
2488         }
2489         else
2490         {
2491                 // release packet
2492                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2493                 return;
2494         }
2495
2496         // get 802.3 Header and  remove LLC
2497 #ifdef CONFIG_STA_SUPPORT
2498         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2499                 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2500 #endif // CONFIG_STA_SUPPORT //
2501
2502
2503         ASSERT(pRxBlk->pRxPacket);
2504
2505         // Ralink Aggregation frame
2506         pAd->RalinkCounters.OneSecRxAggregationCount ++;
2507         Payload1Size = pRxBlk->DataSize - Msdu2Size;
2508         Payload2Size = Msdu2Size - LENGTH_802_3;
2509
2510         pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2511 #ifdef CONFIG_STA_SUPPORT
2512         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2513                 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2514 #endif // CONFIG_STA_SUPPORT //
2515
2516         if (!pPacket2)
2517         {
2518                 // release packet
2519                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2520                 return;
2521         }
2522
2523         // update payload size of 1st packet
2524         pRxBlk->DataSize = Payload1Size;
2525         wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2526
2527 #ifdef CONFIG_STA_SUPPORT
2528         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2529                 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2530 #endif // CONFIG_STA_SUPPORT //
2531
2532         if (pPacket2)
2533         {
2534 #ifdef CONFIG_STA_SUPPORT
2535                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2536                         ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2537 #endif // CONFIG_STA_SUPPORT //
2538         }
2539 }
2540
2541
2542 #define RESET_FRAGFRAME(_fragFrame) \
2543         {                                                               \
2544                 _fragFrame.RxSize = 0;          \
2545                 _fragFrame.Sequence = 0;        \
2546                 _fragFrame.LastFrag = 0;        \
2547                 _fragFrame.Flags = 0;           \
2548         }
2549
2550
2551 PNDIS_PACKET RTMPDeFragmentDataFrame(
2552         IN      PRTMP_ADAPTER   pAd,
2553         IN      RX_BLK                  *pRxBlk)
2554 {
2555         PHEADER_802_11  pHeader = pRxBlk->pHeader;
2556         PNDIS_PACKET    pRxPacket = pRxBlk->pRxPacket;
2557         UCHAR                   *pData = pRxBlk->pData;
2558         USHORT                  DataSize = pRxBlk->DataSize;
2559         PNDIS_PACKET    pRetPacket = NULL;
2560         UCHAR                   *pFragBuffer = NULL;
2561         BOOLEAN                 bReassDone = FALSE;
2562         UCHAR                   HeaderRoom = 0;
2563
2564
2565         ASSERT(pHeader);
2566
2567         HeaderRoom = pData - (UCHAR *)pHeader;
2568
2569         // Re-assemble the fragmented packets
2570         if (pHeader->Frag == 0)         // Frag. Number is 0 : First frag or only one pkt
2571         {
2572                 // the first pkt of fragment, record it.
2573                 if (pHeader->FC.MoreFrag)
2574                 {
2575                         ASSERT(pAd->FragFrame.pFragPacket);
2576                         pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2577                         pAd->FragFrame.RxSize   = DataSize + HeaderRoom;
2578                         NdisMoveMemory(pFragBuffer,      pHeader, pAd->FragFrame.RxSize);
2579                         pAd->FragFrame.Sequence = pHeader->Sequence;
2580                         pAd->FragFrame.LastFrag = pHeader->Frag;           // Should be 0
2581                         ASSERT(pAd->FragFrame.LastFrag == 0);
2582                         goto done;      // end of processing this frame
2583                 }
2584         }
2585         else    //Middle & End of fragment
2586         {
2587                 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2588                         (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2589                 {
2590                         // Fragment is not the same sequence or out of fragment number order
2591                         // Reset Fragment control blk
2592                         RESET_FRAGFRAME(pAd->FragFrame);
2593                         DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2594                         goto done; // give up this frame
2595                 }
2596                 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2597                 {
2598                         // Fragment frame is too large, it exeeds the maximum frame size.
2599                         // Reset Fragment control blk
2600                         RESET_FRAGFRAME(pAd->FragFrame);
2601                         DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2602                         goto done; // give up this frame
2603                 }
2604
2605         //
2606                 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2607                 // In this case, we will dropt it.
2608                 //
2609                 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2610                 {
2611                         DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2612                         goto done; // give up this frame
2613                 }
2614
2615                 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2616
2617                 // concatenate this fragment into the re-assembly buffer
2618                 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2619                 pAd->FragFrame.RxSize  += DataSize;
2620                 pAd->FragFrame.LastFrag = pHeader->Frag;           // Update fragment number
2621
2622                 // Last fragment
2623                 if (pHeader->FC.MoreFrag == FALSE)
2624                 {
2625                         bReassDone = TRUE;
2626                 }
2627         }
2628
2629 done:
2630         // always release rx fragmented packet
2631         RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2632
2633         // return defragmented packet if packet is reassembled completely
2634         // otherwise return NULL
2635         if (bReassDone)
2636         {
2637                 PNDIS_PACKET pNewFragPacket;
2638
2639                 // allocate a new packet buffer for fragment
2640                 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2641                 if (pNewFragPacket)
2642                 {
2643                         // update RxBlk
2644                         pRetPacket = pAd->FragFrame.pFragPacket;
2645                         pAd->FragFrame.pFragPacket = pNewFragPacket;
2646                         pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2647                         pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2648                         pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2649                         pRxBlk->pRxPacket = pRetPacket;
2650                 }
2651                 else
2652                 {
2653                         RESET_FRAGFRAME(pAd->FragFrame);
2654                 }
2655         }
2656
2657         return pRetPacket;
2658 }
2659
2660
2661 VOID Indicate_AMSDU_Packet(
2662         IN      PRTMP_ADAPTER   pAd,
2663         IN      RX_BLK                  *pRxBlk,
2664         IN      UCHAR                   FromWhichBSSID)
2665 {
2666         UINT                    nMSDU;
2667
2668         update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2669         RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2670         nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2671 }
2672
2673 VOID Indicate_EAPOL_Packet(
2674         IN      PRTMP_ADAPTER   pAd,
2675         IN      RX_BLK                  *pRxBlk,
2676         IN      UCHAR                   FromWhichBSSID)
2677 {
2678         MAC_TABLE_ENTRY *pEntry = NULL;
2679
2680
2681 #ifdef CONFIG_STA_SUPPORT
2682         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2683         {
2684                 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2685                 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2686                 return;
2687         }
2688 #endif // CONFIG_STA_SUPPORT //
2689
2690         if (pEntry == NULL)
2691         {
2692                 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2693                 // release packet
2694                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2695                 return;
2696         }
2697 }
2698
2699 #define BCN_TBTT_OFFSET         64      //defer 64 us
2700 VOID ReSyncBeaconTime(
2701         IN  PRTMP_ADAPTER   pAd)
2702 {
2703
2704         UINT32  Offset;
2705
2706
2707         Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2708
2709         pAd->TbttTickCount++;
2710
2711         //
2712         // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2713         // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2714         //
2715         if (Offset == (BCN_TBTT_OFFSET-2))
2716         {
2717                 BCN_TIME_CFG_STRUC csr;
2718                 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2719                 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ;     // ASIC register in units of 1/16 TU = 64us
2720                 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2721         }
2722         else
2723         {
2724                 if (Offset == (BCN_TBTT_OFFSET-1))
2725                 {
2726                         BCN_TIME_CFG_STRUC csr;
2727
2728                         RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2729                         csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
2730                         RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2731                 }
2732         }
2733 }
2734