⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 es1371.cpp

📁 此代码为WCE5.0下声卡的源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:

    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 + -