source: rtems/bsps/shared/dev/pci/pci_find_device.c @ 9ec8cfc5

5
Last change on this file since 9ec8cfc5 was 9ec8cfc5, checked in by Sebastian Huber <sebastian.huber@…>, on 04/19/18 at 04:10:36

bsps: Move pci_find_device.c to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/**
2 * @file
3 *
4 * This file implements a BSP independent version of pci_find_device().
5 */
6
7/*
8 * The software in this file was based upon the pci_find_device()
9 * implementation provided by  Till Straumann under the following terms.
10 * That implementation had been copied to multiple BSPs. This implementation
11 * is BSP independent and follows RTEMS Project coding guidelines.
12 *
13 * COPYRIGHT (c) 2016.
14 * On-Line Applications Research Corporation (OAR).
15 *
16 * Authorship
17 * ----------
18 * This software was created by
19 *     Till Straumann <strauman@slac.stanford.edu>, 2001,
20 *      Stanford Linear Accelerator Center, Stanford University.
21 *
22 * Acknowledgement of sponsorship
23 * ------------------------------
24 * This software was produced by
25 *     the Stanford Linear Accelerator Center, Stanford University,
26 *      under Contract DE-AC03-76SFO0515 with the Department of Energy.
27 *
28 * Government disclaimer of liability
29 * ----------------------------------
30 * Neither the United States nor the United States Department of Energy,
31 * nor any of their employees, makes any warranty, express or implied, or
32 * assumes any legal liability or responsibility for the accuracy,
33 * completeness, or usefulness of any data, apparatus, product, or process
34 * disclosed, or represents that its use would not infringe privately owned
35 * rights.
36 *
37 * Stanford disclaimer of liability
38 * --------------------------------
39 * Stanford University makes no representations or warranties, express or
40 * implied, nor assumes any liability for the use of this software.
41 *
42 * Stanford disclaimer of copyright
43 * --------------------------------
44 * Stanford University, owner of the copyright, hereby disclaims its
45 * copyright and all other rights in this software.  Hence, anyone may
46 * freely use it for any purpose without restriction.
47 *
48 * Maintenance of notices
49 * ----------------------
50 * In the interest of clarity regarding the origin and status of this
51 * SLAC software, this and all the preceding Stanford University notices
52 * are to remain affixed to any copy or derivative of this software made
53 * or distributed by the recipient and are to be affixed to any copy of
54 * software made or distributed by the recipient that contains a copy or
55 * derivative of this software.
56 *
57 * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
58 */
59
60
61#include <rtems/pci.h>
62#include <rtems/bspIo.h>
63#include <inttypes.h>
64#include <stdio.h>
65
66/*
67 *  Public methods from this file
68 */
69void pci_dump(FILE *f);
70
71/*
72 * These are used to construct the handle returned by pci_find_device()
73 * but the caller does not need to know how to decode them.
74 */
75#define PCIB_DEVSIG_BUS(x) (((x)>>8) &0xff)
76#define PCIB_DEVSIG_DEV(x) (((x)>>3) & 0x1f)
77#define PCIB_DEVSIG_FUNC(x) ((x) & 0x7)
78#define PCIB_DEVSIG_MAKE(b,d,f) ((b<<8)|(d<<3)|(f))
79
80/*
81 * Function pointer to helper function called during bus iteration.
82 */
83typedef int (*pci_scan_helper_t)(
84  int   bus,
85  int   dev,
86  int   fun,
87  void *uarg
88);
89
90/*
91 *
92 */
93static uint32_t pci_scan(
94  uint32_t           handle,
95  pci_scan_helper_t  helper,
96  void              *uarg
97);
98
99typedef struct {
100  uint16_t   vendor_id;
101  uint16_t   device_id;
102  int        instance;
103  uint8_t    bus;
104  uint8_t    device;
105  uint8_t    function;
106} pci_scan_arg_t;
107
108static int find_dev_helper(
109  int   bus,
110  int   device,
111  int   function,
112  void *uarg
113)
114{
115  pci_scan_arg_t  *scan = uarg;
116  uint16_t         vendor_tmp;
117  uint16_t         device_tmp;
118
119  pci_read_config_word(bus, device, function, PCI_VENDOR_ID, &vendor_tmp);
120  if (scan->vendor_id == vendor_tmp) {
121    pci_read_config_word(bus, device, function, PCI_DEVICE_ID, &device_tmp);
122    if (scan->device_id == device_tmp && scan->instance-- == 0) {
123      scan->bus      = bus;
124      scan->device   = device;
125      scan->function = function;
126
127      return 1;
128    }
129  }
130  return 0;
131}
132
133int pci_find_device(
134  uint16_t vendorid,
135  uint16_t deviceid,
136  int      instance,
137  int     *bus,
138  int     *device,
139  int     *function
140)
141{
142  pci_scan_arg_t  scan;
143
144  scan.instance   = instance;
145  scan.vendor_id  = vendorid;
146  scan.device_id  = deviceid;
147
148  if ( pci_scan(0, find_dev_helper, (void*)&scan) != 0 ) {
149    *bus      = scan.bus;
150    *device   = scan.device;
151    *function = scan.function;
152    return 0;
153  }
154  return -1;
155}
156
157static int dump_dev_helper(
158  int   bus,
159  int   device,
160  int   function,
161  void *arg
162)
163{
164  uint16_t  vendor_id;
165  uint16_t  device_id;
166  uint16_t  cmd;
167  uint16_t  status;
168  uint32_t  base0;
169  uint32_t  base1;
170  uint8_t   irq_pin;
171  uint8_t   int_line;
172  FILE     *fp = arg;
173
174  pci_read_config_word (bus, device, function, PCI_VENDOR_ID,      &vendor_id);
175  pci_read_config_word (bus, device, function, PCI_DEVICE_ID,      &device_id);
176  pci_read_config_word (bus, device, function, PCI_COMMAND,        &cmd);
177  pci_read_config_word (bus, device, function, PCI_STATUS,         &status);
178  pci_read_config_dword(bus, device, function, PCI_BASE_ADDRESS_0, &base0);
179  pci_read_config_dword(bus, device, function, PCI_BASE_ADDRESS_1, &base1);
180  pci_read_config_byte (bus, device, function, PCI_INTERRUPT_PIN,  &irq_pin);
181  pci_read_config_byte (bus, device, function, PCI_INTERRUPT_LINE, &int_line);
182
183  fprintf(
184    fp,
185    "%3d:0x%02x:%d   0x%04x:0x%04x 0x%04x 0x%04x 0x%08" PRIx32 " 0x%08" PRIx32 "   %d %3d(0x%02x)\n",
186    bus,
187    device,
188    function,
189    vendor_id,
190    device_id,
191    cmd,
192    status,
193    base0,
194    base1,
195    irq_pin,
196    int_line,
197    int_line
198  );
199  return 0;
200}
201
202void pci_dump(
203  FILE *fp
204)
205{
206  if ( !fp )
207    fp = stdout;
208  fprintf(
209    fp,
210    "BUS:SLOT:FUN VENDOR:DEV_ID   CMD  STAT   BASE_ADDR0 BASE_ADDR1 INTn IRQ_LINE\n"
211  );
212  pci_scan(0, dump_dev_helper, fp);
213}
214
215static uint32_t pci_scan(
216  uint32_t           handle,
217  pci_scan_helper_t  helper,
218  void               *arg
219)
220{
221  uint32_t vendor;
222  uint8_t  bus;
223  uint8_t  dev;
224  uint8_t  fun;
225  uint8_t  hd;
226
227  bus = PCIB_DEVSIG_BUS(  (unsigned long)handle );
228  dev = PCIB_DEVSIG_DEV(  (unsigned long)handle );
229  fun = PCIB_DEVSIG_FUNC( (unsigned long)handle );
230
231  hd = fun > 0 ? PCI_MAX_FUNCTIONS : 1;
232
233  for (; bus<pci_bus_count(); bus++, dev=0) {
234    for (; dev<PCI_MAX_DEVICES; dev++, fun=0) {
235      for (; fun<hd; fun++) {
236        /*
237         * The last devfn id/slot is special; must skip it
238         */
239        if ((PCI_MAX_DEVICES-1 == dev) && (PCI_MAX_FUNCTIONS-1 == fun) )
240          break;
241
242        (void)pci_read_config_dword(bus, dev, 0, PCI_VENDOR_ID, &vendor);
243        if (PCI_INVALID_VENDORDEVICEID == vendor)
244          continue;
245
246        if ( fun == 0 ) {
247          pci_read_config_byte(bus,dev, 0,  PCI_HEADER_TYPE, &hd);
248          hd = (hd & PCI_HEADER_TYPE_MULTI_FUNCTION ? PCI_MAX_FUNCTIONS : 1);
249        }
250
251        (void)pci_read_config_dword(bus, dev, fun, PCI_VENDOR_ID, &vendor);
252        if (PCI_INVALID_VENDORDEVICEID == vendor)
253          continue;
254        #ifdef PCI_DEBUG
255          fprintf(
256            stderr,
257            "pci_scan: found 0x%08" PRIx32 " at %d/x%02x/%d\n", vendor, bus, dev, fun
258          );
259        #endif
260        if ( (*helper)(bus, dev, fun, arg) > 0 ) {
261          if ( ++fun >= hd ) {
262            fun = 0;
263            if ( ++dev >= PCI_MAX_DEVICES ) {
264              dev = 0;
265              bus++;
266            }
267          }
268          return PCIB_DEVSIG_MAKE(bus,dev,fun);
269        }
270      }
271    }
272  }
273  return 0;
274}
Note: See TracBrowser for help on using the repository browser.