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

📄 dma.cpp

📁 Windows CE 6.0 BSP for the Beagle Board.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
// Portions Copyright (c) Texas Instruments.  All rights reserved.
//
//------------------------------------------------------------------------------

#include <string.h>
#include "wavemain.h"
#include "omap3_defs.h"
#include "ceddk.h"
#include "omap3_mcbsp.h"
#include "dma_arb.h"
//#undef DEBUGMSG
//#define DEBUGMSG(x, y) RETAILMSG(1,y)
//#define DEBUG 1

//------------------------------------------------------------------------------
//
//  DMA definitions
//

// looping number in case DMA fails
#define DMA_SAFETY_LOOP_NUM     100

#if defined(DEBUG)
static void DumpDMA_LC(PTSTR szChannel, OMAP2420_DMA_REGS *pCh);
#endif

//------------------------------------------------------------------------------
//
//  Function: OMAP2420DMAContext ()

OMAP2420DMAContext::OMAP2420DMAContext()
{
    m_hCont = NULL;
    m_pInDMAReg = NULL;
    m_pOutDMAReg = NULL;
    m_paAudioDMA.LowPart = 0;
    m_paAudioDMA.HighPart = 0;
    m_pbDMABufOut=NULL;
    m_pbDMABufIn=NULL;
}


//------------------------------------------------------------------------------
//
//  Function: HWMapDMAMemory ()
//  
//  Map DMA related H/W registers and allocate continous DMA pages into the 
//  local address space.
//

BOOL
OMAP2420DMAContext::HWMapDMAMemory(DWORD dwSize)
{
    PBYTE pbDMATemp;
    PHYSICAL_ADDRESS pa;

    /* find the system dma controller */
    uint bytesToAlloc = 0;
    uint err = DMA_ControllerEnum(NULL,&bytesToAlloc);
    if (err!=DMAERR_NOTENOUGHSPACE)
    {
        DEBUGMSG(ZONE_ERROR, (L"OMAP2420DMAContext::HWMapDMAMemory: "
            L"Could not get size of enumeration of platform dma controllers.\r\n"
        ));
        return FALSE;
    }
    DMACONTROLLER *pContList = (DMACONTROLLER *)malloc(bytesToAlloc);
    if (pContList == NULL)
    {
        DEBUGMSG(ZONE_ERROR, (L"OMAP2420DMAContext::HWMapDMAMemory: "
            L"Could not malloc dma controllers.\r\n"
        ));
        return FALSE;
    }
    err = DMA_ControllerEnum(pContList,&bytesToAlloc);
    if (err)
    {
        DEBUGMSG(ZONE_ERROR, (L"OMAP2420DMAContext::HWMapDMAMemory: "
            L"Could not enumerate platform dma controllers.\r\n"
        ));
        free(pContList);
        return FALSE;
    }
    /* find the system dma controller */
    uint numEntries = bytesToAlloc/sizeof(DMACONTROLLER);
    uint i;
    for(i=0;i<numEntries;i++)
    {
        if (!_stricmp(pContList[i].mName,"System"))
            break;
    }
    if (i==numEntries)
    {
        DEBUGMSG(ZONE_ERROR, (L"OMAP2420DMAContext::HWMapDMAMemory: "
            L"Could not find \"System\" dma controller.\r\n"
        ));
        free(pContList);
        return FALSE;
    }
    uint controllerId = pContList[i].mSysId;
    free(pContList);

    /* open the controller now */
    err = DMA_ControllerOpen(controllerId, &m_hCont);
    if (err)
    {
        DEBUGMSG(ZONE_ERROR, (L"OMAP2420DMAContext::HWMapDMAMemory: "
            L"Could not open \"System\" dma controller.\r\n"
        ));
        return FALSE;
    }

    /* we need to allocate our input and output channels */
    uint chanIO = (1<<AUDIO_INPUT_DMA_CHANNEL) | (1<<AUDIO_OUTPUT_DMA_CHANNEL);
    err = DMA_ControllerAcquireChannels(m_hCont, 2, &chanIO);
    if (err)
    {
        DEBUGMSG(ZONE_ERROR, (L"OMAP2420DMAContext::HWMapDMAMemory: "
            L"Could not acquire audio i/o channels\r\n"
        ));
        DMA_ControllerClose(m_hCont);
        m_hCont = NULL;
        return FALSE;
    }

    /* if we get here, then we have ownership of the two dma channels we need */

    // map DMA registers into driver address space
    pa.HighPart= 0;
    pa.LowPart = OMAP3_SDMA_REGS_PA;
    volatile OMAP2420_SDMA_REGS *pDMA_Regs = (OMAP2420_SDMA_REGS *)MmMapIoSpace(pa, sizeof(OMAP2420_SDMA_REGS), FALSE);
    if (!pDMA_Regs)
    {
        DEBUGMSG(ZONE_ERROR, (L"OMAP2420DMAContext::HWMapDMAMemory: "
            L"ERROR mapping DMA registers.\n"
        ));
        goto ErrExit;
    }

    // enable input DMA IRQ
    err = DMA_ControllerSet(m_hCont, DMACP_L3IntEnb, 1<< AUDIO_INPUT_DMA_CHANNEL);
    if (err)
    {
        DEBUGMSG(ZONE_ERROR, (L"OMAP2420DMAContext::HWMapDMAMemory: "
            L"ERROR setting IRQ for L3 input dma channel.\r\n"
        ));
        goto ErrExit;
    }
    // enable output DMA IRQ
    err = DMA_ControllerSet(m_hCont, DMACP_L2IntEnb, 1<< AUDIO_OUTPUT_DMA_CHANNEL);
    if (err)
    {
        DEBUGMSG(ZONE_ERROR, (L"OMAP2420DMAContext::HWMapDMAMemory: "
            L"ERROR setting IRQ for L2 output dma channel.\r\n"
        ));
        goto ErrExit;        
    }

    // get the channel register pointers
    m_pInDMAReg  = &pDMA_Regs->CHNL_CTRL[AUDIO_INPUT_DMA_CHANNEL];
    m_pOutDMAReg = &pDMA_Regs->CHNL_CTRL[AUDIO_OUTPUT_DMA_CHANNEL];

    // allocate the DMA pages
    DMA_ADAPTER_OBJECT AdapterObject; 
    AdapterObject.ObjectSize = sizeof(AdapterObject); 
    AdapterObject.InterfaceType = Internal; 
    AdapterObject.BusNumber = 0; 
    m_pbDMABufOut = NULL;

    pbDMATemp = (PBYTE)HalAllocateCommonBuffer(&AdapterObject, dwSize, &m_paAudioDMA, FALSE);
    if (!pbDMATemp)
    {
        DEBUGMSG(ZONE_ERROR, (L"OMAP2420DMAContext::HWMapDMAMemory: "
            L"ERROR mapping DMA memory.\n"
        ));
        goto ErrExit;
    }

    m_pbDMABufOut = m_pbDMABufIn = pbDMATemp;

#ifdef MIXER_CACHEDMEM
    // Map DMA buffer also to cached memory for DMA out
    // Mixer will call cache flush after block is completed
    m_pbDMABufOut = (PBYTE)MmMapIoSpace(m_paAudioDMA, dwSize, TRUE);
    if (!m_pbDMABufOut)
    {
        DEBUGMSG(ZONE_ERROR, (L"OMAP2420DMAContext::HWMapDMAMemory: "
            L"ERROR mapping DMA buffer to cached memory, using uncached.\n"
        ));
        m_pbDMABufOut = pbDMATemp;
    }
#endif

    return TRUE;

ErrExit:

    m_pInDMAReg  =NULL;
    m_pOutDMAReg =NULL;
    m_pbDMABufOut=NULL;
    m_pbDMABufIn =NULL;

    if (m_hCont)
    {
        DMA_ControllerClose(m_hCont);
        m_hCont = NULL;
    }

    return FALSE;
}


