ACPICA: Add post-order callback to acpi_walk_namespace
[safe/jmp/linux-2.6] / drivers / pci / hotplug / cpqphp_core.c
index 1fc2599..075b4f4 100644 (file)
@@ -25,8 +25,7 @@
  * Send feedback to <greg@kroah.com>
  *
  * Jan 12, 2003 -      Added 66/100/133MHz PCI-X support,
- *                     Torben Mathiasen <torben.mathiasen@hp.com>
- *
+ *                     Torben Mathiasen <torben.mathiasen@hp.com>
  */
 
 #include <linux/module.h>
@@ -37,6 +36,7 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 
@@ -44,7 +44,6 @@
 
 #include "cpqphp.h"
 #include "cpqphp_nvram.h"
-#include "../../../arch/i386/pci/pci.h"        /* horrible hack showing how processor dependent we are... */
 
 
 /* Global variables */
@@ -52,6 +51,7 @@ int cpqhp_debug;
 int cpqhp_legacy_mode;
 struct controller *cpqhp_ctrl_list;    /* = NULL */
 struct pci_func *cpqhp_slot_list[256];
+struct irq_routing_table *cpqhp_routing_table;
 
 /* local variables */
 static void __iomem *smbios_table;
@@ -77,33 +77,6 @@ MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
 
 #define CPQHPC_MODULE_MINOR 208
 
-static int one_time_init       (void);
-static int set_attention_status        (struct hotplug_slot *slot, u8 value);
-static int process_SI          (struct hotplug_slot *slot);
-static int process_SS          (struct hotplug_slot *slot);
-static int hardware_test       (struct hotplug_slot *slot, u32 value);
-static int get_power_status    (struct hotplug_slot *slot, u8 *value);
-static int get_attention_status        (struct hotplug_slot *slot, u8 *value);
-static int get_latch_status    (struct hotplug_slot *slot, u8 *value);
-static int get_adapter_status  (struct hotplug_slot *slot, u8 *value);
-static int get_max_bus_speed   (struct hotplug_slot *slot, enum pci_bus_speed *value);
-static int get_cur_bus_speed   (struct hotplug_slot *slot, enum pci_bus_speed *value);
-
-static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = {
-       .owner =                THIS_MODULE,
-       .set_attention_status = set_attention_status,
-       .enable_slot =          process_SI,
-       .disable_slot =         process_SS,
-       .hardware_test =        hardware_test,
-       .get_power_status =     get_power_status,
-       .get_attention_status = get_attention_status,
-       .get_latch_status =     get_latch_status,
-       .get_adapter_status =   get_adapter_status,
-       .get_max_bus_speed =    get_max_bus_speed,
-       .get_cur_bus_speed =    get_cur_bus_speed,
-};
-
-
 static inline int is_slot64bit(struct slot *slot)
 {
        return (readb(slot->p_sm_slot + SMBIOS_SLOT_WIDTH) == 0x06) ? 1 : 0;
@@ -116,12 +89,10 @@ static inline int is_slot66mhz(struct slot *slot)
 
 /**
  * detect_SMBIOS_pointer - find the System Management BIOS Table in mem region.
- *
  * @begin: begin pointer for region to be scanned.
  * @end: end pointer for region to be scanned.
  *
- * Returns pointer to the head of the SMBIOS tables (or NULL)
- *
+ * Returns pointer to the head of the SMBIOS tables (or %NULL).
  */
 static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *end)
 {
@@ -145,7 +116,7 @@ static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *e
                        break;
                }
        }
-       
+
        if (!status)
                fp = NULL;
 
@@ -156,9 +127,9 @@ static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *e
 
 /**
  * init_SERR - Initializes the per slot SERR generation.
+ * @ctrl: controller to use
  *
  * For unexpected switch opens
- *
  */
 static int init_SERR(struct controller * ctrl)
 {
@@ -172,7 +143,7 @@ static int init_SERR(struct controller * ctrl)
        tempdword = ctrl->first_slot;
 
        number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
-       // Loop through slots
+       /* Loop through slots */
        while (number_of_slots) {
                physical_slot = tempdword;
                writeb(0, ctrl->hpc_reg + SLOT_SERR);
@@ -183,54 +154,56 @@ static int init_SERR(struct controller * ctrl)
        return 0;
 }
 
-
-/* nice debugging output */
-static int pci_print_IRQ_route (void)
+static int init_cpqhp_routing_table(void)
 {
-       struct irq_routing_table *routing_table;
        int len;
-       int loop;
-
-       u8 tbus, tdevice, tslot;
 
-       routing_table = pcibios_get_irq_routing_table();
-       if (routing_table == NULL) {
-               err("No BIOS Routing Table??? Not good\n");
+       cpqhp_routing_table = pcibios_get_irq_routing_table();
+       if (cpqhp_routing_table == NULL)
                return -ENOMEM;
-       }
 
-       len = (routing_table->size - sizeof(struct irq_routing_table)) /
-                       sizeof(struct irq_info);
-       // Make sure I got at least one entry
+       len = cpqhp_routing_table_length();
        if (len == 0) {
-               kfree(routing_table);
+               kfree(cpqhp_routing_table);
+               cpqhp_routing_table = NULL;
                return -1;
        }
 
-       dbg("bus dev func slot\n");
+       return 0;
+}
+
+/* nice debugging output */
+static void pci_print_IRQ_route(void)
+{
+       int len;
+       int loop;
+       u8 tbus, tdevice, tslot;
+
+       len = cpqhp_routing_table_length();
 
+       dbg("bus dev func slot\n");
        for (loop = 0; loop < len; ++loop) {
-               tbus = routing_table->slots[loop].bus;
-               tdevice = routing_table->slots[loop].devfn;
-               tslot = routing_table->slots[loop].slot;
+               tbus = cpqhp_routing_table->slots[loop].bus;
+               tdevice = cpqhp_routing_table->slots[loop].devfn;
+               tslot = cpqhp_routing_table->slots[loop].slot;
                dbg("%d %d %d %d\n", tbus, tdevice >> 3, tdevice & 0x7, tslot);
 
        }
-       kfree(routing_table);
-       return 0;
+       return;
 }
 
 
 /**
  * get_subsequent_smbios_entry: get the next entry from bios table.
- *
- * Gets the first entry if previous == NULL
- * Otherwise, returns the next entry
- * Uses global SMBIOS Table pointer
- *
+ * @smbios_start: where to start in the SMBIOS table
+ * @smbios_table: location of the SMBIOS table
  * @curr: %NULL or pointer to previously returned structure
  *
- * returns a pointer to an SMBIOS structure or NULL if none found
+ * Gets the first entry if previous == NULL;
+ * otherwise, returns the next entry.
+ * Uses global SMBIOS Table pointer.
+ *
+ * Returns a pointer to an SMBIOS structure or NULL if none found.
  */
 static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start,
                                                void __iomem *smbios_table,
@@ -242,9 +215,9 @@ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start,
        void __iomem *p_max;
 
        if (!smbios_table || !curr)
-               return(NULL);
+               return NULL;
 
-       // set p_max to the end of the table
+       /* set p_max to the end of the table */
        p_max = smbios_start + readw(smbios_table + ST_LENGTH);
 
        p_temp = curr;
@@ -253,35 +226,35 @@ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start,
        while ((p_temp < p_max) && !bail) {
                /* Look for the double NULL terminator
                 * The first condition is the previous byte
-                * and the second is the curr */
-               if (!previous_byte && !(readb(p_temp))) {
+                * and the second is the curr
+                */
+               if (!previous_byte && !(readb(p_temp)))
                        bail = 1;
-               }
 
                previous_byte = readb(p_temp);
                p_temp++;
        }
 
-       if (p_temp < p_max) {
+       if (p_temp < p_max)
                return p_temp;
-       } else {
+       else
                return NULL;
-       }
 }
 
 
 /**
- * get_SMBIOS_entry
- *
- * @type:SMBIOS structure type to be returned
+ * get_SMBIOS_entry - return the requested SMBIOS entry or %NULL
+ * @smbios_start: where to start in the SMBIOS table
+ * @smbios_table: location of the SMBIOS table
+ * @type: SMBIOS structure type to be returned
  * @previous: %NULL or pointer to previously returned structure
  *
- * Gets the first entry of the specified type if previous == NULL
+ * Gets the first entry of the specified type if previous == %NULL;
  * Otherwise, returns the next entry of the given type.
- * Uses global SMBIOS Table pointer
- * Uses get_subsequent_smbios_entry
+ * Uses global SMBIOS Table pointer.
+ * Uses get_subsequent_smbios_entry.
  *
- * returns a pointer to an SMBIOS structure or %NULL if none found
+ * Returns a pointer to an SMBIOS structure or %NULL if none found.
  */
 static void __iomem *get_SMBIOS_entry(void __iomem *smbios_start,
                                        void __iomem *smbios_table,
@@ -291,21 +264,18 @@ static void __iomem *get_SMBIOS_entry(void __iomem *smbios_start,
        if (!smbios_table)
                return NULL;
 
-       if (!previous) {                  
+       if (!previous)
                previous = smbios_start;
-       } else {
+       else
                previous = get_subsequent_smbios_entry(smbios_start,
                                        smbios_table, previous);
-       }
 
-       while (previous) {
-               if (readb(previous + SMBIOS_GENERIC_TYPE) != type) {
+       while (previous)
+               if (readb(previous + SMBIOS_GENERIC_TYPE) != type)
                        previous = get_subsequent_smbios_entry(smbios_start,
                                                smbios_table, previous);
-               } else {
+               else
                        break;
-               }
-       }
 
        return previous;
 }
@@ -314,152 +284,13 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
 {
        struct slot *slot = hotplug_slot->private;
 
-       dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        kfree(slot->hotplug_slot->info);
-       kfree(slot->hotplug_slot->name);
        kfree(slot->hotplug_slot);
        kfree(slot);
 }
 
-static int ctrl_slot_setup(struct controller *ctrl,
-                       void __iomem *smbios_start,
-                       void __iomem *smbios_table)
-{
-       struct slot *slot;
-       struct hotplug_slot *hotplug_slot;
-       struct hotplug_slot_info *hotplug_slot_info;
-       u8 number_of_slots;
-       u8 slot_device;
-       u8 slot_number;
-       u8 ctrl_slot;
-       u32 tempdword;
-       void __iomem *slot_entry= NULL;
-       int result = -ENOMEM;
-
-       dbg("%s\n", __FUNCTION__);
-
-       tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
-
-       number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
-       slot_device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
-       slot_number = ctrl->first_slot;
-
-       while (number_of_slots) {
-               slot = kzalloc(sizeof(*slot), GFP_KERNEL);
-               if (!slot)
-                       goto error;
-
-               slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)),
-                                               GFP_KERNEL);
-               if (!slot->hotplug_slot)
-                       goto error_slot;
-               hotplug_slot = slot->hotplug_slot;
-
-               hotplug_slot->info =
-                               kzalloc(sizeof(*(hotplug_slot->info)),
-                                                       GFP_KERNEL);
-               if (!hotplug_slot->info)
-                       goto error_hpslot;
-               hotplug_slot_info = hotplug_slot->info;
-               hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
-
-               if (!hotplug_slot->name)
-                       goto error_info;
-
-               slot->ctrl = ctrl;
-               slot->bus = ctrl->bus;
-               slot->device = slot_device;
-               slot->number = slot_number;
-               dbg("slot->number = %d\n", slot->number);
-
-               slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9,
-                                       slot_entry);
-
-               while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) !=
-                               slot->number)) {
-                       slot_entry = get_SMBIOS_entry(smbios_start,
-                                               smbios_table, 9, slot_entry);
-               }
-
-               slot->p_sm_slot = slot_entry;
-
-               init_timer(&slot->task_event);
-               slot->task_event.expires = jiffies + 5 * HZ;
-               slot->task_event.function = cpqhp_pushbutton_thread;
-
-               //FIXME: these capabilities aren't used but if they are
-               //       they need to be correctly implemented
-               slot->capabilities |= PCISLOT_REPLACE_SUPPORTED;
-               slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED;
-
-               if (is_slot64bit(slot))
-                       slot->capabilities |= PCISLOT_64_BIT_SUPPORTED;
-               if (is_slot66mhz(slot))
-                       slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED;
-               if (ctrl->speed == PCI_SPEED_66MHz)
-                       slot->capabilities |= PCISLOT_66_MHZ_OPERATION;
-
-               ctrl_slot =
-                       slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4);
-
-               // Check presence
-               slot->capabilities |=
-                       ((((~tempdword) >> 23) |
-                        ((~tempdword) >> 15)) >> ctrl_slot) & 0x02;
-               // Check the switch state
-               slot->capabilities |=
-                       ((~tempdword & 0xFF) >> ctrl_slot) & 0x01;
-               // Check the slot enable
-               slot->capabilities |=
-                       ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04;
-
-               /* register this slot with the hotplug pci core */
-               hotplug_slot->release = &release_slot;
-               hotplug_slot->private = slot;
-               make_slot_name(hotplug_slot->name, SLOT_NAME_SIZE, slot);
-               hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
-               
-               hotplug_slot_info->power_status = get_slot_enabled(ctrl, slot);
-               hotplug_slot_info->attention_status =
-                       cpq_get_attention_status(ctrl, slot);
-               hotplug_slot_info->latch_status =
-                       cpq_get_latch_status(ctrl, slot);
-               hotplug_slot_info->adapter_status =
-                       get_presence_status(ctrl, slot);
-               
-               dbg("registering bus %d, dev %d, number %d, "
-                               "ctrl->slot_device_offset %d, slot %d\n",
-                               slot->bus, slot->device,
-                               slot->number, ctrl->slot_device_offset,
-                               slot_number);
-               result = pci_hp_register(hotplug_slot);
-               if (result) {
-                       err("pci_hp_register failed with error %d\n", result);
-                       goto error_name;
-               }
-               
-               slot->next = ctrl->slot;
-               ctrl->slot = slot;
-
-               number_of_slots--;
-               slot_device++;
-               slot_number++;
-       }
-
-       return 0;
-error_name:
-       kfree(hotplug_slot->name);
-error_info:
-       kfree(hotplug_slot_info);
-error_hpslot:
-       kfree(hotplug_slot);
-error_slot:
-       kfree(slot);
-error:
-       return result;
-}
-
 static int ctrl_slot_cleanup (struct controller * ctrl)
 {
        struct slot *old_slot, *next_slot;
@@ -476,111 +307,96 @@ static int ctrl_slot_cleanup (struct controller * ctrl)
 
        cpqhp_remove_debugfs_files(ctrl);
 
-       //Free IRQ associated with hot plug device
+       /* Free IRQ associated with hot plug device */
        free_irq(ctrl->interrupt, ctrl);
-       //Unmap the memory
+       /* Unmap the memory */
        iounmap(ctrl->hpc_reg);
-       //Finally reclaim PCI mem
+       /* Finally reclaim PCI mem */
        release_mem_region(pci_resource_start(ctrl->pci_dev, 0),
                           pci_resource_len(ctrl->pci_dev, 0));
 
-       return(0);
+       return 0;
 }
 
 
