linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Patch] 3/4 PCI Hot-plug driver patch for 2.5.74 kernel
@ 2003-07-12 16:13 Dely Sy
  0 siblings, 0 replies; only message in thread
From: Dely Sy @ 2003-07-12 16:13 UTC (permalink / raw)
  To: linux-kernel

Part 3 of 4 PCI Hot-plug driver patch for 2.5.74 kernel

diff -Nru a/drivers/pci/hotplug/cpqphp_hpc.c b/drivers/pci/hotplug/cpqphp_hpc.c
--- a/drivers/pci/hotplug/cpqphp_hpc.c	1969-12-31 16:00:00.000000000 -0800
+++ b/drivers/pci/hotplug/cpqphp_hpc.c	2003-07-07 09:32:22.000000000 -0700
@@ -0,0 +1,1203 @@
+/*
+ * Compaq PCI Hot Plug Driver
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <dely.l.sy@intel.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/pci.h>
+#include <linux/delay.h>  /* for delays */
+#include <asm/system.h>
+#include "cpqphp.h"
+
+#ifdef DEBUG
+#define DBG_K_TRACE_ENTRY      ((unsigned int)0x00000001)	/* On function entry */
+#define DBG_K_TRACE_EXIT       ((unsigned int)0x00000002)	/* On function exit */
+#define DBG_K_INFO             ((unsigned int)0x00000004)	/* Info messages */
+#define DBG_K_ERROR            ((unsigned int)0x00000008)	/* Error messages */
+#define DBG_K_TRACE            (DBG_K_TRACE_ENTRY|DBG_K_TRACE_EXIT)
+#define DBG_K_STANDARD         (DBG_K_INFO|DBG_K_ERROR|DBG_K_TRACE)
+/* Redefine this flagword to set debug level */
+#define DEBUG_LEVEL            DBG_K_STANDARD
+
+#define DEFINE_DBG_BUFFER     char __dbg_str_buf[256];
+
+#define DBG_PRINT( dbg_flags, args... )                  \
+	do {                                             \
+	  if ( DEBUG_LEVEL & ( dbg_flags ) )             \
+	  {                                              \
+	    int len;                                     \
+	    len = sprintf( __dbg_str_buf, "%s:%d: %s: ", \
+		  __FILE__, __LINE__, __FUNCTION__ );    \
+	    sprintf( __dbg_str_buf + len, args );        \
+	    printk( KERN_NOTICE "%s\n", __dbg_str_buf ); \
+	  }                                              \
+	} while (0)
+
+#define DBG_ENTER_ROUTINE	DBG_PRINT (DBG_K_TRACE_ENTRY, "%s", "[Entry]");
+#define DBG_LEAVE_ROUTINE	DBG_PRINT (DBG_K_TRACE_EXIT, "%s", "[Exit]");
+#else
+#define DEFINE_DBG_BUFFER
+#define DBG_ENTER_ROUTINE
+#define DBG_LEAVE_ROUTINE
+#endif				/* DEBUG */
+
+struct ctrl_reg {		/* offset */
+	u8 slot_RST;		/* 0x00 */	
+	u8 slot_enable;		/* 0x01 */
+	u16 misc;		/* 0x02 */
+	u32 led_control;	/* 0x04 */
+	u32 int_input_clear;	/* 0x08 */
+	u32 int_mask;		/* 0x0a */
+	u8 reserved0;		/* 0x10 */
+	u8 reserved1;		/* 0x11 */
+	u8 reserved2;		/* 0x12 */
+	u8 gen_output_AB;	/* 0x13 */
+	u32 non_int_input;	/* 0x14 */
+	u32 reserved3;		/* 0x18 */
+	u32 reserved4;		/* 0x1a */
+	u32 reserved5;		/* 0x20 */
+	u8 reserved6;		/* 0x24 */
+	u8 reserved7;		/* 0x25 */
+	u16 reserved8;		/* 0x26 */
+	u8 slot_mask;		/* 0x28 */
+	u8 reserved9;		/* 0x29 */
+	u8 reserved10;		/* 0x2a */
+	u8 reserved11;		/* 0x2b */
+	u8 slot_SERR;		/* 0x2c */
+	u8 slot_power;		/* 0x2d */
+	u8 reserved12;		/* 0x2e */
+	u8 reserved13;		/* 0x2f */
+	u8 next_curr_freq;	/* 0x30 */
+	u8 reset_freq_mode;	/* 0x31 */
+
+} __attribute__ ((packed));
+
+/* offsets to the controller registers based on the above structure layout */
+enum ctrl_offsets {
+	SLOT_RST = 		offsetof(struct ctrl_reg, slot_RST),
+	SLOT_ENABLE =		offsetof(struct ctrl_reg, slot_enable),
+	MISC =			offsetof(struct ctrl_reg, misc),
+	LED_CONTROL =		offsetof(struct ctrl_reg, led_control),
+	INT_INPUT_CLEAR =	offsetof(struct ctrl_reg, int_input_clear),
+	INT_MASK = 		offsetof(struct ctrl_reg, int_mask),
+	CTRL_RESERVED0 = 	offsetof(struct ctrl_reg, reserved0),
+	CTRL_RESERVED1 =	offsetof(struct ctrl_reg, reserved1),
+	CTRL_RESERVED2 =	offsetof(struct ctrl_reg, reserved1),
+	GEN_OUTPUT_AB = 	offsetof(struct ctrl_reg, gen_output_AB),
+	NON_INT_INPUT = 	offsetof(struct ctrl_reg, non_int_input),
+	CTRL_RESERVED3 =	offsetof(struct ctrl_reg, reserved3),
+	CTRL_RESERVED4 =	offsetof(struct ctrl_reg, reserved4),
+	CTRL_RESERVED5 =	offsetof(struct ctrl_reg, reserved5),
+	CTRL_RESERVED6 =	offsetof(struct ctrl_reg, reserved6),
+	CTRL_RESERVED7 =	offsetof(struct ctrl_reg, reserved7),
+	CTRL_RESERVED8 =	offsetof(struct ctrl_reg, reserved8),
+	SLOT_MASK = 		offsetof(struct ctrl_reg, slot_mask),
+	CTRL_RESERVED9 = 	offsetof(struct ctrl_reg, reserved9),
+	CTRL_RESERVED10 =	offsetof(struct ctrl_reg, reserved10),
+	CTRL_RESERVED11 =	offsetof(struct ctrl_reg, reserved11),
+	SLOT_SERR =		offsetof(struct ctrl_reg, slot_SERR),
+	SLOT_POWER =		offsetof(struct ctrl_reg, slot_power),
+	CTRL_RESERVED12 =	offsetof(struct ctrl_reg, reserved12),
+	CTRL_RESERVED13 =	offsetof(struct ctrl_reg, reserved13),
+	NEXT_CURR_FREQ =	offsetof(struct ctrl_reg, next_curr_freq),
+	RESET_FREQ_MODE =	offsetof(struct ctrl_reg, reset_freq_mode),
+};
+
+
+struct sema_struct {
+	struct semaphore crit_sect;
+	int owner_id;
+	int count;
+};
+
+struct php_ctlr_state_s {
+	struct php_ctlr_state_s *pnext;
+	struct pci_dev *pci_dev;
+	unsigned int irq;
+	struct sema_struct hwlock;
+	unsigned long flags;	/* spinlock's */
+	u32 ctrl_int_comp;		/* interrupt comparator */
+	u32 first_device_num;
+	u32 num_slots;
+	u16 ctlrcap;
+	php_intr_callback_t switch_change_callback;
+	php_intr_callback_t presence_change_callback;
+	php_intr_callback_t power_fault_callback;
+	void *callback_instance_id;
+	void *creg;				/* Ptr to controller register space */
+};
+
+
+spinlock_t hpc_event_lock;
+
+DEFINE_DBG_BUFFER		/* Debug string buffer for entire HPC defined here */
+static struct php_ctlr_state_s *php_ctlr_list_head = 0;	/* HPC state linked list */
+static int ctlr_seq_num = 0;	/* Controller sequenc # */
+
+static irqreturn_t hpc_isr(int IRQ, void *dev_id, struct pt_regs *regs);
+
+static wait_queue_head_t delay_wait_q_head;
+
+/* delay in jiffies to wait */
+static void longdelay(int delay)
+{
+	init_waitqueue_head(&delay_wait_q_head);
+
+	interruptible_sleep_on_timeout(&delay_wait_q_head, delay);
+}
+
+static void cpqhpc_set_SOGO (struct slot *slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u16 misc;
+
+	misc = readw(php_ctlr->creg + MISC);
+	misc = (misc | 0x0001) & 0xFFFB;
+	writew(misc, php_ctlr->creg + MISC);
+}
+
+static int cpqhpc_wait_for_SOBS (struct slot *slot)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	int retval = 0;
+
+	DBG_ENTER_ROUTINE 
+
+	add_wait_queue(&slot->ctrl->queue, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(2*HZ);
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&slot->ctrl->queue, &wait);
+	if (signal_pending(current))
+		retval =  -EINTR;
+
+	DBG_LEAVE_ROUTINE 
+	return retval;
+}
+
+static void hpc_update_hpc(struct slot *slot)
+{
+	cpqhpc_set_SOGO(slot);
+	cpqhpc_wait_for_SOBS(slot);
+}
+
+static int hpc_get_attention_status(struct slot *slot, u8 *status)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u32 led_control;
+
+	DBG_ENTER_ROUTINE 
+
+	led_control = readl(php_ctlr->creg + LED_CONTROL);
+	led_control &= (0x01010000L << slot->hp_slot);
+	*status = led_control ? 1 : 0;
+
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static int hpc_get_power_status(struct slot * slot, u8 *status)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u8 slot_enable;
+
+	DBG_ENTER_ROUTINE 
+
+	slot_enable = readb(php_ctlr->creg + SLOT_ENABLE);
+	slot_enable &= (0x01L << slot->hp_slot);
+	*status = slot_enable ? 1 : 0;
+
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static int hpc_get_latch_status(struct slot *slot, u8 *status)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u32 latch_status;
+
+	DBG_ENTER_ROUTINE 
+
+	latch_status = (readl(php_ctlr->creg + INT_INPUT_CLEAR) & (0x01L << slot->hp_slot));
+	*status = (latch_status == 0) ? 1 : 0;
+
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static int hpc_get_adapter_status(struct slot *slot, u8 *status)
+{
+	u8 presence_save = 0;
+	u32 tempdword;
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+
+	DBG_ENTER_ROUTINE 
+
+	tempdword = readl(php_ctlr->creg + INT_INPUT_CLEAR);
+	presence_save = (u8) ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> slot->hp_slot) & 0x02;
+
+	*status = (presence_save != 0) ? 1 : 0;
+
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static int hpc_query_power_fault(struct slot * slot)
+{
+	u32 status;
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u32 tempdword;
+
+	DBG_ENTER_ROUTINE 
+
+	tempdword = readl(php_ctlr->creg + INT_INPUT_CLEAR);
+	status = (tempdword & (0x00000100 << slot->hp_slot));
+
+	DBG_LEAVE_ROUTINE
+	/* Note: Logic 0 => fault */
+	return status ? 0 : 1;
+}
+
+/*
+ * change to call set_led_state()
+ */
+
+static void hpc_set_attention_status(struct slot *slot, u8 status)
+{
+	struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u32 led_control;
+	
+	switch (status) {
+	case 0:
+		led_control = readl(php_ctlr->creg + LED_CONTROL);
+		led_control &= ~(0x01010000L << slot->hp_slot);
+		writel(led_control, php_ctlr->creg + LED_CONTROL);
+		break;
+	case 1:
+		led_control = readl(php_ctlr->creg + LED_CONTROL);
+		led_control |= (0x01010000L << slot->hp_slot);
+		writel(led_control, php_ctlr->creg + LED_CONTROL);
+		break;
+	}
+}
+
+static void hpc_green_led_on(struct slot * slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u32 led_control;
+	
+	led_control = readl(php_ctlr->creg + LED_CONTROL);
+	led_control |= 0x0101L << slot->hp_slot;
+	writel(led_control, php_ctlr->creg + LED_CONTROL);
+
+}
+
+static void hpc_green_led_off(struct slot * slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u32 led_control;
+	
+	led_control = readl(php_ctlr->creg + LED_CONTROL);
+	led_control &= ~(0x0101L << slot->hp_slot);
+	writel(led_control, php_ctlr->creg + LED_CONTROL);
+
+}
+
+static void hpc_green_led_blink(struct slot * slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u32 led_control;
+	
+	led_control = readl(php_ctlr->creg + LED_CONTROL);
+	led_control &= ~(0x0101L << slot->hp_slot);
+	led_control |= (0x0001L << slot->hp_slot);
+	writel(led_control, php_ctlr->creg + LED_CONTROL);
+
+}
+
+/*
+ * 0: all 4 variables set
+ * 1: no physical_slot_num
+ */
+int phphpc_get_ctlr_slot_config(struct controller *ctrl,
+	int *num_ctlr_slots,	/* number of slots in this HPC			*/
+	int *first_device_num,	/* PCI dev num of the first slot in this HPC	*/
+	int *physical_slot_num,	/* phy slot num of the first slot in this HPC	*/
+	int *updown,		/* physical_slot_num increament: 1 or -1	*/
+	int *flags)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+
+	DBG_ENTER_ROUTINE 
+
+	* first_device_num = php_ctlr->first_device_num;
+	*num_ctlr_slots = php_ctlr->num_slots;
+
+	/* this HPC does not conform to SHPC and provides no physical_slot_num. */
+	*physical_slot_num = -1;
+
+	*updown = 1;		/* could be -1 in SHPC */
+	*flags = 1;
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static void hpc_release_ctlr(struct controller *ctrl)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *p, *p_prev;
+
+	DBG_ENTER_ROUTINE 
+
+	if (php_ctlr->irq) {
+		free_irq(php_ctlr->irq, ctrl);
+		php_ctlr->irq = 0;
+	}
+
+	if (php_ctlr->pci_dev) {
+		iounmap((void *) pci_resource_start(php_ctlr->pci_dev, 0));
+		release_mem_region(pci_resource_start(php_ctlr->pci_dev, 0), pci_resource_len(php_ctlr->pci_dev, 0));
+		php_ctlr->pci_dev = 0;
+	}
+
+	p = php_ctlr_list_head;
+	p_prev = NULL;
+	while (p) {
+		if (p == php_ctlr) {
+			if (p_prev)
+				p_prev->pnext = p->pnext;
+			else
+				php_ctlr_list_head = p->pnext;
+			break;
+		} else {
+			p_prev = p;
+			p = p->pnext;
+		}
+	}
+
+	kfree(php_ctlr);
+
+	DBG_LEAVE_ROUTINE
+}
+
+static int hpc_power_on_slot(struct slot * slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u8 slot_enable;
+
+	DBG_ENTER_ROUTINE 
+
+	slot_enable = readb(php_ctlr->creg + SLOT_ENABLE);
+	slot_enable |= (0x01 << slot->hp_slot);
+	writeb(slot_enable, php_ctlr->creg + SLOT_ENABLE);
+
+	DBG_LEAVE_ROUTINE
+	return 0;
+}
+
+static int hpc_power_off_slot(struct slot * slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u8 slot_enable;
+
+	DBG_ENTER_ROUTINE 
+
+	slot_enable = readb(php_ctlr->creg + SLOT_ENABLE);
+	slot_enable &= ~(0x01 << slot->hp_slot);
+	writeb(slot_enable, php_ctlr->creg + SLOT_ENABLE);
+
+	DBG_LEAVE_ROUTINE
+
+	return 0;
+}
+
+static void hpc_enable_msl_interrupt(struct slot *slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u32 rc;
+	u16 misc;
+
+	DBG_ENTER_ROUTINE 
+
+	if (php_ctlr->creg) {
+		rc = readb(php_ctlr->creg + SLOT_ENABLE);
+		
+		writeb(rc, php_ctlr->creg + SLOT_SERR);
+		writel(0xFFFFFFC0L | ~rc, php_ctlr->creg + INT_MASK);
+			
+		misc = readw(php_ctlr->creg + MISC);
+		misc &= 0xFFFD;
+		writew(misc, php_ctlr->creg + MISC);
+	}
+
+	DBG_LEAVE_ROUTINE
+}
+
+static u32 hpc_get_slot_capability(struct slot *slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u32 slot_state = 0, temp;
+	u8 slot_enable;
+
+	DBG_ENTER_ROUTINE 
+
+	temp = readl(php_ctlr->creg + INT_INPUT_CLEAR);
+
+	/* Check presence */
+	slot_state |= ((((~temp) >> 23) | ((~temp) >> 15)) >> slot->hp_slot) & 0x02;
+	/* Check the switch state */
+	slot_state |= ((~temp & 0xFF) >> slot->hp_slot) & 0x01;
+	/* Check the slot enable */
+	slot_enable = readb(php_ctlr->creg + SLOT_ENABLE);
+	slot_state |= ((slot_enable << 2) >> slot->hp_slot) & 0x04;
+
+	return slot_state;
+
+	DBG_LEAVE_ROUTINE
+}
+
+static irqreturn_t hpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
+{
+	struct controller *ctrl = (struct controller *)dev_id;
+	struct php_ctlr_state_s *php_ctlr;
+	u8 schedule_flag = 0;
+	u32 Diff;
+	u32 temp_dword;
+	u16 misc;
+	u8 reset;
+
+	if (!ctrl || !(php_ctlr = ctrl->hpc_ctlr_handle) || !php_ctlr->creg)
+		return IRQ_NONE;
+
+	/* Check to see if it was our interrupt */
+	misc = readw(php_ctlr->creg + MISC);
+	if (!(misc & 0x000C))
+		return IRQ_NONE;
+
+	if (misc & 0x0004) {
+		/* Serial Output interrupt Pending */
+		misc |= 0x0004;	/* Clear the interrupt */
+		writew(misc, php_ctlr->creg + MISC);
+		misc = readw(php_ctlr->creg + MISC);	/* Read to clear posted writes */
+		wake_up_interruptible(&ctrl->queue);
+	}
+
+	if (misc & 0x0008) {
+		/* General-interrupt-input interrupt Pending */
+		Diff = readl(php_ctlr->creg + INT_INPUT_CLEAR) ^ php_ctlr->ctrl_int_comp;
+
+		php_ctlr->ctrl_int_comp = readl(php_ctlr->creg + INT_INPUT_CLEAR);
+
+		writel(Diff, php_ctlr->creg + INT_INPUT_CLEAR);	/* Clear the interrupt */
+
+		/* Read it back to clear any posted writes */
+		temp_dword = readl(php_ctlr->creg + INT_INPUT_CLEAR);
+
+		if (!Diff)
+			writel(0xFFFFFFFF, php_ctlr->creg + INT_INPUT_CLEAR);	/* Clear all interrupts */
+
+		if (php_ctlr->switch_change_callback)
+			schedule_flag += php_ctlr->switch_change_callback(
+				(Diff & 0xFFL), php_ctlr->callback_instance_id);
+		if (php_ctlr->presence_change_callback)
+			schedule_flag += php_ctlr->presence_change_callback(
+				((Diff & 0xFFFF0000L) >> 16), php_ctlr->callback_instance_id);
+		if (php_ctlr->power_fault_callback)
+			schedule_flag += php_ctlr->power_fault_callback(
+				((Diff & 0xFF00L) >> 8), php_ctlr->callback_instance_id);
+	}
+
+	/* Setting bus speed is applicable only to Compaq HPC with rev >= 0x13 
+	 * or with subsystem_device == PCI_SUB_HPC_ID4 
+	 */
+	if ((ctrl->pci_dev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) && 
+		((ctrl->rev >= 0x13) || (ctrl->pci_dev->subsystem_device == PCI_SUB_HPC_ID4))) {
+		reset = readb(php_ctlr->creg + RESET_FREQ_MODE);
+		if (reset & 0x40) {
+			/* Bus reset has completed */
+			reset &= 0xCF;
+			writeb(reset, php_ctlr->creg + RESET_FREQ_MODE);
+			reset = readb(php_ctlr->creg + RESET_FREQ_MODE);
+			wake_up_interruptible(&ctrl->queue);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+int phphpc_get_ctrl_cap(struct controller *ctrl, u16 * pctlrcap, u8 * prev)
+{
+	u16 vendor_id;
+	u16 subsystem_vid;
+	u16 subsystem_did;
+	u32 rc;
+	u8 bus_cap;
+	struct pci_dev *pdev;
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!ctrl->hpc_ctlr_handle) {
+		err("Process %d: Invalid HPC controller handle!\n", current->pid);
+		return -1;
+	}
+
+	if (!pctlrcap) {
+		err("Process %d: Invalid HPC ctrlcap pointer passed in!\n", current->pid);
+		return -1;
+	}
+
+	if (!prev) {
+		err("Process %d: Invalid HPC rev pointer passed in!\n", current->pid);
+		return -1;
+	}
+
+	dbg("Pass in ctlrcap = %x\n", *pctlrcap);
+
+	if (!php_ctlr->pci_dev) {
+		err("Process %d: Invalid HPC controller pci_dev!\n", current->pid);
+		return -1;
+	}
+
+	pdev = php_ctlr->pci_dev;
+
+	/* Need to read VID early b/c it's used to differentiate CPQ and INTC discovery */
+	vendor_id = pdev->vendor;
+	if ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL)) {
+		err ("%s: HPC controller(vendor=%x) not supported by this driver!\n", __FUNCTION__, vendor_id);
+		return -1;
+	}
+
+	rc = pci_read_config_byte(pdev, PCI_REVISION_ID, prev);
+	dbg("Vendor ID: %x revision: %x\n", vendor_id, *prev);
+	if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!(*prev)))) {
+		err("%s: Unsupported revision of HPC controller found!\n", __FUNCTION__);
+		return -1;
+	}
+
+	/*
+	 *  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 ((*prev > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) {
+		subsystem_vid = pdev->subsystem_vendor;
+		subsystem_did = pdev->subsystem_device;
+		dbg("Sub-Vendor ID: %x, Sub-Device ID: %x\n", subsystem_vid, subsystem_did);
+		if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
+			err("%s: HPC controller not supported by this driver!\n", __FUNCTION__);
+			return -1;
+		}
+
+		/* Set Default values of "0" for everything */
+		*pctlrcap = 0;
+		
+		/* 
+		 * Interpretation of bit pattern in *pctlrcap
+		 * Based on Intel PHPC SSVID/SID Programming Model
+		 * Bit 0 Speed_capability:       0 = 33MHz, 1 = 66MHz
+		 * Bit 1 Push_button :           0 = pushbutton present, 1 = no pushbutton
+		 * Bit 2 Slot_switch_type:       0 = switch present, 1 = no switch
+		 * Bit 3 DeFeature PHP:          0 = PHP not supported, 1 = PHP supported
+		 * Bit 4 Alternate_base_address: 0 = not supported, 1 = supported
+		 * Bit 5 PCI_config_space: Index/data access to working registers
+		 *                               0 = not supported, 1 = supported
+		 * Bit 6 PCIX_speed: 0 = 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
+		 *                   1 = 133MHz PCI-X if Bit 7 is 1
+		 * Bit 7 PCIX_support:           0 = conventional PCI, 1 = PCI-X
+		 * Bit 8-15  Reserved
+		 */
+		if (subsystem_vid == PCI_VENDOR_ID_COMPAQ) {
+			switch ( *prev >= 0x13) { 
+			case 0: 
+				if (subsystem_did == PCI_SUB_HPC_ID) {
+					*pctlrcap = 0x2A;	/* sw, 33, no pb, no pcix	*/
+					break;
+				} else if (subsystem_did == PCI_SUB_HPC_ID2) {
+					*pctlrcap = 0x28;	/* sw, 33, pb, no pcix	*/
+					break;
+				} else if (subsystem_did == PCI_SUB_HPC_ID_INTC) {
+					*pctlrcap = 0x2A;	/* sw, 33, no pb, no pcix	*/
+					break;
+				} else if (subsystem_did == PCI_SUB_HPC_ID3) {
+					*pctlrcap = 0x29;	/* sw, 66, pb, no pcix	*/
+					break;
+				} else if (subsystem_did == PCI_SUB_HPC_ID4) {
+					*pctlrcap = 0xA8;	/* sw, 100, pb, pcix	*/
+					break;
+				} else {
+					err("%s: unsupported Sub-Device ID: %x\n", __FUNCTION__, subsystem_did);
+					php_ctlr->ctlrcap = 0;
+					return -1;
+				}
+			case 1:	/* True for CIOBX */
+				pci_read_config_byte(pdev, 0x41, &bus_cap);
+				if (bus_cap & 0x80) {
+					*pctlrcap = 0xE8;	/* sw, 133, pb, pcix	*/
+					break;
+				} else if (bus_cap & 0x40) {
+					*pctlrcap = 0xA8;	/* sw, 100, pb, pcix	*/
+					break;
+				} else if (bus_cap & 0x20) {
+					*pctlrcap = 0xA9;	/* sw, 66, pb, pcix	*/
+					break;
+				} else if (bus_cap & 0x10) {
+					*pctlrcap = 0x29;	/* sw, 100, pb, no pcix	*/
+					break;
+				} else {
+					*pctlrcap = 0xA9;	/* default to sw, 66, pb, pcix	*/
+					break;
+				}
+			}
+		} else if (subsystem_vid == PCI_VENDOR_ID_INTEL) {
+			*pctlrcap = subsystem_did;
+		} else
+			err("%s: unsupported Sub-Vendor ID: %x\n", __FUNCTION__, subsystem_vid);
+
+		php_ctlr->ctlrcap = *pctlrcap;
+	}
+
+	dbg("ctlrcap = %x\n", *pctlrcap);
+
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
+{
+	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+
+	DBG_ENTER_ROUTINE 
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	/* PCI-X support */
+	if (php_ctlr->ctlrcap & 0x0080) {
+		/* Frequency of operation in PCI-X mode */
+		if (php_ctlr->ctlrcap & 0x0040) {
+			bus_speed = PCI_SPEED_133MHz_PCIX;
+		} else {
+			if (php_ctlr->ctlrcap & 0x0001)
+				bus_speed = PCI_SPEED_66MHz_PCIX;
+			else
+				bus_speed = PCI_SPEED_100MHz_PCIX;
+		}
+	} else {
+		if (php_ctlr->ctlrcap & 0x0001)
+			bus_speed = PCI_SPEED_66MHz;
+		else
+			bus_speed = PCI_SPEED_33MHz;
+	}
+
+	*value = bus_speed;
+
+	dbg("Supported bus speed = %d\n", bus_speed);
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
+{
+	u8 adapter_speed = PCI_SPEED_UNKNOWN;
+	u8 m66cap, pcixcap1, pcixcap2;
+	u8 temp_byte;
+
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+
+	DBG_ENTER_ROUTINE 
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return -1;
+	}
+
+	down(&slot->ctrl->crit_sect);
+
+	/* turn on board without attaching to the bus */
+	temp_byte = readb(php_ctlr->creg + SLOT_POWER);
+	temp_byte |= (0x01 << slot->hp_slot);
+	writeb(temp_byte, php_ctlr->creg + SLOT_POWER);
+
+	hpc_update_hpc(slot);
+
+	/* Change bits in slot power register to force another shift out */
+	/* NOTE: this is to work around the timer bug */
+	temp_byte = readb(php_ctlr->creg + SLOT_POWER);
+	writeb(0x00, php_ctlr->creg + SLOT_POWER);
+	writeb(temp_byte, php_ctlr->creg + SLOT_POWER);
+
+	hpc_update_hpc(slot);
+
+	longdelay(6 * (HZ / 10));
+
+	m66cap = readl(php_ctlr->creg + NON_INT_INPUT) & 0xff;
+	pcixcap1 = (readl(php_ctlr->creg + NON_INT_INPUT) >> 8) & 0xff;
+	pcixcap2 = (readl(php_ctlr->creg + NON_INT_INPUT) >> 16) & 0xff;
+	dbg("m66cap = %x\n", m66cap);
+
+	if (php_ctlr->ctlrcap & PCIXSupport) {
+		if ((pcixcap1 >> slot->hp_slot) & 1) {
+			if ((pcixcap2 >> slot->hp_slot) & 1)
+				adapter_speed = PCI_SPEED_133MHz_PCIX;
+			else
+				adapter_speed = PCI_SPEED_66MHz_PCIX;
+		} else {
+			if ((m66cap >> slot->hp_slot) & 1)
+				adapter_speed = PCI_SPEED_66MHz;
+			else
+				adapter_speed = PCI_SPEED_33MHz;
+		}
+	} else {
+		if ((m66cap >> slot->hp_slot) & 1)
+			adapter_speed = PCI_SPEED_66MHz;
+		else
+			adapter_speed = PCI_SPEED_33MHz;
+	}
+
+	/* turn off board without attaching to the bus */
+	temp_byte = readb(php_ctlr->creg + SLOT_POWER);
+	temp_byte &= ~(0x01 << slot->hp_slot);
+	writeb(temp_byte, php_ctlr->creg + SLOT_POWER);
+
+	hpc_update_hpc(slot);
+
+	/* Done with exclusive hardware access */
+	up(&slot->ctrl->crit_sect);
+
+	*value = adapter_speed;
+	dbg("Adapter speed = %d\n", adapter_speed);
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u32 pci_misc_config;
+	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
+	u16 temp_word;
+	u32 temp_dword;
+	struct pci_dev *dev;
+	u8 curr_freq;
+	struct controller *ctrl;
+
+	DBG_ENTER_ROUTINE 
+	if (!slot->ctrl->hpc_ctlr_handle || !php_ctlr->pci_dev) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	ctrl = slot->ctrl;
+
+	if ((php_ctlr->pci_dev->vendor == PCI_VENDOR_ID_INTEL) &&
+		(php_ctlr->pci_dev->device == PCI_INTC_P64H2_DID)) {
+
+		/*
+		 * For P64H2 hpc, bus speed is determined by P64H2_HUB
+		 * Let's find P64H2_HUB on this bus.
+		 */
+		dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, PCI_INTC_P64H2_HUB_PCI, PCI_ANY_ID, PCI_ANY_ID, NULL);
+		if (dev == NULL)
+			info("Can't find VID-0x8086 DID-0x1460\n");
+
+		while (dev != NULL) {
+			pci_read_config_word(dev, 0x40, &temp_word);
+			pci_read_config_dword(dev, 0x18, &temp_dword);
+			dbg("%s: bus=%x dev=%x, CNF=%x, BNUM=%x\n", __FUNCTION__, dev->bus->number, PCI_SLOT(dev->devfn), temp_word, temp_dword);
+			if (((temp_dword & 0x0000ff00) >> 8) == php_ctlr->pci_dev->bus->number) {
+				if ((temp_word & 0x0100) == 0x0100) {
+					if ((temp_word & 0x00c0) == 0x00c0)
+						bus_speed = PCI_SPEED_133MHz_PCIX;
+					else if ((temp_word & 0x0080) == 0x0080)
+						bus_speed = PCI_SPEED_100MHz_PCIX;
+					else if ((temp_word & 0x0040) == 0x0040)
+						bus_speed = PCI_SPEED_66MHz_PCIX;
+				} else {
+					if ((temp_word & 0x0040) == 0x0040)
+						bus_speed = PCI_SPEED_66MHz;
+					else if ((temp_word & 0x00c0) == 0)
+						bus_speed = PCI_SPEED_33MHz;
+				}
+				break;
+			}
+			dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, PCI_INTC_P64H2_HUB_PCI, PCI_ANY_ID, PCI_ANY_ID, dev);
+		}
+	} else {
+		if (php_ctlr->ctlrcap & PCIXSupport) {
+			if ((ctrl->pci_dev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) && 
+				((ctrl->rev >= 0x13) || (ctrl->pci_dev->subsystem_device == PCI_SUB_HPC_ID4))) {
+				/* for Compaq CIOBX or PCI_SUB_HPC_ID4 */
+				curr_freq = readb(php_ctlr->creg + NEXT_CURR_FREQ);
+				if ((curr_freq & 0xB0) == 0xB0)
+					bus_speed = PCI_SPEED_133MHz_PCIX;
+				else if ((curr_freq & 0xA0) == 0xA0)
+					bus_speed = PCI_SPEED_100MHz_PCIX;
+				else if ((curr_freq & 0x90) == 0x90)
+					bus_speed = PCI_SPEED_66MHz_PCIX;
+				else if ((curr_freq & 0x10) == 0x10)
+					bus_speed = PCI_SPEED_66MHz;
+				else bus_speed = PCI_SPEED_33MHz;
+			} else {  /* all others */
+
+				pci_read_config_dword(php_ctlr->pci_dev, 0x40, &pci_misc_config);
+				/* Read HPC PCI Misc. Configuration at offset 40h */
+
+				dbg("HPC PCI Misc Config = %x\n", pci_misc_config);
+
+				if (pci_misc_config & 0x00200000) {	/* Bit 21 of PCI Misc. Config. */
+					if (readw(php_ctlr->creg + MISC) & 0x8000) {	/* Bit 31 - 133 MHZ Prescale indicator */
+						if (readw(php_ctlr->creg + MISC) & 0x0040)	/* Bit 22 - frequency range bit */
+							bus_speed = PCI_SPEED_133MHz_PCIX;
+						else
+							bus_speed = PCI_SPEED_100MHz_PCIX;
+					} else
+						bus_speed = PCI_SPEED_66MHz_PCIX;
+				} else {
+					if (readw(php_ctlr->creg + MISC) & 0x0800)	/* Bit 27 - 66MHZ Prescale indicator */
+						bus_speed = PCI_SPEED_66MHz;
+					else
+						bus_speed = PCI_SPEED_33MHz;
+				}
+			}
+		} else {
+			if (readw(php_ctlr->creg + MISC) & 0x0800)	/* Bit 27 - 66MHZ Prescale indicator */
+				bus_speed = PCI_SPEED_66MHz;
+			else
+				bus_speed = PCI_SPEED_33MHz;
+		}
+	}
+
+	*value = bus_speed;
+	dbg("Current bus speed = %d\n", bus_speed);
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static int hpc_set_controller_speed (struct slot *slot, enum pci_bus_speed value)
+{
+	struct slot *p_slot;
+	struct controller *ctrl;
+	u8 reg, adapter_speed;
+	u8 slot_power, hp_slot;
+	u16 reg16;
+	u32 leds;
+
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+
+	DBG_ENTER_ROUTINE 
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+	
+	ctrl = slot->ctrl;
+	hp_slot = slot->hp_slot;
+	slot_power = readb(php_ctlr->creg + SLOT_POWER);
+	leds = readl(php_ctlr->creg + LED_CONTROL);
+	adapter_speed = value;
+
+	/* We don't allow freq/mode changes if we find another adapter running
+	 * in another slot on this controller */
+	for(p_slot = ctrl->slot; p_slot; p_slot = p_slot->next) {
+		if (p_slot->device == (hp_slot + ctrl->slot_device_offset)) 
+			continue;
+		if (!p_slot->hotplug_slot && !p_slot->hotplug_slot->info) 
+			continue;
+		if (p_slot->hotplug_slot->info->adapter_status == 0) 
+			continue;
+		/* If another adapter is running on the same segment but at a
+		 * lower speed/mode, we allow the new adapter to function at
+		 * this rate if supported */
+		if (ctrl->speed < adapter_speed) 
+			return 0;
+
+		return 1;
+	}
+	
+	/* We try to set the max speed supported by both the adapter and
+	 * controller */
+	if (ctrl->speed_capability < adapter_speed) {
+		if (ctrl->speed == ctrl->speed_capability)
+			return 0;
+		adapter_speed = ctrl->speed_capability;
+	}
+
+	writel(0x0L, php_ctlr->creg + LED_CONTROL);
+	writeb(0x00, php_ctlr->creg + SLOT_ENABLE);
+	
+	hpc_update_hpc(slot);
+	
+	if (adapter_speed != PCI_SPEED_133MHz_PCIX)
+		reg = 0xF5;
+	else
+		reg = 0xF4;	
+	pci_write_config_byte(ctrl->pci_dev, 0x41, reg);
+	
+	reg16 = readw(php_ctlr->creg + NEXT_CURR_FREQ);
+	reg16 &= ~0x000F;
+	switch(adapter_speed) {
+		case(PCI_SPEED_133MHz_PCIX): 
+			reg = 0x75;
+			reg16 |= 0xB; 
+			break;
+		case(PCI_SPEED_100MHz_PCIX):
+			reg = 0x74;
+			reg16 |= 0xA;
+			break;
+		case(PCI_SPEED_66MHz_PCIX):
+			reg = 0x73;
+			reg16 |= 0x9;
+			break;
+		case(PCI_SPEED_66MHz):
+			reg = 0x73;
+			reg16 |= 0x1;
+			break;
+		default: /* 33MHz PCI 2.2 */
+			reg = 0x71;
+			break;
+			
+	}
+	reg16 |= 0xB << 12;
+	writew(reg16, php_ctlr->creg + NEXT_CURR_FREQ);
+	
+	mdelay(5); 
+	
+	/* Reenable interrupts */
+	writel(0, php_ctlr->creg + INT_MASK);
+
+	pci_write_config_byte(ctrl->pci_dev, 0x41, reg); 
+	
+	/* Restart state machine */
+	reg = ~0xF;
+	pci_read_config_byte(ctrl->pci_dev, 0x43, &reg);
+	pci_write_config_byte(ctrl->pci_dev, 0x43, reg);
+	
+	/* Only if mode change...*/
+	if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) ||
+		((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) 
+		hpc_update_hpc(slot);	
+
+	mdelay(1100);
+	
+	/* Restore LED/Slot state */
+	writel(leds, php_ctlr->creg + LED_CONTROL);
+	writeb(slot_power, php_ctlr->creg + SLOT_ENABLE);
+	
+	hpc_update_hpc(slot);
+
+	ctrl->speed = adapter_speed;
+	slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+	info("Successfully changed frequency/mode for adapter in slot %d\n", 
+			slot->number);
+	return 0;
+}
+
+static struct hpc_ops cpqphp_hpc_ops = {
+	.power_on_slot			= hpc_power_on_slot,
+	.power_off_slot			= hpc_power_off_slot,
+	.set_attention_status		= hpc_set_attention_status,
+	.get_power_status		= hpc_get_power_status,
+	.get_attention_status		= hpc_get_attention_status,
+	.get_latch_status		= hpc_get_latch_status,
+	.get_adapter_status		= hpc_get_adapter_status,
+
+	.get_max_bus_speed		= hpc_get_max_bus_speed,
+	.get_cur_bus_speed		= hpc_get_cur_bus_speed,
+	.get_adapter_speed		= hpc_get_adapter_speed,
+	.set_controller_speed	= hpc_set_controller_speed,
+
+	.get_slot_capability	= hpc_get_slot_capability,
+	.query_power_fault		= hpc_query_power_fault,
+	.green_led_on			= hpc_green_led_on,
+	.green_led_off			= hpc_green_led_off,
+	.green_led_blink		= hpc_green_led_blink,
+
+	.enable_msl_interrupt	= hpc_enable_msl_interrupt,
+	.update_hpc				= hpc_update_hpc,
+	.release_ctlr			= hpc_release_ctlr,
+};
+
+int phphpc_init(struct controller * ctrl,
+		struct pci_dev * pdev,
+		php_intr_callback_t switch_change_callback,
+		php_intr_callback_t presence_change_callback,
+		php_intr_callback_t power_fault_callback)
+{
+	struct php_ctlr_state_s *php_ctlr, *p;
+	void *instance_id = ctrl;
+	unsigned long psw;
+	int rc;
+	u16 temp_word, misc;
+	static int first = 1;
+
+	DBG_ENTER_ROUTINE
+	php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
+
+	if (!php_ctlr) {	/* allocate controller state data */
+		err("%s: HPC controller memory allocation error!\n", __FUNCTION__);
+		goto abort;
+	}
+
+	memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s));
+
+	php_ctlr->pci_dev = pdev;	/* save pci_dev in context */
+
+	if (first) {
+		spin_lock_init(&hpc_event_lock);
+		first = 0;
+	}
+
+	dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev->irq);
+	for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
+		if (pci_resource_len(pdev, rc) > 0)
+			dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc,
+				pci_resource_start(pdev, rc), pci_resource_len(pdev, rc));
+	info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, pdev->subsystem_device);
+
+	if (!request_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0), MY_NAME)) {
+		err("%s: cannot reserve MMIO region\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+
+	php_ctlr->creg = (struct ctrl_reg *)
+		ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+	if (!php_ctlr->creg) {
+		err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, pci_resource_len(pdev, 0), pci_resource_start(pdev, 0));
+		release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+		goto abort_free_ctlr;
+	}
+
+	init_MUTEX(&ctrl->crit_sect);
+	/* setup wait queue */
+	init_waitqueue_head(&ctrl->queue);
+
+	/* find the IRQ */
+	php_ctlr->irq = pdev->irq;
+	dbg("HPC interrupt = %d\n", php_ctlr->irq);
+
+	/* Save interrupt callback info */
+	php_ctlr->switch_change_callback = switch_change_callback;
+	php_ctlr->presence_change_callback = presence_change_callback;
+	php_ctlr->power_fault_callback = power_fault_callback;
+	php_ctlr->callback_instance_id = instance_id;
+
+	/* return PCI Controller Info */
+	php_ctlr->first_device_num = readb(php_ctlr->creg + SLOT_MASK) >> 4;
+	php_ctlr->num_slots = readb(php_ctlr->creg + SLOT_MASK) & 0xF;
+
+	/* Mask all general input interrupts */
+	writel(0xFFFFFFFFL, php_ctlr->creg + INT_MASK);
+
+	/*Disable interrupts */
+	spin_lock_irqsave(&hpc_event_lock, psw);
+
+	/*this code installs the interrupt handler */
+	rc = request_irq(php_ctlr->irq, hpc_isr, SA_SHIRQ, MY_NAME, (void *) ctrl);
+	dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc);
+
+	if ((php_ctlr->pci_dev->vendor == PCI_VENDOR_ID_INTEL) &&
+		(php_ctlr->pci_dev->device == PCI_INTC_P64H2_DID)) {
+		/*
+		 *  If this is the Intel Tiger IA64 platform, Read the ABAR config
+		 *  space register and clear bit 14 to assure HPC uses normal
+		 *  interrupts, NOT SCI interrupt.
+		 */
+		rc = pci_read_config_word(pdev, 0x80, &temp_word);
+		dbg("ABAR reads %x\n", temp_word);
+		temp_word = temp_word & 0xBFFF;
+		rc |= pci_write_config_word(pdev, 0x80, temp_word);
+		pci_read_config_word(pdev, 0x80, &temp_word);
+		if (rc || (temp_word & ~0xBFFF))
+			err("Unable to set ABAR[%x] rc = %d\n", temp_word, rc);
+		else
+			dbg("ABAR set to %x\n", temp_word);
+	}
+
+	/* Re-enable interrupts */
+	spin_unlock_irqrestore(&hpc_event_lock, psw);
+
+	/* Enable Shift Out interrupt and clear it, also */
+	/* enable SERR on power fault */
+	misc = readw(php_ctlr->creg + MISC);
+	misc |= 0x6006;
+	writew(misc, php_ctlr->creg + MISC);
+
+	/* Changed 05/05/97 to clear all interrupts at start */
+	writel(0xFFFFFFFF, php_ctlr->creg + INT_INPUT_CLEAR);	
+
+	php_ctlr->ctrl_int_comp = readl(php_ctlr->creg + INT_INPUT_CLEAR);
+
+	writel(0x0L, php_ctlr->creg + INT_MASK);
+	/*
+	 *  Initialize the per slot SERR for unexpected switch open to 0
+	 *  If the bit is et to 1, slot switch interrupt causes the SERR# pin
+	 *  to be asserted.
+	 */
+	writeb(0, php_ctlr->creg + SLOT_SERR);
+
+	/*  Add this HPC instance into the HPC list */
+	/*  TO DO:  Do we need to spinlock this? */
+	if (php_ctlr_list_head == 0) {
+		php_ctlr_list_head = php_ctlr;
+		p = php_ctlr_list_head;
+		p->pnext = 0;
+	} else {
+		p = php_ctlr_list_head;
+
+		while (p->pnext)
+			p = p->pnext;
+
+		p->pnext = php_ctlr;
+	}
+
+	ctlr_seq_num++;
+	ctrl->hpc_ctlr_handle = php_ctlr;
+	ctrl->hpc_ops = &cpqphp_hpc_ops;
+
+	DBG_LEAVE_ROUTINE
+	return 0;
+
+	/* We end up here for the many possible ways to fail this API.  */
+abort_free_ctlr:
+	kfree(php_ctlr);
+abort:
+	DBG_LEAVE_ROUTINE
+	return -1;
+}
diff -Nru a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c
--- a/drivers/pci/hotplug/cpqphp_pci.c	2003-07-02 13:56:02.000000000 -0700
+++ b/drivers/pci/hotplug/cpqphp_pci.c	2003-07-07 09:32:23.000000000 -0700
@@ -36,50 +36,9 @@
 #include <linux/pci.h>
 #include "../pci.h"
 #include "cpqphp.h"