//------------------------------------------------------------------------------
//
//  Function: CheckDMAStatus ()
//  
//  DMA status verification for debugging
//

#if defined(DEBUG)
static void 
CheckDMAStatus(OMAP2420_DMA_REGS  *pDMAReg, BOOL fEnabled)
{
    DWORD dwCount = 0;

    DWORD dwValConfirm = INREG32(&pDMAReg->DMA4_CCR);
    if (fEnabled) 
    {
        while ( !( dwValConfirm & DMA_CCR_ENABLE ) )
        {
            // Put safety checking in case something is wrong
            if (dwCount++>DMA_SAFETY_LOOP_NUM)
                break;

            dwValConfirm = INREG32(&pDMAReg->DMA4_CCR);
            DEBUGMSG(ZONE_ERROR, (L"OMAP2420DMAContext::HWMapDMAMemory: "
                L"ERROR DMA safety checking = %d %08X\r\n", fEnabled, dwValConfirm
            ));
        }
    }
    else
    {
        while ( dwValConfirm & DMA_CCR_ENABLE )
        {
            // Put safety checking in case something is wrong
            if (dwCount++>DMA_SAFETY_LOOP_NUM)
                break;

            dwValConfirm = INREG32(&pDMAReg->DMA4_CCR);
            DEBUGMSG(ZONE_ERROR, (L"OMAP2420DMAContext::HWMapDMAMemory: "
                L"ERROR DMA safety checking = %d %08X\r\n", fEnabled, dwValConfirm
            ));
        }
    }
}
#endif  // #if defined(DEBUG)


