1 /* 2 * (C) Copyright IBM Corporation 2006 3 * All Rights Reserved. 4 * 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: 11 * 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 14 * Software. 15 * 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. 23 */ 24 25 /** 26 * \file common_bridge.c 27 * Support routines used to process PCI header information for bridges. 28 * 29 * \author Ian Romanick <[email protected]> 30 */ 31 32 #include "config.h" 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <ctype.h> 36 #include <errno.h> 37 38 #if defined(HAVE_STRING_H) 39 # include <string.h> 40 #elif defined(HAVE_STRINGS_H) 41 # include <strings.h> 42 #endif 43 44 #if defined(HAVE_INTTYPES_H) 45 # include <inttypes.h> 46 #elif defined(HAVE_STDINT_H) 47 # include <stdint.h> 48 #endif 49 50 #include "pciaccess.h" 51 #include "pciaccess_private.h" 52 53 static int 54 read_bridge_info( struct pci_device_private * priv ) 55 { 56 uint8_t buf[0x40]; 57 pciaddr_t bytes; 58 int err; 59 60 61 /* Make sure the device has been probed. If not, header_type won't be 62 * set and the rest of this function will fail. 63 */ 64 err = pci_device_probe(& priv->base); 65 if (err) { 66 return err; 67 } 68 69 switch ( priv->header_type & 0x7f ) { 70 case 0x00: 71 break; 72 73 case 0x01: { 74 struct pci_bridge_info *info; 75 76 info = malloc(sizeof(*info)); 77 if (info != NULL) { 78 pci_device_cfg_read( (struct pci_device *) priv, buf + 0x18, 0x18, 79 0x40 - 0x18, & bytes ); 80 81 info->primary_bus = buf[0x18]; 82 info->secondary_bus = buf[0x19]; 83 info->subordinate_bus = buf[0x1a]; 84 info->secondary_latency_timer = buf[0x1b]; 85 86 info->io_type = buf[0x1c] & 0x0f; 87 info->io_base = (((uint32_t) (buf[0x1c] & 0x0f0)) << 8) 88 + (((uint32_t) buf[0x30]) << 16) 89 + (((uint32_t) buf[0x31]) << 24); 90 91 info->io_limit = 0x00000fff 92 + (((uint32_t) (buf[0x1d] & 0x0f0)) << 8) 93 + (((uint32_t) buf[0x32]) << 16) 94 + (((uint32_t) buf[0x33]) << 24); 95 96 info->mem_type = buf[0x20] & 0x0f; 97 info->mem_base = (((uint32_t) (buf[0x20] & 0x0f0)) << 16) 98 + (((uint32_t) buf[0x21]) << 24); 99 100 info->mem_limit = 0x0000ffff 101 + (((uint32_t) (buf[0x22] & 0x0f0)) << 16) 102 + (((uint32_t) buf[0x23]) << 24); 103 104 info->prefetch_mem_type = buf[0x24] & 0x0f; 105 info->prefetch_mem_base = (((uint64_t) (buf[0x24] & 0x0f0)) << 16) 106 + (((uint64_t) buf[0x25]) << 24) 107 + (((uint64_t) buf[0x28]) << 32) 108 + (((uint64_t) buf[0x29]) << 40) 109 + (((uint64_t) buf[0x2a]) << 48) 110 + (((uint64_t) buf[0x2b]) << 56); 111 112 info->prefetch_mem_limit = 0x0000ffff 113 + (((uint64_t) (buf[0x26] & 0x0f0)) << 16) 114 + (((uint64_t) buf[0x27]) << 24) 115 + (((uint64_t) buf[0x2c]) << 32) 116 + (((uint64_t) buf[0x2d]) << 40) 117 + (((uint64_t) buf[0x2e]) << 48) 118 + (((uint64_t) buf[0x2f]) << 56); 119 120 info->bridge_control = ((uint16_t) buf[0x3e]) 121 + (((uint16_t) buf[0x3f]) << 8); 122 123 info->secondary_status = ((uint16_t) buf[0x1e]) 124 + (((uint16_t) buf[0x1f]) << 8); 125 } 126 127 priv->bridge.pci = info; 128 break; 129 } 130 131 case 0x02: { 132 struct pci_pcmcia_bridge_info *info; 133 134 info = malloc(sizeof(*info)); 135 if (info != NULL) { 136 pci_device_cfg_read( (struct pci_device *) priv, buf + 0x16, 0x16, 137 0x40 - 0x16, & bytes ); 138 139 info->primary_bus = buf[0x18]; 140 info->card_bus = buf[0x19]; 141 info->subordinate_bus = buf[0x1a]; 142 info->cardbus_latency_timer = buf[0x1b]; 143 144 info->mem[0].base = (((uint32_t) buf[0x1c])) 145 + (((uint32_t) buf[0x1d]) << 8) 146 + (((uint32_t) buf[0x1e]) << 16) 147 + (((uint32_t) buf[0x1f]) << 24); 148 149 info->mem[0].limit = (((uint32_t) buf[0x20])) 150 + (((uint32_t) buf[0x21]) << 8) 151 + (((uint32_t) buf[0x22]) << 16) 152 + (((uint32_t) buf[0x23]) << 24); 153 154 info->mem[1].base = (((uint32_t) buf[0x24])) 155 + (((uint32_t) buf[0x25]) << 8) 156 + (((uint32_t) buf[0x26]) << 16) 157 + (((uint32_t) buf[0x27]) << 24); 158 159 info->mem[1].limit = (((uint32_t) buf[0x28])) 160 + (((uint32_t) buf[0x29]) << 8) 161 + (((uint32_t) buf[0x2a]) << 16) 162 + (((uint32_t) buf[0x2b]) << 24); 163 164 info->io[0].base = (((uint32_t) buf[0x2c])) 165 + (((uint32_t) buf[0x2d]) << 8) 166 + (((uint32_t) buf[0x2e]) << 16) 167 + (((uint32_t) buf[0x2f]) << 24); 168 169 info->io[0].limit = (((uint32_t) buf[0x30])) 170 + (((uint32_t) buf[0x31]) << 8) 171 + (((uint32_t) buf[0x32]) << 16) 172 + (((uint32_t) buf[0x33]) << 24); 173 174 info->io[1].base = (((uint32_t) buf[0x34])) 175 + (((uint32_t) buf[0x35]) << 8) 176 + (((uint32_t) buf[0x36]) << 16) 177 + (((uint32_t) buf[0x37]) << 24); 178 179 info->io[1].limit = (((uint32_t) buf[0x38])) 180 + (((uint32_t) buf[0x39]) << 8) 181 + (((uint32_t) buf[0x3a]) << 16) 182 + (((uint32_t) buf[0x3b]) << 24); 183 184 info->secondary_status = ((uint16_t) buf[0x16]) 185 + (((uint16_t) buf[0x17]) << 8); 186 187 info->bridge_control = ((uint16_t) buf[0x3e]) 188 + (((uint16_t) buf[0x3f]) << 8); 189 } 190 191 priv->bridge.pcmcia = info; 192 break; 193 } 194 } 195 196 return 0; 197 } 198 199 200 /** 201 * Get the PCI bridge information for a device 202 * 203 * \returns 204 * If \c dev is a PCI-to-PCI bridge, a pointer to a \c pci_bridge_info 205 * structure. Otherwise, \c NULL is returned. 206 */ 207 const struct pci_bridge_info * 208 pci_device_get_bridge_info( struct pci_device * dev ) 209 { 210 struct pci_device_private * priv = (struct pci_device_private *) dev; 211 212 if (priv->bridge.pci == NULL) { 213 read_bridge_info(priv); 214 } 215 216 return (priv->header_type == 1) ? priv->bridge.pci : NULL; 217 } 218 219 220 /** 221 * Get the PCMCIA bridge information for a device 222 * 223 * \returns 224 * If \c dev is a PCI-to-PCMCIA bridge, a pointer to a 225 * \c pci_pcmcia_bridge_info structure. Otherwise, \c NULL is returned. 226 */ 227 const struct pci_pcmcia_bridge_info * 228 pci_device_get_pcmcia_bridge_info( struct pci_device * dev ) 229 { 230 struct pci_device_private * priv = (struct pci_device_private *) dev; 231 232 if (priv->bridge.pcmcia == NULL) { 233 read_bridge_info(priv); 234 } 235 236 return (priv->header_type == 2) ? priv->bridge.pcmcia : NULL; 237 } 238 239 240 /** 241 * Determine the primary, secondary, and subordinate buses for a bridge 242 * 243 * Determines the IDs of the primary, secondary, and subordinate buses for 244 * a specified bridge. Not all bridges directly store this information 245 * (e.g., PCI-to-ISA bridges). For those bridges, no error is returned, but 246 * -1 is stored in the bus IDs that don't make sense. 247 * 248 * For example, for a PCI-to-ISA bridge, \c primary_bus will be set to the ID 249 * of the bus containing the device and both \c secondary_bus and 250 * \c subordinate_bus will be set to -1. 251 * 252 * \return 253 * On success, zero is returned. If \c dev is not a bridge, \c ENODEV is 254 * returned. 255 * 256 * \bug 257 * Host bridges are handled the same way as PCI-to-ISA bridges. This is 258 * almost certainly not correct. 259 */ 260 int 261 pci_device_get_bridge_buses(struct pci_device * dev, int *primary_bus, 262 int *secondary_bus, int *subordinate_bus) 263 { 264 struct pci_device_private * priv = (struct pci_device_private *) dev; 265 266 /* If the device isn't a bridge, return an error. 267 */ 268 269 if (((dev->device_class >> 16) & 0x0ff) != 0x06) { 270 return ENODEV; 271 } 272 273 if (!priv->bridge.pci) { 274 return ENODEV; 275 } 276 277 switch ((dev->device_class >> 8) & 0x0ff) { 278 case 0x00: 279 /* What to do for host bridges? I'm pretty sure this isn't right. 280 */ 281 *primary_bus = dev->bus; 282 *secondary_bus = -1; 283 *subordinate_bus = -1; 284 break; 285 286 case 0x01: 287 case 0x02: 288 case 0x03: 289 *primary_bus = dev->bus; 290 *secondary_bus = -1; 291 *subordinate_bus = -1; 292 break; 293 294 case 0x04: 295 if (priv->bridge.pci == NULL) 296 read_bridge_info(priv); 297 if (priv->header_type == 0x01) { 298 *primary_bus = priv->bridge.pci->primary_bus; 299 *secondary_bus = priv->bridge.pci->secondary_bus; 300 *subordinate_bus = priv->bridge.pci->subordinate_bus; 301 } else { 302 *primary_bus = dev->bus; 303 *secondary_bus = -1; 304 *subordinate_bus = -1; 305 } 306 break; 307 308 case 0x07: 309 if (priv->bridge.pcmcia == NULL) 310 read_bridge_info(priv); 311 if (priv->header_type == 0x02) { 312 *primary_bus = priv->bridge.pcmcia->primary_bus; 313 *secondary_bus = priv->bridge.pcmcia->card_bus; 314 *subordinate_bus = priv->bridge.pcmcia->subordinate_bus; 315 } else { 316 *primary_bus = dev->bus; 317 *secondary_bus = -1; 318 *subordinate_bus = -1; 319 } 320 break; 321 } 322 323 return 0; 324 } 325 326 #define PCI_CLASS_BRIDGE 0x06 327 #define PCI_SUBCLASS_BRIDGE_PCI 0x04 328 329 struct pci_device * 330 pci_device_get_parent_bridge(struct pci_device *dev) 331 { 332 struct pci_id_match bridge_match = { 333 PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 334 (PCI_CLASS_BRIDGE << 16) | (PCI_SUBCLASS_BRIDGE_PCI << 8), 335 0 336 }; 337 338 struct pci_device *bridge; 339 struct pci_device_iterator *iter; 340 341 if (dev == NULL) 342 return NULL; 343 344 iter = pci_id_match_iterator_create(& bridge_match); 345 if (iter == NULL) 346 return NULL; 347 348 while ((bridge = pci_device_next(iter)) != NULL) { 349 if (bridge->domain == dev->domain) { 350 const struct pci_bridge_info *info = 351 pci_device_get_bridge_info(bridge); 352 353 if (info != NULL) { 354 if (info->secondary_bus == dev->bus) { 355 break; 356 } 357 } 358 } 359 } 360 361 pci_iterator_destroy(iter); 362 363 return bridge; 364 } 365