📄 hwctxt_kingfish2.cpp
字号:
{
ULONG BytesTransferred = 0;
ULONG BytesTotal;
DWORD Bits = dwDCSR & (DMA_DONEA|DMA_DONEB|DMA_BIU);
RETAILMSG(AC97_DEBUG2,(_T("TransferOutputBuffers:%d\r\n"),Bits));
switch (Bits)
{
case 0:
case DMA_BIU:
// No done bits set- must not be my interrupt
return 0;
case DMA_DONEA|DMA_DONEB|DMA_BIU:
// Load B, then A
BytesTransferred = TransferOutputBuffer(OUT_BUFFER_B);
// fall through
case DMA_DONEA: // This should never happen!
case DMA_DONEA|DMA_BIU:
BytesTransferred += TransferOutputBuffer(OUT_BUFFER_A); // charlie, A => B
break;
case DMA_DONEA|DMA_DONEB:
// Load A, then B
BytesTransferred = TransferOutputBuffer(OUT_BUFFER_A);
// charlie
BytesTransferred += TransferOutputBuffer(OUT_BUFFER_B);
break; // charlie
// fall through
case DMA_DONEB|DMA_BIU: // This should never happen!
case DMA_DONEB:
// Load B
BytesTransferred += TransferOutputBuffer(OUT_BUFFER_B); // charlie, B => A
break;
}
// If it was our interrupt, but we weren't able to transfer any bytes
// (e.g. no full buffers ready to be emptied)
// and all the output DMA buffers are now empty, then stop the output DMA
BytesTotal = m_OutBytes[OUT_BUFFER_A]+m_OutBytes[OUT_BUFFER_B];
if (BytesTotal==0)
{
StopOutputDMA();
}
return BytesTransferred;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: TransferInputBuffer()
Description: Retrieves the chunk of recorded sound data and inputs
it into an audio buffer for potential "mixing".
Returns: Number of bytes needing to be transferred.
-------------------------------------------------------------------*/
ULONG HardwareContext::TransferInputBuffer(ULONG NumBuf)
{
ULONG BytesTransferred = 0;
PBYTE pBufferStart = m_Input_pbDMA_PAGES[NumBuf];
PBYTE pBufferEnd = pBufferStart + AUDIO_DMA_PAGE_SIZE;
PBYTE pBufferLast;
RETAILMSG(AC97_DEBUG3,(_T("TransferInputBuffer:%d\r\n"),NumBuf));
__try
{
pBufferLast = m_InputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd,NULL);
BytesTransferred = m_InBytes[NumBuf] = pBufferLast-pBufferStart;
if(NumBuf == IN_BUFFER_A) // Input Buffer A
{
m_InputDMAStatus &= ~DMA_DONEA;
m_InputDMAStatus |= DMA_STRTA;
}
else // Input Buffer B
{
m_InputDMAStatus &= ~DMA_DONEB;
m_InputDMAStatus |= DMA_STRTB;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:TransferInputBuffer() - EXCEPTION: %d"), GetExceptionCode()));
}
return BytesTransferred;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: TransferInputBuffers()
Description: Determines which input buffer (A or B) needs to
be filled with recorded sound data. The correct
buffer is then populated with recorded sound data
from the input channel.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
ULONG HardwareContext::TransferInputBuffers(DWORD dwDCSR)
{
ULONG BytesTransferred=0;
DWORD Bits = dwDCSR & (DMA_DONEA|DMA_DONEB|DMA_BIU);
RETAILMSG(AC97_DEBUG3,(_T("TransferInputBuffers:%d\r\n"),Bits));
switch (Bits)
{
case 0:
case DMA_BIU:
// No done bits set- must not be my interrupt
return 0;
case DMA_DONEA|DMA_DONEB|DMA_BIU:
// Load B, then A
BytesTransferred = TransferInputBuffer(IN_BUFFER_B);
// fall through
case DMA_DONEA: // This should never happen!
case DMA_DONEA|DMA_BIU:
// Load A
BytesTransferred += TransferInputBuffer(IN_BUFFER_A);
break;
case DMA_DONEA|DMA_DONEB:
// Load A, then B
BytesTransferred = TransferInputBuffer(IN_BUFFER_A);
BytesTransferred += TransferInputBuffer(IN_BUFFER_B);
break;
// fall through
case DMA_DONEB|DMA_BIU: // This should never happen!
case DMA_DONEB:
// 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)
{
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);
while(TRUE)
{
WaitForSingleObject(m_hAudioInterrupt, INFINITE);
dmaInterruptSource = 0;
//----- 1. Grab the lock -----
Lock();
__try
{
//----- 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.
if( s2440INT->INTMSK & (1 << IRQ_DMA2) ){
dmaInterruptSource |= DMA_CH_MIC; // Input DMA is supported...
//----- 2. Acknowledge the DMA interrupt -----
InterruptDone(m_dwSysintrInput);
}
if( s2440INT->INTMSK & (1 << IRQ_DMA1) ){
dmaInterruptSource |= DMA_CH_OUT;
// Output DMA is supported...
//----- 2. Acknowledge the DMA interrupt -----
InterruptDone(m_dwSysintrOutput);
}
if ( m_Dx != D0 ) continue;
//----- 4. Handle any interrupts on the input source -----
// NOTE: The InterruptDone() call below automatically clears the interrupt.
if ((dmaInterruptSource & DMA_CH_MIC) != 0)
{
//----- 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(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
#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);
}
//----- 7. Handle any interrupts on the output source -----
// NOTE: The InterruptDone() call below automatically clears the interrupt.
if ((dmaInterruptSource & DMA_CH_OUT) != 0)
{
//----- 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
delay_count = 0;
while((g_pDMAregs->DSTAT1&0xfffff)==0){
#if WAIT_DMA_END
Sleep(1);
#else
if( delay_count++ > 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
delay_count = 0;
while((g_pDMAregs->DSTAT1&0xfffff)==0){
#if WAIT_DMA_END
Sleep(1);
#else
if( delay_count++ > 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;
//
// Turn off/on mute bit in volume control register.
//
if( (channel & DMA_CH_OUT ) && !m_OutputDMARunning ) // 030711
{
if(g_SoundPath == HEADPHONE)
{
if(bMute)
{
volume = ReadCodecRegister(AC97_HEADPHONE_VOL);
WriteCodecRegister(AC97_HEADPHONE_VOL, volume | 0x8080);
}
else
{
volume = ReadCodecRegister(AC97_HEADPHONE_VOL);
WriteCodecRegister(AC97_HEADPHONE_VOL, volume & ~0x8080);
}
}
else
{
if(bMute)
{
volume = ReadCodecRegister(AC97_LOUDSPK_VOL);
WriteCodecRegister(AC97_LOUDSPK_VOL, volume | 0x8080);
}
else
{
volume = ReadCodecRegister(AC97_LOUDSPK_VOL);
WriteCodecRegister(AC97_LOUDSPK_VOL, volume & ~0x8080);
}
}
}
#if AC97_RECORD_MICIN
if( (channel & DMA_CH_MIC ) && !m_InputDMARunning )
{
if(bMute)
{
volume = ReadCodecRegister(AC97_REC_VOL);
WriteCodecRegister(AC97_REC_VOL, volume | 0x8000);
}
else
{
volume = ReadCodecRegister(AC97_REC_VOL);
WriteCodecRegister(AC97_REC_VOL, volume & ~0x8000);
}
}
#else
if( (channel & DMA_CH_MIC ) && !m_InputDMARunning )
{
if(bMute)
{
volume = ReadCodecRegister(AC97_LINEIN_VOL);
WriteCodecRegister(AC97_LINEIN_VOL, volume | 0xe000);
}
else
{
volume = ReadCodecRegister(AC97_LINEIN_VOL);
WriteCodecRegister(AC97_LINEIN_VOL, volume & ~0xe000);
}
}
#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.
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;
}
}
retu
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -