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