:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / resource / rsaddr.c
1 /*******************************************************************************
2  *
3  * Module Name: rsaddr - Acpi_rs_address16_resource
4  *                       Acpi_rs_address16_stream
5  *                       Acpi_rs_address32_resource
6  *                       Acpi_rs_address32_stream
7  *              $Revision$
8  *
9  ******************************************************************************/
10
11 /*
12  *  Copyright (C) 2000, 2001 R. Byron Moore
13  *
14  *  This program is free software; you can redistribute it and/or modify
15  *  it under the terms of the GNU General Public License as published by
16  *  the Free Software Foundation; either version 2 of the License, or
17  *  (at your option) any later version.
18  *
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software
26  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27  */
28
29
30 #include "acpi.h"
31 #include "acresrc.h"
32
33 #define _COMPONENT          ACPI_RESOURCES
34          MODULE_NAME         ("rsaddr")
35
36
37 /*******************************************************************************
38  *
39  * FUNCTION:    Acpi_rs_address16_resource
40  *
41  * PARAMETERS:  Byte_stream_buffer      - Pointer to the resource input byte
42  *                                              stream
43  *              Bytes_consumed          - u32 pointer that is filled with
44  *                                          the number of bytes consumed from
45  *                                          the Byte_stream_buffer
46  *              Output_buffer           - Pointer to the user's return buffer
47  *              Structure_size          - u32 pointer that is filled with
48  *                                          the number of bytes in the filled
49  *                                          in structure
50  *
51  * RETURN:      Status  AE_OK if okay, else a valid ACPI_STATUS code
52  *
53  * DESCRIPTION: Take the resource byte stream and fill out the appropriate
54  *                  structure pointed to by the Output_buffer. Return the
55  *                  number of bytes consumed from the byte stream.
56  *
57  ******************************************************************************/
58
59 ACPI_STATUS
60 acpi_rs_address16_resource (
61         u8                      *byte_stream_buffer,
62         u32                     *bytes_consumed,
63         u8                      **output_buffer,
64         u32                     *structure_size)
65 {
66         u8                      *buffer = byte_stream_buffer;
67         RESOURCE                *output_struct = (RESOURCE *) * output_buffer;
68         u16                     temp16;
69         u8                      temp8;
70         u32                     index;
71         u32                     struct_size = sizeof(ADDRESS16_RESOURCE) +
72                           RESOURCE_LENGTH_NO_DATA;
73
74
75         /*
76          * Point past the Descriptor to get the number of bytes consumed
77          */
78         buffer += 1;
79
80         MOVE_UNALIGNED16_TO_16 (&temp16, buffer);
81
82         *bytes_consumed = temp16 + 3;
83
84         output_struct->id = address16;
85
86         output_struct->length = struct_size;
87
88         /*
89          * Get the Resource Type (Byte3)
90          */
91         buffer += 2;
92         temp8 = *buffer;
93
94         /* Values 0-2 are valid */
95         if (temp8 > 2) {
96                 return (AE_AML_ERROR);
97         }
98
99         output_struct->data.address16.resource_type = temp8 & 0x03;
100
101         /*
102          * Get the General Flags (Byte4)
103          */
104         buffer += 1;
105         temp8 = *buffer;
106
107         /*
108          * Producer / Consumer
109          */
110         output_struct->data.address16.producer_consumer = temp8 & 0x01;
111
112         /*
113          * Decode
114          */
115         output_struct->data.address16.decode = (temp8 >> 1) & 0x01;
116
117         /*
118          * Min Address Fixed
119          */
120         output_struct->data.address16.min_address_fixed = (temp8 >> 2) & 0x01;
121
122         /*
123          * Max Address Fixed
124          */
125         output_struct->data.address16.max_address_fixed = (temp8 >> 3) & 0x01;
126
127         /*
128          * Get the Type Specific Flags (Byte5)
129          */
130         buffer += 1;
131         temp8 = *buffer;
132
133         if (MEMORY_RANGE == output_struct->data.address16.resource_type) {
134                 output_struct->data.address16.attribute.memory.read_write_attribute =
135                                 (u16) (temp8 & 0x01);
136                 output_struct->data.address16.attribute.memory.cache_attribute =
137                                 (u16) ((temp8 >> 1) & 0x0F);
138         }
139
140         else {
141                 if (IO_RANGE == output_struct->data.address16.resource_type) {
142                         output_struct->data.address16.attribute.io.range_attribute =
143                                 (u16) (temp8 & 0x03);
144                 }
145
146                 else {
147                         /* BUS_NUMBER_RANGE == Address32_data->Resource_type */
148                         /* Nothing needs to be filled in */
149                 }
150         }
151
152         /*
153          * Get Granularity (Bytes 6-7)
154          */
155         buffer += 1;
156         MOVE_UNALIGNED16_TO_16 (&output_struct->data.address16.granularity,
157                          buffer);
158
159         /*
160          * Get Min_address_range (Bytes 8-9)
161          */
162         buffer += 2;
163         MOVE_UNALIGNED16_TO_16 (&output_struct->data.address16.min_address_range,
164                          buffer);
165
166         /*
167          * Get Max_address_range (Bytes 10-11)
168          */
169         buffer += 2;
170         MOVE_UNALIGNED16_TO_16
171                 (&output_struct->data.address16.max_address_range,
172                  buffer);
173
174         /*
175          * Get Address_translation_offset (Bytes 12-13)
176          */
177         buffer += 2;
178         MOVE_UNALIGNED16_TO_16
179                 (&output_struct->data.address16.address_translation_offset,
180                  buffer);
181
182         /*
183          * Get Address_length (Bytes 14-15)
184          */
185         buffer += 2;
186         MOVE_UNALIGNED16_TO_16
187                 (&output_struct->data.address16.address_length,
188                  buffer);
189
190         /*
191          * Resource Source Index (if present)
192          */
193         buffer += 2;
194
195         /*
196          * This will leave us pointing to the Resource Source Index
197          *  If it is present, then save it off and calculate the
198          *  pointer to where the null terminated string goes:
199          *  Each Interrupt takes 32-bits + the 5 bytes of the
200          *  stream that are default.
201          */
202         if (*bytes_consumed > 16) {
203                 /* Dereference the Index */
204
205                 temp8 = *buffer;
206                 output_struct->data.address16.resource_source_index =
207                                 (u32) temp8;
208
209                 /* Point to the String */
210
211                 buffer += 1;
212
213                 /* Copy the string into the buffer */
214
215                 index = 0;
216
217                 while (0x00 != *buffer) {
218                         output_struct->data.address16.resource_source[index] =
219                                 *buffer;
220
221                         buffer += 1;
222                         index += 1;
223                 }
224
225                 /*
226                  * Add the terminating null
227                  */
228                 output_struct->data.address16.resource_source[index] = 0x00;
229
230                 output_struct->data.address16.resource_source_string_length =
231                                 index + 1;
232
233                 /*
234                  * In order for the Struct_size to fall on a 32-bit boundry,
235                  *  calculate the length of the string and expand the
236                  *  Struct_size to the next 32-bit boundry.
237                  */
238                 temp8 = (u8) (index + 1);
239                 struct_size += ROUND_UP_TO_32_bITS (temp8);
240                 output_struct->length = struct_size;
241         }
242         else {
243                 output_struct->data.address16.resource_source_index = 0x00;
244                 output_struct->data.address16.resource_source_string_length = 0;
245                 output_struct->data.address16.resource_source[0] = 0x00;
246         }
247
248         /*
249          * Return the final size of the structure
250          */
251         *structure_size = struct_size;
252
253         return (AE_OK);
254 }
255
256
257 /*******************************************************************************
258  *
259  * FUNCTION:    Acpi_rs_address16_stream
260  *
261  * PARAMETERS:  Linked_list             - Pointer to the resource linked list
262  *              Output_buffer           - Pointer to the user's return buffer
263  *              Bytes_consumed          - u32 pointer that is filled with
264  *                                          the number of bytes of the
265  *                                          Output_buffer used
266  *
267  * RETURN:      Status  AE_OK if okay, else a valid ACPI_STATUS code
268  *
269  * DESCRIPTION: Take the linked list resource structure and fills in the
270  *                  the appropriate bytes in a byte stream
271  *
272  ******************************************************************************/
273
274 ACPI_STATUS
275 acpi_rs_address16_stream (
276         RESOURCE                *linked_list,
277         u8                      **output_buffer,
278         u32                     *bytes_consumed)
279 {
280         u8                      *buffer = *output_buffer;
281         u8                      *length_field;
282         u8                      temp8;
283         NATIVE_CHAR             *temp_pointer = NULL;
284         u32                     actual_bytes;
285
286
287         /*
288          * The descriptor field is static
289          */
290         *buffer = 0x88;
291         buffer += 1;
292
293         /*
294          * Save a pointer to the Length field - to be filled in later
295          */
296         length_field = buffer;
297         buffer += 2;
298
299         /*
300          * Set the Resource Type (Memory, Io, Bus_number)
301          */
302         temp8 = (u8) (linked_list->data.address16.resource_type & 0x03);
303         *buffer = temp8;
304         buffer += 1;
305
306         /*
307          * Set the general flags
308          */
309         temp8 = (u8) (linked_list->data.address16.producer_consumer & 0x01);
310
311         temp8 |= (linked_list->data.address16.decode & 0x01) << 1;
312         temp8 |= (linked_list->data.address16.min_address_fixed & 0x01) << 2;
313         temp8 |= (linked_list->data.address16.max_address_fixed & 0x01) << 3;
314
315         *buffer = temp8;
316         buffer += 1;
317
318         /*
319          * Set the type specific flags
320          */
321         temp8 = 0;
322
323         if (MEMORY_RANGE == linked_list->data.address16.resource_type) {
324                 temp8 = (u8)
325                         (linked_list->data.address16.attribute.memory.read_write_attribute &
326                          0x01);
327
328                 temp8 |=
329                         (linked_list->data.address16.attribute.memory.cache_attribute &
330                          0x0F) << 1;
331         }
332
333         else if (IO_RANGE == linked_list->data.address16.resource_type) {
334                 temp8 = (u8)
335                         (linked_list->data.address16.attribute.io.range_attribute &
336                          0x03);
337         }
338
339         *buffer = temp8;
340         buffer += 1;
341
342         /*
343          * Set the address space granularity
344          */
345         MOVE_UNALIGNED16_TO_16 (buffer,
346                          &linked_list->data.address16.granularity);
347         buffer += 2;
348
349         /*
350          * Set the address range minimum
351          */
352         MOVE_UNALIGNED16_TO_16 (buffer,
353                          &linked_list->data.address16.min_address_range);
354         buffer += 2;
355
356         /*
357          * Set the address range maximum
358          */
359         MOVE_UNALIGNED16_TO_16 (buffer,
360                          &linked_list->data.address16.max_address_range);
361         buffer += 2;
362
363         /*
364          * Set the address translation offset
365          */
366         MOVE_UNALIGNED16_TO_16 (buffer,
367                           &linked_list->data.address16.address_translation_offset);
368         buffer += 2;
369
370         /*
371          * Set the address length
372          */
373         MOVE_UNALIGNED16_TO_16 (buffer,
374                          &linked_list->data.address16.address_length);
375         buffer += 2;
376
377         /*
378          * Resource Source Index and Resource Source are optional
379          */
380         if (0 != linked_list->data.address16.resource_source_string_length) {
381                 temp8 = (u8) linked_list->data.address16.resource_source_index;
382
383                 *buffer = temp8;
384                 buffer += 1;
385
386                 temp_pointer = (NATIVE_CHAR *) buffer;
387
388                 /*
389                  * Copy the string
390                  */
391                 STRCPY (temp_pointer, linked_list->data.address16.resource_source);
392
393                 /*
394                  * Buffer needs to be set to the length of the sting + one for the
395                  *  terminating null
396                  */
397                 buffer += (STRLEN (linked_list->data.address16.resource_source) + 1);
398         }
399
400         /*
401          * Return the number of bytes consumed in this operation
402          */
403         actual_bytes = (u32) ((NATIVE_UINT) buffer -
404                            (NATIVE_UINT) *output_buffer);
405
406         *bytes_consumed = actual_bytes;
407
408         /*
409          * Set the length field to the number of bytes consumed
410          * minus the header size (3 bytes)
411          */
412         actual_bytes -= 3;
413         MOVE_UNALIGNED16_TO_16 (length_field, &actual_bytes);
414
415         return (AE_OK);
416 }
417
418
419 /*******************************************************************************
420  *
421  * FUNCTION:    Acpi_rs_address32_resource
422  *
423  * PARAMETERS:  Byte_stream_buffer      - Pointer to the resource input byte
424  *                                          stream
425  *              Bytes_consumed          - u32 pointer that is filled with
426  *                                          the number of bytes consumed from
427  *                                          the Byte_stream_buffer
428  *              Output_buffer           - Pointer to the user's return buffer
429  *              Structure_size          - u32 pointer that is filled with
430  *                                          the number of bytes in the filled
431  *                                          in structure
432  *
433  * RETURN:      Status  AE_OK if okay, else a valid ACPI_STATUS code
434  *
435  * DESCRIPTION: Take the resource byte stream and fill out the appropriate
436  *                  structure pointed to by the Output_buffer. Return the
437  *                  number of bytes consumed from the byte stream.
438  *
439  ******************************************************************************/
440
441 ACPI_STATUS
442 acpi_rs_address32_resource (
443         u8                      *byte_stream_buffer,
444         u32                     *bytes_consumed,
445         u8                      **output_buffer,
446         u32                     *structure_size)
447 {
448         u8                      *buffer;
449         RESOURCE                *output_struct;
450         u16                     temp16;
451         u8                      temp8;
452         u32                     struct_size;
453         u32                     index;
454
455
456         buffer = byte_stream_buffer;
457
458         output_struct = (RESOURCE *) *output_buffer;
459
460         struct_size = sizeof (ADDRESS32_RESOURCE) +
461                           RESOURCE_LENGTH_NO_DATA;
462
463         /*
464          * Point past the Descriptor to get the number of bytes consumed
465          */
466         buffer += 1;
467         MOVE_UNALIGNED16_TO_16 (&temp16, buffer);
468
469         *bytes_consumed = temp16 + 3;
470
471         output_struct->id = address32;
472
473         /*
474          * Get the Resource Type (Byte3)
475          */
476         buffer += 2;
477         temp8 = *buffer;
478
479         /* Values 0-2 are valid */
480         if(temp8 > 2) {
481                 return (AE_AML_ERROR);
482         }
483
484         output_struct->data.address32.resource_type = temp8 & 0x03;
485
486         /*
487          * Get the General Flags (Byte4)
488          */
489         buffer += 1;
490         temp8 = *buffer;
491
492         /*
493          * Producer / Consumer
494          */
495         output_struct->data.address32.producer_consumer = temp8 & 0x01;
496
497         /*
498          * Decode
499          */
500         output_struct->data.address32.decode = (temp8 >> 1) & 0x01;
501
502         /*
503          * Min Address Fixed
504          */
505         output_struct->data.address32.min_address_fixed = (temp8 >> 2) & 0x01;
506
507         /*
508          * Max Address Fixed
509          */
510         output_struct->data.address32.max_address_fixed = (temp8 >> 3) & 0x01;
511
512         /*
513          * Get the Type Specific Flags (Byte5)
514          */
515         buffer += 1;
516         temp8 = *buffer;
517
518         if (MEMORY_RANGE == output_struct->data.address32.resource_type) {
519                 output_struct->data.address32.attribute.memory.read_write_attribute =
520                                 (u16) (temp8 & 0x01);
521
522                 output_struct->data.address32.attribute.memory.cache_attribute =
523                                 (u16) ((temp8 >> 1) & 0x0F);
524         }
525
526         else {
527                 if (IO_RANGE == output_struct->data.address32.resource_type) {
528                         output_struct->data.address32.attribute.io.range_attribute =
529                                 (u16) (temp8 & 0x03);
530                 }
531
532                 else {
533                         /* BUS_NUMBER_RANGE == Output_struct->Data.Address32.Resource_type */
534                         /* Nothing needs to be filled in */
535                 }
536         }
537
538         /*
539          * Get Granularity (Bytes 6-9)
540          */
541         buffer += 1;
542         MOVE_UNALIGNED32_TO_32 (&output_struct->data.address32.granularity,
543                          buffer);
544
545         /*
546          * Get Min_address_range (Bytes 10-13)
547          */
548         buffer += 4;
549         MOVE_UNALIGNED32_TO_32 (&output_struct->data.address32.min_address_range,
550                          buffer);
551
552         /*
553          * Get Max_address_range (Bytes 14-17)
554          */
555         buffer += 4;
556         MOVE_UNALIGNED32_TO_32 (&output_struct->data.address32.max_address_range,
557                          buffer);
558
559         /*
560          * Get Address_translation_offset (Bytes 18-21)
561          */
562         buffer += 4;
563         MOVE_UNALIGNED32_TO_32
564                          (&output_struct->data.address32.address_translation_offset,
565                                  buffer);
566
567         /*
568          * Get Address_length (Bytes 22-25)
569          */
570         buffer += 4;
571         MOVE_UNALIGNED32_TO_32 (&output_struct->data.address32.address_length,
572                          buffer);
573
574         /*
575          * Resource Source Index (if present)
576          */
577         buffer += 4;
578
579         /*
580          * This will leave us pointing to the Resource Source Index
581          *  If it is present, then save it off and calculate the
582          *  pointer to where the null terminated string goes:
583          *  Each Interrupt takes 32-bits + the 5 bytes of the
584          *  stream that are default.
585          */
586         if (*bytes_consumed > 26) {
587                 /* Dereference the Index */
588
589                 temp8 = *buffer;
590                 output_struct->data.address32.resource_source_index = (u32)temp8;
591
592                 /* Point to the String */
593
594                 buffer += 1;
595
596                 /* Copy the string into the buffer */
597
598                 index = 0;
599
600                 while (0x00 != *buffer) {
601                         output_struct->data.address32.resource_source[index] = *buffer;
602                         buffer += 1;
603                         index += 1;
604                 }
605
606                 /*
607                  * Add the terminating null
608                  */
609                 output_struct->data.address32.resource_source[index] = 0x00;
610
611                 output_struct->data.address32.resource_source_string_length = index + 1;
612
613                 /*
614                  * In order for the Struct_size to fall on a 32-bit boundry,
615                  *  calculate the length of the string and expand the
616                  *  Struct_size to the next 32-bit boundry.
617                  */
618                 temp8 = (u8) (index + 1);
619                 struct_size += ROUND_UP_TO_32_bITS (temp8);
620         }
621
622         else {
623                 output_struct->data.address32.resource_source_index = 0x00;
624                 output_struct->data.address32.resource_source_string_length = 0;
625                 output_struct->data.address32.resource_source[0] = 0x00;
626         }
627
628         /*
629          * Set the Length parameter
630          */
631         output_struct->length = struct_size;
632
633         /*
634          * Return the final size of the structure
635          */
636         *structure_size = struct_size;
637
638         return (AE_OK);
639 }
640
641
642 /*******************************************************************************
643  *
644  * FUNCTION:    Acpi_rs_address32_stream
645  *
646  * PARAMETERS:  Linked_list             - Pointer to the resource linked list
647  *              Output_buffer           - Pointer to the user's return buffer
648  *              Bytes_consumed          - u32 pointer that is filled with
649  *                                          the number of bytes of the
650  *                                          Output_buffer used
651  *
652  * RETURN:      Status  AE_OK if okay, else a valid ACPI_STATUS code
653  *
654  * DESCRIPTION: Take the linked list resource structure and fills in the
655  *                  the appropriate bytes in a byte stream
656  *
657  ******************************************************************************/
658
659 ACPI_STATUS
660 acpi_rs_address32_stream (
661         RESOURCE                *linked_list,
662         u8                      **output_buffer,
663         u32                     *bytes_consumed)
664 {
665         u8                      *buffer;
666         u16                     *length_field;
667         u8                      temp8;
668         NATIVE_CHAR             *temp_pointer;
669
670
671         buffer = *output_buffer;
672
673         /*
674          * The descriptor field is static
675          */
676         *buffer = 0x87;
677         buffer += 1;
678
679         /*
680          * Set a pointer to the Length field - to be filled in later
681          */
682
683         length_field = (u16 *)buffer;
684         buffer += 2;
685
686         /*
687          * Set the Resource Type (Memory, Io, Bus_number)
688          */
689         temp8 = (u8) (linked_list->data.address32.resource_type & 0x03);
690
691         *buffer = temp8;
692         buffer += 1;
693
694         /*
695          * Set the general flags
696          */
697         temp8 = (u8) (linked_list->data.address32.producer_consumer & 0x01);
698         temp8 |= (linked_list->data.address32.decode & 0x01) << 1;
699         temp8 |= (linked_list->data.address32.min_address_fixed & 0x01) << 2;
700         temp8 |= (linked_list->data.address32.max_address_fixed & 0x01) << 3;
701
702         *buffer = temp8;
703         buffer += 1;
704
705         /*
706          * Set the type specific flags
707          */
708         temp8 = 0;
709
710         if(MEMORY_RANGE == linked_list->data.address32.resource_type) {
711                 temp8 = (u8)
712                         (linked_list->data.address32.attribute.memory.read_write_attribute &
713                         0x01);
714
715                 temp8 |=
716                         (linked_list->data.address32.attribute.memory.cache_attribute &
717                          0x0F) << 1;
718         }
719
720         else if (IO_RANGE == linked_list->data.address32.resource_type) {
721                 temp8 = (u8)
722                         (linked_list->data.address32.attribute.io.range_attribute &
723                          0x03);
724         }
725
726         *buffer = temp8;
727         buffer += 1;
728
729         /*
730          * Set the address space granularity
731          */
732         MOVE_UNALIGNED32_TO_32 (buffer,
733                          &linked_list->data.address32.granularity);
734         buffer += 4;
735
736         /*
737          * Set the address range minimum
738          */
739         MOVE_UNALIGNED32_TO_32 (buffer,
740                          &linked_list->data.address32.min_address_range);
741         buffer += 4;
742
743         /*
744          * Set the address range maximum
745          */
746         MOVE_UNALIGNED32_TO_32 (buffer,
747                          &linked_list->data.address32.max_address_range);
748         buffer += 4;
749
750         /*
751          * Set the address translation offset
752          */
753         MOVE_UNALIGNED32_TO_32 (buffer,
754                           &linked_list->data.address32.address_translation_offset);
755         buffer += 4;
756
757         /*
758          * Set the address length
759          */
760         MOVE_UNALIGNED32_TO_32 (buffer,
761                          &linked_list->data.address32.address_length);
762         buffer += 4;
763
764         /*
765          * Resource Source Index and Resource Source are optional
766          */
767         if (0 != linked_list->data.address32.resource_source_string_length) {
768                 temp8 = (u8) linked_list->data.address32.resource_source_index;
769
770                 *buffer = temp8;
771                 buffer += 1;
772
773                 temp_pointer = (NATIVE_CHAR *) buffer;
774
775                 /*
776                  * Copy the string
777                  */
778                 STRCPY (temp_pointer, linked_list->data.address32.resource_source);
779
780                 /*
781                  * Buffer needs to be set to the length of the sting + one for the
782                  *  terminating null
783                  */
784                 buffer += (STRLEN (linked_list->data.address32.resource_source) + 1);
785         }
786
787         /*
788          * Return the number of bytes consumed in this operation
789          */
790         *bytes_consumed = (u32) ((NATIVE_UINT) buffer -
791                            (NATIVE_UINT) *output_buffer);
792
793         /*
794          * Set the length field to the number of bytes consumed
795          *  minus the header size (3 bytes)
796          */
797         *length_field = (u16) (*bytes_consumed - 3);
798
799         return (AE_OK);
800 }
801