int aps_init(bus_space_tag_t iot, bus_space_handle_t ioh) { unsigned char iobuf[16]; /* command 0x17/0x81: check EC */ iobuf[APS_CMD] = 0x17; iobuf[APS_ARG1] = 0x81; if (aps_do_io(iot, ioh, iobuf, APS_WRITE_1, APS_READ_3)) return (1); if (iobuf[APS_RET] != 0 ||iobuf[APS_ARG3] != 0) return (1); /* Test values from the Linux driver */ if ((iobuf[APS_ARG1] != 0 || iobuf[APS_ARG2] != 0x60) && (iobuf[APS_ARG1] != 1 || iobuf[APS_ARG2] != 0)) return (1); /* command 0x14: set power */ iobuf[APS_CMD] = 0x14; iobuf[APS_ARG1] = 0x01; if (aps_do_io(iot, ioh, iobuf, APS_WRITE_1, APS_READ_0)) return (1); if (iobuf[APS_RET] != 0) return (1); /* command 0x10: set config (sample rate and order) */ iobuf[APS_CMD] = 0x10; iobuf[APS_ARG1] = 0xc8; iobuf[APS_ARG2] = 0x00; iobuf[APS_ARG3] = 0x02; if (aps_do_io(iot, ioh, iobuf, APS_WRITE_3, APS_READ_0)) return (1); if (iobuf[APS_RET] != 0) return (1); /* command 0x11: refresh data */ iobuf[APS_CMD] = 0x11; if (aps_do_io(iot, ioh, iobuf, APS_WRITE_0, APS_READ_1)) return (1); if (iobuf[APS_ARG1] != 0) return (1); return (0); }
void aps_power(int why, void *arg) { struct aps_softc *sc = (struct aps_softc *)arg; bus_space_tag_t iot = sc->aps_iot; bus_space_handle_t ioh = sc->aps_ioh; unsigned char iobuf[16]; if (why != PWR_RESUME) { timeout_del(&aps_timeout); return; } /* * Redo the init sequence on resume, because APS is * as forgetful as it is deaf. */ /* get APS mode */ iobuf[APS_CMD] = 0x13; if (aps_do_io(iot, ioh, iobuf, APS_WRITE_0, APS_READ_1) || aps_init(iot, ioh)) printf("aps: failed to wake up\n"); else timeout_add(&aps_timeout, (5 * hz) / 10); }
int aps_match(struct device *parent, void *match, void *aux) { bus_space_tag_t iot; bus_space_handle_t ioh; struct isa_attach_args *ia = aux; int iobase; u_int8_t cr; char iobuf[16]; iot = ia->ia_iot; iobase = ia->ipa_io[0].base; if (bus_space_map(iot, iobase, APS_ADDR_SIZE, 0, &ioh)) { DPRINTF(("aps: can't map i/o space\n")); return (0); } /* See if this machine has APS */ /* get APS mode */ iobuf[APS_CMD] = 0x13; if (aps_do_io(iot, ioh, iobuf, APS_WRITE_0, APS_READ_1)) { bus_space_unmap(iot, ioh, APS_ADDR_SIZE); return (0); } /* * Observed values from Linux driver: * 0x01: T42 * 0x02: chip already initialised * 0x03: T41 * 0x05: T61 */ cr = iobuf[APS_ARG1]; bus_space_unmap(iot, ioh, APS_ADDR_SIZE); DPRINTF(("aps: state register 0x%x\n", cr)); if (iobuf[APS_RET] != 0 || cr < 1 || cr > 5) { DPRINTF(("aps0: unsupported state %d\n", cr)); return (0); } ia->ipa_nio = 1; ia->ipa_io[0].length = APS_ADDR_SIZE; ia->ipa_nmem = 0; ia->ipa_nirq = 0; ia->ipa_ndrq = 0; return (1); }
static int aps_probe(struct device *dev) { struct resource *iores; int iorid = 0; u_int8_t cr; unsigned char iobuf[16]; #if defined(APSDEBUG) || defined(KLD_MODULE) device_printf(dev, "%s: port 0x%x\n", __func__, isa_get_port(dev)); #endif if (device_get_unit(dev) != 0) return ENXIO; iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &iorid, RF_ACTIVE); if (iores == NULL) { DPRINTF(("aps: can't map i/o space\n")); return ENXIO; } /* See if this machine has APS */ /* get APS mode */ iobuf[APS_CMD] = 0x13; if (aps_do_io(iores, iobuf, APS_WRITE_0, APS_READ_1)) { bus_release_resource(dev, SYS_RES_IOPORT, iorid, iores); return ENXIO; } /* * Observed values from Linux driver: * 0x01: T42 * 0x02: chip already initialised * 0x03: T41 * 0x05: T61 */ cr = iobuf[APS_ARG1]; bus_release_resource(dev, SYS_RES_IOPORT, iorid, iores); DPRINTF(("aps: state register 0x%x\n", cr)); if (iobuf[APS_RET] != 0 || cr < 1 || cr > 5) { DPRINTF(("aps: unsupported state %d\n", cr)); return ENXIO; } device_set_desc(dev, "ThinkPad Active Protection System"); return 0; }
static int aps_read_data(struct aps_softc *sc) { unsigned char iobuf[16]; /* command 0x11: refresh data */ iobuf[APS_CMD] = 0x11; if (aps_do_io(sc->sc_iores, iobuf, APS_WRITE_0, APS_READ_ALL)) return (1); sc->aps_data.state = iobuf[APS_STATE]; sc->aps_data.x_accel = iobuf[APS_XACCEL] + 256 * iobuf[APS_XACCEL + 1]; sc->aps_data.y_accel = iobuf[APS_YACCEL] + 256 * iobuf[APS_YACCEL + 1]; sc->aps_data.temp1 = iobuf[APS_TEMP]; sc->aps_data.x_var = iobuf[APS_XVAR] + 256 * iobuf[APS_XVAR + 1]; sc->aps_data.y_var = iobuf[APS_YVAR] + 256 * iobuf[APS_YVAR + 1]; sc->aps_data.temp2 = iobuf[APS_TEMP2]; sc->aps_data.input = iobuf[APS_INPUT]; return (0); }
static int aps_resume(struct device *dev) { struct aps_softc *sc = device_get_softc(dev); unsigned char iobuf[16]; /* * Redo the init sequence on resume, because APS is * as forgetful as it is deaf. */ /* get APS mode */ iobuf[APS_CMD] = 0x13; if (aps_do_io(sc->sc_iores, iobuf, APS_WRITE_0, APS_READ_1) || aps_init(sc->sc_iores)) { device_printf(sc->sc_dev, "failed to wake up\n"); return EIO; } sensor_task_register(sc, aps_refresh, 1); return 0; }