Merge branch 'origin'
[pandora-kernel.git] / drivers / acpi / resources / rsutils.c
1 /*******************************************************************************
2  *
3  * Module Name: rsutils - Utilities for the resource manager
4  *
5  ******************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2006, R. Byron Moore
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43
44 #include <acpi/acpi.h>
45 #include <acpi/acnamesp.h>
46 #include <acpi/acresrc.h>
47
48 #define _COMPONENT          ACPI_RESOURCES
49 ACPI_MODULE_NAME("rsutils")
50
51 /*******************************************************************************
52  *
53  * FUNCTION:    acpi_rs_decode_bitmask
54  *
55  * PARAMETERS:  Mask            - Bitmask to decode
56  *              List            - Where the converted list is returned
57  *
58  * RETURN:      Count of bits set (length of list)
59  *
60  * DESCRIPTION: Convert a bit mask into a list of values
61  *
62  ******************************************************************************/
63 u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
64 {
65         acpi_native_uint i;
66         u8 bit_count;
67
68         ACPI_FUNCTION_ENTRY();
69
70         /* Decode the mask bits */
71
72         for (i = 0, bit_count = 0; mask; i++) {
73                 if (mask & 0x0001) {
74                         list[bit_count] = (u8) i;
75                         bit_count++;
76                 }
77
78                 mask >>= 1;
79         }
80
81         return (bit_count);
82 }
83
84 /*******************************************************************************
85  *
86  * FUNCTION:    acpi_rs_encode_bitmask
87  *
88  * PARAMETERS:  List            - List of values to encode
89  *              Count           - Length of list
90  *
91  * RETURN:      Encoded bitmask
92  *
93  * DESCRIPTION: Convert a list of values to an encoded bitmask
94  *
95  ******************************************************************************/
96
97 u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
98 {
99         acpi_native_uint i;
100         u16 mask;
101
102         ACPI_FUNCTION_ENTRY();
103
104         /* Encode the list into a single bitmask */
105
106         for (i = 0, mask = 0; i < count; i++) {
107                 mask |= (0x0001 << list[i]);
108         }
109
110         return (mask);
111 }
112
113 /*******************************************************************************
114  *
115  * FUNCTION:    acpi_rs_move_data
116  *
117  * PARAMETERS:  Destination         - Pointer to the destination descriptor
118  *              Source              - Pointer to the source descriptor
119  *              item_count          - How many items to move
120  *              move_type           - Byte width
121  *
122  * RETURN:      None
123  *
124  * DESCRIPTION: Move multiple data items from one descriptor to another. Handles
125  *              alignment issues and endian issues if necessary, as configured
126  *              via the ACPI_MOVE_* macros. (This is why a memcpy is not used)
127  *
128  ******************************************************************************/
129
130 void
131 acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
132 {
133         acpi_native_uint i;
134
135         ACPI_FUNCTION_ENTRY();
136
137         /* One move per item */
138
139         for (i = 0; i < item_count; i++) {
140                 switch (move_type) {
141                         /*
142                          * For the 8-bit case, we can perform the move all at once
143                          * since there are no alignment or endian issues
144                          */
145                 case ACPI_RSC_MOVE8:
146                         ACPI_MEMCPY(destination, source, item_count);
147                         return;
148
149                         /*
150                          * 16-, 32-, and 64-bit cases must use the move macros that perform
151                          * endian conversion and/or accomodate hardware that cannot perform
152                          * misaligned memory transfers
153                          */
154                 case ACPI_RSC_MOVE16:
155                         ACPI_MOVE_16_TO_16(&ACPI_CAST_PTR(u16, destination)[i],
156                                            &ACPI_CAST_PTR(u16, source)[i]);
157                         break;
158
159                 case ACPI_RSC_MOVE32:
160                         ACPI_MOVE_32_TO_32(&ACPI_CAST_PTR(u32, destination)[i],
161                                            &ACPI_CAST_PTR(u32, source)[i]);
162                         break;
163
164                 case ACPI_RSC_MOVE64:
165                         ACPI_MOVE_64_TO_64(&ACPI_CAST_PTR(u64, destination)[i],
166                                            &ACPI_CAST_PTR(u64, source)[i]);
167                         break;
168
169                 default:
170                         return;
171                 }
172         }
173 }
174
175 /*******************************************************************************
176  *
177  * FUNCTION:    acpi_rs_set_resource_length
178  *
179  * PARAMETERS:  total_length        - Length of the AML descriptor, including
180  *                                    the header and length fields.
181  *              Aml                 - Pointer to the raw AML descriptor
182  *
183  * RETURN:      None
184  *
185  * DESCRIPTION: Set the resource_length field of an AML
186  *              resource descriptor, both Large and Small descriptors are
187  *              supported automatically. Note: Descriptor Type field must
188  *              be valid.
189  *
190  ******************************************************************************/
191
192 void
193 acpi_rs_set_resource_length(acpi_rsdesc_size total_length,
194                             union aml_resource *aml)
195 {
196         acpi_rs_length resource_length;
197
198         ACPI_FUNCTION_ENTRY();
199
200         /* Length is the total descriptor length minus the header length */
201
202         resource_length = (acpi_rs_length)
203             (total_length - acpi_ut_get_resource_header_length(aml));
204
205         /* Length is stored differently for large and small descriptors */
206
207         if (aml->small_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) {
208                 /* Large descriptor -- bytes 1-2 contain the 16-bit length */
209
210                 ACPI_MOVE_16_TO_16(&aml->large_header.resource_length,
211                                    &resource_length);
212         } else {
213                 /* Small descriptor -- bits 2:0 of byte 0 contain the length */
214
215                 aml->small_header.descriptor_type = (u8)
216
217                     /* Clear any existing length, preserving descriptor type bits */
218                     ((aml->small_header.
219                       descriptor_type & ~ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK)
220
221                      | resource_length);
222         }
223 }
224
225 /*******************************************************************************
226  *
227  * FUNCTION:    acpi_rs_set_resource_header
228  *
229  * PARAMETERS:  descriptor_type     - Byte to be inserted as the type
230  *              total_length        - Length of the AML descriptor, including
231  *                                    the header and length fields.
232  *              Aml                 - Pointer to the raw AML descriptor
233  *
234  * RETURN:      None
235  *
236  * DESCRIPTION: Set the descriptor_type and resource_length fields of an AML
237  *              resource descriptor, both Large and Small descriptors are
238  *              supported automatically
239  *
240  ******************************************************************************/
241
242 void
243 acpi_rs_set_resource_header(u8 descriptor_type,
244                             acpi_rsdesc_size total_length,
245                             union aml_resource *aml)
246 {
247         ACPI_FUNCTION_ENTRY();
248
249         /* Set the Resource Type */
250
251         aml->small_header.descriptor_type = descriptor_type;
252
253         /* Set the Resource Length */
254
255         acpi_rs_set_resource_length(total_length, aml);
256 }
257
258 /*******************************************************************************
259  *
260  * FUNCTION:    acpi_rs_strcpy
261  *
262  * PARAMETERS:  Destination         - Pointer to the destination string
263  *              Source              - Pointer to the source string
264  *
265  * RETURN:      String length, including NULL terminator
266  *
267  * DESCRIPTION: Local string copy that returns the string length, saving a
268  *              strcpy followed by a strlen.
269  *
270  ******************************************************************************/
271
272 static u16 acpi_rs_strcpy(char *destination, char *source)
273 {
274         u16 i;
275
276         ACPI_FUNCTION_ENTRY();
277
278         for (i = 0; source[i]; i++) {
279                 destination[i] = source[i];
280         }
281
282         destination[i] = 0;
283
284         /* Return string length including the NULL terminator */
285
286         return ((u16) (i + 1));
287 }
288
289 /*******************************************************************************
290  *
291  * FUNCTION:    acpi_rs_get_resource_source
292  *
293  * PARAMETERS:  resource_length     - Length field of the descriptor
294  *              minimum_length      - Minimum length of the descriptor (minus
295  *                                    any optional fields)
296  *              resource_source     - Where the resource_source is returned
297  *              Aml                 - Pointer to the raw AML descriptor
298  *              string_ptr          - (optional) where to store the actual
299  *                                    resource_source string
300  *
301  * RETURN:      Length of the string plus NULL terminator, rounded up to 32 bit
302  *
303  * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor
304  *              to an internal resource descriptor
305  *
306  ******************************************************************************/
307
308 acpi_rs_length
309 acpi_rs_get_resource_source(acpi_rs_length resource_length,
310                             acpi_rs_length minimum_length,
311                             struct acpi_resource_source * resource_source,
312                             union aml_resource * aml, char *string_ptr)
313 {
314         acpi_rsdesc_size total_length;
315         u8 *aml_resource_source;
316
317         ACPI_FUNCTION_ENTRY();
318
319         total_length =
320             resource_length + sizeof(struct aml_resource_large_header);
321         aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length);
322
323         /*
324          * resource_source is present if the length of the descriptor is longer than
325          * the minimum length.
326          *
327          * Note: Some resource descriptors will have an additional null, so
328          * we add 1 to the minimum length.
329          */
330         if (total_length > (acpi_rsdesc_size) (minimum_length + 1)) {
331                 /* Get the resource_source_index */
332
333                 resource_source->index = aml_resource_source[0];
334
335                 resource_source->string_ptr = string_ptr;
336                 if (!string_ptr) {
337                         /*
338                          * String destination pointer is not specified; Set the String
339                          * pointer to the end of the current resource_source structure.
340                          */
341                         resource_source->string_ptr =
342                             ACPI_ADD_PTR(char, resource_source,
343                                          sizeof(struct acpi_resource_source));
344                 }
345
346                 /*
347                  * In order for the struct_size to fall on a 32-bit boundary, calculate
348                  * the length of the string (+1 for the NULL terminator) and expand the
349                  * struct_size to the next 32-bit boundary.
350                  *
351                  * Zero the entire area of the buffer.
352                  */
353                 total_length =
354                     ACPI_ROUND_UP_to_32_bITS(ACPI_STRLEN
355                                              ((char *)&aml_resource_source[1]) +
356                                              1);
357                 ACPI_MEMSET(resource_source->string_ptr, 0, total_length);
358
359                 /* Copy the resource_source string to the destination */
360
361                 resource_source->string_length =
362                     acpi_rs_strcpy(resource_source->string_ptr,
363                                    (char *)&aml_resource_source[1]);
364
365                 return ((acpi_rs_length) total_length);
366         }
367
368         /* resource_source is not present */
369
370         resource_source->index = 0;
371         resource_source->string_length = 0;
372         resource_source->string_ptr = NULL;
373         return (0);
374 }
375
376 /*******************************************************************************
377  *
378  * FUNCTION:    acpi_rs_set_resource_source
379  *
380  * PARAMETERS:  Aml                 - Pointer to the raw AML descriptor
381  *              minimum_length      - Minimum length of the descriptor (minus
382  *                                    any optional fields)
383  *              resource_source     - Internal resource_source
384
385  *
386  * RETURN:      Total length of the AML descriptor
387  *
388  * DESCRIPTION: Convert an optional resource_source from internal format to a
389  *              raw AML resource descriptor
390  *
391  ******************************************************************************/
392
393 acpi_rsdesc_size
394 acpi_rs_set_resource_source(union aml_resource * aml,
395                             acpi_rs_length minimum_length,
396                             struct acpi_resource_source * resource_source)
397 {
398         u8 *aml_resource_source;
399         acpi_rsdesc_size descriptor_length;
400
401         ACPI_FUNCTION_ENTRY();
402
403         descriptor_length = minimum_length;
404
405         /* Non-zero string length indicates presence of a resource_source */
406
407         if (resource_source->string_length) {
408                 /* Point to the end of the AML descriptor */
409
410                 aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length);
411
412                 /* Copy the resource_source_index */
413
414                 aml_resource_source[0] = (u8) resource_source->index;
415
416                 /* Copy the resource_source string */
417
418                 ACPI_STRCPY((char *)&aml_resource_source[1],
419                             resource_source->string_ptr);
420
421                 /*
422                  * Add the length of the string (+ 1 for null terminator) to the
423                  * final descriptor length
424                  */
425                 descriptor_length +=
426                     ((acpi_rsdesc_size) resource_source->string_length + 1);
427         }
428
429         /* Return the new total length of the AML descriptor */
430
431         return (descriptor_length);
432 }
433
434 /*******************************************************************************
435  *
436  * FUNCTION:    acpi_rs_get_prt_method_data
437  *
438  * PARAMETERS:  Handle          - a handle to the containing object
439  *              ret_buffer      - a pointer to a buffer structure for the
440  *                                  results
441  *
442  * RETURN:      Status
443  *
444  * DESCRIPTION: This function is called to get the _PRT value of an object
445  *              contained in an object specified by the handle passed in
446  *
447  *              If the function fails an appropriate status will be returned
448  *              and the contents of the callers buffer is undefined.
449  *
450  ******************************************************************************/
451
452 acpi_status
453 acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer)
454 {
455         union acpi_operand_object *obj_desc;
456         acpi_status status;
457
458         ACPI_FUNCTION_TRACE("rs_get_prt_method_data");
459
460         /* Parameters guaranteed valid by caller */
461
462         /* Execute the method, no parameters */
463
464         status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRT,
465                                          ACPI_BTYPE_PACKAGE, &obj_desc);
466         if (ACPI_FAILURE(status)) {
467                 return_ACPI_STATUS(status);
468         }
469
470         /*
471          * Create a resource linked list from the byte stream buffer that comes
472          * back from the _CRS method execution.
473          */
474         status = acpi_rs_create_pci_routing_table(obj_desc, ret_buffer);
475
476         /* On exit, we must delete the object returned by evaluate_object */
477
478         acpi_ut_remove_reference(obj_desc);
479         return_ACPI_STATUS(status);
480 }
481
482 /*******************************************************************************
483  *
484  * FUNCTION:    acpi_rs_get_crs_method_data
485  *
486  * PARAMETERS:  Handle          - a handle to the containing object
487  *              ret_buffer      - a pointer to a buffer structure for the
488  *                                  results
489  *
490  * RETURN:      Status
491  *
492  * DESCRIPTION: This function is called to get the _CRS value of an object
493  *              contained in an object specified by the handle passed in
494  *
495  *              If the function fails an appropriate status will be returned
496  *              and the contents of the callers buffer is undefined.
497  *
498  ******************************************************************************/
499
500 acpi_status
501 acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
502 {
503         union acpi_operand_object *obj_desc;
504         acpi_status status;
505
506         ACPI_FUNCTION_TRACE("rs_get_crs_method_data");
507
508         /* Parameters guaranteed valid by caller */
509
510         /* Execute the method, no parameters */
511
512         status = acpi_ut_evaluate_object(handle, METHOD_NAME__CRS,
513                                          ACPI_BTYPE_BUFFER, &obj_desc);
514         if (ACPI_FAILURE(status)) {
515                 return_ACPI_STATUS(status);
516         }
517
518         /*
519          * Make the call to create a resource linked list from the
520          * byte stream buffer that comes back from the _CRS method
521          * execution.
522          */
523         status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
524
525         /* on exit, we must delete the object returned by evaluate_object */
526
527         acpi_ut_remove_reference(obj_desc);
528         return_ACPI_STATUS(status);
529 }
530
531 /*******************************************************************************
532  *
533  * FUNCTION:    acpi_rs_get_prs_method_data
534  *
535  * PARAMETERS:  Handle          - a handle to the containing object
536  *              ret_buffer      - a pointer to a buffer structure for the
537  *                                  results
538  *
539  * RETURN:      Status
540  *
541  * DESCRIPTION: This function is called to get the _PRS value of an object
542  *              contained in an object specified by the handle passed in
543  *
544  *              If the function fails an appropriate status will be returned
545  *              and the contents of the callers buffer is undefined.
546  *
547  ******************************************************************************/
548
549 #ifdef ACPI_FUTURE_USAGE
550 acpi_status
551 acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
552 {
553         union acpi_operand_object *obj_desc;
554         acpi_status status;
555
556         ACPI_FUNCTION_TRACE("rs_get_prs_method_data");
557
558         /* Parameters guaranteed valid by caller */
559
560         /* Execute the method, no parameters */
561
562         status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRS,
563                                          ACPI_BTYPE_BUFFER, &obj_desc);
564         if (ACPI_FAILURE(status)) {
565                 return_ACPI_STATUS(status);
566         }
567
568         /*
569          * Make the call to create a resource linked list from the
570          * byte stream buffer that comes back from the _CRS method
571          * execution.
572          */
573         status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
574
575         /* on exit, we must delete the object returned by evaluate_object */
576
577         acpi_ut_remove_reference(obj_desc);
578         return_ACPI_STATUS(status);
579 }
580 #endif                          /*  ACPI_FUTURE_USAGE  */
581
582 /*******************************************************************************
583  *
584  * FUNCTION:    acpi_rs_get_method_data
585  *
586  * PARAMETERS:  Handle          - a handle to the containing object
587  *              Path            - Path to method, relative to Handle
588  *              ret_buffer      - a pointer to a buffer structure for the
589  *                                  results
590  *
591  * RETURN:      Status
592  *
593  * DESCRIPTION: This function is called to get the _CRS or _PRS value of an
594  *              object contained in an object specified by the handle passed in
595  *
596  *              If the function fails an appropriate status will be returned
597  *              and the contents of the callers buffer is undefined.
598  *
599  ******************************************************************************/
600
601 acpi_status
602 acpi_rs_get_method_data(acpi_handle handle,
603                         char *path, struct acpi_buffer *ret_buffer)
604 {
605         union acpi_operand_object *obj_desc;
606         acpi_status status;
607
608         ACPI_FUNCTION_TRACE("rs_get_method_data");
609
610         /* Parameters guaranteed valid by caller */
611
612         /* Execute the method, no parameters */
613
614         status =
615             acpi_ut_evaluate_object(handle, path, ACPI_BTYPE_BUFFER, &obj_desc);
616         if (ACPI_FAILURE(status)) {
617                 return_ACPI_STATUS(status);
618         }
619
620         /*
621          * Make the call to create a resource linked list from the
622          * byte stream buffer that comes back from the method
623          * execution.
624          */
625         status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
626
627         /* On exit, we must delete the object returned by evaluate_object */
628
629         acpi_ut_remove_reference(obj_desc);
630         return_ACPI_STATUS(status);
631 }
632
633 /*******************************************************************************
634  *
635  * FUNCTION:    acpi_rs_set_srs_method_data
636  *
637  * PARAMETERS:  Handle          - a handle to the containing object
638  *              in_buffer       - a pointer to a buffer structure of the
639  *                                  parameter
640  *
641  * RETURN:      Status
642  *
643  * DESCRIPTION: This function is called to set the _SRS of an object contained
644  *              in an object specified by the handle passed in
645  *
646  *              If the function fails an appropriate status will be returned
647  *              and the contents of the callers buffer is undefined.
648  *
649  ******************************************************************************/
650
651 acpi_status
652 acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer)
653 {
654         struct acpi_parameter_info info;
655         union acpi_operand_object *params[2];
656         acpi_status status;
657         struct acpi_buffer buffer;
658
659         ACPI_FUNCTION_TRACE("rs_set_srs_method_data");
660
661         /* Parameters guaranteed valid by caller */
662
663         /*
664          * The in_buffer parameter will point to a linked list of
665          * resource parameters.  It needs to be formatted into a
666          * byte stream to be sent in as an input parameter to _SRS
667          *
668          * Convert the linked list into a byte stream
669          */
670         buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
671         status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer);
672         if (ACPI_FAILURE(status)) {
673                 return_ACPI_STATUS(status);
674         }
675
676         /* Init the param object */
677
678         params[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
679         if (!params[0]) {
680                 acpi_os_free(buffer.pointer);
681                 return_ACPI_STATUS(AE_NO_MEMORY);
682         }
683
684         /* Set up the parameter object */
685
686         params[0]->buffer.length = (u32) buffer.length;
687         params[0]->buffer.pointer = buffer.pointer;
688         params[0]->common.flags = AOPOBJ_DATA_VALID;
689         params[1] = NULL;
690
691         info.node = handle;
692         info.parameters = params;
693         info.parameter_type = ACPI_PARAM_ARGS;
694
695         /* Execute the method, no return value */
696
697         status = acpi_ns_evaluate_relative(METHOD_NAME__SRS, &info);
698         if (ACPI_SUCCESS(status)) {
699                 /* Delete any return object (especially if implicit_return is enabled) */
700
701                 if (info.return_object) {
702                         acpi_ut_remove_reference(info.return_object);
703                 }
704         }
705
706         /* Clean up and return the status from acpi_ns_evaluate_relative */
707
708         acpi_ut_remove_reference(params[0]);
709         return_ACPI_STATUS(status);
710 }