diff options
Diffstat (limited to 'drivers/acpi/resources/rscalc.c')
-rw-r--r-- | drivers/acpi/resources/rscalc.c | 841 |
1 files changed, 841 insertions, 0 deletions
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c new file mode 100644 index 000000000000..8a5f0a52371d --- /dev/null +++ b/drivers/acpi/resources/rscalc.c | |||
@@ -0,0 +1,841 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * Module Name: rscalc - Calculate stream and list lengths | ||
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 | #include <acpi/amlcode.h> | ||
48 | #include <acpi/acnamesp.h> | ||
49 | |||
50 | #define _COMPONENT ACPI_RESOURCES | ||
51 | ACPI_MODULE_NAME ("rscalc") | ||
52 | |||
53 | |||
54 | /******************************************************************************* | ||
55 | * | ||
56 | * FUNCTION: acpi_rs_get_byte_stream_length | ||
57 | * | ||
58 | * PARAMETERS: linked_list - Pointer to the resource linked list | ||
59 | * size_needed - u32 pointer of the size buffer needed | ||
60 | * to properly return the parsed data | ||
61 | * | ||
62 | * RETURN: Status | ||
63 | * | ||
64 | * DESCRIPTION: Takes the resource byte stream and parses it once, calculating | ||
65 | * the size buffer needed to hold the linked list that conveys | ||
66 | * the resource data. | ||
67 | * | ||
68 | ******************************************************************************/ | ||
69 | |||
70 | acpi_status | ||
71 | acpi_rs_get_byte_stream_length ( | ||
72 | struct acpi_resource *linked_list, | ||
73 | acpi_size *size_needed) | ||
74 | { | ||
75 | acpi_size byte_stream_size_needed = 0; | ||
76 | acpi_size segment_size; | ||
77 | u8 done = FALSE; | ||
78 | |||
79 | |||
80 | ACPI_FUNCTION_TRACE ("rs_get_byte_stream_length"); | ||
81 | |||
82 | |||
83 | while (!done) { | ||
84 | /* | ||
85 | * Init the variable that will hold the size to add to the total. | ||
86 | */ | ||
87 | segment_size = 0; | ||
88 | |||
89 | switch (linked_list->id) { | ||
90 | case ACPI_RSTYPE_IRQ: | ||
91 | /* | ||
92 | * IRQ Resource | ||
93 | * For an IRQ Resource, Byte 3, although optional, will always be | ||
94 | * created - it holds IRQ information. | ||
95 | */ | ||
96 | segment_size = 4; | ||
97 | break; | ||
98 | |||
99 | case ACPI_RSTYPE_DMA: | ||
100 | /* | ||
101 | * DMA Resource | ||
102 | * For this resource the size is static | ||
103 | */ | ||
104 | segment_size = 3; | ||
105 | break; | ||
106 | |||
107 | case ACPI_RSTYPE_START_DPF: | ||
108 | /* | ||
109 | * Start Dependent Functions Resource | ||
110 | * For a start_dependent_functions Resource, Byte 1, although | ||
111 | * optional, will always be created. | ||
112 | */ | ||
113 | segment_size = 2; | ||
114 | break; | ||
115 | |||
116 | case ACPI_RSTYPE_END_DPF: | ||
117 | /* | ||
118 | * End Dependent Functions Resource | ||
119 | * For this resource the size is static | ||
120 | */ | ||
121 | segment_size = 1; | ||
122 | break; | ||
123 | |||
124 | case ACPI_RSTYPE_IO: | ||
125 | /* | ||
126 | * IO Port Resource | ||
127 | * For this resource the size is static | ||
128 | */ | ||
129 | segment_size = 8; | ||
130 | break; | ||
131 | |||
132 | case ACPI_RSTYPE_FIXED_IO: | ||
133 | /* | ||
134 | * Fixed IO Port Resource | ||
135 | * For this resource the size is static | ||
136 | */ | ||
137 | segment_size = 4; | ||
138 | break; | ||
139 | |||
140 | case ACPI_RSTYPE_VENDOR: | ||
141 | /* | ||
142 | * Vendor Defined Resource | ||
143 | * For a Vendor Specific resource, if the Length is between 1 and 7 | ||
144 | * it will be created as a Small Resource data type, otherwise it | ||
145 | * is a Large Resource data type. | ||
146 | */ | ||
147 | if (linked_list->data.vendor_specific.length > 7) { | ||
148 | segment_size = 3; | ||
149 | } | ||
150 | else { | ||
151 | segment_size = 1; | ||
152 | } | ||
153 | segment_size += linked_list->data.vendor_specific.length; | ||
154 | break; | ||
155 | |||
156 | case ACPI_RSTYPE_END_TAG: | ||
157 | /* | ||
158 | * End Tag | ||
159 | * For this resource the size is static | ||
160 | */ | ||
161 | segment_size = 2; | ||
162 | done = TRUE; | ||
163 | break; | ||
164 | |||
165 | case ACPI_RSTYPE_MEM24: | ||
166 | /* | ||
167 | * 24-Bit Memory Resource | ||
168 | * For this resource the size is static | ||
169 | */ | ||
170 | segment_size = 12; | ||
171 | break; | ||
172 | |||
173 | case ACPI_RSTYPE_MEM32: | ||
174 | /* | ||
175 | * 32-Bit Memory Range Resource | ||
176 | * For this resource the size is static | ||
177 | */ | ||
178 | segment_size = 20; | ||
179 | break; | ||
180 | |||
181 | case ACPI_RSTYPE_FIXED_MEM32: | ||
182 | /* | ||
183 | * 32-Bit Fixed Memory Resource | ||
184 | * For this resource the size is static | ||
185 | */ | ||
186 | segment_size = 12; | ||
187 | break; | ||
188 | |||
189 | case ACPI_RSTYPE_ADDRESS16: | ||
190 | /* | ||
191 | * 16-Bit Address Resource | ||
192 | * The base size of this byte stream is 16. If a Resource Source | ||
193 | * string is not NULL, add 1 for the Index + the length of the null | ||
194 | * terminated string Resource Source + 1 for the null. | ||
195 | */ | ||
196 | segment_size = 16; | ||
197 | |||
198 | if (linked_list->data.address16.resource_source.string_ptr) { | ||
199 | segment_size += linked_list->data.address16.resource_source.string_length; | ||
200 | segment_size++; | ||
201 | } | ||
202 | break; | ||
203 | |||
204 | case ACPI_RSTYPE_ADDRESS32: | ||
205 | /* | ||
206 | * 32-Bit Address Resource | ||
207 | * The base size of this byte stream is 26. If a Resource | ||
208 | * Source string is not NULL, add 1 for the Index + the | ||
209 | * length of the null terminated string Resource Source + | ||
210 | * 1 for the null. | ||
211 | */ | ||
212 | segment_size = 26; | ||
213 | |||
214 | if (linked_list->data.address32.resource_source.string_ptr) { | ||
215 | segment_size += linked_list->data.address32.resource_source.string_length; | ||
216 | segment_size++; | ||
217 | } | ||
218 | break; | ||
219 | |||
220 | case ACPI_RSTYPE_ADDRESS64: | ||
221 | /* | ||
222 | * 64-Bit Address Resource | ||
223 | * The base size of this byte stream is 46. If a resource_source | ||
224 | * string is not NULL, add 1 for the Index + the length of the null | ||
225 | * terminated string Resource Source + 1 for the null. | ||
226 | */ | ||
227 | segment_size = 46; | ||
228 | |||
229 | if (linked_list->data.address64.resource_source.string_ptr) { | ||
230 | segment_size += linked_list->data.address64.resource_source.string_length; | ||
231 | segment_size++; | ||
232 | } | ||
233 | break; | ||
234 | |||
235 | case ACPI_RSTYPE_EXT_IRQ: | ||
236 | /* | ||
237 | * Extended IRQ Resource | ||
238 | * The base size of this byte stream is 9. This is for an Interrupt | ||
239 | * table length of 1. For each additional interrupt, add 4. | ||
240 | * If a Resource Source string is not NULL, add 1 for the | ||
241 | * Index + the length of the null terminated string | ||
242 | * Resource Source + 1 for the null. | ||
243 | */ | ||
244 | segment_size = 9 + | ||
245 | (((acpi_size) linked_list->data.extended_irq.number_of_interrupts - 1) * 4); | ||
246 | |||
247 | if (linked_list->data.extended_irq.resource_source.string_ptr) { | ||
248 | segment_size += linked_list->data.extended_irq.resource_source.string_length; | ||
249 | segment_size++; | ||
250 | } | ||
251 | break; | ||
252 | |||
253 | default: | ||
254 | /* | ||
255 | * If we get here, everything is out of sync, exit with error | ||
256 | */ | ||
257 | return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); | ||
258 | |||
259 | } /* switch (linked_list->Id) */ | ||
260 | |||
261 | /* | ||
262 | * Update the total | ||
263 | */ | ||
264 | byte_stream_size_needed += segment_size; | ||
265 | |||
266 | /* | ||
267 | * Point to the next object | ||
268 | */ | ||
269 | linked_list = ACPI_PTR_ADD (struct acpi_resource, | ||
270 | linked_list, linked_list->length); | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | * This is the data the caller needs | ||
275 | */ | ||
276 | *size_needed = byte_stream_size_needed; | ||
277 | return_ACPI_STATUS (AE_OK); | ||
278 | } | ||
279 | |||
280 | |||
281 | /******************************************************************************* | ||
282 | * | ||
283 | * FUNCTION: acpi_rs_get_list_length | ||
284 | * | ||
285 | * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream | ||
286 | * byte_stream_buffer_length - Size of byte_stream_buffer | ||
287 | * size_needed - u32 pointer of the size buffer | ||
288 | * needed to properly return the | ||
289 | * parsed data | ||
290 | * | ||
291 | * RETURN: Status | ||
292 | * | ||
293 | * DESCRIPTION: Takes the resource byte stream and parses it once, calculating | ||
294 | * the size buffer needed to hold the linked list that conveys | ||
295 | * the resource data. | ||
296 | * | ||
297 | ******************************************************************************/ | ||
298 | |||
299 | acpi_status | ||
300 | acpi_rs_get_list_length ( | ||
301 | u8 *byte_stream_buffer, | ||
302 | u32 byte_stream_buffer_length, | ||
303 | acpi_size *size_needed) | ||
304 | { | ||
305 | u32 buffer_size = 0; | ||
306 | u32 bytes_parsed = 0; | ||
307 | u8 number_of_interrupts = 0; | ||
308 | u8 number_of_channels = 0; | ||
309 | u8 resource_type; | ||
310 | u32 structure_size; | ||
311 | u32 bytes_consumed; | ||
312 | u8 *buffer; | ||
313 | u8 temp8; | ||
314 | u16 temp16; | ||
315 | u8 index; | ||
316 | u8 additional_bytes; | ||
317 | |||
318 | |||
319 | ACPI_FUNCTION_TRACE ("rs_get_list_length"); | ||
320 | |||
321 | |||
322 | while (bytes_parsed < byte_stream_buffer_length) { | ||
323 | /* | ||
324 | * The next byte in the stream is the resource type | ||
325 | */ | ||
326 | resource_type = acpi_rs_get_resource_type (*byte_stream_buffer); | ||
327 | |||
328 | switch (resource_type) { | ||
329 | case ACPI_RDESC_TYPE_MEMORY_24: | ||
330 | /* | ||
331 | * 24-Bit Memory Resource | ||
332 | */ | ||
333 | bytes_consumed = 12; | ||
334 | |||
335 | structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem24); | ||
336 | break; | ||
337 | |||
338 | |||
339 | case ACPI_RDESC_TYPE_LARGE_VENDOR: | ||
340 | /* | ||
341 | * Vendor Defined Resource | ||
342 | */ | ||
343 | buffer = byte_stream_buffer; | ||
344 | ++buffer; | ||
345 | |||
346 | ACPI_MOVE_16_TO_16 (&temp16, buffer); | ||
347 | bytes_consumed = temp16 + 3; | ||
348 | |||
349 | /* | ||
350 | * Ensure a 32-bit boundary for the structure | ||
351 | */ | ||
352 | temp16 = (u16) ACPI_ROUND_UP_to_32_bITS (temp16); | ||
353 | |||
354 | structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor) + | ||
355 | (temp16 * sizeof (u8)); | ||
356 | break; | ||
357 | |||
358 | |||
359 | case ACPI_RDESC_TYPE_MEMORY_32: | ||
360 | /* | ||
361 | * 32-Bit Memory Range Resource | ||
362 | */ | ||
363 | bytes_consumed = 20; | ||
364 | |||
365 | structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem32); | ||
366 | break; | ||
367 | |||
368 | |||
369 | case ACPI_RDESC_TYPE_FIXED_MEMORY_32: | ||
370 | /* | ||
371 | * 32-Bit Fixed Memory Resource | ||
372 | */ | ||
373 | bytes_consumed = 12; | ||
374 | |||
375 | structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_mem32); | ||
376 | break; | ||
377 | |||
378 | |||
379 | case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE: | ||
380 | /* | ||
381 | * 64-Bit Address Resource | ||
382 | */ | ||
383 | buffer = byte_stream_buffer; | ||
384 | |||
385 | ++buffer; | ||
386 | ACPI_MOVE_16_TO_16 (&temp16, buffer); | ||
387 | |||
388 | bytes_consumed = temp16 + 3; | ||
389 | structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64); | ||
390 | break; | ||
391 | |||
392 | |||
393 | case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE: | ||
394 | /* | ||
395 | * 64-Bit Address Resource | ||
396 | */ | ||
397 | buffer = byte_stream_buffer; | ||
398 | |||
399 | ++buffer; | ||
400 | ACPI_MOVE_16_TO_16 (&temp16, buffer); | ||
401 | |||
402 | bytes_consumed = temp16 + 3; | ||
403 | |||
404 | /* | ||
405 | * Resource Source Index and Resource Source are optional elements. | ||
406 | * Check the length of the Bytestream. If it is greater than 43, | ||
407 | * that means that an Index exists and is followed by a null | ||
408 | * terminated string. Therefore, set the temp variable to the | ||
409 | * length minus the minimum byte stream length plus the byte for | ||
410 | * the Index to determine the size of the NULL terminated string. | ||
411 | */ | ||
412 | if (43 < temp16) { | ||
413 | temp8 = (u8) (temp16 - 44); | ||
414 | } | ||
415 | else { | ||
416 | temp8 = 0; | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | * Ensure a 64-bit boundary for the structure | ||
421 | */ | ||
422 | temp8 = (u8) ACPI_ROUND_UP_to_64_bITS (temp8); | ||
423 | |||
424 | structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64) + | ||
425 | (temp8 * sizeof (u8)); | ||
426 | break; | ||
427 | |||
428 | |||
429 | case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE: | ||
430 | /* | ||
431 | * 32-Bit Address Resource | ||
432 | */ | ||
433 | buffer = byte_stream_buffer; | ||
434 | |||
435 | ++buffer; | ||
436 | ACPI_MOVE_16_TO_16 (&temp16, buffer); | ||
437 | |||
438 | bytes_consumed = temp16 + 3; | ||
439 | |||
440 | /* | ||
441 | * Resource Source Index and Resource Source are optional elements. | ||
442 | * Check the length of the Bytestream. If it is greater than 23, | ||
443 | * that means that an Index exists and is followed by a null | ||
444 | * terminated string. Therefore, set the temp variable to the | ||
445 | * length minus the minimum byte stream length plus the byte for | ||
446 | * the Index to determine the size of the NULL terminated string. | ||
447 | */ | ||
448 | if (23 < temp16) { | ||
449 | temp8 = (u8) (temp16 - 24); | ||
450 | } | ||
451 | else { | ||
452 | temp8 = 0; | ||
453 | } | ||
454 | |||
455 | /* | ||
456 | * Ensure a 32-bit boundary for the structure | ||
457 | */ | ||
458 | temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8); | ||
459 | |||
460 | structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address32) + | ||
461 | (temp8 * sizeof (u8)); | ||
462 | break; | ||
463 | |||
464 | |||
465 | case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE: | ||
466 | /* | ||
467 | * 16-Bit Address Resource | ||
468 | */ | ||
469 | buffer = byte_stream_buffer; | ||
470 | |||
471 | ++buffer; | ||
472 | ACPI_MOVE_16_TO_16 (&temp16, buffer); | ||
473 | |||
474 | bytes_consumed = temp16 + 3; | ||
475 | |||
476 | /* | ||
477 | * Resource Source Index and Resource Source are optional elements. | ||
478 | * Check the length of the Bytestream. If it is greater than 13, | ||
479 | * that means that an Index exists and is followed by a null | ||
480 | * terminated string. Therefore, set the temp variable to the | ||
481 | * length minus the minimum byte stream length plus the byte for | ||
482 | * the Index to determine the size of the NULL terminated string. | ||
483 | */ | ||
484 | if (13 < temp16) { | ||
485 | temp8 = (u8) (temp16 - 14); | ||
486 | } | ||
487 | else { | ||
488 | temp8 = 0; | ||
489 | } | ||
490 | |||
491 | /* | ||
492 | * Ensure a 32-bit boundary for the structure | ||
493 | */ | ||
494 | temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8); | ||
495 | |||
496 | structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address16) + | ||
497 | (temp8 * sizeof (u8)); | ||
498 | break; | ||
499 | |||
500 | |||
501 | case ACPI_RDESC_TYPE_EXTENDED_XRUPT: | ||
502 | /* | ||
503 | * Extended IRQ | ||
504 | */ | ||
505 | buffer = byte_stream_buffer; | ||
506 | |||
507 | ++buffer; | ||
508 | ACPI_MOVE_16_TO_16 (&temp16, buffer); | ||
509 | |||
510 | bytes_consumed = temp16 + 3; | ||
511 | |||
512 | /* | ||
513 | * Point past the length field and the Interrupt vector flags to | ||
514 | * save off the Interrupt table length to the Temp8 variable. | ||
515 | */ | ||
516 | buffer += 3; | ||
517 | temp8 = *buffer; | ||
518 | |||
519 | /* | ||
520 | * To compensate for multiple interrupt numbers, add 4 bytes for | ||
521 | * each additional interrupts greater than 1 | ||
522 | */ | ||
523 | additional_bytes = (u8) ((temp8 - 1) * 4); | ||
524 | |||
525 | /* | ||
526 | * Resource Source Index and Resource Source are optional elements. | ||
527 | * Check the length of the Bytestream. If it is greater than 9, | ||
528 | * that means that an Index exists and is followed by a null | ||
529 | * terminated string. Therefore, set the temp variable to the | ||
530 | * length minus the minimum byte stream length plus the byte for | ||
531 | * the Index to determine the size of the NULL terminated string. | ||
532 | */ | ||
533 | if (9 + additional_bytes < temp16) { | ||
534 | temp8 = (u8) (temp16 - (9 + additional_bytes)); | ||
535 | } | ||
536 | else { | ||
537 | temp8 = 0; | ||
538 | } | ||
539 | |||
540 | /* | ||
541 | * Ensure a 32-bit boundary for the structure | ||
542 | */ | ||
543 | temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8); | ||
544 | |||
545 | structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_ext_irq) + | ||
546 | (additional_bytes * sizeof (u8)) + | ||
547 | (temp8 * sizeof (u8)); | ||
548 | break; | ||
549 | |||
550 | |||
551 | case ACPI_RDESC_TYPE_IRQ_FORMAT: | ||
552 | /* | ||
553 | * IRQ Resource. | ||
554 | * Determine if it there are two or three trailing bytes | ||
555 | */ | ||
556 | buffer = byte_stream_buffer; | ||
557 | temp8 = *buffer; | ||
558 | |||
559 | if(temp8 & 0x01) { | ||
560 | bytes_consumed = 4; | ||
561 | } | ||
562 | else { | ||
563 | bytes_consumed = 3; | ||
564 | } | ||
565 | |||
566 | /* Point past the descriptor */ | ||
567 | |||
568 | ++buffer; | ||
569 | |||
570 | /* | ||
571 | * Look at the number of bits set | ||
572 | */ | ||
573 | ACPI_MOVE_16_TO_16 (&temp16, buffer); | ||
574 | |||
575 | for (index = 0; index < 16; index++) { | ||
576 | if (temp16 & 0x1) { | ||
577 | ++number_of_interrupts; | ||
578 | } | ||
579 | |||
580 | temp16 >>= 1; | ||
581 | } | ||
582 | |||
583 | structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io) + | ||
584 | (number_of_interrupts * sizeof (u32)); | ||
585 | break; | ||
586 | |||
587 | |||
588 | case ACPI_RDESC_TYPE_DMA_FORMAT: | ||
589 | /* | ||
590 | * DMA Resource | ||
591 | */ | ||
592 | buffer = byte_stream_buffer; | ||
593 | bytes_consumed = 3; | ||
594 | |||
595 | /* Point past the descriptor */ | ||
596 | |||
597 | ++buffer; | ||
598 | |||
599 | /* | ||
600 | * Look at the number of bits set | ||
601 | */ | ||
602 | temp8 = *buffer; | ||
603 | |||
604 | for(index = 0; index < 8; index++) { | ||
605 | if(temp8 & 0x1) { | ||
606 | ++number_of_channels; | ||
607 | } | ||
608 | |||
609 | temp8 >>= 1; | ||
610 | } | ||
611 | |||
612 | structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_dma) + | ||
613 | (number_of_channels * sizeof (u32)); | ||
614 | break; | ||
615 | |||
616 | |||
617 | case ACPI_RDESC_TYPE_START_DEPENDENT: | ||
618 | /* | ||
619 | * Start Dependent Functions Resource | ||
620 | * Determine if it there are two or three trailing bytes | ||
621 | */ | ||
622 | buffer = byte_stream_buffer; | ||
623 | temp8 = *buffer; | ||
624 | |||
625 | if(temp8 & 0x01) { | ||
626 | bytes_consumed = 2; | ||
627 | } | ||
628 | else { | ||
629 | bytes_consumed = 1; | ||
630 | } | ||
631 | |||
632 | structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_start_dpf); | ||
633 | break; | ||
634 | |||
635 | |||
636 | case ACPI_RDESC_TYPE_END_DEPENDENT: | ||
637 | /* | ||
638 | * End Dependent Functions Resource | ||
639 | */ | ||
640 | bytes_consumed = 1; | ||
641 | structure_size = ACPI_RESOURCE_LENGTH; | ||
642 | break; | ||
643 | |||
644 | |||
645 | case ACPI_RDESC_TYPE_IO_PORT: | ||
646 | /* | ||
647 | * IO Port Resource | ||
648 | */ | ||
649 | bytes_consumed = 8; | ||
650 | structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io); | ||
651 | break; | ||
652 | |||
653 | |||
654 | case ACPI_RDESC_TYPE_FIXED_IO_PORT: | ||
655 | /* | ||
656 | * Fixed IO Port Resource | ||
657 | */ | ||
658 | bytes_consumed = 4; | ||
659 | structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_io); | ||
660 | break; | ||
661 | |||
662 | |||
663 | case ACPI_RDESC_TYPE_SMALL_VENDOR: | ||
664 | /* | ||
665 | * Vendor Specific Resource | ||
666 | */ | ||
667 | buffer = byte_stream_buffer; | ||
668 | |||
669 | temp8 = *buffer; | ||
670 | temp8 = (u8) (temp8 & 0x7); | ||
671 | bytes_consumed = temp8 + 1; | ||
672 | |||
673 | /* | ||
674 | * Ensure a 32-bit boundary for the structure | ||
675 | */ | ||
676 | temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8); | ||
677 | structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor) + | ||
678 | (temp8 * sizeof (u8)); | ||
679 | break; | ||
680 | |||
681 | |||
682 | case ACPI_RDESC_TYPE_END_TAG: | ||
683 | /* | ||
684 | * End Tag | ||
685 | */ | ||
686 | bytes_consumed = 2; | ||
687 | structure_size = ACPI_RESOURCE_LENGTH; | ||
688 | byte_stream_buffer_length = bytes_parsed; | ||
689 | break; | ||
690 | |||
691 | |||
692 | default: | ||
693 | /* | ||
694 | * If we get here, everything is out of sync, | ||
695 | * exit with an error | ||
696 | */ | ||
697 | return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); | ||
698 | } | ||
699 | |||
700 | /* | ||
701 | * Update the return value and counter | ||
702 | */ | ||
703 | buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE (structure_size); | ||
704 | bytes_parsed += bytes_consumed; | ||
705 | |||
706 | /* | ||
707 | * Set the byte stream to point to the next resource | ||
708 | */ | ||
709 | byte_stream_buffer += bytes_consumed; | ||
710 | } | ||
711 | |||
712 | /* | ||
713 | * This is the data the caller needs | ||
714 | */ | ||
715 | *size_needed = buffer_size; | ||
716 | return_ACPI_STATUS (AE_OK); | ||
717 | } | ||
718 | |||
719 | |||
720 | /******************************************************************************* | ||
721 | * | ||
722 | * FUNCTION: acpi_rs_get_pci_routing_table_length | ||
723 | * | ||
724 | * PARAMETERS: package_object - Pointer to the package object | ||
725 | * buffer_size_needed - u32 pointer of the size buffer | ||
726 | * needed to properly return the | ||
727 | * parsed data | ||
728 | * | ||
729 | * RETURN: Status | ||
730 | * | ||
731 | * DESCRIPTION: Given a package representing a PCI routing table, this | ||
732 | * calculates the size of the corresponding linked list of | ||
733 | * descriptions. | ||
734 | * | ||
735 | ******************************************************************************/ | ||
736 | |||
737 | acpi_status | ||
738 | acpi_rs_get_pci_routing_table_length ( | ||
739 | union acpi_operand_object *package_object, | ||
740 | acpi_size *buffer_size_needed) | ||
741 | { | ||
742 | u32 number_of_elements; | ||
743 | acpi_size temp_size_needed = 0; | ||
744 | union acpi_operand_object **top_object_list; | ||
745 | u32 index; | ||
746 | union acpi_operand_object *package_element; | ||
747 | union acpi_operand_object **sub_object_list; | ||
748 | u8 name_found; | ||
749 | u32 table_index; | ||
750 | |||
751 | |||
752 | ACPI_FUNCTION_TRACE ("rs_get_pci_routing_table_length"); | ||
753 | |||
754 | |||
755 | number_of_elements = package_object->package.count; | ||
756 | |||
757 | /* | ||
758 | * Calculate the size of the return buffer. | ||
759 | * The base size is the number of elements * the sizes of the | ||
760 | * structures. Additional space for the strings is added below. | ||
761 | * The minus one is to subtract the size of the u8 Source[1] | ||
762 | * member because it is added below. | ||
763 | * | ||
764 | * But each PRT_ENTRY structure has a pointer to a string and | ||
765 | * the size of that string must be found. | ||
766 | */ | ||
767 | top_object_list = package_object->package.elements; | ||
768 | |||
769 | for (index = 0; index < number_of_elements; index++) { | ||
770 | /* | ||
771 | * Dereference the sub-package | ||
772 | */ | ||
773 | package_element = *top_object_list; | ||
774 | |||
775 | /* | ||
776 | * The sub_object_list will now point to an array of the | ||
777 | * four IRQ elements: Address, Pin, Source and source_index | ||
778 | */ | ||
779 | sub_object_list = package_element->package.elements; | ||
780 | |||
781 | /* | ||
782 | * Scan the irq_table_elements for the Source Name String | ||
783 | */ | ||
784 | name_found = FALSE; | ||
785 | |||
786 | for (table_index = 0; table_index < 4 && !name_found; table_index++) { | ||
787 | if ((ACPI_TYPE_STRING == ACPI_GET_OBJECT_TYPE (*sub_object_list)) || | ||
788 | ((ACPI_TYPE_LOCAL_REFERENCE == ACPI_GET_OBJECT_TYPE (*sub_object_list)) && | ||
789 | ((*sub_object_list)->reference.opcode == AML_INT_NAMEPATH_OP))) { | ||
790 | name_found = TRUE; | ||
791 | } | ||
792 | else { | ||
793 | /* | ||
794 | * Look at the next element | ||
795 | */ | ||
796 | sub_object_list++; | ||
797 | } | ||
798 | } | ||
799 | |||
800 | temp_size_needed += (sizeof (struct acpi_pci_routing_table) - 4); | ||
801 | |||
802 | /* | ||
803 | * Was a String type found? | ||
804 | */ | ||
805 | if (name_found) { | ||
806 | if (ACPI_GET_OBJECT_TYPE (*sub_object_list) == ACPI_TYPE_STRING) { | ||
807 | /* | ||
808 | * The length String.Length field does not include the | ||
809 | * terminating NULL, add 1 | ||
810 | */ | ||
811 | temp_size_needed += ((acpi_size) (*sub_object_list)->string.length + 1); | ||
812 | } | ||
813 | else { | ||
814 | temp_size_needed += acpi_ns_get_pathname_length ( | ||
815 | (*sub_object_list)->reference.node); | ||
816 | } | ||
817 | } | ||
818 | else { | ||
819 | /* | ||
820 | * If no name was found, then this is a NULL, which is | ||
821 | * translated as a u32 zero. | ||
822 | */ | ||
823 | temp_size_needed += sizeof (u32); | ||
824 | } | ||
825 | |||
826 | /* Round up the size since each element must be aligned */ | ||
827 | |||
828 | temp_size_needed = ACPI_ROUND_UP_to_64_bITS (temp_size_needed); | ||
829 | |||
830 | /* | ||
831 | * Point to the next union acpi_operand_object | ||
832 | */ | ||
833 | top_object_list++; | ||
834 | } | ||
835 | |||
836 | /* | ||
837 | * Adding an extra element to the end of the list, essentially a NULL terminator | ||
838 | */ | ||
839 | *buffer_size_needed = temp_size_needed + sizeof (struct acpi_pci_routing_table); | ||
840 | return_ACPI_STATUS (AE_OK); | ||
841 | } | ||