]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/rt2860/common/cmm_mac_pci.c
Staging: rt2860: add RT3090 chipset support
[net-next-2.6.git] / drivers / staging / rt2860 / common / cmm_mac_pci.c
CommitLineData
ca97b838
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
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*/
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 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*/
396VOID 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:
ca97b838
BZ
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
522VOID 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========================================================================
635Routine Description:
636 Disable DMA.
637
638Arguments:
639 *pAd the raxx interface data pointer
640
641Return Value:
642 None
643
644Note:
645========================================================================
646*/
647VOID 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========================================================================
662Routine Description:
663 Enable DMA.
664
665Arguments:
666 *pAd the raxx interface data pointer
667
668Return Value:
669 None
670
671Note:
672========================================================================
673*/
674VOID 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
705BOOLEAN 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========================================================================
773Routine Description:
774 Write Beacon buffer to Asic.
775
776Arguments:
777 *pAd the raxx interface data pointer
778
779Return Value:
780 None
781
782Note:
783========================================================================
784*/
785VOID 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
845VOID 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
e44fd1cf
BZ
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)
ca97b838
BZ
866 {
867 // Support PCIe Advance Power Save
e44fd1cf
BZ
868 if (bFromTx == TRUE
869 &&(pAd->Mlme.bPsPollTimerRunning == TRUE))
ca97b838
BZ
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 {
e44fd1cf
BZ
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 //
ca97b838
BZ
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 }
e44fd1cf
BZ
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 //
ca97b838
BZ
924 }
925 else
ca97b838
BZ
926 {
927 // PCI, 2860-PCIe
e44fd1cf 928 DBGPRINT(RT_DEBUG_TRACE, ("<==RT28xxPciStaAsicForceWakeup::Original PCI Power Saving\n"));
ca97b838
BZ
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
940VOID 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 }
e44fd1cf
BZ
951 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
952 &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
ca97b838
BZ
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
ca97b838
BZ
1002VOID 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);
e44fd1cf
BZ
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 //
ca97b838
BZ
1030}
1031
1032VOID 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"));
e44fd1cf
BZ
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)
ca97b838 1050 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
e44fd1cf 1051#endif // RTMP_PCI_SUPPORT //
ca97b838
BZ
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"));
e44fd1cf
BZ
1058#ifdef RTMP_PCI_SUPPORT
1059if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
1060 &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
ca97b838 1061 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
e44fd1cf 1062#endif // RTMP_PCI_SUPPORT //
ca97b838
BZ
1063 return;
1064 }
e44fd1cf
BZ
1065//KH Debug: need to check. I add the compile flag "CONFIG_STA_SUPPORT" to enclose the following codes.
1066#ifdef RTMP_PCI_SUPPORT
1067if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
1068 &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1069 {
ca97b838
BZ
1070 pAd->Mlme.bPsPollTimerRunning = FALSE;
1071 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
e44fd1cf
BZ
1072 }
1073#endif // RTMP_PCI_SUPPORT //
ca97b838
BZ
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);
ca97b838
BZ
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
e44fd1cf 1113//KH Debug:The following codes should be enclosed by RT3090 compile flag
ca97b838
BZ
1114 if (pChipOps->AsicReverseRfFromSleepMode)
1115 pChipOps->AsicReverseRfFromSleepMode(pAd);
1116
e44fd1cf
BZ
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.
1120if ((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
ca97b838
BZ
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}
ca97b838
BZ
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 */
1158BOOLEAN 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
e44fd1cf
BZ
1169 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1170 {
1171 if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
ca97b838
BZ
1172 {
1173 pAd->Mlme.bPsPollTimerRunning = FALSE;
1174 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
e44fd1cf
BZ
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 {
1180 // Some chips don't need to delay 6ms, so copy RTMPPCIePowerLinkCtrlRestore
1181 // return condition here.
1182 /*
1183 if (((pAd->MACVersion&0xffff0000) != 0x28600000)
1184 && ((pAd->DeviceID == NIC2860_PCIe_DEVICE_ID)
1185 ||(pAd->DeviceID == NIC2790_PCIe_DEVICE_ID)))
1186 */
ca97b838
BZ
1187 {
1188 DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOn ()\n"));
1189 // 1. Set PCI Link Control in Configuration Space.
1190 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
1191 RTMPusecDelay(6000);
1192 }
1193 }
e44fd1cf 1194 }
ca97b838 1195
e44fd1cf
BZ
1196#ifdef PCIE_PS_SUPPORT
1197if (!(((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)
1198 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
1199 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))))
1200#endif // PCIE_PS_SUPPORT //
1201 {
ca97b838 1202 pAd->bPCIclkOff = FALSE;
e44fd1cf
BZ
1203 DBGPRINT(RT_DEBUG_TRACE, ("PSM :309xbPCIclkOff == %d\n", pAd->bPCIclkOff));
1204 }
ca97b838
BZ
1205 // 2. Send wake up command.
1206 AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02);
1207 pAd->bPCIclkOff = FALSE;
1208 // 2-1. wait command ok.
1209 AsicCheckCommanOk(pAd, PowerWakeCID);
1210 RTMP_ASIC_INTERRUPT_ENABLE(pAd);
1211
ca97b838
BZ
1212 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
1213 if (Level == GUI_IDLE_POWER_SAVE)
1214 {
e44fd1cf
BZ
1215#ifdef PCIE_PS_SUPPORT
1216
1217 // add by johnli, RF power sequence setup, load RF normal operation-mode setup
1218 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)))
1219 {
1220 RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
1221
1222 if (pChipOps->AsicReverseRfFromSleepMode)
1223 pChipOps->AsicReverseRfFromSleepMode(pAd);
1224 // 3090 MCU Wakeup command needs more time to be stable.
1225 // Before stable, don't issue other MCU command to prevent from firmware error.
1226 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)
1227 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
1228 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
1229 {
1230 RTMP_SEM_LOCK(&pAd->McuCmdLock);
1231 pAd->brt30xxBanMcuCmd = FALSE;
1232 RTMP_SEM_UNLOCK(&pAd->McuCmdLock);
1233 }
1234 }
1235 else
1236 // end johnli
1237#endif // PCIE_PS_SUPPORT //
ca97b838
BZ
1238 {
1239 // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
1240 {
1241 if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
1242 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
1243 {
1244 // Must using 40MHz.
1245 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
1246 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
1247 }
1248 else
1249 {
1250 // Must using 20MHz.
1251 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1252 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1253 }
1254 }
1255
1256 }
1257 }
1258 return TRUE;
1259
1260}
1261
1262
1263/*
1264 ==========================================================================
1265 Description:
1266 This routine sends command to firmware and turn our chip to power save mode.
1267 Both RadioOff and .11 power save function needs to call this routine.
1268 Input:
1269 Level = GUIRADIO_OFF : GUI Radio Off mode
1270 Level = DOT11POWERSAVE : 802.11 power save mode
1271 Level = RTMP_HALT : When Disable device.
1272
1273 ==========================================================================
1274 */
1275BOOLEAN RT28xxPciAsicRadioOff(
1276 IN PRTMP_ADAPTER pAd,
1277 IN UCHAR Level,
1278 IN USHORT TbttNumToNextWakeUp)
1279{
1280 WPDMA_GLO_CFG_STRUC DmaCfg;
1281 UCHAR i, tempBBP_R3 = 0;
1282 BOOLEAN brc = FALSE, Cancelled;
1283 UINT32 TbTTTime = 0;
1284 UINT32 PsPollTime = 0/*, MACValue*/;
1285 ULONG BeaconPeriodTime;
1286 UINT32 RxDmaIdx, RxCpuIdx;
1287 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));
1288
1289 if (pAd->OpMode == OPMODE_AP && Level==DOT11POWERSAVE)
1290 return FALSE;
1291
1292 // Check Rx DMA busy status, if more than half is occupied, give up this radio off.
1293 RTMP_IO_READ32(pAd, RX_DRX_IDX , &RxDmaIdx);
1294 RTMP_IO_READ32(pAd, RX_CRX_IDX , &RxCpuIdx);
1295 if ((RxDmaIdx > RxCpuIdx) && ((RxDmaIdx - RxCpuIdx) > RX_RING_SIZE/3))
1296 {
1297 DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return1. RxDmaIdx = %d , RxCpuIdx = %d. \n", RxDmaIdx, RxCpuIdx));
1298 return FALSE;
1299 }
1300 else if ((RxCpuIdx >= RxDmaIdx) && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE/3))
1301 {
1302 DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return2. RxCpuIdx = %d. RxDmaIdx = %d , \n", RxCpuIdx, RxDmaIdx));
1303 return FALSE;
1304 }
1305
1306 // Once go into this function, disable tx because don't want too many packets in queue to prevent HW stops.
e44fd1cf
BZ
1307 //pAd->bPCIclkOffDisableTx = TRUE;
1308 RTMP_SET_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
1309 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
1310 && pAd->OpMode == OPMODE_STA
1311 &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE
1312 )
ca97b838 1313 {
ca97b838
BZ
1314 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
1315 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1316
1317 if (Level == DOT11POWERSAVE)
1318 {
1319 RTMP_IO_READ32(pAd, TBTT_TIMER, &TbTTTime);
1320 TbTTTime &= 0x1ffff;
1321 // 00. check if need to do sleep in this DTIM period. If next beacon will arrive within 30ms , ...doesn't necessarily sleep.
1322 // TbTTTime uint = 64us, LEAD_TIME unit = 1024us, PsPollTime unit = 1ms
1323 if (((64*TbTTTime) <((LEAD_TIME*1024) + 40000)) && (TbttNumToNextWakeUp == 0))
1324 {
1325 DBGPRINT(RT_DEBUG_TRACE, ("TbTTTime = 0x%x , give up this sleep. \n", TbTTTime));
1326 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
e44fd1cf
BZ
1327 //pAd->bPCIclkOffDisableTx = FALSE;
1328 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
ca97b838
BZ
1329 return FALSE;
1330 }
1331 else
1332 {
1333 PsPollTime = (64*TbTTTime- LEAD_TIME*1024)/1000;
e44fd1cf
BZ
1334#ifdef PCIE_PS_SUPPORT
1335 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)
1336 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
1337 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
1338 {
1339 PsPollTime -= 5;
1340 }
1341 else
1342#endif // PCIE_PS_SUPPORT //
ca97b838
BZ
1343 PsPollTime -= 3;
1344
1345 BeaconPeriodTime = pAd->CommonCfg.BeaconPeriod*102/100;
1346 if (TbttNumToNextWakeUp > 0)
1347 PsPollTime += ((TbttNumToNextWakeUp -1) * BeaconPeriodTime);
1348
1349 pAd->Mlme.bPsPollTimerRunning = TRUE;
1350 RTMPSetTimer(&pAd->Mlme.PsPollTimer, PsPollTime);
1351 }
1352 }
1353 }
e44fd1cf
BZ
1354 else
1355 {
1356 DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOff::Level!=DOT11POWERSAVE \n"));
1357 }
1358
1359 pAd->bPCIclkOffDisableTx = FALSE;
ca97b838
BZ
1360
1361 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
1362
1363 // Set to 1R.
1364 if (pAd->Antenna.field.RxPath > 1 && pAd->OpMode == OPMODE_STA)
1365 {
1366 tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7);
1367 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3);
1368 }
1369
1370 // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
1371 if ((INFRA_ON(pAd) || pAd->OpMode == OPMODE_AP) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
1372 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
1373 {
1374 // Must using 40MHz.
1375 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
1376 }
1377 else
1378 {
1379 // Must using 20MHz.
1380 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
1381 }
1382
1383 if (Level != RTMP_HALT)
1384 {
1385 // Change Interrupt bitmask.
1386 // When PCI clock is off, don't want to service interrupt.
1387 RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt);
1388 }
1389 else
1390 {
1391 RTMP_ASIC_INTERRUPT_DISABLE(pAd);
1392 }
1393
1394
1395 RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
1396 // 2. Send Sleep command
1397 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
1398 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
1399 // send POWER-SAVE command to MCU. high-byte = 1 save power as much as possible. high byte = 0 save less power
1400 AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x1);
1401 // 2-1. Wait command success
1402 // Status = 1 : success, Status = 2, already sleep, Status = 3, Maybe MAC is busy so can't finish this task.
1403 brc = AsicCheckCommanOk(pAd, PowerSafeCID);
1404
1405 // 3. After 0x30 command is ok, send radio off command. lowbyte = 0 for power safe.
1406 // If 0x30 command is not ok this time, we can ignore 0x35 command. It will make sure not cause firmware'r problem.
1407 if ((Level == DOT11POWERSAVE) && (brc == TRUE))
1408 {
1409 AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 0, 0x00); // lowbyte = 0 means to do power safe, NOT turn off radio.
1410 // 3-1. Wait command success
1411 AsicCheckCommanOk(pAd, PowerRadioOffCID);
1412 }
1413 else if (brc == TRUE)
1414 {
1415 AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 1, 0x00); // lowbyte = 0 means to do power safe, NOT turn off radio.
1416 // 3-1. Wait command success
1417 AsicCheckCommanOk(pAd, PowerRadioOffCID);
1418 }
1419
1420 // 1. Wait DMA not busy
1421 i = 0;
1422 do
1423 {
1424 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
1425 if ((DmaCfg.field.RxDMABusy == 0) && (DmaCfg.field.TxDMABusy == 0))
1426 break;
1427 RTMPusecDelay(20);
1428 i++;
1429 }while(i < 50);
1430
1431 /*
1432 if (i >= 50)
1433 {
1434 pAd->CheckDmaBusyCount++;
1435 DBGPRINT(RT_DEBUG_TRACE, ("DMA Rx keeps busy. return on AsicRadioOff () CheckDmaBusyCount = %d \n", pAd->CheckDmaBusyCount));
1436 }
1437 else
1438 {
1439 pAd->CheckDmaBusyCount = 0;
1440 }
1441 */
e44fd1cf
BZ
1442//KH Debug:My original codes have the follwoing codes, but currecnt codes do not have it.
1443// Disable for stability. If PCIE Link Control is modified for advance power save, re-covery this code segment.
1444RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x1280);
1445//OPSTATUS_SET_FLAG(pAd, fOP_STATUS_CLKSELECT_40MHZ);
1446
1447#ifdef PCIE_PS_SUPPORT
1448if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)
1449 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
1450 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
1451 {
1452 DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOff::3090 return to skip the following TbttNumToNextWakeUp setting for 279x\n"));
1453 pAd->bPCIclkOff = TRUE;
1454 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
1455 // For this case, doesn't need to below actions, so return here.
1456 return brc;
1457 }
1458#endif // PCIE_PS_SUPPORT //
ca97b838
BZ
1459
1460 if (Level == DOT11POWERSAVE)
1461 {
1462 AUTO_WAKEUP_STRUC AutoWakeupCfg;
1463 //RTMPSetTimer(&pAd->Mlme.PsPollTimer, 90);
1464
1465 // we have decided to SLEEP, so at least do it for a BEACON period.
1466 if (TbttNumToNextWakeUp == 0)
1467 TbttNumToNextWakeUp = 1;
1468
1469 AutoWakeupCfg.word = 0;
1470 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
1471
1472 // 1. Set auto wake up timer.
1473 AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
1474 AutoWakeupCfg.field.EnableAutoWakeup = 1;
1475 AutoWakeupCfg.field.AutoLeadTime = LEAD_TIME;
1476 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
1477 }
1478
ca97b838
BZ
1479 // 4-1. If it's to disable our device. Need to restore PCI Configuration Space to its original value.
1480 if (Level == RTMP_HALT && pAd->OpMode == OPMODE_STA)
1481 {
1482 if ((brc == TRUE) && (i < 50))
1483 RTMPPCIeLinkCtrlSetting(pAd, 1);
1484 }
1485 // 4. Set PCI configuration Space Link Comtrol fields. Only Radio Off needs to call this function
1486 else if (pAd->OpMode == OPMODE_STA)
1487 {
1488 if ((brc == TRUE) && (i < 50))
1489 RTMPPCIeLinkCtrlSetting(pAd, 3);
1490 }
ca97b838 1491
e44fd1cf
BZ
1492 //pAd->bPCIclkOffDisableTx = FALSE;
1493 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
ca97b838
BZ
1494 return TRUE;
1495}
1496
1497
1498
1499
1500VOID RT28xxPciMlmeRadioOn(
1501 IN PRTMP_ADAPTER pAd)
1502{
1503 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1504 return;
1505
1506 DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __func__));
1507
e44fd1cf
BZ
1508 if ((pAd->OpMode == OPMODE_AP) ||
1509 ((pAd->OpMode == OPMODE_STA)
1510 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
1511 ||pAd->StaCfg.PSControl.field.EnableNewPS == FALSE
1512 )))
ca97b838 1513 {
ca97b838 1514 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
ca97b838
BZ
1515 //NICResetFromError(pAd);
1516
1517 RTMPRingCleanUp(pAd, QID_AC_BK);
1518 RTMPRingCleanUp(pAd, QID_AC_BE);
1519 RTMPRingCleanUp(pAd, QID_AC_VI);
1520 RTMPRingCleanUp(pAd, QID_AC_VO);
ca97b838
BZ
1521 RTMPRingCleanUp(pAd, QID_MGMT);
1522 RTMPRingCleanUp(pAd, QID_RX);
1523
ca97b838
BZ
1524 // Enable Tx/Rx
1525 RTMPEnableRxTx(pAd);
1526
1527 // Clear Radio off flag
1528 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1529
e44fd1cf
BZ
1530 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
1531
ca97b838
BZ
1532 // Set LED
1533 RTMPSetLED(pAd, LED_RADIO_ON);
1534 }
1535
ca97b838 1536 if ((pAd->OpMode == OPMODE_STA) &&
e44fd1cf
BZ
1537 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1538 &&(pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
ca97b838
BZ
1539 {
1540 BOOLEAN Cancelled;
1541
1542 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
1543
1544 pAd->Mlme.bPsPollTimerRunning = FALSE;
1545 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1546 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
e44fd1cf 1547 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 40);
ca97b838 1548 }
ca97b838
BZ
1549}
1550
1551
1552VOID RT28xxPciMlmeRadioOFF(
1553 IN PRTMP_ADAPTER pAd)
1554{
1555 BOOLEAN brc=TRUE;
1556
1557 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1558 return;
1559
1560 // Link down first if any association exists
1561 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
1562 {
1563 if (INFRA_ON(pAd) || ADHOC_ON(pAd))
1564 {
1565 MLME_DISASSOC_REQ_STRUCT DisReq;
1566 MLME_QUEUE_ELEM *pMsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1567
1568 if (pMsgElem)
1569 {
1570 COPY_MAC_ADDR(&DisReq.Addr, pAd->CommonCfg.Bssid);
1571 DisReq.Reason = REASON_DISASSOC_STA_LEAVING;
1572
1573 pMsgElem->Machine = ASSOC_STATE_MACHINE;
1574 pMsgElem->MsgType = MT2_MLME_DISASSOC_REQ;
1575 pMsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT);
1576 NdisMoveMemory(pMsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT));
1577
1578 MlmeDisassocReqAction(pAd, pMsgElem);
1579 kfree(pMsgElem);
1580
1581 RTMPusecDelay(1000);
1582 }
1583 }
1584 }
1585
1586 DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __func__));
1587
1588 // Set Radio off flag
1589 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1590
1591 {
1592 BOOLEAN Cancelled;
e44fd1cf
BZ
1593 if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1594 {
ca97b838
BZ
1595 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1596 {
1597 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
1598 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1599 }
e44fd1cf
BZ
1600 // If during power safe mode.
1601 if (pAd->StaCfg.bRadio == TRUE)
1602 {
1603 DBGPRINT(RT_DEBUG_TRACE,("-->MlmeRadioOff() return on bRadio == TRUE; \n"));
1604 return;
1605 }
1606 // Always radio on since the NIC needs to set the MCU command (LED_RADIO_OFF).
1607 if (IDLE_ON(pAd) &&
1608 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1609 {
1610 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
1611 }
1612 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
ca97b838
BZ
1613 {
1614 BOOLEAN Cancelled;
1615 pAd->Mlme.bPsPollTimerRunning = FALSE;
1616 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1617 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
1618 }
e44fd1cf 1619 }
ca97b838
BZ
1620
1621 // Link down first if any association exists
1622 if (INFRA_ON(pAd) || ADHOC_ON(pAd))
1623 LinkDown(pAd, FALSE);
1624 RTMPusecDelay(10000);
1625 //==========================================
1626 // Clean up old bss table
1627 BssTableInit(&pAd->ScanTab);
1628
e44fd1cf
BZ
1629 /*
1630 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
ca97b838
BZ
1631 {
1632 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1633 return;
1634 }
e44fd1cf 1635 */
ca97b838
BZ
1636 }
1637
e44fd1cf 1638 // Set LED.Move to here for fixing LED bug. This flag must be called after LinkDown
ca97b838
BZ
1639 RTMPSetLED(pAd, LED_RADIO_OFF);
1640
e44fd1cf
BZ
1641//KH Debug:All PCIe devices need to use timer to execute radio off function, or the PCIe&&EnableNewPS needs.
1642//KH Ans:It is right, because only when the PCIe and EnableNewPs is true, we need to delay the RadioOffTimer
1643//to avoid the deadlock with PCIe Power saving function.
1644if (pAd->OpMode == OPMODE_STA&&
1645 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)&&
1646 pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1647 {
1648 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1649 }
1650else
1651{
ca97b838
BZ
1652 brc=RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0);
1653
1654 if (brc==FALSE)
1655 {
1656 DBGPRINT(RT_DEBUG_ERROR,("%s call RT28xxPciAsicRadioOff fail !!\n", __func__));
1657 }
e44fd1cf
BZ
1658}
1659/*
1660*/
ca97b838
BZ
1661}
1662
1663#endif // RTMP_MAC_PCI //