[ACPI] Lindent all ACPI files
[linux-2.6-microblaze.git] / drivers / acpi / resources / rsirq.c
1 /*******************************************************************************
2  *
3  * Module Name: rsirq - IRQ resource descriptors
4  *
5  ******************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2005, 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/acresrc.h>
46
47 #define _COMPONENT          ACPI_RESOURCES
48 ACPI_MODULE_NAME("rsirq")
49
50 /*******************************************************************************
51  *
52  * FUNCTION:    acpi_rs_irq_resource
53  *
54  * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
55  *                                        stream
56  *              bytes_consumed          - Pointer to where the number of bytes
57  *                                        consumed the byte_stream_buffer is
58  *                                        returned
59  *              output_buffer           - Pointer to the return data buffer
60  *              structure_size          - Pointer to where the number of bytes
61  *                                        in the return data struct is returned
62  *
63  * RETURN:      Status
64  *
65  * DESCRIPTION: Take the resource byte stream and fill out the appropriate
66  *              structure pointed to by the output_buffer. Return the
67  *              number of bytes consumed from the byte stream.
68  *
69  ******************************************************************************/
70 acpi_status
71 acpi_rs_irq_resource(u8 * byte_stream_buffer,
72                      acpi_size * bytes_consumed,
73                      u8 ** output_buffer, acpi_size * structure_size)
74 {
75         u8 *buffer = byte_stream_buffer;
76         struct acpi_resource *output_struct = (void *)*output_buffer;
77         u16 temp16 = 0;
78         u8 temp8 = 0;
79         u8 index;
80         u8 i;
81         acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_irq);
82
83         ACPI_FUNCTION_TRACE("rs_irq_resource");
84
85         /*
86          * The number of bytes consumed are contained in the descriptor
87          * (Bits:0-1)
88          */
89         temp8 = *buffer;
90         *bytes_consumed = (temp8 & 0x03) + 1;
91         output_struct->id = ACPI_RSTYPE_IRQ;
92
93         /* Point to the 16-bits of Bytes 1 and 2 */
94
95         buffer += 1;
96         ACPI_MOVE_16_TO_16(&temp16, buffer);
97
98         output_struct->data.irq.number_of_interrupts = 0;
99
100         /* Decode the IRQ bits */
101
102         for (i = 0, index = 0; index < 16; index++) {
103                 if ((temp16 >> index) & 0x01) {
104                         output_struct->data.irq.interrupts[i] = index;
105                         i++;
106                 }
107         }
108
109         /* Zero interrupts is valid */
110
111         output_struct->data.irq.number_of_interrupts = i;
112         if (i > 0) {
113                 /* Calculate the structure size based upon the number of interrupts */
114
115                 struct_size += ((acpi_size) i - 1) * 4;
116         }
117
118         /* Point to Byte 3 if it is used */
119
120         if (4 == *bytes_consumed) {
121                 buffer += 2;
122                 temp8 = *buffer;
123
124                 /* Check for HE, LL interrupts */
125
126                 switch (temp8 & 0x09) {
127                 case 0x01:      /* HE */
128                         output_struct->data.irq.edge_level =
129                             ACPI_EDGE_SENSITIVE;
130                         output_struct->data.irq.active_high_low =
131                             ACPI_ACTIVE_HIGH;
132                         break;
133
134                 case 0x08:      /* LL */
135                         output_struct->data.irq.edge_level =
136                             ACPI_LEVEL_SENSITIVE;
137                         output_struct->data.irq.active_high_low =
138                             ACPI_ACTIVE_LOW;
139                         break;
140
141                 default:
142                         /*
143                          * Only _LL and _HE polarity/trigger interrupts
144                          * are allowed (ACPI spec, section "IRQ Format")
145                          * so 0x00 and 0x09 are illegal.
146                          */
147                         ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
148                                           "Invalid interrupt polarity/trigger in resource list, %X\n",
149                                           temp8));
150                         return_ACPI_STATUS(AE_BAD_DATA);
151                 }
152
153                 /* Check for sharable */
154
155                 output_struct->data.irq.shared_exclusive = (temp8 >> 3) & 0x01;
156         } else {
157                 /*
158                  * Assume Edge Sensitive, Active High, Non-Sharable
159                  * per ACPI Specification
160                  */
161                 output_struct->data.irq.edge_level = ACPI_EDGE_SENSITIVE;
162                 output_struct->data.irq.active_high_low = ACPI_ACTIVE_HIGH;
163                 output_struct->data.irq.shared_exclusive = ACPI_EXCLUSIVE;
164         }
165
166         /* Set the Length parameter */
167
168         output_struct->length = (u32) struct_size;
169
170         /* Return the final size of the structure */
171
172         *structure_size = struct_size;
173         return_ACPI_STATUS(AE_OK);
174 }
175
176 /*******************************************************************************
177  *
178  * FUNCTION:    acpi_rs_irq_stream
179  *
180  * PARAMETERS:  linked_list             - Pointer to the resource linked list
181  *              output_buffer           - Pointer to the user's return buffer
182  *              bytes_consumed          - Pointer to where the number of bytes
183  *                                        used in the output_buffer is returned
184  *
185  * RETURN:      Status
186  *
187  * DESCRIPTION: Take the linked list resource structure and fills in the
188  *              the appropriate bytes in a byte stream
189  *
190  ******************************************************************************/
191
192 acpi_status
193 acpi_rs_irq_stream(struct acpi_resource *linked_list,
194                    u8 ** output_buffer, acpi_size * bytes_consumed)
195 {
196         u8 *buffer = *output_buffer;
197         u16 temp16 = 0;
198         u8 temp8 = 0;
199         u8 index;
200         u8 IRqinfo_byte_needed;
201
202         ACPI_FUNCTION_TRACE("rs_irq_stream");
203
204         /*
205          * The descriptor field is set based upon whether a third byte is
206          * needed to contain the IRQ Information.
207          */
208         if (ACPI_EDGE_SENSITIVE == linked_list->data.irq.edge_level &&
209             ACPI_ACTIVE_HIGH == linked_list->data.irq.active_high_low &&
210             ACPI_EXCLUSIVE == linked_list->data.irq.shared_exclusive) {
211                 *buffer = 0x22;
212                 IRqinfo_byte_needed = FALSE;
213         } else {
214                 *buffer = 0x23;
215                 IRqinfo_byte_needed = TRUE;
216         }
217
218         buffer += 1;
219         temp16 = 0;
220
221         /* Loop through all of the interrupts and set the mask bits */
222
223         for (index = 0;
224              index < linked_list->data.irq.number_of_interrupts; index++) {
225                 temp8 = (u8) linked_list->data.irq.interrupts[index];
226                 temp16 |= 0x1 << temp8;
227         }
228
229         ACPI_MOVE_16_TO_16(buffer, &temp16);
230         buffer += 2;
231
232         /* Set the IRQ Info byte if needed. */
233
234         if (IRqinfo_byte_needed) {
235                 temp8 = 0;
236                 temp8 = (u8) ((linked_list->data.irq.shared_exclusive &
237                                0x01) << 4);
238
239                 if (ACPI_LEVEL_SENSITIVE == linked_list->data.irq.edge_level &&
240                     ACPI_ACTIVE_LOW == linked_list->data.irq.active_high_low) {
241                         temp8 |= 0x08;
242                 } else {
243                         temp8 |= 0x01;
244                 }
245
246                 *buffer = temp8;
247                 buffer += 1;
248         }
249
250         /* Return the number of bytes consumed in this operation */
251
252         *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
253         return_ACPI_STATUS(AE_OK);
254 }
255
256 /*******************************************************************************
257  *
258  * FUNCTION:    acpi_rs_extended_irq_resource
259  *
260  * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
261  *                                        stream
262  *              bytes_consumed          - Pointer to where the number of bytes
263  *                                        consumed the byte_stream_buffer is
264  *                                        returned
265  *              output_buffer           - Pointer to the return data buffer
266  *              structure_size          - Pointer to where the number of bytes
267  *                                        in the return data struct is returned
268  *
269  * RETURN:      Status
270  *
271  * DESCRIPTION: Take the resource byte stream and fill out the appropriate
272  *              structure pointed to by the output_buffer. Return the
273  *              number of bytes consumed from the byte stream.
274  *
275  ******************************************************************************/
276
277 acpi_status
278 acpi_rs_extended_irq_resource(u8 * byte_stream_buffer,
279                               acpi_size * bytes_consumed,
280                               u8 ** output_buffer, acpi_size * structure_size)
281 {
282         u8 *buffer = byte_stream_buffer;
283         struct acpi_resource *output_struct = (void *)*output_buffer;
284         u16 temp16 = 0;
285         u8 temp8 = 0;
286         u8 *temp_ptr;
287         u8 index;
288         acpi_size struct_size =
289             ACPI_SIZEOF_RESOURCE(struct acpi_resource_ext_irq);
290
291         ACPI_FUNCTION_TRACE("rs_extended_irq_resource");
292
293         /* Point past the Descriptor to get the number of bytes consumed */
294
295         buffer += 1;
296         ACPI_MOVE_16_TO_16(&temp16, buffer);
297
298         /* Validate minimum descriptor length */
299
300         if (temp16 < 6) {
301                 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
302         }
303
304         *bytes_consumed = temp16 + 3;
305         output_struct->id = ACPI_RSTYPE_EXT_IRQ;
306
307         /* Point to the Byte3 */
308
309         buffer += 2;
310         temp8 = *buffer;
311
312         output_struct->data.extended_irq.producer_consumer = temp8 & 0x01;
313
314         /*
315          * Check for Interrupt Mode
316          *
317          * The definition of an Extended IRQ changed between ACPI spec v1.0b
318          * and ACPI spec 2.0 (section 6.4.3.6 in both).
319          *
320          * - Edge/Level are defined opposite in the table vs the headers
321          */
322         output_struct->data.extended_irq.edge_level =
323             (temp8 & 0x2) ? ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE;
324
325         /* Check Interrupt Polarity */
326
327         output_struct->data.extended_irq.active_high_low = (temp8 >> 2) & 0x1;
328
329         /* Check for sharable */
330
331         output_struct->data.extended_irq.shared_exclusive = (temp8 >> 3) & 0x01;
332
333         /* Point to Byte4 (IRQ Table length) */
334
335         buffer += 1;
336         temp8 = *buffer;
337
338         /* Must have at least one IRQ */
339
340         if (temp8 < 1) {
341                 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
342         }
343
344         output_struct->data.extended_irq.number_of_interrupts = temp8;
345
346         /*
347          * Add any additional structure size to properly calculate
348          * the next pointer at the end of this function
349          */
350         struct_size += (temp8 - 1) * 4;
351
352         /* Point to Byte5 (First IRQ Number) */
353
354         buffer += 1;
355
356         /* Cycle through every IRQ in the table */
357
358         for (index = 0; index < temp8; index++) {
359                 ACPI_MOVE_32_TO_32(&output_struct->data.extended_irq.
360                                    interrupts[index], buffer);
361
362                 /* Point to the next IRQ */
363
364                 buffer += 4;
365         }
366
367         /*
368          * This will leave us pointing to the Resource Source Index
369          * If it is present, then save it off and calculate the
370          * pointer to where the null terminated string goes:
371          * Each Interrupt takes 32-bits + the 5 bytes of the
372          * stream that are default.
373          *
374          * Note: Some resource descriptors will have an additional null, so
375          * we add 1 to the length.
376          */
377         if (*bytes_consumed >
378             ((acpi_size) output_struct->data.extended_irq.number_of_interrupts *
379              4) + (5 + 1)) {
380                 /* Dereference the Index */
381
382                 temp8 = *buffer;
383                 output_struct->data.extended_irq.resource_source.index =
384                     (u32) temp8;
385
386                 /* Point to the String */
387
388                 buffer += 1;
389
390                 /* Point the String pointer to the end of this structure. */
391
392                 output_struct->data.extended_irq.resource_source.string_ptr =
393                     (char *)((char *)output_struct + struct_size);
394
395                 temp_ptr = (u8 *)
396                     output_struct->data.extended_irq.resource_source.string_ptr;
397
398                 /* Copy the string into the buffer */
399
400                 index = 0;
401                 while (0x00 != *buffer) {
402                         *temp_ptr = *buffer;
403
404                         temp_ptr += 1;
405                         buffer += 1;
406                         index += 1;
407                 }
408
409                 /* Add the terminating null */
410
411                 *temp_ptr = 0x00;
412                 output_struct->data.extended_irq.resource_source.string_length =
413                     index + 1;
414
415                 /*
416                  * In order for the struct_size to fall on a 32-bit boundary,
417                  * calculate the length of the string and expand the
418                  * struct_size to the next 32-bit boundary.
419                  */
420                 temp8 = (u8) (index + 1);
421                 struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
422         } else {
423                 output_struct->data.extended_irq.resource_source.index = 0x00;
424                 output_struct->data.extended_irq.resource_source.string_length =
425                     0;
426                 output_struct->data.extended_irq.resource_source.string_ptr =
427                     NULL;
428         }
429
430         /* Set the Length parameter */
431
432         output_struct->length = (u32) struct_size;
433
434         /* Return the final size of the structure */
435
436         *structure_size = struct_size;
437         return_ACPI_STATUS(AE_OK);
438 }
439
440 /*******************************************************************************
441  *
442  * FUNCTION:    acpi_rs_extended_irq_stream
443  *
444  * PARAMETERS:  linked_list             - Pointer to the resource linked list
445  *              output_buffer           - Pointer to the user's return buffer
446  *              bytes_consumed          - Pointer to where the number of bytes
447  *                                        used in the output_buffer is returned
448  *
449  * RETURN:      Status
450  *
451  * DESCRIPTION: Take the linked list resource structure and fills in the
452  *              the appropriate bytes in a byte stream
453  *
454  ******************************************************************************/
455
456 acpi_status
457 acpi_rs_extended_irq_stream(struct acpi_resource *linked_list,
458                             u8 ** output_buffer, acpi_size * bytes_consumed)
459 {
460         u8 *buffer = *output_buffer;
461         u16 *length_field;
462         u8 temp8 = 0;
463         u8 index;
464         char *temp_pointer = NULL;
465
466         ACPI_FUNCTION_TRACE("rs_extended_irq_stream");
467
468         /* The descriptor field is static */
469
470         *buffer = 0x89;
471         buffer += 1;
472
473         /* Set a pointer to the Length field - to be filled in later */
474
475         length_field = ACPI_CAST_PTR(u16, buffer);
476         buffer += 2;
477
478         /* Set the Interrupt vector flags */
479
480         temp8 = (u8) (linked_list->data.extended_irq.producer_consumer & 0x01);
481         temp8 |=
482             ((linked_list->data.extended_irq.shared_exclusive & 0x01) << 3);
483
484         /*
485          * Set the Interrupt Mode
486          *
487          * The definition of an Extended IRQ changed between ACPI spec v1.0b
488          * and ACPI spec 2.0 (section 6.4.3.6 in both).  This code does not
489          * implement the more restrictive definition of 1.0b
490          *
491          * - Edge/Level are defined opposite in the table vs the headers
492          */
493         if (ACPI_EDGE_SENSITIVE == linked_list->data.extended_irq.edge_level) {
494                 temp8 |= 0x2;
495         }
496
497         /* Set the Interrupt Polarity */
498
499         temp8 |= ((linked_list->data.extended_irq.active_high_low & 0x1) << 2);
500
501         *buffer = temp8;
502         buffer += 1;
503
504         /* Set the Interrupt table length */
505
506         temp8 = (u8) linked_list->data.extended_irq.number_of_interrupts;
507
508         *buffer = temp8;
509         buffer += 1;
510
511         for (index = 0;
512              index < linked_list->data.extended_irq.number_of_interrupts;
513              index++) {
514                 ACPI_MOVE_32_TO_32(buffer,
515                                    &linked_list->data.extended_irq.
516                                    interrupts[index]);
517                 buffer += 4;
518         }
519
520         /* Resource Source Index and Resource Source are optional */
521
522         if (0 != linked_list->data.extended_irq.resource_source.string_length) {
523                 *buffer =
524                     (u8) linked_list->data.extended_irq.resource_source.index;
525                 buffer += 1;
526
527                 temp_pointer = (char *)buffer;
528
529                 /* Copy the string */
530
531                 ACPI_STRCPY(temp_pointer,
532                             linked_list->data.extended_irq.resource_source.
533                             string_ptr);
534
535                 /*
536                  * Buffer needs to be set to the length of the sting + one for the
537                  * terminating null
538                  */
539                 buffer +=
540                     (acpi_size) (ACPI_STRLEN
541                                  (linked_list->data.extended_irq.
542                                   resource_source.string_ptr) + 1);
543         }
544
545         /* Return the number of bytes consumed in this operation */
546
547         *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
548
549         /*
550          * Set the length field to the number of bytes consumed
551          * minus the header size (3 bytes)
552          */
553         *length_field = (u16) (*bytes_consumed - 3);
554         return_ACPI_STATUS(AE_OK);
555 }