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/hpc/hpcapm.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: hpcapm.c,v 1.13 2007/10/19 11:59:42 ad Exp $   */
    2 
    3 /*
    4  * Copyright (c) 2000 Takemura Shin
    5  * Copyright (c) 2000-2001 SATO Kazumi
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __KERNEL_RCSID(0, "$NetBSD: hpcapm.c,v 1.13 2007/10/19 11:59:42 ad Exp $");
   33 
   34 #ifdef _KERNEL_OPT
   35 #include "opt_hpcapm.h"
   36 #endif
   37 
   38 #include <sys/param.h>
   39 #include <sys/device.h>
   40 #include <sys/kernel.h>
   41 #include <sys/systm.h>
   42 
   43 #include <dev/hpc/apm/apmvar.h>
   44 
   45 #include <sys/bus.h>
   46 #include <machine/config_hook.h>
   47 #include <machine/platid.h>
   48 #include <machine/platid_mask.h>
   49 
   50 #ifdef HPCAPMDEBUG
   51 #ifndef HPCAPMDEBUG_CONF
   52 #define HPCAPMDEBUG_CONF 1
   53 #endif
   54 int     hpcapm_debug = HPCAPMDEBUG_CONF;
   55 #define DPRINTF(arg)     do { if (hpcapm_debug) printf arg; } while(0);
   56 #define DPRINTFN(n, arg) do { if (hpcapm_debug > (n)) printf arg; } while (0);
   57 #else
   58 #define DPRINTF(arg)     do { } while (0);
   59 #define DPRINTFN(n, arg) do { } while (0);
   60 #endif
   61 
   62 /* Definition of the driver for autoconfig. */
   63 static int      hpcapm_match(struct device *, struct cfdata *, void *);
   64 static void     hpcapm_attach(struct device *, struct device *, void *);
   65 static int      hpcapm_hook(void *, int, long, void *);
   66 
   67 static void     hpcapm_disconnect(void *);
   68 static void     hpcapm_enable(void *, int);
   69 static int      hpcapm_set_powstate(void *, u_int, u_int);
   70 static int      hpcapm_get_powstat(void *, struct apm_power_info *);
   71 static int      hpcapm_get_event(void *, u_int *, u_int *);
   72 static void     hpcapm_cpu_busy(void *);
   73 static void     hpcapm_cpu_idle(void *);
   74 static void     hpcapm_get_capabilities(void *, u_int *, u_int *);
   75 
   76 struct apmhpc_softc {
   77         struct device sc_dev;
   78         void *sc_apmdev;
   79         volatile unsigned int events;
   80         volatile int power_state;
   81         volatile int battery_state;
   82         volatile int ac_state;
   83         config_hook_tag sc_standby_hook;
   84         config_hook_tag sc_suspend_hook;
   85         config_hook_tag sc_battery_hook;
   86         config_hook_tag sc_ac_hook;
   87         int battery_life;
   88         int minutes_left;
   89 };
   90 
   91 CFATTACH_DECL(hpcapm, sizeof (struct apmhpc_softc),
   92     hpcapm_match, hpcapm_attach, NULL, NULL);
   93 
   94 struct apm_accessops hpcapm_accessops = {
   95         hpcapm_disconnect,
   96         hpcapm_enable,
   97         hpcapm_set_powstate,
   98         hpcapm_get_powstat,
   99         hpcapm_get_event,
  100         hpcapm_cpu_busy,
  101         hpcapm_cpu_idle,
  102         hpcapm_get_capabilities,
  103 };
  104 
  105 extern struct cfdriver hpcapm_cd;
  106 
  107 static int
  108 hpcapm_match(struct device *parent,
  109              struct cfdata *cf, void *aux)
  110 {
  111 
  112         return 1;
  113 }
  114 
  115 static void
  116 hpcapm_attach(struct device *parent,
  117               struct device *self, void *aux)
  118 {
  119         struct apmhpc_softc *sc;
  120         struct apmdev_attach_args aaa;
  121 
  122         sc = device_private(self);
  123         printf(": pseudo power management module\n");
  124 
  125         sc->events = 0;
  126         sc->power_state = APM_SYS_READY;
  127         sc->battery_state = APM_BATT_FLAG_UNKNOWN;
  128         sc->ac_state = APM_AC_UNKNOWN;
  129         sc->battery_life = APM_BATT_LIFE_UNKNOWN;
  130         sc->minutes_left = 0;
  131         sc->sc_standby_hook = config_hook(CONFIG_HOOK_PMEVENT,
  132                                           CONFIG_HOOK_PMEVENT_STANDBYREQ,
  133                                           CONFIG_HOOK_EXCLUSIVE,
  134                                           hpcapm_hook, sc);
  135         sc->sc_suspend_hook = config_hook(CONFIG_HOOK_PMEVENT,
  136                                           CONFIG_HOOK_PMEVENT_SUSPENDREQ,
  137                                           CONFIG_HOOK_EXCLUSIVE,
  138                                           hpcapm_hook, sc);
  139 
  140         sc->sc_battery_hook = config_hook(CONFIG_HOOK_PMEVENT,
  141                                           CONFIG_HOOK_PMEVENT_BATTERY,
  142                                           CONFIG_HOOK_SHARE,
  143                                           hpcapm_hook, sc);
  144 
  145         sc->sc_ac_hook = config_hook(CONFIG_HOOK_PMEVENT,
  146                                      CONFIG_HOOK_PMEVENT_AC,
  147                                      CONFIG_HOOK_SHARE,
  148                                      hpcapm_hook, sc);
  149 
  150         aaa.accessops = &hpcapm_accessops;
  151         aaa.accesscookie = sc;
  152         aaa.apm_detail = 0x0102;
  153 
  154         sc->sc_apmdev = config_found_ia(self, "apmdevif", &aaa, apmprint);
  155 }
  156 
  157 static int
  158 hpcapm_hook(void *ctx, int type, long id, void *msg)
  159 {
  160         struct apmhpc_softc *sc;
  161         int s;
  162         int charge;
  163         int message;
  164 
  165         sc = ctx;
  166 
  167         if (type != CONFIG_HOOK_PMEVENT)
  168                 return 1;
  169 
  170         if (CONFIG_HOOK_VALUEP(msg))
  171                 message = (int)msg;
  172         else
  173                 message = *(int *)msg;
  174 
  175         s = splhigh();
  176         switch (id) {
  177         case CONFIG_HOOK_PMEVENT_STANDBYREQ:
  178                 if (sc->power_state != APM_SYS_STANDBY) {
  179                         sc->events |= (1 << APM_USER_STANDBY_REQ);
  180                 } else {
  181                         sc->events |= (1 << APM_NORMAL_RESUME);
  182                 }
  183                 break;
  184         case CONFIG_HOOK_PMEVENT_SUSPENDREQ:
  185                 if (sc->power_state != APM_SYS_SUSPEND) {
  186                         DPRINTF(("hpcapm: suspend request\n"));
  187                         sc->events |= (1 << APM_USER_SUSPEND_REQ);
  188                 } else {
  189                         sc->events |= (1 << APM_NORMAL_RESUME);
  190                 }
  191                 break;
  192         case CONFIG_HOOK_PMEVENT_BATTERY:
  193                 switch (message) {
  194                 case CONFIG_HOOK_BATT_CRITICAL:
  195                         DPRINTF(("hpcapm: battery state critical\n"));
  196                         charge = sc->battery_state & APM_BATT_FLAG_CHARGING;
  197                         sc->battery_state = APM_BATT_FLAG_CRITICAL;
  198                         sc->battery_state |= charge;
  199                         sc->battery_life = 0;
  200                         break;
  201                 case CONFIG_HOOK_BATT_LOW:
  202                         DPRINTF(("hpcapm: battery state low\n"));
  203                         charge = sc->battery_state & APM_BATT_FLAG_CHARGING;
  204                         sc->battery_state = APM_BATT_FLAG_LOW;
  205                         sc->battery_state |= charge;
  206                         break;
  207                 case CONFIG_HOOK_BATT_HIGH:
  208                         DPRINTF(("hpcapm: battery state high\n"));
  209                         charge = sc->battery_state & APM_BATT_FLAG_CHARGING;
  210                         sc->battery_state = APM_BATT_FLAG_HIGH;
  211                         sc->battery_state |= charge;
  212                         break;
  213                 case CONFIG_HOOK_BATT_10P:
  214                         DPRINTF(("hpcapm: battery life 10%%\n"));
  215                         sc->battery_life = 10;
  216                         break;
  217                 case CONFIG_HOOK_BATT_20P:
  218                         DPRINTF(("hpcapm: battery life 20%%\n"));
  219                         sc->battery_life = 20;
  220                         break;
  221                 case CONFIG_HOOK_BATT_30P:
  222                         DPRINTF(("hpcapm: battery life 30%%\n"));
  223                         sc->battery_life = 30;
  224                         break;
  225                 case CONFIG_HOOK_BATT_40P:
  226                         DPRINTF(("hpcapm: battery life 40%%\n"));
  227                         sc->battery_life = 40;
  228                         break;
  229                 case CONFIG_HOOK_BATT_50P:
  230                         DPRINTF(("hpcapm: battery life 50%%\n"));
  231                         sc->battery_life = 50;
  232                         break;
  233                 case CONFIG_HOOK_BATT_60P:
  234                         DPRINTF(("hpcapm: battery life 60%%\n"));
  235                         sc->battery_life = 60;
  236                         break;
  237                 case CONFIG_HOOK_BATT_70P:
  238                         DPRINTF(("hpcapm: battery life 70%%\n"));
  239                         sc->battery_life = 70;
  240                         break;
  241                 case CONFIG_HOOK_BATT_80P:
  242                         DPRINTF(("hpcapm: battery life 80%%\n"));
  243                         sc->battery_life = 80;
  244                         break;
  245                 case CONFIG_HOOK_BATT_90P:
  246                         DPRINTF(("hpcapm: battery life 90%%\n"));
  247                         sc->battery_life = 90;
  248                         break;
  249                 case CONFIG_HOOK_BATT_100P:
  250                         DPRINTF(("hpcapm: battery life 100%%\n"));
  251                         sc->battery_life = 100;
  252                         break;
  253                 case CONFIG_HOOK_BATT_UNKNOWN:
  254                         DPRINTF(("hpcapm: battery state unknown\n"));
  255                         sc->battery_state = APM_BATT_FLAG_UNKNOWN;
  256                         sc->battery_life = APM_BATT_LIFE_UNKNOWN;
  257                         break;
  258                 case CONFIG_HOOK_BATT_NO_SYSTEM_BATTERY:
  259                         DPRINTF(("hpcapm: battery state no system battery?\n"));
  260                         sc->battery_state = APM_BATT_FLAG_NO_SYSTEM_BATTERY;
  261                         sc->battery_life = APM_BATT_LIFE_UNKNOWN;
  262                         break;
  263                 }
  264                 break;
  265         case CONFIG_HOOK_PMEVENT_AC:
  266                 switch (message) {
  267                 case CONFIG_HOOK_AC_OFF:
  268                         DPRINTF(("hpcapm: ac not connected\n"));
  269                         sc->battery_state &= ~APM_BATT_FLAG_CHARGING;
  270                         sc->ac_state = APM_AC_OFF;
  271                         break;
  272                 case CONFIG_HOOK_AC_ON_CHARGE:
  273                         DPRINTF(("hpcapm: charging\n"));
  274                         sc->battery_state |= APM_BATT_FLAG_CHARGING;
  275                         sc->ac_state = APM_AC_ON;
  276                         break;
  277                 case CONFIG_HOOK_AC_ON_NOCHARGE:
  278                         DPRINTF(("hpcapm: ac connected\n"));
  279                         sc->battery_state &= ~APM_BATT_FLAG_CHARGING;
  280                         sc->ac_state = APM_AC_ON;
  281                         break;
  282                 case CONFIG_HOOK_AC_UNKNOWN:
  283                         sc->ac_state = APM_AC_UNKNOWN;
  284                         break;
  285                 }
  286                 break;
  287         }
  288         splx(s);
  289 
  290         return (0);
  291 }
  292 
  293 static void
  294 hpcapm_disconnect(void *scx)
  295 {
  296         struct apmhpc_softc *sc;
  297 
  298         sc = scx;
  299 }
  300 
  301 static void
  302 hpcapm_enable(void *scx, int onoff)
  303 {
  304         struct apmhpc_softc *sc;
  305 
  306         sc = scx;
  307 }
  308 
  309 static int
  310 hpcapm_set_powstate(void *scx, u_int devid, u_int powstat)
  311 {
  312         struct apmhpc_softc *sc;
  313         int s;
  314 
  315         sc = scx;
  316 
  317         if (devid != APM_DEV_ALLDEVS)
  318                 return APM_ERR_UNRECOG_DEV;
  319 
  320         switch (powstat) {
  321         case APM_SYS_READY:
  322                 DPRINTF(("hpcapm: set power state READY\n"));
  323                 sc->power_state = APM_SYS_READY;
  324                 break;
  325         case APM_SYS_STANDBY:
  326                 DPRINTF(("hpcapm: set power state STANDBY\n"));
  327                 s = splhigh();
  328                 config_hook_call(CONFIG_HOOK_PMEVENT,
  329                                  CONFIG_HOOK_PMEVENT_HARDPOWER,
  330                                  (void *)PWR_STANDBY);
  331                 sc->power_state = APM_SYS_STANDBY;
  332                 machine_standby();
  333                 config_hook_call_reverse(CONFIG_HOOK_PMEVENT,
  334                     CONFIG_HOOK_PMEVENT_HARDPOWER,
  335                     (void *)PWR_RESUME);
  336                 DPRINTF(("hpcapm: resume\n"));
  337                 splx(s);
  338                 break;
  339         case APM_SYS_SUSPEND:
  340                 DPRINTF(("hpcapm: set power state SUSPEND...\n"));
  341                 s = splhigh();
  342                 config_hook_call(CONFIG_HOOK_PMEVENT,
  343                     CONFIG_HOOK_PMEVENT_HARDPOWER,
  344                     (void *)PWR_SUSPEND);
  345                 sc->power_state = APM_SYS_SUSPEND;
  346                 machine_sleep();
  347                 config_hook_call_reverse(CONFIG_HOOK_PMEVENT,
  348                                  CONFIG_HOOK_PMEVENT_HARDPOWER,
  349                                  (void *)PWR_RESUME);
  350                 DPRINTF(("hpcapm: resume\n"));
  351                 splx(s);
  352                 break;
  353         case APM_SYS_OFF:
  354                 DPRINTF(("hpcapm: set power state OFF\n"));
  355                 sc->power_state = APM_SYS_OFF;
  356                 break;
  357         case APM_LASTREQ_INPROG:
  358                 /*DPRINTF(("hpcapm: set power state INPROG\n"));
  359                  */
  360                 break;
  361         case APM_LASTREQ_REJECTED:
  362                 DPRINTF(("hpcapm: set power state REJECTED\n"));
  363                 break;
  364         }
  365 
  366         return (0);
  367 }
  368 
  369 static int
  370 hpcapm_get_powstat(void *scx, struct apm_power_info *pinfo)
  371 {
  372         struct apmhpc_softc *sc;
  373         int val;
  374 
  375         sc = scx;
  376 
  377         if (config_hook_call(CONFIG_HOOK_GET,
  378                              CONFIG_HOOK_ACADAPTER, &val) != -1)
  379                 pinfo->ac_state = val;
  380         else
  381                 pinfo->ac_state = sc->ac_state;
  382         if (config_hook_call(CONFIG_HOOK_GET,
  383                              CONFIG_HOOK_CHARGE, &val) != -1)
  384                 pinfo->battery_state = val;
  385         else
  386                 pinfo->battery_state = sc->battery_state;
  387         if (config_hook_call(CONFIG_HOOK_GET,
  388                              CONFIG_HOOK_BATTERYVAL, &val) != -1)
  389                 pinfo->battery_life = val;
  390         else
  391                 pinfo->battery_life = sc->battery_life;
  392         return (0);
  393 }
  394 
  395 static int
  396 hpcapm_get_event(void *scx, u_int *event_type, u_int *event_info)
  397 {
  398         struct apmhpc_softc *sc;
  399         int s, i;
  400 
  401         sc = scx;
  402         s = splhigh();
  403         for (i = APM_STANDBY_REQ; i <= APM_CAP_CHANGE; i++) {
  404                 if (sc->events & (1 << i)) {
  405                         sc->events &= ~(1 << i);
  406                         *event_type = i;
  407                         if (*event_type == APM_NORMAL_RESUME ||
  408                             *event_type == APM_CRIT_RESUME) {
  409                                 /* pccard power off in the suspend state */
  410                                 *event_info = 1;
  411                                 sc->power_state = APM_SYS_READY;
  412                         } else
  413                                 *event_info = 0;
  414                         return (0);
  415                 }
  416         }
  417         splx(s);
  418 
  419         return APM_ERR_NOEVENTS;
  420 }
  421 
  422 static void
  423 hpcapm_cpu_busy(void *scx)
  424 {
  425         struct apmhpc_softc *sc;
  426 
  427         sc = scx;
  428 }
  429 
  430 static void
  431 hpcapm_cpu_idle(void *scx)
  432 {
  433         struct apmhpc_softc *sc;
  434 
  435         sc = scx;
  436 }
  437 
  438 static void
  439 hpcapm_get_capabilities(void *scx, u_int *numbatts, u_int *capflags)
  440 {
  441         struct apmhpc_softc *sc;
  442 
  443         *numbatts = 0;
  444         *capflags = APM_GLOBAL_STANDBY | APM_GLOBAL_SUSPEND;
  445 
  446         sc = scx;
  447 }

Cache object: 753402091ec69119b9b84dfb74d5d056


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