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/i386/acpica/acpi_machdep.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 /*-
    2  * Copyright (c) 2001 Mitsuru IWASAKI
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/5.3/sys/i386/acpica/acpi_machdep.c 132619 2004-07-24 22:41:30Z njl $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/bus.h>
   32 #include <sys/conf.h>
   33 #include <sys/fcntl.h>
   34 #include <sys/kernel.h>
   35 #include <sys/sysctl.h>
   36 #include <sys/uio.h>
   37 #include <vm/vm.h>
   38 #include <vm/pmap.h>
   39 
   40 #include "acpi.h"
   41 #include <dev/acpica/acpivar.h>
   42 #include <dev/acpica/acpiio.h>
   43 
   44 /*
   45  * APM driver emulation 
   46  */
   47 
   48 #include <sys/selinfo.h>
   49 
   50 #include <machine/apm_bios.h>
   51 #include <machine/pc/bios.h>
   52 
   53 #include <i386/bios/apm.h>
   54 
   55 uint32_t acpi_reset_video = 1;
   56 TUNABLE_INT("hw.acpi.reset_video", &acpi_reset_video);
   57 
   58 static int intr_model = ACPI_INTR_PIC;
   59 static int apm_active;
   60 
   61 static d_open_t apmopen;
   62 static d_close_t apmclose;
   63 static d_write_t apmwrite;
   64 static d_ioctl_t apmioctl;
   65 static d_poll_t apmpoll;
   66 
   67 static struct cdevsw apm_cdevsw = {
   68         .d_version =    D_VERSION,
   69         .d_flags =      D_NEEDGIANT,
   70         .d_open =       apmopen,
   71         .d_close =      apmclose,
   72         .d_write =      apmwrite,
   73         .d_ioctl =      apmioctl,
   74         .d_poll =       apmpoll,
   75         .d_name =       "apm",
   76 };
   77 
   78 static int
   79 acpi_capm_convert_battstate(struct  acpi_battinfo *battp)
   80 {
   81         int     state;
   82 
   83         state = APM_UNKNOWN;
   84 
   85         if (battp->state & ACPI_BATT_STAT_DISCHARG) {
   86                 if (battp->cap >= 50)
   87                         state = 0;      /* high */
   88                 else
   89                         state = 1;      /* low */
   90         }
   91         if (battp->state & ACPI_BATT_STAT_CRITICAL)
   92                 state = 2;              /* critical */
   93         if (battp->state & ACPI_BATT_STAT_CHARGING)
   94                 state = 3;              /* charging */
   95 
   96         /* If still unknown, determine it based on the battery capacity. */
   97         if (state == APM_UNKNOWN) {
   98                 if (battp->cap >= 50)
   99                         state = 0;      /* high */
  100                 else
  101                         state = 1;      /* low */
  102         }
  103 
  104         return (state);
  105 }
  106 
  107 static int
  108 acpi_capm_convert_battflags(struct  acpi_battinfo *battp)
  109 {
  110         int     flags;
  111 
  112         flags = 0;
  113 
  114         if (battp->cap >= 50)
  115                 flags |= APM_BATT_HIGH;
  116         else {
  117                 if (battp->state & ACPI_BATT_STAT_CRITICAL)
  118                         flags |= APM_BATT_CRITICAL;
  119                 else
  120                         flags |= APM_BATT_LOW;
  121         }
  122         if (battp->state & ACPI_BATT_STAT_CHARGING)
  123                 flags |= APM_BATT_CHARGING;
  124         if (battp->state == ACPI_BATT_STAT_NOT_PRESENT)
  125                 flags = APM_BATT_NOT_PRESENT;
  126 
  127         return (flags);
  128 }
  129 
  130 static int
  131 acpi_capm_get_info(apm_info_t aip)
  132 {
  133         int     acline;
  134         struct  acpi_battinfo batt;
  135 
  136         aip->ai_infoversion = 1;
  137         aip->ai_major       = 1;
  138         aip->ai_minor       = 2;
  139         aip->ai_status      = apm_active;
  140         aip->ai_capabilities= 0xff00;   /* unknown */
  141 
  142         if (acpi_acad_get_acline(&acline))
  143                 aip->ai_acline = APM_UNKNOWN;   /* unknown */
  144         else
  145                 aip->ai_acline = acline;        /* on/off */
  146 
  147         if (acpi_battery_get_battinfo(-1, &batt)) {
  148                 aip->ai_batt_stat = APM_UNKNOWN;
  149                 aip->ai_batt_life = APM_UNKNOWN;
  150                 aip->ai_batt_time = -1;          /* unknown */
  151                 aip->ai_batteries = ~0U;         /* unknown */
  152         } else {
  153                 aip->ai_batt_stat = acpi_capm_convert_battstate(&batt);
  154                 aip->ai_batt_life = batt.cap;
  155                 aip->ai_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
  156                 aip->ai_batteries = acpi_battery_get_units();
  157         }
  158 
  159         return (0);
  160 }
  161 
  162 static int
  163 acpi_capm_get_pwstatus(apm_pwstatus_t app)
  164 {
  165         int     batt_unit;
  166         int     acline;
  167         struct  acpi_battinfo batt;
  168 
  169         if (app->ap_device != PMDV_ALLDEV &&
  170             (app->ap_device < PMDV_BATT0 || app->ap_device > PMDV_BATT_ALL))
  171                 return (1);
  172 
  173         if (app->ap_device == PMDV_ALLDEV)
  174                 batt_unit = -1;                 /* all units */
  175         else
  176                 batt_unit = app->ap_device - PMDV_BATT0;
  177 
  178         if (acpi_battery_get_battinfo(batt_unit, &batt))
  179                 return (1);
  180 
  181         app->ap_batt_stat = acpi_capm_convert_battstate(&batt);
  182         app->ap_batt_flag = acpi_capm_convert_battflags(&batt);
  183         app->ap_batt_life = batt.cap;
  184         app->ap_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
  185 
  186         if (acpi_acad_get_acline(&acline))
  187                 app->ap_acline = APM_UNKNOWN;
  188         else
  189                 app->ap_acline = acline;        /* on/off */
  190 
  191         return (0);
  192 }
  193 
  194 static int
  195 apmopen(struct cdev *dev, int flag, int fmt, d_thread_t *td)
  196 {
  197         return (0);
  198 }
  199 
  200 static int
  201 apmclose(struct cdev *dev, int flag, int fmt, d_thread_t *td)
  202 {
  203         return (0);
  204 }
  205 
  206 static int
  207 apmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, d_thread_t *td)
  208 {
  209         int     error = 0;
  210         struct  acpi_softc *acpi_sc;
  211         struct apm_info info;
  212         apm_info_old_t aiop;
  213 
  214         acpi_sc = devclass_get_softc(devclass_find("acpi"), 0);
  215 
  216         switch (cmd) {
  217         case APMIO_SUSPEND:
  218                 if ((flag & FWRITE) == 0)
  219                         return (EPERM);
  220                 if (apm_active)
  221                         acpi_SetSleepState(acpi_sc, acpi_sc->acpi_suspend_sx);
  222                 else
  223                         error = EINVAL;
  224                 break;
  225         case APMIO_STANDBY:
  226                 if ((flag & FWRITE) == 0)
  227                         return (EPERM);
  228                 if (apm_active)
  229                         acpi_SetSleepState(acpi_sc, acpi_sc->acpi_standby_sx);
  230                 else
  231                         error = EINVAL;
  232                 break;
  233         case APMIO_GETINFO_OLD:
  234                 if (acpi_capm_get_info(&info))
  235                         error = ENXIO;
  236                 aiop = (apm_info_old_t)addr;
  237                 aiop->ai_major = info.ai_major;
  238                 aiop->ai_minor = info.ai_minor;
  239                 aiop->ai_acline = info.ai_acline;
  240                 aiop->ai_batt_stat = info.ai_batt_stat;
  241                 aiop->ai_batt_life = info.ai_batt_life;
  242                 aiop->ai_status = info.ai_status;
  243                 break;
  244         case APMIO_GETINFO:
  245                 if (acpi_capm_get_info((apm_info_t)addr))
  246                         error = ENXIO;
  247                 break;
  248         case APMIO_GETPWSTATUS:
  249                 if (acpi_capm_get_pwstatus((apm_pwstatus_t)addr))
  250                         error = ENXIO;
  251                 break;
  252         case APMIO_ENABLE:
  253                 if ((flag & FWRITE) == 0)
  254                         return (EPERM);
  255                 apm_active = 1;
  256                 break;
  257         case APMIO_DISABLE:
  258                 if ((flag & FWRITE) == 0)
  259                         return (EPERM);
  260                 apm_active = 0;
  261                 break;
  262         case APMIO_HALTCPU:
  263                 break;
  264         case APMIO_NOTHALTCPU:
  265                 break;
  266         case APMIO_DISPLAY:
  267                 if ((flag & FWRITE) == 0)
  268                         return (EPERM);
  269                 break;
  270         case APMIO_BIOS:
  271                 if ((flag & FWRITE) == 0)
  272                         return (EPERM);
  273                 bzero(addr, sizeof(struct apm_bios_arg));
  274                 break;
  275         default:
  276                 error = EINVAL;
  277                 break;
  278         }
  279 
  280         return (error);
  281 }
  282 
  283 static int
  284 apmwrite(struct cdev *dev, struct uio *uio, int ioflag)
  285 {
  286         return (uio->uio_resid);
  287 }
  288 
  289 static int
  290 apmpoll(struct cdev *dev, int events, d_thread_t *td)
  291 {
  292         return (0);
  293 }
  294 
  295 static void
  296 acpi_capm_init(struct acpi_softc *sc)
  297 {
  298         make_dev(&apm_cdevsw, 0, 0, 5, 0664, "apm");
  299 }
  300 
  301 int
  302 acpi_machdep_init(device_t dev)
  303 {
  304         struct  acpi_softc *sc;
  305 
  306         sc = devclass_get_softc(devclass_find("acpi"), 0);
  307         acpi_capm_init(sc);
  308 
  309         acpi_install_wakeup_handler(sc);
  310 
  311         if (intr_model == ACPI_INTR_PIC)
  312                 BUS_CONFIG_INTR(dev, AcpiGbl_FADT->SciInt, INTR_TRIGGER_LEVEL,
  313                     INTR_POLARITY_LOW);
  314         else
  315                 acpi_SetIntrModel(intr_model);
  316 
  317         SYSCTL_ADD_UINT(&sc->acpi_sysctl_ctx,
  318             SYSCTL_CHILDREN(sc->acpi_sysctl_tree), OID_AUTO,
  319             "reset_video", CTLFLAG_RD | CTLFLAG_RW, &acpi_reset_video, 0,
  320             "Call the VESA reset BIOS vector on the resume path");
  321 
  322         return (0);
  323 }
  324 
  325 void
  326 acpi_SetDefaultIntrModel(int model)
  327 {
  328 
  329         intr_model = model;
  330 }
  331 
  332 /* Check BIOS date.  If 1998 or older, disable ACPI. */
  333 int
  334 acpi_machdep_quirks(int *quirks)
  335 {
  336     char *va;
  337     int year;
  338 
  339     /* BIOS address 0xffff5 contains the date in the format mm/dd/yy. */
  340     va = pmap_mapdev(0xffff0, 16);
  341     sscanf(va + 11, "%2d", &year);
  342     pmap_unmapdev((vm_offset_t)va, 16);
  343 
  344     /* 
  345      * Date must be >= 1/1/1999 or we don't trust ACPI.  Note that this
  346      * check must be changed by my 114th birthday.
  347      */
  348     if (year > 90 && year < 99)
  349         *quirks = ACPI_Q_BROKEN;
  350 
  351     return (0);
  352 }

Cache object: 64624662aefd2e9244a7ebc7b1a4c016


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