📄 hwctxt.cpp
字号:
m_InputDMAStatus &= ~DMA_STRTB; // Buffer B just completed...
m_InputDMAStatus |= DMA_DONEB;
m_InputDMAStatus &= ~DMA_BIU; // Buffer A is in use
///////////////////////////////////
UINT32 delay_count1;
delay_count1 = 0;
while((v_pDMAregs->DSTAT2&0xfffff)==0){
#if WAIT_DMA_END
Sleep(1);
#else
if( delay_count1++ > DELAY_COUNT ) break;
#endif
}
////////////////////////////////// Added by JJG 07.03.04
#if DMA_FLAG
SELECT_AUDIO_DMA_INPUT_BUFFER_B();
#else
SELECT_AUDIO_DMA_INPUT_BUFFER_A();
#endif
RETAILMSG(AC97_DEBUG,(_T("In1\r\n")));
}else
{
m_InputDMAStatus &= ~DMA_STRTA; // Buffer A just completed...
m_InputDMAStatus |= DMA_DONEA;
m_InputDMAStatus |= DMA_BIU; // Buffer B is in use
///////////////////////////////////
UINT32 delay_count1;
delay_count1 = 0;
while((v_pDMAregs->DSTAT2&0xfffff)==0){
#if WAIT_DMA_END
Sleep(1);
#else
if( delay_count1++ > DELAY_COUNT ) break;
#endif
}
////////////////////////////////// Added by JJG 07.03.04
#if DMA_FLAG
SELECT_AUDIO_DMA_INPUT_BUFFER_A();
#else
SELECT_AUDIO_DMA_INPUT_BUFFER_B();
#endif
RETAILMSG(AC97_DEBUG,(_T("In2\r\n")));
}
#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);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:InterruptThread() - EXCEPTION: %d"), GetExceptionCode()));
}
//----- 10. Give up the lock -----
//Unlock();
}
}
void HardwareContext::InterruptThreadOutput()
{
ULONG OutputTransferred;
BOOL dmaInterruptSource = 0;
// Fast way to access embedded pointers in wave headers in other processes.
SetProcPermissions((DWORD)-1);
while(TRUE)
{
WaitForSingleObject(m_hAudioInterruptOutput, INFINITE);
RETAILMSG(AC97_DEBUG,(_T("InterruptThread\r\n")));
dmaInterruptSource = 0;
//----- 1. Grab the lock -----
//Lock();
__try
{
InterruptDone(m_dwSysintrOutput);
if ( m_Dx != D0 ) continue;
//----- 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
UINT32 delay_count2;
delay_count2 = 0;
while((v_pDMAregs->DSTAT1&0xfffff)==0){
#if WAIT_DMA_END
Sleep(1);
#else
if( delay_count2++ > DELAY_COUNT ) break;
#endif
}
RETAILMSG(AC97_DEBUG2,(_T("Out1\r\n")));
#if DMA_FLAG
SELECT_AUDIO_DMA_OUTPUT_BUFFER_B(); // charlie. B => A
#else
SELECT_AUDIO_DMA_OUTPUT_BUFFER_A(); // charlie. B => A
#endif
}else
{
m_OutputDMAStatus &= ~DMA_STRTA; // Buffer B just completed...
m_OutputDMAStatus |= DMA_DONEA;
m_OutputDMAStatus |= DMA_BIU; // Buffer A is in use
UINT32 delay_count2;
delay_count2 = 0;
while((v_pDMAregs->DSTAT1&0xfffff)==0){
#if WAIT_DMA_END
Sleep(1);
#else
if( delay_count2++ > DELAY_COUNT ) break;
#endif
}
RETAILMSG(AC97_DEBUG2,(_T("Out2\r\n")));
#if DMA_FLAG
SELECT_AUDIO_DMA_OUTPUT_BUFFER_A(); // charlie. B => A
#else
SELECT_AUDIO_DMA_OUTPUT_BUFFER_B(); // charlie. B => A
#endif
}
#if !DMA_FLAG
//----- 8. Schedule the next DMA transfer -----
AUDIO_OUT_DMA_ENABLE();
#endif
//----- 9. Fill the non-playing buffer with the next chunk of audio data to play -----
OutputTransferred = TransferOutputBuffers(m_OutputDMAStatus);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:InterruptThread() - EXCEPTION: %d"), GetExceptionCode()));
}
//----- 10. Give up the lock -----
//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)
{
static DWORD dwActiveChannel = 0;
USHORT volume;
Lock();
//
// Turn off/on mute bit in volume control register.
//
if( (channel & DMA_CH_OUT )) // 030711
{
if(bMute)
{
volume = ReadCodecRegister(AC97_HEADPHONE_VOL);
WriteCodecRegister(AC97_HEADPHONE_VOL, volume | 0x8000);
}
else
{
volume = ReadCodecRegister(AC97_HEADPHONE_VOL);
WriteCodecRegister(AC97_HEADPHONE_VOL, volume & ~0x8000);
}
}
#if AC97_RECORD_MICIN
if( (channel & DMA_CH_MIC ) )
{
if(bMute)
{
volume = ReadCodecRegister(AC97_MIC_VOL);
WriteCodecRegister(AC97_MIC_VOL, volume | 0x8000);
}
else
{
volume = ReadCodecRegister(AC97_MIC_VOL);
WriteCodecRegister(AC97_MIC_VOL, volume & ~0x8000);
}
}
#else
if( (channel & DMA_CH_MIC ))
{
if(bMute)
{
volume = ReadCodecRegister(AC97_LINEIN_VOL);
WriteCodecRegister(AC97_LINEIN_VOL, volume | 0x8000);
}
else
{
volume = ReadCodecRegister(AC97_LINEIN_VOL);
WriteCodecRegister(AC97_LINEIN_VOL, volume & ~0x8000);
}
}
#endif
Unlock();
return(TRUE);
}
void CallInterruptThreadInput(HardwareContext *pHWContext)
{
pHWContext->InterruptThreadInput();
}
void CallInterruptThreadOutput(HardwareContext *pHWContext)
{
pHWContext->InterruptThreadOutput();
}
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.
DWORD dwErr = DevicePowerNotify(_T("WAV1:"), D0, POWER_NAME);
if ( ERROR_SUCCESS != dwErr ) {
RETAILMSG(1, (TEXT("WAVEDEV::Open:DevicePowerNotify ERROR: %u\r\n"), dwErr ));
mmErr = MMSYSERR_ERROR;
}
}
return mmErr;
}
DWORD
HardwareContext::Close(
void
)
{
DWORD mmErr = MMSYSERR_NOERROR;
DWORD dwErr;
// we are done so inform Power Manager to power us down, 030711
dwErr = DevicePowerNotify(_T("WAV1:"), (_CEDEVICE_POWER_STATE)D4, POWER_NAME);
if ( ERROR_SUCCESS != dwErr ) {
RETAILMSG(1, (TEXT("WAVEDEV::Close:DevicePowerNofify ERROR: %u\r\n"), dwErr ));
mmErr = MMSYSERR_ERROR;
}
return mmErr;
}
BOOL
HardwareContext::IOControl(
DWORD dwOpenData,
DWORD dwCode,
PBYTE pBufIn,
DWORD dwLenIn,
PBYTE pBufOut,
DWORD dwLenOut,
PDWORD pdwActualOut)
{
DWORD dwErr = ERROR_SUCCESS;
BOOL bRc = TRUE;
UNREFERENCED_PARAMETER(dwOpenData);
switch (dwCode) {
//
// Power Management
//
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 = 0x11;
// no wake
// no inrush
// Report our nominal power consumption in uAmps rather than mWatts.
ppc->Flags = POWER_CAP_PREFIX_MICRO | POWER_CAP_UNIT_AMPS;
// REVIEW: Do we enable all these for normal playback?
// D0: SPI + I2S + CODEC (Playback) + Headphone=
// 0.5 mA + 0.5 mA + (23 mW, into BUGBUG ohms ) + (30 mW, into 32 ohms)
// 500 uA + 500 uA + 23000 uA + 32000 uA
ppc->Power[D0] = 56000;
*pdwActualOut = sizeof(POWER_CAPABILITIES);
} break;
case IOCTL_POWER_SET:
{
CEDEVICE_POWER_STATE NewDx;
bRc = TRUE;
break;
if ( !pdwActualOut || !pBufOut || (dwLenOut < sizeof(CEDEVICE_POWER_STATE)) ) {
bRc = FALSE;
dwErr = ERROR_INVALID_PARAMETER;
break;
}
NewDx = *(PCEDEVICE_POWER_STATE)pBufOut;
if ( VALID_DX(NewDx) ) {
// grab the CS since the normal Xxx_PowerXxx can not.
Lock();
switch ( NewDx ) {
case D0:
if (m_Dx != D0) {
PowerUp();
m_Dx = D0;
}
break;
default:
if (m_Dx != (_CEDEVICE_POWER_STATE)D4) {
PowerDown();
m_Dx = (_CEDEVICE_POWER_STATE)D4;
}
break;
}
// return our state
*(PCEDEVICE_POWER_STATE)pBufOut = m_Dx;
RETAILMSG(1, (TEXT("WAVEDEV: IOCTL_POWER_SET: D%u => D%u \r\n"), NewDx, 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 + -