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 (!(res->dma_resource[i].flags & IORESOURCE_UNSET) && 98 i < PNP_MAX_DMA) 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]); 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]); 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_dev *dev; 448 }; 449 450 static acpi_status pnpacpi_option_resource(struct acpi_resource *res, 451 void *data) 452 { 453 int priority = 0; 454 struct acpipnp_parse_option_s *parse_data = (struct acpipnp_parse_option_s *)data; 455 struct pnp_dev *dev = parse_data->dev; 456 struct pnp_option *option = parse_data->option; 457 458 switch (res->id) { 459 case ACPI_RSTYPE_IRQ: 460 pnpacpi_parse_irq_option(option, &res->data.irq); 461 break; 462 case ACPI_RSTYPE_EXT_IRQ: 463 pnpacpi_parse_ext_irq_option(option, 464 &res->data.extended_irq); 465 break; 466 case ACPI_RSTYPE_DMA: 467 pnpacpi_parse_dma_option(option, &res->data.dma); 468 break; 469 case ACPI_RSTYPE_IO: 470 pnpacpi_parse_port_option(option, &res->data.io); 471 break; 472 case ACPI_RSTYPE_FIXED_IO: 473 pnpacpi_parse_fixed_port_option(option, 474 &res->data.fixed_io); 475 break; 476 case ACPI_RSTYPE_MEM24: 477 pnpacpi_parse_mem24_option(option, &res->data.memory24); 478 break; 479 case ACPI_RSTYPE_MEM32: 480 pnpacpi_parse_mem32_option(option, &res->data.memory32); 481 break; 482 case ACPI_RSTYPE_FIXED_MEM32: 483 pnpacpi_parse_fixed_mem32_option(option, 484 &res->data.fixed_memory32); 485 break; 486 case ACPI_RSTYPE_START_DPF: 487 switch (res->data.start_dpf.compatibility_priority) { 488 case ACPI_GOOD_CONFIGURATION: 489 priority = PNP_RES_PRIORITY_PREFERRED; 490 break; 491 492 case ACPI_ACCEPTABLE_CONFIGURATION: 493 priority = PNP_RES_PRIORITY_ACCEPTABLE; 494 break; 495 496 case ACPI_SUB_OPTIMAL_CONFIGURATION: 497 priority = PNP_RES_PRIORITY_FUNCTIONAL; 498 break; 499 default: 500 priority = PNP_RES_PRIORITY_INVALID; 501 break; 502 } 503 /* TBD: Considering performace/robustness bits */ 504 option = pnp_register_dependent_option(dev, priority); 505 if (!option) 506 return AE_ERROR; 507 parse_data->option = option; 508 break; 509 case ACPI_RSTYPE_END_DPF: 510 return AE_CTRL_TERMINATE; 511 default: 512 pnp_warn("PnPACPI: unknown resource type %d", res->id); 513 return AE_ERROR; 514 } 515 516 return AE_OK; 517 } 518 519 acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle, 520 struct pnp_dev *dev) 521 { 522 acpi_status status; 523 struct acpipnp_parse_option_s parse_data; 524 525 parse_data.option = pnp_register_independent_option(dev); 526 if (!parse_data.option) 527 return AE_ERROR; 528 parse_data.dev = dev; 529 status = acpi_walk_resources(handle, METHOD_NAME__PRS, 530 pnpacpi_option_resource, &parse_data); 531 532 return status; 533 } 534 535 /* 536 * Set resource 537 */ 538 static acpi_status pnpacpi_count_resources(struct acpi_resource *res, 539 void *data) 540 { 541 int *res_cnt = (int *)data; 542 switch (res->id) { 543 case ACPI_RSTYPE_IRQ: 544 case ACPI_RSTYPE_EXT_IRQ: 545 case ACPI_RSTYPE_DMA: 546 case ACPI_RSTYPE_IO: 547 case ACPI_RSTYPE_FIXED_IO: 548 case ACPI_RSTYPE_MEM24: 549 case ACPI_RSTYPE_MEM32: 550 case ACPI_RSTYPE_FIXED_MEM32: 551 #if 0 552 case ACPI_RSTYPE_ADDRESS16: 553 case ACPI_RSTYPE_ADDRESS32: 554 case ACPI_RSTYPE_ADDRESS64: 555 #endif 556 (*res_cnt) ++; 557 default: 558 return AE_OK; 559 } 560 return AE_OK; 561 } 562 563 static acpi_status pnpacpi_type_resources(struct acpi_resource *res, 564 void *data) 565 { 566 struct acpi_resource **resource = (struct acpi_resource **)data; 567 switch (res->id) { 568 case ACPI_RSTYPE_IRQ: 569 case ACPI_RSTYPE_EXT_IRQ: 570 case ACPI_RSTYPE_DMA: 571 case ACPI_RSTYPE_IO: 572 case ACPI_RSTYPE_FIXED_IO: 573 case ACPI_RSTYPE_MEM24: 574 case ACPI_RSTYPE_MEM32: 575 case ACPI_RSTYPE_FIXED_MEM32: 576 #if 0 577 case ACPI_RSTYPE_ADDRESS16: 578 case ACPI_RSTYPE_ADDRESS32: 579 case ACPI_RSTYPE_ADDRESS64: 580 #endif 581 (*resource)->id = res->id; 582 (*resource)++; 583 default: 584 return AE_OK; 585 } 586 587 return AE_OK; 588 } 589 590 int pnpacpi_build_resource_template(acpi_handle handle, 591 struct acpi_buffer *buffer) 592 { 593 struct acpi_resource *resource; 594 int res_cnt = 0; 595 acpi_status status; 596 597 status = acpi_walk_resources(handle, METHOD_NAME__CRS, 598 pnpacpi_count_resources, &res_cnt); 599 if (ACPI_FAILURE(status)) { 600 pnp_err("Evaluate _CRS failed"); 601 return -EINVAL; 602 } 603 if (!res_cnt) 604 return -EINVAL; 605 buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1; 606 buffer->pointer = pnpacpi_kmalloc(buffer->length - 1, GFP_KERNEL); 607 if (!buffer->pointer) 608 return -ENOMEM; 609 pnp_dbg("Res cnt %d", res_cnt); 610 resource = (struct acpi_resource *)buffer->pointer; 611 status = acpi_walk_resources(handle, METHOD_NAME__CRS, 612 pnpacpi_type_resources, &resource); 613 if (ACPI_FAILURE(status)) { 614 kfree(buffer->pointer); 615 pnp_err("Evaluate _CRS failed"); 616 return -EINVAL; 617 } 618 /* resource will pointer the end resource now */ 619 resource->id = ACPI_RSTYPE_END_TAG; 620 621 return 0; 622 } 623 624 static void pnpacpi_encode_irq(struct acpi_resource *resource, 625 struct resource *p) 626 { 627 int edge_level, active_high_low; 628 629 decode_irq_flags(p->flags & IORESOURCE_BITS, &edge_level, 630 &active_high_low); 631 resource->id = ACPI_RSTYPE_IRQ; 632 resource->length = sizeof(struct acpi_resource); 633 resource->data.irq.edge_level = edge_level; 634 resource->data.irq.active_high_low = active_high_low; 635 if (edge_level == ACPI_EDGE_SENSITIVE) 636 resource->data.irq.shared_exclusive = ACPI_EXCLUSIVE; 637 else 638 resource->data.irq.shared_exclusive = ACPI_SHARED; 639 resource->data.irq.number_of_interrupts = 1; 640 resource->data.irq.interrupts[0] = p->start; 641 } 642 643 static void pnpacpi_encode_ext_irq(struct acpi_resource *resource, 644 struct resource *p) 645 { 646 int edge_level, active_high_low; 647 648 decode_irq_flags(p->flags & IORESOURCE_BITS, &edge_level, 649 &active_high_low); 650 resource->id = ACPI_RSTYPE_EXT_IRQ; 651 resource->length = sizeof(struct acpi_resource); 652 resource->data.extended_irq.producer_consumer = ACPI_CONSUMER; 653 resource->data.extended_irq.edge_level = edge_level; 654 resource->data.extended_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.extended_irq.number_of_interrupts = 1; 660 resource->data.extended_irq.interrupts[0] = p->start; 661 } 662 663 static void pnpacpi_encode_dma(struct acpi_resource *resource, 664 struct resource *p) 665 { 666 resource->id = ACPI_RSTYPE_DMA; 667 resource->length = sizeof(struct acpi_resource); 668 /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ 669 if (p->flags & IORESOURCE_DMA_COMPATIBLE) 670 resource->data.dma.type = ACPI_COMPATIBILITY; 671 else if (p->flags & IORESOURCE_DMA_TYPEA) 672 resource->data.dma.type = ACPI_TYPE_A; 673 else if (p->flags & IORESOURCE_DMA_TYPEB) 674 resource->data.dma.type = ACPI_TYPE_B; 675 else if (p->flags & IORESOURCE_DMA_TYPEF) 676 resource->data.dma.type = ACPI_TYPE_F; 677 if (p->flags & IORESOURCE_DMA_8BIT) 678 resource->data.dma.transfer = ACPI_TRANSFER_8; 679 else if (p->flags & IORESOURCE_DMA_8AND16BIT) 680 resource->data.dma.transfer = ACPI_TRANSFER_8_16; 681 else if (p->flags & IORESOURCE_DMA_16BIT) 682 resource->data.dma.transfer = ACPI_TRANSFER_16; 683 resource->data.dma.bus_master = p->flags & IORESOURCE_DMA_MASTER; 684 resource->data.dma.number_of_channels = 1; 685 resource->data.dma.channels[0] = p->start; 686 } 687 688 static void pnpacpi_encode_io(struct acpi_resource *resource, 689 struct resource *p) 690 { 691 resource->id = ACPI_RSTYPE_IO; 692 resource->length = sizeof(struct acpi_resource); 693 /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */ 694 resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR)? 695 ACPI_DECODE_16 : ACPI_DECODE_10; 696 resource->data.io.min_base_address = p->start; 697 resource->data.io.max_base_address = p->end; 698 resource->data.io.alignment = 0; /* Correct? */ 699 resource->data.io.range_length = p->end - p->start + 1; 700 } 701 702 static void pnpacpi_encode_fixed_io(struct acpi_resource *resource, 703 struct resource *p) 704 { 705 resource->id = ACPI_RSTYPE_FIXED_IO; 706 resource->length = sizeof(struct acpi_resource); 707 resource->data.fixed_io.base_address = p->start; 708 resource->data.fixed_io.range_length = p->end - p->start + 1; 709 } 710 711 static void pnpacpi_encode_mem24(struct acpi_resource *resource, 712 struct resource *p) 713 { 714 resource->id = ACPI_RSTYPE_MEM24; 715 resource->length = sizeof(struct acpi_resource); 716 /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */ 717 resource->data.memory24.read_write_attribute = 718 (p->flags & IORESOURCE_MEM_WRITEABLE) ? 719 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; 720 resource->data.memory24.min_base_address = p->start; 721 resource->data.memory24.max_base_address = p->end; 722 resource->data.memory24.alignment = 0; 723 resource->data.memory24.range_length = p->end - p->start + 1; 724 } 725 726 static void pnpacpi_encode_mem32(struct acpi_resource *resource, 727 struct resource *p) 728 { 729 resource->id = ACPI_RSTYPE_MEM32; 730 resource->length = sizeof(struct acpi_resource); 731 resource->data.memory32.read_write_attribute = 732 (p->flags & IORESOURCE_MEM_WRITEABLE) ? 733 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; 734 resource->data.memory32.min_base_address = p->start; 735 resource->data.memory32.max_base_address = p->end; 736 resource->data.memory32.alignment = 0; 737 resource->data.memory32.range_length = p->end - p->start + 1; 738 } 739 740 static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource, 741 struct resource *p) 742 { 743 resource->id = ACPI_RSTYPE_FIXED_MEM32; 744 resource->length = sizeof(struct acpi_resource); 745 resource->data.fixed_memory32.read_write_attribute = 746 (p->flags & IORESOURCE_MEM_WRITEABLE) ? 747 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; 748 resource->data.fixed_memory32.range_base_address = p->start; 749 resource->data.fixed_memory32.range_length = p->end - p->start + 1; 750 } 751 752 int pnpacpi_encode_resources(struct pnp_resource_table *res_table, 753 struct acpi_buffer *buffer) 754 { 755 int i = 0; 756 /* pnpacpi_build_resource_template allocates extra mem */ 757 int res_cnt = (buffer->length - 1)/sizeof(struct acpi_resource) - 1; 758 struct acpi_resource *resource = (struct acpi_resource*)buffer->pointer; 759 int port = 0, irq = 0, dma = 0, mem = 0; 760 761 pnp_dbg("res cnt %d", res_cnt); 762 while (i < res_cnt) { 763 switch(resource->id) { 764 case ACPI_RSTYPE_IRQ: 765 pnp_dbg("Encode irq"); 766 pnpacpi_encode_irq(resource, 767 &res_table->irq_resource[irq]); 768 irq++; 769 break; 770 771 case ACPI_RSTYPE_EXT_IRQ: 772 pnp_dbg("Encode ext irq"); 773 pnpacpi_encode_ext_irq(resource, 774 &res_table->irq_resource[irq]); 775 irq++; 776 break; 777 case ACPI_RSTYPE_DMA: 778 pnp_dbg("Encode dma"); 779 pnpacpi_encode_dma(resource, 780 &res_table->dma_resource[dma]); 781 dma ++; 782 break; 783 case ACPI_RSTYPE_IO: 784 pnp_dbg("Encode io"); 785 pnpacpi_encode_io(resource, 786 &res_table->port_resource[port]); 787 port ++; 788 break; 789 case ACPI_RSTYPE_FIXED_IO: 790 pnp_dbg("Encode fixed io"); 791 pnpacpi_encode_fixed_io(resource, 792 &res_table->port_resource[port]); 793 port ++; 794 break; 795 case ACPI_RSTYPE_MEM24: 796 pnp_dbg("Encode mem24"); 797 pnpacpi_encode_mem24(resource, 798 &res_table->mem_resource[mem]); 799 mem ++; 800 break; 801 case ACPI_RSTYPE_MEM32: 802 pnp_dbg("Encode mem32"); 803 pnpacpi_encode_mem32(resource, 804 &res_table->mem_resource[mem]); 805 mem ++; 806 break; 807 case ACPI_RSTYPE_FIXED_MEM32: 808 pnp_dbg("Encode fixed mem32"); 809 pnpacpi_encode_fixed_mem32(resource, 810 &res_table->mem_resource[mem]); 811 mem ++; 812 break; 813 default: /* other type */ 814 pnp_warn("unknown resource type %d", resource->id); 815 return -EINVAL; 816 } 817 resource ++; 818 i ++; 819 } 820 return 0; 821 } 822