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

📄 ddk_sdma.c

📁 freescale i.mx31 BSP CE5.0全部源码
💻 C
📖 第 1 页 / 共 4 页
字号:
//  Function:  DDKSdmaInitChain
//
//  This function initializes a buffer descriptor chain.
//
//  Parameters:
//      chan
//          [in] - Virtual channel returned by DDKSdmaOpenChan function.
//
//      waterMark
//          [in] - Specifies the watermark level used by the peripheral
//          to generate a DMA request.  This parameter tells the
//          DMA how many transfers to complete for each assertion of 
//          the DMA request.  Ignored for memory-to-memory transfers.
//
//  Returns:
//      Returns TRUE if the chain could be initialized, otherwise
//      returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DDKSdmaInitChain(UINT8 chan, UINT32 waterMark)
{
    BOOL rc = FALSE;
    
    // Clear the stats for all buffer descriptors
    if (!DDKSdmaClearChainStatus(chan))
    {
        ERRORMSG(1, (_T("Chain status could not be cleared!\r\n")));
        goto cleanUp;
    }

    // Request lock of control channel
    SdmaLockCtrlChan();
    
    // Make sure channel is not running before we update it
    if (!DDKSdmaStopChan(chan, TRUE))
    {
        ERRORMSG(1, (_T("Cannot kill channel!\r\n")));
        goto cleanUp;
    }

    // Initialize context for the channel
    if (!SdmaSetChanContext(chan, &g_pHostSharedUA->chanDesc[chan], waterMark,
        &g_pHostSharedUA->chanCtxt))
    {
        ERRORMSG(1, (_T("Cannot initialize channel context!\r\n")));
        goto cleanUp;
    }

    // Write out the channel context
    if (!SdmaWriteChanContext(chan, (UINT32) &g_pHostSharedPA->chanCtxt))
    {
        ERRORMSG(1, (_T("Cannot load channel context!\r\n")));
        goto cleanUp;
    }

    // Set physical address of current buffer descriptor
    g_pHostSharedUA->chanCtrlBlk[chan].curBufDescPA =
        g_pHostSharedUA->chanCtrlBlk[chan].baseBufDescPA;

    rc = TRUE;

cleanUp:
    // Unlock control channel
    SdmaUnlockCtrlChan();
    return rc;

}


//-----------------------------------------------------------------------------
//
// Function:  DDKSdmaStartChan
//
// This function starts the specified channel.
//
// Parameters:
//      chan
//          [in] - Virtual channel to start.
//
// Returns:
//      Returns TRUE if the start request is successful, else returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DDKSdmaStartChan(UINT8 chan)
{
    BOOL rc = FALSE;

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

    // Check if channel has been previously opened
    if (INREG32(&g_pSDMA->CHNPRI[chan]) == SDMA_CHNPRI_CHNPRI_DISABLE)
    {
        ERRORMSG(1, (_T("Channel not opened!\r\n")));
        goto cleanUp;
    }

    // Synchronize with DVFC since bus scaling may be in
    // progress.  During bus scaling, the DVFC driver
    // must wait for all channels to idle before
    // updating the SDMA ACR bit
    WaitForSingleObject(g_hAcrMutex, INFINITE);

    // If HSTART bit is not already set for this channel
    if (!(INREG32(&g_pSDMA->HSTART) & CHAN_MASK(chan)))
    {
#ifdef DDK_SDMA_VERBOSE
        // Dump out CCB for channel being started
        RETAILMSG(TRUE, (_T("CCB[%d]:\r\n"), chan));
        RETAILMSG(TRUE, (_T("curBufDescPA = 0x%x\r\n"), g_pHostSharedUA->chanCtrlBlk[chan].curBufDescPA));
        RETAILMSG(TRUE, (_T("baseBufDescPA = 0x%x\r\n"), g_pHostSharedUA->chanCtrlBlk[chan].baseBufDescPA));
        RETAILMSG(TRUE, (_T("baseBufDescUA = 0x%x\r\n"), g_pHostSharedUA->chanDesc[chan].pBaseBufDescUA));
        
        // Dump out snapshot of important SDMA registers
        RETAILMSG(TRUE, (_T("MC0PTR = 0x%x\r\n"), INREG32(&g_pSDMA->MC0PTR)));
        RETAILMSG(TRUE, (_T("INTR = 0x%x\r\n"), INREG32(&g_pSDMA->INTR)));
        RETAILMSG(TRUE, (_T("STOP_STAT = 0x%x\r\n"), INREG32(&g_pSDMA->STOP_STAT)));
        RETAILMSG(TRUE, (_T("HSTART = 0x%x\r\n"), INREG32(&g_pSDMA->HSTART)));
        RETAILMSG(TRUE, (_T("EVTOVR = 0x%x\r\n"), INREG32(&g_pSDMA->EVTOVR)));
        RETAILMSG(TRUE, (_T("HOSTOVR = 0x%x\r\n"), INREG32(&g_pSDMA->HOSTOVR)));
        RETAILMSG(TRUE, (_T("EVTPEND = 0x%x\r\n"), INREG32(&g_pSDMA->EVTPEND)));
        RETAILMSG(TRUE, (_T("EVTERR = 0x%x\r\n"), INREG32(&g_pSDMA->EVTERR)));
        RETAILMSG(TRUE, (_T("PSW = 0x%x\r\n"), INREG32(&g_pSDMA->PSW)));
        RETAILMSG(TRUE, (_T("CHN0ADDR = 0x%x\r\n"), INREG32(&g_pSDMA->CHN0ADDR)));
        RETAILMSG(TRUE, (_T("CHNENBL[0] = 0x%x\r\n"), INREG32(&g_pSDMA->CHNENBL[0])));
        RETAILMSG(TRUE, (_T("CHNENBL[1] = 0x%x\r\n"), INREG32(&g_pSDMA->CHNENBL[1])));
        RETAILMSG(TRUE, (_T("CHNENBL[2] = 0x%x\r\n"), INREG32(&g_pSDMA->CHNENBL[2])));
        RETAILMSG(TRUE, (_T("CHNENBL[3] = 0x%x\r\n"), INREG32(&g_pSDMA->CHNENBL[3])));
        RETAILMSG(TRUE, (_T("CHNPRI[0] = 0x%x\r\n"), INREG32(&g_pSDMA->CHNPRI[0])));
        RETAILMSG(TRUE, (_T("CHNPRI[1] = 0x%x\r\n"), INREG32(&g_pSDMA->CHNPRI[1])));
        RETAILMSG(TRUE, (_T("CHNPRI[2] = 0x%x\r\n"), INREG32(&g_pSDMA->CHNPRI[2])));
        RETAILMSG(TRUE, (_T("CHNPRI[3] = 0x%x\r\n"), INREG32(&g_pSDMA->CHNPRI[3])));
#endif

        // Start request can be granted (HSTART ignores write of zero into bits)
        OUTREG32(&g_pSDMA->HSTART, CHAN_MASK(chan));
    }

    ReleaseMutex(g_hAcrMutex);

    rc = TRUE;

cleanUp:
    return rc;
}


//-----------------------------------------------------------------------------
//
//  Function:  DDKSdmaStopChan
//
//  This function stops the specified channel.
//
//  Parameters:
//      chan
//          [in] - Virtual channel to stop.
//
//      bKill
//          [in] - Set TRUE to terminate the channel if it is actively
//          running.
//
//  Returns:
//      Returns TRUE if the stop request is successful, else returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DDKSdmaStopChan(UINT8 chan, BOOL bKill)
{
    BOOL rc = FALSE;

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

    // Synchronize with DVFC since bus scaling may be in
    // progress.  During bus scaling, the DVFC driver
    // must wait for all channels to idle before
    // updating the SDMA ACR bit
    WaitForSingleObject(g_hAcrMutex, INFINITE);

    // Clear HE and HSTART bits using STOP_STAT register
    OUTREG32(&g_pSDMA->STOP_STAT, CHAN_MASK(chan));

    ReleaseMutex(g_hAcrMutex);

    // Kill running channel if requested
    if (bKill)
    {
        // Forcing a reschedule to kill the channel is
        // not recommended.  For now we just ignore the
        // kill request and let the channel terminate
        // normally.
    }

    rc = TRUE;

cleanUp:
    return rc;
}


//-----------------------------------------------------------------------------
//
//  Function:  SdmaInit
//
//  This function initializes the SDMA.  Called by the Device Manager to
//  initialize a device.
//
//  Parameters:
//      None.
//
//  Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL SdmaInit(void)
{
    BOOL rc = FALSE;
    UINT8 dmaEvent;
    UINT16 count;
    DMA_ADAPTER_OBJECT Adapter;
    PBYTE pRamImageUA;
    PHYSICAL_ADDRESS pRamImagePA;
        
    // Zero out shared region
    memset(g_pHostSharedUA, 0, BSPSdmaGetSharedSize());

    // Configure chan 0 control block (single buffer descriptor reused for all
    // chan 0 commands)
    g_pHostSharedUA->chanCtrlBlk[0].baseBufDescPA =
        (UINT32) &g_pHostSharedPA->chan0BufDesc;
    g_pHostSharedUA->chanCtrlBlk[0].curBufDescPA =
        (UINT32) &g_pHostSharedPA->chan0BufDesc;

#ifdef SDMA_CONTEXT_WITH_SCRATCH
    // Configure context size to include scratch memory
    INSREG32BF(&g_pSDMA->CHN0ADDR, SDMA_CHN0ADDR_SMSZ,
        SDMA_CHN0ADDR_SMSZ_32WORDCNTX);
#endif

    // Clear channel enable RAM
    for (dmaEvent = 0; dmaEvent < SDMA_NUM_CHANNELS; dmaEvent++)
    {
        OUTREG32(&g_pSDMA->CHNENBL[dmaEvent], 0);
    }

    // Set event override
    SdmaSetChanOverride(0, FALSE, TRUE, TRUE);
        
    // Channel 0 operations will use interlocked updates of the priority
    // register to safely share channel 0 resources.  Signify channel 0
    // availability with SDMA_CHNPRI_CHNPRI_DISABLE priority setting
    SdmaSetChanPriority(0, SDMA_CHNPRI_CHNPRI_DISABLE);

    // Allocate a block of virtual memory (physically contiguous) for the
    // DMA RAM image.
    //
    memset(&Adapter, 0, sizeof(DMA_ADAPTER_OBJECT));
    Adapter.InterfaceType = Internal;
    Adapter.ObjectSize    = sizeof(DMA_ADAPTER_OBJECT);

    pRamImageUA = (PBYTE) HalAllocateCommonBuffer(&Adapter, SDMA_RAM_SIZE,
        &pRamImagePA, FALSE);

    // Copy SDMA RAM image into shared buffer
    count = SdmaLoadRamScripts(pRamImageUA);
    
    // Load DMA scripts into RAM
    rc = SdmaWritePM(pRamImagePA.LowPart, SDMA_PM_CODE_START, count);

    // Free the block allocated for the DMA image
    HalFreeCommonBuffer(NULL, SDMA_RAM_SIZE, pRamImagePA, (PVOID)(pRamImageUA), FALSE);

    return rc;
}


