aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/resources/rsutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/resources/rsutils.c')
-rw-r--r--drivers/acpi/resources/rsutils.c390
1 files changed, 387 insertions, 3 deletions
diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c
index 4446778eaf79..25b5aedd6612 100644
--- a/drivers/acpi/resources/rsutils.c
+++ b/drivers/acpi/resources/rsutils.c
@@ -5,7 +5,7 @@
5 ******************************************************************************/ 5 ******************************************************************************/
6 6
7/* 7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore 8 * Copyright (C) 2000 - 2006, R. Byron Moore
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,389 @@ ACPI_MODULE_NAME("rsutils")
50 50
51/******************************************************************************* 51/*******************************************************************************
52 * 52 *
53 * FUNCTION: acpi_rs_decode_bitmask
54 *
55 * PARAMETERS: Mask - Bitmask to decode
56 * List - Where the converted list is returned
57 *
58 * RETURN: Count of bits set (length of list)
59 *
60 * DESCRIPTION: Convert a bit mask into a list of values
61 *
62 ******************************************************************************/
63u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
64{
65 acpi_native_uint i;
66 u8 bit_count;
67
68 ACPI_FUNCTION_ENTRY();
69
70 /* Decode the mask bits */
71
72 for (i = 0, bit_count = 0; mask; i++) {
73 if (mask & 0x0001) {
74 list[bit_count] = (u8) i;
75 bit_count++;
76 }
77
78 mask >>= 1;
79 }
80
81 return (bit_count);
82}
83
84/*******************************************************************************
85 *
86 * FUNCTION: acpi_rs_encode_bitmask
87 *
88 * PARAMETERS: List - List of values to encode
89 * Count - Length of list
90 *
91 * RETURN: Encoded bitmask
92 *
93 * DESCRIPTION: Convert a list of values to an encoded bitmask
94 *
95 ******************************************************************************/
96
97u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
98{
99 acpi_native_uint i;
100 u16 mask;
101
102 ACPI_FUNCTION_ENTRY();
103
104 /* Encode the list into a single bitmask */
105
106 for (i = 0, mask = 0; i < count; i++) {
107 mask |= (0x0001 << list[i]);
108 }
109
110 return (mask);
111}
112
113/*******************************************************************************
114 *
115 * FUNCTION: acpi_rs_move_data
116 *
117 * PARAMETERS: Destination - Pointer to the destination descriptor
118 * Source - Pointer to the source descriptor
119 * item_count - How many items to move
120 * move_type - Byte width
121 *
122 * RETURN: None
123 *
124 * DESCRIPTION: Move multiple data items from one descriptor to another. Handles
125 * alignment issues and endian issues if necessary, as configured
126 * via the ACPI_MOVE_* macros. (This is why a memcpy is not used)
127 *
128 ******************************************************************************/
129
130void
131acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
132{
133 acpi_native_uint i;
134
135 ACPI_FUNCTION_ENTRY();
136
137 /* One move per item */
138
139 for (i = 0; i < item_count; i++) {
140 switch (move_type) {
141 /*
142 * For the 8-bit case, we can perform the move all at once
143 * since there are no alignment or endian issues
144 */
145 case ACPI_RSC_MOVE8:
146 ACPI_MEMCPY(destination, source, item_count);
147 return;
148
149 /*
150 * 16-, 32-, and 64-bit cases must use the move macros that perform
151 * endian conversion and/or accomodate hardware that cannot perform
152 * misaligned memory transfers
153 */
154 case ACPI_RSC_MOVE16:
155 ACPI_MOVE_16_TO_16(&ACPI_CAST_PTR(u16, destination)[i],
156 &ACPI_CAST_PTR(u16, source)[i]);
157 break;
158
159 case ACPI_RSC_MOVE32:
160 ACPI_MOVE_32_TO_32(&ACPI_CAST_PTR(u32, destination)[i],
161 &ACPI_CAST_PTR(u32, source)[i]);
162 break;
163
164 case ACPI_RSC_MOVE64:
165 ACPI_MOVE_64_TO_64(&ACPI_CAST_PTR(u64, destination)[i],
166 &ACPI_CAST_PTR(u64, source)[i]);
167 break;
168
169 default:
170 return;
171 }
172 }
173}
174
175/*******************************************************************************
176 *
177 * FUNCTION: acpi_rs_set_resource_length
178 *
179 * PARAMETERS: total_length - Length of the AML descriptor, including
180 * the header and length fields.
181 * Aml - Pointer to the raw AML descriptor
182 *
183 * RETURN: None
184 *
185 * DESCRIPTION: Set the resource_length field of an AML
186 * resource descriptor, both Large and Small descriptors are
187 * supported automatically. Note: Descriptor Type field must
188 * be valid.
189 *
190 ******************************************************************************/
191
192void
193acpi_rs_set_resource_length(acpi_rsdesc_size total_length,
194 union aml_resource *aml)
195{
196 acpi_rs_length resource_length;
197
198 ACPI_FUNCTION_ENTRY();
199
200 /* Length is the total descriptor length minus the header length */
201
202 resource_length = (acpi_rs_length)
203 (total_length - acpi_ut_get_resource_header_length(aml));
204
205 /* Length is stored differently for large and small descriptors */
206
207 if (aml->small_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) {
208 /* Large descriptor -- bytes 1-2 contain the 16-bit length */
209
210 ACPI_MOVE_16_TO_16(&aml->large_header.resource_length,
211 &resource_length);
212 } else {
213 /* Small descriptor -- bits 2:0 of byte 0 contain the length */
214
215 aml->small_header.descriptor_type = (u8)
216
217 /* Clear any existing length, preserving descriptor type bits */
218 ((aml->small_header.
219 descriptor_type & ~ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK)
220
221 | resource_length);
222 }
223}
224
225/*******************************************************************************
226 *
227 * FUNCTION: acpi_rs_set_resource_header
228 *
229 * PARAMETERS: descriptor_type - Byte to be inserted as the type
230 * total_length - Length of the AML descriptor, including
231 * the header and length fields.
232 * Aml - Pointer to the raw AML descriptor
233 *
234 * RETURN: None
235 *
236 * DESCRIPTION: Set the descriptor_type and resource_length fields of an AML
237 * resource descriptor, both Large and Small descriptors are
238 * supported automatically
239 *
240 ******************************************************************************/
241
242void
243acpi_rs_set_resource_header(u8 descriptor_type,
244 acpi_rsdesc_size total_length,
245 union aml_resource *aml)
246{
247 ACPI_FUNCTION_ENTRY();
248
249 /* Set the Resource Type */
250
251 aml->small_header.descriptor_type = descriptor_type;
252
253 /* Set the Resource Length */
254
255 acpi_rs_set_resource_length(total_length, aml);
256}
257
258/*******************************************************************************
259 *
260 * FUNCTION: acpi_rs_strcpy
261 *
262 * PARAMETERS: Destination - Pointer to the destination string
263 * Source - Pointer to the source string
264 *
265 * RETURN: String length, including NULL terminator
266 *
267 * DESCRIPTION: Local string copy that returns the string length, saving a
268 * strcpy followed by a strlen.
269 *
270 ******************************************************************************/
271
272static u16 acpi_rs_strcpy(char *destination, char *source)
273{
274 u16 i;
275
276 ACPI_FUNCTION_ENTRY();
277
278 for (i = 0; source[i]; i++) {
279 destination[i] = source[i];
280 }
281
282 destination[i] = 0;
283
284 /* Return string length including the NULL terminator */
285
286 return ((u16) (i + 1));
287}
288
289/*******************************************************************************
290 *
291 * FUNCTION: acpi_rs_get_resource_source
292 *
293 * PARAMETERS: resource_length - Length field of the descriptor
294 * minimum_length - Minimum length of the descriptor (minus
295 * any optional fields)
296 * resource_source - Where the resource_source is returned
297 * Aml - Pointer to the raw AML descriptor
298 * string_ptr - (optional) where to store the actual
299 * resource_source string
300 *
301 * RETURN: Length of the string plus NULL terminator, rounded up to 32 bit
302 *
303 * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor
304 * to an internal resource descriptor
305 *
306 ******************************************************************************/
307
308acpi_rs_length
309acpi_rs_get_resource_source(acpi_rs_length resource_length,
310 acpi_rs_length minimum_length,
311 struct acpi_resource_source * resource_source,
312 union aml_resource * aml, char *string_ptr)
313{
314 acpi_rsdesc_size total_length;
315 u8 *aml_resource_source;
316
317 ACPI_FUNCTION_ENTRY();
318
319 total_length =
320 resource_length + sizeof(struct aml_resource_large_header);
321 aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length);
322
323 /*
324 * resource_source is present if the length of the descriptor is longer than
325 * the minimum length.
326 *
327 * Note: Some resource descriptors will have an additional null, so
328 * we add 1 to the minimum length.
329 */
330 if (total_length > (acpi_rsdesc_size) (minimum_length + 1)) {
331 /* Get the resource_source_index */
332
333 resource_source->index = aml_resource_source[0];
334
335 resource_source->string_ptr = string_ptr;
336 if (!string_ptr) {
337 /*
338 * String destination pointer is not specified; Set the String
339 * pointer to the end of the current resource_source structure.
340 */
341 resource_source->string_ptr =
342 ACPI_ADD_PTR(char, resource_source,
343 sizeof(struct acpi_resource_source));
344 }
345
346 /*
347 * In order for the struct_size to fall on a 32-bit boundary, calculate
348 * the length of the string (+1 for the NULL terminator) and expand the
349 * struct_size to the next 32-bit boundary.
350 *
351 * Zero the entire area of the buffer.
352 */
353 total_length =
354 ACPI_ROUND_UP_to_32_bITS(ACPI_STRLEN
355 ((char *)&aml_resource_source[1]) +
356 1);
357 ACPI_MEMSET(resource_source->string_ptr, 0, total_length);
358
359 /* Copy the resource_source string to the destination */
360
361 resource_source->string_length =
362 acpi_rs_strcpy(resource_source->string_ptr,
363 (char *)&aml_resource_source[1]);
364
365 return ((acpi_rs_length) total_length);
366 }
367
368 /* resource_source is not present */
369
370 resource_source->index = 0;
371 resource_source->string_length = 0;
372 resource_source->string_ptr = NULL;
373 return (0);
374}
375
376/*******************************************************************************
377 *
378 * FUNCTION: acpi_rs_set_resource_source
379 *
380 * PARAMETERS: Aml - Pointer to the raw AML descriptor
381 * minimum_length - Minimum length of the descriptor (minus
382 * any optional fields)
383 * resource_source - Internal resource_source
384
385 *
386 * RETURN: Total length of the AML descriptor
387 *
388 * DESCRIPTION: Convert an optional resource_source from internal format to a
389 * raw AML resource descriptor
390 *
391 ******************************************************************************/
392
393acpi_rsdesc_size
394acpi_rs_set_resource_source(union aml_resource * aml,
395 acpi_rs_length minimum_length,
396 struct acpi_resource_source * resource_source)
397{
398 u8 *aml_resource_source;
399 acpi_rsdesc_size descriptor_length;
400
401 ACPI_FUNCTION_ENTRY();
402
403 descriptor_length = minimum_length;
404
405 /* Non-zero string length indicates presence of a resource_source */
406
407 if (resource_source->string_length) {
408 /* Point to the end of the AML descriptor */
409
410 aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length);
411
412 /* Copy the resource_source_index */
413
414 aml_resource_source[0] = (u8) resource_source->index;
415
416 /* Copy the resource_source string */
417
418 ACPI_STRCPY((char *)&aml_resource_source[1],
419 resource_source->string_ptr);
420
421 /*
422 * Add the length of the string (+ 1 for null terminator) to the
423 * final descriptor length
424 */
425 descriptor_length +=
426 ((acpi_rsdesc_size) resource_source->string_length + 1);
427 }
428
429 /* Return the new total length of the AML descriptor */
430
431 return (descriptor_length);
432}
433
434/*******************************************************************************
435 *
53 * FUNCTION: acpi_rs_get_prt_method_data 436 * FUNCTION: acpi_rs_get_prt_method_data
54 * 437 *
55 * PARAMETERS: Handle - a handle to the containing object 438 * PARAMETERS: Handle - a handle to the containing object
@@ -65,8 +448,9 @@ ACPI_MODULE_NAME("rsutils")
65 * and the contents of the callers buffer is undefined. 448 * and the contents of the callers buffer is undefined.
66 * 449 *
67 ******************************************************************************/ 450 ******************************************************************************/
451
68acpi_status 452acpi_status
69acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) 453acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer)
70{ 454{
71 union acpi_operand_object *obj_desc; 455 union acpi_operand_object *obj_desc;
72 acpi_status status; 456 acpi_status status;
@@ -284,7 +668,7 @@ acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer)
284 * Convert the linked list into a byte stream 668 * Convert the linked list into a byte stream
285 */ 669 */
286 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 670 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
287 status = acpi_rs_create_byte_stream(in_buffer->pointer, &buffer); 671 status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer);
288 if (ACPI_FAILURE(status)) { 672 if (ACPI_FAILURE(status)) {
289 return_ACPI_STATUS(status); 673 return_ACPI_STATUS(status);
290 } 674 }