ACPICA: Restructure includes into public/private
[deliverable/linux.git] / drivers / acpi / executer / exfldio.c
index 1ece1c3fc37560661feab1e04b950cf221705202..33cd17a1064f7c7444ead73f4338341bc47b60a1 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2007, R. Byron Moore
+ * Copyright (C) 2000 - 2008, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -42,6 +42,7 @@
  */
 
 #include <acpi/acpi.h>
+#include <acpi/accommon.h>
 #include <acpi/acinterp.h>
 #include <acpi/amlcode.h>
 #include <acpi/acevents.h>
@@ -153,14 +154,15 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
                        /*
                         * Slack mode only:  We will go ahead and allow access to this
                         * field if it is within the region length rounded up to the next
-                        * access width boundary.
+                        * access width boundary. acpi_size cast for 64-bit compile.
                         */
                        if (ACPI_ROUND_UP(rgn_desc->region.length,
                                          obj_desc->common_field.
                                          access_byte_width) >=
-                           (obj_desc->common_field.base_byte_offset +
-                            (acpi_native_uint) obj_desc->common_field.
-                            access_byte_width + field_datum_byte_offset)) {
+                           ((acpi_size) obj_desc->common_field.
+                            base_byte_offset +
+                            obj_desc->common_field.access_byte_width +
+                            field_datum_byte_offset)) {
                                return_ACPI_STATUS(AE_OK);
                        }
                }
@@ -497,14 +499,13 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
                        return_ACPI_STATUS(status);
                }
 
-               ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-                                 "I/O to Data Register: ValuePtr %p\n",
-                                 value));
-
                if (read_write == ACPI_READ) {
 
                        /* Read the datum from the data_register */
 
+                       ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+                                         "Read from Data Register\n"));
+
                        status =
                            acpi_ex_extract_from_field(obj_desc->index_field.
                                                       data_obj, value,
@@ -512,6 +513,10 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
                } else {
                        /* Write the datum to the data_register */
 
+                       ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+                                         "Write to Data Register: Value %8.8X%8.8X\n",
+                                         ACPI_FORMAT_UINT64(*value)));
+
                        status =
                            acpi_ex_insert_into_field(obj_desc->index_field.
                                                      data_obj, value,
@@ -806,18 +811,39 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
        u32 datum_count;
        u32 field_datum_count;
        u32 i;
+       u32 required_length;
+       void *new_buffer;
 
        ACPI_FUNCTION_TRACE(ex_insert_into_field);
 
        /* Validate input buffer */
 
-       if (buffer_length <
-           ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
-               ACPI_ERROR((AE_INFO,
-                           "Field size %X (bits) is too large for buffer (%X)",
-                           obj_desc->common_field.bit_length, buffer_length));
+       new_buffer = NULL;
+       required_length =
+           ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
+       /*
+        * We must have a buffer that is at least as long as the field
+        * we are writing to.  This is because individual fields are
+        * indivisible and partial writes are not supported -- as per
+        * the ACPI specification.
+        */
+       if (buffer_length < required_length) {
 
-               return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
+               /* We need to create a new buffer */
+
+               new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
+               if (!new_buffer) {
+                       return_ACPI_STATUS(AE_NO_MEMORY);
+               }
+
+               /*
+                * Copy the original data to the new buffer, starting
+                * at Byte zero.  All unused (upper) bytes of the
+                * buffer will be 0.
+                */
+               ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length);
+               buffer = new_buffer;
+               buffer_length = required_length;
        }
 
        /*
@@ -867,7 +893,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
                                                        merged_datum,
                                                        field_offset);
                if (ACPI_FAILURE(status)) {
-                       return_ACPI_STATUS(status);
+                       goto exit;
                }
 
                field_offset += obj_desc->common_field.access_byte_width;
@@ -925,5 +951,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
                                                mask, merged_datum,
                                                field_offset);
 
+      exit:
+       /* Free temporary buffer if we used one */
+
+       if (new_buffer) {
+               ACPI_FREE(new_buffer);
+       }
        return_ACPI_STATUS(status);
 }
This page took 0.026078 seconds and 5 git commands to generate.