.\" $NetBSD: pci.9,v 1.23 2006/06/18 09:25:15 wiz Exp $ .\" .\" Copyright (c) 2001, 2003 The NetBSD Foundation, Inc. .\" All rights reserved. .\" .\" This code is derived from software contributed to The NetBSD Foundation .\" by Gregory McGarry. .\" .\" 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 by the NetBSD .\" Foundation, Inc. and its contributors. .\" 4. Neither the name of The NetBSD Foundation nor the names of its .\" contributors may be used to endorse or promote products derived .\" from this software without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS .\" ``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 THE FOUNDATION OR CONTRIBUTORS .\" 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 June 17, 2006 .Dt PCI 9 .Os .Sh NAME .Nm PCI , .Nm pci_activate , .Nm pci_conf_read , .Nm pci_conf_write , .Nm pci_conf_print , .Nm pci_conf_capture , .Nm pci_conf_restore , .Nm pci_find_device , .Nm pci_get_capability , .Nm pci_mapreg_type , .Nm pci_mapreg_map , .Nm pci_mapreg_info , .Nm pci_intr_map , .Nm pci_intr_string , .Nm pci_intr_evcnt , .Nm pci_intr_establish , .Nm pci_intr_disestablish , .Nm pci_get_powerstate , .Nm pci_set_powerstate , .Nm pci_vpd_read , .Nm pci_vpd_write , .Nm pci_make_tag , .Nm pci_decompose_tag , .Nm pci_findvendor , .Nm pci_devinfo , .Nm PCI_VENDOR , .Nm PCI_PRODUCT , .Nm PCI_REVISION .Nd Peripheral Component Interconnect .Sh SYNOPSIS .In machine/bus.h .In dev/pci/pcivar.h .In dev/pci/pcireg.h .In dev/pci/pcidevs.h .Ft int .Fn pci_activate "pci_chipset_tag_t pc" "pcitag_t tag" "int reg" "void *sc" "int (*wakeup)(pci_chipset_tag_t pc, pcitag_t tag, void *sc, pcireg_t reg)" .Ft pcireg_t .Fn pci_conf_read "pci_chipset_tag_t pc" "pcitag_t tag" "int reg" .Ft void .Fn pci_conf_write "pci_chipset_tag_t pc" "pcitag_t tag" "int reg" \ "pcireg_t val" .Ft void .Fn pci_conf_print "pci_chipset_tag_t pc" "pcitag_t tag" \ "void (*func)(pci_chipset_tag_t, pcitag_t, const pcireg_t *)" .Ft void .Fn pci_conf_capture "pci_chipset_tag_t pc" "pcitag_t tag" \ "struct pci_conf_state *" .Ft void .Fn pci_conf_restore "pci_chipset_tag_t pc" "pcitag_t tag" \ "struct pci_conf_state *" .Ft int .Fn pci_find_device "struct pci_attach_args *pa" \ "int (*func)(struct pci_attach_args *)" .Ft int .Fn pci_get_capability "pci_chipset_tag_t pc" "pcitag_t tag" \ "int capid" "int *offsetp" "pcireg_t *valuep" .Ft pcireg_t .Fn pci_mapreg_type "pci_chipset_tag_t pc" "pcitag_t tag" "int reg" .Ft int .Fn pci_mapreg_map "struct pci_attach_args *pa" "int reg" \ "pcireg_t type" "int busflags" "bus_space_tag_t *tagp" \ "bus_space_handle_t *handlep" "bus_addr_t *basep" "bus_size_t *sizep" .Ft int .Fn pci_mapreg_info "pci_chipset_tag_t pc" "pcitag_t tag" "int reg" \ "pcireg_t type" "bus_addr_t *basep" "bus_size_t *sizep" "int *flagsp" .Ft int .Fn pci_find_rom "struct pci_attach_args *pa" \ "bus_space_tag_t bst" "bus_space_handle_t bsh" "int code" \ "bus_space_handle_t *handlep" "bus_space_size_t *sizep" .Ft int .Fn pci_intr_map "struct pci_attach_args *pa" "pci_intr_handle_t *ih" .Ft const char * .Fn pci_intr_string "pci_chipset_tag_t pc" "pci_intr_handle_t ih" .Ft const struct evcnt * .Fn pci_intr_evcnt "pci_chipset_tag_t pc" "pci_intr_handle_t ih" .Ft void * .Fn pci_intr_establish "pci_chipset_tag_t pc" "pci_intr_handle_t ih" \ "int level" "int (*handler)(void *)" "void *arg" .Ft void .Fn pci_intr_disestablish "pci_chipset_tag_t pc" "void *ih" .Ft int .Fn pci_set_powerstate "pci_chipset_tag_t pc" "pcitag_t tag" \ "pcireg_t newstate" .Ft int .Fn pci_get_powerstate "pci_chipset_tag_t pc" "pcitag_t tag" "pcireg_t *state" .Ft int .Fn pci_vpd_read "pci_chipset_tag_t pc" "pcitag_t tag" "int offset" \ "int count" "pcireg_t *data" .Ft int .Fn pci_vpd_write "pci_chipset_tag_t pc" "pcitag_t tag" "int offset" \ "int count" "pcireg_t *data" .Ft pcitag_t .Fn pci_make_tag "pci_chipset_tag_t pc" "int bus" "int device" \ "int function" .Ft void .Fn pci_decompose_tag "pci_chipset_tag_t pc" "pcitag_t tag" \ "int *busp" "int *devicep" "int *functionp" .Ft char * .Fn pci_findvendor "pcireg_t id" .Ft void .Fn pci_devinfo "pcireg_t id" "pcireg_t class" "int show" "char *cp" "size_t len" .Ft int .Fn PCI_VENDOR "pcireg_t id" .Ft int .Fn PCI_PRODUCT "pcireg_t id" .Ft int .Fn PCI_REVISION "pcireg_t id" .Sh DESCRIPTION The machine-independent .Nm subsystem provides support for PCI devices. .Pp The PCI bus was initially developed by Intel in the early 1990's to replace the ISA bus for interfacing with their Pentium processor. The PCI specification is widely regarded as well designed, and the PCI bus has found widespread acceptance in machines ranging from Apple's PowerPC-based systems to Sun's UltraSPARC-based machines. .Pp The PCI bus is a multiplexed bus, allowing addresses and data on the same pins for a reduced number of pins. Data transfers can be 8-bit, 16-bit or 32-bit. A 64-bit extended PCI bus is also defined. Multi-byte transfers are little-endian. The PCI bus operates up to 33MHz and any device on the bus can be the bus master. .Pp AGP is a version of PCI optimised for high-throughput data rates, particularly for accelerated frame buffers. .Pp The PCI bus is a "plug and play" bus, in the sense that devices can be configured dynamically by software. The PCI interface chip on a PCI device bus presents a small window of registers into the PCI configuration space. These registers contain information about the device such as the vendor and a product ID. The configuration registers can also be written to by software to alter how the device interfaces to the PCI bus. An important register in the configuration space is the Base Address Register (BAR). The BAR is written to by software to map the device registers into a window of processor address space. Once this mapping is done, the device registers can be accessed relative to the base address. .Sh DATA TYPES Drivers for devices attached to the .Nm will make use of the following data types: .Bl -tag -width compact .It Fa pcireg_t Configuration space register. .It Fa pci_chipset_tag_t Chipset tag for the PCI bus. .It Fa pcitag_t Configuration tag describing the location and function of the PCI device. It contains the tuple .Ao bus, device, function .Ac . .It Fa pci_intr_handle_t The opaque handle describing an established interrupt handler. .It Fa struct pci_attach_args Devices have their identity recorded in this structure. It contains the following members: .Bd -literal bus_space_tag_t pa_iot; /* pci i/o space tag */ bus_space_tag_t pa_memt; /* pci mem space tag */ bus_dma_tag_t pa_dmat; /* DMA tag */ pci_chipset_tag_t pa_pc; int pa_flags; /* flags */ pcitag_t pa_tag; pcireg_t pa_id; pcireg_t pa_class; .Ed .It Fa struct pci_conf_state Stores the PCI configuration state of a device. It contains the following member: .Bd -literal pcireg_t reg[16]; /* pci conf register */ .Ed .El .Sh FUNCTIONS .Bl -tag -width compact .It Fn pci_activate "pc" "tag" "sc" "fun" Attempt to bring the device to state D0. If the device is not in the D0 state call .Fa fun to restore its state. If .Fa fun is .Dv NULL then restoring from state D3 is going to fail. .It Fn pci_conf_read "pc" "tag" "reg" Read from register .Fa reg in PCI configuration space. The argument .Fa tag is the PCI tag for the current device attached to PCI chipset .Fa pc . .It Fn pci_conf_write "pc" "tag" "reg" "val" Write to register .Fa reg in PCI configuration space. The argument .Fa tag is the PCI tag for the current device attached to PCI chipset .Fa pc . .It Fn pci_conf_print "pc" "tag" "func" Print out most of the registers in the PCI configuration for the device. The argument .Fa tag is the PCI tag for the current device attached to PCI chipset .Fa pc . The argument .Fa func is a function called by .Fn pci_conf_print to print the device-dependent registers. This function is only useful for driver development and is usually wrapped in pre-processor declarations. .It Fn pci_conf_capture "pc" "tag" "pcs" Capture PCI configuration space into structure .Fa pcs . The argument .Fa tag is the PCI tag for the current device attached to the PCI chipset .Fa pc . .It Fn pci_conf_restore "pc" "tag" "pcs" Restores PCI configuration space from structure .Fa pcs . The argument .Fa tag is the PCI tag for the current device attached to the PCI chipset .Fa pc . .It Fn pci_find_device "pa" "func" Find a device using a match function on all probed busses. The argument .Fa func is called by .Fn pci_find_device to match a device. The argument .Fa pa is filled in if the device is matched. .Fn pci_find_device returns 1 if the device is matched, and zero otherwise. This function is specifically for use by LKMs (see .Xr lkm 4 ) and its use otherwise is strongly discouraged. .It Fn pci_get_capability "pc" "tag" "capid" "offsetp" "valuep" Parse the device capability list in configuration space looking for capability .Fa capid . If .Fa offsetp is not NULL, the register offset in configuration space is returned in .Fa offsetp . If .Fa valuep is not NULL, the value of the capability is returned in .Fa valuep . The argument .Fa tag is the PCI tag for the current device attached to PCI chipset .Fa pc . This function returns 1 if the capability was found. If the capability was not found, it returns zero, and .Fa offsetp and .Fa valuep remain unchanged. .It Fn pci_mapreg_type "pc" "tag" "reg" Interrogates the Base Address Register (BAR) in configuration space specified by .Fa reg and returns the default (or current) mapping type. Valid returns values are: .Bl -tag -width compact .It Dv PCI_MAPREG_TYPE_IO The mapping is to I/O address space. .It Dv PCI_MAPREG_TYPE_MEM The mapping is to memory address space. .It Dv PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT The mapping is to 64-bit memory address space. .It Dv PCI_MAPREG_TYPE_ROM The mapping is to ROM. Note that in the current implementation, .Dv PCI_MAPREG_TYPE_ROM has the same numeric value as .Dv PCI_MAPREG_TYPE_MEM . .El .Pp The argument .Fa tag is the PCI tag for the current device attached to PCI chipset .Fa pc . .It Fn pci_mapreg_map "pa" "reg" "type" "busflags" "tagp" "handlep" "basep" "sizep" Maps the register windows for the device into kernel virtual address space. This function is generally only called during the driver attach step and takes a pointer to the .Em struct pci_attach_args in .Fa pa . The physical address of the mapping is in the Base Address Register (BAR) in configuration space specified by .Fa reg . Valid values for the type of mapping .Fa type are: .Bl -tag -width compact .It Dv PCI_MAPREG_TYPE_IO The mapping should be to I/O address space. .It Dv PCI_MAPREG_TYPE_MEM The mapping should be to memory address space. .It Dv PCI_MAPREG_TYPE_ROM The mapping is to access ROM. This type of mapping is only permitted when the value for .Fa reg is .Dv PCI_MAPREG_ROM . .El .Pp The argument .Fa busflags are bus-space flags passed to .Fn bus_space_map to perform the mapping (see .Xr bus_space 9 ) . The bus-space tag and handle for the mapped register window are returned in .Fa tagp and .Fa handlep respectively. The bus-address and size of the mapping are returned in .Fa basep and .Fa sizep respectively. If any of .Fa tagp , .Fa handlep , .Fa basep , or .Fa sizep are NULL then .Fn pci_mapreg_map does not define their return value. This function returns zero on success and non-zero on error. .It Fn pci_mapreg_info "pc" "tag" "reg" "type" "basep" "sizep" "flagsp" Performs the same operations as .Fn pci_mapreg_map but doesn't actually map the register window into kernel virtual address space. Returns the bus-address, size and bus flags in .Fa basep , .Fa sizep and .Fa flagsp respectively. These return values can be used by .Fn bus_space_map to actually map the register window into kernel virtual address space. This function is useful for setting up the registers in configuration space and deferring the mapping to a later time, such as in a bus-independent attachment routine. .Fa pci_mapreg_info returns zero on success and non-zero on failure. .It Fn pci_find_rom "pa" "bst" "bsh" "code" "handlep" "sizep" Locates a suitable ROM image within a PCI expansion ROM previously mapped with .Fn pci_mapreg_map and creates a subregion for it with .Fn bus_space_subregion . The .Fa bst and .Fa bsh arguments are the bus tag and handle obtained with the prior call to .Fn pci_mapreg_map . Valid values for the image type .Fa code are: .Bl -tag -width compact .It Dv PCI_ROM_CODE_TYPE_X86 Find a ROM image containing i386 executable code for use by PC BIOS. .It Dv PCI_ROM_CODE_TYPE_OFW Find a ROM image containing Forth code for use by Open Firmware. .It Dv PCI_ROM_CODE_TYPE_HPPA Find a ROM image containing HP PA/RISC executable code. .El .Pp The created subregion will cover the entire selected ROM image, including header data. The handle to this subregion is returned in .Fa handlep . The size of the image (and the corresponding subregion) is returned in .Fa sizep . This function can only be used with expansion ROMs located at the .Dv PCI_MAPREG_ROM base address register (BAR). .It Fn pci_intr_map "pa" "ih" See .Xr pci_intr 9 . .It Fn pci_intr_string "pc" "ih" See .Xr pci_intr 9 . .It Fn pci_intr_evcnt "pc" "ih" See .Xr pci_intr 9 . .It Fn pci_intr_establish "pc" "ih" "level" "handler" "arg" See .Xr pci_intr 9 . .It Fn pci_intr_disestablish "pc" "ih" See .Xr pci_intr 9 . .It Fn pci_set_powerstate "pc" "tag" "newstate" Set power state of the device to newstate. Valid values for .Fa newstate are: .Pp .Bl -tag -width PCI_PMCSR_STATE_D0 -compact .It Dv PCI_PMCSR_STATE_D0 .It Dv PCI_PMCSR_STATE_D1 .It Dv PCI_PMCSR_STATE_D2 .It Dv PCI_PMCSR_STATE_D3 .El .It Fn pci_get_powerstate "pc" "tag" "state"` Get current power state of the device. .It Fn pci_vpd_read "pc" "tag" "offset" "count" "data" Read .Fa count 32-bit words of Vital Product Data for the device starting at offset .Fa offset into the buffer pointed to by .Fa data . Returns 0 on success or non-zero if the device has no Vital Product Data capability or if reading the Vital Product Data fails. .It Fn pci_vpd_write "pc" "tag" "offset" "count" "data" Write .Fa count 32-bit words of Vital Product Data for the device starting at offset .Fa offset from the buffer pointed to by .Fa data . Returns 0 on success or non-zero if the device has no Vital Product Data capability of if writing the Vital Product Data fails. .It Fn pci_make_tag "pc" "bus" "device" "function" Create a new PCI tag for the PCI device specified by the tuple .Ao bus, device, function .Ac . This function is not useful to the usual PCI device driver. It is generally used by drivers of multi-function devices when attaching other PCI device drivers to each function. .It Fn pci_decompose_tag "pc" "tag" "busp" "devicep" "fnp" Decompose the PCI tag .Fa tag generated by .Fn pci_make_tag into its .Ao bus, device, function .Ac tuple. .It Fn pci_findvendor "id" Return the string of the vendor name for the device specified by .Fa id . .It Fn pci_devinfo "id" "class" "show" "cp" "len" Returns the description string from the in-kernel PCI database for the device described by .Fa id and .Fa class . The description string is returned in .Fa cp ; the size of that storage is given in .Fa len . The argument .Fa show specifies whether the PCI subsystem should report the string to the console. .It Fn PCI_VENDOR "id" Return the PCI vendor id for device .Fa id . .It Fn PCI_PRODUCT "id" Return the PCI product id for device .Fa id . .It Fn PCI_REVISION "id" Return the PCI product revision for device .Fa id . .El .Sh AUTOCONFIGURATION During autoconfiguration, a .Nm driver will receive a pointer to .Fa struct pci_attach_args describing the device attaches to the PCI bus. Drivers match the device using the .Fa pa_id member using .Fn PCI_VENDOR . .Fn PCI_PRODUCT and .Fn PCI_REVISION . .Pp During the driver attach step, drivers can read the device configuration space using .Fn pci_conf_read . The meaning attached to registers in the PCI configuration space are device-dependent, but will usually contain physical addresses of the device register windows. Device options can also be stored into the PCI configuration space using .Fn pci_conf_write . For example, the driver can request support for bus-mastering DMA by writing the option to the PCI configuration space. .Pp Device capabilities can be queried using .Fn pci_get_capability , and returns device-specific information which can be found in the PCI configuration space to alter device operation. .Pp After reading the physical addresses of the device register windows from configuration space, these windows must be mapped into kernel virtual address space using .Fn pci_mapreg_map . Device registers can now be accessed using the standard bus-space API (see .Xr bus_space 9 ) . .Pp Details of using PCI interrupts is described in .Xr pci_intr 9 . .Sh DMA SUPPORT The PCI bus supports bus-mastering operations from any device on the bus. The DMA facilities are accessed through the standard .Xr bus_dma 9 interface. To support DMA transfers from the device to the host, it is necessary to enable bus-mastering in the PCI configuration space for the device. .Pp During system shutdown, it is necessary to abort any DMA transfers in progress by registering a shutdown hook (see .Xr shutdownhook_establish 9 ) . .Sh CODE REFERENCES This section describes places within the .Nx source tree where actual code implementing or using the machine-independent PCI subsystem can be found. All pathnames are relative to .Pa /usr/src . .Pp The PCI subsystem itself is implemented within the files .Pa sys/dev/pci/pci.c , .Pa sys/dev/pci/pci_subr.c , .Pa sys/dev/pci/pci_map.c , .Pa sys/dev/pci/pci_quirks.c , and .Pa sys/dev/pci/pciconf.c . Machine-dependent portions are implemented within the file .Pa sys/arch/\*[Lt]arch\*[Gt]/pci/pci_machdep.c . .Pp The database of known devices exists within the file .Pa sys/dev/pci/pcidevs_data.h and is generated automatically from the file .Pa sys/dev/pci/pcidevs . New vendor and product identifiers should be added to this file. The database can be regenerated using the Makefile .Pa sys/dev/pci/Makefile.pcidevs . .Sh SEE ALSO .Xr pci 4 , .Xr autoconf 9 , .Xr bus_dma 9 , .Xr bus_space 9 , .Xr driver 9 , .Xr pci_configure_bus 9 , .Xr pci_intr 9 , .Xr shutdownhook_establish 9 .Sh HISTORY The machine-independent PCI subsystem appeared in .Nx 1.2 .