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

📄 es1371.cpp

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

    return ulReadData;
}

// {{{ HwRegRMW
/* -----------------------------------------------------------------------  /

    Routine:  HwRegRMW

    Purpose:  The routine is used to access a Concert chip register via
              its shadowed value.  This routine is required to provide
              exclusion (synchronization) to the register.

              This routine should be run from the KeSynchronizeExecution
              call,  forceing this routine to execute at our devices
              DIRQL.  It also acquires the spin lock, providing exclusion.

              The current value in the shadow ram is read, ANDed with
              the mask and ORed with the bits.


    Inputs:

    Output:   None

    Errors:   None

/  ----------------------------------------------------------------------- */
UCHAR
CES1371::HwRegRMW (  UCHAR Reg, UCHAR bBitMask, UCHAR bSetBits )
{
   UCHAR bNewValue;
   UCHAR *puc_DRegs = (UCHAR *)m_ulDRegs;

   // are we setting the whole data space?
   if ( 0x00 == bBitMask )
   {
       return ( *(puc_DRegs + Reg) );
   }
   else if ( 0xff == bBitMask )
   {
       bNewValue = bSetBits;
   }
   else
   {
       // read original value, 
       // zero out bits of interest, 
       // set proper bits to one 
       if ( (0xff != *(puc_DRegs + Reg)) || ( m_ulPowerState > 0 ) )
           bNewValue = *(puc_DRegs + Reg);
       else
           bNewValue = READ_PORT_UCHAR (m_pPciAddr + Reg);
       bNewValue &= ~bBitMask;
       bNewValue |= (bSetBits & bBitMask);
   }
   // write new value to hardware
   if ( 0 == m_ulPowerState )
       WRITE_PORT_UCHAR ( m_pPciAddr + Reg, bNewValue);

   // save the value for the future
   *(puc_DRegs + Reg) = bNewValue;

   return bNewValue;

}  // end of function: hw_reg_rmw_char

// }}}

// {{{ HwRegRMW
USHORT
CES1371::HwRegRMW ( UCHAR Reg, USHORT wBitMask, USHORT wSetBits )
{
   USHORT wNewValue;
   USHORT *pus_DRegs = (USHORT *)m_ulDRegs;
   
   // are we setting the whole data space?
   if ( 0x0000 == wBitMask )
   {
       return ( *(pus_DRegs + Reg/2) );
   }
   else if ( 0xffff == wBitMask )
   {
       wNewValue = wSetBits;
   }
   else
   {
       // read original value, 
       // zero out bits of interest, 
       // set proper bits to one
       if ( (0xffff != *(pus_DRegs + (Reg/2))) || ( m_ulPowerState > 0 ) )
           wNewValue = *(pus_DRegs + (Reg/2));
       else
           wNewValue = READ_PORT_USHORT ( (PUSHORT)(m_pPciAddr + Reg) );
       wNewValue &= ~wBitMask;
       wNewValue |= (wSetBits & wBitMask);
   }
     
   /* write new value to hardware */
   if ( 0 == m_ulPowerState )
       WRITE_PORT_USHORT ( (PUSHORT)(m_pPciAddr + Reg), wNewValue );
   
   // save the value for the future
   *(pus_DRegs + (Reg/2)) = wNewValue;

   return wNewValue;
  
}  /* end of function: hw_reg_rmw_short */

// }}}

// {{{ HwRegRMW
ULONG
CES1371::HwRegRMW ( UCHAR Reg, ULONG dwBitMask, ULONG dwSetBits )
{
   ULONG dwNewValue;

   // are we setting the whole data space?
   if ( 0x00000000 == dwBitMask )
   {
       return ( m_ulDRegs[Reg/4] );
   }
   else if ( 0xffffffff == dwBitMask )
   {
       dwNewValue = dwSetBits;
   }
   else
   {
       // read original value, 
       // zero out bits of interest, 
       // set proper bits to one 
       if ( (0xffffffff != m_ulDRegs[Reg/4]) || ( m_ulPowerState > 0 ) )
           dwNewValue = m_ulDRegs[Reg/4];
       else
           dwNewValue = READ_PORT_ULONG ( (PULONG)(m_pPciAddr + Reg) );

       dwNewValue &= ~dwBitMask;
       dwNewValue |= (dwSetBits & dwBitMask);
   }

   /* write new value to hardware */
   if ( 0 == m_ulPowerState )
       WRITE_PORT_ULONG ( (PULONG)(m_pPciAddr + Reg), dwNewValue );

   // save the value for the future
   m_ulDRegs[Reg/4] = dwNewValue;

   return dwNewValue;

}  /* end of function: hw_reg_rmw_long */

// }}}

// {{{ SRCRegRead

