📄 dmawince.c
字号:
//
// These are taken by wave (audio) driver.
//
pDMAGlobals->pArrayChannel[WMDMA_STEREO_OUT] = 1;
pDMAGlobals->pArrayChannel[WMDMA_STEREO_IN] = 1;
# if WM_MONODAC
pDMAGlobals->pArrayChannel[WMDMA_MONO_OUT] = 1;
# endif /* WM_MONODAC */
# if WM_VOICE
pDMAGlobals->pArrayChannel[WMDMA_VOICE_OUT] = 1;
# endif /* WM_VOICE */
#endif /* !WM_USE_DYNAMIC_DMA_CHANNEL */
pDMAGlobals->gDmacIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//
// Create DMA IST
// This thread will handle all DMA interrupts and be responsible for calling appropriate
// second level handlers.
//
if (!(InterruptInitialize(SYSINTR_DMA, pDMAGlobals->gDmacIntrEvent, NULL, 0)))
{
RETAILMSG(1,(TEXT("DMAC: Interrupt initialization failed IID = %d...\r\n"), SYSINTR_DMA));
DEBUGMSG(1,(TEXT("SYSINTR_MAXIMUM = %d"), SYSINTR_MAXIMUM));
xllpStatus = XLLP_STATUS_FAILURE;
goto finish;
}
pDMAGlobals->gDmacThreadReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
pDMAGlobals->gDmacIntrThread =
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) DmacIntrThread, NULL, 0, NULL);
if ( pDMAGlobals->gDmacIntrThread == NULL )
{
DEBUGMSG(1,(TEXT("DMAC: CreateThread failed.\r\n")));
xllpStatus = XLLP_STATUS_NO_RESOURCES;
goto finish;
}
SetThreadPriority( pDMAGlobals->gDmacIntrThread, THREAD_PRIORITY_TIME_CRITICAL );
WaitForSingleObject(pDMAGlobals->gDmacThreadReadyEvent, INFINITE);
//
// Initialize DMAC hardware
// This will also stop any ongoing DMA activity
//
pDMAGlobals->hDMAEvent[0] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_0);
pDMAGlobals->hDMAEvent[1] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_1);
pDMAGlobals->hDMAEvent[2] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_2);
pDMAGlobals->hDMAEvent[3] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_3);
pDMAGlobals->hDMAEvent[4] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_4);
pDMAGlobals->hDMAEvent[5] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_5);
pDMAGlobals->hDMAEvent[6] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_6);
pDMAGlobals->hDMAEvent[7] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_7);
pDMAGlobals->hDMAEvent[8] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_8);
pDMAGlobals->hDMAEvent[9] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_9);
pDMAGlobals->hDMAEvent[10] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_10);
pDMAGlobals->hDMAEvent[11] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_11);
pDMAGlobals->hDMAEvent[12] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_12);
pDMAGlobals->hDMAEvent[13] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_13);
pDMAGlobals->hDMAEvent[14] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_14);
pDMAGlobals->hDMAEvent[15] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_15);
pDMAGlobals->hDMAEvent[16] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_16);
pDMAGlobals->hDMAEvent[17] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_17);
pDMAGlobals->hDMAEvent[18] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_18);
pDMAGlobals->hDMAEvent[19] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_19);
pDMAGlobals->hDMAEvent[20] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_20);
pDMAGlobals->hDMAEvent[21] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_21);
pDMAGlobals->hDMAEvent[22] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_22);
pDMAGlobals->hDMAEvent[23] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_23);
pDMAGlobals->hDMAEvent[24] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_24);
pDMAGlobals->hDMAEvent[25] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_25);
pDMAGlobals->hDMAEvent[26] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_26);
pDMAGlobals->hDMAEvent[27] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_27);
pDMAGlobals->hDMAEvent[28] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_28);
pDMAGlobals->hDMAEvent[29] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_29);
pDMAGlobals->hDMAEvent[30] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_30);
pDMAGlobals->hDMAEvent[31] = CreateEvent(NULL,FALSE,FALSE,DMA_CHANNEL_31);
XllpDmacHwInit();
XllpDmacEnableInterrupt();
Sleep(10);
SetEvent(hFirstTime); // Signal that GDE Setup has successfully completed.
finish:
return xllpStatus;
}
//******************************************************************************
//
// Function Name: DmacIntrThread
//
// Description: The IST for DMA Controller interrupt.
//
//
// Input Arguments:
//
//
// Output Arguments:
//
//
// Return Value:
// None
//
// Notes: Calls the XllpDmacIntHandler which does the guts of the work
//
//*******************************************************************************
INT WINAPI DmacIntrThread
(
void
)
{
DWORD tmpDINT;
//DWORD EventData;
int i;
XLLP_VUINT32_T *pDCSR ;
XLLP_VUINT32_T tmpDCSR;
XLLP_VUINT32_T tmpDcsrClear;
SetEvent(pDMAGlobals->gDmacThreadReadyEvent);
while (TRUE)
{
WaitForSingleObject(pDMAGlobals->gDmacIntrEvent, INFINITE);
// DMA interrupts are currently masked. This routine will not be interrupted by another DMA interrupt.
tmpDINT = pDmacHandle->DINT;
for ( i=0; i<XLLP_DMAC_CHANNEL_NUM; i++ )
{
if (tmpDINT & (1u << i))
{
// Provide the Waiting Object the current value of the channel Status Register.
// where data describing the specific cause of the interrupt is held. The
// Dma Engine clears the Status register when it acknowledges the interrupt.
SetEventData(pDMAGlobals->hDMAEvent[i], pDmacHandle->DCSR[i]);
// Acknowledge the given interrupt channel
//pDmacHandle->DCSR[i] |= (0x1 << 2); // Orig.
pDCSR = &(pDmacHandle->DCSR[i]);
tmpDCSR = *pDCSR;
// 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
*pDCSR = tmpDcsrClear;
// Signal the waiting thread
SetEvent(pDMAGlobals->hDMAEvent[i]); // should search this list in priority order instead of linearly.
// Stop searching if there are no more threads to signal
if ((unsigned)i >= tmpDINT)
break;
}
}
// Now that we have SetEvent on all known interrupt source, we can re-enable DMA interrupts.
InterruptDone(SYSINTR_DMA);
}
return XLLP_STATUS_SUCCESS;
}
BOOL XllpDmacAcquireMutex
(
HANDLE *hDmacMutex,
DWORD timeout
)
{
//
// Create the mutex for protecting access to shared data structures (channel array map)
// Need to be acquired before calling XllpAllocate/FreeChannel
//
if ((*hDmacMutex = CreateMutex(NULL, FALSE, DMAC_MUTEX_NAME)) == NULL)
{
return FALSE;
}
if (WaitForSingleObject(*hDmacMutex, timeout) == WAIT_TIMEOUT)
{
CloseHandle(*hDmacMutex);
return FALSE;
}
return TRUE;
}
VOID XllpDmacFreeMutex
(
HANDLE hDmacMutex
)
{
ReleaseMutex(hDmacMutex);
CloseHandle(hDmacMutex);
}
void XllpDmacDumpStatus( XLLP_DMAC_CHANNEL_T aChannel )
{
//RETAILMSG(1,(TEXT("DMA:>DumpStatus DmaChan=%02d Src=0x%08x Tgt=0x%08x Cmd=0x%08x Dcsr=0x%08x DINT=0x%08x \r\n"),aChannel, pDmacHandle->DDG[aChannel].DSADR, pDmacHandle->DDG[aChannel].DTADR, pDmacHandle->DDG[aChannel].DCMD, pDmacHandle->DCSR[aChannel], pDmacHandle->DINT ));
//RETAILMSG(1,(TEXT("DMA:>DrcmrRx=0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x \r\n"), pDmacHandle->DRCMR1[48], pDmacHandle->DRCMR1[50],pDmacHandle->DRCMR1[52],pDmacHandle->DRCMR1[54],pDmacHandle->DRCMR1[56],pDmacHandle->DRCMR1[58],pDmacHandle->DRCMR1[60] ));
//RETAILMSG(1,(TEXT("DMA:>DrcmrTx=0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x \r\n"), pDmacHandle->DRCMR1[49], pDmacHandle->DRCMR1[51],pDmacHandle->DRCMR1[53],pDmacHandle->DRCMR1[55],pDmacHandle->DRCMR1[57],pDmacHandle->DRCMR1[59],pDmacHandle->DRCMR1[61] ));
}
void XllpDmacEnableInterrupt
(
)
{
volatile XLLP_INTC_T *v_pICReg;
v_pICReg = ( XLLP_INTC_T *)VirtualAllocCopyPhysical(sizeof(XLLP_INTC_T),"v_pICReg",(PVOID)(BULVERDE_BASE_REG_PA_INTC));
if (v_pICReg == NULL)
return;
INTC_DMAC_INT_EN(v_pICReg->icmr);
}
void XllpDmacDisableInterrupt
(
)
{
volatile XLLP_INTC_T *v_pICReg;
v_pICReg = ( XLLP_INTC_T *)VirtualAllocCopyPhysical(sizeof(XLLP_INTC_T),"v_pICReg",(PVOID)(BULVERDE_BASE_REG_PA_INTC));
if (v_pICReg == NULL)
return;
INTC_DMAC_INT_DIS(v_pICReg->icmr);
}
//******************************************************************************
//
// Function Name: OSMemAlloc
//
// Description: Allocates a block of memory
//
//
// Input Arguments:
// numBytes: Number of bytes to allocate
//
// Output Arguments:
//
//
// Return Value:
// void*: Pointer to allocated memory. NULL if unsuccessful.
//
// Notes:
// Memory allocated by this call is aligned on page boundary (4K on XScale)
//
//*******************************************************************************
VOID* OSMemAlloc
(
UINT32 numBytes
)
{
return VirtualAlloc(0, numBytes, MEM_COMMIT, PAGE_READWRITE | PAGE_NOCACHE);
}
//******************************************************************************
//
// Function Name: OSMemFree
//
// Description: Frees a previously allocated block of memory
//
//
// Input Arguments:
// VOID* memPtr: pointer to memory to deallocate
//
// Output Arguments:
//
//
// Return Value:
//
//
// Notes:
//
//
//*******************************************************************************
VOID OSMemFree
(
VOID* memPtr
)
{
VirtualFree(memPtr, 0, MEM_RELEASE);
}
//******************************************************************************
//
// Function Name: OSGetMaxPages
//
// Description: Returns max number of physical pages that may be occupied by a user buffer
//
//
// Input Arguments:
// pBuffer: Virtual address to user buffer
// bufferLength: Length of user buffer
//
// Output Arguments:
//
//
// Return Value:
// Maximum number of physical pages that can be spanned by user buffer
//
// Notes:
// WinCe generally allocates memory aligned on page boundaries.
//
//*******************************************************************************
XLLP_UINT32_T OSGetMaxPages
(
XLLP_UINT8_T *pBuffer,
XLLP_UINT32_T bufferLength
)
{
return ADDRESS_AND_SIZE_TO_SPAN_PAGES(pBuffer, bufferLength);
}
//******************************************************************************
//
// Function Name: OSLockPhysicalPages
//
// Description: Locks physical pages representing a virtual address space into memory.
// Returns information about locked pages to user
//
//
// Input Arguments:
// VOID* virtualAddress: Pointer to virtual address space to lock
// UINT32 numBytesTolock; Number of bytes of linear address sace to lock
// UINT32 osFlags: OS specific flags.
//
// Output Arguments:
// UINT32 *pageAddresses: Array in which list of all physical pages representing
// buffer is returned
//
// Return Value:
// TRUE: if successful
// FALSE: otherwise
//
// Notes:
// Invokes LockPages on WinCE which is supported for .NET, PocketPC and SmartPhone
// platforms
//
//*******************************************************************************
BOOL OSLockPhysicalPages
(
VOID* virtualAddress,
XLLP_UINT32_T numBytesToLock,
XLLP_UINT32_T *pageAddresses,
XLLP_UINT32_T osFlags
)
{
return LockPages(virtualAddress, numBytesToLock, pageAddresses, osFlags);
}
//******************************************************************************
//
// Function Name: OSUnlockPhysicalPages
//
// Description: Unlocks previously locked physical pages representing a virtual
// address space into memory.
//
// Input Arguments:
// VOID* virtualAddress: Pointer to virtual address space to lock
// UINT32 numBytesToUnlock; Number of bytes of linear address sace to unlock
//
// Output Arguments:
//
// Return Value:
// TRUE: if successful
// FALSE: otherwise
//
// Notes:
// Invokes UnlockPages on WinCE which is supported for .NET, PocketPC and SmartPhone
// platforms
//
//*******************************************************************************
BOOL OSUnlockPhysicalPages
(
VOID* virtualAddress,
XLLP_UINT32_T numBytesToUnlock
)
{
return UnlockPages(virtualAddress, numBytesToUnlock);
}
//=============================================================================
//=========================Working DMA Sample Code ============================
//================================ Start ======================================
//
// To validate the "DMA Engine" the following two routines were called in the
// Keyboard IST when the "0" key was pressed. Diagnostic output via the function
// NKDbgPrintfW(..) shows the Virtual and Physical addresses used to setup and
// run the Memory-to-Memory DMA transfer
//
// XllpDmacInit(void);
// XllpDmacTest(void);
//
// Note: XllpDmacTest was added to dma.def for validation testing.
//
//=============================================================================
//=============================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -