linux/drivers/pnp/pnpacpi/rsparser.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * pnpacpi -- PnP ACPI driver
   4 *
   5 * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
   6 * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com>
   7 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
   8 *      Bjorn Helgaas <bjorn.helgaas@hp.com>
   9 */
  10#include <linux/kernel.h>
  11#include <linux/acpi.h>
  12#include <linux/pci.h>
  13#include <linux/pnp.h>
  14#include <linux/slab.h>
  15#include "../base.h"
  16#include "pnpacpi.h"
  17
  18static void decode_irq_flags(struct pnp_dev *dev, int flags, u8 *triggering,
  19                             u8 *polarity, u8 *shareable)
  20{
  21        switch (flags & (IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_HIGHLEVEL |
  22                         IORESOURCE_IRQ_LOWEDGE  | IORESOURCE_IRQ_HIGHEDGE)) {
  23        case IORESOURCE_IRQ_LOWLEVEL:
  24                *triggering = ACPI_LEVEL_SENSITIVE;
  25                *polarity = ACPI_ACTIVE_LOW;
  26                break;
  27        case IORESOURCE_IRQ_HIGHLEVEL:
  28                *triggering = ACPI_LEVEL_SENSITIVE;
  29                *polarity = ACPI_ACTIVE_HIGH;
  30                break;
  31        case IORESOURCE_IRQ_LOWEDGE:
  32                *triggering = ACPI_EDGE_SENSITIVE;
  33                *polarity = ACPI_ACTIVE_LOW;
  34                break;
  35        case IORESOURCE_IRQ_HIGHEDGE:
  36                *triggering = ACPI_EDGE_SENSITIVE;
  37                *polarity = ACPI_ACTIVE_HIGH;
  38                break;
  39        default:
  40                dev_err(&dev->dev, "can't encode invalid IRQ mode %#x\n",
  41                        flags);
  42                *triggering = ACPI_EDGE_SENSITIVE;
  43                *polarity = ACPI_ACTIVE_HIGH;
  44                break;
  45        }
  46
  47        if (flags & IORESOURCE_IRQ_SHAREABLE)
  48                *shareable = ACPI_SHARED;
  49        else
  50                *shareable = ACPI_EXCLUSIVE;
  51}
  52
  53static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
  54                     int transfer)
  55{
  56        int flags = 0;
  57
  58        if (bus_master)
  59                flags |= IORESOURCE_DMA_MASTER;
  60        switch (type) {
  61        case ACPI_COMPATIBILITY:
  62                flags |= IORESOURCE_DMA_COMPATIBLE;
  63                break;
  64        case ACPI_TYPE_A:
  65                flags |= IORESOURCE_DMA_TYPEA;
  66                break;
  67        case ACPI_TYPE_B:
  68                flags |= IORESOURCE_DMA_TYPEB;
  69                break;
  70        case ACPI_TYPE_F:
  71                flags |= IORESOURCE_DMA_TYPEF;
  72                break;
  73        default:
  74                /* Set a default value ? */
  75                flags |= IORESOURCE_DMA_COMPATIBLE;
  76                dev_err(&dev->dev, "invalid DMA type %d\n", type);
  77        }
  78        switch (transfer) {
  79        case ACPI_TRANSFER_8:
  80                flags |= IORESOURCE_DMA_8BIT;
  81                break;
  82        case ACPI_TRANSFER_8_16:
  83                flags |= IORESOURCE_DMA_8AND16BIT;
  84                break;
  85        case ACPI_TRANSFER_16:
  86                flags |= IORESOURCE_DMA_16BIT;
  87                break;
  88        default:
  89                /* Set a default value ? */
  90                flags |= IORESOURCE_DMA_8AND16BIT;
  91                dev_err(&dev->dev, "invalid DMA transfer type %d\n", transfer);
  92        }
  93
  94        return flags;
  95}
  96
  97/*
  98 * Allocated Resources
  99 */
 100
 101static void pnpacpi_add_irqresource(struct pnp_dev *dev, struct resource *r)
 102{
 103        if (!(r->flags & IORESOURCE_DISABLED))
 104                pcibios_penalize_isa_irq(r->start, 1);
 105
 106        pnp_add_resource(dev, r);
 107}
 108
 109/*
 110 * Device CSRs that do not appear in PCI config space should be described
 111 * via ACPI.  This would normally be done with Address Space Descriptors
 112 * marked as "consumer-only," but old versions of Windows and Linux ignore
 113 * the producer/consumer flag, so HP invented a vendor-defined resource to
 114 * describe the location and size of CSR space.
 115 */
 116static struct acpi_vendor_uuid hp_ccsr_uuid = {
 117        .subtype = 2,
 118        .data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a,
 119            0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad },
 120};
 121
 122static int vendor_resource_matches(struct pnp_dev *dev,
 123                                   struct acpi_resource_vendor_typed *vendor,
 124                                   struct acpi_vendor_uuid *match,
 125                                   int expected_len)
 126{
 127        int uuid_len = sizeof(vendor->uuid);
 128        u8 uuid_subtype = vendor->uuid_subtype;
 129        u8 *uuid = vendor->uuid;
 130        int actual_len;
 131
 132        /* byte_length includes uuid_subtype and uuid */
 133        actual_len = vendor->byte_length - uuid_len - 1;
 134
 135        if (uuid_subtype == match->subtype &&
 136            uuid_len == sizeof(match->data) &&
 137            memcmp(uuid, match->data, uuid_len) == 0) {
 138                if (expected_len && expected_len != actual_len) {
 139                        dev_err(&dev->dev,
 140                                "wrong vendor descriptor size; expected %d, found %d bytes\n",
 141                                expected_len, actual_len);
 142                        return 0;
 143                }
 144
 145                return 1;
 146        }
 147
 148        return 0;
 149}
 150
 151static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
 152                                    struct acpi_resource_vendor_typed *vendor)
 153{
 154        if (vendor_resource_matches(dev, vendor, &hp_ccsr_uuid, 16)) {
 155                u64 start, length;
 156
 157                memcpy(&start, vendor->byte_data, sizeof(start));
 158                memcpy(&length, vendor->byte_data + 8, sizeof(length));
 159
 160                pnp_add_mem_resource(dev, start, start + length - 1, 0);
 161        }
 162}
 163
 164static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
 165                                              void *data)
 166{
 167        struct pnp_dev *dev = data;
 168        struct acpi_resource_dma *dma;
 169        struct acpi_resource_vendor_typed *vendor_typed;
 170        struct acpi_resource_gpio *gpio;
 171        struct resource_win win = {{0}, 0};
 172        struct resource *r = &win.res;
 173        int i, flags;
 174
 175        if (acpi_dev_resource_address_space(res, &win)
 176            || acpi_dev_resource_ext_address_space(res, &win)) {
 177                pnp_add_resource(dev, &win.res);
 178                return AE_OK;
 179        }
 180
 181        r->flags = 0;
 182        if (acpi_dev_resource_interrupt(res, 0, r)) {
 183                pnpacpi_add_irqresource(dev, r);
 184                for (i = 1; acpi_dev_resource_interrupt(res, i, r); i++)
 185                        pnpacpi_add_irqresource(dev, r);
 186
 187                if (i > 1) {
 188                        /*
 189                         * The IRQ encoder puts a single interrupt in each
 190                         * descriptor, so if a _CRS descriptor has more than
 191                         * one interrupt, we won't be able to re-encode it.
 192                         */
 193                        if (pnp_can_write(dev)) {
 194                                dev_warn(&dev->dev,
 195                                         "multiple interrupts in _CRS descriptor; configuration can't be changed\n");
 196                                dev->capabilities &= ~PNP_WRITE;
 197                        }
 198                }
 199                return AE_OK;
 200        } else if (acpi_gpio_get_irq_resource(res, &gpio)) {
 201                /*
 202                 * If the resource is GpioInt() type then extract the IRQ
 203                 * from GPIO resource and fill it into IRQ resource type.
 204                 */
 205                i = acpi_dev_gpio_irq_get(dev->data, 0);
 206                if (i >= 0) {
 207                        flags = acpi_dev_irq_flags(gpio->triggering,
 208                                                   gpio->polarity,
 209                                                   gpio->shareable);
 210                } else {
 211                        flags = IORESOURCE_DISABLED;
 212                }
 213                pnp_add_irq_resource(dev, i, flags);
 214                return AE_OK;
 215        } else if (r->flags & IORESOURCE_DISABLED) {
 216                pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
 217                return AE_OK;
 218        }
 219
 220        switch (res->type) {
 221        case ACPI_RESOURCE_TYPE_MEMORY24:
 222        case ACPI_RESOURCE_TYPE_MEMORY32:
 223        case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
 224                if (acpi_dev_resource_memory(res, r))
 225                        pnp_add_resource(dev, r);
 226                break;
 227        case ACPI_RESOURCE_TYPE_IO:
 228        case ACPI_RESOURCE_TYPE_FIXED_IO:
 229                if (acpi_dev_resource_io(res, r))
 230                        pnp_add_resource(dev, r);
 231                break;
 232        case ACPI_RESOURCE_TYPE_DMA:
 233                dma = &res->data.dma;
 234                if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
 235                        flags = dma_flags(dev, dma->type, dma->bus_master,
 236                                          dma->transfer);
 237                else
 238                        flags = IORESOURCE_DISABLED;
 239                pnp_add_dma_resource(dev, dma->channels[0], flags);
 240                break;
 241
 242        case ACPI_RESOURCE_TYPE_START_DEPENDENT:
 243        case ACPI_RESOURCE_TYPE_END_DEPENDENT:
 244                break;
 245
 246        case ACPI_RESOURCE_TYPE_VENDOR:
 247                vendor_typed = &res->data.vendor_typed;
 248                pnpacpi_parse_allocated_vendor(dev, vendor_typed);
 249                break;
 250
 251        case ACPI_RESOURCE_TYPE_END_TAG:
 252                break;
 253
 254        case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
 255                break;
 256
 257        case ACPI_RESOURCE_TYPE_SERIAL_BUS:
 258                /* serial bus connections (I2C/SPI/UART) are not pnp */
 259                break;
 260
 261        default:
 262                dev_warn(&dev->dev, "unknown resource type %d in _CRS\n",
 263                         res->type);
 264                return AE_ERROR;
 265        }
 266
 267        return AE_OK;
 268}
 269
 270int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
 271{
 272        struct acpi_device *acpi_dev = dev->data;
 273        acpi_handle handle = acpi_dev->handle;
 274        acpi_status status;
 275
 276        pnp_dbg(&dev->dev, "parse allocated resources\n");
 277
 278        pnp_init_resources(dev);
 279
 280        status = acpi_walk_resources(handle, METHOD_NAME__CRS,
 281                                     pnpacpi_allocated_resource, dev);
 282
 283        if (ACPI_FAILURE(status)) {
 284                if (status != AE_NOT_FOUND)
 285                        dev_err(&dev->dev, "can't evaluate _CRS: %d", status);
 286                return -EPERM;
 287        }
 288        return 0;
 289}
 290
 291static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
 292                                            unsigned int option_flags,
 293                                            struct acpi_resource_dma *p)
 294{
 295        int i;
 296        unsigned char map = 0, flags;
 297
 298        for (i = 0; i < p->channel_count; i++)
 299                map |= 1 << p->channels[i];
 300
 301        flags = dma_flags(dev, p->type, p->bus_master, p->transfer);
 302        pnp_register_dma_resource(dev, option_flags, map, flags);
 303}
 304
 305static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
 306                                            unsigned int option_flags,
 307                                            struct acpi_resource_irq *p)
 308{
 309        int i;
 310        pnp_irq_mask_t map;
 311        unsigned char flags;
 312
 313        bitmap_zero(map.bits, PNP_IRQ_NR);
 314        for (i = 0; i < p->interrupt_count; i++)
 315                if (p->interrupts[i])
 316                        __set_bit(p->interrupts[i], map.bits);
 317
 318        flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->shareable);
 319        pnp_register_irq_resource(dev, option_flags, &map, flags);
 320}
 321
 322static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
 323                                        unsigned int option_flags,
 324                                        struct acpi_resource_extended_irq *p)
 325{
 326        int i;
 327        pnp_irq_mask_t map;
 328        unsigned char flags;
 329
 330        bitmap_zero(map.bits, PNP_IRQ_NR);
 331        for (i = 0; i < p->interrupt_count; i++) {
 332                if (p->interrupts[i]) {
 333                        if (p->interrupts[i] < PNP_IRQ_NR)
 334                                __set_bit(p->interrupts[i], map.bits);
 335                        else
 336                                dev_err(&dev->dev,
 337                                        "ignoring IRQ %d option (too large for %d entry bitmap)\n",
 338                                        p->interrupts[i], PNP_IRQ_NR);
 339                }
 340        }
 341
 342        flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->shareable);
 343        pnp_register_irq_resource(dev, option_flags, &map, flags);
 344}
 345
 346static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
 347                                             unsigned int option_flags,
 348                                             struct acpi_resource_io *io)
 349{
 350        unsigned char flags = 0;
 351
 352        if (io->io_decode == ACPI_DECODE_16)
 353                flags = IORESOURCE_IO_16BIT_ADDR;
 354        pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum,
 355                                   io->alignment, io->address_length, flags);
 356}
 357
 358static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
 359                                        unsigned int option_flags,
 360                                        struct acpi_resource_fixed_io *io)
 361{
 362        pnp_register_port_resource(dev, option_flags, io->address, io->address,
 363                                   0, io->address_length, IORESOURCE_IO_FIXED);
 364}
 365
 366static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
 367                                              unsigned int option_flags,
 368                                              struct acpi_resource_memory24 *p)
 369{
 370        unsigned char flags = 0;
 371
 372        if (p->write_protect == ACPI_READ_WRITE_MEMORY)
 373                flags = IORESOURCE_MEM_WRITEABLE;
 374        pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
 375                                  p->alignment, p->address_length, flags);
 376}
 377
 378static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
 379                                              unsigned int option_flags,
 380                                              struct acpi_resource_memory32 *p)
 381{
 382        unsigned char flags = 0;
 383
 384        if (p->write_protect == ACPI_READ_WRITE_MEMORY)
 385                flags = IORESOURCE_MEM_WRITEABLE;
 386        pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
 387                                  p->alignment, p->address_length, flags);
 388}
 389
 390static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
 391                                        unsigned int option_flags,
 392                                        struct acpi_resource_fixed_memory32 *p)
 393{
 394        unsigned char flags = 0;
 395
 396        if (p->write_protect == ACPI_READ_WRITE_MEMORY)
 397                flags = IORESOURCE_MEM_WRITEABLE;
 398        pnp_register_mem_resource(dev, option_flags, p->address, p->address,
 399                                  0, p->address_length, flags);
 400}
 401
 402static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
 403                                                unsigned int option_flags,
 404                                                struct acpi_resource *r)
 405{
 406        struct acpi_resource_address64 addr, *p = &addr;
 407        acpi_status status;
 408        unsigned char flags = 0;
 409
 410        status = acpi_resource_to_address64(r, p);
 411        if (ACPI_FAILURE(status)) {
 412                dev_warn(&dev->dev, "can't convert resource type %d\n",
 413                         r->type);
 414                return;
 415        }
 416
 417        if (p->resource_type == ACPI_MEMORY_RANGE) {
 418                if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
 419                        flags = IORESOURCE_MEM_WRITEABLE;
 420                pnp_register_mem_resource(dev, option_flags, p->address.minimum,
 421                                          p->address.minimum, 0, p->address.address_length,
 422                                          flags);
 423        } else if (p->resource_type == ACPI_IO_RANGE)
 424                pnp_register_port_resource(dev, option_flags, p->address.minimum,
 425                                           p->address.minimum, 0, p->address.address_length,
 426                                           IORESOURCE_IO_FIXED);
 427}
 428
 429static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
 430                                                    unsigned int option_flags,
 431                                                    struct acpi_resource *r)
 432{
 433        struct acpi_resource_extended_address64 *p = &r->data.ext_address64;
 434        unsigned char flags = 0;
 435
 436        if (p->resource_type == ACPI_MEMORY_RANGE) {
 437                if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
 438                        flags = IORESOURCE_MEM_WRITEABLE;
 439                pnp_register_mem_resource(dev, option_flags, p->address.minimum,
 440                                          p->address.minimum, 0, p->address.address_length,
 441                                          flags);
 442        } else if (p->resource_type == ACPI_IO_RANGE)
 443                pnp_register_port_resource(dev, option_flags, p->address.minimum,
 444                                           p->address.minimum, 0, p->address.address_length,
 445                                           IORESOURCE_IO_FIXED);
 446}
 447
 448struct acpipnp_parse_option_s {
 449        struct pnp_dev *dev;
 450        unsigned int option_flags;
 451};
 452
 453static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
 454                                                  void *data)
 455{
 456        int priority;
 457        struct acpipnp_parse_option_s *parse_data = data;
 458        struct pnp_dev *dev = parse_data->dev;
 459        unsigned int option_flags = parse_data->option_flags;
 460
 461        switch (res->type) {
 462        case ACPI_RESOURCE_TYPE_IRQ:
 463                pnpacpi_parse_irq_option(dev, option_flags, &res->data.irq);
 464                break;
 465
 466        case ACPI_RESOURCE_TYPE_DMA:
 467                pnpacpi_parse_dma_option(dev, option_flags, &res->data.dma);
 468                break;
 469
 470        case ACPI_RESOURCE_TYPE_START_DEPENDENT:
 471                switch (res->data.start_dpf.compatibility_priority) {
 472                case ACPI_GOOD_CONFIGURATION:
 473                        priority = PNP_RES_PRIORITY_PREFERRED;
 474                        break;
 475
 476                case ACPI_ACCEPTABLE_CONFIGURATION:
 477                        priority = PNP_RES_PRIORITY_ACCEPTABLE;
 478                        break;
 479
 480                case ACPI_SUB_OPTIMAL_CONFIGURATION:
 481                        priority = PNP_RES_PRIORITY_FUNCTIONAL;
 482                        break;
 483                default:
 484                        priority = PNP_RES_PRIORITY_INVALID;
 485                        break;
 486                }
 487                parse_data->option_flags = pnp_new_dependent_set(dev, priority);
 488                break;
 489
 490        case ACPI_RESOURCE_TYPE_END_DEPENDENT:
 491                parse_data->option_flags = 0;
 492                break;
 493
 494        case ACPI_RESOURCE_TYPE_IO:
 495                pnpacpi_parse_port_option(dev, option_flags, &res->data.io);
 496                break;
 497
 498        case ACPI_RESOURCE_TYPE_FIXED_IO:
 499                pnpacpi_parse_fixed_port_option(dev, option_flags,
 500                                                &res->data.fixed_io);
 501                break;
 502
 503        case ACPI_RESOURCE_TYPE_VENDOR:
 504        case ACPI_RESOURCE_TYPE_END_TAG:
 505                break;
 506
 507        case ACPI_RESOURCE_TYPE_MEMORY24:
 508                pnpacpi_parse_mem24_option(dev, option_flags,
 509                                           &res->data.memory24);
 510                break;
 511
 512        case ACPI_RESOURCE_TYPE_MEMORY32:
 513                pnpacpi_parse_mem32_option(dev, option_flags,
 514                                           &res->data.memory32);
 515                break;
 516
 517        case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
 518                pnpacpi_parse_fixed_mem32_option(dev, option_flags,
 519                                                 &res->data.fixed_memory32);
 520                break;
 521
 522        case ACPI_RESOURCE_TYPE_ADDRESS16:
 523        case ACPI_RESOURCE_TYPE_ADDRESS32:
 524        case ACPI_RESOURCE_TYPE_ADDRESS64:
 525                pnpacpi_parse_address_option(dev, option_flags, res);
 526                break;
 527
 528        case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
 529                pnpacpi_parse_ext_address_option(dev, option_flags, res);
 530                break;
 531
 532        case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 533                pnpacpi_parse_ext_irq_option(dev, option_flags,
 534                                             &res->data.extended_irq);
 535                break;
 536
 537        case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
 538                break;
 539
 540        default:
 541                dev_warn(&dev->dev, "unknown resource type %d in _PRS\n",
 542                         res->type);
 543                return AE_ERROR;
 544        }
 545
 546        return AE_OK;
 547}
 548
 549int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
 550{
 551        struct acpi_device *acpi_dev = dev->data;
 552        acpi_handle handle = acpi_dev->handle;
 553        acpi_status status;
 554        struct acpipnp_parse_option_s parse_data;
 555
 556        pnp_dbg(&dev->dev, "parse resource options\n");
 557
 558        parse_data.dev = dev;
 559        parse_data.option_flags = 0;
 560
 561        status = acpi_walk_resources(handle, METHOD_NAME__PRS,
 562                                     pnpacpi_option_resource, &parse_data);
 563
 564        if (ACPI_FAILURE(status)) {
 565                if (status != AE_NOT_FOUND)
 566                        dev_err(&dev->dev, "can't evaluate _PRS: %d", status);
 567                return -EPERM;
 568        }
 569        return 0;
 570}
 571
 572static int pnpacpi_supported_resource(struct acpi_resource *res)
 573{
 574        switch (res->type) {
 575        case ACPI_RESOURCE_TYPE_IRQ:
 576        case ACPI_RESOURCE_TYPE_DMA:
 577        case ACPI_RESOURCE_TYPE_IO:
 578        case ACPI_RESOURCE_TYPE_FIXED_IO:
 579        case ACPI_RESOURCE_TYPE_MEMORY24:
 580        case ACPI_RESOURCE_TYPE_MEMORY32:
 581        case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
 582        case ACPI_RESOURCE_TYPE_ADDRESS16:
 583        case ACPI_RESOURCE_TYPE_ADDRESS32:
 584        case ACPI_RESOURCE_TYPE_ADDRESS64:
 585        case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
 586        case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 587                return 1;
 588        }
 589        return 0;
 590}
 591
 592/*
 593 * Set resource
 594 */
 595static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
 596                                           void *data)
 597{
 598        int *res_cnt = data;
 599
 600        if (pnpacpi_supported_resource(res))
 601                (*res_cnt)++;
 602        return AE_OK;
 603}
 604
 605static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
 606{
 607        struct acpi_resource **resource = data;
 608
 609        if (pnpacpi_supported_resource(res)) {
 610                (*resource)->type = res->type;
 611                (*resource)->length = sizeof(struct acpi_resource);
 612                if (res->type == ACPI_RESOURCE_TYPE_IRQ)
 613                        (*resource)->data.irq.descriptor_length =
 614                                        res->data.irq.descriptor_length;
 615                (*resource)++;
 616        }
 617
 618        return AE_OK;
 619}
 620
 621int pnpacpi_build_resource_template(struct pnp_dev *dev,
 622                                    struct acpi_buffer *buffer)
 623{
 624        struct acpi_device *acpi_dev = dev->data;
 625        acpi_handle handle = acpi_dev->handle;
 626        struct acpi_resource *resource;
 627        int res_cnt = 0;
 628        acpi_status status;
 629
 630        status = acpi_walk_resources(handle, METHOD_NAME__CRS,
 631                                     pnpacpi_count_resources, &res_cnt);
 632        if (ACPI_FAILURE(status)) {
 633                dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);
 634                return -EINVAL;
 635        }
 636        if (!res_cnt)
 637                return -EINVAL;
 638        buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;
 639        buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL);
 640        if (!buffer->pointer)
 641                return -ENOMEM;
 642
 643        resource = (struct acpi_resource *)buffer->pointer;
 644        status = acpi_walk_resources(handle, METHOD_NAME__CRS,
 645                                     pnpacpi_type_resources, &resource);
 646        if (ACPI_FAILURE(status)) {
 647                kfree(buffer->pointer);
 648                dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);
 649                return -EINVAL;
 650        }
 651        /* resource will pointer the end resource now */
 652        resource->type = ACPI_RESOURCE_TYPE_END_TAG;
 653        resource->length = sizeof(struct acpi_resource);
 654
 655        return 0;
 656}
 657
 658static void pnpacpi_encode_irq(struct pnp_dev *dev,
 659                               struct acpi_resource *resource,
 660                               struct resource *p)
 661{
 662        struct acpi_resource_irq *irq = &resource->data.irq;
 663        u8 triggering, polarity, shareable;
 664
 665        if (!pnp_resource_enabled(p)) {
 666                irq->interrupt_count = 0;
 667                pnp_dbg(&dev->dev, "  encode irq (%s)\n",
 668                        p ? "disabled" : "missing");
 669                return;
 670        }
 671
 672        decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
 673        irq->triggering = triggering;
 674        irq->polarity = polarity;
 675        irq->shareable = shareable;
 676        irq->interrupt_count = 1;
 677        irq->interrupts[0] = p->start;
 678
 679        pnp_dbg(&dev->dev, "  encode irq %d %s %s %s (%d-byte descriptor)\n",
 680                (int) p->start,
 681                triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
 682                polarity == ACPI_ACTIVE_LOW ? "low" : "high",
 683                irq->shareable == ACPI_SHARED ? "shared" : "exclusive",
 684                irq->descriptor_length);
 685}
 686
 687static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
 688                                   struct acpi_resource *resource,
 689                                   struct resource *p)
 690{
 691        struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
 692        u8 triggering, polarity, shareable;
 693
 694        if (!pnp_resource_enabled(p)) {
 695                extended_irq->interrupt_count = 0;
 696                pnp_dbg(&dev->dev, "  encode extended irq (%s)\n",
 697                        p ? "disabled" : "missing");
 698                return;
 699        }
 700
 701        decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
 702        extended_irq->producer_consumer = ACPI_CONSUMER;
 703        extended_irq->triggering = triggering;
 704        extended_irq->polarity = polarity;
 705        extended_irq->shareable = shareable;
 706        extended_irq->interrupt_count = 1;
 707        extended_irq->interrupts[0] = p->start;
 708
 709        pnp_dbg(&dev->dev, "  encode irq %d %s %s %s\n", (int) p->start,
 710                triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
 711                polarity == ACPI_ACTIVE_LOW ? "low" : "high",
 712                extended_irq->shareable == ACPI_SHARED ? "shared" : "exclusive");
 713}
 714
 715static void pnpacpi_encode_dma(struct pnp_dev *dev,
 716                               struct acpi_resource *resource,
 717                               struct resource *p)
 718{
 719        struct acpi_resource_dma *dma = &resource->data.dma;
 720
 721        if (!pnp_resource_enabled(p)) {
 722                dma->channel_count = 0;
 723                pnp_dbg(&dev->dev, "  encode dma (%s)\n",
 724                        p ? "disabled" : "missing");
 725                return;
 726        }
 727
 728        /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
 729        switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
 730        case IORESOURCE_DMA_TYPEA:
 731                dma->type = ACPI_TYPE_A;
 732                break;
 733        case IORESOURCE_DMA_TYPEB:
 734                dma->type = ACPI_TYPE_B;
 735                break;
 736        case IORESOURCE_DMA_TYPEF:
 737                dma->type = ACPI_TYPE_F;
 738                break;
 739        default:
 740                dma->type = ACPI_COMPATIBILITY;
 741        }
 742
 743        switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {
 744        case IORESOURCE_DMA_8BIT:
 745                dma->transfer = ACPI_TRANSFER_8;
 746                break;
 747        case IORESOURCE_DMA_8AND16BIT:
 748                dma->transfer = ACPI_TRANSFER_8_16;
 749                break;
 750        default:
 751                dma->transfer = ACPI_TRANSFER_16;
 752        }
 753
 754        dma->bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
 755        dma->channel_count = 1;
 756        dma->channels[0] = p->start;
 757
 758        pnp_dbg(&dev->dev, "  encode dma %d "
 759                "type %#x transfer %#x master %d\n",
 760                (int) p->start, dma->type, dma->transfer, dma->bus_master);
 761}
 762
 763static void pnpacpi_encode_io(struct pnp_dev *dev,
 764                              struct acpi_resource *resource,
 765                              struct resource *p)
 766{
 767        struct acpi_resource_io *io = &resource->data.io;
 768
 769        if (pnp_resource_enabled(p)) {
 770                /* Note: pnp_assign_port copies pnp_port->flags into p->flags */
 771                io->io_decode = (p->flags & IORESOURCE_IO_16BIT_ADDR) ?
 772                    ACPI_DECODE_16 : ACPI_DECODE_10;
 773                io->minimum = p->start;
 774                io->maximum = p->end;
 775                io->alignment = 0;      /* Correct? */
 776                io->address_length = resource_size(p);
 777        } else {
 778                io->minimum = 0;
 779                io->address_length = 0;
 780        }
 781
 782        pnp_dbg(&dev->dev, "  encode io %#x-%#x decode %#x\n", io->minimum,
 783                io->minimum + io->address_length - 1, io->io_decode);
 784}
 785
 786static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
 787                                    struct acpi_resource *resource,
 788                                    struct resource *p)
 789{
 790        struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io;
 791
 792        if (pnp_resource_enabled(p)) {
 793                fixed_io->address = p->start;
 794                fixed_io->address_length = resource_size(p);
 795        } else {
 796                fixed_io->address = 0;
 797                fixed_io->address_length = 0;
 798        }
 799
 800        pnp_dbg(&dev->dev, "  encode fixed_io %#x-%#x\n", fixed_io->address,
 801                fixed_io->address + fixed_io->address_length - 1);
 802}
 803
 804static void pnpacpi_encode_mem24(struct pnp_dev *dev,
 805                                 struct acpi_resource *resource,
 806                                 struct resource *p)
 807{
 808        struct acpi_resource_memory24 *memory24 = &resource->data.memory24;
 809
 810        if (pnp_resource_enabled(p)) {
 811                /* Note: pnp_assign_mem copies pnp_mem->flags into p->flags */
 812                memory24->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?
 813                    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
 814                memory24->minimum = p->start;
 815                memory24->maximum = p->end;
 816                memory24->alignment = 0;
 817                memory24->address_length = resource_size(p);
 818        } else {
 819                memory24->minimum = 0;
 820                memory24->address_length = 0;
 821        }
 822
 823        pnp_dbg(&dev->dev, "  encode mem24 %#x-%#x write_protect %#x\n",
 824                memory24->minimum,
 825                memory24->minimum + memory24->address_length - 1,
 826                memory24->write_protect);
 827}
 828
 829static void pnpacpi_encode_mem32(struct pnp_dev *dev,
 830                                 struct acpi_resource *resource,
 831                                 struct resource *p)
 832{
 833        struct acpi_resource_memory32 *memory32 = &resource->data.memory32;
 834
 835        if (pnp_resource_enabled(p)) {
 836                memory32->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?
 837                    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
 838                memory32->minimum = p->start;
 839                memory32->maximum = p->end;
 840                memory32->alignment = 0;
 841                memory32->address_length = resource_size(p);
 842        } else {
 843                memory32->minimum = 0;
 844                memory32->alignment = 0;
 845        }
 846
 847        pnp_dbg(&dev->dev, "  encode mem32 %#x-%#x write_protect %#x\n",
 848                memory32->minimum,
 849                memory32->minimum + memory32->address_length - 1,
 850                memory32->write_protect);
 851}
 852
 853static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
 854                                       struct acpi_resource *resource,
 855                                       struct resource *p)
 856{
 857        struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32;
 858
 859        if (pnp_resource_enabled(p)) {
 860                fixed_memory32->write_protect =
 861                    p->flags & IORESOURCE_MEM_WRITEABLE ?
 862                    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
 863                fixed_memory32->address = p->start;
 864                fixed_memory32->address_length = resource_size(p);
 865        } else {
 866                fixed_memory32->address = 0;
 867                fixed_memory32->address_length = 0;
 868        }
 869
 870        pnp_dbg(&dev->dev, "  encode fixed_mem32 %#x-%#x write_protect %#x\n",
 871                fixed_memory32->address,
 872                fixed_memory32->address + fixed_memory32->address_length - 1,
 873                fixed_memory32->write_protect);
 874}
 875
 876int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer)
 877{
 878        int i = 0;
 879        /* pnpacpi_build_resource_template allocates extra mem */
 880        int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1;
 881        struct acpi_resource *resource = buffer->pointer;
 882        unsigned int port = 0, irq = 0, dma = 0, mem = 0;
 883
 884        pnp_dbg(&dev->dev, "encode %d resources\n", res_cnt);
 885        while (i < res_cnt) {
 886                switch (resource->type) {
 887                case ACPI_RESOURCE_TYPE_IRQ:
 888                        pnpacpi_encode_irq(dev, resource,
 889                               pnp_get_resource(dev, IORESOURCE_IRQ, irq));
 890                        irq++;
 891                        break;
 892
 893                case ACPI_RESOURCE_TYPE_DMA:
 894                        pnpacpi_encode_dma(dev, resource,
 895                                pnp_get_resource(dev, IORESOURCE_DMA, dma));
 896                        dma++;
 897                        break;
 898                case ACPI_RESOURCE_TYPE_IO:
 899                        pnpacpi_encode_io(dev, resource,
 900                                pnp_get_resource(dev, IORESOURCE_IO, port));
 901                        port++;
 902                        break;
 903                case ACPI_RESOURCE_TYPE_FIXED_IO:
 904                        pnpacpi_encode_fixed_io(dev, resource,
 905                                pnp_get_resource(dev, IORESOURCE_IO, port));
 906                        port++;
 907                        break;
 908                case ACPI_RESOURCE_TYPE_MEMORY24:
 909                        pnpacpi_encode_mem24(dev, resource,
 910                                pnp_get_resource(dev, IORESOURCE_MEM, mem));
 911                        mem++;
 912                        break;
 913                case ACPI_RESOURCE_TYPE_MEMORY32:
 914                        pnpacpi_encode_mem32(dev, resource,
 915                                pnp_get_resource(dev, IORESOURCE_MEM, mem));
 916                        mem++;
 917                        break;
 918                case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
 919                        pnpacpi_encode_fixed_mem32(dev, resource,
 920                                pnp_get_resource(dev, IORESOURCE_MEM, mem));
 921                        mem++;
 922                        break;
 923                case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 924                        pnpacpi_encode_ext_irq(dev, resource,
 925                                pnp_get_resource(dev, IORESOURCE_IRQ, irq));
 926                        irq++;
 927                        break;
 928                case ACPI_RESOURCE_TYPE_START_DEPENDENT:
 929                case ACPI_RESOURCE_TYPE_END_DEPENDENT:
 930                case ACPI_RESOURCE_TYPE_VENDOR:
 931                case ACPI_RESOURCE_TYPE_END_TAG:
 932                case ACPI_RESOURCE_TYPE_ADDRESS16:
 933                case ACPI_RESOURCE_TYPE_ADDRESS32:
 934                case ACPI_RESOURCE_TYPE_ADDRESS64:
 935                case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
 936                case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
 937                default:        /* other type */
 938                        dev_warn(&dev->dev,
 939                                 "can't encode unknown resource type %d\n",
 940                                 resource->type);
 941                        return -EINVAL;
 942                }
 943                resource++;
 944                i++;
 945        }
 946        return 0;
 947}
 948