summaryrefslogtreecommitdiffstats
path: root/c_user/pci_library.rst
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2016-02-04 10:19:13 +1300
committerAmar Takhar <verm@darkbeer.org>2016-05-02 20:51:26 -0400
commitc9aaf3145fc84b55191c460f645985b814994d70 (patch)
tree8fb8388ed36ed695112330376654fd780d0fcd48 /c_user/pci_library.rst
parentClean ups. (diff)
downloadrtems-docs-c9aaf3145fc84b55191c460f645985b814994d70.tar.bz2
Clean up
Diffstat (limited to 'c_user/pci_library.rst')
-rw-r--r--c_user/pci_library.rst279
1 files changed, 140 insertions, 139 deletions
diff --git a/c_user/pci_library.rst b/c_user/pci_library.rst
index 0512b45..6d97e3d 100644
--- a/c_user/pci_library.rst
+++ b/c_user/pci_library.rst
@@ -1,3 +1,7 @@
+.. COMMENT: COPYRIGHT (c) 1988-2008.
+.. COMMENT: On-Line Applications Research Corporation (OAR).
+.. COMMENT: All rights reserved.
+
PCI Library
###########
@@ -6,19 +10,19 @@ PCI Library
Introduction
============
-The Peripheral Component Interconnect (PCI) bus is a very common computer
-bus architecture that is found in almost every PC today. The PCI bus is
-normally located at the motherboard where some PCI devices are soldered
-directly onto the PCB and expansion slots allows the user to add custom
-devices easily. There is a wide range of PCI hardware available implementing
-all sorts of interfaces and functions.
+The Peripheral Component Interconnect (PCI) bus is a very common computer bus
+architecture that is found in almost every PC today. The PCI bus is normally
+located at the motherboard where some PCI devices are soldered directly onto
+the PCB and expansion slots allows the user to add custom devices easily. There
+is a wide range of PCI hardware available implementing all sorts of interfaces
+and functions.
This section describes the PCI Library available in RTEMS used to access the
PCI bus in a portable way across computer architectures supported by RTEMS.
The PCI Library aims to be compatible with PCI 2.3 with a couple of
-limitations, for example there is no support for hot-plugging, 64-bit
-memory space and cardbus bridges.
+limitations, for example there is no support for hot-plugging, 64-bit memory
+space and cardbus bridges.
In order to support different architectures and with small foot-print embedded
systems in mind the PCI Library offers four different configuration options
@@ -26,7 +30,7 @@ listed below. It is selected during compile time by defining the appropriate
macros in confdefs.h. It is also possible to enable PCI_LIB_NONE (No
Configuration) which can be used for debuging PCI access functions.
-- Auto Configuration (do Plug & Play)
+- Auto Configuration (Plug & Play)
- Read Configuration (read BIOS or boot loader configuration)
@@ -37,24 +41,24 @@ Configuration) which can be used for debuging PCI access functions.
Background
==========
-The PCI bus is constructed in a way where on-board devices and devices
-in expansion slots can be automatically found (probed) and configured
-using Plug & Play completely implemented in software. The bus is set up once
-during boot up. The Plug & Play information can be read and written from
-PCI configuration space. A PCI device is identified in configuration space by
-a unique bus, slot and function number. Each PCI slot can have up to 8
-functions and interface to another PCI sub-bus by implementing a PCI-to-PCI
-bridge according to the PCI Bridge Architecture specification.
-
-Using the unique \[bus:slot:func] any device can be configured regardless of how
-PCI is currently set up as long as all PCI buses are enumerated correctly. The
-enumeration is done during probing, all bridges are given a bus number in
-order for the bridges to respond to accesses from both directions. The PCI
-library can assign address ranges to which a PCI device should respond using
-Plug & Play technique or a static user defined configuration. After the
-configuration has been performed the PCI device drivers can find devices by
-the read-only PCI Class type, Vendor ID and Device ID information found in
-configuration space for each device.
+The PCI bus is constructed in a way where on-board devices and devices in
+expansion slots can be automatically found (probed) and configured using Plug &
+Play completely implemented in software. The bus is set up once during boot
+up. The Plug & Play information can be read and written from PCI configuration
+space. A PCI device is identified in configuration space by a unique bus, slot
+and function number. Each PCI slot can have up to 8 functions and interface to
+another PCI sub-bus by implementing a PCI-to-PCI bridge according to the PCI
+Bridge Architecture specification.
+
+Using the unique \[bus:slot:func] any device can be configured regardless of
+how PCI is currently set up as long as all PCI buses are enumerated
+correctly. The enumeration is done during probing, all bridges are given a bus
+number in order for the bridges to respond to accesses from both
+directions. The PCI library can assign address ranges to which a PCI device
+should respond using Plug & Play technique or a static user defined
+configuration. After the configuration has been performed the PCI device
+drivers can find devices by the read-only PCI Class type, Vendor ID and Device
+ID information found in configuration space for each device.
In some systems there is a boot loader or BIOS which have already configured
all PCI devices, but on embedded targets it is quite common that there is no
@@ -65,14 +69,13 @@ translate the \[bus:slot:func] into a valid PCI configuration space access.
If the target is not a host, but a peripheral, configuration space can not be
accessed, the peripheral is set up by the host during start up. In complex
embedded PCI systems the peripheral may need to access other PCI boards than
-the host. In such systems a custom (static) configuration of both the host
-and peripheral may be a convenient solution.
+the host. In such systems a custom (static) configuration of both the host and
+peripheral may be a convenient solution.
The PCI bus defines four interrupt signals INTA#..INTD#. The interrupt signals
must be mapped into a system interrupt/vector, it is up to the BSP or host
-driver to know the mapping, however the BIOS or boot loader may use the
-8-bit read/write "Interrupt Line" register to pass the knowledge along to the
-OS.
+driver to know the mapping, however the BIOS or boot loader may use the 8-bit
+read/write "Interrupt Line" register to pass the knowledge along to the OS.
The PCI standard defines and recommends that the backplane route the interupt
lines in a systematic way, however in standard there is no such requirement.
@@ -105,8 +108,8 @@ PCI Configuration
During start up the PCI bus must be configured in order for host and
peripherals to access one another using Memory or I/O accesses and that
-interrupts are properly handled. Three different spaces are defined and
-mapped separately:
+interrupts are properly handled. Three different spaces are defined and mapped
+separately:
# I/O space (IO)
@@ -114,14 +117,14 @@ mapped separately:
# prefetchable Memory space (MEM)
-Regions of the same type (I/O or Memory) may not overlap which is guaranteed
-by the software. MEM regions may be mapped into MEMIO regions, but MEMIO
-regions can not be mapped into MEM, for that could lead to prefetching of
-registers. The interrupt pin which a board is driving can be read out from
-PCI configuration space, however it is up to software to know how interrupt
-signals are routed between PCI-to-PCI bridges and how PCI INT[A..D]# pins are
-mapped to system IRQ. In systems where previous software (boot loader or BIOS)
-has already set up this the configuration is overwritten or simply read out.
+Regions of the same type (I/O or Memory) may not overlap which is guaranteed by
+the software. MEM regions may be mapped into MEMIO regions, but MEMIO regions
+can not be mapped into MEM, for that could lead to prefetching of
+registers. The interrupt pin which a board is driving can be read out from PCI
+configuration space, however it is up to software to know how interrupt signals
+are routed between PCI-to-PCI bridges and how PCI INT[A..D]# pins are mapped to
+system IRQ. In systems where previous software (boot loader or BIOS) has
+already set up this the configuration is overwritten or simply read out.
In order to support different configuration methods the following configuration
libraries are selectable by the user:
@@ -138,7 +141,8 @@ libraries are selectable by the user:
A host driver can be made to support all three configuration methods, or any
combination. It may be defined by the BSP which approach is used.
-The configuration software is called from the PCI driver (pci_config_init()).
+The configuration software is called from the PCI driver
+(``pci_config_init()``).
Regardless of configuration method a PCI device tree is created in RAM during
initialization, the tree can be accessed to find devices and resources without
@@ -148,14 +152,14 @@ device tree at compile time when using the static/peripheral method.
RTEMS Configuration selection
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The active configuration method can be selected at compile time in the same
-way as other project parameters by including rtems/confdefs.h and setting
+The active configuration method can be selected at compile time in the same way
+as other project parameters by including rtems/confdefs.h and setting
-- CONFIGURE_INIT
+- ``CONFIGURE_INIT``
-- RTEMS_PCI_CONFIG_LIB
+- ``RTEMS_PCI_CONFIG_LIB``
-- CONFIGURE_PCI_LIB = PCI_LIB_(AUTO,STATIC,READ,PERIPHERAL)
+- ``CONFIGURE_PCI_LIB`` = PCI_LIB_(AUTO,STATIC,READ,PERIPHERAL)
See the RTEMS configuration section how to setup the PCI library.
@@ -163,17 +167,17 @@ Auto Configuration
~~~~~~~~~~~~~~~~~~
The auto configuration software enumerates PCI buses and initializes all PCI
-devices found using Plug & Play. The auto configuration software requires
-that a configuration setup has been registered by the driver or BSP in order
-to setup the I/O and Memory regions at the correct address ranges. PCI
-interrupt pins can optionally be routed over PCI-to-PCI bridges and mapped
-to a system interrupt number. BAR resources are sorted by size and required
-alignment, unused "dead" space may be created when PCI bridges are present
-due to the PCI bridge window size does not equal the alignment. To cope with
-that resources are reordered to fit smaller BARs into the dead space to minimize
-the PCI space required. If a BAR or ROM register can not be allocated a PCI
-address region (due to too few resources available) the register will be given
-the value of pci_invalid_address which defaults to 0.
+devices found using Plug & Play. The auto configuration software requires that
+a configuration setup has been registered by the driver or BSP in order to
+setup the I/O and Memory regions at the correct address ranges. PCI interrupt
+pins can optionally be routed over PCI-to-PCI bridges and mapped to a system
+interrupt number. BAR resources are sorted by size and required alignment,
+unused "dead" space may be created when PCI bridges are present due to the PCI
+bridge window size does not equal the alignment. To cope with that resources
+are reordered to fit smaller BARs into the dead space to minimize the PCI space
+required. If a BAR or ROM register can not be allocated a PCI address region
+(due to too few resources available) the register will be given the value of
+pci_invalid_address which defaults to 0.
The auto configuration routines support:
@@ -185,8 +189,7 @@ The auto configuration routines support:
- memory space (MEMIO)
-- prefetchable memory space (MEM), if not present MEM will be mapped into
- MEMIO
+- prefetchable memory space (MEM), if not present MEM will be mapped into MEMIO
- multiple PCI buses - PCI-to-PCI bridges
@@ -224,8 +227,8 @@ Static Configuration
~~~~~~~~~~~~~~~~~~~~
To support custom configurations and small-footprint PCI systems, the user may
-provide the PCI device tree which contains the current configuration. The
-PCI buses are enumerated and all resources are written to PCI devices during
+provide the PCI device tree which contains the current configuration. The PCI
+buses are enumerated and all resources are written to PCI devices during
initialization. When this approach is selected PCI boards must be located at
the same slots every time and devices can not be removed or added, Plug & Play
is not performed. Boards of the same type may of course be exchanged.
@@ -240,13 +243,13 @@ Peripheral Configuration
On systems where a peripheral PCI device needs to access other PCI devices than
the host the peripheral configuration approach may be handy. Most PCI devices
-answers on the PCI host's requests and start DMA accesses into the Hosts memory,
-however in some complex systems PCI devices may want to access other devices
-on the same bus or at another PCI bus.
+answers on the PCI host's requests and start DMA accesses into the Hosts
+memory, however in some complex systems PCI devices may want to access other
+devices on the same bus or at another PCI bus.
-A PCI peripheral is not allowed to do PCI configuration cycles, which
-means that it must either rely on the host to give it the addresses it
-needs, or that the addresses are predefined.
+A PCI peripheral is not allowed to do PCI configuration cycles, which means
+that it must either rely on the host to give it the addresses it needs, or that
+the addresses are predefined.
This configuration approach is very similar to the static option, however the
configuration is never written to PCI bus, instead it is only used for drivers
@@ -256,8 +259,8 @@ PCI Access
----------
The PCI access routines are low-level routines provided for drivers,
-configuration software, etc. in order to access different regions in a way
-not dependent upon the host driver, BSP or platform.
+configuration software, etc. in order to access different regions in a way not
+dependent upon the host driver, BSP or platform.
- PCI configuration space
@@ -275,26 +278,28 @@ configuration space access.
Some non-standard hardware may also define the PCI bus big-endian, for example
the LEON2 AT697 PCI host bridge and some LEON3 systems may be configured that
way. It is up to the BSP to set the appropriate PCI endianness on compile time
-(BSP_PCI_BIG_ENDIAN) in order for inline macros to be correctly defined.
-Another possibility is to use the function pointers defined by the access
-layer to implement drivers that support "run-time endianness detection".
+(``BSP_PCI_BIG_ENDIAN``) in order for inline macros to be correctly defined.
+Another possibility is to use the function pointers defined by the access layer
+to implement drivers that support "run-time endianness detection".
Configuration space
~~~~~~~~~~~~~~~~~~~
-Configuration space is accessed using the routines listed below. The
-pci_dev_t type is used to specify a specific PCI bus, device and function. It
-is up to the host driver or BSP to create a valid access to the requested
-PCI slot. Requests made to slots that are not supported by hardware should
-result in PCISTS_MSTABRT and/or data must be ignored (writes) or 0xffffffff
-is always returned (reads).
+Configuration space is accessed using the routines listed below. The pci_dev_t
+type is used to specify a specific PCI bus, device and function. It is up to
+the host driver or BSP to create a valid access to the requested PCI
+slot. Requests made to slots that are not supported by hardware should result
+in ``PCISTS_MSTABRT`` and/or data must be ignored (writes) or ``0xFFFFFFFF`` is
+always returned (reads).
+
.. code:: c
- /* Configuration Space Access Read Routines \*/
- extern int pci_cfg_r8(pci_dev_t dev, int ofs, uint8_t \*data);
- extern int pci_cfg_r16(pci_dev_t dev, int ofs, uint16_t \*data);
- extern int pci_cfg_r32(pci_dev_t dev, int ofs, uint32_t \*data);
- /* Configuration Space Access Write Routines \*/
+ /* Configuration Space Access Read Routines */
+ extern int pci_cfg_r8(pci_dev_t dev, int ofs, uint8_t *data);
+ extern int pci_cfg_r16(pci_dev_t dev, int ofs, uint16_t *data);
+ extern int pci_cfg_r32(pci_dev_t dev, int ofs, uint32_t *data);
+
+ /* Configuration Space Access Write Routines */
extern int pci_cfg_w8(pci_dev_t dev, int ofs, uint8_t data);
extern int pci_cfg_w16(pci_dev_t dev, int ofs, uint16_t data);
extern int pci_cfg_w32(pci_dev_t dev, int ofs, uint32_t data);
@@ -305,20 +310,20 @@ I/O space
The BSP or driver provide special routines in order to access I/O space. Some
architectures have a special instruction accessing I/O space, others have it
mapped into a "PCI I/O window" in the standard address space accessed by the
-CPU. The window size may vary and must be taken into consideration by the
-host driver. The below routines must be used to access I/O space. The address
-given to the functions is not the PCI I/O addresses, the caller must have
-translated PCI I/O addresses (available in the PCI BARs) into a BSP or host
-driver custom address, see `Access functions`_ for how
-addresses are translated.
+CPU. The window size may vary and must be taken into consideration by the host
+driver. The below routines must be used to access I/O space. The address given
+to the functions is not the PCI I/O addresses, the caller must have translated
+PCI I/O addresses (available in the PCI BARs) into a BSP or host driver custom
+address, see `Access functions`_ for how addresses are translated.
.. code:: c
- /* Read a register over PCI I/O Space \*/
+ /* Read a register over PCI I/O Space */
extern uint8_t pci_io_r8(uint32_t adr);
extern uint16_t pci_io_r16(uint32_t adr);
extern uint32_t pci_io_r32(uint32_t adr);
- /* Write a register over PCI I/O Space \*/
+
+ /* Write a register over PCI I/O Space */
extern void pci_io_w8(uint32_t adr, uint8_t data);
extern void pci_io_w16(uint32_t adr, uint16_t data);
extern void pci_io_w32(uint32_t adr, uint32_t data);
@@ -334,52 +339,53 @@ memory space. This leads to register content being swapped, which must be
swapped back. The below routines makes it possible to access registers over PCI
memory space in a portable way on different architectures, the BSP or
architecture must provide necessary functions in order to implement this.
+
.. code:: c
- static inline uint16_t pci_ld_le16(volatile uint16_t \*addr);
- static inline void pci_st_le16(volatile uint16_t \*addr, uint16_t val);
- static inline uint32_t pci_ld_le32(volatile uint32_t \*addr);
- static inline void pci_st_le32(volatile uint32_t \*addr, uint32_t val);
- static inline uint16_t pci_ld_be16(volatile uint16_t \*addr);
- static inline void pci_st_be16(volatile uint16_t \*addr, uint16_t val);
- static inline uint32_t pci_ld_be32(volatile uint32_t \*addr);
- static inline void pci_st_be32(volatile uint32_t \*addr, uint32_t val);
+ static inline uint16_t pci_ld_le16(volatile uint16_t *addr);
+ static inline void pci_st_le16(volatile uint16_t *addr, uint16_t val);
+ static inline uint32_t pci_ld_le32(volatile uint32_t *addr);
+ static inline void pci_st_le32(volatile uint32_t *addr, uint32_t val);
+ static inline uint16_t pci_ld_be16(volatile uint16_t *addr);
+ static inline void pci_st_be16(volatile uint16_t *addr, uint16_t val);
+ static inline uint32_t pci_ld_be32(volatile uint32_t *addr);
+ static inline void pci_st_be32(volatile uint32_t *addr, uint32_t val);
-In order to support non-standard big-endian PCI bus the above pci_* functions
-is required, pci_ld_le16 != ld_le16 on big endian PCI buses.
+In order to support non-standard big-endian PCI bus the above ``pci_*``
+functions is required, ``pci_ld_le16 != ld_le16`` on big endian PCI buses.
Access functions
~~~~~~~~~~~~~~~~
The PCI Access Library can provide device drivers with function pointers
-executing the above Configuration, I/O and Memory space accesses. The
-functions have the same arguments and return values as the above
-functions.
+executing the above Configuration, I/O and Memory space accesses. The functions
+have the same arguments and return values as the above functions.
The pci_access_func() function defined below can be used to get a function
pointer of a specific access type.
+
.. code:: c
/* Get Read/Write function for accessing a register over PCI Memory Space
- * (non-inline functions).
- *
- * Arguments
- * wr 0(Read), 1(Write)
- * size 1(Byte), 2(Word), 4(Double Word)
- * func Where function pointer will be stored
- * endian PCI_LITTLE_ENDIAN or PCI_BIG_ENDIAN
- * type 1(I/O), 3(REG over MEM), 4(CFG)
- *
- * Return
- * 0 Found function
- * others No such function defined by host driver or BSP
- \*/
- int pci_access_func(int wr, int size, void \**func, int endian, int type);
+ * (non-inline functions).
+ *
+ * Arguments
+ * wr 0(Read), 1(Write)
+ * size 1(Byte), 2(Word), 4(Double Word)
+ * func Where function pointer will be stored
+ * endian PCI_LITTLE_ENDIAN or PCI_BIG_ENDIAN
+ * type 1(I/O), 3(REG over MEM), 4(CFG)
+ *
+ * Return
+ * 0 Found function
+ * others No such function defined by host driver or BSP
+ */
+ int pci_access_func(int wr, int size, void **func, int endian, int type);
PCI device drivers may be written to support run-time detection of endianess,
this is mosly for debugging or for development systems. When the product is
-finally deployed macros switch to using the inline functions instead which
-have been configured for the correct endianness.
+finally deployed macros switch to using the inline functions instead which have
+been configured for the correct endianness.
PCI address translation
~~~~~~~~~~~~~~~~~~~~~~~
@@ -390,23 +396,25 @@ using configuration space routines or in the device tree, the addresses given
are PCI addresses. The below functions can be used to translate PCI addresses
into CPU accessible addresses or vice versa, translation may be different for
different PCI spaces/regions.
+
.. code:: c
- /* Translate PCI address into CPU accessible address \*/
- static inline int pci_pci2cpu(uint32_t \*address, int type);
- /* Translate CPU accessible address into PCI address (for DMA) \*/
- static inline int pci_cpu2pci(uint32_t \*address, int type);
+ /* Translate PCI address into CPU accessible address */
+ static inline int pci_pci2cpu(uint32_t *address, int type);
+
+ /* Translate CPU accessible address into PCI address (for DMA) */
+ static inline int pci_cpu2pci(uint32_t *address, int type);
PCI Interrupt
-------------
-The PCI specification defines four different interrupt lines INTA#..INTD#,
-the interrupts are low level sensitive which make it possible to support
-multiple interrupt sources on the same interrupt line. Since the lines are
-level sensitive the interrupt sources must be acknowledged before clearing the
+The PCI specification defines four different interrupt lines INTA#..INTD#, the
+interrupts are low level sensitive which make it possible to support multiple
+interrupt sources on the same interrupt line. Since the lines are level
+sensitive the interrupt sources must be acknowledged before clearing the
interrupt contoller, or the interrupt controller must be masked. The BSP must
-provide a routine for clearing/acknowledging the interrupt controller, it is
-up to the interrupt service routine to acknowledge the interrupt source.
+provide a routine for clearing/acknowledging the interrupt controller, it is up
+to the interrupt service routine to acknowledge the interrupt source.
The PCI Library relies on the BSP for implementing shared interrupt handling
through the BSP_PCI_shared_interrupt_* functions/macros, they must be defined
@@ -423,10 +431,3 @@ PCI Shell command
The RTEMS shell has a PCI command 'pci' which makes it possible to read/write
configuration space, print the current PCI configuration and print out a
configuration C-file for the static or peripheral library.
-
-.. COMMENT: COPYRIGHT (c) 1988-2007.
-
-.. COMMENT: On-Line Applications Research Corporation (OAR).
-
-.. COMMENT: All rights reserved.
-