-#include "cpqphp_nvram.h"
-#include "../../../arch/i386/pci/pci.h"	/* horrible hack showing how processor dependent we are... */
-
-
-u8 cpqhp_nic_irq;
-u8 cpqhp_disk_irq;
-
-static u16 unused_IRQ;
-
-/*
- * detect_HRT_floating_pointer
- *
- * find the Hot Plug Resource Table in the specified region of memory.
- *
- */
-static void *detect_HRT_floating_pointer(void *begin, void *end)
-{
-	void *fp;
-	void *endp;
-	u8 temp1, temp2, temp3, temp4;
-	int status = 0;
-
-	endp = (end - sizeof(struct hrt) + 1);
-
-	for (fp = begin; fp <= endp; fp += 16) {
-		temp1 = readb(fp + SIG0);
-		temp2 = readb(fp + SIG1);
-		temp3 = readb(fp + SIG2);
-		temp4 = readb(fp + SIG3);
-		if (temp1 == '$' &&
-		    temp2 == 'H' &&
-		    temp3 == 'R' &&
-		    temp4 == 'T') {
-			status = 1;
-			break;
-		}
-	}
-
-	if (!status)
-		fp = NULL;
-
-	dbg("Discovered Hotplug Resource Table at %p\n", fp);
-	return fp;
-}
+#ifndef CONFIG_IA64
+#include "../arch/i386/pci/pci.h"    /* horrible hack showing how processor dependant we are... */
+#endif
 
 
 int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)  
