BIOS PCI enumeration question

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.
Post Reply
stdcall
Member
Member
Posts: 78
Joined: Thu Mar 14, 2013 1:30 am

BIOS PCI enumeration question

Post by stdcall »

Hey.
I'm a bit confused about the enumeration process of the PCI in x86 BIOS.
What I don't understand, is what is finally written to the BAR's by the BIOS.
In few places in the internet, It states that before reading the size mask, the BAR value is read and restored to the BAR afterwards.
And in other places I read that the BIOS write's the actual mapped memory address back to the BAR.

If the first is true,
How does the PCI device knows where it has been mapped ?

Thanks
Ramon
“Meaningless! Meaningless!”
says the Teacher.
“Utterly meaningless!
Everything is meaningless.” - Ecclesiastes 1, 2

Educational Purpose Operating System - EPOS
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: BIOS PCI enumeration question

Post by Brendan »

Hi,
mellowcandle wrote:I'm a bit confused about the enumeration process of the PCI in x86 BIOS.
What I don't understand, is what is finally written to the BAR's by the BIOS.
In few places in the internet, It states that before reading the size mask, the BAR value is read and restored to the BAR afterwards.
And in other places I read that the BIOS write's the actual mapped memory address back to the BAR.
The lowest bits of the BAR's address part are hardwired to zero to indicate the size (and minimum alignment) of the area that the device needs. If the BAR's address part contains 0x00000000 you can't know how many bits are hardwired to zero with that information alone. You'd have to write "all ones" and read it back to determine how many bits are hardwired to zero. If you read it back and get (e.g.) 0xFFFF0000 then you know (or can determine - e.g. using "not then increment") that the size required by the device is 0x00010000 bytes. Of course if you don't want to trash whatever was in the BAR beforehand (which is relatively typical for an OS) then you'll need to save the original contents and restore it after.

When a computer is first turned on the PCI devices (and their BARs) aren't configured yet, and the PCI devices are essentially disabled (note: there are a few exceptions to this, but that's the general idea). It's firmware's responsibility to examine the PCI devices, allocate areas of the physical address for them, configure them (their BARs, IRQs, etc), and enable them. For fun I'm going to call this "PCI device resource assignment".

Note that an OS might just rely on "PCI device resource assignment" done by firmware; or it might do "PCI device resource assignment" itself from scratch. It turns out that in some cases (hot-plug PCI) the OS mostly has to be able to do it itself (at least partially).

How "PCI device resource assignment" works is a little complicated; as there's other constraints to worry about. Specifically; where bridges are involved the bride has a "range of addresses to forward from primary bus to secondary bus", which means that all devices on any sub-bus need to be configured to use the same range. The other complication is that PCI devices require "natural alignment" - an "X byte" area has to be aligned on an "X byte" boundary.

You could assign physical address space to devices one at a time in the order they're found; but that can cause a lot of space wasted for aligning areas. For example, if the first device wants 128 MiB, the second device wants 1 MiB and the third device wants 128 MiB, then that middle area is going to cause 127 MiB of the physical address space to be wasted. Much smarter is to examine a sub-bus and arrange the areas in order of smallest to largest (or from largest to smallest) to minimise space wasted for alignment.

This is done recursively, using "depth first" (e.g. resources assigned to child sub-buses before you start worrying about parent sub-buses), while configuring bridges as you go.

The other thing that complicates it is that there may not be enough space in the first 4 GiB of the physical address space (e.g. maybe 3 GiB of it is RAM, and there's normally also things like ROM/firmware, APICs, HPET, etc). If you need more space for PCI devices, then you have to look at which devices (and bridges) support 64-bit addresses. If anything on a sub-bus can't handle 64-bit addresses then everything on that sub-bus must go in the first 4 GiB of the physical address space.

As I'm sure you can imagine, it gets messy. ;)


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
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: BIOS PCI enumeration question

Post by SpyderTL »

mellowcandle wrote: How does the PCI device knows where it has been mapped?
The PCI registers (including the BAR registers) are actually physically located on the PCI device, so when the BIOS changes a devices address, it immediately knows its new address.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
stdcall
Member
Member
Posts: 78
Joined: Thu Mar 14, 2013 1:30 am

Re: BIOS PCI enumeration question

Post by stdcall »

Thanks ! now it's clear.
“Meaningless! Meaningless!”
says the Teacher.
“Utterly meaningless!
Everything is meaningless.” - Ecclesiastes 1, 2

Educational Purpose Operating System - EPOS
Post Reply