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 59 60 switch ( priv->header_type & 0x7f ) { 61 case 0x00: 62 break; 63 64 case 0x01: { 65 struct pci_bridge_info *info; 66 67 info = malloc(sizeof(*info)); 68 if (info != NULL) { 69 pci_device_cfg_read( (struct pci_device *) priv, buf + 0x18, 0x18, 70 0x40 - 0x18, & bytes ); 71 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]; 76 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); 81 82 info->io_limit = 0x00000fff 83 + (((uint32_t) (buf[0x1d] & 0x0f0)) << 8) 84 + (((uint32_t) buf[0x32]) << 16) 85 + (((uint32_t) buf[0x33]) << 24); 86 87 info->mem_type = buf[0x20] & 0x0f; 88 info->mem_base = (((uint32_t) (buf[0x20] & 0x0f0)) << 16) 89 + (((uint32_t) buf[0x21]) << 24); 90 91 info->mem_limit = 0x0000ffff 92 + (((uint32_t) (buf[0x22] & 0x0f0)) << 16) 93 + (((uint32_t) buf[0x23]) << 24); 94 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); 102 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); 110 111 info->bridge_control = ((uint16_t) buf[0x3e]) 112 + (((uint16_t) buf[0x3f]) << 8); 113 114 info->secondary_status = ((uint16_t) buf[0x1e]) 115 + (((uint16_t) buf[0x1f]) << 8); 116 } 117 118 priv->bridge.pci = info; 119 break; 120 } 121 122 case 0x02: { 123 struct pci_pcmcia_bridge_info *info; 124 125 info = malloc(sizeof(*info)); 126 if (info != NULL) { 127 pci_device_cfg_read( (struct pci_device *) priv, buf + 0x16, 0x16, 128 0x40 - 0x16, & bytes ); 129 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]; 134 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); 139 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); 144 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); 149 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); 154 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); 159 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); 164 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); 169 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); 174 175 info->secondary_status = ((uint16_t) buf[0x16]) 176 + (((uint16_t) buf[0x17]) << 8); 177 178 info->bridge_control = ((uint16_t) buf[0x3e]) 179 + (((uint16_t) buf[0x3f]) << 8); 180 } 181 182 priv->bridge.pcmcia = info; 183 break; 184 } 185 } 186 187 return 0; 188 } 189 190 191 /** 192 * Get the PCI bridge information for a device 193 * 194 * \returns 195 * If \c dev is a PCI-to-PCI bridge, a pointer to a \c pci_bridge_info 196 * structure. Otherwise, \c NULL is returned. 197 */ 198 const struct pci_bridge_info * 199 pci_device_get_bridge_info( struct pci_device * dev ) 200 { 201 struct pci_device_private * priv = (struct pci_device_private *) dev; 202 203 if (priv->bridge.pci == NULL) { 204 read_bridge_info(priv); 205 } 206 207 return (priv->header_type == 1) ? priv->bridge.pci : NULL; 208 } 209 210 211 /** 212 * Get the PCMCIA bridge information for a device 213 * 214 * \returns 215 * If \c dev is a PCI-to-PCMCIA bridge, a pointer to a 216 * \c pci_pcmcia_bridge_info structure. Otherwise, \c NULL is returned. 217 */ 218 const struct pci_pcmcia_bridge_info * 219 pci_device_get_pcmcia_bridge_info( struct pci_device * dev ) 220 { 221 struct pci_device_private * priv = (struct pci_device_private *) dev; 222 223 if (priv->bridge.pcmcia == NULL) { 224 read_bridge_info(priv); 225 } 226 227 return (priv->header_type == 2) ? priv->bridge.pcmcia : NULL; 228 } 229 230 231 /** 232 * Determine the primary, secondary, and subordinate buses for a bridge 233 * 234 * Determines the IDs of the primary, secondary, and subordinate buses for 235 * a specified bridge. Not all bridges directly store this information 236 * (e.g., PCI-to-ISA bridges). For those bridges, no error is returned, but 237 * -1 is stored in the bus IDs that don't make sense. 238 * 239 * For example, for a PCI-to-ISA bridge, \c primary_bus will be set to the ID 240 * of the bus containing the device and both \c secondary_bus and 241 * \c subordinate_bus will be set to -1. 242 * 243 * \return 244 * On success, zero is returned. If \c dev is not a bridge, \c ENODEV is 245 * returned. 246 * 247 * \bug 248 * Host bridges are handled the same way as PCI-to-ISA bridges. This is 249 * almost certainly not correct. 250 */ 251 int 252 pci_device_get_bridge_buses(struct pci_device * dev, int *primary_bus, 253 int *secondary_bus, int *subordinate_bus) 254 { 255 struct pci_device_private * priv = (struct pci_device_private *) dev; 256 257 /* If the device isn't a bridge, return an error. 258 */ 259 260 if (((dev->device_class >> 16) & 0x0ff) != 0x06) { 261 return ENODEV; 262 } 263 264 if (priv->bridge.pci == NULL) { 265 read_bridge_info(priv); 266 } 267 268 switch ((dev->device_class >> 8) & 0x0ff) { 269 case 0x00: 270 /* What to do for host bridges? I'm pretty sure this isn't right. 271 */ 272 *primary_bus = dev->bus; 273 *secondary_bus = -1; 274 *subordinate_bus = -1; 275 break; 276 277 case 0x01: 278 case 0x02: 279 case 0x03: 280 *primary_bus = dev->bus; 281 *secondary_bus = -1; 282 *subordinate_bus = -1; 283 break; 284 285 case 0x04: 286 *primary_bus = priv->bridge.pci->primary_bus; 287 *secondary_bus = priv->bridge.pci->secondary_bus; 288 *subordinate_bus = priv->bridge.pci->subordinate_bus; 289 break; 290 291 case 0x07: 292 *primary_bus = priv->bridge.pcmcia->primary_bus; 293 *secondary_bus = priv->bridge.pcmcia->card_bus; 294 *subordinate_bus = priv->bridge.pcmcia->subordinate_bus; 295 break; 296 } 297 298 return 0; 299 } 300