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

📄 es1371.cpp

📁 此代码为WCE5.0下声卡的源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//
// Copyright 1998-2000 (c) Creative Labs, Malvern.  All rights reserved.
// Portions copyright 1999-2000 (c) Microsoft Corporation.  All rights reserved.
//

#include "wavdrv.h"
#include <nkintr.h>
#include <ceddk.h>
#include <cardserv.h>
#include <devload.h>
#include <giisr.h>
#include <ddkreg.h>

#define DEVLOAD_DEVICEID_VALNAME TEXT("DeviceID")
#define DEVLOAD_REVISIONID_VALNAME TEXT("RevisionID")

// {{{ constructor/destructor

CES1371::CES1371 (void)
{ int i;

	InitializeCriticalSection( &m_csPageLock );

	//initialize our member variables
    for (i = 0; i < NUM_DMACHANNELS; i++) {
       	m_dmachannel[i].ulDMAChannelState = DMA_STOPPED;
        m_dmachannel[i].fAllocated = FALSE;
    }
   	m_dmachannel[ES1371_ADC ].ulDirection = DMADIR_IN;
   	m_dmachannel[ES1371_DAC0].ulDirection = DMADIR_OUT;
   	m_dmachannel[ES1371_DAC1].ulDirection = DMADIR_OUT;

   	m_dmachannel[ES1371_ADC].ulInitialSize = PRE_ALLOC_BUFFER_SIZE_ADC;
   	m_dmachannel[ES1371_DAC0].ulInitialSize = PRE_ALLOC_BUFFER_SIZE_DAC0;
   	m_dmachannel[ES1371_DAC1].ulInitialSize = PRE_ALLOC_BUFFER_SIZE_DAC1;

   	m_dmachannel[ES1371_ADC].ucIntMask = ES1371_INT_ADC;
   	m_dmachannel[ES1371_DAC0].ucIntMask = ES1371_INT_DAC0;
   	m_dmachannel[ES1371_DAC1].ucIntMask = ES1371_INT_DAC1;

	m_hISTInterruptEvent = NULL;

	m_hISThread = NULL;
	m_bExitIST = FALSE;

	m_fIsMapped = FALSE;

    m_ulPowerState = 0;		// record the internal state of the device as "powered up"
}

CES1371::~CES1371 ()
{
    //invalidate our member variables

	// Close the IST
	m_bExitIST = true;
	SetEvent(m_hISTInterruptEvent);
	if( WAIT_OBJECT_0 != WaitForSingleObject(m_hISThread, 10000) )
		DEBUGMSG(ZONE_ERROR,(TEXT("~CES1371-- Error closing IST \r\n")));

	CloseHandle(m_hISTInterruptEvent);
    CloseHandle(m_hISThread);
	DeleteCriticalSection( &m_csPageLock );

	if (m_fIsMapped) {
		MmUnmapIoSpace(m_pPciAddr, m_dwPciLength);
		m_fIsMapped = FALSE;
	}
    if (m_hIsrHandler != NULL) {
        FreeIntChainHandler(m_hIsrHandler);
    }
}

void
CES1371::GetDMABuffer (ULONG ulChannelIndex, PULONG pulBufferSize, PVOID * pvVirtAddr)
{
    if (ulChannelIndex < NUM_DMACHANNELS) {
        *pulBufferSize = m_dmachannel[ulChannelIndex].ulBufferSize;
        *pvVirtAddr = m_dmachannel[ulChannelIndex].pvBufferVirtAddr;
    }
}

ULONG
CES1371::GetNumFreeDMAChannels(ULONG ulDirection)
{ ULONG count = 0;
  int index;

    for (index = 0; index < NUM_DMACHANNELS; index++) {
        if ((m_dmachannel[index].ulDirection & ulDirection) && ! m_dmachannel[index].fAllocated) {
			count ++;
        }
    }
	return count;
}

MMRESULT
CES1371::AllocDMAChannel (ULONG ulDirection, ULONG ulSize, PULONG pulChannelIndex)
{ ULONG index;
    

    if (ulSize > 64 * 1024) {
        // ES1371 only handles up to 64Kbyte DMA buffers
        return MMSYSERR_NOMEM;
    }

    // make two passes through the DMA channel table:
    // in pass 1, we try to use pre-allocated memory first.
    // only in pass 2 do we allocate new memory
    for (index = 0; index < NUM_DMACHANNELS; index++) {
        if ((m_dmachannel[index].ulDirection & ulDirection) && ! m_dmachannel[index].fAllocated) {
            // we found an open slot. see if we can get enough memory
            if (m_dmachannel[index].ulAllocatedSize >= ulSize) {
                // currently allocated memory is sufficient. We're done.
                m_dmachannel[index].fAllocated = TRUE;
                m_dmachannel[index].ulBufferSize = ulSize; // record what we're actually using
                *pulChannelIndex = index;
                return MMSYSERR_NOERROR;
            }
        }
    }
    // pass 2: find a free slot and allocate memory
    for (index = 0; index < NUM_DMACHANNELS; index++) {
        if ((m_dmachannel[index].ulDirection & ulDirection) && ! m_dmachannel[index].fAllocated) {
            // pass 2: try to allocate memory for the request
            // make new allocation first, only if it succeeds do we release existing memory
            ULONG ulPhysAddr;
            PVOID pVirtAddr;
            PHYSICAL_ADDRESS LogicalAddress;
            DMA_ADAPTER_OBJECT AdapterObject;

            AdapterObject.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
            AdapterObject.InterfaceType = (INTERFACE_TYPE) m_dwInterfaceType;
            AdapterObject.BusNumber = m_dwBusNumber;

            if ((pVirtAddr = HalAllocateCommonBuffer(&AdapterObject, ulSize, &LogicalAddress, FALSE)) == NULL)
            {
        		DEBUGMSG(ZONE_ERROR,(TEXT("AllocDMAChannel - unable to allocate %d bytes of physical memory\r\n"), ulSize));
                // if this fails, there's not much point in trying it over and over
                return MMSYSERR_NOMEM;
            }

            ulPhysAddr = LogicalAddress.LowPart;

            if (m_dmachannel[index].ulBufferSize > 0) {
                // free the previous allocation
                LogicalAddress.QuadPart = 0;
                HalFreeCommonBuffer(NULL, 0, LogicalAddress, m_dmachannel[index].pvBufferVirtAddr, FALSE);
            }
            m_dmachannel[index].ulAllocatedSize = ulSize;
            m_dmachannel[index].ulBufferSize = ulSize;
		    m_dmachannel[index].ulBufferPhysAddr = ulPhysAddr;
		    m_dmachannel[index].pvBufferVirtAddr = pVirtAddr;
            m_dmachannel[index].fAllocated = TRUE;
            *pulChannelIndex = index;
            return MMSYSERR_NOERROR;
        }
    }

    DEBUGMSG(ZONE_INFO, (TEXT("AllocDMAChannel - no free channels\r\n")));

    return MMSYSERR_ALLOCATED;
}

BOOL 
CES1371::FreeDMAChannel (ULONG ulChannelIndex)
{
    ASSERT(ulChannelIndex < NUM_DMACHANNELS);
    ASSERT(m_dmachannel[ulChannelIndex].fAllocated);

    m_dmachannel[ulChannelIndex].fAllocated = FALSE;
    m_dmachannel[ulChannelIndex].pfIntHandler = NULL;
    m_dmachannel[ulChannelIndex].pvIntContext = NULL;

    // note that we DO NOT relinquish physical memory, since contigous physical memory is
    // harder to come by as the system runs. We'd run the risk of not getting the memory
    // back next time we need it.

    return TRUE;
}



// }}}

// {{{ Init