-//============================================================================
-// function:   get_slot_mapping
-//
-// Description: Attempts to determine a logical slot mapping for a PCI
-//             device.  Won't work for more than one PCI-PCI bridge
-//             in a slot.
-//
-// Input:      u8 bus_num - bus number of PCI device
-//             u8 dev_num - device number of PCI device
-//             u8 *slot - Pointer to u8 where slot number will
-//                     be returned
-//
-// Output:     SUCCESS or FAILURE
-//=============================================================================
+/**
+ * get_slot_mapping - determine logical slot mapping for PCI device
+ *
+ * Won't work for more than one PCI-PCI bridge in a slot.
+ *
+ * @bus_num - bus number of PCI device
+ * @dev_num - device number of PCI device
+ * @slot - Pointer to u8 where slot number will        be returned
+ *
+ * Output:     SUCCESS or FAILURE
+ */
 static int
 get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot)
 {
-       struct irq_routing_table *PCIIRQRoutingInfoLength;
        u32 work;
        long len;
        long loop;
 
        u8 tbus, tdevice, tslot, bridgeSlot;
 
-       dbg("%s: %p, %d, %d, %p\n", __FUNCTION__, bus, bus_num, dev_num, slot);
+       dbg("%s: %p, %d, %d, %p\n", __func__, bus, bus_num, dev_num, slot);
 
        bridgeSlot = 0xFF;
 
-       PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table();
-       if (!PCIIRQRoutingInfoLength)
-               return -1;
-
-       len = (PCIIRQRoutingInfoLength->size -
-              sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
-       // Make sure I got at least one entry
-       if (len == 0) {
-               kfree(PCIIRQRoutingInfoLength);
-               return -1;
-       }
-
+       len = cpqhp_routing_table_length();
        for (loop = 0; loop < len; ++loop) {
-               tbus = PCIIRQRoutingInfoLength->slots[loop].bus;
-               tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn >> 3;
-               tslot = PCIIRQRoutingInfoLength->slots[loop].slot;
+               tbus = cpqhp_routing_table->slots[loop].bus;
+               tdevice = cpqhp_routing_table->slots[loop].devfn >> 3;
+               tslot = cpqhp_routing_table->slots[loop].slot;
 
                if ((tbus == bus_num) && (tdevice == dev_num)) {
                        *slot = tslot;
-                       kfree(PCIIRQRoutingInfoLength);
                        return 0;
                } else {
                        /* Did not get a match on the target PCI device. Check
-                        * if the current IRQ table entry is a PCI-to-PCI bridge
-                        * device.  If so, and it's secondary bus matches the
-                        * bus number for the target device, I need to save the
-                        * bridge's slot number.  If I can not find an entry for
-                        * the target device, I will have to assume it's on the
-                        * other side of the bridge, and assign it the bridge's
-                        * slot. */
+                        * if the current IRQ table entry is a PCI-to-PCI
+                        * bridge device.  If so, and it's secondary bus
+                        * matches the bus number for the target device, I need
+                        * to save the bridge's slot number.  If I can not find
+                        * an entry for the target device, I will have to
+                        * assume it's on the other side of the bridge, and
+                        * assign it the bridge's slot.
+                        */
                        bus->number = tbus;
                        pci_bus_read_config_dword(bus, PCI_DEVFN(tdevice, 0),
-                                               PCI_REVISION_ID, &work);
+                                               PCI_CLASS_REVISION, &work);
 
                        if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
                                pci_bus_read_config_dword(bus,
                                                        PCI_DEVFN(tdevice, 0),
                                                        PCI_PRIMARY_BUS, &work);
                                // See if bridge's secondary bus matches target bus.
-                               if (((work >> 8) & 0x000000FF) == (long) bus_num) {
+                               if (((work >> 8) & 0x000000FF) == (long) bus_num)
                                        bridgeSlot = tslot;
-                               }
                        }
                }
 
        }
 
-       // If we got here, we didn't find an entry in the IRQ mapping table 
-       // for the target PCI device.  If we did determine that the target 
-       // device is on the other side of a PCI-to-PCI bridge, return the 
-       // slot number for the bridge.
+       /* If we got here, we didn't find an entry in the IRQ mapping table for
+        * the target PCI device.  If we did determine that the target device
+        * is on the other side of a PCI-to-PCI bridge, return the slot number
+        * for the bridge.
+        */
        if (bridgeSlot != 0xFF) {
                *slot = bridgeSlot;
-               kfree(PCIIRQRoutingInfoLength);
                return 0;
        }
-       kfree(PCIIRQRoutingInfoLength);
-       // Couldn't find an entry in the routing table for this PCI device
+       /* Couldn't find an entry in the routing table for this PCI device */
        return -1;
 }
 
 
 /**
  * cpqhp_set_attention_status - Turns the Amber LED for a slot on or off
- *
+ * @ctrl: struct controller to use
+ * @func: PCI device/function info
+ * @status: LED control flag: 1 = LED on, 0 = LED off
  */
 static int
 cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
@@ -589,38 +405,39 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
        u8 hp_slot;
 
        if (func == NULL)
-               return(1);
+               return 1;
 
        hp_slot = func->device - ctrl->slot_device_offset;
 
-       // Wait for exclusive access to hardware
+       /* Wait for exclusive access to hardware */
        mutex_lock(&ctrl->crit_sect);
 
-       if (status == 1) {
+       if (status == 1)
                amber_LED_on (ctrl, hp_slot);
-       } else if (status == 0) {
+       else if (status == 0)
                amber_LED_off (ctrl, hp_slot);
-       else {
-               // Done with exclusive hardware access
+       else {
+               /* Done with exclusive hardware access */
                mutex_unlock(&ctrl->crit_sect);
-               return(1);
+               return 1;
        }
 
        set_SOGO(ctrl);
 
-       // Wait for SOBS to be unset
+       /* Wait for SOBS to be unset */
        wait_for_ctrl_irq (ctrl);
 
-       // Done with exclusive hardware access
+       /* Done with exclusive hardware access */
        mutex_unlock(&ctrl->crit_sect);
 
-       return(0);
+       return 0;
 }
 
 
 /**
  * set_attention_status - Turns the Amber LED for a slot on or off
- *
+ * @hotplug_slot: slot to change LED on
+ * @status: LED control flag
  */
 static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
 {
@@ -632,7 +449,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
        u8 device;
        u8 function;
 
-       dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
                return -ENODEV;
@@ -659,7 +476,7 @@ static int process_SI(struct hotplug_slot *hotplug_slot)
        u8 device;
        u8 function;
 
-       dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
                return -ENODEV;
@@ -691,7 +508,7 @@ static int process_SS(struct hotplug_slot *hotplug_slot)
        u8 device;
        u8 function;
 
-       dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
                return -ENODEV;
@@ -704,7 +521,7 @@ static int process_SS(struct hotplug_slot *hotplug_slot)
        if (!slot_func)
                return -ENODEV;
 
-       dbg("In %s, slot_func = %p, ctrl = %p\n", __FUNCTION__, slot_func, ctrl);
+       dbg("In %s, slot_func = %p, ctrl = %p\n", __func__, slot_func, ctrl);
        return cpqhp_process_SS(ctrl, slot_func);
 }
 
@@ -714,9 +531,9 @@ static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value)
        struct slot *slot = hotplug_slot->private;
        struct controller *ctrl = slot->ctrl;
 
-       dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
-       return cpqhp_hardware_test(ctrl, value);        
+       return cpqhp_hardware_test(ctrl, value);
 }
 
 
@@ -725,7 +542,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
        struct slot *slot = hotplug_slot->private;
        struct controller *ctrl = slot->ctrl;
 
-       dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        *value = get_slot_enabled(ctrl, slot);
        return 0;
@@ -735,8 +552,8 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
 {
        struct slot *slot = hotplug_slot->private;
        struct controller *ctrl = slot->ctrl;
-       
-       dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        *value = cpq_get_attention_status(ctrl, slot);
        return 0;
@@ -747,7 +564,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
        struct slot *slot = hotplug_slot->private;
        struct controller *ctrl = slot->ctrl;
 
-       dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        *value = cpq_get_latch_status(ctrl, slot);
 
@@ -759,7 +576,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
        struct slot *slot = hotplug_slot->private;
        struct controller *ctrl = slot->ctrl;
 
-       dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        *value = get_presence_status(ctrl, slot);
 
@@ -771,7 +588,7 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
        struct slot *slot = hotplug_slot->private;
        struct controller *ctrl = slot->ctrl;
 
-       dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        *value = ctrl->speed_capability;
 
@@ -783,265 +600,481 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
        struct slot *slot = hotplug_slot->private;
        struct controller *ctrl = slot->ctrl;
 
-       dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+       dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        *value = ctrl->speed;
 
        return 0;
 }
 
-static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       u8 num_of_slots = 0;
-       u8 hp_slot = 0;
-       u8 device;
-       u8 rev;
-       u8 bus_cap;
-       u16 temp_word;
-       u16 vendor_id;
-       u16 subsystem_vid;
-       u16 subsystem_deviceid;
-       u32 rc;
-       struct controller *ctrl;
-       struct pci_func *func;
-       int err;
+static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = {
+       .set_attention_status = set_attention_status,
+       .enable_slot =          process_SI,
+       .disable_slot =         process_SS,
+       .hardware_test =        hardware_test,
+       .get_power_status =     get_power_status,
+       .get_attention_status = get_attention_status,
+       .get_latch_status =     get_latch_status,
+       .get_adapter_status =   get_adapter_status,
+       .get_max_bus_speed =    get_max_bus_speed,
+       .get_cur_bus_speed =    get_cur_bus_speed,
+};
 
-       err = pci_enable_device(pdev);
-       if (err) {
-               printk(KERN_ERR MY_NAME ": cannot enable PCI device %s (%d)\n",
-                       pci_name(pdev), err);
-               return err;
-       }
+#define SLOT_NAME_SIZE 10
 
-       // Need to read VID early b/c it's used to differentiate CPQ and INTC discovery
-       rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
-       if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) {
-               err(msg_HPC_non_compaq_or_intel);
-               rc = -ENODEV;
-               goto err_disable_device;
-       }
-       dbg("Vendor ID: %x\n", vendor_id);
+static int ctrl_slot_setup(struct controller *ctrl,
+                       void __iomem *smbios_start,
+                       void __iomem *smbios_table)
+{
+       struct slot *slot;
+       struct hotplug_slot *hotplug_slot;
+       struct hotplug_slot_info *hotplug_slot_info;
+       u8 number_of_slots;
+       u8 slot_device;
+       u8 slot_number;
+       u8 ctrl_slot;
+       u32 tempdword;
+       char name[SLOT_NAME_SIZE];
+       void __iomem *slot_entry= NULL;
+       int result = -ENOMEM;
 
-       rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-       dbg("revision: %d\n", rev);
-       if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!rev))) {
-               err(msg_HPC_rev_error);
-               rc = -ENODEV;
-               goto err_disable_device;
-       }
+       dbg("%s\n", __func__);
 
-       /* Check for the proper subsytem ID's
-        * Intel uses a different SSID programming model than Compaq.  
-        * For Intel, each SSID bit identifies a PHP capability.
-        * Also Intel HPC's may have RID=0.
-        */
-       if ((rev > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) {
-               // TODO: This code can be made to support non-Compaq or Intel subsystem IDs
-               rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
-               if (rc) {
-                       err("%s : pci_read_config_word failed\n", __FUNCTION__);
-                       goto err_disable_device;
-               }
-               dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
-               if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
-                       err(msg_HPC_non_compaq_or_intel);
-                       rc = -ENODEV;
-                       goto err_disable_device;
-               }
+       tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
 
-               ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL);
-               if (!ctrl) {
-                       err("%s : out of memory\n", __FUNCTION__);
-                       rc = -ENOMEM;
-                       goto err_disable_device;
-               }
+       number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
+       slot_device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
+       slot_number = ctrl->first_slot;
 
-               rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
-               if (rc) {
-                       err("%s : pci_read_config_word failed\n", __FUNCTION__);
-                       goto err_free_ctrl;
+       while (number_of_slots) {
+               slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+               if (!slot)
+                       goto error;
+
+               slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)),
+                                               GFP_KERNEL);
+               if (!slot->hotplug_slot)
+                       goto error_slot;
+               hotplug_slot = slot->hotplug_slot;
+
+               hotplug_slot->info = kzalloc(sizeof(*(hotplug_slot->info)),
+                                                       GFP_KERNEL);
+               if (!hotplug_slot->info)
+                       goto error_hpslot;
+               hotplug_slot_info = hotplug_slot->info;
+
+               slot->ctrl = ctrl;
+               slot->bus = ctrl->bus;
+               slot->device = slot_device;
+               slot->number = slot_number;
+               dbg("slot->number = %u\n", slot->number);
+
+               slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9,
+                                       slot_entry);
+
+               while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) !=
+                               slot->number)) {
+                       slot_entry = get_SMBIOS_entry(smbios_start,
+                                               smbios_table, 9, slot_entry);
                }
 
-               info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid);
-
-               /* Set Vendor ID, so it can be accessed later from other functions */
-               ctrl->vendor_id = vendor_id;
-
-               switch (subsystem_vid) {
-                       case PCI_VENDOR_ID_COMPAQ:
-                               if (rev >= 0x13) { /* CIOBX */
-                                       ctrl->push_flag = 1;
-                                       ctrl->slot_switch_type = 1;
-                                       ctrl->push_button = 1;
-                                       ctrl->pci_config_space = 1;
-                                       ctrl->defeature_PHP = 1;
-                                       ctrl->pcix_support = 1;
-                                       ctrl->pcix_speed_capability = 1;
-                                       pci_read_config_byte(pdev, 0x41, &bus_cap);
-                                       if (bus_cap & 0x80) {
-                                               dbg("bus max supports 133MHz PCI-X\n");
-                                               ctrl->speed_capability = PCI_SPEED_133MHz_PCIX;
-                                               break;
-                                       }
-                                       if (bus_cap & 0x40) {
-                                               dbg("bus max supports 100MHz PCI-X\n");
-                                               ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
-                                               break;
-                                       }
-                                       if (bus_cap & 20) {
-                                               dbg("bus max supports 66MHz PCI-X\n");
-                                               ctrl->speed_capability = PCI_SPEED_66MHz_PCIX;
-                                               break;
-                                       }
-                                       if (bus_cap & 10) {
-                                               dbg("bus max supports 66MHz PCI\n");
-                                               ctrl->speed_capability = PCI_SPEED_66MHz;
-                                               break;
-                                       }
-
-                                       break;
-                               }
-
-                               switch (subsystem_deviceid) {
-                                       case PCI_SUB_HPC_ID:
-                                               /* Original 6500/7000 implementation */
-                                               ctrl->slot_switch_type = 1;
-                                               ctrl->speed_capability = PCI_SPEED_33MHz;
-                                               ctrl->push_button = 0;
-                                               ctrl->pci_config_space = 1;
-                                               ctrl->defeature_PHP = 1;
-                                               ctrl->pcix_support = 0;
-                                               ctrl->pcix_speed_capability = 0;
-                                               break;
-                                       case PCI_SUB_HPC_ID2:
-                                               /* First Pushbutton implementation */
-                                               ctrl->push_flag = 1;
-                                               ctrl->slot_switch_type = 1;
-                                               ctrl->speed_capability = PCI_SPEED_33MHz;
-                                               ctrl->push_button = 1;
-                                               ctrl->pci_config_space = 1;
-                                               ctrl->defeature_PHP = 1;
-                                               ctrl->pcix_support = 0;
-                                               ctrl->pcix_speed_capability = 0;
-                                               break;
-                                       case PCI_SUB_HPC_ID_INTC:
-                                               /* Third party (6500/7000) */
-                                               ctrl->slot_switch_type = 1;
-                                               ctrl->speed_capability = PCI_SPEED_33MHz;
-                                               ctrl->push_button = 0;
-                                               ctrl->pci_config_space = 1;
-                                               ctrl->defeature_PHP = 1;
-                                               ctrl->pcix_support = 0;
-                                               ctrl->pcix_speed_capability = 0;
-                                               break;
-                                       case PCI_SUB_HPC_ID3:
-                                               /* First 66 Mhz implementation */
-                                               ctrl->push_flag = 1;
-                                               ctrl->slot_switch_type = 1;
-                                               ctrl->speed_capability = PCI_SPEED_66MHz;
-                                               ctrl->push_button = 1;
-                                               ctrl->pci_config_space = 1;
-                                               ctrl->defeature_PHP = 1;
-                                               ctrl->pcix_support = 0;
-                                               ctrl->pcix_speed_capability = 0;
-                                               break;
-                                       case PCI_SUB_HPC_ID4:
-                                               /* First PCI-X implementation, 100MHz */
-                                               ctrl->push_flag = 1;
-                                               ctrl->slot_switch_type = 1;
-                                               ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
-                                               ctrl->push_button = 1;
-                                               ctrl->pci_config_space = 1;
-                                               ctrl->defeature_PHP = 1;
-                                               ctrl->pcix_support = 1;
-                                               ctrl->pcix_speed_capability = 0;        
-                                               break;
-                                       default:
-                                               err(msg_HPC_not_supported);
-                                               rc = -ENODEV;
-                                               goto err_free_ctrl;
-                               }
-                               break;
+               slot->p_sm_slot = slot_entry;
 
-                       case PCI_VENDOR_ID_INTEL:
-                               /* Check for speed capability (0=33, 1=66) */
-                               if (subsystem_deviceid & 0x0001) {
-                                       ctrl->speed_capability = PCI_SPEED_66MHz;
-                               } else {
-                                       ctrl->speed_capability = PCI_SPEED_33MHz;
-                               }
-
-                               /* Check for push button */
-                               if (subsystem_deviceid & 0x0002) {
-                                       /* no push button */
-                                       ctrl->push_button = 0;
-                               } else {
-                                       /* push button supported */
-                                       ctrl->push_button = 1;
-                               }
-
-                               /* Check for slot switch type (0=mechanical, 1=not mechanical) */
-                               if (subsystem_deviceid & 0x0004) {
-                                       /* no switch */
-                                       ctrl->slot_switch_type = 0;
-                               } else {
-                                       /* switch */
-                                       ctrl->slot_switch_type = 1;
-                               }
-
-                               /* PHP Status (0=De-feature PHP, 1=Normal operation) */
-                               if (subsystem_deviceid & 0x0008) {
-                                       ctrl->defeature_PHP = 1;        // PHP supported
-                               } else {
-                                       ctrl->defeature_PHP = 0;        // PHP not supported
-                               }
-
-                               /* Alternate Base Address Register Interface (0=not supported, 1=supported) */
-                               if (subsystem_deviceid & 0x0010) {
-                                       ctrl->alternate_base_address = 1;       // supported
-                               } else {
-                                       ctrl->alternate_base_address = 0;       // not supported
-                               }
-
-                               /* PCI Config Space Index (0=not supported, 1=supported) */
-                               if (subsystem_deviceid & 0x0020) {
-                                       ctrl->pci_config_space = 1;             // supported
-                               } else {
-                                       ctrl->pci_config_space = 0;             // not supported
-                               }
-
-                               /* PCI-X support */
-                               if (subsystem_deviceid & 0x0080) {
-                                       /* PCI-X capable */
-                                       ctrl->pcix_support = 1;
-                                       /* Frequency of operation in PCI-X mode */
-                                       if (subsystem_deviceid & 0x0040) {
-                                               /* 133MHz PCI-X if bit 7 is 1 */
-                                               ctrl->pcix_speed_capability = 1;
-                                       } else {
-                                               /* 100MHz PCI-X if bit 7 is 1 and bit 0 is 0, */
-                                               /* 66MHz PCI-X if bit 7 is 1 and bit 0 is 1 */
-                                               ctrl->pcix_speed_capability = 0;
-                                       }
-                               } else {
-                                       /* Conventional PCI */
-                                       ctrl->pcix_support = 0;
-                                       ctrl->pcix_speed_capability = 0;
-                               }
-                               break;
+               init_timer(&slot->task_event);
+               slot->task_event.expires = jiffies + 5 * HZ;
+               slot->task_event.function = cpqhp_pushbutton_thread;
+
+               /*FIXME: these capabilities aren't used but if they are
+                *       they need to be correctly implemented
+                */
+               slot->capabilities |= PCISLOT_REPLACE_SUPPORTED;
+               slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED;
 
-                       default:
-                               err(msg_HPC_not_supported);
-                               rc = -ENODEV;
-                               goto err_free_ctrl;
+               if (is_slot64bit(slot))
+                       slot->capabilities |= PCISLOT_64_BIT_SUPPORTED;
+               if (is_slot66mhz(slot))
+                       slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED;
+               if (ctrl->speed == PCI_SPEED_66MHz)
+                       slot->capabilities |= PCISLOT_66_MHZ_OPERATION;
+
+               ctrl_slot =
+                       slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4);
+
+               /* Check presence */
+               slot->capabilities |=
+                       ((((~tempdword) >> 23) |
+                        ((~tempdword) >> 15)) >> ctrl_slot) & 0x02;
+               /* Check the switch state */
+               slot->capabilities |=
+                       ((~tempdword & 0xFF) >> ctrl_slot) & 0x01;
+               /* Check the slot enable */
+               slot->capabilities |=
+                       ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04;
+
+               /* register this slot with the hotplug pci core */
+               hotplug_slot->release = &release_slot;
+               hotplug_slot->private = slot;
+               snprintf(name, SLOT_NAME_SIZE, "%u", slot->number);
+               hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
+
+               hotplug_slot_info->power_status = get_slot_enabled(ctrl, slot);
+               hotplug_slot_info->attention_status =
+                       cpq_get_attention_status(ctrl, slot);
+               hotplug_slot_info->latch_status =
+                       cpq_get_latch_status(ctrl, slot);
+               hotplug_slot_info->adapter_status =
+                       get_presence_status(ctrl, slot);
+
+               dbg("registering bus %d, dev %d, number %d, "
+                               "ctrl->slot_device_offset %d, slot %d\n",
+                               slot->bus, slot->device,
+                               slot->number, ctrl->slot_device_offset,
+                               slot_number);
+               result = pci_hp_register(hotplug_slot,
+                                        ctrl->pci_dev->bus,
+                                        slot->device,
+                                        name);
+               if (result) {
+                       err("pci_hp_register failed with error %d\n", result);
+                       goto error_info;
                }
 
-       } else {
+               slot->next = ctrl->slot;
+               ctrl->slot = slot;
+
+               number_of_slots--;
+               slot_device++;
+               slot_number++;
+       }
+
+       return 0;
+error_info:
+       kfree(hotplug_slot_info);
+error_hpslot:
+       kfree(hotplug_slot);
+error_slot:
+       kfree(slot);
+error:
+       return result;
+}
+
+static int one_time_init(void)
+{
+       int loop;
+       int retval = 0;
+
+       if (initialized)
+               return 0;
+
+       power_mode = 0;
+
+       retval = init_cpqhp_routing_table();
+       if (retval)
+               goto error;
+
+       if (cpqhp_debug)
+               pci_print_IRQ_route();
+
+       dbg("Initialize + Start the notification mechanism \n");
+
+       retval = cpqhp_event_start_thread();
+       if (retval)
+               goto error;
+
+       dbg("Initialize slot lists\n");
+       for (loop = 0; loop < 256; loop++)
+               cpqhp_slot_list[loop] = NULL;
+
+       /* FIXME: We also need to hook the NMI handler eventually.
+        * this also needs to be worked with Christoph
+        * register_NMI_handler();
+        */
+       /* Map rom address */
+       cpqhp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
+       if (!cpqhp_rom_start) {
+               err ("Could not ioremap memory region for ROM\n");
+               retval = -EIO;
+               goto error;
+       }
+
+       /* Now, map the int15 entry point if we are on compaq specific
+        * hardware
+        */
+       compaq_nvram_init(cpqhp_rom_start);
+
+       /* Map smbios table entry point structure */
+       smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start,
+                                       cpqhp_rom_start + ROM_PHY_LEN);
+       if (!smbios_table) {
+               err ("Could not find the SMBIOS pointer in memory\n");
+               retval = -EIO;
+               goto error_rom_start;
+       }
+
+       smbios_start = ioremap(readl(smbios_table + ST_ADDRESS),
+                                       readw(smbios_table + ST_LENGTH));
+       if (!smbios_start) {
+               err ("Could not ioremap memory region taken from SMBIOS values\n");
+               retval = -EIO;
+               goto error_smbios_start;
+       }
+
+       initialized = 1;
+
+       return retval;
+
+error_smbios_start:
+       iounmap(smbios_start);
+error_rom_start:
+       iounmap(cpqhp_rom_start);
+error:
+       return retval;
+}
+
+static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       u8 num_of_slots = 0;
+       u8 hp_slot = 0;
+       u8 device;
+       u8 bus_cap;
+       u16 temp_word;
+       u16 vendor_id;
+       u16 subsystem_vid;
+       u16 subsystem_deviceid;
+       u32 rc;
+       struct controller *ctrl;
+       struct pci_func *func;
+       int err;
+
+       err = pci_enable_device(pdev);
+       if (err) {
+               printk(KERN_ERR MY_NAME ": cannot enable PCI device %s (%d)\n",
+                       pci_name(pdev), err);
+               return err;
+       }
+
+       /* Need to read VID early b/c it's used to differentiate CPQ and INTC
+        * discovery
+        */
+       rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
+       if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) {
+               err(msg_HPC_non_compaq_or_intel);
+               rc = -ENODEV;
+               goto err_disable_device;
+       }
+       dbg("Vendor ID: %x\n", vendor_id);
+
+       dbg("revision: %d\n", pdev->revision);
+       if ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!pdev->revision)) {
+               err(msg_HPC_rev_error);
+               rc = -ENODEV;
+               goto err_disable_device;
+       }
+
+       /* Check for the proper subsytem ID's
+        * Intel uses a different SSID programming model than Compaq.
+        * For Intel, each SSID bit identifies a PHP capability.
+        * Also Intel HPC's may have RID=0.
+        */
+       if ((pdev->revision <= 2) && (vendor_id != PCI_VENDOR_ID_INTEL)) {
                err(msg_HPC_not_supported);
                return -ENODEV;
        }
 