//-----------------------------------------------------------------------------
//
// Function:  SdmaDeinit
//
// This function deinitializes the SDMA.  Called by the Device Manager to
// de-initialize a device.
//
// Parameters:
//      None.
//
// Returns:
//      Returns TRUE.
//
//-----------------------------------------------------------------------------
BOOL SdmaDeinit(void)
{
    BOOL rc = TRUE;
    UINT8 chan;

    // Close all channels
    for (chan = 1; chan < SDMA_NUM_CHANNELS; chan++)
    {
        DDKSdmaCloseChan(chan);
    }
        
    // Deallocate SDMA driver data structures
    SdmaDealloc();

    return rc;
}


//-----------------------------------------------------------------------------
//
// Function:  SdmaAlloc
//
// This function allocates the data structures required for interaction
// with the SDMA hardware.
//
// Parameters:
//      None.
//
// Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL SdmaAlloc(void)
{
    BOOL rc = FALSE;
    PHYSICAL_ADDRESS phyAddr;

    if (g_pSDMA == NULL)
    {
        phyAddr.QuadPart = CSP_BASE_REG_PA_SDMA;

        // Map peripheral physical address to virtual address
        g_pSDMA = (PCSP_SDMA_REGS) MmMapIoSpace(phyAddr, sizeof(CSP_SDMA_REGS),
            FALSE);

        // Check if virtual mapping failed
        if (g_pSDMA == NULL)
        {
            ERRORMSG(1, (_T("MmMapIoSpace failed!\r\n")));
            goto cleanUp;
        }
    }

    if (g_pHostSharedUA == NULL)
    {
        phyAddr.QuadPart = INREG32(&g_pSDMA->MC0PTR);
        
        // If we have not yet allocated host shared region
        if (phyAddr.LowPart == 0)
        {
            ERRORMSG(1, (_T("SDMA MC0PTR not initialized!\r\n")));
            goto cleanUp;
        }

        // Map host shared physical address space to virtual address space
        g_pHostSharedUA = (PSDMA_HOST_SHARED_REGION) MmMapIoSpace(phyAddr,
            BSPSdmaGetSharedSize(), FALSE);

        RETAILMSG(TRUE, (_T("SDMA Memory Map:  PA = 0x%x, size = %d bytes"), 
            phyAddr.LowPart, BSPSdmaGetSharedSize()));

        // Check if virtual mapping failed
        if (g_pHostSharedUA == NULL)
        {
            ERRORMSG(1, (_T("MmMapIoSpace failed!\r\n")));
            goto cleanUp;
        }

        // Save physical address for use by other DLL functions
        g_pHostSharedPA = (PSDMA_HOST_SHARED_REGION) phyAddr.LowPart;
    }

    if (g_hSdmaMutex == NULL)
    {
        g_hSdmaMutex = CreateMutex(NULL, FALSE, L"MUTEX_SDMA");

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

    // Create mutex for supporting AHB bus scaling
    if (g_hAcrMutex == NULL)
    {
        g_hAcrMutex = CreateMutex(NULL, FALSE, L"MUTEX_ACR");

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

    rc = TRUE;

cleanUp:
    if (!rc)  SdmaDealloc();
    return rc;
}


//-----------------------------------------------------------------------------
//
// Function:  SdmaDealloc
//
// This function deallocates the data structures required for interaction
// with the SDMA hardware.  Note that data structures for individual channels
// are freed in SdmaDeinit.
//
// Parameters:
//      None.
//
// Returns:
//      Returns TRUE.

⌨️ 快捷键说明

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