Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /******************************************************************************* |
2 | * | |
3 | * Module Name: rsaddr - Address resource descriptors (16/32/64) | |
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 | ||
45 | #include <acpi/acpi.h> | |
46 | #include <acpi/acresrc.h> | |
47 | ||
48 | #define _COMPONENT ACPI_RESOURCES | |
49 | ACPI_MODULE_NAME ("rsaddr") | |
50 | ||
51 | ||
52 | /******************************************************************************* | |
53 | * | |
54 | * FUNCTION: acpi_rs_address16_resource | |
55 | * | |
56 | * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte | |
57 | * stream | |
58 | * bytes_consumed - Pointer to where the number of bytes | |
59 | * consumed the byte_stream_buffer is | |
60 | * returned | |
61 | * output_buffer - Pointer to the return data buffer | |
62 | * structure_size - Pointer to where the number of bytes | |
63 | * in the return data struct is returned | |
64 | * | |
65 | * RETURN: Status | |
66 | * | |
67 | * DESCRIPTION: Take the resource byte stream and fill out the appropriate | |
68 | * structure pointed to by the output_buffer. Return the | |
69 | * number of bytes consumed from the byte stream. | |
70 | * | |
71 | ******************************************************************************/ | |
72 | ||
73 | acpi_status | |
74 | acpi_rs_address16_resource ( | |
75 | u8 *byte_stream_buffer, | |
76 | acpi_size *bytes_consumed, | |
77 | u8 **output_buffer, | |
78 | acpi_size *structure_size) | |
79 | { | |
80 | u8 *buffer = byte_stream_buffer; | |
81 | struct acpi_resource *output_struct = (void *) *output_buffer; | |
82 | u8 *temp_ptr; | |
83 | acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address16); | |
84 | u32 index; | |
85 | u16 temp16; | |
86 | u8 temp8; | |
87 | ||
88 | ||
89 | ACPI_FUNCTION_TRACE ("rs_address16_resource"); | |
90 | ||
91 | ||
92 | /* | |
93 | * Point past the Descriptor to get the number of bytes consumed | |
94 | */ | |
95 | buffer += 1; | |
96 | ACPI_MOVE_16_TO_16 (&temp16, buffer); | |
97 | ||
98 | /* Validate minimum descriptor length */ | |
99 | ||
100 | if (temp16 < 13) { | |
101 | return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); | |
102 | } | |
103 | ||
104 | *bytes_consumed = temp16 + 3; | |
105 | output_struct->id = ACPI_RSTYPE_ADDRESS16; | |
106 | ||
107 | /* | |
108 | * Get the Resource Type (Byte3) | |
109 | */ | |
110 | buffer += 2; | |
111 | temp8 = *buffer; | |
112 | ||
113 | /* Values 0-2 and 0xC0-0xFF are valid */ | |
114 | ||
115 | if ((temp8 > 2) && (temp8 < 0xC0)) { | |
116 | return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); | |
117 | } | |
118 | ||
119 | output_struct->data.address16.resource_type = temp8; | |
120 | ||
121 | /* | |
122 | * Get the General Flags (Byte4) | |
123 | */ | |
124 | buffer += 1; | |
125 | temp8 = *buffer; | |
126 | ||
127 | /* Producer / Consumer */ | |
128 | ||
129 | output_struct->data.address16.producer_consumer = temp8 & 0x01; | |
130 | ||
131 | /* Decode */ | |
132 | ||
133 | output_struct->data.address16.decode = (temp8 >> 1) & 0x01; | |
134 | ||
135 | /* Min Address Fixed */ | |
136 | ||
137 | output_struct->data.address16.min_address_fixed = (temp8 >> 2) & 0x01; | |
138 | ||
139 | /* Max Address Fixed */ | |
140 | ||
141 | output_struct->data.address16.max_address_fixed = (temp8 >> 3) & 0x01; | |
142 | ||
143 | /* | |
144 | * Get the Type Specific Flags (Byte5) | |
145 | */ | |
146 | buffer += 1; | |
147 | temp8 = *buffer; | |
148 | ||
149 | if (ACPI_MEMORY_RANGE == output_struct->data.address16.resource_type) { | |
150 | output_struct->data.address16.attribute.memory.read_write_attribute = | |
151 | (u16) (temp8 & 0x01); | |
152 | output_struct->data.address16.attribute.memory.cache_attribute = | |
153 | (u16) ((temp8 >> 1) & 0x03); | |
154 | } | |
155 | else { | |
156 | if (ACPI_IO_RANGE == output_struct->data.address16.resource_type) { | |
157 | output_struct->data.address16.attribute.io.range_attribute = | |
158 | (u16) (temp8 & 0x03); | |
159 | output_struct->data.address16.attribute.io.translation_attribute = | |
160 | (u16) ((temp8 >> 4) & 0x03); | |
161 | } | |
162 | else { | |
163 | /* BUS_NUMBER_RANGE == Address16.Data->resource_type */ | |
164 | /* Nothing needs to be filled in */ | |
165 | } | |
166 | } | |
167 | ||
168 | /* | |
169 | * Get Granularity (Bytes 6-7) | |
170 | */ | |
171 | buffer += 1; | |
172 | ACPI_MOVE_16_TO_32 (&output_struct->data.address16.granularity, buffer); | |
173 | ||
174 | /* | |
175 | * Get min_address_range (Bytes 8-9) | |
176 | */ | |
177 | buffer += 2; | |
178 | ACPI_MOVE_16_TO_32 (&output_struct->data.address16.min_address_range, buffer); | |
179 | ||
180 | /* | |
181 | * Get max_address_range (Bytes 10-11) | |
182 | */ | |
183 | buffer += 2; | |
184 | ACPI_MOVE_16_TO_32 (&output_struct->data.address16.max_address_range, buffer); | |
185 | ||
186 | /* | |
187 | * Get address_translation_offset (Bytes 12-13) | |
188 | */ | |
189 | buffer += 2; | |
190 | ACPI_MOVE_16_TO_32 (&output_struct->data.address16.address_translation_offset, buffer); | |
191 | ||
192 | /* | |
193 | * Get address_length (Bytes 14-15) | |
194 | */ | |
195 | buffer += 2; | |
196 | ACPI_MOVE_16_TO_32 (&output_struct->data.address16.address_length, buffer); | |
197 | ||
198 | /* | |
199 | * Resource Source Index (if present) | |
200 | */ | |
201 | buffer += 2; | |
202 | ||
203 | /* | |
204 | * This will leave us pointing to the Resource Source Index | |
205 | * If it is present, then save it off and calculate the | |
206 | * pointer to where the null terminated string goes: | |
207 | * Each Interrupt takes 32-bits + the 5 bytes of the | |
208 | * stream that are default. | |
209 | * | |
210 | * Note: Some resource descriptors will have an additional null, so | |
211 | * we add 1 to the length. | |
212 | */ | |
213 | if (*bytes_consumed > (16 + 1)) { | |
214 | /* Dereference the Index */ | |
215 | ||
216 | temp8 = *buffer; | |
217 | output_struct->data.address16.resource_source.index = (u32) temp8; | |
218 | ||
219 | /* Point to the String */ | |
220 | ||
221 | buffer += 1; | |
222 | ||
223 | /* Point the String pointer to the end of this structure */ | |
224 | ||
225 | output_struct->data.address16.resource_source.string_ptr = | |
226 | (char *)((u8 * )output_struct + struct_size); | |
227 | ||
228 | temp_ptr = (u8 *) output_struct->data.address16.resource_source.string_ptr; | |
229 | ||
230 | /* Copy the string into the buffer */ | |
231 | ||
232 | index = 0; | |
233 | ||
234 | while (0x00 != *buffer) { | |
235 | *temp_ptr = *buffer; | |
236 | ||
237 | temp_ptr += 1; | |
238 | buffer += 1; | |
239 | index += 1; | |
240 | } | |
241 | ||
242 | /* | |
243 | * Add the terminating null | |
244 | */ | |
245 | *temp_ptr = 0x00; | |
246 | ||
247 | output_struct->data.address16.resource_source.string_length = index + 1; | |
248 | ||
249 | /* | |
250 | * In order for the struct_size to fall on a 32-bit boundary, | |
251 | * calculate the length of the string and expand the | |
252 | * struct_size to the next 32-bit boundary. | |
253 | */ | |
254 | temp8 = (u8) (index + 1); | |
255 | struct_size += ACPI_ROUND_UP_to_32_bITS (temp8); | |
256 | } | |
257 | else { | |
258 | output_struct->data.address16.resource_source.index = 0x00; | |
259 | output_struct->data.address16.resource_source.string_length = 0; | |
260 | output_struct->data.address16.resource_source.string_ptr = NULL; | |
261 | } | |
262 | ||
263 | /* | |
264 | * Set the Length parameter | |
265 | */ | |
266 | output_struct->length = (u32) struct_size; | |
267 | ||
268 | /* | |
269 | * Return the final size of the structure | |
270 | */ | |
271 | *structure_size = struct_size; | |
272 | return_ACPI_STATUS (AE_OK); | |
273 | } | |
274 | ||
275 | ||
276 | /******************************************************************************* | |
277 | * | |
278 | * FUNCTION: acpi_rs_address16_stream | |
279 | * | |
280 | * PARAMETERS: linked_list - Pointer to the resource linked list | |
281 | * output_buffer - Pointer to the user's return buffer | |
282 | * bytes_consumed - Pointer to where the number of bytes | |
283 | * used in the output_buffer is returned | |
284 | * | |
285 | * RETURN: Status | |
286 | * | |
287 | * DESCRIPTION: Take the linked list resource structure and fills in the | |
288 | * the appropriate bytes in a byte stream | |
289 | * | |
290 | ******************************************************************************/ | |
291 | ||
292 | acpi_status | |
293 | acpi_rs_address16_stream ( | |
294 | struct acpi_resource *linked_list, | |
295 | u8 **output_buffer, | |
296 | acpi_size *bytes_consumed) | |
297 | { | |
298 | u8 *buffer = *output_buffer; | |
299 | u8 *length_field; | |
300 | u8 temp8; | |
301 | char *temp_pointer = NULL; | |
302 | acpi_size actual_bytes; | |
303 | ||
304 | ||
305 | ACPI_FUNCTION_TRACE ("rs_address16_stream"); | |
306 | ||
307 | ||
308 | /* | |
309 | * The descriptor field is static | |
310 | */ | |
311 | *buffer = 0x88; | |
312 | buffer += 1; | |
313 | ||
314 | /* | |
315 | * Save a pointer to the Length field - to be filled in later | |
316 | */ | |
317 | length_field = buffer; | |
318 | buffer += 2; | |
319 | ||
320 | /* | |
321 | * Set the Resource Type (Memory, Io, bus_number) | |
322 | */ | |
323 | temp8 = (u8) (linked_list->data.address16.resource_type & 0x03); | |
324 | *buffer = temp8; | |
325 | buffer += 1; | |
326 | ||
327 | /* | |
328 | * Set the general flags | |
329 | */ | |
330 | temp8 = (u8) (linked_list->data.address16.producer_consumer & 0x01); | |
331 | ||
332 | temp8 |= (linked_list->data.address16.decode & 0x01) << 1; | |
333 | temp8 |= (linked_list->data.address16.min_address_fixed & 0x01) << 2; | |
334 | temp8 |= (linked_list->data.address16.max_address_fixed & 0x01) << 3; | |
335 | ||
336 | *buffer = temp8; | |
337 | buffer += 1; | |
338 | ||
339 | /* | |
340 | * Set the type specific flags | |
341 | */ | |
342 | temp8 = 0; | |
343 | ||
344 | if (ACPI_MEMORY_RANGE == linked_list->data.address16.resource_type) { | |
345 | temp8 = (u8) | |
346 | (linked_list->data.address16.attribute.memory.read_write_attribute & | |
347 | 0x01); | |
348 | ||
349 | temp8 |= | |
350 | (linked_list->data.address16.attribute.memory.cache_attribute & | |
351 | 0x03) << 1; | |
352 | } | |
353 | else if (ACPI_IO_RANGE == linked_list->data.address16.resource_type) { | |
354 | temp8 = (u8) | |
355 | (linked_list->data.address16.attribute.io.range_attribute & | |
356 | 0x03); | |
357 | temp8 |= | |
358 | (linked_list->data.address16.attribute.io.translation_attribute & | |
359 | 0x03) << 4; | |
360 | } | |
361 | ||
362 | *buffer = temp8; | |
363 | buffer += 1; | |
364 | ||
365 | /* | |
366 | * Set the address space granularity | |
367 | */ | |
368 | ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.granularity); | |
369 | buffer += 2; | |
370 | ||
371 | /* | |
372 | * Set the address range minimum | |
373 | */ | |
374 | ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.min_address_range); | |
375 | buffer += 2; | |
376 | ||
377 | /* | |
378 | * Set the address range maximum | |
379 | */ | |
380 | ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.max_address_range); | |
381 | buffer += 2; | |
382 | ||
383 | /* | |
384 | * Set the address translation offset | |
385 | */ | |
386 | ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.address_translation_offset); | |
387 | buffer += 2; | |
388 | ||
389 | /* | |
390 | * Set the address length | |
391 | */ | |
392 | ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.address_length); | |
393 | buffer += 2; | |
394 | ||
395 | /* | |
396 | * Resource Source Index and Resource Source are optional | |
397 | */ | |
398 | if (0 != linked_list->data.address16.resource_source.string_length) { | |
399 | temp8 = (u8) linked_list->data.address16.resource_source.index; | |
400 | ||
401 | *buffer = temp8; | |
402 | buffer += 1; | |
403 | ||
404 | temp_pointer = (char *) buffer; | |
405 | ||
406 | /* | |
407 | * Copy the string | |
408 | */ | |
409 | ACPI_STRCPY (temp_pointer, | |
410 | linked_list->data.address16.resource_source.string_ptr); | |
411 | ||
412 | /* | |
413 | * Buffer needs to be set to the length of the sting + one for the | |
414 | * terminating null | |
415 | */ | |
416 | buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.address16.resource_source.string_ptr) + 1); | |
417 | } | |
418 | ||
419 | /* | |
420 | * Return the number of bytes consumed in this operation | |
421 | */ | |
422 | actual_bytes = ACPI_PTR_DIFF (buffer, *output_buffer); | |
423 | *bytes_consumed = actual_bytes; | |
424 | ||
425 | /* | |
426 | * Set the length field to the number of bytes consumed | |
427 | * minus the header size (3 bytes) | |
428 | */ | |
429 | actual_bytes -= 3; | |
430 | ACPI_MOVE_SIZE_TO_16 (length_field, &actual_bytes); | |
431 | return_ACPI_STATUS (AE_OK); | |
432 | } | |
433 | ||
434 | ||
435 | /******************************************************************************* | |
436 | * | |
437 | * FUNCTION: acpi_rs_address32_resource | |
438 | * | |
439 | * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte | |
440 | * stream | |
441 | * bytes_consumed - Pointer to where the number of bytes | |
442 | * consumed the byte_stream_buffer is | |
443 | * returned | |
444 | * output_buffer - Pointer to the return data buffer | |
445 | * structure_size - Pointer to where the number of bytes | |
446 | * in the return data struct is returned | |
447 | * | |
448 | * RETURN: Status | |
449 | * | |
450 | * DESCRIPTION: Take the resource byte stream and fill out the appropriate | |
451 | * structure pointed to by the output_buffer. Return the | |
452 | * number of bytes consumed from the byte stream. | |
453 | * | |
454 | ******************************************************************************/ | |
455 | ||
456 | acpi_status | |
457 | acpi_rs_address32_resource ( | |
458 | u8 *byte_stream_buffer, | |
459 | acpi_size *bytes_consumed, | |
460 | u8 **output_buffer, | |
461 | acpi_size *structure_size) | |
462 | { | |
463 | u8 *buffer; | |
464 | struct acpi_resource *output_struct= (void *) *output_buffer; | |
465 | u16 temp16; | |
466 | u8 temp8; | |
467 | u8 *temp_ptr; | |
468 | acpi_size struct_size; | |
469 | u32 index; | |
470 | ||
471 | ||
472 | ACPI_FUNCTION_TRACE ("rs_address32_resource"); | |
473 | ||
474 | ||
475 | buffer = byte_stream_buffer; | |
476 | struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address32); | |
477 | ||
478 | /* | |
479 | * Point past the Descriptor to get the number of bytes consumed | |
480 | */ | |
481 | buffer += 1; | |
482 | ACPI_MOVE_16_TO_16 (&temp16, buffer); | |
483 | ||
484 | /* Validate minimum descriptor length */ | |
485 | ||
486 | if (temp16 < 23) { | |
487 | return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); | |
488 | } | |
489 | ||
490 | *bytes_consumed = temp16 + 3; | |
491 | output_struct->id = ACPI_RSTYPE_ADDRESS32; | |
492 | ||
493 | /* | |
494 | * Get the Resource Type (Byte3) | |
495 | */ | |
496 | buffer += 2; | |
497 | temp8 = *buffer; | |
498 | ||
499 | /* Values 0-2 and 0xC0-0xFF are valid */ | |
500 | ||
501 | if ((temp8 > 2) && (temp8 < 0xC0)) { | |
502 | return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); | |
503 | } | |
504 | ||
505 | output_struct->data.address32.resource_type = temp8; | |
506 | ||
507 | /* | |
508 | * Get the General Flags (Byte4) | |
509 | */ | |
510 | buffer += 1; | |
511 | temp8 = *buffer; | |
512 | ||
513 | /* | |
514 | * Producer / Consumer | |
515 | */ | |
516 | output_struct->data.address32.producer_consumer = temp8 & 0x01; | |
517 | ||
518 | /* | |
519 | * Decode | |
520 | */ | |
521 | output_struct->data.address32.decode = (temp8 >> 1) & 0x01; | |
522 | ||
523 | /* | |
524 | * Min Address Fixed | |
525 | */ | |
526 | output_struct->data.address32.min_address_fixed = (temp8 >> 2) & 0x01; | |
527 | ||
528 | /* | |
529 | * Max Address Fixed | |
530 | */ | |
531 | output_struct->data.address32.max_address_fixed = (temp8 >> 3) & 0x01; | |
532 | ||
533 | /* | |
534 | * Get the Type Specific Flags (Byte5) | |
535 | */ | |
536 | buffer += 1; | |
537 | temp8 = *buffer; | |
538 | ||
539 | if (ACPI_MEMORY_RANGE == output_struct->data.address32.resource_type) { | |
540 | output_struct->data.address32.attribute.memory.read_write_attribute = | |
541 | (u16) (temp8 & 0x01); | |
542 | ||
543 | output_struct->data.address32.attribute.memory.cache_attribute = | |
544 | (u16) ((temp8 >> 1) & 0x03); | |
545 | } | |
546 | else { | |
547 | if (ACPI_IO_RANGE == output_struct->data.address32.resource_type) { | |
548 | output_struct->data.address32.attribute.io.range_attribute = | |
549 | (u16) (temp8 & 0x03); | |
550 | output_struct->data.address32.attribute.io.translation_attribute = | |
551 | (u16) ((temp8 >> 4) & 0x03); | |
552 | } | |
553 | else { | |
554 | /* BUS_NUMBER_RANGE == output_struct->Data.Address32.resource_type */ | |
555 | /* Nothing needs to be filled in */ | |
556 | } | |
557 | } | |
558 | ||
559 | /* | |
560 | * Get Granularity (Bytes 6-9) | |
561 | */ | |
562 | buffer += 1; | |
563 | ACPI_MOVE_32_TO_32 (&output_struct->data.address32.granularity, buffer); | |
564 | ||
565 | /* | |
566 | * Get min_address_range (Bytes 10-13) | |
567 | */ | |
568 | buffer += 4; | |
569 | ACPI_MOVE_32_TO_32 (&output_struct->data.address32.min_address_range, buffer); | |
570 | ||
571 | /* | |
572 | * Get max_address_range (Bytes 14-17) | |
573 | */ | |
574 | buffer += 4; | |
575 | ACPI_MOVE_32_TO_32 (&output_struct->data.address32.max_address_range, buffer); | |
576 | ||
577 | /* | |
578 | * Get address_translation_offset (Bytes 18-21) | |
579 | */ | |
580 | buffer += 4; | |
581 | ACPI_MOVE_32_TO_32 (&output_struct->data.address32.address_translation_offset, buffer); | |
582 | ||
583 | /* | |
584 | * Get address_length (Bytes 22-25) | |
585 | */ | |
586 | buffer += 4; | |
587 | ACPI_MOVE_32_TO_32 (&output_struct->data.address32.address_length, buffer); | |
588 | ||
589 | /* | |
590 | * Resource Source Index (if present) | |
591 | */ | |
592 | buffer += 4; | |
593 | ||
594 | /* | |
595 | * This will leave us pointing to the Resource Source Index | |
596 | * If it is present, then save it off and calculate the | |
597 | * pointer to where the null terminated string goes: | |
598 | * | |
599 | * Note: Some resource descriptors will have an additional null, so | |
600 | * we add 1 to the length. | |
601 | */ | |
602 | if (*bytes_consumed > (26 + 1)) { | |
603 | /* Dereference the Index */ | |
604 | ||
605 | temp8 = *buffer; | |
606 | output_struct->data.address32.resource_source.index = | |
607 | (u32) temp8; | |
608 | ||
609 | /* Point to the String */ | |
610 | ||
611 | buffer += 1; | |
612 | ||
613 | /* Point the String pointer to the end of this structure */ | |
614 | ||
615 | output_struct->data.address32.resource_source.string_ptr = | |
616 | (char *)((u8 *)output_struct + struct_size); | |
617 | ||
618 | temp_ptr = (u8 *) output_struct->data.address32.resource_source.string_ptr; | |
619 | ||
620 | /* Copy the string into the buffer */ | |
621 | ||
622 | index = 0; | |
623 | while (0x00 != *buffer) { | |
624 | *temp_ptr = *buffer; | |
625 | ||
626 | temp_ptr += 1; | |
627 | buffer += 1; | |
628 | index += 1; | |
629 | } | |
630 | ||
631 | /* | |
632 | * Add the terminating null | |
633 | */ | |
634 | *temp_ptr = 0x00; | |
635 | output_struct->data.address32.resource_source.string_length = index + 1; | |
636 | ||
637 | /* | |
638 | * In order for the struct_size to fall on a 32-bit boundary, | |
639 | * calculate the length of the string and expand the | |
640 | * struct_size to the next 32-bit boundary. | |
641 | */ | |
642 | temp8 = (u8) (index + 1); | |
643 | struct_size += ACPI_ROUND_UP_to_32_bITS (temp8); | |
644 | } | |
645 | else { | |
646 | output_struct->data.address32.resource_source.index = 0x00; | |
647 | output_struct->data.address32.resource_source.string_length = 0; | |
648 | output_struct->data.address32.resource_source.string_ptr = NULL; | |
649 | } | |
650 | ||
651 | /* | |
652 | * Set the Length parameter | |
653 | */ | |
654 | output_struct->length = (u32) struct_size; | |
655 | ||
656 | /* | |
657 | * Return the final size of the structure | |
658 | */ | |
659 | *structure_size = struct_size; | |
660 | return_ACPI_STATUS (AE_OK); | |
661 | } | |
662 | ||
663 | ||
664 | /******************************************************************************* | |
665 | * | |
666 | * FUNCTION: acpi_rs_address32_stream | |
667 | * | |
668 | * PARAMETERS: linked_list - Pointer to the resource linked list | |
669 | * output_buffer - Pointer to the user's return buffer | |
670 | * bytes_consumed - Pointer to where the number of bytes | |
671 | * used in the output_buffer is returned | |
672 | * | |
673 | * RETURN: Status | |
674 | * | |
675 | * DESCRIPTION: Take the linked list resource structure and fills in the | |
676 | * the appropriate bytes in a byte stream | |
677 | * | |
678 | ******************************************************************************/ | |
679 | ||
680 | acpi_status | |
681 | acpi_rs_address32_stream ( | |
682 | struct acpi_resource *linked_list, | |
683 | u8 **output_buffer, | |
684 | acpi_size *bytes_consumed) | |
685 | { | |
686 | u8 *buffer; | |
687 | u16 *length_field; | |
688 | u8 temp8; | |
689 | char *temp_pointer; | |
690 | ||
691 | ||
692 | ACPI_FUNCTION_TRACE ("rs_address32_stream"); | |
693 | ||
694 | ||
695 | buffer = *output_buffer; | |
696 | ||
697 | /* | |
698 | * The descriptor field is static | |
699 | */ | |
700 | *buffer = 0x87; | |
701 | buffer += 1; | |
702 | ||
703 | /* | |
704 | * Set a pointer to the Length field - to be filled in later | |
705 | */ | |
706 | length_field = ACPI_CAST_PTR (u16, buffer); | |
707 | buffer += 2; | |
708 | ||
709 | /* | |
710 | * Set the Resource Type (Memory, Io, bus_number) | |
711 | */ | |
712 | temp8 = (u8) (linked_list->data.address32.resource_type & 0x03); | |
713 | ||
714 | *buffer = temp8; | |
715 | buffer += 1; | |
716 | ||
717 | /* | |
718 | * Set the general flags | |
719 | */ | |
720 | temp8 = (u8) (linked_list->data.address32.producer_consumer & 0x01); | |
721 | temp8 |= (linked_list->data.address32.decode & 0x01) << 1; | |
722 | temp8 |= (linked_list->data.address32.min_address_fixed & 0x01) << 2; | |
723 | temp8 |= (linked_list->data.address32.max_address_fixed & 0x01) << 3; | |
724 | ||
725 | *buffer = temp8; | |
726 | buffer += 1; | |
727 | ||
728 | /* | |
729 | * Set the type specific flags | |
730 | */ | |
731 | temp8 = 0; | |
732 | ||
733 | if (ACPI_MEMORY_RANGE == linked_list->data.address32.resource_type) { | |
734 | temp8 = (u8) | |
735 | (linked_list->data.address32.attribute.memory.read_write_attribute & | |
736 | 0x01); | |
737 | ||
738 | temp8 |= | |
739 | (linked_list->data.address32.attribute.memory.cache_attribute & | |
740 | 0x03) << 1; | |
741 | } | |
742 | else if (ACPI_IO_RANGE == linked_list->data.address32.resource_type) { | |
743 | temp8 = (u8) | |
744 | (linked_list->data.address32.attribute.io.range_attribute & | |
745 | 0x03); | |
746 | temp8 |= | |
747 | (linked_list->data.address32.attribute.io.translation_attribute & | |
748 | 0x03) << 4; | |
749 | } | |
750 | ||
751 | *buffer = temp8; | |
752 | buffer += 1; | |
753 | ||
754 | /* | |
755 | * Set the address space granularity | |
756 | */ | |
757 | ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.granularity); | |
758 | buffer += 4; | |
759 | ||
760 | /* | |
761 | * Set the address range minimum | |
762 | */ | |
763 | ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.min_address_range); | |
764 | buffer += 4; | |
765 | ||
766 | /* | |
767 | * Set the address range maximum | |
768 | */ | |
769 | ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.max_address_range); | |
770 | buffer += 4; | |
771 | ||
772 | /* | |
773 | * Set the address translation offset | |
774 | */ | |
775 | ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.address_translation_offset); | |
776 | buffer += 4; | |
777 | ||
778 | /* | |
779 | * Set the address length | |
780 | */ | |
781 | ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.address_length); | |
782 | buffer += 4; | |
783 | ||
784 | /* | |
785 | * Resource Source Index and Resource Source are optional | |
786 | */ | |
787 | if (0 != linked_list->data.address32.resource_source.string_length) { | |
788 | temp8 = (u8) linked_list->data.address32.resource_source.index; | |
789 | ||
790 | *buffer = temp8; | |
791 | buffer += 1; | |
792 | ||
793 | temp_pointer = (char *) buffer; | |
794 | ||
795 | /* | |
796 | * Copy the string | |
797 | */ | |
798 | ACPI_STRCPY (temp_pointer, | |
799 | linked_list->data.address32.resource_source.string_ptr); | |
800 | ||
801 | /* | |
802 | * Buffer needs to be set to the length of the sting + one for the | |
803 | * terminating null | |
804 | */ | |
805 | buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.address32.resource_source.string_ptr) + 1); | |
806 | } | |
807 | ||
808 | /* | |
809 | * Return the number of bytes consumed in this operation | |
810 | */ | |
811 | *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); | |
812 | ||
813 | /* | |
814 | * Set the length field to the number of bytes consumed | |
815 | * minus the header size (3 bytes) | |
816 | */ | |
817 | *length_field = (u16) (*bytes_consumed - 3); | |
818 | return_ACPI_STATUS (AE_OK); | |
819 | } | |
820 | ||
821 | ||
822 | /******************************************************************************* | |
823 | * | |
824 | * FUNCTION: acpi_rs_address64_resource | |
825 | * | |
826 | * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte | |
827 | * stream | |
828 | * bytes_consumed - Pointer to where the number of bytes | |
829 | * consumed the byte_stream_buffer is | |
830 | * returned | |
831 | * output_buffer - Pointer to the return data buffer | |
832 | * structure_size - Pointer to where the number of bytes | |
833 | * in the return data struct is returned | |
834 | * | |
835 | * RETURN: Status | |
836 | * | |
837 | * DESCRIPTION: Take the resource byte stream and fill out the appropriate | |
838 | * structure pointed to by the output_buffer. Return the | |
839 | * number of bytes consumed from the byte stream. | |
840 | * | |
841 | ******************************************************************************/ | |
842 | ||
843 | acpi_status | |
844 | acpi_rs_address64_resource ( | |
845 | u8 *byte_stream_buffer, | |
846 | acpi_size *bytes_consumed, | |
847 | u8 **output_buffer, | |
848 | acpi_size *structure_size) | |
849 | { | |
850 | u8 *buffer; | |
851 | struct acpi_resource *output_struct = (void *) *output_buffer; | |
852 | u16 temp16; | |
853 | u8 temp8; | |
854 | u8 resource_type; | |
855 | u8 *temp_ptr; | |
856 | acpi_size struct_size; | |
857 | u32 index; | |
858 | ||
859 | ||
860 | ACPI_FUNCTION_TRACE ("rs_address64_resource"); | |
861 | ||
862 | ||
863 | buffer = byte_stream_buffer; | |
864 | struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64); | |
865 | resource_type = *buffer; | |
866 | ||
867 | /* | |
868 | * Point past the Descriptor to get the number of bytes consumed | |
869 | */ | |
870 | buffer += 1; | |
871 | ACPI_MOVE_16_TO_16 (&temp16, buffer); | |
872 | ||
873 | /* Validate minimum descriptor length */ | |
874 | ||
875 | if (temp16 < 43) { | |
876 | return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); | |
877 | } | |
878 | ||
879 | *bytes_consumed = temp16 + 3; | |
880 | output_struct->id = ACPI_RSTYPE_ADDRESS64; | |
881 | ||
882 | /* | |
883 | * Get the Resource Type (Byte3) | |
884 | */ | |
885 | buffer += 2; | |
886 | temp8 = *buffer; | |
887 | ||
888 | /* Values 0-2 and 0xC0-0xFF are valid */ | |
889 | ||
890 | if ((temp8 > 2) && (temp8 < 0xC0)) { | |
891 | return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); | |
892 | } | |
893 | ||
894 | output_struct->data.address64.resource_type = temp8; | |
895 | ||
896 | /* | |
897 | * Get the General Flags (Byte4) | |
898 | */ | |
899 | buffer += 1; | |
900 | temp8 = *buffer; | |
901 | ||
902 | /* | |
903 | * Producer / Consumer | |
904 | */ | |
905 | output_struct->data.address64.producer_consumer = temp8 & 0x01; | |
906 | ||
907 | /* | |
908 | * Decode | |
909 | */ | |
910 | output_struct->data.address64.decode = (temp8 >> 1) & 0x01; | |
911 | ||
912 | /* | |
913 | * Min Address Fixed | |
914 | */ | |
915 | output_struct->data.address64.min_address_fixed = (temp8 >> 2) & 0x01; | |
916 | ||
917 | /* | |
918 | * Max Address Fixed | |
919 | */ | |
920 | output_struct->data.address64.max_address_fixed = (temp8 >> 3) & 0x01; | |
921 | ||
922 | /* | |
923 | * Get the Type Specific Flags (Byte5) | |
924 | */ | |
925 | buffer += 1; | |
926 | temp8 = *buffer; | |
927 | ||
928 | if (ACPI_MEMORY_RANGE == output_struct->data.address64.resource_type) { | |
929 | output_struct->data.address64.attribute.memory.read_write_attribute = | |
930 | (u16) (temp8 & 0x01); | |
931 | ||
932 | output_struct->data.address64.attribute.memory.cache_attribute = | |
933 | (u16) ((temp8 >> 1) & 0x03); | |
934 | } | |
935 | else { | |
936 | if (ACPI_IO_RANGE == output_struct->data.address64.resource_type) { | |
937 | output_struct->data.address64.attribute.io.range_attribute = | |
938 | (u16) (temp8 & 0x03); | |
939 | output_struct->data.address64.attribute.io.translation_attribute = | |
940 | (u16) ((temp8 >> 4) & 0x03); | |
941 | } | |
942 | else { | |
943 | /* BUS_NUMBER_RANGE == output_struct->Data.Address64.resource_type */ | |
944 | /* Nothing needs to be filled in */ | |
945 | } | |
946 | } | |
947 | ||
948 | if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) { | |
949 | /* Move past revision_id and Reserved byte */ | |
950 | ||
951 | buffer += 2; | |
952 | } | |
953 | ||
954 | /* | |
955 | * Get Granularity (Bytes 6-13) or (Bytes 8-15) | |
956 | */ | |
957 | buffer += 1; | |
958 | ACPI_MOVE_64_TO_64 (&output_struct->data.address64.granularity, buffer); | |
959 | ||
960 | /* | |
961 | * Get min_address_range (Bytes 14-21) or (Bytes 16-23) | |
962 | */ | |
963 | buffer += 8; | |
964 | ACPI_MOVE_64_TO_64 (&output_struct->data.address64.min_address_range, buffer); | |
965 | ||
966 | /* | |
967 | * Get max_address_range (Bytes 22-29) or (Bytes 24-31) | |
968 | */ | |
969 | buffer += 8; | |
970 | ACPI_MOVE_64_TO_64 (&output_struct->data.address64.max_address_range, buffer); | |
971 | ||
972 | /* | |
973 | * Get address_translation_offset (Bytes 30-37) or (Bytes 32-39) | |
974 | */ | |
975 | buffer += 8; | |
976 | ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_translation_offset, buffer); | |
977 | ||
978 | /* | |
979 | * Get address_length (Bytes 38-45) or (Bytes 40-47) | |
980 | */ | |
981 | buffer += 8; | |
982 | ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_length, buffer); | |
983 | ||
984 | output_struct->data.address64.resource_source.index = 0x00; | |
985 | output_struct->data.address64.resource_source.string_length = 0; | |
986 | output_struct->data.address64.resource_source.string_ptr = NULL; | |
987 | ||
988 | if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) { | |
989 | /* Get type_specific_attribute (Bytes 48-55) */ | |
990 | ||
991 | buffer += 8; | |
992 | ACPI_MOVE_64_TO_64 (&output_struct->data.address64.type_specific_attributes, buffer); | |
993 | } | |
994 | else { | |
995 | output_struct->data.address64.type_specific_attributes = 0; | |
996 | ||
997 | /* | |
998 | * Resource Source Index (if present) | |
999 | */ | |
1000 | buffer += 8; | |
1001 | ||
1002 | /* | |
1003 | * This will leave us pointing to the Resource Source Index | |
1004 | * If it is present, then save it off and calculate the | |
1005 | * pointer to where the null terminated string goes: | |
1006 | * Each Interrupt takes 32-bits + the 5 bytes of the | |
1007 | * stream that are default. | |
1008 | * | |
1009 | * Note: Some resource descriptors will have an additional null, so | |
1010 | * we add 1 to the length. | |
1011 | */ | |
1012 | if (*bytes_consumed > (46 + 1)) { | |
1013 | /* Dereference the Index */ | |
1014 | ||
1015 | temp8 = *buffer; | |
1016 | output_struct->data.address64.resource_source.index = | |
1017 | (u32) temp8; | |
1018 | ||
1019 | /* Point to the String */ | |
1020 | ||
1021 | buffer += 1; | |
1022 | ||
1023 | /* Point the String pointer to the end of this structure */ | |
1024 | ||
1025 | output_struct->data.address64.resource_source.string_ptr = | |
1026 | (char *)((u8 *)output_struct + struct_size); | |
1027 | ||
1028 | temp_ptr = (u8 *) output_struct->data.address64.resource_source.string_ptr; | |
1029 | ||
1030 | /* Copy the string into the buffer */ | |
1031 | ||
1032 | index = 0; | |
1033 | while (0x00 != *buffer) { | |
1034 | *temp_ptr = *buffer; | |
1035 | ||
1036 | temp_ptr += 1; | |
1037 | buffer += 1; | |
1038 | index += 1; | |
1039 | } | |
1040 | ||
1041 | /* | |
1042 | * Add the terminating null | |
1043 | */ | |
1044 | *temp_ptr = 0x00; | |
1045 | output_struct->data.address64.resource_source.string_length = index + 1; | |
1046 | ||
1047 | /* | |
1048 | * In order for the struct_size to fall on a 32-bit boundary, | |
1049 | * calculate the length of the string and expand the | |
1050 | * struct_size to the next 32-bit boundary. | |
1051 | */ | |
1052 | temp8 = (u8) (index + 1); | |
1053 | struct_size += ACPI_ROUND_UP_to_32_bITS (temp8); | |
1054 | } | |
1055 | } | |
1056 | ||
1057 | /* | |
1058 | * Set the Length parameter | |
1059 | */ | |
1060 | output_struct->length = (u32) struct_size; | |
1061 | ||
1062 | /* | |
1063 | * Return the final size of the structure | |
1064 | */ | |
1065 | *structure_size = struct_size; | |
1066 | return_ACPI_STATUS (AE_OK); | |
1067 | } | |
1068 | ||
1069 | ||
1070 | /******************************************************************************* | |
1071 | * | |
1072 | * FUNCTION: acpi_rs_address64_stream | |
1073 | * | |
1074 | * PARAMETERS: linked_list - Pointer to the resource linked list | |
1075 | * output_buffer - Pointer to the user's return buffer | |
1076 | * bytes_consumed - Pointer to where the number of bytes | |
1077 | * used in the output_buffer is returned | |
1078 | * | |
1079 | * RETURN: Status | |
1080 | * | |
1081 | * DESCRIPTION: Take the linked list resource structure and fills in the | |
1082 | * the appropriate bytes in a byte stream | |
1083 | * | |
1084 | ******************************************************************************/ | |
1085 | ||
1086 | acpi_status | |
1087 | acpi_rs_address64_stream ( | |
1088 | struct acpi_resource *linked_list, | |
1089 | u8 **output_buffer, | |
1090 | acpi_size *bytes_consumed) | |
1091 | { | |
1092 | u8 *buffer; | |
1093 | u16 *length_field; | |
1094 | u8 temp8; | |
1095 | char *temp_pointer; | |
1096 | ||
1097 | ||
1098 | ACPI_FUNCTION_TRACE ("rs_address64_stream"); | |
1099 | ||
1100 | ||
1101 | buffer = *output_buffer; | |
1102 | ||
1103 | /* | |
1104 | * The descriptor field is static | |
1105 | */ | |
1106 | *buffer = 0x8A; | |
1107 | buffer += 1; | |
1108 | ||
1109 | /* | |
1110 | * Set a pointer to the Length field - to be filled in later | |
1111 | */ | |
1112 | length_field = ACPI_CAST_PTR (u16, buffer); | |
1113 | buffer += 2; | |
1114 | ||
1115 | /* | |
1116 | * Set the Resource Type (Memory, Io, bus_number) | |
1117 | */ | |
1118 | temp8 = (u8) (linked_list->data.address64.resource_type & 0x03); | |
1119 | ||
1120 | *buffer = temp8; | |
1121 | buffer += 1; | |
1122 | ||
1123 | /* | |
1124 | * Set the general flags | |
1125 | */ | |
1126 | temp8 = (u8) (linked_list->data.address64.producer_consumer & 0x01); | |
1127 | temp8 |= (linked_list->data.address64.decode & 0x01) << 1; | |
1128 | temp8 |= (linked_list->data.address64.min_address_fixed & 0x01) << 2; | |
1129 | temp8 |= (linked_list->data.address64.max_address_fixed & 0x01) << 3; | |
1130 | ||
1131 | *buffer = temp8; | |
1132 | buffer += 1; | |
1133 | ||
1134 | /* | |
1135 | * Set the type specific flags | |
1136 | */ | |
1137 | temp8 = 0; | |
1138 | ||
1139 | if (ACPI_MEMORY_RANGE == linked_list->data.address64.resource_type) { | |
1140 | temp8 = (u8) | |
1141 | (linked_list->data.address64.attribute.memory.read_write_attribute & | |
1142 | 0x01); | |
1143 | ||
1144 | temp8 |= | |
1145 | (linked_list->data.address64.attribute.memory.cache_attribute & | |
1146 | 0x03) << 1; | |
1147 | } | |
1148 | else if (ACPI_IO_RANGE == linked_list->data.address64.resource_type) { | |
1149 | temp8 = (u8) | |
1150 | (linked_list->data.address64.attribute.io.range_attribute & | |
1151 | 0x03); | |
1152 | temp8 |= | |
1153 | (linked_list->data.address64.attribute.io.range_attribute & | |
1154 | 0x03) << 4; | |
1155 | } | |
1156 | ||
1157 | *buffer = temp8; | |
1158 | buffer += 1; | |
1159 | ||
1160 | /* | |
1161 | * Set the address space granularity | |
1162 | */ | |
1163 | ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.granularity); | |
1164 | buffer += 8; | |
1165 | ||
1166 | /* | |
1167 | * Set the address range minimum | |
1168 | */ | |
1169 | ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.min_address_range); | |
1170 | buffer += 8; | |
1171 | ||
1172 | /* | |
1173 | * Set the address range maximum | |
1174 | */ | |
1175 | ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.max_address_range); | |
1176 | buffer += 8; | |
1177 | ||
1178 | /* | |
1179 | * Set the address translation offset | |
1180 | */ | |
1181 | ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.address_translation_offset); | |
1182 | buffer += 8; | |
1183 | ||
1184 | /* | |
1185 | * Set the address length | |
1186 | */ | |
1187 | ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.address_length); | |
1188 | buffer += 8; | |
1189 | ||
1190 | /* | |
1191 | * Resource Source Index and Resource Source are optional | |
1192 | */ | |
1193 | if (0 != linked_list->data.address64.resource_source.string_length) { | |
1194 | temp8 = (u8) linked_list->data.address64.resource_source.index; | |
1195 | ||
1196 | *buffer = temp8; | |
1197 | buffer += 1; | |
1198 | ||
1199 | temp_pointer = (char *) buffer; | |
1200 | ||
1201 | /* | |
1202 | * Copy the string | |
1203 | */ | |
1204 | ACPI_STRCPY (temp_pointer, linked_list->data.address64.resource_source.string_ptr); | |
1205 | ||
1206 | /* | |
1207 | * Buffer needs to be set to the length of the sting + one for the | |
1208 | * terminating null | |
1209 | */ | |
1210 | buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.address64.resource_source.string_ptr) + 1); | |
1211 | } | |
1212 | ||
1213 | /* | |
1214 | * Return the number of bytes consumed in this operation | |
1215 | */ | |
1216 | *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); | |
1217 | ||
1218 | /* | |
1219 | * Set the length field to the number of bytes consumed | |
1220 | * minus the header size (3 bytes) | |
1221 | */ | |
1222 | *length_field = (u16) (*bytes_consumed - 3); | |
1223 | return_ACPI_STATUS (AE_OK); | |
1224 | } | |
1225 |