USHORT
CES1371::SRCRegRead( USHORT reg )
{
   /* LOCAL DATA */
   ULONG    dtemp;
   /* END LOCAL DATA */

   // Is the device powered down?
   if ( m_ulPowerState > 0 )
        return m_usSRCRegsPMContext[ reg ];

   /* wait for ready */
   dtemp = SRCPollIOReg ();
    
   /* assert a read request */
   WRITE_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF),
                    (dtemp & SRC_CTLMASK) | (ULONG(reg) << 25) );

   /* wait for the data */
   dtemp = SRCPollIOReg ();
   return (USHORT) dtemp;
}

// }}}

void 
CES1371::SRCRegWrite(USHORT reg, USHORT val)
{
    ULONG    i, dtemp;

    // Is the device powered down?
    if ( m_ulPowerState > 0 )
    {
        m_usSRCRegsPMContext[ reg ] = val;
        return;
    }

    /* wait for ready */
    dtemp = SRCPollIOReg ();

    /* assert the write request */
    i = (dtemp & SRC_CTLMASK) | SRC_WENABLE |
            ( (ULONG)reg << 25 ) | val;

    /* write the value */
    WRITE_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF), i);

#ifdef DBG
    {
      USHORT us;
      us = SRCRegRead ( reg );
      if ( us != val )
        _DbgPrintF( DEBUGLVL_TERSE, ("[SRCRegWrite] FAILED reg %02x wrote %04x read %04x", reg, val, us));
    }
#endif

    return;
}

// }}}


void
CES1371::SRCSetRate( ULONG ulChannelIndex, USHORT wSampleRate )
{
    ULONG    i, freq, dtemp;
    USHORT   N, truncM, truncStart, wtemp;

    // Is the device powered down?
    if ( m_ulPowerState > 0 )
        return;

    switch ( ulChannelIndex )
    {
      case ES1371_DAC0:
        // freeze the channel
        for( i = 0; i < SRC_IOPOLL_COUNT; ++i )
            if( !(READ_PORT_ULONG ( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF) ) & SRC_BUSY) )
                break;

        dtemp = READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF));
        WRITE_PORT_ULONG( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF),
                (dtemp & SRC_CTLMASK) | SRC_DAC0FREEZE);

        // calculate new frequency and write it
        // preserve accum 
        freq = ((ULONG) wSampleRate << 16) / 3000U;
        SRCRegWrite( SRC_DAC0_BASE + SRC_INT_REGS_OFF, 
                     (SRCRegRead( SRC_DAC0_BASE + SRC_INT_REGS_OFF ) & 0x00ffU) |
                       ((USHORT) (freq >> 6) & 0xfc00));
        SRCRegWrite( SRC_DAC0_BASE + SRC_VFREQ_FRAC_OFF, (USHORT) freq >> 1);

        // un-freeze the channel
        for( i = 0; i < SRC_IOPOLL_COUNT; ++i )
            if( !(READ_PORT_ULONG ( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF) ) & SRC_BUSY) )
                break;
        dtemp = READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF));
        WRITE_PORT_ULONG( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF),
                (dtemp & SRC_CTLMASK) & (~SRC_DAC0FREEZE) );
        break;

      case ES1371_DAC1:
        // freeze the channel
        for( i = 0; i < SRC_IOPOLL_COUNT; ++i )
            if( !(READ_PORT_ULONG ( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF) ) & SRC_BUSY) )
                break;

        dtemp = READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF));
        WRITE_PORT_ULONG( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF),
                (dtemp & SRC_CTLMASK) | SRC_DAC1FREEZE);

        // calculate new frequency and write it
        // preserve accum 
        freq = ((ULONG) wSampleRate << 16) / 3000U;
        SRCRegWrite( SRC_DAC1_BASE + SRC_INT_REGS_OFF, 
                     (SRCRegRead( SRC_DAC1_BASE + SRC_INT_REGS_OFF ) & 0x00ffU) |
                       ((USHORT) (freq >> 6) & 0xfc00));
        SRCRegWrite( SRC_DAC1_BASE + SRC_VFREQ_FRAC_OFF, (USHORT) freq >> 1);

        // un-freeze the channel
        for( i = 0; i < SRC_IOPOLL_COUNT; ++i )
            if( !(READ_PORT_ULONG ( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF) ) & SRC_BUSY) )
                break;
        dtemp = READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF));
        WRITE_PORT_ULONG( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF),
                (dtemp & SRC_CTLMASK) & (~SRC_DAC1FREEZE) );
        break;

      case ES1371_ADC:
        // derive oversample ratio
        N = wSampleRate/3000U;
        if( N == 15 || N == 13 || N == 11 || N == 9 )
            --N;

        // truncate the filter and write n/trunc_start
        truncM = (21*N - 1) | 1;
        if( wSampleRate >= 24000U )
        {
            if( truncM > 239 )
                truncM = 239;
            truncStart = (239 - truncM) >> 1;
            
            SRCRegWrite( SRC_ADC_BASE + SRC_TRUNC_N_OFF,
                         (truncStart << 9) | (N << 4));
        }
        else
        {
            if( truncM > 119 )
                truncM = 119;
            truncStart = (119 - truncM) >> 1;

            SRCRegWrite( SRC_ADC_BASE + SRC_TRUNC_N_OFF,
                    0x8000U | (truncStart << 9) | (N << 4));
        }

        /* calculate new frequency and write it - preserve accum */
        freq = ((48000UL << 16) / wSampleRate) * N;
        wtemp = SRCRegRead( SRC_ADC_BASE + SRC_INT_REGS_OFF );
        SRCRegWrite( SRC_ADC_BASE + SRC_INT_REGS_OFF,
                     (wtemp & 0x00ff) | ((USHORT) (freq >> 6) & 0xfc00));
        SRCRegWrite( SRC_ADC_BASE + SRC_VFREQ_FRAC_OFF, (USHORT) freq >> 1);

        SRCRegWrite( SRC_ADC_VOL_L, N << 8);
        SRCRegWrite( SRC_ADC_VOL_R, N << 8);
        break;
    }

    return;
}


