From 91732005067f08ee989045d2522a82d804cf4c3a Mon Sep 17 00:00:00 2001
From: "Sergey Semyonov (Serge)" <ion2@mail.ru>
Date: Mon, 27 Sep 2010 11:30:31 +0000
Subject: [PATCH] devman: scan pci bus. Not yet complete.

git-svn-id: svn://kolibrios.org@1628 a494cfbc-eb01-0410-851d-a64ba20cac60
---
 drivers/devman/Makefile          |    6 +-
 drivers/devman/acpi.c            |  111 +--
 drivers/devman/acpi_bus.h        |   55 +-
 drivers/devman/pci/pci.c         |  175 +++-
 drivers/devman/pci/probe.c       |  419 ++++++++
 drivers/devman/pci_bind.c        |   98 ++
 drivers/devman/pci_root.c        |  149 +++
 drivers/devman/scan.c            |    8 +-
 drivers/devman/scan.cc           | 1557 ++++++++++++++++++++++++++++++
 drivers/include/linux/pci.h      |  345 +++----
 drivers/include/linux/pci_regs.h |  686 +++++++++++++
 11 files changed, 3339 insertions(+), 270 deletions(-)
 create mode 100644 drivers/devman/pci/probe.c
 create mode 100644 drivers/devman/pci_bind.c
 create mode 100644 drivers/devman/pci_root.c
 create mode 100644 drivers/devman/scan.cc
 create mode 100644 drivers/include/linux/pci_regs.h

diff --git a/drivers/devman/Makefile b/drivers/devman/Makefile
index 897356ddf7..91212d7ecd 100644
--- a/drivers/devman/Makefile
+++ b/drivers/devman/Makefile
@@ -1,4 +1,5 @@
 
+
 CC = gcc
 FASM = e:/fasm/fasm.exe
 
@@ -27,7 +28,10 @@ NAME= acpi
 NAME_SRCS= 	acpi.c		\
 		scan.c		\
 		pci_irq.c	\
-		pci/pci.c
+		pci_root.c	\
+		pci/pci.c	\
+		pci/probe.c	\
+		pci_bind.c
 
 
 all: $(NAME).dll
diff --git a/drivers/devman/acpi.c b/drivers/devman/acpi.c
index 6f08a82157..019b463944 100644
--- a/drivers/devman/acpi.c
+++ b/drivers/devman/acpi.c
@@ -110,29 +110,12 @@ void print_device_tree(struct acpi_device *device)
 };
 
 
-/*
-int acpi_pci_bind_root(struct acpi_device *device)
-{
-    device->ops.bind = acpi_pci_bind;
-    device->ops.unbind = acpi_pci_unbind;
 
-    return 0;
-}
-*/
 
 static bool pci_use_crs = false;
 
 #define IORESOURCE_BUS      0x00001000
 
-struct acpi_pci_root {
-    struct list_head node;
-    struct acpi_device * device;
-    struct acpi_pci_id id;
-    struct pci_bus *bus;
-    u16 segment;
-    struct resource secondary;      /* downstream bus range */
-
-};
 
 static LIST_HEAD(acpi_pci_roots);
 
@@ -179,6 +162,23 @@ static ACPI_STATUS try_get_root_bridge_busnr(ACPI_HANDLE handle,
 }
 
 
+static void acpi_pci_bridge_scan(struct acpi_device *device)
+{
+    int status;
+    struct acpi_device *child = NULL;
+
+    if (device->flags.bus_address)
+        if (device->parent && device->parent->ops.bind) {
+            status = device->parent->ops.bind(device);
+            if (!status) {
+                list_for_each_entry(child, &device->children, node)
+                    acpi_pci_bridge_scan(child);
+            }
+        }
+}
+
+
+
 struct pci_root_info
 {
     struct acpi_device *bridge;
@@ -416,7 +416,7 @@ struct pci_bus*  pci_acpi_scan_root(struct acpi_pci_root *root)
         bus = pci_create_bus(busnum, &pci_root_ops, sd);
         if (bus) {
             get_current_resources(device, busnum, domain, bus);
-//            bus->subordinate = pci_scan_child_bus(bus);
+            bus->subordinate = pci_scan_child_bus(bus);
         }
     }
 
@@ -528,9 +528,9 @@ static int acpi_pci_root_add(struct acpi_device *device)
      * -----------------------
      * Thus binding the ACPI and PCI devices.
      */
-//    result = acpi_pci_bind_root(device);
-//    if (result)
-//        goto end;
+    result = acpi_pci_bind_root(device);
+    if (result)
+        goto end;
 
     /*
      * PCI Routing Table
@@ -544,8 +544,8 @@ static int acpi_pci_root_add(struct acpi_device *device)
     /*
      * Scan and bind all _ADR-Based Devices
      */
-//    list_for_each_entry(child, &device->children, node)
-//        acpi_pci_bridge_scan(child);
+    list_for_each_entry(child, &device->children, node)
+        acpi_pci_bridge_scan(child);
 
     return 0;
 
@@ -761,71 +761,6 @@ err:
 
 };
 
-#if 0
-    scan_devices();
-
-    {
-        bool retval = false;
-        u32_t bus, last_bus;
-
-        if( (last_bus = PciApi(1))==-1)
-            return retval;
-
-        dbgprintf("last bus %x\n", last_bus);
-
-        for(bus=0; bus <= last_bus; bus++)
-        {
-            u32_t dev;
-
-            for(dev = 0; dev < 32; dev++)
-            {
-                u32_t fn;
-
-                for(fn = 0; fn < 8; fn++)
-                {
-
-                    u32_t id;
-                    u32_t irq_bios, irq_acpi;
-                    u32_t irq_pin;
-                    u16_t pcicmd;
-                    u32_t tmp;
-
-                    u32_t devfn = (dev<<3 )|fn;
-
-                    id = PciRead32(bus,devfn, PCI_VENDOR_ID);
-
-    /* some broken boards return 0 or ~0 if a slot is empty: */
-                if (id == 0xffffffff || id == 0x00000000 ||
-                    id == 0x0000ffff || id == 0xffff0000)
-                    continue;
-
-                pcicmd = PciRead16(bus,devfn, PCI_COMMAND);
-                if (! pcicmd & PCI_COMMAND_IO)
-                    continue;
-
-                tmp = PciRead32(bus,devfn, 0x3C);
-
-                irq_bios = tmp & 0xFF;
-                irq_pin  = (tmp >> 8) & 0xFF;
-
-                int slot = (fn >> 3) & 0x1f;
-
-                irq_acpi = irqtable[ dev * PCI_MAX_PINS +(irq_pin-1) ];
-
-                if( irq_acpi < 0)
-                    dbgprintf("PCI: no ACPI IRQ routing for "
-                    "device %d.%d.%d INT%c\n",bus,dev,fn,'A'+irq_pin-1);
-
-                dbgprintf("pci device %x_%x bus %d dev %d fn %d,"
-                          "IRQ PIN %d BIOS IRQ %d ACPI IRQ %d\n",
-                          id & 0xFFFF, id>>16, bus, dev, fn, irq_pin, irq_bios, irq_acpi);
-                };
-            }
-        };
-    };
-#endif
-
-
 #if 0
 
 ACPI_STATUS
diff --git a/drivers/devman/acpi_bus.h b/drivers/devman/acpi_bus.h
index 4b866336ed..7ec4eeb0ab 100644
--- a/drivers/devman/acpi_bus.h
+++ b/drivers/devman/acpi_bus.h
@@ -1,4 +1,37 @@
 
+struct acpi_device;
+
+
+/*
+ * ACPI Driver
+ * -----------
+ */
+
+typedef int (*acpi_op_add) (struct acpi_device * device);
+typedef int (*acpi_op_remove) (struct acpi_device * device, int type);
+typedef int (*acpi_op_start) (struct acpi_device * device);
+//typedef int (*acpi_op_suspend) (struct acpi_device * device,
+//                pm_message_t state);
+typedef int (*acpi_op_resume) (struct acpi_device * device);
+typedef int (*acpi_op_bind) (struct acpi_device * device);
+typedef int (*acpi_op_unbind) (struct acpi_device * device);
+typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event);
+
+struct acpi_bus_ops {
+    u32 acpi_op_add:1;
+    u32 acpi_op_start:1;
+};
+
+struct acpi_device_ops {
+    acpi_op_add add;
+    acpi_op_remove remove;
+    acpi_op_start start;
+//    acpi_op_suspend suspend;
+    acpi_op_resume resume;
+    acpi_op_bind bind;
+    acpi_op_unbind unbind;
+    acpi_op_notify notify;
+};
 
 struct resource_list {
     struct resource_list *next;
@@ -36,12 +69,6 @@ enum acpi_bus_device_type {
 #define ACPI_SMBUS_IBM_HID      "SMBUSIBM"
 
 
-struct acpi_bus_ops
-{
-    u32_t acpi_op_add:1;
-    u32_t acpi_op_start:1;
-};
-
 
 #define ACPI_ID_LEN     16 /* only 9 bytes needed here, 16 bytes are used */
                            /* to workaround crosscompile issues */
@@ -106,7 +133,7 @@ struct acpi_device
 //    struct acpi_device_wakeup wakeup;
 //    struct acpi_device_perf performance;
 //    struct acpi_device_dir dir;
-//    struct acpi_device_ops ops;
+    struct acpi_device_ops ops;
 //    struct acpi_driver *driver;
     void *driver_data;
 //    struct device dev;
@@ -115,6 +142,16 @@ struct acpi_device
 };
 
 
+struct acpi_pci_root {
+    struct list_head node;
+    struct acpi_device * device;
+    struct acpi_pci_id id;
+    struct pci_bus *bus;
+    u16 segment;
+    struct resource secondary;      /* downstream bus range */
+
+};
+
 
 #define acpi_device_bid(d)  ((d)->pnp.bus_id)
 #define acpi_device_adr(d)  ((d)->pnp.bus_address)
@@ -126,3 +163,7 @@ int acpi_match_device_ids(struct acpi_device *device,
               const struct acpi_device_ids *ids);
 
 int acpi_pci_irq_add_prt(ACPI_HANDLE handle, struct pci_bus *bus);
+int acpi_pci_bind_root(struct acpi_device *device);
+struct pci_dev *acpi_get_pci_dev(ACPI_HANDLE handle);
+int acpi_is_root_bridge(ACPI_HANDLE handle);
+
diff --git a/drivers/devman/pci/pci.c b/drivers/devman/pci/pci.c
index 7c0e4bf0c6..23f236b494 100644
--- a/drivers/devman/pci/pci.c
+++ b/drivers/devman/pci/pci.c
@@ -7,7 +7,8 @@
 
 LIST_HEAD(pci_root_buses);
 
-#define IO_SPACE_LIMIT 0xffff
+#define IO_SPACE_LIMIT          0xffff
+#define PCIBIOS_SUCCESSFUL      0x00
 
 struct resource ioport_resource = {
     .name   = "PCI IO",
@@ -23,13 +24,90 @@ struct resource iomem_resource = {
     .flags  = IORESOURCE_MEM,
 };
 
+#define PCI_FIND_CAP_TTL    48
 
-static inline int pci_domain_nr(struct pci_bus *bus)
+static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
+                   u8 pos, int cap, int *ttl)
 {
-    struct pci_sysdata *sd = bus->sysdata;
-    return sd->domain;
+    u8 id;
+
+    while ((*ttl)--) {
+        pci_bus_read_config_byte(bus, devfn, pos, &pos);
+        if (pos < 0x40)
+            break;
+        pos &= ~3;
+        pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID,
+                     &id);
+        if (id == 0xff)
+            break;
+        if (id == cap)
+            return pos;
+        pos += PCI_CAP_LIST_NEXT;
+    }
+    return 0;
 }
 
+static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn,
+                   u8 pos, int cap)
+{
+    int ttl = PCI_FIND_CAP_TTL;
+
+    return __pci_find_next_cap_ttl(bus, devfn, pos, cap, &ttl);
+}
+static int __pci_bus_find_cap_start(struct pci_bus *bus,
+                    unsigned int devfn, u8 hdr_type)
+{
+    u16 status;
+
+    pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status);
+    if (!(status & PCI_STATUS_CAP_LIST))
+        return 0;
+
+    switch (hdr_type) {
+    case PCI_HEADER_TYPE_NORMAL:
+    case PCI_HEADER_TYPE_BRIDGE:
+        return PCI_CAPABILITY_LIST;
+    case PCI_HEADER_TYPE_CARDBUS:
+        return PCI_CB_CAPABILITY_LIST;
+    default:
+        return 0;
+    }
+
+    return 0;
+}
+
+
+/**
+ * pci_find_capability - query for devices' capabilities
+ * @dev: PCI device to query
+ * @cap: capability code
+ *
+ * Tell if a device supports a given PCI capability.
+ * Returns the address of the requested capability structure within the
+ * device's PCI configuration space or 0 in case the device does not
+ * support it.  Possible values for @cap:
+ *
+ *  %PCI_CAP_ID_PM           Power Management
+ *  %PCI_CAP_ID_AGP          Accelerated Graphics Port
+ *  %PCI_CAP_ID_VPD          Vital Product Data
+ *  %PCI_CAP_ID_SLOTID       Slot Identification
+ *  %PCI_CAP_ID_MSI          Message Signalled Interrupts
+ *  %PCI_CAP_ID_CHSWP        CompactPCI HotSwap
+ *  %PCI_CAP_ID_PCIX         PCI-X
+ *  %PCI_CAP_ID_EXP          PCI Express
+ */
+int pci_find_capability(struct pci_dev *dev, int cap)
+{
+    int pos;
+
+    pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type);
+    if (pos)
+        pos = __pci_find_next_cap(dev->bus, dev->devfn, pos, cap);
+
+    return pos;
+}
+
+
 static struct pci_bus * pci_alloc_bus(void)
 {
     struct pci_bus *b;
@@ -149,3 +227,92 @@ pci_find_next_bus(const struct pci_bus *from)
 }
 
 
+/**
+ * pci_get_slot - locate PCI device for a given PCI slot
+ * @bus: PCI bus on which desired PCI device resides
+ * @devfn: encodes number of PCI slot in which the desired PCI
+ * device resides and the logical device number within that slot
+ * in case of multi-function devices.
+ *
+ * Given a PCI bus and slot/function number, the desired PCI device
+ * is located in the list of PCI devices.
+ * If the device is found, its reference count is increased and this
+ * function returns a pointer to its data structure.  The caller must
+ * decrement the reference count by calling pci_dev_put().
+ * If no device is found, %NULL is returned.
+ */
+struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn)
+{
+    struct list_head *tmp;
+    struct pci_dev *dev;
+
+//    WARN_ON(in_interrupt());
+//    down_read(&pci_bus_sem);
+
+    list_for_each(tmp, &bus->devices) {
+        dev = pci_dev_b(tmp);
+        if (dev->devfn == devfn)
+            goto out;
+    }
+
+    dev = NULL;
+ out:
+//    pci_dev_get(dev);
+//    up_read(&pci_bus_sem);
+    return dev;
+}
+
+
+
+
+/**
+ * pci_find_ext_capability - Find an extended capability
+ * @dev: PCI device to query
+ * @cap: capability code
+ *
+ * Returns the address of the requested extended capability structure
+ * within the device's PCI configuration space or 0 if the device does
+ * not support it.  Possible values for @cap:
+ *
+ *  %PCI_EXT_CAP_ID_ERR     Advanced Error Reporting
+ *  %PCI_EXT_CAP_ID_VC      Virtual Channel
+ *  %PCI_EXT_CAP_ID_DSN     Device Serial Number
+ *  %PCI_EXT_CAP_ID_PWR     Power Budgeting
+ */
+int pci_find_ext_capability(struct pci_dev *dev, int cap)
+{
+    u32 header;
+    int ttl;
+    int pos = PCI_CFG_SPACE_SIZE;
+
+    /* minimum 8 bytes per capability */
+    ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
+
+    if (dev->cfg_size <= PCI_CFG_SPACE_SIZE)
+        return 0;
+
+    if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL)
+        return 0;
+
+    /*
+     * If we have no capabilities, this is indicated by cap ID,
+     * cap version and next pointer all being 0.
+     */
+    if (header == 0)
+        return 0;
+
+    while (ttl-- > 0) {
+        if (PCI_EXT_CAP_ID(header) == cap)
+            return pos;
+
+        pos = PCI_EXT_CAP_NEXT(header);
+        if (pos < PCI_CFG_SPACE_SIZE)
+            break;
+
+        if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL)
+            break;
+    }
+
+    return 0;
+}
+
diff --git a/drivers/devman/pci/probe.c b/drivers/devman/pci/probe.c
new file mode 100644
index 0000000000..946ea53855
--- /dev/null
+++ b/drivers/devman/pci/probe.c
@@ -0,0 +1,419 @@
+
+#include <ddk.h>
+#include <linux/errno.h>
+#include <mutex.h>
+#include <pci.h>
+#include <syscall.h>
+
+
+#define LEGACY_IO_RESOURCE  (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
+
+/**
+ * pci_setup_device - fill in class and map information of a device
+ * @dev: the device structure to fill
+ *
+ * Initialize the device structure with information about the device's
+ * vendor,class,memory and IO-space addresses,IRQ lines etc.
+ * Called at initialisation of the PCI subsystem and by CardBus services.
+ * Returns 0 on success and negative if unknown type of device (not normal,
+ * bridge or CardBus).
+ */
+int pci_setup_device(struct pci_dev *dev)
+{
+    u32 class;
+    u8 hdr_type;
+    struct pci_slot *slot;
+    int pos = 0;
+
+    if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type))
+        return -EIO;
+
+    dev->sysdata = dev->bus->sysdata;
+//    dev->dev.parent = dev->bus->bridge;
+//    dev->dev.bus = &pci_bus_type;
+    dev->hdr_type = hdr_type & 0x7f;
+    dev->multifunction = !!(hdr_type & 0x80);
+    dev->error_state = pci_channel_io_normal;
+    set_pcie_port_type(dev);
+
+    list_for_each_entry(slot, &dev->bus->slots, list)
+        if (PCI_SLOT(dev->devfn) == slot->number)
+            dev->slot = slot;
+
+    /* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer)
+       set this higher, assuming the system even supports it.  */
+    dev->dma_mask = 0xffffffff;
+
+//    dev_set_name(&dev->dev, "%04x:%02x:%02x.%d", pci_domain_nr(dev->bus),
+//             dev->bus->number, PCI_SLOT(dev->devfn),
+//             PCI_FUNC(dev->devfn));
+
+    pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
+    dev->revision = class & 0xff;
+    class >>= 8;                    /* upper 3 bytes */
+    dev->class = class;
+    class >>= 8;
+
+    dbgprintf("found [%04x:%04x] class %06x header type %02x\n",
+         dev->vendor, dev->device, class, dev->hdr_type);
+
+    /* need to have dev->class ready */
+    dev->cfg_size = pci_cfg_space_size(dev);
+
+    /* "Unknown power state" */
+    dev->current_state = PCI_UNKNOWN;
+
+    /* Early fixups, before probing the BARs */
+//    pci_fixup_device(pci_fixup_early, dev);
+    /* device class may be changed after fixup */
+    class = dev->class >> 8;
+
+    switch (dev->hdr_type) {            /* header type */
+    case PCI_HEADER_TYPE_NORMAL:            /* standard header */
+        if (class == PCI_CLASS_BRIDGE_PCI)
+            goto bad;
+        pci_read_irq(dev);
+        pci_read_bases(dev, 6, PCI_ROM_ADDRESS);
+        pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
+        pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device);
+
+        /*
+         *  Do the ugly legacy mode stuff here rather than broken chip
+         *  quirk code. Legacy mode ATA controllers have fixed
+         *  addresses. These are not always echoed in BAR0-3, and
+         *  BAR0-3 in a few cases contain junk!
+         */
+        if (class == PCI_CLASS_STORAGE_IDE) {
+            u8 progif;
+            pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
+            if ((progif & 1) == 0) {
+                dev->resource[0].start = 0x1F0;
+                dev->resource[0].end = 0x1F7;
+                dev->resource[0].flags = LEGACY_IO_RESOURCE;
+                dev->resource[1].start = 0x3F6;
+                dev->resource[1].end = 0x3F6;
+                dev->resource[1].flags = LEGACY_IO_RESOURCE;
+            }
+            if ((progif & 4) == 0) {
+                dev->resource[2].start = 0x170;
+                dev->resource[2].end = 0x177;
+                dev->resource[2].flags = LEGACY_IO_RESOURCE;
+                dev->resource[3].start = 0x376;
+                dev->resource[3].end = 0x376;
+                dev->resource[3].flags = LEGACY_IO_RESOURCE;
+            }
+        }
+        break;
+
+    case PCI_HEADER_TYPE_BRIDGE:            /* bridge header */
+        if (class != PCI_CLASS_BRIDGE_PCI)
+            goto bad;
+        /* The PCI-to-PCI bridge spec requires that subtractive
+           decoding (i.e. transparent) bridge must have programming
+           interface code of 0x01. */
+        pci_read_irq(dev);
+        dev->transparent = ((dev->class & 0xff) == 1);
+        pci_read_bases(dev, 2, PCI_ROM_ADDRESS1);
+        set_pcie_hotplug_bridge(dev);
+        pos = pci_find_capability(dev, PCI_CAP_ID_SSVID);
+        if (pos) {
+            pci_read_config_word(dev, pos + PCI_SSVID_VENDOR_ID, &dev->subsystem_vendor);
+            pci_read_config_word(dev, pos + PCI_SSVID_DEVICE_ID, &dev->subsystem_device);
+        }
+        break;
+
+    case PCI_HEADER_TYPE_CARDBUS:           /* CardBus bridge header */
+        if (class != PCI_CLASS_BRIDGE_CARDBUS)
+            goto bad;
+        pci_read_irq(dev);
+        pci_read_bases(dev, 1, 0);
+        pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
+        pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device);
+        break;
+
+    default:                    /* unknown header */
+        dbgprintf("unknown header type %02x, "
+            "ignoring device\n", dev->hdr_type);
+        return -EIO;
+
+    bad:
+        dbgprintf("ignoring class %02x (doesn't match header "
+            "type %02x)\n", class, dev->hdr_type);
+        dev->class = PCI_CLASS_NOT_DEFINED;
+    }
+
+    /* We found a fine healthy device, go go go... */
+    return 0;
+}
+
+
+
+struct pci_dev *alloc_pci_dev(void)
+{
+    struct pci_dev *dev;
+
+    dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
+    if (!dev)
+        return NULL;
+
+    INIT_LIST_HEAD(&dev->bus_list);
+
+    return dev;
+}
+
+/*
+ * Read the config data for a PCI device, sanity-check it
+ * and fill in the dev structure...
+ */
+static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
+{
+    struct pci_dev *dev;
+    u32 l;
+    int timeout = 10;
+
+    if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
+        return NULL;
+
+    /* some broken boards return 0 or ~0 if a slot is empty: */
+    if (l == 0xffffffff || l == 0x00000000 ||
+        l == 0x0000ffff || l == 0xffff0000)
+        return NULL;
+
+    /* Configuration request Retry Status */
+    while (l == 0xffff0001) {
+        delay(timeout/10);
+        timeout *= 2;
+        if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
+            return NULL;
+        /* Card hasn't responded in 60 seconds?  Must be stuck. */
+        if (delay > 60 * 1000) {
+            printk(KERN_WARNING "pci %04x:%02x:%02x.%d: not "
+                    "responding\n", pci_domain_nr(bus),
+                    bus->number, PCI_SLOT(devfn),
+                    PCI_FUNC(devfn));
+            return NULL;
+        }
+    }
+
+    dev = alloc_pci_dev();
+    if (!dev)
+        return NULL;
+
+    dev->bus = bus;
+    dev->devfn = devfn;
+    dev->vendor = l & 0xffff;
+    dev->device = (l >> 16) & 0xffff;
+
+    if (pci_setup_device(dev)) {
+        kfree(dev);
+        return NULL;
+    }
+
+    return dev;
+}
+
+
+struct pci_dev * pci_scan_single_device(struct pci_bus *bus, int devfn)
+{
+    struct pci_dev *dev;
+
+    dev = pci_get_slot(bus, devfn);
+    if (dev) {
+//        pci_dev_put(dev);
+        return dev;
+    }
+
+    dev = pci_scan_device(bus, devfn);
+    if (!dev)
+        return NULL;
+
+    pci_device_add(dev, bus);
+
+    return dev;
+}
+
+static unsigned next_ari_fn(struct pci_dev *dev, unsigned fn)
+{
+    u16 cap;
+    unsigned pos, next_fn;
+
+    if (!dev)
+        return 0;
+
+    pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
+    if (!pos)
+        return 0;
+    pci_read_config_word(dev, pos + 4, &cap);
+    next_fn = cap >> 8;
+    if (next_fn <= fn)
+        return 0;
+    return next_fn;
+}
+
+static unsigned next_trad_fn(struct pci_dev *dev, unsigned fn)
+{
+    return (fn + 1) % 8;
+}
+
+static unsigned no_next_fn(struct pci_dev *dev, unsigned fn)
+{
+    return 0;
+}
+
+static int only_one_child(struct pci_bus *bus)
+{
+    struct pci_dev *parent = bus->self;
+    if (!parent || !pci_is_pcie(parent))
+        return 0;
+    if (parent->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
+        parent->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
+        return 1;
+    return 0;
+}
+
+/**
+ * pci_scan_slot - scan a PCI slot on a bus for devices.
+ * @bus: PCI bus to scan
+ * @devfn: slot number to scan (must have zero function.)
+ *
+ * Scan a PCI slot on the specified PCI bus for devices, adding
+ * discovered devices to the @bus->devices list.  New devices
+ * will not have is_added set.
+ *
+ * Returns the number of new devices found.
+ */
+int pci_scan_slot(struct pci_bus *bus, int devfn)
+{
+    unsigned fn, nr = 0;
+    struct pci_dev *dev;
+    unsigned (*next_fn)(struct pci_dev *, unsigned) = no_next_fn;
+
+    if (only_one_child(bus) && (devfn > 0))
+        return 0; /* Already scanned the entire slot */
+
+    dev = pci_scan_single_device(bus, devfn);
+    if (!dev)
+        return 0;
+    if (!dev->is_added)
+        nr++;
+
+    if (pci_ari_enabled(bus))
+        next_fn = next_ari_fn;
+    else if (dev->multifunction)
+        next_fn = next_trad_fn;
+
+    for (fn = next_fn(dev, 0); fn > 0; fn = next_fn(dev, fn)) {
+        dev = pci_scan_single_device(bus, devfn + fn);
+        if (dev) {
+            if (!dev->is_added)
+                nr++;
+            dev->multifunction = 1;
+        }
+    }
+
+    /* only one slot has pcie device */
+    if (bus->self && nr)
+        pcie_aspm_init_link_state(bus->self);
+
+    return nr;
+}
+
+
+unsigned int pci_scan_child_bus(struct pci_bus *bus)
+{
+    unsigned int devfn, pass, max = bus->secondary;
+    struct pci_dev *dev;
+
+    dbgprintf("scanning bus\n");
+
+    /* Go find them, Rover! */
+    for (devfn = 0; devfn < 0x100; devfn += 8)
+        pci_scan_slot(bus, devfn);
+
+    /* Reserve buses for SR-IOV capability. */
+    max += pci_iov_bus_range(bus);
+
+    /*
+     * After performing arch-dependent fixup of the bus, look behind
+     * all PCI-to-PCI bridges on this bus.
+     */
+    if (!bus->is_added) {
+        dbgprintf("fixups for bus\n");
+        pcibios_fixup_bus(bus);
+        if (pci_is_root_bus(bus))
+            bus->is_added = 1;
+    }
+
+    for (pass=0; pass < 2; pass++)
+        list_for_each_entry(dev, &bus->devices, bus_list) {
+            if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+                dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+                max = pci_scan_bridge(bus, dev, max, pass);
+        }
+
+    /*
+     * We've scanned the bus and so we know all about what's on
+     * the other side of any bridges that may be on this bus plus
+     * any devices.
+     *
+     * Return how far we've got finding sub-buses.
+     */
+    dbgprintf("bus scan returning with max=%02x\n", max);
+    return max;
+}
+
+/**
+ * pci_cfg_space_size - get the configuration space size of the PCI device.
+ * @dev: PCI device
+ *
+ * Regular PCI devices have 256 bytes, but PCI-X 2 and PCI Express devices
+ * have 4096 bytes.  Even if the device is capable, that doesn't mean we can
+ * access it.  Maybe we don't have a way to generate extended config space
+ * accesses, or the device is behind a reverse Express bridge.  So we try
+ * reading the dword at 0x100 which must either be 0 or a valid extended
+ * capability header.
+ */
+int pci_cfg_space_size_ext(struct pci_dev *dev)
+{
+    u32 status;
+    int pos = PCI_CFG_SPACE_SIZE;
+
+    if (pci_read_config_dword(dev, pos, &status) != PCIBIOS_SUCCESSFUL)
+        goto fail;
+    if (status == 0xffffffff)
+        goto fail;
+
+    return PCI_CFG_SPACE_EXP_SIZE;
+
+ fail:
+    return PCI_CFG_SPACE_SIZE;
+}
+
+int pci_cfg_space_size(struct pci_dev *dev)
+{
+    int pos;
+    u32 status;
+    u16 class;
+
+    class = dev->class >> 8;
+    if (class == PCI_CLASS_BRIDGE_HOST)
+        return pci_cfg_space_size_ext(dev);
+
+    pos = pci_pcie_cap(dev);
+    if (!pos) {
+        pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+        if (!pos)
+            goto fail;
+
+        pci_read_config_dword(dev, pos + PCI_X_STATUS, &status);
+        if (!(status & (PCI_X_STATUS_266MHZ | PCI_X_STATUS_533MHZ)))
+            goto fail;
+    }
+
+    return pci_cfg_space_size_ext(dev);
+
+ fail:
+    return PCI_CFG_SPACE_SIZE;
+}
+
+
diff --git a/drivers/devman/pci_bind.c b/drivers/devman/pci_bind.c
new file mode 100644
index 0000000000..02a6978dd0
--- /dev/null
+++ b/drivers/devman/pci_bind.c
@@ -0,0 +1,98 @@
+
+#include <ddk.h>
+#include <linux/errno.h>
+#include <mutex.h>
+#include <pci.h>
+#include <syscall.h>
+
+#include "acpi.h"
+#include "acpi_bus.h"
+
+
+#define PREFIX "ACPI: "
+
+
+static int acpi_pci_unbind(struct acpi_device *device)
+{
+    struct pci_dev *dev;
+
+    dev = acpi_get_pci_dev(device->handle);
+    if (!dev)
+        goto out;
+
+//    device_set_run_wake(&dev->dev, false);
+//    pci_acpi_remove_pm_notifier(device);
+
+    if (!dev->subordinate)
+        goto out;
+
+//    acpi_pci_irq_del_prt(dev->subordinate);
+
+    device->ops.bind = NULL;
+    device->ops.unbind = NULL;
+
+out:
+//    pci_dev_put(dev);
+    return 0;
+}
+
+static int acpi_pci_bind(struct acpi_device *device)
+{
+    ACPI_STATUS status;
+    ACPI_HANDLE handle;
+    struct pci_bus *bus;
+    struct pci_dev *dev;
+
+    dev = acpi_get_pci_dev(device->handle);
+    if (!dev)
+        return 0;
+
+//    pci_acpi_add_pm_notifier(device, dev);
+//    if (device->wakeup.flags.run_wake)
+//        device_set_run_wake(&dev->dev, true);
+
+    /*
+     * Install the 'bind' function to facilitate callbacks for
+     * children of the P2P bridge.
+     */
+    if (dev->subordinate) {
+        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                  "Device %04x:%02x:%02x.%d is a PCI bridge\n",
+                  pci_domain_nr(dev->bus), dev->bus->number,
+                  PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)));
+        device->ops.bind = acpi_pci_bind;
+        device->ops.unbind = acpi_pci_unbind;
+    }
+
+    /*
+     * Evaluate and parse _PRT, if exists.  This code allows parsing of
+     * _PRT objects within the scope of non-bridge devices.  Note that
+     * _PRTs within the scope of a PCI bridge assume the bridge's
+     * subordinate bus number.
+     *
+     * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
+     */
+    status = AcpiGetHandle(device->handle, METHOD_NAME__PRT, &handle);
+    if (ACPI_FAILURE(status))
+        goto out;
+
+    if (dev->subordinate)
+        bus = dev->subordinate;
+    else
+        bus = dev->bus;
+
+    acpi_pci_irq_add_prt(device->handle, bus);
+
+out:
+//    pci_dev_put(dev);
+    return 0;
+}
+
+int acpi_pci_bind_root(struct acpi_device *device)
+{
+    device->ops.bind = acpi_pci_bind;
+    device->ops.unbind = acpi_pci_unbind;
+
+    return 0;
+}
+
diff --git a/drivers/devman/pci_root.c b/drivers/devman/pci_root.c
new file mode 100644
index 0000000000..85b3aa38b1
--- /dev/null
+++ b/drivers/devman/pci_root.c
@@ -0,0 +1,149 @@
+
+#include <ddk.h>
+#include <linux/errno.h>
+#include <mutex.h>
+#include <pci.h>
+#include <syscall.h>
+
+#include "acpi.h"
+#include "acpi_bus.h"
+
+
+#define PREFIX "ACPI: "
+
+
+struct acpi_handle_node {
+    struct list_head node;
+    ACPI_HANDLE handle;
+};
+
+static const struct acpi_device_ids root_device_ids[] = {
+    {"PNP0A03", 0},
+    {"", 0},
+};
+
+static LIST_HEAD(acpi_pci_roots);
+
+
+/**
+ * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge
+ * @handle - the ACPI CA node in question.
+ *
+ * Note: we could make this API take a struct acpi_device * instead, but
+ * for now, it's more convenient to operate on an acpi_handle.
+ */
+int acpi_is_root_bridge(ACPI_HANDLE handle)
+{
+    int ret;
+    struct acpi_device *device;
+
+    ret = acpi_bus_get_device(handle, &device);
+    if (ret)
+        return 0;
+
+    ret = acpi_match_device_ids(device, root_device_ids);
+    if (ret)
+        return 0;
+    else
+        return 1;
+}
+
+
+struct acpi_pci_root *acpi_pci_find_root(ACPI_HANDLE handle)
+{
+    struct acpi_pci_root *root;
+
+    list_for_each_entry(root, &acpi_pci_roots, node) {
+        if (root->device->handle == handle)
+            return root;
+    }
+    return NULL;
+}
+
+
+/**
+ * acpi_get_pci_dev - convert ACPI CA handle to struct pci_dev
+ * @handle: the handle in question
+ *
+ * Given an ACPI CA handle, the desired PCI device is located in the
+ * list of PCI devices.
+ *
+ * If the device is found, its reference count is increased and this
+ * function returns a pointer to its data structure.  The caller must
+ * decrement the reference count by calling pci_dev_put().
+ * If no device is found, %NULL is returned.
+ */
+struct pci_dev *acpi_get_pci_dev(ACPI_HANDLE handle)
+{
+    int dev, fn;
+    unsigned long long adr;
+    ACPI_STATUS status;
+    ACPI_HANDLE phandle;
+    struct pci_bus *pbus;
+    struct pci_dev *pdev = NULL;
+    struct acpi_handle_node *node, *tmp;
+    struct acpi_pci_root *root;
+    LIST_HEAD(device_list);
+
+    /*
+     * Walk up the ACPI CA namespace until we reach a PCI root bridge.
+     */
+    phandle = handle;
+    while (!acpi_is_root_bridge(phandle)) {
+        node = kzalloc(sizeof(struct acpi_handle_node), GFP_KERNEL);
+        if (!node)
+            goto out;
+
+        INIT_LIST_HEAD(&node->node);
+        node->handle = phandle;
+        list_add(&node->node, &device_list);
+
+        status = AcpiGetParent(phandle, &phandle);
+        if (ACPI_FAILURE(status))
+            goto out;
+    }
+
+    root = acpi_pci_find_root(phandle);
+    if (!root)
+        goto out;
+
+    pbus = root->bus;
+
+    /*
+     * Now, walk back down the PCI device tree until we return to our
+     * original handle. Assumes that everything between the PCI root
+     * bridge and the device we're looking for must be a P2P bridge.
+     */
+    list_for_each_entry(node, &device_list, node) {
+        ACPI_HANDLE hnd = node->handle;
+        status = acpi_evaluate_integer(hnd, "_ADR", NULL, &adr);
+        if (ACPI_FAILURE(status))
+            goto out;
+        dev = (adr >> 16) & 0xffff;
+        fn  = adr & 0xffff;
+
+        pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn));
+        if (!pdev || hnd == handle)
+            break;
+
+        pbus = pdev->subordinate;
+//        pci_dev_put(pdev);
+
+        /*
+         * This function may be called for a non-PCI device that has a
+         * PCI parent (eg. a disk under a PCI SATA controller).  In that
+         * case pdev->subordinate will be NULL for the parent.
+         */
+        if (!pbus) {
+            dbgprintf("Not a PCI-to-PCI bridge\n");
+            pdev = NULL;
+            break;
+        }
+    }
+out:
+    list_for_each_entry_safe(node, tmp, &device_list, node)
+        kfree(node);
+
+    return pdev;
+}
+
diff --git a/drivers/devman/scan.c b/drivers/devman/scan.c
index 651c5442bf..2afd34f6b1 100644
--- a/drivers/devman/scan.c
+++ b/drivers/devman/scan.c
@@ -626,10 +626,10 @@ static int acpi_add_single_object(struct acpi_device **child,
     /*
      * Bind _ADR-Based Devices when hot add
      */
-//    if (device->flags.bus_address) {
-//        if (device->parent && device->parent->ops.bind)
-//            device->parent->ops.bind(device);
-//    }
+    if (device->flags.bus_address) {
+        if (device->parent && device->parent->ops.bind)
+            device->parent->ops.bind(device);
+    }
 
 end:
     if (!result) {
diff --git a/drivers/devman/scan.cc b/drivers/devman/scan.cc
new file mode 100644
index 0000000000..e5047e710e
--- /dev/null
+++ b/drivers/devman/scan.cc
@@ -0,0 +1,1557 @@
+/*
+ * scan.c - support for transforming the ACPI namespace into individual objects
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/acpi.h>
+#include <linux/signal.h>
+#include <linux/kthread.h>
+#include <linux/dmi.h>
+
+#include <acpi/acpi_drivers.h>
+
+#include "internal.h"
+
+#define _COMPONENT		ACPI_BUS_COMPONENT
+ACPI_MODULE_NAME("scan");
+#define STRUCT_TO_INT(s)	(*((int*)&s))
+extern struct acpi_device *acpi_root;
+
+#define ACPI_BUS_CLASS			"system_bus"
+#define ACPI_BUS_HID			"LNXSYBUS"
+#define ACPI_BUS_DEVICE_NAME		"System Bus"
+
+#define ACPI_IS_ROOT_DEVICE(device)    (!(device)->parent)
+
+static LIST_HEAD(acpi_device_list);
+static LIST_HEAD(acpi_bus_id_list);
+DEFINE_MUTEX(acpi_device_lock);
+LIST_HEAD(acpi_wakeup_device_list);
+
+struct acpi_device_bus_id{
+	char bus_id[15];
+	unsigned int instance_no;
+	struct list_head node;
+};
+
+/*
+ * Creates hid/cid(s) string needed for modalias and uevent
+ * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
+ * char *modalias: "acpi:IBM0001:ACPI0001"
+*/
+static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
+			   int size)
+{
+	int len;
+	int count;
+	struct acpi_hardware_id *id;
+
+	len = snprintf(modalias, size, "acpi:");
+	size -= len;
+
+	list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
+		count = snprintf(&modalias[len], size, "%s:", id->id);
+		if (count < 0 || count >= size)
+			return -EINVAL;
+		len += count;
+		size -= count;
+	}
+
+	modalias[len] = '\0';
+	return len;
+}
+
+static ssize_t
+acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) {
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+	int len;
+
+	/* Device has no HID and no CID or string is >1024 */
+	len = create_modalias(acpi_dev, buf, 1024);
+	if (len <= 0)
+		return 0;
+	buf[len++] = '\n';
+	return len;
+}
+static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
+
+static void acpi_bus_hot_remove_device(void *context)
+{
+	struct acpi_device *device;
+	acpi_handle handle = context;
+	struct acpi_object_list arg_list;
+	union acpi_object arg;
+	acpi_status status = AE_OK;
+
+	if (acpi_bus_get_device(handle, &device))
+		return;
+
+	if (!device)
+		return;
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+		"Hot-removing device %s...\n", dev_name(&device->dev)));
+
+	if (acpi_bus_trim(device, 1)) {
+		printk(KERN_ERR PREFIX
+				"Removing device failed\n");
+		return;
+	}
+
+	/* power off device */
+	status = acpi_evaluate_object(handle, "_PS3", NULL, NULL);
+	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
+		printk(KERN_WARNING PREFIX
+				"Power-off device failed\n");
+
+	if (device->flags.lockable) {
+		arg_list.count = 1;
+		arg_list.pointer = &arg;
+		arg.type = ACPI_TYPE_INTEGER;
+		arg.integer.value = 0;
+		acpi_evaluate_object(handle, "_LCK", &arg_list, NULL);
+	}
+
+	arg_list.count = 1;
+	arg_list.pointer = &arg;
+	arg.type = ACPI_TYPE_INTEGER;
+	arg.integer.value = 1;
+
+	/*
+	 * TBD: _EJD support.
+	 */
+	status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
+	if (ACPI_FAILURE(status))
+		printk(KERN_WARNING PREFIX
+				"Eject device failed\n");
+
+	return;
+}
+
+static ssize_t
+acpi_eject_store(struct device *d, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int ret = count;
+	acpi_status status;
+	acpi_object_type type = 0;
+	struct acpi_device *acpi_device = to_acpi_device(d);
+
+	if ((!count) || (buf[0] != '1')) {
+		return -EINVAL;
+	}
+#ifndef FORCE_EJECT
+	if (acpi_device->driver == NULL) {
+		ret = -ENODEV;
+		goto err;
+	}
+#endif
+	status = acpi_get_type(acpi_device->handle, &type);
+	if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) {
+		ret = -ENODEV;
+		goto err;
+	}
+
+	acpi_os_hotplug_execute(acpi_bus_hot_remove_device, acpi_device->handle);
+err:
+	return ret;
+}
+
+static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
+
+static ssize_t
+acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf) {
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+	return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev));
+}
+static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
+
+static ssize_t
+acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) {
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+	struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
+	int result;
+
+	result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path);
+	if (result)
+		goto end;
+
+	result = sprintf(buf, "%s\n", (char*)path.pointer);
+	kfree(path.pointer);
+end:
+	return result;
+}
+static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);
+
+static int acpi_device_setup_files(struct acpi_device *dev)
+{
+	acpi_status status;
+	acpi_handle temp;
+	int result = 0;
+
+	/*
+	 * Devices gotten from FADT don't have a "path" attribute
+	 */
+	if (dev->handle) {
+		result = device_create_file(&dev->dev, &dev_attr_path);
+		if (result)
+			goto end;
+	}
+
+	result = device_create_file(&dev->dev, &dev_attr_hid);
+	if (result)
+		goto end;
+
+	result = device_create_file(&dev->dev, &dev_attr_modalias);
+	if (result)
+		goto end;
+
+        /*
+         * If device has _EJ0, 'eject' file is created that is used to trigger
+         * hot-removal function from userland.
+         */
+	status = acpi_get_handle(dev->handle, "_EJ0", &temp);
+	if (ACPI_SUCCESS(status))
+		result = device_create_file(&dev->dev, &dev_attr_eject);
+end:
+	return result;
+}
+
+static void acpi_device_remove_files(struct acpi_device *dev)
+{
+	acpi_status status;
+	acpi_handle temp;
+
+	/*
+	 * If device has _EJ0, 'eject' file is created that is used to trigger
+	 * hot-removal function from userland.
+	 */
+	status = acpi_get_handle(dev->handle, "_EJ0", &temp);
+	if (ACPI_SUCCESS(status))
+		device_remove_file(&dev->dev, &dev_attr_eject);
+
+	device_remove_file(&dev->dev, &dev_attr_modalias);
+	device_remove_file(&dev->dev, &dev_attr_hid);
+	if (dev->handle)
+		device_remove_file(&dev->dev, &dev_attr_path);
+}
+/* --------------------------------------------------------------------------
+			ACPI Bus operations
+   -------------------------------------------------------------------------- */
+
+int acpi_match_device_ids(struct acpi_device *device,
+			  const struct acpi_device_id *ids)
+{
+	const struct acpi_device_id *id;
+	struct acpi_hardware_id *hwid;
+
+	/*
+	 * If the device is not present, it is unnecessary to load device
+	 * driver for it.
+	 */
+	if (!device->status.present)
+		return -ENODEV;
+
+	for (id = ids; id->id[0]; id++)
+		list_for_each_entry(hwid, &device->pnp.ids, list)
+			if (!strcmp((char *) id->id, hwid->id))
+				return 0;
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL(acpi_match_device_ids);
+
+static void acpi_free_ids(struct acpi_device *device)
+{
+	struct acpi_hardware_id *id, *tmp;
+
+	list_for_each_entry_safe(id, tmp, &device->pnp.ids, list) {
+		kfree(id->id);
+		kfree(id);
+	}
+}
+
+static void acpi_device_release(struct device *dev)
+{
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+	acpi_free_ids(acpi_dev);
+	kfree(acpi_dev);
+}
+
+static int acpi_device_suspend(struct device *dev, pm_message_t state)
+{
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+	struct acpi_driver *acpi_drv = acpi_dev->driver;
+
+	if (acpi_drv && acpi_drv->ops.suspend)
+		return acpi_drv->ops.suspend(acpi_dev, state);
+	return 0;
+}
+
+static int acpi_device_resume(struct device *dev)
+{
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+	struct acpi_driver *acpi_drv = acpi_dev->driver;
+
+	if (acpi_drv && acpi_drv->ops.resume)
+		return acpi_drv->ops.resume(acpi_dev);
+	return 0;
+}
+
+static int acpi_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
+
+	return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
+}
+
+static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+	int len;
+
+	if (add_uevent_var(env, "MODALIAS="))
+		return -ENOMEM;
+	len = create_modalias(acpi_dev, &env->buf[env->buflen - 1],
+			      sizeof(env->buf) - env->buflen);
+	if (len >= (sizeof(env->buf) - env->buflen))
+		return -ENOMEM;
+	env->buflen += len;
+	return 0;
+}
+
+static void acpi_device_notify(acpi_handle handle, u32 event, void *data)
+{
+	struct acpi_device *device = data;
+
+	device->driver->ops.notify(device, event);
+}
+
+static acpi_status acpi_device_notify_fixed(void *data)
+{
+	struct acpi_device *device = data;
+
+	/* Fixed hardware devices have no handles */
+	acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device);
+	return AE_OK;
+}
+
+static int acpi_device_install_notify_handler(struct acpi_device *device)
+{
+	acpi_status status;
+
+	if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
+		status =
+		    acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+						     acpi_device_notify_fixed,
+						     device);
+	else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
+		status =
+		    acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
+						     acpi_device_notify_fixed,
+						     device);
+	else
+		status = acpi_install_notify_handler(device->handle,
+						     ACPI_DEVICE_NOTIFY,
+						     acpi_device_notify,
+						     device);
+
+	if (ACPI_FAILURE(status))
+		return -EINVAL;
+	return 0;
+}
+
+static void acpi_device_remove_notify_handler(struct acpi_device *device)
+{
+	if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
+		acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+						acpi_device_notify_fixed);
+	else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
+		acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
+						acpi_device_notify_fixed);
+	else
+		acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
+					   acpi_device_notify);
+}
+
+static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *);
+static int acpi_start_single_object(struct acpi_device *);
+static int acpi_device_probe(struct device * dev)
+{
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+	struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);
+	int ret;
+
+	ret = acpi_bus_driver_init(acpi_dev, acpi_drv);
+	if (!ret) {
+		if (acpi_dev->bus_ops.acpi_op_start)
+			acpi_start_single_object(acpi_dev);
+
+		if (acpi_drv->ops.notify) {
+			ret = acpi_device_install_notify_handler(acpi_dev);
+			if (ret) {
+				if (acpi_drv->ops.remove)
+					acpi_drv->ops.remove(acpi_dev,
+						     acpi_dev->removal_type);
+				return ret;
+			}
+		}
+
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+			"Found driver [%s] for device [%s]\n",
+			acpi_drv->name, acpi_dev->pnp.bus_id));
+		get_device(dev);
+	}
+	return ret;
+}
+
+static int acpi_device_remove(struct device * dev)
+{
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+	struct acpi_driver *acpi_drv = acpi_dev->driver;
+
+	if (acpi_drv) {
+		if (acpi_drv->ops.notify)
+			acpi_device_remove_notify_handler(acpi_dev);
+		if (acpi_drv->ops.remove)
+			acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type);
+	}
+	acpi_dev->driver = NULL;
+	acpi_dev->driver_data = NULL;
+
+	put_device(dev);
+	return 0;
+}
+
+struct bus_type acpi_bus_type = {
+	.name		= "acpi",
+	.suspend	= acpi_device_suspend,
+	.resume		= acpi_device_resume,
+	.match		= acpi_bus_match,
+	.probe		= acpi_device_probe,
+	.remove		= acpi_device_remove,
+	.uevent		= acpi_device_uevent,
+};
+
+static int acpi_device_register(struct acpi_device *device)
+{
+	int result;
+	struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id;
+	int found = 0;
+
+	/*
+	 * Linkage
+	 * -------
+	 * Link this device to its parent and siblings.
+	 */
+	INIT_LIST_HEAD(&device->children);
+	INIT_LIST_HEAD(&device->node);
+	INIT_LIST_HEAD(&device->wakeup_list);
+
+	new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
+	if (!new_bus_id) {
+		printk(KERN_ERR PREFIX "Memory allocation error\n");
+		return -ENOMEM;
+	}
+
+	mutex_lock(&acpi_device_lock);
+	/*
+	 * Find suitable bus_id and instance number in acpi_bus_id_list
+	 * If failed, create one and link it into acpi_bus_id_list
+	 */
+	list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) {
+		if (!strcmp(acpi_device_bus_id->bus_id,
+			    acpi_device_hid(device))) {
+			acpi_device_bus_id->instance_no++;
+			found = 1;
+			kfree(new_bus_id);
+			break;
+		}
+	}
+	if (!found) {
+		acpi_device_bus_id = new_bus_id;
+		strcpy(acpi_device_bus_id->bus_id, acpi_device_hid(device));
+		acpi_device_bus_id->instance_no = 0;
+		list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list);
+	}
+	dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no);
+
+	if (device->parent)
+		list_add_tail(&device->node, &device->parent->children);
+
+	if (device->wakeup.flags.valid)
+		list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list);
+	mutex_unlock(&acpi_device_lock);
+
+	if (device->parent)
+		device->dev.parent = &device->parent->dev;
+	device->dev.bus = &acpi_bus_type;
+	device->dev.release = &acpi_device_release;
+	result = device_register(&device->dev);
+	if (result) {
+		dev_err(&device->dev, "Error registering device\n");
+		goto end;
+	}
+
+	result = acpi_device_setup_files(device);
+	if (result)
+		printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n",
+		       dev_name(&device->dev));
+
+	device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
+	return 0;
+end:
+	mutex_lock(&acpi_device_lock);
+	if (device->parent)
+		list_del(&device->node);
+	list_del(&device->wakeup_list);
+	mutex_unlock(&acpi_device_lock);
+	return result;
+}
+
+static void acpi_device_unregister(struct acpi_device *device, int type)
+{
+	mutex_lock(&acpi_device_lock);
+	if (device->parent)
+		list_del(&device->node);
+
+	list_del(&device->wakeup_list);
+	mutex_unlock(&acpi_device_lock);
+
+	acpi_detach_data(device->handle, acpi_bus_data_handler);
+
+	acpi_device_remove_files(device);
+	device_unregister(&device->dev);
+}
+
+/* --------------------------------------------------------------------------
+                                 Driver Management
+   -------------------------------------------------------------------------- */
+/**
+ * acpi_bus_driver_init - add a device to a driver
+ * @device: the device to add and initialize
+ * @driver: driver for the device
+ *
+ * Used to initialize a device via its device driver.  Called whenever a
+ * driver is bound to a device.  Invokes the driver's add() ops.
+ */
+static int
+acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver)
+{
+	int result = 0;
+
+	if (!device || !driver)
+		return -EINVAL;
+
+	if (!driver->ops.add)
+		return -ENOSYS;
+
+	result = driver->ops.add(device);
+	if (result) {
+		device->driver = NULL;
+		device->driver_data = NULL;
+		return result;
+	}
+
+	device->driver = driver;
+
+	/*
+	 * TBD - Configuration Management: Assign resources to device based
+	 * upon possible configuration and currently allocated resources.
+	 */
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+			  "Driver successfully bound to device\n"));
+	return 0;
+}
+
+static int acpi_start_single_object(struct acpi_device *device)
+{
+	int result = 0;
+	struct acpi_driver *driver;
+
+
+	if (!(driver = device->driver))
+		return 0;
+
+	if (driver->ops.start) {
+		result = driver->ops.start(device);
+		if (result && driver->ops.remove)
+			driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);
+	}
+
+	return result;
+}
+
+/**
+ * acpi_bus_register_driver - register a driver with the ACPI bus
+ * @driver: driver being registered
+ *
+ * Registers a driver with the ACPI bus.  Searches the namespace for all
+ * devices that match the driver's criteria and binds.  Returns zero for
+ * success or a negative error status for failure.
+ */
+int acpi_bus_register_driver(struct acpi_driver *driver)
+{
+	int ret;
+
+	if (acpi_disabled)
+		return -ENODEV;
+	driver->drv.name = driver->name;
+	driver->drv.bus = &acpi_bus_type;
+	driver->drv.owner = driver->owner;
+
+	ret = driver_register(&driver->drv);
+	return ret;
+}
+
+EXPORT_SYMBOL(acpi_bus_register_driver);
+
+/**
+ * acpi_bus_unregister_driver - unregisters a driver with the APIC bus
+ * @driver: driver to unregister
+ *
+ * Unregisters a driver with the ACPI bus.  Searches the namespace for all
+ * devices that match the driver's criteria and unbinds.
+ */
+void acpi_bus_unregister_driver(struct acpi_driver *driver)
+{
+	driver_unregister(&driver->drv);
+}
+
+EXPORT_SYMBOL(acpi_bus_unregister_driver);
+
+/* --------------------------------------------------------------------------
+                                 Device Enumeration
+   -------------------------------------------------------------------------- */
+static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
+{
+	acpi_status status;
+	int ret;
+	struct acpi_device *device;
+
+	/*
+	 * Fixed hardware devices do not appear in the namespace and do not
+	 * have handles, but we fabricate acpi_devices for them, so we have
+	 * to deal with them specially.
+	 */
+	if (handle == NULL)
+		return acpi_root;
+
+	do {
+		status = acpi_get_parent(handle, &handle);
+		if (status == AE_NULL_ENTRY)
+			return NULL;
+		if (ACPI_FAILURE(status))
+			return acpi_root;
+
+		ret = acpi_bus_get_device(handle, &device);
+		if (ret == 0)
+			return device;
+	} while (1);
+}
+
+acpi_status
+acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd)
+{
+	acpi_status status;
+	acpi_handle tmp;
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object *obj;
+
+	status = acpi_get_handle(handle, "_EJD", &tmp);
+	if (ACPI_FAILURE(status))
+		return status;
+
+	status = acpi_evaluate_object(handle, "_EJD", NULL, &buffer);
+	if (ACPI_SUCCESS(status)) {
+		obj = buffer.pointer;
+		status = acpi_get_handle(ACPI_ROOT_OBJECT, obj->string.pointer,
+					 ejd);
+		kfree(buffer.pointer);
+	}
+	return status;
+}
+EXPORT_SYMBOL_GPL(acpi_bus_get_ejd);
+
+void acpi_bus_data_handler(acpi_handle handle, void *context)
+{
+
+	/* TBD */
+
+	return;
+}
+
+static int acpi_bus_get_perf_flags(struct acpi_device *device)
+{
+	device->performance.state = ACPI_STATE_UNKNOWN;
+	return 0;
+}
+
+static acpi_status
+acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device,
+					     union acpi_object *package)
+{
+	int i = 0;
+	union acpi_object *element = NULL;
+
+	if (!device || !package || (package->package.count < 2))
+		return AE_BAD_PARAMETER;
+
+	element = &(package->package.elements[0]);
+	if (!element)
+		return AE_BAD_PARAMETER;
+	if (element->type == ACPI_TYPE_PACKAGE) {
+		if ((element->package.count < 2) ||
+		    (element->package.elements[0].type !=
+		     ACPI_TYPE_LOCAL_REFERENCE)
+		    || (element->package.elements[1].type != ACPI_TYPE_INTEGER))
+			return AE_BAD_DATA;
+		device->wakeup.gpe_device =
+		    element->package.elements[0].reference.handle;
+		device->wakeup.gpe_number =
+		    (u32) element->package.elements[1].integer.value;
+	} else if (element->type == ACPI_TYPE_INTEGER) {
+		device->wakeup.gpe_number = element->integer.value;
+	} else
+		return AE_BAD_DATA;
+
+	element = &(package->package.elements[1]);
+	if (element->type != ACPI_TYPE_INTEGER) {
+		return AE_BAD_DATA;
+	}
+	device->wakeup.sleep_state = element->integer.value;
+
+	if ((package->package.count - 2) > ACPI_MAX_HANDLES) {
+		return AE_NO_MEMORY;
+	}
+	device->wakeup.resources.count = package->package.count - 2;
+	for (i = 0; i < device->wakeup.resources.count; i++) {
+		element = &(package->package.elements[i + 2]);
+		if (element->type != ACPI_TYPE_LOCAL_REFERENCE)
+			return AE_BAD_DATA;
+
+		device->wakeup.resources.handles[i] = element->reference.handle;
+	}
+
+	acpi_gpe_can_wake(device->wakeup.gpe_device, device->wakeup.gpe_number);
+
+	return AE_OK;
+}
+
+static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
+{
+	struct acpi_device_id button_device_ids[] = {
+		{"PNP0C0D", 0},
+		{"PNP0C0C", 0},
+		{"PNP0C0E", 0},
+		{"", 0},
+	};
+	acpi_status status;
+	acpi_event_status event_status;
+
+	device->wakeup.run_wake_count = 0;
+	device->wakeup.flags.notifier_present = 0;
+
+	/* Power button, Lid switch always enable wakeup */
+	if (!acpi_match_device_ids(device, button_device_ids)) {
+		device->wakeup.flags.run_wake = 1;
+		device->wakeup.flags.always_enabled = 1;
+		return;
+	}
+
+	status = acpi_get_gpe_status(device->wakeup.gpe_device,
+					device->wakeup.gpe_number,
+						&event_status);
+	if (status == AE_OK)
+		device->wakeup.flags.run_wake =
+				!!(event_status & ACPI_EVENT_FLAG_HANDLE);
+}
+
+static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
+{
+	acpi_status status = 0;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *package = NULL;
+	int psw_error;
+
+	/* _PRW */
+	status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer);
+	if (ACPI_FAILURE(status)) {
+		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW"));
+		goto end;
+	}
+
+	package = (union acpi_object *)buffer.pointer;
+	status = acpi_bus_extract_wakeup_device_power_package(device, package);
+	if (ACPI_FAILURE(status)) {
+		ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package"));
+		goto end;
+	}
+
+	kfree(buffer.pointer);
+
+	device->wakeup.flags.valid = 1;
+	device->wakeup.prepare_count = 0;
+	acpi_bus_set_run_wake_flags(device);
+	/* Call _PSW/_DSW object to disable its ability to wake the sleeping
+	 * system for the ACPI device with the _PRW object.
+	 * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW.
+	 * So it is necessary to call _DSW object first. Only when it is not
+	 * present will the _PSW object used.
+	 */
+	psw_error = acpi_device_sleep_wake(device, 0, 0, 0);
+	if (psw_error)
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				"error in _DSW or _PSW evaluation\n"));
+
+end:
+	if (ACPI_FAILURE(status))
+		device->flags.wake_capable = 0;
+	return 0;
+}
+
+static int acpi_bus_get_power_flags(struct acpi_device *device)
+{
+	acpi_status status = 0;
+	acpi_handle handle = NULL;
+	u32 i = 0;
+
+
+	/*
+	 * Power Management Flags
+	 */
+	status = acpi_get_handle(device->handle, "_PSC", &handle);
+	if (ACPI_SUCCESS(status))
+		device->power.flags.explicit_get = 1;
+	status = acpi_get_handle(device->handle, "_IRC", &handle);
+	if (ACPI_SUCCESS(status))
+		device->power.flags.inrush_current = 1;
+
+	/*
+	 * Enumerate supported power management states
+	 */
+	for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) {
+		struct acpi_device_power_state *ps = &device->power.states[i];
+		char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' };
+
+		/* Evaluate "_PRx" to se if power resources are referenced */
+		acpi_evaluate_reference(device->handle, object_name, NULL,
+					&ps->resources);
+		if (ps->resources.count) {
+			device->power.flags.power_resources = 1;
+			ps->flags.valid = 1;
+		}
+
+		/* Evaluate "_PSx" to see if we can do explicit sets */
+		object_name[2] = 'S';
+		status = acpi_get_handle(device->handle, object_name, &handle);
+		if (ACPI_SUCCESS(status)) {
+			ps->flags.explicit_set = 1;
+			ps->flags.valid = 1;
+		}
+
+		/* State is valid if we have some power control */
+		if (ps->resources.count || ps->flags.explicit_set)
+			ps->flags.valid = 1;
+
+		ps->power = -1;	/* Unknown - driver assigned */
+		ps->latency = -1;	/* Unknown - driver assigned */
+	}
+
+	/* Set defaults for D0 and D3 states (always valid) */
+	device->power.states[ACPI_STATE_D0].flags.valid = 1;
+	device->power.states[ACPI_STATE_D0].power = 100;
+	device->power.states[ACPI_STATE_D3].flags.valid = 1;
+	device->power.states[ACPI_STATE_D3].power = 0;
+
+	/* TBD: System wake support and resource requirements. */
+
+	device->power.state = ACPI_STATE_UNKNOWN;
+	acpi_bus_get_power(device->handle, &(device->power.state));
+
+	return 0;
+}
+
+static int acpi_bus_get_flags(struct acpi_device *device)
+{
+	acpi_status status = AE_OK;
+	acpi_handle temp = NULL;
+
+
+	/* Presence of _STA indicates 'dynamic_status' */
+	status = acpi_get_handle(device->handle, "_STA", &temp);
+	if (ACPI_SUCCESS(status))
+		device->flags.dynamic_status = 1;
+
+	/* Presence of _RMV indicates 'removable' */
+	status = acpi_get_handle(device->handle, "_RMV", &temp);
+	if (ACPI_SUCCESS(status))
+		device->flags.removable = 1;
+
+	/* Presence of _EJD|_EJ0 indicates 'ejectable' */
+	status = acpi_get_handle(device->handle, "_EJD", &temp);
+	if (ACPI_SUCCESS(status))
+		device->flags.ejectable = 1;
+	else {
+		status = acpi_get_handle(device->handle, "_EJ0", &temp);
+		if (ACPI_SUCCESS(status))
+			device->flags.ejectable = 1;
+	}
+
+	/* Presence of _LCK indicates 'lockable' */
+	status = acpi_get_handle(device->handle, "_LCK", &temp);
+	if (ACPI_SUCCESS(status))
+		device->flags.lockable = 1;
+
+	/* Presence of _PS0|_PR0 indicates 'power manageable' */
+	status = acpi_get_handle(device->handle, "_PS0", &temp);
+	if (ACPI_FAILURE(status))
+		status = acpi_get_handle(device->handle, "_PR0", &temp);
+	if (ACPI_SUCCESS(status))
+		device->flags.power_manageable = 1;
+
+	/* Presence of _PRW indicates wake capable */
+	status = acpi_get_handle(device->handle, "_PRW", &temp);
+	if (ACPI_SUCCESS(status))
+		device->flags.wake_capable = 1;
+
+	/* TBD: Performance management */
+
+	return 0;
+}
+
+static void acpi_device_get_busid(struct acpi_device *device)
+{
+	char bus_id[5] = { '?', 0 };
+	struct acpi_buffer buffer = { sizeof(bus_id), bus_id };
+	int i = 0;
+
+	/*
+	 * Bus ID
+	 * ------
+	 * The device's Bus ID is simply the object name.
+	 * TBD: Shouldn't this value be unique (within the ACPI namespace)?
+	 */
+	if (ACPI_IS_ROOT_DEVICE(device)) {
+		strcpy(device->pnp.bus_id, "ACPI");
+		return;
+	}
+
+	switch (device->device_type) {
+	case ACPI_BUS_TYPE_POWER_BUTTON:
+		strcpy(device->pnp.bus_id, "PWRF");
+		break;
+	case ACPI_BUS_TYPE_SLEEP_BUTTON:
+		strcpy(device->pnp.bus_id, "SLPF");
+		break;
+	default:
+		acpi_get_name(device->handle, ACPI_SINGLE_NAME, &buffer);
+		/* Clean up trailing underscores (if any) */
+		for (i = 3; i > 1; i--) {
+			if (bus_id[i] == '_')
+				bus_id[i] = '\0';
+			else
+				break;
+		}
+		strcpy(device->pnp.bus_id, bus_id);
+		break;
+	}
+}
+
+/*
+ * acpi_bay_match - see if a device is an ejectable driver bay
+ *
+ * If an acpi object is ejectable and has one of the ACPI ATA methods defined,
+ * then we can safely call it an ejectable drive bay
+ */
+static int acpi_bay_match(struct acpi_device *device){
+	acpi_status status;
+	acpi_handle handle;
+	acpi_handle tmp;
+	acpi_handle phandle;
+
+	handle = device->handle;
+
+	status = acpi_get_handle(handle, "_EJ0", &tmp);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
+		(ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
+		(ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
+		(ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
+		return 0;
+
+	if (acpi_get_parent(handle, &phandle))
+		return -ENODEV;
+
+        if ((ACPI_SUCCESS(acpi_get_handle(phandle, "_GTF", &tmp))) ||
+                (ACPI_SUCCESS(acpi_get_handle(phandle, "_GTM", &tmp))) ||
+                (ACPI_SUCCESS(acpi_get_handle(phandle, "_STM", &tmp))) ||
+                (ACPI_SUCCESS(acpi_get_handle(phandle, "_SDD", &tmp))))
+                return 0;
+
+	return -ENODEV;
+}
+
+/*
+ * acpi_dock_match - see if a device has a _DCK method
+ */
+static int acpi_dock_match(struct acpi_device *device)
+{
+	acpi_handle tmp;
+	return acpi_get_handle(device->handle, "_DCK", &tmp);
+}
+
+char *acpi_device_hid(struct acpi_device *device)
+{
+	struct acpi_hardware_id *hid;
+
+	hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list);
+	return hid->id;
+}
+EXPORT_SYMBOL(acpi_device_hid);
+
+static void acpi_add_id(struct acpi_device *device, const char *dev_id)
+{
+	struct acpi_hardware_id *id;
+
+	id = kmalloc(sizeof(*id), GFP_KERNEL);
+	if (!id)
+		return;
+
+	id->id = kmalloc(strlen(dev_id) + 1, GFP_KERNEL);
+	if (!id->id) {
+		kfree(id);
+		return;
+	}
+
+	strcpy(id->id, dev_id);
+	list_add_tail(&id->list, &device->pnp.ids);
+}
+
+/*
+ * Old IBM workstations have a DSDT bug wherein the SMBus object
+ * lacks the SMBUS01 HID and the methods do not have the necessary "_"
+ * prefix.  Work around this.
+ */
+static int acpi_ibm_smbus_match(struct acpi_device *device)
+{
+	acpi_handle h_dummy;
+	struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
+	int result;
+
+	if (!dmi_name_in_vendors("IBM"))
+		return -ENODEV;
+
+	/* Look for SMBS object */
+	result = acpi_get_name(device->handle, ACPI_SINGLE_NAME, &path);
+	if (result)
+		return result;
+
+	if (strcmp("SMBS", path.pointer)) {
+		result = -ENODEV;
+		goto out;
+	}
+
+	/* Does it have the necessary (but misnamed) methods? */
+	result = -ENODEV;
+	if (ACPI_SUCCESS(acpi_get_handle(device->handle, "SBI", &h_dummy)) &&
+	    ACPI_SUCCESS(acpi_get_handle(device->handle, "SBR", &h_dummy)) &&
+	    ACPI_SUCCESS(acpi_get_handle(device->handle, "SBW", &h_dummy)))
+		result = 0;
+out:
+	kfree(path.pointer);
+	return result;
+}
+
+static void acpi_device_set_id(struct acpi_device *device)
+{
+	acpi_status status;
+	struct acpi_device_info *info;
+	struct acpica_device_id_list *cid_list;
+	int i;
+
+	switch (device->device_type) {
+	case ACPI_BUS_TYPE_DEVICE:
+		if (ACPI_IS_ROOT_DEVICE(device)) {
+			acpi_add_id(device, ACPI_SYSTEM_HID);
+			break;
+		}
+
+		status = acpi_get_object_info(device->handle, &info);
+		if (ACPI_FAILURE(status)) {
+			printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__);
+			return;
+		}
+
+		if (info->valid & ACPI_VALID_HID)
+			acpi_add_id(device, info->hardware_id.string);
+		if (info->valid & ACPI_VALID_CID) {
+			cid_list = &info->compatible_id_list;
+			for (i = 0; i < cid_list->count; i++)
+				acpi_add_id(device, cid_list->ids[i].string);
+		}
+		if (info->valid & ACPI_VALID_ADR) {
+			device->pnp.bus_address = info->address;
+			device->flags.bus_address = 1;
+		}
+
+		kfree(info);
+
+		/*
+		 * Some devices don't reliably have _HIDs & _CIDs, so add
+		 * synthetic HIDs to make sure drivers can find them.
+		 */
+		if (acpi_is_video_device(device))
+			acpi_add_id(device, ACPI_VIDEO_HID);
+		else if (ACPI_SUCCESS(acpi_bay_match(device)))
+			acpi_add_id(device, ACPI_BAY_HID);
+		else if (ACPI_SUCCESS(acpi_dock_match(device)))
+			acpi_add_id(device, ACPI_DOCK_HID);
+		else if (!acpi_ibm_smbus_match(device))
+			acpi_add_id(device, ACPI_SMBUS_IBM_HID);
+		else if (!acpi_device_hid(device) &&
+			 ACPI_IS_ROOT_DEVICE(device->parent)) {
+			acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
+			strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME);
+			strcpy(device->pnp.device_class, ACPI_BUS_CLASS);
+		}
+
+		break;
+	case ACPI_BUS_TYPE_POWER:
+		acpi_add_id(device, ACPI_POWER_HID);
+		break;
+	case ACPI_BUS_TYPE_PROCESSOR:
+		acpi_add_id(device, ACPI_PROCESSOR_OBJECT_HID);
+		break;
+	case ACPI_BUS_TYPE_THERMAL:
+		acpi_add_id(device, ACPI_THERMAL_HID);
+		break;
+	case ACPI_BUS_TYPE_POWER_BUTTON:
+		acpi_add_id(device, ACPI_BUTTON_HID_POWERF);
+		break;
+	case ACPI_BUS_TYPE_SLEEP_BUTTON:
+		acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF);
+		break;
+	}
+
+	/*
+	 * We build acpi_devices for some objects that don't have _HID or _CID,
+	 * e.g., PCI bridges and slots.  Drivers can't bind to these objects,
+	 * but we do use them indirectly by traversing the acpi_device tree.
+	 * This generic ID isn't useful for driver binding, but it provides
+	 * the useful property that "every acpi_device has an ID."
+	 */
+	if (list_empty(&device->pnp.ids))
+		acpi_add_id(device, "device");
+}
+
+static int acpi_device_set_context(struct acpi_device *device)
+{
+	acpi_status status;
+
+	/*
+	 * Context
+	 * -------
+	 * Attach this 'struct acpi_device' to the ACPI object.  This makes
+	 * resolutions from handle->device very efficient.  Fixed hardware
+	 * devices have no handles, so we skip them.
+	 */
+	if (!device->handle)
+		return 0;
+
+	status = acpi_attach_data(device->handle,
+				  acpi_bus_data_handler, device);
+	if (ACPI_SUCCESS(status))
+		return 0;
+
+	printk(KERN_ERR PREFIX "Error attaching device data\n");
+	return -ENODEV;
+}
+
+static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
+{
+	if (!dev)
+		return -EINVAL;
+
+	dev->removal_type = ACPI_BUS_REMOVAL_EJECT;
+	device_release_driver(&dev->dev);
+
+	if (!rmdevice)
+		return 0;
+
+	/*
+	 * unbind _ADR-Based Devices when hot removal
+	 */
+	if (dev->flags.bus_address) {
+		if ((dev->parent) && (dev->parent->ops.unbind))
+			dev->parent->ops.unbind(dev);
+	}
+	acpi_device_unregister(dev, ACPI_BUS_REMOVAL_EJECT);
+
+	return 0;
+}
+
+static int acpi_add_single_object(struct acpi_device **child,
+				  acpi_handle handle, int type,
+				  unsigned long long sta,
+				  struct acpi_bus_ops *ops)
+{
+	int result;
+	struct acpi_device *device;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+
+	device = kzalloc(sizeof(struct acpi_device), GFP_KERNEL);
+	if (!device) {
+		printk(KERN_ERR PREFIX "Memory allocation error\n");
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&device->pnp.ids);
+	device->device_type = type;
+	device->handle = handle;
+	device->parent = acpi_bus_get_parent(handle);
+	device->bus_ops = *ops; /* workround for not call .start */
+	STRUCT_TO_INT(device->status) = sta;
+
+	acpi_device_get_busid(device);
+
+	/*
+	 * Flags
+	 * -----
+	 * Note that we only look for object handles -- cannot evaluate objects
+	 * until we know the device is present and properly initialized.
+	 */
+	result = acpi_bus_get_flags(device);
+	if (result)
+		goto end;
+
+	/*
+	 * Initialize Device
+	 * -----------------
+	 * TBD: Synch with Core's enumeration/initialization process.
+	 */
+	acpi_device_set_id(device);
+
+	/*
+	 * Power Management
+	 * ----------------
+	 */
+	if (device->flags.power_manageable) {
+		result = acpi_bus_get_power_flags(device);
+		if (result)
+			goto end;
+	}
+
+	/*
+	 * Wakeup device management
+	 *-----------------------
+	 */
+	if (device->flags.wake_capable) {
+		result = acpi_bus_get_wakeup_device_flags(device);
+		if (result)
+			goto end;
+	}
+
+	/*
+	 * Performance Management
+	 * ----------------------
+	 */
+	if (device->flags.performance_manageable) {
+		result = acpi_bus_get_perf_flags(device);
+		if (result)
+			goto end;
+	}
+
+	if ((result = acpi_device_set_context(device)))
+		goto end;
+
+	result = acpi_device_register(device);
+
+	/*
+	 * Bind _ADR-Based Devices when hot add
+	 */
+	if (device->flags.bus_address) {
+		if (device->parent && device->parent->ops.bind)
+			device->parent->ops.bind(device);
+	}
+
+end:
+	if (!result) {
+		acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+			"Adding %s [%s] parent %s\n", dev_name(&device->dev),
+			 (char *) buffer.pointer,
+			 device->parent ? dev_name(&device->parent->dev) :
+					  "(null)"));
+		kfree(buffer.pointer);
+		*child = device;
+	} else
+		acpi_device_release(&device->dev);
+
+	return result;
+}
+
+#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \
+			  ACPI_STA_DEVICE_UI      | ACPI_STA_DEVICE_FUNCTIONING)
+
+static int acpi_bus_type_and_status(acpi_handle handle, int *type,
+				    unsigned long long *sta)
+{
+	acpi_status status;
+	acpi_object_type acpi_type;
+
+	status = acpi_get_type(handle, &acpi_type);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	switch (acpi_type) {
+	case ACPI_TYPE_ANY:		/* for ACPI_ROOT_OBJECT */
+	case ACPI_TYPE_DEVICE:
+		*type = ACPI_BUS_TYPE_DEVICE;
+		status = acpi_bus_get_status_handle(handle, sta);
+		if (ACPI_FAILURE(status))
+			return -ENODEV;
+		break;
+	case ACPI_TYPE_PROCESSOR:
+		*type = ACPI_BUS_TYPE_PROCESSOR;
+		status = acpi_bus_get_status_handle(handle, sta);
+		if (ACPI_FAILURE(status))
+			return -ENODEV;
+		break;
+	case ACPI_TYPE_THERMAL:
+		*type = ACPI_BUS_TYPE_THERMAL;
+		*sta = ACPI_STA_DEFAULT;
+		break;
+	case ACPI_TYPE_POWER:
+		*type = ACPI_BUS_TYPE_POWER;
+		*sta = ACPI_STA_DEFAULT;
+		break;
+	default:
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
+				      void *context, void **return_value)
+{
+	struct acpi_bus_ops *ops = context;
+	int type;
+	unsigned long long sta;
+	struct acpi_device *device;
+	acpi_status status;
+	int result;
+
+	result = acpi_bus_type_and_status(handle, &type, &sta);
+	if (result)
+		return AE_OK;
+
+	if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
+	    !(sta & ACPI_STA_DEVICE_FUNCTIONING))
+		return AE_CTRL_DEPTH;
+
+	/*
+	 * We may already have an acpi_device from a previous enumeration.  If
+	 * so, we needn't add it again, but we may still have to start it.
+	 */
+	device = NULL;
+	acpi_bus_get_device(handle, &device);
+	if (ops->acpi_op_add && !device)
+		acpi_add_single_object(&device, handle, type, sta, ops);
+
+	if (!device)
+		return AE_CTRL_DEPTH;
+
+	if (ops->acpi_op_start && !(ops->acpi_op_add)) {
+		status = acpi_start_single_object(device);
+		if (ACPI_FAILURE(status))
+			return AE_CTRL_DEPTH;
+	}
+
+	if (!*return_value)
+		*return_value = device;
+	return AE_OK;
+}
+
+static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
+			 struct acpi_device **child)
+{
+	acpi_status status;
+	void *device = NULL;
+
+	status = acpi_bus_check_add(handle, 0, ops, &device);
+	if (ACPI_SUCCESS(status))
+		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
+				    acpi_bus_check_add, NULL, ops, &device);
+
+	if (child)
+		*child = device;
+
+	if (device)
+		return 0;
+	else
+		return -ENODEV;
+}
+
+/*
+ * acpi_bus_add and acpi_bus_start
+ *
+ * scan a given ACPI tree and (probably recently hot-plugged)
+ * create and add or starts found devices.
+ *
+ * If no devices were found -ENODEV is returned which does not
+ * mean that this is a real error, there just have been no suitable
+ * ACPI objects in the table trunk from which the kernel could create
+ * a device and add/start an appropriate driver.
+ */
+
+int
+acpi_bus_add(struct acpi_device **child,
+	     struct acpi_device *parent, acpi_handle handle, int type)
+{
+	struct acpi_bus_ops ops;
+
+	memset(&ops, 0, sizeof(ops));
+	ops.acpi_op_add = 1;
+
+	return acpi_bus_scan(handle, &ops, child);
+}
+EXPORT_SYMBOL(acpi_bus_add);
+
+int acpi_bus_start(struct acpi_device *device)
+{
+	struct acpi_bus_ops ops;
+
+	if (!device)
+		return -EINVAL;
+
+	memset(&ops, 0, sizeof(ops));
+	ops.acpi_op_start = 1;
+
+	return acpi_bus_scan(device->handle, &ops, NULL);
+}
+EXPORT_SYMBOL(acpi_bus_start);
+
+int acpi_bus_trim(struct acpi_device *start, int rmdevice)
+{
+	acpi_status status;
+	struct acpi_device *parent, *child;
+	acpi_handle phandle, chandle;
+	acpi_object_type type;
+	u32 level = 1;
+	int err = 0;
+
+	parent = start;
+	phandle = start->handle;
+	child = chandle = NULL;
+
+	while ((level > 0) && parent && (!err)) {
+		status = acpi_get_next_object(ACPI_TYPE_ANY, phandle,
+					      chandle, &chandle);
+
+		/*
+		 * If this scope is exhausted then move our way back up.
+		 */
+		if (ACPI_FAILURE(status)) {
+			level--;
+			chandle = phandle;
+			acpi_get_parent(phandle, &phandle);
+			child = parent;
+			parent = parent->parent;
+
+			if (level == 0)
+				err = acpi_bus_remove(child, rmdevice);
+			else
+				err = acpi_bus_remove(child, 1);
+
+			continue;
+		}
+
+		status = acpi_get_type(chandle, &type);
+		if (ACPI_FAILURE(status)) {
+			continue;
+		}
+		/*
+		 * If there is a device corresponding to chandle then
+		 * parse it (depth-first).
+		 */
+		if (acpi_bus_get_device(chandle, &child) == 0) {
+			level++;
+			phandle = chandle;
+			chandle = NULL;
+			parent = child;
+		}
+		continue;
+	}
+	return err;
+}
+EXPORT_SYMBOL_GPL(acpi_bus_trim);
+
+static int acpi_bus_scan_fixed(void)
+{
+	int result = 0;
+	struct acpi_device *device = NULL;
+	struct acpi_bus_ops ops;
+
+	memset(&ops, 0, sizeof(ops));
+	ops.acpi_op_add = 1;
+	ops.acpi_op_start = 1;
+
+	/*
+	 * Enumerate all fixed-feature devices.
+	 */
+	if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) {
+		result = acpi_add_single_object(&device, NULL,
+						ACPI_BUS_TYPE_POWER_BUTTON,
+						ACPI_STA_DEFAULT,
+						&ops);
+	}
+
+	if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
+		result = acpi_add_single_object(&device, NULL,
+						ACPI_BUS_TYPE_SLEEP_BUTTON,
+						ACPI_STA_DEFAULT,
+						&ops);
+	}
+
+	return result;
+}
+
+int __init acpi_scan_init(void)
+{
+	int result;
+	struct acpi_bus_ops ops;
+
+	memset(&ops, 0, sizeof(ops));
+	ops.acpi_op_add = 1;
+	ops.acpi_op_start = 1;
+
+	result = bus_register(&acpi_bus_type);
+	if (result) {
+		/* We don't want to quit even if we failed to add suspend/resume */
+		printk(KERN_ERR PREFIX "Could not register bus type\n");
+	}
+
+	/*
+	 * Enumerate devices in the ACPI namespace.
+	 */
+	result = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root);
+
+	if (!result)
+		result = acpi_bus_scan_fixed();
+
+	if (result)
+		acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
+
+	return result;
+}
diff --git a/drivers/include/linux/pci.h b/drivers/include/linux/pci.h
index 5b295409d0..b27201e9aa 100644
--- a/drivers/include/linux/pci.h
+++ b/drivers/include/linux/pci.h
@@ -1,10 +1,22 @@
 
 #include <types.h>
 #include <list.h>
+#include <pci_regs.h>
 
 #ifndef __PCI_H__
 #define __PCI_H__
 
+
+/* pci_slot represents a physical slot */
+struct pci_slot {
+    struct pci_bus *bus;        /* The bus this slot is on */
+    struct list_head list;      /* node in list of slots on this bus */
+//    struct hotplug_slot *hotplug;   /* Hotplug info (migrate over time) */
+    unsigned char number;       /* PCI_SLOT(pci_dev->devfn) */
+//    struct kobject kobj;
+};
+
+
 #define PCI_ANY_ID (~0)
 
 
@@ -134,144 +146,6 @@
 #define PCI_CLASS_OTHERS                0xff
 
 
-/*
- * Under PCI, each device has 256 bytes of configuration address space,
- * of which the first 64 bytes are standardized as follows:
- */
-#define PCI_VENDOR_ID                   0x000    /* 16 bits */
-#define PCI_DEVICE_ID                   0x002    /* 16 bits */
-#define PCI_COMMAND                     0x004    /* 16 bits */
-#define  PCI_COMMAND_IO                 0x001    /* Enable response in I/O space */
-#define  PCI_COMMAND_MEMORY             0x002    /* Enable response in Memory space */
-#define  PCI_COMMAND_MASTER             0x004    /* Enable bus mastering */
-#define  PCI_COMMAND_SPECIAL            0x008    /* Enable response to special cycles */
-#define  PCI_COMMAND_INVALIDATE         0x010    /* Use memory write and invalidate */
-#define  PCI_COMMAND_VGA_PALETTE        0x020    /* Enable palette snooping */
-#define  PCI_COMMAND_PARITY             0x040    /* Enable parity checking */
-#define  PCI_COMMAND_WAIT               0x080    /* Enable address/data stepping */
-#define  PCI_COMMAND_SERR               0x100    /* Enable SERR */
-#define  PCI_COMMAND_FAST_BACK          0x200    /* Enable back-to-back writes */
-#define  PCI_COMMAND_INTX_DISABLE       0x400    /* INTx Emulation Disable */
-
-#define PCI_STATUS                      0x006    /* 16 bits */
-#define  PCI_STATUS_CAP_LIST            0x010    /* Support Capability List */
-#define  PCI_STATUS_66MHZ               0x020    /* Support 66 Mhz PCI 2.1 bus */
-#define  PCI_STATUS_UDF                 0x040    /* Support User Definable Features [obsolete] */
-#define  PCI_STATUS_FAST_BACK           0x080    /* Accept fast-back to back */
-#define  PCI_STATUS_PARITY              0x100    /* Detected parity error */
-#define  PCI_STATUS_DEVSEL_MASK         0x600    /* DEVSEL timing */
-#define  PCI_STATUS_DEVSEL_FAST         0x000
-#define  PCI_STATUS_DEVSEL_MEDIUM       0x200
-#define  PCI_STATUS_DEVSEL_SLOW         0x400
-#define  PCI_STATUS_SIG_TARGET_ABORT    0x800    /* Set on target abort */
-#define  PCI_STATUS_REC_TARGET_ABORT    0x1000   /* Master ack of " */
-#define  PCI_STATUS_REC_MASTER_ABORT    0x2000   /* Set on master abort */
-#define  PCI_STATUS_SIG_SYSTEM_ERROR    0x4000   /* Set when we drive SERR */
-#define  PCI_STATUS_DETECTED_PARITY     0x8000   /* Set on parity error */
-
-#define PCI_CLASS_REVISION               0x08    /* High 24 bits are class, low 8 revision */
-#define PCI_REVISION_ID                  0x08    /* Revision ID */
-#define PCI_CLASS_PROG                   0x09    /* Reg. Level Programming Interface */
-#define PCI_CLASS_DEVICE                 0x0a    /* Device class */
-
-#define PCI_CACHE_LINE_SIZE              0x0c    /* 8 bits */
-#define PCI_LATENCY_TIMER                0x0d    /* 8 bits */
-#define PCI_HEADER_TYPE                  0x0e    /* 8 bits */
-#define  PCI_HEADER_TYPE_NORMAL             0
-#define  PCI_HEADER_TYPE_BRIDGE             1
-#define  PCI_HEADER_TYPE_CARDBUS            2
-
-#define PCI_BIST                         0x0f    /* 8 bits */
-#define  PCI_BIST_CODE_MASK              0x0f    /* Return result */
-#define  PCI_BIST_START                  0x40    /* 1 to start BIST, 2 secs or less */
-#define  PCI_BIST_CAPABLE                0x80    /* 1 if BIST capable */
-
-/*
- * Base addresses specify locations in memory or I/O space.
- * Decoded size can be determined by writing a value of
- * 0xffffffff to the register, and reading it back.  Only
- * 1 bits are decoded.
- */
-#define  PCI_BASE_ADDRESS_0             0x10    /* 32 bits */
-#define  PCI_BASE_ADDRESS_1             0x14    /* 32 bits [htype 0,1 only] */
-#define  PCI_BASE_ADDRESS_2             0x18    /* 32 bits [htype 0 only] */
-#define  PCI_BASE_ADDRESS_3             0x1c    /* 32 bits */
-#define  PCI_BASE_ADDRESS_4             0x20    /* 32 bits */
-#define  PCI_BASE_ADDRESS_5             0x24    /* 32 bits */
-#define  PCI_BASE_ADDRESS_SPACE         0x01    /* 0 = memory, 1 = I/O */
-#define  PCI_BASE_ADDRESS_SPACE_IO      0x01
-#define  PCI_BASE_ADDRESS_SPACE_MEMORY  0x00
-#define  PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
-#define  PCI_BASE_ADDRESS_MEM_TYPE_32   0x00    /* 32 bit address */
-#define  PCI_BASE_ADDRESS_MEM_TYPE_1M   0x02    /* Below 1M [obsolete] */
-#define  PCI_BASE_ADDRESS_MEM_TYPE_64   0x04    /* 64 bit address */
-#define  PCI_BASE_ADDRESS_MEM_PREFETCH  0x08    /* prefetchable? */
-#define  PCI_BASE_ADDRESS_MEM_MASK      (~0x0fUL)
-#define  PCI_BASE_ADDRESS_IO_MASK       (~0x03UL)
-/* bit 1 is reserved if address_space = 1 */
-
-#define PCI_ROM_ADDRESS1                0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
-
-/* Header type 0 (normal devices) */
-#define PCI_CARDBUS_CIS                  0x28
-#define PCI_SUBSYSTEM_VENDOR_ID          0x2c
-#define PCI_SUBSYSTEM_ID                 0x2e
-#define PCI_ROM_ADDRESS                  0x30    /* Bits 31..11 are address, 10..1 reserved */
-#define  PCI_ROM_ADDRESS_ENABLE          0x01
-#define PCI_ROM_ADDRESS_MASK             (~0x7ffUL)
-
-#define PCI_INTERRUPT_LINE               0x3c    /* 8 bits */
-#define PCI_INTERRUPT_PIN                0x3d    /* 8 bits */
-
-
-#define PCI_CB_SUBSYSTEM_VENDOR_ID       0x40
-#define PCI_CB_SUBSYSTEM_ID              0x42
-
-#define PCI_CAPABILITY_LIST              0x34    /* Offset of first capability list entry */
-#define PCI_CB_CAPABILITY_LIST           0x14
-/* Capability lists */
-
-#define PCI_CAP_LIST_ID                  0       /* Capability ID */
-#define  PCI_CAP_ID_PM                   0x01    /* Power Management */
-#define  PCI_CAP_ID_AGP                  0x02    /* Accelerated Graphics Port */
-#define  PCI_CAP_ID_VPD                  0x03    /* Vital Product Data */
-#define  PCI_CAP_ID_SLOTID               0x04    /* Slot Identification */
-#define  PCI_CAP_ID_MSI                  0x05    /* Message Signalled Interrupts */
-#define  PCI_CAP_ID_CHSWP                0x06    /* CompactPCI HotSwap */
-#define  PCI_CAP_ID_PCIX                 0x07    /* PCI-X */
-#define  PCI_CAP_ID_HT                   0x08    /* HyperTransport */
-#define  PCI_CAP_ID_VNDR                 0x09    /* Vendor specific capability */
-#define  PCI_CAP_ID_SHPC                 0x0C    /* PCI Standard Hot-Plug Controller */
-#define  PCI_CAP_ID_EXP                  0x10    /* PCI Express */
-#define  PCI_CAP_ID_MSIX                 0x11    /* MSI-X */
-#define PCI_CAP_LIST_NEXT                1       /* Next capability in the list */
-#define PCI_CAP_FLAGS                    2       /* Capability defined flags (16 bits) */
-#define PCI_CAP_SIZEOF                   4
-
-
-/* AGP registers */
-
-#define PCI_AGP_VERSION                     2   /* BCD version number */
-#define PCI_AGP_RFU                         3   /* Rest of capability flags */
-#define PCI_AGP_STATUS                      4   /* Status register */
-#define  PCI_AGP_STATUS_RQ_MASK        0xff000000  /* Maximum number of requests - 1 */
-#define  PCI_AGP_STATUS_SBA            0x0200   /* Sideband addressing supported */
-#define  PCI_AGP_STATUS_64BIT          0x0020   /* 64-bit addressing supported */
-#define  PCI_AGP_STATUS_FW             0x0010   /* FW transfers supported */
-#define  PCI_AGP_STATUS_RATE4          0x0004   /* 4x transfer rate supported */
-#define  PCI_AGP_STATUS_RATE2          0x0002   /* 2x transfer rate supported */
-#define  PCI_AGP_STATUS_RATE1          0x0001   /* 1x transfer rate supported */
-#define PCI_AGP_COMMAND                     8   /* Control register */
-#define  PCI_AGP_COMMAND_RQ_MASK    0xff000000  /* Master: Maximum number of requests */
-#define  PCI_AGP_COMMAND_SBA           0x0200   /* Sideband addressing enabled */
-#define  PCI_AGP_COMMAND_AGP           0x0100   /* Allow processing of AGP transactions */
-#define  PCI_AGP_COMMAND_64BIT         0x0020   /* Allow processing of 64-bit addresses */
-#define  PCI_AGP_COMMAND_FW            0x0010   /* Force FW transfers */
-#define  PCI_AGP_COMMAND_RATE4         0x0004   /* Use 4x rate */
-#define  PCI_AGP_COMMAND_RATE2         0x0002   /* Use 2x rate */
-#define  PCI_AGP_COMMAND_RATE1         0x0001   /* Use 1x rate */
-#define PCI_AGP_SIZEOF                     12
-
 
 #define PCI_MAP_REG_START                   0x10
 #define PCI_MAP_REG_END                     0x28
