aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/resources/rscalc.c
diff options
context:
space:
mode:
authorRobert Moore <Robert.Moore@intel.com>2005-09-16 16:51:15 -0400
committerLen Brown <len.brown@intel.com>2005-09-21 23:51:39 -0400
commitbda663d36b94c723153246a4231bbc0f1cd1836e (patch)
treecc9f75c1d010d1b99d29f13acd600b21eda5eec5 /drivers/acpi/resources/rscalc.c
parentefb0372bbaf5b829ff8c39db372779928af542a7 (diff)
[ACPI] ACPICA 20050916
Fixed a problem within the Resource Manager where support for the Generic Register descriptor was not fully implemented. This descriptor is now fully recognized, parsed, disassembled, and displayed. Restructured the Resource Manager code to utilize table-driven dispatch and lookup, eliminating many of the large switch() statements. This reduces overall subsystem code size and code complexity. Affects the resource parsing and construction, disassembly, and debug dump output. Cleaned up and restructured the debug dump output for all resource descriptors. Improved readability of the output and reduced code size. Fixed a problem where changes to internal data structures caused the optional ACPI_MUTEX_DEBUG code to fail compilation if specified. Signed-off-by: Robert Moore <Robert.Moore@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/resources/rscalc.c')
-rw-r--r--drivers/acpi/resources/rscalc.c985
1 files changed, 477 insertions, 508 deletions
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
index 378f58390fc1..cd051c97bf5b 100644
--- a/drivers/acpi/resources/rscalc.c
+++ b/drivers/acpi/resources/rscalc.c
@@ -44,651 +44,620 @@
44#include <acpi/acpi.h> 44#include <acpi/acpi.h>
45#include <acpi/acresrc.h> 45#include <acpi/acresrc.h>
46#include <acpi/amlcode.h> 46#include <acpi/amlcode.h>
47#include <acpi/amlresrc.h>
47#include <acpi/acnamesp.h> 48#include <acpi/acnamesp.h>
48 49
49#define _COMPONENT ACPI_RESOURCES 50#define _COMPONENT ACPI_RESOURCES
50ACPI_MODULE_NAME("rscalc") 51ACPI_MODULE_NAME("rscalc")
51 52
53/*
54 * Base sizes for external resource descriptors, indexed by internal type.
55 * Includes size of the descriptor header (1 byte for small descriptors,
56 * 3 bytes for large descriptors)
57 */
58static u8 acpi_gbl_stream_sizes[] = {
59 4, /* ACPI_RSTYPE_IRQ (Byte 3 is optional, but always created) */
60 3, /* ACPI_RSTYPE_DMA */
61 2, /* ACPI_RSTYPE_START_DPF (Byte 1 is optional, but always created) */
62 1, /* ACPI_RSTYPE_END_DPF */
63 8, /* ACPI_RSTYPE_IO */
64 4, /* ACPI_RSTYPE_FIXED_IO */
65 1, /* ACPI_RSTYPE_VENDOR */
66 2, /* ACPI_RSTYPE_END_TAG */
67 12, /* ACPI_RSTYPE_MEM24 */
68 20, /* ACPI_RSTYPE_MEM32 */
69 12, /* ACPI_RSTYPE_FIXED_MEM32 */
70 16, /* ACPI_RSTYPE_ADDRESS16 */
71 26, /* ACPI_RSTYPE_ADDRESS32 */
72 46, /* ACPI_RSTYPE_ADDRESS64 */
73 9, /* ACPI_RSTYPE_EXT_IRQ */
74 15 /* ACPI_RSTYPE_GENERIC_REG */
75};
76
77/*
78 * Base sizes of resource descriptors, both the actual AML stream length and
79 * size of the internal struct representation.
80 */
81typedef struct acpi_resource_sizes {
82 u8 minimum_stream_size;
83 u8 minimum_struct_size;
84
85} ACPI_RESOURCE_SIZES;
86
87static ACPI_RESOURCE_SIZES acpi_gbl_sm_resource_sizes[] = {
88 0, 0, /* 0x00, Reserved */
89 0, 0, /* 0x01, Reserved */
90 0, 0, /* 0x02, Reserved */
91 0, 0, /* 0x03, Reserved */
92 3, ACPI_SIZEOF_RESOURCE(struct acpi_resource_irq), /* ACPI_RDESC_TYPE_IRQ_FORMAT */
93 3, ACPI_SIZEOF_RESOURCE(struct acpi_resource_dma), /* ACPI_RDESC_TYPE_DMA_FORMAT */
94 1, ACPI_SIZEOF_RESOURCE(struct acpi_resource_start_dpf), /* ACPI_RDESC_TYPE_START_DEPENDENT */
95 1, ACPI_RESOURCE_LENGTH, /* ACPI_RDESC_TYPE_END_DEPENDENT */
96 8, ACPI_SIZEOF_RESOURCE(struct acpi_resource_io), /* ACPI_RDESC_TYPE_IO_PORT */
97 4, ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_io), /* ACPI_RDESC_TYPE_FIXED_IO_PORT */
98 0, 0, /* 0x0A, Reserved */
99 0, 0, /* 0x0B, Reserved */
100 0, 0, /* 0x0C, Reserved */
101 0, 0, /* 0x0D, Reserved */
102 1, ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor), /* ACPI_RDESC_TYPE_SMALL_VENDOR */
103 2, ACPI_RESOURCE_LENGTH, /* ACPI_RDESC_TYPE_END_TAG */
104};
105
106static ACPI_RESOURCE_SIZES acpi_gbl_lg_resource_sizes[] = {
107 0, 0, /* 0x00, Reserved */
108 12, ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem24), /* ACPI_RDESC_TYPE_MEMORY_24 */
109 15, ACPI_SIZEOF_RESOURCE(struct acpi_resource_generic_reg), /* ACPI_RDESC_TYPE_GENERIC_REGISTER */
110 0, 0, /* 0x03, Reserved */
111 3, ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor), /* ACPI_RDESC_TYPE_LARGE_VENDOR */
112 20, ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem32), /* ACPI_RDESC_TYPE_MEMORY_32 */
113 12, ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_mem32), /* ACPI_RDESC_TYPE_FIXED_MEMORY_32 */
114 26, ACPI_SIZEOF_RESOURCE(struct acpi_resource_address32), /* ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE */
115 16, ACPI_SIZEOF_RESOURCE(struct acpi_resource_address16), /* ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE */
116 9, ACPI_SIZEOF_RESOURCE(struct acpi_resource_ext_irq), /* ACPI_RDESC_TYPE_EXTENDED_XRUPT */
117 46, ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64), /* ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE */
118 56, ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64), /* ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE */
119};
120
121/* Local prototypes */
122
123static u8 acpi_rs_count_set_bits(u16 bit_field);
124
125static ACPI_RESOURCE_SIZES *acpi_rs_get_resource_sizes(u8 resource_type);
126
127static u16 acpi_rs_get_resource_length(u8 * resource);
128
129static acpi_size
130acpi_rs_struct_option_length(struct acpi_resource_source *resource_source);
131
132static u32
133acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length);
134
52/******************************************************************************* 135/*******************************************************************************
53 * 136 *
54 * FUNCTION: acpi_rs_get_byte_stream_length 137 * FUNCTION: acpi_rs_count_set_bits
55 * 138 *
56 * PARAMETERS: linked_list - Pointer to the resource linked list 139 * PARAMETERS: bit_field - Field in which to count bits
57 * size_needed - u32 pointer of the size buffer needed
58 * to properly return the parsed data
59 * 140 *
60 * RETURN: Status 141 * RETURN: Number of bits set within the field
61 * 142 *
62 * DESCRIPTION: Takes the resource byte stream and parses it once, calculating 143 * DESCRIPTION: Count the number of bits set in a resource field. Used for
63 * the size buffer needed to hold the linked list that conveys 144 * (Short descriptor) interrupt and DMA lists.
64 * the resource data.
65 * 145 *
66 ******************************************************************************/ 146 ******************************************************************************/
67acpi_status
68acpi_rs_get_byte_stream_length(struct acpi_resource *linked_list,
69 acpi_size * size_needed)
70{
71 acpi_size byte_stream_size_needed = 0;
72 acpi_size segment_size;
73 u8 done = FALSE;
74
75 ACPI_FUNCTION_TRACE("rs_get_byte_stream_length");
76 147
77 while (!done) { 148static u8 acpi_rs_count_set_bits(u16 bit_field)
78 /* Init the variable that will hold the size to add to the total. */ 149{
150 u8 bits_set;
79 151
80 segment_size = 0; 152 ACPI_FUNCTION_ENTRY();
81 153
82 switch (linked_list->id) { 154 for (bits_set = 0; bit_field; bits_set++) {
83 case ACPI_RSTYPE_IRQ: 155 /* Zero the least significant bit that is set */
84 /*
85 * IRQ Resource
86 * For an IRQ Resource, Byte 3, although optional, will always be
87 * created - it holds IRQ information.
88 */
89 segment_size = 4;
90 break;
91 156
92 case ACPI_RSTYPE_DMA: 157 bit_field &= (bit_field - 1);
93 /* 158 }
94 * DMA Resource
95 * For this resource the size is static
96 */
97 segment_size = 3;
98 break;
99
100 case ACPI_RSTYPE_START_DPF:
101 /*
102 * Start Dependent Functions Resource
103 * For a start_dependent_functions Resource, Byte 1, although
104 * optional, will always be created.
105 */
106 segment_size = 2;
107 break;
108 159
109 case ACPI_RSTYPE_END_DPF: 160 return (bits_set);
110 /* 161}
111 * End Dependent Functions Resource
112 * For this resource the size is static
113 */
114 segment_size = 1;
115 break;
116 162
117 case ACPI_RSTYPE_IO: 163/*******************************************************************************
118 /* 164 *
119 * IO Port Resource 165 * FUNCTION: acpi_rs_get_resource_sizes
120 * For this resource the size is static 166 *
121 */ 167 * PARAMETERS: resource_type - Byte 0 of a resource descriptor
122 segment_size = 8; 168 *
123 break; 169 * RETURN: Pointer to the resource conversion handler
170 *
171 * DESCRIPTION: Extract the Resource Type/Name from the first byte of
172 * a resource descriptor.
173 *
174 ******************************************************************************/
124 175
125 case ACPI_RSTYPE_FIXED_IO: 176static ACPI_RESOURCE_SIZES *acpi_rs_get_resource_sizes(u8 resource_type)
126 /* 177{
127 * Fixed IO Port Resource 178 ACPI_RESOURCE_SIZES *size_info;
128 * For this resource the size is static
129 */
130 segment_size = 4;
131 break;
132 179
133 case ACPI_RSTYPE_VENDOR: 180 ACPI_FUNCTION_ENTRY();
134 /*
135 * Vendor Defined Resource
136 * For a Vendor Specific resource, if the Length is between 1 and 7
137 * it will be created as a Small Resource data type, otherwise it
138 * is a Large Resource data type.
139 */
140 if (linked_list->data.vendor_specific.length > 7) {
141 segment_size = 3;
142 } else {
143 segment_size = 1;
144 }
145 segment_size +=
146 linked_list->data.vendor_specific.length;
147 break;
148 181
149 case ACPI_RSTYPE_END_TAG: 182 /* Determine if this is a small or large resource */
150 /*
151 * End Tag
152 * For this resource the size is static
153 */
154 segment_size = 2;
155 done = TRUE;
156 break;
157 183
158 case ACPI_RSTYPE_MEM24: 184 if (resource_type & ACPI_RDESC_TYPE_LARGE) {
159 /* 185 /* Large Resource Type -- bits 6:0 contain the name */
160 * 24-Bit Memory Resource
161 * For this resource the size is static
162 */
163 segment_size = 12;
164 break;
165 186
166 case ACPI_RSTYPE_MEM32: 187 if (resource_type > ACPI_RDESC_LARGE_MAX) {
167 /* 188 return (NULL);
168 * 32-Bit Memory Range Resource 189 }
169 * For this resource the size is static
170 */
171 segment_size = 20;
172 break;
173 190
174 case ACPI_RSTYPE_FIXED_MEM32: 191 size_info = &acpi_gbl_lg_resource_sizes[(resource_type &
175 /* 192 ACPI_RDESC_LARGE_MASK)];
176 * 32-Bit Fixed Memory Resource 193 } else {
177 * For this resource the size is static 194 /* Small Resource Type -- bits 6:3 contain the name */
178 */
179 segment_size = 12;
180 break;
181 195
182 case ACPI_RSTYPE_ADDRESS16: 196 size_info = &acpi_gbl_sm_resource_sizes[((resource_type &
183 /* 197 ACPI_RDESC_SMALL_MASK)
184 * 16-Bit Address Resource 198 >> 3)];
185 * The base size of this byte stream is 16. If a Resource Source 199 }
186 * string is not NULL, add 1 for the Index + the length of the null
187 * terminated string Resource Source + 1 for the null.
188 */
189 segment_size = 16;
190
191 if (linked_list->data.address16.resource_source.
192 string_ptr) {
193 segment_size +=
194 linked_list->data.address16.resource_source.
195 string_length;
196 segment_size++;
197 }
198 break;
199 200
200 case ACPI_RSTYPE_ADDRESS32: 201 /* Zero entry indicates an invalid resource type */
201 /*
202 * 32-Bit Address Resource
203 * The base size of this byte stream is 26. If a Resource
204 * Source string is not NULL, add 1 for the Index + the
205 * length of the null terminated string Resource Source +
206 * 1 for the null.
207 */
208 segment_size = 26;
209
210 if (linked_list->data.address32.resource_source.
211 string_ptr) {
212 segment_size +=
213 linked_list->data.address32.resource_source.
214 string_length;
215 segment_size++;
216 }
217 break;
218 202
219 case ACPI_RSTYPE_ADDRESS64: 203 if (!size_info->minimum_stream_size) {
220 /* 204 return (NULL);
221 * 64-Bit Address Resource 205 }
222 * The base size of this byte stream is 46. If a resource_source
223 * string is not NULL, add 1 for the Index + the length of the null
224 * terminated string Resource Source + 1 for the null.
225 */
226 segment_size = 46;
227
228 if (linked_list->data.address64.resource_source.
229 string_ptr) {
230 segment_size +=
231 linked_list->data.address64.resource_source.
232 string_length;
233 segment_size++;
234 }
235 break;
236 206
237 case ACPI_RSTYPE_EXT_IRQ: 207 return (size_info);
238 /* 208}
239 * Extended IRQ Resource
240 * The base size of this byte stream is 9. This is for an Interrupt
241 * table length of 1. For each additional interrupt, add 4.
242 * If a Resource Source string is not NULL, add 1 for the
243 * Index + the length of the null terminated string
244 * Resource Source + 1 for the null.
245 */
246 segment_size = 9 + (((acpi_size)
247 linked_list->data.extended_irq.
248 number_of_interrupts - 1) * 4);
249
250 if (linked_list->data.extended_irq.resource_source.
251 string_ptr) {
252 segment_size +=
253 linked_list->data.extended_irq.
254 resource_source.string_length;
255 segment_size++;
256 }
257 break;
258 209
259 default: 210/*******************************************************************************
211 *
212 * FUNCTION: acpi_rs_get_resource_length
213 *
214 * PARAMETERS: Resource - Pointer to the resource descriptor
215 *
216 * RETURN: Byte length of the (AML byte stream) descriptor. By definition,
217 * this does not include the size of the descriptor header and the
218 * length field itself.
219 *
220 * DESCRIPTION: Extract the length of a resource descriptor.
221 *
222 ******************************************************************************/
260 223
261 /* If we get here, everything is out of sync, exit with error */ 224static u16 acpi_rs_get_resource_length(u8 * resource)
225{
226 u16 resource_length;
262 227
263 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); 228 ACPI_FUNCTION_ENTRY();
264 229
265 } /* switch (linked_list->Id) */ 230 /* Determine if this is a small or large resource */
266 231
267 /* Update the total */ 232 if (*resource & ACPI_RDESC_TYPE_LARGE) {
233 /* Large Resource type -- length is in bytes 1-2 */
268 234
269 byte_stream_size_needed += segment_size; 235 ACPI_MOVE_16_TO_16(&resource_length, (resource + 1));
270 236
271 /* Point to the next object */ 237 } else {
238 /* Small Resource Type -- bits 2:0 of byte 0 contain the length */
272 239
273 linked_list = ACPI_PTR_ADD(struct acpi_resource, 240 resource_length =
274 linked_list, linked_list->length); 241 (u16) (*resource & ACPI_RDESC_SMALL_LENGTH_MASK);
275 } 242 }
276 243
277 /* This is the data the caller needs */ 244 return (resource_length);
278
279 *size_needed = byte_stream_size_needed;
280 return_ACPI_STATUS(AE_OK);
281} 245}
282 246
283/******************************************************************************* 247/*******************************************************************************
284 * 248 *
285 * FUNCTION: acpi_rs_get_list_length 249 * FUNCTION: acpi_rs_struct_option_length
286 * 250 *
287 * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream 251 * PARAMETERS: resource_source - Pointer to optional descriptor field
288 * byte_stream_buffer_length - Size of byte_stream_buffer
289 * size_needed - u32 pointer of the size buffer
290 * needed to properly return the
291 * parsed data
292 * 252 *
293 * RETURN: Status 253 * RETURN: Status
294 * 254 *
295 * DESCRIPTION: Takes the resource byte stream and parses it once, calculating 255 * DESCRIPTION: Common code to handle optional resource_source_index and
296 * the size buffer needed to hold the linked list that conveys 256 * resource_source fields in some Large descriptors. Used during
297 * the resource data. 257 * list-to-stream conversion
298 * 258 *
299 ******************************************************************************/ 259 ******************************************************************************/
300 260
301acpi_status 261static acpi_size
302acpi_rs_get_list_length(u8 * byte_stream_buffer, 262acpi_rs_struct_option_length(struct acpi_resource_source *resource_source)
303 u32 byte_stream_buffer_length, acpi_size * size_needed)
304{ 263{
305 u32 buffer_size = 0; 264 ACPI_FUNCTION_ENTRY();
306 u32 bytes_parsed = 0;
307 u8 number_of_interrupts = 0;
308 u8 number_of_channels = 0;
309 u8 resource_type;
310 u32 structure_size;
311 u32 bytes_consumed;
312 u8 *buffer;
313 u8 temp8;
314 u16 temp16;
315 u8 index;
316 u8 additional_bytes;
317
318 ACPI_FUNCTION_TRACE("rs_get_list_length");
319
320 while (bytes_parsed < byte_stream_buffer_length) {
321 /* The next byte in the stream is the resource type */
322
323 resource_type = acpi_rs_get_resource_type(*byte_stream_buffer);
324 265
325 switch (resource_type) { 266 /*
326 case ACPI_RDESC_TYPE_MEMORY_24: 267 * If the resource_source string is valid, return the size of the string
327 /* 268 * (string_length includes the NULL terminator) plus the size of the
328 * 24-Bit Memory Resource 269 * resource_source_index (1).
329 */ 270 */
330 bytes_consumed = 12; 271 if (resource_source->string_ptr) {
331 272 return ((acpi_size) resource_source->string_length + 1);
332 structure_size = 273 }
333 ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem24);
334 break;
335 274
336 case ACPI_RDESC_TYPE_LARGE_VENDOR: 275 return (0);
337 /* 276}
338 * Vendor Defined Resource
339 */
340 buffer = byte_stream_buffer;
341 ++buffer;
342 277
343 ACPI_MOVE_16_TO_16(&temp16, buffer); 278/*******************************************************************************
344 bytes_consumed = temp16 + 3; 279 *
280 * FUNCTION: acpi_rs_stream_option_length
281 *
282 * PARAMETERS: resource_length - Length from the resource header
283 * minimum_total_length - Minimum length of this resource, before
284 * any optional fields. Includes header size
285 *
286 * RETURN: Length of optional string (0 if no string present)
287 *
288 * DESCRIPTION: Common code to handle optional resource_source_index and
289 * resource_source fields in some Large descriptors. Used during
290 * stream-to-list conversion
291 *
292 ******************************************************************************/
345 293
346 /* Ensure a 32-bit boundary for the structure */ 294static u32
295acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length)
296{
297 u32 string_length = 0;
298 u32 minimum_resource_length;
347 299
348 temp16 = (u16) ACPI_ROUND_UP_to_32_bITS(temp16); 300 ACPI_FUNCTION_ENTRY();
349 301
350 structure_size = 302 /*
351 ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor) + 303 * The resource_source_index and resource_source are optional elements of some
352 (temp16 * sizeof(u8)); 304 * Large-type resource descriptors.
353 break; 305 */
354 306
355 case ACPI_RDESC_TYPE_MEMORY_32: 307 /* Compute minimum size of the data part of the resource descriptor */
356 /*
357 * 32-Bit Memory Range Resource
358 */
359 bytes_consumed = 20;
360 308
361 structure_size = 309 minimum_resource_length =
362 ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem32); 310 minimum_total_length - sizeof(struct asl_large_header);
363 break;
364 311
365 case ACPI_RDESC_TYPE_FIXED_MEMORY_32: 312 /*
366 /* 313 * If the length of the actual resource descriptor is greater than the ACPI
367 * 32-Bit Fixed Memory Resource 314 * spec-defined minimum length, it means that a resource_source_index exists
368 */ 315 * and is followed by a (required) null terminated string. The string length
369 bytes_consumed = 12; 316 * (including the null terminator) is the resource length minus the minimum
317 * length, minus one byte for the resource_source_index itself.
318 */
319 if (resource_length > minimum_resource_length) {
320 /* Compute the length of the optional string */
370 321
371 structure_size = 322 string_length = resource_length - minimum_resource_length - 1;
372 ACPI_SIZEOF_RESOURCE(struct 323 }
373 acpi_resource_fixed_mem32);
374 break;
375 324
376 case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE: 325 /* Round up length to 32 bits for internal structure alignment */
377 /*
378 * 64-Bit Address Resource
379 */
380 buffer = byte_stream_buffer;
381 326
382 ++buffer; 327 return (ACPI_ROUND_UP_to_32_bITS(string_length));
383 ACPI_MOVE_16_TO_16(&temp16, buffer); 328}
384 329
385 bytes_consumed = temp16 + 3; 330/*******************************************************************************
386 structure_size = 331 *
387 ACPI_SIZEOF_RESOURCE(struct 332 * FUNCTION: acpi_rs_get_byte_stream_length
388 acpi_resource_address64); 333 *
389 break; 334 * PARAMETERS: Resource - Pointer to the resource linked list
335 * size_needed - Where the required size is returned
336 *
337 * RETURN: Status
338 *
339 * DESCRIPTION: Takes a linked list of internal resource descriptors and
340 * calculates the size buffer needed to hold the corresponding
341 * external resource byte stream.
342 *
343 ******************************************************************************/
390 344
391 case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE: 345acpi_status
392 /* 346acpi_rs_get_byte_stream_length(struct acpi_resource * resource,
393 * 64-Bit Address Resource 347 acpi_size * size_needed)
394 */ 348{
395 buffer = byte_stream_buffer; 349 acpi_size byte_stream_size_needed = 0;
350 acpi_size segment_size;
396 351
397 ++buffer; 352 ACPI_FUNCTION_TRACE("rs_get_byte_stream_length");
398 ACPI_MOVE_16_TO_16(&temp16, buffer);
399 353
400 bytes_consumed = temp16 + 3; 354 /* Traverse entire list of internal resource descriptors */
401 355
402 /* 356 while (resource) {
403 * Resource Source Index and Resource Source are optional elements. 357 /* Validate the descriptor type */
404 * Check the length of the Bytestream. If it is greater than 43,
405 * that means that an Index exists and is followed by a null
406 * terminated string. Therefore, set the temp variable to the
407 * length minus the minimum byte stream length plus the byte for
408 * the Index to determine the size of the NULL terminated string.
409 */
410 if (43 < temp16) {
411 temp8 = (u8) (temp16 - 44);
412 } else {
413 temp8 = 0;
414 }
415 358
416 /* Ensure a 64-bit boundary for the structure */ 359 if (resource->type > ACPI_RSTYPE_MAX) {
360 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
361 }
417 362
418 temp8 = (u8) ACPI_ROUND_UP_to_64_bITS(temp8); 363 /* Get the base size of the (external stream) resource descriptor */
419 364
420 structure_size = 365 segment_size = acpi_gbl_stream_sizes[resource->type];
421 ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64)
422 + (temp8 * sizeof(u8));
423 break;
424 366
425 case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE: 367 /*
368 * Augment the base size for descriptors with optional and/or
369 * variable-length fields
370 */
371 switch (resource->type) {
372 case ACPI_RSTYPE_VENDOR:
426 /* 373 /*
427 * 32-Bit Address Resource 374 * Vendor Defined Resource:
375 * For a Vendor Specific resource, if the Length is between 1 and 7
376 * it will be created as a Small Resource data type, otherwise it
377 * is a Large Resource data type.
428 */ 378 */
429 buffer = byte_stream_buffer; 379 if (resource->data.vendor_specific.length > 7) {
430 380 /* Base size of a Large resource descriptor */
431 ++buffer;
432 ACPI_MOVE_16_TO_16(&temp16, buffer);
433 381
434 bytes_consumed = temp16 + 3; 382 segment_size = 3;
435
436 /*
437 * Resource Source Index and Resource Source are optional elements.
438 * Check the length of the Bytestream. If it is greater than 23,
439 * that means that an Index exists and is followed by a null
440 * terminated string. Therefore, set the temp variable to the
441 * length minus the minimum byte stream length plus the byte for
442 * the Index to determine the size of the NULL terminated string.
443 */
444 if (23 < temp16) {
445 temp8 = (u8) (temp16 - 24);
446 } else {
447 temp8 = 0;
448 } 383 }
449 384
450 /* Ensure a 32-bit boundary for the structure */ 385 /* Add the size of the vendor-specific data */
451 386
452 temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8); 387 segment_size += resource->data.vendor_specific.length;
453
454 structure_size =
455 ACPI_SIZEOF_RESOURCE(struct acpi_resource_address32)
456 + (temp8 * sizeof(u8));
457 break; 388 break;
458 389
459 case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE: 390 case ACPI_RSTYPE_END_TAG:
460 /* 391 /*
461 * 16-Bit Address Resource 392 * End Tag:
393 * We are done -- return the accumulated total size.
462 */ 394 */
463 buffer = byte_stream_buffer; 395 *size_needed = byte_stream_size_needed + segment_size;
464 396
465 ++buffer; 397 /* Normal exit */
466 ACPI_MOVE_16_TO_16(&temp16, buffer);
467 398
468 bytes_consumed = temp16 + 3; 399 return_ACPI_STATUS(AE_OK);
469 400
401 case ACPI_RSTYPE_ADDRESS16:
470 /* 402 /*
471 * Resource Source Index and Resource Source are optional elements. 403 * 16-Bit Address Resource:
472 * Check the length of the Bytestream. If it is greater than 13, 404 * Add the size of the optional resource_source info
473 * that means that an Index exists and is followed by a null
474 * terminated string. Therefore, set the temp variable to the
475 * length minus the minimum byte stream length plus the byte for
476 * the Index to determine the size of the NULL terminated string.
477 */ 405 */
478 if (13 < temp16) { 406 segment_size +=
479 temp8 = (u8) (temp16 - 14); 407 acpi_rs_struct_option_length(&resource->data.
480 } else { 408 address16.
481 temp8 = 0; 409 resource_source);
482 }
483
484 /* Ensure a 32-bit boundary for the structure */
485
486 temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
487
488 structure_size =
489 ACPI_SIZEOF_RESOURCE(struct acpi_resource_address16)
490 + (temp8 * sizeof(u8));
491 break; 410 break;
492 411
493 case ACPI_RDESC_TYPE_EXTENDED_XRUPT: 412 case ACPI_RSTYPE_ADDRESS32:
494 /*
495 * Extended IRQ
496 */
497 buffer = byte_stream_buffer;
498
499 ++buffer;
500 ACPI_MOVE_16_TO_16(&temp16, buffer);
501
502 bytes_consumed = temp16 + 3;
503
504 /* 413 /*
505 * Point past the length field and the Interrupt vector flags to 414 * 32-Bit Address Resource:
506 * save off the Interrupt table length to the Temp8 variable. 415 * Add the size of the optional resource_source info
507 */ 416 */
508 buffer += 3; 417 segment_size +=
509 temp8 = *buffer; 418 acpi_rs_struct_option_length(&resource->data.
419 address32.
420 resource_source);
421 break;
510 422
423 case ACPI_RSTYPE_ADDRESS64:
511 /* 424 /*
512 * To compensate for multiple interrupt numbers, add 4 bytes for 425 * 64-Bit Address Resource:
513 * each additional interrupts greater than 1 426 * Add the size of the optional resource_source info
514 */ 427 */
515 additional_bytes = (u8) ((temp8 - 1) * 4); 428 segment_size +=
429 acpi_rs_struct_option_length(&resource->data.
430 address64.
431 resource_source);
432 break;
516 433
434 case ACPI_RSTYPE_EXT_IRQ:
517 /* 435 /*
518 * Resource Source Index and Resource Source are optional elements. 436 * Extended IRQ Resource:
519 * Check the length of the Bytestream. If it is greater than 9, 437 * Add the size of each additional optional interrupt beyond the
520 * that means that an Index exists and is followed by a null 438 * required 1 (4 bytes for each u32 interrupt number)
521 * terminated string. Therefore, set the temp variable to the
522 * length minus the minimum byte stream length plus the byte for
523 * the Index to determine the size of the NULL terminated string.
524 */ 439 */
525 if (9 + additional_bytes < temp16) { 440 segment_size += (((acpi_size)
526 temp8 = (u8) (temp16 - (9 + additional_bytes)); 441 resource->data.extended_irq.
527 } else { 442 number_of_interrupts - 1) * 4);
528 temp8 = 0;
529 }
530 443
531 /* Ensure a 32-bit boundary for the structure */ 444 /* Add the size of the optional resource_source info */
532 445
533 temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8); 446 segment_size +=
447 acpi_rs_struct_option_length(&resource->data.
448 extended_irq.
449 resource_source);
450 break;
534 451
535 structure_size = 452 default:
536 ACPI_SIZEOF_RESOURCE(struct acpi_resource_ext_irq) +
537 (additional_bytes * sizeof(u8)) +
538 (temp8 * sizeof(u8));
539 break; 453 break;
454 }
540 455
541 case ACPI_RDESC_TYPE_IRQ_FORMAT: 456 /* Update the total */
542 /*
543 * IRQ Resource.
544 * Determine if it there are two or three trailing bytes
545 */
546 buffer = byte_stream_buffer;
547 temp8 = *buffer;
548 457
549 if (temp8 & 0x01) { 458 byte_stream_size_needed += segment_size;
550 bytes_consumed = 4;
551 } else {
552 bytes_consumed = 3;
553 }
554 459
555 /* Point past the descriptor */ 460 /* Point to the next object */
556 461
557 ++buffer; 462 resource = ACPI_PTR_ADD(struct acpi_resource,
463 resource, resource->length);
464 }
558 465
559 /* Look at the number of bits set */ 466 /* Did not find an END_TAG descriptor */
560 467
561 ACPI_MOVE_16_TO_16(&temp16, buffer); 468 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
469}
562 470
563 for (index = 0; index < 16; index++) { 471/*******************************************************************************
564 if (temp16 & 0x1) { 472 *
565 ++number_of_interrupts; 473 * FUNCTION: acpi_rs_get_list_length
566 } 474 *
475 * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream
476 * byte_stream_buffer_length - Size of byte_stream_buffer
477 * size_needed - Where the size needed is returned
478 *
479 * RETURN: Status
480 *
481 * DESCRIPTION: Takes an external resource byte stream and calculates the size
482 * buffer needed to hold the corresponding internal resource
483 * descriptor linked list.
484 *
485 ******************************************************************************/
567 486
568 temp16 >>= 1; 487acpi_status
569 } 488acpi_rs_get_list_length(u8 * byte_stream_buffer,
489 u32 byte_stream_buffer_length, acpi_size * size_needed)
490{
491 u8 *buffer;
492 ACPI_RESOURCE_SIZES *resource_info;
493 u32 buffer_size = 0;
494 u32 bytes_parsed = 0;
495 u8 resource_type;
496 u16 temp16;
497 u16 resource_length;
498 u16 header_length;
499 u32 extra_struct_bytes;
570 500
571 structure_size = 501 ACPI_FUNCTION_TRACE("rs_get_list_length");
572 ACPI_SIZEOF_RESOURCE(struct acpi_resource_io) +
573 (number_of_interrupts * sizeof(u32));
574 break;
575 502
576 case ACPI_RDESC_TYPE_DMA_FORMAT: 503 while (bytes_parsed < byte_stream_buffer_length) {
577 /* 504 /* The next byte in the stream is the resource descriptor type */
578 * DMA Resource
579 */
580 buffer = byte_stream_buffer;
581 bytes_consumed = 3;
582 505
583 /* Point past the descriptor */ 506 resource_type = acpi_rs_get_resource_type(*byte_stream_buffer);
584 507
585 ++buffer; 508 /* Get the base stream size and structure sizes for the descriptor */
586 509
587 /* Look at the number of bits set */ 510 resource_info = acpi_rs_get_resource_sizes(resource_type);
511 if (!resource_info) {
512 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
513 }
588 514
589 temp8 = *buffer; 515 /* Get the Length field from the input resource descriptor */
590 516
591 for (index = 0; index < 8; index++) { 517 resource_length =
592 if (temp8 & 0x1) { 518 acpi_rs_get_resource_length(byte_stream_buffer);
593 ++number_of_channels;
594 }
595 519
596 temp8 >>= 1; 520 /* Augment the size for descriptors with optional fields */
597 }
598 521
599 structure_size = 522 extra_struct_bytes = 0;
600 ACPI_SIZEOF_RESOURCE(struct acpi_resource_dma) +
601 (number_of_channels * sizeof(u32));
602 break;
603 523
604 case ACPI_RDESC_TYPE_START_DEPENDENT: 524 if (!(resource_type & ACPI_RDESC_TYPE_LARGE)) {
605 /* 525 /*
606 * Start Dependent Functions Resource 526 * Small resource descriptors
607 * Determine if it there are two or three trailing bytes
608 */ 527 */
609 buffer = byte_stream_buffer; 528 header_length = 1;
610 temp8 = *buffer; 529 buffer = byte_stream_buffer + header_length;
611 530
612 if (temp8 & 0x01) { 531 switch (resource_type) {
613 bytes_consumed = 2; 532 case ACPI_RDESC_TYPE_IRQ_FORMAT:
614 } else { 533 /*
615 bytes_consumed = 1; 534 * IRQ Resource:
616 } 535 * Get the number of bits set in the IRQ word
536 */
537 ACPI_MOVE_16_TO_16(&temp16, buffer);
617 538
618 structure_size = 539 extra_struct_bytes =
619 ACPI_SIZEOF_RESOURCE(struct 540 (acpi_rs_count_set_bits(temp16) *
620 acpi_resource_start_dpf); 541 sizeof(u32));
621 break; 542 break;
622 543
623 case ACPI_RDESC_TYPE_END_DEPENDENT: 544 case ACPI_RDESC_TYPE_DMA_FORMAT:
624 /* 545 /*
625 * End Dependent Functions Resource 546 * DMA Resource:
626 */ 547 * Get the number of bits set in the DMA channels byte
627 bytes_consumed = 1; 548 */
628 structure_size = ACPI_RESOURCE_LENGTH; 549 extra_struct_bytes =
629 break; 550 (acpi_rs_count_set_bits((u16) * buffer) *
551 sizeof(u32));
552 break;
630 553
631 case ACPI_RDESC_TYPE_IO_PORT: 554 case ACPI_RDESC_TYPE_SMALL_VENDOR:
632 /* 555 /*
633 * IO Port Resource 556 * Vendor Specific Resource:
634 */ 557 * Ensure a 32-bit boundary for the structure
635 bytes_consumed = 8; 558 */
636 structure_size = 559 extra_struct_bytes =
637 ACPI_SIZEOF_RESOURCE(struct acpi_resource_io); 560 ACPI_ROUND_UP_to_32_bITS(resource_length);
638 break; 561 break;
639 562
640 case ACPI_RDESC_TYPE_FIXED_IO_PORT: 563 case ACPI_RDESC_TYPE_END_TAG:
641 /* 564 /*
642 * Fixed IO Port Resource 565 * End Tag:
643 */ 566 * Terminate the loop now
644 bytes_consumed = 4; 567 */
645 structure_size = 568 byte_stream_buffer_length = bytes_parsed;
646 ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_io); 569 break;
647 break;
648 570
649 case ACPI_RDESC_TYPE_SMALL_VENDOR: 571 default:
572 break;
573 }
574 } else {
650 /* 575 /*
651 * Vendor Specific Resource 576 * Large resource descriptors
652 */ 577 */
653 buffer = byte_stream_buffer; 578 header_length = sizeof(struct asl_large_header);
579 buffer = byte_stream_buffer + header_length;
654 580
655 temp8 = *buffer; 581 switch (resource_type) {
656 temp8 = (u8) (temp8 & 0x7); 582 case ACPI_RDESC_TYPE_LARGE_VENDOR:
657 bytes_consumed = temp8 + 1; 583 /*
584 * Vendor Defined Resource:
585 * Add vendor data and ensure a 32-bit boundary for the structure
586 */
587 extra_struct_bytes =
588 ACPI_ROUND_UP_to_32_bITS(resource_length);
589 break;
658 590
659 /* Ensure a 32-bit boundary for the structure */ 591 case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE:
592 case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE:
593 /*
594 * 32-Bit or 16-bit Address Resource:
595 * Add the size of any optional data (resource_source)
596 */
597 extra_struct_bytes =
598 acpi_rs_stream_option_length
599 (resource_length,
600 resource_info->minimum_stream_size);
601 break;
660 602
661 temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8); 603 case ACPI_RDESC_TYPE_EXTENDED_XRUPT:
662 structure_size = 604 /*
663 ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor) + 605 * Extended IRQ:
664 (temp8 * sizeof(u8)); 606 * Point past the interrupt_vector_flags to get the
665 break; 607 * interrupt_table_length.
608 */
609 buffer++;
666 610
667 case ACPI_RDESC_TYPE_END_TAG: 611 /*
668 /* 612 * Add 4 bytes for each additional interrupt. Note: at least one
669 * End Tag 613 * interrupt is required and is included in the minimum
670 */ 614 * descriptor size
671 bytes_consumed = 2; 615 */
672 structure_size = ACPI_RESOURCE_LENGTH; 616 extra_struct_bytes =
673 byte_stream_buffer_length = bytes_parsed; 617 ((*buffer - 1) * sizeof(u32));
674 break;
675 618
676 default: 619 /* Add the size of any optional data (resource_source) */
677 /*
678 * If we get here, everything is out of sync,
679 * exit with an error
680 */
681 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
682 }
683 620
684 /* Update the return value and counter */ 621 extra_struct_bytes +=
622 acpi_rs_stream_option_length(resource_length
623 -
624 extra_struct_bytes,
625 resource_info->
626 minimum_stream_size);
627 break;
685 628
686 buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE(structure_size); 629 case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
687 bytes_parsed += bytes_consumed; 630 /*
631 * 64-Bit Address Resource:
632 * Add the size of any optional data (resource_source)
633 * Ensure a 64-bit boundary for the structure
634 */
635 extra_struct_bytes =
636 ACPI_ROUND_UP_to_64_bITS
637 (acpi_rs_stream_option_length
638 (resource_length,
639 resource_info->minimum_stream_size));
640 break;
641
642 default:
643 break;
644 }
645 }
646
647 /* Update the required buffer size for the internal descriptor structs */
688 648
689 /* Set the byte stream to point to the next resource */ 649 temp16 =
650 (u16) (resource_info->minimum_struct_size +
651 extra_struct_bytes);
652 buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE(temp16);
690 653
691 byte_stream_buffer += bytes_consumed; 654 /*
655 * Update byte count and point to the next resource within the stream
656 * using the size of the header plus the length contained in the header
657 */
658 temp16 = (u16) (header_length + resource_length);
659 bytes_parsed += temp16;
660 byte_stream_buffer += temp16;
692 } 661 }
693 662
694 /* This is the data the caller needs */ 663 /* This is the data the caller needs */