示例#1
0
void
AcpiDmNamestring (
    char                    *Name)
{
    UINT32                  SegCount;


    if (!Name)
    {
        return;
    }

    /* Handle all Scope Prefix operators */

    while (ACPI_IS_ROOT_PREFIX (ACPI_GET8 (Name)) ||
           ACPI_IS_PARENT_PREFIX (ACPI_GET8 (Name)))
    {
        /* Append prefix character */

        AcpiOsPrintf ("%1c", ACPI_GET8 (Name));
        Name++;
    }

    switch (ACPI_GET8 (Name))
    {
    case 0:
        SegCount = 0;
        break;

    case AML_DUAL_NAME_PREFIX:
        SegCount = 2;
        Name++;
        break;

    case AML_MULTI_NAME_PREFIX_OP:
        SegCount = (UINT32) ACPI_GET8 (Name + 1);
        Name += 2;
        break;

    default:
        SegCount = 1;
        break;
    }

    while (SegCount)
    {
        /* Append Name segment */

        AcpiDmDumpName (*ACPI_CAST_PTR (UINT32, Name));

        SegCount--;
        if (SegCount)
        {
            /* Not last name, append dot separator */

            AcpiOsPrintf (".");
        }
        Name += ACPI_NAME_SIZE;
    }
}
示例#2
0
char *
acpi_ps_get_next_namestring (
	struct acpi_parse_state         *parser_state)
{
	u8                              *start = parser_state->aml;
	u8                              *end = parser_state->aml;


	ACPI_FUNCTION_TRACE ("ps_get_next_namestring");


	/* Handle multiple prefix characters */

	while (acpi_ps_is_prefix_char (ACPI_GET8 (end))) {
		/* Include prefix '\\' or '^' */

		end++;
	}

	/* Decode the path */

	switch (ACPI_GET8 (end)) {
	case 0:

		/* null_name */

		if (end == start) {
			start = NULL;
		}
		end++;
		break;

	case AML_DUAL_NAME_PREFIX:

		/* Two name segments */

		end += 1 + (2 * ACPI_NAME_SIZE);
		break;

	case AML_MULTI_NAME_PREFIX_OP:

		/* Multiple name segments, 4 chars each */

		end += 2 + ((acpi_size) ACPI_GET8 (end + 1) * ACPI_NAME_SIZE);
		break;

	default:

		/* Single name segment */

		end += ACPI_NAME_SIZE;
		break;
	}

	parser_state->aml = (u8*) end;
	return_PTR ((char *) start);
}
示例#3
0
u32
acpi_ps_get_next_package_length (
	struct acpi_parse_state         *parser_state)
{
	u32                             encoded_length;
	u32                             length = 0;


	ACPI_FUNCTION_TRACE ("ps_get_next_package_length");


	encoded_length = (u32) ACPI_GET8 (parser_state->aml);
	parser_state->aml++;


	switch (encoded_length >> 6) /* bits 6-7 contain encoding scheme */ {
	case 0: /* 1-byte encoding (bits 0-5) */

		length = (encoded_length & 0x3F);
		break;


	case 1: /* 2-byte encoding (next byte + bits 0-3) */

		length = ((ACPI_GET8 (parser_state->aml) << 04) |
				 (encoded_length & 0x0F));
		parser_state->aml++;
		break;


	case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */

		length = ((ACPI_GET8 (parser_state->aml + 1) << 12) |
				  (ACPI_GET8 (parser_state->aml)    << 04) |
				  (encoded_length & 0x0F));
		parser_state->aml += 2;
		break;


	case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */

		length = ((ACPI_GET8 (parser_state->aml + 2) << 20) |
				  (ACPI_GET8 (parser_state->aml + 1) << 12) |
				  (ACPI_GET8 (parser_state->aml)    << 04) |
				  (encoded_length & 0x0F));
		parser_state->aml += 3;
		break;

	default:

		/* Can't get here, only 2 bits / 4 cases */
		break;
	}

