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/acpi_tz.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: acpi_tz.c,v 1.9 2004/03/24 09:14:58 martin Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2003 Jared D. McNeill <jmcneill@invisible.ca>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. The name of the author may not be used to endorse or promote products
   13  *    derived from this software without specific prior written permission.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   20  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   22  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   23  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 /*
   29  * ACPI Thermal Zone driver
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __KERNEL_RCSID(0, "$NetBSD: acpi_tz.c,v 1.9 2004/03/24 09:14:58 martin Exp $");
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/kernel.h>
   38 #include <sys/errno.h>
   39 #include <sys/ioctl.h>
   40 #include <sys/syslog.h>
   41 #include <sys/device.h>
   42 #include <sys/callout.h>
   43 #include <sys/proc.h>
   44 #include <sys/lock.h>
   45 #include <dev/sysmon/sysmonvar.h>
   46 
   47 #include <dev/acpi/acpica.h>
   48 #include <dev/acpi/acpireg.h>
   49 #include <dev/acpi/acpivar.h>
   50 
   51 /* flags */
   52 #define ATZ_F_VERBOSE           0x01    /* show events to console */
   53 
   54 /* constants */
   55 #define ATZ_TZP_RATE    300     /* default if no _TZP CM present (30 secs) */
   56 #define ATZ_NLEVELS     10      /* number of cooling levels, from ACPI spec */
   57 
   58 /* sensor indexes */
   59 #define ATZ_SENSOR_TEMP 0       /* thermal zone temperature */
   60 #define ATZ_NUMSENSORS  1       /* number of sensors */
   61 
   62 const struct envsys_range acpitz_ranges[] = {
   63         { 0, 1, ATZ_SENSOR_TEMP },
   64 };
   65 
   66 int     acpitz_match(struct device *, struct cfdata *, void *);
   67 void    acpitz_attach(struct device *, struct device *, void *);
   68 
   69 /*
   70  * ACPI Temperature Zone information. Note all temperatures are reported
   71  * in tenths of degrees Kelvin
   72  */
   73 struct acpitz_zone {
   74         /* Active cooling temperature threshold */
   75         UINT32 ac[ATZ_NLEVELS];
   76         /* Package of references to all active cooling devices for a level */
   77         ACPI_BUFFER al[ATZ_NLEVELS];
   78         /* Critical temperature threshold for system shutdown */
   79         UINT32 crt;
   80         /* Critical temperature threshold for S4 sleep */
   81         UINT32 hot;
   82         /* Package of references to processor objects for passive cooling */
   83         ACPI_BUFFER psl;
   84         /* Passive cooling temperature threshold */
   85         UINT32 psv;
   86         /* Thermal constants for use in passive cooling formulas */
   87         UINT32 tc1, tc2;
   88         /* Current temperature of the thermal zone */
   89         UINT32 tmp;
   90         /* Thermal sampling period for passive cooling, in tenths of seconds */
   91         UINT32 tsp;
   92         /* Package of references to devices in this TZ (optional) */
   93         ACPI_BUFFER tzd;
   94         /* Recommended TZ polling frequency, in tenths of seconds */
   95         UINT32 tzp;
   96 };
   97 
   98 struct acpitz_softc {
   99         struct device sc_dev;
  100         struct acpi_devnode *sc_devnode;
  101         struct acpitz_zone sc_zone;
  102         struct callout sc_callout;
  103         struct envsys_tre_data sc_data[ATZ_NUMSENSORS];
  104         struct envsys_basic_info sc_info[ATZ_NUMSENSORS];
  105         struct sysmon_envsys sc_sysmon;
  106         struct simplelock sc_slock;
  107         int sc_flags;
  108         int sc_rate;            /* tz poll rate */
  109 };
  110 
  111 void    acpitz_get_status(void *);
  112 static void     acpitz_print_status(struct acpitz_softc *);
  113 void    acpitz_notify_handler(ACPI_HANDLE, UINT32, void *);
  114 static void     acpitz_tick(void *);
  115 static void     acpitz_init_envsys(struct acpitz_softc *);
  116 static int      acpitz_gtredata(struct sysmon_envsys *,
  117                                 struct envsys_tre_data *);
  118 static int      acpitz_streinfo(struct sysmon_envsys *,
  119                                 struct envsys_basic_info *);
  120 
  121 CFATTACH_DECL(acpitz, sizeof(struct acpitz_softc), acpitz_match,
  122     acpitz_attach, NULL, NULL);
  123 
  124 /*
  125  * acpitz_match: autoconf(9) match routine
  126  */
  127 int
  128 acpitz_match(struct device *parent, struct cfdata *match, void *aux)
  129 {
  130         struct acpi_attach_args *aa = aux;
  131 
  132         if (aa->aa_node->ad_type != ACPI_TYPE_THERMAL)
  133                 return 0;
  134 
  135         return 1;
  136 }
  137 
  138 /*
  139  * acpitz_attach: autoconf(9) attach routine
  140  */
  141 void
  142 acpitz_attach(struct device *parent, struct device *self, void *aux)
  143 {
  144         struct acpitz_softc *sc = (struct acpitz_softc *)self;
  145         struct acpi_attach_args *aa = aux;
  146         ACPI_STATUS rv;
  147         ACPI_INTEGER v;
  148 
  149 #if 0
  150         sc->sc_flags = ATZ_F_VERBOSE;
  151 #endif
  152         sc->sc_devnode = aa->aa_node;
  153 
  154         printf(": ACPI Thermal Zone\n");
  155 
  156         rv = acpi_eval_integer(sc->sc_devnode->ad_handle, "_TZP", &v);
  157         if (ACPI_FAILURE(rv)) {
  158                 printf("%s: unable to get polling interval; using default of",
  159                     sc->sc_dev.dv_xname);
  160                 sc->sc_zone.tzp = ATZ_TZP_RATE;
  161         } else {
  162                 sc->sc_zone.tzp = v;
  163                 printf("%s: polling interval is", sc->sc_dev.dv_xname);
  164         }
  165         printf(" %d.%ds\n", sc->sc_zone.tzp / 10, sc->sc_zone.tsp % 10);
  166 
  167         /* XXX a value of 0 means "polling is not necessary" */
  168         if (sc->sc_zone.tzp == 0)
  169                 sc->sc_zone.tzp = ATZ_TZP_RATE;
  170         
  171         acpitz_get_status(sc);
  172 
  173         rv = AcpiInstallNotifyHandler(sc->sc_devnode->ad_handle,
  174             ACPI_SYSTEM_NOTIFY, acpitz_notify_handler, sc);
  175         if (ACPI_FAILURE(rv)) {
  176                 printf("%s: unable to install SYSTEM NOTIFY handler: %s\n",
  177                     sc->sc_dev.dv_xname, AcpiFormatException(rv));
  178                 return;
  179         }
  180 
  181         callout_init(&sc->sc_callout);
  182         callout_reset(&sc->sc_callout, (sc->sc_zone.tzp / 10) * hz,
  183             acpitz_tick, sc);
  184 
  185         acpitz_init_envsys(sc);
  186 }
  187 
  188 void
  189 acpitz_get_status(void *opaque)
  190 {
  191         struct acpitz_softc *sc = opaque;
  192         ACPI_STATUS rv;
  193         ACPI_INTEGER v;
  194 
  195         rv = acpi_eval_integer(sc->sc_devnode->ad_handle, "_TMP", &v);
  196         if (ACPI_FAILURE(rv)) {
  197                 printf("%s: failed to evaluate _TMP: %s\n",
  198                     sc->sc_dev.dv_xname, AcpiFormatException(rv));
  199                 return;
  200         }
  201         sc->sc_zone.tmp = v;
  202 
  203         /*
  204          * The temperature unit for envsys(9) is microKelvin, so convert to
  205          * that from ACPI's microKelvin. Also, the ACPI specification assumes
  206          * that K = C + 273.2 rather than the nominal 273.15 used by envsys(9),
  207          * so we correct for that too.
  208          */
  209         sc->sc_data[ATZ_SENSOR_TEMP].cur.data_us =
  210             sc->sc_zone.tmp * 100000 - 50000;
  211         sc->sc_data[ATZ_SENSOR_TEMP].validflags |= ENVSYS_FCURVALID;
  212 
  213         if (sc->sc_flags & ATZ_F_VERBOSE)
  214                 acpitz_print_status(sc);
  215 
  216         return;
  217 }
  218 
  219 static void
  220 acpitz_print_status(struct acpitz_softc *sc)
  221 {
  222 
  223         printf("%s: zone temperature is now %d K\n", sc->sc_dev.dv_xname,
  224             sc->sc_zone.tmp / 10);
  225 
  226         return;
  227 }
  228 
  229 void
  230 acpitz_notify_handler(ACPI_HANDLE hdl, UINT32 notify, void *opaque)
  231 {
  232         struct acpitz_softc *sc = opaque;
  233         int rv;
  234 
  235         switch (notify) {
  236         case ACPI_NOTIFY_ThermalZoneStatusChanged:
  237         case ACPI_NOTIFY_ThermalZoneTripPointsChanged:
  238                 rv = AcpiOsQueueForExecution(OSD_PRIORITY_LO,
  239                     acpitz_get_status, sc);
  240                 if (ACPI_FAILURE(rv)) {
  241                         printf("%s: unable to queue status check: %s\n",
  242                             sc->sc_dev.dv_xname, AcpiFormatException(rv));
  243                 }
  244                 break;
  245         default:
  246                 printf("%s: received unhandled notify message 0x%x\n",
  247                     sc->sc_dev.dv_xname, notify);
  248                 break;
  249         }
  250 
  251         return;
  252 }
  253 
  254 static void
  255 acpitz_tick(void *opaque)
  256 {
  257         struct acpitz_softc *sc = opaque;
  258 
  259         callout_reset(&sc->sc_callout, (sc->sc_zone.tzp / 10) * hz,
  260             acpitz_tick, opaque);
  261         AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpitz_get_status, sc);
  262 
  263         return;
  264 }
  265 
  266 static void
  267 acpitz_init_envsys(struct acpitz_softc *sc)
  268 {
  269         int i;
  270 
  271         simple_lock_init(&sc->sc_slock);
  272 
  273         for (i = 0; i < ATZ_NUMSENSORS; i++) {
  274                 sc->sc_data[i].sensor = sc->sc_info[i].sensor = i;
  275                 sc->sc_data[i].validflags = ENVSYS_FVALID;
  276                 sc->sc_info[i].validflags = ENVSYS_FVALID;
  277                 sc->sc_data[i].warnflags = ENVSYS_WARN_OK;
  278         }
  279 #define INITDATA(index, unit, string) \
  280         sc->sc_data[index].units = unit;                                   \
  281         sc->sc_info[index].units = unit;                                   \
  282         snprintf(sc->sc_info[index].desc, sizeof(sc->sc_info[index].desc), \
  283             "%s %s", sc->sc_dev.dv_xname, string);
  284 
  285         INITDATA(ATZ_SENSOR_TEMP, ENVSYS_STEMP, "temperature");
  286 
  287         /* hook into sysmon */
  288         sc->sc_sysmon.sme_ranges = acpitz_ranges;
  289         sc->sc_sysmon.sme_sensor_info = sc->sc_info;
  290         sc->sc_sysmon.sme_sensor_data = sc->sc_data;
  291         sc->sc_sysmon.sme_cookie = sc;
  292         sc->sc_sysmon.sme_gtredata = acpitz_gtredata;
  293         sc->sc_sysmon.sme_streinfo = acpitz_streinfo;
  294         sc->sc_sysmon.sme_nsensors = ATZ_NUMSENSORS;
  295         sc->sc_sysmon.sme_envsys_version = 1000;
  296 
  297         if (sysmon_envsys_register(&sc->sc_sysmon))
  298                 printf("%s: unable to register with sysmon\n",
  299                     sc->sc_dev.dv_xname);
  300 }
  301 
  302 int
  303 acpitz_gtredata(struct sysmon_envsys *sme, struct envsys_tre_data *tred)
  304 {
  305         struct acpitz_softc *sc = sme->sme_cookie;
  306 
  307         simple_lock(&sc->sc_slock);
  308 
  309         *tred = sc->sc_data[tred->sensor];
  310 
  311         simple_unlock(&sc->sc_slock);
  312 
  313         return 0;
  314 }
  315 
  316 int
  317 acpitz_streinfo(struct sysmon_envsys *sme, struct envsys_basic_info *binfo)
  318 {
  319 
  320         /* XXX not implemented */
  321         binfo->validflags = 0;
  322 
  323         return 0;
  324 }

Cache object: c5558073c0e1f0deda4b24843ebafd7f


[ 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.