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.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.c,v 1.59.2.3 2004/06/14 03:18:58 jmc Exp $        */
    2 
    3 /*-
    4  * Copyright (c) 2003 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Charles M. Hannum of By Noon Software, Inc.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * Copyright 2001, 2003 Wasabi Systems, Inc.
   41  * All rights reserved.
   42  *
   43  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
   44  *
   45  * Redistribution and use in source and binary forms, with or without
   46  * modification, are permitted provided that the following conditions
   47  * are met:
   48  * 1. Redistributions of source code must retain the above copyright
   49  *    notice, this list of conditions and the following disclaimer.
   50  * 2. Redistributions in binary form must reproduce the above copyright
   51  *    notice, this list of conditions and the following disclaimer in the
   52  *    documentation and/or other materials provided with the distribution.
   53  * 3. All advertising materials mentioning features or use of this software
   54  *    must display the following acknowledgement:
   55  *      This product includes software developed for the NetBSD Project by
   56  *      Wasabi Systems, Inc.
   57  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
   58  *    or promote products derived from this software without specific prior
   59  *    written permission.
   60  *
   61  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
   62  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   63  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   64  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
   65  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   66  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   67  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   68  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   69  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   70  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   71  * POSSIBILITY OF SUCH DAMAGE.
   72  */
   73 
   74 /*
   75  * Autoconfiguration support for the Intel ACPI Component Architecture
   76  * ACPI reference implementation.
   77  */
   78 
   79 #include <sys/cdefs.h>
   80 __KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.59.2.3 2004/06/14 03:18:58 jmc Exp $");
   81 
   82 #include "opt_acpi.h"
   83 
   84 #include <sys/param.h>
   85 #include <sys/systm.h>
   86 #include <sys/device.h>
   87 #include <sys/malloc.h>
   88 #include <sys/kernel.h>
   89 #include <sys/proc.h>
   90 
   91 #include <dev/acpi/acpica.h>
   92 #include <dev/acpi/acpireg.h>
   93 #include <dev/acpi/acpivar.h>
   94 #include <dev/acpi/acpi_osd.h>
   95 #ifdef ACPIVERBOSE
   96 #include <dev/acpi/acpidevs_data.h>
   97 #endif
   98 
   99 #ifdef ACPI_PCI_FIXUP
  100 #include <dev/pci/pcidevs.h>
  101 #endif
  102 
  103 MALLOC_DECLARE(M_ACPI);
  104 
  105 #include <machine/acpi_machdep.h>
  106 
  107 #ifdef ACPI_DEBUGGER
  108 #define ACPI_DBGR_INIT          0x01
  109 #define ACPI_DBGR_TABLES        0x02
  110 #define ACPI_DBGR_ENABLE        0x04
  111 #define ACPI_DBGR_PROBE         0x08
  112 #define ACPI_DBGR_RUNNING       0x10
  113 
  114 int     acpi_dbgr = 0x00;
  115 #endif
  116 
  117 int     acpi_match(struct device *, struct cfdata *, void *);
  118 void    acpi_attach(struct device *, struct device *, void *);
  119 
  120 int     acpi_print(void *aux, const char *);
  121 
  122 extern struct cfdriver acpi_cd;
  123 
  124 CFATTACH_DECL(acpi, sizeof(struct acpi_softc),
  125     acpi_match, acpi_attach, NULL, NULL);
  126 
  127 /*
  128  * This is a flag we set when the ACPI subsystem is active.  Machine
  129  * dependent code may wish to skip other steps (such as attaching
  130  * subsystems that ACPI supercedes) when ACPI is active.
  131  */
  132 int     acpi_active;
  133 
  134 /*
  135  * Pointer to the ACPI subsystem's state.  There can be only
  136  * one ACPI instance.
  137  */
  138 struct acpi_softc *acpi_softc;
  139 
  140 /*
  141  * Locking stuff.
  142  */
  143 static struct simplelock acpi_slock;
  144 static int acpi_locked;
  145 
  146 /*
  147  * Prototypes.
  148  */
  149 void            acpi_shutdown(void *);
  150 ACPI_STATUS     acpi_disable(struct acpi_softc *sc);
  151 void            acpi_build_tree(struct acpi_softc *);
  152 ACPI_STATUS     acpi_make_devnode(ACPI_HANDLE, UINT32, void *, void **);
  153 
  154 void            acpi_enable_fixed_events(struct acpi_softc *);
  155 #ifdef ACPI_PCI_FIXUP
  156 void            acpi_pci_fixup(struct acpi_softc *);
  157 #endif
  158 #if defined(ACPI_PCI_FIXUP) || defined(ACPI_ACTIVATE_DEV)
  159 ACPI_STATUS     acpi_allocate_resources(ACPI_HANDLE handle);
  160 #endif
  161 
  162 /*
  163  * acpi_probe:
  164  *
  165  *      Probe for ACPI support.  This is called by the
  166  *      machine-dependent ACPI front-end.  All of the
  167  *      actual work is done by ACPICA.
  168  *
  169  *      NOTE: This is not an autoconfiguration interface function.
  170  */
  171 int
  172 acpi_probe(void)
  173 {
  174         static int beenhere;
  175         ACPI_STATUS rv;
  176 
  177         if (beenhere != 0)
  178                 panic("acpi_probe: ACPI has already been probed");
  179         beenhere = 1;
  180 
  181         simple_lock_init(&acpi_slock);
  182         acpi_locked = 0;
  183 
  184         /*
  185          * Start up ACPICA.
  186          */
  187 #ifdef ACPI_DEBUGGER
  188         if (acpi_dbgr & ACPI_DBGR_INIT)
  189                 acpi_osd_debugger();
  190 #endif
  191 
  192         rv = AcpiInitializeSubsystem();
  193         if (ACPI_FAILURE(rv)) {
  194                 printf("ACPI: unable to initialize ACPICA: %s\n",
  195                     AcpiFormatException(rv));
  196                 return (0);
  197         }
  198 
  199 #ifdef ACPI_DEBUGGER
  200         if (acpi_dbgr & ACPI_DBGR_TABLES)
  201                 acpi_osd_debugger();
  202 #endif
  203 
  204         rv = AcpiLoadTables();
  205         if (ACPI_FAILURE(rv)) {
  206                 printf("ACPI: unable to load tables: %s\n",
  207                     AcpiFormatException(rv));
  208                 return (0);
  209         }
  210 
  211         /*
  212          * Looks like we have ACPI!
  213          */
  214 
  215         return (1);
  216 }
  217 
  218 /*
  219  * acpi_match:
  220  *
  221  *      Autoconfiguration `match' routine.
  222  */
  223 int
  224 acpi_match(struct device *parent, struct cfdata *match, void *aux)
  225 {
  226         struct acpibus_attach_args *aa = aux;
  227 
  228         if (strcmp(aa->aa_busname, acpi_cd.cd_name) != 0)
  229                 return (0);
  230 
  231         /*
  232          * XXX Check other locators?  Hard to know -- machine
  233          * dependent code has already checked for the presence
  234          * of ACPI by calling acpi_probe(), so I suppose we
  235          * don't really have to do anything else.
  236          */
  237         return (1);
  238 }
  239 
  240 /*
  241  * acpi_attach:
  242  *
  243  *      Autoconfiguration `attach' routine.  Finish initializing
  244  *      ACPICA (some initialization was done in acpi_probe(),
  245  *      which was required to check for the presence of ACPI),
  246  *      and enable the ACPI subsystem.
  247  */
  248 void
  249 acpi_attach(struct device *parent, struct device *self, void *aux)
  250 {
  251         struct acpi_softc *sc = (void *) self;
  252         struct acpibus_attach_args *aa = aux;
  253         ACPI_STATUS rv;
  254 
  255         printf("\n");
  256 
  257         if (acpi_softc != NULL)
  258                 panic("acpi_attach: ACPI has already been attached");
  259 
  260         sysmon_power_settype("acpi");
  261 
  262         printf("%s: using Intel ACPI CA subsystem version %08x\n",
  263             sc->sc_dev.dv_xname, ACPI_CA_VERSION);
  264 
  265         printf("%s: X/RSDT: OemId <%6.6s,%8.8s,%08x>, AslId <%4.4s,%08x>\n",
  266             sc->sc_dev.dv_xname,
  267             AcpiGbl_XSDT->OemId, AcpiGbl_XSDT->OemTableId,
  268             AcpiGbl_XSDT->OemRevision,
  269             AcpiGbl_XSDT->AslCompilerId, AcpiGbl_XSDT->AslCompilerRevision);
  270 
  271         sc->sc_quirks = acpi_find_quirks();
  272 
  273         sc->sc_iot = aa->aa_iot;
  274         sc->sc_memt = aa->aa_memt;
  275         sc->sc_pc = aa->aa_pc;
  276         sc->sc_pciflags = aa->aa_pciflags;
  277         sc->sc_ic = aa->aa_ic;
  278 
  279         acpi_softc = sc;
  280 
  281         /*
  282          * Bring ACPI on-line.
  283          */
  284 #ifdef ACPI_DEBUGGER
  285         if (acpi_dbgr & ACPI_DBGR_ENABLE)
  286                 acpi_osd_debugger();
  287 #endif
  288 
  289         rv = AcpiEnableSubsystem(0);
  290         if (ACPI_FAILURE(rv)) {
  291                 printf("%s: unable to enable ACPI: %s\n",
  292                     sc->sc_dev.dv_xname, AcpiFormatException(rv));
  293                 return;
  294         }
  295 
  296         /* early EC handler initialization if ECDT table is available */
  297 #if NACPIEC > 0
  298         acpiec_early_attach(&sc->sc_dev);
  299 #endif
  300 
  301         rv = AcpiInitializeObjects(0);
  302         if (ACPI_FAILURE(rv)) {
  303                 printf("%s: unable to initialize ACPI objects: %s\n",
  304                     sc->sc_dev.dv_xname, AcpiFormatException(rv));
  305                 return;
  306         }
  307         acpi_active = 1;
  308 
  309         /* Our current state is "awake". */
  310         sc->sc_sleepstate = ACPI_STATE_S0;
  311 
  312         /* Show SCI interrupt. */
  313         if (AcpiGbl_FADT != NULL)
  314                 printf("%s: SCI interrupting at int %d\n",
  315                         sc->sc_dev.dv_xname, AcpiGbl_FADT->SciInt);
  316         /*
  317          * Check for fixed-hardware features.
  318          */
  319         acpi_enable_fixed_events(sc);
  320 
  321         /*
  322          * Fix up PCI devices.
  323          */
  324 #ifdef ACPI_PCI_FIXUP
  325         if ((sc->sc_quirks & (ACPI_QUIRK_BADPCI | ACPI_QUIRK_BADIRQ)) == 0)
  326                 acpi_pci_fixup(sc);
  327 #endif
  328  
  329         /*
  330          * Scan the namespace and build our device tree.
  331          */
  332 #ifdef ACPI_DEBUGGER
  333         if (acpi_dbgr & ACPI_DBGR_PROBE)
  334                 acpi_osd_debugger();
  335 #endif
  336         acpi_md_callback((struct device *)sc);
  337         acpi_build_tree(sc);
  338 
  339         /*
  340          * Register a shutdown hook that disables certain ACPI
  341          * events that might happen and confuse us while we're
  342          * trying to shut down.
  343          */
  344         sc->sc_sdhook = shutdownhook_establish(acpi_shutdown, sc);
  345         if (sc->sc_sdhook == NULL)
  346                 printf("%s: WARNING: unable to register shutdown hook\n",
  347                     sc->sc_dev.dv_xname);
  348 
  349 #ifdef ACPI_DEBUGGER
  350         if (acpi_dbgr & ACPI_DBGR_RUNNING)
  351                 acpi_osd_debugger();
  352 #endif
  353 }
  354 
  355 /*
  356  * acpi_shutdown:
  357  *
  358  *      Shutdown hook for ACPI -- disable some events that
  359  *      might confuse us.
  360  */
  361 void
  362 acpi_shutdown(void *arg)
  363 {
  364         struct acpi_softc *sc = arg;
  365         ACPI_STATUS rv;
  366 
  367         rv = acpi_disable(sc);
  368         if (ACPI_FAILURE(rv))
  369                 printf("%s: WARNING: unable to disable ACPI: %s\n",
  370                     sc->sc_dev.dv_xname, AcpiFormatException(rv));
  371 }
  372 
  373 /*
  374  * acpi_disable:
  375  *
  376  *      Disable ACPI.
  377  */
  378 ACPI_STATUS
  379 acpi_disable(struct acpi_softc *sc)
  380 {
  381         ACPI_STATUS rv = AE_OK;
  382 
  383 #ifdef ACPI_DISABLE_ON_POWEROFF
  384         if (acpi_active) {
  385                 rv = AcpiDisable();
  386                 if (ACPI_SUCCESS(rv))
  387                         acpi_active = 0;
  388         }
  389 #endif
  390         return (rv);
  391 }
  392 
  393 struct acpi_make_devnode_state {
  394         struct acpi_softc *softc;
  395         struct acpi_scope *scope;
  396 };
  397 
  398 /*
  399  * acpi_build_tree:
  400  *
  401  *      Scan relevant portions of the ACPI namespace and attach
  402  *      child devices.
  403  */
  404 void
  405 acpi_build_tree(struct acpi_softc *sc)
  406 {
  407         static const char *scopes[] = {
  408                 "\\_PR_",       /* ACPI 1.0 processor namespace */
  409                 "\\_SB_",       /* system bus namespace */
  410                 "\\_SI_",       /* system idicator namespace */
  411                 "\\_TZ_",       /* ACPI 1.0 thermal zone namespace */
  412                 NULL,
  413         };
  414         struct acpi_attach_args aa;
  415         struct acpi_make_devnode_state state;
  416         struct acpi_scope *as;
  417         struct acpi_devnode *ad;
  418         ACPI_HANDLE parent;
  419         ACPI_STATUS rv;
  420         int i;
  421 
  422         TAILQ_INIT(&sc->sc_scopes);
  423 
  424         state.softc = sc;
  425 
  426         /*
  427          * Scan the namespace and build our tree.
  428          */
  429         for (i = 0; scopes[i] != NULL; i++) {
  430                 as = malloc(sizeof(*as), M_ACPI, M_WAITOK);
  431                 as->as_name = scopes[i];
  432                 TAILQ_INIT(&as->as_devnodes);
  433 
  434                 TAILQ_INSERT_TAIL(&sc->sc_scopes, as, as_list);
  435 
  436                 state.scope = as;
  437 
  438                 rv = AcpiGetHandle(ACPI_ROOT_OBJECT, (char *) scopes[i],
  439                     &parent);
  440                 if (ACPI_SUCCESS(rv)) {
  441                         AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100,
  442                             acpi_make_devnode, &state, NULL);
  443                 }
  444 
  445                 /* Now, for this namespace, try and attach the devices. */
  446                 TAILQ_FOREACH(ad, &as->as_devnodes, ad_list) {
  447                         aa.aa_node = ad;
  448                         aa.aa_iot = sc->sc_iot;
  449                         aa.aa_memt = sc->sc_memt;
  450                         aa.aa_pc = sc->sc_pc;
  451                         aa.aa_pciflags = sc->sc_pciflags;
  452                         aa.aa_ic = sc->sc_ic;
  453 
  454                         if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE) {
  455                                 /*
  456                                  * XXX We only attach devices which are:
  457                                  *
  458                                  *      - present
  459                                  *      - enabled
  460                                  *      - functioning properly
  461                                  *
  462                                  * However, if enabled, it's decoding resources,
  463                                  * so we should claim them, if possible.
  464                                  * Requires changes to bus_space(9).
  465                                  */
  466                                 if ((ad->ad_devinfo->Valid & ACPI_VALID_STA) ==
  467                                     ACPI_VALID_STA &&
  468                                     (ad->ad_devinfo->CurrentStatus &
  469                                      (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
  470                                       ACPI_STA_DEV_OK)) !=
  471                                     (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
  472                                      ACPI_STA_DEV_OK))
  473                                         continue;
  474 
  475                                 /*
  476                                  * XXX Same problem as above...
  477                                  */
  478                                 if ((ad->ad_devinfo->Valid & ACPI_VALID_HID)
  479                                     == 0)
  480                                         continue;
  481                         }
  482 
  483                         ad->ad_device = config_found(&sc->sc_dev,
  484                             &aa, acpi_print);
  485                 }
  486         }
  487 }
  488 
  489 #ifdef ACPI_ACTIVATE_DEV
  490 static void
  491 acpi_activate_device(ACPI_HANDLE handle, ACPI_DEVICE_INFO **di)
  492 {
  493         ACPI_STATUS rv;
  494         ACPI_BUFFER buf;
  495 
  496         buf.Pointer = NULL;
  497         buf.Length = ACPI_ALLOCATE_BUFFER;
  498 
  499 #ifdef ACPI_DEBUG
  500         printf("acpi_activate_device: %s, old status=%x\n", 
  501                (*di)->HardwareId.Value, (*di)->CurrentStatus);
  502 #endif
  503 
  504         rv = acpi_allocate_resources(handle);
  505         if (ACPI_FAILURE(rv)) {
  506                 printf("acpi: activate failed for %s\n",
  507                        (*di)->HardwareId.Value);
  508         } else {
  509                 printf("acpi: activated %s\n", (*di)->HardwareId.Value);
  510         }
  511 
  512         (void)AcpiGetObjectInfo(handle, &buf);
  513         AcpiOsFree(*di);
  514         *di = buf.Pointer;
  515 
  516 #ifdef ACPI_DEBUG
  517         printf("acpi_activate_device: %s, new status=%x\n", 
  518                (*di)->HardwareId.Value, (*di)->CurrentStatus);
  519 #endif
  520 }
  521 #endif /* ACPI_ACTIVATE_DEV */
  522 
  523 /*
  524  * acpi_make_devnode:
  525  *
  526  *      Make an ACPI devnode.
  527  */
  528 ACPI_STATUS
  529 acpi_make_devnode(ACPI_HANDLE handle, UINT32 level, void *context,
  530     void **status)
  531 {
  532         struct acpi_make_devnode_state *state = context;
  533 #if defined(ACPI_DEBUG) || defined(ACPI_EXTRA_DEBUG)
  534         struct acpi_softc *sc = state->softc;
  535 #endif
  536         struct acpi_scope *as = state->scope;
  537         struct acpi_devnode *ad;
  538         ACPI_OBJECT_TYPE type;
  539         ACPI_BUFFER buf;
  540         ACPI_DEVICE_INFO *devinfo;
  541         ACPI_STATUS rv;
  542 
  543         rv = AcpiGetType(handle, &type);
  544         if (ACPI_SUCCESS(rv)) {
  545                 buf.Pointer = NULL;
  546                 buf.Length = ACPI_ALLOCATE_BUFFER;
  547                 rv = AcpiGetObjectInfo(handle, &buf);
  548                 if (ACPI_FAILURE(rv)) {
  549 #ifdef ACPI_DEBUG
  550                         printf("%s: AcpiGetObjectInfo failed: %s\n",
  551                             sc->sc_dev.dv_xname, AcpiFormatException(rv));
  552 #endif
  553                         goto out; /* XXX why return OK */
  554                 }
  555 
  556                 devinfo = buf.Pointer;
  557 
  558                 switch (type) {
  559                 case ACPI_TYPE_DEVICE:
  560 #ifdef ACPI_ACTIVATE_DEV
  561                         if ((devinfo->Valid & (ACPI_VALID_STA|ACPI_VALID_HID)) ==
  562                             (ACPI_VALID_STA|ACPI_VALID_HID) &&
  563                             (devinfo->CurrentStatus &
  564                              (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED)) ==
  565                             ACPI_STA_DEV_PRESENT)
  566                                 acpi_activate_device(handle, &devinfo);
  567 
  568                         /* FALLTHROUGH */
  569 #endif
  570 
  571                 case ACPI_TYPE_PROCESSOR:
  572                 case ACPI_TYPE_THERMAL:
  573                 case ACPI_TYPE_POWER:
  574                         ad = malloc(sizeof(*ad), M_ACPI, M_NOWAIT|M_ZERO);
  575                         if (ad == NULL)
  576                                 return (AE_NO_MEMORY);
  577 
  578                         ad->ad_devinfo = devinfo;
  579                         ad->ad_handle = handle;
  580                         ad->ad_level = level;
  581                         ad->ad_scope = as;
  582                         ad->ad_type = type;
  583 
  584                         TAILQ_INSERT_TAIL(&as->as_devnodes, ad, ad_list);
  585 
  586                         if ((ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0)
  587                                 goto out;
  588 
  589 #ifdef ACPI_EXTRA_DEBUG
  590                         printf("%s: HID %s found in scope %s level %d\n",
  591                             sc->sc_dev.dv_xname,
  592                             ad->ad_devinfo->HardwareId.Value,
  593                             as->as_name, ad->ad_level);
  594                         if (ad->ad_devinfo->Valid & ACPI_VALID_UID)
  595                                 printf("       UID %s\n",
  596                                     ad->ad_devinfo->UniqueId.Value);
  597                         if (ad->ad_devinfo->Valid & ACPI_VALID_ADR)
  598                                 printf("       ADR 0x%016qx\n",
  599                                     ad->ad_devinfo->Address);
  600                         if (ad->ad_devinfo->Valid & ACPI_VALID_STA)
  601                                 printf("       STA 0x%08x\n",
  602                                     ad->ad_devinfo->CurrentStatus);
  603 #endif
  604                 }
  605         }
  606  out:
  607         return (AE_OK);
  608 }
  609 
  610 /*
  611  * acpi_print:
  612  *
  613  *      Autoconfiguration print routine.
  614  */
  615 int
  616 acpi_print(void *aux, const char *pnp)
  617 {
  618         struct acpi_attach_args *aa = aux;
  619         ACPI_STATUS rv;
  620 
  621         if (pnp) {
  622                 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
  623                         char *pnpstr =
  624                             aa->aa_node->ad_devinfo->HardwareId.Value;
  625                         char *str;
  626 
  627                         aprint_normal("%s ", pnpstr);
  628                         rv = acpi_eval_string(aa->aa_node->ad_handle,
  629                             "_STR", &str);
  630                         if (ACPI_SUCCESS(rv)) {
  631                                 aprint_normal("[%s] ", str);
  632                                 AcpiOsFree(str);
  633                         }
  634 #ifdef ACPIVERBOSE
  635                         else {
  636                                 int i;
  637 
  638                                 for (i = 0; i < sizeof(acpi_knowndevs) /
  639                                     sizeof(acpi_knowndevs[0]); i++) {
  640                                         if (strcmp(acpi_knowndevs[i].pnp,
  641                                             pnpstr) == 0) {
  642                                                 printf("[%s] ",
  643                                                     acpi_knowndevs[i].str);
  644                                         }
  645                                 }
  646                         }
  647                             
  648 #endif
  649                 } else {
  650                         aprint_normal("ACPI Object Type '%s' (0x%02x) ",
  651                            AcpiUtGetTypeName(aa->aa_node->ad_devinfo->Type),
  652                            aa->aa_node->ad_devinfo->Type);
  653                 }
  654                 aprint_normal("at %s", pnp);
  655         } else {
  656                 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
  657                         aprint_normal(" (%s", aa->aa_node->ad_devinfo->HardwareId.Value);
  658                         if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_UID) {
  659                                 char *uid;
  660 
  661                                 uid = aa->aa_node->ad_devinfo->UniqueId.Value;
  662                                 if (uid[0] == '\0')
  663                                         uid = "<null>";
  664                                 aprint_normal("-%s", uid);
  665                         }
  666                         aprint_normal(")");
  667                 }
  668         }
  669 
  670         return (UNCONF);
  671 }
  672 
  673 /*****************************************************************************
  674  * ACPI fixed-hardware feature handlers
  675  *****************************************************************************/
  676 
  677 UINT32          acpi_fixed_button_handler(void *);
  678 void            acpi_fixed_button_pressed(void *);
  679 
  680 /*
  681  * acpi_enable_fixed_events:
  682  *
  683  *      Enable any fixed-hardware feature handlers.
  684  */
  685 void
  686 acpi_enable_fixed_events(struct acpi_softc *sc)
  687 {
  688         static int beenhere;
  689         ACPI_STATUS rv;
  690 
  691         KASSERT(beenhere == 0);
  692         beenhere = 1;
  693 
  694         /*
  695          * Check for fixed-hardware buttons.
  696          */
  697 
  698         if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->PwrButton == 0) {
  699                 printf("%s: fixed-feature power button present\n",
  700                     sc->sc_dev.dv_xname);
  701                 sc->sc_smpsw_power.smpsw_name = sc->sc_dev.dv_xname;
  702                 sc->sc_smpsw_power.smpsw_type = PSWITCH_TYPE_POWER;
  703                 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) {
  704                         printf("%s: unable to register fixed power button "
  705                             "with sysmon\n", sc->sc_dev.dv_xname);
  706                 } else {
  707                         rv = AcpiInstallFixedEventHandler(
  708                             ACPI_EVENT_POWER_BUTTON,
  709                             acpi_fixed_button_handler, &sc->sc_smpsw_power);
  710                         if (ACPI_FAILURE(rv)) {
  711                                 printf("%s: unable to install handler for "
  712                                     "fixed power button: %s\n",
  713                                     sc->sc_dev.dv_xname,
  714                                     AcpiFormatException(rv));
  715                         }
  716                 }
  717         }
  718 
  719         if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->SleepButton == 0) {
  720                 printf("%s: fixed-feature sleep button present\n",
  721                     sc->sc_dev.dv_xname);
  722                 sc->sc_smpsw_sleep.smpsw_name = sc->sc_dev.dv_xname;
  723                 sc->sc_smpsw_sleep.smpsw_type = PSWITCH_TYPE_SLEEP;
  724                 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) {
  725                         printf("%s: unable to register fixed sleep button "
  726                             "with sysmon\n", sc->sc_dev.dv_xname);
  727                 } else {
  728                         rv = AcpiInstallFixedEventHandler(
  729                             ACPI_EVENT_SLEEP_BUTTON,
  730                             acpi_fixed_button_handler, &sc->sc_smpsw_sleep);
  731                         if (ACPI_FAILURE(rv)) {
  732                                 printf("%s: unable to install handler for "
  733                                     "fixed sleep button: %s\n",
  734                                     sc->sc_dev.dv_xname,
  735                                     AcpiFormatException(rv));
  736                         }
  737                 }
  738         }
  739 }
  740 
  741 /*
  742  * acpi_fixed_button_handler:
  743  *
  744  *      Event handler for the fixed buttons.
  745  */
  746 UINT32
  747 acpi_fixed_button_handler(void *context)
  748 {
  749         struct sysmon_pswitch *smpsw = context;
  750         int rv;
  751 
  752 #ifdef ACPI_BUT_DEBUG
  753         printf("%s: fixed button handler\n", smpsw->smpsw_name);
  754 #endif
  755 
  756         rv = AcpiOsQueueForExecution(OSD_PRIORITY_LO,
  757             acpi_fixed_button_pressed, smpsw);
  758         if (ACPI_FAILURE(rv))
  759                 printf("%s: WARNING: unable to queue fixed button pressed "
  760                     "callback: %s\n", smpsw->smpsw_name,
  761                     AcpiFormatException(rv));
  762 
  763         return (ACPI_INTERRUPT_HANDLED);
  764 }
  765 
  766 /*
  767  * acpi_fixed_button_pressed:
  768  *
  769  *      Deal with a fixed button being pressed.
  770  */
  771 void
  772 acpi_fixed_button_pressed(void *context)
  773 {
  774         struct sysmon_pswitch *smpsw = context;
  775 
  776 #ifdef ACPI_BUT_DEBUG
  777         printf("%s: fixed button pressed, calling sysmon\n",
  778             smpsw->smpsw_name);
  779 #endif
  780 
  781         sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED);
  782 }
  783 
  784 /*****************************************************************************
  785  * ACPI utility routines.
  786  *****************************************************************************/
  787 
  788 /*
  789  * acpi_eval_integer:
  790  *
  791  *      Evaluate an integer object.
  792  */
  793 ACPI_STATUS
  794 acpi_eval_integer(ACPI_HANDLE handle, char *path, ACPI_INTEGER *valp)
  795 {
  796         ACPI_STATUS rv;
  797         ACPI_BUFFER buf;
  798         ACPI_OBJECT param;
  799 
  800         if (handle == NULL)
  801                 handle = ACPI_ROOT_OBJECT;
  802 
  803         buf.Pointer = &param;
  804         buf.Length = sizeof(param);
  805 
  806         rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf, ACPI_TYPE_INTEGER);
  807         if (ACPI_SUCCESS(rv))
  808                 *valp = param.Integer.Value;
  809 
  810         return (rv);
  811 }
  812 
  813 /*
  814  * acpi_eval_string:
  815  *
  816  *      Evaluate a (Unicode) string object.
  817  */
  818 ACPI_STATUS
  819 acpi_eval_string(ACPI_HANDLE handle, char *path, char **stringp)
  820 {
  821         ACPI_STATUS rv;
  822         ACPI_BUFFER buf;
  823 
  824         if (handle == NULL)
  825                 handle = ACPI_ROOT_OBJECT;
  826 
  827         buf.Pointer = NULL;
  828         buf.Length = ACPI_ALLOCATE_BUFFER;
  829 
  830         rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf, ACPI_TYPE_STRING);
  831         if (ACPI_SUCCESS(rv)) {
  832                 ACPI_OBJECT *param = buf.Pointer;
  833                 char *ptr = param->String.Pointer;
  834                 size_t len = param->String.Length;
  835                 if ((*stringp = AcpiOsAllocate(len)) == NULL)
  836                         rv = AE_NO_MEMORY;
  837                 else
  838                         (void)memcpy(*stringp, ptr, len);
  839                 AcpiOsFree(param);
  840         }
  841 
  842         return (rv);
  843 }
  844 
  845 
  846 /*
  847  * acpi_eval_struct:
  848  *
  849  *      Evaluate a more complex structure.
  850  *      Caller must free buf.Pointer by AcpiOsFree().
  851  */
  852 ACPI_STATUS
  853 acpi_eval_struct(ACPI_HANDLE handle, char *path, ACPI_BUFFER *bufp)
  854 {
  855         ACPI_STATUS rv;
  856 
  857         if (handle == NULL)
  858                 handle = ACPI_ROOT_OBJECT;
  859 
  860         bufp->Pointer = NULL;
  861         bufp->Length = ACPI_ALLOCATE_BUFFER;
  862 
  863         rv = AcpiEvaluateObject(handle, path, NULL, bufp);
  864 
  865         return (rv);
  866 }
  867 
  868 /*
  869  * acpi_get:
  870  *
  871  *      Fetch data info the specified (empty) ACPI buffer.
  872  *      Caller must free buf.Pointer by AcpiOsFree().
  873  */
  874 ACPI_STATUS
  875 acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf,
  876     ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *))
  877 {
  878         buf->Pointer = NULL;
  879         buf->Length = ACPI_ALLOCATE_BUFFER;
  880 
  881         return ((*getit)(handle, buf));
  882 }
  883 
  884 
  885 /*
  886  * acpi_match_hid
  887  *
  888  *      Match given ids against _HID and _CIDs
  889  */
  890 int
  891 acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids)
  892 {
  893         int i;
  894 
  895         while (*ids) {
  896                 if (ad->Valid & ACPI_VALID_HID) {
  897                         if (pmatch(ad->HardwareId.Value, *ids, NULL) == 2)
  898                                 return (1);
  899                 }
  900 
  901                 if (ad->Valid & ACPI_VALID_CID) {
  902                         for (i = 0; i < ad->CompatibilityId.Count; i++) {
  903                                 if (pmatch(ad->CompatibilityId.Id[i].Value, *ids, NULL) == 2)
  904                                         return (1);
  905                         }
  906                 }
  907                 ids++;
  908         }
  909 
  910         return (0);
  911 }
  912 
  913 
  914 /*****************************************************************************
  915  * ACPI sleep support.
  916  *****************************************************************************/
  917 
  918 static int
  919 is_available_state(struct acpi_softc *sc, int state)
  920 {
  921         UINT8 type_a, type_b;
  922 
  923         return (ACPI_SUCCESS(AcpiGetSleepTypeData((UINT8)state,
  924                                                   &type_a, &type_b)));
  925 }
  926 
  927 /*
  928  * acpi_enter_sleep_state:
  929  *
  930  *      enter to the specified sleep state.
  931  */
  932 
  933 ACPI_STATUS
  934 acpi_enter_sleep_state(struct acpi_softc *sc, int state)
  935 {
  936         int s;
  937         ACPI_STATUS ret = AE_OK;
  938 
  939         switch (state) {
  940         case ACPI_STATE_S0:
  941                 break;
  942         case ACPI_STATE_S1:
  943         case ACPI_STATE_S2:
  944         case ACPI_STATE_S3:
  945         case ACPI_STATE_S4:
  946                 if (!is_available_state(sc, state)) {
  947                         printf("acpi: cannot enter the sleep state (%d).\n",
  948                                state);
  949                         break;
  950                 }
  951                 ret = AcpiEnterSleepStatePrep(state);
  952                 if (ACPI_FAILURE(ret)) {
  953                         printf("acpi: failed preparing to sleep (%s)\n",
  954                                AcpiFormatException(ret));
  955                         break;
  956                 }
  957                 if (state==ACPI_STATE_S1) {
  958                         /* just enter the state */
  959                         acpi_md_OsDisableInterrupt();
  960                         AcpiEnterSleepState((UINT8)state);
  961                         AcpiUtReleaseMutex(ACPI_MTX_HARDWARE);
  962                 } else {
  963                         /* XXX: powerhooks(9) framework is too poor to
  964                          * support ACPI sleep state...
  965                          */
  966                         dopowerhooks(PWR_SOFTSUSPEND);
  967                         s = splhigh();
  968                         dopowerhooks(PWR_SUSPEND);
  969                         acpi_md_sleep(state);
  970                         dopowerhooks(PWR_RESUME);
  971                         splx(s);
  972                         dopowerhooks(PWR_SOFTRESUME);
  973                         if (state==ACPI_STATE_S4)
  974                                 AcpiEnable();
  975                 }
  976                 AcpiLeaveSleepState((UINT8)state);
  977                 break;
  978         case ACPI_STATE_S5:
  979                 ret = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
  980                 if (ACPI_FAILURE(ret)) {
  981                         printf("acpi: failed preparing to sleep (%s)\n",
  982                                AcpiFormatException(ret));
  983                         break;
  984                 }
  985                 acpi_md_OsDisableInterrupt();
  986                 AcpiEnterSleepState(ACPI_STATE_S5);
  987                 printf("WARNING: powerdown failed!\n");
  988                 break;
  989         }
  990 
  991         return (ret);
  992 }
  993 
  994 #ifdef ACPI_PCI_FIXUP
  995 ACPI_STATUS acpi_pci_fixup_bus(ACPI_HANDLE, UINT32, void *, void **);
  996 /*
  997  * acpi_pci_fixup:
  998  *
  999  *      Set up PCI devices that BIOS didn't handle right.
 1000  *      Iterate through all devices and try to get the _PTR
 1001  *      (PCI Routing Table).  If it exists then make sure all
 1002  *      interrupt links that it uses are working.
 1003  */
 1004 void
 1005 acpi_pci_fixup(struct acpi_softc *sc)
 1006 {
 1007         ACPI_HANDLE parent;
 1008         ACPI_STATUS rv;
 1009 
 1010 #ifdef ACPI_DEBUG
 1011         printf("acpi_pci_fixup starts:\n");
 1012 #endif
 1013         rv = AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &parent);
 1014         if (ACPI_FAILURE(rv))
 1015                 return;
 1016         sc->sc_pci_bus = 0;
 1017         AcpiWalkNamespace(ACPI_TYPE_DEVICE, parent, 100,
 1018             acpi_pci_fixup_bus, sc, NULL);
 1019 }
 1020 
 1021 static uint
 1022 acpi_get_intr(ACPI_HANDLE handle)
 1023 {
 1024         ACPI_BUFFER ret;
 1025         ACPI_STATUS rv;
 1026         ACPI_RESOURCE *res;
 1027         ACPI_RESOURCE_IRQ *irq;
 1028         uint intr;
 1029 
 1030         intr = -1;
 1031         rv = acpi_get(handle, &ret, AcpiGetCurrentResources);
 1032         if (ACPI_FAILURE(rv))
 1033                 return (intr);
 1034         for (res = ret.Pointer; res->Id != ACPI_RSTYPE_END_TAG;
 1035              res = ACPI_NEXT_RESOURCE(res)) {
 1036                 if (res->Id == ACPI_RSTYPE_IRQ) {
 1037                         irq = (ACPI_RESOURCE_IRQ *)&res->Data;
 1038                         if (irq->NumberOfInterrupts == 1)
 1039                                 intr = irq->Interrupts[0];
 1040                         break;
 1041                 }
 1042         }
 1043         AcpiOsFree(ret.Pointer);
 1044         return (intr);
 1045 }
 1046 
 1047 static void
 1048 acpi_pci_set_line(int bus, int dev, int pin, int line)
 1049 {
 1050         ACPI_STATUS err;
 1051         ACPI_PCI_ID pid;
 1052         UINT32 intr, id, bhlc;
 1053         int func, nfunc;
 1054 
 1055         pid.Bus = bus;
 1056         pid.Device = dev;
 1057         pid.Function = 0;
 1058         
 1059         err = AcpiOsReadPciConfiguration(&pid, PCI_BHLC_REG, &bhlc, 32);
 1060         if (err)
 1061                 return;
 1062         if (PCI_HDRTYPE_MULTIFN(bhlc))
 1063                 nfunc = 8;
 1064         else
 1065                 nfunc = 1;
 1066 
 1067         for (func = 0; func < nfunc; func++) {
 1068                 pid.Function = func;
 1069 
 1070                 err = AcpiOsReadPciConfiguration(&pid, PCI_ID_REG, &id, 32);
 1071                 if (err || PCI_VENDOR(id) == PCI_VENDOR_INVALID ||
 1072                     PCI_VENDOR(id) == 0)
 1073                         continue;
 1074 
 1075                 err = AcpiOsReadPciConfiguration(&pid, PCI_INTERRUPT_REG,
 1076                           &intr, 32);
 1077                 if (err) {
 1078                         printf("AcpiOsReadPciConfiguration failed %d\n", err);
 1079                         return;
 1080                 }
 1081                 if (pin == PCI_INTERRUPT_PIN(intr) &&
 1082                     line != PCI_INTERRUPT_LINE(intr)) {
 1083 #ifdef ACPI_DEBUG
 1084                         printf("acpi fixup pci intr: %d:%d:%d %c: %d -> %d\n",
 1085                                bus, dev, func,
 1086                                pin + '@', PCI_INTERRUPT_LINE(intr),
 1087                                line);
 1088 #endif
 1089                         intr &= ~(PCI_INTERRUPT_LINE_MASK <<
 1090                                   PCI_INTERRUPT_LINE_SHIFT);
 1091                         intr |= line << PCI_INTERRUPT_LINE_SHIFT;
 1092                         err = AcpiOsWritePciConfiguration(&pid,
 1093                                   PCI_INTERRUPT_REG, intr, 32);
 1094                         if (err) {
 1095                                 printf("AcpiOsWritePciConfiguration failed"
 1096                                        " %d\n", err);
 1097                                 return;
 1098                         }
 1099                 }
 1100         }
 1101 }
 1102 
 1103 ACPI_STATUS
 1104 acpi_pci_fixup_bus(ACPI_HANDLE handle, UINT32 level, void *context,
 1105                    void **status)
 1106 {
 1107         struct acpi_softc *sc = context;
 1108         ACPI_STATUS rv;
 1109         ACPI_BUFFER buf;
 1110         UINT8 *Buffer;
 1111         ACPI_PCI_ROUTING_TABLE *PrtElement;
 1112         ACPI_HANDLE link;
 1113         uint line;
 1114         ACPI_INTEGER val;
 1115 
 1116         rv = acpi_get(handle, &buf, AcpiGetIrqRoutingTable);
 1117         if (ACPI_FAILURE(rv))
 1118                 return (AE_OK);
 1119 
 1120         /*
 1121          * If at level 1, this is a PCI root bus. Try the _BBN method
 1122          * to get the right PCI bus numbering for the following
 1123          * busses (this is a depth-first walk). It may fail,
 1124          * for example if there's only one root bus, but that
 1125          * case should be ok, so we'll ignore that.
 1126          */
 1127         if (level == 1) {
 1128                 rv = acpi_eval_integer(handle, METHOD_NAME__BBN, &val);
 1129                 if (!ACPI_FAILURE(rv)) {
 1130 #ifdef ACPI_DEBUG
 1131                         printf("%s: fixup: _BBN success, bus # was %d now %d\n",
 1132                             sc->sc_dev.dv_xname, sc->sc_pci_bus,
 1133                             ACPI_LOWORD(val));
 1134 #endif
 1135                         sc->sc_pci_bus = ACPI_LOWORD(val);
 1136                 }
 1137         }
 1138                         
 1139 
 1140 #ifdef ACPI_DEBUG
 1141         printf("%s: fixing up PCI bus %d at level %u\n", sc->sc_dev.dv_xname,
 1142             sc->sc_pci_bus, level);
 1143 #endif
 1144 
 1145         for (Buffer = buf.Pointer; ; Buffer += PrtElement->Length) {
 1146                 PrtElement = (ACPI_PCI_ROUTING_TABLE *)Buffer;
 1147                 if (PrtElement->Length == 0)
 1148                         break;
 1149                 if (PrtElement->Source[0] == 0)
 1150                         continue;
 1151 
 1152                 rv = AcpiGetHandle(NULL, PrtElement->Source, &link);
 1153                 if (ACPI_FAILURE(rv))
 1154                         continue;
 1155                 line = acpi_get_intr(link);
 1156                 if (line == -1) {
 1157 #ifdef ACPI_DEBUG
 1158                         printf("%s: fixing up intr link %s\n",
 1159                             sc->sc_dev.dv_xname, PrtElement->Source);
 1160 #endif
 1161                         rv = acpi_allocate_resources(link);
 1162                         if (ACPI_FAILURE(rv)) {
 1163                                 printf("%s: interrupt allocation failed %s\n",
 1164                                     sc->sc_dev.dv_xname, PrtElement->Source);
 1165                                 continue;
 1166                         }
 1167                         line = acpi_get_intr(link);
 1168                         if (line == -1) {
 1169                                 printf("%s: get intr failed %s\n",
 1170                                     sc->sc_dev.dv_xname, PrtElement->Source);
 1171                                 continue;
 1172                         }
 1173                 }
 1174 
 1175                 acpi_pci_set_line(sc->sc_pci_bus, PrtElement->Address >> 16,
 1176                     PrtElement->Pin + 1, line);
 1177         }
 1178 
 1179         sc->sc_pci_bus++;
 1180 
 1181         AcpiOsFree(buf.Pointer);
 1182         return (AE_OK);
 1183 }
 1184 #endif /* ACPI_PCI_FIXUP */
 1185 
 1186 #if defined(ACPI_PCI_FIXUP) || defined(ACPI_ACTIVATE_DEV)
 1187 /* XXX This very incomplete */
 1188 ACPI_STATUS
 1189 acpi_allocate_resources(ACPI_HANDLE handle)
 1190 {
 1191         ACPI_BUFFER bufp, bufc, bufn;
 1192         ACPI_RESOURCE *resp, *resc, *resn;
 1193         ACPI_RESOURCE_IRQ *irq;
 1194         ACPI_STATUS rv;
 1195         uint delta;
 1196 
 1197         rv = acpi_get(handle, &bufp, AcpiGetPossibleResources);
 1198         if (ACPI_FAILURE(rv))
 1199                 goto out;
 1200         rv = acpi_get(handle, &bufc, AcpiGetCurrentResources);
 1201         if (ACPI_FAILURE(rv)) {
 1202                 goto out1;
 1203         }
 1204 
 1205         bufn.Length = 1000;
 1206         bufn.Pointer = resn = malloc(bufn.Length, M_ACPI, M_WAITOK);
 1207         resp = bufp.Pointer;
 1208         resc = bufc.Pointer;
 1209         while (resc->Id != ACPI_RSTYPE_END_TAG &&
 1210                resp->Id != ACPI_RSTYPE_END_TAG) {
 1211                 while (resc->Id != resp->Id && resp->Id != ACPI_RSTYPE_END_TAG)
 1212                         resp = ACPI_NEXT_RESOURCE(resp);
 1213                 if (resp->Id == ACPI_RSTYPE_END_TAG)
 1214                         break;
 1215                 /* Found identical Id */
 1216                 resn->Id = resc->Id;
 1217                 switch (resc->Id) {
 1218                 case ACPI_RSTYPE_IRQ:
 1219                         memcpy(&resn->Data, &resp->Data,
 1220                                sizeof(ACPI_RESOURCE_IRQ));
 1221                         irq = (ACPI_RESOURCE_IRQ *)&resn->Data;
 1222                         irq->Interrupts[0] =
 1223                             ((ACPI_RESOURCE_IRQ *)&resp->Data)->
 1224                                 Interrupts[irq->NumberOfInterrupts-1];
 1225                         irq->NumberOfInterrupts = 1;
 1226                         resn->Length = ACPI_SIZEOF_RESOURCE(ACPI_RESOURCE_IRQ);
 1227                         break;
 1228                 case ACPI_RSTYPE_IO:
 1229                         memcpy(&resn->Data, &resp->Data,
 1230                                sizeof(ACPI_RESOURCE_IO));
 1231                         resn->Length = resp->Length;
 1232                         break;
 1233                 default:
 1234                         printf("acpi_allocate_resources: res=%d\n", resc->Id);
 1235                         rv = AE_BAD_DATA;
 1236                         goto out2;
 1237                 }
 1238                 resc = ACPI_NEXT_RESOURCE(resc);
 1239                 resn = ACPI_NEXT_RESOURCE(resn);
 1240                 delta = (UINT8 *)resn - (UINT8 *)bufn.Pointer;
 1241                 if (delta >= 
 1242                     bufn.Length-ACPI_SIZEOF_RESOURCE(ACPI_RESOURCE_DATA)) {
 1243                         bufn.Length *= 2;
 1244                         bufn.Pointer = realloc(bufn.Pointer, bufn.Length,
 1245                                                M_ACPI, M_WAITOK);
 1246                         resn = (ACPI_RESOURCE *)((UINT8 *)bufn.Pointer + delta);
 1247                 }
 1248         }
 1249         if (resc->Id != ACPI_RSTYPE_END_TAG) {
 1250                 printf("acpi_allocate_resources: resc not exhausted\n");
 1251                 rv = AE_BAD_DATA;
 1252                 goto out3;
 1253         }
 1254 
 1255         resn->Id = ACPI_RSTYPE_END_TAG;
 1256         rv = AcpiSetCurrentResources(handle, &bufn);
 1257         if (ACPI_FAILURE(rv)) {
 1258                 printf("acpi_allocate_resources: AcpiSetCurrentResources %s\n",
 1259                        AcpiFormatException(rv));
 1260         }
 1261 
 1262 out3:
 1263         free(bufn.Pointer, M_ACPI);
 1264 out2:
 1265         AcpiOsFree(bufc.Pointer);
 1266 out1:
 1267         AcpiOsFree(bufp.Pointer);
 1268 out:
 1269         return rv;
 1270 }
 1271 #endif /* ACPI_PCI_FIXUP || ACPI_ACTIVATE_DEV */

Cache object: a643dd083b569154dc7b61920d5a5735


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