On Wed, Nov 5, 2008 at 12:35 PM, Myles Watson <[EMAIL PROTECTED]> wrote:

> I couldn't see a great spot to put this on the wiki, so I decided to attach
> it as a plain text file first.  I didn't want to spend too much time on
> formatting until we decide where it goes.
>
> This text file explains how the pci_device code works.


This time with attachment.

Myles

>
>
> Thanks,
> Myles
>
For many devices, there is only one PCI domain.  In this case, they call 
pci_domain_scan_bus.  It calls pci_scan_bus for all devfns (0x00-0xff) on 
link[0] starting with bus number 0.

pci_scan_bus scans a bus from min_devfn-max_devfn, and assigns bus numbers for 
any bridges it finds.  It starts by removing all the children of the bus, and 
putting them in a list of old_devices.  Then, for each devfn it searches the 
list (pci_get_dev) and probes the bus (pci_probe_dev.)  There are 4 
possibilities here: 00 not in the tree and not responding, 01 not in the tree 
and responding, 10 in the tree and not responding, and 11 in the tree and 
responding.

00 - The device is not there; skip it and all functions if it is function 0.
01 - The device responds but was not specified in the dts.  pci_probe_dev 
creates a new device with dtsname dynamic-<PATH> and fills in the device 
structure.
10 - The device is in the tree, but doesn't respond to probing.  The device is 
marked as disabled, and a warning message is issued.
11 - The device is in the tree and responds to probing.  pci_probe_dev uses the 
device struct returned from pci_get_dev, and fills in the information.

Now that the devices have been probed from min_devfn to max_devfn, any leftover 
children in the old_devices list are printed with a warning.

At this point all of the children on the bus have been found and assigned 
device structures.  Each child that has a dev_phase3_scan method (bridges) is 
then scanned and passed the current bus number (curr_bus) to number subordinate 
buses.

The return value for the function is the curr_bus number, which is the highest 
bus number that has been assigned so far.

Bridge Scanning

The default function for scanning subordinate pci busses (phase3_scan) is 
pci_scan_bridge.  It takes a device and the curent bus number as parameters.  
It simply calls do_pci_scan_bridge with pci_scan_bus as a parameter.  
do_pci_scan_bridge takes a scanning function as a parameter so that devices can 
use the basic functionality with a custom bus scanning function, if needed.


do_pci_scan_bridge gets the bus to be enumerated from dev->link[0] and sets 
dev->links to 1.  ** I'm not sure why it sets this to one here! **  Then it 
sets the starting child bus number (bus->secondary) to the next bus number, and 
the and the ending child bus number (bus->subordinate) to 0xff so that all of 
them get enumerated.  Note that this is only in the bus structure, not in 
hardware yet.

Next the device is disabled and the status bits are cleared so that the devices 
do not generate or respond to traffic while they are being configured.  Now the 
bus numbers are written to hardware, and the do_scan_bus function is called to 
find the child devices of the bridge.

After the subordinate buses are scanned, the true value for the maximum bus 
number of the child (bus->subordinate) is known, so it is set in hardware and 
the device is returned to its previous enable state.

Information in the device struct set during probing

pci_probe_dev initializes many fields in the device struct based on information 
that the hardware returns.  It is passed a pointer to the device struct from 
the dts tree, or NULL if this devfn had no matching device.

If there was no matching device but a device responds at that devfn, a new one 
is created as a child of the currently scanned bus.  Otherwise no child is 
added, and NULL is returned.

If there was a matching device, its magic enable sequence is called if defined. 
 Some devices require initialization before they will respond to PCI 
configuration cycles.  They will not be found if there is not a matching device 
in the dts. If the device does not respond, it is disabled and the function 
returns.

Responding devices have their configuration space information (header type, 
class, status, revision, etc.) saved in the device structure.  They also get 
pci_ops set if they were not set in the dts.

set_pci_ops uses the information from the device header to decide what "driver" 
(set of functions implemented by the device) to use.  There are three ways the 
device can get a driver:

1. It has one assigned in the dts
2. It matches a driver in the list all_device_operations 
(find_device_operations) 
3. It gets a default driver based on if it is a bridge, normal, or cardbus 
device.

If it is a bridge, get_pci_bridge_ops assigns the ops based on the values of 
CONFIG_<BUS_NAME>_PLUGIN_SUPPORT.   

 

--
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to