linux/drivers/acpi/events/evregion.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Module Name: evregion - ACPI address_space (op_region) handler dispatch
   4 *
   5 *****************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2008, Intel Corp.
   9 * All rights reserved.
  10 *
  11 * Redistribution and use in source and binary forms, with or without
  12 * modification, are permitted provided that the following conditions
  13 * are met:
  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.
  25 *
  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.
  29 *
  30 * NO WARRANTY
  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.
  42 */
  43
  44#include <acpi/acpi.h>
  45#include <acpi/acevents.h>
  46#include <acpi/acnamesp.h>
  47#include <acpi/acinterp.h>
  48
  49#define _COMPONENT          ACPI_EVENTS
  50ACPI_MODULE_NAME("evregion")
  51#define ACPI_NUM_DEFAULT_SPACES     4
  52static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = {
  53        ACPI_ADR_SPACE_SYSTEM_MEMORY,
  54        ACPI_ADR_SPACE_SYSTEM_IO,
  55        ACPI_ADR_SPACE_PCI_CONFIG,
  56        ACPI_ADR_SPACE_DATA_TABLE
  57};
  58
  59/* Local prototypes */
  60
  61static acpi_status
  62acpi_ev_reg_run(acpi_handle obj_handle,
  63                u32 level, void *context, void **return_value);
  64
  65static acpi_status
  66acpi_ev_install_handler(acpi_handle obj_handle,
  67                        u32 level, void *context, void **return_value);
  68
  69/*******************************************************************************
  70 *
  71 * FUNCTION:    acpi_ev_install_region_handlers
  72 *
  73 * PARAMETERS:  None
  74 *
  75 * RETURN:      Status
  76 *
  77 * DESCRIPTION: Installs the core subsystem default address space handlers.
  78 *
  79 ******************************************************************************/
  80
  81acpi_status acpi_ev_install_region_handlers(void)
  82{
  83        acpi_status status;
  84        u32 i;
  85
  86        ACPI_FUNCTION_TRACE(ev_install_region_handlers);
  87
  88        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  89        if (ACPI_FAILURE(status)) {
  90                return_ACPI_STATUS(status);
  91        }
  92
  93        /*
  94         * All address spaces (PCI Config, EC, SMBus) are scope dependent
  95         * and registration must occur for a specific device.
  96         *
  97         * In the case of the system memory and IO address spaces there is currently
  98         * no device associated with the address space.  For these we use the root.
  99         *
 100         * We install the default PCI config space handler at the root so
 101         * that this space is immediately available even though the we have
 102         * not enumerated all the PCI Root Buses yet.  This is to conform
 103         * to the ACPI specification which states that the PCI config
 104         * space must be always available -- even though we are nowhere
 105         * near ready to find the PCI root buses at this point.
 106         *
 107         * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
 108         * has already been installed (via acpi_install_address_space_handler).
 109         * Similar for AE_SAME_HANDLER.
 110         */
 111        for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
 112                status = acpi_ev_install_space_handler(acpi_gbl_root_node,
 113                                                       acpi_gbl_default_address_spaces
 114                                                       [i],
 115                                                       ACPI_DEFAULT_HANDLER,
 116                                                       NULL, NULL);
 117                switch (status) {
 118                case AE_OK:
 119                case AE_SAME_HANDLER:
 120                case AE_ALREADY_EXISTS:
 121
 122                        /* These exceptions are all OK */
 123
 124                        status = AE_OK;
 125                        break;
 126
 127                default:
 128
 129                        goto unlock_and_exit;
 130                }
 131        }
 132
 133      unlock_and_exit:
 134        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 135        return_ACPI_STATUS(status);
 136}
 137
 138/*******************************************************************************
 139 *
 140 * FUNCTION:    acpi_ev_initialize_op_regions
 141 *
 142 * PARAMETERS:  None
 143 *
 144 * RETURN:      Status
 145 *
 146 * DESCRIPTION: Execute _REG methods for all Operation Regions that have
 147 *              an installed default region handler.
 148 *
 149 ******************************************************************************/
 150
 151acpi_status acpi_ev_initialize_op_regions(void)
 152{
 153        acpi_status status;
 154        u32 i;
 155
 156        ACPI_FUNCTION_TRACE(ev_initialize_op_regions);
 157
 158        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 159        if (ACPI_FAILURE(status)) {
 160                return_ACPI_STATUS(status);
 161        }
 162
 163        /*
 164         * Run the _REG methods for op_regions in each default address space
 165         */
 166        for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
 167
 168                /* TBD: Make sure handler is the DEFAULT handler, otherwise
 169                 * _REG will have already been run.
 170                 */
 171                status = acpi_ev_execute_reg_methods(acpi_gbl_root_node,
 172                                                     acpi_gbl_default_address_spaces
 173                                                     [i]);
 174        }
 175
 176        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 177        return_ACPI_STATUS(status);
 178}
 179
 180/*******************************************************************************
 181 *
 182 * FUNCTION:    acpi_ev_execute_reg_method
 183 *
 184 * PARAMETERS:  region_obj          - Region object
 185 *              Function            - Passed to _REG: On (1) or Off (0)
 186 *
 187 * RETURN:      Status
 188 *
 189 * DESCRIPTION: Execute _REG method for a region
 190 *
 191 ******************************************************************************/
 192
 193acpi_status
 194acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
 195{
 196        struct acpi_evaluate_info *info;
 197        union acpi_operand_object *args[3];
 198        union acpi_operand_object *region_obj2;
 199        acpi_status status;
 200
 201        ACPI_FUNCTION_TRACE(ev_execute_reg_method);
 202
 203        region_obj2 = acpi_ns_get_secondary_object(region_obj);
 204        if (!region_obj2) {
 205                return_ACPI_STATUS(AE_NOT_EXIST);
 206        }
 207
 208        if (region_obj2->extra.method_REG == NULL) {
 209                return_ACPI_STATUS(AE_OK);
 210        }
 211
 212        /* Allocate and initialize the evaluation information block */
 213
 214        info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
 215        if (!info) {
 216                return_ACPI_STATUS(AE_NO_MEMORY);
 217        }
 218
 219        info->prefix_node = region_obj2->extra.method_REG;
 220        info->pathname = NULL;
 221        info->parameters = args;
 222        info->flags = ACPI_IGNORE_RETURN_VALUE;
 223
 224        /*
 225         * The _REG method has two arguments:
 226         *
 227         * Arg0 - Integer:
 228         *  Operation region space ID Same value as region_obj->Region.space_id
 229         *
 230         * Arg1 - Integer:
 231         *  connection status 1 for connecting the handler, 0 for disconnecting
 232         *  the handler (Passed as a parameter)
 233         */
 234        args[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
 235        if (!args[0]) {
 236                status = AE_NO_MEMORY;
 237                goto cleanup1;
 238        }
 239
 240        args[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
 241        if (!args[1]) {
 242                status = AE_NO_MEMORY;
 243                goto cleanup2;
 244        }
 245
 246        /* Setup the parameter objects */
 247
 248        args[0]->integer.value = region_obj->region.space_id;
 249        args[1]->integer.value = function;
 250        args[2] = NULL;
 251
 252        /* Execute the method, no return value */
 253
 254        ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
 255                        (ACPI_TYPE_METHOD, info->prefix_node, NULL));
 256
 257        status = acpi_ns_evaluate(info);
 258        acpi_ut_remove_reference(args[1]);
 259
 260      cleanup2:
 261        acpi_ut_remove_reference(args[0]);
 262
 263      cleanup1:
 264        ACPI_FREE(info);
 265        return_ACPI_STATUS(status);
 266}
 267
 268/*******************************************************************************
 269 *
 270 * FUNCTION:    acpi_ev_address_space_dispatch
 271 *
 272 * PARAMETERS:  region_obj          - Internal region object
 273 *              Function            - Read or Write operation
 274 *              Address             - Where in the space to read or write
 275 *              bit_width           - Field width in bits (8, 16, 32, or 64)
 276 *              Value               - Pointer to in or out value, must be
 277 *                                    full 64-bit acpi_integer
 278 *
 279 * RETURN:      Status
 280 *
 281 * DESCRIPTION: Dispatch an address space or operation region access to
 282 *              a previously installed handler.
 283 *
 284 ******************************************************************************/
 285
 286acpi_status
 287acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
 288                               u32 function,
 289                               acpi_physical_address address,
 290                               u32 bit_width, acpi_integer * value)
 291{
 292        acpi_status status;
 293        acpi_adr_space_handler handler;
 294        acpi_adr_space_setup region_setup;
 295        union acpi_operand_object *handler_desc;
 296        union acpi_operand_object *region_obj2;
 297        void *region_context = NULL;
 298
 299        ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
 300
 301        region_obj2 = acpi_ns_get_secondary_object(region_obj);
 302        if (!region_obj2) {
 303                return_ACPI_STATUS(AE_NOT_EXIST);
 304        }
 305
 306        /* Ensure that there is a handler associated with this region */
 307
 308        handler_desc = region_obj->region.handler;
 309        if (!handler_desc) {
 310                ACPI_ERROR((AE_INFO,
 311                            "No handler for Region [%4.4s] (%p) [%s]",
 312                            acpi_ut_get_node_name(region_obj->region.node),
 313                            region_obj,
 314                            acpi_ut_get_region_name(region_obj->region.
 315                                                    space_id)));
 316
 317                return_ACPI_STATUS(AE_NOT_EXIST);
 318        }
 319
 320        /*
 321         * It may be the case that the region has never been initialized
 322         * Some types of regions require special init code
 323         */
 324        if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
 325                /*
 326                 * This region has not been initialized yet, do it
 327                 */
 328                region_setup = handler_desc->address_space.setup;
 329                if (!region_setup) {
 330
 331                        /* No initialization routine, exit with error */
 332
 333                        ACPI_ERROR((AE_INFO,
 334                                    "No init routine for region(%p) [%s]",
 335                                    region_obj,
 336                                    acpi_ut_get_region_name(region_obj->region.
 337                                                            space_id)));
 338                        return_ACPI_STATUS(AE_NOT_EXIST);
 339                }
 340
 341                /*
 342                 * We must exit the interpreter because the region
 343                 * setup will potentially execute control methods
 344                 * (e.g., _REG method for this region)
 345                 */
 346                acpi_ex_exit_interpreter();
 347
 348                status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
 349                                      handler_desc->address_space.context,
 350                                      &region_context);
 351
 352                /* Re-enter the interpreter */
 353
 354                acpi_ex_enter_interpreter();
 355
 356                /* Check for failure of the Region Setup */
 357
 358                if (ACPI_FAILURE(status)) {
 359                        ACPI_EXCEPTION((AE_INFO, status,
 360                                        "During region initialization: [%s]",
 361                                        acpi_ut_get_region_name(region_obj->
 362                                                                region.
 363                                                                space_id)));
 364                        return_ACPI_STATUS(status);
 365                }
 366
 367                /*
 368                 * Region initialization may have been completed by region_setup
 369                 */
 370                if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
 371                        region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;
 372
 373                        if (region_obj2->extra.region_context) {
 374
 375                                /* The handler for this region was already installed */
 376
 377                                ACPI_FREE(region_context);
 378                        } else {
 379                                /*
 380                                 * Save the returned context for use in all accesses to
 381                                 * this particular region
 382                                 */
 383                                region_obj2->extra.region_context =
 384                                    region_context;
 385                        }
 386                }
 387        }
 388
 389        /* We have everything we need, we can invoke the address space handler */
 390
 391        handler = handler_desc->address_space.handler;
 392
 393        ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
 394                          "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
 395                          &region_obj->region.handler->address_space, handler,
 396                          ACPI_FORMAT_NATIVE_UINT(address),
 397                          acpi_ut_get_region_name(region_obj->region.
 398                                                  space_id)));
 399
 400        if (!(handler_desc->address_space.handler_flags &
 401              ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
 402                /*
 403                 * For handlers other than the default (supplied) handlers, we must
 404                 * exit the interpreter because the handler *might* block -- we don't
 405                 * know what it will do, so we can't hold the lock on the intepreter.
 406                 */
 407                acpi_ex_exit_interpreter();
 408        }
 409
 410        /* Call the handler */
 411
 412        status = handler(function, address, bit_width, value,
 413                         handler_desc->address_space.context,
 414                         region_obj2->extra.region_context);
 415
 416        if (ACPI_FAILURE(status)) {
 417                ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
 418                                acpi_ut_get_region_name(region_obj->region.
 419                                                        space_id)));
 420        }
 421
 422        if (!(handler_desc->address_space.handler_flags &
 423              ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
 424                /*
 425                 * We just returned from a non-default handler, we must re-enter the
 426                 * interpreter
 427                 */
 428                acpi_ex_enter_interpreter();
 429        }
 430
 431        return_ACPI_STATUS(status);
 432}
 433
 434/*******************************************************************************
 435 *
 436 * FUNCTION:    acpi_ev_detach_region
 437 *
 438 * PARAMETERS:  region_obj          - Region Object
 439 *              acpi_ns_is_locked   - Namespace Region Already Locked?
 440 *
 441 * RETURN:      None
 442 *
 443 * DESCRIPTION: Break the association between the handler and the region
 444 *              this is a two way association.
 445 *
 446 ******************************************************************************/
 447
 448void
 449acpi_ev_detach_region(union acpi_operand_object *region_obj,
 450                      u8 acpi_ns_is_locked)
 451{
 452        union acpi_operand_object *handler_obj;
 453        union acpi_operand_object *obj_desc;
 454        union acpi_operand_object **last_obj_ptr;
 455        acpi_adr_space_setup region_setup;
 456        void **region_context;
 457        union acpi_operand_object *region_obj2;
 458        acpi_status status;
 459
 460        ACPI_FUNCTION_TRACE(ev_detach_region);
 461
 462        region_obj2 = acpi_ns_get_secondary_object(region_obj);
 463        if (!region_obj2) {
 464                return_VOID;
 465        }
 466        region_context = &region_obj2->extra.region_context;
 467
 468        /* Get the address handler from the region object */
 469
 470        handler_obj = region_obj->region.handler;
 471        if (!handler_obj) {
 472
 473                /* This region has no handler, all done */
 474
 475                return_VOID;
 476        }
 477
 478        /* Find this region in the handler's list */
 479
 480        obj_desc = handler_obj->address_space.region_list;
 481        last_obj_ptr = &handler_obj->address_space.region_list;
 482
 483        while (obj_desc) {
 484
 485                /* Is this the correct Region? */
 486
 487                if (obj_desc == region_obj) {
 488                        ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
 489                                          "Removing Region %p from address handler %p\n",
 490                                          region_obj, handler_obj));
 491
 492                        /* This is it, remove it from the handler's list */
 493
 494                        *last_obj_ptr = obj_desc->region.next;
 495                        obj_desc->region.next = NULL;   /* Must clear field */
 496
 497                        if (acpi_ns_is_locked) {
 498                                status =
 499                                    acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 500                                if (ACPI_FAILURE(status)) {
 501                                        return_VOID;
 502                                }
 503                        }
 504
 505                        /* Now stop region accesses by executing the _REG method */
 506
 507                        status = acpi_ev_execute_reg_method(region_obj, 0);
 508                        if (ACPI_FAILURE(status)) {
 509                                ACPI_EXCEPTION((AE_INFO, status,
 510                                                "from region _REG, [%s]",
 511                                                acpi_ut_get_region_name
 512                                                (region_obj->region.space_id)));
 513                        }
 514
 515                        if (acpi_ns_is_locked) {
 516                                status =
 517                                    acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 518                                if (ACPI_FAILURE(status)) {
 519                                        return_VOID;
 520                                }
 521                        }
 522
 523                        /*
 524                         * If the region has been activated, call the setup handler
 525                         * with the deactivate notification
 526                         */
 527                        if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
 528                                region_setup = handler_obj->address_space.setup;
 529                                status =
 530                                    region_setup(region_obj,
 531                                                 ACPI_REGION_DEACTIVATE,
 532                                                 handler_obj->address_space.
 533                                                 context, region_context);
 534
 535                                /* Init routine may fail, Just ignore errors */
 536
 537                                if (ACPI_FAILURE(status)) {
 538                                        ACPI_EXCEPTION((AE_INFO, status,
 539                                                        "from region handler - deactivate, [%s]",
 540                                                        acpi_ut_get_region_name
 541                                                        (region_obj->region.
 542                                                         space_id)));
 543                                }
 544
 545                                region_obj->region.flags &=
 546                                    ~(AOPOBJ_SETUP_COMPLETE);
 547                        }
 548
 549                        /*
 550                         * Remove handler reference in the region
 551                         *
 552                         * NOTE: this doesn't mean that the region goes away, the region
 553                         * is just inaccessible as indicated to the _REG method
 554                         *
 555                         * If the region is on the handler's list, this must be the
 556                         * region's handler
 557                         */
 558                        region_obj->region.handler = NULL;
 559                        acpi_ut_remove_reference(handler_obj);
 560
 561                        return_VOID;
 562                }
 563
 564                /* Walk the linked list of handlers */
 565
 566                last_obj_ptr = &obj_desc->region.next;
 567                obj_desc = obj_desc->region.next;
 568        }
 569
 570        /* If we get here, the region was not in the handler's region list */
 571
 572        ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
 573                          "Cannot remove region %p from address handler %p\n",
 574                          region_obj, handler_obj));
 575
 576        return_VOID;
 577}
 578
 579/*******************************************************************************
 580 *
 581 * FUNCTION:    acpi_ev_attach_region
 582 *
 583 * PARAMETERS:  handler_obj         - Handler Object
 584 *              region_obj          - Region Object
 585 *              acpi_ns_is_locked   - Namespace Region Already Locked?
 586 *
 587 * RETURN:      None
 588 *
 589 * DESCRIPTION: Create the association between the handler and the region
 590 *              this is a two way association.
 591 *
 592 ******************************************************************************/
 593
 594acpi_status
 595acpi_ev_attach_region(union acpi_operand_object *handler_obj,
 596                      union acpi_operand_object *region_obj,
 597                      u8 acpi_ns_is_locked)
 598{
 599
 600        ACPI_FUNCTION_TRACE(ev_attach_region);
 601
 602        ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
 603                          "Adding Region [%4.4s] %p to address handler %p [%s]\n",
 604                          acpi_ut_get_node_name(region_obj->region.node),
 605                          region_obj, handler_obj,
 606                          acpi_ut_get_region_name(region_obj->region.
 607                                                  space_id)));
 608
 609        /* Link this region to the front of the handler's list */
 610
 611        region_obj->region.next = handler_obj->address_space.region_list;
 612        handler_obj->address_space.region_list = region_obj;
 613
 614        /* Install the region's handler */
 615
 616        if (region_obj->region.handler) {
 617                return_ACPI_STATUS(AE_ALREADY_EXISTS);
 618        }
 619
 620        region_obj->region.handler = handler_obj;
 621        acpi_ut_add_reference(handler_obj);
 622
 623        return_ACPI_STATUS(AE_OK);
 624}
 625
 626/*******************************************************************************
 627 *
 628 * FUNCTION:    acpi_ev_install_handler
 629 *
 630 * PARAMETERS:  walk_namespace callback
 631 *
 632 * DESCRIPTION: This routine installs an address handler into objects that are
 633 *              of type Region or Device.
 634 *
 635 *              If the Object is a Device, and the device has a handler of
 636 *              the same type then the search is terminated in that branch.
 637 *
 638 *              This is because the existing handler is closer in proximity
 639 *              to any more regions than the one we are trying to install.
 640 *
 641 ******************************************************************************/
 642
 643static acpi_status
 644acpi_ev_install_handler(acpi_handle obj_handle,
 645                        u32 level, void *context, void **return_value)
 646{
 647        union acpi_operand_object *handler_obj;
 648        union acpi_operand_object *next_handler_obj;
 649        union acpi_operand_object *obj_desc;
 650        struct acpi_namespace_node *node;
 651        acpi_status status;
 652
 653        ACPI_FUNCTION_NAME(ev_install_handler);
 654
 655        handler_obj = (union acpi_operand_object *)context;
 656
 657        /* Parameter validation */
 658
 659        if (!handler_obj) {
 660                return (AE_OK);
 661        }
 662
 663        /* Convert and validate the device handle */
 664
 665        node = acpi_ns_map_handle_to_node(obj_handle);
 666        if (!node) {
 667                return (AE_BAD_PARAMETER);
 668        }
 669
 670        /*
 671         * We only care about regions.and objects
 672         * that are allowed to have address space handlers
 673         */
 674        if ((node->type != ACPI_TYPE_DEVICE) &&
 675            (node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
 676                return (AE_OK);
 677        }
 678
 679        /* Check for an existing internal object */
 680
 681        obj_desc = acpi_ns_get_attached_object(node);
 682        if (!obj_desc) {
 683
 684                /* No object, just exit */
 685
 686                return (AE_OK);
 687        }
 688
 689        /* Devices are handled different than regions */
 690
 691        if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_DEVICE) {
 692
 693                /* Check if this Device already has a handler for this address space */
 694
 695                next_handler_obj = obj_desc->device.handler;
 696                while (next_handler_obj) {
 697
 698                        /* Found a handler, is it for the same address space? */
 699
 700                        if (next_handler_obj->address_space.space_id ==
 701                            handler_obj->address_space.space_id) {
 702                                ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
 703                                                  "Found handler for region [%s] in device %p(%p) handler %p\n",
 704                                                  acpi_ut_get_region_name
 705                                                  (handler_obj->address_space.
 706                                                   space_id), obj_desc,
 707                                                  next_handler_obj,
 708                                                  handler_obj));
 709
 710                                /*
 711                                 * Since the object we found it on was a device, then it
 712                                 * means that someone has already installed a handler for
 713                                 * the branch of the namespace from this device on.  Just
 714                                 * bail out telling the walk routine to not traverse this
 715                                 * branch.  This preserves the scoping rule for handlers.
 716                                 */
 717                                return (AE_CTRL_DEPTH);
 718                        }
 719
 720                        /* Walk the linked list of handlers attached to this device */
 721
 722                        next_handler_obj = next_handler_obj->address_space.next;
 723                }
 724
 725                /*
 726                 * As long as the device didn't have a handler for this
 727                 * space we don't care about it.  We just ignore it and
 728                 * proceed.
 729                 */
 730                return (AE_OK);
 731        }
 732
 733        /* Object is a Region */
 734
 735        if (obj_desc->region.space_id != handler_obj->address_space.space_id) {
 736                /*
 737                 * This region is for a different address space
 738                 * -- just ignore it
 739                 */
 740                return (AE_OK);
 741        }
 742
 743        /*
 744         * Now we have a region and it is for the handler's address
 745         * space type.
 746         *
 747         * First disconnect region for any previous handler (if any)
 748         */
 749        acpi_ev_detach_region(obj_desc, FALSE);
 750
 751        /* Connect the region to the new handler */
 752
 753        status = acpi_ev_attach_region(handler_obj, obj_desc, FALSE);
 754        return (status);
 755}
 756
 757/*******************************************************************************
 758 *
 759 * FUNCTION:    acpi_ev_install_space_handler
 760 *
 761 * PARAMETERS:  Node            - Namespace node for the device
 762 *              space_id        - The address space ID
 763 *              Handler         - Address of the handler
 764 *              Setup           - Address of the setup function
 765 *              Context         - Value passed to the handler on each access
 766 *
 767 * RETURN:      Status
 768 *
 769 * DESCRIPTION: Install a handler for all op_regions of a given space_id.
 770 *              Assumes namespace is locked
 771 *
 772 ******************************************************************************/
 773
 774acpi_status
 775acpi_ev_install_space_handler(struct acpi_namespace_node * node,
 776                              acpi_adr_space_type space_id,
 777                              acpi_adr_space_handler handler,
 778                              acpi_adr_space_setup setup, void *context)
 779{
 780        union acpi_operand_object *obj_desc;
 781        union acpi_operand_object *handler_obj;
 782        acpi_status status;
 783        acpi_object_type type;
 784        u8 flags = 0;
 785
 786        ACPI_FUNCTION_TRACE(ev_install_space_handler);
 787
 788        /*
 789         * This registration is valid for only the types below
 790         * and the root.  This is where the default handlers
 791         * get placed.
 792         */
 793        if ((node->type != ACPI_TYPE_DEVICE) &&
 794            (node->type != ACPI_TYPE_PROCESSOR) &&
 795            (node->type != ACPI_TYPE_THERMAL) && (node != acpi_gbl_root_node)) {
 796                status = AE_BAD_PARAMETER;
 797                goto unlock_and_exit;
 798        }
 799
 800        if (handler == ACPI_DEFAULT_HANDLER) {
 801                flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
 802
 803                switch (space_id) {
 804                case ACPI_ADR_SPACE_SYSTEM_MEMORY:
 805                        handler = acpi_ex_system_memory_space_handler;
 806                        setup = acpi_ev_system_memory_region_setup;
 807                        break;
 808
 809                case ACPI_ADR_SPACE_SYSTEM_IO:
 810                        handler = acpi_ex_system_io_space_handler;
 811                        setup = acpi_ev_io_space_region_setup;
 812                        break;
 813
 814                case ACPI_ADR_SPACE_PCI_CONFIG:
 815                        handler = acpi_ex_pci_config_space_handler;
 816                        setup = acpi_ev_pci_config_region_setup;
 817                        break;
 818
 819                case ACPI_ADR_SPACE_CMOS:
 820                        handler = acpi_ex_cmos_space_handler;
 821                        setup = acpi_ev_cmos_region_setup;
 822                        break;
 823
 824                case ACPI_ADR_SPACE_PCI_BAR_TARGET:
 825                        handler = acpi_ex_pci_bar_space_handler;
 826                        setup = acpi_ev_pci_bar_region_setup;
 827                        break;
 828
 829                case ACPI_ADR_SPACE_DATA_TABLE:
 830                        handler = acpi_ex_data_table_space_handler;
 831                        setup = NULL;
 832                        break;
 833
 834                default:
 835                        status = AE_BAD_PARAMETER;
 836                        goto unlock_and_exit;
 837                }
 838        }
 839
 840        /* If the caller hasn't specified a setup routine, use the default */
 841
 842        if (!setup) {
 843                setup = acpi_ev_default_region_setup;
 844        }
 845
 846        /* Check for an existing internal object */
 847
 848        obj_desc = acpi_ns_get_attached_object(node);
 849        if (obj_desc) {
 850                /*
 851                 * The attached device object already exists.
 852                 * Make sure the handler is not already installed.
 853                 */
 854                handler_obj = obj_desc->device.handler;
 855
 856                /* Walk the handler list for this device */
 857
 858                while (handler_obj) {
 859
 860                        /* Same space_id indicates a handler already installed */
 861
 862                        if (handler_obj->address_space.space_id == space_id) {
 863                                if (handler_obj->address_space.handler ==
 864                                    handler) {
 865                                        /*
 866                                         * It is (relatively) OK to attempt to install the SAME
 867                                         * handler twice. This can easily happen
 868                                         * with PCI_Config space.
 869                                         */
 870                                        status = AE_SAME_HANDLER;
 871                                        goto unlock_and_exit;
 872                                } else {
 873                                        /* A handler is already installed */
 874
 875                                        status = AE_ALREADY_EXISTS;
 876                                }
 877                                goto unlock_and_exit;
 878                        }
 879
 880                        /* Walk the linked list of handlers */
 881
 882                        handler_obj = handler_obj->address_space.next;
 883                }
 884        } else {
 885                ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
 886                                  "Creating object on Device %p while installing handler\n",
 887                                  node));
 888
 889                /* obj_desc does not exist, create one */
 890
 891                if (node->type == ACPI_TYPE_ANY) {
 892                        type = ACPI_TYPE_DEVICE;
 893                } else {
 894                        type = node->type;
 895                }
 896
 897                obj_desc = acpi_ut_create_internal_object(type);
 898                if (!obj_desc) {
 899                        status = AE_NO_MEMORY;
 900                        goto unlock_and_exit;
 901                }
 902
 903                /* Init new descriptor */
 904
 905                obj_desc->common.type = (u8) type;
 906
 907                /* Attach the new object to the Node */
 908
 909                status = acpi_ns_attach_object(node, obj_desc, type);
 910
 911                /* Remove local reference to the object */
 912
 913                acpi_ut_remove_reference(obj_desc);
 914
 915                if (ACPI_FAILURE(status)) {
 916                        goto unlock_and_exit;
 917                }
 918        }
 919
 920        ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
 921                          "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
 922                          acpi_ut_get_region_name(space_id), space_id,
 923                          acpi_ut_get_node_name(node), node, obj_desc));
 924
 925        /*
 926         * Install the handler
 927         *
 928         * At this point there is no existing handler.
 929         * Just allocate the object for the handler and link it
 930         * into the list.
 931         */
 932        handler_obj =
 933            acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
 934        if (!handler_obj) {
 935                status = AE_NO_MEMORY;
 936                goto unlock_and_exit;
 937        }
 938
 939        /* Init handler obj */
 940
 941        handler_obj->address_space.space_id = (u8) space_id;
 942        handler_obj->address_space.handler_flags = flags;
 943        handler_obj->address_space.region_list = NULL;
 944        handler_obj->address_space.node = node;
 945        handler_obj->address_space.handler = handler;
 946        handler_obj->address_space.context = context;
 947        handler_obj->address_space.setup = setup;
 948
 949        /* Install at head of Device.address_space list */
 950
 951        handler_obj->address_space.next = obj_desc->device.handler;
 952
 953        /*
 954         * The Device object is the first reference on the handler_obj.
 955         * Each region that uses the handler adds a reference.
 956         */
 957        obj_desc->device.handler = handler_obj;
 958
 959        /*
 960         * Walk the namespace finding all of the regions this
 961         * handler will manage.
 962         *
 963         * Start at the device and search the branch toward
 964         * the leaf nodes until either the leaf is encountered or
 965         * a device is detected that has an address handler of the
 966         * same type.
 967         *
 968         * In either case, back up and search down the remainder
 969         * of the branch
 970         */
 971        status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
 972                                        ACPI_NS_WALK_UNLOCK,
 973                                        acpi_ev_install_handler, handler_obj,
 974                                        NULL);
 975
 976      unlock_and_exit:
 977        return_ACPI_STATUS(status);
 978}
 979
 980/*******************************************************************************
 981 *
 982 * FUNCTION:    acpi_ev_execute_reg_methods
 983 *
 984 * PARAMETERS:  Node            - Namespace node for the device
 985 *              space_id        - The address space ID
 986 *
 987 * RETURN:      Status
 988 *
 989 * DESCRIPTION: Run all _REG methods for the input Space ID;
 990 *              Note: assumes namespace is locked, or system init time.
 991 *
 992 ******************************************************************************/
 993
 994acpi_status
 995acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
 996                            acpi_adr_space_type space_id)
 997{
 998        acpi_status status;
 999
1000        ACPI_FUNCTION_TRACE(ev_execute_reg_methods);
1001
1002        /*
1003         * Run all _REG methods for all Operation Regions for this
1004         * space ID.  This is a separate walk in order to handle any
1005         * interdependencies between regions and _REG methods.  (i.e. handlers
1006         * must be installed for all regions of this Space ID before we
1007         * can run any _REG methods)
1008         */
1009        status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
1010                                        ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
1011                                        &space_id, NULL);
1012
1013        return_ACPI_STATUS(status);
1014}
1015
1016/*******************************************************************************
1017 *
1018 * FUNCTION:    acpi_ev_reg_run
1019 *
1020 * PARAMETERS:  walk_namespace callback
1021 *
1022 * DESCRIPTION: Run _REG method for region objects of the requested space_iD
1023 *
1024 ******************************************************************************/
1025
1026static acpi_status
1027acpi_ev_reg_run(acpi_handle obj_handle,
1028                u32 level, void *context, void **return_value)
1029{
1030        union acpi_operand_object *obj_desc;
1031        struct acpi_namespace_node *node;
1032        acpi_adr_space_type space_id;
1033        acpi_status status;
1034
1035        space_id = *ACPI_CAST_PTR(acpi_adr_space_type, context);
1036
1037        /* Convert and validate the device handle */
1038
1039        node = acpi_ns_map_handle_to_node(obj_handle);
1040        if (!node) {
1041                return (AE_BAD_PARAMETER);
1042        }
1043
1044        /*
1045         * We only care about regions.and objects
1046         * that are allowed to have address space handlers
1047         */
1048        if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
1049                return (AE_OK);
1050        }
1051
1052        /* Check for an existing internal object */
1053
1054        obj_desc = acpi_ns_get_attached_object(node);
1055        if (!obj_desc) {
1056
1057                /* No object, just exit */
1058
1059                return (AE_OK);
1060        }
1061
1062        /* Object is a Region */
1063
1064        if (obj_desc->region.space_id != space_id) {
1065                /*
1066                 * This region is for a different address space
1067                 * -- just ignore it
1068                 */
1069                return (AE_OK);
1070        }
1071
1072        status = acpi_ev_execute_reg_method(obj_desc, 1);
1073        return (status);
1074}
1075
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.