]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/dev/acpica/components/utilities/utaddress.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / dev / acpica / components / utilities / utaddress.c
1 /******************************************************************************
2  *
3  * Module Name: utaddress - OpRegion address range check
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2013, 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 __UTADDRESS_C__
45
46 #include <contrib/dev/acpica/include/acpi.h>
47 #include <contrib/dev/acpica/include/accommon.h>
48 #include <contrib/dev/acpica/include/acnamesp.h>
49
50
51 #define _COMPONENT          ACPI_UTILITIES
52         ACPI_MODULE_NAME    ("utaddress")
53
54
55 /*******************************************************************************
56  *
57  * FUNCTION:    AcpiUtAddAddressRange
58  *
59  * PARAMETERS:  SpaceId             - Address space ID
60  *              Address             - OpRegion start address
61  *              Length              - OpRegion length
62  *              RegionNode          - OpRegion namespace node
63  *
64  * RETURN:      Status
65  *
66  * DESCRIPTION: Add the Operation Region address range to the global list.
67  *              The only supported Space IDs are Memory and I/O. Called when
68  *              the OpRegion address/length operands are fully evaluated.
69  *
70  * MUTEX:       Locks the namespace
71  *
72  * NOTE: Because this interface is only called when an OpRegion argument
73  * list is evaluated, there cannot be any duplicate RegionNodes.
74  * Duplicate Address/Length values are allowed, however, so that multiple
75  * address conflicts can be detected.
76  *
77  ******************************************************************************/
78
79 ACPI_STATUS
80 AcpiUtAddAddressRange (
81     ACPI_ADR_SPACE_TYPE     SpaceId,
82     ACPI_PHYSICAL_ADDRESS   Address,
83     UINT32                  Length,
84     ACPI_NAMESPACE_NODE     *RegionNode)
85 {
86     ACPI_ADDRESS_RANGE      *RangeInfo;
87     ACPI_STATUS             Status;
88
89
90     ACPI_FUNCTION_TRACE (UtAddAddressRange);
91
92
93     if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
94         (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
95     {
96         return_ACPI_STATUS (AE_OK);
97     }
98
99     /* Allocate/init a new info block, add it to the appropriate list */
100
101     RangeInfo = ACPI_ALLOCATE (sizeof (ACPI_ADDRESS_RANGE));
102     if (!RangeInfo)
103     {
104         return_ACPI_STATUS (AE_NO_MEMORY);
105     }
106
107     RangeInfo->StartAddress = Address;
108     RangeInfo->EndAddress = (Address + Length - 1);
109     RangeInfo->RegionNode = RegionNode;
110
111     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
112     if (ACPI_FAILURE (Status))
113     {
114         ACPI_FREE (RangeInfo);
115         return_ACPI_STATUS (Status);
116     }
117
118     RangeInfo->Next = AcpiGbl_AddressRangeList[SpaceId];
119     AcpiGbl_AddressRangeList[SpaceId] = RangeInfo;
120
121     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
122         "\nAdded [%4.4s] address range: 0x%p-0x%p\n",
123         AcpiUtGetNodeName (RangeInfo->RegionNode),
124         ACPI_CAST_PTR (void, Address),
125         ACPI_CAST_PTR (void, RangeInfo->EndAddress)));
126
127     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
128     return_ACPI_STATUS (AE_OK);
129 }
130
131
132 /*******************************************************************************
133  *
134  * FUNCTION:    AcpiUtRemoveAddressRange
135  *
136  * PARAMETERS:  SpaceId             - Address space ID
137  *              RegionNode          - OpRegion namespace node
138  *
139  * RETURN:      None
140  *
141  * DESCRIPTION: Remove the Operation Region from the global list. The only
142  *              supported Space IDs are Memory and I/O. Called when an
143  *              OpRegion is deleted.
144  *
145  * MUTEX:       Assumes the namespace is locked
146  *
147  ******************************************************************************/
148
149 void
150 AcpiUtRemoveAddressRange (
151     ACPI_ADR_SPACE_TYPE     SpaceId,
152     ACPI_NAMESPACE_NODE     *RegionNode)
153 {
154     ACPI_ADDRESS_RANGE      *RangeInfo;
155     ACPI_ADDRESS_RANGE      *Prev;
156
157
158     ACPI_FUNCTION_TRACE (UtRemoveAddressRange);
159
160
161     if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
162         (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
163     {
164         return_VOID;
165     }
166
167     /* Get the appropriate list head and check the list */
168
169     RangeInfo = Prev = AcpiGbl_AddressRangeList[SpaceId];
170     while (RangeInfo)
171     {
172         if (RangeInfo->RegionNode == RegionNode)
173         {
174             if (RangeInfo == Prev) /* Found at list head */
175             {
176                 AcpiGbl_AddressRangeList[SpaceId] = RangeInfo->Next;
177             }
178             else
179             {
180                 Prev->Next = RangeInfo->Next;
181             }
182
183             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
184                 "\nRemoved [%4.4s] address range: 0x%p-0x%p\n",
185                 AcpiUtGetNodeName (RangeInfo->RegionNode),
186                 ACPI_CAST_PTR (void, RangeInfo->StartAddress),
187                 ACPI_CAST_PTR (void, RangeInfo->EndAddress)));
188
189             ACPI_FREE (RangeInfo);
190             return_VOID;
191         }
192
193         Prev = RangeInfo;
194         RangeInfo = RangeInfo->Next;
195     }
196
197     return_VOID;
198 }
199
200
201 /*******************************************************************************
202  *
203  * FUNCTION:    AcpiUtCheckAddressRange
204  *
205  * PARAMETERS:  SpaceId             - Address space ID
206  *              Address             - Start address
207  *              Length              - Length of address range
208  *              Warn                - TRUE if warning on overlap desired
209  *
210  * RETURN:      Count of the number of conflicts detected. Zero is always
211  *              returned for Space IDs other than Memory or I/O.
212  *
213  * DESCRIPTION: Check if the input address range overlaps any of the
214  *              ASL operation region address ranges. The only supported
215  *              Space IDs are Memory and I/O.
216  *
217  * MUTEX:       Assumes the namespace is locked.
218  *
219  ******************************************************************************/
220
221 UINT32
222 AcpiUtCheckAddressRange (
223     ACPI_ADR_SPACE_TYPE     SpaceId,
224     ACPI_PHYSICAL_ADDRESS   Address,
225     UINT32                  Length,
226     BOOLEAN                 Warn)
227 {
228     ACPI_ADDRESS_RANGE      *RangeInfo;
229     ACPI_PHYSICAL_ADDRESS   EndAddress;
230     char                    *Pathname;
231     UINT32                  OverlapCount = 0;
232
233
234     ACPI_FUNCTION_TRACE (UtCheckAddressRange);
235
236
237     if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
238         (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
239     {
240         return_UINT32 (0);
241     }
242
243     RangeInfo = AcpiGbl_AddressRangeList[SpaceId];
244     EndAddress = Address + Length - 1;
245
246     /* Check entire list for all possible conflicts */
247
248     while (RangeInfo)
249     {
250         /*
251          * Check if the requested Address/Length overlaps this AddressRange.
252          * Four cases to consider:
253          *
254          * 1) Input address/length is contained completely in the address range
255          * 2) Input address/length overlaps range at the range start
256          * 3) Input address/length overlaps range at the range end
257          * 4) Input address/length completely encompasses the range
258          */
259         if ((Address <= RangeInfo->EndAddress) &&
260             (EndAddress >= RangeInfo->StartAddress))
261         {
262             /* Found an address range overlap */
263
264             OverlapCount++;
265             if (Warn)   /* Optional warning message */
266             {
267                 Pathname = AcpiNsGetExternalPathname (RangeInfo->RegionNode);
268
269                 ACPI_WARNING ((AE_INFO,
270                     "0x%p-0x%p %s conflicts with Region %s %d",
271                     ACPI_CAST_PTR (void, Address),
272                     ACPI_CAST_PTR (void, EndAddress),
273                     AcpiUtGetRegionName (SpaceId), Pathname, OverlapCount));
274                 ACPI_FREE (Pathname);
275             }
276         }
277
278         RangeInfo = RangeInfo->Next;
279     }
280
281     return_UINT32 (OverlapCount);
282 }
283
284
285 /*******************************************************************************
286  *
287  * FUNCTION:    AcpiUtDeleteAddressLists
288  *
289  * PARAMETERS:  None
290  *
291  * RETURN:      None
292  *
293  * DESCRIPTION: Delete all global address range lists (called during
294  *              subsystem shutdown).
295  *
296  ******************************************************************************/
297
298 void
299 AcpiUtDeleteAddressLists (
300     void)
301 {
302     ACPI_ADDRESS_RANGE      *Next;
303     ACPI_ADDRESS_RANGE      *RangeInfo;
304     int                     i;
305
306
307     /* Delete all elements in all address range lists */
308
309     for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++)
310     {
311         Next = AcpiGbl_AddressRangeList[i];
312
313         while (Next)
314         {
315             RangeInfo = Next;
316             Next = RangeInfo->Next;
317             ACPI_FREE (RangeInfo);
318         }
319
320         AcpiGbl_AddressRangeList[i] = NULL;
321     }
322 }