xref: /openbsd-src/sys/arch/amd64/pci/acpipci.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
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