📄 dma.c
字号:
//
// 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 + -