コード例 #1
0
ファイル: acpi_ec.c プロジェクト: ele7enxxh/dtrace-pf
static int
acpi_ec_probe(device_t dev)
{
    ACPI_BUFFER buf;
    ACPI_HANDLE h;
    ACPI_OBJECT *obj;
    ACPI_STATUS status;
    device_t	peer;
    char	desc[64];
    int		ecdt;
    int		ret;
    struct acpi_ec_params *params;
    static char *ec_ids[] = { "PNP0C09", NULL };

    /* Check that this is a device and that EC is not disabled. */
    if (acpi_get_type(dev) != ACPI_TYPE_DEVICE || acpi_disabled("ec"))
        return (ENXIO);

    /*
     * If probed via ECDT, set description and continue.  Otherwise,
     * we can access the namespace and make sure this is not a
     * duplicate probe.
     */
    ret = ENXIO;
    ecdt = 0;
    buf.Pointer = NULL;
    buf.Length = ACPI_ALLOCATE_BUFFER;
    params = acpi_get_private(dev);
    if (params != NULL) {
        ecdt = 1;
        ret = 0;
    } else if (ACPI_ID_PROBE(device_get_parent(dev), dev, ec_ids)) {
        params = malloc(sizeof(struct acpi_ec_params), M_TEMP,
                        M_WAITOK | M_ZERO);
        h = acpi_get_handle(dev);

        /*
         * Read the unit ID to check for duplicate attach and the
         * global lock value to see if we should acquire it when
         * accessing the EC.
         */
        status = acpi_GetInteger(h, "_UID", &params->uid);
        if (ACPI_FAILURE(status))
            params->uid = 0;
        status = acpi_GetInteger(h, "_GLK", &params->glk);
        if (ACPI_FAILURE(status))
            params->glk = 0;

        /*
         * Evaluate the _GPE method to find the GPE bit used by the EC to
         * signal status (SCI).  If it's a package, it contains a reference
         * and GPE bit, similar to _PRW.
         */
        status = AcpiEvaluateObject(h, "_GPE", NULL, &buf);
        if (ACPI_FAILURE(status)) {
            device_printf(dev, "can't evaluate _GPE - %s\n",
                          AcpiFormatException(status));
            goto out;
        }
        obj = (ACPI_OBJECT *)buf.Pointer;
        if (obj == NULL)
            goto out;

        switch (obj->Type) {
        case ACPI_TYPE_INTEGER:
            params->gpe_handle = NULL;
            params->gpe_bit = obj->Integer.Value;
            break;
        case ACPI_TYPE_PACKAGE:
            if (!ACPI_PKG_VALID(obj, 2))
                goto out;
            params->gpe_handle =
                acpi_GetReference(NULL, &obj->Package.Elements[0]);
            if (params->gpe_handle == NULL ||
                    acpi_PkgInt32(obj, 1, &params->gpe_bit) != 0)
                goto out;
            break;
        default:
            device_printf(dev, "_GPE has invalid type %d\n", obj->Type);
            goto out;
        }

        /* Store the values we got from the namespace for attach. */
        acpi_set_private(dev, params);

        /*
         * Check for a duplicate probe.  This can happen when a probe
         * via ECDT succeeded already.  If this is a duplicate, disable
         * this device.
         */
        peer = devclass_get_device(acpi_ec_devclass, params->uid);
        if (peer == NULL || !device_is_alive(peer))
            ret = 0;
        else
            device_disable(dev);
    }

out:
    if (ret == 0) {
        snprintf(desc, sizeof(desc), "Embedded Controller: GPE %#x%s%s",
                 params->gpe_bit, (params->glk) ? ", GLK" : "",
                 ecdt ? ", ECDT" : "");
        device_set_desc_copy(dev, desc);
    }

    if (ret > 0 && params)
        free(params, M_TEMP);
    if (buf.Pointer)
        AcpiOsFree(buf.Pointer);
    return (ret);
}
コード例 #2
0
ファイル: acpi_ec.c プロジェクト: ele7enxxh/dtrace-pf
static int
acpi_ec_attach(device_t dev)
{
    struct acpi_ec_softc	*sc;
    struct acpi_ec_params	*params;
    ACPI_STATUS			Status;

    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);

    /* Fetch/initialize softc (assumes softc is pre-zeroed). */
    sc = device_get_softc(dev);
    params = acpi_get_private(dev);
    sc->ec_dev = dev;
    sc->ec_handle = acpi_get_handle(dev);

    /* Retrieve previously probed values via device ivars. */
    sc->ec_glk = params->glk;
    sc->ec_gpebit = params->gpe_bit;
    sc->ec_gpehandle = params->gpe_handle;
    sc->ec_uid = params->uid;
    sc->ec_suspending = FALSE;
    acpi_set_private(dev, NULL);
    free(params, M_TEMP);

    /* Attach bus resources for data and command/status ports. */
    sc->ec_data_rid = 0;
    sc->ec_data_res = bus_alloc_resource_any(sc->ec_dev, SYS_RES_IOPORT,
                      &sc->ec_data_rid, RF_ACTIVE);
    if (sc->ec_data_res == NULL) {
        device_printf(dev, "can't allocate data port\n");
        goto error;
    }
    sc->ec_data_tag = rman_get_bustag(sc->ec_data_res);
    sc->ec_data_handle = rman_get_bushandle(sc->ec_data_res);

    sc->ec_csr_rid = 1;
    sc->ec_csr_res = bus_alloc_resource_any(sc->ec_dev, SYS_RES_IOPORT,
                                            &sc->ec_csr_rid, RF_ACTIVE);
    if (sc->ec_csr_res == NULL) {
        device_printf(dev, "can't allocate command/status port\n");
        goto error;
    }
    sc->ec_csr_tag = rman_get_bustag(sc->ec_csr_res);
    sc->ec_csr_handle = rman_get_bushandle(sc->ec_csr_res);

    /*
     * Install a handler for this EC's GPE bit.  We want edge-triggered
     * behavior.
     */
    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching GPE handler\n"));
    Status = AcpiInstallGpeHandler(sc->ec_gpehandle, sc->ec_gpebit,
                                   ACPI_GPE_EDGE_TRIGGERED, EcGpeHandler, sc);
    if (ACPI_FAILURE(Status)) {
        device_printf(dev, "can't install GPE handler for %s - %s\n",
                      acpi_name(sc->ec_handle), AcpiFormatException(Status));
        goto error;
    }

    /*
     * Install address space handler
     */
    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching address space handler\n"));
    Status = AcpiInstallAddressSpaceHandler(sc->ec_handle, ACPI_ADR_SPACE_EC,
                                            &EcSpaceHandler, &EcSpaceSetup, sc);
    if (ACPI_FAILURE(Status)) {
        device_printf(dev, "can't install address space handler for %s - %s\n",
                      acpi_name(sc->ec_handle), AcpiFormatException(Status));
        goto error;
    }

    /* Enable runtime GPEs for the handler. */
    Status = AcpiEnableGpe(sc->ec_gpehandle, sc->ec_gpebit);
    if (ACPI_FAILURE(Status)) {
        device_printf(dev, "AcpiEnableGpe failed: %s\n",
                      AcpiFormatException(Status));
        goto error;
    }

    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "acpi_ec_attach complete\n"));
    return (0);

error:
    AcpiRemoveGpeHandler(sc->ec_gpehandle, sc->ec_gpebit, EcGpeHandler);
    AcpiRemoveAddressSpaceHandler(sc->ec_handle, ACPI_ADR_SPACE_EC,
                                  EcSpaceHandler);
    if (sc->ec_csr_res)
        bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_csr_rid,
                             sc->ec_csr_res);
    if (sc->ec_data_res)
        bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_data_rid,
                             sc->ec_data_res);
    return (ENXIO);
}
コード例 #3
0
ファイル: ipmi_acpi.c プロジェクト: FreeBSDFoundation/freebsd
static int
ipmi_acpi_attach(device_t dev)
{
	ACPI_HANDLE devh;
	const char *mode;
	struct ipmi_get_info info;
	struct ipmi_softc *sc = device_get_softc(dev);
	int count, error, flags, i, type;
	int interface_type = 0, interface_version = 0;

	error = 0;
	devh = acpi_get_handle(dev);
	if (ACPI_FAILURE(acpi_GetInteger(devh, "_IFT", &interface_type)))
		return (ENXIO);

	if (ACPI_FAILURE(acpi_GetInteger(devh, "_SRV", &interface_version)))
		return (ENXIO);

	switch (interface_type) {
	case KCS_MODE:
		count = 2;
		mode = "KCS";
		break;
	case SMIC_MODE:
		count = 3;
		mode = "SMIC";
		break;
	case BT_MODE:
		device_printf(dev, "BT interface not supported\n");
		return (ENXIO);
	case SSIF_MODE:
		if (ACPI_FAILURE(acpi_GetInteger(devh, "_ADR", &flags)))
			return (ENXIO);
		info.address = flags;
		device_printf(dev, "SSIF interface not supported on ACPI\n");
		return (0);
	default:
		return (ENXIO);
	}

	if (bus_get_resource(dev, SYS_RES_IOPORT, 0, NULL, NULL) == 0)
		type = SYS_RES_IOPORT;
	else if (bus_get_resource(dev, SYS_RES_MEMORY, 0, NULL, NULL) == 0)
		type = SYS_RES_MEMORY;
	else {
		device_printf(dev, "unknown resource type\n");
		return (ENXIO);
	}

	sc->ipmi_io_rid = 0;
	sc->ipmi_io_res[0] = bus_alloc_resource_any(dev, type,
	    &sc->ipmi_io_rid, RF_ACTIVE);
	sc->ipmi_io_type = type;
	sc->ipmi_io_spacing = 1;
	if (sc->ipmi_io_res[0] == NULL) {
		device_printf(dev, "couldn't configure I/O resource\n");
		return (ENXIO);
	}

	/* If we have multiple resources, allocate up to MAX_RES. */
	for (i = 1; i < MAX_RES; i++) {
		sc->ipmi_io_rid = i;
		sc->ipmi_io_res[i] = bus_alloc_resource_any(dev, type,
		    &sc->ipmi_io_rid, RF_ACTIVE);
		if (sc->ipmi_io_res[i] == NULL)
			break;
	}
	sc->ipmi_io_rid = 0;

	/* If we have multiple resources, make sure we have enough of them. */
	if (sc->ipmi_io_res[1] != NULL && sc->ipmi_io_res[count - 1] == NULL) {
		device_printf(dev, "too few I/O resources\n");
		error = ENXIO;
		goto bad;
	}

	device_printf(dev, "%s mode found at %s 0x%jx on %s\n",
	    mode, type == SYS_RES_IOPORT ? "io" : "mem",
	    (uintmax_t)rman_get_start(sc->ipmi_io_res[0]),
	    device_get_name(device_get_parent(dev)));

	sc->ipmi_dev = dev;

	/*
	 * Setup an interrupt if we have an interrupt resource.  We
	 * don't support GPE interrupts via _GPE yet.
	 */
	sc->ipmi_irq_rid = 0;
	sc->ipmi_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
	    &sc->ipmi_irq_rid, RF_SHAREABLE | RF_ACTIVE);

	/* Warn if _GPE exists. */
	if (ACPI_SUCCESS(AcpiEvaluateObject(devh, "_GPE", NULL, NULL)))
		device_printf(dev, "_GPE support not implemented\n");

	/*
	 * We assume an alignment of 1 byte as currently the IPMI spec
	 * doesn't provide any way to determine the alignment via ACPI.
	 */
	switch (interface_type) {
	case KCS_MODE:
		error = ipmi_kcs_attach(sc);
		if (error)
			goto bad;
		break;
	case SMIC_MODE:
		error = ipmi_smic_attach(sc);
		if (error)
			goto bad;
		break;
	}
	error = ipmi_attach(dev);
	if (error)
		goto bad;

	return (0);
bad:
	ipmi_release_resources(dev);
	return (error);
}
コード例 #4
0
static int __devinit toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
{
	acpi_status status;
	acpi_handle ec_handle, handle;
	int error;
	u32 hci_result;

	dev->hotkey_dev = input_allocate_device();
	if (!dev->hotkey_dev) {
		pr_info("Unable to register input device\n");
		return -ENOMEM;
	}

	dev->hotkey_dev->name = "Toshiba input device";
	dev->hotkey_dev->phys = "toshiba_acpi/input0";
	dev->hotkey_dev->id.bustype = BUS_HOST;

	error = sparse_keymap_setup(dev->hotkey_dev, toshiba_acpi_keymap, NULL);
	if (error)
		goto err_free_dev;

	/*
	 * For some machines the SCI responsible for providing hotkey
	 * notification doesn't fire. We can trigger the notification
	 * whenever the Fn key is pressed using the NTFY method, if
	 * supported, so if it's present set up an i8042 key filter
	 * for this purpose.
	 */
	status = AE_ERROR;
	ec_handle = ec_get_handle();
	if (ec_handle)
		status = acpi_get_handle(ec_handle, "NTFY", &handle);

	if (ACPI_SUCCESS(status)) {
		INIT_WORK(&dev->hotkey_work, toshiba_acpi_hotkey_work);

		error = i8042_install_filter(toshiba_acpi_i8042_filter);
		if (error) {
			pr_err("Error installing key filter\n");
			goto err_free_keymap;
		}

		dev->ntfy_supported = 1;
	}

	/*
	 * Determine hotkey query interface. Prefer using the INFO
	 * method when it is available.
	 */
	status = acpi_get_handle(dev->acpi_dev->handle, "INFO", &handle);
	if (ACPI_SUCCESS(status)) {
		dev->info_supported = 1;
	} else {
		hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
		if (hci_result == HCI_SUCCESS)
			dev->system_event_supported = 1;
	}

	if (!dev->info_supported && !dev->system_event_supported) {
		pr_warn("No hotkey query interface found\n");
		goto err_remove_filter;
	}

	status = acpi_evaluate_object(dev->acpi_dev->handle, "ENAB", NULL, NULL);
	if (ACPI_FAILURE(status)) {
		pr_info("Unable to enable hotkeys\n");
		error = -ENODEV;
		goto err_remove_filter;
	}

	error = input_register_device(dev->hotkey_dev);
	if (error) {
		pr_info("Unable to register input device\n");
		goto err_remove_filter;
	}

	hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE, &hci_result);
	return 0;

 err_remove_filter:
	if (dev->ntfy_supported)
		i8042_remove_filter(toshiba_acpi_i8042_filter);
 err_free_keymap:
	sparse_keymap_free(dev->hotkey_dev);
 err_free_dev:
	input_free_device(dev->hotkey_dev);
	dev->hotkey_dev = NULL;
	return error;
}
コード例 #5
0
ファイル: bus.c プロジェクト: DecimalMan/linux-misc
static void acpi_bus_osc_support(void)
{
	u32 capbuf[2];
	struct acpi_osc_context context = {
		.uuid_str = sb_uuid_str,
		.rev = 1,
		.cap.length = 8,
		.cap.pointer = capbuf,
	};
	acpi_handle handle;

	capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE;
	capbuf[OSC_SUPPORT_DWORD] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\
			defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
	capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT;
#endif

#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
	capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT;
#endif

#ifdef ACPI_HOTPLUG_OST
	capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT;
#endif

	if (!ghes_disable)
		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT;
	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
		return;
	if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) {
		u32 *capbuf_ret = context.ret.pointer;
		if (context.ret.length > OSC_SUPPORT_DWORD)
			osc_sb_apei_support_acked =
				capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT;
		kfree(context.ret.pointer);
	}
	/* do we need to check other returned cap? Sounds no */
}

/* --------------------------------------------------------------------------
                             Notification Handling
   -------------------------------------------------------------------------- */

/**
 * acpi_bus_notify
 * ---------------
 * Callback for all 'system-level' device notifications (values 0x00-0x7F).
 */
static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
{
	struct acpi_device *device = NULL;
	struct acpi_driver *driver;

	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n",
			  type, handle));

	switch (type) {

	case ACPI_NOTIFY_BUS_CHECK:
		/* TBD */
		break;

	case ACPI_NOTIFY_DEVICE_CHECK:
		/* TBD */
		break;

	case ACPI_NOTIFY_DEVICE_WAKE:
		/* TBD */
		break;

	case ACPI_NOTIFY_EJECT_REQUEST:
		/* TBD */
		break;

	case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
		/* TBD: Exactly what does 'light' mean? */
		break;

	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
		/* TBD */
		break;

	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
		/* TBD */
		break;

	case ACPI_NOTIFY_POWER_FAULT:
		/* TBD */
		break;

	default:
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "Received unknown/unsupported notification [%08x]\n",
				  type));
		break;
	}

	acpi_bus_get_device(handle, &device);
	if (device) {
		driver = device->driver;
		if (driver && driver->ops.notify &&
		    (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
			driver->ops.notify(device, type);
	}
}

/* --------------------------------------------------------------------------
                             Initialization/Cleanup
   -------------------------------------------------------------------------- */

static int __init acpi_bus_init_irq(void)
{
	acpi_status status;
	char *message = NULL;


	/*
	 * Let the system know what interrupt model we are using by
	 * evaluating the \_PIC object, if exists.
	 */

	switch (acpi_irq_model) {
	case ACPI_IRQ_MODEL_PIC:
		message = "PIC";
		break;
	case ACPI_IRQ_MODEL_IOAPIC:
		message = "IOAPIC";
		break;
	case ACPI_IRQ_MODEL_IOSAPIC:
		message = "IOSAPIC";
		break;
	case ACPI_IRQ_MODEL_PLATFORM:
		message = "platform specific model";
		break;
	default:
		printk(KERN_WARNING PREFIX "Unknown interrupt routing model\n");
		return -ENODEV;
	}

	printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message);

	status = acpi_execute_simple_method(NULL, "\\_PIC", acpi_irq_model);
	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PIC"));
		return -ENODEV;
	}

	return 0;
}
コード例 #6
0
ファイル: acpi_ec.c プロジェクト: UnitedMarsupials/kame
static int
acpi_ec_attach(device_t dev)
{
    struct acpi_ec_softc	*sc;
    ACPI_STATUS			Status;
    int errval = 0;

    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);

    /*
     * Fetch/initialise softc
     */
    sc = device_get_softc(dev);
    bzero(sc, sizeof(*sc));
    sc->ec_dev = dev;
    sc->ec_handle = acpi_get_handle(dev);

    /* 
     * Attach bus resources
     */
    sc->ec_data_rid = 0;
    if ((sc->ec_data_res = bus_alloc_resource(sc->ec_dev, SYS_RES_IOPORT, &sc->ec_data_rid,
					      0, ~0, 1, RF_ACTIVE)) == NULL) {
	device_printf(dev, "can't allocate data port\n");
	errval = ENXIO;
	goto out;
    }
    sc->ec_data_tag = rman_get_bustag(sc->ec_data_res);
    sc->ec_data_handle = rman_get_bushandle(sc->ec_data_res);

    sc->ec_csr_rid = 1;
    if ((sc->ec_csr_res = bus_alloc_resource(sc->ec_dev, SYS_RES_IOPORT, &sc->ec_csr_rid,
					     0, ~0, 1, RF_ACTIVE)) == NULL) {
	device_printf(dev, "can't allocate command/status port\n");
	errval = ENXIO;
	goto out;
    }
    sc->ec_csr_tag = rman_get_bustag(sc->ec_csr_res);
    sc->ec_csr_handle = rman_get_bushandle(sc->ec_csr_res);

    /*
     * Install GPE handler
     *
     * Evaluate the _GPE method to find the GPE bit used by the EC to signal
     * status (SCI).
     */
    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching GPE\n"));
    if (ACPI_FAILURE(Status = acpi_EvaluateInteger(sc->ec_handle, "_GPE", &sc->ec_gpebit))) {
	device_printf(dev, "can't evaluate _GPE - %s\n", AcpiFormatException(Status));
	errval =ENXIO;
	goto out;
    }

    /*
     * Install a handler for this EC's GPE bit.  Note that EC SCIs are 
     * treated as both edge- and level-triggered interrupts; in other words
     * we clear the status bit immediately after getting an EC-SCI, then
     * again after we're done processing the event.  This guarantees that
     * events we cause while performing a transaction (e.g. IBE/OBF) get 
     * cleared before re-enabling the GPE.
     */
    if (ACPI_FAILURE(Status = AcpiInstallGpeHandler(sc->ec_gpebit,
						    ACPI_EVENT_LEVEL_TRIGGERED |
						    ACPI_EVENT_EDGE_TRIGGERED, 
						    EcGpeHandler, sc))) {
	device_printf(dev, "can't install GPE handler for %s - %s\n",
		      acpi_name(sc->ec_handle), AcpiFormatException(Status));
	errval = ENXIO;
	goto out;
    }

    /* 
     * Install address space handler
     */
    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching address space handler\n"));
    if (ACPI_FAILURE(Status = AcpiInstallAddressSpaceHandler(sc->ec_handle,
							     ACPI_ADR_SPACE_EC,
							     EcSpaceHandler,
							     EcSpaceSetup,
							     sc))) {
	device_printf(dev, "can't install address space handler for %s - %s\n",
		      acpi_name(sc->ec_handle), AcpiFormatException(Status));
	panic("very suck");
	errval = ENXIO;
	goto out;
    }
    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attach complete\n"));
    return_VALUE(0);
 out:
    if(sc->ec_csr_res)
	bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_csr_rid, 
			     sc->ec_csr_res);
    if(sc->ec_data_res)
        bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_data_rid,
			     sc->ec_data_res);
    return_VALUE(errval);
}
コード例 #7
0
acpi_status
bm_get_pm_capabilities (
	BM_NODE			*node)
{
	acpi_status             status = AE_OK;
	BM_DEVICE		*device = NULL;
	BM_DEVICE		*parent_device = NULL;
	acpi_handle             acpi_handle = NULL;
	BM_POWER_STATE          dx_supported = ACPI_STATE_UNKNOWN;
	char                    object_name[5] = {'_','S','0','D','\0'};
	u32                     i = 0;

	FUNCTION_TRACE("bm_get_pm_capabilities");

	if (!node || !node->parent) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	device = &(node->device);
	parent_device = &(node->parent->device);

	/*
	 * Power Management Flags:
	 * -----------------------
	 */
	if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PSC",
		&acpi_handle))) {
		device->power.flags |= BM_FLAGS_POWER_STATE;
	}

	if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_IRC",
		&acpi_handle))) {
		device->power.flags |= BM_FLAGS_INRUSH_CURRENT;
	}

	if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PRW",
		&acpi_handle))) {
		device->power.flags |= BM_FLAGS_WAKE_CAPABLE;
	}

	/*
	 * Device Power State:
	 * -------------------
	 * Note that we can't get the device's power state until we've
	 * initialized all power resources, so for now we just set to
	 * unknown.
	 */
	device->power.state = ACPI_STATE_UNKNOWN;

	/*
	 * Dx Supported in S0:
	 * -------------------
	 * Figure out which Dx states are supported by this device for the
	 * S0 (working) state.  Note that D0 and D3 are required (assumed).
	 */
	device->power.dx_supported[ACPI_STATE_S0] = BM_FLAGS_D0_SUPPORT |
		BM_FLAGS_D3_SUPPORT;

	if ((ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PR1",
		&acpi_handle))) ||
		(ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PS1",
		&acpi_handle)))) {
		device->power.dx_supported[ACPI_STATE_S0] |=
			BM_FLAGS_D1_SUPPORT;
	}

	if ((ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PR2",
		&acpi_handle))) ||
		(ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PS2",
		&acpi_handle)))) {
		device->power.dx_supported[ACPI_STATE_S0] |=
			BM_FLAGS_D2_SUPPORT;
	}

	/*
	 * Dx Supported in S1-S5:
	 * ----------------------
	 * Figure out which Dx states are supported by this device for
	 * all other Sx states.
	 */
	for (i = ACPI_STATE_S1; i <= ACPI_STATE_S5; i++) {

		/*
		 * D3 support is assumed (off is always possible!).
		 */
		device->power.dx_supported[i] = BM_FLAGS_D3_SUPPORT;

		/*
		 * Evalute _Sx_d:
		 * -------------
		 * Which returns the highest (power) Dx state supported in
		 * this system (Sx) state.  We convert this value to a bit
		 * mask of supported states (conceptually simpler).
		 */
		status = bm_evaluate_simple_integer(device->acpi_handle,
			object_name, &dx_supported);
		if (ACPI_SUCCESS(status)) {
			switch (dx_supported) {
			case 0:
				device->power.dx_supported[i] |=
					BM_FLAGS_D0_SUPPORT;
				/* fall through */
			case 1:
				device->power.dx_supported[i] |=
					BM_FLAGS_D1_SUPPORT;
				/* fall through */
			case 2:
				device->power.dx_supported[i] |=
					BM_FLAGS_D2_SUPPORT;
				/* fall through */
			case 3:
				device->power.dx_supported[i] |=
					BM_FLAGS_D3_SUPPORT;
				break;
			}

			/*
			 * Validate:
			 * ---------
			 * Mask of any states that _Sx_d falsely advertises
			 * (e.g.claims D1 support but neither _PR2 or _PS2
			 * exist).  In other words, S1-S5 can't offer a Dx
			 * state that isn't supported by S0.
			 */
			device->power.dx_supported[i] &=
				device->power.dx_supported[ACPI_STATE_S0];
		}

		object_name[2]++;
	}

	return_ACPI_STATUS(AE_OK);
}
コード例 #8
0
ファイル: dbcmds.c プロジェクト: 0-T-0/ps4-linux
static acpi_status
acpi_db_device_resources(acpi_handle obj_handle,
			 u32 nesting_level, void *context, void **return_value)
{
	struct acpi_namespace_node *node;
	struct acpi_namespace_node *prt_node = NULL;
	struct acpi_namespace_node *crs_node = NULL;
	struct acpi_namespace_node *prs_node = NULL;
	struct acpi_namespace_node *aei_node = NULL;
	char *parent_path;
	struct acpi_buffer return_buffer;
	acpi_status status;

	node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
	parent_path = acpi_ns_get_external_pathname(node);
	if (!parent_path) {
		return (AE_NO_MEMORY);
	}

	/* Get handles to the resource methods for this device */

	(void)acpi_get_handle(node, METHOD_NAME__PRT,
			      ACPI_CAST_PTR(acpi_handle, &prt_node));
	(void)acpi_get_handle(node, METHOD_NAME__CRS,
			      ACPI_CAST_PTR(acpi_handle, &crs_node));
	(void)acpi_get_handle(node, METHOD_NAME__PRS,
			      ACPI_CAST_PTR(acpi_handle, &prs_node));
	(void)acpi_get_handle(node, METHOD_NAME__AEI,
			      ACPI_CAST_PTR(acpi_handle, &aei_node));

	if (!prt_node && !crs_node && !prs_node && !aei_node) {
		goto cleanup;	/* Nothing to do */
	}

	acpi_os_printf("\nDevice: %s\n", parent_path);

	/* Prepare for a return object of arbitrary size */

	return_buffer.pointer = acpi_gbl_db_buffer;
	return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

	/* _PRT */

	if (prt_node) {
		acpi_os_printf("Evaluating _PRT\n");

		status =
		    acpi_evaluate_object(prt_node, NULL, NULL, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("Could not evaluate _PRT: %s\n",
				       acpi_format_exception(status));
			goto get_crs;
		}

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status = acpi_get_irq_routing_table(node, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("GetIrqRoutingTable failed: %s\n",
				       acpi_format_exception(status));
			goto get_crs;
		}

		acpi_rs_dump_irq_list(ACPI_CAST_PTR(u8, acpi_gbl_db_buffer));
	}

	/* _CRS */

get_crs:
	if (crs_node) {
		acpi_os_printf("Evaluating _CRS\n");

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status =
		    acpi_evaluate_object(crs_node, NULL, NULL, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("Could not evaluate _CRS: %s\n",
				       acpi_format_exception(status));
			goto get_prs;
		}

		/* This code exercises the acpi_walk_resources interface */

		status = acpi_walk_resources(node, METHOD_NAME__CRS,
					     acpi_db_resource_callback, NULL);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiWalkResources failed: %s\n",
				       acpi_format_exception(status));
			goto get_prs;
		}

		/* Get the _CRS resource list (test ALLOCATE buffer) */

		return_buffer.pointer = NULL;
		return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;

		status = acpi_get_current_resources(node, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiGetCurrentResources failed: %s\n",
				       acpi_format_exception(status));
			goto get_prs;
		}

		/* This code exercises the acpi_walk_resource_buffer interface */

		status = acpi_walk_resource_buffer(&return_buffer,
						   acpi_db_resource_callback,
						   NULL);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiWalkResourceBuffer failed: %s\n",
				       acpi_format_exception(status));
			goto end_crs;
		}

		/* Dump the _CRS resource list */

		acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource,
							 return_buffer.
							 pointer));

		/*
		 * Perform comparison of original AML to newly created AML. This
		 * tests both the AML->Resource conversion and the Resource->AML
		 * conversion.
		 */
		(void)acpi_dm_test_resource_conversion(node, METHOD_NAME__CRS);

		/* Execute _SRS with the resource list */

		acpi_os_printf("Evaluating _SRS\n");

		status = acpi_set_current_resources(node, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiSetCurrentResources failed: %s\n",
				       acpi_format_exception(status));
			goto end_crs;
		}

