📄 hwctxt.cpp
字号:
{
AUDIO_STATE result = AUDIO_STATE_IGNORE;
ULONG InputTransferred;
//RETAILMSG(ZONE_ERROR, (TEXT( "GetInterruptType\r\n" )) );
//
// I N P U T
//
//did we get an input error?
if (m_pDMARegisters->dcsr[DMA_CH_RCV] & DCSR_BUSERRINTR)
{
RETAILMSG(ZONE_ERROR, (TEXT( "DCSR_BUSERRINTR ERROR on input\r\n" )) );
//m_vpBLReg->hex_led = 0x97AC0001;
DEBUGCHK(0); // an unplanned dma interrupt occured
DumpDmacRegs();
m_pDMARegisters->dcsr[DMA_CH_RCV] |= (DCSR_RUN | DCSR_BUSERRINTR); // clear this interrupt
}
//did we get an input end interrupt?
if (m_pDMARegisters->dcsr[DMA_CH_RCV] & DCSR_ENDINTR) //if the input channel stopped at the end of a buffer xfer
{
RETAILMSG(ZONE_ERROR, (TEXT( "DCSR_ENDINTR on intput\r\n" )) );
m_pDMARegisters->dcsr[DMA_CH_RCV] |= DCSR_ENDINTR; //acknowlege the interrupt
InputTransferred = TransferInputBuffers( (DWORD) v_nNextPage[WAPI_IN] );
v_nNextPage[WAPI_IN] = (!v_nNextPage[WAPI_IN] ? 1 : 0);
if( InputTransferred==0 )
{
StopInputDMA();
}
//m_vpBLReg->hex_led = 0x97AC0002;
}
//did we get an input start interrupt?
if (m_pDMARegisters->dcsr[DMA_CH_RCV] & DCSR_STARTINTR)
{
RETAILMSG(ZONE_VERBOSE, (TEXT( "DCSR_STARTINTER on input\r\n" )) );
m_pDMARegisters->dcsr[DMA_CH_RCV] |= DCSR_STARTINTR; // reset the interrupt
//m_vpBLReg->hex_led = 0x97AC0003;
DEBUGCHK(0); // an unplanned dma interrupt occured
}
//
// O U T P U T
//
//did we get an output error?
if (m_pDMARegisters->dcsr[DMA_CH_OUT] & DCSR_BUSERRINTR)
{
static DWORD numints=0x97AC0000;
static int shift=0;
RETAILMSG(ZONE_ERROR, (TEXT( "DCSR_BUSERRINTR ERROR on output\r\n" )) );
//m_vpBLReg->hex_led = (numints >> shift);
shift--;
if (shift>15) shift=0;
DumpDmacRegs();
m_pDMARegisters->dcsr[DMA_CH_OUT] |= (DCSR_RUN | DCSR_BUSERRINTR); // clear this interrupt
//note if we get here, we have a lot more to do than clear the interrupt.
//DEBUGCHK(0); // an unplanned dma interrupt occured
}
//did we get an output interrupt?
if (m_pDMARegisters->dcsr[DMA_CH_OUT] & DCSR_ENDINTR) //if the out channel stopped at the end of a buffer xfer
{
//RETAILMSG(ZONE_ERROR, (TEXT( "DCSR_ENDINTER on output\r\n" )) );
m_pDMARegisters->dcsr[DMA_CH_OUT] |= DCSR_ENDINTR;
TransferOutputBuffers( (DWORD)v_nNextPage[WAPI_OUT] );
v_nNextPage[WAPI_OUT] = (!v_nNextPage[WAPI_OUT] ? 1 : 0);
if( m_OutBytes[0] + m_OutBytes[1]==0 )
{
StopOutputDMA();
}
//m_vpBLReg->hex_led = 0x97AC0005;
}
if (m_pDMARegisters->dcsr[DMA_CH_OUT] & DCSR_STARTINTR)
{
RETAILMSG(ZONE_ERROR, (TEXT( "DCSR_STARTINTR on output\r\n" )) );
m_pDMARegisters->dcsr[DMA_CH_OUT] |= DCSR_STARTINTR; // reset the interrupt
DEBUGCHK(0); // an unplanned dma interrupt occured
//m_vpBLReg->hex_led = 0x97AC0006;
}
///RETAILMSG(ZONE_VERBOSE, (TEXT( "-PDD_AudioGetInterruptType\r\n" )) );
//m_vpBLReg->hex_led = 0x97AC0007;
return result;
}
*/
/*
void HardwareContext::InterruptThread()
{
// Need to be able to access everyone else's address space during interrupt handler.
SetProcPermissions((ULONG)-1);
while (TRUE)
{
WaitForSingleObject(m_hAudioInterrupt, INFINITE);
// Grab the lock
Lock();
GetInterruptType();
Unlock();
InterruptDone(m_IntrAudio);
} // while(TRUE)
} */
void CallInputInterruptThread(HardwareContext *pHWContext)
{
FUNC_WPDD("CallInterruptThread");
SetProcPermissions((ULONG)-1);
pHWContext->InputInterruptThread();
}
void CallOutputInterruptThread(HardwareContext *pHWContext)
{
FUNC_WPDD("CallInterruptThread");
SetProcPermissions((ULONG)-1);
pHWContext->OutputInterruptThread();
}
void HardwareContext::InputInterruptThread( )
{
ULONG InputTransferred;
FUNC_WPDD("CallInterruptThread");
while (TRUE)
{
WaitForSingleObject(hInputIntEvent, INFINITE);
Lock();
RETAILMSG(ZONE_ERROR, (TEXT( "DCSR_ENDINTR on intput\r\n" )) );
InputTransferred = TransferInputBuffers( (DWORD) v_nNextPage[WAPI_IN] );
v_nNextPage[WAPI_IN] = (!v_nNextPage[WAPI_IN] ? 1 : 0);
if( InputTransferred==0 )
{
StopInputDMA();
}
Unlock();
}
}
void HardwareContext::OutputInterruptThread( )
{
FUNC_WPDD("CallInterruptThread");
while (TRUE)
{
WaitForSingleObject(hOutputIntEvent, INFINITE);
//RETAILMSG(ZONE_ERROR, (TEXT( "DCSR_ENDINTER on output\r\n" )) );
Lock();
TransferOutputBuffers( (DWORD)v_nNextPage[WAPI_OUT] );
v_nNextPage[WAPI_OUT] = (!v_nNextPage[WAPI_OUT] ? 1 : 0);
if( m_OutBytes[0] + m_OutBytes[1]==0 )
{
StopOutputDMA();
}
//m_vpBLReg->hex_led = 0x97AC0005;
Unlock();
}
}
/*
void CallInterruptThread(HardwareContext *pHWContext)
{
FUNC_WPDD("CallInterruptThread");
pHWContext->InterruptThread();
}
*/
BOOL HardwareContext::TestAcLink()
{
BOOL RetVal=TRUE;
int i;
unsigned short int Value;
/*
if (ReadAC97(MASTER_VOLUME, &Value, DEV_AUDIO)!=SUCCESS)
{
m_vpBLReg->hex_led = 0xBADD001;
while (1);
RetVal=FALSE;
}
if (SafeWriteAC97(MASTER_VOLUME, 0x0e0e, DEV_AUDIO)!=SUCCESS)
{
m_vpBLReg->hex_led = 0xBADD002;
while (1);
RetVal=FALSE;
}
if (ReadAC97(MASTER_VOLUME, &Value, DEV_AUDIO)!=SUCCESS)
{
m_vpBLReg->hex_led = 0xBADD003;
while (1);
RetVal=FALSE;
}
m_vpBLReg->hex_led = (unsigned short int) Value;
*/
for (i=0;i<0x80;i+=2)
{
ReadAC97(i, &Value, DEV_AUDIO);
RETAILMSG(ERROR, (TEXT( "register::value %x %x" ),i,Value) );
}
return (RetVal);
}
//------------------------------------------------------------------------------------------------------------
// 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 = g_dma_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= DMA_XMIT_B_DESCRIPTOR_BASE_PHYSICAL ; // address of the next (XmitB) descriptor
m_vpAudioXmitA->dtadr= DMAC_AC97_AUDIO_XMIT_FIFO; // source address of the AC97 XmitA buffer
m_vpAudioXmitA->dsadr= DMA_XMIT_A_BUFFER_BASE_PHYSICAL; // 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= DMA_XMIT_A_DESCRIPTOR_BASE_PHYSICAL; // address of the next (XmitA) descriptor
m_vpAudioXmitB->dtadr= DMAC_AC97_AUDIO_XMIT_FIFO; // source address of the AC97 XmitB buffer
m_vpAudioXmitB->dsadr= DMA_XMIT_B_BUFFER_BASE_PHYSICAL ; // 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 = g_dma_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= DMA_RCV_B_DESCRIPTOR_BASE_PHYSICAL; // address of the next (RcvB) descriptor
m_vpAudioRcvA-> dtadr= DMA_RCV_A_BUFFER_BASE_PHYSICAL; // source address of the AC97 RcvA buffer
m_vpAudioRcvA-> dsadr= DMAC_AC97_AUDIO_RCV_FIFO; // destination address of the RcvA buffer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -