acpi_status
acpi_ex_system_memory_space_handler (
	u32                     function,
	ACPI_PHYSICAL_ADDRESS   address,
	u32                     bit_width,
	u32                     *value,
	void                    *handler_context,
	void                    *region_context)
{
	acpi_status             status = AE_OK;
	void                    *logical_addr_ptr = NULL;
	acpi_mem_space_context  *mem_info = region_context;
	u32                     length;


	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;

	default:
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid System_memory width %d\n",
			bit_width));
		return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
		break;
	}


	/*
	 * 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);
		}

		mem_info->mapped_length = 0; /* In case of failure below */

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

		status = acpi_os_map_memory (address, SYSMEM_REGION_WINDOW_SIZE,
				  (void **) &mem_info->mapped_logical_address);
		if (ACPI_FAILURE (status)) {
			return_ACPI_STATUS (status);
		}

		/* Save the physical address and mapping size */

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


	/*
	 * Generate a logical pointer corresponding to the address we want to
	 * access
	 */

	/* TBD: should these pointers go to 64-bit in all cases ? */

	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 %d (%d width) Address=%8.8X%8.8X\n", function, bit_width,
		HIDWORD (address), LODWORD (address)));

   /* Perform the memory read or write */

	switch (function) {

	case ACPI_READ_ADR_SPACE:

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

		case 16:
			MOVE_UNALIGNED16_TO_32 (value, logical_addr_ptr);
			break;

		case 32:
			MOVE_UNALIGNED32_TO_32 (value, logical_addr_ptr);
			break;
		}

		break;


	case ACPI_WRITE_ADR_SPACE:

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

		case 16:
			MOVE_UNALIGNED16_TO_16 (logical_addr_ptr, value);
			break;

		case 32:
			MOVE_UNALIGNED32_TO_32 (logical_addr_ptr, value);
			break;
		}

		break;


	default:
		status = AE_BAD_PARAMETER;
		break;
	}

	return_ACPI_STATUS (status);
}
Example #2
0
acpi_status
acpi_rs_calculate_list_length (
	u8                      *byte_stream_buffer,
	u32                     byte_stream_buffer_length,
	u32                     *size_needed)
{
	u32                     buffer_size = 0;
	u32                     bytes_parsed = 0;
	u8                      number_of_interrupts = 0;
	u8                      number_of_channels = 0;
	u8                      resource_type;
	u32                     structure_size;
	u32                     bytes_consumed;
	u8                      *buffer;
	u8                      temp8;
	u16                     temp16;
	u8                      index;
	u8                      additional_bytes;


	FUNCTION_TRACE ("Rs_calculate_list_length");


	while (bytes_parsed < byte_stream_buffer_length) {
		/*
		 * The next byte in the stream is the resource type
		 */
		resource_type = acpi_rs_get_resource_type (*byte_stream_buffer);

		switch (resource_type) {
		case RESOURCE_DESC_MEMORY_24:
			/*
			 * 24-Bit Memory Resource
			 */
			bytes_consumed = 12;

			structure_size = SIZEOF_RESOURCE (acpi_resource_mem24);
			break;


		case RESOURCE_DESC_LARGE_VENDOR:
			/*
			 * Vendor Defined Resource
			 */
			buffer = byte_stream_buffer;
			++buffer;

			MOVE_UNALIGNED16_TO_16 (&temp16, buffer);
			bytes_consumed = temp16 + 3;

			/*
			 * Ensure a 32-bit boundary for the structure
			 */
			temp16 = (u16) ROUND_UP_TO_32_bITS (temp16);

			structure_size = SIZEOF_RESOURCE (acpi_resource_vendor) +
					   (temp16 * sizeof (u8));
			break;


		case RESOURCE_DESC_MEMORY_32:
			/*
			 * 32-Bit Memory Range Resource
			 */

			bytes_consumed = 20;

			structure_size = SIZEOF_RESOURCE (acpi_resource_mem32);
			break;


		case RESOURCE_DESC_FIXED_MEMORY_32:
			/*
			 * 32-Bit Fixed Memory Resource
			 */
			bytes_consumed = 12;

			structure_size = SIZEOF_RESOURCE (acpi_resource_fixed_mem32);
			break;


		case RESOURCE_DESC_QWORD_ADDRESS_SPACE:
			/*
			 * 64-Bit Address Resource
			 */
			buffer = byte_stream_buffer;

			++buffer;
			MOVE_UNALIGNED16_TO_16 (&temp16, buffer);

			bytes_consumed = temp16 + 3;

			/*
			 * Resource Source Index and Resource Source are
			 * optional elements.  Check the length of the
			 * Bytestream.  If it is greater than 43, that
			 * means that an Index exists and is followed by
			 * a null termininated string.  Therefore, set
			 * the temp variable to the length minus the minimum
			 * byte stream length plus the byte for the Index to
			 * determine the size of the NULL terminiated string.
			 */
			if (43 < temp16) {
				temp8 = (u8) (temp16 - 44);
			}
			else {
				temp8 = 0;
			}

			/*
			 * Ensure a 64-bit boundary for the structure
			 */
			temp8 = (u8) ROUND_UP_TO_64_bITS (temp8);

			structure_size = SIZEOF_RESOURCE (acpi_resource_address64) +
					   (temp8 * sizeof (u8));
			break;


		case RESOURCE_DESC_DWORD_ADDRESS_SPACE:
			/*
			 * 32-Bit Address Resource
			 */
			buffer = byte_stream_buffer;

			++buffer;
			MOVE_UNALIGNED16_TO_16 (&temp16, buffer);

			bytes_consumed = temp16 + 3;

			/*
			 * Resource Source Index and Resource Source are
			 * optional elements.  Check the length of the
			 * Bytestream.  If it is greater than 23, that
			 * means that an Index exists and is followed by
			 * a null termininated string.  Therefore, set
			 * the temp variable to the length minus the minimum
			 * byte stream length plus the byte for the Index to
			 * determine the size of the NULL terminiated string.
			 */
			if (23 < temp16) {
				temp8 = (u8) (temp16 - 24);
			}
			else {
				temp8 = 0;
			}

			/*
			 * Ensure a 32-bit boundary for the structure
			 */
			temp8 = (u8) ROUND_UP_TO_32_bITS (temp8);

			structure_size = SIZEOF_RESOURCE (acpi_resource_address32) +
					   (temp8 * sizeof (u8));
			break;


		case RESOURCE_DESC_WORD_ADDRESS_SPACE:
			/*
			 * 16-Bit Address Resource
			 */
			buffer = byte_stream_buffer;

			++buffer;
			MOVE_UNALIGNED16_TO_16 (&temp16, buffer);

			bytes_consumed = temp16 + 3;

			/*
			 * Resource Source Index and Resource Source are
			 * optional elements.  Check the length of the
			 * Bytestream.  If it is greater than 13, that
			 * means that an Index exists and is followed by
			 * a null termininated string.  Therefore, set
			 * the temp variable to the length minus the minimum
			 * byte stream length plus the byte for the Index to
			 * determine the size of the NULL terminiated string.
			 */
			if (13 < temp16) {
				temp8 = (u8) (temp16 - 14);
			}
			else {
				temp8 = 0;
			}

			/*
			 * Ensure a 32-bit boundary for the structure
			 */
			temp8 = (u8) ROUND_UP_TO_32_bITS (temp8);

			structure_size = SIZEOF_RESOURCE (acpi_resource_address16) +
					   (temp8 * sizeof (u8));
			break;


		case RESOURCE_DESC_EXTENDED_XRUPT:
			/*
			 * Extended IRQ
			 */
			buffer = byte_stream_buffer;

			++buffer;
			MOVE_UNALIGNED16_TO_16 (&temp16, buffer);

			bytes_consumed = temp16 + 3;

			/*
			 * Point past the length field and the
			 * Interrupt vector flags to save off the
			 * Interrupt table length to the Temp8 variable.
			 */
			buffer += 3;
			temp8 = *buffer;

			/*
			 * To compensate for multiple interrupt numbers, add 4 bytes for
			 * each additional interrupts greater than 1
			 */
			additional_bytes = (u8) ((temp8 - 1) * 4);

			/*
			 * Resource Source Index and Resource Source are
			 * optional elements.  Check the length of the
			 * Bytestream.  If it is greater than 9, that
			 * means that an Index exists and is followed by
			 * a null termininated string.  Therefore, set
			 * the temp variable to the length minus the minimum
			 * byte stream length plus the byte for the Index to
			 * determine the size of the NULL terminiated string.
			 */
			if (9 + additional_bytes < temp16) {
				temp8 = (u8) (temp16 - (9 + additional_bytes));
			}

			else {
				temp8 = 0;
			}

			/*
			 * Ensure a 32-bit boundary for the structure
			 */
			temp8 = (u8) ROUND_UP_TO_32_bITS (temp8);

			structure_size = SIZEOF_RESOURCE (acpi_resource_ext_irq) +
					   (additional_bytes * sizeof (u8)) +
					   (temp8 * sizeof (u8));
			break;


		case RESOURCE_DESC_IRQ_FORMAT:
			/*
			 * IRQ Resource.
			 * Determine if it there are two or three trailing bytes
			 */
			buffer = byte_stream_buffer;
			temp8 = *buffer;

			if(temp8 & 0x01) {
				bytes_consumed = 4;
			}

			else {
				bytes_consumed = 3;
			}

			/*
			 * Point past the descriptor
			 */
			++buffer;

			/*
			 * Look at the number of bits set
			 */
			MOVE_UNALIGNED16_TO_16 (&temp16, buffer);

			for (index = 0; index < 16; index++) {
				if (temp16 & 0x1) {
					++number_of_interrupts;
				}

				temp16 >>= 1;
			}

			structure_size = SIZEOF_RESOURCE (acpi_resource_io) +
					   (number_of_interrupts * sizeof (u32));
			break;


		case RESOURCE_DESC_DMA_FORMAT:
			/*
			 * DMA Resource
			 */
			buffer = byte_stream_buffer;
			bytes_consumed = 3;

			/*
			 * Point past the descriptor
			 */
			++buffer;

			/*
			 * Look at the number of bits set
			 */
			temp8 = *buffer;

			for(index = 0; index < 8; index++) {
				if(temp8 & 0x1) {
					++number_of_channels;
				}

				temp8 >>= 1;
			}

			structure_size = SIZEOF_RESOURCE (acpi_resource_dma) +
					   (number_of_channels * sizeof (u32));
			break;


		case RESOURCE_DESC_START_DEPENDENT:
			/*
			 * Start Dependent Functions Resource
			 * Determine if it there are two or three trailing bytes
			 */
			buffer = byte_stream_buffer;
			temp8 = *buffer;

			if(temp8 & 0x01) {
				bytes_consumed = 2;
			}
			else {
				bytes_consumed = 1;
			}

			structure_size = SIZEOF_RESOURCE (acpi_resource_start_dpf);
			break;


		case RESOURCE_DESC_END_DEPENDENT:
			/*
			 * End Dependent Functions Resource
			 */
			bytes_consumed = 1;
			structure_size = ACPI_RESOURCE_LENGTH;
			break;


		case RESOURCE_DESC_IO_PORT:
			/*
			 * IO Port Resource
			 */
			bytes_consumed = 8;
			structure_size = SIZEOF_RESOURCE (acpi_resource_io);
			break;


		case RESOURCE_DESC_FIXED_IO_PORT:
			/*
			 * Fixed IO Port Resource
			 */
			bytes_consumed = 4;
			structure_size = SIZEOF_RESOURCE (acpi_resource_fixed_io);
			break;


		case RESOURCE_DESC_SMALL_VENDOR:
			/*
			 * Vendor Specific Resource
			 */
			buffer = byte_stream_buffer;

			temp8 = *buffer;
			temp8 = (u8) (temp8 & 0x7);
			bytes_consumed = temp8 + 1;

			/*
			 * Ensure a 32-bit boundary for the structure
			 */
			temp8 = (u8) ROUND_UP_TO_32_bITS (temp8);
			structure_size = SIZEOF_RESOURCE (acpi_resource_vendor) +
					   (temp8 * sizeof (u8));
			break;


		case RESOURCE_DESC_END_TAG:
			/*
			 * End Tag
			 */
			bytes_consumed = 2;
			structure_size = ACPI_RESOURCE_LENGTH;
			byte_stream_buffer_length = bytes_parsed;
			break;


		default:
			/*
			 * If we get here, everything is out of sync,
			 *  so exit with an error
			 */
			return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
			break;
		}


		/*
		 * Update the return value and counter
		 */
		buffer_size += structure_size;
		bytes_parsed += bytes_consumed;

		/*
		 * Set the byte stream to point to the next resource
		 */
		byte_stream_buffer += bytes_consumed;
	}


	/*
	 * This is the data the caller needs
	 */
	*size_needed = buffer_size;
	return_ACPI_STATUS (AE_OK);
}
Example #3
0
acpi_status
acpi_rs_irq_resource (
	u8                      *byte_stream_buffer,
	u32                     *bytes_consumed,
	u8                      **output_buffer,
	u32                     *structure_size)
{
	u8                      *buffer = byte_stream_buffer;
	acpi_resource           *output_struct = (acpi_resource *) *output_buffer;
	u16                     temp16 = 0;
	u8                      temp8 = 0;
	u8                      index;
	u8                      i;
	u32                     struct_size = SIZEOF_RESOURCE (acpi_resource_irq);


	FUNCTION_TRACE ("Rs_irq_resource");


	/*
	 * The number of bytes consumed are contained in the descriptor
	 *  (Bits:0-1)
	 */
	temp8 = *buffer;
	*bytes_consumed = (temp8 & 0x03) + 1;
	output_struct->id = ACPI_RSTYPE_IRQ;

	/*
	 * Point to the 16-bits of Bytes 1 and 2
	 */
	buffer += 1;
	MOVE_UNALIGNED16_TO_16 (&temp16, buffer);

	output_struct->data.irq.number_of_interrupts = 0;

	/* Decode the IRQ bits */

	for (i = 0, index = 0; index < 16; index++) {
		if((temp16 >> index) & 0x01) {
			output_struct->data.irq.interrupts[i] = index;
			i++;
		}
	}
	output_struct->data.irq.number_of_interrupts = i;

	/*
	 * Calculate the structure size based upon the number of interrupts
	 */
	struct_size += (output_struct->data.irq.number_of_interrupts - 1) * 4;

	/*
	 * Point to Byte 3 if it is used
	 */
	if (4 == *bytes_consumed) {
		buffer += 2;
		temp8 = *buffer;

		/*
		 * Check for HE, LL or HL
		 */
		if (temp8 & 0x01) {
			output_struct->data.irq.edge_level = EDGE_SENSITIVE;
			output_struct->data.irq.active_high_low = ACTIVE_HIGH;
		}

		else {
			if (temp8 & 0x8) {
				output_struct->data.irq.edge_level = LEVEL_SENSITIVE;
				output_struct->data.irq.active_high_low = ACTIVE_LOW;
			}

			else {
				/*
				 * Only _LL and _HE polarity/trigger interrupts
				 * are allowed (ACPI spec v1.0b ection 6.4.2.1),
				 * so an error will occur if we reach this point
				 */
				return_ACPI_STATUS (AE_BAD_DATA);
			}
		}

		/*
		 * Check for sharable
		 */
		output_struct->data.irq.shared_exclusive = (temp8 >> 3) & 0x01;
	}