xref: /freebsd/sys/contrib/dev/acpica/components/utilities/utownerid.c (revision f8146b882bc156c1d8ddf14bbea67253ebc064bb)
1efcc2a30SJung-uk Kim /*******************************************************************************
2efcc2a30SJung-uk Kim  *
3efcc2a30SJung-uk Kim  * Module Name: utownerid - Support for Table/Method Owner IDs
4efcc2a30SJung-uk Kim  *
5efcc2a30SJung-uk Kim  ******************************************************************************/
6efcc2a30SJung-uk Kim 
7efcc2a30SJung-uk Kim /*
8*f8146b88SJung-uk Kim  * Copyright (C) 2000 - 2016, Intel Corp.
9efcc2a30SJung-uk Kim  * All rights reserved.
10efcc2a30SJung-uk Kim  *
11efcc2a30SJung-uk Kim  * Redistribution and use in source and binary forms, with or without
12efcc2a30SJung-uk Kim  * modification, are permitted provided that the following conditions
13efcc2a30SJung-uk Kim  * are met:
14efcc2a30SJung-uk Kim  * 1. Redistributions of source code must retain the above copyright
15efcc2a30SJung-uk Kim  *    notice, this list of conditions, and the following disclaimer,
16efcc2a30SJung-uk Kim  *    without modification.
17efcc2a30SJung-uk Kim  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18efcc2a30SJung-uk Kim  *    substantially similar to the "NO WARRANTY" disclaimer below
19efcc2a30SJung-uk Kim  *    ("Disclaimer") and any redistribution must be conditioned upon
20efcc2a30SJung-uk Kim  *    including a substantially similar Disclaimer requirement for further
21efcc2a30SJung-uk Kim  *    binary redistribution.
22efcc2a30SJung-uk Kim  * 3. Neither the names of the above-listed copyright holders nor the names
23efcc2a30SJung-uk Kim  *    of any contributors may be used to endorse or promote products derived
24efcc2a30SJung-uk Kim  *    from this software without specific prior written permission.
25efcc2a30SJung-uk Kim  *
26efcc2a30SJung-uk Kim  * Alternatively, this software may be distributed under the terms of the
27efcc2a30SJung-uk Kim  * GNU General Public License ("GPL") version 2 as published by the Free
28efcc2a30SJung-uk Kim  * Software Foundation.
29efcc2a30SJung-uk Kim  *
30efcc2a30SJung-uk Kim  * NO WARRANTY
31efcc2a30SJung-uk Kim  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32efcc2a30SJung-uk Kim  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33efcc2a30SJung-uk Kim  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34efcc2a30SJung-uk Kim  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35efcc2a30SJung-uk Kim  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36efcc2a30SJung-uk Kim  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37efcc2a30SJung-uk Kim  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38efcc2a30SJung-uk Kim  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39efcc2a30SJung-uk Kim  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40efcc2a30SJung-uk Kim  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41efcc2a30SJung-uk Kim  * POSSIBILITY OF SUCH DAMAGES.
42efcc2a30SJung-uk Kim  */
43efcc2a30SJung-uk Kim 
44efcc2a30SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h>
45efcc2a30SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h>
46efcc2a30SJung-uk Kim #include <contrib/dev/acpica/include/acnamesp.h>
47efcc2a30SJung-uk Kim 
48efcc2a30SJung-uk Kim 
49efcc2a30SJung-uk Kim #define _COMPONENT          ACPI_UTILITIES
50efcc2a30SJung-uk Kim         ACPI_MODULE_NAME    ("utownerid")
51efcc2a30SJung-uk Kim 
52efcc2a30SJung-uk Kim 
53efcc2a30SJung-uk Kim /*******************************************************************************
54efcc2a30SJung-uk Kim  *
55efcc2a30SJung-uk Kim  * FUNCTION:    AcpiUtAllocateOwnerId
56efcc2a30SJung-uk Kim  *
57efcc2a30SJung-uk Kim  * PARAMETERS:  OwnerId         - Where the new owner ID is returned
58efcc2a30SJung-uk Kim  *
59efcc2a30SJung-uk Kim  * RETURN:      Status
60efcc2a30SJung-uk Kim  *
61efcc2a30SJung-uk Kim  * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to
62efcc2a30SJung-uk Kim  *              track objects created by the table or method, to be deleted
63efcc2a30SJung-uk Kim  *              when the method exits or the table is unloaded.
64efcc2a30SJung-uk Kim  *
65efcc2a30SJung-uk Kim  ******************************************************************************/
66efcc2a30SJung-uk Kim 
67efcc2a30SJung-uk Kim ACPI_STATUS
68efcc2a30SJung-uk Kim AcpiUtAllocateOwnerId (
69efcc2a30SJung-uk Kim     ACPI_OWNER_ID           *OwnerId)
70efcc2a30SJung-uk Kim {
71efcc2a30SJung-uk Kim     UINT32                  i;
72efcc2a30SJung-uk Kim     UINT32                  j;
73efcc2a30SJung-uk Kim     UINT32                  k;
74efcc2a30SJung-uk Kim     ACPI_STATUS             Status;
75efcc2a30SJung-uk Kim 
76efcc2a30SJung-uk Kim 
77efcc2a30SJung-uk Kim     ACPI_FUNCTION_TRACE (UtAllocateOwnerId);
78efcc2a30SJung-uk Kim 
79efcc2a30SJung-uk Kim 
80efcc2a30SJung-uk Kim     /* Guard against multiple allocations of ID to the same location */
81efcc2a30SJung-uk Kim 
82efcc2a30SJung-uk Kim     if (*OwnerId)
83efcc2a30SJung-uk Kim     {
84*f8146b88SJung-uk Kim         ACPI_ERROR ((AE_INFO,
85*f8146b88SJung-uk Kim             "Owner ID [0x%2.2X] already exists", *OwnerId));
86efcc2a30SJung-uk Kim         return_ACPI_STATUS (AE_ALREADY_EXISTS);
87efcc2a30SJung-uk Kim     }
88efcc2a30SJung-uk Kim 
89efcc2a30SJung-uk Kim     /* Mutex for the global ID mask */
90efcc2a30SJung-uk Kim 
91efcc2a30SJung-uk Kim     Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
92efcc2a30SJung-uk Kim     if (ACPI_FAILURE (Status))
93efcc2a30SJung-uk Kim     {
94efcc2a30SJung-uk Kim         return_ACPI_STATUS (Status);
95efcc2a30SJung-uk Kim     }
96efcc2a30SJung-uk Kim 
97efcc2a30SJung-uk Kim     /*
98efcc2a30SJung-uk Kim      * Find a free owner ID, cycle through all possible IDs on repeated
99*f8146b88SJung-uk Kim      * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index
100*f8146b88SJung-uk Kim      * may have to be scanned twice.
101efcc2a30SJung-uk Kim      */
102efcc2a30SJung-uk Kim     for (i = 0, j = AcpiGbl_LastOwnerIdIndex;
103efcc2a30SJung-uk Kim          i < (ACPI_NUM_OWNERID_MASKS + 1);
104efcc2a30SJung-uk Kim          i++, j++)
105efcc2a30SJung-uk Kim     {
106efcc2a30SJung-uk Kim         if (j >= ACPI_NUM_OWNERID_MASKS)
107efcc2a30SJung-uk Kim         {
108efcc2a30SJung-uk Kim             j = 0;  /* Wraparound to start of mask array */
109efcc2a30SJung-uk Kim         }
110efcc2a30SJung-uk Kim 
111efcc2a30SJung-uk Kim         for (k = AcpiGbl_NextOwnerIdOffset; k < 32; k++)
112efcc2a30SJung-uk Kim         {
113efcc2a30SJung-uk Kim             if (AcpiGbl_OwnerIdMask[j] == ACPI_UINT32_MAX)
114efcc2a30SJung-uk Kim             {
115efcc2a30SJung-uk Kim                 /* There are no free IDs in this mask */
116efcc2a30SJung-uk Kim 
117efcc2a30SJung-uk Kim                 break;
118efcc2a30SJung-uk Kim             }
119efcc2a30SJung-uk Kim 
120efcc2a30SJung-uk Kim             if (!(AcpiGbl_OwnerIdMask[j] & (1 << k)))
121efcc2a30SJung-uk Kim             {
122efcc2a30SJung-uk Kim                 /*
123efcc2a30SJung-uk Kim                  * Found a free ID. The actual ID is the bit index plus one,
124efcc2a30SJung-uk Kim                  * making zero an invalid Owner ID. Save this as the last ID
125efcc2a30SJung-uk Kim                  * allocated and update the global ID mask.
126efcc2a30SJung-uk Kim                  */
127efcc2a30SJung-uk Kim                 AcpiGbl_OwnerIdMask[j] |= (1 << k);
128efcc2a30SJung-uk Kim 
129efcc2a30SJung-uk Kim                 AcpiGbl_LastOwnerIdIndex = (UINT8) j;
130efcc2a30SJung-uk Kim                 AcpiGbl_NextOwnerIdOffset = (UINT8) (k + 1);
131efcc2a30SJung-uk Kim 
132efcc2a30SJung-uk Kim                 /*
133efcc2a30SJung-uk Kim                  * Construct encoded ID from the index and bit position
134efcc2a30SJung-uk Kim                  *
135efcc2a30SJung-uk Kim                  * Note: Last [j].k (bit 255) is never used and is marked
136efcc2a30SJung-uk Kim                  * permanently allocated (prevents +1 overflow)
137efcc2a30SJung-uk Kim                  */
138efcc2a30SJung-uk Kim                 *OwnerId = (ACPI_OWNER_ID) ((k + 1) + ACPI_MUL_32 (j));
139efcc2a30SJung-uk Kim 
140efcc2a30SJung-uk Kim                 ACPI_DEBUG_PRINT ((ACPI_DB_VALUES,
141efcc2a30SJung-uk Kim                     "Allocated OwnerId: %2.2X\n", (unsigned int) *OwnerId));
142efcc2a30SJung-uk Kim                 goto Exit;
143efcc2a30SJung-uk Kim             }
144efcc2a30SJung-uk Kim         }
145efcc2a30SJung-uk Kim 
146efcc2a30SJung-uk Kim         AcpiGbl_NextOwnerIdOffset = 0;
147efcc2a30SJung-uk Kim     }
148efcc2a30SJung-uk Kim 
149efcc2a30SJung-uk Kim     /*
150efcc2a30SJung-uk Kim      * All OwnerIds have been allocated. This typically should
151efcc2a30SJung-uk Kim      * not happen since the IDs are reused after deallocation. The IDs are
152efcc2a30SJung-uk Kim      * allocated upon table load (one per table) and method execution, and
153efcc2a30SJung-uk Kim      * they are released when a table is unloaded or a method completes
154efcc2a30SJung-uk Kim      * execution.
155efcc2a30SJung-uk Kim      *
156*f8146b88SJung-uk Kim      * If this error happens, there may be very deep nesting of invoked
157*f8146b88SJung-uk Kim      * control methods, or there may be a bug where the IDs are not released.
158efcc2a30SJung-uk Kim      */
159efcc2a30SJung-uk Kim     Status = AE_OWNER_ID_LIMIT;
160efcc2a30SJung-uk Kim     ACPI_ERROR ((AE_INFO,
161efcc2a30SJung-uk Kim         "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT"));
162efcc2a30SJung-uk Kim 
163efcc2a30SJung-uk Kim Exit:
164efcc2a30SJung-uk Kim     (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
165efcc2a30SJung-uk Kim     return_ACPI_STATUS (Status);
166efcc2a30SJung-uk Kim }
167efcc2a30SJung-uk Kim 
168efcc2a30SJung-uk Kim 
169efcc2a30SJung-uk Kim /*******************************************************************************
170efcc2a30SJung-uk Kim  *
171efcc2a30SJung-uk Kim  * FUNCTION:    AcpiUtReleaseOwnerId
172efcc2a30SJung-uk Kim  *
173efcc2a30SJung-uk Kim  * PARAMETERS:  OwnerIdPtr          - Pointer to a previously allocated OwnerID
174efcc2a30SJung-uk Kim  *
175efcc2a30SJung-uk Kim  * RETURN:      None. No error is returned because we are either exiting a
176efcc2a30SJung-uk Kim  *              control method or unloading a table. Either way, we would
177efcc2a30SJung-uk Kim  *              ignore any error anyway.
178efcc2a30SJung-uk Kim  *
179efcc2a30SJung-uk Kim  * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255
180efcc2a30SJung-uk Kim  *
181efcc2a30SJung-uk Kim  ******************************************************************************/
182efcc2a30SJung-uk Kim 
183efcc2a30SJung-uk Kim void
184efcc2a30SJung-uk Kim AcpiUtReleaseOwnerId (
185efcc2a30SJung-uk Kim     ACPI_OWNER_ID           *OwnerIdPtr)
186efcc2a30SJung-uk Kim {
187efcc2a30SJung-uk Kim     ACPI_OWNER_ID           OwnerId = *OwnerIdPtr;
188efcc2a30SJung-uk Kim     ACPI_STATUS             Status;
189efcc2a30SJung-uk Kim     UINT32                  Index;
190efcc2a30SJung-uk Kim     UINT32                  Bit;
191efcc2a30SJung-uk Kim 
192efcc2a30SJung-uk Kim 
193efcc2a30SJung-uk Kim     ACPI_FUNCTION_TRACE_U32 (UtReleaseOwnerId, OwnerId);
194efcc2a30SJung-uk Kim 
195efcc2a30SJung-uk Kim 
196efcc2a30SJung-uk Kim     /* Always clear the input OwnerId (zero is an invalid ID) */
197efcc2a30SJung-uk Kim 
198efcc2a30SJung-uk Kim     *OwnerIdPtr = 0;
199efcc2a30SJung-uk Kim 
200efcc2a30SJung-uk Kim     /* Zero is not a valid OwnerID */
201efcc2a30SJung-uk Kim 
202efcc2a30SJung-uk Kim     if (OwnerId == 0)
203efcc2a30SJung-uk Kim     {
204efcc2a30SJung-uk Kim         ACPI_ERROR ((AE_INFO, "Invalid OwnerId: 0x%2.2X", OwnerId));
205efcc2a30SJung-uk Kim         return_VOID;
206efcc2a30SJung-uk Kim     }
207efcc2a30SJung-uk Kim 
208efcc2a30SJung-uk Kim     /* Mutex for the global ID mask */
209efcc2a30SJung-uk Kim 
210efcc2a30SJung-uk Kim     Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
211efcc2a30SJung-uk Kim     if (ACPI_FAILURE (Status))
212efcc2a30SJung-uk Kim     {
213efcc2a30SJung-uk Kim         return_VOID;
214efcc2a30SJung-uk Kim     }
215efcc2a30SJung-uk Kim 
216efcc2a30SJung-uk Kim     /* Normalize the ID to zero */
217efcc2a30SJung-uk Kim 
218efcc2a30SJung-uk Kim     OwnerId--;
219efcc2a30SJung-uk Kim 
220efcc2a30SJung-uk Kim     /* Decode ID to index/offset pair */
221efcc2a30SJung-uk Kim 
222efcc2a30SJung-uk Kim     Index = ACPI_DIV_32 (OwnerId);
223efcc2a30SJung-uk Kim     Bit = 1 << ACPI_MOD_32 (OwnerId);
224efcc2a30SJung-uk Kim 
225efcc2a30SJung-uk Kim     /* Free the owner ID only if it is valid */
226efcc2a30SJung-uk Kim 
227efcc2a30SJung-uk Kim     if (AcpiGbl_OwnerIdMask[Index] & Bit)
228efcc2a30SJung-uk Kim     {
229efcc2a30SJung-uk Kim         AcpiGbl_OwnerIdMask[Index] ^= Bit;
230efcc2a30SJung-uk Kim     }
231efcc2a30SJung-uk Kim     else
232efcc2a30SJung-uk Kim     {
233efcc2a30SJung-uk Kim         ACPI_ERROR ((AE_INFO,
234efcc2a30SJung-uk Kim             "Release of non-allocated OwnerId: 0x%2.2X", OwnerId + 1));
235efcc2a30SJung-uk Kim     }
236efcc2a30SJung-uk Kim 
237efcc2a30SJung-uk Kim     (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
238efcc2a30SJung-uk Kim     return_VOID;
239efcc2a30SJung-uk Kim }
240