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