]> err.no Git - linux-2.6/blob - drivers/acpi/resources/rslist.c
[ACPI] ACPICA 20050916
[linux-2.6] / drivers / acpi / resources / rslist.c
1 /*******************************************************************************
2  *
3  * Module Name: rslist - Linked list utilities
4  *
5  ******************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2005, R. Byron Moore
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 #include <acpi/acpi.h>
45 #include <acpi/acresrc.h>
46
47 #define _COMPONENT          ACPI_RESOURCES
48 ACPI_MODULE_NAME("rslist")
49
50 /* Dispatch table for convert-to-stream functions */
51 typedef
52 acpi_status(*ACPI_STREAM_HANDLER) (struct acpi_resource * resource,
53                                    u8 ** output_buffer,
54                                    acpi_size * bytes_consumed);
55
56 static ACPI_STREAM_HANDLER acpi_gbl_stream_dispatch[] = {
57         acpi_rs_irq_stream,     /* ACPI_RSTYPE_IRQ */
58         acpi_rs_dma_stream,     /* ACPI_RSTYPE_DMA */
59         acpi_rs_start_depend_fns_stream,        /* ACPI_RSTYPE_START_DPF */
60         acpi_rs_end_depend_fns_stream,  /* ACPI_RSTYPE_END_DPF */
61         acpi_rs_io_stream,      /* ACPI_RSTYPE_IO */
62         acpi_rs_fixed_io_stream,        /* ACPI_RSTYPE_FIXED_IO */
63         acpi_rs_vendor_stream,  /* ACPI_RSTYPE_VENDOR */
64         acpi_rs_end_tag_stream, /* ACPI_RSTYPE_END_TAG */
65         acpi_rs_memory24_stream,        /* ACPI_RSTYPE_MEM24 */
66         acpi_rs_memory32_range_stream,  /* ACPI_RSTYPE_MEM32 */
67         acpi_rs_fixed_memory32_stream,  /* ACPI_RSTYPE_FIXED_MEM32 */
68         acpi_rs_address16_stream,       /* ACPI_RSTYPE_ADDRESS16 */
69         acpi_rs_address32_stream,       /* ACPI_RSTYPE_ADDRESS32 */
70         acpi_rs_address64_stream,       /* ACPI_RSTYPE_ADDRESS64 */
71         acpi_rs_extended_irq_stream,    /* ACPI_RSTYPE_EXT_IRQ */
72         acpi_rs_generic_register_stream /* ACPI_RSTYPE_GENERIC_REG */
73 };
74
75 /* Dispatch tables for convert-to-resource functions */
76
77 typedef
78 acpi_status(*ACPI_RESOURCE_HANDLER) (u8 * byte_stream_buffer,
79                                      acpi_size * bytes_consumed,
80                                      u8 ** output_buffer,
81                                      acpi_size * structure_size);
82
83 static ACPI_RESOURCE_HANDLER acpi_gbl_sm_resource_dispatch[] = {
84         NULL,                   /* 0x00, Reserved */
85         NULL,                   /* 0x01, Reserved */
86         NULL,                   /* 0x02, Reserved */
87         NULL,                   /* 0x03, Reserved */
88         acpi_rs_irq_resource,   /* ACPI_RDESC_TYPE_IRQ_FORMAT */
89         acpi_rs_dma_resource,   /* ACPI_RDESC_TYPE_DMA_FORMAT */
90         acpi_rs_start_depend_fns_resource,      /* ACPI_RDESC_TYPE_START_DEPENDENT */
91         acpi_rs_end_depend_fns_resource,        /* ACPI_RDESC_TYPE_END_DEPENDENT */
92         acpi_rs_io_resource,    /* ACPI_RDESC_TYPE_IO_PORT */
93         acpi_rs_fixed_io_resource,      /* ACPI_RDESC_TYPE_FIXED_IO_PORT */
94         NULL,                   /* 0x0A, Reserved */
95         NULL,                   /* 0x0B, Reserved */
96         NULL,                   /* 0x0C, Reserved */
97         NULL,                   /* 0x0D, Reserved */
98         acpi_rs_vendor_resource,        /* ACPI_RDESC_TYPE_SMALL_VENDOR */
99         acpi_rs_end_tag_resource        /* ACPI_RDESC_TYPE_END_TAG */
100 };
101
102 static ACPI_RESOURCE_HANDLER acpi_gbl_lg_resource_dispatch[] = {
103         NULL,                   /* 0x00, Reserved */
104         acpi_rs_memory24_resource,      /* ACPI_RDESC_TYPE_MEMORY_24 */
105         acpi_rs_generic_register_resource,      /* ACPI_RDESC_TYPE_GENERIC_REGISTER */
106         NULL,                   /* 0x03, Reserved */
107         acpi_rs_vendor_resource,        /* ACPI_RDESC_TYPE_LARGE_VENDOR */
108         acpi_rs_memory32_range_resource,        /* ACPI_RDESC_TYPE_MEMORY_32 */
109         acpi_rs_fixed_memory32_resource,        /* ACPI_RDESC_TYPE_FIXED_MEMORY_32 */
110         acpi_rs_address32_resource,     /* ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE */
111         acpi_rs_address16_resource,     /* ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE */
112         acpi_rs_extended_irq_resource,  /* ACPI_RDESC_TYPE_EXTENDED_XRUPT */
113         acpi_rs_address64_resource,     /* ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE */
114         acpi_rs_address64_resource      /* ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE */
115 };
116
117 /* Local prototypes */
118
119 static ACPI_RESOURCE_HANDLER acpi_rs_get_resource_handler(u8 resource_type);
120
121 /*******************************************************************************
122  *
123  * FUNCTION:    acpi_rs_get_resource_type
124  *
125  * PARAMETERS:  resource_type       - Byte 0 of a resource descriptor
126  *
127  * RETURN:      The Resource Type with no extraneous bits (except the large/
128  *              small bit -- left alone)
129  *
130  * DESCRIPTION: Extract the Resource Type/Name from the first byte of
131  *              a resource descriptor.
132  *
133  ******************************************************************************/
134
135 u8 acpi_rs_get_resource_type(u8 resource_type)
136 {
137         ACPI_FUNCTION_ENTRY();
138
139         /* Determine if this is a small or large resource */
140
141         if (resource_type & ACPI_RDESC_TYPE_LARGE) {
142                 /* Large Resource Type -- bits 6:0 contain the name */
143
144                 return (resource_type);
145         } else {
146                 /* Small Resource Type -- bits 6:3 contain the name */
147
148                 return ((u8) (resource_type & ACPI_RDESC_SMALL_MASK));
149         }
150 }
151
152 /*******************************************************************************
153  *
154  * FUNCTION:    acpi_rs_get_resource_handler
155  *
156  * PARAMETERS:  resource_type       - Byte 0 of a resource descriptor
157  *
158  * RETURN:      Pointer to the resource conversion handler
159  *
160  * DESCRIPTION: Extract the Resource Type/Name from the first byte of
161  *              a resource descriptor.
162  *
163  ******************************************************************************/
164
165 static ACPI_RESOURCE_HANDLER acpi_rs_get_resource_handler(u8 resource_type)
166 {
167         ACPI_FUNCTION_ENTRY();
168
169         /* Determine if this is a small or large resource */
170
171         if (resource_type & ACPI_RDESC_TYPE_LARGE) {
172                 /* Large Resource Type -- bits 6:0 contain the name */
173
174                 if (resource_type > ACPI_RDESC_LARGE_MAX) {
175                         return (NULL);
176                 }
177
178                 return (acpi_gbl_lg_resource_dispatch[(resource_type &
179                                                        ACPI_RDESC_LARGE_MASK)]);
180         } else {
181                 /* Small Resource Type -- bits 6:3 contain the name */
182
183                 return (acpi_gbl_sm_resource_dispatch[((resource_type &
184                                                         ACPI_RDESC_SMALL_MASK)
185                                                        >> 3)]);
186         }
187 }
188
189 /*******************************************************************************
190  *
191  * FUNCTION:    acpi_rs_byte_stream_to_list
192  *
193  * PARAMETERS:  byte_stream_buffer      - Pointer to the resource byte stream
194  *              byte_stream_buffer_length - Length of byte_stream_buffer
195  *              output_buffer           - Pointer to the buffer that will
196  *                                        contain the output structures
197  *
198  * RETURN:      Status
199  *
200  * DESCRIPTION: Takes the resource byte stream and parses it, creating a
201  *              linked list of resources in the caller's output buffer
202  *
203  ******************************************************************************/
204
205 acpi_status
206 acpi_rs_byte_stream_to_list(u8 * byte_stream_buffer,
207                             u32 byte_stream_buffer_length, u8 * output_buffer)
208 {
209         u8 *buffer = output_buffer;
210         acpi_status status;
211         acpi_size bytes_parsed = 0;
212         acpi_size bytes_consumed = 0;
213         acpi_size structure_size = 0;
214         struct acpi_resource *resource;
215         ACPI_RESOURCE_HANDLER handler;
216
217         ACPI_FUNCTION_TRACE("rs_byte_stream_to_list");
218
219         /* Loop until end-of-buffer or an end_tag is found */
220
221         while (bytes_parsed < byte_stream_buffer_length) {
222                 /* Get the handler associated with this Descriptor Type */
223
224                 handler = acpi_rs_get_resource_handler(*byte_stream_buffer);
225                 if (handler) {
226                         /* Convert a byte stream resource to local resource struct */
227
228                         status = handler(byte_stream_buffer, &bytes_consumed,
229                                          &buffer, &structure_size);
230                 } else {
231                         /* Invalid resource type */
232
233                         status = AE_AML_INVALID_RESOURCE_TYPE;
234                 }
235
236                 if (ACPI_FAILURE(status)) {
237                         return_ACPI_STATUS(status);
238                 }
239
240                 /* Set the aligned length of the new resource descriptor */
241
242                 resource = ACPI_CAST_PTR(struct acpi_resource, buffer);
243                 resource->length =
244                     (u32) ACPI_ALIGN_RESOURCE_SIZE(resource->length);
245
246                 /* Normal exit on completion of an end_tag resource descriptor */
247
248                 if (acpi_rs_get_resource_type(*byte_stream_buffer) ==
249                     ACPI_RDESC_TYPE_END_TAG) {
250                         return_ACPI_STATUS(AE_OK);
251                 }
252
253                 /* Update counter and point to the next input resource */
254
255                 bytes_parsed += bytes_consumed;
256                 byte_stream_buffer += bytes_consumed;
257
258                 /* Point to the next structure in the output buffer */
259
260                 buffer += ACPI_ALIGN_RESOURCE_SIZE(structure_size);
261         }
262
263         /* Completed buffer, but did not find an end_tag resource descriptor */
264
265         return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
266 }
267
268 /*******************************************************************************
269  *
270  * FUNCTION:    acpi_rs_list_to_byte_stream
271  *
272  * PARAMETERS:  Resource                - Pointer to the resource linked list
273  *              byte_steam_size_needed  - Calculated size of the byte stream
274  *                                        needed from calling
275  *                                        acpi_rs_get_byte_stream_length()
276  *                                        The size of the output_buffer is
277  *                                        guaranteed to be >=
278  *                                        byte_stream_size_needed
279  *              output_buffer           - Pointer to the buffer that will
280  *                                        contain the byte stream
281  *
282  * RETURN:      Status
283  *
284  * DESCRIPTION: Takes the resource linked list and parses it, creating a
285  *              byte stream of resources in the caller's output buffer
286  *
287  ******************************************************************************/
288
289 acpi_status
290 acpi_rs_list_to_byte_stream(struct acpi_resource *resource,
291                             acpi_size byte_stream_size_needed,
292                             u8 * output_buffer)
293 {
294         u8 *buffer = output_buffer;
295         acpi_size bytes_consumed = 0;
296         acpi_status status;
297
298         ACPI_FUNCTION_TRACE("rs_list_to_byte_stream");
299
300         /* Convert each resource descriptor in the list */
301
302         while (1) {
303                 /* Validate Type before dispatch */
304
305                 if (resource->type > ACPI_RSTYPE_MAX) {
306                         ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
307                                           "Invalid descriptor type (%X) in resource list\n",
308                                           resource->type));
309                         return_ACPI_STATUS(AE_BAD_DATA);
310                 }
311
312                 /* Perform the conversion, per resource type */
313
314                 status = acpi_gbl_stream_dispatch[resource->type] (resource,
315                                                                    &buffer,
316                                                                    &bytes_consumed);
317                 if (ACPI_FAILURE(status)) {
318                         return_ACPI_STATUS(status);
319                 }
320
321                 /* Check for end-of-list */
322
323                 if (resource->type == ACPI_RSTYPE_END_TAG) {
324                         /* An End Tag indicates the end of the Resource Template */
325
326                         return_ACPI_STATUS(AE_OK);
327                 }
328
329                 /* Set the Buffer to point to the next (output) resource descriptor */
330
331                 buffer += bytes_consumed;
332
333                 /* Point to the next input resource object */
334
335                 resource = ACPI_PTR_ADD(struct acpi_resource,
336                                         resource, resource->length);
337         }
338 }