diff options
Diffstat (limited to 'drivers/acpi/acpica/psargs.c')
-rw-r--r-- | drivers/acpi/acpica/psargs.c | 143 |
1 files changed, 129 insertions, 14 deletions
diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c index e1fad0ee013..5ac36aba507 100644 --- a/drivers/acpi/acpica/psargs.c +++ b/drivers/acpi/acpica/psargs.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2011, Intel Corp. | 8 | * Copyright (C) 2000 - 2012, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -484,34 +484,54 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, | |||
484 | static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state | 484 | static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state |
485 | *parser_state) | 485 | *parser_state) |
486 | { | 486 | { |
487 | u32 aml_offset = (u32) | 487 | u32 aml_offset; |
488 | ACPI_PTR_DIFF(parser_state->aml, | ||
489 | parser_state->aml_start); | ||
490 | union acpi_parse_object *field; | 488 | union acpi_parse_object *field; |
489 | union acpi_parse_object *arg = NULL; | ||
491 | u16 opcode; | 490 | u16 opcode; |
492 | u32 name; | 491 | u32 name; |
492 | u8 access_type; | ||
493 | u8 access_attribute; | ||
494 | u8 access_length; | ||
495 | u32 pkg_length; | ||
496 | u8 *pkg_end; | ||
497 | u32 buffer_length; | ||
493 | 498 | ||
494 | ACPI_FUNCTION_TRACE(ps_get_next_field); | 499 | ACPI_FUNCTION_TRACE(ps_get_next_field); |
495 | 500 | ||
501 | aml_offset = | ||
502 | (u32)ACPI_PTR_DIFF(parser_state->aml, parser_state->aml_start); | ||
503 | |||
496 | /* Determine field type */ | 504 | /* Determine field type */ |
497 | 505 | ||
498 | switch (ACPI_GET8(parser_state->aml)) { | 506 | switch (ACPI_GET8(parser_state->aml)) { |
499 | default: | 507 | case AML_FIELD_OFFSET_OP: |
500 | 508 | ||
501 | opcode = AML_INT_NAMEDFIELD_OP; | 509 | opcode = AML_INT_RESERVEDFIELD_OP; |
510 | parser_state->aml++; | ||
502 | break; | 511 | break; |
503 | 512 | ||
504 | case 0x00: | 513 | case AML_FIELD_ACCESS_OP: |
505 | 514 | ||
506 | opcode = AML_INT_RESERVEDFIELD_OP; | 515 | opcode = AML_INT_ACCESSFIELD_OP; |
507 | parser_state->aml++; | 516 | parser_state->aml++; |
508 | break; | 517 | break; |
509 | 518 | ||
510 | case 0x01: | 519 | case AML_FIELD_CONNECTION_OP: |
511 | 520 | ||
512 | opcode = AML_INT_ACCESSFIELD_OP; | 521 | opcode = AML_INT_CONNECTION_OP; |
522 | parser_state->aml++; | ||
523 | break; | ||
524 | |||
525 | case AML_FIELD_EXT_ACCESS_OP: | ||
526 | |||
527 | opcode = AML_INT_EXTACCESSFIELD_OP; | ||
513 | parser_state->aml++; | 528 | parser_state->aml++; |
514 | break; | 529 | break; |
530 | |||
531 | default: | ||
532 | |||
533 | opcode = AML_INT_NAMEDFIELD_OP; | ||
534 | break; | ||
515 | } | 535 | } |
516 | 536 | ||
517 | /* Allocate a new field op */ | 537 | /* Allocate a new field op */ |
@@ -549,16 +569,111 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state | |||
549 | break; | 569 | break; |
550 | 570 | ||
551 | case AML_INT_ACCESSFIELD_OP: | 571 | case AML_INT_ACCESSFIELD_OP: |
572 | case AML_INT_EXTACCESSFIELD_OP: | ||
552 | 573 | ||
553 | /* | 574 | /* |
554 | * Get access_type and access_attrib and merge into the field Op | 575 | * Get access_type and access_attrib and merge into the field Op |
555 | * access_type is first operand, access_attribute is second | 576 | * access_type is first operand, access_attribute is second. stuff |
577 | * these bytes into the node integer value for convenience. | ||
556 | */ | 578 | */ |
557 | field->common.value.integer = | 579 | |
558 | (((u32) ACPI_GET8(parser_state->aml) << 8)); | 580 | /* Get the two bytes (Type/Attribute) */ |
581 | |||
582 | access_type = ACPI_GET8(parser_state->aml); | ||
559 | parser_state->aml++; | 583 | parser_state->aml++; |
560 | field->common.value.integer |= ACPI_GET8(parser_state->aml); | 584 | access_attribute = ACPI_GET8(parser_state->aml); |
561 | parser_state->aml++; | 585 | parser_state->aml++; |
586 | |||
587 | field->common.value.integer = (u8)access_type; | ||
588 | field->common.value.integer |= (u16)(access_attribute << 8); | ||
589 | |||
590 | /* This opcode has a third byte, access_length */ | ||
591 | |||
592 | if (opcode == AML_INT_EXTACCESSFIELD_OP) { | ||
593 | access_length = ACPI_GET8(parser_state->aml); | ||
594 | parser_state->aml++; | ||
595 | |||
596 | field->common.value.integer |= | ||
597 | (u32)(access_length << 16); | ||
598 | } | ||
599 | break; | ||
600 | |||
601 | case AML_INT_CONNECTION_OP: | ||
602 | |||
603 | /* | ||
604 | * Argument for Connection operator can be either a Buffer | ||
605 | * (resource descriptor), or a name_string. | ||
606 | */ | ||
607 | if (ACPI_GET8(parser_state->aml) == AML_BUFFER_OP) { | ||
608 | parser_state->aml++; | ||
609 | |||
610 | pkg_end = parser_state->aml; | ||
611 | pkg_length = | ||
612 | acpi_ps_get_next_package_length(parser_state); | ||
613 | pkg_end += pkg_length; | ||
614 | |||
615 | if (parser_state->aml < pkg_end) { | ||
616 | |||
617 | /* Non-empty list */ | ||
618 | |||
619 | arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP); | ||
620 | if (!arg) { | ||
621 | return_PTR(NULL); | ||
622 | } | ||
623 | |||
624 | /* Get the actual buffer length argument */ | ||
625 | |||
626 | opcode = ACPI_GET8(parser_state->aml); | ||
627 | parser_state->aml++; | ||
628 | |||
629 | switch (opcode) { | ||
630 | case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ | ||
631 | buffer_length = | ||
632 | ACPI_GET8(parser_state->aml); | ||
633 | parser_state->aml += 1; | ||
634 | break; | ||
635 | |||
636 | case AML_WORD_OP: /* AML_WORDDATA_ARG */ | ||
637 | buffer_length = | ||
638 | ACPI_GET16(parser_state->aml); | ||
639 | parser_state->aml += 2; | ||
640 | break; | ||
641 | |||
642 | case AML_DWORD_OP: /* AML_DWORDATA_ARG */ | ||
643 | buffer_length = | ||
644 | ACPI_GET32(parser_state->aml); | ||
645 | parser_state->aml += 4; | ||
646 | break; | ||
647 | |||
648 | default: | ||
649 | buffer_length = 0; | ||
650 | break; | ||
651 | } | ||
652 | |||
653 | /* Fill in bytelist data */ | ||
654 | |||
655 | arg->named.value.size = buffer_length; | ||
656 | arg->named.data = parser_state->aml; | ||
657 | } | ||
658 | |||
659 | /* Skip to End of byte data */ | ||
660 | |||
661 | parser_state->aml = pkg_end; | ||
662 | } else { | ||
663 | arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); | ||
664 | if (!arg) { | ||
665 | return_PTR(NULL); | ||
666 | } | ||
667 | |||
668 | /* Get the Namestring argument */ | ||
669 | |||
670 | arg->common.value.name = | ||
671 | acpi_ps_get_next_namestring(parser_state); | ||
672 | } | ||
673 | |||
674 | /* Link the buffer/namestring to parent (CONNECTION_OP) */ | ||
675 | |||
676 | acpi_ps_append_arg(field, arg); | ||
562 | break; | 677 | break; |
563 | 678 | ||
564 | default: | 679 | default: |