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