aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/psargs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpica/psargs.c')
-rw-r--r--drivers/acpi/acpica/psargs.c143
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,
484static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state 484static 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: