📄 hwctxt.cpp
字号:
InterruptDone(m_SysIntrAudioDMA);
} // while(TRUE)
}
void CallInterruptThread(HardwareContext *pHWContext)
{
DEBUGMSG(ZONE_INIT, (TEXT("CallInterruptThread")));
pHWContext->InterruptThread();
}
void CallInputInterruptThread(HardwareContext *pHWContext)
{
DEBUGMSG(ZONE_INIT, (TEXT("CallInputInterruptThread")));
SetProcPermissions((ULONG)-1);
pHWContext->InputInterruptThread();
}
void CallOutputInterruptThread(HardwareContext *pHWContext)
{
DEBUGMSG(ZONE_INIT, (TEXT("CallOutputInterruptThread")));
SetProcPermissions((ULONG)-1);
pHWContext->OutputInterruptThread();
}
void HardwareContext::InputInterruptThread( )
{
ULONG InputTransferred;
DEBUGMSG(ZONE_INIT, (TEXT("InputInterruptThread")));
while (TRUE)
{
WaitForSingleObject(hInputIntEvent, INFINITE);
if (TRUE == m_audioDeinit)
{
return;
}
DEBUGMSG(ZONE_VERBOSE, (TEXT( "DCSR_ENDINTR on intput\r\n" )) );
Lock();
int buffer = GetLastInputBuffer();
InputTransferred = TransferInputBuffer(buffer);
if( InputTransferred==0 )
{
StopInputDMA();
}
Unlock();
}
}
void HardwareContext::OutputInterruptThread( )
{
DEBUGMSG(ZONE_INIT, (TEXT("OutputInterruptThread")));
while (TRUE)
{
WaitForSingleObject(hOutputIntEvent, INFINITE);
if (TRUE == m_audioDeinit)
{
return;
}
DEBUGMSG(ZONE_VERBOSE, (TEXT( "DCSR_ENDINTER on output\r\n" )) );
Lock();
int buffer = GetNextOutputBuffer();
ULONG Bytes = TransferOutputBuffer(buffer);
if(!m_OutputDMARunning)
{
if(Bytes)
{
// More data to play. Restart DMA engine by loading the descriptor
// address reg to initialize DMA, pointing to the buffer just loaded.
m_pDMARegisters->ddg[m_PlaybackChannel].ddadr =
(buffer == 0) ? (UINT32)m_vpAudioXmitA_Physical : (UINT32)m_vpAudioXmitB_Physical;;
// Set the RUN bit and also enable STOPINTR so that we know DMA is done
// on last buffer. A zero length buffer is considered the last buffer.
m_pDMARegisters->dcsr[m_PlaybackChannel] |= DCSR_RUN | DCSR_STOPIRQEN;
m_OutputDMARunning=TRUE;
}
else
{
// No more data to play. Will stop when the previous buffer
//StopOutputDMA();
}
}
Unlock();
}
}
#if !USE_I2S_INTERFACE
BOOL HardwareContext::TestAcLink()
{
BOOL RetVal=TRUE;
int i;
unsigned short int Value;
for (i=0;i<0x80;i+=2)
{
SafeReadCodec(i, &Value, DEV_AUDIO);
RETAILMSG(1, (TEXT( "register::value %x %x" ),i,Value ));
}
return (RetVal);
}
#endif
//------------------------------------------------------------------------------------------------------------
// Function: FillDescriptors
//
// Purpose: Fill the descriptors with appropriate data
//
// Note: This code could be cleaner, but I want to be explicit on the programming of descriptors
//
//-------------------------------------------------------------------------------------------------------------
BOOL HardwareContext::FillOutputDescriptors( void )
{
union DmaCmdReg CmdBuff;
memset (&CmdBuff,0, sizeof (CmdBuff));
// set individual bit fields to for debug.
#define USE_BITFIELD
#ifdef USE_BITFIELD
// set values with bit fields
CmdBuff.DcmdReg.len = AUDIO_BUFFER_SIZE; //length of memory buffer
CmdBuff.DcmdReg.width = 0x3; // binary 11 (see quick Quick Reference sheet to DMA programming in the cotulla EAS)
CmdBuff.DcmdReg.size = 0x3; // binary 11
CmdBuff.DcmdReg.endian = 0; // little endian
CmdBuff.DcmdReg.flybyt = 0; // Flowthrough
CmdBuff.DcmdReg.flybys = 0; // Flowthrough
CmdBuff.DcmdReg.endirqen = 1; // 1 means Interrupt when decrement length = 0;
CmdBuff.DcmdReg.startirqen = 0; // 1 means Interrupt when the desc is loaded
CmdBuff.DcmdReg.flowtrg = 1; // 1 means the target is an external peripheral
CmdBuff.DcmdReg.flowsrc = 0; // 1 means the source is an external peripheral (and needs flow con
CmdBuff.DcmdReg.inctrgadd = 0; // 1 means increment the target address (since it's memory)
CmdBuff.DcmdReg.incsrcadd = 1; // 1 means increment the source address (since it's a peripheral)
#else
// set value based on masks
CmdBuff.DcmdDword = DMAC_AC97_XMITAB_CMD_MASK | AUDIO_BUFFER_SIZE;
#endif
//
// fill XmitA Descriptor
//
m_vpAudioXmitA->ddadr= (UINT32)m_vpAudioXmitB_Physical ; // address of the next (XmitB) descriptor
#if USE_I2S_INTERFACE
m_vpAudioXmitA->dtadr= DMAC_IIS_AUDIO_XMIT_FIFO; // source address of the IIS XmitA buffer
#else
m_vpAudioXmitA->dtadr= DMAC_AC97_AUDIO_XMIT_FIFO; // source address of the AC97 XmitA buffer
#endif
m_vpAudioXmitA->dsadr= (UINT32)(m_Output_pbDMA_PAGES_Physical[0]); // destination address of the XmitA buffer
m_vpAudioXmitA->dcmd = CmdBuff.DcmdDword ; // size and cmd values of the XmitA buffer
//
// fill XmitB Descriptor
//
m_vpAudioXmitB->ddadr= (UINT32)m_vpAudioXmitA_Physical; // address of the next (XmitA) descriptor
#if USE_I2S_INTERFACE
m_vpAudioXmitB->dtadr= DMAC_IIS_AUDIO_XMIT_FIFO; // source address of the IIS XmitB buffer
#else
m_vpAudioXmitB->dtadr= DMAC_AC97_AUDIO_XMIT_FIFO; // source address of the AC97 XmitB buffer
#endif
m_vpAudioXmitB->dsadr= (UINT32)(m_Output_pbDMA_PAGES_Physical[1]) ; // destination address of the XmitB buffer
m_vpAudioXmitB->dcmd = CmdBuff.DcmdDword ; // size and cmd values of the XmitB buffer
return TRUE;
}
//------------------------------------------------------------------------------------------------------------
// Function: FillDescriptors
//
// Purpose: Fill the descriptors with appropriate data
//
// Note: This code could be cleaner, but I want to be explicit on the programming of descriptors
//
//-------------------------------------------------------------------------------------------------------------
BOOL HardwareContext::FillInputDescriptors( void )
{
union DmaCmdReg CmdBuff;
memset (&CmdBuff,0, sizeof (CmdBuff));
// set individual bit fields to for debug.
#define USE_BITFIELD
#ifdef USE_BITFIELD
// set values with bit fields
CmdBuff.DcmdReg.len = AUDIO_BUFFER_SIZE; //length of the memory buffer
CmdBuff.DcmdReg.width = 0x3; // binary 11 (see quick Quick Reference sheet to DMA programming in the cotulla EAS)
CmdBuff.DcmdReg.size = 0x3; // binary 11
CmdBuff.DcmdReg.endian = 0; // little endian
CmdBuff.DcmdReg.flybyt = 0; // Flowthrough
CmdBuff.DcmdReg.flybys = 0; // Flowthrough
CmdBuff.DcmdReg.endirqen = 1; // 1 means Interrupt when decrement length = 0;
CmdBuff.DcmdReg.startirqen = 0; // 1 means Interrupt when the desc is loaded
CmdBuff.DcmdReg.flowtrg = 0; // 1 means the target is an external peripheral
CmdBuff.DcmdReg.flowsrc = 1; // 1 means the source is an external peripheral (and needs flow control)
CmdBuff.DcmdReg.inctrgadd = 1; // 1 means increment the target address (since it's memory)
CmdBuff.DcmdReg.incsrcadd = 0; // 1 means increment the source address (since it's a peripheral)
#else
// set value based on masks
CmdBuff.DcmdDword = DMAC_AC97_RCVAB_CMD_MASK | AUDIO_BUFFER_SIZE;
#endif
//
// fill RcvA Descriptor
//
m_vpAudioRcvA-> ddadr= (UINT32)m_vpAudioRcvB_Physical; // address of the next (RcvB) descriptor
m_vpAudioRcvA-> dtadr= (UINT32)(m_Input_pbDMA_PAGES_Physical[0]); // source address of the AC97/IIS RcvA buffer
#if USE_I2S_INTERFACE
m_vpAudioRcvA-> dsadr= DMAC_IIS_AUDIO_RCV_FIFO; // destination address of the RcvA buffer
#else
m_vpAudioRcvA-> dsadr= DMAC_AC97_AUDIO_RCV_FIFO; // destination address of the RcvA buffer
#endif
m_vpAudioRcvA-> dcmd = CmdBuff.DcmdDword ; // size and cmd values of the RcvA buffer
//
// fill RcvB Descriptor
//
m_vpAudioRcvB-> ddadr= (UINT32)m_vpAudioRcvA_Physical ; // address of the next (RcvA) descriptor
m_vpAudioRcvB-> dtadr= (UINT32)(m_Input_pbDMA_PAGES_Physical[1]); // source address of the AC97/IIS RcvB buffer
#if USE_I2S_INTERFACE
m_vpAudioRcvB-> dsadr= DMAC_IIS_AUDIO_RCV_FIFO; // destination address of the RcvB buffer
#else
m_vpAudioRcvB-> dsadr= DMAC_AC97_AUDIO_RCV_FIFO; // destination address of the RcvB buffer
#endif
m_vpAudioRcvB-> dcmd = CmdBuff.DcmdDword ; // size and cmd values of the RcvB buffer
return TRUE;
}
//------------------------------------------------------------------------------------------------------------
// Function: StopDmac
//
// Purpose: To stop DMA transmit
//-------------------------------------------------------------------------------------------------------------
void HardwareContext::StopDmac(int Channel)
{
m_pDMARegisters->dcsr[Channel] &= ~DCSR_RUN; //clear the run but
return;
}
//------------------------------------------------------------------------------------------------------------
// Function: ClearDmac
//
// Purpose: To clear DMA status
//-------------------------------------------------------------------------------------------------------------
VOID HardwareContext::ClearDmac(int Channel)
{
DWORD dwDCSR;
dwDCSR = m_pDMARegisters->dcsr[Channel];
if(dwDCSR & DCSR_STOPINTR)
{
dwDCSR &= ~DCSR_STOPIRQEN;
}
// Clear the status
m_pDMARegisters->dcsr[Channel] = dwDCSR;
return;
}
//------------------------------------------------------------------------------------------------------------
// Function: AC97SetSampleRate
//
// Purpose: Write the sample rate value to the ac97 codec
//-------------------------------------------------------------------------------------------------------------
BOOL HardwareContext::SetSampleRate(unsigned short int SampleRate, WAPI_INOUT apidir )
{
short int RetVal=TRUE;
unsigned short int value = 0;
switch(SampleRate)
{
case 8000:
value = KHZ08_000;
break;
case 11025:
value = KHZ11_025;
break;
case 16000:
value = KHZ16_000;
break;
case 22050:
value = KHZ22_050;
break;
case 32000:
value = KHZ32_000;
break;
case 44100:
value = KHZ44_100;
break;
case 48000:
value = KHZ48_000;
break;
default:
DEBUGCHK(0); //we sent a bad rate
RetVal=FALSE;
return (RetVal);
}
#if USE_I2S_INTERFACE
if (apidir == WAPI_IN)
{
RetVal=SetI2sSampleRate(SampleRate); //set the input sample rate
}
else
{
RetVal=SetI2sSampleRate(SampleRate); //set the output sample rate
}
#else
if (apidir == WAPI_IN)
RetVal=SafeWriteCodec((XLLP_UINT16_T)AUDIO_ADC_RATE,value , DEV_AUDIO); //set the input sample rate
else
RetVal=SafeWriteCodec((XLLP_UINT16_T)AUDIO_DAC_RATE,value , DEV_AUDIO); //set the output sample rate
#endif
return (RetVal);
}
void HardwareContext::DumpDmacRegs()
{
#if 0
int i;
DEBUGMSG(ZONE_ERROR, (TEXT( "gsr %x, posr %x, pocr %x, pisr %x, picr %x\r\n" ),
m_pAc97regs->GSR,
m_pAc97regs->POSR,
m_pAc97regs->POCR,
m_pAc97regs->PISR,
m_pAc97regs->PICR
) );
for (i=0; i< 16; i++)
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->dcsr[%d] %x \r\n" ),i,m_pDMARegisters->dcsr[i] ) );
//skip rsvd section rsvd0[44];
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->dint %x \r\n" ),m_pDMARegisters->dint ) );
//skip rsvd seciton rsvd1[3];
for (i=0; i< 39; i++)
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->drcmr[%d] %x \r\n" ),i,m_pDMARegisters->drcmr[i] ) );
for (i=0; i<16; i++)
{
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->ddg[%d].ddadr %x \r\n" ),i,m_pDMARegisters->ddg[i].ddadr ) );
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->ddg[%d].dsadr %x \r\n" ),i,m_pDMARegisters->ddg[i].dsadr ) );
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->ddg[%d].dtadr %x \r\n" ),i,m_pDMARegisters->ddg[i].dtadr ) );
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->ddg[%d].dcmd %x \r\n" ),i,m_pDMARegisters->ddg[i].dcmd ) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -