.\" $NetBSD: pci_configure_bus.9,v 1.20 2020/08/27 14:14:00 fcambus Exp $
.\"
.\" Copyright 2001 Wasabi Systems, Inc.
.\" All rights reserved.
.\"
.\" Written by Allen Briggs for Wasabi Systems, Inc.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed for the NetBSD Project by
.\" Wasabi Systems, Inc.
.\" 4. The name of Wasabi Systems, Inc. may not be used to endorse
.\" or promote products derived from this software without specific prior
.\" written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd July 7, 2020
.Dt PCI_CONFIGURE_BUS 9
.Os
.Sh NAME
.Nm pci_configure_bus ,
.Nm pci_conf_hook ,
.Nm pci_conf_interrupt ,
.Nm pciconf_resource_init ,
.Nm pciconf_resource_add ,
.Nm pciconf_resource_fini
.Nd perform PCI bus configuration
.Sh SYNOPSIS
.In dev/pci/pciconf.h
.Ft int
.Fn pci_configure_bus "pci_chipset_tag_t pc" "struct pciconf_resources *res" \
"int firstbus" "int cacheline_size"
.Ft struct pciconf_resources *
.Fn pciconf_resource_init "void"
.Ft void
.Fn pciconf_resource_add "struct pciconf_resources *res" "int type" \
"bus_addr_t addr" "bus_size_t size"
.Ft void
.Fn pciconf_resource_fini "struct pciconf_resources *res"
.Sh DESCRIPTION
The
.Fn pci_configure_bus
function configures a PCI bus for use.
This involves:
.Bl -bullet
.It
Defining bus numbers for all busses on the system,
.It
Setting the Base Address Registers for all devices,
.It
Setting up the interrupt line register for all devices,
.It
Configuring bus latency timers for all devices, and
.It
Configuring cacheline sizes for all devices.
.El
.Pp
In traditional PCs and Alpha systems, the BIOS or firmware takes care
of this task, but that is not the case for all systems.
.Fn pci_configure_bus
should be called prior to the autoconfiguration of the bus.
.Pp
The
.Fa pc
argument is a machine-dependent tag used to specify the PCI chipset to the
system.
This should be the same value used with
.Fn pci_make_tag .
The
.Fa res
argument is a container for PCI bus resources that will be used to
configure the bus.
The
.Fa firstbus
argument indicates the number of the first bus to be configured.
The
.Fa 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.
.Pp
An implementation may choose to not have full configuration performed
by
.Fn 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
.In machine/pci_machdep.h
must define the
.Dv __HAVE_PCI_CONF_HOOK
symbol (without a value), and a machine-dependent function
.Fn pci_conf_hook
(declared in the same header)
must be defined.
The prototype for this function is:
.Pp
.Ft int
.Fn "pci_conf_hook" "pci_chipset_tag_t pc" "int bus" \
"int device" "int function" "pcireg_t id" ;
.Pp
In this function,
.Fa bus ,
.Fa device ,
and
.Fa function
uniquely identify the item being configured;
in addition to this, the value of the device's PCI identification
register is passed in
.Fa id .
For each device
.Fn pci_conf_hook
can then decide upon the amount of configuration to be performed by
returning a bitwise inclusive-or of the following flags:
.Bl -tag -width PCI_CONF_ENABLE_MEM -offset indent
.It Dv PCI_CONF_MAP_IO
Configure Base Address Registers that map I/O space
.It Dv PCI_CONF_MAP_MEM
Configure Base Address Registers that map memory space
.It Dv PCI_CONF_MAP_ROM
Configure Expansion ROM Base Address register
.It Dv PCI_CONF_ENABLE_IO
Enable I/O space accesses
.It Dv PCI_CONF_ENABLE_MEM
Enable memory space accesses
.It Dv PCI_CONF_ENABLE_BM
Enable bus mastering
.El
.Pp
In addition,
.Dv PCI_CONF_ALL
specifies all of the above.
.Pp
One of the functions of
.Fn pci_configure_bus
is to configure interrupt
.Dq line
information.
This must be done on a machine-dependent basis, so a
machine-dependent function
.Fn pci_conf_interrupt
must be defined.
The prototype for this function is
.Pp
.Ft void
.Fn "pci_conf_interrupt" "pci_chipset_tag_t pc" "int bus" \
"int device" "int pin" "int swiz" "int *iline"
.Pp
In this function,
.Fa bus ,
.Fa device ,
and
.Fa pin ,
uniquely identify the item being configured.
The
.Fa swiz
argument is a
.Dq 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
.Fa iline .
See chapter 9 of the
.Dq PCI-to-PCI Bridge Architecture Specification
for more information on swizzling (also known as interrupt routing).
.Pp
The resources used to configure the PCI bus are encapsulated into a
resource container.
The
.Fn pciconf_resource_init
function allocates and initializes one of these containers, and the
.Fn pciconf_resource_add
function adds resources to the container, specifying the type, start
address, and size of the resource being added.
The following resource types are supported:
.Bl -tag -width PCICONF_RESOURCE_PREFETCHABLE_MEM -offset indent
.It Dv PCICONF_RESOURCE_IO
An address region used for PCI I/O accesses.
.It Dv PCICONF_RESOURCE_MEM
An address region used for PCI memory accesses where reads may have side
effects.
.It Dv PCICONF_RESOURCE_PREFETCHABLE_MEM
An address region used for PCI memory accesses where reads do not have
side effects
.Po
e.g. ROMs, frame buffers, other memory-like regions that are marked as
prefetchable in their BAR
.Pc .
.El
.Pp
If an implementation does not distinguish between prefetchable and
non-prefetchable memory, then adding a
.Dv PCICONF_RESOURCE_PREFETCHABLE_MEM
resource is not required;
.Dv PCICONF_RESOURCE_MEM
resources will be used for ROMs and BARs that are marked as prefetchable.
.Pp
Once the bus has been successfully configured, the resource container should
be disposed of by calling
.Fn pciconf_resource_fini .
.Sh RETURN VALUES
If successful
.Fn 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.
.Sh ENVIRONMENT
The
.Fn pci_configure_bus
function is only included in the kernel if the kernel is compiled with
the
.Dv PCI_NETBSD_CONFIGURE
option enabled.
.Sh EXAMPLES
The
.Fn pci_conf_hook
function in evbppc's walnut implementation looks like:
.Pp
.Bd -literal -compact
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);
}
.Ed
.Pp
The
.Fn pci_conf_interrupt
function in the sandpoint implementation looks like:
.Pp
.Bd -literal -compact
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);
}
}
.Ed
.Pp
This configuration example is taken from the bebox port.
.Pp
.Bd -literal -compact
#define PCI_IO_START 0x00008000
#define PCI_IO_END 0x0000ffff
#define PCI_IO_SIZE ((PCI_IO_END - PCI_IO_START) + 1)
#define PCI_MEM_START 0x00000000
#define PCI_MEM_END 0x0fffffff
#define PCI_MEM_SIZE ((PCI_MEM_END - PCI_MEM_START) + 1)
...
struct pciconf_resources *pcires;
...
pcires = pciconf_resource_init();
pciconf_resource_add(pcires, PCICONF_RESOURCE_IO,
PCI_IO_START, PCI_IO_SIZE);
pciconf_resource_add(pcires, PCICONF_RESOURCE_MEM,
PCI_MEM_START, PCI_MEM_SIZE);
...
pci_configure_bus(pc, pcires, 0, CACHELINESIZE);
...
pciconf_resource_fini(pcires);
...
.Ed
.Pp
Note that this must be called before the PCI bus is attached during
autoconfiguration.
.Sh SEE ALSO
.Xr pci 4
.Sh HISTORY
.Fn pci_configure_bus
was added in
.Nx 1.6 .