Auto-update from upstream
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / acpi / resources / rsaddr.c
CommitLineData
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
1da177e4
LT
44#include <acpi/acpi.h>
45#include <acpi/acresrc.h>
46
47#define _COMPONENT ACPI_RESOURCES
4be44fcd 48ACPI_MODULE_NAME("rsaddr")
1da177e4
LT
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 ******************************************************************************/
1da177e4 70acpi_status
4be44fcd
LB
71acpi_rs_address16_resource(u8 * byte_stream_buffer,
72 acpi_size * bytes_consumed,
73 u8 ** output_buffer, acpi_size * structure_size)
1da177e4 74{
4be44fcd
LB
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);
1da177e4 83
4be44fcd 84 ACPI_FUNCTION_TRACE("rs_address16_resource");
1da177e4 85
44f6c012
RM
86 /* Point past the Descriptor to get the number of bytes consumed */
87
1da177e4 88 buffer += 1;
4be44fcd 89 ACPI_MOVE_16_TO_16(&temp16, buffer);
1da177e4
LT
90
91 /* Validate minimum descriptor length */
92
93 if (temp16 < 13) {
4be44fcd 94 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
1da177e4
LT
95 }
96
97 *bytes_consumed = temp16 + 3;
98 output_struct->id = ACPI_RSTYPE_ADDRESS16;
99
44f6c012
RM
100 /* Get the Resource Type (Byte3) */
101
1da177e4
LT
102 buffer += 2;
103 temp8 = *buffer;
104
105 /* Values 0-2 and 0xC0-0xFF are valid */
106
107 if ((temp8 > 2) && (temp8 < 0xC0)) {
4be44fcd 108 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
1da177e4
LT
109 }
110
111 output_struct->data.address16.resource_type = temp8;
112
44f6c012
RM
113 /* Get the General Flags (Byte4) */
114
1da177e4
LT
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
44f6c012
RM
134 /* Get the Type Specific Flags (Byte5) */
135
1da177e4
LT
136 buffer += 1;
137 temp8 = *buffer;
138
139 if (ACPI_MEMORY_RANGE == output_struct->data.address16.resource_type) {
4be44fcd
LB
140 output_struct->data.address16.attribute.memory.
141 read_write_attribute = (u16) (temp8 & 0x01);
1da177e4 142 output_struct->data.address16.attribute.memory.cache_attribute =
4be44fcd
LB
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 {
1da177e4
LT
152 /* BUS_NUMBER_RANGE == Address16.Data->resource_type */
153 /* Nothing needs to be filled in */
154 }
155 }
156
44f6c012
RM
157 /* Get Granularity (Bytes 6-7) */
158
1da177e4 159 buffer += 1;
4be44fcd 160 ACPI_MOVE_16_TO_32(&output_struct->data.address16.granularity, buffer);
1da177e4 161
44f6c012
RM
162 /* Get min_address_range (Bytes 8-9) */
163
1da177e4 164 buffer += 2;
4be44fcd
LB
165 ACPI_MOVE_16_TO_32(&output_struct->data.address16.min_address_range,
166 buffer);
1da177e4 167
44f6c012
RM
168 /* Get max_address_range (Bytes 10-11) */
169
1da177e4 170 buffer += 2;
4be44fcd
LB
171 ACPI_MOVE_16_TO_32(&output_struct->data.address16.max_address_range,
172 buffer);
1da177e4 173
44f6c012
RM
174 /* Get address_translation_offset (Bytes 12-13) */
175
1da177e4 176 buffer += 2;
4be44fcd
LB
177 ACPI_MOVE_16_TO_32(&output_struct->data.address16.
178 address_translation_offset, buffer);
44f6c012
RM
179
180 /* Get address_length (Bytes 14-15) */
1da177e4 181
1da177e4 182 buffer += 2;
4be44fcd
LB
183 ACPI_MOVE_16_TO_32(&output_struct->data.address16.address_length,
184 buffer);
1da177e4 185
44f6c012
RM
186 /* Resource Source Index (if present) */
187
1da177e4
LT
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;
4be44fcd
LB
204 output_struct->data.address16.resource_source.index =
205 (u32) temp8;
1da177e4
LT
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 =
4be44fcd 214 (char *)((u8 *) output_struct + struct_size);
1da177e4 215
44f6c012 216 temp_ptr = (u8 *)
4be44fcd 217 output_struct->data.address16.resource_source.string_ptr;
1da177e4
LT
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
44f6c012
RM
231 /* Add the terminating null */
232
1da177e4
LT
233 *temp_ptr = 0x00;
234
4be44fcd
LB
235 output_struct->data.address16.resource_source.string_length =
236 index + 1;
1da177e4
LT
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);
4be44fcd
LB
244 struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
245 } else {
1da177e4
LT
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
44f6c012
RM
251 /* Set the Length parameter */
252
1da177e4
LT
253 output_struct->length = (u32) struct_size;
254
44f6c012
RM
255 /* Return the final size of the structure */
256
1da177e4 257 *structure_size = struct_size;
4be44fcd 258 return_ACPI_STATUS(AE_OK);
1da177e4
LT
259}
260
1da177e4
LT
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
277acpi_status
4be44fcd
LB
278acpi_rs_address16_stream(struct acpi_resource *linked_list,
279 u8 ** output_buffer, acpi_size * bytes_consumed)
1da177e4 280{
4be44fcd
LB
281 u8 *buffer = *output_buffer;
282 u8 *length_field;
283 u8 temp8;
284 char *temp_pointer = NULL;
285 acpi_size actual_bytes;
1da177e4 286
4be44fcd 287 ACPI_FUNCTION_TRACE("rs_address16_stream");
1da177e4 288
44f6c012
RM
289 /* The descriptor field is static */
290
1da177e4
LT
291 *buffer = 0x88;
292 buffer += 1;
293
44f6c012
RM
294 /* Save a pointer to the Length field - to be filled in later */
295
1da177e4
LT
296 length_field = buffer;
297 buffer += 2;
298
44f6c012
RM
299 /* Set the Resource Type (Memory, Io, bus_number) */
300
1da177e4
LT
301 temp8 = (u8) (linked_list->data.address16.resource_type & 0x03);
302 *buffer = temp8;
303 buffer += 1;
304
44f6c012
RM
305 /* Set the general flags */
306
1da177e4
LT
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
44f6c012
RM
316 /* Set the type specific flags */
317
1da177e4
LT
318 temp8 = 0;
319
320 if (ACPI_MEMORY_RANGE == linked_list->data.address16.resource_type) {
321 temp8 = (u8)
4be44fcd
LB
322 (linked_list->data.address16.attribute.memory.
323 read_write_attribute & 0x01);
1da177e4
LT
324
325 temp8 |=
4be44fcd
LB
326 (linked_list->data.address16.attribute.memory.
327 cache_attribute & 0x03) << 1;
328 } else if (ACPI_IO_RANGE == linked_list->data.address16.resource_type) {
1da177e4 329 temp8 = (u8)
4be44fcd
LB
330 (linked_list->data.address16.attribute.io.range_attribute &
331 0x03);
1da177e4 332 temp8 |=
4be44fcd
LB
333 (linked_list->data.address16.attribute.io.
334 translation_attribute & 0x03) << 4;
1da177e4
LT
335 }
336
337 *buffer = temp8;
338 buffer += 1;
339
44f6c012
RM
340 /* Set the address space granularity */
341
4be44fcd 342 ACPI_MOVE_32_TO_16(buffer, &linked_list->data.address16.granularity);
1da177e4
LT
343 buffer += 2;
344
44f6c012
RM
345 /* Set the address range minimum */
346
4be44fcd
LB
347 ACPI_MOVE_32_TO_16(buffer,
348 &linked_list->data.address16.min_address_range);
1da177e4
LT
349 buffer += 2;
350
44f6c012
RM
351 /* Set the address range maximum */
352
4be44fcd
LB
353 ACPI_MOVE_32_TO_16(buffer,
354 &linked_list->data.address16.max_address_range);
1da177e4
LT
355 buffer += 2;
356
44f6c012
RM
357 /* Set the address translation offset */
358
4be44fcd
LB
359 ACPI_MOVE_32_TO_16(buffer,
360 &linked_list->data.address16.
361 address_translation_offset);
1da177e4
LT
362 buffer += 2;
363
44f6c012
RM
364 /* Set the address length */
365
4be44fcd 366 ACPI_MOVE_32_TO_16(buffer, &linked_list->data.address16.address_length);
1da177e4
LT
367 buffer += 2;
368
44f6c012
RM
369 /* Resource Source Index and Resource Source are optional */
370
1da177e4
LT
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
4be44fcd 377 temp_pointer = (char *)buffer;
1da177e4 378
44f6c012
RM
379 /* Copy the string */
380
4be44fcd
LB
381 ACPI_STRCPY(temp_pointer,
382 linked_list->data.address16.resource_source.
383 string_ptr);
1da177e4
LT
384
385 /*
386 * Buffer needs to be set to the length of the sting + one for the
387 * terminating null
388 */
4be44fcd
LB
389 buffer +=
390 (acpi_size) (ACPI_STRLEN
391 (linked_list->data.address16.resource_source.
392 string_ptr) + 1);
1da177e4
LT
393 }
394
44f6c012
RM
395 /* Return the number of bytes consumed in this operation */
396
4be44fcd 397 actual_bytes = ACPI_PTR_DIFF(buffer, *output_buffer);
1da177e4
LT
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;
4be44fcd
LB
405 ACPI_MOVE_SIZE_TO_16(length_field, &actual_bytes);
406 return_ACPI_STATUS(AE_OK);
1da177e4
LT
407}
408
1da177e4
LT
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
430acpi_status
4be44fcd
LB
431acpi_rs_address32_resource(u8 * byte_stream_buffer,
432 acpi_size * bytes_consumed,
433 u8 ** output_buffer, acpi_size * structure_size)
1da177e4 434{
4be44fcd
LB
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;
1da177e4 442
4be44fcd 443 ACPI_FUNCTION_TRACE("rs_address32_resource");
1da177e4
LT
444
445 buffer = byte_stream_buffer;
4be44fcd 446 struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_address32);
1da177e4 447
44f6c012
RM
448 /* Point past the Descriptor to get the number of bytes consumed */
449
1da177e4 450 buffer += 1;
4be44fcd 451 ACPI_MOVE_16_TO_16(&temp16, buffer);
1da177e4
LT
452
453 /* Validate minimum descriptor length */
454
455 if (temp16 < 23) {
4be44fcd 456 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
1da177e4
LT
457 }
458
459 *bytes_consumed = temp16 + 3;
460 output_struct->id = ACPI_RSTYPE_ADDRESS32;
461
44f6c012
RM
462 /* Get the Resource Type (Byte3) */
463
1da177e4
LT
464 buffer += 2;
465 temp8 = *buffer;
466
467 /* Values 0-2 and 0xC0-0xFF are valid */
468
469 if ((temp8 > 2) && (temp8 < 0xC0)) {
4be44fcd 470 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
1da177e4
LT
471 }
472
473 output_struct->data.address32.resource_type = temp8;
474
44f6c012
RM
475 /* Get the General Flags (Byte4) */
476
1da177e4
LT
477 buffer += 1;
478 temp8 = *buffer;
479
44f6c012
RM
480 /* Producer / Consumer */
481
1da177e4
LT
482 output_struct->data.address32.producer_consumer = temp8 & 0x01;
483
44f6c012
RM
484 /* Decode */
485
1da177e4
LT
486 output_struct->data.address32.decode = (temp8 >> 1) & 0x01;
487
44f6c012
RM
488 /* Min Address Fixed */
489
1da177e4
LT
490 output_struct->data.address32.min_address_fixed = (temp8 >> 2) & 0x01;
491
44f6c012
RM
492 /* Max Address Fixed */
493
1da177e4
LT
494 output_struct->data.address32.max_address_fixed = (temp8 >> 3) & 0x01;
495
44f6c012
RM
496 /* Get the Type Specific Flags (Byte5) */
497
1da177e4
LT
498 buffer += 1;
499 temp8 = *buffer;
500
501 if (ACPI_MEMORY_RANGE == output_struct->data.address32.resource_type) {
4be44fcd
LB
502 output_struct->data.address32.attribute.memory.
503 read_write_attribute = (u16) (temp8 & 0x01);
1da177e4
LT
504
505 output_struct->data.address32.attribute.memory.cache_attribute =
4be44fcd
LB
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 {
1da177e4
LT
515 /* BUS_NUMBER_RANGE == output_struct->Data.Address32.resource_type */
516 /* Nothing needs to be filled in */
517 }
518 }
519
44f6c012
RM
520 /* Get Granularity (Bytes 6-9) */
521
1da177e4 522 buffer += 1;
4be44fcd 523 ACPI_MOVE_32_TO_32(&output_struct->data.address32.granularity, buffer);
1da177e4 524
44f6c012
RM
525 /* Get min_address_range (Bytes 10-13) */
526
1da177e4 527 buffer += 4;
4be44fcd
LB
528 ACPI_MOVE_32_TO_32(&output_struct->data.address32.min_address_range,
529 buffer);
1da177e4 530
44f6c012
RM
531 /* Get max_address_range (Bytes 14-17) */
532
1da177e4 533 buffer += 4;
4be44fcd
LB
534 ACPI_MOVE_32_TO_32(&output_struct->data.address32.max_address_range,
535 buffer);
1da177e4 536
44f6c012
RM
537 /* Get address_translation_offset (Bytes 18-21) */
538
1da177e4 539 buffer += 4;
4be44fcd
LB
540 ACPI_MOVE_32_TO_32(&output_struct->data.address32.
541 address_translation_offset, buffer);
44f6c012
RM
542
543 /* Get address_length (Bytes 22-25) */
1da177e4 544
1da177e4 545 buffer += 4;
4be44fcd
LB
546 ACPI_MOVE_32_TO_32(&output_struct->data.address32.address_length,
547 buffer);
1da177e4 548
44f6c012
RM
549 /* Resource Source Index (if present) */
550
1da177e4
LT
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 =
4be44fcd 566 (u32) temp8;
1da177e4
LT
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 =
4be44fcd 575 (char *)((u8 *) output_struct + struct_size);
1da177e4 576
44f6c012 577 temp_ptr = (u8 *)
4be44fcd 578 output_struct->data.address32.resource_source.string_ptr;
1da177e4
LT
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
44f6c012
RM
591 /* Add the terminating null */
592
1da177e4 593 *temp_ptr = 0x00;
4be44fcd
LB
594 output_struct->data.address32.resource_source.string_length =
595 index + 1;
1da177e4
LT
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);
4be44fcd
LB
603 struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
604 } else {
1da177e4
LT
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
44f6c012
RM
610 /* Set the Length parameter */
611
1da177e4
LT
612 output_struct->length = (u32) struct_size;
613
44f6c012
RM
614 /* Return the final size of the structure */
615
1da177e4 616 *structure_size = struct_size;
4be44fcd 617 return_ACPI_STATUS(AE_OK);
1da177e4
LT
618}
619
1da177e4
LT
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
636acpi_status
4be44fcd
LB
637acpi_rs_address32_stream(struct acpi_resource *linked_list,
638 u8 ** output_buffer, acpi_size * bytes_consumed)
1da177e4 639{
4be44fcd
LB
640 u8 *buffer;
641 u16 *length_field;
642 u8 temp8;
643 char *temp_pointer;
1da177e4 644
4be44fcd 645 ACPI_FUNCTION_TRACE("rs_address32_stream");
1da177e4
LT
646
647 buffer = *output_buffer;
648
44f6c012
RM
649 /* The descriptor field is static */
650
1da177e4
LT
651 *buffer = 0x87;
652 buffer += 1;
653
44f6c012
RM
654 /* Set a pointer to the Length field - to be filled in later */
655
4be44fcd 656 length_field = ACPI_CAST_PTR(u16, buffer);
1da177e4
LT
657 buffer += 2;
658
44f6c012
RM
659 /* Set the Resource Type (Memory, Io, bus_number) */
660
1da177e4
LT
661 temp8 = (u8) (linked_list->data.address32.resource_type & 0x03);
662
663 *buffer = temp8;
664 buffer += 1;
665
44f6c012
RM
666 /* Set the general flags */
667
1da177e4
LT
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
44f6c012
RM
676 /* Set the type specific flags */
677
1da177e4
LT
678 temp8 = 0;
679
680 if (ACPI_MEMORY_RANGE == linked_list->data.address32.resource_type) {
681 temp8 = (u8)
4be44fcd
LB
682 (linked_list->data.address32.attribute.memory.
683 read_write_attribute & 0x01);
1da177e4
LT
684
685 temp8 |=
4be44fcd
LB
686 (linked_list->data.address32.attribute.memory.
687 cache_attribute & 0x03) << 1;
688 } else if (ACPI_IO_RANGE == linked_list->data.address32.resource_type) {
1da177e4 689 temp8 = (u8)
4be44fcd
LB
690 (linked_list->data.address32.attribute.io.range_attribute &
691 0x03);
1da177e4 692 temp8 |=
4be44fcd
LB
693 (linked_list->data.address32.attribute.io.
694 translation_attribute & 0x03) << 4;
1da177e4
LT
695 }
696
697 *buffer = temp8;
698 buffer += 1;
699
44f6c012
RM
700 /* Set the address space granularity */
701
4be44fcd 702 ACPI_MOVE_32_TO_32(buffer, &linked_list->data.address32.granularity);
1da177e4
LT
703 buffer += 4;
704
44f6c012
RM
705 /* Set the address range minimum */
706
4be44fcd
LB
707 ACPI_MOVE_32_TO_32(buffer,
708 &linked_list->data.address32.min_address_range);
1da177e4
LT
709 buffer += 4;
710
44f6c012
RM
711 /* Set the address range maximum */
712
4be44fcd
LB
713 ACPI_MOVE_32_TO_32(buffer,
714 &linked_list->data.address32.max_address_range);
1da177e4
LT
715 buffer += 4;
716
44f6c012
RM
717 /* Set the address translation offset */
718
4be44fcd
LB
719 ACPI_MOVE_32_TO_32(buffer,
720 &linked_list->data.address32.
721 address_translation_offset);
1da177e4
LT
722 buffer += 4;
723
44f6c012
RM
724 /* Set the address length */
725
4be44fcd 726 ACPI_MOVE_32_TO_32(buffer, &linked_list->data.address32.address_length);
1da177e4
LT
727 buffer += 4;
728
44f6c012
RM
729 /* Resource Source Index and Resource Source are optional */
730
1da177e4
LT
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
4be44fcd 737 temp_pointer = (char *)buffer;
1da177e4 738
44f6c012
RM
739 /* Copy the string */
740
4be44fcd
LB
741 ACPI_STRCPY(temp_pointer,
742 linked_list->data.address32.resource_source.
743 string_ptr);
1da177e4
LT
744
745 /*
746 * Buffer needs to be set to the length of the sting + one for the
747 * terminating null
748 */
4be44fcd
LB
749 buffer +=
750 (acpi_size) (ACPI_STRLEN
751 (linked_list->data.address32.resource_source.
752 string_ptr) + 1);
1da177e4
LT
753 }
754
44f6c012
RM
755 /* Return the number of bytes consumed in this operation */
756
4be44fcd 757 *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
1da177e4
LT
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);
4be44fcd 764 return_ACPI_STATUS(AE_OK);
1da177e4
LT
765}
766
1da177e4
LT
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
788acpi_status
4be44fcd
LB
789acpi_rs_address64_resource(u8 * byte_stream_buffer,
790 acpi_size * bytes_consumed,
791 u8 ** output_buffer, acpi_size * structure_size)
1da177e4 792{
4be44fcd
LB
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;
1da177e4 801
4be44fcd 802 ACPI_FUNCTION_TRACE("rs_address64_resource");
1da177e4
LT
803
804 buffer = byte_stream_buffer;
4be44fcd 805 struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64);
1da177e4
LT
806 resource_type = *buffer;
807
44f6c012
RM
808 /* Point past the Descriptor to get the number of bytes consumed */
809
1da177e4 810 buffer += 1;
4be44fcd 811 ACPI_MOVE_16_TO_16(&temp16, buffer);
1da177e4
LT
812
813 /* Validate minimum descriptor length */
814
815 if (temp16 < 43) {
4be44fcd 816 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
1da177e4
LT
817 }
818
819 *bytes_consumed = temp16 + 3;
820 output_struct->id = ACPI_RSTYPE_ADDRESS64;
821
44f6c012
RM
822 /* Get the Resource Type (Byte3) */
823
1da177e4
LT
824 buffer += 2;
825 temp8 = *buffer;
826
827 /* Values 0-2 and 0xC0-0xFF are valid */
828
829 if ((temp8 > 2) && (temp8 < 0xC0)) {
4be44fcd 830 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
1da177e4
LT
831 }
832
833 output_struct->data.address64.resource_type = temp8;
834
44f6c012
RM
835 /* Get the General Flags (Byte4) */
836
1da177e4
LT
837 buffer += 1;
838 temp8 = *buffer;
839
44f6c012
RM
840 /* Producer / Consumer */
841
1da177e4
LT
842 output_struct->data.address64.producer_consumer = temp8 & 0x01;
843
44f6c012
RM
844 /* Decode */
845
1da177e4
LT
846 output_struct->data.address64.decode = (temp8 >> 1) & 0x01;
847
44f6c012
RM
848 /* Min Address Fixed */
849
1da177e4
LT
850 output_struct->data.address64.min_address_fixed = (temp8 >> 2) & 0x01;
851
44f6c012
RM
852 /* Max Address Fixed */
853
1da177e4
LT
854 output_struct->data.address64.max_address_fixed = (temp8 >> 3) & 0x01;
855
44f6c012
RM
856 /* Get the Type Specific Flags (Byte5) */
857
1da177e4
LT
858 buffer += 1;
859 temp8 = *buffer;
860
861 if (ACPI_MEMORY_RANGE == output_struct->data.address64.resource_type) {
4be44fcd
LB
862 output_struct->data.address64.attribute.memory.
863 read_write_attribute = (u16) (temp8 & 0x01);
1da177e4
LT
864
865 output_struct->data.address64.attribute.memory.cache_attribute =
4be44fcd
LB
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 {
1da177e4
LT
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
44f6c012
RM
886 /* Get Granularity (Bytes 6-13) or (Bytes 8-15) */
887
1da177e4 888 buffer += 1;
4be44fcd 889 ACPI_MOVE_64_TO_64(&output_struct->data.address64.granularity, buffer);
1da177e4 890
44f6c012
RM
891 /* Get min_address_range (Bytes 14-21) or (Bytes 16-23) */
892
1da177e4 893 buffer += 8;
4be44fcd
LB
894 ACPI_MOVE_64_TO_64(&output_struct->data.address64.min_address_range,
895 buffer);
1da177e4 896
44f6c012
RM
897 /* Get max_address_range (Bytes 22-29) or (Bytes 24-31) */
898
1da177e4 899 buffer += 8;
4be44fcd
LB
900 ACPI_MOVE_64_TO_64(&output_struct->data.address64.max_address_range,
901 buffer);
1da177e4 902
44f6c012
RM
903 /* Get address_translation_offset (Bytes 30-37) or (Bytes 32-39) */
904
1da177e4 905 buffer += 8;
4be44fcd
LB
906 ACPI_MOVE_64_TO_64(&output_struct->data.address64.
907 address_translation_offset, buffer);
44f6c012
RM
908
909 /* Get address_length (Bytes 38-45) or (Bytes 40-47) */
1da177e4 910
1da177e4 911 buffer += 8;
4be44fcd
LB
912 ACPI_MOVE_64_TO_64(&output_struct->data.address64.address_length,
913 buffer);
1da177e4
LT
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;
4be44fcd
LB
923 ACPI_MOVE_64_TO_64(&output_struct->data.address64.
924 type_specific_attributes, buffer);
925 } else {
1da177e4
LT
926 output_struct->data.address64.type_specific_attributes = 0;
927
44f6c012
RM
928 /* Resource Source Index (if present) */
929
1da177e4
LT
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 =
4be44fcd 947 (u32) temp8;
1da177e4
LT
948
949 /* Point to the String */
950
951 buffer += 1;
952
953 /* Point the String pointer to the end of this structure */
954
4be44fcd
LB
955 output_struct->data.address64.resource_source.
956 string_ptr =
957 (char *)((u8 *) output_struct + struct_size);
1da177e4 958
44f6c012 959 temp_ptr = (u8 *)
4be44fcd
LB
960 output_struct->data.address64.resource_source.
961 string_ptr;
1da177e4
LT
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;
4be44fcd
LB
978 output_struct->data.address64.resource_source.
979 string_length = index + 1;
1da177e4
LT
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);
4be44fcd 987 struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
1da177e4
LT
988 }
989 }
990
44f6c012
RM
991 /* Set the Length parameter */
992
1da177e4
LT
993 output_struct->length = (u32) struct_size;
994
44f6c012
RM
995 /* Return the final size of the structure */
996
1da177e4 997 *structure_size = struct_size;
4be44fcd 998 return_ACPI_STATUS(AE_OK);
1da177e4
LT
999}
1000
1da177e4
LT
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
1017acpi_status
4be44fcd
LB
1018acpi_rs_address64_stream(struct acpi_resource *linked_list,
1019 u8 ** output_buffer, acpi_size * bytes_consumed)
1da177e4 1020{
4be44fcd
LB
1021 u8 *buffer;
1022 u16 *length_field;
1023 u8 temp8;
1024 char *temp_pointer;
1da177e4 1025
4be44fcd 1026 ACPI_FUNCTION_TRACE("rs_address64_stream");
1da177e4
LT
1027
1028 buffer = *output_buffer;
1029
44f6c012
RM
1030 /* The descriptor field is static */
1031
1da177e4
LT
1032 *buffer = 0x8A;
1033 buffer += 1;
1034
44f6c012
RM
1035 /* Set a pointer to the Length field - to be filled in later */
1036
4be44fcd 1037 length_field = ACPI_CAST_PTR(u16, buffer);
1da177e4
LT
1038 buffer += 2;
1039
44f6c012
RM
1040 /* Set the Resource Type (Memory, Io, bus_number) */
1041
1da177e4
LT
1042 temp8 = (u8) (linked_list->data.address64.resource_type & 0x03);
1043
1044 *buffer = temp8;
1045 buffer += 1;
1046
44f6c012
RM
1047 /* Set the general flags */
1048
1da177e4
LT
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
44f6c012
RM
1057 /* Set the type specific flags */
1058
1da177e4
LT
1059 temp8 = 0;
1060
1061 if (ACPI_MEMORY_RANGE == linked_list->data.address64.resource_type) {
1062 temp8 = (u8)
4be44fcd
LB
1063 (linked_list->data.address64.attribute.memory.
1064 read_write_attribute & 0x01);
1da177e4
LT
1065
1066 temp8 |=
4be44fcd
LB
1067 (linked_list->data.address64.attribute.memory.
1068 cache_attribute & 0x03) << 1;
1069 } else if (ACPI_IO_RANGE == linked_list->data.address64.resource_type) {
1da177e4 1070 temp8 = (u8)
4be44fcd
LB
1071 (linked_list->data.address64.attribute.io.range_attribute &
1072 0x03);
1da177e4 1073 temp8 |=
4be44fcd
LB
1074 (linked_list->data.address64.attribute.io.range_attribute &
1075 0x03) << 4;
1da177e4
LT
1076 }
1077
1078 *buffer = temp8;
1079 buffer += 1;
1080
44f6c012
RM
1081 /* Set the address space granularity */
1082
4be44fcd 1083 ACPI_MOVE_64_TO_64(buffer, &linked_list->data.address64.granularity);
1da177e4
LT
1084 buffer += 8;
1085
44f6c012
RM
1086 /* Set the address range minimum */
1087
4be44fcd
LB
1088 ACPI_MOVE_64_TO_64(buffer,
1089 &linked_list->data.address64.min_address_range);
1da177e4
LT
1090 buffer += 8;
1091
44f6c012
RM
1092 /* Set the address range maximum */
1093
4be44fcd
LB
1094 ACPI_MOVE_64_TO_64(buffer,
1095 &linked_list->data.address64.max_address_range);
1da177e4
LT
1096 buffer += 8;
1097
44f6c012
RM
1098 /* Set the address translation offset */
1099
4be44fcd
LB
1100 ACPI_MOVE_64_TO_64(buffer,
1101 &linked_list->data.address64.
1102 address_translation_offset);
1da177e4
LT
1103 buffer += 8;
1104
44f6c012
RM
1105 /* Set the address length */
1106
4be44fcd 1107 ACPI_MOVE_64_TO_64(buffer, &linked_list->data.address64.address_length);
1da177e4
LT
1108 buffer += 8;
1109
44f6c012
RM
1110 /* Resource Source Index and Resource Source are optional */
1111
1da177e4
LT
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
4be44fcd 1118 temp_pointer = (char *)buffer;
1da177e4 1119
44f6c012
RM
1120 /* Copy the string */
1121
4be44fcd
LB
1122 ACPI_STRCPY(temp_pointer,
1123 linked_list->data.address64.resource_source.
1124 string_ptr);
1da177e4
LT
1125
1126 /*
1127 * Buffer needs to be set to the length of the sting + one for the
1128 * terminating null
1129 */
4be44fcd
LB
1130 buffer +=
1131 (acpi_size) (ACPI_STRLEN
1132 (linked_list->data.address64.resource_source.
1133 string_ptr) + 1);
1da177e4
LT
1134 }
1135
44f6c012
RM
1136 /* Return the number of bytes consumed in this operation */
1137
4be44fcd 1138 *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
1da177e4
LT
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);
4be44fcd 1145 return_ACPI_STATUS(AE_OK);
1da177e4 1146}