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