PageRenderTime 37ms CodeModel.GetById 12ms app.highlight 20ms RepoModel.GetById 2ms app.codeStats 0ms

/drivers/acpi/resources/rsirq.c

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