2 * (C) Copyright IBM Corporation 2006
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
26 * \file common_bridge.c
27 * Support routines used to process PCI header information for bridges.
29 * \author Ian Romanick <idr@us.ibm.com>
38 #if defined(HAVE_STRING_H)
40 #elif defined(HAVE_STRINGS_H)
44 #if defined(HAVE_INTTYPES_H)
45 # include <inttypes.h>
46 #elif defined(HAVE_STDINT_H)
50 #include "pciaccess.h"
51 #include "pciaccess_private.h"
54 read_bridge_info( struct pci_device_private * priv )
60 switch ( priv->header_type & 0x7f ) {
65 struct pci_bridge_info *info;
67 info = malloc(sizeof(*info));
69 pci_device_cfg_read( (struct pci_device *) priv, buf + 0x18, 0x18,
70 0x40 - 0x18, & bytes );
72 info->primary_bus = buf[0x18];
73 info->secondary_bus = buf[0x19];
74 info->subordinate_bus = buf[0x1a];
75 info->secondary_latency_timer = buf[0x1b];
77 info->io_type = buf[0x1c] & 0x0f;
78 info->io_base = (((uint32_t) (buf[0x1c] & 0x0f0)) << 8)
79 + (((uint32_t) buf[0x30]) << 16)
80 + (((uint32_t) buf[0x31]) << 24);
82 info->io_limit = 0x00000fff
83 + (((uint32_t) (buf[0x1d] & 0x0f0)) << 8)
84 + (((uint32_t) buf[0x32]) << 16)
85 + (((uint32_t) buf[0x33]) << 24);
87 info->mem_type = buf[0x20] & 0x0f;
88 info->mem_base = (((uint32_t) (buf[0x20] & 0x0f0)) << 16)
89 + (((uint32_t) buf[0x21]) << 24);
91 info->mem_limit = 0x0000ffff
92 + (((uint32_t) (buf[0x22] & 0x0f0)) << 16)
93 + (((uint32_t) buf[0x23]) << 24);
95 info->prefetch_mem_type = buf[0x24] & 0x0f;
96 info->prefetch_mem_base = (((uint64_t) (buf[0x24] & 0x0f0)) << 16)
97 + (((uint64_t) buf[0x25]) << 24)
98 + (((uint64_t) buf[0x28]) << 32)
99 + (((uint64_t) buf[0x29]) << 40)
100 + (((uint64_t) buf[0x2a]) << 48)
101 + (((uint64_t) buf[0x2b]) << 56);
103 info->prefetch_mem_limit = 0x0000ffff
104 + (((uint64_t) (buf[0x26] & 0x0f0)) << 16)
105 + (((uint64_t) buf[0x27]) << 24)
106 + (((uint64_t) buf[0x2c]) << 32)
107 + (((uint64_t) buf[0x2d]) << 40)
108 + (((uint64_t) buf[0x2e]) << 48)
109 + (((uint64_t) buf[0x2f]) << 56);
111 info->bridge_control = ((uint16_t) buf[0x3e])
112 + (((uint16_t) buf[0x3f]) << 8);
114 info->secondary_status = ((uint16_t) buf[0x1e])
115 + (((uint16_t) buf[0x1f]) << 8);
118 priv->bridge.pci = info;
123 struct pci_pcmcia_bridge_info *info;
125 info = malloc(sizeof(*info));
127 pci_device_cfg_read( (struct pci_device *) priv, buf + 0x16, 0x16,
128 0x40 - 0x16, & bytes );
130 info->primary_bus = buf[0x18];
131 info->card_bus = buf[0x19];
132 info->subordinate_bus = buf[0x1a];
133 info->cardbus_latency_timer = buf[0x1b];
135 info->mem[0].base = (((uint32_t) buf[0x1c]))
136 + (((uint32_t) buf[0x1d]) << 8)
137 + (((uint32_t) buf[0x1e]) << 16)
138 + (((uint32_t) buf[0x1f]) << 24);
140 info->mem[0].limit = (((uint32_t) buf[0x20]))
141 + (((uint32_t) buf[0x21]) << 8)
142 + (((uint32_t) buf[0x22]) << 16)
143 + (((uint32_t) buf[0x23]) << 24);
145 info->mem[1].base = (((uint32_t) buf[0x24]))
146 + (((uint32_t) buf[0x25]) << 8)
147 + (((uint32_t) buf[0x26]) << 16)
148 + (((uint32_t) buf[0x27]) << 24);
150 info->mem[1].limit = (((uint32_t) buf[0x28]))
151 + (((uint32_t) buf[0x29]) << 8)
152 + (((uint32_t) buf[0x2a]) << 16)
153 + (((uint32_t) buf[0x2b]) << 24);
155 info->io[0].base = (((uint32_t) buf[0x2c]))
156 + (((uint32_t) buf[0x2d]) << 8)
157 + (((uint32_t) buf[0x2e]) << 16)
158 + (((uint32_t) buf[0x2f]) << 24);
160 info->io[0].limit = (((uint32_t) buf[0x30]))
161 + (((uint32_t) buf[0x31]) << 8)
162 + (((uint32_t) buf[0x32]) << 16)
163 + (((uint32_t) buf[0x33]) << 24);
165 info->io[1].base = (((uint32_t) buf[0x34]))
166 + (((uint32_t) buf[0x35]) << 8)
167 + (((uint32_t) buf[0x36]) << 16)
168 + (((uint32_t) buf[0x37]) << 24);
170 info->io[1].limit = (((uint32_t) buf[0x38]))
171 + (((uint32_t) buf[0x39]) << 8)
172 + (((uint32_t) buf[0x3a]) << 16)
173 + (((uint32_t) buf[0x3b]) << 24);
175 info->secondary_status = ((uint16_t) buf[0x16])
176 + (((uint16_t) buf[0x17]) << 8);
178 info->bridge_control = ((uint16_t) buf[0x3e])
179 + (((uint16_t) buf[0x3f]) << 8);
182 priv->bridge.pcmcia = info;
191 const struct pci_bridge_info *
192 pci_device_get_bridge_info( struct pci_device * dev )
194 struct pci_device_private * priv = (struct pci_device_private *) dev;
196 if (priv->bridge.pci == NULL) {
197 read_bridge_info(priv);
200 return (priv->header_type == 1) ? priv->bridge.pci : NULL;
204 const struct pci_pcmcia_bridge_info *
205 pci_device_get_pcmcia_bridge_info( struct pci_device * dev )
207 struct pci_device_private * priv = (struct pci_device_private *) dev;
209 if (priv->bridge.pcmcia == NULL) {
210 read_bridge_info(priv);
213 return (priv->header_type == 2) ? priv->bridge.pcmcia : NULL;
218 pci_device_get_bridge_buses(struct pci_device * dev, int *primary_bus,
219 int *secondary_bus, int *subordinate_bus)
221 struct pci_device_private * priv = (struct pci_device_private *) dev;
223 /* If the device isn't a bridge, return an error.
226 if (((dev->device_class >> 16) & 0x0ff) != 0x06) {
230 if (priv->bridge.pci == NULL) {
231 read_bridge_info(priv);
234 switch ((dev->device_class >> 8) & 0x0ff) {
236 /* What to do for host bridges? I'm pretty sure this isn't right.
238 *primary_bus = dev->bus;
240 *subordinate_bus = -1;
246 *primary_bus = dev->bus;
248 *subordinate_bus = -1;
252 *primary_bus = priv->bridge.pci->primary_bus;
253 *secondary_bus = priv->bridge.pci->secondary_bus;
254 *subordinate_bus = priv->bridge.pci->subordinate_bus;
258 *primary_bus = priv->bridge.pcmcia->primary_bus;
259 *secondary_bus = priv->bridge.pcmcia->card_bus;
260 *subordinate_bus = priv->bridge.pcmcia->subordinate_bus;