-       // Tell the user that we found one.
+       /* TODO: This code can be made to support non-Compaq or Intel
+        * subsystem IDs
+        */
+       rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
+       if (rc) {
+               err("%s : pci_read_config_word failed\n", __func__);
+               goto err_disable_device;
+       }
+       dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
+       if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
+               err(msg_HPC_non_compaq_or_intel);
+               rc = -ENODEV;
+               goto err_disable_device;
+       }
+
+       ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL);
+       if (!ctrl) {
+               err("%s : out of memory\n", __func__);
+               rc = -ENOMEM;
+               goto err_disable_device;
+       }
+
+       rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
+       if (rc) {
+               err("%s : pci_read_config_word failed\n", __func__);
+               goto err_free_ctrl;
+       }
+
+       info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid);
+
+       /* Set Vendor ID, so it can be accessed later from other
+        * functions
+        */
+       ctrl->vendor_id = vendor_id;
+
+       switch (subsystem_vid) {
+       case PCI_VENDOR_ID_COMPAQ:
+               if (pdev->revision >= 0x13) { /* CIOBX */
+                       ctrl->push_flag = 1;
+                       ctrl->slot_switch_type = 1;
+                       ctrl->push_button = 1;
+                       ctrl->pci_config_space = 1;
+                       ctrl->defeature_PHP = 1;
+                       ctrl->pcix_support = 1;
+                       ctrl->pcix_speed_capability = 1;
+                       pci_read_config_byte(pdev, 0x41, &bus_cap);
+                       if (bus_cap & 0x80) {
+                               dbg("bus max supports 133MHz PCI-X\n");
+                               ctrl->speed_capability = PCI_SPEED_133MHz_PCIX;
+                               break;
+                       }
+                       if (bus_cap & 0x40) {
+                               dbg("bus max supports 100MHz PCI-X\n");
+                               ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
+                               break;
+                       }
+                       if (bus_cap & 20) {
+                               dbg("bus max supports 66MHz PCI-X\n");
+                               ctrl->speed_capability = PCI_SPEED_66MHz_PCIX;
+                               break;
+                       }
+                       if (bus_cap & 10) {
+                               dbg("bus max supports 66MHz PCI\n");
+                               ctrl->speed_capability = PCI_SPEED_66MHz;
+                               break;
+                       }
+
+                       break;
+               }
+
+               switch (subsystem_deviceid) {
+               case PCI_SUB_HPC_ID:
+                       /* Original 6500/7000 implementation */
+                       ctrl->slot_switch_type = 1;
+                       ctrl->speed_capability = PCI_SPEED_33MHz;
+                       ctrl->push_button = 0;
+                       ctrl->pci_config_space = 1;
+                       ctrl->defeature_PHP = 1;
+                       ctrl->pcix_support = 0;
+                       ctrl->pcix_speed_capability = 0;
+                       break;
+               case PCI_SUB_HPC_ID2:
+                       /* First Pushbutton implementation */
+                       ctrl->push_flag = 1;
+                       ctrl->slot_switch_type = 1;
+                       ctrl->speed_capability = PCI_SPEED_33MHz;
+                       ctrl->push_button = 1;
+                       ctrl->pci_config_space = 1;
+                       ctrl->defeature_PHP = 1;
+                       ctrl->pcix_support = 0;
+                       ctrl->pcix_speed_capability = 0;
+                       break;
+               case PCI_SUB_HPC_ID_INTC:
+                       /* Third party (6500/7000) */
+                       ctrl->slot_switch_type = 1;
+                       ctrl->speed_capability = PCI_SPEED_33MHz;
+                       ctrl->push_button = 0;
+                       ctrl->pci_config_space = 1;
+                       ctrl->defeature_PHP = 1;
+                       ctrl->pcix_support = 0;
+                       ctrl->pcix_speed_capability = 0;
+                       break;
+               case PCI_SUB_HPC_ID3:
+                       /* First 66 Mhz implementation */
+                       ctrl->push_flag = 1;
+                       ctrl->slot_switch_type = 1;
+                       ctrl->speed_capability = PCI_SPEED_66MHz;
+                       ctrl->push_button = 1;
+                       ctrl->pci_config_space = 1;
+                       ctrl->defeature_PHP = 1;
+                       ctrl->pcix_support = 0;
+                       ctrl->pcix_speed_capability = 0;
+                       break;
+               case PCI_SUB_HPC_ID4:
+                       /* First PCI-X implementation, 100MHz */
+                       ctrl->push_flag = 1;
+                       ctrl->slot_switch_type = 1;
+                       ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
+                       ctrl->push_button = 1;
+                       ctrl->pci_config_space = 1;
+                       ctrl->defeature_PHP = 1;
+                       ctrl->pcix_support = 1;
+                       ctrl->pcix_speed_capability = 0;
+                       break;
+               default:
+                       err(msg_HPC_not_supported);
+                       rc = -ENODEV;
+                       goto err_free_ctrl;
+               }
+               break;
+
+       case PCI_VENDOR_ID_INTEL:
+               /* Check for speed capability (0=33, 1=66) */
+               if (subsystem_deviceid & 0x0001)
+                       ctrl->speed_capability = PCI_SPEED_66MHz;
+               else
+                       ctrl->speed_capability = PCI_SPEED_33MHz;
+
+               /* Check for push button */
+               if (subsystem_deviceid & 0x0002)
+                       ctrl->push_button = 0;
+               else
+                       ctrl->push_button = 1;
+
+               /* Check for slot switch type (0=mechanical, 1=not mechanical) */
+               if (subsystem_deviceid & 0x0004)
+                       ctrl->slot_switch_type = 0;
+               else
+                       ctrl->slot_switch_type = 1;
+
+               /* PHP Status (0=De-feature PHP, 1=Normal operation) */
+               if (subsystem_deviceid & 0x0008)
+                       ctrl->defeature_PHP = 1;        /* PHP supported */
+               else
+                       ctrl->defeature_PHP = 0;        /* PHP not supported */
+
+               /* Alternate Base Address Register Interface
+                * (0=not supported, 1=supported)
+                */
+               if (subsystem_deviceid & 0x0010)
+                       ctrl->alternate_base_address = 1;
+               else
+                       ctrl->alternate_base_address = 0;
+
+               /* PCI Config Space Index (0=not supported, 1=supported) */
+               if (subsystem_deviceid & 0x0020)
+                       ctrl->pci_config_space = 1;
+               else
+                       ctrl->pci_config_space = 0;
+
+               /* PCI-X support */
+               if (subsystem_deviceid & 0x0080) {
+                       ctrl->pcix_support = 1;
+                       if (subsystem_deviceid & 0x0040)
+                               /* 133MHz PCI-X if bit 7 is 1 */
+                               ctrl->pcix_speed_capability = 1;
+                       else
+                               /* 100MHz PCI-X if bit 7 is 1 and bit 0 is 0, */
+                               /* 66MHz PCI-X if bit 7 is 1 and bit 0 is 1 */
+                               ctrl->pcix_speed_capability = 0;
+               } else {
+                       /* Conventional PCI */
+                       ctrl->pcix_support = 0;
+                       ctrl->pcix_speed_capability = 0;
+               }
+               break;
+
+       default:
+               err(msg_HPC_not_supported);
+               rc = -ENODEV;
+               goto err_free_ctrl;
+       }
+
+       /* Tell the user that we found one. */
        info("Initializing the PCI hot plug controller residing on PCI bus %d\n",
                                        pdev->bus->number);
 
@@ -1074,7 +1107,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        memcpy(ctrl->pci_bus, pdev->bus, sizeof(*ctrl->pci_bus));
 
        ctrl->bus = pdev->bus->number;
-       ctrl->rev = rev;
+       ctrl->rev = pdev->revision;
        dbg("bus device function rev: %d %d %d %d\n", ctrl->bus,
                PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev);
 
@@ -1086,7 +1119,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc) {
                goto err_free_bus;
        }
-       
+
        dbg("pdev = %p\n", pdev);
        dbg("pci resource start %llx\n", (unsigned long long)pci_resource_start(pdev, 0));
        dbg("pci resource len %llx\n", (unsigned long long)pci_resource_len(pdev, 0));
@@ -1108,7 +1141,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_free_mem_region;
        }
 
-       // Check for 66Mhz operation
+       /* Check for 66Mhz operation */
        ctrl->speed = get_controller_speed(ctrl);
 
 
@@ -1119,7 +1152,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         *
         ********************************************************/
 
-       // find the physical slot number of the first hot plug slot
+       /* find the physical slot number of the first hot plug slot */
 
        /* Get slot won't work for devices behind bridges, but
         * in this case it will always be called for the "base"
@@ -1136,18 +1169,18 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_iounmap;
        }
 
-       // Store PCI Config Space for all devices on this bus
+       /* Store PCI Config Space for all devices on this bus */
        rc = cpqhp_save_config(ctrl, ctrl->bus, readb(ctrl->hpc_reg + SLOT_MASK));
        if (rc) {
                err("%s: unable to save PCI configuration data, error %d\n",
-                               __FUNCTION__, rc);
+                               __func__, rc);
                goto err_iounmap;
        }
 
        /*
         * Get IO, memory, and IRQ resources for new devices
         */
