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