Line data Source code
1 : /* $OpenBSD: ipmi_acpi.c,v 1.1 2018/03/14 18:52:16 patrick Exp $ */
2 : /*
3 : * Copyright (c) 2018 Patrick Wildt <patrick@blueri.se>
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/signalvar.h>
20 : #include <sys/systm.h>
21 : #include <sys/device.h>
22 : #include <sys/malloc.h>
23 :
24 : #include <machine/bus.h>
25 : #include <machine/apmvar.h>
26 :
27 : #include <dev/acpi/acpireg.h>
28 : #include <dev/acpi/acpivar.h>
29 : #include <dev/acpi/acpidev.h>
30 : #include <dev/acpi/amltypes.h>
31 : #include <dev/acpi/dsdt.h>
32 : #undef DEVNAME
33 :
34 : #include <dev/ipmivar.h>
35 :
36 : #define DEVNAME(s) ((s)->sc.sc_dev.dv_xname)
37 :
38 : int ipmi_acpi_match(struct device *, void *, void *);
39 : void ipmi_acpi_attach(struct device *, struct device *, void *);
40 : int ipmi_acpi_parse_crs(int, union acpi_resource *, void *);
41 :
42 : extern void ipmi_attach(struct device *, struct device *, void *);
43 :
44 : struct ipmi_acpi_softc {
45 : struct ipmi_softc sc;
46 :
47 : struct acpi_softc *sc_acpi;
48 : struct aml_node *sc_devnode;
49 :
50 : int sc_ift;
51 :
52 : bus_space_tag_t sc_iot;
53 : bus_size_t sc_iobase;
54 : int sc_iospacing;
55 : char sc_iotype;
56 : };
57 :
58 : struct cfattach ipmi_acpi_ca = {
59 : sizeof(struct ipmi_acpi_softc), ipmi_acpi_match, ipmi_acpi_attach,
60 : };
61 :
62 : const char *ipmi_acpi_hids[] = { ACPI_DEV_IPMI, NULL };
63 :
64 : int
65 0 : ipmi_acpi_match(struct device *parent, void *match, void *aux)
66 : {
67 0 : struct acpi_attach_args *aa = aux;
68 0 : struct cfdata *cf = match;
69 :
70 : /* sanity */
71 0 : return (acpi_matchhids(aa, ipmi_acpi_hids, cf->cf_driver->cd_name));
72 : }
73 :
74 : void
75 0 : ipmi_acpi_attach(struct device *parent, struct device *self, void *aux)
76 : {
77 0 : struct ipmi_acpi_softc *sc = (struct ipmi_acpi_softc *)self;
78 0 : struct acpi_attach_args *aa = aux;
79 0 : struct ipmi_attach_args ia;
80 0 : struct aml_value res;
81 0 : int64_t ift;
82 : int rc;
83 :
84 0 : sc->sc_acpi = (struct acpi_softc *)parent;
85 0 : sc->sc_devnode = aa->aaa_node;
86 :
87 0 : rc = aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "_IFT", 0, NULL, &ift);
88 0 : if (rc) {
89 0 : printf(": no _IFT\n");
90 0 : return;
91 : }
92 0 : sc->sc_ift = ift;
93 :
94 0 : if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CRS", 0, NULL, &res)) {
95 0 : printf(": no _CRS method\n");
96 0 : return;
97 : }
98 0 : if (res.type != AML_OBJTYPE_BUFFER) {
99 0 : printf(": invalid _CRS object (type %d len %d)\n",
100 0 : res.type, res.length);
101 0 : aml_freevalue(&res);
102 0 : return;
103 : }
104 :
105 0 : aml_parse_resource(&res, ipmi_acpi_parse_crs, sc);
106 0 : aml_freevalue(&res);
107 :
108 0 : if (sc->sc_iot == NULL) {
109 0 : printf("%s: incomplete resources (ift %d)\n",
110 0 : DEVNAME(sc), sc->sc_ift);
111 0 : return;
112 : }
113 :
114 0 : ia.iaa_iot = sc->sc_iot;
115 0 : ia.iaa_memt = sc->sc_iot;
116 0 : ia.iaa_if_type = sc->sc_ift;
117 0 : ia.iaa_if_rev = 0;
118 0 : ia.iaa_if_irq = -1;
119 0 : ia.iaa_if_irqlvl = 0;
120 0 : ia.iaa_if_iospacing = sc->sc_iospacing;
121 0 : ia.iaa_if_iobase = sc->sc_iobase;
122 0 : ia.iaa_if_iotype = sc->sc_iotype;
123 :
124 0 : ipmi_attach(parent, self, &ia);
125 0 : }
126 :
127 : int
128 0 : ipmi_acpi_parse_crs(int crsidx, union acpi_resource *crs, void *arg)
129 : {
130 0 : struct ipmi_acpi_softc *sc = arg;
131 0 : int type = AML_CRSTYPE(crs);
132 :
133 0 : switch (crsidx) {
134 : case 0:
135 0 : if (type != SR_IOPORT) {
136 0 : printf("%s: Unexpected resource #%d type %d\n",
137 0 : DEVNAME(sc), crsidx, type);
138 0 : break;
139 : }
140 0 : sc->sc_iot = sc->sc_acpi->sc_iot;
141 0 : sc->sc_iobase = crs->sr_ioport._max;
142 0 : sc->sc_iospacing = 1;
143 0 : sc->sc_iotype = 'i';
144 0 : break;
145 : case 1:
146 0 : if (type != SR_IOPORT) {
147 0 : printf("%s: Unexpected resource #%d type %d\n",
148 0 : DEVNAME(sc), crsidx, type);
149 0 : break;
150 : }
151 0 : if (crs->sr_ioport._max <= sc->sc_iobase)
152 : break;
153 0 : sc->sc_iospacing = crs->sr_ioport._max - sc->sc_iobase;
154 0 : break;
155 : default:
156 0 : printf("%s: invalid resource #%d type %d (ift %d)\n",
157 0 : DEVNAME(sc), crsidx, type, sc->sc_ift);
158 0 : }
159 :
160 0 : return 0;
161 : }
|