blob: 4cf46e1ee01b36d502215a02617557041f81eaf0 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*******************************************************************************
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
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <acpi/acpi.h>
45#include <acpi/acresrc.h>
46
47#define _COMPONENT ACPI_RESOURCES
Len Brown4be44fc2005-08-05 00:44:28 -040048ACPI_MODULE_NAME("rsaddr")
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
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 ******************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -070070acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -040071acpi_rs_address16_resource(u8 * byte_stream_buffer,
72 acpi_size * bytes_consumed,
73 u8 ** output_buffer, acpi_size * structure_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -070074{
Len Brown4be44fc2005-08-05 00:44:28 -040075 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
Len Brown4be44fc2005-08-05 00:44:28 -040084 ACPI_FUNCTION_TRACE("rs_address16_resource");
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
Robert Moore44f6c012005-04-18 22:49:35 -040086 /* Point past the Descriptor to get the number of bytes consumed */
87
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 buffer += 1;
Len Brown4be44fc2005-08-05 00:44:28 -040089 ACPI_MOVE_16_TO_16(&temp16, buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
91 /* Validate minimum descriptor length */
92
93 if (temp16 < 13) {
Len Brown4be44fc2005-08-05 00:44:28 -040094 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 }
96
97 *bytes_consumed = temp16 + 3;
98 output_struct->id = ACPI_RSTYPE_ADDRESS16;
99
Robert Moore44f6c012005-04-18 22:49:35 -0400100 /* Get the Resource Type (Byte3) */
101
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102 buffer += 2;
103 temp8 = *buffer;
104
105 /* Values 0-2 and 0xC0-0xFF are valid */
106
107 if ((temp8 > 2) && (temp8 < 0xC0)) {
Len Brown4be44fc2005-08-05 00:44:28 -0400108 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 }
110
111 output_struct->data.address16.resource_type = temp8;
112
Robert Moore44f6c012005-04-18 22:49:35 -0400113 /* Get the General Flags (Byte4) */
114
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 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
Robert Moore44f6c012005-04-18 22:49:35 -0400134 /* Get the Type Specific Flags (Byte5) */
135
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 buffer += 1;
137 temp8 = *buffer;
138
139 if (ACPI_MEMORY_RANGE == output_struct->data.address16.resource_type) {
Len Brown4be44fc2005-08-05 00:44:28 -0400140 output_struct->data.address16.attribute.memory.
141 read_write_attribute = (u16) (temp8 & 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 output_struct->data.address16.attribute.memory.cache_attribute =
Len Brown4be44fc2005-08-05 00:44:28 -0400143 (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 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 /* BUS_NUMBER_RANGE == Address16.Data->resource_type */
153 /* Nothing needs to be filled in */
154 }
155 }
156
Robert Moore44f6c012005-04-18 22:49:35 -0400157 /* Get Granularity (Bytes 6-7) */
158
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 buffer += 1;
Len Brown4be44fc2005-08-05 00:44:28 -0400160 ACPI_MOVE_16_TO_32(&output_struct->data.address16.granularity, buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161
Robert Moore44f6c012005-04-18 22:49:35 -0400162 /* Get min_address_range (Bytes 8-9) */
163
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 buffer += 2;
Len Brown4be44fc2005-08-05 00:44:28 -0400165 ACPI_MOVE_16_TO_32(&output_struct->data.address16.min_address_range,
166 buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167
Robert Moore44f6c012005-04-18 22:49:35 -0400168 /* Get max_address_range (Bytes 10-11) */
169
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 buffer += 2;
Len Brown4be44fc2005-08-05 00:44:28 -0400171 ACPI_MOVE_16_TO_32(&output_struct->data.address16.max_address_range,
172 buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173
Robert Moore44f6c012005-04-18 22:49:35 -0400174 /* Get address_translation_offset (Bytes 12-13) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175
Robert Moore44f6c012005-04-18 22:49:35 -0400176 buffer += 2;
Len Brown4be44fc2005-08-05 00:44:28 -0400177 ACPI_MOVE_16_TO_32(&output_struct->data.address16.
178 address_translation_offset, buffer);
Robert Moore44f6c012005-04-18 22:49:35 -0400179
180 /* Get address_length (Bytes 14-15) */
181
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 buffer += 2;
Len Brown4be44fc2005-08-05 00:44:28 -0400183 ACPI_MOVE_16_TO_32(&output_struct->data.address16.address_length,
184 buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185
Robert Moore44f6c012005-04-18 22:49:35 -0400186 /* Resource Source Index (if present) */
187
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 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;
Len Brown4be44fc2005-08-05 00:44:28 -0400204 output_struct->data.address16.resource_source.index =
205 (u32) temp8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
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 =
Len Brown4be44fc2005-08-05 00:44:28 -0400214 (char *)((u8 *) output_struct + struct_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
Robert Moore44f6c012005-04-18 22:49:35 -0400216 temp_ptr = (u8 *)
Len Brown4be44fc2005-08-05 00:44:28 -0400217 output_struct->data.address16.resource_source.string_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
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
Robert Moore44f6c012005-04-18 22:49:35 -0400231 /* Add the terminating null */
232
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 *temp_ptr = 0x00;
234
Len Brown4be44fc2005-08-05 00:44:28 -0400235 output_struct->data.address16.resource_source.string_length =
236 index + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237
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);
Len Brown4be44fc2005-08-05 00:44:28 -0400244 struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
245 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 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
Robert Moore44f6c012005-04-18 22:49:35 -0400251 /* Set the Length parameter */
252
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 output_struct->length = (u32) struct_size;
254
Robert Moore44f6c012005-04-18 22:49:35 -0400255 /* Return the final size of the structure */
256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 *structure_size = struct_size;
Len Brown4be44fc2005-08-05 00:44:28 -0400258 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259}
260
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261/*******************************************************************************
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
Len Brown4be44fc2005-08-05 00:44:28 -0400278acpi_rs_address16_stream(struct acpi_resource *linked_list,
279 u8 ** output_buffer, acpi_size * bytes_consumed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280{
Len Brown4be44fc2005-08-05 00:44:28 -0400281 u8 *buffer = *output_buffer;
282 u8 *length_field;
283 u8 temp8;
284 char *temp_pointer = NULL;
285 acpi_size actual_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
Len Brown4be44fc2005-08-05 00:44:28 -0400287 ACPI_FUNCTION_TRACE("rs_address16_stream");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288
Robert Moore44f6c012005-04-18 22:49:35 -0400289 /* The descriptor field is static */
290
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 *buffer = 0x88;
292 buffer += 1;
293
Robert Moore44f6c012005-04-18 22:49:35 -0400294 /* Save a pointer to the Length field - to be filled in later */
295
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 length_field = buffer;
297 buffer += 2;
298
Robert Moore44f6c012005-04-18 22:49:35 -0400299 /* Set the Resource Type (Memory, Io, bus_number) */
300
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 temp8 = (u8) (linked_list->data.address16.resource_type & 0x03);
302 *buffer = temp8;
303 buffer += 1;
304
Robert Moore44f6c012005-04-18 22:49:35 -0400305 /* Set the general flags */
306
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 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
Robert Moore44f6c012005-04-18 22:49:35 -0400316 /* Set the type specific flags */
317
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 temp8 = 0;
319
320 if (ACPI_MEMORY_RANGE == linked_list->data.address16.resource_type) {
321 temp8 = (u8)
Len Brown4be44fc2005-08-05 00:44:28 -0400322 (linked_list->data.address16.attribute.memory.
323 read_write_attribute & 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324
325 temp8 |=
Len Brown4be44fc2005-08-05 00:44:28 -0400326 (linked_list->data.address16.attribute.memory.
327 cache_attribute & 0x03) << 1;
328 } else if (ACPI_IO_RANGE == linked_list->data.address16.resource_type) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 temp8 = (u8)
Len Brown4be44fc2005-08-05 00:44:28 -0400330 (linked_list->data.address16.attribute.io.range_attribute &
331 0x03);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 temp8 |=
Len Brown4be44fc2005-08-05 00:44:28 -0400333 (linked_list->data.address16.attribute.io.
334 translation_attribute & 0x03) << 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 }
336
337 *buffer = temp8;
338 buffer += 1;
339
Robert Moore44f6c012005-04-18 22:49:35 -0400340 /* Set the address space granularity */
341
Len Brown4be44fc2005-08-05 00:44:28 -0400342 ACPI_MOVE_32_TO_16(buffer, &linked_list->data.address16.granularity);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 buffer += 2;
344
Robert Moore44f6c012005-04-18 22:49:35 -0400345 /* Set the address range minimum */
346
Len Brown4be44fc2005-08-05 00:44:28 -0400347 ACPI_MOVE_32_TO_16(buffer,
348 &linked_list->data.address16.min_address_range);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 buffer += 2;
350
Robert Moore44f6c012005-04-18 22:49:35 -0400351 /* Set the address range maximum */
352
Len Brown4be44fc2005-08-05 00:44:28 -0400353 ACPI_MOVE_32_TO_16(buffer,
354 &linked_list->data.address16.max_address_range);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 buffer += 2;
356
Robert Moore44f6c012005-04-18 22:49:35 -0400357 /* Set the address translation offset */
358
Len Brown4be44fc2005-08-05 00:44:28 -0400359 ACPI_MOVE_32_TO_16(buffer,
360 &linked_list->data.address16.
361 address_translation_offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 buffer += 2;
363
Robert Moore44f6c012005-04-18 22:49:35 -0400364 /* Set the address length */
365
Len Brown4be44fc2005-08-05 00:44:28 -0400366 ACPI_MOVE_32_TO_16(buffer, &linked_list->data.address16.address_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 buffer += 2;
368
Robert Moore44f6c012005-04-18 22:49:35 -0400369 /* Resource Source Index and Resource Source are optional */
370
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 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
Len Brown4be44fc2005-08-05 00:44:28 -0400377 temp_pointer = (char *)buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
Robert Moore44f6c012005-04-18 22:49:35 -0400379 /* Copy the string */
380
Len Brown4be44fc2005-08-05 00:44:28 -0400381 ACPI_STRCPY(temp_pointer,
382 linked_list->data.address16.resource_source.
383 string_ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
385 /*
386 * Buffer needs to be set to the length of the sting + one for the
387 * terminating null
388 */
Len Brown4be44fc2005-08-05 00:44:28 -0400389 buffer +=
390 (acpi_size) (ACPI_STRLEN
391 (linked_list->data.address16.resource_source.
392 string_ptr) + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 }
394
Robert Moore44f6c012005-04-18 22:49:35 -0400395 /* Return the number of bytes consumed in this operation */
396
Len Brown4be44fc2005-08-05 00:44:28 -0400397 actual_bytes = ACPI_PTR_DIFF(buffer, *output_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 *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;
Len Brown4be44fc2005-08-05 00:44:28 -0400405 ACPI_MOVE_SIZE_TO_16(length_field, &actual_bytes);
406 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407}
408
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409/*******************************************************************************
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
Len Brown4be44fc2005-08-05 00:44:28 -0400431acpi_rs_address32_resource(u8 * byte_stream_buffer,
432 acpi_size * bytes_consumed,
433 u8 ** output_buffer, acpi_size * structure_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434{
Len Brown4be44fc2005-08-05 00:44:28 -0400435 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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442
Len Brown4be44fc2005-08-05 00:44:28 -0400443 ACPI_FUNCTION_TRACE("rs_address32_resource");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444
445 buffer = byte_stream_buffer;
Len Brown4be44fc2005-08-05 00:44:28 -0400446 struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_address32);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
Robert Moore44f6c012005-04-18 22:49:35 -0400448 /* Point past the Descriptor to get the number of bytes consumed */
449
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 buffer += 1;
Len Brown4be44fc2005-08-05 00:44:28 -0400451 ACPI_MOVE_16_TO_16(&temp16, buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
453 /* Validate minimum descriptor length */
454
455 if (temp16 < 23) {
Len Brown4be44fc2005-08-05 00:44:28 -0400456 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 }
458
459 *bytes_consumed = temp16 + 3;
460 output_struct->id = ACPI_RSTYPE_ADDRESS32;
461
Robert Moore44f6c012005-04-18 22:49:35 -0400462 /* Get the Resource Type (Byte3) */
463
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 buffer += 2;
465 temp8 = *buffer;
466
467 /* Values 0-2 and 0xC0-0xFF are valid */
468
469 if ((temp8 > 2) && (temp8 < 0xC0)) {
Len Brown4be44fc2005-08-05 00:44:28 -0400470 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 }
472
473 output_struct->data.address32.resource_type = temp8;
474
Robert Moore44f6c012005-04-18 22:49:35 -0400475 /* Get the General Flags (Byte4) */
476
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 buffer += 1;
478 temp8 = *buffer;
479
Robert Moore44f6c012005-04-18 22:49:35 -0400480 /* Producer / Consumer */
481
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 output_struct->data.address32.producer_consumer = temp8 & 0x01;
483
Robert Moore44f6c012005-04-18 22:49:35 -0400484 /* Decode */
485
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 output_struct->data.address32.decode = (temp8 >> 1) & 0x01;
487
Robert Moore44f6c012005-04-18 22:49:35 -0400488 /* Min Address Fixed */
489
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 output_struct->data.address32.min_address_fixed = (temp8 >> 2) & 0x01;
491
Robert Moore44f6c012005-04-18 22:49:35 -0400492 /* Max Address Fixed */
493
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 output_struct->data.address32.max_address_fixed = (temp8 >> 3) & 0x01;
495
Robert Moore44f6c012005-04-18 22:49:35 -0400496 /* Get the Type Specific Flags (Byte5) */
497
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 buffer += 1;
499 temp8 = *buffer;
500
501 if (ACPI_MEMORY_RANGE == output_struct->data.address32.resource_type) {
Len Brown4be44fc2005-08-05 00:44:28 -0400502 output_struct->data.address32.attribute.memory.
503 read_write_attribute = (u16) (temp8 & 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504
505 output_struct->data.address32.attribute.memory.cache_attribute =
Len Brown4be44fc2005-08-05 00:44:28 -0400506 (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 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 /* BUS_NUMBER_RANGE == output_struct->Data.Address32.resource_type */
516 /* Nothing needs to be filled in */
517 }
518 }
519
Robert Moore44f6c012005-04-18 22:49:35 -0400520 /* Get Granularity (Bytes 6-9) */
521
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 buffer += 1;
Len Brown4be44fc2005-08-05 00:44:28 -0400523 ACPI_MOVE_32_TO_32(&output_struct->data.address32.granularity, buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
Robert Moore44f6c012005-04-18 22:49:35 -0400525 /* Get min_address_range (Bytes 10-13) */
526
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 buffer += 4;
Len Brown4be44fc2005-08-05 00:44:28 -0400528 ACPI_MOVE_32_TO_32(&output_struct->data.address32.min_address_range,
529 buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530
Robert Moore44f6c012005-04-18 22:49:35 -0400531 /* Get max_address_range (Bytes 14-17) */
532
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 buffer += 4;
Len Brown4be44fc2005-08-05 00:44:28 -0400534 ACPI_MOVE_32_TO_32(&output_struct->data.address32.max_address_range,
535 buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
Robert Moore44f6c012005-04-18 22:49:35 -0400537 /* Get address_translation_offset (Bytes 18-21) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
Robert Moore44f6c012005-04-18 22:49:35 -0400539 buffer += 4;
Len Brown4be44fc2005-08-05 00:44:28 -0400540 ACPI_MOVE_32_TO_32(&output_struct->data.address32.
541 address_translation_offset, buffer);
Robert Moore44f6c012005-04-18 22:49:35 -0400542
543 /* Get address_length (Bytes 22-25) */
544
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 buffer += 4;
Len Brown4be44fc2005-08-05 00:44:28 -0400546 ACPI_MOVE_32_TO_32(&output_struct->data.address32.address_length,
547 buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548
Robert Moore44f6c012005-04-18 22:49:35 -0400549 /* Resource Source Index (if present) */
550
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 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 =
Len Brown4be44fc2005-08-05 00:44:28 -0400566 (u32) temp8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567
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 =
Len Brown4be44fc2005-08-05 00:44:28 -0400575 (char *)((u8 *) output_struct + struct_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576
Robert Moore44f6c012005-04-18 22:49:35 -0400577 temp_ptr = (u8 *)
Len Brown4be44fc2005-08-05 00:44:28 -0400578 output_struct->data.address32.resource_source.string_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579
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
Robert Moore44f6c012005-04-18 22:49:35 -0400591 /* Add the terminating null */
592
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 *temp_ptr = 0x00;
Len Brown4be44fc2005-08-05 00:44:28 -0400594 output_struct->data.address32.resource_source.string_length =
595 index + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
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);
Len Brown4be44fc2005-08-05 00:44:28 -0400603 struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
604 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 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
Robert Moore44f6c012005-04-18 22:49:35 -0400610 /* Set the Length parameter */
611
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 output_struct->length = (u32) struct_size;
613
Robert Moore44f6c012005-04-18 22:49:35 -0400614 /* Return the final size of the structure */
615
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 *structure_size = struct_size;
Len Brown4be44fc2005-08-05 00:44:28 -0400617 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618}
619
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620/*******************************************************************************
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
Len Brown4be44fc2005-08-05 00:44:28 -0400637acpi_rs_address32_stream(struct acpi_resource *linked_list,
638 u8 ** output_buffer, acpi_size * bytes_consumed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639{
Len Brown4be44fc2005-08-05 00:44:28 -0400640 u8 *buffer;
641 u16 *length_field;
642 u8 temp8;
643 char *temp_pointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
Len Brown4be44fc2005-08-05 00:44:28 -0400645 ACPI_FUNCTION_TRACE("rs_address32_stream");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
647 buffer = *output_buffer;
648
Robert Moore44f6c012005-04-18 22:49:35 -0400649 /* The descriptor field is static */
650
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 *buffer = 0x87;
652 buffer += 1;
653
Robert Moore44f6c012005-04-18 22:49:35 -0400654 /* Set a pointer to the Length field - to be filled in later */
655
Len Brown4be44fc2005-08-05 00:44:28 -0400656 length_field = ACPI_CAST_PTR(u16, buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 buffer += 2;
658
Robert Moore44f6c012005-04-18 22:49:35 -0400659 /* Set the Resource Type (Memory, Io, bus_number) */
660
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 temp8 = (u8) (linked_list->data.address32.resource_type & 0x03);
662
663 *buffer = temp8;
664 buffer += 1;
665
Robert Moore44f6c012005-04-18 22:49:35 -0400666 /* Set the general flags */
667
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 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
Robert Moore44f6c012005-04-18 22:49:35 -0400676 /* Set the type specific flags */
677
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 temp8 = 0;
679
680 if (ACPI_MEMORY_RANGE == linked_list->data.address32.resource_type) {
681 temp8 = (u8)
Len Brown4be44fc2005-08-05 00:44:28 -0400682 (linked_list->data.address32.attribute.memory.
683 read_write_attribute & 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684
685 temp8 |=
Len Brown4be44fc2005-08-05 00:44:28 -0400686 (linked_list->data.address32.attribute.memory.
687 cache_attribute & 0x03) << 1;
688 } else if (ACPI_IO_RANGE == linked_list->data.address32.resource_type) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 temp8 = (u8)
Len Brown4be44fc2005-08-05 00:44:28 -0400690 (linked_list->data.address32.attribute.io.range_attribute &
691 0x03);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 temp8 |=
Len Brown4be44fc2005-08-05 00:44:28 -0400693 (linked_list->data.address32.attribute.io.
694 translation_attribute & 0x03) << 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 }
696
697 *buffer = temp8;
698 buffer += 1;
699
Robert Moore44f6c012005-04-18 22:49:35 -0400700 /* Set the address space granularity */
701
Len Brown4be44fc2005-08-05 00:44:28 -0400702 ACPI_MOVE_32_TO_32(buffer, &linked_list->data.address32.granularity);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 buffer += 4;
704
Robert Moore44f6c012005-04-18 22:49:35 -0400705 /* Set the address range minimum */
706
Len Brown4be44fc2005-08-05 00:44:28 -0400707 ACPI_MOVE_32_TO_32(buffer,
708 &linked_list->data.address32.min_address_range);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 buffer += 4;
710
Robert Moore44f6c012005-04-18 22:49:35 -0400711 /* Set the address range maximum */
712
Len Brown4be44fc2005-08-05 00:44:28 -0400713 ACPI_MOVE_32_TO_32(buffer,
714 &linked_list->data.address32.max_address_range);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715 buffer += 4;
716
Robert Moore44f6c012005-04-18 22:49:35 -0400717 /* Set the address translation offset */
718
Len Brown4be44fc2005-08-05 00:44:28 -0400719 ACPI_MOVE_32_TO_32(buffer,
720 &linked_list->data.address32.
721 address_translation_offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 buffer += 4;
723
Robert Moore44f6c012005-04-18 22:49:35 -0400724 /* Set the address length */
725
Len Brown4be44fc2005-08-05 00:44:28 -0400726 ACPI_MOVE_32_TO_32(buffer, &linked_list->data.address32.address_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 buffer += 4;
728
Robert Moore44f6c012005-04-18 22:49:35 -0400729 /* Resource Source Index and Resource Source are optional */
730
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 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
Len Brown4be44fc2005-08-05 00:44:28 -0400737 temp_pointer = (char *)buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738
Robert Moore44f6c012005-04-18 22:49:35 -0400739 /* Copy the string */
740
Len Brown4be44fc2005-08-05 00:44:28 -0400741 ACPI_STRCPY(temp_pointer,
742 linked_list->data.address32.resource_source.
743 string_ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744
745 /*
746 * Buffer needs to be set to the length of the sting + one for the
747 * terminating null
748 */
Len Brown4be44fc2005-08-05 00:44:28 -0400749 buffer +=
750 (acpi_size) (ACPI_STRLEN
751 (linked_list->data.address32.resource_source.
752 string_ptr) + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 }
754
Robert Moore44f6c012005-04-18 22:49:35 -0400755 /* Return the number of bytes consumed in this operation */
756
Len Brown4be44fc2005-08-05 00:44:28 -0400757 *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758
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);
Len Brown4be44fc2005-08-05 00:44:28 -0400764 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765}
766
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767/*******************************************************************************
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
Len Brown4be44fc2005-08-05 00:44:28 -0400789acpi_rs_address64_resource(u8 * byte_stream_buffer,
790 acpi_size * bytes_consumed,
791 u8 ** output_buffer, acpi_size * structure_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792{
Len Brown4be44fc2005-08-05 00:44:28 -0400793 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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
Len Brown4be44fc2005-08-05 00:44:28 -0400802 ACPI_FUNCTION_TRACE("rs_address64_resource");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803
804 buffer = byte_stream_buffer;
Len Brown4be44fc2005-08-05 00:44:28 -0400805 struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 resource_type = *buffer;
807
Robert Moore44f6c012005-04-18 22:49:35 -0400808 /* Point past the Descriptor to get the number of bytes consumed */
809
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 buffer += 1;
Len Brown4be44fc2005-08-05 00:44:28 -0400811 ACPI_MOVE_16_TO_16(&temp16, buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812
813 /* Validate minimum descriptor length */
814
815 if (temp16 < 43) {
Len Brown4be44fc2005-08-05 00:44:28 -0400816 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 }
818
819 *bytes_consumed = temp16 + 3;
820 output_struct->id = ACPI_RSTYPE_ADDRESS64;
821
Robert Moore44f6c012005-04-18 22:49:35 -0400822 /* Get the Resource Type (Byte3) */
823
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 buffer += 2;
825 temp8 = *buffer;
826
827 /* Values 0-2 and 0xC0-0xFF are valid */
828
829 if ((temp8 > 2) && (temp8 < 0xC0)) {
Len Brown4be44fc2005-08-05 00:44:28 -0400830 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 }
832
833 output_struct->data.address64.resource_type = temp8;
834
Robert Moore44f6c012005-04-18 22:49:35 -0400835 /* Get the General Flags (Byte4) */
836
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 buffer += 1;
838 temp8 = *buffer;
839
Robert Moore44f6c012005-04-18 22:49:35 -0400840 /* Producer / Consumer */
841
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 output_struct->data.address64.producer_consumer = temp8 & 0x01;
843
Robert Moore44f6c012005-04-18 22:49:35 -0400844 /* Decode */
845
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 output_struct->data.address64.decode = (temp8 >> 1) & 0x01;
847
Robert Moore44f6c012005-04-18 22:49:35 -0400848 /* Min Address Fixed */
849
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 output_struct->data.address64.min_address_fixed = (temp8 >> 2) & 0x01;
851
Robert Moore44f6c012005-04-18 22:49:35 -0400852 /* Max Address Fixed */
853
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 output_struct->data.address64.max_address_fixed = (temp8 >> 3) & 0x01;
855
Robert Moore44f6c012005-04-18 22:49:35 -0400856 /* Get the Type Specific Flags (Byte5) */
857
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 buffer += 1;
859 temp8 = *buffer;
860
861 if (ACPI_MEMORY_RANGE == output_struct->data.address64.resource_type) {
Len Brown4be44fc2005-08-05 00:44:28 -0400862 output_struct->data.address64.attribute.memory.
863 read_write_attribute = (u16) (temp8 & 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864
865 output_struct->data.address64.attribute.memory.cache_attribute =
Len Brown4be44fc2005-08-05 00:44:28 -0400866 (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 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 /* 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
Robert Moore44f6c012005-04-18 22:49:35 -0400886 /* Get Granularity (Bytes 6-13) or (Bytes 8-15) */
887
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 buffer += 1;
Len Brown4be44fc2005-08-05 00:44:28 -0400889 ACPI_MOVE_64_TO_64(&output_struct->data.address64.granularity, buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890
Robert Moore44f6c012005-04-18 22:49:35 -0400891 /* Get min_address_range (Bytes 14-21) or (Bytes 16-23) */
892
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 buffer += 8;
Len Brown4be44fc2005-08-05 00:44:28 -0400894 ACPI_MOVE_64_TO_64(&output_struct->data.address64.min_address_range,
895 buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896
Robert Moore44f6c012005-04-18 22:49:35 -0400897 /* Get max_address_range (Bytes 22-29) or (Bytes 24-31) */
898
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 buffer += 8;
Len Brown4be44fc2005-08-05 00:44:28 -0400900 ACPI_MOVE_64_TO_64(&output_struct->data.address64.max_address_range,
901 buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902
Robert Moore44f6c012005-04-18 22:49:35 -0400903 /* Get address_translation_offset (Bytes 30-37) or (Bytes 32-39) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904
Robert Moore44f6c012005-04-18 22:49:35 -0400905 buffer += 8;
Len Brown4be44fc2005-08-05 00:44:28 -0400906 ACPI_MOVE_64_TO_64(&output_struct->data.address64.
907 address_translation_offset, buffer);
Robert Moore44f6c012005-04-18 22:49:35 -0400908
909 /* Get address_length (Bytes 38-45) or (Bytes 40-47) */
910
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 buffer += 8;
Len Brown4be44fc2005-08-05 00:44:28 -0400912 ACPI_MOVE_64_TO_64(&output_struct->data.address64.address_length,
913 buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914
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;
Len Brown4be44fc2005-08-05 00:44:28 -0400923 ACPI_MOVE_64_TO_64(&output_struct->data.address64.
924 type_specific_attributes, buffer);
925 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 output_struct->data.address64.type_specific_attributes = 0;
927
Robert Moore44f6c012005-04-18 22:49:35 -0400928 /* Resource Source Index (if present) */
929
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 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 =
Len Brown4be44fc2005-08-05 00:44:28 -0400947 (u32) temp8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
949 /* Point to the String */
950
951 buffer += 1;
952
953 /* Point the String pointer to the end of this structure */
954
Len Brown4be44fc2005-08-05 00:44:28 -0400955 output_struct->data.address64.resource_source.
956 string_ptr =
957 (char *)((u8 *) output_struct + struct_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958
Robert Moore44f6c012005-04-18 22:49:35 -0400959 temp_ptr = (u8 *)
Len Brown4be44fc2005-08-05 00:44:28 -0400960 output_struct->data.address64.resource_source.
961 string_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962
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;
Len Brown4be44fc2005-08-05 00:44:28 -0400978 output_struct->data.address64.resource_source.
979 string_length = index + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980
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);
Len Brown4be44fc2005-08-05 00:44:28 -0400987 struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 }
989 }
990
Robert Moore44f6c012005-04-18 22:49:35 -0400991 /* Set the Length parameter */
992
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 output_struct->length = (u32) struct_size;
994
Robert Moore44f6c012005-04-18 22:49:35 -0400995 /* Return the final size of the structure */
996
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 *structure_size = struct_size;
Len Brown4be44fc2005-08-05 00:44:28 -0400998 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999}
1000
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001/*******************************************************************************
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
Len Brown4be44fc2005-08-05 00:44:28 -04001018acpi_rs_address64_stream(struct acpi_resource *linked_list,
1019 u8 ** output_buffer, acpi_size * bytes_consumed)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020{
Len Brown4be44fc2005-08-05 00:44:28 -04001021 u8 *buffer;
1022 u16 *length_field;
1023 u8 temp8;
1024 char *temp_pointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025
Len Brown4be44fc2005-08-05 00:44:28 -04001026 ACPI_FUNCTION_TRACE("rs_address64_stream");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027
1028 buffer = *output_buffer;
1029
Robert Moore44f6c012005-04-18 22:49:35 -04001030 /* The descriptor field is static */
1031
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 *buffer = 0x8A;
1033 buffer += 1;
1034
Robert Moore44f6c012005-04-18 22:49:35 -04001035 /* Set a pointer to the Length field - to be filled in later */
1036
Len Brown4be44fc2005-08-05 00:44:28 -04001037 length_field = ACPI_CAST_PTR(u16, buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 buffer += 2;
1039
Robert Moore44f6c012005-04-18 22:49:35 -04001040 /* Set the Resource Type (Memory, Io, bus_number) */
1041
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 temp8 = (u8) (linked_list->data.address64.resource_type & 0x03);
1043
1044 *buffer = temp8;
1045 buffer += 1;
1046
Robert Moore44f6c012005-04-18 22:49:35 -04001047 /* Set the general flags */
1048
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 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
Robert Moore44f6c012005-04-18 22:49:35 -04001057 /* Set the type specific flags */
1058
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 temp8 = 0;
1060
1061 if (ACPI_MEMORY_RANGE == linked_list->data.address64.resource_type) {
1062 temp8 = (u8)
Len Brown4be44fc2005-08-05 00:44:28 -04001063 (linked_list->data.address64.attribute.memory.
1064 read_write_attribute & 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
1066 temp8 |=
Len Brown4be44fc2005-08-05 00:44:28 -04001067 (linked_list->data.address64.attribute.memory.
1068 cache_attribute & 0x03) << 1;
1069 } else if (ACPI_IO_RANGE == linked_list->data.address64.resource_type) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 temp8 = (u8)
Len Brown4be44fc2005-08-05 00:44:28 -04001071 (linked_list->data.address64.attribute.io.range_attribute &
1072 0x03);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 temp8 |=
Len Brown4be44fc2005-08-05 00:44:28 -04001074 (linked_list->data.address64.attribute.io.range_attribute &
1075 0x03) << 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 }
1077
1078 *buffer = temp8;
1079 buffer += 1;
1080
Robert Moore44f6c012005-04-18 22:49:35 -04001081 /* Set the address space granularity */
1082
Len Brown4be44fc2005-08-05 00:44:28 -04001083 ACPI_MOVE_64_TO_64(buffer, &linked_list->data.address64.granularity);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 buffer += 8;
1085
Robert Moore44f6c012005-04-18 22:49:35 -04001086 /* Set the address range minimum */
1087
Len Brown4be44fc2005-08-05 00:44:28 -04001088 ACPI_MOVE_64_TO_64(buffer,
1089 &linked_list->data.address64.min_address_range);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 buffer += 8;
1091
Robert Moore44f6c012005-04-18 22:49:35 -04001092 /* Set the address range maximum */
1093
Len Brown4be44fc2005-08-05 00:44:28 -04001094 ACPI_MOVE_64_TO_64(buffer,
1095 &linked_list->data.address64.max_address_range);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 buffer += 8;
1097
Robert Moore44f6c012005-04-18 22:49:35 -04001098 /* Set the address translation offset */
1099
Len Brown4be44fc2005-08-05 00:44:28 -04001100 ACPI_MOVE_64_TO_64(buffer,
1101 &linked_list->data.address64.
1102 address_translation_offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 buffer += 8;
1104
Robert Moore44f6c012005-04-18 22:49:35 -04001105 /* Set the address length */
1106
Len Brown4be44fc2005-08-05 00:44:28 -04001107 ACPI_MOVE_64_TO_64(buffer, &linked_list->data.address64.address_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 buffer += 8;
1109
Robert Moore44f6c012005-04-18 22:49:35 -04001110 /* Resource Source Index and Resource Source are optional */
1111
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 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
Len Brown4be44fc2005-08-05 00:44:28 -04001118 temp_pointer = (char *)buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119
Robert Moore44f6c012005-04-18 22:49:35 -04001120 /* Copy the string */
1121
Len Brown4be44fc2005-08-05 00:44:28 -04001122 ACPI_STRCPY(temp_pointer,
1123 linked_list->data.address64.resource_source.
1124 string_ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
1126 /*
1127 * Buffer needs to be set to the length of the sting + one for the
1128 * terminating null
1129 */
Len Brown4be44fc2005-08-05 00:44:28 -04001130 buffer +=
1131 (acpi_size) (ACPI_STRLEN
1132 (linked_list->data.address64.resource_source.
1133 string_ptr) + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 }
1135
Robert Moore44f6c012005-04-18 22:49:35 -04001136 /* Return the number of bytes consumed in this operation */
1137
Len Brown4be44fc2005-08-05 00:44:28 -04001138 *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
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);
Len Brown4be44fc2005-08-05 00:44:28 -04001145 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146}