//--------------------------------------------------------------------------
//
//  Name: SRCWaitForFrame1
//
//  Description: code that polls a value in the SRC converter so that we know
//               when it is safe to write.
//
//  Parameters:  PFRAME_CONTEXT
//
//  Returns: always succeeds
//
//  Note: Apparently, we can't do CODEC writes when the sync pulse is high.
//        Luckily, there are some debug things in the SRC that let us know
//        when sync pulse is low. This needs to be synched with the ISR so
//        we don't get interrupted and lose track of where we are.
//
//--------------------------------------------------------------------------
void
CES1371::SRCWaitForFrame1 ( )
{
    while( !((READ_PORT_ULONG( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF) ) & 0x00070000UL) ==
          0x00010000UL) )
//<mod:ce> KeStallExecutionProcessor(1);

    return;
}

// }}}
   
// {{{ SRCPollIOReg

//--------------------------------------------------------------------------
//
//  Name: SRCPollIOReg
//
//  Description:
//
//  Parameters: 
//
//  Returns:    
//
//  Note: This function must be called prior to any
//        writes to the Disable/Pause bits
//
//--------------------------------------------------------------------------
ULONG
CES1371::SRCPollIOReg ()
{
  int i;
  ULONG dw=0;

  for (i=0; i<SRC_IOPOLL_COUNT; ++i)
  {
        if (!((dw = READ_PORT_ULONG ((PULONG)(m_pPciAddr+ES1371_dSRCIO_OFF))) & SRC_BUSY) )
          break;

//<mod:ce> KeStallExecutionProcessor (1);
  }

#ifdef DBG
  if (i == SRC_IOPOLL_COUNT)
        _DbgPrintF( DEBUGLVL_TERSE, ("[SRCPollIOReg] timeout %x", dw));
#endif

  return dw;
}

// }}}
    
//--------------------------------------------------------------------------
//
//  Name: InitDMAChannel
//
//  Description: Intialize all the things about a DMA channel
//
//  Parameters: ULONG ulChannelIndex : Index of the DMA channel to init
//              ULONG ulBufferPhysAddr : Physical address of the DMA buffer
//                                    in memory
//              USHORT usBufferSize : Number of bytes in a DMA buffer
//
//  Returns: none   
//
//  Note:
//
//--------------------------------------------------------------------------
void
CES1371::InitDMAChannel( ULONG ulChannelIndex, DMAINTHANDLER pfHandler, PVOID pContext)
{


    m_dmachannel[ulChannelIndex].pfIntHandler = pfHandler;
    m_dmachannel[ulChannelIndex].pvIntContext = pContext;

    ULONG ulBufferPhysAddr = m_dmachannel[ulChannelIndex].ulBufferPhysAddr;
    ULONG ulFrameCount = 0;


    switch ( ulChannelIndex ) {
    case ES1371_DAC0 :
      // Set up the physical DMA buffer address
      HwPagedIOWrite( ES1371_DAC0CTL_PAGE, ES1371_dDAC0PADDR_OFF, ulBufferPhysAddr);  
      // Clear out the Frame count register
      HwPagedIOWrite( ES1371_DAC0CTL_PAGE, ES1371_wDAC0FC_OFF, ulFrameCount);  
      break;

    case ES1371_DAC1 :
      // Set up the physical DMA buffer address
      HwPagedIOWrite( ES1371_DAC1CTL_PAGE, ES1371_dDAC1PADDR_OFF, ulBufferPhysAddr);  
      // Clear out the Frame count register
      HwPagedIOWrite( ES1371_DAC1CTL_PAGE, ES1371_wDAC1FC_OFF, ulFrameCount);  
      break;

    case ES1371_ADC :
      // Set up the physical DMA buffer address
      HwPagedIOWrite( ES1371_ADCCTL_PAGE, ES1371_dADCPADDR_OFF, ulBufferPhysAddr);  
      // Clear out the Frame count register
      HwPagedIOWrite( ES1371_ADCCTL_PAGE, ES1371_wADCFC_OFF, ulFrameCount);  
      break;

    }

⌨️ 快捷键说明

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