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