@@ -93,7 +52,7 @@
 
 	/* No pci device, we need to create it then */
 	if (func->pci_dev == NULL) {
-		dbg("INFO: pci_dev still null\n");
+		dbg("%s: pci_dev still null. do pci_scan_slot\n", __FUNCTION__);
 
 		num = pci_scan_slot(ctrl->pci_dev->bus, PCI_DEVFN(func->device, func->function));
 		if (num)
@@ -118,29 +77,37 @@
 
 int cpqhp_unconfigure_device(struct pci_func* func) 
 {
+	int rc = 0;
 	int j;
-	
+
+
 	dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, func->device, func->function);
 
 	for (j=0; j<8 ; j++) {
 		struct pci_dev* temp = pci_find_slot(func->bus, (func->device << 3) | j);
-		if (temp)
+		if (temp) {
 			pci_remove_bus_device(temp);
+		}
 	}
-	return 0;
+	return rc;
 }
 
 static int PCI_RefinedAccessConfig(struct pci_bus *bus, unsigned int devfn, u8 offset, u32 *value)
 {
 	u32 vendID = 0;
+	int rc;
+
+	rc = pci_bus_read_config_dword (bus, devfn, PCI_VENDOR_ID, &vendID);
 
-	if (pci_bus_read_config_dword (bus, devfn, PCI_VENDOR_ID, &vendID) == -1)
+	if (rc == -1)
 		return -1;
 	if (vendID == 0xffffffff)
 		return -1;
-	return pci_bus_read_config_dword (bus, devfn, offset, value);
-}
 
+	rc = pci_bus_read_config_dword (bus, devfn, offset, value);
+
+	return rc;
+}
 
 /*
  * cpqhp_set_irq
@@ -151,6 +118,7 @@
  */
 int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
 {
+#if defined(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM) && defined(CONFIG_X86)
 	int rc;
 	u16 temp_word;
 	struct pci_dev fakedev;
@@ -166,60 +134,53 @@
 	if (!rc)
 		return !rc;
 
-	// set the Edge Level Control Register (ELCR)
+	/* set the Edge Level Control Register (ELCR) */
 	temp_word = inb(0x4d0);
 	temp_word |= inb(0x4d1) << 8;
 
 	temp_word |= 0x01 << irq_num;
 
-	// This should only be for x86 as it sets the Edge Level Control Register
+	/* This should only be for x86 as it sets the Edge Level Control Register */
 	outb((u8) (temp_word & 0xFF), 0x4d0);
 	outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
-
+#endif
 	return 0;
 }
 
 
-/*
- * WTF??? This function isn't in the code, yet a function calls it, but the 
- * compiler optimizes it away?  strange.  Here as a placeholder to keep the 
- * compiler happy.
- */
-static int PCI_ScanBusNonBridge (u8 bus, u8 device)
-{
-	return 0;
-}
 
-static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 * dev_num)
+static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 * bus_num, u8 * dev_num)
 {
 	u8 tdevice;
 	u32 work;
 	u8 tbus;
+	struct pci_bus lpci_bus, *pci_bus;
 
-	ctrl->pci_bus->number = bus_num;
+	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = *bus_num;
 
-	for (tdevice = 0; tdevice < 0xFF; tdevice++) {
-		//Scan for access first
-		if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
+	for (tdevice = 0; tdevice < 0x100; tdevice++) {
+		if (PCI_RefinedAccessConfig (pci_bus, tdevice, 0x08, &work) == -1)
 			continue;
-		dbg("Looking for nonbridge bus_num %d dev_num %d\n", bus_num, tdevice);
-		//Yep we got one. Not a bridge ?
+		dbg("Looking for nonbridge bus_num %d dev_num %d\n", *bus_num, tdevice);
 		if ((work >> 8) != PCI_TO_PCI_BRIDGE_CLASS) {
 			*dev_num = tdevice;
 			dbg("found it !\n");
 			return 0;
 		}
 	}
-	for (tdevice = 0; tdevice < 0xFF; tdevice++) {
-		//Scan for access first
-		if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
+	for (tdevice = 0; tdevice < 0x100; tdevice++) {
+		if (PCI_RefinedAccessConfig (pci_bus, tdevice, 0x08, &work) == -1)
 			continue;
-		dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice);
-		//Yep we got one. bridge ?
+		dbg("Looking for bridge bus_num %d dev_num %d\n", *bus_num, tdevice);
 		if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
-			pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(tdevice, 0), PCI_SECONDARY_BUS, &tbus);
-			dbg("Recurse on bus_num %d tdevice %d\n", tbus, tdevice);
-			if (PCI_ScanBusNonBridge(tbus, tdevice) == 0)
+			pci_bus_read_config_byte(pci_bus, tdevice, PCI_SECONDARY_BUS, &tbus);
+
+			dbg("Found a new bus %d on bus %d device %d\n", tbus, *bus_num, tdevice);
+			dbg("Recurse on the new bus %d\n", tbus);
+			*bus_num = tbus;
+			if (PCI_ScanBusForNonBridge(ctrl, bus_num, dev_num) == 0)  
 				return 0;
 		}
 	}
