1*29492bb7SDavid van Moolenbroek /******************************************************************************
2*29492bb7SDavid van Moolenbroek *
3*29492bb7SDavid van Moolenbroek * Module Name: evhandler - Support for Address Space handlers
4*29492bb7SDavid van Moolenbroek *
5*29492bb7SDavid van Moolenbroek *****************************************************************************/
6*29492bb7SDavid van Moolenbroek
7*29492bb7SDavid van Moolenbroek /*
8*29492bb7SDavid van Moolenbroek * Copyright (C) 2000 - 2014, Intel Corp.
9*29492bb7SDavid van Moolenbroek * All rights reserved.
10*29492bb7SDavid van Moolenbroek *
11*29492bb7SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
12*29492bb7SDavid van Moolenbroek * modification, are permitted provided that the following conditions
13*29492bb7SDavid van Moolenbroek * are met:
14*29492bb7SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
15*29492bb7SDavid van Moolenbroek * notice, this list of conditions, and the following disclaimer,
16*29492bb7SDavid van Moolenbroek * without modification.
17*29492bb7SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18*29492bb7SDavid van Moolenbroek * substantially similar to the "NO WARRANTY" disclaimer below
19*29492bb7SDavid van Moolenbroek * ("Disclaimer") and any redistribution must be conditioned upon
20*29492bb7SDavid van Moolenbroek * including a substantially similar Disclaimer requirement for further
21*29492bb7SDavid van Moolenbroek * binary redistribution.
22*29492bb7SDavid van Moolenbroek * 3. Neither the names of the above-listed copyright holders nor the names
23*29492bb7SDavid van Moolenbroek * of any contributors may be used to endorse or promote products derived
24*29492bb7SDavid van Moolenbroek * from this software without specific prior written permission.
25*29492bb7SDavid van Moolenbroek *
26*29492bb7SDavid van Moolenbroek * Alternatively, this software may be distributed under the terms of the
27*29492bb7SDavid van Moolenbroek * GNU General Public License ("GPL") version 2 as published by the Free
28*29492bb7SDavid van Moolenbroek * Software Foundation.
29*29492bb7SDavid van Moolenbroek *
30*29492bb7SDavid van Moolenbroek * NO WARRANTY
31*29492bb7SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32*29492bb7SDavid van Moolenbroek * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33*29492bb7SDavid van Moolenbroek * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34*29492bb7SDavid van Moolenbroek * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35*29492bb7SDavid van Moolenbroek * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36*29492bb7SDavid van Moolenbroek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37*29492bb7SDavid van Moolenbroek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38*29492bb7SDavid van Moolenbroek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39*29492bb7SDavid van Moolenbroek * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40*29492bb7SDavid van Moolenbroek * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41*29492bb7SDavid van Moolenbroek * POSSIBILITY OF SUCH DAMAGES.
42*29492bb7SDavid van Moolenbroek */
43*29492bb7SDavid van Moolenbroek
44*29492bb7SDavid van Moolenbroek #include "acpi.h"
45*29492bb7SDavid van Moolenbroek #include "accommon.h"
46*29492bb7SDavid van Moolenbroek #include "acevents.h"
47*29492bb7SDavid van Moolenbroek #include "acnamesp.h"
48*29492bb7SDavid van Moolenbroek #include "acinterp.h"
49*29492bb7SDavid van Moolenbroek
50*29492bb7SDavid van Moolenbroek #define _COMPONENT ACPI_EVENTS
51*29492bb7SDavid van Moolenbroek ACPI_MODULE_NAME ("evhandler")
52*29492bb7SDavid van Moolenbroek
53*29492bb7SDavid van Moolenbroek
54*29492bb7SDavid van Moolenbroek /* Local prototypes */
55*29492bb7SDavid van Moolenbroek
56*29492bb7SDavid van Moolenbroek static ACPI_STATUS
57*29492bb7SDavid van Moolenbroek AcpiEvInstallHandler (
58*29492bb7SDavid van Moolenbroek ACPI_HANDLE ObjHandle,
59*29492bb7SDavid van Moolenbroek UINT32 Level,
60*29492bb7SDavid van Moolenbroek void *Context,
61*29492bb7SDavid van Moolenbroek void **ReturnValue);
62*29492bb7SDavid van Moolenbroek
63*29492bb7SDavid van Moolenbroek /* These are the address spaces that will get default handlers */
64*29492bb7SDavid van Moolenbroek
65*29492bb7SDavid van Moolenbroek UINT8 AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] =
66*29492bb7SDavid van Moolenbroek {
67*29492bb7SDavid van Moolenbroek ACPI_ADR_SPACE_SYSTEM_MEMORY,
68*29492bb7SDavid van Moolenbroek ACPI_ADR_SPACE_SYSTEM_IO,
69*29492bb7SDavid van Moolenbroek ACPI_ADR_SPACE_PCI_CONFIG,
70*29492bb7SDavid van Moolenbroek ACPI_ADR_SPACE_DATA_TABLE
71*29492bb7SDavid van Moolenbroek };
72*29492bb7SDavid van Moolenbroek
73*29492bb7SDavid van Moolenbroek
74*29492bb7SDavid van Moolenbroek /*******************************************************************************
75*29492bb7SDavid van Moolenbroek *
76*29492bb7SDavid van Moolenbroek * FUNCTION: AcpiEvInstallRegionHandlers
77*29492bb7SDavid van Moolenbroek *
78*29492bb7SDavid van Moolenbroek * PARAMETERS: None
79*29492bb7SDavid van Moolenbroek *
80*29492bb7SDavid van Moolenbroek * RETURN: Status
81*29492bb7SDavid van Moolenbroek *
82*29492bb7SDavid van Moolenbroek * DESCRIPTION: Installs the core subsystem default address space handlers.
83*29492bb7SDavid van Moolenbroek *
84*29492bb7SDavid van Moolenbroek ******************************************************************************/
85*29492bb7SDavid van Moolenbroek
86*29492bb7SDavid van Moolenbroek ACPI_STATUS
AcpiEvInstallRegionHandlers(void)87*29492bb7SDavid van Moolenbroek AcpiEvInstallRegionHandlers (
88*29492bb7SDavid van Moolenbroek void)
89*29492bb7SDavid van Moolenbroek {
90*29492bb7SDavid van Moolenbroek ACPI_STATUS Status;
91*29492bb7SDavid van Moolenbroek UINT32 i;
92*29492bb7SDavid van Moolenbroek
93*29492bb7SDavid van Moolenbroek
94*29492bb7SDavid van Moolenbroek ACPI_FUNCTION_TRACE (EvInstallRegionHandlers);
95*29492bb7SDavid van Moolenbroek
96*29492bb7SDavid van Moolenbroek
97*29492bb7SDavid van Moolenbroek Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
98*29492bb7SDavid van Moolenbroek if (ACPI_FAILURE (Status))
99*29492bb7SDavid van Moolenbroek {
100*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (Status);
101*29492bb7SDavid van Moolenbroek }
102*29492bb7SDavid van Moolenbroek
103*29492bb7SDavid van Moolenbroek /*
104*29492bb7SDavid van Moolenbroek * All address spaces (PCI Config, EC, SMBus) are scope dependent and
105*29492bb7SDavid van Moolenbroek * registration must occur for a specific device.
106*29492bb7SDavid van Moolenbroek *
107*29492bb7SDavid van Moolenbroek * In the case of the system memory and IO address spaces there is
108*29492bb7SDavid van Moolenbroek * currently no device associated with the address space. For these we
109*29492bb7SDavid van Moolenbroek * use the root.
110*29492bb7SDavid van Moolenbroek *
111*29492bb7SDavid van Moolenbroek * We install the default PCI config space handler at the root so that
112*29492bb7SDavid van Moolenbroek * this space is immediately available even though the we have not
113*29492bb7SDavid van Moolenbroek * enumerated all the PCI Root Buses yet. This is to conform to the ACPI
114*29492bb7SDavid van Moolenbroek * specification which states that the PCI config space must be always
115*29492bb7SDavid van Moolenbroek * available -- even though we are nowhere near ready to find the PCI root
116*29492bb7SDavid van Moolenbroek * buses at this point.
117*29492bb7SDavid van Moolenbroek *
118*29492bb7SDavid van Moolenbroek * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
119*29492bb7SDavid van Moolenbroek * has already been installed (via AcpiInstallAddressSpaceHandler).
120*29492bb7SDavid van Moolenbroek * Similar for AE_SAME_HANDLER.
121*29492bb7SDavid van Moolenbroek */
122*29492bb7SDavid van Moolenbroek for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
123*29492bb7SDavid van Moolenbroek {
124*29492bb7SDavid van Moolenbroek Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,
125*29492bb7SDavid van Moolenbroek AcpiGbl_DefaultAddressSpaces[i],
126*29492bb7SDavid van Moolenbroek ACPI_DEFAULT_HANDLER, NULL, NULL);
127*29492bb7SDavid van Moolenbroek switch (Status)
128*29492bb7SDavid van Moolenbroek {
129*29492bb7SDavid van Moolenbroek case AE_OK:
130*29492bb7SDavid van Moolenbroek case AE_SAME_HANDLER:
131*29492bb7SDavid van Moolenbroek case AE_ALREADY_EXISTS:
132*29492bb7SDavid van Moolenbroek
133*29492bb7SDavid van Moolenbroek /* These exceptions are all OK */
134*29492bb7SDavid van Moolenbroek
135*29492bb7SDavid van Moolenbroek Status = AE_OK;
136*29492bb7SDavid van Moolenbroek break;
137*29492bb7SDavid van Moolenbroek
138*29492bb7SDavid van Moolenbroek default:
139*29492bb7SDavid van Moolenbroek
140*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
141*29492bb7SDavid van Moolenbroek }
142*29492bb7SDavid van Moolenbroek }
143*29492bb7SDavid van Moolenbroek
144*29492bb7SDavid van Moolenbroek UnlockAndExit:
145*29492bb7SDavid van Moolenbroek (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
146*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (Status);
147*29492bb7SDavid van Moolenbroek }
148*29492bb7SDavid van Moolenbroek
149*29492bb7SDavid van Moolenbroek
150*29492bb7SDavid van Moolenbroek /*******************************************************************************
151*29492bb7SDavid van Moolenbroek *
152*29492bb7SDavid van Moolenbroek * FUNCTION: AcpiEvHasDefaultHandler
153*29492bb7SDavid van Moolenbroek *
154*29492bb7SDavid van Moolenbroek * PARAMETERS: Node - Namespace node for the device
155*29492bb7SDavid van Moolenbroek * SpaceId - The address space ID
156*29492bb7SDavid van Moolenbroek *
157*29492bb7SDavid van Moolenbroek * RETURN: TRUE if default handler is installed, FALSE otherwise
158*29492bb7SDavid van Moolenbroek *
159*29492bb7SDavid van Moolenbroek * DESCRIPTION: Check if the default handler is installed for the requested
160*29492bb7SDavid van Moolenbroek * space ID.
161*29492bb7SDavid van Moolenbroek *
162*29492bb7SDavid van Moolenbroek ******************************************************************************/
163*29492bb7SDavid van Moolenbroek
164*29492bb7SDavid van Moolenbroek BOOLEAN
AcpiEvHasDefaultHandler(ACPI_NAMESPACE_NODE * Node,ACPI_ADR_SPACE_TYPE SpaceId)165*29492bb7SDavid van Moolenbroek AcpiEvHasDefaultHandler (
166*29492bb7SDavid van Moolenbroek ACPI_NAMESPACE_NODE *Node,
167*29492bb7SDavid van Moolenbroek ACPI_ADR_SPACE_TYPE SpaceId)
168*29492bb7SDavid van Moolenbroek {
169*29492bb7SDavid van Moolenbroek ACPI_OPERAND_OBJECT *ObjDesc;
170*29492bb7SDavid van Moolenbroek ACPI_OPERAND_OBJECT *HandlerObj;
171*29492bb7SDavid van Moolenbroek
172*29492bb7SDavid van Moolenbroek
173*29492bb7SDavid van Moolenbroek /* Must have an existing internal object */
174*29492bb7SDavid van Moolenbroek
175*29492bb7SDavid van Moolenbroek ObjDesc = AcpiNsGetAttachedObject (Node);
176*29492bb7SDavid van Moolenbroek if (ObjDesc)
177*29492bb7SDavid van Moolenbroek {
178*29492bb7SDavid van Moolenbroek HandlerObj = ObjDesc->Device.Handler;
179*29492bb7SDavid van Moolenbroek
180*29492bb7SDavid van Moolenbroek /* Walk the linked list of handlers for this object */
181*29492bb7SDavid van Moolenbroek
182*29492bb7SDavid van Moolenbroek while (HandlerObj)
183*29492bb7SDavid van Moolenbroek {
184*29492bb7SDavid van Moolenbroek if (HandlerObj->AddressSpace.SpaceId == SpaceId)
185*29492bb7SDavid van Moolenbroek {
186*29492bb7SDavid van Moolenbroek if (HandlerObj->AddressSpace.HandlerFlags &
187*29492bb7SDavid van Moolenbroek ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
188*29492bb7SDavid van Moolenbroek {
189*29492bb7SDavid van Moolenbroek return (TRUE);
190*29492bb7SDavid van Moolenbroek }
191*29492bb7SDavid van Moolenbroek }
192*29492bb7SDavid van Moolenbroek
193*29492bb7SDavid van Moolenbroek HandlerObj = HandlerObj->AddressSpace.Next;
194*29492bb7SDavid van Moolenbroek }
195*29492bb7SDavid van Moolenbroek }
196*29492bb7SDavid van Moolenbroek
197*29492bb7SDavid van Moolenbroek return (FALSE);
198*29492bb7SDavid van Moolenbroek }
199*29492bb7SDavid van Moolenbroek
200*29492bb7SDavid van Moolenbroek
201*29492bb7SDavid van Moolenbroek /*******************************************************************************
202*29492bb7SDavid van Moolenbroek *
203*29492bb7SDavid van Moolenbroek * FUNCTION: AcpiEvInstallHandler
204*29492bb7SDavid van Moolenbroek *
205*29492bb7SDavid van Moolenbroek * PARAMETERS: WalkNamespace callback
206*29492bb7SDavid van Moolenbroek *
207*29492bb7SDavid van Moolenbroek * DESCRIPTION: This routine installs an address handler into objects that are
208*29492bb7SDavid van Moolenbroek * of type Region or Device.
209*29492bb7SDavid van Moolenbroek *
210*29492bb7SDavid van Moolenbroek * If the Object is a Device, and the device has a handler of
211*29492bb7SDavid van Moolenbroek * the same type then the search is terminated in that branch.
212*29492bb7SDavid van Moolenbroek *
213*29492bb7SDavid van Moolenbroek * This is because the existing handler is closer in proximity
214*29492bb7SDavid van Moolenbroek * to any more regions than the one we are trying to install.
215*29492bb7SDavid van Moolenbroek *
216*29492bb7SDavid van Moolenbroek ******************************************************************************/
217*29492bb7SDavid van Moolenbroek
218*29492bb7SDavid van Moolenbroek static ACPI_STATUS
AcpiEvInstallHandler(ACPI_HANDLE ObjHandle,UINT32 Level,void * Context,void ** ReturnValue)219*29492bb7SDavid van Moolenbroek AcpiEvInstallHandler (
220*29492bb7SDavid van Moolenbroek ACPI_HANDLE ObjHandle,
221*29492bb7SDavid van Moolenbroek UINT32 Level,
222*29492bb7SDavid van Moolenbroek void *Context,
223*29492bb7SDavid van Moolenbroek void **ReturnValue)
224*29492bb7SDavid van Moolenbroek {
225*29492bb7SDavid van Moolenbroek ACPI_OPERAND_OBJECT *HandlerObj;
226*29492bb7SDavid van Moolenbroek ACPI_OPERAND_OBJECT *NextHandlerObj;
227*29492bb7SDavid van Moolenbroek ACPI_OPERAND_OBJECT *ObjDesc;
228*29492bb7SDavid van Moolenbroek ACPI_NAMESPACE_NODE *Node;
229*29492bb7SDavid van Moolenbroek ACPI_STATUS Status;
230*29492bb7SDavid van Moolenbroek
231*29492bb7SDavid van Moolenbroek
232*29492bb7SDavid van Moolenbroek ACPI_FUNCTION_NAME (EvInstallHandler);
233*29492bb7SDavid van Moolenbroek
234*29492bb7SDavid van Moolenbroek
235*29492bb7SDavid van Moolenbroek HandlerObj = (ACPI_OPERAND_OBJECT *) Context;
236*29492bb7SDavid van Moolenbroek
237*29492bb7SDavid van Moolenbroek /* Parameter validation */
238*29492bb7SDavid van Moolenbroek
239*29492bb7SDavid van Moolenbroek if (!HandlerObj)
240*29492bb7SDavid van Moolenbroek {
241*29492bb7SDavid van Moolenbroek return (AE_OK);
242*29492bb7SDavid van Moolenbroek }
243*29492bb7SDavid van Moolenbroek
244*29492bb7SDavid van Moolenbroek /* Convert and validate the device handle */
245*29492bb7SDavid van Moolenbroek
246*29492bb7SDavid van Moolenbroek Node = AcpiNsValidateHandle (ObjHandle);
247*29492bb7SDavid van Moolenbroek if (!Node)
248*29492bb7SDavid van Moolenbroek {
249*29492bb7SDavid van Moolenbroek return (AE_BAD_PARAMETER);
250*29492bb7SDavid van Moolenbroek }
251*29492bb7SDavid van Moolenbroek
252*29492bb7SDavid van Moolenbroek /*
253*29492bb7SDavid van Moolenbroek * We only care about regions and objects that are allowed to have
254*29492bb7SDavid van Moolenbroek * address space handlers
255*29492bb7SDavid van Moolenbroek */
256*29492bb7SDavid van Moolenbroek if ((Node->Type != ACPI_TYPE_DEVICE) &&
257*29492bb7SDavid van Moolenbroek (Node->Type != ACPI_TYPE_REGION) &&
258*29492bb7SDavid van Moolenbroek (Node != AcpiGbl_RootNode))
259*29492bb7SDavid van Moolenbroek {
260*29492bb7SDavid van Moolenbroek return (AE_OK);
261*29492bb7SDavid van Moolenbroek }
262*29492bb7SDavid van Moolenbroek
263*29492bb7SDavid van Moolenbroek /* Check for an existing internal object */
264*29492bb7SDavid van Moolenbroek
265*29492bb7SDavid van Moolenbroek ObjDesc = AcpiNsGetAttachedObject (Node);
266*29492bb7SDavid van Moolenbroek if (!ObjDesc)
267*29492bb7SDavid van Moolenbroek {
268*29492bb7SDavid van Moolenbroek /* No object, just exit */
269*29492bb7SDavid van Moolenbroek
270*29492bb7SDavid van Moolenbroek return (AE_OK);
271*29492bb7SDavid van Moolenbroek }
272*29492bb7SDavid van Moolenbroek
273*29492bb7SDavid van Moolenbroek /* Devices are handled different than regions */
274*29492bb7SDavid van Moolenbroek
275*29492bb7SDavid van Moolenbroek if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)
276*29492bb7SDavid van Moolenbroek {
277*29492bb7SDavid van Moolenbroek /* Check if this Device already has a handler for this address space */
278*29492bb7SDavid van Moolenbroek
279*29492bb7SDavid van Moolenbroek NextHandlerObj = ObjDesc->Device.Handler;
280*29492bb7SDavid van Moolenbroek while (NextHandlerObj)
281*29492bb7SDavid van Moolenbroek {
282*29492bb7SDavid van Moolenbroek /* Found a handler, is it for the same address space? */
283*29492bb7SDavid van Moolenbroek
284*29492bb7SDavid van Moolenbroek if (NextHandlerObj->AddressSpace.SpaceId ==
285*29492bb7SDavid van Moolenbroek HandlerObj->AddressSpace.SpaceId)
286*29492bb7SDavid van Moolenbroek {
287*29492bb7SDavid van Moolenbroek ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
288*29492bb7SDavid van Moolenbroek "Found handler for region [%s] in device %p(%p) "
289*29492bb7SDavid van Moolenbroek "handler %p\n",
290*29492bb7SDavid van Moolenbroek AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
291*29492bb7SDavid van Moolenbroek ObjDesc, NextHandlerObj, HandlerObj));
292*29492bb7SDavid van Moolenbroek
293*29492bb7SDavid van Moolenbroek /*
294*29492bb7SDavid van Moolenbroek * Since the object we found it on was a device, then it
295*29492bb7SDavid van Moolenbroek * means that someone has already installed a handler for
296*29492bb7SDavid van Moolenbroek * the branch of the namespace from this device on. Just
297*29492bb7SDavid van Moolenbroek * bail out telling the walk routine to not traverse this
298*29492bb7SDavid van Moolenbroek * branch. This preserves the scoping rule for handlers.
299*29492bb7SDavid van Moolenbroek */
300*29492bb7SDavid van Moolenbroek return (AE_CTRL_DEPTH);
301*29492bb7SDavid van Moolenbroek }
302*29492bb7SDavid van Moolenbroek
303*29492bb7SDavid van Moolenbroek /* Walk the linked list of handlers attached to this device */
304*29492bb7SDavid van Moolenbroek
305*29492bb7SDavid van Moolenbroek NextHandlerObj = NextHandlerObj->AddressSpace.Next;
306*29492bb7SDavid van Moolenbroek }
307*29492bb7SDavid van Moolenbroek
308*29492bb7SDavid van Moolenbroek /*
309*29492bb7SDavid van Moolenbroek * As long as the device didn't have a handler for this space we
310*29492bb7SDavid van Moolenbroek * don't care about it. We just ignore it and proceed.
311*29492bb7SDavid van Moolenbroek */
312*29492bb7SDavid van Moolenbroek return (AE_OK);
313*29492bb7SDavid van Moolenbroek }
314*29492bb7SDavid van Moolenbroek
315*29492bb7SDavid van Moolenbroek /* Object is a Region */
316*29492bb7SDavid van Moolenbroek
317*29492bb7SDavid van Moolenbroek if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
318*29492bb7SDavid van Moolenbroek {
319*29492bb7SDavid van Moolenbroek /* This region is for a different address space, just ignore it */
320*29492bb7SDavid van Moolenbroek
321*29492bb7SDavid van Moolenbroek return (AE_OK);
322*29492bb7SDavid van Moolenbroek }
323*29492bb7SDavid van Moolenbroek
324*29492bb7SDavid van Moolenbroek /*
325*29492bb7SDavid van Moolenbroek * Now we have a region and it is for the handler's address space type.
326*29492bb7SDavid van Moolenbroek *
327*29492bb7SDavid van Moolenbroek * First disconnect region for any previous handler (if any)
328*29492bb7SDavid van Moolenbroek */
329*29492bb7SDavid van Moolenbroek AcpiEvDetachRegion (ObjDesc, FALSE);
330*29492bb7SDavid van Moolenbroek
331*29492bb7SDavid van Moolenbroek /* Connect the region to the new handler */
332*29492bb7SDavid van Moolenbroek
333*29492bb7SDavid van Moolenbroek Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
334*29492bb7SDavid van Moolenbroek return (Status);
335*29492bb7SDavid van Moolenbroek }
336*29492bb7SDavid van Moolenbroek
337*29492bb7SDavid van Moolenbroek
338*29492bb7SDavid van Moolenbroek /*******************************************************************************
339*29492bb7SDavid van Moolenbroek *
340*29492bb7SDavid van Moolenbroek * FUNCTION: AcpiEvInstallSpaceHandler
341*29492bb7SDavid van Moolenbroek *
342*29492bb7SDavid van Moolenbroek * PARAMETERS: Node - Namespace node for the device
343*29492bb7SDavid van Moolenbroek * SpaceId - The address space ID
344*29492bb7SDavid van Moolenbroek * Handler - Address of the handler
345*29492bb7SDavid van Moolenbroek * Setup - Address of the setup function
346*29492bb7SDavid van Moolenbroek * Context - Value passed to the handler on each access
347*29492bb7SDavid van Moolenbroek *
348*29492bb7SDavid van Moolenbroek * RETURN: Status
349*29492bb7SDavid van Moolenbroek *
350*29492bb7SDavid van Moolenbroek * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
351*29492bb7SDavid van Moolenbroek * Assumes namespace is locked
352*29492bb7SDavid van Moolenbroek *
353*29492bb7SDavid van Moolenbroek ******************************************************************************/
354*29492bb7SDavid van Moolenbroek
355*29492bb7SDavid van Moolenbroek ACPI_STATUS
AcpiEvInstallSpaceHandler(ACPI_NAMESPACE_NODE * Node,ACPI_ADR_SPACE_TYPE SpaceId,ACPI_ADR_SPACE_HANDLER Handler,ACPI_ADR_SPACE_SETUP Setup,void * Context)356*29492bb7SDavid van Moolenbroek AcpiEvInstallSpaceHandler (
357*29492bb7SDavid van Moolenbroek ACPI_NAMESPACE_NODE *Node,
358*29492bb7SDavid van Moolenbroek ACPI_ADR_SPACE_TYPE SpaceId,
359*29492bb7SDavid van Moolenbroek ACPI_ADR_SPACE_HANDLER Handler,
360*29492bb7SDavid van Moolenbroek ACPI_ADR_SPACE_SETUP Setup,
361*29492bb7SDavid van Moolenbroek void *Context)
362*29492bb7SDavid van Moolenbroek {
363*29492bb7SDavid van Moolenbroek ACPI_OPERAND_OBJECT *ObjDesc;
364*29492bb7SDavid van Moolenbroek ACPI_OPERAND_OBJECT *HandlerObj;
365*29492bb7SDavid van Moolenbroek ACPI_STATUS Status;
366*29492bb7SDavid van Moolenbroek ACPI_OBJECT_TYPE Type;
367*29492bb7SDavid van Moolenbroek UINT8 Flags = 0;
368*29492bb7SDavid van Moolenbroek
369*29492bb7SDavid van Moolenbroek
370*29492bb7SDavid van Moolenbroek ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
371*29492bb7SDavid van Moolenbroek
372*29492bb7SDavid van Moolenbroek
373*29492bb7SDavid van Moolenbroek /*
374*29492bb7SDavid van Moolenbroek * This registration is valid for only the types below and the root. This
375*29492bb7SDavid van Moolenbroek * is where the default handlers get placed.
376*29492bb7SDavid van Moolenbroek */
377*29492bb7SDavid van Moolenbroek if ((Node->Type != ACPI_TYPE_DEVICE) &&
378*29492bb7SDavid van Moolenbroek (Node->Type != ACPI_TYPE_PROCESSOR) &&
379*29492bb7SDavid van Moolenbroek (Node->Type != ACPI_TYPE_THERMAL) &&
380*29492bb7SDavid van Moolenbroek (Node != AcpiGbl_RootNode))
381*29492bb7SDavid van Moolenbroek {
382*29492bb7SDavid van Moolenbroek Status = AE_BAD_PARAMETER;
383*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
384*29492bb7SDavid van Moolenbroek }
385*29492bb7SDavid van Moolenbroek
386*29492bb7SDavid van Moolenbroek if (Handler == ACPI_DEFAULT_HANDLER)
387*29492bb7SDavid van Moolenbroek {
388*29492bb7SDavid van Moolenbroek Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
389*29492bb7SDavid van Moolenbroek
390*29492bb7SDavid van Moolenbroek switch (SpaceId)
391*29492bb7SDavid van Moolenbroek {
392*29492bb7SDavid van Moolenbroek case ACPI_ADR_SPACE_SYSTEM_MEMORY:
393*29492bb7SDavid van Moolenbroek
394*29492bb7SDavid van Moolenbroek Handler = AcpiExSystemMemorySpaceHandler;
395*29492bb7SDavid van Moolenbroek Setup = AcpiEvSystemMemoryRegionSetup;
396*29492bb7SDavid van Moolenbroek break;
397*29492bb7SDavid van Moolenbroek
398*29492bb7SDavid van Moolenbroek case ACPI_ADR_SPACE_SYSTEM_IO:
399*29492bb7SDavid van Moolenbroek
400*29492bb7SDavid van Moolenbroek Handler = AcpiExSystemIoSpaceHandler;
401*29492bb7SDavid van Moolenbroek Setup = AcpiEvIoSpaceRegionSetup;
402*29492bb7SDavid van Moolenbroek break;
403*29492bb7SDavid van Moolenbroek
404*29492bb7SDavid van Moolenbroek case ACPI_ADR_SPACE_PCI_CONFIG:
405*29492bb7SDavid van Moolenbroek
406*29492bb7SDavid van Moolenbroek Handler = AcpiExPciConfigSpaceHandler;
407*29492bb7SDavid van Moolenbroek Setup = AcpiEvPciConfigRegionSetup;
408*29492bb7SDavid van Moolenbroek break;
409*29492bb7SDavid van Moolenbroek
410*29492bb7SDavid van Moolenbroek case ACPI_ADR_SPACE_CMOS:
411*29492bb7SDavid van Moolenbroek
412*29492bb7SDavid van Moolenbroek Handler = AcpiExCmosSpaceHandler;
413*29492bb7SDavid van Moolenbroek Setup = AcpiEvCmosRegionSetup;
414*29492bb7SDavid van Moolenbroek break;
415*29492bb7SDavid van Moolenbroek
416*29492bb7SDavid van Moolenbroek case ACPI_ADR_SPACE_PCI_BAR_TARGET:
417*29492bb7SDavid van Moolenbroek
418*29492bb7SDavid van Moolenbroek Handler = AcpiExPciBarSpaceHandler;
419*29492bb7SDavid van Moolenbroek Setup = AcpiEvPciBarRegionSetup;
420*29492bb7SDavid van Moolenbroek break;
421*29492bb7SDavid van Moolenbroek
422*29492bb7SDavid van Moolenbroek case ACPI_ADR_SPACE_DATA_TABLE:
423*29492bb7SDavid van Moolenbroek
424*29492bb7SDavid van Moolenbroek Handler = AcpiExDataTableSpaceHandler;
425*29492bb7SDavid van Moolenbroek Setup = NULL;
426*29492bb7SDavid van Moolenbroek break;
427*29492bb7SDavid van Moolenbroek
428*29492bb7SDavid van Moolenbroek default:
429*29492bb7SDavid van Moolenbroek
430*29492bb7SDavid van Moolenbroek Status = AE_BAD_PARAMETER;
431*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
432*29492bb7SDavid van Moolenbroek }
433*29492bb7SDavid van Moolenbroek }
434*29492bb7SDavid van Moolenbroek
435*29492bb7SDavid van Moolenbroek /* If the caller hasn't specified a setup routine, use the default */
436*29492bb7SDavid van Moolenbroek
437*29492bb7SDavid van Moolenbroek if (!Setup)
438*29492bb7SDavid van Moolenbroek {
439*29492bb7SDavid van Moolenbroek Setup = AcpiEvDefaultRegionSetup;
440*29492bb7SDavid van Moolenbroek }
441*29492bb7SDavid van Moolenbroek
442*29492bb7SDavid van Moolenbroek /* Check for an existing internal object */
443*29492bb7SDavid van Moolenbroek
444*29492bb7SDavid van Moolenbroek ObjDesc = AcpiNsGetAttachedObject (Node);
445*29492bb7SDavid van Moolenbroek if (ObjDesc)
446*29492bb7SDavid van Moolenbroek {
447*29492bb7SDavid van Moolenbroek /*
448*29492bb7SDavid van Moolenbroek * The attached device object already exists. Make sure the handler
449*29492bb7SDavid van Moolenbroek * is not already installed.
450*29492bb7SDavid van Moolenbroek */
451*29492bb7SDavid van Moolenbroek HandlerObj = ObjDesc->Device.Handler;
452*29492bb7SDavid van Moolenbroek
453*29492bb7SDavid van Moolenbroek /* Walk the handler list for this device */
454*29492bb7SDavid van Moolenbroek
455*29492bb7SDavid van Moolenbroek while (HandlerObj)
456*29492bb7SDavid van Moolenbroek {
457*29492bb7SDavid van Moolenbroek /* Same SpaceId indicates a handler already installed */
458*29492bb7SDavid van Moolenbroek
459*29492bb7SDavid van Moolenbroek if (HandlerObj->AddressSpace.SpaceId == SpaceId)
460*29492bb7SDavid van Moolenbroek {
461*29492bb7SDavid van Moolenbroek if (HandlerObj->AddressSpace.Handler == Handler)
462*29492bb7SDavid van Moolenbroek {
463*29492bb7SDavid van Moolenbroek /*
464*29492bb7SDavid van Moolenbroek * It is (relatively) OK to attempt to install the SAME
465*29492bb7SDavid van Moolenbroek * handler twice. This can easily happen with the
466*29492bb7SDavid van Moolenbroek * PCI_Config space.
467*29492bb7SDavid van Moolenbroek */
468*29492bb7SDavid van Moolenbroek Status = AE_SAME_HANDLER;
469*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
470*29492bb7SDavid van Moolenbroek }
471*29492bb7SDavid van Moolenbroek else
472*29492bb7SDavid van Moolenbroek {
473*29492bb7SDavid van Moolenbroek /* A handler is already installed */
474*29492bb7SDavid van Moolenbroek
475*29492bb7SDavid van Moolenbroek Status = AE_ALREADY_EXISTS;
476*29492bb7SDavid van Moolenbroek }
477*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
478*29492bb7SDavid van Moolenbroek }
479*29492bb7SDavid van Moolenbroek
480*29492bb7SDavid van Moolenbroek /* Walk the linked list of handlers */
481*29492bb7SDavid van Moolenbroek
482*29492bb7SDavid van Moolenbroek HandlerObj = HandlerObj->AddressSpace.Next;
483*29492bb7SDavid van Moolenbroek }
484*29492bb7SDavid van Moolenbroek }
485*29492bb7SDavid van Moolenbroek else
486*29492bb7SDavid van Moolenbroek {
487*29492bb7SDavid van Moolenbroek ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
488*29492bb7SDavid van Moolenbroek "Creating object on Device %p while installing handler\n", Node));
489*29492bb7SDavid van Moolenbroek
490*29492bb7SDavid van Moolenbroek /* ObjDesc does not exist, create one */
491*29492bb7SDavid van Moolenbroek
492*29492bb7SDavid van Moolenbroek if (Node->Type == ACPI_TYPE_ANY)
493*29492bb7SDavid van Moolenbroek {
494*29492bb7SDavid van Moolenbroek Type = ACPI_TYPE_DEVICE;
495*29492bb7SDavid van Moolenbroek }
496*29492bb7SDavid van Moolenbroek else
497*29492bb7SDavid van Moolenbroek {
498*29492bb7SDavid van Moolenbroek Type = Node->Type;
499*29492bb7SDavid van Moolenbroek }
500*29492bb7SDavid van Moolenbroek
501*29492bb7SDavid van Moolenbroek ObjDesc = AcpiUtCreateInternalObject (Type);
502*29492bb7SDavid van Moolenbroek if (!ObjDesc)
503*29492bb7SDavid van Moolenbroek {
504*29492bb7SDavid van Moolenbroek Status = AE_NO_MEMORY;
505*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
506*29492bb7SDavid van Moolenbroek }
507*29492bb7SDavid van Moolenbroek
508*29492bb7SDavid van Moolenbroek /* Init new descriptor */
509*29492bb7SDavid van Moolenbroek
510*29492bb7SDavid van Moolenbroek ObjDesc->Common.Type = (UINT8) Type;
511*29492bb7SDavid van Moolenbroek
512*29492bb7SDavid van Moolenbroek /* Attach the new object to the Node */
513*29492bb7SDavid van Moolenbroek
514*29492bb7SDavid van Moolenbroek Status = AcpiNsAttachObject (Node, ObjDesc, Type);
515*29492bb7SDavid van Moolenbroek
516*29492bb7SDavid van Moolenbroek /* Remove local reference to the object */
517*29492bb7SDavid van Moolenbroek
518*29492bb7SDavid van Moolenbroek AcpiUtRemoveReference (ObjDesc);
519*29492bb7SDavid van Moolenbroek
520*29492bb7SDavid van Moolenbroek if (ACPI_FAILURE (Status))
521*29492bb7SDavid van Moolenbroek {
522*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
523*29492bb7SDavid van Moolenbroek }
524*29492bb7SDavid van Moolenbroek }
525*29492bb7SDavid van Moolenbroek
526*29492bb7SDavid van Moolenbroek ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
527*29492bb7SDavid van Moolenbroek "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
528*29492bb7SDavid van Moolenbroek AcpiUtGetRegionName (SpaceId), SpaceId,
529*29492bb7SDavid van Moolenbroek AcpiUtGetNodeName (Node), Node, ObjDesc));
530*29492bb7SDavid van Moolenbroek
531*29492bb7SDavid van Moolenbroek /*
532*29492bb7SDavid van Moolenbroek * Install the handler
533*29492bb7SDavid van Moolenbroek *
534*29492bb7SDavid van Moolenbroek * At this point there is no existing handler. Just allocate the object
535*29492bb7SDavid van Moolenbroek * for the handler and link it into the list.
536*29492bb7SDavid van Moolenbroek */
537*29492bb7SDavid van Moolenbroek HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
538*29492bb7SDavid van Moolenbroek if (!HandlerObj)
539*29492bb7SDavid van Moolenbroek {
540*29492bb7SDavid van Moolenbroek Status = AE_NO_MEMORY;
541*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
542*29492bb7SDavid van Moolenbroek }
543*29492bb7SDavid van Moolenbroek
544*29492bb7SDavid van Moolenbroek /* Init handler obj */
545*29492bb7SDavid van Moolenbroek
546*29492bb7SDavid van Moolenbroek HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
547*29492bb7SDavid van Moolenbroek HandlerObj->AddressSpace.HandlerFlags = Flags;
548*29492bb7SDavid van Moolenbroek HandlerObj->AddressSpace.RegionList = NULL;
549*29492bb7SDavid van Moolenbroek HandlerObj->AddressSpace.Node = Node;
550*29492bb7SDavid van Moolenbroek HandlerObj->AddressSpace.Handler = Handler;
551*29492bb7SDavid van Moolenbroek HandlerObj->AddressSpace.Context = Context;
552*29492bb7SDavid van Moolenbroek HandlerObj->AddressSpace.Setup = Setup;
553*29492bb7SDavid van Moolenbroek
554*29492bb7SDavid van Moolenbroek /* Install at head of Device.AddressSpace list */
555*29492bb7SDavid van Moolenbroek
556*29492bb7SDavid van Moolenbroek HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler;
557*29492bb7SDavid van Moolenbroek
558*29492bb7SDavid van Moolenbroek /*
559*29492bb7SDavid van Moolenbroek * The Device object is the first reference on the HandlerObj.
560*29492bb7SDavid van Moolenbroek * Each region that uses the handler adds a reference.
561*29492bb7SDavid van Moolenbroek */
562*29492bb7SDavid van Moolenbroek ObjDesc->Device.Handler = HandlerObj;
563*29492bb7SDavid van Moolenbroek
564*29492bb7SDavid van Moolenbroek /*
565*29492bb7SDavid van Moolenbroek * Walk the namespace finding all of the regions this
566*29492bb7SDavid van Moolenbroek * handler will manage.
567*29492bb7SDavid van Moolenbroek *
568*29492bb7SDavid van Moolenbroek * Start at the device and search the branch toward
569*29492bb7SDavid van Moolenbroek * the leaf nodes until either the leaf is encountered or
570*29492bb7SDavid van Moolenbroek * a device is detected that has an address handler of the
571*29492bb7SDavid van Moolenbroek * same type.
572*29492bb7SDavid van Moolenbroek *
573*29492bb7SDavid van Moolenbroek * In either case, back up and search down the remainder
574*29492bb7SDavid van Moolenbroek * of the branch
575*29492bb7SDavid van Moolenbroek */
576*29492bb7SDavid van Moolenbroek Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
577*29492bb7SDavid van Moolenbroek ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL,
578*29492bb7SDavid van Moolenbroek HandlerObj, NULL);
579*29492bb7SDavid van Moolenbroek
580*29492bb7SDavid van Moolenbroek UnlockAndExit:
581*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (Status);
582*29492bb7SDavid van Moolenbroek }
583