Ram initialization and small c.

Eric W. Biederman ebiederman at lnxi.com
Fri Feb 14 20:24:00 CET 2003


"Ronald G. Minnich" <rminnich at lanl.gov> writes:

> On 14 Feb 2003, Eric W. Biederman wrote:
> 
> > So what I am looking at:
> > 
> > The current pci bus scan starts with a root pci bus device.
> > And then finds the devices on that bus, and the recursively scans
> > the sub busses.
> 

O.k.  Getting into specifics:
>From our pci.h, the current operations we have for a pci device.

struct pci_dev_operations {
	void (*read_resources)(struct pci_dev *dev);
	void (*set_resources)(struct pci_dev *dev);
	void (*init)(struct pci_dev *dev);
	unsigned int (*scan_bus)(struct pci_dev *bus, unsigned int max);
};

> I'm still not getting it. 
> 
> For some chips, LinuxBIOS needs to call some chip-specific code for that
> device BEFORE the pci bus scan, or resource allocation gets done
> incorrectly. How can we structure the code so that the pre-pci init
> functions work in a reasonable way that most people can understand?  The
> current superio stuff does this, and the information to drive it is
> contained in the superio file. If you have code that needs to be called
> before the PCI scan, you initalize the structure member to point to a
> function. Same for after PCI scan, same for right before hardwaremain()  
> exits. You can look at the superio.c file for the given chip and see if
> this pre-pci-scan function exists and is called.


O.k.  The superio code I definitely figure is a step in that direction.

This discussion must get into nitty gritty specifics if we are going to
reach a consensus.

What we currently do:
pci_enumerate();
pci_configure();
pci_initialize();

In pci_enumerate(),
  If a device is in the hard coded list it is placed into the list of pci devices
  even if it does not exist.  This allows invisible devices on the motherboard to
  be configured.
  
  In addition each device is assigned a set of operations.  set_pci_ops
  does that work.  
  
  set_pci_ops first looks through a table of device drivers and listed
  by vendor and device id to see if it can find a specific driver for that
  device.  If a driver is found it uses those device methods.  Otherwise
  depending if it is a bridge or a normal pci device a default set of
  methods is assigned.
  
  After pci_scan_bus finishes enumerating the devices on a bus.  It looks
  at each child device to see if it has a scan_bus method.  And if so it 
  calls  child->ops->scan_bus().  Which is usually just pci_scan_bus again.
  

In pci_configure.  
   The device tree is walked again.  And for each device it's read_resources
   operation is called, to find the bar's on that device.  read_resources
   allows for the presence of non standard bars.  Each bar read_resources returns
   can either be a fixed resource, that must be catered to.  Or a resource needing
   to be assigned a value.

   Then a second pass is made to the tree and set_resources is called on each device.

   For bridges, read_resources, and set_resources are recursive.

In pci_initialize.
   The device tree is walked one last time, and this time the init() method
   of each device is called.


> I like the self-contained nature of the superio.c files (I grabbed all
> those ideas from Plan 9). Does this seem desirable to people? 

Yes.  Self contained is good.  The one part my newer pci code that is
lacking that you did well on the superio code is a way to build the static
device information.  I suspect we want to allow a different structure for
each different device, but basically I like the superio directive.

> If so, can
> we expand it to the south and north bridges so as to replace the current
> ad-hoc mechanisms?

Look at what I have done with pci.  Essentially I have already done
that.  Everything but making the configuration manageable.

> If this mechanism is not desirable, how would it change? Would the 
> .c files continue to be self-contained or would we start getting into more 
> linker sets and other magic stuff (which, as you can tell, worries me as 
> it does confuse people). 

The only magic thing that I might touch with a linker is building the
table of devices.  But that is to make things more self contained.

> I would appreciate some feedback from the other committers and 
> developers.

Agreed.  Just Eric talking is imperfect.

I just looked through the LinuxBIOS tree at every superio.c.  And perhaps I
missed something but I did not see a single superio file that used
more than one of the three functions defined, and none of them used
the pre pci function.

So all of those I can straight forwardly transformed so their init or
finishup method is converted into a pci init method and called from
pci_initialize().

For the hypothetical case of needing a device that is called before
the rest of the pci initialization, it can be forced into the device
tree ahead of everything else.  And it's scan_bus method can do what
special magic is required.

Similarly for the hypothetical case of needing a device that is called
after everything else, a dummy device can be inserted way at the
bottom and the end of the pci device tree, so that it's init method
will be called last.

So it is possible in a nasty way to cope with those hypothetical
situations.  Buying time for a clean fix to be put into the LinuxBIOS
tree.

If you have specific examples of things that need to be done I am
quite willing to discuss them and how I would fit it into the new
frame work.

The code flow I am confident of.  The mechanism to configure it that I
do not currently have that problem solved.  But I suspect we can use
something like the current superio configuration to statically build
parts of the device tree.

Eric




More information about the coreboot mailing list