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/Osd/OsdHardware.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) 2000, 2001 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 /*
   29  * 6.7 : Hardware Abstraction
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #include <contrib/dev/acpica/acpi.h>
   36 
   37 #include <sys/bus.h>
   38 #include <sys/kernel.h>
   39 #include <machine/bus.h>
   40 #include <machine/pci_cfgreg.h>
   41 #include <dev/acpica/acpivar.h>
   42 #include <dev/pci/pcireg.h>
   43 
   44 /*
   45  * ACPICA's rather gung-ho approach to hardware resource ownership is a little
   46  * troublesome insofar as there is no easy way for us to know in advance
   47  * exactly which I/O resources it's going to want to use.
   48  *
   49  * In order to deal with this, we ignore resource ownership entirely, and simply
   50  * use the native I/O space accessor functionality.  This is Evil, but it works.
   51  *
   52  * XXX use an intermediate #define for the tag/handle
   53  */
   54 
   55 #ifdef __i386__
   56 #define ACPI_BUS_SPACE_IO       I386_BUS_SPACE_IO
   57 #define ACPI_BUS_HANDLE         0
   58 #endif
   59 #ifdef __ia64__
   60 #define ACPI_BUS_SPACE_IO       IA64_BUS_SPACE_IO
   61 #define ACPI_BUS_HANDLE         0
   62 #endif
   63 #ifdef __amd64__
   64 #define ACPI_BUS_SPACE_IO       AMD64_BUS_SPACE_IO
   65 #define ACPI_BUS_HANDLE         0
   66 #endif
   67 
   68 /*
   69  * Some BIOS vendors use AML to read/write directly to IO space.  This
   70  * can cause a problem if such accesses interfere with the OS's access to
   71  * the same ports.  Windows XP and newer systems block accesses to certain
   72  * IO ports.  We print a message or block accesses based on a tunable.
   73  */
   74 static int illegal_bios_ports[] = {
   75         0x000, 0x00f,   /* DMA controller 1 */
   76         0x020, 0x021,   /* PIC */
   77         0x040, 0x043,   /* Timer 1 */
   78         0x048, 0x04b,   /* Timer 2 failsafe */
   79         0x070, 0x071,   /* CMOS and RTC */
   80         0x074, 0x076,   /* Extended CMOS */
   81         0x081, 0x083,   /* DMA1 page registers */
   82         0x087, 0x087,   /* DMA1 ch0 low page */
   83         0x089, 0x08b,   /* DMA2 ch2 (0x89), ch3 low page (0x8a, 0x8b) */
   84         0x08f, 0x091,   /* DMA2 low page refresh (0x8f) */
   85                         /* Arb ctrl port, card select feedback (0x90, 0x91) */
   86         0x093, 0x094,   /* System board setup */
   87         0x096, 0x097,   /* POS channel select */
   88         0x0a0, 0x0a1,   /* PIC (cascaded) */
   89         0x0c0, 0x0df,   /* ISA DMA */
   90         0x4d0, 0x4d1,   /* PIC ELCR (edge/level control) */
   91         0xcf8, 0xcff,   /* PCI config space. Microsoft adds 0xd00 also but
   92                            that seems incorrect. */
   93         -1, -1
   94 };
   95 
   96 /* Block accesses to bad IO port addresses or just print a warning. */
   97 static int block_bad_io;
   98 TUNABLE_INT("debug.acpi.block_bad_io", &block_bad_io);
   99 
  100 /*
  101  * Look up bad ports in our table.  Returns 0 if ok, 1 if marked bad but
  102  * access is still allowed, or -1 to deny access.
  103  */
  104 static int
  105 acpi_os_check_port(UINT32 addr, UINT32 width)
  106 {
  107         int error, *port;
  108 
  109         error = 0;
  110         for (port = illegal_bios_ports; *port != -1; port += 2) {
  111                 if ((addr >= port[0] && addr <= port[1]) ||
  112                     (addr < port[0] && addr + (width / 8) > port[0])) {
  113                         if (block_bad_io)
  114                             error = -1;
  115                         else
  116                             error = 1;
  117                         break;
  118                 }
  119         }
  120 
  121         return (error);
  122 }
  123 
  124 ACPI_STATUS
  125 AcpiOsReadPort(ACPI_IO_ADDRESS InPort, UINT32 *Value, UINT32 Width)
  126 {
  127     int error;
  128 
  129     error = acpi_os_check_port(InPort, Width);
  130     if (error != 0) {
  131         if (bootverbose)
  132                 printf("acpi: bad read from port 0x%03x (%d)\n",
  133                         (int)InPort, Width);
  134         if (error == -1)
  135             return (AE_BAD_PARAMETER);
  136     }
  137 
  138     switch (Width) {
  139     case 8:
  140         *(u_int8_t *)Value = bus_space_read_1(ACPI_BUS_SPACE_IO,
  141             ACPI_BUS_HANDLE, InPort);
  142         break;
  143     case 16:
  144         *(u_int16_t *)Value = bus_space_read_2(ACPI_BUS_SPACE_IO,
  145             ACPI_BUS_HANDLE, InPort);
  146         break;
  147     case 32:
  148         *(u_int32_t *)Value = bus_space_read_4(ACPI_BUS_SPACE_IO,
  149             ACPI_BUS_HANDLE, InPort);
  150         break;
  151     default:
  152         /* debug trap goes here */
  153         break;
  154     }
  155 
  156     return (AE_OK);
  157 }
  158 
  159 ACPI_STATUS
  160 AcpiOsWritePort(ACPI_IO_ADDRESS OutPort, UINT32 Value, UINT32 Width)
  161 {
  162     int error;
  163 
  164     error = acpi_os_check_port(OutPort, Width);
  165     if (error != 0) {
  166         if (bootverbose)
  167                 printf("acpi: bad write to port 0x%03x (%d), val %#x\n",
  168                         (int)OutPort, Width, Value);
  169         if (error == -1)
  170             return (AE_BAD_PARAMETER);
  171     }
  172 
  173     switch (Width) {
  174     case 8:
  175         bus_space_write_1(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value);
  176         break;
  177     case 16:
  178         bus_space_write_2(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value);
  179         break;
  180     case 32:
  181         bus_space_write_4(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value);
  182         break;
  183     default:
  184         /* debug trap goes here */
  185         break;
  186     }
  187 
  188     return (AE_OK);
  189 }
  190 
  191 ACPI_STATUS
  192 AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, void *Value,
  193     UINT32 Width)
  194 {
  195     u_int32_t   byte_width = Width / 8;
  196     u_int32_t   val;
  197 
  198     if (!pci_cfgregopen())
  199         return (AE_NOT_EXIST);
  200 
  201     val = pci_cfgregread(PciId->Bus, PciId->Device, PciId->Function, Register,
  202         byte_width);
  203     switch (Width) {
  204     case 8:
  205         *(u_int8_t *)Value = val & 0xff;
  206         break;
  207     case 16:
  208         *(u_int16_t *)Value = val & 0xffff;
  209         break;
  210     case 32:
  211         *(u_int32_t *)Value = val;
  212         break;
  213     default:
  214         /* debug trap goes here */
  215         break;
  216     }
  217 
  218     return (AE_OK);
  219 }
  220 
  221 
  222 ACPI_STATUS
  223 AcpiOsWritePciConfiguration (ACPI_PCI_ID *PciId, UINT32 Register,
  224     ACPI_INTEGER Value, UINT32 Width)
  225 {
  226     u_int32_t   byte_width = Width / 8;
  227 
  228     if (!pci_cfgregopen())
  229         return (AE_NOT_EXIST);
  230 
  231     pci_cfgregwrite(PciId->Bus, PciId->Device, PciId->Function, Register,
  232         Value, byte_width);
  233 
  234     return (AE_OK);
  235 }
  236 
  237 /*
  238  * Depth-first recursive case for finding the bus, given the slot/function.
  239  */
  240 static int
  241 acpi_bus_number(ACPI_HANDLE root, ACPI_HANDLE curr, ACPI_PCI_ID *PciId)
  242 {
  243     ACPI_HANDLE parent;
  244     ACPI_STATUS status;
  245     ACPI_OBJECT_TYPE type;
  246     UINT32 adr;
  247     int bus, slot, func, class, subclass, header;
  248 
  249     /* Try to get the _BBN object of the root, otherwise assume it is 0. */
  250     bus = 0;
  251     if (root == curr) {
  252         status = acpi_GetInteger(root, "_BBN", &bus);
  253         if (ACPI_FAILURE(status) && bootverbose)
  254             printf("acpi_bus_number: root bus has no _BBN, assuming 0\n");
  255         return (bus);
  256     }
  257     status = AcpiGetParent(curr, &parent);
  258     if (ACPI_FAILURE(status))
  259         return (bus);
  260 
  261     /* First, recurse up the tree until we find the host bus. */
  262     bus = acpi_bus_number(root, parent, PciId);
  263 
  264     /* Validate parent bus device type. */
  265     if (ACPI_FAILURE(AcpiGetType(parent, &type)) || type != ACPI_TYPE_DEVICE) {
  266         printf("acpi_bus_number: not a device, type %d\n", type);
  267         return (bus);
  268     }
  269 
  270     /* Get the parent's slot and function. */
  271     status = acpi_GetInteger(parent, "_ADR", &adr);
  272     if (ACPI_FAILURE(status))
  273         return (bus);
  274     slot = ACPI_HIWORD(adr);
  275     func = ACPI_LOWORD(adr);
  276 
  277     /* Is this a PCI-PCI or Cardbus-PCI bridge? */
  278     class = pci_cfgregread(bus, slot, func, PCIR_CLASS, 1);
  279     if (class != PCIC_BRIDGE)
  280         return (bus);
  281     subclass = pci_cfgregread(bus, slot, func, PCIR_SUBCLASS, 1);
  282 
  283     /* Find the header type, masking off the multifunction bit. */
  284     header = pci_cfgregread(bus, slot, func, PCIR_HDRTYPE, 1) & PCIM_HDRTYPE;
  285     if (header == PCIM_HDRTYPE_BRIDGE && subclass == PCIS_BRIDGE_PCI)
  286         bus = pci_cfgregread(bus, slot, func, PCIR_SECBUS_1, 1);
  287     else if (header == PCIM_HDRTYPE_CARDBUS && subclass == PCIS_BRIDGE_CARDBUS)
  288         bus = pci_cfgregread(bus, slot, func, PCIR_SECBUS_2, 1);
  289     return (bus);
  290 }
  291 
  292 /*
  293  * Find the bus number for a device
  294  *
  295  * rhandle: handle for the root bus
  296  * chandle: handle for the device
  297  * PciId: pointer to device slot and function, we fill out bus
  298  */
  299 void
  300 AcpiOsDerivePciId(ACPI_HANDLE rhandle, ACPI_HANDLE chandle, ACPI_PCI_ID **PciId)
  301 {
  302     ACPI_HANDLE parent;
  303     ACPI_STATUS status;
  304     int bus;
  305 
  306     if (pci_cfgregopen() == 0)
  307         panic("AcpiOsDerivePciId unable to initialize pci bus");
  308 
  309     /* Try to read _BBN for bus number if we're at the root */
  310     bus = 0;
  311     if (rhandle == chandle) {
  312         status = acpi_GetInteger(rhandle, "_BBN", &bus);
  313         if (ACPI_FAILURE(status) && bootverbose)
  314             printf("AcpiOsDerivePciId: root bus has no _BBN, assuming 0\n");
  315     }
  316 
  317     /*
  318      * Get the parent handle and call the recursive case.  It is not
  319      * clear why we seem to be getting a chandle that points to a child
  320      * of the desired slot/function but passing in the parent handle
  321      * here works.
  322      */
  323     if (ACPI_SUCCESS(AcpiGetParent(chandle, &parent)))
  324         bus = acpi_bus_number(rhandle, parent, *PciId);
  325     (*PciId)->Bus = bus;
  326     if (bootverbose) {
  327         printf("AcpiOsDerivePciId: %s -> bus %d dev %d func %d\n",
  328             acpi_name(chandle), (*PciId)->Bus, (*PciId)->Device,
  329             (*PciId)->Function);
  330     }
  331 }

Cache object: 1790396a343b45a0f846598723c5e2ee


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