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
176 RingBasePaLow += TXD_SIZE;
177 RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE;
179 // advance to next TxBuf address
180 BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE;
181 BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE;
183 DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d entry allocated\n", num, index));
185 if (Status == NDIS_STATUS_RESOURCES)
189 // Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler
191 pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE;
192 RTMP_AllocateMgmtDescMemory(
194 pAd->MgmtDescRing.AllocSize,
196 &pAd->MgmtDescRing.AllocVa,
197 &pAd->MgmtDescRing.AllocPa);
199 if (pAd->MgmtDescRing.AllocVa == NULL)
201 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
202 DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
203 Status = NDIS_STATUS_RESOURCES;
207 // Zero init this memory block
208 NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize);
210 // Save PA & VA for further operation
211 RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa);
212 RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->MgmtDescRing.AllocPa);
213 RingBaseVa = pAd->MgmtDescRing.AllocVa;
216 // Initialize MGMT Ring and associated buffer memory
218 for (index = 0; index < MGMT_RING_SIZE; index++)
220 pAd->MgmtRing.Cell[index].pNdisPacket = NULL;
221 pAd->MgmtRing.Cell[index].pNextNdisPacket = NULL;
222 // Init MGMT Ring Size, Va, Pa variables
223 pAd->MgmtRing.Cell[index].AllocSize = TXD_SIZE;
224 pAd->MgmtRing.Cell[index].AllocVa = RingBaseVa;
225 RTMP_SetPhysicalAddressHigh(pAd->MgmtRing.Cell[index].AllocPa, RingBasePaHigh);
226 RTMP_SetPhysicalAddressLow (pAd->MgmtRing.Cell[index].AllocPa, RingBasePaLow);
228 // Offset to next ring descriptor address
229 RingBasePaLow += TXD_SIZE;
230 RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE;
232 // link the pre-allocated TxBuf to TXD
233 pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[index].AllocVa;
236 // no pre-allocated buffer required in MgmtRing for scatter-gather case
238 DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", index));
241 // Allocate RX ring descriptor's memory except Tx ring which allocated eariler
243 pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE;
244 RTMP_AllocateRxDescMemory(
246 pAd->RxDescRing.AllocSize,
248 &pAd->RxDescRing.AllocVa,
249 &pAd->RxDescRing.AllocPa);
251 if (pAd->RxDescRing.AllocVa == NULL)
253 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
254 DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
255 Status = NDIS_STATUS_RESOURCES;
259 // Zero init this memory block
260 NdisZeroMemory(pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize);
263 printk("RX DESC %p size = %ld\n", pAd->RxDescRing.AllocVa,
264 pAd->RxDescRing.AllocSize);
266 // Save PA & VA for further operation
267 RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->RxDescRing.AllocPa);
268 RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->RxDescRing.AllocPa);
269 RingBaseVa = pAd->RxDescRing.AllocVa;
272 // Initialize Rx Ring and associated buffer memory
274 for (index = 0; index < RX_RING_SIZE; index++)
276 // Init RX Ring Size, Va, Pa variables
277 pAd->RxRing.Cell[index].AllocSize = RXD_SIZE;
278 pAd->RxRing.Cell[index].AllocVa = RingBaseVa;
279 RTMP_SetPhysicalAddressHigh(pAd->RxRing.Cell[index].AllocPa, RingBasePaHigh);
280 RTMP_SetPhysicalAddressLow (pAd->RxRing.Cell[index].AllocPa, RingBasePaLow);
282 // Offset to next ring descriptor address
283 RingBasePaLow += RXD_SIZE;
284 RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE;
286 // Setup Rx associated Buffer size & allocate share memory
287 pDmaBuf = &pAd->RxRing.Cell[index].DmaBuf;
288 pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE;
289 pPacket = RTMP_AllocateRxPacketBuffer(
296 /* keep allocated rx packet */
297 pAd->RxRing.Cell[index].pNdisPacket = pPacket;
300 if (pDmaBuf->AllocVa == NULL)
302 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
303 DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n"));
304 Status = NDIS_STATUS_RESOURCES;
308 // Zero init this memory block
309 NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize);
311 // Write RxD buffer address & allocated buffer length
312 pRxD = (PRXD_STRUC) pAd->RxRing.Cell[index].AllocVa;
313 pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa);
317 DBGPRINT(RT_DEBUG_TRACE, ("Rx Ring: total %d entry allocated\n", index));
322 NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME));
323 pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
325 if (pAd->FragFrame.pFragPacket == NULL)
327 Status = NDIS_STATUS_RESOURCES;
330 if (Status != NDIS_STATUS_SUCCESS)
332 // Log error inforamtion
333 NdisWriteErrorLogEntry(
335 NDIS_ERROR_CODE_OUT_OF_RESOURCES,
340 DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status));
346 ========================================================================
349 Initialize transmit data structures
352 Adapter Pointer to our adapter
360 Initialize all transmit releated private buffer, include those define
361 in RTMP_ADAPTER structure and all private data structures.
363 ========================================================================
365 VOID NICInitTxRxRingAndBacklogQueue(
366 IN PRTMP_ADAPTER pAd)
368 //WPDMA_GLO_CFG_STRUC GloCfg;
371 DBGPRINT(RT_DEBUG_TRACE, ("<--> NICInitTxRxRingAndBacklogQueue\n"));
373 // Initialize all transmit related software queues
374 InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_BE]);
375 InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_BK]);
376 InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_VI]);
377 InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_VO]);
378 InitializeQueueHeader(&pAd->TxSwQueue[QID_HCCA]);
380 // Init RX Ring index pointer
381 pAd->RxRing.RxSwReadIdx = 0;
382 pAd->RxRing.RxCpuIdx = RX_RING_SIZE - 1;
384 // Init TX rings index pointer
385 for (i=0; i<NUM_OF_TX_RING; i++)
387 pAd->TxRing[i].TxSwFreeIdx = 0;
388 pAd->TxRing[i].TxCpuIdx = 0;
391 // init MGMT ring index pointer
392 pAd->MgmtRing.TxSwFreeIdx = 0;
393 pAd->MgmtRing.TxCpuIdx = 0;
395 pAd->PrivateInfo.TxRingFullCnt = 0;
400 ========================================================================
403 Reset NIC Asics. Call after rest DMA. So reset TX_CTX_IDX to zero.
406 Adapter Pointer to our adapter
412 IRQL = DISPATCH_LEVEL
415 Reset NIC to initial state AS IS system boot up time.
417 ========================================================================
419 VOID RTMPRingCleanUp(
420 IN PRTMP_ADAPTER pAd,
426 PNDIS_PACKET pPacket;
428 PRTMP_TX_RING pTxRing;
429 unsigned long IrqFlags;
431 DBGPRINT(RT_DEBUG_TRACE,("RTMPRingCleanUp(RingIdx=%d, Pending-NDIS=%ld)\n", RingType, pAd->RalinkCounters.PendingNdisPacketCount));
439 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
440 pTxRing = &pAd->TxRing[RingType];
442 // We have to clean all descriptors in case some error happened with reset
443 for (i=0; i<TX_RING_SIZE; i++) // We have to scan all TX ring
445 pTxD = (PTXD_STRUC) pTxRing->Cell[i].AllocVa;
447 pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNdisPacket;
448 // release scatter-and-gather NDIS_PACKET
451 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
452 pTxRing->Cell[i].pNdisPacket = NULL;
455 pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNextNdisPacket;
456 // release scatter-and-gather NDIS_PACKET
459 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
460 pTxRing->Cell[i].pNextNdisPacket = NULL;
464 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + RingType * 0x10, &pTxRing->TxDmaIdx);
465 pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx;
466 pTxRing->TxCpuIdx = pTxRing->TxDmaIdx;
467 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + RingType * 0x10, pTxRing->TxCpuIdx);
469 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
470 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
471 while (pAd->TxSwQueue[RingType].Head != NULL)
473 pEntry = RemoveHeadQueue(&pAd->TxSwQueue[RingType]);
474 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
475 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
476 DBGPRINT(RT_DEBUG_TRACE,("Release 1 NDIS packet from s/w backlog queue\n"));
478 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
482 // We have to clean all descriptors in case some error happened with reset
483 NdisAcquireSpinLock(&pAd->MgmtRingLock);
485 for (i=0; i<MGMT_RING_SIZE; i++)
487 pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[i].AllocVa;
489 pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNdisPacket;
490 // rlease scatter-and-gather NDIS_PACKET
493 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
494 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
496 pAd->MgmtRing.Cell[i].pNdisPacket = NULL;
498 pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNextNdisPacket;
499 // release scatter-and-gather NDIS_PACKET
502 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
503 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
505 pAd->MgmtRing.Cell[i].pNextNdisPacket = NULL;
509 RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pAd->MgmtRing.TxDmaIdx);
510 pAd->MgmtRing.TxSwFreeIdx = pAd->MgmtRing.TxDmaIdx;
511 pAd->MgmtRing.TxCpuIdx = pAd->MgmtRing.TxDmaIdx;
512 RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx);
514 NdisReleaseSpinLock(&pAd->MgmtRingLock);
515 pAd->RalinkCounters.MgmtRingFullCount = 0;
519 // We have to clean all descriptors in case some error happened with reset
520 NdisAcquireSpinLock(&pAd->RxRingLock);
522 for (i=0; i<RX_RING_SIZE; i++)
524 pRxD = (PRXD_STRUC) pAd->RxRing.Cell[i].AllocVa;
528 RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx);
529 pAd->RxRing.RxSwReadIdx = pAd->RxRing.RxDmaIdx;
530 pAd->RxRing.RxCpuIdx = ((pAd->RxRing.RxDmaIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxDmaIdx-1));
531 RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
533 NdisReleaseSpinLock(&pAd->RxRingLock);
542 NDIS_STATUS AdapterBlockAllocateMemory(
547 dma_addr_t *phy_addr;
548 POS_COOKIE pObj = (POS_COOKIE) handle;
550 pci_dev = pObj->pci_dev;
551 phy_addr = &pObj->pAd_pa;
553 *ppAd = (PVOID)vmalloc(sizeof(RTMP_ADAPTER)); //pci_alloc_consistent(pci_dev, sizeof(RTMP_ADAPTER), phy_addr);
557 NdisZeroMemory(*ppAd, sizeof(RTMP_ADAPTER));
558 ((PRTMP_ADAPTER)*ppAd)->OS_Cookie = handle;
559 return (NDIS_STATUS_SUCCESS);
561 return (NDIS_STATUS_FAILURE);
566 void RTMP_AllocateTxDescMemory(
567 IN PRTMP_ADAPTER pAd,
571 OUT PVOID *VirtualAddress,
572 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
574 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
576 *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
580 void RTMP_AllocateMgmtDescMemory(
581 IN PRTMP_ADAPTER pAd,
584 OUT PVOID *VirtualAddress,
585 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
587 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
589 *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
593 void RTMP_AllocateRxDescMemory(
594 IN PRTMP_ADAPTER pAd,
597 OUT PVOID *VirtualAddress,
598 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
600 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
602 *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
606 void RTMP_FreeRxDescMemory(
607 IN PRTMP_ADAPTER pAd,
609 IN PVOID VirtualAddress,
610 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress)
612 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
614 PCI_FREE_CONSISTENT(pObj->pci_dev, Length, VirtualAddress, PhysicalAddress);
618 void RTMP_AllocateFirstTxBuffer(
619 IN PRTMP_ADAPTER pAd,
623 OUT PVOID *VirtualAddress,
624 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
626 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
628 *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
632 * FUNCTION: Allocate a common buffer for DMA
634 * AdapterHandle: AdapterHandle
635 * Length: Number of bytes to allocate
636 * Cached: Whether or not the memory can be cached
637 * VirtualAddress: Pointer to memory is returned here
638 * PhysicalAddress: Physical address corresponding to virtual address
641 void RTMP_AllocateSharedMemory(
642 IN PRTMP_ADAPTER pAd,
645 OUT PVOID *VirtualAddress,
646 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
648 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
650 *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
653 VOID RTMPFreeTxRxRingMemory(
654 IN PRTMP_ADAPTER pAd)
657 PRTMP_TX_RING pTxRing;
659 PNDIS_PACKET pPacket;
660 unsigned int IrqFlags;
662 POS_COOKIE pObj =(POS_COOKIE) pAd->OS_Cookie;
664 DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n"));
666 // Free TxSwQueue Packet
667 for (index=0; index <NUM_OF_TX_RING; index++)
670 PNDIS_PACKET pPacket;
671 PQUEUE_HEADER pQueue;
673 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
674 pQueue = &pAd->TxSwQueue[index];
677 pEntry = RemoveHeadQueue(pQueue);
678 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
679 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
681 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
684 // Free Tx Ring Packet
685 for (index=0;index< NUM_OF_TX_RING;index++)
687 pTxRing = &pAd->TxRing[index];
689 for (j=0; j< TX_RING_SIZE; j++)
691 pTxD = (PTXD_STRUC) (pTxRing->Cell[j].AllocVa);
692 pPacket = pTxRing->Cell[j].pNdisPacket;
696 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
697 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
699 //Always assign pNdisPacket as NULL after clear
700 pTxRing->Cell[j].pNdisPacket = NULL;
702 pPacket = pTxRing->Cell[j].pNextNdisPacket;
706 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
707 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
709 //Always assign pNextNdisPacket as NULL after clear
710 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
715 for (index = RX_RING_SIZE - 1 ; index >= 0; index--)
717 if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) && (pAd->RxRing.Cell[index].pNdisPacket))
719 PCI_UNMAP_SINGLE(pObj->pci_dev, pAd->RxRing.Cell[index].DmaBuf.AllocPa, pAd->RxRing.Cell[index].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
720 RELEASE_NDIS_PACKET(pAd, pAd->RxRing.Cell[index].pNdisPacket, NDIS_STATUS_SUCCESS);
723 NdisZeroMemory(pAd->RxRing.Cell, RX_RING_SIZE * sizeof(RTMP_DMACB));
725 if (pAd->RxDescRing.AllocVa)
727 PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->RxDescRing.AllocSize, pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocPa);
729 NdisZeroMemory(&pAd->RxDescRing, sizeof(RTMP_DMABUF));
731 if (pAd->MgmtDescRing.AllocVa)
733 PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->MgmtDescRing.AllocSize, pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocPa);
735 NdisZeroMemory(&pAd->MgmtDescRing, sizeof(RTMP_DMABUF));
737 for (num = 0; num < NUM_OF_TX_RING; num++)
739 if (pAd->TxBufSpace[num].AllocVa)
741 PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->TxBufSpace[num].AllocSize, pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocPa);
743 NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(RTMP_DMABUF));
745 if (pAd->TxDescRing[num].AllocVa)
747 PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->TxDescRing[num].AllocSize, pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocPa);
749 NdisZeroMemory(&pAd->TxDescRing[num], sizeof(RTMP_DMABUF));
752 if (pAd->FragFrame.pFragPacket)
753 RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS);
755 DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n"));
760 * FUNCTION: Allocate a packet buffer for DMA
762 * AdapterHandle: AdapterHandle
763 * Length: Number of bytes to allocate
764 * Cached: Whether or not the memory can be cached
765 * VirtualAddress: Pointer to memory is returned here
766 * PhysicalAddress: Physical address corresponding to virtual address
768 * Cached is ignored: always cached memory
770 PNDIS_PACKET RTMP_AllocateRxPacketBuffer(
771 IN PRTMP_ADAPTER pAd,
774 OUT PVOID *VirtualAddress,
775 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
779 pkt = RTPKT_TO_OSPKT(DEV_ALLOC_SKB(Length));
782 DBGPRINT(RT_DEBUG_ERROR, ("can't allocate rx %ld size packet\n",Length));
786 RTMP_SET_PACKET_SOURCE(pkt, PKTSRC_NDIS);
787 *VirtualAddress = (PVOID) RTPKT_TO_OSPKT(pkt)->data;
788 *PhysicalAddress = PCI_MAP_SINGLE(pAd, *VirtualAddress, Length, -1, PCI_DMA_FROMDEVICE);
790 *VirtualAddress = (PVOID) NULL;
791 *PhysicalAddress = (NDIS_PHYSICAL_ADDRESS) NULL;
794 return (PNDIS_PACKET) pkt;
798 VOID Invalid_Remaining_Packet(
799 IN PRTMP_ADAPTER pAd,
800 IN ULONG VirtualAddress)
802 NDIS_PHYSICAL_ADDRESS PhysicalAddress;
804 PhysicalAddress = PCI_MAP_SINGLE(pAd, (void *)(VirtualAddress+1600), RX_BUFFER_NORMSIZE-1600, -1, PCI_DMA_FROMDEVICE);
807 PNDIS_PACKET GetPacketFromRxRing(
808 IN PRTMP_ADAPTER pAd,
809 OUT PRT28XX_RXD_STRUC pSaveRxD,
810 OUT BOOLEAN *pbReschedule,
811 IN OUT UINT32 *pRxPending)
814 PNDIS_PACKET pRxPacket = NULL;
815 PNDIS_PACKET pNewPacket;
817 NDIS_PHYSICAL_ADDRESS AllocPa;
818 BOOLEAN bReschedule = FALSE;
820 RTMP_SEM_LOCK(&pAd->RxRingLock);
822 if (*pRxPending == 0)
824 // Get how may packets had been received
825 RTMP_IO_READ32(pAd, RX_DRX_IDX , &pAd->RxRing.RxDmaIdx);
827 if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx)
829 // no more rx packets
834 // get rx pending count
835 if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx)
836 *pRxPending = pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx;
838 *pRxPending = pAd->RxRing.RxDmaIdx + RX_RING_SIZE - pAd->RxRing.RxSwReadIdx;
842 // Point to Rx indexed rx ring descriptor
843 pRxD = (PRXD_STRUC) pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].AllocVa;
845 if (pRxD->DDONE == 0)
848 // DMAIndx had done but DDONE bit not ready
854 // return rx descriptor
855 NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE);
857 pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa);
861 // unmap the rx buffer
862 PCI_UNMAP_SINGLE(pAd, pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa,
863 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
864 pRxPacket = pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket;
866 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE;
867 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket = (PNDIS_PACKET) pNewPacket;
868 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocVa = AllocVa;
869 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa = AllocPa;
870 /* update SDP0 to new buffer of rx packet */
871 pRxD->SDP0 = AllocPa;
875 //printk("No Rx Buffer\n");
882 // had handled one rx packet
883 *pRxPending = *pRxPending - 1;
885 // update rx descriptor and kick rx
886 INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE);
888 pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1);
889 RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
892 RTMP_SEM_UNLOCK(&pAd->RxRingLock);
893 *pbReschedule = bReschedule;
896 /* End of 2860_rtmp_init.c */