root/dev/acpi/acpidock.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. acpidock_match
  2. acpidock_attach
  3. acpidock_status
  4. acpidock_docklock
  5. acpidock_dockctl
  6. acpidock_eject
  7. acpidock_notify
  8. acpidock_foundejd

    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 }

/* [<][>][^][v][top][bottom][index][help] */