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