	return_VALUE (length);
}
示例#4
0
文件: psparse.c 项目: ModeenF/haiku
UINT16
AcpiPsPeekOpcode (
    ACPI_PARSE_STATE        *ParserState)
{
    UINT8                   *Aml;
    UINT16                  Opcode;


    Aml = ParserState->Aml;
    Opcode = (UINT16) ACPI_GET8 (Aml);

    if (Opcode == AML_EXTENDED_OP_PREFIX)
    {
        /* Extended opcode, get the second opcode byte */

        Aml++;
        Opcode = (UINT16) ((Opcode << 8) | ACPI_GET8 (Aml));
    }

    return (Opcode);
}
示例#5
0
static void
AcpiRsDumpDescriptor (
    void                    *Resource,
    ACPI_RSDUMP_INFO        *Table)
{
    UINT8                   *Target = NULL;
    UINT8                   *PreviousTarget;
    const char              *Name;
    UINT8                   Count;


    /* First table entry must contain the table length (# of table entries) */

    Count = Table->Offset;

    while (Count)
    {
        PreviousTarget = Target;
        Target = ACPI_ADD_PTR (UINT8, Resource, Table->Offset);
        Name = Table->Name;

        switch (Table->Opcode)
        {
        case ACPI_RSD_TITLE:
            /*
             * Optional resource title
             */
            if (Table->Name)
            {
                AcpiOsPrintf ("%s Resource\n", Name);
            }
            break;

        /* Strings */

        case ACPI_RSD_LITERAL:

            AcpiRsOutString (Name, ACPI_CAST_PTR (char, Table->Pointer));
            break;

        case ACPI_RSD_STRING:

            AcpiRsOutString (Name, ACPI_CAST_PTR (char, Target));
            break;

        /* Data items, 8/16/32/64 bit */

        case ACPI_RSD_UINT8:

            if (Table->Pointer)
            {
                AcpiRsOutString (Name, Table->Pointer [*Target]);
            }
            else
            {
                AcpiRsOutInteger8 (Name, ACPI_GET8 (Target));
            }
            break;

        case ACPI_RSD_UINT16:

            AcpiRsOutInteger16 (Name, ACPI_GET16 (Target));
            break;

        case ACPI_RSD_UINT32:

            AcpiRsOutInteger32 (Name, ACPI_GET32 (Target));
            break;

        case ACPI_RSD_UINT64:

            AcpiRsOutInteger64 (Name, ACPI_GET64 (Target));
            break;

        /* Flags: 1-bit and 2-bit flags supported */

        case ACPI_RSD_1BITFLAG:

            AcpiRsOutString (Name, Table->Pointer [*Target & 0x01]);
            break;

        case ACPI_RSD_2BITFLAG:

            AcpiRsOutString (Name, Table->Pointer [*Target & 0x03]);
            break;

        case ACPI_RSD_3BITFLAG:

            AcpiRsOutString (Name, Table->Pointer [*Target & 0x07]);
            break;

        case ACPI_RSD_SHORTLIST:
            /*
             * Short byte list (single line output) for DMA and IRQ resources
             * Note: The list length is obtained from the previous table entry
             */
            if (PreviousTarget)
            {
                AcpiRsOutTitle (Name);
                AcpiRsDumpShortByteList (*PreviousTarget, Target);
            }
            break;

        case ACPI_RSD_SHORTLISTX:
            /*
             * Short byte list (single line output) for GPIO vendor data
             * Note: The list length is obtained from the previous table entry
             */
            if (PreviousTarget)
            {
                AcpiRsOutTitle (Name);
                AcpiRsDumpShortByteList (*PreviousTarget,
                    *(ACPI_CAST_INDIRECT_PTR (UINT8, Target)));
            }
            break;

        case ACPI_RSD_LONGLIST:
            /*
             * Long byte list for Vendor resource data
             * Note: The list length is obtained from the previous table entry
             */
            if (PreviousTarget)
            {
                AcpiRsDumpByteList (ACPI_GET16 (PreviousTarget), Target);
            }
            break;

        case ACPI_RSD_DWORDLIST:
            /*
             * Dword list for Extended Interrupt resources
             * Note: The list length is obtained from the previous table entry
             */
            if (PreviousTarget)
            {
                AcpiRsDumpDwordList (*PreviousTarget,
                    ACPI_CAST_PTR (UINT32, Target));
            }
            break;

        case ACPI_RSD_WORDLIST:
            /*
             * Word list for GPIO Pin Table
             * Note: The list length is obtained from the previous table entry
             */
            if (PreviousTarget)
            {
                AcpiRsDumpWordList (*PreviousTarget,
                    *(ACPI_CAST_INDIRECT_PTR (UINT16, Target)));
            }
            break;

        case ACPI_RSD_ADDRESS:
            /*
             * Common flags for all Address resources
             */
            AcpiRsDumpAddressCommon (ACPI_CAST_PTR (
                ACPI_RESOURCE_DATA, Target));
            break;

        case ACPI_RSD_SOURCE:
            /*
             * Optional ResourceSource for Address resources
             */
            AcpiRsDumpResourceSource (ACPI_CAST_PTR (
                ACPI_RESOURCE_SOURCE, Target));
            break;

        case ACPI_RSD_LABEL:
            /*
             * ResourceLabel
             */
            AcpiRsDumpResourceLabel ("Resource Label", ACPI_CAST_PTR (
                ACPI_RESOURCE_LABEL, Target));
            break;

        case ACPI_RSD_SOURCE_LABEL:
            /*
             * ResourceSourceLabel
             */
            AcpiRsDumpResourceLabel ("Resource Source Label", ACPI_CAST_PTR (
                ACPI_RESOURCE_LABEL, Target));
            break;

        default:

            AcpiOsPrintf ("**** Invalid table opcode [%X] ****\n",
                Table->Opcode);
            return;
        }

        Table++;
        Count--;
    }
}
示例#6
0
文件: rsdump.c 项目: 0-T-0/ps4-linux
static void
acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)
{
	u8 *target = NULL;
	u8 *previous_target;
	char *name;
	u8 count;

	/* First table entry must contain the table length (# of table entries) */

	count = table->offset;

	while (count) {
		previous_target = target;
		target = ACPI_ADD_PTR(u8, resource, table->offset);
		name = table->name;

		switch (table->opcode) {
		case ACPI_RSD_TITLE:
			/*
			 * Optional resource title
			 */
			if (table->name) {
				acpi_os_printf("%s Resource\n", name);
			}
			break;

			/* Strings */

		case ACPI_RSD_LITERAL:

			acpi_rs_out_string(name,
					   ACPI_CAST_PTR(char, table->pointer));
			break;

		case ACPI_RSD_STRING:

			acpi_rs_out_string(name, ACPI_CAST_PTR(char, target));
			break;

			/* Data items, 8/16/32/64 bit */

		case ACPI_RSD_UINT8:

			if (table->pointer) {
				acpi_rs_out_string(name, ACPI_CAST_PTR(char,
								       table->
								       pointer
								       [*target]));
			} else {
				acpi_rs_out_integer8(name, ACPI_GET8(target));
			}
			break;

		case ACPI_RSD_UINT16:

			acpi_rs_out_integer16(name, ACPI_GET16(target));
			break;

		case ACPI_RSD_UINT32:

			acpi_rs_out_integer32(name, ACPI_GET32(target));
			break;

		case ACPI_RSD_UINT64:

			acpi_rs_out_integer64(name, ACPI_GET64(target));
			break;

			/* Flags: 1-bit and 2-bit flags supported */

		case ACPI_RSD_1BITFLAG:

			acpi_rs_out_string(name, ACPI_CAST_PTR(char,
							       table->
							       pointer[*target &
								       0x01]));
			break;

		case ACPI_RSD_2BITFLAG:

			acpi_rs_out_string(name, ACPI_CAST_PTR(char,
							       table->
							       pointer[*target &
								       0x03]));
			break;

		case ACPI_RSD_3BITFLAG:

			acpi_rs_out_string(name, ACPI_CAST_PTR(char,
							       table->
							       pointer[*target &
								       0x07]));
			break;

		case ACPI_RSD_SHORTLIST:
			/*
			 * Short byte list (single line output) for DMA and IRQ resources
			 * Note: The list length is obtained from the previous table entry
			 */
			if (previous_target) {
				acpi_rs_out_title(name);
				acpi_rs_dump_short_byte_list(*previous_target,
							     target);
			}
			break;

		case ACPI_RSD_SHORTLISTX:
			/*
			 * Short byte list (single line output) for GPIO vendor data
			 * Note: The list length is obtained from the previous table entry
			 */
			if (previous_target) {
				acpi_rs_out_title(name);
				acpi_rs_dump_short_byte_list(*previous_target,
							     *
							     (ACPI_CAST_INDIRECT_PTR
							      (u8, target)));
			}
			break;

		case ACPI_RSD_LONGLIST:
			/*
			 * Long byte list for Vendor resource data
			 * Note: The list length is obtained from the previous table entry
			 */
			if (previous_target) {
				acpi_rs_dump_byte_list(ACPI_GET16
						       (previous_target),
						       target);
			}
			break;

		case ACPI_RSD_DWORDLIST:
			/*
			 * Dword list for Extended Interrupt resources
			 * Note: The list length is obtained from the previous table entry
			 */
			if (previous_target) {
				acpi_rs_dump_dword_list(*previous_target,
							ACPI_CAST_PTR(u32,
								      target));
			}
			break;

		case ACPI_RSD_WORDLIST:
			/*
			 * Word list for GPIO Pin Table
			 * Note: The list length is obtained from the previous table entry
			 */
			if (previous_target) {
				acpi_rs_dump_word_list(*previous_target,
						       *(ACPI_CAST_INDIRECT_PTR
							 (u16, target)));
			}
			break;

		case ACPI_RSD_ADDRESS:
			/*
			 * Common flags for all Address resources
			 */
			acpi_rs_dump_address_common(ACPI_CAST_PTR
						    (union acpi_resource_data,
						     target));
			break;

		case ACPI_RSD_SOURCE:
			/*
			 * Optional resource_source for Address resources
			 */
			acpi_rs_dump_resource_source(ACPI_CAST_PTR
						     (struct
								   acpi_resource_source,
								   target));
			break;

		default:

			acpi_os_printf("**** Invalid table opcode [%X] ****\n",
				       table->opcode);
			return;
		}
示例#7
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_system_memory_space_handler
 *
 * PARAMETERS:  Function            - Read or Write operation
 *              Address             - Where in the space to read or write
 *              bit_width           - Field width in bits (8, 16, or 32)
 *              Value               - Pointer to in or out value
 *              handler_context     - Pointer to Handler's context
 *              region_context      - Pointer to context specific to the
 *                                    accessed region
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Handler for the System Memory address space (Op Region)
 *
 ******************************************************************************/
acpi_status
acpi_ex_system_memory_space_handler(u32 function,
				    acpi_physical_address address,
				    u32 bit_width,
				    u64 *value,
				    void *handler_context, void *region_context)
{
	acpi_status status = AE_OK;
	void *logical_addr_ptr = NULL;
	struct acpi_mem_space_context *mem_info = region_context;
	u32 length;
	acpi_size map_length;
	acpi_size page_boundary_map_length;
#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
	u32 remainder;
#endif

	ACPI_FUNCTION_TRACE(ex_system_memory_space_handler);

	/* Validate and translate the bit width */

	switch (bit_width) {
	case 8:
		length = 1;
		break;

	case 16:
		length = 2;
		break;

	case 32:
		length = 4;
		break;

	case 64:
		length = 8;
		break;

	default:
		ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %u",
			    bit_width));
		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
	}

#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
	/*
	 * Hardware does not support non-aligned data transfers, we must verify
	 * the request.
	 */
	(void)acpi_ut_short_divide((u64) address, length, NULL, &remainder);
	if (remainder != 0) {
		return_ACPI_STATUS(AE_AML_ALIGNMENT);
	}
#endif

	/*
	 * Does the request fit into the cached memory mapping?
	 * Is 1) Address below the current mapping? OR
	 *    2) Address beyond the current mapping?
	 */
	if ((address < mem_info->mapped_physical_address) ||
	    (((u64) address + length) > ((u64)
					 mem_info->mapped_physical_address +
					 mem_info->mapped_length))) {
		/*
		 * The request cannot be resolved by the current memory mapping;
		 * Delete the existing mapping and create a new one.
		 */
		if (mem_info->mapped_length) {

			/* Valid mapping, delete it */

			acpi_os_unmap_memory(mem_info->mapped_logical_address,
					     mem_info->mapped_length);
		}

		/*
		 * Attempt to map from the requested address to the end of the region.
		 * However, we will never map more than one page, nor will we cross
		 * a page boundary.
		 */
		map_length = (acpi_size)
		    ((mem_info->address + mem_info->length) - address);

		/*
		 * If mapping the entire remaining portion of the region will cross
		 * a page boundary, just map up to the page boundary, do not cross.
		 * On some systems, crossing a page boundary while mapping regions
		 * can cause warnings if the pages have different attributes
		 * due to resource management
		 */
		page_boundary_map_length =
		    ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address;

		if (!page_boundary_map_length) {
			page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE;
		}

		if (map_length > page_boundary_map_length) {
			map_length = page_boundary_map_length;
		}

		/* Create a new mapping starting at the address given */

		mem_info->mapped_logical_address = acpi_os_map_memory((acpi_physical_address) address, map_length);
		if (!mem_info->mapped_logical_address) {
			ACPI_ERROR((AE_INFO,
				    "Could not map memory at 0x%8.8X%8.8X, size %u",
				    ACPI_FORMAT_NATIVE_UINT(address),
				    (u32) map_length));
			mem_info->mapped_length = 0;
			return_ACPI_STATUS(AE_NO_MEMORY);
		}

		/* Save the physical address and mapping size */

		mem_info->mapped_physical_address = address;
		mem_info->mapped_length = map_length;
	}

	/*
	 * Generate a logical pointer corresponding to the address we want to
	 * access
	 */
	logical_addr_ptr = mem_info->mapped_logical_address +
	    ((u64) address - (u64) mem_info->mapped_physical_address);

	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
			  "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
			  bit_width, function,
			  ACPI_FORMAT_NATIVE_UINT(address)));

	/*
	 * Perform the memory read or write
	 *
	 * Note: For machines that do not support non-aligned transfers, the target
	 * address was checked for alignment above.  We do not attempt to break the
	 * transfer up into smaller (byte-size) chunks because the AML specifically
	 * asked for a transfer width that the hardware may require.
	 */
	switch (function) {
	case ACPI_READ:

		*value = 0;
		switch (bit_width) {
		case 8:
			*value = (u64) ACPI_GET8(logical_addr_ptr);
			break;

		case 16:
			*value = (u64) ACPI_GET16(logical_addr_ptr);
			break;

		case 32:
			*value = (u64) ACPI_GET32(logical_addr_ptr);
			break;

		case 64:
			*value = (u64) ACPI_GET64(logical_addr_ptr);
			break;

		default:
			/* bit_width was already validated */
			break;
		}
		break;

	case ACPI_WRITE:

		switch (bit_width) {
		case 8:
			ACPI_SET8(logical_addr_ptr) = (u8) * value;
			break;

		case 16:
			ACPI_SET16(logical_addr_ptr) = (u16) * value;
			break;

		case 32:
			ACPI_SET32(logical_addr_ptr) = (u32) * value;
			break;

		case 64:
			ACPI_SET64(logical_addr_ptr) = (u64) * value;
			break;

		default:
			/* bit_width was already validated */
			break;
		}
		break;

	default:
		status = AE_BAD_PARAMETER;
		break;
	}

	return_ACPI_STATUS(status);
}
示例#8
0
文件: exregion.c 项目: coyizumi/cs111
ACPI_STATUS
AcpiExSystemMemorySpaceHandler (
    UINT32                  Function,
    ACPI_PHYSICAL_ADDRESS   Address,
    UINT32                  BitWidth,
    UINT64                  *Value,
    void                    *HandlerContext,
    void                    *RegionContext)
{
    ACPI_STATUS             Status = AE_OK;
    void                    *LogicalAddrPtr = NULL;
    ACPI_MEM_SPACE_CONTEXT  *MemInfo = RegionContext;
    UINT32                  Length;
    ACPI_SIZE               MapLength;
    ACPI_SIZE               PageBoundaryMapLength;
#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
    UINT32                  Remainder;
#endif


    ACPI_FUNCTION_TRACE (ExSystemMemorySpaceHandler);


    /* Validate and translate the bit width */

    switch (BitWidth)
    {
    case 8:

        Length = 1;
        break;

    case 16:

        Length = 2;
        break;

    case 32:

        Length = 4;
        break;

    case 64:

        Length = 8;
        break;

    default:

        ACPI_ERROR ((AE_INFO, "Invalid SystemMemory width %u",
            BitWidth));
        return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
    }

#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
    /*
     * Hardware does not support non-aligned data transfers, we must verify
     * the request.
     */
    (void) AcpiUtShortDivide ((UINT64) Address, Length, NULL, &Remainder);
    if (Remainder != 0)
    {
        return_ACPI_STATUS (AE_AML_ALIGNMENT);
    }
#endif

    /*
     * Does the request fit into the cached memory mapping?
     * Is 1) Address below the current mapping? OR
     *    2) Address beyond the current mapping?
     */
    if ((Address < MemInfo->MappedPhysicalAddress) ||
        (((UINT64) Address + Length) >
            ((UINT64)
            MemInfo->MappedPhysicalAddress + MemInfo->MappedLength)))
    {
        /*
         * The request cannot be resolved by the current memory mapping;
         * Delete the existing mapping and create a new one.
         */
        if (MemInfo->MappedLength)
        {
            /* Valid mapping, delete it */

            AcpiOsUnmapMemory (MemInfo->MappedLogicalAddress,
                MemInfo->MappedLength);
        }

        /*
         * October 2009: Attempt to map from the requested address to the
         * end of the region. However, we will never map more than one
         * page, nor will we cross a page boundary.
         */
        MapLength = (ACPI_SIZE)
            ((MemInfo->Address + MemInfo->Length) - Address);

        /*
         * If mapping the entire remaining portion of the region will cross
         * a page boundary, just map up to the page boundary, do not cross.
         * On some systems, crossing a page boundary while mapping regions
         * can cause warnings if the pages have different attributes
         * due to resource management.
         *
         * This has the added benefit of constraining a single mapping to
         * one page, which is similar to the original code that used a 4k
         * maximum window.
         */
        PageBoundaryMapLength = (ACPI_SIZE)
            (ACPI_ROUND_UP (Address, ACPI_DEFAULT_PAGE_SIZE) - Address);
        if (PageBoundaryMapLength == 0)
        {
            PageBoundaryMapLength = ACPI_DEFAULT_PAGE_SIZE;
        }

        if (MapLength > PageBoundaryMapLength)
        {
            MapLength = PageBoundaryMapLength;
        }

        /* Create a new mapping starting at the address given */

        MemInfo->MappedLogicalAddress = AcpiOsMapMemory (Address, MapLength);
        if (!MemInfo->MappedLogicalAddress)
        {
            ACPI_ERROR ((AE_INFO,
                "Could not map memory at 0x%8.8X%8.8X, size %u",
                ACPI_FORMAT_UINT64 (Address), (UINT32) MapLength));
            MemInfo->MappedLength = 0;
            return_ACPI_STATUS (AE_NO_MEMORY);
        }

        /* Save the physical address and mapping size */

        MemInfo->MappedPhysicalAddress = Address;
        MemInfo->MappedLength = MapLength;
    }

    /*
     * Generate a logical pointer corresponding to the address we want to
     * access
     */
    LogicalAddrPtr = MemInfo->MappedLogicalAddress +
        ((UINT64) Address - (UINT64) MemInfo->MappedPhysicalAddress);

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
        BitWidth, Function, ACPI_FORMAT_UINT64 (Address)));

    /*
     * Perform the memory read or write
     *
     * Note: For machines that do not support non-aligned transfers, the target
     * address was checked for alignment above. We do not attempt to break the
     * transfer up into smaller (byte-size) chunks because the AML specifically
     * asked for a transfer width that the hardware may require.
     */
    switch (Function)
    {
    case ACPI_READ:

        *Value = 0;
        switch (BitWidth)
        {
        case 8:

            *Value = (UINT64) ACPI_GET8 (LogicalAddrPtr);
            break;

        case 16:

            *Value = (UINT64) ACPI_GET16 (LogicalAddrPtr);
            break;

        case 32:

            *Value = (UINT64) ACPI_GET32 (LogicalAddrPtr);
            break;

        case 64:

            *Value = (UINT64) ACPI_GET64 (LogicalAddrPtr);
            break;

        default:

            /* BitWidth was already validated */

            break;
        }
        break;

    case ACPI_WRITE:

        switch (BitWidth)
        {
        case 8:

            ACPI_SET8 (LogicalAddrPtr, *Value);
            break;

        case 16:

            ACPI_SET16 (LogicalAddrPtr, *Value);
            break;

        case 32:

            ACPI_SET32 (LogicalAddrPtr, *Value);
            break;

        case 64:

            ACPI_SET64 (LogicalAddrPtr, *Value);
            break;

        default:

            /* BitWidth was already validated */

            break;
        }
        break;

    default:

        Status = AE_BAD_PARAMETER;
        break;
    }

    return_ACPI_STATUS (Status);
}
示例#9
0
static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
						       *parser_state)
{
	u32 aml_offset = (u32)
	    ACPI_PTR_DIFF(parser_state->aml,
			  parser_state->aml_start);
	union acpi_parse_object *field;
	u16 opcode;
	u32 name;

	ACPI_FUNCTION_TRACE("ps_get_next_field");

	/* Determine field type */

	switch (ACPI_GET8(parser_state->aml)) {
	default:

		opcode = AML_INT_NAMEDFIELD_OP;
		break;

	case 0x00:

		opcode = AML_INT_RESERVEDFIELD_OP;
		parser_state->aml++;
		break;

	case 0x01:

		opcode = AML_INT_ACCESSFIELD_OP;
		parser_state->aml++;
		break;
	}

	/* Allocate a new field op */

	field = acpi_ps_alloc_op(opcode);
	if (!field) {
		return_PTR(NULL);
	}

	field->common.aml_offset = aml_offset;

	/* Decode the field type */

	switch (opcode) {
	case AML_INT_NAMEDFIELD_OP:

		/* Get the 4-character name */

		ACPI_MOVE_32_TO_32(&name, parser_state->aml);
		acpi_ps_set_name(field, name);
		parser_state->aml += ACPI_NAME_SIZE;

		/* Get the length which is encoded as a package length */

		field->common.value.size =
		    acpi_ps_get_next_package_length(parser_state);
		break;

	case AML_INT_RESERVEDFIELD_OP:

		/* Get the length which is encoded as a package length */

		field->common.value.size =
		    acpi_ps_get_next_package_length(parser_state);
		break;

	case AML_INT_ACCESSFIELD_OP:

		/*
		 * Get access_type and access_attrib and merge into the field Op
		 * access_type is first operand, access_attribute is second
		 */
		field->common.value.integer =
		    (ACPI_GET8(parser_state->aml) << 8);
		parser_state->aml++;
		field->common.value.integer |= ACPI_GET8(parser_state->aml);
		parser_state->aml++;
		break;

	default:

		/* Opcode was set in previous switch */
		break;
	}

	return_PTR(field);
}
示例#10
0
void
acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
			    u32 arg_type, union acpi_parse_object *arg)
{

	ACPI_FUNCTION_TRACE_U32("ps_get_next_simple_arg", arg_type);

	switch (arg_type) {
	case ARGP_BYTEDATA:

		acpi_ps_init_op(arg, AML_BYTE_OP);
		arg->common.value.integer = (u32) ACPI_GET8(parser_state->aml);
		parser_state->aml++;
		break;

	case ARGP_WORDDATA:

		acpi_ps_init_op(arg, AML_WORD_OP);

		/* Get 2 bytes from the AML stream */

		ACPI_MOVE_16_TO_32(&arg->common.value.integer,
				   parser_state->aml);
		parser_state->aml += 2;
		break;

	case ARGP_DWORDDATA:

		acpi_ps_init_op(arg, AML_DWORD_OP);

		/* Get 4 bytes from the AML stream */

		ACPI_MOVE_32_TO_32(&arg->common.value.integer,
				   parser_state->aml);
		parser_state->aml += 4;
		break;

	case ARGP_QWORDDATA:

		acpi_ps_init_op(arg, AML_QWORD_OP);

		/* Get 8 bytes from the AML stream */

		ACPI_MOVE_64_TO_64(&arg->common.value.integer,
				   parser_state->aml);
		parser_state->aml += 8;
		break;

	case ARGP_CHARLIST:

		acpi_ps_init_op(arg, AML_STRING_OP);
		arg->common.value.string = (char *)parser_state->aml;

		while (ACPI_GET8(parser_state->aml) != '\0') {
			parser_state->aml++;
		}
		parser_state->aml++;
		break;

	case ARGP_NAME:
	case ARGP_NAMESTRING:

		acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP);
		arg->common.value.name =
		    acpi_ps_get_next_namestring(parser_state);
		break;

	default:

		ACPI_REPORT_ERROR(("Invalid arg_type %X\n", arg_type));
		break;
	}

	return_VOID;
}
示例#11
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_system_memory_space_handler
 *
 * PARAMETERS:  Function            - Read or Write operation
 *              Address             - Where in the space to read or write
 *              bit_width           - Field width in bits (8, 16, or 32)
 *              Value               - Pointer to in or out value
 *              handler_context     - Pointer to Handler's context
 *              region_context      - Pointer to context specific to the
 *                                    accessed region
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Handler for the System Memory address space (Op Region)
 *
 ******************************************************************************/
acpi_status
acpi_ex_system_memory_space_handler(u32 function,
				    acpi_physical_address address,
				    u32 bit_width,
				    acpi_integer * value,
				    void *handler_context, void *region_context)
{
	acpi_status status = AE_OK;
	void *logical_addr_ptr = NULL;
	struct acpi_mem_space_context *mem_info = region_context;
	u32 length;
	acpi_size window_size;
#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
	u32 remainder;
#endif

	ACPI_FUNCTION_TRACE(ex_system_memory_space_handler);

	/* Validate and translate the bit width */

	switch (bit_width) {
	case 8:
		length = 1;
		break;

	case 16:
		length = 2;
		break;

	case 32:
		length = 4;
		break;

	case 64:
		length = 8;
		break;

	default:
		ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %d",
			    bit_width));
		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
	}

#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
	/*
	 * Hardware does not support non-aligned data transfers, we must verify
	 * the request.
	 */
	(void)acpi_ut_short_divide((acpi_integer) address, length, NULL,
				   &remainder);
	if (remainder != 0) {
		return_ACPI_STATUS(AE_AML_ALIGNMENT);
	}
#endif

	/*
	 * Does the request fit into the cached memory mapping?
	 * Is 1) Address below the current mapping? OR
	 *    2) Address beyond the current mapping?
	 */
	if ((address < mem_info->mapped_physical_address) ||
	    (((acpi_integer) address + length) > ((acpi_integer)
						  mem_info->
						  mapped_physical_address +
						  mem_info->mapped_length))) {
		/*
		 * The request cannot be resolved by the current memory mapping;
		 * Delete the existing mapping and create a new one.
		 */
		if (mem_info->mapped_length) {

			/* Valid mapping, delete it */

			acpi_os_unmap_memory(mem_info->mapped_logical_address,
					     mem_info->mapped_length);
		}

		/*
		 * Don't attempt to map memory beyond the end of the region, and
		 * constrain the maximum mapping size to something reasonable.
		 */
		window_size = (acpi_size)
		    ((mem_info->address + mem_info->length) - address);

		if (window_size > ACPI_SYSMEM_REGION_WINDOW_SIZE) {
			window_size = ACPI_SYSMEM_REGION_WINDOW_SIZE;
		}

		/* Create a new mapping starting at the address given */

		mem_info->mapped_logical_address =
		    acpi_os_map_memory((acpi_native_uint) address, window_size);
		if (!mem_info->mapped_logical_address) {
			ACPI_ERROR((AE_INFO,
				    "Could not map memory at %8.8X%8.8X, size %X",
				    ACPI_FORMAT_UINT64(address),
				    (u32) window_size));
			mem_info->mapped_length = 0;
			return_ACPI_STATUS(AE_NO_MEMORY);
		}

		/* Save the physical address and mapping size */

		mem_info->mapped_physical_address = address;
		mem_info->mapped_length = window_size;
	}

	/*
	 * Generate a logical pointer corresponding to the address we want to
	 * access
	 */
	logical_addr_ptr = mem_info->mapped_logical_address +
	    ((acpi_integer) address -
	     (acpi_integer) mem_info->mapped_physical_address);

	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
			  "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n",
			  bit_width, function, ACPI_FORMAT_UINT64(address)));

	/*
	 * Perform the memory read or write
	 *
	 * Note: For machines that do not support non-aligned transfers, the target
	 * address was checked for alignment above.  We do not attempt to break the
	 * transfer up into smaller (byte-size) chunks because the AML specifically
	 * asked for a transfer width that the hardware may require.
	 */
	switch (function) {
	case ACPI_READ:

		*value = 0;
		switch (bit_width) {
		case 8:
			*value = (acpi_integer) ACPI_GET8(logical_addr_ptr);
			break;

		case 16:
			*value = (acpi_integer) ACPI_GET16(logical_addr_ptr);
			break;

		case 32:
			*value = (acpi_integer) ACPI_GET32(logical_addr_ptr);
			break;

		case 64:
			*value = (acpi_integer) ACPI_GET64(logical_addr_ptr);
			break;

		default:
			/* bit_width was already validated */
			break;
		}
		break;

	case ACPI_WRITE:

		switch (bit_width) {
		case 8:
			ACPI_SET8(logical_addr_ptr) = (u8) * value;
			break;

		case 16:
			ACPI_SET16(logical_addr_ptr) = (u16) * value;
			break;

		case 32:
			ACPI_SET32(logical_addr_ptr) = (u32) * value;
			break;

		case 64:
			ACPI_SET64(logical_addr_ptr) = (u64) * value;
			break;

		default:
			/* bit_width was already validated */
			break;
		}
		break;

	default:
		status = AE_BAD_PARAMETER;
		break;
	}

	return_ACPI_STATUS(status);
}
示例#12
0
ACPI_STATUS
AcpiExSystemMemorySpaceHandler (
    UINT32                  Function,
    ACPI_PHYSICAL_ADDRESS   Address,
    UINT32                  BitWidth,
    ACPI_INTEGER            *Value,
    void                    *HandlerContext,
    void                    *RegionContext)
{
    ACPI_STATUS             Status = AE_OK;
    void                    *LogicalAddrPtr = NULL;
    ACPI_MEM_SPACE_CONTEXT  *MemInfo = RegionContext;
    UINT32                  Length;
    ACPI_SIZE               WindowSize;
#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
    UINT32                  Remainder;
#endif


    ACPI_FUNCTION_TRACE (ExSystemMemorySpaceHandler);


    /* Validate and translate the bit width */

    switch (BitWidth)
    {
    case 8:
        Length = 1;
        break;

    case 16:
        Length = 2;
        break;

    case 32:
        Length = 4;
        break;

    case 64:
        Length = 8;
        break;

    default:
        ACPI_ERROR ((AE_INFO, "Invalid SystemMemory width %d",
            BitWidth));
        return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
    }

#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
    /*
     * Hardware does not support non-aligned data transfers, we must verify
     * the request.
     */
    (void) AcpiUtShortDivide ((ACPI_INTEGER) Address, Length, NULL, &Remainder);
    if (Remainder != 0)
    {
        return_ACPI_STATUS (AE_AML_ALIGNMENT);
    }
#endif

    /*
     * Does the request fit into the cached memory mapping?
     * Is 1) Address below the current mapping? OR
     *    2) Address beyond the current mapping?
     */
    if ((Address < MemInfo->MappedPhysicalAddress) ||
        (((ACPI_INTEGER) Address + Length) >
            ((ACPI_INTEGER)
            MemInfo->MappedPhysicalAddress + MemInfo->MappedLength)))
    {
        /*
         * The request cannot be resolved by the current memory mapping;
         * Delete the existing mapping and create a new one.
         */
        if (MemInfo->MappedLength)
        {
            /* Valid mapping, delete it */

            AcpiOsUnmapMemory (MemInfo->MappedLogicalAddress,
                MemInfo->MappedLength);
        }

        /*
         * Don't attempt to map memory beyond the end of the region, and
         * constrain the maximum mapping size to something reasonable.
         */
        WindowSize = (ACPI_SIZE)
            ((MemInfo->Address + MemInfo->Length) - Address);

        if (WindowSize > ACPI_SYSMEM_REGION_WINDOW_SIZE)
        {
            WindowSize = ACPI_SYSMEM_REGION_WINDOW_SIZE;
        }

        /* Create a new mapping starting at the address given */

        MemInfo->MappedLogicalAddress = AcpiOsMapMemory (
            (ACPI_PHYSICAL_ADDRESS) Address, WindowSize);
        if (!MemInfo->MappedLogicalAddress)
        {
            ACPI_ERROR ((AE_INFO,
                "Could not map memory at %8.8X%8.8X, size %X",
                ACPI_FORMAT_NATIVE_UINT (Address), (UINT32) WindowSize));
            MemInfo->MappedLength = 0;
            return_ACPI_STATUS (AE_NO_MEMORY);
        }

        /* Save the physical address and mapping size */

        MemInfo->MappedPhysicalAddress = Address;
        MemInfo->MappedLength = WindowSize;
    }

    /*
     * Generate a logical pointer corresponding to the address we want to
     * access
     */
    LogicalAddrPtr = MemInfo->MappedLogicalAddress +
        ((ACPI_INTEGER) Address - (ACPI_INTEGER) MemInfo->MappedPhysicalAddress);

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n",
        BitWidth, Function, ACPI_FORMAT_NATIVE_UINT (Address)));

    /*
     * Perform the memory read or write
     *
     * Note: For machines that do not support non-aligned transfers, the target
     * address was checked for alignment above.  We do not attempt to break the
     * transfer up into smaller (byte-size) chunks because the AML specifically
     * asked for a transfer width that the hardware may require.
     */
    switch (Function)
    {
    case ACPI_READ:

        *Value = 0;
        switch (BitWidth)
        {
        case 8:
            *Value = (ACPI_INTEGER) ACPI_GET8 (LogicalAddrPtr);
            break;

        case 16:
            *Value = (ACPI_INTEGER) ACPI_GET16 (LogicalAddrPtr);
            break;

        case 32:
            *Value = (ACPI_INTEGER) ACPI_GET32 (LogicalAddrPtr);
            break;

        case 64:
            *Value = (ACPI_INTEGER) ACPI_GET64 (LogicalAddrPtr);
            break;

        default:
            /* BitWidth was already validated */
            break;
        }
        break;

    case ACPI_WRITE:

        switch (BitWidth)
        {
        case 8:
            ACPI_SET8 (LogicalAddrPtr) = (UINT8) *Value;
            break;

        case 16:
            ACPI_SET16 (LogicalAddrPtr) = (UINT16) *Value;
            break;

        case 32:
            ACPI_SET32 ( LogicalAddrPtr) = (UINT32) *Value;
            break;

        case 64:
            ACPI_SET64 (LogicalAddrPtr) = (UINT64) *Value;
            break;

        default:
            /* BitWidth was already validated */
            break;
        }
        break;

    default:
        Status = AE_BAD_PARAMETER;
        break;
    }

    return_ACPI_STATUS (Status);
}