PCI

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
lemonyii
Member
Member
Posts: 153
Joined: Thu Mar 25, 2010 11:28 pm
Location: China

PCI

Post by lemonyii »

hi again,
i'm starting working on my pci code now. i read some by searching here and http://wiki.osdev.org/PCI#Class_Codes
and i write some code myself. but all the vendor&device id except the first are 0xffffffff and all the class are 0.
what's wrong with my code? did i missed smth?

Code: Select all

extern i64 pci_init(){
	register u64	i,j,val;
	for(i=0x80000000; i<0x80ffff00; i+=0x100){
		outdword(0xCF8, i);
		val = indword(0xCFC);
		if(val == 0xffffffff) break;
		outdword(0xCF8, i+0x08);
		val = indword(0xCFC);
		val >>= 24;
		j = 0;
		while(val!=pci_class_table[j].class && pci_class_table[j].class) j++;
		if(pci_class_table[j].class){
			printk(COLOR_FG, pci_class_table[j].dscrpt);
			printk(COLOR_FG, L"\n");
		}
	}
	return 0;
}
thx
Enjoy my life!------A fish with a tattooed retina
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: PCI

Post by Combuster »

Basic data flow examination shows that the first unoccupied slot stops the code, and that you are not printing the class code.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
lemonyii
Member
Member
Posts: 153
Joined: Thu Mar 25, 2010 11:28 pm
Location: China

Re: PCI

Post by lemonyii »

Combuster wrote:Basic data flow examination shows that the first unoccupied slot stops the code, and that you are not printing the class code.
do you mean

Code: Select all

if(val == 0xffffffff) break;
if i quote this line, it will all result in class = 0.
Enjoy my life!------A fish with a tattooed retina
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: PCI

Post by Combuster »

Did you ever consider that neither alternative is correct? :shock:


I suggest you practice some debugging skills. Homework: implement a red-black tree in userspace without asking for help. It's a first year's assignment at the local college, and it should teach you how to solve problems with non-trivial code. You will keep getting stuck in OS development if you can't systematically trace the origin of a bug.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: PCI

Post by gerryg400 »

Code: Select all

      if(val == 0xffffffff) break;
Do you know what break does?
- gerryg400
If a trainstation is where trains stop, what is a workstation ?
User avatar
lemonyii
Member
Member
Posts: 153
Joined: Thu Mar 25, 2010 11:28 pm
Location: China

Re: PCI

Post by lemonyii »

Homework: implement a red-black tree in userspace without asking for help. It's a first year's assignment at the local college,
in fact it IS the first year of my college :mrgreen: but i did this when i was 15 or 16.
i think the reason why i got faults is not my code, but the way i understand PCI.
as to the break, i remember a book referred that if you got 0xffffffff in vendor id and device id, it is a null slot and you may regard it as the end of you emuration.
and i think that it does not matter if i emurate by BFS or DFS if a check all the devices, right?
thx
Enjoy my life!------A fish with a tattooed retina
User avatar
zity
Member
Member
Posts: 99
Joined: Mon Jul 13, 2009 5:52 am
Location: Denmark

Re: PCI

Post by zity »

lemonyii wrote:as to the break, i remember a book referred that if you got 0xffffffff in vendor id and device id, it is a null slot and you may regard it as the end of you emuration.
Yes 0xFFFF (or even 0x0 on some broken boards) is an empty slot, but you should NOT stop enumerate. Just because you hit an empty slot doesn't mean that the rest of the slots are empty too.
User avatar
lemonyii
Member
Member
Posts: 153
Joined: Thu Mar 25, 2010 11:28 pm
Location: China

Re: PCI

Post by lemonyii »

but why do i still got all class=0 with that line deleted? should i do something else?
Enjoy my life!------A fish with a tattooed retina
User avatar
Neolander
Member
Member
Posts: 228
Joined: Tue Mar 23, 2010 3:01 pm
Location: Uppsala, Sweden
Contact:

Re: PCI

Post by Neolander »

What zity says is that if you hit an empty slot, the correct thing to do is to move to the next item, not to stop enumerating slots, because if slot n is empty it does not mean that slot n+1 will be empty too. break means getting out of a for() or a while() statement. With break, the implemented behavior is "if slot n is empty, stop searching".
What you meant is probably continue, which actually implements "if slot n is empty, ignore it and check slot n+1".

However, I don't know about PCI, it's just some intuitive analysis of the various posts around here, so I may be misunderstood.
Last edited by Neolander on Thu May 06, 2010 12:13 am, edited 1 time in total.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: PCI

Post by Brendan »

Hi,
lemonyii wrote:as to the break, i remember a book referred that if you got 0xffffffff in vendor id and device id, it is a null slot and you may regard it as the end of you emuration.
and i think that it does not matter if i emurate by BFS or DFS if a check all the devices, right?
thx
For PCI there's up to 256 buses, up to 32 devices per bus and up to 8 functions per device. If you scan all functions in all devices on all buses it'll add up to 65536 checks and take far too long (because even for PCI devices, accessing I/O ports isn't fast), and in some cases you'll get wrong information for using information that doesn't exist (e.g. trying to get information for a device's second function when the device is a "single function" device).

For PCI devices, there's a flag in configuration space (bit 7 in the "Header Type" field) that says if the device is a multi-function device or not. If this bit isn't set then there's only one function and you don't need to check for any more (and shouldn't attempt to check for more functions). If the bit is set, then you check the functions in order and stop at the first unimplemented function.

For the PCI buses, there's host controller/s and PCI bridges. You start checking with the host controller/s PCI bus number, and when you find a PCI bridge you find the "secondary bus number" from it's configuration space and scan that PCI bus too. In that way you discover all PCI buses without checking any PCI buses that don't exist. The first PCI host controller is always "bus 0, device 0, function 0", and if this device is a multi-function device then additional host controllers will be part of the same device.

For devices within a bus, you do have to check all 32 of them.

It's usually easier to use at least 2 pieces of code for this - one piece to scan each device on a specific bus and determine if each device is multi-function or not, and one to determine if a specific function on a specific device on a specific bus is a PCI bridge or host controller (and call the first "scan_bus(secondary_bus_number)" piece of code if it is).

For example:

Code: Select all

void scan_PCI_bus(uint8_t bus_number) {
    uint8_t device_number;
    uint8_t function_number;

    for(device_number = 0; device_number < 32; device_number++) {
        if( device_exists ) {
            function_number = 0;
            if( device_is_multifunction ) {
                while( (handle_PCI_function(bus_number, device_number, function_number) == 0) && (function_number < 7) {
                    function_number++;
                }
            } else { // Device is single-function
                handle_PCI_function(bus_number, device_number, function_number);
            }
        }
    }
}

int handle_PCI_function(uint8_t bus_number, uint8_t device_number, uint8_t function_number) {
    uint8_t secondary_bus_number;

    if( function_exists ) {

        // Do other stuff here (display information about the device??)

        if( (device_is_host_controller) || (device_is_PCI_to_PCI_bridge) ) {
            secondary_bus_number = get_secondary_bus_number(bus_number, device_number, function_number);
            scan_PCI_bus(secondary_bus_number);
        }
        return 0;
    } else {
        return 1;
    }
}
Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
lemonyii
Member
Member
Posts: 153
Joined: Thu Mar 25, 2010 11:28 pm
Location: China

Re: PCI

Post by lemonyii »

thx you all above!
i can read out many none zero class in qemu and vmware now.(but not in bochs :shock: )the next thing i got to do is to identify them.
is the class list at http://wiki.osdev.org/PCI#Class_Codes the latest? i built a table according to it.
one more question:
(generally speaking) is there much difference between devices(of same subclass) of different vendor?
say, can i use a same driver for device of different vendor?
or what kind of device should write very(above 20%) different code?
thx
Enjoy my life!------A fish with a tattooed retina
User avatar
lemonyii
Member
Member
Posts: 153
Joined: Thu Mar 25, 2010 11:28 pm
Location: China

Re: PCI

Post by lemonyii »

http://wiki.osdev.org/PCI#Class_Codes
It seems that there is a little fault in SubClass Codes Table:
see CLASS 0x06, there are two subclass 0x00, one of which is PCI-to-PCI bridge,
i think the subclass should be 0x04 right?
Enjoy my life!------A fish with a tattooed retina
User avatar
lemonyii
Member
Member
Posts: 153
Joined: Thu Mar 25, 2010 11:28 pm
Location: China

Re: PCI

Post by lemonyii »

i can read pci configuration header now.
but i got a few devices in vmware and qemu,even less in bochs.
i dont care other things but IOAPIC, because i hope to configure it without ACPI but through PCI. is it possible to do this?
will it be much more on real machine? how many do you often get?
in vmware:
inqemu
inqemu
in qemu:
in qemu
in qemu
Enjoy my life!------A fish with a tattooed retina
User avatar
zity
Member
Member
Posts: 99
Joined: Mon Jul 13, 2009 5:52 am
Location: Denmark

Re: PCI

Post by zity »

Normally emulators don't have more than a few PCI devices, so it looks fine.

The only connection between the I/O APIC and the PCI bus is that the I/O APIC receives the interrupts from the PCI devices. In other words, you cannot initialize the I/O APIC though the PCI bus, since the I/O APIC is not a part of the PCI bus.

To configure the I/O APIC, you either have to parse the ACPI or the MP tables.
User avatar
lemonyii
Member
Member
Posts: 153
Joined: Thu Mar 25, 2010 11:28 pm
Location: China

Re: PCI

Post by lemonyii »

so could i use device in pci mode without IOAPIC?
and where to parse the ACPI or MP table?
i do have little knowledge about ACPI.
thx
Enjoy my life!------A fish with a tattooed retina
Post Reply