xref: /libpciaccess/src/common_bridge.c (revision 1a2ac5f1)
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