pciconf.asm

来自「PC燒錄BIOS的源程序」· 汇编 代码 · 共 317 行

ASM
317
字号
;// This file implemente some Function to Read/Write Bytes from PCI Configuration Space
;// Search for Specified PCI Device in the system .
;// MaSuiYi 2002.05.07
;// (C)opyright by Inventec Co., LTD.

	.model small
	.486p

	.code

;//Macro definition

PCI_CONF_PORT EQU 0CF8H
PCI_DATA_PORT EQU 0CFCH

;// End of Macro Definition

;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------
;//Global Output Function Declaration Begin
	public _Write2PCIByte
	public _ReadPCIByte
	public _Find_PCI_Device

;//Global Output Function Declaration End
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------


;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------
;// C Like grammar:
;// void Write2PCIByte( unsigned char BUS_NUMBER,
;//						unsigned char DEVICE_NUMBER,
;//						unsigned char FUNCTION_NUMBER,
;//						unsigned char REGISTER_NUMBER,
;//						unsigned char VALUE)
;//
;// Input:BUS_NUMBER	  = bus to read from
;		  DEVICE_NUMBER	  = device number to read from
;		  FUNCTION_NUMBER = function number to read from
;		  REGISTER_NUMBER = starting register number
;		  VALUE           = The Value you want to write
;
;// Output: NONE
;
;// Stack:	Unused
;
;// Description:Reads a Byte from PCI configuration space
;
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------
_Write2PCIByte PROC NEAR

Bus       EQU byte ptr [bp + 4]
Device    EQU byte ptr [bp + 6]
Function  EQU byte ptr [bp + 8]
Register  EQU byte ptr [bp + 10]
Value     EQU byte ptr [bp + 12]

        push    bp
        mov     bp, sp

        ;// Initialize EAX W/Enable Bit

        mov     dx, PCI_CONF_PORT                     ; PCI CONFIGURATION PORT
        mov     eax, 80000000H

        ;// Build Bus Number Into EAX

        xor     ebx, ebx
        mov     bl, Bus
        shl     ebx, 16
        or      eax, ebx

        ;// Build Device Number Into EAX

        xor     ebx, ebx
        mov     bl, Device
        shl     ebx, 11
        or      eax, ebx

        ;// Build Function Number Into EAX

        xor     ebx, ebx
        mov     bl, Function
        shl     ebx, 8
        or      eax, ebx

        ;// Build MOD 4 Register Into EAX

        xor     ebx, ebx
        mov     bl, Register
        and     bl, NOT 3
        or      eax, ebx

        ;// Read In Four Bytes Near Ours

        out     dx, eax
        mov     dx, PCI_DATA_PORT
        in      eax, dx

        ;// Shift Our Register Position Into AL Register

        mov     cl, Register
        and     cl, 3
        shl     cl, 3

        ;// Move Our Value Into AL and Shift Back To Correct Position

        ror     eax, cl
        mov     al, Value
        rol     eax, cl

        ;// And .... Write It

        out     dx, eax

        pop     bp
        ret

_Write2PCIByte ENDP

;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------
;// C Like grammar:
;// unsigned char ReadPCIByte ( unsigned char BUS_NUMBER,
;//								unsigned char DEVICE_NUMBER,
;//								unsigned char FUNCTION_NUMBER,
;//								unsigned char REGISTER_NUMBER)
;//
;// Input:BUS_NUMBER	  = bus to read from
;		  DEVICE_NUMBER	  = device number to read from
;		  FUNCTION_NUMBER = function number to read from
;		  REGISTER_NUMBER = starting register number
;
;// Output: unsigned char: the bytes have read from  pci Confuiguration space 
;
;// Stack:	Unused
;
;// Description:Reads a Byte from PCI configuration space
;
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------
_ReadPCIByte PROC NEAR

