The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/acpi_support/atk0110.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: atk0110.c,v 1.4 2010/02/11 06:54:57 cnst Exp $ */
    2 /*      $OpenBSD: atk0110.c,v 1.1 2009/07/23 01:38:16 cnst Exp $        */
    3 
    4 /*
    5  * Copyright (c) 2009, 2010 Constantine A. Murenin <cnst++@FreeBSD.org>
    6  *
    7  * Permission to use, copy, modify, and distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  */
   19 
   20 #include <sys/cdefs.h>
   21 __FBSDID("$FreeBSD: releng/8.4/sys/dev/acpi_support/atk0110.c 210476 2010-07-25 17:48:16Z rpaulo $");
   22 
   23 #include <machine/_inttypes.h>
   24 #include <sys/param.h>
   25 #include <sys/systm.h>
   26 #include <sys/kernel.h>
   27 #include <sys/bus.h>
   28 #include <sys/module.h>
   29 #include <sys/malloc.h>
   30 #include <sys/sysctl.h>
   31 
   32 #include <contrib/dev/acpica/include/acpi.h>
   33 #include <dev/acpica/acpivar.h>
   34 
   35 /*
   36  * ASUSTeK AI Booster (ACPI ASOC ATK0110).
   37  *
   38  * This code was originally written for OpenBSD after the techniques
   39  * described in the Linux's asus_atk0110.c and FreeBSD's Takanori Watanabe's
   40  * acpi_aiboost.c were verified to be accurate on the actual hardware kindly
   41  * provided by Sam Fourman Jr.  It was subsequently ported from OpenBSD to
   42  * DragonFly BSD, to NetBSD's sysmon_envsys(9) and to FreeBSD's sysctl(9).
   43  *
   44  *                                -- Constantine A. Murenin <http://cnst.su/>
   45  */
   46 
   47 #define _COMPONENT      ACPI_OEM
   48 ACPI_MODULE_NAME("aibs");
   49 ACPI_SERIAL_DECL(aibs, "aibs");
   50 
   51 #define AIBS_MORE_SENSORS
   52 #define AIBS_VERBOSE
   53 
   54 enum aibs_type {
   55         AIBS_VOLT,
   56         AIBS_TEMP,
   57         AIBS_FAN
   58 };
   59 
   60 struct aibs_sensor {
   61         ACPI_INTEGER    v;
   62         ACPI_INTEGER    i;
   63         ACPI_INTEGER    l;
   64         ACPI_INTEGER    h;
   65         enum aibs_type  t;
   66 };
   67 
   68 struct aibs_softc {
   69         struct device           *sc_dev;
   70         ACPI_HANDLE             sc_ah;
   71 
   72         struct aibs_sensor      *sc_asens_volt;
   73         struct aibs_sensor      *sc_asens_temp;
   74         struct aibs_sensor      *sc_asens_fan;
   75 };
   76 
   77 static int aibs_probe(device_t);
   78 static int aibs_attach(device_t);
   79 static int aibs_detach(device_t);
   80 static int aibs_sysctl(SYSCTL_HANDLER_ARGS);
   81 
   82 static void aibs_attach_sif(struct aibs_softc *, enum aibs_type);
   83 
   84 static device_method_t aibs_methods[] = {
   85         DEVMETHOD(device_probe,         aibs_probe),
   86         DEVMETHOD(device_attach,        aibs_attach),
   87         DEVMETHOD(device_detach,        aibs_detach),
   88         { NULL, NULL }
   89 };
   90 
   91 static driver_t aibs_driver = {
   92         "aibs",
   93         aibs_methods,
   94         sizeof(struct aibs_softc)
   95 };
   96 
   97 static devclass_t aibs_devclass;
   98 
   99 DRIVER_MODULE(aibs, acpi, aibs_driver, aibs_devclass, NULL, NULL);
  100 
  101 
  102 static char* aibs_hids[] = {
  103         "ATK0110",
  104         NULL
  105 };
  106 
  107 static int
  108 aibs_probe(device_t dev)
  109 {
  110         if (acpi_disabled("aibs") ||
  111             ACPI_ID_PROBE(device_get_parent(dev), dev, aibs_hids) == NULL)
  112                 return ENXIO;
  113 
  114         device_set_desc(dev, "ASUSTeK AI Booster (ACPI ASOC ATK0110)");
  115         return 0;
  116 }
  117 
  118 static int
  119 aibs_attach(device_t dev)
  120 {
  121         struct aibs_softc *sc = device_get_softc(dev);
  122 
  123         sc->sc_dev = dev;
  124         sc->sc_ah = acpi_get_handle(dev);
  125 
  126         aibs_attach_sif(sc, AIBS_VOLT);
  127         aibs_attach_sif(sc, AIBS_TEMP);
  128         aibs_attach_sif(sc, AIBS_FAN);
  129 
  130         return 0;
  131 }
  132 
  133 static void
  134 aibs_attach_sif(struct aibs_softc *sc, enum aibs_type st)
  135 {
  136         ACPI_STATUS             s;
  137         ACPI_BUFFER             b;
  138         ACPI_OBJECT             *bp, *o;
  139         int                     i, n;
  140         const char              *node;
  141         char                    name[] = "?SIF";
  142         struct aibs_sensor      *as;
  143         struct sysctl_oid       *so;
  144 
  145         switch (st) {
  146         case AIBS_VOLT:
  147                 node = "volt";
  148                 name[0] = 'V';
  149                 break;
  150         case AIBS_TEMP:
  151                 node = "temp";
  152                 name[0] = 'T';
  153                 break;
  154         case AIBS_FAN:
  155                 node = "fan";
  156                 name[0] = 'F';
  157                 break;
  158         default:
  159                 return;
  160         }
  161 
  162         b.Length = ACPI_ALLOCATE_BUFFER;
  163         s = AcpiEvaluateObjectTyped(sc->sc_ah, name, NULL, &b,
  164             ACPI_TYPE_PACKAGE);
  165         if (ACPI_FAILURE(s)) {
  166                 device_printf(sc->sc_dev, "%s not found\n", name);
  167                 return;
  168         }
  169 
  170         bp = b.Pointer;
  171         o = bp->Package.Elements;
  172         if (o[0].Type != ACPI_TYPE_INTEGER) {
  173                 device_printf(sc->sc_dev, "%s[0]: invalid type\n", name);
  174                 AcpiOsFree(b.Pointer);
  175                 return;
  176         }
  177 
  178         n = o[0].Integer.Value;
  179         if (bp->Package.Count - 1 < n) {
  180                 device_printf(sc->sc_dev, "%s: invalid package\n", name);
  181                 AcpiOsFree(b.Pointer);
  182                 return;
  183         } else if (bp->Package.Count - 1 > n) {
  184                 int on = n;
  185 
  186 #ifdef AIBS_MORE_SENSORS
  187                 n = bp->Package.Count - 1;
  188 #endif
  189                 device_printf(sc->sc_dev, "%s: malformed package: %i/%i"
  190                     ", assume %i\n", name, on, bp->Package.Count - 1, n);
  191         }
  192         if (n < 1) {
  193                 device_printf(sc->sc_dev, "%s: no members in the package\n",
  194                     name);
  195                 AcpiOsFree(b.Pointer);
  196                 return;
  197         }
  198 
  199         as = malloc(sizeof(*as) * n, M_DEVBUF, M_NOWAIT | M_ZERO);
  200         if (as == NULL) {
  201                 device_printf(sc->sc_dev, "%s: malloc fail\n", name);
  202                 AcpiOsFree(b.Pointer);
  203                 return;
  204         }
  205         switch (st) {
  206         case AIBS_VOLT:
  207                 sc->sc_asens_volt = as;
  208                 break;
  209         case AIBS_TEMP:
  210                 sc->sc_asens_temp = as;
  211                 break;
  212         case AIBS_FAN:
  213                 sc->sc_asens_fan = as;
  214                 break;
  215         }
  216 
  217         /* sysctl subtree for sensors of this type */
  218         so = SYSCTL_ADD_NODE(device_get_sysctl_ctx(sc->sc_dev),
  219             SYSCTL_CHILDREN(device_get_sysctl_tree(sc->sc_dev)), st,
  220             node, CTLFLAG_RD, NULL, NULL);
  221 
  222         for (i = 0, o++; i < n; i++, o++) {
  223                 ACPI_OBJECT     *oi;
  224                 char            si[3];
  225                 const char      *desc;
  226 
  227                 /* acpica5 automatically evaluates the referenced package */
  228                 if (o[0].Type != ACPI_TYPE_PACKAGE) {
  229                         device_printf(sc->sc_dev,
  230                             "%s: %i: not a package: %i type\n",
  231                             name, i, o[0].Type);
  232                         continue;
  233                 }
  234                 oi = o[0].Package.Elements;
  235                 if (o[0].Package.Count != 5 ||
  236                     oi[0].Type != ACPI_TYPE_INTEGER ||
  237                     oi[1].Type != ACPI_TYPE_STRING ||
  238                     oi[2].Type != ACPI_TYPE_INTEGER ||
  239                     oi[3].Type != ACPI_TYPE_INTEGER ||
  240                     oi[4].Type != ACPI_TYPE_INTEGER) {
  241                         device_printf(sc->sc_dev,
  242                             "%s: %i: invalid package\n",
  243                             name, i);
  244                         continue;
  245                 }
  246                 as[i].i = oi[0].Integer.Value;
  247                 desc = oi[1].String.Pointer;
  248                 as[i].l = oi[2].Integer.Value;
  249                 as[i].h = oi[3].Integer.Value;
  250                 as[i].t = st;
  251 #ifdef AIBS_VERBOSE
  252                 device_printf(sc->sc_dev, "%c%i: "
  253                     "0x%08"PRIx64" %20s %5"PRIi64" / %5"PRIi64"  "
  254                     "0x%"PRIx64"\n",
  255                     name[0], i,
  256                     as[i].i, desc, (int64_t)as[i].l, (int64_t)as[i].h,
  257                     oi[4].Integer.Value);
  258 #endif
  259                 snprintf(si, sizeof(si), "%i", i);
  260                 SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->sc_dev),
  261                     SYSCTL_CHILDREN(so), i, si, CTLTYPE_OPAQUE | CTLFLAG_RD,
  262                     sc, st, aibs_sysctl, st == AIBS_TEMP ? "IK" : "I", desc);
  263         }
  264 
  265         AcpiOsFree(b.Pointer);
  266 }
  267 
  268 static int
  269 aibs_detach(device_t dev)
  270 {
  271         struct aibs_softc       *sc = device_get_softc(dev);
  272 
  273         if (sc->sc_asens_volt != NULL)
  274                 free(sc->sc_asens_volt, M_DEVBUF);
  275         if (sc->sc_asens_temp != NULL)
  276                 free(sc->sc_asens_temp, M_DEVBUF);
  277         if (sc->sc_asens_fan != NULL)
  278                 free(sc->sc_asens_fan, M_DEVBUF);
  279         return 0;
  280 }
  281 
  282 #ifdef AIBS_VERBOSE
  283 #define ddevice_printf(x...) device_printf(x)
  284 #else
  285 #define ddevice_printf(x...)
  286 #endif
  287 
  288 static int
  289 aibs_sysctl(SYSCTL_HANDLER_ARGS)
  290 {
  291         struct aibs_softc       *sc = arg1;
  292         enum aibs_type          st = arg2;
  293         int                     i = oidp->oid_number;
  294         ACPI_STATUS             rs;
  295         ACPI_OBJECT             p, *bp;
  296         ACPI_OBJECT_LIST        mp;
  297         ACPI_BUFFER             b;
  298         char                    *name;
  299         struct aibs_sensor      *as;
  300         ACPI_INTEGER            v, l, h;
  301         int                     so[3];
  302 
  303         switch (st) {
  304         case AIBS_VOLT:
  305                 name = "RVLT";
  306                 as = sc->sc_asens_volt;
  307                 break;
  308         case AIBS_TEMP:
  309                 name = "RTMP";
  310                 as = sc->sc_asens_temp;
  311                 break;
  312         case AIBS_FAN:
  313                 name = "RFAN";
  314                 as = sc->sc_asens_fan;
  315                 break;
  316         default:
  317                 return ENOENT;
  318         }
  319         if (as == NULL)
  320                 return ENOENT;
  321         l = as[i].l;
  322         h = as[i].h;
  323         p.Type = ACPI_TYPE_INTEGER;
  324         p.Integer.Value = as[i].i;
  325         mp.Count = 1;
  326         mp.Pointer = &p;
  327         b.Length = ACPI_ALLOCATE_BUFFER;
  328         ACPI_SERIAL_BEGIN(aibs);
  329         rs = AcpiEvaluateObjectTyped(sc->sc_ah, name, &mp, &b,
  330             ACPI_TYPE_INTEGER);
  331         if (ACPI_FAILURE(rs)) {
  332                 ddevice_printf(sc->sc_dev,
  333                     "%s: %i: evaluation failed\n",
  334                     name, i);
  335                 ACPI_SERIAL_END(aibs);
  336                 return EIO;
  337         }
  338         bp = b.Pointer;
  339         v = bp->Integer.Value;
  340         AcpiOsFree(b.Pointer);
  341         ACPI_SERIAL_END(aibs);
  342 
  343         switch (st) {
  344         case AIBS_VOLT:
  345                 break;
  346         case AIBS_TEMP:
  347                 v += 2732;
  348                 l += 2732;
  349                 h += 2732;
  350                 break;
  351         case AIBS_FAN:
  352                 break;
  353         }
  354         so[0] = v;
  355         so[1] = l;
  356         so[2] = h;
  357         return sysctl_handle_opaque(oidp, &so, sizeof(so), req);
  358 }

Cache object: a52478468727ab8bbce3513e429aad68


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.