@@ -227,75 +188,59 @@
 	return -1;
 }
 
-
-static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot, u8 nobridge)
+static int PCI_GetBusDevHelper(struct controller *ctrl, u8 * bus_num, u8 * dev_num,
+			       struct slot *slot, u8 nobridge)
 {
-	struct irq_routing_table *PCIIRQRoutingInfoLength;
-	long len;
 	long loop;
 	u32 work;
+	u8 tbus, tdevice;
+	struct pci_bus lpci_bus, *pci_bus;
+	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+
+	dbg("GetBusDev: bus %d dev %d func %d\n", *bus_num, *dev_num >> 3, *dev_num & 0x7);
+	for (loop = 0; loop < 8; ++loop) {
+		tbus = slot->bus;
+		tdevice = slot->device << 3 | loop;
+
+		*bus_num = tbus;
+		*dev_num = tdevice;
+		pci_bus->number = tbus;
 
-	u8 tbus, tdevice, tslot;
+		pci_bus_read_config_dword(pci_bus, *dev_num, PCI_VENDOR_ID, &work);
 
-	PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table();
-	if (!PCIIRQRoutingInfoLength)
-		return -1;
+		if (!nobridge || (work == 0xffffffff)) {
+			dbg("GetBusDev: nodev bus %d dev %d func %d\n", *bus_num, *dev_num >> 3, *dev_num & 0x7);
+			return 0;
+		}
 
-	len = (PCIIRQRoutingInfoLength->size -
-	       sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
-	// Make sure I got at least one entry
-	if (len == 0) {
-		if (PCIIRQRoutingInfoLength != NULL)
-			kfree(PCIIRQRoutingInfoLength );
-		return -1;
-	}
+		dbg("bus_num %d dev_num %d func_num %d\n", *bus_num, *dev_num >> 3, *dev_num & 0x7);
 
-	for (loop = 0; loop < len; ++loop) {
-		tbus = PCIIRQRoutingInfoLength->slots[loop].bus;
-		tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn;
-		tslot = PCIIRQRoutingInfoLength->slots[loop].slot;
+		pci_bus_read_config_dword(pci_bus, *dev_num, PCI_CLASS_REVISION, &work);
 
-		if (tslot == slot) {
-			*bus_num = tbus;
-			*dev_num = tdevice;
-			ctrl->pci_bus->number = tbus;
-			pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_VENDOR_ID, &work);
-			if (!nobridge || (work == 0xffffffff)) {
-				if (PCIIRQRoutingInfoLength != NULL)
-					kfree(PCIIRQRoutingInfoLength );
-				return 0;
-			}
+		dbg("work >> 8 (%x) = BRIDGE (%x)\n", work >> 8, PCI_TO_PCI_BRIDGE_CLASS);
 
-			dbg("bus_num %d devfn %d\n", *bus_num, *dev_num);
-			pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_CLASS_REVISION, &work);
-			dbg("work >> 8 (%x) = BRIDGE (%x)\n", work >> 8, PCI_TO_PCI_BRIDGE_CLASS);
-
-			if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
-				pci_bus_read_config_byte (ctrl->pci_bus, *dev_num, PCI_SECONDARY_BUS, &tbus);
-				dbg("Scan bus for Non Bridge: bus %d\n", tbus);
-				if (PCI_ScanBusForNonBridge(ctrl, tbus, dev_num) == 0) {
-					*bus_num = tbus;
-					if (PCIIRQRoutingInfoLength != NULL)
-						kfree(PCIIRQRoutingInfoLength );
-					return 0;
-				}
-			} else {
-				if (PCIIRQRoutingInfoLength != NULL)
-					kfree(PCIIRQRoutingInfoLength );
-				return 0;
-			}
+		if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
 
-		}
+			pci_bus_read_config_byte(pci_bus, *dev_num, PCI_SECONDARY_BUS, &tbus);
+
+			dbg("Scan bus for Non Bridge: bus %d\n", tbus);
+			*bus_num = tbus;
+			if (PCI_ScanBusForNonBridge(ctrl, bus_num, dev_num) == 0)
+				return 0;
+			else
+				dbg("no Non Bridge under bus %d\n", tbus);
+		} else
+			return 0;
 	}
-	if (PCIIRQRoutingInfoLength != NULL)
-		kfree(PCIIRQRoutingInfoLength );
+
+	dbg("GetBusDev: fail bus %d dev %d func %d\n", *bus_num, *dev_num >> 3, *dev_num & 0x7);
 	return -1;
 }
 
-
-int cpqhp_get_bus_dev (struct controller *ctrl, u8 * bus_num, u8 * dev_num, u8 slot)
+int cpqhp_get_bus_dev (struct controller *ctrl, u8 * bus_num, u8 * dev_num, struct slot *slot)
 {
-	return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0);	//plain (bridges allowed)
+	return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0);	/*plain (bridges allowed) */
 }
 
 
@@ -311,9 +256,9 @@
  *
  * returns 0 if success
  */
-int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug)
+int cpqhp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num)
 {
-	long rc;
+	int rc;
 	u8 class_code;
 	u8 header_type;
 	u32 ID;
@@ -329,36 +274,46 @@
 	int cloop = 0;
 	int stop_it;
 	int index;
+	int is_hot_plug = num_ctlr_slots || first_device_num;
+	struct pci_bus lpci_bus, *pci_bus;
+	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
 
-	//              Decide which slots are supported
+	dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, num_ctlr_slots, first_device_num);
 
+	/*  Decide which slots are supported */
 	if (is_hot_plug) {
-		//*********************************
-		// is_hot_plug is the slot mask
-		//*********************************
-		FirstSupported = is_hot_plug >> 4;
-		LastSupported = FirstSupported + (is_hot_plug & 0x0F) - 1;
+		/*********************************
+		 is_hot_plug is the slot mask
+		 *********************************/
+		FirstSupported = first_device_num;
+		LastSupported = FirstSupported + num_ctlr_slots - 1;
 	} else {
 		FirstSupported = 0;
 		LastSupported = 0x1F;
 	}
 
-	//     Save PCI configuration space for all devices in supported slots
-	ctrl->pci_bus->number = busnumber;
+	dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported, LastSupported);
+
+	/* Save PCI configuration space for all devices in supported slots */
+	pci_bus->number = busnumber;
 	for (device = FirstSupported; device <= LastSupported; device++) {
 		ID = 0xFFFFFFFF;
-		rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
+		rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
 
-		if (ID != 0xFFFFFFFF) {	  //  device in slot
-			rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code);
+		if (ID != 0xFFFFFFFF) {	  /*  device in slot */
+			rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code);
+			
 			if (rc)
 				return rc;
 
-			rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type);
+			rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type);
 			if (rc)
 				return rc;
 
-			// If multi-function device, set max_functions to 8
+			dbg("class_code = %x, header_type = %x\n", class_code, header_type);
+
+			/* If multi-function device, set max_functions to 8 */
 			if (header_type & 0x80)
 				max_functions = 8;
 			else
@@ -369,33 +324,36 @@
 			do {
 				DevError = 0;
 
-				if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {   // P-P Bridge
-					//  Recurse the subordinate bus
-					//  get the subordinate bus number
-					rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, function), PCI_SECONDARY_BUS, &secondary_bus);
+				if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {   /* P-P Bridge */
+					/*  Recurse the subordinate bus
+					    get the subordinate bus number */
+					rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), PCI_SECONDARY_BUS, &secondary_bus);
 					if (rc) {
 						return rc;
 					} else {
 						sub_bus = (int) secondary_bus;
 
-						// Save secondary bus cfg spc
-						// with this recursive call.
-						rc = cpqhp_save_config(ctrl, sub_bus, 0);
+						/* Save secondary bus cfg spc
+						   with this recursive call. */
+						rc = cpqhp_save_config(ctrl, sub_bus, 0, 0);
 						if (rc)
 							return rc;
-						ctrl->pci_bus->number = busnumber;
 					}
 				}
 
 				index = 0;
 				new_slot = cpqhp_slot_find(busnumber, device, index++);
-				while (new_slot && 
-				       (new_slot->function != (u8) function))
-					new_slot = cpqhp_slot_find(busnumber, device, index++);
 
+				dbg("new_slot = %p\n", new_slot);
+
+				while (new_slot && (new_slot->function != (u8) function)) {
+					new_slot = cpqhp_slot_find(busnumber, device, index++);
+					dbg("new_slot = %p\n", new_slot);
+				}
 				if (!new_slot) {
-					// Setup slot structure.
+					/* Setup slot structure. */
 					new_slot = cpqhp_slot_create(busnumber);
+					dbg("new_slot = %p\n", new_slot);
 
 					if (new_slot == NULL)
 						return(1);
@@ -406,12 +364,15 @@
 				new_slot->function = (u8) function;
 				new_slot->is_a_board = 1;
 				new_slot->switch_save = 0x10;
-				// In case of unsupported board
+				/* In case of unsupported board */
 				new_slot->status = DevError;
 				new_slot->pci_dev = pci_find_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function);
+				dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev);
 
 				for (cloop = 0; cloop < 0x20; cloop++) {
-					rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));
+					rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, function), cloop << 2, (u32 *) & (new_slot->config_space [cloop]));
+
+					/*dbg("new_slot->config_space[%x] = %x\n", cloop, new_slot->config_space[cloop]); */
 					if (rc)
 						return rc;
 				}
@@ -420,35 +381,40 @@
 
 				stop_it = 0;
 
-				//  this loop skips to the next present function
-				//  reading in Class Code and Header type.
+				/*  this loop skips to the next present function
+				    reading in Class Code and Header type. */
 
 				while ((function < max_functions)&&(!stop_it)) {
-					rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, function), PCI_VENDOR_ID, &ID);
-					if (ID == 0xFFFFFFFF) {	 // nothing there.
+					rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, function), PCI_VENDOR_ID, &ID);
+
+					if (ID == 0xFFFFFFFF) {  /* nothing there. */
 						function++;
-					} else {  // Something there
-						rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, function), 0x0B, &class_code);
+						dbg("Nothing there\n");
+					} else {  /* Something there */
+
+						rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), 0x0B, &class_code);
 						if (rc)
 							return rc;
 
-						rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, function), PCI_HEADER_TYPE, &header_type);
+						rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), PCI_HEADER_TYPE, &header_type);
 						if (rc)
 							return rc;
 
+						dbg("class_code = %x, header_type = %x\n", class_code, header_type);
 						stop_it++;
 					}
 				}
 
 			} while (function < max_functions);
-		}		// End of IF (device in slot?)
+		}		/* End of IF (device in slot?) */
 		else if (is_hot_plug) {
-			// Setup slot structure with entry for empty slot
+			/* Setup slot structure with entry for empty slot */
 			new_slot = cpqhp_slot_create(busnumber);
 
 			if (new_slot == NULL) {
 				return(1);
 			}
+			dbg("new_slot = %p\n", new_slot);
 
 			new_slot->bus = (u8) busnumber;
 			new_slot->device = (u8) device;
@@ -457,7 +423,7 @@
 			new_slot->presence_save = 0;
 			new_slot->switch_save = 0;
 		}
-	}			// End of FOR loop
+	}			/* End of FOR loop */
 
 	return(0);
 }
@@ -473,7 +439,7 @@
  */
 int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot)
 {
-	long rc;
+	int rc;
 	u8 class_code;
 	u8 header_type;
 	u32 ID;
@@ -483,17 +449,21 @@
 	int function;
 	int cloop = 0;
 	int stop_it;
+	struct pci_bus lpci_bus, *pci_bus;
+	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = new_slot->bus;
 
 	ID = 0xFFFFFFFF;
 
-	ctrl->pci_bus->number = new_slot->bus;
-	pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID);
+	pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID);
+
+	if (ID != 0xFFFFFFFF) {	  /*  device in slot */
+		pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code);
 
-	if (ID != 0xFFFFFFFF) {	  //  device in slot
-		pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code);
-		pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type);
+		pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type);
 
-		if (header_type & 0x80)	// Multi-function device
+		if (header_type & 0x80)	/* Multi-function device */
 			max_functions = 8;
 		else
 			max_functions = 1;
@@ -501,49 +471,47 @@
 		function = 0;
 
 		do {
-			if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  // PCI-PCI Bridge
-				//  Recurse the subordinate bus
-				pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_SECONDARY_BUS, &secondary_bus);
+			if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	 /* PCI-PCI Bridge */
+				/*  Recurse the subordinate bus */
+				pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_SECONDARY_BUS, &secondary_bus);
 
 				sub_bus = (int) secondary_bus;
 
