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/acpica/acpi_resource.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2000 Michael Smith
    3  * Copyright (c) 2000 BSDi
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, 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 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 #include "opt_acpi.h"
   32 #include <sys/param.h>
   33 #include <sys/kernel.h>
   34 #include <sys/bus.h>
   35 #include <sys/malloc.h>
   36 #include <sys/module.h>
   37 
   38 #include <machine/bus.h>
   39 #include <machine/resource.h>
   40 #include <sys/rman.h>
   41 
   42 #include <contrib/dev/acpica/acpi.h>
   43 #include <dev/acpica/acpivar.h>
   44 
   45 /* Hooks for the ACPI CA debugging infrastructure */
   46 #define _COMPONENT      ACPI_BUS
   47 ACPI_MODULE_NAME("RESOURCE")
   48 
   49 struct lookup_irq_request {
   50     ACPI_RESOURCE *acpi_res;
   51     struct resource *res;
   52     int         counter;
   53     int         rid;
   54     int         found;
   55 };
   56 
   57 static ACPI_STATUS
   58 acpi_lookup_irq_handler(ACPI_RESOURCE *res, void *context)
   59 {
   60     struct lookup_irq_request *req;
   61     u_int irqnum, irq;
   62 
   63     switch (res->Type) {
   64     case ACPI_RESOURCE_TYPE_IRQ:
   65     case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
   66         if (res->Type == ACPI_RESOURCE_TYPE_IRQ) {
   67             irqnum = res->Data.Irq.InterruptCount;
   68             irq = res->Data.Irq.Interrupts[0];
   69         } else {
   70             irqnum = res->Data.ExtendedIrq.InterruptCount;
   71             irq = res->Data.ExtendedIrq.Interrupts[0];
   72         }
   73         if (irqnum != 1)
   74             break;
   75         req = (struct lookup_irq_request *)context;
   76         if (req->counter != req->rid) {
   77             req->counter++;
   78             break;
   79         }
   80         req->found = 1;
   81         KASSERT(irq == rman_get_start(req->res),
   82             ("IRQ resources do not match"));
   83         bcopy(res, req->acpi_res, sizeof(ACPI_RESOURCE));
   84         return (AE_CTRL_TERMINATE);
   85     }
   86     return (AE_OK);
   87 }
   88 
   89 ACPI_STATUS
   90 acpi_lookup_irq_resource(device_t dev, int rid, struct resource *res,
   91     ACPI_RESOURCE *acpi_res)
   92 {
   93     struct lookup_irq_request req;
   94     ACPI_STATUS status;
   95 
   96     req.acpi_res = acpi_res;
   97     req.res = res;
   98     req.counter = 0;
   99     req.rid = rid;
  100     req.found = 0;
  101     status = AcpiWalkResources(acpi_get_handle(dev), "_CRS",
  102         acpi_lookup_irq_handler, &req);
  103     if (ACPI_SUCCESS(status) && req.found == 0)
  104         status = AE_NOT_FOUND;
  105     return (status);
  106 }
  107 
  108 void
  109 acpi_config_intr(device_t dev, ACPI_RESOURCE *res)
  110 {
  111     u_int irq;
  112     int pol, trig;
  113 
  114     switch (res->Type) {
  115     case ACPI_RESOURCE_TYPE_IRQ:
  116         KASSERT(res->Data.Irq.InterruptCount == 1,
  117             ("%s: multiple interrupts", __func__));
  118         irq = res->Data.Irq.Interrupts[0];
  119         trig = res->Data.Irq.Triggering;
  120         pol = res->Data.Irq.Polarity;
  121         break;
  122     case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
  123         KASSERT(res->Data.ExtendedIrq.InterruptCount == 1,
  124             ("%s: multiple interrupts", __func__));
  125         irq = res->Data.ExtendedIrq.Interrupts[0];
  126         trig = res->Data.ExtendedIrq.Triggering;
  127         pol = res->Data.ExtendedIrq.Polarity;
  128         break;
  129     default:
  130         panic("%s: bad resource type %u", __func__, res->Type);
  131     }
  132     BUS_CONFIG_INTR(dev, irq, (trig == ACPI_EDGE_SENSITIVE) ?
  133         INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, (pol == ACPI_ACTIVE_HIGH) ?
  134         INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
  135 }
  136 
  137 /*
  138  * Fetch a device's resources and associate them with the device.
  139  *
  140  * Note that it might be nice to also locate ACPI-specific resource items, such
  141  * as GPE bits.
  142  *
  143  * We really need to split the resource-fetching code out from the
  144  * resource-parsing code, since we may want to use the parsing
  145  * code for _PRS someday.
  146  */
  147 ACPI_STATUS
  148 acpi_parse_resources(device_t dev, ACPI_HANDLE handle,
  149                      struct acpi_parse_resource_set *set, void *arg)
  150 {
  151     ACPI_BUFFER         buf;
  152     ACPI_RESOURCE       *res;
  153     char                *curr, *last;
  154     ACPI_STATUS         status;
  155     void                *context;
  156 
  157     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  158 
  159     /*
  160      * Special-case some devices that abuse _PRS/_CRS to mean
  161      * something other than "I consume this resource".
  162      *
  163      * XXX do we really need this?  It's only relevant once
  164      *     we start always-allocating these resources, and even
  165      *     then, the only special-cased device is likely to be
  166      *     the PCI interrupt link.
  167      */
  168 
  169     /* Fetch the device's current resources. */
  170     buf.Length = ACPI_ALLOCATE_BUFFER;
  171     if (ACPI_FAILURE((status = AcpiGetCurrentResources(handle, &buf)))) {
  172         if (status != AE_NOT_FOUND && status != AE_TYPE)
  173             printf("can't fetch resources for %s - %s\n",
  174                    acpi_name(handle), AcpiFormatException(status));
  175         return_ACPI_STATUS (status);
  176     }
  177     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %ld bytes of resources\n",
  178                      acpi_name(handle), (long)buf.Length));
  179     set->set_init(dev, arg, &context);
  180 
  181     /* Iterate through the resources */
  182     curr = buf.Pointer;
  183     last = (char *)buf.Pointer + buf.Length;
  184     while (curr < last) {
  185         res = (ACPI_RESOURCE *)curr;
  186         curr += res->Length;
  187 
  188         /* Handle the individual resource types */
  189         switch(res->Type) {
  190         case ACPI_RESOURCE_TYPE_END_TAG:
  191             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
  192             curr = last;
  193             break;
  194         case ACPI_RESOURCE_TYPE_FIXED_IO:
  195             if (res->Data.FixedIo.AddressLength <= 0)
  196                 break;
  197             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
  198                              res->Data.FixedIo.Address,
  199                              res->Data.FixedIo.AddressLength));
  200             set->set_ioport(dev, context,
  201                             res->Data.FixedIo.Address,
  202                             res->Data.FixedIo.AddressLength);
  203             break;
  204         case ACPI_RESOURCE_TYPE_IO:
  205             if (res->Data.Io.AddressLength <= 0)
  206                 break;
  207             if (res->Data.Io.Minimum == res->Data.Io.Maximum) {
  208                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
  209                                  res->Data.Io.Minimum,
  210                                  res->Data.Io.AddressLength));
  211                 set->set_ioport(dev, context,
  212                                 res->Data.Io.Minimum,
  213                                 res->Data.Io.AddressLength);
  214             } else {
  215                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
  216                                  res->Data.Io.Minimum,
  217                                  res->Data.Io.Maximum, 
  218                                  res->Data.Io.AddressLength));
  219                 set->set_iorange(dev, context,
  220                                  res->Data.Io.Minimum,
  221                                  res->Data.Io.Maximum, 
  222                                  res->Data.Io.AddressLength,
  223                                  res->Data.Io.Alignment);
  224             }
  225             break;
  226         case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
  227             if (res->Data.FixedMemory32.AddressLength <= 0)
  228                 break;
  229             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
  230                               res->Data.FixedMemory32.Address, 
  231                               res->Data.FixedMemory32.AddressLength));
  232             set->set_memory(dev, context,
  233                             res->Data.FixedMemory32.Address, 
  234                             res->Data.FixedMemory32.AddressLength);
  235             break;
  236         case ACPI_RESOURCE_TYPE_MEMORY32:
  237             if (res->Data.Memory32.AddressLength <= 0)
  238                 break;
  239             if (res->Data.Memory32.Minimum ==
  240                 res->Data.Memory32.Maximum) {
  241 
  242                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
  243                                   res->Data.Memory32.Minimum, 
  244                                   res->Data.Memory32.AddressLength));
  245                 set->set_memory(dev, context,
  246                                 res->Data.Memory32.Minimum,
  247                                 res->Data.Memory32.AddressLength);
  248             } else {
  249                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
  250                                  res->Data.Memory32.Minimum, 
  251                                  res->Data.Memory32.Maximum,
  252                                  res->Data.Memory32.AddressLength));
  253                 set->set_memoryrange(dev, context,
  254                                      res->Data.Memory32.Minimum,
  255                                      res->Data.Memory32.Maximum,
  256                                      res->Data.Memory32.AddressLength,
  257                                      res->Data.Memory32.Alignment);
  258             }
  259             break;
  260         case ACPI_RESOURCE_TYPE_MEMORY24:
  261             if (res->Data.Memory24.AddressLength <= 0)
  262                 break;
  263             if (res->Data.Memory24.Minimum ==
  264                 res->Data.Memory24.Maximum) {
  265 
  266                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
  267                                  res->Data.Memory24.Minimum, 
  268                                  res->Data.Memory24.AddressLength));
  269                 set->set_memory(dev, context, res->Data.Memory24.Minimum,
  270                                 res->Data.Memory24.AddressLength);
  271             } else {
  272                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
  273                                  res->Data.Memory24.Minimum, 
  274                                  res->Data.Memory24.Maximum,
  275                                  res->Data.Memory24.AddressLength));
  276                 set->set_memoryrange(dev, context,
  277                                      res->Data.Memory24.Minimum,
  278                                      res->Data.Memory24.Maximum,
  279                                      res->Data.Memory24.AddressLength,
  280                                      res->Data.Memory24.Alignment);
  281             }
  282             break;
  283         case ACPI_RESOURCE_TYPE_IRQ:
  284             /*
  285              * from 1.0b 6.4.2 
  286              * "This structure is repeated for each separate interrupt
  287              * required"
  288              */
  289             set->set_irq(dev, context, res->Data.Irq.Interrupts,
  290                 res->Data.Irq.InterruptCount, res->Data.Irq.Triggering,
  291                 res->Data.Irq.Polarity);
  292             break;
  293         case ACPI_RESOURCE_TYPE_DMA:
  294             /*
  295              * from 1.0b 6.4.3 
  296              * "This structure is repeated for each separate dma channel
  297              * required"
  298              */
  299             set->set_drq(dev, context, res->Data.Dma.Channels,
  300                          res->Data.Dma.ChannelCount);
  301             break;
  302         case ACPI_RESOURCE_TYPE_START_DEPENDENT:
  303             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependent functions\n"));
  304             set->set_start_dependent(dev, context,
  305                                      res->Data.StartDpf.CompatibilityPriority);
  306             break;
  307         case ACPI_RESOURCE_TYPE_END_DEPENDENT:
  308             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependent functions\n"));
  309             set->set_end_dependent(dev, context);
  310             break;
  311         case ACPI_RESOURCE_TYPE_ADDRESS32:
  312             if (res->Data.Address32.AddressLength <= 0)
  313                 break;
  314             if (res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) {
  315                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
  316                     "ignored Address32 %s producer\n",
  317                     res->Data.Address32.ResourceType == ACPI_IO_RANGE ?
  318                     "IO" : "Memory"));
  319                 break;
  320             }
  321             if (res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE &&
  322                 res->Data.Address32.ResourceType != ACPI_IO_RANGE) {
  323                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
  324                     "ignored Address32 for non-memory, non-I/O\n"));
  325                 break;
  326             }
  327 
  328             if (res->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED &&
  329                 res->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED) {
  330 
  331                 if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
  332                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
  333                                      "Address32/Memory 0x%x/%d\n",
  334                                      res->Data.Address32.Minimum,
  335                                      res->Data.Address32.AddressLength));
  336                     set->set_memory(dev, context,
  337                                     res->Data.Address32.Minimum,
  338                                     res->Data.Address32.AddressLength);
  339                 } else {
  340                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
  341                                      "Address32/IO 0x%x/%d\n",
  342                                      res->Data.Address32.Minimum,
  343                                      res->Data.Address32.AddressLength));
  344                     set->set_ioport(dev, context,
  345                                     res->Data.Address32.Minimum,
  346                                     res->Data.Address32.AddressLength);
  347                 }
  348             } else {
  349                 if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
  350                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
  351                                      "Address32/Memory 0x%x-0x%x/%d\n",
  352                                      res->Data.Address32.Minimum,
  353                                      res->Data.Address32.Maximum,
  354                                      res->Data.Address32.AddressLength));
  355                     set->set_memoryrange(dev, context,
  356                                           res->Data.Address32.Minimum,
  357                                           res->Data.Address32.Maximum,
  358                                           res->Data.Address32.AddressLength,
  359                                           res->Data.Address32.Granularity);
  360                 } else {
  361                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
  362                                      "Address32/IO 0x%x-0x%x/%d\n",
  363                                      res->Data.Address32.Minimum,
  364                                      res->Data.Address32.Maximum,
  365                                      res->Data.Address32.AddressLength));
  366                     set->set_iorange(dev, context,
  367                                      res->Data.Address32.Minimum,
  368                                      res->Data.Address32.Maximum,
  369                                      res->Data.Address32.AddressLength,
  370                                      res->Data.Address32.Granularity);
  371                 }
  372             }               
  373             break;
  374         case ACPI_RESOURCE_TYPE_ADDRESS16:
  375             if (res->Data.Address16.AddressLength <= 0)
  376                 break;
  377             if (res->Data.Address16.ProducerConsumer != ACPI_CONSUMER) {
  378                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
  379                     "ignored Address16 %s producer\n",
  380                     res->Data.Address16.ResourceType == ACPI_IO_RANGE ?
  381                     "IO" : "Memory"));
  382                 break;
  383             }
  384             if (res->Data.Address16.ResourceType != ACPI_MEMORY_RANGE &&
  385                 res->Data.Address16.ResourceType != ACPI_IO_RANGE) {
  386                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
  387                         "ignored Address16 for non-memory, non-I/O\n"));
  388                 break;
  389             }
  390 
  391             if (res->Data.Address16.MinAddressFixed == ACPI_ADDRESS_FIXED &&
  392                 res->Data.Address16.MaxAddressFixed == ACPI_ADDRESS_FIXED) {
  393 
  394                 if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
  395                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
  396                                      "Address16/Memory 0x%x/%d\n",
  397                                      res->Data.Address16.Minimum,
  398                                      res->Data.Address16.AddressLength));
  399                     set->set_memory(dev, context,
  400                                     res->Data.Address16.Minimum,
  401                                     res->Data.Address16.AddressLength);
  402                 } else {
  403                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
  404                                      "Address16/IO 0x%x/%d\n",
  405                                      res->Data.Address16.Minimum,
  406                                      res->Data.Address16.AddressLength));
  407                     set->set_ioport(dev, context,
  408                                     res->Data.Address16.Minimum,
  409                                     res->Data.Address16.AddressLength);
  410                 }
  411             } else {
  412                 if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
  413                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
  414                                      "Address16/Memory 0x%x-0x%x/%d\n",
  415                                      res->Data.Address16.Minimum,
  416                                      res->Data.Address16.Maximum,
  417                                      res->Data.Address16.AddressLength));
  418                     set->set_memoryrange(dev, context,
  419                                           res->Data.Address16.Minimum,
  420                                           res->Data.Address16.Maximum,
  421                                           res->Data.Address16.AddressLength,
  422                                           res->Data.Address16.Granularity);
  423                 } else {
  424                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
  425                                      "Address16/IO 0x%x-0x%x/%d\n",
  426                                      res->Data.Address16.Minimum,
  427                                      res->Data.Address16.Maximum,
  428                                      res->Data.Address16.AddressLength));
  429                     set->set_iorange(dev, context,
  430                                      res->Data.Address16.Minimum,
  431                                      res->Data.Address16.Maximum,
  432                                      res->Data.Address16.AddressLength,
  433                                      res->Data.Address16.Granularity);
  434                 }
  435             }               
  436             break;
  437         case ACPI_RESOURCE_TYPE_ADDRESS64:
  438             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
  439                              "unimplemented Address64 resource\n"));
  440             break;
  441         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
  442             if (res->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) {
  443                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
  444                     "ignored ExtIRQ producer\n"));
  445                 break;
  446             }
  447             set->set_ext_irq(dev, context, res->Data.ExtendedIrq.Interrupts,
  448                 res->Data.ExtendedIrq.InterruptCount,
  449                 res->Data.ExtendedIrq.Triggering,
  450                 res->Data.ExtendedIrq.Polarity);
  451             break;
  452         case ACPI_RESOURCE_TYPE_VENDOR:
  453             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
  454                              "unimplemented VendorSpecific resource\n"));
  455             break;
  456         default:
  457             break;
  458         }
  459     }    
  460 
  461     AcpiOsFree(buf.Pointer);
  462     set->set_done(dev, context);
  463     return_ACPI_STATUS (AE_OK);
  464 }
  465 
  466 /*
  467  * Resource-set vectors used to attach _CRS-derived resources 
  468  * to an ACPI device.
  469  */
  470 static void     acpi_res_set_init(device_t dev, void *arg, void **context);
  471 static void     acpi_res_set_done(device_t dev, void *context);
  472 static void     acpi_res_set_ioport(device_t dev, void *context,
  473                                     u_int32_t base, u_int32_t length);
  474 static void     acpi_res_set_iorange(device_t dev, void *context,
  475                                      u_int32_t low, u_int32_t high, 
  476                                      u_int32_t length, u_int32_t align);
  477 static void     acpi_res_set_memory(device_t dev, void *context,
  478                                     u_int32_t base, u_int32_t length);
  479 static void     acpi_res_set_memoryrange(device_t dev, void *context,
  480                                          u_int32_t low, u_int32_t high, 
  481                                          u_int32_t length, u_int32_t align);
  482 static void     acpi_res_set_irq(device_t dev, void *context, u_int8_t *irq,
  483                                  int count, int trig, int pol);
  484 static void     acpi_res_set_ext_irq(device_t dev, void *context,
  485                                  u_int32_t *irq, int count, int trig, int pol);
  486 static void     acpi_res_set_drq(device_t dev, void *context, u_int8_t *drq,
  487                                  int count);
  488 static void     acpi_res_set_start_dependent(device_t dev, void *context,
  489                                              int preference);
  490 static void     acpi_res_set_end_dependent(device_t dev, void *context);
  491 
  492 struct acpi_parse_resource_set acpi_res_parse_set = {
  493     acpi_res_set_init,
  494     acpi_res_set_done,
  495     acpi_res_set_ioport,
  496     acpi_res_set_iorange,
  497     acpi_res_set_memory,
  498     acpi_res_set_memoryrange,
  499     acpi_res_set_irq,
  500     acpi_res_set_ext_irq,
  501     acpi_res_set_drq,
  502     acpi_res_set_start_dependent,
  503     acpi_res_set_end_dependent
  504 };
  505 
  506 struct acpi_res_context {
  507     int         ar_nio;
  508     int         ar_nmem;
  509     int         ar_nirq;
  510     int         ar_ndrq;
  511     void        *ar_parent;
  512 };
  513 
  514 static void
  515 acpi_res_set_init(device_t dev, void *arg, void **context)
  516 {
  517     struct acpi_res_context     *cp;
  518 
  519     if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) {
  520         bzero(cp, sizeof(*cp));
  521         cp->ar_parent = arg;
  522         *context = cp;
  523     }
  524 }
  525 
  526 static void
  527 acpi_res_set_done(device_t dev, void *context)
  528 {
  529     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
  530 
  531     if (cp == NULL)
  532         return;
  533     AcpiOsFree(cp);
  534 }
  535 
  536 static void
  537 acpi_res_set_ioport(device_t dev, void *context, u_int32_t base,
  538                     u_int32_t length)
  539 {
  540     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
  541 
  542     if (cp == NULL)
  543         return;
  544     bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length);
  545 }
  546 
  547 static void
  548 acpi_res_set_iorange(device_t dev, void *context, u_int32_t low,
  549                      u_int32_t high, u_int32_t length, u_int32_t align)
  550 {
  551     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
  552 
  553     if (cp == NULL)
  554         return;
  555     device_printf(dev, "I/O range not supported\n");
  556 }
  557 
  558 static void
  559 acpi_res_set_memory(device_t dev, void *context, u_int32_t base,
  560                     u_int32_t length)
  561 {
  562     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
  563 
  564     if (cp == NULL)
  565         return;
  566 
  567     bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
  568 }
  569 
  570 static void
  571 acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low,
  572                          u_int32_t high, u_int32_t length, u_int32_t align)
  573 {
  574     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
  575 
  576     if (cp == NULL)
  577         return;
  578     device_printf(dev, "memory range not supported\n");
  579 }
  580 
  581 static void
  582 acpi_res_set_irq(device_t dev, void *context, u_int8_t *irq, int count,
  583     int trig, int pol)
  584 {
  585     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
  586 
  587     if (cp == NULL || irq == NULL)
  588         return;
  589 
  590     /* This implements no resource relocation. */
  591     if (count != 1)
  592         return;
  593 
  594     bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
  595 }
  596 
  597 static void
  598 acpi_res_set_ext_irq(device_t dev, void *context, u_int32_t *irq, int count,
  599     int trig, int pol)
  600 {
  601     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
  602 
  603     if (cp == NULL || irq == NULL)
  604         return;
  605 
  606     /* This implements no resource relocation. */
  607     if (count != 1)
  608         return;
  609 
  610     bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
  611 }
  612 
  613 static void
  614 acpi_res_set_drq(device_t dev, void *context, u_int8_t *drq, int count)
  615 {
  616     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
  617 
  618     if (cp == NULL || drq == NULL)
  619         return;
  620     
  621     /* This implements no resource relocation. */
  622     if (count != 1)
  623         return;
  624 
  625     bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
  626 }
  627 
  628 static void
  629 acpi_res_set_start_dependent(device_t dev, void *context, int preference)
  630 {
  631     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
  632 
  633     if (cp == NULL)
  634         return;
  635     device_printf(dev, "dependent functions not supported\n");
  636 }
  637 
  638 static void
  639 acpi_res_set_end_dependent(device_t dev, void *context)
  640 {
  641     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
  642 
  643     if (cp == NULL)
  644         return;
  645     device_printf(dev, "dependent functions not supported\n");
  646 }
  647 
  648 /*
  649  * Resource-owning placeholders for IO and memory pseudo-devices.
  650  *
  651  * This code allocates system resources that will be used by ACPI
  652  * child devices.  The acpi parent manages these resources through a
  653  * private rman.
  654  */
  655 
  656 static int      acpi_sysres_rid = 100;
  657 
  658 static int      acpi_sysres_probe(device_t dev);
  659 static int      acpi_sysres_attach(device_t dev);
  660 
  661 static device_method_t acpi_sysres_methods[] = {
  662     /* Device interface */
  663     DEVMETHOD(device_probe,     acpi_sysres_probe),
  664     DEVMETHOD(device_attach,    acpi_sysres_attach),
  665 
  666     {0, 0}
  667 };
  668 
  669 static driver_t acpi_sysres_driver = {
  670     "acpi_sysresource",
  671     acpi_sysres_methods,
  672     0,
  673 };
  674 
  675 static devclass_t acpi_sysres_devclass;
  676 DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysres_driver, acpi_sysres_devclass,
  677     0, 0);
  678 MODULE_DEPEND(acpi_sysresource, acpi, 1, 1, 1);
  679 
  680 static int
  681 acpi_sysres_probe(device_t dev)
  682 {
  683     static char *sysres_ids[] = { "PNP0C01", "PNP0C02", NULL };
  684 
  685     if (acpi_disabled("sysresource") ||
  686         ACPI_ID_PROBE(device_get_parent(dev), dev, sysres_ids) == NULL)
  687         return (ENXIO);
  688 
  689     device_set_desc(dev, "System Resource");
  690     device_quiet(dev);
  691     return (BUS_PROBE_DEFAULT);
  692 }
  693 
  694 static int
  695 acpi_sysres_attach(device_t dev)
  696 {
  697     device_t bus;
  698     struct resource_list_entry *bus_rle, *dev_rle;
  699     struct resource_list *bus_rl, *dev_rl;
  700     int done, type;
  701     u_long start, end, count;
  702 
  703     /*
  704      * Loop through all current resources to see if the new one overlaps
  705      * any existing ones.  If so, grow the old one up and/or down
  706      * accordingly.  Discard any that are wholly contained in the old.  If
  707      * the resource is unique, add it to the parent.  It will later go into
  708      * the rman pool.
  709      */
  710     bus = device_get_parent(dev);
  711     dev_rl = BUS_GET_RESOURCE_LIST(bus, dev);
  712     bus_rl = BUS_GET_RESOURCE_LIST(device_get_parent(bus), bus);
  713     STAILQ_FOREACH(dev_rle, dev_rl, link) {
  714         if (dev_rle->type != SYS_RES_IOPORT && dev_rle->type != SYS_RES_MEMORY)
  715             continue;
  716 
  717         start = dev_rle->start;
  718         end = dev_rle->end;
  719         count = dev_rle->count;
  720         type = dev_rle->type;
  721         done = FALSE;
  722 
  723         STAILQ_FOREACH(bus_rle, bus_rl, link) {
  724             if (bus_rle->type != type)
  725                 continue;
  726 
  727             /* New resource wholly contained in old, discard. */
  728             if (start >= bus_rle->start && end <= bus_rle->end)
  729                 break;
  730 
  731             /* New tail overlaps old head, grow existing resource downward. */
  732             if (start < bus_rle->start && end >= bus_rle->start) {
  733                 bus_rle->count += bus_rle->start - start;
  734                 bus_rle->start = start;
  735                 done = TRUE;
  736             }
  737 
  738             /* New head overlaps old tail, grow existing resource upward. */
  739             if (start <= bus_rle->end && end > bus_rle->end) {
  740                 bus_rle->count += end - bus_rle->end;
  741                 bus_rle->end = end;
  742                 done = TRUE;
  743             }
  744 
  745             /* If we adjusted the old resource, we're finished. */
  746             if (done)
  747                 break;
  748         }
  749 
  750         /* If we didn't merge with anything, add this resource. */
  751         if (bus_rle == NULL)
  752             bus_set_resource(bus, type, acpi_sysres_rid++, start, count);
  753     }
  754 
  755     /* After merging/moving resources to the parent, free the list. */
  756     resource_list_free(dev_rl);
  757 
  758     return (0);
  759 }

Cache object: fe1289a86446bfffdfcf896005175b71


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