Annotation of sys/dev/acpi/acpidock.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: acpidock.c,v 1.25 2007/04/23 19:29:03 mk Exp $ */
! 2: /*
! 3: * Copyright (c) 2006,2007 Michael Knudsen <mk@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: #include <sys/sensors.h>
! 23:
! 24: #include <machine/bus.h>
! 25:
! 26: #include <dev/acpi/acpireg.h>
! 27: #include <dev/acpi/acpivar.h>
! 28: #include <dev/acpi/acpidev.h>
! 29: #include <dev/acpi/amltypes.h>
! 30: #include <dev/acpi/dsdt.h>
! 31:
! 32: struct aml_nodelist {
! 33: struct aml_node *node;
! 34: TAILQ_ENTRY(aml_nodelist) entries;
! 35: };
! 36:
! 37: int acpidock_match(struct device *, void *, void *);
! 38: void acpidock_attach(struct device *, struct device *, void *);
! 39:
! 40: struct cfattach acpidock_ca = {
! 41: sizeof(struct acpidock_softc), acpidock_match, acpidock_attach
! 42: };
! 43:
! 44: struct cfdriver acpidock_cd = {
! 45: NULL, "acpidock", DV_DULL
! 46: };
! 47:
! 48:
! 49: int acpidock_docklock(struct acpidock_softc *, int);
! 50: int acpidock_dockctl(struct acpidock_softc *, int);
! 51: int acpidock_eject(struct acpidock_softc *, struct aml_node *);
! 52: int acpidock_notify(struct aml_node *, int, void *);
! 53: int acpidock_status(struct acpidock_softc *);
! 54:
! 55: void acpidock_foundejd(struct aml_node *, void *);
! 56:
! 57: int
! 58: acpidock_match(struct device *parent, void *match, void *aux)
! 59: {
! 60: struct acpi_attach_args *aaa = aux;
! 61: struct cfdata *cf = match;
! 62:
! 63: /* sanity */
! 64: if (aaa->aaa_name == NULL ||
! 65: strcmp(aaa->aaa_name, cf->cf_driver->cd_name) != 0 ||
! 66: aaa->aaa_table != NULL)
! 67: return (0);
! 68:
! 69: return (1);
! 70: }
! 71:
! 72: void
! 73: acpidock_attach(struct device *parent, struct device *self, void *aux)
! 74: {
! 75: struct acpidock_softc *sc = (struct acpidock_softc *)self;
! 76: struct acpi_attach_args *aa = aux;
! 77: extern struct aml_node aml_root;
! 78:
! 79: sc->sc_acpi = (struct acpi_softc *)parent;
! 80: sc->sc_devnode = aa->aaa_node->child;
! 81:
! 82: printf(": %s", sc->sc_devnode->parent->name);
! 83:
! 84: acpidock_status(sc);
! 85: if (sc->sc_docked == ACPIDOCK_STATUS_DOCKED) {
! 86: acpidock_docklock(sc, 1);
! 87: acpidock_dockctl(sc, 1);
! 88: } else {
! 89: acpidock_dockctl(sc, 0);
! 90: acpidock_docklock(sc, 0);
! 91: }
! 92:
! 93: acpidock_status(sc);
! 94: printf(":%s docked (%d)\n",
! 95: sc->sc_docked == ACPIDOCK_STATUS_DOCKED ? "" : " not",
! 96: sc->sc_sta);
! 97:
! 98: strlcpy(sc->sc_sensdev.xname, DEVNAME(sc),
! 99: sizeof(sc->sc_sensdev.xname));
! 100: if (sc->sc_docked)
! 101: strlcpy(sc->sc_sens.desc, "docked",
! 102: sizeof(sc->sc_sens.desc));
! 103: else
! 104: strlcpy(sc->sc_sens.desc, "not docked",
! 105: sizeof(sc->sc_sens.desc));
! 106:
! 107: sc->sc_sens.type = SENSOR_INDICATOR;
! 108: sc->sc_sens.value = sc->sc_docked == ACPIDOCK_STATUS_DOCKED;
! 109: sensor_attach(&sc->sc_sensdev, &sc->sc_sens);
! 110: sensordev_install(&sc->sc_sensdev);
! 111:
! 112: TAILQ_INIT(&sc->sc_deps_h);
! 113: aml_find_node(aml_root.child, "_EJD", acpidock_foundejd, sc);
! 114:
! 115: aml_register_notify(sc->sc_devnode->parent, aa->aaa_dev,
! 116: acpidock_notify, sc, ACPIDEV_NOPOLL);
! 117:
! 118: }
! 119:
! 120: int
! 121: acpidock_status(struct acpidock_softc *sc)
! 122: {
! 123: struct aml_value res;
! 124: int rv;
! 125:
! 126: if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_STA", 0, NULL,
! 127: &res) != 0)
! 128: rv = 0;
! 129: else
! 130: rv = 1;
! 131:
! 132: sc->sc_sta = aml_val2int(&res);
! 133:
! 134: sc->sc_docked = sc->sc_sta & STA_PRESENT;
! 135:
! 136: aml_freevalue(&res);
! 137:
! 138: return (rv);
! 139: }
! 140:
! 141: int
! 142: acpidock_docklock(struct acpidock_softc *sc, int lock)
! 143: {
! 144: struct aml_value cmd;
! 145: struct aml_value res;
! 146: int rv;
! 147:
! 148: memset(&cmd, 0, sizeof cmd);
! 149: cmd.v_integer = lock;
! 150: cmd.type = AML_OBJTYPE_INTEGER;
! 151: if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_LCK", 1, &cmd,
! 152: &res) != 0) {
! 153: dnprintf(20, "%s: _LCK %d failed\n", DEVNAME(sc), lock);
! 154:
! 155: rv = 0;
! 156: } else {
! 157: dnprintf(20, "%s: _LCK %d successful\n", DEVNAME(sc), lock);
! 158:
! 159: rv = 1;
! 160: }
! 161:
! 162: aml_freevalue(&res);
! 163:
! 164: return rv;
! 165: }
! 166:
! 167: int
! 168: acpidock_dockctl(struct acpidock_softc *sc, int dock)
! 169: {
! 170: struct aml_value cmd;
! 171: struct aml_value res;
! 172: int rv;
! 173:
! 174: memset(&cmd, 0, sizeof cmd);
! 175: cmd.v_integer = dock;
! 176: cmd.type = AML_OBJTYPE_INTEGER;
! 177: if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_DCK", 1, &cmd,
! 178: &res) != 0) {
! 179: /* XXX */
! 180: dnprintf(15, "%s: _DCK %d failed\n", DEVNAME(sc), dock);
! 181:
! 182: rv = 0;
! 183: } else {
! 184: dnprintf(15, "%s: _DCK %d successful\n", DEVNAME(sc), dock);
! 185:
! 186: rv = 1;
! 187: }
! 188:
! 189: aml_freevalue(&res);
! 190:
! 191: return rv;
! 192: }
! 193:
! 194: int
! 195: acpidock_eject(struct acpidock_softc *sc, struct aml_node *node)
! 196: {
! 197: struct aml_value cmd;
! 198: struct aml_value res;
! 199: int rv;
! 200:
! 201: memset(&cmd, 0, sizeof cmd);
! 202: cmd.v_integer = 1;
! 203: cmd.type = AML_OBJTYPE_INTEGER;
! 204: if (aml_evalname(sc->sc_acpi, node, "_EJ0", 1, &cmd,
! 205: &res) != 0) {
! 206: /* XXX */
! 207: dnprintf(15, "%s: _EJ0 failed\n", DEVNAME(sc));
! 208:
! 209: rv = 0;
! 210: } else {
! 211: dnprintf(15, "%s: _EJ0 successful\n", DEVNAME(sc));
! 212:
! 213: rv = 1;
! 214: }
! 215:
! 216: aml_freevalue(&res);
! 217:
! 218: return rv;
! 219: }
! 220:
! 221: int
! 222: acpidock_notify(struct aml_node *node, int notify_type, void *arg)
! 223: {
! 224: struct acpidock_softc *sc = arg;
! 225:
! 226: dnprintf(5, "%s: acpidock_notify: notify %d\n", DEVNAME(sc),
! 227: notify_type);
! 228:
! 229: switch (notify_type) {
! 230: case ACPIDOCK_EVENT_INSERT:
! 231: printf("%s: dock", DEVNAME(sc));
! 232: acpidock_docklock(sc, 1);
! 233: acpidock_dockctl(sc, 1);
! 234:
! 235: break;
! 236: case ACPIDOCK_EVENT_EJECT: {
! 237: struct aml_nodelist *n;
! 238:
! 239: TAILQ_FOREACH(n, &sc->sc_deps_h, entries)
! 240: acpidock_eject(sc, n->node);
! 241:
! 242: acpidock_dockctl(sc, 0);
! 243: acpidock_docklock(sc, 0);
! 244:
! 245: /* now actually undock */
! 246: acpidock_eject(sc, sc->sc_devnode);
! 247:
! 248: printf("%s: undock", DEVNAME(sc));
! 249:
! 250: break;
! 251: }
! 252: }
! 253:
! 254: acpidock_status(sc);
! 255: sc->sc_sens.value = sc->sc_docked == ACPIDOCK_STATUS_DOCKED;
! 256: if (sc->sc_docked)
! 257: strlcpy(sc->sc_sens.desc, "docked",
! 258: sizeof(sc->sc_sens.desc));
! 259: else
! 260: strlcpy(sc->sc_sens.desc, "not docked",
! 261: sizeof(sc->sc_sens.desc));
! 262:
! 263: printf(": status %s\n",
! 264: sc->sc_docked == ACPIDOCK_STATUS_DOCKED ? "docked" : "undocked");
! 265:
! 266: return (0);
! 267: }
! 268:
! 269: void
! 270: acpidock_foundejd(struct aml_node *node, void *arg)
! 271: {
! 272: struct acpidock_softc *sc = (struct acpidock_softc *)arg;
! 273: struct aml_value res;
! 274:
! 275: dnprintf(15, "%s: %s", DEVNAME(sc), node->parent->name);
! 276:
! 277: if (aml_evalnode(sc->sc_acpi, node, 0, NULL, &res) == -1) {
! 278: printf(": error\n");
! 279: } else {
! 280: struct aml_nodelist *n;
! 281:
! 282: /* XXX debug */
! 283: dnprintf(10, "%s: %s depends on %s\n", DEVNAME(sc),
! 284: node->parent->name, res.v_string);
! 285:
! 286: /* XXX more than one dock? */
! 287:
! 288: n = malloc(sizeof(struct aml_nodelist), M_DEVBUF, M_WAITOK);
! 289: n->node = node->parent;
! 290:
! 291: TAILQ_INSERT_TAIL(&sc->sc_deps_h, n, entries);
! 292: }
! 293:
! 294: aml_freevalue(&res);
! 295: }
CVSweb