Exemplo n.º 1
0
ACPI_STATUS
AcpiDsRestartControlMethod (
    ACPI_WALK_STATE         *WalkState,
    ACPI_OPERAND_OBJECT     *ReturnDesc)
{
    ACPI_STATUS             Status;
    int                     SameAsImplicitReturn;


    ACPI_FUNCTION_TRACE_PTR (DsRestartControlMethod, WalkState);


    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n",
        AcpiUtGetNodeName (WalkState->MethodNode),
        WalkState->MethodCallOp, ReturnDesc));

    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "    ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n",
        WalkState->ReturnUsed,
        WalkState->Results, WalkState));

    /* Did the called method return a value? */

    if (ReturnDesc)
    {
        /* Is the implicit return object the same as the return desc? */

        SameAsImplicitReturn = (WalkState->ImplicitReturnObj == ReturnDesc);

        /* Are we actually going to use the return value? */

        if (WalkState->ReturnUsed)
        {
            /* Save the return value from the previous method */

            Status = AcpiDsResultPush (ReturnDesc, WalkState);
            if (ACPI_FAILURE (Status))
            {
                AcpiUtRemoveReference (ReturnDesc);
                return_ACPI_STATUS (Status);
            }

            /*
             * Save as THIS method's return value in case it is returned
             * immediately to yet another method
             */
            WalkState->ReturnDesc = ReturnDesc;
        }

        /*
         * The following code is the optional support for the so-called
         * "implicit return". Some AML code assumes that the last value of the
         * method is "implicitly" returned to the caller, in the absence of an
         * explicit return value.
         *
         * Just save the last result of the method as the return value.
         *
         * NOTE: this is optional because the ASL language does not actually
         * support this behavior.
         */
        else if (!AcpiDsDoImplicitReturn (ReturnDesc, WalkState, FALSE) ||
                 SameAsImplicitReturn)
        {
            /*
             * Delete the return value if it will not be used by the
             * calling method or remove one reference if the explicit return
             * is the same as the implicit return value.
             */
            AcpiUtRemoveReference (ReturnDesc);
        }
    }

    return_ACPI_STATUS (AE_OK);
}
Exemplo n.º 2
0
acpi_status
acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
			     union acpi_parse_object *op)
{
	acpi_status status;
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *operand_desc;
	struct acpi_namespace_node *node;
	union acpi_parse_object *next_op;

	ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);

	/*
	 * This is where we evaluate the address and length fields of the
	 * op_region declaration
	 */
	node = op->common.node;

	/* next_op points to the op that holds the space_iD */

	next_op = op->common.value.arg;

	/* next_op points to address op */

	next_op = next_op->common.next;

	/* Evaluate/create the address and length operands */

	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Resolve the length and address operands to numbers */

	status = acpi_ex_resolve_operands(op->common.aml_opcode,
					  ACPI_WALK_OPERANDS, walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {
		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	/*
	 * Get the length operand and save it
	 * (at Top of stack)
	 */
	operand_desc = walk_state->operands[walk_state->num_operands - 1];

	obj_desc->region.length = (u32) operand_desc->integer.value;
	acpi_ut_remove_reference(operand_desc);

	/*
	 * Get the address and save it
	 * (at top of stack - 1)
	 */
	operand_desc = walk_state->operands[walk_state->num_operands - 2];

	obj_desc->region.address = (acpi_physical_address)
	    operand_desc->integer.value;
	acpi_ut_remove_reference(operand_desc);

	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
			  obj_desc,
			  ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address),
			  obj_desc->region.length));

	/* Now the address and length are valid for this opregion */

	obj_desc->region.flags |= AOPOBJ_DATA_VALID;

	return_ACPI_STATUS(status);
}
Exemplo n.º 3
0
ACPI_STATUS
AcpiRsConvertAmlToResources (
    UINT8                   *Aml,
    UINT32                  Length,
    UINT32                  Offset,
    UINT8                   ResourceIndex,
    void                    **Context)
{
    ACPI_RESOURCE           **ResourcePtr = ACPI_CAST_INDIRECT_PTR (
                                ACPI_RESOURCE, Context);
    ACPI_RESOURCE           *Resource;
    AML_RESOURCE            *AmlResource;
    ACPI_RSCONVERT_INFO     *ConversionTable;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (RsConvertAmlToResources);


    /*
     * Check that the input buffer and all subsequent pointers into it
     * are aligned on a native word boundary. Most important on IA64
     */
    Resource = *ResourcePtr;
    if (ACPI_IS_MISALIGNED (Resource))
    {
        ACPI_WARNING ((AE_INFO,
            "Misaligned resource pointer %p", Resource));
    }

    /* Get the appropriate conversion info table */

    AmlResource = ACPI_CAST_PTR (AML_RESOURCE, Aml);

    if (AcpiUtGetResourceType (Aml) ==
        ACPI_RESOURCE_NAME_SERIAL_BUS)
    {
        if (AmlResource->CommonSerialBus.Type >
            AML_RESOURCE_MAX_SERIALBUSTYPE)
        {
            ConversionTable = NULL;
        }
        else
        {
            /* This is an I2C, SPI, or UART SerialBus descriptor */

            ConversionTable = AcpiGbl_ConvertResourceSerialBusDispatch [
                AmlResource->CommonSerialBus.Type];
        }
    }
    else
    {
        ConversionTable = AcpiGbl_GetResourceDispatch[ResourceIndex];
    }

    if (!ConversionTable)
    {
        ACPI_ERROR ((AE_INFO,
            "Invalid/unsupported resource descriptor: Type 0x%2.2X",
            ResourceIndex));
        return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
    }

     /* Convert the AML byte stream resource to a local resource struct */

    Status = AcpiRsConvertAmlToResource (
        Resource, AmlResource, ConversionTable);
    if (ACPI_FAILURE (Status))
    {
        ACPI_EXCEPTION ((AE_INFO, Status,
            "Could not convert AML resource (Type 0x%X)", *Aml));
        return_ACPI_STATUS (Status);
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_RESOURCES,
        "Type %.2X, AmlLength %.2X InternalLength %.2X\n",
        AcpiUtGetResourceType (Aml), Length,
        Resource->Length));

    /* Point to the next structure in the output buffer */

    *ResourcePtr = ACPI_NEXT_RESOURCE (Resource);
    return_ACPI_STATUS (AE_OK);
}
Exemplo n.º 4
0
static int acpi_processor_get_psd(struct acpi_processor	*pr)
{
	int result = 0;
	acpi_status status = AE_OK;
	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
	struct acpi_buffer format = {sizeof("NNNNN"), "NNNNN"};
	struct acpi_buffer state = {0, NULL};
	union acpi_object  *psd = NULL;
	struct acpi_psd_package *pdomain;

	status = acpi_evaluate_object(pr->handle, "_PSD", NULL, &buffer);
	if (ACPI_FAILURE(status)) {
		return -ENODEV;
	}

	psd = (union acpi_object *) buffer.pointer;
	if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) {
		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
		result = -EFAULT;
		goto end;
	}

	if (psd->package.count != 1) {
		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
		result = -EFAULT;
		goto end;
	}

	pdomain = &(pr->performance->domain_info);

	state.length = sizeof(struct acpi_psd_package);
	state.pointer = pdomain;

	status = acpi_extract_package(&(psd->package.elements[0]),
		&format, &state);
	if (ACPI_FAILURE(status)) {
		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
		result = -EFAULT;
		goto end;
	}

	if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) {
		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:num_entries\n"));
		result = -EFAULT;
		goto end;
	}

	if (pdomain->revision != ACPI_PSD_REV0_REVISION) {
		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:revision\n"));
		result = -EFAULT;
		goto end;
	}

	if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL &&
	    pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY &&
	    pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) {
		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD:coord_type\n"));
		result = -EFAULT;
		goto end;
	}

end:
	kfree(buffer.pointer);
	return result;
}
Exemplo n.º 5
0
Arquivo: nsparse.c Projeto: E-LLP/n900
/*******************************************************************************
 *
 * FUNCTION:    ns_one_complete_parse
 *
 * PARAMETERS:  pass_number             - 1 or 2
 *              table_desc              - The table to be parsed.
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Perform one complete parse of an ACPI/AML table.
 *
 ******************************************************************************/
acpi_status
acpi_ns_one_complete_parse(u32 pass_number,
			   u32 table_index,
			   struct acpi_namespace_node *start_node)
{
	union acpi_parse_object *parse_root;
	acpi_status status;
       u32 aml_length;
	u8 *aml_start;
	struct acpi_walk_state *walk_state;
	struct acpi_table_header *table;
	acpi_owner_id owner_id;

	ACPI_FUNCTION_TRACE(ns_one_complete_parse);

	status = acpi_tb_get_owner_id(table_index, &owner_id);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Create and init a Root Node */

	parse_root = acpi_ps_create_scope_op();
	if (!parse_root) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	/* Create and initialize a new walk state */

	walk_state = acpi_ds_create_walk_state(owner_id, NULL, NULL, NULL);
	if (!walk_state) {
		acpi_ps_free_op(parse_root);
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	status = acpi_get_table_by_index(table_index, &table);
	if (ACPI_FAILURE(status)) {
		acpi_ds_delete_walk_state(walk_state);
		acpi_ps_free_op(parse_root);
		return_ACPI_STATUS(status);
	}

	/* Table must consist of at least a complete header */

	if (table->length < sizeof(struct acpi_table_header)) {
		status = AE_BAD_HEADER;
	} else {
		aml_start = (u8 *) table + sizeof(struct acpi_table_header);
		aml_length = table->length - sizeof(struct acpi_table_header);
		status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL,
					       aml_start, aml_length, NULL,
					       (u8) pass_number);
	}

	if (ACPI_FAILURE(status)) {
		acpi_ds_delete_walk_state(walk_state);
		goto cleanup;
	}

	/* start_node is the default location to load the table */

	if (start_node && start_node != acpi_gbl_root_node) {
		status =
		    acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD,
					     walk_state);
		if (ACPI_FAILURE(status)) {
			acpi_ds_delete_walk_state(walk_state);
			goto cleanup;
		}
	}

	/* Parse the AML */

	ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "*PARSE* pass %d parse\n",
			  (unsigned)pass_number));
	status = acpi_ps_parse_aml(walk_state);

      cleanup:
	acpi_ps_delete_parse_tree(parse_root);
	return_ACPI_STATUS(status);
}
Exemplo n.º 6
0
ACPI_STATUS
AcpiRemoveNotifyHandler (
    ACPI_HANDLE             Device,
    UINT32                  HandlerType,
    ACPI_NOTIFY_HANDLER     Handler)
{
    ACPI_OPERAND_OBJECT     *NotifyObj;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);


    /* Parameter validation */

    if ((!Device)  ||
        (!Handler) ||
        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Convert and validate the device handle */

    Node = AcpiNsMapHandleToNode (Device);
    if (!Node)
    {
        Status = AE_BAD_PARAMETER;
        goto UnlockAndExit;
    }

    /* Root Object */

    if (Device == ACPI_ROOT_OBJECT)
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
            "Removing notify handler for namespace root object\n"));

        if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
              !AcpiGbl_SystemNotify.Handler)        ||
            ((HandlerType & ACPI_DEVICE_NOTIFY) &&
              !AcpiGbl_DeviceNotify.Handler))
        {
            Status = AE_NOT_EXIST;
            goto UnlockAndExit;
        }

        if (HandlerType & ACPI_SYSTEM_NOTIFY)
        {
            AcpiGbl_SystemNotify.Node    = NULL;
            AcpiGbl_SystemNotify.Handler = NULL;
            AcpiGbl_SystemNotify.Context = NULL;
        }

        if (HandlerType & ACPI_DEVICE_NOTIFY)
        {
            AcpiGbl_DeviceNotify.Node    = NULL;
            AcpiGbl_DeviceNotify.Handler = NULL;
            AcpiGbl_DeviceNotify.Context = NULL;
        }
    }

    /* All Other Objects */

    else
    {
        /* Notifies allowed on this object? */

        if (!AcpiEvIsNotifyObject (Node))
        {
            Status = AE_TYPE;
            goto UnlockAndExit;
        }

        /* Check for an existing internal object */

        ObjDesc = AcpiNsGetAttachedObject (Node);
        if (!ObjDesc)
        {
            Status = AE_NOT_EXIST;
            goto UnlockAndExit;
        }

        /* Object exists - make sure there's an existing handler */

        if (HandlerType & ACPI_SYSTEM_NOTIFY)
        {
            NotifyObj = ObjDesc->CommonNotify.SystemNotify;
            if (!NotifyObj)
            {
                Status = AE_NOT_EXIST;
                goto UnlockAndExit;
            }

            if (NotifyObj->Notify.Handler != Handler)
            {
                Status = AE_BAD_PARAMETER;
                goto UnlockAndExit;
            }

            /* Remove the handler */

            ObjDesc->CommonNotify.SystemNotify = NULL;
            AcpiUtRemoveReference (NotifyObj);
        }

        if (HandlerType & ACPI_DEVICE_NOTIFY)
        {
            NotifyObj = ObjDesc->CommonNotify.DeviceNotify;
            if (!NotifyObj)
            {
                Status = AE_NOT_EXIST;
                goto UnlockAndExit;
            }

            if (NotifyObj->Notify.Handler != Handler)
            {
                Status = AE_BAD_PARAMETER;
                goto UnlockAndExit;
            }

            /* Remove the handler */

            ObjDesc->CommonNotify.DeviceNotify = NULL;
            AcpiUtRemoveReference (NotifyObj);
        }
    }


UnlockAndExit:
    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    return_ACPI_STATUS (Status);
}
Exemplo n.º 7
0
static int acpi_processor_get_performance_states(struct acpi_processor *pr)
{
	int result = 0;
	acpi_status status = AE_OK;
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
	struct acpi_buffer format = { sizeof("NNNNNN"), "NNNNNN" };
	struct acpi_buffer state = { 0, NULL };
	union acpi_object *pss = NULL;
	int i;


	status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PSS"));
		return -ENODEV;
	}

	pss = (union acpi_object *)buffer.pointer;
	if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
		printk(KERN_ERR PREFIX "Invalid _PSS data\n");
		result = -EFAULT;
		goto end;
	}

	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n",
			  pss->package.count));

	pr->performance->state_count = pss->package.count;
	pr->performance->states =
	    kmalloc(sizeof(struct acpi_processor_px) * pss->package.count,
		    GFP_KERNEL);
	if (!pr->performance->states) {
		result = -ENOMEM;
		goto end;
	}

	for (i = 0; i < pr->performance->state_count; i++) {

		struct acpi_processor_px *px = &(pr->performance->states[i]);

		state.length = sizeof(struct acpi_processor_px);
		state.pointer = px;

		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));

		status = acpi_extract_package(&(pss->package.elements[i]),
					      &format, &state);
		if (ACPI_FAILURE(status)) {
			ACPI_EXCEPTION((AE_INFO, status, "Invalid _PSS data"));
			result = -EFAULT;
			kfree(pr->performance->states);
			goto end;
		}

		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
				  i,
				  (u32) px->core_frequency,
				  (u32) px->power,
				  (u32) px->transition_latency,
				  (u32) px->bus_master_latency,
				  (u32) px->control, (u32) px->status));

		/*
 		 * Check that ACPI's u64 MHz will be valid as u32 KHz in cpufreq
		 */
		if (!px->core_frequency ||
		    ((u32)(px->core_frequency * 1000) !=
		     (px->core_frequency * 1000))) {
			printk(KERN_ERR PREFIX
			       "Invalid BIOS _PSS frequency: 0x%llx MHz\n",
			       px->core_frequency);
			result = -EFAULT;
			kfree(pr->performance->states);
			goto end;
		}
	}

      end:
	kfree(buffer.pointer);

	return result;
}
Exemplo n.º 8
0
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);



    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 %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);



        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);
}
Exemplo n.º 9
0
static u32
acpi_ex_generate_access(u32 field_bit_offset,
                        u32 field_bit_length, u32 region_length)
{
    u32 field_byte_length;
    u32 field_byte_offset;
    u32 field_byte_end_offset;
    u32 access_byte_width;
    u32 field_start_offset;
    u32 field_end_offset;
    u32 minimum_access_width = 0xFFFFFFFF;
    u32 minimum_accesses = 0xFFFFFFFF;
    u32 accesses;

    ACPI_FUNCTION_TRACE(ex_generate_access);



    field_byte_offset = ACPI_DIV_8(ACPI_ROUND_DOWN(field_bit_offset, 8));
    field_byte_end_offset = ACPI_DIV_8(ACPI_ROUND_UP(field_bit_length +
                                       field_bit_offset, 8));
    field_byte_length = field_byte_end_offset - field_byte_offset;

    ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
                      "Bit length %d, Bit offset %d\n",
                      field_bit_length, field_bit_offset));

    ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
                      "Byte Length %d, Byte Offset %d, End Offset %d\n",
                      field_byte_length, field_byte_offset,
                      field_byte_end_offset));


    for (access_byte_width = 1; access_byte_width <= 8;
            access_byte_width <<= 1) {

        if (ACPI_ROUND_UP(field_byte_end_offset, access_byte_width) <=
                region_length) {
            field_start_offset =
                ACPI_ROUND_DOWN(field_byte_offset,
                                access_byte_width) /
                access_byte_width;

            field_end_offset =
                ACPI_ROUND_UP((field_byte_length +
                               field_byte_offset),
                              access_byte_width) /
                access_byte_width;

            accesses = field_end_offset - field_start_offset;

            ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
                              "AccessWidth %d end is within region\n",
                              access_byte_width));

            ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
                              "Field Start %d, Field End %d -- requires %d accesses\n",
                              field_start_offset, field_end_offset,
                              accesses));



            if (accesses <= 1) {
                ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
                                  "Entire field can be accessed with one operation of size %d\n",
                                  access_byte_width));
                return_VALUE(access_byte_width);
            }


            if (accesses < minimum_accesses) {
                minimum_accesses = accesses;
                minimum_access_width = access_byte_width;
            }
        } else {
            ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
                              "AccessWidth %d end is NOT within region\n",
                              access_byte_width));
            if (access_byte_width == 1) {
                ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
                                  "Field goes beyond end-of-region!\n"));



                return_VALUE(0);
            }


            ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
                              "Backing off to previous optimal access width of %d\n",
                              minimum_access_width));
            return_VALUE(minimum_access_width);
        }
    }


    ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
                      "Cannot access field in one operation, using width 8\n"));
    return_VALUE(8);
}
Exemplo n.º 10
0
acpi_status
acpi_ds_init_one_object (
	acpi_handle                     obj_handle,
	u32                             level,
	void                            *context,
	void                            **return_value)
{
	acpi_object_type                type;
	acpi_status                     status;
	struct acpi_init_walk_info      *info = (struct acpi_init_walk_info *) context;


	ACPI_FUNCTION_NAME ("ds_init_one_object");


	/*
	 * We are only interested in objects owned by the table that
	 * was just loaded
	 */
	if (((struct acpi_namespace_node *) obj_handle)->owner_id !=
			info->table_desc->table_id) {
		return (AE_OK);
	}

	info->object_count++;

	/* And even then, we are only interested in a few object types */

	type = acpi_ns_get_type (obj_handle);

	switch (type) {
	case ACPI_TYPE_REGION:

		status = acpi_ds_initialize_region (obj_handle);
		if (ACPI_FAILURE (status)) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region %p [%4.4s] - Init failure, %s\n",
				obj_handle, acpi_ut_get_node_name (obj_handle),
				acpi_format_exception (status)));
		}

		info->op_region_count++;
		break;


	case ACPI_TYPE_METHOD:

		info->method_count++;

		/* Print a dot for each method unless we are going to print the entire pathname */

		if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
		}

		/*
		 * Set the execution data width (32 or 64) based upon the
		 * revision number of the parent ACPI table.
		 * TBD: This is really for possible future support of integer width
		 * on a per-table basis. Currently, we just use a global for the width.
		 */
		if (info->table_desc->pointer->revision == 1) {
			((struct acpi_namespace_node *) obj_handle)->flags |= ANOBJ_DATA_WIDTH_32;
		}

		/*
		 * Always parse methods to detect errors, we will delete
		 * the parse tree below
		 */
		status = acpi_ds_parse_method (obj_handle);
		if (ACPI_FAILURE (status)) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Method %p [%4.4s] - parse failure, %s\n",
				obj_handle, acpi_ut_get_node_name (obj_handle),
				acpi_format_exception (status)));

			/* This parse failed, but we will continue parsing more methods */

			break;
		}

		/*
		 * Delete the parse tree.  We simply re-parse the method
		 * for every execution since there isn't much overhead
		 */
		acpi_ns_delete_namespace_subtree (obj_handle);
		acpi_ns_delete_namespace_by_owner (((struct acpi_namespace_node *) obj_handle)->object->method.owning_id);
		break;


	case ACPI_TYPE_DEVICE:

		info->device_count++;
		break;


	default:
		break;
	}

	/*
	 * We ignore errors from above, and always return OK, since
	 * we don't want to abort the walk on a single error.
	 */
	return (AE_OK);
}
Exemplo n.º 11
0
ACPI_STATUS
AcpiUtGetSimpleObjectSize (
    ACPI_OPERAND_OBJECT     *InternalObject,
    ACPI_SIZE               *ObjLength)
{
    ACPI_SIZE               Length;
    ACPI_STATUS             Status = AE_OK;


    ACPI_FUNCTION_TRACE_PTR ("UtGetSimpleObjectSize", InternalObject);


    /* Handle a null object (Could be a uninitialized package element -- which is legal) */

    if (!InternalObject)
    {
        *ObjLength = 0;
        return_ACPI_STATUS (AE_OK);
    }

    /* Start with the length of the Acpi object */

    Length = sizeof (ACPI_OBJECT);

    if (ACPI_GET_DESCRIPTOR_TYPE (InternalObject) == ACPI_DESC_TYPE_NAMED)
    {
        /* Object is a named object (reference), just return the length */

        *ObjLength = ACPI_ROUND_UP_TO_NATIVE_WORD (Length);
        return_ACPI_STATUS (Status);
    }

    /*
     * The final length depends on the object type
     * Strings and Buffers are packed right up against the parent object and
     * must be accessed bytewise or there may be alignment problems on
     * certain processors
     */
    switch (ACPI_GET_OBJECT_TYPE (InternalObject))
    {
    case ACPI_TYPE_STRING:

        Length += (ACPI_SIZE) InternalObject->String.Length + 1;
        break;


    case ACPI_TYPE_BUFFER:

        Length += (ACPI_SIZE) InternalObject->Buffer.Length;
        break;


    case ACPI_TYPE_INTEGER:
    case ACPI_TYPE_PROCESSOR:
    case ACPI_TYPE_POWER:

        /*
         * No extra data for these types
         */
        break;


    case ACPI_TYPE_LOCAL_REFERENCE:

        switch (InternalObject->Reference.Opcode)
        {
        case AML_INT_NAMEPATH_OP:

            /*
             * Get the actual length of the full pathname to this object.
             * The reference will be converted to the pathname to the object
             */
            Length += ACPI_ROUND_UP_TO_NATIVE_WORD (AcpiNsGetPathnameLength (InternalObject->Reference.Node));
            break;

        default:

            /*
             * No other reference opcodes are supported.
             * Notably, Locals and Args are not supported, but this may be
             * required eventually.
             */
            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
                "Unsupported Reference opcode=%X in object %p\n",
                InternalObject->Reference.Opcode, InternalObject));
            Status = AE_TYPE;
            break;
        }
        break;


    default:

        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported type=%X in object %p\n",
            ACPI_GET_OBJECT_TYPE (InternalObject), InternalObject));
        Status = AE_TYPE;
        break;
    }

    /*
     * Account for the space required by the object rounded up to the next
     * multiple of the machine word size.  This keeps each object aligned
     * on a machine word boundary. (preventing alignment faults on some
     * machines.)
     */
    *ObjLength = ACPI_ROUND_UP_TO_NATIVE_WORD (Length);
    return_ACPI_STATUS (Status);
}
Exemplo n.º 12
0
/*******************************************************************************
 *
 * 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;

#ifndef ACPI_DUMP_APP
				obj_desc->method.implementation =
				    acpi_ut_osi_implementation;
#endif
#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);

				if (ACPI_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)) {
						acpi_ut_remove_reference
						    (obj_desc);
						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)) {
						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_by_path("\\_GPE", NULL,
					     ACPI_NS_NO_UPSEARCH,
					     &acpi_gbl_fadt_gpe_device);
	}

	return_ACPI_STATUS(status);
}
Exemplo n.º 13
0
acpi_status
acpi_ns_lookup(union acpi_generic_state *scope_info,
	       char *pathname,
	       acpi_object_type type,
	       acpi_interpreter_mode interpreter_mode,
	       u32 flags,
	       struct acpi_walk_state *walk_state,
	       struct acpi_namespace_node **return_node)
{
	acpi_status status;
	char *path = pathname;
	struct acpi_namespace_node *prefix_node;
	struct acpi_namespace_node *current_node = NULL;
	struct acpi_namespace_node *this_node = NULL;
	u32 num_segments;
	u32 num_carats;
	acpi_name simple_name;
	acpi_object_type type_to_check_for;
	acpi_object_type this_search_type;
	u32 search_parent_flag = ACPI_NS_SEARCH_PARENT;
	u32 local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND |
				    ACPI_NS_SEARCH_PARENT);

	ACPI_FUNCTION_TRACE("ns_lookup");

	if (!return_node) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	acpi_gbl_ns_lookup_count++;
	*return_node = ACPI_ENTRY_NOT_FOUND;

	if (!acpi_gbl_root_node) {
		return_ACPI_STATUS(AE_NO_NAMESPACE);
	}

	/*
	 * Get the prefix scope.
	 * A null scope means use the root scope
	 */
	if ((!scope_info) || (!scope_info->scope.node)) {
		ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
				  "Null scope prefix, using root node (%p)\n",
				  acpi_gbl_root_node));

		prefix_node = acpi_gbl_root_node;
	} else {
		prefix_node = scope_info->scope.node;
		if (ACPI_GET_DESCRIPTOR_TYPE(prefix_node) !=
		    ACPI_DESC_TYPE_NAMED) {
			ACPI_ERROR((AE_INFO, "%p is not a namespace node [%s]",
				    prefix_node,
				    acpi_ut_get_descriptor_name(prefix_node)));
			return_ACPI_STATUS(AE_AML_INTERNAL);
		}

		/*
		 * This node might not be a actual "scope" node (such as a
		 * Device/Method, etc.)  It could be a Package or other object node.
		 * Backup up the tree to find the containing scope node.
		 */
		while (!acpi_ns_opens_scope(prefix_node->type) &&
		       prefix_node->type != ACPI_TYPE_ANY) {
			prefix_node = acpi_ns_get_parent_node(prefix_node);
		}
	}

	/* Save type   TBD: may be no longer necessary */

	type_to_check_for = type;

	/*
	 * Begin examination of the actual pathname
	 */
	if (!pathname) {
		/* A Null name_path is allowed and refers to the root */

		num_segments = 0;
		this_node = acpi_gbl_root_node;
		path = "";

		ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
				  "Null Pathname (Zero segments), Flags=%X\n",
				  flags));
	} else {
		/*
		 * Name pointer is valid (and must be in internal name format)
		 *
		 * Check for scope prefixes:
		 *
		 * As represented in the AML stream, a namepath consists of an
		 * optional scope prefix followed by a name segment part.
		 *
		 * If present, the scope prefix is either a Root Prefix (in
		 * which case the name is fully qualified), or one or more
		 * Parent Prefixes (in which case the name's scope is relative
		 * to the current scope).
		 */
		if (*path == (u8) AML_ROOT_PREFIX) {
			/* Pathname is fully qualified, start from the root */

			this_node = acpi_gbl_root_node;
			search_parent_flag = ACPI_NS_NO_UPSEARCH;

			/* Point to name segment part */

			path++;

			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
					  "Path is absolute from root [%p]\n",
					  this_node));
		} else {
			/* Pathname is relative to current scope, start there */

			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
					  "Searching relative to prefix scope [%4.4s] (%p)\n",
					  acpi_ut_get_node_name(prefix_node),
					  prefix_node));

			/*
			 * Handle multiple Parent Prefixes (carat) by just getting
			 * the parent node for each prefix instance.
			 */
			this_node = prefix_node;
			num_carats = 0;
			while (*path == (u8) AML_PARENT_PREFIX) {
				/* Name is fully qualified, no search rules apply */

				search_parent_flag = ACPI_NS_NO_UPSEARCH;
				/*
				 * Point past this prefix to the name segment
				 * part or the next Parent Prefix
				 */
				path++;

				/* Backup to the parent node */

				num_carats++;
				this_node = acpi_ns_get_parent_node(this_node);
				if (!this_node) {
					/* Current scope has no parent scope */

					ACPI_ERROR((AE_INFO,
						    "ACPI path has too many parent prefixes (^) - reached beyond root node"));
					return_ACPI_STATUS(AE_NOT_FOUND);
				}
			}

			if (search_parent_flag == ACPI_NS_NO_UPSEARCH) {
				ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
						  "Search scope is [%4.4s], path has %d carat(s)\n",
						  acpi_ut_get_node_name
						  (this_node), num_carats));
			}
		}

		/*
		 * Determine the number of ACPI name segments in this pathname.
		 *
		 * The segment part consists of either:
		 *  - A Null name segment (0)
		 *  - A dual_name_prefix followed by two 4-byte name segments
		 *  - A multi_name_prefix followed by a byte indicating the
		 *      number of segments and the segments themselves.
		 *  - A single 4-byte name segment
		 *
		 * Examine the name prefix opcode, if any, to determine the number of
		 * segments.
		 */
		switch (*path) {
		case 0:
			/*
			 * Null name after a root or parent prefixes. We already
			 * have the correct target node and there are no name segments.
			 */
			num_segments = 0;
			type = this_node->type;

			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
					  "Prefix-only Pathname (Zero name segments), Flags=%X\n",
					  flags));
			break;

		case AML_DUAL_NAME_PREFIX:

			/* More than one name_seg, search rules do not apply */

			search_parent_flag = ACPI_NS_NO_UPSEARCH;

			/* Two segments, point to first name segment */

			num_segments = 2;
			path++;

			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
					  "Dual Pathname (2 segments, Flags=%X)\n",
					  flags));
			break;

		case AML_MULTI_NAME_PREFIX_OP:

			/* More than one name_seg, search rules do not apply */

			search_parent_flag = ACPI_NS_NO_UPSEARCH;

			/* Extract segment count, point to first name segment */

			path++;
			num_segments = (u32) (u8) * path;
			path++;

			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
					  "Multi Pathname (%d Segments, Flags=%X)\n",
					  num_segments, flags));
			break;

		default:
			/*
			 * Not a Null name, no Dual or Multi prefix, hence there is
			 * only one name segment and Pathname is already pointing to it.
			 */
			num_segments = 1;

			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
					  "Simple Pathname (1 segment, Flags=%X)\n",
					  flags));
			break;
		}

		ACPI_DEBUG_EXEC(acpi_ns_print_pathname(num_segments, path));
	}

	/*
	 * Search namespace for each segment of the name.  Loop through and
	 * verify (or add to the namespace) each name segment.
	 *
	 * The object type is significant only at the last name
	 * segment.  (We don't care about the types along the path, only
	 * the type of the final target object.)
	 */
	this_search_type = ACPI_TYPE_ANY;
	current_node = this_node;
	while (num_segments && current_node) {
		num_segments--;
		if (!num_segments) {
			/*
			 * This is the last segment, enable typechecking
			 */
			this_search_type = type;

			/*
			 * Only allow automatic parent search (search rules) if the caller
			 * requested it AND we have a single, non-fully-qualified name_seg
			 */
			if ((search_parent_flag != ACPI_NS_NO_UPSEARCH) &&
			    (flags & ACPI_NS_SEARCH_PARENT)) {
				local_flags |= ACPI_NS_SEARCH_PARENT;
			}

			/* Set error flag according to caller */

			if (flags & ACPI_NS_ERROR_IF_FOUND) {
				local_flags |= ACPI_NS_ERROR_IF_FOUND;
			}
		}

		/* Extract one ACPI name from the front of the pathname */

		ACPI_MOVE_32_TO_32(&simple_name, path);

		/* Try to find the single (4 character) ACPI name */

		status =
		    acpi_ns_search_and_enter(simple_name, walk_state,
					     current_node, interpreter_mode,
					     this_search_type, local_flags,
					     &this_node);
		if (ACPI_FAILURE(status)) {
			if (status == AE_NOT_FOUND) {
				/* Name not found in ACPI namespace */

				ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
						  "Name [%4.4s] not found in scope [%4.4s] %p\n",
						  (char *)&simple_name,
						  (char *)&current_node->name,
						  current_node));
			}

			*return_node = this_node;
			return_ACPI_STATUS(status);
		}

		/*
		 * Sanity typecheck of the target object:
		 *
		 * If 1) This is the last segment (num_segments == 0)
		 *    2) And we are looking for a specific type
		 *       (Not checking for TYPE_ANY)
		 *    3) Which is not an alias
		 *    4) Which is not a local type (TYPE_SCOPE)
		 *    5) And the type of target object is known (not TYPE_ANY)
		 *    6) And target object does not match what we are looking for
		 *
		 * Then we have a type mismatch.  Just warn and ignore it.
		 */
		if ((num_segments == 0) &&
		    (type_to_check_for != ACPI_TYPE_ANY) &&
		    (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) &&
		    (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) &&
		    (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) &&
		    (this_node->type != ACPI_TYPE_ANY) &&
		    (this_node->type != type_to_check_for)) {
			/* Complain about a type mismatch */

			ACPI_WARNING((AE_INFO,
				      "ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)",
				      ACPI_CAST_PTR(char, &simple_name),
				      acpi_ut_get_type_name(this_node->type),
				      acpi_ut_get_type_name
				      (type_to_check_for)));
		}

		/*
		 * If this is the last name segment and we are not looking for a
		 * specific type, but the type of found object is known, use that type
		 * to see if it opens a scope.
		 */
		if ((num_segments == 0) && (type == ACPI_TYPE_ANY)) {
			type = this_node->type;
		}

		/* Point to next name segment and make this node current */

		path += ACPI_NAME_SIZE;
		current_node = this_node;
	}
Exemplo n.º 14
0
void
AcpiDsTerminateControlMethod (
    ACPI_OPERAND_OBJECT     *MethodDesc,
    ACPI_WALK_STATE         *WalkState)
{

    ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState);


    /* MethodDesc is required, WalkState is optional */

    if (!MethodDesc)
    {
        return_VOID;
    }

    if (WalkState)
    {
        /* Delete all arguments and locals */

        AcpiDsMethodDataDeleteAll (WalkState);

        /*
         * If method is serialized, release the mutex and restore the
         * current sync level for this thread
         */
        if (MethodDesc->Method.Mutex)
        {
            /* Acquisition Depth handles recursive calls */

            MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--;
            if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth)
            {
                WalkState->Thread->CurrentSyncLevel =
                    MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel;

                AcpiOsReleaseMutex (MethodDesc->Method.Mutex->Mutex.OsMutex);
                MethodDesc->Method.Mutex->Mutex.ThreadId = 0;
            }
        }

        /*
         * Delete any namespace objects created anywhere within the
         * namespace by the execution of this method. Unless:
         * 1) This method is a module-level executable code method, in which
         *    case we want make the objects permanent.
         * 2) There are other threads executing the method, in which case we
         *    will wait until the last thread has completed.
         */
        if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) &&
             (MethodDesc->Method.ThreadCount == 1))
        {
            /* Delete any direct children of (created by) this method */

            AcpiNsDeleteNamespaceSubtree (WalkState->MethodNode);

            /*
             * Delete any objects that were created by this method
             * elsewhere in the namespace (if any were created).
             * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the
             * deletion such that we don't have to perform an entire
             * namespace walk for every control method execution.
             */
            if (MethodDesc->Method.InfoFlags & ACPI_METHOD_MODIFIED_NAMESPACE)
            {
                AcpiNsDeleteNamespaceByOwner (MethodDesc->Method.OwnerId);
                MethodDesc->Method.InfoFlags &= ~ACPI_METHOD_MODIFIED_NAMESPACE;
            }
        }
    }

    /* Decrement the thread count on the method */

    if (MethodDesc->Method.ThreadCount)
    {
        MethodDesc->Method.ThreadCount--;
    }
    else
    {
        ACPI_ERROR ((AE_INFO,
            "Invalid zero thread count in method"));
    }

    /* Are there any other threads currently executing this method? */

    if (MethodDesc->Method.ThreadCount)
    {
        /*
         * Additional threads. Do not release the OwnerId in this case,
         * we immediately reuse it for the next thread executing this method
         */
        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
            "*** Completed execution of one thread, %u threads remaining\n",
            MethodDesc->Method.ThreadCount));
    }
    else
    {
        /* This is the only executing thread for this method */

        /*
         * Support to dynamically change a method from NotSerialized to
         * Serialized if it appears that the method is incorrectly written and
         * does not support multiple thread execution. The best example of this
         * is if such a method creates namespace objects and blocks. A second
         * thread will fail with an AE_ALREADY_EXISTS exception.
         *
         * This code is here because we must wait until the last thread exits
         * before marking the method as serialized.
         */
        if (MethodDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED_PENDING)
        {
            if (WalkState)
            {
                ACPI_INFO ((AE_INFO,
                    "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error",
                    WalkState->MethodNode->Name.Ascii));
            }

            /*
             * Method tried to create an object twice and was marked as
             * "pending serialized". The probable cause is that the method
             * cannot handle reentrancy.
             *
             * The method was created as NotSerialized, but it tried to create
             * a named object and then blocked, causing the second thread
             * entrance to begin and then fail. Workaround this problem by
             * marking the method permanently as Serialized when the last
             * thread exits here.
             */
            MethodDesc->Method.InfoFlags &= ~ACPI_METHOD_SERIALIZED_PENDING;
            MethodDesc->Method.InfoFlags |=
                (ACPI_METHOD_SERIALIZED | ACPI_METHOD_IGNORE_SYNC_LEVEL);
            MethodDesc->Method.SyncLevel = 0;
        }

        /* No more threads, we can free the OwnerId */

        if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL))
        {
            AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId);
        }
    }

    return_VOID;
}
Exemplo n.º 15
0
acpi_status
acpi_ex_setup_region (
	union acpi_operand_object       *obj_desc,
	u32                             field_datum_byte_offset)
{
	acpi_status                     status = AE_OK;
	union acpi_operand_object       *rgn_desc;


	ACPI_FUNCTION_TRACE_U32 ("ex_setup_region", field_datum_byte_offset);


	rgn_desc = obj_desc->common_field.region_obj;

	/* We must have a valid region */

	if (ACPI_GET_OBJECT_TYPE (rgn_desc) != ACPI_TYPE_REGION) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X (%s)\n",
			ACPI_GET_OBJECT_TYPE (rgn_desc),
			acpi_ut_get_object_type_name (rgn_desc)));

		return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
	}

	/*
	 * If the Region Address and Length have not been previously evaluated,
	 * evaluate them now and save the results.
	 */
	if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) {
		status = acpi_ds_get_region_arguments (rgn_desc);
		if (ACPI_FAILURE (status)) {
			return_ACPI_STATUS (status);
		}
	}

	if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) {
		/* SMBus has a non-linear address space */

		return_ACPI_STATUS (AE_OK);
	}

#ifdef ACPI_UNDER_DEVELOPMENT
	/*
	 * If the Field access is any_acc, we can now compute the optimal
	 * access (because we know know the length of the parent region)
	 */
	if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
		if (ACPI_FAILURE (status)) {
			return_ACPI_STATUS (status);
		}
	}
#endif

	/*
	 * Validate the request.  The entire request from the byte offset for a
	 * length of one field datum (access width) must fit within the region.
	 * (Region length is specified in bytes)
	 */
	if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset
			   + field_datum_byte_offset
			   + obj_desc->common_field.access_byte_width)) {
		if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) {
			/*
			 * This is the case where the access_type (acc_word, etc.) is wider
			 * than the region itself.  For example, a region of length one
			 * byte, and a field with Dword access specified.
			 */
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n",
				acpi_ut_get_node_name (obj_desc->common_field.node),
				obj_desc->common_field.access_byte_width,
				acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length));
		}

		/*
		 * Offset rounded up to next multiple of field width
		 * exceeds region length, indicate an error
		 */
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
			"Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n",
			acpi_ut_get_node_name (obj_desc->common_field.node),
			obj_desc->common_field.base_byte_offset,
			field_datum_byte_offset, obj_desc->common_field.access_byte_width,
			acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length));

		if (!acpi_strict) {
			/*
			 * Allow access to the field if it is within the region size
			 * rounded up to a multiple of the access byte width.  This
			 * overcomes "off-by-one" programming errors in the AML often
			 * found in Toshiba laptops.  These errors were allowed by
			 * the Microsoft ASL compiler.
			 */
			u32 rounded_length = ACPI_ROUND_UP(rgn_desc->region.length,
									obj_desc->common_field.access_byte_width);

			if (rounded_length < (obj_desc->common_field.base_byte_offset
						+ field_datum_byte_offset
						+ obj_desc->common_field.access_byte_width)) {
				return_ACPI_STATUS (AE_AML_REGION_LIMIT);
			} else {
				static int	warn_once = 1;
				if (warn_once) {
					// Could also associate a flag with each field, and
					// warn once for each field.
					ACPI_REPORT_WARNING((
						"The ACPI AML in your computer contains errors, "
						"please nag the manufacturer to correct it.\n"));
					ACPI_REPORT_WARNING((
						"Allowing relaxed access to fields; "
						"turn on CONFIG_ACPI_DEBUG for details.\n"));
					warn_once = 0;
				}
				return_ACPI_STATUS (AE_OK);
			}
		}
		else {
			return_ACPI_STATUS (AE_AML_REGION_LIMIT);
		}
	}

	return_ACPI_STATUS (AE_OK);
}
int acpi_pci_bind(struct acpi_device *device)
{
	int result = 0;
	acpi_status status;
	struct acpi_pci_data *data;
	struct acpi_pci_data *pdata;
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
	acpi_handle handle;

	if (!device || !device->parent)
		return -EINVAL;

	data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
	if (ACPI_FAILURE(status)) {
		kfree(data);
		return -ENODEV;
	}

	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n",
			  (char *)buffer.pointer));

	/* 
	 * Segment & Bus
	 * -------------
	 * These are obtained via the parent device's ACPI-PCI context.
	 */
	status = acpi_get_data(device->parent->handle, acpi_pci_data_handler,
			       (void **)&pdata);
	if (ACPI_FAILURE(status) || !pdata || !pdata->bus) {
		ACPI_EXCEPTION((AE_INFO, status,
				"Invalid ACPI-PCI context for parent device %s",
				acpi_device_bid(device->parent)));
		result = -ENODEV;
		goto end;
	}
	data->id.segment = pdata->id.segment;
	data->id.bus = pdata->bus->number;

	/*
	 * Device & Function
	 * -----------------
	 * These are simply obtained from the device's _ADR method.  Note
	 * that a value of zero is valid.
	 */
	data->id.device = device->pnp.bus_address >> 16;
	data->id.function = device->pnp.bus_address & 0xFFFF;

	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %04x:%02x:%02x.%d\n",
			  data->id.segment, data->id.bus, data->id.device,
			  data->id.function));

	/*
	 * TBD: Support slot devices (e.g. function=0xFFFF).
	 */

	/* 
	 * Locate PCI Device
	 * -----------------
	 * Locate matching device in PCI namespace.  If it doesn't exist
	 * this typically means that the device isn't currently inserted
	 * (e.g. docking station, port replicator, etc.).
	 */
	data->dev = pci_get_slot(pdata->bus,
				PCI_DEVFN(data->id.device, data->id.function));
	if (!data->dev) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "Device %04x:%02x:%02x.%d not present in PCI namespace\n",
				  data->id.segment, data->id.bus,
				  data->id.device, data->id.function));
		result = -ENODEV;
		goto end;
	}
	if (!data->dev->bus) {
		printk(KERN_ERR PREFIX
			    "Device %04x:%02x:%02x.%d has invalid 'bus' field\n",
			    data->id.segment, data->id.bus,
			    data->id.device, data->id.function);
		result = -ENODEV;
		goto end;
	}

	/*
	 * PCI Bridge?
	 * -----------
	 * If so, set the 'bus' field and install the 'bind' function to 
	 * facilitate callbacks for all of its children.
	 */
	if (data->dev->subordinate) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "Device %04x:%02x:%02x.%d is a PCI bridge\n",
				  data->id.segment, data->id.bus,
				  data->id.device, data->id.function));
		data->bus = data->dev->subordinate;
		device->ops.bind = acpi_pci_bind;
		device->ops.unbind = acpi_pci_unbind;
	}

	/*
	 * Attach ACPI-PCI Context
	 * -----------------------
	 * Thus binding the ACPI and PCI devices.
	 */
	status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status,
				"Unable to attach ACPI-PCI context to device %s",
				acpi_device_bid(device)));
		result = -ENODEV;
		goto end;
	}

	/*
	 * PCI Routing Table
	 * -----------------
	 * Evaluate and parse _PRT, if exists.  This code is independent of 
	 * PCI bridges (above) to allow parsing of _PRT objects within the
	 * scope of non-bridge devices.  Note that _PRTs within the scope of
	 * a PCI bridge assume the bridge's subordinate bus number.
	 *
	 * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
	 */
	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
	if (ACPI_SUCCESS(status)) {
		if (data->bus)	/* PCI-PCI bridge */
			acpi_pci_irq_add_prt(device->handle, data->id.segment,
					     data->bus->number);
		else		/* non-bridge PCI device */
			acpi_pci_irq_add_prt(device->handle, data->id.segment,
					     data->id.bus);
	}

      end:
	kfree(buffer.pointer);
	if (result) {
		pci_dev_put(data->dev);
		kfree(data);
	}
	return result;
}
Exemplo n.º 17
0
acpi_status
acpi_ex_extract_from_field (
	union acpi_operand_object       *obj_desc,
	void                            *buffer,
	u32                             buffer_length)
{
	acpi_status                     status;
	u32                             field_datum_byte_offset;
	u32                             buffer_datum_offset;
	acpi_integer                    previous_raw_datum = 0;
	acpi_integer                    this_raw_datum = 0;
	acpi_integer                    merged_datum = 0;
	u32                             byte_field_length;
	u32                             datum_count;
	u32                             i;


	ACPI_FUNCTION_TRACE ("ex_extract_from_field");


	/*
	 * The field must fit within the caller's buffer
	 */
	byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length);
	if (byte_field_length > buffer_length) {
		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
			"Field size %X (bytes) too large for buffer (%X)\n",
			byte_field_length, buffer_length));

		return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
	}

	/* Convert field byte count to datum count, round up if necessary */

	datum_count = ACPI_ROUND_UP_TO (byte_field_length,
			   obj_desc->common_field.access_byte_width);

	/*
	 * If the field is not aligned on a datum boundary and does not
	 * fit within a single datum, we must read an extra datum.
	 *
	 * We could just split the aligned and non-aligned cases since the
	 * aligned case is so very simple, but this would require more code.
	 */
	if ((obj_desc->common_field.end_field_valid_bits != 0)    &&
		(!(obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM))) {
		datum_count++;
	}

	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
		"byte_len %X, datum_len %X, byte_gran %X\n",
		byte_field_length, datum_count,obj_desc->common_field.access_byte_width));

	/*
	 * Clear the caller's buffer (the whole buffer length as given)
	 * This is very important, especially in the cases where the buffer
	 * is longer than the size of the field.
	 */
	ACPI_MEMSET (buffer, 0, buffer_length);

	field_datum_byte_offset = 0;
	buffer_datum_offset= 0;

	/* Read the entire field */

	for (i = 0; i < datum_count; i++) {
		status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
				  &this_raw_datum, ACPI_READ);
		if (ACPI_FAILURE (status)) {
			return_ACPI_STATUS (status);
		}

		/* We might actually be done if the request fits in one datum */

		if ((datum_count == 1) &&
			(obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM)) {
			/* 1) Shift the valid data bits down to start at bit 0 */

			merged_datum = (this_raw_datum >> obj_desc->common_field.start_field_bit_offset);

			/* 2) Mask off any upper unused bits (bits not part of the field) */

			if (obj_desc->common_field.end_buffer_valid_bits) {
				merged_datum &= ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_buffer_valid_bits);
			}

			/* Store the datum to the caller buffer */

			acpi_ex_set_buffer_datum (merged_datum, buffer, buffer_length,
					obj_desc->common_field.access_byte_width, buffer_datum_offset);

			return_ACPI_STATUS (AE_OK);
		}

		/* Special handling for the last datum to ignore extra bits */

		if ((i >= (datum_count -1))          &&
			(obj_desc->common_field.end_field_valid_bits)) {
			/*
			 * This is the last iteration of the loop.  We need to clear
			 * any unused bits (bits that are not part of this field) before
			 * we store the final merged datum into the caller buffer.
			 */
			this_raw_datum &=
				ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits);
		}

		/*
		 * Create the (possibly) merged datum to be stored to the caller buffer
		 */
		if (obj_desc->common_field.start_field_bit_offset == 0) {
			/* Field is not skewed and we can just copy the datum */

			acpi_ex_set_buffer_datum (this_raw_datum, buffer, buffer_length,
					obj_desc->common_field.access_byte_width, buffer_datum_offset);
			buffer_datum_offset++;
		}
		else {
			/* Not aligned -- on the first iteration, just save the datum */

			if (i != 0) {
				/*
				 * Put together the appropriate bits of the two raw data to make a
				 * single complete field datum
				 *
				 * 1) Normalize the first datum down to bit 0
				 */
				merged_datum = (previous_raw_datum >> obj_desc->common_field.start_field_bit_offset);

				/* 2) Insert the second datum "above" the first datum */

				merged_datum |= (this_raw_datum << obj_desc->common_field.datum_valid_bits);

				acpi_ex_set_buffer_datum (merged_datum, buffer, buffer_length,
						obj_desc->common_field.access_byte_width, buffer_datum_offset);
				buffer_datum_offset++;
			}

			/*
			 * Save the raw datum that was just acquired since it may contain bits
			 * of the *next* field datum
			 */
			previous_raw_datum = this_raw_datum;
		}
Exemplo n.º 18
0
acpi_status
acpi_ex_name_segment (
	u8                      **in_aml_address,
	NATIVE_CHAR             *name_string)
{
	u8                      *aml_address = *in_aml_address;
	acpi_status             status = AE_OK;
	u32                     index;
	NATIVE_CHAR             char_buf[5];


	FUNCTION_TRACE ("Ex_name_segment");


	/*
	 * If first character is a digit, then we know that we aren't looking at a
	 * valid name segment
	 */
	char_buf[0] = *aml_address;

	if ('0' <= char_buf[0] && char_buf[0] <= '9') {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "leading digit: %c\n", char_buf[0]));
		return_ACPI_STATUS (AE_CTRL_PENDING);
	}

	ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n"));

	for (index = 4;
		(index > 0) && (acpi_ut_valid_acpi_character (*aml_address));
		--index) {
		char_buf[4 - index] = *aml_address++;
		ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", char_buf[4 - index]));
	}


	/* Valid name segment  */

	if (0 == index) {
		/* Found 4 valid characters */

		char_buf[4] = '\0';

		if (name_string) {
			STRCAT (name_string, char_buf);
			ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
				"Appended to - %s \n", name_string));
		}

		else {
			ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
				"No Name string - %s \n", char_buf));
		}
	}

	else if (4 == index) {
		/*
		 * First character was not a valid name character,
		 * so we are looking at something other than a name.
		 */
		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
			"Leading character is not alpha: %02Xh (not a name)\n",
			char_buf[0]));
		status = AE_CTRL_PENDING;
	}

	else {
		/* Segment started with one or more valid characters, but fewer than 4 */

		status = AE_AML_BAD_NAME;
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad character %02x in name, at %p\n",
			*aml_address, aml_address));
	}

	*in_aml_address = aml_address;
	return_ACPI_STATUS (status);
}
Exemplo n.º 19
0
static ACPI_STATUS
AcpiDmCreateNewExternal (
    char                    *ExternalPath,
    char                    *InternalPath,
    UINT8                   Type,
    UINT32                  Value,
    UINT16                  Flags)
{
    ACPI_EXTERNAL_LIST      *NewExternal;
    ACPI_EXTERNAL_LIST      *NextExternal;
    ACPI_EXTERNAL_LIST      *PrevExternal = NULL;


    ACPI_FUNCTION_TRACE (DmCreateNewExternal);


    /* Check all existing externals to ensure no duplicates */

    NextExternal = AcpiGbl_ExternalList;
    while (NextExternal)
    {
        /* Check for duplicates */

        if (!strcmp (ExternalPath, NextExternal->Path))
        {
            /*
             * If this external came from an External() opcode, we are
             * finished with this one. (No need to check any further).
             */
            if (NextExternal->Flags & ACPI_EXT_ORIGIN_FROM_OPCODE)
            {
                return_ACPI_STATUS (AE_ALREADY_EXISTS);
            }

            /* Allow upgrade of type from ANY */

            else if ((NextExternal->Type == ACPI_TYPE_ANY) &&
                (Type != ACPI_TYPE_ANY))
            {
                NextExternal->Type = Type;
            }

            /* Update the argument count as necessary */

            if (Value < NextExternal->Value)
            {
                NextExternal->Value = Value;
            }

            /* Update flags. */

            NextExternal->Flags |= Flags;
            NextExternal->Flags &= ~ACPI_EXT_INTERNAL_PATH_ALLOCATED;

            return_ACPI_STATUS (AE_ALREADY_EXISTS);
        }

        NextExternal = NextExternal->Next;
    }

    /* Allocate and init a new External() descriptor */

    NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
    if (!NewExternal)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
        "Adding external reference node (%s) type [%s]\n",
        ExternalPath, AcpiUtGetTypeName (Type)));

    NewExternal->Flags = Flags;
    NewExternal->Value = Value;
    NewExternal->Path = ExternalPath;
    NewExternal->Type = Type;
    NewExternal->Length = (UINT16) strlen (ExternalPath);
    NewExternal->InternalPath = InternalPath;

    /* Link the new descriptor into the global list, alphabetically ordered */

    NextExternal = AcpiGbl_ExternalList;
    while (NextExternal)
    {
        if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
        {
            if (PrevExternal)
            {
                PrevExternal->Next = NewExternal;
            }
            else
            {
                AcpiGbl_ExternalList = NewExternal;
            }

            NewExternal->Next = NextExternal;
            return_ACPI_STATUS (AE_OK);
        }

        PrevExternal = NextExternal;
        NextExternal = NextExternal->Next;
    }

    if (PrevExternal)
    {
        PrevExternal->Next = NewExternal;
    }
    else
    {
        AcpiGbl_ExternalList = NewExternal;
    }

    return_ACPI_STATUS (AE_OK);
}
Exemplo n.º 20
0
acpi_status
acpi_ex_get_name_string (
	acpi_object_type8       data_type,
	u8                      *in_aml_address,
	NATIVE_CHAR             **out_name_string,
	u32                     *out_name_length)
{
	acpi_status             status = AE_OK;
	u8                      *aml_address = in_aml_address;
	NATIVE_CHAR             *name_string = NULL;
	u32                     num_segments;
	u32                     prefix_count = 0;
	u8                      prefix = 0;
	u8                      has_prefix = FALSE;


	FUNCTION_TRACE_PTR ("Ex_get_name_string", aml_address);


	if (INTERNAL_TYPE_REGION_FIELD == data_type  ||
		INTERNAL_TYPE_BANK_FIELD == data_type    ||
		INTERNAL_TYPE_INDEX_FIELD == data_type) {
		/* Disallow prefixes for types associated with Field_unit names */

		name_string = acpi_ex_allocate_name_string (0, 1);
		if (!name_string) {
			status = AE_NO_MEMORY;
		}
		else {
			status = acpi_ex_name_segment (&aml_address, name_string);
		}
	}

	else {
		/*
		 * Data_type is not a field name.
		 * Examine first character of name for root or parent prefix operators
		 */
		switch (*aml_address) {

		case AML_ROOT_PREFIX:

			prefix = *aml_address++;
			ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Root_prefix: %x\n", prefix));

			/*
			 * Remember that we have a Root_prefix --
			 * see comment in Acpi_ex_allocate_name_string()
			 */
			prefix_count = (u32) -1;
			has_prefix = TRUE;
			break;


		case AML_PARENT_PREFIX:

			/* Increment past possibly multiple parent prefixes */

			do {
				prefix = *aml_address++;
				ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Parent_prefix: %x\n", prefix));

				++prefix_count;

			} while (*aml_address == AML_PARENT_PREFIX);
			has_prefix = TRUE;
			break;


		default:

			break;
		}


		/* Examine first character of name for name segment prefix operator */

		switch (*aml_address) {

		case AML_DUAL_NAME_PREFIX:

			prefix = *aml_address++;
			ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Dual_name_prefix: %x\n", prefix));

			name_string = acpi_ex_allocate_name_string (prefix_count, 2);
			if (!name_string) {
				status = AE_NO_MEMORY;
				break;
			}

			/* Indicate that we processed a prefix */

			has_prefix = TRUE;

			status = acpi_ex_name_segment (&aml_address, name_string);
			if (ACPI_SUCCESS (status)) {
				status = acpi_ex_name_segment (&aml_address, name_string);
			}
			break;


		case AML_MULTI_NAME_PREFIX_OP:

			prefix = *aml_address++;
			ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Multi_name_prefix: %x\n", prefix));

			/* Fetch count of segments remaining in name path */

			num_segments = *aml_address++;

			name_string = acpi_ex_allocate_name_string (prefix_count, num_segments);
			if (!name_string) {
				status = AE_NO_MEMORY;
				break;
			}

			/* Indicate that we processed a prefix */

			has_prefix = TRUE;

			while (num_segments &&
					(status = acpi_ex_name_segment (&aml_address, name_string)) == AE_OK) {
				--num_segments;
			}

			break;


		case 0:

			/* Null_name valid as of 8-12-98 ASL/AML Grammar Update */

			if (-1 == prefix_count) {
				ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Name_seg is \"\\\" followed by NULL\n"));
			}

			/* Consume the NULL byte */

			aml_address++;
			name_string = acpi_ex_allocate_name_string (prefix_count, 0);
			if (!name_string) {
				status = AE_NO_MEMORY;
				break;
			}

			break;


		default:

			/* Name segment string */

			name_string = acpi_ex_allocate_name_string (prefix_count, 1);
			if (!name_string) {
				status = AE_NO_MEMORY;
				break;
			}

			status = acpi_ex_name_segment (&aml_address, name_string);
			break;

		}   /* Switch (Peek_op ())   */
	}


	if (AE_CTRL_PENDING == status && has_prefix) {
		/* Ran out of segments after processing a prefix */

		REPORT_ERROR (
			("Ex_do_name: Malformed Name at %p\n", name_string));
		status = AE_AML_BAD_NAME;
	}


	*out_name_string = name_string;
	*out_name_length = (u32) (aml_address - in_aml_address);

	return_ACPI_STATUS (status);
}
Exemplo n.º 21
0
int acpi_processor_notify_smm(struct module *calling_module)
{
	acpi_status status;
	static int is_done = 0;


	if (!(acpi_processor_ppc_status & PPC_REGISTERED))
		return -EBUSY;

	if (!try_module_get(calling_module))
		return -EINVAL;

	/* is_done is set to negative if an error occured,
	 * and to postitive if _no_ error occured, but SMM
	 * was already notified. This avoids double notification
	 * which might lead to unexpected results...
	 */
	if (is_done > 0) {
		module_put(calling_module);
		return 0;
	} else if (is_done < 0) {
		module_put(calling_module);
		return is_done;
	}

	is_done = -EIO;

	/* Can't write pstate_cnt to smi_cmd if either value is zero */
	if ((!acpi_fadt.smi_cmd) || (!acpi_fadt.pstate_cnt)) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_cnt\n"));
		module_put(calling_module);
		return 0;
	}

	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
			  "Writing pstate_cnt [0x%x] to smi_cmd [0x%x]\n",
			  acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));

	/* FADT v1 doesn't support pstate_cnt, many BIOS vendors use
	 * it anyway, so we need to support it... */
	if (acpi_fadt_is_v1) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "Using v1.0 FADT reserved value for pstate_cnt\n"));
	}

	status = acpi_os_write_port(acpi_fadt.smi_cmd,
				    (u32) acpi_fadt.pstate_cnt, 8);
	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status,
				"Failed to write pstate_cnt [0x%x] to "
				"smi_cmd [0x%x]", acpi_fadt.pstate_cnt,
				acpi_fadt.smi_cmd));
		module_put(calling_module);
		return status;
	}

	/* Success. If there's no _PPC, we need to fear nothing, so
	 * we can allow the cpufreq driver to be rmmod'ed. */
	is_done = 1;

	if (!(acpi_processor_ppc_status & PPC_IN_USE))
		module_put(calling_module);

	return 0;
}
Exemplo n.º 22
0
const ACPI_OPCODE_INFO *
AcpiPsGetOpcodeInfo (
    UINT16                  Opcode)
{
#ifdef ACPI_DEBUG_OUTPUT
    const char              *OpcodeName = "Unknown AML opcode";
#endif

    ACPI_FUNCTION_NAME (PsGetOpcodeInfo);


    /*
     * Detect normal 8-bit opcode or extended 16-bit opcode
     */
    if (!(Opcode & 0xFF00))
    {
        /* Simple (8-bit) opcode: 0-255, can't index beyond table  */

        return (&AcpiGbl_AmlOpInfo [AcpiGbl_ShortOpIndex [(UINT8) Opcode]]);
    }

    if (((Opcode & 0xFF00) == AML_EXTENDED_OPCODE) &&
        (((UINT8) Opcode) <= MAX_EXTENDED_OPCODE))
    {
        /* Valid extended (16-bit) opcode */

        return (&AcpiGbl_AmlOpInfo [AcpiGbl_LongOpIndex [(UINT8) Opcode]]);
    }

#if defined ACPI_ASL_COMPILER && defined ACPI_DEBUG_OUTPUT
#include "asldefine.h"

    switch (Opcode)
    {
    case AML_RAW_DATA_BYTE:
        OpcodeName = "-Raw Data Byte-";
        break;

    case AML_RAW_DATA_WORD:
        OpcodeName = "-Raw Data Word-";
        break;

    case AML_RAW_DATA_DWORD:
        OpcodeName = "-Raw Data Dword-";
        break;

    case AML_RAW_DATA_QWORD:
        OpcodeName = "-Raw Data Qword-";
        break;

    case AML_RAW_DATA_BUFFER:
        OpcodeName = "-Raw Data Buffer-";
        break;

    case AML_RAW_DATA_CHAIN:
        OpcodeName = "-Raw Data Buffer Chain-";
        break;

    case AML_PACKAGE_LENGTH:
        OpcodeName = "-Package Length-";
        break;

    case AML_UNASSIGNED_OPCODE:
        OpcodeName = "-Unassigned Opcode-";
        break;

    case AML_DEFAULT_ARG_OP:
        OpcodeName = "-Default Arg-";
        break;

    default:
        break;
    }
#endif

    /* Unknown AML opcode */

    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
        "%s [%4.4X]\n", OpcodeName, Opcode));

    return (&AcpiGbl_AmlOpInfo [_UNK]);
}
acpi_status
acpi_ds_store_object_to_local(u16 opcode,
			      u32 index,
			      union acpi_operand_object *obj_desc,
			      struct acpi_walk_state *walk_state)
{
	acpi_status status;
	struct acpi_namespace_node *node;
	union acpi_operand_object *current_obj_desc;
	union acpi_operand_object *new_obj_desc;

	ACPI_FUNCTION_TRACE(ds_store_object_to_local);
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Opcode=%X Index=%d Obj=%p\n",
			  opcode, index, obj_desc));

	/* Parameter validation */

	if (!obj_desc) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	/* Get the namespace node for the arg/local */

	status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	current_obj_desc = acpi_ns_get_attached_object(node);
	if (current_obj_desc == obj_desc) {
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p already installed!\n",
				  obj_desc));
		return_ACPI_STATUS(status);
	}

	/*
	 * If the reference count on the object is more than one, we must
	 * take a copy of the object before we store.  A reference count
	 * of exactly 1 means that the object was just created during the
	 * evaluation of an expression, and we can safely use it since it
	 * is not used anywhere else.
	 */
	new_obj_desc = obj_desc;
	if (obj_desc->common.reference_count > 1) {
		status =
		    acpi_ut_copy_iobject_to_iobject(obj_desc, &new_obj_desc,
						    walk_state);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}
	}

	/*
	 * 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 (current_obj_desc) {
		/*
		 * 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) {
			/*
			 * If we have a valid reference object that came from ref_of(),
			 * do the indirect store
			 */
			if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) ==
			     ACPI_DESC_TYPE_OPERAND)
			    && (current_obj_desc->common.type ==
				ACPI_TYPE_LOCAL_REFERENCE)
			    && (current_obj_desc->reference.opcode ==
				AML_REF_OF_OP)) {
				ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
						  "Arg (%p) is an ObjRef(Node), storing in node %p\n",
						  new_obj_desc,
						  current_obj_desc));

				/*
				 * Store this object to the Node (perform the indirect store)
				 * NOTE: No implicit conversion is performed, as per the ACPI
				 * specification rules on storing to Locals/Args.
				 */
				status =
				    acpi_ex_store_object_to_node(new_obj_desc,
								 current_obj_desc->
								 reference.
								 object,
								 walk_state,
								 ACPI_NO_IMPLICIT_CONVERSION);

				/* Remove local reference if we copied the object above */

				if (new_obj_desc != obj_desc) {
					acpi_ut_remove_reference(new_obj_desc);
				}
				return_ACPI_STATUS(status);
			}
		}

		/*
		 * Delete the existing object
		 * before storing the new one
		 */
		acpi_ds_method_data_delete_value(opcode, index, walk_state);
	}

	/*
	 * Install the Obj descriptor (*new_obj_desc) into
	 * the descriptor for the Arg or Local.
	 * (increments the object reference count by one)
	 */
	status =
	    acpi_ds_method_data_set_value(opcode, index, new_obj_desc,
					  walk_state);

	/* Remove local reference if we copied the object above */

	if (new_obj_desc != obj_desc) {
		acpi_ut_remove_reference(new_obj_desc);
	}

	return_ACPI_STATUS(status);
}
Exemplo n.º 24
0
acpi_status
acpi_ex_access_region (
	union acpi_operand_object       *obj_desc,
	u32                             field_datum_byte_offset,
	acpi_integer                    *value,
	u32                             function)
{
	acpi_status                     status;
	union acpi_operand_object       *rgn_desc;
	acpi_physical_address           address;


	ACPI_FUNCTION_TRACE ("ex_access_region");


	/*
	 * Ensure that the region operands are fully evaluated and verify
	 * the validity of the request
	 */
	status = acpi_ex_setup_region (obj_desc, field_datum_byte_offset);
	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}

	/*
	 * The physical address of this field datum is:
	 *
	 * 1) The base of the region, plus
	 * 2) The base offset of the field, plus
	 * 3) The current offset into the field
	 */
	rgn_desc = obj_desc->common_field.region_obj;
	address = rgn_desc->region.address
			 + obj_desc->common_field.base_byte_offset
			 + field_datum_byte_offset;

	if ((function & ACPI_IO_MASK) == ACPI_READ) {
		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
	}
	else {
		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
	}

	ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
		" Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n",
		acpi_ut_get_region_name (rgn_desc->region.space_id),
		rgn_desc->region.space_id,
		obj_desc->common_field.access_byte_width,
		obj_desc->common_field.base_byte_offset,
		field_datum_byte_offset,
		ACPI_FORMAT_UINT64 (address)));

	/* Invoke the appropriate address_space/op_region handler */

	status = acpi_ev_address_space_dispatch (rgn_desc, function,
			  address, ACPI_MUL_8 (obj_desc->common_field.access_byte_width), value);

	if (ACPI_FAILURE (status)) {
		if (status == AE_NOT_IMPLEMENTED) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"Region %s(%X) not implemented\n",
				acpi_ut_get_region_name (rgn_desc->region.space_id),
				rgn_desc->region.space_id));
		}
		else if (status == AE_NOT_EXIST) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"Region %s(%X) has no handler\n",
				acpi_ut_get_region_name (rgn_desc->region.space_id),
				rgn_desc->region.space_id));
		}
	}

	return_ACPI_STATUS (status);
}
Exemplo n.º 25
0
static ACPI_STATUS
acpi_parse_resource(ACPI_RESOURCE *res, void *context)
{
    struct acpi_parse_resource_set *set;
    struct acpi_resource_context *arc;
    UINT64 min, max, length, gran;
#ifdef ACPI_DEBUG
    const char *name;
#endif
    device_t dev;

    arc = context;
    dev = arc->dev;
    set = arc->set;

    switch (res->Type) {
    case ACPI_RESOURCE_TYPE_END_TAG:
	ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
	break;
    case ACPI_RESOURCE_TYPE_FIXED_IO:
	if (res->Data.FixedIo.AddressLength <= 0)
	    break;
	ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
	    res->Data.FixedIo.Address, res->Data.FixedIo.AddressLength));
	set->set_ioport(dev, arc->context, res->Data.FixedIo.Address,
	    res->Data.FixedIo.AddressLength);
	break;
    case ACPI_RESOURCE_TYPE_IO:
	if (res->Data.Io.AddressLength <= 0)
	    break;
	if (res->Data.Io.Minimum == res->Data.Io.Maximum) {
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
		res->Data.Io.Minimum, res->Data.Io.AddressLength));
	    set->set_ioport(dev, arc->context, res->Data.Io.Minimum,
		res->Data.Io.AddressLength);
	} else {
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
		res->Data.Io.Minimum, res->Data.Io.Maximum,
		res->Data.Io.AddressLength));
	    set->set_iorange(dev, arc->context, res->Data.Io.Minimum,
		res->Data.Io.Maximum, res->Data.Io.AddressLength,
		res->Data.Io.Alignment);
	}
	break;
    case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
	if (res->Data.FixedMemory32.AddressLength <= 0)
	    break;
	ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
	    res->Data.FixedMemory32.Address,
	    res->Data.FixedMemory32.AddressLength));
	set->set_memory(dev, arc->context, res->Data.FixedMemory32.Address, 
	    res->Data.FixedMemory32.AddressLength);
	break;
    case ACPI_RESOURCE_TYPE_MEMORY32:
	if (res->Data.Memory32.AddressLength <= 0)
	    break;
	if (res->Data.Memory32.Minimum == res->Data.Memory32.Maximum) {
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
		res->Data.Memory32.Minimum, res->Data.Memory32.AddressLength));
	    set->set_memory(dev, arc->context, res->Data.Memory32.Minimum,
		res->Data.Memory32.AddressLength);
	} else {
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
		res->Data.Memory32.Minimum, res->Data.Memory32.Maximum,
		res->Data.Memory32.AddressLength));
	    set->set_memoryrange(dev, arc->context, res->Data.Memory32.Minimum,
		res->Data.Memory32.Maximum, res->Data.Memory32.AddressLength,
		res->Data.Memory32.Alignment);
	}
	break;
    case ACPI_RESOURCE_TYPE_MEMORY24:
	if (res->Data.Memory24.AddressLength <= 0)
	    break;
	if (res->Data.Memory24.Minimum == res->Data.Memory24.Maximum) {
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
		res->Data.Memory24.Minimum, res->Data.Memory24.AddressLength));
	    set->set_memory(dev, arc->context, res->Data.Memory24.Minimum,
		res->Data.Memory24.AddressLength);
	} else {
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
		res->Data.Memory24.Minimum, res->Data.Memory24.Maximum,
		res->Data.Memory24.AddressLength));
	    set->set_memoryrange(dev, arc->context, res->Data.Memory24.Minimum,
		res->Data.Memory24.Maximum, res->Data.Memory24.AddressLength,
		res->Data.Memory24.Alignment);
	}
	break;
    case ACPI_RESOURCE_TYPE_IRQ:
	/*
	 * from 1.0b 6.4.2 
	 * "This structure is repeated for each separate interrupt
	 * required"
	 */
	set->set_irq(dev, arc->context, res->Data.Irq.Interrupts,
	    res->Data.Irq.InterruptCount, res->Data.Irq.Triggering,
	    res->Data.Irq.Polarity);
	break;
    case ACPI_RESOURCE_TYPE_DMA:
	/*
	 * from 1.0b 6.4.3 
	 * "This structure is repeated for each separate DMA channel
	 * required"
	 */
	set->set_drq(dev, arc->context, res->Data.Dma.Channels,
	    res->Data.Dma.ChannelCount);
	break;
    case ACPI_RESOURCE_TYPE_START_DEPENDENT:
	ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependent functions\n"));
	set->set_start_dependent(dev, arc->context,
	    res->Data.StartDpf.CompatibilityPriority);
	break;
    case ACPI_RESOURCE_TYPE_END_DEPENDENT:
	ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependent functions\n"));
	set->set_end_dependent(dev, arc->context);
	break;
    case ACPI_RESOURCE_TYPE_ADDRESS16:
    case ACPI_RESOURCE_TYPE_ADDRESS32:
    case ACPI_RESOURCE_TYPE_ADDRESS64:
    case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
	switch (res->Type) {
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	    gran = res->Data.Address16.Granularity;
	    min = res->Data.Address16.Minimum;
	    max = res->Data.Address16.Maximum;
	    length = res->Data.Address16.AddressLength;
#ifdef ACPI_DEBUG
	    name = "Address16";
#endif
	    break;
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	    gran = res->Data.Address32.Granularity;
	    min = res->Data.Address32.Minimum;
	    max = res->Data.Address32.Maximum;
	    length = res->Data.Address32.AddressLength;
#ifdef ACPI_DEBUG
	    name = "Address32";
#endif
	    break;
	case ACPI_RESOURCE_TYPE_ADDRESS64:
	    gran = res->Data.Address64.Granularity;
	    min = res->Data.Address64.Minimum;
	    max = res->Data.Address64.Maximum;
	    length = res->Data.Address64.AddressLength;
#ifdef ACPI_DEBUG
	    name = "Address64";
#endif
	    break;
	default:
	    KASSERT(res->Type == ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64,
		("should never happen"));
	    gran = res->Data.ExtAddress64.Granularity;
	    min = res->Data.ExtAddress64.Minimum;
	    max = res->Data.ExtAddress64.Maximum;
	    length = res->Data.ExtAddress64.AddressLength;
#ifdef ACPI_DEBUG
	    name = "ExtAddress64";
#endif
	    break;
	}
	if (length <= 0)
	    break;
	if (res->Data.Address.ProducerConsumer != ACPI_CONSUMER) {
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
		"ignored %s %s producer\n", name,
		acpi_address_range_name(res->Data.Address.ResourceType)));
	    break;
	}
	if (res->Data.Address.ResourceType != ACPI_MEMORY_RANGE &&
	    res->Data.Address.ResourceType != ACPI_IO_RANGE) {
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
		"ignored %s for non-memory, non-I/O\n", name));
	    break;
	}

#ifdef __i386__
	if (min > ULONG_MAX || (res->Data.Address.MaxAddressFixed && max >
	    ULONG_MAX)) {
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored %s above 4G\n",
		name));
	    break;
	}
	if (max > ULONG_MAX)
		max = ULONG_MAX;
#endif
	if (res->Data.Address.MinAddressFixed == ACPI_ADDRESS_FIXED &&
	    res->Data.Address.MaxAddressFixed == ACPI_ADDRESS_FIXED) {
	    if (res->Data.Address.ResourceType == ACPI_MEMORY_RANGE) {
		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/Memory 0x%jx/%ju\n",
		    name, (uintmax_t)min, (uintmax_t)length));
		set->set_memory(dev, arc->context, min, length);
	    } else {
		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/IO 0x%jx/%ju\n", name,
		    (uintmax_t)min, (uintmax_t)length));
		set->set_ioport(dev, arc->context, min, length);
	    }
	} else {
	    if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
		    "%s/Memory 0x%jx-0x%jx/%ju\n", name, (uintmax_t)min,
		    (uintmax_t)max, (uintmax_t)length));
		set->set_memoryrange(dev, arc->context, min, max, length, gran);
	    } else {
		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/IO 0x%jx-0x%jx/%ju\n",
		    name, (uintmax_t)min, (uintmax_t)max, (uintmax_t)length));
		set->set_iorange(dev, arc->context, min, max, length, gran);
	    }
	}		    
	break;
    case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
	if (res->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) {
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored ExtIRQ producer\n"));
	    break;
	}
	set->set_ext_irq(dev, arc->context, res->Data.ExtendedIrq.Interrupts,
	    res->Data.ExtendedIrq.InterruptCount,
	    res->Data.ExtendedIrq.Triggering, res->Data.ExtendedIrq.Polarity);
	break;
    case ACPI_RESOURCE_TYPE_VENDOR:
	ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
	    "unimplemented VendorSpecific resource\n"));
	break;
    default:
	break;
    }
    return (AE_OK);
}
Exemplo n.º 26
0
acpi_status
acpi_ex_field_datum_io (
	union acpi_operand_object       *obj_desc,
	u32                             field_datum_byte_offset,
	acpi_integer                    *value,
	u32                             read_write)
{
	acpi_status                     status;
	acpi_integer                    local_value;


	ACPI_FUNCTION_TRACE_U32 ("ex_field_datum_io", field_datum_byte_offset);


	if (read_write == ACPI_READ) {
		if (!value) {
			local_value = 0;
			value = &local_value; /* To support reads without saving return value */
		}

		/* Clear the entire return buffer first, [Very Important!] */

		*value = 0;
	}

	/*
	 * The four types of fields are:
	 *
	 * buffer_field - Read/write from/to a Buffer
	 * region_field - Read/write from/to a Operation Region.
	 * bank_field  - Write to a Bank Register, then read/write from/to an op_region
	 * index_field - Write to an Index Register, then read/write from/to a Data Register
	 */
	switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
	case ACPI_TYPE_BUFFER_FIELD:
		/*
		 * If the buffer_field arguments have not been previously evaluated,
		 * evaluate them now and save the results.
		 */
		if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
			status = acpi_ds_get_buffer_field_arguments (obj_desc);
			if (ACPI_FAILURE (status)) {
				return_ACPI_STATUS (status);
			}
		}

		if (read_write == ACPI_READ) {
			/*
			 * Copy the data from the source buffer.
			 * Length is the field width in bytes.
			 */
			ACPI_MEMCPY (value, (obj_desc->buffer_field.buffer_obj)->buffer.pointer
					  + obj_desc->buffer_field.base_byte_offset
					  + field_datum_byte_offset,
					  obj_desc->common_field.access_byte_width);
		}
		else {
			/*
			 * Copy the data to the target buffer.
			 * Length is the field width in bytes.
			 */
			ACPI_MEMCPY ((obj_desc->buffer_field.buffer_obj)->buffer.pointer
					+ obj_desc->buffer_field.base_byte_offset
					+ field_datum_byte_offset,
					value, obj_desc->common_field.access_byte_width);
		}

		status = AE_OK;
		break;


	case ACPI_TYPE_LOCAL_BANK_FIELD:

		/* Ensure that the bank_value is not beyond the capacity of the register */

		if (acpi_ex_register_overflow (obj_desc->bank_field.bank_obj,
				  (acpi_integer) obj_desc->bank_field.value)) {
			return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
		}

		/*
		 * For bank_fields, we must write the bank_value to the bank_register
		 * (itself a region_field) before we can access the data.
		 */
		status = acpi_ex_insert_into_field (obj_desc->bank_field.bank_obj,
				 &obj_desc->bank_field.value,
				 sizeof (obj_desc->bank_field.value));
		if (ACPI_FAILURE (status)) {
			return_ACPI_STATUS (status);
		}

		/*
		 * Now that the Bank has been selected, fall through to the
		 * region_field case and write the datum to the Operation Region
		 */

		/*lint -fallthrough */


	case ACPI_TYPE_LOCAL_REGION_FIELD:
		/*
		 * For simple region_fields, we just directly access the owning
		 * Operation Region.
		 */
		status = acpi_ex_access_region (obj_desc, field_datum_byte_offset, value,
				  read_write);
		break;


	case ACPI_TYPE_LOCAL_INDEX_FIELD:


		/* Ensure that the index_value is not beyond the capacity of the register */

		if (acpi_ex_register_overflow (obj_desc->index_field.index_obj,
				  (acpi_integer) obj_desc->index_field.value)) {
			return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
		}

		/* Write the index value to the index_register (itself a region_field) */

		field_datum_byte_offset += obj_desc->index_field.value;

		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
				"Write to Index Register: Value %8.8X\n",
				field_datum_byte_offset));

		status = acpi_ex_insert_into_field (obj_desc->index_field.index_obj,
				 &field_datum_byte_offset,
				 sizeof (field_datum_byte_offset));
		if (ACPI_FAILURE (status)) {
			return_ACPI_STATUS (status);
		}

		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
				"I/O to Data Register: value_ptr %p\n",
				value));

		if (read_write == ACPI_READ) {
			/* Read the datum from the data_register */

			status = acpi_ex_extract_from_field (obj_desc->index_field.data_obj,
					  value, sizeof (acpi_integer));
		}
		else {
			/* Write the datum to the data_register */

			status = acpi_ex_insert_into_field (obj_desc->index_field.data_obj,
					  value, sizeof (acpi_integer));
		}
		break;


	default:

		ACPI_REPORT_ERROR (("Wrong object type in field I/O %X\n",
			ACPI_GET_OBJECT_TYPE (obj_desc)));
		status = AE_AML_INTERNAL;
		break;
	}

	if (ACPI_SUCCESS (status)) {
		if (read_write == ACPI_READ) {
			ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Read %8.8X%8.8X, Width %d\n",
					   ACPI_FORMAT_UINT64 (*value),
					   obj_desc->common_field.access_byte_width));
		}
		else {
			ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written %8.8X%8.8X, Width %d\n",
					   ACPI_FORMAT_UINT64 (*value),
					   obj_desc->common_field.access_byte_width));
		}
	}

	return_ACPI_STATUS (status);
}
Exemplo n.º 27
0
acpi_status
acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
				   union acpi_parse_object *op)
{
	acpi_status status;
	union acpi_operand_object *obj_desc;
	union acpi_operand_object **operand;
	struct acpi_namespace_node *node;
	union acpi_parse_object *next_op;
	u32 table_index;
	struct acpi_table_header *table;

	ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);

	/*
	 * This is where we evaluate the signature_string and oem_iDString
	 * and oem_table_iDString of the data_table_region declaration
	 */
	node = op->common.node;

	/* next_op points to signature_string op */

	next_op = op->common.value.arg;

	/*
	 * Evaluate/create the signature_string and oem_iDString
	 * and oem_table_iDString operands
	 */
	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/*
	 * Resolve the signature_string and oem_iDString
	 * and oem_table_iDString operands
	 */
	status = acpi_ex_resolve_operands(op->common.aml_opcode,
					  ACPI_WALK_OPERANDS, walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	operand = &walk_state->operands[0];

	/* Find the ACPI table */

	status = acpi_tb_find_table(operand[0]->string.pointer,
				    operand[1]->string.pointer,
				    operand[2]->string.pointer, &table_index);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	acpi_ut_remove_reference(operand[0]);
	acpi_ut_remove_reference(operand[1]);
	acpi_ut_remove_reference(operand[2]);

	status = acpi_get_table_by_index(table_index, &table);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {
		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	obj_desc->region.address =
	    (acpi_physical_address) ACPI_TO_INTEGER(table);
	obj_desc->region.length = table->length;

	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
			  obj_desc,
			  ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address),
			  obj_desc->region.length));

	/* Now the address and length are valid for this opregion */

	obj_desc->region.flags |= AOPOBJ_DATA_VALID;

	return_ACPI_STATUS(status);
}
Exemplo n.º 28
0
acpi_status
acpi_ex_write_with_update_rule (
	union acpi_operand_object       *obj_desc,
	acpi_integer                    mask,
	acpi_integer                    field_value,
	u32                             field_datum_byte_offset)
{
	acpi_status                     status = AE_OK;
	acpi_integer                    merged_value;
	acpi_integer                    current_value;


	ACPI_FUNCTION_TRACE_U32 ("ex_write_with_update_rule", mask);


	/* Start with the new bits  */

	merged_value = field_value;

	/* If the mask is all ones, we don't need to worry about the update rule */

	if (mask != ACPI_INTEGER_MAX) {
		/* Decode the update rule */

		switch (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK) {
		case AML_FIELD_UPDATE_PRESERVE:
			/*
			 * Check if update rule needs to be applied (not if mask is all
			 * ones)  The left shift drops the bits we want to ignore.
			 */
			if ((~mask << (ACPI_MUL_8 (sizeof (mask)) -
					 ACPI_MUL_8 (obj_desc->common_field.access_byte_width))) != 0) {
				/*
				 * Read the current contents of the byte/word/dword containing
				 * the field, and merge with the new field value.
				 */
				status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
						  &current_value, ACPI_READ);
				if (ACPI_FAILURE (status)) {
					return_ACPI_STATUS (status);
				}

				merged_value |= (current_value & ~mask);
			}
			break;

		case AML_FIELD_UPDATE_WRITE_AS_ONES:

			/* Set positions outside the field to all ones */

			merged_value |= ~mask;
			break;

		case AML_FIELD_UPDATE_WRITE_AS_ZEROS:

			/* Set positions outside the field to all zeros */

			merged_value &= mask;
			break;

		default:

			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"write_with_update_rule: Unknown update_rule setting: %X\n",
				(obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK)));
			return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
		}
	}

	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
		"Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n",
		ACPI_FORMAT_UINT64 (mask),
		field_datum_byte_offset,
		obj_desc->common_field.access_byte_width,
		ACPI_FORMAT_UINT64 (field_value),
		ACPI_FORMAT_UINT64 (merged_value)));

	/* Write the merged value */

	status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
			  &merged_value, ACPI_WRITE);

	return_ACPI_STATUS (status);
}
Exemplo n.º 29
0
/*
 * TODO: The kernel doesn't have a 'down_timeout' function -- had to
 * improvise.  The process is to sleep for one scheduler quantum
 * until the semaphore becomes available.  Downside is that this
 * may result in starvation for timeout-based waits when there's
 * lots of semaphore activity.
 *
 * TODO: Support for units > 1?
 */
acpi_status
acpi_os_wait_semaphore(
	acpi_handle		handle,
	u32			units,
	u16			timeout)
{
	acpi_status		status = AE_OK;
	struct semaphore	*sem = (struct semaphore*)handle;
	int			ret = 0;

	ACPI_FUNCTION_TRACE ("os_wait_semaphore");

	if (!sem || (units < 1))
		return_ACPI_STATUS (AE_BAD_PARAMETER);

	if (units > 1)
		return_ACPI_STATUS (AE_SUPPORT);

	ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout));

	if (in_atomic())
		timeout = 0;

	switch (timeout)
	{
		/*
		 * No Wait:
		 * --------
		 * A zero timeout value indicates that we shouldn't wait - just
		 * acquire the semaphore if available otherwise return AE_TIME
		 * (a.k.a. 'would block').
		 */
		case 0:
		if(down_trylock(sem))
			status = AE_TIME;
		break;

		/*
		 * Wait Indefinitely:
		 * ------------------
		 */
		case ACPI_WAIT_FOREVER:
		down(sem);
		break;

		/*
		 * Wait w/ Timeout:
		 * ----------------
		 */
		default:
		// TODO: A better timeout algorithm?
		{
			int i = 0;
			static const int quantum_ms = 1000/HZ;

			ret = down_trylock(sem);
			for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) {
				current->state = TASK_INTERRUPTIBLE;
				schedule_timeout(1);
				ret = down_trylock(sem);
			}
	
			if (ret != 0)
				status = AE_TIME;
		}
		break;
	}

	if (ACPI_FAILURE(status)) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Failed to acquire semaphore[%p|%d|%d], %s\n", 
			handle, units, timeout, acpi_format_exception(status)));
	}
	else {
		ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquired semaphore[%p|%d|%d]\n", handle, units, timeout));
	}

	return_ACPI_STATUS (status);
}
Exemplo n.º 30
0
ACPI_STATUS
AcpiDsCallControlMethod (
    ACPI_THREAD_STATE       *Thread,
    ACPI_WALK_STATE         *ThisWalkState,
    ACPI_PARSE_OBJECT       *Op)
{
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *MethodNode;
    ACPI_WALK_STATE         *NextWalkState = NULL;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_EVALUATE_INFO      *Info;
    UINT32                  i;


    ACPI_FUNCTION_TRACE_PTR (DsCallControlMethod, ThisWalkState);

    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Calling method %p, currentstate=%p\n",
        ThisWalkState->PrevOp, ThisWalkState));

    /*
     * Get the namespace entry for the control method we are about to call
     */
    MethodNode = ThisWalkState->MethodCallNode;
    if (!MethodNode)
    {
        return_ACPI_STATUS (AE_NULL_ENTRY);
    }

    ObjDesc = AcpiNsGetAttachedObject (MethodNode);
    if (!ObjDesc)
    {
        return_ACPI_STATUS (AE_NULL_OBJECT);
    }

    /* Init for new method, possibly wait on method mutex */

    Status = AcpiDsBeginMethodExecution (MethodNode, ObjDesc,
                ThisWalkState);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Begin method parse/execution. Create a new walk state */

    NextWalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwnerId,
                        NULL, ObjDesc, Thread);
    if (!NextWalkState)
    {
        Status = AE_NO_MEMORY;
        goto Cleanup;
    }

    /*
     * The resolved arguments were put on the previous walk state's operand
     * stack. Operands on the previous walk state stack always
     * start at index 0. Also, null terminate the list of arguments
     */
    ThisWalkState->Operands [ThisWalkState->NumOperands] = NULL;

    /*
     * Allocate and initialize the evaluation information block
     * TBD: this is somewhat inefficient, should change interface to
     * DsInitAmlWalk. For now, keeps this struct off the CPU stack
     */
    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
    if (!Info)
    {
        Status = AE_NO_MEMORY;
        goto Cleanup;
    }

    Info->Parameters = &ThisWalkState->Operands[0];

    Status = AcpiDsInitAmlWalk (NextWalkState, NULL, MethodNode,
                ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength,
                Info, ACPI_IMODE_EXECUTE);

    ACPI_FREE (Info);
    if (ACPI_FAILURE (Status))
    {
        goto Cleanup;
    }

    /*
     * Delete the operands on the previous walkstate operand stack
     * (they were copied to new objects)
     */
    for (i = 0; i < ObjDesc->Method.ParamCount; i++)
    {
        AcpiUtRemoveReference (ThisWalkState->Operands [i]);
        ThisWalkState->Operands [i] = NULL;
    }

    /* Clear the operand stack */

    ThisWalkState->NumOperands = 0;

    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "**** Begin nested execution of [%4.4s] **** WalkState=%p\n",
        MethodNode->Name.Ascii, NextWalkState));

    /* Invoke an internal method if necessary */

    if (ObjDesc->Method.InfoFlags & ACPI_METHOD_INTERNAL_ONLY)
    {
        Status = ObjDesc->Method.Dispatch.Implementation (NextWalkState);
        if (Status == AE_OK)
        {
            Status = AE_CTRL_TERMINATE;
        }
    }

    return_ACPI_STATUS (Status);


Cleanup:

    /* On error, we must terminate the method properly */

    AcpiDsTerminateControlMethod (ObjDesc, NextWalkState);
    if (NextWalkState)
    {
        AcpiDsDeleteWalkState (NextWalkState);
    }

    return_ACPI_STATUS (Status);
}