vserver 2.0 rc7
[linux-2.6.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         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
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 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
680 acpi_status
681 acpi_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
843 acpi_status
844 acpi_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
1086 acpi_status
1087 acpi_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