Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /******************************************************************************
  2.  *
  3.  * Module Name: exregion - ACPI default op_region (address space) handlers
  4.  *
  5.  *****************************************************************************/
  6.  
  7. /*
  8.  * Copyright (C) 2000 - 2015, Intel Corp.
  9.  * All rights reserved.
  10.  *
  11.  * Redistribution and use in source and binary forms, with or without
  12.  * modification, are permitted provided that the following conditions
  13.  * are met:
  14.  * 1. Redistributions of source code must retain the above copyright
  15.  *    notice, this list of conditions, and the following disclaimer,
  16.  *    without modification.
  17.  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18.  *    substantially similar to the "NO WARRANTY" disclaimer below
  19.  *    ("Disclaimer") and any redistribution must be conditioned upon
  20.  *    including a substantially similar Disclaimer requirement for further
  21.  *    binary redistribution.
  22.  * 3. Neither the names of the above-listed copyright holders nor the names
  23.  *    of any contributors may be used to endorse or promote products derived
  24.  *    from this software without specific prior written permission.
  25.  *
  26.  * Alternatively, this software may be distributed under the terms of the
  27.  * GNU General Public License ("GPL") version 2 as published by the Free
  28.  * Software Foundation.
  29.  *
  30.  * NO WARRANTY
  31.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35.  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40.  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41.  * POSSIBILITY OF SUCH DAMAGES.
  42.  */
  43.  
  44. #include <acpi/acpi.h>
  45. #include "accommon.h"
  46. #include "acinterp.h"
  47.  
  48. #define _COMPONENT          ACPI_EXECUTER
  49. ACPI_MODULE_NAME("exregion")
  50.  
  51. /*******************************************************************************
  52.  *
  53.  * FUNCTION:    acpi_ex_system_memory_space_handler
  54.  *
  55.  * PARAMETERS:  function            - Read or Write operation
  56.  *              address             - Where in the space to read or write
  57.  *              bit_width           - Field width in bits (8, 16, or 32)
  58.  *              value               - Pointer to in or out value
  59.  *              handler_context     - Pointer to Handler's context
  60.  *              region_context      - Pointer to context specific to the
  61.  *                                    accessed region
  62.  *
  63.  * RETURN:      Status
  64.  *
  65.  * DESCRIPTION: Handler for the System Memory address space (Op Region)
  66.  *
  67.  ******************************************************************************/
  68. acpi_status
  69. acpi_ex_system_memory_space_handler(u32 function,
  70.                                     acpi_physical_address address,
  71.                                     u32 bit_width,
  72.                                     u64 *value,
  73.                                     void *handler_context, void *region_context)
  74. {
  75.         acpi_status status = AE_OK;
  76.         void *logical_addr_ptr = NULL;
  77.         struct acpi_mem_space_context *mem_info = region_context;
  78.         u32 length;
  79.         acpi_size map_length;
  80.         acpi_size page_boundary_map_length;
  81. #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
  82.         u32 remainder;
  83. #endif
  84.  
  85.         ACPI_FUNCTION_TRACE(ex_system_memory_space_handler);
  86.  
  87.         /* Validate and translate the bit width */
  88.  
  89.         switch (bit_width) {
  90.         case 8:
  91.  
  92.                 length = 1;
  93.                 break;
  94.  
  95.         case 16:
  96.  
  97.                 length = 2;
  98.                 break;
  99.  
  100.         case 32:
  101.  
  102.                 length = 4;
  103.                 break;
  104.  
  105.         case 64:
  106.  
  107.                 length = 8;
  108.                 break;
  109.  
  110.         default:
  111.  
  112.                 ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %u",
  113.                             bit_width));
  114.                 return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
  115.         }
  116.  
  117. #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
  118.         /*
  119.          * Hardware does not support non-aligned data transfers, we must verify
  120.          * the request.
  121.          */
  122.         (void)acpi_ut_short_divide((u64) address, length, NULL, &remainder);
  123.         if (remainder != 0) {
  124.                 return_ACPI_STATUS(AE_AML_ALIGNMENT);
  125.         }
  126. #endif
  127.  
  128.         /*
  129.          * Does the request fit into the cached memory mapping?
  130.          * Is 1) Address below the current mapping? OR
  131.          *    2) Address beyond the current mapping?
  132.          */
  133.         if ((address < mem_info->mapped_physical_address) ||
  134.             (((u64) address + length) > ((u64)
  135.                                          mem_info->mapped_physical_address +
  136.                                          mem_info->mapped_length))) {
  137.                 /*
  138.                  * The request cannot be resolved by the current memory mapping;
  139.                  * Delete the existing mapping and create a new one.
  140.                  */
  141.                 if (mem_info->mapped_length) {
  142.  
  143.                         /* Valid mapping, delete it */
  144.  
  145.                         acpi_os_unmap_memory(mem_info->mapped_logical_address,
  146.                                              mem_info->mapped_length);
  147.                 }
  148.  
  149.                 /*
  150.                  * October 2009: Attempt to map from the requested address to the
  151.                  * end of the region. However, we will never map more than one
  152.                  * page, nor will we cross a page boundary.
  153.                  */
  154.                 map_length = (acpi_size)
  155.                     ((mem_info->address + mem_info->length) - address);
  156.  
  157.                 /*
  158.                  * If mapping the entire remaining portion of the region will cross
  159.                  * a page boundary, just map up to the page boundary, do not cross.
  160.                  * On some systems, crossing a page boundary while mapping regions
  161.                  * can cause warnings if the pages have different attributes
  162.                  * due to resource management.
  163.                  *
  164.                  * This has the added benefit of constraining a single mapping to
  165.                  * one page, which is similar to the original code that used a 4k
  166.                  * maximum window.
  167.                  */
  168.                 page_boundary_map_length = (acpi_size)
  169.                     (ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address);
  170.                 if (page_boundary_map_length == 0) {
  171.                         page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE;
  172.                 }
  173.  
  174.                 if (map_length > page_boundary_map_length) {
  175.                         map_length = page_boundary_map_length;
  176.                 }
  177.  
  178.                 /* Create a new mapping starting at the address given */
  179.  
  180.                 mem_info->mapped_logical_address =
  181.                     acpi_os_map_memory(address, map_length);
  182.                 if (!mem_info->mapped_logical_address) {
  183.                         ACPI_ERROR((AE_INFO,
  184.                                     "Could not map memory at 0x%8.8X%8.8X, size %u",
  185.                                     ACPI_FORMAT_UINT64(address),
  186.                                     (u32)map_length));
  187.                         mem_info->mapped_length = 0;
  188.                         return_ACPI_STATUS(AE_NO_MEMORY);
  189.                 }
  190.  
  191.                 /* Save the physical address and mapping size */
  192.  
  193.                 mem_info->mapped_physical_address = address;
  194.                 mem_info->mapped_length = map_length;
  195.         }
  196.  
  197.         /*
  198.          * Generate a logical pointer corresponding to the address we want to
  199.          * access
  200.          */
  201.         logical_addr_ptr = mem_info->mapped_logical_address +
  202.             ((u64) address - (u64) mem_info->mapped_physical_address);
  203.  
  204.         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  205.                           "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
  206.                           bit_width, function, ACPI_FORMAT_UINT64(address)));
  207.  
  208.         /*
  209.          * Perform the memory read or write
  210.          *
  211.          * Note: For machines that do not support non-aligned transfers, the target
  212.          * address was checked for alignment above. We do not attempt to break the
  213.          * transfer up into smaller (byte-size) chunks because the AML specifically
  214.          * asked for a transfer width that the hardware may require.
  215.          */
  216.         switch (function) {
  217.         case ACPI_READ:
  218.  
  219.                 *value = 0;
  220.                 switch (bit_width) {
  221.                 case 8:
  222.  
  223.                         *value = (u64)ACPI_GET8(logical_addr_ptr);
  224.                         break;
  225.  
  226.                 case 16:
  227.  
  228.                         *value = (u64)ACPI_GET16(logical_addr_ptr);
  229.                         break;
  230.  
  231.                 case 32:
  232.  
  233.                         *value = (u64)ACPI_GET32(logical_addr_ptr);
  234.                         break;
  235.  
  236.                 case 64:
  237.  
  238.                         *value = (u64)ACPI_GET64(logical_addr_ptr);
  239.                         break;
  240.  
  241.                 default:
  242.  
  243.                         /* bit_width was already validated */
  244.  
  245.                         break;
  246.                 }
  247.                 break;
  248.  
  249.         case ACPI_WRITE:
  250.  
  251.                 switch (bit_width) {
  252.                 case 8:
  253.  
  254.                         ACPI_SET8(logical_addr_ptr, *value);
  255.                         break;
  256.  
  257.                 case 16:
  258.  
  259.                         ACPI_SET16(logical_addr_ptr, *value);
  260.                         break;
  261.  
  262.                 case 32:
  263.  
  264.                         ACPI_SET32(logical_addr_ptr, *value);
  265.                         break;
  266.  
  267.                 case 64:
  268.  
  269.                         ACPI_SET64(logical_addr_ptr, *value);
  270.                         break;
  271.  
  272.                 default:
  273.  
  274.                         /* bit_width was already validated */
  275.  
  276.                         break;
  277.                 }
  278.                 break;
  279.  
  280.         default:
  281.  
  282.                 status = AE_BAD_PARAMETER;
  283.                 break;
  284.         }
  285.  
  286.         return_ACPI_STATUS(status);
  287. }
  288.  
  289. /*******************************************************************************
  290.  *
  291.  * FUNCTION:    acpi_ex_system_io_space_handler
  292.  *
  293.  * PARAMETERS:  function            - Read or Write operation
  294.  *              address             - Where in the space to read or write
  295.  *              bit_width           - Field width in bits (8, 16, or 32)
  296.  *              value               - Pointer to in or out value
  297.  *              handler_context     - Pointer to Handler's context
  298.  *              region_context      - Pointer to context specific to the
  299.  *                                    accessed region
  300.  *
  301.  * RETURN:      Status
  302.  *
  303.  * DESCRIPTION: Handler for the System IO address space (Op Region)
  304.  *
  305.  ******************************************************************************/
  306.  
  307. acpi_status
  308. acpi_ex_system_io_space_handler(u32 function,
  309.                                 acpi_physical_address address,
  310.                                 u32 bit_width,
  311.                                 u64 *value,
  312.                                 void *handler_context, void *region_context)
  313. {
  314.         acpi_status status = AE_OK;
  315.         u32 value32;
  316.  
  317.         ACPI_FUNCTION_TRACE(ex_system_io_space_handler);
  318.  
  319.         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  320.                           "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
  321.                           bit_width, function, ACPI_FORMAT_UINT64(address)));
  322.  
  323.         /* Decode the function parameter */
  324.  
  325.         switch (function) {
  326.         case ACPI_READ:
  327.  
  328.                 status = acpi_hw_read_port((acpi_io_address) address,
  329.                                            &value32, bit_width);
  330.                 *value = value32;
  331.                 break;
  332.  
  333.         case ACPI_WRITE:
  334.  
  335.                 status = acpi_hw_write_port((acpi_io_address) address,
  336.                                             (u32) * value, bit_width);
  337.                 break;
  338.  
  339.         default:
  340.  
  341.                 status = AE_BAD_PARAMETER;
  342.                 break;
  343.         }
  344.  
  345.         return_ACPI_STATUS(status);
  346. }
  347.  
  348. /*******************************************************************************
  349.  *
  350.  * FUNCTION:    acpi_ex_pci_config_space_handler
  351.  *
  352.  * PARAMETERS:  function            - Read or Write operation
  353.  *              address             - Where in the space to read or write
  354.  *              bit_width           - Field width in bits (8, 16, or 32)
  355.  *              value               - Pointer to in or out value
  356.  *              handler_context     - Pointer to Handler's context
  357.  *              region_context      - Pointer to context specific to the
  358.  *                                    accessed region
  359.  *
  360.  * RETURN:      Status
  361.  *
  362.  * DESCRIPTION: Handler for the PCI Config address space (Op Region)
  363.  *
  364.  ******************************************************************************/
  365.  
  366. acpi_status
  367. acpi_ex_pci_config_space_handler(u32 function,
  368.                                  acpi_physical_address address,
  369.                                  u32 bit_width,
  370.                                  u64 *value,
  371.                                  void *handler_context, void *region_context)
  372. {
  373.         acpi_status status = AE_OK;
  374.         struct acpi_pci_id *pci_id;
  375.         u16 pci_register;
  376.  
  377.         ACPI_FUNCTION_TRACE(ex_pci_config_space_handler);
  378.  
  379.         /*
  380.          *  The arguments to acpi_os(Read|Write)pci_configuration are:
  381.          *
  382.          *  pci_segment is the PCI bus segment range 0-31
  383.          *  pci_bus     is the PCI bus number range 0-255
  384.          *  pci_device  is the PCI device number range 0-31
  385.          *  pci_function is the PCI device function number
  386.          *  pci_register is the Config space register range 0-255 bytes
  387.          *
  388.          *  value - input value for write, output address for read
  389.          *
  390.          */
  391.         pci_id = (struct acpi_pci_id *)region_context;
  392.         pci_register = (u16) (u32) address;
  393.  
  394.         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  395.                           "Pci-Config %u (%u) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
  396.                           function, bit_width, pci_id->segment, pci_id->bus,
  397.                           pci_id->device, pci_id->function, pci_register));
  398.  
  399.         switch (function) {
  400.         case ACPI_READ:
  401.  
  402.                 *value = 0;
  403.                 status = acpi_os_read_pci_configuration(pci_id, pci_register,
  404.                                                         value, bit_width);
  405.                 break;
  406.  
  407.         case ACPI_WRITE:
  408.  
  409.                 status = acpi_os_write_pci_configuration(pci_id, pci_register,
  410.                                                          *value, bit_width);
  411.                 break;
  412.  
  413.         default:
  414.  
  415.                 status = AE_BAD_PARAMETER;
  416.                 break;
  417.         }
  418.  
  419.         return_ACPI_STATUS(status);
  420. }
  421.  
  422. /*******************************************************************************
  423.  *
  424.  * FUNCTION:    acpi_ex_cmos_space_handler
  425.  *
  426.  * PARAMETERS:  function            - Read or Write operation
  427.  *              address             - Where in the space to read or write
  428.  *              bit_width           - Field width in bits (8, 16, or 32)
  429.  *              value               - Pointer to in or out value
  430.  *              handler_context     - Pointer to Handler's context
  431.  *              region_context      - Pointer to context specific to the
  432.  *                                    accessed region
  433.  *
  434.  * RETURN:      Status
  435.  *
  436.  * DESCRIPTION: Handler for the CMOS address space (Op Region)
  437.  *
  438.  ******************************************************************************/
  439.  
  440. acpi_status
  441. acpi_ex_cmos_space_handler(u32 function,
  442.                            acpi_physical_address address,
  443.                            u32 bit_width,
  444.                            u64 *value,
  445.                            void *handler_context, void *region_context)
  446. {
  447.         acpi_status status = AE_OK;
  448.  
  449.         ACPI_FUNCTION_TRACE(ex_cmos_space_handler);
  450.  
  451.         return_ACPI_STATUS(status);
  452. }
  453.  
  454. /*******************************************************************************
  455.  *
  456.  * FUNCTION:    acpi_ex_pci_bar_space_handler
  457.  *
  458.  * PARAMETERS:  function            - Read or Write operation
  459.  *              address             - Where in the space to read or write
  460.  *              bit_width           - Field width in bits (8, 16, or 32)
  461.  *              value               - Pointer to in or out value
  462.  *              handler_context     - Pointer to Handler's context
  463.  *              region_context      - Pointer to context specific to the
  464.  *                                    accessed region
  465.  *
  466.  * RETURN:      Status
  467.  *
  468.  * DESCRIPTION: Handler for the PCI bar_target address space (Op Region)
  469.  *
  470.  ******************************************************************************/
  471.  
  472. acpi_status
  473. acpi_ex_pci_bar_space_handler(u32 function,
  474.                               acpi_physical_address address,
  475.                               u32 bit_width,
  476.                               u64 *value,
  477.                               void *handler_context, void *region_context)
  478. {
  479.         acpi_status status = AE_OK;
  480.  
  481.         ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler);
  482.  
  483.         return_ACPI_STATUS(status);
  484. }
  485.  
  486. /*******************************************************************************
  487.  *
  488.  * FUNCTION:    acpi_ex_data_table_space_handler
  489.  *
  490.  * PARAMETERS:  function            - Read or Write operation
  491.  *              address             - Where in the space to read or write
  492.  *              bit_width           - Field width in bits (8, 16, or 32)
  493.  *              value               - Pointer to in or out value
  494.  *              handler_context     - Pointer to Handler's context
  495.  *              region_context      - Pointer to context specific to the
  496.  *                                    accessed region
  497.  *
  498.  * RETURN:      Status
  499.  *
  500.  * DESCRIPTION: Handler for the Data Table address space (Op Region)
  501.  *
  502.  ******************************************************************************/
  503.  
  504. acpi_status
  505. acpi_ex_data_table_space_handler(u32 function,
  506.                                  acpi_physical_address address,
  507.                                  u32 bit_width,
  508.                                  u64 *value,
  509.                                  void *handler_context, void *region_context)
  510. {
  511.         ACPI_FUNCTION_TRACE(ex_data_table_space_handler);
  512.  
  513.         /*
  514.          * Perform the memory read or write. The bit_width was already
  515.          * validated.
  516.          */
  517.         switch (function) {
  518.         case ACPI_READ:
  519.  
  520.                 memcpy(ACPI_CAST_PTR(char, value),
  521.                        ACPI_PHYSADDR_TO_PTR(address), ACPI_DIV_8(bit_width));
  522.                 break;
  523.  
  524.         case ACPI_WRITE:
  525.  
  526.                 memcpy(ACPI_PHYSADDR_TO_PTR(address),
  527.                        ACPI_CAST_PTR(char, value), ACPI_DIV_8(bit_width));
  528.                 break;
  529.  
  530.         default:
  531.  
  532.                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  533.         }
  534.  
  535.         return_ACPI_STATUS(AE_OK);
  536. }
  537.