1 /* $OpenBSD: acpiac.c,v 1.28 2010/08/07 16:55:38 canacar 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/event.h> 20 #include <sys/systm.h> 21 #include <sys/device.h> 22 #include <sys/malloc.h> 23 24 #include <machine/bus.h> 25 #include <machine/apmvar.h> 26 27 #include <dev/acpi/acpireg.h> 28 #include <dev/acpi/acpivar.h> 29 #include <dev/acpi/acpidev.h> 30 #include <dev/acpi/amltypes.h> 31 #include <dev/acpi/dsdt.h> 32 33 #include <sys/sensors.h> 34 35 int acpiac_match(struct device *, void *, void *); 36 void acpiac_attach(struct device *, struct device *, void *); 37 int acpiac_notify(struct aml_node *, int, void *); 38 39 void acpiac_refresh(void *); 40 int acpiac_getsta(struct acpiac_softc *); 41 42 struct cfattach acpiac_ca = { 43 sizeof(struct acpiac_softc), acpiac_match, acpiac_attach 44 }; 45 46 struct cfdriver acpiac_cd = { 47 NULL, "acpiac", DV_DULL 48 }; 49 50 const char *acpiac_hids[] = { ACPI_DEV_AC, 0 }; 51 52 int 53 acpiac_match(struct device *parent, void *match, void *aux) 54 { 55 struct acpi_attach_args *aa = aux; 56 struct cfdata *cf = match; 57 58 /* sanity */ 59 return (acpi_matchhids(aa, acpiac_hids, cf->cf_driver->cd_name)); 60 } 61 62 void 63 acpiac_attach(struct device *parent, struct device *self, void *aux) 64 { 65 struct acpiac_softc *sc = (struct acpiac_softc *)self; 66 struct acpi_attach_args *aa = aux; 67 68 sc->sc_acpi = (struct acpi_softc *)parent; 69 sc->sc_devnode = aa->aaa_node; 70 71 acpiac_getsta(sc); 72 printf(": AC unit "); 73 if (sc->sc_ac_stat == PSR_ONLINE) 74 printf("online\n"); 75 else if (sc->sc_ac_stat == PSR_OFFLINE) 76 printf("offline\n"); 77 else 78 printf("in unknown state\n"); 79 80 strlcpy(sc->sc_sensdev.xname, DEVNAME(sc), 81 sizeof(sc->sc_sensdev.xname)); 82 strlcpy(sc->sc_sens[0].desc, "power supply", 83 sizeof(sc->sc_sens[0].desc)); 84 sc->sc_sens[0].type = SENSOR_INDICATOR; 85 sensor_attach(&sc->sc_sensdev, &sc->sc_sens[0]); 86 sensordev_install(&sc->sc_sensdev); 87 sc->sc_sens[0].value = sc->sc_ac_stat; 88 89 aml_register_notify(sc->sc_devnode, aa->aaa_dev, 90 acpiac_notify, sc, ACPIDEV_NOPOLL); 91 } 92 93 void 94 acpiac_refresh(void *arg) 95 { 96 struct acpiac_softc *sc = arg; 97 98 acpiac_getsta(sc); 99 sc->sc_sens[0].value = sc->sc_ac_stat; 100 acpi_record_event(sc->sc_acpi, APM_POWER_CHANGE); 101 } 102 103 int 104 acpiac_getsta(struct acpiac_softc *sc) 105 { 106 int64_t sta; 107 108 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_STA", 0, NULL, NULL)) { 109 dnprintf(10, "%s: no _STA\n", 110 DEVNAME(sc)); 111 } 112 113 if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "_PSR", 0, NULL, &sta)) { 114 dnprintf(10, "%s: no _PSR\n", 115 DEVNAME(sc)); 116 return (1); 117 } 118 sc->sc_ac_stat = sta; 119 return (0); 120 } 121 122 int 123 acpiac_notify(struct aml_node *node, int notify_type, void *arg) 124 { 125 struct acpiac_softc *sc = arg; 126 127 dnprintf(10, "acpiac_notify: %.2x %s\n", notify_type, 128 sc->sc_devnode->name); 129 130 switch (notify_type) { 131 case 0x00: 132 case 0x01: 133 case 0x81: 134 /* 135 * XXX some sony vaio's use the wrong notify type 136 * work around it by honoring it as a 0x80 137 */ 138 /* FALLTHROUGH */ 139 case 0x80: 140 acpiac_refresh(sc); 141 dnprintf(10, "A/C status: %d\n", sc->sc_ac_stat); 142 break; 143 } 144 return (0); 145 } 146