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