[PATCH] fix semaphore handling in __unregister_chrdev_region
[linux/fpc-iii.git] / drivers / acpi / utilities / utmath.c
blob2525c1a93547504b8f990e6556894b0fee34d8f2
1 /*******************************************************************************
3 * Module Name: utmath - Integer math support routines
5 ******************************************************************************/
7 /*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
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.
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.
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.
45 #include <acpi/acpi.h>
48 #define _COMPONENT ACPI_UTILITIES
49 ACPI_MODULE_NAME ("utmath")
52 * Support for double-precision integer divide. This code is included here
53 * in order to support kernel environments where the double-precision math
54 * library is not available.
57 #ifndef ACPI_USE_NATIVE_DIVIDE
58 /*******************************************************************************
60 * FUNCTION: acpi_ut_short_divide
62 * PARAMETERS: Dividend - 64-bit dividend
63 * Divisor - 32-bit divisor
64 * out_quotient - Pointer to where the quotient is returned
65 * out_remainder - Pointer to where the remainder is returned
67 * RETURN: Status (Checks for divide-by-zero)
69 * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits)
70 * divide and modulo. The result is a 64-bit quotient and a
71 * 32-bit remainder.
73 ******************************************************************************/
75 acpi_status
76 acpi_ut_short_divide (
77 acpi_integer dividend,
78 u32 divisor,
79 acpi_integer *out_quotient,
80 u32 *out_remainder)
82 union uint64_overlay dividend_ovl;
83 union uint64_overlay quotient;
84 u32 remainder32;
87 ACPI_FUNCTION_TRACE ("ut_short_divide");
90 /* Always check for a zero divisor */
92 if (divisor == 0) {
93 ACPI_REPORT_ERROR (("acpi_ut_short_divide: Divide by zero\n"));
94 return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
97 dividend_ovl.full = dividend;
100 * The quotient is 64 bits, the remainder is always 32 bits,
101 * and is generated by the second divide.
103 ACPI_DIV_64_BY_32 (0, dividend_ovl.part.hi, divisor,
104 quotient.part.hi, remainder32);
105 ACPI_DIV_64_BY_32 (remainder32, dividend_ovl.part.lo, divisor,
106 quotient.part.lo, remainder32);
108 /* Return only what was requested */
110 if (out_quotient) {
111 *out_quotient = quotient.full;
113 if (out_remainder) {
114 *out_remainder = remainder32;
117 return_ACPI_STATUS (AE_OK);
121 /*******************************************************************************
123 * FUNCTION: acpi_ut_divide
125 * PARAMETERS: in_dividend - Dividend
126 * in_divisor - Divisor
127 * out_quotient - Pointer to where the quotient is returned
128 * out_remainder - Pointer to where the remainder is returned
130 * RETURN: Status (Checks for divide-by-zero)
132 * DESCRIPTION: Perform a divide and modulo.
134 ******************************************************************************/
136 acpi_status
137 acpi_ut_divide (
138 acpi_integer in_dividend,
139 acpi_integer in_divisor,
140 acpi_integer *out_quotient,
141 acpi_integer *out_remainder)
143 union uint64_overlay dividend;
144 union uint64_overlay divisor;
145 union uint64_overlay quotient;
146 union uint64_overlay remainder;
147 union uint64_overlay normalized_dividend;
148 union uint64_overlay normalized_divisor;
149 u32 partial1;
150 union uint64_overlay partial2;
151 union uint64_overlay partial3;
154 ACPI_FUNCTION_TRACE ("ut_divide");
157 /* Always check for a zero divisor */
159 if (in_divisor == 0) {
160 ACPI_REPORT_ERROR (("acpi_ut_divide: Divide by zero\n"));
161 return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
164 divisor.full = in_divisor;
165 dividend.full = in_dividend;
166 if (divisor.part.hi == 0) {
168 * 1) Simplest case is where the divisor is 32 bits, we can
169 * just do two divides
171 remainder.part.hi = 0;
174 * The quotient is 64 bits, the remainder is always 32 bits,
175 * and is generated by the second divide.
177 ACPI_DIV_64_BY_32 (0, dividend.part.hi, divisor.part.lo,
178 quotient.part.hi, partial1);
179 ACPI_DIV_64_BY_32 (partial1, dividend.part.lo, divisor.part.lo,
180 quotient.part.lo, remainder.part.lo);
183 else {
185 * 2) The general case where the divisor is a full 64 bits
186 * is more difficult
188 quotient.part.hi = 0;
189 normalized_dividend = dividend;
190 normalized_divisor = divisor;
192 /* Normalize the operands (shift until the divisor is < 32 bits) */
194 do {
195 ACPI_SHIFT_RIGHT_64 (normalized_divisor.part.hi,
196 normalized_divisor.part.lo);
197 ACPI_SHIFT_RIGHT_64 (normalized_dividend.part.hi,
198 normalized_dividend.part.lo);
200 } while (normalized_divisor.part.hi != 0);
202 /* Partial divide */
204 ACPI_DIV_64_BY_32 (normalized_dividend.part.hi,
205 normalized_dividend.part.lo,
206 normalized_divisor.part.lo,
207 quotient.part.lo, partial1);
210 * The quotient is always 32 bits, and simply requires adjustment.
211 * The 64-bit remainder must be generated.
213 partial1 = quotient.part.lo * divisor.part.hi;
214 partial2.full = (acpi_integer) quotient.part.lo * divisor.part.lo;
215 partial3.full = (acpi_integer) partial2.part.hi + partial1;
217 remainder.part.hi = partial3.part.lo;
218 remainder.part.lo = partial2.part.lo;
220 if (partial3.part.hi == 0) {
221 if (partial3.part.lo >= dividend.part.hi) {
222 if (partial3.part.lo == dividend.part.hi) {
223 if (partial2.part.lo > dividend.part.lo) {
224 quotient.part.lo--;
225 remainder.full -= divisor.full;
228 else {
229 quotient.part.lo--;
230 remainder.full -= divisor.full;
234 remainder.full = remainder.full - dividend.full;
235 remainder.part.hi = (u32) -((s32) remainder.part.hi);
236 remainder.part.lo = (u32) -((s32) remainder.part.lo);
238 if (remainder.part.lo) {
239 remainder.part.hi--;
244 /* Return only what was requested */
246 if (out_quotient) {
247 *out_quotient = quotient.full;
249 if (out_remainder) {
250 *out_remainder = remainder.full;
253 return_ACPI_STATUS (AE_OK);
256 #else
258 /*******************************************************************************
260 * FUNCTION: acpi_ut_short_divide, acpi_ut_divide
262 * DESCRIPTION: Native versions of the ut_divide functions. Use these if either
263 * 1) The target is a 64-bit platform and therefore 64-bit
264 * integer math is supported directly by the machine.
265 * 2) The target is a 32-bit or 16-bit platform, and the
266 * double-precision integer math library is available to
267 * perform the divide.
269 ******************************************************************************/
271 acpi_status
272 acpi_ut_short_divide (
273 acpi_integer in_dividend,
274 u32 divisor,
275 acpi_integer *out_quotient,
276 u32 *out_remainder)
279 ACPI_FUNCTION_TRACE ("ut_short_divide");
282 /* Always check for a zero divisor */
284 if (divisor == 0) {
285 ACPI_REPORT_ERROR (("acpi_ut_short_divide: Divide by zero\n"));
286 return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
289 /* Return only what was requested */
291 if (out_quotient) {
292 *out_quotient = in_dividend / divisor;
294 if (out_remainder) {
295 *out_remainder = (u32) in_dividend % divisor;
298 return_ACPI_STATUS (AE_OK);
301 acpi_status
302 acpi_ut_divide (
303 acpi_integer in_dividend,
304 acpi_integer in_divisor,
305 acpi_integer *out_quotient,
306 acpi_integer *out_remainder)
308 ACPI_FUNCTION_TRACE ("ut_divide");
311 /* Always check for a zero divisor */
313 if (in_divisor == 0) {
314 ACPI_REPORT_ERROR (("acpi_ut_divide: Divide by zero\n"));
315 return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
319 /* Return only what was requested */
321 if (out_quotient) {
322 *out_quotient = in_dividend / in_divisor;
324 if (out_remainder) {
325 *out_remainder = in_dividend % in_divisor;
328 return_ACPI_STATUS (AE_OK);
331 #endif