make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / drivers / acpi / resources / rsirq.c
1 /*******************************************************************************
2  *
3  * Module Name: rsirq - IRQ resource descriptors
4  *              $Revision: 1.1.1.1 $
5  *
6  ******************************************************************************/
7
8 /*
9  *  Copyright (C) 2000, 2001 R. Byron Moore
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26
27 #include "acpi.h"
28 #include "acresrc.h"
29
30 #define _COMPONENT          ACPI_RESOURCES
31          MODULE_NAME         ("rsirq")
32
33
34 /*******************************************************************************
35  *
36  * FUNCTION:    Acpi_rs_irq_resource
37  *
38  * PARAMETERS:  Byte_stream_buffer      - Pointer to the resource input byte
39  *                                        stream
40  *              Bytes_consumed          - u32 pointer that is filled with
41  *                                        the number of bytes consumed from
42  *                                        the Byte_stream_buffer
43  *              Output_buffer           - Pointer to the user's return buffer
44  *              Structure_size          - u32 pointer that is filled with
45  *                                        the number of bytes in the filled
46  *                                        in structure
47  *
48  * RETURN:      Status
49  *
50  * DESCRIPTION: Take the resource byte stream and fill out the appropriate
51  *              structure pointed to by the Output_buffer. Return the
52  *              number of bytes consumed from the byte stream.
53  *
54  ******************************************************************************/
55
56 acpi_status
57 acpi_rs_irq_resource (
58         u8                      *byte_stream_buffer,
59         u32                     *bytes_consumed,
60         u8                      **output_buffer,
61         u32                     *structure_size)
62 {
63         u8                      *buffer = byte_stream_buffer;
64         acpi_resource           *output_struct = (acpi_resource *) *output_buffer;
65         u16                     temp16 = 0;
66         u8                      temp8 = 0;
67         u8                      index;
68         u8                      i;
69         u32                     struct_size = SIZEOF_RESOURCE (acpi_resource_irq);
70
71
72         FUNCTION_TRACE ("Rs_irq_resource");
73
74
75         /*
76          * The number of bytes consumed are contained in the descriptor
77          *  (Bits:0-1)
78          */
79         temp8 = *buffer;
80         *bytes_consumed = (temp8 & 0x03) + 1;
81         output_struct->id = ACPI_RSTYPE_IRQ;
82
83         /*
84          * Point to the 16-bits of Bytes 1 and 2
85          */
86         buffer += 1;
87         MOVE_UNALIGNED16_TO_16 (&temp16, buffer);
88
89         output_struct->data.irq.number_of_interrupts = 0;
90
91         /* Decode the IRQ bits */
92
93         for (i = 0, index = 0; index < 16; index++) {
94                 if((temp16 >> index) & 0x01) {
95                         output_struct->data.irq.interrupts[i] = index;
96                         i++;
97                 }
98         }
99         output_struct->data.irq.number_of_interrupts = i;
100
101         /*
102          * Calculate the structure size based upon the number of interrupts
103          */
104         struct_size += (output_struct->data.irq.number_of_interrupts - 1) * 4;
105
106         /*
107          * Point to Byte 3 if it is used
108          */
109         if (4 == *bytes_consumed) {
110                 buffer += 2;
111                 temp8 = *buffer;
112
113                 /*
114                  * Check for HE, LL or HL
115                  */
116                 if (temp8 & 0x01) {
117                         output_struct->data.irq.edge_level = EDGE_SENSITIVE;
118                         output_struct->data.irq.active_high_low = ACTIVE_HIGH;
119                 }
120
121                 else {
122                         if (temp8 & 0x8) {
123                                 output_struct->data.irq.edge_level = LEVEL_SENSITIVE;
124                                 output_struct->data.irq.active_high_low = ACTIVE_LOW;
125                         }
126
127                         else {
128                                 /*
129                                  * Only _LL and _HE polarity/trigger interrupts
130                                  * are allowed (ACPI spec v1.0b ection 6.4.2.1),
131                                  * so an error will occur if we reach this point
132                                  */
133                                 return_ACPI_STATUS (AE_BAD_DATA);
134                         }
135                 }
136
137                 /*
138                  * Check for sharable
139                  */
140                 output_struct->data.irq.shared_exclusive = (temp8 >> 3) & 0x01;
141         }
142
143         else {
144                 /*
145                  * Assume Edge Sensitive, Active High, Non-Sharable
146                  * per ACPI Specification
147                  */
148                 output_struct->data.irq.edge_level = EDGE_SENSITIVE;
149                 output_struct->data.irq.active_high_low = ACTIVE_HIGH;
150                 output_struct->data.irq.shared_exclusive = EXCLUSIVE;
151         }
152
153         /*
154          * Set the Length parameter
155          */
156         output_struct->length = struct_size;
157
158         /*
159          * Return the final size of the structure
160          */
161         *structure_size = struct_size;
162         return_ACPI_STATUS (AE_OK);
163 }
164
165
166 /*******************************************************************************
167  *
168  * FUNCTION:    Acpi_rs_irq_stream
169  *
170  * PARAMETERS:  Linked_list             - Pointer to the resource linked list
171  *              Output_buffer           - Pointer to the user's return buffer
172  *              Bytes_consumed          - u32 pointer that is filled with
173  *                                        the number of bytes of the
174  *                                        Output_buffer used
175  *
176  * RETURN:      Status
177  *
178  * DESCRIPTION: Take the linked list resource structure and fills in the
179  *              the appropriate bytes in a byte stream
180  *
181  ******************************************************************************/
182
183 acpi_status
184 acpi_rs_irq_stream (
185         acpi_resource           *linked_list,
186         u8                      **output_buffer,
187         u32                     *bytes_consumed)
188 {
189         u8                      *buffer = *output_buffer;
190         u16                     temp16 = 0;
191         u8                      temp8 = 0;
192         u8                      index;
193         u8                      IRQinfo_byte_needed;
194
195
196         FUNCTION_TRACE ("Rs_irq_stream");
197
198
199         /*
200          * The descriptor field is set based upon whether a third byte is
201          * needed to contain the IRQ Information.
202          */
203         if (EDGE_SENSITIVE == linked_list->data.irq.edge_level &&
204                 ACTIVE_HIGH == linked_list->data.irq.active_high_low &&
205                 EXCLUSIVE == linked_list->data.irq.shared_exclusive) {
206                 *buffer = 0x22;
207                 IRQinfo_byte_needed = FALSE;
208         }
209
210         else {
211                 *buffer = 0x23;
212                 IRQinfo_byte_needed = TRUE;
213         }
214
215         buffer += 1;
216         temp16 = 0;
217
218         /*
219          * Loop through all of the interrupts and set the mask bits
220          */
221         for(index = 0;
222                 index < linked_list->data.irq.number_of_interrupts;
223                 index++) {
224                 temp8 = (u8) linked_list->data.irq.interrupts[index];
225                 temp16 |= 0x1 << temp8;
226         }
227
228         MOVE_UNALIGNED16_TO_16 (buffer, &temp16);
229         buffer += 2;
230
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 (LEVEL_SENSITIVE == linked_list->data.irq.edge_level &&
240                         ACTIVE_LOW == linked_list->data.irq.active_high_low) {
241                         temp8 |= 0x08;
242                 }
243
244                 else {
245                         temp8 |= 0x01;
246                 }
247
248                 *buffer = temp8;
249                 buffer += 1;
250         }
251
252         /*
253          * Return the number of bytes consumed in this operation
254          */
255         *bytes_consumed = POINTER_DIFF (buffer, *output_buffer);
256         return_ACPI_STATUS (AE_OK);
257 }
258
259
260 /*******************************************************************************
261  *
262  * FUNCTION:    Acpi_rs_extended_irq_resource
263  *
264  * PARAMETERS:  Byte_stream_buffer      - Pointer to the resource input byte
265  *                                        stream
266  *              Bytes_consumed          - u32 pointer that is filled with
267  *                                        the number of bytes consumed from
268  *                                        the Byte_stream_buffer
269  *              Output_buffer           - Pointer to the user's return buffer
270  *              Structure_size          - u32 pointer that is filled with
271  *                                        the number of bytes in the filled
272  *                                        in structure
273  *
274  * RETURN:      Status
275  *
276  * DESCRIPTION: Take the resource byte stream and fill out the appropriate
277  *              structure pointed to by the Output_buffer. Return the
278  *              number of bytes consumed from the byte stream.
279  *
280  ******************************************************************************/
281
282 acpi_status
283 acpi_rs_extended_irq_resource (
284         u8                      *byte_stream_buffer,
285         u32                     *bytes_consumed,
286         u8                      **output_buffer,
287         u32                     *structure_size)
288 {
289         u8                      *buffer = byte_stream_buffer;
290         acpi_resource           *output_struct = (acpi_resource *) *output_buffer;
291         u16                     temp16 = 0;
292         u8                      temp8 = 0;
293         NATIVE_CHAR             *temp_ptr;
294         u8                      index;
295         u32                     struct_size = SIZEOF_RESOURCE (acpi_resource_ext_irq);
296
297
298         FUNCTION_TRACE ("Rs_extended_irq_resource");
299
300
301         /*
302          * Point past the Descriptor to get the number of bytes consumed
303          */
304         buffer += 1;
305         MOVE_UNALIGNED16_TO_16 (&temp16, buffer);
306
307         *bytes_consumed = temp16 + 3;
308         output_struct->id = ACPI_RSTYPE_EXT_IRQ;
309
310         /*
311          * Point to the Byte3
312          */
313         buffer += 2;
314         temp8 = *buffer;
315
316         output_struct->data.extended_irq.producer_consumer = temp8 & 0x01;
317
318         /*
319          * Check for HE, LL or HL
320          */
321         if(temp8 & 0x02) {
322                 output_struct->data.extended_irq.edge_level = EDGE_SENSITIVE;
323                 output_struct->data.extended_irq.active_high_low = ACTIVE_HIGH;
324         }
325
326         else {
327                 if(temp8 & 0x4) {
328                         output_struct->data.extended_irq.edge_level = LEVEL_SENSITIVE;
329                         output_struct->data.extended_irq.active_high_low = ACTIVE_LOW;
330                 }
331
332                 else {
333                         /*
334                          * Only _LL and _HE polarity/trigger interrupts
335                          * are allowed (ACPI spec v1.0b ection 6.4.2.1),
336                          * so an error will occur if we reach this point
337                          */
338                         return_ACPI_STATUS (AE_BAD_DATA);
339                 }
340         }
341
342         /*
343          * Check for sharable
344          */
345         output_struct->data.extended_irq.shared_exclusive = (temp8 >> 3) & 0x01;
346
347         /*
348          * Point to Byte4 (IRQ Table length)
349          */
350         buffer += 1;
351         temp8 = *buffer;
352
353         output_struct->data.extended_irq.number_of_interrupts = temp8;
354
355         /*
356          * Add any additional structure size to properly calculate
357          * the next pointer at the end of this function
358          */
359         struct_size += (temp8 - 1) * 4;
360
361         /*
362          * Point to Byte5 (First IRQ Number)
363          */
364         buffer += 1;
365
366         /*
367          * Cycle through every IRQ in the table
368          */
369         for (index = 0; index < temp8; index++) {
370                 output_struct->data.extended_irq.interrupts[index] =
371                                 (u32)*buffer;
372
373                 /* Point to the next IRQ */
374
375                 buffer += 4;
376         }
377
378         /*
379          * This will leave us pointing to the Resource Source Index
380          * If it is present, then save it off and calculate the
381          * pointer to where the null terminated string goes:
382          * Each Interrupt takes 32-bits + the 5 bytes of the
383          * stream that are default.
384          */
385         if (*bytes_consumed >
386                 (u32)(output_struct->data.extended_irq.number_of_interrupts * 4) + 5) {
387                 /* Dereference the Index */
388
389                 temp8 = *buffer;
390                 output_struct->data.extended_irq.resource_source.index = (u32) temp8;
391
392                 /* Point to the String */
393
394                 buffer += 1;
395
396                 /*
397                  * Point the String pointer to the end of this structure.
398                  */
399                 output_struct->data.extended_irq.resource_source.string_ptr =
400                                 (NATIVE_CHAR *)(output_struct + struct_size);
401
402                 temp_ptr = output_struct->data.extended_irq.resource_source.string_ptr;
403
404                 /* Copy the string into the buffer */
405
406                 index = 0;
407
408                 while (0x00 != *buffer) {
409                         *temp_ptr = *buffer;
410
411                         temp_ptr += 1;
412                         buffer += 1;
413                         index += 1;
414                 }
415
416                 /*
417                  * Add the terminating null
418                  */
419                 *temp_ptr = 0x00;
420                 output_struct->data.extended_irq.resource_source.string_length = index + 1;
421
422                 /*
423                  * In order for the Struct_size to fall on a 32-bit boundary,
424                  * calculate the length of the string and expand the
425                  * Struct_size to the next 32-bit boundary.
426                  */
427                 temp8 = (u8) (index + 1);
428                 struct_size += ROUND_UP_TO_32_bITS (temp8);
429         }
430
431         else {
432                 output_struct->data.extended_irq.resource_source.index = 0x00;
433                 output_struct->data.extended_irq.resource_source.string_length = 0;
434                 output_struct->data.extended_irq.resource_source.string_ptr = NULL;
435         }
436
437         /*
438          * Set the Length parameter
439          */
440         output_struct->length = struct_size;
441
442         /*
443          * Return the final size of the structure
444          */
445         *structure_size = struct_size;
446         return_ACPI_STATUS (AE_OK);
447 }
448
449
450 /*******************************************************************************
451  *
452  * FUNCTION:    Acpi_rs_extended_irq_stream
453  *
454  * PARAMETERS:  Linked_list             - Pointer to the resource linked list
455  *              Output_buffer           - Pointer to the user's return buffer
456  *              Bytes_consumed          - u32 pointer that is filled with
457  *                                        the number of bytes of the
458  *                                        Output_buffer used
459  *
460  * RETURN:      Status
461  *
462  * DESCRIPTION: Take the linked list resource structure and fills in the
463  *              the appropriate bytes in a byte stream
464  *
465  ******************************************************************************/
466
467 acpi_status
468 acpi_rs_extended_irq_stream (
469         acpi_resource           *linked_list,
470         u8                      **output_buffer,
471         u32                     *bytes_consumed)
472 {
473         u8                      *buffer = *output_buffer;
474         u16                     *length_field;
475         u8                      temp8 = 0;
476         u8                      index;
477         NATIVE_CHAR             *temp_pointer = NULL;
478
479
480         FUNCTION_TRACE ("Rs_extended_irq_stream");
481
482
483         /*
484          * The descriptor field is static
485          */
486         *buffer = 0x89;
487         buffer += 1;
488
489         /*
490          * Set a pointer to the Length field - to be filled in later
491          */
492         length_field = (u16 *)buffer;
493         buffer += 2;
494
495         /*
496          * Set the Interrupt vector flags
497          */
498         temp8 = (u8)(linked_list->data.extended_irq.producer_consumer & 0x01);
499         temp8 |= ((linked_list->data.extended_irq.shared_exclusive & 0x01) << 3);
500
501         if (LEVEL_SENSITIVE == linked_list->data.extended_irq.edge_level &&
502            ACTIVE_LOW == linked_list->data.extended_irq.active_high_low) {
503                 temp8 |= 0x04;
504         }
505         else {
506                 temp8 |= 0x02;
507         }
508
509         *buffer = temp8;
510         buffer += 1;
511
512         /*
513          * Set the Interrupt table length
514          */
515         temp8 = (u8) linked_list->data.extended_irq.number_of_interrupts;
516
517         *buffer = temp8;
518         buffer += 1;
519
520         for (index = 0; index < linked_list->data.extended_irq.number_of_interrupts;
521                  index++) {
522                 MOVE_UNALIGNED32_TO_32 (buffer,
523                                   &linked_list->data.extended_irq.interrupts[index]);
524                 buffer += 4;
525         }
526
527         /*
528          * Resource Source Index and Resource Source are optional
529          */
530         if (0 != linked_list->data.extended_irq.resource_source.string_length) {
531                 *buffer = (u8) linked_list->data.extended_irq.resource_source.index;
532                 buffer += 1;
533
534                 temp_pointer = (NATIVE_CHAR *) buffer;
535
536                 /*
537                  * Copy the string
538                  */
539                 STRCPY (temp_pointer,
540                         linked_list->data.extended_irq.resource_source.string_ptr);
541
542                 /*
543                  * Buffer needs to be set to the length of the sting + one for the
544                  * terminating null
545                  */
546                 buffer += (STRLEN (linked_list->data.extended_irq.resource_source.string_ptr) + 1);
547         }
548
549         /*
550          * Return the number of bytes consumed in this operation
551          */
552         *bytes_consumed = POINTER_DIFF (buffer, *output_buffer);
553
554         /*
555          * Set the length field to the number of bytes consumed
556          * minus the header size (3 bytes)
557          */
558         *length_field = (u16) (*bytes_consumed - 3);
559         return_ACPI_STATUS (AE_OK);
560 }
561