NAME
pci_configure_bus,
pci_conf_hook,
pci_conf_interrupt —
perform PCI bus
configuration
SYNOPSIS
#include <dev/pci/pciconf.h>
int
pci_configure_bus(
pci_chipset_tag_t pc,
struct extent *ioext,
struct extent
*memext,
struct extent *pmemext,
int firstbus,
int cacheline_size);
DESCRIPTION
The
pci_configure_bus() function configures a PCI bus for use.
This involves:
- Defining bus numbers for all busses on the system,
- Setting the Base Address Registers for all devices,
- Setting up the interrupt line register for all
devices,
- Configuring bus latency timers for all devices, and
- Configuring cacheline sizes for all devices.
In traditional PCs and Alpha systems, the BIOS or firmware takes care of this
task, but that is not the case for all systems.
pci_configure_bus() should be called prior to the
autoconfiguration of the bus.
The
pc argument is a machine-dependent tag used to specify
the PCI chipset to the system. This should be the same value used with
pci_make_tag(). The extent arguments define memory extents
from which the address space for the cards will be taken. These addresses
should be in the PCI address space. The
ioext extent is
for PCI I/O accesses. The
memext extent is for PCI
memory accesses that might have side effects. I.e., that can not be cached.
The
pmemext extent is for PCI memory accesses that can
be cached. The
pmemext extent will be used for any ROMs
and any memory regions that are marked as “prefetchable” in their
BAR. If an implementation does not distinguish between prefetchable and
non-prefetchable memory, it may pass NULL for
pmemext.
In this case, prefetchable memory allocations will be made from the
non-prefetchable region. The
firstbus argument indicates
the number of the first bus to be configured. The
cacheline_size argument is used to configure the PCI
Cache Line Size Register; it should be the size, in bytes, of the largest
D-cache line on the system.
An implementation may choose to not have full configuration performed by
pci_configure_bus() on certain PCI devices, such as PCI host
bridges or PCI bus analyzers which are instantiated as devices on the bus. In
order for this to take place, the header
<machine/pci_machdep.h> must define
the
__HAVE_PCI_CONF_HOOK
symbol (without a value), and
a machine-dependent function
pci_conf_hook() (declared in
the same header) must be defined. The prototype for this function is
int
pci_conf_hook(
pci_chipset_tag_t pc,
int bus,
int device,
int function,
pcireg_t id)
In this function,
bus,
device, and
function uniquely identify the item being configured; in
addition to this, the value of the device's PCI identification register is
passed in
id. For each device
pci_conf_hook() can then decide upon the amount of
configuration to be performed by returning a bitwise inclusive-or of the
following flags:
-
-
PCI_CONF_MAP_IO
- Configure Base Address Registers that map I/O space
-
-
PCI_CONF_MAP_MEM
- Configure Base Address Registers that map memory space
-
-
PCI_CONF_MAP_ROM
- Configure Expansion ROM Base Address register
-
-
PCI_CONF_ENABLE_IO
- Enable I/O space accesses
-
-
PCI_CONF_ENABLE_MEM
- Enable memory space accesses
-
-
PCI_CONF_ENABLE_BM
- Enable bus mastering
In addition,
PCI_CONF_ALL
specifies all of the above.
One of the functions of
pci_configure_bus() is to configure
interrupt “line” information. This must be done on a
machine-dependent basis, so a machine-dependent function
pci_conf_interrupt() must be defined. The prototype for this
function is
void
pci_conf_interrupt(
pci_chipset_tag_t
pc,
int bus,
int device,
int pin,
int swiz,
int *iline)
In this function,
bus,
device, and
pin, uniquely identify the item being configured. The
swiz argument is a “swizzle”, a sum of the
device numbers of the primary interface of the bridges between the host bridge
and the current device. The function is responsible for setting the value of
iline. See chapter 9 of the “PCI-to-PCI Bridge
Architecture Specification” for more information on swizzling (also
known as interrupt routing).
RETURN VALUES
If successful
pci_configure_bus() returns 0. A non-zero return
value means that the bus was not completely configured for some reason. A
description of the failure will be displayed on the console.
ENVIRONMENT
The
pci_configure_bus() function is only included in the
kernel if the kernel is compiled with the
PCI_NETBSD_CONFIGURE
option enabled.
EXAMPLES
The
pci_conf_hook() function in evbppc's walnut implementation
looks like:
int
pci_conf_hook(pci_chipset_tag_t pc, int bus, int dev, int func,
pcireg_t id)
{
if ((PCI_VENDOR(id) == PCI_VENDOR_IBM &&
PCI_PRODUCT(id) == PCI_PRODUCT_IBM_405GP) ||
(PCI_VENDOR(id) == PCI_VENDOR_INTEL &&
PCI_PRODUCT(id) == PCI_PRODUCT_INTEL_80960_RP)) {
/* Don't configure the bridge and PCI probe. */
return 0;
}
return (PCI_CONF_ALL & ~PCI_CONF_MAP_ROM);
}
The
pci_conf_interrupt() function in the sandpoint
implementation looks like:
void
pci_conf_interrupt(pci_chipset_tag_t pc, int bus, int dev, int pin,
int swiz, int *iline)
{
if (bus == 0) {
*iline = dev;
} else {
*iline = 13 + ((swiz + dev + 3) & 3);
}
}
The BeBox has nearly 1GB of PCI I/O memory starting at processor address
0x81000000 (PCI I/O address 0x01000000), and nearly 1GB of PCI memory starting
at 0xC0000000 (PCI memory address 0x00000000). The
pci_configure_bus() function might be called as follows:
struct extent *ioext, *memext;
...
ioext = extent_create("pciio", 0x01000000, 0x0fffffff,
NULL, 0, EX_NOWAIT);
memext = extent_create("pcimem", 0x00000000, 0x0fffffff,
NULL, 0, EX_NOWAIT);
...
pci_configure_bus(0, ioext, memext, NULL);
...
extent_destroy(ioext);
extent_destroy(memext);
...
Note that this must be called before the PCI bus is attached during
autoconfiguration.
SEE ALSO
pci(4),
extent(9)
HISTORY
pci_configure_bus() was added in
NetBSD
1.6.