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