-				// Save the config headers for the secondary bus.
-				rc = cpqhp_save_config(ctrl, sub_bus, 0);
+				/* Save the config headers for the secondary bus. */
+				rc = cpqhp_save_config(ctrl, sub_bus, 0, 0);
+
 				if (rc)
 					return(rc);
-				ctrl->pci_bus->number = new_slot->bus;
 
-			}	// End of IF
+			}	/* End of IF */
 
 			new_slot->status = 0;
 
 			for (cloop = 0; cloop < 0x20; cloop++) {
-				pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));
+				pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, function), cloop << 2, (u32 *) & (new_slot->config_space [cloop]));
 			}
 
 			function++;
 
 			stop_it = 0;
 
-			//  this loop skips to the next present function
-			//  reading in the Class Code and the Header type.
+			/*  this loop skips to the next present function
+			    reading in the Class Code and the Header type. */
 
 			while ((function < max_functions) && (!stop_it)) {
-				pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID);
+				pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID);
 
-				if (ID == 0xFFFFFFFF) {	 // nothing there.
+				if (ID == 0xFFFFFFFF) {	 /* nothing there. */
 					function++;
-				} else {  // Something there
-					pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code);
-
-					pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, &header_type);
-
+				} else {  /* Something there */
+					pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code);
+					pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, &header_type);
 					stop_it++;
 				}
 			}
 
 		} while (function < max_functions);
-	}			// End of IF (device in slot?)
+	}			/* End of IF (device in slot?) */
 	else {
 		return(2);
 	}
@@ -553,136 +521,6 @@
 
 
 /*
- * cpqhp_save_base_addr_length
- *
- * Saves the length of all base address registers for the
- * specified slot.  this is for hot plug REPLACE
- *
- * returns 0 if success
- */
-int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func)
-{
-	u8 cloop;
-	u8 header_type;
-	u8 secondary_bus;
-	u8 type;
-	int sub_bus;
-	u32 temp_register;
-	u32 base;
-	u32 rc;
-	struct pci_func *next;
-	int index = 0;
-	struct pci_bus *pci_bus = ctrl->pci_bus;
-	unsigned int devfn;
-
-	func = cpqhp_slot_find(func->bus, func->device, index++);
-
-	while (func != NULL) {
-		pci_bus->number = func->bus;
-		devfn = PCI_DEVFN(func->device, func->function);
-
-		// Check for Bridge
-		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
-
-		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
-			// PCI-PCI Bridge
-			pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
-
-			sub_bus = (int) secondary_bus;
-
-			next = cpqhp_slot_list[sub_bus];
-
-			while (next != NULL) {
-				rc = cpqhp_save_base_addr_length(ctrl, next);
-
-				if (rc)
-					return(rc);
-
-				next = next->next;
-			}
-			pci_bus->number = func->bus;
-
-			//FIXME: this loop is duplicated in the non-bridge case.  The two could be rolled together
-			// Figure out IO and memory base lengths
-			for (cloop = 0x10; cloop <= 0x14; cloop += 4) {
-				temp_register = 0xFFFFFFFF;
-				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
-				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
-
-				if (base) {  // If this register is implemented
-					if (base & 0x01L) {
-						// IO base
-						// set base = amount of IO space requested
-						base = base & 0xFFFFFFFE;
-						base = (~base) + 1;
-
-						type = 1;
-					} else {
-						// memory base
-						base = base & 0xFFFFFFF0;
-						base = (~base) + 1;
-
-						type = 0;
-					}
-				} else {
-					base = 0x0L;
-					type = 0;
-				}
-
-				// Save information in slot structure
-				func->base_length[(cloop - 0x10) >> 2] =
-				base;
-				func->base_type[(cloop - 0x10) >> 2] = type;
-
-			}	// End of base register loop
-
-
-		} else if ((header_type & 0x7F) == 0x00) {	  // PCI-PCI Bridge
-			// Figure out IO and memory base lengths
-			for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
-				temp_register = 0xFFFFFFFF;
-				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
-				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
-
-				if (base) {  // If this register is implemented
-					if (base & 0x01L) {
-						// IO base
-						// base = amount of IO space requested
-						base = base & 0xFFFFFFFE;
-						base = (~base) + 1;
-
-						type = 1;
-					} else {
-						// memory base
-						// base = amount of memory space requested
-						base = base & 0xFFFFFFF0;
-						base = (~base) + 1;
-
-						type = 0;
-					}
-				} else {
-					base = 0x0L;
-					type = 0;
-				}
-
-				// Save information in slot structure
-				func->base_length[(cloop - 0x10) >> 2] = base;
-				func->base_type[(cloop - 0x10) >> 2] = type;
-
-			}	// End of base register loop
-
-		} else {	  // Some other unknown header type
-		}
-
-		// find the next device in this slot
-		func = cpqhp_slot_find(func->bus, func->device, index++);
-	}
-
-	return(0);
-}
-
-
-/*
  * cpqhp_save_used_resources
  *
  * Stores used resource information for existing boards.  this is
@@ -690,50 +528,62 @@
  * this function is for hot plug ADD
  *
  * returns 0 if success
+ * if disable  == 1(DISABLE_CARD),
+ *  it loops for all functions of the slot and disables them.
+ * else, it just get resources of the function and return.
  */
-int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
+int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func *func, int disable)
 {
 	u8 cloop;
 	u8 header_type;
 	u8 secondary_bus;
 	u8 temp_byte;
-	u8 b_base;
-	u8 b_length;
 	u16 command;
 	u16 save_command;
-	u16 w_base;
-	u16 w_length;
+	u16 w_base, w_length;
 	u32 temp_register;
 	u32 save_base;
-	u32 base;
+	u32 base, length;
+	u64 base64 = 0;
 	int index = 0;
-	struct pci_resource *mem_node;
-	struct pci_resource *p_mem_node;
+	unsigned int devfn;
+	struct pci_resource *mem_node = NULL;
+	struct pci_resource *p_mem_node = NULL;
+	struct pci_resource *t_mem_node;
 	struct pci_resource *io_node;
 	struct pci_resource *bus_node;
-	struct pci_bus *pci_bus = ctrl->pci_bus;
-	unsigned int devfn;
+	struct pci_bus lpci_bus, *pci_bus;
+	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
 
-	func = cpqhp_slot_find(func->bus, func->device, index++);
+	if (disable)
+		func = cpqhp_slot_find(func->bus, func->device, index++);
 
 	while ((func != NULL) && func->is_a_board) {
 		pci_bus->number = func->bus;
 		devfn = PCI_DEVFN(func->device, func->function);
 
-		// Save the command register
+		/* Save the command register */
 		pci_bus_read_config_word (pci_bus, devfn, PCI_COMMAND, &save_command);
 
-		// disable card
-		command = 0x00;
-		pci_bus_write_config_word (pci_bus, devfn, PCI_COMMAND, command);
+		if (disable) {
+			/* disable card */
+			command = 0x00;
+
+			pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
+		}
 
-		// Check for Bridge
+		/* Check for Bridge */
 		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
 
-		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  // PCI-PCI Bridge
-			// Clear Bridge Control Register
-			command = 0x00;
-			pci_bus_write_config_word (pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
+		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {     /* PCI-PCI Bridge */
+			dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n", func->bus, func->device, save_command);
+			if (disable) {
+				/* Clear Bridge Control Register */
+				command = 0x00;
+				pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
+			}
+
 			pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
 			pci_bus_read_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);
 
@@ -741,661 +591,290 @@
 			if (!bus_node)
 				return -ENOMEM;
 
-			bus_node->base = secondary_bus;
-			bus_node->length = temp_byte - secondary_bus + 1;
+			bus_node->base = (ulong)secondary_bus;
+			bus_node->length = (ulong)(temp_byte - secondary_bus + 1);
 
 			bus_node->next = func->bus_head;
 			func->bus_head = bus_node;
 
-			// Save IO base and Limit registers
-			pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_BASE, &b_base);
-			pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_LIMIT, &b_length);
+			/* Save IO base and Limit registers */
+			pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_BASE, &temp_byte);
+			base = temp_byte;
+			pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_LIMIT, &temp_byte);
+			length = temp_byte;
 
-			if ((b_base <= b_length) && (save_command & 0x01)) {
+			if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) {
 				io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
 				if (!io_node)
 					return -ENOMEM;
 
-				io_node->base = (b_base & 0xF0) << 8;
-				io_node->length = (b_length - b_base + 0x10) << 8;
+				io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8;
+				io_node->length = (ulong)(length - base + 0x10) << 8;
 
 				io_node->next = func->io_head;
 				func->io_head = io_node;
 			}
 
-			// Save memory base and Limit registers
+			/* Save memory base and Limit registers */
 			pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
 			pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
 
-			if ((w_base <= w_length) && (save_command & 0x02)) {
+			if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
 				mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
 				if (!mem_node)
 					return -ENOMEM;
 
-				mem_node->base = w_base << 16;
-				mem_node->length = (w_length - w_base + 0x10) << 16;
+				mem_node->base = (ulong)w_base << 16;
+				mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
 
 				mem_node->next = func->mem_head;
 				func->mem_head = mem_node;
 			}
-
-			// Save prefetchable memory base and Limit registers
+			/* Save prefetchable memory base and Limit registers */
 			pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
 			pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
 
-			if ((w_base <= w_length) && (save_command & 0x02)) {
+			if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
 				p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
 				if (!p_mem_node)
 					return -ENOMEM;
 
-				p_mem_node->base = w_base << 16;
-				p_mem_node->length = (w_length - w_base + 0x10) << 16;
+				p_mem_node->base = (ulong)w_base << 16;
+				p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
 
 				p_mem_node->next = func->p_mem_head;
 				func->p_mem_head = p_mem_node;
 			}
-			// Figure out IO and memory base lengths
-			for (cloop = 0x10; cloop <= 0x14; cloop += 4) {
+
+			/* Figure out IO and memory base lengths
+			   P2P BAR is not for children though... */
+			for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_1; cloop += 4) {
 				pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base);
 
 				temp_register = 0xFFFFFFFF;
 				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
-				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
+				pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp_register);
 
-				temp_register = base;
+				if (!disable) {
+					pci_bus_write_config_dword (pci_bus, devfn, cloop, save_base);
+				}
 
-				if (base) {  // If this register is implemented
-					if (((base & 0x03L) == 0x01)
-					    && (save_command & 0x01)) {
-						// IO base
-						// set temp_register = amount of IO space requested
-						temp_register = base & 0xFFFFFFFE;
-						temp_register = (~temp_register) + 1;
-
-						io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-						if (!io_node)
-							return -ENOMEM;
-
-						io_node->base =
-						save_base & (~0x03L);
-						io_node->length = temp_register;
+				if (!temp_register)
+					continue;
 
-						io_node->next = func->io_head;
-						func->io_head = io_node;
+				base = temp_register;
+
+				if ((base & PCI_BASE_ADDRESS_SPACE_IO) && (!disable || (save_command & PCI_COMMAND_IO))) {
+					/* IO base */
+					/* set temp_register = amount of IO space requested */
+					base = base & 0xFFFFFFFCL;
+					base = (~base) + 1;
+
+					io_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL);
+					if (!io_node)
+						return -ENOMEM;
+
+					io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK;
+					io_node->length = (ulong)base;
+					dbg("sur: IO bar=0x%x(length=0x%x)\n", io_node->base, io_node->length);
+
+					io_node->next = func->io_head;
+					func->io_head = io_node;
+				} else {  /* map Memory */
+					int prefetchable = 1;
+					char *res_type_str = "PMEM";
+					u32 temp_register2;
+
+					t_mem_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL);
+					if (!t_mem_node)
+						return -ENOMEM;
+
+					if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
+						prefetchable = 0;
+						mem_node = t_mem_node;
+						res_type_str++;
 					} else
