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