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

📄 ddk_sdma.c

📁 freescale i.mx31 BSP CE5.0全部源码
💻 C
📖 第 1 页 / 共 4 页
字号:
//-----------------------------------------------------------------------------
//
//  Copyright (C) 2006, Freescale Semiconductor, Inc. All Rights Reserved
//  THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
//  BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
//  FREESCALE SEMICONDUCTOR, INC.
//
//-----------------------------------------------------------------------------
//
//  File:  ddk_sdma.c
//
//  This file contains a DDK interface for the SDMA module.
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include "mxarm11.h"

//-----------------------------------------------------------------------------
// External Functions
extern BOOL SdmaLoadRamScripts(void * pBuf);
extern BOOL SdmaSetChanDesc(DDK_DMA_REQ dmaReq, PSDMA_CHAN_DESC pChanDesc);
extern BOOL SdmaUpdateChanDesc(DDK_DMA_REQ dmaReq, PSDMA_CHAN_DESC pChanDesc);
extern BOOL SdmaSetChanContext(UINT8 chan, PSDMA_CHAN_DESC pChanDesc, 
    UINT8 waterMark, PSDMA_CHANNEL_CONTEXT pChanCtxt);

extern PVOID BSPSdmaAllocChain(UINT8 chan, UINT32 numBufDesc, 
    PPHYSICAL_ADDRESS phyAddr);
extern VOID BSPSdmaFreeChain(UINT8 chan);
extern UINT32 BSPSdmaGetSharedSize(VOID);

//-----------------------------------------------------------------------------
// External Variables


//-----------------------------------------------------------------------------
// Defines
#define CHAN_MASK(chan) (1 << (chan))
#define CMD_SETCTX(chan) (((chan) << 3) | SDMA_CMD_C0_SETCTX)
// #define DDK_SDMA_VERBOSE


//-----------------------------------------------------------------------------
// Types


//-----------------------------------------------------------------------------
// Global Variables
DMA_ADAPTER_OBJECT g_DmaAdapter = { sizeof(DMA_ADAPTER_OBJECT), 
                                    Internal, 0 };
PSDMA_HOST_SHARED_REGION g_pHostSharedUA = NULL;
PSDMA_HOST_SHARED_REGION g_pHostSharedPA = NULL;


//-----------------------------------------------------------------------------
// Local Variables
static PCSP_SDMA_REGS g_pSDMA = NULL;
static HANDLE g_hSdmaMutex;
static HANDLE g_hAcrMutex;

//-----------------------------------------------------------------------------
// Local Functions
BOOL SdmaInit(void);
BOOL SdmaDeinit(void);
BOOL SdmaAlloc(void);
BOOL SdmaDealloc(void);
static BOOL SdmaWritePM(UINT32 srcAddrPA, UINT32 dstAddrPM, UINT16 count);
static BOOL SdmaWriteChanContext(UINT8 chan, UINT32 srcAddrPA);
static void SdmaSetChanOverride(UINT8 chan, BOOL bHostOvr,
    BOOL bEventOvr, BOOL bDspOvr);
static void SdmaSetChanPriority(UINT8 chan, UINT8 priority);
static BOOL SdmaGetChanStatus(UINT8 chan);
static UINT8 SdmaFindUnusedChan(UINT8 priority);
static void SdmaLockCtrlChan(void);
static void SdmaUnlockCtrlChan(void);
static BOOL SdmaValidChan(UINT8 chan);


