Commit 46bcd6ad authored by Len Brown's avatar Len Brown

[ACPI] ACPICA 20041203 from Bob Moore and Alexey Starikovskiy

The low-level field insertion/extraction code (exfldio)
has been completely rewritten to eliminate unnecessary
complexity, bugs, and boundary conditions.

Fixed a problem in the ToInteger, ToBuffer, ToHexString,
and ToDecimalString operators where the input operand could
be inadvertently deleted if no conversion was necessary
(e.g., if the input to ToInteger was an Integer object.)

Fixed a problem with the ToDecimalString and ToHexString
where an incorrect exception code was returned if the
resulting string would be > 200 chars.  AE_STRING_LIMIT is
now returned.

Fixed a problem with the Concatenate operator where AE_OK
was always returned, even if the operation failed.

Fixed a problem in oswinxf (used by AcpiExec and iASL)
to allow > 128 semaphores to be allocated.
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 8c15f7c9
......@@ -762,9 +762,8 @@ acpi_ds_eval_region_operands (
*
* RETURN: Status
*
* DESCRIPTION: Get the operands and complete the following data objec types:
* Buffer
* Package
* DESCRIPTION: Get the operands and complete the following data object types:
* Buffer, Package.
*
****************************************************************************/
......
......@@ -399,16 +399,24 @@ acpi_ds_exec_end_op (
goto cleanup;
}
/* Resolve all operands */
/*
* All opcodes require operand resolution, with the only exceptions
* being the object_type and size_of operators.
*/
if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) {
/* Resolve all operands */
status = acpi_ex_resolve_operands (walk_state->opcode,
&(walk_state->operands [walk_state->num_operands -1]),
walk_state);
if (ACPI_SUCCESS (status)) {
ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
acpi_ps_get_opcode_name (walk_state->opcode),
walk_state->num_operands, "after ex_resolve_operands");
}
}
status = acpi_ex_resolve_operands (walk_state->opcode,
&(walk_state->operands [walk_state->num_operands -1]),
walk_state);
if (ACPI_SUCCESS (status)) {
ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
acpi_ps_get_opcode_name (walk_state->opcode),
walk_state->num_operands, "after ex_resolve_operands");
/*
* Dispatch the request to the appropriate interpreter handler
* routine. There is one routine per opcode "type" based upon the
......
......@@ -605,8 +605,8 @@ acpi_ev_gpe_dispatch (
if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_EDGE_TRIGGERED) {
status = acpi_hw_clear_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to clear GPE[%2X]\n",
gpe_number));
ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n",
acpi_format_exception (status), gpe_number));
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
}
......@@ -643,8 +643,8 @@ acpi_ev_gpe_dispatch (
status = acpi_hw_clear_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR ((
"acpi_ev_gpe_dispatch: Unable to clear GPE[%2X]\n",
gpe_number));
"acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n",
acpi_format_exception (status), gpe_number));
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
}
......@@ -659,8 +659,8 @@ acpi_ev_gpe_dispatch (
status = acpi_ev_disable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR ((
"acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n",
gpe_number));
"acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n",
acpi_format_exception (status), gpe_number));
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
......@@ -668,12 +668,12 @@ acpi_ev_gpe_dispatch (
* Execute the method associated with the GPE
* NOTE: Level-triggered GPEs are cleared after the method completes.
*/
if (ACPI_FAILURE (acpi_os_queue_for_execution (OSD_PRIORITY_GPE,
acpi_ev_asynch_execute_gpe_method,
gpe_event_info))) {
status = acpi_os_queue_for_execution (OSD_PRIORITY_GPE,
acpi_ev_asynch_execute_gpe_method, gpe_event_info);
if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR ((
"acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%2X], event is disabled\n",
gpe_number));
"acpi_ev_gpe_dispatch: %s, Unable to queue handler for GPE[%2X] - event disabled\n",
acpi_format_exception (status), gpe_number));
}
break;
......@@ -692,8 +692,8 @@ acpi_ev_gpe_dispatch (
status = acpi_ev_disable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR ((
"acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n",
gpe_number));
"acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n",
acpi_format_exception (status), gpe_number));
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
break;
......
......@@ -714,9 +714,6 @@ acpi_ex_dump_object_descriptor (
acpi_ex_out_integer ("bit_length", obj_desc->common_field.bit_length);
acpi_ex_out_integer ("fld_bit_offset", obj_desc->common_field.start_field_bit_offset);
acpi_ex_out_integer ("base_byte_offset", obj_desc->common_field.base_byte_offset);
acpi_ex_out_integer ("datum_valid_bits", obj_desc->common_field.datum_valid_bits);
acpi_ex_out_integer ("end_fld_valid_bits",obj_desc->common_field.end_field_valid_bits);
acpi_ex_out_integer ("end_buf_valid_bits",obj_desc->common_field.end_buffer_valid_bits);
acpi_ex_out_pointer ("parent_node", obj_desc->common_field.node);
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
......
......@@ -610,210 +610,6 @@ acpi_ex_write_with_update_rule (
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_get_buffer_datum
*
* PARAMETERS: Datum - Where the Datum is returned
* Buffer - Raw field buffer
* buffer_length - Entire length (used for big-endian only)
* byte_granularity - 1/2/4/8 Granularity of the field
* (aka Datum Size)
* buffer_offset - Datum offset into the buffer
*
* RETURN: none
*
* DESCRIPTION: Get a datum from the buffer according to the buffer field
* byte granularity
*
******************************************************************************/
void
acpi_ex_get_buffer_datum (
acpi_integer *datum,
void *buffer,
u32 buffer_length,
u32 byte_granularity,
u32 buffer_offset)
{
u32 index;
ACPI_FUNCTION_TRACE_U32 ("ex_get_buffer_datum", byte_granularity);
/* Get proper index into buffer (handles big/little endian) */
index = ACPI_BUFFER_INDEX (buffer_length, buffer_offset, byte_granularity);
/* Move the requested number of bytes */
switch (byte_granularity) {
case ACPI_FIELD_BYTE_GRANULARITY:
*datum = ((u8 *) buffer) [index];
break;
case ACPI_FIELD_WORD_GRANULARITY:
ACPI_MOVE_16_TO_64 (datum, &(((u16 *) buffer) [index]));
break;
case ACPI_FIELD_DWORD_GRANULARITY:
ACPI_MOVE_32_TO_64 (datum, &(((u32 *) buffer) [index]));
break;
case ACPI_FIELD_QWORD_GRANULARITY:
ACPI_MOVE_64_TO_64 (datum, &(((u64 *) buffer) [index]));
break;
default:
/* Should not get here */
break;
}
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_set_buffer_datum
*
* PARAMETERS: merged_datum - Value to store
* Buffer - Receiving buffer
* buffer_length - Entire length (used for big-endian only)
* byte_granularity - 1/2/4/8 Granularity of the field
* (aka Datum Size)
* buffer_offset - Datum offset into the buffer
*
* RETURN: none
*
* DESCRIPTION: Store the merged datum to the buffer according to the
* byte granularity
*
******************************************************************************/
void
acpi_ex_set_buffer_datum (
acpi_integer merged_datum,
void *buffer,
u32 buffer_length,
u32 byte_granularity,
u32 buffer_offset)
{
u32 index;
ACPI_FUNCTION_TRACE_U32 ("ex_set_buffer_datum", byte_granularity);
/* Get proper index into buffer (handles big/little endian) */
index = ACPI_BUFFER_INDEX (buffer_length, buffer_offset, byte_granularity);
/* Move the requested number of bytes */
switch (byte_granularity) {
case ACPI_FIELD_BYTE_GRANULARITY:
((u8 *) buffer) [index] = (u8) merged_datum;
break;
case ACPI_FIELD_WORD_GRANULARITY:
ACPI_MOVE_64_TO_16 (&(((u16 *) buffer)[index]), &merged_datum);
break;
case ACPI_FIELD_DWORD_GRANULARITY:
ACPI_MOVE_64_TO_32 (&(((u32 *) buffer)[index]), &merged_datum);
break;
case ACPI_FIELD_QWORD_GRANULARITY:
ACPI_MOVE_64_TO_64 (&(((u64 *) buffer)[index]), &merged_datum);
break;
default:
/* Should not get here */
break;
}
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_common_buffer_setup
*
* PARAMETERS: obj_desc - Field object
* buffer_length - Length of caller's buffer
* datum_count - Where the datum_count is returned
*
* RETURN: Status, datum_count
*
* DESCRIPTION: Common code to validate the incoming buffer size and compute
* the number of field "datums" that must be read or written.
* A "datum" is the smallest unit that can be read or written
* to the field, it is either 1,2,4, or 8 bytes.
*
******************************************************************************/
acpi_status
acpi_ex_common_buffer_setup (
union acpi_operand_object *obj_desc,
u32 buffer_length,
u32 *datum_count)
{
u32 byte_field_length;
u32 actual_byte_field_length;
ACPI_FUNCTION_TRACE ("ex_common_buffer_setup");
/*
* Incoming buffer must be at least as long as the field, we do not
* allow "partial" field reads/writes. We do not care if the buffer is
* larger than the field, this typically happens when an integer is
* read/written to a field that is actually smaller than an integer.
*/
byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (
obj_desc->common_field.bit_length);
if (byte_field_length > buffer_length) {
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
"Field size %X (bytes) is too large for buffer (%X)\n",
byte_field_length, buffer_length));
return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
}
/*
* Create "actual" field byte count (minimum number of bytes that
* must be read), then convert to datum count (minimum number
* of datum-sized units that must be read)
*/
actual_byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (
obj_desc->common_field.start_field_bit_offset +
obj_desc->common_field.bit_length);
*datum_count = ACPI_ROUND_UP_TO (actual_byte_field_length,
obj_desc->common_field.access_byte_width);
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
"buffer_bytes %X, actual_bytes %X, Datums %X, byte_gran %X\n",
byte_field_length, actual_byte_field_length,
*datum_count, obj_desc->common_field.access_byte_width));
return_ACPI_STATUS (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_extract_from_field
......@@ -835,128 +631,92 @@ acpi_ex_extract_from_field (
u32 buffer_length)
{
acpi_status status;
u32 field_datum_byte_offset;
u32 buffer_datum_offset;
acpi_integer previous_raw_datum = 0;
acpi_integer this_raw_datum = 0;
acpi_integer merged_datum = 0;
acpi_integer raw_datum;
acpi_integer merged_datum;
u32 field_offset = 0;
u32 buffer_offset = 0;
u32 buffer_tail_bits;
u32 datum_count;
u32 field_datum_count;
u32 i;
ACPI_FUNCTION_TRACE ("ex_extract_from_field");
/* Validate buffer, compute number of datums */
/* Validate target buffer and clear it */
status = acpi_ex_common_buffer_setup (obj_desc, buffer_length, &datum_count);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES (
obj_desc->common_field.bit_length)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"Field size %X (bits) is too large for buffer (%X)\n",
obj_desc->common_field.bit_length, buffer_length));
/*
* Clear the caller's buffer (the whole buffer length as given)
* This is very important, especially in the cases where the buffer
* is longer than the size of the field.
*/
return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
}
ACPI_MEMSET (buffer, 0, buffer_length);
field_datum_byte_offset = 0;
buffer_datum_offset= 0;
/* Read the entire field */
for (i = 0; i < datum_count; i++) {
status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
&this_raw_datum, ACPI_READ);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/* We might actually be done if the request fits in one datum */
if ((datum_count == 1) &&
(obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM)) {
/* 1) Shift the valid data bits down to start at bit 0 */
/* Compute the number of datums (access width data items) */
merged_datum = (this_raw_datum >> obj_desc->common_field.start_field_bit_offset);
datum_count = ACPI_ROUND_UP_TO (
obj_desc->common_field.bit_length,
obj_desc->common_field.access_bit_width);
field_datum_count = ACPI_ROUND_UP_TO (
obj_desc->common_field.bit_length +
obj_desc->common_field.start_field_bit_offset,
obj_desc->common_field.access_bit_width);
/* 2) Mask off any upper unused bits (bits not part of the field) */
/* Priming read from the field */
if (obj_desc->common_field.end_buffer_valid_bits) {
merged_datum &= ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_buffer_valid_bits);
}
status = acpi_ex_field_datum_io (obj_desc, field_offset, &raw_datum, ACPI_READ);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
merged_datum = raw_datum >> obj_desc->common_field.start_field_bit_offset;
/* Store the datum to the caller buffer */
/* Read the rest of the field */
acpi_ex_set_buffer_datum (merged_datum, buffer, buffer_length,
obj_desc->common_field.access_byte_width, buffer_datum_offset);
for (i = 1; i < field_datum_count; i++) {
/* Get next input datum from the field */
return_ACPI_STATUS (AE_OK);
field_offset += obj_desc->common_field.access_byte_width;
status = acpi_ex_field_datum_io (obj_desc, field_offset,
&raw_datum, ACPI_READ);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/* Special handling for the last datum to ignore extra bits */
if ((i >= (datum_count -1)) &&
(obj_desc->common_field.end_field_valid_bits)) {
/*
* This is the last iteration of the loop. We need to clear
* any unused bits (bits that are not part of this field) before
* we store the final merged datum into the caller buffer.
*/
this_raw_datum &=
ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits);
}
/* Merge with previous datum if necessary */
/*
* Create the (possibly) merged datum to be stored to the caller buffer
*/
if (obj_desc->common_field.start_field_bit_offset == 0) {
/* Field is not skewed and we can just copy the datum */
merged_datum |= raw_datum <<
(obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset);
acpi_ex_set_buffer_datum (this_raw_datum, buffer, buffer_length,
obj_desc->common_field.access_byte_width, buffer_datum_offset);
buffer_datum_offset++;
if (i == datum_count) {
break;
}
else {
/* Not aligned -- on the first iteration, just save the datum */
if (i != 0) {
/*
* Put together the appropriate bits of the two raw data to make a
* single complete field datum
*
* 1) Normalize the first datum down to bit 0
*/
merged_datum = (previous_raw_datum >> obj_desc->common_field.start_field_bit_offset);
/* Write merged datum to target buffer */
/* 2) Insert the second datum "above" the first datum */
ACPI_MEMCPY (((char *) buffer) + buffer_offset, &merged_datum,
ACPI_MIN(obj_desc->common_field.access_byte_width,
buffer_length - buffer_offset));
merged_datum |= (this_raw_datum << obj_desc->common_field.datum_valid_bits);
acpi_ex_set_buffer_datum (merged_datum, buffer, buffer_length,
obj_desc->common_field.access_byte_width, buffer_datum_offset);
buffer_datum_offset++;
}
buffer_offset += obj_desc->common_field.access_byte_width;
merged_datum = raw_datum >> obj_desc->common_field.start_field_bit_offset;
}
/*
* Save the raw datum that was just acquired since it may contain bits
* of the *next* field datum
*/
previous_raw_datum = this_raw_datum;
}
/* Mask off any extra bits in the last datum */
field_datum_byte_offset += obj_desc->common_field.access_byte_width;
buffer_tail_bits = obj_desc->common_field.bit_length % obj_desc->common_field.access_bit_width;
if (buffer_tail_bits) {
merged_datum &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits);
}
/* For non-aligned case, there is one last datum to insert */
/* Write the last datum to the buffer */
if (obj_desc->common_field.start_field_bit_offset != 0) {
merged_datum = (this_raw_datum >> obj_desc->common_field.start_field_bit_offset);
acpi_ex_set_buffer_datum (merged_datum, buffer, buffer_length,
obj_desc->common_field.access_byte_width, buffer_datum_offset);
}
ACPI_MEMCPY (((char *) buffer) + buffer_offset, &merged_datum,
ACPI_MIN(obj_desc->common_field.access_byte_width,
buffer_length - buffer_offset));
return_ACPI_STATUS (AE_OK);
}
......@@ -983,169 +743,91 @@ acpi_ex_insert_into_field (
u32 buffer_length)
{
acpi_status status;
u32 field_datum_byte_offset;
u32 datum_offset;
acpi_integer mask;
acpi_integer merged_datum;
acpi_integer previous_raw_datum;
acpi_integer this_raw_datum;
acpi_integer raw_datum = 0;
u32 field_offset = 0;
u32 buffer_offset = 0;
u32 buffer_tail_bits;
u32 datum_count;
u32 field_datum_count;
u32 i;
ACPI_FUNCTION_TRACE ("ex_insert_into_field");
/* Validate buffer, compute number of datums */
status = acpi_ex_common_buffer_setup (obj_desc, buffer_length, &datum_count);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/*
* Break the request into up to three parts (similar to an I/O request):
* 1) non-aligned part at start
* 2) aligned part in middle
* 3) non-aligned part at the end
*/
field_datum_byte_offset = 0;
datum_offset= 0;
/* Get a single datum from the caller's buffer */
acpi_ex_get_buffer_datum (&previous_raw_datum, buffer, buffer_length,
obj_desc->common_field.access_byte_width, datum_offset);
/*
* Part1:
* Write a partial field datum if field does not begin on a datum boundary
* Note: The code in this section also handles the aligned case
*
* Construct Mask with 1 bits where the field is, 0 bits elsewhere
* (Only the bottom 5 bits of bit_length are valid for a shift operation)
*
* Mask off bits that are "below" the field (if any)
*/
mask = ACPI_MASK_BITS_BELOW (obj_desc->common_field.start_field_bit_offset);
/* If the field fits in one datum, may need to mask upper bits */
/* Validate input buffer */
if ((obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM) &&
obj_desc->common_field.end_field_valid_bits) {
/* There are bits above the field, mask them off also */
if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES (
obj_desc->common_field.bit_length)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"Field size %X (bits) is too large for buffer (%X)\n",
obj_desc->common_field.bit_length, buffer_length));
mask &= ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits);
return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
}
/* Shift and mask the value into the field position */
merged_datum = (previous_raw_datum << obj_desc->common_field.start_field_bit_offset);
merged_datum &= mask;
/* Apply the update rule (if necessary) and write the datum to the field */
/* Compute the number of datums (access width data items) */
status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum,
field_datum_byte_offset);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
mask = ACPI_MASK_BITS_BELOW (obj_desc->common_field.start_field_bit_offset);
datum_count = ACPI_ROUND_UP_TO (obj_desc->common_field.bit_length,
obj_desc->common_field.access_bit_width);
field_datum_count = ACPI_ROUND_UP_TO (obj_desc->common_field.bit_length +
obj_desc->common_field.start_field_bit_offset,
obj_desc->common_field.access_bit_width);
/* We just wrote the first datum */
/* Get initial Datum from the input buffer */
datum_offset++;
ACPI_MEMCPY (&raw_datum, buffer,
ACPI_MIN(obj_desc->common_field.access_byte_width,
buffer_length - buffer_offset));
/* If the entire field fits within one datum, we are done. */
merged_datum = raw_datum << obj_desc->common_field.start_field_bit_offset;
if ((datum_count == 1) &&
(obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM)) {
return_ACPI_STATUS (AE_OK);
}
/* Write the entire field */
/*
* Part2:
* Write the aligned data.
*
* We don't need to worry about the update rule for these data, because
* all of the bits in each datum are part of the field.
*
* The last datum must be special cased because it might contain bits
* that are not part of the field -- therefore the "update rule" must be
* applied in Part3 below.
*/
while (datum_offset < datum_count) {
field_datum_byte_offset += obj_desc->common_field.access_byte_width;
for (i = 1; i < field_datum_count; i++) {
/* Write merged datum to the target field */
/*
* Get the next raw buffer datum. It may contain bits of the previous
* field datum
*/
acpi_ex_get_buffer_datum (&this_raw_datum, buffer, buffer_length,
obj_desc->common_field.access_byte_width, datum_offset);
merged_datum &= mask;
status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, field_offset);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/* Create the field datum based on the field alignment */
/* Start new output datum by merging with previous input datum */
if (obj_desc->common_field.start_field_bit_offset != 0) {
/*
* Put together appropriate bits of the two raw buffer data to make
* a single complete field datum
*/
merged_datum =
(previous_raw_datum >> obj_desc->common_field.datum_valid_bits) |
(this_raw_datum << obj_desc->common_field.start_field_bit_offset);
}
else {
/* Field began aligned on datum boundary */
field_offset += obj_desc->common_field.access_byte_width;
merged_datum = raw_datum >>
(obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset);
mask = ACPI_INTEGER_MAX;
merged_datum = this_raw_datum;
if (i == datum_count) {
break;
}
/*
* Special handling for the last datum if the field does NOT end on
* a datum boundary. Update Rule must be applied to the bits outside
* the field.
*/
datum_offset++;
if ((datum_offset == datum_count) &&
(obj_desc->common_field.end_field_valid_bits)) {
/*
* If there are dangling non-aligned bits, perform one more merged write
* Else - field is aligned at the end, no need for any more writes
*/
/* Get the next input datum from the buffer */
/*
* Part3:
* This is the last datum and the field does not end on a datum boundary.
* Build the partial datum and write with the update rule.
*
* Mask off the unused bits above (after) the end-of-field
*/
mask = ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits);
merged_datum &= mask;
buffer_offset += obj_desc->common_field.access_byte_width;
ACPI_MEMCPY (&raw_datum, ((char *) buffer) + buffer_offset,
ACPI_MIN(obj_desc->common_field.access_byte_width,
buffer_length - buffer_offset));
merged_datum |= raw_datum << obj_desc->common_field.start_field_bit_offset;
}
/* Write the last datum with the update rule */
/* Mask off any extra bits in the last datum */
status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum,
field_datum_byte_offset);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
}
else {
/* Normal (aligned) case -- write the completed datum */
buffer_tail_bits = (obj_desc->common_field.bit_length +
obj_desc->common_field.start_field_bit_offset) % obj_desc->common_field.access_bit_width;
if (buffer_tail_bits) {
mask &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits);
}
status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
&merged_datum, ACPI_WRITE);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
}
/* Write the last datum to the field */
/*
* Save the most recent datum since it may contain bits of the *next*
* field datum. Update current byte offset.
*/
previous_raw_datum = this_raw_datum;
}
merged_datum &= mask;
status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, field_offset);
return_ACPI_STATUS (status);
}
......
......@@ -389,7 +389,7 @@ acpi_ex_do_concatenate (
if (local_operand1 != operand1) {
acpi_ut_remove_reference (local_operand1);
}
return_ACPI_STATUS (AE_OK);
return_ACPI_STATUS (status);
}
......
......@@ -507,6 +507,10 @@ acpi_ex_opcode_1A_1T_1R (
status = acpi_ex_convert_to_string (operand[0], &return_desc,
ACPI_EXPLICIT_CONVERT_DECIMAL);
if (return_desc == operand[0]) {
/* No conversion performed, add ref to handle return value */
acpi_ut_add_reference (return_desc);
}
break;
......@@ -514,12 +518,20 @@ acpi_ex_opcode_1A_1T_1R (
status = acpi_ex_convert_to_string (operand[0], &return_desc,
ACPI_EXPLICIT_CONVERT_HEX);
if (return_desc == operand[0]) {
/* No conversion performed, add ref to handle return value */
acpi_ut_add_reference (return_desc);
}
break;
case AML_TO_BUFFER_OP: /* to_buffer (Data, Result) */
status = acpi_ex_convert_to_buffer (operand[0], &return_desc);
if (return_desc == operand[0]) {
/* No conversion performed, add ref to handle return value */
acpi_ut_add_reference (return_desc);
}
break;
......@@ -527,6 +539,10 @@ acpi_ex_opcode_1A_1T_1R (
status = acpi_ex_convert_to_integer (operand[0], &return_desc,
ACPI_ANY_BASE);
if (return_desc == operand[0]) {
/* No conversion performed, add ref to handle return value */
acpi_ut_add_reference (return_desc);
}
break;
......@@ -551,10 +567,12 @@ acpi_ex_opcode_1A_1T_1R (
goto cleanup;
}
/*
* Store the return value computed above into the target object
*/
status = acpi_ex_store (return_desc, operand[1], walk_state);
if (ACPI_SUCCESS (status)) {
/*
* Store the return value computed above into the target object
*/
status = acpi_ex_store (return_desc, operand[1], walk_state);
}
cleanup:
......
......@@ -339,6 +339,8 @@ acpi_ex_prep_common_field_object (
obj_desc->common_field.access_byte_width = (u8)
ACPI_DIV_8 (access_bit_width); /* 1, 2, 4, 8 */
obj_desc->common_field.access_bit_width = (u8) access_bit_width;
/*
* base_byte_offset is the address of the start of the field within the
* region. It is the byte address of the first *datum* (field-width data
......@@ -361,28 +363,6 @@ acpi_ex_prep_common_field_object (
obj_desc->common_field.start_field_bit_offset = (u8)
(field_bit_position - ACPI_MUL_8 (obj_desc->common_field.base_byte_offset));
/*
* Valid bits -- the number of bits that compose a partial datum,
* 1) At the end of the field within the region (arbitrary starting bit
* offset)
* 2) At the end of a buffer used to contain the field (starting offset
* always zero)
*/
obj_desc->common_field.end_field_valid_bits = (u8)
((obj_desc->common_field.start_field_bit_offset + field_bit_length) %
access_bit_width);
/* start_buffer_bit_offset always = 0 */
obj_desc->common_field.end_buffer_valid_bits = (u8)
(field_bit_length % access_bit_width);
/*
* datum_valid_bits is the number of valid field bits in the first
* field datum.
*/
obj_desc->common_field.datum_valid_bits = (u8)
(access_bit_width - obj_desc->common_field.start_field_bit_offset);
/*
* Does the entire field fit within a single field access element? (datum)
* (i.e., without crossing a datum boundary)
......
......@@ -318,7 +318,7 @@
#define ARGI_SHIFT_LEFT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_SHIFT_RIGHT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_SIGNAL_OP ARGI_LIST1 (ARGI_EVENT)
#define ARGI_SIZE_OF_OP ARGI_LIST1 (ARGI_REFERENCE) /* Force delay of operand resolution */
#define ARGI_SIZE_OF_OP ARGI_LIST1 (ARGI_DATAOBJECT)
#define ARGI_SLEEP_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_STALL_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_STATICSTRING_OP ARGI_INVALID_OPCODE
......@@ -333,7 +333,7 @@
#define ARGI_TO_HEX_STR_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
#define ARGI_TO_INTEGER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
#define ARGI_TO_STRING_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_FIXED_TARGET)
#define ARGI_TYPE_OP ARGI_LIST1 (ARGI_REFERENCE) /* Force delay of operand resolution */
#define ARGI_TYPE_OP ARGI_LIST1 (ARGI_ANYTYPE)
#define ARGI_UNLOAD_OP ARGI_LIST1 (ARGI_DDBHANDLE)
#define ARGI_VAR_PACKAGE_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_WAIT_OP ARGI_LIST2 (ARGI_EVENT, ARGI_INTEGER)
......@@ -521,14 +521,14 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] =
/* 2D */ ACPI_OP ("FindSetRightBit", ARGP_FIND_SET_RIGHT_BIT_OP,ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
/* 2E */ ACPI_OP ("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
/* 2F */ ACPI_OP ("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R),
/* 30 */ ACPI_OP ("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
/* 30 */ ACPI_OP ("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
/* 31 */ ACPI_OP ("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
/* 32 */ ACPI_OP ("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT),
/* 33 */ ACPI_OP ("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP,ARGI_CREATE_DWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
/* 34 */ ACPI_OP ("CreateWordField", ARGP_CREATE_WORD_FIELD_OP, ARGI_CREATE_WORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
/* 35 */ ACPI_OP ("CreateByteField", ARGP_CREATE_BYTE_FIELD_OP, ARGI_CREATE_BYTE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
/* 36 */ ACPI_OP ("CreateBitField", ARGP_CREATE_BIT_FIELD_OP, ARGI_CREATE_BIT_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
/* 37 */ ACPI_OP ("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
/* 37 */ ACPI_OP ("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
/* 38 */ ACPI_OP ("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
/* 39 */ ACPI_OP ("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
/* 3A */ ACPI_OP ("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
......
......@@ -64,7 +64,7 @@
/* Version string */
#define ACPI_CA_VERSION 0x20041119
#define ACPI_CA_VERSION 0x20041203
/*
* OS name, used for the _OS object. The _OS object is essentially obsolete,
......
......@@ -55,6 +55,7 @@
#define ACPI_SET_BIT(target,bit) ((target) |= (bit))
#define ACPI_CLEAR_BIT(target,bit) ((target) &= ~(bit))
#define ACPI_MIN(a,b) (((a)<(b))?(a):(b))
#if ACPI_MACHINE_WIDTH == 16
......
......@@ -94,9 +94,7 @@
u32 bit_length; /* Length of field in bits */\
u32 base_byte_offset; /* Byte offset within containing object */\
u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\
u8 datum_valid_bits; /* Valid bit in first "Field datum" */\
u8 end_field_valid_bits; /* Valid bits in the last "field datum" */\
u8 end_buffer_valid_bits; /* Valid bits in the last "buffer datum" */\
u8 access_bit_width; /* Read/Write size in bits (8-64) */\
u32 value; /* Value to store into the Bank or Index register */\
struct acpi_namespace_node *node; /* Link back to parent node */
......
......@@ -320,6 +320,7 @@
#define AML_HAS_TARGET 0x0800
#define AML_HAS_ARGS 0x1000
#define AML_CONSTANT 0x2000
#define AML_NO_OPERAND_RESOLVE 0x4000
/* Convenient flag groupings */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment