I've written a simple algorithm which scans all possible PCI busses, devices and device functions of a system and stores the address where a device were detected. This works like a charm on emulators and some PCs here. But some other computers are going to hang up so I guess there are a few aspects where my code could be improved:
Code: Select all
scan_pci_bus:
push r9
push rax
push rbx
push rcx
push rdx
mov r9, 0x104F00 ; Memory address where we store the address of all devices we found
xor rax, rax ; This register will address the bus
xor rbx, rbx ; This register will address the device on the bus
xor rcx, rcx ; This register will address the function of a device
.bus_loop:
cmp eax, 0xFF
je .end
.device_loop:
cmp ebx, 0x0B
je .end_device_loop
.function_loop:
cmp ecx, 0x09
je .end_function_loop
push rax
xor rdx, rdx ; We need offset 0
call pci_config_read ; ( eax = bus, ebx = device, ecx = function, edx = offset);
cmp eax, 0xFFFF0000
jae .continue
pop rax
push rax
push rbx
push rcx
shl eax, 16
or eax, 0x80000000
shl ebx, 11
shl ecx, 8
or eax, ebx
or eax, ecx
mov [r9], rax
add r9, 0x08
pop rcx
pop rbx
.continue:
pop rax
inc ecx
jmp .function_loop
.end_function_loop:
xor ecx, ecx
inc ebx
jmp .device_loop
.end_device_loop:
xor ebx, ebx
inc eax
jmp .bus_loop
.end:
mov rax, 0xFFFFFFFFFFFFFFFF
mov [r9], rax
pop rdx
pop rcx
pop rbx
pop rax
pop r9
ret
;*
;
; eax => bus
; ebx => device
; ecx => function
; edx => offset
; eax <= retval
;
;*
pci_config_read:
cli
push rbx
push rcx
push rdx
shl eax, 16
or eax, 0x80000000
shl ebx, 11
shl ecx, 8
and edx, 0xFC
or eax, ebx
or eax, ecx
or eax, edx
mov dx, 0xCF8 ; PCI config address / register
out dx, eax
mov dx, 0xCFC ; PCI config data / register
in eax, dx
pop rdx
pop rcx
pop rbx
sti
ret
Thanks for any hints!