📄 hwctxt.cpp
字号:
// Load B
BytesTransferred += TransferInputBuffer(IN_BUFFER_B);
break;
}
// If it was our interrupt, but we weren't able to transfer any bytes
// (e.g. no empty buffers ready to be filled)
// Then stop the input DMA
if (BytesTransferred==0)
{
//RETAILMSG(1,(TEXT("+++ NO BYTES transferred by DMA\r\n")));
StopInputDMA();
}
return BytesTransferred;
}
void HardwareContext::InterruptThread()
{
ULONG InputTransferred, OutputTransferred;
BOOL dmaInterruptSource = 0;
// Fast way to access embedded pointers in wave headers in other processes.
SetProcPermissions((DWORD)-1);
RETAILMSG(DBG_AUDIO,(TEXT("InterruptThread... wait event\n")));
while(TRUE)
{
RETAILMSG(DBG_AUDIO,(TEXT("Wait event\n")));
RETAILMSG(DBG_AUDIO,(TEXT(" INTMSK[0x%x]\n"),s2443INT->INTMSK));
WaitForSingleObject(m_hAudioInterrupt, INFINITE);
RETAILMSG(DBG_AUDIO,(TEXT("INTMSK: 0x%x\n"),s2443INT->INTMSK));
g_ForCount++;
dmaInterruptSource = 0;
//----- 1. Grab the lock -----
Lock();
__try
{
RETAILMSG(DBG_AUDIO,(TEXT("try\n")));
//----- 3. Determine the interrupt source (input DMA operation or output DMA operation?) -----
//----- NOTE: Often, platforms use two separate DMA channels for input/output operations but
// have the OAL return SYSINTR_AUDIO as the interrupt source. If this is the case,
// then the interrupt source (input or output DMA channel) must be determined in
// this step.
// charlie, determine the interrupt source
/*
RETAILMSG(1,(TEXT("INTMSK: 0x%x\n"),s2443INT->INTMSK));
RETAILMSG(1,(TEXT("INTPND: 0x%x\n"),s2443INT->INTPND));
RETAILMSG(1,(TEXT("SUBSRCPND: 0x%x\n"),s2443INT->SUBSRCPND));
RETAILMSG(1,(TEXT("INTSUBMSK: 0x%x\n"),s2443INT->INTSUBMSK));*/
if( s2443INT->INTSUBMSK & (1<< IRQ_SUB_DMA1))
{
delay_count = 0;
dmaInterruptSource |= DMA_CH_MIC; // Input DMA is supported...
// For determine the interrupt source
//----- 2. Acknowledge the DMA interrupt -----
//RETAILMSG(1,(TEXT("MIC-------------------\n")));
InterruptDone(m_dwSysintrInput);
}
if( s2443INT->INTSUBMSK & (1<< IRQ_SUB_DMA2)){
dmaInterruptSource |= DMA_CH_OUT; // Output DMA is supported...
// For determine the interrupt source
//----- 2. Acknowledge the DMA interrupt -----
InterruptDone(m_dwSysintrOutput);
}
//----- 4. Handle any interrupts on the input source -----
// NOTE: The InterruptDone() call below automatically clears the interrupt.
if((dmaInterruptSource == DMA_CH_MIC))
{
//----- Determine which buffer just completed the DMA transfer -----
if(m_InputDMAStatus & DMA_BIU)
{
m_InputDMAStatus &= ~DMA_STRTB; // Buffer B just completed...
m_InputDMAStatus |= DMA_DONEB;
m_InputDMAStatus &= ~DMA_BIU; // Buffer A is in use
#if DMA_FLAG
SELECT_AUDIO_DMA_INPUT_BUFFER_B();
#else
SELECT_AUDIO_DMA_INPUT_BUFFER_A();
#endif
//RETAILMSG(1,(TEXT("try2-MIC_B(%x)\n"), m_InputDMAStatus));
}else
{
m_InputDMAStatus &= ~DMA_STRTA; // Buffer A just completed...
m_InputDMAStatus |= DMA_DONEA;
m_InputDMAStatus |= DMA_BIU; // Buffer B is in use
#if DMA_FLAG
SELECT_AUDIO_DMA_INPUT_BUFFER_A();
#else
SELECT_AUDIO_DMA_INPUT_BUFFER_B();
#endif
//RETAILMSG(1,(TEXT("try2_A(%x)\n"), m_InputDMAStatus));
}
#if !DMA_FLAG
//----- 5. Schedule the next DMA transfer -----
AUDIO_IN_DMA_ENABLE();
#endif
//----- 6. Retrieve the next chunk of recorded data from the non-playing buffer -----
InputTransferred = TransferInputBuffers(m_InputDMAStatus);
}
else
{
//----- 7. Handle any interrupts on the output source -----
// NOTE: The InterruptDone() call below automatically clears the interrupt.
//----- Determine which buffer just completed the DMA transfer -----
if(m_OutputDMAStatus & DMA_BIU)
{
m_OutputDMAStatus &= ~DMA_STRTB; // Buffer A just completed...
m_OutputDMAStatus |= DMA_DONEB;
m_OutputDMAStatus &= ~DMA_BIU; // Buffer B is in use
// Wait for start DMA.
delay_count = 0;
while((g_pDMAregs->DSTAT2&0xfffff)==0){
if( delay_count++ > DELAY_COUNT ) break;
}
#if DMA_FLAG
SELECT_AUDIO_DMA_OUTPUT_BUFFER_B(); // charlie. B => A
#else
SELECT_AUDIO_DMA_OUTPUT_BUFFER_A(); // charlie. B => A
#endif
RETAILMSG(DBG_AUDIO,(_T("try-DMA_BIU-B(%x)\n"), m_OutputDMAStatus));
}else
{
m_OutputDMAStatus &= ~DMA_STRTA; // Buffer B just completed...
m_OutputDMAStatus |= DMA_DONEA;
m_OutputDMAStatus |= DMA_BIU; // Buffer A is in use
// Wait for start DMA.
delay_count = 0;
while((g_pDMAregs->DSTAT2&0xfffff)==0){
if( delay_count++ > DELAY_COUNT ) break;
}
#if DMA_FLAG
SELECT_AUDIO_DMA_OUTPUT_BUFFER_A(); // charlie. B => A
#else
SELECT_AUDIO_DMA_OUTPUT_BUFFER_B(); // charlie. B => A
#endif
}
// SET_AUDIO_DMA_OUTPUT_DCON();
// AUDIO_OUT_DMA_ENABLE();
#if !DMA_FLAG
//----- 8. Schedule the next DMA transfer -----
AUDIO_OUT_DMA_ENABLE();
#endif
RETAILMSG(DBG_AUDIO,(_T("try-!DMA_BIU-A(%x)\n"), m_OutputDMAStatus));
//----- 9. Fill the non-playing buffer with the next chunk of audio data to play -----
OutputTransferred = TransferOutputBuffers(m_OutputDMAStatus);
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
RETAILMSG(DBG_AUDIO, (TEXT("WAVDEV2.DLL:InterruptThread() - EXCEPTION: %d"), GetExceptionCode()));
}
//----- 10. Unlock -----
Unlock();
}
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: AudioMute()
Description: Mutes/unmutes the specified audio channel.
Notes: If both audio channels are MUTED, then the chip
is powered down to conserve battery life.
Alternatively, if either audio channel is unMUTED,
the chip is powered up.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::AudioMute(DWORD channel, BOOL bMute)
{
#if 0
static DWORD dwActiveChannel = 0;
{
if(bMute)
{
_WrL3Addr(0x14);
_WrL3Data(0xa4,0);
}
else
{
_WrL3Addr(0x14);
_WrL3Data(0xa0,0);
}
}
#endif
return(TRUE);
}
void CallInterruptThread(HardwareContext *pHWContext)
{
pHWContext->InterruptThread();
}
DWORD HardwareContext::Open(void)
{
DWORD mmErr = MMSYSERR_NOERROR;
// Don't allow play when not on, if there is a power constraint upon us.
if ( D0 != m_Dx )
{
// Tell the Power Manager we need to power up.
// If there is a power constraint then fail.
RETAILMSG(DBG_WAV, (TEXT("[A_HW] Open : DevicePowerNotify - D0\r\n")));
DWORD dwErr = DevicePowerNotify(_T("WAV1:"), D0, POWER_NAME);
if ( ERROR_SUCCESS != dwErr )
{
RETAILMSG(DBG_WAV, (TEXT("WAVEDEV::Open:DevicePowerNotify ERROR1: %u\r\n"), dwErr ));
dwErr = DevicePowerNotify(_T("WAV1:"), D0, POWER_NAME);
mmErr = MMSYSERR_ERROR;
}
}
return mmErr;
}
DWORD HardwareContext::Close(void)
{
DWORD mmErr = MMSYSERR_NOERROR;
DWORD dwErr;
if (bInputClose==TRUE) bIsRecording = FALSE;
else bIsPlaying = FALSE;
// we are done so inform Power Manager to power us down
if(bIsPlaying==FALSE && bIsRecording==FALSE)
{
bClosing = TRUE;
if ( D4 != m_Dx )
{
RETAILMSG(DBG_WAV, (TEXT("[A_HW] Close : DevicePowerNotify - D4\r\n")));
dwErr = DevicePowerNotify(_T("WAV1:"), (_CEDEVICE_POWER_STATE)D4, POWER_NAME);
if ( ERROR_SUCCESS != dwErr )
{
RETAILMSG(DBG_WAV, (TEXT("WAVEDEV::Close:DevicePowerNofify ERROR1: %u\r\n"), dwErr));
dwErr = DevicePowerNotify(_T("WAV1:"), (_CEDEVICE_POWER_STATE)D4, POWER_NAME);
mmErr = MMSYSERR_ERROR;
}
}
}
if(bInputClose==TRUE && m_InputDMARunning==TRUE)
{
RETAILMSG(1, (TEXT("[A_HW] Close : StopInputDMA Exception!\r\n")));
StopInputDMA();
}
bInputClose=FALSE;
return mmErr;
}
void HardwareContext::CodecPowerDown()
{
if(!bIdlePwrDown)
{
RETAILMSG(DBG_WAV,(TEXT("[A_HW] CodecPowerDown : Done\r\n")));
}
else
RETAILMSG(DBG_WAV,(TEXT("[A_HW] CodecPowerDown : Already Off\r\n")));
}
BOOL
HardwareContext::IOControl(DWORD dwOpenData,
DWORD dwCode,
PBYTE pBufIn,
DWORD dwLenIn,
PBYTE pBufOut,
DWORD dwLenOut,
PDWORD pdwActualOut)
{
DWORD dwErr = ERROR_SUCCESS;
BOOL bRc = TRUE;
WCHAR wPState[20];
DWORD dFlag;
switch (dwCode) {
//
// Power Management
//
case IOCTL_POWER_QUERY:
if(pBufOut != NULL && dwLenIn == sizeof(CEDEVICE_POWER_STATE))
{
// return a good status on any valid query, since we are always ready to
// change power states.
bRc = FALSE;
__try
{
CEDEVICE_POWER_STATE NewDx = *(PCEDEVICE_POWER_STATE) pBufOut;
if(VALID_DX(NewDx))
{
// this is a valid Dx state so return a good status
bRc = TRUE;
}
RETAILMSG(1, (L"%s: IOCTL_POWER_QUERY %u %s\r\n", TEXT("AUDIO"),
NewDx, bRc == TRUE ? L"succeeded" : L"failed"));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
RETAILMSG(1, (L"%s: exception in ioctl2\r\n"));
bRc=FALSE;
}
}
break;
case IOCTL_POWER_CAPABILITIES:
{
PPOWER_CAPABILITIES ppc;
if ( !pdwActualOut || !pBufOut || (dwLenOut < sizeof(POWER_CAPABILITIES)) ) {
bRc = FALSE;
dwErr = ERROR_INVALID_PARAMETER;
break;
}
ppc = (PPOWER_CAPABILITIES)pBufOut;
memset(ppc, 0, sizeof(POWER_CAPABILITIES));
// support D0, D4
ppc->DeviceDx = DX_MASK(D0)|DX_MASK(D4);
DEBUGMSG(ZONE_FUNCTION, (TEXT("WAVE: IOCTL_POWER_CAPABILITIES = 0x%x\r\n"), ppc->DeviceDx));
RETAILMSG(DBG_WAV,(TEXT("WAVDEV::IOCTL_POWER_CAPABILITIES\r\n")));
*pdwActualOut = sizeof(POWER_CAPABILITIES);
} break;
case IOCTL_POWER_SET:
CEDEVICE_POWER_STATE NewDx;
if ( !pdwActualOut || !pBufOut || (dwLenOut < sizeof(CEDEVICE_POWER_STATE)) )
{
bRc = FALSE;
dwErr = ERROR_INVALID_PARAMETER;
break;
}
NewDx = *(PCEDEVICE_POWER_STATE)pBufOut;
RETAILMSG(1, (TEXT("[A_HW] IOControl(IOCTL_POWER_SET) : D%u => D%u \r\n"), m_Dx, NewDx));
if ( VALID_DX(NewDx) )
{
// grab the CS since the normal Xxx_PowerXxx can not.
Lock();
switch ( NewDx )
{
case D0:
if (m_Dx != D0)
{
m_Dx = D0;
// Codec Power On, if Off
if (bIdlePwrDown == TRUE) // When Codec is off,
{
RETAILMSG(1, (TEXT("[A_HW] IOControl : Turning Codec On\r\n")));
/*g_pCLKPWRreg->CLKSRC = g_pCLKPWRreg->CLKSRC & ~(0x3<<14); //clock from Divided EPLL
g_pIISregs->IISMOD = g_pIISregs->IISMOD & ~(0x3<<10) | (0x01<<10); //clock from EPLL*/
g_pIISregs->IISMOD = g_pIISregs->IISMOD & ~(0x3<<10); // PCLK
//g_pCLKPWRreg->CLKCON |= IIS_INTERNAL_CLOCK_ENABLE;
InitCodec();
bIdlePwrDown = FALSE; // Then, Codec is on
}
dwErr = GetSystemPowerState(wPState, 20, &dFlag);
RETAILMSG(1, (TEXT("[A_HW] IOControl : System Power State - %s \r\n"),wPState));
//bPowerSet = TRUE; // for logo test (unattended mode)
}
break;
default:
if (m_Dx != (_CEDEVICE_POWER_STATE)D4)
{
m_Dx = (_CEDEVICE_POWER_STATE)D4;
dwErr = GetSystemPowerState(wPState, 20, &dFlag);
RETAILMSG(1, (TEXT("[A_HW] IOControl : System Power State - %s \r\n"),wPState));
AudioMute((DMA_CH_OUT | DMA_CH_MIC), TRUE);
if(m_OutputDMARunning && !bClosing && (_tcscmp(wPState, _T("unattended")) != 0))
{
bDoingSuspend = TRUE;
RETAILMSG(1, (TEXT("[A_HW] IOControl : going into Suspend state\r\n")));
}
bClosing = FALSE;
//bPowerSet = FALSE; // for logo test (unattended mode)
}
break;
}
// return our state
*(PCEDEVICE_POWER_STATE)pBufOut = m_Dx;
Unlock();
*pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
}
else
{
bRc = FALSE;
dwErr = ERROR_INVALID_PARAMETER;
}
break;
case IOCTL_POWER_GET:
if ( !pdwActualOut || !pBufOut || (dwLenOut < sizeof(CEDEVICE_POWER_STATE)) )
{
bRc = FALSE;
dwErr = ERROR_INVALID_PARAMETER;
break;
}
*(PCEDEVICE_POWER_STATE)pBufOut = m_Dx;
RETAILMSG(1, (TEXT("WAVEDEV: IOCTL_POWER_GET: D%u \r\n"), m_Dx));
*pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
break;
default:
bRc = FALSE;
dwErr = ERROR_INVALID_FUNCTION;
DEBUGMSG (ZONE_FUNCTION, (TEXT(" Unsupported ioctl 0x%X\r\n"), dwCode));
break;
}
if ( !bRc ) {
SetLastError(dwErr);
}
return(bRc);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -