Ejemplo n.º 1
0
static void
asus_attach(device_t parent, device_t self, void *opaque)
{
	asus_softc_t *sc = device_private(self);
	struct acpi_attach_args *aa = opaque;
	ACPI_STATUS rv;

	sc->sc_node = aa->aa_node;
	sc->sc_dev = self;

	aprint_naive("\n");
	aprint_normal("\n");

	asus_init(self);

	sc->sc_smpsw_valid = true;
	sc->sc_smpsw[ASUS_PSW_DISPLAY_CYCLE].smpsw_name =
	    PSWITCH_HK_DISPLAY_CYCLE;
	sc->sc_smpsw[ASUS_PSW_DISPLAY_CYCLE].smpsw_type =
	    PSWITCH_TYPE_HOTKEY;
	if (sysmon_pswitch_register(&sc->sc_smpsw[ASUS_PSW_DISPLAY_CYCLE])) {
		aprint_error_dev(self, "couldn't register with sysmon\n");
		sc->sc_smpsw_valid = false;
	}

	rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle, ACPI_ALL_NOTIFY,
	    asus_notify_handler, sc);
	if (ACPI_FAILURE(rv))
		aprint_error_dev(self, "couldn't install notify handler: %s\n",
		    AcpiFormatException(rv));

	if (!pmf_device_register(self, asus_suspend, asus_resume))
		aprint_error_dev(self, "couldn't establish power handler\n");
}
Ejemplo n.º 2
0
static int
acpi_cmbat_attach(device_t dev)
{
    int		error;
    ACPI_HANDLE	handle;
    struct acpi_cmbat_softc *sc;

    sc = device_get_softc(dev);
    handle = acpi_get_handle(dev);
    sc->dev = dev;

    timespecclear(&sc->bst_lastupdated);

    error = acpi_battery_register(dev);
    if (error != 0) {
    	device_printf(dev, "registering battery failed\n");
	return (error);
    }

    /*
     * Install a system notify handler in addition to the device notify.
     * Toshiba notebook uses this alternate notify for its battery.
     */
    AcpiInstallNotifyHandler(handle, ACPI_ALL_NOTIFY,
	acpi_cmbat_notify_handler, dev);

    AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_init_battery, dev);

    return (0);
}
Ejemplo n.º 3
0
static ACPI_STATUS
InstallHandlers (void)
{
    ACPI_STATUS             Status;


    /* Install global notify handler */

    Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT,
        ACPI_SYSTEM_NOTIFY, NotifyHandler, NULL);
    if (ACPI_FAILURE (Status))
    {
        ACPI_EXCEPTION ((AE_INFO, Status, "While installing Notify handler"));
        return (Status);
    }

    Status = AcpiInstallAddressSpaceHandler (ACPI_ROOT_OBJECT,
        ACPI_ADR_SPACE_SYSTEM_MEMORY, RegionHandler, RegionInit, NULL);
    if (ACPI_FAILURE (Status))
    {
        ACPI_EXCEPTION ((AE_INFO, Status, "While installing an OpRegion handler"));
        return (Status);
    }

    return (AE_OK);
}
Ejemplo n.º 4
0
status_t
install_notify_handler(acpi_handle device, uint32 handlerType,
                       acpi_notify_handler handler, void *context)
{
    return AcpiInstallNotifyHandler(device, handlerType,
                                    (ACPI_NOTIFY_HANDLER)handler, context) == AE_OK ? B_OK : B_ERROR;
}
Ejemplo n.º 5
0
static int
acpi_lid_attach(device_t dev)
{
    struct acpi_prw_data	prw;
    struct acpi_lid_softc	*sc;

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

    sc = device_get_softc(dev);
    sc->lid_dev = dev;
    sc->lid_handle = acpi_get_handle(dev);

    /*
     * If a system does not get lid events, it may make sense to change
     * the type to ACPI_ALL_NOTIFY.  Some systems generate both a wake and
     * runtime notify in that case though.
     */
    AcpiInstallNotifyHandler(sc->lid_handle, ACPI_DEVICE_NOTIFY,
                             acpi_lid_notify_handler, sc);

    /* Enable the GPE for wake/runtime. */
    acpi_wake_set_enable(dev, 1);
    if (acpi_parse_prw(sc->lid_handle, &prw) == 0)
        AcpiEnableGpe(prw.gpe_handle, prw.gpe_bit);

    return (0);
}
Ejemplo n.º 6
0
static int
acpi_panasonic_attach(device_t dev)
{
	struct acpi_panasonic_softc *sc;
	struct acpi_softc *acpi_sc;
	ACPI_STATUS status;
	int i;

	sc = device_get_softc(dev);
	sc->dev = dev;
	sc->handle = acpi_get_handle(dev);

	acpi_sc = acpi_device_get_parent_softc(dev);

	/* Build sysctl tree */
	sysctl_ctx_init(&sc->sysctl_ctx);
	sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
	    SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO,
	    "panasonic", CTLFLAG_RD, 0, "");
	for (i = 0; sysctl_table[i].name != NULL; i++) {
		SYSCTL_ADD_PROC(&sc->sysctl_ctx,
		    SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
		    sysctl_table[i].name,
		    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY,
		    sc, i, acpi_panasonic_sysctl, "I", "");
	}

#if 0
	/* Activate hotkeys */
	status = AcpiEvaluateObject(sc->handle, "", NULL, NULL);
	if (ACPI_FAILURE(status)) {
		device_printf(dev, "enable FN keys failed\n");
		sysctl_ctx_free(&sc->sysctl_ctx);
		return (ENXIO);
	}
#endif

	/* Handle notifies */
	status = AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY,
	    acpi_panasonic_notify, sc);
	if (ACPI_FAILURE(status)) {
		device_printf(dev, "couldn't install notify handler - %s\n",
		    AcpiFormatException(status));
		sysctl_ctx_free(&sc->sysctl_ctx);
		return (ENXIO);
	}

	/* Install power profile event handler */
	sc->power_evh = EVENTHANDLER_REGISTER(power_profile_change,
	    acpi_panasonic_power_profile, sc->handle, 0);

	return (0);
}
Ejemplo n.º 7
0
/*
 * Install event handler for the hot plug events on the bus node as well
 * as device function (dev=0,func=0).
 */
static ACPI_STATUS
pciehpc_acpi_install_event_handler(pcie_hp_ctrl_t *ctrl_p)
{
	pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0];
	int status = AE_OK;
	pciehpc_acpi_t *acpi_p;

	PCIE_DBG("install event handler for slot %d\n",
	    slot_p->hs_phy_slot_num);
	acpi_p = ctrl_p->hc_misc_data;
	if (acpi_p->slot_dev_obj == NULL)
		return (AE_NOT_FOUND);

	/*
	 * Install event hanlder for events on the bus object.
	 * (Note: Insert event (hot-insert) is delivered on this object)
	 */
	status = AcpiInstallNotifyHandler(acpi_p->slot_dev_obj,
	    ACPI_SYSTEM_NOTIFY, pciehpc_acpi_notify_handler, (void *)ctrl_p);
	if (status != AE_OK)
		goto cleanup;

	/*
	 * Install event hanlder for events on the device function object.
	 * (Note: Eject device event (hot-remove) is delivered on this object)
	 *
	 * NOTE: Here the assumption is that Notify events are delivered
	 * on all of the 8 possible device functions so, subscribing to
	 * one of them is sufficient.
	 */
	status = AcpiInstallNotifyHandler(acpi_p->bus_obj,
	    ACPI_SYSTEM_NOTIFY, pciehpc_acpi_notify_handler, (void *)ctrl_p);
	return (status);

cleanup:
	(void) AcpiRemoveNotifyHandler(acpi_p->slot_dev_obj,
	    ACPI_SYSTEM_NOTIFY, pciehpc_acpi_notify_handler);
	return (status);
}
Ejemplo n.º 8
0
static int
acpi_dock_attach(device_t dev)
{
	struct acpi_dock_softc *sc;
	ACPI_HANDLE	h;

	sc = device_get_softc(dev);
	h = acpi_get_handle(dev);
	if (sc == NULL || h == NULL)
		return (ENXIO);

	sc->status = ACPI_DOCK_STATUS_UNKNOWN;

	AcpiEvaluateObject(h, "_INI", NULL, NULL);

	ACPI_SERIAL_BEGIN(dock);

	acpi_dock_device_check(dev);

	/* Get the sysctl tree */
	sc->sysctl_ctx = device_get_sysctl_ctx(dev);
	sc->sysctl_tree = device_get_sysctl_tree(dev);

	SYSCTL_ADD_INT(sc->sysctl_ctx,
		SYSCTL_CHILDREN(sc->sysctl_tree),
		OID_AUTO, "_sta", CTLFLAG_RD,
		&sc->_sta, 0, "Dock _STA");
	SYSCTL_ADD_INT(sc->sysctl_ctx,
		SYSCTL_CHILDREN(sc->sysctl_tree),
		OID_AUTO, "_bdn", CTLFLAG_RD,
		&sc->_bdn, 0, "Dock _BDN");
	SYSCTL_ADD_INT(sc->sysctl_ctx,
		SYSCTL_CHILDREN(sc->sysctl_tree),
		OID_AUTO, "_uid", CTLFLAG_RD,
		&sc->_uid, 0, "Dock _UID");
	SYSCTL_ADD_PROC(sc->sysctl_ctx,
		SYSCTL_CHILDREN(sc->sysctl_tree),
		OID_AUTO, "status",
		CTLTYPE_INT|CTLFLAG_RW, dev, 0,
		acpi_dock_status_sysctl, "I",
		"Dock/Undock operation");

	ACPI_SERIAL_END(dock);

	AcpiInstallNotifyHandler(h, ACPI_ALL_NOTIFY,
				 acpi_dock_notify_handler, dev);

	return (0);
}
Ejemplo n.º 9
0
static int
acpi_button_attach(device_t dev)
{
    struct acpi_prw_data	prw;
    struct acpi_button_softc	*sc;
    ACPI_STATUS			status;
    int event;

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

    sc = device_get_softc(dev);
    sc->button_dev = dev;
    sc->button_handle = acpi_get_handle(dev);
    event = (sc->button_type == ACPI_SLEEP_BUTTON) ?
	    ACPI_EVENT_SLEEP_BUTTON : ACPI_EVENT_POWER_BUTTON;

    /* 
     * Install the new handler.  We could remove any fixed handlers added
     * from the FADT once we have a duplicate from the AML but some systems
     * only return events on one or the other so we have to keep both.
     */
    if (sc->fixed) {
	AcpiClearEvent(event);
	status = AcpiInstallFixedEventHandler(event,
			acpi_button_fixed_handler, sc);
    } else {
	/*
	 * If a system does not get lid events, it may make sense to change
	 * the type to ACPI_ALL_NOTIFY.  Some systems generate both a wake
	 * and runtime notify in that case though.
	 */
	status = AcpiInstallNotifyHandler(sc->button_handle,
			ACPI_DEVICE_NOTIFY, acpi_button_notify_handler, sc);
    }
    if (ACPI_FAILURE(status)) {
	device_printf(sc->button_dev, "couldn't install notify handler - %s\n",
		      AcpiFormatException(status));
	return_VALUE (ENXIO);
    }

    /* Enable the GPE for wake/runtime */
    acpi_wake_set_enable(dev, 1);
    if (acpi_parse_prw(sc->button_handle, &prw) == 0)
	AcpiEnableGpe(prw.gpe_handle, prw.gpe_bit);
    
    return_VALUE (0);
}
Ejemplo n.º 10
0
Archivo: acpica.c Proyecto: olsner/os
static ACPI_STATUS InstallHandlers (void)
{
    ACPI_STATUS             Status;


    /* Install global notify handler */

    Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY,
                                        NotifyHandler, NULL);
    if (ACPI_FAILURE (Status))
    {
        ACPI_EXCEPTION ((AE_INFO, Status, "While installing Notify handler"));
        return (Status);
    }

    return (AE_OK);
}
Ejemplo n.º 11
0
/*
 * acpitz_attach: autoconf(9) attach routine
 */
void
acpitz_attach(struct device *parent, struct device *self, void *aux)
{
	struct acpitz_softc *sc = (struct acpitz_softc *)self;
	struct acpi_attach_args *aa = aux;
	ACPI_STATUS rv;
	ACPI_INTEGER v;

#if 0
	sc->sc_flags = ATZ_F_VERBOSE;
#endif
	sc->sc_devnode = aa->aa_node;

	printf(": ACPI Thermal Zone\n");

	rv = acpi_eval_integer(sc->sc_devnode->ad_handle, "_TZP", &v);
	if (ACPI_FAILURE(rv)) {
		printf("%s: unable to get polling interval; using default of",
		    sc->sc_dev.dv_xname);
		sc->sc_zone.tzp = ATZ_TZP_RATE;
	} else {
		sc->sc_zone.tzp = v;
		printf("%s: polling interval is", sc->sc_dev.dv_xname);
	}
	printf(" %d.%ds\n", sc->sc_zone.tzp / 10, sc->sc_zone.tsp % 10);

	/* XXX a value of 0 means "polling is not necessary" */
	if (sc->sc_zone.tzp == 0)
		sc->sc_zone.tzp = ATZ_TZP_RATE;
	
	acpitz_get_status(sc);

	rv = AcpiInstallNotifyHandler(sc->sc_devnode->ad_handle,
	    ACPI_SYSTEM_NOTIFY, acpitz_notify_handler, sc);
	if (ACPI_FAILURE(rv)) {
		printf("%s: unable to install SYSTEM NOTIFY handler: %s\n",
		    sc->sc_dev.dv_xname, AcpiFormatException(rv));
		return;
	}

	callout_init(&sc->sc_callout);
	callout_reset(&sc->sc_callout, (sc->sc_zone.tzp / 10) * hz,
	    acpitz_tick, sc);

	acpitz_init_envsys(sc);
}
Ejemplo n.º 12
0
static int
acpi_cmbat_attach(device_t dev)
{
	int		error;
	ACPI_HANDLE	handle;
	struct acpi_cmbat_softc *sc;

	if ((sc = device_get_softc(dev)) == NULL) {
		return (ENXIO);
	}

	handle = acpi_get_handle(dev);

	AcpiInstallNotifyHandler(handle, ACPI_DEVICE_NOTIFY,
				 acpi_cmbat_notify_handler, dev);

	sc->bif_updating = sc->bst_updating = 0;
	sc->dev = dev;

	timespecclear(&sc->bif_lastupdated);
	timespecclear(&sc->bst_lastupdated);

	if (acpi_cmbat_units == 0) {
		if ((error = acpi_register_ioctl(ACPIIO_CMBAT_GET_BIF,
				acpi_cmbat_ioctl, NULL)) != 0) {
			return (error);
		}
		if ((error = acpi_register_ioctl(ACPIIO_CMBAT_GET_BST,
				acpi_cmbat_ioctl, NULL)) != 0) {
			return (error);
		}
	}

	if ((error = acpi_battery_register(ACPI_BATT_TYPE_CMBAT,
			acpi_cmbat_units)) != 0) {
		return (error);
	}

	acpi_cmbat_units++;
	timespecclear(&acpi_cmbat_info_lastupdated);
	sc->initializing = 0;

	AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cmbat_init_battery, dev);
	return (0);
}
Ejemplo n.º 13
0
static int
acpi_lid_attach(device_t dev)
{
    struct acpi_lid_softc	*sc;

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

    sc = device_get_softc(dev);
    sc->lid_dev = dev;
    sc->lid_handle = acpi_get_handle(dev);

    /*
     * Install notification handler
     */
    AcpiInstallNotifyHandler(sc->lid_handle, ACPI_DEVICE_NOTIFY, acpi_lid_notify_handler, sc);
    acpi_device_enable_wake_capability(sc->lid_handle, 1);
    return_VALUE(0);
}
Ejemplo n.º 14
0
static int
acpi_button_attach(device_t dev)
{
    struct acpi_button_softc	*sc;
    ACPI_STATUS			status;

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

    sc = device_get_softc(dev);
    sc->button_dev = dev;
    sc->button_handle = acpi_get_handle(dev);

    if (ACPI_FAILURE(status = AcpiInstallNotifyHandler(sc->button_handle, ACPI_DEVICE_NOTIFY, 
					   acpi_button_notify_handler, sc))) {
	device_printf(sc->button_dev, "couldn't install Notify handler - %s\n", AcpiFormatException(status));
	return_VALUE(ENXIO);
    }
    acpi_device_enable_wake_capability(sc->button_handle, 1);
    return_VALUE(0);
}
Ejemplo n.º 15
0
/*
 * acpilid_attach:
 *
 *	Autoconfiguration `attach' routine.
 */
void
acpilid_attach(struct device *parent, struct device *self, void *aux)
{
	struct acpilid_softc *sc = (void *) self;
	struct acpi_attach_args *aa = aux;
	ACPI_STATUS rv;

	printf(": ACPI Lid Switch\n");

	sc->sc_node = aa->aa_node;

	rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle,
	    ACPI_DEVICE_NOTIFY, acpilid_notify_handler, sc);
	if (rv != AE_OK) {
		printf("%s: unable to register device notify handler: %d\n",
		    sc->sc_dev.dv_xname, rv);
		return;
	}

	/* Display the current state when it changes. */
	sc->sc_flags = ACPILID_F_VERBOSE;
}
Ejemplo n.º 16
0
/*
 * Install event handler for ACPI system events.
 * Acpinex driver handles ACPI system events for its children,
 * device specific events will be handled by device drivers.
 * Return DDI_SUCCESS on success, and DDI_FAILURE on failure.
 */
static int
acpinex_event_install_handler(ACPI_HANDLE hdl, void *arg,
    ACPI_DEVICE_INFO *infop, acpidev_data_handle_t dhdl)
{
	int rc = DDI_SUCCESS;

	ASSERT(hdl != NULL);
	ASSERT(dhdl != NULL);
	ASSERT(infop != NULL);

	/*
	 * Check whether the event handler has already been installed on the
	 * device object. With the introduction of ACPI Alias objects, which are
	 * similar to symlinks in file systems, there may be multiple name
	 * objects in the ACPI namespace pointing to the same underlying device
	 * object. Those Alias objects need to be filtered out, otherwise
	 * it will attempt to install the event handler multiple times on the
	 * same device object which will fail.
	 */
	if (acpidev_data_get_flag(dhdl, ACPIDEV_DATA_HANDLER_READY)) {
		return (DDI_SUCCESS);
	}
	if (ACPI_SUCCESS(AcpiInstallNotifyHandler(hdl, ACPI_SYSTEM_NOTIFY,
	    acpinex_event_system_handler, arg))) {
		acpidev_data_set_flag(dhdl, ACPIDEV_DATA_HANDLER_READY);
	} else {
		char *objname;

		objname = acpidev_get_object_name(hdl);
		cmn_err(CE_WARN,
		    "!acpinex: failed to install system event handler for %s.",
		    objname);
		acpidev_free_object_name(objname);
		rc = DDI_FAILURE;
	}

	return (rc);
}
Ejemplo n.º 17
0
static int
acpi_acad_attach(device_t dev)
{
    struct acpi_acad_softc *sc;
    struct acpi_softc	   *acpi_sc;
    ACPI_HANDLE	handle;
    int		error;

    sc = device_get_softc(dev);
    handle = acpi_get_handle(dev);

    error = acpi_register_ioctl(ACPIIO_ACAD_GET_STATUS, acpi_acad_ioctl, dev);
    if (error != 0)
	return (error);

    ACPI_SERIAL_INIT(acad);

    if (device_get_unit(dev) == 0) {
	acpi_sc = acpi_device_get_parent_softc(dev);
	SYSCTL_ADD_PROC(&acpi_sc->acpi_sysctl_ctx,
			SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
			OID_AUTO, "acline", CTLTYPE_INT | CTLFLAG_RD,
			&sc->status, 0, acpi_acad_sysctl, "I", "");
    }

    /* Get initial status after whole system is up. */
    sc->status = -1;

    /*
     * Install both system and device notify handlers since the Casio
     * FIVA needs them.
     */
    AcpiInstallNotifyHandler(handle, ACPI_ALL_NOTIFY,
			     acpi_acad_notify_handler, dev);
    AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_acad_init_acline, dev);

    return (0);
}
Ejemplo n.º 18
0
static int
acpi_fujitsu_attach(device_t dev)
{
	struct acpi_fujitsu_softc *sc;

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

	sc = device_get_softc(dev);
	sc->dev = dev;
	sc->handle = acpi_get_handle(dev);

	/* Install notification handler */
	AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY,
	    acpi_fujitsu_notify_handler, sc);

	/* Snag our default values for the hotkeys / hotkey states. */
	ACPI_SERIAL_BEGIN(fujitsu);
	if (!acpi_fujitsu_init(sc))
		device_printf(dev, "Couldn't initialize hotkey states!\n");
	ACPI_SERIAL_END(fujitsu);

	return (0);
}
Ejemplo n.º 19
0
/*
 * Call this *after* all CPUs have been attached.
 */
static void
acpi_cpu_startup(void *arg)
{
    struct acpi_cpu_softc *sc;
    int i;

    /* Get set of CPU devices */
    devclass_get_devices(acpi_cpu_devclass, &cpu_devices, &cpu_ndevices);

    /*
     * Setup any quirks that might necessary now that we have probed
     * all the CPUs
     */
    acpi_cpu_quirks();

    cpu_cx_count = 0;
    if (cpu_cx_generic) {
	/*
	 * We are using generic Cx mode, probe for available Cx states
	 * for all processors.
	 */
	for (i = 0; i < cpu_ndevices; i++) {
	    sc = device_get_softc(cpu_devices[i]);
	    acpi_cpu_generic_cx_probe(sc);
	    if (sc->cpu_cx_count > cpu_cx_count)
		    cpu_cx_count = sc->cpu_cx_count;
	}

	/*
	 * Find the highest Cx state common to all CPUs
	 * in the system, taking quirks into account.
	 */
	for (i = 0; i < cpu_ndevices; i++) {
	    sc = device_get_softc(cpu_devices[i]);
	    if (sc->cpu_cx_count < cpu_cx_count)
		cpu_cx_count = sc->cpu_cx_count;
	}
    } else {
	/*
	 * We are using _CST mode, remove C3 state if necessary.
	 * Update the largest Cx state supported in the global cpu_cx_count.
	 * It will be used in the global Cx sysctl handler.
	 * As we now know for sure that we will be using _CST mode
	 * install our notify handler.
	 */
	for (i = 0; i < cpu_ndevices; i++) {
	    sc = device_get_softc(cpu_devices[i]);
	    if (cpu_quirks & CPU_QUIRK_NO_C3) {
		sc->cpu_cx_count = sc->cpu_non_c3 + 1;
	    }
	    if (sc->cpu_cx_count > cpu_cx_count)
		cpu_cx_count = sc->cpu_cx_count;
	    AcpiInstallNotifyHandler(sc->cpu_handle, ACPI_DEVICE_NOTIFY,
		acpi_cpu_notify, sc);
	}
    }

    /* Perform Cx final initialization. */
    for (i = 0; i < cpu_ndevices; i++) {
	sc = device_get_softc(cpu_devices[i]);
	acpi_cpu_startup_cx(sc);
    }

    /* Add a sysctl handler to handle global Cx lowest setting */
    SYSCTL_ADD_PROC(&cpu_sysctl_ctx, SYSCTL_CHILDREN(cpu_sysctl_tree),
	OID_AUTO, "cx_lowest", CTLTYPE_STRING | CTLFLAG_RW,
	NULL, 0, acpi_cpu_global_cx_lowest_sysctl, "A",
	"Global lowest Cx sleep state to use");

    /* Take over idling from cpu_idle_default(). */
    cpu_cx_lowest = 0;
    cpu_disable_idle = FALSE;
    cpu_idle_hook = acpi_cpu_idle;
}
Ejemplo n.º 20
0
static int
acpi_tz_attach(device_t dev)
{
    struct acpi_tz_softc	*sc;
    struct acpi_softc		*acpi_sc;
    int				error;
    char			oidname[8];

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

    sc = device_get_softc(dev);
    sc->tz_dev = dev;
    sc->tz_handle = acpi_get_handle(dev);
    sc->tz_requested = TZ_ACTIVE_NONE;
    sc->tz_active = TZ_ACTIVE_UNKNOWN;
    sc->tz_thflags = TZ_THFLAG_NONE;
    sc->tz_cooling_proc = NULL;
    sc->tz_cooling_proc_running = FALSE;
    sc->tz_cooling_active = FALSE;
    sc->tz_cooling_updated = FALSE;
    sc->tz_cooling_enabled = FALSE;

    /*
     * Parse the current state of the thermal zone and build control
     * structures.  We don't need to worry about interference with the
     * control thread since we haven't fully attached this device yet.
     */
    if ((error = acpi_tz_establish(sc)) != 0)
	return (error);

    /*
     * Register for any Notify events sent to this zone.
     */
    AcpiInstallNotifyHandler(sc->tz_handle, ACPI_DEVICE_NOTIFY,
			     acpi_tz_notify_handler, sc);

    /*
     * Create our sysctl nodes.
     *
     * XXX we need a mechanism for adding nodes under ACPI.
     */
    if (device_get_unit(dev) == 0) {
	acpi_sc = acpi_device_get_parent_softc(dev);
	sysctl_ctx_init(&acpi_tz_sysctl_ctx);
	acpi_tz_sysctl_tree = SYSCTL_ADD_NODE(&acpi_tz_sysctl_ctx,
			      SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
			      OID_AUTO, "thermal", CTLFLAG_RD, 0, "");
	SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
		       SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
		       OID_AUTO, "min_runtime", CTLFLAG_RW,
		       &acpi_tz_min_runtime, 0,
		       "minimum cooling run time in sec");
	SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
		       SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
		       OID_AUTO, "polling_rate", CTLFLAG_RW,
		       &acpi_tz_polling_rate, 0, "monitor polling interval in seconds");
	SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
		       SYSCTL_CHILDREN(acpi_tz_sysctl_tree), OID_AUTO,
		       "user_override", CTLFLAG_RW, &acpi_tz_override, 0,
		       "allow override of thermal settings");
    }
    sysctl_ctx_init(&sc->tz_sysctl_ctx);
    sprintf(oidname, "tz%d", device_get_unit(dev));
    sc->tz_sysctl_tree = SYSCTL_ADD_NODE(&sc->tz_sysctl_ctx,
					 SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
					 OID_AUTO, oidname, CTLFLAG_RD, 0, "");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD,
		    &sc->tz_temperature, 0, sysctl_handle_int,
		    "IK", "current thermal zone temperature");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "active", CTLTYPE_INT | CTLFLAG_RW,
		    sc, 0, acpi_tz_active_sysctl, "I", "cooling is active");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "passive_cooling", CTLTYPE_INT | CTLFLAG_RW,
		    sc, 0, acpi_tz_cooling_sysctl, "I",
		    "enable passive (speed reduction) cooling");

    SYSCTL_ADD_INT(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		   OID_AUTO, "thermal_flags", CTLFLAG_RD,
		   &sc->tz_thflags, 0, "thermal zone flags");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_PSV", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.psv),
		    acpi_tz_temp_sysctl, "IK", "passive cooling temp setpoint");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_HOT", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.hot),
		    acpi_tz_temp_sysctl, "IK",
		    "too hot temp setpoint (suspend now)");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_CRT", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.crt),
		    acpi_tz_temp_sysctl, "IK",
		    "critical temp setpoint (shutdown now)");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_ACx", CTLTYPE_INT | CTLFLAG_RD,
		    &sc->tz_zone.ac, sizeof(sc->tz_zone.ac),
		    sysctl_handle_opaque, "IK", "");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_TC1", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.tc1),
		    acpi_tz_passive_sysctl, "I",
		    "thermal constant 1 for passive cooling");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_TC2", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.tc2),
		    acpi_tz_passive_sysctl, "I",
		    "thermal constant 2 for passive cooling");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_TSP", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.tsp),
		    acpi_tz_passive_sysctl, "I",
		    "thermal sampling period for passive cooling");

    /*
     * Create thread to service all of the thermal zones.  Register
     * our power profile event handler.
     */
    sc->tz_event = EVENTHANDLER_REGISTER(power_profile_change,
	acpi_tz_power_profile, sc, 0);
    if (acpi_tz_proc == NULL) {
	error = kproc_create(acpi_tz_thread, NULL, &acpi_tz_proc,
	    RFHIGHPID, 0, "acpi_thermal");
	if (error != 0) {
	    device_printf(sc->tz_dev, "could not create thread - %d", error);
	    goto out;
	}
    }

    /*
     * Create a thread to handle passive cooling for 1st zone which
     * has _PSV, _TSP, _TC1 and _TC2.  Users can enable it for other
     * zones manually for now.
     *
     * XXX We enable only one zone to avoid multiple zones conflict
     * with each other since cpufreq currently sets all CPUs to the
     * given frequency whereas it's possible for different thermal
     * zones to specify independent settings for multiple CPUs.
     */
    if (acpi_tz_cooling_unit < 0 && acpi_tz_cooling_is_available(sc))
	sc->tz_cooling_enabled = TRUE;
    if (sc->tz_cooling_enabled) {
	error = acpi_tz_cooling_thread_start(sc);
	if (error != 0) {
	    sc->tz_cooling_enabled = FALSE;
	    goto out;
	}
	acpi_tz_cooling_unit = device_get_unit(dev);
    }

    /*
     * Flag the event handler for a manual invocation by our timeout.
     * We defer it like this so that the rest of the subsystem has time
     * to come up.  Don't bother evaluating/printing the temperature at
     * this point; on many systems it'll be bogus until the EC is running.
     */
    sc->tz_flags |= TZ_FLAG_GETPROFILE;

out:
    if (error != 0) {
	EVENTHANDLER_DEREGISTER(power_profile_change, sc->tz_event);
	AcpiRemoveNotifyHandler(sc->tz_handle, ACPI_DEVICE_NOTIFY,
	    acpi_tz_notify_handler);
	sysctl_ctx_free(&sc->tz_sysctl_ctx);
    }
    return_VALUE (error);
}
Ejemplo n.º 21
0
static void
sony_acpi_attach(device_t parent, device_t self, void *aux)
{
	struct sony_acpi_softc *sc = device_private(self);
	struct acpi_attach_args *aa = aux;
	ACPI_STATUS rv;
	int i;

	aprint_naive(": Sony Miscellaneous Controller\n");
	aprint_normal(": Sony Miscellaneous Controller\n");

	sc->sc_node = aa->aa_node;
	sc->sc_dev = self;

	rv = AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 100,
	    sony_acpi_find_pic, sc, NULL);
	if (ACPI_FAILURE(rv))
		aprint_error_dev(self, "couldn't walk namespace: %s\n",
		    AcpiFormatException(rv));

	/*
	 * If we don't find an SNY6001 device, assume that we need the
	 * Fn key initialization sequence.
	 */
	if (sc->sc_has_pic == false)
		sc->sc_quirks |= SONY_ACPI_QUIRK_FNINIT;

	sony_acpi_quirk_setup(sc);

	/* Configure suspend button and hotkeys */
	sc->sc_smpsw[SONY_PSW_SLEEP].smpsw_name = device_xname(self);
	sc->sc_smpsw[SONY_PSW_SLEEP].smpsw_type = PSWITCH_TYPE_SLEEP;
	sc->sc_smpsw[SONY_PSW_DISPLAY_CYCLE].smpsw_name =
	    PSWITCH_HK_DISPLAY_CYCLE;
	sc->sc_smpsw[SONY_PSW_DISPLAY_CYCLE].smpsw_type = PSWITCH_TYPE_HOTKEY;
	sc->sc_smpsw[SONY_PSW_ZOOM].smpsw_name = PSWITCH_HK_ZOOM_BUTTON;
	sc->sc_smpsw[SONY_PSW_ZOOM].smpsw_type = PSWITCH_TYPE_HOTKEY;
	sc->sc_smpsw_valid = 1;

	for (i = 0; i < SONY_PSW_LAST; i++)
		if (sysmon_pswitch_register(&sc->sc_smpsw[i]) != 0) {
			aprint_error_dev(self, 
			    "couldn't register %s with sysmon\n",
			    sc->sc_smpsw[i].smpsw_name);
			sc->sc_smpsw_valid = 0;
		}

	/* Install notify handler */
	rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle,
	    ACPI_DEVICE_NOTIFY, sony_acpi_notify_handler, self);
	if (ACPI_FAILURE(rv))
		aprint_error_dev(self,
		    "couldn't install notify handler (%d)\n", rv);

	/* Install sysctl handler */
	rv = AcpiWalkNamespace(ACPI_TYPE_METHOD,
	    sc->sc_node->ad_handle, 1, sony_walk_cb, sc, NULL);
#ifdef DIAGNOSTIC
	if (ACPI_FAILURE(rv))
		aprint_error_dev(self, "Cannot walk ACPI namespace (%d)\n",
		    rv);
#endif

	if (!pmf_device_register(self, sony_acpi_suspend, sony_acpi_resume))
		aprint_error_dev(self, "couldn't establish power handler\n");

	if (!pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_UP,
				 sony_acpi_brightness_up, true))
		aprint_error_dev(self, "couldn't register BRIGHTNESS UP handler\n");

	if (!pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_DOWN,
				 sony_acpi_brightness_down, true))
		aprint_error_dev(self, "couldn't register BRIGHTNESS DOWN handler\n");
}
Ejemplo n.º 22
0
static status_t
acpi_std_ops(int32 op,...)
{
    switch (op) {
    case B_MODULE_INIT:
    {
        ACPI_OBJECT arg;
        ACPI_OBJECT_LIST parameter;
        void *settings;
        bool acpiDisabled = false;
        AcpiGbl_CopyDsdtLocally = true;

        settings = load_driver_settings("kernel");
        if (settings != NULL) {
            acpiDisabled = !get_driver_boolean_parameter(settings, "acpi",
                           true, true);
            unload_driver_settings(settings);
        }

        if (!acpiDisabled) {
            // check if safemode settings disable ACPI
            settings = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS);
            if (settings != NULL) {
                acpiDisabled = get_driver_boolean_parameter(settings,
                               B_SAFEMODE_DISABLE_ACPI, false, false);
                unload_driver_settings(settings);
            }
        }

        if (acpiDisabled) {
            ERROR("ACPI disabled\n");
            return ENOSYS;
        }

        if (gDPC->new_dpc_queue(&gDPCHandle, "acpi_task",
                                B_URGENT_DISPLAY_PRIORITY + 1) != B_OK) {
            ERROR("failed to create os execution queue\n");
            return B_ERROR;
        }

#ifdef ACPI_DEBUG_OUTPUT
        AcpiDbgLevel = ACPI_DEBUG_ALL | ACPI_LV_VERBOSE;
        AcpiDbgLayer = ACPI_ALL_COMPONENTS;
#endif

        if (checkAndLogFailure(AcpiInitializeSubsystem(),
                               "AcpiInitializeSubsystem failed"))
            goto err;

        if (checkAndLogFailure(AcpiInitializeTables(NULL, 0, TRUE),
                               "AcpiInitializeTables failed"))
            goto err;

        if (checkAndLogFailure(AcpiLoadTables(),
                               "AcpiLoadTables failed"))
            goto err;

        /* Install the default address space handlers. */
        if (checkAndLogFailure(AcpiInstallAddressSpaceHandler(
                                   ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_SYSTEM_MEMORY,
                                   ACPI_DEFAULT_HANDLER, NULL, NULL),
                               "Could not initialise SystemMemory handler:"))
            goto err;

        if (checkAndLogFailure(AcpiInstallAddressSpaceHandler(
                                   ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_SYSTEM_IO,
                                   ACPI_DEFAULT_HANDLER, NULL, NULL),
                               "Could not initialise SystemIO handler:"))
            goto err;

        if (checkAndLogFailure(AcpiInstallAddressSpaceHandler(
                                   ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_PCI_CONFIG,
                                   ACPI_DEFAULT_HANDLER, NULL, NULL),
                               "Could not initialise PciConfig handler:"))
            goto err;

        arg.Integer.Type = ACPI_TYPE_INTEGER;
        arg.Integer.Value = apic_available() ? APIC_MODE : PIC_MODE;

        parameter.Count = 1;
        parameter.Pointer = &arg;

        AcpiEvaluateObject(NULL, "\\_PIC", &parameter, NULL);

        if (checkAndLogFailure(AcpiEnableSubsystem(
                                   ACPI_FULL_INITIALIZATION),
                               "AcpiEnableSubsystem failed"))
            goto err;

        if (checkAndLogFailure(AcpiInitializeObjects(
                                   ACPI_FULL_INITIALIZATION),
                               "AcpiInitializeObjects failed"))
            goto err;

        //TODO: Walk namespace init ALL _PRW's

#ifdef ACPI_DEBUG_OUTPUT
        checkAndLogFailure(
            AcpiInstallGlobalEventHandler(globalGPEHandler, NULL),
            "Failed to install global GPE-handler.");

        checkAndLogFailure(AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT,
                           ACPI_ALL_NOTIFY, globalNotifyHandler, NULL),
                           "Failed to install global Notify-handler.");
#endif
        checkAndLogFailure(AcpiEnableAllRuntimeGpes(),
                           "Failed to enable all runtime Gpes");

        checkAndLogFailure(AcpiUpdateAllGpes(),
                           "Failed to update all Gpes");

        TRACE("ACPI initialized\n");
        return B_OK;

err:
        return B_ERROR;
    }

    case B_MODULE_UNINIT:
    {
        if (checkAndLogFailure(AcpiTerminate(),
                               "Could not bring system out of ACPI mode. Oh well."));

        gDPC->delete_dpc_queue(gDPCHandle);
        gDPCHandle = NULL;
        break;
    }

    default:
        return B_ERROR;
    }
    return B_OK;
}
Ejemplo n.º 23
0
/* Probe and setup any valid performance states (Px). */
static int
acpi_perf_evaluate(device_t dev)
{
	struct acpi_perf_softc *sc;
	ACPI_BUFFER buf;
	ACPI_OBJECT *pkg, *res;
	ACPI_STATUS status;
	int count, error, i, j;
	static int once = 1;
	uint32_t *p;

	/* Get the control values and parameters for each state. */
	error = ENXIO;
	sc = device_get_softc(dev);
	buf.Pointer = NULL;
	buf.Length = ACPI_ALLOCATE_BUFFER;
	status = AcpiEvaluateObject(sc->handle, "_PSS", NULL, &buf);
	if (ACPI_FAILURE(status))
		return (ENXIO);

	pkg = (ACPI_OBJECT *)buf.Pointer;
	if (!ACPI_PKG_VALID(pkg, 1)) {
		device_printf(dev, "invalid top level _PSS package\n");
		goto out;
	}
	sc->px_count = pkg->Package.Count;

	sc->px_states = malloc(sc->px_count * sizeof(struct acpi_px),
	    M_ACPIPERF, M_WAITOK | M_ZERO);
	if (sc->px_states == NULL)
		goto out;

	/*
	 * Each state is a package of {CoreFreq, Power, TransitionLatency,
	 * BusMasterLatency, ControlVal, StatusVal}, sorted from highest
	 * performance to lowest.
	 */
	count = 0;
	for (i = 0; i < sc->px_count; i++) {
		res = &pkg->Package.Elements[i];
		if (!ACPI_PKG_VALID(res, 6)) {
			if (once) {
				once = 0;
				device_printf(dev, "invalid _PSS package\n");
			}
			continue;
		}

		/* Parse the rest of the package into the struct. */
		p = &sc->px_states[count].core_freq;
		for (j = 0; j < 6; j++, p++)
			acpi_PkgInt32(res, j, p);

		/*
		 * Check for some impossible frequencies that some systems
		 * use to indicate they don't actually support this Px state.
		 */
		if (sc->px_states[count].core_freq == 0 ||
		    sc->px_states[count].core_freq == 9999 ||
		    sc->px_states[count].core_freq == 0x9999 ||
		    sc->px_states[count].core_freq >= 0xffff)
			continue;

		/* Check for duplicate entries */
		if (count > 0 &&
		    sc->px_states[count - 1].core_freq ==
			sc->px_states[count].core_freq)
			continue;

		count++;
	}
	sc->px_count = count;

	/* No valid Px state found so give up. */
	if (count == 0)
		goto out;
	AcpiOsFree(buf.Pointer);

	/* Get the control and status registers (one of each). */
	buf.Pointer = NULL;
	buf.Length = ACPI_ALLOCATE_BUFFER;
	status = AcpiEvaluateObject(sc->handle, "_PCT", NULL, &buf);
	if (ACPI_FAILURE(status))
		goto out;

	/* Check the package of two registers, each a Buffer in GAS format. */
	pkg = (ACPI_OBJECT *)buf.Pointer;
	if (!ACPI_PKG_VALID(pkg, 2)) {
		device_printf(dev, "invalid perf register package\n");
		goto out;
	}

	error = acpi_PkgGas(sc->dev, pkg, 0, &sc->perf_ctrl_type, &sc->px_rid,
	    &sc->perf_ctrl, 0);
	if (error) {
		/*
		 * If the register is of type FFixedHW, we can only return
		 * info, we can't get or set new settings.
		 */
		if (error == EOPNOTSUPP) {
			sc->info_only = TRUE;
			error = 0;
		} else
			device_printf(dev, "failed in PERF_CTL attach\n");
		goto out;
	}
	sc->px_rid++;

	error = acpi_PkgGas(sc->dev, pkg, 1, &sc->perf_sts_type, &sc->px_rid,
	    &sc->perf_status, 0);
	if (error) {
		if (error == EOPNOTSUPP) {
			sc->info_only = TRUE;
			error = 0;
		} else
			device_printf(dev, "failed in PERF_STATUS attach\n");
		goto out;
	}
	sc->px_rid++;

	/* Get our current limit and register for notifies. */
	acpi_px_available(sc);
	AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY,
	    acpi_px_notify, sc);
	error = 0;

out:
	if (error) {
		if (sc->px_states) {
			free(sc->px_states, M_ACPIPERF);
			sc->px_states = NULL;
		}
		if (sc->perf_ctrl) {
			bus_release_resource(sc->dev, sc->perf_ctrl_type, 0,
			    sc->perf_ctrl);
			bus_delete_resource(sc->dev, sc->perf_ctrl_type, 0);
			sc->perf_ctrl = NULL;
		}
		if (sc->perf_status) {
			bus_release_resource(sc->dev, sc->perf_sts_type, 1,
			    sc->perf_status);
			bus_delete_resource(sc->dev, sc->perf_sts_type, 1);
			sc->perf_status = NULL;
		}
		sc->px_rid = 0;
		sc->px_count = 0;
	}
	if (buf.Pointer)
		AcpiOsFree(buf.Pointer);
	return (error);
}
Ejemplo n.º 24
0
static void
thinkpad_attach(device_t parent, device_t self, void *opaque)
{
	thinkpad_softc_t *sc = device_private(self);
	struct acpi_attach_args *aa = (struct acpi_attach_args *)opaque;
	struct sysmon_pswitch *psw;
	device_t curdev;
	ACPI_STATUS rv;
	ACPI_INTEGER val;
	int i;

	sc->sc_node = aa->aa_node;
	sc->sc_dev = self;
	sc->sc_display_state = THINKPAD_DISPLAY_LCD;

	aprint_naive("\n");
	aprint_normal("\n");

	/* T61 uses \UCMS method for issuing CMOS commands */
	rv = AcpiGetHandle(NULL, "\\UCMS", &sc->sc_cmoshdl);
	if (ACPI_FAILURE(rv))
		sc->sc_cmoshdl_valid = false;
	else {
		aprint_verbose_dev(self, "using CMOS at \\UCMS\n");
		sc->sc_cmoshdl_valid = true;
	}

	sc->sc_ecdev = NULL;
	TAILQ_FOREACH(curdev, &alldevs, dv_list)
		if (device_is_a(curdev, "acpiecdt") ||
		    device_is_a(curdev, "acpiec")) {
			sc->sc_ecdev = curdev;
			break;
		}
	if (sc->sc_ecdev)
		aprint_verbose_dev(self, "using EC at %s\n",
		    device_xname(sc->sc_ecdev));

	/* Get the supported event mask */
	rv = acpi_eval_integer(sc->sc_node->ad_handle, "MHKA", &val);
	if (ACPI_FAILURE(rv)) {
		aprint_error_dev(self, "couldn't evaluate MHKA: %s\n",
		    AcpiFormatException(rv));
		goto fail;
	}

	/* Enable all supported events */
	rv = thinkpad_mask_init(sc, val);
	if (ACPI_FAILURE(rv)) {
		aprint_error_dev(self, "couldn't set event mask: %s\n",
		    AcpiFormatException(rv));
		goto fail;
	}

	/* Install notify handler for events */
	rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle,
	    ACPI_DEVICE_NOTIFY, thinkpad_notify_handler, sc);
	if (ACPI_FAILURE(rv))
		aprint_error_dev(self, "couldn't install notify handler: %s\n",
		    AcpiFormatException(rv));

	/* Register power switches with sysmon */
	psw = sc->sc_smpsw;
	sc->sc_smpsw_valid = true;

	psw[TP_PSW_SLEEP].smpsw_name = device_xname(self);
	psw[TP_PSW_SLEEP].smpsw_type = PSWITCH_TYPE_SLEEP;
#if notyet
	psw[TP_PSW_HIBERNATE].smpsw_name = device_xname(self);
	mpsw[TP_PSW_HIBERNATE].smpsw_type = PSWITCH_TYPE_HIBERNATE;
#endif
	for (i = TP_PSW_DISPLAY_CYCLE; i < TP_PSW_LAST; i++)
		sc->sc_smpsw[i].smpsw_type = PSWITCH_TYPE_HOTKEY;
	psw[TP_PSW_DISPLAY_CYCLE].smpsw_name = PSWITCH_HK_DISPLAY_CYCLE;
	psw[TP_PSW_LOCK_SCREEN].smpsw_name = PSWITCH_HK_LOCK_SCREEN;
	psw[TP_PSW_BATTERY_INFO].smpsw_name = PSWITCH_HK_BATTERY_INFO;
	psw[TP_PSW_EJECT_BUTTON].smpsw_name = PSWITCH_HK_EJECT_BUTTON;
	psw[TP_PSW_ZOOM_BUTTON].smpsw_name = PSWITCH_HK_ZOOM_BUTTON;
	psw[TP_PSW_VENDOR_BUTTON].smpsw_name = PSWITCH_HK_VENDOR_BUTTON;

	for (i = 0; i < TP_PSW_LAST; i++) {
		/* not supported yet */
		if (i == TP_PSW_HIBERNATE)
			continue;
		if (sysmon_pswitch_register(&sc->sc_smpsw[i]) != 0) {
			aprint_error_dev(self,
			    "couldn't register with sysmon\n");
			sc->sc_smpsw_valid = false;
			break;
		}
	}

	/* Register temperature and fan sensors with envsys */
	thinkpad_sensors_init(sc);

fail:
	if (!pmf_device_register(self, NULL, thinkpad_resume))
		aprint_error_dev(self, "couldn't establish power handler\n");
	if (!pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_UP,
	    thinkpad_brightness_up, true))
		aprint_error_dev(self, "couldn't register event handler\n");
	if (!pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_DOWN,
	    thinkpad_brightness_down, true))
		aprint_error_dev(self, "couldn't register event handler\n");
}
Ejemplo n.º 25
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;

    sc->cpu_dev = dev;

    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) {
	uint32_t cap_set[3];
	ACPI_STATUS status;

	cap_set[0] = 0;
	cap_set[1] = cpu_features;
	status = acpi_eval_osc(dev, handle,
	    "4077A616-290C-47BE-9EBD-D87058713953", 1, cap_set, 2);

	if (ACPI_FAILURE(status)) {
	    ACPI_OBJECT_LIST arglist;
	    ACPI_OBJECT arg[4];

	    if (bootverbose)
		device_printf(dev, "_OSC failed, using _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);
	}
    }

    ksnprintf(sc->cpu_sensdev.xname, sizeof(sc->cpu_sensdev.xname), "%s",
	device_get_nameunit(dev));
    sensordev_install(&sc->cpu_sensdev);

    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);
    sc->cpu_pst = child;

    bus_generic_probe(dev);
    bus_generic_attach(dev);

    AcpiInstallNotifyHandler(handle, ACPI_DEVICE_NOTIFY, acpi_cpu_notify, sc);

    return 0;
}
Ejemplo n.º 26
0
ACPI_STATUS
AeInstallHandlers (void)
{
    ACPI_STATUS             Status;
    UINT32                  i;
    ACPI_HANDLE             Handle;


    ACPI_FUNCTION_ENTRY ();


    Status = AcpiInstallTableHandler (AeTableHandler, NULL);
    if (ACPI_FAILURE (Status))
    {
        printf ("Could not install table handler, %s\n",
            AcpiFormatException (Status));
    }

    Status = AcpiInstallExceptionHandler (AeExceptionHandler);
    if (ACPI_FAILURE (Status))
    {
        printf ("Could not install exception handler, %s\n",
            AcpiFormatException (Status));
    }

    /* Install global notify handler */

    Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY,
                                        AeNotifyHandler, NULL);
    if (ACPI_FAILURE (Status))
    {
        printf ("Could not install a global notify handler, %s\n",
            AcpiFormatException (Status));
    }

    Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_DEVICE_NOTIFY,
                                        AeDeviceNotifyHandler, NULL);
    if (ACPI_FAILURE (Status))
    {
        printf ("Could not install a global notify handler, %s\n",
            AcpiFormatException (Status));
    }

    Status = AcpiGetHandle (NULL, "\\_SB", &Handle);
    if (ACPI_SUCCESS (Status))
    {
        Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
                                            AeNotifyHandler, NULL);
        if (ACPI_FAILURE (Status))
        {
            printf ("Could not install a notify handler, %s\n",
                AcpiFormatException (Status));
        }

        Status = AcpiRemoveNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
                                            AeNotifyHandler);
        if (ACPI_FAILURE (Status))
        {
            printf ("Could not remove a notify handler, %s\n",
                AcpiFormatException (Status));
        }

        Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
                                            AeNotifyHandler, NULL);
        Status = AcpiRemoveNotifyHandler (Handle, ACPI_ALL_NOTIFY,
                                            AeNotifyHandler);
        Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
                                            AeNotifyHandler, NULL);
        if (ACPI_FAILURE (Status))
        {
            printf ("Could not install a notify handler, %s\n",
                AcpiFormatException (Status));
        }

        Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle);
        Status = AcpiDetachData (Handle, AeAttachedDataHandler);
        Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle);
    }
    else
    {
        printf ("No _SB_ found, %s\n", AcpiFormatException (Status));
    }

    /* Set a handler for all supported operation regions */

    for (i = 0; i < AEXEC_NUM_REGIONS; i++)
    {
        Status = AcpiRemoveAddressSpaceHandler (AcpiGbl_RootNode,
                        SpaceId[i], AeRegionHandler);

        /* Install handler at the root object.
         * TBD: all default handlers should be installed here!
         */
        Status = AcpiInstallAddressSpaceHandler (AcpiGbl_RootNode,
                        SpaceId[i], AeRegionHandler, AeRegionInit, NULL);
        if (ACPI_FAILURE (Status))
        {
            ACPI_EXCEPTION ((AE_INFO, Status,
                "Could not install an OpRegion handler for %s space(%u)",
                AcpiUtGetRegionName((UINT8) SpaceId[i]), SpaceId[i]));
            return (Status);
        }
    }

    /*
     * Initialize the global Region Handler space
     * MCW 3/23/00
     */
    AeRegions.NumberOfRegions = 0;
    AeRegions.RegionList = NULL;

    return Status;
}
Ejemplo n.º 27
0
static int
acpi_cpu_attach(device_t dev)
{
    struct acpi_cpux_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->cpux_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_attach(dev);

    AcpiInstallNotifyHandler(handle, ACPI_DEVICE_NOTIFY, acpi_cpu_notify, sc);

    return 0;
}
Ejemplo n.º 28
0
void
acpi_secondary_init(void)
{
  ACPI_STATUS Status;
  ACPI_STATUS DisplayOneDevice (ACPI_HANDLE, UINT32, void *, void **);
  /* Complete the ACPICA initialization sequence */

  Status = AcpiInitializeSubsystem ();
  if (ACPI_FAILURE (Status)) {
    DLOG_COM1 ("Failed to initialize ACPI.\n");
  }
  Status = AcpiReallocateRootTable ();
  if (ACPI_FAILURE (Status)) {
    DLOG_COM1 ("Failed: AcpiReallocateRootTable %d.\n", Status);
  }
  Status = AcpiLoadTables ();
  if (ACPI_FAILURE (Status)) {
    DLOG_COM1 ("Failed: AcpiLoadTables.\n");
  }
  Status = AcpiEnableSubsystem (ACPI_FULL_INITIALIZATION);
  if (ACPI_FAILURE (Status)) {
    DLOG_COM1 ("Failed: AcpiEnableSubsystem.\n");
  }
  Status = AcpiInitializeObjects (ACPI_FULL_INITIALIZATION);
  if (ACPI_FAILURE (Status)) {
    DLOG_COM1 ("Failed: AcpiInitializeObjects.\n");
  }

  /* Must enable IOAPIC before checking any PCI routing tables. */
  acpi_enable_IOAPIC ();

  /* Install System Control Interrupt */
  u8 vector = find_unused_vector (MINIMUM_VECTOR_PRIORITY);
  if (vector) {
    u64 flags = IOAPIC_DELIVERY_FIXED | IOAPIC_DESTINATION_LOGICAL;
    u8 gsi = acpi_sci_irq;
    /* SCI defaults to LEVEL/LOW in IO-APIC mode. */
    if ((acpi_sci_flags & ACPI_MADT_POLARITY_MASK) == ACPI_MADT_POLARITY_ACTIVE_HIGH)
      flags |= IOAPIC_POLARITY_HIGH;
    else
      flags |= IOAPIC_POLARITY_LOW;
    if ((acpi_sci_flags & ACPI_MADT_TRIGGER_MASK) == ACPI_MADT_TRIGGER_EDGE)
      flags |= IOAPIC_TRIGGER_EDGE;
    else
      flags |= IOAPIC_TRIGGER_LEVEL;
    if (IOAPIC_map_GSI (gsi, vector, 0x0100000000000000ULL | flags) != -1) {
      set_vector_handler (vector, acpi_irq_handler);
      DLOG ("ACPI: mapped GSI 0x%X to vector 0x%X (%s, %s)\n",
                     gsi, vector,
                     flags & IOAPIC_TRIGGER_LEVEL ? "level" : "edge",
                     flags & IOAPIC_POLARITY_LOW ? "low" : "high");
    } else
      DLOG ("ACPI: failed to map GSI\n");
  } else
    DLOG ("ACPI: failed to find unused vector\n");

  DLOG ("AcpiEnableEvent returned %d\n",
                 AcpiEnableEvent (ACPI_EVENT_POWER_BUTTON, 0));
  DLOG ("AcpiInstallFixedEventHandler returned %d\n",
                 AcpiInstallFixedEventHandler (ACPI_EVENT_POWER_BUTTON, acpi_power_button, NULL));
  DLOG ("AcpiInstallNotifyHandler returned %d\n",
                 AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, acpi_notify_handler, NULL));
  DLOG ("AcpiInstallNotifyHandler returned %d\n",
                 AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_DEVICE_NOTIFY, acpi_notify_handler, NULL));

  extern u8 AcpiGbl_OsiData;
  AcpiGbl_OsiData=0;

  /* Walk the System Bus "\_SB_" and output info about each object
   * found. */

#if 0
  ACPI_HANDLE SysBusHandle;
  AcpiGetHandle (ACPI_ROOT_OBJECT, ACPI_NS_SYSTEM_BUS, &SysBusHandle);
  AcpiWalkNamespace (ACPI_TYPE_ANY, SysBusHandle, INT_MAX,
                     DisplayOneDevice, NULL, NULL);
#else
  AcpiGetDevices (NULL, DisplayOneDevice, NULL, NULL);
#endif
}
ACPI_STATUS
AeInstallEarlyHandlers (
    void)
{
    ACPI_STATUS             Status;
    UINT32                  i;
    ACPI_HANDLE             Handle;


    ACPI_FUNCTION_ENTRY ();


    Status = AcpiInstallInterfaceHandler (AeInterfaceHandler);
    if (ACPI_FAILURE (Status))
    {
        printf ("Could not install interface handler, %s\n",
            AcpiFormatException (Status));
    }

    Status = AcpiInstallTableHandler (AeTableHandler, NULL);
    if (ACPI_FAILURE (Status))
    {
        printf ("Could not install table handler, %s\n",
            AcpiFormatException (Status));
    }

    Status = AcpiInstallExceptionHandler (AeExceptionHandler);
    if (ACPI_FAILURE (Status))
    {
        printf ("Could not install exception handler, %s\n",
            AcpiFormatException (Status));
    }

    /* Install global notify handlers */

    Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY,
        AeSystemNotifyHandler, NULL);
    if (ACPI_FAILURE (Status))
    {
        printf ("Could not install a global system notify handler, %s\n",
            AcpiFormatException (Status));
    }

    Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_DEVICE_NOTIFY,
        AeDeviceNotifyHandler, NULL);
    if (ACPI_FAILURE (Status))
    {
        printf ("Could not install a global notify handler, %s\n",
            AcpiFormatException (Status));
    }

    Status = AcpiGetHandle (NULL, "\\_SB", &Handle);
    if (ACPI_SUCCESS (Status))
    {
        Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
            AeNotifyHandler1, NULL);
        if (ACPI_FAILURE (Status))
        {
            printf ("Could not install a notify handler, %s\n",
                AcpiFormatException (Status));
        }

        Status = AcpiRemoveNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
            AeNotifyHandler1);
        if (ACPI_FAILURE (Status))
        {
            printf ("Could not remove a notify handler, %s\n",
                AcpiFormatException (Status));
        }

        Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
            AeNotifyHandler1, NULL);
        AE_CHECK_OK (AcpiInstallNotifyHandler, Status);

        Status = AcpiRemoveNotifyHandler (Handle, ACPI_ALL_NOTIFY,
            AeNotifyHandler1);
        AE_CHECK_OK (AcpiRemoveNotifyHandler, Status);

#if 0
        Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
            AeNotifyHandler1, NULL);
        if (ACPI_FAILURE (Status))
        {
            printf ("Could not install a notify handler, %s\n",
                AcpiFormatException (Status));
        }
#endif

        /* Install two handlers for _SB_ */

        Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
            AeNotifyHandler1, ACPI_CAST_PTR (void, 0x01234567));

        Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
            AeNotifyHandler2, ACPI_CAST_PTR (void, 0x89ABCDEF));

        /* Attempt duplicate handler installation, should fail */

        Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
            AeNotifyHandler1, ACPI_CAST_PTR (void, 0x77777777));

        Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle);
        AE_CHECK_OK (AcpiAttachData, Status);

        Status = AcpiDetachData (Handle, AeAttachedDataHandler);
        AE_CHECK_OK (AcpiDetachData, Status);

        /* Test attach data at the root object */

        Status = AcpiAttachData (ACPI_ROOT_OBJECT, AeAttachedDataHandler,
            AcpiGbl_RootNode);
        AE_CHECK_OK (AcpiAttachData, Status);

        Status = AcpiAttachData (ACPI_ROOT_OBJECT, AeAttachedDataHandler2,
            AcpiGbl_RootNode);
        AE_CHECK_OK (AcpiAttachData, Status);

        /* Test support for multiple attaches */

        Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle);
        AE_CHECK_OK (AcpiAttachData, Status);

        Status = AcpiAttachData (Handle, AeAttachedDataHandler2, Handle);
        AE_CHECK_OK (AcpiAttachData, Status);
    }
    else
    {
Ejemplo n.º 30
0
static int
acpi_tz_attach(device_t dev)
{
    struct acpi_tz_softc	*sc;
    struct acpi_softc		*acpi_sc;
    int				error;
    char			oidname[8];

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

    sc = device_get_softc(dev);
    sc->tz_dev = dev;
    sc->tz_handle = acpi_get_handle(dev);
    sc->tz_requested = TZ_ACTIVE_NONE;
    sc->tz_active = TZ_ACTIVE_UNKNOWN;
    sc->tz_thflags = TZ_THFLAG_NONE;
    sc->tz_cooling_proc = NULL;
    sc->tz_cooling_proc_running = FALSE;
    sc->tz_cooling_active = FALSE;
    sc->tz_cooling_updated = FALSE;
    sc->tz_cooling_enabled = FALSE;

    /*
     * Parse the current state of the thermal zone and build control
     * structures.  We don't need to worry about interference with the
     * control thread since we haven't fully attached this device yet.
     */
    if ((error = acpi_tz_establish(sc)) != 0)
	return (error);

    /*
     * Register for any Notify events sent to this zone.
     */
    AcpiInstallNotifyHandler(sc->tz_handle, ACPI_DEVICE_NOTIFY,
			     acpi_tz_notify_handler, sc);

    /*
     * Create our sysctl nodes.
     *
     * XXX we need a mechanism for adding nodes under ACPI.
     */
    if (device_get_unit(dev) == 0) {
	acpi_sc = acpi_device_get_parent_softc(dev);
	sysctl_ctx_init(&acpi_tz_sysctl_ctx);
	acpi_tz_sysctl_tree = SYSCTL_ADD_NODE(&acpi_tz_sysctl_ctx,
			      SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
			      OID_AUTO, "thermal", CTLFLAG_RD, 0, "");
	SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
		       SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
		       OID_AUTO, "min_runtime", CTLFLAG_RW,
		       &acpi_tz_min_runtime, 0,
		       "minimum cooling run time in sec");
	SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
		       SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
		       OID_AUTO, "polling_rate", CTLFLAG_RW,
		       &acpi_tz_polling_rate, 0, "monitor polling interval in seconds");
	SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
		       SYSCTL_CHILDREN(acpi_tz_sysctl_tree), OID_AUTO,
		       "user_override", CTLFLAG_RW, &acpi_tz_override, 0,
		       "allow override of thermal settings");
    }
    sysctl_ctx_init(&sc->tz_sysctl_ctx);
    sprintf(oidname, "tz%d", device_get_unit(dev));
    sc->tz_sysctl_tree = SYSCTL_ADD_NODE_WITH_LABEL(&sc->tz_sysctl_ctx,
			 SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
			 OID_AUTO, oidname, CTLFLAG_RD, 0, "", "thermal_zone");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD,
		    &sc->tz_temperature, 0, sysctl_handle_int,
		    "IK", "current thermal zone temperature");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "active", CTLTYPE_INT | CTLFLAG_RW,
		    sc, 0, acpi_tz_active_sysctl, "I", "cooling is active");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "passive_cooling", CTLTYPE_INT | CTLFLAG_RW,
		    sc, 0, acpi_tz_cooling_sysctl, "I",
		    "enable passive (speed reduction) cooling");

    SYSCTL_ADD_INT(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		   OID_AUTO, "thermal_flags", CTLFLAG_RD,
		   &sc->tz_thflags, 0, "thermal zone flags");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_PSV", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.psv),
		    acpi_tz_temp_sysctl, "IK", "passive cooling temp setpoint");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_HOT", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.hot),
		    acpi_tz_temp_sysctl, "IK",
		    "too hot temp setpoint (suspend now)");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_CRT", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.crt),
		    acpi_tz_temp_sysctl, "IK",
		    "critical temp setpoint (shutdown now)");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_ACx", CTLTYPE_INT | CTLFLAG_RD,
		    &sc->tz_zone.ac, sizeof(sc->tz_zone.ac),
		    sysctl_handle_opaque, "IK", "");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_TC1", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.tc1),
		    acpi_tz_passive_sysctl, "I",
		    "thermal constant 1 for passive cooling");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_TC2", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.tc2),
		    acpi_tz_passive_sysctl, "I",
		    "thermal constant 2 for passive cooling");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_TSP", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.tsp),
		    acpi_tz_passive_sysctl, "I",
		    "thermal sampling period for passive cooling");

    /*
     * Register our power profile event handler.
     */
    sc->tz_event = EVENTHANDLER_REGISTER(power_profile_change,
	acpi_tz_power_profile, sc, 0);

    /*
     * Flag the event handler for a manual invocation by our timeout.
     * We defer it like this so that the rest of the subsystem has time
     * to come up.  Don't bother evaluating/printing the temperature at
     * this point; on many systems it'll be bogus until the EC is running.
     */
    sc->tz_flags |= TZ_FLAG_GETPROFILE;

    return_VALUE (0);
}