Bus       EQU byte ptr [bp + 4]
Device    EQU byte ptr [bp + 6]
Function  EQU byte ptr [bp + 8]
Register  EQU byte ptr [bp + 10]

        push    bp
        mov     bp, sp

        ;// Initialize EAX W/Enable Bit

        mov     dx, PCI_CONF_PORT
        mov     eax, 80000000H

        ;// Build Bus Number Into EAX

        xor     ebx, ebx
        mov     bl, Bus
        shl     ebx, 16
        or      eax, ebx

        ;// Build Device Number Into EAX

        xor     ebx, ebx
        mov     bl, Device
        shl     ebx, 11
        or      eax, ebx

        ;// Build Function Number Into EAX

        xor     ebx, ebx
        mov     bl, Function
        shl     ebx, 8
        or      eax, ebx

        ;// Build MOD 4 Register Into EAX

        xor     ebx, ebx
        mov     bl, Register
        and     bl, NOT 3
        or      eax, ebx

        ;// Read In Four Bytes Near Ours

        out     dx, eax
        mov     dx, PCI_DATA_PORT
        in      eax, dx

        ;// Shift Our Register Position Into AL Register

		mov     cl, Register
        and     cl, 3
        shl     cl, 3

        ;// Move Our Value Into AL and Shift Back To Correct Position

        ror     eax, cl
        xor     ah, ah

        ;// And .... Get Back

        pop     bp
        ret

_ReadPCIByte ENDP


;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------
;// C Like grammar:
;// unsigned char Find_PCI_Device(unsigned int Device) ;
;//
;// Input:DEvice = Device Identification(PIIX4 is 0x7110 82443BX is 0x7190)
;
;// Output: unsigned char: The specified Device Number(<0x20)  
;
;// Stack:	Unused
;
;// Description: Use This To Locate IDSEL For A PCI Chipset.
;// Actual 'C' Code For Find_PCI_Device: This is same as the following 
;//
;// usigned char Find_PCI_Device(unsigned int Device)
;// {
;//   unsigned char loop ;
;//   unsigned int NextID = 0 ;
;//
;//   for (loop = 0; loop < 0x20; loop++) {
;//
;//      NextID = ReadPCIByte (0,          // Bus
;//                        loop,       // Device Select
;//                        0,          // Function 0
;//                        3) ;        // PCI Device ID Register
;//
;//      NextID = NextID << 8 ;
;//
;//      NextID |= ReadPCIByte (0,          // Bus
;//                         loop,       // Device Select
;//                         0,          // Function 0
;//                         2) ;        // PCI Device ID Register
;//
;//      if (NextID == Device) return (loop) ;
;//
;//   }
;//
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------

_Find_PCI_Device PROC NEAR

		push    bp                      ;// Set Up Stack Frame
		mov     bp,sp                   ;// Set Up Stack Frame
		push    si                      ;// Save Caller's Regs Like 'C' Does
        push    di                      ;// Save Caller's Regs Like 'C' Does

		NextID EQU WORD PTR [BP - 2]    ;// Local Variable NextID
		Count  EQU WORD PTR [BP - 4]    ;// Local Variable Count (=loop)
        Device EQU WORD PTR [BP + 4]    ;// Caller's Device ID To Search For

        mov     NextID, 0               ;// Clear Out Local Variables
        mov     Count, 0                ;// Clear Out Local Variables

        jmp     StartLoop

TryAgain:
        add     Count, 1                ;// Increment IDSEL To Check

StartLoop:
        mov     ax, Count               ;// Max Valid IDSEL Is 20H
        cmp     ax, 20H
        jge     GetOut

        ;//
        ;// Read Device ID Registers From Next PCI Device
        ;//

		push    3                       ;// Read PCI Register 3 For This IDSEL
		push    0                       ;// Read Function 0 Of This Device
		push    Count                   ;// Read Device "Count" On This Bus
		push    0                       ;// Read Bus 0 Devices Only
		call    _ReadPCIByte            ;// Get It
		add     sp, 8                   ;// Adjust Caller Stack
		mov     NextID, ax              ;// Store Now, Still Need Other Half

		shl     NextID, 8               ;// Shift Upper Part Of DeviceID Over

		push    2                       ;// Read PCI Register 2 For This IDSEL
		push    0                       ;// Read Function 0 Of This Device
		push    Count                   ;// Read Device "Count" On This Bus
		push    0                       ;// Read Bus 0 Devices Only
		call    _ReadPCIByte            ;// Get It
		add     sp, 8                   ;// Adjust Caller Stack
		or      NextID, ax              ;// Merge With Upper Half

        mov     ax, Device              ;// Does It Matcher Caller's Device??
        cmp     NextID, ax              ;//
        jne     TryAgain                ;// Nope, Try Next PCI "Slot"

        mov     ax, Count               ;// Yep, Return Count In AX

GetOut:
        pop     di
        pop     si
        mov     sp,bp
        pop     bp
        ret     0
	
_Find_PCI_Device ENDP



        end

⌨️ 快捷键说明

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