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