Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 77b2555b52a894a2e39a42e43d993df875c46a6a 552 lines 16 kB view raw
1/******************************************************************************* 2 * 3 * Module Name: rsirq - IRQ resource descriptors 4 * 5 ******************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2005, R. Byron Moore 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44#include <acpi/acpi.h> 45#include <acpi/acresrc.h> 46 47#define _COMPONENT ACPI_RESOURCES 48ACPI_MODULE_NAME("rsirq") 49 50/******************************************************************************* 51 * 52 * FUNCTION: acpi_rs_irq_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 ******************************************************************************/ 70acpi_status 71acpi_rs_irq_resource(u8 * byte_stream_buffer, 72 acpi_size * bytes_consumed, 73 u8 ** output_buffer, acpi_size * structure_size) 74{ 75 u8 *buffer = byte_stream_buffer; 76 struct acpi_resource *output_struct = (void *)*output_buffer; 77 u16 temp16 = 0; 78 u8 temp8 = 0; 79 u8 index; 80 u8 i; 81 acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_irq); 82 83 ACPI_FUNCTION_TRACE("rs_irq_resource"); 84 85 /* 86 * The number of bytes consumed are contained in the descriptor 87 * (Bits:0-1) 88 */ 89 temp8 = *buffer; 90 *bytes_consumed = (temp8 & 0x03) + 1; 91 output_struct->id = ACPI_RSTYPE_IRQ; 92 93 /* Point to the 16-bits of Bytes 1 and 2 */ 94 95 buffer += 1; 96 ACPI_MOVE_16_TO_16(&temp16, buffer); 97 98 output_struct->data.irq.number_of_interrupts = 0; 99 100 /* Decode the IRQ bits */ 101 102 for (i = 0, index = 0; index < 16; index++) { 103 if ((temp16 >> index) & 0x01) { 104 output_struct->data.irq.interrupts[i] = index; 105 i++; 106 } 107 } 108 109 /* Zero interrupts is valid */ 110 111 output_struct->data.irq.number_of_interrupts = i; 112 if (i > 0) { 113 /* Calculate the structure size based upon the number of interrupts */ 114 115 struct_size += ((acpi_size) i - 1) * 4; 116 } 117 118 /* Point to Byte 3 if it is used */ 119 120 if (4 == *bytes_consumed) { 121 buffer += 2; 122 temp8 = *buffer; 123 124 /* Check for HE, LL interrupts */ 125 126 switch (temp8 & 0x09) { 127 case 0x01: /* HE */ 128 output_struct->data.irq.edge_level = 129 ACPI_EDGE_SENSITIVE; 130 output_struct->data.irq.active_high_low = 131 ACPI_ACTIVE_HIGH; 132 break; 133 134 case 0x08: /* LL */ 135 output_struct->data.irq.edge_level = 136 ACPI_LEVEL_SENSITIVE; 137 output_struct->data.irq.active_high_low = 138 ACPI_ACTIVE_LOW; 139 break; 140 141 default: 142 /* 143 * Only _LL and _HE polarity/trigger interrupts 144 * are allowed (ACPI spec, section "IRQ Format") 145 * so 0x00 and 0x09 are illegal. 146 */ 147 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 148 "Invalid interrupt polarity/trigger in resource list, %X\n", 149 temp8)); 150 return_ACPI_STATUS(AE_BAD_DATA); 151 } 152 153 /* Check for sharable */ 154 155 output_struct->data.irq.shared_exclusive = (temp8 >> 3) & 0x01; 156 } else { 157 /* 158 * Assume Edge Sensitive, Active High, Non-Sharable 159 * per ACPI Specification 160 */ 161 output_struct->data.irq.edge_level = ACPI_EDGE_SENSITIVE; 162 output_struct->data.irq.active_high_low = ACPI_ACTIVE_HIGH; 163 output_struct->data.irq.shared_exclusive = ACPI_EXCLUSIVE; 164 } 165 166 /* Set the Length parameter */ 167 168 output_struct->length = (u32) struct_size; 169 170 /* Return the final size of the structure */ 171 172 *structure_size = struct_size; 173 return_ACPI_STATUS(AE_OK); 174} 175 176/******************************************************************************* 177 * 178 * FUNCTION: acpi_rs_irq_stream 179 * 180 * PARAMETERS: linked_list - Pointer to the resource linked list 181 * output_buffer - Pointer to the user's return buffer 182 * bytes_consumed - Pointer to where the number of bytes 183 * used in the output_buffer is returned 184 * 185 * RETURN: Status 186 * 187 * DESCRIPTION: Take the linked list resource structure and fills in the 188 * the appropriate bytes in a byte stream 189 * 190 ******************************************************************************/ 191 192acpi_status 193acpi_rs_irq_stream(struct acpi_resource *linked_list, 194 u8 ** output_buffer, acpi_size * bytes_consumed) 195{ 196 u8 *buffer = *output_buffer; 197 u16 temp16 = 0; 198 u8 temp8 = 0; 199 u8 index; 200 u8 IRqinfo_byte_needed; 201 202 ACPI_FUNCTION_TRACE("rs_irq_stream"); 203 204 /* 205 * The descriptor field is set based upon whether a third byte is 206 * needed to contain the IRQ Information. 207 */ 208 if (ACPI_EDGE_SENSITIVE == linked_list->data.irq.edge_level && 209 ACPI_ACTIVE_HIGH == linked_list->data.irq.active_high_low && 210 ACPI_EXCLUSIVE == linked_list->data.irq.shared_exclusive) { 211 *buffer = 0x22; 212 IRqinfo_byte_needed = FALSE; 213 } else { 214 *buffer = 0x23; 215 IRqinfo_byte_needed = TRUE; 216 } 217 218 buffer += 1; 219 temp16 = 0; 220 221 /* Loop through all of the interrupts and set the mask bits */ 222 223 for (index = 0; 224 index < linked_list->data.irq.number_of_interrupts; index++) { 225 temp8 = (u8) linked_list->data.irq.interrupts[index]; 226 temp16 |= 0x1 << temp8; 227 } 228 229 ACPI_MOVE_16_TO_16(buffer, &temp16); 230 buffer += 2; 231 232 /* Set the IRQ Info byte if needed. */ 233 234 if (IRqinfo_byte_needed) { 235 temp8 = 0; 236 temp8 = (u8) ((linked_list->data.irq.shared_exclusive & 237 0x01) << 4); 238 239 if (ACPI_LEVEL_SENSITIVE == linked_list->data.irq.edge_level && 240 ACPI_ACTIVE_LOW == linked_list->data.irq.active_high_low) { 241 temp8 |= 0x08; 242 } else { 243 temp8 |= 0x01; 244 } 245 246 *buffer = temp8; 247 buffer += 1; 248 } 249 250 /* Return the number of bytes consumed in this operation */ 251 252 *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer); 253 return_ACPI_STATUS(AE_OK); 254} 255 256/******************************************************************************* 257 * 258 * FUNCTION: acpi_rs_extended_irq_resource 259 * 260 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte 261 * stream 262 * bytes_consumed - Pointer to where the number of bytes 263 * consumed the byte_stream_buffer is 264 * returned 265 * output_buffer - Pointer to the return data buffer 266 * structure_size - Pointer to where the number of bytes 267 * in the return data struct is returned 268 * 269 * RETURN: Status 270 * 271 * DESCRIPTION: Take the resource byte stream and fill out the appropriate 272 * structure pointed to by the output_buffer. Return the 273 * number of bytes consumed from the byte stream. 274 * 275 ******************************************************************************/ 276 277acpi_status 278acpi_rs_extended_irq_resource(u8 * byte_stream_buffer, 279 acpi_size * bytes_consumed, 280 u8 ** output_buffer, acpi_size * structure_size) 281{ 282 u8 *buffer = byte_stream_buffer; 283 struct acpi_resource *output_struct = (void *)*output_buffer; 284 u16 temp16 = 0; 285 u8 temp8 = 0; 286 u8 *temp_ptr; 287 u8 index; 288 acpi_size struct_size = 289 ACPI_SIZEOF_RESOURCE(struct acpi_resource_ext_irq); 290 291 ACPI_FUNCTION_TRACE("rs_extended_irq_resource"); 292 293 /* Get the Descriptor Length field */ 294 295 buffer += 1; 296 ACPI_MOVE_16_TO_16(&temp16, buffer); 297 298 /* Validate minimum descriptor length */ 299 300 if (temp16 < 6) { 301 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); 302 } 303 304 *bytes_consumed = temp16 + 3; 305 output_struct->id = ACPI_RSTYPE_EXT_IRQ; 306 307 /* Point to the Byte3 */ 308 309 buffer += 2; 310 temp8 = *buffer; 311 312 output_struct->data.extended_irq.producer_consumer = temp8 & 0x01; 313 314 /* 315 * Check for Interrupt Mode 316 * 317 * The definition of an Extended IRQ changed between ACPI spec v1.0b 318 * and ACPI spec 2.0 (section 6.4.3.6 in both). 319 * 320 * - Edge/Level are defined opposite in the table vs the headers 321 */ 322 output_struct->data.extended_irq.edge_level = 323 (temp8 & 0x2) ? ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE; 324 325 /* Check Interrupt Polarity */ 326 327 output_struct->data.extended_irq.active_high_low = (temp8 >> 2) & 0x1; 328 329 /* Check for sharable */ 330 331 output_struct->data.extended_irq.shared_exclusive = (temp8 >> 3) & 0x01; 332 333 /* Point to Byte4 (IRQ Table length) */ 334 335 buffer += 1; 336 temp8 = *buffer; 337 338 /* Must have at least one IRQ */ 339 340 if (temp8 < 1) { 341 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); 342 } 343 344 output_struct->data.extended_irq.number_of_interrupts = temp8; 345 346 /* 347 * Add any additional structure size to properly calculate 348 * the next pointer at the end of this function 349 */ 350 struct_size += (temp8 - 1) * 4; 351 352 /* Point to Byte5 (First IRQ Number) */ 353 354 buffer += 1; 355 356 /* Cycle through every IRQ in the table */ 357 358 for (index = 0; index < temp8; index++) { 359 ACPI_MOVE_32_TO_32(&output_struct->data.extended_irq. 360 interrupts[index], buffer); 361 362 /* Point to the next IRQ */ 363 364 buffer += 4; 365 } 366 367 /* 368 * This will leave us pointing to the Resource Source Index 369 * If it is present, then save it off and calculate the 370 * pointer to where the null terminated string goes: 371 * Each Interrupt takes 32-bits + the 5 bytes of the 372 * stream that are default. 373 * 374 * Note: Some resource descriptors will have an additional null, so 375 * we add 1 to the length. 376 */ 377 if (*bytes_consumed > 378 ((acpi_size) output_struct->data.extended_irq.number_of_interrupts * 379 4) + (5 + 1)) { 380 /* Dereference the Index */ 381 382 temp8 = *buffer; 383 output_struct->data.extended_irq.resource_source.index = 384 (u32) temp8; 385 386 /* Point to the String */ 387 388 buffer += 1; 389 390 /* Point the String pointer to the end of this structure. */ 391 392 output_struct->data.extended_irq.resource_source.string_ptr = 393 (char *)((char *)output_struct + struct_size); 394 395 temp_ptr = (u8 *) 396 output_struct->data.extended_irq.resource_source.string_ptr; 397 398 /* Copy the string into the buffer */ 399 400 index = 0; 401 while (*buffer) { 402 *temp_ptr = *buffer; 403 404 temp_ptr += 1; 405 buffer += 1; 406 index += 1; 407 } 408 409 /* Add the terminating null */ 410 411 *temp_ptr = 0; 412 output_struct->data.extended_irq.resource_source.string_length = 413 index + 1; 414 415 /* 416 * In order for the struct_size to fall on a 32-bit boundary, 417 * calculate the length of the string and expand the 418 * struct_size to the next 32-bit boundary. 419 */ 420 temp8 = (u8) (index + 1); 421 struct_size += ACPI_ROUND_UP_to_32_bITS(temp8); 422 } else { 423 output_struct->data.extended_irq.resource_source.index = 0; 424 output_struct->data.extended_irq.resource_source.string_length = 425 0; 426 output_struct->data.extended_irq.resource_source.string_ptr = 427 NULL; 428 } 429 430 /* Set the Length parameter */ 431 432 output_struct->length = (u32) struct_size; 433 434 /* Return the final size of the structure */ 435 436 *structure_size = struct_size; 437 return_ACPI_STATUS(AE_OK); 438} 439 440/******************************************************************************* 441 * 442 * FUNCTION: acpi_rs_extended_irq_stream 443 * 444 * PARAMETERS: linked_list - Pointer to the resource linked list 445 * output_buffer - Pointer to the user's return buffer 446 * bytes_consumed - Pointer to where the number of bytes 447 * used in the output_buffer is returned 448 * 449 * RETURN: Status 450 * 451 * DESCRIPTION: Take the linked list resource structure and fills in the 452 * the appropriate bytes in a byte stream 453 * 454 ******************************************************************************/ 455 456acpi_status 457acpi_rs_extended_irq_stream(struct acpi_resource *linked_list, 458 u8 ** output_buffer, acpi_size * bytes_consumed) 459{ 460 u8 *buffer = *output_buffer; 461 u16 *length_field; 462 u8 temp8 = 0; 463 u8 index; 464 465 ACPI_FUNCTION_TRACE("rs_extended_irq_stream"); 466 467 /* Set the Descriptor Type field */ 468 469 *buffer = ACPI_RDESC_TYPE_EXTENDED_XRUPT; 470 buffer += 1; 471 472 /* Save a pointer to the Length field - to be filled in later */ 473 474 length_field = ACPI_CAST_PTR(u16, buffer); 475 buffer += 2; 476 477 /* Set the Interrupt vector flags */ 478 479 temp8 = (u8) (linked_list->data.extended_irq.producer_consumer & 0x01); 480 temp8 |= 481 ((linked_list->data.extended_irq.shared_exclusive & 0x01) << 3); 482 483 /* 484 * Set the Interrupt Mode 485 * 486 * The definition of an Extended IRQ changed between ACPI spec v1.0b 487 * and ACPI spec 2.0 (section 6.4.3.6 in both). This code does not 488 * implement the more restrictive definition of 1.0b 489 * 490 * - Edge/Level are defined opposite in the table vs the headers 491 */ 492 if (ACPI_EDGE_SENSITIVE == linked_list->data.extended_irq.edge_level) { 493 temp8 |= 0x2; 494 } 495 496 /* Set the Interrupt Polarity */ 497 498 temp8 |= ((linked_list->data.extended_irq.active_high_low & 0x1) << 2); 499 500 *buffer = temp8; 501 buffer += 1; 502 503 /* Set the Interrupt table length */ 504 505 temp8 = (u8) linked_list->data.extended_irq.number_of_interrupts; 506 507 *buffer = temp8; 508 buffer += 1; 509 510 for (index = 0; 511 index < linked_list->data.extended_irq.number_of_interrupts; 512 index++) { 513 ACPI_MOVE_32_TO_32(buffer, 514 &linked_list->data.extended_irq. 515 interrupts[index]); 516 buffer += 4; 517 } 518 519 /* Resource Source Index and Resource Source are optional */ 520 521 if (0 != linked_list->data.extended_irq.resource_source.string_length) { 522 *buffer = 523 (u8) linked_list->data.extended_irq.resource_source.index; 524 buffer += 1; 525 526 /* Copy the string */ 527 528 ACPI_STRCPY((char *)buffer, 529 linked_list->data.extended_irq.resource_source. 530 string_ptr); 531 532 /* 533 * Buffer needs to be set to the length of the string + one for the 534 * terminating null 535 */ 536 buffer += 537 (acpi_size) (ACPI_STRLEN 538 (linked_list->data.extended_irq. 539 resource_source.string_ptr) + 1); 540 } 541 542 /* Return the number of bytes consumed in this operation */ 543 544 *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer); 545 546 /* 547 * Set the length field to the number of bytes consumed 548 * minus the header size (3 bytes) 549 */ 550 *length_field = (u16) (*bytes_consumed - 3); 551 return_ACPI_STATUS(AE_OK); 552}