linux-old/drivers/hotplug/acpiphp_glue.c
<<
>>
Prefs
   1/*
   2 * ACPI PCI HotPlug glue functions to ACPI CA subsystem
   3 *
   4 * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
   5 * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
   6 * Copyright (C) 2002,2003 NEC Corporation
   7 *
   8 * All rights reserved.
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License as published by
  12 * the Free Software Foundation; either version 2 of the License, or (at
  13 * your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful, but
  16 * WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  18 * NON INFRINGEMENT.  See the GNU General Public License for more
  19 * details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24 *
  25 * Send feedback to <t-kochi@bq.jp.nec.com>
  26 *
  27 */
  28
  29#include <linux/init.h>
  30#include <linux/module.h>
  31
  32#include <linux/kernel.h>
  33#include <linux/pci.h>
  34#include <linux/smp_lock.h>
  35#include <asm/semaphore.h>
  36
  37#include "pci_hotplug.h"
  38#include "acpiphp.h"
  39
  40static LIST_HEAD(bridge_list);
  41
  42#define MY_NAME "acpiphp_glue"
  43
  44static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
  45static void handle_hotplug_event_func (acpi_handle, u32, void *);
  46
  47/*
  48 * initialization & terminatation routines
  49 */
  50
  51/**
  52 * is_ejectable - determine if a slot is ejectable
  53 * @handle: handle to acpi namespace
  54 *
  55 * Ejectable slot should satisfy at least these conditions:
  56 *
  57 *  1. has _ADR method
  58 *  2. has _EJ0 method
  59 *
  60 * optionally
  61 *
  62 *  1. has _STA method
  63 *  2. has _PS0 method
  64 *  3. has _PS3 method
  65 *  4. ..
  66 *
  67 */
  68static int is_ejectable (acpi_handle handle)
  69{
  70        acpi_status status;
  71        acpi_handle tmp;
  72
  73        status = acpi_get_handle(handle, "_ADR", &tmp);
  74        if (ACPI_FAILURE(status)) {
  75                return 0;
  76        }
  77
  78        status = acpi_get_handle(handle, "_EJ0", &tmp);
  79        if (ACPI_FAILURE(status)) {
  80                return 0;
  81        }
  82
  83        return 1;
  84}
  85
  86
  87/* callback routine to check the existence of ejectable slots */
  88static acpi_status
  89is_ejectable_slot (acpi_handle handle, u32 lvl, void *context, void **rv)
  90{
  91        int *count = (int *)context;
  92
  93        if (is_ejectable(handle)) {
  94                (*count)++;
  95                /* only one ejectable slot is enough */
  96                return AE_CTRL_TERMINATE;
  97        } else {
  98                return AE_OK;
  99        }
 100}
 101
 102
 103/* callback routine to register each ACPI PCI slot object */
 104static acpi_status
 105register_slot (acpi_handle handle, u32 lvl, void *context, void **rv)
 106{
 107        struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context;
 108        struct acpiphp_slot *slot;
 109        struct acpiphp_func *newfunc;
 110        acpi_handle tmp;
 111        acpi_status status = AE_OK;
 112        unsigned long adr, sun;
 113        int device, function;
 114        static int num_slots = 0;       /* XXX if we support I/O node hotplug... */
 115
 116        status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
 117
 118        if (ACPI_FAILURE(status))
 119                return AE_OK;
 120
 121        status = acpi_get_handle(handle, "_EJ0", &tmp);
 122
 123        if (ACPI_FAILURE(status))
 124                return AE_OK;
 125
 126        device = (adr >> 16) & 0xffff;
 127        function = adr & 0xffff;
 128
 129        newfunc = kmalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
 130        if (!newfunc)
 131                return AE_NO_MEMORY;
 132        memset(newfunc, 0, sizeof(struct acpiphp_func));
 133
 134        INIT_LIST_HEAD(&newfunc->sibling);
 135        newfunc->handle = handle;
 136        newfunc->function = function;
 137        newfunc->flags = FUNC_HAS_EJ0;
 138
 139        if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp)))
 140                newfunc->flags |= FUNC_HAS_STA;
 141
 142        if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS0", &tmp)))
 143                newfunc->flags |= FUNC_HAS_PS0;
 144
 145        if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp)))
 146                newfunc->flags |= FUNC_HAS_PS3;
 147
 148        status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun);
 149        if (ACPI_FAILURE(status))
 150                sun = -1;
 151
 152        /* search for objects that share the same slot */
 153        for (slot = bridge->slots; slot; slot = slot->next)
 154                if (slot->device == device) {
 155                        if (slot->sun != sun)
 156                                warn("sibling found, but _SUN doesn't match!\n");
 157                        break;
 158                }
 159
 160        if (!slot) {
 161                slot = kmalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
 162                if (!slot) {
 163                        kfree(newfunc);
 164                        return AE_NO_MEMORY;
 165                }
 166
 167                memset(slot, 0, sizeof(struct acpiphp_slot));
 168                slot->bridge = bridge;
 169                slot->id = num_slots++;
 170                slot->device = device;
 171                slot->sun = sun;
 172                INIT_LIST_HEAD(&slot->funcs);
 173                init_MUTEX(&slot->crit_sect);
 174
 175                slot->next = bridge->slots;
 176                bridge->slots = slot;
 177
 178                bridge->nr_slots++;
 179
 180                dbg("found ACPI PCI Hotplug slot at PCI %02x:%02x Slot:%d\n",
 181                    slot->bridge->bus, slot->device, slot->sun);
 182        }
 183
 184        newfunc->slot = slot;
 185        list_add_tail(&newfunc->sibling, &slot->funcs);
 186
 187        /* associate corresponding pci_dev */
 188        newfunc->pci_dev = pci_find_slot(bridge->bus,
 189                                         PCI_DEVFN(device, function));
 190        if (newfunc->pci_dev) {
 191                if (acpiphp_init_func_resource(newfunc) < 0) {
 192                        kfree(newfunc);
 193                        return AE_ERROR;
 194                }
 195                slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
 196        }
 197
 198        /* install notify handler */
 199        status = acpi_install_notify_handler(handle,
 200                                             ACPI_SYSTEM_NOTIFY,
 201                                             handle_hotplug_event_func,
 202                                             newfunc);
 203
 204        if (ACPI_FAILURE(status)) {
 205                err("failed to register interrupt notify handler\n");
 206                return status;
 207        }
 208
 209        return AE_OK;
 210}
 211
 212
 213/* see if it's worth looking at this bridge */
 214static int detect_ejectable_slots (acpi_handle *bridge_handle)
 215{
 216        acpi_status status;
 217        int count;
 218
 219        count = 0;
 220
 221        /* only check slots defined directly below bridge object */
 222        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1,
 223                                     is_ejectable_slot, (void *)&count, NULL);
 224
 225        return count;
 226}
 227
 228
 229/* decode ACPI _CRS data and convert into our internal resource list
 230 * TBD: _TRA, etc.
 231 */
 232static void
 233decode_acpi_resource (struct acpi_resource *resource, struct acpiphp_bridge *bridge)
 234{
 235        struct acpi_resource_address16 *address16_data;
 236        struct acpi_resource_address32 *address32_data;
 237        struct acpi_resource_address64 *address64_data;
 238        struct pci_resource *res;
 239
 240        u32 resource_type, producer_consumer, address_length;
 241        u64 min_address_range, max_address_range;
 242        u16 cache_attribute = 0;
 243
 244        int done = 0, found;
 245
 246        /* shut up gcc */
 247        resource_type = producer_consumer = address_length = 0;
 248        min_address_range = max_address_range = 0;
 249
 250        while (!done) {
 251                found = 0;
 252
 253                switch (resource->id) {
 254                case ACPI_RSTYPE_ADDRESS16:
 255                        address16_data = (struct acpi_resource_address16 *)&resource->data;
 256                        resource_type = address16_data->resource_type;
 257                        producer_consumer = address16_data->producer_consumer;
 258                        min_address_range = address16_data->min_address_range;
 259                        max_address_range = address16_data->max_address_range;
 260                        address_length = address16_data->address_length;
 261                        if (resource_type == ACPI_MEMORY_RANGE)
 262                                cache_attribute = address16_data->attribute.memory.cache_attribute;
 263                        found = 1;
 264                        break;
 265
 266                case ACPI_RSTYPE_ADDRESS32:
 267                        address32_data = (struct acpi_resource_address32 *)&resource->data;
 268                        resource_type = address32_data->resource_type;
 269                        producer_consumer = address32_data->producer_consumer;
 270                        min_address_range = address32_data->min_address_range;
 271                        max_address_range = address32_data->max_address_range;
 272                        address_length = address32_data->address_length;
 273                        if (resource_type == ACPI_MEMORY_RANGE)
 274                                cache_attribute = address32_data->attribute.memory.cache_attribute;
 275                        found = 1;
 276                        break;
 277
 278                case ACPI_RSTYPE_ADDRESS64:
 279                        address64_data = (struct acpi_resource_address64 *)&resource->data;
 280                        resource_type = address64_data->resource_type;
 281                        producer_consumer = address64_data->producer_consumer;
 282                        min_address_range = address64_data->min_address_range;
 283                        max_address_range = address64_data->max_address_range;
 284                        address_length = address64_data->address_length;
 285                        if (resource_type == ACPI_MEMORY_RANGE)
 286                                cache_attribute = address64_data->attribute.memory.cache_attribute;
 287                        found = 1;
 288                        break;
 289
 290                case ACPI_RSTYPE_END_TAG:
 291                        done = 1;
 292                        break;
 293
 294                default:
 295                        /* ignore */
 296                        break;
 297                }
 298
 299                resource = (struct acpi_resource *)((char*)resource + resource->length);
 300
 301                if (found && producer_consumer == ACPI_PRODUCER && address_length > 0) {
 302                        switch (resource_type) {
 303                        case ACPI_MEMORY_RANGE:
 304                                if (cache_attribute == ACPI_PREFETCHABLE_MEMORY) {
 305                                        dbg("resource type: prefetchable memory 0x%x - 0x%x\n", (u32)min_address_range, (u32)max_address_range);
 306                                        res = acpiphp_make_resource(min_address_range,
 307                                                            address_length);
 308                                        if (!res) {
 309                                                err("out of memory\n");
 310                                                return;
 311                                        }
 312                                        res->next = bridge->p_mem_head;
 313                                        bridge->p_mem_head = res;
 314                                } else {
 315                                        dbg("resource type: memory 0x%x - 0x%x\n", (u32)min_address_range, (u32)max_address_range);
 316                                        res = acpiphp_make_resource(min_address_range,
 317                                                            address_length);
 318                                        if (!res) {
 319                                                err("out of memory\n");
 320                                                return;
 321                                        }
 322                                        res->next = bridge->mem_head;
 323                                        bridge->mem_head = res;
 324                                }
 325                                break;
 326                        case ACPI_IO_RANGE:
 327                                dbg("resource type: io 0x%x - 0x%x\n", (u32)min_address_range, (u32)max_address_range);
 328                                res = acpiphp_make_resource(min_address_range,
 329                                                    address_length);
 330                                if (!res) {
 331                                        err("out of memory\n");
 332                                        return;
 333                                }
 334                                res->next = bridge->io_head;
 335                                bridge->io_head = res;
 336                                break;
 337                        case ACPI_BUS_NUMBER_RANGE:
 338                                dbg("resource type: bus number %d - %d\n", (u32)min_address_range, (u32)max_address_range);
 339                                res = acpiphp_make_resource(min_address_range,
 340                                                    address_length);
 341                                if (!res) {
 342                                        err("out of memory\n");
 343                                        return;
 344                                }
 345                                res->next = bridge->bus_head;
 346                                bridge->bus_head = res;
 347                                break;
 348                        default:
 349                                /* invalid type */
 350                                break;
 351                        }
 352                }
 353        }
 354
 355        acpiphp_resource_sort_and_combine(&bridge->io_head);
 356        acpiphp_resource_sort_and_combine(&bridge->mem_head);
 357        acpiphp_resource_sort_and_combine(&bridge->p_mem_head);
 358        acpiphp_resource_sort_and_combine(&bridge->bus_head);
 359
 360        dbg("ACPI _CRS resource:\n");
 361        acpiphp_dump_resource(bridge);
 362}
 363
 364
 365/* find pci_bus structure associated to specific bus number */
 366static struct pci_bus *find_pci_bus(const struct list_head *list, int bus)
 367{
 368        const struct list_head *l;
 369
 370        list_for_each (l, list) {
 371                struct pci_bus *b = pci_bus_b(l);
 372                if (b->number == bus)
 373                        return b;
 374
 375                if (!list_empty(&b->children)) {
 376                        /* XXX recursive call */
 377                        b = find_pci_bus(&b->children, bus);
 378
 379                        if (b)
 380                                return b;
 381                }
 382        }
 383
 384        return NULL;
 385}
 386
 387
 388/* decode ACPI 2.0 _HPP hot plug parameters */
 389static void decode_hpp(struct acpiphp_bridge *bridge)
 390{
 391        acpi_status status;
 392        struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER,
 393                                      .pointer = NULL};
 394        union acpi_object *package;
 395        int i;
 396
 397        /* default numbers */
 398        bridge->hpp.cache_line_size = 0x10;
 399        bridge->hpp.latency_timer = 0x40;
 400        bridge->hpp.enable_SERR = 0;
 401        bridge->hpp.enable_PERR = 0;
 402
 403        status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer);
 404
 405        if (ACPI_FAILURE(status)) {
 406                dbg("_HPP evaluation failed\n");
 407                return;
 408        }
 409
 410        package = (union acpi_object *) buffer.pointer;
 411
 412        if (!package || package->type != ACPI_TYPE_PACKAGE ||
 413            package->package.count != 4 || !package->package.elements) {
 414                err("invalid _HPP object; ignoring\n");
 415                goto err_exit;
 416        }
 417
 418        for (i = 0; i < 4; i++) {
 419                if (package->package.elements[i].type != ACPI_TYPE_INTEGER) {
 420                        err("invalid _HPP parameter type; ignoring\n");
 421                        goto err_exit;
 422                }
 423        }
 424
 425        bridge->hpp.cache_line_size = package->package.elements[0].integer.value;
 426        bridge->hpp.latency_timer = package->package.elements[1].integer.value;
 427        bridge->hpp.enable_SERR = package->package.elements[2].integer.value;
 428        bridge->hpp.enable_PERR = package->package.elements[3].integer.value;
 429
 430        dbg("_HPP parameter = (%02x, %02x, %02x, %02x)\n",
 431            bridge->hpp.cache_line_size,
 432            bridge->hpp.latency_timer,
 433            bridge->hpp.enable_SERR,
 434            bridge->hpp.enable_PERR);
 435
 436        bridge->flags |= BRIDGE_HAS_HPP;
 437
 438 err_exit:
 439        kfree(buffer.pointer);
 440}
 441
 442
 443/* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */
 444static void init_bridge_misc (struct acpiphp_bridge *bridge)
 445{
 446        acpi_status status;
 447
 448        /* decode ACPI 2.0 _HPP (hot plug parameters) */
 449        decode_hpp(bridge);
 450
 451        /* subtract all resources already allocated */
 452        acpiphp_detect_pci_resource(bridge);
 453
 454        /* register all slot objects under this bridge */
 455        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
 456                                     register_slot, bridge, NULL);
 457
 458        /* install notify handler */
 459        status = acpi_install_notify_handler(bridge->handle,
 460                                             ACPI_SYSTEM_NOTIFY,
 461                                             handle_hotplug_event_bridge,
 462                                             bridge);
 463
 464        if (ACPI_FAILURE(status)) {
 465                err("failed to register interrupt notify handler\n");
 466        }
 467
 468        list_add(&bridge->list, &bridge_list);
 469
 470        dbg("Bridge resource:\n");
 471        acpiphp_dump_resource(bridge);
 472}
 473
 474
 475/* allocate and initialize host bridge data structure */
 476static void add_host_bridge (acpi_handle *handle, int seg, int bus)
 477{
 478        acpi_status status;
 479        struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER,
 480                                      .pointer = NULL};
 481        struct acpiphp_bridge *bridge;
 482
 483        bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
 484        if (bridge == NULL)
 485                return;
 486
 487        memset(bridge, 0, sizeof(struct acpiphp_bridge));
 488
 489        bridge->type = BRIDGE_TYPE_HOST;
 490        bridge->handle = handle;
 491        bridge->seg = seg;
 492        bridge->bus = bus;
 493
 494        bridge->pci_bus = find_pci_bus(&pci_root_buses, bus);
 495
 496        bridge->res_lock = SPIN_LOCK_UNLOCKED;
 497
 498        /* to be overridden when we decode _CRS */
 499        bridge->sub = bridge->bus;
 500
 501        /* decode resources */
 502
 503        status = acpi_get_current_resources(handle, &buffer);
 504
 505        if (ACPI_FAILURE(status)) {
 506                err("failed to decode bridge resources\n");
 507                kfree(bridge);
 508                return;
 509        }
 510
 511        decode_acpi_resource(buffer.pointer, bridge);
 512        kfree(buffer.pointer);
 513
 514        if (bridge->bus_head) {
 515                bridge->bus = bridge->bus_head->base;
 516                bridge->sub = bridge->bus_head->base + bridge->bus_head->length - 1;
 517        }
 518
 519        init_bridge_misc(bridge);
 520}
 521
 522
 523/* allocate and initialize PCI-to-PCI bridge data structure */
 524static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int fn)
 525{
 526        struct acpiphp_bridge *bridge;
 527        u8 tmp8;
 528        u16 tmp16;
 529        u64 base64, limit64;
 530        u32 base, limit, base32u, limit32u;
 531
 532        bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
 533        if (bridge == NULL) {
 534                err("out of memory\n");
 535                return;
 536        }
 537
 538        memset(bridge, 0, sizeof(struct acpiphp_bridge));
 539
 540        bridge->type = BRIDGE_TYPE_P2P;
 541        bridge->handle = handle;
 542        bridge->seg = seg;
 543
 544        bridge->pci_dev = pci_find_slot(bus, PCI_DEVFN(dev, fn));
 545        if (!bridge->pci_dev) {
 546                err("Can't get pci_dev\n");
 547                kfree(bridge);
 548                return;
 549        }
 550
 551        bridge->pci_bus = bridge->pci_dev->subordinate;
 552        if (!bridge->pci_bus) {
 553                err("This is not a PCI-to-PCI bridge!\n");
 554                kfree(bridge);
 555                return;
 556        }
 557
 558        bridge->res_lock = SPIN_LOCK_UNLOCKED;
 559
 560        bridge->bus = bridge->pci_bus->number;
 561        bridge->sub = bridge->pci_bus->subordinate;
 562
 563        /*
 564         * decode resources under this P2P bridge
 565         */
 566
 567        /* I/O resources */
 568        pci_read_config_byte(bridge->pci_dev, PCI_IO_BASE, &tmp8);
 569        base = tmp8;
 570        pci_read_config_byte(bridge->pci_dev, PCI_IO_LIMIT, &tmp8);
 571        limit = tmp8;
 572
 573        switch (base & PCI_IO_RANGE_TYPE_MASK) {
 574        case PCI_IO_RANGE_TYPE_16:
 575                base = (base << 8) & 0xf000;
 576                limit = ((limit << 8) & 0xf000) + 0xfff;
 577                bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);
 578                if (!bridge->io_head) {
 579                        err("out of memory\n");
 580                        kfree(bridge);
 581                        return;
 582                }
 583                dbg("16bit I/O range: %04x-%04x\n",
 584                    (u32)bridge->io_head->base,
 585                    (u32)(bridge->io_head->base + bridge->io_head->length - 1));
 586                break;
 587        case PCI_IO_RANGE_TYPE_32:
 588                pci_read_config_word(bridge->pci_dev, PCI_IO_BASE_UPPER16, &tmp16);
 589                base = ((u32)tmp16 << 16) | ((base << 8) & 0xf000);
 590                pci_read_config_word(bridge->pci_dev, PCI_IO_LIMIT_UPPER16, &tmp16);
 591                limit = (((u32)tmp16 << 16) | ((limit << 8) & 0xf000)) + 0xfff;
 592                bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);
 593                if (!bridge->io_head) {
 594                        err("out of memory\n");
 595                        kfree(bridge);
 596                        return;
 597                }
 598                dbg("32bit I/O range: %08x-%08x\n",
 599                    (u32)bridge->io_head->base,
 600                    (u32)(bridge->io_head->base + bridge->io_head->length - 1));
 601                break;
 602        case 0x0f:
 603                dbg("I/O space unsupported\n");
 604                break;
 605        default:
 606                warn("Unknown I/O range type\n");
 607        }
 608
 609        /* Memory resources (mandatory for P2P bridge) */
 610        pci_read_config_word(bridge->pci_dev, PCI_MEMORY_BASE, &tmp16);
 611        base = (tmp16 & 0xfff0) << 16;
 612        pci_read_config_word(bridge->pci_dev, PCI_MEMORY_LIMIT, &tmp16);
 613        limit = ((tmp16 & 0xfff0) << 16) | 0xfffff;
 614        bridge->mem_head = acpiphp_make_resource((u64)base, limit - base + 1);
 615        if (!bridge->mem_head) {
 616                err("out of memory\n");
 617                kfree(bridge);
 618                return;
 619        }
 620        dbg("32bit Memory range: %08x-%08x\n",
 621            (u32)bridge->mem_head->base,
 622            (u32)(bridge->mem_head->base + bridge->mem_head->length-1));
 623
 624        /* Prefetchable Memory resources (optional) */
 625        pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_BASE, &tmp16);
 626        base = tmp16;
 627        pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_LIMIT, &tmp16);
 628        limit = tmp16;
 629
 630        switch (base & PCI_MEMORY_RANGE_TYPE_MASK) {
 631        case PCI_PREF_RANGE_TYPE_32:
 632                base = (base & 0xfff0) << 16;
 633                limit = ((limit & 0xfff0) << 16) | 0xfffff;
 634                bridge->p_mem_head = acpiphp_make_resource((u64)base, limit - base + 1);
 635                if (!bridge->p_mem_head) {
 636                        err("out of memory\n");
 637                        kfree(bridge);
 638                        return;
 639                }
 640                dbg("32bit Prefetchable memory range: %08x-%08x\n",
 641                    (u32)bridge->p_mem_head->base,
 642                    (u32)(bridge->p_mem_head->base + bridge->p_mem_head->length - 1));
 643                break;
 644        case PCI_PREF_RANGE_TYPE_64:
 645                pci_read_config_dword(bridge->pci_dev, PCI_PREF_BASE_UPPER32, &base32u);
 646                pci_read_config_dword(bridge->pci_dev, PCI_PREF_LIMIT_UPPER32, &limit32u);
 647                base64 = ((u64)base32u << 32) | ((base & 0xfff0) << 16);
 648                limit64 = (((u64)limit32u << 32) | ((limit & 0xfff0) << 16)) + 0xfffff;
 649
 650                bridge->p_mem_head = acpiphp_make_resource(base64, limit64 - base64 + 1);
 651                if (!bridge->p_mem_head) {
 652                        err("out of memory\n");
 653                        kfree(bridge);
 654                        return;
 655                }
 656                dbg("64bit Prefetchable memory range: %08x%08x-%08x%08x\n",
 657                    (u32)(bridge->p_mem_head->base >> 32),
 658                    (u32)(bridge->p_mem_head->base & 0xffffffff),
 659                    (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) >> 32),
 660                    (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) & 0xffffffff));
 661                break;
 662        case 0x0f:
 663                break;
 664        default:
 665                warn("Unknown prefetchale memory type\n");
 666        }
 667
 668        init_bridge_misc(bridge);
 669}
 670
 671
 672/* callback routine to find P2P bridges */
 673static acpi_status
 674find_p2p_bridge (acpi_handle handle, u32 lvl, void *context, void **rv)
 675{
 676        acpi_status status;
 677        acpi_handle dummy_handle;
 678        unsigned long *segbus = context;
 679        unsigned long tmp;
 680        int seg, bus, device, function;
 681        struct pci_dev *dev;
 682
 683        /* get PCI address */
 684        seg = (*segbus >> 8) & 0xff;
 685        bus = *segbus & 0xff;
 686
 687        status = acpi_get_handle(handle, "_ADR", &dummy_handle);
 688        if (ACPI_FAILURE(status))
 689                return AE_OK;           /* continue */
 690
 691        status = acpi_evaluate_integer(handle, "_ADR", NULL, &tmp);
 692        if (ACPI_FAILURE(status)) {
 693                dbg("%s: _ADR evaluation failure\n", __FUNCTION__);
 694                return AE_OK;
 695        }
 696
 697        device = (tmp >> 16) & 0xffff;
 698        function = tmp & 0xffff;
 699
 700        dev = pci_find_slot(bus, PCI_DEVFN(device, function));
 701
 702        if (!dev)
 703                return AE_OK;
 704
 705        if (!dev->subordinate)
 706                return AE_OK;
 707
 708        /* check if this bridge has ejectable slots */
 709        if (detect_ejectable_slots(handle) > 0) {
 710                dbg("found PCI-to-PCI bridge at PCI %s\n", dev->slot_name);
 711                add_p2p_bridge(handle, seg, bus, device, function);
 712        }
 713
 714        return AE_OK;
 715}
 716
 717
 718/* find hot-pluggable slots, and then find P2P bridge */
 719static int add_bridge (acpi_handle handle)
 720{
 721        acpi_status status;
 722        unsigned long tmp;
 723        int seg, bus;
 724        acpi_handle dummy_handle;
 725
 726        /* if the bridge doesn't have _STA, we assume it is always there */
 727        status = acpi_get_handle(handle, "_STA", &dummy_handle);
 728        if (ACPI_SUCCESS(status)) {
 729                status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp);
 730                if (ACPI_FAILURE(status)) {
 731                        dbg("%s: _STA evaluation failure\n", __FUNCTION__);
 732                        return 0;
 733                }
 734                if ((tmp & ACPI_STA_FUNCTIONING) == 0)
 735                        /* don't register this object */
 736                        return 0;
 737        }
 738
 739        /* get PCI segment number */
 740        status = acpi_evaluate_integer(handle, "_SEG", NULL, &tmp);
 741
 742        seg = ACPI_SUCCESS(status) ? tmp : 0;
 743
 744        /* get PCI bus number */
 745        status = acpi_evaluate_integer(handle, "_BBN", NULL, &tmp);
 746
 747        if (ACPI_SUCCESS(status)) {
 748                bus = tmp;
 749        } else {
 750                warn("can't get bus number, assuming 0\n");
 751                bus = 0;
 752        }
 753
 754        /* check if this bridge has ejectable slots */
 755        if (detect_ejectable_slots(handle) > 0) {
 756                dbg("found PCI host-bus bridge with hot-pluggable slots\n");
 757                add_host_bridge(handle, seg, bus);
 758                return 0;
 759        }
 760
 761        tmp = seg << 8 | bus;
 762
 763        /* search P2P bridges under this host bridge */
 764        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
 765                                     find_p2p_bridge, &tmp, NULL);
 766
 767        if (ACPI_FAILURE(status))
 768                warn("find_p2p_bridge faied (error code = 0x%x)\n",status);
 769
 770        return 0;
 771}
 772
 773
 774static void remove_bridge (acpi_handle handle)
 775{
 776        /* No-op for now .. */
 777}
 778
 779static int power_on_slot (struct acpiphp_slot *slot)
 780{
 781        acpi_status status;
 782        struct acpiphp_func *func;
 783        struct list_head *l;
 784        int retval = 0;
 785
 786        /* if already enabled, just skip */
 787        if (slot->flags & SLOT_POWEREDON)
 788                goto err_exit;
 789
 790        list_for_each (l, &slot->funcs) {
 791                func = list_entry(l, struct acpiphp_func, sibling);
 792
 793                if (func->flags & FUNC_HAS_PS0) {
 794                        dbg("%s: executing _PS0\n", __FUNCTION__);
 795                        status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL);
 796                        if (ACPI_FAILURE(status)) {
 797                                warn("%s: _PS0 failed\n", __FUNCTION__);
 798                                retval = -1;
 799                                goto err_exit;
 800                        } else
 801                                break;
 802                }
 803        }
 804
 805        /* TBD: evaluate _STA to check if the slot is enabled */
 806
 807        slot->flags |= SLOT_POWEREDON;
 808
 809 err_exit:
 810        return retval;
 811}
 812
 813
 814static int power_off_slot (struct acpiphp_slot *slot)
 815{
 816        acpi_status status;
 817        struct acpiphp_func *func;
 818        struct list_head *l;
 819        struct acpi_object_list arg_list;
 820        union acpi_object arg;
 821
 822        int retval = 0;
 823
 824        /* if already disabled, just skip */
 825        if ((slot->flags & SLOT_POWEREDON) == 0)
 826                goto err_exit;
 827
 828        list_for_each (l, &slot->funcs) {
 829                func = list_entry(l, struct acpiphp_func, sibling);
 830
 831                if (func->pci_dev && (func->flags & FUNC_HAS_PS3)) {
 832                        status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);
 833                        if (ACPI_FAILURE(status)) {
 834                                warn("%s: _PS3 failed\n", __FUNCTION__);
 835                                retval = -1;
 836                                goto err_exit;
 837                        } else
 838                                break;
 839                }
 840        }
 841
 842        list_for_each (l, &slot->funcs) {
 843                func = list_entry(l, struct acpiphp_func, sibling);
 844
 845                /* We don't want to call _EJ0 on non-existing functions. */
 846                if (func->pci_dev && (func->flags & FUNC_HAS_EJ0)) {
 847                        /* _EJ0 method take one argument */
 848                        arg_list.count = 1;
 849                        arg_list.pointer = &arg;
 850                        arg.type = ACPI_TYPE_INTEGER;
 851                        arg.integer.value = 1;
 852                        status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);
 853                        if (ACPI_FAILURE(status)) {
 854                                warn("%s: _EJ0 failed\n", __FUNCTION__);
 855                                retval = -1;
 856                                goto err_exit;
 857                        } else
 858                                break;
 859                }
 860        }
 861
 862        /* TBD: evaluate _STA to check if the slot is disabled */
 863
 864        slot->flags &= (~SLOT_POWEREDON);
 865
 866 err_exit:
 867        return retval;
 868}
 869
 870
 871/**
 872 * enable_device - enable, configure a slot
 873 * @slot: slot to be enabled
 874 *
 875 * This function should be called per *physical slot*,
 876 * not per each slot object in ACPI namespace.
 877 *
 878 */
 879static int enable_device (struct acpiphp_slot *slot)
 880{
 881        u8 bus;
 882        struct pci_dev dev0, *dev;
 883        struct pci_bus *child;
 884        struct list_head *l;
 885        struct acpiphp_func *func;
 886        int retval = 0;
 887
 888        if (slot->flags & SLOT_ENABLED)
 889                goto err_exit;
 890
 891        /* sanity check: dev should be NULL when hot-plugged in */
 892        dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0));
 893        if (dev) {
 894                /* This case shouldn't happen */
 895                err("pci_dev structure already exists.\n");
 896                retval = -1;
 897                goto err_exit;
 898        }
 899
 900        /* allocate resources to device */
 901        retval = acpiphp_configure_slot(slot);
 902        if (retval)
 903                goto err_exit;
 904
 905        memset(&dev0, 0, sizeof (struct pci_dev));
 906
 907        dev0.bus = slot->bridge->pci_bus;
 908        dev0.devfn = PCI_DEVFN(slot->device, 0);
 909        dev0.sysdata = dev0.bus->sysdata;
 910
 911        /* returned `dev' is the *first function* only! */
 912        dev = pci_scan_slot (&dev0);
 913
 914        if (!dev) {
 915                err("No new device found\n");
 916                retval = -1;
 917                goto err_exit;
 918        }
 919
 920        if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
 921                pci_read_config_byte(dev, PCI_SECONDARY_BUS, &bus);
 922                child = (struct pci_bus*) pci_add_new_bus(dev->bus, dev, bus);
 923                pci_do_scan_bus(child);
 924        }
 925
 926        /* associate pci_dev to our representation */
 927        list_for_each (l, &slot->funcs) {
 928                func = list_entry(l, struct acpiphp_func, sibling);
 929
 930                func->pci_dev = pci_find_slot(slot->bridge->bus,
 931                                              PCI_DEVFN(slot->device,
 932                                                        func->function));
 933                if (!func->pci_dev)
 934                        continue;
 935
 936                /* configure device */
 937                retval = acpiphp_configure_function(func);
 938                if (retval)
 939                        goto err_exit;
 940        }
 941
 942        slot->flags |= SLOT_ENABLED;
 943
 944        dbg("Available resources:\n");
 945        acpiphp_dump_resource(slot->bridge);
 946
 947 err_exit:
 948        return retval;
 949}
 950
 951
 952/**
 953 * disable_device - disable a slot
 954 */
 955static int disable_device (struct acpiphp_slot *slot)
 956{
 957        int retval = 0;
 958        struct acpiphp_func *func;
 959        struct list_head *l;
 960
 961        /* is this slot already disabled? */
 962        if (!(slot->flags & SLOT_ENABLED))
 963                goto err_exit;
 964
 965        list_for_each (l, &slot->funcs) {
 966                func = list_entry(l, struct acpiphp_func, sibling);
 967
 968                if (func->pci_dev)
 969                        if (acpiphp_unconfigure_function(func)) {
 970                                err("failed to unconfigure device\n");
 971                                retval = -1;
 972                                goto err_exit;
 973                        }
 974        }
 975
 976        slot->flags &= (~SLOT_ENABLED);
 977
 978 err_exit:
 979        return retval;
 980}
 981
 982
 983/**
 984 * get_slot_status - get ACPI slot status
 985 *
 986 * if a slot has _STA for each function and if any one of them
 987 * returned non-zero status, return it
 988 *
 989 * if a slot doesn't have _STA and if any one of its functions'
 990 * configuration space is configured, return 0x0f as a _STA
 991 *
 992 * otherwise return 0
 993 */
 994static unsigned int get_slot_status (struct acpiphp_slot *slot)
 995{
 996        acpi_status status;
 997        unsigned long sta = 0;
 998        u32 dvid;
 999        struct list_head *l;
1000        struct acpiphp_func *func;
1001
1002        list_for_each (l, &slot->funcs) {
1003                func = list_entry(l, struct acpiphp_func, sibling);
1004
1005                if (func->flags & FUNC_HAS_STA) {
1006                        status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta);
1007                        if (ACPI_SUCCESS(status) && sta)
1008                                break;
1009                } else {
1010                        pci_bus_read_config_dword(slot->bridge->pci_bus,
1011                                        PCI_DEVFN(slot->device, func->function),
1012                                        PCI_VENDOR_ID, &dvid);
1013                        if (dvid != 0xffffffff) {
1014                                sta = ACPI_STA_ALL;
1015                                break;
1016                        }
1017                }
1018        }
1019
1020        return (unsigned int)sta;
1021}
1022
1023
1024/*
1025 * ACPI event handlers
1026 */
1027
1028/**
1029 * handle_hotplug_event_bridge - handle ACPI event on bridges
1030 *
1031 * @handle: Notify()'ed acpi_handle
1032 * @type: Notify code
1033 * @context: pointer to acpiphp_bridge structure
1034 *
1035 * handles ACPI event notification on {host,p2p} bridges
1036 *
1037 */
1038static void handle_hotplug_event_bridge (acpi_handle handle, u32 type, void *context)
1039{
1040        struct acpiphp_bridge *bridge;
1041        char objname[64];
1042        struct acpi_buffer buffer = { .length = sizeof(objname),
1043                                      .pointer = objname };
1044
1045        bridge = (struct acpiphp_bridge *)context;
1046
1047        acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
1048
1049        switch (type) {
1050        case ACPI_NOTIFY_BUS_CHECK:
1051                /* bus re-enumerate */
1052                dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
1053                acpiphp_check_bridge(bridge);
1054                break;
1055
1056        case ACPI_NOTIFY_DEVICE_CHECK:
1057                /* device check */
1058                dbg("%s: Device check notify on %s\n", __FUNCTION__, objname);
1059                acpiphp_check_bridge(bridge);
1060                break;
1061
1062        case ACPI_NOTIFY_DEVICE_WAKE:
1063                /* wake event */
1064                dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname);
1065                break;
1066
1067        case ACPI_NOTIFY_EJECT_REQUEST:
1068                /* request device eject */
1069                dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
1070                break;
1071
1072        default:
1073                warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
1074                break;
1075        }
1076}
1077
1078
1079/**
1080 * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
1081 *
1082 * @handle: Notify()'ed acpi_handle
1083 * @type: Notify code
1084 * @context: pointer to acpiphp_func structure
1085 *
1086 * handles ACPI event notification on slots
1087 *
1088 */
1089static void handle_hotplug_event_func (acpi_handle handle, u32 type, void *context)
1090{
1091        struct acpiphp_func *func;
1092        char objname[64];
1093        struct acpi_buffer buffer = { .length = sizeof(objname),
1094                                      .pointer = objname };
1095
1096        acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
1097
1098        func = (struct acpiphp_func *)context;
1099
1100        switch (type) {
1101        case ACPI_NOTIFY_BUS_CHECK:
1102                /* bus re-enumerate */
1103                dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
1104                acpiphp_enable_slot(func->slot);
1105                break;
1106
1107        case ACPI_NOTIFY_DEVICE_CHECK:
1108                /* device check : re-enumerate from parent bus */
1109                dbg("%s: Device check notify on %s\n", __FUNCTION__, objname);
1110                acpiphp_check_bridge(func->slot->bridge);
1111                break;
1112
1113        case ACPI_NOTIFY_DEVICE_WAKE:
1114                /* wake event */
1115                dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname);
1116                break;
1117
1118        case ACPI_NOTIFY_EJECT_REQUEST:
1119                /* request device eject */
1120                dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
1121                acpiphp_disable_slot(func->slot);
1122                break;
1123
1124        default:
1125                warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
1126                break;
1127        }
1128}
1129
1130
1131static struct acpi_pci_driver acpi_pci_hp_driver = {
1132        .add =          add_bridge,
1133        .remove =       remove_bridge,
1134};
1135
1136/**
1137 * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures
1138 *
1139 */
1140int acpiphp_glue_init (void)
1141{
1142        int num;
1143
1144        if (list_empty(&pci_root_buses))
1145                return -1;
1146
1147        num = acpi_pci_register_driver(&acpi_pci_hp_driver);
1148
1149        if (num <= 0)
1150                return -1;
1151
1152        return 0;
1153}
1154
1155
1156/**
1157 * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures
1158 *
1159 * This function frees all data allocated in acpiphp_glue_init()
1160 */
1161void acpiphp_glue_exit (void)
1162{
1163        struct list_head *l1, *l2, *n1, *n2;
1164        struct acpiphp_bridge *bridge;
1165        struct acpiphp_slot *slot, *next;
1166        struct acpiphp_func *func;
1167        acpi_status status;
1168
1169        list_for_each_safe (l1, n1, &bridge_list) {
1170                bridge = (struct acpiphp_bridge *)l1;
1171                slot = bridge->slots;
1172                while (slot) {
1173                        next = slot->next;
1174                        list_for_each_safe (l2, n2, &slot->funcs) {
1175                                func = list_entry(l2, struct acpiphp_func, sibling);
1176                                acpiphp_free_resource(&func->io_head);
1177                                acpiphp_free_resource(&func->mem_head);
1178                                acpiphp_free_resource(&func->p_mem_head);
1179                                acpiphp_free_resource(&func->bus_head);
1180                                status = acpi_remove_notify_handler(func->handle,
1181                                                                    ACPI_SYSTEM_NOTIFY,
1182                                                                    handle_hotplug_event_func);
1183                                if (ACPI_FAILURE(status))
1184                                        err("failed to remove notify handler\n");
1185                                kfree(func);
1186                        }
1187                        kfree(slot);
1188                        slot = next;
1189                }
1190                status = acpi_remove_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY,
1191                                                    handle_hotplug_event_bridge);
1192                if (ACPI_FAILURE(status))
1193                        err("failed to remove notify handler\n");
1194
1195                acpiphp_free_resource(&bridge->io_head);
1196                acpiphp_free_resource(&bridge->mem_head);
1197                acpiphp_free_resource(&bridge->p_mem_head);
1198                acpiphp_free_resource(&bridge->bus_head);
1199
1200                kfree(bridge);
1201        }
1202}
1203
1204
1205/**
1206 * acpiphp_get_num_slots - count number of slots in a system
1207 */
1208int acpiphp_get_num_slots (void)
1209{
1210        struct list_head *node;
1211        struct acpiphp_bridge *bridge;
1212        int num_slots;
1213
1214        num_slots = 0;
1215
1216        list_for_each (node, &bridge_list) {
1217                bridge = (struct acpiphp_bridge *)node;
1218                dbg("Bus%d %dslot(s)\n", bridge->bus, bridge->nr_slots);
1219                num_slots += bridge->nr_slots;
1220        }
1221
1222        dbg("Total %dslots\n", num_slots);
1223        return num_slots;
1224}
1225
1226
1227/**
1228 * acpiphp_for_each_slot - call function for each slot
1229 * @fn: callback function
1230 * @data: context to be passed to callback function
1231 *
1232 */
1233int acpiphp_for_each_slot(acpiphp_callback fn, void *data)
1234{
1235        struct list_head *node;
1236        struct acpiphp_bridge *bridge;
1237        struct acpiphp_slot *slot;
1238        int retval = 0;
1239
1240        list_for_each (node, &bridge_list) {
1241                bridge = (struct acpiphp_bridge *)node;
1242                for (slot = bridge->slots; slot; slot = slot->next) {
1243                        retval = fn(slot, data);
1244                        if (!retval)
1245                                goto err_exit;
1246                }
1247        }
1248
1249 err_exit:
1250        return retval;
1251}
1252
1253
1254/* search matching slot from id  */
1255struct acpiphp_slot *get_slot_from_id (int id)
1256{
1257        struct list_head *node;
1258        struct acpiphp_bridge *bridge;
1259        struct acpiphp_slot *slot;
1260
1261        list_for_each (node, &bridge_list) {
1262                bridge = (struct acpiphp_bridge *)node;
1263                for (slot = bridge->slots; slot; slot = slot->next)
1264                        if (slot->id == id)
1265                                return slot;
1266        }
1267
1268        /* should never happen! */
1269        err("%s: no object for id %d\n",__FUNCTION__, id);
1270        return 0;
1271}
1272
1273
1274/**
1275 * acpiphp_enable_slot - power on slot
1276 */
1277int acpiphp_enable_slot (struct acpiphp_slot *slot)
1278{
1279        int retval;
1280
1281        down(&slot->crit_sect);
1282
1283        /* wake up all functions */
1284        retval = power_on_slot(slot);
1285        if (retval)
1286                goto err_exit;
1287
1288        if (get_slot_status(slot) == ACPI_STA_ALL)
1289                /* configure all functions */
1290                retval = enable_device(slot);
1291
1292 err_exit:
1293        up(&slot->crit_sect);
1294        return retval;
1295}
1296
1297
1298/**
1299 * acpiphp_disable_slot - power off slot
1300 */
1301int acpiphp_disable_slot (struct acpiphp_slot *slot)
1302{
1303        int retval = 0;
1304
1305        down(&slot->crit_sect);
1306
1307        /* unconfigure all functions */
1308        retval = disable_device(slot);
1309        if (retval)
1310                goto err_exit;
1311
1312        /* power off all functions */
1313        retval = power_off_slot(slot);
1314        if (retval)
1315                goto err_exit;
1316
1317        acpiphp_resource_sort_and_combine(&slot->bridge->io_head);
1318        acpiphp_resource_sort_and_combine(&slot->bridge->mem_head);
1319        acpiphp_resource_sort_and_combine(&slot->bridge->p_mem_head);
1320        acpiphp_resource_sort_and_combine(&slot->bridge->bus_head);
1321        dbg("Available resources:\n");
1322        acpiphp_dump_resource(slot->bridge);
1323
1324 err_exit:
1325        up(&slot->crit_sect);
1326        return retval;
1327}
1328
1329
1330/**
1331 * acpiphp_check_bridge - re-enumerate devices
1332 */
1333int acpiphp_check_bridge (struct acpiphp_bridge *bridge)
1334{
1335        struct acpiphp_slot *slot;
1336        unsigned int sta;
1337        int retval = 0;
1338        int enabled, disabled;
1339
1340        enabled = disabled = 0;
1341
1342        for (slot = bridge->slots; slot; slot = slot->next) {
1343                sta = get_slot_status(slot);
1344                if (slot->flags & SLOT_ENABLED) {
1345                        /* if enabled but not present, disable */
1346                        if (sta != ACPI_STA_ALL) {
1347                                retval = acpiphp_disable_slot(slot);
1348                                if (retval) {
1349                                        err("Error occurred in enabling\n");
1350                                        up(&slot->crit_sect);
1351                                        goto err_exit;
1352                                }
1353                                disabled++;
1354                        }
1355                } else {
1356                        /* if disabled but present, enable */
1357                        if (sta == ACPI_STA_ALL) {
1358                                retval = acpiphp_enable_slot(slot);
1359                                if (retval) {
1360                                        err("Error occurred in enabling\n");
1361                                        up(&slot->crit_sect);
1362                                        goto err_exit;
1363                                }
1364                                enabled++;
1365                        }
1366                }
1367        }
1368
1369        dbg("%s: %d enabled, %d disabled\n", __FUNCTION__, enabled, disabled);
1370
1371 err_exit:
1372        return retval;
1373}
1374
1375
1376/*
1377 * slot enabled:  1
1378 * slot disabled: 0
1379 */
1380u8 acpiphp_get_power_status (struct acpiphp_slot *slot)
1381{
1382        unsigned int sta;
1383
1384        sta = get_slot_status(slot);
1385
1386        return (sta & ACPI_STA_ENABLED) ? 1 : 0;
1387}
1388
1389
1390/*
1391 * attention LED ON: 1
1392 *              OFF: 0
1393 *
1394 * TBD
1395 * no direct attention led status information via ACPI
1396 *
1397 */
1398u8 acpiphp_get_attention_status (struct acpiphp_slot *slot)
1399{
1400        return 0;
1401}
1402
1403
1404/*
1405 * latch closed:  1
1406 * latch   open:  0
1407 */
1408u8 acpiphp_get_latch_status (struct acpiphp_slot *slot)
1409{
1410        unsigned int sta;
1411
1412        sta = get_slot_status(slot);
1413
1414        return (sta & ACPI_STA_SHOW_IN_UI) ? 1 : 0;
1415}
1416
1417
1418/*
1419 * adapter presence : 1
1420 *          absence : 0
1421 */
1422u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot)
1423{
1424        unsigned int sta;
1425
1426        sta = get_slot_status(slot);
1427
1428        return (sta == 0) ? 0 : 1;
1429}
1430
1431
1432/*
1433 * pci address (seg/bus/dev)
1434 */
1435u32 acpiphp_get_address (struct acpiphp_slot *slot)
1436{
1437        u32 address;
1438
1439        address = ((slot->bridge->seg) << 16) |
1440                  ((slot->bridge->bus) << 8) |
1441                  slot->device;
1442
1443        return address;
1444}
1445
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.