| 1 | /* $NetBSD: pcivar.h,v 1.108 2016/07/11 06:14:51 knakahara Exp $ */ |
| 2 | |
| 3 | /* |
| 4 | * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. |
| 5 | * Copyright (c) 1994 Charles M. Hannum. All rights reserved. |
| 6 | * |
| 7 | * Redistribution and use in source and binary forms, with or without |
| 8 | * modification, are permitted provided that the following conditions |
| 9 | * are met: |
| 10 | * 1. Redistributions of source code must retain the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer. |
| 12 | * 2. Redistributions in binary form must reproduce the above copyright |
| 13 | * notice, this list of conditions and the following disclaimer in the |
| 14 | * documentation and/or other materials provided with the distribution. |
| 15 | * 3. All advertising materials mentioning features or use of this software |
| 16 | * must display the following acknowledgement: |
| 17 | * This product includes software developed by Charles M. Hannum. |
| 18 | * 4. The name of the author may not be used to endorse or promote products |
| 19 | * derived from this software without specific prior written permission. |
| 20 | * |
| 21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| 22 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| 23 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| 24 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| 26 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 30 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 | */ |
| 32 | |
| 33 | #ifndef _DEV_PCI_PCIVAR_H_ |
| 34 | #define _DEV_PCI_PCIVAR_H_ |
| 35 | |
| 36 | /* |
| 37 | * Definitions for PCI autoconfiguration. |
| 38 | * |
| 39 | * This file describes types and functions which are used for PCI |
| 40 | * configuration. Some of this information is machine-specific, and is |
| 41 | * provided by pci_machdep.h. |
| 42 | */ |
| 43 | |
| 44 | #include <sys/device.h> |
| 45 | #include <sys/pmf.h> |
| 46 | #include <sys/bus.h> |
| 47 | #include <dev/pci/pcireg.h> |
| 48 | #include <dev/pci/pci_verbose.h> |
| 49 | |
| 50 | /* |
| 51 | * Structures and definitions needed by the machine-dependent header. |
| 52 | */ |
| 53 | struct pcibus_attach_args; |
| 54 | struct pci_attach_args; |
| 55 | struct pci_softc; |
| 56 | |
| 57 | #ifdef _KERNEL |
| 58 | /* |
| 59 | * Machine-dependent definitions. |
| 60 | */ |
| 61 | #include <machine/pci_machdep.h> |
| 62 | |
| 63 | enum pci_override_idx { |
| 64 | PCI_OVERRIDE_CONF_READ = __BIT(0) |
| 65 | , PCI_OVERRIDE_CONF_WRITE = __BIT(1) |
| 66 | , PCI_OVERRIDE_INTR_MAP = __BIT(2) |
| 67 | , PCI_OVERRIDE_INTR_STRING = __BIT(3) |
| 68 | , PCI_OVERRIDE_INTR_EVCNT = __BIT(4) |
| 69 | , PCI_OVERRIDE_INTR_ESTABLISH = __BIT(5) |
| 70 | , PCI_OVERRIDE_INTR_DISESTABLISH = __BIT(6) |
| 71 | , PCI_OVERRIDE_MAKE_TAG = __BIT(7) |
| 72 | , PCI_OVERRIDE_DECOMPOSE_TAG = __BIT(8) |
| 73 | }; |
| 74 | |
| 75 | /* Only add new fields to the end of this structure! */ |
| 76 | struct pci_overrides { |
| 77 | pcireg_t (*ov_conf_read)(void *, pci_chipset_tag_t, pcitag_t, int); |
| 78 | void (*ov_conf_write)(void *, pci_chipset_tag_t, pcitag_t, int, |
| 79 | pcireg_t); |
| 80 | int (*ov_intr_map)(void *, const struct pci_attach_args *, |
| 81 | pci_intr_handle_t *); |
| 82 | const char *(*ov_intr_string)(void *, pci_chipset_tag_t, |
| 83 | pci_intr_handle_t, char *, size_t); |
| 84 | const struct evcnt *(*ov_intr_evcnt)(void *, pci_chipset_tag_t, |
| 85 | pci_intr_handle_t); |
| 86 | void *(*ov_intr_establish)(void *, pci_chipset_tag_t, pci_intr_handle_t, |
| 87 | int, int (*)(void *), void *); |
| 88 | void (*ov_intr_disestablish)(void *, pci_chipset_tag_t, void *); |
| 89 | pcitag_t (*ov_make_tag)(void *, pci_chipset_tag_t, int, int, int); |
| 90 | void (*ov_decompose_tag)(void *, pci_chipset_tag_t, pcitag_t, |
| 91 | int *, int *, int *); |
| 92 | }; |
| 93 | |
| 94 | /* |
| 95 | * PCI bus attach arguments. |
| 96 | */ |
| 97 | struct pcibus_attach_args { |
| 98 | char *_pba_busname; /* XXX placeholder */ |
| 99 | bus_space_tag_t pba_iot; /* pci i/o space tag */ |
| 100 | bus_space_tag_t pba_memt; /* pci mem space tag */ |
| 101 | bus_dma_tag_t pba_dmat; /* DMA tag */ |
| 102 | bus_dma_tag_t pba_dmat64; /* DMA tag */ |
| 103 | pci_chipset_tag_t pba_pc; |
| 104 | int pba_flags; /* flags; see below */ |
| 105 | |
| 106 | int pba_bus; /* PCI bus number */ |
| 107 | int pba_sub; /* pba_bus >= pba_sub: no |
| 108 | * buses are subordinate to |
| 109 | * pba_bus. |
| 110 | * |
| 111 | * pba_bus < pba_sub: buses |
| 112 | * [pba_bus + 1, pba_sub] are |
| 113 | * subordinate to pba_bus. |
| 114 | */ |
| 115 | |
| 116 | /* |
| 117 | * Pointer to the pcitag of our parent bridge. If there is no |
| 118 | * parent bridge, then we assume we are a root bus. |
| 119 | */ |
| 120 | pcitag_t *pba_bridgetag; |
| 121 | |
| 122 | /* |
| 123 | * Interrupt swizzling information. These fields |
| 124 | * are only used by secondary busses. |
| 125 | */ |
| 126 | u_int pba_intrswiz; /* how to swizzle pins */ |
| 127 | pcitag_t pba_intrtag; /* intr. appears to come from here */ |
| 128 | }; |
| 129 | |
| 130 | /* |
| 131 | * This is used by <machine/pci_machdep.h> to access the pba_pc member. It |
| 132 | * can't use it directly since pcibus_attach_args has yet to be defined. |
| 133 | */ |
| 134 | static inline pci_chipset_tag_t |
| 135 | pcibus_attach_args_pc(struct pcibus_attach_args *pba) |
| 136 | { |
| 137 | return pba->pba_pc; |
| 138 | } |
| 139 | |
| 140 | /* |
| 141 | * PCI device attach arguments. |
| 142 | */ |
| 143 | struct pci_attach_args { |
| 144 | bus_space_tag_t pa_iot; /* pci i/o space tag */ |
| 145 | bus_space_tag_t pa_memt; /* pci mem space tag */ |
| 146 | bus_dma_tag_t pa_dmat; /* DMA tag */ |
| 147 | bus_dma_tag_t pa_dmat64; /* DMA tag */ |
| 148 | pci_chipset_tag_t pa_pc; |
| 149 | int pa_flags; /* flags; see below */ |
| 150 | |
| 151 | u_int pa_bus; |
| 152 | u_int pa_device; |
| 153 | u_int pa_function; |
| 154 | pcitag_t pa_tag; |
| 155 | pcireg_t pa_id, pa_class; |
| 156 | |
| 157 | /* |
| 158 | * Interrupt information. |
| 159 | * |
| 160 | * "Intrline" is used on systems whose firmware puts |
| 161 | * the right routing data into the line register in |
| 162 | * configuration space. The rest are used on systems |
| 163 | * that do not. |
| 164 | */ |
| 165 | u_int pa_intrswiz; /* how to swizzle pins if ppb */ |
| 166 | pcitag_t pa_intrtag; /* intr. appears to come from here */ |
| 167 | pci_intr_pin_t pa_intrpin; /* intr. appears on this pin */ |
| 168 | pci_intr_line_t pa_intrline; /* intr. routing information */ |
| 169 | pci_intr_pin_t pa_rawintrpin; /* unswizzled pin */ |
| 170 | }; |
| 171 | |
| 172 | /* |
| 173 | * This is used by <machine/pci_machdep.h> to access the pa_pc member. It |
| 174 | * can't use it directly since pci_attach_args has yet to be defined. |
| 175 | */ |
| 176 | static inline pci_chipset_tag_t |
| 177 | pci_attach_args_pc(const struct pci_attach_args *pa) |
| 178 | { |
| 179 | return pa->pa_pc; |
| 180 | } |
| 181 | |
| 182 | /* |
| 183 | * Flags given in the bus and device attachment args. |
| 184 | */ |
| 185 | #define PCI_FLAGS_IO_OKAY 0x01 /* I/O space is okay */ |
| 186 | #define PCI_FLAGS_MEM_OKAY 0x02 /* memory space is okay */ |
| 187 | #define PCI_FLAGS_MRL_OKAY 0x04 /* Memory Read Line okay */ |
| 188 | #define PCI_FLAGS_MRM_OKAY 0x08 /* Memory Read Multiple okay */ |
| 189 | #define PCI_FLAGS_MWI_OKAY 0x10 /* Memory Write and Invalidate |
| 190 | okay */ |
| 191 | #define PCI_FLAGS_MSI_OKAY 0x20 /* Message Signaled Interrupts |
| 192 | okay */ |
| 193 | #define PCI_FLAGS_MSIX_OKAY 0x40 /* Message Signaled Interrupts |
| 194 | (Extended) okay */ |
| 195 | |
| 196 | /* |
| 197 | * PCI device 'quirks'. |
| 198 | * |
| 199 | * In general strange behaviour which can be handled by a driver (e.g. |
| 200 | * a bridge's inability to pass a type of access correctly) should be. |
| 201 | * The quirks table should only contain information which impacts |
| 202 | * the operation of the MI PCI code and which can't be pushed lower |
| 203 | * (e.g. because it's unacceptable to require a driver to be present |
| 204 | * for the information to be known). |
| 205 | */ |
| 206 | struct pci_quirkdata { |
| 207 | pci_vendor_id_t vendor; /* Vendor ID */ |
| 208 | pci_product_id_t product; /* Product ID */ |
| 209 | int quirks; /* quirks; see below */ |
| 210 | }; |
| 211 | #define PCI_QUIRK_MULTIFUNCTION 1 |
| 212 | #define PCI_QUIRK_MONOFUNCTION 2 |
| 213 | #define PCI_QUIRK_SKIP_FUNC(n) (4 << n) |
| 214 | #define PCI_QUIRK_SKIP_FUNC0 PCI_QUIRK_SKIP_FUNC(0) |
| 215 | #define PCI_QUIRK_SKIP_FUNC1 PCI_QUIRK_SKIP_FUNC(1) |
| 216 | #define PCI_QUIRK_SKIP_FUNC2 PCI_QUIRK_SKIP_FUNC(2) |
| 217 | #define PCI_QUIRK_SKIP_FUNC3 PCI_QUIRK_SKIP_FUNC(3) |
| 218 | #define PCI_QUIRK_SKIP_FUNC4 PCI_QUIRK_SKIP_FUNC(4) |
| 219 | #define PCI_QUIRK_SKIP_FUNC5 PCI_QUIRK_SKIP_FUNC(5) |
| 220 | #define PCI_QUIRK_SKIP_FUNC6 PCI_QUIRK_SKIP_FUNC(6) |
| 221 | #define PCI_QUIRK_SKIP_FUNC7 PCI_QUIRK_SKIP_FUNC(7) |
| 222 | |
| 223 | struct pci_conf_state { |
| 224 | pcireg_t reg[16]; |
| 225 | }; |
| 226 | |
| 227 | struct pci_range { |
| 228 | bus_addr_t r_offset; |
| 229 | bus_size_t r_size; |
| 230 | int r_flags; |
| 231 | }; |
| 232 | |
| 233 | struct pci_child { |
| 234 | device_t c_dev; |
| 235 | bool c_psok; |
| 236 | pcireg_t c_powerstate; |
| 237 | struct pci_conf_state c_conf; |
| 238 | struct pci_range c_range[8]; |
| 239 | }; |
| 240 | |
| 241 | struct pci_softc { |
| 242 | device_t sc_dev; |
| 243 | bus_space_tag_t sc_iot, sc_memt; |
| 244 | bus_dma_tag_t sc_dmat; |
| 245 | bus_dma_tag_t sc_dmat64; |
| 246 | pci_chipset_tag_t sc_pc; |
| 247 | int sc_bus, sc_maxndevs; |
| 248 | pcitag_t *sc_bridgetag; |
| 249 | u_int sc_intrswiz; |
| 250 | pcitag_t sc_intrtag; |
| 251 | int sc_flags; |
| 252 | /* accounting of child devices */ |
| 253 | struct pci_child sc_devices[32*8]; |
| 254 | #define PCI_SC_DEVICESC(d, f) sc_devices[(d) * 8 + (f)] |
| 255 | }; |
| 256 | |
| 257 | extern struct cfdriver pci_cd; |
| 258 | |
| 259 | int pcibusprint(void *, const char *); |
| 260 | |
| 261 | /* |
| 262 | * Configuration space access and utility functions. (Note that most, |
| 263 | * e.g. make_tag, conf_read, conf_write are declared by pci_machdep.h.) |
| 264 | */ |
| 265 | int pci_mapreg_probe(pci_chipset_tag_t, pcitag_t, int, pcireg_t *); |
| 266 | pcireg_t pci_mapreg_type(pci_chipset_tag_t, pcitag_t, int); |
| 267 | int pci_mapreg_info(pci_chipset_tag_t, pcitag_t, int, pcireg_t, |
| 268 | bus_addr_t *, bus_size_t *, int *); |
| 269 | int pci_mapreg_map(const struct pci_attach_args *, int, pcireg_t, int, |
| 270 | bus_space_tag_t *, bus_space_handle_t *, bus_addr_t *, |
| 271 | bus_size_t *); |
| 272 | int pci_mapreg_submap(const struct pci_attach_args *, int, pcireg_t, int, |
| 273 | bus_size_t, bus_size_t, bus_space_tag_t *, bus_space_handle_t *, |
| 274 | bus_addr_t *, bus_size_t *); |
| 275 | |
| 276 | |
| 277 | int pci_find_rom(const struct pci_attach_args *, bus_space_tag_t, |
| 278 | bus_space_handle_t, bus_size_t, |
| 279 | int, bus_space_handle_t *, bus_size_t *); |
| 280 | |
| 281 | int pci_get_capability(pci_chipset_tag_t, pcitag_t, int, int *, pcireg_t *); |
| 282 | int pci_get_ht_capability(pci_chipset_tag_t, pcitag_t, int, int *, |
| 283 | pcireg_t *); |
| 284 | int pci_get_ext_capability(pci_chipset_tag_t, pcitag_t, int, int *, |
| 285 | pcireg_t *); |
| 286 | |
| 287 | int pci_msi_count(pci_chipset_tag_t, pcitag_t); |
| 288 | int pci_msix_count(pci_chipset_tag_t, pcitag_t); |
| 289 | |
| 290 | /* |
| 291 | * Helper functions for autoconfiguration. |
| 292 | */ |
| 293 | #ifndef PCI_MACHDEP_ENUMERATE_BUS |
| 294 | int pci_enumerate_bus(struct pci_softc *, const int *, |
| 295 | int (*)(const struct pci_attach_args *), struct pci_attach_args *); |
| 296 | #endif |
| 297 | int pci_probe_device(struct pci_softc *, pcitag_t tag, |
| 298 | int (*)(const struct pci_attach_args *), |
| 299 | struct pci_attach_args *); |
| 300 | void pci_devinfo(pcireg_t, pcireg_t, int, char *, size_t); |
| 301 | void pci_aprint_devinfo_fancy(const struct pci_attach_args *, |
| 302 | const char *, const char *, int); |
| 303 | #define pci_aprint_devinfo(pap, naive) \ |
| 304 | pci_aprint_devinfo_fancy(pap, naive, NULL, 0); |
| 305 | void pci_conf_print(pci_chipset_tag_t, pcitag_t, |
| 306 | void (*)(pci_chipset_tag_t, pcitag_t, const pcireg_t *)); |
| 307 | const struct pci_quirkdata * |
| 308 | pci_lookup_quirkdata(pci_vendor_id_t, pci_product_id_t); |
| 309 | |
| 310 | /* |
| 311 | * Helper functions for user access to the PCI bus. |
| 312 | */ |
| 313 | struct proc; |
| 314 | int pci_devioctl(pci_chipset_tag_t, pcitag_t, u_long, void *, |
| 315 | int flag, struct lwp *); |
| 316 | |
| 317 | /* |
| 318 | * Power Management (PCI 2.2) |
| 319 | */ |
| 320 | |
| 321 | #define PCI_PWR_D0 0 |
| 322 | #define PCI_PWR_D1 1 |
| 323 | #define PCI_PWR_D2 2 |
| 324 | #define PCI_PWR_D3 3 |
| 325 | int pci_powerstate(pci_chipset_tag_t, pcitag_t, const int *, int *); |
| 326 | |
| 327 | /* |
| 328 | * Vital Product Data (PCI 2.2) |
| 329 | */ |
| 330 | int pci_vpd_read(pci_chipset_tag_t, pcitag_t, int, int, pcireg_t *); |
| 331 | int pci_vpd_write(pci_chipset_tag_t, pcitag_t, int, int, pcireg_t *); |
| 332 | |
| 333 | /* |
| 334 | * Misc. |
| 335 | */ |
| 336 | int pci_find_device(struct pci_attach_args *pa, |
| 337 | int (*match)(const struct pci_attach_args *)); |
| 338 | int pci_dma64_available(const struct pci_attach_args *); |
| 339 | void pci_conf_capture(pci_chipset_tag_t, pcitag_t, struct pci_conf_state *); |
| 340 | void pci_conf_restore(pci_chipset_tag_t, pcitag_t, struct pci_conf_state *); |
| 341 | int pci_get_powerstate(pci_chipset_tag_t, pcitag_t, pcireg_t *); |
| 342 | int pci_set_powerstate(pci_chipset_tag_t, pcitag_t, pcireg_t); |
| 343 | int pci_activate(pci_chipset_tag_t, pcitag_t, device_t, |
| 344 | int (*)(pci_chipset_tag_t, pcitag_t, device_t, pcireg_t)); |
| 345 | int pci_activate_null(pci_chipset_tag_t, pcitag_t, device_t, pcireg_t); |
| 346 | int pci_chipset_tag_create(pci_chipset_tag_t, uint64_t, |
| 347 | const struct pci_overrides *, |
| 348 | void *, pci_chipset_tag_t *); |
| 349 | void pci_chipset_tag_destroy(pci_chipset_tag_t); |
| 350 | int pci_bus_devorder(pci_chipset_tag_t, int, uint8_t *, int); |
| 351 | void *pci_intr_establish_xname(pci_chipset_tag_t, pci_intr_handle_t, |
| 352 | int, int (*)(void *), void *, const char *); |
| 353 | #ifndef __HAVE_PCI_MSI_MSIX |
| 354 | typedef enum { |
| 355 | PCI_INTR_TYPE_INTX = 0, |
| 356 | PCI_INTR_TYPE_MSI, |
| 357 | PCI_INTR_TYPE_MSIX, |
| 358 | PCI_INTR_TYPE_SIZE, |
| 359 | } pci_intr_type_t; |
| 360 | |
| 361 | pci_intr_type_t |
| 362 | pci_intr_type(pci_chipset_tag_t, pci_intr_handle_t); |
| 363 | int pci_intr_alloc(const struct pci_attach_args *, pci_intr_handle_t **, |
| 364 | int *, pci_intr_type_t); |
| 365 | void pci_intr_release(pci_chipset_tag_t, pci_intr_handle_t *, int); |
| 366 | #endif |
| 367 | |
| 368 | /* |
| 369 | * Device abstraction for inheritance by elanpci(4), for example. |
| 370 | */ |
| 371 | int pcimatch(device_t, cfdata_t, void *); |
| 372 | void pciattach(device_t, device_t, void *); |
| 373 | int pcidetach(device_t, int); |
| 374 | void pcidevdetached(device_t, device_t); |
| 375 | int pcirescan(device_t, const char *, const int *); |
| 376 | |
| 377 | /* |
| 378 | * Interrupts. |
| 379 | */ |
| 380 | #define PCI_INTR_MPSAFE 1 |
| 381 | |
| 382 | int pci_intr_setattr(pci_chipset_tag_t, pci_intr_handle_t *, int, uint64_t); |
| 383 | |
| 384 | /* |
| 385 | * Local constants |
| 386 | */ |
| 387 | #define PCI_INTRSTR_LEN 64 |
| 388 | |
| 389 | #endif /* _KERNEL */ |
| 390 | |
| 391 | #endif /* _DEV_PCI_PCIVAR_H_ */ |
| 392 | |