<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Mar 9, 2016 at 8:21 PM, Gedare Bloom <span dir="ltr"><<a href="mailto:gedare@rtems.org" target="_blank">gedare@rtems.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Wed, Mar 9, 2016 at 5:24 PM, Joel Sherrill <<a href="mailto:joel@rtems.org">joel@rtems.org</a>> wrote:<br>
> This patch fundamentally results from enhancements to the pc386 BSP<br>
> to support systems which do **NOT** have the legacy PCI BIOS. The<br>
> patch adds support for detecting when legacy PCI BIOS is not<br>
> present and then using IO space to access to PCI Configuration Space.<br>
> This resulted in dynamically selected between two implementations<br>
> of PCI and refactoring out the shared methods.<br>
><br>
> This patch adds shared implementations of pci_bus_count() and<br>
> pci_find_device(). Subsequent patches will remove implementations<br>
> of these methods in other BSPs where possible.<br>
> ---<br>
>  c/src/lib/libbsp/Makefile.am                   |   3 +<br>
>  c/src/lib/libbsp/i386/Makefile.am              |   1 +<br>
>  c/src/lib/libbsp/i386/pc386/Makefile.am        |   3 +<br>
>  c/src/lib/libbsp/i386/pc386/startup/bspstart.c |  31 ++-<br>
>  c/src/lib/libbsp/i386/shared/pci/pci_io.c      | 200 ++++++++++++++++++<br>
>  c/src/lib/libbsp/i386/shared/pci/pcibios.c     | 149 ++------------<br>
>  c/src/lib/libbsp/shared/pci/pci_bus_count.c    |  67 ++++++<br>
>  c/src/lib/libbsp/shared/pci/pci_find_device.c  | 274 +++++++++++++++++++++++++<br>
>  8 files changed, 594 insertions(+), 134 deletions(-)<br>
>  create mode 100644 c/src/lib/libbsp/i386/shared/pci/pci_io.c<br>
>  create mode 100644 c/src/lib/libbsp/shared/pci/pci_bus_count.c<br>
>  create mode 100644 c/src/lib/libbsp/shared/pci/pci_find_device.c<br>
><br>
> diff --git a/c/src/lib/libbsp/Makefile.am b/c/src/lib/libbsp/Makefile.am<br>
> index 16c276f..c54fdcb 100644<br>
> --- a/c/src/lib/libbsp/Makefile.am<br>
> +++ b/c/src/lib/libbsp/Makefile.am<br>
> @@ -29,6 +29,9 @@ EXTRA_DIST += shared/include/coverhd.h<br>
>  EXTRA_DIST += shared/gdbstub/rtems-stub-glue.c<br>
>  EXTRA_DIST += shared/include/bootcard.h<br>
><br>
> +EXTRA_DIST += shared/pci/pci_bus_count.c<br>
> +EXTRA_DIST += shared/pci/pci_find_device.c<br>
> +<br>
>  include_bspdir = $(includedir)/bsp<br>
><br>
>  include_bsp_HEADERS =<br>
> diff --git a/c/src/lib/libbsp/i386/Makefile.am b/c/src/lib/libbsp/i386/Makefile.am<br>
> index f10b764..3b6df65 100644<br>
> --- a/c/src/lib/libbsp/i386/Makefile.am<br>
> +++ b/c/src/lib/libbsp/i386/Makefile.am<br>
> @@ -22,6 +22,7 @@ EXTRA_DIST += shared/irq/irq_init.c<br>
><br>
>  # shared/pci<br>
>  EXTRA_DIST += shared/pci/pcibios.c<br>
> +EXTRA_DIST += shared/pci/pci_io.c<br>
><br>
>  include $(top_srcdir)/../../../automake/<a href="http://subdirs.am" rel="noreferrer" target="_blank">subdirs.am</a><br>
>  include $(top_srcdir)/../../../automake/<a href="http://local.am" rel="noreferrer" target="_blank">local.am</a><br>
> diff --git a/c/src/lib/libbsp/i386/pc386/Makefile.am b/c/src/lib/libbsp/i386/pc386/Makefile.am<br>
> index a9c645b..fc73afd 100644<br>
> --- a/c/src/lib/libbsp/i386/pc386/Makefile.am<br>
> +++ b/c/src/lib/libbsp/i386/pc386/Makefile.am<br>
> @@ -141,6 +141,9 @@ libbsp_a_SOURCES += ../../shared/gnatinstallhandler.c<br>
><br>
>  # pci<br>
>  libbsp_a_SOURCES += ../../i386/shared/pci/pcibios.c<br>
> +libbsp_a_SOURCES += ../../i386/shared/pci/pci_io.c<br>
> +libbsp_a_SOURCES += ../../shared/pci/pci_bus_count.c<br>
> +libbsp_a_SOURCES += ../../shared/pci/pci_find_device.c<br>
><br>
>  include_HEADERS += ../../i386/shared/comm/uart.h<br>
>  # startup<br>
> diff --git a/c/src/lib/libbsp/i386/pc386/startup/bspstart.c b/c/src/lib/libbsp/i386/pc386/startup/bspstart.c<br>
> index ac871f0..a0bbf66 100644<br>
> --- a/c/src/lib/libbsp/i386/pc386/startup/bspstart.c<br>
> +++ b/c/src/lib/libbsp/i386/pc386/startup/bspstart.c<br>
> @@ -34,17 +34,40 @@<br>
>  #include <libcpu/cpuModel.h><br>
><br>
>  /*<br>
> + * PCI Bus Configuration<br>
> + */<br>
> +rtems_pci_config_t BSP_pci_configuration = {<br>
> +  (volatile unsigned char*)0,<br>
> +  (volatile unsigned char*)0,<br>
> +  NULL<br>
> +};<br>
> +<br>
> +const pci_config_access_functions *pci_bios_initialize(void);<br>
> +const pci_config_access_functions *pci_io_initialize(void);<br>
> +<br>
> +/*<br>
>   * Helper to initialize the PCI Bus<br>
>   */<br>
>  static void bsp_pci_initialize_helper(void)<br>
>  {<br>
>  #if (BSP_IS_EDISON == 0)<br>
> -  int pci_init_retval;<br>
> +  const pci_config_access_functions *pci_accessors;<br>
><br>
> -  pci_init_retval = pci_initialize();<br>
> -  if (pci_init_retval != PCIB_ERR_SUCCESS) {<br>
> -      printk("PCI bus: could not initialize PCI BIOS interface\n");<br>
> +  pci_accessors = pci_bios_initialize();<br>
> +  if (pci_accessors != NULL) {<br>
> +    printk("PCI bus: using PCI BIOS interface\n");<br>
> +    BSP_pci_configuration.pci_functions = pci_accessors;<br>
> +    return;<br>
>    }<br>
> +<br>
> +  pci_accessors = pci_io_initialize();<br>
> +  if (pci_accessors != NULL) {<br>
> +    printk("PCI bus: using PCI I/O interface\n");<br>
> +    BSP_pci_configuration.pci_functions = pci_accessors;<br>
> +    return;<br>
> +  }<br>
> +<br>
> +  printk("PCI bus: could not initialize PCI BIOS interface\n");<br>
>  #endif<br>
>  }<br>
><br>
> diff --git a/c/src/lib/libbsp/i386/shared/pci/pci_io.c b/c/src/lib/libbsp/i386/shared/pci/pci_io.c<br>
> new file mode 100644<br>
> index 0000000..9103b5c<br>
> --- /dev/null<br>
> +++ b/c/src/lib/libbsp/i386/shared/pci/pci_io.c<br>
> @@ -0,0 +1,200 @@<br>
> +#include <rtems.h><br>
> +#include <rtems/pci.h><br>
> +#include <bsp.h><br>
> +<br>
> +static int pci_io_initialized = 0;<br>
> +<br>
> +/*<br>
> + * Forward reference. Initialized at bottom.<br>
> + */<br>
> +static const pci_config_access_functions pci_io_indirect_functions;<br>
> +<br>
> +/* prototype before defining */<br>
> +const pci_config_access_functions *pci_io_initialize(void);<br>
> +<br>
</div></div>Why isn't this coming from a header?<br>
<div><div class="h5"><br></div></div></blockquote><div><br></div><div>Just avoiding adding things to the bsp.h but that's another issue. I moved this</div><div>prototype and the additional ones in bspstart.c to include/bsp.h.</div><div><br></div><div>Eventually we have to address public/private in bsp.h but that's not this pass.</div><div><br></div><div>Thanks. I was torn on what to do.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">
> +/*<br>
> + * Detects presense of PCI Configuration is in I/O space. If so, return pointer to<br>
> + * accessor methods.<br>
> + *<br>
> + * NOTE: TBD to determine if (a) PCI Bus exists and (b) this is the access method.<br>
> + */<br>
> +const pci_config_access_functions *pci_io_initialize(void)<br>
> +{<br>
> +  pci_io_initialized = 1;<br>
> +<br>
> +  printk( "PCI I/O Support Initialized\n" );<br>
> +<br>
> +  return &pci_io_indirect_functions;<br>
> +}<br>
> +<br>
> +/*<br>
> + * Build PCI Address<br>
> + */<br>
> +static inline uint32_t pci_io_build_address(<br>
> +  uint16_t  bus,<br>
> +  uint16_t  slot,<br>
> +  uint16_t  function,<br>
> +  uint16_t  offset<br>
> +)<br>
> +{<br>
> +  uint32_t bus_u32      = (uint32_t)bus;<br>
> +  uint32_t slot_u32     = (uint32_t)slot;<br>
> +  uint32_t function_u32 = (uint32_t)function;<br>
> +  uint32_t address;<br>
> +<br>
> +  /*<br>
> +   * create configuration address as per figure at<br>
> +   *   <a href="http://wiki.osdev.org/PCI#Configuration_Space_Access_Mechanism_.231" rel="noreferrer" target="_blank">http://wiki.osdev.org/PCI#Configuration_Space_Access_Mechanism_.231</a><br>
> +   */<br>
> +  address  = (uint32_t) 0x80000000;  /* Bit  31    - Enable Bit */<br>
> +                                     /* Bits 30-24 - Reserved */<br>
> +  address |= bus_u32 << 16;          /* Bits 23-16 - Bus Number */<br>
> +  address |= slot_u32 << 11;         /* Bits 15-11 - Device/Slot Number */<br>
> +  address |= function_u32 << 8;      /* Bits 10-8  - Function Number */<br>
> +  address |= offset & 0xfc;          /* Bits 7-2   - Offset/Register Number */<br>
> +                                     /* Bits 1-0   - Reserved 0 */<br>
> +  return address;<br>
> +}<br>
> +<br>
> +static int BSP_pci_read_config_byte(<br>
> +  unsigned char bus,<br>
> +  unsigned char slot,<br>
> +  unsigned char function,<br>
> +  unsigned char offset,<br>
> +  unsigned char *value<br>
> +)<br>
> +{<br>
> +  uint32_t address;<br>
> +  uint32_t tmp;<br>
> +<br>
> +  address = pci_io_build_address( bus, slot, function, offset );<br>
> +<br>
> +  /* write out the address */<br>
> +  outport_long(0xCF8, address);<br>
> +<br>
> +  /* read in the data */<br>
> +  inport_long(0xCFC, tmp);<br>
> +<br>
> +  /* (offset & 3) * 8) = 0 will choose the first byte of the 32 bits register */<br>
> +  *value = (uint16_t)(tmp >> ((offset & 3) * 8)) & 0xff;<br>
> +  return PCIBIOS_SUCCESSFUL;<br>
> +}<br>
> +<br>
> +static int BSP_pci_read_config_word(<br>
> +  unsigned char bus,<br>
> +  unsigned char slot,<br>
> +  unsigned char function,<br>
> +  unsigned char offset,<br>
> +  unsigned short *value<br>
> +)<br>
> +{<br>
> +  uint32_t address;<br>
> +  uint32_t tmp;<br>
> +<br>
> +  address = pci_io_build_address( bus, slot, function, offset );<br>
> +<br>
> +  /* write out the address */<br>
> +  outport_long(0xCF8, address);<br>
> +<br>
> +  /* read in the data */<br>
> +  inport_long(0xCFC, tmp);<br>
> +<br>
> +  /* (offset & 2) * 8) = 0 will choose the first word of the 32 bits register */<br>
> +  *value = (uint16_t)(tmp >> ((offset & 2) * 8)) & 0xffff;<br>
> +  return PCIBIOS_SUCCESSFUL;<br>
> +}<br>
> +<br>
> +static int BSP_pci_read_config_dword(<br>
> +  unsigned char bus,<br>
> +  unsigned char slot,<br>
> +  unsigned char function,<br>
> +  unsigned char offset,<br>
> +  uint32_t     *value<br>
> +)<br>
> +{<br>
> +  uint32_t address;<br>
> +  uint32_t tmp;<br>
> +<br>
> +  address = pci_io_build_address( bus, slot, function, offset );<br>
> +<br>
> +  /* write out the address */<br>
> +  outport_long(0xCF8, address);<br>
> +<br>
> +  /* read in the data */<br>
> +  inport_long(0xCFC, tmp);<br>
> +<br>
> +  *value = tmp;<br>
> +  return PCIBIOS_SUCCESSFUL;<br>
> +}<br>
> +<br>
> +static int BSP_pci_write_config_byte(<br>
> +  unsigned char bus,<br>
> +  unsigned char slot,<br>
> +  unsigned char function,<br>
> +  unsigned char offset,<br>
> +  unsigned char value<br>
> +)<br>
> +{<br>
> +  uint32_t address;<br>
> +<br>
> +  address = pci_io_build_address( bus, slot, function, offset );<br>
> +<br>
> +  /* write out the address */<br>
> +  outport_long(0xCF8, address);<br>
> +<br>
> +  /* read in the data */<br>
> +  outport_byte(0xCFC, value);<br>
> +<br>
> +  return PCIBIOS_SUCCESSFUL;<br>
> +}<br>
> +<br>
> +static int BSP_pci_write_config_word(<br>
> +  unsigned char bus,<br>
> +  unsigned char slot,<br>
> +  unsigned char function,<br>
> +  unsigned char offset,<br>
> +  unsigned short value<br>
> +)<br>
> +{<br>
> +  uint32_t address;<br>
> +<br>
> +  address = pci_io_build_address( bus, slot, function, offset );<br>
> +<br>
> +  /* write out the address */<br>
> +  outport_long(0xCF8, address);<br>
> +<br>
> +  /* read in the data */<br>
> +  outport_word(0xCFC, value);<br>
> +<br>
> +  return PCIBIOS_SUCCESSFUL;<br>
> +}<br>
> +<br>
> +static int BSP_pci_write_config_dword(<br>
> +  unsigned char bus,<br>
> +  unsigned char slot,<br>
> +  unsigned char function,<br>
> +  unsigned char offset,<br>
> +  uint32_t      value<br>
> +)<br>
> +{<br>
> +  uint32_t address;<br>
> +<br>
> +  address = pci_io_build_address( bus, slot, function, offset );<br>
> +<br>
> +  /* write out the address */<br>
> +  outport_long(0xCF8, address);<br>
> +<br>
> +  /* read in the data */<br>
> +  outport_long(0xCFC, value);<br>
> +<br>
> +  return PCIBIOS_SUCCESSFUL;<br>
> +}<br>
> +<br>
> +static const pci_config_access_functions pci_io_indirect_functions = {<br>
> +  BSP_pci_read_config_byte,<br>
> +  BSP_pci_read_config_word,<br>
> +  BSP_pci_read_config_dword,<br>
> +  BSP_pci_write_config_byte,<br>
> +  BSP_pci_write_config_word,<br>
> +  BSP_pci_write_config_dword<br>
> +};<br>
> diff --git a/c/src/lib/libbsp/i386/shared/pci/pcibios.c b/c/src/lib/libbsp/i386/shared/pci/pcibios.c<br>
> index 7dc53a1..e746494 100644<br>
> --- a/c/src/lib/libbsp/i386/shared/pci/pcibios.c<br>
> +++ b/c/src/lib/libbsp/i386/shared/pci/pcibios.c<br>
> @@ -40,16 +40,23 @@ static int pcib_convert_err(int err);<br>
>  #define PCIB_DEVSIG_BUS(x) (((x)>>8) &0xff)<br>
>  #define PCIB_DEVSIG_DEV(x) (((x)>>3) & 0x1f)<br>
>  #define PCIB_DEVSIG_FUNC(x) ((x) & 0x7)<br>
> +<br>
>  /*<br>
> - * Detects presense of PCI BIOS, returns<br>
> - * error code<br>
> + * Forward reference. Initialized at bottom.<br>
>   */<br>
> -int<br>
> -pci_initialize(void)<br>
> +static const pci_config_access_functions pci_bios_indirect_functions;<br>
> +<br>
> +/* prototype before defining */<br>
> +const pci_config_access_functions *pci_bios_initialize(void);<br>
> +<br>
> +/*<br>
> + * Detects presense of PCI BIOS, returns pointer to accessor methods.<br>
> + */<br>
> +const pci_config_access_functions *pci_bios_initialize(void)<br>
>  {<br>
>    unsigned char *ucp;<br>
> -  unsigned char sum;<br>
> -  int      i;<br>
> +  unsigned char  sum;<br>
> +  int            i;<br>
><br>
>    pcibInitialized = 0;<br>
><br>
> @@ -80,7 +87,7 @@ pci_initialize(void)<br>
><br>
>    if (ucp >= (unsigned char *)0xFFFFF) {<br>
>      /* BIOS-32 not found */<br>
> -    return PCIB_ERR_NOTPRESENT;<br>
> +    return NULL;<br>
>    }<br>
><br>
>    /* BIOS-32 found, let us find PCI BIOS */<br>
> @@ -102,7 +109,7 @@ pci_initialize(void)<br>
><br>
>    if ((pcibExchg[0] & 0xff) != 0) {<br>
>      /* Not found */<br>
> -    return PCIB_ERR_NOTPRESENT;<br>
> +    return NULL;<br>
>    }<br>
><br>
>    /* Found PCI entry point */<br>
> @@ -125,130 +132,18 @@ pci_initialize(void)<br>
><br>
>    if ((pcibExchg[0] & 0xff00) != 0) {<br>
>      /* Not found */<br>
> -    return PCIB_ERR_NOTPRESENT;<br>
> +    return NULL;<br>
>    }<br>
><br>
>    if (pcibExchg[3] != 0x20494350) {<br>
>      /* Signature does not match */<br>
> -    return PCIB_ERR_NOTPRESENT;<br>
> +    return NULL;<br>
>    }<br>
><br>
>    /* Success */<br>
> -<br>
>    pcibInitialized = 1;<br>
> -  return PCIB_ERR_SUCCESS;<br>
> -}<br>
> -<br>
> -/*<br>
> - * Find specified device and return its signature: combination<br>
> - * of bus number, device number and function number<br>
> - */<br>
> -static int<br>
> -pcib_find_by_devid(int vendorId, int devId, int idx, int *sig)<br>
> -{<br>
> -  if (!pcibInitialized) {<br>
> -    return PCIB_ERR_UNINITIALIZED;<br>
> -  }<br>
> -<br>
> -  pcibExchg[0] = pcibEntry;<br>
> -  pcibExchg[1] = vendorId;<br>
> -  pcibExchg[2] = devId;<br>
> -  pcibExchg[3] = idx;<br>
> -<br>
> -  __asm__ ("    pusha");<br>
> -  __asm__ ("    movl pcibExchg, %edi");<br>
> -  __asm__ ("    movb $0xb1, %ah");<br>
> -  __asm__ ("    movb $0x02, %al");<br>
> -  __asm__ ("    movl pcibExchg+4, %edx");<br>
> -  __asm__ ("    movl pcibExchg+8, %ecx");<br>
> -  __asm__ ("    movl pcibExchg+12, %esi");<br>
> -  __asm__ ("    pushl %cs");<br>
> -  __asm__ ("    call *%edi");<br>
> -  __asm__ ("    movl %eax, pcibExchg");<br>
> -  __asm__ ("    movl %ebx, pcibExchg+4");<br>
> -  __asm__ ("    popa");<br>
> -<br>
> -  *sig = pcibExchg[1] & 0xffff;<br>
><br>
> -  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);<br>
> -}<br>
> -<br>
> -int<br>
> -pci_find_device(<br>
> -  unsigned short vendorid,<br>
> -  unsigned short deviceid,<br>
> -  int instance,<br>
> -  int *pbus,<br>
> -  int *pdev,<br>
> -  int *pfun<br>
> -)<br>
> -{<br>
> -  int status;<br>
> -  int sig = 0;<br>
> -<br>
> -  status = pcib_find_by_devid( vendorid, deviceid, instance, &sig );<br>
> -<br>
> -  *pbus = PCIB_DEVSIG_BUS(sig);<br>
> -  *pdev = PCIB_DEVSIG_DEV(sig);<br>
> -  *pfun = PCIB_DEVSIG_FUNC(sig);<br>
> -  return status ? -1 : 0;<br>
> -}<br>
> -<br>
> -static uint8_t ucBusCount = 0xff;<br>
> -<br>
> -unsigned char<br>
> -pci_bus_count(void)<br>
> -{<br>
> -  if ( ucBusCount == 0xff ) {<br>
> -    unsigned char bus;<br>
> -    unsigned char dev;<br>
> -    unsigned char fun;<br>
> -    unsigned char nfn;<br>
> -    unsigned char hd = 0;<br>
> -    uint32_t d = 0;<br>
> -<br>
> -    ucBusCount = 0;<br>
> -<br>
> -    for (bus=0; bus< 0xff; bus++) {<br>
> -      for (dev=0; dev<PCI_MAX_DEVICES; dev++) {<br>
> -        pci_read_config_dword(bus, dev, fun, PCI_VENDOR_ID, &d);<br>
> -<br>
> -        if ( -1 == d ) {<br>
> -          continue;<br>
> -        }<br>
> -<br>
> -        pci_read_config_byte(bus, dev, fun, PCI_HEADER_TYPE, &hd);<br>
> -        nfn = (hd & 0x80) ? PCI_MAX_FUNCTIONS : 1;<br>
> -<br>
> -        for ( fun=0; fun<nfn; fun++ ) {<br>
> -<br>
> -          pci_read_config_dword(bus, dev, fun, PCI_VENDOR_ID, &d);<br>
> -          if ( -1 == d )<br>
> -            continue;<br>
> -<br>
> -          pci_read_config_dword(bus, dev, fun, PCI_CLASS_REVISION, &d);<br>
> -<br>
> -          if ( (d >> 16) == PCI_CLASS_BRIDGE_PCI ) {<br>
> -            pci_read_config_byte(bus, dev, fun, PCI_SUBORDINATE_BUS, &hd);<br>
> -<br>
> -            if ( hd > ucBusCount )<br>
> -              ucBusCount = hd;<br>
> -          }<br>
> -<br>
> -        }<br>
> -      }<br>
> -    }<br>
> -<br>
> -    if ( ucBusCount == 0 ) {<br>
> -      printk("pci_bus_count() found 0 busses, assuming 1\n");<br>
> -      ucBusCount = 1;<br>
> -    } else if ( ucBusCount == 0xff ) {<br>
> -      printk("pci_bus_count() found 0xff busses, assuming 1\n");<br>
> -      ucBusCount = 1;<br>
> -    }<br>
> -  }<br>
> -<br>
> -  return ucBusCount;<br>
> +  return &pci_bios_indirect_functions;<br>
>  }<br>
><br>
>  /*<br>
> @@ -568,7 +463,7 @@ BSP_pci_write_config_dword(<br>
>    return PCIBIOS_SUCCESSFUL;<br>
>  }<br>
><br>
> -const pci_config_access_functions pci_indirect_functions = {<br>
> +static const pci_config_access_functions pci_bios_indirect_functions = {<br>
>    BSP_pci_read_config_byte,<br>
>    BSP_pci_read_config_word,<br>
>    BSP_pci_read_config_dword,<br>
> @@ -576,9 +471,3 @@ const pci_config_access_functions pci_indirect_functions = {<br>
>    BSP_pci_write_config_word,<br>
>    BSP_pci_write_config_dword<br>
>  };<br>
> -<br>
> -rtems_pci_config_t BSP_pci_configuration = {<br>
> -  (volatile unsigned char*)0,<br>
> -  (volatile unsigned char*)0,<br>
> -  &pci_indirect_functions<br>
> -};<br>
> diff --git a/c/src/lib/libbsp/shared/pci/pci_bus_count.c b/c/src/lib/libbsp/shared/pci/pci_bus_count.c<br>
> new file mode 100644<br>
> index 0000000..d0c7c80<br>
> --- /dev/null<br>
> +++ b/c/src/lib/libbsp/shared/pci/pci_bus_count.c<br>
> @@ -0,0 +1,67 @@<br>
> +/*<br>
> + * This software is Copyright (C) 1998 by T.sqware - all rights limited<br>
> + * It is provided in to the public domain "as is", can be freely modified<br>
> + * as far as this copyight notice is kept unchanged, but does not imply<br>
> + * an endorsement by T.sqware of the product in which it is included.<br>
> + */<br>
> +<br>
> +#include <rtems.h><br>
> +#include <rtems/pci.h><br>
> +<br>
> +static uint8_t pci_number_of_buses = 0xff;<br>
> +<br>
> +unsigned char pci_bus_count(void)<br>
> +{<br>
> +  if ( pci_number_of_buses != 0xff ) {<br>
> +    return pci_number_of_buses;<br>
> +  }<br>
> +<br>
> +  uint8_t  bus;<br>
> +  uint8_t  device;<br>
> +  uint8_t  function;<br>
> +  uint8_t  number_of_functions;<br>
> +  uint8_t  header = 0;<br>
> +  uint8_t  buses = 0;<br>
> +  uint32_t vendor = 0;<br>
> +  uint32_t class_rev = 0;<br>
> +<br>
> +  pci_number_of_buses = 0;<br>
> +<br>
> +  for (bus=0; bus < 0xff; bus++) {<br>
> +    for (device=0; device < PCI_MAX_DEVICES; device++) {<br>
> +<br>
> +       pci_read_config_dword(bus, device, 0, PCI_VENDOR_ID, &vendor);<br>
> +       if ( vendor == -1 ) {<br>
> +         continue;<br>
> +       }<br>
> +<br>
> +       pci_read_config_byte(bus, device, 0, PCI_HEADER_TYPE, &header);<br>
> +       number_of_functions = (header & 0x80) ? PCI_MAX_FUNCTIONS : 1;<br>
> +<br>
> +       for ( function=0; function < number_of_functions; function++ ) {<br>
> +         pci_read_config_dword(bus, device, function, PCI_VENDOR_ID, &vendor);<br>
> +         if ( vendor == -1 ) {<br>
> +           continue;<br>
> +         }<br>
> +<br>
> +         pci_read_config_dword(bus, device, function, PCI_CLASS_REVISION, &class_rev);<br>
> +         if ( (class_rev >> 16) == PCI_CLASS_BRIDGE_PCI ) {<br>
> +            pci_read_config_byte(bus, device, function, PCI_SUBORDINATE_BUS, &buses);<br>
> +            if ( buses > pci_number_of_buses ) {<br>
> +              pci_number_of_buses = buses;<br>
> +            }<br>
> +         }<br>
> +       }<br>
> +    }<br>
> +  }<br>
> +<br>
> +  if ( pci_number_of_buses == 0 ) {<br>
> +    printk("pci_bus_count() found 0 busses, assuming 1\n");<br>
> +    pci_number_of_buses = 1;<br>
> +  } else if ( pci_number_of_buses == 0xff ) {<br>
> +    printk("pci_bus_count() found 0xff busses, assuming 1\n");<br>
> +    pci_number_of_buses = 1;<br>
> +  }<br>
> +<br>
> +  return pci_number_of_buses;<br>
> +}<br>
> diff --git a/c/src/lib/libbsp/shared/pci/pci_find_device.c b/c/src/lib/libbsp/shared/pci/pci_find_device.c<br>
> new file mode 100644<br>
> index 0000000..1feddcc<br>
> --- /dev/null<br>
> +++ b/c/src/lib/libbsp/shared/pci/pci_find_device.c<br>
> @@ -0,0 +1,274 @@<br>
> +/**<br>
> + * @file<br>
> + *<br>
> + * This file implements a BSP independent version of pci_find_device().<br>
> + */<br>
> +<br>
> +/*<br>
> + * The software in this file was based upon the pci_find_device()<br>
> + * implementation provided by  Till Straumann under the following terms.<br>
> + * That implementation had been copied to multiple BSPs. This implementation<br>
> + * is BSP independent and follows RTEMS Project coding guidelines.<br>
> + *<br>
> + * COPYRIGHT (c) 2016.<br>
> + * On-Line Applications Research Corporation (OAR).<br>
> + *<br>
> + * Authorship<br>
> + * ----------<br>
> + * This software was created by<br>
> + *     Till Straumann <<a href="mailto:strauman@slac.stanford.edu">strauman@slac.stanford.edu</a>>, 2001,<br>
> + *      Stanford Linear Accelerator Center, Stanford University.<br>
> + *<br>
> + * Acknowledgement of sponsorship<br>
> + * ------------------------------<br>
> + * This software was produced by<br>
> + *     the Stanford Linear Accelerator Center, Stanford University,<br>
> + *      under Contract DE-AC03-76SFO0515 with the Department of Energy.<br>
> + *<br>
> + * Government disclaimer of liability<br>
> + * ----------------------------------<br>
> + * Neither the United States nor the United States Department of Energy,<br>
> + * nor any of their employees, makes any warranty, express or implied, or<br>
> + * assumes any legal liability or responsibility for the accuracy,<br>
> + * completeness, or usefulness of any data, apparatus, product, or process<br>
> + * disclosed, or represents that its use would not infringe privately owned<br>
> + * rights.<br>
> + *<br>
> + * Stanford disclaimer of liability<br>
> + * --------------------------------<br>
> + * Stanford University makes no representations or warranties, express or<br>
> + * implied, nor assumes any liability for the use of this software.<br>
> + *<br>
> + * Stanford disclaimer of copyright<br>
> + * --------------------------------<br>
> + * Stanford University, owner of the copyright, hereby disclaims its<br>
> + * copyright and all other rights in this software.  Hence, anyone may<br>
> + * freely use it for any purpose without restriction.<br>
> + *<br>
> + * Maintenance of notices<br>
> + * ----------------------<br>
> + * In the interest of clarity regarding the origin and status of this<br>
> + * SLAC software, this and all the preceding Stanford University notices<br>
> + * are to remain affixed to any copy or derivative of this software made<br>
> + * or distributed by the recipient and are to be affixed to any copy of<br>
> + * software made or distributed by the recipient that contains a copy or<br>
> + * derivative of this software.<br>
> + *<br>
> + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03<br>
> + */<br>
> +<br>
> +<br>
> +#include <rtems/pci.h><br>
> +#include <rtems/bspIo.h><br>
> +#include <inttypes.h><br>
> +#include <stdio.h><br>
> +<br>
> +/*<br>
> + *  Public methods from this file<br>
> + */<br>
> +void pci_dump(FILE *f);<br>
> +<br>
> +/*<br>
> + * These are used to construct the handle returned by pci_find_device()<br>
> + * but the caller does not need to know how to decode them.<br>
> + */<br>
> +#define PCIB_DEVSIG_BUS(x) (((x)>>8) &0xff)<br>
> +#define PCIB_DEVSIG_DEV(x) (((x)>>3) & 0x1f)<br>
> +#define PCIB_DEVSIG_FUNC(x) ((x) & 0x7)<br>
> +#define PCIB_DEVSIG_MAKE(b,d,f) ((b<<8)|(d<<3)|(f))<br>
> +<br>
> +/*<br>
> + * Function pointer to helper function called during bus iteration.<br>
> + */<br>
> +typedef int (*pci_scan_helper_t)(<br>
> +  int   bus,<br>
> +  int   dev,<br>
> +  int   fun,<br>
> +  void *uarg<br>
> +);<br>
> +<br>
> +/*<br>
> + *<br>
> + */<br>
> +static uint32_t pci_scan(<br>
> +  uint32_t           handle,<br>
> +  pci_scan_helper_t  helper,<br>
> +  void              *uarg<br>
> +);<br>
> +<br>
> +typedef struct {<br>
> +  uint16_t   vendor_id;<br>
> +  uint16_t   device_id;<br>
> +  int        instance;<br>
> +  uint8_t    bus;<br>
> +  uint8_t    device;<br>
> +  uint8_t    function;<br>
> +} pci_scan_arg_t;<br>
> +<br>
> +static int find_dev_helper(<br>
> +  int   bus,<br>
> +  int   device,<br>
> +  int   function,<br>
> +  void *uarg<br>
> +)<br>
> +{<br>
> +  pci_scan_arg_t  *scan = uarg;<br>
> +  uint16_t         vendor_tmp;<br>
> +  uint16_t         device_tmp;<br>
> +<br>
> +  pci_read_config_word(bus, device, function, PCI_VENDOR_ID, &vendor_tmp);<br>
> +  if (scan->vendor_id == vendor_tmp) {<br>
> +    pci_read_config_word(bus, device, function, PCI_DEVICE_ID, &device_tmp);<br>
> +    if (scan->device_id == device_tmp && scan->instance-- == 0) {<br>
> +      scan->bus      = bus;<br>
> +      scan->device   = device;<br>
> +      scan->function = function;<br>
> +<br>
> +      return 1;<br>
> +    }<br>
> +  }<br>
> +  return 0;<br>
> +}<br>
> +<br>
> +int pci_find_device(<br>
> +  uint16_t vendorid,<br>
> +  uint16_t deviceid,<br>
> +  int      instance,<br>
> +  int     *bus,<br>
> +  int     *device,<br>
> +  int     *function<br>
> +)<br>
> +{<br>
> +  pci_scan_arg_t  scan;<br>
> +<br>
> +  scan.instance   = instance;<br>
> +  scan.vendor_id  = vendorid;<br>
> +  scan.device_id  = deviceid;<br>
> +<br>
> +  if ( pci_scan(0, find_dev_helper, (void*)&scan) != 0 ) {<br>
> +    *bus      = scan.bus;<br>
> +    *device   = scan.device;<br>
> +    *function = scan.function;<br>
> +    return 0;<br>
> +  }<br>
> +  return -1;<br>
> +}<br>
> +<br>
> +static int dump_dev_helper(<br>
> +  int   bus,<br>
> +  int   device,<br>
> +  int   function,<br>
> +  void *arg<br>
> +)<br>
> +{<br>
> +  uint16_t  vendor_id;<br>
> +  uint16_t  device_id;<br>
> +  uint16_t  cmd;<br>
> +  uint16_t  status;<br>
> +  uint32_t  base0;<br>
> +  uint32_t  base1;<br>
> +  uint8_t   irq_pin;<br>
> +  uint8_t   int_line;<br>
> +  FILE     *fp = arg;<br>
> +<br>
> +  pci_read_config_word (bus, device, function, PCI_VENDOR_ID,      &vendor_id);<br>
> +  pci_read_config_word (bus, device, function, PCI_DEVICE_ID,      &device_id);<br>
> +  pci_read_config_word (bus, device, function, PCI_COMMAND,        &cmd);<br>
> +  pci_read_config_word (bus, device, function, PCI_STATUS,         &status);<br>
> +  pci_read_config_dword(bus, device, function, PCI_BASE_ADDRESS_0, &base0);<br>
> +  pci_read_config_dword(bus, device, function, PCI_BASE_ADDRESS_1, &base1);<br>
> +  pci_read_config_byte (bus, device, function, PCI_INTERRUPT_PIN,  &irq_pin);<br>
> +  pci_read_config_byte (bus, device, function, PCI_INTERRUPT_LINE, &int_line);<br>
> +<br>
> +  fprintf(<br>
> +    fp,<br>
> +    "%3d:0x%02x:%d   0x%04x:0x%04x 0x%04x 0x%04x 0x%08" PRIx32 " 0x%08" PRIx32 "   %d %3d(0x%02x)\n",<br>
> +    bus,<br>
> +    device,<br>
> +    function,<br>
> +    vendor_id,<br>
> +    device_id,<br>
> +    cmd,<br>
> +    status,<br>
> +    base0,<br>
> +    base1,<br>
> +    irq_pin,<br>
> +    int_line,<br>
> +    int_line<br>
> +  );<br>
> +  return 0;<br>
> +}<br>
> +<br>
> +void pci_dump(<br>
> +  FILE *fp<br>
> +)<br>
> +{<br>
> +  if ( !fp )<br>
> +    fp = stdout;<br>
> +  fprintf(<br>
> +    fp,<br>
> +    "BUS:SLOT:FUN VENDOR:DEV_ID   CMD  STAT   BASE_ADDR0 BASE_ADDR1 INTn IRQ_LINE\n"<br>
> +  );<br>
> +  pci_scan(0, dump_dev_helper, fp);<br>
> +}<br>
> +<br>
> +static uint32_t pci_scan(<br>
> +  uint32_t           handle,<br>
> +  pci_scan_helper_t  helper,<br>
> +  void               *arg<br>
> +)<br>
> +{<br>
> +  uint32_t vendor;<br>
> +  uint8_t  bus;<br>
> +  uint8_t  dev;<br>
> +  uint8_t  fun;<br>
> +  uint8_t  hd;<br>
> +<br>
> +  bus = PCIB_DEVSIG_BUS(  (unsigned long)handle );<br>
> +  dev = PCIB_DEVSIG_DEV(  (unsigned long)handle );<br>
> +  fun = PCIB_DEVSIG_FUNC( (unsigned long)handle );<br>
> +<br>
> +  hd = fun > 0 ? PCI_MAX_FUNCTIONS : 1;<br>
> +<br>
> +  for (; bus<pci_bus_count(); bus++, dev=0) {<br>
> +    for (; dev<PCI_MAX_DEVICES; dev++, fun=0) {<br>
> +      for (; fun<hd; fun++) {<br>
> +        /*<br>
> +         * The last devfn id/slot is special; must skip it<br>
> +         */<br>
> +        if ((PCI_MAX_DEVICES-1 == dev) && (PCI_MAX_FUNCTIONS-1 == fun) )<br>
> +          break;<br>
> +<br>
> +        (void)pci_read_config_dword(bus, dev, 0, PCI_VENDOR_ID, &vendor);<br>
> +        if (PCI_INVALID_VENDORDEVICEID == vendor)<br>
> +          continue;<br>
> +<br>
> +        if ( fun == 0 ) {<br>
> +          pci_read_config_byte(bus,dev, 0,  PCI_HEADER_TYPE, &hd);<br>
> +          hd = (hd & PCI_HEADER_TYPE_MULTI_FUNCTION ? PCI_MAX_FUNCTIONS : 1);<br>
> +        }<br>
> +<br>
> +        (void)pci_read_config_dword(bus, dev, fun, PCI_VENDOR_ID, &vendor);<br>
> +        if (PCI_INVALID_VENDORDEVICEID == vendor)<br>
> +          continue;<br>
> +        #ifdef PCI_DEBUG<br>
> +          fprintf(<br>
> +            stderr,<br>
> +            "pci_scan: found 0x%08" PRIx32 " at %d/x%02x/%d\n", vendor, bus, dev, fun<br>
> +          );<br>
> +        #endif<br>
> +        if ( (*helper)(bus, dev, fun, arg) > 0 ) {<br>
> +          if ( ++fun >= hd ) {<br>
> +            fun = 0;<br>
> +            if ( ++dev >= PCI_MAX_DEVICES ) {<br>
> +              dev = 0;<br>
> +              bus++;<br>
> +            }<br>
> +          }<br>
> +          return PCIB_DEVSIG_MAKE(bus,dev,fun);<br>
> +        }<br>
> +      }<br>
> +    }<br>
> +  }<br>
> +  return 0;<br>
> +}<br>
> --<br>
> 1.8.3.1<br>
><br>
</div></div>> _______________________________________________<br>
> devel mailing list<br>
> <a href="mailto:devel@rtems.org">devel@rtems.org</a><br>
> <a href="http://lists.rtems.org/mailman/listinfo/devel" rel="noreferrer" target="_blank">http://lists.rtems.org/mailman/listinfo/devel</a><br>
</blockquote></div><br></div></div>