1 /*******************************************************************************
3 * Module Name: rsmisc - Miscellaneous resource descriptors
5 ******************************************************************************/
8 * Copyright (C) 2000 - 2012, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
46 #include <contrib/dev/acpica/include/acpi.h>
47 #include <contrib/dev/acpica/include/accommon.h>
48 #include <contrib/dev/acpica/include/acresrc.h>
50 #define _COMPONENT ACPI_RESOURCES
51 ACPI_MODULE_NAME ("rsmisc")
54 #define INIT_RESOURCE_TYPE(i) i->ResourceOffset
55 #define INIT_RESOURCE_LENGTH(i) i->AmlOffset
56 #define INIT_TABLE_LENGTH(i) i->Value
58 #define COMPARE_OPCODE(i) i->ResourceOffset
59 #define COMPARE_TARGET(i) i->AmlOffset
60 #define COMPARE_VALUE(i) i->Value
63 /*******************************************************************************
65 * FUNCTION: AcpiRsConvertAmlToResource
67 * PARAMETERS: Resource - Pointer to the resource descriptor
68 * Aml - Where the AML descriptor is returned
69 * Info - Pointer to appropriate conversion table
73 * DESCRIPTION: Convert an external AML resource descriptor to the corresponding
74 * internal resource descriptor
76 ******************************************************************************/
79 AcpiRsConvertAmlToResource (
80 ACPI_RESOURCE *Resource,
82 ACPI_RSCONVERT_INFO *Info)
84 ACPI_RS_LENGTH AmlResourceLength;
89 UINT8 FlagsMode = FALSE;
94 ACPI_FUNCTION_TRACE (RsConvertAmlToResource);
99 return_ACPI_STATUS (AE_BAD_PARAMETER);
102 if (((ACPI_SIZE) Resource) & 0x3)
104 /* Each internal resource struct is expected to be 32-bit aligned */
106 ACPI_WARNING ((AE_INFO,
107 "Misaligned resource pointer (get): %p Type 0x%2.2X Length %u",
108 Resource, Resource->Type, Resource->Length));
111 /* Extract the resource Length field (does not include header length) */
113 AmlResourceLength = AcpiUtGetResourceLength (Aml);
116 * First table entry must be ACPI_RSC_INITxxx and must contain the
117 * table length (# of table entries)
119 Count = INIT_TABLE_LENGTH (Info);
123 * Source is the external AML byte stream buffer,
124 * destination is the internal resource descriptor
126 Source = ACPI_ADD_PTR (void, Aml, Info->AmlOffset);
127 Destination = ACPI_ADD_PTR (void, Resource, Info->ResourceOffset);
129 switch (Info->Opcode)
131 case ACPI_RSC_INITGET:
133 * Get the resource type and the initial (minimum) length
135 ACPI_MEMSET (Resource, 0, INIT_RESOURCE_LENGTH (Info));
136 Resource->Type = INIT_RESOURCE_TYPE (Info);
137 Resource->Length = INIT_RESOURCE_LENGTH (Info);
141 case ACPI_RSC_INITSET:
145 case ACPI_RSC_FLAGINIT:
151 case ACPI_RSC_1BITFLAG:
153 * Mask and shift the flag bit
155 ACPI_SET8 (Destination,
156 ((ACPI_GET8 (Source) >> Info->Value) & 0x01));
160 case ACPI_RSC_2BITFLAG:
162 * Mask and shift the flag bits
164 ACPI_SET8 (Destination,
165 ((ACPI_GET8 (Source) >> Info->Value) & 0x03));
169 case ACPI_RSC_3BITFLAG:
171 * Mask and shift the flag bits
173 ACPI_SET8 (Destination,
174 ((ACPI_GET8 (Source) >> Info->Value) & 0x07));
180 ItemCount = ACPI_GET8 (Source);
181 ACPI_SET8 (Destination, ItemCount);
183 Resource->Length = Resource->Length +
184 (Info->Value * (ItemCount - 1));
188 case ACPI_RSC_COUNT16:
190 ItemCount = AmlResourceLength;
191 ACPI_SET16 (Destination, ItemCount);
193 Resource->Length = Resource->Length +
194 (Info->Value * (ItemCount - 1));
198 case ACPI_RSC_COUNT_GPIO_PIN:
200 Target = ACPI_ADD_PTR (void, Aml, Info->Value);
201 ItemCount = ACPI_GET16 (Target) - ACPI_GET16 (Source);
203 Resource->Length = Resource->Length + ItemCount;
204 ItemCount = ItemCount / 2;
205 ACPI_SET16 (Destination, ItemCount);
209 case ACPI_RSC_COUNT_GPIO_VEN:
211 ItemCount = ACPI_GET8 (Source);
212 ACPI_SET8 (Destination, ItemCount);
214 Resource->Length = Resource->Length +
215 (Info->Value * ItemCount);
219 case ACPI_RSC_COUNT_GPIO_RES:
222 * Vendor data is optional (length/offset may both be zero)
223 * Examine vendor data length field first
225 Target = ACPI_ADD_PTR (void, Aml, (Info->Value + 2));
226 if (ACPI_GET16 (Target))
228 /* Use vendor offset to get resource source length */
230 Target = ACPI_ADD_PTR (void, Aml, Info->Value);
231 ItemCount = ACPI_GET16 (Target) - ACPI_GET16 (Source);
235 /* No vendor data to worry about */
237 ItemCount = Aml->LargeHeader.ResourceLength +
238 sizeof (AML_RESOURCE_LARGE_HEADER) -
242 Resource->Length = Resource->Length + ItemCount;
243 ACPI_SET16 (Destination, ItemCount);
247 case ACPI_RSC_COUNT_SERIAL_VEN:
249 ItemCount = ACPI_GET16 (Source) - Info->Value;
251 Resource->Length = Resource->Length + ItemCount;
252 ACPI_SET16 (Destination, ItemCount);
256 case ACPI_RSC_COUNT_SERIAL_RES:
258 ItemCount = (AmlResourceLength +
259 sizeof (AML_RESOURCE_LARGE_HEADER)) -
260 ACPI_GET16 (Source) - Info->Value;
262 Resource->Length = Resource->Length + ItemCount;
263 ACPI_SET16 (Destination, ItemCount);
267 case ACPI_RSC_LENGTH:
269 Resource->Length = Resource->Length + Info->Value;
274 case ACPI_RSC_MOVE16:
275 case ACPI_RSC_MOVE32:
276 case ACPI_RSC_MOVE64:
278 * Raw data move. Use the Info value field unless ItemCount has
279 * been previously initialized via a COUNT opcode
283 ItemCount = Info->Value;
285 AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
289 case ACPI_RSC_MOVE_GPIO_PIN:
291 /* Generate and set the PIN data pointer */
293 Target = (char *) ACPI_ADD_PTR (void, Resource,
294 (Resource->Length - ItemCount * 2));
295 *(UINT16 **) Destination = ACPI_CAST_PTR (UINT16, Target);
297 /* Copy the PIN data */
299 Source = ACPI_ADD_PTR (void, Aml, ACPI_GET16 (Source));
300 AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode);
304 case ACPI_RSC_MOVE_GPIO_RES:
306 /* Generate and set the ResourceSource string pointer */
308 Target = (char *) ACPI_ADD_PTR (void, Resource,
309 (Resource->Length - ItemCount));
310 *(UINT8 **) Destination = ACPI_CAST_PTR (UINT8, Target);
312 /* Copy the ResourceSource string */
314 Source = ACPI_ADD_PTR (void, Aml, ACPI_GET16 (Source));
315 AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode);
319 case ACPI_RSC_MOVE_SERIAL_VEN:
321 /* Generate and set the Vendor Data pointer */
323 Target = (char *) ACPI_ADD_PTR (void, Resource,
324 (Resource->Length - ItemCount));
325 *(UINT8 **) Destination = ACPI_CAST_PTR (UINT8, Target);
327 /* Copy the Vendor Data */
329 Source = ACPI_ADD_PTR (void, Aml, Info->Value);
330 AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode);
334 case ACPI_RSC_MOVE_SERIAL_RES:
336 /* Generate and set the ResourceSource string pointer */
338 Target = (char *) ACPI_ADD_PTR (void, Resource,
339 (Resource->Length - ItemCount));
340 *(UINT8 **) Destination = ACPI_CAST_PTR (UINT8, Target);
342 /* Copy the ResourceSource string */
344 Source = ACPI_ADD_PTR (void, Aml, (ACPI_GET16 (Source) + Info->Value));
345 AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode);
351 ACPI_MEMSET (Destination, Info->AmlOffset, Info->Value);
357 Target = ACPI_ADD_PTR (char, Resource, Info->Value);
358 ACPI_MEMCPY (Destination, Source, ACPI_GET16 (Target));
362 case ACPI_RSC_ADDRESS:
364 * Common handler for address descriptor flags
366 if (!AcpiRsGetAddressCommon (Resource, Aml))
368 return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
373 case ACPI_RSC_SOURCE:
375 * Optional ResourceSource (Index and String)
378 AcpiRsGetResourceSource (AmlResourceLength, Info->Value,
379 Destination, Aml, NULL);
383 case ACPI_RSC_SOURCEX:
385 * Optional ResourceSource (Index and String). This is the more
386 * complicated case used by the Interrupt() macro
388 Target = ACPI_ADD_PTR (char, Resource,
389 Info->AmlOffset + (ItemCount * 4));
392 AcpiRsGetResourceSource (AmlResourceLength, (ACPI_RS_LENGTH)
393 (((ItemCount - 1) * sizeof (UINT32)) + Info->Value),
394 Destination, Aml, Target);
398 case ACPI_RSC_BITMASK:
400 * 8-bit encoded bitmask (DMA macro)
402 ItemCount = AcpiRsDecodeBitmask (ACPI_GET8 (Source), Destination);
405 Resource->Length += (ItemCount - 1);
408 Target = ACPI_ADD_PTR (char, Resource, Info->Value);
409 ACPI_SET8 (Target, ItemCount);
413 case ACPI_RSC_BITMASK16:
415 * 16-bit encoded bitmask (IRQ macro)
417 ACPI_MOVE_16_TO_16 (&Temp16, Source);
419 ItemCount = AcpiRsDecodeBitmask (Temp16, Destination);
422 Resource->Length += (ItemCount - 1);
425 Target = ACPI_ADD_PTR (char, Resource, Info->Value);
426 ACPI_SET8 (Target, ItemCount);
430 case ACPI_RSC_EXIT_NE:
432 * Control - Exit conversion if not equal
434 switch (Info->ResourceOffset)
436 case ACPI_RSC_COMPARE_AML_LENGTH:
437 if (AmlResourceLength != Info->Value)
443 case ACPI_RSC_COMPARE_VALUE:
444 if (ACPI_GET8 (Source) != Info->Value)
452 ACPI_ERROR ((AE_INFO, "Invalid conversion sub-opcode"));
453 return_ACPI_STATUS (AE_BAD_PARAMETER);
460 ACPI_ERROR ((AE_INFO, "Invalid conversion opcode"));
461 return_ACPI_STATUS (AE_BAD_PARAMETER);
471 /* Round the resource struct length up to the next boundary (32 or 64) */
473 Resource->Length = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (Resource->Length);
475 return_ACPI_STATUS (AE_OK);
479 /*******************************************************************************
481 * FUNCTION: AcpiRsConvertResourceToAml
483 * PARAMETERS: Resource - Pointer to the resource descriptor
484 * Aml - Where the AML descriptor is returned
485 * Info - Pointer to appropriate conversion table
489 * DESCRIPTION: Convert an internal resource descriptor to the corresponding
490 * external AML resource descriptor.
492 ******************************************************************************/
495 AcpiRsConvertResourceToAml (
496 ACPI_RESOURCE *Resource,
498 ACPI_RSCONVERT_INFO *Info)
503 ACPI_RSDESC_SIZE AmlLength = 0;
506 UINT16 ItemCount = 0;
509 ACPI_FUNCTION_TRACE (RsConvertResourceToAml);
514 return_ACPI_STATUS (AE_BAD_PARAMETER);
518 * First table entry must be ACPI_RSC_INITxxx and must contain the
519 * table length (# of table entries)
521 Count = INIT_TABLE_LENGTH (Info);
526 * Source is the internal resource descriptor,
527 * destination is the external AML byte stream buffer
529 Source = ACPI_ADD_PTR (void, Resource, Info->ResourceOffset);
530 Destination = ACPI_ADD_PTR (void, Aml, Info->AmlOffset);
532 switch (Info->Opcode)
534 case ACPI_RSC_INITSET:
536 ACPI_MEMSET (Aml, 0, INIT_RESOURCE_LENGTH (Info));
537 AmlLength = INIT_RESOURCE_LENGTH (Info);
538 AcpiRsSetResourceHeader (INIT_RESOURCE_TYPE (Info), AmlLength, Aml);
542 case ACPI_RSC_INITGET:
546 case ACPI_RSC_FLAGINIT:
548 * Clear the flag byte
550 ACPI_SET8 (Destination, 0);
554 case ACPI_RSC_1BITFLAG:
556 * Mask and shift the flag bit
558 ACPI_SET_BIT (*ACPI_CAST8 (Destination), (UINT8)
559 ((ACPI_GET8 (Source) & 0x01) << Info->Value));
563 case ACPI_RSC_2BITFLAG:
565 * Mask and shift the flag bits
567 ACPI_SET_BIT (*ACPI_CAST8 (Destination), (UINT8)
568 ((ACPI_GET8 (Source) & 0x03) << Info->Value));
572 case ACPI_RSC_3BITFLAG:
574 * Mask and shift the flag bits
576 ACPI_SET_BIT (*ACPI_CAST8 (Destination), (UINT8)
577 ((ACPI_GET8 (Source) & 0x07) << Info->Value));
583 ItemCount = ACPI_GET8 (Source);
584 ACPI_SET8 (Destination, ItemCount);
586 AmlLength = (UINT16) (AmlLength + (Info->Value * (ItemCount - 1)));
590 case ACPI_RSC_COUNT16:
592 ItemCount = ACPI_GET16 (Source);
593 AmlLength = (UINT16) (AmlLength + ItemCount);
594 AcpiRsSetResourceLength (AmlLength, Aml);
598 case ACPI_RSC_COUNT_GPIO_PIN:
600 ItemCount = ACPI_GET16 (Source);
601 ACPI_SET16 (Destination, AmlLength);
603 AmlLength = (UINT16) (AmlLength + ItemCount * 2);
604 Target = ACPI_ADD_PTR (void, Aml, Info->Value);
605 ACPI_SET16 (Target, AmlLength);
606 AcpiRsSetResourceLength (AmlLength, Aml);
610 case ACPI_RSC_COUNT_GPIO_VEN:
612 ItemCount = ACPI_GET16 (Source);
613 ACPI_SET16 (Destination, ItemCount);
615 AmlLength = (UINT16) (AmlLength + (Info->Value * ItemCount));
616 AcpiRsSetResourceLength (AmlLength, Aml);
620 case ACPI_RSC_COUNT_GPIO_RES:
622 /* Set resource source string length */
624 ItemCount = ACPI_GET16 (Source);
625 ACPI_SET16 (Destination, AmlLength);
627 /* Compute offset for the Vendor Data */
629 AmlLength = (UINT16) (AmlLength + ItemCount);
630 Target = ACPI_ADD_PTR (void, Aml, Info->Value);
632 /* Set vendor offset only if there is vendor data */
634 if (Resource->Data.Gpio.VendorLength)
636 ACPI_SET16 (Target, AmlLength);
639 AcpiRsSetResourceLength (AmlLength, Aml);
643 case ACPI_RSC_COUNT_SERIAL_VEN:
645 ItemCount = ACPI_GET16 (Source);
646 ACPI_SET16 (Destination, ItemCount + Info->Value);
647 AmlLength = (UINT16) (AmlLength + ItemCount);
648 AcpiRsSetResourceLength (AmlLength, Aml);
652 case ACPI_RSC_COUNT_SERIAL_RES:
654 ItemCount = ACPI_GET16 (Source);
655 AmlLength = (UINT16) (AmlLength + ItemCount);
656 AcpiRsSetResourceLength (AmlLength, Aml);
660 case ACPI_RSC_LENGTH:
662 AcpiRsSetResourceLength (Info->Value, Aml);
667 case ACPI_RSC_MOVE16:
668 case ACPI_RSC_MOVE32:
669 case ACPI_RSC_MOVE64:
673 ItemCount = Info->Value;
675 AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
679 case ACPI_RSC_MOVE_GPIO_PIN:
681 Destination = (char *) ACPI_ADD_PTR (void, Aml,
682 ACPI_GET16 (Destination));
683 Source = * (UINT16 **) Source;
684 AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
688 case ACPI_RSC_MOVE_GPIO_RES:
690 /* Used for both ResourceSource string and VendorData */
692 Destination = (char *) ACPI_ADD_PTR (void, Aml,
693 ACPI_GET16 (Destination));
694 Source = * (UINT8 **) Source;
695 AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
699 case ACPI_RSC_MOVE_SERIAL_VEN:
701 Destination = (char *) ACPI_ADD_PTR (void, Aml,
702 (AmlLength - ItemCount));
703 Source = * (UINT8 **) Source;
704 AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
708 case ACPI_RSC_MOVE_SERIAL_RES:
710 Destination = (char *) ACPI_ADD_PTR (void, Aml,
711 (AmlLength - ItemCount));
712 Source = * (UINT8 **) Source;
713 AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
717 case ACPI_RSC_ADDRESS:
719 /* Set the Resource Type, General Flags, and Type-Specific Flags */
721 AcpiRsSetAddressCommon (Aml, Resource);
725 case ACPI_RSC_SOURCEX:
727 * Optional ResourceSource (Index and String)
729 AmlLength = AcpiRsSetResourceSource (
730 Aml, (ACPI_RS_LENGTH) AmlLength, Source);
731 AcpiRsSetResourceLength (AmlLength, Aml);
735 case ACPI_RSC_SOURCE:
737 * Optional ResourceSource (Index and String). This is the more
738 * complicated case used by the Interrupt() macro
740 AmlLength = AcpiRsSetResourceSource (Aml, Info->Value, Source);
741 AcpiRsSetResourceLength (AmlLength, Aml);
745 case ACPI_RSC_BITMASK:
747 * 8-bit encoded bitmask (DMA macro)
749 ACPI_SET8 (Destination,
750 AcpiRsEncodeBitmask (Source,
751 *ACPI_ADD_PTR (UINT8, Resource, Info->Value)));
755 case ACPI_RSC_BITMASK16:
757 * 16-bit encoded bitmask (IRQ macro)
759 Temp16 = AcpiRsEncodeBitmask (Source,
760 *ACPI_ADD_PTR (UINT8, Resource, Info->Value));
761 ACPI_MOVE_16_TO_16 (Destination, &Temp16);
765 case ACPI_RSC_EXIT_LE:
767 * Control - Exit conversion if less than or equal
769 if (ItemCount <= Info->Value)
776 case ACPI_RSC_EXIT_NE:
778 * Control - Exit conversion if not equal
780 switch (COMPARE_OPCODE (Info))
782 case ACPI_RSC_COMPARE_VALUE:
784 if (*ACPI_ADD_PTR (UINT8, Resource,
785 COMPARE_TARGET (Info)) != COMPARE_VALUE (Info))
793 ACPI_ERROR ((AE_INFO, "Invalid conversion sub-opcode"));
794 return_ACPI_STATUS (AE_BAD_PARAMETER);
799 case ACPI_RSC_EXIT_EQ:
801 * Control - Exit conversion if equal
803 if (*ACPI_ADD_PTR (UINT8, Resource,
804 COMPARE_TARGET (Info)) == COMPARE_VALUE (Info))
813 ACPI_ERROR ((AE_INFO, "Invalid conversion opcode"));
814 return_ACPI_STATUS (AE_BAD_PARAMETER);
822 return_ACPI_STATUS (AE_OK);
827 /* Previous resource validations */
829 if (Aml->ExtAddress64.RevisionID != AML_RESOURCE_EXTENDED_ADDRESS_REVISION)
831 return_ACPI_STATUS (AE_SUPPORT);
834 if (Resource->Data.StartDpf.PerformanceRobustness >= 3)
836 return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE);
839 if (((Aml->Irq.Flags & 0x09) == 0x00) ||
840 ((Aml->Irq.Flags & 0x09) == 0x09))
843 * Only [ActiveHigh, EdgeSensitive] or [ActiveLow, LevelSensitive]
844 * polarity/trigger interrupts are allowed (ACPI spec, section
845 * "IRQ Format"), so 0x00 and 0x09 are illegal.
847 ACPI_ERROR ((AE_INFO,
848 "Invalid interrupt polarity/trigger in resource list, 0x%X",
850 return_ACPI_STATUS (AE_BAD_DATA);
853 Resource->Data.ExtendedIrq.InterruptCount = Temp8;
856 /* Must have at least one IRQ */
858 return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
861 if (Resource->Data.Dma.Transfer == 0x03)
863 ACPI_ERROR ((AE_INFO,
864 "Invalid DMA.Transfer preference (3)"));
865 return_ACPI_STATUS (AE_BAD_DATA);