1 /* $OpenBSD: acpipci.c,v 1.9 2024/10/10 05:51:23 jsg Exp $ */ 2 /* 3 * Copyright (c) 2018 Mark Kettenis 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/device.h> 20 #include <sys/extent.h> 21 #include <sys/malloc.h> 22 #include <sys/systm.h> 23 24 #include <dev/acpi/acpireg.h> 25 #include <dev/acpi/acpivar.h> 26 #include <dev/acpi/acpidev.h> 27 #include <dev/acpi/amltypes.h> 28 #include <dev/acpi/dsdt.h> 29 30 #include <dev/pci/pcidevs.h> 31 #include <dev/pci/pcireg.h> 32 #include <dev/pci/pcivar.h> 33 34 /* 33DB4D5B-1FF7-401C-9657-7441C03DD766 */ 35 #define ACPI_PCI_UUID \ 36 { 0x5b, 0x4d, 0xdb, 0x33, \ 37 0xf7, 0x1f, \ 38 0x1c, 0x40, \ 39 0x96, 0x57, \ 40 0x74, 0x41, 0xc0, 0x3d, 0xd7, 0x66 } 41 42 /* Support field. */ 43 #define ACPI_PCI_PCIE_CONFIG 0x00000001 44 #define ACPI_PCI_ASPM 0x00000002 45 #define ACPI_PCI_CPMC 0x00000004 46 #define ACPI_PCI_SEGMENTS 0x00000008 47 #define ACPI_PCI_MSI 0x00000010 48 49 /* Control field. */ 50 #define ACPI_PCI_PCIE_HOTPLUG 0x00000001 51 52 struct acpipci_softc { 53 struct device sc_dev; 54 struct acpi_softc *sc_acpi; 55 struct aml_node *sc_node; 56 57 bus_space_tag_t sc_iot; 58 bus_space_tag_t sc_memt; 59 bus_dma_tag_t sc_dmat; 60 61 struct extent *sc_busex; 62 struct extent *sc_memex; 63 struct extent *sc_ioex; 64 char sc_busex_name[32]; 65 char sc_ioex_name[32]; 66 char sc_memex_name[32]; 67 int sc_bus; 68 uint32_t sc_seg; 69 }; 70 71 int acpipci_match(struct device *, void *, void *); 72 void acpipci_attach(struct device *, struct device *, void *); 73 74 const struct cfattach acpipci_ca = { 75 sizeof(struct acpipci_softc), acpipci_match, acpipci_attach 76 }; 77 78 struct cfdriver acpipci_cd = { 79 NULL, "acpipci", DV_DULL 80 }; 81 82 const char *acpipci_hids[] = { 83 "PNP0A08", 84 "PNP0A03", 85 NULL 86 }; 87 88 int acpipci_print(void *, const char *); 89 int acpipci_parse_resources(int, union acpi_resource *, void *); 90 void acpipci_osc(struct acpipci_softc *); 91 92 int 93 acpipci_match(struct device *parent, void *match, void *aux) 94 { 95 struct acpi_attach_args *aaa = aux; 96 struct cfdata *cf = match; 97 98 return acpi_matchhids(aaa, acpipci_hids, cf->cf_driver->cd_name); 99 } 100 101 void 102 acpipci_attach(struct device *parent, struct device *self, void *aux) 103 { 104 struct acpi_attach_args *aaa = aux; 105 struct acpipci_softc *sc = (struct acpipci_softc *)self; 106 struct aml_value res; 107 uint64_t bbn = 0; 108 uint64_t seg = 0; 109 110 acpi_haspci = 1; 111 112 sc->sc_iot = aaa->aaa_iot; 113 sc->sc_memt = aaa->aaa_memt; 114 sc->sc_dmat = aaa->aaa_dmat; 115 116 sc->sc_acpi = (struct acpi_softc *)parent; 117 sc->sc_node = aaa->aaa_node; 118 printf(" %s", sc->sc_node->name); 119 120 acpipci_osc(sc); 121 122 aml_evalinteger(sc->sc_acpi, sc->sc_node, "_BBN", 0, NULL, &bbn); 123 sc->sc_bus = bbn; 124 125 aml_evalinteger(sc->sc_acpi, sc->sc_node, "_SEG", 0, NULL, &seg); 126 sc->sc_seg = seg; 127 128 if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) { 129 printf(": can't find resources\n"); 130 131 pci_init_extents(); 132 sc->sc_busex = pcibus_ex; 133 sc->sc_ioex = pciio_ex; 134 sc->sc_memex = pcimem_ex; 135 136 return; 137 } 138 139 /* Create extents for our address spaces. */ 140 snprintf(sc->sc_busex_name, sizeof(sc->sc_busex_name), 141 "%s pcibus", sc->sc_dev.dv_xname); 142 snprintf(sc->sc_ioex_name, sizeof(sc->sc_ioex_name), 143 "%s pciio", sc->sc_dev.dv_xname); 144 snprintf(sc->sc_memex_name, sizeof(sc->sc_memex_name), 145 "%s pcimem", sc->sc_dev.dv_xname); 146 sc->sc_busex = extent_create(sc->sc_busex_name, 0, 255, 147 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 148 sc->sc_ioex = extent_create(sc->sc_ioex_name, 0, 0xffffffff, 149 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 150 sc->sc_memex = extent_create(sc->sc_memex_name, 0, (u_long)-1, 151 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 152 153 aml_parse_resource(&res, acpipci_parse_resources, sc); 154 155 if (sc->sc_acpi->sc_major < 5) { 156 extent_destroy(sc->sc_ioex); 157 extent_destroy(sc->sc_memex); 158 159 pci_init_extents(); 160 sc->sc_ioex = pciio_ex; 161 sc->sc_memex = pcimem_ex; 162 } 163 164 printf("\n"); 165 166 #ifdef ACPIPCI_DEBUG 167 extent_print(sc->sc_busex); 168 extent_print(sc->sc_ioex); 169 extent_print(sc->sc_memex); 170 #endif 171 } 172 173 void 174 acpipci_attach_bus(struct device *parent, struct acpipci_softc *sc) 175 { 176 struct pcibus_attach_args pba; 177 pcitag_t tag; 178 pcireg_t id, class; 179 180 memset(&pba, 0, sizeof(pba)); 181 pba.pba_busname = "pci"; 182 pba.pba_iot = sc->sc_iot; 183 pba.pba_memt = sc->sc_memt; 184 pba.pba_dmat = sc->sc_dmat; 185 pba.pba_busex = sc->sc_busex; 186 pba.pba_ioex = sc->sc_ioex; 187 pba.pba_memex = sc->sc_memex; 188 pba.pba_pmemex = sc->sc_memex; 189 pba.pba_domain = pci_ndomains++; 190 pba.pba_bus = sc->sc_bus; 191 192 /* Enable MSI in ACPI 2.0 and above, unless we're told not to. */ 193 if (sc->sc_acpi->sc_fadt->hdr.revision >= 2 && 194 (sc->sc_acpi->sc_fadt->iapc_boot_arch & FADT_NO_MSI) == 0) 195 pba.pba_flags |= PCI_FLAGS_MSI_ENABLED; 196 197 /* Enable MSI for QEMU claiming ACPI 1.0 */ 198 tag = pci_make_tag(pba.pba_pc, sc->sc_bus, 0, 0); 199 id = pci_conf_read(pba.pba_pc, tag, PCI_SUBSYS_ID_REG); 200 if (sc->sc_acpi->sc_fadt->hdr.revision == 1 && 201 PCI_VENDOR(id) == PCI_VENDOR_QUMRANET) 202 pba.pba_flags |= PCI_FLAGS_MSI_ENABLED; 203 204 /* 205 * Don't enable MSI on chipsets from low-end manufacturers 206 * like VIA and SiS. We do this by looking at the host 207 * bridge, which should be device 0 function 0. 208 */ 209 id = pci_conf_read(pba.pba_pc, tag, PCI_ID_REG); 210 class = pci_conf_read(pba.pba_pc, tag, PCI_CLASS_REG); 211 if (PCI_CLASS(class) == PCI_CLASS_BRIDGE && 212 PCI_SUBCLASS(class) != PCI_SUBCLASS_BRIDGE_HOST && 213 PCI_VENDOR(id) != PCI_VENDOR_AMD && 214 PCI_VENDOR(id) != PCI_VENDOR_NVIDIA && 215 PCI_VENDOR(id) != PCI_VENDOR_INTEL) 216 pba.pba_flags &= ~PCI_FLAGS_MSI_ENABLED; 217 218 /* 219 * Don't enable MSI on a HyperTransport bus. In order to 220 * determine that a bus is a HyperTransport bus, we look at 221 * device 24 function 0, which is the HyperTransport 222 * host/primary interface integrated on most 64-bit AMD CPUs. 223 * If that device has a HyperTransport capability, this must 224 * be a HyperTransport bus and we disable MSI. 225 */ 226 tag = pci_make_tag(pba.pba_pc, sc->sc_bus, 24, 0); 227 if (pci_get_capability(pba.pba_pc, tag, PCI_CAP_HT, NULL, NULL)) 228 pba.pba_flags &= ~PCI_FLAGS_MSI_ENABLED; 229 230 config_found(parent, &pba, acpipci_print); 231 } 232 233 void 234 acpipci_attach_busses(struct device *parent) 235 { 236 int i; 237 238 for (i = 0; i < acpipci_cd.cd_ndevs; i++) { 239 if (acpipci_cd.cd_devs[i]) 240 acpipci_attach_bus(parent, acpipci_cd.cd_devs[i]); 241 } 242 } 243 244 int 245 acpipci_print(void *aux, const char *pnp) 246 { 247 struct pcibus_attach_args *pba = aux; 248 249 if (pnp) 250 printf("%s at %s", pba->pba_busname, pnp); 251 printf(" bus %d", pba->pba_bus); 252 return (UNCONF); 253 } 254 255 int 256 acpipci_parse_resources(int crsidx, union acpi_resource *crs, void *arg) 257 { 258 struct acpipci_softc *sc = arg; 259 int type = AML_CRSTYPE(crs); 260 int restype, tflags = 0; 261 u_long min, len = 0, tra = 0; 262 263 switch (type) { 264 case LR_WORD: 265 restype = crs->lr_word.type; 266 tflags = crs->lr_word.tflags; 267 min = crs->lr_word._min; 268 len = crs->lr_word._len; 269 tra = crs->lr_word._tra; 270 break; 271 case LR_DWORD: 272 restype = crs->lr_dword.type; 273 tflags = crs->lr_dword.tflags; 274 min = crs->lr_dword._min; 275 len = crs->lr_dword._len; 276 tra = crs->lr_dword._tra; 277 break; 278 case LR_QWORD: 279 restype = crs->lr_qword.type; 280 tflags = crs->lr_qword.tflags; 281 min = crs->lr_qword._min; 282 len = crs->lr_qword._len; 283 tra = crs->lr_qword._tra; 284 break; 285 case LR_MEM32FIXED: 286 /* 287 * Coreboot on the PC Engines apu2 incorrectly uses a 288 * Memory32Fixed resource descriptor to describe mmio 289 * address space forwarded to the PCI bus. 290 */ 291 restype = LR_TYPE_MEMORY; 292 min = crs->lr_m32fixed._bas; 293 len = crs->lr_m32fixed._len; 294 break; 295 } 296 297 if (len == 0) 298 return 0; 299 300 switch (restype) { 301 case LR_TYPE_MEMORY: 302 if (tflags & LR_MEMORY_TTP) 303 return 0; 304 extent_free(sc->sc_memex, min, len, EX_WAITOK | EX_CONFLICTOK); 305 break; 306 case LR_TYPE_IO: 307 if (tflags & LR_IO_TTP) 308 return 0; 309 extent_free(sc->sc_ioex, min, len, EX_WAITOK | EX_CONFLICTOK); 310 break; 311 case LR_TYPE_BUS: 312 extent_free(sc->sc_busex, min, len, EX_WAITOK); 313 /* 314 * Let _CRS minimum bus number override _BBN. 315 */ 316 sc->sc_bus = min; 317 break; 318 } 319 320 return 0; 321 } 322 323 void 324 acpipci_osc(struct acpipci_softc *sc) 325 { 326 struct aml_value args[4]; 327 struct aml_value res; 328 static uint8_t uuid[16] = ACPI_PCI_UUID; 329 uint32_t buf[3]; 330 331 memset(args, 0, sizeof(args)); 332 args[0].type = AML_OBJTYPE_BUFFER; 333 args[0].v_buffer = uuid; 334 args[0].length = sizeof(uuid); 335 args[1].type = AML_OBJTYPE_INTEGER; 336 args[1].v_integer = 1; 337 args[2].type = AML_OBJTYPE_INTEGER; 338 args[2].v_integer = 3; 339 args[3].type = AML_OBJTYPE_BUFFER; 340 args[3].v_buffer = (uint8_t *)buf; 341 args[3].length = sizeof(buf); 342 343 memset(buf, 0, sizeof(buf)); 344 buf[0] = 0x0; 345 buf[1] = ACPI_PCI_PCIE_CONFIG | ACPI_PCI_MSI; 346 buf[2] = ACPI_PCI_PCIE_HOTPLUG; 347 348 if (aml_evalname(sc->sc_acpi, sc->sc_node, "_OSC", 4, args, &res)) 349 return; 350 351 if (res.type == AML_OBJTYPE_BUFFER) { 352 size_t len = res.length; 353 uint32_t *p = (uint32_t *)res.v_buffer; 354 355 printf(":"); 356 while (len >= 4) { 357 printf(" 0x%08x", *p); 358 p++; 359 len -= 4; 360 } 361 } 362 } 363