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