Ejemplo n.º 1
0
void
acpitz_get_status(void *opaque)
{
	struct acpitz_softc *sc = opaque;
	ACPI_STATUS rv;
	ACPI_INTEGER v;

	rv = acpi_eval_integer(sc->sc_devnode->ad_handle, "_TMP", &v);
	if (ACPI_FAILURE(rv)) {
		printf("%s: failed to evaluate _TMP: %s\n",
		    sc->sc_dev.dv_xname, AcpiFormatException(rv));
		return;
	}
	sc->sc_zone.tmp = v;

	/*
	 * The temperature unit for envsys(9) is microKelvin, so convert to
	 * that from ACPI's microKelvin. Also, the ACPI specification assumes
	 * that K = C + 273.2 rather than the nominal 273.15 used by envsys(9),
	 * so we correct for that too.
	 */
	sc->sc_data[ATZ_SENSOR_TEMP].cur.data_us =
	    sc->sc_zone.tmp * 100000 - 50000;
	sc->sc_data[ATZ_SENSOR_TEMP].validflags |= ENVSYS_FCURVALID;

	if (sc->sc_flags & ATZ_F_VERBOSE)
		acpitz_print_status(sc);

	return;
}
Ejemplo n.º 2
0
static int
asus_sysctl_verify(SYSCTLFN_ARGS)
{
	struct sysctlnode node;
	struct asus_softc *sc;
	ACPI_INTEGER cfv;
	ACPI_STATUS rv;
	int err, tmp;

	node = *rnode;
	sc = rnode->sysctl_data;
	if (node.sysctl_num == sc->sc_cfv_mib) {
		rv = acpi_eval_integer(sc->sc_node->ad_handle,
		    ASUS_METHOD_CFVG, &cfv);
		if (ACPI_FAILURE(rv))
			return ENXIO;
		tmp = cfv & 0xff;
		node.sysctl_data = &tmp;
		err = sysctl_lookup(SYSCTLFN_CALL(&node));
		if (err || newp == NULL)
			return err;

		if (tmp < 0 || (uint64_t)tmp >= sc->sc_cfvnum)
			return EINVAL;

		rv = acpi_eval_set_integer(sc->sc_node->ad_handle,
		    ASUS_METHOD_CFVS, tmp);

		if (ACPI_FAILURE(rv))
			return ENXIO;
	}

	return 0;
}
Ejemplo n.º 3
0
static bool
sony_acpi_suspend(device_t dv PMF_FN_ARGS)
{
	struct sony_acpi_softc *sc = device_private(dv);

	acpi_eval_integer(sc->sc_node->ad_handle, "GBRT", &sc->sc_pmstate.brt);

	return true;
}
Ejemplo n.º 4
0
static bool
asus_get_fan_speed(struct asus_softc *sc, uint32_t *speed)
{
	ACPI_INTEGER rpmh, rpml;
	ACPI_STATUS rv;

	rv = acpi_eval_integer(sc->sc_node->ad_handle,
	    ASUS_EC_METHOD_FAN_RPMH, &rpmh);
	if (ACPI_FAILURE(rv))
		return false;
	rv = acpi_eval_integer(sc->sc_node->ad_handle,
	    ASUS_EC_METHOD_FAN_RPML, &rpml);
	if (ACPI_FAILURE(rv))
		return false;

	if (speed)
		*speed = (rpmh << 8) | rpml;
	return true;
}
static int
acpitz_get_fanspeed(device_t dv,
                    uint32_t *fanmin, uint32_t *fanmax, uint32_t *fancurrent)
{
    struct acpitz_softc *sc = device_private(dv);
    ACPI_INTEGER fmin, fmax, fcurr;
    ACPI_HANDLE handle;
    ACPI_STATUS rv;
    int rc = 0;

    handle = sc->sc_node->ad_handle;

    rv = acpi_eval_integer(handle, "FMIN", &fmin);

    if (ACPI_FAILURE(rv)) {
        fmin = ATZ_TMP_INVALID;
        rc = 1;
    }

    rv = acpi_eval_integer(handle, "FMAX", &fmax);

    if (ACPI_FAILURE(rv)) {
        fmax = ATZ_TMP_INVALID;
        rc = 1;
    }
    rv = acpi_eval_integer(handle, "FRSP", &fcurr);

    if (ACPI_FAILURE(rv)) {
        fcurr = ATZ_TMP_INVALID;
        rc = 1;
    }

    if (fanmin != NULL)
        *fanmin = fmin;

    if (fanmax != NULL)
        *fanmax = fmax;

    if (fancurrent != NULL)
        *fancurrent = fcurr;

    return rc;
}
/*
 * acpitz_attach: autoconf(9) attach routine
 */
