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 + -
显示快捷键?