diff options
Diffstat (limited to 'drivers/acpi/acpica/rsmisc.c')
-rw-r--r-- | drivers/acpi/acpica/rsmisc.c | 561 |
1 files changed, 561 insertions, 0 deletions
diff --git a/drivers/acpi/acpica/rsmisc.c b/drivers/acpi/acpica/rsmisc.c new file mode 100644 index 000000000000..5bc49a553284 --- /dev/null +++ b/drivers/acpi/acpica/rsmisc.c | |||
@@ -0,0 +1,561 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * Module Name: rsmisc - Miscellaneous resource descriptors | ||
4 | * | ||
5 | ******************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2008, Intel Corp. | ||
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 | #include <acpi/acpi.h> | ||
45 | #include "accommon.h" | ||
46 | #include "acresrc.h" | ||
47 | |||
48 | #define _COMPONENT ACPI_RESOURCES | ||
49 | ACPI_MODULE_NAME("rsmisc") | ||
50 | #define INIT_RESOURCE_TYPE(i) i->resource_offset | ||
51 | #define INIT_RESOURCE_LENGTH(i) i->aml_offset | ||
52 | #define INIT_TABLE_LENGTH(i) i->value | ||
53 | #define COMPARE_OPCODE(i) i->resource_offset | ||
54 | #define COMPARE_TARGET(i) i->aml_offset | ||
55 | #define COMPARE_VALUE(i) i->value | ||
56 | /******************************************************************************* | ||
57 | * | ||
58 | * FUNCTION: acpi_rs_convert_aml_to_resource | ||
59 | * | ||
60 | * PARAMETERS: Resource - Pointer to the resource descriptor | ||
61 | * Aml - Where the AML descriptor is returned | ||
62 | * Info - Pointer to appropriate conversion table | ||
63 | * | ||
64 | * RETURN: Status | ||
65 | * | ||
66 | * DESCRIPTION: Convert an external AML resource descriptor to the corresponding | ||
67 | * internal resource descriptor | ||
68 | * | ||
69 | ******************************************************************************/ | ||
70 | acpi_status | ||
71 | acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, | ||
72 | union aml_resource *aml, | ||
73 | struct acpi_rsconvert_info *info) | ||
74 | { | ||
75 | acpi_rs_length aml_resource_length; | ||
76 | void *source; | ||
77 | void *destination; | ||
78 | char *target; | ||
79 | u8 count; | ||
80 | u8 flags_mode = FALSE; | ||
81 | u16 item_count = 0; | ||
82 | u16 temp16 = 0; | ||
83 | |||
84 | ACPI_FUNCTION_TRACE(rs_convert_aml_to_resource); | ||
85 | |||
86 | if (((acpi_size) resource) & 0x3) { | ||
87 | |||
88 | /* Each internal resource struct is expected to be 32-bit aligned */ | ||
89 | |||
90 | ACPI_WARNING((AE_INFO, | ||
91 | "Misaligned resource pointer (get): %p Type %2.2X Len %X", | ||
92 | resource, resource->type, resource->length)); | ||
93 | } | ||
94 | |||
95 | /* Extract the resource Length field (does not include header length) */ | ||
96 | |||
97 | aml_resource_length = acpi_ut_get_resource_length(aml); | ||
98 | |||
99 | /* | ||
100 | * First table entry must be ACPI_RSC_INITxxx and must contain the | ||
101 | * table length (# of table entries) | ||
102 | */ | ||
103 | count = INIT_TABLE_LENGTH(info); | ||
104 | |||
105 | while (count) { | ||
106 | /* | ||
107 | * Source is the external AML byte stream buffer, | ||
108 | * destination is the internal resource descriptor | ||
109 | */ | ||
110 | source = ACPI_ADD_PTR(void, aml, info->aml_offset); | ||
111 | destination = | ||
112 | ACPI_ADD_PTR(void, resource, info->resource_offset); | ||
113 | |||
114 | switch (info->opcode) { | ||
115 | case ACPI_RSC_INITGET: | ||
116 | /* | ||
117 | * Get the resource type and the initial (minimum) length | ||
118 | */ | ||
119 | ACPI_MEMSET(resource, 0, INIT_RESOURCE_LENGTH(info)); | ||
120 | resource->type = INIT_RESOURCE_TYPE(info); | ||
121 | resource->length = INIT_RESOURCE_LENGTH(info); | ||
122 | break; | ||
123 | |||
124 | case ACPI_RSC_INITSET: | ||
125 | break; | ||
126 | |||
127 | case ACPI_RSC_FLAGINIT: | ||
128 | |||
129 | flags_mode = TRUE; | ||
130 | break; | ||
131 | |||
132 | case ACPI_RSC_1BITFLAG: | ||
133 | /* | ||
134 | * Mask and shift the flag bit | ||
135 | */ | ||
136 | ACPI_SET8(destination) = (u8) | ||
137 | ((ACPI_GET8(source) >> info->value) & 0x01); | ||
138 | break; | ||
139 | |||
140 | case ACPI_RSC_2BITFLAG: | ||
141 | /* | ||
142 | * Mask and shift the flag bits | ||
143 | */ | ||
144 | ACPI_SET8(destination) = (u8) | ||
145 | ((ACPI_GET8(source) >> info->value) & 0x03); | ||
146 | break; | ||
147 | |||
148 | case ACPI_RSC_COUNT: | ||
149 | |||
150 | item_count = ACPI_GET8(source); | ||
151 | ACPI_SET8(destination) = (u8) item_count; | ||
152 | |||
153 | resource->length = resource->length + | ||
154 | (info->value * (item_count - 1)); | ||
155 | break; | ||
156 | |||
157 | case ACPI_RSC_COUNT16: | ||
158 | |||
159 | item_count = aml_resource_length; | ||
160 | ACPI_SET16(destination) = item_count; | ||
161 | |||
162 | resource->length = resource->length + | ||
163 | (info->value * (item_count - 1)); | ||
164 | break; | ||
165 | |||
166 | case ACPI_RSC_LENGTH: | ||
167 | |||
168 | resource->length = resource->length + info->value; | ||
169 | break; | ||
170 | |||
171 | case ACPI_RSC_MOVE8: | ||
172 | case ACPI_RSC_MOVE16: | ||
173 | case ACPI_RSC_MOVE32: | ||
174 | case ACPI_RSC_MOVE64: | ||
175 | /* | ||
176 | * Raw data move. Use the Info value field unless item_count has | ||
177 | * been previously initialized via a COUNT opcode | ||
178 | */ | ||
179 | if (info->value) { | ||
180 | item_count = info->value; | ||
181 | } | ||
182 | acpi_rs_move_data(destination, source, item_count, | ||
183 | info->opcode); | ||
184 | break; | ||
185 | |||
186 | case ACPI_RSC_SET8: | ||
187 | |||
188 | ACPI_MEMSET(destination, info->aml_offset, info->value); | ||
189 | break; | ||
190 | |||
191 | case ACPI_RSC_DATA8: | ||
192 | |||
193 | target = ACPI_ADD_PTR(char, resource, info->value); | ||
194 | ACPI_MEMCPY(destination, source, ACPI_GET16(target)); | ||
195 | break; | ||
196 | |||
197 | case ACPI_RSC_ADDRESS: | ||
198 | /* | ||
199 | * Common handler for address descriptor flags | ||
200 | */ | ||
201 | if (!acpi_rs_get_address_common(resource, aml)) { | ||
202 | return_ACPI_STATUS | ||
203 | (AE_AML_INVALID_RESOURCE_TYPE); | ||
204 | } | ||
205 | break; | ||
206 | |||
207 | case ACPI_RSC_SOURCE: | ||
208 | /* | ||
209 | * Optional resource_source (Index and String) | ||
210 | */ | ||
211 | resource->length += | ||
212 | acpi_rs_get_resource_source(aml_resource_length, | ||
213 | info->value, | ||
214 | destination, aml, NULL); | ||
215 | break; | ||
216 | |||
217 | case ACPI_RSC_SOURCEX: | ||
218 | /* | ||
219 | * Optional resource_source (Index and String). This is the more | ||
220 | * complicated case used by the Interrupt() macro | ||
221 | */ | ||
222 | target = | ||
223 | ACPI_ADD_PTR(char, resource, | ||
224 | info->aml_offset + (item_count * 4)); | ||
225 | |||
226 | resource->length += | ||
227 | acpi_rs_get_resource_source(aml_resource_length, | ||
228 | (acpi_rs_length) (((item_count - 1) * sizeof(u32)) + info->value), destination, aml, target); | ||
229 | break; | ||
230 | |||
231 | case ACPI_RSC_BITMASK: | ||
232 | /* | ||
233 | * 8-bit encoded bitmask (DMA macro) | ||
234 | */ | ||
235 | item_count = | ||
236 | acpi_rs_decode_bitmask(ACPI_GET8(source), | ||
237 | destination); | ||
238 | if (item_count) { | ||
239 | resource->length += (item_count - 1); | ||
240 | } | ||
241 | |||
242 | target = ACPI_ADD_PTR(char, resource, info->value); | ||
243 | ACPI_SET8(target) = (u8) item_count; | ||
244 | break; | ||
245 | |||
246 | case ACPI_RSC_BITMASK16: | ||
247 | /* | ||
248 | * 16-bit encoded bitmask (IRQ macro) | ||
249 | */ | ||
250 | ACPI_MOVE_16_TO_16(&temp16, source); | ||
251 | |||
252 | item_count = | ||
253 | acpi_rs_decode_bitmask(temp16, destination); | ||
254 | if (item_count) { | ||
255 | resource->length += (item_count - 1); | ||
256 | } | ||
257 | |||
258 | target = ACPI_ADD_PTR(char, resource, info->value); | ||
259 | ACPI_SET8(target) = (u8) item_count; | ||
260 | break; | ||
261 | |||
262 | case ACPI_RSC_EXIT_NE: | ||
263 | /* | ||
264 | * Control - Exit conversion if not equal | ||
265 | */ | ||
266 | switch (info->resource_offset) { | ||
267 | case ACPI_RSC_COMPARE_AML_LENGTH: | ||
268 | if (aml_resource_length != info->value) { | ||
269 | goto exit; | ||
270 | } | ||
271 | break; | ||
272 | |||
273 | case ACPI_RSC_COMPARE_VALUE: | ||
274 | if (ACPI_GET8(source) != info->value) { | ||
275 | goto exit; | ||
276 | } | ||
277 | break; | ||
278 | |||
279 | default: | ||
280 | |||
281 | ACPI_ERROR((AE_INFO, | ||
282 | "Invalid conversion sub-opcode")); | ||
283 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
284 | } | ||
285 | break; | ||
286 | |||
287 | default: | ||
288 | |||
289 | ACPI_ERROR((AE_INFO, "Invalid conversion opcode")); | ||
290 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
291 | } | ||
292 | |||
293 | count--; | ||
294 | info++; | ||
295 | } | ||
296 | |||
297 | exit: | ||
298 | if (!flags_mode) { | ||
299 | |||
300 | /* Round the resource struct length up to the next boundary (32 or 64) */ | ||
301 | |||
302 | resource->length = | ||
303 | (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(resource->length); | ||
304 | } | ||
305 | return_ACPI_STATUS(AE_OK); | ||
306 | } | ||
307 | |||
308 | /******************************************************************************* | ||
309 | * | ||
310 | * FUNCTION: acpi_rs_convert_resource_to_aml | ||
311 | * | ||
312 | * PARAMETERS: Resource - Pointer to the resource descriptor | ||
313 | * Aml - Where the AML descriptor is returned | ||
314 | * Info - Pointer to appropriate conversion table | ||
315 | * | ||
316 | * RETURN: Status | ||
317 | * | ||
318 | * DESCRIPTION: Convert an internal resource descriptor to the corresponding | ||
319 | * external AML resource descriptor. | ||
320 | * | ||
321 | ******************************************************************************/ | ||
322 | |||
323 | acpi_status | ||
324 | acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, | ||
325 | union aml_resource *aml, | ||
326 | struct acpi_rsconvert_info *info) | ||
327 | { | ||
328 | void *source = NULL; | ||
329 | void *destination; | ||
330 | acpi_rsdesc_size aml_length = 0; | ||
331 | u8 count; | ||
332 | u16 temp16 = 0; | ||
333 | u16 item_count = 0; | ||
334 | |||
335 | ACPI_FUNCTION_TRACE(rs_convert_resource_to_aml); | ||
336 | |||
337 | /* | ||
338 | * First table entry must be ACPI_RSC_INITxxx and must contain the | ||
339 | * table length (# of table entries) | ||
340 | */ | ||
341 | count = INIT_TABLE_LENGTH(info); | ||
342 | |||
343 | while (count) { | ||
344 | /* | ||
345 | * Source is the internal resource descriptor, | ||
346 | * destination is the external AML byte stream buffer | ||
347 | */ | ||
348 | source = ACPI_ADD_PTR(void, resource, info->resource_offset); | ||
349 | destination = ACPI_ADD_PTR(void, aml, info->aml_offset); | ||
350 | |||
351 | switch (info->opcode) { | ||
352 | case ACPI_RSC_INITSET: | ||
353 | |||
354 | ACPI_MEMSET(aml, 0, INIT_RESOURCE_LENGTH(info)); | ||
355 | aml_length = INIT_RESOURCE_LENGTH(info); | ||
356 | acpi_rs_set_resource_header(INIT_RESOURCE_TYPE(info), | ||
357 | aml_length, aml); | ||
358 | break; | ||
359 | |||
360 | case ACPI_RSC_INITGET: | ||
361 | break; | ||
362 | |||
363 | case ACPI_RSC_FLAGINIT: | ||
364 | /* | ||
365 | * Clear the flag byte | ||
366 | */ | ||
367 | ACPI_SET8(destination) = 0; | ||
368 | break; | ||
369 | |||
370 | case ACPI_RSC_1BITFLAG: | ||
371 | /* | ||
372 | * Mask and shift the flag bit | ||
373 | */ | ||
374 | ACPI_SET8(destination) |= (u8) | ||
375 | ((ACPI_GET8(source) & 0x01) << info->value); | ||
376 | break; | ||
377 | |||
378 | case ACPI_RSC_2BITFLAG: | ||
379 | /* | ||
380 | * Mask and shift the flag bits | ||
381 | */ | ||
382 | ACPI_SET8(destination) |= (u8) | ||
383 | ((ACPI_GET8(source) & 0x03) << info->value); | ||
384 | break; | ||
385 | |||
386 | case ACPI_RSC_COUNT: | ||
387 | |||
388 | item_count = ACPI_GET8(source); | ||
389 | ACPI_SET8(destination) = (u8) item_count; | ||
390 | |||
391 | aml_length = | ||
392 | (u16) (aml_length + | ||
393 | (info->value * (item_count - 1))); | ||
394 | break; | ||
395 | |||
396 | case ACPI_RSC_COUNT16: | ||
397 | |||
398 | item_count = ACPI_GET16(source); | ||
399 | aml_length = (u16) (aml_length + item_count); | ||
400 | acpi_rs_set_resource_length(aml_length, aml); | ||
401 | break; | ||
402 | |||
403 | case ACPI_RSC_LENGTH: | ||
404 | |||
405 | acpi_rs_set_resource_length(info->value, aml); | ||
406 | break; | ||
407 | |||
408 | case ACPI_RSC_MOVE8: | ||
409 | case ACPI_RSC_MOVE16: | ||
410 | case ACPI_RSC_MOVE32: | ||
411 | case ACPI_RSC_MOVE64: | ||
412 | |||
413 | if (info->value) { | ||
414 | item_count = info->value; | ||
415 | } | ||
416 | acpi_rs_move_data(destination, source, item_count, | ||
417 | info->opcode); | ||
418 | break; | ||
419 | |||
420 | case ACPI_RSC_ADDRESS: | ||
421 | |||
422 | /* Set the Resource Type, General Flags, and Type-Specific Flags */ | ||
423 | |||
424 | acpi_rs_set_address_common(aml, resource); | ||
425 | break; | ||
426 | |||
427 | case ACPI_RSC_SOURCEX: | ||
428 | /* | ||
429 | * Optional resource_source (Index and String) | ||
430 | */ | ||
431 | aml_length = | ||
432 | acpi_rs_set_resource_source(aml, (acpi_rs_length) | ||
433 | aml_length, source); | ||
434 | acpi_rs_set_resource_length(aml_length, aml); | ||
435 | break; | ||
436 | |||
437 | case ACPI_RSC_SOURCE: | ||
438 | /* | ||
439 | * Optional resource_source (Index and String). This is the more | ||
440 | * complicated case used by the Interrupt() macro | ||
441 | */ | ||
442 | aml_length = | ||
443 | acpi_rs_set_resource_source(aml, info->value, | ||
444 | source); | ||
445 | acpi_rs_set_resource_length(aml_length, aml); | ||
446 | break; | ||
447 | |||
448 | case ACPI_RSC_BITMASK: | ||
449 | /* | ||
450 | * 8-bit encoded bitmask (DMA macro) | ||
451 | */ | ||
452 | ACPI_SET8(destination) = (u8) | ||
453 | acpi_rs_encode_bitmask(source, | ||
454 | *ACPI_ADD_PTR(u8, resource, | ||
455 | info->value)); | ||
456 | break; | ||
457 | |||
458 | case ACPI_RSC_BITMASK16: | ||
459 | /* | ||
460 | * 16-bit encoded bitmask (IRQ macro) | ||
461 | */ | ||
462 | temp16 = acpi_rs_encode_bitmask(source, | ||
463 | *ACPI_ADD_PTR(u8, | ||
464 | resource, | ||
465 | info-> | ||
466 | value)); | ||
467 | ACPI_MOVE_16_TO_16(destination, &temp16); | ||
468 | break; | ||
469 | |||
470 | case ACPI_RSC_EXIT_LE: | ||
471 | /* | ||
472 | * Control - Exit conversion if less than or equal | ||
473 | */ | ||
474 | if (item_count <= info->value) { | ||
475 | goto exit; | ||
476 | } | ||
477 | break; | ||
478 | |||
479 | case ACPI_RSC_EXIT_NE: | ||
480 | /* | ||
481 | * Control - Exit conversion if not equal | ||
482 | */ | ||
483 | switch (COMPARE_OPCODE(info)) { | ||
484 | case ACPI_RSC_COMPARE_VALUE: | ||
485 | |||
486 | if (*ACPI_ADD_PTR(u8, resource, | ||
487 | COMPARE_TARGET(info)) != | ||
488 | COMPARE_VALUE(info)) { | ||
489 | goto exit; | ||
490 | } | ||
491 | break; | ||
492 | |||
493 | default: | ||
494 | |||
495 | ACPI_ERROR((AE_INFO, | ||
496 | "Invalid conversion sub-opcode")); | ||
497 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
498 | } | ||
499 | break; | ||
500 | |||
501 | case ACPI_RSC_EXIT_EQ: | ||
502 | /* | ||
503 | * Control - Exit conversion if equal | ||
504 | */ | ||
505 | if (*ACPI_ADD_PTR(u8, resource, | ||
506 | COMPARE_TARGET(info)) == | ||
507 | COMPARE_VALUE(info)) { | ||
508 | goto exit; | ||
509 | } | ||
510 | break; | ||
511 | |||
512 | default: | ||
513 | |||
514 | ACPI_ERROR((AE_INFO, "Invalid conversion opcode")); | ||
515 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
516 | } | ||
517 | |||
518 | count--; | ||
519 | info++; | ||
520 | } | ||
521 | |||
522 | exit: | ||
523 | return_ACPI_STATUS(AE_OK); | ||
524 | } | ||
525 | |||
526 | #if 0 | ||
527 | /* Previous resource validations */ | ||
528 | |||
529 | if (aml->ext_address64.revision_iD != AML_RESOURCE_EXTENDED_ADDRESS_REVISION) { | ||
530 | return_ACPI_STATUS(AE_SUPPORT); | ||
531 | } | ||
532 | |||
533 | if (resource->data.start_dpf.performance_robustness >= 3) { | ||
534 | return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE); | ||
535 | } | ||
536 | |||
537 | if (((aml->irq.flags & 0x09) == 0x00) || ((aml->irq.flags & 0x09) == 0x09)) { | ||
538 | /* | ||
539 | * Only [active_high, edge_sensitive] or [active_low, level_sensitive] | ||
540 | * polarity/trigger interrupts are allowed (ACPI spec, section | ||
541 | * "IRQ Format"), so 0x00 and 0x09 are illegal. | ||
542 | */ | ||
543 | ACPI_ERROR((AE_INFO, | ||
544 | "Invalid interrupt polarity/trigger in resource list, %X", | ||
545 | aml->irq.flags)); | ||
546 | return_ACPI_STATUS(AE_BAD_DATA); | ||
547 | } | ||
548 | |||
549 | resource->data.extended_irq.interrupt_count = temp8; | ||
550 | if (temp8 < 1) { | ||
551 | |||
552 | /* Must have at least one IRQ */ | ||
553 | |||
554 | return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); | ||
555 | } | ||
556 | |||
557 | if (resource->data.dma.transfer == 0x03) { | ||
558 | ACPI_ERROR((AE_INFO, "Invalid DMA.Transfer preference (3)")); | ||
559 | return_ACPI_STATUS(AE_BAD_DATA); | ||
560 | } | ||
561 | #endif | ||