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