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