Staging: rt3070: remove dead QOS_DLS_SUPPORT 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 #ifdef DOT11N_DRAFT3
1178         if (pTxWI->BW)
1179                 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1180 #endif // DOT11N_DRAFT3 //
1181
1182         pTxWI->MCS = pTransmit->field.MCS;
1183         pTxWI->PHYMODE = pTransmit->field.MODE;
1184         pTxWI->CFACK = CfAck;
1185
1186 #ifdef DOT11_N_SUPPORT
1187         if (pMac)
1188         {
1189                 if (pAd->CommonCfg.bMIMOPSEnable)
1190                 {
1191                         if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1192                         {
1193                                 // Dynamic MIMO Power Save Mode
1194                                 pTxWI->MIMOps = 1;
1195                         }
1196                         else if (pMac->MmpsMode == MMPS_STATIC)
1197                         {
1198                                 // Static MIMO Power Save Mode
1199                                 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1200                                 {
1201                                         pTxWI->MCS = 7;
1202                                         pTxWI->MIMOps = 0;
1203                                 }
1204                         }
1205                 }
1206                 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1207                 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1208                 {
1209                         pTxWI->MpduDensity = 7;
1210                 }
1211                 else
1212                 {
1213                         pTxWI->MpduDensity = pMac->MpduDensity;
1214                 }
1215         }
1216 #endif // DOT11_N_SUPPORT //
1217
1218         pTxWI->PacketId = pTxWI->MCS;
1219         NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1220 }
1221
1222
1223 VOID RTMPWriteTxWI_Data(
1224         IN      PRTMP_ADAPTER           pAd,
1225         IN      OUT PTXWI_STRUC         pTxWI,
1226         IN      TX_BLK                          *pTxBlk)
1227 {
1228         HTTRANSMIT_SETTING      *pTransmit;
1229         PMAC_TABLE_ENTRY        pMacEntry;
1230 #ifdef DOT11_N_SUPPORT
1231         UCHAR                           BASize;
1232 #endif // DOT11_N_SUPPORT //
1233
1234
1235         ASSERT(pTxWI);
1236
1237         pTransmit = pTxBlk->pTransmit;
1238         pMacEntry = pTxBlk->pMacEntry;
1239
1240
1241         //
1242         // Always use Long preamble before verifiation short preamble functionality works well.
1243         // Todo: remove the following line if short preamble functionality works
1244         //
1245         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1246         NdisZeroMemory(pTxWI, TXWI_SIZE);
1247
1248         pTxWI->FRAG             = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1249         pTxWI->ACK              = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1250         pTxWI->txop             = pTxBlk->FrameGap;
1251
1252                 pTxWI->WirelessCliID            = pTxBlk->Wcid;
1253
1254         pTxWI->MPDUtotalByteCount       = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1255         pTxWI->CFACK                            = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1256
1257         // If CCK or OFDM, BW must be 20
1258         pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1259 #ifdef DOT11_N_SUPPORT
1260 #ifdef DOT11N_DRAFT3
1261         if (pTxWI->BW)
1262                 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1263 #endif // DOT11N_DRAFT3 //
1264         pTxWI->AMPDU    = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1265
1266         // John tune the performace with Intel Client in 20 MHz performance
1267         BASize = pAd->CommonCfg.TxBASize;
1268         if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1269         {
1270                 UCHAR           RABAOriIdx = 0; //The RA's BA Originator table index.
1271
1272                 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1273                 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1274         }
1275
1276         pTxWI->TxBF = pTransmit->field.TxBF;
1277         pTxWI->BAWinSize = BASize;
1278         pTxWI->ShortGI = pTransmit->field.ShortGI;
1279         pTxWI->STBC = pTransmit->field.STBC;
1280 #endif // DOT11_N_SUPPORT //
1281
1282         pTxWI->MCS = pTransmit->field.MCS;
1283         pTxWI->PHYMODE = pTransmit->field.MODE;
1284
1285 #ifdef DOT11_N_SUPPORT
1286         if (pMacEntry)
1287         {
1288                 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1289                 {
1290                         // Dynamic MIMO Power Save Mode
1291                         pTxWI->MIMOps = 1;
1292                 }
1293                 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1294                 {
1295                         // Static MIMO Power Save Mode
1296                         if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1297                         {
1298                                 pTxWI->MCS = 7;
1299                                 pTxWI->MIMOps = 0;
1300                         }
1301                 }
1302
1303                 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1304                 {
1305                         pTxWI->MpduDensity = 7;
1306                 }
1307                 else
1308                 {
1309                         pTxWI->MpduDensity = pMacEntry->MpduDensity;
1310                 }
1311         }
1312 #endif // DOT11_N_SUPPORT //
1313
1314 #ifdef DBG_DIAGNOSE
1315                 if (pTxBlk->QueIdx== 0)
1316                 {
1317                         pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1318                         pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1319                 }
1320 #endif // DBG_DIAGNOSE //
1321
1322         // for rate adapation
1323         pTxWI->PacketId = pTxWI->MCS;
1324 #ifdef INF_AMAZON_SE
1325 /*Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */
1326         if( RTMP_GET_PACKET_NOBULKOUT(pTxBlk->pPacket))
1327         {
1328                 if(pTxWI->PHYMODE == MODE_CCK)
1329                 {
1330                         pTxWI->PacketId = 6;
1331                 }
1332         }
1333 #endif // INF_AMAZON_SE //
1334 }
1335
1336
1337 VOID RTMPWriteTxWI_Cache(
1338         IN      PRTMP_ADAPTER           pAd,
1339         IN      OUT PTXWI_STRUC         pTxWI,
1340         IN      TX_BLK                          *pTxBlk)
1341 {
1342         PHTTRANSMIT_SETTING     /*pTxHTPhyMode,*/ pTransmit;
1343         PMAC_TABLE_ENTRY        pMacEntry;
1344
1345         //
1346         // update TXWI
1347         //
1348         pMacEntry = pTxBlk->pMacEntry;
1349         pTransmit = pTxBlk->pTransmit;
1350
1351         //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1352         //if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry))
1353         //if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch))
1354         if (pMacEntry->bAutoTxRateSwitch)
1355         {
1356                 pTxWI->txop = IFS_HTTXOP;
1357
1358                 // If CCK or OFDM, BW must be 20
1359                 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1360                 pTxWI->ShortGI = pTransmit->field.ShortGI;
1361                 pTxWI->STBC = pTransmit->field.STBC;
1362
1363                 pTxWI->MCS = pTransmit->field.MCS;
1364                 pTxWI->PHYMODE = pTransmit->field.MODE;
1365
1366                 // set PID for TxRateSwitching
1367                 pTxWI->PacketId = pTransmit->field.MCS;
1368         }
1369
1370 #ifdef DOT11_N_SUPPORT
1371         pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1372         pTxWI->MIMOps = 0;
1373
1374 #ifdef DOT11N_DRAFT3
1375         if (pTxWI->BW)
1376                 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1377 #endif // DOT11N_DRAFT3 //
1378
1379         if (pAd->CommonCfg.bMIMOPSEnable)
1380         {
1381                 // MIMO Power Save Mode
1382                 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1383                 {
1384                         // Dynamic MIMO Power Save Mode
1385                         pTxWI->MIMOps = 1;
1386                 }
1387                 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1388                 {
1389                         // Static MIMO Power Save Mode
1390                         if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1391                         {
1392                                 pTxWI->MCS = 7;
1393                                 pTxWI->MIMOps = 0;
1394                         }
1395                 }
1396         }
1397 #endif // DOT11_N_SUPPORT //
1398
1399 #ifdef DBG_DIAGNOSE
1400         if (pTxBlk->QueIdx== 0)
1401         {
1402                 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1403                 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1404         }
1405 #endif // DBG_DIAGNOSE //
1406
1407         pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1408
1409 }
1410
1411
1412 /*
1413         ========================================================================
1414
1415         Routine Description:
1416                 Calculates the duration which is required to transmit out frames
1417         with given size and specified rate.
1418
1419         Arguments:
1420                 pTxD            Pointer to transmit descriptor
1421                 Ack             Setting for Ack requirement bit
1422                 Fragment        Setting for Fragment bit
1423                 RetryMode       Setting for retry mode
1424                 Ifs             Setting for IFS gap
1425                 Rate            Setting for transmit rate
1426                 Service         Setting for service
1427                 Length          Frame length
1428                 TxPreamble      Short or Long preamble when using CCK rates
1429                 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1430
1431         Return Value:
1432                 None
1433
1434         IRQL = PASSIVE_LEVEL
1435         IRQL = DISPATCH_LEVEL
1436
1437         ========================================================================
1438 */
1439 VOID RTMPWriteTxDescriptor(
1440         IN      PRTMP_ADAPTER   pAd,
1441         IN      PTXD_STRUC              pTxD,
1442         IN      BOOLEAN                 bWIV,
1443         IN      UCHAR                   QueueSEL)
1444 {
1445         //
1446         // Always use Long preamble before verifiation short preamble functionality works well.
1447         // Todo: remove the following line if short preamble functionality works
1448         //
1449         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1450
1451         pTxD->WIV       = (bWIV) ? 1: 0;
1452         pTxD->QSEL= (QueueSEL);
1453         if (pAd->bGenOneHCCA == TRUE)
1454                 pTxD->QSEL= FIFO_HCCA;
1455         pTxD->DMADONE = 0;
1456 }
1457
1458
1459 // should be called only when -
1460 // 1. MEADIA_CONNECTED
1461 // 2. AGGREGATION_IN_USED
1462 // 3. Fragmentation not in used
1463 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1464 BOOLEAN TxFrameIsAggregatible(
1465         IN      PRTMP_ADAPTER   pAd,
1466         IN      PUCHAR                  pPrevAddr1,
1467         IN      PUCHAR                  p8023hdr)
1468 {
1469
1470         // can't aggregate EAPOL (802.1x) frame
1471         if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1472                 return FALSE;
1473
1474         // can't aggregate multicast/broadcast frame
1475         if (p8023hdr[0] & 0x01)
1476                 return FALSE;
1477
1478         if (INFRA_ON(pAd)) // must be unicast to AP
1479                 return TRUE;
1480         else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1481                 return TRUE;
1482         else
1483                 return FALSE;
1484 }
1485
1486
1487 /*
1488         ========================================================================
1489
1490         Routine Description:
1491            Check the MSDU Aggregation policy
1492         1.HT aggregation is A-MSDU
1493         2.legaacy rate aggregation is software aggregation by Ralink.
1494
1495         Arguments:
1496
1497         Return Value:
1498
1499         Note:
1500
1501         ========================================================================
1502 */
1503 BOOLEAN PeerIsAggreOn(
1504         IN      PRTMP_ADAPTER   pAd,
1505         IN      ULONG              TxRate,
1506         IN      PMAC_TABLE_ENTRY pMacEntry)
1507 {
1508         ULONG   AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1509
1510         if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1511         {
1512 #ifdef DOT11_N_SUPPORT
1513                 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1514                 {
1515                         return TRUE;
1516                 }
1517 #endif // DOT11_N_SUPPORT //
1518
1519 #ifdef AGGREGATION_SUPPORT
1520                 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1521                 {       // legacy  Ralink Aggregation support
1522                         return TRUE;
1523                 }
1524 #endif // AGGREGATION_SUPPORT //
1525         }
1526
1527         return FALSE;
1528
1529 }
1530
1531
1532 /*
1533         ========================================================================
1534
1535         Routine Description:
1536                 Check and fine the packet waiting in SW queue with highest priority
1537
1538         Arguments:
1539                 pAd Pointer to our adapter
1540
1541         Return Value:
1542                 pQueue          Pointer to Waiting Queue
1543
1544         IRQL = DISPATCH_LEVEL
1545
1546         Note:
1547
1548         ========================================================================
1549 */
1550 PQUEUE_HEADER   RTMPCheckTxSwQueue(
1551         IN      PRTMP_ADAPTER   pAd,
1552         OUT PUCHAR                      pQueIdx)
1553 {
1554
1555         ULONG   Number;
1556         // 2004-11-15 to be removed. test aggregation only
1557 //      if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2))
1558 //               return NULL;
1559
1560         Number = pAd->TxSwQueue[QID_AC_BK].Number
1561                          + pAd->TxSwQueue[QID_AC_BE].Number
1562                          + pAd->TxSwQueue[QID_AC_VI].Number
1563                          + pAd->TxSwQueue[QID_AC_VO].Number
1564                          + pAd->TxSwQueue[QID_HCCA].Number;
1565
1566         if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1567         {
1568                 *pQueIdx = QID_AC_VO;
1569                 return (&pAd->TxSwQueue[QID_AC_VO]);
1570         }
1571         else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1572         {
1573                 *pQueIdx = QID_AC_VI;
1574                 return (&pAd->TxSwQueue[QID_AC_VI]);
1575         }
1576         else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1577         {
1578                 *pQueIdx = QID_AC_BE;
1579                 return (&pAd->TxSwQueue[QID_AC_BE]);
1580         }
1581         else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1582         {
1583                 *pQueIdx = QID_AC_BK;
1584                 return (&pAd->TxSwQueue[QID_AC_BK]);
1585         }
1586         else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1587         {
1588                 *pQueIdx = QID_HCCA;
1589                 return (&pAd->TxSwQueue[QID_HCCA]);
1590         }
1591
1592         // No packet pending in Tx Sw queue
1593         *pQueIdx = QID_AC_BK;
1594
1595         return (NULL);
1596 }
1597
1598
1599
1600 /*
1601         ========================================================================
1602
1603         Routine Description:
1604                 Suspend MSDU transmission
1605
1606         Arguments:
1607                 pAd     Pointer to our adapter
1608
1609         Return Value:
1610                 None
1611
1612         Note:
1613
1614         ========================================================================
1615 */
1616 VOID    RTMPSuspendMsduTransmission(
1617         IN      PRTMP_ADAPTER   pAd)
1618 {
1619         DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1620
1621
1622         //
1623         // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1624         // use Lowbound as R66 value on ScanNextChannel(...)
1625         //
1626         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1627
1628         // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1629         //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
1630         RTMPSetAGCInitValue(pAd, BW_20);
1631
1632         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1633         //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000);                // abort all TX rings
1634 }
1635
1636
1637 /*
1638         ========================================================================
1639
1640         Routine Description:
1641                 Resume MSDU transmission
1642
1643         Arguments:
1644                 pAd     Pointer to our adapter
1645
1646         Return Value:
1647                 None
1648
1649         IRQL = DISPATCH_LEVEL
1650
1651         Note:
1652
1653         ========================================================================
1654 */
1655 VOID RTMPResumeMsduTransmission(
1656         IN      PRTMP_ADAPTER   pAd)
1657 {
1658 //    UCHAR                     IrqState;
1659
1660         DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1661
1662
1663         // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value
1664         // R66 should not be 0
1665         if (pAd->BbpTuning.R66CurrentValue == 0)
1666         {
1667                 pAd->BbpTuning.R66CurrentValue = 0x38;
1668                 DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
1669         }
1670         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1671
1672         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1673 // sample, for IRQ LOCK to SEM LOCK
1674 //    IrqState = pAd->irq_disabled;
1675 //      if (IrqState)
1676 //              RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1677 //    else
1678         RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1679 }
1680
1681
1682 UINT deaggregate_AMSDU_announce(
1683         IN      PRTMP_ADAPTER   pAd,
1684         PNDIS_PACKET            pPacket,
1685         IN      PUCHAR                  pData,
1686         IN      ULONG                   DataSize)
1687 {
1688         USHORT                  PayloadSize;
1689         USHORT                  SubFrameSize;
1690         PHEADER_802_3   pAMSDUsubheader;
1691         UINT                    nMSDU;
1692     UCHAR                       Header802_3[14];
1693
1694         PUCHAR                  pPayload, pDA, pSA, pRemovedLLCSNAP;
1695         PNDIS_PACKET    pClonePacket;
1696
1697
1698
1699         nMSDU = 0;
1700
1701         while (DataSize > LENGTH_802_3)
1702         {
1703
1704                 nMSDU++;
1705
1706                 //hex_dump("subheader", pData, 64);
1707                 pAMSDUsubheader = (PHEADER_802_3)pData;
1708                 //pData += LENGTH_802_3;
1709                 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1710                 SubFrameSize = PayloadSize + LENGTH_802_3;
1711
1712
1713                 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
1714                 {
1715                         break;
1716                 }
1717
1718                 //printk("%d subframe: Size = %d\n",  nMSDU, PayloadSize);
1719
1720                 pPayload = pData + LENGTH_802_3;
1721                 pDA = pData;
1722                 pSA = pData + MAC_ADDR_LEN;
1723
1724                 // convert to 802.3 header
1725         CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
1726
1727 #ifdef CONFIG_STA_SUPPORT
1728                 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
1729                 {
1730                     // avoid local heap overflow, use dyanamic allocation
1731                    MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1732                    memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
1733                    Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
1734                    WpaEAPOLKeyAction(pAd, Elem);
1735                    kfree(Elem);
1736                 }
1737 #endif // CONFIG_STA_SUPPORT //
1738
1739 #ifdef CONFIG_STA_SUPPORT
1740                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1741                 {
1742                         if (pRemovedLLCSNAP)
1743                         {
1744                                 pPayload -= LENGTH_802_3;
1745                                 PayloadSize += LENGTH_802_3;
1746                                 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
1747                         }
1748                 }
1749 #endif // CONFIG_STA_SUPPORT //
1750
1751                 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1752                 if (pClonePacket)
1753                 {
1754 #ifdef CONFIG_STA_SUPPORT
1755                         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1756                                 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
1757 #endif // CONFIG_STA_SUPPORT //
1758                 }
1759
1760
1761                 // A-MSDU has padding to multiple of 4 including subframe header.
1762                 // align SubFrameSize up to multiple of 4
1763                 SubFrameSize = (SubFrameSize+3)&(~0x3);
1764
1765
1766                 if (SubFrameSize > 1528 || SubFrameSize < 32)
1767                 {
1768                         break;
1769                 }
1770
1771                 if (DataSize > SubFrameSize)
1772                 {
1773                         pData += SubFrameSize;
1774                         DataSize -= SubFrameSize;
1775                 }
1776                 else
1777                 {
1778                         // end of A-MSDU
1779                         DataSize = 0;
1780                 }
1781         }
1782
1783         // finally release original rx packet
1784         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1785
1786         return nMSDU;
1787 }
1788
1789
1790 UINT BA_Reorder_AMSDU_Annnounce(
1791         IN      PRTMP_ADAPTER   pAd,
1792         IN      PNDIS_PACKET    pPacket)
1793 {
1794         PUCHAR                  pData;
1795         USHORT                  DataSize;
1796         UINT                    nMSDU = 0;
1797
1798         pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1799         DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1800
1801         nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1802
1803         return nMSDU;
1804 }
1805
1806
1807 /*
1808         ==========================================================================
1809         Description:
1810                 Look up the MAC address in the MAC table. Return NULL if not found.
1811         Return:
1812                 pEntry - pointer to the MAC entry; NULL is not found
1813         ==========================================================================
1814 */
1815 MAC_TABLE_ENTRY *MacTableLookup(
1816         IN PRTMP_ADAPTER pAd,
1817         PUCHAR pAddr)
1818 {
1819         ULONG HashIdx;
1820         MAC_TABLE_ENTRY *pEntry = NULL;
1821
1822         HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1823         pEntry = pAd->MacTab.Hash[HashIdx];
1824
1825         while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
1826         {
1827                 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1828                 {
1829                         break;
1830                 }
1831                 else
1832                         pEntry = pEntry->pNext;
1833         }
1834
1835         return pEntry;
1836 }
1837
1838 MAC_TABLE_ENTRY *MacTableInsertEntry(
1839         IN  PRTMP_ADAPTER   pAd,
1840         IN  PUCHAR                      pAddr,
1841         IN      UCHAR                   apidx,
1842         IN BOOLEAN      CleanAll)
1843 {
1844         UCHAR HashIdx;
1845         int i, FirstWcid;
1846         MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1847 //      USHORT  offset;
1848 //      ULONG   addr;
1849
1850         // if FULL, return
1851         if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1852                 return NULL;
1853
1854         FirstWcid = 1;
1855 #ifdef CONFIG_STA_SUPPORT
1856         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1857         if (pAd->StaCfg.BssType == BSS_INFRA)
1858                 FirstWcid = 2;
1859 #endif // CONFIG_STA_SUPPORT //
1860
1861         // allocate one MAC entry
1862         NdisAcquireSpinLock(&pAd->MacTabLock);
1863         for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++)   // skip entry#0 so that "entry index == AID" for fast lookup
1864         {
1865                 // pick up the first available vacancy
1866                 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1867                         (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1868                         (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
1869                         (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1870                         )
1871                 {
1872                         pEntry = &pAd->MacTab.Content[i];
1873                         if (CleanAll == TRUE)
1874                         {
1875                                 pEntry->MaxSupportedRate = RATE_11;
1876                                 pEntry->CurrTxRate = RATE_11;
1877                                 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1878                                 pEntry->PairwiseKey.KeyLen = 0;
1879                                 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1880                         }
1881                         {
1882
1883 #ifdef CONFIG_STA_SUPPORT
1884                                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1885                                 {
1886                                         pEntry->ValidAsCLI = TRUE;
1887                                         pEntry->ValidAsWDS = FALSE;
1888                                         pEntry->ValidAsApCli = FALSE;
1889                                         pEntry->ValidAsMesh = FALSE;
1890                                         pEntry->ValidAsDls = FALSE;
1891                                 }
1892 #endif // CONFIG_STA_SUPPORT //
1893                         }
1894
1895                         pEntry->bIAmBadAtheros = FALSE;
1896                         pEntry->pAd = pAd;
1897                         pEntry->CMTimerRunning = FALSE;
1898                         pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1899                         pEntry->RSNIE_Len = 0;
1900                         NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
1901                         pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1902
1903                         if (pEntry->ValidAsMesh)
1904                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
1905                         else if (pEntry->ValidAsApCli)
1906                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
1907                         else if (pEntry->ValidAsWDS)
1908                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
1909                         else
1910                                 pEntry->apidx = apidx;
1911
1912                         {
1913
1914 #ifdef CONFIG_STA_SUPPORT
1915                                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1916                                 {
1917                                         pEntry->AuthMode = pAd->StaCfg.AuthMode;
1918                                         pEntry->WepStatus = pAd->StaCfg.WepStatus;
1919                                         pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1920                                 }
1921 #endif // CONFIG_STA_SUPPORT //
1922                         }
1923
1924                         pEntry->GTKState = REKEY_NEGOTIATING;
1925                         pEntry->PairwiseKey.KeyLen = 0;
1926                         pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1927                         pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1928                         pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1929                         COPY_MAC_ADDR(pEntry->Addr, pAddr);
1930                         pEntry->Sst = SST_NOT_AUTH;
1931                         pEntry->AuthState = AS_NOT_AUTH;
1932                         pEntry->Aid = (USHORT)i;  //0;
1933                         pEntry->CapabilityInfo = 0;
1934                         pEntry->PsMode = PWR_ACTIVE;
1935                         pEntry->PsQIdleCount = 0;
1936                         pEntry->NoDataIdleCount = 0;
1937                         pEntry->ContinueTxFailCnt = 0;
1938                         InitializeQueueHeader(&pEntry->PsQueue);
1939
1940
1941                         pAd->MacTab.Size ++;
1942
1943                         // Add this entry into ASIC RX WCID search table
1944                         RT28XX_STA_ENTRY_ADD(pAd, pEntry);
1945
1946
1947
1948                         DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
1949                         break;
1950                 }
1951         }
1952
1953         // add this MAC entry into HASH table
1954         if (pEntry)
1955         {
1956                 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1957                 if (pAd->MacTab.Hash[HashIdx] == NULL)
1958                 {
1959                         pAd->MacTab.Hash[HashIdx] = pEntry;
1960                 }
1961                 else
1962                 {
1963                         pCurrEntry = pAd->MacTab.Hash[HashIdx];
1964                         while (pCurrEntry->pNext != NULL)
1965                                 pCurrEntry = pCurrEntry->pNext;
1966                         pCurrEntry->pNext = pEntry;
1967                 }
1968         }
1969
1970         NdisReleaseSpinLock(&pAd->MacTabLock);
1971         return pEntry;
1972 }
1973
1974 /*
1975         ==========================================================================
1976         Description:
1977                 Delete a specified client from MAC table
1978         ==========================================================================
1979  */
1980 BOOLEAN MacTableDeleteEntry(
1981         IN PRTMP_ADAPTER pAd,
1982         IN USHORT wcid,
1983         IN PUCHAR pAddr)
1984 {
1985         USHORT HashIdx;
1986         MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1987         BOOLEAN Cancelled;
1988         //USHORT        offset; // unused variable
1989         //UCHAR j;                      // unused variable
1990
1991         if (wcid >= MAX_LEN_OF_MAC_TABLE)
1992                 return FALSE;
1993
1994         NdisAcquireSpinLock(&pAd->MacTabLock);
1995
1996         HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1997         //pEntry = pAd->MacTab.Hash[HashIdx];
1998         pEntry = &pAd->MacTab.Content[wcid];
1999
2000         if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
2001                 ))
2002         {
2003                 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2004                 {
2005
2006                         // Delete this entry from ASIC on-chip WCID Table
2007                         RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
2008
2009 #ifdef DOT11_N_SUPPORT
2010                         // free resources of BA
2011                         BASessionTearDownALL(pAd, pEntry->Aid);
2012 #endif // DOT11_N_SUPPORT //
2013
2014
2015                         pPrevEntry = NULL;
2016                         pProbeEntry = pAd->MacTab.Hash[HashIdx];
2017                         ASSERT(pProbeEntry);
2018
2019                         // update Hash list
2020                         do
2021                         {
2022                                 if (pProbeEntry == pEntry)
2023                                 {
2024                                         if (pPrevEntry == NULL)
2025                                         {
2026                                                 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
2027                                         }
2028                                         else
2029                                         {
2030                                                 pPrevEntry->pNext = pEntry->pNext;
2031                                         }
2032                                         break;
2033                                 }
2034
2035                                 pPrevEntry = pProbeEntry;
2036                                 pProbeEntry = pProbeEntry->pNext;
2037                         } while (pProbeEntry);
2038
2039                         // not found !!!
2040                         ASSERT(pProbeEntry != NULL);
2041
2042                         RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
2043
2044
2045                 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
2046                 {
2047                         RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
2048                         pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2049                 }
2050
2051
2052                         NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2053                         pAd->MacTab.Size --;
2054                         DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
2055                 }
2056                 else
2057                 {
2058                         printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
2059                 }
2060         }
2061
2062         NdisReleaseSpinLock(&pAd->MacTabLock);
2063
2064         //Reset operating mode when no Sta.
2065         if (pAd->MacTab.Size == 0)
2066         {
2067 #ifdef DOT11_N_SUPPORT
2068                 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
2069 #endif // DOT11_N_SUPPORT //
2070                 //AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
2071                 RT28XX_UPDATE_PROTECT(pAd);  // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet
2072         }
2073
2074         return TRUE;
2075 }
2076
2077
2078 /*
2079         ==========================================================================
2080         Description:
2081                 This routine reset the entire MAC table. All packets pending in
2082                 the power-saving queues are freed here.
2083         ==========================================================================
2084  */
2085 VOID MacTableReset(
2086         IN  PRTMP_ADAPTER  pAd)
2087 {
2088         int         i;
2089
2090         DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
2091         //NdisAcquireSpinLock(&pAd->MacTabLock);
2092
2093         for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
2094         {
2095                 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
2096            {
2097
2098 #ifdef DOT11_N_SUPPORT
2099                         // free resources of BA
2100                         BASessionTearDownALL(pAd, i);
2101 #endif // DOT11_N_SUPPORT //
2102
2103                         pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2104
2105
2106
2107 #ifdef RT2870
2108                         NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
2109                         RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2110 #endif // RT2870 //
2111
2112                         //AsicDelWcidTab(pAd, i);
2113                 }
2114         }
2115
2116         return;
2117 }
2118
2119 /*
2120         ==========================================================================
2121         Description:
2122
2123         IRQL = DISPATCH_LEVEL
2124
2125         ==========================================================================
2126 */
2127 VOID AssocParmFill(
2128         IN PRTMP_ADAPTER pAd,
2129         IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2130         IN PUCHAR                     pAddr,
2131         IN USHORT                     CapabilityInfo,
2132         IN ULONG                      Timeout,
2133         IN USHORT                     ListenIntv)
2134 {
2135         COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2136         // Add mask to support 802.11b mode only
2137         AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2138         AssocReq->Timeout = Timeout;
2139         AssocReq->ListenIntv = ListenIntv;
2140 }
2141
2142
2143 /*
2144         ==========================================================================
2145         Description:
2146
2147         IRQL = DISPATCH_LEVEL
2148
2149         ==========================================================================
2150 */
2151 VOID DisassocParmFill(
2152         IN PRTMP_ADAPTER pAd,
2153         IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2154         IN PUCHAR pAddr,
2155         IN USHORT Reason)
2156 {
2157         COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2158         DisassocReq->Reason = Reason;
2159 }
2160
2161
2162 /*
2163         ========================================================================
2164
2165         Routine Description:
2166                 Check the out going frame, if this is an DHCP or ARP datagram
2167         will be duplicate another frame at low data rate transmit.
2168
2169         Arguments:
2170                 pAd             Pointer to our adapter
2171                 pPacket         Pointer to outgoing Ndis frame
2172
2173         Return Value:
2174                 TRUE            To be duplicate at Low data rate transmit. (1mb)
2175                 FALSE           Do nothing.
2176
2177         IRQL = DISPATCH_LEVEL
2178
2179         Note:
2180
2181                 MAC header + IP Header + UDP Header
2182                   14 Bytes        20 Bytes
2183
2184                 UDP Header
2185                 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2186                                                 Source Port
2187                 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2188                                         Destination Port
2189
2190                 port 0x43 means Bootstrap Protocol, server.
2191                 Port 0x44 means Bootstrap Protocol, client.
2192
2193         ========================================================================
2194 */
2195
2196 BOOLEAN RTMPCheckDHCPFrame(
2197         IN      PRTMP_ADAPTER   pAd,
2198         IN      PNDIS_PACKET    pPacket)
2199 {
2200         PACKET_INFO     PacketInfo;
2201         ULONG                   NumberOfBytesRead = 0;
2202         ULONG                   CurrentOffset = 0;
2203         PVOID                   pVirtualAddress = NULL;
2204         UINT                    NdisBufferLength;
2205         PUCHAR                  pSrc;
2206         USHORT                  Protocol;
2207         UCHAR                   ByteOffset36 = 0;
2208         UCHAR                   ByteOffset38 = 0;
2209         BOOLEAN                 ReadFirstParm = TRUE;
2210
2211         RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2212
2213         NumberOfBytesRead += NdisBufferLength;
2214         pSrc = (PUCHAR) pVirtualAddress;
2215         Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2216
2217         //
2218         // Check DHCP & BOOTP protocol
2219         //
2220         while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2221         {
2222                 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2223                 {
2224                         CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2225                         ByteOffset36 = *(pSrc + CurrentOffset);
2226                         ReadFirstParm = FALSE;
2227                 }
2228
2229                 if (NumberOfBytesRead >= 37)
2230                 {
2231                         CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2232                         ByteOffset38 = *(pSrc + CurrentOffset);
2233                         //End of Read
2234                         break;
2235                 }
2236                 return FALSE;
2237         }
2238
2239         // Check for DHCP & BOOTP protocol
2240         if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2241                 {
2242                 //
2243                 // 2054 (hex 0806) for ARP datagrams
2244                 // if this packet is not ARP datagrams, then do nothing
2245                 // ARP datagrams will also be duplicate at 1mb broadcast frames
2246                 //
2247                 if (Protocol != 0x0806 )
2248                         return FALSE;
2249                 }
2250
2251         return TRUE;
2252 }
2253
2254
2255 BOOLEAN RTMPCheckEtherType(
2256         IN      PRTMP_ADAPTER   pAd,
2257         IN      PNDIS_PACKET    pPacket)
2258 {
2259         USHORT  TypeLen;
2260         UCHAR   Byte0, Byte1;
2261         PUCHAR  pSrcBuf;
2262         UINT32  pktLen;
2263         UINT16  srcPort, dstPort;
2264         BOOLEAN status = TRUE;
2265
2266
2267         pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2268         pktLen = GET_OS_PKT_LEN(pPacket);
2269
2270         ASSERT(pSrcBuf);
2271
2272         RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2273
2274         // get Ethernet protocol field
2275         TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2276
2277         pSrcBuf += LENGTH_802_3;        // Skip the Ethernet Header.
2278
2279         if (TypeLen <= 1500)
2280         {       // 802.3, 802.3 LLC
2281                 /*
2282                         DestMAC(6) + SrcMAC(6) + Lenght(2) +
2283                         DSAP(1) + SSAP(1) + Control(1) +
2284                         if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2285                                 => + SNAP (5, OriginationID(3) + etherType(2))
2286                 */
2287                 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2288                 {
2289                         Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2290                         RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2291                         TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2292                         pSrcBuf += 8; // Skip this LLC/SNAP header
2293                 }
2294                 else
2295                 {
2296                         //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2297                 }
2298         }
2299
2300         // If it's a VLAN packet, get the real Type/Length field.
2301         if (TypeLen == 0x8100)
2302         {
2303                 /* 0x8100 means VLAN packets */
2304
2305                 /* Dest. MAC Address (6-bytes) +
2306                    Source MAC Address (6-bytes) +
2307                    Length/Type = 802.1Q Tag Type (2-byte) +
2308                    Tag Control Information (2-bytes) +
2309                    Length / Type (2-bytes) +
2310                    data payload (0-n bytes) +
2311                    Pad (0-p bytes) +
2312                    Frame Check Sequence (4-bytes) */
2313
2314                 RTMP_SET_PACKET_VLAN(pPacket, 1);
2315                 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2316                 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2317
2318                 pSrcBuf += 4; // Skip the VLAN Header.
2319         }
2320
2321         switch (TypeLen)
2322         {
2323                 case 0x0800:
2324                         {
2325                                 ASSERT((pktLen > 34));
2326                                 if (*(pSrcBuf + 9) == 0x11)
2327                                 {       // udp packet
2328                                         ASSERT((pktLen > 34));  // 14 for ethernet header, 20 for IP header
2329
2330                                         pSrcBuf += 20;  // Skip the IP header
2331                                         srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2332                                         dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2333
2334                                         if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2335                                         {       //It's a BOOTP/DHCP packet
2336                                                 RTMP_SET_PACKET_DHCP(pPacket, 1);
2337                                         }
2338                                 }
2339                         }
2340                         break;
2341                 case 0x0806:
2342                         {
2343                                 //ARP Packet.
2344                                 RTMP_SET_PACKET_DHCP(pPacket, 1);
2345                         }
2346                         break;
2347                 case 0x888e:
2348                         {
2349                                 // EAPOL Packet.
2350                                 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2351                         }
2352                         break;
2353                 default:
2354                         status = FALSE;
2355                         break;
2356         }
2357
2358         return status;
2359
2360 }
2361
2362
2363
2364 VOID Update_Rssi_Sample(
2365         IN PRTMP_ADAPTER        pAd,
2366         IN RSSI_SAMPLE          *pRssi,
2367         IN PRXWI_STRUC          pRxWI)
2368                 {
2369         CHAR    rssi0 = pRxWI->RSSI0;
2370         CHAR    rssi1 = pRxWI->RSSI1;
2371         CHAR    rssi2 = pRxWI->RSSI2;
2372
2373         if (rssi0 != 0)
2374         {
2375                 pRssi->LastRssi0        = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2376                 pRssi->AvgRssi0X8       = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2377                 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2378         }
2379
2380         if (rssi1 != 0)
2381         {
2382                 pRssi->LastRssi1        = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2383                 pRssi->AvgRssi1X8       = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2384                 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2385         }
2386
2387         if (rssi2 != 0)
2388         {
2389                 pRssi->LastRssi2        = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2390                 pRssi->AvgRssi2X8  = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2391                 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2392         }
2393 }
2394
2395
2396
2397 // Normal legacy Rx packet indication
2398 VOID Indicate_Legacy_Packet(
2399         IN      PRTMP_ADAPTER   pAd,
2400         IN      RX_BLK                  *pRxBlk,
2401         IN      UCHAR                   FromWhichBSSID)
2402 {
2403         PNDIS_PACKET    pRxPacket = pRxBlk->pRxPacket;
2404         UCHAR                   Header802_3[LENGTH_802_3];
2405
2406         // 1. get 802.3 Header
2407         // 2. remove LLC
2408         //              a. pointer pRxBlk->pData to payload
2409         //      b. modify pRxBlk->DataSize
2410 #ifdef CONFIG_STA_SUPPORT
2411         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2412                 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2413 #endif // CONFIG_STA_SUPPORT //
2414
2415         if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2416         {
2417                 // release packet
2418                 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2419                 return;
2420         }
2421
2422
2423         STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2424
2425 #ifdef RT2870
2426 #ifdef DOT11_N_SUPPORT
2427         if (pAd->CommonCfg.bDisableReordering == 0)
2428         {
2429                 PBA_REC_ENTRY           pBAEntry;
2430                 ULONG                           Now32;
2431                 UCHAR                           Wcid = pRxBlk->pRxWI->WirelessCliID;
2432                 UCHAR                           TID = pRxBlk->pRxWI->TID;
2433                 USHORT                          Idx;
2434
2435 #define REORDERING_PACKET_TIMEOUT               ((100 * HZ)/1000)       // system ticks -- 100 ms
2436
2437                 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2438                 {
2439                         Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2440                         if (Idx != 0)
2441                         {
2442                                 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2443                                 // update last rx time
2444                                 NdisGetSystemUpTime(&Now32);
2445                                 if ((pBAEntry->list.qlen > 0) &&
2446                                          RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2447                                         )
2448                                 {
2449                                         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);
2450                                         hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2451                                         ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2452                                 }
2453                         }
2454                 }
2455         }
2456 #endif // DOT11_N_SUPPORT //
2457 #endif // RT2870 //
2458
2459         wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2460
2461         //
2462         // pass this 802.3 packet to upper layer or forward this packet to WM directly
2463         //
2464 #ifdef CONFIG_STA_SUPPORT
2465         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2466                 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2467 #endif // CONFIG_STA_SUPPORT //
2468
2469 }
2470
2471
2472 // Normal, AMPDU or AMSDU
2473 VOID CmmRxnonRalinkFrameIndicate(
2474         IN      PRTMP_ADAPTER   pAd,
2475         IN      RX_BLK                  *pRxBlk,
2476         IN      UCHAR                   FromWhichBSSID)
2477 {
2478 #ifdef DOT11_N_SUPPORT
2479         if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2480         {
2481                 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2482         }
2483         else
2484 #endif // DOT11_N_SUPPORT //
2485         {
2486 #ifdef DOT11_N_SUPPORT
2487                 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2488                 {
2489                         // handle A-MSDU
2490                         Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2491                 }
2492                 else
2493 #endif // DOT11_N_SUPPORT //
2494                 {
2495                         Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2496                 }
2497         }
2498 }
2499
2500
2501 VOID CmmRxRalinkFrameIndicate(
2502         IN      PRTMP_ADAPTER   pAd,
2503         IN      MAC_TABLE_ENTRY *pEntry,
2504         IN      RX_BLK                  *pRxBlk,
2505         IN      UCHAR                   FromWhichBSSID)
2506 {
2507         UCHAR                   Header802_3[LENGTH_802_3];
2508         UINT16                  Msdu2Size;
2509         UINT16                  Payload1Size, Payload2Size;
2510         PUCHAR                  pData2;
2511         PNDIS_PACKET    pPacket2 = NULL;
2512
2513
2514
2515         Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2516
2517         if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2518         {
2519                 /* skip two byte MSDU2 len */
2520                 pRxBlk->pData += 2;
2521                 pRxBlk->DataSize -= 2;
2522         }
2523         else
2524         {
2525                 // release packet
2526                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2527                 return;
2528         }
2529
2530         // get 802.3 Header and  remove LLC
2531 #ifdef CONFIG_STA_SUPPORT
2532         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2533                 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2534 #endif // CONFIG_STA_SUPPORT //
2535
2536
2537         ASSERT(pRxBlk->pRxPacket);
2538
2539         // Ralink Aggregation frame
2540         pAd->RalinkCounters.OneSecRxAggregationCount ++;
2541         Payload1Size = pRxBlk->DataSize - Msdu2Size;
2542         Payload2Size = Msdu2Size - LENGTH_802_3;
2543
2544         pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2545 #ifdef CONFIG_STA_SUPPORT
2546         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2547                 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2548 #endif // CONFIG_STA_SUPPORT //
2549
2550         if (!pPacket2)
2551         {
2552                 // release packet
2553                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2554                 return;
2555         }
2556
2557         // update payload size of 1st packet
2558         pRxBlk->DataSize = Payload1Size;
2559         wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2560
2561 #ifdef CONFIG_STA_SUPPORT
2562         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2563                 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2564 #endif // CONFIG_STA_SUPPORT //
2565
2566         if (pPacket2)
2567         {
2568 #ifdef CONFIG_STA_SUPPORT
2569                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2570                         ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2571 #endif // CONFIG_STA_SUPPORT //
2572         }
2573 }
2574
2575
2576 #define RESET_FRAGFRAME(_fragFrame) \
2577         {                                                               \
2578                 _fragFrame.RxSize = 0;          \
2579                 _fragFrame.Sequence = 0;        \
2580                 _fragFrame.LastFrag = 0;        \
2581                 _fragFrame.Flags = 0;           \
2582         }
2583
2584
2585 PNDIS_PACKET RTMPDeFragmentDataFrame(
2586         IN      PRTMP_ADAPTER   pAd,
2587         IN      RX_BLK                  *pRxBlk)
2588 {
2589         PHEADER_802_11  pHeader = pRxBlk->pHeader;
2590         PNDIS_PACKET    pRxPacket = pRxBlk->pRxPacket;
2591         UCHAR                   *pData = pRxBlk->pData;
2592         USHORT                  DataSize = pRxBlk->DataSize;
2593         PNDIS_PACKET    pRetPacket = NULL;
2594         UCHAR                   *pFragBuffer = NULL;
2595         BOOLEAN                 bReassDone = FALSE;
2596         UCHAR                   HeaderRoom = 0;
2597
2598
2599         ASSERT(pHeader);
2600
2601         HeaderRoom = pData - (UCHAR *)pHeader;
2602
2603         // Re-assemble the fragmented packets
2604         if (pHeader->Frag == 0)         // Frag. Number is 0 : First frag or only one pkt
2605         {
2606                 // the first pkt of fragment, record it.
2607                 if (pHeader->FC.MoreFrag)
2608                 {
2609                         ASSERT(pAd->FragFrame.pFragPacket);
2610                         pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2611                         pAd->FragFrame.RxSize   = DataSize + HeaderRoom;
2612                         NdisMoveMemory(pFragBuffer,      pHeader, pAd->FragFrame.RxSize);
2613                         pAd->FragFrame.Sequence = pHeader->Sequence;
2614                         pAd->FragFrame.LastFrag = pHeader->Frag;           // Should be 0
2615                         ASSERT(pAd->FragFrame.LastFrag == 0);
2616                         goto done;      // end of processing this frame
2617                 }
2618         }
2619         else    //Middle & End of fragment
2620         {
2621                 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2622                         (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2623                 {
2624                         // Fragment is not the same sequence or out of fragment number order
2625                         // Reset Fragment control blk
2626                         RESET_FRAGFRAME(pAd->FragFrame);
2627                         DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2628                         goto done; // give up this frame
2629                 }
2630                 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2631                 {
2632                         // Fragment frame is too large, it exeeds the maximum frame size.
2633                         // Reset Fragment control blk
2634                         RESET_FRAGFRAME(pAd->FragFrame);
2635                         DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2636                         goto done; // give up this frame
2637                 }
2638
2639         //
2640                 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2641                 // In this case, we will dropt it.
2642                 //
2643                 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2644                 {
2645                         DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2646                         goto done; // give up this frame
2647                 }
2648
2649                 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2650
2651                 // concatenate this fragment into the re-assembly buffer
2652                 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2653                 pAd->FragFrame.RxSize  += DataSize;
2654                 pAd->FragFrame.LastFrag = pHeader->Frag;           // Update fragment number
2655
2656                 // Last fragment
2657                 if (pHeader->FC.MoreFrag == FALSE)
2658                 {
2659                         bReassDone = TRUE;
2660                 }
2661         }
2662
2663 done:
2664         // always release rx fragmented packet
2665         RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2666
2667         // return defragmented packet if packet is reassembled completely
2668         // otherwise return NULL
2669         if (bReassDone)
2670         {
2671                 PNDIS_PACKET pNewFragPacket;
2672
2673                 // allocate a new packet buffer for fragment
2674                 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2675                 if (pNewFragPacket)
2676                 {
2677                         // update RxBlk
2678                         pRetPacket = pAd->FragFrame.pFragPacket;
2679                         pAd->FragFrame.pFragPacket = pNewFragPacket;
2680                         pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2681                         pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2682                         pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2683                         pRxBlk->pRxPacket = pRetPacket;
2684                 }
2685                 else
2686                 {
2687                         RESET_FRAGFRAME(pAd->FragFrame);
2688                 }
2689         }
2690
2691         return pRetPacket;
2692 }
2693
2694
2695 VOID Indicate_AMSDU_Packet(
2696         IN      PRTMP_ADAPTER   pAd,
2697         IN      RX_BLK                  *pRxBlk,
2698         IN      UCHAR                   FromWhichBSSID)
2699 {
2700         UINT                    nMSDU;
2701
2702         update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2703         RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2704         nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2705 }
2706
2707 VOID Indicate_EAPOL_Packet(
2708         IN      PRTMP_ADAPTER   pAd,
2709         IN      RX_BLK                  *pRxBlk,
2710         IN      UCHAR                   FromWhichBSSID)
2711 {
2712         MAC_TABLE_ENTRY *pEntry = NULL;
2713
2714
2715 #ifdef CONFIG_STA_SUPPORT
2716         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2717         {
2718                 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2719                 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2720                 return;
2721         }
2722 #endif // CONFIG_STA_SUPPORT //
2723
2724         if (pEntry == NULL)
2725         {
2726                 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2727                 // release packet
2728                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2729                 return;
2730         }
2731 }
2732
2733 #define BCN_TBTT_OFFSET         64      //defer 64 us
2734 VOID ReSyncBeaconTime(
2735         IN  PRTMP_ADAPTER   pAd)
2736 {
2737
2738         UINT32  Offset;
2739
2740
2741         Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2742
2743         pAd->TbttTickCount++;
2744
2745         //
2746         // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2747         // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2748         //
2749         if (Offset == (BCN_TBTT_OFFSET-2))
2750         {
2751                 BCN_TIME_CFG_STRUC csr;
2752                 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2753                 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ;     // ASIC register in units of 1/16 TU = 64us
2754                 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2755         }
2756         else
2757         {
2758                 if (Offset == (BCN_TBTT_OFFSET-1))
2759                 {
2760                         BCN_TIME_CFG_STRUC csr;
2761
2762                         RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2763                         csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
2764                         RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2765                 }
2766         }
2767 }
2768