Pull sim-fixes into release branch
[pandora-kernel.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 #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->id = 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:  linked_list             - 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 *linked_list,
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) (linked_list->data.address16.resource_type & 0x03);
438         buffer += 1;
439
440         /* Set the general flags */
441
442         *buffer = acpi_rs_encode_general_flags(&linked_list->data);
443         buffer += 1;
444
445         /* Set the type specific flags */
446
447         *buffer = acpi_rs_encode_specific_flags(&linked_list->data);
448         buffer += 1;
449
450         /* Set the address space granularity */
451
452         ACPI_MOVE_32_TO_16(buffer, &linked_list->data.address16.granularity);
453         buffer += 2;
454
455         /* Set the address range minimum */
456
457         ACPI_MOVE_32_TO_16(buffer,
458                            &linked_list->data.address16.min_address_range);
459         buffer += 2;
460
461         /* Set the address range maximum */
462
463         ACPI_MOVE_32_TO_16(buffer,
464                            &linked_list->data.address16.max_address_range);
465         buffer += 2;
466
467         /* Set the address translation offset */
468
469         ACPI_MOVE_32_TO_16(buffer,
470                            &linked_list->data.address16.
471                            address_translation_offset);
472         buffer += 2;
473
474         /* Set the address length */
475
476         ACPI_MOVE_32_TO_16(buffer, &linked_list->data.address16.address_length);
477         buffer += 2;
478
479         /* Resource Source Index and Resource Source are optional */
480
481         if (linked_list->data.address16.resource_source.string_length) {
482                 *buffer =
483                     (u8) linked_list->data.address16.resource_source.index;
484                 buffer += 1;
485
486                 /* Copy the resource_source string */
487
488                 ACPI_STRCPY((char *)buffer,
489                             linked_list->data.address16.resource_source.
490                             string_ptr);
491
492                 /*
493                  * Buffer needs to be set to the length of the string + one for the
494                  * terminating null
495                  */
496                 buffer +=
497                     (acpi_size) (ACPI_STRLEN
498                                  (linked_list->data.address16.resource_source.
499                                   string_ptr) + 1);
500         }
501
502         /* Return the number of bytes consumed in this operation */
503
504         actual_bytes = ACPI_PTR_DIFF(buffer, *output_buffer);
505         *bytes_consumed = actual_bytes;
506
507         /*
508          * Set the length field to the number of bytes consumed
509          * minus the header size (3 bytes)
510          */
511         actual_bytes -= 3;
512         ACPI_MOVE_SIZE_TO_16(length_field, &actual_bytes);
513         return_ACPI_STATUS(AE_OK);
514 }
515
516 /*******************************************************************************
517  *
518  * FUNCTION:    acpi_rs_address32_resource
519  *
520  * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
521  *                                        stream
522  *              bytes_consumed          - Pointer to where the number of bytes
523  *                                        consumed the byte_stream_buffer is
524  *                                        returned
525  *              output_buffer           - Pointer to the return data buffer
526  *              structure_size          - Pointer to where the number of bytes
527  *                                        in the return data struct is returned
528  *
529  * RETURN:      Status
530  *
531  * DESCRIPTION: Take the resource byte stream and fill out the appropriate
532  *              structure pointed to by the output_buffer. Return the
533  *              number of bytes consumed from the byte stream.
534  *
535  ******************************************************************************/
536
537 acpi_status
538 acpi_rs_address32_resource(u8 * byte_stream_buffer,
539                            acpi_size * bytes_consumed,
540                            u8 ** output_buffer, acpi_size * structure_size)
541 {
542         u16 temp16;
543         u8 temp8;
544         u8 *temp_ptr;
545         u32 index;
546         u8 *buffer = byte_stream_buffer;
547         struct acpi_resource *output_struct = (void *)*output_buffer;
548         acpi_size struct_size =
549             ACPI_SIZEOF_RESOURCE(struct acpi_resource_address32);
550
551         ACPI_FUNCTION_TRACE("rs_address32_resource");
552
553         /* Get the Descriptor Length field */
554
555         buffer += 1;
556         ACPI_MOVE_16_TO_16(&temp16, buffer);
557
558         /* Validate minimum descriptor length */
559
560         if (temp16 < 23) {
561                 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
562         }
563
564         *bytes_consumed = temp16 + 3;
565         output_struct->id = ACPI_RSTYPE_ADDRESS32;
566
567         /* Get the Resource Type (Byte3) */
568
569         buffer += 2;
570         temp8 = *buffer;
571
572         /* Values 0-2 and 0xC0-0xFF are valid */
573
574         if ((temp8 > 2) && (temp8 < 0xC0)) {
575                 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
576         }
577
578         output_struct->data.address32.resource_type = temp8;
579
580         /* Get the General Flags (Byte4) */
581
582         buffer += 1;
583         acpi_rs_decode_general_flags(&output_struct->data, *buffer);
584
585         /* Get the Type Specific Flags (Byte5) */
586
587         buffer += 1;
588         acpi_rs_decode_specific_flags(&output_struct->data, *buffer);
589
590         /* Get Granularity (Bytes 6-9) */
591
592         buffer += 1;
593         ACPI_MOVE_32_TO_32(&output_struct->data.address32.granularity, buffer);
594
595         /* Get min_address_range (Bytes 10-13) */
596
597         buffer += 4;
598         ACPI_MOVE_32_TO_32(&output_struct->data.address32.min_address_range,
599                            buffer);
600
601         /* Get max_address_range (Bytes 14-17) */
602
603         buffer += 4;
604         ACPI_MOVE_32_TO_32(&output_struct->data.address32.max_address_range,
605                            buffer);
606
607         /* Get address_translation_offset (Bytes 18-21) */
608
609         buffer += 4;
610         ACPI_MOVE_32_TO_32(&output_struct->data.address32.
611                            address_translation_offset, buffer);
612
613         /* Get address_length (Bytes 22-25) */
614
615         buffer += 4;
616         ACPI_MOVE_32_TO_32(&output_struct->data.address32.address_length,
617                            buffer);
618
619         /* Resource Source Index (if present) */
620
621         buffer += 4;
622
623         /*
624          * This will leave us pointing to the Resource Source Index
625          * If it is present, then save it off and calculate the
626          * pointer to where the null terminated string goes:
627          *
628          * Note: Some resource descriptors will have an additional null, so
629          * we add 1 to the length.
630          */
631         if (*bytes_consumed > (26 + 1)) {
632                 /* Dereference the Index */
633
634                 output_struct->data.address32.resource_source.index =
635                     (u32) * buffer;
636
637                 /* Point to the String */
638
639                 buffer += 1;
640
641                 /* Point the String pointer to the end of this structure */
642
643                 output_struct->data.address32.resource_source.string_ptr =
644                     (char *)((u8 *) output_struct + struct_size);
645
646                 temp_ptr = (u8 *)
647                     output_struct->data.address32.resource_source.string_ptr;
648
649                 /* Copy the resource_source string into the buffer */
650
651                 index = 0;
652                 while (*buffer) {
653                         *temp_ptr = *buffer;
654
655                         temp_ptr++;
656                         buffer++;
657                         index++;
658                 }
659
660                 /* Add the terminating null and set the string length */
661
662                 *temp_ptr = 0;
663                 output_struct->data.address32.resource_source.string_length =
664                     index + 1;
665
666                 /*
667                  * In order for the struct_size to fall on a 32-bit boundary,
668                  * calculate the length of the string and expand the
669                  * struct_size to the next 32-bit boundary.
670                  */
671                 temp8 = (u8) (index + 1);
672                 struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
673         } else {
674                 output_struct->data.address32.resource_source.index = 0;
675                 output_struct->data.address32.resource_source.string_length = 0;
676                 output_struct->data.address32.resource_source.string_ptr = NULL;
677         }
678
679         /* Set the Length parameter */
680
681         output_struct->length = (u32) struct_size;
682
683         /* Return the final size of the structure */
684
685         *structure_size = struct_size;
686         return_ACPI_STATUS(AE_OK);
687 }
688
689 /*******************************************************************************
690  *
691  * FUNCTION:    acpi_rs_address32_stream
692  *
693  * PARAMETERS:  linked_list             - Pointer to the resource linked list
694  *              output_buffer           - Pointer to the user's return buffer
695  *              bytes_consumed          - Pointer to where the number of bytes
696  *                                        used in the output_buffer is returned
697  *
698  * RETURN:      Status
699  *
700  * DESCRIPTION: Take the linked list resource structure and fills in the
701  *              the appropriate bytes in a byte stream
702  *
703  ******************************************************************************/
704
705 acpi_status
706 acpi_rs_address32_stream(struct acpi_resource *linked_list,
707                          u8 ** output_buffer, acpi_size * bytes_consumed)
708 {
709         u8 *buffer;
710         u16 *length_field;
711
712         ACPI_FUNCTION_TRACE("rs_address32_stream");
713
714         buffer = *output_buffer;
715
716         /* Set the Descriptor Type field */
717
718         *buffer = ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE;
719         buffer += 1;
720
721         /* Save a pointer to the Length field - to be filled in later */
722
723         length_field = ACPI_CAST_PTR(u16, buffer);
724         buffer += 2;
725
726         /* Set the Resource Type (Memory, Io, bus_number) */
727
728         *buffer = (u8) (linked_list->data.address32.resource_type & 0x03);
729         buffer += 1;
730
731         /* Set the general flags */
732
733         *buffer = acpi_rs_encode_general_flags(&linked_list->data);
734         buffer += 1;
735
736         /* Set the type specific flags */
737
738         *buffer = acpi_rs_encode_specific_flags(&linked_list->data);
739         buffer += 1;
740
741         /* Set the address space granularity */
742
743         ACPI_MOVE_32_TO_32(buffer, &linked_list->data.address32.granularity);
744         buffer += 4;
745
746         /* Set the address range minimum */
747
748         ACPI_MOVE_32_TO_32(buffer,
749                            &linked_list->data.address32.min_address_range);
750         buffer += 4;
751
752         /* Set the address range maximum */
753
754         ACPI_MOVE_32_TO_32(buffer,
755                            &linked_list->data.address32.max_address_range);
756         buffer += 4;
757
758         /* Set the address translation offset */
759
760         ACPI_MOVE_32_TO_32(buffer,
761                            &linked_list->data.address32.
762                            address_translation_offset);
763         buffer += 4;
764
765         /* Set the address length */
766
767         ACPI_MOVE_32_TO_32(buffer, &linked_list->data.address32.address_length);
768         buffer += 4;
769
770         /* Resource Source Index and Resource Source are optional */
771
772         if (linked_list->data.address32.resource_source.string_length) {
773                 *buffer =
774                     (u8) linked_list->data.address32.resource_source.index;
775                 buffer += 1;
776
777                 /* Copy the resource_source string */
778
779                 ACPI_STRCPY((char *)buffer,
780                             linked_list->data.address32.resource_source.
781                             string_ptr);
782
783                 /*
784                  * Buffer needs to be set to the length of the string + one for the
785                  *  terminating null
786                  */
787                 buffer +=
788                     (acpi_size) (ACPI_STRLEN
789                                  (linked_list->data.address32.resource_source.
790                                   string_ptr) + 1);
791         }
792
793         /* Return the number of bytes consumed in this operation */
794
795         *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
796
797         /*
798          * Set the length field to the number of bytes consumed
799          * minus the header size (3 bytes)
800          */
801         *length_field = (u16) (*bytes_consumed - 3);
802         return_ACPI_STATUS(AE_OK);
803 }
804
805 /*******************************************************************************
806  *
807  * FUNCTION:    acpi_rs_address64_resource
808  *
809  * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
810  *                                        stream
811  *              bytes_consumed          - Pointer to where the number of bytes
812  *                                        consumed the byte_stream_buffer is
813  *                                        returned
814  *              output_buffer           - Pointer to the return data buffer
815  *              structure_size          - Pointer to where the number of bytes
816  *                                        in the return data struct is returned
817  *
818  * RETURN:      Status
819  *
820  * DESCRIPTION: Take the resource byte stream and fill out the appropriate
821  *              structure pointed to by the output_buffer. Return the
822  *              number of bytes consumed from the byte stream.
823  *
824  ******************************************************************************/
825
826 acpi_status
827 acpi_rs_address64_resource(u8 * byte_stream_buffer,
828                            acpi_size * bytes_consumed,
829                            u8 ** output_buffer, acpi_size * structure_size)
830 {
831         u16 temp16;
832         u8 temp8;
833         u8 resource_type;
834         u8 *temp_ptr;
835         u32 index;
836         u8 *buffer = byte_stream_buffer;
837         struct acpi_resource *output_struct = (void *)*output_buffer;
838         acpi_size struct_size =
839             ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64);
840
841         ACPI_FUNCTION_TRACE("rs_address64_resource");
842
843         /* Get the Descriptor Type */
844
845         resource_type = *buffer;
846
847         /* Get the Descriptor Length field */
848
849         buffer += 1;
850         ACPI_MOVE_16_TO_16(&temp16, buffer);
851
852         /* Validate minimum descriptor length */
853
854         if (temp16 < 43) {
855                 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
856         }
857
858         *bytes_consumed = temp16 + 3;
859         output_struct->id = ACPI_RSTYPE_ADDRESS64;
860
861         /* Get the Resource Type (Byte3) */
862
863         buffer += 2;
864         temp8 = *buffer;
865
866         /* Values 0-2 and 0xC0-0xFF are valid */
867
868         if ((temp8 > 2) && (temp8 < 0xC0)) {
869                 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
870         }
871
872         output_struct->data.address64.resource_type = temp8;
873
874         /* Get the General Flags (Byte4) */
875
876         buffer += 1;
877         acpi_rs_decode_general_flags(&output_struct->data, *buffer);
878
879         /* Get the Type Specific Flags (Byte5) */
880
881         buffer += 1;
882         acpi_rs_decode_specific_flags(&output_struct->data, *buffer);
883
884         if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) {
885                 /* Move past revision_id and Reserved byte */
886
887                 buffer += 2;
888         }
889
890         /* Get Granularity (Bytes 6-13) or (Bytes 8-15) */
891
892         buffer += 1;
893         ACPI_MOVE_64_TO_64(&output_struct->data.address64.granularity, buffer);
894
895         /* Get min_address_range (Bytes 14-21) or (Bytes 16-23) */
896
897         buffer += 8;
898         ACPI_MOVE_64_TO_64(&output_struct->data.address64.min_address_range,
899                            buffer);
900
901         /* Get max_address_range (Bytes 22-29) or (Bytes 24-31) */
902
903         buffer += 8;
904         ACPI_MOVE_64_TO_64(&output_struct->data.address64.max_address_range,
905                            buffer);
906
907         /* Get address_translation_offset (Bytes 30-37) or (Bytes 32-39) */
908
909         buffer += 8;
910         ACPI_MOVE_64_TO_64(&output_struct->data.address64.
911                            address_translation_offset, buffer);
912
913         /* Get address_length (Bytes 38-45) or (Bytes 40-47) */
914
915         buffer += 8;
916         ACPI_MOVE_64_TO_64(&output_struct->data.address64.address_length,
917                            buffer);
918
919         output_struct->data.address64.resource_source.index = 0;
920         output_struct->data.address64.resource_source.string_length = 0;
921         output_struct->data.address64.resource_source.string_ptr = NULL;
922
923         if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) {
924                 /* Get type_specific_attribute (Bytes 48-55) */
925
926                 buffer += 8;
927                 ACPI_MOVE_64_TO_64(&output_struct->data.address64.
928                                    type_specific_attributes, buffer);
929         } else {
930                 output_struct->data.address64.type_specific_attributes = 0;
931
932                 /* Resource Source Index (if present) */
933
934                 buffer += 8;
935
936                 /*
937                  * This will leave us pointing to the Resource Source Index
938                  * If it is present, then save it off and calculate the
939                  * pointer to where the null terminated string goes:
940                  * Each Interrupt takes 32-bits + the 5 bytes of the
941                  * stream that are default.
942                  *
943                  * Note: Some resource descriptors will have an additional null, so
944                  * we add 1 to the length.
945                  */
946                 if (*bytes_consumed > (46 + 1)) {
947                         /* Dereference the Index */
948
949                         output_struct->data.address64.resource_source.index =
950                             (u32) * buffer;
951
952                         /* Point to the String */
953
954                         buffer += 1;
955
956                         /* Point the String pointer to the end of this structure */
957
958                         output_struct->data.address64.resource_source.
959                             string_ptr =
960                             (char *)((u8 *) output_struct + struct_size);
961
962                         temp_ptr = (u8 *)
963                             output_struct->data.address64.resource_source.
964                             string_ptr;
965
966                         /* Copy the resource_source string into the buffer */
967
968                         index = 0;
969                         while (*buffer) {
970                                 *temp_ptr = *buffer;
971
972                                 temp_ptr++;
973                                 buffer++;
974                                 index++;
975                         }
976
977                         /*
978                          * Add the terminating null and set the string length
979                          */
980                         *temp_ptr = 0;
981                         output_struct->data.address64.resource_source.
982                             string_length = index + 1;
983
984                         /*
985                          * In order for the struct_size to fall on a 32-bit boundary,
986                          * calculate the length of the string and expand the
987                          * struct_size to the next 32-bit boundary.
988                          */
989                         temp8 = (u8) (index + 1);
990                         struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
991                 }
992         }
993
994         /* Set the Length parameter */
995
996         output_struct->length = (u32) struct_size;
997
998         /* Return the final size of the structure */
999
1000         *structure_size = struct_size;
1001         return_ACPI_STATUS(AE_OK);
1002 }
1003
1004 /*******************************************************************************
1005  *
1006  * FUNCTION:    acpi_rs_address64_stream
1007  *
1008  * PARAMETERS:  linked_list             - Pointer to the resource linked list
1009  *              output_buffer           - Pointer to the user's return buffer
1010  *              bytes_consumed          - Pointer to where the number of bytes
1011  *                                        used in the output_buffer is returned
1012  *
1013  * RETURN:      Status
1014  *
1015  * DESCRIPTION: Take the linked list resource structure and fills in the
1016  *              the appropriate bytes in a byte stream
1017  *
1018  ******************************************************************************/
1019
1020 acpi_status
1021 acpi_rs_address64_stream(struct acpi_resource *linked_list,
1022                          u8 ** output_buffer, acpi_size * bytes_consumed)
1023 {
1024         u8 *buffer;
1025         u16 *length_field;
1026
1027         ACPI_FUNCTION_TRACE("rs_address64_stream");
1028
1029         buffer = *output_buffer;
1030
1031         /* Set the Descriptor Type field */
1032
1033         *buffer = ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE;
1034         buffer += 1;
1035
1036         /* Save a pointer to the Length field - to be filled in later */
1037
1038         length_field = ACPI_CAST_PTR(u16, buffer);
1039         buffer += 2;
1040
1041         /* Set the Resource Type (Memory, Io, bus_number) */
1042
1043         *buffer = (u8) (linked_list->data.address64.resource_type & 0x03);
1044         buffer += 1;
1045
1046         /* Set the general flags */
1047
1048         *buffer = acpi_rs_encode_general_flags(&linked_list->data);
1049         buffer += 1;
1050
1051         /* Set the type specific flags */
1052
1053         *buffer = acpi_rs_encode_specific_flags(&linked_list->data);
1054         buffer += 1;
1055
1056         /* Set the address space granularity */
1057
1058         ACPI_MOVE_64_TO_64(buffer, &linked_list->data.address64.granularity);
1059         buffer += 8;
1060
1061         /* Set the address range minimum */
1062
1063         ACPI_MOVE_64_TO_64(buffer,
1064                            &linked_list->data.address64.min_address_range);
1065         buffer += 8;
1066
1067         /* Set the address range maximum */
1068
1069         ACPI_MOVE_64_TO_64(buffer,
1070                            &linked_list->data.address64.max_address_range);
1071         buffer += 8;
1072
1073         /* Set the address translation offset */
1074
1075         ACPI_MOVE_64_TO_64(buffer,
1076                            &linked_list->data.address64.
1077                            address_translation_offset);
1078         buffer += 8;
1079
1080         /* Set the address length */
1081
1082         ACPI_MOVE_64_TO_64(buffer, &linked_list->data.address64.address_length);
1083         buffer += 8;
1084
1085         /* Resource Source Index and Resource Source are optional */
1086
1087         if (linked_list->data.address64.resource_source.string_length) {
1088                 *buffer =
1089                     (u8) linked_list->data.address64.resource_source.index;
1090                 buffer += 1;
1091
1092                 /* Copy the resource_source string */
1093
1094                 ACPI_STRCPY((char *)buffer,
1095                             linked_list->data.address64.resource_source.
1096                             string_ptr);
1097
1098                 /*
1099                  * Buffer needs to be set to the length of the string + one for the
1100                  * terminating null
1101                  */
1102                 buffer +=
1103                     (acpi_size) (ACPI_STRLEN
1104                                  (linked_list->data.address64.resource_source.
1105                                   string_ptr) + 1);
1106         }
1107
1108         /* Return the number of bytes consumed in this operation */
1109
1110         *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
1111
1112         /*
1113          * Set the length field to the number of bytes consumed
1114          * minus the header size (3 bytes)
1115          */
1116         *length_field = (u16) (*bytes_consumed - 3);
1117         return_ACPI_STATUS(AE_OK);
1118 }