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

📄 pci.cpp

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

    This code was mainly ported from jeff leyda's .wav file player for DOS. 

    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:
    pci.cpp

Abstract: PCI bus 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

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

#include "pci.h"

/*
void cs_write(unsigned long port, unsigned char val) 
{
    outl(port & 0xfffffffc | 0x80000000, 0x0cf8); outb(val, 0xcfc + (port & 0x3)); 
}

unsigned char cs_read_b(unsigned long port) 
{
    outl(port & 0xfffffffc | 0x80000000, 0x0cf8); return(inb(0xcfc + (port & 0x3))); 
}

unsigned short cs_read_w(unsigned long port) 
{
    outl(port & 0xfffffffc | 0x80000000, 0x0cf8); return(inw(0xcfc + (port & 0x3))); 
}

unsigned long cs_read_l(unsigned long port) 
{
    outl(port & 0xfffffffc | 0x80000000, 0x0cf8); return(inl(0xcfc + (port & 0x3))); 
}

// Enable ACPI by set B7 on Reg 0x40, LPC 
void cs_write_b(unsigned long port, unsigned long val)
{
    outl(port, 0x0cf8);
    b = inb(0x0cfc) | 0x80;
    outb(val, 0xcfc);
}
*/

///////////////////////////////////////////////////////////////////////////////////
//
// 8/16/32bit PCI reader
//
// Entry: EAX=PCI Bus/Device/fn/register number
//           BIT30 set if 32 bit access requested
//           BIT29 set if 16 bit access requested
//           otherwise defaults to 8bit read
//
// Exit:  DL,DX,EDX register data depending on requested read size
//
// Note: this routine is meant to be called via pciRegRead8, pciRegread16,
//	or pciRegRead32, listed below.
//
// Note2: don't attempt to read 32bits of data from a non dword aligned reg
//	 number.  Likewise, don't do 16bit reads from non word aligned reg #
//
///////////////////////////////////////////////////////////////////////////////////

void __declspec (naked) pciRegRead (void)
{
	__asm
	{
            push      ebx
	        push	  ecx
              
            mov       ebx, eax                        ; save eax, dh
            mov       cl, dh
            and       eax, NOT PCI32+PCI16            ; clear out data size request
            or        eax, BIT31                      ; make a PCI access request
            and       al, NOT 3                       ; force index to be dword

            mov       dx, PCI_INDEX_PORT
            out       dx, eax                         ; write PCI selector

            mov       dx, PCI_DATA_PORT
            mov       al, bl
            and       al, 3                           ; figure out which port to
            add       dl, al                          ; read to

    	    in        eax, dx                         ; do 32bit read
            test      ebx, PCI32
            jz        not32_bit

            mov       edx, eax                        ; return 32bits of data

not32_bit:
            mov       dx, ax                          ; return 16bits of data
            test      ebx, PCI32+PCI16
            jnz       do16_bit
            mov       dh, cl                          ; restore dh for 8 bit read

do16_bit:
			mov       eax, ebx                        ; restore eax
			and       eax, NOT PCI32+PCI16            ; clear out data size request
  
			pop	ecx
			pop	ebx
			ret
	}
}

void __declspec (naked) pciRegRead8 (void)
{
	__asm
	{
			and       eax, NOT PCI16+PCI32            ; set up 8 bit read size
			jmp       pciRegRead			; call generic PCI access
    }
}

void __declspec (naked) pciRegRead16 (void)
{
	__asm
	{
			and       eax, NOT PCI16+PCI32	        ; set up 16 bit read size
			or        eax, PCI16			; call generic PCI access
			jmp       pciRegRead
    }
}

void __declspec (naked) pciRegRead32 (void)
{
	__asm
	{
			and       eax, NOT PCI16+PCI32	        ; set up 32 bit read size
			or        eax, PCI32			; call generic PCI access
			jmp       pciRegRead
	}
}

