diff options
author | Till Straumann <strauman@slac.stanford.edu> | 2005-11-04 03:34:08 +0000 |
---|---|---|
committer | Till Straumann <strauman@slac.stanford.edu> | 2005-11-04 03:34:08 +0000 |
commit | 98afe3169509bceb7d81ad056fc16d16b71b006a (patch) | |
tree | b69c3f20cb82fd70e1612ec4a72f4a169fc62cf8 /c/src/lib/libbsp/powerpc/shared/pci/pcifinddevice.c | |
parent | 2005-11-03 Till Straumann <strauman@slac.stanford.edu> (diff) | |
download | rtems-98afe3169509bceb7d81ad056fc16d16b71b006a.tar.bz2 |
2005-11-03 Till Straumann <strauman@slac.stanford.edu>
* shared/motorola/motorola.c, shared/pci/detect_raven_bridge.c,
shared/pci/pci.c, shared/pci/pci.h, shared/pci/pcifinddevice.c:
Several PCI enhancements and fixes: all BSP flavors now use the
generic clear_hostbridge_errors() routine (this means that only
polling memory probing is possible [see detect_raven_bridge.c for
details]). Interrupt fixup routine now supports multi-function
devices. Interrupt fixup routine now honours a flag/option so that
wrong firmware values can be overridden. Fixed irq routing table for
mvme2100 [PMC]. Added irq routing table for mvme2300. Added a
BSP_pciScan() routine that executes a user callback on each non-empty
slot/fun. Added BSP_pciConfigDump() to display basic config headers.
Diffstat (limited to 'c/src/lib/libbsp/powerpc/shared/pci/pcifinddevice.c')
-rw-r--r-- | c/src/lib/libbsp/powerpc/shared/pci/pcifinddevice.c | 150 |
1 files changed, 131 insertions, 19 deletions
diff --git a/c/src/lib/libbsp/powerpc/shared/pci/pcifinddevice.c b/c/src/lib/libbsp/powerpc/shared/pci/pcifinddevice.c index 2c2c011dca..c660877680 100644 --- a/c/src/lib/libbsp/powerpc/shared/pci/pcifinddevice.c +++ b/c/src/lib/libbsp/powerpc/shared/pci/pcifinddevice.c @@ -12,6 +12,48 @@ #include <bsp/pci.h> #include <rtems/bspIo.h> +#include <stdio.h> + +/* Stolen from i386... */ + +/* + * Make device signature from bus number, device number and function + * number + */ +#define PCIB_DEVSIG_MAKE(b,d,f) ((b<<8)|(d<<3)|(f)) + +/* + * Extract various parts from device signature + */ +#define PCIB_DEVSIG_BUS(x) (((x)>>8) &0xff) +#define PCIB_DEVSIG_DEV(x) (((x)>>3) & 0x1f) +#define PCIB_DEVSIG_FUNC(x) ((x) & 0x7) + +typedef struct { + unsigned short vid,did; + int inst; +} fd_arg; + +static int +find_dev_cb( + int bus, + int dev, + int fun, + void *uarg +) { +fd_arg *a = uarg; +unsigned short s; + + pci_read_config_word(bus,dev,fun,PCI_VENDOR_ID,&s); + if (a->vid == s) { + pci_read_config_word(bus,dev,fun,PCI_DEVICE_ID,&s); + if (a->did == s && 0 == a->inst-- ) { + a->inst = PCIB_DEVSIG_MAKE( bus, dev, fun ); + return 1; + } + } + return 0; +} int pci_find_device( @@ -22,39 +64,109 @@ pci_find_device( int *pdev, int *pfun ) { +fd_arg a; +void *h; + a.vid = vendorid; + a.did = deviceid; + a.inst = instance; + + if ( (h = BSP_pciScan(0, find_dev_cb, (void*)&a)) ) { + *pbus = PCIB_DEVSIG_BUS( a.inst ); + *pdev = PCIB_DEVSIG_DEV( a.inst ); + *pfun = PCIB_DEVSIG_FUNC( a.inst ); + return 0; + } + return -1; +} + +static int +dump_dev_cb( + int bus, + int dev, + int fun, + void *uarg +) { +unsigned short vi,di; +unsigned short cd,st; +unsigned int b1,b2; +unsigned char il,ip; +FILE *f = uarg; + + pci_read_config_word (bus, dev, fun, PCI_VENDOR_ID, &vi); + pci_read_config_word (bus, dev, fun, PCI_DEVICE_ID, &di); + pci_read_config_word (bus, dev, fun, PCI_COMMAND, &cd); + pci_read_config_word (bus, dev, fun, PCI_STATUS, &st); + pci_read_config_dword(bus, dev, fun, PCI_BASE_ADDRESS_0, &b1); + pci_read_config_dword(bus, dev, fun, PCI_BASE_ADDRESS_1, &b2); + pci_read_config_byte (bus, dev, fun, PCI_INTERRUPT_LINE, &il); + pci_read_config_byte (bus, dev, fun, PCI_INTERRUPT_PIN, &ip); + + fprintf(f,"%3d:0x%02x:%d 0x%04x-0x%04x: 0x%04x 0x%04x 0x%08x 0x%08x %d -> %3d (=0x%02x)\n", + bus, dev, fun, vi, di, cd, st, b1, b2, ip, il, il); + return 0; +} + +void +BSP_pciConfigDump(FILE *f) +{ + if ( !f ) + f = stdout; + fprintf(f,"BUS:SLOT:FUN VENDOR-DEV_ID: COMMAND STATUS BASE_ADDR0 BASE_ADDR1 IRQ_PIN -> IRQ_LINE\n"); + BSP_pciScan(0, dump_dev_cb, f); +} + +BSP_PciScanHandle +BSP_pciScan( + BSP_PciScanHandle handle, + BSP_PciScannerCb cb, + void *uarg +) { + unsigned int d; - unsigned short s; unsigned char bus,dev,fun,hd; - for (bus=0; bus<pci_bus_count(); bus++) { - for (dev=0; dev<PCI_MAX_DEVICES; dev++) { + bus = PCIB_DEVSIG_BUS( (unsigned long)handle ); + dev = PCIB_DEVSIG_DEV( (unsigned long)handle ); + fun = PCIB_DEVSIG_FUNC( (unsigned long)handle ); - pci_read_config_byte(bus,dev,0, PCI_HEADER_TYPE, &hd); - hd = (hd & PCI_MULTI_FUNCTION ? PCI_MAX_FUNCTIONS : 1); + hd = fun > 0 ? PCI_MAX_FUNCTIONS : 1; - for (fun=0; fun<hd; fun++) { + 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; + if (PCI_MAX_DEVICES-1==dev && PCI_MAX_FUNCTIONS-1 == fun) + break; + + (void)pci_read_config_dword(bus,dev,0,PCI_VENDOR_ID,&d); + if (PCI_INVALID_VENDORDEVICEID == d) + continue; + + if ( 0 == fun ) { + pci_read_config_byte(bus,dev,0, PCI_HEADER_TYPE, &hd); + hd = (hd & PCI_MULTI_FUNCTION ? PCI_MAX_FUNCTIONS : 1); + } + (void)pci_read_config_dword(bus,dev,fun,PCI_VENDOR_ID,&d); if (PCI_INVALID_VENDORDEVICEID == d) continue; #ifdef PCI_DEBUG - printk("pci_find_by_devid: found 0x%08x at %d/%d/%d\n",d,bus,dev,fun); + printk("BSP_pciScan: found 0x%08x at %d/x%02x/%d\n",d,bus,dev,fun); #endif - (void) pci_read_config_word(bus,dev,fun,PCI_VENDOR_ID,&s); - if (vendorid != s) - continue; - (void) pci_read_config_word(bus,dev,fun,PCI_DEVICE_ID,&s); - if (deviceid == s) { - if (instance--) continue; - *pbus=bus; *pdev=dev; *pfun=fun; - return 0; - } + if ( cb(bus,dev,fun,uarg) > 0 ) { + if ( ++fun >= hd ) { + fun = 0; + if ( ++dev >= PCI_MAX_DEVICES ) { + dev = 0; + bus++; + } + } + return (void*) PCIB_DEVSIG_MAKE(bus,dev,fun); + } } } } - return -1; + return 0; } |