Subversion Repositories shark

Rev

Rev 456 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
428 giacomo 1
/*
2
 *      PCI searching functions.
3
 *
4
 *      Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter,
5
 *                              David Mosberger-Tang
6
 *      Copyright 1997 -- 2000 Martin Mares <mj@ucw.cz>
7
 *      Copyright 2003 -- Greg Kroah-Hartman <greg@kroah.com>
8
 */
9
 
430 giacomo 10
#include <linuxcomp.h>
11
 
428 giacomo 12
#include <linux/init.h>
13
#include <linux/pci.h>
14
#include <linux/module.h>
15
#include <linux/interrupt.h>
16
 
17
spinlock_t pci_bus_lock = SPIN_LOCK_UNLOCKED;
18
 
19
static struct pci_bus * __devinit
20
pci_do_find_bus(struct pci_bus* bus, unsigned char busnr)
21
{
22
        struct pci_bus* child;
23
        struct list_head *tmp;
24
 
25
        if(bus->number == busnr)
26
                return bus;
27
 
28
        list_for_each(tmp, &bus->children) {
29
                child = pci_do_find_bus(pci_bus_b(tmp), busnr);
30
                if(child)
31
                        return child;
32
        }
33
        return NULL;
34
}
35
 
36
/**
37
 * pci_find_bus - locate PCI bus from a given domain and bus number
38
 * @domain: number of PCI domain to search
39
 * @busnr: number of desired PCI bus
40
 *
41
 * Given a PCI bus number and domain number, the desired PCI bus is located
42
 * in the global list of PCI buses.  If the bus is found, a pointer to its
43
 * data structure is returned.  If no bus is found, %NULL is returned.
44
 */
45
struct pci_bus * __devinit pci_find_bus(int domain, int busnr)
46
{
47
        struct pci_bus *bus = NULL;
48
        struct pci_bus *tmp_bus;
49
 
50
        while ((bus = pci_find_next_bus(bus)) != NULL)  {
456 giacomo 51
                cprintf("Domain = %d\n",pci_domain_nr(bus));
52
                if (pci_domain_nr(bus) != domain)
428 giacomo 53
                        continue;
54
                tmp_bus = pci_do_find_bus(bus, busnr);
55
                if (tmp_bus)
56
                        return tmp_bus;
57
        }
58
        return NULL;
59
}
60
 
61
/**
62
 * pci_find_next_bus - begin or continue searching for a PCI bus
63
 * @from: Previous PCI bus found, or %NULL for new search.
64
 *
65
 * Iterates through the list of known PCI busses.  A new search is
66
 * initiated by passing %NULL to the @from argument.  Otherwise if
67
 * @from is not %NULL, searches continue from next device on the
68
 * global list.
69
 */
70
struct pci_bus *
71
pci_find_next_bus(const struct pci_bus *from)
72
{
73
        struct list_head *n;
74
        struct pci_bus *b = NULL;
75
 
457 giacomo 76
        //WARN_ON(in_interrupt());
428 giacomo 77
        spin_lock(&pci_bus_lock);
78
        n = from ? from->node.next : pci_root_buses.next;
79
        if (n != &pci_root_buses)
80
                b = pci_bus_b(n);
81
        spin_unlock(&pci_bus_lock);
82
        return b;
83
}
84
 
85
/**
86
 * pci_find_slot - locate PCI device from a given PCI slot
87
 * @bus: number of PCI bus on which desired PCI device resides
88
 * @devfn: encodes number of PCI slot in which the desired PCI
89
 * device resides and the logical device number within that slot
90
 * in case of multi-function devices.
91
 *
92
 * Given a PCI bus and slot/function number, the desired PCI device
93
 * is located in system global list of PCI devices.  If the device
94
 * is found, a pointer to its data structure is returned.  If no
95
 * device is found, %NULL is returned.
96
 */
97
struct pci_dev *
98
pci_find_slot(unsigned int bus, unsigned int devfn)
99
{
100
        struct pci_dev *dev = NULL;
101
 
102
        while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
103
                if (dev->bus->number == bus && dev->devfn == devfn)
104
                        return dev;
105
        }