static void
acpitz_attach(device_t parent, device_t self, void *aux)
{
    struct acpitz_softc *sc = device_private(self);
    struct acpi_attach_args *aa = aux;
    ACPI_INTEGER val;
    ACPI_STATUS rv;

    sc->sc_first = true;
    sc->sc_have_fan = false;
    sc->sc_node = aa->aa_node;
    sc->sc_zone.tzp = ATZ_TZP_RATE;

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

    /*
     * The _TZP (ACPI 4.0, p. 430) defines the recommended
     * polling interval (in tenths of seconds). A value zero
     * means that polling "should not be necessary".
     */
    rv = acpi_eval_integer(sc->sc_node->ad_handle, "_TZP", &val);

    if (ACPI_SUCCESS(rv) && val != 0)
        sc->sc_zone.tzp = val;

    aprint_debug_dev(self, "polling interval %d.%d seconds\n",
                     sc->sc_zone.tzp / 10, sc->sc_zone.tzp % 10);

    sc->sc_zone_expire = ATZ_ZONE_EXPIRE / sc->sc_zone.tzp;

    /*
     * XXX: The fan controls seen here are available on
     *	some HP laptops. Arguably these should not
     *	appear in a generic device driver like this.
     */
    if (acpitz_get_fanspeed(self, &sc->sc_zone.fanmin,
                            &sc->sc_zone.fanmax, &sc->sc_zone.fancurrent) == 0)
        sc->sc_have_fan = true;

    acpitz_get_zone(self, 1);
    acpitz_get_status(self);

    (void)pmf_device_register(self, NULL, NULL);
    (void)acpi_power_register(sc->sc_node->ad_handle);
    (void)acpi_register_notify(sc->sc_node, acpitz_notify_handler);

    callout_init(&sc->sc_callout, CALLOUT_MPSAFE);
    callout_setfunc(&sc->sc_callout, acpitz_tick, self);

    acpitz_init_envsys(self);

    callout_schedule(&sc->sc_callout, sc->sc_zone.tzp * hz / 10);
}
Ejemplo n.º 7
0
static ACPI_STATUS
sony_walk_cb(ACPI_HANDLE hnd, UINT32 v, void *context, void **status)
{
	struct sony_acpi_softc *sc = (void *)context;
	const struct sysctlnode *node, *snode;
	const char *name = acpi_name(hnd);
	ACPI_INTEGER acpi_val;
	char buf[SYSCTL_NAMELEN + 1], *ptr;
	int rv;

	if ((name = strrchr(name, '.')) == NULL)
		return AE_OK;

	name++;
	if ((*name != 'G') && (*name != 'S'))
		return AE_OK;

	(void)strlcpy(buf, name, sizeof(buf));
	*buf = 'G';

	/*
	 * We assume that if the 'get' of the name as an integer is
	 * successful it is ok.
	 */
	if (acpi_eval_integer(sc->sc_node->ad_handle, buf, &acpi_val))
		return AE_OK;

	for (ptr = buf; *ptr; ptr++)
		*ptr = tolower(*ptr);

	if ((rv = sysctl_createv(&sc->sc_log, 0, NULL, &node, CTLFLAG_PERMANENT,
	    CTLTYPE_NODE, "hw", NULL, NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0)
		goto out;

	if ((rv = sysctl_createv(&sc->sc_log, 0, &node, &snode, 0,
	    CTLTYPE_NODE, device_xname(sc->sc_dev),
	    SYSCTL_DESCR("sony controls"),
	    NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
		goto out;

	if ((rv = sysctl_createv(&sc->sc_log, 0, &snode, &node,
	    CTLFLAG_READWRITE, CTLTYPE_INT, buf + 1, NULL,
	    sony_sysctl_helper, 0, sc, 0, CTL_CREATE, CTL_EOL)) != 0)
		goto out;

out:
#ifdef DIAGNOSTIC
	if (rv)
		printf("%s: sysctl_createv failed (rv = %d)\n",
		    device_xname(sc->sc_dev), rv);
#endif
	return AE_OK;
}
Ejemplo n.º 8
0
static bool
asus_suspend(device_t self PMF_FN_ARGS)
{
	asus_softc_t *sc = device_private(self);
	ACPI_STATUS rv;

	/* capture display brightness when we're sleeping */
	rv = acpi_eval_integer(sc->sc_node->ad_handle, ASUS_METHOD_PBLG,
	    &sc->sc_brightness);
	if (ACPI_FAILURE(rv))
		aprint_error_dev(sc->sc_dev, "couldn't evaluate PBLG: %s\n",
		    AcpiFormatException(rv));

	return true;
}
Ejemplo n.º 9
0
static void
sony_acpi_brightness_down(device_t dv)
{
	struct sony_acpi_softc *sc = device_private(dv);
	ACPI_INTEGER arg;
	ACPI_STATUS rv;

	rv = acpi_eval_integer(sc->sc_node->ad_handle, "GBRT", &arg);
	if (ACPI_FAILURE(rv))
		return;
	if (arg <= 0)
		arg = 0;
	else
		arg--;
	sony_acpi_eval_set_integer(sc->sc_node->ad_handle, "SBRT", arg, NULL);
}
Ejemplo n.º 10
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.º 11
0
static bool
asus_suspend(device_t self, const pmf_qual_t *qual)
{
	struct asus_softc *sc = device_private(self);
	ACPI_INTEGER val = 0;
	ACPI_STATUS rv;

	/* Capture display brightness. */
	rv = acpi_eval_integer(sc->sc_node->ad_handle, ASUS_METHOD_PBLG, &val);

	if (ACPI_FAILURE(rv) || val > INT32_MAX)
		sc->sc_brightness = -1;
	else
		sc->sc_brightness = val;

	return true;
}
Ejemplo n.º 12
0
/*
 * acpilid_status_changed:
 *
 *	Get, and possibly display, the lid status, and take action.
 */
void
acpilid_status_changed(void *arg)
{
	struct acpilid_softc *sc = arg;
	int status;

	if (acpi_eval_integer(sc->sc_node->ad_handle, "_LID",
	    &status) != AE_OK)
		return;

	if (sc->sc_flags & ACPILID_F_VERBOSE)
		printf("%s: Lid %s\n",
		    sc->sc_dev.dv_xname,
		    status == 0 ? "closed " : "open");

	/*
	 * XXX Perform the appropriate action for the new lid status.
	 */
}
Ejemplo n.º 13
0
static int
sony_sysctl_helper(SYSCTLFN_ARGS)
{
	struct sysctlnode node;
	ACPI_INTEGER acpi_val;
	ACPI_STATUS rv;
	int val, old_val, error;
	char buf[SYSCTL_NAMELEN + 1], *ptr;
	struct sony_acpi_softc *sc = rnode->sysctl_data;

	(void)snprintf(buf, sizeof(buf), "G%s", rnode->sysctl_name);
	for (ptr = buf; *ptr; ptr++)
		*ptr = toupper(*ptr);

	rv = acpi_eval_integer(sc->sc_node->ad_handle, buf, &acpi_val);
	if (ACPI_FAILURE(rv)) {
#ifdef DIAGNOSTIC
		printf("%s: couldn't get `%s'\n", device_xname(sc->sc_dev), buf);
#endif
		return EIO;
	}
	val = old_val = acpi_val;

	node = *rnode;
	node.sysctl_data = &val;

	error = sysctl_lookup(SYSCTLFN_CALL(&node));
	if (error || newp == NULL)
		return error;

	(void)snprintf(buf, sizeof(buf), "S%s", rnode->sysctl_name);
	acpi_val = val;
	rv = sony_acpi_eval_set_integer(sc->sc_node->ad_handle, buf,
	    acpi_val, NULL);
	if (ACPI_FAILURE(rv)) {
#ifdef DIAGNOSTIC
		printf("%s: couldn't set `%s' to %d\n",
		    device_xname(sc->sc_dev), buf, val);
#endif
		return EIO;
	}
	return 0;
}
Ejemplo n.º 14
0
static void
asus_init(device_t self)
{
	struct asus_softc *sc = device_private(self);
	ACPI_INTEGER cfv;
	ACPI_STATUS rv;

	/* Disable ASL display switching. */
	rv = acpi_eval_set_integer(sc->sc_node->ad_handle, "INIT", 0x40);

	if (ACPI_FAILURE(rv))
		aprint_error_dev(self, "couldn't evaluate INIT: %s\n",
		    AcpiFormatException(rv));

	rv = acpi_eval_integer(sc->sc_node->ad_handle, ASUS_METHOD_CFVG, &cfv);

	if (ACPI_FAILURE(rv))
		return;

	sc->sc_cfvnum = (cfv >> 8) & 0xff;
}
Ejemplo n.º 15
0
static int
fujitsu_hk_get_irb(struct fujitsu_hk_softc *sc, uint32_t *valuep)
{
    ACPI_HANDLE hdl = sc->sc_node->ad_handle;
    ACPI_INTEGER val;
    ACPI_STATUS rv;

    if (!(sc->sc_caps & FUJITSU_HK_CAP_GIRB))
        return ENODEV;

    rv = acpi_eval_integer(hdl, "GIRB", &val);
    if (ACPI_FAILURE(rv)) {
        aprint_error_dev(sc->sc_dev, "failed to evaluate %s.%s: %s\n",
                         acpi_name(hdl), "GIRB", AcpiFormatException(rv));
        return EIO;
    }

    *valuep = (uint32_t)val;

    return 0;
}
Ejemplo n.º 16
0
static int
thinkpad_match(device_t parent, struct cfdata *match, void *opaque)
{
	struct acpi_attach_args *aa = (struct acpi_attach_args *)opaque;
	ACPI_INTEGER ver;

	if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
		return 0;

	if (!acpi_match_hid(aa->aa_node->ad_devinfo, thinkpad_ids))
		return 0;

	/* We only support hotkey version 0x0100 */
	if (ACPI_FAILURE(acpi_eval_integer(aa->aa_node->ad_handle, "MHKV",
	    &ver)))
		return 0;

	if (ver != THINKPAD_HKEY_VERSION)
		return 0;

	/* Cool, looks like we're good to go */
	return 1;
}
static int
acpitz_get_integer(device_t dv, const char *cm, uint32_t *val)
{
    struct acpitz_softc *sc = device_private(dv);
    ACPI_INTEGER tmp;
    ACPI_STATUS rv;

    rv = acpi_eval_integer(sc->sc_node->ad_handle, cm, &tmp);

    if (ACPI_FAILURE(rv)) {
        *val = ATZ_TMP_INVALID;

        ACPI_DEBUG_PRINT((ACPI_DB_DEBUG_OBJECT,
                          "%s: failed to evaluate %s: %s\n",
                          device_xname(dv), cm, AcpiFormatException(rv)));

        return 1;
    }

    *val = tmp;

    return 0;
}
Ejemplo n.º 18
0
static void
thinkpad_temp_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
{
	thinkpad_softc_t *sc = sme->sme_cookie;
	char sname[5] = "TMP?";
	ACPI_INTEGER val;
	ACPI_STATUS rv;
	int temp;

	sname[3] = '0' + edata->sensor;
	rv = acpi_eval_integer(acpiec_get_handle(sc->sc_ecdev), sname, &val);
	if (ACPI_FAILURE(rv)) {
		edata->state = ENVSYS_SINVALID;
		return;
	}
	temp = (int)val;
	if (temp > 127 || temp < -127) {
		edata->state = ENVSYS_SINVALID;
		return;
	}

	edata->value_cur = temp * 1000000 + 273150000;
	edata->state = ENVSYS_SVALID;
}
Ejemplo n.º 19
0
static void
thinkpad_get_hotkeys(void *opaque)
{
	thinkpad_softc_t *sc = (thinkpad_softc_t *)opaque;
	device_t self = sc->sc_dev;
	ACPI_STATUS rv;
	ACPI_INTEGER val;
	int type, event;
	
	for (;;) {
		rv = acpi_eval_integer(sc->sc_node->ad_handle, "MHKP", &val);
		if (ACPI_FAILURE(rv)) {
			aprint_error_dev(self, "couldn't evaluate MHKP: %s\n",
			    AcpiFormatException(rv));
			return;
		}

		if (val == 0)
			return;

		type = (val & 0xf000) >> 12;
		event = val & 0x0fff;

		if (type != 1)
			/* Only type 1 events are supported for now */
			continue;

		switch (event) {
		case THINKPAD_NOTIFY_BrightnessUp:
			thinkpad_brightness_up(self);
			break;
		case THINKPAD_NOTIFY_BrightnessDown:
			thinkpad_brightness_down(self);
			break;
		case THINKPAD_NOTIFY_WirelessSwitch:
			thinkpad_wireless_toggle(sc);
			break;
		case THINKPAD_NOTIFY_SleepButton:
			if (sc->sc_smpsw_valid == false)
				break;
			sysmon_pswitch_event(&sc->sc_smpsw[TP_PSW_SLEEP],
			    PSWITCH_EVENT_PRESSED);
			break;
		case THINKPAD_NOTIFY_HibernateButton:
#if notyet
			if (sc->sc_smpsw_valid == false)
				break;
			sysmon_pswitch_event(&sc->sc_smpsw[TP_PSW_HIBERNATE],
			    PSWITCH_EVENT_PRESSED);
#endif
			break;
		case THINKPAD_NOTIFY_DisplayCycle:
			if (sc->sc_smpsw_valid == false)
				break;
			sysmon_pswitch_event(
			    &sc->sc_smpsw[TP_PSW_DISPLAY_CYCLE],
			    PSWITCH_EVENT_PRESSED);
			break;
		case THINKPAD_NOTIFY_LockScreen:
			if (sc->sc_smpsw_valid == false)
				break;
			sysmon_pswitch_event(
			    &sc->sc_smpsw[TP_PSW_LOCK_SCREEN],
			    PSWITCH_EVENT_PRESSED);
			break;
		case THINKPAD_NOTIFY_BatteryInfo:
			if (sc->sc_smpsw_valid == false)
				break;
			sysmon_pswitch_event(
			    &sc->sc_smpsw[TP_PSW_BATTERY_INFO],
			    PSWITCH_EVENT_PRESSED);
			break;
		case THINKPAD_NOTIFY_EjectButton:
			if (sc->sc_smpsw_valid == false)
				break;
			sysmon_pswitch_event(
			    &sc->sc_smpsw[TP_PSW_EJECT_BUTTON],
			    PSWITCH_EVENT_PRESSED);
			break;
		case THINKPAD_NOTIFY_Zoom:
			if (sc->sc_smpsw_valid == false)
				break;
			sysmon_pswitch_event(
			    &sc->sc_smpsw[TP_PSW_ZOOM_BUTTON],
			    PSWITCH_EVENT_PRESSED);
			break;
		case THINKPAD_NOTIFY_ThinkVantage:
			if (sc->sc_smpsw_valid == false)
				break;
			sysmon_pswitch_event(
			    &sc->sc_smpsw[TP_PSW_VENDOR_BUTTON],
			    PSWITCH_EVENT_PRESSED);
			break;
		case THINKPAD_NOTIFY_FnF1:
		case THINKPAD_NOTIFY_FnF6:
		case THINKPAD_NOTIFY_PointerSwitch:
		case THINKPAD_NOTIFY_FnF10:
		case THINKPAD_NOTIFY_FnF11:
		case THINKPAD_NOTIFY_ThinkLight:
			/* XXXJDM we should deliver hotkeys as keycodes */
			break;
		default:
			aprint_debug_dev(self, "notify event 0x%03x\n", event);
			break;
		}
	}
}
Ejemplo n.º 20
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.º 21
0
/*
 * acpiec_attach:
 *
 *	Autoconfiguration `attach' routine.
 */
void
acpiec_attach(struct device *parent, struct device *self, void *aux)
{
	struct acpi_ec_softc *sc = (void *) self;
	struct acpi_attach_args *aa = aux;
	struct acpi_io *io0, *io1;
	ACPI_STATUS rv;

	FUNCTION_TRACE(__FUNCTION__);

	printf(": ACPI Embedded Controller\n");

	sc->sc_node = aa->aa_node;

	/* Parse our resources. */
	ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "parsing EC resources\n"));
	rv = acpi_resource_parse(&sc->sc_dev, sc->sc_node, &sc->sc_res,
	    &acpi_resource_parse_ops_default);
	if (rv != AE_OK) {
		printf("%s: unable to parse resources: %d\n",
		    sc->sc_dev.dv_xname, rv);
		return;
	}

	sc->sc_data_st = aa->aa_iot;
	io0 = acpi_res_io(&sc->sc_res, 0);
	if (io0 == NULL) {
		printf("%s: unable to find data register resource\n",
		    sc->sc_dev.dv_xname);
		return;
	}
	if (bus_space_map(sc->sc_data_st, io0->ar_base, io0->ar_length,
	    0, &sc->sc_data_sh) != 0) {
		printf("%s: unable to map data register\n",
		    sc->sc_dev.dv_xname);
		return;
	}

	sc->sc_csr_st = aa->aa_iot;
	io1 = acpi_res_io(&sc->sc_res, 1);
	if (io1 == NULL) {
		printf("%s: unable to find csr register resource\n",
		    sc->sc_dev.dv_xname);
		return;
	}
	if (bus_space_map(sc->sc_csr_st, io1->ar_base, io1->ar_length,
	    0, &sc->sc_csr_sh) != 0) {
		printf("%s: unable to map csr register\n",
		    sc->sc_dev.dv_xname);
		return;
	}

	/*
	 * Install GPE handler.
	 *
	 * We evaluate the _GPE method to find the GPE bit used by the
	 * Embedded Controller to signal status (SCI).
	 */
	if ((rv = acpi_eval_integer(sc->sc_node->ad_handle, "_GPE",
	     &sc->sc_gpebit)) != AE_OK) {
		printf("%s: unable to evaluate _GPE: %d\n",
		    sc->sc_dev.dv_xname, rv);
		return;
	}

	/*
	 * 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 ((rv = AcpiInstallGpeHandler(sc->sc_gpebit,
	     ACPI_EVENT_LEVEL_TRIGGERED | ACPI_EVENT_EDGE_TRIGGERED,
	     EcGpeHandler, sc)) != AE_OK) {
		printf("%s: unable to install GPE handler: %d\n",
		    sc->sc_dev.dv_xname, rv);
		return;
	}

	/* Install address space handler. */
	if ((rv = AcpiInstallAddressSpaceHandler(sc->sc_node->ad_handle,
	     ACPI_ADR_SPACE_EC, EcSpaceHandler, EcSpaceSetup, sc)) != AE_OK) {
		printf("%s: unable to install address space handler: %d\n",
		    sc->sc_dev.dv_xname, rv);
		return;
	}

	return_VOID;
}
Ejemplo n.º 22
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;
	deviter_t di;
	ACPI_STATUS rv;
	ACPI_INTEGER val;
	int i;

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

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

	sc->sc_ecdev = NULL;
	for (curdev = deviter_first(&di, DEVITER_F_ROOT_FIRST);
	     curdev != NULL; curdev = deviter_next(&di))
		if (device_is_a(curdev, "acpiecdt") ||
		    device_is_a(curdev, "acpiec")) {
			sc->sc_ecdev = curdev;
			break;
		}
	deviter_release(&di);

	if (sc->sc_ecdev)
		aprint_debug_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;
	}

	(void)acpi_register_notify(sc->sc_node, thinkpad_notify_handler);

	/*
	 * Obtain a handle for CMOS commands. This is used by T61.
	 */
	(void)AcpiGetHandle(NULL, "\\UCMS", &sc->sc_cmoshdl);

	/*
	 * Obtain a handle to the power resource available on many models.
	 * Since pmf(9) is not yet integrated with the ACPI power resource
	 * code, this must be turned on manually upon resume. Otherwise the
	 * system may, for instance, resume from S3 with usb(4) powered down.
	 */
	(void)AcpiGetHandle(NULL, "\\_SB.PCI0.LPC.EC.PUBS", &sc->sc_powhdl);

	/* 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;
#ifndef THINKPAD_NORMAL_HOTKEYS
	psw[TP_PSW_FNF1_BUTTON].smpsw_name     = PSWITCH_HK_FNF1_BUTTON;
	psw[TP_PSW_WIRELESS_BUTTON].smpsw_name = PSWITCH_HK_WIRELESS_BUTTON;
	psw[TP_PSW_WWAN_BUTTON].smpsw_name     = PSWITCH_HK_WWAN_BUTTON;
	psw[TP_PSW_POINTER_BUTTON].smpsw_name  = PSWITCH_HK_POINTER_BUTTON;
	psw[TP_PSW_FNF10_BUTTON].smpsw_name    = PSWITCH_HK_FNF10_BUTTON;
	psw[TP_PSW_FNF11_BUTTON].smpsw_name    = PSWITCH_HK_FNF11_BUTTON;
	psw[TP_PSW_BRIGHTNESS_UP].smpsw_name   = PSWITCH_HK_BRIGHTNESS_UP;
	psw[TP_PSW_BRIGHTNESS_DOWN].smpsw_name = PSWITCH_HK_BRIGHTNESS_DOWN;
	psw[TP_PSW_THINKLIGHT].smpsw_name      = PSWITCH_HK_THINKLIGHT;
	psw[TP_PSW_VOLUME_UP].smpsw_name       = PSWITCH_HK_VOLUME_UP;
	psw[TP_PSW_VOLUME_DOWN].smpsw_name     = PSWITCH_HK_VOLUME_DOWN;
	psw[TP_PSW_VOLUME_MUTE].smpsw_name     = PSWITCH_HK_VOLUME_MUTE;
#endif /* THINKPAD_NORMAL_HOTKEYS */

	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");
}