| PCI_CONFIGURE_BUS(9) | Kernel Developer's Manual | PCI_CONFIGURE_BUS(9) | 
pci_configure_bus,
  pci_conf_hook,
  pci_conf_interrupt,
  pciconf_resource_init,
  pciconf_resource_add,
  pciconf_resource_fini —
#include <dev/pci/pciconf.h>
int
  
  pci_configure_bus(pci_chipset_tag_t
    pc, struct
    pciconf_resources *res,
    int firstbus,
    int cacheline_size);
struct pciconf_resources *
  
  pciconf_resource_init(void);
void
  
  pciconf_resource_add(struct
    pciconf_resources *res,
    int type,
    bus_addr_t addr,
    bus_size_t size);
void
  
  pciconf_resource_fini(struct
    pciconf_resources *res);
pci_configure_bus() 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
    res argument is a container for PCI bus resources that
    will be used to configure the bus. 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_IOPCI_CONF_MAP_MEMPCI_CONF_MAP_ROMPCI_CONF_ENABLE_IOPCI_CONF_ENABLE_MEMPCI_CONF_ENABLE_BMIn 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).
The resources used to configure the PCI bus are encapsulated into
    a resource container. The pciconf_resource_init()
    function allocates and initializes one of these containers, and the
    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:
PCICONF_RESOURCE_IOPCICONF_RESOURCE_MEMPCICONF_RESOURCE_PREFETCHABLE_MEMIf an implementation does not distinguish between prefetchable and
    non-prefetchable memory, then adding a
    PCICONF_RESOURCE_PREFETCHABLE_MEM resource is not
    required; PCICONF_RESOURCE_MEM resources will be
    used for ROMs and BARs that are marked as prefetchable.
Once the bus has been successfully configured, the resource
    container should be disposed of by calling
    pciconf_resource_fini().
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.
pci_configure_bus() function is only included in the
  kernel if the kernel is compiled with the
  PCI_NETBSD_CONFIGURE option enabled.
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);
	}
}
This configuration example is taken from the bebox port.
#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); ...
Note that this must be called before the PCI bus is attached during autoconfiguration.
pci_configure_bus() was added in NetBSD
  1.6.
| July 7, 2020 | NetBSD 10.0 |