//-----------------------------------------------------------------------------
//
//  Function:  DDKSdmaOpenChan
//
//  This function tries to find an available virtual SDMA channel that can
//  be used to support a memory-to-memory, peripheral-to-memory, or
//  memory-to-peripheral transfer.
//
//  Parameters:
//      dmaReq
//          [in] - Specifies the DMA request that will be bound to
//          a virtual channel.
//
//      priority
//          [in] - Priority assigned to the opened channel.
//
//      lpName
//          [in] - Pointer to a null-terminated string that specifies the name 
//          of the event object signaled when a transfer interrupt occurs
//          This parameter will be passed to CreateEvent to open a handle to a 
//          named event object.  To signal a registered interrupt handler,
//          set this parameter to NULL and use sysIntr parameter to specify
//          the logical interrupt.
//
//      irq
//          [in] - Only used if lpName is set to NULL.  Specifies the harware
//          IRQ that will be translated into a registered SYSINTR within
//          OEMInterruptHandler when a transfer interrupt occurs.  Set to
//          IRQ_NONE if no interrupt will be generated by the channel.
//
//  Returns:
//      Returns the virtual channel index if successful,
//      otherwise returns NULL.
//
//-----------------------------------------------------------------------------
UINT8 DDKSdmaOpenChan(DDK_DMA_REQ dmaReq, UINT8 priority, LPTSTR lpName, 
    DWORD irq)
{
    UINT8 chan;
    DMA_IRQ_MAP_PARMS dmaIrqMap;
    UINT32 i, dmaMask;

    // Try to find an available channel
    chan = SdmaFindUnusedChan(priority);    

    // If available channel was found
    if (chan == 0)
    {
        ERRORMSG(1, (_T("No available channel!\r\n")));
        goto cleanUp;
    }
    
    // Reset CCB
    g_pHostSharedUA->chanCtrlBlk[chan].curBufDescPA = 0;
    g_pHostSharedUA->chanCtrlBlk[chan].baseBufDescPA = 0;
    g_pHostSharedUA->chanCtrlBlk[chan].chanDesc = 0;
    g_pHostSharedUA->chanCtrlBlk[chan].chanStatus = 0;    

    // Reset channel descriptor fields for buffer descriptors
    g_pHostSharedUA->chanDesc[chan].pBaseBufDescUA = NULL;
    g_pHostSharedUA->chanDesc[chan].numBufDesc = 0;

    // Attempt to configure remaining channel descriptor fields based DMA request
    if (!SdmaSetChanDesc(dmaReq, &g_pHostSharedUA->chanDesc[chan]))
    {
        ERRORMSG(1, (_T("SdmaSetChanDesc failed!\r\n")));
        goto cleanUp;
    }
        
    // If the channel has an associated DMA request
    if (g_pHostSharedUA->chanDesc[chan].dmaMask)
    {
        // Search through the DMA requests specified for this channel
        for (i = 0, dmaMask = 0x1; i < SDMA_NUM_CHANNELS; i++, dmaMask <<= 1)
        {
            if (dmaMask & g_pHostSharedUA->chanDesc[chan].dmaMask)
            {
                // Bind DMA requests to virtual channel
                SETREG32(&g_pSDMA->CHNENBL[i], CHAN_MASK(chan));
            }
        }

        // Clear event override
        SdmaSetChanOverride(chan, FALSE, FALSE, TRUE);
    }
    else
    {
        // No DMAREQ for memory-to-memory, set event override
        SdmaSetChanOverride(chan, FALSE, TRUE, TRUE);
    }

    // If event object to signal not specified
    if ((lpName == NULL) && (irq != IRQ_NONE))
    {
        // Map SDMA channel to a hardware IRQ
        dmaIrqMap.irq = irq;
        dmaIrqMap.chan = chan;
        
        if (!KernelIoControl(IOCTL_HAL_REQUEST_DMA_IRQ_MAP, &dmaIrqMap, 
            sizeof(dmaIrqMap), NULL, 0, NULL))
        {
            ERRORMSG(1, (_T("IOCTL_HAL_REQUEST_DMA_IRQ_MAP failed!\r\n")));
            goto cleanUp;
        }
    }

    return chan;

cleanUp:
    DDKSdmaCloseChan(chan);
    return 0;
}


//-----------------------------------------------------------------------------
//
//  Function:  DDKSdmaUpdateSharedChan
//
//  This function allows a channel that has multiple DMA requests combined into
//  a shared DMA event to be reconfigured for one of the alternate DMA requests.
//
//  Parameters:
//      dmaReq
//          [in] - Specifies one of the possible DMA requests valid for
//                 a channel with a shared DMA event.  The DMA request
//                 must be one of the set of requests valid for the opened
//                 channel.
//
//  Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DDKSdmaUpdateSharedChan(UINT8 chan, DDK_DMA_REQ dmaReq)
{
    BOOL rc = FALSE;

    // Validate channel
    if (!SdmaValidChan(chan))
    {
        ERRORMSG(1, (_T("Channel validation failed!\r\n")));
        goto cleanUp;
    }

    rc = SdmaUpdateChanDesc(dmaReq, &g_pHostSharedUA->chanDesc[chan]);

cleanUp:
    return rc;
}


//-----------------------------------------------------------------------------
//
// Function:  DDKSdmaCloseChan
//
// This function closes a channel previously opened by the DDKSdmaOpenChan
// routine.
//
// Parameters:
//      chan
//          [in] - Virtual channel returned by DDKSdmaOpenChan function.
//
// Returns:
//      Returns TRUE if the close operation was successful, otherwise
//      returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DDKSdmaCloseChan(UINT8 chan)
{
    BOOL rc = FALSE;
    UINT32 i, dmaMask;

    // Validate channel
    if (!SdmaValidChan(chan))
    {
        ERRORMSG(1, (_T("Channel validation failed!\r\n")));
        goto cleanUp;
    }

    // If the channel has an associated DMA request
    if (g_pHostSharedUA->chanDesc[chan].dmaMask)
    {
        // Search through the DMA requests specified for this channel
        for (i = 0, dmaMask = 0x1; i < SDMA_NUM_CHANNELS; i++, dmaMask <<= 1)
        {
            if (dmaMask & g_pHostSharedUA->chanDesc[chan].dmaMask)
            {
                // Unbind DMA request from virtual channel
                CLRREG32(&g_pSDMA->CHNENBL[i], CHAN_MASK(chan));
            }
        }

        // Clear event override
        SdmaSetChanOverride(chan, FALSE, FALSE, TRUE);
    }

    // Make sure event override is cleared
    SdmaSetChanOverride(chan, FALSE, FALSE, TRUE);

    // Unmap the buffer descriptors
    DDKSdmaFreeChain(chan);
    
    // Unmap channel from hardware IRQ
    KernelIoControl(IOCTL_HAL_RELEASE_DMA_IRQ_MAP, &chan, sizeof(chan), 
        NULL, 0, NULL);
        
    // Reset CCB
    g_pHostSharedUA->chanCtrlBlk[chan].curBufDescPA = 0;
    g_pHostSharedUA->chanCtrlBlk[chan].baseBufDescPA = 0;
    g_pHostSharedUA->chanCtrlBlk[chan].chanDesc = 0;
    g_pHostSharedUA->chanCtrlBlk[chan].chanStatus = 0;    

    // Return channel back to pool of unused channels
    SdmaSetChanPriority(chan, SDMA_CHNPRI_CHNPRI_DISABLE);

    rc = TRUE;

cleanUp:
    return rc;
}


