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