static acpi_status acpi_ds_create_external_region(acpi_status lookup_status, union acpi_parse_object *op, char *path, struct acpi_walk_state *walk_state, struct acpi_namespace_node **node) { acpi_status status; union acpi_operand_object *obj_desc; if (lookup_status != AE_NOT_FOUND) { return (lookup_status); } /* * Table disassembly: * operation_region not found. Generate an External for it, and * insert the name into the namespace. */ acpi_dm_add_to_external_list(op, path, ACPI_TYPE_REGION, 0); status = acpi_ns_lookup(walk_state->scope_info, path, ACPI_TYPE_REGION, ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, walk_state, node); if (ACPI_FAILURE(status)) { return (status); } /* Must create and install a region object for the new node */ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION); if (!obj_desc) { return (AE_NO_MEMORY); } obj_desc->region.node = *node; status = acpi_ns_attach_object(*node, obj_desc, ACPI_TYPE_REGION); return (status); }
/******************************************************************************* * * FUNCTION: acpi_install_notify_handler * * PARAMETERS: Device - The device for which notifies will be handled * handler_type - The type of handler: * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) * ACPI_ALL_NOTIFY: both system and device * Handler - Address of the handler * Context - Value passed to the handler on each GPE * * RETURN: Status * * DESCRIPTION: Install a handler for notifies on an ACPI device * ******************************************************************************/ acpi_status acpi_install_notify_handler(acpi_handle device, u32 handler_type, acpi_notify_handler handler, void *context) { union acpi_operand_object *obj_desc; union acpi_operand_object *notify_obj; struct acpi_namespace_node *node; acpi_status status; ACPI_FUNCTION_TRACE(acpi_install_notify_handler); /* Parameter validation */ if ((!device) || (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Convert and validate the device handle */ node = acpi_ns_validate_handle(device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } /* * Root Object: * Registering a notify handler on the root object indicates that the * caller wishes to receive notifications for all objects. Note that * only one <external> global handler can be regsitered (per notify type). */ if (device == ACPI_ROOT_OBJECT) { /* Make sure the handler is not already installed */ if (((handler_type & ACPI_SYSTEM_NOTIFY) && acpi_gbl_system_notify.handler) || ((handler_type & ACPI_DEVICE_NOTIFY) && acpi_gbl_device_notify.handler)) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; } if (handler_type & ACPI_SYSTEM_NOTIFY) { acpi_gbl_system_notify.node = node; acpi_gbl_system_notify.handler = handler; acpi_gbl_system_notify.context = context; } if (handler_type & ACPI_DEVICE_NOTIFY) { acpi_gbl_device_notify.node = node; acpi_gbl_device_notify.handler = handler; acpi_gbl_device_notify.context = context; } /* Global notify handler installed */ } /* * All Other Objects: * Caller will only receive notifications specific to the target object. * Note that only certain object types can receive notifications. */ else { /* Notifies allowed on this object? */ if (!acpi_ev_is_notify_object(node)) { status = AE_TYPE; goto unlock_and_exit; } /* Check for an existing internal object */ obj_desc = acpi_ns_get_attached_object(node); if (obj_desc) { /* Object exists - make sure there's no handler */ if (((handler_type & ACPI_SYSTEM_NOTIFY) && obj_desc->common_notify.system_notify) || ((handler_type & ACPI_DEVICE_NOTIFY) && obj_desc->common_notify.device_notify)) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; } } else { /* Create a new object */ obj_desc = acpi_ut_create_internal_object(node->type); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; } /* Attach new object to the Node */ status = acpi_ns_attach_object(device, obj_desc, node->type); /* Remove local reference to the object */ acpi_ut_remove_reference(obj_desc); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } } /* Install the handler */ notify_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); if (!notify_obj) { status = AE_NO_MEMORY; goto unlock_and_exit; } notify_obj->notify.node = node; notify_obj->notify.handler = handler; notify_obj->notify.context = context; if (handler_type & ACPI_SYSTEM_NOTIFY) { obj_desc->common_notify.system_notify = notify_obj; } if (handler_type & ACPI_DEVICE_NOTIFY) { obj_desc->common_notify.device_notify = notify_obj; } if (handler_type == ACPI_ALL_NOTIFY) { /* Extra ref if installed in both */ acpi_ut_add_reference(notify_obj); } } unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); }
acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) { union acpi_operand_object *obj_desc; union acpi_operand_object *second_desc = NULL; u32 type; acpi_status status; ACPI_FUNCTION_TRACE(ex_prep_field_value); /* Parameter validation */ if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) { if (!info->region_node) { ACPI_ERROR((AE_INFO, "Null RegionNode")); return_ACPI_STATUS(AE_AML_NO_OPERAND); } type = acpi_ns_get_type(info->region_node); if (type != ACPI_TYPE_REGION) { ACPI_ERROR((AE_INFO, "Needed Region, found type 0x%X (%s)", type, acpi_ut_get_type_name(type))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } } /* Allocate a new field object */ obj_desc = acpi_ut_create_internal_object(info->field_type); if (!obj_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } /* Initialize areas of the object that are common to all fields */ obj_desc->common_field.node = info->field_node; status = acpi_ex_prep_common_field_object(obj_desc, info->field_flags, info->attribute, info->field_bit_position, info->field_bit_length); if (ACPI_FAILURE(status)) { acpi_ut_delete_object_desc(obj_desc); return_ACPI_STATUS(status); } /* Initialize areas of the object that are specific to the field type */ switch (info->field_type) { case ACPI_TYPE_LOCAL_REGION_FIELD: obj_desc->field.region_obj = acpi_ns_get_attached_object(info->region_node); /* An additional reference for the container */ acpi_ut_add_reference(obj_desc->field.region_obj); /* allow full data read from EC address space */ if (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_EC) { if (obj_desc->common_field.bit_length > 8) { unsigned width = ACPI_ROUND_BITS_UP_TO_BYTES( obj_desc->common_field.bit_length); // access_bit_width is u8, don't overflow it if (width > 8) width = 8; obj_desc->common_field.access_byte_width = width; obj_desc->common_field.access_bit_width = 8 * width; } } ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n", obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset, obj_desc->field.access_byte_width, obj_desc->field.region_obj)); break; case ACPI_TYPE_LOCAL_BANK_FIELD: obj_desc->bank_field.value = info->bank_value; obj_desc->bank_field.region_obj = acpi_ns_get_attached_object(info->region_node); obj_desc->bank_field.bank_obj = acpi_ns_get_attached_object(info->register_node); /* An additional reference for the attached objects */ acpi_ut_add_reference(obj_desc->bank_field.region_obj); acpi_ut_add_reference(obj_desc->bank_field.bank_obj); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n", obj_desc->bank_field.start_field_bit_offset, obj_desc->bank_field.base_byte_offset, obj_desc->field.access_byte_width, obj_desc->bank_field.region_obj, obj_desc->bank_field.bank_obj)); /* * Remember location in AML stream of the field unit * opcode and operands -- since the bank_value * operands must be evaluated. */ second_desc = obj_desc->common.next_object; second_desc->extra.aml_start = ACPI_CAST_PTR(union acpi_parse_object, info->data_register_node)->named.data; second_desc->extra.aml_length = ACPI_CAST_PTR(union acpi_parse_object, info->data_register_node)->named.length; break; case ACPI_TYPE_LOCAL_INDEX_FIELD: /* Get the Index and Data registers */ obj_desc->index_field.index_obj = acpi_ns_get_attached_object(info->register_node); obj_desc->index_field.data_obj = acpi_ns_get_attached_object(info->data_register_node); if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) { ACPI_ERROR((AE_INFO, "Null Index Object during field prep")); acpi_ut_delete_object_desc(obj_desc); return_ACPI_STATUS(AE_AML_INTERNAL); } /* An additional reference for the attached objects */ acpi_ut_add_reference(obj_desc->index_field.data_obj); acpi_ut_add_reference(obj_desc->index_field.index_obj); /* * April 2006: Changed to match MS behavior * * The value written to the Index register is the byte offset of the * target field in units of the granularity of the index_field * * Previously, the value was calculated as an index in terms of the * width of the Data register, as below: * * obj_desc->index_field.Value = (u32) * (Info->field_bit_position / ACPI_MUL_8 ( * obj_desc->Field.access_byte_width)); * * February 2006: Tried value as a byte offset: * obj_desc->index_field.Value = (u32) * ACPI_DIV_8 (Info->field_bit_position); */ obj_desc->index_field.value = (u32) ACPI_ROUND_DOWN(ACPI_DIV_8(info->field_bit_position), obj_desc->index_field. access_byte_width); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n", obj_desc->index_field.start_field_bit_offset, obj_desc->index_field.base_byte_offset, obj_desc->index_field.value, obj_desc->field.access_byte_width, obj_desc->index_field.index_obj, obj_desc->index_field.data_obj)); break; default: /* No other types should get here */ break; } /* * Store the constructed descriptor (obj_desc) into the parent Node, * preserving the current type of that named_obj. */ status = acpi_ns_attach_object(info->field_node, obj_desc, acpi_ns_get_type(info->field_node)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "Set NamedObj %p [%4.4s], ObjDesc %p\n", info->field_node, acpi_ut_get_node_name(info->field_node), obj_desc)); /* Remove local reference to the object */ acpi_ut_remove_reference(obj_desc); return_ACPI_STATUS(status); }
acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) { union acpi_operand_object *obj_desc; union acpi_operand_object *second_desc = NULL; acpi_status status; u32 access_byte_width; u32 type; ACPI_FUNCTION_TRACE(ex_prep_field_value); /* */ if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) { if (!info->region_node) { ACPI_ERROR((AE_INFO, "Null RegionNode")); return_ACPI_STATUS(AE_AML_NO_OPERAND); } type = acpi_ns_get_type(info->region_node); if (type != ACPI_TYPE_REGION) { ACPI_ERROR((AE_INFO, "Needed Region, found type 0x%X (%s)", type, acpi_ut_get_type_name(type))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } } /* */ obj_desc = acpi_ut_create_internal_object(info->field_type); if (!obj_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } /* */ obj_desc->common_field.node = info->field_node; status = acpi_ex_prep_common_field_object(obj_desc, info->field_flags, info->attribute, info->field_bit_position, info->field_bit_length); if (ACPI_FAILURE(status)) { acpi_ut_delete_object_desc(obj_desc); return_ACPI_STATUS(status); } /* */ switch (info->field_type) { case ACPI_TYPE_LOCAL_REGION_FIELD: obj_desc->field.region_obj = acpi_ns_get_attached_object(info->region_node); /* */ obj_desc->field.access_length = info->access_length; if (info->connection_node) { second_desc = info->connection_node->object; if (!(second_desc->common.flags & AOPOBJ_DATA_VALID)) { status = acpi_ds_get_buffer_arguments(second_desc); if (ACPI_FAILURE(status)) { acpi_ut_delete_object_desc(obj_desc); return_ACPI_STATUS(status); } } obj_desc->field.resource_buffer = second_desc->buffer.pointer; obj_desc->field.resource_length = (u16)second_desc->buffer.length; } else if (info->resource_buffer) { obj_desc->field.resource_buffer = info->resource_buffer; obj_desc->field.resource_length = info->resource_length; } /* */ if ((obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_EC) && (obj_desc->common_field.bit_length > 8)) { access_byte_width = ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field. bit_length); /* */ if (access_byte_width < 256) { obj_desc->common_field.access_byte_width = (u8)access_byte_width; } } /* */ acpi_ut_add_reference(obj_desc->field.region_obj); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n", obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset, obj_desc->field.access_byte_width, obj_desc->field.region_obj)); break; case ACPI_TYPE_LOCAL_BANK_FIELD: obj_desc->bank_field.value = info->bank_value; obj_desc->bank_field.region_obj = acpi_ns_get_attached_object(info->region_node); obj_desc->bank_field.bank_obj = acpi_ns_get_attached_object(info->register_node); /* */ acpi_ut_add_reference(obj_desc->bank_field.region_obj); acpi_ut_add_reference(obj_desc->bank_field.bank_obj); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n", obj_desc->bank_field.start_field_bit_offset, obj_desc->bank_field.base_byte_offset, obj_desc->field.access_byte_width, obj_desc->bank_field.region_obj, obj_desc->bank_field.bank_obj)); /* */ second_desc = obj_desc->common.next_object; second_desc->extra.aml_start = ACPI_CAST_PTR(union acpi_parse_object, info->data_register_node)->named.data; second_desc->extra.aml_length = ACPI_CAST_PTR(union acpi_parse_object, info->data_register_node)->named.length; break; case ACPI_TYPE_LOCAL_INDEX_FIELD: /* */ obj_desc->index_field.index_obj = acpi_ns_get_attached_object(info->register_node); obj_desc->index_field.data_obj = acpi_ns_get_attached_object(info->data_register_node); if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) { ACPI_ERROR((AE_INFO, "Null Index Object during field prep")); acpi_ut_delete_object_desc(obj_desc); return_ACPI_STATUS(AE_AML_INTERNAL); } /* */ acpi_ut_add_reference(obj_desc->index_field.data_obj); acpi_ut_add_reference(obj_desc->index_field.index_obj); /* */ obj_desc->index_field.value = (u32) ACPI_ROUND_DOWN(ACPI_DIV_8(info->field_bit_position), obj_desc->index_field. access_byte_width); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n", obj_desc->index_field.start_field_bit_offset, obj_desc->index_field.base_byte_offset, obj_desc->index_field.value, obj_desc->field.access_byte_width, obj_desc->index_field.index_obj, obj_desc->index_field.data_obj)); break; default: /* */ break; } /* */ status = acpi_ns_attach_object(info->field_node, obj_desc, acpi_ns_get_type(info->field_node)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "Set NamedObj %p [%4.4s], ObjDesc %p\n", info->field_node, acpi_ut_get_node_name(info->field_node), obj_desc)); /* */ acpi_ut_remove_reference(obj_desc); return_ACPI_STATUS(status); }
acpi_status acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, struct acpi_namespace_node *node, struct acpi_walk_state *walk_state, u8 implicit_conversion) { acpi_status status = AE_OK; union acpi_operand_object *target_desc; union acpi_operand_object *new_desc; acpi_object_type target_type; ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_node, source_desc); /* Get current type of the node, and object attached to Node */ target_type = acpi_ns_get_type(node); target_desc = acpi_ns_get_attached_object(node); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n", source_desc, acpi_ut_get_object_type_name(source_desc), node, acpi_ut_get_type_name(target_type))); /* * Resolve the source object to an actual value * (If it is a reference object) */ status = acpi_ex_resolve_object(&source_desc, target_type, walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* If no implicit conversion, drop into the default case below */ if ((!implicit_conversion) || (walk_state->opcode == AML_COPY_OP)) { /* Force execution of default (no implicit conversion) */ target_type = ACPI_TYPE_ANY; } /* Do the actual store operation */ switch (target_type) { case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: /* For fields, copy the source data to the target field. */ status = acpi_ex_write_data_to_field(source_desc, target_desc, &walk_state->result_obj); break; case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* * These target types are all of type Integer/String/Buffer, and * therefore support implicit conversion before the store. * * Copy and/or convert the source object to a new target object */ status = acpi_ex_store_object_to_object(source_desc, target_desc, &new_desc, walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } if (new_desc != target_desc) { /* * Store the new new_desc as the new value of the Name, and set * the Name's type to that of the value being stored in it. * source_desc reference count is incremented by attach_object. * * Note: This may change the type of the node if an explicit store * has been performed such that the node/object type has been * changed. */ status = acpi_ns_attach_object(node, new_desc, new_desc->common.type); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Store %s into %s via Convert/Attach\n", acpi_ut_get_object_type_name (source_desc), acpi_ut_get_object_type_name (new_desc))); } break; default: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %s (%p) directly into node (%p) with no implicit conversion\n", acpi_ut_get_object_type_name(source_desc), source_desc, node)); /* No conversions for all other types. Just attach the source object */ status = acpi_ns_attach_object(node, source_desc, ACPI_GET_OBJECT_TYPE (source_desc)); break; } return_ACPI_STATUS(status); }
acpi_status acpi_ev_install_space_handler(struct acpi_namespace_node * node, acpi_adr_space_type space_id, acpi_adr_space_handler handler, acpi_adr_space_setup setup, void *context) { union acpi_operand_object *obj_desc; union acpi_operand_object *handler_obj; acpi_status status; acpi_object_type type; u8 flags = 0; ACPI_FUNCTION_TRACE(ev_install_space_handler); /* * This registration is valid for only the types below * and the root. This is where the default handlers * get placed. */ if ((node->type != ACPI_TYPE_DEVICE) && (node->type != ACPI_TYPE_PROCESSOR) && (node->type != ACPI_TYPE_THERMAL) && (node != acpi_gbl_root_node)) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } if (handler == ACPI_DEFAULT_HANDLER) { flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; switch (space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: handler = acpi_ex_system_memory_space_handler; setup = acpi_ev_system_memory_region_setup; break; case ACPI_ADR_SPACE_SYSTEM_IO: handler = acpi_ex_system_io_space_handler; setup = acpi_ev_io_space_region_setup; break; case ACPI_ADR_SPACE_PCI_CONFIG: handler = acpi_ex_pci_config_space_handler; setup = acpi_ev_pci_config_region_setup; break; case ACPI_ADR_SPACE_CMOS: handler = acpi_ex_cmos_space_handler; setup = acpi_ev_cmos_region_setup; break; case ACPI_ADR_SPACE_PCI_BAR_TARGET: handler = acpi_ex_pci_bar_space_handler; setup = acpi_ev_pci_bar_region_setup; break; case ACPI_ADR_SPACE_DATA_TABLE: handler = acpi_ex_data_table_space_handler; setup = NULL; break; default: status = AE_BAD_PARAMETER; goto unlock_and_exit; } } /* If the caller hasn't specified a setup routine, use the default */ if (!setup) { setup = acpi_ev_default_region_setup; } /* Check for an existing internal object */ obj_desc = acpi_ns_get_attached_object(node); if (obj_desc) { /* * The attached device object already exists. * Make sure the handler is not already installed. */ handler_obj = obj_desc->device.handler; /* Walk the handler list for this device */ while (handler_obj) { /* Same space_id indicates a handler already installed */ if (handler_obj->address_space.space_id == space_id) { if (handler_obj->address_space.handler == handler) { /* * It is (relatively) OK to attempt to install the SAME * handler twice. This can easily happen * with PCI_Config space. */ status = AE_SAME_HANDLER; goto unlock_and_exit; } else { /* A handler is already installed */ status = AE_ALREADY_EXISTS; } goto unlock_and_exit; } /* Walk the linked list of handlers */ handler_obj = handler_obj->address_space.next; } } else { ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, "Creating object on Device %p while installing handler\n", node)); /* obj_desc does not exist, create one */ if (node->type == ACPI_TYPE_ANY) { type = ACPI_TYPE_DEVICE; } else { type = node->type; } obj_desc = acpi_ut_create_internal_object(type); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; } /* Init new descriptor */ obj_desc->common.type = (u8) type; /* Attach the new object to the Node */ status = acpi_ns_attach_object(node, obj_desc, type); /* Remove local reference to the object */ acpi_ut_remove_reference(obj_desc); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } } ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", acpi_ut_get_region_name(space_id), space_id, acpi_ut_get_node_name(node), node, obj_desc)); /* * Install the handler * * At this point there is no existing handler. * Just allocate the object for the handler and link it * into the list. */ handler_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_ADDRESS_HANDLER); if (!handler_obj) { status = AE_NO_MEMORY; goto unlock_and_exit; } /* Init handler obj */ handler_obj->address_space.space_id = (u8) space_id; handler_obj->address_space.handler_flags = flags; handler_obj->address_space.region_list = NULL; handler_obj->address_space.node = node; handler_obj->address_space.handler = handler; handler_obj->address_space.context = context; handler_obj->address_space.setup = setup; /* Install at head of Device.address_space list */ handler_obj->address_space.next = obj_desc->device.handler; /* * The Device object is the first reference on the handler_obj. * Each region that uses the handler adds a reference. */ obj_desc->device.handler = handler_obj; /* * Walk the namespace finding all of the regions this * handler will manage. * * Start at the device and search the branch toward * the leaf nodes until either the leaf is encountered or * a device is detected that has an address handler of the * same type. * * In either case, back up and search down the remainder * of the branch */ status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler, handler_obj, NULL); unlock_and_exit: return_ACPI_STATUS(status); }
acpi_status acpi_install_notify_handler(acpi_handle device, u32 handler_type, acpi_notify_handler handler, void *context) { union acpi_operand_object *obj_desc; union acpi_operand_object *notify_obj; struct acpi_namespace_node *node; acpi_status status; ACPI_FUNCTION_TRACE(acpi_install_notify_handler); if ((!device) || (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } node = acpi_ns_map_handle_to_node(device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } if (device == ACPI_ROOT_OBJECT) { if (((handler_type & ACPI_SYSTEM_NOTIFY) && acpi_gbl_system_notify.handler) || ((handler_type & ACPI_DEVICE_NOTIFY) && acpi_gbl_device_notify.handler)) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; } if (handler_type & ACPI_SYSTEM_NOTIFY) { acpi_gbl_system_notify.node = node; acpi_gbl_system_notify.handler = handler; acpi_gbl_system_notify.context = context; } if (handler_type & ACPI_DEVICE_NOTIFY) { acpi_gbl_device_notify.node = node; acpi_gbl_device_notify.handler = handler; acpi_gbl_device_notify.context = context; } } else { if (!acpi_ev_is_notify_object(node)) { status = AE_TYPE; goto unlock_and_exit; } obj_desc = acpi_ns_get_attached_object(node); if (obj_desc) { if (((handler_type & ACPI_SYSTEM_NOTIFY) && obj_desc->common_notify.system_notify) || ((handler_type & ACPI_DEVICE_NOTIFY) && obj_desc->common_notify.device_notify)) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; } } else { obj_desc = acpi_ut_create_internal_object(node->type); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; } status = acpi_ns_attach_object(device, obj_desc, node->type); acpi_ut_remove_reference(obj_desc); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } } notify_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); if (!notify_obj) { status = AE_NO_MEMORY; goto unlock_and_exit; } notify_obj->notify.node = node; notify_obj->notify.handler = handler; notify_obj->notify.context = context; if (handler_type & ACPI_SYSTEM_NOTIFY) { obj_desc->common_notify.system_notify = notify_obj; } if (handler_type & ACPI_DEVICE_NOTIFY) { obj_desc->common_notify.device_notify = notify_obj; } if (handler_type == ACPI_ALL_NOTIFY) { acpi_ut_add_reference(notify_obj); } } unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); }
acpi_status acpi_install_notify_handler ( acpi_handle device, u32 handler_type, acpi_notify_handler handler, void *context) { acpi_operand_object *obj_desc; acpi_operand_object *notify_obj; acpi_namespace_node *device_node; acpi_status status = AE_OK; FUNCTION_TRACE ("Acpi_install_notify_handler"); /* Parameter validation */ if ((!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); /* Convert and validate the device handle */ device_node = acpi_ns_map_handle_to_node (device); if (!device_node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } /* * Root Object: * Registering a notify handler on the root object indicates that the * caller wishes to receive notifications for all objects. Note that * only one <external> global handler can be regsitered (per notify type). */ if (device == ACPI_ROOT_OBJECT) { /* Make sure the handler is not already installed */ if (((handler_type == ACPI_SYSTEM_NOTIFY) && acpi_gbl_sys_notify.handler) || ((handler_type == ACPI_DEVICE_NOTIFY) && acpi_gbl_drv_notify.handler)) { status = AE_EXIST; goto unlock_and_exit; } if (handler_type == ACPI_SYSTEM_NOTIFY) { acpi_gbl_sys_notify.node = device_node; acpi_gbl_sys_notify.handler = handler; acpi_gbl_sys_notify.context = context; } else /* ACPI_DEVICE_NOTIFY */ { acpi_gbl_drv_notify.node = device_node; acpi_gbl_drv_notify.handler = handler; acpi_gbl_drv_notify.context = context; } /* Global notify handler installed */ } /* * All Other Objects: * Caller will only receive notifications specific to the target object. * Note that only certain object types can receive notifications. */ else { /* * These are the ONLY objects that can receive ACPI notifications */ if ((device_node->type != ACPI_TYPE_DEVICE) && (device_node->type != ACPI_TYPE_PROCESSOR) && (device_node->type != ACPI_TYPE_POWER) && (device_node->type != ACPI_TYPE_THERMAL)) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } /* Check for an existing internal object */ obj_desc = acpi_ns_get_attached_object (device_node); if (obj_desc) { /* Object exists - make sure there's no handler */ if (((handler_type == ACPI_SYSTEM_NOTIFY) && obj_desc->device.sys_handler) || ((handler_type == ACPI_DEVICE_NOTIFY) && obj_desc->device.drv_handler)) { status = AE_EXIST; goto unlock_and_exit; } } else { /* Create a new object */ obj_desc = acpi_ut_create_internal_object (device_node->type); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; } /* Attach new object to the Node */ status = acpi_ns_attach_object (device, obj_desc, (u8) device_node->type); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } } /* Install the handler */ notify_obj = acpi_ut_create_internal_object (INTERNAL_TYPE_NOTIFY); if (!notify_obj) { status = AE_NO_MEMORY; goto unlock_and_exit; } notify_obj->notify_handler.node = device_node; notify_obj->notify_handler.handler = handler; notify_obj->notify_handler.context = context; if (handler_type == ACPI_SYSTEM_NOTIFY) { obj_desc->device.sys_handler = notify_obj; } else /* ACPI_DEVICE_NOTIFY */ { obj_desc->device.drv_handler = notify_obj; } } unlock_and_exit: acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (status); }
ACPI_STATUS acpi_ds_method_data_set_value ( u32 type, u32 index, ACPI_OPERAND_OBJECT *src_desc, ACPI_WALK_STATE *walk_state) { ACPI_STATUS status; ACPI_OPERAND_OBJECT **entry; /* Parameter validation */ if (!src_desc) { return (AE_BAD_PARAMETER); } /* Get a pointer to the requested method stack entry */ status = acpi_ds_method_data_get_entry (type, index, walk_state, &entry); if (ACPI_FAILURE (status)) { goto cleanup; } if (*entry == src_desc) { goto cleanup; } /* * If there is an object already in this slot, we either * have to delete it, or if this is an argument and there * is an object reference stored there, we have to do * an indirect store! */ if (*entry) { /* * Check for an indirect store if an argument * contains an object reference (stored as an Node). * We don't allow this automatic dereferencing for * locals, since a store to a local should overwrite * anything there, including an object reference. * * If both Arg0 and Local0 contain Ref_of (Local4): * * Store (1, Arg0) - Causes indirect store to local4 * Store (1, Local0) - Stores 1 in local0, overwriting * the reference to local4 * Store (1, De_refof (Local0)) - Causes indirect store to local4 * * Weird, but true. */ if ((type == MTH_TYPE_ARG) && (VALID_DESCRIPTOR_TYPE (*entry, ACPI_DESC_TYPE_NAMED))) { /* Detach an existing object from the Node */ acpi_ns_detach_object ((ACPI_NAMESPACE_NODE *) *entry); /* * Store this object into the Node * (do the indirect store) */ status = acpi_ns_attach_object ((ACPI_NAMESPACE_NODE *) *entry, src_desc, src_desc->common.type); return (status); } /* * Otherwise, just delete the existing object * before storing the new one */ acpi_ds_method_data_delete_value (type, index, walk_state); } /* * Install the Obj_stack descriptor (*Src_desc) into * the descriptor for the Arg or Local. * Install the new object in the stack entry * (increments the object reference count by one) */ status = acpi_ds_method_data_set_entry (type, index, src_desc, walk_state); if (ACPI_FAILURE (status)) { goto cleanup; } /* Normal exit */ return (AE_OK); /* Error exit */ cleanup: return (status); }
ACPI_STATUS acpi_ns_root_initialize (void) { ACPI_STATUS status = AE_OK; PREDEFINED_NAMES *init_val = NULL; ACPI_NAMESPACE_NODE *new_node; ACPI_OPERAND_OBJECT *obj_desc; acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); /* * The global root ptr is initially NULL, so a non-NULL value indicates * that Acpi_ns_root_initialize() has already been called; just return. */ if (acpi_gbl_root_node) { status = AE_OK; goto unlock_and_exit; } /* * Tell the rest of the subsystem that the root is initialized * (This is OK because the namespace is locked) */ acpi_gbl_root_node = &acpi_gbl_root_node_struct; /* Enter the pre-defined names in the name table */ for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) { status = acpi_ns_lookup (NULL, init_val->name, (OBJECT_TYPE_INTERNAL) init_val->type, IMODE_LOAD_PASS2, NS_NO_UPSEARCH, NULL, &new_node); /* * Name entered successfully. * If entry in Pre_defined_names[] specifies an * initial value, create the initial value. */ if (init_val->val) { /* * Entry requests an initial value, allocate a * descriptor for it. */ obj_desc = acpi_cm_create_internal_object ( (OBJECT_TYPE_INTERNAL) init_val->type); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; } /* * Convert value string from table entry to * internal representation. Only types actually * used for initial values are implemented here. */ switch (init_val->type) { case ACPI_TYPE_NUMBER: obj_desc->number.value = (ACPI_INTEGER) STRTOUL (init_val->val, NULL, 10); break; case ACPI_TYPE_STRING: obj_desc->string.length = (u16) STRLEN (init_val->val); /* * Allocate a buffer for the string. All * String.Pointers must be allocated buffers! * (makes deletion simpler) */ obj_desc->string.pointer = acpi_cm_allocate ( (obj_desc->string.length + 1)); if (!obj_desc->string.pointer) { acpi_cm_remove_reference (obj_desc); status = AE_NO_MEMORY; goto unlock_and_exit; } STRCPY (obj_desc->string.pointer, init_val->val); break; case ACPI_TYPE_MUTEX: obj_desc->mutex.sync_level = (u16) STRTOUL (init_val->val, NULL, 10); if (STRCMP (init_val->name, "_GL_") == 0) { /* * Create a counting semaphore for the * global lock */ status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 1, &obj_desc->mutex.semaphore); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } /* * We just created the mutex for the * global lock, save it */ acpi_gbl_global_lock_semaphore = obj_desc->mutex.semaphore; } else { /* Create a mutex */ status = acpi_os_create_semaphore (1, 1, &obj_desc->mutex.semaphore); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } } break; default: REPORT_ERROR (("Unsupported initial type value %X\n", init_val->type)); acpi_cm_remove_reference (obj_desc); obj_desc = NULL; continue; } /* Store pointer to value descriptor in the Node */ acpi_ns_attach_object (new_node, obj_desc, obj_desc->common.type); } } unlock_and_exit: acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); return (status); }
acpi_status acpi_ns_root_initialize(void) { acpi_status status; const struct acpi_predefined_names *init_val = NULL; struct acpi_namespace_node *new_node; union acpi_operand_object *obj_desc; acpi_string val = NULL; ACPI_FUNCTION_TRACE(ns_root_initialize); status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } if (acpi_gbl_root_node) { status = AE_OK; goto unlock_and_exit; } acpi_gbl_root_node = &acpi_gbl_root_node_struct; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Entering predefined entries into namespace\n")); for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) { if (!ACPI_STRCMP(init_val->name, "_OSI") && !acpi_gbl_create_osi_method) { continue; } status = acpi_ns_lookup(NULL, init_val->name, init_val->type, ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH, NULL, &new_node); if (ACPI_FAILURE(status) || (!new_node)) { ACPI_EXCEPTION((AE_INFO, status, "Could not create predefined name %s", init_val->name)); } if (init_val->val) { status = acpi_os_predefined_override(init_val, &val); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "Could not override predefined %s", init_val->name)); } if (!val) { val = init_val->val; } obj_desc = acpi_ut_create_internal_object(init_val->type); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; } switch (init_val->type) { case ACPI_TYPE_METHOD: obj_desc->method.param_count = (u8) ACPI_TO_INTEGER(val); obj_desc->common.flags |= AOPOBJ_DATA_VALID; #if defined (ACPI_ASL_COMPILER) new_node->value = obj_desc->method.param_count; #else obj_desc->method.info_flags = ACPI_METHOD_INTERNAL_ONLY; obj_desc->method.dispatch.implementation = acpi_ut_osi_implementation; #endif break; case ACPI_TYPE_INTEGER: obj_desc->integer.value = ACPI_TO_INTEGER(val); break; case ACPI_TYPE_STRING: obj_desc->string.length = (u32) ACPI_STRLEN(val); obj_desc->string.pointer = val; obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; break; case ACPI_TYPE_MUTEX: obj_desc->mutex.node = new_node; obj_desc->mutex.sync_level = (u8) (ACPI_TO_INTEGER(val) - 1); status = acpi_os_create_mutex(&obj_desc->mutex. os_mutex); if (ACPI_FAILURE(status)) { acpi_ut_remove_reference(obj_desc); goto unlock_and_exit; } if (ACPI_STRCMP(init_val->name, "_GL_") == 0) { acpi_gbl_global_lock_mutex = obj_desc; status = acpi_os_create_semaphore(1, 0, &acpi_gbl_global_lock_semaphore); if (ACPI_FAILURE(status)) { acpi_ut_remove_reference (obj_desc); goto unlock_and_exit; } } break; default: ACPI_ERROR((AE_INFO, "Unsupported initial type value 0x%X", init_val->type)); acpi_ut_remove_reference(obj_desc); obj_desc = NULL; continue; } status = acpi_ns_attach_object(new_node, obj_desc, obj_desc->common.type); acpi_ut_remove_reference(obj_desc); } } unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); if (ACPI_SUCCESS(status)) { status = acpi_ns_get_node(NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH, &acpi_gbl_fadt_gpe_device); } return_ACPI_STATUS(status); }
acpi_status acpi_ex_prep_field_value ( struct acpi_create_field_info *info) { union acpi_operand_object *obj_desc; u32 type; acpi_status status; ACPI_FUNCTION_TRACE ("ex_prep_field_value"); /* Parameter validation */ if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) { if (!info->region_node) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null region_node\n")); return_ACPI_STATUS (AE_AML_NO_OPERAND); } type = acpi_ns_get_type (info->region_node); if (type != ACPI_TYPE_REGION) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X %s\n", type, acpi_ut_get_type_name (type))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } } /* Allocate a new field object */ obj_desc = acpi_ut_create_internal_object (info->field_type); if (!obj_desc) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Initialize areas of the object that are common to all fields */ obj_desc->common_field.node = info->field_node; status = acpi_ex_prep_common_field_object (obj_desc, info->field_flags, info->attribute, info->field_bit_position, info->field_bit_length); if (ACPI_FAILURE (status)) { acpi_ut_delete_object_desc (obj_desc); return_ACPI_STATUS (status); } /* Initialize areas of the object that are specific to the field type */ switch (info->field_type) { case ACPI_TYPE_LOCAL_REGION_FIELD: obj_desc->field.region_obj = acpi_ns_get_attached_object (info->region_node); /* An additional reference for the container */ acpi_ut_add_reference (obj_desc->field.region_obj); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "region_field: Bitoff=%X Off=%X Gran=%X Region %p\n", obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset, obj_desc->field.access_byte_width, obj_desc->field.region_obj)); break; case ACPI_TYPE_LOCAL_BANK_FIELD: obj_desc->bank_field.value = info->bank_value; obj_desc->bank_field.region_obj = acpi_ns_get_attached_object (info->region_node); obj_desc->bank_field.bank_obj = acpi_ns_get_attached_object (info->register_node); /* An additional reference for the attached objects */ acpi_ut_add_reference (obj_desc->bank_field.region_obj); acpi_ut_add_reference (obj_desc->bank_field.bank_obj); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Bank Field: bit_off=%X Off=%X Gran=%X Region %p bank_reg %p\n", obj_desc->bank_field.start_field_bit_offset, obj_desc->bank_field.base_byte_offset, obj_desc->field.access_byte_width, obj_desc->bank_field.region_obj, obj_desc->bank_field.bank_obj)); break; case ACPI_TYPE_LOCAL_INDEX_FIELD: obj_desc->index_field.index_obj = acpi_ns_get_attached_object (info->register_node); obj_desc->index_field.data_obj = acpi_ns_get_attached_object (info->data_register_node); obj_desc->index_field.value = (u32) (info->field_bit_position / ACPI_MUL_8 (obj_desc->field.access_byte_width)); if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Index Object\n")); return_ACPI_STATUS (AE_AML_INTERNAL); } /* An additional reference for the attached objects */ acpi_ut_add_reference (obj_desc->index_field.data_obj); acpi_ut_add_reference (obj_desc->index_field.index_obj); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "index_field: bitoff=%X off=%X gran=%X Index %p Data %p\n", obj_desc->index_field.start_field_bit_offset, obj_desc->index_field.base_byte_offset, obj_desc->field.access_byte_width, obj_desc->index_field.index_obj, obj_desc->index_field.data_obj)); break; default: /* No other types should get here */ break; } /* * Store the constructed descriptor (obj_desc) into the parent Node, * preserving the current type of that named_obj. */ status = acpi_ns_attach_object (info->field_node, obj_desc, acpi_ns_get_type (info->field_node)); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "set named_obj %p (%4.4s) val = %p\n", info->field_node, info->field_node->name.ascii, obj_desc)); /* Remove local reference to the object */ acpi_ut_remove_reference (obj_desc); return_ACPI_STATUS (status); }
acpi_status acpi_install_notify_handler(acpi_handle device, u32 handler_type, acpi_notify_handler handler, void *context) { struct acpi_namespace_node *node = ACPI_CAST_PTR(struct acpi_namespace_node, device); union acpi_operand_object *obj_desc; union acpi_operand_object *handler_obj; acpi_status status; u32 i; ACPI_FUNCTION_TRACE(acpi_install_notify_handler); /* Parameter validation */ if ((!device) || (!handler) || (!handler_type) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* * Root Object: * Registering a notify handler on the root object indicates that the * caller wishes to receive notifications for all objects. Note that * only one global handler can be registered per notify type. * Ensure that a handler is not already installed. */ if (device == ACPI_ROOT_OBJECT) { for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { if (handler_type & (i + 1)) { if (acpi_gbl_global_notify[i].handler) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; } acpi_gbl_global_notify[i].handler = handler; acpi_gbl_global_notify[i].context = context; } } goto unlock_and_exit; /* Global notify handler installed, all done */ } /* * All Other Objects: * Caller will only receive notifications specific to the target * object. Note that only certain object types are allowed to * receive notifications. */ /* Are Notifies allowed on this object? */ if (!acpi_ev_is_notify_object(node)) { status = AE_TYPE; goto unlock_and_exit; } /* Check for an existing internal object, might not exist */ obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { /* Create a new object */ obj_desc = acpi_ut_create_internal_object(node->type); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; } /* Attach new object to the Node, remove local reference */ status = acpi_ns_attach_object(device, obj_desc, node->type); acpi_ut_remove_reference(obj_desc); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } } /* Ensure that the handler is not already installed in the lists */ for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { if (handler_type & (i + 1)) { handler_obj = obj_desc->common_notify.notify_list[i]; while (handler_obj) { if (handler_obj->notify.handler == handler) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; } handler_obj = handler_obj->notify.next[i]; } } } /* Create and populate a new notify handler object */ handler_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); if (!handler_obj) { status = AE_NO_MEMORY; goto unlock_and_exit; } handler_obj->notify.node = node; handler_obj->notify.handler_type = handler_type; handler_obj->notify.handler = handler; handler_obj->notify.context = context; /* Install the handler at the list head(s) */ for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { if (handler_type & (i + 1)) { handler_obj->notify.next[i] = obj_desc->common_notify.notify_list[i]; obj_desc->common_notify.notify_list[i] = handler_obj; } } /* Add an extra reference if handler was installed in both lists */ if (handler_type == ACPI_ALL_NOTIFY) { acpi_ut_add_reference(handler_obj); } unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); }
/******************************************************************************* * * FUNCTION: acpi_install_gpe_block * * PARAMETERS: gpe_device - Handle to the parent GPE Block Device * gpe_block_address - Address and space_iD * register_count - Number of GPE register pairs in the block * interrupt_number - H/W interrupt for the block * * RETURN: Status * * DESCRIPTION: Create and Install a block of GPE registers * ******************************************************************************/ acpi_status acpi_install_gpe_block(acpi_handle gpe_device, struct acpi_generic_address *gpe_block_address, u32 register_count, u32 interrupt_number) { acpi_status status; union acpi_operand_object *obj_desc; struct acpi_namespace_node *node; struct acpi_gpe_block_info *gpe_block; ACPI_FUNCTION_TRACE(acpi_install_gpe_block); if ((!gpe_device) || (!gpe_block_address) || (!register_count)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return (status); } node = acpi_ns_validate_handle(gpe_device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } /* * For user-installed GPE Block Devices, the gpe_block_base_number * is always zero */ status = acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0, interrupt_number, &gpe_block); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } /* Install block in the device_object attached to the node */ obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { /* * No object, create a new one (Device nodes do not always have * an attached object) */ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; } status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE); /* Remove local reference to the object */ acpi_ut_remove_reference(obj_desc); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } } /* Now install the GPE block in the device_object */ obj_desc->device.gpe_block = gpe_block; /* Enable the runtime GPEs in the new block */ status = acpi_ev_initialize_gpe_block(node, gpe_block); unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); }
acpi_status acpi_ds_create_buffer_field(union acpi_parse_object *op, struct acpi_walk_state *walk_state) { union acpi_parse_object *arg; struct acpi_namespace_node *node; acpi_status status; union acpi_operand_object *obj_desc; union acpi_operand_object *second_desc = NULL; u32 flags; ACPI_FUNCTION_TRACE(ds_create_buffer_field); /* * Get the name_string argument (name of the new buffer_field) */ if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { /* For create_field, name is the 4th argument */ arg = acpi_ps_get_arg(op, 3); } else { /* For all other create_XXXField operators, name is the 3rd argument */ arg = acpi_ps_get_arg(op, 2); } if (!arg) { return_ACPI_STATUS(AE_AML_NO_OPERAND); } if (walk_state->deferred_node) { node = walk_state->deferred_node; status = AE_OK; } else { /* Execute flag should always be set when this function is entered */ if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { return_ACPI_STATUS(AE_AML_INTERNAL); } /* Creating new namespace node, should not already exist */ flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND; /* * Mark node temporary if we are executing a normal control * method. (Don't mark if this is a module-level code method) */ if (walk_state->method_node && !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) { flags |= ACPI_NS_TEMPORARY; } /* Enter the name_string into the namespace */ status = acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1, flags, walk_state, &node); if (ACPI_FAILURE(status)) { ACPI_ERROR_NAMESPACE(arg->common.value.string, status); return_ACPI_STATUS(status); } } /* * We could put the returned object (Node) on the object stack for later, * but for now, we will put it in the "op" object that the parser uses, * so we can get it again at the end of this scope. */ op->common.node = node; /* * If there is no object attached to the node, this node was just created * and we need to create the field object. Otherwise, this was a lookup * of an existing node and we don't want to create the field object again. */ obj_desc = acpi_ns_get_attached_object(node); if (obj_desc) { return_ACPI_STATUS(AE_OK); } /* * The Field definition is not fully parsed at this time. * (We must save the address of the AML for the buffer and index operands) */ /* Create the buffer field object */ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD); if (!obj_desc) { status = AE_NO_MEMORY; goto cleanup; } /* * Remember location in AML stream of the field unit opcode and operands -- * since the buffer and index operands must be evaluated. */ second_desc = obj_desc->common.next_object; second_desc->extra.aml_start = op->named.data; second_desc->extra.aml_length = op->named.length; obj_desc->buffer_field.node = node; /* Attach constructed field descriptors to parent node */ status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_BUFFER_FIELD); if (ACPI_FAILURE(status)) { goto cleanup; } cleanup: /* Remove local reference to the object */ acpi_ut_remove_reference(obj_desc); return_ACPI_STATUS(status); }
/******************************************************************************* * * FUNCTION: acpi_ns_root_initialize * * PARAMETERS: None * * RETURN: Status * * DESCRIPTION: Allocate and initialize the default root named objects * * MUTEX: Locks namespace for entire execution * ******************************************************************************/ acpi_status acpi_ns_root_initialize(void) { acpi_status status; const struct acpi_predefined_names *init_val = NULL; struct acpi_namespace_node *new_node; union acpi_operand_object *obj_desc; acpi_string val = NULL; ACPI_FUNCTION_TRACE(ns_root_initialize); status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* * The global root ptr is initially NULL, so a non-NULL value indicates * that acpi_ns_root_initialize() has already been called; just return. */ if (acpi_gbl_root_node) { status = AE_OK; goto unlock_and_exit; } /* * Tell the rest of the subsystem that the root is initialized * (This is OK because the namespace is locked) */ acpi_gbl_root_node = &acpi_gbl_root_node_struct; /* Enter the pre-defined names in the name table */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Entering predefined entries into namespace\n")); for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) { /* _OSI is optional for now, will be permanent later */ if (!ACPI_STRCMP(init_val->name, "_OSI") && !acpi_gbl_create_osi_method) { continue; } status = acpi_ns_lookup(NULL, init_val->name, init_val->type, ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH, NULL, &new_node); if (ACPI_FAILURE(status) || (!new_node)) { /* Must be on same line for code converter */ ACPI_EXCEPTION((AE_INFO, status, "Could not create predefined name %s", init_val->name)); } /* * Name entered successfully. * If entry in pre_defined_names[] specifies an * initial value, create the initial value. */ if (init_val->val) { status = acpi_os_predefined_override(init_val, &val); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "Could not override predefined %s", init_val->name)); } if (!val) { val = init_val->val; } /* * Entry requests an initial value, allocate a * descriptor for it. */ obj_desc = acpi_ut_create_internal_object(init_val->type); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; } /* * Convert value string from table entry to * internal representation. Only types actually * used for initial values are implemented here. */ switch (init_val->type) { case ACPI_TYPE_METHOD: obj_desc->method.param_count = (u8) ACPI_TO_INTEGER(val); obj_desc->common.flags |= AOPOBJ_DATA_VALID; #if defined (ACPI_ASL_COMPILER) /* Save the parameter count for the i_aSL compiler */ new_node->value = obj_desc->method.param_count; #else /* Mark this as a very SPECIAL method */ obj_desc->method.method_flags = AML_METHOD_INTERNAL_ONLY; obj_desc->method.implementation = acpi_ut_osi_implementation; #endif break; case ACPI_TYPE_INTEGER: obj_desc->integer.value = ACPI_TO_INTEGER(val); break; case ACPI_TYPE_STRING: /* * Build an object around the static string */ obj_desc->string.length = (u32) ACPI_STRLEN(val); obj_desc->string.pointer = val; obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; break; case ACPI_TYPE_MUTEX: obj_desc->mutex.node = new_node; obj_desc->mutex.sync_level = (u8) (ACPI_TO_INTEGER(val) - 1); /* Create a mutex */ status = acpi_os_create_mutex(&obj_desc->mutex. os_mutex); if (ACPI_FAILURE(status)) { acpi_ut_remove_reference(obj_desc); goto unlock_and_exit; } /* Special case for ACPI Global Lock */ if (ACPI_STRCMP(init_val->name, "_GL_") == 0) { acpi_gbl_global_lock_mutex = obj_desc; /* Create additional counting semaphore for global lock */ status = acpi_os_create_semaphore(1, 0, &acpi_gbl_global_lock_semaphore); if (ACPI_FAILURE(status)) { acpi_ut_remove_reference (obj_desc); goto unlock_and_exit; } } break; default: ACPI_ERROR((AE_INFO, "Unsupported initial type value %X", init_val->type)); acpi_ut_remove_reference(obj_desc); obj_desc = NULL; continue; } /* Store pointer to value descriptor in the Node */ status = acpi_ns_attach_object(new_node, obj_desc, ACPI_GET_OBJECT_TYPE (obj_desc)); /* Remove local reference to the object */ acpi_ut_remove_reference(obj_desc); } } unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); /* Save a handle to "_GPE", it is always present */ if (ACPI_SUCCESS(status)) { status = acpi_ns_get_node(NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH, &acpi_gbl_fadt_gpe_device); } return_ACPI_STATUS(status); }
acpi_status acpi_ds_store_object_to_local ( u16 opcode, u32 index, acpi_operand_object *src_desc, acpi_walk_state *walk_state) { acpi_status status; acpi_operand_object **entry; FUNCTION_TRACE ("Ds_method_data_set_value"); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode=%d Idx=%d Obj=%p\n", opcode, index, src_desc)); /* Parameter validation */ if (!src_desc) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Get a pointer to the requested method stack entry */ status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); if (ACPI_FAILURE (status)) { goto cleanup; } if (*entry == src_desc) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p already installed!\n", src_desc)); goto cleanup; } /* * If there is an object already in this slot, we either * have to delete it, or if this is an argument and there * is an object reference stored there, we have to do * an indirect store! */ if (*entry) { /* * Check for an indirect store if an argument * contains an object reference (stored as an Node). * We don't allow this automatic dereferencing for * locals, since a store to a local should overwrite * anything there, including an object reference. * * If both Arg0 and Local0 contain Ref_of (Local4): * * Store (1, Arg0) - Causes indirect store to local4 * Store (1, Local0) - Stores 1 in local0, overwriting * the reference to local4 * Store (1, De_refof (Local0)) - Causes indirect store to local4 * * Weird, but true. */ if ((opcode == AML_ARG_OP) && (VALID_DESCRIPTOR_TYPE (*entry, ACPI_DESC_TYPE_NAMED))) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Arg (%p) is an Obj_ref(Node), storing in %p\n", src_desc, *entry)); /* Detach an existing object from the Node */ acpi_ns_detach_object ((acpi_namespace_node *) *entry); /* * Store this object into the Node * (do the indirect store) */ status = acpi_ns_attach_object ((acpi_namespace_node *) *entry, src_desc, src_desc->common.type); return_ACPI_STATUS (status); } #ifdef ACPI_ENABLE_IMPLICIT_CONVERSION /* * Perform "Implicit conversion" of the new object to the type of the * existing object */ status = acpi_ex_convert_to_target_type ((*entry)->common.type, &src_desc, walk_state); if (ACPI_FAILURE (status)) { goto cleanup; } #endif /* * Delete the existing object * before storing the new one */ acpi_ds_method_data_delete_value (opcode, index, walk_state); } /* * Install the Obj_stack descriptor (*Src_desc) into * the descriptor for the Arg or Local. * Install the new object in the stack entry * (increments the object reference count by one) */ status = acpi_ds_method_data_set_entry (opcode, index, src_desc, walk_state); if (ACPI_FAILURE (status)) { goto cleanup; } /* Normal exit */ return_ACPI_STATUS (AE_OK); /* Error exit */ cleanup: return_ACPI_STATUS (status); }