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