]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/rt2860/common/cmm_mac_pci.c
d910bfdbd2f361b3b78db717f2cb59d1d2cb2b9a
[net-next-2.6.git] / drivers / staging / rt2860 / common / cmm_mac_pci.c
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26 */
27
28
29 #ifdef RTMP_MAC_PCI
30 #include        "../rt_config.h"
31
32
33 /*
34         ========================================================================
35
36         Routine Description:
37                 Allocate DMA memory blocks for send, receive
38
39         Arguments:
40                 Adapter         Pointer to our adapter
41
42         Return Value:
43                 NDIS_STATUS_SUCCESS
44                 NDIS_STATUS_FAILURE
45                 NDIS_STATUS_RESOURCES
46
47         IRQL = PASSIVE_LEVEL
48
49         Note:
50
51         ========================================================================
52 */
53 NDIS_STATUS     RTMPAllocTxRxRingMemory(
54         IN      PRTMP_ADAPTER   pAd)
55 {
56         NDIS_STATUS             Status = NDIS_STATUS_SUCCESS;
57         ULONG                   RingBasePaHigh;
58         ULONG                   RingBasePaLow;
59         PVOID                   RingBaseVa;
60         INT                             index, num;
61         PTXD_STRUC              pTxD;
62         PRXD_STRUC              pRxD;
63         ULONG                   ErrorValue = 0;
64         PRTMP_TX_RING   pTxRing;
65         PRTMP_DMABUF    pDmaBuf;
66         PNDIS_PACKET    pPacket;
67 //      PRTMP_REORDERBUF        pReorderBuf;
68
69         DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n"));
70         do
71         {
72                 //
73                 // Allocate all ring descriptors, include TxD, RxD, MgmtD.
74                 // Although each size is different, to prevent cacheline and alignment
75                 // issue, I intentional set them all to 64 bytes.
76                 //
77                 for (num=0; num<NUM_OF_TX_RING; num++)
78                 {
79                         ULONG  BufBasePaHigh;
80                         ULONG  BufBasePaLow;
81                         PVOID  BufBaseVa;
82
83                         //
84                         // Allocate Tx ring descriptor's memory (5 TX rings = 4 ACs + 1 HCCA)
85                         //
86                         pAd->TxDescRing[num].AllocSize = TX_RING_SIZE * TXD_SIZE;
87                         RTMP_AllocateTxDescMemory(
88                                 pAd,
89                                 num,
90                                 pAd->TxDescRing[num].AllocSize,
91                                 FALSE,
92                                 &pAd->TxDescRing[num].AllocVa,
93                                 &pAd->TxDescRing[num].AllocPa);
94
95                         if (pAd->TxDescRing[num].AllocVa == NULL)
96                         {
97                                 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
98                                 DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
99                                 Status = NDIS_STATUS_RESOURCES;
100                                 break;
101                         }
102
103                         // Zero init this memory block
104                         NdisZeroMemory(pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocSize);
105
106                         // Save PA & VA for further operation
107                         RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxDescRing[num].AllocPa);
108                         RingBasePaLow  = RTMP_GetPhysicalAddressLow (pAd->TxDescRing[num].AllocPa);
109                         RingBaseVa     = pAd->TxDescRing[num].AllocVa;
110
111                         //
112                         // Allocate all 1st TXBuf's memory for this TxRing
113                         //
114                         pAd->TxBufSpace[num].AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE;
115                         RTMP_AllocateFirstTxBuffer(
116                                 pAd,
117                                 num,
118                                 pAd->TxBufSpace[num].AllocSize,
119                                 FALSE,
120                                 &pAd->TxBufSpace[num].AllocVa,
121                                 &pAd->TxBufSpace[num].AllocPa);
122
123                         if (pAd->TxBufSpace[num].AllocVa == NULL)
124                         {
125                                 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
126                                 DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
127                                 Status = NDIS_STATUS_RESOURCES;
128                                 break;
129                         }
130
131                         // Zero init this memory block
132                         NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocSize);
133
134                         // Save PA & VA for further operation
135                         BufBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxBufSpace[num].AllocPa);
136                         BufBasePaLow  = RTMP_GetPhysicalAddressLow (pAd->TxBufSpace[num].AllocPa);
137                         BufBaseVa     = pAd->TxBufSpace[num].AllocVa;
138
139                         //
140                         // Initialize Tx Ring Descriptor and associated buffer memory
141                         //
142                         pTxRing = &pAd->TxRing[num];
143                         for (index = 0; index < TX_RING_SIZE; index++)
144                         {
145                                 pTxRing->Cell[index].pNdisPacket = NULL;
146                                 pTxRing->Cell[index].pNextNdisPacket = NULL;
147                                 // Init Tx Ring Size, Va, Pa variables
148                                 pTxRing->Cell[index].AllocSize = TXD_SIZE;
149                                 pTxRing->Cell[index].AllocVa = RingBaseVa;
150                                 RTMP_SetPhysicalAddressHigh(pTxRing->Cell[index].AllocPa, RingBasePaHigh);
151                                 RTMP_SetPhysicalAddressLow (pTxRing->Cell[index].AllocPa, RingBasePaLow);
152
153                                 // Setup Tx Buffer size & address. only 802.11 header will store in this space
154                                 pDmaBuf = &pTxRing->Cell[index].DmaBuf;
155                                 pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE;
156                                 pDmaBuf->AllocVa = BufBaseVa;
157                                 RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, BufBasePaHigh);
158                                 RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, BufBasePaLow);
159
160                                 // link the pre-allocated TxBuf to TXD
161                                 pTxD = (PTXD_STRUC) pTxRing->Cell[index].AllocVa;
162                                 pTxD->SDPtr0 = BufBasePaLow;
163                                 // advance to next ring descriptor address
164                                 pTxD->DMADONE = 1;
165                                 RingBasePaLow += TXD_SIZE;
166                                 RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE;
167
168                                 // advance to next TxBuf address
169                                 BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE;
170                                 BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE;
171                         }
172                         DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d entry allocated\n", num, index));
173                 }
174                 if (Status == NDIS_STATUS_RESOURCES)
175                         break;
176
177                 //
178                 // Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler
179                 //
180                 pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE;
181                 RTMP_AllocateMgmtDescMemory(
182                         pAd,
183                         pAd->MgmtDescRing.AllocSize,
184                         FALSE,
185                         &pAd->MgmtDescRing.AllocVa,
186                         &pAd->MgmtDescRing.AllocPa);
187
188                 if (pAd->MgmtDescRing.AllocVa == NULL)
189                 {
190                         ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
191                         DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
192                         Status = NDIS_STATUS_RESOURCES;
193                         break;
194                 }
195
196                 // Zero init this memory block
197                 NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize);
198
199                 // Save PA & VA for further operation
200                 RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa);
201                 RingBasePaLow  = RTMP_GetPhysicalAddressLow (pAd->MgmtDescRing.AllocPa);
202                 RingBaseVa     = pAd->MgmtDescRing.AllocVa;
203
204                 //
205                 // Initialize MGMT Ring and associated buffer memory
206                 //
207                 for (index = 0; index < MGMT_RING_SIZE; index++)
208                 {
209                         pAd->MgmtRing.Cell[index].pNdisPacket = NULL;
210                         pAd->MgmtRing.Cell[index].pNextNdisPacket = NULL;
211                         // Init MGMT Ring Size, Va, Pa variables
212                         pAd->MgmtRing.Cell[index].AllocSize = TXD_SIZE;
213                         pAd->MgmtRing.Cell[index].AllocVa = RingBaseVa;
214                         RTMP_SetPhysicalAddressHigh(pAd->MgmtRing.Cell[index].AllocPa, RingBasePaHigh);
215                         RTMP_SetPhysicalAddressLow (pAd->MgmtRing.Cell[index].AllocPa, RingBasePaLow);
216
217                         // Offset to next ring descriptor address
218                         RingBasePaLow += TXD_SIZE;
219                         RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE;
220
221                         // link the pre-allocated TxBuf to TXD
222                         pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[index].AllocVa;
223                         pTxD->DMADONE = 1;
224
225                         // no pre-allocated buffer required in MgmtRing for scatter-gather case
226                 }
227                 DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", index));
228
229                 //
230                 // Allocate RX ring descriptor's memory except Tx ring which allocated eariler
231                 //
232                 pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE;
233                 RTMP_AllocateRxDescMemory(
234                         pAd,
235                         pAd->RxDescRing.AllocSize,
236                         FALSE,
237                         &pAd->RxDescRing.AllocVa,
238                         &pAd->RxDescRing.AllocPa);
239
240                 if (pAd->RxDescRing.AllocVa == NULL)
241                 {
242                         ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
243                         DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
244                         Status = NDIS_STATUS_RESOURCES;
245                         break;
246                 }
247
248                 // Zero init this memory block
249                 NdisZeroMemory(pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize);
250
251
252                 DBGPRINT(RT_DEBUG_OFF,
253                                         ("RX DESC %p  size = %ld\n", pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize));
254
255                 // Save PA & VA for further operation
256                 RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->RxDescRing.AllocPa);
257                 RingBasePaLow  = RTMP_GetPhysicalAddressLow (pAd->RxDescRing.AllocPa);
258                 RingBaseVa     = pAd->RxDescRing.AllocVa;
259
260                 //
261                 // Initialize Rx Ring and associated buffer memory
262                 //
263                 for (index = 0; index < RX_RING_SIZE; index++)
264                 {
265                         // Init RX Ring Size, Va, Pa variables
266                         pAd->RxRing.Cell[index].AllocSize = RXD_SIZE;
267                         pAd->RxRing.Cell[index].AllocVa = RingBaseVa;
268                         RTMP_SetPhysicalAddressHigh(pAd->RxRing.Cell[index].AllocPa, RingBasePaHigh);
269                         RTMP_SetPhysicalAddressLow (pAd->RxRing.Cell[index].AllocPa, RingBasePaLow);
270
271                         //NdisZeroMemory(RingBaseVa, RXD_SIZE);
272
273                         // Offset to next ring descriptor address
274                         RingBasePaLow += RXD_SIZE;
275                         RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE;
276
277                         // Setup Rx associated Buffer size & allocate share memory
278                         pDmaBuf = &pAd->RxRing.Cell[index].DmaBuf;
279                         pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE;
280                         pPacket = RTMP_AllocateRxPacketBuffer(
281                                 pAd,
282                                 pDmaBuf->AllocSize,
283                                 FALSE,
284                                 &pDmaBuf->AllocVa,
285                                 &pDmaBuf->AllocPa);
286
287                         /* keep allocated rx packet */
288                         pAd->RxRing.Cell[index].pNdisPacket = pPacket;
289
290                         // Error handling
291                         if (pDmaBuf->AllocVa == NULL)
292                         {
293                                 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
294                                 DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n"));
295                                 Status = NDIS_STATUS_RESOURCES;
296                                 break;
297                         }
298
299                         // Zero init this memory block
300                         NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize);
301
302                         // Write RxD buffer address & allocated buffer length
303                         pRxD = (PRXD_STRUC) pAd->RxRing.Cell[index].AllocVa;
304                         pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa);
305                         pRxD->DDONE = 0;
306
307                 }
308
309                 DBGPRINT(RT_DEBUG_TRACE, ("Rx Ring: total %d entry allocated\n", index));
310
311         }       while (FALSE);
312
313
314         NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME));
315         pAd->FragFrame.pFragPacket =  RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
316
317         if (pAd->FragFrame.pFragPacket == NULL)
318         {
319                 Status = NDIS_STATUS_RESOURCES;
320         }
321
322         if (Status != NDIS_STATUS_SUCCESS)
323         {
324                 // Log error inforamtion
325                 NdisWriteErrorLogEntry(
326                         pAd->AdapterHandle,
327                         NDIS_ERROR_CODE_OUT_OF_RESOURCES,
328                         1,
329                         ErrorValue);
330         }
331
332         // Following code segment get from original func:NICInitTxRxRingAndBacklogQueue(), now should integrate it to here.
333         {
334                 DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitTxRxRingAndBacklogQueue\n"));
335
336 /*
337                 // Disable DMA.
338                 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
339                 GloCfg.word &= 0xff0;
340                 GloCfg.field.EnTXWriteBackDDONE =1;
341                 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
342 */
343
344                 // Initialize all transmit related software queues
345                 for(index = 0; index < NUM_OF_TX_RING; index++)
346                 {
347                         InitializeQueueHeader(&pAd->TxSwQueue[index]);
348                         // Init TX rings index pointer
349                         pAd->TxRing[index].TxSwFreeIdx = 0;
350                         pAd->TxRing[index].TxCpuIdx = 0;
351                         //RTMP_IO_WRITE32(pAd, (TX_CTX_IDX0 + i * 0x10) ,  pAd->TxRing[i].TX_CTX_IDX);
352                 }
353
354                 // Init RX Ring index pointer
355                 pAd->RxRing.RxSwReadIdx = 0;
356                 pAd->RxRing.RxCpuIdx = RX_RING_SIZE - 1;
357                 //RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RX_CRX_IDX0);
358
359
360                 // init MGMT ring index pointer
361                 pAd->MgmtRing.TxSwFreeIdx = 0;
362                 pAd->MgmtRing.TxCpuIdx = 0;
363
364                 pAd->PrivateInfo.TxRingFullCnt = 0;
365
366                 DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitTxRxRingAndBacklogQueue\n"));
367         }
368
369         DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status));
370         return Status;
371 }
372
373
374
375
376 /*
377         ========================================================================
378
379         Routine Description:
380                 Reset NIC Asics. Call after rest DMA. So reset TX_CTX_IDX to zero.
381
382         Arguments:
383                 Adapter                                         Pointer to our adapter
384
385         Return Value:
386                 None
387
388         IRQL = PASSIVE_LEVEL
389         IRQL = DISPATCH_LEVEL
390
391         Note:
392                 Reset NIC to initial state AS IS system boot up time.
393
394         ========================================================================
395 */
396 VOID    RTMPRingCleanUp(
397         IN      PRTMP_ADAPTER   pAd,
398         IN      UCHAR                   RingType)
399 {
400         PTXD_STRUC              pTxD;
401         PRXD_STRUC              pRxD;
402         PQUEUE_ENTRY    pEntry;
403         PNDIS_PACKET    pPacket;
404         int                             i;
405         PRTMP_TX_RING   pTxRing;
406         unsigned long   IrqFlags;
407         //UINT32                        RxSwReadIdx;
408
409
410         DBGPRINT(RT_DEBUG_TRACE,("RTMPRingCleanUp(RingIdx=%d, Pending-NDIS=%ld)\n", RingType, pAd->RalinkCounters.PendingNdisPacketCount));
411         switch (RingType)
412         {
413                 case QID_AC_BK:
414                 case QID_AC_BE:
415                 case QID_AC_VI:
416                 case QID_AC_VO:
417
418                         pTxRing = &pAd->TxRing[RingType];
419
420                         RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
421                         // We have to clean all descriptors in case some error happened with reset
422                         for (i=0; i<TX_RING_SIZE; i++) // We have to scan all TX ring
423                         {
424                                 pTxD  = (PTXD_STRUC) pTxRing->Cell[i].AllocVa;
425
426                                 pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNdisPacket;
427                                 // release scatter-and-gather NDIS_PACKET
428                                 if (pPacket)
429                                 {
430                                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
431                                         pTxRing->Cell[i].pNdisPacket = NULL;
432                                 }
433
434                                 pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNextNdisPacket;
435                                 // release scatter-and-gather NDIS_PACKET
436                                 if (pPacket)
437                                 {
438                                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
439                                         pTxRing->Cell[i].pNextNdisPacket = NULL;
440                                 }
441                         }
442
443                         RTMP_IO_READ32(pAd, TX_DTX_IDX0 + RingType * 0x10, &pTxRing->TxDmaIdx);
444                         pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx;
445                         pTxRing->TxCpuIdx = pTxRing->TxDmaIdx;
446                         RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + RingType * 0x10, pTxRing->TxCpuIdx);
447
448                         RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
449
450                         RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
451                         while (pAd->TxSwQueue[RingType].Head != NULL)
452                         {
453                                 pEntry = RemoveHeadQueue(&pAd->TxSwQueue[RingType]);
454                                 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
455                                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
456                                 DBGPRINT(RT_DEBUG_TRACE,("Release 1 NDIS packet from s/w backlog queue\n"));
457                         }
458                         RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
459                         break;
460
461                 case QID_MGMT:
462                         // We have to clean all descriptors in case some error happened with reset
463                         NdisAcquireSpinLock(&pAd->MgmtRingLock);
464
465                         for (i=0; i<MGMT_RING_SIZE; i++)
466                         {
467                                 pTxD  = (PTXD_STRUC) pAd->MgmtRing.Cell[i].AllocVa;
468
469                                 pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNdisPacket;
470                                 // rlease scatter-and-gather NDIS_PACKET
471                                 if (pPacket)
472                                 {
473                                         PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
474                                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
475                                 }
476                                 pAd->MgmtRing.Cell[i].pNdisPacket = NULL;
477
478                                 pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNextNdisPacket;
479                                 // release scatter-and-gather NDIS_PACKET
480                                 if (pPacket)
481                                 {
482                                         PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
483                                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
484                         }
485                                 pAd->MgmtRing.Cell[i].pNextNdisPacket = NULL;
486
487                         }
488
489                         RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pAd->MgmtRing.TxDmaIdx);
490                         pAd->MgmtRing.TxSwFreeIdx = pAd->MgmtRing.TxDmaIdx;
491                         pAd->MgmtRing.TxCpuIdx = pAd->MgmtRing.TxDmaIdx;
492                         RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx);
493
494                         NdisReleaseSpinLock(&pAd->MgmtRingLock);
495                         pAd->RalinkCounters.MgmtRingFullCount = 0;
496                         break;
497
498                 case QID_RX:
499                         // We have to clean all descriptors in case some error happened with reset
500                         NdisAcquireSpinLock(&pAd->RxRingLock);
501
502                         for (i=0; i<RX_RING_SIZE; i++)
503                         {
504                                 pRxD  = (PRXD_STRUC) pAd->RxRing.Cell[i].AllocVa;
505                 pRxD->DDONE = 0 ;
506                         }
507
508                         RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx);
509                         pAd->RxRing.RxSwReadIdx = pAd->RxRing.RxDmaIdx;
510                         pAd->RxRing.RxCpuIdx = ((pAd->RxRing.RxDmaIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxDmaIdx-1));
511                         RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
512
513                         NdisReleaseSpinLock(&pAd->RxRingLock);
514                         break;
515
516                 default:
517                         break;
518         }
519 }
520
521
522 VOID RTMPFreeTxRxRingMemory(
523     IN  PRTMP_ADAPTER   pAd)
524 {
525         int index, num , j;
526         PRTMP_TX_RING pTxRing;
527         PTXD_STRUC        pTxD;
528         PNDIS_PACKET  pPacket;
529         unsigned int  IrqFlags;
530
531         //POS_COOKIE pObj =(POS_COOKIE) pAd->OS_Cookie;
532
533         DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n"));
534
535         // Free TxSwQueue Packet
536         for (index=0; index <NUM_OF_TX_RING; index++)
537         {
538                 PQUEUE_ENTRY pEntry;
539                 PNDIS_PACKET pPacket;
540                 PQUEUE_HEADER   pQueue;
541
542                 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
543                 pQueue = &pAd->TxSwQueue[index];
544                 while (pQueue->Head)
545                 {
546                         pEntry = RemoveHeadQueue(pQueue);
547                         pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
548                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
549                 }
550                 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
551         }
552
553         // Free Tx Ring Packet
554         for (index=0;index< NUM_OF_TX_RING;index++)
555         {
556                 pTxRing = &pAd->TxRing[index];
557
558                 for (j=0; j< TX_RING_SIZE; j++)
559                 {
560                         pTxD = (PTXD_STRUC) (pTxRing->Cell[j].AllocVa);
561                         pPacket = pTxRing->Cell[j].pNdisPacket;
562
563                         if (pPacket)
564                         {
565                                 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
566                                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
567                         }
568                         //Always assign pNdisPacket as NULL after clear
569                         pTxRing->Cell[j].pNdisPacket = NULL;
570
571                         pPacket = pTxRing->Cell[j].pNextNdisPacket;
572
573                         if (pPacket)
574                         {
575                                 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
576                                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
577                         }
578                         //Always assign pNextNdisPacket as NULL after clear
579                         pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
580
581                 }
582         }
583
584         for (index = RX_RING_SIZE - 1 ; index >= 0; index--)
585         {
586                 if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) && (pAd->RxRing.Cell[index].pNdisPacket))
587                 {
588                         PCI_UNMAP_SINGLE(pAd, pAd->RxRing.Cell[index].DmaBuf.AllocPa, pAd->RxRing.Cell[index].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
589                         RELEASE_NDIS_PACKET(pAd, pAd->RxRing.Cell[index].pNdisPacket, NDIS_STATUS_SUCCESS);
590                 }
591         }
592         NdisZeroMemory(pAd->RxRing.Cell, RX_RING_SIZE * sizeof(RTMP_DMACB));
593
594         if (pAd->RxDescRing.AllocVa)
595     {
596                 RTMP_FreeDescMemory(pAd, pAd->RxDescRing.AllocSize, pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocPa);
597     }
598     NdisZeroMemory(&pAd->RxDescRing, sizeof(RTMP_DMABUF));
599
600         if (pAd->MgmtDescRing.AllocVa)
601         {
602                 RTMP_FreeDescMemory(pAd, pAd->MgmtDescRing.AllocSize, pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocPa);
603         }
604         NdisZeroMemory(&pAd->MgmtDescRing, sizeof(RTMP_DMABUF));
605
606         for (num = 0; num < NUM_OF_TX_RING; num++)
607         {
608         if (pAd->TxBufSpace[num].AllocVa)
609                 {
610                         RTMP_FreeFirstTxBuffer(pAd, pAd->TxBufSpace[num].AllocSize, FALSE, pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocPa);
611             }
612             NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(RTMP_DMABUF));
613
614         if (pAd->TxDescRing[num].AllocVa)
615                 {
616                         RTMP_FreeDescMemory(pAd, pAd->TxDescRing[num].AllocSize, pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocPa);
617             }
618             NdisZeroMemory(&pAd->TxDescRing[num], sizeof(RTMP_DMABUF));
619         }
620
621         if (pAd->FragFrame.pFragPacket)
622                 RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS);
623
624         DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n"));
625 }
626
627
628 /***************************************************************************
629   *
630   *     register related procedures.
631   *
632   **************************************************************************/
633 /*
634 ========================================================================
635 Routine Description:
636     Disable DMA.
637
638 Arguments:
639         *pAd                            the raxx interface data pointer
640
641 Return Value:
642         None
643
644 Note:
645 ========================================================================
646 */
647 VOID RT28XXDMADisable(
648         IN RTMP_ADAPTER                 *pAd)
649 {
650         WPDMA_GLO_CFG_STRUC     GloCfg;
651
652
653         RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
654         GloCfg.word &= 0xff0;
655         GloCfg.field.EnTXWriteBackDDONE =1;
656         RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
657 }
658
659
660 /*
661 ========================================================================
662 Routine Description:
663     Enable DMA.
664
665 Arguments:
666         *pAd                            the raxx interface data pointer
667
668 Return Value:
669         None
670
671 Note:
672 ========================================================================
673 */
674 VOID RT28XXDMAEnable(
675         IN RTMP_ADAPTER                 *pAd)
676 {
677         WPDMA_GLO_CFG_STRUC     GloCfg;
678         int i = 0;
679
680         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
681         do
682         {
683                 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
684                 if ((GloCfg.field.TxDMABusy == 0)  && (GloCfg.field.RxDMABusy == 0))
685                         break;
686
687                 DBGPRINT(RT_DEBUG_TRACE, ("==>  DMABusy\n"));
688                 RTMPusecDelay(1000);
689                 i++;
690         }while ( i <200);
691
692         RTMPusecDelay(50);
693
694         GloCfg.field.EnTXWriteBackDDONE = 1;
695         GloCfg.field.WPDMABurstSIZE = 2;
696         GloCfg.field.EnableRxDMA = 1;
697         GloCfg.field.EnableTxDMA = 1;
698
699         DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word));
700         RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
701
702 }
703
704
705 BOOLEAN AsicCheckCommanOk(
706         IN PRTMP_ADAPTER pAd,
707         IN UCHAR                 Command)
708 {
709         UINT32  CmdStatus = 0, CID = 0, i;
710         UINT32  ThisCIDMask = 0;
711
712         i = 0;
713         do
714         {
715                 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
716                 // Find where the command is. Because this is randomly specified by firmware.
717                 if ((CID & CID0MASK) == Command)
718                 {
719                         ThisCIDMask = CID0MASK;
720                         break;
721                 }
722                 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
723                 {
724                         ThisCIDMask = CID1MASK;
725                         break;
726                 }
727                 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
728                 {
729                         ThisCIDMask = CID2MASK;
730                         break;
731                 }
732                 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
733                 {
734                         ThisCIDMask = CID3MASK;
735                         break;
736                 }
737
738                 RTMPusecDelay(100);
739                 i++;
740         }while (i < 200);
741
742         // Get CommandStatus Value
743         RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
744
745         // This command's status is at the same position as command. So AND command position's bitmask to read status.
746         if (i < 200)
747         {
748                 // If Status is 1, the comamnd is success.
749                 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
750                         || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
751                 {
752                         DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
753                         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
754                         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
755                         return TRUE;
756                 }
757                 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
758         }
759         else
760         {
761                 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
762         }
763         // Clear Command and Status.
764         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
765         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
766
767         return FALSE;
768 }
769
770
771 /*
772 ========================================================================
773 Routine Description:
774     Write Beacon buffer to Asic.
775
776 Arguments:
777         *pAd                            the raxx interface data pointer
778
779 Return Value:
780         None
781
782 Note:
783 ========================================================================
784 */
785 VOID RT28xx_UpdateBeaconToAsic(
786         IN RTMP_ADAPTER         *pAd,
787         IN INT                          apidx,
788         IN ULONG                        FrameLen,
789         IN ULONG                        UpdatePos)
790 {
791         ULONG                           CapInfoPos = 0;
792         UCHAR                   *ptr, *ptr_update, *ptr_capinfo;
793         UINT                    i;
794         BOOLEAN                 bBcnReq = FALSE;
795         UCHAR                   bcn_idx = 0;
796
797
798         {
799                 DBGPRINT(RT_DEBUG_ERROR, ("%s() : No valid Interface be found.\n", __func__));
800                 return;
801         }
802
803         //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE)
804         //      || ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL)
805         //              || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP))
806         //      )
807         if (bBcnReq == FALSE)
808         {
809                 /* when the ra interface is down, do not send its beacon frame */
810                 /* clear all zero */
811                 for(i=0; i<TXWI_SIZE; i+=4)
812                         RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, 0x00);
813         }
814         else
815         {
816                 ptr = (PUCHAR)&pAd->BeaconTxWI;
817                 for (i=0; i<TXWI_SIZE; i+=4)  // 16-byte TXWI field
818                 {
819                         UINT32 longptr =  *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
820                         RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, longptr);
821                         ptr += 4;
822                 }
823
824                 // Update CapabilityInfo in Beacon
825                 for (i = CapInfoPos; i < (CapInfoPos+2); i++)
826                 {
827                         RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, *ptr_capinfo);
828                         ptr_capinfo ++;
829                 }
830
831                 if (FrameLen > UpdatePos)
832                 {
833                         for (i= UpdatePos; i< (FrameLen); i++)
834                         {
835                                 RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, *ptr_update);
836                                 ptr_update ++;
837                         }
838                 }
839
840         }
841
842 }
843
844
845 VOID RT28xxPciStaAsicForceWakeup(
846         IN PRTMP_ADAPTER pAd,
847         IN BOOLEAN       bFromTx)
848 {
849     AUTO_WAKEUP_STRUC   AutoWakeupCfg;
850
851     if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
852         return;
853
854     if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW))
855     {
856         DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n"));
857         return;
858     }
859
860     OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WAKEUP_NOW);
861
862     RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
863
864     if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
865                 &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
866     {
867         // Support PCIe Advance Power Save
868         if (bFromTx == TRUE
869                         &&(pAd->Mlme.bPsPollTimerRunning == TRUE))
870         {
871             pAd->Mlme.bPsPollTimerRunning = FALSE;
872                 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
873                 RTMPusecDelay(3000);
874             DBGPRINT(RT_DEBUG_TRACE, ("=======AsicForceWakeup===bFromTx\n"));
875         }
876
877                 AutoWakeupCfg.word = 0;
878                 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
879
880         if (RT28xxPciAsicRadioOn(pAd, DOT11POWERSAVE))
881         {
882 #ifdef PCIE_PS_SUPPORT
883                         // add by johnli, RF power sequence setup, load RF normal operation-mode setup
884                         if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd))
885                         {
886                                 RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
887
888                                 if (pChipOps->AsicReverseRfFromSleepMode)
889                                         pChipOps->AsicReverseRfFromSleepMode(pAd);
890                         }
891                         else
892 #endif // PCIE_PS_SUPPORT //
893                         {
894                         // end johnli
895                                 // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
896                                 if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
897                                         && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
898                                 {
899                                         // Must using 40MHz.
900                                         AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
901                                         AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
902                                 }
903                                 else
904                                 {
905                                         // Must using 20MHz.
906                                         AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
907                                         AsicLockChannel(pAd, pAd->CommonCfg.Channel);
908                                 }
909                         }
910         }
911 #ifdef PCIE_PS_SUPPORT
912                 // 3090 MCU Wakeup command needs more time to be stable.
913                 // Before stable, don't issue other MCU command to prevent from firmware error.
914                 if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd)
915                         && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
916                         && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
917                         {
918                         DBGPRINT(RT_DEBUG_TRACE, ("<==RT28xxPciStaAsicForceWakeup::Release the MCU Lock(3090)\n"));
919                         RTMP_SEM_LOCK(&pAd->McuCmdLock);
920                         pAd->brt30xxBanMcuCmd = FALSE;
921                         RTMP_SEM_UNLOCK(&pAd->McuCmdLock);
922                         }
923 #endif // PCIE_PS_SUPPORT //
924     }
925     else
926     {
927         // PCI, 2860-PCIe
928          DBGPRINT(RT_DEBUG_TRACE, ("<==RT28xxPciStaAsicForceWakeup::Original PCI Power Saving\n"));
929         AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
930         AutoWakeupCfg.word = 0;
931             RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
932     }
933
934     OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
935     OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW);
936     DBGPRINT(RT_DEBUG_TRACE, ("<=======RT28xxPciStaAsicForceWakeup\n"));
937 }
938
939
940 VOID RT28xxPciStaAsicSleepThenAutoWakeup(
941         IN PRTMP_ADAPTER pAd,
942         IN USHORT TbttNumToNextWakeUp)
943 {
944         BOOLEAN brc;
945
946         if (pAd->StaCfg.bRadio == FALSE)
947         {
948                 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
949                 return;
950         }
951         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
952                 &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
953         {
954                 ULONG   Now = 0;
955                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW))
956                 {
957                         DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n"));
958                         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
959                         return;
960                 }
961
962                 NdisGetSystemUpTime(&Now);
963                 // If last send NULL fram time is too close to this receiving beacon (within 8ms), don't go to sleep for this DTM.
964                 // Because Some AP can't queuing outgoing frames immediately.
965                 if (((pAd->Mlme.LastSendNULLpsmTime + 8) >= Now) && (pAd->Mlme.LastSendNULLpsmTime <= Now))
966                 {
967                         DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu :  RxCountSinceLastNULL = %lu. \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL));
968                         return;
969                 }
970                 else if ((pAd->RalinkCounters.RxCountSinceLastNULL > 0) && ((pAd->Mlme.LastSendNULLpsmTime + pAd->CommonCfg.BeaconPeriod) >= Now))
971                 {
972                         DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu: RxCountSinceLastNULL = %lu > 0 \n", Now, pAd->Mlme.LastSendNULLpsmTime,  pAd->RalinkCounters.RxCountSinceLastNULL));
973                         return;
974                 }
975
976                 brc = RT28xxPciAsicRadioOff(pAd, DOT11POWERSAVE, TbttNumToNextWakeUp);
977                 if (brc==TRUE)
978                         OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
979         }
980         else
981         {
982                 AUTO_WAKEUP_STRUC       AutoWakeupCfg;
983                 // we have decided to SLEEP, so at least do it for a BEACON period.
984                 if (TbttNumToNextWakeUp == 0)
985                         TbttNumToNextWakeUp = 1;
986
987                 //RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt);
988
989                 AutoWakeupCfg.word = 0;
990                 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
991                 AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
992                 AutoWakeupCfg.field.EnableAutoWakeup = 1;
993                 AutoWakeupCfg.field.AutoLeadTime = 5;
994                 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
995                 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x00);   // send POWER-SAVE command to MCU. Timeout 40us.
996                 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
997                 DBGPRINT(RT_DEBUG_TRACE, ("<-- %s, TbttNumToNextWakeUp=%d \n", __func__, TbttNumToNextWakeUp));
998         }
999
1000 }
1001
1002 VOID PsPollWakeExec(
1003         IN PVOID SystemSpecific1,
1004         IN PVOID FunctionContext,
1005         IN PVOID SystemSpecific2,
1006         IN PVOID SystemSpecific3)
1007 {
1008         RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1009         unsigned long flags;
1010
1011     DBGPRINT(RT_DEBUG_TRACE,("-->PsPollWakeExec \n"));
1012         RTMP_INT_LOCK(&pAd->irq_lock, flags);
1013     if (pAd->Mlme.bPsPollTimerRunning)
1014     {
1015             RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
1016     }
1017     pAd->Mlme.bPsPollTimerRunning = FALSE;
1018         RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
1019 #ifdef PCIE_PS_SUPPORT
1020         // For rt30xx power solution 3, Use software timer to wake up in psm. So call
1021         // AsicForceWakeup here instead of handling twakeup interrupt.
1022         if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd))
1023         && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
1024         && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
1025         {
1026                 DBGPRINT(RT_DEBUG_TRACE,("<--PsPollWakeExec::3090 calls AsicForceWakeup(pAd, DOT11POWERSAVE) in advance \n"));
1027                 AsicForceWakeup(pAd, DOT11POWERSAVE);
1028         }
1029 #endif // PCIE_PS_SUPPORT //
1030 }
1031
1032 VOID  RadioOnExec(
1033         IN PVOID SystemSpecific1,
1034         IN PVOID FunctionContext,
1035         IN PVOID SystemSpecific2,
1036         IN PVOID SystemSpecific3)
1037 {
1038         RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1039         RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
1040         WPDMA_GLO_CFG_STRUC     DmaCfg;
1041         BOOLEAN                         Cancelled;
1042
1043         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1044         {
1045                 DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on fOP_STATUS_DOZE == TRUE; \n"));
1046 //KH Debug: Add the compile flag "RT2860 and condition
1047 #ifdef RTMP_PCI_SUPPORT
1048                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
1049                         &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1050                 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1051 #endif // RTMP_PCI_SUPPORT //
1052                 return;
1053         }
1054
1055         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1056         {
1057                 DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on SCAN_IN_PROGRESS; \n"));
1058 #ifdef RTMP_PCI_SUPPORT
1059 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
1060         &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1061                 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1062 #endif // RTMP_PCI_SUPPORT //
1063                 return;
1064         }
1065 //KH Debug: need to check. I add the compile flag "CONFIG_STA_SUPPORT" to enclose the following codes.
1066 #ifdef RTMP_PCI_SUPPORT
1067 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
1068         &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1069         {
1070         pAd->Mlme.bPsPollTimerRunning = FALSE;
1071         RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1072         }
1073 #endif // RTMP_PCI_SUPPORT //
1074         if (pAd->StaCfg.bRadio == TRUE)
1075         {
1076                 pAd->bPCIclkOff = FALSE;
1077                 RTMPRingCleanUp(pAd, QID_AC_BK);
1078                 RTMPRingCleanUp(pAd, QID_AC_BE);
1079                 RTMPRingCleanUp(pAd, QID_AC_VI);
1080                 RTMPRingCleanUp(pAd, QID_AC_VO);
1081                 RTMPRingCleanUp(pAd, QID_MGMT);
1082                 RTMPRingCleanUp(pAd, QID_RX);
1083
1084                 // 2. Send wake up command.
1085                 AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02);
1086                 // 2-1. wait command ok.
1087                 AsicCheckCommanOk(pAd, PowerWakeCID);
1088
1089                 // When PCI clock is off, don't want to service interrupt. So when back to clock on, enable interrupt.
1090                 //RTMP_IO_WRITE32(pAd, INT_MASK_CSR, (DELAYINTMASK|RxINT));
1091                 RTMP_ASIC_INTERRUPT_ENABLE(pAd);
1092
1093                 // 3. Enable Tx DMA.
1094                 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
1095                 DmaCfg.field.EnableTxDMA = 1;
1096                 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
1097
1098                 // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
1099                 if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
1100                         && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
1101                 {
1102                         // Must using 40MHz.
1103                         AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
1104                         AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
1105                 }
1106                 else
1107                 {
1108                         // Must using 20MHz.
1109                         AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1110                         AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1111                 }
1112
1113 //KH Debug:The following codes should be enclosed by RT3090 compile flag
1114                 if (pChipOps->AsicReverseRfFromSleepMode)
1115                         pChipOps->AsicReverseRfFromSleepMode(pAd);
1116
1117 #ifdef PCIE_PS_SUPPORT
1118 // 3090 MCU Wakeup command needs more time to be stable.
1119 // Before stable, don't issue other MCU command to prevent from firmware error.
1120 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)
1121         && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
1122         && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
1123         {
1124         RTMP_SEM_LOCK(&pAd->McuCmdLock);
1125         pAd->brt30xxBanMcuCmd = FALSE;
1126         RTMP_SEM_UNLOCK(&pAd->McuCmdLock);
1127         }
1128 #endif // PCIE_PS_SUPPORT //
1129
1130                 // Clear Radio off flag
1131                 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1132
1133                 // Set LED
1134                 RTMPSetLED(pAd, LED_RADIO_ON);
1135
1136         if (pAd->StaCfg.Psm == PWR_ACTIVE)
1137         {
1138                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1139         }
1140         }
1141         else
1142         {
1143                 RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0);
1144         }
1145 }
1146
1147 /*
1148         ==========================================================================
1149         Description:
1150                 This routine sends command to firmware and turn our chip to wake up mode from power save mode.
1151                 Both RadioOn and .11 power save function needs to call this routine.
1152         Input:
1153                 Level = GUIRADIO_OFF : call this function is from Radio Off to Radio On.  Need to restore PCI host value.
1154                 Level = other value : normal wake up function.
1155
1156         ==========================================================================
1157  */
1158 BOOLEAN RT28xxPciAsicRadioOn(
1159         IN PRTMP_ADAPTER pAd,
1160         IN UCHAR     Level)
1161 {
1162     //WPDMA_GLO_CFG_STRUC       DmaCfg;
1163         BOOLEAN                         Cancelled;
1164     //UINT32                        MACValue;
1165
1166         if (pAd->OpMode == OPMODE_AP && Level==DOT11POWERSAVE)
1167                 return FALSE;
1168
1169         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1170         {
1171                 if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1172         {
1173             pAd->Mlme.bPsPollTimerRunning = FALSE;
1174                 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1175                 }
1176                 if ((pAd->StaCfg.PSControl.field.EnableNewPS == TRUE &&
1177                      (Level == GUIRADIO_OFF || Level == GUI_IDLE_POWER_SAVE)) ||
1178                     RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)) {
1179                         // Some chips don't need to delay 6ms, so copy RTMPPCIePowerLinkCtrlRestore
1180                         // return condition here.
1181                         /*
1182                         if (((pAd->MACVersion&0xffff0000) != 0x28600000)
1183                                 && ((pAd->DeviceID == NIC2860_PCIe_DEVICE_ID)
1184                                 ||(pAd->DeviceID == NIC2790_PCIe_DEVICE_ID)))
1185                         */
1186                 {
1187                         DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOn ()\n"));
1188                         // 1. Set PCI Link Control in Configuration Space.
1189                         RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
1190                         RTMPusecDelay(6000);
1191                 }
1192         }
1193         }
1194
1195 #ifdef PCIE_PS_SUPPORT
1196 if (!(((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)
1197         && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
1198         && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))))
1199 #endif // PCIE_PS_SUPPORT //
1200         {
1201     pAd->bPCIclkOff = FALSE;
1202                 DBGPRINT(RT_DEBUG_TRACE, ("PSM :309xbPCIclkOff == %d\n", pAd->bPCIclkOff));
1203         }
1204         // 2. Send wake up command.
1205         AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02);
1206     pAd->bPCIclkOff = FALSE;
1207         // 2-1. wait command ok.
1208         AsicCheckCommanOk(pAd, PowerWakeCID);
1209         RTMP_ASIC_INTERRUPT_ENABLE(pAd);
1210
1211         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
1212         if (Level == GUI_IDLE_POWER_SAVE)
1213         {
1214 #ifdef  PCIE_PS_SUPPORT
1215
1216                         // add by johnli, RF power sequence setup, load RF normal operation-mode setup
1217                         if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)))
1218                         {
1219                                 RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
1220
1221                                 if (pChipOps->AsicReverseRfFromSleepMode)
1222                                         pChipOps->AsicReverseRfFromSleepMode(pAd);
1223                                 // 3090 MCU Wakeup command needs more time to be stable.
1224                                 // Before stable, don't issue other MCU command to prevent from firmware error.
1225                                 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)
1226                                         && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
1227                                         && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
1228                                         {
1229                                                 RTMP_SEM_LOCK(&pAd->McuCmdLock);
1230                                                 pAd->brt30xxBanMcuCmd = FALSE;
1231                                                 RTMP_SEM_UNLOCK(&pAd->McuCmdLock);
1232                                         }
1233                         }
1234                         else
1235                         // end johnli
1236 #endif // PCIE_PS_SUPPORT //
1237                         {
1238                         // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
1239                                 {
1240                                 if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
1241                                         && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
1242                                 {
1243                                         // Must using 40MHz.
1244                                         AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
1245                                         AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
1246                                 }
1247                                 else
1248                                 {
1249                                         // Must using 20MHz.
1250                                         AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1251                                         AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1252                                 }
1253                                 }
1254
1255                         }
1256         }
1257         return TRUE;
1258
1259 }
1260
1261
1262 /*
1263         ==========================================================================
1264         Description:
1265                 This routine sends command to firmware and turn our chip to power save mode.
1266                 Both RadioOff and .11 power save function needs to call this routine.
1267         Input:
1268                 Level = GUIRADIO_OFF  : GUI Radio Off mode
1269                 Level = DOT11POWERSAVE  : 802.11 power save mode
1270                 Level = RTMP_HALT  : When Disable device.
1271
1272         ==========================================================================
1273  */
1274 BOOLEAN RT28xxPciAsicRadioOff(
1275         IN PRTMP_ADAPTER    pAd,
1276         IN UCHAR            Level,
1277         IN USHORT           TbttNumToNextWakeUp)
1278 {
1279         WPDMA_GLO_CFG_STRUC     DmaCfg;
1280         UCHAR           i, tempBBP_R3 = 0;
1281         BOOLEAN         brc = FALSE, Cancelled;
1282     UINT32              TbTTTime = 0;
1283         UINT32          PsPollTime = 0/*, MACValue*/;
1284     ULONG               BeaconPeriodTime;
1285     UINT32              RxDmaIdx, RxCpuIdx;
1286         DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> Lv= %d, TxCpuIdx = %d, TxDmaIdx = %d. RxCpuIdx = %d, RxDmaIdx = %d.\n", Level,pAd->TxRing[0].TxCpuIdx, pAd->TxRing[0].TxDmaIdx, pAd->RxRing.RxCpuIdx, pAd->RxRing.RxDmaIdx));
1287
1288         if (pAd->OpMode == OPMODE_AP && Level==DOT11POWERSAVE)
1289                 return FALSE;
1290
1291     // Check Rx DMA busy status, if more than half is occupied, give up this radio off.
1292         RTMP_IO_READ32(pAd, RX_DRX_IDX , &RxDmaIdx);
1293         RTMP_IO_READ32(pAd, RX_CRX_IDX , &RxCpuIdx);
1294         if ((RxDmaIdx > RxCpuIdx) && ((RxDmaIdx - RxCpuIdx) > RX_RING_SIZE/3))
1295         {
1296                 DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return1. RxDmaIdx = %d ,  RxCpuIdx = %d. \n", RxDmaIdx, RxCpuIdx));
1297                 return FALSE;
1298         }
1299         else if ((RxCpuIdx >= RxDmaIdx) && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE/3))
1300         {
1301                 DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return2.  RxCpuIdx = %d. RxDmaIdx = %d ,  \n", RxCpuIdx, RxDmaIdx));
1302                 return FALSE;
1303         }
1304
1305     // Once go into this function, disable tx because don't want too many packets in queue to prevent HW stops.
1306         //pAd->bPCIclkOffDisableTx = TRUE;
1307         RTMP_SET_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
1308         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
1309                 && pAd->OpMode == OPMODE_STA
1310                 &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE
1311                 )
1312         {
1313             RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
1314             RTMPCancelTimer(&pAd->Mlme.PsPollTimer,     &Cancelled);
1315
1316             if (Level == DOT11POWERSAVE)
1317                 {
1318                         RTMP_IO_READ32(pAd, TBTT_TIMER, &TbTTTime);
1319                         TbTTTime &= 0x1ffff;
1320                         // 00. check if need to do sleep in this DTIM period.   If next beacon will arrive within 30ms , ...doesn't necessarily sleep.
1321                         // TbTTTime uint = 64us, LEAD_TIME unit = 1024us, PsPollTime unit = 1ms
1322                 if  (((64*TbTTTime) <((LEAD_TIME*1024) + 40000)) && (TbttNumToNextWakeUp == 0))
1323                         {
1324                                 DBGPRINT(RT_DEBUG_TRACE, ("TbTTTime = 0x%x , give up this sleep. \n", TbTTTime));
1325                     OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
1326                     //pAd->bPCIclkOffDisableTx = FALSE;
1327                     RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
1328                                 return FALSE;
1329                         }
1330                         else
1331                         {
1332                                 PsPollTime = (64*TbTTTime- LEAD_TIME*1024)/1000;
1333 #ifdef PCIE_PS_SUPPORT
1334                                 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)
1335                                 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
1336                                 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
1337                                 {
1338                                                         PsPollTime -= 5;
1339                                 }
1340                                 else
1341 #endif // PCIE_PS_SUPPORT //
1342                                 PsPollTime -= 3;
1343
1344                     BeaconPeriodTime = pAd->CommonCfg.BeaconPeriod*102/100;
1345                                 if (TbttNumToNextWakeUp > 0)
1346                                         PsPollTime += ((TbttNumToNextWakeUp -1) * BeaconPeriodTime);
1347
1348                     pAd->Mlme.bPsPollTimerRunning = TRUE;
1349                                 RTMPSetTimer(&pAd->Mlme.PsPollTimer, PsPollTime);
1350                         }
1351                 }
1352         }
1353         else
1354         {
1355                 DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOff::Level!=DOT11POWERSAVE \n"));
1356         }
1357
1358         pAd->bPCIclkOffDisableTx = FALSE;
1359
1360     RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
1361
1362     // Set to 1R.
1363         if (pAd->Antenna.field.RxPath > 1 && pAd->OpMode == OPMODE_STA)
1364         {
1365         tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7);
1366                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3);
1367         }
1368
1369         // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
1370         if ((INFRA_ON(pAd) || pAd->OpMode == OPMODE_AP) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
1371                 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
1372         {
1373                 // Must using 40MHz.
1374                 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
1375         }
1376         else
1377         {
1378                 // Must using 20MHz.
1379                 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
1380         }
1381
1382         if (Level != RTMP_HALT)
1383         {
1384                 // Change Interrupt bitmask.
1385     // When PCI clock is off, don't want to service interrupt.
1386         RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt);
1387         }
1388         else
1389         {
1390                 RTMP_ASIC_INTERRUPT_DISABLE(pAd);
1391         }
1392
1393
1394         RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
1395         //  2. Send Sleep command
1396         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
1397         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
1398         // send POWER-SAVE command to MCU. high-byte = 1 save power as much as possible. high byte = 0 save less power
1399         AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x1);
1400         //  2-1. Wait command success
1401         // Status = 1 : success, Status = 2, already sleep, Status = 3, Maybe MAC is busy so can't finish this task.
1402         brc = AsicCheckCommanOk(pAd, PowerSafeCID);
1403
1404         //  3. After 0x30 command is ok, send radio off command. lowbyte = 0 for power safe.
1405         // If 0x30 command is not ok this time, we can ignore 0x35 command. It will make sure not cause firmware'r problem.
1406         if ((Level == DOT11POWERSAVE) && (brc == TRUE))
1407         {
1408                 AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 0, 0x00);     // lowbyte = 0 means to do power safe, NOT turn off radio.
1409                 //  3-1. Wait command success
1410                 AsicCheckCommanOk(pAd, PowerRadioOffCID);
1411         }
1412         else if (brc == TRUE)
1413         {
1414                 AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 1, 0x00);     // lowbyte = 0 means to do power safe, NOT turn off radio.
1415                 //  3-1. Wait command success
1416                 AsicCheckCommanOk(pAd, PowerRadioOffCID);
1417         }
1418
1419         // 1. Wait DMA not busy
1420         i = 0;
1421         do
1422         {
1423                 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
1424                 if ((DmaCfg.field.RxDMABusy == 0) && (DmaCfg.field.TxDMABusy == 0))
1425                         break;
1426                 RTMPusecDelay(20);
1427                 i++;
1428         }while(i < 50);
1429
1430         /*
1431         if (i >= 50)
1432         {
1433                 pAd->CheckDmaBusyCount++;
1434                 DBGPRINT(RT_DEBUG_TRACE, ("DMA Rx keeps busy.  return on AsicRadioOff () CheckDmaBusyCount = %d \n", pAd->CheckDmaBusyCount));
1435         }
1436         else
1437         {
1438                 pAd->CheckDmaBusyCount = 0;
1439         }
1440         */
1441 //KH Debug:My original codes have the follwoing codes, but currecnt codes do not have it.
1442 // Disable for stability. If PCIE Link Control is modified for advance power save, re-covery this code segment.
1443 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x1280);
1444 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_CLKSELECT_40MHZ);
1445
1446 #ifdef PCIE_PS_SUPPORT
1447 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)
1448         && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
1449         && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
1450         {
1451         DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOff::3090 return to skip the following TbttNumToNextWakeUp setting for 279x\n"));
1452         pAd->bPCIclkOff = TRUE;
1453         RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
1454         // For this case, doesn't need to below actions, so return here.
1455         return brc;
1456         }
1457 #endif // PCIE_PS_SUPPORT //
1458
1459         if (Level == DOT11POWERSAVE)
1460         {
1461                 AUTO_WAKEUP_STRUC       AutoWakeupCfg;
1462                 //RTMPSetTimer(&pAd->Mlme.PsPollTimer, 90);
1463
1464                 // we have decided to SLEEP, so at least do it for a BEACON period.
1465                 if (TbttNumToNextWakeUp == 0)
1466                         TbttNumToNextWakeUp = 1;
1467
1468                 AutoWakeupCfg.word = 0;
1469                 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
1470
1471                 // 1. Set auto wake up timer.
1472                 AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
1473                 AutoWakeupCfg.field.EnableAutoWakeup = 1;
1474                 AutoWakeupCfg.field.AutoLeadTime = LEAD_TIME;
1475                 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
1476         }
1477
1478         //  4-1. If it's to disable our device. Need to restore PCI Configuration Space to its original value.
1479         if (Level == RTMP_HALT && pAd->OpMode == OPMODE_STA)
1480         {
1481                 if ((brc == TRUE) && (i < 50))
1482                         RTMPPCIeLinkCtrlSetting(pAd, 1);
1483         }
1484         //  4. Set PCI configuration Space Link Comtrol fields.  Only Radio Off needs to call this function
1485         else if (pAd->OpMode == OPMODE_STA)
1486         {
1487                 if ((brc == TRUE) && (i < 50))
1488                         RTMPPCIeLinkCtrlSetting(pAd, 3);
1489         }
1490
1491         //pAd->bPCIclkOffDisableTx = FALSE;
1492         RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
1493         return TRUE;
1494 }
1495
1496
1497
1498
1499 VOID RT28xxPciMlmeRadioOn(
1500         IN PRTMP_ADAPTER pAd)
1501 {
1502     if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1503                 return;
1504
1505     DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __func__));
1506
1507      if ((pAd->OpMode == OPMODE_AP) ||
1508         ((pAd->OpMode == OPMODE_STA)
1509         && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
1510         ||pAd->StaCfg.PSControl.field.EnableNewPS == FALSE
1511         )))
1512     {
1513                         RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
1514                 //NICResetFromError(pAd);
1515
1516         RTMPRingCleanUp(pAd, QID_AC_BK);
1517         RTMPRingCleanUp(pAd, QID_AC_BE);
1518         RTMPRingCleanUp(pAd, QID_AC_VI);
1519         RTMPRingCleanUp(pAd, QID_AC_VO);
1520         RTMPRingCleanUp(pAd, QID_MGMT);
1521         RTMPRingCleanUp(pAd, QID_RX);
1522
1523         // Enable Tx/Rx
1524         RTMPEnableRxTx(pAd);
1525
1526         // Clear Radio off flag
1527         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1528
1529         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
1530
1531             // Set LED
1532             RTMPSetLED(pAd, LED_RADIO_ON);
1533     }
1534
1535     if ((pAd->OpMode == OPMODE_STA) &&
1536         (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1537         &&(pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
1538     {
1539         BOOLEAN         Cancelled;
1540
1541         RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
1542
1543         pAd->Mlme.bPsPollTimerRunning = FALSE;
1544         RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1545         RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer,     &Cancelled);
1546         RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 40);
1547     }
1548 }
1549
1550
1551 VOID RT28xxPciMlmeRadioOFF(
1552         IN PRTMP_ADAPTER pAd)
1553 {
1554         BOOLEAN brc=TRUE;
1555
1556     if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1557         return;
1558
1559         // Link down first if any association exists
1560         if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
1561         {
1562                 if (INFRA_ON(pAd) || ADHOC_ON(pAd))
1563                 {
1564                         MLME_DISASSOC_REQ_STRUCT DisReq;
1565                         MLME_QUEUE_ELEM *pMsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1566
1567                         if (pMsgElem)
1568                         {
1569                                 COPY_MAC_ADDR(&DisReq.Addr, pAd->CommonCfg.Bssid);
1570                                 DisReq.Reason =  REASON_DISASSOC_STA_LEAVING;
1571
1572                                 pMsgElem->Machine = ASSOC_STATE_MACHINE;
1573                                 pMsgElem->MsgType = MT2_MLME_DISASSOC_REQ;
1574                                 pMsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT);
1575                                 NdisMoveMemory(pMsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT));
1576
1577                                 MlmeDisassocReqAction(pAd, pMsgElem);
1578                                 kfree(pMsgElem);
1579
1580                                 RTMPusecDelay(1000);
1581                         }
1582                 }
1583         }
1584
1585     DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __func__));
1586
1587         // Set Radio off flag
1588         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1589
1590     {
1591         BOOLEAN         Cancelled;
1592         if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1593                 {
1594         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1595         {
1596                         RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
1597                         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1598         }
1599                         // If during power safe mode.
1600                         if (pAd->StaCfg.bRadio == TRUE)
1601                         {
1602                                 DBGPRINT(RT_DEBUG_TRACE,("-->MlmeRadioOff() return on bRadio == TRUE; \n"));
1603                                 return;
1604                         }
1605                         // Always radio on since the NIC needs to set the MCU command (LED_RADIO_OFF).
1606                         if (IDLE_ON(pAd) &&
1607                                 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1608                         {
1609                                 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
1610                         }
1611                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1612         {
1613             BOOLEAN Cancelled;
1614             pAd->Mlme.bPsPollTimerRunning = FALSE;
1615             RTMPCancelTimer(&pAd->Mlme.PsPollTimer,     &Cancelled);
1616                 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer,     &Cancelled);
1617         }
1618                 }
1619
1620         // Link down first if any association exists
1621         if (INFRA_ON(pAd) || ADHOC_ON(pAd))
1622             LinkDown(pAd, FALSE);
1623         RTMPusecDelay(10000);
1624         //==========================================
1625         // Clean up old bss table
1626         BssTableInit(&pAd->ScanTab);
1627
1628         /*
1629         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1630         {
1631             RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1632             return;
1633         }
1634         */
1635     }
1636
1637         // Set LED.Move to here for fixing LED bug. This flag must be called after LinkDown
1638         RTMPSetLED(pAd, LED_RADIO_OFF);
1639
1640 //KH Debug:All PCIe devices need to use timer to execute radio off function, or the PCIe&&EnableNewPS needs.
1641 //KH Ans:It is right, because only when the PCIe and EnableNewPs is true, we need to delay the RadioOffTimer
1642 //to avoid the deadlock with PCIe Power saving function.
1643 if (pAd->OpMode == OPMODE_STA&&
1644         OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)&&
1645         pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1646         {
1647         RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1648         }
1649 else
1650 {
1651                 brc=RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0);
1652
1653         if (brc==FALSE)
1654         {
1655                 DBGPRINT(RT_DEBUG_ERROR,("%s call RT28xxPciAsicRadioOff fail !!\n", __func__));
1656         }
1657 }
1658 /*
1659 */
1660 }
1661
1662 #endif // RTMP_MAC_PCI //