1 /* $OpenBSD: acpiac.c,v 1.27 2009/03/11 20:37:46 jordan Exp $ */ 2 /* 3 * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/device.h> 21 #include <sys/malloc.h> 22 23 #include <machine/bus.h> 24 25 #include <dev/acpi/acpireg.h> 26 #include <dev/acpi/acpivar.h> 27 #include <dev/acpi/acpidev.h> 28 #include <dev/acpi/amltypes.h> 29 #include <dev/acpi/dsdt.h> 30 31 #include <sys/sensors.h> 32 33 int acpiac_match(struct device *, void *, void *); 34 void acpiac_attach(struct device *, struct device *, void *); 35 int acpiac_notify(struct aml_node *, int, void *); 36 37 void acpiac_refresh(void *); 38 int acpiac_getsta(struct acpiac_softc *); 39 40 struct cfattach acpiac_ca = { 41 sizeof(struct acpiac_softc), acpiac_match, acpiac_attach 42 }; 43 44 struct cfdriver acpiac_cd = { 45 NULL, "acpiac", DV_DULL 46 }; 47 48 const char *acpiac_hids[] = { ACPI_DEV_AC, 0 }; 49 50 int 51 acpiac_match(struct device *parent, void *match, void *aux) 52 { 53 struct acpi_attach_args *aa = aux; 54 struct cfdata *cf = match; 55 56 /* sanity */ 57 return (acpi_matchhids(aa, acpiac_hids, cf->cf_driver->cd_name)); 58 } 59 60 void 61 acpiac_attach(struct device *parent, struct device *self, void *aux) 62 { 63 struct acpiac_softc *sc = (struct acpiac_softc *)self; 64 struct acpi_attach_args *aa = aux; 65 66 sc->sc_acpi = (struct acpi_softc *)parent; 67 sc->sc_devnode = aa->aaa_node; 68 69 acpiac_getsta(sc); 70 printf(": AC unit "); 71 if (sc->sc_ac_stat == PSR_ONLINE) 72 printf("online\n"); 73 else if (sc->sc_ac_stat == PSR_OFFLINE) 74 printf("offline\n"); 75 else 76 printf("in unknown state\n"); 77 78 strlcpy(sc->sc_sensdev.xname, DEVNAME(sc), 79 sizeof(sc->sc_sensdev.xname)); 80 strlcpy(sc->sc_sens[0].desc, "power supply", 81 sizeof(sc->sc_sens[0].desc)); 82 sc->sc_sens[0].type = SENSOR_INDICATOR; 83 sensor_attach(&sc->sc_sensdev, &sc->sc_sens[0]); 84 sensordev_install(&sc->sc_sensdev); 85 sc->sc_sens[0].value = sc->sc_ac_stat; 86 87 aml_register_notify(sc->sc_devnode, aa->aaa_dev, 88 acpiac_notify, sc, ACPIDEV_NOPOLL); 89 } 90 91 void 92 acpiac_refresh(void *arg) 93 { 94 struct acpiac_softc *sc = arg; 95 96 acpiac_getsta(sc); 97 sc->sc_sens[0].value = sc->sc_ac_stat; 98 } 99 100 int 101 acpiac_getsta(struct acpiac_softc *sc) 102 { 103 int64_t sta; 104 105 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_STA", 0, NULL, NULL)) { 106 dnprintf(10, "%s: no _STA\n", 107 DEVNAME(sc)); 108 } 109 110 if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "_PSR", 0, NULL, &sta)) { 111 dnprintf(10, "%s: no _PSR\n", 112 DEVNAME(sc)); 113 return (1); 114 } 115 sc->sc_ac_stat = sta; 116 return (0); 117 } 118 119 int 120 acpiac_notify(struct aml_node *node, int notify_type, void *arg) 121 { 122 struct acpiac_softc *sc = arg; 123 124 dnprintf(10, "acpiac_notify: %.2x %s\n", notify_type, 125 sc->sc_devnode->name); 126 127 switch (notify_type) { 128 case 0x00: 129 case 0x01: 130 case 0x81: 131 /* 132 * XXX some sony vaio's use the wrong notify type 133 * work around it by honoring it as a 0x80 134 */ 135 /* FALLTHROUGH */ 136 case 0x80: 137 acpiac_refresh(sc); 138 dnprintf(10, "A/C status: %d\n", sc->sc_ac_stat); 139 break; 140 } 141 return (0); 142 } 143