]> git.kernelconcepts.de Git - karo-tx-redboot.git/blobdiff - doc/html/ref/ecos-pci-library.html
Initial revision
[karo-tx-redboot.git] / doc / html / ref / ecos-pci-library.html
diff --git a/doc/html/ref/ecos-pci-library.html b/doc/html/ref/ecos-pci-library.html
new file mode 100644 (file)
index 0000000..90a8e5a
--- /dev/null
@@ -0,0 +1,787 @@
+<!-- Copyright (C) 2003 Red Hat, Inc.                                -->
+<!-- This material may be distributed only subject to the terms      -->
+<!-- and conditions set forth in the Open Publication License, v1.0  -->
+<!-- or later (the latest version is presently available at          -->
+<!-- http://www.opencontent.org/openpub/).                           -->
+<!-- Distribution of the work or derivative of the work in any       -->
+<!-- standard (paper) book form is prohibited unless prior           -->
+<!-- permission is obtained from the copyright holder.               -->
+<HTML
+><HEAD
+><TITLE
+>The eCos PCI Library</TITLE
+><meta name="MSSmartTagsPreventParsing" content="TRUE">
+<META
+NAME="GENERATOR"
+CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
+"><LINK
+REL="HOME"
+TITLE="eCos Reference Manual"
+HREF="ecos-ref.html"><LINK
+REL="UP"
+TITLE="PCI Library"
+HREF="io-pci.html"><LINK
+REL="PREVIOUS"
+TITLE="PCI Library"
+HREF="io-pci.html"><LINK
+REL="NEXT"
+TITLE="PCI Library reference"
+HREF="pci-library-reference.html"></HEAD
+><BODY
+CLASS="CHAPTER"
+BGCOLOR="#FFFFFF"
+TEXT="#000000"
+LINK="#0000FF"
+VLINK="#840084"
+ALINK="#0000FF"
+><DIV
+CLASS="NAVHEADER"
+><TABLE
+SUMMARY="Header navigation table"
+WIDTH="100%"
+BORDER="0"
+CELLPADDING="0"
+CELLSPACING="0"
+><TR
+><TH
+COLSPAN="3"
+ALIGN="center"
+>eCos Reference Manual</TH
+></TR
+><TR
+><TD
+WIDTH="10%"
+ALIGN="left"
+VALIGN="bottom"
+><A
+HREF="io-pci.html"
+ACCESSKEY="P"
+>Prev</A
+></TD
+><TD
+WIDTH="80%"
+ALIGN="center"
+VALIGN="bottom"
+></TD
+><TD
+WIDTH="10%"
+ALIGN="right"
+VALIGN="bottom"
+><A
+HREF="pci-library-reference.html"
+ACCESSKEY="N"
+>Next</A
+></TD
+></TR
+></TABLE
+><HR
+ALIGN="LEFT"
+WIDTH="100%"></DIV
+><DIV
+CLASS="CHAPTER"
+><H1
+><A
+NAME="ECOS-PCI-LIBRARY">Chapter 30. The eCos PCI Library</H1
+><DIV
+CLASS="TOC"
+><DL
+><DT
+><B
+>Table of Contents</B
+></DT
+><DT
+><A
+HREF="ecos-pci-library.html#PCI-LIBRARY"
+>PCI Library</A
+></DT
+><DT
+><A
+HREF="pci-library-reference.html"
+>PCI Library reference</A
+></DT
+></DL
+></DIV
+><P
+>The PCI library is an optional part of eCos, and is only
+       applicable to some platforms.</P
+><DIV
+CLASS="SECT1"
+><H1
+CLASS="SECT1"
+><A
+NAME="PCI-LIBRARY">PCI Library</H1
+><P
+>The eCos PCI library provides the following functionality:</P
+><P
+></P
+><OL
+TYPE="1"
+><LI
+><P
+>Scan the PCI bus for specific devices or devices of a certain
+class.</P
+></LI
+><LI
+><P
+>Read and change generic PCI information.</P
+></LI
+><LI
+><P
+>Read and change device-specific PCI information.</P
+></LI
+><LI
+><P
+>Allocate PCI memory and IO space to devices.</P
+></LI
+><LI
+><P
+>Translate a device's PCI interrupts to equivalent HAL
+vectors.</P
+></LI
+></OL
+><P
+>Example code fragments are from the pci1 test (see <TT
+CLASS="FILENAME"
+>io/pci/&lt;release&gt;/tests/pci1.c</TT
+>).</P
+><P
+>All of the functions described below are declared in the header
+file <TT
+CLASS="FILENAME"
+>&lt;cyg/io/pci.h&gt;</TT
+> which all
+clients of the PCI library should include.</P
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN12691">PCI Overview</H2
+><P
+>The PCI bus supports several address spaces: memory, IO, and configuration. All PCI
+devices must support mandatory configuration space registers. Some devices may also present
+IO mapped and/or memory mapped resources. Before devices on the bus can be used, they must
+be configured. Basically, configuration will assign PCI IO and/or memory address ranges to
+each device and then enable that device. All PCI devices have a unique address in
+configuration space. This address is comprised of a bus number, a device number, and a
+function number. Special devices called bridges are used to connect two PCI busses together.
+The PCI standard supports up to 255 busses with each bus having up to 32 devices and each
+device having up to 8 functions.</P
+><P
+>The environment in which a platform operates will dictate if and how eCos should
+configure devices on the PCI bus. If the platform acts as a host on a single PCI bus,
+then devices may be configured individually from the relevant device driver. If the
+platform is not the primary host, such as a PCI card plugged into a PC, configuration
+of PCI devices may be left to the PC BIOS. If PCI-PCI bridges are involved, configuration
+of all devices is best done all at once early in the boot process. This is because all
+devices on the secondary side of a bridge must be evaluated for their IO and memory space
+requirements before the bridge can be configured.</P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN12695">Initializing the bus</H2
+><P
+>The PCI bus needs to be initialized before it can be used.
+This only needs to be done once - some HALs may do it as part of
+the platform initialization procedure, other HALs may leave it to
+the application or device drivers to do it. The following function
+will do the initialization only once, so it's safe to call from
+multiple drivers:</P
+><TABLE
+BORDER="5"
+BGCOLOR="#E0E0F0"
+WIDTH="70%"
+><TR
+><TD
+><PRE
+CLASS="PROGRAMLISTING"
+>void cyg_pci_init( void );</PRE
+></TD
+></TR
+></TABLE
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN12699">Scanning for devices</H2
+><P
+>After the bus has been initialized, it is possible to scan
+it for devices. This is done using the function:</P
+><TABLE
+BORDER="5"
+BGCOLOR="#E0E0F0"
+WIDTH="70%"
+><TR
+><TD
+><PRE
+CLASS="PROGRAMLISTING"
+>cyg_bool cyg_pci_find_next(  cyg_pci_device_id cur_devid, 
+                            cyg_pci_device_id *next_devid );</PRE
+></TD
+></TR
+></TABLE
+><P
+>It will scan the bus for devices starting at <TT
+CLASS="PARAMETER"
+><I
+>cur_devid</I
+></TT
+>. If a device is found, its devid is stored in <TT
+CLASS="PARAMETER"
+><I
+>next_devid</I
+></TT
+> and the function returns <TT
+CLASS="CONSTANT"
+>true</TT
+>.</P
+><P
+>The <TT
+CLASS="FILENAME"
+>pci1</TT
+> test's outer loop looks like:</P
+><TABLE
+BORDER="5"
+BGCOLOR="#E0E0F0"
+WIDTH="70%"
+><TR
+><TD
+><PRE
+CLASS="PROGRAMLISTING"
+>    cyg_pci_init();
+    if (cyg_pci_find_next(CYG_PCI_NULL_DEVID, &amp;devid)) {
+        do {
+             &lt;use devid&gt;
+        } while (cyg_pci_find_next(devid, &amp;devid));
+    }</PRE
+></TD
+></TR
+></TABLE
+><P
+>What happens is that the bus gets initialized and a scan is
+started. <TT
+CLASS="LITERAL"
+>CYG_PCI_NULL_DEVID</TT
+> causes <TT
+CLASS="FUNCTION"
+>cyg_pci_find_next()</TT
+> to restart its scan. If the bus does not
+contain any devices, the first call to <TT
+CLASS="FUNCTION"
+>cyg_pci_find_next()</TT
+>
+will return <TT
+CLASS="CONSTANT"
+>false</TT
+>.</P
+><P
+>If the call returns <TT
+CLASS="CONSTANT"
+>true</TT
+>, a loop is entered where
+the found devid is used. After devid processing has completed, the next device
+on the bus is searched for; <TT
+CLASS="FUNCTION"
+>cyg_pci_find_next()</TT
+>
+continues its scan from the current devid. The loop terminates when
+no more devices are found on the bus.</P
+><P
+>This is the generic way of scanning the bus, enumerating all
+the devices on the bus. But if the application is looking for a
+device of a given device class (e.g., a SCSI controller), or a specific
+vendor device, these functions simplify the task a bit:</P
+><TABLE
+BORDER="5"
+BGCOLOR="#E0E0F0"
+WIDTH="70%"
+><TR
+><TD
+><PRE
+CLASS="PROGRAMLISTING"
+>cyg_bool cyg_pci_find_class(  cyg_uint32 dev_class,
+                              cyg_pci_device_id *devid );
+cyg_bool cyg_pci_find_device(  cyg_uint16 vendor, cyg_uint16 device,
+                               cyg_pci_device_id *devid );</PRE
+></TD
+></TR
+></TABLE
+><P
+>They work just like <TT
+CLASS="FUNCTION"
+>cyg_pci_find_next()</TT
+>,
+but only return true when the dev_class or vendor/device
+qualifiers match those of a device on the bus. The devid serves
+as both an input and an output operand: the scan starts at the given
+device, and if a device is found devid is updated with the value
+for the found device.</P
+><P
+>The <TT
+CLASS="FILENAME"
+>&lt;cyg/io/pci_cfg.h&gt;</TT
+> header
+file (included by <TT
+CLASS="FILENAME"
+>pci.h</TT
+>) contains definitions for PCI 
+class, vendor and device codes which can be used as arguments to the find
+functions.
+The list of vendor and device codes is not complete: add new codes
+as necessary. If possible also register the codes at the PCI Code
+List (<A
+HREF="http://www.yourvote.com/pci"
+TARGET="_top"
+>http://www.yourvote.com/pci)</A
+> which is where the eCos definitions are generated from.</P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN12726">Generic config information</H2
+><P
+>When a valid device ID (devid) is found using one of the above
+functions, the associated device can be queried and controlled using
+the functions:</P
+><TABLE
+BORDER="5"
+BGCOLOR="#E0E0F0"
+WIDTH="70%"
+><TR
+><TD
+><PRE
+CLASS="PROGRAMLISTING"
+>void cyg_pci_get_device_info (  cyg_pci_device_id devid, 
+                                cyg_pci_device *dev_info );
+void cyg_pci_set_device_info (  cyg_pci_device_id devid, 
+                                cyg_pci_device *dev_info );</PRE
+></TD
+></TR
+></TABLE
+><P
+>The <SPAN
+CLASS="STRUCTNAME"
+>cyg_pci_device structure</SPAN
+> (defined in
+<TT
+CLASS="FILENAME"
+>pci.h</TT
+>) primarily holds information as described by the PCI
+ specification <A
+HREF="ecos-pci-library.html#PCI-SPEC"
+>[1]</A
+>.
+The <TT
+CLASS="FILENAME"
+>pci1</TT
+> test prints out some of this information:</P
+><TABLE
+BORDER="5"
+BGCOLOR="#E0E0F0"
+WIDTH="70%"
+><TR
+><TD
+><PRE
+CLASS="PROGRAMLISTING"
+>            // Get device info
+            cyg_pci_get_device_info(devid, &amp;dev_info);
+            diag_printf("\n Command   0x%04x, Status 0x%04x\n",
+                        dev_info.command, dev_info.status);</PRE
+></TD
+></TR
+></TABLE
+><P
+>The command register can also be written to, controlling (among
+other things) whether the device responds to IO and memory access
+from the bus. </P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN12737">Specific config information</H2
+><P
+>The above functions only allow access to generic PCI config
+registers. A device can have extra config registers not specified
+by the PCI specification. These can be accessed with these functions:</P
+><TABLE
+BORDER="5"
+BGCOLOR="#E0E0F0"
+WIDTH="70%"
+><TR
+><TD
+><PRE
+CLASS="PROGRAMLISTING"
+>void cyg_pci_read_config_uint8(  cyg_pci_device_id devid,
+                                 cyg_uint8 offset, cyg_uint8 *val);
+void cyg_pci_read_config_uint16(  cyg_pci_device_id devid,
+                                  cyg_uint8 offset, cyg_uint16 *val);
+void cyg_pci_read_config_uint32(  cyg_pci_device_id devid,
+                                  cyg_uint8 offset, cyg_uint32 *val);
+void cyg_pci_write_config_uint8(  cyg_pci_device_id devid,
+                                  cyg_uint8 offset, cyg_uint8 val);
+void cyg_pci_write_config_uint16(  cyg_pci_device_id devid,
+                                   cyg_uint8 offset, cyg_uint16 val);
+void cyg_pci_write_config_uint32(  cyg_pci_device_id devid,
+                                   cyg_uint8 offset, cyg_uint32 val);</PRE
+></TD
+></TR
+></TABLE
+><P
+>The write functions should only be used for device-specific
+config registers since using them on generic registers may invalidate
+the contents of a previously fetched cyg_pci_device
+structure.</P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN12742">Allocating memory</H2
+><P
+>A PCI device ignores all IO and memory access from the PCI
+bus until it has been activated. Activation cannot happen until
+after device configuration. Configuration means telling the device
+where it should map its IO and memory resources. This is done with
+one of the following functions::</P
+><TABLE
+BORDER="5"
+BGCOLOR="#E0E0F0"
+WIDTH="70%"
+><TR
+><TD
+><PRE
+CLASS="PROGRAMLISTING"
+>cyg_bool cyg_pci_configure_device( cyg_pci_device *dev_info );
+cyg_bool cyg_pci_configure_bus( cyg_uint8 bus, cyg_uint8 *next_bus );</PRE
+></TD
+></TR
+></TABLE
+><P
+>The <TT
+CLASS="FUNCTION"
+>cyg_pci_configure_device</TT
+> handles all IO
+and memory regions that need configuration on non-bridge devices. On
+platforms with multiple busses connected by bridges, the <TT
+CLASS="FUNCTION"
+>cyg_pci_configure_bus</TT
+> function should be used. It will recursively
+configure all devices on the given <TT
+CLASS="PARAMETER"
+><I
+>bus</I
+></TT
+> and all
+subordinate busses. <TT
+CLASS="FUNCTION"
+>cyg_pci_configure_bus</TT
+> will
+use <TT
+CLASS="FUNCTION"
+>cyg_pci_configure_device</TT
+> to configure
+individual non-bridge devices.</P
+><P
+> Each region is represented in the PCI device's config space by BARs
+(Base Address Registers) and is handled individually according to type
+using these functions:</P
+><TABLE
+BORDER="5"
+BGCOLOR="#E0E0F0"
+WIDTH="70%"
+><TR
+><TD
+><PRE
+CLASS="PROGRAMLISTING"
+>cyg_bool cyg_pci_allocate_memory(  cyg_pci_device *dev_info,
+                                   cyg_uint32 bar, 
+                                   CYG_PCI_ADDRESS64 *base );
+cyg_bool cyg_pci_allocate_io(  cyg_pci_device *dev_info,
+                               cyg_uint32 bar, 
+                               CYG_PCI_ADDRESS32 *base );</PRE
+></TD
+></TR
+></TABLE
+><P
+>The memory bases (in two distinct address spaces) are increased
+as memory regions are allocated to devices. Allocation will fail
+(the function returns false) if the base exceeds the limits of the
+address space (IO is 1MB, memory is 2^32 or 2^64 bytes).</P
+><P
+>These functions can also be called directly by the application/driver
+if necessary, but this should not be necessary.</P
+><P
+>The bases are initialized with default values provided by
+the HAL. It is possible for an application to override these using
+the following functions: </P
+><TABLE
+BORDER="5"
+BGCOLOR="#E0E0F0"
+WIDTH="70%"
+><TR
+><TD
+><PRE
+CLASS="PROGRAMLISTING"
+>void cyg_pci_set_memory_base(  CYG_PCI_ADDRESS64 base );
+void cyg_pci_set_io_base( CYG_PCI_ADDRESS32 base );</PRE
+></TD
+></TR
+></TABLE
+><P
+>When a device has been configured, the cyg_pci_device
+structure will contain the physical address in the CPU's
+address space where the device's memory regions can be
+accessed. </P
+><P
+>This information is provided in <TT
+CLASS="VARNAME"
+>base_map[]</TT
+> -
+there is a 32 bit word for each of the device's BARs. For
+32 bit PCI memory regions, each 32 bit word will be an actual pointer
+that can be used immediately by the driver: the memory space will normally
+be linearly addressable by the CPU.</P
+><P
+>However, for 64 bit PCI memory regions, some (or all) of the
+region may be outside of the CPUs address space. In this case the
+driver will need to know how to access the region in segments. This
+functionality may be adopted by the eCos HAL if deemed useful in
+the future. The 2GB available on many systems should suffice though.</P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="PCI-INTERRUPTS">Interrupts</H2
+><P
+>A device may generate interrupts. The HAL vector associated
+with a given device on the bus is platform specific. This function
+allows a driver to find the actual interrupt vector for a given
+device:</P
+><TABLE
+BORDER="5"
+BGCOLOR="#E0E0F0"
+WIDTH="70%"
+><TR
+><TD
+><PRE
+CLASS="PROGRAMLISTING"
+>cyg_bool cyg_pci_translate_interrupt(  cyg_pci_device *dev_info,
+                                       CYG_ADDRWORD *vec );</PRE
+></TD
+></TR
+></TABLE
+><P
+>If the function returns false, no interrupts will be generated
+by the device. If it returns true, the CYG_ADDRWORD pointed
+to by vec is updated with the HAL interrupt vector the device will
+be using. This is how the function is used in the <TT
+CLASS="FILENAME"
+>pci1</TT
+>
+test:</P
+><TABLE
+BORDER="5"
+BGCOLOR="#E0E0F0"
+WIDTH="70%"
+><TR
+><TD
+><PRE
+CLASS="PROGRAMLISTING"
+>            if (cyg_pci_translate_interrupt(&amp;dev_info, &amp;irq))
+                diag_printf(" Wired to HAL vector %d\n", irq);
+            else
+                diag_printf(" Does not generate interrupts.\n");</PRE
+></TD
+></TR
+></TABLE
+><P
+>The application/drive should attach an interrupt
+handler to a device's interrupt before activating the device.</P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN12770">Activating a device</H2
+><P
+>When the device has been allocated memory space it can be
+activated. This is not done by the library since a driver may have
+to initialize more state on the device before it can be safely activated.</P
+><P
+>Activating the device is done by enabling flags in its command
+word. As an example, see the <TT
+CLASS="FILENAME"
+>pci1</TT
+> test which can be
+configured to enable the devices it finds. This allows these to be accessed from
+GDB (if a breakpoint is set on <TT
+CLASS="FUNCTION"
+>cyg_test_exit</TT
+>):</P
+><TABLE
+BORDER="5"
+BGCOLOR="#E0E0F0"
+WIDTH="70%"
+><TR
+><TD
+><PRE
+CLASS="PROGRAMLISTING"
+>#ifdef ENABLE_PCI_DEVICES
+      {
+          cyg_uint16 cmd;
+
+          // Don't use cyg_pci_set_device_info since it clears
+          // some of the fields we want to print out below.
+          cyg_pci_read_config_uint16(dev_info.devid,
+                                     CYG_PCI_CFG_COMMAND, &amp;cmd);
+          cmd |= CYG_PCI_CFG_COMMAND_IO|CYG_PCI_CFG_COMMAND_MEMORY;
+          cyg_pci_write_config_uint16(dev_info.devid,
+                                      CYG_PCI_CFG_COMMAND, cmd);
+      }
+      diag_printf(" **** Device IO and MEM access enabled\n");
+#endif</PRE
+></TD
+></TR
+></TABLE
+><DIV
+CLASS="NOTE"
+><BLOCKQUOTE
+CLASS="NOTE"
+><P
+><B
+>Note: </B
+>The best way to activate a device is actually
+through <TT
+CLASS="FUNCTION"
+>cyg_pci_set_device_info()</TT
+>,
+but in this particular case the <SPAN
+CLASS="STRUCTNAME"
+>cyg_pci_device</SPAN
+>
+structure contents from before the activation is required for printout
+further down in the code.</P
+></BLOCKQUOTE
+></DIV
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN12782">Links</H2
+><P
+>See these links for more information about PCI:</P
+><P
+></P
+><OL
+TYPE="1"
+><LI
+><P
+><A
+NAME="PCI-SPEC"
+></A
+><A
+HREF="http://www.pcisig.com/"
+TARGET="_top"
+>http://www.pcisig.com/</A
+> - information on the PCI specifications</P
+></LI
+><LI
+><P
+><A
+HREF="http://www.yourvote.com/pci/"
+TARGET="_top"
+>http://www.yourvote.com/pci/</A
+> - list of vendor and device IDs</P
+></LI
+><LI
+><P
+><A
+HREF="http://www.picmg.org/"
+TARGET="_top"
+>http://www.picmg.org/</A
+> - PCI Industrial Computer Manufacturers Group</P
+></LI
+></OL
+></DIV
+></DIV
+></DIV
+><DIV
+CLASS="NAVFOOTER"
+><HR
+ALIGN="LEFT"
+WIDTH="100%"><TABLE
+SUMMARY="Footer navigation table"
+WIDTH="100%"
+BORDER="0"
+CELLPADDING="0"
+CELLSPACING="0"
+><TR
+><TD
+WIDTH="33%"
+ALIGN="left"
+VALIGN="top"
+><A
+HREF="io-pci.html"
+ACCESSKEY="P"
+>Prev</A
+></TD
+><TD
+WIDTH="34%"
+ALIGN="center"
+VALIGN="top"
+><A
+HREF="ecos-ref.html"
+ACCESSKEY="H"
+>Home</A
+></TD
+><TD
+WIDTH="33%"
+ALIGN="right"
+VALIGN="top"
+><A
+HREF="pci-library-reference.html"
+ACCESSKEY="N"
+>Next</A
+></TD
+></TR
+><TR
+><TD
+WIDTH="33%"
+ALIGN="left"
+VALIGN="top"
+>PCI Library</TD
+><TD
+WIDTH="34%"
+ALIGN="center"
+VALIGN="top"
+><A
+HREF="io-pci.html"
+ACCESSKEY="U"
+>Up</A
+></TD
+><TD
+WIDTH="33%"
+ALIGN="right"
+VALIGN="top"
+>PCI Library reference</TD
+></TR
+></TABLE
+></DIV
+></BODY
+></HTML
+>
\ No newline at end of file