acpi.c revision 1.5.2.5 1 1.5.2.5 jdolecek /* $NetBSD: acpi.c,v 1.5.2.5 2002/09/06 08:43:48 jdolecek Exp $ */
2 1.5.2.2 thorpej
3 1.5.2.2 thorpej /*
4 1.5.2.2 thorpej * Copyright 2001 Wasabi Systems, Inc.
5 1.5.2.2 thorpej * All rights reserved.
6 1.5.2.2 thorpej *
7 1.5.2.2 thorpej * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 1.5.2.2 thorpej *
9 1.5.2.2 thorpej * Redistribution and use in source and binary forms, with or without
10 1.5.2.2 thorpej * modification, are permitted provided that the following conditions
11 1.5.2.2 thorpej * are met:
12 1.5.2.2 thorpej * 1. Redistributions of source code must retain the above copyright
13 1.5.2.2 thorpej * notice, this list of conditions and the following disclaimer.
14 1.5.2.2 thorpej * 2. Redistributions in binary form must reproduce the above copyright
15 1.5.2.2 thorpej * notice, this list of conditions and the following disclaimer in the
16 1.5.2.2 thorpej * documentation and/or other materials provided with the distribution.
17 1.5.2.2 thorpej * 3. All advertising materials mentioning features or use of this software
18 1.5.2.2 thorpej * must display the following acknowledgement:
19 1.5.2.2 thorpej * This product includes software developed for the NetBSD Project by
20 1.5.2.2 thorpej * Wasabi Systems, Inc.
21 1.5.2.2 thorpej * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 1.5.2.2 thorpej * or promote products derived from this software without specific prior
23 1.5.2.2 thorpej * written permission.
24 1.5.2.2 thorpej *
25 1.5.2.2 thorpej * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 1.5.2.2 thorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 1.5.2.2 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 1.5.2.2 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 1.5.2.2 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 1.5.2.2 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 1.5.2.2 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 1.5.2.2 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 1.5.2.2 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 1.5.2.2 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 1.5.2.2 thorpej * POSSIBILITY OF SUCH DAMAGE.
36 1.5.2.2 thorpej */
37 1.5.2.2 thorpej
38 1.5.2.2 thorpej /*
39 1.5.2.2 thorpej * Autoconfiguration support for the Intel ACPI Component Architecture
40 1.5.2.2 thorpej * ACPI reference implementation.
41 1.5.2.2 thorpej */
42 1.5.2.2 thorpej
43 1.5.2.2 thorpej #include <sys/cdefs.h>
44 1.5.2.5 jdolecek __KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.5.2.5 2002/09/06 08:43:48 jdolecek Exp $");
45 1.5.2.2 thorpej
46 1.5.2.2 thorpej #include <sys/param.h>
47 1.5.2.2 thorpej #include <sys/systm.h>
48 1.5.2.2 thorpej #include <sys/device.h>
49 1.5.2.2 thorpej #include <sys/malloc.h>
50 1.5.2.2 thorpej
51 1.5.2.2 thorpej #include <dev/acpi/acpica.h>
52 1.5.2.2 thorpej #include <dev/acpi/acpireg.h>
53 1.5.2.2 thorpej #include <dev/acpi/acpivar.h>
54 1.5.2.2 thorpej #include <dev/acpi/acpi_osd.h>
55 1.5.2.2 thorpej
56 1.5.2.5 jdolecek #ifndef ACPI_PCI_FIXUP
57 1.5.2.5 jdolecek #define ACPI_PCI_FIXUP 1
58 1.5.2.5 jdolecek #endif
59 1.5.2.5 jdolecek
60 1.5.2.5 jdolecek #ifndef ACPI_ACTIVATE_DEV
61 1.5.2.5 jdolecek #define ACPI_ACTIVATE_DEV 0
62 1.5.2.5 jdolecek #endif
63 1.5.2.5 jdolecek
64 1.5.2.5 jdolecek #if ACPI_PCI_FIXUP
65 1.5.2.5 jdolecek #include <dev/acpi/acpica/Subsystem/acnamesp.h> /* AcpiNsGetNodeByPath() */
66 1.5.2.5 jdolecek #include <dev/pci/pcidevs.h>
67 1.5.2.5 jdolecek #endif
68 1.5.2.5 jdolecek
69 1.5.2.5 jdolecek #include <machine/acpi_machdep.h>
70 1.5.2.5 jdolecek
71 1.5.2.2 thorpej #ifdef ENABLE_DEBUGGER
72 1.5.2.2 thorpej #define ACPI_DBGR_INIT 0x01
73 1.5.2.2 thorpej #define ACPI_DBGR_TABLES 0x02
74 1.5.2.2 thorpej #define ACPI_DBGR_ENABLE 0x04
75 1.5.2.2 thorpej #define ACPI_DBGR_PROBE 0x08
76 1.5.2.2 thorpej #define ACPI_DBGR_RUNNING 0x10
77 1.5.2.2 thorpej
78 1.5.2.2 thorpej int acpi_dbgr = 0x00;
79 1.5.2.2 thorpej #endif
80 1.5.2.2 thorpej
81 1.5.2.2 thorpej int acpi_match(struct device *, struct cfdata *, void *);
82 1.5.2.2 thorpej void acpi_attach(struct device *, struct device *, void *);
83 1.5.2.2 thorpej
84 1.5.2.2 thorpej int acpi_print(void *aux, const char *);
85 1.5.2.2 thorpej
86 1.5.2.2 thorpej extern struct cfdriver acpi_cd;
87 1.5.2.2 thorpej
88 1.5.2.2 thorpej struct cfattach acpi_ca = {
89 1.5.2.2 thorpej sizeof(struct acpi_softc), acpi_match, acpi_attach,
90 1.5.2.2 thorpej };
91 1.5.2.2 thorpej
92 1.5.2.2 thorpej /*
93 1.5.2.2 thorpej * This is a flag we set when the ACPI subsystem is active. Machine
94 1.5.2.2 thorpej * dependent code may wish to skip other steps (such as attaching
95 1.5.2.2 thorpej * subsystems that ACPI supercedes) when ACPI is active.
96 1.5.2.2 thorpej */
97 1.5.2.2 thorpej int acpi_active;
98 1.5.2.2 thorpej
99 1.5.2.2 thorpej /*
100 1.5.2.2 thorpej * Pointer to the ACPI subsystem's state. There can be only
101 1.5.2.2 thorpej * one ACPI instance.
102 1.5.2.2 thorpej */
103 1.5.2.2 thorpej struct acpi_softc *acpi_softc;
104 1.5.2.2 thorpej
105 1.5.2.2 thorpej void acpi_shutdown(void *);
106 1.5.2.2 thorpej ACPI_STATUS acpi_disable(struct acpi_softc *sc);
107 1.5.2.2 thorpej void acpi_build_tree(struct acpi_softc *);
108 1.5.2.2 thorpej ACPI_STATUS acpi_make_devnode(ACPI_HANDLE, UINT32, void *, void **);
109 1.5.2.2 thorpej
110 1.5.2.2 thorpej void acpi_enable_fixed_events(struct acpi_softc *);
111 1.5.2.5 jdolecek #if ACPI_PCI_FIXUP
112 1.5.2.5 jdolecek void acpi_pci_fixup(struct acpi_softc *);
113 1.5.2.5 jdolecek #endif
114 1.5.2.5 jdolecek #if ACPI_PCI_FIXUP || ACPI_ACTIVATE_DEV
115 1.5.2.5 jdolecek ACPI_STATUS acpi_allocate_resources(ACPI_HANDLE handle);
116 1.5.2.5 jdolecek #endif
117 1.5.2.2 thorpej
118 1.5.2.2 thorpej /*
119 1.5.2.2 thorpej * acpi_probe:
120 1.5.2.2 thorpej *
121 1.5.2.2 thorpej * Probe for ACPI support. This is called by the
122 1.5.2.2 thorpej * machine-dependent ACPI front-end. All of the
123 1.5.2.2 thorpej * actual work is done by ACPICA.
124 1.5.2.2 thorpej *
125 1.5.2.2 thorpej * NOTE: This is not an autoconfiguration interface function.
126 1.5.2.2 thorpej */
127 1.5.2.2 thorpej int
128 1.5.2.2 thorpej acpi_probe(void)
129 1.5.2.2 thorpej {
130 1.5.2.2 thorpej static int beenhere;
131 1.5.2.2 thorpej ACPI_STATUS rv;
132 1.5.2.2 thorpej
133 1.5.2.2 thorpej if (beenhere != 0)
134 1.5.2.2 thorpej panic("acpi_probe: ACPI has already been probed");
135 1.5.2.2 thorpej beenhere = 1;
136 1.5.2.2 thorpej
137 1.5.2.2 thorpej /*
138 1.5.2.2 thorpej * Start up ACPICA.
139 1.5.2.2 thorpej */
140 1.5.2.2 thorpej #ifdef ENABLE_DEBUGGER
141 1.5.2.2 thorpej if (acpi_dbgr & ACPI_DBGR_INIT)
142 1.5.2.2 thorpej acpi_osd_debugger();
143 1.5.2.2 thorpej #endif
144 1.5.2.2 thorpej
145 1.5.2.2 thorpej rv = AcpiInitializeSubsystem();
146 1.5.2.2 thorpej if (rv != AE_OK) {
147 1.5.2.2 thorpej printf("ACPI: unable to initialize ACPICA: %d\n", rv);
148 1.5.2.2 thorpej return (0);
149 1.5.2.2 thorpej }
150 1.5.2.2 thorpej
151 1.5.2.2 thorpej #ifdef ENABLE_DEBUGGER
152 1.5.2.2 thorpej if (acpi_dbgr & ACPI_DBGR_TABLES)
153 1.5.2.2 thorpej acpi_osd_debugger();
154 1.5.2.2 thorpej #endif
155 1.5.2.2 thorpej
156 1.5.2.2 thorpej rv = AcpiLoadTables();
157 1.5.2.2 thorpej if (rv != AE_OK) {
158 1.5.2.2 thorpej printf("ACPI: unable to load tables: %d\n", rv);
159 1.5.2.2 thorpej return (0);
160 1.5.2.2 thorpej }
161 1.5.2.2 thorpej
162 1.5.2.2 thorpej /*
163 1.5.2.2 thorpej * Looks like we have ACPI!
164 1.5.2.2 thorpej */
165 1.5.2.2 thorpej
166 1.5.2.2 thorpej return (1);
167 1.5.2.2 thorpej }
168 1.5.2.2 thorpej
169 1.5.2.2 thorpej /*
170 1.5.2.2 thorpej * acpi_match:
171 1.5.2.2 thorpej *
172 1.5.2.2 thorpej * Autoconfiguration `match' routine.
173 1.5.2.2 thorpej */
174 1.5.2.2 thorpej int
175 1.5.2.2 thorpej acpi_match(struct device *parent, struct cfdata *match, void *aux)
176 1.5.2.2 thorpej {
177 1.5.2.2 thorpej struct acpibus_attach_args *aa = aux;
178 1.5.2.2 thorpej
179 1.5.2.2 thorpej if (strcmp(aa->aa_busname, acpi_cd.cd_name) != 0)
180 1.5.2.2 thorpej return (0);
181 1.5.2.2 thorpej
182 1.5.2.2 thorpej /*
183 1.5.2.2 thorpej * XXX Check other locators? Hard to know -- machine
184 1.5.2.2 thorpej * dependent code has already checked for the presence
185 1.5.2.2 thorpej * of ACPI by calling acpi_probe(), so I suppose we
186 1.5.2.2 thorpej * don't really have to do anything else.
187 1.5.2.2 thorpej */
188 1.5.2.2 thorpej return (1);
189 1.5.2.2 thorpej }
190 1.5.2.2 thorpej
191 1.5.2.2 thorpej /*
192 1.5.2.2 thorpej * acpi_attach:
193 1.5.2.2 thorpej *
194 1.5.2.2 thorpej * Autoconfiguration `attach' routine. Finish initializing
195 1.5.2.2 thorpej * ACPICA (some initialization was done in acpi_probe(),
196 1.5.2.2 thorpej * which was required to check for the presence of ACPI),
197 1.5.2.2 thorpej * and enable the ACPI subsystem.
198 1.5.2.2 thorpej */
199 1.5.2.2 thorpej void
200 1.5.2.2 thorpej acpi_attach(struct device *parent, struct device *self, void *aux)
201 1.5.2.2 thorpej {
202 1.5.2.2 thorpej struct acpi_softc *sc = (void *) self;
203 1.5.2.2 thorpej struct acpibus_attach_args *aa = aux;
204 1.5.2.2 thorpej ACPI_STATUS rv;
205 1.5.2.2 thorpej
206 1.5.2.2 thorpej printf("\n");
207 1.5.2.2 thorpej
208 1.5.2.2 thorpej if (acpi_softc != NULL)
209 1.5.2.2 thorpej panic("acpi_attach: ACPI has already been attached");
210 1.5.2.2 thorpej
211 1.5.2.2 thorpej sc->sc_iot = aa->aa_iot;
212 1.5.2.2 thorpej sc->sc_memt = aa->aa_memt;
213 1.5.2.2 thorpej sc->sc_pc = aa->aa_pc;
214 1.5.2.2 thorpej sc->sc_pciflags = aa->aa_pciflags;
215 1.5.2.2 thorpej
216 1.5.2.2 thorpej acpi_softc = sc;
217 1.5.2.2 thorpej
218 1.5.2.2 thorpej /*
219 1.5.2.2 thorpej * Install the default address space handlers.
220 1.5.2.2 thorpej */
221 1.5.2.2 thorpej
222 1.5.2.2 thorpej rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
223 1.5.2.2 thorpej ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL);
224 1.5.2.2 thorpej if (rv != AE_OK) {
225 1.5.2.2 thorpej printf("%s: unable to install SYSTEM MEMORY handler: %d\n",
226 1.5.2.2 thorpej sc->sc_dev.dv_xname, rv);
227 1.5.2.2 thorpej return;
228 1.5.2.2 thorpej }
229 1.5.2.2 thorpej
230 1.5.2.2 thorpej rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
231 1.5.2.2 thorpej ACPI_ADR_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL);
232 1.5.2.2 thorpej if (rv != AE_OK) {
233 1.5.2.2 thorpej printf("%s: unable to install SYSTEM IO handler: %d\n",
234 1.5.2.2 thorpej sc->sc_dev.dv_xname, rv);
235 1.5.2.2 thorpej return;
236 1.5.2.2 thorpej }
237 1.5.2.2 thorpej
238 1.5.2.2 thorpej rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
239 1.5.2.2 thorpej ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
240 1.5.2.2 thorpej if (rv != AE_OK) {
241 1.5.2.2 thorpej printf("%s: unable to install PCI CONFIG handler: %d\n",
242 1.5.2.2 thorpej sc->sc_dev.dv_xname, rv);
243 1.5.2.2 thorpej return;
244 1.5.2.2 thorpej }
245 1.5.2.2 thorpej
246 1.5.2.2 thorpej /*
247 1.5.2.2 thorpej * Bring ACPI on-line.
248 1.5.2.2 thorpej *
249 1.5.2.2 thorpej * Note that we request that _STA (device init) and _INI (object init)
250 1.5.2.2 thorpej * methods not be run.
251 1.5.2.2 thorpej *
252 1.5.2.2 thorpej * XXX We need to arrange for the object init pass after we have
253 1.5.2.2 thorpej * XXX attached all of our children.
254 1.5.2.2 thorpej */
255 1.5.2.2 thorpej #ifdef ENABLE_DEBUGGER
256 1.5.2.2 thorpej if (acpi_dbgr & ACPI_DBGR_ENABLE)
257 1.5.2.2 thorpej acpi_osd_debugger();
258 1.5.2.2 thorpej #endif
259 1.5.2.2 thorpej rv = AcpiEnableSubsystem(ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT);
260 1.5.2.2 thorpej if (rv != AE_OK) {
261 1.5.2.2 thorpej printf("%s: unable to enable ACPI: %d\n",
262 1.5.2.2 thorpej sc->sc_dev.dv_xname, rv);
263 1.5.2.2 thorpej return;
264 1.5.2.2 thorpej }
265 1.5.2.2 thorpej acpi_active = 1;
266 1.5.2.2 thorpej
267 1.5.2.2 thorpej /*
268 1.5.2.2 thorpej * Set up the default sleep state to enter when various
269 1.5.2.2 thorpej * switches are activated.
270 1.5.2.2 thorpej */
271 1.5.2.2 thorpej sc->sc_switch_sleep[ACPI_SWITCH_POWERBUTTON] = ACPI_STATE_S5;
272 1.5.2.2 thorpej sc->sc_switch_sleep[ACPI_SWITCH_SLEEPBUTTON] = ACPI_STATE_S1;
273 1.5.2.2 thorpej sc->sc_switch_sleep[ACPI_SWITCH_LID] = ACPI_STATE_S1;
274 1.5.2.2 thorpej
275 1.5.2.2 thorpej /* Our current state is "awake". */
276 1.5.2.2 thorpej sc->sc_sleepstate = ACPI_STATE_S0;
277 1.5.2.2 thorpej
278 1.5.2.5 jdolecek /* Show SCI interrupt. */
279 1.5.2.5 jdolecek if (AcpiGbl_FADT != NULL)
280 1.5.2.5 jdolecek printf("%s: SCI interrupting at irq %d\n",
281 1.5.2.5 jdolecek sc->sc_dev.dv_xname, AcpiGbl_FADT->SciInt);
282 1.5.2.2 thorpej /*
283 1.5.2.2 thorpej * Check for fixed-hardware features.
284 1.5.2.2 thorpej */
285 1.5.2.2 thorpej acpi_enable_fixed_events(sc);
286 1.5.2.2 thorpej
287 1.5.2.2 thorpej /*
288 1.5.2.5 jdolecek * Fix up PCI devices.
289 1.5.2.5 jdolecek */
290 1.5.2.5 jdolecek #if ACPI_PCI_FIXUP
291 1.5.2.5 jdolecek acpi_pci_fixup(sc);
292 1.5.2.5 jdolecek #endif
293 1.5.2.5 jdolecek
294 1.5.2.5 jdolecek /*
295 1.5.2.2 thorpej * Scan the namespace and build our device tree.
296 1.5.2.2 thorpej */
297 1.5.2.2 thorpej #ifdef ENABLE_DEBUGGER
298 1.5.2.2 thorpej if (acpi_dbgr & ACPI_DBGR_PROBE)
299 1.5.2.2 thorpej acpi_osd_debugger();
300 1.5.2.2 thorpej #endif
301 1.5.2.2 thorpej acpi_build_tree(sc);
302 1.5.2.2 thorpej
303 1.5.2.2 thorpej /*
304 1.5.2.2 thorpej * Register a shutdown hook that disables certain ACPI
305 1.5.2.2 thorpej * events that might happen and confuse us while we're
306 1.5.2.2 thorpej * trying to shut down.
307 1.5.2.2 thorpej */
308 1.5.2.2 thorpej sc->sc_sdhook = shutdownhook_establish(acpi_shutdown, sc);
309 1.5.2.2 thorpej if (sc->sc_sdhook == NULL)
310 1.5.2.2 thorpej printf("%s: WARNING: unable to register shutdown hook\n",
311 1.5.2.2 thorpej sc->sc_dev.dv_xname);
312 1.5.2.2 thorpej
313 1.5.2.2 thorpej #ifdef ENABLE_DEBUGGER
314 1.5.2.2 thorpej if (acpi_dbgr & ACPI_DBGR_RUNNING)
315 1.5.2.2 thorpej acpi_osd_debugger();
316 1.5.2.2 thorpej #endif
317 1.5.2.2 thorpej }
318 1.5.2.2 thorpej
319 1.5.2.2 thorpej /*
320 1.5.2.2 thorpej * acpi_shutdown:
321 1.5.2.2 thorpej *
322 1.5.2.2 thorpej * Shutdown hook for ACPI -- disable some events that
323 1.5.2.2 thorpej * might confuse us.
324 1.5.2.2 thorpej */
325 1.5.2.2 thorpej void
326 1.5.2.2 thorpej acpi_shutdown(void *arg)
327 1.5.2.2 thorpej {
328 1.5.2.2 thorpej struct acpi_softc *sc = arg;
329 1.5.2.2 thorpej
330 1.5.2.2 thorpej if (acpi_disable(sc) != AE_OK)
331 1.5.2.2 thorpej printf("%s: WARNING: unable to disable ACPI\n",
332 1.5.2.2 thorpej sc->sc_dev.dv_xname);
333 1.5.2.2 thorpej }
334 1.5.2.2 thorpej
335 1.5.2.2 thorpej /*
336 1.5.2.2 thorpej * acpi_disable:
337 1.5.2.2 thorpej *
338 1.5.2.2 thorpej * Disable ACPI.
339 1.5.2.2 thorpej */
340 1.5.2.2 thorpej ACPI_STATUS
341 1.5.2.2 thorpej acpi_disable(struct acpi_softc *sc)
342 1.5.2.2 thorpej {
343 1.5.2.2 thorpej ACPI_STATUS rv = AE_OK;
344 1.5.2.2 thorpej
345 1.5.2.2 thorpej if (acpi_active) {
346 1.5.2.2 thorpej rv = AcpiDisable();
347 1.5.2.2 thorpej if (rv == AE_OK)
348 1.5.2.2 thorpej acpi_active = 0;
349 1.5.2.2 thorpej }
350 1.5.2.2 thorpej return (rv);
351 1.5.2.2 thorpej }
352 1.5.2.2 thorpej
353 1.5.2.2 thorpej struct acpi_make_devnode_state {
354 1.5.2.2 thorpej struct acpi_softc *softc;
355 1.5.2.2 thorpej struct acpi_scope *scope;
356 1.5.2.2 thorpej };
357 1.5.2.2 thorpej
358 1.5.2.2 thorpej /*
359 1.5.2.2 thorpej * acpi_build_tree:
360 1.5.2.2 thorpej *
361 1.5.2.2 thorpej * Scan relevant portions of the ACPI namespace and attach
362 1.5.2.2 thorpej * child devices.
363 1.5.2.2 thorpej */
364 1.5.2.2 thorpej void
365 1.5.2.2 thorpej acpi_build_tree(struct acpi_softc *sc)
366 1.5.2.2 thorpej {
367 1.5.2.2 thorpej static const char *scopes[] = {
368 1.5.2.2 thorpej "\\_PR_", /* ACPI 1.0 processor namespace */
369 1.5.2.2 thorpej "\\_SB_", /* system bus namespace */
370 1.5.2.2 thorpej "\\_SI_", /* system idicator namespace */
371 1.5.2.2 thorpej "\\_TZ_", /* ACPI 1.0 thermal zone namespace */
372 1.5.2.2 thorpej NULL,
373 1.5.2.2 thorpej };
374 1.5.2.2 thorpej struct acpi_attach_args aa;
375 1.5.2.2 thorpej struct acpi_make_devnode_state state;
376 1.5.2.2 thorpej struct acpi_scope *as;
377 1.5.2.2 thorpej struct acpi_devnode *ad;
378 1.5.2.2 thorpej ACPI_HANDLE parent;
379 1.5.2.2 thorpej int i;
380 1.5.2.2 thorpej
381 1.5.2.2 thorpej TAILQ_INIT(&sc->sc_scopes);
382 1.5.2.2 thorpej
383 1.5.2.2 thorpej state.softc = sc;
384 1.5.2.2 thorpej
385 1.5.2.2 thorpej /*
386 1.5.2.2 thorpej * Scan the namespace and build our tree.
387 1.5.2.2 thorpej */
388 1.5.2.2 thorpej for (i = 0; scopes[i] != NULL; i++) {
389 1.5.2.2 thorpej as = malloc(sizeof(*as), M_DEVBUF, M_WAITOK);
390 1.5.2.2 thorpej as->as_name = scopes[i];
391 1.5.2.2 thorpej TAILQ_INIT(&as->as_devnodes);
392 1.5.2.2 thorpej
393 1.5.2.2 thorpej TAILQ_INSERT_TAIL(&sc->sc_scopes, as, as_list);
394 1.5.2.2 thorpej
395 1.5.2.2 thorpej state.scope = as;
396 1.5.2.2 thorpej
397 1.5.2.2 thorpej if (AcpiGetHandle(ACPI_ROOT_OBJECT, (char *) scopes[i],
398 1.5.2.2 thorpej &parent) == AE_OK) {
399 1.5.2.2 thorpej AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100,
400 1.5.2.2 thorpej acpi_make_devnode, &state, NULL);
401 1.5.2.2 thorpej }
402 1.5.2.2 thorpej
403 1.5.2.2 thorpej /* Now, for this namespace, try and attach the devices. */
404 1.5.2.2 thorpej TAILQ_FOREACH(ad, &as->as_devnodes, ad_list) {
405 1.5.2.2 thorpej aa.aa_node = ad;
406 1.5.2.2 thorpej aa.aa_iot = sc->sc_iot;
407 1.5.2.2 thorpej aa.aa_memt = sc->sc_memt;
408 1.5.2.2 thorpej aa.aa_pc = sc->sc_pc;
409 1.5.2.2 thorpej aa.aa_pciflags = sc->sc_pciflags;
410 1.5.2.2 thorpej
411 1.5.2.2 thorpej /*
412 1.5.2.2 thorpej * XXX We only attach devices which are:
413 1.5.2.2 thorpej *
414 1.5.2.2 thorpej * - present
415 1.5.2.2 thorpej * - enabled
416 1.5.2.2 thorpej * - functioning properly
417 1.5.2.2 thorpej *
418 1.5.2.2 thorpej * However, if enabled, it's decoding resources,
419 1.5.2.2 thorpej * so we should claim them, if possible. Requires
420 1.5.2.2 thorpej * changes to bus_space(9).
421 1.5.2.2 thorpej */
422 1.5.2.2 thorpej if ((ad->ad_devinfo.CurrentStatus &
423 1.5.2.2 thorpej (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
424 1.5.2.5 jdolecek ACPI_STA_DEV_OK)) !=
425 1.5.2.2 thorpej (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
426 1.5.2.5 jdolecek ACPI_STA_DEV_OK))
427 1.5.2.2 thorpej continue;
428 1.5.2.2 thorpej
429 1.5.2.2 thorpej /*
430 1.5.2.2 thorpej * XXX Same problem as above...
431 1.5.2.2 thorpej */
432 1.5.2.2 thorpej if ((ad->ad_devinfo.Valid & ACPI_VALID_HID) == 0)
433 1.5.2.2 thorpej continue;
434 1.5.2.2 thorpej
435 1.5.2.2 thorpej ad->ad_device = config_found(&sc->sc_dev,
436 1.5.2.2 thorpej &aa, acpi_print);
437 1.5.2.2 thorpej }
438 1.5.2.2 thorpej }
439 1.5.2.2 thorpej }
440 1.5.2.2 thorpej
441 1.5.2.5 jdolecek #if ACPI_ACTIVATE_DEV
442 1.5.2.5 jdolecek static void
443 1.5.2.5 jdolecek acpi_activate_device(ACPI_HANDLE handle, ACPI_DEVICE_INFO *di)
444 1.5.2.5 jdolecek {
445 1.5.2.5 jdolecek ACPI_STATUS rv;
446 1.5.2.5 jdolecek
447 1.5.2.5 jdolecek #ifdef ACPI_DEBUG
448 1.5.2.5 jdolecek printf("acpi_activate_device: %s, old status=%x\n",
449 1.5.2.5 jdolecek di->HardwareId, di->CurrentStatus);
450 1.5.2.5 jdolecek #endif
451 1.5.2.5 jdolecek
452 1.5.2.5 jdolecek rv = acpi_allocate_resources(handle);
453 1.5.2.5 jdolecek if (ACPI_FAILURE(rv)) {
454 1.5.2.5 jdolecek printf("acpi: activate failed for %s\n", di->HardwareId);
455 1.5.2.5 jdolecek }
456 1.5.2.5 jdolecek
457 1.5.2.5 jdolecek (void)AcpiGetObjectInfo(handle, di);
458 1.5.2.5 jdolecek #ifdef ACPI_DEBUG
459 1.5.2.5 jdolecek printf("acpi_activate_device: %s, new status=%x\n",
460 1.5.2.5 jdolecek di->HardwareId, di->CurrentStatus);
461 1.5.2.5 jdolecek #endif
462 1.5.2.5 jdolecek }
463 1.5.2.5 jdolecek #endif /* ACPI_ACTIVATE_DEV */
464 1.5.2.5 jdolecek
465 1.5.2.2 thorpej /*
466 1.5.2.2 thorpej * acpi_make_devnode:
467 1.5.2.2 thorpej *
468 1.5.2.2 thorpej * Make an ACPI devnode.
469 1.5.2.2 thorpej */
470 1.5.2.2 thorpej ACPI_STATUS
471 1.5.2.2 thorpej acpi_make_devnode(ACPI_HANDLE handle, UINT32 level, void *context,
472 1.5.2.2 thorpej void **status)
473 1.5.2.2 thorpej {
474 1.5.2.2 thorpej struct acpi_make_devnode_state *state = context;
475 1.5.2.2 thorpej #ifdef ACPI_DEBUG
476 1.5.2.2 thorpej struct acpi_softc *sc = state->softc;
477 1.5.2.2 thorpej #endif
478 1.5.2.2 thorpej struct acpi_scope *as = state->scope;
479 1.5.2.2 thorpej struct acpi_devnode *ad;
480 1.5.2.5 jdolecek ACPI_DEVICE_INFO devinfo;
481 1.5.2.2 thorpej ACPI_OBJECT_TYPE type;
482 1.5.2.2 thorpej ACPI_STATUS rv;
483 1.5.2.2 thorpej
484 1.5.2.2 thorpej if (AcpiGetType(handle, &type) == AE_OK) {
485 1.5.2.5 jdolecek rv = AcpiGetObjectInfo(handle, &devinfo);
486 1.5.2.5 jdolecek if (rv != AE_OK) {
487 1.5.2.5 jdolecek #ifdef ACPI_DEBUG
488 1.5.2.5 jdolecek printf("%s: AcpiGetObjectInfo failed\n",
489 1.5.2.5 jdolecek sc->sc_dev.dv_xname);
490 1.5.2.5 jdolecek #endif
491 1.5.2.5 jdolecek goto out; /* XXX why return OK */
492 1.5.2.5 jdolecek }
493 1.5.2.5 jdolecek
494 1.5.2.2 thorpej switch (type) {
495 1.5.2.2 thorpej case ACPI_TYPE_DEVICE:
496 1.5.2.5 jdolecek #if ACPI_ACTIVATE_DEV
497 1.5.2.5 jdolecek if ((devinfo.Valid & ACPI_VALID_STA) &&
498 1.5.2.5 jdolecek (devinfo.CurrentStatus &
499 1.5.2.5 jdolecek (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED)) ==
500 1.5.2.5 jdolecek ACPI_STA_DEV_PRESENT)
501 1.5.2.5 jdolecek acpi_activate_device(handle, &devinfo);
502 1.5.2.5 jdolecek /* FALLTHROUGH */
503 1.5.2.5 jdolecek #endif
504 1.5.2.5 jdolecek
505 1.5.2.2 thorpej case ACPI_TYPE_PROCESSOR:
506 1.5.2.2 thorpej case ACPI_TYPE_THERMAL:
507 1.5.2.2 thorpej case ACPI_TYPE_POWER:
508 1.5.2.3 jdolecek ad = malloc(sizeof(*ad), M_DEVBUF, M_NOWAIT|M_ZERO);
509 1.5.2.2 thorpej if (ad == NULL)
510 1.5.2.2 thorpej return (AE_NO_MEMORY);
511 1.5.2.2 thorpej
512 1.5.2.2 thorpej ad->ad_handle = handle;
513 1.5.2.2 thorpej ad->ad_level = level;
514 1.5.2.2 thorpej ad->ad_scope = as;
515 1.5.2.2 thorpej ad->ad_type = type;
516 1.5.2.2 thorpej
517 1.5.2.2 thorpej TAILQ_INSERT_TAIL(&as->as_devnodes, ad, ad_list);
518 1.5.2.2 thorpej
519 1.5.2.2 thorpej rv = AcpiGetObjectInfo(handle, &ad->ad_devinfo);
520 1.5.2.2 thorpej if (rv != AE_OK)
521 1.5.2.2 thorpej goto out;
522 1.5.2.2 thorpej
523 1.5.2.2 thorpej if ((ad->ad_devinfo.Valid & ACPI_VALID_HID) == 0)
524 1.5.2.2 thorpej goto out;
525 1.5.2.2 thorpej
526 1.5.2.5 jdolecek #ifdef ACPI_EXTRA_DEBUG
527 1.5.2.2 thorpej printf("%s: HID %s found in scope %s level %d\n",
528 1.5.2.2 thorpej sc->sc_dev.dv_xname, ad->ad_devinfo.HardwareId,
529 1.5.2.2 thorpej as->as_name, ad->ad_level);
530 1.5.2.2 thorpej if (ad->ad_devinfo.Valid & ACPI_VALID_UID)
531 1.5.2.2 thorpej printf(" UID %s\n",
532 1.5.2.2 thorpej ad->ad_devinfo.UniqueId);
533 1.5.2.2 thorpej if (ad->ad_devinfo.Valid & ACPI_VALID_ADR)
534 1.5.2.2 thorpej printf(" ADR 0x%016qx\n",
535 1.5.2.2 thorpej ad->ad_devinfo.Address);
536 1.5.2.2 thorpej if (ad->ad_devinfo.Valid & ACPI_VALID_STA)
537 1.5.2.2 thorpej printf(" STA 0x%08x\n",
538 1.5.2.2 thorpej ad->ad_devinfo.CurrentStatus);
539 1.5.2.2 thorpej #endif
540 1.5.2.2 thorpej }
541 1.5.2.2 thorpej }
542 1.5.2.2 thorpej out:
543 1.5.2.2 thorpej return (AE_OK);
544 1.5.2.2 thorpej }
545 1.5.2.2 thorpej
546 1.5.2.2 thorpej /*
547 1.5.2.2 thorpej * acpi_print:
548 1.5.2.2 thorpej *
549 1.5.2.2 thorpej * Autoconfiguration print routine.
550 1.5.2.2 thorpej */
551 1.5.2.2 thorpej int
552 1.5.2.2 thorpej acpi_print(void *aux, const char *pnp)
553 1.5.2.2 thorpej {
554 1.5.2.2 thorpej struct acpi_attach_args *aa = aux;
555 1.5.2.4 jdolecek #if 0
556 1.5.2.2 thorpej char *str;
557 1.5.2.4 jdolecek #endif
558 1.5.2.2 thorpej
559 1.5.2.2 thorpej if (pnp) {
560 1.5.2.2 thorpej printf("%s ", aa->aa_node->ad_devinfo.HardwareId);
561 1.5.2.4 jdolecek #if 0 /* Not until we fix acpi_eval_string */
562 1.5.2.2 thorpej if (acpi_eval_string(aa->aa_node->ad_handle,
563 1.5.2.2 thorpej "_STR", &str) == AE_OK) {
564 1.5.2.2 thorpej printf("[%s] ", str);
565 1.5.2.2 thorpej AcpiOsFree(str);
566 1.5.2.2 thorpej }
567 1.5.2.4 jdolecek #endif
568 1.5.2.2 thorpej printf("at %s", pnp);
569 1.5.2.2 thorpej }
570 1.5.2.2 thorpej
571 1.5.2.2 thorpej return (UNCONF);
572 1.5.2.2 thorpej }
573 1.5.2.2 thorpej
574 1.5.2.2 thorpej /*****************************************************************************
575 1.5.2.2 thorpej * ACPI fixed-hardware feature handlers
576 1.5.2.2 thorpej *****************************************************************************/
577 1.5.2.2 thorpej
578 1.5.2.2 thorpej UINT32 acpi_fixed_power_button_handler(void *);
579 1.5.2.2 thorpej UINT32 acpi_fixed_sleep_button_handler(void *);
580 1.5.2.2 thorpej
581 1.5.2.2 thorpej /*
582 1.5.2.2 thorpej * acpi_enable_fixed_events:
583 1.5.2.2 thorpej *
584 1.5.2.2 thorpej * Enable any fixed-hardware feature handlers.
585 1.5.2.2 thorpej */
586 1.5.2.2 thorpej void
587 1.5.2.2 thorpej acpi_enable_fixed_events(struct acpi_softc *sc)
588 1.5.2.2 thorpej {
589 1.5.2.2 thorpej static int beenhere;
590 1.5.2.2 thorpej ACPI_STATUS rv;
591 1.5.2.2 thorpej
592 1.5.2.2 thorpej /*
593 1.5.2.2 thorpej * Check for fixed-hardware buttons.
594 1.5.2.2 thorpej */
595 1.5.2.2 thorpej
596 1.5.2.2 thorpej if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->PwrButton == 0) {
597 1.5.2.2 thorpej if (beenhere == 0)
598 1.5.2.2 thorpej printf("%s: fixed-feature power button present\n",
599 1.5.2.2 thorpej sc->sc_dev.dv_xname);
600 1.5.2.2 thorpej rv = AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON,
601 1.5.2.2 thorpej acpi_fixed_power_button_handler, sc);
602 1.5.2.2 thorpej if (rv != AE_OK)
603 1.5.2.2 thorpej printf("%s: unable to install handler for fixed "
604 1.5.2.2 thorpej "power button: %d\n", sc->sc_dev.dv_xname, rv);
605 1.5.2.2 thorpej }
606 1.5.2.2 thorpej
607 1.5.2.2 thorpej if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->SleepButton == 0) {
608 1.5.2.2 thorpej if (beenhere == 0)
609 1.5.2.2 thorpej printf("%s: fixed-feature sleep button present\n",
610 1.5.2.2 thorpej sc->sc_dev.dv_xname);
611 1.5.2.2 thorpej rv = AcpiInstallFixedEventHandler(ACPI_EVENT_SLEEP_BUTTON,
612 1.5.2.2 thorpej acpi_fixed_sleep_button_handler, sc);
613 1.5.2.2 thorpej if (rv != AE_OK)
614 1.5.2.2 thorpej printf("%s: unable to install handler for fixed "
615 1.5.2.2 thorpej "power button: %d\n", sc->sc_dev.dv_xname, rv);
616 1.5.2.2 thorpej }
617 1.5.2.2 thorpej
618 1.5.2.2 thorpej beenhere = 1;
619 1.5.2.2 thorpej }
620 1.5.2.2 thorpej
621 1.5.2.2 thorpej /*
622 1.5.2.2 thorpej * acpi_fixed_power_button_handler:
623 1.5.2.2 thorpej *
624 1.5.2.2 thorpej * Fixed event handler for the power button.
625 1.5.2.2 thorpej */
626 1.5.2.2 thorpej UINT32
627 1.5.2.2 thorpej acpi_fixed_power_button_handler(void *context)
628 1.5.2.2 thorpej {
629 1.5.2.2 thorpej struct acpi_softc *sc = context;
630 1.5.2.2 thorpej
631 1.5.2.2 thorpej /* XXX XXX XXX */
632 1.5.2.2 thorpej
633 1.5.2.2 thorpej printf("%s: fixed power button pressed\n", sc->sc_dev.dv_xname);
634 1.5.2.2 thorpej
635 1.5.2.4 jdolecek return (ACPI_INTERRUPT_HANDLED);
636 1.5.2.2 thorpej }
637 1.5.2.2 thorpej
638 1.5.2.2 thorpej /*
639 1.5.2.2 thorpej * acpi_fixed_sleep_button_handler:
640 1.5.2.2 thorpej *
641 1.5.2.2 thorpej * Fixed event handler for the sleep button.
642 1.5.2.2 thorpej */
643 1.5.2.2 thorpej UINT32
644 1.5.2.2 thorpej acpi_fixed_sleep_button_handler(void *context)
645 1.5.2.2 thorpej {
646 1.5.2.2 thorpej struct acpi_softc *sc = context;
647 1.5.2.2 thorpej
648 1.5.2.2 thorpej /* XXX XXX XXX */
649 1.5.2.2 thorpej
650 1.5.2.2 thorpej printf("%s: fixed sleep button pressed\n", sc->sc_dev.dv_xname);
651 1.5.2.2 thorpej
652 1.5.2.4 jdolecek return (ACPI_INTERRUPT_HANDLED);
653 1.5.2.2 thorpej }
654 1.5.2.2 thorpej
655 1.5.2.2 thorpej /*****************************************************************************
656 1.5.2.2 thorpej * ACPI utility routines.
657 1.5.2.2 thorpej *****************************************************************************/
658 1.5.2.2 thorpej
659 1.5.2.2 thorpej /*
660 1.5.2.2 thorpej * acpi_eval_integer:
661 1.5.2.2 thorpej *
662 1.5.2.2 thorpej * Evaluate an integer object.
663 1.5.2.2 thorpej */
664 1.5.2.2 thorpej ACPI_STATUS
665 1.5.2.2 thorpej acpi_eval_integer(ACPI_HANDLE handle, char *path, int *valp)
666 1.5.2.2 thorpej {
667 1.5.2.2 thorpej ACPI_STATUS rv;
668 1.5.2.2 thorpej ACPI_BUFFER buf;
669 1.5.2.2 thorpej ACPI_OBJECT param;
670 1.5.2.2 thorpej
671 1.5.2.2 thorpej if (handle == NULL)
672 1.5.2.2 thorpej handle = ACPI_ROOT_OBJECT;
673 1.5.2.2 thorpej
674 1.5.2.2 thorpej buf.Pointer = ¶m;
675 1.5.2.2 thorpej buf.Length = sizeof(param);
676 1.5.2.2 thorpej
677 1.5.2.2 thorpej rv = AcpiEvaluateObject(handle, path, NULL, &buf);
678 1.5.2.2 thorpej if (rv == AE_OK) {
679 1.5.2.2 thorpej if (param.Type == ACPI_TYPE_INTEGER)
680 1.5.2.2 thorpej *valp = param.Integer.Value;
681 1.5.2.2 thorpej else
682 1.5.2.2 thorpej rv = AE_TYPE;
683 1.5.2.2 thorpej }
684 1.5.2.2 thorpej
685 1.5.2.2 thorpej return (rv);
686 1.5.2.2 thorpej }
687 1.5.2.2 thorpej
688 1.5.2.4 jdolecek #if 0
689 1.5.2.2 thorpej /*
690 1.5.2.2 thorpej * acpi_eval_string:
691 1.5.2.2 thorpej *
692 1.5.2.4 jdolecek * Evaluate a (Unicode) string object.
693 1.5.2.4 jdolecek * XXX current API may leak memory, so don't use this.
694 1.5.2.2 thorpej */
695 1.5.2.2 thorpej ACPI_STATUS
696 1.5.2.2 thorpej acpi_eval_string(ACPI_HANDLE handle, char *path, char **stringp)
697 1.5.2.2 thorpej {
698 1.5.2.2 thorpej ACPI_STATUS rv;
699 1.5.2.2 thorpej ACPI_BUFFER buf;
700 1.5.2.4 jdolecek ACPI_OBJECT *param;
701 1.5.2.2 thorpej
702 1.5.2.2 thorpej if (handle == NULL)
703 1.5.2.2 thorpej handle = ACPI_ROOT_OBJECT;
704 1.5.2.2 thorpej
705 1.5.2.2 thorpej buf.Pointer = NULL;
706 1.5.2.2 thorpej buf.Length = 0;
707 1.5.2.2 thorpej
708 1.5.2.2 thorpej rv = AcpiEvaluateObject(handle, path, NULL, &buf);
709 1.5.2.2 thorpej if (rv != AE_BUFFER_OVERFLOW)
710 1.5.2.2 thorpej return (rv);
711 1.5.2.2 thorpej
712 1.5.2.2 thorpej buf.Pointer = AcpiOsAllocate(buf.Length);
713 1.5.2.2 thorpej if (buf.Pointer == NULL)
714 1.5.2.2 thorpej return (AE_NO_MEMORY);
715 1.5.2.2 thorpej
716 1.5.2.2 thorpej rv = AcpiEvaluateObject(handle, path, NULL, &buf);
717 1.5.2.4 jdolecek param = (ACPI_OBJECT *)buf.Pointer;
718 1.5.2.2 thorpej if (rv == AE_OK) {
719 1.5.2.4 jdolecek if (param->Type == ACPI_TYPE_STRING) {
720 1.5.2.4 jdolecek /* XXX may leak buf.Pointer!! */
721 1.5.2.4 jdolecek *stringp = param->String.Pointer;
722 1.5.2.2 thorpej return (AE_OK);
723 1.5.2.2 thorpej }
724 1.5.2.2 thorpej rv = AE_TYPE;
725 1.5.2.2 thorpej }
726 1.5.2.2 thorpej
727 1.5.2.2 thorpej AcpiOsFree(buf.Pointer);
728 1.5.2.2 thorpej return (rv);
729 1.5.2.2 thorpej }
730 1.5.2.4 jdolecek #endif
731 1.5.2.4 jdolecek
732 1.5.2.4 jdolecek
733 1.5.2.4 jdolecek /*
734 1.5.2.4 jdolecek * acpi_eval_struct:
735 1.5.2.4 jdolecek *
736 1.5.2.4 jdolecek * Evaluate a more complex structure. Caller must free buf.Pointer.
737 1.5.2.4 jdolecek */
738 1.5.2.4 jdolecek ACPI_STATUS
739 1.5.2.4 jdolecek acpi_eval_struct(ACPI_HANDLE handle, char *path, ACPI_BUFFER *bufp)
740 1.5.2.4 jdolecek {
741 1.5.2.4 jdolecek ACPI_STATUS rv;
742 1.5.2.4 jdolecek
743 1.5.2.4 jdolecek if (handle == NULL)
744 1.5.2.4 jdolecek handle = ACPI_ROOT_OBJECT;
745 1.5.2.4 jdolecek
746 1.5.2.4 jdolecek bufp->Pointer = NULL;
747 1.5.2.4 jdolecek bufp->Length = 0;
748 1.5.2.4 jdolecek
749 1.5.2.4 jdolecek rv = AcpiEvaluateObject(handle, path, NULL, bufp);
750 1.5.2.4 jdolecek if (rv != AE_BUFFER_OVERFLOW)
751 1.5.2.4 jdolecek return (rv);
752 1.5.2.4 jdolecek
753 1.5.2.4 jdolecek bufp->Pointer = AcpiOsAllocate(bufp->Length);
754 1.5.2.4 jdolecek if (bufp->Pointer == NULL)
755 1.5.2.4 jdolecek return (AE_NO_MEMORY);
756 1.5.2.4 jdolecek
757 1.5.2.4 jdolecek rv = AcpiEvaluateObject(handle, path, NULL, bufp);
758 1.5.2.4 jdolecek
759 1.5.2.4 jdolecek return (rv);
760 1.5.2.4 jdolecek }
761 1.5.2.2 thorpej
762 1.5.2.2 thorpej /*
763 1.5.2.2 thorpej * acpi_get:
764 1.5.2.2 thorpej *
765 1.5.2.2 thorpej * Fetch data info the specified (empty) ACPI buffer.
766 1.5.2.2 thorpej */
767 1.5.2.2 thorpej ACPI_STATUS
768 1.5.2.2 thorpej acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf,
769 1.5.2.2 thorpej ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *))
770 1.5.2.2 thorpej {
771 1.5.2.2 thorpej ACPI_STATUS rv;
772 1.5.2.2 thorpej
773 1.5.2.2 thorpej buf->Pointer = NULL;
774 1.5.2.2 thorpej buf->Length = 0;
775 1.5.2.2 thorpej
776 1.5.2.2 thorpej rv = (*getit)(handle, buf);
777 1.5.2.2 thorpej if (rv != AE_BUFFER_OVERFLOW)
778 1.5.2.2 thorpej return (rv);
779 1.5.2.2 thorpej
780 1.5.2.4 jdolecek buf->Pointer = AcpiOsAllocate(buf->Length);
781 1.5.2.2 thorpej if (buf->Pointer == NULL)
782 1.5.2.2 thorpej return (AE_NO_MEMORY);
783 1.5.2.4 jdolecek memset(buf->Pointer, 0, buf->Length);
784 1.5.2.2 thorpej
785 1.5.2.2 thorpej return ((*getit)(handle, buf));
786 1.5.2.2 thorpej }
787 1.5.2.5 jdolecek
788 1.5.2.5 jdolecek
789 1.5.2.5 jdolecek /*****************************************************************************
790 1.5.2.5 jdolecek * ACPI sleep support.
791 1.5.2.5 jdolecek *****************************************************************************/
792 1.5.2.5 jdolecek
793 1.5.2.5 jdolecek static int
794 1.5.2.5 jdolecek is_available_state(struct acpi_softc *sc, int state)
795 1.5.2.5 jdolecek {
796 1.5.2.5 jdolecek UINT8 type_a, type_b;
797 1.5.2.5 jdolecek
798 1.5.2.5 jdolecek return (ACPI_SUCCESS(AcpiGetSleepTypeData((UINT8)state,
799 1.5.2.5 jdolecek &type_a, &type_b)));
800 1.5.2.5 jdolecek }
801 1.5.2.5 jdolecek
802 1.5.2.5 jdolecek /*
803 1.5.2.5 jdolecek * acpi_enter_sleep_state:
804 1.5.2.5 jdolecek *
805 1.5.2.5 jdolecek * enter to the specified sleep state.
806 1.5.2.5 jdolecek */
807 1.5.2.5 jdolecek
808 1.5.2.5 jdolecek ACPI_STATUS
809 1.5.2.5 jdolecek acpi_enter_sleep_state(struct acpi_softc *sc, int state)
810 1.5.2.5 jdolecek {
811 1.5.2.5 jdolecek int s;
812 1.5.2.5 jdolecek ACPI_STATUS ret = AE_OK;
813 1.5.2.5 jdolecek
814 1.5.2.5 jdolecek switch (state) {
815 1.5.2.5 jdolecek case ACPI_STATE_S0:
816 1.5.2.5 jdolecek break;
817 1.5.2.5 jdolecek case ACPI_STATE_S1:
818 1.5.2.5 jdolecek case ACPI_STATE_S2:
819 1.5.2.5 jdolecek case ACPI_STATE_S3:
820 1.5.2.5 jdolecek case ACPI_STATE_S4:
821 1.5.2.5 jdolecek if (!is_available_state(sc, state)) {
822 1.5.2.5 jdolecek printf("acpi: cannot enter the sleep state (%d).\n",
823 1.5.2.5 jdolecek state);
824 1.5.2.5 jdolecek break;
825 1.5.2.5 jdolecek }
826 1.5.2.5 jdolecek ret = AcpiEnterSleepStatePrep(state);
827 1.5.2.5 jdolecek if (ACPI_FAILURE(ret)) {
828 1.5.2.5 jdolecek printf("acpi: failed preparing to sleep (%s)\n",
829 1.5.2.5 jdolecek AcpiFormatException(ret));
830 1.5.2.5 jdolecek break;
831 1.5.2.5 jdolecek }
832 1.5.2.5 jdolecek if (state==ACPI_STATE_S1) {
833 1.5.2.5 jdolecek /* just enter the state */
834 1.5.2.5 jdolecek acpi_md_OsDisableInterrupt();
835 1.5.2.5 jdolecek AcpiEnterSleepState((UINT8)state);
836 1.5.2.5 jdolecek AcpiUtReleaseMutex(ACPI_MTX_HARDWARE);
837 1.5.2.5 jdolecek } else {
838 1.5.2.5 jdolecek /* XXX: powerhooks(9) framework is too poor to
839 1.5.2.5 jdolecek * support ACPI sleep state...
840 1.5.2.5 jdolecek */
841 1.5.2.5 jdolecek dopowerhooks(PWR_SOFTSUSPEND);
842 1.5.2.5 jdolecek s = splhigh();
843 1.5.2.5 jdolecek dopowerhooks(PWR_SUSPEND);
844 1.5.2.5 jdolecek acpi_md_sleep(state);
845 1.5.2.5 jdolecek dopowerhooks(PWR_RESUME);
846 1.5.2.5 jdolecek splx(s);
847 1.5.2.5 jdolecek dopowerhooks(PWR_SOFTRESUME);
848 1.5.2.5 jdolecek if (state==ACPI_STATE_S4)
849 1.5.2.5 jdolecek AcpiEnable();
850 1.5.2.5 jdolecek }
851 1.5.2.5 jdolecek AcpiLeaveSleepState((UINT8)state);
852 1.5.2.5 jdolecek break;
853 1.5.2.5 jdolecek case ACPI_STATE_S5:
854 1.5.2.5 jdolecek AcpiEnterSleepStatePrep(ACPI_STATE_S5);
855 1.5.2.5 jdolecek acpi_md_OsDisableInterrupt();
856 1.5.2.5 jdolecek AcpiEnterSleepState(ACPI_STATE_S5);
857 1.5.2.5 jdolecek printf("WARNING: powerdown failed!\n");
858 1.5.2.5 jdolecek break;
859 1.5.2.5 jdolecek }
860 1.5.2.5 jdolecek
861 1.5.2.5 jdolecek return (ret);
862 1.5.2.5 jdolecek }
863 1.5.2.5 jdolecek
864 1.5.2.5 jdolecek #if ACPI_PCI_FIXUP
865 1.5.2.5 jdolecek ACPI_STATUS acpi_pci_fixup_bus(ACPI_HANDLE, UINT32, void *, void **);
866 1.5.2.5 jdolecek /*
867 1.5.2.5 jdolecek * acpi_pci_fixup:
868 1.5.2.5 jdolecek *
869 1.5.2.5 jdolecek * Set up PCI devices that BIOS didn't handle right.
870 1.5.2.5 jdolecek * Iterate through all devices and try to get the _PTR
871 1.5.2.5 jdolecek * (PCI Routing Table). If it exists then make sure all
872 1.5.2.5 jdolecek * interrupt links that it uses are working.
873 1.5.2.5 jdolecek */
874 1.5.2.5 jdolecek void
875 1.5.2.5 jdolecek acpi_pci_fixup(struct acpi_softc *sc)
876 1.5.2.5 jdolecek {
877 1.5.2.5 jdolecek ACPI_HANDLE parent;
878 1.5.2.5 jdolecek
879 1.5.2.5 jdolecek #ifdef ACPI_DEBUG
880 1.5.2.5 jdolecek printf("acpi_pci_fixup starts:\n");
881 1.5.2.5 jdolecek #endif
882 1.5.2.5 jdolecek if (AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &parent) != AE_OK)
883 1.5.2.5 jdolecek return;
884 1.5.2.5 jdolecek sc->sc_pci_bus = 0;
885 1.5.2.5 jdolecek AcpiWalkNamespace(ACPI_TYPE_DEVICE, parent, 100,
886 1.5.2.5 jdolecek acpi_pci_fixup_bus, sc, NULL);
887 1.5.2.5 jdolecek }
888 1.5.2.5 jdolecek
889 1.5.2.5 jdolecek static ACPI_HANDLE
890 1.5.2.5 jdolecek acpi_get_node(char *name)
891 1.5.2.5 jdolecek {
892 1.5.2.5 jdolecek ACPI_NAMESPACE_NODE *ObjDesc;
893 1.5.2.5 jdolecek ACPI_STATUS Status;
894 1.5.2.5 jdolecek
895 1.5.2.5 jdolecek Status = AcpiNsGetNodeByPath(name, NULL, 0, &ObjDesc);
896 1.5.2.5 jdolecek if (ACPI_FAILURE (Status)) {
897 1.5.2.5 jdolecek printf("acpi_get_node: could not find: %s\n",
898 1.5.2.5 jdolecek AcpiFormatException (Status));
899 1.5.2.5 jdolecek return NULL;
900 1.5.2.5 jdolecek }
901 1.5.2.5 jdolecek return ObjDesc;
902 1.5.2.5 jdolecek }
903 1.5.2.5 jdolecek
904 1.5.2.5 jdolecek static uint
905 1.5.2.5 jdolecek acpi_get_intr(ACPI_HANDLE handle)
906 1.5.2.5 jdolecek {
907 1.5.2.5 jdolecek ACPI_BUFFER ret;
908 1.5.2.5 jdolecek ACPI_STATUS rv;
909 1.5.2.5 jdolecek ACPI_RESOURCE *res;
910 1.5.2.5 jdolecek ACPI_RESOURCE_IRQ *irq;
911 1.5.2.5 jdolecek uint intr;
912 1.5.2.5 jdolecek
913 1.5.2.5 jdolecek intr = -1;
914 1.5.2.5 jdolecek rv = acpi_get(handle, &ret, AcpiGetCurrentResources);
915 1.5.2.5 jdolecek if (ACPI_FAILURE(rv))
916 1.5.2.5 jdolecek return (intr);
917 1.5.2.5 jdolecek for (res = ret.Pointer; res->Id != ACPI_RSTYPE_END_TAG;
918 1.5.2.5 jdolecek res = ACPI_NEXT_RESOURCE(res)) {
919 1.5.2.5 jdolecek if (res->Id == ACPI_RSTYPE_IRQ) {
920 1.5.2.5 jdolecek irq = (ACPI_RESOURCE_IRQ *)&res->Data;
921 1.5.2.5 jdolecek if (irq->NumberOfInterrupts == 1)
922 1.5.2.5 jdolecek intr = irq->Interrupts[0];
923 1.5.2.5 jdolecek break;
924 1.5.2.5 jdolecek }
925 1.5.2.5 jdolecek }
926 1.5.2.5 jdolecek free(ret.Pointer, M_DEVBUF);
927 1.5.2.5 jdolecek return (intr);
928 1.5.2.5 jdolecek }
929 1.5.2.5 jdolecek
930 1.5.2.5 jdolecek static void
931 1.5.2.5 jdolecek acpi_pci_set_line(int bus, int dev, int pin, int line)
932 1.5.2.5 jdolecek {
933 1.5.2.5 jdolecek ACPI_STATUS err;
934 1.5.2.5 jdolecek ACPI_PCI_ID pid;
935 1.5.2.5 jdolecek UINT32 intr, id, bhlc;
936 1.5.2.5 jdolecek int func, nfunc;
937 1.5.2.5 jdolecek
938 1.5.2.5 jdolecek pid.Bus = bus;
939 1.5.2.5 jdolecek pid.Device = dev;
940 1.5.2.5 jdolecek pid.Function = 0;
941 1.5.2.5 jdolecek
942 1.5.2.5 jdolecek err = AcpiOsReadPciConfiguration(&pid, PCI_BHLC_REG, &bhlc, 32);
943 1.5.2.5 jdolecek if (err)
944 1.5.2.5 jdolecek return;
945 1.5.2.5 jdolecek if (PCI_HDRTYPE_MULTIFN(bhlc))
946 1.5.2.5 jdolecek nfunc = 8;
947 1.5.2.5 jdolecek else
948 1.5.2.5 jdolecek nfunc = 1;
949 1.5.2.5 jdolecek
950 1.5.2.5 jdolecek for (func = 0; func < nfunc; func++) {
951 1.5.2.5 jdolecek pid.Function = func;
952 1.5.2.5 jdolecek
953 1.5.2.5 jdolecek err = AcpiOsReadPciConfiguration(&pid, PCI_ID_REG, &id, 32);
954 1.5.2.5 jdolecek if (err || PCI_VENDOR(id) == PCI_VENDOR_INVALID ||
955 1.5.2.5 jdolecek PCI_VENDOR(id) == 0)
956 1.5.2.5 jdolecek continue;
957 1.5.2.5 jdolecek
958 1.5.2.5 jdolecek err = AcpiOsReadPciConfiguration(&pid, PCI_INTERRUPT_REG,
959 1.5.2.5 jdolecek &intr, 32);
960 1.5.2.5 jdolecek if (err) {
961 1.5.2.5 jdolecek printf("AcpiOsReadPciConfiguration failed %d\n", err);
962 1.5.2.5 jdolecek return;
963 1.5.2.5 jdolecek }
964 1.5.2.5 jdolecek if (pin == PCI_INTERRUPT_PIN(intr) &&
965 1.5.2.5 jdolecek line != PCI_INTERRUPT_LINE(intr)) {
966 1.5.2.5 jdolecek #ifdef ACPI_DEBUG
967 1.5.2.5 jdolecek printf("acpi fixup pci intr: %d:%d:%d %c: %d -> %d\n",
968 1.5.2.5 jdolecek bus, dev, func,
969 1.5.2.5 jdolecek pin + '@', PCI_INTERRUPT_LINE(intr),
970 1.5.2.5 jdolecek line);
971 1.5.2.5 jdolecek #endif
972 1.5.2.5 jdolecek intr &= ~(PCI_INTERRUPT_LINE_MASK <<
973 1.5.2.5 jdolecek PCI_INTERRUPT_LINE_SHIFT);
974 1.5.2.5 jdolecek intr |= line << PCI_INTERRUPT_LINE_SHIFT;
975 1.5.2.5 jdolecek err = AcpiOsWritePciConfiguration(&pid,
976 1.5.2.5 jdolecek PCI_INTERRUPT_REG, intr, 32);
977 1.5.2.5 jdolecek if (err) {
978 1.5.2.5 jdolecek printf("AcpiOsWritePciConfiguration failed"
979 1.5.2.5 jdolecek " %d\n", err);
980 1.5.2.5 jdolecek return;
981 1.5.2.5 jdolecek }
982 1.5.2.5 jdolecek }
983 1.5.2.5 jdolecek }
984 1.5.2.5 jdolecek }
985 1.5.2.5 jdolecek
986 1.5.2.5 jdolecek ACPI_STATUS
987 1.5.2.5 jdolecek acpi_pci_fixup_bus(ACPI_HANDLE handle, UINT32 level, void *context,
988 1.5.2.5 jdolecek void **status)
989 1.5.2.5 jdolecek {
990 1.5.2.5 jdolecek struct acpi_softc *sc = context;
991 1.5.2.5 jdolecek ACPI_STATUS rv;
992 1.5.2.5 jdolecek ACPI_BUFFER buf;
993 1.5.2.5 jdolecek UINT8 *Buffer;
994 1.5.2.5 jdolecek ACPI_PCI_ROUTING_TABLE *PrtElement;
995 1.5.2.5 jdolecek ACPI_HANDLE link;
996 1.5.2.5 jdolecek uint line;
997 1.5.2.5 jdolecek
998 1.5.2.5 jdolecek rv = acpi_get(handle, &buf, AcpiGetIrqRoutingTable);
999 1.5.2.5 jdolecek if (ACPI_FAILURE(rv))
1000 1.5.2.5 jdolecek return (AE_OK);
1001 1.5.2.5 jdolecek
1002 1.5.2.5 jdolecek #ifdef ACPI_DEBUG
1003 1.5.2.5 jdolecek printf("%s: fixing up PCI\n", sc->sc_dev.dv_xname);
1004 1.5.2.5 jdolecek #endif
1005 1.5.2.5 jdolecek
1006 1.5.2.5 jdolecek for (Buffer = buf.Pointer; ; Buffer += PrtElement->Length) {
1007 1.5.2.5 jdolecek PrtElement = (ACPI_PCI_ROUTING_TABLE *)Buffer;
1008 1.5.2.5 jdolecek if (PrtElement->Length == 0)
1009 1.5.2.5 jdolecek break;
1010 1.5.2.5 jdolecek if (PrtElement->Source == NULL)
1011 1.5.2.5 jdolecek continue;
1012 1.5.2.5 jdolecek
1013 1.5.2.5 jdolecek link = acpi_get_node(PrtElement->Source);
1014 1.5.2.5 jdolecek if (link == NULL)
1015 1.5.2.5 jdolecek continue;
1016 1.5.2.5 jdolecek line = acpi_get_intr(link);
1017 1.5.2.5 jdolecek if (line == -1) {
1018 1.5.2.5 jdolecek #ifdef ACPI_DEBUG
1019 1.5.2.5 jdolecek printf("%s: fixing up link %s\n", sc->sc_dev.dv_xname,
1020 1.5.2.5 jdolecek PrtElement->Source);
1021 1.5.2.5 jdolecek #endif
1022 1.5.2.5 jdolecek rv = acpi_allocate_resources(link);
1023 1.5.2.5 jdolecek if (ACPI_FAILURE(rv)) {
1024 1.5.2.5 jdolecek printf("%s: interrupt allocation failed %s\n",
1025 1.5.2.5 jdolecek sc->sc_dev.dv_xname, PrtElement->Source);
1026 1.5.2.5 jdolecek continue;
1027 1.5.2.5 jdolecek }
1028 1.5.2.5 jdolecek line = acpi_get_intr(link);
1029 1.5.2.5 jdolecek if (line == -1) {
1030 1.5.2.5 jdolecek printf("%s: get intr failed %s\n",
1031 1.5.2.5 jdolecek sc->sc_dev.dv_xname, PrtElement->Source);
1032 1.5.2.5 jdolecek continue;
1033 1.5.2.5 jdolecek }
1034 1.5.2.5 jdolecek }
1035 1.5.2.5 jdolecek
1036 1.5.2.5 jdolecek acpi_pci_set_line(sc->sc_pci_bus, PrtElement->Address >> 16,
1037 1.5.2.5 jdolecek PrtElement->Pin + 1, line);
1038 1.5.2.5 jdolecek }
1039 1.5.2.5 jdolecek
1040 1.5.2.5 jdolecek sc->sc_pci_bus++;
1041 1.5.2.5 jdolecek
1042 1.5.2.5 jdolecek free(buf.Pointer, M_DEVBUF);
1043 1.5.2.5 jdolecek return (AE_OK);
1044 1.5.2.5 jdolecek }
1045 1.5.2.5 jdolecek #endif /* ACPI_PCI_FIXUP */
1046 1.5.2.5 jdolecek
1047 1.5.2.5 jdolecek #if ACPI_PCI_FIXUP || ACPI_ACTIVATE_DEV
1048 1.5.2.5 jdolecek /* XXX This very incomplete */
1049 1.5.2.5 jdolecek ACPI_STATUS
1050 1.5.2.5 jdolecek acpi_allocate_resources(ACPI_HANDLE handle)
1051 1.5.2.5 jdolecek {
1052 1.5.2.5 jdolecek ACPI_BUFFER bufp, bufc, bufn;
1053 1.5.2.5 jdolecek ACPI_RESOURCE *resp, *resc, *resn;
1054 1.5.2.5 jdolecek ACPI_RESOURCE_IRQ *irq;
1055 1.5.2.5 jdolecek ACPI_STATUS rv;
1056 1.5.2.5 jdolecek uint delta;
1057 1.5.2.5 jdolecek
1058 1.5.2.5 jdolecek rv = acpi_get(handle, &bufp, AcpiGetPossibleResources);
1059 1.5.2.5 jdolecek if (ACPI_FAILURE(rv))
1060 1.5.2.5 jdolecek goto out;
1061 1.5.2.5 jdolecek rv = acpi_get(handle, &bufc, AcpiGetCurrentResources);
1062 1.5.2.5 jdolecek if (ACPI_FAILURE(rv)) {
1063 1.5.2.5 jdolecek goto out1;
1064 1.5.2.5 jdolecek }
1065 1.5.2.5 jdolecek
1066 1.5.2.5 jdolecek bufn.Length = 1000;
1067 1.5.2.5 jdolecek bufn.Pointer = resn = malloc(bufn.Length, M_DEVBUF, M_WAITOK);
1068 1.5.2.5 jdolecek resp = bufp.Pointer;
1069 1.5.2.5 jdolecek resc = bufc.Pointer;
1070 1.5.2.5 jdolecek while (resc->Id != ACPI_RSTYPE_END_TAG &&
1071 1.5.2.5 jdolecek resp->Id != ACPI_RSTYPE_END_TAG) {
1072 1.5.2.5 jdolecek while (resc->Id != resp->Id && resp->Id != ACPI_RSTYPE_END_TAG)
1073 1.5.2.5 jdolecek resp = ACPI_NEXT_RESOURCE(resp);
1074 1.5.2.5 jdolecek if (resp->Id == ACPI_RSTYPE_END_TAG)
1075 1.5.2.5 jdolecek break;
1076 1.5.2.5 jdolecek /* Found identical Id */
1077 1.5.2.5 jdolecek resn->Id = resc->Id;
1078 1.5.2.5 jdolecek switch (resc->Id) {
1079 1.5.2.5 jdolecek case ACPI_RSTYPE_IRQ:
1080 1.5.2.5 jdolecek memcpy(&resn->Data, &resp->Data,
1081 1.5.2.5 jdolecek sizeof(ACPI_RESOURCE_IRQ));
1082 1.5.2.5 jdolecek irq = (ACPI_RESOURCE_IRQ *)&resn->Data;
1083 1.5.2.5 jdolecek irq->Interrupts[0] =
1084 1.5.2.5 jdolecek ((ACPI_RESOURCE_IRQ *)&resp->Data)->
1085 1.5.2.5 jdolecek Interrupts[irq->NumberOfInterrupts-1];
1086 1.5.2.5 jdolecek irq->NumberOfInterrupts = 1;
1087 1.5.2.5 jdolecek resn->Length = ACPI_SIZEOF_RESOURCE(ACPI_RESOURCE_IRQ);
1088 1.5.2.5 jdolecek break;
1089 1.5.2.5 jdolecek case ACPI_RSTYPE_IO:
1090 1.5.2.5 jdolecek memcpy(&resn->Data, &resp->Data,
1091 1.5.2.5 jdolecek sizeof(ACPI_RESOURCE_IO));
1092 1.5.2.5 jdolecek resn->Length = resp->Length;
1093 1.5.2.5 jdolecek break;
1094 1.5.2.5 jdolecek default:
1095 1.5.2.5 jdolecek printf("acpi_allocate_resources: res=%d\n", resc->Id);
1096 1.5.2.5 jdolecek rv = AE_BAD_DATA;
1097 1.5.2.5 jdolecek goto out2;
1098 1.5.2.5 jdolecek }
1099 1.5.2.5 jdolecek resc = ACPI_NEXT_RESOURCE(resc);
1100 1.5.2.5 jdolecek resn = ACPI_NEXT_RESOURCE(resn);
1101 1.5.2.5 jdolecek delta = (UINT8 *)resn - (UINT8 *)bufn.Pointer;
1102 1.5.2.5 jdolecek if (delta >= bufn.Length-ACPI_SIZEOF_RESOURCE(ACPI_RESOURCE_DATA)) {
1103 1.5.2.5 jdolecek bufn.Length *= 2;
1104 1.5.2.5 jdolecek bufn.Pointer = realloc(bufn.Pointer, bufn.Length,
1105 1.5.2.5 jdolecek M_DEVBUF, M_WAITOK);
1106 1.5.2.5 jdolecek resn = (ACPI_RESOURCE *)((UINT8 *)bufn.Pointer + delta);
1107 1.5.2.5 jdolecek }
1108 1.5.2.5 jdolecek }
1109 1.5.2.5 jdolecek if (resc->Id != ACPI_RSTYPE_END_TAG) {
1110 1.5.2.5 jdolecek printf("acpi_allocate_resources: resc not exhausted\n");
1111 1.5.2.5 jdolecek rv = AE_BAD_DATA;
1112 1.5.2.5 jdolecek goto out3;
1113 1.5.2.5 jdolecek }
1114 1.5.2.5 jdolecek
1115 1.5.2.5 jdolecek resn->Id = ACPI_RSTYPE_END_TAG;
1116 1.5.2.5 jdolecek rv = AcpiSetCurrentResources(handle, &bufn);
1117 1.5.2.5 jdolecek if (ACPI_FAILURE(rv)) {
1118 1.5.2.5 jdolecek printf("acpi_allocate_resources: AcpiSetCurrentResources %s\n",
1119 1.5.2.5 jdolecek AcpiFormatException(rv));
1120 1.5.2.5 jdolecek }
1121 1.5.2.5 jdolecek
1122 1.5.2.5 jdolecek out3:
1123 1.5.2.5 jdolecek free(bufn.Pointer, M_DEVBUF);
1124 1.5.2.5 jdolecek out2:
1125 1.5.2.5 jdolecek free(bufc.Pointer, M_DEVBUF);
1126 1.5.2.5 jdolecek out1:
1127 1.5.2.5 jdolecek free(bufp.Pointer, M_DEVBUF);
1128 1.5.2.5 jdolecek out:
1129 1.5.2.5 jdolecek return rv;
1130 1.5.2.5 jdolecek }
1131 1.5.2.5 jdolecek #endif /* ACPI_PCI_FIXUP || ACPI_ACTIVATE_DEV */
1132