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

📄 ac97.cpp

📁 ICEExt for Driver Studio3.2的sourcecode
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*++
    Copyright  (c) 2004 Sten
    Contact information:
        mail: stenri@mail.ru

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

 
Module Name:
    ac97.cpp

Abstract: AC'97 code functions 

Revision History:

 Sten        01/01/2004
      Initial release. Started expiriments on using AC'97.. Wow!!

--*/

extern "C" {
#pragma warning ( push, 3 )
#include <ntddk.h>
#pragma warning ( pop )
}

#pragma warning ( disable: 4514 ) // unreferenced inline function has been removed
#pragma warning ( disable: 4127 ) // conditional expression is constant

#include <windef.h>
#include <ntverp.h>

#include "softice.h"
#include "defs.h"
#include "pci.h"
#include "ac97.h"
#include "keyboard.h"

#include "mp3.h"

static USHORT NAMBAR    = 0;             // BAR for mixer 
static USHORT NABMBAR   = 0;             // BAR for bus master regs
static UCHAR  INTLINE   = 0;             // interrupt line for the device
static ULONG  INTVECTOR = 0;             // AC97 Interrupt vector

static PVOID  OldHandler = 0;            // Old AC97 IRQ handler

static ULONG *BDL_BUFFER = 0;            // pointer to the Buffer Descriptor List

UCHAR  *WAV_BUFFER1 = 0;                 // pointer to the first  wav buffer 
UCHAR  *WAV_BUFFER2 = 0;                 // pointer to the second wav buffer

ULONG AC97_PCI_ADDRESS = 0;              // AC97 PCI address

///////////////////////////////////////////////////////////////////////////////////
//
// AC97 IRQ Handler
//
///////////////////////////////////////////////////////////////////////////////////
static __declspec(naked) VOID ac97_IRQHandler( VOID )
{
    __asm
    {
			pushad
			push       fs
			push       ds
			push       es

			mov        eax, 00000030h
			mov        fs,ax

			mov        eax, 23h
			mov        ds,ax
			mov        es,ax

			mov        ebp,esp
			sub        esp,32
    }

    USHORT dwStsReg;
    USHORT dwPOSRReg;
    __asm
    {
            mov     dx, ds:[NABMBAR]
            add     dx, GLOB_STS_REG               ; set pointer to Global Status reg
            in      ax, dx
            mov     dwStsReg, ax

            mov     dx, ds:[NABMBAR]
            add     dx, PO_SR_REG                  ; set pointer to PCM Out Cntl reg
            in      ax, dx
            mov     dwPOSRReg, ax
            
    }

    if (*si_IceIsActive)
    {
        DbgPrint("AC97 Handler: %04X %04X\n", dwStsReg,dwPOSRReg);
    }

//_Out:
    __asm
    {
          movzx      eax, INTLINE         ; send End Of Interrupt signal
          call       si_SendSpecificEOI

          mov        esp,ebp

          pop        es
          pop        ds
          pop        fs
          popad

          //iretd
          jmp        cs:[OldHandler]
    }
}