///////////////////////////////////////////////////////////////////////////////////
//
// 8/16/32bit PCI writer
//
// Entry: EAX=PCI Bus/Device/fn/register number
//           BIT31 set if 32 bit access requested
//           BIT30 set if 16 bit access requested
//           otherwise defaults to 8bit read
//        DL/DX/EDX data to write depending on size
//
//
// note: this routine is meant to be called via pciRegWrite8, pciRegWrite16,
// 	or pciRegWrite32 as detailed below.
//
// Note2: don't attempt to write 32bits of data from a non dword aligned reg
//	 number.  Likewise, don't do 16bit writes from non word aligned reg #
//
///////////////////////////////////////////////////////////////////////////////////
void __declspec (naked) pciRegWrite (void)
{
	__asm
	{ 
            push	ebx
            push	cx
            mov       ebx, eax                        ; save eax, dx
            mov       cx, dx
            or        eax, BIT31                      ; make a PCI access request
            and       eax, NOT PCI16                  ; clear out data size request
            and       al, NOT 3                       ; force index to be dword

            mov       dx, PCI_INDEX_PORT
            out       dx, eax                         ; write PCI selector

            mov       dx, PCI_DATA_PORT
            mov       al, bl
            and       al, 3                           ; figure out which port to
            add       dl, al                          ; write to

            mov       eax, edx                        ; put data into eax
            mov       ax, cx

            out       dx, al
            test      ebx, PCI16+PCI32                ; only 8bit access? bail
            jz        cleanup

            out       dx, ax                          ; write 16 bit value
            test      ebx, PCI16                      ; 16bit requested?  bail
            jnz       cleanup

            out       dx, eax                         ; write full 32bit
cleanup:
			mov       eax, ebx                        ; restore eax
			and       eax, NOT PCI32+PCI16            ; clear out data size request
			mov       dx, cx                          ; restore dx
			pop       cx
			pop	      ebx
			ret
	}
}


void __declspec (naked) pciRegWrite8 (void)
{
	__asm
	{
			and       eax, NOT PCI16+PCI32	    ; set up 8 bit write size
			jmp       pciRegWrite		      	; call generic PCI access
	}
}

void __declspec (naked) pciRegWrite16 (void)
{
	__asm
	{
			and        eax, NOT PCI16+PCI32		; set up 16 bit write size
			or         eax, PCI16	       		; call generic PCI access
			jmp        pciRegWrite
    }
}

void __declspec (naked) pciRegWrite32 (void)
{
	__asm
	{
			and     eax, NOT PCI16+PCI32        ; set up 32 bit write size
			or      eax, PCI32			        ; call generic PCI access
			jmp     pciRegWrite
	}
}

///////////////////////////////////////////////////////////////////////////////////
//
// PCIFindDevice: scan through PCI space looking for a device+vendor ID
//
// Entry: EAX=Device+vendor ID
//
//  Exit: EAX=PCI address if device found
//        CY clear if found, set if not found. EAX invalid if CY set.
//
// [old stackless] Destroys: ebx, edx, esi, edi, cl
//
///////////////////////////////////////////////////////////////////////////////////
DWORD pciFindDevice ( DWORD dwID )
{
	DWORD val;

	__asm
	{
			push	  ecx
			push	  edx
			push 	  esi
			push      edi

			mov       eax, dwID
			mov       esi, eax                ; save off vend+device ID
			mov       edi, (80000000h - 100h) ; start with bus 0, dev 0 func 0

nextPCIdevice:
            add       edi, 100h
            cmp       edi, 80fff800h	        ; scanned all devices?
            stc
            jz        PCIscanExit             ; not found

            mov       eax, edi                ; read PCI registers
            call      pciRegRead32
            cmp       edx, esi                ; found device?
            jnz       nextPCIDevice
            clc

PCIScanExit:
            jnc       all_ok
            pushfd
            xor       edi, edi
            popfd
all_ok:
   	        pushfd
      	    mov	eax, edi	        ; return found PCI address
	        and	eax, NOT BIT31	        ; return only bus/dev/fn #
	        popfd

    	    pop	edi
      	    pop	esi
	        pop	edx
	        pop	ecx

			mov val, eax
	}

	return val;
}

⌨️ 快捷键说明

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