@@ -334,6 +208,26 @@
 #define PCI_SLOT(devfn)        (((devfn) >> 3) & 0x1f)
 #define PCI_FUNC(devfn)        ((devfn) & 0x07)
 
+/* Ioctls for /proc/bus/pci/X/Y nodes. */
+#define PCIIOC_BASE		('P' << 24 | 'C' << 16 | 'I' << 8)
+#define PCIIOC_CONTROLLER	(PCIIOC_BASE | 0x00)	/* Get controller for PCI device. */
+#define PCIIOC_MMAP_IS_IO	(PCIIOC_BASE | 0x01)	/* Set mmap state to I/O space. */
+#define PCIIOC_MMAP_IS_MEM	(PCIIOC_BASE | 0x02)	/* Set mmap state to MEM space. */
+#define PCIIOC_WRITE_COMBINE	(PCIIOC_BASE | 0x03)	/* Enable/disable write-combining. */
+
+
+typedef unsigned int __bitwise pci_channel_state_t;
+
+enum pci_channel_state {
+    /* I/O channel is in normal state */
+    pci_channel_io_normal = (__force pci_channel_state_t) 1,
+
+    /* I/O to channel is blocked */
+    pci_channel_io_frozen = (__force pci_channel_state_t) 2,
+
+    /* PCI card is dead */
+    pci_channel_io_perm_failure = (__force pci_channel_state_t) 3,
+};
 
 
 typedef unsigned int PCITAG;
