1 /* $OpenBSD: acpipci.c,v 1.3 2019/09/07 13:46:19 kettenis 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 58 int acpipci_match(struct device *, void *, void *); 59 void acpipci_attach(struct device *, struct device *, void *); 60 61 struct cfattach acpipci_ca = { 62 sizeof(struct acpipci_softc), acpipci_match, acpipci_attach 63 }; 64 65 struct cfdriver acpipci_cd = { 66 NULL, "acpipci", DV_DULL 67 }; 68 69 const char *acpipci_hids[] = { 70 "PNP0A08", 71 "PNP0A03", 72 NULL 73 }; 74 75 int 76 acpipci_match(struct device *parent, void *match, void *aux) 77 { 78 struct acpi_attach_args *aaa = aux; 79 struct cfdata *cf = match; 80 81 return acpi_matchhids(aaa, acpipci_hids, cf->cf_driver->cd_name); 82 } 83 84 void 85 acpipci_attach(struct device *parent, struct device *self, void *aux) 86 { 87 struct acpi_attach_args *aaa = aux; 88 struct acpipci_softc *sc = (struct acpipci_softc *)self; 89 struct aml_value args[4]; 90 struct aml_value res; 91 static uint8_t uuid[16] = ACPI_PCI_UUID; 92 uint32_t buf[3]; 93 94 sc->sc_acpi = (struct acpi_softc *)parent; 95 sc->sc_node = aaa->aaa_node; 96 printf(" %s", sc->sc_node->name); 97 98 memset(args, 0, sizeof(args)); 99 args[0].type = AML_OBJTYPE_BUFFER; 100 args[0].v_buffer = uuid; 101 args[0].length = sizeof(uuid); 102 args[1].type = AML_OBJTYPE_INTEGER; 103 args[1].v_integer = 1; 104 args[2].type = AML_OBJTYPE_INTEGER; 105 args[2].v_integer = 3; 106 args[3].type = AML_OBJTYPE_BUFFER; 107 args[3].v_buffer = (uint8_t *)buf; 108 args[3].length = sizeof(buf); 109 110 memset(buf, 0, sizeof(buf)); 111 buf[0] = 0x0; 112 buf[1] = ACPI_PCI_PCIE_CONFIG | ACPI_PCI_MSI; 113 buf[2] = ACPI_PCI_PCIE_HOTPLUG; 114 115 if (aml_evalname(sc->sc_acpi, sc->sc_node, "_OSC", 4, args, &res)) { 116 printf(": _OSC failed\n"); 117 return; 118 } 119 120 if (res.type == AML_OBJTYPE_BUFFER) { 121 size_t len = res.length; 122 uint32_t *p = (uint32_t *)res.v_buffer; 123 124 printf(":"); 125 while (len >= 4) { 126 printf(" 0x%08x", *p); 127 p++; 128 len -= 4; 129 } 130 } 131 132 printf("\n"); 133 } 134