📄 es1371.cpp
字号:
case ES1371_ADC :
// read the Frame register
ulCurrentPos = HwPagedIORead( ES1371_ADCCTL_PAGE, ES1371_wADCFC_OFF);
// the current frame count is in the upper WORD
ulCurrentPos >>= 16;
// multiply the DWORD count by 4 to get a BYTE count to return
ulCurrentPos *= 4;
break;
}
return ulCurrentPos;
}
//--------------------------------------------------------------------------
//
// Name: SetDMAPosition
//
// Description: sets the current position of a DMA channel.
//
// Parameters: ULONG ulChannelIndex : Index of the DMA channel
// ULONG ulPosition: new DMA position in bytes
//
//
//--------------------------------------------------------------------------
void
CES1371::SetDMAPosition( ULONG ulChannelIndex, ULONG ulPosition )
{ ULONG ulCurrentPos;
ulPosition >>= 2; // convert from bytes to dwords
switch ( ulChannelIndex )
{
case ES1371_DAC0 :
// write the Frame register
ulCurrentPos = HwPagedIORead( ES1371_DAC0CTL_PAGE, ES1371_wDAC0FC_OFF);
HwPagedIOWrite( ES1371_DAC0CTL_PAGE, ES1371_wDAC0FC_OFF, (ulCurrentPos & 0x0000ffff) | (ulPosition << 16));
break;
case ES1371_DAC1 :
ulCurrentPos = HwPagedIORead( ES1371_DAC1CTL_PAGE, ES1371_wDAC1FC_OFF);
HwPagedIOWrite( ES1371_DAC1CTL_PAGE, ES1371_wDAC1FC_OFF, (ulCurrentPos & 0x0000ffff) | (ulPosition << 16));
break;
case ES1371_ADC :
ulCurrentPos = HwPagedIORead( ES1371_ADCCTL_PAGE, ES1371_wADCFC_OFF);
HwPagedIOWrite( ES1371_ADCCTL_PAGE, ES1371_wADCFC_OFF, (ulCurrentPos & 0x0000ffff) | (ulPosition << 16));
break;
}
}
//--------------------------------------------------------------------------
//
// Name: GetInterruptSource
//
// Description: returns the source of the current interrupt
//
// Parameters: none
//
// Returns: UCHAR LONG current DMA position in bytes
//
//--------------------------------------------------------------------------
UCHAR
CES1371::GetInterruptSource( void )
{
ULONG intstat;
UCHAR intsrc;
intstat = READ_PORT_ULONG( (PULONG)(m_pPciAddr + ES1371_dSTATUS_OFF) );
// If we get all f's back we can't see the hardware
if ( 0xffffffff == intstat )
return ES1371_INT_NONE;
if ( !( ES1371_INTSTAT_PENDING & intstat ))
return ES1371_INT_NONE;
intsrc = (UCHAR)(intstat) & ES1371_INT_MASK;
return intsrc;
}
//--------------------------------------------------------------------------
//
// Name: AckDMAInterrupt
//
// Description: clean up a (set of) interrupt(s)
//
// Parameters: UCHAR ucIntSrc : a bit mask interrupts to ack
//
// Returns: none
//
//--------------------------------------------------------------------------
void
CES1371::AckDMAInterrupt( UCHAR ucIntSrc )
{
UCHAR ackmask = 0;
if ( ES1371_INT_ADC & ucIntSrc )
ackmask |= ES1371_SERCTL_ADCIE ;
if ( ES1371_INT_DAC0 & ucIntSrc )
ackmask |= ES1371_SERCTL_DAC0IE ;
if ( ES1371_INT_DAC1 & ucIntSrc )
ackmask |= ES1371_SERCTL_DAC1IE ;
// now ack the interrupts - first set the IEs to 0
HwRegRMW( ES1371_bSERCTL_OFF, ackmask, 0x00);
// then set the IEs back to 1
HwRegRMW( ES1371_bSERCTL_OFF, ackmask, ackmask);
}
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
BOOL CES1371::MapDevice (CRegKey * pRegKey)
{
PHYSICAL_ADDRESS MappedAddress;
DDKWINDOWINFO wini;
DDKISRINFO isri;
DDKPCIINFO pcii;
DWORD dwStatus;
// read window information
wini.cbSize = sizeof(wini);
dwStatus = DDKReg_GetWindowInfo(pRegKey->Key(), &wini);
if(dwStatus != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR, (_T("Ensoniq: DDKReg_GetWindowInfo() failed %d\r\n"), dwStatus));
return FALSE;
}
m_dwBusNumber = wini.dwBusNumber;
m_dwInterfaceType = wini.dwInterfaceType;
// sanity check return values
if(wini.dwNumIoWindows != 1) {
DEBUGMSG(ZONE_ERROR, (_T("Ensoniq: invalid window parameters read from registry\r\n")));
return FALSE;
}
// read ISR information
isri.cbSize = sizeof(isri);
dwStatus = DDKReg_GetIsrInfo(pRegKey->Key(), &isri);
if(dwStatus != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR, (_T("Ensoniq: DDKReg_GetIsrInfo() failed %d\r\n"), dwStatus));
return FALSE;
}
// sanity check return values
if(isri.dwSysintr == SYSINTR_NOP) {
DEBUGMSG(ZONE_ERROR, (_T("Ensoniq: no sysintr specified in registry\r\n")));
return FALSE;
}
if(isri.szIsrDll[0] != 0) {
if(isri.szIsrHandler[0] == 0 || isri.dwIrq == IRQ_UNSPECIFIED) {
DEBUGMSG(ZONE_ERROR, (_T("Ensoniq: invalid installable ISR information in registry\r\n")));
return FALSE;
}
}
// read PCI id
pcii.cbSize = sizeof(pcii);
dwStatus = DDKReg_GetPciInfo(pRegKey->Key(), &pcii);
if(dwStatus != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR, (_T("Ensoniq: DDKReg_GetPciInfo() failed %d\r\n"), dwStatus));
return FALSE;
}
// sanity check return values
if((pcii.dwWhichIds & (PCIIDM_DEVICEID | PCIIDM_REVISIONID)) != (PCIIDM_DEVICEID | PCIIDM_REVISIONID)) {
DEBUGMSG(ZONE_ERROR, (_T("Ensoniq: insufficient device ID information in registry\r\n")));
return FALSE;
}
m_IntrAudio = isri.dwSysintr;
m_dwPciLength = wini.ioWindows[0].dwLen;
m_dwDeviceID = pcii.idVals[PCIID_DEVICEID];
m_dwRevisionID = pcii.idVals[PCIID_REVISIONID];
PHYSICAL_ADDRESS PortAddress = {wini.ioWindows[0].dwBase, 0};
// Install ISR handler if there is one
if (isri.szIsrDll[0] != 0) {
// Install ISR handler
m_hIsrHandler = LoadIntChainHandler(isri.szIsrDll, isri.szIsrHandler, (BYTE) isri.dwIrq);
if (m_hIsrHandler == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("Ensoniq: Couldn't install ISR handler\r\n")));
} else {
GIISR_INFO Info;
PVOID dwPhysAddr;
DWORD inIoSpace = 1; // io space
if (!TransBusAddrToStatic(PCIBus, 0, PortAddress, m_dwPciLength, &inIoSpace, &dwPhysAddr)) {
DEBUGMSG(ZONE_ERROR, (TEXT("Ensoniq: Failed TransBusAddrToStatic\r\n")));
return FALSE;
}
DEBUGMSG(ZONE_ERROR, (TEXT("Ensoniq: Installed ISR handler, Dll = '%s', Handler = '%s', Irq = %d, PhysAddr = 0x%x\r\n"),
isri.szIsrDll, isri.szIsrHandler, isri.dwIrq, dwPhysAddr));
// Set up ISR handler
Info.SysIntr = m_IntrAudio;
Info.CheckPort = TRUE;
Info.PortIsIO = TRUE;
Info.UseMaskReg = FALSE;
Info.PortAddr = (DWORD)dwPhysAddr + ES1371_dSTATUS_OFF;
Info.PortSize = sizeof(DWORD);
Info.Mask = ES1371_INTSTAT_PENDING;
if (!KernelLibIoControl(m_hIsrHandler, IOCTL_GIISR_INFO, &Info, sizeof(Info), NULL, 0, NULL)) {
DEBUGMSG(ZONE_ERROR, (TEXT("Ensoniq: KernelLibIoControl call failed.\r\n")));
return FALSE;
}
}
}
//
// Translate IO address
//
ULONG fInIoSpace = TRUE; // io space
if ( ! HalTranslateBusAddress( PCIBus, 0, PortAddress, &fInIoSpace, &MappedAddress)) {
DEBUGMSG(ZONE_ERROR, (TEXT("Ensoniq: HalTranslateBusAddress failed\r\n")));
return FALSE;
}
if ( fInIoSpace ) {
m_pPciAddr = (PUCHAR) MappedAddress.LowPart;
m_fIsMapped = FALSE;
}
else {
m_pPciAddr = (PUCHAR) MmMapIoSpace(MappedAddress, m_dwPciLength, FALSE);
m_fIsMapped = TRUE;
}
DEBUGMSG(ZONE_INFO, (TEXT("ENSONIQ1371: IO PORT [%X]\r\n"),m_pPciAddr));
//
// Configure Interupt
//
//
// Map IO and Interupt to System spaces
//
m_hISTInterruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (m_hISTInterruptEvent == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("ES1371 - unable to create IST event\r\n")));
return FALSE;
}
if (!InterruptInitialize(m_IntrAudio, m_hISTInterruptEvent, NULL, NULL) ) {
DEBUGMSG(ZONE_ERROR, (TEXT("ES1371 - InterruptInitialize(%d,%08x) Failed\r\n"), m_IntrAudio, m_hISTInterruptEvent));
return FALSE;
}
//
// We'll try and reserve physical memory since it is more likely to succeed
// on driver load
// If this fails, we'll try again at run-time
for (int i = 0; i < NUM_DMACHANNELS; i++) {
DMA_ADAPTER_OBJECT AdapterObject;
PHYSICAL_ADDRESS LogicalAddress;
AdapterObject.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
AdapterObject.InterfaceType = (INTERFACE_TYPE) m_dwInterfaceType;
AdapterObject.BusNumber = m_dwBusNumber;
if ((m_dmachannel[i].pvBufferVirtAddr = HalAllocateCommonBuffer(&AdapterObject, m_dmachannel[i].ulInitialSize, &LogicalAddress, FALSE)) != NULL)
{
m_dmachannel[i].ulBufferPhysAddr = LogicalAddress.LowPart;
m_dmachannel[i].ulAllocatedSize = m_dmachannel[i].ulInitialSize;
}
else
{
m_dmachannel[i].ulAllocatedSize = 0;
DEBUGMSG(ZONE_WARNING,(TEXT("ES1371: unable to reserve %d bytes for DMA channel %d\r\n"),
m_dmachannel[i].ulInitialSize, i ));
}
}
// record the Device ID and Revision ID for posterity.
//call our initialization functions
InitHardware();
//
// Turn on card
//
SetPowerState(1); // Turn off to set register arrays
SetPowerState(0);
DEBUGMSG(ZONE_INFO, (TEXT("ES1371: PCI Init Done\r\n")));
return TRUE;
}
//--------------------------------------------------------------------------
//
// Name: CES1371::AudioInitialize
//
// Description: maps hardware and sets up the Interrupt Service Thread
//
// Parameters: none
//
// Returns: BOOL
// TRUE if device was mapped properly and IST was set up correctly
// FALSE if either of the above fails
//
// Note:
//
//--------------------------------------------------------------------------
BOOL CES1371::AudioInitialize(CRegKey * pRegKey)
{
DEBUGMSG(ZONE_ENTER, (TEXT("CES1371::AudioInitialize \r\n")));
BOOL bRetVal = 0;
ULONG nRetVal = 0;
// Set up the IST
DWORD dwThreadId=0;
m_hISThread = CreateThread(NULL, 0, IST_Startup, this, 0, &dwThreadId);
if(m_hISThread == NULL)
{
DEBUGMSG(ZONE_ERROR,(TEXT("DsDriver::Open -- unable to create IST\r\n")));
return FALSE;
}
DWORD dwPriority = 210;
pRegKey->QueryDword (TEXT("Priority256"), dwPriority);
CeSetThreadPriority(m_hISThread, dwPriority);
return TRUE;
}
//--------------------------------------------------------------------------
//
//--------------------------------------------------------------------------
DWORD WINAPI CES1371::IST_Startup(LPVOID lpParameter)
{
((CES1371 *)lpParameter)->IST();
return 0;
}
//--------------------------------------------------------------------------
//
// Name: CES1371::IST
//
// Description: The Interrupt service thread,
//
// Parameters: none
//
// Returns: VOID
//
// Note:
//
//--------------------------------------------------------------------------
VOID CES1371::IST()
{
DWORD dwRet=0;
BOOL bKeepLooping = TRUE;
//Initialize
// loop here waiting for an Interrupt to occur
while(bKeepLooping)
{
#ifdef MIPS
// certain MIPS platforms have problems with back-to-back interrupts (e.g. full-duplex capture/playback)
// check if another interrupt is pending on the device & skip the wait.
UCHAR intsrc2 = GetInterruptSource();
if(!(intsrc2 & (ES1371_INT_ADC | ES1371_INT_DAC0 | ES1371_INT_DAC1 | ES1371_INT_PM)) ) {
dwRet = WaitForSingleObject(m_hISTInterruptEvent, INFINITE);
}
else {
dwRet = WAIT_OBJECT_0;
}
#else
dwRet = WaitForSingleObject(m_hISTInterruptEvent, INFINITE);
#endif
if(m_bExitIST == TRUE)
break;
switch(dwRet)
{
case WAIT_OBJECT_0:
//
// Do processing
//
// Route Interrupt to the appropriate object
{
// Grab the interrupt source, acknowledge on our device, the re-enable the interrupt.
UCHAR intsrc = GetInterruptSource();
AckDMAInterrupt(intsrc);
InterruptDone(m_IntrAudio);
DEBUGMSG(ZONE_INTERRUPT, (TEXT("IST: %x\r\n"), intsrc));
// the interrupt handlers might need their proc permissions
// jacked up. rather than doing this on a per handler basis,
// we just do it once for all of them
DWORD dwSavedPermissions = GetCurrentPermissions();
SetProcPermissions((ULONG) -1);
for (int i = 0; i < NUM_DMACHANNELS; i++) {
if (intsrc & m_dmachannel[i].ucIntMask) {
if (m_dmachannel[i].pfIntHandler != NULL) {
(*m_dmachannel[i].pfIntHandler) (m_dmachannel[i].pvIntContext);
}
else {
DEBUGMSG(ZONE_ERROR, (TEXT("DMA Channel %d - bogus interrupt\r\n"), i));
}
}
}
SetProcPermissions(dwSavedPermissions);
}
break;
case WAIT_ABANDONED:
DEBUGMSG(ZONE_ERROR, (TEXT("CES1371 IST: WAIT_ABANDONED.. \r\n")));
break;
case WAIT_TIMEOUT:
DEBUGMSG(ZONE_ERROR, (TEXT("CES1371 IST: WAIT_TIMEOUT.. \r\n")));
break;
case WAIT_FAILED:
DEBUGMSG(ZONE_ERROR, (TEXT("CES1371 IST: WAIT_FAILED.. \r\n")));
break;
default:
// bKeepLooping = FALSE;
break;
}
}
DEBUGMSG(ZONE_INFO, (TEXT("CES1371 IST: Exiting.. \r\n")));
InterruptDone(m_IntrAudio);
InterruptDisable (m_IntrAudio);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -