O.k. I have been trying to find a way with a minimum of hard codes
to handle two specific problems.
1) Multiple PCI bridges whose speed I need to auto-detect.
2) Generate a correct MPtable with multiple IO-APICs on
multiple buses.
I have enough pci buses that I cannot count on bus:devfn being
constant after I power of the machine. No one has yet plugged in
a generic pci bridge and caused me havoc yet but the chances are
getting increasingly great that someone will.
Case 1 is easy. I just need to do a lookup in a table of drivers by
vendor and deviceid and I can find some extra initialization code to run.
Case 2 is the hard one. This needs a generic way of running
motherboard agnostic code, with motherboard specific information.
Earlier I played with this problem and came up with a generic
infrastructure. So generic in fact it actually wasn't useful. The
signficant realization from that earlier effor is that the
configuration information that is needed for various tasks is specific
to those tasks, and cannot be represented generically even if you can
hang it on a generic frame.
With a specific problem to solve the problem became simpler.
First there is only one view point that matters in LinuxBIOS. The
view point needed for setting the up the system. Or specifically
from a pci perspective, the configuration data view point.
Practically what I need is the standard pci device tree with extra
information hooked onto it.
Roughly:
pci_dev == pci_bus
|
pci_dev (dev 0 fn 0)
|
pci_dev (dev 1 fn 0)
|
pci_dev (dev 2 fn 0)
|
pci_dev (dev 3 fn 0)
|
ioapic ->ioapic irq route to (dev 0 fn 0)
->ioapic irq route to (dev 0 fn 1)
->ioapic irq route to (dev 0 fn 2)
Where roughly we are dealing with thre structures.
struct pci_dev
struct pci_bus
and
struct configuration
struct configuration
is organized as a linked list of configuration items
for a specific device to process. Struct configuration either
contains a union, or is the header for several different kinds of
specific configuration information.
A structure with all of the options could be built but a link list
allows for the same configuration on two different pieces of hardware
to be represented the same way. Allowing for some amount of device
independent code, to be written.
The big change is that pci_enumerate will start with a partially
populated tree, and merge it's scan data with the pre supplied data
already present, in the prepopulated tree. With irq tables there
won't be a lot missing but I probably should treat them as if there
was.
For those worried about bloat this is all I have on the p4dpr,
It's 18 pci devices true but the number is still quite manageable.
[root@p4dpr root]# lspci -n
00:00.0 Class 0600: 8086:2540 (rev 02)
00:00.1 Class ff00: 8086:2541 (rev 02)
00:02.0 Class 0604: 8086:2543 (rev 02)
00:1d.0 Class 0c03: 8086:2482 (rev 02)
00:1d.1 Class 0c03: 8086:2484 (rev 02)
00:1d.2 Class 0c03: 8086:2487 (rev 02)
00:1e.0 Class 0604: 8086:244e (rev 42)
00:1f.0 Class 0601: 8086:2480 (rev 02)
00:1f.1 Class 0101: 8086:248b (rev 02)
00:1f.3 Class 0c05: 8086:2483 (rev 02)
01:1c.0 Class 0800: 8086:1461 (rev 03)
01:1d.0 Class 0604: 8086:1460 (rev 03)
01:1e.0 Class 0800: 8086:1461 (rev 03)
01:1f.0 Class 0604: 8086:1460 (rev 03)
03:01.0 Class 0280: 14fc:0000 (rev 01)
03:04.0 Class 0200: 8086:100d (rev 02)
04:01.0 Class 0300: 1002:4752 (rev 27)
04:02.0 Class 0200: 8086:1229 (rev 0d)
After merging in pci_enumerate which preserves all of the motherboard
specific information. Then the device will be looked up by vendor and
device id. This will find any motherboard independent code that knows
a little more than the generic pci code how to setup the device.
Currently I am looking at the functions:
struct pci_dev_operations {
void (*read_resources)(struct pci_dev *dev);
void (*set_resources)(struct pci_dev *dev);
void (*init)(struct pci_dev *dev);
};
As it is very common to have devices with extra resources/base registers.
The init method is called after all of the devices have had their
resources allocated to them, to do some final device initialization.
This seems to be the only sane way to remove a dangerous pile of hard
codes. I will try and implement this in the next couple of days to
see how how difficult this really will be.
Eric