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 edge_level, int active_high_low) 36 { 37 int flag; 38 if (edge_level == ACPI_LEVEL_SENSITIVE) { 39 if(active_high_low == ACPI_ACTIVE_LOW) 40 flag = IORESOURCE_IRQ_LOWLEVEL; 41 else 42 flag = IORESOURCE_IRQ_HIGHLEVEL; 43 } 44 else { 45 if(active_high_low == 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 *edge_level, int *active_high_low) 54 { 55 switch (flag) { 56 case IORESOURCE_IRQ_LOWLEVEL: 57 *edge_level = ACPI_LEVEL_SENSITIVE; 58 *active_high_low = ACPI_ACTIVE_LOW; 59 break; 60 case IORESOURCE_IRQ_HIGHLEVEL: 61 *edge_level = ACPI_LEVEL_SENSITIVE; 62 *active_high_low = ACPI_ACTIVE_HIGH; 63 break; 64 case IORESOURCE_IRQ_LOWEDGE: 65 *edge_level = ACPI_EDGE_SENSITIVE; 66 *active_high_low = ACPI_ACTIVE_LOW; 67 break; 68 case IORESOURCE_IRQ_HIGHEDGE: 69 *edge_level = ACPI_EDGE_SENSITIVE; 70 *active_high_low = 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 edge_level, int active_high_low) 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, edge_level, active_high_low); 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->id) { 167 case ACPI_RSTYPE_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.number_of_interrupts; i++) { 173 pnpacpi_parse_allocated_irqresource(res_table, 174 res->data.irq.interrupts[i], 175 res->data.irq.edge_level, 176 res->data.irq.active_high_low); 177 } 178 break; 179 180 case ACPI_RSTYPE_EXT_IRQ: 181 for (i = 0; i < res->data.extended_irq.number_of_interrupts; i++) { 182 pnpacpi_parse_allocated_irqresource(res_table, 183 res->data.extended_irq.interrupts[i], 184 res->data.extended_irq.edge_level, 185 res->data.extended_irq.active_high_low); 186 } 187 break; 188 case ACPI_RSTYPE_DMA: 189 if (res->data.dma.number_of_channels > 0) 190 pnpacpi_parse_allocated_dmaresource(res_table, 191 res->data.dma.channels[0]); 192 break; 193 case ACPI_RSTYPE_IO: 194 pnpacpi_parse_allocated_ioresource(res_table, 195 res->data.io.min_base_address, 196 res->data.io.range_length); 197 break; 198 case ACPI_RSTYPE_FIXED_IO: 199 pnpacpi_parse_allocated_ioresource(res_table, 200 res->data.fixed_io.base_address, 201 res->data.fixed_io.range_length); 202 break; 203 case ACPI_RSTYPE_MEM24: 204 pnpacpi_parse_allocated_memresource(res_table, 205 res->data.memory24.min_base_address, 206 res->data.memory24.range_length); 207 break; 208 case ACPI_RSTYPE_MEM32: 209 pnpacpi_parse_allocated_memresource(res_table, 210 res->data.memory32.min_base_address, 211 res->data.memory32.range_length); 212 break; 213 case ACPI_RSTYPE_FIXED_MEM32: 214 pnpacpi_parse_allocated_memresource(res_table, 215 res->data.fixed_memory32.range_base_address, 216 res->data.fixed_memory32.range_length); 217 break; 218 case ACPI_RSTYPE_ADDRESS16: 219 pnpacpi_parse_allocated_memresource(res_table, 220 res->data.address16.min_address_range, 221 res->data.address16.address_length); 222 break; 223 case ACPI_RSTYPE_ADDRESS32: 224 pnpacpi_parse_allocated_memresource(res_table, 225 res->data.address32.min_address_range, 226 res->data.address32.address_length); 227 break; 228 case ACPI_RSTYPE_ADDRESS64: 229 pnpacpi_parse_allocated_memresource(res_table, 230 res->data.address64.min_address_range, 231 res->data.address64.address_length); 232 break; 233 case ACPI_RSTYPE_VENDOR: 234 break; 235 default: 236 pnp_warn("PnPACPI: unknown resource type %d", res->id); 237 return AE_ERROR; 238 } 239 240 return AE_OK; 241 } 242 243 acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, struct pnp_resource_table * res) 244 { 245 /* Blank the resource table values */ 246 pnp_init_resource_table(res); 247 248 return acpi_walk_resources(handle, METHOD_NAME__CRS, pnpacpi_allocated_resource, res); 249 } 250 251 static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_resource_dma *p) 252 { 253 int i; 254 struct pnp_dma * dma; 255 256 if (p->number_of_channels == 0) 257 return; 258 dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL); 259 if (!dma) 260 return; 261 262 for(i = 0; i < p->number_of_channels; i++) 263 dma->map |= 1 << p->channels[i]; 264 dma->flags = 0; 265 if (p->bus_master) 266 dma->flags |= IORESOURCE_DMA_MASTER; 267 switch (p->type) { 268 case ACPI_COMPATIBILITY: 269 dma->flags |= IORESOURCE_DMA_COMPATIBLE; 270 break; 271 case ACPI_TYPE_A: 272 dma->flags |= IORESOURCE_DMA_TYPEA; 273 break; 274 case ACPI_TYPE_B: 275 dma->flags |= IORESOURCE_DMA_TYPEB; 276 break; 277 case ACPI_TYPE_F: 278 dma->flags |= IORESOURCE_DMA_TYPEF; 279 break; 280 default: 281 /* Set a default value ? */ 282 dma->flags |= IORESOURCE_DMA_COMPATIBLE; 283 pnp_err("Invalid DMA type"); 284 } 285 switch (p->transfer) { 286 case ACPI_TRANSFER_8: 287 dma->flags |= IORESOURCE_DMA_8BIT; 288 break; 289 case ACPI_TRANSFER_8_16: 290 dma->flags |= IORESOURCE_DMA_8AND16BIT; 291 break; 292 case ACPI_TRANSFER_16: 293 dma->flags |= IORESOURCE_DMA_16BIT; 294 break; 295 default: 296 /* Set a default value ? */ 297 dma->flags |= IORESOURCE_DMA_8AND16BIT; 298 pnp_err("Invalid DMA transfer type"); 299 } 300 301 pnp_register_dma_resource(option,dma); 302 return; 303 } 304 305 306 static void pnpacpi_parse_irq_option(struct pnp_option *option, 307 struct acpi_resource_irq *p) 308 { 309 int i; 310 struct pnp_irq * irq; 311 312 if (p->number_of_interrupts == 0) 313 return; 314 irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL); 315 if (!irq) 316 return; 317 318 for(i = 0; i < p->number_of_interrupts; i++) 319 if (p->interrupts[i]) 320 __set_bit(p->interrupts[i], irq->map); 321 irq->flags = irq_flags(p->edge_level, p->active_high_low); 322 323 pnp_register_irq_resource(option, irq); 324 return; 325 } 326 327 static void pnpacpi_parse_ext_irq_option(struct pnp_option *option, 328 struct acpi_resource_ext_irq *p) 329 { 330 int i; 331 struct pnp_irq * irq; 332 333 if (p->number_of_interrupts == 0) 334 return; 335 irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL); 336 if (!irq) 337 return; 338 339 for(i = 0; i < p->number_of_interrupts; i++) 340 if (p->interrupts[i]) 341 __set_bit(p->interrupts[i], irq->map); 342 irq->flags = irq_flags(p->edge_level, p->active_high_low); 343 344 pnp_register_irq_resource(option, irq); 345 return; 346 } 347 348 static void 349 pnpacpi_parse_port_option(struct pnp_option *option, 350 struct acpi_resource_io *io) 351 { 352 struct pnp_port * port; 353 354 if (io->range_length == 0) 355 return; 356 port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); 357 if (!port) 358 return; 359 port->min = io->min_base_address; 360 port->max = io->max_base_address; 361 port->align = io->alignment; 362 port->size = io->range_length; 363 port->flags = ACPI_DECODE_16 == io->io_decode ? 364 PNP_PORT_FLAG_16BITADDR : 0; 365 pnp_register_port_resource(option,port); 366 return; 367 } 368 369 static void 370 pnpacpi_parse_fixed_port_option(struct pnp_option *option, 371 struct acpi_resource_fixed_io *io) 372 { 373 struct pnp_port * port; 374 375 if (io->range_length == 0) 376 return; 377 port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); 378 if (!port) 379 return; 380 port->min = port->max = io->base_address; 381 port->size = io->range_length; 382 port->align = 0; 383 port->flags = PNP_PORT_FLAG_FIXED; 384 pnp_register_port_resource(option,port); 385 return; 386 } 387 388 static void 389 pnpacpi_parse_mem24_option(struct pnp_option *option, 390 struct acpi_resource_mem24 *p) 391 { 392 struct pnp_mem * mem; 393 394 if (p->range_length == 0) 395 return; 396 mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); 397 if (!mem) 398 return; 399 mem->min = p->min_base_address; 400 mem->max = p->max_base_address; 401 mem->align = p->alignment; 402 mem->size = p->range_length; 403 404 mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ? 405 IORESOURCE_MEM_WRITEABLE : 0; 406 407 pnp_register_mem_resource(option,mem); 408 return; 409 } 410 411 static void 412 pnpacpi_parse_mem32_option(struct pnp_option *option, 413 struct acpi_resource_mem32 *p) 414 { 415 struct pnp_mem * mem; 416 417 if (p->range_length == 0) 418 return; 419 mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); 420 if (!mem) 421 return; 422 mem->min = p->min_base_address; 423 mem->max = p->max_base_address; 424 mem->align = p->alignment; 425 mem->size = p->range_length; 426 427 mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ? 428 IORESOURCE_MEM_WRITEABLE : 0; 429 430 pnp_register_mem_resource(option,mem); 431 return; 432 } 433 434 static void 435 pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, 436 struct acpi_resource_fixed_mem32 *p) 437 { 438 struct pnp_mem * mem; 439 440 if (p->range_length == 0) 441 return; 442 mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); 443 if (!mem) 444 return; 445 mem->min = mem->max = p->range_base_address; 446 mem->size = p->range_length; 447 mem->align = 0; 448 449 mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ? 450 IORESOURCE_MEM_WRITEABLE : 0; 451 452 pnp_register_mem_resource(option,mem); 453 return; 454 } 455 456 struct acpipnp_parse_option_s { 457 struct pnp_option *option; 458 struct pnp_option *option_independent; 459 struct pnp_dev *dev; 460 }; 461 462 static acpi_status pnpacpi_option_resource(struct acpi_resource *res, 463 void *data) 464 { 465 int priority = 0; 466 struct acpipnp_parse_option_s *parse_data = (struct acpipnp_parse_option_s *)data; 467 struct pnp_dev *dev = parse_data->dev; 468 struct pnp_option *option = parse_data->option; 469 470 switch (res->id) { 471 case ACPI_RSTYPE_IRQ: 472 pnpacpi_parse_irq_option(option, &res->data.irq); 473 break; 474 case ACPI_RSTYPE_EXT_IRQ: 475 pnpacpi_parse_ext_irq_option(option, 476 &res->data.extended_irq); 477 break; 478 case ACPI_RSTYPE_DMA: 479 pnpacpi_parse_dma_option(option, &res->data.dma); 480 break; 481 case ACPI_RSTYPE_IO: 482 pnpacpi_parse_port_option(option, &res->data.io); 483 break; 484 case ACPI_RSTYPE_FIXED_IO: 485 pnpacpi_parse_fixed_port_option(option, 486 &res->data.fixed_io); 487 break; 488 case ACPI_RSTYPE_MEM24: 489 pnpacpi_parse_mem24_option(option, &res->data.memory24); 490 break; 491 case ACPI_RSTYPE_MEM32: 492 pnpacpi_parse_mem32_option(option, &res->data.memory32); 493 break; 494 case ACPI_RSTYPE_FIXED_MEM32: 495 pnpacpi_parse_fixed_mem32_option(option, 496 &res->data.fixed_memory32); 497 break; 498 case ACPI_RSTYPE_START_DPF: 499 switch (res->data.start_dpf.compatibility_priority) { 500 case ACPI_GOOD_CONFIGURATION: 501 priority = PNP_RES_PRIORITY_PREFERRED; 502 break; 503 504 case ACPI_ACCEPTABLE_CONFIGURATION: 505 priority = PNP_RES_PRIORITY_ACCEPTABLE; 506 break; 507 508 case ACPI_SUB_OPTIMAL_CONFIGURATION: 509 priority = PNP_RES_PRIORITY_FUNCTIONAL; 510 break; 511 default: 512 priority = PNP_RES_PRIORITY_INVALID; 513 break; 514 } 515 /* TBD: Considering performace/robustness bits */ 516 option = pnp_register_dependent_option(dev, priority); 517 if (!option) 518 return AE_ERROR; 519 parse_data->option = option; 520 break; 521 case ACPI_RSTYPE_END_DPF: 522 /*only one EndDependentFn is allowed*/ 523 if (!parse_data->option_independent) { 524 pnp_warn("PnPACPI: more than one EndDependentFn"); 525 return AE_ERROR; 526 } 527 parse_data->option = parse_data->option_independent; 528 parse_data->option_independent = NULL; 529 break; 530 default: 531 pnp_warn("PnPACPI: unknown resource type %d", res->id); 532 return AE_ERROR; 533 } 534 535 return AE_OK; 536 } 537 538 acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle, 539 struct pnp_dev *dev) 540 { 541 acpi_status status; 542 struct acpipnp_parse_option_s parse_data; 543 544 parse_data.option = pnp_register_independent_option(dev); 545 if (!parse_data.option) 546 return AE_ERROR; 547 parse_data.option_independent = parse_data.option; 548 parse_data.dev = dev; 549 status = acpi_walk_resources(handle, METHOD_NAME__PRS, 550 pnpacpi_option_resource, &parse_data); 551 552 return status; 553 } 554 555 /* 556 * Set resource 557 */ 558 static acpi_status pnpacpi_count_resources(struct acpi_resource *res, 559 void *data) 560 { 561 int *res_cnt = (int *)data; 562 switch (res->id) { 563 case ACPI_RSTYPE_IRQ: 564 case ACPI_RSTYPE_EXT_IRQ: 565 case ACPI_RSTYPE_DMA: 566 case ACPI_RSTYPE_IO: 567 case ACPI_RSTYPE_FIXED_IO: 568 case ACPI_RSTYPE_MEM24: 569 case ACPI_RSTYPE_MEM32: 570 case ACPI_RSTYPE_FIXED_MEM32: 571 #if 0 572 case ACPI_RSTYPE_ADDRESS16: 573 case ACPI_RSTYPE_ADDRESS32: 574 case ACPI_RSTYPE_ADDRESS64: 575 #endif 576 (*res_cnt) ++; 577 default: 578 return AE_OK; 579 } 580 return AE_OK; 581 } 582 583 static acpi_status pnpacpi_type_resources(struct acpi_resource *res, 584 void *data) 585 { 586 struct acpi_resource **resource = (struct acpi_resource **)data; 587 switch (res->id) { 588 case ACPI_RSTYPE_IRQ: 589 case ACPI_RSTYPE_EXT_IRQ: 590 case ACPI_RSTYPE_DMA: 591 case ACPI_RSTYPE_IO: 592 case ACPI_RSTYPE_FIXED_IO: 593 case ACPI_RSTYPE_MEM24: 594 case ACPI_RSTYPE_MEM32: 595 case ACPI_RSTYPE_FIXED_MEM32: 596 #if 0 597 case ACPI_RSTYPE_ADDRESS16: 598 case ACPI_RSTYPE_ADDRESS32: 599 case ACPI_RSTYPE_ADDRESS64: 600 #endif 601 (*resource)->id = res->id; 602 (*resource)++; 603 default: 604 return AE_OK; 605 } 606 607 return AE_OK; 608 } 609 610 int pnpacpi_build_resource_template(acpi_handle handle, 611 struct acpi_buffer *buffer) 612 { 613 struct acpi_resource *resource; 614 int res_cnt = 0; 615 acpi_status status; 616 617 status = acpi_walk_resources(handle, METHOD_NAME__CRS, 618 pnpacpi_count_resources, &res_cnt); 619 if (ACPI_FAILURE(status)) { 620 pnp_err("Evaluate _CRS failed"); 621 return -EINVAL; 622 } 623 if (!res_cnt) 624 return -EINVAL; 625 buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1; 626 buffer->pointer = kcalloc(1, buffer->length - 1, GFP_KERNEL); 627 if (!buffer->pointer) 628 return -ENOMEM; 629 pnp_dbg("Res cnt %d", res_cnt); 630 resource = (struct acpi_resource *)buffer->pointer; 631 status = acpi_walk_resources(handle, METHOD_NAME__CRS, 632 pnpacpi_type_resources, &resource); 633 if (ACPI_FAILURE(status)) { 634 kfree(buffer->pointer); 635 pnp_err("Evaluate _CRS failed"); 636 return -EINVAL; 637 } 638 /* resource will pointer the end resource now */ 639 resource->id = ACPI_RSTYPE_END_TAG; 640 641 return 0; 642 } 643 644 static void pnpacpi_encode_irq(struct acpi_resource *resource, 645 struct resource *p) 646 { 647 int edge_level, active_high_low; 648 649 decode_irq_flags(p->flags & IORESOURCE_BITS, &edge_level, 650 &active_high_low); 651 resource->id = ACPI_RSTYPE_IRQ; 652 resource->length = sizeof(struct acpi_resource); 653 resource->data.irq.edge_level = edge_level; 654 resource->data.irq.active_high_low = active_high_low; 655 if (edge_level == ACPI_EDGE_SENSITIVE) 656 resource->data.irq.shared_exclusive = ACPI_EXCLUSIVE; 657 else 658 resource->data.irq.shared_exclusive = ACPI_SHARED; 659 resource->data.irq.number_of_interrupts = 1; 660 resource->data.irq.interrupts[0] = p->start; 661 } 662 663 static void pnpacpi_encode_ext_irq(struct acpi_resource *resource, 664 struct resource *p) 665 { 666 int edge_level, active_high_low; 667 668 decode_irq_flags(p->flags & IORESOURCE_BITS, &edge_level, 669 &active_high_low); 670 resource->id = ACPI_RSTYPE_EXT_IRQ; 671 resource->length = sizeof(struct acpi_resource); 672 resource->data.extended_irq.producer_consumer = ACPI_CONSUMER; 673 resource->data.extended_irq.edge_level = edge_level; 674 resource->data.extended_irq.active_high_low = active_high_low; 675 if (edge_level == ACPI_EDGE_SENSITIVE) 676 resource->data.irq.shared_exclusive = ACPI_EXCLUSIVE; 677 else 678 resource->data.irq.shared_exclusive = ACPI_SHARED; 679 resource->data.extended_irq.number_of_interrupts = 1; 680 resource->data.extended_irq.interrupts[0] = p->start; 681 } 682 683 static void pnpacpi_encode_dma(struct acpi_resource *resource, 684 struct resource *p) 685 { 686 resource->id = ACPI_RSTYPE_DMA; 687 resource->length = sizeof(struct acpi_resource); 688 /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ 689 if (p->flags & IORESOURCE_DMA_COMPATIBLE) 690 resource->data.dma.type = ACPI_COMPATIBILITY; 691 else if (p->flags & IORESOURCE_DMA_TYPEA) 692 resource->data.dma.type = ACPI_TYPE_A; 693 else if (p->flags & IORESOURCE_DMA_TYPEB) 694 resource->data.dma.type = ACPI_TYPE_B; 695 else if (p->flags & IORESOURCE_DMA_TYPEF) 696 resource->data.dma.type = ACPI_TYPE_F; 697 if (p->flags & IORESOURCE_DMA_8BIT) 698 resource->data.dma.transfer = ACPI_TRANSFER_8; 699 else if (p->flags & IORESOURCE_DMA_8AND16BIT) 700 resource->data.dma.transfer = ACPI_TRANSFER_8_16; 701 else if (p->flags & IORESOURCE_DMA_16BIT) 702 resource->data.dma.transfer = ACPI_TRANSFER_16; 703 resource->data.dma.bus_master = p->flags & IORESOURCE_DMA_MASTER; 704 resource->data.dma.number_of_channels = 1; 705 resource->data.dma.channels[0] = p->start; 706 } 707 708 static void pnpacpi_encode_io(struct acpi_resource *resource, 709 struct resource *p) 710 { 711 resource->id = ACPI_RSTYPE_IO; 712 resource->length = sizeof(struct acpi_resource); 713 /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */ 714 resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR)? 715 ACPI_DECODE_16 : ACPI_DECODE_10; 716 resource->data.io.min_base_address = p->start; 717 resource->data.io.max_base_address = p->end; 718 resource->data.io.alignment = 0; /* Correct? */ 719 resource->data.io.range_length = p->end - p->start + 1; 720 } 721 722 static void pnpacpi_encode_fixed_io(struct acpi_resource *resource, 723 struct resource *p) 724 { 725 resource->id = ACPI_RSTYPE_FIXED_IO; 726 resource->length = sizeof(struct acpi_resource); 727 resource->data.fixed_io.base_address = p->start; 728 resource->data.fixed_io.range_length = p->end - p->start + 1; 729 } 730 731 static void pnpacpi_encode_mem24(struct acpi_resource *resource, 732 struct resource *p) 733 { 734 resource->id = ACPI_RSTYPE_MEM24; 735 resource->length = sizeof(struct acpi_resource); 736 /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */ 737 resource->data.memory24.read_write_attribute = 738 (p->flags & IORESOURCE_MEM_WRITEABLE) ? 739 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; 740 resource->data.memory24.min_base_address = p->start; 741 resource->data.memory24.max_base_address = p->end; 742 resource->data.memory24.alignment = 0; 743 resource->data.memory24.range_length = p->end - p->start + 1; 744 } 745 746 static void pnpacpi_encode_mem32(struct acpi_resource *resource, 747 struct resource *p) 748 { 749 resource->id = ACPI_RSTYPE_MEM32; 750 resource->length = sizeof(struct acpi_resource); 751 resource->data.memory32.read_write_attribute = 752 (p->flags & IORESOURCE_MEM_WRITEABLE) ? 753 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; 754 resource->data.memory32.min_base_address = p->start; 755 resource->data.memory32.max_base_address = p->end; 756 resource->data.memory32.alignment = 0; 757 resource->data.memory32.range_length = p->end - p->start + 1; 758 } 759 760 static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource, 761 struct resource *p) 762 { 763 resource->id = ACPI_RSTYPE_FIXED_MEM32; 764 resource->length = sizeof(struct acpi_resource); 765 resource->data.fixed_memory32.read_write_attribute = 766 (p->flags & IORESOURCE_MEM_WRITEABLE) ? 767 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; 768 resource->data.fixed_memory32.range_base_address = p->start; 769 resource->data.fixed_memory32.range_length = p->end - p->start + 1; 770 } 771 772 int pnpacpi_encode_resources(struct pnp_resource_table *res_table, 773 struct acpi_buffer *buffer) 774 { 775 int i = 0; 776 /* pnpacpi_build_resource_template allocates extra mem */ 777 int res_cnt = (buffer->length - 1)/sizeof(struct acpi_resource) - 1; 778 struct acpi_resource *resource = (struct acpi_resource*)buffer->pointer; 779 int port = 0, irq = 0, dma = 0, mem = 0; 780 781 pnp_dbg("res cnt %d", res_cnt); 782 while (i < res_cnt) { 783 switch(resource->id) { 784 case ACPI_RSTYPE_IRQ: 785 pnp_dbg("Encode irq"); 786 pnpacpi_encode_irq(resource, 787 &res_table->irq_resource[irq]); 788 irq++; 789 break; 790 791 case ACPI_RSTYPE_EXT_IRQ: 792 pnp_dbg("Encode ext irq"); 793 pnpacpi_encode_ext_irq(resource, 794 &res_table->irq_resource[irq]); 795 irq++; 796 break; 797 case ACPI_RSTYPE_DMA: 798 pnp_dbg("Encode dma"); 799 pnpacpi_encode_dma(resource, 800 &res_table->dma_resource[dma]); 801 dma ++; 802 break; 803 case ACPI_RSTYPE_IO: 804 pnp_dbg("Encode io"); 805 pnpacpi_encode_io(resource, 806 &res_table->port_resource[port]); 807 port ++; 808 break; 809 case ACPI_RSTYPE_FIXED_IO: 810 pnp_dbg("Encode fixed io"); 811 pnpacpi_encode_fixed_io(resource, 812 &res_table->port_resource[port]); 813 port ++; 814 break; 815 case ACPI_RSTYPE_MEM24: 816 pnp_dbg("Encode mem24"); 817 pnpacpi_encode_mem24(resource, 818 &res_table->mem_resource[mem]); 819 mem ++; 820 break; 821 case ACPI_RSTYPE_MEM32: 822 pnp_dbg("Encode mem32"); 823 pnpacpi_encode_mem32(resource, 824 &res_table->mem_resource[mem]); 825 mem ++; 826 break; 827 case ACPI_RSTYPE_FIXED_MEM32: 828 pnp_dbg("Encode fixed mem32"); 829 pnpacpi_encode_fixed_mem32(resource, 830 &res_table->mem_resource[mem]); 831 mem ++; 832 break; 833 default: /* other type */ 834 pnp_warn("unknown resource type %d", resource->id); 835 return -EINVAL; 836 } 837 resource ++; 838 i ++; 839 } 840 return 0; 841 } 842