xref: /titanic_50/usr/src/uts/intel/io/acpica/resources/rsmisc.c (revision 2bc987325e3ded1865bff043128661815c4690b9)
1 /*******************************************************************************
2  *
3  * Module Name: rsmisc - Miscellaneous resource descriptors
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2011, 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 #define __RSMISC_C__
45 
46 #include "acpi.h"
47 #include "accommon.h"
48 #include "acresrc.h"
49 
50 #define _COMPONENT          ACPI_RESOURCES
51         ACPI_MODULE_NAME    ("rsmisc")
52 
53 
54 #define INIT_RESOURCE_TYPE(i)       i->ResourceOffset
55 #define INIT_RESOURCE_LENGTH(i)     i->AmlOffset
56 #define INIT_TABLE_LENGTH(i)        i->Value
57 
58 #define COMPARE_OPCODE(i)           i->ResourceOffset
59 #define COMPARE_TARGET(i)           i->AmlOffset
60 #define COMPARE_VALUE(i)            i->Value
61 
62 
63 /*******************************************************************************
64  *
65  * FUNCTION:    AcpiRsConvertAmlToResource
66  *
67  * PARAMETERS:  Resource            - Pointer to the resource descriptor
68  *              Aml                 - Where the AML descriptor is returned
69  *              Info                - Pointer to appropriate conversion table
70  *
71  * RETURN:      Status
72  *
73  * DESCRIPTION: Convert an external AML resource descriptor to the corresponding
74  *              internal resource descriptor
75  *
76  ******************************************************************************/
77 
78 ACPI_STATUS
79 AcpiRsConvertAmlToResource (
80     ACPI_RESOURCE           *Resource,
81     AML_RESOURCE            *Aml,
82     ACPI_RSCONVERT_INFO     *Info)
83 {
84     ACPI_RS_LENGTH          AmlResourceLength;
85     void                    *Source;
86     void                    *Destination;
87     char                    *Target;
88     UINT8                   Count;
89     UINT8                   FlagsMode = FALSE;
90     UINT16                  ItemCount = 0;
91     UINT16                  Temp16 = 0;
92 
93 
94     ACPI_FUNCTION_TRACE (RsConvertAmlToResource);
95 
96 
97     if (((ACPI_SIZE) Resource) & 0x3)
98     {
99         /* Each internal resource struct is expected to be 32-bit aligned */
100 
101         ACPI_WARNING ((AE_INFO,
102             "Misaligned resource pointer (get): %p Type 0x%2.2X Length %u",
103             Resource, Resource->Type, Resource->Length));
104     }
105 
106     /* Extract the resource Length field (does not include header length) */
107 
108     AmlResourceLength = AcpiUtGetResourceLength (Aml);
109 
110     /*
111      * First table entry must be ACPI_RSC_INITxxx and must contain the
112      * table length (# of table entries)
113      */
114     Count = INIT_TABLE_LENGTH (Info);
115 
116     while (Count)
117     {
118         /*
119          * Source is the external AML byte stream buffer,
120          * destination is the internal resource descriptor
121          */
122         Source      = ACPI_ADD_PTR (void, Aml, Info->AmlOffset);
123         Destination = ACPI_ADD_PTR (void, Resource, Info->ResourceOffset);
124 
125         switch (Info->Opcode)
126         {
127         case ACPI_RSC_INITGET:
128             /*
129              * Get the resource type and the initial (minimum) length
130              */
131             ACPI_MEMSET (Resource, 0, INIT_RESOURCE_LENGTH (Info));
132             Resource->Type = INIT_RESOURCE_TYPE (Info);
133             Resource->Length = INIT_RESOURCE_LENGTH (Info);
134             break;
135 
136 
137         case ACPI_RSC_INITSET:
138             break;
139 
140 
141         case ACPI_RSC_FLAGINIT:
142 
143             FlagsMode = TRUE;
144             break;
145 
146 
147         case ACPI_RSC_1BITFLAG:
148             /*
149              * Mask and shift the flag bit
150              */
151             ACPI_SET8 (Destination) = (UINT8)
152                 ((ACPI_GET8 (Source) >> Info->Value) & 0x01);
153             break;
154 
155 
156         case ACPI_RSC_2BITFLAG:
157             /*
158              * Mask and shift the flag bits
159              */
160             ACPI_SET8 (Destination) = (UINT8)
161                 ((ACPI_GET8 (Source) >> Info->Value) & 0x03);
162             break;
163 
164 
165         case ACPI_RSC_COUNT:
166 
167             ItemCount = ACPI_GET8 (Source);
168             ACPI_SET8 (Destination) = (UINT8) ItemCount;
169 
170             Resource->Length = Resource->Length +
171                 (Info->Value * (ItemCount - 1));
172             break;
173 
174 
175         case ACPI_RSC_COUNT16:
176 
177             ItemCount = AmlResourceLength;
178             ACPI_SET16 (Destination) = ItemCount;
179 
180             Resource->Length = Resource->Length +
181                 (Info->Value * (ItemCount - 1));
182             break;
183 
184 
185         case ACPI_RSC_LENGTH:
186 
187             Resource->Length = Resource->Length + Info->Value;
188             break;
189 
190 
191         case ACPI_RSC_MOVE8:
192         case ACPI_RSC_MOVE16:
193         case ACPI_RSC_MOVE32:
194         case ACPI_RSC_MOVE64:
195             /*
196              * Raw data move. Use the Info value field unless ItemCount has
197              * been previously initialized via a COUNT opcode
198              */
199             if (Info->Value)
200             {
201                 ItemCount = Info->Value;
202             }
203             AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
204             break;
205 
206 
207         case ACPI_RSC_SET8:
208 
209             ACPI_MEMSET (Destination, Info->AmlOffset, Info->Value);
210             break;
211 
212 
213         case ACPI_RSC_DATA8:
214 
215             Target = ACPI_ADD_PTR (char, Resource, Info->Value);
216             ACPI_MEMCPY (Destination, Source,  ACPI_GET16 (Target));
217             break;
218 
219 
220         case ACPI_RSC_ADDRESS:
221             /*
222              * Common handler for address descriptor flags
223              */
224             if (!AcpiRsGetAddressCommon (Resource, Aml))
225             {
226                 return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
227             }
228             break;
229 
230 
231         case ACPI_RSC_SOURCE:
232             /*
233              * Optional ResourceSource (Index and String)
234              */
235             Resource->Length +=
236                 AcpiRsGetResourceSource (AmlResourceLength, Info->Value,
237                     Destination, Aml, NULL);
238             break;
239 
240 
241         case ACPI_RSC_SOURCEX:
242             /*
243              * Optional ResourceSource (Index and String). This is the more
244              * complicated case used by the Interrupt() macro
245              */
246             Target = ACPI_ADD_PTR (char, Resource, Info->AmlOffset + (ItemCount * 4));
247 
248             Resource->Length +=
249                 AcpiRsGetResourceSource (AmlResourceLength,
250                     (ACPI_RS_LENGTH) (((ItemCount - 1) * sizeof (UINT32)) + Info->Value),
251                     Destination, Aml, Target);
252             break;
253 
254 
255         case ACPI_RSC_BITMASK:
256             /*
257              * 8-bit encoded bitmask (DMA macro)
258              */
259             ItemCount = AcpiRsDecodeBitmask (ACPI_GET8 (Source), Destination);
260             if (ItemCount)
261             {
262                 Resource->Length += (ItemCount - 1);
263             }
264 
265             Target = ACPI_ADD_PTR (char, Resource, Info->Value);
266             ACPI_SET8 (Target) = (UINT8) ItemCount;
267             break;
268 
269 
270         case ACPI_RSC_BITMASK16:
271             /*
272              * 16-bit encoded bitmask (IRQ macro)
273              */
274             ACPI_MOVE_16_TO_16 (&Temp16, Source);
275 
276             ItemCount = AcpiRsDecodeBitmask (Temp16, Destination);
277             if (ItemCount)
278             {
279                 Resource->Length += (ItemCount - 1);
280             }
281 
282             Target = ACPI_ADD_PTR (char, Resource, Info->Value);
283             ACPI_SET8 (Target) = (UINT8) ItemCount;
284             break;
285 
286 
287         case ACPI_RSC_EXIT_NE:
288             /*
289              * Control - Exit conversion if not equal
290              */
291             switch (Info->ResourceOffset)
292             {
293             case ACPI_RSC_COMPARE_AML_LENGTH:
294                 if (AmlResourceLength != Info->Value)
295                 {
296                     goto Exit;
297                 }
298                 break;
299 
300             case ACPI_RSC_COMPARE_VALUE:
301                 if (ACPI_GET8 (Source) != Info->Value)
302                 {
303                     goto Exit;
304                 }
305                 break;
306 
307             default:
308 
309                 ACPI_ERROR ((AE_INFO, "Invalid conversion sub-opcode"));
310                 return_ACPI_STATUS (AE_BAD_PARAMETER);
311             }
312             break;
313 
314 
315         default:
316 
317             ACPI_ERROR ((AE_INFO, "Invalid conversion opcode"));
318             return_ACPI_STATUS (AE_BAD_PARAMETER);
319         }
320 
321         Count--;
322         Info++;
323     }
324 
325 Exit:
326     if (!FlagsMode)
327     {
328         /* Round the resource struct length up to the next boundary (32 or 64) */
329 
330         Resource->Length = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (Resource->Length);
331     }
332     return_ACPI_STATUS (AE_OK);
333 }
334 
335 
336 /*******************************************************************************
337  *
338  * FUNCTION:    AcpiRsConvertResourceToAml
339  *
340  * PARAMETERS:  Resource            - Pointer to the resource descriptor
341  *              Aml                 - Where the AML descriptor is returned
342  *              Info                - Pointer to appropriate conversion table
343  *
344  * RETURN:      Status
345  *
346  * DESCRIPTION: Convert an internal resource descriptor to the corresponding
347  *              external AML resource descriptor.
348  *
349  ******************************************************************************/
350 
351 ACPI_STATUS
352 AcpiRsConvertResourceToAml (
353     ACPI_RESOURCE           *Resource,
354     AML_RESOURCE            *Aml,
355     ACPI_RSCONVERT_INFO     *Info)
356 {
357     void                    *Source = NULL;
358     void                    *Destination;
359     ACPI_RSDESC_SIZE        AmlLength = 0;
360     UINT8                   Count;
361     UINT16                  Temp16 = 0;
362     UINT16                  ItemCount = 0;
363 
364 
365     ACPI_FUNCTION_TRACE (RsConvertResourceToAml);
366 
367 
368     /*
369      * First table entry must be ACPI_RSC_INITxxx and must contain the
370      * table length (# of table entries)
371      */
372     Count = INIT_TABLE_LENGTH (Info);
373 
374     while (Count)
375     {
376         /*
377          * Source is the internal resource descriptor,
378          * destination is the external AML byte stream buffer
379          */
380         Source      = ACPI_ADD_PTR (void, Resource, Info->ResourceOffset);
381         Destination = ACPI_ADD_PTR (void, Aml, Info->AmlOffset);
382 
383         switch (Info->Opcode)
384         {
385         case ACPI_RSC_INITSET:
386 
387             ACPI_MEMSET (Aml, 0, INIT_RESOURCE_LENGTH (Info));
388             AmlLength = INIT_RESOURCE_LENGTH (Info);
389             AcpiRsSetResourceHeader (INIT_RESOURCE_TYPE (Info), AmlLength, Aml);
390             break;
391 
392 
393         case ACPI_RSC_INITGET:
394             break;
395 
396 
397         case ACPI_RSC_FLAGINIT:
398             /*
399              * Clear the flag byte
400              */
401             ACPI_SET8 (Destination) = 0;
402             break;
403 
404 
405         case ACPI_RSC_1BITFLAG:
406             /*
407              * Mask and shift the flag bit
408              */
409             ACPI_SET8 (Destination) |= (UINT8)
410                 ((ACPI_GET8 (Source) & 0x01) << Info->Value);
411             break;
412 
413 
414         case ACPI_RSC_2BITFLAG:
415             /*
416              * Mask and shift the flag bits
417              */
418             ACPI_SET8 (Destination) |= (UINT8)
419                 ((ACPI_GET8 (Source) & 0x03) << Info->Value);
420             break;
421 
422 
423         case ACPI_RSC_COUNT:
424 
425             ItemCount = ACPI_GET8 (Source);
426             ACPI_SET8 (Destination) = (UINT8) ItemCount;
427 
428             AmlLength = (UINT16) (AmlLength + (Info->Value * (ItemCount - 1)));
429             break;
430 
431 
432         case ACPI_RSC_COUNT16:
433 
434             ItemCount = ACPI_GET16 (Source);
435             AmlLength = (UINT16) (AmlLength + ItemCount);
436             AcpiRsSetResourceLength (AmlLength, Aml);
437             break;
438 
439 
440         case ACPI_RSC_LENGTH:
441 
442             AcpiRsSetResourceLength (Info->Value, Aml);
443             break;
444 
445 
446         case ACPI_RSC_MOVE8:
447         case ACPI_RSC_MOVE16:
448         case ACPI_RSC_MOVE32:
449         case ACPI_RSC_MOVE64:
450 
451             if (Info->Value)
452             {
453                 ItemCount = Info->Value;
454             }
455             AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
456             break;
457 
458 
459         case ACPI_RSC_ADDRESS:
460 
461             /* Set the Resource Type, General Flags, and Type-Specific Flags */
462 
463             AcpiRsSetAddressCommon (Aml, Resource);
464             break;
465 
466 
467         case ACPI_RSC_SOURCEX:
468             /*
469              * Optional ResourceSource (Index and String)
470              */
471             AmlLength = AcpiRsSetResourceSource (
472                             Aml, (ACPI_RS_LENGTH) AmlLength, Source);
473             AcpiRsSetResourceLength (AmlLength, Aml);
474             break;
475 
476 
477         case ACPI_RSC_SOURCE:
478             /*
479              * Optional ResourceSource (Index and String). This is the more
480              * complicated case used by the Interrupt() macro
481              */
482             AmlLength = AcpiRsSetResourceSource (Aml, Info->Value, Source);
483             AcpiRsSetResourceLength (AmlLength, Aml);
484             break;
485 
486 
487         case ACPI_RSC_BITMASK:
488             /*
489              * 8-bit encoded bitmask (DMA macro)
490              */
491             ACPI_SET8 (Destination) = (UINT8)
492                 AcpiRsEncodeBitmask (Source,
493                     *ACPI_ADD_PTR (UINT8, Resource, Info->Value));
494             break;
495 
496 
497         case ACPI_RSC_BITMASK16:
498             /*
499              * 16-bit encoded bitmask (IRQ macro)
500              */
501             Temp16 = AcpiRsEncodeBitmask (Source,
502                         *ACPI_ADD_PTR (UINT8, Resource, Info->Value));
503             ACPI_MOVE_16_TO_16 (Destination, &Temp16);
504             break;
505 
506 
507         case ACPI_RSC_EXIT_LE:
508             /*
509              * Control - Exit conversion if less than or equal
510              */
511             if (ItemCount <= Info->Value)
512             {
513                 goto Exit;
514             }
515             break;
516 
517 
518         case ACPI_RSC_EXIT_NE:
519             /*
520              * Control - Exit conversion if not equal
521              */
522             switch (COMPARE_OPCODE (Info))
523             {
524             case ACPI_RSC_COMPARE_VALUE:
525 
526                 if (*ACPI_ADD_PTR (UINT8, Resource,
527                         COMPARE_TARGET (Info)) != COMPARE_VALUE (Info))
528                 {
529                     goto Exit;
530                 }
531                 break;
532 
533             default:
534 
535                 ACPI_ERROR ((AE_INFO, "Invalid conversion sub-opcode"));
536                 return_ACPI_STATUS (AE_BAD_PARAMETER);
537             }
538             break;
539 
540 
541         case ACPI_RSC_EXIT_EQ:
542             /*
543              * Control - Exit conversion if equal
544              */
545             if (*ACPI_ADD_PTR (UINT8, Resource,
546                     COMPARE_TARGET (Info)) == COMPARE_VALUE (Info))
547             {
548                 goto Exit;
549             }
550             break;
551 
552 
553         default:
554 
555             ACPI_ERROR ((AE_INFO, "Invalid conversion opcode"));
556             return_ACPI_STATUS (AE_BAD_PARAMETER);
557         }
558 
559         Count--;
560         Info++;
561     }
562 
563 Exit:
564     return_ACPI_STATUS (AE_OK);
565 }
566 
567 
568 #if 0
569 /* Previous resource validations */
570 
571     if (Aml->ExtAddress64.RevisionID != AML_RESOURCE_EXTENDED_ADDRESS_REVISION)
572     {
573         return_ACPI_STATUS (AE_SUPPORT);
574     }
575 
576     if (Resource->Data.StartDpf.PerformanceRobustness >= 3)
577     {
578         return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE);
579     }
580 
581     if (((Aml->Irq.Flags & 0x09) == 0x00) ||
582         ((Aml->Irq.Flags & 0x09) == 0x09))
583     {
584         /*
585          * Only [ActiveHigh, EdgeSensitive] or [ActiveLow, LevelSensitive]
586          * polarity/trigger interrupts are allowed (ACPI spec, section
587          * "IRQ Format"), so 0x00 and 0x09 are illegal.
588          */
589         ACPI_ERROR ((AE_INFO,
590             "Invalid interrupt polarity/trigger in resource list, 0x%X",
591             Aml->Irq.Flags));
592         return_ACPI_STATUS (AE_BAD_DATA);
593     }
594 
595     Resource->Data.ExtendedIrq.InterruptCount = Temp8;
596     if (Temp8 < 1)
597     {
598         /* Must have at least one IRQ */
599 
600         return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
601     }
602 
603     if (Resource->Data.Dma.Transfer == 0x03)
604     {
605         ACPI_ERROR ((AE_INFO,
606             "Invalid DMA.Transfer preference (3)"));
607         return_ACPI_STATUS (AE_BAD_DATA);
608     }
609 #endif
610 
611 
612