PageRenderTime 63ms CodeModel.GetById 15ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/acpi/resources/rsaddr.c

https://bitbucket.org/evzijst/gittest
C | 1225 lines | 495 code | 229 blank | 501 comment | 64 complexity | ab5347bbf6690dc36966ca975759b567 MD5 | raw file
   1/*******************************************************************************
   2 *
   3 * Module Name: rsaddr - Address resource descriptors (16/32/64)
   4 *
   5 ******************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2005, R. Byron Moore
   9 * All rights reserved.
  10 *
  11 * Redistribution and use in source and binary forms, with or without
  12 * modification, are permitted provided that the following conditions
  13 * are met:
  14 * 1. Redistributions of source code must retain the above copyright
  15 *    notice, this list of conditions, and the following disclaimer,
  16 *    without modification.
  17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18 *    substantially similar to the "NO WARRANTY" disclaimer below
  19 *    ("Disclaimer") and any redistribution must be conditioned upon
  20 *    including a substantially similar Disclaimer requirement for further
  21 *    binary redistribution.
  22 * 3. Neither the names of the above-listed copyright holders nor the names
  23 *    of any contributors may be used to endorse or promote products derived
  24 *    from this software without specific prior written permission.
  25 *
  26 * Alternatively, this software may be distributed under the terms of the
  27 * GNU General Public License ("GPL") version 2 as published by the Free
  28 * Software Foundation.
  29 *
  30 * NO WARRANTY
  31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41 * POSSIBILITY OF SUCH DAMAGES.
  42 */
  43
  44
  45#include <acpi/acpi.h>
  46#include <acpi/acresrc.h>
  47
  48#define _COMPONENT          ACPI_RESOURCES
  49	 ACPI_MODULE_NAME    ("rsaddr")
  50
  51
  52/*******************************************************************************
  53 *
  54 * FUNCTION:    acpi_rs_address16_resource
  55 *
  56 * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
  57 *                                        stream
  58 *              bytes_consumed          - Pointer to where the number of bytes
  59 *                                        consumed the byte_stream_buffer is
  60 *                                        returned
  61 *              output_buffer           - Pointer to the return data buffer
  62 *              structure_size          - Pointer to where the number of bytes
  63 *                                        in the return data struct is returned
  64 *
  65 * RETURN:      Status
  66 *
  67 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
  68 *              structure pointed to by the output_buffer. Return the
  69 *              number of bytes consumed from the byte stream.
  70 *
  71 ******************************************************************************/
  72
  73acpi_status
  74acpi_rs_address16_resource (
  75	u8                              *byte_stream_buffer,
  76	acpi_size                       *bytes_consumed,
  77	u8                              **output_buffer,
  78	acpi_size                       *structure_size)
  79{
  80	u8                              *buffer = byte_stream_buffer;
  81	struct acpi_resource            *output_struct = (void *) *output_buffer;
  82	u8                              *temp_ptr;
  83	acpi_size                       struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address16);
  84	u32                             index;
  85	u16                             temp16;
  86	u8                              temp8;
  87
  88
  89	ACPI_FUNCTION_TRACE ("rs_address16_resource");
  90
  91
  92	/*
  93	 * Point past the Descriptor to get the number of bytes consumed
  94	 */
  95	buffer += 1;
  96	ACPI_MOVE_16_TO_16 (&temp16, buffer);
  97
  98	/* Validate minimum descriptor length */
  99
 100	if (temp16 < 13) {
 101		return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
 102	}
 103
 104	*bytes_consumed = temp16 + 3;
 105	output_struct->id = ACPI_RSTYPE_ADDRESS16;
 106
 107	/*
 108	 * Get the Resource Type (Byte3)
 109	 */
 110	buffer += 2;
 111	temp8 = *buffer;
 112
 113	/* Values 0-2 and 0xC0-0xFF are valid */
 114
 115	if ((temp8 > 2) && (temp8 < 0xC0)) {
 116		return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
 117	}
 118
 119	output_struct->data.address16.resource_type = temp8;
 120
 121	/*
 122	 * Get the General Flags (Byte4)
 123	 */
 124	buffer += 1;
 125	temp8 = *buffer;
 126
 127	/* Producer / Consumer */
 128
 129	output_struct->data.address16.producer_consumer = temp8 & 0x01;
 130
 131	/* Decode */
 132
 133	output_struct->data.address16.decode = (temp8 >> 1) & 0x01;
 134
 135	/* Min Address Fixed */
 136
 137	output_struct->data.address16.min_address_fixed = (temp8 >> 2) & 0x01;
 138
 139	/* Max Address Fixed */
 140
 141	output_struct->data.address16.max_address_fixed = (temp8 >> 3) & 0x01;
 142
 143	/*
 144	 * Get the Type Specific Flags (Byte5)
 145	 */
 146	buffer += 1;
 147	temp8 = *buffer;
 148
 149	if (ACPI_MEMORY_RANGE == output_struct->data.address16.resource_type) {
 150		output_struct->data.address16.attribute.memory.read_write_attribute =
 151				(u16) (temp8 & 0x01);
 152		output_struct->data.address16.attribute.memory.cache_attribute =
 153				(u16) ((temp8 >> 1) & 0x03);
 154	}
 155	else {
 156		if (ACPI_IO_RANGE == output_struct->data.address16.resource_type) {
 157			output_struct->data.address16.attribute.io.range_attribute =
 158				(u16) (temp8 & 0x03);
 159			output_struct->data.address16.attribute.io.translation_attribute =
 160				(u16) ((temp8 >> 4) & 0x03);
 161		}
 162		else {
 163			/* BUS_NUMBER_RANGE == Address16.Data->resource_type */
 164			/* Nothing needs to be filled in */
 165		}
 166	}
 167
 168	/*
 169	 * Get Granularity (Bytes 6-7)
 170	 */
 171	buffer += 1;
 172	ACPI_MOVE_16_TO_32 (&output_struct->data.address16.granularity, buffer);
 173
 174	/*
 175	 * Get min_address_range (Bytes 8-9)
 176	 */
 177	buffer += 2;
 178	ACPI_MOVE_16_TO_32 (&output_struct->data.address16.min_address_range, buffer);
 179
 180	/*
 181	 * Get max_address_range (Bytes 10-11)
 182	 */
 183	buffer += 2;
 184	ACPI_MOVE_16_TO_32 (&output_struct->data.address16.max_address_range, buffer);
 185
 186	/*
 187	 * Get address_translation_offset (Bytes 12-13)
 188	 */
 189	buffer += 2;
 190	ACPI_MOVE_16_TO_32 (&output_struct->data.address16.address_translation_offset, buffer);
 191
 192	/*
 193	 * Get address_length (Bytes 14-15)
 194	 */
 195	buffer += 2;
 196	ACPI_MOVE_16_TO_32 (&output_struct->data.address16.address_length, buffer);
 197
 198	/*
 199	 * Resource Source Index (if present)
 200	 */
 201	buffer += 2;
 202
 203	/*
 204	 * This will leave us pointing to the Resource Source Index
 205	 * If it is present, then save it off and calculate the
 206	 * pointer to where the null terminated string goes:
 207	 * Each Interrupt takes 32-bits + the 5 bytes of the
 208	 * stream that are default.
 209	 *
 210	 * Note: Some resource descriptors will have an additional null, so
 211	 * we add 1 to the length.
 212	 */
 213	if (*bytes_consumed > (16 + 1)) {
 214		/* Dereference the Index */
 215
 216		temp8 = *buffer;
 217		output_struct->data.address16.resource_source.index = (u32) temp8;
 218
 219		/* Point to the String */
 220
 221		buffer += 1;
 222
 223		/* Point the String pointer to the end of this structure */
 224
 225		output_struct->data.address16.resource_source.string_ptr =
 226				(char *)((u8 * )output_struct + struct_size);
 227
 228		temp_ptr = (u8 *) output_struct->data.address16.resource_source.string_ptr;
 229
 230		/* Copy the string into the buffer */
 231
 232		index = 0;
 233
 234		while (0x00 != *buffer) {
 235			*temp_ptr = *buffer;
 236
 237			temp_ptr += 1;
 238			buffer += 1;
 239			index += 1;
 240		}
 241
 242		/*
 243		 * Add the terminating null
 244		 */
 245		*temp_ptr = 0x00;
 246
 247		output_struct->data.address16.resource_source.string_length = index + 1;
 248
 249		/*
 250		 * In order for the struct_size to fall on a 32-bit boundary,
 251		 * calculate the length of the string and expand the
 252		 * struct_size to the next 32-bit boundary.
 253		 */
 254		temp8 = (u8) (index + 1);
 255		struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
 256	}
 257	else {
 258		output_struct->data.address16.resource_source.index = 0x00;
 259		output_struct->data.address16.resource_source.string_length = 0;
 260		output_struct->data.address16.resource_source.string_ptr = NULL;
 261	}
 262
 263	/*
 264	 * Set the Length parameter
 265	 */
 266	output_struct->length = (u32) struct_size;
 267
 268	/*
 269	 * Return the final size of the structure
 270	 */
 271	*structure_size = struct_size;
 272	return_ACPI_STATUS (AE_OK);
 273}
 274
 275
 276/*******************************************************************************
 277 *
 278 * FUNCTION:    acpi_rs_address16_stream
 279 *
 280 * PARAMETERS:  linked_list             - Pointer to the resource linked list
 281 *              output_buffer           - Pointer to the user's return buffer
 282 *              bytes_consumed          - Pointer to where the number of bytes
 283 *                                        used in the output_buffer is returned
 284 *
 285 * RETURN:      Status
 286 *
 287 * DESCRIPTION: Take the linked list resource structure and fills in the
 288 *              the appropriate bytes in a byte stream
 289 *
 290 ******************************************************************************/
 291
 292acpi_status
 293acpi_rs_address16_stream (
 294	struct acpi_resource            *linked_list,
 295	u8                              **output_buffer,
 296	acpi_size                       *bytes_consumed)
 297{
 298	u8                              *buffer = *output_buffer;
 299	u8                              *length_field;
 300	u8                              temp8;
 301	char                            *temp_pointer = NULL;
 302	acpi_size                       actual_bytes;
 303
 304
 305	ACPI_FUNCTION_TRACE ("rs_address16_stream");
 306
 307
 308	/*
 309	 * The descriptor field is static
 310	 */
 311	*buffer = 0x88;
 312	buffer += 1;
 313
 314	/*
 315	 * Save a pointer to the Length field - to be filled in later
 316	 */
 317	length_field = buffer;
 318	buffer += 2;
 319
 320	/*
 321	 * Set the Resource Type (Memory, Io, bus_number)
 322	 */
 323	temp8 = (u8) (linked_list->data.address16.resource_type & 0x03);
 324	*buffer = temp8;
 325	buffer += 1;
 326
 327	/*
 328	 * Set the general flags
 329	 */
 330	temp8 = (u8) (linked_list->data.address16.producer_consumer & 0x01);
 331
 332	temp8 |= (linked_list->data.address16.decode & 0x01) << 1;
 333	temp8 |= (linked_list->data.address16.min_address_fixed & 0x01) << 2;
 334	temp8 |= (linked_list->data.address16.max_address_fixed & 0x01) << 3;
 335
 336	*buffer = temp8;
 337	buffer += 1;
 338
 339	/*
 340	 * Set the type specific flags
 341	 */
 342	temp8 = 0;
 343
 344	if (ACPI_MEMORY_RANGE == linked_list->data.address16.resource_type) {
 345		temp8 = (u8)
 346			(linked_list->data.address16.attribute.memory.read_write_attribute &
 347			 0x01);
 348
 349		temp8 |=
 350			(linked_list->data.address16.attribute.memory.cache_attribute &
 351			 0x03) << 1;
 352	}
 353	else if (ACPI_IO_RANGE == linked_list->data.address16.resource_type) {
 354		temp8 = (u8)
 355			(linked_list->data.address16.attribute.io.range_attribute &
 356			 0x03);
 357		temp8 |=
 358			(linked_list->data.address16.attribute.io.translation_attribute &
 359			 0x03) << 4;
 360	}
 361
 362	*buffer = temp8;
 363	buffer += 1;
 364
 365	/*
 366	 * Set the address space granularity
 367	 */
 368	ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.granularity);
 369	buffer += 2;
 370
 371	/*
 372	 * Set the address range minimum
 373	 */
 374	ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.min_address_range);
 375	buffer += 2;
 376
 377	/*
 378	 * Set the address range maximum
 379	 */
 380	ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.max_address_range);
 381	buffer += 2;
 382
 383	/*
 384	 * Set the address translation offset
 385	 */
 386	ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.address_translation_offset);
 387	buffer += 2;
 388
 389	/*
 390	 * Set the address length
 391	 */
 392	ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.address_length);
 393	buffer += 2;
 394
 395	/*
 396	 * Resource Source Index and Resource Source are optional
 397	 */
 398	if (0 != linked_list->data.address16.resource_source.string_length) {
 399		temp8 = (u8) linked_list->data.address16.resource_source.index;
 400
 401		*buffer = temp8;
 402		buffer += 1;
 403
 404		temp_pointer = (char *) buffer;
 405
 406		/*
 407		 * Copy the string
 408		 */
 409		ACPI_STRCPY (temp_pointer,
 410				linked_list->data.address16.resource_source.string_ptr);
 411
 412		/*
 413		 * Buffer needs to be set to the length of the sting + one for the
 414		 * terminating null
 415		 */
 416		buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.address16.resource_source.string_ptr) + 1);
 417	}
 418
 419	/*
 420	 * Return the number of bytes consumed in this operation
 421	 */
 422	actual_bytes = ACPI_PTR_DIFF (buffer, *output_buffer);
 423	*bytes_consumed = actual_bytes;
 424
 425	/*
 426	 * Set the length field to the number of bytes consumed
 427	 * minus the header size (3 bytes)
 428	 */
 429	actual_bytes -= 3;
 430	ACPI_MOVE_SIZE_TO_16 (length_field, &actual_bytes);
 431	return_ACPI_STATUS (AE_OK);
 432}
 433
 434
 435/*******************************************************************************
 436 *
 437 * FUNCTION:    acpi_rs_address32_resource
 438 *
 439 * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
 440 *                                        stream
 441 *              bytes_consumed          - Pointer to where the number of bytes
 442 *                                        consumed the byte_stream_buffer is
 443 *                                        returned
 444 *              output_buffer           - Pointer to the return data buffer
 445 *              structure_size          - Pointer to where the number of bytes
 446 *                                        in the return data struct is returned
 447 *
 448 * RETURN:      Status
 449 *
 450 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
 451 *              structure pointed to by the output_buffer. Return the
 452 *              number of bytes consumed from the byte stream.
 453 *
 454 ******************************************************************************/
 455
 456acpi_status
 457acpi_rs_address32_resource (
 458	u8                              *byte_stream_buffer,
 459	acpi_size                       *bytes_consumed,
 460	u8                              **output_buffer,
 461	acpi_size                       *structure_size)
 462{
 463	u8                              *buffer;
 464	struct acpi_resource            *output_struct= (void *) *output_buffer;
 465	u16                             temp16;
 466	u8                              temp8;
 467	u8                              *temp_ptr;
 468	acpi_size                       struct_size;
 469	u32                             index;
 470
 471
 472	ACPI_FUNCTION_TRACE ("rs_address32_resource");
 473
 474
 475	buffer = byte_stream_buffer;
 476	struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address32);
 477
 478	/*
 479	 * Point past the Descriptor to get the number of bytes consumed
 480	 */
 481	buffer += 1;
 482	ACPI_MOVE_16_TO_16 (&temp16, buffer);
 483
 484	/* Validate minimum descriptor length */
 485
 486	if (temp16 < 23) {
 487		return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
 488	}
 489
 490	*bytes_consumed = temp16 + 3;
 491	output_struct->id = ACPI_RSTYPE_ADDRESS32;
 492
 493	/*
 494	 * Get the Resource Type (Byte3)
 495	 */
 496	buffer += 2;
 497	temp8 = *buffer;
 498
 499	/* Values 0-2 and 0xC0-0xFF are valid */
 500
 501	if ((temp8 > 2) && (temp8 < 0xC0)) {
 502		return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
 503	}
 504
 505	output_struct->data.address32.resource_type = temp8;
 506
 507	/*
 508	 * Get the General Flags (Byte4)
 509	 */
 510	buffer += 1;
 511	temp8 = *buffer;
 512
 513	/*
 514	 * Producer / Consumer
 515	 */
 516	output_struct->data.address32.producer_consumer = temp8 & 0x01;
 517
 518	/*
 519	 * Decode
 520	 */
 521	output_struct->data.address32.decode = (temp8 >> 1) & 0x01;
 522
 523	/*
 524	 * Min Address Fixed
 525	 */
 526	output_struct->data.address32.min_address_fixed = (temp8 >> 2) & 0x01;
 527
 528	/*
 529	 * Max Address Fixed
 530	 */
 531	output_struct->data.address32.max_address_fixed = (temp8 >> 3) & 0x01;
 532
 533	/*
 534	 * Get the Type Specific Flags (Byte5)
 535	 */
 536	buffer += 1;
 537	temp8 = *buffer;
 538
 539	if (ACPI_MEMORY_RANGE == output_struct->data.address32.resource_type) {
 540		output_struct->data.address32.attribute.memory.read_write_attribute =
 541				(u16) (temp8 & 0x01);
 542
 543		output_struct->data.address32.attribute.memory.cache_attribute =
 544				(u16) ((temp8 >> 1) & 0x03);
 545	}
 546	else {
 547		if (ACPI_IO_RANGE == output_struct->data.address32.resource_type) {
 548			output_struct->data.address32.attribute.io.range_attribute =
 549				(u16) (temp8 & 0x03);
 550			output_struct->data.address32.attribute.io.translation_attribute =
 551				(u16) ((temp8 >> 4) & 0x03);
 552		}
 553		else {
 554			/* BUS_NUMBER_RANGE == output_struct->Data.Address32.resource_type */
 555			/* Nothing needs to be filled in */
 556		}
 557	}
 558
 559	/*
 560	 * Get Granularity (Bytes 6-9)
 561	 */
 562	buffer += 1;
 563	ACPI_MOVE_32_TO_32 (&output_struct->data.address32.granularity, buffer);
 564
 565	/*
 566	 * Get min_address_range (Bytes 10-13)
 567	 */
 568	buffer += 4;
 569	ACPI_MOVE_32_TO_32 (&output_struct->data.address32.min_address_range, buffer);
 570
 571	/*
 572	 * Get max_address_range (Bytes 14-17)
 573	 */
 574	buffer += 4;
 575	ACPI_MOVE_32_TO_32 (&output_struct->data.address32.max_address_range, buffer);
 576
 577	/*
 578	 * Get address_translation_offset (Bytes 18-21)
 579	 */
 580	buffer += 4;
 581	ACPI_MOVE_32_TO_32 (&output_struct->data.address32.address_translation_offset, buffer);
 582
 583	/*
 584	 * Get address_length (Bytes 22-25)
 585	 */
 586	buffer += 4;
 587	ACPI_MOVE_32_TO_32 (&output_struct->data.address32.address_length, buffer);
 588
 589	/*
 590	 * Resource Source Index (if present)
 591	 */
 592	buffer += 4;
 593
 594	/*
 595	 * This will leave us pointing to the Resource Source Index
 596	 * If it is present, then save it off and calculate the
 597	 * pointer to where the null terminated string goes:
 598	 *
 599	 * Note: Some resource descriptors will have an additional null, so
 600	 * we add 1 to the length.
 601	 */
 602	if (*bytes_consumed > (26 + 1)) {
 603		/* Dereference the Index */
 604
 605		temp8 = *buffer;
 606		output_struct->data.address32.resource_source.index =
 607				(u32) temp8;
 608
 609		/* Point to the String */
 610
 611		buffer += 1;
 612
 613		/* Point the String pointer to the end of this structure */
 614
 615		output_struct->data.address32.resource_source.string_ptr =
 616				(char *)((u8 *)output_struct + struct_size);
 617
 618		temp_ptr = (u8 *) output_struct->data.address32.resource_source.string_ptr;
 619
 620		/* Copy the string into the buffer */
 621
 622		index = 0;
 623		while (0x00 != *buffer) {
 624			*temp_ptr = *buffer;
 625
 626			temp_ptr += 1;
 627			buffer += 1;
 628			index += 1;
 629		}
 630
 631		/*
 632		 * Add the terminating null
 633		 */
 634		*temp_ptr = 0x00;
 635		output_struct->data.address32.resource_source.string_length = index + 1;
 636
 637		/*
 638		 * In order for the struct_size to fall on a 32-bit boundary,
 639		 * calculate the length of the string and expand the
 640		 * struct_size to the next 32-bit boundary.
 641		 */
 642		temp8 = (u8) (index + 1);
 643		struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
 644	}
 645	else {
 646		output_struct->data.address32.resource_source.index = 0x00;
 647		output_struct->data.address32.resource_source.string_length = 0;
 648		output_struct->data.address32.resource_source.string_ptr = NULL;
 649	}
 650
 651	/*
 652	 * Set the Length parameter
 653	 */
 654	output_struct->length = (u32) struct_size;
 655
 656	/*
 657	 * Return the final size of the structure
 658	 */
 659	*structure_size = struct_size;
 660	return_ACPI_STATUS (AE_OK);
 661}
 662
 663
 664/*******************************************************************************
 665 *
 666 * FUNCTION:    acpi_rs_address32_stream
 667 *
 668 * PARAMETERS:  linked_list             - Pointer to the resource linked list
 669 *              output_buffer           - Pointer to the user's return buffer
 670 *              bytes_consumed          - Pointer to where the number of bytes
 671 *                                        used in the output_buffer is returned
 672 *
 673 * RETURN:      Status
 674 *
 675 * DESCRIPTION: Take the linked list resource structure and fills in the
 676 *              the appropriate bytes in a byte stream
 677 *
 678 ******************************************************************************/
 679
 680acpi_status
 681acpi_rs_address32_stream (
 682	struct acpi_resource            *linked_list,
 683	u8                              **output_buffer,
 684	acpi_size                       *bytes_consumed)
 685{
 686	u8                              *buffer;
 687	u16                             *length_field;
 688	u8                              temp8;
 689	char                            *temp_pointer;
 690
 691
 692	ACPI_FUNCTION_TRACE ("rs_address32_stream");
 693
 694
 695	buffer = *output_buffer;
 696
 697	/*
 698	 * The descriptor field is static
 699	 */
 700	*buffer = 0x87;
 701	buffer += 1;
 702
 703	/*
 704	 * Set a pointer to the Length field - to be filled in later
 705	 */
 706	length_field = ACPI_CAST_PTR (u16, buffer);
 707	buffer += 2;
 708
 709	/*
 710	 * Set the Resource Type (Memory, Io, bus_number)
 711	 */
 712	temp8 = (u8) (linked_list->data.address32.resource_type & 0x03);
 713
 714	*buffer = temp8;
 715	buffer += 1;
 716
 717	/*
 718	 * Set the general flags
 719	 */
 720	temp8 = (u8) (linked_list->data.address32.producer_consumer & 0x01);
 721	temp8 |= (linked_list->data.address32.decode & 0x01) << 1;
 722	temp8 |= (linked_list->data.address32.min_address_fixed & 0x01) << 2;
 723	temp8 |= (linked_list->data.address32.max_address_fixed & 0x01) << 3;
 724
 725	*buffer = temp8;
 726	buffer += 1;
 727
 728	/*
 729	 * Set the type specific flags
 730	 */
 731	temp8 = 0;
 732
 733	if (ACPI_MEMORY_RANGE == linked_list->data.address32.resource_type) {
 734		temp8 = (u8)
 735			(linked_list->data.address32.attribute.memory.read_write_attribute &
 736			0x01);
 737
 738		temp8 |=
 739			(linked_list->data.address32.attribute.memory.cache_attribute &
 740			 0x03) << 1;
 741	}
 742	else if (ACPI_IO_RANGE == linked_list->data.address32.resource_type) {
 743		temp8 = (u8)
 744			(linked_list->data.address32.attribute.io.range_attribute &
 745			 0x03);
 746		temp8 |=
 747			(linked_list->data.address32.attribute.io.translation_attribute &
 748			 0x03) << 4;
 749	}
 750
 751	*buffer = temp8;
 752	buffer += 1;
 753
 754	/*
 755	 * Set the address space granularity
 756	 */
 757	ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.granularity);
 758	buffer += 4;
 759
 760	/*
 761	 * Set the address range minimum
 762	 */
 763	ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.min_address_range);
 764	buffer += 4;
 765
 766	/*
 767	 * Set the address range maximum
 768	 */
 769	ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.max_address_range);
 770	buffer += 4;
 771
 772	/*
 773	 * Set the address translation offset
 774	 */
 775	ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.address_translation_offset);
 776	buffer += 4;
 777
 778	/*
 779	 * Set the address length
 780	 */
 781	ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.address_length);
 782	buffer += 4;
 783
 784	/*
 785	 * Resource Source Index and Resource Source are optional
 786	 */
 787	if (0 != linked_list->data.address32.resource_source.string_length) {
 788		temp8 = (u8) linked_list->data.address32.resource_source.index;
 789
 790		*buffer = temp8;
 791		buffer += 1;
 792
 793		temp_pointer = (char *) buffer;
 794
 795		/*
 796		 * Copy the string
 797		 */
 798		ACPI_STRCPY (temp_pointer,
 799			linked_list->data.address32.resource_source.string_ptr);
 800
 801		/*
 802		 * Buffer needs to be set to the length of the sting + one for the
 803		 *  terminating null
 804		 */
 805		buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.address32.resource_source.string_ptr) + 1);
 806	}
 807
 808	/*
 809	 * Return the number of bytes consumed in this operation
 810	 */
 811	*bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
 812
 813	/*
 814	 * Set the length field to the number of bytes consumed
 815	 *  minus the header size (3 bytes)
 816	 */
 817	*length_field = (u16) (*bytes_consumed - 3);
 818	return_ACPI_STATUS (AE_OK);
 819}
 820
 821
 822/*******************************************************************************
 823 *
 824 * FUNCTION:    acpi_rs_address64_resource
 825 *
 826 * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
 827 *                                        stream
 828 *              bytes_consumed          - Pointer to where the number of bytes
 829 *                                        consumed the byte_stream_buffer is
 830 *                                        returned
 831 *              output_buffer           - Pointer to the return data buffer
 832 *              structure_size          - Pointer to where the number of bytes
 833 *                                        in the return data struct is returned
 834 *
 835 * RETURN:      Status
 836 *
 837 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
 838 *              structure pointed to by the output_buffer. Return the
 839 *              number of bytes consumed from the byte stream.
 840 *
 841 ******************************************************************************/
 842
 843acpi_status
 844acpi_rs_address64_resource (
 845	u8                              *byte_stream_buffer,
 846	acpi_size                       *bytes_consumed,
 847	u8                              **output_buffer,
 848	acpi_size                       *structure_size)
 849{
 850	u8                              *buffer;
 851	struct acpi_resource            *output_struct = (void *) *output_buffer;
 852	u16                             temp16;
 853	u8                              temp8;
 854	u8                              resource_type;
 855	u8                              *temp_ptr;
 856	acpi_size                       struct_size;
 857	u32                             index;
 858
 859
 860	ACPI_FUNCTION_TRACE ("rs_address64_resource");
 861
 862
 863	buffer = byte_stream_buffer;
 864	struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64);
 865	resource_type = *buffer;
 866
 867	/*
 868	 * Point past the Descriptor to get the number of bytes consumed
 869	 */
 870	buffer += 1;
 871	ACPI_MOVE_16_TO_16 (&temp16, buffer);
 872
 873	/* Validate minimum descriptor length */
 874
 875	if (temp16 < 43) {
 876		return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
 877	}
 878
 879	*bytes_consumed = temp16 + 3;
 880	output_struct->id = ACPI_RSTYPE_ADDRESS64;
 881
 882	/*
 883	 * Get the Resource Type (Byte3)
 884	 */
 885	buffer += 2;
 886	temp8 = *buffer;
 887
 888	/* Values 0-2 and 0xC0-0xFF are valid */
 889
 890	if ((temp8 > 2) && (temp8 < 0xC0)) {
 891		return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
 892	}
 893
 894	output_struct->data.address64.resource_type = temp8;
 895
 896	/*
 897	 * Get the General Flags (Byte4)
 898	 */
 899	buffer += 1;
 900	temp8 = *buffer;
 901
 902	/*
 903	 * Producer / Consumer
 904	 */
 905	output_struct->data.address64.producer_consumer = temp8 & 0x01;
 906
 907	/*
 908	 * Decode
 909	 */
 910	output_struct->data.address64.decode = (temp8 >> 1) & 0x01;
 911
 912	/*
 913	 * Min Address Fixed
 914	 */
 915	output_struct->data.address64.min_address_fixed = (temp8 >> 2) & 0x01;
 916
 917	/*
 918	 * Max Address Fixed
 919	 */
 920	output_struct->data.address64.max_address_fixed = (temp8 >> 3) & 0x01;
 921
 922	/*
 923	 * Get the Type Specific Flags (Byte5)
 924	 */
 925	buffer += 1;
 926	temp8 = *buffer;
 927
 928	if (ACPI_MEMORY_RANGE == output_struct->data.address64.resource_type) {
 929		output_struct->data.address64.attribute.memory.read_write_attribute =
 930				(u16) (temp8 & 0x01);
 931
 932		output_struct->data.address64.attribute.memory.cache_attribute =
 933				(u16) ((temp8 >> 1) & 0x03);
 934	}
 935	else {
 936		if (ACPI_IO_RANGE == output_struct->data.address64.resource_type) {
 937			output_struct->data.address64.attribute.io.range_attribute =
 938				(u16) (temp8 & 0x03);
 939			output_struct->data.address64.attribute.io.translation_attribute =
 940				(u16) ((temp8 >> 4) & 0x03);
 941		}
 942		else {
 943			/* BUS_NUMBER_RANGE == output_struct->Data.Address64.resource_type */
 944			/* Nothing needs to be filled in */
 945		}
 946	}
 947
 948	if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) {
 949		/* Move past revision_id and Reserved byte */
 950
 951		buffer += 2;
 952	}
 953
 954	/*
 955	 * Get Granularity (Bytes 6-13) or (Bytes 8-15)
 956	 */
 957	buffer += 1;
 958	ACPI_MOVE_64_TO_64 (&output_struct->data.address64.granularity, buffer);
 959
 960	/*
 961	 * Get min_address_range (Bytes 14-21) or (Bytes 16-23)
 962	 */
 963	buffer += 8;
 964	ACPI_MOVE_64_TO_64 (&output_struct->data.address64.min_address_range, buffer);
 965
 966	/*
 967	 * Get max_address_range (Bytes 22-29) or (Bytes 24-31)
 968	 */
 969	buffer += 8;
 970	ACPI_MOVE_64_TO_64 (&output_struct->data.address64.max_address_range, buffer);
 971
 972	/*
 973	 * Get address_translation_offset (Bytes 30-37) or (Bytes 32-39)
 974	 */
 975	buffer += 8;
 976	ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_translation_offset, buffer);
 977
 978	/*
 979	 * Get address_length (Bytes 38-45) or (Bytes 40-47)
 980	 */
 981	buffer += 8;
 982	ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_length, buffer);
 983
 984	output_struct->data.address64.resource_source.index = 0x00;
 985	output_struct->data.address64.resource_source.string_length = 0;
 986	output_struct->data.address64.resource_source.string_ptr = NULL;
 987
 988	if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) {
 989		/* Get type_specific_attribute (Bytes 48-55) */
 990
 991		buffer += 8;
 992		ACPI_MOVE_64_TO_64 (&output_struct->data.address64.type_specific_attributes, buffer);
 993	}
 994	else {
 995		output_struct->data.address64.type_specific_attributes = 0;
 996
 997		/*
 998		 * Resource Source Index (if present)
 999		 */
1000		buffer += 8;
1001
1002		/*
1003		 * This will leave us pointing to the Resource Source Index
1004		 * If it is present, then save it off and calculate the
1005		 * pointer to where the null terminated string goes:
1006		 * Each Interrupt takes 32-bits + the 5 bytes of the
1007		 * stream that are default.
1008		 *
1009		 * Note: Some resource descriptors will have an additional null, so
1010		 * we add 1 to the length.
1011		 */
1012		if (*bytes_consumed > (46 + 1)) {
1013			/* Dereference the Index */
1014
1015			temp8 = *buffer;
1016			output_struct->data.address64.resource_source.index =
1017					(u32) temp8;
1018
1019			/* Point to the String */
1020
1021			buffer += 1;
1022
1023			/* Point the String pointer to the end of this structure */
1024
1025			output_struct->data.address64.resource_source.string_ptr =
1026					(char *)((u8 *)output_struct + struct_size);
1027
1028			temp_ptr = (u8 *) output_struct->data.address64.resource_source.string_ptr;
1029
1030			/* Copy the string into the buffer */
1031
1032			index = 0;
1033			while (0x00 != *buffer) {
1034				*temp_ptr = *buffer;
1035
1036				temp_ptr += 1;
1037				buffer += 1;
1038				index += 1;
1039			}
1040
1041			/*
1042			 * Add the terminating null
1043			 */
1044			*temp_ptr = 0x00;
1045			output_struct->data.address64.resource_source.string_length = index + 1;
1046
1047			/*
1048			 * In order for the struct_size to fall on a 32-bit boundary,
1049			 * calculate the length of the string and expand the
1050			 * struct_size to the next 32-bit boundary.
1051			 */
1052			temp8 = (u8) (index + 1);
1053			struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
1054		}
1055	}
1056
1057	/*
1058	 * Set the Length parameter
1059	 */
1060	output_struct->length = (u32) struct_size;
1061
1062	/*
1063	 * Return the final size of the structure
1064	 */
1065	*structure_size = struct_size;
1066	return_ACPI_STATUS (AE_OK);
1067}
1068
1069
1070/*******************************************************************************
1071 *
1072 * FUNCTION:    acpi_rs_address64_stream
1073 *
1074 * PARAMETERS:  linked_list             - Pointer to the resource linked list
1075 *              output_buffer           - Pointer to the user's return buffer
1076 *              bytes_consumed          - Pointer to where the number of bytes
1077 *                                        used in the output_buffer is returned
1078 *
1079 * RETURN:      Status
1080 *
1081 * DESCRIPTION: Take the linked list resource structure and fills in the
1082 *              the appropriate bytes in a byte stream
1083 *
1084 ******************************************************************************/
1085
1086acpi_status
1087acpi_rs_address64_stream (
1088	struct acpi_resource            *linked_list,
1089	u8                              **output_buffer,
1090	acpi_size                       *bytes_consumed)
1091{
1092	u8                              *buffer;
1093	u16                             *length_field;
1094	u8                              temp8;
1095	char                            *temp_pointer;
1096
1097
1098	ACPI_FUNCTION_TRACE ("rs_address64_stream");
1099
1100
1101	buffer = *output_buffer;
1102
1103	/*
1104	 * The descriptor field is static
1105	 */
1106	*buffer = 0x8A;
1107	buffer += 1;
1108
1109	/*
1110	 * Set a pointer to the Length field - to be filled in later
1111	 */
1112	length_field = ACPI_CAST_PTR (u16, buffer);
1113	buffer += 2;
1114
1115	/*
1116	 * Set the Resource Type (Memory, Io, bus_number)
1117	 */
1118	temp8 = (u8) (linked_list->data.address64.resource_type & 0x03);
1119
1120	*buffer = temp8;
1121	buffer += 1;
1122
1123	/*
1124	 * Set the general flags
1125	 */
1126	temp8 = (u8) (linked_list->data.address64.producer_consumer & 0x01);
1127	temp8 |= (linked_list->data.address64.decode & 0x01) << 1;
1128	temp8 |= (linked_list->data.address64.min_address_fixed & 0x01) << 2;
1129	temp8 |= (linked_list->data.address64.max_address_fixed & 0x01) << 3;
1130
1131	*buffer = temp8;
1132	buffer += 1;
1133
1134	/*
1135	 * Set the type specific flags
1136	 */
1137	temp8 = 0;
1138
1139	if (ACPI_MEMORY_RANGE == linked_list->data.address64.resource_type) {
1140		temp8 = (u8)
1141			(linked_list->data.address64.attribute.memory.read_write_attribute &
1142			0x01);
1143
1144		temp8 |=
1145			(linked_list->data.address64.attribute.memory.cache_attribute &
1146			 0x03) << 1;
1147	}
1148	else if (ACPI_IO_RANGE == linked_list->data.address64.resource_type) {
1149		temp8 = (u8)
1150			(linked_list->data.address64.attribute.io.range_attribute &
1151			 0x03);
1152		temp8 |=
1153			(linked_list->data.address64.attribute.io.range_attribute &
1154			 0x03) << 4;
1155	}
1156
1157	*buffer = temp8;
1158	buffer += 1;
1159
1160	/*
1161	 * Set the address space granularity
1162	 */
1163	ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.granularity);
1164	buffer += 8;
1165
1166	/*
1167	 * Set the address range minimum
1168	 */
1169	ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.min_address_range);
1170	buffer += 8;
1171
1172	/*
1173	 * Set the address range maximum
1174	 */
1175	ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.max_address_range);
1176	buffer += 8;
1177
1178	/*
1179	 * Set the address translation offset
1180	 */
1181	ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.address_translation_offset);
1182	buffer += 8;
1183
1184	/*
1185	 * Set the address length
1186	 */
1187	ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.address_length);
1188	buffer += 8;
1189
1190	/*
1191	 * Resource Source Index and Resource Source are optional
1192	 */
1193	if (0 != linked_list->data.address64.resource_source.string_length) {
1194		temp8 = (u8) linked_list->data.address64.resource_source.index;
1195
1196		*buffer = temp8;
1197		buffer += 1;
1198
1199		temp_pointer = (char *) buffer;
1200
1201		/*
1202		 * Copy the string
1203		 */
1204		ACPI_STRCPY (temp_pointer, linked_list->data.address64.resource_source.string_ptr);
1205
1206		/*
1207		 * Buffer needs to be set to the length of the sting + one for the
1208		 * terminating null
1209		 */
1210		buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.address64.resource_source.string_ptr) + 1);
1211	}
1212
1213	/*
1214	 * Return the number of bytes consumed in this operation
1215	 */
1216	*bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
1217
1218	/*
1219	 * Set the length field to the number of bytes consumed
1220	 * minus the header size (3 bytes)
1221	 */
1222	*length_field = (u16) (*bytes_consumed - 3);
1223	return_ACPI_STATUS (AE_OK);
1224}
1225