📄 pingpongdma.cpp
字号:
//**********************************************************************
//
// Filename: pingpongdma.cpp
//
// Description: Ping pong dma class
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Use of this source code is subject to the terms of the Cirrus end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to
// use this source code. For a copy of the EULA, please see the
// EULA.RTF on your install media.
//
// Copyright(c) Cirrus Logic Corporation 2003, All Rights Reserved
//
//**********************************************************************
#include "wavecommon.h"
//
// This shows the type of bus we are on.
//
static const DMA_ADAPTER_OBJECT DmaAdapter =
{
sizeof(DMA_ADAPTER_OBJECT),
Internal,
0
};
#if 0
const ULONG DmaInterrupts[NUM_DMA_CHANNELS] =
{
SYSINTR_DMA0,
SYSINTR_DMA1,
SYSINTR_DMA2,
SYSINTR_DMA3,
SYSINTR_DMA4,
SYSINTR_DMA5,
SYSINTR_DMA6,
SYSINTR_DMA7,
SYSINTR_DMA8,
SYSINTR_DMA9
}
volatile ULONG const *g_pulDmaBaseAddress[NUM_DMA_CHANNELS] =
{
DMA_M2P0_TX_BASE,
DMA_M2P1_RX_BASE,
DMA_M2P2_TX_BASE,
DMA_M2P3_RX_BASE,
DMA_M2P4_TX_BASE,
DMA_M2P5_RX_BASE,
DMA_M2P6_TX_BASE,
DMA_M2P7_RX_BASE,
DMA_M2P8_TX_BASE,
DMA_M2P9_RX_BASE,
};
#endif // 0
//****************************************************************************
// ConvertChannelToNNumber
//****************************************************************************
//
//
//
static ULONG GetInterruptNumber(volatile ULONG *pulDmaBase)
{
ULONG ulSysIntr;
switch((ULONG)pulDmaBase)
{
case (ULONG)DMA_M2P0_TX_BASE:
ulSysIntr = SYSINTR_DMA0;
break;
case (ULONG)DMA_M2P1_RX_BASE:
ulSysIntr = SYSINTR_DMA1;
break;
case (ULONG)DMA_M2P2_TX_BASE:
ulSysIntr = SYSINTR_DMA2;
break;
case (ULONG)DMA_M2P3_RX_BASE:
ulSysIntr = SYSINTR_DMA3;
break;
case (ULONG)DMA_M2P4_TX_BASE:
ulSysIntr = SYSINTR_DMA4;
break;
case (ULONG)DMA_M2P5_RX_BASE:
ulSysIntr = SYSINTR_DMA5;
break;
case (ULONG)DMA_M2P6_TX_BASE:
ulSysIntr = SYSINTR_DMA6;
break;
case (ULONG)DMA_M2P7_RX_BASE:
ulSysIntr = SYSINTR_DMA7;
break;
case (ULONG)DMA_M2P8_TX_BASE:
ulSysIntr = SYSINTR_DMA8;
break;
case (ULONG)DMA_M2P9_RX_BASE:
ulSysIntr = SYSINTR_DMA9;
break;
default:
ulSysIntr = SYSINTR_NOP;
PRINTMSG
(
ZONE_ERROR,
(
TEXT("ERROR : Bad Dma Base 0x%08x"),
(ULONG)pulDmaBase
)
);
DebugBreak();
//
// Bad value.
//
break;
}
return(ulSysIntr);
}
//****************************************************************************
// PingPongDma::PingPongDma
//****************************************************************************
// Constructor
//
//
PingPongDma::PingPongDma(void):
m_pBuffer(0),
m_ulBufferSize(0),
m_pulDma(0),
m_ulPeriph(0),
m_ulCurrentPos(0),
m_ulSysIntr(0),
m_bPlaying(FALSE),
m_bExitThread(FALSE),
m_pfnCallBack(0),
m_hCallBackHandle(0),
m_bOrder(0)
{
m_ulPhysBuff = 0;
}
//****************************************************************************
// PingPongDma::~PingPongDma
//****************************************************************************
// Destructor
//
//
PingPongDma::~PingPongDma(void)
{
FUNC_DMA((L"+PingPongDma::~PingPongDma\n"));
//
// Kill the interrupt thread. I need to know the proper way to do
// this.
//
if(m_hThread)
{
m_bExitThread = TRUE;
WaitForSingleObject
(
m_hThread,
INFINITE
);
}
if(m_hEvent)
{
CloseHandle(m_hEvent);
}
//
// Free the memory. I doubt that this will ever happen but just in case.
//
if(m_pBuffer)
{
FreePhysMem(m_pBuffer);
}
FUNC_DMA((L"-PingPongDma::~PingPongDma\n"));
}
//****************************************************************************
// PingPongDma::Initialize
//****************************************************************************
//
// Since a constructor cannot return an error value we must return the
// use an initialize function.
//
MMRESULT PingPongDma::Initialize
(
volatile ULONG *pulDmaChannel,
ULONG ulPeripheral,
ULONG ulBufferSize
)
{
MMRESULT Result = MMSYSERR_NOERROR;
// ULONG ulPwrcnt;
BOOL bIntInit;
FUNC_DMA((L"+PingPongDma::Initialize\n"));
//
// Program the power control register to use all dma channels.
//
// ulPwrcnt = *CSC_PWRCNT;
// *CSC_SYSLOCK = 0xAA;
// *CSC_PWRCNT = ulPwrcnt | PWRCNT_DMAM2PCH1 | PWRCNT_DMAM2PCH0 |
// PWRCNT_DMAM2PCH3 | PWRCNT_DMAM2PCH2 | PWRCNT_DMAM2PCH5 |
// PWRCNT_DMAM2PCH4 | PWRCNT_DMAM2PCH7 | PWRCNT_DMAM2PCH6 |
// PWRCNT_DMAM2PCH9 | PWRCNT_DMAM2PCH8;
//Sleep(1);
//
// Allocate a DMA buffer.
//
m_pBuffer = AllocPhysMem
(
ulBufferSize,
PAGE_READWRITE | PAGE_NOCACHE,
0,
0,
&m_ulPhysBuff
);
if(!m_pBuffer)
{
ERRMSG((L"PingPongDma::Initialize Failed to Allocate DMA buffer. \r\n"));
Result = MMSYSERR_NOMEM;
}
//
// Create an event and a thread, and then associate them.
//
if(Result == MMSYSERR_NOERROR)
{
m_hEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
if(!m_hEvent)
{
ERRMSG((L"PingPongDma::Initialize Failed to Create Interrupt Event.\r\n"));
Result = MMSYSERR_NOMEM;
}
}
//
// Get the event handle, register the interrupt, and then
// associate it with the event.
//
if(Result == MMSYSERR_NOERROR)
{
m_ulSysIntr = GetInterruptNumber(pulDmaChannel);
bIntInit = InterruptInitialize(m_ulSysIntr,m_hEvent, NULL, 0) ;
if(!bIntInit)
{
ERRMSG((L"PingPongDma::Initialize Failed to hook interrupt \r\n"));
Result = MMSYSERR_NOMEM;
}
}
//
// Create the thread for the IST, passing it the event handle.
// The IST code calls WaitOnSingleObject, so give it the event handle.
//
if(Result == MMSYSERR_NOERROR)
{
m_hThread = CreateThread
(
(LPSECURITY_ATTRIBUTES)NULL,
0,
(LPTHREAD_START_ROUTINE)IST,
(PVOID)this,
0,
NULL
);
if(!m_hThread)
{
ERRMSG((L"PingPongDma::Initialize Failed to Create IST Thread.\r\n"));
Result = MMSYSERR_NOMEM;
}
}
if(Result == MMSYSERR_NOERROR)
{
//
// Set the new thread priority to a high priority.
// This thread priority may be too low.
//
//CeSetThreadPriority(m_hThread, 249);
CeSetThreadPriority(m_hThread, 200);
m_pulDma = pulDmaChannel;
m_ulPeriph = ulPeripheral;
m_ulBufferSize = ulBufferSize;
//
// Set up so there is a next frame interrupt, but keep DMA off.
//
m_pulDma[M2P_CTRL>>2] = M2P_CTRL_NFBINTEN |
M2P_CTRL_STALLINTEN |
M2P_CTRL_ICE;
m_pulDma[M2P_PPALLOC>>2] = m_ulPeriph & PRALLOC_MASK;
m_pulDma[M2P_REMAIN>>2] = 0;
Flush();
}
FUNC_DMA((L"-PingPongDma::Initialize\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -