Staging: rt2860: fix possible NULL dereferences
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / rt2860 / common / cmm_data.c
blob774fabb0be406b6b549ea141ab83385973fbb9b7
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_sta_aifsn[]={3,7,2,2};
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};
76 ========================================================================
78 Routine Description:
79 API for MLME to transmit management frame to AP (BSS Mode)
80 or station (IBSS Mode)
82 Arguments:
83 pAd Pointer to our adapter
84 pData Pointer to the outgoing 802.11 frame
85 Length Size of outgoing management frame
87 Return Value:
88 NDIS_STATUS_FAILURE
89 NDIS_STATUS_PENDING
90 NDIS_STATUS_SUCCESS
92 IRQL = PASSIVE_LEVEL
93 IRQL = DISPATCH_LEVEL
95 Note:
97 ========================================================================
99 NDIS_STATUS MiniportMMRequest(
100 IN PRTMP_ADAPTER pAd,
101 IN UCHAR QueIdx,
102 IN PUCHAR pData,
103 IN UINT Length)
105 PNDIS_PACKET pPacket;
106 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
107 ULONG FreeNum;
108 #ifdef RT2860
109 unsigned long IrqFlags = 0;
110 #endif
111 UCHAR IrqState;
112 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
114 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
116 QueIdx=3;
118 // 2860C use Tx Ring
120 IrqState = pAd->irq_disabled;
122 #ifdef RT2860
123 if ((pAd->MACVersion == 0x28600100) && (!IrqState))
124 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
125 #endif
128 // Reset is in progress, stop immediately
129 if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
130 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
131 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
133 Status = NDIS_STATUS_FAILURE;
134 break;
137 // Check Free priority queue
138 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
140 // 2860C use Tx Ring
141 if (pAd->MACVersion == 0x28600100)
143 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
145 else
147 FreeNum = GET_MGMTRING_FREENO(pAd);
150 if ((FreeNum > 0))
152 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
153 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
154 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
155 if (Status != NDIS_STATUS_SUCCESS)
157 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
158 break;
161 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
162 //pAd->CommonCfg.MlmeRate = RATE_2;
165 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
166 if (Status != NDIS_STATUS_SUCCESS)
167 RTMPFreeNdisPacket(pAd, pPacket);
169 else
171 pAd->RalinkCounters.MgmtRingFullCount++;
172 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
173 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
176 } while (FALSE);
178 #ifdef RT2860
179 // 2860C use Tx Ring
180 if ((pAd->MACVersion == 0x28600100) && (!IrqState))
181 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
182 #endif
183 return Status;
186 #ifdef RT2860
187 NDIS_STATUS MiniportMMRequestUnlock(
188 IN PRTMP_ADAPTER pAd,
189 IN UCHAR QueIdx,
190 IN PUCHAR pData,
191 IN UINT Length)
193 PNDIS_PACKET pPacket;
194 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
195 ULONG FreeNum;
196 TXWI_STRUC TXWI;
197 ULONG SW_TX_IDX;
198 PTXD_STRUC pTxD;
200 QueIdx = 3;
201 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
205 // Reset is in progress, stop immediately
206 if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
207 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
208 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
210 Status = NDIS_STATUS_FAILURE;
211 break;
214 // Check Free priority queue
215 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
216 // 2860C use Tx Ring
217 if (pAd->MACVersion == 0x28600100)
219 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
220 SW_TX_IDX = pAd->TxRing[QueIdx].TxCpuIdx;
221 pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SW_TX_IDX].AllocVa;
223 else
225 FreeNum = GET_MGMTRING_FREENO(pAd);
226 SW_TX_IDX = pAd->MgmtRing.TxCpuIdx;
227 pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SW_TX_IDX].AllocVa;
229 if ((FreeNum > 0))
231 NdisZeroMemory(&TXWI, TXWI_SIZE);
232 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&TXWI, TXWI_SIZE, pData, Length);
233 if (Status != NDIS_STATUS_SUCCESS)
235 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
236 break;
239 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
240 if (Status != NDIS_STATUS_SUCCESS)
241 RTMPFreeNdisPacket(pAd, pPacket);
243 else
245 pAd->RalinkCounters.MgmtRingFullCount++;
246 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing\n", QueIdx));
249 } while (FALSE);
252 return Status;
254 #endif
257 ========================================================================
259 Routine Description:
260 Copy frame from waiting queue into relative ring buffer and set
261 appropriate ASIC register to kick hardware transmit function
263 Arguments:
264 pAd Pointer to our adapter
265 pBuffer Pointer to memory of outgoing frame
266 Length Size of outgoing management frame
268 Return Value:
269 NDIS_STATUS_FAILURE
270 NDIS_STATUS_PENDING
271 NDIS_STATUS_SUCCESS
273 IRQL = PASSIVE_LEVEL
274 IRQL = DISPATCH_LEVEL
276 Note:
278 ========================================================================
280 NDIS_STATUS MlmeHardTransmit(
281 IN PRTMP_ADAPTER pAd,
282 IN UCHAR QueIdx,
283 IN PNDIS_PACKET pPacket)
285 if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
287 return NDIS_STATUS_FAILURE;
290 #ifdef RT2860
291 if ( pAd->MACVersion == 0x28600100 )
292 return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket);
293 else
294 #endif
295 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
299 #ifdef RT2860
300 NDIS_STATUS MlmeHardTransmitTxRing(
301 IN PRTMP_ADAPTER pAd,
302 IN UCHAR QueIdx,
303 IN PNDIS_PACKET pPacket)
305 PACKET_INFO PacketInfo;
306 PUCHAR pSrcBufVA;
307 UINT SrcBufLen;
308 PTXD_STRUC pTxD;
309 PHEADER_802_11 pHeader_802_11;
310 BOOLEAN bAckRequired, bInsertTimestamp;
311 ULONG SrcBufPA;
312 UCHAR MlmeRate;
313 ULONG SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
314 PTXWI_STRUC pFirstTxWI;
315 ULONG FreeNum;
316 MAC_TABLE_ENTRY *pMacEntry = NULL;
319 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
321 if (pSrcBufVA == NULL)
323 // The buffer shouldn't be NULL
324 return NDIS_STATUS_FAILURE;
327 // Make sure MGMT ring resource won't be used by other threads
328 //NdisAcquireSpinLock(&pAd->TxRingLock);
330 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
332 if (FreeNum == 0)
334 //NdisReleaseSpinLock(&pAd->TxRingLock);
335 return NDIS_STATUS_FAILURE;
338 SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
340 pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa;
342 if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket)
344 printk("MlmeHardTransmit Error\n");
345 return NDIS_STATUS_FAILURE;
348 // outgoing frame always wakeup PHY to prevent frame lost
349 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
350 AsicForceWakeup(pAd, FROM_TX);
352 pFirstTxWI =(PTXWI_STRUC)pSrcBufVA;
354 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXWI_SIZE);
355 if (pHeader_802_11->Addr1[0] & 0x01)
357 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
359 else
361 MlmeRate = pAd->CommonCfg.MlmeRate;
364 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
365 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
367 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
370 // Verify Mlme rate for a / g bands.
371 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
372 MlmeRate = RATE_6;
375 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
376 // Snice it's been set to 0 while on MgtMacHeaderInit
377 // By the way this will cause frame to be send on PWR_SAVE failed.
380 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
382 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
383 if (pHeader_802_11->FC.Type != BTYPE_DATA)
385 if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) || !(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
387 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
389 else
391 pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave;
395 bInsertTimestamp = FALSE;
396 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
398 bAckRequired = FALSE;
400 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
402 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
404 bAckRequired = FALSE;
405 pHeader_802_11->Duration = 0;
407 else
409 bAckRequired = TRUE;
410 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
411 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
413 bInsertTimestamp = TRUE;
417 pHeader_802_11->Sequence = pAd->Sequence++;
418 if (pAd->Sequence > 0xfff)
419 pAd->Sequence = 0;
420 // Before radar detection done, mgmt frame can not be sent but probe req
421 // Because we need to use probe req to trigger driver to send probe req in passive scan
422 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
423 && (pAd->CommonCfg.bIEEE80211H == 1)
424 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
426 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
427 return (NDIS_STATUS_FAILURE);
431 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
432 // should always has only one ohysical buffer, and the whole frame size equals
433 // to the first scatter buffer size
436 // Initialize TX Descriptor
437 // For inter-frame gap, the number is for this frame and next frame
438 // For MLME rate, we will fix as 2Mb to match other vendor's implement
440 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
441 // Only beacon use Nseq=TRUE. So here we use Nseq=FALSE.
442 if (pMacEntry == NULL)
444 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
445 0, RESERVED_WCID, (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
447 else
449 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
450 bInsertTimestamp, FALSE, bAckRequired, FALSE,
451 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE),
452 pMacEntry->MaxHTPhyMode.field.MCS, 0,
453 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
454 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
457 pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket;
458 pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL;
460 SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
463 RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA);
464 pTxD->LastSec0 = 1;
465 pTxD->LastSec1 = 1;
466 pTxD->SDLen0 = SrcBufLen;
467 pTxD->SDLen1 = 0;
468 pTxD->SDPtr0 = SrcBufPA;
469 pTxD->DMADONE = 0;
471 pAd->RalinkCounters.KickTxCount++;
472 pAd->RalinkCounters.OneSecTxDoneCount++;
474 // Increase TX_CTX_IDX, but write to register later.
475 INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
477 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10, pAd->TxRing[QueIdx].TxCpuIdx);
479 return NDIS_STATUS_SUCCESS;
481 #endif /* RT2860 */
483 NDIS_STATUS MlmeHardTransmitMgmtRing(
484 IN PRTMP_ADAPTER pAd,
485 IN UCHAR QueIdx,
486 IN PNDIS_PACKET pPacket)
488 PACKET_INFO PacketInfo;
489 PUCHAR pSrcBufVA;
490 UINT SrcBufLen;
491 PHEADER_802_11 pHeader_802_11;
492 BOOLEAN bAckRequired, bInsertTimestamp;
493 UCHAR MlmeRate;
494 PTXWI_STRUC pFirstTxWI;
495 MAC_TABLE_ENTRY *pMacEntry = NULL;
497 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
498 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
501 if (pSrcBufVA == NULL)
503 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
504 return NDIS_STATUS_FAILURE;
507 // outgoing frame always wakeup PHY to prevent frame lost
508 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
509 #ifdef RT2860
510 AsicForceWakeup(pAd, FROM_TX);
511 #endif
512 #ifdef RT2870
513 AsicForceWakeup(pAd, TRUE);
514 #endif
516 pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
517 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
519 if (pHeader_802_11->Addr1[0] & 0x01)
521 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
523 else
525 MlmeRate = pAd->CommonCfg.MlmeRate;
528 // Verify Mlme rate for a / g bands.
529 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
530 MlmeRate = RATE_6;
532 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
533 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
535 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
539 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
540 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
541 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
544 if (pAd->LatchRfRegs.Channel > 14)
545 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
546 else
547 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
552 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
553 // Snice it's been set to 0 while on MgtMacHeaderInit
554 // By the way this will cause frame to be send on PWR_SAVE failed.
556 // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
558 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
560 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
561 if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
563 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
564 (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
565 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
566 else
567 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
570 bInsertTimestamp = FALSE;
571 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
573 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
574 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
576 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
578 bAckRequired = FALSE;
580 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
582 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
584 bAckRequired = FALSE;
585 pHeader_802_11->Duration = 0;
587 else
589 bAckRequired = TRUE;
590 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
591 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
593 bInsertTimestamp = TRUE;
598 pHeader_802_11->Sequence = pAd->Sequence++;
599 if (pAd->Sequence >0xfff)
600 pAd->Sequence = 0;
602 // Before radar detection done, mgmt frame can not be sent but probe req
603 // Because we need to use probe req to trigger driver to send probe req in passive scan
604 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
605 && (pAd->CommonCfg.bIEEE80211H == 1)
606 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
608 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
609 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
610 return (NDIS_STATUS_FAILURE);
614 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
615 // should always has only one ohysical buffer, and the whole frame size equals
616 // to the first scatter buffer size
619 // Initialize TX Descriptor
620 // For inter-frame gap, the number is for this frame and next frame
621 // For MLME rate, we will fix as 2Mb to match other vendor's implement
623 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
624 if (pMacEntry == NULL)
626 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
627 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
629 else
631 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
632 bInsertTimestamp, FALSE, bAckRequired, FALSE,
633 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
634 pMacEntry->MaxHTPhyMode.field.MCS, 0,
635 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
636 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
639 // Now do hardware-depened kick out.
640 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
642 // Make sure to release MGMT ring resource
643 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
644 return NDIS_STATUS_SUCCESS;
648 /********************************************************************************
650 New DeQueue Procedures.
652 ********************************************************************************/
654 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
655 do{ \
656 if (bIntContext == FALSE) \
657 RTMP_IRQ_LOCK((lock), IrqFlags); \
658 }while(0)
660 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
661 do{ \
662 if (bIntContext == FALSE) \
663 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
664 }while(0)
667 ========================================================================
668 Tx Path design algorithm:
669 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
670 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
671 Classification Rule=>
672 Multicast: (*addr1 & 0x01) == 0x01
673 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
674 11N Rate : If peer support HT
675 (1).AMPDU -- If TXBA is negotiated.
676 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
677 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
678 (3).Normal -- Other packets which send as 11n rate.
680 B/G Rate : If peer is b/g only.
681 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
682 (2).Normal -- Other packets which send as b/g rate.
683 Fragment:
684 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
686 Classified Packet Handle Rule=>
687 Multicast:
688 No ACK, //pTxBlk->bAckRequired = FALSE;
689 No WMM, //pTxBlk->bWMM = FALSE;
690 No piggyback, //pTxBlk->bPiggyBack = FALSE;
691 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
692 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
693 the same policy to handle it.
694 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
696 11N Rate :
697 No piggyback, //pTxBlk->bPiggyBack = FALSE;
699 (1).AMSDU
700 pTxBlk->bWMM = TRUE;
701 (2).AMPDU
702 pTxBlk->bWMM = TRUE;
703 (3).Normal
705 B/G Rate :
706 (1).ARALINK
708 (2).Normal
709 ========================================================================
711 static UCHAR TxPktClassification(
712 IN RTMP_ADAPTER *pAd,
713 IN PNDIS_PACKET pPacket)
715 UCHAR TxFrameType = TX_UNKOWN_FRAME;
716 UCHAR Wcid;
717 MAC_TABLE_ENTRY *pMacEntry = NULL;
718 BOOLEAN bHTRate = FALSE;
720 Wcid = RTMP_GET_PACKET_WCID(pPacket);
721 if (Wcid == MCAST_WCID)
722 { // Handle for RA is Broadcast/Multicast Address.
723 return TX_MCAST_FRAME;
726 // Handle for unicast packets
727 pMacEntry = &pAd->MacTab.Content[Wcid];
728 if (RTMP_GET_PACKET_LOWRATE(pPacket))
729 { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
730 TxFrameType = TX_LEGACY_FRAME;
732 else if (IS_HT_RATE(pMacEntry))
733 { // it's a 11n capable packet
735 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
736 // Currently didn't support A-MSDU embedded in A-MPDU
737 bHTRate = TRUE;
738 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
739 TxFrameType = TX_LEGACY_FRAME;
740 #ifdef UAPSD_AP_SUPPORT
741 else if (RTMP_GET_PACKET_EOSP(pPacket))
742 TxFrameType = TX_LEGACY_FRAME;
743 #endif // UAPSD_AP_SUPPORT //
744 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
745 return TX_AMPDU_FRAME;
746 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
747 return TX_AMSDU_FRAME;
748 else
749 TxFrameType = TX_LEGACY_FRAME;
751 else
752 { // it's a legacy b/g packet.
753 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
754 (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
755 (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
756 { // if peer support Ralink Aggregation, we use it.
757 TxFrameType = TX_RALINK_FRAME;
759 else
761 TxFrameType = TX_LEGACY_FRAME;
765 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
766 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
767 TxFrameType = TX_FRAG_FRAME;
769 return TxFrameType;
773 BOOLEAN RTMP_FillTxBlkInfo(
774 IN RTMP_ADAPTER *pAd,
775 IN TX_BLK *pTxBlk)
777 PACKET_INFO PacketInfo;
778 PNDIS_PACKET pPacket;
779 PMAC_TABLE_ENTRY pMacEntry = NULL;
781 pPacket = pTxBlk->pPacket;
782 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
784 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
785 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
786 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
787 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
789 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
790 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
791 else
792 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
794 // Default to clear this flag
795 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
798 if (pTxBlk->Wcid == MCAST_WCID)
800 pTxBlk->pMacEntry = NULL;
802 #ifdef MCAST_RATE_SPECIFIC
803 PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
804 if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
805 pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
806 else
807 #endif // MCAST_RATE_SPECIFIC //
808 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
811 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
812 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
813 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
814 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
815 if (RTMP_GET_PACKET_MOREDATA(pPacket))
817 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
821 else
823 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
824 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
826 pMacEntry = pTxBlk->pMacEntry;
829 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
830 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
831 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
832 else
833 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
836 // If support WMM, enable it.
837 #ifdef RT2860
838 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
839 #endif
840 #ifdef RT2870
841 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
842 CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
843 #endif
844 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
847 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
849 if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
850 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
851 { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
852 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
854 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
855 if (IS_HT_STA(pTxBlk->pMacEntry) &&
856 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
857 ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
859 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
860 TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
864 if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
865 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
866 { // Currently piggy-back only support when peer is operate in b/g mode.
867 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
870 if (RTMP_GET_PACKET_MOREDATA(pPacket))
872 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
874 #ifdef UAPSD_AP_SUPPORT
875 if (RTMP_GET_PACKET_EOSP(pPacket))
877 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
879 #endif // UAPSD_AP_SUPPORT //
881 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
883 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
886 pMacEntry->DebugTxCount++;
889 return TRUE;
893 BOOLEAN CanDoAggregateTransmit(
894 IN RTMP_ADAPTER *pAd,
895 IN NDIS_PACKET *pPacket,
896 IN TX_BLK *pTxBlk)
899 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
901 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
902 return FALSE;
904 if (RTMP_GET_PACKET_DHCP(pPacket) ||
905 RTMP_GET_PACKET_EAPOL(pPacket) ||
906 RTMP_GET_PACKET_WAI(pPacket))
907 return FALSE;
909 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
910 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
911 { // For AMSDU, allow the packets with total length < max-amsdu size
912 return FALSE;
915 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
916 (pTxBlk->TxPacketList.Number == 2))
917 { // For RALINK-Aggregation, allow two frames in one batch.
918 return FALSE;
921 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
922 return TRUE;
923 else
924 return FALSE;
929 ========================================================================
931 Routine Description:
932 To do the enqueue operation and extract the first item of waiting
933 list. If a number of available shared memory segments could meet
934 the request of extracted item, the extracted item will be fragmented
935 into shared memory segments.
937 Arguments:
938 pAd Pointer to our adapter
939 pQueue Pointer to Waiting Queue
941 Return Value:
942 None
944 IRQL = DISPATCH_LEVEL
946 Note:
948 ========================================================================
950 VOID RTMPDeQueuePacket(
951 IN PRTMP_ADAPTER pAd,
952 IN BOOLEAN bIntContext,
953 IN UCHAR QIdx, /* BulkOutPipeId */
954 IN UCHAR Max_Tx_Packets)
956 PQUEUE_ENTRY pEntry = NULL;
957 PNDIS_PACKET pPacket;
958 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
959 UCHAR Count=0;
960 PQUEUE_HEADER pQueue;
961 ULONG FreeNumber[NUM_OF_TX_RING];
962 UCHAR QueIdx, sQIdx, eQIdx;
963 unsigned long IrqFlags = 0;
964 BOOLEAN hasTxDesc = FALSE;
965 TX_BLK TxBlk;
966 TX_BLK *pTxBlk;
970 if (QIdx == NUM_OF_TX_RING)
972 sQIdx = 0;
973 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
974 eQIdx = 3; // 4 ACs, start from 0.
976 else
978 sQIdx = eQIdx = QIdx;
981 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
983 Count=0;
985 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
988 while (1)
990 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
991 fRTMP_ADAPTER_RADIO_OFF |
992 fRTMP_ADAPTER_RESET_IN_PROGRESS |
993 fRTMP_ADAPTER_HALT_IN_PROGRESS |
994 fRTMP_ADAPTER_NIC_NOT_EXIST))))
996 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
997 return;
1000 if (Count >= Max_Tx_Packets)
1001 break;
1003 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1004 if (&pAd->TxSwQueue[QueIdx] == NULL)
1006 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1007 break;
1009 #ifdef RT2860
1010 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1013 if (FreeNumber[QueIdx] <= 5)
1015 // free Tx(QueIdx) resources
1016 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
1017 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1019 #endif /* RT2860 */
1020 // probe the Queue Head
1021 pQueue = &pAd->TxSwQueue[QueIdx];
1022 if ((pEntry = pQueue->Head) == NULL)
1024 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1025 break;
1028 pTxBlk = &TxBlk;
1029 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
1030 pTxBlk->QueIdx = QueIdx;
1032 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1034 // Early check to make sure we have enoguh Tx Resource.
1035 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
1036 if (!hasTxDesc)
1038 pAd->PrivateInfo.TxRingFullCnt++;
1040 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1042 break;
1045 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
1046 pEntry = RemoveHeadQueue(pQueue);
1047 pTxBlk->TotalFrameNum++;
1048 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
1049 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
1050 pTxBlk->pPacket = pPacket;
1051 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
1053 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
1055 // Enhance SW Aggregation Mechanism
1056 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
1058 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
1059 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1060 break;
1064 if((pEntry = pQueue->Head) == NULL)
1065 break;
1067 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
1068 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1069 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1070 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
1071 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
1072 break;
1074 //Remove the packet from the TxSwQueue and insert into pTxBlk
1075 pEntry = RemoveHeadQueue(pQueue);
1076 ASSERT(pEntry);
1077 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1078 pTxBlk->TotalFrameNum++;
1079 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
1080 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
1081 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
1082 }while(1);
1084 if (pTxBlk->TxPacketList.Number == 1)
1085 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
1088 #ifdef RT2870
1089 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1090 #endif // RT2870 //
1092 Count += pTxBlk->TxPacketList.Number;
1094 // Do HardTransmit now.
1095 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
1097 #ifdef RT2860
1098 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1099 // static rate also need NICUpdateFifoStaCounters() function.
1100 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1101 NICUpdateFifoStaCounters(pAd);
1102 #endif
1105 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
1107 #ifdef RT2870
1108 if (!hasTxDesc)
1109 RTUSBKickBulkOut(pAd);
1110 #endif // RT2870 //
1117 ========================================================================
1119 Routine Description:
1120 Calculates the duration which is required to transmit out frames
1121 with given size and specified rate.
1123 Arguments:
1124 pAd Pointer to our adapter
1125 Rate Transmit rate
1126 Size Frame size in units of byte
1128 Return Value:
1129 Duration number in units of usec
1131 IRQL = PASSIVE_LEVEL
1132 IRQL = DISPATCH_LEVEL
1134 Note:
1136 ========================================================================
1138 USHORT RTMPCalcDuration(
1139 IN PRTMP_ADAPTER pAd,
1140 IN UCHAR Rate,
1141 IN ULONG Size)
1143 ULONG Duration = 0;
1145 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
1147 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
1148 Duration = 96; // 72+24 preamble+plcp
1149 else
1150 Duration = 192; // 144+48 preamble+plcp
1152 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
1153 if ((Size << 4) % RateIdTo500Kbps[Rate])
1154 Duration ++;
1156 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
1158 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1159 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
1160 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
1161 Duration += 4;
1163 else //mimo rate
1165 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1168 return (USHORT)Duration;
1173 ========================================================================
1175 Routine Description:
1176 Calculates the duration which is required to transmit out frames
1177 with given size and specified rate.
1179 Arguments:
1180 pTxWI Pointer to head of each MPDU to HW.
1181 Ack Setting for Ack requirement bit
1182 Fragment Setting for Fragment bit
1183 RetryMode Setting for retry mode
1184 Ifs Setting for IFS gap
1185 Rate Setting for transmit rate
1186 Service Setting for service
1187 Length Frame length
1188 TxPreamble Short or Long preamble when using CCK rates
1189 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1191 Return Value:
1192 None
1194 IRQL = PASSIVE_LEVEL
1195 IRQL = DISPATCH_LEVEL
1197 See also : BASmartHardTransmit() !!!
1199 ========================================================================
1201 VOID RTMPWriteTxWI(
1202 IN PRTMP_ADAPTER pAd,
1203 IN PTXWI_STRUC pOutTxWI,
1204 IN BOOLEAN FRAG,
1205 IN BOOLEAN CFACK,
1206 IN BOOLEAN InsTimestamp,
1207 IN BOOLEAN AMPDU,
1208 IN BOOLEAN Ack,
1209 IN BOOLEAN NSeq, // HW new a sequence.
1210 IN UCHAR BASize,
1211 IN UCHAR WCID,
1212 IN ULONG Length,
1213 IN UCHAR PID,
1214 IN UCHAR TID,
1215 IN UCHAR TxRate,
1216 IN UCHAR Txopmode,
1217 IN BOOLEAN CfAck,
1218 IN HTTRANSMIT_SETTING *pTransmit)
1220 PMAC_TABLE_ENTRY pMac = NULL;
1221 TXWI_STRUC TxWI;
1222 PTXWI_STRUC pTxWI;
1224 if (WCID < MAX_LEN_OF_MAC_TABLE)
1225 pMac = &pAd->MacTab.Content[WCID];
1228 // Always use Long preamble before verifiation short preamble functionality works well.
1229 // Todo: remove the following line if short preamble functionality works
1231 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1232 NdisZeroMemory(&TxWI, TXWI_SIZE);
1233 pTxWI = &TxWI;
1235 pTxWI->FRAG= FRAG;
1237 pTxWI->CFACK = CFACK;
1238 pTxWI->TS= InsTimestamp;
1239 pTxWI->AMPDU = AMPDU;
1240 pTxWI->ACK = Ack;
1241 pTxWI->txop= Txopmode;
1243 pTxWI->NSEQ = NSeq;
1244 // John tune the performace with Intel Client in 20 MHz performance
1245 BASize = pAd->CommonCfg.TxBASize;
1247 if( BASize >7 )
1248 BASize =7;
1249 pTxWI->BAWinSize = BASize;
1250 pTxWI->ShortGI = pTransmit->field.ShortGI;
1251 pTxWI->STBC = pTransmit->field.STBC;
1253 pTxWI->WirelessCliID = WCID;
1254 pTxWI->MPDUtotalByteCount = Length;
1255 pTxWI->PacketId = PID;
1257 // If CCK or OFDM, BW must be 20
1258 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1260 pTxWI->MCS = pTransmit->field.MCS;
1261 pTxWI->PHYMODE = pTransmit->field.MODE;
1262 pTxWI->CFACK = CfAck;
1264 if (pMac)
1266 if (pAd->CommonCfg.bMIMOPSEnable)
1268 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1270 // Dynamic MIMO Power Save Mode
1271 pTxWI->MIMOps = 1;
1273 else if (pMac->MmpsMode == MMPS_STATIC)
1275 // Static MIMO Power Save Mode
1276 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1278 pTxWI->MCS = 7;
1279 pTxWI->MIMOps = 0;
1283 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1284 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1286 pTxWI->MpduDensity = 7;
1288 else
1290 pTxWI->MpduDensity = pMac->MpduDensity;
1294 pTxWI->PacketId = pTxWI->MCS;
1295 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1299 VOID RTMPWriteTxWI_Data(
1300 IN PRTMP_ADAPTER pAd,
1301 IN OUT PTXWI_STRUC pTxWI,
1302 IN TX_BLK *pTxBlk)
1304 HTTRANSMIT_SETTING *pTransmit;
1305 PMAC_TABLE_ENTRY pMacEntry;
1306 UCHAR BASize;
1308 ASSERT(pTxWI);
1310 pTransmit = pTxBlk->pTransmit;
1311 pMacEntry = pTxBlk->pMacEntry;
1315 // Always use Long preamble before verifiation short preamble functionality works well.
1316 // Todo: remove the following line if short preamble functionality works
1318 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1319 NdisZeroMemory(pTxWI, TXWI_SIZE);
1321 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1322 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1323 pTxWI->txop = pTxBlk->FrameGap;
1325 pTxWI->WirelessCliID = pTxBlk->Wcid;
1327 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1328 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1330 // If CCK or OFDM, BW must be 20
1331 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1332 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1334 // John tune the performace with Intel Client in 20 MHz performance
1335 BASize = pAd->CommonCfg.TxBASize;
1336 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1338 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1340 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1341 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1344 pTxWI->TxBF = pTransmit->field.TxBF;
1345 pTxWI->BAWinSize = BASize;
1346 pTxWI->ShortGI = pTransmit->field.ShortGI;
1347 pTxWI->STBC = pTransmit->field.STBC;
1349 pTxWI->MCS = pTransmit->field.MCS;
1350 pTxWI->PHYMODE = pTransmit->field.MODE;
1352 if (pMacEntry)
1354 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1356 // Dynamic MIMO Power Save Mode
1357 pTxWI->MIMOps = 1;
1359 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1361 // Static MIMO Power Save Mode
1362 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1364 pTxWI->MCS = 7;
1365 pTxWI->MIMOps = 0;
1369 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1371 pTxWI->MpduDensity = 7;
1373 else
1375 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1380 // for rate adapation
1381 pTxWI->PacketId = pTxWI->MCS;
1385 VOID RTMPWriteTxWI_Cache(
1386 IN PRTMP_ADAPTER pAd,
1387 IN OUT PTXWI_STRUC pTxWI,
1388 IN TX_BLK *pTxBlk)
1390 PHTTRANSMIT_SETTING pTransmit;
1391 PMAC_TABLE_ENTRY pMacEntry;
1394 // update TXWI
1396 pMacEntry = pTxBlk->pMacEntry;
1397 pTransmit = pTxBlk->pTransmit;
1399 if (pMacEntry->bAutoTxRateSwitch)
1401 pTxWI->txop = IFS_HTTXOP;
1403 // If CCK or OFDM, BW must be 20
1404 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1405 pTxWI->ShortGI = pTransmit->field.ShortGI;
1406 pTxWI->STBC = pTransmit->field.STBC;
1408 pTxWI->MCS = pTransmit->field.MCS;
1409 pTxWI->PHYMODE = pTransmit->field.MODE;
1411 // set PID for TxRateSwitching
1412 pTxWI->PacketId = pTransmit->field.MCS;
1415 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1416 pTxWI->MIMOps = 0;
1418 if (pAd->CommonCfg.bMIMOPSEnable)
1420 // MIMO Power Save Mode
1421 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1423 // Dynamic MIMO Power Save Mode
1424 pTxWI->MIMOps = 1;
1426 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1428 // Static MIMO Power Save Mode
1429 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1431 pTxWI->MCS = 7;
1432 pTxWI->MIMOps = 0;
1438 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1444 ========================================================================
1446 Routine Description:
1447 Calculates the duration which is required to transmit out frames
1448 with given size and specified rate.
1450 Arguments:
1451 pTxD Pointer to transmit descriptor
1452 Ack Setting for Ack requirement bit
1453 Fragment Setting for Fragment bit
1454 RetryMode Setting for retry mode
1455 Ifs Setting for IFS gap
1456 Rate Setting for transmit rate
1457 Service Setting for service
1458 Length Frame length
1459 TxPreamble Short or Long preamble when using CCK rates
1460 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1462 Return Value:
1463 None
1465 IRQL = PASSIVE_LEVEL
1466 IRQL = DISPATCH_LEVEL
1468 ========================================================================
1470 VOID RTMPWriteTxDescriptor(
1471 IN PRTMP_ADAPTER pAd,
1472 IN PTXD_STRUC pTxD,
1473 IN BOOLEAN bWIV,
1474 IN UCHAR QueueSEL)
1477 // Always use Long preamble before verifiation short preamble functionality works well.
1478 // Todo: remove the following line if short preamble functionality works
1480 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1482 pTxD->WIV = (bWIV) ? 1: 0;
1483 pTxD->QSEL= (QueueSEL);
1484 if (pAd->bGenOneHCCA == TRUE)
1485 pTxD->QSEL= FIFO_HCCA;
1486 pTxD->DMADONE = 0;
1490 // should be called only when -
1491 // 1. MEADIA_CONNECTED
1492 // 2. AGGREGATION_IN_USED
1493 // 3. Fragmentation not in used
1494 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1495 BOOLEAN TxFrameIsAggregatible(
1496 IN PRTMP_ADAPTER pAd,
1497 IN PUCHAR pPrevAddr1,
1498 IN PUCHAR p8023hdr)
1501 // can't aggregate EAPOL (802.1x) frame
1502 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1503 return FALSE;
1505 // can't aggregate multicast/broadcast frame
1506 if (p8023hdr[0] & 0x01)
1507 return FALSE;
1509 if (INFRA_ON(pAd)) // must be unicast to AP
1510 return TRUE;
1511 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1512 return TRUE;
1513 else
1514 return FALSE;
1519 ========================================================================
1521 Routine Description:
1522 Check the MSDU Aggregation policy
1523 1.HT aggregation is A-MSDU
1524 2.legaacy rate aggregation is software aggregation by Ralink.
1526 Arguments:
1528 Return Value:
1530 Note:
1532 ========================================================================
1534 BOOLEAN PeerIsAggreOn(
1535 IN PRTMP_ADAPTER pAd,
1536 IN ULONG TxRate,
1537 IN PMAC_TABLE_ENTRY pMacEntry)
1539 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1541 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1543 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1545 return TRUE;
1548 #ifdef AGGREGATION_SUPPORT
1549 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1550 { // legacy Ralink Aggregation support
1551 return TRUE;
1553 #endif // AGGREGATION_SUPPORT //
1556 return FALSE;
1562 ========================================================================
1564 Routine Description:
1565 Check and fine the packet waiting in SW queue with highest priority
1567 Arguments:
1568 pAd Pointer to our adapter
1570 Return Value:
1571 pQueue Pointer to Waiting Queue
1573 IRQL = DISPATCH_LEVEL
1575 Note:
1577 ========================================================================
1579 PQUEUE_HEADER RTMPCheckTxSwQueue(
1580 IN PRTMP_ADAPTER pAd,
1581 OUT PUCHAR pQueIdx)
1584 ULONG Number;
1586 Number = pAd->TxSwQueue[QID_AC_BK].Number
1587 + pAd->TxSwQueue[QID_AC_BE].Number
1588 + pAd->TxSwQueue[QID_AC_VI].Number
1589 + pAd->TxSwQueue[QID_AC_VO].Number
1590 + pAd->TxSwQueue[QID_HCCA].Number;
1592 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1594 *pQueIdx = QID_AC_VO;
1595 return (&pAd->TxSwQueue[QID_AC_VO]);
1597 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1599 *pQueIdx = QID_AC_VI;
1600 return (&pAd->TxSwQueue[QID_AC_VI]);
1602 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1604 *pQueIdx = QID_AC_BE;
1605 return (&pAd->TxSwQueue[QID_AC_BE]);
1607 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1609 *pQueIdx = QID_AC_BK;
1610 return (&pAd->TxSwQueue[QID_AC_BK]);
1612 else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1614 *pQueIdx = QID_HCCA;
1615 return (&pAd->TxSwQueue[QID_HCCA]);
1618 // No packet pending in Tx Sw queue
1619 *pQueIdx = QID_AC_BK;
1621 return (NULL);
1624 #ifdef RT2860
1625 BOOLEAN RTMPFreeTXDUponTxDmaDone(
1626 IN PRTMP_ADAPTER pAd,
1627 IN UCHAR QueIdx)
1629 PRTMP_TX_RING pTxRing;
1630 PTXD_STRUC pTxD;
1631 PNDIS_PACKET pPacket;
1632 UCHAR FREE = 0;
1633 TXD_STRUC TxD, *pOriTxD;
1634 //ULONG IrqFlags;
1635 BOOLEAN bReschedule = FALSE;
1638 ASSERT(QueIdx < NUM_OF_TX_RING);
1639 pTxRing = &pAd->TxRing[QueIdx];
1641 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx);
1642 while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx)
1644 // static rate also need NICUpdateFifoStaCounters() function.
1645 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1646 NICUpdateFifoStaCounters(pAd);
1648 /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */
1649 FREE++;
1650 pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1651 pOriTxD = pTxD;
1652 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
1653 pTxD = &TxD;
1655 pTxD->DMADONE = 0;
1657 /*====================================================================*/
1659 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket;
1660 if (pPacket)
1662 #ifdef CONFIG_5VT_ENHANCE
1663 if (RTMP_GET_PACKET_5VT(pPacket))
1664 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
1665 else
1666 #endif // CONFIG_5VT_ENHANCE //
1667 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1668 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1670 //Always assign pNdisPacket as NULL after clear
1671 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL;
1673 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket;
1675 ASSERT(pPacket == NULL);
1676 if (pPacket)
1678 #ifdef CONFIG_5VT_ENHANCE
1679 if (RTMP_GET_PACKET_5VT(pPacket))
1680 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
1681 else
1682 #endif // CONFIG_5VT_ENHANCE //
1683 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1684 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1686 //Always assign pNextNdisPacket as NULL after clear
1687 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
1689 /*====================================================================*/
1691 pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0);
1692 pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
1693 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
1694 /* get tx_tdx_idx again */
1695 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx);
1697 NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
1701 return bReschedule;
1707 ========================================================================
1709 Routine Description:
1710 Process TX Rings DMA Done interrupt, running in DPC level
1712 Arguments:
1713 Adapter Pointer to our adapter
1715 Return Value:
1716 None
1718 IRQL = DISPATCH_LEVEL
1720 ========================================================================
1722 BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(
1723 IN PRTMP_ADAPTER pAd,
1724 IN INT_SOURCE_CSR_STRUC TxRingBitmap)
1726 unsigned long IrqFlags;
1727 BOOLEAN bReschedule = FALSE;
1729 // Make sure Tx ring resource won't be used by other threads
1731 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1733 if (TxRingBitmap.field.Ac0DmaDone)
1734 bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE);
1736 if (TxRingBitmap.field.HccaDmaDone)
1737 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_HCCA);
1739 if (TxRingBitmap.field.Ac3DmaDone)
1740 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO);
1742 if (TxRingBitmap.field.Ac2DmaDone)
1743 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI);
1745 if (TxRingBitmap.field.Ac1DmaDone)
1746 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK);
1748 // Make sure to release Tx ring resource
1749 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1751 // Dequeue outgoing frames from TxSwQueue[] and process it
1752 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1754 return bReschedule;
1759 ========================================================================
1761 Routine Description:
1762 Process MGMT ring DMA done interrupt, running in DPC level
1764 Arguments:
1765 pAd Pointer to our adapter
1767 Return Value:
1768 None
1770 IRQL = DISPATCH_LEVEL
1772 Note:
1774 ========================================================================
1776 VOID RTMPHandleMgmtRingDmaDoneInterrupt(
1777 IN PRTMP_ADAPTER pAd)
1779 PTXD_STRUC pTxD;
1780 PNDIS_PACKET pPacket;
1781 UCHAR FREE = 0;
1782 PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing;
1784 NdisAcquireSpinLock(&pAd->MgmtRingLock);
1786 RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx);
1787 while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx)
1789 FREE++;
1790 pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
1791 pTxD->DMADONE = 0;
1792 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket;
1795 if (pPacket)
1797 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
1798 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1800 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL;
1802 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket;
1803 if (pPacket)
1805 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1806 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1808 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL;
1809 INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE);
1811 NdisReleaseSpinLock(&pAd->MgmtRingLock);
1817 ========================================================================
1819 Routine Description:
1820 Arguments:
1821 Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon.
1823 IRQL = DISPATCH_LEVEL
1825 ========================================================================
1827 VOID RTMPHandleTBTTInterrupt(
1828 IN PRTMP_ADAPTER pAd)
1831 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1839 ========================================================================
1841 Routine Description:
1842 Arguments:
1843 Adapter Pointer to our adapter. Rewrite beacon content before next send-out.
1845 IRQL = DISPATCH_LEVEL
1847 ========================================================================
1849 VOID RTMPHandlePreTBTTInterrupt(
1850 IN PRTMP_ADAPTER pAd)
1853 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1855 DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt...\n"));
1862 VOID RTMPHandleRxCoherentInterrupt(
1863 IN PRTMP_ADAPTER pAd)
1865 WPDMA_GLO_CFG_STRUC GloCfg;
1867 if (pAd == NULL)
1869 DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n"));
1870 return;
1873 DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n"));
1875 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word);
1877 GloCfg.field.EnTXWriteBackDDONE = 0;
1878 GloCfg.field.EnableRxDMA = 0;
1879 GloCfg.field.EnableTxDMA = 0;
1880 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
1882 RTMPRingCleanUp(pAd, QID_AC_BE);
1883 RTMPRingCleanUp(pAd, QID_AC_BK);
1884 RTMPRingCleanUp(pAd, QID_AC_VI);
1885 RTMPRingCleanUp(pAd, QID_AC_VO);
1886 RTMPRingCleanUp(pAd, QID_HCCA);
1887 RTMPRingCleanUp(pAd, QID_MGMT);
1888 RTMPRingCleanUp(pAd, QID_RX);
1890 RTMPEnableRxTx(pAd);
1892 DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n"));
1894 #endif /* RT2860 */
1897 ========================================================================
1899 Routine Description:
1900 Suspend MSDU transmission
1902 Arguments:
1903 pAd Pointer to our adapter
1905 Return Value:
1906 None
1908 Note:
1910 ========================================================================
1912 VOID RTMPSuspendMsduTransmission(
1913 IN PRTMP_ADAPTER pAd)
1915 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1919 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1920 // use Lowbound as R66 value on ScanNextChannel(...)
1922 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1924 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1925 RTMPSetAGCInitValue(pAd, BW_20);
1927 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1932 ========================================================================
1934 Routine Description:
1935 Resume MSDU transmission
1937 Arguments:
1938 pAd Pointer to our adapter
1940 Return Value:
1941 None
1943 IRQL = DISPATCH_LEVEL
1945 Note:
1947 ========================================================================
1949 VOID RTMPResumeMsduTransmission(
1950 IN PRTMP_ADAPTER pAd)
1952 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1954 // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value
1955 // R66 should not be 0
1956 if (pAd->BbpTuning.R66CurrentValue == 0)
1958 pAd->BbpTuning.R66CurrentValue = 0x38;
1959 DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
1962 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1964 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1965 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1969 UINT deaggregate_AMSDU_announce(
1970 IN PRTMP_ADAPTER pAd,
1971 PNDIS_PACKET pPacket,
1972 IN PUCHAR pData,
1973 IN ULONG DataSize)
1975 USHORT PayloadSize;
1976 USHORT SubFrameSize;
1977 PHEADER_802_3 pAMSDUsubheader;
1978 UINT nMSDU;
1979 UCHAR Header802_3[14];
1981 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
1982 PNDIS_PACKET pClonePacket;
1986 nMSDU = 0;
1988 while (DataSize > LENGTH_802_3)
1991 nMSDU++;
1993 pAMSDUsubheader = (PHEADER_802_3)pData;
1994 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1995 SubFrameSize = PayloadSize + LENGTH_802_3;
1998 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
2000 break;
2003 pPayload = pData + LENGTH_802_3;
2004 pDA = pData;
2005 pSA = pData + MAC_ADDR_LEN;
2007 // convert to 802.3 header
2008 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
2010 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
2012 // avoid local heap overflow, use dyanamic allocation
2013 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
2014 if (Elem == NULL)
2015 return;
2016 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
2017 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
2018 WpaEAPOLKeyAction(pAd, Elem);
2019 kfree(Elem);
2023 if (pRemovedLLCSNAP)
2025 pPayload -= LENGTH_802_3;
2026 PayloadSize += LENGTH_802_3;
2027 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
2031 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
2032 if (pClonePacket)
2034 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
2038 // A-MSDU has padding to multiple of 4 including subframe header.
2039 // align SubFrameSize up to multiple of 4
2040 SubFrameSize = (SubFrameSize+3)&(~0x3);
2043 if (SubFrameSize > 1528 || SubFrameSize < 32)
2045 break;
2048 if (DataSize > SubFrameSize)
2050 pData += SubFrameSize;
2051 DataSize -= SubFrameSize;
2053 else
2055 // end of A-MSDU
2056 DataSize = 0;
2060 // finally release original rx packet
2061 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
2063 return nMSDU;
2067 UINT BA_Reorder_AMSDU_Annnounce(
2068 IN PRTMP_ADAPTER pAd,
2069 IN PNDIS_PACKET pPacket)
2071 PUCHAR pData;
2072 USHORT DataSize;
2073 UINT nMSDU = 0;
2075 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
2076 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
2078 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
2080 return nMSDU;
2085 ==========================================================================
2086 Description:
2087 Look up the MAC address in the MAC table. Return NULL if not found.
2088 Return:
2089 pEntry - pointer to the MAC entry; NULL is not found
2090 ==========================================================================
2092 MAC_TABLE_ENTRY *MacTableLookup(
2093 IN PRTMP_ADAPTER pAd,
2094 PUCHAR pAddr)
2096 ULONG HashIdx;
2097 MAC_TABLE_ENTRY *pEntry = NULL;
2099 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2100 pEntry = pAd->MacTab.Hash[HashIdx];
2102 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
2104 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2106 break;
2108 else
2109 pEntry = pEntry->pNext;
2112 return pEntry;
2115 MAC_TABLE_ENTRY *MacTableInsertEntry(
2116 IN PRTMP_ADAPTER pAd,
2117 IN PUCHAR pAddr,
2118 IN UCHAR apidx,
2119 IN BOOLEAN CleanAll)
2121 UCHAR HashIdx;
2122 int i, FirstWcid;
2123 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
2125 // if FULL, return
2126 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
2127 return NULL;
2129 FirstWcid = 1;
2131 if (pAd->StaCfg.BssType == BSS_INFRA)
2132 FirstWcid = 2;
2134 // allocate one MAC entry
2135 NdisAcquireSpinLock(&pAd->MacTabLock);
2136 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
2138 // pick up the first available vacancy
2139 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
2140 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
2141 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
2142 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
2145 pEntry = &pAd->MacTab.Content[i];
2146 if (CleanAll == TRUE)
2148 pEntry->MaxSupportedRate = RATE_11;
2149 pEntry->CurrTxRate = RATE_11;
2150 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2151 pEntry->PairwiseKey.KeyLen = 0;
2152 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
2156 pEntry->ValidAsCLI = TRUE;
2157 pEntry->ValidAsWDS = FALSE;
2158 pEntry->ValidAsApCli = FALSE;
2159 pEntry->ValidAsMesh = FALSE;
2160 pEntry->ValidAsDls = FALSE;
2164 pEntry->bIAmBadAtheros = FALSE;
2165 pEntry->pAd = pAd;
2166 pEntry->CMTimerRunning = FALSE;
2167 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2168 pEntry->RSNIE_Len = 0;
2169 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
2170 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
2172 if (pEntry->ValidAsMesh)
2173 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
2174 else if (pEntry->ValidAsApCli)
2175 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
2176 else if (pEntry->ValidAsWDS)
2177 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
2178 else
2179 pEntry->apidx = apidx;
2183 pEntry->AuthMode = pAd->StaCfg.AuthMode;
2184 pEntry->WepStatus = pAd->StaCfg.WepStatus;
2185 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
2186 #ifdef RT2860
2187 AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)i);
2188 #endif
2192 pEntry->GTKState = REKEY_NEGOTIATING;
2193 pEntry->PairwiseKey.KeyLen = 0;
2194 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
2196 #ifdef RT2860
2197 if ((pAd->OpMode == OPMODE_STA) &&
2198 (pAd->StaCfg.BssType == BSS_ADHOC))
2199 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
2200 else
2201 #endif
2202 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
2204 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
2205 COPY_MAC_ADDR(pEntry->Addr, pAddr);
2206 pEntry->Sst = SST_NOT_AUTH;
2207 pEntry->AuthState = AS_NOT_AUTH;
2208 pEntry->Aid = (USHORT)i; //0;
2209 pEntry->CapabilityInfo = 0;
2210 pEntry->PsMode = PWR_ACTIVE;
2211 pEntry->PsQIdleCount = 0;
2212 pEntry->NoDataIdleCount = 0;
2213 pEntry->ContinueTxFailCnt = 0;
2214 InitializeQueueHeader(&pEntry->PsQueue);
2217 pAd->MacTab.Size ++;
2218 // Add this entry into ASIC RX WCID search table
2219 RT28XX_STA_ENTRY_ADD(pAd, pEntry);
2223 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
2224 break;
2228 // add this MAC entry into HASH table
2229 if (pEntry)
2231 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2232 if (pAd->MacTab.Hash[HashIdx] == NULL)
2234 pAd->MacTab.Hash[HashIdx] = pEntry;
2236 else
2238 pCurrEntry = pAd->MacTab.Hash[HashIdx];
2239 while (pCurrEntry->pNext != NULL)
2240 pCurrEntry = pCurrEntry->pNext;
2241 pCurrEntry->pNext = pEntry;
2245 NdisReleaseSpinLock(&pAd->MacTabLock);
2246 return pEntry;
2250 ==========================================================================
2251 Description:
2252 Delete a specified client from MAC table
2253 ==========================================================================
2255 BOOLEAN MacTableDeleteEntry(
2256 IN PRTMP_ADAPTER pAd,
2257 IN USHORT wcid,
2258 IN PUCHAR pAddr)
2260 USHORT HashIdx;
2261 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
2262 BOOLEAN Cancelled;
2264 if (wcid >= MAX_LEN_OF_MAC_TABLE)
2265 return FALSE;
2267 NdisAcquireSpinLock(&pAd->MacTabLock);
2269 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2270 pEntry = &pAd->MacTab.Content[wcid];
2272 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
2275 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2278 // Delete this entry from ASIC on-chip WCID Table
2279 RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
2281 // free resources of BA
2282 BASessionTearDownALL(pAd, pEntry->Aid);
2284 pPrevEntry = NULL;
2285 pProbeEntry = pAd->MacTab.Hash[HashIdx];
2286 ASSERT(pProbeEntry);
2288 // update Hash list
2291 if (pProbeEntry == pEntry)
2293 if (pPrevEntry == NULL)
2295 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
2297 else
2299 pPrevEntry->pNext = pEntry->pNext;
2301 break;
2304 pPrevEntry = pProbeEntry;
2305 pProbeEntry = pProbeEntry->pNext;
2306 } while (pProbeEntry);
2308 // not found !!!
2309 ASSERT(pProbeEntry != NULL);
2311 RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
2314 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
2316 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
2317 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2321 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2322 pAd->MacTab.Size --;
2323 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
2325 else
2327 printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
2331 NdisReleaseSpinLock(&pAd->MacTabLock);
2333 //Reset operating mode when no Sta.
2334 if (pAd->MacTab.Size == 0)
2336 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
2337 #ifdef RT2860
2338 AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
2339 #else
2340 // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet
2341 // Set MAC register value according operation mode
2342 RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_UPDATE_PROTECT, NULL, 0);
2343 #endif
2346 return TRUE;
2351 ==========================================================================
2352 Description:
2353 This routine reset the entire MAC table. All packets pending in
2354 the power-saving queues are freed here.
2355 ==========================================================================
2357 VOID MacTableReset(
2358 IN PRTMP_ADAPTER pAd)
2360 int i;
2362 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
2363 //NdisAcquireSpinLock(&pAd->MacTabLock);
2365 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
2367 #ifdef RT2860
2368 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2369 #endif
2370 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
2372 // free resources of BA
2373 BASessionTearDownALL(pAd, i);
2375 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2379 #ifdef RT2870
2380 NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
2381 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2382 #endif // RT2870 //
2384 //AsicDelWcidTab(pAd, i);
2388 return;
2392 ==========================================================================
2393 Description:
2395 IRQL = DISPATCH_LEVEL
2397 ==========================================================================
2399 VOID AssocParmFill(
2400 IN PRTMP_ADAPTER pAd,
2401 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2402 IN PUCHAR pAddr,
2403 IN USHORT CapabilityInfo,
2404 IN ULONG Timeout,
2405 IN USHORT ListenIntv)
2407 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2408 // Add mask to support 802.11b mode only
2409 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2410 AssocReq->Timeout = Timeout;
2411 AssocReq->ListenIntv = ListenIntv;
2416 ==========================================================================
2417 Description:
2419 IRQL = DISPATCH_LEVEL
2421 ==========================================================================
2423 VOID DisassocParmFill(
2424 IN PRTMP_ADAPTER pAd,
2425 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2426 IN PUCHAR pAddr,
2427 IN USHORT Reason)
2429 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2430 DisassocReq->Reason = Reason;
2435 ========================================================================
2437 Routine Description:
2438 Check the out going frame, if this is an DHCP or ARP datagram
2439 will be duplicate another frame at low data rate transmit.
2441 Arguments:
2442 pAd Pointer to our adapter
2443 pPacket Pointer to outgoing Ndis frame
2445 Return Value:
2446 TRUE To be duplicate at Low data rate transmit. (1mb)
2447 FALSE Do nothing.
2449 IRQL = DISPATCH_LEVEL
2451 Note:
2453 MAC header + IP Header + UDP Header
2454 14 Bytes 20 Bytes
2456 UDP Header
2457 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2458 Source Port
2459 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2460 Destination Port
2462 port 0x43 means Bootstrap Protocol, server.
2463 Port 0x44 means Bootstrap Protocol, client.
2465 ========================================================================
2468 BOOLEAN RTMPCheckDHCPFrame(
2469 IN PRTMP_ADAPTER pAd,
2470 IN PNDIS_PACKET pPacket)
2472 PACKET_INFO PacketInfo;
2473 ULONG NumberOfBytesRead = 0;
2474 ULONG CurrentOffset = 0;
2475 PVOID pVirtualAddress = NULL;
2476 UINT NdisBufferLength;
2477 PUCHAR pSrc;
2478 USHORT Protocol;
2479 UCHAR ByteOffset36 = 0;
2480 UCHAR ByteOffset38 = 0;
2481 BOOLEAN ReadFirstParm = TRUE;
2483 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2485 NumberOfBytesRead += NdisBufferLength;
2486 pSrc = (PUCHAR) pVirtualAddress;
2487 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2490 // Check DHCP & BOOTP protocol
2492 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2494 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2496 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2497 ByteOffset36 = *(pSrc + CurrentOffset);
2498 ReadFirstParm = FALSE;
2501 if (NumberOfBytesRead >= 37)
2503 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2504 ByteOffset38 = *(pSrc + CurrentOffset);
2505 //End of Read
2506 break;
2508 return FALSE;
2511 // Check for DHCP & BOOTP protocol
2512 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2515 // 2054 (hex 0806) for ARP datagrams
2516 // if this packet is not ARP datagrams, then do nothing
2517 // ARP datagrams will also be duplicate at 1mb broadcast frames
2519 if (Protocol != 0x0806 )
2520 return FALSE;
2523 return TRUE;
2527 BOOLEAN RTMPCheckEtherType(
2528 IN PRTMP_ADAPTER pAd,
2529 IN PNDIS_PACKET pPacket)
2531 USHORT TypeLen;
2532 UCHAR Byte0, Byte1;
2533 PUCHAR pSrcBuf;
2534 UINT32 pktLen;
2535 UINT16 srcPort, dstPort;
2536 BOOLEAN status = TRUE;
2539 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2540 pktLen = GET_OS_PKT_LEN(pPacket);
2542 ASSERT(pSrcBuf);
2544 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2546 // get Ethernet protocol field
2547 TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2549 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
2551 if (TypeLen <= 1500)
2552 { // 802.3, 802.3 LLC
2554 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2555 DSAP(1) + SSAP(1) + Control(1) +
2556 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2557 => + SNAP (5, OriginationID(3) + etherType(2))
2559 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2561 Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2562 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2563 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2564 pSrcBuf += 8; // Skip this LLC/SNAP header
2566 else
2568 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2572 // If it's a VLAN packet, get the real Type/Length field.
2573 if (TypeLen == 0x8100)
2575 /* 0x8100 means VLAN packets */
2577 /* Dest. MAC Address (6-bytes) +
2578 Source MAC Address (6-bytes) +
2579 Length/Type = 802.1Q Tag Type (2-byte) +
2580 Tag Control Information (2-bytes) +
2581 Length / Type (2-bytes) +
2582 data payload (0-n bytes) +
2583 Pad (0-p bytes) +
2584 Frame Check Sequence (4-bytes) */
2586 RTMP_SET_PACKET_VLAN(pPacket, 1);
2587 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2588 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2590 pSrcBuf += 4; // Skip the VLAN Header.
2593 switch (TypeLen)
2595 case 0x0800:
2597 ASSERT((pktLen > 34));
2598 if (*(pSrcBuf + 9) == 0x11)
2599 { // udp packet
2600 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
2602 pSrcBuf += 20; // Skip the IP header
2603 srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2604 dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2606 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2607 { //It's a BOOTP/DHCP packet
2608 RTMP_SET_PACKET_DHCP(pPacket, 1);
2612 break;
2613 case 0x0806:
2615 //ARP Packet.
2616 RTMP_SET_PACKET_DHCP(pPacket, 1);
2618 break;
2619 case 0x888e:
2621 // EAPOL Packet.
2622 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2624 break;
2625 default:
2626 status = FALSE;
2627 break;
2630 return status;
2636 VOID Update_Rssi_Sample(
2637 IN PRTMP_ADAPTER pAd,
2638 IN RSSI_SAMPLE *pRssi,
2639 IN PRXWI_STRUC pRxWI)
2641 CHAR rssi0 = pRxWI->RSSI0;
2642 CHAR rssi1 = pRxWI->RSSI1;
2643 CHAR rssi2 = pRxWI->RSSI2;
2645 if (rssi0 != 0)
2647 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2648 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2649 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2652 if (rssi1 != 0)
2654 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2655 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2656 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2659 if (rssi2 != 0)
2661 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2662 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2663 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2669 // Normal legacy Rx packet indication
2670 VOID Indicate_Legacy_Packet(
2671 IN PRTMP_ADAPTER pAd,
2672 IN RX_BLK *pRxBlk,
2673 IN UCHAR FromWhichBSSID)
2675 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2676 UCHAR Header802_3[LENGTH_802_3];
2678 // 1. get 802.3 Header
2679 // 2. remove LLC
2680 // a. pointer pRxBlk->pData to payload
2681 // b. modify pRxBlk->DataSize
2682 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2684 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2687 // release packet
2688 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2689 return;
2693 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2695 #ifdef RT2870
2696 if (pAd->CommonCfg.bDisableReordering == 0)
2698 PBA_REC_ENTRY pBAEntry;
2699 ULONG Now32;
2700 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
2701 UCHAR TID = pRxBlk->pRxWI->TID;
2702 USHORT Idx;
2704 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
2706 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2708 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2709 if (Idx != 0)
2711 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2712 // update last rx time
2713 NdisGetSystemUpTime(&Now32);
2714 if ((pBAEntry->list.qlen > 0) &&
2715 RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2718 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);
2719 hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2720 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2725 #endif // RT2870 //
2727 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2730 // pass this 802.3 packet to upper layer or forward this packet to WM directly
2732 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2736 // Normal, AMPDU or AMSDU
2737 VOID CmmRxnonRalinkFrameIndicate(
2738 IN PRTMP_ADAPTER pAd,
2739 IN RX_BLK *pRxBlk,
2740 IN UCHAR FromWhichBSSID)
2742 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2744 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2746 else
2748 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2750 // handle A-MSDU
2751 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2753 else
2755 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2761 VOID CmmRxRalinkFrameIndicate(
2762 IN PRTMP_ADAPTER pAd,
2763 IN MAC_TABLE_ENTRY *pEntry,
2764 IN RX_BLK *pRxBlk,
2765 IN UCHAR FromWhichBSSID)
2767 UCHAR Header802_3[LENGTH_802_3];
2768 UINT16 Msdu2Size;
2769 UINT16 Payload1Size, Payload2Size;
2770 PUCHAR pData2;
2771 PNDIS_PACKET pPacket2 = NULL;
2775 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2777 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2779 /* skip two byte MSDU2 len */
2780 pRxBlk->pData += 2;
2781 pRxBlk->DataSize -= 2;
2783 else
2785 // release packet
2786 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2787 return;
2790 // get 802.3 Header and remove LLC
2791 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2793 ASSERT(pRxBlk->pRxPacket);
2795 // Ralink Aggregation frame
2796 pAd->RalinkCounters.OneSecRxAggregationCount ++;
2797 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2798 Payload2Size = Msdu2Size - LENGTH_802_3;
2800 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2802 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2804 if (!pPacket2)
2806 // release packet
2807 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2808 return;
2811 // update payload size of 1st packet
2812 pRxBlk->DataSize = Payload1Size;
2813 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2815 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2817 if (pPacket2)
2819 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2824 #define RESET_FRAGFRAME(_fragFrame) \
2826 _fragFrame.RxSize = 0; \
2827 _fragFrame.Sequence = 0; \
2828 _fragFrame.LastFrag = 0; \
2829 _fragFrame.Flags = 0; \
2833 PNDIS_PACKET RTMPDeFragmentDataFrame(
2834 IN PRTMP_ADAPTER pAd,
2835 IN RX_BLK *pRxBlk)
2837 PHEADER_802_11 pHeader = pRxBlk->pHeader;
2838 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2839 UCHAR *pData = pRxBlk->pData;
2840 USHORT DataSize = pRxBlk->DataSize;
2841 PNDIS_PACKET pRetPacket = NULL;
2842 UCHAR *pFragBuffer = NULL;
2843 BOOLEAN bReassDone = FALSE;
2844 UCHAR HeaderRoom = 0;
2847 ASSERT(pHeader);
2849 HeaderRoom = pData - (UCHAR *)pHeader;
2851 // Re-assemble the fragmented packets
2852 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
2854 // the first pkt of fragment, record it.
2855 if (pHeader->FC.MoreFrag)
2857 ASSERT(pAd->FragFrame.pFragPacket);
2858 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2859 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2860 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
2861 pAd->FragFrame.Sequence = pHeader->Sequence;
2862 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
2863 ASSERT(pAd->FragFrame.LastFrag == 0);
2864 goto done; // end of processing this frame
2867 else //Middle & End of fragment
2869 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2870 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2872 // Fragment is not the same sequence or out of fragment number order
2873 // Reset Fragment control blk
2874 RESET_FRAGFRAME(pAd->FragFrame);
2875 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2876 goto done; // give up this frame
2878 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2880 // Fragment frame is too large, it exeeds the maximum frame size.
2881 // Reset Fragment control blk
2882 RESET_FRAGFRAME(pAd->FragFrame);
2883 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2884 goto done; // give up this frame
2888 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2889 // In this case, we will dropt it.
2891 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2893 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2894 goto done; // give up this frame
2897 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2899 // concatenate this fragment into the re-assembly buffer
2900 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2901 pAd->FragFrame.RxSize += DataSize;
2902 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
2904 // Last fragment
2905 if (pHeader->FC.MoreFrag == FALSE)
2907 bReassDone = TRUE;
2911 done:
2912 // always release rx fragmented packet
2913 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2915 // return defragmented packet if packet is reassembled completely
2916 // otherwise return NULL
2917 if (bReassDone)
2919 PNDIS_PACKET pNewFragPacket;
2921 // allocate a new packet buffer for fragment
2922 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2923 if (pNewFragPacket)
2925 // update RxBlk
2926 pRetPacket = pAd->FragFrame.pFragPacket;
2927 pAd->FragFrame.pFragPacket = pNewFragPacket;
2928 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2929 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2930 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2931 pRxBlk->pRxPacket = pRetPacket;
2933 else
2935 RESET_FRAGFRAME(pAd->FragFrame);
2939 return pRetPacket;
2943 VOID Indicate_AMSDU_Packet(
2944 IN PRTMP_ADAPTER pAd,
2945 IN RX_BLK *pRxBlk,
2946 IN UCHAR FromWhichBSSID)
2948 UINT nMSDU;
2950 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2951 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2952 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2955 VOID Indicate_EAPOL_Packet(
2956 IN PRTMP_ADAPTER pAd,
2957 IN RX_BLK *pRxBlk,
2958 IN UCHAR FromWhichBSSID)
2960 MAC_TABLE_ENTRY *pEntry = NULL;
2963 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2964 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2965 return;
2968 if (pEntry == NULL)
2970 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2971 // release packet
2972 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2973 return;
2977 #define BCN_TBTT_OFFSET 64 //defer 64 us
2978 VOID ReSyncBeaconTime(
2979 IN PRTMP_ADAPTER pAd)
2982 UINT32 Offset;
2985 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2987 pAd->TbttTickCount++;
2990 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2991 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2993 if (Offset == (BCN_TBTT_OFFSET-2))
2995 BCN_TIME_CFG_STRUC csr;
2996 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2997 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
2998 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
3000 else
3002 if (Offset == (BCN_TBTT_OFFSET-1))
3004 BCN_TIME_CFG_STRUC csr;
3006 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
3007 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
3008 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);