rsirq.c revision 71867
1/*******************************************************************************
2 *
3 * Module Name: rsirq - AcpiRsIrqResource,
4 *                      AcpiRsIrqStream
5 *                      AcpiRsExtendedIrqResource
6 *                      AcpiRsExtendedIrqStream
7 *              $Revision: 13 $
8 *
9 ******************************************************************************/
10
11/******************************************************************************
12 *
13 * 1. Copyright Notice
14 *
15 * Some or all of this work - Copyright (c) 1999, 2000, 2001, Intel Corp.
16 * All rights reserved.
17 *
18 * 2. License
19 *
20 * 2.1. This is your license from Intel Corp. under its intellectual property
21 * rights.  You may have additional license terms from the party that provided
22 * you this software, covering your right to use that party's intellectual
23 * property rights.
24 *
25 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
26 * copy of the source code appearing in this file ("Covered Code") an
27 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
28 * base code distributed originally by Intel ("Original Intel Code") to copy,
29 * make derivatives, distribute, use and display any portion of the Covered
30 * Code in any form, with the right to sublicense such rights; and
31 *
32 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
33 * license (with the right to sublicense), under only those claims of Intel
34 * patents that are infringed by the Original Intel Code, to make, use, sell,
35 * offer to sell, and import the Covered Code and derivative works thereof
36 * solely to the minimum extent necessary to exercise the above copyright
37 * license, and in no event shall the patent license extend to any additions
38 * to or modifications of the Original Intel Code.  No other license or right
39 * is granted directly or by implication, estoppel or otherwise;
40 *
41 * The above copyright and patent license is granted only if the following
42 * conditions are met:
43 *
44 * 3. Conditions
45 *
46 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
47 * Redistribution of source code of any substantial portion of the Covered
48 * Code or modification with rights to further distribute source must include
49 * the above Copyright Notice, the above License, this list of Conditions,
50 * and the following Disclaimer and Export Compliance provision.  In addition,
51 * Licensee must cause all Covered Code to which Licensee contributes to
52 * contain a file documenting the changes Licensee made to create that Covered
53 * Code and the date of any change.  Licensee must include in that file the
54 * documentation of any changes made by any predecessor Licensee.  Licensee
55 * must include a prominent statement that the modification is derived,
56 * directly or indirectly, from Original Intel Code.
57 *
58 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
59 * Redistribution of source code of any substantial portion of the Covered
60 * Code or modification without rights to further distribute source must
61 * include the following Disclaimer and Export Compliance provision in the
62 * documentation and/or other materials provided with distribution.  In
63 * addition, Licensee may not authorize further sublicense of source of any
64 * portion of the Covered Code, and must include terms to the effect that the
65 * license from Licensee to its licensee is limited to the intellectual
66 * property embodied in the software Licensee provides to its licensee, and
67 * not to intellectual property embodied in modifications its licensee may
68 * make.
69 *
70 * 3.3. Redistribution of Executable. Redistribution in executable form of any
71 * substantial portion of the Covered Code or modification must reproduce the
72 * above Copyright Notice, and the following Disclaimer and Export Compliance
73 * provision in the documentation and/or other materials provided with the
74 * distribution.
75 *
76 * 3.4. Intel retains all right, title, and interest in and to the Original
77 * Intel Code.
78 *
79 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
80 * Intel shall be used in advertising or otherwise to promote the sale, use or
81 * other dealings in products derived from or relating to the Covered Code
82 * without prior written authorization from Intel.
83 *
84 * 4. Disclaimer and Export Compliance
85 *
86 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
87 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
88 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
89 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
90 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
91 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
92 * PARTICULAR PURPOSE.
93 *
94 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
95 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
96 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
97 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
98 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
99 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
100 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
101 * LIMITED REMEDY.
102 *
103 * 4.3. Licensee shall not export, either directly or indirectly, any of this
104 * software or system incorporating such software without first obtaining any
105 * required license or other approval from the U. S. Department of Commerce or
106 * any other agency or department of the United States Government.  In the
107 * event Licensee exports any such software from the United States or
108 * re-exports any such software from a foreign destination, Licensee shall
109 * ensure that the distribution and export/re-export of the software is in
110 * compliance with all laws, regulations, orders, or other restrictions of the
111 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
112 * any of its subsidiaries will export/re-export any technical data, process,
113 * software, or service, directly or indirectly, to any country for which the
114 * United States government or any agency thereof requires an export license,
115 * other governmental approval, or letter of assurance, without first obtaining
116 * such license, approval or letter.
117 *
118 *****************************************************************************/
119
120#define __RSIRQ_C__
121
122#include "acpi.h"
123#include "acresrc.h"
124
125#define _COMPONENT          RESOURCE_MANAGER
126        MODULE_NAME         ("rsirq")
127
128
129/*******************************************************************************
130 *
131 * FUNCTION:    AcpiRsIrqResource
132 *
133 * PARAMETERS:  ByteStreamBuffer        - Pointer to the resource input byte
134 *                                          stream
135 *              BytesConsumed           - UINT32 pointer that is filled with
136 *                                          the number of bytes consumed from
137 *                                          the ByteStreamBuffer
138 *              OutputBuffer            - Pointer to the user's return buffer
139 *              StructureSize           - UINT32 pointer that is filled with
140 *                                          the number of bytes in the filled
141 *                                          in structure
142 *
143 * RETURN:      Status  AE_OK if okay, else a valid ACPI_STATUS code
144 *
145 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
146 *                  structure pointed to by the OutputBuffer.  Return the
147 *                  number of bytes consumed from the byte stream.
148 *
149 ******************************************************************************/
150
151ACPI_STATUS
152AcpiRsIrqResource (
153    UINT8                   *ByteStreamBuffer,
154    UINT32                  *BytesConsumed,
155    UINT8                   **OutputBuffer,
156    UINT32                  *StructureSize)
157{
158    UINT8                   *Buffer = ByteStreamBuffer;
159    RESOURCE                *OutputStruct = (RESOURCE *) * OutputBuffer;
160    UINT16                  Temp16 = 0;
161    UINT8                   Temp8 = 0;
162    UINT8                   Index;
163    UINT8                   i;
164    UINT32                  StructSize = sizeof (IRQ_RESOURCE) +
165                                         RESOURCE_LENGTH_NO_DATA;
166
167
168    FUNCTION_TRACE ("RsIrqResource");
169
170    /*
171     * The number of bytes consumed are contained in the descriptor
172     *  (Bits:0-1)
173     */
174    Temp8 = *Buffer;
175    *BytesConsumed = (Temp8 & 0x03) + 1;
176    OutputStruct->Id = Irq;
177
178    /*
179     * Point to the 16-bits of Bytes 1 and 2
180     */
181    Buffer += 1;
182    MOVE_UNALIGNED16_TO_16 (&Temp16, Buffer);
183
184    OutputStruct->Data.Irq.NumberOfInterrupts = 0;
185
186    /* Decode the IRQ bits */
187
188    for (i = 0, Index = 0; Index < 16; Index++)
189    {
190        if((Temp16 >> Index) & 0x01)
191        {
192            OutputStruct->Data.Irq.Interrupts[i] = Index;
193            i++;
194        }
195    }
196    OutputStruct->Data.Irq.NumberOfInterrupts = i;
197
198    /*
199     * Calculate the structure size based upon the number of interrupts
200     */
201    StructSize += (OutputStruct->Data.Irq.NumberOfInterrupts - 1) * 4;
202
203    /*
204     * Point to Byte 3 if it is used
205     */
206    if (4 == *BytesConsumed)
207    {
208        Buffer += 2;
209        Temp8 = *Buffer;
210
211        /*
212         * Check for HE, LL or HL
213         */
214        if (Temp8 & 0x01)
215        {
216            OutputStruct->Data.Irq.EdgeLevel = EDGE_SENSITIVE;
217            OutputStruct->Data.Irq.ActiveHighLow = ACTIVE_HIGH;
218        }
219
220        else
221        {
222            if (Temp8 & 0x8)
223            {
224                OutputStruct->Data.Irq.EdgeLevel = LEVEL_SENSITIVE;
225                OutputStruct->Data.Irq.ActiveHighLow = ACTIVE_LOW;
226            }
227
228            else
229            {
230                /*
231                 * Only _LL and _HE polarity/trigger interrupts
232                 *  are allowed (ACPI spec v1.0b ection 6.4.2.1),
233                 *  so an error will occur if we reach this point
234                 */
235                return_ACPI_STATUS (AE_BAD_DATA);
236            }
237        }
238
239        /*
240         * Check for sharable
241         */
242        OutputStruct->Data.Irq.SharedExclusive = (Temp8 >> 3) & 0x01;
243    }
244
245    else
246    {
247        /*
248         * Assume Edge Sensitive, Active High, Non-Sharable
249         *  per ACPI Specification
250         */
251        OutputStruct->Data.Irq.EdgeLevel = EDGE_SENSITIVE;
252        OutputStruct->Data.Irq.ActiveHighLow = ACTIVE_HIGH;
253        OutputStruct->Data.Irq.SharedExclusive = EXCLUSIVE;
254    }
255
256    /*
257     * Set the Length parameter
258     */
259    OutputStruct->Length = StructSize;
260
261    /*
262     * Return the final size of the structure
263     */
264    *StructureSize = StructSize;
265
266    return_ACPI_STATUS (AE_OK);
267}
268
269
270/*******************************************************************************
271 *
272 * FUNCTION:    AcpiRsIrqStream
273 *
274 * PARAMETERS:  LinkedList              - Pointer to the resource linked list
275 *              OutputBuffer            - Pointer to the user's return buffer
276 *              BytesConsumed           - UINT32 pointer that is filled with
277 *                                          the number of bytes of the
278 *                                          OutputBuffer used
279 *
280 * RETURN:      Status  AE_OK if okay, else a valid ACPI_STATUS code
281 *
282 * DESCRIPTION: Take the linked list resource structure and fills in the
283 *                  the appropriate bytes in a byte stream
284 *
285 ******************************************************************************/
286
287ACPI_STATUS
288AcpiRsIrqStream (
289    RESOURCE                *LinkedList,
290    UINT8                   **OutputBuffer,
291    UINT32                  *BytesConsumed)
292{
293    UINT8                   *Buffer = *OutputBuffer;
294    UINT16                  Temp16 = 0;
295    UINT8                   Temp8 = 0;
296    UINT8                   Index;
297    BOOLEAN                 IRQInfoByteNeeded;
298
299
300    FUNCTION_TRACE ("RsIrqStream");
301
302
303    /*
304     * The descriptor field is set based upon whether a third byte is
305     *  needed to contain the IRQ Information.
306     */
307    if (EDGE_SENSITIVE == LinkedList->Data.Irq.EdgeLevel &&
308        ACTIVE_HIGH == LinkedList->Data.Irq.ActiveHighLow &&
309        EXCLUSIVE == LinkedList->Data.Irq.SharedExclusive)
310    {
311        *Buffer = 0x22;
312        IRQInfoByteNeeded = FALSE;
313    }
314    else
315    {
316        *Buffer = 0x23;
317        IRQInfoByteNeeded = TRUE;
318    }
319
320    Buffer += 1;
321    Temp16 = 0;
322
323    /*
324     * Loop through all of the interrupts and set the mask bits
325     */
326    for(Index = 0;
327        Index < LinkedList->Data.Irq.NumberOfInterrupts;
328        Index++)
329    {
330        Temp8 = (UINT8) LinkedList->Data.Irq.Interrupts[Index];
331        Temp16 |= 0x1 << Temp8;
332    }
333
334    MOVE_UNALIGNED16_TO_16 (Buffer, &Temp16);
335    Buffer += 2;
336
337    /*
338     * Set the IRQ Info byte if needed.
339     */
340    if (IRQInfoByteNeeded)
341    {
342        Temp8 = 0;
343        Temp8 = (UINT8) ((LinkedList->Data.Irq.SharedExclusive &
344                          0x01) << 4);
345
346        if (LEVEL_SENSITIVE == LinkedList->Data.Irq.EdgeLevel &&
347            ACTIVE_LOW == LinkedList->Data.Irq.ActiveHighLow)
348        {
349            Temp8 |= 0x08;
350        }
351
352        else
353        {
354            Temp8 |= 0x01;
355        }
356
357        *Buffer = Temp8;
358        Buffer += 1;
359    }
360
361    /*
362     * Return the number of bytes consumed in this operation
363     */
364    *BytesConsumed = (UINT32) ((NATIVE_UINT) Buffer -
365                     (NATIVE_UINT) *OutputBuffer);
366
367    return_ACPI_STATUS (AE_OK);
368}
369
370
371/*******************************************************************************
372 *
373 * FUNCTION:    AcpiRsExtendedIrqResource
374 *
375 * PARAMETERS:  ByteStreamBuffer        - Pointer to the resource input byte
376 *                                          stream
377 *              BytesConsumed           - UINT32 pointer that is filled with
378 *                                          the number of bytes consumed from
379 *                                          the ByteStreamBuffer
380 *              OutputBuffer            - Pointer to the user's return buffer
381 *              StructureSize           - UINT32 pointer that is filled with
382 *                                          the number of bytes in the filled
383 *                                          in structure
384 *
385 * RETURN:      Status  AE_OK if okay, else a valid ACPI_STATUS code
386 *
387 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
388 *                  structure pointed to by the OutputBuffer.  Return the
389 *                  number of bytes consumed from the byte stream.
390 *
391 ******************************************************************************/
392
393ACPI_STATUS
394AcpiRsExtendedIrqResource (
395    UINT8                   *ByteStreamBuffer,
396    UINT32                  *BytesConsumed,
397    UINT8                   **OutputBuffer,
398    UINT32                  *StructureSize)
399{
400    UINT8                   *Buffer = ByteStreamBuffer;
401    RESOURCE                *OutputStruct = (RESOURCE *) * OutputBuffer;
402    UINT16                  Temp16 = 0;
403    UINT8                   Temp8 = 0;
404    UINT8                   Index;
405    UINT32                  StructSize = sizeof (EXTENDED_IRQ_RESOURCE) +
406                                         RESOURCE_LENGTH_NO_DATA;
407
408
409    FUNCTION_TRACE ("RsExtendedIrqResource");
410
411    /*
412     * Point past the Descriptor to get the number of bytes consumed
413     */
414    Buffer += 1;
415    MOVE_UNALIGNED16_TO_16 (&Temp16, Buffer);
416
417    *BytesConsumed = Temp16 + 3;
418    OutputStruct->Id = ExtendedIrq;
419
420    /*
421     * Point to the Byte3
422     */
423    Buffer += 2;
424    Temp8 = *Buffer;
425
426    OutputStruct->Data.ExtendedIrq.ProducerConsumer = Temp8 & 0x01;
427
428    /*
429     * Check for HE, LL or HL
430     */
431    if(Temp8 & 0x02)
432    {
433        OutputStruct->Data.ExtendedIrq.EdgeLevel = EDGE_SENSITIVE;
434        OutputStruct->Data.ExtendedIrq.ActiveHighLow = ACTIVE_HIGH;
435    }
436
437    else
438    {
439        if(Temp8 & 0x4)
440        {
441            OutputStruct->Data.ExtendedIrq.EdgeLevel = LEVEL_SENSITIVE;
442            OutputStruct->Data.ExtendedIrq.ActiveHighLow = ACTIVE_LOW;
443        }
444
445        else
446        {
447            /*
448             * Only _LL and _HE polarity/trigger interrupts
449             *  are allowed (ACPI spec v1.0b ection 6.4.2.1),
450             *  so an error will occur if we reach this point
451             */
452            return_ACPI_STATUS (AE_BAD_DATA);
453        }
454    }
455
456    /*
457     * Check for sharable
458     */
459    OutputStruct->Data.ExtendedIrq.SharedExclusive =
460            (Temp8 >> 3) & 0x01;
461
462    /*
463     * Point to Byte4 (IRQ Table length)
464     */
465    Buffer += 1;
466    Temp8 = *Buffer;
467
468    OutputStruct->Data.ExtendedIrq.NumberOfInterrupts = Temp8;
469
470    /*
471     * Add any additional structure size to properly calculate
472     *  the next pointer at the end of this function
473     */
474     StructSize += (Temp8 - 1) * 4;
475
476    /*
477     * Point to Byte5 (First IRQ Number)
478     */
479    Buffer += 1;
480
481    /*
482     * Cycle through every IRQ in the table
483     */
484    for (Index = 0; Index < Temp8; Index++)
485    {
486        OutputStruct->Data.ExtendedIrq.Interrupts[Index] =
487                (UINT32)*Buffer;
488
489        /* Point to the next IRQ */
490
491        Buffer += 4;
492    }
493
494    /*
495     * This will leave us pointing to the Resource Source Index
496     *  If it is present, then save it off and calculate the
497     *  pointer to where the null terminated string goes:
498     *  Each Interrupt takes 32-bits + the 5 bytes of the
499     *  stream that are default.
500     */
501    if (*BytesConsumed >
502        (UINT32)(OutputStruct->Data.ExtendedIrq.NumberOfInterrupts *
503         4) + 5)
504    {
505        /* Dereference the Index */
506
507        Temp8 = *Buffer;
508        OutputStruct->Data.ExtendedIrq.ResourceSourceIndex =
509                (UINT32)Temp8;
510
511        /* Point to the String */
512
513        Buffer += 1;
514
515        /* Copy the string into the buffer */
516
517        Index = 0;
518
519        while (0x00 != *Buffer)
520        {
521            OutputStruct->Data.ExtendedIrq.ResourceSource[Index] =
522                    *Buffer;
523
524            Buffer += 1;
525            Index += 1;
526        }
527
528        /*
529         * Add the terminating null
530         */
531        OutputStruct->Data.ExtendedIrq.ResourceSource[Index] = 0x00;
532        OutputStruct->Data.ExtendedIrq.ResourceSourceStringLength =
533                Index + 1;
534
535        /*
536         * In order for the StructSize to fall on a 32-bit boundry,
537         *  calculate the length of the string and expand the
538         *  StructSize to the next 32-bit boundry.
539         */
540        Temp8 = (UINT8) (Index + 1);
541        Temp8 = (UINT8) ROUND_UP_TO_32BITS (Temp8);
542    }
543
544    else
545    {
546        OutputStruct->Data.ExtendedIrq.ResourceSourceIndex = 0x00;
547        OutputStruct->Data.ExtendedIrq.ResourceSourceStringLength = 0;
548        OutputStruct->Data.ExtendedIrq.ResourceSource[0] = 0x00;
549    }
550
551    /*
552     * Set the Length parameter
553     */
554    OutputStruct->Length = StructSize;
555
556    /*
557     * Return the final size of the structure
558     */
559    *StructureSize = StructSize;
560
561    return_ACPI_STATUS (AE_OK);
562}
563
564
565/*******************************************************************************
566 *
567 * FUNCTION:    AcpiRsExtendedIrqStream
568 *
569 * PARAMETERS:  LinkedList              - Pointer to the resource linked list
570 *              OutputBuffer            - Pointer to the user's return buffer
571 *              BytesConsumed           - UINT32 pointer that is filled with
572 *                                          the number of bytes of the
573 *                                          OutputBuffer used
574 *
575 * RETURN:      Status  AE_OK if okay, else a valid ACPI_STATUS code
576 *
577 * DESCRIPTION: Take the linked list resource structure and fills in the
578 *              the appropriate bytes in a byte stream
579 *
580 ******************************************************************************/
581
582ACPI_STATUS
583AcpiRsExtendedIrqStream (
584    RESOURCE                *LinkedList,
585    UINT8                   **OutputBuffer,
586    UINT32                  *BytesConsumed)
587{
588    UINT8                   *Buffer = *OutputBuffer;
589    UINT16                  *LengthField;
590    UINT8                   Temp8 = 0;
591    UINT8                   Index;
592    NATIVE_CHAR             *TempPointer = NULL;
593
594
595    FUNCTION_TRACE ("RsExtendedIrqStream");
596
597
598    /*
599     * The descriptor field is static
600     */
601    *Buffer = 0x89;
602    Buffer += 1;
603
604    /*
605     * Set a pointer to the Length field - to be filled in later
606     */
607
608    LengthField = (UINT16 *)Buffer;
609    Buffer += 2;
610
611    /*
612     * Set the Interrupt vector flags
613     */
614    Temp8 = (UINT8)(LinkedList->Data.ExtendedIrq.ProducerConsumer & 0x01);
615
616    Temp8 |= ((LinkedList->Data.ExtendedIrq.SharedExclusive & 0x01) << 3);
617
618    if (LEVEL_SENSITIVE == LinkedList->Data.ExtendedIrq.EdgeLevel &&
619       ACTIVE_LOW == LinkedList->Data.ExtendedIrq.ActiveHighLow)
620    {
621        Temp8 |= 0x04;
622    }
623    else
624    {
625        Temp8 |= 0x02;
626    }
627
628    *Buffer = Temp8;
629    Buffer += 1;
630
631    /*
632     * Set the Interrupt table length
633     */
634    Temp8 = (UINT8) LinkedList->Data.ExtendedIrq.NumberOfInterrupts;
635
636    *Buffer = Temp8;
637    Buffer += 1;
638
639    for (Index = 0;
640         Index < LinkedList->Data.ExtendedIrq.NumberOfInterrupts;
641         Index++)
642    {
643        MOVE_UNALIGNED32_TO_32 (Buffer,
644                        &LinkedList->Data.ExtendedIrq.Interrupts[Index]);
645        Buffer += 4;
646    }
647
648    /*
649     * Resource Source Index and Resource Source are optional
650     */
651    if (0 != LinkedList->Data.ExtendedIrq.ResourceSourceStringLength)
652    {
653        *Buffer = (UINT8) LinkedList->Data.ExtendedIrq.ResourceSourceIndex;
654        Buffer += 1;
655
656        TempPointer = (NATIVE_CHAR *) Buffer;
657
658        /*
659         * Copy the string
660         */
661        STRCPY (TempPointer, LinkedList->Data.ExtendedIrq.ResourceSource);
662
663        /*
664         * Buffer needs to be set to the length of the sting + one for the
665         *  terminating null
666         */
667        Buffer += (STRLEN (LinkedList->Data.ExtendedIrq.ResourceSource) + 1);
668    }
669
670    /*
671     * Return the number of bytes consumed in this operation
672     */
673    *BytesConsumed = (UINT32) ((NATIVE_UINT) Buffer -
674                     (NATIVE_UINT) *OutputBuffer);
675
676    /*
677     * Set the length field to the number of bytes consumed
678     *  minus the header size (3 bytes)
679     */
680    *LengthField = (UINT16) (*BytesConsumed - 3);
681
682    return_ACPI_STATUS (AE_OK);
683}
684
685