2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
31 Miniport generic portion header file
35 -------- ---------- ----------------------------------------------
36 Paul Lin 2002-08-01 created
37 John Chang 2004-08-20 RT2561/2661 use scatter-gather scheme
38 Jan Lee 2006-09-15 RT2860. Change for 802.11n , EEPROM, Led, BA, HT.
40 #include "../rt_config.h"
46 ========================================================================
49 Allocate DMA memory blocks for send, receive
52 Adapter Pointer to our adapter
63 ========================================================================
65 NDIS_STATUS RTMPAllocTxRxRingMemory(
68 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
76 PRTMP_TX_RING pTxRing;
80 DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n"));
84 // Allocate all ring descriptors, include TxD, RxD, MgmtD.
85 // Although each size is different, to prevent cacheline and alignment
86 // issue, I intentional set them all to 64 bytes.
88 for (num=0; num<NUM_OF_TX_RING; num++)
95 // Allocate Tx ring descriptor's memory (5 TX rings = 4 ACs + 1 HCCA)
97 pAd->TxDescRing[num].AllocSize = TX_RING_SIZE * TXD_SIZE;
98 RTMP_AllocateTxDescMemory(
101 pAd->TxDescRing[num].AllocSize,
103 &pAd->TxDescRing[num].AllocVa,
104 &pAd->TxDescRing[num].AllocPa);
106 if (pAd->TxDescRing[num].AllocVa == NULL)
108 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
109 DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
110 Status = NDIS_STATUS_RESOURCES;
114 // Zero init this memory block
115 NdisZeroMemory(pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocSize);
117 // Save PA & VA for further operation
118 RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxDescRing[num].AllocPa);
119 RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxDescRing[num].AllocPa);
120 RingBaseVa = pAd->TxDescRing[num].AllocVa;
123 // Allocate all 1st TXBuf's memory for this TxRing
125 pAd->TxBufSpace[num].AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE;
126 RTMP_AllocateFirstTxBuffer(
129 pAd->TxBufSpace[num].AllocSize,
131 &pAd->TxBufSpace[num].AllocVa,
132 &pAd->TxBufSpace[num].AllocPa);
134 if (pAd->TxBufSpace[num].AllocVa == NULL)
136 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
137 DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
138 Status = NDIS_STATUS_RESOURCES;
142 // Zero init this memory block
143 NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocSize);
145 // Save PA & VA for further operation
146 BufBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxBufSpace[num].AllocPa);
147 BufBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxBufSpace[num].AllocPa);
148 BufBaseVa = pAd->TxBufSpace[num].AllocVa;
151 // Initialize Tx Ring Descriptor and associated buffer memory
153 pTxRing = &pAd->TxRing[num];
154 for (index = 0; index < TX_RING_SIZE; index++)
156 pTxRing->Cell[index].pNdisPacket = NULL;
157 pTxRing->Cell[index].pNextNdisPacket = NULL;
158 // Init Tx Ring Size, Va, Pa variables
159 pTxRing->Cell[index].AllocSize = TXD_SIZE;
160 pTxRing->Cell[index].AllocVa = RingBaseVa;
161 RTMP_SetPhysicalAddressHigh(pTxRing->Cell[index].AllocPa, RingBasePaHigh);
162 RTMP_SetPhysicalAddressLow (pTxRing->Cell[index].AllocPa, RingBasePaLow);
164 // Setup Tx Buffer size & address. only 802.11 header will store in this space
165 pDmaBuf = &pTxRing->Cell[index].DmaBuf;
166 pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE;
167 pDmaBuf->AllocVa = BufBaseVa;
168 RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, BufBasePaHigh);
169 RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, BufBasePaLow);
171 // link the pre-allocated TxBuf to TXD
172 pTxD = (PTXD_STRUC) pTxRing->Cell[index].AllocVa;
173 pTxD->SDPtr0 = BufBasePaLow;
174 // advance to next ring descriptor address
177 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
179 RingBasePaLow += TXD_SIZE;
180 RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE;
182 // advance to next TxBuf address
183 BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE;
184 BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE;
186 DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d entry allocated\n", num, index));
188 if (Status == NDIS_STATUS_RESOURCES)
192 // Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler
194 pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE;
195 RTMP_AllocateMgmtDescMemory(
197 pAd->MgmtDescRing.AllocSize,
199 &pAd->MgmtDescRing.AllocVa,
200 &pAd->MgmtDescRing.AllocPa);
202 if (pAd->MgmtDescRing.AllocVa == NULL)
204 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
205 DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
206 Status = NDIS_STATUS_RESOURCES;
210 // Zero init this memory block
211 NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize);
213 // Save PA & VA for further operation
214 RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa);
215 RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->MgmtDescRing.AllocPa);
216 RingBaseVa = pAd->MgmtDescRing.AllocVa;
219 // Initialize MGMT Ring and associated buffer memory
221 for (index = 0; index < MGMT_RING_SIZE; index++)
223 pAd->MgmtRing.Cell[index].pNdisPacket = NULL;
224 pAd->MgmtRing.Cell[index].pNextNdisPacket = NULL;
225 // Init MGMT Ring Size, Va, Pa variables
226 pAd->MgmtRing.Cell[index].AllocSize = TXD_SIZE;
227 pAd->MgmtRing.Cell[index].AllocVa = RingBaseVa;
228 RTMP_SetPhysicalAddressHigh(pAd->MgmtRing.Cell[index].AllocPa, RingBasePaHigh);
229 RTMP_SetPhysicalAddressLow (pAd->MgmtRing.Cell[index].AllocPa, RingBasePaLow);
231 // Offset to next ring descriptor address
232 RingBasePaLow += TXD_SIZE;
233 RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE;
235 // link the pre-allocated TxBuf to TXD
236 pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[index].AllocVa;
240 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
242 // no pre-allocated buffer required in MgmtRing for scatter-gather case
244 DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", index));
247 // Allocate RX ring descriptor's memory except Tx ring which allocated eariler
249 pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE;
250 RTMP_AllocateRxDescMemory(
252 pAd->RxDescRing.AllocSize,
254 &pAd->RxDescRing.AllocVa,
255 &pAd->RxDescRing.AllocPa);
257 if (pAd->RxDescRing.AllocVa == NULL)
259 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
260 DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
261 Status = NDIS_STATUS_RESOURCES;
265 // Zero init this memory block
266 NdisZeroMemory(pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize);
269 printk("RX DESC %p size = %ld\n", pAd->RxDescRing.AllocVa,
270 pAd->RxDescRing.AllocSize);
272 // Save PA & VA for further operation
273 RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->RxDescRing.AllocPa);
274 RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->RxDescRing.AllocPa);
275 RingBaseVa = pAd->RxDescRing.AllocVa;
278 // Initialize Rx Ring and associated buffer memory
280 for (index = 0; index < RX_RING_SIZE; index++)
282 // Init RX Ring Size, Va, Pa variables
283 pAd->RxRing.Cell[index].AllocSize = RXD_SIZE;
284 pAd->RxRing.Cell[index].AllocVa = RingBaseVa;
285 RTMP_SetPhysicalAddressHigh(pAd->RxRing.Cell[index].AllocPa, RingBasePaHigh);
286 RTMP_SetPhysicalAddressLow (pAd->RxRing.Cell[index].AllocPa, RingBasePaLow);
288 // Offset to next ring descriptor address
289 RingBasePaLow += RXD_SIZE;
290 RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE;
292 // Setup Rx associated Buffer size & allocate share memory
293 pDmaBuf = &pAd->RxRing.Cell[index].DmaBuf;
294 pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE;
295 pPacket = RTMP_AllocateRxPacketBuffer(
302 /* keep allocated rx packet */
303 pAd->RxRing.Cell[index].pNdisPacket = pPacket;
306 if (pDmaBuf->AllocVa == NULL)
308 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
309 DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n"));
310 Status = NDIS_STATUS_RESOURCES;
314 // Zero init this memory block
315 NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize);
317 // Write RxD buffer address & allocated buffer length
318 pRxD = (PRXD_STRUC) pAd->RxRing.Cell[index].AllocVa;
319 pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa);
323 RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD);
327 DBGPRINT(RT_DEBUG_TRACE, ("Rx Ring: total %d entry allocated\n", index));
332 NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME));
333 pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
335 if (pAd->FragFrame.pFragPacket == NULL)
337 Status = NDIS_STATUS_RESOURCES;
340 if (Status != NDIS_STATUS_SUCCESS)
342 // Log error inforamtion
343 NdisWriteErrorLogEntry(
345 NDIS_ERROR_CODE_OUT_OF_RESOURCES,
350 DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status));
356 ========================================================================
359 Initialize transmit data structures
362 Adapter Pointer to our adapter
370 Initialize all transmit releated private buffer, include those define
371 in RTMP_ADAPTER structure and all private data structures.
373 ========================================================================
375 VOID NICInitTxRxRingAndBacklogQueue(
376 IN PRTMP_ADAPTER pAd)
378 //WPDMA_GLO_CFG_STRUC GloCfg;
381 DBGPRINT(RT_DEBUG_TRACE, ("<--> NICInitTxRxRingAndBacklogQueue\n"));
383 // Initialize all transmit related software queues
384 InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_BE]);
385 InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_BK]);
386 InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_VI]);
387 InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_VO]);
388 InitializeQueueHeader(&pAd->TxSwQueue[QID_HCCA]);
390 // Init RX Ring index pointer
391 pAd->RxRing.RxSwReadIdx = 0;
392 pAd->RxRing.RxCpuIdx = RX_RING_SIZE - 1;
394 // Init TX rings index pointer
395 for (i=0; i<NUM_OF_TX_RING; i++)
397 pAd->TxRing[i].TxSwFreeIdx = 0;
398 pAd->TxRing[i].TxCpuIdx = 0;
401 // init MGMT ring index pointer
402 pAd->MgmtRing.TxSwFreeIdx = 0;
403 pAd->MgmtRing.TxCpuIdx = 0;
405 pAd->PrivateInfo.TxRingFullCnt = 0;
410 ========================================================================
413 Reset NIC Asics. Call after rest DMA. So reset TX_CTX_IDX to zero.
416 Adapter Pointer to our adapter
422 IRQL = DISPATCH_LEVEL
425 Reset NIC to initial state AS IS system boot up time.
427 ========================================================================
429 VOID RTMPRingCleanUp(
430 IN PRTMP_ADAPTER pAd,
436 PNDIS_PACKET pPacket;
438 PRTMP_TX_RING pTxRing;
439 unsigned long IrqFlags;
441 DBGPRINT(RT_DEBUG_TRACE,("RTMPRingCleanUp(RingIdx=%d, Pending-NDIS=%ld)\n", RingType, pAd->RalinkCounters.PendingNdisPacketCount));
449 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
450 pTxRing = &pAd->TxRing[RingType];
452 // We have to clean all descriptors in case some error happened with reset
453 for (i=0; i<TX_RING_SIZE; i++) // We have to scan all TX ring
455 pTxD = (PTXD_STRUC) pTxRing->Cell[i].AllocVa;
457 pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNdisPacket;
458 // release scatter-and-gather NDIS_PACKET
461 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
462 pTxRing->Cell[i].pNdisPacket = NULL;
465 pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNextNdisPacket;
466 // release scatter-and-gather NDIS_PACKET
469 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
470 pTxRing->Cell[i].pNextNdisPacket = NULL;
474 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + RingType * 0x10, &pTxRing->TxDmaIdx);
475 pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx;
476 pTxRing->TxCpuIdx = pTxRing->TxDmaIdx;
477 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + RingType * 0x10, pTxRing->TxCpuIdx);
479 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
480 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
481 while (pAd->TxSwQueue[RingType].Head != NULL)
483 pEntry = RemoveHeadQueue(&pAd->TxSwQueue[RingType]);
484 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
485 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
486 DBGPRINT(RT_DEBUG_TRACE,("Release 1 NDIS packet from s/w backlog queue\n"));
488 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
492 // We have to clean all descriptors in case some error happened with reset
493 NdisAcquireSpinLock(&pAd->MgmtRingLock);
495 for (i=0; i<MGMT_RING_SIZE; i++)
497 pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[i].AllocVa;
499 pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNdisPacket;
500 // rlease scatter-and-gather NDIS_PACKET
503 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
504 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
506 pAd->MgmtRing.Cell[i].pNdisPacket = NULL;
508 pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNextNdisPacket;
509 // release scatter-and-gather NDIS_PACKET
512 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
513 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
515 pAd->MgmtRing.Cell[i].pNextNdisPacket = NULL;
519 RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pAd->MgmtRing.TxDmaIdx);
520 pAd->MgmtRing.TxSwFreeIdx = pAd->MgmtRing.TxDmaIdx;
521 pAd->MgmtRing.TxCpuIdx = pAd->MgmtRing.TxDmaIdx;
522 RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx);
524 NdisReleaseSpinLock(&pAd->MgmtRingLock);
525 pAd->RalinkCounters.MgmtRingFullCount = 0;
529 // We have to clean all descriptors in case some error happened with reset
530 NdisAcquireSpinLock(&pAd->RxRingLock);
532 for (i=0; i<RX_RING_SIZE; i++)
534 pRxD = (PRXD_STRUC) pAd->RxRing.Cell[i].AllocVa;
538 RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx);
539 pAd->RxRing.RxSwReadIdx = pAd->RxRing.RxDmaIdx;
540 pAd->RxRing.RxCpuIdx = ((pAd->RxRing.RxDmaIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxDmaIdx-1));
541 RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
543 NdisReleaseSpinLock(&pAd->RxRingLock);
552 NDIS_STATUS AdapterBlockAllocateMemory(
557 dma_addr_t *phy_addr;
558 POS_COOKIE pObj = (POS_COOKIE) handle;
560 pci_dev = pObj->pci_dev;
561 phy_addr = &pObj->pAd_pa;
563 *ppAd = (PVOID)vmalloc(sizeof(RTMP_ADAPTER)); //pci_alloc_consistent(pci_dev, sizeof(RTMP_ADAPTER), phy_addr);
567 NdisZeroMemory(*ppAd, sizeof(RTMP_ADAPTER));
568 ((PRTMP_ADAPTER)*ppAd)->OS_Cookie = handle;
569 return (NDIS_STATUS_SUCCESS);
571 return (NDIS_STATUS_FAILURE);
576 void RTMP_AllocateTxDescMemory(
577 IN PRTMP_ADAPTER pAd,
581 OUT PVOID *VirtualAddress,
582 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
584 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
586 *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
590 void RTMP_AllocateMgmtDescMemory(
591 IN PRTMP_ADAPTER pAd,
594 OUT PVOID *VirtualAddress,
595 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
597 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
599 *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
603 void RTMP_AllocateRxDescMemory(
604 IN PRTMP_ADAPTER pAd,
607 OUT PVOID *VirtualAddress,
608 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
610 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
612 *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
616 void RTMP_FreeRxDescMemory(
617 IN PRTMP_ADAPTER pAd,
619 IN PVOID VirtualAddress,
620 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress)
622 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
624 PCI_FREE_CONSISTENT(pObj->pci_dev, Length, VirtualAddress, PhysicalAddress);
628 void RTMP_AllocateFirstTxBuffer(
629 IN PRTMP_ADAPTER pAd,
633 OUT PVOID *VirtualAddress,
634 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
636 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
638 *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
642 * FUNCTION: Allocate a common buffer for DMA
644 * AdapterHandle: AdapterHandle
645 * Length: Number of bytes to allocate
646 * Cached: Whether or not the memory can be cached
647 * VirtualAddress: Pointer to memory is returned here
648 * PhysicalAddress: Physical address corresponding to virtual address
651 void RTMP_AllocateSharedMemory(
652 IN PRTMP_ADAPTER pAd,
655 OUT PVOID *VirtualAddress,
656 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
658 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
660 *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
663 VOID RTMPFreeTxRxRingMemory(
664 IN PRTMP_ADAPTER pAd)
667 PRTMP_TX_RING pTxRing;
669 PNDIS_PACKET pPacket;
670 unsigned int IrqFlags;
672 POS_COOKIE pObj =(POS_COOKIE) pAd->OS_Cookie;
674 DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n"));
676 // Free TxSwQueue Packet
677 for (index=0; index <NUM_OF_TX_RING; index++)
680 PNDIS_PACKET pPacket;
681 PQUEUE_HEADER pQueue;
683 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
684 pQueue = &pAd->TxSwQueue[index];
687 pEntry = RemoveHeadQueue(pQueue);
688 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
689 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
691 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
694 // Free Tx Ring Packet
695 for (index=0;index< NUM_OF_TX_RING;index++)
697 pTxRing = &pAd->TxRing[index];
699 for (j=0; j< TX_RING_SIZE; j++)
701 pTxD = (PTXD_STRUC) (pTxRing->Cell[j].AllocVa);
702 pPacket = pTxRing->Cell[j].pNdisPacket;
706 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
707 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
709 //Always assign pNdisPacket as NULL after clear
710 pTxRing->Cell[j].pNdisPacket = NULL;
712 pPacket = pTxRing->Cell[j].pNextNdisPacket;
716 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
717 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
719 //Always assign pNextNdisPacket as NULL after clear
720 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
725 for (index = RX_RING_SIZE - 1 ; index >= 0; index--)
727 if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) && (pAd->RxRing.Cell[index].pNdisPacket))
729 PCI_UNMAP_SINGLE(pObj->pci_dev, pAd->RxRing.Cell[index].DmaBuf.AllocPa, pAd->RxRing.Cell[index].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
730 RELEASE_NDIS_PACKET(pAd, pAd->RxRing.Cell[index].pNdisPacket, NDIS_STATUS_SUCCESS);
733 NdisZeroMemory(pAd->RxRing.Cell, RX_RING_SIZE * sizeof(RTMP_DMACB));
735 if (pAd->RxDescRing.AllocVa)
737 PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->RxDescRing.AllocSize, pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocPa);
739 NdisZeroMemory(&pAd->RxDescRing, sizeof(RTMP_DMABUF));
741 if (pAd->MgmtDescRing.AllocVa)
743 PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->MgmtDescRing.AllocSize, pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocPa);
745 NdisZeroMemory(&pAd->MgmtDescRing, sizeof(RTMP_DMABUF));
747 for (num = 0; num < NUM_OF_TX_RING; num++)
749 if (pAd->TxBufSpace[num].AllocVa)
751 PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->TxBufSpace[num].AllocSize, pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocPa);
753 NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(RTMP_DMABUF));
755 if (pAd->TxDescRing[num].AllocVa)
757 PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->TxDescRing[num].AllocSize, pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocPa);
759 NdisZeroMemory(&pAd->TxDescRing[num], sizeof(RTMP_DMABUF));
762 if (pAd->FragFrame.pFragPacket)
763 RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS);
765 DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n"));
770 * FUNCTION: Allocate a packet buffer for DMA
772 * AdapterHandle: AdapterHandle
773 * Length: Number of bytes to allocate
774 * Cached: Whether or not the memory can be cached
775 * VirtualAddress: Pointer to memory is returned here
776 * PhysicalAddress: Physical address corresponding to virtual address
778 * Cached is ignored: always cached memory
780 PNDIS_PACKET RTMP_AllocateRxPacketBuffer(
781 IN PRTMP_ADAPTER pAd,
784 OUT PVOID *VirtualAddress,
785 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
789 pkt = RTPKT_TO_OSPKT(DEV_ALLOC_SKB(Length));
792 DBGPRINT(RT_DEBUG_ERROR, ("can't allocate rx %ld size packet\n",Length));
796 RTMP_SET_PACKET_SOURCE(pkt, PKTSRC_NDIS);
797 *VirtualAddress = (PVOID) RTPKT_TO_OSPKT(pkt)->data;
798 *PhysicalAddress = PCI_MAP_SINGLE(pAd, *VirtualAddress, Length, -1, PCI_DMA_FROMDEVICE);
800 *VirtualAddress = (PVOID) NULL;
801 *PhysicalAddress = (NDIS_PHYSICAL_ADDRESS) NULL;
804 return (PNDIS_PACKET) pkt;
808 VOID Invalid_Remaining_Packet(
809 IN PRTMP_ADAPTER pAd,
810 IN ULONG VirtualAddress)
812 NDIS_PHYSICAL_ADDRESS PhysicalAddress;
814 PhysicalAddress = PCI_MAP_SINGLE(pAd, (void *)(VirtualAddress+1600), RX_BUFFER_NORMSIZE-1600, -1, PCI_DMA_FROMDEVICE);
817 PNDIS_PACKET GetPacketFromRxRing(
818 IN PRTMP_ADAPTER pAd,
819 OUT PRT28XX_RXD_STRUC pSaveRxD,
820 OUT BOOLEAN *pbReschedule,
821 IN OUT UINT32 *pRxPending)
828 PNDIS_PACKET pRxPacket = NULL;
829 PNDIS_PACKET pNewPacket;
831 NDIS_PHYSICAL_ADDRESS AllocPa;
832 BOOLEAN bReschedule = FALSE;
834 RTMP_SEM_LOCK(&pAd->RxRingLock);
836 if (*pRxPending == 0)
838 // Get how may packets had been received
839 RTMP_IO_READ32(pAd, RX_DRX_IDX , &pAd->RxRing.RxDmaIdx);
841 if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx)
843 // no more rx packets
848 // get rx pending count
849 if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx)
850 *pRxPending = pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx;
852 *pRxPending = pAd->RxRing.RxDmaIdx + RX_RING_SIZE - pAd->RxRing.RxSwReadIdx;
857 pDestRxD = (PRXD_STRUC) pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].AllocVa;
860 RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD);
862 // Point to Rx indexed rx ring descriptor
863 pRxD = (PRXD_STRUC) pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].AllocVa;
866 if (pRxD->DDONE == 0)
869 // DMAIndx had done but DDONE bit not ready
875 // return rx descriptor
876 NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE);
878 pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa);
882 // unmap the rx buffer
883 PCI_UNMAP_SINGLE(pAd, pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa,
884 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
885 pRxPacket = pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket;
887 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE;
888 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket = (PNDIS_PACKET) pNewPacket;
889 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocVa = AllocVa;
890 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa = AllocPa;
891 /* update SDP0 to new buffer of rx packet */
892 pRxD->SDP0 = AllocPa;
896 //printk("No Rx Buffer\n");
903 // had handled one rx packet
904 *pRxPending = *pRxPending - 1;
906 // update rx descriptor and kick rx
908 RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD);
909 WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD);
911 INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE);
913 pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1);
914 RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
917 RTMP_SEM_UNLOCK(&pAd->RxRingLock);
918 *pbReschedule = bReschedule;
921 /* End of 2860_rtmp_init.c */