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"
35 extern RTMP_RF_REGS RF2850RegTable[];
36 extern UCHAR NUM_OF_2850_CHNL;
38 USHORT RtmpPCI_WriteTxResource(
42 OUT USHORT *FreeNumber)
45 UCHAR *pDMAHeaderBufVA;
46 USHORT TxIdx, RetTxIdx;
49 PRTMP_TX_RING pTxRing;
53 // get Tx Ring Resource
55 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
56 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
57 pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
58 BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
60 // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
61 if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
63 hwHeaderLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
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;
118 PRTMP_TX_RING pTxRing;
122 // get Tx Ring Resource
124 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
125 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
126 pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
127 BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
129 // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
130 hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
132 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen);
134 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
135 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
138 // build Tx Descriptor
140 #ifndef RT_BIG_ENDIAN
141 pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
143 pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
147 NdisZeroMemory(pTxD, TXD_SIZE);
149 pTxD->SDPtr0 = BufBasePaLow;
150 pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding
151 pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);;
152 pTxD->SDLen1 = pTxBlk->SrcBufLen;
154 pTxD->LastSec1 = (bIsLast) ? 1 : 0;
156 RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
158 RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI);
159 RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
160 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
161 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
162 #endif // RT_BIG_ENDIAN //
168 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
169 pTxRing->TxCpuIdx = TxIdx;
177 USHORT RtmpPCI_WriteMultiTxResource(
178 IN PRTMP_ADAPTER pAd,
181 OUT USHORT *FreeNumber)
184 UCHAR *pDMAHeaderBufVA;
185 USHORT TxIdx, RetTxIdx;
192 PRTMP_TX_RING pTxRing;
196 bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0);
199 // get Tx Ring Resource
201 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
202 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
203 pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
204 BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
208 // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
209 if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
210 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;
211 hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
212 else if (pTxBlk->TxFrameType == TX_RALINK_FRAME)
213 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD;
214 hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD;
216 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
217 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
219 firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHdrLen;
223 firstDMALen = pTxBlk->MpduHeaderLen;
226 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen);
228 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
229 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
232 // build Tx Descriptor
234 #ifndef RT_BIG_ENDIAN
235 pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
237 pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
241 NdisZeroMemory(pTxD, TXD_SIZE);
243 pTxD->SDPtr0 = BufBasePaLow;
244 pTxD->SDLen0 = firstDMALen; // include padding
245 pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);;
246 pTxD->SDLen1 = pTxBlk->SrcBufLen;
248 pTxD->LastSec1 = (bIsLast) ? 1 : 0;
250 RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
254 RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA+ TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
257 RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI);
259 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
260 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
261 #endif // RT_BIG_ENDIAN //
267 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
268 pTxRing->TxCpuIdx = TxIdx;
277 VOID RtmpPCI_FinalWriteTxResource(
278 IN PRTMP_ADAPTER pAd,
280 IN USHORT totalMPDUSize,
281 IN USHORT FirstTxIdx)
285 PRTMP_TX_RING pTxRing;
288 // get Tx Ring Resource
290 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
291 pTxWI = (PTXWI_STRUC) pTxRing->Cell[FirstTxIdx].DmaBuf.AllocVa;
292 pTxWI->MPDUtotalByteCount = totalMPDUSize;
294 RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI);
295 #endif // RT_BIG_ENDIAN //
300 VOID RtmpPCIDataLastTxIdx(
301 IN PRTMP_ADAPTER pAd,
310 PRTMP_TX_RING pTxRing;
313 // get Tx Ring Resource
315 pTxRing = &pAd->TxRing[QueIdx];
318 // build Tx Descriptor
320 #ifndef RT_BIG_ENDIAN
321 pTxD = (PTXD_STRUC) pTxRing->Cell[LastTxIdx].AllocVa;
323 pDestTxD = (PTXD_STRUC) pTxRing->Cell[LastTxIdx].AllocVa;
331 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
332 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
333 #endif // RT_BIG_ENDIAN //
338 USHORT RtmpPCI_WriteFragTxResource(
339 IN PRTMP_ADAPTER pAd,
342 OUT USHORT *FreeNumber)
344 UCHAR *pDMAHeaderBufVA;
345 USHORT TxIdx, RetTxIdx;
352 PRTMP_TX_RING pTxRing;
357 // Get Tx Ring Resource
359 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
360 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
361 pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
362 BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
365 // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
367 hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
369 firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen;
370 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen);
374 // Build Tx Descriptor
376 #ifndef RT_BIG_ENDIAN
377 pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
379 pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
383 NdisZeroMemory(pTxD, TXD_SIZE);
385 if (fragNum == pTxBlk->TotalFragNum)
387 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
388 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
391 pTxD->SDPtr0 = BufBasePaLow;
392 pTxD->SDLen0 = firstDMALen; // include padding
393 pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);
394 pTxD->SDLen1 = pTxBlk->SrcBufLen;
398 RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
401 RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI);
402 RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
403 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
404 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
405 #endif // RT_BIG_ENDIAN //
408 pTxBlk->Priv += pTxBlk->SrcBufLen;
413 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
414 pTxRing->TxCpuIdx = TxIdx;
423 Must be run in Interrupt context
424 This function handle PCI specific TxDesc and cpu index update and kick the packet out.
426 int RtmpPCIMgmtKickOut(
427 IN RTMP_ADAPTER *pAd,
429 IN PNDIS_PACKET pPacket,
438 ULONG SwIdx = pAd->MgmtRing.TxCpuIdx;
441 pDestTxD = (PTXD_STRUC)pAd->MgmtRing.Cell[SwIdx].AllocVa;
444 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
446 pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa;
449 pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket;
450 pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL;
452 RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT);
457 pTxD->SDPtr0 = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);;
458 pTxD->SDLen0 = SrcBufLen;
461 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
462 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
465 pAd->RalinkCounters.KickTxCount++;
466 pAd->RalinkCounters.OneSecTxDoneCount++;
468 // Increase TX_CTX_IDX, but write to register later.
469 INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
471 RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx);
477 #ifdef CONFIG_STA_SUPPORT
479 ========================================================================
482 Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
485 pRxD Pointer to the Rx descriptor
488 NDIS_STATUS_SUCCESS No err
489 NDIS_STATUS_FAILURE Error
493 ========================================================================
495 NDIS_STATUS RTMPCheckRxError(
496 IN PRTMP_ADAPTER pAd,
497 IN PHEADER_802_11 pHeader,
498 IN PRXWI_STRUC pRxWI,
499 IN PRT28XX_RXD_STRUC pRxD)
504 // Phy errors & CRC errors
505 if (/*(pRxD->PhyErr) ||*/ (pRxD->Crc))
507 // Check RSSI for Noise Hist statistic collection.
508 dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
510 pAd->StaCfg.RPIDensity[0] += 1;
512 pAd->StaCfg.RPIDensity[1] += 1;
514 pAd->StaCfg.RPIDensity[2] += 1;
516 pAd->StaCfg.RPIDensity[3] += 1;
518 pAd->StaCfg.RPIDensity[4] += 1;
520 pAd->StaCfg.RPIDensity[5] += 1;
522 pAd->StaCfg.RPIDensity[6] += 1;
524 pAd->StaCfg.RPIDensity[7] += 1;
526 return(NDIS_STATUS_FAILURE);
529 // Add Rx size to channel load counter, we should ignore error counts
530 pAd->StaCfg.CLBusyBytes += (pRxD->SDL0 + 14);
532 // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics
535 if (pHeader->FC.ToDs)
537 return(NDIS_STATUS_FAILURE);
541 // Drop not U2M frames, cant's drop here because we will drop beacon in this case
542 // I am kind of doubting the U2M bit operation
543 // if (pRxD->U2M == 0)
544 // return(NDIS_STATUS_FAILURE);
546 // drop decyption fail frame
549 if (pRxD->CipherErr == 2)
550 {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV ok but MICErr "));}
551 else if (pRxD->CipherErr == 1)
552 {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV Err "));}
553 else if (pRxD->CipherErr == 3)
554 DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: Key not valid "));
556 if (((pRxD->CipherErr & 1) == 1) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
557 RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
559 DBGPRINT_RAW(RT_DEBUG_TRACE,(" %d (len=%d, Mcast=%d, MyBss=%d, Wcid=%d, KeyId=%d)\n",
562 pRxD->Mcast | pRxD->Bcast,
564 pRxWI->WirelessCliID,
570 if (pRxD->CipherErr == 2)
572 pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex];
573 #ifdef WPA_SUPPLICANT_SUPPORT
574 if (pAd->StaCfg.WpaSupplicantUP)
575 WpaSendMicFailureToWpaSupplicant(pAd,
576 (pWpaKey->Type == PAIRWISEKEY) ? TRUE:FALSE);
578 #endif // WPA_SUPPLICANT_SUPPORT //
579 RTMPReportMicError(pAd, pWpaKey);
581 if (((pRxD->CipherErr & 2) == 2) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
582 RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
584 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n"));
588 return(NDIS_STATUS_SUCCESS);
590 return(NDIS_STATUS_FAILURE);
593 return(NDIS_STATUS_SUCCESS);
597 ==========================================================================
599 This routine sends command to firmware and turn our chip to power save mode.
600 Both RadioOff and .11 power save function needs to call this routine.
602 Level = GUIRADIO_OFF : GUI Radio Off mode
603 Level = DOT11POWERSAVE : 802.11 power save mode
604 Level = RTMP_HALT : When Disable device.
606 ==========================================================================
608 VOID RT28xxPciAsicRadioOff(
609 IN PRTMP_ADAPTER pAd,
611 IN USHORT TbttNumToNextWakeUp)
613 WPDMA_GLO_CFG_STRUC DmaCfg;
614 UCHAR i, tempBBP_R3 = 0;
615 BOOLEAN brc = FALSE, Cancelled;
617 UINT32 PsPollTime = 0, MACValue;
618 ULONG BeaconPeriodTime;
619 UINT32 RxDmaIdx, RxCpuIdx;
620 DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> TxCpuIdx = %d, TxDmaIdx = %d. RxCpuIdx = %d, RxDmaIdx = %d.\n", pAd->TxRing[0].TxCpuIdx, pAd->TxRing[0].TxDmaIdx, pAd->RxRing.RxCpuIdx, pAd->RxRing.RxDmaIdx));
622 // Check Rx DMA busy status, if more than half is occupied, give up this radio off.
623 RTMP_IO_READ32(pAd, RX_DRX_IDX , &RxDmaIdx);
624 RTMP_IO_READ32(pAd, RX_CRX_IDX , &RxCpuIdx);
625 if ((RxDmaIdx > RxCpuIdx) && ((RxDmaIdx - RxCpuIdx) > RX_RING_SIZE/3))
627 DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return1. RxDmaIdx = %d , RxCpuIdx = %d. \n", RxDmaIdx, RxCpuIdx));
630 else if ((RxCpuIdx >= RxDmaIdx) && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE/3))
632 DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return2. RxCpuIdx = %d. RxDmaIdx = %d , \n", RxCpuIdx, RxDmaIdx));
636 // Once go into this function, disable tx because don't want too many packets in queue to prevent HW stops.
637 RTMP_SET_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
639 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
641 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
642 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
644 if (Level == DOT11POWERSAVE)
646 RTMP_IO_READ32(pAd, TBTT_TIMER, &TbTTTime);
648 // 00. check if need to do sleep in this DTIM period. If next beacon will arrive within 30ms , ...doesn't necessarily sleep.
649 // TbTTTime uint = 64us, LEAD_TIME unit = 1024us, PsPollTime unit = 1ms
650 if (((64*TbTTTime) <((LEAD_TIME*1024) + 40000)) && (TbttNumToNextWakeUp == 0))
652 DBGPRINT(RT_DEBUG_TRACE, ("TbTTTime = 0x%x , give up this sleep. \n", TbTTTime));
653 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
654 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
659 PsPollTime = (64*TbTTTime- LEAD_TIME*1024)/1000;
662 BeaconPeriodTime = pAd->CommonCfg.BeaconPeriod*102/100;
663 if (TbttNumToNextWakeUp > 0)
664 PsPollTime += ((TbttNumToNextWakeUp -1) * BeaconPeriodTime);
666 pAd->Mlme.bPsPollTimerRunning = TRUE;
667 RTMPSetTimer(&pAd->Mlme.PsPollTimer, PsPollTime);
672 // 0. Disable Tx DMA.
673 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
674 DmaCfg.field.EnableTxDMA = 0;
675 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
677 // 1. Wait DMA not busy
681 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
682 if ((DmaCfg.field.TxDMABusy == 0) && (DmaCfg.field.RxDMABusy == 0))
690 DBGPRINT(RT_DEBUG_TRACE, ("DMA keeps busy. return on RT28xxPciAsicRadioOff ()\n"));
691 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
692 DmaCfg.field.EnableTxDMA = 1;
693 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
694 pAd->CheckDmaBusyCount++;
699 pAd->CheckDmaBusyCount = 0;
702 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
705 if (pAd->Antenna.field.RxPath > 1)
707 tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7);
708 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3);
711 // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
712 if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
713 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
716 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
721 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
724 if (Level != RTMP_HALT)
726 // Change Interrupt bitmask.
727 RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt);
731 NICDisableInterrupt(pAd);
734 RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
736 RTMP_IO_READ32(pAd, MAC_SYS_CTRL , &MACValue);
738 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL , MACValue);
740 // 2. Send Sleep command
741 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
742 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
743 // send POWER-SAVE command to MCU. high-byte = 1 save power as much as possible. high byte = 0 save less power
744 AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x1);
745 // 2-1. Wait command success
746 // Status = 1 : success, Status = 2, already sleep, Status = 3, Maybe MAC is busy so can't finish this task.
747 brc = AsicCheckCommanOk(pAd, PowerSafeCID);
752 AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x01); // send POWER-SAVE command to MCU. Timeout unit:40us.
753 //RTMPusecDelay(200);
754 brc = AsicCheckCommanOk(pAd, PowerSafeCID);
757 // 3. After 0x30 command is ok, send radio off command. lowbyte = 0 for power safe.
758 // If 0x30 command is not ok this time, we can ignore 0x35 command. It will make sure not cause firmware'r problem.
759 if ((Level == DOT11POWERSAVE) && (brc == TRUE))
761 AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 0, 0x00); // lowbyte = 0 means to do power safe, NOT turn off radio.
762 // 3-1. Wait command success
763 AsicCheckCommanOk(pAd, PowerRadioOffCID);
765 else if (brc == TRUE)
767 AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 1, 0x00); // lowbyte = 0 means to do power safe, NOT turn off radio.
768 // 3-1. Wait command success
769 AsicCheckCommanOk(pAd, PowerRadioOffCID);
776 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
777 if ((DmaCfg.field.RxDMABusy == 0) && (DmaCfg.field.TxDMABusy == 0))
785 pAd->CheckDmaBusyCount++;
786 DBGPRINT(RT_DEBUG_TRACE, ("DMA Rx keeps busy. on RT28xxPciAsicRadioOff ()\n"));
790 pAd->CheckDmaBusyCount = 0;
793 if (Level == DOT11POWERSAVE)
795 AUTO_WAKEUP_STRUC AutoWakeupCfg;
796 //RTMPSetTimer(&pAd->Mlme.PsPollTimer, 90);
798 // we have decided to SLEEP, so at least do it for a BEACON period.
799 if (TbttNumToNextWakeUp == 0)
800 TbttNumToNextWakeUp = 1;
802 AutoWakeupCfg.word = 0;
803 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
805 // 1. Set auto wake up timer.
806 AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
807 AutoWakeupCfg.field.EnableAutoWakeup = 1;
808 AutoWakeupCfg.field.AutoLeadTime = LEAD_TIME;
809 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
812 // 4-1. If it's to disable our device. Need to restore PCI Configuration Space to its original value.
813 if (Level == RTMP_HALT)
815 if ((brc == TRUE) && (i < 50))
816 RTMPPCIeLinkCtrlSetting(pAd, 0);
818 // 4. Set PCI configuration Space Link Comtrol fields. Only Radio Off needs to call this function
821 if ((brc == TRUE) && (i < 50))
822 RTMPPCIeLinkCtrlSetting(pAd, 3);
825 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
830 ==========================================================================
832 This routine sends command to firmware and turn our chip to wake up mode from power save mode.
833 Both RadioOn and .11 power save function needs to call this routine.
835 Level = GUIRADIO_OFF : call this function is from Radio Off to Radio On. Need to restore PCI host value.
836 Level = other value : normal wake up function.
838 ==========================================================================
840 BOOLEAN RT28xxPciAsicRadioOn(
841 IN PRTMP_ADAPTER pAd,
844 WPDMA_GLO_CFG_STRUC DmaCfg;
845 BOOLEAN Cancelled, brv = TRUE;
848 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
850 pAd->Mlme.bPsPollTimerRunning = FALSE;
851 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
852 if ((Level == GUIRADIO_OFF) || (Level == GUI_IDLE_POWER_SAVE)
853 || (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)))
855 DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOn ()\n"));
856 // 1. Set PCI Link Control in Configuration Space.
857 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
862 pAd->bPCIclkOff = FALSE;
863 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x3a80);
864 // 2. Send wake up command.
865 AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02);
867 // 2-1. wait command ok.
868 brv = AsicCheckCommanOk(pAd, PowerWakeCID);
871 NICEnableInterrupt(pAd);
874 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
875 DmaCfg.field.EnableTxDMA = 1;
876 DmaCfg.field.EnableRxDMA = 1;
877 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
880 RTMP_IO_READ32(pAd, MAC_SYS_CTRL , &MACValue);
882 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL , MACValue);
884 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
885 if (Level == GUI_IDLE_POWER_SAVE)
887 // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
888 if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
889 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
892 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
893 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
898 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
899 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
908 VOID RT28xxPciStaAsicForceWakeup(
909 IN PRTMP_ADAPTER pAd,
912 AUTO_WAKEUP_STRUC AutoWakeupCfg;
914 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW))
916 DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n"));
920 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WAKEUP_NOW);
921 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
923 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
925 // Support PCIe Advance Power Save
926 if (((Level == FROM_TX) && (pAd->Mlme.bPsPollTimerRunning == TRUE)) ||
927 (Level == RTMP_HALT))
929 pAd->Mlme.bPsPollTimerRunning = FALSE;
930 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
932 DBGPRINT(RT_DEBUG_TRACE, ("=======AsicForceWakeup===bFromTx\n"));
935 AutoWakeupCfg.word = 0;
936 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
938 // If this is called from Halt. ALWAYS force wakeup!!!
939 if (Level == RTMP_HALT)
941 RT28xxPciAsicRadioOn(pAd, RTMP_HALT);
945 if (RT28xxPciAsicRadioOn(pAd, DOT11POWERSAVE))
947 // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
948 if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
949 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
952 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
953 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
958 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
959 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
967 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x00);
968 AutoWakeupCfg.word = 0;
969 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
972 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
973 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW);
974 DBGPRINT(RT_DEBUG_TRACE, ("<=======RT28xxPciStaAsicForceWakeup\n"));
977 VOID RT28xxPciStaAsicSleepThenAutoWakeup(
978 IN PRTMP_ADAPTER pAd,
979 IN USHORT TbttNumToNextWakeUp)
981 if (pAd->StaCfg.bRadio == FALSE)
983 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
986 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
989 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW))
991 DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n"));
992 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
996 NdisGetSystemUpTime(&Now);
997 // If last send NULL fram time is too close to this receiving beacon (within 8ms), don't go to sleep for this DTM.
998 // Because Some AP can't queuing outgoing frames immediately.
999 if (((pAd->Mlme.LastSendNULLpsmTime + 8) >= Now) && (pAd->Mlme.LastSendNULLpsmTime <= Now))
1001 DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu : RxCountSinceLastNULL = %lu. \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL));
1004 else if ((pAd->RalinkCounters.RxCountSinceLastNULL > 0) && ((pAd->Mlme.LastSendNULLpsmTime + pAd->CommonCfg.BeaconPeriod) >= Now))
1006 DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu: RxCountSinceLastNULL = %lu > 0 \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL));
1010 RT28xxPciAsicRadioOff(pAd, DOT11POWERSAVE, TbttNumToNextWakeUp);
1014 AUTO_WAKEUP_STRUC AutoWakeupCfg;
1015 // we have decided to SLEEP, so at least do it for a BEACON period.
1016 if (TbttNumToNextWakeUp == 0)
1017 TbttNumToNextWakeUp = 1;
1019 AutoWakeupCfg.word = 0;
1020 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
1021 AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
1022 AutoWakeupCfg.field.EnableAutoWakeup = 1;
1023 AutoWakeupCfg.field.AutoLeadTime = 5;
1024 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
1025 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x00); // send POWER-SAVE command to MCU. Timeout 40us.
1026 DBGPRINT(RT_DEBUG_TRACE, ("<-- %s, TbttNumToNextWakeUp=%d \n", __func__, TbttNumToNextWakeUp));
1028 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
1031 VOID PsPollWakeExec(
1032 IN PVOID SystemSpecific1,
1033 IN PVOID FunctionContext,
1034 IN PVOID SystemSpecific2,
1035 IN PVOID SystemSpecific3)
1037 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1038 unsigned long flags;
1040 DBGPRINT(RT_DEBUG_TRACE,("-->PsPollWakeExec \n"));
1041 RTMP_INT_LOCK(&pAd->irq_lock, flags);
1042 if (pAd->Mlme.bPsPollTimerRunning)
1044 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
1046 pAd->Mlme.bPsPollTimerRunning = FALSE;
1047 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
1051 IN PVOID SystemSpecific1,
1052 IN PVOID FunctionContext,
1053 IN PVOID SystemSpecific2,
1054 IN PVOID SystemSpecific3)
1056 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1057 WPDMA_GLO_CFG_STRUC DmaCfg;
1060 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1062 DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on fOP_STATUS_DOZE == TRUE; \n"));
1063 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1067 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1069 DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on SCAN_IN_PROGRESS; \n"));
1070 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1073 pAd->Mlme.bPsPollTimerRunning = FALSE;
1074 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1075 if (pAd->StaCfg.bRadio == TRUE)
1077 pAd->bPCIclkOff = FALSE;
1078 RTMPRingCleanUp(pAd, QID_AC_BK);
1079 RTMPRingCleanUp(pAd, QID_AC_BE);
1080 RTMPRingCleanUp(pAd, QID_AC_VI);
1081 RTMPRingCleanUp(pAd, QID_AC_VO);
1082 RTMPRingCleanUp(pAd, QID_HCCA);
1083 RTMPRingCleanUp(pAd, QID_MGMT);
1084 RTMPRingCleanUp(pAd, QID_RX);
1086 // 2. Send wake up command.
1087 AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02);
1088 // 2-1. wait command ok.
1089 AsicCheckCommanOk(pAd, PowerWakeCID);
1091 // When PCI clock is off, don't want to service interrupt. So when back to clock on, enable interrupt.
1092 NICEnableInterrupt(pAd);
1094 // 3. Enable Tx DMA.
1095 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
1096 DmaCfg.field.EnableTxDMA = 1;
1097 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
1099 // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
1100 if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
1101 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
1103 // Must using 40MHz.
1104 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
1105 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
1109 // Must using 20MHz.
1110 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1111 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1114 // Clear Radio off flag
1115 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1118 RTMPSetLED(pAd, LED_RADIO_ON);
1120 if (pAd->StaCfg.Psm == PWR_ACTIVE)
1122 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1127 RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0);
1131 #endif // CONFIG_STA_SUPPORT //
1133 VOID RT28xxPciMlmeRadioOn(
1134 IN PRTMP_ADAPTER pAd)
1136 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1139 DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __func__));
1141 if ((pAd->OpMode == OPMODE_AP) ||
1142 ((pAd->OpMode == OPMODE_STA) && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))))
1144 NICResetFromError(pAd);
1147 RTMPRingCleanUp(pAd, QID_AC_BK);
1148 RTMPRingCleanUp(pAd, QID_AC_BE);
1149 RTMPRingCleanUp(pAd, QID_AC_VI);
1150 RTMPRingCleanUp(pAd, QID_AC_VO);
1151 RTMPRingCleanUp(pAd, QID_HCCA);
1152 RTMPRingCleanUp(pAd, QID_MGMT);
1153 RTMPRingCleanUp(pAd, QID_RX);
1157 RTMPEnableRxTx(pAd);
1159 // Clear Radio off flag
1160 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1163 RTMPSetLED(pAd, LED_RADIO_ON);
1166 #ifdef CONFIG_STA_SUPPORT
1167 if ((pAd->OpMode == OPMODE_STA) &&
1168 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)))
1172 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
1174 pAd->Mlme.bPsPollTimerRunning = FALSE;
1175 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1176 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
1177 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1179 #endif // CONFIG_STA_SUPPORT //
1182 VOID RT28xxPciMlmeRadioOFF(
1183 IN PRTMP_ADAPTER pAd)
1185 WPDMA_GLO_CFG_STRUC GloCfg;
1188 if (pAd->StaCfg.bRadio == TRUE)
1190 DBGPRINT(RT_DEBUG_TRACE,("-->MlmeRadioOff() return on bRadio == TRUE; \n"));
1194 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1197 DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __func__));
1200 RTMPSetLED(pAd, LED_RADIO_OFF);
1202 #ifdef CONFIG_STA_SUPPORT
1203 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1207 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1209 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
1210 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1213 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
1217 // Always radio on since the NIC needs to set the MCU command (LED_RADIO_OFF).
\r
1218 if ((pAd->OpMode == OPMODE_STA) &&
\r
1219 (IDLE_ON(pAd)) &&
\r
1220 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
\r
1222 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
\r
1225 pAd->Mlme.bPsPollTimerRunning = FALSE;
1226 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1227 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
1230 // Link down first if any association exists
1231 if (INFRA_ON(pAd) || ADHOC_ON(pAd))
1232 LinkDown(pAd, FALSE);
1233 RTMPusecDelay(10000);
1234 //==========================================
1235 // Clean up old bss table
1236 BssTableInit(&pAd->ScanTab);
1238 RTMPRingCleanUp(pAd, QID_AC_BK);
1239 RTMPRingCleanUp(pAd, QID_AC_BE);
1240 RTMPRingCleanUp(pAd, QID_AC_VI);
1241 RTMPRingCleanUp(pAd, QID_AC_VO);
1242 RTMPRingCleanUp(pAd, QID_HCCA);
1243 RTMPRingCleanUp(pAd, QID_MGMT);
1244 RTMPRingCleanUp(pAd, QID_RX);
1246 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
1248 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 500);
1252 #endif // CONFIG_STA_SUPPORT //
1254 // Set Radio off flag
1255 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1257 // Disable Tx/Rx DMA
1258 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA
1259 GloCfg.field.EnableTxDMA = 0;
1260 GloCfg.field.EnableRxDMA = 0;
1261 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); // abort all TX rings
1264 // MAC_SYS_CTRL => value = 0x0 => 40mA
1265 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0);
1267 // PWR_PIN_CFG => value = 0x0 => 40mA
1268 RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0);
1270 // TX_PIN_CFG => value = 0x0 => 20mA
1271 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0);
1273 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
1275 // Must using 40MHz.
1276 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
1280 // Must using 20MHz.
1281 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
1284 // Waiting for DMA idle
1288 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
1289 if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
1292 RTMPusecDelay(1000);