1 /* 2 * pnpacpi -- PnP ACPI driver 3 * 4 * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr> 5 * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2, or (at your option) any 10 * later version. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 #include <linux/kernel.h> 22 #include <linux/acpi.h> 23 #include <linux/pci.h> 24 #include "pnpacpi.h" 25 26 #ifdef CONFIG_IA64 27 #define valid_IRQ(i) (1) 28 #else 29 #define valid_IRQ(i) (((i) != 0) && ((i) != 2)) 30 #endif 31 32 /* 33 * Allocated Resources 34 */ 35 static int irq_flags(int triggering, int polarity) 36 { 37 if (triggering == ACPI_LEVEL_SENSITIVE) { 38 if (polarity == ACPI_ACTIVE_LOW) 39 return IORESOURCE_IRQ_LOWLEVEL; 40 else 41 return IORESOURCE_IRQ_HIGHLEVEL; 42 } else { 43 if (polarity == ACPI_ACTIVE_LOW) 44 return IORESOURCE_IRQ_LOWEDGE; 45 else 46 return IORESOURCE_IRQ_HIGHEDGE; 47 } 48 } 49 50 static void decode_irq_flags(int flag, int *triggering, int *polarity) 51 { 52 switch (flag) { 53 case IORESOURCE_IRQ_LOWLEVEL: 54 *triggering = ACPI_LEVEL_SENSITIVE; 55 *polarity = ACPI_ACTIVE_LOW; 56 break; 57 case IORESOURCE_IRQ_HIGHLEVEL: 58 *triggering = ACPI_LEVEL_SENSITIVE; 59 *polarity = ACPI_ACTIVE_HIGH; 60 break; 61 case IORESOURCE_IRQ_LOWEDGE: 62 *triggering = ACPI_EDGE_SENSITIVE; 63 *polarity = ACPI_ACTIVE_LOW; 64 break; 65 case IORESOURCE_IRQ_HIGHEDGE: 66 *triggering = ACPI_EDGE_SENSITIVE; 67 *polarity = ACPI_ACTIVE_HIGH; 68 break; 69 } 70 } 71 72 static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, 73 u32 gsi, int triggering, 74 int polarity, int shareable) 75 { 76 int i = 0; 77 int irq; 78 int p, t; 79 static unsigned char warned; 80 81 if (!valid_IRQ(gsi)) 82 return; 83 84 while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) && 85 i < PNP_MAX_IRQ) 86 i++; 87 if (i >= PNP_MAX_IRQ && !warned) { 88 printk(KERN_WARNING "pnpacpi: exceeded the max number of IRQ " 89 "resources: %d \n", PNP_MAX_IRQ); 90 warned = 1; 91 return; 92 } 93 /* 94 * in IO-APIC mode, use overrided attribute. Two reasons: 95 * 1. BIOS bug in DSDT 96 * 2. BIOS uses IO-APIC mode Interrupt Source Override 97 */ 98 if (!acpi_get_override_irq(gsi, &t, &p)) { 99 t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; 100 p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; 101 102 if (triggering != t || polarity != p) { 103 pnp_warn("IRQ %d override to %s, %s", 104 gsi, t ? "edge":"level", p ? "low":"high"); 105 triggering = t; 106 polarity = p; 107 } 108 } 109 110 res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag 111 res->irq_resource[i].flags |= irq_flags(triggering, polarity); 112 irq = acpi_register_gsi(gsi, triggering, polarity); 113 if (irq < 0) { 114 res->irq_resource[i].flags |= IORESOURCE_DISABLED; 115 return; 116 } 117 118 if (shareable) 119 res->irq_resource[i].flags |= IORESOURCE_IRQ_SHAREABLE; 120 121 res->irq_resource[i].start = irq; 122 res->irq_resource[i].end = irq; 123 pcibios_penalize_isa_irq(irq, 1); 124 } 125 126 static int dma_flags(int type, int bus_master, int transfer) 127 { 128 int flags = 0; 129 130 if (bus_master) 131 flags |= IORESOURCE_DMA_MASTER; 132 switch (type) { 133 case ACPI_COMPATIBILITY: 134 flags |= IORESOURCE_DMA_COMPATIBLE; 135 break; 136 case ACPI_TYPE_A: 137 flags |= IORESOURCE_DMA_TYPEA; 138 break; 139 case ACPI_TYPE_B: 140 flags |= IORESOURCE_DMA_TYPEB; 141 break; 142 case ACPI_TYPE_F: 143 flags |= IORESOURCE_DMA_TYPEF; 144 break; 145 default: 146 /* Set a default value ? */ 147 flags |= IORESOURCE_DMA_COMPATIBLE; 148 pnp_err("Invalid DMA type"); 149 } 150 switch (transfer) { 151 case ACPI_TRANSFER_8: 152 flags |= IORESOURCE_DMA_8BIT; 153 break; 154 case ACPI_TRANSFER_8_16: 155 flags |= IORESOURCE_DMA_8AND16BIT; 156 break; 157 case ACPI_TRANSFER_16: 158 flags |= IORESOURCE_DMA_16BIT; 159 break; 160 default: 161 /* Set a default value ? */ 162 flags |= IORESOURCE_DMA_8AND16BIT; 163 pnp_err("Invalid DMA transfer type"); 164 } 165 166 return flags; 167 } 168 169 static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, 170 u32 dma, int type, 171 int bus_master, int transfer) 172 { 173 int i = 0; 174 static unsigned char warned; 175 176 while (i < PNP_MAX_DMA && 177 !(res->dma_resource[i].flags & IORESOURCE_UNSET)) 178 i++; 179 if (i < PNP_MAX_DMA) { 180 res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag 181 res->dma_resource[i].flags |= 182 dma_flags(type, bus_master, transfer); 183 if (dma == -1) { 184 res->dma_resource[i].flags |= IORESOURCE_DISABLED; 185 return; 186 } 187 res->dma_resource[i].start = dma; 188 res->dma_resource[i].end = dma; 189 } else if (!warned) { 190 printk(KERN_WARNING "pnpacpi: exceeded the max number of DMA " 191 "resources: %d \n", PNP_MAX_DMA); 192 warned = 1; 193 } 194 } 195 196 static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, 197 u64 io, u64 len, int io_decode) 198 { 199 int i = 0; 200 static unsigned char warned; 201 202 while (!(res->port_resource[i].flags & IORESOURCE_UNSET) && 203 i < PNP_MAX_PORT) 204 i++; 205 if (i < PNP_MAX_PORT) { 206 res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag 207 if (io_decode == ACPI_DECODE_16) 208 res->port_resource[i].flags |= PNP_PORT_FLAG_16BITADDR; 209 if (len <= 0 || (io + len - 1) >= 0x10003) { 210 res->port_resource[i].flags |= IORESOURCE_DISABLED; 211 return; 212 } 213 res->port_resource[i].start = io; 214 res->port_resource[i].end = io + len - 1; 215 } else if (!warned) { 216 printk(KERN_WARNING "pnpacpi: exceeded the max number of IO " 217 "resources: %d \n", PNP_MAX_PORT); 218 warned = 1; 219 } 220 } 221 222 static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res, 223 u64 mem, u64 len, 224 int write_protect) 225 { 226 int i = 0; 227 static unsigned char warned; 228 229 while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) && 230 (i < PNP_MAX_MEM)) 231 i++; 232 if (i < PNP_MAX_MEM) { 233 res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag 234 if (len <= 0) { 235 res->mem_resource[i].flags |= IORESOURCE_DISABLED; 236 return; 237 } 238 if (write_protect == ACPI_READ_WRITE_MEMORY) 239 res->mem_resource[i].flags |= IORESOURCE_MEM_WRITEABLE; 240 241 res->mem_resource[i].start = mem; 242 res->mem_resource[i].end = mem + len - 1; 243 } else if (!warned) { 244 printk(KERN_WARNING "pnpacpi: exceeded the max number of mem " 245 "resources: %d\n", PNP_MAX_MEM); 246 warned = 1; 247 } 248 } 249 250 static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table, 251 struct acpi_resource *res) 252 { 253 struct acpi_resource_address64 addr, *p = &addr; 254 acpi_status status; 255 256 status = acpi_resource_to_address64(res, p); 257 if (!ACPI_SUCCESS(status)) { 258 pnp_warn("PnPACPI: failed to convert resource type %d", 259 res->type); 260 return; 261 } 262 263 if (p->producer_consumer == ACPI_PRODUCER) 264 return; 265 266 if (p->resource_type == ACPI_MEMORY_RANGE) 267 pnpacpi_parse_allocated_memresource(res_table, 268 p->minimum, p->address_length, 269 p->info.mem.write_protect); 270 else if (p->resource_type == ACPI_IO_RANGE) 271 pnpacpi_parse_allocated_ioresource(res_table, 272 p->minimum, p->address_length, 273 p->granularity == 0xfff ? ACPI_DECODE_10 : 274 ACPI_DECODE_16); 275 } 276 277 static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, 278 void *data) 279 { 280 struct pnp_resource_table *res_table = data; 281 int i; 282 283 switch (res->type) { 284 case ACPI_RESOURCE_TYPE_IRQ: 285 /* 286 * Per spec, only one interrupt per descriptor is allowed in 287 * _CRS, but some firmware violates this, so parse them all. 288 */ 289 for (i = 0; i < res->data.irq.interrupt_count; i++) { 290 pnpacpi_parse_allocated_irqresource(res_table, 291 res->data.irq.interrupts[i], 292 res->data.irq.triggering, 293 res->data.irq.polarity, 294 res->data.irq.sharable); 295 } 296 break; 297 298 case ACPI_RESOURCE_TYPE_DMA: 299 if (res->data.dma.channel_count > 0) 300 pnpacpi_parse_allocated_dmaresource(res_table, 301 res->data.dma.channels[0], 302 res->data.dma.type, 303 res->data.dma.bus_master, 304 res->data.dma.transfer); 305 break; 306 307 case ACPI_RESOURCE_TYPE_IO: 308 pnpacpi_parse_allocated_ioresource(res_table, 309 res->data.io.minimum, 310 res->data.io.address_length, 311 res->data.io.io_decode); 312 break; 313 314 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 315 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 316 break; 317 318 case ACPI_RESOURCE_TYPE_FIXED_IO: 319 pnpacpi_parse_allocated_ioresource(res_table, 320 res->data.fixed_io.address, 321 res->data.fixed_io.address_length, 322 ACPI_DECODE_10); 323 break; 324 325 case ACPI_RESOURCE_TYPE_VENDOR: 326 break; 327 328 case ACPI_RESOURCE_TYPE_END_TAG: 329 break; 330 331 case ACPI_RESOURCE_TYPE_MEMORY24: 332 pnpacpi_parse_allocated_memresource(res_table, 333 res->data.memory24.minimum, 334 res->data.memory24.address_length, 335 res->data.memory24.write_protect); 336 break; 337 case ACPI_RESOURCE_TYPE_MEMORY32: 338 pnpacpi_parse_allocated_memresource(res_table, 339 res->data.memory32.minimum, 340 res->data.memory32.address_length, 341 res->data.memory32.write_protect); 342 break; 343 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 344 pnpacpi_parse_allocated_memresource(res_table, 345 res->data.fixed_memory32.address, 346 res->data.fixed_memory32.address_length, 347 res->data.fixed_memory32.write_protect); 348 break; 349 case ACPI_RESOURCE_TYPE_ADDRESS16: 350 case ACPI_RESOURCE_TYPE_ADDRESS32: 351 case ACPI_RESOURCE_TYPE_ADDRESS64: 352 pnpacpi_parse_allocated_address_space(res_table, res); 353 break; 354 355 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: 356 if (res->data.ext_address64.producer_consumer == ACPI_PRODUCER) 357 return AE_OK; 358 break; 359 360 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 361 if (res->data.extended_irq.producer_consumer == ACPI_PRODUCER) 362 return AE_OK; 363 364 for (i = 0; i < res->data.extended_irq.interrupt_count; i++) { 365 pnpacpi_parse_allocated_irqresource(res_table, 366 res->data.extended_irq.interrupts[i], 367 res->data.extended_irq.triggering, 368 res->data.extended_irq.polarity, 369 res->data.extended_irq.sharable); 370 } 371 break; 372 373 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: 374 break; 375 376 default: 377 pnp_warn("PnPACPI: unknown resource type %d", res->type); 378 return AE_ERROR; 379 } 380 381 return AE_OK; 382 } 383 384 acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, 385 struct pnp_resource_table * res) 386 { 387 /* Blank the resource table values */ 388 pnp_init_resource_table(res); 389 390 return acpi_walk_resources(handle, METHOD_NAME__CRS, 391 pnpacpi_allocated_resource, res); 392 } 393 394 static __init void pnpacpi_parse_dma_option(struct pnp_option *option, 395 struct acpi_resource_dma *p) 396 { 397 int i; 398 struct pnp_dma *dma; 399 400 if (p->channel_count == 0) 401 return; 402 dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL); 403 if (!dma) 404 return; 405 406 for (i = 0; i < p->channel_count; i++) 407 dma->map |= 1 << p->channels[i]; 408 409 dma->flags = dma_flags(p->type, p->bus_master, p->transfer); 410 411 pnp_register_dma_resource(option, dma); 412 } 413 414 static __init void pnpacpi_parse_irq_option(struct pnp_option *option, 415 struct acpi_resource_irq *p) 416 { 417 int i; 418 struct pnp_irq *irq; 419 420 if (p->interrupt_count == 0) 421 return; 422 irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL); 423 if (!irq) 424 return; 425 426 for (i = 0; i < p->interrupt_count; i++) 427 if (p->interrupts[i]) 428 __set_bit(p->interrupts[i], irq->map); 429 irq->flags = irq_flags(p->triggering, p->polarity); 430 431 pnp_register_irq_resource(option, irq); 432 } 433 434 static __init void pnpacpi_parse_ext_irq_option(struct pnp_option *option, 435 struct acpi_resource_extended_irq *p) 436 { 437 int i; 438 struct pnp_irq *irq; 439 440 if (p->interrupt_count == 0) 441 return; 442 irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL); 443 if (!irq) 444 return; 445 446 for (i = 0; i < p->interrupt_count; i++) 447 if (p->interrupts[i]) 448 __set_bit(p->interrupts[i], irq->map); 449 irq->flags = irq_flags(p->triggering, p->polarity); 450 451 pnp_register_irq_resource(option, irq); 452 } 453 454 static __init void pnpacpi_parse_port_option(struct pnp_option *option, 455 struct acpi_resource_io *io) 456 { 457 struct pnp_port *port; 458 459 if (io->address_length == 0) 460 return; 461 port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); 462 if (!port) 463 return; 464 port->min = io->minimum; 465 port->max = io->maximum; 466 port->align = io->alignment; 467 port->size = io->address_length; 468 port->flags = ACPI_DECODE_16 == io->io_decode ? 469 PNP_PORT_FLAG_16BITADDR : 0; 470 pnp_register_port_resource(option, port); 471 } 472 473 static __init void pnpacpi_parse_fixed_port_option(struct pnp_option *option, 474 struct acpi_resource_fixed_io *io) 475 { 476 struct pnp_port *port; 477 478 if (io->address_length == 0) 479 return; 480 port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); 481 if (!port) 482 return; 483 port->min = port->max = io->address; 484 port->size = io->address_length; 485 port->align = 0; 486 port->flags = PNP_PORT_FLAG_FIXED; 487 pnp_register_port_resource(option, port); 488 } 489 490 static __init void pnpacpi_parse_mem24_option(struct pnp_option *option, 491 struct acpi_resource_memory24 *p) 492 { 493 struct pnp_mem *mem; 494 495 if (p->address_length == 0) 496 return; 497 mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); 498 if (!mem) 499 return; 500 mem->min = p->minimum; 501 mem->max = p->maximum; 502 mem->align = p->alignment; 503 mem->size = p->address_length; 504 505 mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? 506 IORESOURCE_MEM_WRITEABLE : 0; 507 508 pnp_register_mem_resource(option, mem); 509 } 510 511 static __init void pnpacpi_parse_mem32_option(struct pnp_option *option, 512 struct acpi_resource_memory32 *p) 513 { 514 struct pnp_mem *mem; 515 516 if (p->address_length == 0) 517 return; 518 mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); 519 if (!mem) 520 return; 521 mem->min = p->minimum; 522 mem->max = p->maximum; 523 mem->align = p->alignment; 524 mem->size = p->address_length; 525 526 mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? 527 IORESOURCE_MEM_WRITEABLE : 0; 528 529 pnp_register_mem_resource(option, mem); 530 } 531 532 static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, 533 struct acpi_resource_fixed_memory32 *p) 534 { 535 struct pnp_mem *mem; 536 537 if (p->address_length == 0) 538 return; 539 mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); 540 if (!mem) 541 return; 542 mem->min = mem->max = p->address; 543 mem->size = p->address_length; 544 mem->align = 0; 545 546 mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? 547 IORESOURCE_MEM_WRITEABLE : 0; 548 549 pnp_register_mem_resource(option, mem); 550 } 551 552 static __init void pnpacpi_parse_address_option(struct pnp_option *option, 553 struct acpi_resource *r) 554 { 555 struct acpi_resource_address64 addr, *p = &addr; 556 acpi_status status; 557 struct pnp_mem *mem; 558 struct pnp_port *port; 559 560 status = acpi_resource_to_address64(r, p); 561 if (!ACPI_SUCCESS(status)) { 562 pnp_warn("PnPACPI: failed to convert resource type %d", 563 r->type); 564 return; 565 } 566 567 if (p->address_length == 0) 568 return; 569 570 if (p->resource_type == ACPI_MEMORY_RANGE) { 571 mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); 572 if (!mem) 573 return; 574 mem->min = mem->max = p->minimum; 575 mem->size = p->address_length; 576 mem->align = 0; 577 mem->flags = (p->info.mem.write_protect == 578 ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE 579 : 0; 580 pnp_register_mem_resource(option, mem); 581 } else if (p->resource_type == ACPI_IO_RANGE) { 582 port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); 583 if (!port) 584 return; 585 port->min = port->max = p->minimum; 586 port->size = p->address_length; 587 port->align = 0; 588 port->flags = PNP_PORT_FLAG_FIXED; 589 pnp_register_port_resource(option, port); 590 } 591 } 592 593 struct acpipnp_parse_option_s { 594 struct pnp_option *option; 595 struct pnp_option *option_independent; 596 struct pnp_dev *dev; 597 }; 598 599 static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, 600 void *data) 601 { 602 int priority = 0; 603 struct acpipnp_parse_option_s *parse_data = data; 604 struct pnp_dev *dev = parse_data->dev; 605 struct pnp_option *option = parse_data->option; 606 607 switch (res->type) { 608 case ACPI_RESOURCE_TYPE_IRQ: 609 pnpacpi_parse_irq_option(option, &res->data.irq); 610 break; 611 612 case ACPI_RESOURCE_TYPE_DMA: 613 pnpacpi_parse_dma_option(option, &res->data.dma); 614 break; 615 616 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 617 switch (res->data.start_dpf.compatibility_priority) { 618 case ACPI_GOOD_CONFIGURATION: 619 priority = PNP_RES_PRIORITY_PREFERRED; 620 break; 621 622 case ACPI_ACCEPTABLE_CONFIGURATION: 623 priority = PNP_RES_PRIORITY_ACCEPTABLE; 624 break; 625 626 case ACPI_SUB_OPTIMAL_CONFIGURATION: 627 priority = PNP_RES_PRIORITY_FUNCTIONAL; 628 break; 629 default: 630 priority = PNP_RES_PRIORITY_INVALID; 631 break; 632 } 633 /* TBD: Consider performance/robustness bits */ 634 option = pnp_register_dependent_option(dev, priority); 635 if (!option) 636 return AE_ERROR; 637 parse_data->option = option; 638 break; 639 640 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 641 /*only one EndDependentFn is allowed */ 642 if (!parse_data->option_independent) { 643 pnp_warn("PnPACPI: more than one EndDependentFn"); 644 return AE_ERROR; 645 } 646 parse_data->option = parse_data->option_independent; 647 parse_data->option_independent = NULL; 648 break; 649 650 case ACPI_RESOURCE_TYPE_IO: 651 pnpacpi_parse_port_option(option, &res->data.io); 652 break; 653 654 case ACPI_RESOURCE_TYPE_FIXED_IO: 655 pnpacpi_parse_fixed_port_option(option, &res->data.fixed_io); 656 break; 657 658 case ACPI_RESOURCE_TYPE_VENDOR: 659 case ACPI_RESOURCE_TYPE_END_TAG: 660 break; 661 662 case ACPI_RESOURCE_TYPE_MEMORY24: 663 pnpacpi_parse_mem24_option(option, &res->data.memory24); 664 break; 665 666 case ACPI_RESOURCE_TYPE_MEMORY32: 667 pnpacpi_parse_mem32_option(option, &res->data.memory32); 668 break; 669 670 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 671 pnpacpi_parse_fixed_mem32_option(option, 672 &res->data.fixed_memory32); 673 break; 674 675 case ACPI_RESOURCE_TYPE_ADDRESS16: 676 case ACPI_RESOURCE_TYPE_ADDRESS32: 677 case ACPI_RESOURCE_TYPE_ADDRESS64: 678 pnpacpi_parse_address_option(option, res); 679 break; 680 681 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: 682 break; 683 684 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 685 pnpacpi_parse_ext_irq_option(option, &res->data.extended_irq); 686 break; 687 688 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: 689 break; 690 691 default: 692 pnp_warn("PnPACPI: unknown resource type %d", res->type); 693 return AE_ERROR; 694 } 695 696 return AE_OK; 697 } 698 699 acpi_status __init pnpacpi_parse_resource_option_data(acpi_handle handle, 700 struct pnp_dev *dev) 701 { 702 acpi_status status; 703 struct acpipnp_parse_option_s parse_data; 704 705 parse_data.option = pnp_register_independent_option(dev); 706 if (!parse_data.option) 707 return AE_ERROR; 708 parse_data.option_independent = parse_data.option; 709 parse_data.dev = dev; 710 status = acpi_walk_resources(handle, METHOD_NAME__PRS, 711 pnpacpi_option_resource, &parse_data); 712 713 return status; 714 } 715 716 static int pnpacpi_supported_resource(struct acpi_resource *res) 717 { 718 switch (res->type) { 719 case ACPI_RESOURCE_TYPE_IRQ: 720 case ACPI_RESOURCE_TYPE_DMA: 721 case ACPI_RESOURCE_TYPE_IO: 722 case ACPI_RESOURCE_TYPE_FIXED_IO: 723 case ACPI_RESOURCE_TYPE_MEMORY24: 724 case ACPI_RESOURCE_TYPE_MEMORY32: 725 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 726 case ACPI_RESOURCE_TYPE_ADDRESS16: 727 case ACPI_RESOURCE_TYPE_ADDRESS32: 728 case ACPI_RESOURCE_TYPE_ADDRESS64: 729 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 730 return 1; 731 } 732 return 0; 733 } 734 735 /* 736 * Set resource 737 */ 738 static acpi_status pnpacpi_count_resources(struct acpi_resource *res, 739 void *data) 740 { 741 int *res_cnt = data; 742 743 if (pnpacpi_supported_resource(res)) 744 (*res_cnt)++; 745 return AE_OK; 746 } 747 748 static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data) 749 { 750 struct acpi_resource **resource = data; 751 752 if (pnpacpi_supported_resource(res)) { 753 (*resource)->type = res->type; 754 (*resource)->length = sizeof(struct acpi_resource); 755 (*resource)++; 756 } 757 758 return AE_OK; 759 } 760 761 int pnpacpi_build_resource_template(acpi_handle handle, 762 struct acpi_buffer *buffer) 763 { 764 struct acpi_resource *resource; 765 int res_cnt = 0; 766 acpi_status status; 767 768 status = acpi_walk_resources(handle, METHOD_NAME__CRS, 769 pnpacpi_count_resources, &res_cnt); 770 if (ACPI_FAILURE(status)) { 771 pnp_err("Evaluate _CRS failed"); 772 return -EINVAL; 773 } 774 if (!res_cnt) 775 return -EINVAL; 776 buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1; 777 buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL); 778 if (!buffer->pointer) 779 return -ENOMEM; 780 pnp_dbg("Res cnt %d", res_cnt); 781 resource = (struct acpi_resource *)buffer->pointer; 782 status = acpi_walk_resources(handle, METHOD_NAME__CRS, 783 pnpacpi_type_resources, &resource); 784 if (ACPI_FAILURE(status)) { 785 kfree(buffer->pointer); 786 pnp_err("Evaluate _CRS failed"); 787 return -EINVAL; 788 } 789 /* resource will pointer the end resource now */ 790 resource->type = ACPI_RESOURCE_TYPE_END_TAG; 791 792 return 0; 793 } 794 795 static void pnpacpi_encode_irq(struct acpi_resource *resource, 796 struct resource *p) 797 { 798 int triggering, polarity; 799 800 decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); 801 resource->data.irq.triggering = triggering; 802 resource->data.irq.polarity = polarity; 803 if (triggering == ACPI_EDGE_SENSITIVE) 804 resource->data.irq.sharable = ACPI_EXCLUSIVE; 805 else 806 resource->data.irq.sharable = ACPI_SHARED; 807 resource->data.irq.interrupt_count = 1; 808 resource->data.irq.interrupts[0] = p->start; 809 } 810 811 static void pnpacpi_encode_ext_irq(struct acpi_resource *resource, 812 struct resource *p) 813 { 814 int triggering, polarity; 815 816 decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); 817 resource->data.extended_irq.producer_consumer = ACPI_CONSUMER; 818 resource->data.extended_irq.triggering = triggering; 819 resource->data.extended_irq.polarity = polarity; 820 if (triggering == ACPI_EDGE_SENSITIVE) 821 resource->data.irq.sharable = ACPI_EXCLUSIVE; 822 else 823 resource->data.irq.sharable = ACPI_SHARED; 824 resource->data.extended_irq.interrupt_count = 1; 825 resource->data.extended_irq.interrupts[0] = p->start; 826 } 827 828 static void pnpacpi_encode_dma(struct acpi_resource *resource, 829 struct resource *p) 830 { 831 /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ 832 switch (p->flags & IORESOURCE_DMA_SPEED_MASK) { 833 case IORESOURCE_DMA_TYPEA: 834 resource->data.dma.type = ACPI_TYPE_A; 835 break; 836 case IORESOURCE_DMA_TYPEB: 837 resource->data.dma.type = ACPI_TYPE_B; 838 break; 839 case IORESOURCE_DMA_TYPEF: 840 resource->data.dma.type = ACPI_TYPE_F; 841 break; 842 default: 843 resource->data.dma.type = ACPI_COMPATIBILITY; 844 } 845 846 switch (p->flags & IORESOURCE_DMA_TYPE_MASK) { 847 case IORESOURCE_DMA_8BIT: 848 resource->data.dma.transfer = ACPI_TRANSFER_8; 849 break; 850 case IORESOURCE_DMA_8AND16BIT: 851 resource->data.dma.transfer = ACPI_TRANSFER_8_16; 852 break; 853 default: 854 resource->data.dma.transfer = ACPI_TRANSFER_16; 855 } 856 857 resource->data.dma.bus_master = !!(p->flags & IORESOURCE_DMA_MASTER); 858 resource->data.dma.channel_count = 1; 859 resource->data.dma.channels[0] = p->start; 860 } 861 862 static void pnpacpi_encode_io(struct acpi_resource *resource, 863 struct resource *p) 864 { 865 /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */ 866 resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ? 867 ACPI_DECODE_16 : ACPI_DECODE_10; 868 resource->data.io.minimum = p->start; 869 resource->data.io.maximum = p->end; 870 resource->data.io.alignment = 0; /* Correct? */ 871 resource->data.io.address_length = p->end - p->start + 1; 872 } 873 874 static void pnpacpi_encode_fixed_io(struct acpi_resource *resource, 875 struct resource *p) 876 { 877 resource->data.fixed_io.address = p->start; 878 resource->data.fixed_io.address_length = p->end - p->start + 1; 879 } 880 881 static void pnpacpi_encode_mem24(struct acpi_resource *resource, 882 struct resource *p) 883 { 884 /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */ 885 resource->data.memory24.write_protect = 886 (p->flags & IORESOURCE_MEM_WRITEABLE) ? 887 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; 888 resource->data.memory24.minimum = p->start; 889 resource->data.memory24.maximum = p->end; 890 resource->data.memory24.alignment = 0; 891 resource->data.memory24.address_length = p->end - p->start + 1; 892 } 893 894 static void pnpacpi_encode_mem32(struct acpi_resource *resource, 895 struct resource *p) 896 { 897 resource->data.memory32.write_protect = 898 (p->flags & IORESOURCE_MEM_WRITEABLE) ? 899 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; 900 resource->data.memory32.minimum = p->start; 901 resource->data.memory32.maximum = p->end; 902 resource->data.memory32.alignment = 0; 903 resource->data.memory32.address_length = p->end - p->start + 1; 904 } 905 906 static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource, 907 struct resource *p) 908 { 909 resource->data.fixed_memory32.write_protect = 910 (p->flags & IORESOURCE_MEM_WRITEABLE) ? 911 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; 912 resource->data.fixed_memory32.address = p->start; 913 resource->data.fixed_memory32.address_length = p->end - p->start + 1; 914 } 915 916 int pnpacpi_encode_resources(struct pnp_resource_table *res_table, 917 struct acpi_buffer *buffer) 918 { 919 int i = 0; 920 /* pnpacpi_build_resource_template allocates extra mem */ 921 int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1; 922 struct acpi_resource *resource = buffer->pointer; 923 int port = 0, irq = 0, dma = 0, mem = 0; 924 925 pnp_dbg("res cnt %d", res_cnt); 926 while (i < res_cnt) { 927 switch (resource->type) { 928 case ACPI_RESOURCE_TYPE_IRQ: 929 pnp_dbg("Encode irq"); 930 pnpacpi_encode_irq(resource, 931 &res_table->irq_resource[irq]); 932 irq++; 933 break; 934 935 case ACPI_RESOURCE_TYPE_DMA: 936 pnp_dbg("Encode dma"); 937 pnpacpi_encode_dma(resource, 938 &res_table->dma_resource[dma]); 939 dma++; 940 break; 941 case ACPI_RESOURCE_TYPE_IO: 942 pnp_dbg("Encode io"); 943 pnpacpi_encode_io(resource, 944 &res_table->port_resource[port]); 945 port++; 946 break; 947 case ACPI_RESOURCE_TYPE_FIXED_IO: 948 pnp_dbg("Encode fixed io"); 949 pnpacpi_encode_fixed_io(resource, 950 &res_table-> 951 port_resource[port]); 952 port++; 953 break; 954 case ACPI_RESOURCE_TYPE_MEMORY24: 955 pnp_dbg("Encode mem24"); 956 pnpacpi_encode_mem24(resource, 957 &res_table->mem_resource[mem]); 958 mem++; 959 break; 960 case ACPI_RESOURCE_TYPE_MEMORY32: 961 pnp_dbg("Encode mem32"); 962 pnpacpi_encode_mem32(resource, 963 &res_table->mem_resource[mem]); 964 mem++; 965 break; 966 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 967 pnp_dbg("Encode fixed mem32"); 968 pnpacpi_encode_fixed_mem32(resource, 969 &res_table-> 970 mem_resource[mem]); 971 mem++; 972 break; 973 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 974 pnp_dbg("Encode ext irq"); 975 pnpacpi_encode_ext_irq(resource, 976 &res_table->irq_resource[irq]); 977 irq++; 978 break; 979 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 980 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 981 case ACPI_RESOURCE_TYPE_VENDOR: 982 case ACPI_RESOURCE_TYPE_END_TAG: 983 case ACPI_RESOURCE_TYPE_ADDRESS16: 984 case ACPI_RESOURCE_TYPE_ADDRESS32: 985 case ACPI_RESOURCE_TYPE_ADDRESS64: 986 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: 987 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: 988 default: /* other type */ 989 pnp_warn("unknown resource type %d", resource->type); 990 return -EINVAL; 991 } 992 resource++; 993 i++; 994 } 995 return 0; 996 } 997