@@ -354,6 +248,11 @@ struct resource
          struct resource *parent, *sibling, *child;
 };
 
+/* This defines the direction arg to the DMA mapping routines. */
+#define PCI_DMA_BIDIRECTIONAL	0
+#define PCI_DMA_TODEVICE	1
+#define PCI_DMA_FROMDEVICE	2
+#define PCI_DMA_NONE		3
 
 /*
  *  For PCI devices, the region numbers are assigned this way:
@@ -454,6 +353,8 @@ enum {
 #define IORESOURCE_PCI_FIXED            (1<<4)  /* Do not move resource */
 
 
+
+
 /*
  *  For PCI devices, the region numbers are assigned this way:
  *
@@ -472,32 +373,48 @@ enum {
 
 #define DEVICE_COUNT_RESOURCE   12
 
+
+#define PCI_CFG_SPACE_SIZE      256
+#define PCI_CFG_SPACE_EXP_SIZE  4096
+
+
+typedef int __bitwise pci_power_t;
+
+#define PCI_D0      ((pci_power_t __force) 0)
+#define PCI_D1      ((pci_power_t __force) 1)
+#define PCI_D2      ((pci_power_t __force) 2)
+#define PCI_D3hot   ((pci_power_t __force) 3)
+#define PCI_D3cold  ((pci_power_t __force) 4)
+#define PCI_UNKNOWN ((pci_power_t __force) 5)
+#define PCI_POWER_ERROR ((pci_power_t __force) -1)
+
 /*
  * The pci_dev structure is used to describe PCI devices.
  */
 struct pci_dev {
-//    struct list_head bus_list;  /* node in per-bus list */
-//    struct pci_bus  *bus;       /* bus this device is on */
-//    struct pci_bus  *subordinate;   /* bus this device bridges to */
+    struct list_head bus_list;  /* node in per-bus list */
+    struct pci_bus  *bus;       /* bus this device is on */
+    struct pci_bus  *subordinate;   /* bus this device bridges to */
 
-//    void        *sysdata;       /* hook for sys-specific extension */
+    void        *sysdata;       /* hook for sys-specific extension */
 //    struct proc_dir_entry *procent; /* device entry in /proc/bus/pci */
-//    struct pci_slot *slot;      /* Physical slot this device is in */
-    u32_t        bus;
-    u32_t        devfn;          /* encoded device & function index */
-    u16_t        vendor;
-    u16_t        device;
-    u16_t        subsystem_vendor;
-    u16_t        subsystem_device;
-    u32_t        class;         /* 3 bytes: (base,sub,prog-if) */
-    uint8_t      revision;      /* PCI revision, low byte of class word */
-    uint8_t      hdr_type;      /* PCI header type (`multi' flag masked out) */
-    uint8_t      pcie_type;     /* PCI-E device/port type */
-    uint8_t      rom_base_reg;   /* which config register controls the ROM */
-    uint8_t      pin;           /* which interrupt pin this device uses */
+    struct pci_slot *slot;      /* Physical slot this device is in */
+    u32_t        busnr;
+	unsigned int	devfn;		/* encoded device & function index */
+	unsigned short	vendor;
+	unsigned short	device;
+	unsigned short	subsystem_vendor;
+	unsigned short	subsystem_device;
+	unsigned int	class;		/* 3 bytes: (base,sub,prog-if) */
+	u8		revision;	/* PCI revision, low byte of class word */
+	u8		hdr_type;	/* PCI header type (`multi' flag masked out) */
+	u8		pcie_cap;	/* PCI-E capability offset */
+    u8           pcie_type;     /* PCI-E device/port type */
+	u8		rom_base_reg;	/* which config register controls the ROM */
+	u8		pin;  		/* which interrupt pin this device uses */
 
  //   struct pci_driver *driver;  /* which driver has allocated this device */
-    uint64_t     dma_mask;   /* Mask of the bits of bus address this
+	u64		dma_mask;	/* Mask of the bits of bus address this
                        device implements.  Normally this is
                        0xffffffff.  You only need to change
                        this if your device has broken DMA
@@ -505,21 +422,26 @@ struct pci_dev {
 
  //   struct device_dma_parameters dma_parms;
 
-//    pci_power_t     current_state;  /* Current operating state. In ACPI-speak,
- //                      this is D0-D3, D0 being fully functional,
-//                       and D3 being off. */
-//    int     pm_cap;     /* PM capability offset in the
-//                       configuration space */
+    pci_power_t     current_state;  /* Current operating state. In ACPI-speak,
+                                       this is D0-D3, D0 being fully functional,
+                                       and D3 being off. */
+    int     pm_cap;     /* PM capability offset in the
+                           configuration space */
     unsigned int    pme_support:5;  /* Bitmask of states from which PME#
                        can be generated */
+	unsigned int	pme_interrupt:1;
     unsigned int    d1_support:1;   /* Low power state D1 is supported */
     unsigned int    d2_support:1;   /* Low power state D2 is supported */
     unsigned int    no_d1d2:1;  /* Only allow D0 and D3 */
+	unsigned int	mmio_always_on:1;	/* disallow turning off io/mem
+						   decoding during bar sizing */
+	unsigned int	wakeup_prepared:1;
+	unsigned int	d3_delay;	/* D3->D0 transition time in ms */
 
-//    pci_channel_state_t error_state;    /* current connectivity state */
+    pci_channel_state_t error_state;    /* current connectivity state */
     struct  device  dev;        /* Generic device interface */
 
-//    int     cfg_size;   /* Size of configuration space */
+    int     cfg_size;   /* Size of configuration space */
 
     /*
      * Instead of touching interrupt line and base address registers
@@ -542,12 +464,17 @@ struct pci_dev {
     unsigned int    msix_enabled:1;
     unsigned int    ari_enabled:1;  /* ARI forwarding */
     unsigned int    is_managed:1;
-    unsigned int    is_pcie:1;
+	unsigned int	is_pcie:1;	/* Obsolete. Will be removed.
+					   Use pci_is_pcie() instead */
+	unsigned int    needs_freset:1; /* Dev requires fundamental reset */
     unsigned int    state_saved:1;
     unsigned int    is_physfn:1;
     unsigned int    is_virtfn:1;
-//    pci_dev_flags_t dev_flags;
-//    atomic_t    enable_cnt;   /* pci_enable_device has been called */
+	unsigned int	reset_fn:1;
+	unsigned int    is_hotplug_bridge:1;
+	unsigned int    __aer_firmware_first_valid:1;
+	unsigned int	__aer_firmware_first:1;
+
 
 //    u32     saved_config_space[16]; /* config space saved at suspend time */
 //    struct hlist_head saved_cap_space;
@@ -606,6 +533,28 @@ struct pci_ops
     int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val);
 };
 