//--------------------------------------------------------------------------
//
//  Name: CES1371::InitHardware
//
//  Description: intitializes the 1371 hardware
//
//  Parameters: none
//
//  Returns: void
//
//  Note: 
//
//--------------------------------------------------------------------------
void CES1371::InitHardware()
{
    UCHAR  bReg = 0x00;
    USHORT wReg = 0x0000;
    ULONG  i;

   // if we have a 5880 then take the AC97 codec out of reset
    if ( (m_dwDeviceID == ES5880_PCI_DEVID)                          ||
         ((m_dwDeviceID == ES1371_PCI_DEVID) && (m_dwRevisionID == 7)) || 
         ((m_dwDeviceID == ES1371_PCI_DEVID) && (m_dwRevisionID >= 9))
       )
    {
        // write the es137x AC97 reset bit
        bReg = 0x20;
        HwRegRMW( ES1371_bINTSUMM_OFF, 0x20, bReg );

        // wait around a long time for the codec to come out of reset
        // i.e. 20 msec or 200 * 100 nanosec
#ifdef UNDER_CE
        Sleep(1);
#else
        if ( KeGetCurrentIrql() == PASSIVE_LEVEL )
        {
            LARGE_INTEGER liTimeout =
                   RtlConvertLongToLargeInteger( -200 ); 

            KeDelayExecutionThread( KernelMode, FALSE, &liTimeout );
        }
        else // wait around the old fashioned way by polling
        {
            ULONG ulPollCount;
            UCHAR ucDummyRead;

            for ( ulPollCount = 0; ulPollCount < 110000; ulPollCount++ )
            {
                ucDummyRead = READ_PORT_UCHAR( m_pPciAddr );
            }
        }
#endif

		// The 5880 has a mux to configure the line in/rear spkr out
		// jack to the appropriate function.  In the basic driver,
		// we'll assume it'll always be a line in function (set
		// GPIO2 bit to zero).
		HwRegRMW( ES1371_bGPIO_OFF, (UCHAR)0x04, (UCHAR) 0x00);

    }

    // write bogus values into the DRegs so the initial writes take
    for ( i=0; i<12; i++)
      m_ulDRegs[i] = 0xffffffff;
    
    /* setup the MISCCTRL reg */
    bReg =
        ES1371_MISCCTL_PDLEV_D0
        & ~ES1371_MISCCTL_CCBINTRM_EN;

    HwRegRMW( ES1371_bMISCCTL_OFF, 0xff, bReg );
    
    /* setup the DEVCTRL reg */
    /* enable UART, XTAL clock and PCI clock */
    bReg =
         ES1371_DEVCTL_UART_EN 
        & ~ES1371_DEVCTL_XTALCLK_DS
        & ~ES1371_DEVCTL_PCICLK_DS;
    
    HwRegRMW( ES1371_bDEVCTL_OFF, 0xff, bReg );

    /* setup the JOYCTRL reg */
    bReg = 0;
    HwRegRMW( ES1371_bJOYCTL_OFF, 0xff, bReg );
    
    /* disable the NMI */
    bReg = 0x00;
    HwRegRMW( ES1371_bNMIENA_OFF, 0xff, bReg );
    
    /* clear the NMI status register */
    wReg = 0x0000;
    HwRegRMW( ES1371_wNMISTAT_OFF, 0xffff, wReg );
    
    /* clear the Serial Control register */
    bReg = 0x00;
    HwRegRMW( ES1371_bSERCTL_OFF, 0xff, bReg );
    
    // initialize Codec
    InitCodec();

    /*
     *put the HW into a happy state
     */  
    InitSRC( TRUE );

    // initialize UART
    m_ulUARTState = 0;

    return;
}

// }}}

// {{{ SRCInit

