int
pci_configure_bus(
pci_chipset_tag_t pc
struct extent *ioext
struct extent *memext
struct extent *pmemext
int firstbus
int cacheline_size
)
)
function configures a PCI bus for use.
This involves:
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
PCI_CONF_MAP_MEM
PCI_CONF_MAP_ROM
PCI_CONF_ENABLE_IO
PCI_CONF_ENABLE_MEM
PCI_CONF_ENABLE_BM
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).
)
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.
)
function is only included in the kernel if the kernel is compiled with
the
PCI_NETBSD_CONFIGURE
option enabled.
)
function in evbppc's walnut implementation looks like:
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);
}
int
pci_conf_hook(pci_chipset_tag_t pc, int bus, int dev, int func,
pcireg_t id)
{
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, M_DEVBUF,
NULL, 0, EX_NOWAIT);
memext = extent_create("pcimem", 0x00000000, 0x0fffffff, M_DEVBUF,
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.
)
was added in
NetBSD1.6.