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