Staging: rt2870: remove dead DOT11N_DRAFT3 code
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / rt2870 / common / cmm_data.c
blob96f28733d47c4414536ccaf24893974ef863b976
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
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 *************************************************************************
28 #include "../rt_config.h"
30 #define MAX_TX_IN_TBTT (16)
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 */
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
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
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
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
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"};
69 UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2};
70 //UCHAR default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1};
71 UCHAR default_sta_aifsn[]={3,7,2,2};
73 UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO};
77 ========================================================================
79 Routine Description:
80 API for MLME to transmit management frame to AP (BSS Mode)
81 or station (IBSS Mode)
83 Arguments:
84 pAd Pointer to our adapter
85 pData Pointer to the outgoing 802.11 frame
86 Length Size of outgoing management frame
88 Return Value:
89 NDIS_STATUS_FAILURE
90 NDIS_STATUS_PENDING
91 NDIS_STATUS_SUCCESS
93 IRQL = PASSIVE_LEVEL
94 IRQL = DISPATCH_LEVEL
96 Note:
98 ========================================================================
100 NDIS_STATUS MiniportMMRequest(
101 IN PRTMP_ADAPTER pAd,
102 IN UCHAR QueIdx,
103 IN PUCHAR pData,
104 IN UINT Length)
106 PNDIS_PACKET pPacket;
107 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
108 ULONG FreeNum;
109 UCHAR IrqState;
110 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
112 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
114 QueIdx=3;
116 // 2860C use Tx Ring
118 IrqState = pAd->irq_disabled;
122 // Reset is in progress, stop immediately
123 if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
124 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
125 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
127 Status = NDIS_STATUS_FAILURE;
128 break;
131 // Check Free priority queue
132 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
134 // 2860C use Tx Ring
135 if (pAd->MACVersion == 0x28600100)
137 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
139 else
141 FreeNum = GET_MGMTRING_FREENO(pAd);
144 if ((FreeNum > 0))
146 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
147 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
148 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
149 if (Status != NDIS_STATUS_SUCCESS)
151 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
152 break;
155 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
156 //pAd->CommonCfg.MlmeRate = RATE_2;
159 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
160 if (Status != NDIS_STATUS_SUCCESS)
161 RTMPFreeNdisPacket(pAd, pPacket);
163 else
165 pAd->RalinkCounters.MgmtRingFullCount++;
166 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
167 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
170 } while (FALSE);
173 return Status;
180 ========================================================================
182 Routine Description:
183 Copy frame from waiting queue into relative ring buffer and set
184 appropriate ASIC register to kick hardware transmit function
186 Arguments:
187 pAd Pointer to our adapter
188 pBuffer Pointer to memory of outgoing frame
189 Length Size of outgoing management frame
191 Return Value:
192 NDIS_STATUS_FAILURE
193 NDIS_STATUS_PENDING
194 NDIS_STATUS_SUCCESS
196 IRQL = PASSIVE_LEVEL
197 IRQL = DISPATCH_LEVEL
199 Note:
201 ========================================================================
203 NDIS_STATUS MlmeHardTransmit(
204 IN PRTMP_ADAPTER pAd,
205 IN UCHAR QueIdx,
206 IN PNDIS_PACKET pPacket)
208 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
211 return NDIS_STATUS_FAILURE;
214 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
220 NDIS_STATUS MlmeHardTransmitMgmtRing(
221 IN PRTMP_ADAPTER pAd,
222 IN UCHAR QueIdx,
223 IN PNDIS_PACKET pPacket)
225 PACKET_INFO PacketInfo;
226 PUCHAR pSrcBufVA;
227 UINT SrcBufLen;
228 PHEADER_802_11 pHeader_802_11;
229 BOOLEAN bAckRequired, bInsertTimestamp;
230 UCHAR MlmeRate;
231 PTXWI_STRUC pFirstTxWI;
232 MAC_TABLE_ENTRY *pMacEntry = NULL;
234 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
236 // Make sure MGMT ring resource won't be used by other threads
237 // sample, for IRQ LOCK -> SEM LOCK
238 // IrqState = pAd->irq_disabled;
239 // if (!IrqState)
240 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
243 if (pSrcBufVA == NULL)
245 // The buffer shouldn't be NULL
246 // if (!IrqState)
247 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
248 return NDIS_STATUS_FAILURE;
251 #ifdef CONFIG_STA_SUPPORT
252 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
254 // outgoing frame always wakeup PHY to prevent frame lost
255 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
256 AsicForceWakeup(pAd, TRUE);
258 #endif // CONFIG_STA_SUPPORT //
260 pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
261 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
263 if (pHeader_802_11->Addr1[0] & 0x01)
265 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
267 else
269 MlmeRate = pAd->CommonCfg.MlmeRate;
272 // Verify Mlme rate for a / g bands.
273 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
274 MlmeRate = RATE_6;
276 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
277 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
279 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
282 #ifdef CONFIG_STA_SUPPORT
283 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
285 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
286 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
287 #ifdef DOT11_N_SUPPORT
288 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
289 #endif // DOT11_N_SUPPORT //
292 if (pAd->LatchRfRegs.Channel > 14)
293 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
294 else
295 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
298 #endif // CONFIG_STA_SUPPORT //
301 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
302 // Snice it's been set to 0 while on MgtMacHeaderInit
303 // By the way this will cause frame to be send on PWR_SAVE failed.
305 // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
307 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
308 #ifdef CONFIG_STA_SUPPORT
309 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
310 if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
312 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
313 (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
314 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
315 else
316 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
318 #endif // CONFIG_STA_SUPPORT //
320 bInsertTimestamp = FALSE;
321 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
323 #ifdef CONFIG_STA_SUPPORT
324 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
325 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
327 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
329 #endif // CONFIG_STA_SUPPORT //
330 bAckRequired = FALSE;
332 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
334 //pAd->Sequence++;
335 //pHeader_802_11->Sequence = pAd->Sequence;
337 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
339 bAckRequired = FALSE;
340 pHeader_802_11->Duration = 0;
342 else
344 bAckRequired = TRUE;
345 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
346 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
348 bInsertTimestamp = TRUE;
353 pHeader_802_11->Sequence = pAd->Sequence++;
354 if (pAd->Sequence >0xfff)
355 pAd->Sequence = 0;
357 // Before radar detection done, mgmt frame can not be sent but probe req
358 // Because we need to use probe req to trigger driver to send probe req in passive scan
359 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
360 && (pAd->CommonCfg.bIEEE80211H == 1)
361 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
363 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
364 // if (!IrqState)
365 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
366 return (NDIS_STATUS_FAILURE);
369 #ifdef RT_BIG_ENDIAN
370 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);
371 #endif
374 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
375 // should always has only one ohysical buffer, and the whole frame size equals
376 // to the first scatter buffer size
379 // Initialize TX Descriptor
380 // For inter-frame gap, the number is for this frame and next frame
381 // For MLME rate, we will fix as 2Mb to match other vendor's implement
382 // pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
384 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
385 if (pMacEntry == NULL)
387 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
388 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
390 else
392 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
393 bInsertTimestamp, FALSE, bAckRequired, FALSE,
394 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
395 pMacEntry->MaxHTPhyMode.field.MCS, 0,
396 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
397 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
400 #ifdef RT_BIG_ENDIAN
401 RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI);
402 #endif
404 // Now do hardware-depened kick out.
405 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
407 // Make sure to release MGMT ring resource
408 // if (!IrqState)
409 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
410 return NDIS_STATUS_SUCCESS;
414 /********************************************************************************
416 New DeQueue Procedures.
418 ********************************************************************************/
420 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
421 do{ \
422 if (bIntContext == FALSE) \
423 RTMP_IRQ_LOCK((lock), IrqFlags); \
424 }while(0)
426 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
427 do{ \
428 if (bIntContext == FALSE) \
429 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
430 }while(0)
433 #if 0
434 static VOID dumpTxBlk(TX_BLK *pTxBlk)
436 NDIS_PACKET *pPacket;
437 int i, frameNum;
438 PQUEUE_ENTRY pQEntry;
440 printk("Dump TX_BLK Structure:\n");
441 printk("\tTxFrameType=%d!\n", pTxBlk->TxFrameType);
442 printk("\tTotalFrameLen=%d\n", pTxBlk->TotalFrameLen);
443 printk("\tTotalFrameNum=%ld!\n", pTxBlk->TxPacketList.Number);
444 printk("\tTotalFragNum=%d!\n", pTxBlk->TotalFragNum);
445 printk("\tpPacketList=\n");
447 frameNum = pTxBlk->TxPacketList.Number;
449 for(i=0; i < frameNum; i++)
450 { int j;
451 UCHAR *pBuf;
453 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
454 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
455 if (pPacket)
457 pBuf = GET_OS_PKT_DATAPTR(pPacket);
458 printk("\t\t[%d]:ptr=0x%x, Len=%d!\n", i, (UINT32)(GET_OS_PKT_DATAPTR(pPacket)), GET_OS_PKT_LEN(pPacket));
459 printk("\t\t");
460 for (j =0 ; j < GET_OS_PKT_LEN(pPacket); j++)
462 printk("%02x ", (pBuf[j] & 0xff));
463 if (j == 16)
464 break;
466 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
469 printk("\tWcid=%d!\n", pTxBlk->Wcid);
470 printk("\tapidx=%d!\n", pTxBlk->apidx);
471 printk("----EndOfDump\n");
474 #endif
478 ========================================================================
479 Tx Path design algorithm:
480 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
481 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
482 Classification Rule=>
483 Multicast: (*addr1 & 0x01) == 0x01
484 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
485 11N Rate : If peer support HT
486 (1).AMPDU -- If TXBA is negotiated.
487 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
488 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
489 (3).Normal -- Other packets which send as 11n rate.
491 B/G Rate : If peer is b/g only.
492 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
493 (2).Normal -- Other packets which send as b/g rate.
494 Fragment:
495 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
497 Classified Packet Handle Rule=>
498 Multicast:
499 No ACK, //pTxBlk->bAckRequired = FALSE;
500 No WMM, //pTxBlk->bWMM = FALSE;
501 No piggyback, //pTxBlk->bPiggyBack = FALSE;
502 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
503 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
504 the same policy to handle it.
505 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
507 11N Rate :
508 No piggyback, //pTxBlk->bPiggyBack = FALSE;
510 (1).AMSDU
511 pTxBlk->bWMM = TRUE;
512 (2).AMPDU
513 pTxBlk->bWMM = TRUE;
514 (3).Normal
516 B/G Rate :
517 (1).ARALINK
519 (2).Normal
520 ========================================================================
522 static UCHAR TxPktClassification(
523 IN RTMP_ADAPTER *pAd,
524 IN PNDIS_PACKET pPacket)
526 UCHAR TxFrameType = TX_UNKOWN_FRAME;
527 UCHAR Wcid;
528 MAC_TABLE_ENTRY *pMacEntry = NULL;
529 #ifdef DOT11_N_SUPPORT
530 BOOLEAN bHTRate = FALSE;
531 #endif // DOT11_N_SUPPORT //
533 Wcid = RTMP_GET_PACKET_WCID(pPacket);
534 if (Wcid == MCAST_WCID)
535 { // Handle for RA is Broadcast/Multicast Address.
536 return TX_MCAST_FRAME;
539 // Handle for unicast packets
540 pMacEntry = &pAd->MacTab.Content[Wcid];
541 if (RTMP_GET_PACKET_LOWRATE(pPacket))
542 { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
543 TxFrameType = TX_LEGACY_FRAME;
545 #ifdef DOT11_N_SUPPORT
546 else if (IS_HT_RATE(pMacEntry))
547 { // it's a 11n capable packet
549 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
550 // Currently didn't support A-MSDU embedded in A-MPDU
551 bHTRate = TRUE;
552 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
553 TxFrameType = TX_LEGACY_FRAME;
554 #ifdef UAPSD_AP_SUPPORT
555 else if (RTMP_GET_PACKET_EOSP(pPacket))
556 TxFrameType = TX_LEGACY_FRAME;
557 #endif // UAPSD_AP_SUPPORT //
558 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
559 return TX_AMPDU_FRAME;
560 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
561 return TX_AMSDU_FRAME;
562 else
563 TxFrameType = TX_LEGACY_FRAME;
565 #endif // DOT11_N_SUPPORT //
566 else
567 { // it's a legacy b/g packet.
568 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
569 (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
570 (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
571 { // if peer support Ralink Aggregation, we use it.
572 TxFrameType = TX_RALINK_FRAME;
574 else
576 TxFrameType = TX_LEGACY_FRAME;
580 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
581 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
582 TxFrameType = TX_FRAG_FRAME;
584 return TxFrameType;
588 BOOLEAN RTMP_FillTxBlkInfo(
589 IN RTMP_ADAPTER *pAd,
590 IN TX_BLK *pTxBlk)
592 PACKET_INFO PacketInfo;
593 PNDIS_PACKET pPacket;
594 PMAC_TABLE_ENTRY pMacEntry = NULL;
596 pPacket = pTxBlk->pPacket;
597 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
599 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
600 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
601 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
602 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
604 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
605 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
606 else
607 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
609 // Default to clear this flag
610 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
613 if (pTxBlk->Wcid == MCAST_WCID)
615 pTxBlk->pMacEntry = NULL;
617 #ifdef MCAST_RATE_SPECIFIC
618 PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
619 if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
620 pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
621 else
622 #endif // MCAST_RATE_SPECIFIC //
623 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
626 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
627 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
628 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
629 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
630 if (RTMP_GET_PACKET_MOREDATA(pPacket))
632 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
636 else
638 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
639 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
641 pMacEntry = pTxBlk->pMacEntry;
644 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
645 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
646 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
647 else
648 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
652 #ifdef CONFIG_STA_SUPPORT
653 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
656 // If support WMM, enable it.
657 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
658 CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
659 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
661 #endif // CONFIG_STA_SUPPORT //
664 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
666 if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
667 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
668 { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
669 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
670 #ifdef DOT11_N_SUPPORT
671 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
672 if (IS_HT_STA(pTxBlk->pMacEntry) &&
673 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
674 ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
676 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
677 TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
679 #endif // DOT11_N_SUPPORT //
682 #ifdef DOT11_N_SUPPORT
683 if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
684 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
685 { // Currently piggy-back only support when peer is operate in b/g mode.
686 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
688 #endif // DOT11_N_SUPPORT //
690 if (RTMP_GET_PACKET_MOREDATA(pPacket))
692 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
694 #ifdef UAPSD_AP_SUPPORT
695 if (RTMP_GET_PACKET_EOSP(pPacket))
697 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
699 #endif // UAPSD_AP_SUPPORT //
701 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
703 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
706 pMacEntry->DebugTxCount++;
709 return TRUE;
713 BOOLEAN CanDoAggregateTransmit(
714 IN RTMP_ADAPTER *pAd,
715 IN NDIS_PACKET *pPacket,
716 IN TX_BLK *pTxBlk)
719 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
721 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
722 return FALSE;
724 if (RTMP_GET_PACKET_DHCP(pPacket) ||
725 RTMP_GET_PACKET_EAPOL(pPacket) ||
726 RTMP_GET_PACKET_WAI(pPacket))
727 return FALSE;
729 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
730 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
731 { // For AMSDU, allow the packets with total length < max-amsdu size
732 return FALSE;
735 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
736 (pTxBlk->TxPacketList.Number == 2))
737 { // For RALINK-Aggregation, allow two frames in one batch.
738 return FALSE;
741 #ifdef CONFIG_STA_SUPPORT
742 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
743 return TRUE;
744 else
745 #endif // CONFIG_STA_SUPPORT //
746 return FALSE;
752 ========================================================================
754 Routine Description:
755 To do the enqueue operation and extract the first item of waiting
756 list. If a number of available shared memory segments could meet
757 the request of extracted item, the extracted item will be fragmented
758 into shared memory segments.
760 Arguments:
761 pAd Pointer to our adapter
762 pQueue Pointer to Waiting Queue
764 Return Value:
765 None
767 IRQL = DISPATCH_LEVEL
769 Note:
771 ========================================================================
773 VOID RTMPDeQueuePacket(
774 IN PRTMP_ADAPTER pAd,
775 IN BOOLEAN bIntContext,
776 IN UCHAR QIdx, /* BulkOutPipeId */
777 IN UCHAR Max_Tx_Packets)
779 PQUEUE_ENTRY pEntry = NULL;
780 PNDIS_PACKET pPacket;
781 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
782 UCHAR Count=0;
783 PQUEUE_HEADER pQueue;
784 ULONG FreeNumber[NUM_OF_TX_RING];
785 UCHAR QueIdx, sQIdx, eQIdx;
786 unsigned long IrqFlags = 0;
787 BOOLEAN hasTxDesc = FALSE;
788 TX_BLK TxBlk;
789 TX_BLK *pTxBlk;
791 #ifdef DBG_DIAGNOSE
792 BOOLEAN firstRound;
793 RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
794 #endif
797 if (QIdx == NUM_OF_TX_RING)
799 sQIdx = 0;
800 eQIdx = 3; // 4 ACs, start from 0.
802 else
804 sQIdx = eQIdx = QIdx;
807 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
809 Count=0;
811 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
813 #ifdef DBG_DIAGNOSE
814 firstRound = ((QueIdx == 0) ? TRUE : FALSE);
815 #endif // DBG_DIAGNOSE //
817 while (1)
819 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
820 fRTMP_ADAPTER_RADIO_OFF |
821 fRTMP_ADAPTER_RESET_IN_PROGRESS |
822 fRTMP_ADAPTER_HALT_IN_PROGRESS |
823 fRTMP_ADAPTER_NIC_NOT_EXIST))))
825 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
826 return;
829 if (Count >= Max_Tx_Packets)
830 break;
832 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
833 if (&pAd->TxSwQueue[QueIdx] == NULL)
835 #ifdef DBG_DIAGNOSE
836 if (firstRound == TRUE)
837 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
838 #endif // DBG_DIAGNOSE //
839 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
840 break;
844 // probe the Queue Head
845 pQueue = &pAd->TxSwQueue[QueIdx];
846 if ((pEntry = pQueue->Head) == NULL)
848 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
849 break;
852 pTxBlk = &TxBlk;
853 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
854 //InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it.
855 pTxBlk->QueIdx = QueIdx;
857 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
859 // Early check to make sure we have enoguh Tx Resource.
860 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
861 if (!hasTxDesc)
863 pAd->PrivateInfo.TxRingFullCnt++;
865 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
867 break;
870 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
871 pEntry = RemoveHeadQueue(pQueue);
872 pTxBlk->TotalFrameNum++;
873 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
874 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
875 pTxBlk->pPacket = pPacket;
876 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
878 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
880 // Enhance SW Aggregation Mechanism
881 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
883 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
884 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
885 break;
889 if((pEntry = pQueue->Head) == NULL)
890 break;
892 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
893 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
894 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
895 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
896 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
897 break;
899 //Remove the packet from the TxSwQueue and insert into pTxBlk
900 pEntry = RemoveHeadQueue(pQueue);
901 ASSERT(pEntry);
902 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
903 pTxBlk->TotalFrameNum++;
904 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
905 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
906 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
907 }while(1);
909 if (pTxBlk->TxPacketList.Number == 1)
910 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
913 #ifdef RT2870
914 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
915 #endif // RT2870 //
917 Count += pTxBlk->TxPacketList.Number;
919 // Do HardTransmit now.
920 #ifdef CONFIG_STA_SUPPORT
921 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
922 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
923 #endif // CONFIG_STA_SUPPORT //
926 #if 0 // We should not break if HardTransmit failed. Well, at least now we should not!
927 if (Status != NDIS_STATUS_SUCCESS)
929 DBGPRINT(RT_DEBUG_TRACE /*RT_DEBUG_INFO*/,("RTMPHardTransmit return failed!!!\n"));
930 break;
932 #endif
935 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
937 #ifdef RT2870
938 if (!hasTxDesc)
939 RTUSBKickBulkOut(pAd);
940 #endif // RT2870 //
947 ========================================================================
949 Routine Description:
950 Calculates the duration which is required to transmit out frames
951 with given size and specified rate.
953 Arguments:
954 pAd Pointer to our adapter
955 Rate Transmit rate
956 Size Frame size in units of byte
958 Return Value:
959 Duration number in units of usec
961 IRQL = PASSIVE_LEVEL
962 IRQL = DISPATCH_LEVEL
964 Note:
966 ========================================================================
968 USHORT RTMPCalcDuration(
969 IN PRTMP_ADAPTER pAd,
970 IN UCHAR Rate,
971 IN ULONG Size)
973 ULONG Duration = 0;
975 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
977 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
978 Duration = 96; // 72+24 preamble+plcp
979 else
980 Duration = 192; // 144+48 preamble+plcp
982 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
983 if ((Size << 4) % RateIdTo500Kbps[Rate])
984 Duration ++;
986 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
988 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
989 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
990 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
991 Duration += 4;
993 else //mimo rate
995 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
998 return (USHORT)Duration;
1003 ========================================================================
1005 Routine Description:
1006 Calculates the duration which is required to transmit out frames
1007 with given size and specified rate.
1009 Arguments:
1010 pTxWI Pointer to head of each MPDU to HW.
1011 Ack Setting for Ack requirement bit
1012 Fragment Setting for Fragment bit
1013 RetryMode Setting for retry mode
1014 Ifs Setting for IFS gap
1015 Rate Setting for transmit rate
1016 Service Setting for service
1017 Length Frame length
1018 TxPreamble Short or Long preamble when using CCK rates
1019 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1021 Return Value:
1022 None
1024 IRQL = PASSIVE_LEVEL
1025 IRQL = DISPATCH_LEVEL
1027 See also : BASmartHardTransmit() !!!
1029 ========================================================================
1031 VOID RTMPWriteTxWI(
1032 IN PRTMP_ADAPTER pAd,
1033 IN PTXWI_STRUC pOutTxWI,
1034 IN BOOLEAN FRAG,
1035 IN BOOLEAN CFACK,
1036 IN BOOLEAN InsTimestamp,
1037 IN BOOLEAN AMPDU,
1038 IN BOOLEAN Ack,
1039 IN BOOLEAN NSeq, // HW new a sequence.
1040 IN UCHAR BASize,
1041 IN UCHAR WCID,
1042 IN ULONG Length,
1043 IN UCHAR PID,
1044 IN UCHAR TID,
1045 IN UCHAR TxRate,
1046 IN UCHAR Txopmode,
1047 IN BOOLEAN CfAck,
1048 IN HTTRANSMIT_SETTING *pTransmit)
1050 PMAC_TABLE_ENTRY pMac = NULL;
1051 TXWI_STRUC TxWI;
1052 PTXWI_STRUC pTxWI;
1054 if (WCID < MAX_LEN_OF_MAC_TABLE)
1055 pMac = &pAd->MacTab.Content[WCID];
1058 // Always use Long preamble before verifiation short preamble functionality works well.
1059 // Todo: remove the following line if short preamble functionality works
1061 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1062 NdisZeroMemory(&TxWI, TXWI_SIZE);
1063 pTxWI = &TxWI;
1065 pTxWI->FRAG= FRAG;
1067 pTxWI->CFACK = CFACK;
1068 pTxWI->TS= InsTimestamp;
1069 pTxWI->AMPDU = AMPDU;
1070 pTxWI->ACK = Ack;
1071 pTxWI->txop= Txopmode;
1073 pTxWI->NSEQ = NSeq;
1074 // John tune the performace with Intel Client in 20 MHz performance
1075 #ifdef DOT11_N_SUPPORT
1076 BASize = pAd->CommonCfg.TxBASize;
1078 if( BASize >7 )
1079 BASize =7;
1080 pTxWI->BAWinSize = BASize;
1081 pTxWI->ShortGI = pTransmit->field.ShortGI;
1082 pTxWI->STBC = pTransmit->field.STBC;
1083 #endif // DOT11_N_SUPPORT //
1085 pTxWI->WirelessCliID = WCID;
1086 pTxWI->MPDUtotalByteCount = Length;
1087 pTxWI->PacketId = PID;
1089 // If CCK or OFDM, BW must be 20
1090 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1092 pTxWI->MCS = pTransmit->field.MCS;
1093 pTxWI->PHYMODE = pTransmit->field.MODE;
1094 pTxWI->CFACK = CfAck;
1096 #ifdef DOT11_N_SUPPORT
1097 if (pMac)
1099 if (pAd->CommonCfg.bMIMOPSEnable)
1101 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1103 // Dynamic MIMO Power Save Mode
1104 pTxWI->MIMOps = 1;
1106 else if (pMac->MmpsMode == MMPS_STATIC)
1108 // Static MIMO Power Save Mode
1109 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1111 pTxWI->MCS = 7;
1112 pTxWI->MIMOps = 0;
1116 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1117 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1119 pTxWI->MpduDensity = 7;
1121 else
1123 pTxWI->MpduDensity = pMac->MpduDensity;
1126 #endif // DOT11_N_SUPPORT //
1128 pTxWI->PacketId = pTxWI->MCS;
1129 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1133 VOID RTMPWriteTxWI_Data(
1134 IN PRTMP_ADAPTER pAd,
1135 IN OUT PTXWI_STRUC pTxWI,
1136 IN TX_BLK *pTxBlk)
1138 HTTRANSMIT_SETTING *pTransmit;
1139 PMAC_TABLE_ENTRY pMacEntry;
1140 #ifdef DOT11_N_SUPPORT
1141 UCHAR BASize;
1142 #endif // DOT11_N_SUPPORT //
1145 ASSERT(pTxWI);
1147 pTransmit = pTxBlk->pTransmit;
1148 pMacEntry = pTxBlk->pMacEntry;
1152 // Always use Long preamble before verifiation short preamble functionality works well.
1153 // Todo: remove the following line if short preamble functionality works
1155 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1156 NdisZeroMemory(pTxWI, TXWI_SIZE);
1158 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1159 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1160 pTxWI->txop = pTxBlk->FrameGap;
1162 pTxWI->WirelessCliID = pTxBlk->Wcid;
1164 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1165 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1167 // If CCK or OFDM, BW must be 20
1168 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1169 #ifdef DOT11_N_SUPPORT
1170 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1172 // John tune the performace with Intel Client in 20 MHz performance
1173 BASize = pAd->CommonCfg.TxBASize;
1174 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1176 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1178 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1179 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1182 #if 0 // 3*3
1183 if (BASize > 7)
1184 BASize = 7;
1185 #endif
1187 pTxWI->TxBF = pTransmit->field.TxBF;
1188 pTxWI->BAWinSize = BASize;
1189 pTxWI->ShortGI = pTransmit->field.ShortGI;
1190 pTxWI->STBC = pTransmit->field.STBC;
1191 #endif // DOT11_N_SUPPORT //
1193 pTxWI->MCS = pTransmit->field.MCS;
1194 pTxWI->PHYMODE = pTransmit->field.MODE;
1196 #ifdef DOT11_N_SUPPORT
1197 if (pMacEntry)
1199 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1201 // Dynamic MIMO Power Save Mode
1202 pTxWI->MIMOps = 1;
1204 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1206 // Static MIMO Power Save Mode
1207 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1209 pTxWI->MCS = 7;
1210 pTxWI->MIMOps = 0;
1214 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1216 pTxWI->MpduDensity = 7;
1218 else
1220 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1223 #endif // DOT11_N_SUPPORT //
1225 #ifdef DBG_DIAGNOSE
1226 if (pTxBlk->QueIdx== 0)
1228 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1229 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1231 #endif // DBG_DIAGNOSE //
1233 // for rate adapation
1234 pTxWI->PacketId = pTxWI->MCS;
1238 VOID RTMPWriteTxWI_Cache(
1239 IN PRTMP_ADAPTER pAd,
1240 IN OUT PTXWI_STRUC pTxWI,
1241 IN TX_BLK *pTxBlk)
1243 PHTTRANSMIT_SETTING /*pTxHTPhyMode,*/ pTransmit;
1244 PMAC_TABLE_ENTRY pMacEntry;
1247 // update TXWI
1249 pMacEntry = pTxBlk->pMacEntry;
1250 pTransmit = pTxBlk->pTransmit;
1252 if (pMacEntry->bAutoTxRateSwitch)
1254 pTxWI->txop = IFS_HTTXOP;
1256 // If CCK or OFDM, BW must be 20
1257 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1258 pTxWI->ShortGI = pTransmit->field.ShortGI;
1259 pTxWI->STBC = pTransmit->field.STBC;
1261 pTxWI->MCS = pTransmit->field.MCS;
1262 pTxWI->PHYMODE = pTransmit->field.MODE;
1264 // set PID for TxRateSwitching
1265 pTxWI->PacketId = pTransmit->field.MCS;
1268 #ifdef DOT11_N_SUPPORT
1269 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1270 pTxWI->MIMOps = 0;
1272 if (pAd->CommonCfg.bMIMOPSEnable)
1274 // MIMO Power Save Mode
1275 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1277 // Dynamic MIMO Power Save Mode
1278 pTxWI->MIMOps = 1;
1280 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1282 // Static MIMO Power Save Mode
1283 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1285 pTxWI->MCS = 7;
1286 pTxWI->MIMOps = 0;
1290 #endif // DOT11_N_SUPPORT //
1292 #ifdef DBG_DIAGNOSE
1293 if (pTxBlk->QueIdx== 0)
1295 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1296 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1298 #endif // DBG_DIAGNOSE //
1300 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1306 ========================================================================
1308 Routine Description:
1309 Calculates the duration which is required to transmit out frames
1310 with given size and specified rate.
1312 Arguments:
1313 pTxD Pointer to transmit descriptor
1314 Ack Setting for Ack requirement bit
1315 Fragment Setting for Fragment bit
1316 RetryMode Setting for retry mode
1317 Ifs Setting for IFS gap
1318 Rate Setting for transmit rate
1319 Service Setting for service
1320 Length Frame length
1321 TxPreamble Short or Long preamble when using CCK rates
1322 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1324 Return Value:
1325 None
1327 IRQL = PASSIVE_LEVEL
1328 IRQL = DISPATCH_LEVEL
1330 ========================================================================
1332 VOID RTMPWriteTxDescriptor(
1333 IN PRTMP_ADAPTER pAd,
1334 IN PTXD_STRUC pTxD,
1335 IN BOOLEAN bWIV,
1336 IN UCHAR QueueSEL)
1339 // Always use Long preamble before verifiation short preamble functionality works well.
1340 // Todo: remove the following line if short preamble functionality works
1342 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1344 pTxD->WIV = (bWIV) ? 1: 0;
1345 pTxD->QSEL= (QueueSEL);
1346 //RT2860c?? fixed using EDCA queue for test... We doubt Queue1 has problem. 2006-09-26 Jan
1347 //pTxD->QSEL= FIFO_EDCA;
1348 if (pAd->bGenOneHCCA == TRUE)
1349 pTxD->QSEL= FIFO_HCCA;
1350 pTxD->DMADONE = 0;
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)
1365 // can't aggregate EAPOL (802.1x) frame
1366 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1367 return FALSE;
1369 // can't aggregate multicast/broadcast frame
1370 if (p8023hdr[0] & 0x01)
1371 return FALSE;
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;
1383 ========================================================================
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.
1390 Arguments:
1392 Return Value:
1394 Note:
1396 ========================================================================
1398 BOOLEAN PeerIsAggreOn(
1399 IN PRTMP_ADAPTER pAd,
1400 IN ULONG TxRate,
1401 IN PMAC_TABLE_ENTRY pMacEntry)
1403 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1405 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1407 #ifdef DOT11_N_SUPPORT
1408 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1410 return TRUE;
1412 #endif // DOT11_N_SUPPORT //
1414 #ifdef AGGREGATION_SUPPORT
1415 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1416 { // legacy Ralink Aggregation support
1417 return TRUE;
1419 #endif // AGGREGATION_SUPPORT //
1422 return FALSE;
1427 ========================================================================
1429 Routine Description:
1430 Check and fine the packet waiting in SW queue with highest priority
1432 Arguments:
1433 pAd Pointer to our adapter
1435 Return Value:
1436 pQueue Pointer to Waiting Queue
1438 IRQL = DISPATCH_LEVEL
1440 Note:
1442 ========================================================================
1444 PQUEUE_HEADER RTMPCheckTxSwQueue(
1445 IN PRTMP_ADAPTER pAd,
1446 OUT PUCHAR pQueIdx)
1449 ULONG Number;
1450 // 2004-11-15 to be removed. test aggregation only
1451 // if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2))
1452 // return NULL;
1454 Number = pAd->TxSwQueue[QID_AC_BK].Number
1455 + pAd->TxSwQueue[QID_AC_BE].Number
1456 + pAd->TxSwQueue[QID_AC_VI].Number
1457 + pAd->TxSwQueue[QID_AC_VO].Number
1458 + pAd->TxSwQueue[QID_HCCA].Number;
1460 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1462 *pQueIdx = QID_AC_VO;
1463 return (&pAd->TxSwQueue[QID_AC_VO]);
1465 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1467 *pQueIdx = QID_AC_VI;
1468 return (&pAd->TxSwQueue[QID_AC_VI]);
1470 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1472 *pQueIdx = QID_AC_BE;
1473 return (&pAd->TxSwQueue[QID_AC_BE]);
1475 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1477 *pQueIdx = QID_AC_BK;
1478 return (&pAd->TxSwQueue[QID_AC_BK]);
1480 else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1482 *pQueIdx = QID_HCCA;
1483 return (&pAd->TxSwQueue[QID_HCCA]);
1486 // No packet pending in Tx Sw queue
1487 *pQueIdx = QID_AC_BK;
1489 return (NULL);
1495 ========================================================================
1497 Routine Description:
1498 Suspend MSDU transmission
1500 Arguments:
1501 pAd Pointer to our adapter
1503 Return Value:
1504 None
1506 Note:
1508 ========================================================================
1510 VOID RTMPSuspendMsduTransmission(
1511 IN PRTMP_ADAPTER pAd)
1513 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1517 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1518 // use Lowbound as R66 value on ScanNextChannel(...)
1520 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1522 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1523 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
1524 RTMPSetAGCInitValue(pAd, BW_20);
1526 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1527 //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings
1532 ========================================================================
1534 Routine Description:
1535 Resume MSDU transmission
1537 Arguments:
1538 pAd Pointer to our adapter
1540 Return Value:
1541 None
1543 IRQL = DISPATCH_LEVEL
1545 Note:
1547 ========================================================================
1549 VOID RTMPResumeMsduTransmission(
1550 IN PRTMP_ADAPTER pAd)
1552 // UCHAR IrqState;
1554 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1557 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1559 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1560 // sample, for IRQ LOCK to SEM LOCK
1561 // IrqState = pAd->irq_disabled;
1562 // if (IrqState)
1563 // RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1564 // else
1565 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1569 UINT deaggregate_AMSDU_announce(
1570 IN PRTMP_ADAPTER pAd,
1571 PNDIS_PACKET pPacket,
1572 IN PUCHAR pData,
1573 IN ULONG DataSize)
1575 USHORT PayloadSize;
1576 USHORT SubFrameSize;
1577 PHEADER_802_3 pAMSDUsubheader;
1578 UINT nMSDU;
1579 UCHAR Header802_3[14];
1581 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
1582 PNDIS_PACKET pClonePacket;
1586 nMSDU = 0;
1588 while (DataSize > LENGTH_802_3)
1591 nMSDU++;
1593 //hex_dump("subheader", pData, 64);
1594 pAMSDUsubheader = (PHEADER_802_3)pData;
1595 //pData += LENGTH_802_3;
1596 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1597 SubFrameSize = PayloadSize + LENGTH_802_3;
1600 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
1602 break;
1605 //printk("%d subframe: Size = %d\n", nMSDU, PayloadSize);
1607 pPayload = pData + LENGTH_802_3;
1608 pDA = pData;
1609 pSA = pData + MAC_ADDR_LEN;
1611 // convert to 802.3 header
1612 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
1614 #ifdef CONFIG_STA_SUPPORT
1615 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
1617 // avoid local heap overflow, use dyanamic allocation
1618 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1619 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
1620 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
1621 WpaEAPOLKeyAction(pAd, Elem);
1622 kfree(Elem);
1624 #endif // CONFIG_STA_SUPPORT //
1626 #ifdef CONFIG_STA_SUPPORT
1627 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1629 if (pRemovedLLCSNAP)
1631 pPayload -= LENGTH_802_3;
1632 PayloadSize += LENGTH_802_3;
1633 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
1636 #endif // CONFIG_STA_SUPPORT //
1638 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1639 if (pClonePacket)
1641 #ifdef CONFIG_STA_SUPPORT
1642 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1643 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
1644 #endif // CONFIG_STA_SUPPORT //
1648 // A-MSDU has padding to multiple of 4 including subframe header.
1649 // align SubFrameSize up to multiple of 4
1650 SubFrameSize = (SubFrameSize+3)&(~0x3);
1653 if (SubFrameSize > 1528 || SubFrameSize < 32)
1655 break;
1658 if (DataSize > SubFrameSize)
1660 pData += SubFrameSize;
1661 DataSize -= SubFrameSize;
1663 else
1665 // end of A-MSDU
1666 DataSize = 0;
1670 // finally release original rx packet
1671 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1673 return nMSDU;
1677 UINT BA_Reorder_AMSDU_Annnounce(
1678 IN PRTMP_ADAPTER pAd,
1679 IN PNDIS_PACKET pPacket)
1681 PUCHAR pData;
1682 USHORT DataSize;
1683 UINT nMSDU = 0;
1685 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1686 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1688 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1690 return nMSDU;
1695 ==========================================================================
1696 Description:
1697 Look up the MAC address in the MAC table. Return NULL if not found.
1698 Return:
1699 pEntry - pointer to the MAC entry; NULL is not found
1700 ==========================================================================
1702 MAC_TABLE_ENTRY *MacTableLookup(
1703 IN PRTMP_ADAPTER pAd,
1704 PUCHAR pAddr)
1706 ULONG HashIdx;
1707 MAC_TABLE_ENTRY *pEntry = NULL;
1709 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1710 pEntry = pAd->MacTab.Hash[HashIdx];
1712 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
1714 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1716 break;
1718 else
1719 pEntry = pEntry->pNext;
1722 return pEntry;
1725 MAC_TABLE_ENTRY *MacTableInsertEntry(
1726 IN PRTMP_ADAPTER pAd,
1727 IN PUCHAR pAddr,
1728 IN UCHAR apidx,
1729 IN BOOLEAN CleanAll)
1731 UCHAR HashIdx;
1732 int i, FirstWcid;
1733 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1735 // if FULL, return
1736 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1737 return NULL;
1739 FirstWcid = 1;
1740 #ifdef CONFIG_STA_SUPPORT
1741 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1742 if (pAd->StaCfg.BssType == BSS_INFRA)
1743 FirstWcid = 2;
1744 #endif // CONFIG_STA_SUPPORT //
1746 // allocate one MAC entry
1747 NdisAcquireSpinLock(&pAd->MacTabLock);
1748 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
1750 // pick up the first available vacancy
1751 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1752 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1753 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
1754 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1757 pEntry = &pAd->MacTab.Content[i];
1758 if (CleanAll == TRUE)
1760 pEntry->MaxSupportedRate = RATE_11;
1761 pEntry->CurrTxRate = RATE_11;
1762 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1763 pEntry->PairwiseKey.KeyLen = 0;
1764 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1768 #ifdef CONFIG_STA_SUPPORT
1769 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1771 pEntry->ValidAsCLI = TRUE;
1772 pEntry->ValidAsWDS = FALSE;
1773 pEntry->ValidAsApCli = FALSE;
1774 pEntry->ValidAsMesh = FALSE;
1775 pEntry->ValidAsDls = FALSE;
1777 #endif // CONFIG_STA_SUPPORT //
1780 pEntry->bIAmBadAtheros = FALSE;
1781 pEntry->pAd = pAd;
1782 pEntry->CMTimerRunning = FALSE;
1783 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1784 pEntry->RSNIE_Len = 0;
1785 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
1786 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1788 if (pEntry->ValidAsMesh)
1789 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
1790 else if (pEntry->ValidAsApCli)
1791 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
1792 else if (pEntry->ValidAsWDS)
1793 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
1794 else
1795 pEntry->apidx = apidx;
1799 #ifdef CONFIG_STA_SUPPORT
1800 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1802 pEntry->AuthMode = pAd->StaCfg.AuthMode;
1803 pEntry->WepStatus = pAd->StaCfg.WepStatus;
1804 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1806 #endif // CONFIG_STA_SUPPORT //
1809 pEntry->GTKState = REKEY_NEGOTIATING;
1810 pEntry->PairwiseKey.KeyLen = 0;
1811 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1812 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1813 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1814 COPY_MAC_ADDR(pEntry->Addr, pAddr);
1815 pEntry->Sst = SST_NOT_AUTH;
1816 pEntry->AuthState = AS_NOT_AUTH;
1817 pEntry->Aid = (USHORT)i; //0;
1818 pEntry->CapabilityInfo = 0;
1819 pEntry->PsMode = PWR_ACTIVE;
1820 pEntry->PsQIdleCount = 0;
1821 pEntry->NoDataIdleCount = 0;
1822 pEntry->ContinueTxFailCnt = 0;
1823 InitializeQueueHeader(&pEntry->PsQueue);
1826 pAd->MacTab.Size ++;
1827 // Add this entry into ASIC RX WCID search table
1828 RT28XX_STA_ENTRY_ADD(pAd, pEntry);
1830 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
1831 break;
1835 // add this MAC entry into HASH table
1836 if (pEntry)
1838 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1839 if (pAd->MacTab.Hash[HashIdx] == NULL)
1841 pAd->MacTab.Hash[HashIdx] = pEntry;
1843 else
1845 pCurrEntry = pAd->MacTab.Hash[HashIdx];
1846 while (pCurrEntry->pNext != NULL)
1847 pCurrEntry = pCurrEntry->pNext;
1848 pCurrEntry->pNext = pEntry;
1852 NdisReleaseSpinLock(&pAd->MacTabLock);
1853 return pEntry;
1857 ==========================================================================
1858 Description:
1859 Delete a specified client from MAC table
1860 ==========================================================================
1862 BOOLEAN MacTableDeleteEntry(
1863 IN PRTMP_ADAPTER pAd,
1864 IN USHORT wcid,
1865 IN PUCHAR pAddr)
1867 USHORT HashIdx;
1868 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1869 BOOLEAN Cancelled;
1870 //USHORT offset; // unused variable
1871 //UCHAR j; // unused variable
1873 if (wcid >= MAX_LEN_OF_MAC_TABLE)
1874 return FALSE;
1876 NdisAcquireSpinLock(&pAd->MacTabLock);
1878 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1879 //pEntry = pAd->MacTab.Hash[HashIdx];
1880 pEntry = &pAd->MacTab.Content[wcid];
1882 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
1885 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1888 // Delete this entry from ASIC on-chip WCID Table
1889 RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
1891 #ifdef DOT11_N_SUPPORT
1892 // free resources of BA
1893 BASessionTearDownALL(pAd, pEntry->Aid);
1894 #endif // DOT11_N_SUPPORT //
1897 pPrevEntry = NULL;
1898 pProbeEntry = pAd->MacTab.Hash[HashIdx];
1899 ASSERT(pProbeEntry);
1901 // update Hash list
1904 if (pProbeEntry == pEntry)
1906 if (pPrevEntry == NULL)
1908 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
1910 else
1912 pPrevEntry->pNext = pEntry->pNext;
1914 break;
1917 pPrevEntry = pProbeEntry;
1918 pProbeEntry = pProbeEntry->pNext;
1919 } while (pProbeEntry);
1921 // not found !!!
1922 ASSERT(pProbeEntry != NULL);
1924 RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1927 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
1929 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
1930 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1934 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1935 pAd->MacTab.Size --;
1936 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
1938 else
1940 printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
1944 NdisReleaseSpinLock(&pAd->MacTabLock);
1946 //Reset operating mode when no Sta.
1947 if (pAd->MacTab.Size == 0)
1949 #ifdef DOT11_N_SUPPORT
1950 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
1951 #endif // DOT11_N_SUPPORT //
1952 AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
1955 return TRUE;
1960 ==========================================================================
1961 Description:
1962 This routine reset the entire MAC table. All packets pending in
1963 the power-saving queues are freed here.
1964 ==========================================================================
1966 VOID MacTableReset(
1967 IN PRTMP_ADAPTER pAd)
1969 int i;
1971 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
1972 //NdisAcquireSpinLock(&pAd->MacTabLock);
1974 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
1976 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
1979 #ifdef DOT11_N_SUPPORT
1980 // free resources of BA
1981 BASessionTearDownALL(pAd, i);
1982 #endif // DOT11_N_SUPPORT //
1984 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
1988 #ifdef RT2870
1989 NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
1990 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
1991 #endif // RT2870 //
1993 //AsicDelWcidTab(pAd, i);
1997 return;
2001 ==========================================================================
2002 Description:
2004 IRQL = DISPATCH_LEVEL
2006 ==========================================================================
2008 VOID AssocParmFill(
2009 IN PRTMP_ADAPTER pAd,
2010 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2011 IN PUCHAR pAddr,
2012 IN USHORT CapabilityInfo,
2013 IN ULONG Timeout,
2014 IN USHORT ListenIntv)
2016 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2017 // Add mask to support 802.11b mode only
2018 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2019 AssocReq->Timeout = Timeout;
2020 AssocReq->ListenIntv = ListenIntv;
2025 ==========================================================================
2026 Description:
2028 IRQL = DISPATCH_LEVEL
2030 ==========================================================================
2032 VOID DisassocParmFill(
2033 IN PRTMP_ADAPTER pAd,
2034 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2035 IN PUCHAR pAddr,
2036 IN USHORT Reason)
2038 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2039 DisassocReq->Reason = Reason;
2044 ========================================================================
2046 Routine Description:
2047 Check the out going frame, if this is an DHCP or ARP datagram
2048 will be duplicate another frame at low data rate transmit.
2050 Arguments:
2051 pAd Pointer to our adapter
2052 pPacket Pointer to outgoing Ndis frame
2054 Return Value:
2055 TRUE To be duplicate at Low data rate transmit. (1mb)
2056 FALSE Do nothing.
2058 IRQL = DISPATCH_LEVEL
2060 Note:
2062 MAC header + IP Header + UDP Header
2063 14 Bytes 20 Bytes
2065 UDP Header
2066 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2067 Source Port
2068 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2069 Destination Port
2071 port 0x43 means Bootstrap Protocol, server.
2072 Port 0x44 means Bootstrap Protocol, client.
2074 ========================================================================
2077 BOOLEAN RTMPCheckDHCPFrame(
2078 IN PRTMP_ADAPTER pAd,
2079 IN PNDIS_PACKET pPacket)
2081 PACKET_INFO PacketInfo;
2082 ULONG NumberOfBytesRead = 0;
2083 ULONG CurrentOffset = 0;
2084 PVOID pVirtualAddress = NULL;
2085 UINT NdisBufferLength;
2086 PUCHAR pSrc;
2087 USHORT Protocol;
2088 UCHAR ByteOffset36 = 0;
2089 UCHAR ByteOffset38 = 0;
2090 BOOLEAN ReadFirstParm = TRUE;
2092 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2094 NumberOfBytesRead += NdisBufferLength;
2095 pSrc = (PUCHAR) pVirtualAddress;
2096 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2099 // Check DHCP & BOOTP protocol
2101 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2103 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2105 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2106 ByteOffset36 = *(pSrc + CurrentOffset);
2107 ReadFirstParm = FALSE;
2110 if (NumberOfBytesRead >= 37)
2112 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2113 ByteOffset38 = *(pSrc + CurrentOffset);
2114 //End of Read
2115 break;
2117 return FALSE;
2120 // Check for DHCP & BOOTP protocol
2121 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2124 // 2054 (hex 0806) for ARP datagrams
2125 // if this packet is not ARP datagrams, then do nothing
2126 // ARP datagrams will also be duplicate at 1mb broadcast frames
2128 if (Protocol != 0x0806 )
2129 return FALSE;
2132 return TRUE;
2136 BOOLEAN RTMPCheckEtherType(
2137 IN PRTMP_ADAPTER pAd,
2138 IN PNDIS_PACKET pPacket)
2140 USHORT TypeLen;
2141 UCHAR Byte0, Byte1;
2142 PUCHAR pSrcBuf;
2143 UINT32 pktLen;
2144 UINT16 srcPort, dstPort;
2145 BOOLEAN status = TRUE;
2148 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2149 pktLen = GET_OS_PKT_LEN(pPacket);
2151 ASSERT(pSrcBuf);
2153 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2155 // get Ethernet protocol field
2156 TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2158 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
2160 if (TypeLen <= 1500)
2161 { // 802.3, 802.3 LLC
2163 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2164 DSAP(1) + SSAP(1) + Control(1) +
2165 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2166 => + SNAP (5, OriginationID(3) + etherType(2))
2168 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2170 Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2171 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2172 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2173 pSrcBuf += 8; // Skip this LLC/SNAP header
2175 else
2177 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2181 // If it's a VLAN packet, get the real Type/Length field.
2182 if (TypeLen == 0x8100)
2184 /* 0x8100 means VLAN packets */
2186 /* Dest. MAC Address (6-bytes) +
2187 Source MAC Address (6-bytes) +
2188 Length/Type = 802.1Q Tag Type (2-byte) +
2189 Tag Control Information (2-bytes) +
2190 Length / Type (2-bytes) +
2191 data payload (0-n bytes) +
2192 Pad (0-p bytes) +
2193 Frame Check Sequence (4-bytes) */
2195 RTMP_SET_PACKET_VLAN(pPacket, 1);
2196 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2197 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2199 pSrcBuf += 4; // Skip the VLAN Header.
2202 switch (TypeLen)
2204 case 0x0800:
2206 ASSERT((pktLen > 34));
2207 if (*(pSrcBuf + 9) == 0x11)
2208 { // udp packet
2209 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
2211 pSrcBuf += 20; // Skip the IP header
2212 srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2213 dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2215 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2216 { //It's a BOOTP/DHCP packet
2217 RTMP_SET_PACKET_DHCP(pPacket, 1);
2221 break;
2222 case 0x0806:
2224 //ARP Packet.
2225 RTMP_SET_PACKET_DHCP(pPacket, 1);
2227 break;
2228 case 0x888e:
2230 // EAPOL Packet.
2231 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2233 break;
2234 default:
2235 status = FALSE;
2236 break;
2239 return status;
2245 VOID Update_Rssi_Sample(
2246 IN PRTMP_ADAPTER pAd,
2247 IN RSSI_SAMPLE *pRssi,
2248 IN PRXWI_STRUC pRxWI)
2250 CHAR rssi0 = pRxWI->RSSI0;
2251 CHAR rssi1 = pRxWI->RSSI1;
2252 CHAR rssi2 = pRxWI->RSSI2;
2254 if (rssi0 != 0)
2256 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2257 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2258 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2261 if (rssi1 != 0)
2263 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2264 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2265 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2268 if (rssi2 != 0)
2270 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2271 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2272 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2278 // Normal legacy Rx packet indication
2279 VOID Indicate_Legacy_Packet(
2280 IN PRTMP_ADAPTER pAd,
2281 IN RX_BLK *pRxBlk,
2282 IN UCHAR FromWhichBSSID)
2284 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2285 UCHAR Header802_3[LENGTH_802_3];
2287 // 1. get 802.3 Header
2288 // 2. remove LLC
2289 // a. pointer pRxBlk->pData to payload
2290 // b. modify pRxBlk->DataSize
2291 #ifdef CONFIG_STA_SUPPORT
2292 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2293 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2294 #endif // CONFIG_STA_SUPPORT //
2296 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2298 #if 0 // sample take off, for multiple card design
2299 static int err_size;
2301 err_size++;
2302 if (err_size > 20)
2304 printk("Legacy DataSize = %d\n", pRxBlk->DataSize);
2305 hex_dump("802.3 Header", Header802_3, LENGTH_802_3);
2306 hex_dump("Payload", pRxBlk->pData, 64);
2307 err_size = 0;
2309 #endif
2311 // release packet
2312 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2313 return;
2317 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2319 #ifdef RT2870
2320 #ifdef DOT11_N_SUPPORT
2321 if (pAd->CommonCfg.bDisableReordering == 0)
2323 PBA_REC_ENTRY pBAEntry;
2324 ULONG Now32;
2325 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
2326 UCHAR TID = pRxBlk->pRxWI->TID;
2327 USHORT Idx;
2329 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
2331 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2333 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2334 if (Idx != 0)
2336 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2337 // update last rx time
2338 NdisGetSystemUpTime(&Now32);
2339 if ((pBAEntry->list.qlen > 0) &&
2340 RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2343 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);
2344 hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2345 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2350 #endif // DOT11_N_SUPPORT //
2351 #endif // RT2870 //
2353 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2356 // pass this 802.3 packet to upper layer or forward this packet to WM directly
2358 #ifdef CONFIG_STA_SUPPORT
2359 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2360 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2361 #endif // CONFIG_STA_SUPPORT //
2366 // Normal, AMPDU or AMSDU
2367 VOID CmmRxnonRalinkFrameIndicate(
2368 IN PRTMP_ADAPTER pAd,
2369 IN RX_BLK *pRxBlk,
2370 IN UCHAR FromWhichBSSID)
2372 #ifdef DOT11_N_SUPPORT
2373 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2375 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2377 else
2378 #endif // DOT11_N_SUPPORT //
2380 #ifdef DOT11_N_SUPPORT
2381 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2383 // handle A-MSDU
2384 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2386 else
2387 #endif // DOT11_N_SUPPORT //
2389 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2395 VOID CmmRxRalinkFrameIndicate(
2396 IN PRTMP_ADAPTER pAd,
2397 IN MAC_TABLE_ENTRY *pEntry,
2398 IN RX_BLK *pRxBlk,
2399 IN UCHAR FromWhichBSSID)
2401 UCHAR Header802_3[LENGTH_802_3];
2402 UINT16 Msdu2Size;
2403 UINT16 Payload1Size, Payload2Size;
2404 PUCHAR pData2;
2405 PNDIS_PACKET pPacket2 = NULL;
2409 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2411 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2413 /* skip two byte MSDU2 len */
2414 pRxBlk->pData += 2;
2415 pRxBlk->DataSize -= 2;
2417 else
2419 // release packet
2420 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2421 return;
2424 // get 802.3 Header and remove LLC
2425 #ifdef CONFIG_STA_SUPPORT
2426 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2427 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2428 #endif // CONFIG_STA_SUPPORT //
2431 ASSERT(pRxBlk->pRxPacket);
2433 // Ralink Aggregation frame
2434 pAd->RalinkCounters.OneSecRxAggregationCount ++;
2435 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2436 Payload2Size = Msdu2Size - LENGTH_802_3;
2438 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2439 #ifdef CONFIG_STA_SUPPORT
2440 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2441 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2442 #endif // CONFIG_STA_SUPPORT //
2444 if (!pPacket2)
2446 // release packet
2447 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2448 return;
2451 // update payload size of 1st packet
2452 pRxBlk->DataSize = Payload1Size;
2453 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2455 #ifdef CONFIG_STA_SUPPORT
2456 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2457 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2458 #endif // CONFIG_STA_SUPPORT //
2460 if (pPacket2)
2462 #ifdef CONFIG_STA_SUPPORT
2463 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2464 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2465 #endif // CONFIG_STA_SUPPORT //
2470 #define RESET_FRAGFRAME(_fragFrame) \
2472 _fragFrame.RxSize = 0; \
2473 _fragFrame.Sequence = 0; \
2474 _fragFrame.LastFrag = 0; \
2475 _fragFrame.Flags = 0; \
2479 PNDIS_PACKET RTMPDeFragmentDataFrame(
2480 IN PRTMP_ADAPTER pAd,
2481 IN RX_BLK *pRxBlk)
2483 PHEADER_802_11 pHeader = pRxBlk->pHeader;
2484 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2485 UCHAR *pData = pRxBlk->pData;
2486 USHORT DataSize = pRxBlk->DataSize;
2487 PNDIS_PACKET pRetPacket = NULL;
2488 UCHAR *pFragBuffer = NULL;
2489 BOOLEAN bReassDone = FALSE;
2490 UCHAR HeaderRoom = 0;
2493 ASSERT(pHeader);
2495 HeaderRoom = pData - (UCHAR *)pHeader;
2497 // Re-assemble the fragmented packets
2498 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
2500 // the first pkt of fragment, record it.
2501 if (pHeader->FC.MoreFrag)
2503 ASSERT(pAd->FragFrame.pFragPacket);
2504 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2505 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2506 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
2507 pAd->FragFrame.Sequence = pHeader->Sequence;
2508 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
2509 ASSERT(pAd->FragFrame.LastFrag == 0);
2510 goto done; // end of processing this frame
2513 else //Middle & End of fragment
2515 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2516 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2518 // Fragment is not the same sequence or out of fragment number order
2519 // Reset Fragment control blk
2520 RESET_FRAGFRAME(pAd->FragFrame);
2521 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2522 goto done; // give up this frame
2524 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2526 // Fragment frame is too large, it exeeds the maximum frame size.
2527 // Reset Fragment control blk
2528 RESET_FRAGFRAME(pAd->FragFrame);
2529 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2530 goto done; // give up this frame
2534 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2535 // In this case, we will dropt it.
2537 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2539 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2540 goto done; // give up this frame
2543 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2545 // concatenate this fragment into the re-assembly buffer
2546 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2547 pAd->FragFrame.RxSize += DataSize;
2548 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
2550 // Last fragment
2551 if (pHeader->FC.MoreFrag == FALSE)
2553 bReassDone = TRUE;
2557 done:
2558 // always release rx fragmented packet
2559 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2561 // return defragmented packet if packet is reassembled completely
2562 // otherwise return NULL
2563 if (bReassDone)
2565 PNDIS_PACKET pNewFragPacket;
2567 // allocate a new packet buffer for fragment
2568 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2569 if (pNewFragPacket)
2571 // update RxBlk
2572 pRetPacket = pAd->FragFrame.pFragPacket;
2573 pAd->FragFrame.pFragPacket = pNewFragPacket;
2574 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2575 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2576 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2577 pRxBlk->pRxPacket = pRetPacket;
2579 else
2581 RESET_FRAGFRAME(pAd->FragFrame);
2585 return pRetPacket;
2589 VOID Indicate_AMSDU_Packet(
2590 IN PRTMP_ADAPTER pAd,
2591 IN RX_BLK *pRxBlk,
2592 IN UCHAR FromWhichBSSID)
2594 UINT nMSDU;
2596 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2597 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2598 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2601 VOID Indicate_EAPOL_Packet(
2602 IN PRTMP_ADAPTER pAd,
2603 IN RX_BLK *pRxBlk,
2604 IN UCHAR FromWhichBSSID)
2606 MAC_TABLE_ENTRY *pEntry = NULL;
2609 #ifdef CONFIG_STA_SUPPORT
2610 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2612 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2613 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2614 return;
2616 #endif // CONFIG_STA_SUPPORT //
2618 if (pEntry == NULL)
2620 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2621 // release packet
2622 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2623 return;
2627 #define BCN_TBTT_OFFSET 64 //defer 64 us
2628 VOID ReSyncBeaconTime(
2629 IN PRTMP_ADAPTER pAd)
2632 UINT32 Offset;
2635 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2637 pAd->TbttTickCount++;
2640 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2641 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2643 if (Offset == (BCN_TBTT_OFFSET-2))
2645 BCN_TIME_CFG_STRUC csr;
2646 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2647 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
2648 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2650 else
2652 if (Offset == (BCN_TBTT_OFFSET-1))
2654 BCN_TIME_CFG_STRUC csr;
2656 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2657 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
2658 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);