Example #1
0
/*
 * Query the get methods to determine what functionality is available
 * from the hardware function hotkeys.
 */
static uint8_t
acpi_fujitsu_check_hardware(struct acpi_fujitsu_softc *sc)
{
	int val;

	ACPI_SERIAL_ASSERT(fujitsu);
	/* save the hotkey bitmask */
	if (ACPI_FAILURE(acpi_GetInteger(sc->handle,
	sc->gsif.name, &(sc->gsif.value)))) {
		sc->gsif.exists = 0;
		device_printf(sc->dev, "Couldn't query bitmask value\n");
	} else {
		sc->gsif.exists = 1;
	}

	/* System Volume Level */
	if (ACPI_FAILURE(acpi_GetInteger(sc->handle,
	    sc->gvol.name, &val))) {
		sc->gvol.exists = 0;
	} else {
		sc->gvol.exists = 1;
	}

	if (ACPI_FAILURE(acpi_GetInteger(sc->handle,
		sc->gbls.name, &val))) {
		sc->gbls.exists = 0;
	} else {
		sc->gbls.exists = 1;
	}

	// don't add if we can use the new method
	if (sc->gbls.exists || ACPI_FAILURE(acpi_GetInteger(sc->handle,
	    sc->gbll.name, &val))) {
		sc->gbll.exists = 0;
	} else {
		sc->gbll.exists = 1;
	}

	if (ACPI_FAILURE(acpi_GetInteger(sc->handle,
	    sc->ghks.name, &val))) {
		sc->ghks.exists = 0;
	} else {
		sc->ghks.exists = 1;
	}

	if (ACPI_FAILURE(acpi_GetInteger(sc->handle,
	    sc->gmou.name, &val))) {
		sc->gmou.exists = 0;
	} else {
		sc->gmou.exists = 1;
	}

	if (ACPI_FAILURE(acpi_GetInteger(sc->handle,
	    sc->rbll.name, &val))) {
		sc->rbll.exists = 0;
	} else {
		sc->rbll.exists = 1;
	}

	if (ACPI_FAILURE(acpi_GetInteger(sc->handle,
	    sc->rvol.name, &val))) {
		sc->rvol.exists = 0;
	} else {
		sc->rvol.exists = 1;
	}

	return (TRUE);
}
Example #2
0
static ACPI_STATUS
EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event, u_int gen_count)
{
    static int	no_intr = 0;
    ACPI_STATUS	Status;
    int		count, i, need_poll, slp_ival;

    ACPI_SERIAL_ASSERT(ec);
    Status = AE_NO_HARDWARE_RESPONSE;
    need_poll = cold || rebooting || ec_polled_mode || sc->ec_suspending;

    /* Wait for event by polling or GPE (interrupt). */
    if (need_poll) {
        count = (ec_timeout * 1000) / EC_POLL_DELAY;
        if (count == 0)
            count = 1;
        DELAY(10);
        for (i = 0; i < count; i++) {
            Status = EcCheckStatus(sc, "poll", Event);
            if (ACPI_SUCCESS(Status))
                break;
            DELAY(EC_POLL_DELAY);
        }
    } else {
        slp_ival = hz / 1000;
        if (slp_ival != 0) {
            count = ec_timeout;
        } else {
            /* hz has less than 1 ms resolution so scale timeout. */
            slp_ival = 1;
            count = ec_timeout / (1000 / hz);
        }

        /*
         * Wait for the GPE to signal the status changed, checking the
         * status register each time we get one.  It's possible to get a
         * GPE for an event we're not interested in here (i.e., SCI for
         * EC query).
         */
        for (i = 0; i < count; i++) {
            if (gen_count == sc->ec_gencount)
                tsleep(sc, 0, "ecgpe", slp_ival);
            /*
             * Record new generation count.  It's possible the GPE was
             * just to notify us that a query is needed and we need to
             * wait for a second GPE to signal the completion of the
             * event we are actually waiting for.
             */
            Status = EcCheckStatus(sc, "sleep", Event);
            if (ACPI_SUCCESS(Status)) {
                if (gen_count == sc->ec_gencount)
                    no_intr++;
                else
                    no_intr = 0;
                break;
            }
            gen_count = sc->ec_gencount;
        }

        /*
         * We finished waiting for the GPE and it never arrived.  Try to
         * read the register once and trust whatever value we got.  This is
         * the best we can do at this point.
         */
        if (ACPI_FAILURE(Status))
            Status = EcCheckStatus(sc, "sleep_end", Event);
    }
    if (!need_poll && no_intr > 10) {
        device_printf(sc->ec_dev,
                      "not getting interrupts, switched to polled mode\n");
        ec_polled_mode = 1;
    }
    if (ACPI_FAILURE(Status))
        CTR0(KTR_ACPI, "error: ec wait timed out");
    return (Status);
}
Example #3
0
/*
 * Initializes the names of the ACPI control methods and grabs
 * the current state of all of the ACPI hotkeys into the softc.
 */
