source: rtems/c/src/lib/libbsp/powerpc/shared/pci/pcifinddevice.c @ 98afe31

4.104.114.84.9
Last change on this file since 98afe31 was 98afe31, checked in by Till Straumann <strauman@…>, on Nov 4, 2005 at 3:34:08 AM

2005-11-03 Till Straumann <strauman@…>

  • 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.
  • Property mode set to 100644
File size: 3.9 KB
Line 
1
2/* Author: Till Straumann <strauman@slac.stanford.edu>, 2001 */
3
4/* find a particular PCI device
5 * (we assume, the firmware configured the PCI bus[es] for us)
6 *
7 * $Id$
8 */
9
10#define PCI_INVALID_VENDORDEVICEID  0xffffffff
11#define PCI_MULTI_FUNCTION      0x80
12
13#include <bsp/pci.h>
14#include <rtems/bspIo.h>
15#include <stdio.h>
16
17/* Stolen from i386... */
18
19/*
20 * Make device signature from bus number, device number and function
21 * number
22 */
23#define PCIB_DEVSIG_MAKE(b,d,f) ((b<<8)|(d<<3)|(f))
24
25/*
26 * Extract various parts from device signature
27 */
28#define PCIB_DEVSIG_BUS(x) (((x)>>8) &0xff)
29#define PCIB_DEVSIG_DEV(x) (((x)>>3) & 0x1f)
30#define PCIB_DEVSIG_FUNC(x) ((x) & 0x7)
31
32typedef struct {
33        unsigned short  vid,did;
34        int                             inst;
35} fd_arg;
36
37static int
38find_dev_cb(
39   int bus,
40   int dev,
41   int fun,
42   void *uarg
43) {
44fd_arg         *a = uarg;
45unsigned short  s;
46
47  pci_read_config_word(bus,dev,fun,PCI_VENDOR_ID,&s);
48  if (a->vid == s) {
49    pci_read_config_word(bus,dev,fun,PCI_DEVICE_ID,&s);
50        if (a->did == s && 0 == a->inst-- ) {
51          a->inst = PCIB_DEVSIG_MAKE( bus, dev, fun );
52          return 1;
53        }
54  }
55  return 0;
56}
57
58int
59pci_find_device(
60  unsigned short vendorid,
61  unsigned short deviceid,
62  int instance,
63  int *pbus,
64  int *pdev,
65  int *pfun
66) {
67fd_arg a;
68void   *h;
69        a.vid  = vendorid;
70        a.did  = deviceid;
71        a.inst = instance; 
72
73        if ( (h = BSP_pciScan(0, find_dev_cb, (void*)&a)) ) {
74      *pbus = PCIB_DEVSIG_BUS(  a.inst );
75      *pdev = PCIB_DEVSIG_DEV(  a.inst );
76      *pfun = PCIB_DEVSIG_FUNC( a.inst );
77          return 0;
78        }
79        return -1;
80}
81
82static int
83dump_dev_cb(
84   int bus,
85   int dev,
86   int fun,
87   void *uarg
88) {
89unsigned short vi,di;
90unsigned short cd,st;
91unsigned int   b1,b2;
92unsigned char  il,ip;
93FILE           *f = uarg;
94
95        pci_read_config_word (bus, dev, fun, PCI_VENDOR_ID,      &vi);
96        pci_read_config_word (bus, dev, fun, PCI_DEVICE_ID,      &di);
97        pci_read_config_word (bus, dev, fun, PCI_COMMAND,        &cd);
98        pci_read_config_word (bus, dev, fun, PCI_STATUS,         &st);
99        pci_read_config_dword(bus, dev, fun, PCI_BASE_ADDRESS_0, &b1);
100        pci_read_config_dword(bus, dev, fun, PCI_BASE_ADDRESS_1, &b2);
101        pci_read_config_byte (bus, dev, fun, PCI_INTERRUPT_LINE, &il);
102        pci_read_config_byte (bus, dev, fun, PCI_INTERRUPT_PIN,  &ip);
103
104        fprintf(f,"%3d:0x%02x:%d    0x%04x-0x%04x:  0x%04x 0x%04x 0x%08x 0x%08x       %d -> %3d (=0x%02x)\n",
105                bus, dev, fun, vi, di, cd, st, b1, b2, ip, il, il);
106        return 0;
107}
108
109void
110BSP_pciConfigDump(FILE *f)
111{
112        if ( !f )
113                f = stdout;
114        fprintf(f,"BUS:SLOT:FUN  VENDOR-DEV_ID: COMMAND STATUS BASE_ADDR0 BASE_ADDR1 IRQ_PIN -> IRQ_LINE\n");
115        BSP_pciScan(0, dump_dev_cb, f);
116}
117
118BSP_PciScanHandle
119BSP_pciScan(
120  BSP_PciScanHandle handle,
121  BSP_PciScannerCb cb,
122  void *uarg
123) {
124
125   unsigned int d;
126   unsigned char bus,dev,fun,hd;
127
128   bus = PCIB_DEVSIG_BUS(  (unsigned long)handle );
129   dev = PCIB_DEVSIG_DEV(  (unsigned long)handle );
130   fun = PCIB_DEVSIG_FUNC( (unsigned long)handle );
131
132   hd = fun > 0 ? PCI_MAX_FUNCTIONS : 1;
133
134   for (; bus<pci_bus_count(); bus++, dev=0) {
135     for (; dev<PCI_MAX_DEVICES; dev++, fun=0) {
136       for (; fun<hd; fun++) {
137         /*
138          * The last devfn id/slot is special; must skip it
139          */
140         if (PCI_MAX_DEVICES-1==dev && PCI_MAX_FUNCTIONS-1 == fun)
141           break;
142
143         (void)pci_read_config_dword(bus,dev,0,PCI_VENDOR_ID,&d);
144         if (PCI_INVALID_VENDORDEVICEID == d)
145           continue;
146
147         if ( 0 == fun ) {
148           pci_read_config_byte(bus,dev,0, PCI_HEADER_TYPE, &hd);
149           hd = (hd & PCI_MULTI_FUNCTION ? PCI_MAX_FUNCTIONS : 1);
150                 }
151
152        (void)pci_read_config_dword(bus,dev,fun,PCI_VENDOR_ID,&d);
153        if (PCI_INVALID_VENDORDEVICEID == d)
154          continue;
155#ifdef PCI_DEBUG
156        printk("BSP_pciScan: found 0x%08x at %d/x%02x/%d\n",d,bus,dev,fun);
157#endif
158                if ( cb(bus,dev,fun,uarg) > 0 ) {
159                        if ( ++fun >= hd ) {
160                                fun = 0;
161                                if ( ++dev >= PCI_MAX_DEVICES ) {
162                                        dev = 0;
163                                        bus++;
164                                }
165                        }
166                        return (void*) PCIB_DEVSIG_MAKE(bus,dev,fun);
167                }
168      }
169    }
170  }
171  return 0;
172}
Note: See TracBrowser for help on using the repository browser.