1c0ff6e61SIan Romanick /*
2c0ff6e61SIan Romanick * (C) Copyright IBM Corporation 2006
3c0ff6e61SIan Romanick * All Rights Reserved.
4c0ff6e61SIan Romanick *
5c0ff6e61SIan Romanick * Permission is hereby granted, free of charge, to any person obtaining a
6c0ff6e61SIan Romanick * copy of this software and associated documentation files (the "Software"),
7c0ff6e61SIan Romanick * to deal in the Software without restriction, including without limitation
8c0ff6e61SIan Romanick * on the rights to use, copy, modify, merge, publish, distribute, sub
9c0ff6e61SIan Romanick * license, and/or sell copies of the Software, and to permit persons to whom
10c0ff6e61SIan Romanick * the Software is furnished to do so, subject to the following conditions:
11c0ff6e61SIan Romanick *
12c0ff6e61SIan Romanick * The above copyright notice and this permission notice (including the next
13c0ff6e61SIan Romanick * paragraph) shall be included in all copies or substantial portions of the
14c0ff6e61SIan Romanick * Software.
15c0ff6e61SIan Romanick *
16c0ff6e61SIan Romanick * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17c0ff6e61SIan Romanick * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18c0ff6e61SIan Romanick * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19c0ff6e61SIan Romanick * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20c0ff6e61SIan Romanick * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21c0ff6e61SIan Romanick * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22c0ff6e61SIan Romanick * DEALINGS IN THE SOFTWARE.
23c0ff6e61SIan Romanick */
24c0ff6e61SIan Romanick
25c0ff6e61SIan Romanick /**
26c0ff6e61SIan Romanick * \file common_bridge.c
27c0ff6e61SIan Romanick * Support routines used to process PCI header information for bridges.
28c0ff6e61SIan Romanick *
29c0ff6e61SIan Romanick * \author Ian Romanick <[email protected]>
30c0ff6e61SIan Romanick */
31c0ff6e61SIan Romanick
32*1a2ac5f1SChad Versace #ifndef ANDROID
33c0ff6e61SIan Romanick #include "config.h"
34*1a2ac5f1SChad Versace #endif
35*1a2ac5f1SChad Versace
36c0ff6e61SIan Romanick #include <stdio.h>
37c0ff6e61SIan Romanick #include <stdlib.h>
38c0ff6e61SIan Romanick #include <ctype.h>
39c0e31708SIan Romanick #include <errno.h>
40c0ff6e61SIan Romanick
41c0ff6e61SIan Romanick #if defined(HAVE_STRING_H)
42c0ff6e61SIan Romanick # include <string.h>
43c0ff6e61SIan Romanick #elif defined(HAVE_STRINGS_H)
44c0ff6e61SIan Romanick # include <strings.h>
45c0ff6e61SIan Romanick #endif
46c0ff6e61SIan Romanick
47c0ff6e61SIan Romanick #if defined(HAVE_INTTYPES_H)
48c0ff6e61SIan Romanick # include <inttypes.h>
49c0ff6e61SIan Romanick #elif defined(HAVE_STDINT_H)
50c0ff6e61SIan Romanick # include <stdint.h>
51c0ff6e61SIan Romanick #endif
52c0ff6e61SIan Romanick
53c0ff6e61SIan Romanick #include "pciaccess.h"
54c0ff6e61SIan Romanick #include "pciaccess_private.h"
55c0ff6e61SIan Romanick
56c0ff6e61SIan Romanick static int
read_bridge_info(struct pci_device_private * priv)57c0ff6e61SIan Romanick read_bridge_info( struct pci_device_private * priv )
58c0ff6e61SIan Romanick {
59c0ff6e61SIan Romanick uint8_t buf[0x40];
60c0ff6e61SIan Romanick pciaddr_t bytes;
6128dc34c2SIan Romanick int err;
62c0ff6e61SIan Romanick
63c0ff6e61SIan Romanick
6428dc34c2SIan Romanick /* Make sure the device has been probed. If not, header_type won't be
6528dc34c2SIan Romanick * set and the rest of this function will fail.
6628dc34c2SIan Romanick */
6728dc34c2SIan Romanick err = pci_device_probe(& priv->base);
6828dc34c2SIan Romanick if (err) {
6928dc34c2SIan Romanick return err;
7028dc34c2SIan Romanick }
7128dc34c2SIan Romanick
72c0ff6e61SIan Romanick switch ( priv->header_type & 0x7f ) {
73c0ff6e61SIan Romanick case 0x00:
74c0ff6e61SIan Romanick break;
75c0ff6e61SIan Romanick
76c0ff6e61SIan Romanick case 0x01: {
77c0ff6e61SIan Romanick struct pci_bridge_info *info;
78c0ff6e61SIan Romanick
79c0ff6e61SIan Romanick info = malloc(sizeof(*info));
80c0ff6e61SIan Romanick if (info != NULL) {
81c0ff6e61SIan Romanick pci_device_cfg_read( (struct pci_device *) priv, buf + 0x18, 0x18,
82c0ff6e61SIan Romanick 0x40 - 0x18, & bytes );
83c0ff6e61SIan Romanick
84c0ff6e61SIan Romanick info->primary_bus = buf[0x18];
85c0ff6e61SIan Romanick info->secondary_bus = buf[0x19];
86c0ff6e61SIan Romanick info->subordinate_bus = buf[0x1a];
87c0ff6e61SIan Romanick info->secondary_latency_timer = buf[0x1b];
88c0ff6e61SIan Romanick
89c0ff6e61SIan Romanick info->io_type = buf[0x1c] & 0x0f;
90c0ff6e61SIan Romanick info->io_base = (((uint32_t) (buf[0x1c] & 0x0f0)) << 8)
91c0ff6e61SIan Romanick + (((uint32_t) buf[0x30]) << 16)
92c0ff6e61SIan Romanick + (((uint32_t) buf[0x31]) << 24);
93c0ff6e61SIan Romanick
94c0ff6e61SIan Romanick info->io_limit = 0x00000fff
95c0ff6e61SIan Romanick + (((uint32_t) (buf[0x1d] & 0x0f0)) << 8)
96c0ff6e61SIan Romanick + (((uint32_t) buf[0x32]) << 16)
97c0ff6e61SIan Romanick + (((uint32_t) buf[0x33]) << 24);
98c0ff6e61SIan Romanick
99c0ff6e61SIan Romanick info->mem_type = buf[0x20] & 0x0f;
100c0ff6e61SIan Romanick info->mem_base = (((uint32_t) (buf[0x20] & 0x0f0)) << 16)
101c0ff6e61SIan Romanick + (((uint32_t) buf[0x21]) << 24);
102c0ff6e61SIan Romanick
103c0ff6e61SIan Romanick info->mem_limit = 0x0000ffff
104c0ff6e61SIan Romanick + (((uint32_t) (buf[0x22] & 0x0f0)) << 16)
105c0ff6e61SIan Romanick + (((uint32_t) buf[0x23]) << 24);
106c0ff6e61SIan Romanick
107c0ff6e61SIan Romanick info->prefetch_mem_type = buf[0x24] & 0x0f;
108c0ff6e61SIan Romanick info->prefetch_mem_base = (((uint64_t) (buf[0x24] & 0x0f0)) << 16)
109c0ff6e61SIan Romanick + (((uint64_t) buf[0x25]) << 24)
110c0ff6e61SIan Romanick + (((uint64_t) buf[0x28]) << 32)
111c0ff6e61SIan Romanick + (((uint64_t) buf[0x29]) << 40)
112c0ff6e61SIan Romanick + (((uint64_t) buf[0x2a]) << 48)
113c0ff6e61SIan Romanick + (((uint64_t) buf[0x2b]) << 56);
114c0ff6e61SIan Romanick
115c0ff6e61SIan Romanick info->prefetch_mem_limit = 0x0000ffff
116c0ff6e61SIan Romanick + (((uint64_t) (buf[0x26] & 0x0f0)) << 16)
117c0ff6e61SIan Romanick + (((uint64_t) buf[0x27]) << 24)
118c0ff6e61SIan Romanick + (((uint64_t) buf[0x2c]) << 32)
119c0ff6e61SIan Romanick + (((uint64_t) buf[0x2d]) << 40)
120c0ff6e61SIan Romanick + (((uint64_t) buf[0x2e]) << 48)
121c0ff6e61SIan Romanick + (((uint64_t) buf[0x2f]) << 56);
122c0ff6e61SIan Romanick
123c0ff6e61SIan Romanick info->bridge_control = ((uint16_t) buf[0x3e])
124c0ff6e61SIan Romanick + (((uint16_t) buf[0x3f]) << 8);
125c0ff6e61SIan Romanick
126c0ff6e61SIan Romanick info->secondary_status = ((uint16_t) buf[0x1e])
127c0ff6e61SIan Romanick + (((uint16_t) buf[0x1f]) << 8);
128c0ff6e61SIan Romanick }
129c0ff6e61SIan Romanick
130c0ff6e61SIan Romanick priv->bridge.pci = info;
131c0ff6e61SIan Romanick break;
132c0ff6e61SIan Romanick }
133c0ff6e61SIan Romanick
134c0ff6e61SIan Romanick case 0x02: {
135c0ff6e61SIan Romanick struct pci_pcmcia_bridge_info *info;
136c0ff6e61SIan Romanick
137c0ff6e61SIan Romanick info = malloc(sizeof(*info));
138c0ff6e61SIan Romanick if (info != NULL) {
139c0ff6e61SIan Romanick pci_device_cfg_read( (struct pci_device *) priv, buf + 0x16, 0x16,
140c0ff6e61SIan Romanick 0x40 - 0x16, & bytes );
141c0ff6e61SIan Romanick
142c0ff6e61SIan Romanick info->primary_bus = buf[0x18];
143c0ff6e61SIan Romanick info->card_bus = buf[0x19];
144c0ff6e61SIan Romanick info->subordinate_bus = buf[0x1a];
145c0ff6e61SIan Romanick info->cardbus_latency_timer = buf[0x1b];
146c0ff6e61SIan Romanick
147c0ff6e61SIan Romanick info->mem[0].base = (((uint32_t) buf[0x1c]))
148c0ff6e61SIan Romanick + (((uint32_t) buf[0x1d]) << 8)
149c0ff6e61SIan Romanick + (((uint32_t) buf[0x1e]) << 16)
150c0ff6e61SIan Romanick + (((uint32_t) buf[0x1f]) << 24);
151c0ff6e61SIan Romanick
152c0ff6e61SIan Romanick info->mem[0].limit = (((uint32_t) buf[0x20]))
153c0ff6e61SIan Romanick + (((uint32_t) buf[0x21]) << 8)
154c0ff6e61SIan Romanick + (((uint32_t) buf[0x22]) << 16)
155c0ff6e61SIan Romanick + (((uint32_t) buf[0x23]) << 24);
156c0ff6e61SIan Romanick
157c0ff6e61SIan Romanick info->mem[1].base = (((uint32_t) buf[0x24]))
158c0ff6e61SIan Romanick + (((uint32_t) buf[0x25]) << 8)
159c0ff6e61SIan Romanick + (((uint32_t) buf[0x26]) << 16)
160c0ff6e61SIan Romanick + (((uint32_t) buf[0x27]) << 24);
161c0ff6e61SIan Romanick
162c0ff6e61SIan Romanick info->mem[1].limit = (((uint32_t) buf[0x28]))
163c0ff6e61SIan Romanick + (((uint32_t) buf[0x29]) << 8)
164c0ff6e61SIan Romanick + (((uint32_t) buf[0x2a]) << 16)
165c0ff6e61SIan Romanick + (((uint32_t) buf[0x2b]) << 24);
166c0ff6e61SIan Romanick
167c0ff6e61SIan Romanick info->io[0].base = (((uint32_t) buf[0x2c]))
168c0ff6e61SIan Romanick + (((uint32_t) buf[0x2d]) << 8)
169c0ff6e61SIan Romanick + (((uint32_t) buf[0x2e]) << 16)
170c0ff6e61SIan Romanick + (((uint32_t) buf[0x2f]) << 24);
171c0ff6e61SIan Romanick
172c0ff6e61SIan Romanick info->io[0].limit = (((uint32_t) buf[0x30]))
173c0ff6e61SIan Romanick + (((uint32_t) buf[0x31]) << 8)
174c0ff6e61SIan Romanick + (((uint32_t) buf[0x32]) << 16)
175c0ff6e61SIan Romanick + (((uint32_t) buf[0x33]) << 24);
176c0ff6e61SIan Romanick
177c0ff6e61SIan Romanick info->io[1].base = (((uint32_t) buf[0x34]))
178c0ff6e61SIan Romanick + (((uint32_t) buf[0x35]) << 8)
179c0ff6e61SIan Romanick + (((uint32_t) buf[0x36]) << 16)
180c0ff6e61SIan Romanick + (((uint32_t) buf[0x37]) << 24);
181c0ff6e61SIan Romanick
182c0ff6e61SIan Romanick info->io[1].limit = (((uint32_t) buf[0x38]))
183c0ff6e61SIan Romanick + (((uint32_t) buf[0x39]) << 8)
184c0ff6e61SIan Romanick + (((uint32_t) buf[0x3a]) << 16)
185c0ff6e61SIan Romanick + (((uint32_t) buf[0x3b]) << 24);
186c0ff6e61SIan Romanick
187c0ff6e61SIan Romanick info->secondary_status = ((uint16_t) buf[0x16])
188c0ff6e61SIan Romanick + (((uint16_t) buf[0x17]) << 8);
189c0ff6e61SIan Romanick
190c0ff6e61SIan Romanick info->bridge_control = ((uint16_t) buf[0x3e])
191c0ff6e61SIan Romanick + (((uint16_t) buf[0x3f]) << 8);
192c0ff6e61SIan Romanick }
193c0ff6e61SIan Romanick
194c0ff6e61SIan Romanick priv->bridge.pcmcia = info;
195c0ff6e61SIan Romanick break;
196c0ff6e61SIan Romanick }
197c0ff6e61SIan Romanick }
198c0ff6e61SIan Romanick
199c0ff6e61SIan Romanick return 0;
200c0ff6e61SIan Romanick }
201c0ff6e61SIan Romanick
202c0ff6e61SIan Romanick
20327f0ffcaSIan Romanick /**
20427f0ffcaSIan Romanick * Get the PCI bridge information for a device
20527f0ffcaSIan Romanick *
20627f0ffcaSIan Romanick * \returns
20727f0ffcaSIan Romanick * If \c dev is a PCI-to-PCI bridge, a pointer to a \c pci_bridge_info
20827f0ffcaSIan Romanick * structure. Otherwise, \c NULL is returned.
20927f0ffcaSIan Romanick */
210c0ff6e61SIan Romanick const struct pci_bridge_info *
pci_device_get_bridge_info(struct pci_device * dev)211c0ff6e61SIan Romanick pci_device_get_bridge_info( struct pci_device * dev )
212c0ff6e61SIan Romanick {
213c0ff6e61SIan Romanick struct pci_device_private * priv = (struct pci_device_private *) dev;
214c0ff6e61SIan Romanick
215c0ff6e61SIan Romanick if (priv->bridge.pci == NULL) {
216c0ff6e61SIan Romanick read_bridge_info(priv);
217c0ff6e61SIan Romanick }
218c0ff6e61SIan Romanick
219c0ff6e61SIan Romanick return (priv->header_type == 1) ? priv->bridge.pci : NULL;
220c0ff6e61SIan Romanick }
221c0ff6e61SIan Romanick
222c0ff6e61SIan Romanick
22327f0ffcaSIan Romanick /**
22427f0ffcaSIan Romanick * Get the PCMCIA bridge information for a device
22527f0ffcaSIan Romanick *
22627f0ffcaSIan Romanick * \returns
22727f0ffcaSIan Romanick * If \c dev is a PCI-to-PCMCIA bridge, a pointer to a
22827f0ffcaSIan Romanick * \c pci_pcmcia_bridge_info structure. Otherwise, \c NULL is returned.
22927f0ffcaSIan Romanick */
230c0ff6e61SIan Romanick const struct pci_pcmcia_bridge_info *
pci_device_get_pcmcia_bridge_info(struct pci_device * dev)231c0ff6e61SIan Romanick pci_device_get_pcmcia_bridge_info( struct pci_device * dev )
232c0ff6e61SIan Romanick {
233c0ff6e61SIan Romanick struct pci_device_private * priv = (struct pci_device_private *) dev;
234c0ff6e61SIan Romanick
235c0ff6e61SIan Romanick if (priv->bridge.pcmcia == NULL) {
236c0ff6e61SIan Romanick read_bridge_info(priv);
237c0ff6e61SIan Romanick }
238c0ff6e61SIan Romanick
239c0ff6e61SIan Romanick return (priv->header_type == 2) ? priv->bridge.pcmcia : NULL;
240c0ff6e61SIan Romanick }
241c0e31708SIan Romanick
242c0e31708SIan Romanick
24327f0ffcaSIan Romanick /**
24427f0ffcaSIan Romanick * Determine the primary, secondary, and subordinate buses for a bridge
24527f0ffcaSIan Romanick *
24627f0ffcaSIan Romanick * Determines the IDs of the primary, secondary, and subordinate buses for
24727f0ffcaSIan Romanick * a specified bridge. Not all bridges directly store this information
24827f0ffcaSIan Romanick * (e.g., PCI-to-ISA bridges). For those bridges, no error is returned, but
24927f0ffcaSIan Romanick * -1 is stored in the bus IDs that don't make sense.
25027f0ffcaSIan Romanick *
25127f0ffcaSIan Romanick * For example, for a PCI-to-ISA bridge, \c primary_bus will be set to the ID
25227f0ffcaSIan Romanick * of the bus containing the device and both \c secondary_bus and
25327f0ffcaSIan Romanick * \c subordinate_bus will be set to -1.
25427f0ffcaSIan Romanick *
25527f0ffcaSIan Romanick * \return
25627f0ffcaSIan Romanick * On success, zero is returned. If \c dev is not a bridge, \c ENODEV is
25727f0ffcaSIan Romanick * returned.
25827f0ffcaSIan Romanick *
25927f0ffcaSIan Romanick * \bug
26027f0ffcaSIan Romanick * Host bridges are handled the same way as PCI-to-ISA bridges. This is
26127f0ffcaSIan Romanick * almost certainly not correct.
26227f0ffcaSIan Romanick */
263c0e31708SIan Romanick int
pci_device_get_bridge_buses(struct pci_device * dev,int * primary_bus,int * secondary_bus,int * subordinate_bus)264c0e31708SIan Romanick pci_device_get_bridge_buses(struct pci_device * dev, int *primary_bus,
265c0e31708SIan Romanick int *secondary_bus, int *subordinate_bus)
266c0e31708SIan Romanick {
267c0e31708SIan Romanick struct pci_device_private * priv = (struct pci_device_private *) dev;
268c0e31708SIan Romanick
269c0e31708SIan Romanick /* If the device isn't a bridge, return an error.
270c0e31708SIan Romanick */
271c0e31708SIan Romanick
272c0e31708SIan Romanick if (((dev->device_class >> 16) & 0x0ff) != 0x06) {
273c0e31708SIan Romanick return ENODEV;
274c0e31708SIan Romanick }
275c0e31708SIan Romanick
276c0e31708SIan Romanick switch ((dev->device_class >> 8) & 0x0ff) {
277c0e31708SIan Romanick case 0x00:
278c0e31708SIan Romanick /* What to do for host bridges? I'm pretty sure this isn't right.
279c0e31708SIan Romanick */
280c0e31708SIan Romanick *primary_bus = dev->bus;
281c0e31708SIan Romanick *secondary_bus = -1;
282c0e31708SIan Romanick *subordinate_bus = -1;
283c0e31708SIan Romanick break;
284c0e31708SIan Romanick
285c0e31708SIan Romanick case 0x01:
286c0e31708SIan Romanick case 0x02:
287c0e31708SIan Romanick case 0x03:
288c0e31708SIan Romanick *primary_bus = dev->bus;
289c0e31708SIan Romanick *secondary_bus = -1;
290c0e31708SIan Romanick *subordinate_bus = -1;
291c0e31708SIan Romanick break;
292c0e31708SIan Romanick
293c0e31708SIan Romanick case 0x04:
2949ba94cafSDarren Smith if (priv->bridge.pci == NULL)
2959ba94cafSDarren Smith read_bridge_info(priv);
296066032e0SBryce Harrington if ((priv->header_type & 0x7f) == 0x01) {
297c0e31708SIan Romanick *primary_bus = priv->bridge.pci->primary_bus;
298c0e31708SIan Romanick *secondary_bus = priv->bridge.pci->secondary_bus;
299c0e31708SIan Romanick *subordinate_bus = priv->bridge.pci->subordinate_bus;
3009ba94cafSDarren Smith } else {
3019ba94cafSDarren Smith *primary_bus = dev->bus;
3029ba94cafSDarren Smith *secondary_bus = -1;
3039ba94cafSDarren Smith *subordinate_bus = -1;
3049ba94cafSDarren Smith }
305c0e31708SIan Romanick break;
306c0e31708SIan Romanick
307c0e31708SIan Romanick case 0x07:
3089ba94cafSDarren Smith if (priv->bridge.pcmcia == NULL)
3099ba94cafSDarren Smith read_bridge_info(priv);
310066032e0SBryce Harrington if ((priv->header_type & 0x7f) == 0x02) {
311c0e31708SIan Romanick *primary_bus = priv->bridge.pcmcia->primary_bus;
312c0e31708SIan Romanick *secondary_bus = priv->bridge.pcmcia->card_bus;
313c0e31708SIan Romanick *subordinate_bus = priv->bridge.pcmcia->subordinate_bus;
3149ba94cafSDarren Smith } else {
3159ba94cafSDarren Smith *primary_bus = dev->bus;
3169ba94cafSDarren Smith *secondary_bus = -1;
3179ba94cafSDarren Smith *subordinate_bus = -1;
3189ba94cafSDarren Smith }
319c0e31708SIan Romanick break;
320c0e31708SIan Romanick }
321c0e31708SIan Romanick
322c0e31708SIan Romanick return 0;
323c0e31708SIan Romanick }
324b2fbe63bSAdam Jackson
325b2fbe63bSAdam Jackson #define PCI_CLASS_BRIDGE 0x06
326b2fbe63bSAdam Jackson #define PCI_SUBCLASS_BRIDGE_PCI 0x04
327b2fbe63bSAdam Jackson
328b2fbe63bSAdam Jackson struct pci_device *
pci_device_get_parent_bridge(struct pci_device * dev)329b2fbe63bSAdam Jackson pci_device_get_parent_bridge(struct pci_device *dev)
330b2fbe63bSAdam Jackson {
331b2fbe63bSAdam Jackson struct pci_id_match bridge_match = {
332b2fbe63bSAdam Jackson PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY,
333b2fbe63bSAdam Jackson (PCI_CLASS_BRIDGE << 16) | (PCI_SUBCLASS_BRIDGE_PCI << 8),
334b2fbe63bSAdam Jackson 0
335b2fbe63bSAdam Jackson };
336b2fbe63bSAdam Jackson
337b2fbe63bSAdam Jackson struct pci_device *bridge;
338b2fbe63bSAdam Jackson struct pci_device_iterator *iter;
339b2fbe63bSAdam Jackson
340b2fbe63bSAdam Jackson if (dev == NULL)
341b2fbe63bSAdam Jackson return NULL;
342b2fbe63bSAdam Jackson
343b2fbe63bSAdam Jackson iter = pci_id_match_iterator_create(& bridge_match);
344b2fbe63bSAdam Jackson if (iter == NULL)
345b2fbe63bSAdam Jackson return NULL;
346b2fbe63bSAdam Jackson
347b2fbe63bSAdam Jackson while ((bridge = pci_device_next(iter)) != NULL) {
348b2fbe63bSAdam Jackson if (bridge->domain == dev->domain) {
349b2fbe63bSAdam Jackson const struct pci_bridge_info *info =
350b2fbe63bSAdam Jackson pci_device_get_bridge_info(bridge);
351b2fbe63bSAdam Jackson
352b2fbe63bSAdam Jackson if (info != NULL) {
353b2fbe63bSAdam Jackson if (info->secondary_bus == dev->bus) {
354b2fbe63bSAdam Jackson break;
355b2fbe63bSAdam Jackson }
356b2fbe63bSAdam Jackson }
357b2fbe63bSAdam Jackson }
358b2fbe63bSAdam Jackson }
359b2fbe63bSAdam Jackson
360b2fbe63bSAdam Jackson pci_iterator_destroy(iter);
361b2fbe63bSAdam Jackson
362b2fbe63bSAdam Jackson return bridge;
363b2fbe63bSAdam Jackson }
364