📄 hwctxt.cpp
字号:
//
// 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 "wavemain.h"
#include "nkintr.h"
//------------------------------------------------------------------------------
HardwareContext *g_pHWContext=NULL;
//------------------------------------------------------------------------------
static void CallInterruptThreadTx(HardwareContext *pHWContext);
static void CallInterruptThreadRx(HardwareContext *pHWContext);
static void CallTimeoutThread(HardwareContext *pHWContext);
//#undef DEBUGMSG
//#define DEBUGMSG(x, y) RETAILMSG(1,y)
//------------------------------------------------------------------------------
//
// Function: HardwareContext::HardwareContext()
//
// HardwareContext constructor.
//
HardwareContext::HardwareContext()
: m_InputDeviceContext(), m_OutputDeviceContext()
{
InitializeCriticalSection(&m_Lock);
m_fTerminating = FALSE;
m_Initialized=FALSE;
m_hParent = NULL;
m_CurPowerState = PwrDeviceUnspecified ;
m_hAudioInterruptThreadRx = NULL;
m_hAudioInterruptThreadTx = NULL;
m_hTimeoutThread = NULL;
m_fRequestedSysIntr = FALSE;
m_IntrAudioRx = m_IntrAudioTx = SYSINTR_UNDEFINED ;
m_fRxInterruptIntialized = m_fTxInterruptIntialized = FALSE;
m_hTimeoutEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
m_hAudioInterruptTx = CreateEvent( NULL, FALSE, FALSE, NULL);
m_hAudioInterruptRx = CreateEvent( NULL, FALSE, FALSE, NULL);
}
//------------------------------------------------------------------------------
//
// Function: HardwareContext::~HardwareContext()
//
// destructor
//
HardwareContext::~HardwareContext()
{
m_fTerminating = TRUE;
if (m_hTimeoutEvent!=NULL)
SetEvent(m_hTimeoutEvent);
if (m_hAudioInterruptTx!=NULL)
SetEvent(m_hAudioInterruptTx);
if (m_hAudioInterruptRx)
SetEvent(m_hAudioInterruptRx);
Sleep(500); // Sleep 500 ticks to allow all thread terminated.
TerminateCloseThread(m_hAudioInterruptThreadTx);
TerminateCloseThread(m_hAudioInterruptThreadRx);
TerminateCloseThread(m_hTimeoutThread);
if (m_fRxInterruptIntialized)
InterruptDisable(m_IntrAudioRx);
if (m_fTxInterruptIntialized)
InterruptDisable(m_IntrAudioTx);
if (m_IntrAudioTx != SYSINTR_UNDEFINED && m_fRequestedSysIntr) {
KernelIoControl( IOCTL_HAL_RELEASE_SYSINTR,&m_IntrAudioTx, sizeof( m_IntrAudioTx ), NULL, 0, NULL );
}
if (m_IntrAudioRx != SYSINTR_UNDEFINED && m_fRequestedSysIntr) {
KernelIoControl( IOCTL_HAL_RELEASE_SYSINTR,&m_IntrAudioRx, sizeof( m_IntrAudioRx ), NULL, 0, NULL );
}
if (m_hTimeoutEvent)
CloseHandle(m_hTimeoutEvent);
if (m_hParent ) {
SetDevicePowerState(m_hParent, D4 , NULL);
CloseBusAccessHandle (m_hParent ) ;
}
DeleteCriticalSection(&m_Lock);
}
void HardwareContext::TerminateCloseThread(HANDLE hThread)
{
if (hThread) {
if( ::WaitForSingleObject( hThread, 0 ) != WAIT_OBJECT_0 ) // Can't terminate. Force it.
::TerminateThread( hThread, ( DWORD ) - 1 ) ;
::CloseHandle( hThread );
}
}
//------------------------------------------------------------------------------
//
// Function: Init
//
// map registers, allocate DMA buffers, set hardware to known state
//
BOOL
HardwareContext::Init(DWORD Index)
{
DEBUGMSG(ZONE_AC,(TEXT("WAVEDEV: HardwareContext::Init Index=0x%x\r\n"), Index));
if (m_Initialized)
{
return FALSE;
}
m_hParent = CreateBusAccessHandle((LPCTSTR) Index) ;
m_DriverIndex = Index;
m_InPowerHandler = FALSE;
m_InputDMARunning = FALSE;
m_OutputDMARunning = FALSE;
m_NumForcedSpeaker = 0;
m_bDMARunning = FALSE;
m_bBtHeadsetSelected= FALSE;
m_dwBtAudioRouting = BT_AUDIO_MODEM;
m_bHeadsetPluggedIn = FALSE;
m_bToggleLoadSpeaker= FALSE;
m_hRil = NULL;
// Map registers and the DMA buffers into driver's virtual address space
if (!InitMemories())
{
goto Exit;
}
// Init codec.
InitCodec();
// Configure the DMA controller
InitDMA();
// Configure the controller
InitController();
if (!InitInterruptThread())
{
goto Exit;
}
m_Initialized=TRUE;
Exit:
return m_Initialized;
}
//------------------------------------------------------------------------------
//
// Function: InitMemories()
//
// Map DMA pages into the local address space
//
BOOL
HardwareContext::InitMemories()
{
PBYTE pbDMABufIn, pbDMABufOut;
if (!HWMapControllerRegs ())
{
goto ErrExit;
}
if (HWMapDMAMemory(AUDIO_DMA_PAGE_SIZE*AUDIO_DMA_PAGES*2))
{
pbDMABufIn = HWDMAMemoryIn();
pbDMABufOut = HWDMAMemoryOut();
// Save pointers to the virtual addresses so the driver can access them
for (int i=0; i<AUDIO_DMA_PAGES; i++)
{
m_Output_pbDMA_PAGES[i] = pbDMABufOut + AUDIO_DMA_PAGE_SIZE*i;
m_Input_pbDMA_PAGES[i] = pbDMABufIn + ((AUDIO_DMA_PAGES+i)*AUDIO_DMA_PAGE_SIZE);
}
return TRUE;
}
ErrExit:
return FALSE;
}
//------------------------------------------------------------------------------
//
// Function: InitDMA()
//
// set DMA registers to known state
//
void
HardwareContext::InitDMA()
{
HWInitInputDMA();
HWInitOutputDMA();
}
//------------------------------------------------------------------------------
//
// Function: InitController()
//
//
//
void
HardwareContext::InitController()
{
HWInitController();
HWInitNetwork();
}
//------------------------------------------------------------------------------
//
// Function: InitCodec()
//
//
//
void
HardwareContext::InitCodec()
{
HWInitCodec();
}
//------------------------------------------------------------------------------
//
// Function: StartOutputDMA()
//
// start output DMA on first call and transfer data to DMA buffers
//
void
HardwareContext::StartOutputDMA()
{
if (!m_OutputDMARunning)
{
// Set output dma to running state in case we get
// reentered during TransferOutputBuffer
m_OutputDMARunning=TRUE;
// Prime the output buffer and turn on DMA if anything got transferred
ULONG OutputTransferred;
OutputTransferred = TransferOutputBuffer(0)+TransferOutputBuffer(1);
// If we didn't transfer any data to the DMA buffers, don't enable DMA
if (OutputTransferred==0)
{
m_OutputDMARunning=FALSE;
return;
}
m_bDMARunning = TRUE;
HWUpdateAudioPRC ();
HWStartOutputDMA();
}
}
//------------------------------------------------------------------------------
//
// Function: StopOutputDMA()
//
// stop output DMA and adjust power state
//
void
HardwareContext::StopOutputDMA()
{
if (m_OutputDMARunning)
{
m_OutputDMARunning=FALSE;
HWStopOutputDMA();
if (!m_InputDMARunning && !m_OutputDMARunning)
{
// Take care of power management.
m_bDMARunning = FALSE;
SetupDelayUpdate ();
}
}
}
//------------------------------------------------------------------------------
//
// Function: StartInputDMA()
//
// start wave capture DMA, adjust power state and route audio to modem input
//
void
HardwareContext::StartInputDMA()
{
if (!m_InputDMARunning)
{
#ifdef INPUT_CACHEDMEM
InputBufferCacheDiscard( m_Input_pbDMA_PAGES[0],AUDIO_DMA_PAGE_SIZE*2);
#endif
m_InputDMARunning=TRUE;
m_bDMARunning = TRUE;
HWUpdateAudioPRC ();
// Turn on the recording path.
SetRecordMemoPath (TRUE);
HWStartInputDMA();
}
}
//------------------------------------------------------------------------------
//
// Function: StopInputDMA()
//
// stop capture DMA and switch off modem input
//
void
HardwareContext::StopInputDMA()
{
if (m_InputDMARunning)
{
m_InputDMARunning=FALSE;
HWStopInputDMA();
// Turn off the recording path.
SetRecordMemoPath (FALSE);
if (!m_InputDMARunning && !m_OutputDMARunning)
{
// Take care of power management.
m_bDMARunning = FALSE;
SetupDelayUpdate ();
}
}
}
void HardwareContext::SetupDelayUpdate()
{
SetEvent(m_hTimeoutEvent);
}
void HardwareContext::DelayedUpdate()
{
HWAudioPowerTimeout(TRUE); // Timeout.
}
//------------------------------------------------------------------------------
//
// Function: GetInterruptThreadPriority()
//
// allow registry key to override priority of interrupt threads
//
void
HardwareContext::GetRegistryValue()
{
HKEY hDevKey;
m_dwPriority256 = 210; // Default priority
m_dwTimeoutTicks = 1000; // 1 second.
hDevKey = OpenDeviceKey((LPWSTR)m_DriverIndex);
if (hDevKey)
{
DWORD dwValType;
DWORD dwValLen;
dwValLen = sizeof(DWORD);
RegQueryValueEx(
hDevKey,
TEXT("Priority256"),
NULL,
&dwValType,
(PUCHAR)&m_dwPriority256,
&dwValLen);
dwValLen = sizeof(DWORD);
RegQueryValueEx(
hDevKey,
TEXT("SuspendDelayTicks"),
NULL,
&dwValType,
(PUCHAR)&m_dwTimeoutTicks,
&dwValLen);
if (m_dwTimeoutTicks == 0 )
m_dwTimeoutTicks = INFINITE;
RegCloseKey(hDevKey);
}
}
//------------------------------------------------------------------------------
//
// Function: MapIrqToSysIntr()
//
// get dynamic mapping of hardware irq to software sysintr
//
DWORD
HardwareContext::MapIrqToSysIntr(DWORD irq)
{
DWORD dwSysIntr = SYSINTR_UNDEFINED;
if (!KernelIoControl(
IOCTL_HAL_REQUEST_SYSINTR,
&irq,
sizeof(irq),
&dwSysIntr,
sizeof(dwSysIntr),
NULL))
{
DEBUGMSG(ZONE_ERROR,
(TEXT("WaveDev: IRQ -> SYSINTR translation failed\r\n")));
dwSysIntr = SYSINTR_UNDEFINED;
}
return dwSysIntr;
}
//------------------------------------------------------------------------------
//
// Function: InitInterruptThread()
//
// start interrupt threads and map hardware interrupts to IST
//
BOOL
HardwareContext::InitInterruptThread()
{
DEBUGMSG(ZONE_AC,
(TEXT("WaveDev: HardwareContext::InitInterruptThread\r\n")));
if ( !(m_hTimeoutEvent !=NULL && m_hAudioInterruptTx !=NULL && m_hAudioInterruptRx !=NULL))
return FALSE;
GetRegistryValue();
m_fRequestedSysIntr = TRUE;
m_IntrAudioTx = MapIrqToSysIntr(AUDIO_OUTPUT_DMA_IRQ);
m_IntrAudioRx = MapIrqToSysIntr(AUDIO_INPUT_DMA_IRQ);
if (m_IntrAudioTx == SYSINTR_UNDEFINED ||
m_IntrAudioRx == SYSINTR_UNDEFINED)
{
return FALSE;
}
m_fRxInterruptIntialized = InterruptInitialize(m_IntrAudioTx, m_hAudioInterruptTx, NULL, 0);
m_fTxInterruptIntialized = InterruptInitialize(m_IntrAudioRx, m_hAudioInterruptRx, NULL, 0);
if (!m_fRxInterruptIntialized || !m_fTxInterruptIntialized)
return FALSE ;
m_hAudioInterruptThreadTx = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
0,
(LPTHREAD_START_ROUTINE)CallInterruptThreadTx,
this,
0,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -