|
@@ -45,10 +45,71 @@
|
|
|
#include "accommon.h"
|
|
|
#include "acdispat.h"
|
|
|
#include "acinterp.h"
|
|
|
+#include "amlcode.h"
|
|
|
|
|
|
#define _COMPONENT ACPI_EXECUTER
|
|
|
ACPI_MODULE_NAME("exfield")
|
|
|
|
|
|
+/* Local prototypes */
|
|
|
+static u32
|
|
|
+acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length);
|
|
|
+
|
|
|
+/*******************************************************************************
|
|
|
+ *
|
|
|
+ * FUNCTION: acpi_get_serial_access_bytes
|
|
|
+ *
|
|
|
+ * PARAMETERS: accessor_type - The type of the protocol indicated by region
|
|
|
+ * field access attributes
|
|
|
+ * access_length - The access length of the region field
|
|
|
+ *
|
|
|
+ * RETURN: Decoded access length
|
|
|
+ *
|
|
|
+ * DESCRIPTION: This routine returns the length of the generic_serial_bus
|
|
|
+ * protocol bytes
|
|
|
+ *
|
|
|
+ ******************************************************************************/
|
|
|
+
|
|
|
+static u32
|
|
|
+acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length)
|
|
|
+{
|
|
|
+ u32 length;
|
|
|
+
|
|
|
+ switch (accessor_type) {
|
|
|
+ case AML_FIELD_ATTRIB_QUICK:
|
|
|
+
|
|
|
+ length = 0;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case AML_FIELD_ATTRIB_SEND_RCV:
|
|
|
+ case AML_FIELD_ATTRIB_BYTE:
|
|
|
+
|
|
|
+ length = 1;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case AML_FIELD_ATTRIB_WORD:
|
|
|
+ case AML_FIELD_ATTRIB_WORD_CALL:
|
|
|
+
|
|
|
+ length = 2;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case AML_FIELD_ATTRIB_MULTIBYTE:
|
|
|
+ case AML_FIELD_ATTRIB_RAW_BYTES:
|
|
|
+ case AML_FIELD_ATTRIB_RAW_PROCESS:
|
|
|
+
|
|
|
+ length = access_length;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case AML_FIELD_ATTRIB_BLOCK:
|
|
|
+ case AML_FIELD_ATTRIB_BLOCK_CALL:
|
|
|
+ default:
|
|
|
+
|
|
|
+ length = ACPI_GSBUS_BUFFER_SIZE;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (length);
|
|
|
+}
|
|
|
+
|
|
|
/*******************************************************************************
|
|
|
*
|
|
|
* FUNCTION: acpi_ex_read_data_from_field
|
|
@@ -63,8 +124,9 @@ ACPI_MODULE_NAME("exfield")
|
|
|
* Buffer, depending on the size of the field.
|
|
|
*
|
|
|
******************************************************************************/
|
|
|
+
|
|
|
acpi_status
|
|
|
-acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
|
|
|
+acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state,
|
|
|
union acpi_operand_object *obj_desc,
|
|
|
union acpi_operand_object **ret_buffer_desc)
|
|
|
{
|
|
@@ -73,6 +135,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
|
|
|
acpi_size length;
|
|
|
void *buffer;
|
|
|
u32 function;
|
|
|
+ u16 accessor_type;
|
|
|
|
|
|
ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
|
|
|
|
|
@@ -116,9 +179,22 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
|
|
|
ACPI_READ | (obj_desc->field.attribute << 16);
|
|
|
} else if (obj_desc->field.region_obj->region.space_id ==
|
|
|
ACPI_ADR_SPACE_GSBUS) {
|
|
|
- length = ACPI_GSBUS_BUFFER_SIZE;
|
|
|
- function =
|
|
|
- ACPI_READ | (obj_desc->field.attribute << 16);
|
|
|
+ accessor_type = obj_desc->field.attribute;
|
|
|
+ length = acpi_ex_get_serial_access_length(accessor_type,
|
|
|
+ obj_desc->
|
|
|
+ field.
|
|
|
+ access_length);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Add additional 2 bytes for modeled generic_serial_bus data buffer:
|
|
|
+ * typedef struct {
|
|
|
+ * BYTEStatus; // Byte 0 of the data buffer
|
|
|
+ * BYTELength; // Byte 1 of the data buffer
|
|
|
+ * BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer,
|
|
|
+ * }
|
|
|
+ */
|
|
|
+ length += 2;
|
|
|
+ function = ACPI_READ | (accessor_type << 16);
|
|
|
} else { /* IPMI */
|
|
|
|
|
|
length = ACPI_IPMI_BUFFER_SIZE;
|
|
@@ -231,6 +307,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
|
|
|
void *buffer;
|
|
|
union acpi_operand_object *buffer_desc;
|
|
|
u32 function;
|
|
|
+ u16 accessor_type;
|
|
|
|
|
|
ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
|
|
|
|
|
@@ -284,9 +361,22 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
|
|
|
ACPI_WRITE | (obj_desc->field.attribute << 16);
|
|
|
} else if (obj_desc->field.region_obj->region.space_id ==
|
|
|
ACPI_ADR_SPACE_GSBUS) {
|
|
|
- length = ACPI_GSBUS_BUFFER_SIZE;
|
|
|
- function =
|
|
|
- ACPI_WRITE | (obj_desc->field.attribute << 16);
|
|
|
+ accessor_type = obj_desc->field.attribute;
|
|
|
+ length = acpi_ex_get_serial_access_length(accessor_type,
|
|
|
+ obj_desc->
|
|
|
+ field.
|
|
|
+ access_length);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Add additional 2 bytes for modeled generic_serial_bus data buffer:
|
|
|
+ * typedef struct {
|
|
|
+ * BYTEStatus; // Byte 0 of the data buffer
|
|
|
+ * BYTELength; // Byte 1 of the data buffer
|
|
|
+ * BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer,
|
|
|
+ * }
|
|
|
+ */
|
|
|
+ length += 2;
|
|
|
+ function = ACPI_WRITE | (accessor_type << 16);
|
|
|
} else { /* IPMI */
|
|
|
|
|
|
length = ACPI_IPMI_BUFFER_SIZE;
|