Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rsmisc.c
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * Module Name: rsmisc - Miscellaneous resource descriptors
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2012, Intel Corp.
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 "accommon.h"
46 #include "acresrc.h"
47 
48 #define _COMPONENT ACPI_RESOURCES
49 ACPI_MODULE_NAME("rsmisc")
50 #define INIT_RESOURCE_TYPE(i) i->resource_offset
51 #define INIT_RESOURCE_LENGTH(i) i->aml_offset
52 #define INIT_TABLE_LENGTH(i) i->value
53 #define COMPARE_OPCODE(i) i->resource_offset
54 #define COMPARE_TARGET(i) i->aml_offset
55 #define COMPARE_VALUE(i) i->value
56 /*******************************************************************************
57  *
58  * FUNCTION: acpi_rs_convert_aml_to_resource
59  *
60  * PARAMETERS: resource - Pointer to the resource descriptor
61  * aml - Where the AML descriptor is returned
62  * info - Pointer to appropriate conversion table
63  *
64  * RETURN: Status
65  *
66  * DESCRIPTION: Convert an external AML resource descriptor to the corresponding
67  * internal resource descriptor
68  *
69  ******************************************************************************/
72  union aml_resource *aml,
73  struct acpi_rsconvert_info *info)
74 {
75  acpi_rs_length aml_resource_length;
76  void *source;
77  void *destination;
78  char *target;
79  u8 count;
80  u8 flags_mode = FALSE;
81  u16 item_count = 0;
82  u16 temp16 = 0;
83 
84  ACPI_FUNCTION_TRACE(rs_convert_aml_to_resource);
85 
86  if (!info) {
88  }
89 
90  if (((acpi_size) resource) & 0x3) {
91 
92  /* Each internal resource struct is expected to be 32-bit aligned */
93 
95  "Misaligned resource pointer (get): %p Type 0x%2.2X Length %u",
96  resource, resource->type, resource->length));
97  }
98 
99  /* Extract the resource Length field (does not include header length) */
100 
101  aml_resource_length = acpi_ut_get_resource_length(aml);
102 
103  /*
104  * First table entry must be ACPI_RSC_INITxxx and must contain the
105  * table length (# of table entries)
106  */
107  count = INIT_TABLE_LENGTH(info);
108  while (count) {
109  /*
110  * Source is the external AML byte stream buffer,
111  * destination is the internal resource descriptor
112  */
113  source = ACPI_ADD_PTR(void, aml, info->aml_offset);
114  destination =
115  ACPI_ADD_PTR(void, resource, info->resource_offset);
116 
117  switch (info->opcode) {
118  case ACPI_RSC_INITGET:
119  /*
120  * Get the resource type and the initial (minimum) length
121  */
122  ACPI_MEMSET(resource, 0, INIT_RESOURCE_LENGTH(info));
123  resource->type = INIT_RESOURCE_TYPE(info);
124  resource->length = INIT_RESOURCE_LENGTH(info);
125  break;
126 
127  case ACPI_RSC_INITSET:
128  break;
129 
130  case ACPI_RSC_FLAGINIT:
131 
132  flags_mode = TRUE;
133  break;
134 
135  case ACPI_RSC_1BITFLAG:
136  /*
137  * Mask and shift the flag bit
138  */
139  ACPI_SET8(destination) = (u8)
140  ((ACPI_GET8(source) >> info->value) & 0x01);
141  break;
142 
143  case ACPI_RSC_2BITFLAG:
144  /*
145  * Mask and shift the flag bits
146  */
147  ACPI_SET8(destination) = (u8)
148  ((ACPI_GET8(source) >> info->value) & 0x03);
149  break;
150 
151  case ACPI_RSC_3BITFLAG:
152  /*
153  * Mask and shift the flag bits
154  */
155  ACPI_SET8(destination) = (u8)
156  ((ACPI_GET8(source) >> info->value) & 0x07);
157  break;
158 
159  case ACPI_RSC_COUNT:
160 
161  item_count = ACPI_GET8(source);
162  ACPI_SET8(destination) = (u8) item_count;
163 
164  resource->length = resource->length +
165  (info->value * (item_count - 1));
166  break;
167 
168  case ACPI_RSC_COUNT16:
169 
170  item_count = aml_resource_length;
171  ACPI_SET16(destination) = item_count;
172 
173  resource->length = resource->length +
174  (info->value * (item_count - 1));
175  break;
176 
178 
179  target = ACPI_ADD_PTR(void, aml, info->value);
180  item_count = ACPI_GET16(target) - ACPI_GET16(source);
181 
182  resource->length = resource->length + item_count;
183  item_count = item_count / 2;
184  ACPI_SET16(destination) = item_count;
185  break;
186 
188 
189  item_count = ACPI_GET8(source);
190  ACPI_SET8(destination) = (u8)item_count;
191 
192  resource->length = resource->length +
193  (info->value * item_count);
194  break;
195 
197 
198  /*
199  * Vendor data is optional (length/offset may both be zero)
200  * Examine vendor data length field first
201  */
202  target = ACPI_ADD_PTR(void, aml, (info->value + 2));
203  if (ACPI_GET16(target)) {
204 
205  /* Use vendor offset to get resource source length */
206 
207  target = ACPI_ADD_PTR(void, aml, info->value);
208  item_count =
209  ACPI_GET16(target) - ACPI_GET16(source);
210  } else {
211  /* No vendor data to worry about */
212 
213  item_count = aml->large_header.resource_length +
214  sizeof(struct aml_resource_large_header) -
215  ACPI_GET16(source);
216  }
217 
218  resource->length = resource->length + item_count;
219  ACPI_SET16(destination) = item_count;
220  break;
221 
223 
224  item_count = ACPI_GET16(source) - info->value;
225 
226  resource->length = resource->length + item_count;
227  ACPI_SET16(destination) = item_count;
228  break;
229 
231 
232  item_count = (aml_resource_length +
233  sizeof(struct aml_resource_large_header))
234  - ACPI_GET16(source) - info->value;
235 
236  resource->length = resource->length + item_count;
237  ACPI_SET16(destination) = item_count;
238  break;
239 
240  case ACPI_RSC_LENGTH:
241 
242  resource->length = resource->length + info->value;
243  break;
244 
245  case ACPI_RSC_MOVE8:
246  case ACPI_RSC_MOVE16:
247  case ACPI_RSC_MOVE32:
248  case ACPI_RSC_MOVE64:
249  /*
250  * Raw data move. Use the Info value field unless item_count has
251  * been previously initialized via a COUNT opcode
252  */
253  if (info->value) {
254  item_count = info->value;
255  }
256  acpi_rs_move_data(destination, source, item_count,
257  info->opcode);
258  break;
259 
261 
262  /* Generate and set the PIN data pointer */
263 
264  target = (char *)ACPI_ADD_PTR(void, resource,
265  (resource->length -
266  item_count * 2));
267  *(u16 **)destination = ACPI_CAST_PTR(u16, target);
268 
269  /* Copy the PIN data */
270 
271  source = ACPI_ADD_PTR(void, aml, ACPI_GET16(source));
272  acpi_rs_move_data(target, source, item_count,
273  info->opcode);
274  break;
275 
277 
278  /* Generate and set the resource_source string pointer */
279 
280  target = (char *)ACPI_ADD_PTR(void, resource,
281  (resource->length -
282  item_count));
283  *(u8 **)destination = ACPI_CAST_PTR(u8, target);
284 
285  /* Copy the resource_source string */
286 
287  source = ACPI_ADD_PTR(void, aml, ACPI_GET16(source));
288  acpi_rs_move_data(target, source, item_count,
289  info->opcode);
290  break;
291 
293 
294  /* Generate and set the Vendor Data pointer */
295 
296  target = (char *)ACPI_ADD_PTR(void, resource,
297  (resource->length -
298  item_count));
299  *(u8 **)destination = ACPI_CAST_PTR(u8, target);
300 
301  /* Copy the Vendor Data */
302 
303  source = ACPI_ADD_PTR(void, aml, info->value);
304  acpi_rs_move_data(target, source, item_count,
305  info->opcode);
306  break;
307 
309 
310  /* Generate and set the resource_source string pointer */
311 
312  target = (char *)ACPI_ADD_PTR(void, resource,
313  (resource->length -
314  item_count));
315  *(u8 **)destination = ACPI_CAST_PTR(u8, target);
316 
317  /* Copy the resource_source string */
318 
319  source =
320  ACPI_ADD_PTR(void, aml,
321  (ACPI_GET16(source) + info->value));
322  acpi_rs_move_data(target, source, item_count,
323  info->opcode);
324  break;
325 
326  case ACPI_RSC_SET8:
327 
328  ACPI_MEMSET(destination, info->aml_offset, info->value);
329  break;
330 
331  case ACPI_RSC_DATA8:
332 
333  target = ACPI_ADD_PTR(char, resource, info->value);
334  ACPI_MEMCPY(destination, source, ACPI_GET16(target));
335  break;
336 
337  case ACPI_RSC_ADDRESS:
338  /*
339  * Common handler for address descriptor flags
340  */
341  if (!acpi_rs_get_address_common(resource, aml)) {
344  }
345  break;
346 
347  case ACPI_RSC_SOURCE:
348  /*
349  * Optional resource_source (Index and String)
350  */
351  resource->length +=
352  acpi_rs_get_resource_source(aml_resource_length,
353  info->value,
354  destination, aml, NULL);
355  break;
356 
357  case ACPI_RSC_SOURCEX:
358  /*
359  * Optional resource_source (Index and String). This is the more
360  * complicated case used by the Interrupt() macro
361  */
362  target = ACPI_ADD_PTR(char, resource,
363  info->aml_offset +
364  (item_count * 4));
365 
366  resource->length +=
367  acpi_rs_get_resource_source(aml_resource_length,
369  (((item_count -
370  1) * sizeof(u32)) +
371  info->value),
372  destination, aml,
373  target);
374  break;
375 
376  case ACPI_RSC_BITMASK:
377  /*
378  * 8-bit encoded bitmask (DMA macro)
379  */
380  item_count =
382  destination);
383  if (item_count) {
384  resource->length += (item_count - 1);
385  }
386 
387  target = ACPI_ADD_PTR(char, resource, info->value);
388  ACPI_SET8(target) = (u8) item_count;
389  break;
390 
391  case ACPI_RSC_BITMASK16:
392  /*
393  * 16-bit encoded bitmask (IRQ macro)
394  */
395  ACPI_MOVE_16_TO_16(&temp16, source);
396 
397  item_count =
398  acpi_rs_decode_bitmask(temp16, destination);
399  if (item_count) {
400  resource->length += (item_count - 1);
401  }
402 
403  target = ACPI_ADD_PTR(char, resource, info->value);
404  ACPI_SET8(target) = (u8) item_count;
405  break;
406 
407  case ACPI_RSC_EXIT_NE:
408  /*
409  * control - Exit conversion if not equal
410  */
411  switch (info->resource_offset) {
413  if (aml_resource_length != info->value) {
414  goto exit;
415  }
416  break;
417 
419  if (ACPI_GET8(source) != info->value) {
420  goto exit;
421  }
422  break;
423 
424  default:
425 
427  "Invalid conversion sub-opcode"));
429  }
430  break;
431 
432  default:
433 
434  ACPI_ERROR((AE_INFO, "Invalid conversion opcode"));
436  }
437 
438  count--;
439  info++;
440  }
441 
442  exit:
443  if (!flags_mode) {
444 
445  /* Round the resource struct length up to the next boundary (32 or 64) */
446 
447  resource->length =
448  (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(resource->length);
449  }
451 }
452 
453 /*******************************************************************************
454  *
455  * FUNCTION: acpi_rs_convert_resource_to_aml
456  *
457  * PARAMETERS: resource - Pointer to the resource descriptor
458  * aml - Where the AML descriptor is returned
459  * info - Pointer to appropriate conversion table
460  *
461  * RETURN: Status
462  *
463  * DESCRIPTION: Convert an internal resource descriptor to the corresponding
464  * external AML resource descriptor.
465  *
466  ******************************************************************************/
467 
470  union aml_resource *aml,
471  struct acpi_rsconvert_info *info)
472 {
473  void *source = NULL;
474  void *destination;
475  char *target;
476  acpi_rsdesc_size aml_length = 0;
477  u8 count;
478  u16 temp16 = 0;
479  u16 item_count = 0;
480 
481  ACPI_FUNCTION_TRACE(rs_convert_resource_to_aml);
482 
483  if (!info) {
485  }
486 
487  /*
488  * First table entry must be ACPI_RSC_INITxxx and must contain the
489  * table length (# of table entries)
490  */
491  count = INIT_TABLE_LENGTH(info);
492 
493  while (count) {
494  /*
495  * Source is the internal resource descriptor,
496  * destination is the external AML byte stream buffer
497  */
498  source = ACPI_ADD_PTR(void, resource, info->resource_offset);
499  destination = ACPI_ADD_PTR(void, aml, info->aml_offset);
500 
501  switch (info->opcode) {
502  case ACPI_RSC_INITSET:
503 
504  ACPI_MEMSET(aml, 0, INIT_RESOURCE_LENGTH(info));
505  aml_length = INIT_RESOURCE_LENGTH(info);
507  aml_length, aml);
508  break;
509 
510  case ACPI_RSC_INITGET:
511  break;
512 
513  case ACPI_RSC_FLAGINIT:
514  /*
515  * Clear the flag byte
516  */
517  ACPI_SET8(destination) = 0;
518  break;
519 
520  case ACPI_RSC_1BITFLAG:
521  /*
522  * Mask and shift the flag bit
523  */
524  ACPI_SET8(destination) |= (u8)
525  ((ACPI_GET8(source) & 0x01) << info->value);
526  break;
527 
528  case ACPI_RSC_2BITFLAG:
529  /*
530  * Mask and shift the flag bits
531  */
532  ACPI_SET8(destination) |= (u8)
533  ((ACPI_GET8(source) & 0x03) << info->value);
534  break;
535 
536  case ACPI_RSC_3BITFLAG:
537  /*
538  * Mask and shift the flag bits
539  */
540  ACPI_SET8(destination) |= (u8)
541  ((ACPI_GET8(source) & 0x07) << info->value);
542  break;
543 
544  case ACPI_RSC_COUNT:
545 
546  item_count = ACPI_GET8(source);
547  ACPI_SET8(destination) = (u8) item_count;
548 
549  aml_length =
550  (u16) (aml_length +
551  (info->value * (item_count - 1)));
552  break;
553 
554  case ACPI_RSC_COUNT16:
555 
556  item_count = ACPI_GET16(source);
557  aml_length = (u16) (aml_length + item_count);
558  acpi_rs_set_resource_length(aml_length, aml);
559  break;
560 
562 
563  item_count = ACPI_GET16(source);
564  ACPI_SET16(destination) = (u16)aml_length;
565 
566  aml_length = (u16)(aml_length + item_count * 2);
567  target = ACPI_ADD_PTR(void, aml, info->value);
568  ACPI_SET16(target) = (u16)aml_length;
569  acpi_rs_set_resource_length(aml_length, aml);
570  break;
571 
573 
574  item_count = ACPI_GET16(source);
575  ACPI_SET16(destination) = (u16)item_count;
576 
577  aml_length =
578  (u16)(aml_length + (info->value * item_count));
579  acpi_rs_set_resource_length(aml_length, aml);
580  break;
581 
583 
584  /* Set resource source string length */
585 
586  item_count = ACPI_GET16(source);
587  ACPI_SET16(destination) = (u16)aml_length;
588 
589  /* Compute offset for the Vendor Data */
590 
591  aml_length = (u16)(aml_length + item_count);
592  target = ACPI_ADD_PTR(void, aml, info->value);
593 
594  /* Set vendor offset only if there is vendor data */
595 
596  if (resource->data.gpio.vendor_length) {
597  ACPI_SET16(target) = (u16)aml_length;
598  }
599 
600  acpi_rs_set_resource_length(aml_length, aml);
601  break;
602 
604 
605  item_count = ACPI_GET16(source);
606  ACPI_SET16(destination) = item_count + info->value;
607  aml_length = (u16)(aml_length + item_count);
608  acpi_rs_set_resource_length(aml_length, aml);
609  break;
610 
612 
613  item_count = ACPI_GET16(source);
614  aml_length = (u16)(aml_length + item_count);
615  acpi_rs_set_resource_length(aml_length, aml);
616  break;
617 
618  case ACPI_RSC_LENGTH:
619 
621  break;
622 
623  case ACPI_RSC_MOVE8:
624  case ACPI_RSC_MOVE16:
625  case ACPI_RSC_MOVE32:
626  case ACPI_RSC_MOVE64:
627 
628  if (info->value) {
629  item_count = info->value;
630  }
631  acpi_rs_move_data(destination, source, item_count,
632  info->opcode);
633  break;
634 
636 
637  destination = (char *)ACPI_ADD_PTR(void, aml,
638  ACPI_GET16
639  (destination));
640  source = *(u16 **)source;
641  acpi_rs_move_data(destination, source, item_count,
642  info->opcode);
643  break;
644 
646 
647  /* Used for both resource_source string and vendor_data */
648 
649  destination = (char *)ACPI_ADD_PTR(void, aml,
650  ACPI_GET16
651  (destination));
652  source = *(u8 **)source;
653  acpi_rs_move_data(destination, source, item_count,
654  info->opcode);
655  break;
656 
658 
659  destination = (char *)ACPI_ADD_PTR(void, aml,
660  (aml_length -
661  item_count));
662  source = *(u8 **)source;
663  acpi_rs_move_data(destination, source, item_count,
664  info->opcode);
665  break;
666 
668 
669  destination = (char *)ACPI_ADD_PTR(void, aml,
670  (aml_length -
671  item_count));
672  source = *(u8 **)source;
673  acpi_rs_move_data(destination, source, item_count,
674  info->opcode);
675  break;
676 
677  case ACPI_RSC_ADDRESS:
678 
679  /* Set the Resource Type, General Flags, and Type-Specific Flags */
680 
681  acpi_rs_set_address_common(aml, resource);
682  break;
683 
684  case ACPI_RSC_SOURCEX:
685  /*
686  * Optional resource_source (Index and String)
687  */
688  aml_length =
690  aml_length, source);
691  acpi_rs_set_resource_length(aml_length, aml);
692  break;
693 
694  case ACPI_RSC_SOURCE:
695  /*
696  * Optional resource_source (Index and String). This is the more
697  * complicated case used by the Interrupt() macro
698  */
699  aml_length =
701  source);
702  acpi_rs_set_resource_length(aml_length, aml);
703  break;
704 
705  case ACPI_RSC_BITMASK:
706  /*
707  * 8-bit encoded bitmask (DMA macro)
708  */
709  ACPI_SET8(destination) = (u8)
710  acpi_rs_encode_bitmask(source,
711  *ACPI_ADD_PTR(u8, resource,
712  info->value));
713  break;
714 
715  case ACPI_RSC_BITMASK16:
716  /*
717  * 16-bit encoded bitmask (IRQ macro)
718  */
719  temp16 = acpi_rs_encode_bitmask(source,
720  *ACPI_ADD_PTR(u8,
721  resource,
722  info->
723  value));
724  ACPI_MOVE_16_TO_16(destination, &temp16);
725  break;
726 
727  case ACPI_RSC_EXIT_LE:
728  /*
729  * control - Exit conversion if less than or equal
730  */
731  if (item_count <= info->value) {
732  goto exit;
733  }
734  break;
735 
736  case ACPI_RSC_EXIT_NE:
737  /*
738  * control - Exit conversion if not equal
739  */
740  switch (COMPARE_OPCODE(info)) {
742 
743  if (*ACPI_ADD_PTR(u8, resource,
744  COMPARE_TARGET(info)) !=
745  COMPARE_VALUE(info)) {
746  goto exit;
747  }
748  break;
749 
750  default:
751 
753  "Invalid conversion sub-opcode"));
755  }
756  break;
757 
758  case ACPI_RSC_EXIT_EQ:
759  /*
760  * control - Exit conversion if equal
761  */
762  if (*ACPI_ADD_PTR(u8, resource,
763  COMPARE_TARGET(info)) ==
764  COMPARE_VALUE(info)) {
765  goto exit;
766  }
767  break;
768 
769  default:
770 
771  ACPI_ERROR((AE_INFO, "Invalid conversion opcode"));
773  }
774 
775  count--;
776  info++;
777  }
778 
779  exit:
781 }
782 
783 #if 0
784 /* Previous resource validations */
785 
786 if (aml->ext_address64.revision_ID != AML_RESOURCE_EXTENDED_ADDRESS_REVISION) {
788 }
789 
790 if (resource->data.start_dpf.performance_robustness >= 3) {
792 }
793 
794 if (((aml->irq.flags & 0x09) == 0x00) || ((aml->irq.flags & 0x09) == 0x09)) {
795  /*
796  * Only [active_high, edge_sensitive] or [active_low, level_sensitive]
797  * polarity/trigger interrupts are allowed (ACPI spec, section
798  * "IRQ Format"), so 0x00 and 0x09 are illegal.
799  */
801  "Invalid interrupt polarity/trigger in resource list, 0x%X",
802  aml->irq.flags));
804 }
805 
806 resource->data.extended_irq.interrupt_count = temp8;
807 if (temp8 < 1) {
808 
809  /* Must have at least one IRQ */
810 
812 }
813 
814 if (resource->data.dma.transfer == 0x03) {
815  ACPI_ERROR((AE_INFO, "Invalid DMA.Transfer preference (3)"));
817 }
818 #endif