Page 1 of 1

PCI Enumeration can't find any devices

Posted: Wed Jul 05, 2017 9:48 pm
by Postmann
Hello :)

I have a problem with my PCI enumeration. Somehow it's returning only 0xFFFF for the vendor ID (in AX) for every bus:

Code: Select all

PCI_CONFIG_ADDRESS=0x0CF8;
PCI_CONFIG_DATA=0x0CFC;

for (BUS=0, BUS<256, BUS++) {
		for (DEV=0, DEV<32, DEV++) {
			for (FN=0, FN<8, FN++) {
				asm {
					mov     ax, 32768           
					or      al, [BUS]
					shl     eax, 16                 

					mov     ax, [DEV]
					shl     ax, 11                  
					mov     al, [FN]
					or      ah, al                  
					mov     al, [VEN_ID]

					mov     dx, [PCI_CONFIG_ADDRESS]
					out     dx, eax                 

					mov     dx, [PCI_CONFIG_DATA]            
					in      eax, dx   
					mov 	[RESULT], eax             	
				}
I was testing this on Bochs and without my kernel on FreeDOS and DosBox, it doesn't work on either of them. But why? I don't see any problems with the code.

Re: PCI Enumeration can't find any devices

Posted: Wed Jul 05, 2017 9:51 pm
by ~
Why do you use 32768 as the first value in AX?

Re: PCI Enumeration can't find any devices

Posted: Wed Jul 05, 2017 9:58 pm
by Postmann
I was trying something I found here:
https://www.waste.org/~winkles/hardware/pci.htm

Re: PCI Enumeration can't find any devices

Posted: Wed Jul 05, 2017 10:09 pm
by Brendan
Hi,
Postmann wrote:I was testing this on Bochs and without my kernel on FreeDOS and DosBox, it doesn't work on either of them. But why? I don't see any problems with the code.
Change this part:

Code: Select all

					mov     dx, [PCI_CONFIG_ADDRESS]
					out     dx, eax

					mov     dx, [PCI_CONFIG_DATA]            
					in      eax, dx
					mov 	[RESULT], eax
To this:

Code: Select all

					mov     dx, PCI_CONFIG_ADDRESS
					out     dx, eax

					mov     dx, PCI_CONFIG_DATA
					in      eax, dx
					mov 	[RESULT], eax
~ wrote:Why do you use 32768 as the first value in AX?
That's the "enable" flag (that ends up at bit 31).


Cheers,

Brendan

Re: PCI Enumeration can't find any devices

Posted: Wed Jul 05, 2017 10:12 pm
by ~
You could first make a program to list the bit fields you are generating. That could be the first problem if it isn't really producing the values you want for bus, device, function.

You could also see the PCI example from Chris Giese, it seems to be better. It has helped me in the past. I have even been able to get the base address of graphics modes with it:
http://devel.archefire.org/mirrors/my.e ... /pnp/pci.c

I translated that code to assembly several years ago. I have attached it, maybe it can serve as an additional example.

Re: PCI Enumeration can't find any devices

Posted: Wed Jul 05, 2017 10:40 pm
by Postmann
Brendan wrote:Change this part to this ...
I tried adding the address manually, since without the brackets it generates some weird erros:

Code: Select all

mov     ax, 32768    
or      al, [BUS]
shl     eax, 16                 

mov     ax, [DEV]
shl     ax, 11                  
mov     al, [FN]
or      ah, al                  
mov     al, [VEN_ID]

cli
mov     dx, 0x0CF8
out     dx, eax                 

mov     dx, 0x0CFC        
in      eax, dx   
mov 	[RESULT], eax             	
sti
No change though.

Re: PCI Enumeration can't find any devices

Posted: Thu Jul 06, 2017 1:04 am
by Brendan
Hi,
Postmann wrote:

Code: Select all

mov     ax, 32768    
or      al, [BUS]
shl     eax, 16                 

mov     ax, [DEV]
shl     ax, 11                  
mov     al, [FN]
or      ah, al                  
mov     al, [VEN_ID]

cli
mov     dx, 0x0CF8
out     dx, eax                 

mov     dx, 0x0CFC        
in      eax, dx   
mov 	[RESULT], eax             	
sti
No change though.
That should work, unless there's a bug somewhere else (not in the assembly itself). One possibility is that whichever compiler you're using doesn't know that you're accessing variables and keeps the values in registers (without updating the values in memory).

I'd recommend posting a disassembly of whatever the compiler generated.

Note that there is an unrelated bug (you shouldn't look at functions 1 to 7 unless the device says it is a multi-function device because if you do the information for "function 0" can be return for functions 1 to 7).

Also (for performance) you could do something like this:

Code: Select all

    for(uint32_t i = 0x80000000; i <= 0x80000000 | 255<<24 | 31<<11 | 7<<8 | 0; i += 1 << 8) {
        asm {
            mov eax,[i]
            cli
            mov dx, 0x0CF8
            out dx, eax                 
            mov dx, 0x0CFC        
            in  eax, dx   
            mov [RESULT], eax
            sti
        }

Cheers,

Brendan

Re: PCI Enumeration can't find any devices

Posted: Thu Jul 06, 2017 9:26 am
by Postmann
This is the generated assembly:
https://pastebin.com/v8ScCtRQ

This is the most important part:

Code: Select all

	mov	WORD PTR [rbp-60], 3320
	mov	WORD PTR [rbp-62], 3324
.L3:
	mov	WORD PTR [rbp-72], 0
.L4:
	mov	BYTE PTR [rbp-73], 0
.L5:
#APP
# 55 "DEVICE.c" 1
	mov     ax, 32768    
# 0 "" 2
# 56 "DEVICE.c" 1
	or      al, [BYTE PTR [rbp-69]]
# 0 "" 2
# 57 "DEVICE.c" 1
	shl     eax, 16                 
# 0 "" 2
# 58 "DEVICE.c" 1
	mov     ax, [WORD PTR [rbp-72]]
# 0 "" 2
# 59 "DEVICE.c" 1
	shl     ax, 11                  
# 0 "" 2
# 60 "DEVICE.c" 1
	mov     al, [BYTE PTR [rbp-73]]
# 0 "" 2
# 61 "DEVICE.c" 1
	or      ah, al                  
# 0 "" 2
# 62 "DEVICE.c" 1
	cli
# 0 "" 2
# 63 "DEVICE.c" 1
	mov     dx, 0x0CF8
# 0 "" 2
# 64 "DEVICE.c" 1
	out     dx, eax                 
# 0 "" 2
# 65 "DEVICE.c" 1
	mov     dx, 0x0CFC        
# 0 "" 2
# 66 "DEVICE.c" 1
	in      eax, dx   
# 0 "" 2
# 67 "DEVICE.c" 1
	mov  [DWORD PTR [rbp-68]], eax              
# 0 "" 2
# 68 "DEVICE.c" 1
	sti
# 0 "" 2
#NO_APP
	mov	eax, DWORD PTR [rbp-68]
	mov	eax, eax
	movzx	eax, ax
	cmp	rax, 65535
	je	.L20
	;DEVICE FOUND!
	mov	edi, -1
	jmp	.L9

Re: PCI Enumeration can't find any devices

Posted: Fri Jul 07, 2017 5:29 am
by LtG
It seems you've modified your code from what's in the OP but not included that in your last post.. Also mentioning what the current issue is also helps, even if it's still the same..

Not sure if I'm looking at your code correctly but your initial code has this:
mov al, [VEN_ID]

But most recent doesn't seem to have it? So at:
or ah, al
cli

The "or ah, al" leaves "al" with presumably the "FN"?

Also, have you tried debugging, checking what exactly is in EAX before the OUT? And what the response is with IN? Might be useful..

Re: PCI Enumeration can't find any devices

Posted: Fri Jul 07, 2017 6:17 pm
by ggodw000
hire a detective :D

Re: PCI Enumeration can't find any devices

Posted: Sat Jul 08, 2017 12:21 am
by Postmann
Urgs ... this works:

Code: Select all

mov     ax, 32768    
or      al, [BUS]
shl     eax, 16                 

mov     ax, [DEV]
shl     ax, 11                                 

cli
mov     dx, 0x0CF8
out     dx, eax                 

mov     dx, 0x0CFC        
in      eax, dx   
mov 	[RESULT], eax             	
sti
I guess I shouldn't try my stuff with DosBox anymore. It works with a virtual FreeDOS-machine though and with my own kernel. Thanks anyway. :oops:

Re: PCI Enumeration can't find any devices [SOLVED]

Posted: Sun Jul 09, 2017 9:43 am
by SpyderTL
Be sure to mark your thread as [SOLVED] so that others can use it in the future to troubleshoot their own problems.

I'm not sure if I can change the thread title just by replying to your thread, but I'll give it a shot. If not, you can go back to your initial post and change the title there.

Re: PCI Enumeration can't find any devices

Posted: Sun Jul 09, 2017 9:46 am
by BrightLight
Postmann wrote:

Code: Select all

mov     dx, 0x0CF8
out     dx, eax                 

mov     dx, 0x0CFC        
in      eax, dx   
mov 	[RESULT], eax             	
sti
There's no need to disable/enable hardware interrupts while accessing the PCI configuration space, as there is never a reason for an interrupt handler to access the PCI configuration space registers. Even if the interrupt handler of a PCI device should read PCI configuration status registers or such, it shouldn't do so in the handler itself, and rather just notify the driver by setting a flag.