Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /******************************************************************************* |
2 | * | |
3 | * Module Name: rsaddr - Address resource descriptors (16/32/64) | |
4 | * | |
5 | ******************************************************************************/ | |
6 | ||
7 | /* | |
8 | * Copyright (C) 2000 - 2005, R. Byron Moore | |
9 | * All rights reserved. | |
10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | |
15 | * notice, this list of conditions, and the following disclaimer, | |
16 | * without modification. | |
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | |
18 | * substantially similar to the "NO WARRANTY" disclaimer below | |
19 | * ("Disclaimer") and any redistribution must be conditioned upon | |
20 | * including a substantially similar Disclaimer requirement for further | |
21 | * binary redistribution. | |
22 | * 3. Neither the names of the above-listed copyright holders nor the names | |
23 | * of any contributors may be used to endorse or promote products derived | |
24 | * from this software without specific prior written permission. | |
25 | * | |
26 | * Alternatively, this software may be distributed under the terms of the | |
27 | * GNU General Public License ("GPL") version 2 as published by the Free | |
28 | * Software Foundation. | |
29 | * | |
30 | * NO WARRANTY | |
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | |
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | |
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
41 | * POSSIBILITY OF SUCH DAMAGES. | |
42 | */ | |
43 | ||
1da177e4 LT |
44 | #include <acpi/acpi.h> |
45 | #include <acpi/acresrc.h> | |
46 | ||
47 | #define _COMPONENT ACPI_RESOURCES | |
4be44fcd | 48 | ACPI_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 | 70 | acpi_status |
4be44fcd LB |
71 | acpi_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 | ||
277 | acpi_status | |
4be44fcd LB |
278 | acpi_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 | ||
430 | acpi_status | |
4be44fcd LB |
431 | acpi_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 | ||
636 | acpi_status | |
4be44fcd LB |
637 | acpi_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 | ||
788 | acpi_status | |
4be44fcd LB |
789 | acpi_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 | ||
1017 | acpi_status | |
4be44fcd LB |
1018 | acpi_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 | } |