--- a/drivers/pci/hotplug/Kconfig	Wed Mar 17 11:19:34 2004
+++ b/drivers/pci/hotplug/Kconfig	Wed Mar 17 11:19:34 2004
@@ -88,6 +88,10 @@
 
 	  When in doubt, say N.
 
+config HOTPLUG_PCI_AMD
+	tristate "AMD Standard Hot Plug Controller (SHPC) driver"
+	depends on HOTPLUG_PCI
+
 config HOTPLUG_PCI_CPCI
 	bool "CompactPCI Hotplug driver"
 	depends on HOTPLUG_PCI
--- a/drivers/pci/hotplug/Makefile	Wed Mar 17 11:19:34 2004
+++ b/drivers/pci/hotplug/Makefile	Wed Mar 17 11:19:34 2004
@@ -70,3 +72,13 @@
 		shpchp-objs += shpchprm_nonacpi.o
 	endif
 endif
+
+obj-$(CONFIG_HOTPLUG_PCI_AMD)		+= amdshpc.o
+amdshpc-objs		:=	amdshpc_core.o  \
+				amdshpc_ctrl.o  \
+				amdshpc_pci.o   \
+				amdshpc_ddi.o   \
+				amdshpc_int.o   \
+				amdshpc_led.o   \
+				amdshpc_enb.o   \
+				amdshpc_dsb.o
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/amdshpc.h	Wed Mar 17 11:19:43 2004
@@ -0,0 +1,1265 @@
+/*
+ * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001,2003 IBM Corp.
+ * Copyright (C) 2002-2003 Advanced Micro Devices
+ *
+ * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS
+ * AND CONDITIONS OF THE GNU GENERAL PUBLIC
+ * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS
+ * INCLUDED WITH THIS FILE AND POSTED AT
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Send feedback to <greg@kroah.com> <david.keck@amd.com>
+ *
+ */
+
+#ifndef _SHPC_H_
+#define _SHPC_H_
+
+
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <asm/semaphore.h>
+#include "pci_hotplug.h"
+
+//
+// Timeouts
+//
+#define ONE_TENTH_SEC_TIMEOUT   	10		// 0.1 sec
+#define ONE_SEC_TIMEOUT                 HZ * 1          // 1 sec
+#define FIVE_SEC_TIMEOUT                HZ * 5          // 5 secs
+#define TEN_SEC_TIMEOUT                 HZ * 10         // 10 secs
+#define FIFTEEN_SEC_TIMEOUT             HZ * 15         // 15 secs
+#define QUIESCE_QUIET_TIMEOUT           HZ * 30         // 30 secs
+#define QUIESCE_TIMEOUT                 HZ * 60         // 60 secs
+#define ONE_SEC_INCREMENT               HZ * 1          // 1 sec
+
+#define SLOT_MAGIC      0x67267322
+struct slot {
+	u32 magic;
+	struct slot *next;
+	struct list_head slot_list;
+	u8 bus;
+	u8 device;
+	u8 number;
+	u8 is_a_board;
+	u8 configured;
+	u8 state;
+	u8 switch_save;
+	u8 presence_save;
+	u32 capabilities;
+	u16 reserved2;
+	struct timer_list task_event;
+	u8 hp_slot;
+	struct controller *ctrl;
+	void *p_sm_slot;
+	struct hotplug_slot *hotplug_slot;
+	void* private;
+};
+
+struct controller {
+	struct controller *next;
+	void *shpc_context;
+	u32 ctrl_int_comp;
+	void *hpc_reg;		/* cookie for our pci controller location */
+	struct pci_resource *mem_head;
+	struct pci_resource *p_mem_head;
+	struct pci_resource *io_head;
+	struct pci_resource *bus_head;
+	struct pci_dev *pci_dev;
+	struct pci_bus *pci_bus;
+	struct slot *slot;
+	u8 interrupt;
+	u8 bus;
+	u8 device;
+	u8 function;
+	u8 slot_device_offset;
+	u8 first_slot;
+	u8 add_support;
+	u16 vendor_id;
+};
+
+
+static LIST_HEAD(slot_list);
+
+#if !defined(CONFIG_HOTPLUG_PCI_AMD_MODULE)
+	#define MY_NAME "amd_shpc.o"
+#else
+	#define MY_NAME THIS_MODULE->name
+#endif
+
+//
+// Debug Facilities
+//
+#define debug 0
+#define dbg(format, arg...)                                     \
+	do {                                                    \
+		if (debug)                                      \
+		    printk (KERN_DEBUG "%s: " format "\n",      \
+		    MY_NAME , ## arg);          \
+	} while (0)
+
+#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
+
+#define msg_initialization_err  "Initialization failure, error=%d\n"
+#define msg_HPC_rev_error       "Unsupported revision of the PCI hot plug controller found.\n"
+#define msg_HPC_non_amd         "Non-AMD PCI hot plug controller is not supported by this driver.\n"
+#define msg_HPC_not_amd_hp	"Device is not a hot plug controller.\n"
+#define msg_HPC_not_supported   "This system is not supported by this version of amdshpc. Upgrade to a newer version of amdshpc\n"
+#define msg_unable_to_save      "Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n"
+
+struct hrt {
+	char sig0;
+	char sig1;
+	char sig2;
+	char sig3;
+	u16 unused_IRQ;
+	u16 PCIIRQ;
+	u8 number_of_entries;
+	u8 revision;
+	u16 reserved1;
+	u32 reserved2;
+} __attribute__ ((packed));
+
+/* offsets to the hotplug resource table registers based on the above structure layout */
+enum hrt_offsets {
+	SIG0 =			offsetof(struct hrt, sig0),
+	SIG1 =                  offsetof(struct hrt, sig1),
+	SIG2 =                  offsetof(struct hrt, sig2),
+	SIG3 =                  offsetof(struct hrt, sig3),
+	UNUSED_IRQ =            offsetof(struct hrt, unused_IRQ),
+	PCIIRQ =                offsetof(struct hrt, PCIIRQ),
+	NUMBER_OF_ENTRIES = 	offsetof(struct hrt, number_of_entries),
+	REVISION =              offsetof(struct hrt, revision),
+	HRT_RESERVED1 =         offsetof(struct hrt, reserved1),
+	HRT_RESERVED2 =         offsetof(struct hrt, reserved2),
+};
+
+struct slot_rt {
+	u8 dev_func;
+	u8 primary_bus;
+	u8 secondary_bus;
+	u8 max_bus;
+	u16 io_base;
+	u16 io_length;
+	u16 mem_base;
+	u16 mem_length;
+	u16 pre_mem_base;
+	u16 pre_mem_length;
+} __attribute__ ((packed));
+
+/* offsets to the hotplug slot resource table registers based on the above structure layout */
+enum slot_rt_offsets {
+	DEV_FUNC =	offsetof(struct slot_rt, dev_func),
+	PRIMARY_BUS =   offsetof(struct slot_rt, primary_bus),
+	SECONDARY_BUS = offsetof(struct slot_rt, secondary_bus),
+	MAX_BUS =       offsetof(struct slot_rt, max_bus),
+	IO_BASE =       offsetof(struct slot_rt, io_base),
+	IO_LENGTH =     offsetof(struct slot_rt, io_length),
+	MEM_BASE =      offsetof(struct slot_rt, mem_base),
+	MEM_LENGTH =    offsetof(struct slot_rt, mem_length),
+	PRE_MEM_BASE =	offsetof(struct slot_rt, pre_mem_base),
+	PRE_MEM_LENGTH = offsetof(struct slot_rt, pre_mem_length),
+};
+
+struct pci_func {
+	struct pci_func *next;
+	u8 bus;
+	u8 device;
+	u8 function;
+	u8 is_a_board;
+	u16 status;
+	u8 configured;
+	u8 switch_save;
+	u8 presence_save;
+	u32 base_length[0x06];
+	u8 base_type[0x06];
+	u16 reserved2;
+	u32 config_space[0x20];
+	struct pci_resource *mem_head;
+	struct pci_resource *p_mem_head;
+	struct pci_resource *io_head;
+	struct pci_resource *bus_head;
+	struct timer_list *p_task_event;
+	struct pci_dev* pci_dev;
+};
+
+
+#ifndef FALSE
+	#define FALSE 0
+	#define TRUE 1
+#endif
+
+#define IN
+#define OUT
+
+enum mutex_action {
+	ACQUIRE,
+	RELEASE,
+};
+
+enum hp_boolean {
+	HP_FALSE = 0,
+	HP_TRUE = 1,
+};
+
+// card power requirements
+enum hp_power_requirements {
+	POWER_LOW,		// low power requirements
+	POWER_MEDIUM,		// medium power requirements
+	POWER_HIGH,		// high power requirements
+};
+
+//
+// slot event masks
+//
+#define ATTN_BUTTON_EVENT               0x00000001
+#define ALERT_EVENT     		0x00000002
+#define BUS_REBALANCE_EVENT             0x00000004
+#define QUIESCE_EVENT                   0x00000008
+#define ATTN_LED_PROBLEM_EVENT          0x00000010
+#define ATTN_LED_REQUEST_EVENT          0x00000020
+#define SLOT_REQUEST_EVENT              0x00000040
+#define SLOT_TIMER1_EVENT               0x00000080
+#define SLOT_TIMER2_EVENT               0x00000100
+#define SLOT_TIMER3_EVENT               0x00000200
+#define SLOT_TIMER4_EVENT               0x00000400
+#define SLOT_TIMER5_EVENT               0x00000800
+#define SLOT_TIMER6_EVENT               0x00001000
+#define SLOT_TIMER7_EVENT               0x00002000
+#define SLOT_TIMER8_EVENT               0x00004000
+#define SLOT_TIMER9_EVENT               0x00008000
+#define SLOT_TIMER10_EVENT              0x00010000
+#define LED_TIMER1_EVENT                0x00020000
+#define LED_TIMER2_EVENT                0x00040000
+#define LED_TIMER3_EVENT                0x00080000
+#define LED_TIMER4_EVENT                0x00100000
+#define CMD_ACQUIRE_EVENT               0x00200000
+#define CMD_RELEASE_EVENT               0x00400000
+#define LED_CMD_ACQUIRE_EVENT           0x00800000
+#define LED_CMD_RELEASE_EVENT           0x01000000
+#define BUS_RELEASE_EVENT               0x02000000
+#define BUS_ACQUIRE_EVENT               0x04000000
+
+//
+// controller event masks
+//
+#define BUS_COMPLETE_EVENT              0x00000001
+#define SUSPEND_EVENT                   0x00000002
+#define RESUME_EVENT                    0x00000004
+#define REMOVE_EVENT                    0x00000008
+#define EXIT_REQUEST_EVENT              0x00000010
+#define CTRL_TIMER_EVENT                0x00000020
+#define CMD_COMPLETION_EVENT            0x00000040
+#define CMD_AVAILABLE_MUTEX_EVENT       0x00000080
+#define BUS_AVAILABLE_MUTEX_EVENT       0x00000100
+#define LED_CMD_AVAILABLE_MUTEX_EVENT   0x00000200
+
+
+#define PCI_TO_PCI_BRIDGE_CLASS         0x00060400
+#define SLOT_MASK                       0x28
+
+
+#define ADD_NOT_SUPPORTED               0x00000003
+#define ADAPTER_NOT_SAME                0x00000006
+#define NO_ADAPTER_PRESENT              0x00000009
+
+#define REMOVE_NOT_SUPPORTED            0x00000003
+
+
+
+// slot states
+enum hp_states {
+	SLOT_DISABLE,		// slot disable
+	SLOT_ENABLE,		// slot enable
+};
+
+// indicator values
+enum mode_frequency {
+	MODE_PCI_33,		// PCI 33Mhz
+	MODE_PCI_66,		// PCI 66Mhz
+	MODE_PCIX_66,		// PCI-X 66Mhz
+	MODE_PCIX_100,		// PCI-X 100Mhz
+	MODE_PCIX_133,		// PCI-X 133Mhz
+};
+
+enum hp_indicators {
+	INDICATOR_OFF,		// Indicator off state
+	INDICATOR_ON,		// Indicator on state
+	INDICATOR_BLINK,	// Indicator blink state
+	INDICATOR_NORMAL,	// Indicator normal state
+};
+
+struct pci_resource {
+	struct pci_resource * next;
+	u32 base;
+	u32 length;
+};
+
+struct resource_descriptor {
+	u32 base;
+	u32 limit;
+};
+
+struct irq_mapping {
+	u8 barber_pole;
+	u8 valid_INT;
+	u8 interrupt[4];
+};
+
+struct resource_lists {
+	struct pci_resource *mem_head;
+	struct pci_resource *p_mem_head;
+	struct pci_resource *io_head;
+	struct pci_resource *bus_head;
+	struct irq_mapping *irqs;
+};
+
+#define ROM_PHY_ADDR                    0x0F0000
+#define ROM_PHY_LEN                     0x00ffff
+
+#define NOT_ENOUGH_RESOURCES            0x0000000B
+#define DEVICE_TYPE_NOT_SUPPORTED       0x0000000C
+
+//
+// Prototypes
+//
+extern int  amdshpc_resource_sort_and_combine (struct pci_resource **head);
+
+//
+// State-Machine Function
+//
+typedef long ( *SLOT_STATE_FUNCTION )(
+				     void* shpc_context,
+				     void* slot_context);
+
+//
+// SHPC Constants
+//
+#define SHPC_MAX_NUM_SLOTS      4
+
+
+#define arraysize(p) (sizeof(p)/sizeof((p)[0]))
+
+
+//
+// SHPC Register Offsets
+//
+enum shpc_register_offset {
+	SHPC_SLOTS_AVAILABLE1_REG_OFFSET        = 0x04,
+	SHPC_SLOTS_AVAILABLE2_REG_OFFSET        = 0x08,
+	SHPC_SLOT_CONFIG_REG_OFFSET             = 0x0C,
+	SHPC_SEC_BUS_CONFIG_REG_OFFSET          = 0x10,
+	SHPC_COMMAND_REG_OFFSET                 = 0x14,
+	SHPC_STATUS_REG_OFFSET                  = 0x16,
+	SHPC_INT_LOCATOR_REG_OFFSET             = 0x18,
+	SHPC_SERR_LOCATOR_REG_OFFSET            = 0x1C,
+	SHPC_SERR_INT_REG_OFFSET                = 0x20,
+	SHPC_LOGICAL_SLOT_REG_OFFSET            = 0x24,
+};
+
+
+//
+// SHPC Slots Available Register I
+//
+union SHPC_SLOTS_AVAILABLE1_DWREG {
+	struct {
+		u32 N_33CONV    :5;	// 4:0
+		u32 reserved1   :3;	// 7:5
+		u32 N_66PCIX    :5;	// 12:8
+		u32 reserved2   :3;	// 15:13
+		u32 N_100PCIX   :5;	// 20:16
+		u32 reserved3   :3;	// 23:21
+		u32 N_133PCIX   :5;	// 28:24
+		u32 reserved4   :3;	// 31:29
+	}x;
+	u32 AsDWord;
+};
+
+
+//
+// SHPC Slots Available Register II
+//
+union SHPC_SLOTS_AVAILABLE2_DWREG {
+	struct {
+		u32 N_66CONV    :5;	// 4:0
+		u32 reserved4   :27;	// 31:5
+	}x;
+	u32 AsDWord;
+};
+
+
+//
+// SHPC Slot Configuration Register
+//
+union SHPC_SLOT_CONFIG_DWREG {
+	struct {
+		u32 NSI         :5;	// 4:0
+		u32 reserved1   :3;	// 7:5
+		u32 FDN         :5;	// 12:8
+		u32 reserved2   :3;	// 15:13
+		u32 PSN         :11;	// 26:16
+		u32 reserved3   :2;	// 28:27
+		u32 PSN_UP      :1;	// 29
+		u32 MRLSI       :1;	// 30
+		u32 ABI         :1;	// 31
+	}x;
+	u32 AsDWord;
+};
+
+
+//
+// SHPC Secondary Bus Configuration Register
+//
+union SHPC_SEC_BUS_CONFIG_DWREG {
+	struct {
+		u32 MODE        :3;	// 2:0
+		u32 reserved    :21;	// 23:3
+		u32 format      :8;	// 31:24
+	}x;
+	u32 AsDWord;
+};
+
+
+//
+// SHPC Command Register
+//
+union SHPC_COMMAND_WREG {
+	struct {
+		u16 state               : 2;	// 1:0
+		u16 power_led           : 2;	// 3:2
+		u16 attention_led       : 2;	// 5:4
+		u16 code                : 2;	// 7:6
+		u16 TGT                 : 5;	// 12:8
+		u16 reserved            : 3;	// 15:13
+	} Slot;
+	struct {
+		u16 speed_mode          : 3;	// 2:0
+		u16 code                : 5;	// 7:3
+		u16 reserved            : 8;	// 15:8
+	} Bus;
+	struct {
+		u16 code                : 8;	// 7:0
+		u16 reserved            : 8;	// 15:8
+	}x;
+	u16 AsWord;
+};
+
+
+//
+// SHPC Status Register
+//
+union SHPC_STATUS_WREG {
+	struct {
+		u16 BSY         :1;	// 0
+		u16 MRLO_ERR    :1;	// 1
+		u16 INVCMD_ERR  :1;	// 2
+		u16 INVSM_ERR   :1;	// 3
+		u16 reserved    :12;	// 15:4
+	}x;
+	u16 AsWord;
+};
+
+
+//
+// SHPC Interrupt Locator Register
+//
+union SHPC_INT_LOCATOR_DWREG {
+	struct {
+		u32 CC_IP       :1;	// 0
+		u32 SLOT_IP     :4;	// 4:1
+		u32 reserved    :27;	// 31:5
+	}x;
+	u32 AsDWord;
+};
+
+
+//
+// SHPC SERR Locator Register
+//
+union SHPC_SERR_LOCATOR_DWREG {
+	struct {
+		u32 A_SERRP     :1;	// 0
+		u32 SLOT_SERRP  :4;	// 4:1
+		u32 reserved    :27;	// 31:5
+	}x;
+	u32 AsDWord;
+};
+
+
+//
+// SHPC SERR-INT Register
+//
+union SHPC_SERR_INT_DWREG {
+	struct {
+		u32 GIM         :1;	// 0
+		u32 GSERRM      :1;	// 1
+		u32 CC_IM       :1;	// 2
+		u32 A_SERRM     :1;	// 3
+		u32 reserved1   :12;	// 15:4
+		u32 CC_STS      :1;	// 16
+		u32 ATOUT_STS   :1;	// 17
+		u32 reserved2   :14;	// 31:18
+	}x;
+	u32 AsDWord;
+};
+
+
+//
+// SHPC Logical Slot Register
+//
+union SHPC_LOGICAL_SLOT_DWREG {
+	struct {
+		u32 S_STATE     :2;	// 1:0
+		u32 PIS         :2;	// 3:2
+		u32 AIS         :2;	// 5:4
+		u32 PF          :1;	// 6
+		u32 AB          :1;	// 7
+		u32 MRLS        :1;	// 8
+		u32 M66_CAP     :1;	// 9
+		u32 PRSNT1_2    :2;	// 11:10
+		u32 PCIX_CAP    :2;	// 13:12
+		u32 reserved1   :2;	// 15:14
+		u32 CPC_STS     :1;	// 16
+		u32 IPF_STS     :1;	// 17
+		u32 ABP_STS     :1;	// 18
+		u32 MRLSC_STS   :1;	// 19
+		u32 CPF_STS     :1;	// 20
+		u32 reserved2   :3;	// 23:21
+		u32 CP_IM       :1;	// 24
+		u32 IPF_IM      :1;	// 25
+		u32 AB_IM       :1;	// 26
+		u32 MRLS_IM     :1;	// 27
+		u32 CPF_IM      :1;	// 28
+		u32 MRLS_SERRM  :1;	// 29
+		u32 CPF_SERRM   :1;	// 30
+		u32 reserved3   :1;	// 31
+	}x;
+	u32 AsDWord;
+};
+
+
+//
+// Bus Speed/Mode
+//
+enum shpc_speed_mode {
+	SHPC_BUS_CONV_33        = 0,
+	SHPC_BUS_CONV_66        = 1,
+	SHPC_BUS_PCIX_66        = 2,
+	SHPC_BUS_PCIX_100       = 3,
+	SHPC_BUS_PCIX_133       = 4,
+};
+
+
+//
+// Slot PCIX Capability
+//
+enum shpc_slot_pcix_cap {
+	SHPC_SLOT_CONV          = 0,
+	SHPC_SLOT_PCIX_66       = 1,
+	SHPC_SLOT_PCIX_133      = 3,
+};
+
+
+//
+// Slot LEDs
+//
+enum shpc_slot_led {
+	SHPC_led_NO_CHANGE      = 0,
+	SHPC_LED_ON             = 1,
+	SHPC_LED_BLINK          = 2,
+	SHPC_LED_OFF            = 3,
+};
+
+
+//
+// Slot State
+//
+enum shpc_slot_state {
+	SHPC_SLOT_NO_CHANGE     = 0,
+	SHPC_POWER_ONLY         = 1,
+	SHPC_ENABLE_SLOT        = 2,
+	SHPC_DISABLE_SLOT       = 3,
+};
+
+
+//
+// Command Code
+//
+#define SHPC_SLOT_OPERATION             0x00    // 7:6  (00xxxxxxb)
+#define SHPC_SET_BUS_SPEED_MODE         0x08    // 7:3  (01000xxxb)
+#define SHPC_POWER_ONLY_ALL_SLOTS       0x48    // 7:0  (01001000b)
+#define SHPC_ENABLE_ALL_SLOTS           0x49    // 7:0  (01001001b)
+
+
+//
+// SHPC Status
+//
+enum shpc_status {
+	SHPC_STATUS_CLEARED     = 0,
+	SHPC_STATUS_SET         = 1,
+};
+
+
+//
+// SHPC Mask
+//
+enum shpc_mask {
+	SHPC_UNMASKED   = 0,
+	SHPC_MASKED     = 1,
+};
+
+
+//
+// Slot MRL Sensor
+//
+enum shpc_slot_mrl {
+	SHPC_MRL_CLOSED = 0,
+	SHPC_MRL_OPEN   = 1,
+};
+
+
+//
+// Slot Attn Button
+//
+enum shpc_slot_attn_button {
+	SHPC_ATTN_BUTTON_RELEASED  = 0,
+	SHPC_ATTN_BUTTON_PRESSED   = 1,
+};
+
+
+//
+// Card Power Requirements
+//
+enum shpc_card_power {
+	SHPC_CARD_PRESENT_7_5W  = 0,
+	SHPC_CARD_PRESENT_15W   = 1,
+	SHPC_CARD_PRESENT_25W   = 2,
+	SHPC_SLOT_EMPTY         = 3,
+};
+
+
+// slot config structure
+union SLOT_CONFIG_INFO {
+	struct {
+		u32             lu_slots_implemented    : 5;	// [ 4:0 ]Number of slots implemented
+		u32             lu_reserved1            : 3;	// [ 7:5 ]Reserved
+		u32             lu_base_FDN             : 5;	// [ 12:8 ]First Device Number
+		u32             lu_reserved2            : 3;	// [ 15:13 ]Reserved
+		u32             lu_base_PSN             : 11;	// [ 26:16 ]Physical Slot Number
+		u32             lu_reserved3            : 2;	// [ 28:27 ]Reserved
+		u32             lu_PSN_up               : 1;	// [ 29 ]PSN Up (1=TRUE, 0=FALSE)
+		u32             lu_reserved4            : 2;	// [ 31:30 ]Reserved
+	}x;
+	u32     AsDWord;
+};
+
+
+// logical slot information
+union SLOT_STATUS_INFO {
+	struct {
+		u32     lu_slot_state           : 1;	// [ 0 ]Slot state (1=Enabled, 0=Disabled)
+		u32     lu_power_fault          : 1;	// [ 1 ]Power-Fault? (1=TRUE, 0=FALSE)
+		u32     lu_card_present         : 1;	// [ 2 ]Card Present? (1=TRUE, 0=FALSE)
+		u32     lu_card_power           : 2;	// [ 4:3 ]Card Power Requirements (low/medium/high)
+		u32     lu_card_mode_freq_cap   : 3;	// [ 7:5 ]Card Speed/mode capability
+		u32     lu_mrl_implemented      : 1;	// [ 8 ]MRL Implemented? (1=TRUE, 0=FALSE)
+		u32     lu_mrl_opened           : 1;	// [ 9 ]MRL State (if implemented: 1=TRUE, 0=FALSE)
+		u32     lu_ai_state             : 2;	// [ 11:10 ]Attn Indicator State (Blink/On/Off)
+		u32     lu_pi_state             : 2;	// [ 13:12 ]Power Indicator State (Blink/On/Off)
+		u32     lu_reserved1            : 2;	// [ 14 ]Reserved
+		u32	lu_card_pci66_capable   : 1;	// [ 15 ]Card PCI66 capability (1=TRUE, 0=FALSE)
+		u32     lu_bus_mode_freq        : 3;	// [ 18:16 ]Current Bus speed/mode
+		u32     lu_max_bus_mode_freq    : 3;	// [ 21:19 ]Maximum Bus speed/mode
+		u32     lu_reserved2            : 9;	// [ 30:22 ]Reserved
+		u32     lu_request_failed       : 1;	// [ 31 ]Request Failed? (1=TRUE, 0=FALSE)
+	}x;
+	u32     AsDWord;
+};
+
+enum return_status {
+	STATUS_UNSUCCESSFUL,
+	STATUS_SUCCESS
+};
+
+//
+// Async Request
+//
+enum shpc_async_request {
+	SHPC_ASYNC_ENABLE_SLOT,
+	SHPC_ASYNC_DISABLE_SLOT,
+	SHPC_ASYNC_SURPRISE_REMOVE,
+	SHPC_ASYNC_QUIESCE_DEVNODE,
+	SHPC_ASYNC_QUIESCE_DEVNODE_QUIET,
+	SHPC_ASYNC_QUIESCE_DEVNODE_NOTIFY,
+	SHPC_ASYNC_CANCEL_QUIESCE_DEVNODE,
+	SHPC_ASYNC_LED_LOCATE,
+	SHPC_ASYNC_LED_NORMAL
+};
+
+
+//
+// Async Request
+//
+struct async_request {
+	enum shpc_async_request type;
+	wait_queue_head_t       event;
+	unsigned long           timeout;
+	void                    *request_context;
+};
+
+
+//
+// Async Completion
+//
+struct async_completion {
+	enum shpc_async_request type;
+	unsigned long                   timeout;
+	u8                              hw_initiated;
+	u8                              done;
+	enum hp_boolean                 failed;
+	void                            *request_context;
+};
+
+// ****************************************************************************
+//
+// async_callback() @ PASSIVE_LEVEL
+//
+// Parameters
+//      driver_context - Pointer provided in hp_AddDevice()
+//      slot_id - Zero-based slot number (0..n-1).
+//      Request - Async request completed.  For example: Slot Enable/Disable, AttnLED Attn/Normal.
+//      Status - Slot status at completion
+//      request_context - Pointer provided in hp_StartAsyncRequest(), NULL for
+//              completions on hardware-initiated requests.
+//
+// Return Value
+//      For QUIESCE_DEVNODE request: #DevNodes associated with a particular slot, else 0.
+//
+// ****************************************************************************
+typedef unsigned long ( *SHPC_ASYNC_CALLBACK )( void* driver_context,
+						u8 slot_id,
+						enum shpc_async_request Request,
+						union SLOT_STATUS_INFO Status,
+						void* request_context );
+
+//
+// Slot Context
+//
+struct slot_context {
+
+	spinlock_t		slot_spinlock;
+	struct semaphore        slot_event_bits_semaphore;
+	struct semaphore        cmd_acquire_mutex;
+	struct semaphore        bus_acquire_mutex;
+	u32                     *logical_slot_addr;
+	u8                      slot_number;
+	u8                      slot_psn;
+	u32                     quiesce_requests;
+	u32                     quiesce_replies;
+	u8                      slot_enabled;
+	enum shpc_speed_mode    card_speed_mode;
+	u8                      card_pci66_capable;
+	u8                      in_bus_speed_mode_contention;
+	u8                      problem_detected;
+	u8                      slot_quiesced;
+	u8                      slot_occupied;
+	struct tasklet_struct   attn_button_dpc;
+	struct tasklet_struct   mrl_sensor_dpc;
+	struct tasklet_struct   card_presence_dpc;
+	struct tasklet_struct   isolated_power_fault_dpc;
+	struct tasklet_struct   connected_power_fault_dpc;
+	wait_queue_head_t       slot_event;
+	wait_queue_head_t       led_cmd_acquire_event;
+	wait_queue_head_t       led_cmd_release_event;
+	wait_queue_head_t       cmd_acquire_event;
+	wait_queue_head_t       cmd_release_event;
+	wait_queue_head_t       bus_acquire_event;
+	wait_queue_head_t       bus_release_event;
+	u32                     slot_event_bits;
+	void                    *slot_thread;
+	void                    *attn_led_thread;
+	SLOT_STATE_FUNCTION     slot_function;
+	SLOT_STATE_FUNCTION     attn_led_function;
+	struct async_request    slot_request;
+	struct async_completion slot_completion;
+	struct async_request    attn_led_request;
+	struct async_completion attn_led_completion;
+	void                    *shpc_context;
+	struct timer_list       slot_timer1;
+	struct timer_list       slot_timer2;
+	struct timer_list       slot_timer3;
+	struct timer_list       slot_timer4;
+	struct timer_list       slot_timer5;
+	struct timer_list       slot_timer6;
+	struct timer_list       slot_timer7;
+	struct timer_list       slot_timer8;
+	struct timer_list       slot_timer9;
+	struct timer_list       slot_timer10;
+	struct timer_list       led_timer1;
+	struct timer_list       led_timer2;
+	struct timer_list       led_timer3;
+	struct timer_list       led_timer4;
+};
+
+//
+// SHPC Context
+//
+struct shpc_context {
+	spinlock_t		shpc_spinlock;
+	struct semaphore        shpc_event_bits_semaphore;
+	void                    *mmio_base_addr;
+	struct shpc_context     *next;
+	u8                      first_slot;
+	u8                      number_of_slots;
+	u8                      slots_enabled;
+	u8                      at_power_device_d0;
+	u8                      bus_released;
+	enum shpc_speed_mode    max_speed_mode;
+	enum shpc_speed_mode    bus_speed_mode;
+	struct semaphore        cmd_available_mutex;
+	struct tasklet_struct   cmd_completion_dpc;
+	struct semaphore        bus_available_mutex;
+	wait_queue_head_t       *user_event_pointer;
+	u32                     shpc_event_bits;
+	void                    *driver_context;
+	SHPC_ASYNC_CALLBACK     async_callback;
+	u32                     shpc_instance;
+	struct slot_context     slot_context[ SHPC_MAX_NUM_SLOTS ];
+	void                    *hpc_reg;		// cookie for our pci controller location
+	struct pci_ops          *pci_ops;
+	struct pci_resource     *mem_head;
+	struct pci_resource     *p_mem_head;
+	struct pci_resource     *io_head;
+	struct pci_resource     *bus_head;
+	struct pci_dev          *pci_dev;
+	u8                      interrupt;
+	u8                      bus;
+	u8                      device;
+	u8                      function;
+	u16                     vendor_id;
+	u32                     ctrl_int_comp;
+	u8                      add_support;
+};
+
+//
+// Function Prototypes
+//
+int amdshpc_get_bus_dev (struct controller  *ctrl, u8 * bus_num, u8 * dev_num, u8 slot);
+int amdshpc_process_SI (struct controller *ctrl, struct pci_func *func);
+int amdshpc_process_SS (struct controller *ctrl, struct pci_func *func);
+int amdshpc_find_available_resources (struct controller *ctrl, void *rom_start);
+int amdshpc_save_config(struct controller *ctrl, int busnumber, union SLOT_CONFIG_INFO * is_hot_plug);
+struct pci_func *amdshpc_slot_create(u8 busnumber);
+
+
+void hp_clear_shpc_event_bit(struct shpc_context * shpc_context, u32 mask);
+void hp_set_shpc_event_bit(struct shpc_context * shpc_context, u32 mask);
+
+void hp_clear_slot_event_bit(struct slot_context * slot_context, u32 mask);
+void hp_set_slot_event_bit(struct slot_context * slot_context, u32 mask);
+
+void hp_send_event_to_all_slots(struct shpc_context *shpc_context, u32 mask);
+void hp_send_slot_event(struct slot_context *slot_context, u32 mask);
+
+int hp_get_led_cmd_available_mutex_thread(void *slot_context);
+int hp_get_cmd_available_mutex_thread    (void *slot_context);
+int hp_get_bus_available_mutex_thread(void *slot_context);
+int hp_cmd_available_mutex_thread(void * slot_context);
+int hp_bus_available_mutex_thread(void * slot_context);
+int hp_led_cmd_available_mutex_thread(void * slot_context);
+
+void hp_slot_timer1_func(unsigned long data);
+void hp_slot_timer2_func(unsigned long data);
+void hp_slot_timer3_func(unsigned long data);
+void hp_slot_timer4_func(unsigned long data);
+void hp_slot_timer5_func(unsigned long data);
+void hp_slot_timer6_func(unsigned long data);
+void hp_slot_timer7_func(unsigned long data);
+void hp_slot_timer8_func(unsigned long data);
+void hp_slot_timer9_func(unsigned long data);
+void hp_slot_timer10_func(unsigned long data);
+void hp_led_timer1_func(unsigned long data);
+void hp_led_timer2_func(unsigned long data);
+void hp_led_timer3_func(unsigned long data);
+void hp_led_timer4_func(unsigned long data);
+
+irqreturn_t hp_interrupt_service(int IRQ, void *v, struct pt_regs *regs);
+
+u32 board_replaced(struct pci_func * func, struct controller  * ctrl);
+struct pci_func *amdshpc_slot_find(u8 bus, u8 device, u8 index);
+int amdshpc_save_base_addr_length(struct controller  *ctrl, struct pci_func * func);
+int amdshpc_save_used_resources (struct controller  *ctrl, struct pci_func * func);
+int amdshpc_return_board_resources(struct pci_func * func, struct resource_lists * resources);
+int amdshpc_save_slot_config (struct controller  *ctrl, struct pci_func * new_slot);
+int amdshpc_configure_device (struct controller * ctrl, struct pci_func* func);
+int amdshpc_unconfigure_device(struct pci_func* func);
+
+
+
+void
+hp_attn_button_dpc(
+			  unsigned long deferred_context
+			  );
+
+void
+hp_mrl_sensor_dpc(
+			 unsigned long deferred_context
+			 );
+
+void
+hp_card_presence_dpc(
+			    unsigned long deferred_context
+			    );
+
+void
+hp_isolated_power_fault_dpc(
+				   unsigned long deferred_context
+				   );
+
+void
+hp_connected_power_fault_dpc(
+			    unsigned long deferred_context
+			    );
+
+void
+hp_cmd_completion_dpc(
+		     unsigned long deferred_context
+		     );
+
+int
+hp_slot_thread(
+	      void* slot_context
+	      );
+
+long
+hp_at_slot_disabled_wait_for_slot_request(
+					 struct shpc_context* shpc_context,
+					 struct slot_context* slot_context
+						 );
+
+long
+hp_at_slot_disabled_wait_for_led_cmd_available(
+					      struct shpc_context* shpc_context,
+					      struct slot_context* slot_context
+					      );
+
+long
+hp_at_slot_disabled_wait_for_led_cmd_completion(
+					       struct shpc_context* shpc_context,
+					       struct slot_context* slot_context
+					       );
+
+long
+hp_at_slot_disabled_wait_for_timeout(
+				    struct shpc_context* shpc_context,
+				    struct slot_context* slot_context
+				    );
+
+long
+hp_at_slot_disabled_wait_for_power_cmd_available(
+						struct shpc_context* shpc_context,
+						struct slot_context* slot_context
+						);
+
+long
+hp_at_slot_disabled_wait_for_power_cmd_timeout(
+					      struct shpc_context* shpc_context,
+					      struct slot_context* slot_context
+					      );
+
+long
+hp_at_slot_disabled_wait_for_power_cmd_completion(
+						 struct shpc_context* shpc_context,
+						 struct slot_context* slot_context
+						 );
+
+long
+hp_at_slot_disabled_wait_for_bus_available(
+					  struct shpc_context* shpc_context,
+					  struct slot_context* slot_context
+					  );
+
+long
+hp_at_slot_disabled_wait_for_bus_released(
+					 struct shpc_context* shpc_context,
+					 struct slot_context* slot_context
+					 );
+
+long
+hp_at_slot_disabled_wait_for_speed_mode_cmd_available(
+						     struct shpc_context* shpc_context,
+						     struct slot_context* slot_context
+						     );
+
+long
+hp_at_slot_disabled_wait_for_speed_mode_cmd_completion(
+						      struct shpc_context* shpc_context,
+						      struct slot_context* slot_context
+						      );
+
+long
+hp_at_slot_disabled_wait_for_enable_cmd_available(
+						 struct shpc_context* shpc_context,
+						 struct slot_context* slot_context
+						 );
+
+long
+hp_at_slot_disabled_wait_for_enable_cmd_completion(
+						  struct shpc_context* shpc_context,
+						  struct slot_context* slot_context
+						  );
+
+long
+hp_at_slot_disabled_wait_for_enable_timeout(
+					   struct shpc_context* shpc_context,
+					   struct slot_context* slot_context
+					   );
+
+long
+hp_to_slot_disabled_wait_for_led_cmd_available(
+					      struct shpc_context* shpc_context,
+					      struct slot_context* slot_context
+					      );
+
+long
+hp_to_slot_disabled_wait_for_led_cmd_completion(
+					       struct shpc_context* shpc_context,
+					       struct slot_context* slot_context
+					       );
+
+long
+hp_to_slot_disabled_wait_for_disable_cmd_available(
+						  struct shpc_context* shpc_context,
+						  struct slot_context* slot_context
+						  );
+
+long
+hp_to_slot_disabled_wait_for_disable_cmd_completion(
+						   struct shpc_context* shpc_context,
+						   struct slot_context* slot_context
+						   );
+
+long
+hp_to_slot_disabled_wait_for_disable_timeout(
+					    struct shpc_context* shpc_context,
+					    struct slot_context* slot_context
+					    );
+
+long
+hp_to_slot_disabled_wait_for_bus_available(
+					  struct shpc_context* shpc_context,
+					  struct slot_context* slot_context
+					  );
+
+long
+hp_at_slot_enabled_wait_for_slot_request(
+					struct shpc_context* shpc_context,
+					struct slot_context* slot_context
+					);
+
+long
+hp_at_slot_enabled_wait_for_stop_on_bus_rebalance(
+						 struct shpc_context* shpc_context,
+						 struct slot_context* slot_context
+						 );
+
+long
+hp_at_slot_enabled_wait_for_power_cmd_available(
+					       struct shpc_context* shpc_context,
+					       struct slot_context* slot_context
+					       );
+
+long
+hp_at_slot_enabled_wait_for_power_cmd_completion(
+						struct shpc_context* shpc_context,
+						struct slot_context* slot_context
+						);
+
+long
+hp_at_slot_enabled_wait_for_led_cmd_available(
+					     struct shpc_context* shpc_context,
+					     struct slot_context* slot_context
+					     );
+
+long
+hp_at_slot_enabled_wait_for_led_cmd_completion(
+					      struct shpc_context* shpc_context,
+					      struct slot_context* slot_context
+					      );
+
+long
+hp_at_slot_enabled_wait_for_timeout(
+				   struct shpc_context* shpc_context,
+				   struct slot_context* slot_context
+				   );
+
+long
+hp_at_slot_enabled_wait_for_stop_on_slot_disable(
+						struct shpc_context* shpc_context,
+						struct slot_context* slot_context
+						);
+
+long
+hp_at_slot_enabled_wait_for_stop_on_slot_disable_quiet(
+						      struct shpc_context* shpc_context,
+						      struct slot_context* slot_context
+						      );
+
+long
+hp_to_slot_enabled_wait_for_led_cmd_available(
+					     struct shpc_context* shpc_context,
+					     struct slot_context* slot_context
+					     );
+
+long
+hp_to_slot_enabled_wait_for_led_cmd_completion(
+					      struct shpc_context* shpc_context,
+					      struct slot_context* slot_context
+					      );
+
+void
+hp_get_slot_configuration(
+			 struct shpc_context* shpc_context
+			 );
+
+void
+hp_enable_slot_interrupts(
+			 struct slot_context* slot_context
+			 );
+
+void
+hp_disable_slot_interrupts(
+			  struct slot_context* slot_context
+			  );
+
+void
+hp_enable_global_interrupts(
+			   struct shpc_context* shpc_context
+			   );
+
+void
+hp_disable_global_interrupts(
+			    struct shpc_context* shpc_context
+			    );
+
+enum shpc_speed_mode
+hp_get_bus_speed_mode(
+		     struct shpc_context* shpc_context
+		     );
+
+enum shpc_speed_mode
+hp_get_card_speed_mode(
+		      struct slot_context* slot_context
+		      );
+
+enum mode_frequency
+hp_translate_speed_mode(
+		       enum shpc_speed_mode shpc_speed_mode
+		       );
+
+enum hp_power_requirements
+hp_translate_card_power(
+		       enum shpc_card_power ShpcCardPower
+			       );
+
+enum hp_indicators
+hp_translate_indicator(
+		      enum shpc_slot_led ShpcIndicator
+			      );
+
+u8
+hp_flag_slot_as_enabled(
+		       struct shpc_context* shpc_context,
+		       struct slot_context* slot_context
+		       );
+
+u8
+hp_flag_slot_as_disabled(
+			struct shpc_context* shpc_context,
+			struct slot_context* slot_context
+			);
+
+u8
+hp_signal_enabled_slots_to_rebalance_bus(
+					struct shpc_context* shpc_context
+					);
+
+enum shpc_speed_mode
+hp_get_max_speed_mode(
+		     struct shpc_context* shpc_context,
+		     enum shpc_speed_mode From_speed_mode
+		     );
+
+void
+hp_signal_user_event(
+		    struct shpc_context* shpc_context
+		    );
+
+void
+hp_signal_user_event_at_dpc_level(
+				 struct shpc_context* shpc_context
+				 );
+
+int
+hp_attn_led_thread(
+		  void* slot_context
+		  );
+
+long
+hp_wait_for_attn_led_request(
+			    struct shpc_context* shpc_context,
+			    struct slot_context* slot_context
+			    );
+
+long
+hp_wait_for_attn_led_blink_cmd_available(
+					struct shpc_context* shpc_context,
+					struct slot_context* slot_context
+					);
+
+long
+hp_wait_for_attn_led_blink_cmd_completion(
+					 struct shpc_context* shpc_context,
+					 struct slot_context* slot_context
+					 );
+
+long
+hp_wait_for_attn_led_blink_timeout(
+				  struct shpc_context* shpc_context,
+				  struct slot_context* slot_context
+				  );
+
+long
+hp_wait_for_attn_led_normal_cmd_available(
+					 struct shpc_context* shpc_context,
+					 struct slot_context* slot_context
+					 );
+
+long
+hp_wait_for_attn_led_normal_cmd_completion(
+					  struct shpc_context* shpc_context,
+					  struct slot_context* slot_context
+					  );
+
+long
+hp_wait_for_attn_led_back_to_normal_cmd_available(
+						 struct shpc_context* shpc_context,
+						 struct slot_context* slot_context
+						 );
+
+long
+hp_wait_for_attn_led_back_to_normal_cmd_completion(
+						  struct shpc_context* shpc_context,
+						  struct slot_context* slot_context
+						  );
+
+
+
+#endif  // _SHPC_H_
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/amdshpc_core.c	Wed Mar 17 11:19:43 2004
@@ -0,0 +1,915 @@
+/*
+ * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001,2003 IBM Corp.
+ * Copyright (C) 2002-2003 Advanced Micro Devices
+ *
+ * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS
+ * AND CONDITIONS OF THE GNU GENERAL PUBLIC
+ * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS
+ * INCLUDED WITH THIS FILE AND POSTED AT
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ *
+ * Send feedback to <greg@kroah.com> <david.keck@amd.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include "amdshpc.h"
+#include "amdshpc_ddi.h"
+#include "pci_hotplug.h"
+#include "../../../arch/i386/pci/pci.h"
+
+/* Global variables */
+int amdshpc_debug;
+struct shpc_context *amdshpc_ctrl_list; // used for the shpc state machine
+struct controller *ctrl_list;	 	  // used only for resource management
+struct pci_func *amdshpc_slot_list[256];
+
+static int num_slots;
+static void *amdshpc_rom_start;
+static unsigned long shpc_instance;
+
+#define DRIVER_VERSION	"1.03"
+#define DRIVER_AUTHOR	"Dave Keck <david.keck@amd.com>"
+#define DRIVER_DESC	"AMD Standard Hot Plug Controller Driver"
+#define PCI_DEVICE_ID_AMD_GOLAM_7450	0x7450
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+//MODULE_PARM(debug, "i");
+//MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
+
+static int enable_slot		(struct hotplug_slot *slot);
+static int disable_slot		(struct hotplug_slot *slot);
+static int set_attention_status (struct hotplug_slot *slot, u8 value);
+static int hardware_test	(struct hotplug_slot *slot, u32 value);
+static int get_power_status	(struct hotplug_slot *slot, u8 *value);
+static int get_attention_status	(struct hotplug_slot *slot, u8 *value);
+static int get_latch_status	(struct hotplug_slot *slot, u8 *value);
+static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
+
+// values to be returned to the PCI Hotplug Core
+#define CORE_SLOT_DISABLED		0
+#define CORE_SLOT_ENABLED		1
+
+#define	CORE_INDICATOR_OFF		0
+#define	CORE_INDICATOR_ON		1
+#define	CORE_INDICATOR_BLINK		2
+
+#define CORE_LATCH_CLOSED		1
+#define CORE_LATCH_OPENED		0
+
+static int init_slots (	struct controller *ctrl, int num_slots );
+static void translate_slot_info (struct hotplug_slot_info *info,
+								 union SLOT_STATUS_INFO *query);
+
+static struct hotplug_slot_ops skel_hotplug_slot_ops = {
+	.owner =		THIS_MODULE,
+	.enable_slot =		enable_slot,
+	.disable_slot =		disable_slot,
+	.set_attention_status =	set_attention_status,
+	.hardware_test =	hardware_test,
+	.get_power_status =	get_power_status,
+	.get_attention_status =	get_attention_status,
+	.get_latch_status =	get_latch_status,
+	.get_adapter_status =	get_adapter_status,
+};
+
+/* Inline functions to check the sanity of a pointer that is passed to us */
+static inline int slot_paranoia_check (struct slot *slot, const char *function)
+{
+	if (!slot) {
+		dbg("-->%s - slot == NULL", function);
+		return -1;
+	}
+	if (slot->magic != SLOT_MAGIC) {
+		dbg("-->%s - bad magic number for slot", function);
+		return -1;
+	}
+	if (!slot->hotplug_slot) {
+		dbg("-->%s - slot->hotplug_slot == NULL!", function);
+		return -1;
+	}
+	return 0;
+}
+
+static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function)
+{
+	struct slot *slot;
+
+	if (!hotplug_slot) {
+		dbg("-->%s - hotplug_slot == NULL\n", function);
+		return NULL;
+	}
+
+	slot = (struct slot *)hotplug_slot->private;
+	if (slot_paranoia_check (slot, function))
+				return NULL;
+	return slot;
+}
+
+static int enable_slot (struct hotplug_slot *hotplug_slot)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct shpc_context *shpc_context;
+	union SLOT_STATUS_INFO query;
+	long status;
+	int retval = 0;
+
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	/*
+	 *  enable the specified slot
+	 */
+	shpc_context = ( struct shpc_context * )slot->private;
+	status = hp_StartAsyncRequest(shpc_context, slot->number,
+		SHPC_ASYNC_ENABLE_SLOT, 0, slot );
+
+	//
+	// pretend async request was completed (we're not queuing slot requests)
+	//
+	hp_QuerySlotStatus( shpc_context, slot->number, &query );
+	if( status == STATUS_SUCCESS ) {
+		query.x.lu_slot_state = SLOT_ENABLE;
+		query.x.lu_pi_state = INDICATOR_BLINK;
+		if( query.x.lu_card_present &&
+			( query.x.lu_mrl_implemented == HP_FALSE ||
+			query.x.lu_mrl_opened == HP_FALSE ) &&
+			query.x.lu_power_fault == HP_FALSE ) {
+				query.x.lu_request_failed = HP_FALSE;
+		}
+		else {
+			query.x.lu_request_failed = HP_TRUE;
+		}
+	}
+	else {
+		query.x.lu_request_failed = HP_TRUE;
+	}
+
+	//
+	// translate the slot info to PCI HOTPLUG CORE values
+	//
+	translate_slot_info (hotplug_slot->info, &query);
+
+	retval = ( query.x.lu_request_failed == HP_TRUE ) ? 0 : -1;
+	return retval;
+}
+
+
+static int disable_slot (struct hotplug_slot *hotplug_slot)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct shpc_context *shpc_context;
+	union SLOT_STATUS_INFO query;
+	long status;
+	int retval = 0;
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	/*
+	 *  disable the specified slot
+	 */
+	shpc_context = ( struct shpc_context * )slot->private;
+	status = hp_StartAsyncRequest(shpc_context, slot->number,
+		SHPC_ASYNC_DISABLE_SLOT, 0, slot );
+
+	//
+	// pretend async request was completed (we're not queuing slot requests)
+	//
+	hp_QuerySlotStatus( shpc_context, slot->number, &query );
+	if( status == STATUS_SUCCESS ) {
+		query.x.lu_slot_state = SLOT_DISABLE;
+		query.x.lu_pi_state = INDICATOR_BLINK;
+		query.x.lu_request_failed = HP_FALSE;
+	}
+	else {
+		query.x.lu_request_failed = HP_TRUE;
+	}
+
+	//
+	// translate the slot info to CORE values
+	//
+	translate_slot_info (hotplug_slot->info, &query);
+
+	retval = ( query.x.lu_request_failed == HP_TRUE ) ? 0 : -1;
+	return retval;
+}
+
+static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct shpc_context *shpc_context;
+	int retval = 0;
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg (" %s - physical_slot = %s  state = %d",__FUNCTION__, hotplug_slot->name, status);
+
+	/*
+	 *  turn light on/off
+	 */
+	shpc_context = (struct shpc_context *)slot->private;
+
+	status = hp_StartAsyncRequest(shpc_context, slot->number,
+		((status == CORE_INDICATOR_OFF) ? SHPC_ASYNC_LED_NORMAL : SHPC_ASYNC_LED_LOCATE), 10, slot);
+	hotplug_slot->info->attention_status  = status;
+
+	return retval;
+}
+
+static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct shpc_context *shpc_context;
+	union SLOT_STATUS_INFO query;
+	int retval = 0;
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n",__FUNCTION__, hotplug_slot->name);
+
+	/*
+	 * get the current power status of the specific
+	 * slot and store it in the *value location.
+	 */
+	shpc_context = (struct shpc_context *)slot->private;
+	hp_QuerySlotStatus(shpc_context, slot->number, &query);
+	translate_slot_info (hotplug_slot->info, &query);
+	*value = hotplug_slot->info->power_status;
+
+	return retval;
+}
+
+static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct shpc_context *shpc_context;
+	union SLOT_STATUS_INFO query;
+	int retval = 0;
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n",__FUNCTION__, hotplug_slot->name);
+
+	/*
+	 * get the current attention status of the specific
+	 * slot and store it in the *value location.
+	 */
+	shpc_context = (struct shpc_context *)slot->private;
+	hp_QuerySlotStatus(shpc_context, slot->number, &query);
+	translate_slot_info (hotplug_slot->info, &query);
+	*value = hotplug_slot->info->attention_status;
+
+	return retval;
+}
+
+static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct shpc_context *shpc_context;
+	union SLOT_STATUS_INFO query;
+	int retval = 0;
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n",__FUNCTION__, hotplug_slot->name);
+
+	/*
+	 * get the current latch status of the specific
+	 * slot and store it in the *value location.
+	 */
+	shpc_context = (struct shpc_context *)slot->private;
+	hp_QuerySlotStatus(shpc_context, slot->number, &query);
+	translate_slot_info (hotplug_slot->info, &query);
+	*value = hotplug_slot->info->latch_status;
+
+	return retval;
+}
+
+static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct shpc_context *shpc_context;
+	union SLOT_STATUS_INFO query;
+	int retval = 0;
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n",__FUNCTION__, hotplug_slot->name);
+
+	/*
+	 * get the current adapter status of the specific
+	 * slot and store it in the *value location.
+	 */
+	shpc_context = (struct shpc_context *)slot->private;
+	hp_QuerySlotStatus(shpc_context, slot->number, &query);
+	translate_slot_info (hotplug_slot->info, &query);
+	*value = hotplug_slot->info->adapter_status;
+
+	return retval;
+}
+
+static void translate_slot_info (struct hotplug_slot_info *info,
+				 union SLOT_STATUS_INFO *query)
+{
+	// power indicator
+	if( query->x.lu_pi_state == INDICATOR_OFF ) {
+		info->power_status = CORE_INDICATOR_OFF;
+	}
+	else if( query->x.lu_pi_state == INDICATOR_ON ) {
+		info->power_status = CORE_INDICATOR_ON;
+	}
+	else {
+		info->power_status = CORE_INDICATOR_BLINK;
+	}
+
+	// attention indicator
+	if( query->x.lu_ai_state == INDICATOR_OFF ) {
+		info->attention_status = CORE_INDICATOR_OFF;
+	}
+	else if( query->x.lu_ai_state == INDICATOR_ON ) {
+		info->attention_status = CORE_INDICATOR_ON;
+	}
+	else {
+		info->attention_status = CORE_INDICATOR_BLINK;
+	}
+
+	// retention latch
+	if( query->x.lu_mrl_implemented == HP_TRUE &&
+		query->x.lu_mrl_opened == HP_TRUE ) {
+		info->latch_status = CORE_LATCH_OPENED;
+	}
+	else {
+		info->latch_status = CORE_LATCH_CLOSED;
+	}
+
+	// adapter status
+	if( query->x.lu_slot_state == SLOT_ENABLE ) {
+		info->adapter_status = CORE_SLOT_ENABLED;
+	}
+	else {
+		info->adapter_status = CORE_SLOT_DISABLED;
+	}
+}
+
+static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval = 0;
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	err ("No hardware tests are defined for this driver");
+	retval = -ENODEV;
+
+	/* Or you can specify a test if you want to */
+	/* AMD driver does not have a test */
+	return retval;
+}
+
+#define SLOT_NAME_SIZE	10
+static void make_slot_name (struct slot *slot)
+{
+	unsigned long slot_psn;
+	struct shpc_context *shpc_context;
+
+	shpc_context = ( struct shpc_context * )slot->private;
+
+	//
+	// Get physical slot number
+	//
+	hp_Queryslot_psn(shpc_context, slot->number, &slot_psn);
+
+	snprintf (slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d", (char)slot_psn);
+}
+
+static void release_slot(struct hotplug_slot *hotplug_slot)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+
+	if (slot == NULL)
+		return;
+
+	dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	kfree(slot->hotplug_slot->info);
+	kfree(slot->hotplug_slot->name);
+	kfree(slot->hotplug_slot);
+	kfree(slot);
+}
+
+static int init_slots (struct controller *ctrl, int num_slots)
+{
+	struct slot *slot;
+	struct hotplug_slot *hotplug_slot;
+	struct hotplug_slot_info *info;
+	char *name;
+	int retval = 0;
+	int i;
+	u8 value;
+
+	/*
+	 * Create a structure for each slot, and register that slot
+	 * with the pci_hotplug subsystem.
+	 */
+	for (i = 0; i < num_slots; ++i) {
+		slot = kmalloc (sizeof (struct slot), GFP_KERNEL);
+		if (!slot)
+			return -ENOMEM;
+		memset(slot, 0, sizeof(struct slot));
+
+		hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL);
+		if (!hotplug_slot) {
+			kfree (slot);
+			return -ENOMEM;
+		}
+		memset(hotplug_slot, 0, sizeof (struct hotplug_slot));
+		slot->hotplug_slot = hotplug_slot;
+
+		info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
+		if (!info) {
+			kfree (hotplug_slot);
+			kfree (slot);
+			return -ENOMEM;
+		}
+		memset(info, 0, sizeof (struct hotplug_slot_info));
+		hotplug_slot->info = info;
+
+		name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL);
+		if (!name) {
+			kfree (info);
+			kfree (hotplug_slot);
+			kfree (slot);
+			return -ENOMEM;
+		}
+		hotplug_slot->name = name;
+
+		slot->magic = SLOT_MAGIC;
+		slot->number = i;
+		slot->private = (void*) ctrl->shpc_context;
+
+		hotplug_slot->private = slot;
+		hotplug_slot->release = &release_slot;
+		make_slot_name (slot);
+		hotplug_slot->ops = &skel_hotplug_slot_ops;
+
+		/*
+		 * Initilize the slot info structure with some known
+		 * good values.
+		 */
+		get_power_status(hotplug_slot, &value);
+		info->power_status = value;
+		get_attention_status(hotplug_slot, &value);
+		info->attention_status = value;
+		get_latch_status(hotplug_slot, &value);
+		info->latch_status = value;
+		get_adapter_status(hotplug_slot, &value);
+		info->adapter_status = value;
+
+		dbg ("registering slot %d\n", i);
+		retval = pci_hp_register (slot->hotplug_slot);
+		if (retval) {
+			err ("pci_hp_register failed with error %d\n", retval);
+			kfree (info);
+			kfree (name);
+			kfree (hotplug_slot);
+			kfree (slot);
+			return retval;
+		}
+
+		/* add slot to our internal list */
+		list_add (&slot->slot_list, &slot_list);
+	}
+
+	return retval;
+}
+
+static int amdshpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int retval;
+	int loop;
+	u16 vendor_id;
+	u16 device_id;
+	u32 rc;
+	long status = STATUS_SUCCESS;
+	struct controller *ctrl;
+	struct shpc_context *shpc_context;
+	union SLOT_CONFIG_INFO slot_config;
+
+	rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
+	dbg( "%s-->Vendor ID: %x\n",__FUNCTION__, vendor_id);
+	if (rc || (vendor_id != PCI_VENDOR_ID_AMD)) {
+		err(msg_HPC_non_amd);
+		return -ENODEV;
+	}
+
+	rc = pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
+	dbg( "%s-->Device ID: %x\n",__FUNCTION__, device_id);
+	if (rc || (device_id != PCI_DEVICE_ID_AMD_GOLAM_7450)) {
+		err(msg_HPC_not_amd_hp);
+		return -ENODEV;
+	}
+
+	if (vendor_id == PCI_VENDOR_ID_AMD) {
+
+		shpc_context = (struct shpc_context *)kmalloc(sizeof(struct shpc_context), GFP_KERNEL);
+		if (!shpc_context) {
+			err("%s : out of memory\n",__FUNCTION__);
+			return -ENOMEM;
+		}
+		memset(shpc_context, 0, sizeof(struct shpc_context));
+
+		ctrl = (struct controller *)kmalloc(sizeof(struct controller), GFP_KERNEL);
+		if (!ctrl) {
+			err("%s : out of memory\n", __FUNCTION__);
+			rc =  -ENOMEM;
+			goto err_free_shpc_context;
+		}
+		memset(ctrl, 0, sizeof(struct controller));
+
+		/* Set Vendor ID, so it can be accessed later from other functions */
+		ctrl->vendor_id = vendor_id;
+
+	} else {
+		err(msg_HPC_not_supported);
+		return -ENODEV;
+	}
+
+	ctrl->shpc_context = shpc_context;
+	ctrl->pci_dev = pdev;
+	ctrl->interrupt = pdev->irq;
+	ctrl->device = PCI_SLOT(pdev->devfn);
+	ctrl->function = PCI_FUNC(pdev->devfn);
+
+	//
+	// the AMD hotplug bus is behind a bridge
+	//
+//	ctrl->pci_ops = pdev->subordinate->ops;
+	ctrl->pci_bus = pdev->subordinate;
+	ctrl->bus = pdev->subordinate->number;
+
+	dbg( "%s-->bus = %d   device = %d   function = %d\n",__FUNCTION__, ctrl->bus, ctrl->device, ctrl->function);
+
+	info("Found PCI hot plug controller on bus %d\n", pdev->bus->number);
+	info("Checking if MMIO region available for this HP controller...\n");
+		    
+	//
+	// Get memory mapped I/O region
+	//
+	dbg( "%s-->pdev = %p\n",__FUNCTION__, pdev);
+	dbg("%s -->pci resource start %lx\n",__FUNCTION__, pci_resource_start(pdev, 0));
+	dbg("%s -->pci resource len   %lx\n",__FUNCTION__, pci_resource_len  (pdev, 0));
+	if (!request_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0), MY_NAME)) {
+		err("MMIO region not available, skipping\n");
+		rc = -ENOMEM;
+		goto err_free_ctrl;
+	}
+
+	//
+	// Get linear address to put in controller structure
+	//
+	shpc_context->mmio_base_addr = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+	if (!shpc_context->mmio_base_addr) {
+		err("cannot remap MMIO region %lx @ %lx\n", pci_resource_len(pdev, 0), pci_resource_start(pdev, 0));
+		rc = -ENODEV;
+		goto err_free_mem_region;
+	}
+
+	dbg("%s -->shpc_context->mmio_base_addr = %p",__FUNCTION__, (unsigned long*)shpc_context->mmio_base_addr);
+
+	hp_AddDevice(shpc_context, ctrl, shpc_context->async_callback, shpc_instance++);
+
+	// Initialize controller
+	shpc_context->interrupt = pdev->irq;
+	dbg("%s -->shpc_context->interrupt = %d", __FUNCTION__,pdev->irq);
+	if (!hp_StartDevice(shpc_context)){
+		rc = -ENODEV;
+		goto err_iounmap;
+	}
+
+	//
+	// initialize this array only once
+	//
+	if (shpc_context->shpc_instance == 0 ) {
+		dbg("%s  Initialize slot lists\n",__FUNCTION__);
+		for (loop = 0; loop < 256; loop++) {
+			amdshpc_slot_list[loop] = NULL;
+		}
+	}
+
+	if (!amdshpc_ctrl_list) {
+		amdshpc_ctrl_list = shpc_context;
+		shpc_context->next = NULL;
+	} else {
+		amdshpc_ctrl_list->next = shpc_context;
+		shpc_context->next = NULL;
+	}
+
+	if (!ctrl_list) {
+		ctrl_list = ctrl;
+		ctrl->next = NULL;
+	} else {
+		ctrl_list->next = ctrl;
+		ctrl->next = NULL;
+	}
+
+	// Map rom address so we can get the HPRT table
+	amdshpc_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
+	if (!amdshpc_rom_start) {
+		err ("Could not ioremap memory region for ROM\n");
+		retval = -EIO;;
+		iounmap(amdshpc_rom_start);
+		return retval;
+	}
+
+	//**************************************************
+	//
+	//	Save configuration headers for this and
+	//	subordinate PCI buses
+	//
+	//**************************************************
+
+	// find the physical slot number of the first hot plug slot
+	status = hp_QuerySlots(shpc_context, &slot_config);
+	// first slot on a bridged bus is always #1
+	ctrl->first_slot = 1;
+	dbg("%s  hp_QuerySlots: first_slot = %d, FDN = %d PSN_UP = %d\n",__FUNCTION__,
+						ctrl->first_slot, slot_config.x.lu_base_FDN, slot_config.x.lu_PSN_up);
+
+	if (rc) {
+		err(msg_initialization_err, rc);
+		goto err_iounmap;
+	}
+
+	if (!status) {
+		err(msg_initialization_err, (int)status);
+		goto err_iounmap;
+	}
+
+	// Store PCI Config Space for all devices on this bus
+	rc = amdshpc_save_config(ctrl, ctrl->bus, &slot_config);
+	if (rc) {
+		err("%s: unable to save PCI configuration data, error %d",__FUNCTION__, rc);
+		goto err_iounmap;
+	}
+
+	//
+	// Get IO, memory, and IRQ resources for new PCI devices
+	//
+	rc = amdshpc_find_available_resources(ctrl, amdshpc_rom_start);
+	if (rc) {
+		dbg("%s -->amdshpc_find_available_resources = 0x%x\n",__FUNCTION__, rc);
+		err("unable to locate PCI configuration resources for hot plug.\n");
+		goto err_iounmap;
+	}
+	
+	//
+	// set global variable num_slots
+	//
+	num_slots = shpc_context->number_of_slots;
+
+	dbg("%s   about to call init_slots()",__FUNCTION__);
+	rc = init_slots(ctrl, num_slots);
+	if (rc){
+		goto err_iounmap;
+	}
+
+	return 0;
+
+err_iounmap:
+	iounmap((void *)shpc_context->mmio_base_addr);
+err_free_mem_region:
+	release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+err_free_shpc_context:
+	kfree(shpc_context);
+err_free_ctrl:
+	kfree(ctrl);
+	return rc;
+}
+
+static void cleanup_slots (void)
+{
+	struct list_head *tmp;
+	struct list_head *next;
+	struct slot *slot;
+
+	/*
+	 * Unregister all of our slots with the pci_hotplug subsystem.
+	 * The memory will be freed in the release_slot() callback.
+	 */
+	list_for_each_safe(tmp, next, &slot_list) {
+		slot = list_entry(tmp, struct slot, slot_list);
+		list_del(&slot->slot_list);
+		pci_hp_deregister(slot->hotplug_slot);
+	}
+
+	return;
+}
+static void unload_amdshpc(void)
+{
+	struct pci_func *next;
+	struct pci_func *TempSlot;
+	int loop;
+	struct shpc_context *shpc_context;
+	struct shpc_context *tshpc_context;
+	struct controller *ctrl;
+	struct controller *tctrl;
+	struct pci_resource *res;
+	struct pci_resource *tres;
+
+	ctrl = ctrl_list;
+
+	while (ctrl) {
+		//reclaim PCI mem
+		release_mem_region(pci_resource_start(ctrl->pci_dev, 0),
+				   pci_resource_len(ctrl->pci_dev, 0));
+
+		res = ctrl->io_head;
+		while (res) {
+			tres = res;
+			res = res->next;
+			kfree(tres);
+		}
+
+		res = ctrl->mem_head;
+		while (res) {
+			tres = res;
+			res = res->next;
+			kfree(tres);
+		}
+
+		res = ctrl->p_mem_head;
+		while (res) {
+			tres = res;
+			res = res->next;
+			kfree(tres);
+		}
+
+		res = ctrl->bus_head;
+		while (res) {
+			tres = res;
+			res = res->next;
+			kfree(tres);
+		}
+
+		tctrl = ctrl;
+		ctrl = ctrl->next;
+		kfree(tctrl);
+	}
+
+	for (loop = 0; loop < 256; loop++) {
+		next = amdshpc_slot_list[loop];
+		while (next != NULL) {
+			res = next->io_head;
+			while (res) {
+				tres = res;
+				res = res->next;
+				kfree(tres);
+			}
+
+			res = next->mem_head;
+			while (res) {
+				tres = res;
+				res = res->next;
+				kfree(tres);
+			}
+
+			res = next->p_mem_head;
+			while (res) {
+				tres = res;
+				res = res->next;
+				kfree(tres);
+			}
+
+			res = next->bus_head;
+			while (res) {
+				tres = res;
+				res = res->next;
+				kfree(tres);
+			}
+
+			TempSlot = next;
+			next = next->next;
+			kfree(TempSlot);
+		}
+	}
+
+	shpc_context = amdshpc_ctrl_list;
+
+	while(shpc_context){
+
+		dbg("%s -->shpc_context = %p",__FUNCTION__ , shpc_context);
+		dbg("%s -->kill_amdshpc() instance = %d", __FUNCTION__ ,shpc_context->shpc_instance);
+		hp_StopDevice(shpc_context);
+
+		//Free IRQ associated with hot plug device
+		free_irq(shpc_context->interrupt, shpc_context);
+
+		//Unmap the memory
+		iounmap(shpc_context->mmio_base_addr);
+
+		// free the controller memory
+		tshpc_context = shpc_context;
+		shpc_context = shpc_context->next;
+		kfree(tshpc_context);
+	}
+
+	//unmap the rom address
+	if (amdshpc_rom_start)
+		iounmap(amdshpc_rom_start);
+}
+
+
+static struct pci_device_id hpcd_pci_tbl[] = {
+	{
+	/* handle AMD Standard Hotplug controller */
+
+//    class:          ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00),
+	class:	 ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00),
+	class_mask:	~0,
+
+	/* AMD makes it */
+	vendor:	 	PCI_VENDOR_ID_AMD,
+	device:	 	PCI_DEVICE_ID_AMD_GOLAM_7450,
+	subvendor:	PCI_ANY_ID,
+	subdevice:	PCI_ANY_ID,
+
+	}, { /* end: all zeroes */ }
+};
+
+MODULE_DEVICE_TABLE(pci, hpcd_pci_tbl);
+
+
+
+static struct pci_driver amdshpc_driver = {
+	name:		"pci_hotplug",
+	id_table:	hpcd_pci_tbl,
+	probe:		amdshpc_probe,
+	/* remove:	amdshpc_remove_one, */
+};
+
+
+static int __init amdshpc_init(void)
+{
+	int result;
+
+	amdshpc_debug = debug;
+	/*
+	 * Do specific initialization stuff for your driver here
+	 * Like initilizing your controller hardware (if any) and
+	 * determining the number of slots you have in the system
+	 * right now.
+	 */
+
+	result = pci_module_init(&amdshpc_driver);
+	dbg("%s -->pci_module_init = %d\n",__FUNCTION__ , result);
+	if (result)
+		return result;
+
+
+	info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
+	return 0;
+}
+
+static void __exit amdshpc_exit(void)
+{
+	//
+	// Clean everything up.
+	//
+	dbg("%s -->unload_amdshpc()\n",__FUNCTION__ );
+	unload_amdshpc();
+
+	cleanup_slots();
+
+	dbg("%s -->pci_unregister_driver\n",__FUNCTION__ );
+	pci_unregister_driver(&amdshpc_driver);
+
+}
+
+module_init(amdshpc_init);
+module_exit(amdshpc_exit);
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/amdshpc_ctrl.c	Wed Mar 17 11:19:43 2004
@@ -0,0 +1,969 @@
+/*
+ * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001,2003 IBM Corp.
+ * Copyright (C) 2002-2003 Advanced Micro Devices
+ *
+ * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS
+ * AND CONDITIONS OF THE GNU GENERAL PUBLIC
+ * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS
+ * INCLUDED WITH THIS FILE AND POSTED AT
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ *
+ * Send feedback to <david.keck@amd.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include "amdshpc_ddi.h"
+#include "amdshpc.h"
+
+
+// ****************************************************************************
+//
+// hp_slot_thread() @ PASSIVE_LEVEL
+//
+// ****************************************************************************
+int hp_slot_thread(void* ptr)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	struct shpc_context* shpc_context;
+	struct slot_context* slot_context;
+	union SLOT_STATUS_INFO slot_status;
+	
+	lock_kernel ();
+	daemonize ("amdshpc_slot");
+	unlock_kernel ();
+
+	slot_context = (struct slot_context*) ptr;
+	shpc_context = (struct shpc_context*) slot_context->shpc_context;
+
+	//
+	// Insertion/Removal State Machine (loops until requested to exit)
+	//
+	do {
+		status = slot_context->slot_function( shpc_context, slot_context );
+		//
+		// Suspend?
+		//
+		if(!status) {
+			spin_lock_irqsave(&shpc_context->shpc_spinlock, old_irq_flags);
+			if(shpc_context->shpc_event_bits & SUSPEND_EVENT ) {
+				status = STATUS_SUCCESS;
+			}
+			spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+			if(status) {
+				dbg( "%s-->SUSPEND: slot_id[ %d:%d ]",__FUNCTION__,
+					(int)shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+				do {
+					interruptible_sleep_on(&slot_context->slot_event);
+				}while(!((shpc_context->shpc_event_bits & RESUME_EVENT) ||
+					(shpc_context->shpc_event_bits & REMOVE_EVENT)));
+
+				if(shpc_context->shpc_event_bits & REMOVE_EVENT ) {
+					status = STATUS_UNSUCCESSFUL;
+				}
+				else {
+					dbg("%s-->RESUME: slot_id[ %d:%d ]",__FUNCTION__,
+						shpc_context->shpc_instance, slot_context->slot_number-1 );
+				}
+			}
+		}
+	} while(status);
+
+	//
+	// We're exiting, most likely due to an exit_request_event.  So, let's cleanup!
+	//
+	dbg("%s-->Slot Thread Termination: slot_id[ %d:%d ]",__FUNCTION__,
+		shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Pending SW-initiated slot request?
+	//
+	if(slot_context->slot_event_bits & SLOT_REQUEST_EVENT ) {
+		//
+		// Complete it with failure code
+		//
+		hp_QuerySlotStatus(	shpc_context, slot_context->slot_number - 1, &slot_status );
+		slot_status.x.lu_request_failed = HP_TRUE;
+		shpc_context->async_callback(
+			shpc_context->driver_context,
+			slot_context->slot_number - 1,
+			slot_context->slot_request.type,
+			slot_status,
+			slot_context->slot_request.request_context );
+
+		//
+		// Signal registered user EVENT
+		//
+		hp_signal_user_event( shpc_context );
+	}
+	return(status);
+}
+
+
+// ****************************************************************************
+//
+// hp_attn_led_thread() @ PASSIVE_LEVEL
+//
+// ****************************************************************************
+int
+hp_attn_led_thread(
+	void* ptr
+)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	struct shpc_context* shpc_context;
+	struct slot_context* slot_context;
+	union SLOT_STATUS_INFO slot_status;
+	
+	lock_kernel ();
+	daemonize ("amdshpc_led");
+	unlock_kernel ();
+
+	slot_context = (struct slot_context*) ptr;
+	shpc_context = (struct shpc_context*) slot_context->shpc_context;
+
+	//
+	// Attention LED State Machine (loops until requested to exit)
+	//
+	do {
+		status = slot_context->attn_led_function(shpc_context, slot_context);
+		//
+		// Suspend?
+		//
+		if(!status) {
+			spin_lock_irqsave(&shpc_context->shpc_spinlock, old_irq_flags);
+			if(shpc_context->shpc_event_bits & SUSPEND_EVENT ) {
+				status = STATUS_SUCCESS;
+			}
+			spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+			if(status) {
+				dbg("%s-->SUSPEND: slot_id[ %d:%d ]",__FUNCTION__,
+					shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+				do {
+					interruptible_sleep_on(&slot_context->slot_event);
+				}while(!((shpc_context->shpc_event_bits & RESUME_EVENT) ||
+					(shpc_context->shpc_event_bits & REMOVE_EVENT)));
+
+				if(shpc_context->shpc_event_bits & REMOVE_EVENT ) {
+					status = STATUS_UNSUCCESSFUL;
+				}
+				else {
+					dbg("%s-->RESUME: slot_id[ %d:%d ]",__FUNCTION__,
+						shpc_context->shpc_instance, slot_context->slot_number-1 );
+				}
+			}
+		}
+	} while(status);
+
+	//
+	// We're exiting, most likely due to an exit_request_event.  So, let's cleanup!
+	//
+	dbg("%s-->LED Thread Termination: slot_id[ %d:%d ]",__FUNCTION__,
+		shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Pending SW-initiated AttnLED request?
+	//
+	if(slot_context->slot_event_bits & ATTN_LED_REQUEST_EVENT ) {
+		//
+		// Complete it with failure code
+		//
+		hp_QuerySlotStatus(	shpc_context, slot_context->slot_number - 1, &slot_status );
+		slot_status.x.lu_request_failed = HP_TRUE;
+		shpc_context->async_callback(
+			shpc_context->driver_context,
+			slot_context->slot_number - 1,
+			slot_context->attn_led_request.type,
+			slot_status,
+			slot_context->attn_led_request.request_context );
+
+		//
+		// Signal registered user EVENT
+		//
+		hp_signal_user_event( shpc_context );
+	}
+	return(status);
+}
+
+
+// ****************************************************************************
+//
+// hp_get_slot_configuration() @ Any IRQL
+//
+// ****************************************************************************
+void
+hp_get_slot_configuration(
+	struct shpc_context* shpc_context
+)
+{
+	struct slot_context* slot_context;
+	union SHPC_SLOTS_AVAILABLE1_DWREG SlotAvail1Reg;
+	union SHPC_SLOTS_AVAILABLE2_DWREG SlotAvail2Reg;
+	union SHPC_SLOT_CONFIG_DWREG SlotConfigReg;
+	union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg;
+	enum shpc_speed_mode max_speed_mode;
+	u8 i;
+
+	//
+	// Get max number of slots available
+	//
+	SlotAvail1Reg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SLOTS_AVAILABLE1_REG_OFFSET);
+	SlotAvail2Reg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SLOTS_AVAILABLE2_REG_OFFSET);
+	//
+	// Get slot configuration
+	//
+	SlotConfigReg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SLOT_CONFIG_REG_OFFSET);
+
+	//
+	// Get number of available slots per speed/mode
+	//
+	shpc_context->slots_enabled = 0;
+	shpc_context->number_of_slots = 0;
+	if( SlotAvail1Reg.x.N_133PCIX ) {
+		shpc_context->number_of_slots = ( u8 )SlotAvail1Reg.x.N_133PCIX;
+		shpc_context->max_speed_mode = SHPC_BUS_PCIX_133;
+	}
+	else if( SlotAvail1Reg.x.N_100PCIX ) {
+		shpc_context->number_of_slots = ( u8 )SlotAvail1Reg.x.N_100PCIX;
+		shpc_context->max_speed_mode = SHPC_BUS_PCIX_100;
+	}
+	else if( SlotAvail1Reg.x.N_66PCIX ) {
+		shpc_context->number_of_slots = ( u8 )SlotAvail1Reg.x.N_66PCIX;
+		shpc_context->max_speed_mode = SHPC_BUS_PCIX_66;
+	}
+	else if( SlotAvail2Reg.x.N_66CONV ) {
+		shpc_context->number_of_slots = ( u8 )SlotAvail2Reg.x.N_66CONV;
+		shpc_context->max_speed_mode = SHPC_BUS_CONV_66;
+	}
+	else if( SlotAvail1Reg.x.N_33CONV ) {
+		shpc_context->number_of_slots = ( u8 )SlotAvail1Reg.x.N_33CONV;
+		shpc_context->max_speed_mode = SHPC_BUS_CONV_33;
+	}
+
+	if( shpc_context->number_of_slots ) {
+		//
+		// Be sure NSI field is not exceeded (this should not happen!)
+		//
+		if( shpc_context->number_of_slots > SlotConfigReg.x.NSI ) {
+			shpc_context->number_of_slots = ( u8 )SlotConfigReg.x.NSI;
+		}
+
+		//
+		// Limit slot count to what we're prepared to support
+		//
+		if( shpc_context->number_of_slots > SHPC_MAX_NUM_SLOTS ) {
+			shpc_context->number_of_slots = SHPC_MAX_NUM_SLOTS;
+		}
+
+		//
+		// Get current Bus speed/mode
+		//
+		shpc_context->bus_speed_mode = hp_get_bus_speed_mode( shpc_context );
+
+		//
+		// Initialize slot state based on HW disposition
+		//
+		for( i=0; i< shpc_context->number_of_slots; ++i ) {
+			slot_context = &shpc_context->slot_context[ i ];
+
+			//
+			// Get Physical Slot Number (PSN-based)
+			//
+			if( SlotConfigReg.x.PSN_UP ) {
+				slot_context->slot_psn = ( u8 )SlotConfigReg.x.PSN + i;
+			}
+			else {
+				slot_context->slot_psn = ( u8 )SlotConfigReg.x.PSN - i;
+			}
+
+			//
+			// Assign Logical Slot Number (1-based)
+			//
+			slot_context->slot_number = ( u8 )i+1;
+
+			//
+			// Get Card's speed/mode capabilities
+			//
+			hp_get_card_speed_mode( slot_context );
+
+			//
+			// Check current HW state
+			//
+			logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr );
+
+			//
+			// Already enabled: Card Present, MRL closed, Slot Enabled, No Power-Fault?
+			//
+			if( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY &&
+				( logical_slot_reg.x.MRLS_IM == SHPC_MASKED ||
+				logical_slot_reg.x.MRLS == SHPC_MRL_CLOSED ) &&
+				logical_slot_reg.x.PF == SHPC_STATUS_CLEARED &&
+				logical_slot_reg.x.S_STATE == SHPC_ENABLE_SLOT ) {
+				//
+				// Treat it as a SUCCESSFUL "Slot Enabled" HW-initiated request
+				//
+				slot_context->slot_completion.hw_initiated = TRUE;
+				slot_context->slot_completion.type = SHPC_ASYNC_ENABLE_SLOT;
+				slot_context->slot_completion.failed = HP_FALSE;
+				slot_context->slot_completion.request_context = NULL;
+				slot_context->slot_completion.done = TRUE;
+
+				//
+				// Flag as "Slot Enabled"
+				//
+				++shpc_context->slots_enabled;
+				slot_context->slot_enabled = TRUE;
+				slot_context->in_bus_speed_mode_contention = TRUE;
+				if( logical_slot_reg.x.PIS == SHPC_LED_ON ) {
+					slot_context->slot_function = (SLOT_STATE_FUNCTION) hp_at_slot_enabled_wait_for_slot_request;
+				}
+				else {
+					slot_context->slot_function = (SLOT_STATE_FUNCTION) hp_to_slot_enabled_wait_for_led_cmd_available;
+				}
+			}
+			else {
+				//
+				// Treat it as a SUCCESSFUL "Slot Disable" HW-initiated request
+				//
+				slot_context->slot_completion.hw_initiated = TRUE;
+				slot_context->slot_completion.type = SHPC_ASYNC_DISABLE_SLOT;
+				slot_context->slot_completion.failed = HP_FALSE;
+				slot_context->slot_completion.request_context = NULL;
+				slot_context->slot_completion.done = TRUE;
+
+				//
+				// Flag as "Slot Disabled"
+				//
+				slot_context->slot_enabled = FALSE;
+				slot_context->in_bus_speed_mode_contention = FALSE;
+				if( logical_slot_reg.x.S_STATE == SHPC_DISABLE_SLOT ) {
+					slot_context->slot_function = (SLOT_STATE_FUNCTION) hp_at_slot_disabled_wait_for_slot_request;
+				}
+				else {
+					slot_context->slot_function = (SLOT_STATE_FUNCTION) hp_to_slot_disabled_wait_for_disable_cmd_available;
+				}
+			}
+
+			//
+			// Set Attention LED function
+			//
+			if( logical_slot_reg.x.PF == SHPC_STATUS_SET ) {
+				//
+				// Turn it ON
+				//
+				slot_context->problem_detected = TRUE;
+				slot_context->attn_led_function = (SLOT_STATE_FUNCTION) hp_wait_for_attn_led_back_to_normal_cmd_available;
+			}
+			else {
+				//
+				// Make sure it is turned OFF
+				//
+				slot_context->problem_detected = FALSE;
+				if( logical_slot_reg.x.AIS == SHPC_LED_OFF ) {
+					slot_context->attn_led_function = (SLOT_STATE_FUNCTION) hp_wait_for_attn_led_request;
+				}
+				else {
+					slot_context->attn_led_function = (SLOT_STATE_FUNCTION) hp_wait_for_attn_led_back_to_normal_cmd_available;
+				}
+			}
+		}
+
+		//
+		// Enabled slots running at maximum speed/mode?
+		//
+		if( shpc_context->slots_enabled ) {
+			max_speed_mode = hp_get_max_speed_mode( shpc_context, shpc_context->max_speed_mode );
+
+			//
+			// Signal enabled slots to release the bus, then change bus speed/mode
+			//
+			if( shpc_context->bus_speed_mode != max_speed_mode ) {
+				hp_signal_enabled_slots_to_rebalance_bus( shpc_context );
+			}
+		}
+	}
+}
+
+
+// ****************************************************************************
+//
+// hp_enable_slot_interrupts() @ Any IRQL
+//
+// ****************************************************************************
+void
+hp_enable_slot_interrupts(
+	struct slot_context* slot_context
+)
+{
+	struct shpc_context* shpc_context = ( struct shpc_context* )slot_context->shpc_context;
+	union SHPC_SLOT_CONFIG_DWREG SlotConfigReg;
+	union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg;
+
+	//
+	// Get HW implementation: Attention Button, MRL Sensor
+	//
+	SlotConfigReg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SLOT_CONFIG_REG_OFFSET);
+
+	//
+	// Attention Button: Enabled only if implemented
+	//
+	logical_slot_reg.x.AB_IM = ( SlotConfigReg.x.ABI == SHPC_STATUS_SET ) ?
+		SHPC_UNMASKED : SHPC_MASKED;
+	logical_slot_reg.x.ABP_STS = SHPC_STATUS_SET;
+
+	//
+	// MRL Sensor: Enabled only if implemented (System Error Disabled)
+	//
+	logical_slot_reg.x.MRLS_IM = ( SlotConfigReg.x.MRLSI == SHPC_STATUS_SET ) ?
+		SHPC_UNMASKED : SHPC_MASKED;
+	logical_slot_reg.x.MRLS_SERRM = SHPC_MASKED;
+	logical_slot_reg.x.MRLSC_STS = SHPC_STATUS_SET;
+
+	//
+	// Card Presence: Enabled
+	//
+	logical_slot_reg.x.CP_IM = SHPC_UNMASKED;
+	logical_slot_reg.x.CPC_STS = SHPC_STATUS_SET;
+
+	//
+	// Isolated Power-Fault: Enabled
+	//
+	logical_slot_reg.x.IPF_IM = SHPC_UNMASKED;
+	logical_slot_reg.x.IPF_STS = SHPC_STATUS_SET;
+
+	//
+	// Connected Power-Fault: Enabled (System Error Disabled)
+	//
+	logical_slot_reg.x.CPF_IM = SHPC_UNMASKED;
+	logical_slot_reg.x.CPF_SERRM = SHPC_MASKED;
+	logical_slot_reg.x.CPF_STS = SHPC_STATUS_SET;
+
+	//
+	// Update Mask and Status bits
+	//
+	writel(logical_slot_reg.AsDWord, slot_context->logical_slot_addr);
+}
+
+
+// ****************************************************************************
+//
+// hp_disable_slot_interrupts() @ Any IRQL
+//
+// ****************************************************************************
+void
+hp_disable_slot_interrupts(
+	struct slot_context* slot_context
+)
+{
+	union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg;
+
+	//
+	// Get HW implementation: Attention Button, MRL Sensor
+	//
+	logical_slot_reg.AsDWord = readl(slot_context->logical_slot_addr);
+
+	//
+	// Attention Button: Disabled
+	//
+	logical_slot_reg.x.AB_IM = SHPC_MASKED;
+	logical_slot_reg.x.ABP_STS = SHPC_STATUS_SET;
+
+	//
+	// MRL Sensor: Disabled
+	//
+	logical_slot_reg.x.MRLS_IM = SHPC_MASKED;
+	logical_slot_reg.x.MRLS_SERRM = SHPC_MASKED;
+	logical_slot_reg.x.MRLSC_STS = SHPC_STATUS_SET;
+
+	//
+	// Card Presence: Disabled
+	//
+	logical_slot_reg.x.CP_IM = SHPC_MASKED;
+	logical_slot_reg.x.CPC_STS = SHPC_STATUS_SET;
+
+	//
+	// Isolated Power-Fault: Disabled
+	//
+	logical_slot_reg.x.IPF_IM = SHPC_MASKED;
+	logical_slot_reg.x.IPF_STS = SHPC_STATUS_SET;
+
+	//
+	// Connected Power-Fault: Enabled (System Error Disabled)
+	//
+	logical_slot_reg.x.CPF_IM = SHPC_MASKED;
+	logical_slot_reg.x.CPF_SERRM = SHPC_MASKED;
+	logical_slot_reg.x.CPF_STS = SHPC_STATUS_SET;
+
+	//
+	// Update Mask and Status bits
+	//
+	writel(logical_slot_reg.AsDWord, slot_context->logical_slot_addr);
+}
+
+
+// ****************************************************************************
+//
+// hp_enable_global_interrupts() @ Any IRQL
+//
+// ****************************************************************************
+void
+hp_enable_global_interrupts(
+	struct shpc_context* shpc_context
+)
+{
+	union SHPC_SERR_INT_DWREG SerrIntReg;
+
+	SerrIntReg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SERR_INT_REG_OFFSET);
+
+	//
+	// Arbiter timeout: System Error Disabled
+	//
+	SerrIntReg.x.A_SERRM = SHPC_MASKED;
+	SerrIntReg.x.ATOUT_STS = SHPC_STATUS_SET;
+
+	//
+	// Command Completion: Enabled
+	//
+	SerrIntReg.x.CC_IM = SHPC_UNMASKED;
+	SerrIntReg.x.CC_STS = SHPC_STATUS_SET;
+
+	//
+	// Global: Interrputs Enabled, System Error Disabled
+	//
+	SerrIntReg.x.GIM = SHPC_UNMASKED;
+	SerrIntReg.x.GSERRM = SHPC_MASKED;
+
+	//
+	// Update Mask and Status bits
+	//
+	writel(SerrIntReg.AsDWord, shpc_context->mmio_base_addr + SHPC_SERR_INT_REG_OFFSET);
+}
+
+
+// ****************************************************************************
+//
+// hp_disable_global_interrupts() @ Any IRQL
+//
+// ****************************************************************************
+void
+hp_disable_global_interrupts(
+	struct shpc_context* shpc_context
+)
+{
+	union SHPC_SERR_INT_DWREG SerrIntReg;
+
+	SerrIntReg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SERR_INT_REG_OFFSET);
+	//
+	// Arbiter timeout: System Error Disabled
+	//
+	SerrIntReg.x.A_SERRM = SHPC_MASKED;
+	SerrIntReg.x.ATOUT_STS = SHPC_STATUS_SET;
+
+	//
+	// Command Completion: Disabled
+	//
+	SerrIntReg.x.CC_IM = SHPC_MASKED;
+	SerrIntReg.x.CC_STS = SHPC_STATUS_SET;
+
+	//
+	// Global: Interrputs Disabled, System Error Disabled
+	//
+	SerrIntReg.x.GIM = SHPC_MASKED;
+	SerrIntReg.x.GSERRM = SHPC_MASKED;
+
+	//
+	// Update Mask and Status bits
+	//
+	writel(SerrIntReg.AsDWord, shpc_context->mmio_base_addr + SHPC_SERR_INT_REG_OFFSET);
+}
+
+
+// ****************************************************************************
+//
+// hp_get_card_speed_mode() @ Any IRQL
+//
+// ****************************************************************************
+enum shpc_speed_mode
+hp_get_card_speed_mode(
+	struct slot_context* slot_context
+)
+{
+	union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg;
+
+	//
+	// Slot powered-up?
+	//
+	logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr );
+	if(( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY ) &&
+		( logical_slot_reg.x.S_STATE == SHPC_POWER_ONLY ||
+		logical_slot_reg.x.S_STATE == SHPC_ENABLE_SLOT )) {
+		//
+		// Get Card's maximum speed/mode
+		//
+		if( logical_slot_reg.x.PCIX_CAP == SHPC_SLOT_PCIX_133 ) {
+			slot_context->card_speed_mode = SHPC_BUS_PCIX_133;
+		}
+		else if( logical_slot_reg.x.PCIX_CAP == SHPC_SLOT_PCIX_66 ) {
+			slot_context->card_speed_mode = SHPC_BUS_PCIX_66;
+		}
+		else if( logical_slot_reg.x.M66_CAP == SHPC_STATUS_SET ) {
+			slot_context->card_speed_mode = SHPC_BUS_CONV_66;
+		}
+		else {
+			slot_context->card_speed_mode = SHPC_BUS_CONV_33;
+		}
+
+		//
+		// Get Card's PCI-66 capability
+		//
+		if( logical_slot_reg.x.M66_CAP == SHPC_STATUS_SET ) {
+			slot_context->card_pci66_capable = TRUE;
+		}
+	}
+	else {
+		//
+		// Slot is not powered-up, use PCI-33 as default
+		//
+		slot_context->card_speed_mode = SHPC_BUS_CONV_33;
+		slot_context->card_pci66_capable = FALSE;
+	}
+
+	return slot_context->card_speed_mode;
+}
+
+// ****************************************************************************
+//
+// hp_get_bus_speed_mode() @ Any IRQL
+//
+// ****************************************************************************
+enum shpc_speed_mode
+hp_get_bus_speed_mode(
+	struct shpc_context* shpc_context
+)
+{
+	union SHPC_SEC_BUS_CONFIG_DWREG bus_config_reg;
+	enum shpc_speed_mode bus_speed_mode;
+
+	bus_config_reg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SEC_BUS_CONFIG_REG_OFFSET);
+
+	bus_speed_mode = ( enum shpc_speed_mode )bus_config_reg.x.MODE;
+	if( bus_speed_mode > SHPC_BUS_PCIX_133 ) {
+		bus_speed_mode = SHPC_BUS_CONV_33;
+	}
+
+	return bus_speed_mode;
+}
+
+
+// ****************************************************************************
+//
+// hp_translate_speed_mode() @ Any IRQL
+//
+// ****************************************************************************
+enum mode_frequency
+hp_translate_speed_mode(
+	enum shpc_speed_mode shpc_speed_mode
+)
+{
+	enum mode_frequency translated_speed_mode;
+
+	switch( shpc_speed_mode ) {
+	case SHPC_BUS_PCIX_133:
+		translated_speed_mode = MODE_PCIX_133;
+		break;
+
+	case SHPC_BUS_PCIX_100:
+		translated_speed_mode = MODE_PCIX_100;
+		break;
+
+	case SHPC_BUS_PCIX_66:
+		translated_speed_mode = MODE_PCIX_66;
+		break;
+
+	case SHPC_BUS_CONV_66:
+		translated_speed_mode = MODE_PCI_66;
+		break;
+
+	case SHPC_BUS_CONV_33:
+	default:
+		translated_speed_mode = MODE_PCI_33;
+		break;
+	}
+
+	return translated_speed_mode;
+}
+
+
+// ****************************************************************************
+//
+// hp_translate_card_power() @ Any IRQL
+//
+// ****************************************************************************
+enum hp_power_requirements
+hp_translate_card_power(
+	enum shpc_card_power ShpcCardPower
+)
+{
+	enum hp_states TranslatedCardPower;
+
+	switch( ShpcCardPower ) {
+	case SHPC_CARD_PRESENT_25W:
+		TranslatedCardPower = POWER_HIGH;
+		break;
+
+	case SHPC_CARD_PRESENT_15W:
+		TranslatedCardPower = POWER_MEDIUM;
+		break;
+
+	case SHPC_CARD_PRESENT_7_5W:
+	default:
+		TranslatedCardPower = POWER_LOW;
+		break;
+	}
+
+	return TranslatedCardPower;
+}
+
+
+// ****************************************************************************
+//
+// hp_translate_indicator() @ Any IRQL
+//
+// ****************************************************************************
+enum hp_indicators
+hp_translate_indicator(
+	enum shpc_slot_led ShpcIndicator
+)
+{
+	enum hp_indicators TranslatedIndicator;
+
+	switch( ShpcIndicator ) {
+	case SHPC_LED_ON:
+		TranslatedIndicator = INDICATOR_ON;
+		break;
+
+	case SHPC_LED_BLINK:
+		TranslatedIndicator = INDICATOR_BLINK;
+		break;
+
+	case SHPC_LED_OFF:
+	default:
+		TranslatedIndicator =INDICATOR_OFF;
+		break;
+	}
+
+	return TranslatedIndicator;
+}
+
+
+// ****************************************************************************
+//
+// hp_flag_slot_as_enabled() @ <= DISPATCH_LEVEL
+//
+// ****************************************************************************
+u8
+hp_flag_slot_as_enabled(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+)
+{
+	unsigned long		old_irq_flags;
+	u8 SlotFlagged = FALSE;
+
+	spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+	if( !slot_context->slot_enabled ) {
+		//
+		// Slot just coming on-line
+		//
+		SlotFlagged = TRUE;
+		++shpc_context->slots_enabled;
+		slot_context->slot_enabled = TRUE;
+		hp_clear_shpc_event_bit(shpc_context, BUS_REBALANCE_EVENT);
+	}
+	spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+	return SlotFlagged;
+}
+
+
+// ****************************************************************************
+//
+// hp_flag_slot_as_disabled() @ <= DISPATCH_LEVEL
+//
+// ****************************************************************************
+u8
+hp_flag_slot_as_disabled(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+)
+{
+	unsigned long		old_irq_flags;
+	u8 SlotFlagged = FALSE;
+
+	spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+	if( slot_context->slot_enabled ) {
+		if( --shpc_context->slots_enabled == 0 ) {
+			//
+			// This was the last enabled slot, signal waiting thread that bus is released,
+			//
+			shpc_context->bus_released = TRUE;
+			hp_send_event_to_all_slots(shpc_context, BUS_COMPLETE_EVENT);
+		}
+		SlotFlagged = TRUE;
+		slot_context->slot_enabled = FALSE;
+	}
+	spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+	return SlotFlagged;
+}
+
+
+// ****************************************************************************
+//
+// hp_signal_enabled_slots_to_rebalance_bus() @ <= DISPATCH_LEVEL
+//
+// Comments:
+//	Assumes shpc_spinlock is already held.
+//
+// ****************************************************************************
+u8
+hp_signal_enabled_slots_to_rebalance_bus(
+	struct shpc_context* shpc_context
+)
+{
+	struct slot_context* SlotArray[ SHPC_MAX_NUM_SLOTS ];
+	struct slot_context* Slot;
+	u8 i, j, n;
+
+	//
+	// Initialize array of slot pointers
+	//
+	n = shpc_context->number_of_slots;
+	for( i=0, j=0; i<n; ++i ) {
+		Slot = &shpc_context->slot_context[ i ];
+		if( Slot->slot_enabled ) {
+			SlotArray[ j++ ] = Slot;
+		}
+	}
+	//
+	// Found slots enabled?
+	//
+	if( j ) {
+		//
+		// Bubble-sort enabled slots in order of increasing card speed/mode
+		//
+		n = j;
+		for( i=0; i<n-1; i++ ) {
+			for( j=0; j<n-1-i; j++ ) {
+				if( SlotArray[ j+1 ]->card_speed_mode < SlotArray[ j ]->card_speed_mode ) {
+					Slot = SlotArray[ j ];
+					SlotArray[ j ] = SlotArray[ j+1 ];
+					SlotArray[ j+1 ] = Slot;
+				}
+			}
+		}
+		//
+		// Signal enabled slots in sorted order as an attempt to re-enable slower cards first
+		//
+		hp_set_shpc_event_bit(shpc_context, BUS_REBALANCE_EVENT);
+		for( i=0; i<n; i++ ) {
+			wake_up_interruptible( &SlotArray[ i ]->slot_event);
+		}
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+
+// ****************************************************************************
+//
+// hp_get_max_speed_mode() @ <= DISPATCH_LEVEL
+//
+// Comments:
+//	Assumes shpc_spinlock is already held.
+//
+// ****************************************************************************
+enum shpc_speed_mode
+hp_get_max_speed_mode(
+	struct shpc_context* shpc_context,
+	enum shpc_speed_mode From_speed_mode
+)
+{
+	struct slot_context* slot_context;
+	enum shpc_speed_mode max_speed_mode;
+	u8 i;
+
+	max_speed_mode = From_speed_mode;
+	for( i=0; i< shpc_context->number_of_slots; ++i ) {
+		slot_context = &shpc_context->slot_context[ i ];
+		if( slot_context->in_bus_speed_mode_contention &&
+			slot_context->card_speed_mode < max_speed_mode ) {
+			//
+			// Can only go as fast as the slowest card
+			//
+			max_speed_mode = slot_context->card_speed_mode;
+		}
+	}
+
+	//
+	// Make sure all cards support conventional PCI-66 speed/mode
+	//
+	if( max_speed_mode == SHPC_BUS_CONV_66 ) {
+		for( i=0; i< shpc_context->number_of_slots; ++i ) {
+			slot_context = &shpc_context->slot_context[ i ];
+			if( slot_context->in_bus_speed_mode_contention &&
+				!slot_context->card_pci66_capable ) {
+				//
+				// Fall back to slower common denominator
+				//
+				max_speed_mode = SHPC_BUS_CONV_33;
+			}
+		}
+	}
+
+	return max_speed_mode;
+}
+
+
+// ****************************************************************************
+//
+// hp_signal_user_event() @ <= DISPATCH_LEVEL
+//
+// ****************************************************************************
+void hp_signal_user_event(struct shpc_context* shpc_context)
+{
+	unsigned long		old_irq_flags;
+return;
+	spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+	if( shpc_context->user_event_pointer ) {
+		wake_up_interruptible( shpc_context->user_event_pointer);
+	}
+	spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+}
+
+
+// ****************************************************************************
+//
+// hp_signal_user_event_at_dpc_level() @ DISPATCH_LEVEL
+//
+// ****************************************************************************
+void hp_signal_user_event_at_dpc_level(struct shpc_context* shpc_context)
+{
+return;
+	spin_lock_bh( &shpc_context->shpc_spinlock );
+	if( shpc_context->user_event_pointer ) {
+		wake_up_interruptible( shpc_context->user_event_pointer);
+	}
+	spin_unlock_bh( &shpc_context->shpc_spinlock );
+}
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/amdshpc_ddi.c	Wed Mar 17 11:19:43 2004
@@ -0,0 +1,1660 @@
+/*
+ * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001,2003 IBM Corp.
+ * Copyright (C) 2002-2003 Advanced Micro Devices
+ *
+ * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS
+ * AND CONDITIONS OF THE GNU GENERAL PUBLIC
+ * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS
+ * INCLUDED WITH THIS FILE AND POSTED AT
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ *
+ * Send feedback to <david.keck@amd.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include "amdshpc_ddi.h"
+#include "amdshpc.h"
+
+static unsigned long async_callback (void* driver_context,
+					 u8 slot_number,
+					 enum shpc_async_request async_request,
+					 union SLOT_STATUS_INFO slot_tatus,
+					 void* request_context );
+
+// ****************************************************************************
+//
+// hp_AddDevice() 
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data (per hardware-instance).
+//	driver_context - Caller provided pointer to be returned upon completion.
+//	Callback - Caller provided function to be called upon completion of async requests.
+//  shpc_instance - Zero-based hardware instance.
+//
+// Return Value
+//  Status returned by any system calls made within hp_AddDevice().
+//
+// ****************************************************************************
+long
+hp_AddDevice(
+	struct shpc_context* shpc_context,
+	void* driver_context,
+	SHPC_ASYNC_CALLBACK Callback,
+	unsigned long shpc_instance
+	)
+
+{
+	struct slot_context* slot_context;
+	u8 i;
+	DECLARE_TASKLET(mrl_sensor_dpc0, hp_mrl_sensor_dpc, (unsigned long) &shpc_context->slot_context[0] );
+	DECLARE_TASKLET(attn_button_dpc0, hp_attn_button_dpc, (unsigned long) &shpc_context->slot_context[0]);
+	DECLARE_TASKLET(card_presence_dpc0, hp_card_presence_dpc, (unsigned long) &shpc_context->slot_context[0]);
+	DECLARE_TASKLET(isolated_power_fault_dpc0, hp_isolated_power_fault_dpc, (unsigned long) &shpc_context->slot_context[0]);
+	DECLARE_TASKLET(connected_power_fault_dpc0, hp_connected_power_fault_dpc, (unsigned long) &shpc_context->slot_context[0]);
+
+	DECLARE_TASKLET(mrl_sensor_dpc1, hp_mrl_sensor_dpc, (unsigned long) &shpc_context->slot_context[1] );
+	DECLARE_TASKLET(attn_button_dpc1, hp_attn_button_dpc, (unsigned long) &shpc_context->slot_context[1]);
+	DECLARE_TASKLET(card_presence_dpc1, hp_card_presence_dpc, (unsigned long) &shpc_context->slot_context[1]);
+	DECLARE_TASKLET(isolated_power_fault_dpc1, hp_isolated_power_fault_dpc, (unsigned long) &shpc_context->slot_context[1]);
+	DECLARE_TASKLET(connected_power_fault_dpc1, hp_connected_power_fault_dpc, (unsigned long) &shpc_context->slot_context[1]);
+
+	DECLARE_TASKLET(mrl_sensor_dpc2, hp_mrl_sensor_dpc, (unsigned long) &shpc_context->slot_context[2] );
+	DECLARE_TASKLET(attn_button_dpc2, hp_attn_button_dpc, (unsigned long) &shpc_context->slot_context[2]);
+	DECLARE_TASKLET(card_presence_dpc2, hp_card_presence_dpc, (unsigned long) &shpc_context->slot_context[2]);
+	DECLARE_TASKLET(isolated_power_fault_dpc2, hp_isolated_power_fault_dpc, (unsigned long) &shpc_context->slot_context[2]);
+	DECLARE_TASKLET(connected_power_fault_dpc2, hp_connected_power_fault_dpc, (unsigned long) &shpc_context->slot_context[2]);
+
+	DECLARE_TASKLET(mrl_sensor_dpc3, hp_mrl_sensor_dpc, (unsigned long) &shpc_context->slot_context[3] );
+	DECLARE_TASKLET(attn_button_dpc3, hp_attn_button_dpc, (unsigned long) &shpc_context->slot_context[3]);
+	DECLARE_TASKLET(card_presence_dpc3, hp_card_presence_dpc, (unsigned long) &shpc_context->slot_context[3]);
+	DECLARE_TASKLET(isolated_power_fault_dpc3, hp_isolated_power_fault_dpc, (unsigned long) &shpc_context->slot_context[3]);
+	DECLARE_TASKLET(connected_power_fault_dpc3, hp_connected_power_fault_dpc, (unsigned long) &shpc_context->slot_context[3]);
+
+
+	DECLARE_TASKLET(cmd_completion_dpc, hp_cmd_completion_dpc, (unsigned long) shpc_context );
+
+	//
+	// Init common resources
+	//
+	shpc_context->cmd_completion_dpc = cmd_completion_dpc;
+	shpc_context->driver_context = driver_context;
+	shpc_context->async_callback = (SHPC_ASYNC_CALLBACK)async_callback;
+	shpc_context->shpc_instance = shpc_instance;
+	shpc_context->slots_enabled = 0;
+	shpc_context->number_of_slots = 0;
+	shpc_context->at_power_device_d0 = FALSE;
+	shpc_context->bus_released = FALSE;
+	shpc_context->user_event_pointer = NULL;
+	spin_lock_init( &shpc_context->shpc_spinlock );
+	sema_init( &shpc_context->cmd_available_mutex, 1);
+	sema_init( &shpc_context->bus_available_mutex, 1);
+	sema_init( &shpc_context->shpc_event_bits_semaphore, 1);
+
+	shpc_context->shpc_event_bits=0;	// all shpc events cleared
+
+	dbg("%s -->HwInstance[ %d ]", __FUNCTION__ ,shpc_context->shpc_instance );
+
+	//
+	// Init slot resources
+	//
+	for( i=0; i< SHPC_MAX_NUM_SLOTS; ++i ) {
+		slot_context = &shpc_context->slot_context[ i ];
+		slot_context->shpc_context = ( void* )shpc_context;
+		slot_context->slot_number = ( u8 )i+1;
+		slot_context->slot_enabled = FALSE;
+		slot_context->in_bus_speed_mode_contention = FALSE;
+		slot_context->problem_detected = FALSE;
+		slot_context->slot_quiesced = FALSE;
+		slot_context->slot_thread = NULL;
+		slot_context->slot_function = NULL;
+		slot_context->attn_led_thread = NULL;
+		slot_context->attn_led_function = NULL;
+
+		//
+		// Slot SpinLocks and semaphores
+		//
+		spin_lock_init( &slot_context->slot_spinlock);
+		sema_init(&slot_context->slot_event_bits_semaphore, 1);
+		sema_init(&slot_context->cmd_acquire_mutex, 1);
+		sema_init(&slot_context->bus_acquire_mutex, 1);
+
+		//
+		// Slot timers
+		//
+		init_timer(&slot_context->slot_timer1);
+		init_timer(&slot_context->slot_timer2);
+		init_timer(&slot_context->slot_timer3);
+		init_timer(&slot_context->slot_timer4);
+		init_timer(&slot_context->slot_timer5);
+		init_timer(&slot_context->slot_timer6);
+		init_timer(&slot_context->slot_timer7);
+		init_timer(&slot_context->slot_timer8);
+		init_timer(&slot_context->slot_timer9);
+		init_timer(&slot_context->slot_timer10);
+		init_timer(&slot_context->led_timer1);
+		init_timer(&slot_context->led_timer2);
+		init_timer(&slot_context->led_timer3);
+		init_timer(&slot_context->led_timer4);
+
+		//
+		// Interrupt Service
+		//
+		switch (i) {
+		case 0:
+			slot_context->attn_button_dpc           = attn_button_dpc0;
+			slot_context->mrl_sensor_dpc            = mrl_sensor_dpc0;
+			slot_context->card_presence_dpc         = card_presence_dpc0;
+			slot_context->isolated_power_fault_dpc  = isolated_power_fault_dpc0;
+			slot_context->connected_power_fault_dpc = connected_power_fault_dpc0;
+			break;
+		case 1:
+			slot_context->attn_button_dpc           = attn_button_dpc1;
+			slot_context->mrl_sensor_dpc            = mrl_sensor_dpc1;
+			slot_context->card_presence_dpc         = card_presence_dpc1;
+			slot_context->isolated_power_fault_dpc  = isolated_power_fault_dpc1;
+			slot_context->connected_power_fault_dpc = connected_power_fault_dpc1;
+			break;
+		case 2:
+			slot_context->attn_button_dpc           = attn_button_dpc2;
+			slot_context->mrl_sensor_dpc            = mrl_sensor_dpc2;
+			slot_context->card_presence_dpc         = card_presence_dpc2;
+			slot_context->isolated_power_fault_dpc  = isolated_power_fault_dpc2;
+			slot_context->connected_power_fault_dpc = connected_power_fault_dpc2;
+			break;
+		case 3:
+			slot_context->attn_button_dpc           = attn_button_dpc3;
+			slot_context->mrl_sensor_dpc            = mrl_sensor_dpc3;
+			slot_context->card_presence_dpc         = card_presence_dpc3;
+			slot_context->isolated_power_fault_dpc  = isolated_power_fault_dpc3;
+			slot_context->connected_power_fault_dpc = connected_power_fault_dpc3;
+			break;
+		}
+
+
+		//
+		// Slot Events
+		//
+		slot_context->slot_event_bits=0;	// all slot events cleared
+
+		dbg("%s -->Init slot wait queues",__FUNCTION__ );
+
+		init_waitqueue_head(&slot_context->slot_event);
+		init_waitqueue_head(&slot_context->led_cmd_acquire_event);
+		init_waitqueue_head(&slot_context->led_cmd_release_event);
+		init_waitqueue_head(&slot_context->cmd_acquire_event);
+		init_waitqueue_head(&slot_context->cmd_release_event);
+		init_waitqueue_head(&slot_context->bus_acquire_event);
+		init_waitqueue_head(&slot_context->bus_release_event);
+	}
+	return STATUS_SUCCESS;
+}
+
+
+// ****************************************************************************
+//
+// hp_StartDevice()
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//  Status returned by any system calls made within hp_StartDevice().
+//
+//
+// ****************************************************************************
+long
+hp_StartDevice(
+	struct shpc_context* shpc_context
+	)
+{
+	struct slot_context* slot_context;
+	long status = STATUS_SUCCESS;
+	u32 *logical_slot_addr;
+	u8 i;
+	int pid;
+
+	dbg("%s -->From hp_StartDevice:  MmioBase[ %p ]",__FUNCTION__ , (unsigned long*)shpc_context->mmio_base_addr);
+
+	//
+	// Disable Global Interrupts
+	//
+	dbg("%s -->hp_disable_global_interrupts( shpc_context=%p );",__FUNCTION__ , shpc_context);
+	hp_disable_global_interrupts( shpc_context );
+
+	//
+	// Reset common resources
+	//
+	shpc_context->at_power_device_d0 = TRUE;
+	shpc_context->bus_released = FALSE;
+
+	//
+	// Reset slot resources
+	//
+	logical_slot_addr = shpc_context->mmio_base_addr + SHPC_LOGICAL_SLOT_REG_OFFSET;
+	for( i=0; i< SHPC_MAX_NUM_SLOTS; ++i ) {
+		slot_context = &shpc_context->slot_context[ i ];
+
+		//
+		// Assign Logical Slot Register Address
+		//
+		slot_context->logical_slot_addr = logical_slot_addr++;
+
+		//
+		// Disable Slot Interrupts
+		//
+		dbg("%s -->hp_disable_slot_interrupts(slot_context)=%p",__FUNCTION__ , slot_context);
+		hp_disable_slot_interrupts(slot_context);
+
+		//
+		// Reset slot flags and pointers
+		//
+		slot_context->slot_enabled = FALSE;
+		slot_context->in_bus_speed_mode_contention = FALSE;
+		slot_context->problem_detected = FALSE;
+		slot_context->slot_quiesced = FALSE;
+		slot_context->slot_thread = NULL;
+		slot_context->slot_function = NULL;
+		slot_context->attn_led_thread = NULL;
+		slot_context->attn_led_function = NULL;
+		slot_context->slot_occupied = 0;
+	}
+
+	//
+	// Get initial slot configuration: number_of_slots, slots_enabled, SlotStateFunction
+	//
+	shpc_context->slots_enabled = 0;
+	shpc_context->number_of_slots = 0;
+	hp_get_slot_configuration( shpc_context );
+	dbg("%s -->from hp_StartDevice() number_of_slots = %d", __FUNCTION__ ,shpc_context->number_of_slots);
+	if( shpc_context->number_of_slots == 0 ) {
+		status = STATUS_UNSUCCESSFUL;
+	}
+
+	//
+	//  Hook Interrupt
+	//
+	dbg("%s -->HPC interrupt = %d \n", __FUNCTION__ ,shpc_context->interrupt);
+
+	if (request_irq(shpc_context->interrupt, hp_interrupt_service, SA_SHIRQ, MY_NAME, shpc_context)) {
+		err("Can't get irq %d for the PCI hotplug controller\n", shpc_context->interrupt);
+		status = STATUS_UNSUCCESSFUL;
+		return(status);
+	}
+
+	//
+	// Set slot operation in motion
+	//
+	for( i=0; i<shpc_context->number_of_slots && status; ++i ) {
+
+		slot_context = &shpc_context->slot_context[ i ];
+
+		//
+		// Launch slot command and bus completion mutex threads
+		//
+		// get led cmd available thread
+		pid = kernel_thread(hp_get_led_cmd_available_mutex_thread, slot_context, CLONE_SIGHAND);
+		if (pid < 0) {
+			err ("Can't start up our get_led_cmd_available_mutex thread\n");
+			status = STATUS_UNSUCCESSFUL;
+		}
+		dbg("%s -->Our hp_get_led_cmd_available_mutex thread pid = %d",__FUNCTION__ , pid);
+
+		// get cmd available thread
+		pid = kernel_thread(hp_get_cmd_available_mutex_thread, slot_context, CLONE_SIGHAND);
+		if (pid < 0) {
+			err ("Can't start up our get_cmd_available_mutex thread\n");
+			status = STATUS_UNSUCCESSFUL;
+		}
+		dbg("%s -->Our hp_get_cmd_available_mutex thread pid = %d",__FUNCTION__ , pid);
+
+		// get bus available thread
+		pid = kernel_thread(hp_get_bus_available_mutex_thread, slot_context, CLONE_SIGHAND);
+		if (pid < 0) {
+			err ("Can't start up our get_bus_available_mutex thread\n");
+			status = STATUS_UNSUCCESSFUL;
+		}
+		dbg("%s \n\n\n-->Our get_bus_available_mutex thread pid = %d",__FUNCTION__ , pid);
+
+		//
+		// Launch slot thread
+		//
+		pid = kernel_thread(hp_slot_thread, slot_context, CLONE_SIGHAND);
+		if (pid < 0) {
+			err ("Can't start up our event thread\n");
+			status = STATUS_UNSUCCESSFUL;
+		}
+		dbg("%s -->Our slot event thread pid = %d\n",__FUNCTION__ , pid);
+
+		//
+		// Launch Attention LED Thread
+		//
+		pid = kernel_thread(hp_attn_led_thread, slot_context, CLONE_SIGHAND);
+		if (pid < 0) {
+			err ("Can't start up our event thread\n");
+			status = STATUS_UNSUCCESSFUL;
+		}
+		dbg("%s -->Our LED event thread pid = %d\n",__FUNCTION__ , pid);
+
+		//
+		// Enable Slot Interrupts: Attn Button, MRL Sensor, Card Presence, Power-Fault
+		//
+		if(status) {
+			dbg("%s -->hpStartDevice() Enabling slot interrupts...",__FUNCTION__ );
+			hp_enable_slot_interrupts( slot_context );
+		}
+	}
+
+	//
+	// Enable Global Interrupts: Command Completion
+	//
+	if(status) {
+		dbg("%s -->hpStartDevice() Enabling global interrupts...",__FUNCTION__ );
+		hp_enable_global_interrupts( shpc_context );
+	} else {
+		//
+		// Bail out, we're hosed!
+		//
+		hp_StopDevice( shpc_context );
+		status = STATUS_UNSUCCESSFUL;
+	}
+	dbg("%s -->status = %d\n",__FUNCTION__ , (u32)status);
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_StopDevice()
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//  Status returned by any system calls made within hp_StopDevice().
+//
+// Comments:
+//	The caller is responsible for unmapping mmio_base_addr, via MmUnmapIoSpace(),
+//  after calling hp_StopDevice() for resource re-balancing or device removal.
+//
+// ****************************************************************************
+long
+hp_StopDevice(
+	struct shpc_context* shpc_context
+	)
+{
+	struct slot_context* slot_context;
+	long status = STATUS_SUCCESS;
+	unsigned long	old_irq_flags;
+	u8 i;
+
+	//
+	// Already stopped or never started ?
+	//
+	if( shpc_context->mmio_base_addr == 0 ) {
+		return STATUS_UNSUCCESSFUL;
+	}
+	//
+	// Disable Global Interrupts
+	//
+	hp_disable_global_interrupts( shpc_context );
+
+	//
+	// Signal EXIT request to slot threads
+	//
+
+	spin_lock_irqsave(&shpc_context->shpc_spinlock, old_irq_flags);
+	hp_clear_shpc_event_bit(shpc_context, SUSPEND_EVENT);
+	hp_send_event_to_all_slots(shpc_context,
+				   RESUME_EVENT || REMOVE_EVENT || EXIT_REQUEST_EVENT);
+	spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+	for( i=0; i<SHPC_MAX_NUM_SLOTS; ++i ) {
+		slot_context = &shpc_context->slot_context[ i ];
+
+		//
+		// Disable Slot Interrupts
+		//
+		hp_disable_slot_interrupts( slot_context );
+
+		//
+		// Remove scheduled slot DPCs
+		//
+		tasklet_kill( &slot_context->attn_button_dpc );
+		tasklet_kill( &slot_context->card_presence_dpc );
+		tasklet_kill( &slot_context->isolated_power_fault_dpc );
+		tasklet_kill( &slot_context->connected_power_fault_dpc );
+
+		//
+		// Send events to kill all threads
+		//
+		//
+		// Set event bits to send to running threads
+		//
+		hp_set_shpc_event_bit(shpc_context,
+				      (RESUME_EVENT | REMOVE_EVENT | EXIT_REQUEST_EVENT));
+
+		
+		
+		wake_up_interruptible(&slot_context->led_cmd_acquire_event);
+		wake_up_interruptible(&slot_context->cmd_acquire_event);
+		wake_up_interruptible(&slot_context->bus_acquire_event);
+		wake_up_interruptible(&slot_context->led_cmd_release_event);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+		wake_up_interruptible(&slot_context->bus_release_event);
+		//
+		// Reset slot pointers and flags
+		//
+		slot_context->slot_enabled = FALSE;
+		slot_context->slot_thread = NULL;
+		slot_context->slot_function = NULL;
+		slot_context->attn_led_thread = NULL;
+		slot_context->attn_led_function = NULL;
+	}
+
+	//
+	// Remove scheduled common DPC
+	//
+	tasklet_kill(&shpc_context->cmd_completion_dpc );
+
+	//
+	// Reset common resources
+	//
+	shpc_context->number_of_slots = 0;
+	shpc_context->slots_enabled = 0;
+	shpc_context->at_power_device_d0 = FALSE;
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_SuspendDevice()
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//  Status returned by any system calls made within hp_SuspendDevice().
+//
+// Comments:
+//	hp_SuspendDevice() must be called before transitioning away from PowerDeviceD0.
+//
+// ****************************************************************************
+long
+hp_SuspendDevice(
+	struct shpc_context* shpc_context
+	)
+{
+	long status = STATUS_SUCCESS;
+	unsigned long	old_irq_flags;
+
+	dbg("%s -->HwInstance[ %d ]", __FUNCTION__ ,shpc_context->shpc_instance );
+
+	spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+
+	if(shpc_context->mmio_base_addr &&
+		(!shpc_context->shpc_event_bits & SUSPEND_EVENT) &&
+		(!shpc_context->shpc_event_bits & REMOVE_EVENT)) {
+		hp_clear_shpc_event_bit(shpc_context, RESUME_EVENT);
+
+		hp_send_event_to_all_slots(shpc_context, SUSPEND_EVENT);
+		hp_send_event_to_all_slots(shpc_context, EXIT_REQUEST_EVENT);
+
+		shpc_context->at_power_device_d0 = FALSE;
+	}
+	spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_ResumeDevice() 
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//  Status returned by any system calls made within hp_ResumeDevice().
+//
+// Comments:
+//	hp_SuspendDevice() must be called after transitioning back to PowerDeviceD0.
+//
+// ****************************************************************************
+long
+hp_ResumeDevice(
+	struct shpc_context* shpc_context
+	)
+{
+	long status = STATUS_SUCCESS;
+	unsigned long		old_irq_flags;
+
+	dbg("%s -->HwInstance[ %d ]", __FUNCTION__ ,shpc_context->shpc_instance );
+
+	spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+	if(shpc_context->mmio_base_addr &&
+		(shpc_context->shpc_event_bits & SUSPEND_EVENT) &&
+		(!shpc_context->shpc_event_bits & REMOVE_EVENT)) {
+		hp_clear_shpc_event_bit(shpc_context, SUSPEND_EVENT);
+		hp_clear_shpc_event_bit(shpc_context, EXIT_REQUEST_EVENT);
+		hp_send_event_to_all_slots(shpc_context, RESUME_EVENT);
+		shpc_context->at_power_device_d0 = TRUE;
+	}
+
+	spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_QuerySlots() 
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data.
+//	slot_config - Caller provided storage for slots configuration info.
+//
+// Return Value
+//  Status returned by any system calls made within hp_QuerySlots().
+//
+// ****************************************************************************
+long
+hp_QuerySlots(
+	struct shpc_context* shpc_context,
+	union SLOT_CONFIG_INFO* slot_config
+	)
+{
+	long status = STATUS_SUCCESS;
+	union SHPC_SLOT_CONFIG_DWREG slot_config_reg;
+
+	dbg("%s -->HwInstance[ %d ]  Slots[ %d ]",__FUNCTION__ ,
+		shpc_context->shpc_instance, shpc_context->number_of_slots );
+
+	//
+	// Get slot configuration
+	//
+	slot_config_reg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SLOT_CONFIG_REG_OFFSET);
+
+	slot_config->AsDWord = 0;
+	slot_config->x.lu_slots_implemented = slot_config_reg.x.NSI;
+	slot_config->x.lu_base_PSN = slot_config_reg.x.PSN;
+	slot_config->x.lu_PSN_up = slot_config_reg.x.PSN_UP;
+	slot_config->x.lu_base_FDN = slot_config_reg.x.FDN;
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_QuerySlotStatus()
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data.
+//	slot_id - Zero-based slot number (0..n-1).
+//	Query - Pointer to Slot Status Structure
+//
+// Return Value
+//  Status returned by any system calls made within hp_QuerySlotStatus().
+//
+// ****************************************************************************
+long
+hp_QuerySlotStatus(
+	struct shpc_context* shpc_context,
+	u8 slot_id,
+	union SLOT_STATUS_INFO* Query
+	)
+{
+	struct slot_context* slot_context;
+	long status = STATUS_SUCCESS;
+	union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_id );
+
+	//
+	// Valid slot_id?
+	//
+	if( slot_id >= shpc_context->number_of_slots ) {
+		status = STATUS_UNSUCCESSFUL;
+	}
+	else {
+		//
+		// Which slot?
+		//
+		slot_context = &shpc_context->slot_context[ slot_id ];
+
+		//
+		// Get Max Speed/Mode from common context
+		//
+		Query->x.lu_max_bus_mode_freq = hp_translate_speed_mode( shpc_context->max_speed_mode );
+
+		//
+		// Get Bus Speed/Mode from HW
+		//
+		Query->x.lu_bus_mode_freq = hp_translate_speed_mode( hp_get_bus_speed_mode( shpc_context ));
+
+		//
+		// Get Card Speed/Mode from HW
+		//
+		Query->x.lu_card_mode_freq_cap = hp_translate_speed_mode( hp_get_card_speed_mode( slot_context ));
+
+		//
+		// Get current slot info from HW
+		//
+		logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr );
+
+		//
+		// Card Present?
+		//
+		Query->x.lu_card_present = ( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY ) ?
+			HP_TRUE : HP_FALSE;
+
+		//
+		// Get Card PCI-66 capability
+		//
+		Query->x.lu_card_pci66_capable = (( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY ) &&
+			( logical_slot_reg.x.S_STATE == SHPC_POWER_ONLY || logical_slot_reg.x.S_STATE == SHPC_ENABLE_SLOT ) &&
+			( logical_slot_reg.x.M66_CAP == SHPC_STATUS_SET )) ?
+			HP_TRUE : HP_FALSE;
+
+		//
+		// Power-Fault?
+		//
+		Query->x.lu_power_fault = ( logical_slot_reg.x.PF == SHPC_STATUS_SET ) ?
+			HP_TRUE : HP_FALSE;
+
+		//
+		//  Card Power Requirements
+		//
+		Query->x.lu_card_power = hp_translate_card_power( logical_slot_reg.x.PRSNT1_2 );
+
+		//
+		//  Attention Indicator
+		//
+		Query->x.lu_ai_state = hp_translate_indicator( logical_slot_reg.x.AIS );
+
+		//
+		//  Power Indicator
+		//
+		Query->x.lu_pi_state = hp_translate_indicator( logical_slot_reg.x.PIS );
+
+		//
+		// MRL Implemented?
+		//
+		Query->x.lu_mrl_implemented = ( logical_slot_reg.x.MRLS_IM == SHPC_UNMASKED ) ?
+			HP_TRUE : HP_FALSE;
+
+		//
+		// MRL Opened?
+		//
+		Query->x.lu_mrl_opened = (( logical_slot_reg.x.MRLS == SHPC_MRL_OPEN ) &&
+			( logical_slot_reg.x.MRLS_IM == SHPC_UNMASKED )) ? HP_TRUE : HP_FALSE;
+
+		//
+		// Slot State: Card Present, MRL closed, No Power-Fault, Enabled?
+		//
+		if( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY &&
+			( logical_slot_reg.x.MRLS_IM == SHPC_MASKED ||
+			logical_slot_reg.x.MRLS == SHPC_MRL_CLOSED ) &&
+			logical_slot_reg.x.PF == SHPC_STATUS_CLEARED &&
+			logical_slot_reg.x.S_STATE == SHPC_ENABLE_SLOT ) {
+			Query->x.lu_slot_state = SLOT_ENABLE;
+		}
+		else {
+			Query->x.lu_slot_state = SLOT_DISABLE;
+		}
+
+		//
+		// OK, it's all there!
+		//
+		Query->x.lu_reserved1 = 0;
+		Query->x.lu_reserved2 = 0;
+		Query->x.lu_request_failed = HP_FALSE;
+	}
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_StartAsyncRequest()
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data.
+//	slot_id - Zero-based slot number (0..n-1).
+//	Request - Async request: Slot "Enable/Disable", AttnLED "Attn/Normal").
+//	timeout - For AttnLED "Attn" requests (in seconds)
+//	request_context - Caller provided pointer to be returned upon completion.
+//
+// Return Value
+//	STATUS_SUCCESS if the request is accepted.  The Callback() is later invoked with a completion status.
+//  STATUS_UNSUCCESSFUL if the request is rejected (invalid parameters, or similar request in progress),
+//
+// Comment:
+//	For AttnLED "Attn" requests, the completion Callback() function is invoked as soon as the hardware
+//	completes (Blink) execution.  When the timeout period expires, the AttnLED is brought back to
+//  its "Normal" (On/Off) state, and the Callback() is invoked once again.
+//
+// ****************************************************************************
+long
+hp_StartAsyncRequest(
+	struct shpc_context* shpc_context,
+	u8 slot_id,
+	enum shpc_async_request request,
+	u32 timeout,
+	void* request_context
+	)
+{
+	unsigned long		old_irq_flags;
+	struct slot_context* slot_context;
+	long status = STATUS_SUCCESS;
+
+	dbg("%s -->slot_id[ %d:%d ]  Request[ %d ]",__FUNCTION__ ,
+		shpc_context->shpc_instance, slot_id, request );
+
+	//
+	// Valid slot_id?
+	//
+	if( slot_id >= shpc_context->number_of_slots ) {
+		status = STATUS_UNSUCCESSFUL;
+	}
+	else {
+		slot_context = &shpc_context->slot_context[ slot_id ];
+
+		switch( request ) {
+		case SHPC_ASYNC_ENABLE_SLOT:
+			dbg("%s SHPC_ASYNC_ENABLE_SLOT",__FUNCTION__);
+		case SHPC_ASYNC_DISABLE_SLOT:
+			dbg("%s SHPC_ASYNC_DISABLE_SLOT",__FUNCTION__);
+			//
+			// Slot Request Pending?
+			//
+			spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+			down_interruptible(&slot_context->slot_event_bits_semaphore);
+			down_interruptible(&shpc_context->shpc_event_bits_semaphore);
+			if((slot_context->slot_event_bits & SLOT_REQUEST_EVENT) ||
+				(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)) {
+				status = STATUS_UNSUCCESSFUL;
+				up(&slot_context->slot_event_bits_semaphore);
+				up(&shpc_context->shpc_event_bits_semaphore);
+			}
+			else {
+				up(&slot_context->slot_event_bits_semaphore);
+				up(&shpc_context->shpc_event_bits_semaphore);
+				slot_context->slot_request.type = request;
+				slot_context->slot_request.request_context = request_context;
+				hp_send_slot_event(slot_context, SLOT_REQUEST_EVENT);
+			}
+			spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+			break;
+
+		case SHPC_ASYNC_LED_LOCATE:
+			dbg("%s SHPC_ASYNC_LED_LOCATE",__FUNCTION__);
+		case SHPC_ASYNC_LED_NORMAL:
+			dbg("%s SHPC_ASYNC_LED_NORMAL",__FUNCTION__);
+			//
+			// AttnLED Request Pending?
+			//
+			spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+			down_interruptible(&slot_context->slot_event_bits_semaphore);
+			down_interruptible(&shpc_context->shpc_event_bits_semaphore);
+			if((slot_context->slot_event_bits & ATTN_LED_REQUEST_EVENT) ||
+				(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)) {
+				dbg("%s  LED--STATUS_UNSUCCESSFUL  slot_event_bits = %08X", __FUNCTION__ ,slot_context->slot_event_bits);
+				status = STATUS_UNSUCCESSFUL;
+				up(&slot_context->slot_event_bits_semaphore);
+				up(&shpc_context->shpc_event_bits_semaphore);
+			}
+			else {
+				up(&slot_context->slot_event_bits_semaphore);
+				up(&shpc_context->shpc_event_bits_semaphore);
+				slot_context->attn_led_request.type = request;
+				slot_context->attn_led_request.timeout = timeout;
+				slot_context->attn_led_request.request_context = request_context;
+				hp_send_slot_event(slot_context, ATTN_LED_REQUEST_EVENT);
+			}
+			spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+			break;
+
+		case SHPC_ASYNC_QUIESCE_DEVNODE_NOTIFY:
+			dbg("%s SHPC_ASYNC_QUIESCE_DEVNODE_NOTIFY",__FUNCTION__);
+			//
+			// HP library notification: DevNode is quiesced
+			//
+			spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+			++slot_context->quiesce_replies;
+			if( slot_context->quiesce_requests &&
+				slot_context->quiesce_replies >= slot_context->quiesce_requests ) {
+				slot_context->slot_quiesced = TRUE;
+				hp_send_slot_event(slot_context, QUIESCE_EVENT);
+			}
+			spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+			break;
+
+		case SHPC_ASYNC_CANCEL_QUIESCE_DEVNODE:
+			dbg("%s SHPC_ASYNC_CANCEL_QUIESCE_DEVNODE",__FUNCTION__);
+			//
+			// HP library notification: could not quiesce DevNode
+			//
+			spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+			slot_context->slot_quiesced = FALSE;
+			hp_send_slot_event(slot_context, QUIESCE_EVENT);
+			spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+			//
+			// Abort bus-rebalancing
+			//
+			spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+			shpc_context->bus_released = FALSE;
+			hp_send_event_to_all_slots(shpc_context, BUS_COMPLETE_EVENT);
+			spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+			break;
+
+		default:
+			status = STATUS_UNSUCCESSFUL;
+			break;
+		}
+	}
+
+	return status;
+}
+
+// ****************************************************************************
+//
+// hp_Queryslot_psn() 
+//
+// Parameters
+//          shpc_context - Caller provided storage for SHPC context data.
+//          SlotID - Zero-based slot number (0..n-1).
+//          slot_psn - Pointer to Physical Slot Number
+//
+// Return Value
+//  STATUS_SUCCESS, or STATUS_UNSUCCESSFUL for invalid SlotID.
+//
+// ****************************************************************************
+long hp_Queryslot_psn(struct shpc_context *shpc_context, unsigned char slot_ID, unsigned long *slot_psn)
+{
+	struct slot_context *slot_context;
+	long status = STATUS_SUCCESS;
+	dbg("%s slot_ID[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_ID);
+	//
+	// Valid SlotID?
+	//
+	if( slot_ID >= shpc_context->number_of_slots || slot_psn == NULL ) {
+				status = STATUS_UNSUCCESSFUL;
+	}
+	else {
+		//
+		// Which slot?
+		//
+		slot_context = &shpc_context->slot_context[ slot_ID ];
+		//
+		// Get slot PSN
+		//
+		*slot_psn = slot_context->slot_psn;
+	}
+	return status;
+}
+
+// ****************************************************************************
+//
+// hp_slot_timers1-10func(): Function passed to timer to send event
+//
+// Parameters
+//	slot_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//	void
+//
+// ****************************************************************************
+void hp_slot_timer1_func(unsigned long data){
+
+	struct slot_context *slot_context;
+	slot_context = (struct slot_context*) data;
+
+	dbg("%s", __FUNCTION__);
+	hp_set_slot_event_bit(slot_context, SLOT_TIMER1_EVENT);
+
+	wake_up_interruptible(&slot_context->slot_event);
+}
+
+void hp_slot_timer2_func(unsigned long data){
+
+	struct slot_context *slot_context;
+	slot_context = (struct slot_context*) data;
+
+	dbg("%s", __FUNCTION__);
+	hp_set_slot_event_bit(slot_context, SLOT_TIMER2_EVENT);
+
+	wake_up_interruptible(&slot_context->slot_event);
+}
+
+void hp_slot_timer3_func(unsigned long data){
+
+	struct slot_context *slot_context;
+	slot_context = (struct slot_context*) data;
+
+	dbg("%s", __FUNCTION__);
+	hp_set_slot_event_bit(slot_context, SLOT_TIMER3_EVENT);
+
+	wake_up_interruptible(&slot_context->slot_event);
+}
+
+void hp_slot_timer4_func(unsigned long data){
+
+	struct slot_context *slot_context;
+	slot_context = (struct slot_context*) data;
+
+	dbg("%s", __FUNCTION__);
+	hp_set_slot_event_bit(slot_context, SLOT_TIMER4_EVENT);
+
+	wake_up_interruptible(&slot_context->slot_event);
+}
+
+void hp_slot_timer5_func(unsigned long data){
+
+	struct slot_context *slot_context;
+	slot_context = (struct slot_context*) data;
+
+	dbg("%s", __FUNCTION__);
+	hp_set_slot_event_bit(slot_context, SLOT_TIMER5_EVENT);
+
+	wake_up_interruptible(&slot_context->slot_event);
+}
+
+void hp_slot_timer6_func(unsigned long data){
+
+	struct slot_context *slot_context;
+	slot_context = (struct slot_context*) data;
+
+	dbg("%s", __FUNCTION__);
+	hp_set_slot_event_bit(slot_context, SLOT_TIMER6_EVENT);
+
+	wake_up_interruptible(&slot_context->slot_event);
+}
+
+void hp_slot_timer7_func(unsigned long data){
+
+	struct slot_context *slot_context;
+	slot_context = (struct slot_context*) data;
+
+	dbg("%s", __FUNCTION__);
+	hp_set_slot_event_bit(slot_context, SLOT_TIMER7_EVENT);
+
+	wake_up_interruptible(&slot_context->slot_event);
+}
+
+void hp_slot_timer8_func(unsigned long data){
+
+	struct slot_context *slot_context;
+	slot_context = (struct slot_context*) data;
+
+	dbg("%s", __FUNCTION__);
+	hp_set_slot_event_bit(slot_context, SLOT_TIMER8_EVENT);
+
+	wake_up_interruptible(&slot_context->slot_event);
+}
+
+void hp_slot_timer9_func(unsigned long data){
+
+	struct slot_context *slot_context;
+	slot_context = (struct slot_context*) data;
+
+	dbg("%s", __FUNCTION__);
+	hp_set_slot_event_bit(slot_context, SLOT_TIMER9_EVENT);
+
+	wake_up_interruptible(&slot_context->slot_event);
+}
+
+void hp_slot_timer10_func(unsigned long data){
+
+	struct slot_context *slot_context;
+	slot_context = (struct slot_context*) data;
+
+	dbg("%s", __FUNCTION__);
+	hp_set_slot_event_bit(slot_context, SLOT_TIMER10_EVENT);
+
+	wake_up_interruptible(&slot_context->slot_event);
+}
+
+// ****************************************************************************
+//
+// hp_led_timers1-4_func(): Function passed to timer to send event
+//
+// Parameters
+//	slot_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//	void
+//
+// ****************************************************************************
+void hp_led_timer1_func(unsigned long data){
+
+	struct slot_context *slot_context;
+	slot_context = (struct slot_context*) data;
+
+	dbg("%s", __FUNCTION__);
+	hp_set_slot_event_bit(slot_context, LED_TIMER1_EVENT);
+
+	wake_up_interruptible(&slot_context->slot_event);
+}
+
+void hp_led_timer2_func(unsigned long data){
+
+	struct slot_context *slot_context;
+	slot_context = (struct slot_context*) data;
+
+	dbg("%s", __FUNCTION__);
+	hp_set_slot_event_bit(slot_context, LED_TIMER2_EVENT);
+
+	wake_up_interruptible(&slot_context->slot_event);
+}
+
+void hp_led_timer3_func(unsigned long data){
+
+	struct slot_context *slot_context;
+	slot_context = (struct slot_context*) data;
+
+	dbg("%s", __FUNCTION__);
+	hp_set_slot_event_bit(slot_context, LED_TIMER3_EVENT);
+
+	wake_up_interruptible(&slot_context->slot_event);
+}
+
+void hp_led_timer4_func(unsigned long data){
+
+	struct slot_context *slot_context;
+	slot_context = (struct slot_context*) data;
+
+	dbg("%s", __FUNCTION__);
+	hp_set_slot_event_bit(slot_context, LED_TIMER4_EVENT);
+
+	wake_up_interruptible(&slot_context->slot_event);
+}
+
+// ****************************************************************************
+//
+// hp_clear_slot_event_bit():
+//
+// Parameters
+//	slot_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//	void
+//
+// ****************************************************************************
+void hp_clear_slot_event_bit(struct slot_context * slot_context, u32 mask)
+{
+//	dbg("%s -->slot bits %08X   MASK=%08X",__FUNCTION__ ,slot_context->slot_event_bits, mask);
+
+	down_interruptible(&slot_context->slot_event_bits_semaphore);
+	// cleareventbit
+	slot_context->slot_event_bits &= ~mask;
+	up(&slot_context->slot_event_bits_semaphore);
+}
+
+// ****************************************************************************
+//
+// hp_set_slot_event_bit():
+//
+// Parameters
+//	slot_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//	void
+//
+// ****************************************************************************
+void hp_set_slot_event_bit(struct slot_context * slot_context, u32 mask)
+{
+//	dbg("%s -->slot bits %08X   MASK=%08X",__FUNCTION__ ,slot_context->slot_event_bits, mask);
+
+	down_interruptible(&slot_context->slot_event_bits_semaphore);
+	// cleareventbit
+	slot_context->slot_event_bits |= mask;
+	up(&slot_context->slot_event_bits_semaphore);
+}
+
+// ****************************************************************************
+//
+// hp_clear_shpc_event_bit():
+//
+// Parameters
+//	slot_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//	void
+//
+// ****************************************************************************
+void hp_clear_shpc_event_bit(struct shpc_context * shpc_context, u32 mask)
+{
+	down_interruptible(&shpc_context->shpc_event_bits_semaphore);
+	// cleareventbit
+	shpc_context->shpc_event_bits &= ~mask;
+	up(&shpc_context->shpc_event_bits_semaphore);
+}
+
+// ****************************************************************************
+//
+// hp_set_shpc_event_bit():
+//
+// Parameters
+//	slot_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//	void
+//
+// ****************************************************************************
+void hp_set_shpc_event_bit(struct shpc_context * shpc_context, u32 mask)
+{
+	down_interruptible(&shpc_context->shpc_event_bits_semaphore);
+	// set event bit
+	shpc_context->shpc_event_bits |= mask;
+	up(&shpc_context->shpc_event_bits_semaphore);
+}
+
+// ****************************************************************************
+//
+// hp_send_event_to_all_slots():
+//
+// Parameters
+//	slot_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//	void
+//
+// ****************************************************************************
+void hp_send_event_to_all_slots(struct shpc_context *shpc_context, u32 mask)
+{
+	u8 i;
+	struct slot_context * slot_context;
+
+	down_interruptible(&shpc_context->shpc_event_bits_semaphore);
+	// set event bit
+	shpc_context->shpc_event_bits |= mask;
+	// send event to each slot thread
+	for( i=0; i<shpc_context->number_of_slots; ++i ) {
+		slot_context = &shpc_context->slot_context[ i ];
+		wake_up_interruptible(&slot_context->slot_event);
+	}
+	up(&shpc_context->shpc_event_bits_semaphore);
+}
+
+// ****************************************************************************
+//
+// hp_send_slot_event():
+//
+// Parameters
+//	slot_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//	void
+//
+// ****************************************************************************
+void hp_send_slot_event(struct slot_context * slot_context, u32 mask)
+{
+	// set event bit
+	hp_set_slot_event_bit(slot_context, mask);
+	wake_up_interruptible( &slot_context->slot_event);
+}
+
+
+// ****************************************************************************
+//
+// hp_get_led_cmd_available_mutex_thread():  run as a thread per each slot
+//
+// Parameters
+//	slot_context - Caller provided storage for slot context data.
+//
+// Return Value
+//	void
+//
+// ****************************************************************************
+int hp_get_led_cmd_available_mutex_thread(void *ptr)
+{
+	long status = STATUS_SUCCESS;
+	struct shpc_context* shpc_context;
+	struct slot_context* slot_context;
+	int pid;
+	
+	lock_kernel ();
+	daemonize ("amdshpc_getledcmd_av_mutex");
+	unlock_kernel ();
+
+	slot_context = (struct slot_context* ) ptr;
+	shpc_context = (struct shpc_context* ) slot_context->shpc_context;
+	do {
+		interruptible_sleep_on(&slot_context->led_cmd_acquire_event);
+		if (slot_context->slot_event_bits & LED_CMD_ACQUIRE_EVENT){
+			hp_clear_slot_event_bit(slot_context, LED_CMD_ACQUIRE_EVENT);
+			pid = kernel_thread(hp_led_cmd_available_mutex_thread, slot_context, CLONE_SIGHAND);
+			if (pid < 0) {
+				err ("Can't start up our hp_led_cmd_available_mutex_thread\n");
+				status = STATUS_UNSUCCESSFUL;
+				break;
+			}
+		} else {
+			dbg("%s terminating return 0  slot_id[ %d:%d ]",__FUNCTION__,
+				shpc_context->shpc_instance, slot_context->slot_number-1);
+			return 0;
+		}
+	} while (1);
+	return(status);
+}
+
+// ****************************************************************************
+//
+// hp_led_cmd_available_mutex_thread():  run as a thread per each request for cmd
+//
+// Parameters
+//	slot_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//	void
+//
+// ****************************************************************************
+int hp_led_cmd_available_mutex_thread(void *ptr)
+{
+	struct shpc_context* shpc_context;
+	struct slot_context* slot_context;
+	
+	lock_kernel ();
+	daemonize ("amdshpc_ledcmd_av_mutex");
+	unlock_kernel ();
+
+	slot_context = (struct slot_context* ) ptr;
+	shpc_context = (struct shpc_context* ) slot_context->shpc_context;
+
+	//
+	// acquire the main mutex for all slots exclusion
+	//
+	down_interruptible(&shpc_context->cmd_available_mutex);
+	if ((shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)||
+		(shpc_context->shpc_event_bits & RESUME_EVENT)||
+		(shpc_context->shpc_event_bits & REMOVE_EVENT)){
+		dbg("%s return 0  slot_id[ %d:%d ]",__FUNCTION__,
+			shpc_context->shpc_instance, slot_context->slot_number-1);
+		up(&shpc_context->cmd_available_mutex);
+		return 0;
+	}
+
+	//
+	// now tell our slot thread that it has the mutex
+	//
+	hp_set_shpc_event_bit(shpc_context, LED_CMD_AVAILABLE_MUTEX_EVENT);
+	wake_up_interruptible(&slot_context->slot_event);
+
+	//
+	// wait for our slot thread to release the mutex
+	//
+	interruptible_sleep_on(&slot_context->led_cmd_release_event);
+	if ((shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)||
+		(shpc_context->shpc_event_bits & RESUME_EVENT)||
+		(shpc_context->shpc_event_bits & REMOVE_EVENT)){
+		dbg("%s return 0  slot_id[ %d:%d ]",__FUNCTION__,
+			shpc_context->shpc_instance, slot_context->slot_number-1);
+		up(&shpc_context->cmd_available_mutex);
+		return 0;
+	}
+	hp_clear_slot_event_bit(slot_context, LED_CMD_RELEASE_EVENT);
+
+	hp_clear_shpc_event_bit(shpc_context, LED_CMD_AVAILABLE_MUTEX_EVENT);
+	up(&shpc_context->cmd_available_mutex);
+	dbg("%s cmd_available_mutex RELEASED",__FUNCTION__);
+	return(0);
+}
+
+// ****************************************************************************
+//
+// hp_get_cmd_available_mutex_thread():  run as a thread per each slot
+//
+// Parameters
+//	slot_context - Caller provided storage for slot context data.
+//
+// Return Value
+//	void
+//
+// ****************************************************************************
+int hp_get_cmd_available_mutex_thread(void *ptr)
+{
+	long status = STATUS_SUCCESS;
+	struct shpc_context* shpc_context;
+	struct slot_context* slot_context;
+	int pid;
+	
+	lock_kernel ();
+	daemonize ("amdshpc_getcmd_av_mutex");
+	unlock_kernel ();
+
+	slot_context = (struct slot_context* ) ptr;
+	shpc_context = (struct shpc_context* ) slot_context->shpc_context;
+
+	do {
+		interruptible_sleep_on(&slot_context->cmd_acquire_event);
+		if ((slot_context->slot_event_bits & CMD_ACQUIRE_EVENT) || 
+		    (slot_context->slot_event_bits & CMD_RELEASE_EVENT)){
+			hp_clear_slot_event_bit(slot_context,CMD_ACQUIRE_EVENT);
+			pid = kernel_thread(hp_cmd_available_mutex_thread, slot_context, CLONE_SIGHAND);
+			if (pid < 0) {
+				err ("Can't start up our hp_get_cmd_available_mutex_thread\n");
+				status = STATUS_UNSUCCESSFUL;
+				break;
+			}
+		} else {
+			dbg("%s terminating return 0  slot_id[ %d:%d ]",__FUNCTION__,
+				shpc_context->shpc_instance, slot_context->slot_number-1);
+			return 0;
+		}
+	} while (1);
+	return(status);
+}
+
+// ****************************************************************************
+//
+// hp_cmd_available_mutex_thread():  run as a thread per each request for cmd
+//
+// Parameters
+//	slot_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//	void
+//
+// ****************************************************************************
+int hp_cmd_available_mutex_thread(void *ptr)
+{
+	struct shpc_context* shpc_context;
+	struct slot_context* slot_context;
+	
+	lock_kernel ();
+	daemonize ("amdshpc_cmd_av_mutex");
+	unlock_kernel ();
+
+	slot_context = (struct slot_context* ) ptr;
+	shpc_context = (struct shpc_context* ) slot_context->shpc_context;
+
+	//
+	// acquire the main mutex for all slots exclusion
+	//
+	down_interruptible(&shpc_context->cmd_available_mutex);
+	if ((shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)||
+		(shpc_context->shpc_event_bits & RESUME_EVENT)||
+		(shpc_context->shpc_event_bits & REMOVE_EVENT)){
+		dbg("%s return 0  slot_id[ %d:%d ]",__FUNCTION__,
+			shpc_context->shpc_instance, slot_context->slot_number-1);
+		up(&shpc_context->cmd_available_mutex);
+		return 0;
+	}
+
+	//
+	// now tell our slot thread that it has the mutex
+	//
+	hp_set_shpc_event_bit(shpc_context, CMD_AVAILABLE_MUTEX_EVENT);
+	wake_up_interruptible(&slot_context->slot_event);
+
+	//
+	// wait for our slot thread to release the mutex
+	//
+	interruptible_sleep_on(&slot_context->cmd_release_event);
+	if ((shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)||
+		(shpc_context->shpc_event_bits & RESUME_EVENT)||
+		(shpc_context->shpc_event_bits & REMOVE_EVENT)){
+		dbg("%s return 0  slot_id[ %d:%d ]",__FUNCTION__,
+			shpc_context->shpc_instance, slot_context->slot_number-1);
+		up(&shpc_context->cmd_available_mutex);
+		return 0;
+	}
+	hp_clear_slot_event_bit(slot_context,CMD_RELEASE_EVENT);
+	hp_clear_shpc_event_bit(shpc_context, CMD_AVAILABLE_MUTEX_EVENT);
+	up(&shpc_context->cmd_available_mutex);
+	return(0);
+}
+
+// ****************************************************************************
+//
+// hp_get_bus_available_mutex_thread():  run as a thread per each slot
+//
+// Parameters
+//	slot_context - Caller provided storage for slot context data.
+//
+// Return Value
+//	void
+//
+// ****************************************************************************
+int hp_get_bus_available_mutex_thread(void *ptr)
+{
+	long status = STATUS_SUCCESS;
+	struct shpc_context* shpc_context;
+	struct slot_context* slot_context;
+	int pid;
+	
+	lock_kernel ();
+	daemonize ("amdshpc_getbus_av_mutex");
+	unlock_kernel ();
+
+	slot_context = (struct slot_context* ) ptr;
+	shpc_context = (struct shpc_context* ) slot_context->shpc_context;
+
+	do {
+		interruptible_sleep_on(&slot_context->bus_acquire_event);
+		if (slot_context->slot_event_bits & BUS_ACQUIRE_EVENT) {
+			hp_clear_slot_event_bit(slot_context, BUS_ACQUIRE_EVENT);
+			pid = kernel_thread(hp_bus_available_mutex_thread, slot_context, CLONE_SIGHAND);
+			if (pid < 0) {
+				err ("Can't start up our hp_get_bus_available_mutex_thread\n");
+				status = STATUS_UNSUCCESSFUL;
+				break;
+			}
+		} else {
+			dbg("%s terminating return 0  slot_id[ %d:%d ]",__FUNCTION__,
+				shpc_context->shpc_instance, slot_context->slot_number-1);
+			return 0;
+		}
+	} while (1);
+	return(status);
+}
+
+// ****************************************************************************
+//
+// hp_bus_available_mutex_thread():
+//
+// Parameters
+//	slot_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//	void
+//
+// ****************************************************************************
+int hp_bus_available_mutex_thread(void *ptr)
+{
+	struct shpc_context* shpc_context;
+	struct slot_context* slot_context;
+	
+	lock_kernel ();
+	daemonize ("amdshpc_bus_av_mutex");
+	//  New name
+	unlock_kernel ();
+
+	slot_context = (struct slot_context* ) ptr;
+	shpc_context = (struct shpc_context* ) slot_context->shpc_context;
+
+	//
+	// acquire the main mutex for all slots exclusion
+	//
+	down_interruptible(&shpc_context->bus_available_mutex);
+	if ((shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)||
+		(shpc_context->shpc_event_bits & RESUME_EVENT)||
+		(shpc_context->shpc_event_bits & REMOVE_EVENT)){
+		dbg("%s return 0  slot_id[ %d:%d ]",__FUNCTION__,
+			shpc_context->shpc_instance, slot_context->slot_number-1);
+		up(&shpc_context->bus_available_mutex);
+		return 0;
+	}
+
+	//
+	// now tell our slot thread that it has the mutex
+	//
+	hp_set_shpc_event_bit(shpc_context, BUS_AVAILABLE_MUTEX_EVENT);
+	wake_up_interruptible(&slot_context->slot_event);
+
+	//
+	// wait for our slot thread to release the mutex
+	//
+	interruptible_sleep_on(&slot_context->bus_release_event);
+	if ((shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)||
+		(shpc_context->shpc_event_bits & RESUME_EVENT)||
+		(shpc_context->shpc_event_bits & REMOVE_EVENT)){
+		dbg("%s return 0  slot_id[ %d:%d ]",__FUNCTION__,
+			shpc_context->shpc_instance, slot_context->slot_number-1);
+		up(&shpc_context->bus_available_mutex);
+		return 0;
+	}
+	hp_clear_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+
+	hp_clear_shpc_event_bit(shpc_context, BUS_AVAILABLE_MUTEX_EVENT);
+	up(&shpc_context->bus_available_mutex);
+	return(0);
+}
+
+// ****************************************************************************
+//
+// call_back_routine():
+//
+// Parameters
+//	slot_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//	void
+//
+// ****************************************************************************
+static unsigned long async_callback (void* driver_context,
+				     u8 slot_id,
+				     enum shpc_async_request async_request,
+				     union SLOT_STATUS_INFO slot_status,
+				     void* request_context )
+{
+	u8 phys_slot_num;
+	long rc=0;
+	struct pci_func *slot_func;
+	struct controller *ctrl;
+	struct shpc_context *shpc_context;
+	u8 bus=0;
+	u8 device=0;
+	u8 function=0;
+	unsigned long devices_still_quiescing = 0;
+
+	dbg("%s slot_id = %d",__FUNCTION__, slot_id);
+
+	ctrl = ((struct controller*) driver_context);
+	if (ctrl == NULL){
+		return -ENODEV;
+	}
+
+	shpc_context = (struct shpc_context* ) ctrl->shpc_context;
+	phys_slot_num = shpc_context->slot_context[slot_id].slot_psn;
+	
+	bus		= ctrl->bus;
+	device 	= slot_id + 1;
+	
+	dbg("%s - physical_slot = %d  instance = %d",__FUNCTION__, phys_slot_num, shpc_context->shpc_instance);
+
+	switch( async_request ) {
+	case SHPC_ASYNC_ENABLE_SLOT:
+		dbg("%s SHPC_ASYNC_ENABLE_SLOT",__FUNCTION__);
+		dbg("%s slot occupied = %d",__FUNCTION__,shpc_context->slot_context[slot_id].slot_occupied);
+		if (shpc_context->slot_context[slot_id].slot_occupied == 1) {
+			return 0;
+		}
+		//
+		// Force pci-bus re-enumeration (probe), to load drivers on behalf on enabled device(s) on this slot.
+		//
+		dbg("%s   In callback routine processing enable slot",__FUNCTION__ );
+
+		dbg("%s   CALLING amdshpc_slot_find  bus, dev, fn = %d, %d, %d\n",__FUNCTION__ ,
+			bus, device, function);
+		slot_func = amdshpc_slot_find(bus, device, function);
+		dbg("%s  slot_func = %p ",__FUNCTION__ , slot_func);
+		if (!slot_func) {
+			dbg("%s --> slot_func not found",__FUNCTION__ );
+			return -ENODEV;
+		}
+
+		slot_func->bus = bus;
+		slot_func->device = device;
+		slot_func->function = function;
+		slot_func->configured = 0;
+		dbg("%s   CALLING amdshpc_process_SI(ctrl=%p slot_func=%p)\n",__FUNCTION__ , ctrl, slot_func);
+		rc = amdshpc_process_SI(ctrl, slot_func);
+		if (!rc ) {
+			shpc_context->slot_context[slot_id].slot_occupied = 1;
+		}
+		dbg("%s   amdshpc_process_SI returned  rc=%d",__FUNCTION__ , (int)rc);
+		break;
+
+	case SHPC_ASYNC_SURPRISE_REMOVE:
+		dbg("%s SHPC_ASYNC_SURPRISE_REMOVE",__FUNCTION__);
+		//
+		// Something went wrong with the slot (eg, power-fault), and loaded drivers must be removed.
+		//
+	case SHPC_ASYNC_QUIESCE_DEVNODE:
+		dbg("%s SHPC_ASYNC_QUIESCE_DEVNODE",__FUNCTION__);
+		//
+		// Friendly opportunity to quiesce (remove) drivers, prior to disabling the slot.
+		// After device drivers are removed, it's OK to show messages to that effect.
+		//
+		// If device quiecing will complete at a later time (from a separate thread),
+		// then set "devices_still_quiescing" accordingly, and upon quiecing-completion,
+		// call hp_StartAsyncRequest() with a "SHPC_ASYNC_QUIESCE_DEVNODE_NOTIFY" request.
+		//
+	case SHPC_ASYNC_QUIESCE_DEVNODE_QUIET:
+		dbg("%s SHPC_ASYNC_QUIESCE_DEVNODE_QUIET",__FUNCTION__);
+		//
+		// Friendly opportunity to quiesce (remove) drivers, prior to disabling the slot.
+		// After device drivers are removed, don't show messages to that effect.
+		//
+		// If device quiecing will complete at a later time (from a separate thread),
+		// then set "devices_still_quiescing" accordingly, and upon quiecing-completion,
+		// call hp_StartAsyncRequest() with a "SHPC_ASYNC_QUIESCE_DEVNODE_NOTIFY" request.
+		//
+		dbg("%s   Processing disable slot",__FUNCTION__ );
+		
+		dbg("%s   CALLING amdshpc_slot_find  bus, dev, fn = %d, %d, %d\n",__FUNCTION__ ,
+			bus, device, function);
+
+		slot_func = amdshpc_slot_find(bus, device, function);
+		dbg("%s  slot_func = %p ",__FUNCTION__ , slot_func);
+		if (!slot_func) {
+			dbg("%s --> slot_func not found",__FUNCTION__ );
+			return -ENODEV;
+		}
+
+		dbg("%s   CALLING amdshpc_process_SS(ctrl=%p slot_func=%p)\n",__FUNCTION__ , ctrl, slot_func);
+		rc = amdshpc_process_SS(ctrl, slot_func);
+		if (!rc ) {
+			shpc_context->slot_context[slot_id].slot_occupied = 0;
+		}
+		dbg("%s   amdshpc_process_SS returned  rc=%d",__FUNCTION__ , (int)rc);
+
+		break;
+
+	case SHPC_ASYNC_DISABLE_SLOT:
+		dbg("%s SHPC_ASYNC_DISABLE_SLOT",__FUNCTION__);
+		//
+		// Just a notification, may be used to update some interested GUI application.
+		//
+		break;
+
+	default:
+		break;
+	}
+	return devices_still_quiescing;
+}
+
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/amdshpc_ddi.h	Wed Mar 17 11:19:43 2004
@@ -0,0 +1,235 @@
+/*
+* Copyright (C) 2002,2003 Advanced Micro Devices, Inc.
+* YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS
+* AND CONDITIONS OF THE GNU GENERAL PUBLIC
+* LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS
+* INCLUDED WITH THIS FILE AND POSTED AT
+* http://www.gnu.org/licenses/gpl.html
+*
+*
+* This driver is to be used as a skeleton driver to be show how to interface
+* with the pci hotplug core easily.
+*
+* Send feedback to <david.keck@amd.com>
+*
+*/
+
+
+#ifndef _SHPC_DDI_H_
+#define _SHPC_DDI_H_
+
+#include "amdshpc.h"
+//
+// SHPC Constants
+//
+#define	SHPC_MAX_NUM_SLOTS		4
+
+
+// ****************************************************************************
+//
+// hp_AddDevice()
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data (per hardware-instance).
+//	driver_context - Caller provided pointer to be returned upon completion.
+//	Callback - Caller provided function to be called upon completion of async requests.
+//  shpc_instance - Zero-based hardware instance.
+//
+// Return Value
+//  Status returned by any system calls made within hp_AddDevice().
+//
+// ****************************************************************************
+long
+	hp_AddDevice(
+			struct shpc_context *shpc_context,
+			void* driver_context,
+			SHPC_ASYNC_CALLBACK Callback,
+			unsigned long shpc_instance
+			);
+
+
+// ****************************************************************************
+//
+// hp_StartDevice()
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data.
+//  mmio_base_addr - from u.Memory member of CmResourceTypeMemory
+//	IntVector - from u.Interrupt.Vector member of CmResourceTypeInterrupt
+//	IntMode - from Flags member of CmResourceTypeInterrupt
+//	IntShared - from ShareDisposition member of CmResourceTypeInterrupt
+//	IntAffinity - from u.Interrupt.Affinity member of CmResourceTypeInterrupt
+//
+// Return Value
+//  Status returned by any system calls made within hp_StartDevice().
+//
+// Comments:
+//	The caller is responsible for mapping mmio_base_addr, via MmMapIoSpace(),
+//	before calling hp_StartDevice().
+//
+// ****************************************************************************
+long
+	hp_StartDevice(
+		      struct shpc_context* shpc_context
+		      );
+
+
+// ****************************************************************************
+//
+// hp_StopDevice() 
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//  Status returned by any system calls made within hp_StopDevice().
+//
+// Comments:
+//	The caller is responsible for unmapping mmio_base_addr, via MmUnmapIoSpace(),
+//  after calling hp_StopDevice() for resource re-balancing or device removal.
+//
+// ****************************************************************************
+long hp_StopDevice(struct shpc_context *shpc_context);
+
+// ****************************************************************************
+//
+// hp_SuspendDevice()
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//  Status returned by any system calls made within hp_SuspendDevice().
+//
+// Comments:
+//	hp_SuspendDevice() must be called before transitioning away from PowerDeviceD0.
+//
+// ****************************************************************************
+long hp_SuspendDevice(struct shpc_context *shpc_context);
+
+// ****************************************************************************
+//
+// hp_ResumeDevice() 
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//  Status returned by any system calls made within hp_ResumeDevice().
+//
+// Comments:
+//	hp_SuspendDevice() must be called after transitioning back to PowerDeviceD0.
+//
+// ****************************************************************************
+long hp_ResumeDevice(struct shpc_context *shpc_context);
+
+// ****************************************************************************
+//
+// hp_QuerySlots() 
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data.
+//	SlotConfig - Caller provided storage for slots configuration info.
+//
+// Return Value
+//  Status returned by any system calls made within hp_QuerySlots().
+//
+// ****************************************************************************
+long hp_QuerySlots(struct shpc_context *shpc_context, union SLOT_CONFIG_INFO* SlotConfig);
+
+
+// ****************************************************************************
+//
+// hp_QuerySlotStatus()
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data.
+//	slot_id - Zero-based slot number (0..n-1).
+//	Query - Pointer to Slot Status Structure
+//
+// Return Value
+//  Status returned by any system calls made within hp_QuerySlotStatus().
+//
+// ****************************************************************************
+long hp_QuerySlotStatus(struct shpc_context *shpc_context, u8 slot_id, union SLOT_STATUS_INFO* Query);
+
+// ****************************************************************************
+//
+// hp_Queryslot_psn()
+//
+// Parameters
+//          shpc_context - Caller provided storage for SHPC context data.
+//          SlotID - Zero-based slot number (0..n-1).
+//          slot_psn - Pointer to Physical Slot Number
+//
+// Return Value
+//  STATUS_SUCCESS, or STATUS_UNSUCCESSFUL for invalid SlotID.
+//
+// ****************************************************************************
+long hp_Queryslot_psn(struct shpc_context *shpc_context, unsigned char slot_ID, unsigned long *slot_psn);
+
+// ****************************************************************************
+//
+// hp_StartAsyncRequest()
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data.
+//	slot_id - Zero-based slot number (0..n-1).
+//	Request - Async request: Slot "Enable/Disable", AttnLED "Attn/Normal").
+//	timeout - For AttnLED "Attn" requests (in seconds)
+//	request_context - Caller provided pointer to be returned upon completion.
+//
+// Return Value
+//	STATUS_SUCCESS if the request is accepted.  The Callback() is later invoked with a completion status.
+//  STATUS_UNSUCCESSFUL if the request is rejected (invalid parameters, or similar request in progress),
+//
+// Comment:
+//	For AttnLED "Attn" requests, the completion Callback() function is invoked as soon as the hardware
+//	completes (Blink) execution.  When the timeout period expires, the AttnLED is brought back to
+//  its "Normal" (On/Off) state, and the Callback() is invoked once again.
+//
+// ****************************************************************************
+long hp_StartAsyncRequest(
+			 struct shpc_context *shpc_context,
+			 u8 slot_id,     
+			 enum shpc_async_request Request,
+			 u32 timeout,                            
+			 void* request_context                           
+			 );
+
+
+// ****************************************************************************
+//
+// hp_RegisterUserEvent()
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data.
+//	user_event_pointer - Pointer to caller's provided EVENT object.
+//
+// Return Value
+//	STATUS_SUCCESS if the request is accepted.
+//  STATUS_UNSUCCESSFUL if the request is rejected (EVENT already registered).
+//
+// ****************************************************************************
+long hp_RegisterUserEvent(
+			 struct shpc_context *shpc_context,
+			 wait_queue_head_t *user_event_pointer
+			 );
+
+
+// ****************************************************************************
+//
+// hp_UnRegisterUserEvent()
+//
+// Parameters
+//	shpc_context - Caller provided storage for SHPC context data.
+//
+// Return Value
+//	STATUS_SUCCESS if the request is accepted.
+//  STATUS_UNSUCCESSFUL if the request is rejected (EVENT not previously registered).
+//
+// ****************************************************************************
+long hp_UnRegisterUserEvent(struct shpc_context *shpc_context);
+
+#endif	// _SHPC_DDI_H_
+
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/amdshpc_dsb.c	Wed Mar 17 11:19:43 2004
@@ -0,0 +1,1502 @@
+/*
+ * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001,2003 IBM Corp.
+ * Copyright (C) 2002-2003 Advanced Micro Devices
+ * 
+ * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS
+ * AND CONDITIONS OF THE GNU GENERAL PUBLIC
+ * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS
+ * INCLUDED WITH THIS FILE AND POSTED AT
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Send feedback to <david.keck@amd.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include "amdshpc_ddi.h"
+#include "amdshpc.h"
+
+
+// ****************************************************************************
+//
+// hp_at_slot_enabled_wait_for_slot_request()
+//
+// ****************************************************************************
+long
+hp_at_slot_enabled_wait_for_slot_request(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SLOT_STATUS_INFO slot_status;
+	unsigned long  DevNodes;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Slot Enabled: complete pending slot request
+	//
+	if( slot_context->slot_completion.done ) {
+		dbg("%s -->ENABLE_DONE: slot_id[ %d:%d ]  card_speed_mode[ %d+%d ]  bus_speed_mode[ %d ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			slot_context->card_speed_mode, slot_context->card_pci66_capable,
+			shpc_context->bus_speed_mode );
+		//
+		// Call Completion Callback()
+		//
+		hp_QuerySlotStatus(	shpc_context, slot_context->slot_number - 1, &slot_status );
+		slot_status.x.lu_request_failed = slot_context->slot_completion.failed;
+		shpc_context->async_callback(
+			shpc_context->driver_context,
+			slot_context->slot_number - 1,
+			slot_context->slot_completion.type,
+			slot_status,
+			slot_context->slot_completion.request_context );
+
+		//
+		// Signal registered user EVENT
+		//
+		hp_signal_user_event( shpc_context );
+
+		//
+		// Clear completion flag
+		//
+		slot_context->slot_completion.done = FALSE;
+	}
+
+	//
+	// Clear Button EVENT before waiting
+	//
+	spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+	hp_clear_slot_event_bit(slot_context, ATTN_BUTTON_EVENT);
+	spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+	//
+	// Wait for slot request
+	//
+	shpc_context->shpc_event_bits = 0;slot_context->slot_event_bits = 0;
+
+	wait_event_interruptible(slot_context->slot_event,
+		((slot_context->slot_event_bits & ATTN_BUTTON_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_REQUEST_EVENT) ||
+		(slot_context->slot_event_bits & BUS_REBALANCE_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Notify unrequested removal
+		//
+		slot_context->slot_completion.hw_initiated = TRUE;
+		slot_context->slot_completion.type = SHPC_ASYNC_SURPRISE_REMOVE;
+		slot_context->slot_completion.failed = HP_FALSE;
+		slot_context->slot_completion.request_context = NULL;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// bus_rebalance_event
+	//
+	else if(slot_context->slot_event_bits & BUS_REBALANCE_EVENT) {
+		//
+		// Clear Quiesced EVENT before invoking Callback()
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->quiesce_requests = 0;
+		slot_context->quiesce_replies = 0;
+		slot_context->slot_quiesced = FALSE;
+		hp_clear_slot_event_bit(slot_context, QUIESCE_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Call Completion Callback() to quiesce DevNode(s)
+		//
+		slot_status.AsDWord = 0;
+		DevNodes = shpc_context->async_callback(
+			shpc_context->driver_context,
+			slot_context->slot_number - 1,
+			SHPC_ASYNC_QUIESCE_DEVNODE_QUIET,
+			slot_status,
+			( void* )(unsigned long)slot_context->slot_psn );
+
+		//
+		// Update request count
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->quiesce_requests = DevNodes;
+		if( slot_context->quiesce_requests == 0 ||
+			slot_context->quiesce_replies >= slot_context->quiesce_requests ) {
+			slot_context->slot_quiesced = TRUE;
+			hp_send_slot_event(slot_context, QUIESCE_EVENT);
+		}
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Wait for DevNode quiescing
+		//
+		dbg("%s -->BUS_REBALANCE: slot_id[ %d:%d ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1 );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_stop_on_bus_rebalance;
+	}
+	//
+	// attn_button_event
+	//
+	else if(slot_context->slot_event_bits & ATTN_BUTTON_EVENT) {
+		//
+		// Set completion info for HW-initiated request
+		//
+		slot_context->slot_completion.hw_initiated = TRUE;
+		slot_context->slot_completion.type = SHPC_ASYNC_DISABLE_SLOT;
+		slot_context->slot_completion.request_context = NULL;
+
+		//
+		// Grab Command MUTEX to blink Power LED
+		//
+		dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1 );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_led_cmd_available;
+	}
+	//
+	// SlotRequestEvent
+	//
+	else if(slot_context->slot_event_bits & SLOT_REQUEST_EVENT) {
+		//
+		// Set completion info for SW-initiated request
+		//
+		slot_context->slot_completion.hw_initiated = FALSE;
+		slot_context->slot_completion.type = slot_context->slot_request.type;
+		slot_context->slot_completion.request_context = slot_context->slot_request.request_context;
+
+		//
+		// Request to disable slot?
+		//
+		if( slot_context->slot_request.type == SHPC_ASYNC_DISABLE_SLOT ) {
+			//
+			// Grab Command MUTEX to blink Power LED
+			//
+			dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ]",__FUNCTION__ ,
+				shpc_context->shpc_instance, slot_context->slot_number-1 );
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_led_cmd_available;
+		}
+		else {
+			//
+			// Slot already enabled, just complete the request
+			//
+			dbg("%s -->ENABLE_REQ: slot_id[ %d:%d ]",__FUNCTION__ ,
+				shpc_context->shpc_instance, slot_context->slot_number-1 );
+			slot_context->slot_completion.failed = HP_FALSE;
+			slot_context->slot_completion.done = TRUE;
+		}
+
+		//
+		// Allow next SW-initiated slot request while processing this one
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		hp_clear_slot_event_bit(slot_context, SLOT_REQUEST_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		status = STATUS_UNSUCCESSFUL;
+	}
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_enabled_wait_for_stop_on_bus_rebalance()
+//
+// ****************************************************************************
+long
+hp_at_slot_enabled_wait_for_stop_on_bus_rebalance(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER1_EVENT);
+	slot_context->slot_timer1.data = (unsigned long)slot_context;
+	slot_context->slot_timer1.function = hp_slot_timer1_func;
+	slot_context->slot_timer1.expires = jiffies + QUIESCE_QUIET_TIMEOUT;
+	add_timer(&slot_context->slot_timer1);
+
+	//
+	// Wait for Quiescing EVENT
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((slot_context->slot_event_bits & QUIESCE_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_TIMER1_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER1_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->slot_timer1);
+	}
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Notify unrequested removal
+		//
+		slot_context->slot_completion.hw_initiated = TRUE;
+		slot_context->slot_completion.type = SHPC_ASYNC_SURPRISE_REMOVE;
+		slot_context->slot_completion.failed = HP_FALSE;
+		slot_context->slot_completion.request_context = NULL;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// quiesce_event, timeout
+	//
+	else if((slot_context->slot_event_bits & QUIESCE_EVENT) || (slot_context->slot_event_bits & SLOT_TIMER1_EVENT)) {
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		if((slot_context->slot_event_bits & SLOT_TIMER1_EVENT) || slot_context->slot_quiesced ) {
+			spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+			//
+			// Grab Command MUTEX to set slot at power-only
+			//
+			if((slot_context->slot_event_bits & SLOT_TIMER1_EVENT)) {
+				dbg("%s -->BUS_REBALANCE: slot_id[ %d:%d ] Quiesce timeout",__FUNCTION__ ,
+					shpc_context->shpc_instance, slot_context->slot_number-1 );
+			}
+			else {
+				dbg("%s -->BUS_REBALANCE: slot_id[ %d:%d ] Slot Quiesced",__FUNCTION__ ,
+					shpc_context->shpc_instance, slot_context->slot_number-1 );
+			}
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_power_cmd_available;
+		}
+		else {
+			spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+			//
+			// Cancel bus re-balancing and treat it as a "Slot Enabled" request
+			//
+			slot_context->slot_completion.hw_initiated = TRUE;
+			slot_context->slot_completion.type = SHPC_ASYNC_ENABLE_SLOT;
+			slot_context->slot_completion.request_context = NULL;
+			slot_context->slot_completion.failed = HP_FALSE;
+			slot_context->slot_completion.done = TRUE;
+
+			dbg("%s -->BUS_REBALANCE: slot_id[ %d:%d ] Cancelled: BUSY DevNode",__FUNCTION__ ,
+				shpc_context->shpc_instance, slot_context->slot_number-1 );
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_slot_request;
+		}
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_enabled_wait_for_power_cmd_available() 
+//
+// ****************************************************************************
+long
+hp_at_slot_enabled_wait_for_power_cmd_available(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+)
+{
+	struct task_struct;
+	union SHPC_COMMAND_WREG command_reg;
+	unsigned long	old_irq_flags;
+	long status = STATUS_SUCCESS;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Wait for Command Available MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_ACQUIRE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_acquire_event);
+
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+
+		//
+		// Notify unrequested removal
+		//
+		slot_context->slot_completion.hw_initiated = TRUE;
+		slot_context->slot_completion.type = SHPC_ASYNC_SURPRISE_REMOVE;
+		slot_context->slot_completion.failed = HP_FALSE;
+		slot_context->slot_completion.request_context = NULL;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// cmd_available_mutex
+	//
+	else if(shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) {
+		//
+		// Clear Completion EVENT before issuing next command
+		//
+		spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+		hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT);
+		spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+		//
+		// Set slot to "Disable" and blink Power LED
+		//
+		command_reg.Slot.code = SHPC_SLOT_OPERATION;
+		command_reg.Slot.power_led = SHPC_LED_BLINK;
+		command_reg.Slot.attention_led = SHPC_led_NO_CHANGE;
+		command_reg.Slot.state = SHPC_DISABLE_SLOT;
+		command_reg.Slot.TGT = slot_context->slot_number;
+		writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET);
+
+		//
+		// Wait for command to complete (while holding MUTEX)
+		//
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_power_cmd_completion;
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_enabled_wait_for_power_cmd_completion()
+//
+// ****************************************************************************
+long
+hp_at_slot_enabled_wait_for_power_cmd_completion(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SLOT_STATUS_INFO slot_status;
+	union SHPC_STATUS_WREG status_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER2_EVENT);
+	slot_context->slot_timer2.data = (unsigned long)slot_context;
+	slot_context->slot_timer2.function = hp_slot_timer2_func;
+	slot_context->slot_timer2.expires = jiffies + FIFTEEN_SEC_TIMEOUT;
+	add_timer(&slot_context->slot_timer2);
+
+	//
+	// Wait for Command Completion EVENT while holding MUTEX
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_TIMER2_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER2_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->slot_timer2);
+	}
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Notify unrequested removal
+		//
+		slot_context->slot_completion.hw_initiated = TRUE;
+		slot_context->slot_completion.type = SHPC_ASYNC_SURPRISE_REMOVE;
+		slot_context->slot_completion.failed = HP_FALSE;
+		slot_context->slot_completion.request_context = NULL;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// cmd_completion_event, timeout
+	//
+		else if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+				(slot_context->slot_event_bits & SLOT_TIMER2_EVENT)) {
+		//
+		// Command completed OK?
+		//
+		status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET);
+
+		if( status_reg.x.BSY == SHPC_STATUS_CLEARED &&
+			status_reg.x.MRLO_ERR == SHPC_STATUS_CLEARED &&
+			status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED ) {
+			//
+			// Flag this slot as DISABLED
+			//
+			hp_flag_slot_as_disabled( shpc_context, slot_context );
+
+			//
+			// Call Completion Callback(): slot disabled
+			//
+			hp_QuerySlotStatus(	shpc_context, slot_context->slot_number - 1, &slot_status );
+			slot_status.x.lu_request_failed = HP_FALSE;
+			shpc_context->async_callback(
+				shpc_context->driver_context,
+				slot_context->slot_number - 1,
+				SHPC_ASYNC_DISABLE_SLOT,
+				slot_status,
+				NULL );
+
+			//
+			// Signal registered user EVENT
+			//
+			hp_signal_user_event( shpc_context );
+
+			//
+			// Treat it as an on-going ENABLE request
+			//
+			slot_context->slot_completion.hw_initiated = TRUE;
+			slot_context->slot_completion.type = SHPC_ASYNC_ENABLE_SLOT;
+			slot_context->slot_completion.request_context = NULL;
+
+			//
+			// Grab Command MUTEX to power-on the slot
+			//
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_power_cmd_available;
+		}
+		else {
+			//
+			// Treat it as a HW-initiated DISABLE request
+			//
+			slot_context->slot_completion.hw_initiated = TRUE;
+			slot_context->slot_completion.type = SHPC_ASYNC_DISABLE_SLOT;
+			slot_context->slot_completion.failed = HP_FALSE;
+			slot_context->slot_completion.request_context = NULL;
+			slot_context->slot_completion.done = TRUE;
+
+			//
+			// Grab Command MUTEX to disable slot
+			//
+			dbg("%s -->CMD_ERROR: slot_id[ %d:%d ]  Cmd[ %X ]",__FUNCTION__ ,
+				shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord );
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+		}
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		status = STATUS_UNSUCCESSFUL;
+	}
+	//
+	// Release Command MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_release_event);
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_enabled_wait_for_led_cmd_available()
+//
+// ****************************************************************************
+long
+hp_at_slot_enabled_wait_for_led_cmd_available(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SHPC_COMMAND_WREG command_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Wait for Command Available MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_acquire_event);
+
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// cmd_available_mutex
+	//
+	else if(shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) {
+		//
+		// Clear Completion EVENT before issuing next command
+		//
+		spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+		hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT);
+		spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+		//
+		// Blink Power LED
+		//
+		command_reg.Slot.code = SHPC_SLOT_OPERATION;
+		command_reg.Slot.power_led = SHPC_LED_BLINK;
+		command_reg.Slot.attention_led = SHPC_led_NO_CHANGE;
+		command_reg.Slot.state = SHPC_SLOT_NO_CHANGE;
+		command_reg.Slot.TGT = slot_context->slot_number;
+		writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET);
+
+		//
+		// Wait for command to complete (while holding MUTEX)
+		//
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_led_cmd_completion;
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+		status =STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_enabled_wait_for_led_cmd_completion()
+//
+// ****************************************************************************
+long
+hp_at_slot_enabled_wait_for_led_cmd_completion(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SLOT_STATUS_INFO slot_status;
+	union SHPC_STATUS_WREG status_reg;
+	unsigned long  DevNodes;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER3_EVENT);
+	slot_context->slot_timer3.data = (unsigned long)slot_context;
+	slot_context->slot_timer3.function = hp_slot_timer3_func;
+	slot_context->slot_timer3.expires = jiffies + ONE_SEC_TIMEOUT;
+	add_timer(&slot_context->slot_timer3);
+
+	//
+	// Wait for Command Completion EVENT while holding MUTEX
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+		 (slot_context->slot_event_bits & ALERT_EVENT) ||
+		 (slot_context->slot_event_bits & SLOT_TIMER3_EVENT) ||
+		 (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER3_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->slot_timer3);
+	}
+	dbg("%s -->slot bits %08X   shpc bits  %08X",__FUNCTION__ ,
+		slot_context->slot_event_bits,shpc_context->shpc_event_bits);
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// cmd_completion_event, timeout
+	//
+	else if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+			(slot_context->slot_event_bits & SLOT_TIMER3_EVENT)) {
+		//
+		// Command completed OK?
+		//
+		status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET);
+
+		if( status_reg.x.BSY == SHPC_STATUS_CLEARED &&
+			status_reg.x.MRLO_ERR == SHPC_STATUS_CLEARED &&
+			status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED ) {
+			//
+			// Allow cancellation of operation?
+			//
+			if( slot_context->slot_completion.hw_initiated ) {
+				//
+				// Wait for 5 sec timeout
+				//
+				slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_timeout;
+			}
+			else {
+				//
+				// Clear Quiesced EVENT before invoking Callback()
+				//
+				spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+				slot_context->quiesce_requests = 0;
+				slot_context->quiesce_replies = 0;
+				slot_context->slot_quiesced = FALSE;
+				hp_clear_slot_event_bit(slot_context, QUIESCE_EVENT);
+				spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+				//
+				// Call Completion Callback() to quiesce DevNode(s)
+				//
+				slot_status.AsDWord = 0;
+				DevNodes = shpc_context->async_callback(
+					shpc_context->driver_context,
+					slot_context->slot_number - 1,
+					SHPC_ASYNC_QUIESCE_DEVNODE,
+					slot_status,
+					( void* )(unsigned long)slot_context->slot_psn );
+
+				//
+				// Update request count
+				//
+				spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+				slot_context->quiesce_requests = DevNodes;
+				if( slot_context->quiesce_requests == 0 ||
+					slot_context->quiesce_replies >= slot_context->quiesce_requests ) {
+					slot_context->slot_quiesced = TRUE;
+					hp_send_slot_event(slot_context, QUIESCE_EVENT);
+				}
+				spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+				//
+				// Wait for DevNode quiescing
+				//
+				slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_stop_on_slot_disable;
+			}
+		}
+		else {
+			//
+			// Fail on-going request
+			//
+			slot_context->slot_completion.failed = HP_TRUE;
+			slot_context->slot_completion.done = TRUE;
+
+			//
+			// Grab Command MUTEX to disable slot
+			//
+			dbg("%s -->CMD_ERROR: slot_id[ %d:%d ]  Cmd[ %X ]",__FUNCTION__ ,
+				shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord );
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+		}
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		status = STATUS_UNSUCCESSFUL;
+	}
+	//
+	// Release Command MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_release_event);
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_enabled_wait_for_timeout()
+//
+// ****************************************************************************
+long
+hp_at_slot_enabled_wait_for_timeout(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SLOT_STATUS_INFO slot_status;
+	unsigned long  DevNodes;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Clear Button EVENT before waiting
+	//
+	spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+	down_interruptible(&slot_context->slot_event_bits_semaphore);
+	slot_context->slot_event_bits &= ~ATTN_BUTTON_EVENT;
+	up(&slot_context->slot_event_bits_semaphore);
+	spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER7_EVENT);
+	slot_context->slot_timer7.data = (unsigned long)slot_context;
+	slot_context->slot_timer7.function = hp_slot_timer7_func;
+	slot_context->slot_timer7.expires = jiffies + FIVE_SEC_TIMEOUT;
+	add_timer(&slot_context->slot_timer7);
+
+	//
+	// Wait for 5 sec timeout
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((slot_context->slot_event_bits & ATTN_BUTTON_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_TIMER7_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER7_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->slot_timer7);
+	}
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// attn_button_event
+	//
+	else if(slot_context->slot_event_bits & ATTN_BUTTON_EVENT) {
+		//
+		// Cancel request, grab Command MUTEX to Power LED back ON
+		//
+		dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ] Cancelled: Attn Button",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1 );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_enabled_wait_for_led_cmd_available;
+	}
+	//
+	// timeout
+	//
+	else if(slot_context->slot_event_bits & SLOT_TIMER7_EVENT) {
+		//
+		// Clear Quiesced EVENT before invoking Callback()
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->quiesce_requests = 0;
+		slot_context->quiesce_replies = 0;
+		slot_context->slot_quiesced = FALSE;
+		hp_clear_slot_event_bit(slot_context, QUIESCE_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Call Completion Callback() to quiesce DevNode(s)
+		//
+		slot_status.AsDWord = 0;
+		DevNodes = shpc_context->async_callback(
+			shpc_context->driver_context,
+			slot_context->slot_number - 1,
+			SHPC_ASYNC_QUIESCE_DEVNODE,
+			slot_status,
+			( void* )(unsigned long)slot_context->slot_psn );
+
+		//
+		// Update request count
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->quiesce_requests = DevNodes;
+		if( slot_context->quiesce_requests == 0 ||
+			slot_context->quiesce_replies == slot_context->quiesce_requests ) {
+			slot_context->slot_quiesced = TRUE;
+			hp_send_slot_event(slot_context, QUIESCE_EVENT);
+		}
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Wait for DevNode quiescing
+		//
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_stop_on_slot_disable;
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		status = STATUS_UNSUCCESSFUL;
+	}
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_enabled_wait_for_stop_on_slot_disable()
+//
+// ****************************************************************************
+long
+hp_at_slot_enabled_wait_for_stop_on_slot_disable(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SLOT_STATUS_INFO slot_status;
+	unsigned long  DevNodes;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__ ,shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER4_EVENT);
+	slot_context->slot_timer4.data = (unsigned long)slot_context;
+	slot_context->slot_timer4.function = hp_slot_timer4_func;
+	slot_context->slot_timer4.expires = jiffies + QUIESCE_QUIET_TIMEOUT;
+	add_timer(&slot_context->slot_timer4);
+
+	//
+	// Wait for Quiescing EVENT
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((slot_context->slot_event_bits & QUIESCE_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_TIMER4_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER4_EVENT)) {
+	//
+	// delete the timer because we got an event other than the timer
+	//
+		del_timer_sync(&slot_context->slot_timer4);
+	}
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// quiesce_event
+	//
+	else if(slot_context->slot_event_bits & QUIESCE_EVENT) {
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		if( slot_context->slot_quiesced ) {
+			spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+			//
+			// Complete succesful DISABLE request
+			//
+			slot_context->slot_completion.failed = HP_FALSE;
+			slot_context->slot_completion.done = TRUE;
+
+			//
+			// Grab Command MUTEX to disable slot
+			//
+			//
+			dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ] Slot Quiesced",__FUNCTION__ ,
+				shpc_context->shpc_instance, slot_context->slot_number-1 );
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+		}
+		else {
+			spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+			//
+			// Cancel request, grab Command MUTEX to turn Power LED back ON
+			//
+			slot_context->slot_completion.hw_initiated = TRUE;
+			slot_context->slot_completion.type = SHPC_ASYNC_ENABLE_SLOT;
+			slot_context->slot_completion.request_context = NULL;
+			slot_context->slot_completion.failed = HP_FALSE;
+			slot_context->slot_completion.done = TRUE;
+
+			dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ] Cancelled: BUSY DevNode",__FUNCTION__ ,
+				shpc_context->shpc_instance, slot_context->slot_number-1 );
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_enabled_wait_for_led_cmd_available;
+		}
+	}
+	//
+	// timeout
+	//
+	else if(slot_context->slot_event_bits & SLOT_TIMER4_EVENT) {
+		//
+		// Clear Quiesced EVENT before invoking Callback()
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->quiesce_requests = 0;
+		slot_context->quiesce_replies = 0;
+		slot_context->slot_quiesced = FALSE;
+		hp_clear_slot_event_bit(slot_context, QUIESCE_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Call Completion Callback() to quiesce DevNode(s)
+		//
+		slot_status.AsDWord = 0;
+		DevNodes = shpc_context->async_callback(
+			shpc_context->driver_context,
+			slot_context->slot_number - 1,
+			SHPC_ASYNC_QUIESCE_DEVNODE_QUIET,
+			slot_status,
+			( void* )(unsigned long)slot_context->slot_psn );
+
+		//
+		// Update request count
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->quiesce_requests = DevNodes;
+		if( slot_context->quiesce_requests == 0 ||
+			slot_context->quiesce_replies == slot_context->quiesce_requests ) {
+			slot_context->slot_quiesced = TRUE;
+			hp_send_slot_event(slot_context, QUIESCE_EVENT);
+		}
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Wait for DevNode quiescing
+		//
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_stop_on_slot_disable_quiet;
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_enabled_wait_for_stop_on_slot_disable_quiet()
+//
+// ****************************************************************************
+long
+hp_at_slot_enabled_wait_for_stop_on_slot_disable_quiet(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__ ,shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER5_EVENT);
+	slot_context->slot_timer5.data = (unsigned long)slot_context;
+	slot_context->slot_timer5.function = hp_slot_timer5_func;
+	slot_context->slot_timer5.expires = jiffies + QUIESCE_QUIET_TIMEOUT;
+	add_timer(&slot_context->slot_timer5);
+
+	//
+	// Wait for Quiescing EVENT
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((slot_context->slot_event_bits & QUIESCE_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_TIMER5_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER5_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->slot_timer5);
+	}
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// quiesce_event, timeout
+	//
+	else if((slot_context->slot_event_bits & QUIESCE_EVENT) ||
+			(slot_context->slot_event_bits & SLOT_TIMER5_EVENT)) {
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		if((slot_context->slot_event_bits & SLOT_TIMER5_EVENT) || slot_context->slot_quiesced ) {
+			spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+			//
+			// Complete succesful DISABLE request
+			//
+			slot_context->slot_completion.failed = HP_FALSE;
+			slot_context->slot_completion.done = TRUE;
+
+			//
+			// Grab Command MUTEX to disable slot
+			//
+			//
+			if(slot_context->slot_event_bits & SLOT_TIMER5_EVENT) {
+				dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ] Quiesce timeout",__FUNCTION__ ,
+					shpc_context->shpc_instance, slot_context->slot_number-1 );
+			}
+			else {
+				dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ] Slot Quiesced",__FUNCTION__ ,
+					shpc_context->shpc_instance, slot_context->slot_number-1 );
+			}
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+		}
+		else {
+			spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+			//
+			// Cancel request, grab Command MUTEX to turn Power LED back ON
+			//
+			dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ] Cancelled: BUSY DevNode",__FUNCTION__ ,
+				shpc_context->shpc_instance, slot_context->slot_number-1 );
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_enabled_wait_for_led_cmd_available;
+		}
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_to_slot_enabled_wait_for_led_cmd_available()
+//
+// ****************************************************************************
+long
+hp_to_slot_enabled_wait_for_led_cmd_available(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SHPC_COMMAND_WREG command_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__ ,shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Wait for Command Available MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_ACQUIRE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_acquire_event);
+
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// cmd_available_mutex
+	//
+	else if(shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) {
+		//
+		// Clear Completion EVENT before issuing next command
+		//
+		spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+		hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT);
+		spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+		//
+		// Turn Power LED back ON
+		//
+		command_reg.Slot.code = SHPC_SLOT_OPERATION;
+		command_reg.Slot.power_led = SHPC_LED_ON;
+		command_reg.Slot.attention_led = SHPC_led_NO_CHANGE;
+		command_reg.Slot.state = SHPC_SLOT_NO_CHANGE;
+		command_reg.Slot.TGT = slot_context->slot_number;
+		writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET);
+
+		//
+		// Wait for command to complete (while holding MUTEX)
+		//
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_enabled_wait_for_led_cmd_completion;
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_to_slot_enabled_wait_for_led_cmd_completion()
+//
+// ****************************************************************************
+long
+hp_to_slot_enabled_wait_for_led_cmd_completion(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SHPC_STATUS_WREG status_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , (int)shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER6_EVENT);
+	slot_context->slot_timer6.data = (unsigned long)slot_context;
+	slot_context->slot_timer6.function = hp_slot_timer6_func;
+	slot_context->slot_timer6.expires = jiffies + ONE_SEC_TIMEOUT;
+	add_timer(&slot_context->slot_timer6);
+
+	//
+	// Wait for Command Completion EVENT while holding MUTEX
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_TIMER6_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER6_EVENT)) {
+	//
+	// delete the timer because we got an event other than the timer
+	//
+		del_timer_sync(&slot_context->slot_timer6);
+	}
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// cmd_completion_event, timeout
+	//
+		else if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+				(slot_context->slot_event_bits & SLOT_TIMER6_EVENT)) {
+		//
+		// Command completed OK?
+		//
+		status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET);
+
+		if( status_reg.x.BSY == SHPC_STATUS_CLEARED &&
+			status_reg.x.MRLO_ERR == SHPC_STATUS_CLEARED &&
+			status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED ) {
+			//
+			// Wait for next request
+			//
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_slot_request;
+		}
+		else {
+			//
+			// Fail on-going request
+			//
+			slot_context->slot_completion.failed = HP_TRUE;
+			slot_context->slot_completion.done = TRUE;
+
+			//
+			// Grab Command MUTEX to disable slot
+			//
+			dbg("%s -->CMD_ERROR: slot_id[ %d:%d ]  Cmd[ %X ]",__FUNCTION__ ,
+				shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord );
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+		}
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		status = STATUS_UNSUCCESSFUL;
+	}
+	//
+	// Release Command MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_release_event);
+
+	return status;
+}
+
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/amdshpc_enb.c	Wed Mar 17 11:19:43 2004
@@ -0,0 +1,2112 @@
+/*
+ * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001,2003 IBM Corp.
+ * Copyright (C) 2002-2003 Advanced Micro Devices
+ *
+ * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS
+ * AND CONDITIONS OF THE GNU GENERAL PUBLIC
+ * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS
+ * INCLUDED WITH THIS FILE AND POSTED AT
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Send feedback to <david.keck@amd.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include "amdshpc_ddi.h"
+#include "amdshpc.h"
+
+
+// ****************************************************************************
+//
+// hp_at_slot_disabled_wait_for_slot_request()
+//
+// ****************************************************************************
+long
+hp_at_slot_disabled_wait_for_slot_request(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SLOT_STATUS_INFO slot_status;
+	union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__ ,shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Slot Disabled: complete pending slot request
+	//
+	if( slot_context->slot_completion.done ) {
+		dbg("%s -->DISABLE_DONE: slot_id[ %d:%d ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1 );
+		//
+		// Call Completion Callback()
+		//
+		hp_QuerySlotStatus(	shpc_context, slot_context->slot_number - 1, &slot_status );
+		slot_status.x.lu_request_failed = slot_context->slot_completion.failed;
+		shpc_context->async_callback(
+			shpc_context->driver_context,
+			slot_context->slot_number - 1,
+			slot_context->slot_completion.type,
+			slot_status,
+			slot_context->slot_completion.request_context );
+
+		//
+		// Signal registered user EVENT
+		//
+		hp_signal_user_event( shpc_context );
+
+		//
+		// Clear completion flag
+		//
+		slot_context->slot_completion.done = FALSE;
+	}
+
+	//
+	// Clear Button EVENT before waiting
+	//
+	spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+	hp_clear_slot_event_bit(slot_context, ATTN_BUTTON_EVENT);
+	spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+	//
+	// Wait for slot request
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((slot_context->slot_event_bits & ATTN_BUTTON_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_REQUEST_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	//
+	// attn_button_event
+	//
+	if(slot_context->slot_event_bits & ATTN_BUTTON_EVENT) {
+		//
+		// Set completion info for HW-initiated request
+		//
+		slot_context->slot_completion.hw_initiated = TRUE;
+		slot_context->slot_completion.type = SHPC_ASYNC_ENABLE_SLOT;
+		slot_context->slot_completion.request_context = NULL;
+
+		//
+		// Get current HW disposition
+		//
+		logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr );
+		//
+		// Card present, MRL closed, and no Power-Fault?
+		//
+		if( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY &&
+			( logical_slot_reg.x.MRLS_IM == SHPC_MASKED ||
+			logical_slot_reg.x.MRLS == SHPC_MRL_CLOSED ) &&
+			logical_slot_reg.x.PF == SHPC_STATUS_CLEARED ) {
+			//
+			// Clear Alert EVENT and Attention LED
+			//
+			spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+			hp_clear_slot_event_bit(slot_context, ALERT_EVENT);
+			slot_context->problem_detected = FALSE;
+			hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+			spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+			//
+			// Grab Command MUTEX to blink Power LED
+			//
+			dbg("%s -->ENABLE_REQ: slot_id[ %d:%d ]",__FUNCTION__ ,
+				shpc_context->shpc_instance, slot_context->slot_number-1 );
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_led_cmd_available;
+		}
+		//
+		// Alert: MRL Opened, Power-Fault?
+		//
+		else if( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY ) {
+			//
+			// Update Attention LED
+			//
+			spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+			slot_context->problem_detected = TRUE;
+			hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+			spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+			//
+			// Fail on-going request
+			//
+			slot_context->slot_completion.failed = HP_TRUE;
+			slot_context->slot_completion.done = TRUE;
+			dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+				shpc_context->shpc_instance, slot_context->slot_number-1,
+				logical_slot_reg.AsDWord & 0x3F );
+		}
+	}
+	//
+	// SlotRequestEvent
+	//
+	else if(slot_context->slot_event_bits & SLOT_REQUEST_EVENT) {
+		//
+		// Set completion info for SW-initiated request
+		//
+		slot_context->slot_completion.hw_initiated = FALSE;
+		slot_context->slot_completion.type = slot_context->slot_request.type;
+		slot_context->slot_completion.request_context = slot_context->slot_request.request_context;
+
+		//
+		// Request to enable slot?
+		//
+		if( slot_context->slot_request.type == SHPC_ASYNC_ENABLE_SLOT ) {
+			//
+			// Update alert events based on current HW disposition
+			//
+			logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr );
+			//
+			// Card present, MRL closed, and no Power-Fault?
+			//
+			if( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY &&
+				(logical_slot_reg.x.MRLS_IM == SHPC_MASKED ||
+				logical_slot_reg.x.MRLS == SHPC_MRL_CLOSED ) &&
+				logical_slot_reg.x.PF == SHPC_STATUS_CLEARED ) {
+				//
+				// Clear Alert EVENT and Attention LED
+				//
+				spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+				slot_context->problem_detected = FALSE;
+				hp_clear_slot_event_bit(slot_context, ALERT_EVENT);
+				hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+				spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+				//
+				// Grab Command MUTEX to blink Power LED
+				//
+				dbg("%s -->ENABLE_REQ: slot_id[ %d:%d ]",__FUNCTION__ ,
+					shpc_context->shpc_instance, slot_context->slot_number-1 );
+				slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_led_cmd_available;
+			}
+			//
+			// Alert: MRL Opened, Power-Fault?
+			//
+			else if( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY ) {
+				//
+				// Update Attention LED
+				//
+				spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+				slot_context->problem_detected = TRUE;
+				hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+				spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+				//
+				// Fail on-going request
+				//
+				slot_context->slot_completion.failed = HP_TRUE;
+				slot_context->slot_completion.done = TRUE;
+				dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+					shpc_context->shpc_instance, slot_context->slot_number-1,
+					logical_slot_reg.AsDWord & 0x3F );
+			}
+		}
+		else {
+			//
+			// Slot already disabled, just complete the request
+			//
+			dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ]",__FUNCTION__ ,
+				shpc_context->shpc_instance, slot_context->slot_number-1 );
+			slot_context->slot_completion.failed = HP_FALSE;
+			slot_context->slot_completion.done = TRUE;
+		}
+
+		//
+		// Allow next SW-initiated slot request while processing this one
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		hp_clear_slot_event_bit(slot_context, SLOT_REQUEST_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_disabled_wait_for_led_cmd_available()
+//
+// ****************************************************************************
+long
+hp_at_slot_disabled_wait_for_led_cmd_available(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SHPC_COMMAND_WREG command_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+	//
+	// Wait for Command Available MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_ACQUIRE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_acquire_event);
+
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_REQUEST_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Wait for next request
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			(readl( slot_context->logical_slot_addr ) & 0x3F ));
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_slot_request;
+	}
+	//
+	// cmd_available_mutex
+	//
+	else if(shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) {
+		//
+		// Clear Completion EVENT before issuing next command
+		//
+		spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+		hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT);
+		spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+		//
+		// Blink Power LED
+		//
+		command_reg.Slot.code = SHPC_SLOT_OPERATION;
+		command_reg.Slot.power_led = SHPC_LED_BLINK;
+		command_reg.Slot.attention_led = SHPC_led_NO_CHANGE;
+		command_reg.Slot.state = SHPC_SLOT_NO_CHANGE;
+		command_reg.Slot.TGT = slot_context->slot_number;
+		writew(command_reg.AsWord ,shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET);
+
+		//
+		// Wait for command to complete (while holding MUTEX)
+		//
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_led_cmd_completion;
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_disabled_wait_for_led_cmd_completion()
+//
+// ****************************************************************************
+long
+hp_at_slot_disabled_wait_for_led_cmd_completion(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long	old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SHPC_STATUS_WREG status_reg;
+
+	dbg( "%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER1_EVENT);
+	slot_context->slot_timer1.data = (unsigned long)slot_context;
+	slot_context->slot_timer1.function = hp_slot_timer1_func;
+	slot_context->slot_timer1.expires = jiffies + ONE_SEC_TIMEOUT;
+	add_timer(&slot_context->slot_timer1);
+
+	//
+	// Wait for Command Completion EVENT while holding MUTEX
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_TIMER1_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER1_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->slot_timer1);
+	}
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to make sure Power LED is OFF
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_led_cmd_available;
+	}
+	//
+	// cmd_completion_event, timeout
+	//
+	else if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+			(slot_context->slot_event_bits & SLOT_TIMER1_EVENT)) {
+		//
+		// Command completed OK?
+		//
+		status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET);
+
+		if( status_reg.x.BSY == SHPC_STATUS_CLEARED &&
+			status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED ) {
+			//
+			// Allow cancellation of operation?
+			//
+			if( slot_context->slot_completion.hw_initiated ) {
+				//
+				// Wait for 5 sec timeout
+				//
+				slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_timeout;
+			}
+			else {
+				//
+				// Grab Command MUTEX to power-on the slot
+				//
+				slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_power_cmd_available;
+			}
+		}
+		else {
+			//
+			// Fail on-going request
+			//
+			slot_context->slot_completion.failed = HP_TRUE;
+			slot_context->slot_completion.done = TRUE;
+
+			//
+			// Grab Command MUTEX to make sure Power LED is OFF
+			//
+			dbg("%s -->CMD_ERROR: slot_id[ %d:%d ]  Cmd[ %X ]",__FUNCTION__ ,
+				shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord );
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_led_cmd_available;
+		}
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		status = STATUS_UNSUCCESSFUL;
+	}
+	//
+	// Release Command MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_release_event);
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_disabled_wait_for_timeout()
+//
+// ****************************************************************************
+long
+hp_at_slot_disabled_wait_for_timeout(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__ ,shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Clear Button EVENT before waiting
+	//
+	spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+	hp_clear_slot_event_bit(slot_context, ATTN_BUTTON_EVENT);
+	spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER2_EVENT);
+	slot_context->slot_timer2.data = (unsigned long)slot_context;
+	slot_context->slot_timer2.function = hp_slot_timer2_func;
+	slot_context->slot_timer2.expires = jiffies + FIVE_SEC_TIMEOUT;
+	add_timer(&slot_context->slot_timer2);
+
+	//
+	// Wait for 5 sec timeout
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((slot_context->slot_event_bits & ATTN_BUTTON_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_TIMER2_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER2_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->slot_timer2);
+	}
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to turn OFF Power LED
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_led_cmd_available;
+	}
+	//
+	// attn_button_event
+	//
+	else if(slot_context->slot_event_bits & ATTN_BUTTON_EVENT) {
+		//
+		// Cancel request, grab Command MUTEX to turn OFF Power LED
+		//
+		dbg("%s -->ENABLE_REQ: slot_id[ %d:%d ] Cancelled: Attn Button",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1 );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_led_cmd_available;
+	}
+	//
+	// timeout
+	//
+	else if(slot_context->slot_event_bits & SLOT_TIMER2_EVENT) {
+		//
+		// Grab Command MUTEX to set slot at Power-Only state
+		//
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_power_cmd_available;
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_disabled_wait_for_power_cmd_available()
+//
+// ****************************************************************************
+long
+hp_at_slot_disabled_wait_for_power_cmd_available(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SHPC_COMMAND_WREG command_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Wait for Command Available MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_ACQUIRE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_acquire_event);
+
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to turn OFF Power LED
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_led_cmd_available;
+	}
+	//
+	// cmd_available_mutex
+	//
+	else if(shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) {
+		//
+		// Clear Completion EVENT before issuing next command
+		//
+		spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+		hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT);
+		spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+		//
+		// Power-on the slot
+		//
+		command_reg.Slot.code = SHPC_SLOT_OPERATION;
+		command_reg.Slot.power_led = SHPC_led_NO_CHANGE;
+		command_reg.Slot.attention_led = SHPC_led_NO_CHANGE;
+		command_reg.Slot.state = SHPC_POWER_ONLY;
+		command_reg.Slot.TGT = slot_context->slot_number;
+		writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET);
+
+		//
+		// Wait for 100ms completion pre-amble on RevB-Errata (while holding MUTEX)
+		//
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_power_cmd_timeout;
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_disabled_wait_for_power_cmd_timeout()
+//
+// ****************************************************************************
+long
+hp_at_slot_disabled_wait_for_power_cmd_timeout(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER3_EVENT);
+	slot_context->slot_timer3.data = (unsigned long)slot_context;
+	slot_context->slot_timer3.function = hp_slot_timer3_func;
+	slot_context->slot_timer3.expires = jiffies + ONE_TENTH_SEC_TIMEOUT;
+	add_timer(&slot_context->slot_timer3);
+
+	//
+	// Wait for 100ms completion pre-amble on RevB-Errata (while holding MUTEX)
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((slot_context->slot_event_bits & ALERT_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_TIMER3_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER3_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->slot_timer3);
+	}
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// timeout
+	//
+	else if(slot_context->slot_event_bits & SLOT_TIMER3_EVENT) {
+		//
+		// Wait for command to complete (while holding MUTEX)
+		//
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_power_cmd_completion;
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_disabled_wait_for_power_cmd_completion()
+//
+// ****************************************************************************
+long
+hp_at_slot_disabled_wait_for_power_cmd_completion(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SHPC_STATUS_WREG status_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER4_EVENT);
+	slot_context->slot_timer4.data = (unsigned long)slot_context;
+	slot_context->slot_timer4.function = hp_slot_timer4_func;
+	slot_context->slot_timer4.expires = jiffies + FIFTEEN_SEC_TIMEOUT;
+	add_timer(&slot_context->slot_timer4);
+
+	//
+	// Wait for Command Completion EVENT while holding MUTEX
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_TIMER4_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER4_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->slot_timer4);
+	}
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// cmd_completion_event, timeout
+	//
+	else if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+			(slot_context->slot_event_bits & SLOT_TIMER4_EVENT)) {
+		//
+		// Command completed OK?
+		//
+		status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET);
+
+		if( status_reg.x.BSY == SHPC_STATUS_CLEARED &&
+			status_reg.x.MRLO_ERR == SHPC_STATUS_CLEARED &&
+			status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED ) {
+			//
+			// Grab Bus MUTEX to validate speed/mode
+			//
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_bus_available;
+		}
+		else {
+			//
+			// Fail on-going request
+			//
+			slot_context->slot_completion.failed = HP_TRUE;
+			slot_context->slot_completion.done = TRUE;
+
+			//
+			// Grab Command MUTEX to disable slot
+			//
+			dbg("%s -->CMD_ERROR: slot_id[ %d:%d ]  Cmd[ %X ]",__FUNCTION__ ,
+				shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord );
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+		}
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		status = STATUS_UNSUCCESSFUL;
+	}
+
+	//
+	// Release Command MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_release_event);
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_disabled_wait_for_bus_available()
+//
+// ****************************************************************************
+long
+hp_at_slot_disabled_wait_for_bus_available(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	enum shpc_speed_mode max_speed_mode, bus_speed_mode;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Wait for Bus Available MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, BUS_ACQUIRE_EVENT);
+	wake_up_interruptible(&slot_context->bus_acquire_event);
+
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & BUS_AVAILABLE_MUTEX_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Release Bus MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->bus_release_event);
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// bus_available_mutex
+	//
+	else if(shpc_context->shpc_event_bits & BUS_AVAILABLE_MUTEX_EVENT) {
+		//
+		// Get current HW speed/mode
+		//
+		bus_speed_mode = hp_get_bus_speed_mode( shpc_context );
+		max_speed_mode = hp_get_card_speed_mode( slot_context );
+		if( max_speed_mode > shpc_context->max_speed_mode ) {
+			//
+			// Can only go as fast as the controller allows
+			//
+			max_speed_mode = shpc_context->max_speed_mode;
+		}
+
+		//
+		// Grab global spinlock to check current speed/mode settings
+		//
+		spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+
+		//
+		// Other slots in contetion for bus speed/mode changes?
+		//
+		slot_context->in_bus_speed_mode_contention = FALSE;
+		max_speed_mode = hp_get_max_speed_mode( shpc_context, max_speed_mode );
+
+		//
+		// Make this card can handle PCI-66 speed/mode
+		//
+		if( max_speed_mode == SHPC_BUS_CONV_66 && !slot_context->card_pci66_capable ) {
+			//
+			// Fall back to slower common denominator
+			//
+			max_speed_mode = SHPC_BUS_CONV_33;
+		}
+
+		//
+		// Bus running at incompatible speed/mode?
+		//
+		if( bus_speed_mode != max_speed_mode ) {
+			//
+			// Other slots already enabled?
+			//
+			if( hp_signal_enabled_slots_to_rebalance_bus( shpc_context )) {
+				//
+				// Wait for enabled slots to release the bus, then change bus speed/mode
+				//
+				shpc_context->bus_speed_mode = max_speed_mode;
+				shpc_context->bus_released = FALSE;
+				hp_clear_shpc_event_bit(shpc_context, BUS_COMPLETE_EVENT);
+				slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_bus_released;
+			}
+			else {
+				//
+				// Change bus speed/mode to enable this slot
+				//
+				shpc_context->bus_speed_mode = max_speed_mode;
+				slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_speed_mode_cmd_available;
+			}
+		}
+		else {
+			//
+			// Enable slot at current bus speed/mode
+			//
+			shpc_context->bus_speed_mode = bus_speed_mode;
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_enable_cmd_available;
+		}
+
+		//
+		// Flag this slot in contention for bus speed/mode validation
+		//
+		slot_context->in_bus_speed_mode_contention = TRUE;
+
+		//
+		// Release global spinlock since we're done checking speed/mode
+		//
+		spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+		dbg("%s -->ENABLE_IN_PROGRESS: slot_id[ %d:%d ]  card_speed_mode[ %d+%d ]  bus_speed_mode[ %d=>%d ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			slot_context->card_speed_mode, slot_context->card_pci66_capable,
+			bus_speed_mode, shpc_context->bus_speed_mode );
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		//
+		// Release Bus MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->bus_release_event);
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_disabled_wait_for_bus_released() 
+//
+// ****************************************************************************
+long
+hp_at_slot_disabled_wait_for_bus_released(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Wait for Bus Release EVENT while holding MUTEX
+	//
+	shpc_context->shpc_event_bits = 0;slot_context->slot_event_bits = 0;
+
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & BUS_RELEASE_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Release Bus MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->bus_release_event);
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// bus_release_event
+	//
+	else if(shpc_context->shpc_event_bits & BUS_RELEASE_EVENT) {
+		spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+		if( shpc_context->bus_released ) {
+			spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+			//
+			// Grab Command MUTEX to set Bus speed/mode
+			//
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_speed_mode_cmd_available;
+		}
+		else {
+			spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+			//
+			// Release Bus MUTEX
+			//
+			hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+			wake_up_interruptible(&slot_context->bus_release_event);
+
+			//
+			// Fail on-going request
+			//
+			slot_context->slot_completion.failed = HP_TRUE;
+			slot_context->slot_completion.done = TRUE;
+
+			//
+			// Grab Command MUTEX to disable slot
+			//
+			dbg("%s -->ENABLE_REQ: slot_id[ %d:%d ] Cancelled: BUSY DevNode",__FUNCTION__ ,
+				shpc_context->shpc_instance, slot_context->slot_number-1 );
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+		}
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		//
+		// Release Bus MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->bus_release_event);
+		status =STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_disabled_wait_for_speed_mode_cmd_available()
+//
+// ****************************************************************************
+long
+hp_at_slot_disabled_wait_for_speed_mode_cmd_available(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SHPC_COMMAND_WREG command_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Wait for Command Available MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_ACQUIRE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_acquire_event);
+
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Release Bus, Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+		hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->bus_release_event);
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// cmd_available_mutex
+	//
+	else if(shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) {
+		//
+		// Clear Completion EVENT before issuing next command
+		//
+		spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+		hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT);
+		spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+		//
+		// Set Bus speed/mode
+		//
+		command_reg.Bus.code = SHPC_SET_BUS_SPEED_MODE;
+		command_reg.Bus.speed_mode = shpc_context->bus_speed_mode;
+		writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET);
+
+		//
+		// Wait for command to complete (while holding MUTEX)
+		//
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_speed_mode_cmd_completion;
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		//
+		// Release Bus, Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+		hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->bus_release_event);
+		status =STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_disabled_wait_for_speed_mode_cmd_completion()
+//
+// ****************************************************************************
+long
+hp_at_slot_disabled_wait_for_speed_mode_cmd_completion(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SHPC_STATUS_WREG status_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER5_EVENT);
+	slot_context->slot_timer5.data = (unsigned long)slot_context;
+	slot_context->slot_timer5.function = hp_slot_timer5_func;
+	slot_context->slot_timer5.expires = jiffies + FIFTEEN_SEC_TIMEOUT;
+	add_timer(&slot_context->slot_timer5);
+
+	//
+	// Wait for Command Completion EVENT while holding MUTEX
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_TIMER5_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER5_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->slot_timer5);
+	}
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Release Bus MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->bus_release_event);
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// cmd_completion_event, timeout
+	//
+	else if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+			(slot_context->slot_event_bits & SLOT_TIMER5_EVENT)) {
+
+		//
+		// Command completed OK?
+		//
+		status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET);
+
+		if( status_reg.x.BSY == SHPC_STATUS_CLEARED &&
+			status_reg.x.MRLO_ERR == SHPC_STATUS_CLEARED &&
+			status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED &&
+			status_reg.x.INVSM_ERR == SHPC_STATUS_CLEARED ) {
+			//
+			// Grab Command MUTEX to enable slot
+			//
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_enable_cmd_available;
+		}
+		else {
+			//
+			// Release Bus MUTEX
+			//
+			hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+			wake_up_interruptible(&slot_context->bus_release_event);
+
+			//
+			// Fail on-going request
+			//
+			slot_context->slot_completion.failed = HP_TRUE;
+			slot_context->slot_completion.done = TRUE;
+
+			//
+			// Grab Command MUTEX to disable slot
+			//
+			dbg("%s -->CMD_ERROR: slot_id[ %d:%d ]  Cmd[ %X ]",__FUNCTION__ ,
+				shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord );
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+		}
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		//
+		// Release Bus MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->bus_release_event);
+		status =STATUS_UNSUCCESSFUL;
+	}
+	//
+	// Release Command MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_release_event);
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_disabled_wait_for_enable_cmd_available() 
+//
+// ****************************************************************************
+long
+hp_at_slot_disabled_wait_for_enable_cmd_available(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SHPC_COMMAND_WREG command_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Wait for Command Available MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_ACQUIRE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_acquire_event);
+
+	 wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Release Bus, Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->bus_release_event);
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]",__FUNCTION__ ,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// cmd_available_mutex
+	//
+	else if(shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) {
+		//
+		// Clear Completion EVENT before issuing next command
+		//
+		spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+		hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT);
+		spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+		//
+		// Enable the slot
+		//
+		dbg("%s  ENABLING SLOT...",__FUNCTION__ );
+		command_reg.Slot.code = SHPC_SLOT_OPERATION;
+		command_reg.Slot.power_led = SHPC_LED_ON;
+		command_reg.Slot.attention_led = SHPC_led_NO_CHANGE;
+		command_reg.Slot.state = SHPC_ENABLE_SLOT;
+		command_reg.Slot.TGT = slot_context->slot_number;
+		writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET);
+
+		//
+		// Wait for command to complete (while holding Bus,Command MUTEX)
+		//
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_enable_cmd_completion;
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		//
+		// Release Bus, Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->bus_release_event);
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_disabled_wait_for_enable_cmd_completion()
+//
+// ****************************************************************************
+long
+hp_at_slot_disabled_wait_for_enable_cmd_completion(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SHPC_STATUS_WREG status_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER6_EVENT);
+	slot_context->slot_timer6.data = (unsigned long)slot_context;
+	slot_context->slot_timer6.function = hp_slot_timer6_func;
+	slot_context->slot_timer6.expires = jiffies + FIFTEEN_SEC_TIMEOUT;
+	add_timer(&slot_context->slot_timer6);
+
+	//
+	// Wait for Command Completion EVENT while holding MUTEX
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+		(slot_context->slot_event_bits & ALERT_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_TIMER6_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER6_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->slot_timer6);
+	}
+
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Release Bus MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->bus_release_event);
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]", __FUNCTION__,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// cmd_completion_event, timeout
+	//
+	else if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+			(slot_context->slot_event_bits & SLOT_TIMER6_EVENT)) {
+		//
+		// Command completed OK?
+		//
+		status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET);
+
+		if( status_reg.x.BSY == SHPC_STATUS_CLEARED &&
+			status_reg.x.MRLO_ERR == SHPC_STATUS_CLEARED &&
+			status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED &&
+			status_reg.x.INVSM_ERR == SHPC_STATUS_CLEARED ) {
+			//
+			// Wait for settling time
+			//
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_enable_timeout;
+		}
+		else {
+			//
+			// Release Bus MUTEX
+			//
+			hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+			wake_up_interruptible(&slot_context->bus_release_event);
+
+			//
+			// Fail on-going request
+			//
+			slot_context->slot_completion.failed = HP_TRUE;
+			slot_context->slot_completion.done = TRUE;
+
+			//
+			// Grab Command MUTEX to disable slot
+			//
+			dbg("%s -->CMD_ERROR: slot_id[ %d:%d ]  Cmd[ %X ]", __FUNCTION__,
+				shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord );
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+		}
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		//
+		// Release Bus MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->bus_release_event);
+		status = STATUS_UNSUCCESSFUL;
+	}
+	//
+	// Release Command MUTEX
+	//
+	up( &shpc_context->cmd_available_mutex);
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_at_slot_disabled_wait_for_enable_timeout()
+//
+// ****************************************************************************
+long
+hp_at_slot_disabled_wait_for_enable_timeout(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER7_EVENT);
+	slot_context->slot_timer7.data = (unsigned long)slot_context;
+	slot_context->slot_timer7.function = hp_slot_timer7_func;
+	slot_context->slot_timer7.expires = jiffies + ONE_SEC_TIMEOUT;
+	add_timer(&slot_context->slot_timer7);
+
+	//
+	// Wait for timeout
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((slot_context->slot_event_bits & ALERT_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_TIMER7_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER7_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->slot_timer7);
+	}
+	//
+	// Alert: MRL Opened, Card Removed, Power-Fault?
+	//
+	if(slot_context->slot_event_bits & ALERT_EVENT) {
+
+		//
+		// Update attn_led_problem_event LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		slot_context->problem_detected = TRUE;
+		hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+		//
+		// Fail on-going request
+		//
+		slot_context->slot_completion.failed = HP_TRUE;
+		slot_context->slot_completion.done = TRUE;
+
+		//
+		// Grab Command MUTEX to disable slot
+		//
+		dbg("%s -->ALERT: slot_id[ %d:%d ]  LSR_13:0[ %X ]", __FUNCTION__,
+			shpc_context->shpc_instance, slot_context->slot_number-1,
+			readl( slot_context->logical_slot_addr ) & 0x3F );
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available;
+	}
+	//
+	// timeout
+	//
+	else if(slot_context->slot_event_bits & SLOT_TIMER7_EVENT) {
+		//
+		// Flag this slot as ENABLED
+		//
+		hp_flag_slot_as_enabled( shpc_context, slot_context );
+
+		//
+		// Complete succesful ENABLE request
+		//
+		slot_context->slot_completion.failed = HP_FALSE;
+		slot_context->slot_completion.done = TRUE;
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_slot_request;
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		status =STATUS_UNSUCCESSFUL;
+	}
+	//
+	// Release Bus MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+	wake_up_interruptible(&slot_context->bus_release_event);
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_to_slot_disabled_wait_for_led_cmd_available()
+//
+// ****************************************************************************
+long
+hp_to_slot_disabled_wait_for_led_cmd_available(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SHPC_COMMAND_WREG command_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Wait for Command Available MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_ACQUIRE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_acquire_event);
+
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) {
+		//
+		// Clear Completion EVENT before issuing next command
+		//
+		spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+		hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT);
+		spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+		//
+		// Turn OFF Power LED
+		//
+		command_reg.Slot.code = SHPC_SLOT_OPERATION;
+		command_reg.Slot.power_led = SHPC_LED_OFF;
+		command_reg.Slot.attention_led = SHPC_led_NO_CHANGE;
+		command_reg.Slot.state = SHPC_SLOT_NO_CHANGE;
+		command_reg.Slot.TGT = slot_context->slot_number;
+		writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET);
+
+		//
+		// Wait for Power LED command to complete
+		//
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_led_cmd_completion;
+	}
+	else {				// exit_request_event
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+// ****************************************************************************
+//
+// hp_to_slot_disabled_wait_for_led_cmd_completion()
+//
+// ****************************************************************************
+long
+hp_to_slot_disabled_wait_for_led_cmd_completion(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	long status = STATUS_SUCCESS;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER8_EVENT);
+	slot_context->slot_timer8.data = (unsigned long)slot_context;
+	slot_context->slot_timer8.function = hp_slot_timer8_func;
+	slot_context->slot_timer8.expires = jiffies + ONE_SEC_TIMEOUT;
+	add_timer(&slot_context->slot_timer8);
+
+	//
+	// Wait for Command Completion EVENT while holding MUTEX
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_TIMER8_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER8_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->slot_timer8);
+	}
+
+	if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+	   (slot_context->slot_event_bits & SLOT_TIMER8_EVENT)) {
+		//
+		// Wait for next request
+		//
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_slot_request;
+
+	}else{				// exit_request_event
+		status = STATUS_UNSUCCESSFUL;
+	}
+
+	//
+	// Release command MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_release_event);
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_to_slot_disabled_wait_for_disable_cmd_available()
+//
+// ****************************************************************************
+long
+hp_to_slot_disabled_wait_for_disable_cmd_available(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SHPC_COMMAND_WREG command_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Wait for Command Available MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_ACQUIRE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_acquire_event);
+
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if(shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) {
+		//
+		// Clear Completion EVENT before issuing next command
+		//
+		spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+		hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT);
+		spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+		//
+		// Disable slot and turn OFF Power LED
+		//
+		command_reg.Slot.code = SHPC_SLOT_OPERATION;
+		command_reg.Slot.power_led = SHPC_LED_OFF;
+		command_reg.Slot.attention_led = SHPC_led_NO_CHANGE;
+		command_reg.Slot.state = SHPC_DISABLE_SLOT;
+		command_reg.Slot.TGT = slot_context->slot_number;
+		writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET);
+
+		//
+		// Wait for command to complete
+		//
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_completion;
+	}
+	else {
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->cmd_release_event);
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_to_slot_disabled_wait_for_disable_cmd_completion()
+//
+// ****************************************************************************
+long
+hp_to_slot_disabled_wait_for_disable_cmd_completion(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	long status = STATUS_SUCCESS;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER9_EVENT);
+	slot_context->slot_timer9.data = (unsigned long)slot_context;
+	slot_context->slot_timer9.function = hp_slot_timer9_func;
+	slot_context->slot_timer9.expires = jiffies + FIFTEEN_SEC_TIMEOUT;
+	add_timer(&slot_context->slot_timer9);
+
+	//
+	// Wait for Command Completion EVENT while holding MUTEX
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+		(slot_context->slot_event_bits & SLOT_TIMER9_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER9_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->slot_timer9);
+	}
+
+	if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+	   (slot_context->slot_event_bits & SLOT_TIMER9_EVENT)) {
+		//
+		// Flag this slot as DISABLED (if enabled)
+		//
+		if( hp_flag_slot_as_disabled( shpc_context, slot_context )) {
+			//
+			// Wait for settling time
+			//
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_timeout;
+		}
+		else {
+			//
+			// Wait for next request
+			//
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_slot_request;
+		}
+	}
+	else {				// exit_request_event
+		status = STATUS_UNSUCCESSFUL;
+	}
+	//
+	// Release command MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT);
+	wake_up_interruptible(&slot_context->cmd_release_event);
+
+	return status;
+}
+
+// ****************************************************************************
+//
+// hp_to_slot_disabled_wait_for_DisableTimeout()
+//
+// ****************************************************************************
+long
+hp_to_slot_disabled_wait_for_disable_timeout(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	long status = STATUS_SUCCESS;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, SLOT_TIMER10_EVENT);
+	slot_context->slot_timer10.data = (unsigned long)slot_context;
+	slot_context->slot_timer10.function = hp_slot_timer10_func;
+	slot_context->slot_timer10.expires = jiffies + ONE_SEC_TIMEOUT;
+	add_timer(&slot_context->slot_timer10);
+
+	//
+	// Wait for timeout
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((slot_context->slot_event_bits & SLOT_TIMER10_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & SLOT_TIMER10_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->slot_timer10);
+	}
+
+	//
+	// timeout
+	//
+	if(slot_context->slot_event_bits & SLOT_TIMER10_EVENT) {
+		slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_bus_available;
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_to_slot_disabled_wait_for_bus_available() 
+//
+// ****************************************************************************
+long
+hp_to_slot_disabled_wait_for_bus_available(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long		old_irq_flags;
+	long status = STATUS_SUCCESS;
+	enum shpc_speed_mode max_speed_mode;
+
+	dbg("%s -->slot_id[ %d:%d ]",  __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Wait for Bus Available MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, BUS_ACQUIRE_EVENT);
+	wake_up_interruptible(&slot_context->bus_acquire_event);
+
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & BUS_AVAILABLE_MUTEX_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if(shpc_context->shpc_event_bits & BUS_AVAILABLE_MUTEX_EVENT) {
+			//
+			// Grab global spinlock to check current speed/mode settings
+			//
+			spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+
+			//
+			// Flag this slot out of contetion for bus speed/mode changes
+			//
+			slot_context->in_bus_speed_mode_contention = FALSE;
+
+			//
+			// Enabled slots running at maximum speed/mode?
+			//
+			if( shpc_context->slots_enabled ) {
+				max_speed_mode = hp_get_max_speed_mode( shpc_context, shpc_context->max_speed_mode );
+
+				//
+				// Signal enabled slots to release the bus, then change bus speed/mode
+				//
+				if( shpc_context->bus_speed_mode != max_speed_mode ) {
+					hp_signal_enabled_slots_to_rebalance_bus( shpc_context );
+				}
+			}
+
+			//
+			// Release global spinlock since we're done checking speed/mode
+			//
+			spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+			//
+			// Wait for next request on this slot
+			//
+			slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_slot_request;
+	}
+	else {				// exit_request_event
+		status = STATUS_UNSUCCESSFUL;
+	}
+
+	//
+	// Release Bus MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT);
+	wake_up_interruptible(&slot_context->bus_release_event);
+
+	return status;
+}
+
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/amdshpc_int.c	Wed Mar 17 11:19:43 2004
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2003 IBM Corp.
+ * Copyright (C) 2002-2003 Advanced Micro Devices
+ *
+ * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS
+ * AND CONDITIONS OF THE GNU GENERAL PUBLIC
+ * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS
+ * INCLUDED WITH THIS FILE AND POSTED AT
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Send feedback to <david.keck@amd.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include "amdshpc_ddi.h"
+#include "amdshpc.h"
+
+
+// ****************************************************************************
+//
+// hp_interrupt_service()
+//
+// ****************************************************************************
+irqreturn_t hp_interrupt_service(int IRQ, void *v, struct pt_regs *regs)
+{
+	struct shpc_context *shpc_context = v;
+	struct slot_context *slot_context;
+	union SHPC_SERR_INT_DWREG	SerrIntReg;
+	union SHPC_INT_LOCATOR_DWREG	IntLocatorReg, SlotIndex;
+	union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg;
+	u8 IsShpcInterrupt = FALSE;
+	u8 i;
+
+	//
+	// Device at PowerDeviceD0?
+	//
+	if( !shpc_context->at_power_device_d0 ) {
+		return IRQ_HANDLED;
+	}
+
+	//
+	// Read Interrupt Locator Register ( Pending Interrupts )
+	//
+	IntLocatorReg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_INT_LOCATOR_REG_OFFSET);
+
+	//
+	// Read SERR-INT Register ( Global Mask, Command Completion )
+	//
+	SerrIntReg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SERR_INT_REG_OFFSET);
+
+	//
+	// Global Interrupts Disabled?
+	//
+//	if( SerrIntReg.x.GIM == SHPC_MASKED ) {
+//		return FALSE;
+//	}
+
+	//
+	// Command Completion?
+	//
+	if( IntLocatorReg.x.CC_IP ) {
+		if(( SerrIntReg.x.CC_STS == SHPC_STATUS_SET ) &&
+			( SerrIntReg.x.CC_IM == SHPC_UNMASKED )) {
+			//
+			// Schedule Dpc
+			//
+			IsShpcInterrupt = TRUE;
+			tasklet_schedule(&shpc_context->cmd_completion_dpc);
+
+			//
+			// Clear Interrput (Write-back 1 to STS bits)
+			//
+			writel(SerrIntReg.AsDWord, shpc_context->mmio_base_addr + SHPC_SERR_INT_REG_OFFSET);
+		}
+	}
+
+	//
+	// Slot Interrupts?
+	//
+	if( IntLocatorReg.x.SLOT_IP ) {
+		//
+		// Walk a "1" thru each bit position (one bit per slot)
+		//
+		for( i=0, SlotIndex.x.SLOT_IP = 1; i< SHPC_MAX_NUM_SLOTS; ++i, SlotIndex.x.SLOT_IP <<= 1 ) {
+			slot_context = &shpc_context->slot_context[ i ];
+
+			//
+			// Interrupt from this slot?
+			//
+			if( IntLocatorReg.x.SLOT_IP & SlotIndex.x.SLOT_IP ) {
+				//
+				//  Read Logical Slot Register
+				//
+				logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr );
+
+				//
+				// Attention Button?
+				//
+				if(( logical_slot_reg.x.ABP_STS == SHPC_STATUS_SET ) &&
+					( logical_slot_reg.x.AB_IM == SHPC_UNMASKED )) {
+					//
+					// Schedule Dpc
+					//
+					IsShpcInterrupt = TRUE;
+					tasklet_schedule(&slot_context->attn_button_dpc);
+				}
+
+				//
+				// MRL Sensor?
+				//
+				if(( logical_slot_reg.x.MRLSC_STS == SHPC_STATUS_SET ) &&
+					( logical_slot_reg.x.MRLS_IM == SHPC_UNMASKED )) {
+					//
+					// Schedule Dpc
+					//
+					IsShpcInterrupt = TRUE;
+					tasklet_schedule(&slot_context->mrl_sensor_dpc);
+				}
+
+				//
+				// Card Presence Change?
+				//
+				if(( logical_slot_reg.x.CPC_STS == SHPC_STATUS_SET ) &&
+					( logical_slot_reg.x.CP_IM == SHPC_UNMASKED )) {
+					//
+					// Schedule Dpc
+					//
+					IsShpcInterrupt = TRUE;
+					tasklet_schedule(&slot_context->card_presence_dpc);
+				}
+
+				//
+				// Isolated Power Fault?
+				//
+				if(( logical_slot_reg.x.IPF_STS == SHPC_STATUS_SET ) &&
+					( logical_slot_reg.x.IPF_IM == SHPC_UNMASKED )) {
+					//
+					// Schedule Dpc
+					//
+					IsShpcInterrupt = TRUE;
+					tasklet_schedule(&slot_context->isolated_power_fault_dpc);
+				}
+
+				//
+				// Connected Power Fault?
+				//
+				if(( logical_slot_reg.x.CPF_STS == SHPC_STATUS_SET ) &&
+					( logical_slot_reg.x.CPF_IM == SHPC_UNMASKED )) {
+					//
+					// Schedule Dpc
+					//
+					IsShpcInterrupt = TRUE;
+					tasklet_schedule(&slot_context->connected_power_fault_dpc);
+				}
+
+				//
+				// Clear Interrputs for this slot (Write-back 1 to STS bits)
+				//
+				writel(logical_slot_reg.AsDWord, slot_context->logical_slot_addr);
+			}
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+
+// ****************************************************************************
+//
+// hp_attn_button_dpc() @ DISPATCH_LEVEL
+//
+// ****************************************************************************
+void
+hp_attn_button_dpc(
+	unsigned long deferred_context	// struct slot_context*
+	)
+{
+	struct slot_context* slot_context = ( struct slot_context* )deferred_context;
+	struct shpc_context* shpc_context = slot_context->shpc_context;
+
+	dbg("%s ->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, (slot_context->slot_number-1) );
+	//
+	// Notification Event: Attention Button pressed
+	//
+	spin_lock( &slot_context->slot_spinlock );
+	hp_send_slot_event(slot_context, ATTN_BUTTON_EVENT);
+	spin_unlock( &slot_context->slot_spinlock );
+}
+
+
+// ****************************************************************************
+//
+// hp_card_presence_dpc() @ DISPATCH_LEVEL
+//
+// ****************************************************************************
+void
+hp_card_presence_dpc(
+	unsigned long deferred_context	// struct slot_context*
+	)
+{
+	struct slot_context* slot_context = ( struct slot_context* )deferred_context;
+	struct shpc_context* shpc_context = slot_context->shpc_context;
+	union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Signal registered user EVENT
+	//
+	hp_signal_user_event_at_dpc_level( shpc_context );
+
+	//
+	// Card Removed?
+	//
+	logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr );
+	if( logical_slot_reg.x.PRSNT1_2 == SHPC_SLOT_EMPTY ) {
+		//
+		// Signal Alert EVENT
+		//
+		spin_lock( &slot_context->slot_spinlock );
+		hp_send_slot_event(slot_context, ALERT_EVENT);
+		spin_unlock( &slot_context->slot_spinlock );
+	}
+}
+
+
+// ****************************************************************************
+//
+// hp_mrl_sensor_dpc() @ DISPATCH_LEVEL
+//
+// ****************************************************************************
+void
+hp_mrl_sensor_dpc(
+	unsigned long deferred_context	// struct slot_context*
+	)
+{
+	struct slot_context* slot_context = ( struct slot_context* )deferred_context;
+	struct shpc_context* shpc_context = slot_context->shpc_context;
+	union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Signal registered user EVENT
+	//
+	hp_signal_user_event_at_dpc_level( shpc_context );
+
+	//
+	// MRL Sensor opened?
+	//
+	logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr );
+	if( logical_slot_reg.x.MRLS == SHPC_MRL_OPEN ) {
+		//
+		// Card Present?
+		//
+		if( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY ) {
+			//
+			// Signal Alert EVENT
+			//
+			spin_lock( &slot_context->slot_spinlock );
+			hp_send_slot_event(slot_context, ALERT_EVENT);
+			spin_unlock( &slot_context->slot_spinlock );
+		}
+	}
+	else {
+		//
+		// Power Fault detected whith MRL closed?
+		// Note: Golem A0 may not generate power-fault interrupt
+		if( logical_slot_reg.x.PF == SHPC_STATUS_SET ) {
+			//
+			// Signal Alert EVENT
+			//
+			spin_lock( &slot_context->slot_spinlock );
+			hp_send_slot_event(slot_context, ALERT_EVENT);
+			spin_unlock( &slot_context->slot_spinlock );
+		}
+	}
+}
+
+// ****************************************************************************
+//
+// isolated_power_fault_dpc() @ DISPATCH_LEVEL
+//
+// ****************************************************************************
+void
+hp_isolated_power_fault_dpc(
+	unsigned long deferred_context	// struct slot_context*
+	)
+{
+	struct slot_context* slot_context = ( struct slot_context* )deferred_context;
+	struct shpc_context* shpc_context = slot_context->shpc_context;
+	union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Signal registered user EVENT
+	//
+	hp_signal_user_event_at_dpc_level( shpc_context );
+
+	//
+	// Power Fault detected?
+	//
+	logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr );
+	if( logical_slot_reg.x.PF == SHPC_STATUS_SET ) {
+		//
+		// Signal Alert EVENT
+		//
+		spin_lock( &slot_context->slot_spinlock );
+		hp_send_slot_event(slot_context, ALERT_EVENT);
+		spin_unlock( &slot_context->slot_spinlock );
+	}
+}
+
+
+// ****************************************************************************
+//
+// connected_power_fault_dpc() @ DISPATCH_LEVEL
+//
+// ****************************************************************************
+void
+hp_connected_power_fault_dpc(
+	unsigned long deferred_context	// struct slot_context*
+	)
+{
+	struct slot_context* slot_context = ( struct slot_context* )deferred_context;
+	struct shpc_context* shpc_context = slot_context->shpc_context;
+	union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Signal registered user EVENT
+	//
+	hp_signal_user_event_at_dpc_level( shpc_context );
+
+	//
+	// Power Fault detected?
+	//
+	logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr );
+	if( logical_slot_reg.x.PF == SHPC_STATUS_SET ) {
+		//
+		// Signal Alert EVENT
+		//
+		spin_lock( &slot_context->slot_spinlock );
+		hp_send_slot_event(slot_context, ALERT_EVENT);
+		spin_unlock( &slot_context->slot_spinlock );
+	}
+}
+
+
+// ****************************************************************************
+//
+// hp_cmd_completion_dpc() @ DISPATCH_LEVEL
+//
+// ****************************************************************************
+void
+hp_cmd_completion_dpc(
+	unsigned long deferred_context	// struct shpc_context*
+	)
+{
+	struct shpc_context* shpc_context = ( struct shpc_context* )deferred_context;
+
+	dbg("%s -->HwInstance[ %d ]", __FUNCTION__, shpc_context->shpc_instance );
+
+	//
+	// Notification Event: Command Completion
+	//
+	spin_lock( &shpc_context->shpc_spinlock );
+	hp_send_event_to_all_slots(shpc_context, CMD_COMPLETION_EVENT);
+	spin_unlock( &shpc_context->shpc_spinlock );
+}
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/amdshpc_led.c	Wed Mar 17 11:19:43 2004
@@ -0,0 +1,742 @@
+/*
+ * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001,2003 IBM Corp.
+ * Copyright (C) 2002-2003 Advanced Micro Devices
+ *
+ * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS
+ * AND CONDITIONS OF THE GNU GENERAL PUBLIC
+ * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS
+ * INCLUDED WITH THIS FILE AND POSTED AT
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Send feedback to <david.keck@amd.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include "amdshpc_ddi.h"
+#include "amdshpc.h"
+
+
+// ****************************************************************************
+//
+// hp_wait_for_attn_led_request() @ PASSIVE_LEVEL
+//
+// ****************************************************************************
+long
+hp_wait_for_attn_led_request(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SLOT_STATUS_INFO slot_status;
+	union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+ 	//
+ 	// LED "Normal": complete pending request
+ 	//
+ 	if( slot_context->attn_led_completion.done ) {
+ 		//
+ 		// Call Completion Callback()
+ 		//
+ 		hp_QuerySlotStatus(	shpc_context, slot_context->slot_number - 1, &slot_status );
+ 		slot_status.x.lu_request_failed = slot_context->slot_completion.failed;
+ 		shpc_context->async_callback(
+ 			shpc_context->driver_context,
+ 			slot_context->slot_number - 1,
+ 			slot_context->attn_led_completion.type,
+ 			slot_status,
+ 			slot_context->attn_led_completion.request_context );
+ 
+ 		//
+ 		// Signal registered user EVENT
+ 		//
+ 		hp_signal_user_event( shpc_context );
+ 
+ 		//
+ 		// Clear completion flag
+ 		//
+ 		slot_context->attn_led_completion.done = FALSE;
+ 	}
+ 
+	//
+	// Wait for slot request
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((slot_context->slot_event_bits & ATTN_LED_REQUEST_EVENT) ||
+		(slot_context->slot_event_bits & ATTN_LED_PROBLEM_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	// AttnLEDRequestEvent
+	if(slot_context->slot_event_bits & ATTN_LED_REQUEST_EVENT) {
+		//
+		// Set completion info for SW-initiated request
+		//
+		slot_context->attn_led_completion.hw_initiated = FALSE;
+		slot_context->attn_led_completion.type = slot_context->attn_led_request.type;
+		slot_context->attn_led_completion.timeout = slot_context->attn_led_request.timeout;
+		slot_context->attn_led_completion.request_context = slot_context->attn_led_request.request_context;
+
+		//
+		// Request to locate slot?
+		//
+		if( slot_context->attn_led_request.type == SHPC_ASYNC_LED_LOCATE ) {
+			dbg("%s -->LED_LOCATE_REQ: slot_id[ %d:%d ]", __FUNCTION__,
+				shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+			//
+			// Grab Command MUTEX to blink Attn LED
+			//
+			slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_blink_cmd_available;
+		}
+		else {
+			dbg("%s -->LED_NORMAL_REQ: slot_id[ %d:%d ]", __FUNCTION__,
+				shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+			logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr );
+			if( logical_slot_reg.x.AIS == SHPC_LED_ON || logical_slot_reg.x.AIS == SHPC_LED_OFF ) {
+				//
+				// Already "Normal", just complete the request
+				//
+				slot_context->attn_led_completion.failed = HP_FALSE;
+				slot_context->attn_led_completion.done = TRUE;
+			}
+			//
+			// While waitimg on a request here, the Attn LED should already be On/Off, but...
+			//
+			else {
+				//
+				// Grab Command MUTEX to set Attn LED to "Normal" (On/Off) state
+				//
+				slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_normal_cmd_available;
+			}
+		}
+
+		//
+		// Allow next SW-initiated request while processing this one
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		hp_clear_slot_event_bit(slot_context, ATTN_LED_REQUEST_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+	}
+	// attn_led_problem_event: Detected, Resolved
+	else if (slot_context->slot_event_bits & ATTN_LED_PROBLEM_EVENT){
+		//
+		// Set completion info for HW-initiated request
+		//
+		slot_context->attn_led_completion.hw_initiated = TRUE;
+		slot_context->attn_led_completion.type = SHPC_ASYNC_LED_NORMAL;
+		slot_context->attn_led_completion.timeout = 0;
+		slot_context->attn_led_completion.request_context = NULL;
+
+		//
+		// Grab Command MUTEX to update Attention LED (On/Off)
+		//
+		slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_normal_cmd_available;
+	}
+	else {	// exit_request_event
+		status = STATUS_UNSUCCESSFUL;
+		dbg("%s -->EXIT_REQUEST: slot_id[ %d:%d ]", __FUNCTION__,
+			shpc_context->shpc_instance, slot_context->slot_number-1 );
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_wait_for_attn_led_blink_cmd_available() @ PASSIVE_LEVEL
+//
+// ****************************************************************************
+long
+hp_wait_for_attn_led_blink_cmd_available(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SHPC_COMMAND_WREG command_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Wait for Command Available MUTEX
+	//
+	//down_interruptible(&slot_context->cmd_acquire_mutex);
+	hp_set_slot_event_bit(slot_context, LED_CMD_ACQUIRE_EVENT);
+	wake_up_interruptible(&slot_context->led_cmd_acquire_event);
+
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & LED_CMD_AVAILABLE_MUTEX_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	// cmd_available_mutex
+	if(shpc_context->shpc_event_bits & LED_CMD_AVAILABLE_MUTEX_EVENT) {
+		//
+		// Clear Completion EVENT before issuing next command
+		//
+		spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+		hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT);
+		spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+		//
+		// Blink Attention LED
+		//
+		command_reg.Slot.code = SHPC_SLOT_OPERATION;
+		command_reg.Slot.power_led = SHPC_led_NO_CHANGE;
+		command_reg.Slot.attention_led = SHPC_LED_BLINK;
+		command_reg.Slot.state = SHPC_SLOT_NO_CHANGE;
+		command_reg.Slot.TGT = slot_context->slot_number;
+		writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET);
+
+		//
+		// Wait for command to complete (while holding MUTEX)
+		//
+		slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_blink_cmd_completion;
+	}
+	// exit_request_event
+	else {
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, LED_CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->led_cmd_release_event);
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_wait_for_attn_led_blink_cmd_completion() @ PASSIVE_LEVEL
+//
+// ****************************************************************************
+long
+hp_wait_for_attn_led_blink_cmd_completion(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	long status = STATUS_SUCCESS;
+	union SLOT_STATUS_INFO slot_status;
+	union SHPC_STATUS_WREG status_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, LED_TIMER1_EVENT);
+	slot_context->led_timer1.data = (unsigned long)slot_context;
+	slot_context->led_timer1.function = hp_led_timer1_func;
+	slot_context->led_timer1.expires = jiffies + ONE_SEC_TIMEOUT;
+	add_timer(&slot_context->led_timer1);
+
+	//
+	// Wait for Command Completion EVENT while holding MUTEX
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+		(slot_context->slot_event_bits & LED_TIMER1_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & LED_TIMER1_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->led_timer1);
+	}
+
+	if(shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) {
+		// cmd_completion_event, timeout
+		if ((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || (slot_context->slot_event_bits & LED_TIMER1_EVENT)) {
+			//
+			// Command completed OK?
+			//
+			status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET);
+
+			if( status_reg.x.BSY == SHPC_STATUS_CLEARED &&
+				status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED ) {
+				//
+				// Call Completion Callback()
+				//
+				hp_QuerySlotStatus(	shpc_context, slot_context->slot_number - 1, &slot_status );
+				slot_status.x.lu_request_failed = HP_FALSE;
+				shpc_context->async_callback(
+					shpc_context->driver_context,
+					slot_context->slot_number - 1,
+					SHPC_ASYNC_LED_LOCATE,
+					slot_status,
+					slot_context->attn_led_completion.request_context );
+
+				//
+				// Signal registered user EVENT
+				//
+				hp_signal_user_event( shpc_context );
+
+				//
+				// Wait for specified timeout (in seconds)
+				//
+				slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_blink_timeout;
+			}
+			else {
+				//
+				// Fail on-going request
+				//
+				slot_context->attn_led_completion.failed = HP_TRUE;
+				slot_context->attn_led_completion.done = TRUE;
+
+				//
+				// Grab Command MUTEX to make sure Attn LED gets back to "Normal" (On/Off)
+				//
+				dbg("%s -->CMD_ERROR: slot_id[ %d:%d ]  Cmd[ %X ]", __FUNCTION__,
+					shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord );
+				slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_back_to_normal_cmd_available;
+			}
+
+		// exit_request_event
+		}
+		else {
+			status = STATUS_UNSUCCESSFUL;
+		}
+	}
+	//
+	// Release Command MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, LED_CMD_RELEASE_EVENT);
+	wake_up_interruptible(&slot_context->led_cmd_release_event);
+
+	return status;
+}
+
+// ****************************************************************************
+//
+// hp_wait_for_attn_led_blink_timeout() @ PASSIVE_LEVEL
+//
+// ****************************************************************************
+long
+hp_wait_for_attn_led_blink_timeout(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SLOT_STATUS_INFO slot_status;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, LED_TIMER2_EVENT);
+	slot_context->led_timer2.data = (unsigned long)slot_context;
+	slot_context->led_timer2.function = hp_led_timer2_func;
+	slot_context->led_timer2.expires = jiffies + (ONE_SEC_INCREMENT * slot_context->attn_led_completion.timeout);
+	add_timer(&slot_context->led_timer2);
+
+	//
+	// Wait for specified timeout ( in seconds )
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((slot_context->slot_event_bits & ATTN_LED_REQUEST_EVENT) ||
+		(slot_context->slot_event_bits & LED_TIMER2_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & LED_TIMER2_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		hp_clear_slot_event_bit(slot_context, LED_TIMER2_EVENT);
+		del_timer_sync(&slot_context->led_timer2);
+	}
+
+	// AttnLEDRequestEvent
+	if(slot_context->slot_event_bits & ATTN_LED_REQUEST_EVENT) {
+		//
+		// Set completion info for SW-initiated request
+		//
+		slot_context->attn_led_completion.hw_initiated = FALSE;
+		slot_context->attn_led_completion.type = slot_context->attn_led_request.type;
+		slot_context->attn_led_completion.timeout = slot_context->attn_led_request.timeout;
+		slot_context->attn_led_completion.request_context = slot_context->attn_led_request.request_context;
+
+		//
+		// Request to cancel locate?
+		//
+		if( slot_context->attn_led_request.type == SHPC_ASYNC_LED_NORMAL ) {
+			dbg("%s -->LED_NORMAL_REQ: slot_id[ %d:%d ]", __FUNCTION__,
+				shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+			//
+			// Grab Command MUTEX to set Attn LED at "Normal" (On/Off) state
+			//
+			slot_context->attn_led_function = (SLOT_STATE_FUNCTION)&hp_wait_for_attn_led_normal_cmd_available;
+
+			//
+			// Allow next SW-initiated request while processing this one
+			//
+			spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+			hp_clear_slot_event_bit(slot_context, ATTN_LED_REQUEST_EVENT);
+			spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+		}
+		//
+		// Already located (Attn LED blinking), just re-start timeout
+		//
+		else {
+			dbg("%s -->LED_LOCATE_REQ: slot_id[ %d:%d ]", __FUNCTION__,
+				shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+			//
+			// Allow next SW-initiated request before invoking callback, since next
+			// request may be sent in the context of this thread.
+			//
+			spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+			hp_clear_slot_event_bit(slot_context, ATTN_LED_REQUEST_EVENT);
+			spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+
+			//
+			// Call Completion Callback()
+			//
+			hp_QuerySlotStatus(	shpc_context, slot_context->slot_number - 1, &slot_status );
+			slot_status.x.lu_request_failed = HP_FALSE;
+			shpc_context->async_callback(
+				shpc_context->driver_context,
+				slot_context->slot_number - 1,
+				SHPC_ASYNC_LED_LOCATE,
+				slot_status,
+				slot_context->attn_led_completion.request_context );
+
+			//
+			// Signal registered user EVENT
+			//
+			hp_signal_user_event( shpc_context );
+		}
+	}
+	// timeout
+	else if (slot_context->slot_event_bits & LED_TIMER2_EVENT) {
+		//
+		// Set completion info for HW-initiated request
+		//
+		slot_context->attn_led_completion.hw_initiated = TRUE;
+		slot_context->attn_led_completion.type = SHPC_ASYNC_LED_NORMAL;
+		slot_context->attn_led_completion.timeout = 0;
+		slot_context->attn_led_completion.request_context = NULL;
+
+		//
+		// Grab Command MUTEX to set Attn LED at "Normal" (On/Off) state
+		//
+		slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_normal_cmd_available;
+
+	}
+	// exit_request_event
+	else {
+	status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_wait_for_attn_led_normal_cmd_available() @ PASSIVE_LEVEL
+//
+// ****************************************************************************
+long
+hp_wait_for_attn_led_normal_cmd_available(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SHPC_COMMAND_WREG command_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Wait for Command Available MUTEX
+	//
+	//down_interruptible(&slot_context->cmd_acquire_mutex);
+	hp_set_slot_event_bit(slot_context, LED_CMD_ACQUIRE_EVENT);
+	wake_up_interruptible(&slot_context->led_cmd_acquire_event);
+
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & LED_CMD_AVAILABLE_MUTEX_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	//
+	// cmd_available_mutex
+	//
+	if(shpc_context->shpc_event_bits & LED_CMD_AVAILABLE_MUTEX_EVENT) {
+		//
+		// Clear Completion EVENT before issuing next command
+		//
+		spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+		hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT);
+		spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+		//
+		// Update Attention LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		command_reg.Slot.attention_led = slot_context->problem_detected ?
+			SHPC_LED_ON : SHPC_LED_OFF;
+		hp_clear_slot_event_bit(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+		command_reg.Slot.code = SHPC_SLOT_OPERATION;
+		command_reg.Slot.power_led = SHPC_led_NO_CHANGE;
+		command_reg.Slot.state = SHPC_SLOT_NO_CHANGE;
+		command_reg.Slot.TGT = slot_context->slot_number;
+		writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET);
+
+		//
+		// Wait for command to complete (while holding MUTEX)
+		//
+		slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_normal_cmd_completion;
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, LED_CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->led_cmd_release_event);
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_wait_for_attn_led_normal_cmd_completion() @ PASSIVE_LEVEL
+//
+// ****************************************************************************
+long
+hp_wait_for_attn_led_normal_cmd_completion(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	long status = STATUS_SUCCESS;
+	union SHPC_STATUS_WREG status_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, LED_TIMER3_EVENT);
+	slot_context->led_timer3.data = (unsigned long)slot_context;
+	slot_context->led_timer3.function = hp_led_timer3_func;
+	slot_context->led_timer3.expires = jiffies + ONE_SEC_TIMEOUT;
+	add_timer(&slot_context->led_timer3);
+
+	//
+	// Wait for Command Completion EVENT while holding MUTEX
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+		(slot_context->slot_event_bits & LED_TIMER3_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & LED_TIMER3_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->led_timer3);
+	}
+
+	//
+	// cmd_completion_event, timeout
+	//
+	if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+	   (slot_context->slot_event_bits & LED_TIMER3_EVENT)) {
+		//
+		// Command completed OK?
+		//
+		status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET);
+
+		if( status_reg.x.BSY == SHPC_STATUS_CLEARED &&
+			status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED ) {
+			//
+			// Complete succesful ENABLE request
+			//
+			slot_context->attn_led_completion.failed = HP_FALSE;
+			slot_context->attn_led_completion.done = TRUE;
+			slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_request;
+		}
+		else {
+			//
+			// Fail on-going request
+			//
+			slot_context->attn_led_completion.failed = HP_TRUE;
+			slot_context->attn_led_completion.done = TRUE;
+
+			//
+			// Grab Command MUTEX to make sure Attn LED gets back to "Normal" (On/Off)
+			//
+			dbg("%s -->CMD_ERROR: slot_id[ %d:%d ]  Cmd[ %X ]", __FUNCTION__,
+				shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord );
+			slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_back_to_normal_cmd_available;
+		}
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		status = STATUS_UNSUCCESSFUL;
+	}
+	//
+	// Release Command MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, LED_CMD_RELEASE_EVENT);
+   	wake_up_interruptible(&slot_context->led_cmd_release_event);
+
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_wait_for_attn_led_back_to_normal_cmd_available() @ PASSIVE_LEVEL
+//
+// ****************************************************************************
+long
+hp_wait_for_attn_led_back_to_normal_cmd_available(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	unsigned long old_irq_flags;
+	long status = STATUS_SUCCESS;
+	union SHPC_COMMAND_WREG command_reg;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Wait for Command Available MUTEX
+	//
+	//down_interruptible(&slot_context->cmd_acquire_mutex);
+	hp_set_slot_event_bit(slot_context, LED_CMD_ACQUIRE_EVENT);
+	wake_up_interruptible(&slot_context->led_cmd_acquire_event);
+
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & LED_CMD_AVAILABLE_MUTEX_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	//
+	// cmd_available_mutex
+	//
+	if(shpc_context->shpc_event_bits & LED_CMD_AVAILABLE_MUTEX_EVENT) {
+		//
+		// Clear Completion EVENT before issuing next command
+		//
+		spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags );
+		hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT);
+		spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags );
+
+		//
+		// Update Attention LED
+		//
+		spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags );
+		command_reg.Slot.attention_led = slot_context->problem_detected ?
+			SHPC_LED_ON : SHPC_LED_OFF;
+		hp_clear_slot_event_bit(slot_context, ATTN_LED_PROBLEM_EVENT);
+		spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags );
+		command_reg.Slot.code = SHPC_SLOT_OPERATION;
+		command_reg.Slot.power_led = SHPC_led_NO_CHANGE;
+		command_reg.Slot.state = SHPC_SLOT_NO_CHANGE;
+		command_reg.Slot.TGT = slot_context->slot_number;
+		writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET);
+
+		//
+		// Wait for command to complete (while holding MUTEX)
+		//
+		slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_back_to_normal_cmd_completion;
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		//
+		// Release Command MUTEX
+		//
+		hp_set_slot_event_bit(slot_context, LED_CMD_RELEASE_EVENT);
+		wake_up_interruptible(&slot_context->led_cmd_release_event);
+		status = STATUS_UNSUCCESSFUL;
+	}
+	return status;
+}
+
+
+// ****************************************************************************
+//
+// hp_wait_for_attn_led_back_to_normal_cmd_completion() @ PASSIVE_LEVEL
+//
+// ****************************************************************************
+long
+hp_wait_for_attn_led_back_to_normal_cmd_completion(
+	struct shpc_context* shpc_context,
+	struct slot_context* slot_context
+	)
+{
+	long status = STATUS_SUCCESS;
+
+	dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 );
+
+	//
+	// Setup our timer
+	//
+	hp_clear_slot_event_bit(slot_context, LED_TIMER4_EVENT);
+	slot_context->led_timer4.data = (unsigned long)slot_context;
+	slot_context->led_timer4.function = hp_led_timer4_func;
+	slot_context->led_timer4.expires = jiffies + ONE_SEC_TIMEOUT;
+	add_timer(&slot_context->led_timer4);
+
+	//
+	// Wait for Command Completion EVENT while holding MUTEX
+	//
+	wait_event_interruptible(slot_context->slot_event,
+		((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+		(slot_context->slot_event_bits & LED_TIMER4_EVENT) ||
+		(shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)));
+
+	if (!(slot_context->slot_event_bits & LED_TIMER4_EVENT)) {
+		//
+		// delete the timer because we got an event other than the timer
+		//
+		del_timer_sync(&slot_context->led_timer4);
+	}
+
+	//
+	// cmd_completion_event, timeout
+	//
+	if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) ||
+	   (slot_context->slot_event_bits & LED_TIMER4_EVENT)) {
+		slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_request;
+	}
+	//
+	// exit_request_event
+	//
+	else {
+		status = STATUS_UNSUCCESSFUL;
+	}
+	//
+	// Release Command MUTEX
+	//
+	hp_set_slot_event_bit(slot_context, LED_CMD_RELEASE_EVENT);
+	wake_up_interruptible(&slot_context->led_cmd_release_event);
+
+	return status;
+}
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/amdshpc_pci.c	Wed Mar 17 11:19:43 2004
@@ -0,0 +1,3513 @@
+/* 
+ * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001,2003 IBM Corp.
+ * Copyright (C) 2002-2003 Advanced Micro Devices
+ *
+ * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS
+ * AND CONDITIONS OF THE GNU GENERAL PUBLIC
+ * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS
+ * INCLUDED WITH THIS FILE AND POSTED AT
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Send feedback to <greg@kroah.com> <david.keck@amd.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/pci.h>
+#include "amdshpc.h"
+#include "../pci.h"
+#include "../../../arch/i386/pci/pci.h"
+
+u8 amdshpc_nic_irq;
+u8 amdshpc_disk_irq;
+
+static u16 unused_IRQ;
+
+extern struct controller *amdshpc_ctrl_list;	/* = NULL */
+extern struct pci_func *amdshpc_slot_list[256];
+
+static int bridge_slot_remove(struct pci_func *bridge);
+static int is_bridge(struct pci_func * func);
+static int update_slot_info (struct controller  *ctrl, struct slot *slot);
+static int slot_remove(struct pci_func * old_slot);
+static u32 configure_new_device(struct controller * ctrl, struct pci_func *func,u8 behind_bridge, struct resource_lists *resources);
+static int configure_new_function(struct controller * ctrl, struct pci_func *func,u8 behind_bridge, struct resource_lists *resources);
+int amdshpc_process_SI (struct controller *ctrl, struct pci_func *func);
+
+static u16 unused_IRQ;
+
+/**
+ * board_added - Called after a board has been added to the system.
+ *
+ * Turns power on for the board
+ * Configures board
+ *
+ */
+static u32 board_added(struct pci_func * func, struct controller * ctrl)
+{
+	int index;
+	u32 temp_register = 0xFFFFFFFF;
+	u32 rc = 0;
+	struct pci_func *new_slot = NULL;
+	struct resource_lists res_lists;
+
+	dbg("%s: func->device, slot_offset = %d, %d \n",__FUNCTION__,
+		func->device, ctrl->slot_device_offset);
+
+	// Get vendor/device ID u32
+	rc = pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(func->device, func->function), PCI_VENDOR_ID, &temp_register);
+	dbg("%s: pci_bus_read_config_dword returns %d\n",__FUNCTION__, rc);
+	dbg("%s: temp_register is %x\n",__FUNCTION__, temp_register);
+
+	if (rc != 0) {
+		// Something's wrong here
+		temp_register = 0xFFFFFFFF;
+		dbg("%s: temp register set to %x by error\n",__FUNCTION__, temp_register);
+	}
+	// Preset return code.  It will be changed later if things go okay.
+	rc = NO_ADAPTER_PRESENT;
+
+	// All F's is an empty slot or an invalid board
+	if (temp_register != 0xFFFFFFFF) {	  // Check for a board in the slot
+		res_lists.io_head 	= ctrl->io_head;
+		res_lists.mem_head 	= ctrl->mem_head;
+		res_lists.p_mem_head = ctrl->p_mem_head;
+		res_lists.bus_head 	= ctrl->bus_head;
+		res_lists.irqs = NULL;
+
+		rc = configure_new_device(ctrl, func, 0, &res_lists);
+
+		dbg("%s: back from configure_new_device\n",__FUNCTION__);
+		ctrl->io_head 	= res_lists.io_head;
+		ctrl->mem_head 	= res_lists.mem_head;
+		ctrl->p_mem_head = res_lists.p_mem_head;
+		ctrl->bus_head 	= res_lists.bus_head;
+
+		amdshpc_resource_sort_and_combine(&(ctrl->mem_head));
+		amdshpc_resource_sort_and_combine(&(ctrl->p_mem_head));
+		amdshpc_resource_sort_and_combine(&(ctrl->io_head));
+		amdshpc_resource_sort_and_combine(&(ctrl->bus_head));
+
+		if (rc) {
+			// Something went wrong; disable slot
+//			TO_DO_amd_disable_slot();
+			return(rc);
+		} else {
+			amdshpc_save_slot_config(ctrl, func);
+		}
+
+
+		func->status = 0;
+		func->switch_save = 0x10;
+		func->is_a_board = 0x01;
+
+		//next, we will instantiate the linux pci_dev structures (with appropriate driver notification, if already present)
+		dbg("%s: configure linux pci_dev structure\n",__FUNCTION__);
+		index = 0;
+		do {
+			new_slot = amdshpc_slot_find(ctrl->bus, func->device, index++);
+			if (new_slot && !new_slot->pci_dev) {
+				amdshpc_configure_device(ctrl, new_slot);
+			}
+		} while (new_slot);
+	} else {
+		// Something went wrong; disable slot
+//		TO_DO_amd_disable_slot();
+		return(rc);
+	}
+	return 0;
+}
+
+
+/**
+ * remove_board - Returns resources
+ */
+static u32 remove_board(struct pci_func * func, u32 replace_flag, struct controller  * ctrl)
+{
+	int index;
+	u8 skip = 0;
+	u8 device;
+	u8 hp_slot;
+	u32 rc;
+	struct resource_lists res_lists;
+	struct pci_func *temp_func;
+
+	if (func == NULL)
+		return(1);
+
+	if (amdshpc_unconfigure_device(func))
+		return(1);
+
+	device = func->device;
+
+	hp_slot = func->device - ctrl->slot_device_offset;
+	dbg("In %s, hp_slot = %d\n",__FUNCTION__, hp_slot);
+
+	// When we get here, it is safe to change base Address Registers.
+	// We will attempt to save the base Address Register Lengths
+	if (replace_flag || !ctrl->add_support)
+		rc = amdshpc_save_base_addr_length(ctrl, func);
+	else if (!func->bus_head && !func->mem_head &&
+		 !func->p_mem_head && !func->io_head) {
+		// Here we check to see if we've saved any of the board's
+		// resources already.  If so, we'll skip the attempt to
+		// determine what's being used.
+		index = 0;
+		temp_func = amdshpc_slot_find(func->bus, func->device, index++);
+		while (temp_func) {
+			if (temp_func->bus_head || temp_func->mem_head
+				|| temp_func->p_mem_head || temp_func->io_head) {
+				skip = 1;
+				break;
+			}
+			temp_func = amdshpc_slot_find(temp_func->bus, temp_func->device, index++);
+		}
+
+		if (!skip)
+			rc = amdshpc_save_used_resources(ctrl, func);
+	}
+	// Change status to shutdown
+	if (func->is_a_board)
+		func->status = 0x01;
+	func->configured = 0;
+
+//	TO_DO_amd_disable_slot(ctrl, hp_slot);
+
+	if (!replace_flag && ctrl->add_support) {
+		while (func) {
+			res_lists.io_head = ctrl->io_head;
+			res_lists.mem_head = ctrl->mem_head;
+			res_lists.p_mem_head = ctrl->p_mem_head;
+			res_lists.bus_head = ctrl->bus_head;
+
+			amdshpc_return_board_resources(func, &res_lists);
+
+			ctrl->io_head = res_lists.io_head;
+			ctrl->mem_head = res_lists.mem_head;
+			ctrl->p_mem_head = res_lists.p_mem_head;
+			ctrl->bus_head = res_lists.bus_head;
+
+			amdshpc_resource_sort_and_combine(&(ctrl->mem_head));
+			amdshpc_resource_sort_and_combine(&(ctrl->p_mem_head));
+			amdshpc_resource_sort_and_combine(&(ctrl->io_head));
+			amdshpc_resource_sort_and_combine(&(ctrl->bus_head));
+
+			if (is_bridge(func)) {
+				bridge_slot_remove(func);
+			} else
+				slot_remove(func);
+
+			func = amdshpc_slot_find(ctrl->bus, device, 0);
+		}
+
+		// Setup slot structure with entry for empty slot
+		func = amdshpc_slot_create(ctrl->bus);
+
+		if (func == NULL) {
+			// Out of memory
+			return(1);
+		}
+
+		func->bus = ctrl->bus;
+		func->device = device;
+		func->function = 0;
+		func->configured = 0;
+		func->switch_save = 0x10;
+		func->is_a_board = 0;
+		func->p_task_event = NULL;
+	}
+	return 0;
+}
+
+
+/*
+ * find_slot
+ */
+static inline struct slot* find_slot (struct controller* ctrl, u8 device)
+{
+	struct slot *slot;
+
+	dbg("%s", __FUNCTION__);
+	if (!ctrl)
+		return NULL;
+
+	slot = ctrl->slot;
+
+	while (slot && (slot->device != device)) {
+		slot = slot->next;
+	}
+
+	return slot;
+}
+
+// board insertion
+int amdshpc_process_SI (struct controller *ctrl, struct pci_func *func)
+{
+	u8 device, hp_slot;
+	u16 temp_word;
+	u32 tempdword;
+	int rc;
+	struct slot* p_slot;
+	int physical_slot = 0;
+
+	dbg("%s  0", __FUNCTION__);
+	if (!ctrl)
+		return(1);
+
+	tempdword = 0;
+
+	device = func->device;
+	hp_slot = device - ctrl->slot_device_offset;
+	p_slot = find_slot(ctrl, device);
+	if (p_slot) {
+		physical_slot = p_slot->number;
+	}
+
+	if (tempdword & (0x01 << hp_slot)) {
+		dbg("%s  1", __FUNCTION__);
+		return(1);
+	}
+
+	// add board
+	slot_remove(func);
+
+	func = amdshpc_slot_create(ctrl->bus);
+	dbg("%s  2",__FUNCTION__);
+	if (func == NULL) {
+		dbg("%s 3",__FUNCTION__);
+		return(1);
+	}
+
+	func->bus = ctrl->bus;
+	func->device = device;
+	func->function = 0;
+	func->configured = 0;
+	func->is_a_board = 1;
+
+	// We have to save the presence info for these slots
+	temp_word = ctrl->ctrl_int_comp >> 16;
+	func->presence_save = (temp_word >> hp_slot) & 0x01;
+	func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02;
+
+	dbg("%s 4",__FUNCTION__);
+	if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) {
+		dbg("%s 5",__FUNCTION__);
+		func->switch_save = 0;
+	} else {
+		dbg("%s 6",__FUNCTION__);
+		func->switch_save = 0x10;
+	}
+
+	rc = board_added(func, ctrl);
+	dbg("%s 7 rc=%d",__FUNCTION__,rc);
+	if (rc) {
+		dbg("%s 8",__FUNCTION__);
+		if (is_bridge(func)) {
+			dbg("%s 9",__FUNCTION__);
+			bridge_slot_remove(func);
+		} else {
+			dbg("%s 10",__FUNCTION__);
+			slot_remove(func);
+		}
+
+		// Setup slot structure with entry for empty slot
+		func = amdshpc_slot_create(ctrl->bus);
+
+		dbg("%s 11",__FUNCTION__);
+		if (func == NULL) {
+			// Out of memory
+			return(1);
+		}
+
+		func->bus = ctrl->bus;
+		func->device = device;
+		func->function = 0;
+		func->configured = 0;
+		func->is_a_board = 0;
+
+		// We have to save the presence info for these slots
+		temp_word = ctrl->ctrl_int_comp >> 16;
+		func->presence_save = (temp_word >> hp_slot) & 0x01;
+		func->presence_save |=
+		(temp_word >> (hp_slot + 7)) & 0x02;
+
+		if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) {
+			dbg("%s 12",__FUNCTION__);
+			func->switch_save = 0;
+		} else {
+			dbg("%s 13",__FUNCTION__);
+			func->switch_save = 0x10;
+		}
+	}
+
+	if (rc) {
+		dbg("%s: rc = %d\n",__FUNCTION__, rc);
+	}
+
+	if (p_slot){
+		dbg("%s 14",__FUNCTION__);
+		update_slot_info(ctrl, p_slot);
+	}
+
+	return rc;
+}
+
+// Disable Slot
+int amdshpc_process_SS (struct controller *ctrl, struct pci_func *func)
+{
+	u8 device, class_code, header_type, BCR;
+	u8 index = 0;
+	u8 replace_flag;
+	u32 rc = 0;
+	struct slot* p_slot;
+	int physical_slot=0;
+
+	dbg("%s 0",__FUNCTION__);
+	device = func->device;
+	func = amdshpc_slot_find(ctrl->bus, device, index++);
+	p_slot = find_slot(ctrl, device);
+	if (p_slot) {
+		physical_slot = p_slot->number;
+	}
+
+	// Make sure there are no video controllers here
+	while (func && !rc) {
+		dbg("%s 1..",__FUNCTION__);
+		// Check the Class Code
+		rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(func->device, func->function), 0x0B, &class_code);
+		dbg("%s 1.1 rc = %d  class_code = %02x",__FUNCTION__, rc, class_code);
+		if (rc){
+			dbg("%s 2",__FUNCTION__);
+			return rc;
+		}
+
+		if (class_code == PCI_BASE_CLASS_DISPLAY) {
+			/* Display/Video adapter (not supported) */
+			dbg("%s 3",__FUNCTION__);
+			rc = REMOVE_NOT_SUPPORTED;
+		} else {
+			dbg("%s 3.5",__FUNCTION__);
+			// See if it's a bridge
+			rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(func->device, func->function), PCI_HEADER_TYPE, &header_type);
+			if (rc){
+				dbg("%s 4",__FUNCTION__);
+				return rc;
+			}
+
+			// If it's a bridge, check the VGA Enable bit
+			if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+				dbg("%s 4.5",__FUNCTION__);
+				rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(func->device, func->function), PCI_BRIDGE_CONTROL, &BCR);
+				if (rc){
+					dbg("%s 5",__FUNCTION__);
+					return rc;
+				}
+
+				dbg("%s 5.5",__FUNCTION__);
+				// If the VGA Enable bit is set, remove isn't supported
+				if (BCR & PCI_BRIDGE_CTL_VGA) {
+					dbg("%s 6",__FUNCTION__);
+					rc = REMOVE_NOT_SUPPORTED;
+				}
+			}
+		}
+
+		func = amdshpc_slot_find(ctrl->bus, device, index++);
+		dbg("%s 7",__FUNCTION__);
+	}
+
+	func = amdshpc_slot_find(ctrl->bus, device, 0);
+	dbg("%s 8",__FUNCTION__);
+	if ((func != NULL) && !rc) {
+		dbg("%s 9",__FUNCTION__);
+		//FIXME: Replace flag should be passed into process_SS
+		replace_flag = !(ctrl->add_support);
+		rc = remove_board(func, replace_flag, ctrl);
+	} else if (!rc) {
+		dbg("%s 10",__FUNCTION__);
+		rc = 1;
+	}
+
+	if (p_slot){
+		dbg("%s 11",__FUNCTION__);
+		update_slot_info(ctrl, p_slot);
+	}
+
+	dbg("%s 12",__FUNCTION__);
+	return(rc);
+}
+
+
+/*
+ * 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;
+			dbg("%s -->temp string----> %c%c%c%c  at----->  %p\n", __FUNCTION__, temp1,temp2,temp3,temp4,fp);
+			break;
+		}
+	}
+
+	if (!status) {
+		fp = NULL;
+		dbg("%s -->Did not discover Hotplug Resource Table between start:%p  end:%p\n", __FUNCTION__, begin, end);
+		return fp;
+	}
+
+	dbg("%s -->Discovered Hotplug Resource Table at %p\n", __FUNCTION__, fp);
+	return fp;
+}
+
+/**
+ * amdshpc_slot_find - Looks for a node by bus, and device, multiple functions accessed
+ * @bus: bus to find
+ * @device: device to find
+ * @index: is 0 for first function found, 1 for the second...
+ *
+ * Returns pointer to the node if successful, %NULL otherwise.
+ */
+struct pci_func *amdshpc_slot_find(u8 bus, u8 device, u8 index) {
+	int found = -1;
+	struct pci_func *func;
+
+	func = amdshpc_slot_list[bus];
+	dbg("%s  amdshpc_slot_list[%02x] = %p", __FUNCTION__, bus, amdshpc_slot_list[bus]);
+	dbg("%s  bus, device, index  %x %d %d", __FUNCTION__, bus, device, index);
+
+	if ((func == NULL) || ((func->device == device) && (index == 0)))
+		return(func);
+
+	if (func->device == device)
+		found++;
+
+	while (func->next != NULL) {
+		func = func->next;
+
+		if (func->device == device)
+			found++;
+
+		if (found == index)
+			return(func);
+	}
+
+	return(NULL);
+}
+
+
+/*
+ * amdshpc_resource_sort_and_combine
+ *
+ * Sorts all of the nodes in the list in ascending order by
+ * their base addresses.  Also does garbage collection by
+ * combining adjacent nodes.
+ *
+ * returns 0 if success
+ */
+int amdshpc_resource_sort_and_combine(struct pci_resource **head)
+{
+	struct pci_resource *node1;
+	struct pci_resource *node2;
+	int out_of_order = 1;
+
+	dbg("%s: head = %p, *head = %p\n",__FUNCTION__, head, *head);
+
+	if (!(*head))
+		return(1);
+
+	dbg("%s -->*head->next = %p\n", __FUNCTION__,(*head)->next);
+
+	if (!(*head)->next)
+		return(0);	/* only one item on the list, already sorted! */
+
+	dbg("%s -->*head->base = 0x%x\n", __FUNCTION__,(*head)->base);
+	dbg("%s -->*head->next->base = 0x%x\n", __FUNCTION__,(*head)->next->base);
+	while (out_of_order) {
+		out_of_order = 0;
+
+		// Special case for swapping list head
+		if (((*head)->next) &&
+			((*head)->base > (*head)->next->base)) {
+			node1 = *head;
+			(*head) = (*head)->next;
+			node1->next = (*head)->next;
+			(*head)->next = node1;
+			out_of_order++;
+		}
+
+		node1 = (*head);
+
+		while (node1->next && node1->next->next) {
+			if (node1->next->base > node1->next->next->base) {
+				out_of_order++;
+				node2 = node1->next;
+				node1->next = node1->next->next;
+				node1 = node1->next;
+				node2->next = node1->next;
+				node1->next = node2;
+			} else
+				node1 = node1->next;
+		}
+	}  // End of out_of_order loop
+
+	node1 = *head;
+
+	while (node1 && node1->next) {
+		if ((node1->base + node1->length) == node1->next->base) {
+			// Combine
+			dbg("%s -->8..\n", __FUNCTION__);
+			node1->length += node1->next->length;
+			node2 = node1->next;
+			node1->next = node1->next->next;
+			kfree(node2);
+		} else
+			node1 = node1->next;
+	}
+
+	return(0);
+}
+
+
+/*
+ * amdshpc_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 amdshpc_find_available_resources (struct controller *ctrl, void *rom_start)
+{
+	u8 temp;
+	u8 populated_slot=0;
+	u8 bridged_slot;
+	u8 slot_index;
+	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;
+	struct shpc_context *shpc_context;
+
+	slot_index=0;
+
+	shpc_context = (struct shpc_context* ) ctrl->shpc_context;
+	rom_resource_table = detect_HRT_floating_pointer(rom_start, rom_start+0xffff);
+	dbg("%s -->rom_resource_table = %p\n", __FUNCTION__, 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("%s -->unused_IRQ = %x\n", __FUNCTION__, unused_IRQ);
+	dbg("%s -->PCI_IRQ = %x\n", __FUNCTION__, readl(rom_resource_table + PCIIRQ));
+
+	temp = 0;
+
+	while (unused_IRQ) {
+		if (unused_IRQ & 1) {
+			amdshpc_disk_irq = temp;
+			break;
+		}
+		unused_IRQ = unused_IRQ >> 1;
+		temp++;
+	}
+
+	dbg("%s -->amdshpc_disk_irq= %d\n", __FUNCTION__, amdshpc_disk_irq);
+	unused_IRQ = unused_IRQ >> 1;
+	temp++;
+
+	while (unused_IRQ) {
+		if (unused_IRQ & 1) {
+			amdshpc_nic_irq = temp;
+			break;
+		}
+		unused_IRQ = unused_IRQ >> 1;
+		temp++;
+	}
+
+	dbg("%s -->amdshpc_nic_irq= %d\n", __FUNCTION__, amdshpc_nic_irq);
+	unused_IRQ = readl(rom_resource_table + PCIIRQ);
+
+	temp = 0;
+
+	if (!amdshpc_nic_irq) {
+		amdshpc_nic_irq = ctrl->interrupt;
+	}
+
+	if (!amdshpc_disk_irq) {
+		amdshpc_disk_irq = ctrl->interrupt;
+	}
+
+	dbg("%s -->amdshpc_disk_irq, amdshpc_nic_irq= %d, %d\n", __FUNCTION__, amdshpc_disk_irq, amdshpc_nic_irq);
+
+	one_slot = rom_resource_table + sizeof (struct hrt);
+
+	i = readb(rom_resource_table + NUMBER_OF_ENTRIES);
+	dbg("%s -->number_of_entries = %d\n", __FUNCTION__, i);
+
+	if (!readb(one_slot + SECONDARY_BUS)) {
+		return(1);
+	}
+
+	dbg("%s -->dev|IO base|length|Mem base|length|Pre base|length|PB SB MB\n", __FUNCTION__);
+
+	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("%s -->%2.2x | %4.4x  | %4.4x | %4.4x   | %4.4x | %4.4x   | %4.4x |%2.2x %2.2x %2.2x\n", __FUNCTION__,
+			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
+		pci_bus_read_config_dword(ctrl->pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword);
+		dbg("bus %p, pri-bus %08x, slot %d, function %d, vend ID %d, tempDW %p\n",
+			ctrl->pci_bus, primary_bus, PCI_SLOT(dev_func), PCI_FUNC(dev_func), PCI_VENDOR_ID, &temp_dword);
+
+		dbg("%s -->temp_D_word = %08X\n", __FUNCTION__, temp_dword);
+
+		if (temp_dword != 0xFFFFFFFF) {
+			index = 0;
+			func = amdshpc_slot_find(primary_bus, dev_func >> 3, 0);
+			dbg("%s -->func = %p",__FUNCTION__, (unsigned long*)func);
+			while (func && (func->function != PCI_FUNC(dev_func))) {
+				dbg("%s -->func = %p (bus, dev, fun) = (%d, %d, %d)\n",__FUNCTION__, func, primary_bus, dev_func >> 3, index);
+				func = amdshpc_slot_find(primary_bus, PCI_SLOT(dev_func), 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;
+	 	   }
+			shpc_context->slot_context[slot_index].slot_occupied = 1;
+		} else {
+
+			populated_slot = 0;
+			bridged_slot = 0;
+		}
+	    slot_index++;
+	    
+		// If we've got a valid IO base, use it
+
+		temp_dword = io_base + io_length;
+		dbg("%s -->temp_D_word for io base = %08x",__FUNCTION__, temp_dword);
+
+		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("%s -->found io_node(base, length) = %x, %x\n",__FUNCTION__, io_node->base, io_node->length);
+			dbg("%s -->populated slot =%d \n",__FUNCTION__, 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;
+		dbg("%s -->temp_D_word for mem base = %08x",__FUNCTION__, temp_dword);
+		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("%s -->found mem_node(base, length) = %08x, %08x\n",__FUNCTION__, mem_node->base, mem_node->length);
+			dbg("%s -->populated slot =%d \n",__FUNCTION__, 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;
+		dbg("%s -->temp_D_word for pre mem base = %08x",__FUNCTION__, temp_dword);
+		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("%s -->found p_mem_node(base, length) = %08x, %08x\n",__FUNCTION__, p_mem_node->base, p_mem_node->length);
+			dbg("%s -->populated slot =%d \n",__FUNCTION__, 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("%s -->found bus_node(base, length) = %08x, %08x\n",__FUNCTION__, bus_node->base, bus_node->length);
+			dbg("%s -->populated slot =%d \n",__FUNCTION__, 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 &= amdshpc_resource_sort_and_combine(&(ctrl->mem_head));
+	dbg("%s -->rc =%d \n",__FUNCTION__, rc);
+	rc &= amdshpc_resource_sort_and_combine(&(ctrl->p_mem_head));
+	dbg("%s -->rc =%d \n",__FUNCTION__, rc);
+	rc &= amdshpc_resource_sort_and_combine(&(ctrl->io_head));
+	dbg("%s -->rc =%d \n",__FUNCTION__, rc);
+	rc &= amdshpc_resource_sort_and_combine(&(ctrl->bus_head));
+	dbg("%s -->rc =%d \n",__FUNCTION__, rc);
+
+	return(rc);
+}
+
+
+
+/*
+ * amdshpc_save_config
+ *
+ * Reads configuration for all slots in a PCI bus and saves info.
+ *
+ * Note:  For non-hot plug busses, the slot # saved is the device #
+ *
+ * returns 0 if success
+ */
+int amdshpc_save_config(struct controller *ctrl, int busnumber, union SLOT_CONFIG_INFO* is_hot_plug)
+ {
+	long rc;
+	u8 class_code;
+	u8 header_type;
+	u32 ID;
+	u8 secondary_bus;
+	struct pci_func *new_slot;
+	int sub_bus;
+	int FirstSupported;
+	int LastSupported;
+	int max_functions;
+	int function;
+	u8 DevError;
+	int device = 0;
+	int cloop = 0;
+	int stop_it;
+	int index;
+
+	//  Decide which slots are supported
+	if (is_hot_plug) {
+		FirstSupported 	= ctrl->first_slot;
+		LastSupported = (FirstSupported + is_hot_plug->x.lu_slots_implemented) - 1;
+	} else {
+		FirstSupported = 0;
+		LastSupported = 0x1F;
+	}
+
+	// Save PCI configuration space for all devices in supported slots
+	for (device = FirstSupported; device <= LastSupported; device++) {
+		int devfn = PCI_DEVFN(device, 0);
+
+		ID = 0xFFFFFFFF;
+		rc = pci_bus_read_config_dword(ctrl->pci_bus, devfn, PCI_VENDOR_ID, &ID);
+		if (rc)
+			return rc;
+
+		if (ID != 0xFFFFFFFF) {	  //  device in slot
+			rc = pci_bus_read_config_byte(ctrl->pci_bus, devfn, 0x0B, &class_code);
+			if (rc)
+				return rc;
+
+			rc = pci_bus_read_config_byte(ctrl->pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+			if (rc)
+				return rc;
+
+			// If multi-function device, set max_functions to 8
+			if (header_type & 0x80)
+				max_functions = 8;
+			else
+				max_functions = 1;
+
+			function = 0;
+
+			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 (rc) {
+						return rc;
+					} else {
+						sub_bus = (int) secondary_bus;
+
+						// Save secondary bus cfg spc
+						// with this recursive call.
+						rc = amdshpc_save_config(ctrl, sub_bus, 0);
+
+						if (rc)
+							return rc;
+					}
+				}
+
+				index = 0;
+				new_slot = amdshpc_slot_find(busnumber, device, index++);
+				while (new_slot &&
+				       (new_slot->function != (u8) function))
+					new_slot = amdshpc_slot_find(busnumber, device, index++);
+
+				if (!new_slot) {
+					// Setup slot structure.
+					new_slot = amdshpc_slot_create(busnumber);
+
+					if (new_slot == NULL)
+						return(1);
+				}
+
+				new_slot->bus = (u8) busnumber;
+				new_slot->device = (u8) device;
+				new_slot->function = (u8) function;
+				new_slot->is_a_board = 1;
+				new_slot->switch_save = 0x10;
+				// 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("%s EXISTING SLOT", __FUNCTION__);
+				dbg("%s ns->bus         = %d", __FUNCTION__, new_slot->bus);
+				dbg("%s ns->device      = %d", __FUNCTION__, new_slot->device);
+				dbg("%s ns->function    = %d", __FUNCTION__, new_slot->function);
+				dbg("%s ns->is_a_board  = %d", __FUNCTION__, new_slot->is_a_board);
+				dbg("%s ns->switch_save = %02x", __FUNCTION__, new_slot->switch_save);
+				dbg("%s ns->pci_dev     = %p", __FUNCTION__, 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]));
+					if (rc)
+						return rc;
+				}
+
+				function++;
+				stop_it = 0;
+
+				//  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.
+						function++;
+					} else {  // Something there
+						rc = pci_bus_read_config_byte(ctrl->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);
+						if (rc)
+							return rc;
+
+						stop_it++;
+					}
+				}
+
+			} while (function < max_functions);
+		}		// End of IF (device in slot?)
+		else if (is_hot_plug) {
+			// Setup slot structure with entry for empty slot
+			new_slot = amdshpc_slot_create(busnumber);
+
+			if (new_slot == NULL) {
+				return(1);
+			}
+
+			new_slot->bus = (u8) busnumber;
+			new_slot->device = (u8) device;
+			new_slot->function = 0;
+			new_slot->is_a_board = 0;
+			new_slot->presence_save = 0;
+			new_slot->switch_save = 0;
+			dbg("%s NEW SLOT", __FUNCTION__);
+			dbg("%s ns->bus         = %d", __FUNCTION__, new_slot->bus);
+			dbg("%s ns->device      = %d", __FUNCTION__, new_slot->function);
+			dbg("%s ns->function    = %d", __FUNCTION__, new_slot->function);
+		}
+	}// End of FOR loop
+
+	return 0;
+}
+
+
+/*
+ * amdshpc_set_irq
+ *
+ * @bus_num: bus number of PCI device
+ * @dev_num: device number of PCI device
+ */
+/*
+int amdshpc_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
+{
+	int rc;
+	u16 temp_word;
+	struct pci_dev fakedev;
+	struct pci_bus fakebus;
+
+	fakedev.devfn = dev_num << 3;
+	fakedev.bus = &fakebus;
+	fakebus.number = bus_num;
+	dbg("%s : dev %d, bus %d, pin %d, num %d\n",__FUNCTION__,
+		dev_num, bus_num, int_pin, irq_num);
+	rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num);
+	dbg("%s:rc %d\n",__FUNCTION__, rc);
+	if (rc)
+		return rc;
+
+	// 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
+	outb((u8) (temp_word & 0xFF), 0x4d0);
+	outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
+
+	return 0;
+}
+*/
+
+/*
+ * do_pre_bridge_resource_split
+ *
+ *	Returns zero or one node of resources that aren't in use
+ *
+ */
+static struct pci_resource *do_pre_bridge_resource_split (struct pci_resource **head, struct pci_resource **orig_head, u32 alignment) {
+	struct pci_resource *prevnode = NULL;
+	struct pci_resource *node;
+	struct pci_resource *split_node;
+	u32 rc;
+	u32 temp_dword;
+	dbg("%s -->do_pre_bridge_resource_split\n",__FUNCTION__);
+
+	if (!(*head) || !(*orig_head))
+		return(NULL);
+
+	rc = amdshpc_resource_sort_and_combine(head);
+
+	if (rc)
+		return(NULL);
+
+	if ((*head)->base != (*orig_head)->base)
+		return(NULL);
+
+	if ((*head)->length == (*orig_head)->length)
+		return(NULL);
+
+
+	// If we got here, there the bridge requires some of the resource, but
+	// we may be able to split some off of the front
+
+	node = *head;
+
+	if (node->length & (alignment -1)) {
+		// this one isn't an aligned length, so we'll make a new entry
+		// and split it up.
+		split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+		if (!split_node)
+			return(NULL);
+
+		temp_dword = (node->length | (alignment-1)) + 1 - alignment;
+
+		split_node->base = node->base;
+		split_node->length = temp_dword;
+
+		node->length -= temp_dword;
+		node->base += split_node->length;
+
+		// Put it in the list
+		*head = split_node;
+		split_node->next = node;
+	}
+
+	if (node->length < alignment) {
+		return(NULL);
+	}
+
+	// Now unlink it
+	if (*head == node) {
+		*head = node->next;
+		node->next = NULL;
+	} else {
+		prevnode = *head;
+		while (prevnode->next != node)
+			prevnode = prevnode->next;
+
+		prevnode->next = node->next;
+		node->next = NULL;
+	}
+
+	return(node);
+}
+
+
+/*
+ * do_bridge_resource_split
+ *
+ *	Returns zero or one node of resources that aren't in use
+ *
+ */
+static struct pci_resource *do_bridge_resource_split (struct pci_resource **head, u32 alignment) {
+	struct pci_resource *prevnode = NULL;
+	struct pci_resource *node;
+	u32 rc;
+	u32 temp_dword;
+
+	if (!(*head))
+		return(NULL);
+
+	rc = amdshpc_resource_sort_and_combine(head);
+
+	if (rc)
+		return(NULL);
+
+	node = *head;
+
+	while (node->next) {
+		prevnode = node;
+		node = node->next;
+		kfree(prevnode);
+	}
+
+	if (node->length < alignment) {
+		kfree(node);
+		return(NULL);
+	}
+
+	if (node->base & (alignment - 1)) {
+		// Short circuit if adjusted size is too small
+		temp_dword = (node->base | (alignment-1)) + 1;
+		if ((node->length - (temp_dword - node->base)) < alignment) {
+			kfree(node);
+			return(NULL);
+		}
+
+		node->length -= (temp_dword - node->base);
+		node->base = temp_dword;
+	}
+
+	if (node->length & (alignment - 1)) {
+		// There's stuff in use after this node
+		kfree(node);
+		return(NULL);
+	}
+
+	return(node);
+}
+
+
+/*
+ * sort_by_size
+ *
+ * Sorts nodes on the list by their length.
+ * Smallest first.
+ *
+ */
+static int sort_by_size(struct pci_resource **head)
+{
+	struct pci_resource *current_res;
+	struct pci_resource *next_res;
+	int out_of_order = 1;
+
+	if (!(*head))
+		return(1);
+
+	if (!((*head)->next))
+		return(0);
+
+	while (out_of_order) {
+		out_of_order = 0;
+
+		// Special case for swapping list head
+		if (((*head)->next) &&
+			((*head)->length > (*head)->next->length)) {
+			out_of_order++;
+			current_res = *head;
+			*head = (*head)->next;
+			current_res->next = (*head)->next;
+			(*head)->next = current_res;
+		}
+
+		current_res = *head;
+
+		while (current_res->next && current_res->next->next) {
+			if (current_res->next->length > current_res->next->next->length) {
+				out_of_order++;
+				next_res = current_res->next;
+				current_res->next = current_res->next->next;
+				current_res = current_res->next;
+				next_res->next = current_res->next;
+				current_res->next = next_res;
+			} else
+				current_res	= current_res->next;
+		}
+	}  // End of out_of_order loop
+
+	return(0);
+}
+
+/**
+ * amdshpc_slot_create - Creates a node and adds it to the proper bus.
+ * @busnumber - bus where new node is to be located
+ *
+ * Returns pointer to the new node or NULL if unsuccessful
+ */
+struct pci_func *amdshpc_slot_create(u8 busnumber) {
+	struct pci_func *new_slot;
+	struct pci_func *next;
+
+	dbg("%s  busnumber = %02xh",__FUNCTION__, busnumber);
+	new_slot = (struct pci_func *) kmalloc(sizeof(struct pci_func), GFP_KERNEL);
+
+	if (new_slot == NULL) {
+		// I'm not dead yet!
+		// You will be.
+		return(new_slot);
+	}
+
+	memset(new_slot, 0, sizeof(struct pci_func));
+
+	new_slot->next = NULL;
+	new_slot->configured = 1;
+
+	if (amdshpc_slot_list[busnumber] == NULL) {
+		amdshpc_slot_list[busnumber] = new_slot;
+		dbg("%s   created new slot in amdshpc_slot_list  amdshpc_slot_list[%02X] = %p", __FUNCTION__,
+							busnumber, amdshpc_slot_list[busnumber]);
+	} else {
+		next = amdshpc_slot_list[busnumber];
+		while (next->next != NULL)
+			next = next->next;
+		next->next = new_slot;
+	}
+	return(new_slot);
+}
+
+
+/*
+ * return_resource
+ *
+ * Puts node back in the resource list pointed to by head
+ *
+ */
+static inline void return_resource (struct pci_resource **head, struct pci_resource *node)
+{
+	dbg("%s",__FUNCTION__);
+	if (!node || !head)
+		return;
+	node->next = *head;
+	*head = node;
+}
+
+
+/*
+ * sort_by_max_size
+ *
+ * Sorts nodes on the list by their length.
+ * Largest first.
+ *
+ */
+static int sort_by_max_size(struct pci_resource **head)
+{
+	struct pci_resource *current_res;
+	struct pci_resource *next_res;
+	int out_of_order = 1;
+
+	if (!(*head))
+		return(1);
+
+	if (!((*head)->next))
+		return(0);
+
+	while (out_of_order) {
+		out_of_order = 0;
+
+		// Special case for swapping list head
+		if (((*head)->next) &&
+			((*head)->length < (*head)->next->length)) {
+			out_of_order++;
+			current_res = *head;
+			*head = (*head)->next;
+			current_res->next = (*head)->next;
+			(*head)->next = current_res;
+		}
+
+		current_res = *head;
+
+		while (current_res->next && current_res->next->next) {
+			if (current_res->next->length < current_res->next->next->length) {
+				out_of_order++;
+				next_res = current_res->next;
+				current_res->next = current_res->next->next;
+				current_res = current_res->next;
+				next_res->next = current_res->next;
+				current_res->next = next_res;
+			} else
+				current_res	= current_res->next;
+		}
+	}  // End of out_of_order loop
+
+	return(0);
+}
+
+
+/*
+ * get_max_resource
+ *
+ * Gets the largest node that is at least "size" big from the
+ * list pointed to by head.  It aligns the node on top and bottom
+ * to "size" alignment before returning it.
+ */
+static struct pci_resource *get_max_resource (struct pci_resource **head, u32 size) {
+	struct pci_resource *max;
+	struct pci_resource *temp;
+	struct pci_resource *split_node;
+	u32 temp_dword;
+
+	if (!(*head))
+		return(NULL);
+
+	if (amdshpc_resource_sort_and_combine(head))
+		return(NULL);
+
+	if (sort_by_max_size(head))
+		return(NULL);
+
+	for (max = *head;max; max = max->next) {
+
+		// If not big enough we could probably just bail,
+		// instead we'll continue to the next.
+		if (max->length < size)
+			continue;
+
+		if (max->base & (size - 1)) {
+			// this one isn't base aligned properly
+			// so we'll make a new entry and split it up
+			temp_dword = (max->base | (size-1)) + 1;
+
+			// Short circuit if adjusted size is too small
+			if ((max->length - (temp_dword - max->base)) < size)
+				continue;
+
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+
+			split_node->base = max->base;
+			split_node->length = temp_dword - max->base;
+			max->base = temp_dword;
+			max->length -= split_node->length;
+
+			// Put it next in the list
+			split_node->next = max->next;
+			max->next = split_node;
+		}
+
+		if ((max->base + max->length) & (size - 1)) {
+			// this one isn't end aligned properly at the top
+			// so we'll make a new entry and split it up
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+			temp_dword = ((max->base + max->length) & ~(size - 1));
+			split_node->base = temp_dword;
+			split_node->length = max->length + max->base
+								 - split_node->base;
+			max->length -= split_node->length;
+
+			// Put it in the list
+			split_node->next = max->next;
+			max->next = split_node;
+		}
+
+		// Make sure it didn't shrink too much when we aligned it
+		if (max->length < size)
+			continue;
+
+		// Now take it out of the list
+		temp = (struct pci_resource*) *head;
+		if (temp == max) {
+			*head = max->next;
+		} else {
+			while (temp && temp->next != max) {
+				temp = temp->next;
+			}
+
+			temp->next = max->next;
+		}
+
+		max->next = NULL;
+		return(max);
+	}
+
+	// If we get here, we couldn't find one
+	return(NULL);
+}
+
+
+/*
+ * get_io_resource
+ *
+ * this function sorts the resource list by size and then
+ * returns the first node of "size" length that is not in the
+ * ISA aliasing window.  If it finds a node larger than "size"
+ * it will split it up.
+ *
+ * size must be a power of two.
+ */
+static struct pci_resource *get_io_resource (struct pci_resource **head, u32 size) {
+	struct pci_resource *prevnode;
+	struct pci_resource *node;
+	struct pci_resource *split_node;
+	u32 temp_dword;
+
+	if (!(*head))
+		return(NULL);
+
+	if ( amdshpc_resource_sort_and_combine(head) )
+		return(NULL);
+
+	if ( sort_by_size(head) )
+		return(NULL);
+
+	for (node = *head; node; node = node->next) {
+		if (node->length < size)
+			continue;
+
+		if (node->base & (size - 1)) {
+			// this one isn't base aligned properly
+			// so we'll make a new entry and split it up
+			temp_dword = (node->base | (size-1)) + 1;
+
+			// Short circuit if adjusted size is too small
+			if ((node->length - (temp_dword - node->base)) < size)
+				continue;
+
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+
+			split_node->base = node->base;
+			split_node->length = temp_dword - node->base;
+			node->base = temp_dword;
+			node->length -= split_node->length;
+
+			// Put it in the list
+			split_node->next = node->next;
+			node->next = split_node;
+		} // End of non-aligned base
+
+		// Don't need to check if too small since we already did
+		if (node->length > size) {
+			// this one is longer than we need
+			// so we'll make a new entry and split it up
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+
+			split_node->base = node->base + size;
+			split_node->length = node->length - size;
+			node->length = size;
+
+			// Put it in the list
+			split_node->next = node->next;
+			node->next = split_node;
+		}  // End of too big on top end
+
+		// For IO make sure it's not in the ISA aliasing space
+		if (node->base & 0x300L)
+			continue;
+
+		// If we got here, then it is the right size
+		// Now take it out of the list
+		if (*head == node) {
+			*head = node->next;
+		} else {
+			prevnode = *head;
+			while (prevnode->next != node)
+				prevnode = prevnode->next;
+
+			prevnode->next = node->next;
+		}
+		node->next = NULL;
+		// Stop looping
+		break;
+	}
+
+	return(node);
+}
+
+
+/*
+ * get_resource
+ *
+ * this function sorts the resource list by size and then
+ * returns the first node of "size" length.  If it finds a node
+ * larger than "size" it will split it up.
+ *
+ * size must be a power of two.
+ */
+static struct pci_resource *get_resource (struct pci_resource **head, u32 size) {
+	struct pci_resource *prevnode;
+	struct pci_resource *node;
+	struct pci_resource *split_node;
+	u32 temp_dword;
+
+	if (!(*head))
+		return(NULL);
+
+	if ( amdshpc_resource_sort_and_combine(head) )
+		return(NULL);
+
+	if ( sort_by_size(head) )
+		return(NULL);
+
+	for (node = *head; node; node = node->next) {
+		dbg("%s: req_size =%x node=%p, base=%x, length=%x\n",__FUNCTION__,
+			size, node, node->base, node->length);
+		if (node->length < size)
+			continue;
+
+		if (node->base & (size - 1)) {
+			dbg("%s: not aligned\n",__FUNCTION__);
+			// this one isn't base aligned properly
+			// so we'll make a new entry and split it up
+			temp_dword = (node->base | (size-1)) + 1;
+
+			// Short circuit if adjusted size is too small
+			if ((node->length - (temp_dword - node->base)) < size)
+				continue;
+
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+
+			split_node->base = node->base;
+			split_node->length = temp_dword - node->base;
+			node->base = temp_dword;
+			node->length -= split_node->length;
+
+			// Put it in the list
+			split_node->next = node->next;
+			node->next = split_node;
+		} // End of non-aligned base
+
+		// Don't need to check if too small since we already did
+		if (node->length > size) {
+			dbg("%s: too big\n",__FUNCTION__);
+			// this one is longer than we need
+			// so we'll make a new entry and split it up
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+
+			split_node->base = node->base + size;
+			split_node->length = node->length - size;
+			node->length = size;
+
+			// Put it in the list
+			split_node->next = node->next;
+			node->next = split_node;
+		}  // End of too big on top end
+
+		dbg("%s: got one!!!\n",__FUNCTION__);
+		// If we got here, then it is the right size
+		// Now take it out of the list
+		if (*head == node) {
+			*head = node->next;
+		} else {
+			prevnode = *head;
+			while (prevnode->next != node)
+				prevnode = prevnode->next;
+
+			prevnode->next = node->next;
+		}
+		node->next = NULL;
+		// Stop looping
+		break;
+	}
+	return(node);
+}
+
+/*
+ * amdshpc_return_board_resources
+ *
+ * this routine returns all resources allocated to a board to
+ * the available pool.
+ *
+ * returns 0 if success
+ */
+int amdshpc_return_board_resources(struct pci_func * func, struct resource_lists * resources)
+{
+	int rc = 1;
+	struct pci_resource *node;
+	struct pci_resource *t_node;
+	dbg("%s",__FUNCTION__);
+
+	if (!func)
+		return(1);
+
+	node = func->io_head;
+	func->io_head = NULL;
+	while (node) {
+		t_node = node->next;
+		return_resource(&(resources->io_head), node);
+		node = t_node;
+	}
+
+	node = func->mem_head;
+	func->mem_head = NULL;
+	while (node) {
+		t_node = node->next;
+		return_resource(&(resources->mem_head), node);
+		node = t_node;
+	}
+
+	node = func->p_mem_head;
+	func->p_mem_head = NULL;
+	while (node) {
+		t_node = node->next;
+		return_resource(&(resources->p_mem_head), node);
+		node = t_node;
+	}
+
+	node = func->bus_head;
+	func->bus_head = NULL;
+	while (node) {
+		t_node = node->next;
+		return_resource(&(resources->bus_head), node);
+		node = t_node;
+	}
+
+	rc |= amdshpc_resource_sort_and_combine(&(resources->mem_head));
+	rc |= amdshpc_resource_sort_and_combine(&(resources->p_mem_head));
+	rc |= amdshpc_resource_sort_and_combine(&(resources->io_head));
+	rc |= amdshpc_resource_sort_and_combine(&(resources->bus_head));
+
+	return(rc);
+}
+
+
+/*
+ * amdshpc_destroy_resource_list
+ *
+ * Puts node back in the resource list pointed to by head
+ */
+void amdshpc_destroy_resource_list (struct resource_lists * resources)
+{
+	struct pci_resource *res, *tres;
+
+	res = resources->io_head;
+	resources->io_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = resources->mem_head;
+	resources->mem_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = resources->p_mem_head;
+	resources->p_mem_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = resources->bus_head;
+	resources->bus_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+}
+
+
+/*
+ * amdshpc_destroy_board_resources
+ *
+ * Puts node back in the resource list pointed to by head
+ */
+void amdshpc_destroy_board_resources (struct pci_func * func)
+{
+	struct pci_resource *res, *tres;
+
+	res = func->io_head;
+	func->io_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = func->mem_head;
+	func->mem_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = func->p_mem_head;
+	func->p_mem_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = func->bus_head;
+	func->bus_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+}
+
+/**
+ * configure_new_device - Configures the PCI header information of one board.
+ *
+ * @ctrl: pointer to controller structure
+ * @func: pointer to function structure
+ * @behind_bridge: 1 if this is a recursive call, 0 if not
+ * @resources: pointer to set of resource lists
+ *
+ * Returns 0 if success
+ *
+ */
+static u32 configure_new_device (struct controller * ctrl, struct pci_func * func,
+								 u8 behind_bridge, struct resource_lists * resources)
+{
+	u8 temp_byte, function, max_functions, stop_it;
+	int rc;
+	u32 ID;
+	struct pci_func *new_slot;
+	int index;
+
+	new_slot = func;
+
+	dbg("%s",__FUNCTION__);
+	// Check for Multi-function device
+	rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte);
+	if (rc) {
+		dbg("%s: rc = %d\n",__FUNCTION__, rc);
+		return rc;
+	}
+
+	if (temp_byte & 0x80)	// Multi-function device
+		max_functions = 8;
+	else
+		max_functions = 1;
+
+	function = 0;
+
+	do {
+		rc = configure_new_function(ctrl, new_slot, behind_bridge, resources);
+
+		if (rc) {
+			dbg("%s -->configure_new_function failed %d\n",__FUNCTION__,rc);
+			index = 0;
+
+			while (new_slot) {
+				new_slot = amdshpc_slot_find(new_slot->bus, new_slot->device, index++);
+
+				if (new_slot)
+					amdshpc_return_board_resources(new_slot, resources);
+			}
+
+			return(rc);
+		}
+
+		function++;
+
+		stop_it = 0;
+
+		//  The following loop skips to the next present function
+		//  and creates a board structure
+
+		while ((function < max_functions) && (!stop_it)) {
+			pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID);
+
+			if (ID == 0xFFFFFFFF) {	  // There's nothing there.
+				function++;
+			} else {  // There's something there
+				// Setup slot structure.
+				new_slot = amdshpc_slot_create(func->bus);
+
+				if (new_slot == NULL) {
+					// Out of memory
+					return(1);
+				}
+
+				new_slot->bus = func->bus;
+				new_slot->device = func->device;
+				new_slot->function = function;
+				new_slot->is_a_board = 1;
+				new_slot->status = 0;
+
+				stop_it++;
+			}
+		}
+
+	} while (function < max_functions);
+	dbg("%s -->returning from configure_new_device\n",__FUNCTION__);
+
+	return 0;
+}
+
+
+/*
+  Configuration logic that involves the hotplug data structures and
+  their bookkeeping
+ */
+
+
+/**
+ * configure_new_function - Configures the PCI header information of one device
+ *
+ * @ctrl: pointer to controller structure
+ * @func: pointer to function structure
+ * @behind_bridge: 1 if this is a recursive call, 0 if not
+ * @resources: pointer to set of resource lists
+ *
+ * Calls itself recursively for bridged devices.
+ * Returns 0 if success
+ *
+ */
+static int configure_new_function (struct controller * ctrl, struct pci_func * func,
+								   u8 behind_bridge, struct resource_lists * resources)
+{
+	int cloop;
+	u8 IRQ;
+	u8 temp_byte;
+	u8 device;
+	u8 class_code;
+	u16 command;
+	u16 temp_word;
+	u32 temp_dword;
+	u32 rc;
+	u32 temp_register;
+	u32 base;
+	u32 ID;
+	struct pci_resource *mem_node;
+	struct pci_resource *p_mem_node;
+	struct pci_resource *io_node;
+	struct pci_resource *bus_node;
+	struct pci_resource *hold_mem_node;
+	struct pci_resource *hold_p_mem_node;
+	struct pci_resource *hold_IO_node;
+	struct pci_resource *hold_bus_node;
+	struct irq_mapping irqs;
+	struct pci_func *new_slot;
+	struct resource_lists temp_resources;
+	int devfn = PCI_DEVFN(func->device, func->function);
+
+	dbg("%s", __FUNCTION__);
+	// Check for Bridge
+	rc = pci_bus_read_config_byte(ctrl->pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte);
+	if (rc)
+		return rc;
+
+	if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	// PCI-PCI Bridge
+		// set Primary bus
+		dbg("%s -->set Primary bus = %d\n",__FUNCTION__, func->bus);
+		rc = pci_bus_write_config_byte(ctrl->pci_bus, devfn, PCI_PRIMARY_BUS, func->bus);
+		if (rc)
+			return rc;
+
+		// find range of busses to use
+		dbg("%s -->find ranges of buses to use\n",__FUNCTION__);
+		bus_node = get_max_resource(&resources->bus_head, 1);
+
+		// If we don't have any busses to allocate, we can't continue
+		if (!bus_node)
+			return -ENOMEM;
+
+		// set Secondary bus
+		temp_byte = bus_node->base;
+		dbg("%s -->set Secondary bus = %d\n",__FUNCTION__, bus_node->base);
+		rc = pci_bus_write_config_byte(ctrl->pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte);
+		if (rc)
+			return rc;
+
+		// set subordinate bus
+		temp_byte = bus_node->base + bus_node->length - 1;
+		dbg("%s -->set subordinate bus = %d\n",__FUNCTION__, bus_node->base + bus_node->length - 1);
+		rc = pci_bus_write_config_byte(ctrl->pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
+		if (rc)
+			return rc;
+
+		// set subordinate Latency Timer and base Latency Timer
+		temp_byte = 0x40;
+		rc = pci_bus_write_config_byte(ctrl->pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
+		if (rc)
+			return rc;
+		rc = pci_bus_write_config_byte(ctrl->pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
+		if (rc)
+			return rc;
+
+		// set Cache Line size
+		temp_byte = 0x08;
+		rc = pci_bus_write_config_byte(ctrl->pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
+		if (rc)
+			return rc;
+
+		// Setup the IO, memory, and prefetchable windows
+
+		io_node = get_max_resource(&(resources->io_head), 0x1000);
+		mem_node = get_max_resource(&(resources->mem_head), 0x100000);
+		p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000);
+		dbg("%s -->Setup the IO, memory, and prefetchable windows\n",__FUNCTION__);
+		dbg("%s -->io_node\n",__FUNCTION__);
+		dbg("%s -->(base, len, next) (%x, %x, %p)\n",__FUNCTION__, io_node->base, io_node->length, io_node->next);
+		dbg("%s -->mem_node\n",__FUNCTION__);
+		dbg("%s -->(base, len, next) (%x, %x, %p)\n",__FUNCTION__, mem_node->base, mem_node->length, mem_node->next);
+		dbg("%s -->p_mem_node\n",__FUNCTION__);
+		dbg("%s -->(base, len, next) (%x, %x, %p)\n",__FUNCTION__, p_mem_node->base, p_mem_node->length, p_mem_node->next);
+
+		// set up the IRQ info
+		if (!resources->irqs) {
+			irqs.barber_pole = 0;
+			irqs.interrupt[0] = 0;
+			irqs.interrupt[1] = 0;
+			irqs.interrupt[2] = 0;
+			irqs.interrupt[3] = 0;
+			irqs.valid_INT = 0;
+		} else {
+			irqs.barber_pole = resources->irqs->barber_pole;
+			irqs.interrupt[0] = resources->irqs->interrupt[0];
+			irqs.interrupt[1] = resources->irqs->interrupt[1];
+			irqs.interrupt[2] = resources->irqs->interrupt[2];
+			irqs.interrupt[3] = resources->irqs->interrupt[3];
+			irqs.valid_INT = resources->irqs->valid_INT;
+		}
+
+		// set up resource lists that are now aligned on top and bottom
+		// for anything behind the bridge.
+		temp_resources.bus_head = bus_node;
+		temp_resources.io_head = io_node;
+		temp_resources.mem_head = mem_node;
+		temp_resources.p_mem_head = p_mem_node;
+		temp_resources.irqs = &irqs;
+
+		// Make copies of the nodes we are going to pass down so that
+		// if there is a problem,we can just use these to free resources
+		hold_bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+		hold_IO_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+		hold_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+		hold_p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+		if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) {
+			if (hold_bus_node)
+				kfree(hold_bus_node);
+			if (hold_IO_node)
+				kfree(hold_IO_node);
+			if (hold_mem_node)
+				kfree(hold_mem_node);
+			if (hold_p_mem_node)
+				kfree(hold_p_mem_node);
+
+			return(1);
+		}
+
+		memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource));
+
+		bus_node->base += 1;
+		bus_node->length -= 1;
+		bus_node->next = NULL;
+
+		// If we have IO resources copy them and fill in the bridge's
+		// IO range registers
+		if (io_node) {
+			memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));
+			io_node->next = NULL;
+
+			// set IO base and Limit registers
+			temp_byte = io_node->base >> 8;
+			rc = pci_bus_write_config_byte(ctrl->pci_bus, devfn, PCI_IO_BASE, temp_byte);
+
+			temp_byte = (io_node->base + io_node->length - 1) >> 8;
+			rc = pci_bus_write_config_byte(ctrl->pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
+		} else {
+			kfree(hold_IO_node);
+			hold_IO_node = NULL;
+		}
+
+		// If we have memory resources copy them and fill in the bridge's
+		// memory range registers.  Otherwise, fill in the range
+		// registers with values that disable them.
+		if (mem_node) {
+			memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource));
+			mem_node->next = NULL;
+
+			// set Mem base and Limit registers
+			temp_word = mem_node->base >> 16;
+			pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+
+			temp_word = (mem_node->base + mem_node->length - 1) >> 16;
+			pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+		} else {
+			temp_word = 0xFFFF;
+			pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+
+			temp_word = 0x0000;
+			pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+
+			kfree(hold_mem_node);
+			hold_mem_node = NULL;
+		}
+
+		// If we have prefetchable memory resources copy them and
+		// fill in the bridge's memory range registers.  Otherwise,
+		// fill in the range registers with values that disable them.
+		if (p_mem_node) {
+			memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));
+			p_mem_node->next = NULL;
+
+			// set Pre Mem base and Limit registers
+			temp_word = p_mem_node->base >> 16;
+			pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+
+			temp_word = (p_mem_node->base + p_mem_node->length - 1) >> 16;
+			pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+		} else {
+			temp_word = 0xFFFF;
+			pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+
+			temp_word = 0x0000;
+			pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+
+			kfree(hold_p_mem_node);
+			hold_p_mem_node = NULL;
+		}
+
+		// Adjust this to compensate for extra adjustment in first loop
+		irqs.barber_pole--;
+
+		rc = 0;
+
+		// Here we actually find the devices and configure them
+		for (device = 0; (device <= 0x1F) && !rc; device++) {
+			irqs.barber_pole = (irqs.barber_pole + 1) & 0x03;
+
+			ID = 0xFFFFFFFF;
+			pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(device, 0), 0x00, &ID);
+
+			if (ID != 0xFFFFFFFF) {	  //  device Present
+				// Setup slot structure.
+				new_slot = amdshpc_slot_create(hold_bus_node->base);
+
+				if (new_slot == NULL) {
+					// Out of memory
+					rc = -ENOMEM;
+					continue;
+				}
+
+				new_slot->bus = hold_bus_node->base;
+				new_slot->device = device;
+				new_slot->function = 0;
+				new_slot->is_a_board = 1;
+				new_slot->status = 0;
+
+				rc = configure_new_device(ctrl, new_slot, 1, &temp_resources);
+				dbg("%s -->configure_new_device rc=0x%x\n",__FUNCTION__,rc);
+			}	// End of IF (device in slot?)
+		}		// End of FOR loop
+
+		if (rc) {
+			amdshpc_destroy_resource_list(&temp_resources);
+
+			return_resource(&(resources->bus_head), hold_bus_node);
+			return_resource(&(resources->io_head), hold_IO_node);
+			return_resource(&(resources->mem_head), hold_mem_node);
+			return_resource(&(resources->p_mem_head), hold_p_mem_node);
+			return(rc);
+		}
+		// save the interrupt routing information
+		if (resources->irqs) {
+			resources->irqs->interrupt[0] = irqs.interrupt[0];
+			resources->irqs->interrupt[1] = irqs.interrupt[1];
+			resources->irqs->interrupt[2] = irqs.interrupt[2];
+			resources->irqs->interrupt[3] = irqs.interrupt[3];
+			resources->irqs->valid_INT = irqs.valid_INT;
+		} else if (!behind_bridge) {
+			// We need to hook up the interrupts here
+			for (cloop = 0; cloop < 4; cloop++) {
+				if (irqs.valid_INT & (0x01 << cloop)) {
+rc=0;
+//					rc = amdshpc_set_irq(func->bus, func->device,
+//									   0x0A + cloop, irqs.interrupt[cloop]);
+					if (rc) {
+						amdshpc_destroy_resource_list (&temp_resources);
+
+						return_resource(&(resources-> bus_head), hold_bus_node);
+						return_resource(&(resources-> io_head), hold_IO_node);
+						return_resource(&(resources-> mem_head), hold_mem_node);
+						return_resource(&(resources-> p_mem_head), hold_p_mem_node);
+						return rc;
+					}
+				}
+			}	// end of for loop
+		}
+		// Return unused bus resources
+		// First use the temporary node to store information for the board
+		if (hold_bus_node && bus_node && temp_resources.bus_head) {
+			hold_bus_node->length = bus_node->base - hold_bus_node->base;
+
+			hold_bus_node->next = func->bus_head;
+			func->bus_head = hold_bus_node;
+
+			temp_byte = temp_resources.bus_head->base - 1;
+
+			// set subordinate bus
+			pci_bus_write_config_byte(ctrl->pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
+
+			if (temp_resources.bus_head->length == 0) {
+				kfree(temp_resources.bus_head);
+				temp_resources.bus_head = NULL;
+			} else {
+				return_resource(&(resources->bus_head), temp_resources.bus_head);
+			}
+		}
+
+		// If we have IO space available and there is some left,
+		// return the unused portion
+		if (hold_IO_node && temp_resources.io_head) {
+			io_node = do_pre_bridge_resource_split(&(temp_resources.io_head),
+												   &hold_IO_node, 0x1000);
+
+			// Check if we were able to split something off
+			if (io_node) {
+				hold_IO_node->base = io_node->base + io_node->length;
+
+				temp_byte = (hold_IO_node->base) >> 8;
+				pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_IO_BASE, temp_byte);
+
+				return_resource(&(resources->io_head), io_node);
+			}
+
+			io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000);
+
+			// Check if we were able to split something off
+			if (io_node) {
+				// First use the temporary node to store information for the board
+				hold_IO_node->length = io_node->base - hold_IO_node->base;
+
+				// If we used any, add it to the board's list
+				if (hold_IO_node->length) {
+					hold_IO_node->next = func->io_head;
+					func->io_head = hold_IO_node;
+
+					temp_byte = (io_node->base - 1) >> 8;
+					pci_bus_write_config_byte(ctrl->pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
+
+					return_resource(&(resources->io_head), io_node);
+				} else {
+					// it doesn't need any IO
+					temp_word = 0x0000;
+					pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_IO_LIMIT, temp_word);
+
+					return_resource(&(resources->io_head), io_node);
+					kfree(hold_IO_node);
+				}
+			} else {
+				// it used most of the range
+				hold_IO_node->next = func->io_head;
+				func->io_head = hold_IO_node;
+			}
+		} else if (hold_IO_node) {
+			// it used the whole range
+			hold_IO_node->next = func->io_head;
+			func->io_head = hold_IO_node;
+		}
+		// If we have memory space available and there is some left,
+		// return the unused portion
+		if (hold_mem_node && temp_resources.mem_head) {
+			mem_node = do_pre_bridge_resource_split(&(temp_resources.  mem_head),
+													&hold_mem_node, 0x100000);
+
+			// Check if we were able to split something off
+			if (mem_node) {
+				hold_mem_node->base = mem_node->base + mem_node->length;
+
+				temp_word = (hold_mem_node->base) >> 16;
+				pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+
+				return_resource(&(resources->mem_head), mem_node);
+			}
+
+			mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000);
+
+			// Check if we were able to split something off
+			if (mem_node) {
+				// First use the temporary node to store information for the board
+				hold_mem_node->length = mem_node->base - hold_mem_node->base;
+
+				if (hold_mem_node->length) {
+					hold_mem_node->next = func->mem_head;
+					func->mem_head = hold_mem_node;
+
+					// configure end address
+					temp_word = (mem_node->base - 1) >> 16;
+					pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+
+					// Return unused resources to the pool
+					return_resource(&(resources->mem_head), mem_node);
+				} else {
+					// it doesn't need any Mem
+					temp_word = 0x0000;
+					pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+
+					return_resource(&(resources->mem_head), mem_node);
+					kfree(hold_mem_node);
+				}
+			} else {
+				// it used most of the range
+				hold_mem_node->next = func->mem_head;
+				func->mem_head = hold_mem_node;
+			}
+		} else if (hold_mem_node) {
+			// it used the whole range
+			hold_mem_node->next = func->mem_head;
+			func->mem_head = hold_mem_node;
+		}
+		// If we have prefetchable memory space available and there is some
+		// left at the end, return the unused portion
+		if (hold_p_mem_node && temp_resources.p_mem_head) {
+			p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head),
+													  &hold_p_mem_node, 0x100000);
+
+			// Check if we were able to split something off
+			if (p_mem_node) {
+				hold_p_mem_node->base = p_mem_node->base + p_mem_node->length;
+
+				temp_word = (hold_p_mem_node->base) >> 16;
+				pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+
+				return_resource(&(resources->p_mem_head), p_mem_node);
+			}
+
+			p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000);
+
+			// Check if we were able to split something off
+			if (p_mem_node) {
+				// First use the temporary node to store information for the board
+				hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base;
+
+				// If we used any, add it to the board's list
+				if (hold_p_mem_node->length) {
+					hold_p_mem_node->next = func->p_mem_head;
+					func->p_mem_head = hold_p_mem_node;
+
+					temp_word = (p_mem_node->base - 1) >> 16;
+					pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+
+					return_resource(&(resources->p_mem_head), p_mem_node);
+				} else {
+					// it doesn't need any PMem
+					temp_word = 0x0000;
+					pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+
+					return_resource(&(resources->p_mem_head), p_mem_node);
+					kfree(hold_p_mem_node);
+				}
+			} else {
+				// it used the most of the range
+				hold_p_mem_node->next = func->p_mem_head;
+				func->p_mem_head = hold_p_mem_node;
+			}
+		} else if (hold_p_mem_node) {
+			// it used the whole range
+			hold_p_mem_node->next = func->p_mem_head;
+			func->p_mem_head = hold_p_mem_node;
+		}
+		// We should be configuring an IRQ and the bridge's base address
+		// registers if it needs them.  Although we have never seen such
+		// a device
+
+		// enable card
+		command = 0x0157;	// = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |  PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR
+		pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_COMMAND, command);
+
+		// set Bridge Control Register
+		command = 0x07;		// = PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_NO_ISA
+		pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
+	} else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
+		// Standard device
+		pci_bus_read_config_byte(ctrl->pci_bus, devfn, 0x0B, &class_code);
+
+		if (class_code == PCI_BASE_CLASS_DISPLAY) {
+			// Display (video) adapter (not supported)
+			return(DEVICE_TYPE_NOT_SUPPORTED);
+		}
+		// Figure out IO and memory needs
+		for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
+			temp_register = 0xFFFFFFFF;
+
+			dbg("%s -->CND: devfn=%x, offset=%d\n",__FUNCTION__, devfn, cloop);
+			pci_bus_write_config_dword(ctrl->pci_bus, devfn, cloop, temp_register);
+			pci_bus_read_config_dword(ctrl->pci_bus, devfn, cloop, &temp_register);
+			dbg("%s -->CND: base = 0x%x\n",__FUNCTION__, temp_register);
+
+			if (temp_register) {	  // If this register is implemented
+				if ((temp_register & 0x03L) == 0x01) {
+					// Map IO
+
+					// set base = amount of IO space
+					base = temp_register & 0xFFFFFFFC;
+					base = ~base + 1;
+
+					dbg("%s -->CND:      length = 0x%x\n",__FUNCTION__, base);
+					io_node = get_io_resource(&(resources->io_head), base);
+					dbg("%s -->Got io_node start = %8.8x, length = %8.8x next (%p)\n",__FUNCTION__,
+						io_node->base, io_node->length, io_node->next);
+					dbg("%s -->func (%p) io_head (%p)\n",__FUNCTION__, func, func->io_head);
+
+					// allocate the resource to the board
+					if (io_node) {
+						base = io_node->base;
+
+						io_node->next = func->io_head;
+						func->io_head = io_node;
+					} else
+						return -ENOMEM;
+				} else if ((temp_register & 0x0BL) == 0x08) {
+					// Map prefetchable memory
+					base = temp_register & 0xFFFFFFF0;
+					base = ~base + 1;
+
+					dbg("%s -->CND:      length = 0x%x\n",__FUNCTION__, base);
+					p_mem_node = get_resource(&(resources->p_mem_head), base);
+
+					// allocate the resource to the board
+					if (p_mem_node) {
+						base = p_mem_node->base;
+
+						p_mem_node->next = func->p_mem_head;
+						func->p_mem_head = p_mem_node;
+					} else
+						return -ENOMEM;
+				} else if ((temp_register & 0x0BL) == 0x00) {
+					// Map memory
+					base = temp_register & 0xFFFFFFF0;
+					base = ~base + 1;
+
+					dbg("%s -->CND:      length = 0x%x\n",__FUNCTION__, base);
+					mem_node = get_resource(&(resources->mem_head), base);
+
+					// allocate the resource to the board
+					if (mem_node) {
+						base = mem_node->base;
+
+						mem_node->next = func->mem_head;
+						func->mem_head = mem_node;
+					} else
+						return -ENOMEM;
+				} else if ((temp_register & 0x0BL) == 0x04) {
+					// Map memory
+					base = temp_register & 0xFFFFFFF0;
+					base = ~base + 1;
+
+					dbg("%s -->CND:      length = 0x%x\n",__FUNCTION__, base);
+					mem_node = get_resource(&(resources->mem_head), base);
+
+					// allocate the resource to the board
+					if (mem_node) {
+						base = mem_node->base;
+
+						mem_node->next = func->mem_head;
+						func->mem_head = mem_node;
+					} else
+						return -ENOMEM;
+				} else if ((temp_register & 0x0BL) == 0x06) {
+					// Those bits are reserved, we can't handle this
+					return(1);
+				} else {
+					// Requesting space below 1M
+					return(NOT_ENOUGH_RESOURCES);
+				}
+
+				pci_bus_write_config_dword(ctrl->pci_bus, devfn, cloop, base);
+
+				// Check for 64-bit base
+				if ((temp_register & 0x07L) == 0x04) {
+					cloop += 4;
+
+					// Upper 32 bits of address always zero on today's systems
+					// FIXME this is probably not true on Alpha and ia64???
+					base = 0;
+					pci_bus_write_config_dword(ctrl->pci_bus, devfn, cloop, base);
+				}
+			}
+		}		// End of base register loop
+
+		// Figure out which interrupt pin this function uses
+		pci_bus_read_config_byte(ctrl->pci_bus, devfn, PCI_INTERRUPT_PIN, &temp_byte);
+		dbg("%s temp_byte for interrupt pin = %x", __FUNCTION__, temp_byte);
+		// If this function needs an interrupt and we are behind a bridge
+		// and the pin is tied to something that's already mapped,
+		// set this one the same
+		if (temp_byte && resources->irqs &&
+			(resources->irqs->valid_INT &
+			 (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) {
+			// We have to share with something already set up
+			IRQ = resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03];
+			dbg("%s We're sharing the IRQ from some other device = %02x", __FUNCTION__, IRQ);
+		} else {
+			// Program IRQ based on card type
+			pci_bus_read_config_byte(ctrl->pci_bus, devfn, 0x0B, &class_code);
+			if (class_code == PCI_BASE_CLASS_STORAGE) {
+				dbg("%s We're sharing the disk IRQ (maybe)", __FUNCTION__);
+				IRQ = amdshpc_disk_irq;
+			} else {
+				dbg("%s We're sharing the NIC IRQ (maybe)", __FUNCTION__);
+				IRQ = amdshpc_nic_irq;
+			}
+		}
+
+		// IRQ Line
+		pci_bus_write_config_byte(ctrl->pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ);
+		if (!behind_bridge) {
+//			rc = amdshpc_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ);
+//			rc = amdshpc_set_irq(func->bus, func->device, temp_byte + 20, IRQ);
+			rc = 0;
+			if (rc)
+				return 1;
+		} else {
+			//TBD - this code may also belong in the other clause of this If statement
+			resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03] = IRQ;
+			resources->irqs->valid_INT |= 0x01 << (temp_byte + resources->irqs->barber_pole - 1) & 0x03;
+		}
+
+		// Latency Timer
+		temp_byte = 0x40;
+		pci_bus_write_config_byte(ctrl->pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
+
+		// Cache Line size
+		temp_byte = 0x08;
+		pci_bus_write_config_byte(ctrl->pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
+
+		// disable ROM base Address
+		temp_dword = 0x00L;
+		pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_ROM_ADDRESS, temp_dword);
+
+		// enable card
+		temp_word = 0x0157;	// = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |  PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR
+		pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_COMMAND, temp_word);
+	}			// End of Not-A-Bridge else
+	else {
+		// It's some strange type of PCI adapter (Cardbus?)
+		return DEVICE_TYPE_NOT_SUPPORTED;
+	}
+
+	func->configured = 1;
+
+	return 0;
+}
+
+int amdshpc_configure_device (struct controller * ctrl, struct pci_func* func)
+{
+	unsigned char bus;
+	struct pci_dev dev0;
+	struct pci_bus *child;
+	int num;
+
+	memset(&dev0, 0, sizeof(struct pci_dev));
+	dbg("%s", __FUNCTION__);
+
+	if (func->pci_dev == NULL)
+		func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
+
+	//Still NULL ? Well then scan for it !
+	if (func->pci_dev == NULL) {
+		num = pci_scan_slot(ctrl->pci_dev->bus, PCI_DEVFN(func->device, func->function));
+		if (num)
+			pci_bus_add_devices(ctrl->pci_dev->bus);
+
+		func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
+		if (func->pci_dev == NULL) {
+			dbg("ERROR: pci_dev still null\n");
+			return 0;
+		}
+	}
+
+	if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+		pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus);
+		child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus);
+		pci_do_scan_bus(child);
+
+	}
+
+	return 0;
+}
+
+
+int amdshpc_unconfigure_device(struct pci_func* func)
+{
+	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)
+			pci_remove_bus_device(temp);
+	}
+	return 0;
+}
+
+/*
+static int PCI_RefinedAccessConfig(struct pci_ops *ops, u8 bus, u8 device, u8 function, u8 offset, u32 *value)
+{
+	u32 vendID = 0;
+
+	dbg("%s", __FUNCTION__);
+	if (pci_read_config_dword_nodev (ops, bus, device, function, PCI_VENDOR_ID, &vendID) == -1)
+		return -1;
+	if (vendID == 0xffffffff)
+		return -1;
+	return pci_read_config_dword_nodev (ops, bus, device, function, offset, value);
+}
+
+
+//
+// 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)
+{
+	u8 tdevice;
+	u32 work;
+	u8 tbus;
+
+	dbg("%s", __FUNCTION__);
+	for (tdevice = 0; tdevice < 0x100; tdevice++) {
+		//Scan for access first
+		if (PCI_RefinedAccessConfig(ctrl->pci_ops, bus_num, tdevice >> 3, tdevice & 0x7, 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 ?
+		if ((work >> 8) != PCI_TO_PCI_BRIDGE_CLASS) {
+			*dev_num = tdevice;
+			dbg("found it !\n");
+			return 0;
+		}
+	}
+	for (tdevice = 0; tdevice < 0x100; tdevice++) {
+		//Scan for access first
+		if (PCI_RefinedAccessConfig(ctrl->pci_ops, bus_num, tdevice >> 3, tdevice & 0x7, 0x08, &work) == -1)
+			continue;
+		dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice);
+		//Yep we got one. bridge ?
+		if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
+			pci_read_config_byte_nodev (ctrl->pci_ops, tbus, tdevice, 0, PCI_SECONDARY_BUS, &tbus);
+			dbg("Recurse on bus_num %d tdevice %d\n", tbus, tdevice);
+			if (PCI_ScanBusNonBridge(tbus, tdevice) == 0)
+				return 0;
+		}
+	}
+
+	return -1;
+}
+
+static int PCI_GetBusDevHelper(struct controller  *ctrl, u8 *bus_num, u8 *dev_num, u8 slot, u8 nobridge)
+{
+	struct irq_routing_table *PCIIRQRoutingInfoLength;
+	long len;
+	long loop;
+	u32 work;
+
+	u8 tbus, tdevice, tslot;
+
+	PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table();
+
+	len = (PCIIRQRoutingInfoLength->size -
+	       sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
+	dbg("%s  len = %d",__FUNCTION__, (int)len);
+	// Make sure I got at least one entry
+	if (len == 0) {
+		if (PCIIRQRoutingInfoLength != NULL)
+			kfree(PCIIRQRoutingInfoLength );
+		return -1;
+	}
+
+	for (loop = 0; loop < len; ++loop) {
+		tbus = PCIIRQRoutingInfoLength->slots[loop].bus;
+		tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn;
+		tslot = PCIIRQRoutingInfoLength->slots[loop].slot;
+		dbg("%s  tbus = %02Xh  tdevice = %02Xh  device = %02Xh function = %d  tslot = %d",__FUNCTION__,
+							tbus, tdevice, tdevice >>3, tdevice & 0x7, tslot);
+		if (tslot == slot) {
+			*bus_num = tbus;
+			*dev_num = tdevice;
+			pci_read_config_dword_nodev (ctrl->pci_ops, *bus_num, *dev_num >> 3, *dev_num & 0x7, PCI_VENDOR_ID, &work);
+			if (!nobridge || (work == 0xffffffff)) {
+				if (PCIIRQRoutingInfoLength != NULL)
+					dbg("%s PCIIRQRoutingInfoLength != NULL  returning 0",__FUNCTION__);
+					kfree(PCIIRQRoutingInfoLength );
+				return 0;
+			}
+
+			dbg("bus_num %d dev_num %d func_num %d\n", *bus_num, *dev_num >> 3, *dev_num & 0x7);
+			pci_read_config_dword_nodev (ctrl->pci_ops, *bus_num, *dev_num >> 3, *dev_num & 0x7, 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_read_config_byte_nodev (ctrl->pci_ops, *bus_num, *dev_num >> 3, *dev_num & 0x7, 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 (PCIIRQRoutingInfoLength != NULL)
+		kfree(PCIIRQRoutingInfoLength );
+	return -1;
+}
+
+
+int amdshpc_get_bus_dev (struct controller  *ctrl, u8 * bus_num, u8 * dev_num, u8 slot)
+{
+	dbg("%s", __FUNCTION__);
+	return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0);	//plain (bridges allowed)
+}
+*/
+
+/* More PCI configuration routines; this time centered around hotplug controller */
+
+
+/*
+ * amdshpc_save_slot_config
+ *
+ * Saves configuration info for all PCI devices in a given slot
+ * including subordinate busses.
+ *
+ * returns 0 if success
+ */
+int amdshpc_save_slot_config (struct controller  *ctrl, struct pci_func * new_slot)
+{
+	long rc;
+	u8 class_code;
+	u8 header_type;
+	u32 ID;
+	u8 secondary_bus;
+	int sub_bus;
+	int max_functions;
+	int function;
+	int cloop = 0;
+	int stop_it;
+
+	ID = 0xFFFFFFFF;
+
+	dbg("%s", __FUNCTION__);
+	pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID);
+
+	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);
+
+		if (header_type & 0x80)	// Multi-function device
+			max_functions = 8;
+		else
+			max_functions = 1;
+
+		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);
+
+				sub_bus = (int) secondary_bus;
+
+				// Save the config headers for the secondary bus.
+				rc = amdshpc_save_config(ctrl, sub_bus, 0);
+
+				if (rc)
+					return(rc);
+
+			}	// 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]));
+			}
+
+			function++;
+
+			stop_it = 0;
+
+			//  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);
+
+				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);
+
+					stop_it++;
+				}
+			}
+
+		} while (function < max_functions);
+	}			// End of IF (device in slot?)
+	else {
+		return(2);
+	}
+
+	return(0);
+}
+
+
+/*
+ * amdshpc_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 amdshpc_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;
+
+	dbg("%s", __FUNCTION__);
+	func = amdshpc_slot_find(func->bus, func->device, index++);
+
+	while (func != NULL) {
+		int devfn = PCI_DEVFN(func->device, func->function);
+
+		// Check for Bridge
+		pci_bus_read_config_byte(ctrl->pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+
+		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+			// PCI-PCI Bridge
+			pci_bus_read_config_byte(ctrl->pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
+
+			sub_bus = (int) secondary_bus;
+
+			next = amdshpc_slot_list[sub_bus];
+
+			while (next != NULL) {
+				rc = amdshpc_save_base_addr_length(ctrl, next);
+
+				if (rc)
+					return(rc);
+
+				next = next->next;
+			}
+
+			//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(ctrl->pci_bus, devfn, cloop, temp_register);
+				pci_bus_read_config_dword(ctrl->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(ctrl->pci_bus, devfn, cloop, temp_register);
+				pci_bus_read_config_dword(ctrl->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 = amdshpc_slot_find(func->bus, func->device, index++);
+	}
+
+	return(0);
+}
+
+
+/*
+ * amdshpc_save_used_resources
+ *
+ * Stores used resource information for existing boards.  this is
+ * for boards that were in the system when this driver was loaded.
+ * this function is for hot plug ADD
+ *
+ * returns 0 if success
+ */
+int amdshpc_save_used_resources (struct controller  *ctrl, struct pci_func * func)
+{
+	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;
+	u32 temp_register;
+	u32 save_base;
+	u32 base;
+	int index = 0;
+	struct pci_resource *mem_node;
+	struct pci_resource *p_mem_node;
+	struct pci_resource *io_node;
+	struct pci_resource *bus_node;
+
+	dbg("%s", __FUNCTION__);
+	func = amdshpc_slot_find(func->bus, func->device, index++);
+
+	while ((func != NULL) && func->is_a_board) {
+		int devfn = PCI_DEVFN(func->device, func->function);
+
+		// Save the command register
+		pci_bus_read_config_word(ctrl->pci_bus, devfn, PCI_COMMAND, &save_command);
+
+		// disable card
+		command = 0x00;
+		pci_bus_write_config_word(ctrl->pci_bus, devfn, PCI_COMMAND, command);
+
+		// Check for Bridge
+		pci_bus_read_config_byte(ctrl->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(ctrl->pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
+			pci_bus_read_config_byte(ctrl->pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
+			pci_bus_read_config_byte(ctrl->pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);
+
+			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 = 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(ctrl->pci_bus, devfn, PCI_IO_BASE, &b_base);
+			pci_bus_read_config_byte(ctrl->pci_bus, devfn, PCI_IO_LIMIT, &b_length);
+
+			if ((b_base <= b_length) && (save_command & 0x01)) {
+				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->next = func->io_head;
+				func->io_head = io_node;
+			}
+			// Save memory base and Limit registers
+			pci_bus_read_config_word(ctrl->pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
+			pci_bus_read_config_word(ctrl->pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
+
+			if ((w_base <= w_length) && (save_command & 0x02)) {
+				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->next = func->mem_head;
+				func->mem_head = mem_node;
+			}
+			// Save prefetchable memory base and Limit registers
+			pci_bus_read_config_word(ctrl->pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
+			pci_bus_read_config_word(ctrl->pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
+
+			if ((w_base <= w_length) && (save_command & 0x02)) {
+				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->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) {
+				pci_bus_read_config_dword(ctrl->pci_bus, devfn, cloop, &save_base);
+
+				temp_register = 0xFFFFFFFF;
+				pci_bus_write_config_dword(ctrl->pci_bus, devfn, cloop, temp_register);
+				pci_bus_read_config_dword(ctrl->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 & (~0x03L);
+						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 if ((header_type & 0x7F) == 0x00) {	  // Standard header
+			// Figure out IO and memory base lengths
+			for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
+				pci_bus_read_config_dword(ctrl->pci_bus, devfn, cloop, &save_base);
+
+				temp_register = 0xFFFFFFFF;
+				pci_bus_write_config_dword(ctrl->pci_bus, devfn, cloop, temp_register);
+				pci_bus_read_config_dword(ctrl->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 = amdshpc_slot_find(func->bus, func->device, index++);
+	}
+
+	return(0);
+}
+
+
+/*
+ * amdshpc_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 amdshpc_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;
+
+	dbg("%s", __FUNCTION__);
+	func = amdshpc_slot_find(func->bus, func->device, index++);
+
+	while (func != NULL) {
+		int 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(ctrl->pci_bus, devfn, cloop, func->config_space[cloop >> 2]);
+		}
+
+		pci_bus_read_config_byte(ctrl->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(ctrl->pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
+
+			sub_bus = (int) secondary_bus;
+
+			next = amdshpc_slot_list[sub_bus];
+
+			while (next != NULL) {
+				rc = amdshpc_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(ctrl->pci_bus, devfn, cloop, &temp);
+				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]);
+					return 1;
+				}
+			}
+		}
+
+		func->configured = 1;
+
+		func = amdshpc_slot_find(func->bus, func->device, index++);
+	}
+
+	return 0;
+}
+
+
+/*
+ * amdshpc_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 amdshpc_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;
+
+	dbg("%s", __FUNCTION__);
+	if (!func->is_a_board)
+		return(ADD_NOT_SUPPORTED);
+
+	func = amdshpc_slot_find(func->bus, func->device, index++);
+
+	while (func != NULL) {
+		int devfn = PCI_DEVFN(func->device, func->function);
+
+		pci_bus_read_config_dword(ctrl->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(ctrl->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(ctrl->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(ctrl->pci_bus, devfn, PCI_PRIMARY_BUS, temp_register);
+
+			secondary_bus = (temp_register >> 8) & 0xFF;
+
+			next = amdshpc_slot_list[secondary_bus];
+
+			while (next != NULL) {
+				rc = amdshpc_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(ctrl->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(ctrl->pci_bus, devfn, cloop, temp_register);
+				pci_bus_read_config_dword(ctrl->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;
+				}
+
+				// 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);
+		}
+
+		// Get the next function
+		func = amdshpc_slot_find(func->bus, func->device, index++);
+	}
+
+	return(0);
+}
+
+
+
+static int update_slot_info (struct controller  *ctrl, struct slot *slot)
+{
+//	TO_DO_amd_update_slot_info();
+	dbg("%s   THIS FUNCTION IS STUBBED OUT!!!!!!!!!!!",__FUNCTION__);
+	return 0;
+	/*	struct hotplug_slot_info *info;
+	char buffer[SLOT_NAME_SIZE];
+	int result;
+
+	info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	make_slot_name (&buffer[0], SLOT_NAME_SIZE, slot);
+	info->power_status = get_slot_enabled(ctrl, slot);
+	info->attention_status = cpq_get_attention_status(ctrl, slot);
+	info->latch_status = cpq_get_latch_status(ctrl, slot);
+	info->adapter_status = get_presence_status(ctrl, slot);
+	result = pci_hp_change_slot_info(buffer, info);
+	kfree (info);
+	return result;
+*/
+}
+
+
+/*
+ * slot_remove - Removes a node from the linked list of slots.
+ * @old_slot: slot to remove
+ *
+ * Returns 0 if successful, !0 otherwise.
+ */
+static int slot_remove(struct pci_func * old_slot)
+{
+	struct pci_func *next;
+
+	dbg("%s", __FUNCTION__);
+	if (old_slot == NULL)
+		return(1);
+
+	next = amdshpc_slot_list[old_slot->bus];
+
+	if (next == NULL) {
+		return(1);
+	}
+
+	if (next == old_slot) {
+		amdshpc_slot_list[old_slot->bus] = old_slot->next;
+		amdshpc_destroy_board_resources(old_slot);
+		kfree(old_slot);
+		return(0);
+	}
+
+	while ((next->next != old_slot) && (next->next != NULL)) {
+		next = next->next;
+	}
+
+	if (next->next == old_slot) {
+		next->next = old_slot->next;
+		amdshpc_destroy_board_resources(old_slot);
+		kfree(old_slot);
+		return(0);
+	} else
+		return(2);
+}
+
+// DJZ: I don't think is_bridge will work as is.
+//FIXME
+static int is_bridge(struct pci_func * func)
+{
+	dbg("%s", __FUNCTION__);
+	// Check the header type
+	if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)
+		return 1;
+	else
+		return 0;
+}
+
+
+/**
+ * bridge_slot_remove - Removes a node from the linked list of slots.
+ * @bridge: bridge to remove
+ *
+ * Returns 0 if successful, !0 otherwise.
+ */
+static int bridge_slot_remove(struct pci_func *bridge)
+{
+	u8 subordinateBus, secondaryBus;
+	u8 tempBus;
+	struct pci_func *next;
+
+	dbg("%s", __FUNCTION__);
+	if (bridge == NULL)
+		return(1);
+
+	secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF;
+	subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF;
+
+	for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
+		next = amdshpc_slot_list[tempBus];
+
+		while (!slot_remove(next)) {
+			next = amdshpc_slot_list[tempBus];
+		}
+	}
+
+	next = amdshpc_slot_list[bridge->bus];
+
+	if (next == NULL) {
+		return(1);
+	}
+
+	if (next == bridge) {
+		amdshpc_slot_list[bridge->bus] = bridge->next;
+		kfree(bridge);
+		return(0);
+	}
+
+	while ((next->next != bridge) && (next->next != NULL)) {
+		next = next->next;
+	}
+
+	if (next->next == bridge) {
+		next->next = bridge->next;
+		kfree(bridge);
+		return(0);
+	} else
+		return(2);
+}
+
+
