blob: 4788c079735d8a2571179dbffa2c867a38d142da [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*******************************************************************************
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