106
        return NULL;
107
}
108
 
109
/**
110
 * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
111
 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
112
 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
113
 * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids
114
 * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids
115
 * @from: Previous PCI device found in search, or %NULL for new search.
116
 *
117
 * Iterates through the list of known PCI devices.  If a PCI device is
118
 * found with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its
119
 * device structure is returned.  Otherwise, %NULL is returned.
120
 * A new search is initiated by passing %NULL to the @from argument.
121
 * Otherwise if @from is not %NULL, searches continue from next device on the global list.
122
 *
123
 * NOTE: Do not use this function anymore, use pci_get_subsys() instead, as
124
 * the pci device returned by this function can disappear at any moment in
125
 * time.
126
 */
127
struct pci_dev *
128
pci_find_subsys(unsigned int vendor, unsigned int device,
129
                unsigned int ss_vendor, unsigned int ss_device,
130
                const struct pci_dev *from)
131
{
132
        struct list_head *n;
133
        struct pci_dev *dev;
134
 
457 giacomo 135
        //WARN_ON(in_interrupt());
428 giacomo 136
        spin_lock(&pci_bus_lock);
137
        n = from ? from->global_list.next : pci_devices.next;
138
 
139
        while (n && (n != &pci_devices)) {
140
                dev = pci_dev_g(n);
141
                if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
142
                    (device == PCI_ANY_ID || dev->device == device) &&
143
                    (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
144
                    (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
145
                        goto exit;
146
                n = n->next;
147
        }
148
        dev = NULL;
149
exit:
150
        spin_unlock(&pci_bus_lock);
151
        return dev;
152
}
153
 
154
/**
155
 * pci_find_device - begin or continue searching for a PCI device by vendor/device id
156
 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
157
 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
158
 * @from: Previous PCI device found in search, or %NULL for new search.
159
 *
160
 * Iterates through the list of known PCI devices.  If a PCI device is
161
 * found with a matching @vendor and @device, a pointer to its device structure is
162
 * returned.  Otherwise, %NULL is returned.
163
 * A new search is initiated by passing %NULL to the @from argument.
164
 * Otherwise if @from is not %NULL, searches continue from next device on the global list.
165
 *
166
 * NOTE: Do not use this function anymore, use pci_get_device() instead, as
167
 * the pci device returned by this function can disappear at any moment in
168
 * time.
169
 */
170
struct pci_dev *
171
pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from)
172
{
173
        return pci_find_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
174
}
175
 
176
/**
177
 * pci_get_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
178
 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
179
 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
180
 * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids
181
 * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids
182
 * @from: Previous PCI device found in search, or %NULL for new search.
183
 *
184
 * Iterates through the list of known PCI devices.  If a PCI device is
185
 * found with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its
186
 * device structure is returned, and the reference count to the device is
187
 * incremented.  Otherwise, %NULL is returned.  A new search is initiated by
188
 * passing %NULL to the @from argument.  Otherwise if @from is not %NULL,
189
 * searches continue from next device on the global list.
190
 * The reference count for @from is always decremented if it is not %NULL.
191
 */
192
struct pci_dev *
193
pci_get_subsys(unsigned int vendor, unsigned int device,
194
               unsigned int ss_vendor, unsigned int ss_device,
195
               struct pci_dev *from)
196
{
197
        struct list_head *n;
198
        struct pci_dev *dev;
199
 
457 giacomo 200
        //WARN_ON(in_interrupt());
428 giacomo 201
        spin_lock(&pci_bus_lock);
202
        n = from ? from->global_list.next : pci_devices.next;
203
 
204
        while (n && (n != &pci_devices)) {
205
                dev = pci_dev_g(n);
206
                if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
207
                    (device == PCI_ANY_ID || dev->device == device) &&
208
                    (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
209
                    (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
210
                        goto exit;
211
                n = n->next;
212
        }
213
        dev = NULL;
214
exit:
215
        pci_dev_put(from);
216
        dev = pci_dev_get(dev);
217
        spin_unlock(&pci_bus_lock);
218
        return dev;
219
}
220
 
221
/**
222
 * pci_get_device - begin or continue searching for a PCI device by vendor/device id
223
 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
224
 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
225
 * @from: Previous PCI device found in search, or %NULL for new search.
226
 *
227
 * Iterates through the list of known PCI devices.  If a PCI device is
228
 * found with a matching @vendor and @device, a pointer to its device structure is
229
 * returned.  Otherwise, %NULL is returned.
230
 * A new search is initiated by passing %NULL to the @from argument.
231
 * Otherwise if @from is not %NULL, searches continue from next device on the global list.
232
 *
233
 * Iterates through the list of known PCI devices.  If a PCI device is
234
 * found with a matching @vendor and @device, the reference count to the
235
 * device is incremented and a pointer to its device structure is returned.
236
 * Otherwise, %NULL is returned.  A new search is initiated by passing %NULL
237
 * to the @from argument.  Otherwise if @from is not %NULL, searches continue
238
 * from next device on the global list.  The reference count for @from is
239
 * always decremented if it is not %NULL.
240
 */
241
struct pci_dev *
242
pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from)
243
{
244
        return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
245
}
246
 
247
 
248
/**
249
 * pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id
250
 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
251
 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
252
 * @from: Previous PCI device found in search, or %NULL for new search.
253
 *
254
 * Iterates through the list of known PCI devices in the reverse order of pci_find_device().
255
 * If a PCI device is found with a matching @vendor and @device, a pointer to
256
 * its device structure is returned.  Otherwise, %NULL is returned.
257
 * A new search is initiated by passing %NULL to the @from argument.
258
 * Otherwise if @from is not %NULL, searches continue from previous device on the global list.
259
 */
260
struct pci_dev *
261
pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct pci_dev *from)
262
{
263
        struct list_head *n;
264
        struct pci_dev *dev;
265
 
457 giacomo 266
        //WARN_ON(in_interrupt());
428 giacomo 267
        spin_lock(&pci_bus_lock);
268
        n = from ? from->global_list.prev : pci_devices.prev;
269
 
270
        while (n && (n != &pci_devices)) {
271
                dev = pci_dev_g(n);
272
                if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
273
                    (device == PCI_ANY_ID || dev->device == device))
274
                        goto exit;
275
                n = n->prev;
276
        }
277
        dev = NULL;
278
exit:
279
        spin_unlock(&pci_bus_lock);
280
        return dev;
281
}
282
 
283
 
284
/**
285
 * pci_find_class - begin or continue searching for a PCI device by class
286
 * @class: search for a PCI device with this class designation
287
 * @from: Previous PCI device found in search, or %NULL for new search.
288
 *
289
 * Iterates through the list of known PCI devices.  If a PCI device is
290
 * found with a matching @class, a pointer to its device structure is
291
 * returned.  Otherwise, %NULL is returned.
292
 * A new search is initiated by passing %NULL to the @from argument.
293
 * Otherwise if @from is not %NULL, searches continue from next device
294
 * on the global list.
295
 */
296
struct pci_dev *
297
pci_find_class(unsigned int class, const struct pci_dev *from)
298
{
299
        struct list_head *n;
300
        struct pci_dev *dev;
301
 
302
        spin_lock(&pci_bus_lock);
303
        n = from ? from->global_list.next : pci_devices.next;
304
 
305
        while (n && (n != &pci_devices)) {
306
                dev = pci_dev_g(n);
307
                if (dev->class == class)
308
                        goto exit;
309
                n = n->next;
310
        }
311
        dev = NULL;
312
exit:
313
        spin_unlock(&pci_bus_lock);
314
        return dev;
315
}
316
 
317
EXPORT_SYMBOL(pci_find_bus);
318
EXPORT_SYMBOL(pci_find_class);
319
EXPORT_SYMBOL(pci_find_device);
320
EXPORT_SYMBOL(pci_find_device_reverse);
321
EXPORT_SYMBOL(pci_find_slot);
322
EXPORT_SYMBOL(pci_find_subsys);
323
EXPORT_SYMBOL(pci_get_device);
324
EXPORT_SYMBOL(pci_get_subsys);