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