void CES1371::InitSRC( BOOLEAN fEnable )
{
    USHORT     i;
    ULONG      ulHardwareWrite;

    /* must poll before writes to DISABLE or PAUSE the SRCIO register */
    SRCPollIOReg ();
    /* disable SRC for init */
    ulHardwareWrite = SRC_DISABLE;
    HwRegRMW( ES1371_dSRCIO_OFF, 0xffffffff, ulHardwareWrite ); 
//    WRITE_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF), SRC_DISABLE);

    /* clear the SRC RAM */
    for( i = 0; i < 0x80; ++i )
        SRCRegWrite(i, 0 );

    SRCRegWrite(SRC_DAC0_BASE + SRC_TRUNC_N_OFF, 16 << 4);
    SRCRegWrite(SRC_DAC0_BASE + SRC_INT_REGS_OFF, 16 << 10);
    SRCRegWrite(SRC_DAC1_BASE + SRC_TRUNC_N_OFF, 16 << 4);
    SRCRegWrite(SRC_DAC1_BASE + SRC_INT_REGS_OFF, 16 << 10);
    SRCRegWrite(SRC_ADC_BASE + SRC_TRUNC_N_OFF, 16 << 4);
    SRCRegWrite(SRC_ADC_BASE + SRC_INT_REGS_OFF, 16 << 10);
    SRCRegWrite(SRC_DAC0_VOL_L, 1 << 12);
    SRCRegWrite(SRC_DAC0_VOL_R, 1 << 12);
    SRCRegWrite(SRC_DAC1_VOL_L, 1 << 12);
    SRCRegWrite(SRC_DAC1_VOL_R, 1 << 12);
    SRCRegWrite(SRC_ADC_VOL_L, 1 << 12);
    SRCRegWrite(SRC_ADC_VOL_R, 1 << 12);

    /* default some rates */
    SRCSetRate(ES1371_DAC0, 22050);
    SRCSetRate(ES1371_DAC1, 22050);
    SRCSetRate(ES1371_ADC, 22050);

#if (DBG)
    USHORT usSRCdata[8];
    USHORT j;
    /* dump the SRC ram */
    DEBUGMSG( ZONE_INFO, (TEXT("es1371 dump SRC ram\r")));

    for ( i = 0; i < 16; i++ )
    {
      for ( j = 0; j < 8; j++)
      {
          usSRCdata[j] = SRCRegRead( i*8 + j );  
      }

      DEBUGMSG( ZONE_INFO, (TEXT("%02x %04x %04x %04x %04x %04x %04x %04x %04x\r"), i*8,
                                      usSRCdata[0],usSRCdata[1],
                                      usSRCdata[2],usSRCdata[3],
                                      usSRCdata[4],usSRCdata[5],
                                      usSRCdata[6],usSRCdata[7]));
    }
#endif

    if ( fEnable )
    {
        /* now enable the whole deal */
        SRCPollIOReg ();
        ulHardwareWrite = 0L;
        HwRegRMW( ES1371_dSRCIO_OFF, 0xffffffff, ulHardwareWrite ); 
    }

    return;
}

// }}}

//--------------------------------------------------------------------------
//
//  Name: HwPagedIOWrite
//
//  Description: Does a MP-safe write to the indirect registers
//
//  Parameters: UCHAR Page : the memory page to set
//              PULONG pAddr : the IO address to write
//              ULONG ulData : the data to write
//
//  Returns: NTSTATUS    
//
//--------------------------------------------------------------------------
VOID
CES1371::HwPagedIOWrite( UCHAR Page, ULONG pAddr, ULONG ulData )
{
    if ( 0 == m_ulPowerState )
    {
    	CAutoLock csa(&m_csPageLock);
	    // write the page register if needed
        if ( m_ulDRegs[ES1371_bMEMPAGE_OFF/4] != Page ) {
            WRITE_PORT_UCHAR(m_pPciAddr + ES1371_bMEMPAGE_OFF, Page & 0x0f );
            // save in the regs array
            m_ulDRegs[ES1371_bMEMPAGE_OFF/4] = Page;
        }
        WRITE_PORT_ULONG((PULONG) (m_pPciAddr + pAddr),  ulData);
    }
    else
    {
        // power down state - can't write hardware write the saved setting
        m_ulIRegsPMContext[ (ULONG(Page) * 4) + ( (pAddr - 0x30) / 4 ) ] = ulData;
    }

}

//--------------------------------------------------------------------------
//
//  Name: HwPagedIORead
//
//  Description: Sets the current page of indirect registers
//
//  Parameters: UCHAR Page : the memory page to set
//              PULONG pAddr : the IO address to read
//
//  Returns: data read   
//
//--------------------------------------------------------------------------
ULONG
CES1371::HwPagedIORead( UCHAR Page, ULONG pAddr )
{
    ULONG ulReadData;

    if ( 0 == m_ulPowerState )
    {
    	CAutoLock csa(&m_csPageLock);
	    // write the page register if needed
        if ( m_ulDRegs[ES1371_bMEMPAGE_OFF/4] != Page ) {
            WRITE_PORT_UCHAR(m_pPciAddr + ES1371_bMEMPAGE_OFF, Page & 0x0f );
            // save in the regs array
            m_ulDRegs[ES1371_bMEMPAGE_OFF/4] = Page;
        }
        ulReadData = READ_PORT_ULONG((PULONG) (m_pPciAddr + pAddr));
    }
    else
    {
        // power down state - can't read hardware get the saved setting
        ulReadData = m_ulIRegsPMContext[ (ULONG(Page) * 4) + ( (pAddr - 0x30) / 4 ) ];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -