⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dma.c

📁 编译环境为PB,或AK,实现27x平台上对DMA的控制,由于270平台上DMA都处在同一个一级中断下,要使用单个的DMA通道,通常也可以在OAL重新映射其中断号,但比较费事,本驱动实现对DMA的管理,
💻 C
📖 第 1 页 / 共 3 页
字号:

                //
                // Isolate all writeable bits, including those that
                // both report and clear a status.
                //
                tmpDcsrClear = (tmpDCSR & XLLP_DCSR_WRITABLES_MSK);

                //
                // Stop intr is not cleared by a simple write-back.  Must also
                //  restart the DMA (not done in ISR)
                //
                if (tmpDCSR & XLLP_DMAC_DCSR_STOP_INTR)
                {
                    tmpDcsrClear &= ~(XLLP_DMAC_DCSR_STOP_IRQ_EN);
                }

                //
                // Clear the status
                //
                *dcsrP = tmpDcsrClear;

                //
                // Call handler with requested pointer and triggering DCSR value
                //            
                if (pDMAGlobals->dmaChannelConfigInfo[i].pDeviceHandler)
                {
                    //RETAILMSG(1,(TEXT("DmacInterruptHandler: Calling DMA Handler chan=%d\r\n"),i ));
                    (pDMAGlobals->dmaChannelConfigInfo[i].pDeviceHandler) (pDMAGlobals->dmaChannelConfigInfo[i].pUserContext, tmpDCSR);
                }
                else
                { // Preallocated channels are special cases and
				   // will NOT have a registered handler. They have separate 
				   // IST procesing and do not use the engine IST.
					if( DMA_CH_RCV == i || DMA_CH_MIC == i || DMA_CH_OUT == i)
					{
					   continue;	// Look for interrupt on the next channel
					} 
					else
					{
						//
						// Clear all channel interrupts and then disable them                    
						// Stop any transfers on this channel
						//                    
						tmpDCSR |= XLLP_ALL_INTERRUPTS_STATUS;
						tmpDCSR &= ~(XLLP_DMAC_DCSR_EOR_IRQ_EN | XLLP_DMAC_DCSR_STOP_IRQ_EN | XLLP_DMAC_DCSR_RUN);
						*dcsrP = tmpDCSR;                    
						RETAILMSG(1,(TEXT("DmacIntHandler: All ints disabled chan=%d tmpDcsr=0x%08x DCSR=0x%08x\r\n"), i, tmpDCSR, *dcsrP ));
					}
                }
            }         
        } 

        //
        // If we are done with all interrupts then bail out
        //
        if(!intExists)
            break;

        intExists = FALSE;
    }
    
    //RETAILMSG(1,(TEXT("DmacInterruptHandler Exit: DINT: 0x%08x\r\n"), pDmacHandle->DINT ));
}
***/
#endif


//******************************************************************************
//
// Function Name: XllpDmacCreateDescriptorListFromMdl
//
// Description: Creates a descriptor list for a buffer in virtual address space.
//  			   
//  
// Input Arguments:
//  PBufferMdl                  pBufferMdl:     Points to MDL for which desc list is to be created
//	XLLP_DMAC_TRANSFER_TYPE_T   transferType:   Specifies transfer type from/to device
//  XLLP_UINT32_T               deviceAddress:  Specfies device address from/to which DMA transfer will take place
//  XLLP_DMAC_COMMAND_T         pCmd:           Value for DCMD register
//	                 
// Output Arguments:
//  PDmaDescInfo  *pDmaDescInfo: Information baout DMA descriptors
//
// Return Value: 
//  XLLP_MEM_ALLOC_ERROR:       if error in allocating memory
//  XLLP_STATUS_SUCCESS:              when successful
//
//
// Notes:
//   The DMA descrptors returned are aligned on 16 byte boundaries
//
//*******************************************************************************
XLLP_STATUS_T XllpDmacCreateDescriptorListFromMdl
(
    PBufferMdl                  pBufferMdl,
    XLLP_DMAC_TRANSFER_TYPE_T   transferType,
    PDmaDescInfo                *pDmaDescInfo,	
    XLLP_UINT32_T               deviceAddress,
    XLLP_DMAC_COMMAND_T         *pCmd
)
{
	XLLP_UINT32_T               i;
    XLLP_UINT32_T               sourceAddress;
    XLLP_UINT32_T               targetAddress;
    XLLP_UINT32_T               nextDescPhysicalAddress;
    XLLP_DMAC_DESC_ENABLE_T     aStopContinue;
    P_XLLP_DMAC_DESCRIPTOR_T    pLocalDmaDescList;
	
	*pDmaDescInfo = XllpDmacAllocDmaDescriptorList(pBufferMdl->numEntries);    

	if(! pDmaDescInfo)
		return XLLP_ERR_MEM_ALLOC;
    
    pLocalDmaDescList = (*pDmaDescInfo)->pDmaDescList;

	for(i=0;i<pBufferMdl->numEntries;++i)
	{
        //
        // Initialize the length
        //
		pCmd->aLen = ((XLLP_UINT16_T)pBufferMdl->physBlock[i].blockLength & XLLP_DCMD_LEN_MASK);

        //
        //
        //
        if (transferType == XLLP_DMAC_TRANSFER_MEM_TO_IO) 
        {
            sourceAddress = pBufferMdl->physBlock[i].physicalAds;
            targetAddress = deviceAddress;
        }
        else
        {
            sourceAddress = deviceAddress;
            targetAddress = pBufferMdl->physBlock[i].physicalAds;
        }

        //
        //
        //
        if (i == pBufferMdl->numEntries-1)
            nextDescPhysicalAddress = 0L;
        else
            nextDescPhysicalAddress = XllpDmacGetPhysicalAds((VOID*)&pLocalDmaDescList[i+1]);
            
        if (i == pBufferMdl->numEntries-1) 
            aStopContinue = XLLP_DMAC_DESC_STOP_CHANNEL; 
        else
            aStopContinue = XLLP_DMAC_DESC_RUN_CHANNEL;        
 
        //
        // Fill the DMA descriptor list for this buffer
        //
        XllpDmacFillLinkedDesc( &pLocalDmaDescList[i],
                                (P_XLLP_DMAC_DESCRIPTOR_T)nextDescPhysicalAddress,                                
                                aStopContinue,
                                XLLP_DMAC_DISABLE_DESC_BRANCH,
                                sourceAddress,
                                targetAddress,
                                pCmd );

    }
    
    return XLLP_STATUS_SUCCESS;
}

//******************************************************************************
//
// Function Name: XllpDmacCreateDescriptorList
//
// Description: Creates a descriptor list for a buffer in virtual address space.
//  			   
//  
// Input Arguments:
//  PBufferMdl                  pBufferMdl:     Points to MDL for which desc list is to be created
//	XLLP_DMAC_TRANSFER_TYPE_T   transferType:   Specifies transfer type from/to device
//  XLLP_UINT32_T               deviceAddress:  Specfies device address from/to which DMA transfer will take place
//  XLLP_DMAC_COMMAND_T         pCmd:           Value for DCMD register
//	                 
// Output Arguments:
//  PDmaDescInfo  *pDmaDescInfo: Information baout DMA descriptors
//
// Return Value: 
//  XLLP_MEM_ALLOC_ERROR:       if error in allocating memory
//  XLLP_STATUS_SUCCESS:              when successful
//
//
// Notes:
//   The DMA descrptors returned are aligned on 16 byte boundaries
//
//*******************************************************************************
XLLP_STATUS_T XllpDmacCreateDescriptorList
(
    XLLP_UINT8_T*               pBuffer,
    XLLP_UINT32_T               bufferLength,
    XLLP_DMAC_TRANSFER_TYPE_T   transferType,
    PDmaDescInfo                *pDmaDescInfo,	
    XLLP_UINT32_T               deviceAddress,
    XLLP_DMAC_COMMAND_T         *pCmd,
    XLLP_DMAC_ALIGNMENT_T*      aLign
)
{
    PBufferMdl                  pBufferMdl;
    XLLP_STATUS_T               status;
	
    //
    // Create a MDL for the buffer
    //
    status = XllpDmacCreateBufferMdl(pBuffer, bufferLength, &pBufferMdl, aLign);
    if (status != XLLP_STATUS_SUCCESS)
        return status;

    //
    // Create the DMA descriptor list for this buffer
    //
    status = XllpDmacCreateDescriptorListFromMdl(pBufferMdl, transferType, pDmaDescInfo, deviceAddress, pCmd);
    
    //
    // Free the buffer MDL since we dont need it anymore
    //
    XllpDmacFreeBufferMdl(pBuffer, bufferLength, pBufferMdl);
		
    return status;
}


//******************************************************************************
//
// Function Name: XllpDmacChainDescriptors
//
// Description: Chains descriptors for back to back DMA transfers
//  			   
//  
// Input Arguments:
//   pCurrentDmaDesc:       Current DMA descriptor
//   pNextDmaDesc           Next DMA descriptor to be inserted in chain
//	                 
// Output Arguments:
//
//
// Return Value: 
//  descPhysicalAddress: Physical address of next descriptor...should be non 0
//
// Notes:
//   The DMA descrptors must be aligned on 16 byte physical boundaries
//
//*******************************************************************************
XLLP_UINT32_T XllpDmacChainDescriptors
(
    P_XLLP_DMAC_DESCRIPTOR_T    pCurrentDmaDesc,
    P_XLLP_DMAC_DESCRIPTOR_T    pNextDmaDesc
)
{
    XLLP_UINT32_T   descPhysicalAddress;

    descPhysicalAddress = XllpDmacGetPhysicalAds((VOID*)pNextDmaDesc);
    pCurrentDmaDesc->DDADR = descPhysicalAddress;
    return descPhysicalAddress;
}


//******************************************************************************
//
// Function Name: XllpDmacAllocateMdl
//
// Description: Allocates a memory descriptor list.
//  			   
//  
// Input Arguments:
//  numEntries:     Number of physical block entries in the MDL
//	                 
// Output Arguments:
//
//
// Return Value: 
//  PBufferMdl:     The allocated MDL pointer
//
//
// Notes:
//
//
//*******************************************************************************
PBufferMdl XllpDmacAllocateMdl
(
    XLLP_UINT32_T	numEntries
)
{
    XLLP_UINT32_T   memSize;
    PBufferMdl      pBufferMdl;

    memSize = sizeof(BufferMdl) + (numEntries * sizeof(PhysBlock));
    pBufferMdl = (PBufferMdl) OSMemAlloc(memSize);
    if(pBufferMdl)	
        pBufferMdl->physBlock = (PhysBlock*) ((XLLP_UINT32_T)pBufferMdl + sizeof(BufferMdl));
	
    return pBufferMdl;
}

//******************************************************************************
//
// Function Name: XllpDmacFreeBufferMdl
//
// Description: Frees a MDL allocated for a buffer.
//  			   
//  
// Input Arguments:
//  pBuffer:        Pointer to buffer
//  bufferLength;   length of buffer
//  pBufferMdl:     Pointer to memory descriptor list which needs to be freed
//
//	                 
// Output Arguments:
//
//
// Return Value: 
//
// Notes:
//  The buffer is unlocked in physical memory and then freed
//
//*******************************************************************************
void XllpDmacFreeBufferMdl
(
	XLLP_UINT8_T    *pBuffer,
	XLLP_UINT32_T	bufferLength,
	PBufferMdl      pBufferMdl
)
{
	OSUnlockPhysicalPages(pBuffer, bufferLength);
	OSMemFree(pBufferMdl);
	return;
}

//******************************************************************************
//
// Function Name: XllpDmacGetPhysicalAds
//
// Description: Retrieves the physical address for any specified virtual address
//  			   
//  
// Input Arguments:
//  virtualAddress:        Virtual Address 
//	                 
// Output Arguments:
//
// Return Value: 
//  0:                      Error in retrieving physical address
//  physicalAddress:        Physical address of start of buffer
//
// Notes:
//  The buffer is not locked in physical memory.
//
//*******************************************************************************
XLLP_UINT32_T XllpDmacGetPhysicalAds
(
	VOID*	virtualAddress	
)
{
    BOOL            fResult;
    XLLP_UINT32_T   pageAddress;
    XLLP_UINT32_T   pageOffset;
	//
	// Query address of first page occupied by this buffer
	//
	fResult = OSLockPhysicalPages(virtualAddress, 0x1L, &pageAddress, LOCKFLAG_QUERY_ONLY);
	if (!fResult)
		return 0;

    //
    // Calculate the offset into the page and add it to the page address
    //
    pageOffset = ((XLLP_UINT32_T)virtualAddress & (PAGE_SIZE-1));
    return (pageAddress + pageOffset);	
}

//******************************************************************************
//
// Function Name: XllpDmacCreateBufferMdl
//
// Description: Creates a Memory Descriptor List (MDL) for the user buffer.
//  			   
//  
// Input Arguments:
//  pBuffer:        Pointer to buffer
//  bufferLength;   length of buffer
//	                 
// Output Arguments:
//  pBufferMdl:     Pointer to memory descriptor list which is returned to caller
//  aLign:          Flag which describes if buffer is aligned on 8 byte boundary or not
//
// Return Value: 
//  XLLP_ERR_MEM_ALLOC: Error in memory allocation
//  XLLP_STATUS_SUCCESS:      hen successful
//
// Notes:
//  The caller is responsible for freeing memory occupied by the MDL.
//  The max size of each physically contigious block in the MDL list is restricted to 4K,
//  since maximum permitted transfer anyway is 8K-1 (less than two pages) bytes.
//
//*******************************************************************************
XLLP_STATUS_T XllpDmacCreateBufferMdl
(
    XLLP_UINT8_T            *pBuffer,
    XLLP_UINT32_T           bufferLength,
    PBufferMdl              *pBufferMdl,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -