/*
 * If no AC line devices detected after boot, create an "online" event
 * so that userland code can adjust power settings accordingly.  The default
 * power profile is "performance" so we don't need to repeat that here.
 */
static void
acpi_acad_ac_only(void __unused *arg)
{

    if (devclass_get_count(acpi_acad_devclass) == 0)
	acpi_UserNotify("ACAD", ACPI_ROOT_OBJECT, 1);
}
static void
acpi_acad_get_status(void *context)
{
    struct acpi_acad_softc *sc;
    device_t	dev;
    ACPI_HANDLE	h;
    int		newstatus;

    dev = context;
    sc = device_get_softc(dev);
    h = acpi_get_handle(dev);
    newstatus = -1;
    acpi_GetInteger(h, "_PSR", &newstatus);

    /* If status is valid and has changed, notify the system. */
    ACPI_SERIAL_BEGIN(acad);
    if (newstatus != -1 && sc->status != newstatus) {
	sc->status = newstatus;
	power_profile_set_state(newstatus ? POWER_PROFILE_PERFORMANCE :
	    POWER_PROFILE_ECONOMY);
	ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
	    "%s Line\n", newstatus ? "On" : "Off");
	acpi_UserNotify("ACAD", h, newstatus);
    }
    ACPI_SERIAL_END(acad);
}
示例#3
0
static void
acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
{
    struct acpi_cmbat_softc *sc;
    device_t dev;

    dev = (device_t)context;
    sc = device_get_softc(dev);

    switch (notify) {
    case ACPI_NOTIFY_DEVICE_CHECK:
    case ACPI_BATTERY_BST_CHANGE:
	/*
	 * Clear the last updated time.  The next call to retrieve the
	 * battery status will get the new value for us.
	 */
	timespecclear(&sc->bst_lastupdated);
	break;
    case ACPI_NOTIFY_BUS_CHECK:
    case ACPI_BATTERY_BIF_CHANGE:
	/*
	 * Queue a callback to get the current battery info from thread
	 * context.  It's not safe to block in a notify handler.
	 */
	AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_get_bif_task, dev);
	break;
    }

    acpi_UserNotify("CMBAT", h, notify);
}
示例#4
0
static void
acpi_tz_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
{
    struct acpi_tz_softc	*sc = (struct acpi_tz_softc *)context;

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

    switch (notify) {
    case TZ_NOTIFY_TEMPERATURE:
	/* Temperature change occurred */
	acpi_tz_signal(sc, 0);
	break;
    case TZ_NOTIFY_DEVICES:
    case TZ_NOTIFY_LEVELS:
	/* Zone devices/setpoints changed */
	acpi_tz_signal(sc, TZ_FLAG_GETSETTINGS);
	break;
    default:
	ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
		    "unknown Notify event 0x%x\n", notify);
	break;
    }

    acpi_UserNotify("Thermal", h, notify);

    return_VOID;
}
示例#5
0
static void
acpi_button_notify_wakeup(void *arg)
{
    struct acpi_button_softc	*sc;
    struct acpi_softc		*acpi_sc;

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

    sc = (struct acpi_button_softc *)arg;
    acpi_sc = acpi_device_get_parent_softc(sc->button_dev);
    if (acpi_sc == NULL)
	return_VOID;

    acpi_UserNotify("Button", sc->button_handle, sc->button_type);

    switch (sc->button_type) {
    case ACPI_POWER_BUTTON:
	ACPI_VPRINT(sc->button_dev, acpi_sc, "wakeup by power button\n");
	acpi_event_power_button_wake(acpi_sc);
	break;
    case ACPI_SLEEP_BUTTON:
	ACPI_VPRINT(sc->button_dev, acpi_sc, "wakeup by sleep button\n");
	acpi_event_sleep_button_wake(acpi_sc);
	break;
    default:
	break;		/* unknown button type */
    }
}
示例#6
0
static void
acpi_panasonic_notify(ACPI_HANDLE h, UINT32 notify, void *context)
{
	struct acpi_panasonic_softc *sc;
	UINT32 key = 0;

	sc = (struct acpi_panasonic_softc *)context;

	switch (notify) {
	case 0x80:
		ACPI_SERIAL_BEGIN(panasonic);
		if (acpi_panasonic_hkey_event(sc, h, &key) == 0) {
			acpi_panasonic_hkey_action(sc, h, key);
			acpi_UserNotify("Panasonic", h, (uint8_t)key);
		}
		ACPI_SERIAL_END(panasonic);
		break;
	default:
		device_printf(sc->dev, "unknown notify: %#x\n", notify);
		break;
	}
}
示例#7
0
static void
acpi_lid_notify_status_changed(void *arg)
{
    struct acpi_lid_softc	*sc;
    struct acpi_softc		*acpi_sc;
    ACPI_STATUS			status;

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

    sc = (struct acpi_lid_softc *)arg;
    ACPI_SERIAL_BEGIN(lid);

    /*
     * Evaluate _LID and check the return value, update lid status.
     *	Zero:		The lid is closed
     *	Non-zero:	The lid is open
     */
    status = acpi_GetInteger(sc->lid_handle, "_LID", &sc->lid_status);
    if (ACPI_FAILURE(status))
        goto out;

    acpi_sc = acpi_device_get_parent_softc(sc->lid_dev);
    if (acpi_sc == NULL)
        goto out;

    ACPI_VPRINT(sc->lid_dev, acpi_sc, "Lid %s\n",
                sc->lid_status ? "opened" : "closed");

    acpi_UserNotify("Lid", sc->lid_handle, sc->lid_status);

    if (sc->lid_status == 0)
        EVENTHANDLER_INVOKE(acpi_sleep_event, acpi_sc->acpi_lid_switch_sx);
    else
        EVENTHANDLER_INVOKE(acpi_wakeup_event, acpi_sc->acpi_lid_switch_sx);

out:
    ACPI_SERIAL_END(lid);
    return_VOID;
}
示例#8
0
/*
 * Query each of the ACPI control methods that contain information we're
 * interested in. We check the return values from the control methods and
 * adjust any state variables if they should be adjusted.
 */
static uint8_t
acpi_fujitsu_update(struct acpi_fujitsu_softc *sc)
{
	int changed;
	struct acpi_softc *acpi_sc;

	acpi_sc = acpi_device_get_parent_softc(sc->dev);

	ACPI_SERIAL_ASSERT(fujitsu);
	if(sc->gsif.exists)
		changed = sc->gsif.value & acpi_fujitsu_method_get(sc,METHOD_GHKS);
	else
		changed = 0;

	/* System Volume Level */
	if(sc->gvol.exists) {
		if (ACPI_FAILURE(acpi_GetInteger(sc->handle,
		sc->gvol.name, &(sc->gvol.value)))) {
			device_printf(sc->dev, "Couldn't query volume level\n");
			return (FALSE);
		}
	
		if (changed & VOLUME_CHANGED) {
			sc->bIsMuted =
			(uint8_t)((sc->gvol.value & VOLUME_MUTE_BIT) != 0);
	
			/* Clear the modification bit */
			sc->gvol.value &= VOLUME_SETTING_BITS;
	
			if (sc->bIsMuted) {
				acpi_UserNotify("FUJITSU", sc->handle, FN_MUTE);
				ACPI_VPRINT(sc->dev, acpi_sc, "Volume is now mute\n");
			} else
				ACPI_VPRINT(sc->dev, acpi_sc, "Volume is now %d\n",
				sc->gvol.value);
	
			acpi_UserNotify("FUJITSU", sc->handle, FN_VOLUME);
		}
	}

	/* Internal mouse pointer (eraserhead) */
	if(sc->gmou.exists) {
		if (ACPI_FAILURE(acpi_GetInteger(sc->handle,
		sc->gmou.name, &(sc->gmou.value)))) {
			device_printf(sc->dev, "Couldn't query pointer state\n");
			return (FALSE);
		}
	
		if (changed & MOUSE_CHANGED) {
			sc->bIntPtrEnabled = (uint8_t)(sc->gmou.value & 0x1);
	
			/* Clear the modification bit */
			sc->gmou.value &= MOUSE_SETTING_BITS;
			
			/* Set the value in case it is not hardware controlled */
                        acpi_fujitsu_method_set(sc, METHOD_GMOU, sc->gmou.value);

			acpi_UserNotify("FUJITSU", sc->handle, FN_POINTER_ENABLE);
	
			ACPI_VPRINT(sc->dev, acpi_sc, "Internal pointer is now %s\n",
			(sc->bIntPtrEnabled) ? "enabled" : "disabled");
		}
	}

	/* Screen Brightness Level P8XXX */
	if(sc->gbls.exists) {
		if (ACPI_FAILURE(acpi_GetInteger(sc->handle,
                sc->gbls.name, &(sc->gbls.value)))) {
                        device_printf(sc->dev, "Couldn't query P8XXX brightness level\n");
                        return (FALSE);
                }
		if (changed & BRIGHT_CHANGED) {
			/* No state to record here. */

			/* Clear the modification bit */
			sc->gbls.value &= BRIGHTNESS_SETTING_BITS;

			/* Set the value in case it is not hardware controlled */
			acpi_fujitsu_method_set(sc, METHOD_GBLS, sc->gbls.value);

			acpi_UserNotify("FUJITSU", sc->handle, FN_LCD_BRIGHTNESS);

			ACPI_VPRINT(sc->dev, acpi_sc, "P8XXX Brightness level is now %d\n",
			sc->gbls.value);
                }
	}

	/* Screen Brightness Level */
	if(sc->gbll.exists) {
		if (ACPI_FAILURE(acpi_GetInteger(sc->handle,
		sc->gbll.name, &(sc->gbll.value)))) {
			device_printf(sc->dev, "Couldn't query brightness level\n");
			return (FALSE);
		}
	
		if (changed & BRIGHT_CHANGED) {
			/* No state to record here. */
	
			/* Clear the modification bit */
			sc->gbll.value &= BRIGHTNESS_SETTING_BITS;
	
			acpi_UserNotify("FUJITSU", sc->handle, FN_LCD_BRIGHTNESS);
	
			ACPI_VPRINT(sc->dev, acpi_sc, "Brightness level is now %d\n",
			sc->gbll.value);
		}
	}

	sc->lastValChanged = changed;
	return (TRUE);
}
示例#9
0
/*
 * Evaluate the condition of a thermal zone, take appropriate actions.
 */
static void
acpi_tz_monitor(void *Context)
{
    struct acpi_tz_softc *sc;
    struct	timespec curtime;
    int		temp;
    int		i;
    int		newactive, newflags;

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

    sc = (struct acpi_tz_softc *)Context;

    /* Get the current temperature. */
    if (!acpi_tz_get_temperature(sc)) {
	/* XXX disable zone? go to max cooling? */
	return_VOID;
    }
    temp = sc->tz_temperature;

    /*
     * Work out what we ought to be doing right now.
     *
     * Note that the _ACx levels sort from hot to cold.
     */
    newactive = TZ_ACTIVE_NONE;
    for (i = TZ_NUMLEVELS - 1; i >= 0; i--) {
	if (sc->tz_zone.ac[i] != -1 && temp >= sc->tz_zone.ac[i])
	    newactive = i;
    }

    /*
     * We are going to get _ACx level down (colder side), but give a guaranteed
     * minimum cooling run time if requested.
     */
    if (acpi_tz_min_runtime > 0 && sc->tz_active != TZ_ACTIVE_NONE &&
	sc->tz_active != TZ_ACTIVE_UNKNOWN &&
	(newactive == TZ_ACTIVE_NONE || newactive > sc->tz_active)) {

	getnanotime(&curtime);
	timespecsub(&curtime, &sc->tz_cooling_started);
	if (curtime.tv_sec < acpi_tz_min_runtime)
	    newactive = sc->tz_active;
    }

    /* Handle user override of active mode */
    if (sc->tz_requested != TZ_ACTIVE_NONE && (newactive == TZ_ACTIVE_NONE
        || sc->tz_requested < newactive))
	newactive = sc->tz_requested;

    /* update temperature-related flags */
    newflags = TZ_THFLAG_NONE;
    if (sc->tz_zone.psv != -1 && temp >= sc->tz_zone.psv)
	newflags |= TZ_THFLAG_PSV;
    if (sc->tz_zone.hot != -1 && temp >= sc->tz_zone.hot)
	newflags |= TZ_THFLAG_HOT;
    if (sc->tz_zone.crt != -1 && temp >= sc->tz_zone.crt)
	newflags |= TZ_THFLAG_CRT;

    /* If the active cooling state has changed, we have to switch things. */
    if (sc->tz_active == TZ_ACTIVE_UNKNOWN) {
	/*
	 * We don't know which cooling device is on or off,
	 * so stop them all, because we now know which
	 * should be on (if any).
	 */
	for (i = 0; i < TZ_NUMLEVELS; i++) {
	    if (sc->tz_zone.al[i].Pointer != NULL) {
		acpi_ForeachPackageObject(
		    (ACPI_OBJECT *)sc->tz_zone.al[i].Pointer,
		    acpi_tz_switch_cooler_off, sc);
	    }
	}
	/* now we know that all devices are off */
	sc->tz_active = TZ_ACTIVE_NONE;
    }

    if (newactive != sc->tz_active) {
	/* Turn off unneeded cooling devices that are on, if any are */
	for (i = TZ_ACTIVE_LEVEL(sc->tz_active);
	     i < TZ_ACTIVE_LEVEL(newactive); i++) {
	    acpi_ForeachPackageObject(
		(ACPI_OBJECT *)sc->tz_zone.al[i].Pointer,
		acpi_tz_switch_cooler_off, sc);
	}
	/* Turn on cooling devices that are required, if any are */
	for (i = TZ_ACTIVE_LEVEL(sc->tz_active) - 1;
	     i >= TZ_ACTIVE_LEVEL(newactive); i--) {
	    acpi_ForeachPackageObject(
		(ACPI_OBJECT *)sc->tz_zone.al[i].Pointer,
		acpi_tz_switch_cooler_on, sc);
	}

	ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
		    "switched from %s to %s: %d.%dC\n",
		    acpi_tz_aclevel_string(sc->tz_active),
		    acpi_tz_aclevel_string(newactive), TZ_KELVTOC(temp));
	sc->tz_active = newactive;
	getnanotime(&sc->tz_cooling_started);
    }

    /* XXX (de)activate any passive cooling that may be required. */

    /*
     * If the temperature is at _HOT or _CRT, increment our event count.
     * If it has occurred enough times, shutdown the system.  This is
     * needed because some systems will report an invalid high temperature
     * for one poll cycle.  It is suspected this is due to the embedded
     * controller timing out.  A typical value is 138C for one cycle on
     * a system that is otherwise 65C.
     *
     * If we're almost at that threshold, notify the user through devd(8).
     */
    if ((newflags & (TZ_THFLAG_HOT | TZ_THFLAG_CRT)) != 0) {
	sc->tz_validchecks++;
	if (sc->tz_validchecks == TZ_VALIDCHECKS) {
	    device_printf(sc->tz_dev,
		"WARNING - current temperature (%d.%dC) exceeds safe limits\n",
		TZ_KELVTOC(sc->tz_temperature));
	    shutdown_nice(RB_POWEROFF);
	} else if (sc->tz_validchecks == TZ_NOTIFYCOUNT)
	    acpi_UserNotify("Thermal", sc->tz_handle, TZ_NOTIFY_CRITICAL);
    } else {
	sc->tz_validchecks = 0;
    }
    sc->tz_thflags = newflags;

    return_VOID;
}