Merge with 2.4.0-test3-pre4.
[linux-2.6/linux-mips.git] / drivers / acpi / resources / rsirq.c
blob964d126e2be9aec34a45ff5673e3cbf82e7719ef
1 /******************************************************************************
3 * Module Name: rsirq - Acpi_rs_irq_resource,
4 * Acpi_rs_irq_stream
5 * Acpi_rs_extended_irq_resource
6 * Acpi_rs_extended_irq_stream
8 *****************************************************************************/
11 * Copyright (C) 2000 R. Byron Moore
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "acpi.h"
31 #define _COMPONENT RESOURCE_MANAGER
32 MODULE_NAME ("rsirq");
35 /***************************************************************************
36 * FUNCTION: Acpi_rs_irq_resource
38 * PARAMETERS:
39 * Byte_stream_buffer - Pointer to the resource input byte
40 * stream
41 * Bytes_consumed - u32 pointer that is filled with
42 * the number of bytes consumed from
43 * the Byte_stream_buffer
44 * Output_buffer - Pointer to the user's return buffer
45 * Structure_size - u32 pointer that is filled with
46 * the number of bytes in the filled
47 * in structure
49 * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code
51 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
52 * structure pointed to by the Output_buffer. Return the
53 * number of bytes consumed from the byte stream.
55 ***************************************************************************/
57 ACPI_STATUS
58 acpi_rs_irq_resource (
59 u8 *byte_stream_buffer,
60 u32 *bytes_consumed,
61 u8 **output_buffer,
62 u32 *structure_size)
64 u8 *buffer = byte_stream_buffer;
65 RESOURCE *output_struct = (RESOURCE *) * output_buffer;
66 u16 temp16 = 0;
67 u8 temp8 = 0;
68 u8 index;
69 u8 i;
70 u32 struct_size = sizeof (IRQ_RESOURCE) +
71 RESOURCE_LENGTH_NO_DATA;
75 * The number of bytes consumed are contained in the descriptor
76 * (Bits:0-1)
78 temp8 = *buffer;
80 *bytes_consumed = (temp8 & 0x03) + 1;
82 output_struct->id = irq;
85 * Point to the 16-bits of Bytes 1 and 2
87 buffer += 1;
88 temp16 = *(u16 *)buffer;
90 output_struct->data.irq.number_of_interrupts = 0;
92 /* Decode the IRQ bits */
93 for (i = 0, index = 0; index < 16; index++) {
94 if((temp16 >> index) & 0x01) {
95 output_struct->data.irq.interrupts[i] = index;
96 i++;
99 output_struct->data.irq.number_of_interrupts = i;
102 * Calculate the structure size based upon the number of interrupts
104 struct_size += (output_struct->data.irq.number_of_interrupts - 1) * 4;
107 * Point to Byte 3 if it is used
109 if (4 == *bytes_consumed) {
110 buffer += 2;
112 temp8 = *buffer;
115 * Check for HE, LL or HL
117 if (temp8 & 0x01) {
118 output_struct->data.irq.edge_level = EDGE_SENSITIVE;
119 output_struct->data.irq.active_high_low = ACTIVE_HIGH;
122 else {
123 if (temp8 & 0x8) {
124 output_struct->data.irq.edge_level = LEVEL_SENSITIVE;
125 output_struct->data.irq.active_high_low = ACTIVE_LOW;
128 else {
130 * Only _LL and _HE polarity/trigger interrupts
131 * are allowed (ACPI spec v1.0b ection 6.4.2.1),
132 * so an error will occur if we reach this point
134 return (AE_BAD_DATA);
139 * Check for sharable
141 output_struct->data.irq.shared_exclusive = (temp8 >> 3) & 0x01;
144 else {
146 * Assume Edge Sensitive, Active High, Non-Sharable
147 * per ACPI Specification
149 output_struct->data.irq.edge_level = EDGE_SENSITIVE;
150 output_struct->data.irq.active_high_low = ACTIVE_HIGH;
151 output_struct->data.irq.shared_exclusive = EXCLUSIVE;
155 * Set the Length parameter
157 output_struct->length = struct_size;
160 * Return the final size of the structure
162 *structure_size = struct_size;
164 return (AE_OK);
168 /***************************************************************************
169 * FUNCTION: Acpi_rs_irq_stream
171 * PARAMETERS:
172 * Linked_list - Pointer to the resource linked list
173 * Output_buffer - Pointer to the user's return buffer
174 * Bytes_consumed - u32 pointer that is filled with
175 * the number of bytes of the
176 * Output_buffer used
178 * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code
180 * DESCRIPTION: Take the linked list resource structure and fills in the
181 * the appropriate bytes in a byte stream
183 ***************************************************************************/
185 ACPI_STATUS
186 acpi_rs_irq_stream (
187 RESOURCE *linked_list,
188 u8 **output_buffer,
189 u32 *bytes_consumed)
191 u8 *buffer = *output_buffer;
192 u16 temp16 = 0;
193 u8 temp8 = 0;
194 u8 index;
195 u8 IRQinfo_byte_needed;
199 * The descriptor field is set based upon whether a third byte is
200 * needed to contain the IRQ Information.
202 if (EDGE_SENSITIVE == linked_list->data.irq.edge_level &&
203 ACTIVE_HIGH == linked_list->data.irq.active_high_low &&
204 EXCLUSIVE == linked_list->data.irq.shared_exclusive)
206 *buffer = 0x22;
207 IRQinfo_byte_needed = FALSE;
209 else {
210 *buffer = 0x23;
211 IRQinfo_byte_needed = TRUE;
214 buffer += 1;
216 temp16 = 0;
219 * Loop through all of the interrupts and set the mask bits
221 for(index = 0;
222 index < linked_list->data.irq.number_of_interrupts;
223 index++)
225 temp8 = (u8) linked_list->data.irq.interrupts[index];
226 temp16 |= 0x1 << temp8;
229 *(u16 *)buffer = temp16;
231 buffer += 2;
234 * Set the IRQ Info byte if needed.
236 if (IRQinfo_byte_needed) {
237 temp8 = 0;
239 temp8 = (u8) ((linked_list->data.irq.shared_exclusive &
240 0x01) << 4);
242 if (LEVEL_SENSITIVE == linked_list->data.irq.edge_level &&
243 ACTIVE_LOW == linked_list->data.irq.active_high_low)
245 temp8 |= 0x08;
248 else {
249 temp8 |= 0x01;
252 *buffer = temp8;
254 buffer += 1;
258 * Return the number of bytes consumed in this operation
260 *bytes_consumed = (u32) ((NATIVE_UINT) buffer -
261 (NATIVE_UINT) *output_buffer);
263 return (AE_OK);
267 /***************************************************************************
268 * FUNCTION: Acpi_rs_extended_irq_resource
270 * PARAMETERS:
271 * Byte_stream_buffer - Pointer to the resource input byte
272 * stream
273 * Bytes_consumed - u32 pointer that is filled with
274 * the number of bytes consumed from
275 * the Byte_stream_buffer
276 * Output_buffer - Pointer to the user's return buffer
277 * Structure_size - u32 pointer that is filled with
278 * the number of bytes in the filled
279 * in structure
281 * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code
283 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
284 * structure pointed to by the Output_buffer. Return the
285 * number of bytes consumed from the byte stream.
287 ***************************************************************************/
289 ACPI_STATUS
290 acpi_rs_extended_irq_resource (
291 u8 *byte_stream_buffer,
292 u32 *bytes_consumed,
293 u8 **output_buffer,
294 u32 *structure_size)
296 u8 *buffer = byte_stream_buffer;
297 RESOURCE *output_struct = (RESOURCE *) * output_buffer;
298 u16 temp16 = 0;
299 u8 temp8 = 0;
300 u8 index;
301 u32 struct_size = sizeof (EXTENDED_IRQ_RESOURCE) +
302 RESOURCE_LENGTH_NO_DATA;
306 * Point past the Descriptor to get the number of bytes consumed
308 buffer += 1;
309 temp16 = *(u16 *)buffer;
311 *bytes_consumed = temp16 + 3;
312 output_struct->id = extended_irq;
315 * Point to the Byte3
317 buffer += 2;
318 temp8 = *buffer;
320 output_struct->data.extended_irq.producer_consumer = temp8 & 0x01;
323 * Check for HE, LL or HL
325 if(temp8 & 0x02) {
326 output_struct->data.extended_irq.edge_level = EDGE_SENSITIVE;
327 output_struct->data.extended_irq.active_high_low = ACTIVE_HIGH;
330 else {
331 if(temp8 & 0x4) {
332 output_struct->data.extended_irq.edge_level = LEVEL_SENSITIVE;
333 output_struct->data.extended_irq.active_high_low = ACTIVE_LOW;
336 else {
338 * Only _LL and _HE polarity/trigger interrupts
339 * are allowed (ACPI spec v1.0b ection 6.4.2.1),
340 * so an error will occur if we reach this point
342 return (AE_BAD_DATA);
347 * Check for sharable
349 output_struct->data.extended_irq.shared_exclusive =
350 (temp8 >> 3) & 0x01;
353 * Point to Byte4 (IRQ Table length)
355 buffer += 1;
356 temp8 = *buffer;
358 output_struct->data.extended_irq.number_of_interrupts = temp8;
361 * Add any additional structure size to properly calculate
362 * the next pointer at the end of this function
364 struct_size += (temp8 - 1) * 4;
367 * Point to Byte5 (First IRQ Number)
369 buffer += 1;
372 * Cycle through every IRQ in the table
374 for (index = 0; index < temp8; index++) {
375 output_struct->data.extended_irq.interrupts[index] =
376 (u32)*buffer;
378 /* Point to the next IRQ */
380 buffer += 4;
384 * This will leave us pointing to the Resource Source Index
385 * If it is present, then save it off and calculate the
386 * pointer to where the null terminated string goes:
387 * Each Interrupt takes 32-bits + the 5 bytes of the
388 * stream that are default.
390 if (*bytes_consumed >
391 (u32)(output_struct->data.extended_irq.number_of_interrupts *
392 4) + 5)
394 /* Dereference the Index */
396 temp8 = *buffer;
397 output_struct->data.extended_irq.resource_source_index =
398 (u32)temp8;
400 /* Point to the String */
402 buffer += 1;
404 /* Copy the string into the buffer */
406 index = 0;
408 while (0x00 != *buffer) {
409 output_struct->data.extended_irq.resource_source[index] =
410 *buffer;
412 buffer += 1;
413 index += 1;
417 * Add the terminating null
419 output_struct->data.extended_irq.resource_source[index] = 0x00;
420 output_struct->data.extended_irq.resource_source_string_length =
421 index + 1;
424 * In order for the Struct_size to fall on a 32-bit boundry,
425 * calculate the length of the string and expand the
426 * Struct_size to the next 32-bit boundry.
428 temp8 = (u8) (index + 1);
429 temp8 = (u8) ROUND_UP_TO_32_bITS (temp8);
432 else {
433 output_struct->data.extended_irq.resource_source_index = 0x00;
434 output_struct->data.extended_irq.resource_source_string_length = 0;
435 output_struct->data.extended_irq.resource_source[0] = 0x00;
439 * Set the Length parameter
441 output_struct->length = struct_size;
444 * Return the final size of the structure
446 *structure_size = struct_size;
448 return (AE_OK);
452 /***************************************************************************
453 * FUNCTION: Acpi_rs_extended_irq_stream
455 * PARAMETERS:
456 * Linked_list - Pointer to the resource linked list
457 * Output_buffer - Pointer to the user's return buffer
458 * Bytes_consumed - u32 pointer that is filled with
459 * the number of bytes of the
460 * Output_buffer used
462 * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code
464 * DESCRIPTION: Take the linked list resource structure and fills in the
465 * the appropriate bytes in a byte stream
467 ***************************************************************************/
469 ACPI_STATUS
470 acpi_rs_extended_irq_stream (
471 RESOURCE *linked_list,
472 u8 **output_buffer,
473 u32 *bytes_consumed)
475 u8 *buffer = *output_buffer;
476 u16 *length_field;
477 u8 temp8 = 0;
478 u8 index;
479 u8 *temp_pointer = NULL;
483 * The descriptor field is static
485 *buffer = 0x89;
486 buffer += 1;
489 * Set a pointer to the Length field - to be filled in later
492 length_field = (u16 *)buffer;
493 buffer += 2;
496 * Set the Interrupt vector flags
498 temp8 = (u8)(linked_list->data.extended_irq.producer_consumer & 0x01);
500 temp8 |= ((linked_list->data.extended_irq.shared_exclusive & 0x01) << 3);
502 if (LEVEL_SENSITIVE == linked_list->data.extended_irq.edge_level &&
503 ACTIVE_LOW == linked_list->data.extended_irq.active_high_low)
505 temp8 |= 0x04;
507 else {
508 temp8 |= 0x02;
511 *buffer = temp8;
512 buffer += 1;
515 * Set the Interrupt table length
517 temp8 = (u8) linked_list->data.extended_irq.number_of_interrupts;
519 *buffer = temp8;
521 buffer += 1;
523 for (index = 0;
524 index < linked_list->data.extended_irq.number_of_interrupts;
525 index++)
527 MOVE_UNALIGNED32_TO_32 (buffer,
528 &linked_list->data.extended_irq.interrupts[index]);
529 buffer += 4;
533 * Resource Source Index and Resource Source are optional
535 if (0 != linked_list->data.extended_irq.resource_source_string_length) {
536 temp8 = (u8) linked_list->data.extended_irq.resource_source_index;
538 *buffer = temp8;
539 buffer += 1;
540 temp_pointer = buffer;
543 * Copy the string
545 STRCPY (temp_pointer, linked_list->data.extended_irq.resource_source);
548 * Buffer needs to be set to the length of the sting + one for the
549 * terminating null
551 buffer += (STRLEN (linked_list->data.extended_irq.resource_source) + 1);
555 * Return the number of bytes consumed in this operation
557 *bytes_consumed = (u32) ((NATIVE_UINT) buffer -
558 (NATIVE_UINT) *output_buffer);
561 * Set the length field to the number of bytes consumed
562 * minus the header size (3 bytes)
564 *length_field = (u16) (*bytes_consumed - 3);
566 return (AE_OK);