-       // The next line is required for cpqhp_find_available_resources
+       /* The next line is required for cpqhp_find_available_resources */
        ctrl->interrupt = pdev->irq;
        if (ctrl->interrupt < 0x10) {
                cpqhp_legacy_mode = 1;
@@ -1178,10 +1211,10 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc) {
                err(msg_initialization_err, 6);
                err("%s: unable to save PCI configuration data, error %d\n",
-                       __FUNCTION__, rc);
+                       __func__, rc);
                goto err_iounmap;
        }
-       
+
        /* Mask all general input interrupts */
        writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_MASK);
 
@@ -1195,12 +1228,14 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_iounmap;
        }
 
-       /* Enable Shift Out interrupt and clear it, also enable SERR on power fault */
+       /* Enable Shift Out interrupt and clear it, also enable SERR on power
+        * fault
+        */
        temp_word = readw(ctrl->hpc_reg + MISC);
        temp_word |= 0x4006;
        writew(temp_word, ctrl->hpc_reg + MISC);
 
-       // Changed 05/05/97 to clear all interrupts at start
+       /* Changed 05/05/97 to clear all interrupts at start */
        writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_INPUT_CLEAR);
 
        ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
@@ -1215,13 +1250,14 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                cpqhp_ctrl_list = ctrl;
        }
 
-       // turn off empty slots here unless command line option "ON" set
-       // Wait for exclusive access to hardware
+       /* turn off empty slots here unless command line option "ON" set
+        * Wait for exclusive access to hardware
+        */
        mutex_lock(&ctrl->crit_sect);
 
        num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
 
-       // find first device number for the ctrl
+       /* find first device number for the ctrl */
        device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
 
        while (num_of_slots) {
@@ -1233,23 +1269,21 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                hp_slot = func->device - ctrl->slot_device_offset;
                dbg("hp_slot: %d\n", hp_slot);
 
-               // We have to save the presence info for these slots
+               /* We have to save the presence info for these slots */
                temp_word = ctrl->ctrl_int_comp >> 16;
                func->presence_save = (temp_word >> hp_slot) & 0x01;
                func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02;
 
-               if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) {
+               if (ctrl->ctrl_int_comp & (0x1L << hp_slot))
                        func->switch_save = 0;
-               } else {
+               else
                        func->switch_save = 0x10;
-               }
 
-               if (!power_mode) {
+               if (!power_mode)
                        if (!func->is_a_board) {
                                green_LED_off(ctrl, hp_slot);
                                slot_disable(ctrl, hp_slot);
                        }
-               }
 
                device++;
                num_of_slots--;
@@ -1257,7 +1291,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        if (!power_mode) {
                set_SOGO(ctrl);
-               // Wait for SOBS to be unset
+               /* Wait for SOBS to be unset */
                wait_for_ctrl_irq(ctrl);
        }
 
@@ -1268,7 +1302,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_free_irq;
        }
 
-       // Done with exclusive hardware access
+       /* Done with exclusive hardware access */
        mutex_unlock(&ctrl->crit_sect);
 
        cpqhp_create_debugfs_files(ctrl);
@@ -1290,77 +1324,6 @@ err_disable_device:
        return rc;
 }
 
-
-static int one_time_init(void)
-{
-       int loop;
-       int retval = 0;
-
-       if (initialized)
-               return 0;
-
-       power_mode = 0;
-
-       retval = pci_print_IRQ_route();
-       if (retval)
-               goto error;
-
-       dbg("Initialize + Start the notification mechanism \n");
-
-       retval = cpqhp_event_start_thread();
-       if (retval)
-               goto error;
-
-       dbg("Initialize slot lists\n");
-       for (loop = 0; loop < 256; loop++) {
-               cpqhp_slot_list[loop] = NULL;
-       }
-
-       // FIXME: We also need to hook the NMI handler eventually.
-       // this also needs to be worked with Christoph
-       // register_NMI_handler();
-
-       // Map rom address
-       cpqhp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
-       if (!cpqhp_rom_start) {
-               err ("Could not ioremap memory region for ROM\n");
-               retval = -EIO;
-               goto error;
-       }
-       
-       /* Now, map the int15 entry point if we are on compaq specific hardware */
-       compaq_nvram_init(cpqhp_rom_start);
-       
-       /* Map smbios table entry point structure */
-       smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start,
-                                       cpqhp_rom_start + ROM_PHY_LEN);
-       if (!smbios_table) {
-               err ("Could not find the SMBIOS pointer in memory\n");
-               retval = -EIO;
-               goto error_rom_start;
-       }
-
-       smbios_start = ioremap(readl(smbios_table + ST_ADDRESS),
-                                       readw(smbios_table + ST_LENGTH));
-       if (!smbios_start) {
-               err ("Could not ioremap memory region taken from SMBIOS values\n");
-               retval = -EIO;
-               goto error_smbios_start;
-       }
-
-       initialized = 1;
-
-       return retval;
-
-error_smbios_start:
-       iounmap(smbios_start);
-error_rom_start:
-       iounmap(cpqhp_rom_start);
-error:
-       return retval;
-}
-
-
 static void __exit unload_cpqphpd(void)
 {
        struct pci_func *next;
@@ -1380,10 +1343,10 @@ static void __exit unload_cpqphpd(void)
                if (ctrl->hpc_reg) {
                        u16 misc;
                        rc = read_slot_enable (ctrl);
-                       
+
                        writeb(0, ctrl->hpc_reg + SLOT_SERR);
                        writel(0xFFFFFFC0L | ~rc, ctrl->hpc_reg + INT_MASK);
-                       
+
                        misc = readw(ctrl->hpc_reg + MISC);
                        misc &= 0xFFFD;
                        writew(misc, ctrl->hpc_reg + MISC);
@@ -1463,38 +1426,34 @@ static void __exit unload_cpqphpd(void)
                }
        }
 
-       // Stop the notification mechanism
+       /* Stop the notification mechanism */
        if (initialized)
                cpqhp_event_stop_thread();
 
-       //unmap the rom address
+       /* unmap the rom address */
        if (cpqhp_rom_start)
                iounmap(cpqhp_rom_start);
        if (smbios_start)
                iounmap(smbios_start);
 }
 
-
-
 static struct pci_device_id hpcd_pci_tbl[] = {
        {
        /* handle any PCI Hotplug controller */
        .class =        ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00),
        .class_mask =   ~0,
-       
+
        /* no matter who makes it */
        .vendor =       PCI_ANY_ID,
        .device =       PCI_ANY_ID,
        .subvendor =    PCI_ANY_ID,
        .subdevice =    PCI_ANY_ID,
-       
+
        }, { /* end: all zeroes */ }
 };
 
 MODULE_DEVICE_TABLE(pci, hpcd_pci_tbl);
 
-
-
 static struct pci_driver cpqhpc_driver = {
        .name =         "compaq_pci_hotplug",
        .id_table =     hpcd_pci_tbl,
@@ -1502,8 +1461,6 @@ static struct pci_driver cpqhpc_driver = {
        /* remove:      cpqhpc_remove_one, */
 };
 
-
-
 static int __init cpqhpc_init(void)
 {
        int result;
@@ -1517,7 +1474,6 @@ static int __init cpqhpc_init(void)
        return result;
 }
 
-
 static void __exit cpqhpc_cleanup(void)
 {
        dbg("unload_cpqphpd()\n");
@@ -1528,8 +1484,5 @@ static void __exit cpqhpc_cleanup(void)
        cpqhp_shutdown_debugfs();
 }
 
-
 module_init(cpqhpc_init);
 module_exit(cpqhpc_cleanup);
-
-