-						if (((base & 0x0BL) == 0x08)
-						    && (save_command & 0x02)) {
-						// prefetchable memory base
-						temp_register = base & 0xFFFFFFF0;
-						temp_register = (~temp_register) + 1;
-
-						p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-						if (!p_mem_node)
-							return -ENOMEM;
+						p_mem_node = t_mem_node;
 
-						p_mem_node->base = save_base & (~0x0FL);
-						p_mem_node->length = temp_register;
+					base = base & 0xFFFFFFF0L;
+					base = (~base) + 1;
 
-						p_mem_node->next = func->p_mem_head;
-						func->p_mem_head = p_mem_node;
-					} else
-						if (((base & 0x0BL) == 0x00)
-						    && (save_command & 0x02)) {
-						// prefetchable memory base
-						temp_register = base & 0xFFFFFFF0;
-						temp_register = (~temp_register) + 1;
-
-						mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-						if (!mem_node)
-							return -ENOMEM;
+					switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
+					case PCI_BASE_ADDRESS_MEM_TYPE_32:
+						if (prefetchable) {
+							p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
+							p_mem_node->length = (ulong)base;
+							dbg("sur: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, p_mem_node->base, p_mem_node->length);
+
+							p_mem_node->next = func->p_mem_head;
+							func->p_mem_head = p_mem_node;
+						} else {
+							mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
+							mem_node->length = (ulong)base;
+							dbg("sur: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, mem_node->base, mem_node->length);
+
+							mem_node->next = func->mem_head;
+							func->mem_head = mem_node;
+						}
+						break;
+					case PCI_BASE_ADDRESS_MEM_TYPE_64:
+						pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
+
+						base64 = temp_register2;
+						base64 = (base64 << 32) | save_base;
+
+						if (temp_register2) {
+							dbg("sur: 64 %s high dword of base64(0x%x:%x) masked to 0\n", res_type_str, temp_register2, (u32)base64);
+							base64 &= 0x00000000FFFFFFFFL;
+						}
+
+						if (prefetchable) {
+							p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
+							p_mem_node->length = base;
+							dbg("sur: 64 %s base=0x%x(len=0x%x)\n", res_type_str, p_mem_node->base, p_mem_node->length);
+
+							p_mem_node->next = func->p_mem_head;
+							func->p_mem_head = p_mem_node;
+						} else {
+							mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
+							mem_node->length = base;
+							dbg("sur: 64 %s base=0x%x(len=0x%x)\n", res_type_str, mem_node->base, mem_node->length);
+
+							mem_node->next = func->mem_head;
+							func->mem_head = mem_node;
+						}
+						cloop += 4;
+						break;
+					default:
+						dbg("asur: reserved BAR type=0x%x\n", temp_register);
+						break;
 
-						mem_node->base = save_base & (~0x0FL);
-						mem_node->length = temp_register;
+					}
+				} 
+			}	/* End of base register loop */
+		} else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
+			dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n", func->bus, func->device, save_command);
 
-						mem_node->next = func->mem_head;
-						func->mem_head = mem_node;
-					} else
-						return(1);
-				}
-			}	// End of base register loop
-		} else if ((header_type & 0x7F) == 0x00) {	  // Standard header
-			// Figure out IO and memory base lengths
-			for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
+			/* Figure out IO and memory base lengths */
+			for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
 				pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base);
 
 				temp_register = 0xFFFFFFFF;
-				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
-				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
-
-				temp_register = base;
-
-				if (base) {	  // If this register is implemented
-					if (((base & 0x03L) == 0x01)
-					    && (save_command & 0x01)) {
-						// IO base
-						// set temp_register = amount of IO space requested
-						temp_register = base & 0xFFFFFFFE;
-						temp_register = (~temp_register) + 1;
-
-						io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-						if (!io_node)
-							return -ENOMEM;
-
-						io_node->base = save_base & (~0x01L);
-						io_node->length = temp_register;
-
-						io_node->next = func->io_head;
-						func->io_head = io_node;
-					} else
-						if (((base & 0x0BL) == 0x08)
-						    && (save_command & 0x02)) {
-						// prefetchable memory base
-						temp_register = base & 0xFFFFFFF0;
-						temp_register = (~temp_register) + 1;
-
-						p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-						if (!p_mem_node)
-							return -ENOMEM;
-
-						p_mem_node->base = save_base & (~0x0FL);
-						p_mem_node->length = temp_register;
-
-						p_mem_node->next = func->p_mem_head;
-						func->p_mem_head = p_mem_node;
-					} else
-						if (((base & 0x0BL) == 0x00)
-						    && (save_command & 0x02)) {
-						// prefetchable memory base
-						temp_register = base & 0xFFFFFFF0;
-						temp_register = (~temp_register) + 1;
-
-						mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-						if (!mem_node)
-							return -ENOMEM;
-
-						mem_node->base = save_base & (~0x0FL);
-						mem_node->length = temp_register;
 
-						mem_node->next = func->mem_head;
-						func->mem_head = mem_node;
-					} else
-						return(1);
-				}
-			}	// End of base register loop
-		} else {	  // Some other unknown header type
-		}
-
-		// find the next device in this slot
-		func = cpqhp_slot_find(func->bus, func->device, index++);
-	}
-
-	return(0);
-}
-
-
-/*
- * cpqhp_configure_board
- *
- * Copies saved configuration information to one slot.
- * this is called recursively for bridge devices.
- * this is for hot plug REPLACE!
- *
- * returns 0 if success
- */
-int cpqhp_configure_board(struct controller *ctrl, struct pci_func * func)
-{
-	int cloop;
-	u8 header_type;
-	u8 secondary_bus;
-	int sub_bus;
-	struct pci_func *next;
-	u32 temp;
-	u32 rc;
-	int index = 0;
-	struct pci_bus *pci_bus = ctrl->pci_bus;
-	unsigned int devfn;
-
-	func = cpqhp_slot_find(func->bus, func->device, index++);
-
-	while (func != NULL) {
-		pci_bus->number = func->bus;
-		devfn = PCI_DEVFN(func->device, func->function);
-
-		// Start at the top of config space so that the control
-		// registers are programmed last
-		for (cloop = 0x3C; cloop > 0; cloop -= 4) {
-			pci_bus_write_config_dword (pci_bus, devfn, cloop, func->config_space[cloop >> 2]);
-		}
-
-		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
-
-		// If this is a bridge device, restore subordinate devices
-		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  // PCI-PCI Bridge
-			pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
-
-			sub_bus = (int) secondary_bus;
-
-			next = cpqhp_slot_list[sub_bus];
-
-			while (next != NULL) {
-				rc = cpqhp_configure_board(ctrl, next);
-
-				if (rc)
-					return rc;
-
-				next = next->next;
-			}
-		} else {
-
-			// Check all the base Address Registers to make sure
-			// they are the same.  If not, the board is different.
-
-			for (cloop = 16; cloop < 40; cloop += 4) {
-				pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp);
+				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
+				pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp_register);
 
-				if (temp != func->config_space[cloop >> 2]) {
-					dbg("Config space compare failure!!! offset = %x\n", cloop);
-					dbg("bus = %x, device = %x, function = %x\n", func->bus, func->device, func->function);
-					dbg("temp = %x, config space = %x\n\n", temp, func->config_space[cloop >> 2]);
-					return 1;
+				if (!disable) {
+					pci_bus_write_config_dword (pci_bus, devfn, cloop, save_base);
 				}
-			}
-		}
-
-		func->configured = 1;
-
-		func = cpqhp_slot_find(func->bus, func->device, index++);
-	}
-
-	return 0;
-}
 
+				if (!temp_register)
+					continue;
 
-/*
- * cpqhp_valid_replace
- *
- * this function checks to see if a board is the same as the
- * one it is replacing.  this check will detect if the device's
- * vendor or device id's are the same
- *
- * returns 0 if the board is the same nonzero otherwise
- */
-int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func)
-{
-	u8 cloop;
-	u8 header_type;
-	u8 secondary_bus;
-	u8 type;
-	u32 temp_register = 0;
-	u32 base;
-	u32 rc;
-	struct pci_func *next;
-	int index = 0;
-	struct pci_bus *pci_bus = ctrl->pci_bus;
-	unsigned int devfn;
-
-	if (!func->is_a_board)
-		return(ADD_NOT_SUPPORTED);
-
-	func = cpqhp_slot_find(func->bus, func->device, index++);
-
-	while (func != NULL) {
-		pci_bus->number = func->bus;
-		devfn = PCI_DEVFN(func->device, func->function);
-
-		pci_bus_read_config_dword (pci_bus, devfn, PCI_VENDOR_ID, &temp_register);
-
-		// No adapter present
-		if (temp_register == 0xFFFFFFFF)
-			return(NO_ADAPTER_PRESENT);
-
-		if (temp_register != func->config_space[0])
-			return(ADAPTER_NOT_SAME);
-
-		// Check for same revision number and class code
-		pci_bus_read_config_dword (pci_bus, devfn, PCI_CLASS_REVISION, &temp_register);
-
-		// Adapter not the same
-		if (temp_register != func->config_space[0x08 >> 2])
-			return(ADAPTER_NOT_SAME);
-
-		// Check for Bridge
-		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
-
-		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  // PCI-PCI Bridge
-			// In order to continue checking, we must program the
-			// bus registers in the bridge to respond to accesses
-			// for it's subordinate bus(es)
-
-			temp_register = func->config_space[0x18 >> 2];
-			pci_bus_write_config_dword (pci_bus, devfn, PCI_PRIMARY_BUS, temp_register);
-
-			secondary_bus = (temp_register >> 8) & 0xFF;
-
-			next = cpqhp_slot_list[secondary_bus];
-
-			while (next != NULL) {
-				rc = cpqhp_valid_replace(ctrl, next);
-
-				if (rc)
-					return(rc);
-
-				next = next->next;
-			}
-
-		}
-		// Check to see if it is a standard config header
-		else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
-			// Check subsystem vendor and ID
-			pci_bus_read_config_dword (pci_bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &temp_register);
-
-			if (temp_register != func->config_space[0x2C >> 2]) {
-				// If it's a SMART-2 and the register isn't filled
-				// in, ignore the difference because
-				// they just have an old rev of the firmware
-
-				if (!((func->config_space[0] == 0xAE100E11)
-				      && (temp_register == 0x00L)))
-					return(ADAPTER_NOT_SAME);
-			}
-			// Figure out IO and memory base lengths
-			for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
-				temp_register = 0xFFFFFFFF;
-				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
-				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
-				if (base) {	  // If this register is implemented
-					if (base & 0x01L) {
-						// IO base
-						// set base = amount of IO space requested
-						base = base & 0xFFFFFFFE;
-						base = (~base) + 1;
+				base = temp_register;
+
+				if ((base & PCI_BASE_ADDRESS_SPACE_IO) && (!disable || (save_command & PCI_COMMAND_IO))) {
+					/* IO base */
+					/* set temp_register = amount of IO space requested */
+					base = base & 0xFFFFFFFCL;
+					base = (~base) + 1;
+
+					io_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL);
+					if (!io_node)
+						return -ENOMEM;
+
+					io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK;
+					io_node->length = (ulong)base;
+					dbg("sur adapter: IO bar=0x%x(length=0x%x)\n", io_node->base, io_node->length);
+
+					io_node->next = func->io_head;
+					func->io_head = io_node;
+				} else {  /* map Memory */
+					int prefetchable = 1;
+					char *res_type_str = "PMEM";
+					u32 temp_register2;
+
+					t_mem_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL);
+					if (!t_mem_node)
+						return -ENOMEM;
+
+					if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
+						prefetchable = 0;
+						mem_node = t_mem_node;
+						res_type_str++;
+					} else
+						p_mem_node = t_mem_node;
 
-						type = 1;
-					} else {
-						// memory base
-						base = base & 0xFFFFFFF0;
-						base = (~base) + 1;
+					base = base & 0xFFFFFFF0L;
+					base = (~base) + 1;
 
-						type = 0;
+					switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
+					case PCI_BASE_ADDRESS_MEM_TYPE_32:
+						if (prefetchable) {
+							p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
+							p_mem_node->length = (ulong)base;
+							dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, p_mem_node->base, p_mem_node->length);
+
+							p_mem_node->next = func->p_mem_head;
+							func->p_mem_head = p_mem_node;
+						} else {
+							mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
+							mem_node->length = (ulong)base;
+							dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, mem_node->base, mem_node->length);
+
+							mem_node->next = func->mem_head;
+							func->mem_head = mem_node;
+						}
+						break;
+					case PCI_BASE_ADDRESS_MEM_TYPE_64:
+						pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
+
+						base64 = temp_register2;
+						base64 = (base64 << 32) | save_base;
+
+						if (temp_register2) {
+							dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n", res_type_str, temp_register2, (u32)base64);
+							base64 &= 0x00000000FFFFFFFFL;
+						}
+
+						if (prefetchable) {
+							p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
+							p_mem_node->length = base;
+							dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", res_type_str, p_mem_node->base, p_mem_node->length);
+
+							p_mem_node->next = func->p_mem_head;
+							func->p_mem_head = p_mem_node;
+						} else {
+							mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
+							mem_node->length = base;
+							dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", res_type_str, mem_node->base, mem_node->length);
+
+							mem_node->next = func->mem_head;
+							func->mem_head = mem_node;
+						}
+						cloop += 4;
+						break;
+					default:
+						dbg("asur: reserved BAR type=0x%x\n", temp_register);
+						break;
 					}
-				} else {
-					base = 0x0L;
-					type = 0;
-				}
-
-				// Check information in slot structure
-				if (func->base_length[(cloop - 0x10) >> 2] != base)
-					return(ADAPTER_NOT_SAME);
-
-				if (func->base_type[(cloop - 0x10) >> 2] != type)
-					return(ADAPTER_NOT_SAME);
-
-			}	// End of base register loop
-
-		}		// End of (type 0 config space) else
-		else {
-			// this is not a type 0 or 1 config space header so
-			// we don't know how to do it
-			return(DEVICE_TYPE_NOT_SUPPORTED);
+				} 
+			}	/* End of base register loop */
+		} else {	/* Some other unknown header type */
+			dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n", func->bus, func->device);
 		}
 
