Next: Interrupts and Interrupt Handling
Up: PCI Fixup
Previous: Finding Out How Much
Like all memory the PCI I/O and PCI memory spaces are finite, and to some
extent scarse.
The PCI Fixup code for non-Intel systems (and the BIOS code for Intel
systems) has to allocate each device the amount of memory that it is
requesting in an efficient manner.
Both PCI I/O and PCI Memory must be allocated in a device in a naturally
aligned way. For example, if a device asks for 0xB0 of PCI I/O space
then it must be aligned on an address which is a multiple of 0xB0.
In addition to this, the PCI I/O and PCI Memory bases for
any given bridge must be aligned on 4K and on 1Mbyte
boundaries respectively.
Given that the address spaces
for downstream devices must lie within all of the
upstream PCI-PCI Bridge's memory ranges for any given
device, it is a somewhat difficult problem to allocate
space efficiently.
The algorithm that Linux uses relies on each device described
by the bus/device tree built by the PCI Device Driver being
allocated address space in ascending PCI I/O memory order.
Again a recursive algorithm is used to walk the pci_bus and pci_dev
data structures built by the PCI initialisation code.
Starting at the root PCI bus (pointed at by pci_root ) the BIOS fixup
code:
- Aligns the current global PCI I/O and Memory bases on 4K
and 1 Mbyte boundaries respectively,
- For every device on the current bus (in ascending PCI I/O
memory needs),
- allocate it space in PCI I/O and/or PCI Memory,
- move on the global PCI I/O and Memory bases by the
appropriate amounts,
- Enable the device's use of PCI I/O and PCI Memory,
- Allocate space recursively to all of the busses
downstream of the current bus. Note that this will
change the global PCI I/O and Memory bases,
- Align the current global PCI I/O and Memory bases on 4K
and 1 Mbyte boundaries respectively and in doing so
figure out the size and base of PCI I/O and PCI Memory
windows required by the current PCI-PCI bridge,
- Program the PCI-PCI bridge that links to this bus with
its PCI I/O and PCI Memory bases and limits,
- Turn on bridging of PCI I/O and PCI Memory accesses in
the PCI-PCI Bridge. This means that if any PCI I/O or PCI Memory
addresses seen on the Bridge's primary PCI bus which are within
its PCI I/O and PCI Memory address windows will be bridged onto
its secondary PCI bus.
Taking the PCI system in Figure on
page as our example the
PCI Fixup code would set up the system in the following way:
- Align the PCI bases
- PCI Memory is 0x4000 and
PCI Memory is 0x100000. This allows the PCI-ISA bridges
to translate all addresses below these into ISA address cycles,
- The Video Device
- This is asking for
0x200000 of PCI Memory and so we allocate it that
amount starting at the current PCI Memory base of
0x200000 as it has to be naturally aligned to
the size requested.
The PCI Memory base is moved to
0x400000 and the PCI I/O base remains at 0x4000.
- The PCI-PCI Bridge
- We now cross the PCI-PCI Bridge and
allocate PCI memory there, note that we do not need to
align the bases as they are already correctly aligned:
- The Ethernet Device
- This is asking for 0xB0 bytes
of both PCI I/O and PCI Memory space. It gets allocated PCI
I/O at 0x4000 and PCI Memory at 0x400000.
The PCI Memory base is moved to
0x4000B0 and the PCI I/O base to 0x40B0.
- The SCSI Device
- This is asking for 0x1000 PCI Memory
and so it is allocated it at 0x401000 after it has been
naturally aligned. The PCI I/O base is still 0x40B0 and
the PCI Memory base has been moved to 0x402000.
- The PCI-PCI Bridge's PCI I/O and Memory Windows
- We now return to
the bridge and set its PCI I/O window at between 0x4000 and 0x40B0 and
it's PCI Memory window at between 0x400000 and 0x402000.
This means that the PCI-PCI Bridge will ignore the PCI Memory accesses for
the video device and pass them on if they are for the ethernet or scsi
devices.
Next: Interrupts and Interrupt Handling
Up: PCI Fixup
Previous: Finding Out How Much
David A. Rusling
david.rusling@reo.mts.dec.com