1 /* $NetBSD: pci.h,v 1.3 2014/04/03 19:18:29 riastradh Exp $ */ 2 3 /*- 4 * Copyright (c) 2013 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Taylor R. Campbell. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #ifndef _LINUX_PCI_H_ 33 #define _LINUX_PCI_H_ 34 35 #include <sys/types.h> 36 #include <sys/bus.h> 37 #include <sys/cdefs.h> 38 #include <sys/kmem.h> 39 #include <sys/systm.h> 40 41 #include <dev/pci/pcidevs.h> 42 #include <dev/pci/pcireg.h> 43 #include <dev/pci/pcivar.h> 44 45 #include <linux/ioport.h> 46 47 struct pci_bus; 48 49 struct pci_device_id { 50 uint32_t vendor; 51 uint32_t device; 52 uint32_t subvendor; 53 uint32_t subdevice; 54 uint32_t class; 55 uint32_t class_mask; 56 unsigned long driver_data; 57 }; 58 59 #define PCI_ANY_ID ((pcireg_t)-1) 60 61 #define PCI_BASE_CLASS_DISPLAY PCI_CLASS_DISPLAY 62 63 #define PCI_CLASS_BRIDGE_ISA \ 64 ((PCI_CLASS_BRIDGE << 8) | PCI_SUBCLASS_BRIDGE_ISA) 65 CTASSERT(PCI_CLASS_BRIDGE_ISA == 0x0601); 66 67 #define PCI_VENDOR_ID_INTEL PCI_VENDOR_INTEL 68 69 #define PCI_DEVFN(DEV, FN) \ 70 (__SHIFTIN((DEV), __BITS(3, 7)) | __SHIFTIN((FN), __BITS(0, 2))) 71 #define PCI_SLOT(DEVFN) __SHIFTOUT((DEVFN), __BITS(3, 7)) 72 #define PCI_FUNC(DEVFN) __SHIFTOUT((DEVFN), __BITS(0, 2)) 73 74 #define PCI_CAP_ID_AGP PCI_CAP_AGP 75 76 struct pci_dev { 77 struct pci_attach_args pd_pa; 78 int pd_kludges; /* Gotta lose 'em... */ 79 #define NBPCI_KLUDGE_GET_MUMBLE 0x01 80 #define NBPCI_KLUDGE_MAP_ROM 0x02 81 bus_space_tag_t pd_rom_bst; 82 bus_space_handle_t pd_rom_bsh; 83 bus_size_t pd_rom_size; 84 void *pd_rom_vaddr; 85 device_t pd_dev; 86 struct device dev; /* XXX Don't believe me! */ 87 struct pci_bus *bus; 88 uint32_t devfn; 89 uint16_t vendor; 90 uint16_t device; 91 uint16_t subsystem_vendor; 92 uint16_t subsystem_device; 93 uint8_t revision; 94 uint32_t class; 95 bool msi_enabled; 96 }; 97 98 static inline device_t 99 pci_dev_dev(struct pci_dev *pdev) 100 { 101 return pdev->pd_dev; 102 } 103 104 static inline void 105 linux_pci_dev_init(struct pci_dev *pdev, device_t dev, 106 const struct pci_attach_args *pa, int kludges) 107 { 108 const uint32_t subsystem_id = pci_conf_read(pa->pa_pc, pa->pa_tag, 109 PCI_SUBSYS_ID_REG); 110 111 pdev->pd_pa = *pa; 112 pdev->pd_kludges = kludges; 113 pdev->pd_rom_vaddr = NULL; 114 pdev->pd_dev = dev; 115 pdev->bus = NULL; /* XXX struct pci_dev::bus */ 116 pdev->devfn = PCI_DEVFN(pa->pa_device, pa->pa_function); 117 pdev->vendor = PCI_VENDOR(pa->pa_id); 118 pdev->device = PCI_PRODUCT(pa->pa_id); 119 pdev->subsystem_vendor = PCI_SUBSYS_VENDOR(subsystem_id); 120 pdev->subsystem_device = PCI_SUBSYS_ID(subsystem_id); 121 pdev->revision = PCI_REVISION(pa->pa_class); 122 pdev->class = __SHIFTOUT(pa->pa_class, 0xffffff00UL); /* ? */ 123 pdev->msi_enabled = false; 124 } 125 126 static inline int 127 pci_find_capability(struct pci_dev *pdev, int cap) 128 { 129 return pci_get_capability(pdev->pd_pa.pa_pc, pdev->pd_pa.pa_tag, cap, 130 NULL, NULL); 131 } 132 133 static inline void 134 pci_read_config_dword(struct pci_dev *pdev, int reg, uint32_t *valuep) 135 { 136 KASSERT(!ISSET(reg, 3)); 137 *valuep = pci_conf_read(pdev->pd_pa.pa_pc, pdev->pd_pa.pa_tag, reg); 138 } 139 140 static inline void 141 pci_read_config_word(struct pci_dev *pdev, int reg, uint16_t *valuep) 142 { 143 KASSERT(!ISSET(reg, 1)); 144 *valuep = pci_conf_read(pdev->pd_pa.pa_pc, pdev->pd_pa.pa_tag, 145 (reg &~ 3)) >> (8 * (reg & 3)); 146 } 147 148 static inline void 149 pci_read_config_byte(struct pci_dev *pdev, int reg, uint8_t *valuep) 150 { 151 *valuep = pci_conf_read(pdev->pd_pa.pa_pc, pdev->pd_pa.pa_tag, 152 (reg &~ 1)) >> (8 * (reg & 1)); 153 } 154 155 static inline void 156 pci_write_config_dword(struct pci_dev *pdev, int reg, uint32_t value) 157 { 158 KASSERT(!ISSET(reg, 3)); 159 pci_conf_write(pdev->pd_pa.pa_pc, pdev->pd_pa.pa_tag, reg, value); 160 } 161 162 static inline void 163 pci_rmw_config(struct pci_dev *pdev, int reg, unsigned int bytes, 164 uint32_t value) 165 { 166 const uint32_t mask = ~((~0UL) << (8 * bytes)); 167 const int reg32 = (reg &~ 3); 168 const unsigned int shift = (8 * (reg & 3)); 169 uint32_t value32; 170 171 KASSERT(bytes <= 4); 172 KASSERT(!ISSET(value, ~mask)); 173 pci_read_config_dword(pdev, reg32, &value32); 174 value32 &=~ (mask << shift); 175 value32 |= (value << shift); 176 pci_write_config_dword(pdev, reg32, value32); 177 } 178 179 static inline void 180 pci_write_config_word(struct pci_dev *pdev, int reg, uint16_t value) 181 { 182 KASSERT(!ISSET(reg, 1)); 183 pci_rmw_config(pdev, reg, 2, value); 184 } 185 186 static inline void 187 pci_write_config_byte(struct pci_dev *pdev, int reg, uint8_t value) 188 { 189 pci_rmw_config(pdev, reg, 1, value); 190 } 191 192 /* 193 * XXX pci msi 194 */ 195 static inline void 196 pci_enable_msi(struct pci_dev *pdev) 197 { 198 KASSERT(!pdev->msi_enabled); 199 pdev->msi_enabled = true; 200 } 201 202 static inline void 203 pci_disable_msi(struct pci_dev *pdev) 204 { 205 KASSERT(pdev->msi_enabled); 206 pdev->msi_enabled = false; 207 } 208 209 static inline void 210 pci_set_master(struct pci_dev *pdev) 211 { 212 pcireg_t csr; 213 214 csr = pci_conf_read(pdev->pd_pa.pa_pc, pdev->pd_pa.pa_tag, 215 PCI_COMMAND_STATUS_REG); 216 csr |= PCI_COMMAND_MASTER_ENABLE; 217 pci_conf_write(pdev->pd_pa.pa_pc, pdev->pd_pa.pa_tag, 218 PCI_COMMAND_STATUS_REG, csr); 219 } 220 221 #define PCIBIOS_MIN_MEM 0 /* XXX bogus x86 kludge bollocks */ 222 223 static inline bus_addr_t 224 pcibios_align_resource(void *p, const struct resource *resource, 225 bus_addr_t addr, bus_size_t size) 226 { 227 panic("pcibios_align_resource has accessed unaligned neurons!"); 228 } 229 230 static inline int 231 pci_bus_alloc_resource(struct pci_bus *bus, struct resource *resource, 232 bus_size_t size, bus_size_t align, bus_addr_t start, int type __unused, 233 bus_addr_t (*align_fn)(void *, const struct resource *, bus_addr_t, 234 bus_size_t) __unused, 235 struct pci_dev *pdev) 236 { 237 const struct pci_attach_args *const pa = &pdev->pd_pa; 238 bus_space_tag_t bst; 239 int error; 240 241 switch (resource->flags) { 242 case IORESOURCE_MEM: 243 bst = pa->pa_memt; 244 break; 245 246 case IORESOURCE_IO: 247 bst = pa->pa_iot; 248 break; 249 250 default: 251 panic("I don't know what kind of resource you want!"); 252 } 253 254 resource->r_bst = bst; 255 error = bus_space_alloc(bst, start, __type_max(bus_addr_t), 256 size, align, 0, 0, &resource->start, &resource->r_bsh); 257 if (error) 258 return error; 259 260 resource->size = size; 261 return 0; 262 } 263 264 /* 265 * XXX Mega-kludgerific! pci_get_bus_and_slot and pci_get_class are 266 * defined only for their single purposes in i915drm, in 267 * i915_get_bridge_dev and intel_detect_pch. We can't define them more 268 * generally without adapting pci_find_device (and pci_enumerate_bus 269 * internally) to pass a cookie through. 270 */ 271 272 static inline int /* XXX inline? */ 273 pci_kludgey_match_bus0_dev0_func0(const struct pci_attach_args *pa) 274 { 275 276 if (pa->pa_bus != 0) 277 return 0; 278 if (pa->pa_device != 0) 279 return 0; 280 if (pa->pa_function != 0) 281 return 0; 282 283 return 1; 284 } 285 286 static inline struct pci_dev * 287 pci_get_bus_and_slot(int bus, int slot) 288 { 289 struct pci_attach_args pa; 290 291 KASSERT(bus == 0); 292 KASSERT(slot == PCI_DEVFN(0, 0)); 293 294 if (!pci_find_device(&pa, &pci_kludgey_match_bus0_dev0_func0)) 295 return NULL; 296 297 struct pci_dev *const pdev = kmem_zalloc(sizeof(*pdev), KM_SLEEP); 298 linux_pci_dev_init(pdev, NULL, &pa, NBPCI_KLUDGE_GET_MUMBLE); 299 300 return pdev; 301 } 302 303 static inline int /* XXX inline? */ 304 pci_kludgey_match_isa_bridge(const struct pci_attach_args *pa) 305 { 306 307 if (PCI_CLASS(pa->pa_class) != PCI_CLASS_BRIDGE) 308 return 0; 309 if (PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_BRIDGE_ISA) 310 return 0; 311 312 return 1; 313 } 314 315 static inline struct pci_dev * 316 pci_get_class(uint32_t class_subclass_shifted __unused, 317 struct pci_dev *from __unused) 318 { 319 struct pci_attach_args pa; 320 321 KASSERT(class_subclass_shifted == (PCI_CLASS_BRIDGE_ISA << 8)); 322 KASSERT(from == NULL); 323 324 if (!pci_find_device(&pa, &pci_kludgey_match_isa_bridge)) 325 return NULL; 326 327 struct pci_dev *const pdev = kmem_zalloc(sizeof(*pdev), KM_SLEEP); 328 linux_pci_dev_init(pdev, NULL, &pa, NBPCI_KLUDGE_GET_MUMBLE); 329 330 return pdev; 331 } 332 333 static inline void 334 pci_dev_put(struct pci_dev *pdev) 335 { 336 337 KASSERT(ISSET(pdev->pd_kludges, NBPCI_KLUDGE_GET_MUMBLE)); 338 kmem_free(pdev, sizeof(*pdev)); 339 } 340 341 #define __pci_rom_iomem 342 343 static inline void 344 pci_unmap_rom(struct pci_dev *pdev, void __pci_rom_iomem *vaddr __unused) 345 { 346 347 KASSERT(ISSET(pdev->pd_kludges, NBPCI_KLUDGE_MAP_ROM)); 348 KASSERT(vaddr == pdev->pd_rom_vaddr); 349 bus_space_unmap(pdev->pd_rom_bst, pdev->pd_rom_bsh, pdev->pd_rom_size); 350 pdev->pd_kludges &= ~NBPCI_KLUDGE_MAP_ROM; 351 pdev->pd_rom_vaddr = NULL; 352 } 353 354 static inline void __pci_rom_iomem * 355 pci_map_rom(struct pci_dev *pdev, size_t *sizep) 356 { 357 bus_space_handle_t bsh; 358 bus_size_t size; 359 360 KASSERT(!ISSET(pdev->pd_kludges, NBPCI_KLUDGE_MAP_ROM)); 361 362 if (pci_mapreg_map(&pdev->pd_pa, PCI_MAPREG_ROM, PCI_MAPREG_TYPE_ROM, 363 (BUS_SPACE_MAP_PREFETCHABLE | BUS_SPACE_MAP_LINEAR), 364 &pdev->pd_rom_bst, &pdev->pd_rom_bsh, NULL, &pdev->pd_rom_size) 365 != 0) { 366 aprint_error_dev(pdev->pd_dev, "unable to map ROM\n"); 367 return NULL; 368 } 369 pdev->pd_kludges |= NBPCI_KLUDGE_MAP_ROM; 370 371 /* XXX This type is obviously wrong in general... */ 372 if (pci_find_rom(&pdev->pd_pa, pdev->pd_rom_bst, pdev->pd_rom_bsh, 373 PCI_ROM_CODE_TYPE_X86, &bsh, &size)) { 374 aprint_error_dev(pdev->pd_dev, "unable to find ROM\n"); 375 pci_unmap_rom(pdev, NULL); 376 return NULL; 377 } 378 379 KASSERT(size <= SIZE_T_MAX); 380 *sizep = size; 381 pdev->pd_rom_vaddr = bus_space_vaddr(pdev->pd_rom_bst, bsh); 382 return pdev->pd_rom_vaddr; 383 } 384 385 #endif /* _LINUX_PCI_H_ */ 386