+/*
+ * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
+ * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
+ * buses below host bridges or subtractive decode bridges) go in the list.
+ * Use pci_bus_for_each_resource() to iterate through all the resources.
+ */
+
+/*
+ * PCI_SUBTRACTIVE_DECODE means the bridge forwards the window implicitly
+ * and there's no way to program the bridge with the details of the window.
+ * This does not apply to ACPI _CRS windows, even with the _DEC subtractive-
+ * decode bit set, because they are explicit and can be programmed with _SRS.
+ */
+#define PCI_SUBTRACTIVE_DECODE	0x1
+
+struct pci_bus_resource {
+	struct list_head list;
+	struct resource *res;
+	unsigned int flags;
+};
+
+#define PCI_REGION_FLAG_MASK	0x0fU	/* These bits of resource flags tell us the PCI region flags */
 
 struct pci_bus {
     struct list_head node;      /* node in list of buses */
@@ -638,6 +587,9 @@ struct pci_bus {
 
 #define pci_bus_b(n)    list_entry(n, struct pci_bus, node)
 #define to_pci_bus(n)   container_of(n, struct pci_bus, dev)
+#define pci_dev_b(n)    list_entry(n, struct pci_dev, bus_list)
+#define to_pci_dev(n) container_of(n, struct pci_dev, dev)
+#define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
 
 
 static inline int pci_domain_nr(struct pci_bus *bus)
@@ -645,6 +597,31 @@ static inline int pci_domain_nr(struct pci_bus *bus)
     struct pci_sysdata *sd = bus->sysdata;
     return sd->domain;
 }
+static inline bool pci_dev_msi_enabled(struct pci_dev *pci_dev) { return false; }
+
+/*
+ * Error values that may be returned by PCI functions.
+ */
+#define PCIBIOS_SUCCESSFUL		0x00
+#define PCIBIOS_FUNC_NOT_SUPPORTED	0x81
+#define PCIBIOS_BAD_VENDOR_ID		0x83
+#define PCIBIOS_DEVICE_NOT_FOUND	0x86
+#define PCIBIOS_BAD_REGISTER_NUMBER	0x87
+#define PCIBIOS_SET_FAILED		0x88
+#define PCIBIOS_BUFFER_TOO_SMALL	0x89
+
+/* Low-level architecture-dependent routines */
+
+struct pci_bus_region {
+	resource_size_t start;
+	resource_size_t end;
+};
+
+
+
+
+
+
 
 
 int enum_pci_devices(void);
@@ -658,9 +635,45 @@ int pci_set_dma_mask(struct pci_dev *dev, u64 mask);
 
 struct pci_bus * pci_create_bus(int bus, struct pci_ops *ops, void *sysdata);
 struct pci_bus * pci_find_bus(int domain, int busnr);
+int pci_find_capability(struct pci_dev *dev, int cap);
+int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap);
+int pci_find_ext_capability(struct pci_dev *dev, int cap);
+int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn,
+				int cap);
+int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
 struct pci_bus * pci_find_next_bus(const struct pci_bus *from);
 
+static inline bool pci_is_root_bus(struct pci_bus *pbus)
+{
+    return !(pbus->parent);
+}
 
+/**
+ * pci_pcie_cap - get the saved PCIe capability offset
+ * @dev: PCI device
+ *
+ * PCIe capability offset is calculated at PCI device initialization
+ * time and saved in the data structure. This function returns saved
+ * PCIe capability offset. Using this instead of pci_find_capability()
+ * reduces unnecessary search in the PCI configuration space. If you
+ * need to calculate PCIe capability offset from raw device for some
+ * reasons, please use pci_find_capability() instead.
+ */
+static inline int pci_pcie_cap(struct pci_dev *dev)
+{
+    return dev->pcie_cap;
+}
+
+/**
+ * pci_is_pcie - check if the PCI device is PCI Express capable
+ * @dev: PCI device
+ *
+ * Retrun true if the PCI device is PCI Express capable, false otherwise.
+ */
+static inline bool pci_is_pcie(struct pci_dev *dev)
+{
+    return !!pci_pcie_cap(dev);
+}
 
 #define pci_name(x) "radeon"
 
diff --git a/drivers/include/linux/pci_regs.h b/drivers/include/linux/pci_regs.h
new file mode 100644
index 0000000000..1394894f05
--- /dev/null
+++ b/drivers/include/linux/pci_regs.h
@@ -0,0 +1,686 @@
+/*
+ *	pci_regs.h
+ *
+ *	PCI standard defines
+ *	Copyright 1994, Drew Eckhardt
+ *	Copyright 1997--1999 Martin Mares <mj@ucw.cz>
+ *
+ *	For more information, please consult the following manuals (look at
+ *	http://www.pcisig.com/ for how to get them):
+ *
+ *	PCI BIOS Specification
+ *	PCI Local Bus Specification
+ *	PCI to PCI Bridge Specification
+ *	PCI System Design Guide
+ *
+ * 	For hypertransport information, please consult the following manuals
+ * 	from http://www.hypertransport.org
+ *
+ *	The Hypertransport I/O Link Specification
+ */
+
+#ifndef LINUX_PCI_REGS_H
+#define LINUX_PCI_REGS_H
+
+/*
+ * Under PCI, each device has 256 bytes of configuration address space,
+ * of which the first 64 bytes are standardized as follows:
+ */
+#define PCI_VENDOR_ID		0x00	/* 16 bits */
+#define PCI_DEVICE_ID		0x02	/* 16 bits */
+#define PCI_COMMAND		0x04	/* 16 bits */
+#define  PCI_COMMAND_IO		0x1	/* Enable response in I/O space */
+#define  PCI_COMMAND_MEMORY	0x2	/* Enable response in Memory space */
+#define  PCI_COMMAND_MASTER	0x4	/* Enable bus mastering */
+#define  PCI_COMMAND_SPECIAL	0x8	/* Enable response to special cycles */
+#define  PCI_COMMAND_INVALIDATE	0x10	/* Use memory write and invalidate */
+#define  PCI_COMMAND_VGA_PALETTE 0x20	/* Enable palette snooping */
+#define  PCI_COMMAND_PARITY	0x40	/* Enable parity checking */
+#define  PCI_COMMAND_WAIT 	0x80	/* Enable address/data stepping */
+#define  PCI_COMMAND_SERR	0x100	/* Enable SERR */
+#define  PCI_COMMAND_FAST_BACK	0x200	/* Enable back-to-back writes */
+#define  PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
+
+#define PCI_STATUS		0x06	/* 16 bits */
+#define  PCI_STATUS_INTERRUPT	0x08	/* Interrupt status */
+#define  PCI_STATUS_CAP_LIST	0x10	/* Support Capability List */
+#define  PCI_STATUS_66MHZ	0x20	/* Support 66 Mhz PCI 2.1 bus */
+#define  PCI_STATUS_UDF		0x40	/* Support User Definable Features [obsolete] */
+#define  PCI_STATUS_FAST_BACK	0x80	/* Accept fast-back to back */
+#define  PCI_STATUS_PARITY	0x100	/* Detected parity error */
+#define  PCI_STATUS_DEVSEL_MASK	0x600	/* DEVSEL timing */
+#define  PCI_STATUS_DEVSEL_FAST		0x000
+#define  PCI_STATUS_DEVSEL_MEDIUM	0x200
+#define  PCI_STATUS_DEVSEL_SLOW		0x400
+#define  PCI_STATUS_SIG_TARGET_ABORT	0x800 /* Set on target abort */
+#define  PCI_STATUS_REC_TARGET_ABORT	0x1000 /* Master ack of " */
+#define  PCI_STATUS_REC_MASTER_ABORT	0x2000 /* Set on master abort */
+#define  PCI_STATUS_SIG_SYSTEM_ERROR	0x4000 /* Set when we drive SERR */
+#define  PCI_STATUS_DETECTED_PARITY	0x8000 /* Set on parity error */
+
+#define PCI_CLASS_REVISION	0x08	/* High 24 bits are class, low 8 revision */
+#define PCI_REVISION_ID		0x08	/* Revision ID */
+#define PCI_CLASS_PROG		0x09	/* Reg. Level Programming Interface */
+#define PCI_CLASS_DEVICE	0x0a	/* Device class */
+
+#define PCI_CACHE_LINE_SIZE	0x0c	/* 8 bits */
+#define PCI_LATENCY_TIMER	0x0d	/* 8 bits */
+#define PCI_HEADER_TYPE		0x0e	/* 8 bits */
+#define  PCI_HEADER_TYPE_NORMAL		0
+#define  PCI_HEADER_TYPE_BRIDGE		1
+#define  PCI_HEADER_TYPE_CARDBUS	2
+
+#define PCI_BIST		0x0f	/* 8 bits */
+#define  PCI_BIST_CODE_MASK	0x0f	/* Return result */
+#define  PCI_BIST_START		0x40	/* 1 to start BIST, 2 secs or less */
+#define  PCI_BIST_CAPABLE	0x80	/* 1 if BIST capable */
+
+/*
+ * Base addresses specify locations in memory or I/O space.
+ * Decoded size can be determined by writing a value of
+ * 0xffffffff to the register, and reading it back.  Only
+ * 1 bits are decoded.
+ */
+#define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
+#define PCI_BASE_ADDRESS_1	0x14	/* 32 bits [htype 0,1 only] */
+#define PCI_BASE_ADDRESS_2	0x18	/* 32 bits [htype 0 only] */
+#define PCI_BASE_ADDRESS_3	0x1c	/* 32 bits */
+#define PCI_BASE_ADDRESS_4	0x20	/* 32 bits */
+#define PCI_BASE_ADDRESS_5	0x24	/* 32 bits */
+#define  PCI_BASE_ADDRESS_SPACE		0x01	/* 0 = memory, 1 = I/O */
+#define  PCI_BASE_ADDRESS_SPACE_IO	0x01
+#define  PCI_BASE_ADDRESS_SPACE_MEMORY	0x00
+#define  PCI_BASE_ADDRESS_MEM_TYPE_MASK	0x06
+#define  PCI_BASE_ADDRESS_MEM_TYPE_32	0x00	/* 32 bit address */
+#define  PCI_BASE_ADDRESS_MEM_TYPE_1M	0x02	/* Below 1M [obsolete] */
+#define  PCI_BASE_ADDRESS_MEM_TYPE_64	0x04	/* 64 bit address */
+#define  PCI_BASE_ADDRESS_MEM_PREFETCH	0x08	/* prefetchable? */
+#define  PCI_BASE_ADDRESS_MEM_MASK	(~0x0fUL)
+#define  PCI_BASE_ADDRESS_IO_MASK	(~0x03UL)
+/* bit 1 is reserved if address_space = 1 */
+
+/* Header type 0 (normal devices) */
+#define PCI_CARDBUS_CIS		0x28
+#define PCI_SUBSYSTEM_VENDOR_ID	0x2c
+#define PCI_SUBSYSTEM_ID	0x2e
+#define PCI_ROM_ADDRESS		0x30	/* Bits 31..11 are address, 10..1 reserved */
+#define  PCI_ROM_ADDRESS_ENABLE	0x01
+#define PCI_ROM_ADDRESS_MASK	(~0x7ffUL)
+
+#define PCI_CAPABILITY_LIST	0x34	/* Offset of first capability list entry */
+
+/* 0x35-0x3b are reserved */
+#define PCI_INTERRUPT_LINE	0x3c	/* 8 bits */
+#define PCI_INTERRUPT_PIN	0x3d	/* 8 bits */
+#define PCI_MIN_GNT		0x3e	/* 8 bits */
+#define PCI_MAX_LAT		0x3f	/* 8 bits */
+
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
+#define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
+#define PCI_SUBORDINATE_BUS	0x1a	/* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER	0x1b	/* Latency timer for secondary interface */
+#define PCI_IO_BASE		0x1c	/* I/O range behind the bridge */
+#define PCI_IO_LIMIT		0x1d
+#define  PCI_IO_RANGE_TYPE_MASK	0x0fUL	/* I/O bridging type */
+#define  PCI_IO_RANGE_TYPE_16	0x00
+#define  PCI_IO_RANGE_TYPE_32	0x01
+#define  PCI_IO_RANGE_MASK	(~0x0fUL)
+#define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
+#define PCI_MEMORY_BASE		0x20	/* Memory range behind */
+#define PCI_MEMORY_LIMIT	0x22
+#define  PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL
+#define  PCI_MEMORY_RANGE_MASK	(~0x0fUL)
+#define PCI_PREF_MEMORY_BASE	0x24	/* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT	0x26
+#define  PCI_PREF_RANGE_TYPE_MASK 0x0fUL
+#define  PCI_PREF_RANGE_TYPE_32	0x00
+#define  PCI_PREF_RANGE_TYPE_64	0x01
+#define  PCI_PREF_RANGE_MASK	(~0x0fUL)
+#define PCI_PREF_BASE_UPPER32	0x28	/* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32	0x2c
+#define PCI_IO_BASE_UPPER16	0x30	/* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16	0x32
+/* 0x34 same as for htype 0 */
+/* 0x35-0x3b is reserved */
+#define PCI_ROM_ADDRESS1	0x38	/* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL	0x3e
+#define  PCI_BRIDGE_CTL_PARITY	0x01	/* Enable parity detection on secondary interface */
+#define  PCI_BRIDGE_CTL_SERR	0x02	/* The same for SERR forwarding */
+#define  PCI_BRIDGE_CTL_ISA	0x04	/* Enable ISA mode */
+#define  PCI_BRIDGE_CTL_VGA	0x08	/* Forward VGA addresses */
+#define  PCI_BRIDGE_CTL_MASTER_ABORT	0x20  /* Report master aborts */
+#define  PCI_BRIDGE_CTL_BUS_RESET	0x40	/* Secondary bus reset */
+#define  PCI_BRIDGE_CTL_FAST_BACK	0x80	/* Fast Back2Back enabled on secondary interface */
+
+/* Header type 2 (CardBus bridges) */
+#define PCI_CB_CAPABILITY_LIST	0x14
+/* 0x15 reserved */
+#define PCI_CB_SEC_STATUS	0x16	/* Secondary status */
+#define PCI_CB_PRIMARY_BUS	0x18	/* PCI bus number */
+#define PCI_CB_CARD_BUS		0x19	/* CardBus bus number */
+#define PCI_CB_SUBORDINATE_BUS	0x1a	/* Subordinate bus number */
+#define PCI_CB_LATENCY_TIMER	0x1b	/* CardBus latency timer */
+#define PCI_CB_MEMORY_BASE_0	0x1c
+#define PCI_CB_MEMORY_LIMIT_0	0x20
+#define PCI_CB_MEMORY_BASE_1	0x24
+#define PCI_CB_MEMORY_LIMIT_1	0x28
+#define PCI_CB_IO_BASE_0	0x2c
+#define PCI_CB_IO_BASE_0_HI	0x2e
+#define PCI_CB_IO_LIMIT_0	0x30
+#define PCI_CB_IO_LIMIT_0_HI	0x32
+#define PCI_CB_IO_BASE_1	0x34
+#define PCI_CB_IO_BASE_1_HI	0x36
+#define PCI_CB_IO_LIMIT_1	0x38
+#define PCI_CB_IO_LIMIT_1_HI	0x3a
+#define  PCI_CB_IO_RANGE_MASK	(~0x03UL)
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_CB_BRIDGE_CONTROL	0x3e
+#define  PCI_CB_BRIDGE_CTL_PARITY	0x01	/* Similar to standard bridge control register */
+#define  PCI_CB_BRIDGE_CTL_SERR		0x02
+#define  PCI_CB_BRIDGE_CTL_ISA		0x04
+#define  PCI_CB_BRIDGE_CTL_VGA		0x08
+#define  PCI_CB_BRIDGE_CTL_MASTER_ABORT	0x20
+#define  PCI_CB_BRIDGE_CTL_CB_RESET	0x40	/* CardBus reset */
+#define  PCI_CB_BRIDGE_CTL_16BIT_INT	0x80	/* Enable interrupt for 16-bit cards */
+#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100	/* Prefetch enable for both memory regions */
+#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
+#define  PCI_CB_BRIDGE_CTL_POST_WRITES	0x400
+#define PCI_CB_SUBSYSTEM_VENDOR_ID	0x40
+#define PCI_CB_SUBSYSTEM_ID		0x42
+#define PCI_CB_LEGACY_MODE_BASE		0x44	/* 16-bit PC Card legacy mode base address (ExCa) */
+/* 0x48-0x7f reserved */
+
+/* Capability lists */
+
+#define PCI_CAP_LIST_ID		0	/* Capability ID */
+#define  PCI_CAP_ID_PM		0x01	/* Power Management */
+#define  PCI_CAP_ID_AGP		0x02	/* Accelerated Graphics Port */
+#define  PCI_CAP_ID_VPD		0x03	/* Vital Product Data */
+#define  PCI_CAP_ID_SLOTID	0x04	/* Slot Identification */
+#define  PCI_CAP_ID_MSI		0x05	/* Message Signalled Interrupts */
+#define  PCI_CAP_ID_CHSWP	0x06	/* CompactPCI HotSwap */
+#define  PCI_CAP_ID_PCIX	0x07	/* PCI-X */
+#define  PCI_CAP_ID_HT		0x08	/* HyperTransport */
+#define  PCI_CAP_ID_VNDR	0x09	/* Vendor specific */
+#define  PCI_CAP_ID_DBG		0x0A	/* Debug port */
+#define  PCI_CAP_ID_CCRC	0x0B	/* CompactPCI Central Resource Control */
+#define  PCI_CAP_ID_SHPC 	0x0C	/* PCI Standard Hot-Plug Controller */
+#define  PCI_CAP_ID_SSVID	0x0D	/* Bridge subsystem vendor/device ID */
+#define  PCI_CAP_ID_AGP3	0x0E	/* AGP Target PCI-PCI bridge */
+#define  PCI_CAP_ID_EXP 	0x10	/* PCI Express */
+#define  PCI_CAP_ID_MSIX	0x11	/* MSI-X */
+#define  PCI_CAP_ID_AF		0x13	/* PCI Advanced Features */
+#define PCI_CAP_LIST_NEXT	1	/* Next capability in the list */
+#define PCI_CAP_FLAGS		2	/* Capability defined flags (16 bits) */
+#define PCI_CAP_SIZEOF		4
+
+/* Power Management Registers */
+
+#define PCI_PM_PMC		2	/* PM Capabilities Register */
+#define  PCI_PM_CAP_VER_MASK	0x0007	/* Version */
+#define  PCI_PM_CAP_PME_CLOCK	0x0008	/* PME clock required */
+#define  PCI_PM_CAP_RESERVED    0x0010  /* Reserved field */
+#define  PCI_PM_CAP_DSI		0x0020	/* Device specific initialization */
+#define  PCI_PM_CAP_AUX_POWER	0x01C0	/* Auxilliary power support mask */
+#define  PCI_PM_CAP_D1		0x0200	/* D1 power state support */
+#define  PCI_PM_CAP_D2		0x0400	/* D2 power state support */
+#define  PCI_PM_CAP_PME		0x0800	/* PME pin supported */
+#define  PCI_PM_CAP_PME_MASK	0xF800	/* PME Mask of all supported states */
+#define  PCI_PM_CAP_PME_D0	0x0800	/* PME# from D0 */
+#define  PCI_PM_CAP_PME_D1	0x1000	/* PME# from D1 */
+#define  PCI_PM_CAP_PME_D2	0x2000	/* PME# from D2 */
+#define  PCI_PM_CAP_PME_D3	0x4000	/* PME# from D3 (hot) */
+#define  PCI_PM_CAP_PME_D3cold	0x8000	/* PME# from D3 (cold) */
+#define  PCI_PM_CAP_PME_SHIFT	11	/* Start of the PME Mask in PMC */
+#define PCI_PM_CTRL		4	/* PM control and status register */
+#define  PCI_PM_CTRL_STATE_MASK	0x0003	/* Current power state (D0 to D3) */
+#define  PCI_PM_CTRL_NO_SOFT_RESET	0x0008	/* No reset for D3hot->D0 */
+#define  PCI_PM_CTRL_PME_ENABLE	0x0100	/* PME pin enable */
+#define  PCI_PM_CTRL_DATA_SEL_MASK	0x1e00	/* Data select (??) */
+#define  PCI_PM_CTRL_DATA_SCALE_MASK	0x6000	/* Data scale (??) */
+#define  PCI_PM_CTRL_PME_STATUS	0x8000	/* PME pin status */
+#define PCI_PM_PPB_EXTENSIONS	6	/* PPB support extensions (??) */
+#define  PCI_PM_PPB_B2_B3	0x40	/* Stop clock when in D3hot (??) */
+#define  PCI_PM_BPCC_ENABLE	0x80	/* Bus power/clock control enable (??) */
+#define PCI_PM_DATA_REGISTER	7	/* (??) */
+#define PCI_PM_SIZEOF		8
+
+/* AGP registers */
+
+#define PCI_AGP_VERSION		2	/* BCD version number */
+#define PCI_AGP_RFU		3	/* Rest of capability flags */
+#define PCI_AGP_STATUS		4	/* Status register */
+#define  PCI_AGP_STATUS_RQ_MASK	0xff000000	/* Maximum number of requests - 1 */
+#define  PCI_AGP_STATUS_SBA	0x0200	/* Sideband addressing supported */
+#define  PCI_AGP_STATUS_64BIT	0x0020	/* 64-bit addressing supported */
+#define  PCI_AGP_STATUS_FW	0x0010	/* FW transfers supported */
+#define  PCI_AGP_STATUS_RATE4	0x0004	/* 4x transfer rate supported */
+#define  PCI_AGP_STATUS_RATE2	0x0002	/* 2x transfer rate supported */
+#define  PCI_AGP_STATUS_RATE1	0x0001	/* 1x transfer rate supported */
+#define PCI_AGP_COMMAND		8	/* Control register */
+#define  PCI_AGP_COMMAND_RQ_MASK 0xff000000  /* Master: Maximum number of requests */
+#define  PCI_AGP_COMMAND_SBA	0x0200	/* Sideband addressing enabled */
+#define  PCI_AGP_COMMAND_AGP	0x0100	/* Allow processing of AGP transactions */
+#define  PCI_AGP_COMMAND_64BIT	0x0020 	/* Allow processing of 64-bit addresses */
+#define  PCI_AGP_COMMAND_FW	0x0010 	/* Force FW transfers */
+#define  PCI_AGP_COMMAND_RATE4	0x0004	/* Use 4x rate */
+#define  PCI_AGP_COMMAND_RATE2	0x0002	/* Use 2x rate */
+#define  PCI_AGP_COMMAND_RATE1	0x0001	/* Use 1x rate */
+#define PCI_AGP_SIZEOF		12
+
+/* Vital Product Data */
+
+#define PCI_VPD_ADDR		2	/* Address to access (15 bits!) */
+#define  PCI_VPD_ADDR_MASK	0x7fff	/* Address mask */
+#define  PCI_VPD_ADDR_F		0x8000	/* Write 0, 1 indicates completion */
+#define PCI_VPD_DATA		4	/* 32-bits of data returned here */
+
+/* Slot Identification */
+
+#define PCI_SID_ESR		2	/* Expansion Slot Register */
+#define  PCI_SID_ESR_NSLOTS	0x1f	/* Number of expansion slots available */
+#define  PCI_SID_ESR_FIC	0x20	/* First In Chassis Flag */
+#define PCI_SID_CHASSIS_NR	3	/* Chassis Number */
+
+/* Message Signalled Interrupts registers */
+
+#define PCI_MSI_FLAGS		2	/* Various flags */
+#define  PCI_MSI_FLAGS_64BIT	0x80	/* 64-bit addresses allowed */
+#define  PCI_MSI_FLAGS_QSIZE	0x70	/* Message queue size configured */
+#define  PCI_MSI_FLAGS_QMASK	0x0e	/* Maximum queue size available */
+#define  PCI_MSI_FLAGS_ENABLE	0x01	/* MSI feature enabled */
+#define  PCI_MSI_FLAGS_MASKBIT	0x100	/* 64-bit mask bits allowed */
+#define PCI_MSI_RFU		3	/* Rest of capability flags */
+#define PCI_MSI_ADDRESS_LO	4	/* Lower 32 bits */
+#define PCI_MSI_ADDRESS_HI	8	/* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
+#define PCI_MSI_DATA_32		8	/* 16 bits of data for 32-bit devices */
+#define PCI_MSI_MASK_32		12	/* Mask bits register for 32-bit devices */
+#define PCI_MSI_DATA_64		12	/* 16 bits of data for 64-bit devices */
+#define PCI_MSI_MASK_64		16	/* Mask bits register for 64-bit devices */
+
+/* MSI-X registers (these are at offset PCI_MSIX_FLAGS) */
+#define PCI_MSIX_FLAGS		2
+#define  PCI_MSIX_FLAGS_QSIZE	0x7FF
+#define  PCI_MSIX_FLAGS_ENABLE	(1 << 15)
+#define  PCI_MSIX_FLAGS_MASKALL	(1 << 14)
+#define PCI_MSIX_FLAGS_BIRMASK	(7 << 0)
+
+/* CompactPCI Hotswap Register */
+
+#define PCI_CHSWP_CSR		2	/* Control and Status Register */
+#define  PCI_CHSWP_DHA		0x01	/* Device Hiding Arm */
+#define  PCI_CHSWP_EIM		0x02	/* ENUM# Signal Mask */
+#define  PCI_CHSWP_PIE		0x04	/* Pending Insert or Extract */
+#define  PCI_CHSWP_LOO		0x08	/* LED On / Off */
+#define  PCI_CHSWP_PI		0x30	/* Programming Interface */
+#define  PCI_CHSWP_EXT		0x40	/* ENUM# status - extraction */
+#define  PCI_CHSWP_INS		0x80	/* ENUM# status - insertion */
+
+/* PCI Advanced Feature registers */
+
+#define PCI_AF_LENGTH		2
+#define PCI_AF_CAP		3
+#define  PCI_AF_CAP_TP		0x01
+#define  PCI_AF_CAP_FLR		0x02
+#define PCI_AF_CTRL		4
+#define  PCI_AF_CTRL_FLR	0x01
+#define PCI_AF_STATUS		5
+#define  PCI_AF_STATUS_TP	0x01
+
+/* PCI-X registers */
+
+#define PCI_X_CMD		2	/* Modes & Features */
+#define  PCI_X_CMD_DPERR_E	0x0001	/* Data Parity Error Recovery Enable */
+#define  PCI_X_CMD_ERO		0x0002	/* Enable Relaxed Ordering */
+#define  PCI_X_CMD_READ_512	0x0000	/* 512 byte maximum read byte count */
+#define  PCI_X_CMD_READ_1K	0x0004	/* 1Kbyte maximum read byte count */
+#define  PCI_X_CMD_READ_2K	0x0008	/* 2Kbyte maximum read byte count */
+#define  PCI_X_CMD_READ_4K	0x000c	/* 4Kbyte maximum read byte count */
+#define  PCI_X_CMD_MAX_READ	0x000c	/* Max Memory Read Byte Count */
+				/* Max # of outstanding split transactions */
+#define  PCI_X_CMD_SPLIT_1	0x0000	/* Max 1 */
+#define  PCI_X_CMD_SPLIT_2	0x0010	/* Max 2 */
+#define  PCI_X_CMD_SPLIT_3	0x0020	/* Max 3 */
+#define  PCI_X_CMD_SPLIT_4	0x0030	/* Max 4 */
+#define  PCI_X_CMD_SPLIT_8	0x0040	/* Max 8 */
+#define  PCI_X_CMD_SPLIT_12	0x0050	/* Max 12 */
+#define  PCI_X_CMD_SPLIT_16	0x0060	/* Max 16 */
+#define  PCI_X_CMD_SPLIT_32	0x0070	/* Max 32 */
+#define  PCI_X_CMD_MAX_SPLIT	0x0070	/* Max Outstanding Split Transactions */
+#define  PCI_X_CMD_VERSION(x) 	(((x) >> 12) & 3) /* Version */
+#define PCI_X_STATUS		4	/* PCI-X capabilities */
+#define  PCI_X_STATUS_DEVFN	0x000000ff	/* A copy of devfn */
+#define  PCI_X_STATUS_BUS	0x0000ff00	/* A copy of bus nr */
+#define  PCI_X_STATUS_64BIT	0x00010000	/* 64-bit device */
+#define  PCI_X_STATUS_133MHZ	0x00020000	/* 133 MHz capable */
+#define  PCI_X_STATUS_SPL_DISC	0x00040000	/* Split Completion Discarded */
+#define  PCI_X_STATUS_UNX_SPL	0x00080000	/* Unexpected Split Completion */
+#define  PCI_X_STATUS_COMPLEX	0x00100000	/* Device Complexity */
+#define  PCI_X_STATUS_MAX_READ	0x00600000	/* Designed Max Memory Read Count */
+#define  PCI_X_STATUS_MAX_SPLIT	0x03800000	/* Designed Max Outstanding Split Transactions */
+#define  PCI_X_STATUS_MAX_CUM	0x1c000000	/* Designed Max Cumulative Read Size */
+#define  PCI_X_STATUS_SPL_ERR	0x20000000	/* Rcvd Split Completion Error Msg */
+#define  PCI_X_STATUS_266MHZ	0x40000000	/* 266 MHz capable */
+#define  PCI_X_STATUS_533MHZ	0x80000000	/* 533 MHz capable */
+
+/* PCI Bridge Subsystem ID registers */
+
+#define PCI_SSVID_VENDOR_ID     4	/* PCI-Bridge subsystem vendor id register */
+#define PCI_SSVID_DEVICE_ID     6	/* PCI-Bridge subsystem device id register */
+
+/* PCI Express capability registers */
+
+#define PCI_EXP_FLAGS		2	/* Capabilities register */
+#define PCI_EXP_FLAGS_VERS	0x000f	/* Capability version */
+#define PCI_EXP_FLAGS_TYPE	0x00f0	/* Device/Port type */
+#define  PCI_EXP_TYPE_ENDPOINT	0x0	/* Express Endpoint */
+#define  PCI_EXP_TYPE_LEG_END	0x1	/* Legacy Endpoint */
+#define  PCI_EXP_TYPE_ROOT_PORT 0x4	/* Root Port */
+#define  PCI_EXP_TYPE_UPSTREAM	0x5	/* Upstream Port */
+#define  PCI_EXP_TYPE_DOWNSTREAM 0x6	/* Downstream Port */
+#define  PCI_EXP_TYPE_PCI_BRIDGE 0x7	/* PCI/PCI-X Bridge */
+#define  PCI_EXP_TYPE_RC_END	0x9	/* Root Complex Integrated Endpoint */
+#define  PCI_EXP_TYPE_RC_EC	0x10	/* Root Complex Event Collector */
+#define PCI_EXP_FLAGS_SLOT	0x0100	/* Slot implemented */
+#define PCI_EXP_FLAGS_IRQ	0x3e00	/* Interrupt message number */
+#define PCI_EXP_DEVCAP		4	/* Device capabilities */
+#define  PCI_EXP_DEVCAP_PAYLOAD	0x07	/* Max_Payload_Size */
+#define  PCI_EXP_DEVCAP_PHANTOM	0x18	/* Phantom functions */
+#define  PCI_EXP_DEVCAP_EXT_TAG	0x20	/* Extended tags */
+#define  PCI_EXP_DEVCAP_L0S	0x1c0	/* L0s Acceptable Latency */
+#define  PCI_EXP_DEVCAP_L1	0xe00	/* L1 Acceptable Latency */
+#define  PCI_EXP_DEVCAP_ATN_BUT	0x1000	/* Attention Button Present */
+#define  PCI_EXP_DEVCAP_ATN_IND	0x2000	/* Attention Indicator Present */
+#define  PCI_EXP_DEVCAP_PWR_IND	0x4000	/* Power Indicator Present */
+#define  PCI_EXP_DEVCAP_RBER	0x8000	/* Role-Based Error Reporting */
+#define  PCI_EXP_DEVCAP_PWR_VAL	0x3fc0000 /* Slot Power Limit Value */
+#define  PCI_EXP_DEVCAP_PWR_SCL	0xc000000 /* Slot Power Limit Scale */
+#define  PCI_EXP_DEVCAP_FLR     0x10000000 /* Function Level Reset */
+#define PCI_EXP_DEVCTL		8	/* Device Control */
+#define  PCI_EXP_DEVCTL_CERE	0x0001	/* Correctable Error Reporting En. */
+#define  PCI_EXP_DEVCTL_NFERE	0x0002	/* Non-Fatal Error Reporting Enable */
+#define  PCI_EXP_DEVCTL_FERE	0x0004	/* Fatal Error Reporting Enable */
+#define  PCI_EXP_DEVCTL_URRE	0x0008	/* Unsupported Request Reporting En. */
+#define  PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */
+#define  PCI_EXP_DEVCTL_PAYLOAD	0x00e0	/* Max_Payload_Size */
+#define  PCI_EXP_DEVCTL_EXT_TAG	0x0100	/* Extended Tag Field Enable */
+#define  PCI_EXP_DEVCTL_PHANTOM	0x0200	/* Phantom Functions Enable */
+#define  PCI_EXP_DEVCTL_AUX_PME	0x0400	/* Auxiliary Power PM Enable */
+#define  PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800  /* Enable No Snoop */
+#define  PCI_EXP_DEVCTL_READRQ	0x7000	/* Max_Read_Request_Size */
+#define  PCI_EXP_DEVCTL_BCR_FLR 0x8000  /* Bridge Configuration Retry / FLR */
+#define PCI_EXP_DEVSTA		10	/* Device Status */
+#define  PCI_EXP_DEVSTA_CED	0x01	/* Correctable Error Detected */
+#define  PCI_EXP_DEVSTA_NFED	0x02	/* Non-Fatal Error Detected */
+#define  PCI_EXP_DEVSTA_FED	0x04	/* Fatal Error Detected */
+#define  PCI_EXP_DEVSTA_URD	0x08	/* Unsupported Request Detected */
+#define  PCI_EXP_DEVSTA_AUXPD	0x10	/* AUX Power Detected */
+#define  PCI_EXP_DEVSTA_TRPND	0x20	/* Transactions Pending */
+#define PCI_EXP_LNKCAP		12	/* Link Capabilities */
+#define  PCI_EXP_LNKCAP_SLS	0x0000000f /* Supported Link Speeds */
+#define  PCI_EXP_LNKCAP_MLW	0x000003f0 /* Maximum Link Width */
+#define  PCI_EXP_LNKCAP_ASPMS	0x00000c00 /* ASPM Support */
+#define  PCI_EXP_LNKCAP_L0SEL	0x00007000 /* L0s Exit Latency */
+#define  PCI_EXP_LNKCAP_L1EL	0x00038000 /* L1 Exit Latency */
+#define  PCI_EXP_LNKCAP_CLKPM	0x00040000 /* L1 Clock Power Management */
+#define  PCI_EXP_LNKCAP_SDERC	0x00080000 /* Suprise Down Error Reporting Capable */
+#define  PCI_EXP_LNKCAP_DLLLARC	0x00100000 /* Data Link Layer Link Active Reporting Capable */
+#define  PCI_EXP_LNKCAP_LBNC	0x00200000 /* Link Bandwidth Notification Capability */
+#define  PCI_EXP_LNKCAP_PN	0xff000000 /* Port Number */
+#define PCI_EXP_LNKCTL		16	/* Link Control */
+#define  PCI_EXP_LNKCTL_ASPMC	0x0003	/* ASPM Control */
+#define  PCI_EXP_LNKCTL_RCB	0x0008	/* Read Completion Boundary */
+#define  PCI_EXP_LNKCTL_LD	0x0010	/* Link Disable */
+#define  PCI_EXP_LNKCTL_RL	0x0020	/* Retrain Link */
+#define  PCI_EXP_LNKCTL_CCC	0x0040	/* Common Clock Configuration */
+#define  PCI_EXP_LNKCTL_ES	0x0080	/* Extended Synch */
+#define  PCI_EXP_LNKCTL_CLKREQ_EN 0x100	/* Enable clkreq */
+#define  PCI_EXP_LNKCTL_HAWD	0x0200	/* Hardware Autonomous Width Disable */
+#define  PCI_EXP_LNKCTL_LBMIE	0x0400	/* Link Bandwidth Management Interrupt Enable */
+#define  PCI_EXP_LNKCTL_LABIE	0x0800	/* Lnk Autonomous Bandwidth Interrupt Enable */
+#define PCI_EXP_LNKSTA		18	/* Link Status */
+#define  PCI_EXP_LNKSTA_CLS	0x000f	/* Current Link Speed */
+#define  PCI_EXP_LNKSTA_CLS_2_5GB 0x01	/* Current Link Speed 2.5GT/s */
+#define  PCI_EXP_LNKSTA_CLS_5_0GB 0x02	/* Current Link Speed 5.0GT/s */
+#define  PCI_EXP_LNKSTA_NLW	0x03f0	/* Nogotiated Link Width */
+#define  PCI_EXP_LNKSTA_NLW_SHIFT 4	/* start of NLW mask in link status */
+#define  PCI_EXP_LNKSTA_LT	0x0800	/* Link Training */
+#define  PCI_EXP_LNKSTA_SLC	0x1000	/* Slot Clock Configuration */
+#define  PCI_EXP_LNKSTA_DLLLA	0x2000	/* Data Link Layer Link Active */
+#define  PCI_EXP_LNKSTA_LBMS	0x4000	/* Link Bandwidth Management Status */
+#define  PCI_EXP_LNKSTA_LABS	0x8000	/* Link Autonomous Bandwidth Status */
+#define PCI_EXP_SLTCAP		20	/* Slot Capabilities */
+#define  PCI_EXP_SLTCAP_ABP	0x00000001 /* Attention Button Present */
+#define  PCI_EXP_SLTCAP_PCP	0x00000002 /* Power Controller Present */
+#define  PCI_EXP_SLTCAP_MRLSP	0x00000004 /* MRL Sensor Present */
+#define  PCI_EXP_SLTCAP_AIP	0x00000008 /* Attention Indicator Present */
+#define  PCI_EXP_SLTCAP_PIP	0x00000010 /* Power Indicator Present */
+#define  PCI_EXP_SLTCAP_HPS	0x00000020 /* Hot-Plug Surprise */
+#define  PCI_EXP_SLTCAP_HPC	0x00000040 /* Hot-Plug Capable */
+#define  PCI_EXP_SLTCAP_SPLV	0x00007f80 /* Slot Power Limit Value */
+#define  PCI_EXP_SLTCAP_SPLS	0x00018000 /* Slot Power Limit Scale */
+#define  PCI_EXP_SLTCAP_EIP	0x00020000 /* Electromechanical Interlock Present */
+#define  PCI_EXP_SLTCAP_NCCS	0x00040000 /* No Command Completed Support */
+#define  PCI_EXP_SLTCAP_PSN	0xfff80000 /* Physical Slot Number */
+#define PCI_EXP_SLTCTL		24	/* Slot Control */
+#define  PCI_EXP_SLTCTL_ABPE	0x0001	/* Attention Button Pressed Enable */
+#define  PCI_EXP_SLTCTL_PFDE	0x0002	/* Power Fault Detected Enable */
+#define  PCI_EXP_SLTCTL_MRLSCE	0x0004	/* MRL Sensor Changed Enable */
+#define  PCI_EXP_SLTCTL_PDCE	0x0008	/* Presence Detect Changed Enable */
+#define  PCI_EXP_SLTCTL_CCIE	0x0010	/* Command Completed Interrupt Enable */
+#define  PCI_EXP_SLTCTL_HPIE	0x0020	/* Hot-Plug Interrupt Enable */
+#define  PCI_EXP_SLTCTL_AIC	0x00c0	/* Attention Indicator Control */
+#define  PCI_EXP_SLTCTL_PIC	0x0300	/* Power Indicator Control */
+#define  PCI_EXP_SLTCTL_PCC	0x0400	/* Power Controller Control */
+#define  PCI_EXP_SLTCTL_EIC	0x0800	/* Electromechanical Interlock Control */
+#define  PCI_EXP_SLTCTL_DLLSCE	0x1000	/* Data Link Layer State Changed Enable */
+#define PCI_EXP_SLTSTA		26	/* Slot Status */
+#define  PCI_EXP_SLTSTA_ABP	0x0001	/* Attention Button Pressed */
+#define  PCI_EXP_SLTSTA_PFD	0x0002	/* Power Fault Detected */
+#define  PCI_EXP_SLTSTA_MRLSC	0x0004	/* MRL Sensor Changed */
+#define  PCI_EXP_SLTSTA_PDC	0x0008	/* Presence Detect Changed */
+#define  PCI_EXP_SLTSTA_CC	0x0010	/* Command Completed */
+#define  PCI_EXP_SLTSTA_MRLSS	0x0020	/* MRL Sensor State */
+#define  PCI_EXP_SLTSTA_PDS	0x0040	/* Presence Detect State */
+#define  PCI_EXP_SLTSTA_EIS	0x0080	/* Electromechanical Interlock Status */
+#define  PCI_EXP_SLTSTA_DLLSC	0x0100	/* Data Link Layer State Changed */
+#define PCI_EXP_RTCTL		28	/* Root Control */
+#define  PCI_EXP_RTCTL_SECEE	0x01	/* System Error on Correctable Error */
+#define  PCI_EXP_RTCTL_SENFEE	0x02	/* System Error on Non-Fatal Error */
+#define  PCI_EXP_RTCTL_SEFEE	0x04	/* System Error on Fatal Error */
+#define  PCI_EXP_RTCTL_PMEIE	0x08	/* PME Interrupt Enable */
+#define  PCI_EXP_RTCTL_CRSSVE	0x10	/* CRS Software Visibility Enable */
+#define PCI_EXP_RTCAP		30	/* Root Capabilities */
+#define PCI_EXP_RTSTA		32	/* Root Status */
+#define PCI_EXP_DEVCAP2		36	/* Device Capabilities 2 */
+#define  PCI_EXP_DEVCAP2_ARI	0x20	/* Alternative Routing-ID */
+#define PCI_EXP_DEVCTL2		40	/* Device Control 2 */
+#define  PCI_EXP_DEVCTL2_ARI	0x20	/* Alternative Routing-ID */
+#define PCI_EXP_LNKCTL2		48	/* Link Control 2 */
+#define PCI_EXP_SLTCTL2		56	/* Slot Control 2 */
+
+/* Extended Capabilities (PCI-X 2.0 and Express) */
+#define PCI_EXT_CAP_ID(header)		(header & 0x0000ffff)
+#define PCI_EXT_CAP_VER(header)		((header >> 16) & 0xf)
+#define PCI_EXT_CAP_NEXT(header)	((header >> 20) & 0xffc)
+
+#define PCI_EXT_CAP_ID_ERR	1
+#define PCI_EXT_CAP_ID_VC	2
+#define PCI_EXT_CAP_ID_DSN	3
+#define PCI_EXT_CAP_ID_PWR	4
+#define PCI_EXT_CAP_ID_VNDR	11
+#define PCI_EXT_CAP_ID_ACS	13
+#define PCI_EXT_CAP_ID_ARI	14
+#define PCI_EXT_CAP_ID_ATS	15
+#define PCI_EXT_CAP_ID_SRIOV	16
+
+/* Advanced Error Reporting */
+#define PCI_ERR_UNCOR_STATUS	4	/* Uncorrectable Error Status */
+#define  PCI_ERR_UNC_TRAIN	0x00000001	/* Training */
+#define  PCI_ERR_UNC_DLP	0x00000010	/* Data Link Protocol */
+#define  PCI_ERR_UNC_POISON_TLP	0x00001000	/* Poisoned TLP */
+#define  PCI_ERR_UNC_FCP	0x00002000	/* Flow Control Protocol */
+#define  PCI_ERR_UNC_COMP_TIME	0x00004000	/* Completion Timeout */
+#define  PCI_ERR_UNC_COMP_ABORT	0x00008000	/* Completer Abort */
+#define  PCI_ERR_UNC_UNX_COMP	0x00010000	/* Unexpected Completion */
+#define  PCI_ERR_UNC_RX_OVER	0x00020000	/* Receiver Overflow */
+#define  PCI_ERR_UNC_MALF_TLP	0x00040000	/* Malformed TLP */
+#define  PCI_ERR_UNC_ECRC	0x00080000	/* ECRC Error Status */
+#define  PCI_ERR_UNC_UNSUP	0x00100000	/* Unsupported Request */
+#define PCI_ERR_UNCOR_MASK	8	/* Uncorrectable Error Mask */
+	/* Same bits as above */
+#define PCI_ERR_UNCOR_SEVER	12	/* Uncorrectable Error Severity */
+	/* Same bits as above */
+#define PCI_ERR_COR_STATUS	16	/* Correctable Error Status */
+#define  PCI_ERR_COR_RCVR	0x00000001	/* Receiver Error Status */
+#define  PCI_ERR_COR_BAD_TLP	0x00000040	/* Bad TLP Status */
+#define  PCI_ERR_COR_BAD_DLLP	0x00000080	/* Bad DLLP Status */
+#define  PCI_ERR_COR_REP_ROLL	0x00000100	/* REPLAY_NUM Rollover */
+#define  PCI_ERR_COR_REP_TIMER	0x00001000	/* Replay Timer Timeout */
+#define PCI_ERR_COR_MASK	20	/* Correctable Error Mask */
+	/* Same bits as above */
+#define PCI_ERR_CAP		24	/* Advanced Error Capabilities */
+#define  PCI_ERR_CAP_FEP(x)	((x) & 31)	/* First Error Pointer */
+#define  PCI_ERR_CAP_ECRC_GENC	0x00000020	/* ECRC Generation Capable */
+#define  PCI_ERR_CAP_ECRC_GENE	0x00000040	/* ECRC Generation Enable */
+#define  PCI_ERR_CAP_ECRC_CHKC	0x00000080	/* ECRC Check Capable */
+#define  PCI_ERR_CAP_ECRC_CHKE	0x00000100	/* ECRC Check Enable */
+#define PCI_ERR_HEADER_LOG	28	/* Header Log Register (16 bytes) */
+#define PCI_ERR_ROOT_COMMAND	44	/* Root Error Command */
+/* Correctable Err Reporting Enable */
+#define PCI_ERR_ROOT_CMD_COR_EN		0x00000001
+/* Non-fatal Err Reporting Enable */
+#define PCI_ERR_ROOT_CMD_NONFATAL_EN	0x00000002
+/* Fatal Err Reporting Enable */
+#define PCI_ERR_ROOT_CMD_FATAL_EN	0x00000004
+#define PCI_ERR_ROOT_STATUS	48
+#define PCI_ERR_ROOT_COR_RCV		0x00000001	/* ERR_COR Received */
+/* Multi ERR_COR Received */
+#define PCI_ERR_ROOT_MULTI_COR_RCV	0x00000002
+/* ERR_FATAL/NONFATAL Recevied */
+#define PCI_ERR_ROOT_UNCOR_RCV		0x00000004
+/* Multi ERR_FATAL/NONFATAL Recevied */
+#define PCI_ERR_ROOT_MULTI_UNCOR_RCV	0x00000008
+#define PCI_ERR_ROOT_FIRST_FATAL	0x00000010	/* First Fatal */
+#define PCI_ERR_ROOT_NONFATAL_RCV	0x00000020	/* Non-Fatal Received */
+#define PCI_ERR_ROOT_FATAL_RCV		0x00000040	/* Fatal Received */
+#define PCI_ERR_ROOT_ERR_SRC	52	/* Error Source Identification */
+
+/* Virtual Channel */
+#define PCI_VC_PORT_REG1	4
+#define PCI_VC_PORT_REG2	8
+#define PCI_VC_PORT_CTRL	12
+#define PCI_VC_PORT_STATUS	14
+#define PCI_VC_RES_CAP		16
+#define PCI_VC_RES_CTRL		20
+#define PCI_VC_RES_STATUS	26
+
+/* Power Budgeting */
+#define PCI_PWR_DSR		4	/* Data Select Register */
+#define PCI_PWR_DATA		8	/* Data Register */
+#define  PCI_PWR_DATA_BASE(x)	((x) & 0xff)	    /* Base Power */
+#define  PCI_PWR_DATA_SCALE(x)	(((x) >> 8) & 3)    /* Data Scale */
+#define  PCI_PWR_DATA_PM_SUB(x)	(((x) >> 10) & 7)   /* PM Sub State */
+#define  PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */
+#define  PCI_PWR_DATA_TYPE(x)	(((x) >> 15) & 7)   /* Type */
+#define  PCI_PWR_DATA_RAIL(x)	(((x) >> 18) & 7)   /* Power Rail */
+#define PCI_PWR_CAP		12	/* Capability */
+#define  PCI_PWR_CAP_BUDGET(x)	((x) & 1)	/* Included in system budget */
+
+/*
+ * Hypertransport sub capability types
+ *
+ * Unfortunately there are both 3 bit and 5 bit capability types defined
+ * in the HT spec, catering for that is a little messy. You probably don't
+ * want to use these directly, just use pci_find_ht_capability() and it
+ * will do the right thing for you.
+ */
+#define HT_3BIT_CAP_MASK	0xE0
+#define HT_CAPTYPE_SLAVE	0x00	/* Slave/Primary link configuration */
+#define HT_CAPTYPE_HOST		0x20	/* Host/Secondary link configuration */
+
+#define HT_5BIT_CAP_MASK	0xF8
+#define HT_CAPTYPE_IRQ		0x80	/* IRQ Configuration */
+#define HT_CAPTYPE_REMAPPING_40	0xA0	/* 40 bit address remapping */
+#define HT_CAPTYPE_REMAPPING_64 0xA2	/* 64 bit address remapping */
+#define HT_CAPTYPE_UNITID_CLUMP	0x90	/* Unit ID clumping */
+#define HT_CAPTYPE_EXTCONF	0x98	/* Extended Configuration Space Access */
+#define HT_CAPTYPE_MSI_MAPPING	0xA8	/* MSI Mapping Capability */
+#define  HT_MSI_FLAGS		0x02		/* Offset to flags */
+#define  HT_MSI_FLAGS_ENABLE	0x1		/* Mapping enable */
+#define  HT_MSI_FLAGS_FIXED	0x2		/* Fixed mapping only */
+#define  HT_MSI_FIXED_ADDR	0x00000000FEE00000ULL	/* Fixed addr */
+#define  HT_MSI_ADDR_LO		0x04		/* Offset to low addr bits */
+#define  HT_MSI_ADDR_LO_MASK	0xFFF00000	/* Low address bit mask */
+#define  HT_MSI_ADDR_HI		0x08		/* Offset to high addr bits */
+#define HT_CAPTYPE_DIRECT_ROUTE	0xB0	/* Direct routing configuration */
+#define HT_CAPTYPE_VCSET	0xB8	/* Virtual Channel configuration */
+#define HT_CAPTYPE_ERROR_RETRY	0xC0	/* Retry on error configuration */
+#define HT_CAPTYPE_GEN3		0xD0	/* Generation 3 hypertransport configuration */
+#define HT_CAPTYPE_PM		0xE0	/* Hypertransport powermanagement configuration */
+
+/* Alternative Routing-ID Interpretation */
+#define PCI_ARI_CAP		0x04	/* ARI Capability Register */
+#define  PCI_ARI_CAP_MFVC	0x0001	/* MFVC Function Groups Capability */
+#define  PCI_ARI_CAP_ACS	0x0002	/* ACS Function Groups Capability */
+#define  PCI_ARI_CAP_NFN(x)	(((x) >> 8) & 0xff) /* Next Function Number */
+#define PCI_ARI_CTRL		0x06	/* ARI Control Register */
+#define  PCI_ARI_CTRL_MFVC	0x0001	/* MFVC Function Groups Enable */
+#define  PCI_ARI_CTRL_ACS	0x0002	/* ACS Function Groups Enable */
+#define  PCI_ARI_CTRL_FG(x)	(((x) >> 4) & 7) /* Function Group */
+
+/* Address Translation Service */
+#define PCI_ATS_CAP		0x04	/* ATS Capability Register */
+#define  PCI_ATS_CAP_QDEP(x)	((x) & 0x1f)	/* Invalidate Queue Depth */
+#define  PCI_ATS_MAX_QDEP	32	/* Max Invalidate Queue Depth */
+#define PCI_ATS_CTRL		0x06	/* ATS Control Register */
+#define  PCI_ATS_CTRL_ENABLE	0x8000	/* ATS Enable */
+#define  PCI_ATS_CTRL_STU(x)	((x) & 0x1f)	/* Smallest Translation Unit */
+#define  PCI_ATS_MIN_STU	12	/* shift of minimum STU block */
+
+/* Single Root I/O Virtualization */
+#define PCI_SRIOV_CAP		0x04	/* SR-IOV Capabilities */
+#define  PCI_SRIOV_CAP_VFM	0x01	/* VF Migration Capable */
+#define  PCI_SRIOV_CAP_INTR(x)	((x) >> 21) /* Interrupt Message Number */
+#define PCI_SRIOV_CTRL		0x08	/* SR-IOV Control */
+#define  PCI_SRIOV_CTRL_VFE	0x01	/* VF Enable */
+#define  PCI_SRIOV_CTRL_VFM	0x02	/* VF Migration Enable */
+#define  PCI_SRIOV_CTRL_INTR	0x04	/* VF Migration Interrupt Enable */
+#define  PCI_SRIOV_CTRL_MSE	0x08	/* VF Memory Space Enable */
+#define  PCI_SRIOV_CTRL_ARI	0x10	/* ARI Capable Hierarchy */
+#define PCI_SRIOV_STATUS	0x0a	/* SR-IOV Status */
+#define  PCI_SRIOV_STATUS_VFM	0x01	/* VF Migration Status */
+#define PCI_SRIOV_INITIAL_VF	0x0c	/* Initial VFs */
+#define PCI_SRIOV_TOTAL_VF	0x0e	/* Total VFs */
+#define PCI_SRIOV_NUM_VF	0x10	/* Number of VFs */
+#define PCI_SRIOV_FUNC_LINK	0x12	/* Function Dependency Link */
+#define PCI_SRIOV_VF_OFFSET	0x14	/* First VF Offset */
+#define PCI_SRIOV_VF_STRIDE	0x16	/* Following VF Stride */
+#define PCI_SRIOV_VF_DID	0x1a	/* VF Device ID */
+#define PCI_SRIOV_SUP_PGSIZE	0x1c	/* Supported Page Sizes */
+#define PCI_SRIOV_SYS_PGSIZE	0x20	/* System Page Size */
+#define PCI_SRIOV_BAR		0x24	/* VF BAR0 */
+#define  PCI_SRIOV_NUM_BARS	6	/* Number of VF BARs */
+#define PCI_SRIOV_VFM		0x3c	/* VF Migration State Array Offset*/
+#define  PCI_SRIOV_VFM_BIR(x)	((x) & 7)	/* State BIR */
+#define  PCI_SRIOV_VFM_OFFSET(x) ((x) & ~7)	/* State Offset */
+#define  PCI_SRIOV_VFM_UA	0x0	/* Inactive.Unavailable */
+#define  PCI_SRIOV_VFM_MI	0x1	/* Dormant.MigrateIn */
+#define  PCI_SRIOV_VFM_MO	0x2	/* Active.MigrateOut */
+#define  PCI_SRIOV_VFM_AV	0x3	/* Active.Available */
+
+/* Access Control Service */
+#define PCI_ACS_CAP		0x04	/* ACS Capability Register */
+#define  PCI_ACS_SV		0x01	/* Source Validation */
+#define  PCI_ACS_TB		0x02	/* Translation Blocking */
+#define  PCI_ACS_RR		0x04	/* P2P Request Redirect */
+#define  PCI_ACS_CR		0x08	/* P2P Completion Redirect */
+#define  PCI_ACS_UF		0x10	/* Upstream Forwarding */
+#define  PCI_ACS_EC		0x20	/* P2P Egress Control */
+#define  PCI_ACS_DT		0x40	/* Direct Translated P2P */
+#define PCI_ACS_CTRL		0x06	/* ACS Control Register */
+#define PCI_ACS_EGRESS_CTL_V	0x08	/* ACS Egress Control Vector */
+
+#endif /* LINUX_PCI_REGS_H */