]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/contrib/dev/acpica/compiler/dtutils.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / contrib / dev / acpica / compiler / dtutils.c
1 /******************************************************************************
2  *
3  * Module Name: dtutils.c - Utility routines for the data table compiler
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2015, 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 <contrib/dev/acpica/compiler/aslcompiler.h>
45 #include <contrib/dev/acpica/compiler/dtcompiler.h>
46 #include <contrib/dev/acpica/include/actables.h>
47
48 #define _COMPONENT          DT_COMPILER
49         ACPI_MODULE_NAME    ("dtutils")
50
51 /* Local prototypes */
52
53 static void
54 DtSum (
55     DT_SUBTABLE             *Subtable,
56     void                    *Context,
57     void                    *ReturnValue);
58
59
60 /******************************************************************************
61  *
62  * FUNCTION:    DtError
63  *
64  * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
65  *              MessageId           - Index into global message buffer
66  *              Op                  - Parse node where error happened
67  *              ExtraMessage        - additional error message
68  *
69  * RETURN:      None
70  *
71  * DESCRIPTION: Common error interface for data table compiler
72  *
73  *****************************************************************************/
74
75 void
76 DtError (
77     UINT8                   Level,
78     UINT16                  MessageId,
79     DT_FIELD                *FieldObject,
80     char                    *ExtraMessage)
81 {
82
83     /* Check if user wants to ignore this exception */
84
85     if (AslIsExceptionDisabled (Level, MessageId))
86     {
87         return;
88     }
89
90     if (FieldObject)
91     {
92         AslCommonError (Level, MessageId,
93             FieldObject->Line,
94             FieldObject->Line,
95             FieldObject->ByteOffset,
96             FieldObject->Column,
97             Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage);
98     }
99     else
100     {
101         AslCommonError (Level, MessageId, 0,
102             0, 0, 0, 0, ExtraMessage);
103     }
104 }
105
106
107 /******************************************************************************
108  *
109  * FUNCTION:    DtNameError
110  *
111  * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
112  *              MessageId           - Index into global message buffer
113  *              Op                  - Parse node where error happened
114  *              ExtraMessage        - additional error message
115  *
116  * RETURN:      None
117  *
118  * DESCRIPTION: Error interface for named objects
119  *
120  *****************************************************************************/
121
122 void
123 DtNameError (
124     UINT8                   Level,
125     UINT16                  MessageId,
126     DT_FIELD                *FieldObject,
127     char                    *ExtraMessage)
128 {
129
130     switch (Level)
131     {
132     case ASL_WARNING2:
133     case ASL_WARNING3:
134
135         if (Gbl_WarningLevel < Level)
136         {
137             return;
138         }
139         break;
140
141     default:
142
143         break;
144     }
145
146     if (FieldObject)
147     {
148         AslCommonError (Level, MessageId,
149             FieldObject->Line,
150             FieldObject->Line,
151             FieldObject->ByteOffset,
152             FieldObject->NameColumn,
153             Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage);
154     }
155     else
156     {
157         AslCommonError (Level, MessageId, 0,
158             0, 0, 0, 0, ExtraMessage);
159     }
160 }
161
162
163 /*******************************************************************************
164  *
165  * FUNCTION:    DtFatal
166  *
167  * PARAMETERS:  None
168  *
169  * RETURN:      None
170  *
171  * DESCRIPTION: Dump the error log and abort the compiler. Used for serious
172  *              compile or I/O errors
173  *
174  ******************************************************************************/
175
176 void
177 DtFatal (
178     UINT16                  MessageId,
179     DT_FIELD                *FieldObject,
180     char                    *ExtraMessage)
181 {
182
183     DtError (ASL_ERROR, MessageId, FieldObject, ExtraMessage);
184
185 /*
186  * TBD: remove this entire function, DtFatal
187  *
188  * We cannot abort the compiler on error, because we may be compiling a
189  * list of files. We must move on to the next file.
190  */
191 #ifdef __OBSOLETE
192     CmCleanupAndExit ();
193     exit (1);
194 #endif
195 }
196
197
198 /******************************************************************************
199  *
200  * FUNCTION:    DtStrtoul64
201  *
202  * PARAMETERS:  String              - Null terminated string
203  *              ReturnInteger       - Where the converted integer is returned
204  *
205  * RETURN:      Status
206  *
207  * DESCRIPTION: Simple conversion of a string hex integer constant to unsigned
208  *              value. Assumes no leading "0x" for the constant.
209  *
210  * Portability note: The reason this function exists is because a 64-bit
211  * sscanf is not available in all environments.
212  *
213  *****************************************************************************/
214
215 ACPI_STATUS
216 DtStrtoul64 (
217     char                    *String,
218     UINT64                  *ReturnInteger)
219 {
220     char                    *ThisChar = String;
221     UINT32                  ThisDigit;
222     UINT64                  ReturnValue = 0;
223     int                     DigitCount = 0;
224
225
226     /* Skip over any white space in the buffer */
227
228     while ((*ThisChar == ' ') || (*ThisChar == '\t'))
229     {
230         ThisChar++;
231     }
232
233     /* Skip leading zeros */
234
235     while ((*ThisChar) == '0')
236     {
237         ThisChar++;
238     }
239
240     /* Convert character-by-character */
241
242     while (*ThisChar)
243     {
244         if (ACPI_IS_DIGIT (*ThisChar))
245         {
246             /* Convert ASCII 0-9 to Decimal value */
247
248             ThisDigit = ((UINT8) *ThisChar) - '0';
249         }
250         else /* Letter */
251         {
252             ThisDigit = (UINT32) ACPI_TOUPPER (*ThisChar);
253             if (!ACPI_IS_XDIGIT ((char) ThisDigit))
254             {
255                 /* Not A-F */
256
257                 return (AE_BAD_CHARACTER);
258             }
259
260             /* Convert ASCII Hex char (A-F) to value */
261
262             ThisDigit = (ThisDigit - 'A') + 10;
263         }
264
265         /* Insert the 4-bit hex digit */
266
267         ReturnValue <<= 4;
268         ReturnValue += ThisDigit;
269
270         ThisChar++;
271         DigitCount++;
272         if (DigitCount > 16)
273         {
274             /* Value is too large (> 64 bits/8 bytes/16 hex digits) */
275
276             return (AE_LIMIT);
277         }
278     }
279
280     *ReturnInteger = ReturnValue;
281     return (AE_OK);
282 }
283
284
285 /******************************************************************************
286  *
287  * FUNCTION:    DtGetFieldValue
288  *
289  * PARAMETERS:  Field               - Current field list pointer
290  *
291  * RETURN:      Field value
292  *
293  * DESCRIPTION: Get field value
294  *
295  *****************************************************************************/
296
297 char *
298 DtGetFieldValue (
299     DT_FIELD                *Field)
300 {
301     if (!Field)
302     {
303         return (NULL);
304     }
305
306     return (Field->Value);
307 }
308
309
310 /******************************************************************************
311  *
312  * FUNCTION:    DtGetFieldType
313  *
314  * PARAMETERS:  Info                - Data table info
315  *
316  * RETURN:      Field type
317  *
318  * DESCRIPTION: Get field type
319  *
320  *****************************************************************************/
321
322 UINT8
323 DtGetFieldType (
324     ACPI_DMTABLE_INFO       *Info)
325 {
326     UINT8                   Type;
327
328
329     /* DT_FLAG means that this is the start of a block of flag bits */
330     /* TBD - we can make these a separate opcode later */
331
332     if (Info->Flags & DT_FLAG)
333     {
334         return (DT_FIELD_TYPE_FLAGS_INTEGER);
335     }
336
337     /* Type is based upon the opcode for this field in the info table */
338
339     switch (Info->Opcode)
340     {
341     case ACPI_DMT_FLAG0:
342     case ACPI_DMT_FLAG1:
343     case ACPI_DMT_FLAG2:
344     case ACPI_DMT_FLAG3:
345     case ACPI_DMT_FLAG4:
346     case ACPI_DMT_FLAG5:
347     case ACPI_DMT_FLAG6:
348     case ACPI_DMT_FLAG7:
349     case ACPI_DMT_FLAGS0:
350     case ACPI_DMT_FLAGS1:
351     case ACPI_DMT_FLAGS2:
352     case ACPI_DMT_FLAGS4:
353
354         Type = DT_FIELD_TYPE_FLAG;
355         break;
356
357     case ACPI_DMT_NAME4:
358     case ACPI_DMT_SIG:
359     case ACPI_DMT_NAME6:
360     case ACPI_DMT_NAME8:
361     case ACPI_DMT_STRING:
362
363         Type = DT_FIELD_TYPE_STRING;
364         break;
365
366     case ACPI_DMT_BUFFER:
367     case ACPI_DMT_RAW_BUFFER:
368     case ACPI_DMT_BUF7:
369     case ACPI_DMT_BUF10:
370     case ACPI_DMT_BUF16:
371     case ACPI_DMT_BUF128:
372     case ACPI_DMT_PCI_PATH:
373
374         Type = DT_FIELD_TYPE_BUFFER;
375         break;
376
377     case ACPI_DMT_GAS:
378     case ACPI_DMT_HESTNTFY:
379     case ACPI_DMT_IORTMEM:
380
381         Type = DT_FIELD_TYPE_INLINE_SUBTABLE;
382         break;
383
384     case ACPI_DMT_UNICODE:
385
386         Type = DT_FIELD_TYPE_UNICODE;
387         break;
388
389     case ACPI_DMT_UUID:
390
391         Type = DT_FIELD_TYPE_UUID;
392         break;
393
394     case ACPI_DMT_DEVICE_PATH:
395
396         Type = DT_FIELD_TYPE_DEVICE_PATH;
397         break;
398
399     case ACPI_DMT_LABEL:
400
401         Type = DT_FIELD_TYPE_LABEL;
402         break;
403
404     default:
405
406         Type = DT_FIELD_TYPE_INTEGER;
407         break;
408     }
409
410     return (Type);
411 }
412
413
414 /******************************************************************************
415  *
416  * FUNCTION:    DtGetBufferLength
417  *
418  * PARAMETERS:  Buffer              - List of integers,
419  *                                    for example "10 3A 4F 2E"
420  *
421  * RETURN:      Count of integer
422  *
423  * DESCRIPTION: Get length of bytes needed to store the integers
424  *
425  *****************************************************************************/
426
427 UINT32
428 DtGetBufferLength (
429     char                    *Buffer)
430 {
431     UINT32                  ByteLength = 0;
432
433
434     while (*Buffer)
435     {
436         if (*Buffer == ' ')
437         {
438             ByteLength++;
439
440             while (*Buffer == ' ')
441             {
442                 Buffer++;
443             }
444         }
445
446         Buffer++;
447     }
448
449     return (++ByteLength);
450 }
451
452
453 /******************************************************************************
454  *
455  * FUNCTION:    DtGetFieldLength
456  *
457  * PARAMETERS:  Field               - Current field
458  *              Info                - Data table info
459  *
460  * RETURN:      Field length
461  *
462  * DESCRIPTION: Get length of bytes needed to compile the field
463  *
464  * Note: This function must remain in sync with AcpiDmDumpTable.
465  *
466  *****************************************************************************/
467
468 UINT32
469 DtGetFieldLength (
470     DT_FIELD                *Field,
471     ACPI_DMTABLE_INFO       *Info)
472 {
473     UINT32                  ByteLength = 0;
474     char                    *Value;
475
476
477     /* Length is based upon the opcode for this field in the info table */
478
479     switch (Info->Opcode)
480     {
481     case ACPI_DMT_FLAG0:
482     case ACPI_DMT_FLAG1:
483     case ACPI_DMT_FLAG2:
484     case ACPI_DMT_FLAG3:
485     case ACPI_DMT_FLAG4:
486     case ACPI_DMT_FLAG5:
487     case ACPI_DMT_FLAG6:
488     case ACPI_DMT_FLAG7:
489     case ACPI_DMT_FLAGS0:
490     case ACPI_DMT_FLAGS1:
491     case ACPI_DMT_FLAGS2:
492     case ACPI_DMT_FLAGS4:
493     case ACPI_DMT_LABEL:
494     case ACPI_DMT_EXTRA_TEXT:
495
496         ByteLength = 0;
497         break;
498
499     case ACPI_DMT_UINT8:
500     case ACPI_DMT_CHKSUM:
501     case ACPI_DMT_SPACEID:
502     case ACPI_DMT_ACCWIDTH:
503     case ACPI_DMT_IVRS:
504     case ACPI_DMT_GTDT:
505     case ACPI_DMT_MADT:
506     case ACPI_DMT_PCCT:
507     case ACPI_DMT_PMTT:
508     case ACPI_DMT_SRAT:
509     case ACPI_DMT_ASF:
510     case ACPI_DMT_HESTNTYP:
511     case ACPI_DMT_FADTPM:
512     case ACPI_DMT_EINJACT:
513     case ACPI_DMT_EINJINST:
514     case ACPI_DMT_ERSTACT:
515     case ACPI_DMT_ERSTINST:
516     case ACPI_DMT_DMAR_SCOPE:
517
518         ByteLength = 1;
519         break;
520
521     case ACPI_DMT_UINT16:
522     case ACPI_DMT_DMAR:
523     case ACPI_DMT_HEST:
524     case ACPI_DMT_NFIT:
525     case ACPI_DMT_PCI_PATH:
526
527         ByteLength = 2;
528         break;
529
530     case ACPI_DMT_UINT24:
531
532         ByteLength = 3;
533         break;
534
535     case ACPI_DMT_UINT32:
536     case ACPI_DMT_NAME4:
537     case ACPI_DMT_SIG:
538     case ACPI_DMT_LPIT:
539
540         ByteLength = 4;
541         break;
542
543     case ACPI_DMT_UINT40:
544
545         ByteLength = 5;
546         break;
547
548     case ACPI_DMT_UINT48:
549     case ACPI_DMT_NAME6:
550
551         ByteLength = 6;
552         break;
553
554     case ACPI_DMT_UINT56:
555     case ACPI_DMT_BUF7:
556
557         ByteLength = 7;
558         break;
559
560     case ACPI_DMT_UINT64:
561     case ACPI_DMT_NAME8:
562
563         ByteLength = 8;
564         break;
565
566     case ACPI_DMT_STRING:
567
568         Value = DtGetFieldValue (Field);
569         if (Value)
570         {
571             ByteLength = ACPI_STRLEN (Value) + 1;
572         }
573         else
574         {   /* At this point, this is a fatal error */
575
576             sprintf (MsgBuffer, "Expected \"%s\"", Info->Name);
577             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
578             return (0);
579         }
580         break;
581
582     case ACPI_DMT_GAS:
583
584         ByteLength = sizeof (ACPI_GENERIC_ADDRESS);
585         break;
586
587     case ACPI_DMT_HESTNTFY:
588
589         ByteLength = sizeof (ACPI_HEST_NOTIFY);
590         break;
591
592     case ACPI_DMT_IORTMEM:
593
594         ByteLength = sizeof (ACPI_IORT_MEMORY_ACCESS);
595         break;
596
597     case ACPI_DMT_BUFFER:
598     case ACPI_DMT_RAW_BUFFER:
599
600         Value = DtGetFieldValue (Field);
601         if (Value)
602         {
603             ByteLength = DtGetBufferLength (Value);
604         }
605         else
606         {   /* At this point, this is a fatal error */
607
608             sprintf (MsgBuffer, "Expected \"%s\"", Info->Name);
609             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
610             return (0);
611         }
612         break;
613
614     case ACPI_DMT_BUF10:
615
616         ByteLength = 10;
617         break;
618
619     case ACPI_DMT_BUF16:
620     case ACPI_DMT_UUID:
621
622         ByteLength = 16;
623         break;
624
625     case ACPI_DMT_BUF128:
626
627         ByteLength = 128;
628         break;
629
630     case ACPI_DMT_UNICODE:
631
632         Value = DtGetFieldValue (Field);
633
634         /* TBD: error if Value is NULL? (as below?) */
635
636         ByteLength = (ACPI_STRLEN (Value) + 1) * sizeof(UINT16);
637         break;
638
639     default:
640
641         DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid table opcode");
642         return (0);
643     }
644
645     return (ByteLength);
646 }
647
648
649 /******************************************************************************
650  *
651  * FUNCTION:    DtSum
652  *
653  * PARAMETERS:  DT_WALK_CALLBACK:
654  *              Subtable            - Subtable
655  *              Context             - Unused
656  *              ReturnValue         - Store the checksum of subtable
657  *
658  * RETURN:      Status
659  *
660  * DESCRIPTION: Get the checksum of subtable
661  *
662  *****************************************************************************/
663
664 static void
665 DtSum (
666     DT_SUBTABLE             *Subtable,
667     void                    *Context,
668     void                    *ReturnValue)
669 {
670     UINT8                   Checksum;
671     UINT8                   *Sum = ReturnValue;
672
673
674     Checksum = AcpiTbChecksum (Subtable->Buffer, Subtable->Length);
675     *Sum = (UINT8) (*Sum + Checksum);
676 }
677
678
679 /******************************************************************************
680  *
681  * FUNCTION:    DtSetTableChecksum
682  *
683  * PARAMETERS:  ChecksumPointer     - Where to return the checksum
684  *
685  * RETURN:      None
686  *
687  * DESCRIPTION: Set checksum of the whole data table into the checksum field
688  *
689  *****************************************************************************/
690
691 void
692 DtSetTableChecksum (
693     UINT8                   *ChecksumPointer)
694 {
695     UINT8                   Checksum = 0;
696     UINT8                   OldSum;
697
698
699     DtWalkTableTree (Gbl_RootTable, DtSum, NULL, &Checksum);
700
701     OldSum = *ChecksumPointer;
702     Checksum = (UINT8) (Checksum - OldSum);
703
704     /* Compute the final checksum */
705
706     Checksum = (UINT8) (0 - Checksum);
707     *ChecksumPointer = Checksum;
708 }
709
710
711 /******************************************************************************
712  *
713  * FUNCTION:    DtSetTableLength
714  *
715  * PARAMETERS:  None
716  *
717  * RETURN:      None
718  *
719  * DESCRIPTION: Walk the subtables and set all the length fields
720  *
721  *****************************************************************************/
722
723 void
724 DtSetTableLength (
725     void)
726 {
727     DT_SUBTABLE             *ParentTable;
728     DT_SUBTABLE             *ChildTable;
729
730
731     ParentTable = Gbl_RootTable;
732     ChildTable = NULL;
733
734     if (!ParentTable)
735     {
736         return;
737     }
738
739     DtSetSubtableLength (ParentTable);
740
741     while (1)
742     {
743         ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
744         if (ChildTable)
745         {
746             if (ChildTable->LengthField)
747             {
748                 DtSetSubtableLength (ChildTable);
749             }
750
751             if (ChildTable->Child)
752             {
753                 ParentTable = ChildTable;
754                 ChildTable = NULL;
755             }
756             else
757             {
758                 ParentTable->TotalLength += ChildTable->TotalLength;
759                 if (ParentTable->LengthField)
760                 {
761                     DtSetSubtableLength (ParentTable);
762                 }
763             }
764         }
765         else
766         {
767             ChildTable = ParentTable;
768
769             if (ChildTable == Gbl_RootTable)
770             {
771                 break;
772             }
773
774             ParentTable = DtGetParentSubtable (ParentTable);
775
776             ParentTable->TotalLength += ChildTable->TotalLength;
777             if (ParentTable->LengthField)
778             {
779                 DtSetSubtableLength (ParentTable);
780             }
781         }
782     }
783 }
784
785
786 /******************************************************************************
787  *
788  * FUNCTION:    DtWalkTableTree
789  *
790  * PARAMETERS:  StartTable          - Subtable in the tree where walking begins
791  *              UserFunction        - Called during the walk
792  *              Context             - Passed to user function
793  *              ReturnValue         - The return value of UserFunction
794  *
795  * RETURN:      None
796  *
797  * DESCRIPTION: Performs a depth-first walk of the subtable tree
798  *
799  *****************************************************************************/
800
801 void
802 DtWalkTableTree (
803     DT_SUBTABLE             *StartTable,
804     DT_WALK_CALLBACK        UserFunction,
805     void                    *Context,
806     void                    *ReturnValue)
807 {
808     DT_SUBTABLE             *ParentTable;
809     DT_SUBTABLE             *ChildTable;
810
811
812     ParentTable = StartTable;
813     ChildTable = NULL;
814
815     if (!ParentTable)
816     {
817         return;
818     }
819
820     UserFunction (ParentTable, Context, ReturnValue);
821
822     while (1)
823     {
824         ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
825         if (ChildTable)
826         {
827             UserFunction (ChildTable, Context, ReturnValue);
828
829             if (ChildTable->Child)
830             {
831                 ParentTable = ChildTable;
832                 ChildTable = NULL;
833             }
834         }
835         else
836         {
837             ChildTable = ParentTable;
838             if (ChildTable == Gbl_RootTable)
839             {
840                 break;
841             }
842
843             ParentTable = DtGetParentSubtable (ParentTable);
844
845             if (ChildTable->Peer == StartTable)
846             {
847                 break;
848             }
849         }
850     }
851 }
852
853
854 /*******************************************************************************
855  *
856  * FUNCTION:    UtSubtableCacheCalloc
857  *
858  * PARAMETERS:  None
859  *
860  * RETURN:      Pointer to the buffer. Aborts on allocation failure
861  *
862  * DESCRIPTION: Allocate a subtable object buffer. Bypass the local
863  *              dynamic memory manager for performance reasons (This has a
864  *              major impact on the speed of the compiler.)
865  *
866  ******************************************************************************/
867
868 DT_SUBTABLE *
869 UtSubtableCacheCalloc (
870     void)
871 {
872     ASL_CACHE_INFO          *Cache;
873
874
875     if (Gbl_SubtableCacheNext >= Gbl_SubtableCacheLast)
876     {
877         /* Allocate a new buffer */
878
879         Cache = UtLocalCalloc (sizeof (Cache->Next) +
880             (sizeof (DT_SUBTABLE) * ASL_SUBTABLE_CACHE_SIZE));
881
882         /* Link new cache buffer to head of list */
883
884         Cache->Next = Gbl_SubtableCacheList;
885         Gbl_SubtableCacheList = Cache;
886
887         /* Setup cache management pointers */
888
889         Gbl_SubtableCacheNext = ACPI_CAST_PTR (DT_SUBTABLE, Cache->Buffer);
890         Gbl_SubtableCacheLast = Gbl_SubtableCacheNext + ASL_SUBTABLE_CACHE_SIZE;
891     }
892
893     Gbl_SubtableCount++;
894     return (Gbl_SubtableCacheNext++);
895 }
896
897
898 /*******************************************************************************
899  *
900  * FUNCTION:    UtFieldCacheCalloc
901  *
902  * PARAMETERS:  None
903  *
904  * RETURN:      Pointer to the buffer. Aborts on allocation failure
905  *
906  * DESCRIPTION: Allocate a field object buffer. Bypass the local
907  *              dynamic memory manager for performance reasons (This has a
908  *              major impact on the speed of the compiler.)
909  *
910  ******************************************************************************/
911
912 DT_FIELD *
913 UtFieldCacheCalloc (
914     void)
915 {
916     ASL_CACHE_INFO          *Cache;
917
918
919     if (Gbl_FieldCacheNext >= Gbl_FieldCacheLast)
920     {
921         /* Allocate a new buffer */
922
923         Cache = UtLocalCalloc (sizeof (Cache->Next) +
924             (sizeof (DT_FIELD) * ASL_FIELD_CACHE_SIZE));
925
926         /* Link new cache buffer to head of list */
927
928         Cache->Next = Gbl_FieldCacheList;
929         Gbl_FieldCacheList = Cache;
930
931         /* Setup cache management pointers */
932
933         Gbl_FieldCacheNext = ACPI_CAST_PTR (DT_FIELD, Cache->Buffer);
934         Gbl_FieldCacheLast = Gbl_FieldCacheNext + ASL_FIELD_CACHE_SIZE;
935     }
936
937     Gbl_FieldCount++;
938     return (Gbl_FieldCacheNext++);
939 }
940
941
942 /*******************************************************************************
943  *
944  * FUNCTION:    DtDeleteCaches
945  *
946  * PARAMETERS:  None
947  *
948  * RETURN:      None
949  *
950  * DESCRIPTION: Delete all local cache buffer blocks
951  *
952  ******************************************************************************/
953
954 void
955 DtDeleteCaches (
956     void)
957 {
958     UINT32                  BufferCount;
959     ASL_CACHE_INFO          *Next;
960
961
962     /* Field cache */
963
964     BufferCount = 0;
965     while (Gbl_FieldCacheList)
966     {
967         Next = Gbl_FieldCacheList->Next;
968         ACPI_FREE (Gbl_FieldCacheList);
969         Gbl_FieldCacheList = Next;
970         BufferCount++;
971     }
972
973     DbgPrint (ASL_DEBUG_OUTPUT,
974         "%u Fields, Buffer size: %u fields (%u bytes), %u Buffers\n",
975         Gbl_FieldCount, ASL_FIELD_CACHE_SIZE,
976         (sizeof (DT_FIELD) * ASL_FIELD_CACHE_SIZE), BufferCount);
977
978     Gbl_FieldCount = 0;
979     Gbl_FieldCacheNext = NULL;
980     Gbl_FieldCacheLast = NULL;
981
982     /* Subtable cache */
983
984     BufferCount = 0;
985     while (Gbl_SubtableCacheList)
986     {
987         Next = Gbl_SubtableCacheList->Next;
988         ACPI_FREE (Gbl_SubtableCacheList);
989         Gbl_SubtableCacheList = Next;
990         BufferCount++;
991     }
992
993     DbgPrint (ASL_DEBUG_OUTPUT,
994         "%u Subtables, Buffer size: %u subtables (%u bytes), %u Buffers\n",
995         Gbl_SubtableCount, ASL_SUBTABLE_CACHE_SIZE,
996         (sizeof (DT_SUBTABLE) * ASL_SUBTABLE_CACHE_SIZE), BufferCount);
997
998     Gbl_SubtableCount = 0;
999     Gbl_SubtableCacheNext = NULL;
1000     Gbl_SubtableCacheLast = NULL;
1001 }