| File: | arch/amd64/pci/pci_machdep.c |
| Warning: | line 608, column 11 The left operand of '==' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: pci_machdep.c,v 1.77 2021/03/11 11:16:55 jsg Exp $ */ | |||
| 2 | /* $NetBSD: pci_machdep.c,v 1.3 2003/05/07 21:33:58 fvdl Exp $ */ | |||
| 3 | ||||
| 4 | /*- | |||
| 5 | * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. | |||
| 6 | * All rights reserved. | |||
| 7 | * | |||
| 8 | * This code is derived from software contributed to The NetBSD Foundation | |||
| 9 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | |||
| 10 | * NASA Ames Research Center. | |||
| 11 | * | |||
| 12 | * Redistribution and use in source and binary forms, with or without | |||
| 13 | * modification, are permitted provided that the following conditions | |||
| 14 | * are met: | |||
| 15 | * 1. Redistributions of source code must retain the above copyright | |||
| 16 | * notice, this list of conditions and the following disclaimer. | |||
| 17 | * 2. Redistributions in binary form must reproduce the above copyright | |||
| 18 | * notice, this list of conditions and the following disclaimer in the | |||
| 19 | * documentation and/or other materials provided with the distribution. | |||
| 20 | * | |||
| 21 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |||
| 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |||
| 23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
| 24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |||
| 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
| 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||
| 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||
| 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||
| 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
| 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||
| 31 | * POSSIBILITY OF SUCH DAMAGE. | |||
| 32 | */ | |||
| 33 | ||||
| 34 | /* | |||
| 35 | * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. | |||
| 36 | * Copyright (c) 1994 Charles M. Hannum. All rights reserved. | |||
| 37 | * | |||
| 38 | * Redistribution and use in source and binary forms, with or without | |||
| 39 | * modification, are permitted provided that the following conditions | |||
| 40 | * are met: | |||
| 41 | * 1. Redistributions of source code must retain the above copyright | |||
| 42 | * notice, this list of conditions and the following disclaimer. | |||
| 43 | * 2. Redistributions in binary form must reproduce the above copyright | |||
| 44 | * notice, this list of conditions and the following disclaimer in the | |||
| 45 | * documentation and/or other materials provided with the distribution. | |||
| 46 | * 3. All advertising materials mentioning features or use of this software | |||
| 47 | * must display the following acknowledgement: | |||
| 48 | * This product includes software developed by Charles M. Hannum. | |||
| 49 | * 4. The name of the author may not be used to endorse or promote products | |||
| 50 | * derived from this software without specific prior written permission. | |||
| 51 | * | |||
| 52 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |||
| 53 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
| 54 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||
| 55 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
| 56 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
| 57 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
| 58 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
| 59 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
| 60 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||
| 61 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
| 62 | */ | |||
| 63 | ||||
| 64 | /* | |||
| 65 | * Machine-specific functions for PCI autoconfiguration. | |||
| 66 | */ | |||
| 67 | ||||
| 68 | #include <sys/param.h> | |||
| 69 | #include <sys/systm.h> | |||
| 70 | #include <sys/extent.h> | |||
| 71 | #include <sys/malloc.h> | |||
| 72 | ||||
| 73 | #include <machine/bus.h> | |||
| 74 | ||||
| 75 | #include <machine/pio.h> | |||
| 76 | #include <machine/intr.h> | |||
| 77 | #include <machine/biosvar.h> | |||
| 78 | ||||
| 79 | #include <dev/isa/isareg.h> | |||
| 80 | #include <dev/pci/pcivar.h> | |||
| 81 | #include <dev/pci/pcireg.h> | |||
| 82 | #include <dev/pci/pcidevs.h> | |||
| 83 | #include <dev/pci/ppbreg.h> | |||
| 84 | ||||
| 85 | #include "ioapic.h" | |||
| 86 | ||||
| 87 | #if NIOAPIC1 > 0 | |||
| 88 | #include <machine/i82093var.h> | |||
| 89 | #include <machine/mpbiosvar.h> | |||
| 90 | #endif | |||
| 91 | ||||
| 92 | #include "acpi.h" | |||
| 93 | ||||
| 94 | #include "acpidmar.h" | |||
| 95 | #if NACPIDMAR1 > 0 | |||
| 96 | #include <dev/acpi/acpidmar.h> | |||
| 97 | #endif | |||
| 98 | ||||
| 99 | /* | |||
| 100 | * Memory Mapped Configuration space access. | |||
| 101 | * | |||
| 102 | * Since mapping the whole configuration space will cost us up to | |||
| 103 | * 256MB of kernel virtual memory, we use separate mappings per bus. | |||
| 104 | * The mappings are created on-demand, such that we only use kernel | |||
| 105 | * virtual memory for busses that are actually present. | |||
| 106 | */ | |||
| 107 | bus_addr_t pci_mcfg_addr; | |||
| 108 | int pci_mcfg_min_bus, pci_mcfg_max_bus; | |||
| 109 | bus_space_tag_t pci_mcfgt; | |||
| 110 | bus_space_handle_t pci_mcfgh[256]; | |||
| 111 | ||||
| 112 | struct mutex pci_conf_lock = MUTEX_INITIALIZER(IPL_HIGH){ ((void *)0), ((((0xd)) > 0x0 && ((0xd)) < 0x9 ) ? 0x9 : ((0xd))), 0x0 }; | |||
| 113 | ||||
| 114 | #define PCI_CONF_LOCK()do { mtx_enter(&pci_conf_lock); } while (0) \ | |||
| 115 | do { \ | |||
| 116 | mtx_enter(&pci_conf_lock); \ | |||
| 117 | } while (0) | |||
| 118 | ||||
| 119 | #define PCI_CONF_UNLOCK()do { mtx_leave(&pci_conf_lock); } while (0) \ | |||
| 120 | do { \ | |||
| 121 | mtx_leave(&pci_conf_lock); \ | |||
| 122 | } while (0) | |||
| 123 | ||||
| 124 | #define PCI_MODE1_ENABLE0x80000000UL 0x80000000UL | |||
| 125 | #define PCI_MODE1_ADDRESS_REG0x0cf8 0x0cf8 | |||
| 126 | #define PCI_MODE1_DATA_REG0x0cfc 0x0cfc | |||
| 127 | ||||
| 128 | /* | |||
| 129 | * PCI doesn't have any special needs; just use the generic versions | |||
| 130 | * of these functions. | |||
| 131 | */ | |||
| 132 | struct bus_dma_tag pci_bus_dma_tag = { | |||
| 133 | NULL((void *)0), /* _may_bounce */ | |||
| 134 | _bus_dmamap_create, | |||
| 135 | _bus_dmamap_destroy, | |||
| 136 | _bus_dmamap_load, | |||
| 137 | _bus_dmamap_load_mbuf, | |||
| 138 | _bus_dmamap_load_uio, | |||
| 139 | _bus_dmamap_load_raw, | |||
| 140 | _bus_dmamap_unload, | |||
| 141 | _bus_dmamap_sync, | |||
| 142 | _bus_dmamem_alloc, | |||
| 143 | _bus_dmamem_alloc_range, | |||
| 144 | _bus_dmamem_free, | |||
| 145 | _bus_dmamem_map, | |||
| 146 | _bus_dmamem_unmap, | |||
| 147 | _bus_dmamem_mmap, | |||
| 148 | }; | |||
| 149 | ||||
| 150 | void | |||
| 151 | pci_mcfg_init(bus_space_tag_t iot, bus_addr_t addr, int segment, | |||
| 152 | int min_bus, int max_bus) | |||
| 153 | { | |||
| 154 | if (segment == 0) { | |||
| 155 | pci_mcfgt = iot; | |||
| 156 | pci_mcfg_addr = addr; | |||
| 157 | pci_mcfg_min_bus = min_bus; | |||
| 158 | pci_mcfg_max_bus = max_bus; | |||
| 159 | } | |||
| 160 | } | |||
| 161 | ||||
| 162 | pci_chipset_tag_t | |||
| 163 | pci_lookup_segment(int segment) | |||
| 164 | { | |||
| 165 | KASSERT(segment == 0)((segment == 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/arch/amd64/pci/pci_machdep.c" , 165, "segment == 0")); | |||
| 166 | return NULL((void *)0); | |||
| 167 | } | |||
| 168 | ||||
| 169 | void | |||
| 170 | pci_attach_hook(struct device *parent, struct device *self, | |||
| 171 | struct pcibus_attach_args *pba) | |||
| 172 | { | |||
| 173 | } | |||
| 174 | ||||
| 175 | int | |||
| 176 | pci_bus_maxdevs(pci_chipset_tag_t pc, int busno) | |||
| 177 | { | |||
| 178 | return (32); | |||
| 179 | } | |||
| 180 | ||||
| 181 | pcitag_t | |||
| 182 | pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function) | |||
| 183 | { | |||
| 184 | if (bus >= 256 || device >= 32 || function >= 8) | |||
| 185 | panic("pci_make_tag: bad request"); | |||
| 186 | ||||
| 187 | return (PCI_MODE1_ENABLE0x80000000UL | | |||
| 188 | (bus << 16) | (device << 11) | (function << 8)); | |||
| 189 | } | |||
| 190 | ||||
| 191 | void | |||
| 192 | pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int *fp) | |||
| 193 | { | |||
| 194 | if (bp != NULL((void *)0)) | |||
| 195 | *bp = (tag >> 16) & 0xff; | |||
| 196 | if (dp != NULL((void *)0)) | |||
| 197 | *dp = (tag >> 11) & 0x1f; | |||
| 198 | if (fp != NULL((void *)0)) | |||
| 199 | *fp = (tag >> 8) & 0x7; | |||
| 200 | } | |||
| 201 | ||||
| 202 | int | |||
| 203 | pci_conf_size(pci_chipset_tag_t pc, pcitag_t tag) | |||
| 204 | { | |||
| 205 | int bus; | |||
| 206 | ||||
| 207 | if (pci_mcfg_addr) { | |||
| 208 | pci_decompose_tag(pc, tag, &bus, NULL((void *)0), NULL((void *)0)); | |||
| 209 | if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) | |||
| 210 | return PCIE_CONFIG_SPACE_SIZE0x1000; | |||
| 211 | } | |||
| 212 | ||||
| 213 | return PCI_CONFIG_SPACE_SIZE0x100; | |||
| 214 | } | |||
| 215 | ||||
| 216 | void | |||
| 217 | pci_mcfg_map_bus(int bus) | |||
| 218 | { | |||
| 219 | if (pci_mcfgh[bus]) | |||
| 220 | return; | |||
| 221 | ||||
| 222 | if (bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20), 1 << 20, | |||
| 223 | 0, &pci_mcfgh[bus])) | |||
| 224 | panic("pci_conf_read: cannot map mcfg space"); | |||
| 225 | } | |||
| 226 | ||||
| 227 | pcireg_t | |||
| 228 | pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) | |||
| 229 | { | |||
| 230 | pcireg_t data; | |||
| 231 | int bus; | |||
| 232 | ||||
| 233 | KASSERT((reg & 0x3) == 0)(((reg & 0x3) == 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/arch/amd64/pci/pci_machdep.c" , 233, "(reg & 0x3) == 0")); | |||
| 234 | ||||
| 235 | if (pci_mcfg_addr && reg >= PCI_CONFIG_SPACE_SIZE0x100) { | |||
| 236 | pci_decompose_tag(pc, tag, &bus, NULL((void *)0), NULL((void *)0)); | |||
| 237 | if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) { | |||
| 238 | pci_mcfg_map_bus(bus); | |||
| 239 | data = bus_space_read_4(pci_mcfgt, pci_mcfgh[bus],((pci_mcfgt)->read_4((pci_mcfgh[bus]), ((tag & 0x000ff00 ) << 4 | reg))) | |||
| 240 | (tag & 0x000ff00) << 4 | reg)((pci_mcfgt)->read_4((pci_mcfgh[bus]), ((tag & 0x000ff00 ) << 4 | reg))); | |||
| 241 | return data; | |||
| 242 | } | |||
| 243 | } | |||
| 244 | ||||
| 245 | PCI_CONF_LOCK()do { mtx_enter(&pci_conf_lock); } while (0); | |||
| 246 | outl(PCI_MODE1_ADDRESS_REG, tag | reg)( (__builtin_constant_p((0x0cf8)) && (0x0cf8) < 0x100 ) ? __outlc(0x0cf8, tag | reg) : __outl(0x0cf8, tag | reg)); | |||
| 247 | data = inl(PCI_MODE1_DATA_REG)( (__builtin_constant_p((0x0cfc)) && (0x0cfc) < 0x100 ) ? __inlc(0x0cfc) : __inl(0x0cfc)); | |||
| 248 | outl(PCI_MODE1_ADDRESS_REG, 0)( (__builtin_constant_p((0x0cf8)) && (0x0cf8) < 0x100 ) ? __outlc(0x0cf8, 0) : __outl(0x0cf8, 0)); | |||
| 249 | PCI_CONF_UNLOCK()do { mtx_leave(&pci_conf_lock); } while (0); | |||
| 250 | ||||
| 251 | return data; | |||
| 252 | } | |||
| 253 | ||||
| 254 | void | |||
| 255 | pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) | |||
| 256 | { | |||
| 257 | int bus; | |||
| 258 | ||||
| 259 | KASSERT((reg & 0x3) == 0)(((reg & 0x3) == 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/arch/amd64/pci/pci_machdep.c" , 259, "(reg & 0x3) == 0")); | |||
| 260 | ||||
| 261 | if (pci_mcfg_addr && reg >= PCI_CONFIG_SPACE_SIZE0x100) { | |||
| 262 | pci_decompose_tag(pc, tag, &bus, NULL((void *)0), NULL((void *)0)); | |||
| 263 | if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) { | |||
| 264 | pci_mcfg_map_bus(bus); | |||
| 265 | bus_space_write_4(pci_mcfgt, pci_mcfgh[bus],((pci_mcfgt)->write_4((pci_mcfgh[bus]), ((tag & 0x000ff00 ) << 4 | reg), (data))) | |||
| 266 | (tag & 0x000ff00) << 4 | reg, data)((pci_mcfgt)->write_4((pci_mcfgh[bus]), ((tag & 0x000ff00 ) << 4 | reg), (data))); | |||
| 267 | return; | |||
| 268 | } | |||
| 269 | } | |||
| 270 | ||||
| 271 | PCI_CONF_LOCK()do { mtx_enter(&pci_conf_lock); } while (0); | |||
| 272 | outl(PCI_MODE1_ADDRESS_REG, tag | reg)( (__builtin_constant_p((0x0cf8)) && (0x0cf8) < 0x100 ) ? __outlc(0x0cf8, tag | reg) : __outl(0x0cf8, tag | reg)); | |||
| 273 | outl(PCI_MODE1_DATA_REG, data)( (__builtin_constant_p((0x0cfc)) && (0x0cfc) < 0x100 ) ? __outlc(0x0cfc, data) : __outl(0x0cfc, data)); | |||
| 274 | outl(PCI_MODE1_ADDRESS_REG, 0)( (__builtin_constant_p((0x0cf8)) && (0x0cf8) < 0x100 ) ? __outlc(0x0cf8, 0) : __outl(0x0cf8, 0)); | |||
| 275 | PCI_CONF_UNLOCK()do { mtx_leave(&pci_conf_lock); } while (0); | |||
| 276 | } | |||
| 277 | ||||
| 278 | int | |||
| 279 | pci_msix_table_map(pci_chipset_tag_t pc, pcitag_t tag, | |||
| 280 | bus_space_tag_t memt, bus_space_handle_t *memh) | |||
| 281 | { | |||
| 282 | bus_addr_t base; | |||
| 283 | pcireg_t reg, table, type; | |||
| 284 | int bir, offset; | |||
| 285 | int off, tblsz; | |||
| 286 | ||||
| 287 | if (pci_get_capability(pc, tag, PCI_CAP_MSIX0x11, &off, ®) == 0) | |||
| 288 | panic("%s: no msix capability", __func__); | |||
| 289 | ||||
| 290 | table = pci_conf_read(pc, tag, off + PCI_MSIX_TABLE0x04); | |||
| 291 | bir = (table & PCI_MSIX_TABLE_BIR0x00000007); | |||
| 292 | offset = (table & PCI_MSIX_TABLE_OFF~(0x00000007)); | |||
| 293 | tblsz = PCI_MSIX_MC_TBLSZ(reg)(((reg) & 0x07ff0000) >> 16) + 1; | |||
| 294 | ||||
| 295 | bir = PCI_MAPREG_START0x10 + bir * 4; | |||
| 296 | type = pci_mapreg_type(pc, tag, bir); | |||
| 297 | if (pci_mapreg_info(pc, tag, bir, type, &base, NULL((void *)0), NULL((void *)0)) || | |||
| 298 | _bus_space_map(memt, base + offset, tblsz * 16, 0, memh)) | |||
| 299 | return -1; | |||
| 300 | ||||
| 301 | return 0; | |||
| 302 | } | |||
| 303 | ||||
| 304 | void | |||
| 305 | pci_msix_table_unmap(pci_chipset_tag_t pc, pcitag_t tag, | |||
| 306 | bus_space_tag_t memt, bus_space_handle_t memh) | |||
| 307 | { | |||
| 308 | pcireg_t reg; | |||
| 309 | int tblsz; | |||
| 310 | ||||
| 311 | if (pci_get_capability(pc, tag, PCI_CAP_MSIX0x11, NULL((void *)0), ®) == 0) | |||
| 312 | panic("%s: no msix capability", __func__); | |||
| 313 | ||||
| 314 | tblsz = PCI_MSIX_MC_TBLSZ(reg)(((reg) & 0x07ff0000) >> 16) + 1; | |||
| 315 | _bus_space_unmap(memt, memh, tblsz * 16, NULL((void *)0)); | |||
| 316 | } | |||
| 317 | ||||
| 318 | void msi_hwmask(struct pic *, int); | |||
| 319 | void msi_hwunmask(struct pic *, int); | |||
| 320 | void msi_addroute(struct pic *, struct cpu_info *, int, int, int); | |||
| 321 | void msi_delroute(struct pic *, struct cpu_info *, int, int, int); | |||
| 322 | ||||
| 323 | struct pic msi_pic = { | |||
| 324 | {0, {NULL((void *)0)}, NULL((void *)0), 0, "msi", NULL((void *)0), 0, 0}, | |||
| 325 | PIC_MSI3, | |||
| 326 | #ifdef MULTIPROCESSOR1 | |||
| 327 | {}, | |||
| 328 | #endif | |||
| 329 | msi_hwmask, | |||
| 330 | msi_hwunmask, | |||
| 331 | msi_addroute, | |||
| 332 | msi_delroute, | |||
| 333 | NULL((void *)0), | |||
| 334 | ioapic_edge_stubs | |||
| 335 | }; | |||
| 336 | ||||
| 337 | void | |||
| 338 | msi_hwmask(struct pic *pic, int pin) | |||
| 339 | { | |||
| 340 | } | |||
| 341 | ||||
| 342 | void | |||
| 343 | msi_hwunmask(struct pic *pic, int pin) | |||
| 344 | { | |||
| 345 | } | |||
| 346 | ||||
| 347 | void | |||
| 348 | msi_addroute(struct pic *pic, struct cpu_info *ci, int pin, int vec, int type) | |||
| 349 | { | |||
| 350 | pci_chipset_tag_t pc = NULL((void *)0); /* XXX */ | |||
| 351 | pcitag_t tag = pin; | |||
| 352 | pcireg_t reg, addr; | |||
| 353 | int off; | |||
| 354 | ||||
| 355 | if (pci_get_capability(pc, tag, PCI_CAP_MSI0x05, &off, ®) == 0) | |||
| 356 | panic("%s: no msi capability", __func__); | |||
| 357 | ||||
| 358 | addr = 0xfee00000UL | (ci->ci_apicid << 12); | |||
| 359 | ||||
| 360 | if (reg & PCI_MSI_MC_C640x00800000) { | |||
| 361 | pci_conf_write(pc, tag, off + PCI_MSI_MA0x04, addr); | |||
| 362 | pci_conf_write(pc, tag, off + PCI_MSI_MAU320x08, 0); | |||
| 363 | pci_conf_write(pc, tag, off + PCI_MSI_MD640x0c, vec); | |||
| 364 | } else { | |||
| 365 | pci_conf_write(pc, tag, off + PCI_MSI_MA0x04, addr); | |||
| 366 | pci_conf_write(pc, tag, off + PCI_MSI_MD320x08, vec); | |||
| 367 | } | |||
| 368 | pci_conf_write(pc, tag, off, reg | PCI_MSI_MC_MSIE0x00010000); | |||
| 369 | } | |||
| 370 | ||||
| 371 | void | |||
| 372 | msi_delroute(struct pic *pic, struct cpu_info *ci, int pin, int vec, int type) | |||
| 373 | { | |||
| 374 | pci_chipset_tag_t pc = NULL((void *)0); /* XXX */ | |||
| 375 | pcitag_t tag = pin; | |||
| 376 | pcireg_t reg; | |||
| 377 | int off; | |||
| 378 | ||||
| 379 | if (pci_get_capability(pc, tag, PCI_CAP_MSI0x05, &off, ®)) | |||
| 380 | pci_conf_write(pc, tag, off, reg & ~PCI_MSI_MC_MSIE0x00010000); | |||
| 381 | } | |||
| 382 | ||||
| 383 | int | |||
| 384 | pci_intr_map_msi(struct pci_attach_args *pa, pci_intr_handle_t *ihp) | |||
| 385 | { | |||
| 386 | pci_chipset_tag_t pc = pa->pa_pc; | |||
| 387 | pcitag_t tag = pa->pa_tag; | |||
| 388 | ||||
| 389 | if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED0x20) == 0 || mp_busses == NULL((void *)0) || | |||
| 390 | pci_get_capability(pc, tag, PCI_CAP_MSI0x05, NULL((void *)0), NULL((void *)0)) == 0) | |||
| 391 | return 1; | |||
| 392 | ||||
| 393 | ihp->tag = tag; | |||
| 394 | ihp->line = APIC_INT_VIA_MSG0x20000000; | |||
| 395 | ihp->pin = 0; | |||
| 396 | return 0; | |||
| 397 | } | |||
| 398 | ||||
| 399 | void msix_hwmask(struct pic *, int); | |||
| 400 | void msix_hwunmask(struct pic *, int); | |||
| 401 | void msix_addroute(struct pic *, struct cpu_info *, int, int, int); | |||
| 402 | void msix_delroute(struct pic *, struct cpu_info *, int, int, int); | |||
| 403 | ||||
| 404 | struct pic msix_pic = { | |||
| 405 | {0, {NULL((void *)0)}, NULL((void *)0), 0, "msix", NULL((void *)0), 0, 0}, | |||
| 406 | PIC_MSI3, | |||
| 407 | #ifdef MULTIPROCESSOR1 | |||
| 408 | {}, | |||
| 409 | #endif | |||
| 410 | msix_hwmask, | |||
| 411 | msix_hwunmask, | |||
| 412 | msix_addroute, | |||
| 413 | msix_delroute, | |||
| 414 | NULL((void *)0), | |||
| 415 | ioapic_edge_stubs | |||
| 416 | }; | |||
| 417 | ||||
| 418 | /* | |||
| 419 | * We pack the MSI-X vector number into the lower 8 bits of the PCI | |||
| 420 | * tag and use that as the MSI-X "PIC" pin number. This allows us to | |||
| 421 | * address 256 MSI-X vectors which ought to be enough for anybody. | |||
| 422 | */ | |||
| 423 | #define PCI_MSIX_VEC_MASK0xff 0xff | |||
| 424 | #define PCI_MSIX_VEC(pin)((pin) & 0xff) ((pin) & PCI_MSIX_VEC_MASK0xff) | |||
| 425 | #define PCI_MSIX_TAG(pin)((pin) & ~0xff) ((pin) & ~PCI_MSIX_VEC_MASK0xff) | |||
| 426 | #define PCI_MSIX_PIN(tag, vec)((tag) | (vec)) ((tag) | (vec)) | |||
| 427 | ||||
| 428 | void | |||
| 429 | msix_hwmask(struct pic *pic, int pin) | |||
| 430 | { | |||
| 431 | } | |||
| 432 | ||||
| 433 | void | |||
| 434 | msix_hwunmask(struct pic *pic, int pin) | |||
| 435 | { | |||
| 436 | } | |||
| 437 | ||||
| 438 | void | |||
| 439 | msix_addroute(struct pic *pic, struct cpu_info *ci, int pin, int vec, int type) | |||
| 440 | { | |||
| 441 | pci_chipset_tag_t pc = NULL((void *)0); /* XXX */ | |||
| 442 | bus_space_tag_t memt = X86_BUS_SPACE_MEM(&x86_bus_space_mem_ops); /* XXX */ | |||
| 443 | bus_space_handle_t memh; | |||
| 444 | pcitag_t tag = PCI_MSIX_TAG(pin)((pin) & ~0xff); | |||
| 445 | int entry = PCI_MSIX_VEC(pin)((pin) & 0xff); | |||
| 446 | pcireg_t reg, addr; | |||
| 447 | uint32_t ctrl; | |||
| 448 | int off; | |||
| 449 | ||||
| 450 | if (pci_get_capability(pc, tag, PCI_CAP_MSIX0x11, &off, ®) == 0) | |||
| 451 | panic("%s: no msix capability", __func__); | |||
| 452 | ||||
| 453 | KASSERT(entry <= PCI_MSIX_MC_TBLSZ(reg))((entry <= (((reg) & 0x07ff0000) >> 16)) ? (void )0 : __assert("diagnostic ", "/usr/src/sys/arch/amd64/pci/pci_machdep.c" , 453, "entry <= PCI_MSIX_MC_TBLSZ(reg)")); | |||
| 454 | ||||
| 455 | if (pci_msix_table_map(pc, tag, memt, &memh)) | |||
| 456 | panic("%s: cannot map registers", __func__); | |||
| 457 | ||||
| 458 | addr = 0xfee00000UL | (ci->ci_apicid << 12); | |||
| 459 | ||||
| 460 | bus_space_write_4(memt, memh, PCI_MSIX_MA(entry), addr)((memt)->write_4((memh), (((entry) * 16 + 0)), (addr))); | |||
| 461 | bus_space_write_4(memt, memh, PCI_MSIX_MAU32(entry), 0)((memt)->write_4((memh), (((entry) * 16 + 4)), (0))); | |||
| 462 | bus_space_write_4(memt, memh, PCI_MSIX_MD(entry), vec)((memt)->write_4((memh), (((entry) * 16 + 8)), (vec))); | |||
| 463 | bus_space_barrier(memt, memh, PCI_MSIX_MA(entry)((entry) * 16 + 0), 16, | |||
| 464 | BUS_SPACE_BARRIER_WRITE0x02); | |||
| 465 | ctrl = bus_space_read_4(memt, memh, PCI_MSIX_VC(entry))((memt)->read_4((memh), (((entry) * 16 + 12)))); | |||
| 466 | bus_space_write_4(memt, memh, PCI_MSIX_VC(entry),((memt)->write_4((memh), (((entry) * 16 + 12)), (ctrl & ~0x00000001))) | |||
| 467 | ctrl & ~PCI_MSIX_VC_MASK)((memt)->write_4((memh), (((entry) * 16 + 12)), (ctrl & ~0x00000001))); | |||
| 468 | ||||
| 469 | pci_msix_table_unmap(pc, tag, memt, memh); | |||
| 470 | ||||
| 471 | pci_conf_write(pc, tag, off, reg | PCI_MSIX_MC_MSIXE0x80000000); | |||
| 472 | } | |||
| 473 | ||||
| 474 | void | |||
| 475 | msix_delroute(struct pic *pic, struct cpu_info *ci, int pin, int vec, int type) | |||
| 476 | { | |||
| 477 | pci_chipset_tag_t pc = NULL((void *)0); /* XXX */ | |||
| 478 | bus_space_tag_t memt = X86_BUS_SPACE_MEM(&x86_bus_space_mem_ops); /* XXX */ | |||
| 479 | bus_space_handle_t memh; | |||
| 480 | pcitag_t tag = PCI_MSIX_TAG(pin)((pin) & ~0xff); | |||
| 481 | int entry = PCI_MSIX_VEC(pin)((pin) & 0xff); | |||
| 482 | pcireg_t reg; | |||
| 483 | uint32_t ctrl; | |||
| 484 | ||||
| 485 | if (pci_get_capability(pc, tag, PCI_CAP_MSIX0x11, NULL((void *)0), ®) == 0) | |||
| 486 | return; | |||
| 487 | ||||
| 488 | KASSERT(entry <= PCI_MSIX_MC_TBLSZ(reg))((entry <= (((reg) & 0x07ff0000) >> 16)) ? (void )0 : __assert("diagnostic ", "/usr/src/sys/arch/amd64/pci/pci_machdep.c" , 488, "entry <= PCI_MSIX_MC_TBLSZ(reg)")); | |||
| 489 | ||||
| 490 | if (pci_msix_table_map(pc, tag, memt, &memh)) | |||
| 491 | return; | |||
| 492 | ||||
| 493 | ctrl = bus_space_read_4(memt, memh, PCI_MSIX_VC(entry))((memt)->read_4((memh), (((entry) * 16 + 12)))); | |||
| 494 | bus_space_write_4(memt, memh, PCI_MSIX_VC(entry),((memt)->write_4((memh), (((entry) * 16 + 12)), (ctrl | 0x00000001 ))) | |||
| 495 | ctrl | PCI_MSIX_VC_MASK)((memt)->write_4((memh), (((entry) * 16 + 12)), (ctrl | 0x00000001 ))); | |||
| 496 | ||||
| 497 | pci_msix_table_unmap(pc, tag, memt, memh); | |||
| 498 | } | |||
| 499 | ||||
| 500 | int | |||
| 501 | pci_intr_map_msix(struct pci_attach_args *pa, int vec, pci_intr_handle_t *ihp) | |||
| 502 | { | |||
| 503 | pci_chipset_tag_t pc = pa->pa_pc; | |||
| 504 | pcitag_t tag = pa->pa_tag; | |||
| 505 | pcireg_t reg; | |||
| 506 | ||||
| 507 | KASSERT(PCI_MSIX_VEC(vec) == vec)((((vec) & 0xff) == vec) ? (void)0 : __assert("diagnostic " , "/usr/src/sys/arch/amd64/pci/pci_machdep.c", 507, "PCI_MSIX_VEC(vec) == vec" )); | |||
| 508 | ||||
| 509 | if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED0x20) == 0 || mp_busses == NULL((void *)0) || | |||
| 510 | pci_get_capability(pc, tag, PCI_CAP_MSIX0x11, NULL((void *)0), ®) == 0) | |||
| 511 | return 1; | |||
| 512 | ||||
| 513 | if (vec > PCI_MSIX_MC_TBLSZ(reg)(((reg) & 0x07ff0000) >> 16)) | |||
| 514 | return 1; | |||
| 515 | ||||
| 516 | ihp->tag = PCI_MSIX_PIN(tag, vec)((tag) | (vec)); | |||
| 517 | ihp->line = APIC_INT_VIA_MSGX0x40000000; | |||
| 518 | ihp->pin = 0; | |||
| 519 | return 0; | |||
| 520 | } | |||
| 521 | ||||
| 522 | int | |||
| 523 | pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) | |||
| 524 | { | |||
| 525 | int pin = pa->pa_rawintrpin; | |||
| 526 | int line = pa->pa_intrline; | |||
| 527 | #if NIOAPIC1 > 0 | |||
| 528 | struct mp_intr_map *mip; | |||
| ||||
| 529 | int bus, dev, func; | |||
| 530 | #endif | |||
| 531 | ||||
| 532 | if (pin == 0) { | |||
| 533 | /* No IRQ used. */ | |||
| 534 | goto bad; | |||
| 535 | } | |||
| 536 | ||||
| 537 | if (pin > PCI_INTERRUPT_PIN_MAX0x04) { | |||
| 538 | printf("pci_intr_map: bad interrupt pin %d\n", pin); | |||
| 539 | goto bad; | |||
| 540 | } | |||
| 541 | ||||
| 542 | ihp->tag = pa->pa_tag; | |||
| 543 | ihp->line = line; | |||
| 544 | ihp->pin = pin; | |||
| 545 | ||||
| 546 | #if NIOAPIC1 > 0 | |||
| 547 | pci_decompose_tag(pa->pa_pc, pa->pa_tag, &bus, &dev, &func); | |||
| 548 | ||||
| 549 | if (mp_busses != NULL((void *)0)) { | |||
| 550 | int mpspec_pin = (dev << 2) | (pin - 1); | |||
| 551 | ||||
| 552 | if (bus < mp_nbusses) { | |||
| 553 | for (mip = mp_busses[bus].mb_intrs; | |||
| 554 | mip != NULL((void *)0); mip = mip->next) { | |||
| 555 | if (&mp_busses[bus] == mp_isa_bus || | |||
| 556 | &mp_busses[bus] == mp_eisa_bus) | |||
| 557 | continue; | |||
| 558 | if (mip->bus_pin == mpspec_pin) { | |||
| 559 | ihp->line = mip->ioapic_ih | line; | |||
| 560 | return 0; | |||
| 561 | } | |||
| 562 | } | |||
| 563 | } | |||
| 564 | ||||
| 565 | if (pa->pa_bridgetag) { | |||
| 566 | int swizpin = PPB_INTERRUPT_SWIZZLE(pin, dev)((((pin) + (dev) - 1) % 4) + 1); | |||
| 567 | if (pa->pa_bridgeih[swizpin - 1].line != -1) { | |||
| 568 | ihp->line = pa->pa_bridgeih[swizpin - 1].line; | |||
| 569 | ihp->line |= line; | |||
| 570 | return 0; | |||
| 571 | } | |||
| 572 | } | |||
| 573 | /* | |||
| 574 | * No explicit PCI mapping found. This is not fatal, | |||
| 575 | * we'll try the ISA (or possibly EISA) mappings next. | |||
| 576 | */ | |||
| 577 | } | |||
| 578 | #endif | |||
| 579 | ||||
| 580 | /* | |||
| 581 | * Section 6.2.4, `Miscellaneous Functions', says that 255 means | |||
| 582 | * `unknown' or `no connection' on a PC. We assume that a device with | |||
| 583 | * `no connection' either doesn't have an interrupt (in which case the | |||
| 584 | * pin number should be 0, and would have been noticed above), or | |||
| 585 | * wasn't configured by the BIOS (in which case we punt, since there's | |||
| 586 | * no real way we can know how the interrupt lines are mapped in the | |||
| 587 | * hardware). | |||
| 588 | * | |||
| 589 | * XXX | |||
| 590 | * Since IRQ 0 is only used by the clock, and we can't actually be sure | |||
| 591 | * that the BIOS did its job, we also recognize that as meaning that | |||
| 592 | * the BIOS has not configured the device. | |||
| 593 | */ | |||
| 594 | if (line == 0 || line == X86_PCI_INTERRUPT_LINE_NO_CONNECTION0xff) | |||
| 595 | goto bad; | |||
| 596 | ||||
| 597 | if (line >= NUM_LEGACY_IRQS16) { | |||
| 598 | printf("pci_intr_map: bad interrupt line %d\n", line); | |||
| 599 | goto bad; | |||
| 600 | } | |||
| 601 | if (line == 2) { | |||
| 602 | printf("pci_intr_map: changed line 2 to line 9\n"); | |||
| 603 | line = 9; | |||
| 604 | } | |||
| 605 | ||||
| 606 | #if NIOAPIC1 > 0 | |||
| 607 | if (mp_busses != NULL((void *)0)) { | |||
| 608 | if (mip == NULL((void *)0) && mp_isa_bus) { | |||
| ||||
| 609 | for (mip = mp_isa_bus->mb_intrs; mip != NULL((void *)0); | |||
| 610 | mip = mip->next) { | |||
| 611 | if (mip->bus_pin == line) { | |||
| 612 | ihp->line = mip->ioapic_ih | line; | |||
| 613 | return 0; | |||
| 614 | } | |||
| 615 | } | |||
| 616 | } | |||
| 617 | #if NEISA > 0 | |||
| 618 | if (mip == NULL((void *)0) && mp_eisa_bus) { | |||
| 619 | for (mip = mp_eisa_bus->mb_intrs; mip != NULL((void *)0); | |||
| 620 | mip = mip->next) { | |||
| 621 | if (mip->bus_pin == line) { | |||
| 622 | ihp->line = mip->ioapic_ih | line; | |||
| 623 | return 0; | |||
| 624 | } | |||
| 625 | } | |||
| 626 | } | |||
| 627 | #endif | |||
| 628 | if (mip == NULL((void *)0)) { | |||
| 629 | printf("pci_intr_map: " | |||
| 630 | "bus %d dev %d func %d pin %d; line %d\n", | |||
| 631 | bus, dev, func, pin, line); | |||
| 632 | printf("pci_intr_map: no MP mapping found\n"); | |||
| 633 | } | |||
| 634 | } | |||
| 635 | #endif | |||
| 636 | ||||
| 637 | return 0; | |||
| 638 | ||||
| 639 | bad: | |||
| 640 | ihp->line = -1; | |||
| 641 | return 1; | |||
| 642 | } | |||
| 643 | ||||
| 644 | const char * | |||
| 645 | pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih) | |||
| 646 | { | |||
| 647 | static char irqstr[64]; | |||
| 648 | ||||
| 649 | if (ih.line == 0) | |||
| 650 | panic("pci_intr_string: bogus handle 0x%x", ih.line); | |||
| 651 | ||||
| 652 | if (ih.line & APIC_INT_VIA_MSG0x20000000) | |||
| 653 | return ("msi"); | |||
| 654 | if (ih.line & APIC_INT_VIA_MSGX0x40000000) | |||
| 655 | return ("msix"); | |||
| 656 | ||||
| 657 | #if NIOAPIC1 > 0 | |||
| 658 | if (ih.line & APIC_INT_VIA_APIC0x10000000) | |||
| 659 | snprintf(irqstr, sizeof(irqstr), "apic %d int %d", | |||
| 660 | APIC_IRQ_APIC(ih.line)((ih.line & 0x00ff0000) >> 16), APIC_IRQ_PIN(ih.line)((ih.line & 0x0000ff00) >> 8)); | |||
| 661 | else | |||
| 662 | snprintf(irqstr, sizeof(irqstr), "irq %d", | |||
| 663 | pci_intr_line(pc, ih)((ih.line) & 0xff)); | |||
| 664 | #else | |||
| 665 | snprintf(irqstr, sizeof(irqstr), "irq %d", pci_intr_line(pc, ih)((ih.line) & 0xff)); | |||
| 666 | #endif | |||
| 667 | return (irqstr); | |||
| 668 | } | |||
| 669 | ||||
| 670 | #include "acpiprt.h" | |||
| 671 | #if NACPIPRT1 > 0 | |||
| 672 | void acpiprt_route_interrupt(int bus, int dev, int pin); | |||
| 673 | #endif | |||
| 674 | ||||
| 675 | void * | |||
| 676 | pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level, | |||
| 677 | int (*func)(void *), void *arg, const char *what) | |||
| 678 | { | |||
| 679 | return pci_intr_establish_cpu(pc, ih, level, NULL((void *)0), func, arg, what); | |||
| 680 | } | |||
| 681 | ||||
| 682 | void * | |||
| 683 | pci_intr_establish_cpu(pci_chipset_tag_t pc, pci_intr_handle_t ih, | |||
| 684 | int level, struct cpu_info *ci, | |||
| 685 | int (*func)(void *), void *arg, const char *what) | |||
| 686 | { | |||
| 687 | int pin, irq; | |||
| 688 | int bus, dev; | |||
| 689 | pcitag_t tag = ih.tag; | |||
| 690 | struct pic *pic; | |||
| 691 | ||||
| 692 | if (ih.line & APIC_INT_VIA_MSG0x20000000) { | |||
| 693 | return intr_establish(-1, &msi_pic, tag, IST_PULSE1, level, | |||
| 694 | ci, func, arg, what); | |||
| 695 | } | |||
| 696 | if (ih.line & APIC_INT_VIA_MSGX0x40000000) { | |||
| 697 | return intr_establish(-1, &msix_pic, tag, IST_PULSE1, level, | |||
| 698 | ci, func, arg, what); | |||
| 699 | } | |||
| 700 | ||||
| 701 | pci_decompose_tag(pc, ih.tag, &bus, &dev, NULL((void *)0)); | |||
| 702 | #if NACPIPRT1 > 0 | |||
| 703 | acpiprt_route_interrupt(bus, dev, ih.pin); | |||
| 704 | #endif | |||
| 705 | ||||
| 706 | pic = &i8259_pic; | |||
| 707 | pin = irq = ih.line; | |||
| 708 | ||||
| 709 | #if NIOAPIC1 > 0 | |||
| 710 | if (ih.line & APIC_INT_VIA_APIC0x10000000) { | |||
| 711 | pic = (struct pic *)ioapic_find(APIC_IRQ_APIC(ih.line)((ih.line & 0x00ff0000) >> 16)); | |||
| 712 | if (pic == NULL((void *)0)) { | |||
| 713 | printf("pci_intr_establish: bad ioapic %d\n", | |||
| 714 | APIC_IRQ_APIC(ih.line)((ih.line & 0x00ff0000) >> 16)); | |||
| 715 | return NULL((void *)0); | |||
| 716 | } | |||
| 717 | pin = APIC_IRQ_PIN(ih.line)((ih.line & 0x0000ff00) >> 8); | |||
| 718 | irq = APIC_IRQ_LEGACY_IRQ(ih.line)((ih.line) & 0xff); | |||
| 719 | if (irq < 0 || irq >= NUM_LEGACY_IRQS16) | |||
| 720 | irq = -1; | |||
| 721 | } | |||
| 722 | #endif | |||
| 723 | ||||
| 724 | return intr_establish(irq, pic, pin, IST_LEVEL3, level, ci, | |||
| 725 | func, arg, what); | |||
| 726 | } | |||
| 727 | ||||
| 728 | void | |||
| 729 | pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie) | |||
| 730 | { | |||
| 731 | intr_disestablish(cookie); | |||
| 732 | } | |||
| 733 | ||||
| 734 | struct extent *pciio_ex; | |||
| 735 | struct extent *pcimem_ex; | |||
| 736 | struct extent *pcibus_ex; | |||
| 737 | ||||
| 738 | void | |||
| 739 | pci_init_extents(void) | |||
| 740 | { | |||
| 741 | bios_memmap_t *bmp; | |||
| 742 | u_int64_t size; | |||
| 743 | ||||
| 744 | if (pciio_ex == NULL((void *)0)) { | |||
| 745 | /* | |||
| 746 | * We only have 64K of addressable I/O space. | |||
| 747 | * However, since BARs may contain garbage, we cover | |||
| 748 | * the full 32-bit address space defined by PCI of | |||
| 749 | * which we only make the first 64K available. | |||
| 750 | */ | |||
| 751 | pciio_ex = extent_create("pciio", 0, 0xffffffff, M_DEVBUF2, | |||
| 752 | NULL((void *)0), 0, EX_NOWAIT0x0000 | EX_FILLED0x0100); | |||
| 753 | if (pciio_ex == NULL((void *)0)) | |||
| 754 | return; | |||
| 755 | extent_free(pciio_ex, 0, 0x10000, EX_NOWAIT0x0000); | |||
| 756 | } | |||
| 757 | ||||
| 758 | if (pcimem_ex == NULL((void *)0)) { | |||
| 759 | /* | |||
| 760 | * Cover the 36-bit address space addressable by PAE | |||
| 761 | * here. As long as vendors continue to support | |||
| 762 | * 32-bit operating systems, we should never see BARs | |||
| 763 | * outside that region. | |||
| 764 | * | |||
| 765 | * Dell 13G servers have important devices outside the | |||
| 766 | * 36-bit address space. Until we can extract the address | |||
| 767 | * ranges from ACPI, expand the allowed range to suit. | |||
| 768 | */ | |||
| 769 | pcimem_ex = extent_create("pcimem", 0, 0xffffffffffffffffUL, | |||
| 770 | M_DEVBUF2, NULL((void *)0), 0, EX_NOWAIT0x0000); | |||
| 771 | if (pcimem_ex == NULL((void *)0)) | |||
| 772 | return; | |||
| 773 | extent_alloc_region(pcimem_ex, 0x40000000000UL, | |||
| 774 | 0xfffffc0000000000UL, EX_NOWAIT0x0000); | |||
| 775 | ||||
| 776 | for (bmp = bios_memmap; bmp->type != BIOS_MAP_END0x00; bmp++) { | |||
| 777 | /* | |||
| 778 | * Ignore address space beyond 4G. | |||
| 779 | */ | |||
| 780 | if (bmp->addr >= 0x100000000ULL) | |||
| 781 | continue; | |||
| 782 | size = bmp->size; | |||
| 783 | if (bmp->addr + size >= 0x100000000ULL) | |||
| 784 | size = 0x100000000ULL - bmp->addr; | |||
| 785 | ||||
| 786 | /* Ignore zero-sized regions. */ | |||
| 787 | if (size == 0) | |||
| 788 | continue; | |||
| 789 | ||||
| 790 | if (extent_alloc_region(pcimem_ex, bmp->addr, size, | |||
| 791 | EX_NOWAIT0x0000)) | |||
| 792 | printf("memory map conflict 0x%llx/0x%llx\n", | |||
| 793 | bmp->addr, bmp->size); | |||
| 794 | } | |||
| 795 | ||||
| 796 | /* Take out the video buffer area and BIOS areas. */ | |||
| 797 | extent_alloc_region(pcimem_ex, IOM_BEGIN0x0a0000, IOM_SIZE(0x100000 - 0x0a0000), | |||
| 798 | EX_CONFLICTOK0x0080 | EX_NOWAIT0x0000); | |||
| 799 | } | |||
| 800 | ||||
| 801 | if (pcibus_ex == NULL((void *)0)) { | |||
| 802 | pcibus_ex = extent_create("pcibus", 0, 0xff, M_DEVBUF2, | |||
| 803 | NULL((void *)0), 0, EX_NOWAIT0x0000); | |||
| 804 | } | |||
| 805 | } | |||
| 806 | ||||
| 807 | int | |||
| 808 | pci_probe_device_hook(pci_chipset_tag_t pc, struct pci_attach_args *pa) | |||
| 809 | { | |||
| 810 | #if NACPIDMAR1 > 0 | |||
| 811 | acpidmar_pci_hook(pc, pa); | |||
| 812 | #endif | |||
| 813 | return 0; | |||
| 814 | } | |||
| 815 | ||||
| 816 | #if NACPI1 > 0 | |||
| 817 | void acpi_pci_match(struct device *, struct pci_attach_args *); | |||
| 818 | pcireg_t acpi_pci_min_powerstate(pci_chipset_tag_t, pcitag_t); | |||
| 819 | void acpi_pci_set_powerstate(pci_chipset_tag_t, pcitag_t, int, int); | |||
| 820 | #endif | |||
| 821 | ||||
| 822 | void | |||
| 823 | pci_dev_postattach(struct device *dev, struct pci_attach_args *pa) | |||
| 824 | { | |||
| 825 | #if NACPI1 > 0 | |||
| 826 | acpi_pci_match(dev, pa); | |||
| 827 | #endif | |||
| 828 | } | |||
| 829 | ||||
| 830 | pcireg_t | |||
| 831 | pci_min_powerstate(pci_chipset_tag_t pc, pcitag_t tag) | |||
| 832 | { | |||
| 833 | #if NACPI1 > 0 | |||
| 834 | return acpi_pci_min_powerstate(pc, tag); | |||
| 835 | #else | |||
| 836 | return pci_get_powerstate(pc, tag); | |||
| 837 | #endif | |||
| 838 | } | |||
| 839 | ||||
| 840 | void | |||
| 841 | pci_set_powerstate_md(pci_chipset_tag_t pc, pcitag_t tag, int state, int pre) | |||
| 842 | { | |||
| 843 | #if NACPI1 > 0 | |||
| 844 | acpi_pci_set_powerstate(pc, tag, state, pre); | |||
| 845 | #endif | |||
| 846 | } |