1 /******************************************************************************
3 * Module Name: evhandler - Support for Address Space handlers
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2016, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
50 #define _COMPONENT ACPI_EVENTS
51 ACPI_MODULE_NAME ("evhandler")
54 /* Local prototypes */
57 AcpiEvInstallHandler (
58 ACPI_HANDLE ObjHandle
,
64 /* These are the address spaces that will get default handlers */
66 UINT8 AcpiGbl_DefaultAddressSpaces
[ACPI_NUM_DEFAULT_SPACES
] =
68 ACPI_ADR_SPACE_SYSTEM_MEMORY
,
69 ACPI_ADR_SPACE_SYSTEM_IO
,
70 ACPI_ADR_SPACE_PCI_CONFIG
,
71 ACPI_ADR_SPACE_DATA_TABLE
75 /*******************************************************************************
77 * FUNCTION: AcpiEvInstallRegionHandlers
83 * DESCRIPTION: Installs the core subsystem default address space handlers.
85 ******************************************************************************/
88 AcpiEvInstallRegionHandlers (
95 ACPI_FUNCTION_TRACE (EvInstallRegionHandlers
);
98 Status
= AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE
);
99 if (ACPI_FAILURE (Status
))
101 return_ACPI_STATUS (Status
);
105 * All address spaces (PCI Config, EC, SMBus) are scope dependent and
106 * registration must occur for a specific device.
108 * In the case of the system memory and IO address spaces there is
109 * currently no device associated with the address space. For these we
112 * We install the default PCI config space handler at the root so that
113 * this space is immediately available even though the we have not
114 * enumerated all the PCI Root Buses yet. This is to conform to the ACPI
115 * specification which states that the PCI config space must be always
116 * available -- even though we are nowhere near ready to find the PCI root
117 * buses at this point.
119 * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
120 * has already been installed (via AcpiInstallAddressSpaceHandler).
121 * Similar for AE_SAME_HANDLER.
123 for (i
= 0; i
< ACPI_NUM_DEFAULT_SPACES
; i
++)
125 Status
= AcpiEvInstallSpaceHandler (AcpiGbl_RootNode
,
126 AcpiGbl_DefaultAddressSpaces
[i
],
127 ACPI_DEFAULT_HANDLER
, NULL
, NULL
);
131 case AE_SAME_HANDLER
:
132 case AE_ALREADY_EXISTS
:
134 /* These exceptions are all OK */
146 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE
);
147 return_ACPI_STATUS (Status
);
151 /*******************************************************************************
153 * FUNCTION: AcpiEvHasDefaultHandler
155 * PARAMETERS: Node - Namespace node for the device
156 * SpaceId - The address space ID
158 * RETURN: TRUE if default handler is installed, FALSE otherwise
160 * DESCRIPTION: Check if the default handler is installed for the requested
163 ******************************************************************************/
166 AcpiEvHasDefaultHandler (
167 ACPI_NAMESPACE_NODE
*Node
,
168 ACPI_ADR_SPACE_TYPE SpaceId
)
170 ACPI_OPERAND_OBJECT
*ObjDesc
;
171 ACPI_OPERAND_OBJECT
*HandlerObj
;
174 /* Must have an existing internal object */
176 ObjDesc
= AcpiNsGetAttachedObject (Node
);
179 HandlerObj
= ObjDesc
->CommonNotify
.Handler
;
181 /* Walk the linked list of handlers for this object */
185 if (HandlerObj
->AddressSpace
.SpaceId
== SpaceId
)
187 if (HandlerObj
->AddressSpace
.HandlerFlags
&
188 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED
)
194 HandlerObj
= HandlerObj
->AddressSpace
.Next
;
202 /*******************************************************************************
204 * FUNCTION: AcpiEvInstallHandler
206 * PARAMETERS: WalkNamespace callback
208 * DESCRIPTION: This routine installs an address handler into objects that are
209 * of type Region or Device.
211 * If the Object is a Device, and the device has a handler of
212 * the same type then the search is terminated in that branch.
214 * This is because the existing handler is closer in proximity
215 * to any more regions than the one we are trying to install.
217 ******************************************************************************/
220 AcpiEvInstallHandler (
221 ACPI_HANDLE ObjHandle
,
226 ACPI_OPERAND_OBJECT
*HandlerObj
;
227 ACPI_OPERAND_OBJECT
*NextHandlerObj
;
228 ACPI_OPERAND_OBJECT
*ObjDesc
;
229 ACPI_NAMESPACE_NODE
*Node
;
233 ACPI_FUNCTION_NAME (EvInstallHandler
);
236 HandlerObj
= (ACPI_OPERAND_OBJECT
*) Context
;
238 /* Parameter validation */
245 /* Convert and validate the device handle */
247 Node
= AcpiNsValidateHandle (ObjHandle
);
250 return (AE_BAD_PARAMETER
);
254 * We only care about regions and objects that are allowed to have
255 * address space handlers
257 if ((Node
->Type
!= ACPI_TYPE_DEVICE
) &&
258 (Node
->Type
!= ACPI_TYPE_REGION
) &&
259 (Node
!= AcpiGbl_RootNode
))
264 /* Check for an existing internal object */
266 ObjDesc
= AcpiNsGetAttachedObject (Node
);
269 /* No object, just exit */
274 /* Devices are handled different than regions */
276 if (ObjDesc
->Common
.Type
== ACPI_TYPE_DEVICE
)
278 /* Check if this Device already has a handler for this address space */
280 NextHandlerObj
= AcpiEvFindRegionHandler (
281 HandlerObj
->AddressSpace
.SpaceId
, ObjDesc
->CommonNotify
.Handler
);
284 /* Found a handler, is it for the same address space? */
286 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION
,
287 "Found handler for region [%s] in device %p(%p) handler %p\n",
288 AcpiUtGetRegionName (HandlerObj
->AddressSpace
.SpaceId
),
289 ObjDesc
, NextHandlerObj
, HandlerObj
));
292 * Since the object we found it on was a device, then it means
293 * that someone has already installed a handler for the branch
294 * of the namespace from this device on. Just bail out telling
295 * the walk routine to not traverse this branch. This preserves
296 * the scoping rule for handlers.
298 return (AE_CTRL_DEPTH
);
302 * As long as the device didn't have a handler for this space we
303 * don't care about it. We just ignore it and proceed.
308 /* Object is a Region */
310 if (ObjDesc
->Region
.SpaceId
!= HandlerObj
->AddressSpace
.SpaceId
)
312 /* This region is for a different address space, just ignore it */
318 * Now we have a region and it is for the handler's address space type.
320 * First disconnect region for any previous handler (if any)
322 AcpiEvDetachRegion (ObjDesc
, FALSE
);
324 /* Connect the region to the new handler */
326 Status
= AcpiEvAttachRegion (HandlerObj
, ObjDesc
, FALSE
);
331 /*******************************************************************************
333 * FUNCTION: AcpiEvFindRegionHandler
335 * PARAMETERS: SpaceId - The address space ID
336 * HandlerObj - Head of the handler object list
338 * RETURN: Matching handler object. NULL if space ID not matched
340 * DESCRIPTION: Search a handler object list for a match on the address
343 ******************************************************************************/
345 ACPI_OPERAND_OBJECT
*
346 AcpiEvFindRegionHandler (
347 ACPI_ADR_SPACE_TYPE SpaceId
,
348 ACPI_OPERAND_OBJECT
*HandlerObj
)
351 /* Walk the handler list for this device */
355 /* Same SpaceId indicates a handler is installed */
357 if (HandlerObj
->AddressSpace
.SpaceId
== SpaceId
)
362 /* Next handler object */
364 HandlerObj
= HandlerObj
->AddressSpace
.Next
;
371 /*******************************************************************************
373 * FUNCTION: AcpiEvInstallSpaceHandler
375 * PARAMETERS: Node - Namespace node for the device
376 * SpaceId - The address space ID
377 * Handler - Address of the handler
378 * Setup - Address of the setup function
379 * Context - Value passed to the handler on each access
383 * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
384 * Assumes namespace is locked
386 ******************************************************************************/
389 AcpiEvInstallSpaceHandler (
390 ACPI_NAMESPACE_NODE
*Node
,
391 ACPI_ADR_SPACE_TYPE SpaceId
,
392 ACPI_ADR_SPACE_HANDLER Handler
,
393 ACPI_ADR_SPACE_SETUP Setup
,
396 ACPI_OPERAND_OBJECT
*ObjDesc
;
397 ACPI_OPERAND_OBJECT
*HandlerObj
;
398 ACPI_STATUS Status
= AE_OK
;
399 ACPI_OBJECT_TYPE Type
;
403 ACPI_FUNCTION_TRACE (EvInstallSpaceHandler
);
407 * This registration is valid for only the types below and the root.
408 * The root node is where the default handlers get installed.
410 if ((Node
->Type
!= ACPI_TYPE_DEVICE
) &&
411 (Node
->Type
!= ACPI_TYPE_PROCESSOR
) &&
412 (Node
->Type
!= ACPI_TYPE_THERMAL
) &&
413 (Node
!= AcpiGbl_RootNode
))
415 Status
= AE_BAD_PARAMETER
;
419 if (Handler
== ACPI_DEFAULT_HANDLER
)
421 Flags
= ACPI_ADDR_HANDLER_DEFAULT_INSTALLED
;
425 case ACPI_ADR_SPACE_SYSTEM_MEMORY
:
427 Handler
= AcpiExSystemMemorySpaceHandler
;
428 Setup
= AcpiEvSystemMemoryRegionSetup
;
431 case ACPI_ADR_SPACE_SYSTEM_IO
:
433 Handler
= AcpiExSystemIoSpaceHandler
;
434 Setup
= AcpiEvIoSpaceRegionSetup
;
437 case ACPI_ADR_SPACE_PCI_CONFIG
:
439 Handler
= AcpiExPciConfigSpaceHandler
;
440 Setup
= AcpiEvPciConfigRegionSetup
;
443 case ACPI_ADR_SPACE_CMOS
:
445 Handler
= AcpiExCmosSpaceHandler
;
446 Setup
= AcpiEvCmosRegionSetup
;
449 case ACPI_ADR_SPACE_PCI_BAR_TARGET
:
451 Handler
= AcpiExPciBarSpaceHandler
;
452 Setup
= AcpiEvPciBarRegionSetup
;
455 case ACPI_ADR_SPACE_DATA_TABLE
:
457 Handler
= AcpiExDataTableSpaceHandler
;
463 Status
= AE_BAD_PARAMETER
;
468 /* If the caller hasn't specified a setup routine, use the default */
472 Setup
= AcpiEvDefaultRegionSetup
;
475 /* Check for an existing internal object */
477 ObjDesc
= AcpiNsGetAttachedObject (Node
);
481 * The attached device object already exists. Now make sure
482 * the handler is not already installed.
484 HandlerObj
= AcpiEvFindRegionHandler (SpaceId
,
485 ObjDesc
->CommonNotify
.Handler
);
489 if (HandlerObj
->AddressSpace
.Handler
== Handler
)
492 * It is (relatively) OK to attempt to install the SAME
493 * handler twice. This can easily happen with the
496 Status
= AE_SAME_HANDLER
;
501 /* A handler is already installed */
503 Status
= AE_ALREADY_EXISTS
;
511 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION
,
512 "Creating object on Device %p while installing handler\n",
515 /* ObjDesc does not exist, create one */
517 if (Node
->Type
== ACPI_TYPE_ANY
)
519 Type
= ACPI_TYPE_DEVICE
;
526 ObjDesc
= AcpiUtCreateInternalObject (Type
);
529 Status
= AE_NO_MEMORY
;
533 /* Init new descriptor */
535 ObjDesc
->Common
.Type
= (UINT8
) Type
;
537 /* Attach the new object to the Node */
539 Status
= AcpiNsAttachObject (Node
, ObjDesc
, Type
);
541 /* Remove local reference to the object */
543 AcpiUtRemoveReference (ObjDesc
);
545 if (ACPI_FAILURE (Status
))
551 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION
,
552 "Installing address handler for region %s(%X) "
553 "on Device %4.4s %p(%p)\n",
554 AcpiUtGetRegionName (SpaceId
), SpaceId
,
555 AcpiUtGetNodeName (Node
), Node
, ObjDesc
));
558 * Install the handler
560 * At this point there is no existing handler. Just allocate the object
561 * for the handler and link it into the list.
563 HandlerObj
= AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER
);
566 Status
= AE_NO_MEMORY
;
570 /* Init handler obj */
572 HandlerObj
->AddressSpace
.SpaceId
= (UINT8
) SpaceId
;
573 HandlerObj
->AddressSpace
.HandlerFlags
= Flags
;
574 HandlerObj
->AddressSpace
.RegionList
= NULL
;
575 HandlerObj
->AddressSpace
.Node
= Node
;
576 HandlerObj
->AddressSpace
.Handler
= Handler
;
577 HandlerObj
->AddressSpace
.Context
= Context
;
578 HandlerObj
->AddressSpace
.Setup
= Setup
;
580 /* Install at head of Device.AddressSpace list */
582 HandlerObj
->AddressSpace
.Next
= ObjDesc
->CommonNotify
.Handler
;
585 * The Device object is the first reference on the HandlerObj.
586 * Each region that uses the handler adds a reference.
588 ObjDesc
->CommonNotify
.Handler
= HandlerObj
;
591 * Walk the namespace finding all of the regions this handler will
594 * Start at the device and search the branch toward the leaf nodes
595 * until either the leaf is encountered or a device is detected that
596 * has an address handler of the same type.
598 * In either case, back up and search down the remainder of the branch
600 Status
= AcpiNsWalkNamespace (ACPI_TYPE_ANY
, Node
,
601 ACPI_UINT32_MAX
, ACPI_NS_WALK_UNLOCK
,
602 AcpiEvInstallHandler
, NULL
, HandlerObj
, NULL
);
605 return_ACPI_STATUS (Status
);