static uint8_t
acpi_fujitsu_init(struct acpi_fujitsu_softc *sc)
{
	struct acpi_softc *acpi_sc;
	int i, exists;

	ACPI_SERIAL_ASSERT(fujitsu);

	/* Setup all of the names for each control method */
	sc->_sta.name = "_STA";
	sc->gbll.name = "GBLL";
	sc->gbls.name = "GBLS";
	sc->ghks.name = "GHKS";
	sc->gmou.name = "GMOU";
	sc->gsif.name = "GSIF";
	sc->gvol.name = "GVOL";
	sc->ghks.name = "GHKS";
	sc->gsif.name = "GSIF";
	sc->rbll.name = "RBLL";
	sc->rvol.name = "RVOL";

	/* Determine what hardware functionality is available */
	acpi_fujitsu_check_hardware(sc);

	/* Build the sysctl tree */
	acpi_sc = acpi_device_get_parent_softc(sc->dev);
	sysctl_ctx_init(&sc->sysctl_ctx);
	sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
	    SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
	    OID_AUTO, "fujitsu", CTLFLAG_RD, 0, "");

	for (i = 0; sysctl_table[i].name != NULL; i++) {
		switch(sysctl_table[i].method) {
			case METHOD_GMOU:
				exists = sc->gmou.exists;
				break;
			case METHOD_GBLL:
				exists = sc->gbll.exists;
				break;
			case METHOD_GBLS:
				exists = sc->gbls.exists;
				break;
			case METHOD_GVOL:
			case METHOD_MUTE:
				exists = sc->gvol.exists;
				break;
			case METHOD_RVOL:
				exists = sc->rvol.exists;
				break;
			case METHOD_RBLL:
				exists = sc->rbll.exists;
				break;
			default:
				/* Allow by default */
				exists = 1;
				break;
		}
		if(!exists)
			continue;
		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_fujitsu_sysctl, "I",
		    sysctl_table[i].description);
	}


	/* Set the hotkeys to their initial states */
	if (!acpi_fujitsu_update(sc)) {
		device_printf(sc->dev, "Couldn't init hotkey states\n");
		return (FALSE);
	}

	return (TRUE);
}
Example #4
0
static int
acpi_battery_init(void)
{
    struct acpi_softc	*sc;
    device_t		 dev;
    int	 		 error;

    ACPI_SERIAL_ASSERT(battery);

    error = ENXIO;
    dev = devclass_get_device(devclass_find("acpi"), 0);
    if (dev == NULL)
	goto out;
    sc = device_get_softc(dev);

    error = acpi_register_ioctl(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl,
	NULL);
    if (error != 0)
	goto out;
    error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl,
	NULL);
    if (error != 0)
	goto out;
    error = acpi_register_ioctl(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl, NULL);
    if (error != 0)
	goto out;
    error = acpi_register_ioctl(ACPIIO_BATT_GET_BST, acpi_battery_ioctl, NULL);
    if (error != 0)
	goto out;

    sysctl_ctx_init(&acpi_battery_sysctl_ctx);
    acpi_battery_sysctl_tree = SYSCTL_ADD_NODE(&acpi_battery_sysctl_ctx,
	SYSCTL_CHILDREN(sc->acpi_sysctl_tree), OID_AUTO, "battery", CTLFLAG_RD,
	0, "battery status and info");
    SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx,
	SYSCTL_CHILDREN(acpi_battery_sysctl_tree),
	OID_AUTO, "life", CTLTYPE_INT | CTLFLAG_RD,
	&acpi_battery_battinfo.cap, 0, acpi_battery_sysctl, "I",
	"percent capacity remaining");
    SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx,
	SYSCTL_CHILDREN(acpi_battery_sysctl_tree),
	OID_AUTO, "time", CTLTYPE_INT | CTLFLAG_RD,
	&acpi_battery_battinfo.min, 0, acpi_battery_sysctl, "I",
	"remaining time in minutes");
    SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx,
	SYSCTL_CHILDREN(acpi_battery_sysctl_tree),
	OID_AUTO, "state", CTLTYPE_INT | CTLFLAG_RD,
	&acpi_battery_battinfo.state, 0, acpi_battery_sysctl, "I",
	"current status flags");
    SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx,
	SYSCTL_CHILDREN(acpi_battery_sysctl_tree),
	OID_AUTO, "units", CTLTYPE_INT | CTLFLAG_RD,
	NULL, 0, acpi_battery_units_sysctl, "I", "number of batteries");
    SYSCTL_ADD_INT(&acpi_battery_sysctl_ctx,
	SYSCTL_CHILDREN(acpi_battery_sysctl_tree),
	OID_AUTO, "info_expire", CTLFLAG_RW,
	&acpi_battery_info_expire, 0,
	"time in seconds until info is refreshed");

    acpi_batteries_initted = TRUE;

out:
    if (error != 0) {
	acpi_deregister_ioctl(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl);
	acpi_deregister_ioctl(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl);
	acpi_deregister_ioctl(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl);
	acpi_deregister_ioctl(ACPIIO_BATT_GET_BST, acpi_battery_ioctl);
    }
    return (error);
}
Example #5
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;
			
			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 */
	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);
}
static int
acpi_smbus_read_multi_1(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
    uint8_t *ptr, uint16_t len)
{
	UINT64 val;
	uint8_t	to;
	int error;

	ACPI_SERIAL_ASSERT(smbat);

	if (batt_sleep_ms)
	    AcpiOsSleep(batt_sleep_ms);

	val = addr;
	error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_ADDR,
	    val, 1);
	if (error)
		goto out;

	val = cmd;
	error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_CMD,
	    val, 1);
	if (error)
		goto out;

	val = 0x0B /* | 0x80 if PEC */ ;
	error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL,
	    val, 1);
	if (error)
		goto out;

	if (batt_sleep_ms)
	    AcpiOsSleep(batt_sleep_ms);

	for (to = SMBUS_TIMEOUT; to != 0; to--) {
		error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL,
		    &val, 1);
		if (error)
			goto out;
		if (val == 0)
			break;
		AcpiOsSleep(10);
	}
	if (to == 0) {
		error = ETIMEDOUT;
		goto out;
	}

	error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_STS, &val, 1);
	if (error)
		goto out;
	if (val & SMBUS_STS_MASK) {
		kprintf("%s: AE_ERROR 0x%x\n",
		       __func__, (int)(val & SMBUS_STS_MASK));
		error = EIO;
		goto out;
	}

	/* get length */
	error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_BCNT,
	    &val, 1);
	if (error)
		goto out;
	val = (val & 0x1f) + 1;

	bzero(ptr, len);
	if (len > val)
		len = val;

	if (batt_sleep_ms)
	    AcpiOsSleep(batt_sleep_ms);

	while (len--) {
		error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_DATA
		    + len, &val, 1);
		if (error)
			goto out;

		ptr[len] = val;
		if (batt_sleep_ms)
		    AcpiOsSleep(batt_sleep_ms);
	}

out:
	return (error);
}
static int
acpi_smbus_read_2(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
    uint16_t *ptr)
{
	int error, to;
	UINT64 val;

	ACPI_SERIAL_ASSERT(smbat);

	if (batt_sleep_ms)
	    AcpiOsSleep(batt_sleep_ms);

	val = addr;
	error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_ADDR,
	    val, 1);
	if (error)
		goto out;

	val = cmd;
	error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_CMD,
	    val, 1);
	if (error)
		goto out;

	val = 0x09; /* | 0x80 if PEC */
	error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL,
	    val, 1);
	if (error)
		goto out;

	if (batt_sleep_ms)
	    AcpiOsSleep(batt_sleep_ms);

	for (to = SMBUS_TIMEOUT; to != 0; to--) {
		error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL,
		    &val, 1);
		if (error)
			goto out;
		if (val == 0)
			break;
		AcpiOsSleep(10);
	}
	if (to == 0) {
		error = ETIMEDOUT;
		goto out;
	}

	error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_STS, &val, 1);
	if (error)
		goto out;
	if (val & SMBUS_STS_MASK) {
		kprintf("%s: AE_ERROR 0x%x\n",
		       __func__, (int)(val & SMBUS_STS_MASK));
		error = EIO;
		goto out;
	}

	error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_DATA,
	    &val, 2);
	if (error)
		goto out;

	*ptr = val;

out:
	return (error);
}
Example #8
0
static void
acpi_cmbat_get_bif(void *arg)
{
    struct acpi_cmbat_softc *sc;
    ACPI_STATUS	as;
    ACPI_OBJECT	*res;
    ACPI_HANDLE	h;
    ACPI_BUFFER	bif_buffer;
    device_t dev;

    ACPI_SERIAL_ASSERT(cmbat);

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

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

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

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

end:
    if (bif_buffer.Pointer != NULL)
	AcpiOsFree(bif_buffer.Pointer);
}