-		// Get the next function
+		/* find the next device in this slot */
+		if (!disable)
+			break;
 		func = cpqhp_slot_find(func->bus, func->device, index++);
 	}
 
-
 	return(0);
 }
 
 
 /*
- * cpqhp_find_available_resources
- *
- * Finds available memory, IO, and IRQ resources for programming
- * devices which may be added to the system
- * this function is for hot plug ADD!
- *
- * returns 0 if success
- */  
-int cpqhp_find_available_resources (struct controller *ctrl, void *rom_start)
-{
-	u8 temp;
-	u8 populated_slot;
-	u8 bridged_slot;
-	void *one_slot;
-	struct pci_func *func = NULL;
-	int i = 10, index;
-	u32 temp_dword, rc;
-	struct pci_resource *mem_node;
-	struct pci_resource *p_mem_node;
-	struct pci_resource *io_node;
-	struct pci_resource *bus_node;
-	void *rom_resource_table;
-
-	rom_resource_table = detect_HRT_floating_pointer(rom_start, rom_start+0xffff);
-	dbg("rom_resource_table = %p\n", rom_resource_table);
-
-	if (rom_resource_table == NULL) {
-		return -ENODEV;
-	}
-	// Sum all resources and setup resource maps
-	unused_IRQ = readl(rom_resource_table + UNUSED_IRQ);
-	dbg("unused_IRQ = %x\n", unused_IRQ);
-
-	temp = 0;
-	while (unused_IRQ) {
-		if (unused_IRQ & 1) {
-			cpqhp_disk_irq = temp;
-			break;
-		}
-		unused_IRQ = unused_IRQ >> 1;
-		temp++;
-	}
-
-	dbg("cpqhp_disk_irq= %d\n", cpqhp_disk_irq);
-	unused_IRQ = unused_IRQ >> 1;
-	temp++;
-
-	while (unused_IRQ) {
-		if (unused_IRQ & 1) {
-			cpqhp_nic_irq = temp;
-			break;
-		}
-		unused_IRQ = unused_IRQ >> 1;
-		temp++;
-	}
-
-	dbg("cpqhp_nic_irq= %d\n", cpqhp_nic_irq);
-	unused_IRQ = readl(rom_resource_table + PCIIRQ);
-
-	temp = 0;
-
-	if (!cpqhp_nic_irq) {
-		cpqhp_nic_irq = ctrl->cfgspc_irq;
-	}
-
-	if (!cpqhp_disk_irq) {
-		cpqhp_disk_irq = ctrl->cfgspc_irq;
-	}
-
-	dbg("cpqhp_disk_irq, cpqhp_nic_irq= %d, %d\n", cpqhp_disk_irq, cpqhp_nic_irq);
-
-	rc = compaq_nvram_load(rom_start, ctrl);
-	if (rc)
-		return rc;
-
-	one_slot = rom_resource_table + sizeof (struct hrt);
-
-	i = readb(rom_resource_table + NUMBER_OF_ENTRIES);
-	dbg("number_of_entries = %d\n", i);
-
-	if (!readb(one_slot + SECONDARY_BUS)) {
-		return(1);
-	}
-
-	dbg("dev|IO base|length|Mem base|length|Pre base|length|PB SB MB\n");
-
-	while (i && readb(one_slot + SECONDARY_BUS)) {
-		u8 dev_func = readb(one_slot + DEV_FUNC);
-		u8 primary_bus = readb(one_slot + PRIMARY_BUS);
-		u8 secondary_bus = readb(one_slot + SECONDARY_BUS);
-		u8 max_bus = readb(one_slot + MAX_BUS);
-		u16 io_base = readw(one_slot + IO_BASE);
-		u16 io_length = readw(one_slot + IO_LENGTH);
-		u16 mem_base = readw(one_slot + MEM_BASE);
-		u16 mem_length = readw(one_slot + MEM_LENGTH);
-		u16 pre_mem_base = readw(one_slot + PRE_MEM_BASE);
-		u16 pre_mem_length = readw(one_slot + PRE_MEM_LENGTH);
-
-		dbg("%2.2x | %4.4x  | %4.4x | %4.4x   | %4.4x | %4.4x   | %4.4x |%2.2x %2.2x %2.2x\n",
-		    dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length,
-		    primary_bus, secondary_bus, max_bus);
-
-		// If this entry isn't for our controller's bus, ignore it
-		if (primary_bus != ctrl->bus) {
-			i--;
-			one_slot += sizeof (struct slot_rt);
-			continue;
-		}
-		// find out if this entry is for an occupied slot
-		ctrl->pci_bus->number = primary_bus;
-		pci_bus_read_config_dword (ctrl->pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword);
-		dbg("temp_D_word = %x\n", temp_dword);
-
-		if (temp_dword != 0xFFFFFFFF) {
-			index = 0;
-			func = cpqhp_slot_find(primary_bus, dev_func >> 3, 0);
-
-			while (func && (func->function != (dev_func & 0x07))) {
-				dbg("func = %p (bus, dev, fun) = (%d, %d, %d)\n", func, primary_bus, dev_func >> 3, index);
-				func = cpqhp_slot_find(primary_bus, dev_func >> 3, index++);
-			}
-
-			// If we can't find a match, skip this table entry
-			if (!func) {
-				i--;
-				one_slot += sizeof (struct slot_rt);
-				continue;
-			}
-			// this may not work and shouldn't be used
-			if (secondary_bus != primary_bus)
-				bridged_slot = 1;
-			else
-				bridged_slot = 0;
-
-			populated_slot = 1;
-		} else {
-			populated_slot = 0;
-			bridged_slot = 0;
-		}
-
-
-		// If we've got a valid IO base, use it
-
-		temp_dword = io_base + io_length;
-
-		if ((io_base) && (temp_dword < 0x10000)) {
-			io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-			if (!io_node)
-				return -ENOMEM;
-
-			io_node->base = io_base;
-			io_node->length = io_length;
-
-			dbg("found io_node(base, length) = %x, %x\n", io_node->base, io_node->length);
-			dbg("populated slot =%d \n", populated_slot);
-			if (!populated_slot) {
-				io_node->next = ctrl->io_head;
-				ctrl->io_head = io_node;
-			} else {
-				io_node->next = func->io_head;
-				func->io_head = io_node;
-			}
-		}
-
-		// If we've got a valid memory base, use it
-		temp_dword = mem_base + mem_length;
-		if ((mem_base) && (temp_dword < 0x10000)) {
-			mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-			if (!mem_node)
-				return -ENOMEM;
-
-			mem_node->base = mem_base << 16;
-
-			mem_node->length = mem_length << 16;
-
-			dbg("found mem_node(base, length) = %x, %x\n", mem_node->base, mem_node->length);
-			dbg("populated slot =%d \n", populated_slot);
-			if (!populated_slot) {
-				mem_node->next = ctrl->mem_head;
-				ctrl->mem_head = mem_node;
-			} else {
-				mem_node->next = func->mem_head;
-				func->mem_head = mem_node;
-			}
-		}
-
-		// If we've got a valid prefetchable memory base, and
-		// the base + length isn't greater than 0xFFFF
-		temp_dword = pre_mem_base + pre_mem_length;
-		if ((pre_mem_base) && (temp_dword < 0x10000)) {
-			p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-			if (!p_mem_node)
-				return -ENOMEM;
-
-			p_mem_node->base = pre_mem_base << 16;
-
-			p_mem_node->length = pre_mem_length << 16;
-			dbg("found p_mem_node(base, length) = %x, %x\n", p_mem_node->base, p_mem_node->length);
-			dbg("populated slot =%d \n", populated_slot);
-
-			if (!populated_slot) {
-				p_mem_node->next = ctrl->p_mem_head;
-				ctrl->p_mem_head = p_mem_node;
-			} else {
-				p_mem_node->next = func->p_mem_head;
-				func->p_mem_head = p_mem_node;
-			}
-		}
-
-		// If we've got a valid bus number, use it
-		// The second condition is to ignore bus numbers on
-		// populated slots that don't have PCI-PCI bridges
-		if (secondary_bus && (secondary_bus != primary_bus)) {
-			bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-			if (!bus_node)
-				return -ENOMEM;
-
-			bus_node->base = secondary_bus;
-			bus_node->length = max_bus - secondary_bus + 1;
-			dbg("found bus_node(base, length) = %x, %x\n", bus_node->base, bus_node->length);
-			dbg("populated slot =%d \n", populated_slot);
-			if (!populated_slot) {
-				bus_node->next = ctrl->bus_head;
-				ctrl->bus_head = bus_node;
-			} else {
-				bus_node->next = func->bus_head;
-				func->bus_head = bus_node;
-			}
-		}
-
-		i--;
-		one_slot += sizeof (struct slot_rt);
-	}
-
-	// If all of the following fail, we don't have any resources for
-	// hot plug add
-	rc = 1;
-	rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
-	rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
-	rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head));
-	rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
-
-	return(rc);
-}
-
-
-/*
  * cpqhp_return_board_resources
  *
  * this routine returns all resources allocated to a board to
diff -Nru a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
--- a/drivers/pci/hotplug/Kconfig	2003-07-02 13:46:17.000000000 -0700
+++ b/drivers/pci/hotplug/Kconfig	2003-07-07 09:32:25.000000000 -0700
@@ -47,11 +47,11 @@
 	  When in doubt, say N.
 
 config HOTPLUG_PCI_COMPAQ
-	tristate "Compaq PCI Hotplug driver"
-	depends on HOTPLUG_PCI && X86
+	tristate "Compaq/Intel PCI Hotplug driver"
+	depends on HOTPLUG_PCI
 	help
 	  Say Y here if you have a motherboard with a Compaq PCI Hotplug
-	  controller.
+	  controller or equivalent Intel controller.
 
 	  This code is also available as a module ( = code which can be
 	  inserted in and removed from the running kernel whenever you want).
@@ -60,9 +60,19 @@
 
 	  When in doubt, say N.
 
+config HOTPLUG_PCI_COMPAQ_PHPRM_LEGACY
+	bool "Non-ACPI: Use Hotplug Resource Table ($HRT) for resource information"
+	depends on HOTPLUG_PCI_COMPAQ
+	help
+	  Say Y here if Hotplug resource/configuration information is provided
+	  by platform BIOS $HRT, not by ACPI.
+	  Some ACPI compliant platforms may use this too if $HRT is provided.
+
+	  When in doubt, say N.
+
 config HOTPLUG_PCI_COMPAQ_NVRAM
 	bool "Save configuration into NVRAM on Compaq servers"
-	depends on HOTPLUG_PCI_COMPAQ
+	depends on HOTPLUG_PCI_COMPAQ_PHPRM_LEGACY
 	help
 	  Say Y here if you have a Compaq server that has a PCI Hotplug
 	  controller.  This will allow the PCI Hotplug driver to store the PCI
diff -Nru a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
--- a/drivers/pci/hotplug/Makefile	2003-07-02 13:51:13.000000000 -0700
+++ b/drivers/pci/hotplug/Makefile	2003-07-07 09:32:25.000000000 -0700
@@ -3,7 +3,7 @@
 #
 
 obj-$(CONFIG_HOTPLUG_PCI)		+= pci_hotplug.o
-obj-$(CONFIG_HOTPLUG_PCI_FAKE)		+= fakephp.o 
+obj-$(CONFIG_HOTPLUG_PCI_FAKE)		+= fakephp.o
 obj-$(CONFIG_HOTPLUG_PCI_COMPAQ)	+= cpqphp.o
 obj-$(CONFIG_HOTPLUG_PCI_IBM)		+= ibmphp.o
 obj-$(CONFIG_HOTPLUG_PCI_ACPI)		+= acpiphp.o
@@ -20,7 +20,8 @@
 cpqphp-objs		:=	cpqphp_core.o	\
 				cpqphp_ctrl.o	\
 				cpqphp_sysfs.o	\
-				cpqphp_pci.o
+				cpqphp_pci.o	\
+				cpqphp_hpc.o
 
 ibmphp-objs		:=	ibmphp_core.o	\
 				ibmphp_ebda.o	\
@@ -40,6 +41,13 @@
   endif
 endif
 
+ifeq ($(CONFIG_HOTPLUG_PCI_COMPAQ_PHPRM_LEGACY),y)
+    cpqphp-objs += phprm_legacy.o
+else
+    cpqphp-objs += phprm_acpi.o
+    EXTRA_CFLAGS += -D_LINUX -I$(TOPDIR)/drivers/acpi -I$(TOPDIR)/drivers/acpi/include -DPHP_ACPI
+endif
+
 ifeq ($(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM),y)
 	cpqphp-objs += cpqphp_nvram.o
 endif


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-07-12 16:02 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-12 16:13 [Patch] 3/4 PCI Hot-plug driver patch for 2.5.74 kernel Dely Sy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).