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
73 acpi_status
74 acpi_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 are valid */
114
115 if (temp8 > 2) {
116 return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
117 }
118
119 output_struct->data.address16.resource_type = temp8 & 0x03;
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
292 acpi_status
293 acpi_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
456 acpi_status
457 acpi_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 are valid */
500 if(temp8 > 2) {
501 return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
502 }
503
504 output_struct->data.address32.resource_type = temp8 & 0x03;
505
506 /*
507 * Get the General Flags (Byte4)
508 */
509 buffer += 1;
510 temp8 = *buffer;
511
512 /*
513 * Producer / Consumer
514 */
515 output_struct->data.address32.producer_consumer = temp8 & 0x01;
516
517 /*
518 * Decode
519 */
520 output_struct->data.address32.decode = (temp8 >> 1) & 0x01;
521
522 /*
523 * Min Address Fixed
524 */
525 output_struct->data.address32.min_address_fixed = (temp8 >> 2) & 0x01;
526
527 /*
528 * Max Address Fixed
529 */
530 output_struct->data.address32.max_address_fixed = (temp8 >> 3) & 0x01;
531
532 /*
533 * Get the Type Specific Flags (Byte5)
534 */
535 buffer += 1;
536 temp8 = *buffer;
537
538 if (ACPI_MEMORY_RANGE == output_struct->data.address32.resource_type) {
539 output_struct->data.address32.attribute.memory.read_write_attribute =
540 (u16) (temp8 & 0x01);
541
542 output_struct->data.address32.attribute.memory.cache_attribute =
543 (u16) ((temp8 >> 1) & 0x03);
544 }
545 else {
546 if (ACPI_IO_RANGE == output_struct->data.address32.resource_type) {
547 output_struct->data.address32.attribute.io.range_attribute =
548 (u16) (temp8 & 0x03);
549 output_struct->data.address32.attribute.io.translation_attribute =
550 (u16) ((temp8 >> 4) & 0x03);
551 }
552 else {
553 /* BUS_NUMBER_RANGE == output_struct->Data.Address32.resource_type */
554 /* Nothing needs to be filled in */
555 }
556 }
557
558 /*
559 * Get Granularity (Bytes 6-9)
560 */
561 buffer += 1;
562 ACPI_MOVE_32_TO_32 (&output_struct->data.address32.granularity, buffer);
563
564 /*
565 * Get min_address_range (Bytes 10-13)
566 */
567 buffer += 4;
568 ACPI_MOVE_32_TO_32 (&output_struct->data.address32.min_address_range, buffer);
569
570 /*
571 * Get max_address_range (Bytes 14-17)
572 */
573 buffer += 4;
574 ACPI_MOVE_32_TO_32 (&output_struct->data.address32.max_address_range, buffer);
575
576 /*
577 * Get address_translation_offset (Bytes 18-21)
578 */
579 buffer += 4;
580 ACPI_MOVE_32_TO_32 (&output_struct->data.address32.address_translation_offset, buffer);
581
582 /*
583 * Get address_length (Bytes 22-25)
584 */
585 buffer += 4;
586 ACPI_MOVE_32_TO_32 (&output_struct->data.address32.address_length, buffer);
587
588 /*
589 * Resource Source Index (if present)
590 */
591 buffer += 4;
592
593 /*
594 * This will leave us pointing to the Resource Source Index
595 * If it is present, then save it off and calculate the
596 * pointer to where the null terminated string goes:
597 *
598 * Note: Some resource descriptors will have an additional null, so
599 * we add 1 to the length.
600 */
601 if (*bytes_consumed > (26 + 1)) {
602 /* Dereference the Index */
603
604 temp8 = *buffer;
605 output_struct->data.address32.resource_source.index =
606 (u32) temp8;
607
608 /* Point to the String */
609
610 buffer += 1;
611
612 /* Point the String pointer to the end of this structure */
613
614 output_struct->data.address32.resource_source.string_ptr =
615 (char *)((u8 *)output_struct + struct_size);
616
617 temp_ptr = (u8 *) output_struct->data.address32.resource_source.string_ptr;
618
619 /* Copy the string into the buffer */
620
621 index = 0;
622 while (0x00 != *buffer) {
623 *temp_ptr = *buffer;
624
625 temp_ptr += 1;
626 buffer += 1;
627 index += 1;
628 }
629
630 /*
631 * Add the terminating null
632 */
633 *temp_ptr = 0x00;
634 output_struct->data.address32.resource_source.string_length = index + 1;
635
636 /*
637 * In order for the struct_size to fall on a 32-bit boundary,
638 * calculate the length of the string and expand the
639 * struct_size to the next 32-bit boundary.
640 */
641 temp8 = (u8) (index + 1);
642 struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
643 }
644 else {
645 output_struct->data.address32.resource_source.index = 0x00;
646 output_struct->data.address32.resource_source.string_length = 0;
647 output_struct->data.address32.resource_source.string_ptr = NULL;
648 }
649
650 /*
651 * Set the Length parameter
652 */
653 output_struct->length = (u32) struct_size;
654
655 /*
656 * Return the final size of the structure
657 */
658 *structure_size = struct_size;
659 return_ACPI_STATUS (AE_OK);
660 }
661
662
663 /*******************************************************************************
664 *
665 * FUNCTION: acpi_rs_address32_stream
666 *
667 * PARAMETERS: linked_list - Pointer to the resource linked list
668 * output_buffer - Pointer to the user's return buffer
669 * bytes_consumed - Pointer to where the number of bytes
670 * used in the output_buffer is returned
671 *
672 * RETURN: Status
673 *
674 * DESCRIPTION: Take the linked list resource structure and fills in the
675 * the appropriate bytes in a byte stream
676 *
677 ******************************************************************************/
678
679 acpi_status
680 acpi_rs_address32_stream (
681 struct acpi_resource *linked_list,
682 u8 **output_buffer,
683 acpi_size *bytes_consumed)
684 {
685 u8 *buffer;
686 u16 *length_field;
687 u8 temp8;
688 char *temp_pointer;
689
690
691 ACPI_FUNCTION_TRACE ("rs_address32_stream");
692
693
694 buffer = *output_buffer;
695
696 /*
697 * The descriptor field is static
698 */
699 *buffer = 0x87;
700 buffer += 1;
701
702 /*
703 * Set a pointer to the Length field - to be filled in later
704 */
705 length_field = ACPI_CAST_PTR (u16, buffer);
706 buffer += 2;
707
708 /*
709 * Set the Resource Type (Memory, Io, bus_number)
710 */
711 temp8 = (u8) (linked_list->data.address32.resource_type & 0x03);
712
713 *buffer = temp8;
714 buffer += 1;
715
716 /*
717 * Set the general flags
718 */
719 temp8 = (u8) (linked_list->data.address32.producer_consumer & 0x01);
720 temp8 |= (linked_list->data.address32.decode & 0x01) << 1;
721 temp8 |= (linked_list->data.address32.min_address_fixed & 0x01) << 2;
722 temp8 |= (linked_list->data.address32.max_address_fixed & 0x01) << 3;
723
724 *buffer = temp8;
725 buffer += 1;
726
727 /*
728 * Set the type specific flags
729 */
730 temp8 = 0;
731
732 if (ACPI_MEMORY_RANGE == linked_list->data.address32.resource_type) {
733 temp8 = (u8)
734 (linked_list->data.address32.attribute.memory.read_write_attribute &
735 0x01);
736
737 temp8 |=
738 (linked_list->data.address32.attribute.memory.cache_attribute &
739 0x03) << 1;
740 }
741 else if (ACPI_IO_RANGE == linked_list->data.address32.resource_type) {
742 temp8 = (u8)
743 (linked_list->data.address32.attribute.io.range_attribute &
744 0x03);
745 temp8 |=
746 (linked_list->data.address32.attribute.io.translation_attribute &
747 0x03) << 4;
748 }
749
750 *buffer = temp8;
751 buffer += 1;
752
753 /*
754 * Set the address space granularity
755 */
756 ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.granularity);
757 buffer += 4;
758
759 /*
760 * Set the address range minimum
761 */
762 ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.min_address_range);
763 buffer += 4;
764
765 /*
766 * Set the address range maximum
767 */
768 ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.max_address_range);
769 buffer += 4;
770
771 /*
772 * Set the address translation offset
773 */
774 ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.address_translation_offset);
775 buffer += 4;
776
777 /*
778 * Set the address length
779 */
780 ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.address_length);
781 buffer += 4;
782
783 /*
784 * Resource Source Index and Resource Source are optional
785 */
786 if (0 != linked_list->data.address32.resource_source.string_length) {
787 temp8 = (u8) linked_list->data.address32.resource_source.index;
788
789 *buffer = temp8;
790 buffer += 1;
791
792 temp_pointer = (char *) buffer;
793
794 /*
795 * Copy the string
796 */
797 ACPI_STRCPY (temp_pointer,
798 linked_list->data.address32.resource_source.string_ptr);
799
800 /*
801 * Buffer needs to be set to the length of the sting + one for the
802 * terminating null
803 */
804 buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.address32.resource_source.string_ptr) + 1);
805 }
806
807 /*
808 * Return the number of bytes consumed in this operation
809 */
810 *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
811
812 /*
813 * Set the length field to the number of bytes consumed
814 * minus the header size (3 bytes)
815 */
816 *length_field = (u16) (*bytes_consumed - 3);
817 return_ACPI_STATUS (AE_OK);
818 }
819
820
821 /*******************************************************************************
822 *
823 * FUNCTION: acpi_rs_address64_resource
824 *
825 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
826 * stream
827 * bytes_consumed - Pointer to where the number of bytes
828 * consumed the byte_stream_buffer is
829 * returned
830 * output_buffer - Pointer to the return data buffer
831 * structure_size - Pointer to where the number of bytes
832 * in the return data struct is returned
833 *
834 * RETURN: Status
835 *
836 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
837 * structure pointed to by the output_buffer. Return the
838 * number of bytes consumed from the byte stream.
839 *
840 ******************************************************************************/
841
842 acpi_status
843 acpi_rs_address64_resource (
844 u8 *byte_stream_buffer,
845 acpi_size *bytes_consumed,
846 u8 **output_buffer,
847 acpi_size *structure_size)
848 {
849 u8 *buffer;
850 struct acpi_resource *output_struct = (void *) *output_buffer;
851 u16 temp16;
852 u8 temp8;
853 u8 *temp_ptr;
854 acpi_size struct_size;
855 u32 index;
856
857
858 ACPI_FUNCTION_TRACE ("rs_address64_resource");
859
860
861 buffer = byte_stream_buffer;
862 struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64);
863
864 /*
865 * Point past the Descriptor to get the number of bytes consumed
866 */
867 buffer += 1;
868 ACPI_MOVE_16_TO_16 (&temp16, buffer);
869
870 /* Validate minimum descriptor length */
871
872 if (temp16 < 43) {
873 return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
874 }
875
876 *bytes_consumed = temp16 + 3;
877 output_struct->id = ACPI_RSTYPE_ADDRESS64;
878
879 /*
880 * Get the Resource Type (Byte3)
881 */
882 buffer += 2;
883 temp8 = *buffer;
884
885 /* Values 0-2 are valid */
886
887 if(temp8 > 2) {
888 return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
889 }
890
891 output_struct->data.address64.resource_type = temp8 & 0x03;
892
893 /*
894 * Get the General Flags (Byte4)
895 */
896 buffer += 1;
897 temp8 = *buffer;
898
899 /*
900 * Producer / Consumer
901 */
902 output_struct->data.address64.producer_consumer = temp8 & 0x01;
903
904 /*
905 * Decode
906 */
907 output_struct->data.address64.decode = (temp8 >> 1) & 0x01;
908
909 /*
910 * Min Address Fixed
911 */
912 output_struct->data.address64.min_address_fixed = (temp8 >> 2) & 0x01;
913
914 /*
915 * Max Address Fixed
916 */
917 output_struct->data.address64.max_address_fixed = (temp8 >> 3) & 0x01;
918
919 /*
920 * Get the Type Specific Flags (Byte5)
921 */
922 buffer += 1;
923 temp8 = *buffer;
924
925 if (ACPI_MEMORY_RANGE == output_struct->data.address64.resource_type) {
926 output_struct->data.address64.attribute.memory.read_write_attribute =
927 (u16) (temp8 & 0x01);
928
929 output_struct->data.address64.attribute.memory.cache_attribute =
930 (u16) ((temp8 >> 1) & 0x03);
931 }
932 else {
933 if (ACPI_IO_RANGE == output_struct->data.address64.resource_type) {
934 output_struct->data.address64.attribute.io.range_attribute =
935 (u16) (temp8 & 0x03);
936 output_struct->data.address64.attribute.io.translation_attribute =
937 (u16) ((temp8 >> 4) & 0x03);
938 }
939 else {
940 /* BUS_NUMBER_RANGE == output_struct->Data.Address64.resource_type */
941 /* Nothing needs to be filled in */
942 }
943 }
944
945 /*
946 * Get Granularity (Bytes 6-13)
947 */
948 buffer += 1;
949 ACPI_MOVE_64_TO_64 (&output_struct->data.address64.granularity, buffer);
950
951 /*
952 * Get min_address_range (Bytes 14-21)
953 */
954 buffer += 8;
955 ACPI_MOVE_64_TO_64 (&output_struct->data.address64.min_address_range, buffer);
956
957 /*
958 * Get max_address_range (Bytes 22-29)
959 */
960 buffer += 8;
961 ACPI_MOVE_64_TO_64 (&output_struct->data.address64.max_address_range, buffer);
962
963 /*
964 * Get address_translation_offset (Bytes 30-37)
965 */
966 buffer += 8;
967 ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_translation_offset, buffer);
968
969 /*
970 * Get address_length (Bytes 38-45)
971 */
972 buffer += 8;
973 ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_length, buffer);
974
975 /*
976 * Resource Source Index (if present)
977 */
978 buffer += 8;
979
980 /*
981 * This will leave us pointing to the Resource Source Index
982 * If it is present, then save it off and calculate the
983 * pointer to where the null terminated string goes:
984 * Each Interrupt takes 32-bits + the 5 bytes of the
985 * stream that are default.
986 *
987 * Note: Some resource descriptors will have an additional null, so
988 * we add 1 to the length.
989 */
990 if (*bytes_consumed > (46 + 1)) {
991 /* Dereference the Index */
992
993 temp8 = *buffer;
994 output_struct->data.address64.resource_source.index =
995 (u32) temp8;
996
997 /* Point to the String */
998
999 buffer += 1;
1000
1001 /* Point the String pointer to the end of this structure */
1002
1003 output_struct->data.address64.resource_source.string_ptr =
1004 (char *)((u8 *)output_struct + struct_size);
1005
1006 temp_ptr = (u8 *) output_struct->data.address64.resource_source.string_ptr;
1007
1008 /* Copy the string into the buffer */
1009
1010 index = 0;
1011 while (0x00 != *buffer) {
1012 *temp_ptr = *buffer;
1013
1014 temp_ptr += 1;
1015 buffer += 1;
1016 index += 1;
1017 }
1018
1019 /*
1020 * Add the terminating null
1021 */
1022 *temp_ptr = 0x00;
1023 output_struct->data.address64.resource_source.string_length = index + 1;
1024
1025 /*
1026 * In order for the struct_size to fall on a 32-bit boundary,
1027 * calculate the length of the string and expand the
1028 * struct_size to the next 32-bit boundary.
1029 */
1030 temp8 = (u8) (index + 1);
1031 struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
1032 }
1033 else {
1034 output_struct->data.address64.resource_source.index = 0x00;
1035 output_struct->data.address64.resource_source.string_length = 0;
1036 output_struct->data.address64.resource_source.string_ptr = NULL;
1037 }
1038
1039 /*
1040 * Set the Length parameter
1041 */
1042 output_struct->length = (u32) struct_size;
1043
1044 /*
1045 * Return the final size of the structure
1046 */
1047 *structure_size = struct_size;
1048 return_ACPI_STATUS (AE_OK);
1049 }
1050
1051
1052 /*******************************************************************************
1053 *
1054 * FUNCTION: acpi_rs_address64_stream
1055 *
1056 * PARAMETERS: linked_list - Pointer to the resource linked list
1057 * output_buffer - Pointer to the user's return buffer
1058 * bytes_consumed - Pointer to where the number of bytes
1059 * used in the output_buffer is returned
1060 *
1061 * RETURN: Status
1062 *
1063 * DESCRIPTION: Take the linked list resource structure and fills in the
1064 * the appropriate bytes in a byte stream
1065 *
1066 ******************************************************************************/
1067
1068 acpi_status
1069 acpi_rs_address64_stream (
1070 struct acpi_resource *linked_list,
1071 u8 **output_buffer,
1072 acpi_size *bytes_consumed)
1073 {
1074 u8 *buffer;
1075 u16 *length_field;
1076 u8 temp8;
1077 char *temp_pointer;
1078
1079
1080 ACPI_FUNCTION_TRACE ("rs_address64_stream");
1081
1082
1083 buffer = *output_buffer;
1084
1085 /*
1086 * The descriptor field is static
1087 */
1088 *buffer = 0x8A;
1089 buffer += 1;
1090
1091 /*
1092 * Set a pointer to the Length field - to be filled in later
1093 */
1094 length_field = ACPI_CAST_PTR (u16, buffer);
1095 buffer += 2;
1096
1097 /*
1098 * Set the Resource Type (Memory, Io, bus_number)
1099 */
1100 temp8 = (u8) (linked_list->data.address64.resource_type & 0x03);
1101
1102 *buffer = temp8;
1103 buffer += 1;
1104
1105 /*
1106 * Set the general flags
1107 */
1108 temp8 = (u8) (linked_list->data.address64.producer_consumer & 0x01);
1109 temp8 |= (linked_list->data.address64.decode & 0x01) << 1;
1110 temp8 |= (linked_list->data.address64.min_address_fixed & 0x01) << 2;
1111 temp8 |= (linked_list->data.address64.max_address_fixed & 0x01) << 3;
1112
1113 *buffer = temp8;
1114 buffer += 1;
1115
1116 /*
1117 * Set the type specific flags
1118 */
1119 temp8 = 0;
1120
1121 if (ACPI_MEMORY_RANGE == linked_list->data.address64.resource_type) {
1122 temp8 = (u8)
1123 (linked_list->data.address64.attribute.memory.read_write_attribute &
1124 0x01);
1125
1126 temp8 |=
1127 (linked_list->data.address64.attribute.memory.cache_attribute &
1128 0x03) << 1;
1129 }
1130 else if (ACPI_IO_RANGE == linked_list->data.address64.resource_type) {
1131 temp8 = (u8)
1132 (linked_list->data.address64.attribute.io.range_attribute &
1133 0x03);
1134 temp8 |=
1135 (linked_list->data.address64.attribute.io.range_attribute &
1136 0x03) << 4;
1137 }
1138
1139 *buffer = temp8;
1140 buffer += 1;
1141
1142 /*
1143 * Set the address space granularity
1144 */
1145 ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.granularity);
1146 buffer += 8;
1147
1148 /*
1149 * Set the address range minimum
1150 */
1151 ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.min_address_range);
1152 buffer += 8;
1153
1154 /*
1155 * Set the address range maximum
1156 */
1157 ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.max_address_range);
1158 buffer += 8;
1159
1160 /*
1161 * Set the address translation offset
1162 */
1163 ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.address_translation_offset);
1164 buffer += 8;
1165
1166 /*
1167 * Set the address length
1168 */
1169 ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.address_length);
1170 buffer += 8;
1171
1172 /*
1173 * Resource Source Index and Resource Source are optional
1174 */
1175 if (0 != linked_list->data.address64.resource_source.string_length) {
1176 temp8 = (u8) linked_list->data.address64.resource_source.index;
1177
1178 *buffer = temp8;
1179 buffer += 1;
1180
1181 temp_pointer = (char *) buffer;
1182
1183 /*
1184 * Copy the string
1185 */
1186 ACPI_STRCPY (temp_pointer, linked_list->data.address64.resource_source.string_ptr);
1187
1188 /*
1189 * Buffer needs to be set to the length of the sting + one for the
1190 * terminating null
1191 */
1192 buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.address64.resource_source.string_ptr) + 1);
1193 }
1194
1195 /*
1196 * Return the number of bytes consumed in this operation
1197 */
1198 *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
1199
1200 /*
1201 * Set the length field to the number of bytes consumed
1202 * minus the header size (3 bytes)
1203 */
1204 *length_field = (u16) (*bytes_consumed - 3);
1205 return_ACPI_STATUS (AE_OK);
1206 }
1207
1208
|
This page was automatically generated by the
LXR engine.
|