end_crs:
		ACPI_FREE(return_buffer.pointer);
	}

	/* _PRS */

get_prs:
	if (prs_node) {
		acpi_os_printf("Evaluating _PRS\n");

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status =
		    acpi_evaluate_object(prs_node, NULL, NULL, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("Could not evaluate _PRS: %s\n",
				       acpi_format_exception(status));
			goto get_aei;
		}

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status = acpi_get_possible_resources(node, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiGetPossibleResources failed: %s\n",
				       acpi_format_exception(status));
			goto get_aei;
		}

		acpi_rs_dump_resource_list(ACPI_CAST_PTR
					   (struct acpi_resource,
					    acpi_gbl_db_buffer));
	}

	/* _AEI */

get_aei:
	if (aei_node) {
		acpi_os_printf("Evaluating _AEI\n");

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status =
		    acpi_evaluate_object(aei_node, NULL, NULL, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("Could not evaluate _AEI: %s\n",
				       acpi_format_exception(status));
			goto cleanup;
		}

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status = acpi_get_event_resources(node, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiGetEventResources failed: %s\n",
				       acpi_format_exception(status));
			goto cleanup;
		}

		acpi_rs_dump_resource_list(ACPI_CAST_PTR
					   (struct acpi_resource,
					    acpi_gbl_db_buffer));
	}

cleanup:
	ACPI_FREE(parent_path);
	return (AE_OK);
}
コード例 #9
0
ファイル: mba6x_bl.c プロジェクト: ehazlett/mba6x_bl
static int lp8550_reg_write(u8 reg, u8 val)
{
	acpi_status status;
	acpi_handle handle;
	struct acpi_object_list arg_list;
	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
	union acpi_object args[3];
	union acpi_object *result;
	int ret = 0;
	u8 read_val;

	mutex_lock(&dev_priv.mutex);

	status = acpi_get_handle(NULL, "\\_SB.PCI0.SBUS.SWRB", &handle);
	if (ACPI_FAILURE(status)) {
		pr_err("mba6x_bl: Failed to get acpi handle\n");
		ret = -ENODEV;
		goto out;
	}

	args[0].type = ACPI_TYPE_INTEGER;
	args[0].integer.value = (LP8550_SMBUS_ADDR << 1) & ~1;

	args[1].type = ACPI_TYPE_INTEGER;
	args[1].integer.value = reg;

	args[2].type = ACPI_TYPE_INTEGER;
	args[2].integer.value = val;

	arg_list.count = 3;
	arg_list.pointer = args;

	status = acpi_evaluate_object(handle, NULL, &arg_list, &buffer);
	if (ACPI_FAILURE(status)) {
		pr_err("mba6x_bl: Failed to write reg: 0x%x\n", reg);
		ret = -ENODEV;
		goto out;
	}

	result = buffer.pointer;

	if (result->type != ACPI_TYPE_INTEGER || result->integer.value != 1) {
		pr_err("mba6x_bl: Invalid response at reg: 0x%x (len: %Ld)\n",
			 reg, buffer.length);
		ret = -EINVAL;
		goto out;
	}

out:
	mutex_unlock(&dev_priv.mutex);

	/* Read back the register to see if it stuck */
	lp8550_reg_read(reg, &read_val);
	if (!ret && read_val != val) {
		pr_err("mba6x_bl: Read-back failed at reg: 0x%x, val: 0x%x\n",
			reg, val);
		ret = -EINVAL;
	}

	kfree(buffer.pointer);
	return ret;
}
コード例 #10
0
ファイル: kcl_acpi.c プロジェクト: kolasa/fglrx-13.20.11
/** \brief search for acpi namespace node with specified name
 *  \param parent specify the search scope
 *  \param pathname pointer to a null terminated ascii string
 *  \param ret_handle where to put the return handle
 *  \return status
 */
unsigned int ATI_API_CALL KCL_ACPI_GetDevHandle(KCL_ACPI_DevHandle parent,
                                                const char *pathname,
                                                KCL_ACPI_DevHandle *ret_handle)
{
    return acpi_get_handle(parent, (acpi_string)pathname, ret_handle);
}
コード例 #11
0
static int
acpi_pcib_acpi_attach(device_t dev)
{
    struct acpi_hpcib_softc	*sc;
    ACPI_STATUS			status;
    uint addr, slot, func, busok;
    uint8_t busno;

    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);

    sc = device_get_softc(dev);
    sc->ap_dev = dev;
    sc->ap_handle = acpi_get_handle(dev);

    /*
     * Get our base bus number by evaluating _BBN.
     * If this doesn't work, we assume we're bus number 0.
     *
     * XXX note that it may also not exist in the case where we are 
     *     meant to use a private configuration space mechanism for this bus,
     *     so we should dig out our resources and check to see if we have
     *     anything like that.  How do we do this?
     * XXX If we have the requisite information, and if we don't think the
     *     default PCI configuration space handlers can deal with this bus,
     *     we should attach our own handler.
     * XXX invoke _REG on this for the PCI config space address space?
     * XXX It seems many BIOS's with multiple Host-PCI bridges do not set
     *     _BBN correctly.  They set _BBN to zero for all bridges.  Thus,
     *     if _BBN is zero and pcib0 already exists, we try to read our
     *     bus number from the configuration registers at address _ADR.
     */
    status = acpi_EvaluateInteger(sc->ap_handle, "_BBN", &sc->ap_bus);
    if (ACPI_FAILURE(status)) {
	if (status != AE_NOT_FOUND) {
	    device_printf(dev, "could not evaluate _BBN - %s\n",
		AcpiFormatException(status));
	    return_VALUE(ENXIO);
	} else {
	    /* if it's not found, assume 0 */
	    sc->ap_bus = 0;
	}
    }

    /*
     * If the bus is zero and pcib0 already exists, read the bus number
     * via PCI config space.
     */
    busok = 1;
    if (sc->ap_bus == 0 && devclass_get_device(pcib_devclass, 0) != dev) {
	busok = 0;
	status = acpi_EvaluateInteger(sc->ap_handle, "_ADR", &addr);
	if (ACPI_FAILURE(status)) {
	    if (status != AE_NOT_FOUND) {
		device_printf(dev, "could not evaluate _ADR - %s\n",
		    AcpiFormatException(status));
		return_VALUE(ENXIO);
	    } else
		device_printf(dev, "could not determine config space address\n");
	} else {
	    /* XXX: We assume bus 0. */
	    slot = addr >> 16;
	    func = addr & 0xffff;
	    if (bootverbose)
		device_printf(dev, "reading config registers from 0:%d:%d\n",
		    slot, func);
	    if (host_pcib_get_busno(pci_cfgregread, 0, slot, func, &busno) == 0)
		device_printf(dev, "could not read bus number from config space\n");
	    else {
		sc->ap_bus = busno;
		busok = 1;
	    }
	}
    }
コード例 #12
0
ファイル: acpi_cmbat.c プロジェクト: mihaicarabas/dragonfly
static void
acpi_cmbat_get_bif(void *arg)
{
    struct acpi_cmbat_softc *sc;
    ACPI_STATUS	as;
    ACPI_OBJECT	*res;
    ACPI_HANDLE	h;
    ACPI_BUFFER	bif_buffer;
    device_t dev;

    ACPI_SERIAL_ASSERT(cmbat);

    dev = arg;
    sc = device_get_softc(dev);
    h = acpi_get_handle(dev);
    bif_buffer.Pointer = NULL;
    bif_buffer.Length = ACPI_ALLOCATE_BUFFER;

    as = AcpiEvaluateObject(h, "_BIF", NULL, &bif_buffer);
    if (ACPI_FAILURE(as)) {
	ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
		    "error fetching current battery info -- %s\n",
		    AcpiFormatException(as));
	goto end;
    }

    res = (ACPI_OBJECT *)bif_buffer.Pointer;
    if (!ACPI_PKG_VALID(res, 13)) {
	ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
		    "battery info corrupted\n");
	goto end;
    }

    if (acpi_PkgInt32(res, 0, &sc->bif.units) != 0)
	goto end;
    if (acpi_PkgInt32(res, 1, &sc->bif.dcap) != 0)
	goto end;
    if (acpi_PkgInt32(res, 2, &sc->bif.lfcap) != 0)
	goto end;
    if (acpi_PkgInt32(res, 3, &sc->bif.btech) != 0)
	goto end;
    if (acpi_PkgInt32(res, 4, &sc->bif.dvol) != 0)
	goto end;
    if (acpi_PkgInt32(res, 5, &sc->bif.wcap) != 0)
	goto end;
    if (acpi_PkgInt32(res, 6, &sc->bif.lcap) != 0)
	goto end;
    if (acpi_PkgInt32(res, 7, &sc->bif.gra1) != 0)
	goto end;
    if (acpi_PkgInt32(res, 8, &sc->bif.gra2) != 0)
	goto end;
    if (acpi_PkgStr(res,  9, sc->bif.model, ACPI_CMBAT_MAXSTRLEN) != 0)
	goto end;
    if (acpi_PkgStr(res, 10, sc->bif.serial, ACPI_CMBAT_MAXSTRLEN) != 0)
	goto end;
    if (acpi_PkgStr(res, 11, sc->bif.type, ACPI_CMBAT_MAXSTRLEN) != 0)
	goto end;
    if (acpi_PkgStr(res, 12, sc->bif.oeminfo, ACPI_CMBAT_MAXSTRLEN) != 0)
	goto end;

end:
    if (bif_buffer.Pointer != NULL)
	AcpiOsFree(bif_buffer.Pointer);
}
コード例 #13
0
int
acpi_pci_bind (
    struct acpi_device	*device)
{
    int			result = 0;
    acpi_status		status = AE_OK;
    struct acpi_pci_data	*data = NULL;
    struct acpi_pci_data	*pdata = NULL;
    char			pathname[ACPI_PATHNAME_MAX] = {0};
    struct acpi_buffer	buffer = {ACPI_PATHNAME_MAX, pathname};
    acpi_handle		handle = NULL;

    ACPI_FUNCTION_TRACE("acpi_pci_bind");

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

    data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
    if (!data)
        return_VALUE(-ENOMEM);
    memset(data, 0, sizeof(struct acpi_pci_data));

    acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
    ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n",
                      pathname));

    /*
     * 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_DEBUG_PRINT((ACPI_DB_ERROR,
                          "Invalid ACPI-PCI context for parent device %s\n",
                          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 %02x:%02x:%02x.%02x\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_find_slot(data->id.bus, PCI_DEVFN(data->id.device, data->id.function));
    if (!data->dev) {
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                          "Device %02x:%02x:%02x.%02x 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) {
        ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                          "Device %02x:%02x:%02x.%02x 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 %02x:%02x:%02x.%02x 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;
    }

    /*
     * 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_DEBUG_PRINT((ACPI_DB_ERROR,
                          "Unable to attach ACPI-PCI context to device %s\n",
                          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:
    if (result)
        kfree(data);

    return_VALUE(result);
}
コード例 #14
0
ファイル: bmutils.c プロジェクト: TitaniumBoy/lin
acpi_status  
bm_evaluate_reference_list (
	acpi_handle             handle,
	acpi_string             pathname,
	BM_HANDLE_LIST          *reference_list)
{
	acpi_status             status = AE_OK;
	acpi_object             *package = NULL;
	acpi_object             *element = NULL;
	acpi_handle  		reference_handle = NULL;
	acpi_buffer             buffer;
	u32                     i = 0;

	FUNCTION_TRACE("bm_evaluate_reference_list");

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

	MEMSET(&buffer, 0, sizeof(acpi_buffer));

	/*
	 * Evaluate Object:
	 * ----------------
	 */
	status = bm_evaluate_object(handle, pathname, NULL, &buffer);
	if (ACPI_FAILURE(status)) {
		goto end;
	}

	/*
	 * Validate Package:
	 * -----------------
	 */
	status = bm_cast_buffer(&buffer, (void**)&package,
		sizeof(acpi_object));
	if (ACPI_FAILURE(status)) {
		DEBUG_EVAL_ERROR(ACPI_LV_WARN, handle, pathname, status);
		goto end;
	}

	if (package->type != ACPI_TYPE_PACKAGE) {
		status = AE_BAD_DATA;
		DEBUG_EVAL_ERROR(ACPI_LV_WARN, handle, pathname, status);
		goto end;
	}

	if (package->package.count > BM_HANDLES_MAX) {
		package->package.count = BM_HANDLES_MAX;
	}

	/*
	 * Parse Package Data:
	 * -------------------
	 */
	for (i = 0; i < package->package.count; i++) {

		element = &(package->package.elements[i]);

		if (!element || (element->type != ACPI_TYPE_STRING)) {
			status = AE_BAD_DATA;
			ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid element in package (not a device reference).\n"));
			DEBUG_EVAL_ERROR (ACPI_LV_WARN, handle, pathname, status);
			break;
		}

		/*
		 * Resolve reference string (e.g. "\_PR_.CPU_") to an
		 * acpi_handle.
		 */
		status = acpi_get_handle(handle,
			element->string.pointer, &reference_handle);
		if (ACPI_FAILURE(status)) {
			status = AE_BAD_DATA;
			ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to resolve device reference [%s].\n", element->string.pointer));
			DEBUG_EVAL_ERROR (ACPI_LV_WARN, handle, pathname, status);
			break;
		}

		/*
		 * Resolve acpi_handle to BM_HANDLE.
		 */
		status = bm_get_handle(reference_handle,
			&(reference_list->handles[i]));
		if (ACPI_FAILURE(status)) {
			status = AE_BAD_DATA;
			ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to resolve device reference for [%p].\n", reference_handle));
			DEBUG_EVAL_ERROR (ACPI_LV_WARN, handle, pathname, status);
			break;
		}

		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resolved reference [%s]->[%p]->[%02x]\n", element->string.pointer, reference_handle, reference_list->handles[i]));

		(reference_list->count)++;
	}

end:
	acpi_os_free(buffer.pointer);

	return_ACPI_STATUS(status);
}
コード例 #15
0
ファイル: bus.c プロジェクト: 7799/linux
static void acpi_bus_osc_support(void)
{
	u32 capbuf[2];
	struct acpi_osc_context context = {
		.uuid_str = sb_uuid_str,
		.rev = 1,
		.cap.length = 8,
		.cap.pointer = capbuf,
	};
	acpi_handle handle;

	capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE;
	capbuf[OSC_SUPPORT_DWORD] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\
			defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
	capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT;
#endif

#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
	capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT;
#endif

	capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT;

	if (!ghes_disable)
		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT;
	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
		return;
	if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) {
		u32 *capbuf_ret = context.ret.pointer;
		if (context.ret.length > OSC_SUPPORT_DWORD)
			osc_sb_apei_support_acked =
				capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT;
		kfree(context.ret.pointer);
	}
	/* do we need to check other returned cap? Sounds no */
}

/* --------------------------------------------------------------------------
                             Notification Handling
   -------------------------------------------------------------------------- */

/**
 * acpi_bus_notify
 * ---------------
 * Callback for all 'system-level' device notifications (values 0x00-0x7F).
 */
static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
{
	struct acpi_device *adev;
	struct acpi_driver *driver;
	acpi_status status;
	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;

	switch (type) {
	case ACPI_NOTIFY_BUS_CHECK:
		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
		break;

	case ACPI_NOTIFY_DEVICE_CHECK:
		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
		break;

	case ACPI_NOTIFY_DEVICE_WAKE:
		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_WAKE event\n");
		break;

	case ACPI_NOTIFY_EJECT_REQUEST:
		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
		break;

	case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK_LIGHT event\n");
		/* TBD: Exactly what does 'light' mean? */
		break;

	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
		acpi_handle_err(handle, "Device cannot be configured due "
				"to a frequency mismatch\n");
		break;

	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
		acpi_handle_err(handle, "Device cannot be configured due "
				"to a bus mode mismatch\n");
		break;

	case ACPI_NOTIFY_POWER_FAULT:
		acpi_handle_err(handle, "Device has suffered a power fault\n");
		break;

	default:
		acpi_handle_debug(handle, "Unknown event type 0x%x\n", type);
		break;
	}

	adev = acpi_bus_get_acpi_device(handle);
	if (!adev)
		goto err;

	driver = adev->driver;
	if (driver && driver->ops.notify &&
	    (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
		driver->ops.notify(adev, type);

	switch (type) {
	case ACPI_NOTIFY_BUS_CHECK:
	case ACPI_NOTIFY_DEVICE_CHECK:
	case ACPI_NOTIFY_EJECT_REQUEST:
		status = acpi_hotplug_schedule(adev, type);
		if (ACPI_SUCCESS(status))
			return;
	default:
		break;
	}
	acpi_bus_put_acpi_device(adev);
	return;

 err:
	acpi_evaluate_ost(handle, type, ost_code, NULL);
}

/* --------------------------------------------------------------------------
                             Initialization/Cleanup
   -------------------------------------------------------------------------- */

static int __init acpi_bus_init_irq(void)
{
	acpi_status status;
	char *message = NULL;


	/*
	 * Let the system know what interrupt model we are using by
	 * evaluating the \_PIC object, if exists.
	 */

	switch (acpi_irq_model) {
	case ACPI_IRQ_MODEL_PIC:
		message = "PIC";
		break;
	case ACPI_IRQ_MODEL_IOAPIC:
		message = "IOAPIC";
		break;
	case ACPI_IRQ_MODEL_IOSAPIC:
		message = "IOSAPIC";
		break;
	case ACPI_IRQ_MODEL_PLATFORM:
		message = "platform specific model";
		break;
	default:
		printk(KERN_WARNING PREFIX "Unknown interrupt routing model\n");
		return -ENODEV;
	}

	printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message);

	status = acpi_execute_simple_method(NULL, "\\_PIC", acpi_irq_model);
	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PIC"));
		return -ENODEV;
	}

	return 0;
}
コード例 #16
0
ファイル: bus.c プロジェクト: 710leo/LVS
static void acpi_bus_osc_support(void)
{
	u32 capbuf[2];
	struct acpi_osc_context context = {
		.uuid_str = sb_uuid_str,
		.rev = 1,
		.cap.length = 8,
		.cap.pointer = capbuf,
	};
	acpi_handle handle;

	capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
	capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\
			defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT;
#endif

#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT;
#endif
	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
		return;

	if (is_uv_system() && is_kdump_kernel()) {
		/*
		 * There is no need to parse the OS Capabilities table
		 * in the crash kernel. And it should not be done, as
		 * that parsing includes destructive writes to io ports to
		 * initialize UV system controller interrupts.
		 */
		return;
	}

	if (ACPI_SUCCESS(acpi_run_osc(handle, &context)))
		kfree(context.ret.pointer);
	/* do we need to check the returned cap? Sounds no */
}

/* --------------------------------------------------------------------------
                                Event Management
   -------------------------------------------------------------------------- */

#ifdef CONFIG_ACPI_PROC_EVENT
static DEFINE_SPINLOCK(acpi_bus_event_lock);

LIST_HEAD(acpi_bus_event_list);
DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue);

extern int event_is_open;

int acpi_bus_generate_proc_event4(const char *device_class, const char *bus_id, u8 type, int data)
{
	struct acpi_bus_event *event;
	unsigned long flags = 0;

	/* drop event on the floor if no one's listening */
	if (!event_is_open)
		return 0;

	event = kmalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC);
	if (!event)
		return -ENOMEM;

	strcpy(event->device_class, device_class);
	strcpy(event->bus_id, bus_id);
	event->type = type;
	event->data = data;

	spin_lock_irqsave(&acpi_bus_event_lock, flags);
	list_add_tail(&event->node, &acpi_bus_event_list);
	spin_unlock_irqrestore(&acpi_bus_event_lock, flags);

	wake_up_interruptible(&acpi_bus_event_queue);

	return 0;

}

EXPORT_SYMBOL_GPL(acpi_bus_generate_proc_event4);

int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
{
	if (!device)
		return -EINVAL;
	return acpi_bus_generate_proc_event4(device->pnp.device_class,
					     device->pnp.bus_id, type, data);
}

EXPORT_SYMBOL(acpi_bus_generate_proc_event);

int acpi_bus_receive_event(struct acpi_bus_event *event)
{
	unsigned long flags = 0;
	struct acpi_bus_event *entry = NULL;

	DECLARE_WAITQUEUE(wait, current);


	if (!event)
		return -EINVAL;

	if (list_empty(&acpi_bus_event_list)) {

		set_current_state(TASK_INTERRUPTIBLE);
		add_wait_queue(&acpi_bus_event_queue, &wait);

		if (list_empty(&acpi_bus_event_list))
			schedule();

		remove_wait_queue(&acpi_bus_event_queue, &wait);
		set_current_state(TASK_RUNNING);

		if (signal_pending(current))
			return -ERESTARTSYS;
	}

	spin_lock_irqsave(&acpi_bus_event_lock, flags);
	if (!list_empty(&acpi_bus_event_list)) {
		entry = list_entry(acpi_bus_event_list.next,
				   struct acpi_bus_event, node);
		list_del(&entry->node);
	}
コード例 #17
0
ファイル: bus.c プロジェクト: Andiry/pmfs
static void acpi_bus_osc_support(void)
{
	u32 capbuf[2];
	struct acpi_osc_context context = {
		.uuid_str = sb_uuid_str,
		.rev = 1,
		.cap.length = 8,
		.cap.pointer = capbuf,
	};
	acpi_handle handle;

	capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
	capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\
			defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT;
#endif

#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT;
#endif

#ifdef ACPI_HOTPLUG_OST
	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_HOTPLUG_OST_SUPPORT;
#endif

	if (!ghes_disable)
		capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_APEI_SUPPORT;
	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
		return;
	if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) {
		u32 *capbuf_ret = context.ret.pointer;
		if (context.ret.length > OSC_SUPPORT_TYPE)
			osc_sb_apei_support_acked =
				capbuf_ret[OSC_SUPPORT_TYPE] & OSC_SB_APEI_SUPPORT;
		kfree(context.ret.pointer);
	}
	/* do we need to check other returned cap? Sounds no */
}

/* --------------------------------------------------------------------------
                                Event Management
   -------------------------------------------------------------------------- */

#ifdef CONFIG_ACPI_PROC_EVENT
static DEFINE_SPINLOCK(acpi_bus_event_lock);

LIST_HEAD(acpi_bus_event_list);
DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue);

extern int event_is_open;

int acpi_bus_generate_proc_event4(const char *device_class, const char *bus_id, u8 type, int data)
{
	struct acpi_bus_event *event;
	unsigned long flags;

	/* drop event on the floor if no one's listening */
	if (!event_is_open)
		return 0;

	event = kzalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC);
	if (!event)
		return -ENOMEM;

	strcpy(event->device_class, device_class);
	strcpy(event->bus_id, bus_id);
	event->type = type;
	event->data = data;

	spin_lock_irqsave(&acpi_bus_event_lock, flags);
	list_add_tail(&event->node, &acpi_bus_event_list);
	spin_unlock_irqrestore(&acpi_bus_event_lock, flags);

	wake_up_interruptible(&acpi_bus_event_queue);

	return 0;

}

EXPORT_SYMBOL_GPL(acpi_bus_generate_proc_event4);

int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
{
	if (!device)
		return -EINVAL;
	return acpi_bus_generate_proc_event4(device->pnp.device_class,
					     device->pnp.bus_id, type, data);
}

EXPORT_SYMBOL(acpi_bus_generate_proc_event);

int acpi_bus_receive_event(struct acpi_bus_event *event)
{
	unsigned long flags;
	struct acpi_bus_event *entry = NULL;

	DECLARE_WAITQUEUE(wait, current);


	if (!event)
		return -EINVAL;

	if (list_empty(&acpi_bus_event_list)) {

		set_current_state(TASK_INTERRUPTIBLE);
		add_wait_queue(&acpi_bus_event_queue, &wait);

		if (list_empty(&acpi_bus_event_list))
			schedule();

		remove_wait_queue(&acpi_bus_event_queue, &wait);
		set_current_state(TASK_RUNNING);

		if (signal_pending(current))
			return -ERESTARTSYS;
	}

	spin_lock_irqsave(&acpi_bus_event_lock, flags);
	if (!list_empty(&acpi_bus_event_list)) {
		entry = list_entry(acpi_bus_event_list.next,
				   struct acpi_bus_event, node);
		list_del(&entry->node);
	}
コード例 #18
0
ファイル: core.c プロジェクト: mecke/linux-2.6
static int __init pnpacpi_add_device(struct acpi_device *device)
{
	acpi_handle temp = NULL;
	acpi_status status;
	struct pnp_dev *dev;

	/*
	 * If a PnPacpi device is not present , the device
	 * driver should not be loaded.
	 */
	status = acpi_get_handle(device->handle, "_CRS", &temp);
	if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) ||
	    is_exclusive_device(device) || (!device->status.present))
		return 0;

	dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device));
	if (!dev)
		return -ENOMEM;

	dev->data = device->handle;
	/* .enabled means the device can decode the resources */
	dev->active = device->status.enabled;
	status = acpi_get_handle(device->handle, "_SRS", &temp);
	if (ACPI_SUCCESS(status))
		dev->capabilities |= PNP_CONFIGURABLE;
	dev->capabilities |= PNP_READ;
	if (device->flags.dynamic_status && (dev->capabilities & PNP_CONFIGURABLE))
		dev->capabilities |= PNP_WRITE;
	if (device->flags.removable)
		dev->capabilities |= PNP_REMOVABLE;
	status = acpi_get_handle(device->handle, "_DIS", &temp);
	if (ACPI_SUCCESS(status))
		dev->capabilities |= PNP_DISABLE;

	if (strlen(acpi_device_name(device)))
		strncpy(dev->name, acpi_device_name(device), sizeof(dev->name));
	else
		strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name));

	if (dev->active)
		pnpacpi_parse_allocated_resource(dev);

	if (dev->capabilities & PNP_CONFIGURABLE)
		pnpacpi_parse_resource_option_data(dev);

	if (device->flags.compatible_ids) {
		struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
		int i;

		for (i = 0; i < cid_list->count; i++) {
			if (!ispnpidacpi(cid_list->id[i].value))
				continue;
			pnp_add_id(dev, cid_list->id[i].value);
		}
	}

	/* clear out the damaged flags */
	if (!dev->active)
		pnp_init_resources(dev);
	pnp_add_device(dev);
	num++;

	return AE_OK;
}
コード例 #19
0
ファイル: amdgpu_bios.c プロジェクト: 020gzh/linux
static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
{
	int ret;
	int size = 256 * 1024;
	int i;
	struct pci_dev *pdev = NULL;
	acpi_handle dhandle, atrm_handle;
	acpi_status status;
	bool found = false;

	/* ATRM is for the discrete card only */
	if (adev->flags & AMD_IS_APU)
		return false;

	while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
		dhandle = ACPI_HANDLE(&pdev->dev);
		if (!dhandle)
			continue;

		status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
		if (!ACPI_FAILURE(status)) {
			found = true;
			break;
		}
	}

	if (!found) {
		while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
			dhandle = ACPI_HANDLE(&pdev->dev);
			if (!dhandle)
				continue;

			status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
			if (!ACPI_FAILURE(status)) {
				found = true;
				break;
			}
		}
	}

	if (!found)
		return false;

	adev->bios = kmalloc(size, GFP_KERNEL);
	if (!adev->bios) {
		DRM_ERROR("Unable to allocate bios\n");
		return false;
	}

	for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
		ret = amdgpu_atrm_call(atrm_handle,
				       adev->bios,
				       (i * ATRM_BIOS_PAGE),
				       ATRM_BIOS_PAGE);
		if (ret < ATRM_BIOS_PAGE)
			break;
	}

	if (i == 0 || !AMD_IS_VALID_VBIOS(adev->bios)) {
		kfree(adev->bios);
		return false;
	}
	return true;
}
コード例 #20
0
static int
acpi_cpu_attach(device_t dev)
{
    ACPI_BUFFER		   buf;
    ACPI_OBJECT		   arg[4], *obj;
    ACPI_OBJECT_LIST	   arglist;
    struct pcpu		   *pcpu_data;
    struct acpi_cpu_softc *sc;
    struct acpi_softc	  *acpi_sc;
    ACPI_STATUS		   status;
    u_int		   features;
    int			   cpu_id, drv_count, i;
    driver_t 		  **drivers;
    uint32_t		   cap_set[3];

    /* UUID needed by _OSC evaluation */
    static uint8_t cpu_oscuuid[16] = { 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29,
				       0xBE, 0x47, 0x9E, 0xBD, 0xD8, 0x70,
				       0x58, 0x71, 0x39, 0x53 };

    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);

    sc = device_get_softc(dev);
    sc->cpu_dev = dev;
    sc->cpu_handle = acpi_get_handle(dev);
    cpu_id = (int)(intptr_t)acpi_get_private(dev);
    cpu_softc[cpu_id] = sc;
    pcpu_data = pcpu_find(cpu_id);
    pcpu_data->pc_device = dev;
    sc->cpu_pcpu = pcpu_data;
    cpu_smi_cmd = AcpiGbl_FADT.SmiCommand;
    cpu_cst_cnt = AcpiGbl_FADT.CstControl;

    buf.Pointer = NULL;
    buf.Length = ACPI_ALLOCATE_BUFFER;
    status = AcpiEvaluateObject(sc->cpu_handle, NULL, NULL, &buf);
    if (ACPI_FAILURE(status)) {
	device_printf(dev, "attach failed to get Processor obj - %s\n",
		      AcpiFormatException(status));
	return (ENXIO);
    }
    obj = (ACPI_OBJECT *)buf.Pointer;
    sc->cpu_p_blk = obj->Processor.PblkAddress;
    sc->cpu_p_blk_len = obj->Processor.PblkLength;
    sc->cpu_acpi_id = obj->Processor.ProcId;
    AcpiOsFree(obj);
    ACPI_DEBUG_PRINT((ACPI_DB_INFO, "acpi_cpu%d: P_BLK at %#x/%d\n",
		     device_get_unit(dev), sc->cpu_p_blk, sc->cpu_p_blk_len));

    /*
     * If this is the first cpu we attach, create and initialize the generic
     * resources that will be used by all acpi cpu devices.
     */
    if (device_get_unit(dev) == 0) {
	/* Assume we won't be using generic Cx mode by default */
	cpu_cx_generic = FALSE;

	/* Install hw.acpi.cpu sysctl tree */
	acpi_sc = acpi_device_get_parent_softc(dev);
	sysctl_ctx_init(&cpu_sysctl_ctx);
	cpu_sysctl_tree = SYSCTL_ADD_NODE(&cpu_sysctl_ctx,
	    SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "cpu",
	    CTLFLAG_RD, 0, "node for CPU children");

	/* Queue post cpu-probing task handler */
	AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cpu_startup, NULL);
    }

    /*
     * Before calling any CPU methods, collect child driver feature hints
     * and notify ACPI of them.  We support unified SMP power control
     * so advertise this ourselves.  Note this is not the same as independent
     * SMP control where each CPU can have different settings.
     */
    sc->cpu_features = ACPI_CAP_SMP_SAME | ACPI_CAP_SMP_SAME_C3 |
      ACPI_CAP_C1_IO_HALT;

#if defined(__i386__) || defined(__amd64__)
    /*
     * Ask for MWAIT modes if not disabled and interrupts work
     * reasonable with MWAIT.
     */
    if (!acpi_disabled("mwait") && cpu_mwait_usable())
	sc->cpu_features |= ACPI_CAP_SMP_C1_NATIVE | ACPI_CAP_SMP_C3_NATIVE;
#endif

    if (devclass_get_drivers(acpi_cpu_devclass, &drivers, &drv_count) == 0) {
	for (i = 0; i < drv_count; i++) {
	    if (ACPI_GET_FEATURES(drivers[i], &features) == 0)
		sc->cpu_features |= features;
	}
	free(drivers, M_TEMP);
    }

    /*
     * CPU capabilities are specified in
     * Intel Processor Vendor-Specific ACPI Interface Specification.
     */
    if (sc->cpu_features) {
	arglist.Pointer = arg;
	arglist.Count = 4;
	arg[0].Type = ACPI_TYPE_BUFFER;
	arg[0].Buffer.Length = sizeof(cpu_oscuuid);
	arg[0].Buffer.Pointer = cpu_oscuuid;	/* UUID */
	arg[1].Type = ACPI_TYPE_INTEGER;
	arg[1].Integer.Value = 1;		/* revision */
	arg[2].Type = ACPI_TYPE_INTEGER;
	arg[2].Integer.Value = 1;		/* count */
	arg[3].Type = ACPI_TYPE_BUFFER;
	arg[3].Buffer.Length = sizeof(cap_set);	/* Capabilities buffer */
	arg[3].Buffer.Pointer = (uint8_t *)cap_set;
	cap_set[0] = 0;				/* status */
	cap_set[1] = sc->cpu_features;
	status = AcpiEvaluateObject(sc->cpu_handle, "_OSC", &arglist, NULL);
	if (ACPI_SUCCESS(status)) {
	    if (cap_set[0] != 0)
		device_printf(dev, "_OSC returned status %#x\n", cap_set[0]);
	}
	else {
	    arglist.Pointer = arg;
	    arglist.Count = 1;
	    arg[0].Type = ACPI_TYPE_BUFFER;
	    arg[0].Buffer.Length = sizeof(cap_set);
	    arg[0].Buffer.Pointer = (uint8_t *)cap_set;
	    cap_set[0] = 1; /* revision */
	    cap_set[1] = 1; /* number of capabilities integers */
	    cap_set[2] = sc->cpu_features;
	    AcpiEvaluateObject(sc->cpu_handle, "_PDC", &arglist, NULL);
	}
    }

    /* Probe for Cx state support. */
    acpi_cpu_cx_probe(sc);

    return (0);
}
コード例 #21
0
static int
acpi_cpu_attach(device_t dev)
{
    struct acpi_cpu_softc *sc = device_get_softc(dev);
    ACPI_HANDLE handle;
    device_t child;
    int cpu_id, cpu_features;
    struct acpi_softc *acpi_sc;

    handle = acpi_get_handle(dev);
    cpu_id = acpi_get_magic(dev);

    acpi_sc = acpi_device_get_parent_softc(dev);
    if (cpu_id == 0) {
	sysctl_ctx_init(&sc->glob_sysctl_ctx);
	sc->glob_sysctl_tree = SYSCTL_ADD_NODE(&sc->glob_sysctl_ctx,
			       SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
			       OID_AUTO, "cpu", CTLFLAG_RD, 0,
			       "node for CPU global settings");
    	if (sc->glob_sysctl_tree == NULL)
	    return ENOMEM;
    }

    sysctl_ctx_init(&sc->pcpu_sysctl_ctx);
    sc->pcpu_sysctl_tree = SYSCTL_ADD_NODE(&sc->pcpu_sysctl_ctx,
			   SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
			   OID_AUTO, device_get_nameunit(dev), CTLFLAG_RD, 0,
			   "node for per-CPU settings");
    if (sc->pcpu_sysctl_tree == NULL) {
	sysctl_ctx_free(&sc->glob_sysctl_ctx);
	return ENOMEM;
    }

    /*
     * Before calling any CPU methods, collect child driver feature hints
     * and notify ACPI of them.  We support unified SMP power control
     * so advertise this ourselves.  Note this is not the same as independent
     * SMP control where each CPU can have different settings.
     */
    cpu_features = ACPI_PDC_MP_C1PXTX | ACPI_PDC_MP_C2C3;
    cpu_features |= acpi_cpu_md_features();

    /*
     * CPU capabilities are specified as a buffer of 32-bit integers:
     * revision, count, and one or more capabilities.
     */
    if (cpu_features) {
	ACPI_OBJECT_LIST arglist;
	uint32_t cap_set[3];
	ACPI_OBJECT arg[4];
	ACPI_STATUS status;

	/* UUID needed by _OSC evaluation */
	static uint8_t cpu_oscuuid[16] = {
	   0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
	   0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
	};

	arglist.Pointer = arg;
	arglist.Count = 4;
	arg[0].Type = ACPI_TYPE_BUFFER;
	arg[0].Buffer.Length = sizeof(cpu_oscuuid);
	arg[0].Buffer.Pointer = cpu_oscuuid;	/* UUID */
	arg[1].Type = ACPI_TYPE_INTEGER;
	arg[1].Integer.Value = 1;		/* revision */
	arg[2].Type = ACPI_TYPE_INTEGER;
	arg[2].Integer.Value = 2;		/* # of capabilities integers */
	arg[3].Type = ACPI_TYPE_BUFFER;
	arg[3].Buffer.Length = sizeof(cap_set[0]) * 2; /* capabilities buffer */
	arg[3].Buffer.Pointer = (uint8_t *)cap_set;
	cap_set[0] = 0;
	cap_set[1] = cpu_features;
	status = AcpiEvaluateObject(handle, "_OSC", &arglist, NULL);

	if (!ACPI_SUCCESS(status)) {
	    if (bootverbose)
		device_printf(dev, "_OSC failed, use _PDC\n");

	    arglist.Pointer = arg;
	    arglist.Count = 1;
	    arg[0].Type = ACPI_TYPE_BUFFER;
	    arg[0].Buffer.Length = sizeof(cap_set);
	    arg[0].Buffer.Pointer = (uint8_t *)cap_set;
	    cap_set[0] = 1; /* revision */
	    cap_set[1] = 1; /* # of capabilities integers */
	    cap_set[2] = cpu_features;
	    AcpiEvaluateObject(handle, "_PDC", &arglist, NULL);
	}
    }

    child = BUS_ADD_CHILD(dev, dev, 0, "cpu_cst", -1);
    if (child == NULL)
	return ENXIO;
    acpi_set_handle(child, handle);
    acpi_set_magic(child, cpu_id);
    sc->cpu_cst = child;

    child = BUS_ADD_CHILD(dev, dev, 0, "cpu_pst", -1);
    if (child == NULL)
	return ENXIO;
    acpi_set_handle(child, handle);
    acpi_set_magic(child, cpu_id);

    bus_generic_probe(dev);
    bus_generic_attach(dev);

    AcpiInstallNotifyHandler(handle, ACPI_DEVICE_NOTIFY, acpi_cpu_notify, sc);

    return 0;
}
コード例 #22
0
/**
 * acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events
 * @chip:      gpio chip
 *
 * ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are
 * handled by ACPI event methods which need to be called from the GPIO
 * chip's interrupt handler. acpi_gpiochip_request_interrupts finds out which
 * gpio pins have acpi event methods and assigns interrupt handlers that calls
 * the acpi event methods for those pins.
 */
void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
{
    struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
    struct acpi_resource *res;
    acpi_handle handle, evt_handle;
    struct list_head *evt_pins = NULL;
    acpi_status status;
    unsigned int pin;
    int irq, ret;
    char ev_name[5];

    if (!chip->dev || !chip->to_irq)
        return;

    handle = ACPI_HANDLE(chip->dev);
    if (!handle)
        return;

    status = acpi_get_event_resources(handle, &buf);
    if (ACPI_FAILURE(status))
        return;

    status = acpi_get_handle(handle, "_EVT", &evt_handle);
    if (ACPI_SUCCESS(status)) {
        evt_pins = kzalloc(sizeof(*evt_pins), GFP_KERNEL);
        if (evt_pins) {
            INIT_LIST_HEAD(evt_pins);
            status = acpi_attach_data(handle, acpi_gpio_evt_dh,
                                      evt_pins);
            if (ACPI_FAILURE(status)) {
                kfree(evt_pins);
                evt_pins = NULL;
            }
        }
    }

    /*
     * If a GPIO interrupt has an ACPI event handler method, or _EVT is
     * present, set up an interrupt handler that calls the ACPI event
     * handler.
     */
    for (res = buf.pointer;
            res && (res->type != ACPI_RESOURCE_TYPE_END_TAG);
            res = ACPI_NEXT_RESOURCE(res)) {
        irq_handler_t handler = NULL;
        void *data;

        if (res->type != ACPI_RESOURCE_TYPE_GPIO ||
                res->data.gpio.connection_type !=
                ACPI_RESOURCE_GPIO_TYPE_INT)
            continue;

        pin = res->data.gpio.pin_table[0];
        if (pin > chip->ngpio)
            continue;

        irq = chip->to_irq(chip, pin);
        if (irq < 0)
            continue;

        if (pin <= 255) {
            acpi_handle ev_handle;

            sprintf(ev_name, "_%c%02X",
                    res->data.gpio.triggering ? 'E' : 'L', pin);
            status = acpi_get_handle(handle, ev_name, &ev_handle);
            if (ACPI_SUCCESS(status)) {
                handler = acpi_gpio_irq_handler;
                data = ev_handle;
            }
        }
        if (!handler && evt_pins) {
            struct acpi_gpio_evt_pin *evt_pin;

            evt_pin = kzalloc(sizeof(*evt_pin), GFP_KERNEL);
            if (!evt_pin)
                continue;

            list_add_tail(&evt_pin->node, evt_pins);
            evt_pin->evt_handle = evt_handle;
            evt_pin->pin = pin;
            evt_pin->irq = irq;
            handler = acpi_gpio_irq_handler_evt;
            data = evt_pin;
        }
        if (!handler)
            continue;

        /* Assume BIOS sets the triggering, so no flags */
        ret = devm_request_threaded_irq(chip->dev, irq, NULL, handler,
                                        0, "GPIO-signaled-ACPI-event",
                                        data);
        if (ret)
            dev_err(chip->dev,
                    "Failed to request IRQ %d ACPI event handler\n",
                    irq);
    }
}
コード例 #23
0
static int
acpi_pcib_acpi_attach(device_t dev)
{
    struct acpi_hpcib_softc	*sc;
    ACPI_STATUS			status;
    static int bus0_seen = 0;
    u_int addr, slot, func, busok;
    uint8_t busno;

    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);

    sc = device_get_softc(dev);
    sc->ap_dev = dev;
    sc->ap_handle = acpi_get_handle(dev);

    /*
     * Get our segment number by evaluating _SEG
     * It's OK for this to not exist.
     */
    status = acpi_GetInteger(sc->ap_handle, "_SEG", &sc->ap_segment);
    if (ACPI_FAILURE(status)) {
	if (status != AE_NOT_FOUND) {
	    device_printf(dev, "could not evaluate _SEG - %s\n",
		AcpiFormatException(status));
	    return_VALUE (ENXIO);
	}
	/* If it's not found, assume 0. */
	sc->ap_segment = 0;
    }

    /*
     * Get our base bus number by evaluating _BBN.
     * If this doesn't work, we assume we're bus number 0.
     *
     * XXX note that it may also not exist in the case where we are
     *     meant to use a private configuration space mechanism for this bus,
     *     so we should dig out our resources and check to see if we have
     *     anything like that.  How do we do this?
     * XXX If we have the requisite information, and if we don't think the
     *     default PCI configuration space handlers can deal with this bus,
     *     we should attach our own handler.
     * XXX invoke _REG on this for the PCI config space address space?
     * XXX It seems many BIOS's with multiple Host-PCI bridges do not set
     *     _BBN correctly.  They set _BBN to zero for all bridges.  Thus,
     *     if _BBN is zero and PCI bus 0 already exists, we try to read our
     *     bus number from the configuration registers at address _ADR.
     *     We only do this for domain/segment 0 in the hopes that this is
     *     only needed for old single-domain machines.
     */
    status = acpi_GetInteger(sc->ap_handle, "_BBN", &sc->ap_bus);
    if (ACPI_FAILURE(status)) {
	if (status != AE_NOT_FOUND) {
	    device_printf(dev, "could not evaluate _BBN - %s\n",
		AcpiFormatException(status));
	    return_VALUE (ENXIO);
	} else {
	    /* If it's not found, assume 0. */
	    sc->ap_bus = 0;
	}
    }

    /*
     * If this is segment 0, the bus is zero, and PCI bus 0 already
     * exists, read the bus number via PCI config space.
     */
    busok = 1;
    if (sc->ap_segment == 0 && sc->ap_bus == 0 && bus0_seen) {
	busok = 0;
	status = acpi_GetInteger(sc->ap_handle, "_ADR", &addr);
	if (ACPI_FAILURE(status)) {
	    if (status != AE_NOT_FOUND) {
		device_printf(dev, "could not evaluate _ADR - %s\n",
		    AcpiFormatException(status));
		return_VALUE (ENXIO);
	    } else
		device_printf(dev, "couldn't find _ADR\n");
	} else {
	    /* XXX: We assume bus 0. */
	    slot = ACPI_ADR_PCI_SLOT(addr);
	    func = ACPI_ADR_PCI_FUNC(addr);
	    if (bootverbose)
		device_printf(dev, "reading config registers from 0:%d:%d\n",
		    slot, func);
	    if (host_pcib_get_busno(pci_cfgregread, 0, slot, func, &busno) == 0)
		device_printf(dev, "couldn't read bus number from cfg space\n");
	    else {
		sc->ap_bus = busno;
		busok = 1;
	    }
	}
    }

    /*
     * If nothing else worked, hope that ACPI at least lays out the
     * host-PCI bridges in order and that as a result our unit number
     * is actually our bus number.  There are several reasons this
     * might not be true.
     */
    if (busok == 0) {
	sc->ap_bus = device_get_unit(dev);
	device_printf(dev, "trying bus number %d\n", sc->ap_bus);
    }

    /* If this is bus 0 on segment 0, note that it has been seen already. */
    if (sc->ap_segment == 0 && sc->ap_bus == 0)
	    bus0_seen = 1;

    return (acpi_pcib_attach(dev, &sc->ap_prt, sc->ap_bus));
}