//------------------------------------------------------------------------------
//
//  Function: HWInitInputDMA ()
//  
//  Initialize the input DMA. 
//

void 
OMAP2420DMAContext::HWInitInputDMA()
{
    OMAP2420_DMA_REGS  *pDMAReg;
    DWORD   dwAddr, dwVal;

    DEBUGMSG(ZONE_FUNCTION, (L"+OMAP2420DMAContext::HWInitInputDMA()\r\n"));

    pDMAReg = m_pInDMAReg;

    // disable the channel, clear the configuration
    SETREG32(&pDMAReg->DMA4_CCR, 0);

    // link this channel to itself to get continuous operation
    OUTREG32(&pDMAReg->DMA4_CLNK_CTRL, AUDIO_INPUT_DMA_CHANNEL);

    // 16 bits scalar, no pack, no burst
    OUTREG32(&pDMAReg->DMA4_CSDP, DMA_CSDP_DATATYPE_16BIT);

    // request number, post incremented destination address, high priority
    dwVal = DMA_CCR_SYNC(AUDIO_INPUT_DMA_REQ) | DMA_CCR_DST_AMODE_POST_INC | DMA_CCR_PRIO;
    OUTREG32(&pDMAReg->DMA4_CCR, dwVal);

    // source address
    OUTREG32(&pDMAReg->DMA4_CSSA, AUDIO_INPUT_DMA_SOURCE);

    // destination address
    dwAddr = m_paAudioDMA.LowPart + AUDIO_DMA_PAGES * AUDIO_DMA_PAGE_SIZE;      
    OUTREG32(&pDMAReg->DMA4_CDSA, dwAddr);

    // interrupt conditions
    dwVal = DMA_CICR_FRAME_IE | DMA_CICR_HALF_IE | DMA_CICR_DROP_IE;
    OUTREG32(&pDMAReg->DMA4_CICR, dwVal);

    // number of samples per frame
    OUTREG32(&pDMAReg->DMA4_CEN, AUDIO_DMA_PAGE_SIZE);

    // number of frames per block
    OUTREG32(&pDMAReg->DMA4_CFN, 1);

    // source frame index and element index
    OUTREG32(&pDMAReg->DMA4_CSFI, 0);
    OUTREG32(&pDMAReg->DMA4_CSEI, 0);

    // destination frame index and element index
    OUTREG32(&pDMAReg->DMA4_CDFI, 0);
    OUTREG32(&pDMAReg->DMA4_CDEI, 0);

#if defined(DEBUG)
    DumpDMA_LC(L"Init Input", pDMAReg);
#endif

    DEBUGMSG(ZONE_FUNCTION, (L"-OMAP2420DMAContext::HWInitInputDMA()\r\n"));
}

//------------------------------------------------------------------------------
//
//  Function: HWInitOutputDMA ()
//  
//  Initialize the output DMA. 
//

void 
OMAP2420DMAContext::HWInitOutputDMA()
{
    OMAP2420_DMA_REGS  *pDMAReg;
    DWORD   dwAddr, dwVal;

    DEBUGMSG(ZONE_FUNCTION, (L"+OMAP2420DMAContext::HWInitOutputDMA()\r\n"));

    pDMAReg = m_pOutDMAReg;

    // disable the channel, clear the configuration
    SETREG32(&pDMAReg->DMA4_CCR, 0);

    // link this channel to itself to get continuous operation
    OUTREG32(&pDMAReg->DMA4_CLNK_CTRL, AUDIO_OUTPUT_DMA_CHANNEL);

    // 16 bits scalar, no pack, no burst
    OUTREG32(&pDMAReg->DMA4_CSDP, DMA_CSDP_DATATYPE_16BIT);

    // request number, post incremented source address, high priority
    dwVal = DMA_CCR_SYNC(AUDIO_OUTPUT_DMA_REQ) | DMA_CCR_SRC_AMODE_POST_INC | DMA_CCR_PRIO;
    OUTREG32(&pDMAReg->DMA4_CCR, dwVal);

    // source address
    dwAddr = m_paAudioDMA.LowPart;     
    OUTREG32(&pDMAReg->DMA4_CSSA, dwAddr);

    // destination address
    OUTREG32(&pDMAReg->DMA4_CDSA, AUDIO_OUTPUT_DMA_DEST);

    // interrupt conditions
    dwVal = DMA_CICR_FRAME_IE | DMA_CICR_HALF_IE | DMA_CICR_DROP_IE;
    OUTREG32(&pDMAReg->DMA4_CICR, dwVal);

    // number of samples per frame
    OUTREG32(&pDMAReg->DMA4_CEN, AUDIO_DMA_PAGE_SIZE);

⌨️ 快捷键说明

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