//-----------------------------------------------------------------------------
//
//  Function:  DDKSdmaAllocChain
//
//  This function allocates a chain of buffer descriptors for
//  a virtual DMA channel.  
//
//  Parameters:
//      chan
//          [in] - Virtual channel returned by DDKSdmaOpenChan function.
//
//      numBufDesc
//          [in] - Number of buffer descriptors to allocate for the chain.
//
//  Returns:
//      Returns TRUE if the chain allocation succeeded, otherwise returns 
//      FALSE.
//
//-----------------------------------------------------------------------------
BOOL DDKSdmaAllocChain(UINT8 chan, UINT32 numBufDesc)
{
    BOOL rc = FALSE;
    PVOID pBufDesc;
    PHYSICAL_ADDRESS phyAddr;
    
    // Validate channel
    if (!SdmaValidChan(chan))
    {
        ERRORMSG(1, (_T("Channel validation failed!\r\n")));
        goto cleanUp;
    }

    // Allocate storage for buffer descriptor chain
    pBufDesc = BSPSdmaAllocChain(chan, numBufDesc, &phyAddr);

    if (pBufDesc == NULL)
    {
        ERRORMSG(1, (_T("BSPSdmaAllocChain failed!\r\n")));
        goto cleanUp;
    }

    // Save chain information in CCB and channel descriptor
    g_pHostSharedUA->chanCtrlBlk[chan].baseBufDescPA = phyAddr.LowPart;
    g_pHostSharedUA->chanCtrlBlk[chan].curBufDescPA = phyAddr.LowPart;
    g_pHostSharedUA->chanDesc[chan].pBaseBufDescUA = pBufDesc;
    g_pHostSharedUA->chanDesc[chan].numBufDesc = numBufDesc;

    rc = TRUE;

cleanUp:
    return rc;
}


//-----------------------------------------------------------------------------
//
//  Function:  DDKSdmaFreeChain
//
//  This function frees a chain of buffer descriptors previously
//  allocated with DDKSdmaAllocChain.
//
//  Parameters:
//      chan
//          [in] - Virtual channel returned by DDKSdmaOpenChan function.
//
//  Returns:
//      Returns TRUE if the chain could be deallocated, otherwise
//      returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DDKSdmaFreeChain(UINT8 chan)
{
    BOOL rc = FALSE;

    // Validate channel parameter
    if (chan <= 0 || chan >= SDMA_NUM_CHANNELS)
    {
        ERRORMSG(1, (_T("Invalid channel!\r\n")));
        goto cleanUp;
    }

    // Check if descriptors have been allocated for this channel
    if (g_pHostSharedUA->chanDesc[chan].numBufDesc == 0)
    {
        // Nothing to unmap, return success
        rc = TRUE;
        goto cleanUp;
    }

    // Kill the channel
    if (!DDKSdmaStopChan(chan, TRUE))
    {
        ERRORMSG(1, (_T("Cannot kill channel!\r\n")));
        goto cleanUp;
    }

    // Deallocate storage for buffer descriptor chain
    if (g_pHostSharedUA->chanDesc[chan].pBaseBufDescUA)
    {
        BSPSdmaFreeChain(chan);
    }

    // Reset chain information in CCB
    g_pHostSharedUA->chanCtrlBlk[chan].baseBufDescPA = 0;
    g_pHostSharedUA->chanCtrlBlk[chan].curBufDescPA = 0;
    g_pHostSharedUA->chanDesc[chan].pBaseBufDescUA = NULL;
    g_pHostSharedUA->chanDesc[chan].numBufDesc = 0;

    rc = TRUE;

cleanUp:
    return rc;

}


//-----------------------------------------------------------------------------
//
//  Function:  DDKSdmaSetBufDesc
//
//  This function configures a buffer descriptor for a DMA transfer.
//
//  Parameters:

⌨️ 快捷键说明

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