2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
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. *
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. *
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. *
25 *************************************************************************
29 All functions in this file must be PCI-depended, or you should out your function
33 #include "../rt_config.h"
36 USHORT RtmpPCI_WriteTxResource(
40 OUT USHORT *FreeNumber)
43 UCHAR *pDMAHeaderBufVA;
44 USHORT TxIdx, RetTxIdx;
47 PRTMP_TX_RING pTxRing;
51 // get Tx Ring Resource
53 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
54 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
55 pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
56 BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
58 // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
59 if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
61 //hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;
62 hwHeaderLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
66 //hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
67 hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
69 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen);
71 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
72 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
75 // build Tx Descriptor
78 pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
79 NdisZeroMemory(pTxD, TXD_SIZE);
81 pTxD->SDPtr0 = BufBasePaLow;
82 pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding
83 pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);
84 pTxD->SDLen1 = pTxBlk->SrcBufLen;
86 pTxD->LastSec1 = (bIsLast) ? 1 : 0;
88 RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
94 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
95 pTxRing->TxCpuIdx = TxIdx;
103 USHORT RtmpPCI_WriteSingleTxResource(
104 IN PRTMP_ADAPTER pAd,
107 OUT USHORT *FreeNumber)
110 UCHAR *pDMAHeaderBufVA;
111 USHORT TxIdx, RetTxIdx;
114 PRTMP_TX_RING pTxRing;
118 // get Tx Ring Resource
120 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
121 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
122 pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
123 BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
125 // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
126 //hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
127 hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
129 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen);
131 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
132 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
135 // build Tx Descriptor
137 pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
138 NdisZeroMemory(pTxD, TXD_SIZE);
140 pTxD->SDPtr0 = BufBasePaLow;
141 pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding
142 pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);;
143 pTxD->SDLen1 = pTxBlk->SrcBufLen;
145 pTxD->LastSec1 = (bIsLast) ? 1 : 0;
147 RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
153 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
154 pTxRing->TxCpuIdx = TxIdx;
162 USHORT RtmpPCI_WriteMultiTxResource(
163 IN PRTMP_ADAPTER pAd,
166 OUT USHORT *FreeNumber)
169 UCHAR *pDMAHeaderBufVA;
170 USHORT TxIdx, RetTxIdx;
173 PRTMP_TX_RING pTxRing;
177 bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0);
180 // get Tx Ring Resource
182 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
183 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
184 pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
185 BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
189 // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
190 if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
191 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;
192 hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
193 else if (pTxBlk->TxFrameType == TX_RALINK_FRAME)
194 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD;
195 hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD;
197 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
198 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
200 firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHdrLen;
204 firstDMALen = pTxBlk->MpduHeaderLen;
207 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen);
209 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
210 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
213 // build Tx Descriptor
215 pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
216 NdisZeroMemory(pTxD, TXD_SIZE);
218 pTxD->SDPtr0 = BufBasePaLow;
219 pTxD->SDLen0 = firstDMALen; // include padding
220 pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);;
221 pTxD->SDLen1 = pTxBlk->SrcBufLen;
223 pTxD->LastSec1 = (bIsLast) ? 1 : 0;
225 RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
232 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
233 pTxRing->TxCpuIdx = TxIdx;
242 VOID RtmpPCI_FinalWriteTxResource(
243 IN PRTMP_ADAPTER pAd,
245 IN USHORT totalMPDUSize,
246 IN USHORT FirstTxIdx)
250 PRTMP_TX_RING pTxRing;
253 // get Tx Ring Resource
255 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
256 pTxWI = (PTXWI_STRUC) pTxRing->Cell[FirstTxIdx].DmaBuf.AllocVa;
257 pTxWI->MPDUtotalByteCount = totalMPDUSize;
262 VOID RtmpPCIDataLastTxIdx(
263 IN PRTMP_ADAPTER pAd,
268 PRTMP_TX_RING pTxRing;
271 // get Tx Ring Resource
273 pTxRing = &pAd->TxRing[QueIdx];
276 // build Tx Descriptor
278 pTxD = (PTXD_STRUC) pTxRing->Cell[LastTxIdx].AllocVa;
286 USHORT RtmpPCI_WriteFragTxResource(
287 IN PRTMP_ADAPTER pAd,
290 OUT USHORT *FreeNumber)
292 UCHAR *pDMAHeaderBufVA;
293 USHORT TxIdx, RetTxIdx;
296 PRTMP_TX_RING pTxRing;
301 // Get Tx Ring Resource
303 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
304 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
305 pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
306 BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
309 // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
311 //hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
312 hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
314 firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen;
315 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen);
319 // Build Tx Descriptor
321 pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
322 NdisZeroMemory(pTxD, TXD_SIZE);
324 if (fragNum == pTxBlk->TotalFragNum)
326 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
327 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
330 pTxD->SDPtr0 = BufBasePaLow;
331 pTxD->SDLen0 = firstDMALen; // include padding
332 pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);
333 pTxD->SDLen1 = pTxBlk->SrcBufLen;
337 RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
341 pTxBlk->Priv += pTxBlk->SrcBufLen;
346 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
347 pTxRing->TxCpuIdx = TxIdx;
357 Must be run in Interrupt context
358 This function handle PCI specific TxDesc and cpu index update and kick the packet out.
360 int RtmpPCIMgmtKickOut(
361 IN RTMP_ADAPTER *pAd,
363 IN PNDIS_PACKET pPacket,
368 ULONG SwIdx = pAd->MgmtRing.TxCpuIdx;
370 pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa;
372 pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket;
373 pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL;
375 RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT);
380 pTxD->SDPtr0 = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
381 pTxD->SDLen0 = SrcBufLen;
384 //==================================================================
385 /* DBGPRINT_RAW(RT_DEBUG_TRACE, ("MLMEHardTransmit\n"));
386 for (i = 0; i < (TXWI_SIZE+24); i++)
389 DBGPRINT_RAW(RT_DEBUG_TRACE, ("%x:", *(pSrcBufVA+i)));
391 DBGPRINT_RAW(RT_DEBUG_TRACE, (" :: "));
393 DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n "));
395 DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n "));*/
396 //=======================================================================
398 pAd->RalinkCounters.KickTxCount++;
399 pAd->RalinkCounters.OneSecTxDoneCount++;
401 // Increase TX_CTX_IDX, but write to register later.
402 INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
404 RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx);
411 ========================================================================
414 Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
417 pRxD Pointer to the Rx descriptor
420 NDIS_STATUS_SUCCESS No err
421 NDIS_STATUS_FAILURE Error
425 ========================================================================
427 NDIS_STATUS RTMPCheckRxError(
428 IN PRTMP_ADAPTER pAd,
429 IN PHEADER_802_11 pHeader,
430 IN PRXWI_STRUC pRxWI,
431 IN PRT28XX_RXD_STRUC pRxD)
436 // Phy errors & CRC errors
437 if (/*(pRxD->PhyErr) ||*/ (pRxD->Crc))
439 // Check RSSI for Noise Hist statistic collection.
440 dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
442 pAd->StaCfg.RPIDensity[0] += 1;
444 pAd->StaCfg.RPIDensity[1] += 1;
446 pAd->StaCfg.RPIDensity[2] += 1;
448 pAd->StaCfg.RPIDensity[3] += 1;
450 pAd->StaCfg.RPIDensity[4] += 1;
452 pAd->StaCfg.RPIDensity[5] += 1;
454 pAd->StaCfg.RPIDensity[6] += 1;
456 pAd->StaCfg.RPIDensity[7] += 1;
458 return(NDIS_STATUS_FAILURE);
461 // Add Rx size to channel load counter, we should ignore error counts
462 pAd->StaCfg.CLBusyBytes += (pRxD->SDL0 + 14);
464 // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics
467 if (pHeader->FC.ToDs)
469 return(NDIS_STATUS_FAILURE);
473 // Drop not U2M frames, cant's drop here because we will drop beacon in this case
474 // I am kind of doubting the U2M bit operation
475 // if (pRxD->U2M == 0)
476 // return(NDIS_STATUS_FAILURE);
478 // drop decyption fail frame
481 if (pRxD->CipherErr == 2)
482 {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV ok but MICErr "));}
483 else if (pRxD->CipherErr == 1)
484 {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV Err "));}
485 else if (pRxD->CipherErr == 3)
486 DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: Key not valid "));
488 if (((pRxD->CipherErr & 1) == 1) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
489 RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
491 DBGPRINT_RAW(RT_DEBUG_TRACE,(" %d (len=%d, Mcast=%d, MyBss=%d, Wcid=%d, KeyId=%d)\n",
494 pRxD->Mcast | pRxD->Bcast,
496 pRxWI->WirelessCliID,
497 // CipherName[pRxD->CipherAlg],
503 if (pRxD->CipherErr == 2)
505 pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex];
506 if (pAd->StaCfg.WpaSupplicantUP)
507 WpaSendMicFailureToWpaSupplicant(pAd,
508 (pWpaKey->Type == PAIRWISEKEY) ? TRUE:FALSE);
510 RTMPReportMicError(pAd, pWpaKey);
512 if (((pRxD->CipherErr & 2) == 2) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
513 RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
515 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n"));
519 return(NDIS_STATUS_SUCCESS);
520 /*if ((pRxD->CipherAlg == CIPHER_AES) &&
521 (pHeader->Sequence == pAd->FragFrame.Sequence))
524 // Acceptable since the First FragFrame no CipherErr problem.
526 return(NDIS_STATUS_SUCCESS);
529 return(NDIS_STATUS_FAILURE);
532 return(NDIS_STATUS_SUCCESS);
536 BOOLEAN RTMPFreeTXDUponTxDmaDone(
537 IN PRTMP_ADAPTER pAd,
540 PRTMP_TX_RING pTxRing;
542 PNDIS_PACKET pPacket;
544 TXD_STRUC TxD, *pOriTxD;
546 BOOLEAN bReschedule = FALSE;
549 ASSERT(QueIdx < NUM_OF_TX_RING);
550 pTxRing = &pAd->TxRing[QueIdx];
552 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx);
553 while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx)
555 // RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
557 // static rate also need NICUpdateFifoStaCounters() function.
558 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
559 NICUpdateFifoStaCounters(pAd);
561 /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */
563 pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
565 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
572 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket;
575 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
576 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
578 //Always assign pNdisPacket as NULL after clear
579 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL;
581 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket;
583 ASSERT(pPacket == NULL);
586 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
587 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
589 //Always assign pNextNdisPacket as NULL after clear
590 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
593 pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0);
594 pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
595 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
596 /* get tx_tdx_idx again */
597 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx);
598 NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
600 // RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
610 ========================================================================
613 Process TX Rings DMA Done interrupt, running in DPC level
616 Adapter Pointer to our adapter
621 IRQL = DISPATCH_LEVEL
623 ========================================================================
625 BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(
626 IN PRTMP_ADAPTER pAd,
627 IN INT_SOURCE_CSR_STRUC TxRingBitmap)
630 unsigned long IrqFlags;
631 BOOLEAN bReschedule = FALSE;
633 // Make sure Tx ring resource won't be used by other threads
634 //NdisAcquireSpinLock(&pAd->TxRingLock);
636 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
638 if (TxRingBitmap.field.Ac0DmaDone)
639 bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE);
641 if (TxRingBitmap.field.Ac3DmaDone)
642 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO);
644 if (TxRingBitmap.field.Ac2DmaDone)
645 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI);
647 if (TxRingBitmap.field.Ac1DmaDone)
648 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK);
650 // Make sure to release Tx ring resource
651 //NdisReleaseSpinLock(&pAd->TxRingLock);
652 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
654 // Dequeue outgoing frames from TxSwQueue[] and process it
655 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
662 ========================================================================
665 Process MGMT ring DMA done interrupt, running in DPC level
668 pAd Pointer to our adapter
673 IRQL = DISPATCH_LEVEL
677 ========================================================================
679 VOID RTMPHandleMgmtRingDmaDoneInterrupt(
680 IN PRTMP_ADAPTER pAd)
683 PNDIS_PACKET pPacket;
686 PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing;
688 NdisAcquireSpinLock(&pAd->MgmtRingLock);
690 RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx);
691 while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx)
694 pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
696 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket;
701 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
702 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
704 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL;
706 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket;
709 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
710 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
712 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL;
713 INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE);
716 NdisReleaseSpinLock(&pAd->MgmtRingLock);
722 ========================================================================
726 Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon.
728 IRQL = DISPATCH_LEVEL
730 ========================================================================
732 VOID RTMPHandleTBTTInterrupt(
733 IN PRTMP_ADAPTER pAd)
736 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
744 ========================================================================
748 pAd Pointer to our adapter. Rewrite beacon content before next send-out.
750 IRQL = DISPATCH_LEVEL
752 ========================================================================
754 VOID RTMPHandlePreTBTTInterrupt(
755 IN PRTMP_ADAPTER pAd)
758 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
760 DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt...\n"));
767 VOID RTMPHandleRxCoherentInterrupt(
768 IN PRTMP_ADAPTER pAd)
770 WPDMA_GLO_CFG_STRUC GloCfg;
774 DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n"));
778 DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n"));
780 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word);
782 GloCfg.field.EnTXWriteBackDDONE = 0;
783 GloCfg.field.EnableRxDMA = 0;
784 GloCfg.field.EnableTxDMA = 0;
785 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
787 RTMPRingCleanUp(pAd, QID_AC_BE);
788 RTMPRingCleanUp(pAd, QID_AC_BK);
789 RTMPRingCleanUp(pAd, QID_AC_VI);
790 RTMPRingCleanUp(pAd, QID_AC_VO);
791 RTMPRingCleanUp(pAd, QID_MGMT);
792 RTMPRingCleanUp(pAd, QID_RX);
796 DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n"));
799 PNDIS_PACKET GetPacketFromRxRing(
800 IN PRTMP_ADAPTER pAd,
801 OUT PRT28XX_RXD_STRUC pSaveRxD,
802 OUT BOOLEAN *pbReschedule,
803 IN OUT UINT32 *pRxPending)
806 PNDIS_PACKET pRxPacket = NULL;
807 PNDIS_PACKET pNewPacket;
809 NDIS_PHYSICAL_ADDRESS AllocPa;
810 BOOLEAN bReschedule = FALSE;
813 RTMP_SEM_LOCK(&pAd->RxRingLock);
815 if (*pRxPending == 0)
817 // Get how may packets had been received
818 RTMP_IO_READ32(pAd, RX_DRX_IDX , &pAd->RxRing.RxDmaIdx);
820 if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx)
822 // no more rx packets
827 // get rx pending count
828 if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx)
829 *pRxPending = pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx;
831 *pRxPending = pAd->RxRing.RxDmaIdx + RX_RING_SIZE - pAd->RxRing.RxSwReadIdx;
835 pRxCell = &pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx];
837 // Point to Rx indexed rx ring descriptor
838 pRxD = (PRXD_STRUC) pRxCell->AllocVa;
840 if (pRxD->DDONE == 0)
843 // DMAIndx had done but DDONE bit not ready
849 // return rx descriptor
850 NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE);
852 pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa);
856 // unmap the rx buffer
857 PCI_UNMAP_SINGLE(pAd, pRxCell->DmaBuf.AllocPa,
858 pRxCell->DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
859 pRxPacket = pRxCell->pNdisPacket;
861 pRxCell->DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE;
862 pRxCell->pNdisPacket = (PNDIS_PACKET) pNewPacket;
863 pRxCell->DmaBuf.AllocVa = AllocVa;
864 pRxCell->DmaBuf.AllocPa = AllocPa;
865 /* update SDP0 to new buffer of rx packet */
866 pRxD->SDP0 = AllocPa;
870 //DBGPRINT(RT_DEBUG_TRACE,("No Rx Buffer\n"));
877 // had handled one rx packet
878 *pRxPending = *pRxPending - 1;
880 // update rx descriptor and kick rx
881 INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE);
883 pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1);
884 RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
887 RTMP_SEM_UNLOCK(&pAd->RxRingLock);
888 *pbReschedule = bReschedule;
893 NDIS_STATUS MlmeHardTransmitTxRing(
894 IN PRTMP_ADAPTER pAd,
896 IN PNDIS_PACKET pPacket)
898 PACKET_INFO PacketInfo;
902 PHEADER_802_11 pHeader_802_11;
903 BOOLEAN bAckRequired, bInsertTimestamp;
907 ULONG SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
908 PTXWI_STRUC pFirstTxWI;
910 //HTTRANSMIT_SETTING MlmeTransmit; //Rate for this MGMT frame.
912 MAC_TABLE_ENTRY *pMacEntry = NULL;
915 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
918 if (pSrcBufVA == NULL)
920 // The buffer shouldn't be NULL
921 return NDIS_STATUS_FAILURE;
924 // Make sure MGMT ring resource won't be used by other threads
925 //NdisAcquireSpinLock(&pAd->TxRingLock);
927 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
931 //NdisReleaseSpinLock(&pAd->TxRingLock);
932 return NDIS_STATUS_FAILURE;
935 SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
937 pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa;
939 if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket)
941 DBGPRINT(RT_DEBUG_OFF, ("MlmeHardTransmit Error\n"));
942 //NdisReleaseSpinLock(&pAd->TxRingLock);
943 return NDIS_STATUS_FAILURE;
947 // outgoing frame always wakeup PHY to prevent frame lost
948 // if (pAd->StaCfg.Psm == PWR_SAVE)
949 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
950 AsicForceWakeup(pAd, TRUE);
952 pFirstTxWI =(PTXWI_STRUC)pSrcBufVA;
954 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXWI_SIZE);
955 if (pHeader_802_11->Addr1[0] & 0x01)
957 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
961 MlmeRate = pAd->CommonCfg.MlmeRate;
964 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
965 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
967 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
970 // Verify Mlme rate for a / g bands.
971 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
975 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
976 // Snice it's been set to 0 while on MgtMacHeaderInit
977 // By the way this will cause frame to be send on PWR_SAVE failed.
980 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
981 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
982 if (pHeader_802_11->FC.Type != BTYPE_DATA)
984 if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) || !(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
986 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
990 pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave;
994 bInsertTimestamp = FALSE;
995 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
997 bAckRequired = FALSE;
999 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
1001 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
1003 bAckRequired = FALSE;
1004 pHeader_802_11->Duration = 0;
1008 bAckRequired = TRUE;
1009 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
1010 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
1012 bInsertTimestamp = TRUE;
1016 pHeader_802_11->Sequence = pAd->Sequence++;
1017 if (pAd->Sequence > 0xfff)
1019 // Before radar detection done, mgmt frame can not be sent but probe req
1020 // Because we need to use probe req to trigger driver to send probe req in passive scan
1021 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
1022 && (pAd->CommonCfg.bIEEE80211H == 1)
1023 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
1025 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
1026 //NdisReleaseSpinLock(&pAd->TxRingLock);
1027 return (NDIS_STATUS_FAILURE);
1031 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
1032 // should always has only one ohysical buffer, and the whole frame size equals
1033 // to the first scatter buffer size
1036 // Initialize TX Descriptor
1037 // For inter-frame gap, the number is for this frame and next frame
1038 // For MLME rate, we will fix as 2Mb to match other vendor's implement
1039 // pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
1041 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
1042 // Only beacon use Nseq=TRUE. So here we use Nseq=FALSE.
1043 if (pMacEntry == NULL)
1045 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
1046 0, RESERVED_WCID, (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
1050 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
1051 bInsertTimestamp, FALSE, bAckRequired, FALSE,
1052 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE),
1053 pMacEntry->MaxHTPhyMode.field.MCS, 0,
1054 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
1055 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
1058 pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket;
1059 pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL;
1060 // pFirstTxWI->MPDUtotalByteCount = SrcBufLen - TXWI_SIZE;
1061 SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
1064 RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA);
1067 pTxD->SDLen0 = SrcBufLen;
1069 pTxD->SDPtr0 = SrcBufPA;
1073 pAd->RalinkCounters.KickTxCount++;
1074 pAd->RalinkCounters.OneSecTxDoneCount++;
1076 // Increase TX_CTX_IDX, but write to register later.
1077 INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
1079 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10, pAd->TxRing[QueIdx].TxCpuIdx);
1081 // Make sure to release MGMT ring resource
1082 // NdisReleaseSpinLock(&pAd->TxRingLock);
1084 return NDIS_STATUS_SUCCESS;
1088 NDIS_STATUS MlmeDataHardTransmit(
1089 IN PRTMP_ADAPTER pAd,
1091 IN PNDIS_PACKET pPacket)
1093 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
1096 return NDIS_STATUS_FAILURE;
1099 return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket);
1104 ========================================================================
1106 Routine Description:
1107 Calculates the duration which is required to transmit out frames
1108 with given size and specified rate.
1111 pTxD Pointer to transmit descriptor
1112 Ack Setting for Ack requirement bit
1113 Fragment Setting for Fragment bit
1114 RetryMode Setting for retry mode
1115 Ifs Setting for IFS gap
1116 Rate Setting for transmit rate
1117 Service Setting for service
1119 TxPreamble Short or Long preamble when using CCK rates
1120 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1125 IRQL = PASSIVE_LEVEL
1126 IRQL = DISPATCH_LEVEL
1128 ========================================================================
1130 VOID RTMPWriteTxDescriptor(
1131 IN PRTMP_ADAPTER pAd,
1137 // Always use Long preamble before verifiation short preamble functionality works well.
1138 // Todo: remove the following line if short preamble functionality works
1140 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1142 pTxD->WIV = (bWIV) ? 1: 0;
1143 pTxD->QSEL= (QueueSEL);
1144 //RT2860c?? fixed using EDCA queue for test... We doubt Queue1 has problem. 2006-09-26 Jan
1145 //pTxD->QSEL= FIFO_EDCA;