///////////////////////////////////////////////////////////////////////////////////
//
// Initialize AC97
//
///////////////////////////////////////////////////////////////////////////////////
BOOL ac97_Init( VOID )
{
    // Detect/reset AC97 
    if ((AC97_PCI_ADDRESS = pciFindDevice(MAKELONG(INTEL_VID, ICH5_DID))) == 0)
     if ((AC97_PCI_ADDRESS = pciFindDevice(MAKELONG(INTEL_VID, ICH4_DID))) == 0)
      if ((AC97_PCI_ADDRESS = pciFindDevice(MAKELONG(INTEL_VID, ICH3_DID))) == 0)
       if ((AC97_PCI_ADDRESS = pciFindDevice(MAKELONG(INTEL_VID, ICH2_DID))) == 0)
        if ((AC97_PCI_ADDRESS = pciFindDevice(MAKELONG(INTEL_VID, ICH0_DID))) == 0)
         if ((AC97_PCI_ADDRESS = pciFindDevice(MAKELONG(INTEL_VID, ICH_DID))) == 0)
         {
            DbgPrint("Warning: AC97 not found.\n");
            return FALSE;
         }

    __asm 
    {
        ; get ICH base address regs for mixer and bus master
        mov     eax, AC97_PCI_ADDRESS

        mov     al, NAMBAR_REG
        call    pciRegRead16	        		; read PCI registers 10-11
        and     dx, IO_ADDR_MASK 		        ; mask off BIT0

        mov     ds:[NAMBAR], dx                 ; save audio mixer base addy

        mov     al, NABMBAR_REG
        call    pciRegRead16
        and     dx, IO_ADDR_MASK

        mov     ds:[NABMBAR], dx                ; save bus master base addy

        mov     al, INTLINE_REG
        call    pciRegRead8

        mov     ds:[INTLINE], dl                ; save int line register

        movzx   eax, dl
        call    si_IRQ2INT
        mov     ds:[INTVECTOR], eax

        mov     al, PCI_CMD_REG
        call    pciRegRead16                    ; read PCI command register
        or      dl, IO_ENA+BM_ENA               ; enable IO and bus master
        call    pciRegWrite16
    }

    DbgPrint("AC97 INT LINE:                                %d\n",   INTLINE);
    DbgPrint("AC97 VECTOR:                                  %08x\n", INTVECTOR);
/**/
    KIRQL     Irql;
    KAFFINITY Affinity;
    
    ULONG MappedVector = HalGetInterruptVector(PCIBus,
                                               0,
                                               INTLINE,
                                               INTLINE,
                                               &Irql,
                                               &Affinity);

   
    INTVECTOR = MappedVector & 0x000000FF; // low Mapped vector 8 bits seems 
                                           // to be real system-vector 

    DbgPrint("AC97 MAPPED VECTOR:                           %08x\n", MappedVector);
    DbgPrint("AC97 MAPPED VECTOR Affinity:                  %08x\n", Affinity);
    DbgPrint("AC97 MAPPED VECTOR Irql:                      %08x\n", Irql);
/**/

    if (!INTVECTOR)
    {
        DbgPrint("Error: unable to map AC97 IRQ to system vector.\n");
        return FALSE;
    }

    //-----------------------------------------------------------------------
    // Install my own AC97 IRQ handler
    //-----------------------------------------------------------------------
    OldHandler = SetInterruptHandler(INTVECTOR, ac97_IRQHandler, 0x8e);
    DbgPrint("Old AC97 IRQ Handler:                         %08X\n", OldHandler);


    // Allocate buffer for the BDL
    // It's bad style to use MmAllocateContiguousMemory to alloc memory 
    // for DMA operations but.. :)
    PHYSICAL_ADDRESS HighestAcceptable;
    HighestAcceptable.QuadPart = 0xFFFFFFFF;
    BDL_BUFFER  = (ULONG *)MmAllocateContiguousMemory(256, HighestAcceptable);
    WAV_BUFFER1 = (UCHAR *)MmAllocateContiguousMemory(WAV_BUFFER_SIZE, HighestAcceptable);
    WAV_BUFFER2 = (UCHAR *)MmAllocateContiguousMemory(WAV_BUFFER_SIZE, HighestAcceptable);
   
    if ((!BDL_BUFFER) || (!WAV_BUFFER1) || (!WAV_BUFFER2))
    {
        DbgPrint("Error: unable to allocate enough contiguous physical memory.\n");
        return FALSE;
    }

    // fill our buffers with zeroes
    memset(WAV_BUFFER1,  0, WAV_BUFFER_SIZE);
    memset(WAV_BUFFER2,  0, WAV_BUFFER_SIZE);
 
    return TRUE;
}

VOID ac97_PrepareToPlay( VOID )
{
    // initialize AC97 DMA controller
    ac97_ResetDMA();
    ac97_CreateBDL();
    ac97_SetBDLAddress();
    ac97_SetLastValidIndex(31);

    __asm
    {
			 movzx eax, INTLINE
			 call si_EnableIRQ
    }
}  

///////////////////////////////////////////////////////////////////////////////////
//
// Free allocated memory
//
///////////////////////////////////////////////////////////////////////////////////
VOID ac97_Done( VOID )
{
    if (BDL_BUFFER)  MmFreeContiguousMemory(BDL_BUFFER);
    if (WAV_BUFFER1) MmFreeContiguousMemory(WAV_BUFFER1);
    if (WAV_BUFFER2) MmFreeContiguousMemory(WAV_BUFFER2);

    AC97_PCI_ADDRESS = 0;
    BDL_BUFFER       = 0;
    WAV_BUFFER1      = 0;
    WAV_BUFFER2      = 0;
    
     // Uninstall AC97 IRQ handler
     if (OldHandler)
     {
          SetInterruptHandler(INTVECTOR,OldHandler, 0x8e);
          OldHandler = 0;
     }
}

///////////////////////////////////////////////////////////////////////////////////
//
// Set PCM Front DAC Rate
//
///////////////////////////////////////////////////////////////////////////////////
VOID ac97_SetPcmFrontDacRate( USHORT dwRate )
{
    __asm
	{
			push    eax
			push    edx

 			mov     ax, dwRate
			mov     dx, ds:[NAMBAR]                 ; get mixer base address
			add     dx, CODEC_PCM_FRONT_DACRATE_REG 
			out     dx, ax                          ; out sample rate

			mov     eax, 4
			call    si_DelayMilliSec                ; delays cuz codecs are slow

			pop     edx
			pop     eax
	}
}

///////////////////////////////////////////////////////////////////////////////////
//
// Set PCM Surround DAC Rate
//
///////////////////////////////////////////////////////////////////////////////////
VOID ac97_SetPcmSurroundDacRate( USHORT dwRate )
{
    __asm
	{
			push    eax
			push    edx

 			mov     ax, dwRate
			mov     dx, ds:[NAMBAR]                 ; get mixer base address
			add     dx, CODEC_PCM_SURND_DACRATE_REG 
			out     dx, ax                          ; out sample rate

			mov     eax, 4

⌨️ 快捷键说明

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