📄 cx5530audio.cpp
字号:
m_bExiting = true; // tell interrupt thread to get out of Dodge before sunset...
SetEvent(m_hInterruptEvent);
WaitForSingleObject(m_hInterruptThread, 1000); // wait for sunset...
m_hInterruptThread = NULL;
m_bExiting = false;
}
if (m_hInterruptEvent)
{
CloseHandle(m_hInterruptEvent);
m_hInterruptEvent = NULL;
}
if (m_pCodec)
{
delete m_pCodec;
m_pCodec = NULL;
}
}
bool CCX5530Audio::IsFormatSupported(LPWAVEFORMATEX lpWaveFormat)
{
if (!lpWaveFormat)
return false;
if (lpWaveFormat->nChannels != 2)
return false;
if (lpWaveFormat->wBitsPerSample != 16)
return false;
return true;
}
#ifdef MYDEBUG
void CCX5530Audio::Test(bool bDoInt)
{
FUNCMSG("+CCX5530Audio::Test()");
// fill in the buffers with about 500 Hz sound at 44100 samples/s
int i;
static CMemoryBuffer buf;
if (!buf.ReservePhysicalMem(8192))
{
ERRMSG("Can't reserve buf!");
return;
}
WORD *pBuf = (WORD *)buf.GetVirtualAddress();
WORD *pMax = (WORD*)(((BYTE*)pBuf) + buf.GetSize());
for (i = 0; pBuf < pMax; i++)
{
*pBuf++ = ( i < 40)?-200:200; // left channel
*pBuf++ = ( i < 40)?-200:200; // right channel
if (i > 80)
i = 0;
}
//--- Reload the descriptors....
// set no EOPs: just let the thing loop
// Descriptor: Logical address (DMA input buffer - unused).
PSGD_FORMAT pSGD = (PSGD_FORMAT)( m_PlaybackChannels[0]->GetVirtualAddress());
int iChunk1 = 4096;
int iChunk2 = buf.GetSize() - iChunk1;
pSGD[0].PhysicalAddr = buf.GetPhysicalAddress();
pSGD[0].CountAndFlag = iChunk1; // len (bytes)
pSGD[1].PhysicalAddr = pSGD[0].PhysicalAddr + iChunk1;
pSGD[1].CountAndFlag = iChunk2; // len (bytes)
pSGD[2].PhysicalAddr = m_PlaybackChannels[0]->GetPhysicalAddress();
pSGD[2].CountAndFlag = SGD_JMP; // JMP
if (bDoInt)
{
pSGD[0].CountAndFlag |= SGD_EOP;
pSGD[1].CountAndFlag |= SGD_EOP;
}
UCHAR status;
m_pCodec->SetSampleRate(false, 44100);
INFMSG("Test: SGD table is:");
PSGD_FORMAT pSGD1 = pSGD;
while(true)
{
INFMSG3("\tAddr: 0x%8.8x, size %d, %s",
pSGD1->PhysicalAddr,
pSGD1->CountAndFlag & ~(SGD_EOP | SGD_EOT |SGD_JMP),
(pSGD1->CountAndFlag & SGD_EOP)?TEXT("SGD_EOP"):
(pSGD1->CountAndFlag & SGD_JMP)?TEXT("SGD_JMP"):
(pSGD1->CountAndFlag & SGD_EOT)?TEXT("SGD_EOT"):TEXT("no flag"));
if (pSGD1->CountAndFlag & (SGD_EOT | SGD_JMP))
break;
pSGD1++;
}
status = m_pAudioRegisters->regBusMaster0Status; // clear EOP
m_pAudioRegisters->regBusMaster0PRD = m_PlaybackChannels[0]->GetSGDTable()->GetPhysicalAddress();
m_pAudioRegisters->regBusMaster0Command.byValue = 0x01;
DEBUGMSG(1, (TEXT("DMA started, sleep\r\n")));
for (i = 0; i < 20; i ++)
{
Sleep (100);
GetDMAPosition(0);
}
pSGD[1].CountAndFlag = (pSGD[1].CountAndFlag & ~SGD_EOP)| SGD_EOT;
Sleep(1000);
FUNCMSG("-CCX5530Audio::Test()");
return;
}
#endif
bool CCX5530Audio::GetRegistryConfig()
{
HKEY hKeyActive = HKEY(INVALID_HANDLE_VALUE);
DWORD dwSize;
DWORD dwType;
DWORD dwRet;
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// The HLM\Drivers\Active\?? key was passed in from DEVICE.EXE. The "Key"
// subkey points to the original registry location where we can find our
// extra data about this device.
//
dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_PATH, 0, 0, &hKeyActive);
if (dwRet != ERROR_SUCCESS)
{
ERRMSG2("GetRegistryConfig RegOpenKeyEx(%s) failed %d",REGISTRY_PATH, dwRet);
return false;
}
dwSize = sizeof(m_dwInterrupt);
dwRet = RegQueryValueEx(hKeyActive, REGISTRY_KEY_IRQ, 0, &dwType, (BYTE*)&m_dwInterrupt, &dwSize);
RegCloseKey(hKeyActive);
if (dwRet != ERROR_SUCCESS)
{
ERRMSG1("GetRegistryConfig RegQueryValueEx(Key) failed: %d", dwRet);
}
return dwRet == ERROR_SUCCESS;
}
void CCX5530Audio::InitVSA()
{
// VSA initialization
// VSA 2 first
BYTE byInt = BYTE(m_dwInterrupt);
_outpw( 0xAC1C, 0xFC53 ); //unlock virtual registers
_outpw( 0xAC1C, 0x108 ); //ID the audio config virtual regs
_outpw( 0xAC1E, WORD(m_dwInterrupt)); //set the value
// VSA1 Irq config method : not thread safe ! Replaced with call to HalSetBusDataByOffset below
_asm
{
mov bl, byInt ; because byInt is loaded based on bp, and we clear bp below
push bp
mov bp, 0h
mov dx, 0CF8h ; PCI cmd register
mov eax,800090D0h ; device and other pci stuff
out dx, eax
mov dx, 0CFCh ; PCI data register
xor ax, ax
mov al, bl ; target IRQ
shl eax,16 ; store in upper part of reg for VSA
mov ax, 0A00Ah ; load VSA1 cmd
out dx, ax
pop bp
}
/*
// and now VSA 1 (multithread safe)
bridgeSlot.u.bits.FunctionNumber = 0;
DWORD dwBuffer = (m_dwInterrupt<<16) | 0xA00A;
HalSetBusDataByOffset(
PCIConfiguration,
bus,
bridgeSlot.u.AsULONG,
&dwBuffer,
0xD0,
sizeof(dwBuffer));
*/
}
HRESULT CCX5530Audio::CreatePlaybackBuffer(ULONG *pulSize, DsPlaybackDriverBuffer** pBuffer)
{
FUNCMSG1("CCX5530Audio::CreatePlaybackBuffer, size %d", *pulSize);
HRESULT hr = DSERR_GENERIC;
if (!pBuffer)
return hr;
// any hardware DMA channels free?
for (UINT i = 0; i < MAX_PLAYBACK_CHANNELS; i++)
{
if (m_PlaybackChannels[i] == NULL)
break;
}
if (i >= MAX_PLAYBACK_CHANNELS)
{
WARNMSG("No more free busmasters");
return DSERR_ALLOCATED;
}
// map the channel to a DMA busmaster
// with the current hardware it's simple: there is a single playback channel, and we use busmaster 0
volatile BusMasterRegisters* pRegs;
switch (i)
{
case 0:
pRegs = &m_pAudioRegisters->busMasters[0];
break;
default:
ASSERT(FALSE);
return DSERR_GENERIC;
}
m_PlaybackChannels[i] = new DsPlaybackDriverBuffer(hr, i, pRegs );
if( !m_PlaybackChannels[i] || FAILED(hr) )
{
ERRMSG("CCX5530Audio::CreatePlaybackBuffer -- unable to create buffer object");
if( m_PlaybackChannels[i] )
{
delete m_PlaybackChannels[i];
m_PlaybackChannels[i] = NULL;
}
if( SUCCEEDED(hr))
{
// Change the error code to reflect the failure.
hr = DSERR_OUTOFMEMORY;
}
return hr;
}
// Allocate buffer
if( ! m_PlaybackChannels[i]->ReservePhysicalMem(*pulSize) )
{
ERRMSG("CCX5530Audio::CreatePlaybackBuffer -- unable to allocate memory for buffers ");
delete m_PlaybackChannels[i];
m_PlaybackChannels[i] = NULL;
*pulSize = 0;
return DSERR_OUTOFMEMORY;
}
*pBuffer = m_PlaybackChannels[i];
return hr;
}
HRESULT CCX5530Audio::CreateCaptureBuffer(ULONG *pulSize, DsCaptureDriverBuffer** pBuffer)
{
HRESULT hr = DSERR_GENERIC;
if (!pBuffer)
return hr;
// any hardware DMA channels free?
for (UINT i = 0; i < MAX_CAPTURE_CHANNELS; i++)
{
if (m_CaptureChannels[i] == NULL)
break;
}
if (i >= MAX_CAPTURE_CHANNELS)
{
WARNMSG("No free capture busmasters");
return DSERR_ALLOCATED;
}
// map the capture channel to a DMA busmaster
// with the current hardware it's simple: there is a single record channel, and we use busmaster 1
volatile BusMasterRegisters* pRegs;
switch (i)
{
case 0:
pRegs = &m_pAudioRegisters->busMasters[1];
break;
default:
ASSERT(FALSE);
return DSERR_GENERIC;
}
m_CaptureChannels[i] = new DsCaptureDriverBuffer(hr, i, pRegs);
if( !m_CaptureChannels[i] || FAILED(hr) )
{
ERRMSG("CCX5530Audio::CreateCaptureBuffer -- unable to create secondary buffer object");
if( m_CaptureChannels[i] )
{
delete m_CaptureChannels[i];
m_CaptureChannels[i] = NULL;
}
if( SUCCEEDED(hr))
{
// Change the error code to reflect the failure.
hr = DSERR_OUTOFMEMORY;
}
return hr;
}
// Allocate buffer
if( ! m_CaptureChannels[i]->ReservePhysicalMem(*pulSize) )
{
ERRMSG("CCX5530Audio::CreateCaptureBuffer -- unable to allocate memory for buffers ");
delete m_CaptureChannels[i];
m_CaptureChannels[i] = NULL;
*pulSize = 0;
return DSERR_OUTOFMEMORY;
}
*pBuffer = m_CaptureChannels[i];
return hr;
}
HRESULT CCX5530Audio::SetFrequency(bool bCapture, DWORD dwFrequency)
{
if (!m_pCodec)
return DSERR_CONTROLUNAVAIL;
if (!m_pCodec->SetSampleRate(bCapture, dwFrequency))
return DSERR_CONTROLUNAVAIL;
return DS_OK;
}
#ifdef DEBUG
void CCX5530Audio::DumpRegisters()
{
RETMSG1("regCodecGPIOStatus is 0x%8.8x", m_pAudioRegisters->regCodecGPIOStatus.dwValue);
// offset 0x04;
RETMSG1("regCodecGPIOControl is 0x%8.8x", m_pAudioRegisters->regCodecGPIOControl.dwValue);
// offset 0x08;
RETMSG1("regCodecStatus is 0x%8.8x", m_pAudioRegisters->regCodecStatus.dwValue);
// offset 0x0C
RETMSG1("regCodecCommand is 0x%8.8x", m_pAudioRegisters->regCodecCommand.dwValue);
//offset 0x10 This is a WORD register
RETMSG1("regSMIMirror is 0x%4.4x", m_pAudioRegisters->regSMIMirror);
//offset 0x12 This is a WORD register
RETMSG1("regSMI is 0x%4.4x", m_pAudioRegisters->regSMI);
// offset 0x14
RETMSG1("regIOTrap is 0x%8.8x", m_pAudioRegisters->regIOTrap);
// offset 0x18 Word register
RETMSG1("regIOTrapEnable is 0x%4.4x", m_pAudioRegisters->regIOTrapEnable);
// offset 0x1A Word register
RETMSG1("regIRQEnable is 0x%4.4x", m_pAudioRegisters->regIRQEnable);
// offset 0x1C Word register
RETMSG1("regIRQControl is 0x%4.4x", m_pAudioRegisters->regIRQControl);
// offset 0x1E Word register
RETMSG1("regIRQMask is 0x%4.4x", m_pAudioRegisters->regIRQMask);
// offset 0x20 BYTE register
RETMSG1("busMasters is 0x%2.2x", m_pAudioRegisters->busMasters[0].regBusMasterStatus);
RETMSG1("busMasters is 0x%2.2x", m_pAudioRegisters->busMasters[1].regBusMasterStatus);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -