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