ChangeSet 1.1254.4.7, 2003/06/03 20:54:30-07:00, greg@kroah.com

PCI Hotplug: move drivers/hotplug/* to drivers/pci/hotplug/*
  
This will let include/linux/pci.h get smaller, and is what I should 
have done in the first place 2 years ago...


 drivers/hotplug/Kconfig                 |  120 -
 drivers/hotplug/Makefile                |   44 
 drivers/hotplug/acpiphp.h               |  262 --
 drivers/hotplug/acpiphp_core.c          |  505 -----
 drivers/hotplug/acpiphp_glue.c          | 1335 -------------
 drivers/hotplug/acpiphp_pci.c           |  510 -----
 drivers/hotplug/acpiphp_res.c           |  699 -------
 drivers/hotplug/cpci_hotplug.h          |  100 -
 drivers/hotplug/cpci_hotplug_core.c     |  919 ---------
 drivers/hotplug/cpci_hotplug_pci.c      |  647 ------
 drivers/hotplug/cpcihp_generic.c        |  290 ---
 drivers/hotplug/cpcihp_zt5550.c         |  306 ---
 drivers/hotplug/cpcihp_zt5550.h         |   79 
 drivers/hotplug/cpqphp.h                |  912 ---------
 drivers/hotplug/cpqphp_core.c           | 1541 ---------------
 drivers/hotplug/cpqphp_ctrl.c           | 3084 --------------------------------
 drivers/hotplug/cpqphp_nvram.c          |  667 ------
 drivers/hotplug/cpqphp_nvram.h          |   57 
 drivers/hotplug/cpqphp_pci.c            | 1548 ----------------
 drivers/hotplug/cpqphp_sysfs.c          |  143 -
 drivers/hotplug/ibmphp.h                |  772 --------
 drivers/hotplug/ibmphp_core.c           | 1417 --------------
 drivers/hotplug/ibmphp_ebda.c           | 1228 ------------
 drivers/hotplug/ibmphp_hpc.c            | 1228 ------------
 drivers/hotplug/ibmphp_pci.c            | 1758 ------------------
 drivers/hotplug/ibmphp_res.c            | 2157 ----------------------
 drivers/hotplug/pci_hotplug.h           |  146 -
 drivers/hotplug/pci_hotplug_core.c      |  666 ------
 drivers/hotplug/pcihp_skeleton.c        |  432 ----
 arch/i386/Kconfig                       |    2 
 arch/ia64/Kconfig                       |    2 
 arch/m68knommu/Kconfig                  |    2 
 arch/ppc64/Kconfig                      |    2 
 arch/v850/Kconfig                       |    2 
 arch/x86_64/Kconfig                     |    2 
 drivers/Makefile                        |    1 
 drivers/pci/Makefile                    |    3 
 drivers/pci/hotplug/Kconfig             |  120 +
 drivers/pci/hotplug/Makefile            |   44 
 drivers/pci/hotplug/acpiphp.h           |  262 ++
 drivers/pci/hotplug/acpiphp_core.c      |  505 +++++
 drivers/pci/hotplug/acpiphp_glue.c      | 1335 +++++++++++++
 drivers/pci/hotplug/acpiphp_pci.c       |  510 +++++
 drivers/pci/hotplug/acpiphp_res.c       |  699 +++++++
 drivers/pci/hotplug/cpci_hotplug.h      |  100 +
 drivers/pci/hotplug/cpci_hotplug_core.c |  919 +++++++++
 drivers/pci/hotplug/cpci_hotplug_pci.c  |  647 ++++++
 drivers/pci/hotplug/cpcihp_generic.c    |  290 +++
 drivers/pci/hotplug/cpcihp_zt5550.c     |  306 +++
 drivers/pci/hotplug/cpcihp_zt5550.h     |   79 
 drivers/pci/hotplug/cpqphp.h            |  912 +++++++++
 drivers/pci/hotplug/cpqphp_core.c       | 1541 +++++++++++++++
 drivers/pci/hotplug/cpqphp_ctrl.c       | 3084 ++++++++++++++++++++++++++++++++
 drivers/pci/hotplug/cpqphp_nvram.c      |  667 ++++++
 drivers/pci/hotplug/cpqphp_nvram.h      |   57 
 drivers/pci/hotplug/cpqphp_pci.c        | 1548 ++++++++++++++++
 drivers/pci/hotplug/cpqphp_sysfs.c      |  143 +
 drivers/pci/hotplug/ibmphp.h            |  772 ++++++++
 drivers/pci/hotplug/ibmphp_core.c       | 1417 ++++++++++++++
 drivers/pci/hotplug/ibmphp_ebda.c       | 1228 ++++++++++++
 drivers/pci/hotplug/ibmphp_hpc.c        | 1228 ++++++++++++
 drivers/pci/hotplug/ibmphp_pci.c        | 1758 ++++++++++++++++++
 drivers/pci/hotplug/ibmphp_res.c        | 2157 ++++++++++++++++++++++
 drivers/pci/hotplug/pci_hotplug.h       |  146 +
 drivers/pci/hotplug/pci_hotplug_core.c  |  666 ++++++
 drivers/pci/hotplug/pcihp_skeleton.c    |  432 ++++
 66 files changed, 23581 insertions(+), 23579 deletions(-)


diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig	Wed Jun  4 18:11:56 2003
+++ b/arch/i386/Kconfig	Wed Jun  4 18:11:56 2003
@@ -1135,7 +1135,7 @@
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/hotplug/Kconfig"
+source "drivers/pci/hotplug/Kconfig"
 
 endmenu
 
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	Wed Jun  4 18:11:56 2003
+++ b/arch/ia64/Kconfig	Wed Jun  4 18:11:56 2003
@@ -563,7 +563,7 @@
 	  agent" (/sbin/hotplug) to load modules and set up software needed
 	  to use devices as you hotplug them.
 
-source "drivers/hotplug/Kconfig"
+source "drivers/pci/hotplug/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
 
diff -Nru a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
--- a/arch/m68knommu/Kconfig	Wed Jun  4 18:11:56 2003
+++ b/arch/m68knommu/Kconfig	Wed Jun  4 18:11:56 2003
@@ -488,7 +488,7 @@
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/hotplug/Kconfig"
+source "drivers/pci/hotplug/Kconfig"
 
 endmenu
 
diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
--- a/arch/ppc64/Kconfig	Wed Jun  4 18:11:56 2003
+++ b/arch/ppc64/Kconfig	Wed Jun  4 18:11:56 2003
@@ -234,7 +234,7 @@
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/hotplug/Kconfig"
+source "drivers/pci/hotplug/Kconfig"
 
 config PROC_DEVICETREE
 	bool "Support for Open Firmware device tree in /proc"
diff -Nru a/arch/v850/Kconfig b/arch/v850/Kconfig
--- a/arch/v850/Kconfig	Wed Jun  4 18:11:56 2003
+++ b/arch/v850/Kconfig	Wed Jun  4 18:11:56 2003
@@ -230,7 +230,7 @@
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/hotplug/Kconfig"
+source "drivers/pci/hotplug/Kconfig"
 
 endmenu
 
diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
--- a/arch/x86_64/Kconfig	Wed Jun  4 18:11:56 2003
+++ b/arch/x86_64/Kconfig	Wed Jun  4 18:11:56 2003
@@ -351,7 +351,7 @@
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/hotplug/Kconfig"
+source "drivers/pci/hotplug/Kconfig"
 
 endmenu
 
diff -Nru a/drivers/Makefile b/drivers/Makefile
--- a/drivers/Makefile	Wed Jun  4 18:11:56 2003
+++ b/drivers/Makefile	Wed Jun  4 18:11:56 2003
@@ -46,7 +46,6 @@
 obj-$(CONFIG_PHONE)		+= telephony/
 obj-$(CONFIG_MD)		+= md/
 obj-$(CONFIG_BT)		+= bluetooth/
-obj-$(CONFIG_HOTPLUG_PCI)	+= hotplug/
 obj-$(CONFIG_ISDN_BOOL)		+= isdn/
 obj-$(CONFIG_MCA)		+= mca/
 obj-$(CONFIG_EISA)		+= eisa/
diff -Nru a/drivers/hotplug/Kconfig b/drivers/hotplug/Kconfig
--- a/drivers/hotplug/Kconfig	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,120 +0,0 @@
-#
-# PCI Hotplug support
-#
-
-menu "PCI Hotplug Support"
-	depends on HOTPLUG
-
-config HOTPLUG_PCI
-	tristate "Support for PCI Hotplug (EXPERIMENTAL)"
-	depends on PCI && EXPERIMENTAL
-	---help---
-	  Say Y here if you have a motherboard with a PCI Hotplug controller.
-	  This allows you to add and remove PCI cards while the machine is
-	  powered up and running.  The file system pcihpfs must be mounted
-	  in order to interact with any PCI Hotplug controllers.
-
-	  This code is also available as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called pci_hotplug. If you want to compile it
-	  as a module, say M here and read <file:Documentation/modules.txt>.
-
-	  When in doubt, say N.
-
-config HOTPLUG_PCI_COMPAQ
-	tristate "Compaq PCI Hotplug driver"
-	depends on HOTPLUG_PCI && X86
-	help
-	  Say Y here if you have a motherboard with a Compaq PCI Hotplug
-	  controller.
-
-	  This code is also available as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called cpqphp. If you want to compile it
-	  as a module, say M here and read <file:Documentation/modules.txt>.
-
-	  When in doubt, say N.
-
-config HOTPLUG_PCI_COMPAQ_NVRAM
-	bool "Save configuration into NVRAM on Compaq servers"
-	depends on HOTPLUG_PCI_COMPAQ
-	help
-	  Say Y here if you have a Compaq server that has a PCI Hotplug
-	  controller.  This will allow the PCI Hotplug driver to store the PCI
-	  system configuration options in NVRAM.
-
-	  When in doubt, say N.
-
-config HOTPLUG_PCI_IBM
-	tristate "IBM PCI Hotplug driver"
-	depends on HOTPLUG_PCI && X86_IO_APIC && X86
-	help
-	  Say Y here if you have a motherboard with a IBM PCI Hotplug
-	  controller.
-
-	  This code is also available as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called cpqphp. If you want to compile it
-	  as a module, say M here and read <file:Documentation/modules.txt>.
-
-	  When in doubt, say N.
-
-config HOTPLUG_PCI_ACPI
-	tristate "ACPI PCI Hotplug driver"
-	depends on ACPI_BUS && HOTPLUG_PCI
-	help
-	  Say Y here if you have a system that supports PCI Hotplug using
-	  ACPI.
-
-	  This code is also available as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called acpiphp. If you want to compile it
-	  as a module, say M here and read <file:Documentation/modules.txt>.
-
-	  When in doubt, say N.
-
-config HOTPLUG_PCI_CPCI
-	tristate "CompactPCI Hotplug driver"
-	depends on HOTPLUG_PCI
-	help
-	  Say Y here if you have a CompactPCI system card with CompactPCI
-	  hotswap support per the PICMG 2.1 specification.
-
-	  This code is also available as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called cpci_hotplug. If you want to compile it
-	  as a module, say M here and read <file:Documentation/modules.txt>.
-
-	  When in doubt, say N.
-
-config HOTPLUG_PCI_CPCI_ZT5550
-	tristate "Ziatech ZT5550 CompactPCI Hotplug driver"
-	depends on HOTPLUG_PCI_CPCI && X86
-	help
-	  Say Y here if you have an Performance Technologies (formerly Intel,
-          formerly just Ziatech) Ziatech ZT5550 CompactPCI system card.
-
-	  This code is also available as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called cpcihp_zt5550. If you want to compile it
-	  as a module, say M here and read <file:Documentation/modules.txt>.
-
-	  When in doubt, say N.
-
-config HOTPLUG_PCI_CPCI_GENERIC
-	tristate "Generic port I/O CompactPCI Hotplug driver"
-	depends on HOTPLUG_PCI_CPCI && X86
-	help
-	  Say Y here if you have a CompactPCI system card that exposes the #ENUM
-	  hotswap signal as a bit in a system register that can be read through
-	  standard port I/O.
-
-	  This code is also available as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called cpcihp_generic. If you want to compile it
-	  as a module, say M here and read <file:Documentation/modules.txt>.
-
-	  When in doubt, say N.
-
-endmenu
-
diff -Nru a/drivers/hotplug/Makefile b/drivers/hotplug/Makefile
--- a/drivers/hotplug/Makefile	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,44 +0,0 @@
-#
-# Makefile for the Linux kernel pci hotplug controller drivers.
-#
-
-obj-$(CONFIG_HOTPLUG_PCI)		+= pci_hotplug.o
-obj-$(CONFIG_HOTPLUG_PCI_COMPAQ)	+= cpqphp.o
-obj-$(CONFIG_HOTPLUG_PCI_IBM)		+= ibmphp.o
-obj-$(CONFIG_HOTPLUG_PCI_ACPI)		+= acpiphp.o
-obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550)	+= cpcihp_zt5550.o
-obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC)	+= cpcihp_generic.o
-
-pci_hotplug-objs	:=	pci_hotplug_core.o
-
-ifdef CONFIG_HOTPLUG_PCI_CPCI
-pci_hotplug-objs	+=	cpci_hotplug_core.o	\
-				cpci_hotplug_pci.o
-endif
-
-cpqphp-objs		:=	cpqphp_core.o	\
-				cpqphp_ctrl.o	\
-				cpqphp_sysfs.o	\
-				cpqphp_pci.o
-
-ibmphp-objs		:=	ibmphp_core.o	\
-				ibmphp_ebda.o	\
-				ibmphp_pci.o	\
-				ibmphp_res.o	\
-				ibmphp_hpc.o
-
-acpiphp-objs		:=	acpiphp_core.o	\
-				acpiphp_glue.o	\
-				acpiphp_pci.o	\
-				acpiphp_res.o
-
-ifdef CONFIG_HOTPLUG_PCI_ACPI
-  EXTRA_CFLAGS  += -D_LINUX -I$(TOPDIR)/drivers/acpi
-  ifdef CONFIG_ACPI_DEBUG
-    EXTRA_CFLAGS += -DACPI_DEBUG_OUTPUT
-  endif
-endif
-
-ifeq ($(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM),y)
-	cpqphp-objs += cpqphp_nvram.o
-endif
diff -Nru a/drivers/hotplug/acpiphp.h b/drivers/hotplug/acpiphp.h
--- a/drivers/hotplug/acpiphp.h	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,262 +0,0 @@
-/*
- * ACPI PCI Hot Plug Controller Driver
- *
- * Copyright (c) 1995,2001 Compaq Computer Corporation
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001 IBM Corp.
- * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
- * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com)
- * Copyright (c) 2002 NEC Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <gregkh@us.ibm.com>,
- *		    <h-aono@ap.jp.nec.com>,
- *		    <t-kouchi@cq.jp.nec.com>
- *
- */
-
-#ifndef _ACPIPHP_H
-#define _ACPIPHP_H
-
-#include <linux/acpi.h>
-#include "pci_hotplug.h"
-
-#define dbg(format, arg...)					\
-	do {							\
-		if (acpiphp_debug)				\
-			printk(KERN_DEBUG "%s: " format,	\
-				MY_NAME , ## arg); 		\
-	} while (0)
-#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
-#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
-
-#define SLOT_MAGIC	0x67267322
-/* name size which is used for entries in pcihpfs */
-#define SLOT_NAME_SIZE	32		/* ACPI{_SUN}-{BUS}:{DEV} */
-
-struct acpiphp_bridge;
-struct acpiphp_slot;
-struct pci_resource;
-
-/*
- * struct slot - slot information for each *physical* slot
- */
-struct slot {
-	u32 magic;
-	u8 number;
-	struct hotplug_slot	*hotplug_slot;
-	struct list_head	slot_list;
-
-	struct acpiphp_slot	*acpi_slot;
-};
-
-/*
- * struct pci_resource - describes pci resource (mem, pfmem, io, bus)
- */
-struct pci_resource {
-	struct pci_resource * next;
-	u64 base;
-	u32 length;
-};
-
-/**
- * struct hpp_param - ACPI 2.0 _HPP Hot Plug Parameters
- * @cache_line_size in DWORD
- * @latency_timer in PCI clock
- * @enable_SERR 0 or 1
- * @enable_PERR 0 or 1
- */
-struct hpp_param {
-	u8 cache_line_size;
-	u8 latency_timer;
-	u8 enable_SERR;
-	u8 enable_PERR;
-};
-
-
-/**
- * struct acpiphp_bridge - PCI bridge information
- *
- * for each bridge device in ACPI namespace
- */
-struct acpiphp_bridge {
-	struct list_head list;
-	acpi_handle handle;
-	struct acpiphp_slot *slots;
-	int type;
-	int nr_slots;
-
-	u8 seg;
-	u8 bus;
-	u8 sub;
-
-	u32 flags;
-
-	/* This bus (host bridge) or Secondary bus (PCI-to-PCI bridge) */
-	struct pci_bus *pci_bus;
-
-	/* PCI-to-PCI bridge device */
-	struct pci_dev *pci_dev;
-
-	/* ACPI 2.0 _HPP parameters */
-	struct hpp_param hpp;
-
-	spinlock_t res_lock;
-
-	/* available resources on this bus */
-	struct pci_resource *mem_head;
-	struct pci_resource *p_mem_head;
-	struct pci_resource *io_head;
-	struct pci_resource *bus_head;
-};
-
-
-/**
- * struct acpiphp_slot - PCI slot information
- *
- * PCI slot information for each *physical* PCI slot
- */
-struct acpiphp_slot {
-	struct acpiphp_slot *next;
-	struct acpiphp_bridge *bridge;	/* parent */
-	struct list_head funcs;		/* one slot may have different
-					   objects (i.e. for each function) */
-	struct semaphore crit_sect;
-
-	u32		id;		/* slot id (serial #) for hotplug core */
-	u8		device;		/* pci device# */
-
-	u32		sun;		/* ACPI _SUN (slot unique number) */
-	u32		slotno;		/* slot number relative to bridge */
-	u32		flags;		/* see below */
-};
-
-
-/**
- * struct acpiphp_func - PCI function information
- *
- * PCI function information for each object in ACPI namespace
- * typically 8 objects per slot (i.e. for each PCI function)
- */
-struct acpiphp_func {
-	struct acpiphp_slot *slot;	/* parent */
-
-	struct list_head sibling;
-	struct pci_dev *pci_dev;
-
-	acpi_handle	handle;
-
-	u8		function;	/* pci function# */
-	u32		flags;		/* see below */
-
-	/* resources used for this function */
-	struct pci_resource *mem_head;
-	struct pci_resource *p_mem_head;
-	struct pci_resource *io_head;
-	struct pci_resource *bus_head;
-};
-
-
-/* PCI bus bridge HID */
-#define ACPI_PCI_HOST_HID		"PNP0A03"
-
-/* PCI BRIDGE type */
-#define BRIDGE_TYPE_HOST		0
-#define BRIDGE_TYPE_P2P			1
-
-/* ACPI _STA method value (ignore bit 4; battery present) */
-#define ACPI_STA_PRESENT		(0x00000001)
-#define ACPI_STA_ENABLED		(0x00000002)
-#define ACPI_STA_SHOW_IN_UI		(0x00000004)
-#define ACPI_STA_FUNCTIONING		(0x00000008)
-#define ACPI_STA_ALL			(0x0000000f)
-
-/* bridge flags */
-#define BRIDGE_HAS_STA		(0x00000001)
-#define BRIDGE_HAS_EJ0		(0x00000002)
-#define BRIDGE_HAS_HPP		(0x00000004)
-#define BRIDGE_HAS_PS0		(0x00000010)
-#define BRIDGE_HAS_PS1		(0x00000020)
-#define BRIDGE_HAS_PS2		(0x00000040)
-#define BRIDGE_HAS_PS3		(0x00000080)
-
-/* slot flags */
-
-#define SLOT_POWEREDON		(0x00000001)
-#define SLOT_ENABLED		(0x00000002)
-#define SLOT_MULTIFUNCTION	(x000000004)
-
-/* function flags */
-
-#define FUNC_HAS_STA		(0x00000001)
-#define FUNC_HAS_EJ0		(0x00000002)
-#define FUNC_HAS_PS0		(0x00000010)
-#define FUNC_HAS_PS1		(0x00000020)
-#define FUNC_HAS_PS2		(0x00000040)
-#define FUNC_HAS_PS3		(0x00000080)
-
-/* not yet */
-#define SLOT_SUPPORT_66MHZ	(0x00010000)
-#define SLOT_SUPPORT_100MHZ	(0x00020000)
-#define SLOT_SUPPORT_133MHZ	(0x00040000)
-#define SLOT_SUPPORT_PCIX	(0x00080000)
-
-/* function prototypes */
-
-/* acpiphp_glue.c */
-extern int acpiphp_glue_init (void);
-extern void acpiphp_glue_exit (void);
-extern int acpiphp_get_num_slots (void);
-extern struct acpiphp_slot *get_slot_from_id (int id);
-typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
-extern int acpiphp_for_each_slot (acpiphp_callback fn, void *data);
-
-extern int acpiphp_check_bridge (struct acpiphp_bridge *bridge);
-extern int acpiphp_enable_slot (struct acpiphp_slot *slot);
-extern int acpiphp_disable_slot (struct acpiphp_slot *slot);
-extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot);
-extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot);
-extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
-extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot);
-
-/* acpiphp_pci.c */
-extern struct pci_dev *acpiphp_allocate_pcidev (struct pci_bus *pbus, int dev, int fn);
-extern int acpiphp_configure_slot (struct acpiphp_slot *slot);
-extern int acpiphp_configure_function (struct acpiphp_func *func);
-extern int acpiphp_unconfigure_function (struct acpiphp_func *func);
-extern int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge);
-extern int acpiphp_init_func_resource (struct acpiphp_func *func);
-
-/* acpiphp_res.c */
-extern struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 size);
-extern struct pci_resource *acpiphp_get_max_resource (struct pci_resource **head, u32 size);
-extern struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size);
-extern struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, u64 base, u32 size);
-extern int acpiphp_resource_sort_and_combine (struct pci_resource **head);
-extern struct pci_resource *acpiphp_make_resource (u64 base, u32 length);
-extern void acpiphp_move_resource (struct pci_resource **from, struct pci_resource **to);
-extern void acpiphp_free_resource (struct pci_resource **res);
-extern void acpiphp_dump_resource (struct acpiphp_bridge *bridge); /* debug */
-extern void acpiphp_dump_func_resource (struct acpiphp_func *func); /* debug */
-
-/* variables */
-extern int acpiphp_debug;
-
-#endif /* _ACPIPHP_H */
diff -Nru a/drivers/hotplug/acpiphp_core.c b/drivers/hotplug/acpiphp_core.c
--- a/drivers/hotplug/acpiphp_core.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,505 +0,0 @@
-/*
- * ACPI PCI Hot Plug Controller Driver
- *
- * Copyright (c) 1995,2001 Compaq Computer Corporation
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001 IBM Corp.
- * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
- * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com)
- * Copyright (c) 2002 NEC Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <gregkh@us.ibm.com>,
- *                  <h-aono@ap.jp.nec.com>,
- *		    <t-kouchi@cq.jp.nec.com>
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include "pci_hotplug.h"
-#include "acpiphp.h"
-
-static LIST_HEAD(slot_list);
-
-#if !defined(CONFIG_HOTPLUG_PCI_ACPI_MODULE)
-	#define MY_NAME	"acpiphp"
-#else
-	#define MY_NAME	THIS_MODULE->name
-#endif
-
-static int debug;
-int acpiphp_debug;
-
-/* local variables */
-static int num_slots;
-
-#define DRIVER_VERSION	"0.4"
-#define DRIVER_AUTHOR	"Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-kouchi@cq.jp.nec.com>"
-#define DRIVER_DESC	"ACPI Hot Plug PCI Controller Driver"
-
-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);
-static int get_max_bus_speed	(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value);
-static int get_cur_bus_speed	(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value);
-
-static struct hotplug_slot_ops acpi_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,
-	.get_max_bus_speed	= get_max_bus_speed,
-	.get_cur_bus_speed	= get_cur_bus_speed,
-};
-
-
-/* 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\n", function);
-		return -1;
-	}
-	if (slot->magic != SLOT_MAGIC) {
-		dbg("%s - bad magic number for slot\n", function);
-		return -1;
-	}
-	if (!slot->hotplug_slot) {
-		dbg("%s - slot->hotplug_slot == NULL!\n", 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;
-}
-
-
-/**
- * enable_slot - power on and enable a slot
- * @hotplug_slot: slot to enable
- *
- * Actual tasks are done in acpiphp_enable_slot()
- *
- */
-static int enable_slot (struct hotplug_slot *hotplug_slot)
-{
-	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);
-
-	/* enable the specified slot */
-	retval = acpiphp_enable_slot(slot->acpi_slot);
-
-	return retval;
-}
-
-
-/**
- * disable_slot - disable and power off a slot
- * @hotplug_slot: slot to disable
- *
- * Actual tasks are done in acpiphp_disable_slot()
- *
- */
-static int disable_slot (struct hotplug_slot *hotplug_slot)
-{
-	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);
-
-	/* disable the specified slot */
-	retval = acpiphp_disable_slot(slot->acpi_slot);
-
-	return retval;
-}
-
-
-/**
- * set_attention_status - set attention LED
- *
- * TBD:
- * ACPI doesn't have known method to manipulate
- * attention status LED.
- *
- */
-static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
-{
-	int retval = 0;
-
-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-
-	switch (status) {
-		case 0:
-			/* FIXME turn light off */
-			hotplug_slot->info->attention_status = 0;
-			break;
-
-		case 1:
-		default:
-			/* FIXME turn light on */
-			hotplug_slot->info->attention_status = 1;
-			break;
-	}
-
-	return retval;
-}
-
-
-/**
- * hardware_test - hardware test
- *
- * We have nothing to do for now...
- *
- */
-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\n");
-	retval = -ENODEV;
-
-	return retval;
-}
-
-
-/**
- * get_power_status - get power status of a slot
- * @hotplug_slot: slot to get status
- * @value: pointer to store status
- *
- * Some platforms may not implement _STA method properly.
- * In that case, the value returned may not be reliable.
- *
- */
-static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *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);
-
-	*value = acpiphp_get_power_status(slot->acpi_slot);
-
-	return retval;
-}
-
-
-/**
- * get_attention_status - get attention LED status
- *
- * TBD:
- * ACPI doesn't provide any formal means to access attention LED status.
- *
- */
-static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
-{
-	int retval = 0;
-
-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-
-	*value = hotplug_slot->info->attention_status;
-
-	return retval;
-}
-
-
-/**
- * get_latch_status - get latch status of a slot
- * @hotplug_slot: slot to get status
- * @value: pointer to store status
- *
- * ACPI doesn't provide any formal means to access latch status.
- * Instead, we fake latch status from _STA
- *
- */
-static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *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);
-
-	*value = acpiphp_get_latch_status(slot->acpi_slot);
-
-	return retval;
-}
-
-
-/**
- * get_adapter_status - get adapter status of a slot
- * @hotplug_slot: slot to get status
- * @value: pointer to store status
- *
- * ACPI doesn't provide any formal means to access adapter status.
- * Instead, we fake adapter status from _STA
- *
- */
-static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *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);
-
-	*value = acpiphp_get_adapter_status(slot->acpi_slot);
-
-	return retval;
-}
-
-
-/* return dummy value because ACPI doesn't provide any method... */
-static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
-{
-	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
-
-	if (slot == NULL)
-		return -ENODEV;
-
-	*value = PCI_SPEED_UNKNOWN;
-
-	return 0;
-}
-
-
-/* return dummy value because ACPI doesn't provide any method... */
-static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
-{
-	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
-
-	if (slot == NULL)
-		return -ENODEV;
-
-	*value = PCI_SPEED_UNKNOWN;
-
-	return 0;
-}
-
-
-static int init_acpi (void)
-{
-	int retval;
-
-	/* initialize internal data structure etc. */
-	retval = acpiphp_glue_init();
-
-	/* read initial number of slots */
-	if (!retval) {
-		num_slots = acpiphp_get_num_slots();
-		if (num_slots == 0)
-			retval = -ENODEV;
-	}
-
-	return retval;
-}
-
-
-/**
- * make_slot_name - make a slot name that appears in pcihpfs
- * @slot: slot to name
- *
- */
-static void make_slot_name (struct slot *slot)
-{
-	snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "ACPI%d-%02x:%02x",
-		 slot->acpi_slot->sun,
-		 slot->acpi_slot->bridge->bus,
-		 slot->acpi_slot->device);
-}
-
-/**
- * init_slots - initialize 'struct slot' structures for each slot
- *
- */
-static int init_slots (void)
-{
-	struct slot *slot;
-	int retval = 0;
-	int i;
-
-	for (i = 0; i < num_slots; ++i) {
-		slot = kmalloc(sizeof(struct slot), GFP_KERNEL);
-		if (!slot)
-			return -ENOMEM;
-		memset(slot, 0, sizeof(struct slot));
-
-		slot->hotplug_slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
-		if (!slot->hotplug_slot) {
-			kfree(slot);
-			return -ENOMEM;
-		}
-		memset(slot->hotplug_slot, 0, sizeof(struct hotplug_slot));
-
-		slot->hotplug_slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
-		if (!slot->hotplug_slot->info) {
-			kfree(slot->hotplug_slot);
-			kfree(slot);
-			return -ENOMEM;
-		}
-		memset(slot->hotplug_slot->info, 0, sizeof(struct hotplug_slot_info));
-
-		slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
-		if (!slot->hotplug_slot->name) {
-			kfree(slot->hotplug_slot->info);
-			kfree(slot->hotplug_slot);
-			kfree(slot);
-			return -ENOMEM;
-		}
-
-		slot->magic = SLOT_MAGIC;
-		slot->number = i;
-
-		slot->hotplug_slot->private = slot;
-		slot->hotplug_slot->ops = &acpi_hotplug_slot_ops;
-
-		slot->acpi_slot = get_slot_from_id(i);
-		slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot);
-		slot->hotplug_slot->info->attention_status = acpiphp_get_attention_status(slot->acpi_slot);
-		slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot);
-		slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot);
-
-		make_slot_name(slot);
-
-		retval = pci_hp_register(slot->hotplug_slot);
-		if (retval) {
-			err("pci_hp_register failed with error %d\n", retval);
-			kfree(slot->hotplug_slot->info);
-			kfree(slot->hotplug_slot->name);
-			kfree(slot->hotplug_slot);
-			kfree(slot);
-			return retval;
-		}
-
-		/* add slot to our internal list */
-		list_add(&slot->slot_list, &slot_list);
-		info("Slot [%s] registered\n", slot->hotplug_slot->name);
-	}
-
-	return retval;
-}
-
-
-static void cleanup_slots (void)
-{
-	struct list_head *tmp, *n;
-	struct slot *slot;
-
-	list_for_each_safe (tmp, n, &slot_list) {
-		slot = list_entry(tmp, struct slot, slot_list);
-		list_del(&slot->slot_list);
-		pci_hp_deregister(slot->hotplug_slot);
-		kfree(slot->hotplug_slot->info);
-		kfree(slot->hotplug_slot->name);
-		kfree(slot->hotplug_slot);
-		kfree(slot);
-	}
-
-	return;
-}
-
-
-static int __init acpiphp_init(void)
-{
-	int retval;
-
-	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-
-	acpiphp_debug = debug;
-
-	/* read all the ACPI info from the system */
-	retval = init_acpi();
-	if (retval)
-		return retval;
-
-	retval = init_slots();
-	if (retval)
-		return retval;
-
-	return 0;
-}
-
-
-static void __exit acpiphp_exit(void)
-{
-	cleanup_slots();
-	/* deallocate internal data structures etc. */
-	acpiphp_glue_exit();
-}
-
-module_init(acpiphp_init);
-module_exit(acpiphp_exit);
diff -Nru a/drivers/hotplug/acpiphp_glue.c b/drivers/hotplug/acpiphp_glue.c
--- a/drivers/hotplug/acpiphp_glue.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1335 +0,0 @@
-/*
- * ACPI PCI HotPlug glue functions to ACPI CA subsystem
- *
- * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com)
- * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
- * Copyright (c) 2002 NEC Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <t-kouchi@cq.jp.nec.com>
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <asm/semaphore.h>
-
-#include "pci_hotplug.h"
-#include "acpiphp.h"
-
-static LIST_HEAD(bridge_list);
-
-#define MY_NAME "acpiphp_glue"
-
-static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
-static void handle_hotplug_event_func (acpi_handle, u32, void *);
-
-/*
- * initialization & terminatation routines
- */
-
-/**
- * is_ejectable - determine if a slot is ejectable
- * @handle: handle to acpi namespace
- *
- * Ejectable slot should satisfy at least these conditions:
- *
- *  1. has _ADR method
- *  2. has _EJ0 method
- *
- * optionally
- *
- *  1. has _STA method
- *  2. has _PS0 method
- *  3. has _PS3 method
- *  4. ..
- *
- */
-static int is_ejectable (acpi_handle handle)
-{
-	acpi_status status;
-	acpi_handle tmp;
-
-	status = acpi_get_handle(handle, "_ADR", &tmp);
-	if (ACPI_FAILURE(status)) {
-		return 0;
-	}
-
-	status = acpi_get_handle(handle, "_EJ0", &tmp);
-	if (ACPI_FAILURE(status)) {
-		return 0;
-	}
-
-	return 1;
-}
-
-
-/* callback routine to check the existence of ejectable slots */
-static acpi_status
-is_ejectable_slot (acpi_handle handle, u32 lvl,	void *context, void **rv)
-{
-	int *count = (int *)context;
-
-	if (is_ejectable(handle)) {
-		(*count)++;
-		/* only one ejectable slot is enough */
-		return AE_CTRL_TERMINATE;
-	} else {
-		return AE_OK;
-	}
-}
-
-
-/* callback routine to register each ACPI PCI slot object */
-static acpi_status
-register_slot (acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-	struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context;
-	struct acpiphp_slot *slot;
-	struct acpiphp_func *newfunc;
-	acpi_handle tmp;
-	acpi_status status = AE_OK;
-	unsigned long adr, sun;
-	int device, function;
-	static int num_slots = 0;	/* XXX if we support I/O node hotplug... */
-
-	status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
-
-	if (ACPI_FAILURE(status))
-		return AE_OK;
-
-	status = acpi_get_handle(handle, "_EJ0", &tmp);
-
-	if (ACPI_FAILURE(status))
-		return AE_OK;
-
-	device = (adr >> 16) & 0xffff;
-	function = adr & 0xffff;
-
-	newfunc = kmalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
-	if (!newfunc)
-		return AE_NO_MEMORY;
-	memset(newfunc, 0, sizeof(struct acpiphp_func));
-
-	INIT_LIST_HEAD(&newfunc->sibling);
-	newfunc->handle = handle;
-	newfunc->function = function;
-	newfunc->flags = FUNC_HAS_EJ0;
-
-	if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp)))
-		newfunc->flags |= FUNC_HAS_STA;
-
-	if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS0", &tmp)))
-		newfunc->flags |= FUNC_HAS_PS0;
-
-	if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp)))
-		newfunc->flags |= FUNC_HAS_PS3;
-
-	status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun);
-	if (ACPI_FAILURE(status))
-		sun = -1;
-
-	/* search for objects that share the same slot */
-	for (slot = bridge->slots; slot; slot = slot->next)
-		if (slot->device == device) {
-			if (slot->sun != sun)
-				warn("sibling found, but _SUN doesn't match!\n");
-			break;
-		}
-
-	if (!slot) {
-		slot = kmalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
-		if (!slot) {
-			kfree(newfunc);
-			return AE_NO_MEMORY;
-		}
-
-		memset(slot, 0, sizeof(struct acpiphp_slot));
-		slot->bridge = bridge;
-		slot->id = num_slots++;
-		slot->device = device;
-		slot->sun = sun;
-		INIT_LIST_HEAD(&slot->funcs);
-		init_MUTEX(&slot->crit_sect);
-
-		slot->next = bridge->slots;
-		bridge->slots = slot;
-
-		bridge->nr_slots++;
-
-		dbg("found ACPI PCI Hotplug slot at PCI %02x:%02x Slot:%d\n",
-		    slot->bridge->bus, slot->device, slot->sun);
-	}
-
-	newfunc->slot = slot;
-	list_add_tail(&newfunc->sibling, &slot->funcs);
-
-	/* associate corresponding pci_dev */
-	newfunc->pci_dev = pci_find_slot(bridge->bus,
-					 PCI_DEVFN(device, function));
-	if (newfunc->pci_dev) {
-		if (acpiphp_init_func_resource(newfunc) < 0) {
-			kfree(newfunc);
-			return AE_ERROR;
-		}
-		slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
-	}
-
-	/* install notify handler */
-	status = acpi_install_notify_handler(handle,
-					     ACPI_SYSTEM_NOTIFY,
-					     handle_hotplug_event_func,
-					     newfunc);
-
-	if (ACPI_FAILURE(status)) {
-		err("failed to register interrupt notify handler\n");
-		kfree(newfunc);
-		return status;
-	}
-
-	return AE_OK;
-}
-
-
-/* see if it's worth looking at this bridge */
-static int detect_ejectable_slots (acpi_handle *bridge_handle)
-{
-	acpi_status status;
-	int count;
-
-	count = 0;
-
-	/* only check slots defined directly below bridge object */
-	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1,
-				     is_ejectable_slot, (void *)&count, NULL);
-
-	return count;
-}
-
-
-/* decode ACPI _CRS data and convert into our internal resource list
- * TBD: _TRA, etc.
- */
-static acpi_status
-decode_acpi_resource (struct acpi_resource *resource, void *context)
-{
-	struct acpiphp_bridge *bridge = (struct acpiphp_bridge *) context;
-	struct acpi_resource_address64 address;
-	struct pci_resource *res;
-
-	if (resource->id != ACPI_RSTYPE_ADDRESS16 &&
-	    resource->id != ACPI_RSTYPE_ADDRESS32 &&
-	    resource->id != ACPI_RSTYPE_ADDRESS64)
-		return AE_OK;
-
-	acpi_resource_to_address64(resource, &address);
-
-	if (address.producer_consumer == ACPI_PRODUCER && address.address_length > 0) {
-		dbg("resource type: %d: 0x%llx - 0x%llx\n", address.resource_type, address.min_address_range, address.max_address_range);
-		res = acpiphp_make_resource(address.min_address_range,
-				    address.address_length);
-		if (!res) {
-			err("out of memory\n");
-			return AE_OK;
-		}
-
-		switch (address.resource_type) {
-		case ACPI_MEMORY_RANGE:
-			if (address.attribute.memory.cache_attribute == ACPI_PREFETCHABLE_MEMORY) {
-				res->next = bridge->p_mem_head;
-				bridge->p_mem_head = res;
-			} else {
-				res->next = bridge->mem_head;
-				bridge->mem_head = res;
-			}
-			break;
-		case ACPI_IO_RANGE:
-			res->next = bridge->io_head;
-			bridge->io_head = res;
-			break;
-		case ACPI_BUS_NUMBER_RANGE:
-			res->next = bridge->bus_head;
-			bridge->bus_head = res;
-			break;
-		default:
-			/* invalid type */
-			kfree(res);
-			break;
-		}
-	}
-
-	return AE_OK;
-}
-
-/* decode ACPI 2.0 _HPP hot plug parameters */
-static void decode_hpp(struct acpiphp_bridge *bridge)
-{
-	acpi_status status;
-	struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER,
-				      .pointer = NULL};
-	union acpi_object *package;
-	int i;
-
-	/* default numbers */
-	bridge->hpp.cache_line_size = 0x10;
-	bridge->hpp.latency_timer = 0x40;
-	bridge->hpp.enable_SERR = 0;
-	bridge->hpp.enable_PERR = 0;
-
-	status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer);
-
-	if (ACPI_FAILURE(status)) {
-		dbg("_HPP evaluation failed\n");
-		return;
-	}
-
-	package = (union acpi_object *) buffer.pointer;
-
-	if (!package || package->type != ACPI_TYPE_PACKAGE ||
-	    package->package.count != 4 || !package->package.elements) {
-		err("invalid _HPP object; ignoring\n");
-		goto err_exit;
-	}
-
-	for (i = 0; i < 4; i++) {
-		if (package->package.elements[i].type != ACPI_TYPE_INTEGER) {
-			err("invalid _HPP parameter type; ignoring\n");
-			goto err_exit;
-		}
-	}
-
-	bridge->hpp.cache_line_size = package->package.elements[0].integer.value;
-	bridge->hpp.latency_timer = package->package.elements[1].integer.value;
-	bridge->hpp.enable_SERR = package->package.elements[2].integer.value;
-	bridge->hpp.enable_PERR = package->package.elements[3].integer.value;
-
-	dbg("_HPP parameter = (%02x, %02x, %02x, %02x)\n",
-	    bridge->hpp.cache_line_size,
-	    bridge->hpp.latency_timer,
-	    bridge->hpp.enable_SERR,
-	    bridge->hpp.enable_PERR);
-
-	bridge->flags |= BRIDGE_HAS_HPP;
-
- err_exit:
-	kfree(buffer.pointer);
-}
-
-
-/* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */
-static void init_bridge_misc (struct acpiphp_bridge *bridge)
-{
-	acpi_status status;
-
-	/* decode ACPI 2.0 _HPP (hot plug parameters) */
-	decode_hpp(bridge);
-
-	/* subtract all resources already allocated */
-	acpiphp_detect_pci_resource(bridge);
-
-	/* register all slot objects under this bridge */
-	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
-				     register_slot, bridge, NULL);
-
-	/* install notify handler */
-	status = acpi_install_notify_handler(bridge->handle,
-					     ACPI_SYSTEM_NOTIFY,
-					     handle_hotplug_event_bridge,
-					     bridge);
-
-	if (ACPI_FAILURE(status)) {
-		err("failed to register interrupt notify handler\n");
-	}
-
-	list_add(&bridge->list, &bridge_list);
-
-	dbg("Bridge resource:\n");
-	acpiphp_dump_resource(bridge);
-}
-
-
-/* allocate and initialize host bridge data structure */
-static void add_host_bridge (acpi_handle *handle, int seg, int bus)
-{
-	acpi_status status;
-	struct acpiphp_bridge *bridge;
-
-	bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
-	if (bridge == NULL)
-		return;
-
-	memset(bridge, 0, sizeof(struct acpiphp_bridge));
-
-	bridge->type = BRIDGE_TYPE_HOST;
-	bridge->handle = handle;
-	bridge->seg = seg;
-	bridge->bus = bus;
-
-	bridge->pci_bus = pci_find_bus(bus);
-
-	bridge->res_lock = SPIN_LOCK_UNLOCKED;
-
-	/* to be overridden when we decode _CRS	*/
-	bridge->sub = bridge->bus;
-
-	/* decode resources */
-
-	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
-		decode_acpi_resource, bridge);
-
-	if (ACPI_FAILURE(status)) {
-		err("failed to decode bridge resources\n");
-		kfree(bridge);
-		return;
-	}
-
-	acpiphp_resource_sort_and_combine(&bridge->io_head);
-	acpiphp_resource_sort_and_combine(&bridge->mem_head);
-	acpiphp_resource_sort_and_combine(&bridge->p_mem_head);
-	acpiphp_resource_sort_and_combine(&bridge->bus_head);
-
-	dbg("ACPI _CRS resource:\n");
-	acpiphp_dump_resource(bridge);
-
-	if (bridge->bus_head) {
-		bridge->bus = bridge->bus_head->base;
-		bridge->sub = bridge->bus_head->base + bridge->bus_head->length - 1;
-	}
-
-	init_bridge_misc(bridge);
-}
-
-
-/* allocate and initialize PCI-to-PCI bridge data structure */
-static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int fn)
-{
-	struct acpiphp_bridge *bridge;
-	u8 tmp8;
-	u16 tmp16;
-	u64 base64, limit64;
-	u32 base, limit, base32u, limit32u;
-
-	bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
-	if (bridge == NULL) {
-		err("out of memory\n");
-		return;
-	}
-
-	memset(bridge, 0, sizeof(struct acpiphp_bridge));
-
-	bridge->type = BRIDGE_TYPE_P2P;
-	bridge->handle = handle;
-	bridge->seg = seg;
-
-	bridge->pci_dev = pci_find_slot(bus, PCI_DEVFN(dev, fn));
-	if (!bridge->pci_dev) {
-		err("Can't get pci_dev\n");
-		kfree(bridge);
-		return;
-	}
-
-	bridge->pci_bus = bridge->pci_dev->subordinate;
-	if (!bridge->pci_bus) {
-		err("This is not a PCI-to-PCI bridge!\n");
-		kfree(bridge);
-		return;
-	}
-
-	bridge->res_lock = SPIN_LOCK_UNLOCKED;
-
-	bridge->bus = bridge->pci_bus->number;
-	bridge->sub = bridge->pci_bus->subordinate;
-
-	/*
-	 * decode resources under this P2P bridge
-	 */
-
-	/* I/O resources */
-	pci_read_config_byte(bridge->pci_dev, PCI_IO_BASE, &tmp8);
-	base = tmp8;
-	pci_read_config_byte(bridge->pci_dev, PCI_IO_LIMIT, &tmp8);
-	limit = tmp8;
-
-	switch (base & PCI_IO_RANGE_TYPE_MASK) {
-	case PCI_IO_RANGE_TYPE_16:
-		base = (base << 8) & 0xf000;
-		limit = ((limit << 8) & 0xf000) + 0xfff;
-		bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);
-		if (!bridge->io_head) {
-			err("out of memory\n");
-			kfree(bridge);
-			return;
-		}
-		dbg("16bit I/O range: %04x-%04x\n",
-		    (u32)bridge->io_head->base,
-		    (u32)(bridge->io_head->base + bridge->io_head->length - 1));
-		break;
-	case PCI_IO_RANGE_TYPE_32:
-		pci_read_config_word(bridge->pci_dev, PCI_IO_BASE_UPPER16, &tmp16);
-		base = ((u32)tmp16 << 16) | ((base << 8) & 0xf000);
-		pci_read_config_word(bridge->pci_dev, PCI_IO_LIMIT_UPPER16, &tmp16);
-		limit = (((u32)tmp16 << 16) | ((limit << 8) & 0xf000)) + 0xfff;
-		bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);
-		if (!bridge->io_head) {
-			err("out of memory\n");
-			kfree(bridge);
-			return;
-		}
-		dbg("32bit I/O range: %08x-%08x\n",
-		    (u32)bridge->io_head->base,
-		    (u32)(bridge->io_head->base + bridge->io_head->length - 1));
-		break;
-	case 0x0f:
-		dbg("I/O space unsupported\n");
-		break;
-	default:
-		warn("Unknown I/O range type\n");
-	}
-
-	/* Memory resources (mandatory for P2P bridge) */
-	pci_read_config_word(bridge->pci_dev, PCI_MEMORY_BASE, &tmp16);
-	base = (tmp16 & 0xfff0) << 16;
-	pci_read_config_word(bridge->pci_dev, PCI_MEMORY_LIMIT, &tmp16);
-	limit = ((tmp16 & 0xfff0) << 16) | 0xfffff;
-	bridge->mem_head = acpiphp_make_resource((u64)base, limit - base + 1);
-	if (!bridge->mem_head) {
-		err("out of memory\n");
-		kfree(bridge);
-		return;
-	}
-	dbg("32bit Memory range: %08x-%08x\n",
-	    (u32)bridge->mem_head->base,
-	    (u32)(bridge->mem_head->base + bridge->mem_head->length-1));
-
-	/* Prefetchable Memory resources (optional) */
-	pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_BASE, &tmp16);
-	base = tmp16;
-	pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_LIMIT, &tmp16);
-	limit = tmp16;
-
-	switch (base & PCI_MEMORY_RANGE_TYPE_MASK) {
-	case PCI_PREF_RANGE_TYPE_32:
-		base = (base & 0xfff0) << 16;
-		limit = ((limit & 0xfff0) << 16) | 0xfffff;
-		bridge->p_mem_head = acpiphp_make_resource((u64)base, limit - base + 1);
-		if (!bridge->p_mem_head) {
-			err("out of memory\n");
-			kfree(bridge);
-			return;
-		}
-		dbg("32bit Prefetchable memory range: %08x-%08x\n",
-		    (u32)bridge->p_mem_head->base,
-		    (u32)(bridge->p_mem_head->base + bridge->p_mem_head->length - 1));
-		break;
-	case PCI_PREF_RANGE_TYPE_64:
-		pci_read_config_dword(bridge->pci_dev, PCI_PREF_BASE_UPPER32, &base32u);
-		pci_read_config_dword(bridge->pci_dev, PCI_PREF_LIMIT_UPPER32, &limit32u);
-		base64 = ((u64)base32u << 32) | ((base & 0xfff0) << 16);
-		limit64 = (((u64)limit32u << 32) | ((limit & 0xfff0) << 16)) + 0xfffff;
-
-		bridge->p_mem_head = acpiphp_make_resource(base64, limit64 - base64 + 1);
-		if (!bridge->p_mem_head) {
-			err("out of memory\n");
-			kfree(bridge);
-			return;
-		}
-		dbg("64bit Prefetchable memory range: %08x%08x-%08x%08x\n",
-		    (u32)(bridge->p_mem_head->base >> 32),
-		    (u32)(bridge->p_mem_head->base & 0xffffffff),
-		    (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) >> 32),
-		    (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) & 0xffffffff));
-		break;
-	case 0x0f:
-		break;
-	default:
-		warn("Unknown prefetchale memory type\n");
-	}
-
-	init_bridge_misc(bridge);
-}
-
-
-/* callback routine to find P2P bridges */
-static acpi_status
-find_p2p_bridge (acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-	acpi_status status;
-	acpi_handle dummy_handle;
-	unsigned long *segbus = context;
-	unsigned long tmp;
-	int seg, bus, device, function;
-	struct pci_dev *dev;
-
-	/* get PCI address */
-	seg = (*segbus >> 8) & 0xff;
-	bus = *segbus & 0xff;
-
-	status = acpi_get_handle(handle, "_ADR", &dummy_handle);
-	if (ACPI_FAILURE(status))
-		return AE_OK;		/* continue */
-
-	status = acpi_evaluate_integer(handle, "_ADR", NULL, &tmp);
-	if (ACPI_FAILURE(status)) {
-		dbg("%s: _ADR evaluation failure\n", __FUNCTION__);
-		return AE_OK;
-	}
-
-	device = (tmp >> 16) & 0xffff;
-	function = tmp & 0xffff;
-
-	dev = pci_find_slot(bus, PCI_DEVFN(device, function));
-
-	if (!dev)
-		return AE_OK;
-
-	if (!dev->subordinate)
-		return AE_OK;
-
-	/* check if this bridge has ejectable slots */
-	if (detect_ejectable_slots(handle) > 0) {
-		dbg("found PCI-to-PCI bridge at PCI %s\n", dev->slot_name);
-		add_p2p_bridge(handle, seg, bus, device, function);
-	}
-
-	return AE_OK;
-}
-
-
-/* find hot-pluggable slots, and then find P2P bridge */
-static int add_bridges(struct acpi_device *device)
-{
-	acpi_handle *handle = device->handle;
-	acpi_status status;
-	unsigned long tmp;
-	int seg, bus;
-	acpi_handle dummy_handle;
-
-	/* if the bridge doesn't have _STA, we assume it is always there */
-	status = acpi_get_handle(handle, "_STA", &dummy_handle);
-	if (ACPI_SUCCESS(status)) {
-		status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp);
-		if (ACPI_FAILURE(status)) {
-			dbg("%s: _STA evaluation failure\n", __FUNCTION__);
-			return 0;
-		}
-		if ((tmp & ACPI_STA_FUNCTIONING) == 0)
-			/* don't register this object */
-			return 0;
-	}
-
-	/* get PCI segment number */
-	status = acpi_evaluate_integer(handle, "_SEG", NULL, &tmp);
-
-	seg = ACPI_SUCCESS(status) ? tmp : 0;
-
-	/* get PCI bus number */
-	status = acpi_evaluate_integer(handle, "_BBN", NULL, &tmp);
-
-	if (ACPI_SUCCESS(status)) {
-		bus = tmp;
-	} else {
-		warn("can't get bus number, assuming 0\n");
-		bus = 0;
-	}
-
-	/* check if this bridge has ejectable slots */
-	if (detect_ejectable_slots(handle) > 0) {
-		dbg("found PCI host-bus bridge with hot-pluggable slots\n");
-		add_host_bridge(handle, seg, bus);
-		return 0;
-	}
-
-	tmp = seg << 8 | bus;
-
-	/* search P2P bridges under this host bridge */
-	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-				     find_p2p_bridge, &tmp, NULL);
-
-	if (ACPI_FAILURE(status))
-		warn("find_p2p_bridge faied (error code = 0x%x)\n",status);
-
-	return 0;
-}
-
-
-static int power_on_slot (struct acpiphp_slot *slot)
-{
-	acpi_status status;
-	struct acpiphp_func *func;
-	struct list_head *l;
-	int retval = 0;
-
-	/* is this already enabled? */
-	if (slot->flags & SLOT_POWEREDON)
-		goto err_exit;
-
-	list_for_each (l, &slot->funcs) {
-		func = list_entry(l, struct acpiphp_func, sibling);
-
-		if (func->flags & FUNC_HAS_PS0) {
-			dbg("%s: executing _PS0 on %s\n", __FUNCTION__,
-			    func->pci_dev->slot_name);
-			status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL);
-			if (ACPI_FAILURE(status)) {
-				warn("%s: _PS0 failed\n", __FUNCTION__);
-				retval = -1;
-				goto err_exit;
-			}
-		}
-	}
-
-	/* TBD: evaluate _STA to check if the slot is enabled */
-
-	slot->flags |= SLOT_POWEREDON;
-
- err_exit:
-	return retval;
-}
-
-
-static int power_off_slot (struct acpiphp_slot *slot)
-{
-	acpi_status status;
-	struct acpiphp_func *func;
-	struct list_head *l;
-	struct acpi_object_list arg_list;
-	union acpi_object arg;
-
-	int retval = 0;
-
-	/* is this already enabled? */
-	if ((slot->flags & SLOT_POWEREDON) == 0)
-		goto err_exit;
-
-	list_for_each (l, &slot->funcs) {
-		func = list_entry(l, struct acpiphp_func, sibling);
-
-		if (func->flags & FUNC_HAS_PS3) {
-			dbg("%s: executing _PS3 on %s\n", __FUNCTION__,
-			    func->pci_dev->slot_name);
-			status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);
-			if (ACPI_FAILURE(status)) {
-				warn("%s: _PS3 failed\n", __FUNCTION__);
-				retval = -1;
-				goto err_exit;
-			}
-		}
-	}
-
-	list_for_each (l, &slot->funcs) {
-		func = list_entry(l, struct acpiphp_func, sibling);
-
-		if (func->flags & FUNC_HAS_EJ0) {
-			dbg("%s: executing _EJ0 on %s\n", __FUNCTION__,
-			    func->pci_dev->slot_name);
-
-			/* _EJ0 method take one argument */
-			arg_list.count = 1;
-			arg_list.pointer = &arg;
-			arg.type = ACPI_TYPE_INTEGER;
-			arg.integer.value = 1;
-
-			status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);
-			if (ACPI_FAILURE(status)) {
-				warn("%s: _EJ0 failed\n", __FUNCTION__);
-				retval = -1;
-				goto err_exit;
-			}
-		}
-	}
-
-	/* TBD: evaluate _STA to check if the slot is disabled */
-
-	slot->flags &= (~SLOT_POWEREDON);
-
- err_exit:
-	return retval;
-}
-
-
-/**
- * enable_device - enable, configure a slot
- * @slot: slot to be enabled
- *
- * This function should be called per *physical slot*,
- * not per each slot object in ACPI namespace.
- *
- */
-static int enable_device (struct acpiphp_slot *slot)
-{
-	u8 bus;
-	struct pci_dev *dev;
-	struct pci_bus *child;
-	struct list_head *l;
-	struct acpiphp_func *func;
-	int retval = 0;
-	int num;
-
-	if (slot->flags & SLOT_ENABLED)
-		goto err_exit;
-
-	/* sanity check: dev should be NULL when hot-plugged in */
-	dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0));
-	if (dev) {
-		/* This case shouldn't happen */
-		err("pci_dev structure already exists.\n");
-		retval = -1;
-		goto err_exit;
-	}
-
-	/* allocate resources to device */
-	retval = acpiphp_configure_slot(slot);
-	if (retval)
-		goto err_exit;
-
-	/* returned `dev' is the *first function* only! */
-	num = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0));
-	if (num)
-		pci_bus_add_devices(slot->bridge->pci_bus);
-	dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0));
-
-	if (!dev) {
-		err("No new device found\n");
-		retval = -1;
-		goto err_exit;
-	}
-
-	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-		pci_read_config_byte(dev, PCI_SECONDARY_BUS, &bus);
-		child = (struct pci_bus*) pci_add_new_bus(dev->bus, dev, bus);
-		pci_do_scan_bus(child);
-	}
-
-	/* associate pci_dev to our representation */
-	list_for_each (l, &slot->funcs) {
-		func = list_entry(l, struct acpiphp_func, sibling);
-
-		func->pci_dev = pci_find_slot(slot->bridge->bus,
-					      PCI_DEVFN(slot->device,
-							func->function));
-		if (!func->pci_dev)
-			continue;
-
-		/* configure device */
-		retval = acpiphp_configure_function(func);
-		if (retval)
-			goto err_exit;
-	}
-
-	slot->flags |= SLOT_ENABLED;
-
-	dbg("Available resources:\n");
-	acpiphp_dump_resource(slot->bridge);
-
- err_exit:
-	return retval;
-}
-
-
-/**
- * disable_device - disable a slot
- */
-static int disable_device (struct acpiphp_slot *slot)
-{
-	int retval = 0;
-	struct acpiphp_func *func;
-	struct list_head *l;
-
-	/* is this slot already disabled? */
-	if (!(slot->flags & SLOT_ENABLED))
-		goto err_exit;
-
-	list_for_each (l, &slot->funcs) {
-		func = list_entry(l, struct acpiphp_func, sibling);
-
-		if (func->pci_dev) {
-			if (acpiphp_unconfigure_function(func) == 0) {
-				func->pci_dev = NULL;
-			} else {
-				err("failed to unconfigure device\n");
-				retval = -1;
-				goto err_exit;
-			}
-		}
-	}
-
-	slot->flags &= (~SLOT_ENABLED);
-
- err_exit:
-	return retval;
-}
-
-
-/**
- * get_slot_status - get ACPI slot status
- *
- * if a slot has _STA for each function and if any one of them
- * returned non-zero status, return it
- *
- * if a slot doesn't have _STA and if any one of its functions'
- * configuration space is configured, return 0x0f as a _STA
- *
- * otherwise return 0
- */
-static unsigned int get_slot_status (struct acpiphp_slot *slot)
-{
-	acpi_status status;
-	unsigned long sta = 0;
-	u32 dvid;
-	struct list_head *l;
-	struct acpiphp_func *func;
-
-	list_for_each (l, &slot->funcs) {
-		func = list_entry(l, struct acpiphp_func, sibling);
-
-		if (func->flags & FUNC_HAS_STA) {
-			status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta);
-			if (ACPI_SUCCESS(status) && sta)
-				break;
-		} else {
-			pci_bus_read_config_dword(slot->bridge->pci_bus,
-						  PCI_DEVFN(slot->device,
-							    func->function),
-						  PCI_VENDOR_ID, &dvid);
-			if (dvid != 0xffffffff) {
-				sta = ACPI_STA_ALL;
-				break;
-			}
-		}
-	}
-
-	return (unsigned int)sta;
-}
-
-
-/*
- * ACPI event handlers
- */
-
-/**
- * handle_hotplug_event_bridge - handle ACPI event on bridges
- *
- * @handle: Notify()'ed acpi_handle
- * @type: Notify code
- * @context: pointer to acpiphp_bridge structure
- *
- * handles ACPI event notification on {host,p2p} bridges
- *
- */
-static void handle_hotplug_event_bridge (acpi_handle handle, u32 type, void *context)
-{
-	struct acpiphp_bridge *bridge;
-	char objname[64];
-	struct acpi_buffer buffer = { .length = sizeof(objname),
-				      .pointer = objname };
-
-	bridge = (struct acpiphp_bridge *)context;
-
-	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
-
-	switch (type) {
-	case ACPI_NOTIFY_BUS_CHECK:
-		/* bus re-enumerate */
-		dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
-		acpiphp_check_bridge(bridge);
-		break;
-
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		/* device check */
-		dbg("%s: Device check notify on %s\n", __FUNCTION__, objname);
-		acpiphp_check_bridge(bridge);
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		/* wake event */
-		dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname);
-		break;
-
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		/* request device eject */
-		dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
-		break;
-
-	default:
-		warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
-		break;
-	}
-}
-
-
-/**
- * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
- *
- * @handle: Notify()'ed acpi_handle
- * @type: Notify code
- * @context: pointer to acpiphp_func structure
- *
- * handles ACPI event notification on slots
- *
- */
-static void handle_hotplug_event_func (acpi_handle handle, u32 type, void *context)
-{
-	struct acpiphp_func *func;
-	char objname[64];
-	struct acpi_buffer buffer = { .length = sizeof(objname),
-				      .pointer = objname };
-
-	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
-
-	func = (struct acpiphp_func *)context;
-
-	switch (type) {
-	case ACPI_NOTIFY_BUS_CHECK:
-		/* bus re-enumerate */
-		dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
-		acpiphp_enable_slot(func->slot);
-		break;
-
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		/* device check : re-enumerate from parent bus */
-		dbg("%s: Device check notify on %s\n", __FUNCTION__, objname);
-		acpiphp_check_bridge(func->slot->bridge);
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		/* wake event */
-		dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname);
-		break;
-
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		/* request device eject */
-		dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
-		acpiphp_disable_slot(func->slot);
-		break;
-
-	default:
-		warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
-		break;
-	}
-}
-
-static struct acpi_driver acpi_pci_hp_driver = {
-	.name =		"pci_hp",
-	.class =	"",
-	.ids =		ACPI_PCI_HOST_HID,
-	.ops =	{
-		.add =	add_bridges,
-	}
-};
-
-/**
- * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures
- *
- */
-int acpiphp_glue_init (void)
-{
-	acpi_status status;
-
-	if (list_empty(&pci_root_buses))
-		return -1;
-
-	status = acpi_bus_register_driver(&acpi_pci_hp_driver);
-
-	if (ACPI_FAILURE(status)) {
-		err("%s: acpi_walk_namespace() failed\n", __FUNCTION__);
-		return -1;
-	}
-
-	return 0;
-}
-
-
-/**
- * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures
- *
- * This function frees all data allocated in acpiphp_glue_init()
- */
-void acpiphp_glue_exit (void)
-{
-	struct list_head *l1, *l2, *n1, *n2;
-	struct acpiphp_bridge *bridge;
-	struct acpiphp_slot *slot, *next;
-	struct acpiphp_func *func;
-	acpi_status status;
-
-	list_for_each_safe (l1, n1, &bridge_list) {
-		bridge = (struct acpiphp_bridge *)l1;
-		slot = bridge->slots;
-		while (slot) {
-			next = slot->next;
-			list_for_each_safe (l2, n2, &slot->funcs) {
-				func = list_entry(l2, struct acpiphp_func, sibling);
-				acpiphp_free_resource(&func->io_head);
-				acpiphp_free_resource(&func->mem_head);
-				acpiphp_free_resource(&func->p_mem_head);
-				acpiphp_free_resource(&func->bus_head);
-				status = acpi_remove_notify_handler(func->handle,
-								    ACPI_SYSTEM_NOTIFY,
-								    handle_hotplug_event_func);
-				if (ACPI_FAILURE(status))
-					err("failed to remove notify handler\n");
-				kfree(func);
-			}
-			kfree(slot);
-			slot = next;
-		}
-		status = acpi_remove_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY,
-						    handle_hotplug_event_bridge);
-		if (ACPI_FAILURE(status))
-			err("failed to remove notify handler\n");
-
-		acpiphp_free_resource(&bridge->io_head);
-		acpiphp_free_resource(&bridge->mem_head);
-		acpiphp_free_resource(&bridge->p_mem_head);
-		acpiphp_free_resource(&bridge->bus_head);
-
-		kfree(bridge);
-	}
-}
-
-
-/**
- * acpiphp_get_num_slots - count number of slots in a system
- */
-int acpiphp_get_num_slots (void)
-{
-	struct list_head *node;
-	struct acpiphp_bridge *bridge;
-	int num_slots;
-
-	num_slots = 0;
-
-	list_for_each (node, &bridge_list) {
-		bridge = (struct acpiphp_bridge *)node;
-		dbg("Bus%d %dslot(s)\n", bridge->bus, bridge->nr_slots);
-		num_slots += bridge->nr_slots;
-	}
-
-	dbg("Total %dslots\n", num_slots);
-	return num_slots;
-}
-
-
-/**
- * acpiphp_for_each_slot - call function for each slot
- * @fn: callback function
- * @data: context to be passed to callback function
- *
- */
-int acpiphp_for_each_slot(acpiphp_callback fn, void *data)
-{
-	struct list_head *node;
-	struct acpiphp_bridge *bridge;
-	struct acpiphp_slot *slot;
-	int retval = 0;
-
-	list_for_each (node, &bridge_list) {
-		bridge = (struct acpiphp_bridge *)node;
-		for (slot = bridge->slots; slot; slot = slot->next) {
-			retval = fn(slot, data);
-			if (!retval)
-				goto err_exit;
-		}
-	}
-
- err_exit:
-	return retval;
-}
-
-
-/* search matching slot from id  */
-struct acpiphp_slot *get_slot_from_id (int id)
-{
-	struct list_head *node;
-	struct acpiphp_bridge *bridge;
-	struct acpiphp_slot *slot;
-
-	list_for_each (node, &bridge_list) {
-		bridge = (struct acpiphp_bridge *)node;
-		for (slot = bridge->slots; slot; slot = slot->next)
-			if (slot->id == id)
-				return slot;
-	}
-
-	/* should never happen! */
-	err("%s: no object for id %d\n",__FUNCTION__, id);
-	return 0;
-}
-
-
-/**
- * acpiphp_enable_slot - power on slot
- */
-int acpiphp_enable_slot (struct acpiphp_slot *slot)
-{
-	int retval;
-
-	down(&slot->crit_sect);
-
-	/* wake up all functions */
-	retval = power_on_slot(slot);
-	if (retval)
-		goto err_exit;
-
-	if (get_slot_status(slot) == ACPI_STA_ALL)
-		/* configure all functions */
-		retval = enable_device(slot);
-
- err_exit:
-	up(&slot->crit_sect);
-	return retval;
-}
-
-
-/**
- * acpiphp_disable_slot - power off slot
- */
-int acpiphp_disable_slot (struct acpiphp_slot *slot)
-{
-	int retval = 0;
-
-	down(&slot->crit_sect);
-
-	/* unconfigure all functions */
-	retval = disable_device(slot);
-	if (retval)
-		goto err_exit;
-
-	/* power off all functions */
-	retval = power_off_slot(slot);
-	if (retval)
-		goto err_exit;
-
-	acpiphp_resource_sort_and_combine(&slot->bridge->io_head);
-	acpiphp_resource_sort_and_combine(&slot->bridge->mem_head);
-	acpiphp_resource_sort_and_combine(&slot->bridge->p_mem_head);
-	acpiphp_resource_sort_and_combine(&slot->bridge->bus_head);
-	dbg("Available resources:\n");
-	acpiphp_dump_resource(slot->bridge);
-
- err_exit:
-	up(&slot->crit_sect);
-	return retval;
-}
-
-
-/**
- * acpiphp_check_bridge - re-enumerate devices
- */
-int acpiphp_check_bridge (struct acpiphp_bridge *bridge)
-{
-	struct acpiphp_slot *slot;
-	unsigned int sta;
-	int retval = 0;
-	int enabled, disabled;
-
-	enabled = disabled = 0;
-
-	for (slot = bridge->slots; slot; slot = slot->next) {
-		sta = get_slot_status(slot);
-		if (slot->flags & SLOT_ENABLED) {
-			/* if enabled but not present, disable */
-			if (sta != ACPI_STA_ALL) {
-				retval = acpiphp_disable_slot(slot);
-				if (retval) {
-					err("Error occurred in enabling\n");
-					up(&slot->crit_sect);
-					goto err_exit;
-				}
-				enabled++;
-			}
-		} else {
-			/* if disabled but present, enable */
-			if (sta == ACPI_STA_ALL) {
-				retval = acpiphp_enable_slot(slot);
-				if (retval) {
-					err("Error occurred in enabling\n");
-					up(&slot->crit_sect);
-					goto err_exit;
-				}
-				disabled++;
-			}
-		}
-	}
-
-	dbg("%s: %d enabled, %d disabled\n", __FUNCTION__, enabled, disabled);
-
- err_exit:
-	return retval;
-}
-
-
-/*
- * slot enabled:  1
- * slot disabled: 0
- */
-u8 acpiphp_get_power_status (struct acpiphp_slot *slot)
-{
-	unsigned int sta;
-
-	sta = get_slot_status(slot);
-
-	return (sta & ACPI_STA_ENABLED) ? 1 : 0;
-}
-
-
-/*
- * attention LED ON: 1
- *              OFF: 0
- *
- * TBD
- * no direct attention led status information via ACPI
- *
- */
-u8 acpiphp_get_attention_status (struct acpiphp_slot *slot)
-{
-	return 0;
-}
-
-
-/*
- * latch closed:  1
- * latch   open:  0
- */
-u8 acpiphp_get_latch_status (struct acpiphp_slot *slot)
-{
-	unsigned int sta;
-
-	sta = get_slot_status(slot);
-
-	return (sta & ACPI_STA_SHOW_IN_UI) ? 1 : 0;
-}
-
-
-/*
- * adapter presence : 1
- *          absence : 0
- */
-u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot)
-{
-	unsigned int sta;
-
-	sta = get_slot_status(slot);
-
-	return (sta == 0) ? 0 : 1;
-}
diff -Nru a/drivers/hotplug/acpiphp_pci.c b/drivers/hotplug/acpiphp_pci.c
--- a/drivers/hotplug/acpiphp_pci.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,510 +0,0 @@
-/*
- * ACPI PCI HotPlug PCI configuration space management
- *
- * Copyright (c) 1995,2001 Compaq Computer Corporation
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001,2002 IBM Corp.
- * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com)
- * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
- * Copyright (c) 2002 NEC Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <t-kouchi@cq.jp.nec.com>
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-#include "pci_hotplug.h"
-#include "acpiphp.h"
-
-#define MY_NAME "acpiphp_pci"
-
-
-/* allocate mem/pmem/io resource to a new function */
-static int init_config_space (struct acpiphp_func *func)
-{
-	u32 bar, len;
-	u32 address[] = {
-		PCI_BASE_ADDRESS_0,
-		PCI_BASE_ADDRESS_1,
-		PCI_BASE_ADDRESS_2,
-		PCI_BASE_ADDRESS_3,
-		PCI_BASE_ADDRESS_4,
-		PCI_BASE_ADDRESS_5,
-		0
-	};
-	int count;
-	struct acpiphp_bridge *bridge;
-	struct pci_resource *res;
-	struct pci_bus *pbus;
-	int bus, device, function;
-	unsigned int devfn;
-	u16 tmp;
-
-	bridge = func->slot->bridge;
-	pbus = bridge->pci_bus;
-	bus = bridge->bus;
-	device = func->slot->device;
-	function = func->function;
-	devfn = PCI_DEVFN(device, function);
-
-	for (count = 0; address[count]; count++) {	/* for 6 BARs */
-		pci_bus_write_config_dword(pbus, devfn,
-					   address[count], 0xFFFFFFFF);
-		pci_bus_read_config_dword(pbus, devfn, address[count], &bar);
-
-		if (!bar)	/* This BAR is not implemented */
-			continue;
-
-		dbg("Device %02x.%02x BAR %d wants %x\n", device, function, count, bar);
-
-		if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
-			/* This is IO */
-
-			len = bar & 0xFFFFFFFC;
-			len = ~len + 1;
-
-			dbg("len in IO %x, BAR %d\n", len, count);
-
-			spin_lock(&bridge->res_lock);
-			res = acpiphp_get_io_resource(&bridge->io_head, len);
-			spin_unlock(&bridge->res_lock);
-
-			if (!res) {
-				err("cannot allocate requested io for %02x:%02x.%d len %x\n",
-				    bus, device, function, len);
-				return -1;
-			}
-			pci_bus_write_config_dword(pbus, devfn,
-						   address[count],
-						   (u32)res->base);
-			res->next = func->io_head;
-			func->io_head = res;
-
-		} else {
-			/* This is Memory */
-			if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) {
-				/* pfmem */
-
-				len = bar & 0xFFFFFFF0;
-				len = ~len + 1;
-
-				dbg("len in PFMEM %x, BAR %d\n", len, count);
-
-				spin_lock(&bridge->res_lock);
-				res = acpiphp_get_resource(&bridge->p_mem_head, len);
-				spin_unlock(&bridge->res_lock);
-
-				if (!res) {
-					err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
-					    bus, device, function, len);
-					return -1;
-				}
-
-				pci_bus_write_config_dword(pbus, devfn,
-							   address[count],
-							   (u32)res->base);
-
-				if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {	/* takes up another dword */
-					dbg("inside the pfmem 64 case, count %d\n", count);
-					count += 1;
-					pci_bus_write_config_dword(pbus, devfn,
-								   address[count],
-								   (u32)(res->base >> 32));
-				}
-
-				res->next = func->p_mem_head;
-				func->p_mem_head = res;
-
-			} else {
-				/* regular memory */
-
-				len = bar & 0xFFFFFFF0;
-				len = ~len + 1;
-
-				dbg("len in MEM %x, BAR %d\n", len, count);
-
-				spin_lock(&bridge->res_lock);
-				res = acpiphp_get_resource(&bridge->mem_head, len);
-				spin_unlock(&bridge->res_lock);
-
-				if (!res) {
-					err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
-					    bus, device, function, len);
-					return -1;
-				}
-
-				pci_bus_write_config_dword(pbus, devfn,
-							   address[count],
-							   (u32)res->base);
-
-				if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-					/* takes up another dword */
-					dbg("inside mem 64 case, reg. mem, count %d\n", count);
-					count += 1;
-					pci_bus_write_config_dword(pbus, devfn,
-								   address[count],
-								   (u32)(res->base >> 32));
-				}
-
-				res->next = func->mem_head;
-				func->mem_head = res;
-
-			}
-		}
-	}
-
-	/* disable expansion rom */
-	pci_bus_write_config_dword(pbus, devfn, PCI_ROM_ADDRESS, 0x00000000);
-
-	/* set PCI parameters from _HPP */
-	pci_bus_write_config_byte(pbus, devfn, PCI_CACHE_LINE_SIZE,
-				  bridge->hpp.cache_line_size);
-	pci_bus_write_config_byte(pbus, devfn, PCI_LATENCY_TIMER,
-				  bridge->hpp.latency_timer);
-
-	pci_bus_read_config_word(pbus, devfn, PCI_COMMAND, &tmp);
-	if (bridge->hpp.enable_SERR)
-		tmp |= PCI_COMMAND_SERR;
-	if (bridge->hpp.enable_PERR)
-		tmp |= PCI_COMMAND_PARITY;
-	pci_bus_write_config_word(pbus, devfn, PCI_COMMAND, tmp);
-
-	return 0;
-}
-
-/* detect_used_resource - subtract resource under dev from bridge */
-static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *dev)
-{
-	u32 bar, len;
-	u64 base;
-	u32 address[] = {
-		PCI_BASE_ADDRESS_0,
-		PCI_BASE_ADDRESS_1,
-		PCI_BASE_ADDRESS_2,
-		PCI_BASE_ADDRESS_3,
-		PCI_BASE_ADDRESS_4,
-		PCI_BASE_ADDRESS_5,
-		0
-	};
-	int count;
-	struct pci_resource *res;
-
-	dbg("Device %s\n", dev->slot_name);
-
-	for (count = 0; address[count]; count++) {	/* for 6 BARs */
-		pci_read_config_dword(dev, address[count], &bar);
-
-		if (!bar)	/* This BAR is not implemented */
-			continue;
-
-		pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
-		pci_read_config_dword(dev, address[count], &len);
-
-		if (len & PCI_BASE_ADDRESS_SPACE_IO) {
-			/* This is IO */
-			base = bar & 0xFFFFFFFC;
-			len &= 0xFFFFFFFC;
-			len = ~len + 1;
-
-			dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
-
-			spin_lock(&bridge->res_lock);
-			res = acpiphp_get_resource_with_base(&bridge->io_head, base, len);
-			spin_unlock(&bridge->res_lock);
-			if (res)
-				kfree(res);
-		} else {
-			/* This is Memory */
-			base = bar & 0xFFFFFFF0;
-			if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
-				/* pfmem */
-
-				len &= 0xFFFFFFF0;
-				len = ~len + 1;
-
-				if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {	/* takes up another dword */
-					dbg("prefetch mem 64\n");
-					count += 1;
-				}
-				dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
-				spin_lock(&bridge->res_lock);
-				res = acpiphp_get_resource_with_base(&bridge->p_mem_head, base, len);
-				spin_unlock(&bridge->res_lock);
-				if (res)
-					kfree(res);
-			} else {
-				/* regular memory */
-
-				len &= 0xFFFFFFF0;
-				len = ~len + 1;
-
-				if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-					/* takes up another dword */
-					dbg("mem 64\n");
-					count += 1;
-				}
-				dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
-				spin_lock(&bridge->res_lock);
-				res = acpiphp_get_resource_with_base(&bridge->mem_head, base, len);
-				spin_unlock(&bridge->res_lock);
-				if (res)
-					kfree(res);
-			}
-		}
-
-		pci_write_config_dword(dev, address[count], bar);
-	}
-
-	return 0;
-}
-
-
-/* detect_pci_resource_bus - subtract resource under pci_bus */
-static void detect_used_resource_bus(struct acpiphp_bridge *bridge, struct pci_bus *bus)
-{
-	struct list_head *l;
-	struct pci_dev *dev;
-
-	list_for_each (l, &bus->devices) {
-		dev = pci_dev_b(l);
-		detect_used_resource(bridge, dev);
-		/* XXX recursive call */
-		if (dev->subordinate)
-			detect_used_resource_bus(bridge, dev->subordinate);
-	}
-}
-
-
-/**
- * acpiphp_detect_pci_resource - detect resources under bridge
- * @bridge: detect all resources already used under this bridge
- *
- * collect all resources already allocated for all devices under a bridge.
- */
-int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge)
-{
-	detect_used_resource_bus(bridge, bridge->pci_bus);
-
-	return 0;
-}
-
-
-/**
- * acpiphp_init_slot_resource - gather resource usage information of a slot
- * @slot: ACPI slot object to be checked, should have valid pci_dev member
- *
- * TBD: PCI-to-PCI bridge case
- *      use pci_dev->resource[]
- */
-int acpiphp_init_func_resource (struct acpiphp_func *func)
-{
-	u64 base;
-	u32 bar, len;
-	u32 address[] = {
-		PCI_BASE_ADDRESS_0,
-		PCI_BASE_ADDRESS_1,
-		PCI_BASE_ADDRESS_2,
-		PCI_BASE_ADDRESS_3,
-		PCI_BASE_ADDRESS_4,
-		PCI_BASE_ADDRESS_5,
-		0
-	};
-	int count;
-	struct pci_resource *res;
-	struct pci_dev *dev;
-
-	dev = func->pci_dev;
-	dbg("Hot-pluggable device %s\n", dev->slot_name);
-
-	for (count = 0; address[count]; count++) {	/* for 6 BARs */
-		pci_read_config_dword(dev, address[count], &bar);
-
-		if (!bar)	/* This BAR is not implemented */
-			continue;
-
-		pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
-		pci_read_config_dword(dev, address[count], &len);
-
-		if (len & PCI_BASE_ADDRESS_SPACE_IO) {
-			/* This is IO */
-			base = bar & 0xFFFFFFFC;
-			len &= 0xFFFFFFFC;
-			len = ~len + 1;
-
-			dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
-
-			res = acpiphp_make_resource(base, len);
-			if (!res)
-				goto no_memory;
-
-			res->next = func->io_head;
-			func->io_head = res;
-
-		} else {
-			/* This is Memory */
-			base = bar & 0xFFFFFFF0;
-			if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
-				/* pfmem */
-
-				len &= 0xFFFFFFF0;
-				len = ~len + 1;
-
-				if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {	/* takes up another dword */
-					dbg("prefetch mem 64\n");
-					count += 1;
-				}
-				dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
-				res = acpiphp_make_resource(base, len);
-				if (!res)
-					goto no_memory;
-
-				res->next = func->p_mem_head;
-				func->p_mem_head = res;
-
-			} else {
-				/* regular memory */
-
-				len &= 0xFFFFFFF0;
-				len = ~len + 1;
-
-				if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-					/* takes up another dword */
-					dbg("mem 64\n");
-					count += 1;
-				}
-				dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
-				res = acpiphp_make_resource(base, len);
-				if (!res)
-					goto no_memory;
-
-				res->next = func->mem_head;
-				func->mem_head = res;
-
-			}
-		}
-
-		pci_write_config_dword(dev, address[count], bar);
-	}
-#if 1
-	acpiphp_dump_func_resource(func);
-#endif
-
-	return 0;
-
- no_memory:
-	err("out of memory\n");
-	acpiphp_free_resource(&func->io_head);
-	acpiphp_free_resource(&func->mem_head);
-	acpiphp_free_resource(&func->p_mem_head);
-
-	return -1;
-}
-
-
-/**
- * acpiphp_configure_slot - allocate PCI resources
- * @slot: slot to be configured
- *
- * initializes a PCI functions on a device inserted
- * into the slot
- *
- */
-int acpiphp_configure_slot (struct acpiphp_slot *slot)
-{
-	struct acpiphp_func *func;
-	struct list_head *l;
-	u8 hdr;
-	u32 dvid;
-	int retval = 0;
-	int is_multi = 0;
-
-	pci_bus_read_config_byte(slot->bridge->pci_bus,
-				 PCI_DEVFN(slot->device, 0),
-				 PCI_HEADER_TYPE, &hdr);
-
-	if (hdr & 0x80)
-		is_multi = 1;
-
-	list_for_each (l, &slot->funcs) {
-		func = list_entry(l, struct acpiphp_func, sibling);
-		if (is_multi || func->function == 0) {
-			pci_bus_read_config_dword(slot->bridge->pci_bus,
-						  PCI_DEVFN(slot->device,
-							    func->function),
-						  PCI_VENDOR_ID, &dvid);
-			if (dvid != 0xffffffff) {
-				retval = init_config_space(func);
-				if (retval)
-					break;
-			}
-		}
-	}
-
-	return retval;
-}
-
-/**
- * acpiphp_configure_function - configure PCI function
- * @func: function to be configured
- *
- * initializes a PCI functions on a device inserted
- * into the slot
- *
- */
-int acpiphp_configure_function (struct acpiphp_func *func)
-{
-	/* all handled by the pci core now */
-	return 0;
-}
-
-/**
- * acpiphp_unconfigure_function - unconfigure PCI function
- * @func: function to be unconfigured
- *
- */
-int acpiphp_unconfigure_function (struct acpiphp_func *func)
-{
-	struct acpiphp_bridge *bridge;
-	int retval = 0;
-
-	/* if pci_dev is NULL, ignore it */
-	if (!func->pci_dev)
-		goto err_exit;
-
-	pci_remove_bus_device(func->pci_dev);
-
-	/* free all resources */
-	bridge = func->slot->bridge;
-
-	spin_lock(&bridge->res_lock);
-	acpiphp_move_resource(&func->io_head, &bridge->io_head);
-	acpiphp_move_resource(&func->mem_head, &bridge->mem_head);
-	acpiphp_move_resource(&func->p_mem_head, &bridge->p_mem_head);
-	acpiphp_move_resource(&func->bus_head, &bridge->bus_head);
-	spin_unlock(&bridge->res_lock);
-
- err_exit:
-	return retval;
-}
diff -Nru a/drivers/hotplug/acpiphp_res.c b/drivers/hotplug/acpiphp_res.c
--- a/drivers/hotplug/acpiphp_res.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,699 +0,0 @@
-/*
- * ACPI PCI HotPlug Utility functions
- *
- * Copyright (c) 1995,2001 Compaq Computer Corporation
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001 IBM Corp.
- * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
- * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com)
- * Copyright (c) 2002 NEC Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <gregkh@us.ibm.com>,<h-aono@ap.jp.nec.com>
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/sysctl.h>
-#include <linux/pci.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-
-#include <linux/ioctl.h>
-#include <linux/fcntl.h>
-
-#include <linux/list.h>
-
-#include "pci_hotplug.h"
-#include "acpiphp.h"
-
-#define MY_NAME "acpiphp_res"
-
-
-/*
- * sort_by_size - sort nodes 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;
-}
-
-
-/*
- * sort_by_max_size - sort nodes 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_io_resource - get resource for I/O ports
- *
- * 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.
- *
- * difference from get_resource is handling of ISA aliasing space.
- *
- */
-struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 size)
-{
-	struct pci_resource *prevnode;
-	struct pci_resource *node;
-	struct pci_resource *split_node;
-	u64 temp_qword;
-
-	if (!(*head))
-		return NULL;
-
-	if (acpiphp_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_qword = (node->base | (size-1)) + 1;
-
-			/* Short circuit if adjusted size is too small */
-			if ((node->length - (temp_qword - node->base)) < size)
-				continue;
-
-			split_node = acpiphp_make_resource(node->base, temp_qword - node->base);
-
-			if (!split_node)
-				return NULL;
-
-			node->base = temp_qword;
-			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 = acpiphp_make_resource(node->base + size, node->length - size);
-
-			if (!split_node)
-				return NULL;
-
-			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_max_resource - get the largest 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.
- */
-struct pci_resource *acpiphp_get_max_resource (struct pci_resource **head, u32 size)
-{
-	struct pci_resource *max;
-	struct pci_resource *temp;
-	struct pci_resource *split_node;
-	u64 temp_qword;
-
-	if (!(*head))
-		return NULL;
-
-	if (acpiphp_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_qword = (max->base | (size-1)) + 1;
-
-			/* Short circuit if adjusted size is too small */
-			if ((max->length - (temp_qword - max->base)) < size)
-				continue;
-
-			split_node = acpiphp_make_resource(max->base, temp_qword - max->base);
-
-			if (!split_node)
-				return NULL;
-
-			max->base = temp_qword;
-			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 */
-			temp_qword = ((max->base + max->length) & ~(size - 1));
-
-			split_node = acpiphp_make_resource(temp_qword,
-							   max->length + max->base - temp_qword);
-
-			if (!split_node)
-				return NULL;
-
-			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_resource - get resource (mem, pfmem)
- *
- * 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.
- *
- */
-struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size)
-{
-	struct pci_resource *prevnode;
-	struct pci_resource *node;
-	struct pci_resource *split_node;
-	u64 temp_qword;
-
-	if (!(*head))
-		return NULL;
-
-	if (acpiphp_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, (u32)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_qword = (node->base | (size-1)) + 1;
-
-			/* Short circuit if adjusted size is too small */
-			if ((node->length - (temp_qword - node->base)) < size)
-				continue;
-
-			split_node = acpiphp_make_resource(node->base, temp_qword - node->base);
-
-			if (!split_node)
-				return NULL;
-
-			node->base = temp_qword;
-			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 = acpiphp_make_resource(node->base + size, node->length - size);
-
-			if (!split_node)
-				return NULL;
-
-			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;
-}
-
-/**
- * get_resource_with_base - get resource with specific base address
- *
- * this function
- * returns the first node of "size" length located at specified base address.
- * If it finds a node larger than "size" it will split it up.
- *
- * size must be a power of two.
- *
- */
-struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, u64 base, u32 size)
-{
-	struct pci_resource *prevnode;
-	struct pci_resource *node;
-	struct pci_resource *split_node;
-	u64 temp_qword;
-
-	if (!(*head))
-		return NULL;
-
-	if (acpiphp_resource_sort_and_combine(head))
-		return NULL;
-
-	for (node = *head; node; node = node->next) {
-		dbg(": 1st req_base=%x req_size =%x node=%p, base=%x, length=%x\n",
-		    (u32)base, size, node, (u32)node->base, node->length);
-		if (node->base > base)
-			continue;
-
-		if ((node->base + node->length) < (base + size))
-			continue;
-
-		if (node->base < base) {
-			dbg(": split 1\n");
-			/* this one isn't base aligned properly
-			   so we'll make a new entry and split it up */
-			temp_qword = base;
-
-			/* Short circuit if adjusted size is too small */
-			if ((node->length - (temp_qword - node->base)) < size)
-				continue;
-
-			split_node = acpiphp_make_resource(node->base, temp_qword - node->base);
-
-			if (!split_node)
-				return NULL;
-
-			node->base = temp_qword;
-			node->length -= split_node->length;
-
-			/* Put it in the list */
-			split_node->next = node->next;
-			node->next = split_node;
-		}
-
-		dbg(": 2nd req_base=%x req_size =%x node=%p, base=%x, length=%x\n",
-		    (u32)base, size, node, (u32)node->base, node->length);
-
-		/* Don't need to check if too small since we already did */
-		if (node->length > size) {
-			dbg(": split 2\n");
-			/* this one is longer than we need
-			   so we'll make a new entry and split it up */
-			split_node = acpiphp_make_resource(node->base + size, node->length - size);
-
-			if (!split_node)
-				return NULL;
-
-			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(": got one!!!\n");
-		/* 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;
-}
-
-
-/**
- * acpiphp_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 acpiphp_resource_sort_and_combine (struct pci_resource **head)
-{
-	struct pci_resource *node1;
-	struct pci_resource *node2;
-	int out_of_order = 1;
-
-	if (!(*head))
-		return 1;
-
-	dbg("*head->next = %p\n",(*head)->next);
-
-	if (!(*head)->next)
-		return 0;	/* only one item on the list, already sorted! */
-
-	dbg("*head->base = 0x%x\n",(u32)(*head)->base);
-	dbg("*head->next->base = 0x%x\n", (u32)(*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("8..\n");
-			node1->length += node1->next->length;
-			node2 = node1->next;
-			node1->next = node1->next->next;
-			kfree(node2);
-		} else
-			node1 = node1->next;
-	}
-
-	return 0;
-}
-
-
-/**
- * acpiphp_make_resource - make resource structure
- * @base: base address of a resource
- * @length: length of a resource
- */
-struct pci_resource *acpiphp_make_resource (u64 base, u32 length)
-{
-	struct pci_resource *res;
-
-	res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-	if (res) {
-		memset(res, 0, sizeof(struct pci_resource));
-		res->base = base;
-		res->length = length;
-	}
-
-	return res;
-}
-
-
-/**
- * acpiphp_move_resource - move linked resources from one to another
- * @from: head of linked resource list
- * @to: head of linked resource list
- */
-void acpiphp_move_resource (struct pci_resource **from, struct pci_resource **to)
-{
-	struct pci_resource *tmp;
-
-	while (*from) {
-		tmp = (*from)->next;
-		(*from)->next = *to;
-		*to = *from;
-		*from = tmp;
-	}
-
-	/* *from = NULL is guaranteed */
-}
-
-
-/**
- * acpiphp_free_resource - free all linked resources
- * @res: head of linked resource list
- */
-void acpiphp_free_resource (struct pci_resource **res)
-{
-	struct pci_resource *tmp;
-
-	while (*res) {
-		tmp = (*res)->next;
-		kfree(*res);
-		*res = tmp;
-	}
-
-	/* *res = NULL is guaranteed */
-}
-
-
-/* debug support functions;  will go away sometime :) */
-static void dump_resource(struct pci_resource *head)
-{
-	struct pci_resource *p;
-	int cnt;
-
-	p = head;
-	cnt = 0;
-
-	while (p) {
-		dbg("[%02d] %08x - %08x\n",
-		    cnt++, (u32)p->base, (u32)p->base + p->length - 1);
-		p = p->next;
-	}
-}
-
-void acpiphp_dump_resource(struct acpiphp_bridge *bridge)
-{
-	dbg("I/O resource:\n");
-	dump_resource(bridge->io_head);
-	dbg("MEM resource:\n");
-	dump_resource(bridge->mem_head);
-	dbg("PMEM resource:\n");
-	dump_resource(bridge->p_mem_head);
-	dbg("BUS resource:\n");
-	dump_resource(bridge->bus_head);
-}
-
-void acpiphp_dump_func_resource(struct acpiphp_func *func)
-{
-	dbg("I/O resource:\n");
-	dump_resource(func->io_head);
-	dbg("MEM resource:\n");
-	dump_resource(func->mem_head);
-	dbg("PMEM resource:\n");
-	dump_resource(func->p_mem_head);
-	dbg("BUS resource:\n");
-	dump_resource(func->bus_head);
-}
diff -Nru a/drivers/hotplug/cpci_hotplug.h b/drivers/hotplug/cpci_hotplug.h
--- a/drivers/hotplug/cpci_hotplug.h	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,100 +0,0 @@
-/*
- * CompactPCI Hot Plug Core Functions
- *
- * Copyright (c) 2002 SOMA Networks, Inc.
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001 IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <scottm@somanetworks.com>
- */
-
-#ifndef _CPCI_HOTPLUG_H
-#define _CPCI_HOTPLUG_H
-
-#include <linux/types.h>
-#include <linux/pci.h>
-
-/* PICMG 2.12 R2.0 HS CSR bits: */
-#define HS_CSR_INS	0x0080
-#define HS_CSR_EXT	0x0040
-#define HS_CSR_PI	0x0030
-#define HS_CSR_LOO	0x0008
-#define HS_CSR_PIE	0x0004
-#define HS_CSR_EIM	0x0002
-#define HS_CSR_DHA	0x0001
-
-#define SLOT_MAGIC	0x67267322
-struct slot {
-	u32 magic;
-	u8 number;
-	unsigned int devfn;
-	struct pci_bus *bus;
-	struct pci_dev *dev;
-	unsigned int extracting;
-	struct hotplug_slot *hotplug_slot;
-	struct list_head slot_list;
-};
-
-struct cpci_hp_controller_ops {
-	int (*query_enum) (void);
-	int (*enable_irq) (void);
-	int (*disable_irq) (void);
-	int (*check_irq) (void *dev_id);
-	int (*hardware_test) (struct slot* slot, u32 value);
-	u8  (*get_power) (struct slot* slot);
-	int (*set_power) (struct slot* slot, int value);
-};
-
-struct cpci_hp_controller {
-	unsigned int irq;
-	unsigned long irq_flags;
-	char *devname;
-	void *dev_id;
-	char *name;
-	struct cpci_hp_controller_ops *ops;
-};
-
-extern int cpci_hp_register_controller(struct cpci_hp_controller *controller);
-extern int cpci_hp_unregister_controller(struct cpci_hp_controller *controller);
-extern int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last);
-extern int cpci_hp_unregister_bus(struct pci_bus *bus);
-extern struct slot *cpci_find_slot(struct pci_bus *bus, unsigned int devfn);
-extern int cpci_hp_start(void);
-extern int cpci_hp_stop(void);
-
-/*
- * Internal function prototypes, these functions should not be used by
- * board/chassis drivers.
- */
-extern u8 cpci_get_attention_status(struct slot *slot);
-extern u8 cpci_get_latch_status(struct slot *slot);
-extern u8 cpci_get_adapter_status(struct slot *slot);
-extern u16 cpci_get_hs_csr(struct slot * slot);
-extern u16 cpci_set_hs_csr(struct slot * slot, u16 hs_csr);
-extern int cpci_set_attention_status(struct slot *slot, int status);
-extern int cpci_check_and_clear_ins(struct slot * slot);
-extern int cpci_check_ext(struct slot * slot);
-extern int cpci_clear_ext(struct slot * slot);
-extern int cpci_led_on(struct slot * slot);
-extern int cpci_led_off(struct slot * slot);
-extern int cpci_configure_slot(struct slot *slot);
-extern int cpci_unconfigure_slot(struct slot *slot);
-
-#endif	/* _CPCI_HOTPLUG_H */
diff -Nru a/drivers/hotplug/cpci_hotplug_core.c b/drivers/hotplug/cpci_hotplug_core.c
--- a/drivers/hotplug/cpci_hotplug_core.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,919 +0,0 @@
-/*
- * CompactPCI Hot Plug Driver
- *
- * Copyright (c) 2002 SOMA Networks, Inc.
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001 IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <scottm@somanetworks.com>
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/smp_lock.h>
-#include "pci_hotplug.h"
-#include "cpci_hotplug.h"
-
-#define DRIVER_VERSION	"0.2"
-#define DRIVER_AUTHOR	"Scott Murray <scottm@somanetworks.com>"
-#define DRIVER_DESC	"CompactPCI Hot Plug Core"
-
-#if !defined(CONFIG_HOTPLUG_CPCI_MODULE)
-#define MY_NAME	"cpci_hotplug"
-#else
-#define MY_NAME	THIS_MODULE->name
-#endif
-
-#define dbg(format, arg...)					\
-	do {							\
-		if(cpci_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)
-
-/* local variables */
-static spinlock_t list_lock;
-static LIST_HEAD(slot_list);
-static int slots;
-int cpci_debug;
-static struct cpci_hp_controller *controller;
-static struct semaphore event_semaphore;	/* mutex for process loop (up if something to process) */
-static struct semaphore thread_exit;		/* guard ensure thread has exited before calling it quits */
-static int thread_finished = 1;
-
-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 get_power_status(struct hotplug_slot *slot, u8 * value);
-static int get_attention_status(struct hotplug_slot *slot, u8 * value);
-static int get_latch_status(struct hotplug_slot *slot, u8 * value);
-static int get_adapter_status(struct hotplug_slot *slot, u8 * value);
-
-static struct hotplug_slot_ops cpci_hotplug_slot_ops = {
-	.owner = THIS_MODULE,
-	.enable_slot = enable_slot,
-	.disable_slot = disable_slot,
-	.set_attention_status = set_attention_status,
-	.hardware_test = NULL,
-	.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", function);
-		return NULL;
-	}
-
-	slot = (struct slot *) hotplug_slot->private;
-	if(slot_paranoia_check(slot, function))
-		return NULL;
-	return slot;
-}
-
-static int
-update_latch_status(struct hotplug_slot *hotplug_slot, u8 value)
-{
-	struct hotplug_slot_info info;
-
-	if(!(hotplug_slot && hotplug_slot->info))
-		return -EINVAL;
-	memcpy(&info, hotplug_slot->info, sizeof(struct hotplug_slot_info));
-	info.latch_status = value;
-	return pci_hp_change_slot_info(hotplug_slot, &info);
-}
-
-static int
-update_adapter_status(struct hotplug_slot *hotplug_slot, u8 value)
-{
-	struct hotplug_slot_info info;
-
-	if(!(hotplug_slot && hotplug_slot->info))
-		return -EINVAL;
-	memcpy(&info, hotplug_slot->info, sizeof(struct hotplug_slot_info));
-	info.adapter_status = value;
-	return pci_hp_change_slot_info(hotplug_slot, &info);
-}
-
-static int
-enable_slot(struct hotplug_slot *hotplug_slot)
-{
-	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
-	int retval = 0;
-
-	if(slot == NULL)
-		return -ENODEV;
-
-	dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
-
-	if(controller->ops->set_power) {
-		retval = controller->ops->set_power(slot, 1);
-	}
-
-	return retval;
-}
-
-static int
-disable_slot(struct hotplug_slot *hotplug_slot)
-{
-	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
-	int retval = 0;
-
-	if(slot == NULL)
-		return -ENODEV;
-
-	dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
-
-	/* Unconfigure device */
-	dbg("%s - unconfiguring slot %s",
-	    __FUNCTION__, slot->hotplug_slot->name);
-	if((retval = cpci_unconfigure_slot(slot))) {
-		err("%s - could not unconfigure slot %s",
-		    __FUNCTION__, slot->hotplug_slot->name);
-		return retval;
-	}
-	dbg("%s - finished unconfiguring slot %s",
-	    __FUNCTION__, slot->hotplug_slot->name);
-
-	/* Clear EXT (by setting it) */
-	if(cpci_clear_ext(slot)) {
-		err("%s - could not clear EXT for slot %s",
-		    __FUNCTION__, slot->hotplug_slot->name);
-		retval = -ENODEV;
-	}
-	cpci_led_on(slot);
-
-	if(controller->ops->set_power) {
-		retval = controller->ops->set_power(slot, 0);
-	}
-
-	if(update_adapter_status(slot->hotplug_slot, 0)) {
-		warn("failure to update adapter file");
-	}
-
-	slot->extracting = 0;
-
-	return retval;
-}
-
-static u8
-cpci_get_power_status(struct slot *slot)
-{
-	u8 power = 1;
-
-	if(controller->ops->get_power) {
-		power = controller->ops->get_power(slot);
-	}
-	return power;
-}
-
-static int
-get_power_status(struct hotplug_slot *hotplug_slot, u8 * value)
-{
-	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
-
-	if(slot == NULL)
-		return -ENODEV;
-	*value = cpci_get_power_status(slot);
-	return 0;
-}
-
-static int
-get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value)
-{
-	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
-
-	if(slot == NULL)
-		return -ENODEV;
-	*value = cpci_get_attention_status(slot);
-	return 0;
-}
-
-static int
-set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
-{
-	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
-
-	if(slot == NULL)
-		return -ENODEV;
-	switch (status) {
-	case 0:
-		cpci_set_attention_status(slot, 0);
-		break;
-
-	case 1:
-	default:
-		cpci_set_attention_status(slot, 1);
-		break;
-	}
-
-	return 0;
-}
-
-static int
-get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value)
-{
-	if(hotplug_slot == NULL || hotplug_slot->info == NULL)
-		return -ENODEV;
-	*value = hotplug_slot->info->latch_status;
-	return 0;
-}
-
-static int
-get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value)
-{
-	if(hotplug_slot == NULL || hotplug_slot->info == NULL)
-		return -ENODEV;
-	*value = hotplug_slot->info->adapter_status;
-	return 0;
-}
-
-#define SLOT_NAME_SIZE	6
-static void
-make_slot_name(struct slot *slot)
-{
-	snprintf(slot->hotplug_slot->name,
-		 SLOT_NAME_SIZE, "%02x:%02x", slot->bus->number, slot->number);
-}
-
-int
-cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
-{
-	struct slot *slot;
-	struct hotplug_slot *hotplug_slot;
-	struct hotplug_slot_info *info;
-	char *name;
-	int status = 0;
-	int i;
-
-	if(!(controller && bus)) {
-		return -ENODEV;
-	}
-	if(last < first) {
-		return -EINVAL;
-	}
-
-	/*
-	 * Create a structure for each slot, and register that slot
-	 * with the pci_hotplug subsystem.
-	 */
-	for (i = first; i <= last; ++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->bus = bus;
-		slot->number = i;
-		slot->devfn = PCI_DEVFN(i, 0);
-
-		hotplug_slot->private = slot;
-		make_slot_name(slot);
-		hotplug_slot->ops = &cpci_hotplug_slot_ops;
-
-		/*
-		 * Initialize the slot info structure with some known
-		 * good values.
-		 */
-		dbg("initializing slot %s", slot->hotplug_slot->name);
-		info->power_status = cpci_get_power_status(slot);
-		info->attention_status = cpci_get_attention_status(slot);
-
-		dbg("registering slot %s", slot->hotplug_slot->name);
-		status = pci_hp_register(slot->hotplug_slot);
-		if(status) {
-			err("pci_hp_register failed with error %d", status);
-			kfree(info);
-			kfree(name);
-			kfree(hotplug_slot);
-			kfree(slot);
-			return status;
-		}
-
-		/* Add slot to our internal list */
-		spin_lock(&list_lock);
-		list_add(&slot->slot_list, &slot_list);
-		slots++;
-		spin_unlock(&list_lock);
-	}
-	return status;
-}
-
-int
-cpci_hp_unregister_bus(struct pci_bus *bus)
-{
-	struct slot *slot;
-	struct list_head *tmp;
-	int status;
-
-	if(!bus) {
-		return -ENODEV;
-	}
-
-	spin_lock(&list_lock);
-	if(!slots) {
-		spin_unlock(&list_lock);
-		return -1;
-	}
-	list_for_each(tmp, &slot_list) {
-		slot = list_entry(tmp, struct slot, slot_list);
-		if(slot->bus == bus) {
-			dbg("deregistering slot %s", slot->hotplug_slot->name);
-			status = pci_hp_deregister(slot->hotplug_slot);
-			if(status) {
-				err("pci_hp_deregister failed with error %d",
-				    status);
-				return status;
-			}
-
-			list_del(&slot->slot_list);
-			kfree(slot->hotplug_slot->info);
-			kfree(slot->hotplug_slot->name);
-			kfree(slot->hotplug_slot);
-			kfree(slot);
-
-			slots--;
-		}
-	}
-	spin_unlock(&list_lock);
-	return 0;
-}
-
-struct slot *
-cpci_find_slot(struct pci_bus *bus, unsigned int devfn)
-{
-	struct slot *slot;
-	struct slot *found;
-	struct list_head *tmp;
-
-	if(!bus) {
-		return NULL;
-	}
-
-	spin_lock(&list_lock);
-	if(!slots) {
-		spin_unlock(&list_lock);
-		return NULL;
-	}
-	found = NULL;
-	list_for_each(tmp, &slot_list) {
-		slot = list_entry(tmp, struct slot, slot_list);
-		if(slot->bus == bus && slot->devfn == devfn) {
-			found = slot;
-			break;
-		}
-	}
-	spin_unlock(&list_lock);
-	return found;
-}
-
-/* This is the interrupt mode interrupt handler */
-irqreturn_t
-cpci_hp_intr(int irq, void *data, struct pt_regs *regs)
-{
-	dbg("entered cpci_hp_intr");
-
-	/* Check to see if it was our interrupt */
-	if((controller->irq_flags & SA_SHIRQ) &&
-	    !controller->ops->check_irq(controller->dev_id)) {
-		dbg("exited cpci_hp_intr, not our interrupt");
-		return IRQ_NONE;
-	}
-
-	/* Disable ENUM interrupt */
-	controller->ops->disable_irq();
-
-	/* Trigger processing by the event thread */
-	dbg("Signal event_semaphore");
-	up(&event_semaphore);
-	dbg("exited cpci_hp_intr");
-	return IRQ_HANDLED;
-}
-
-/*
- * According to PICMG 2.12 R2.0, section 6.3.2, upon
- * initialization, the system driver shall clear the
- * INS bits of the cold-inserted devices.
- */
-static int
-init_slots(void)
-{
-	struct slot *slot;
-	struct list_head *tmp;
-	struct pci_dev* dev;
-
-	dbg("%s - enter", __FUNCTION__);
-	spin_lock(&list_lock);
-	if(!slots) {
-		spin_unlock(&list_lock);
-		return -1;
-	}
-	list_for_each(tmp, &slot_list) {
-		slot = list_entry(tmp, struct slot, slot_list);
-		dbg("%s - looking at slot %s",
-		    __FUNCTION__, slot->hotplug_slot->name);
-		if(cpci_check_and_clear_ins(slot)) {
-			dbg("%s - cleared INS for slot %s",
-			    __FUNCTION__, slot->hotplug_slot->name);
-			dev = pci_find_slot(slot->bus->number, PCI_DEVFN(slot->number, 0));
-			if(dev) {
-				if(update_adapter_status(slot->hotplug_slot, 1)) {
-					warn("failure to update adapter file");
-				}
-				if(update_latch_status(slot->hotplug_slot, 1)) {
-					warn("failure to update latch file");
-				}
-				slot->dev = dev;
-			} else {
-				err("%s - no driver attached to device in slot %s",
-				    __FUNCTION__, slot->hotplug_slot->name);
-			}
-		}
-	}
-	spin_unlock(&list_lock);
-	dbg("%s - exit", __FUNCTION__);
-	return 0;
-}
-
-static int
-check_slots(void)
-{
-	struct slot *slot;
-	struct list_head *tmp;
-	int extracted;
-	int inserted;
-
-	spin_lock(&list_lock);
-	if(!slots) {
-		spin_unlock(&list_lock);
-		err("no slots registered, shutting down");
-		return -1;
-	}
-	extracted = inserted = 0;
-	list_for_each(tmp, &slot_list) {
-		slot = list_entry(tmp, struct slot, slot_list);
-		dbg("%s - looking at slot %s",
-		    __FUNCTION__, slot->hotplug_slot->name);
-		if(cpci_check_and_clear_ins(slot)) {
-			u16 hs_csr;
-
-			/* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# twice... */
-			if(slot->dev) {
-				warn("slot %s already inserted", slot->hotplug_slot->name);
-				inserted++;
-				continue;
-			}
-
-			/* Process insertion */
-			dbg("%s - slot %s inserted",
-			    __FUNCTION__, slot->hotplug_slot->name);
-
-			/* GSM, debug */
-			hs_csr = cpci_get_hs_csr(slot);
-			dbg("%s - slot %s HS_CSR (1) = %04x",
-			    __FUNCTION__, slot->hotplug_slot->name, hs_csr);
-
-			/* Configure device */
-			dbg("%s - configuring slot %s",
-			    __FUNCTION__, slot->hotplug_slot->name);
-			if(cpci_configure_slot(slot)) {
-				err("%s - could not configure slot %s",
-				    __FUNCTION__, slot->hotplug_slot->name);
-				continue;
-			}
-			dbg("%s - finished configuring slot %s",
-			    __FUNCTION__, slot->hotplug_slot->name);
-
-			/* GSM, debug */
-			hs_csr = cpci_get_hs_csr(slot);
-			dbg("%s - slot %s HS_CSR (2) = %04x",
-			    __FUNCTION__, slot->hotplug_slot->name, hs_csr);
-
-			if(update_latch_status(slot->hotplug_slot, 1)) {
-				warn("failure to update latch file");
-			}
-
-			if(update_adapter_status(slot->hotplug_slot, 1)) {
-				warn("failure to update adapter file");
-			}
-
-			cpci_led_off(slot);
-
-			/* GSM, debug */
-			hs_csr = cpci_get_hs_csr(slot);
-			dbg("%s - slot %s HS_CSR (3) = %04x",
-			    __FUNCTION__, slot->hotplug_slot->name, hs_csr);
-
-			inserted++;
-		} else if(cpci_check_ext(slot)) {
-			u16 hs_csr;
-
-			/* Process extraction request */
-			dbg("%s - slot %s extracted",
-			    __FUNCTION__, slot->hotplug_slot->name);
-
-			/* GSM, debug */
-			hs_csr = cpci_get_hs_csr(slot);
-			dbg("%s - slot %s HS_CSR = %04x",
-			    __FUNCTION__, slot->hotplug_slot->name, hs_csr);
-
-			if(!slot->extracting) {
-				if(update_latch_status(slot->hotplug_slot, 0)) {
-					warn("failure to update latch file");
-				}
-				slot->extracting = 1;
-			}
-			extracted++;
-		}
-	}
-	spin_unlock(&list_lock);
-	if(inserted || extracted) {
-		return extracted;
-	}
-	else {
-		err("cannot find ENUM# source, shutting down");
-		return -1;
-	}
-}
-
-/* This is the interrupt mode worker thread body */
-static int
-event_thread(void *data)
-{
-	int rc;
-	struct slot *slot;
-	struct list_head *tmp;
-
-	lock_kernel();
-	daemonize("cpci_hp_eventd");
-	unlock_kernel();
-
-	dbg("%s - event thread started", __FUNCTION__);
-	while(1) {
-		dbg("event thread sleeping");
-		down_interruptible(&event_semaphore);
-		dbg("event thread woken, thread_finished = %d",
-		    thread_finished);
-		if(thread_finished || signal_pending(current))
-			break;
-		while(controller->ops->query_enum()) {
-			rc = check_slots();
-			if(rc > 0) {
-				/* Give userspace a chance to handle extraction */
-				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout(HZ / 2);
-			} else if(rc < 0) {
-				dbg("%s - error checking slots", __FUNCTION__);
-				thread_finished = 1;
-				break;
-			}
-		}
-		/* Check for someone yanking out a board */
-		list_for_each(tmp, &slot_list) {
-			slot = list_entry(tmp, struct slot, slot_list);
-			if(slot->extracting) {
-				/*
-				 * Hmmm, we're likely hosed at this point, should we
-				 * bother trying to tell the driver or not?
-				 */
-				err("card in slot %s was improperly removed",
-				    slot->hotplug_slot->name);
-				if(update_adapter_status(slot->hotplug_slot, 0)) {
-					warn("failure to update adapter file");
-				}
-				slot->extracting = 0;
-			}
-		}
-
-		/* Re-enable ENUM# interrupt */
-		dbg("%s - re-enabling irq", __FUNCTION__);
-		controller->ops->enable_irq();
-	}
-
-	dbg("%s - event thread signals exit", __FUNCTION__);
-	up(&thread_exit);
-	return 0;
-}
-
-/* This is the polling mode worker thread body */
-static int
-poll_thread(void *data)
-{
-	int rc;
-	struct slot *slot;
-	struct list_head *tmp;
-
-	lock_kernel();
-	daemonize("cpci_hp_polld");
-	unlock_kernel();
-
-	while(1) {
-		if(thread_finished || signal_pending(current))
-			break;
-
-		while(controller->ops->query_enum()) {
-			rc = check_slots();
-			if(rc > 0) {
-				/* Give userspace a chance to handle extraction */
-				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout(HZ / 2);
-			} else if(rc < 0) {
-				dbg("%s - error checking slots", __FUNCTION__);
-				thread_finished = 1;
-				break;
-			}
-		}
-		/* Check for someone yanking out a board */
-		list_for_each(tmp, &slot_list) {
-			slot = list_entry(tmp, struct slot, slot_list);
-			if(slot->extracting) {
-				/*
-				 * Hmmm, we're likely hosed at this point, should we
-				 * bother trying to tell the driver or not?
-				 */
-				err("card in slot %s was improperly removed",
-				    slot->hotplug_slot->name);
-				if(update_adapter_status(slot->hotplug_slot, 0)) {
-					warn("failure to update adapter file");
-				}
-				slot->extracting = 0;
-			}
-		}
-
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ / 10);
-	}
-	dbg("poll thread signals exit");
-	up(&thread_exit);
-	return 0;
-}
-
-static int
-cpci_start_thread(void)
-{
-	int pid;
-
-	/* initialize our semaphores */
-	init_MUTEX_LOCKED(&event_semaphore);
-	init_MUTEX_LOCKED(&thread_exit);
-	thread_finished = 0;
-
-	if(controller->irq) {
-		pid = kernel_thread(event_thread, 0, 0);
-	} else {
-		pid = kernel_thread(poll_thread, 0, 0);
-	}
-	if(pid < 0) {
-		err("Can't start up our thread");
-		return -1;
-	}
-	dbg("Our thread pid = %d", pid);
-	return 0;
-}
-
-static void
-cpci_stop_thread(void)
-{
-	thread_finished = 1;
-	dbg("thread finish command given");
-	if(controller->irq) {
-		up(&event_semaphore);
-	}
-	dbg("wait for thread to exit");
-	down(&thread_exit);
-}
-
-int
-cpci_hp_register_controller(struct cpci_hp_controller *new_controller)
-{
-	int status = 0;
-
-	if(!controller) {
-		controller = new_controller;
-		if(controller->irq) {
-			if(request_irq(controller->irq,
-					cpci_hp_intr,
-					controller->irq_flags,
-					MY_NAME, controller->dev_id)) {
-				err("Can't get irq %d for the hotplug cPCI controller", controller->irq);
-				status = -ENODEV;
-			}
-			dbg("%s - acquired controller irq %d", __FUNCTION__,
-			    controller->irq);
-		}
-	} else {
-		err("cPCI hotplug controller already registered");
-		status = -1;
-	}
-	return status;
-}
-
-int
-cpci_hp_unregister_controller(struct cpci_hp_controller *old_controller)
-{
-	int status = 0;
-
-	if(controller) {
-		if(!thread_finished) {
-			cpci_stop_thread();
-		}
-		if(controller->irq) {
-			free_irq(controller->irq, controller->dev_id);
-		}
-		controller = NULL;
-	} else {
-		status = -ENODEV;
-	}
-	return status;
-}
-
-int
-cpci_hp_start(void)
-{
-	static int first = 1;
-	int status;
-
-	dbg("%s - enter", __FUNCTION__);
-	if(!controller) {
-		return -ENODEV;
-	}
-
-	spin_lock(&list_lock);
-	if(!slots) {
-		spin_unlock(&list_lock);
-		return -ENODEV;
-	}
-	spin_unlock(&list_lock);
-
-	if(first) {
-		status = init_slots();
-		if(status) {
-			return status;
-		}
-		first = 0;
-	}
-
-	status = cpci_start_thread();
-	if(status) {
-		return status;
-	}
-	dbg("%s - thread started", __FUNCTION__);
-
-	if(controller->irq) {
-		/* Start enum interrupt processing */
-		dbg("%s - enabling irq", __FUNCTION__);
-		controller->ops->enable_irq();
-	}
-	dbg("%s - exit", __FUNCTION__);
-	return 0;
-}
-
-int
-cpci_hp_stop(void)
-{
-	if(!controller) {
-		return -ENODEV;
-	}
-
-	if(controller->irq) {
-		/* Stop enum interrupt processing */
-		dbg("%s - disabling irq", __FUNCTION__);
-		controller->ops->disable_irq();
-	}
-	cpci_stop_thread();
-	return 0;
-}
-
-static void __exit
-cleanup_slots(void)
-{
-	struct list_head *tmp;
-	struct slot *slot;
-
-	/*
-	 * Unregister all of our slots with the pci_hotplug subsystem,
-	 * and free up all memory that we had allocated.
-	 */
-	spin_lock(&list_lock);
-	if(!slots) {
-		goto null_cleanup;
-	}
-	list_for_each(tmp, &slot_list) {
-		slot = list_entry(tmp, struct slot, slot_list);
-		list_del(&slot->slot_list);
-		pci_hp_deregister(slot->hotplug_slot);
-		kfree(slot->hotplug_slot->info);
-		kfree(slot->hotplug_slot->name);
-		kfree(slot->hotplug_slot);
-		kfree(slot);
-	}
-      null_cleanup:
-	spin_unlock(&list_lock);
-	return;
-}
-
-int __init
-cpci_hotplug_init(int debug)
-{
-	spin_lock_init(&list_lock);
-	cpci_debug = debug;
-
-	info(DRIVER_DESC " version: " DRIVER_VERSION);
-	return 0;
-}
-
-void __exit
-cpci_hotplug_exit(void)
-{
-	/*
-	 * Clean everything up.
-	 */
-	cleanup_slots();
-}
-
-
-EXPORT_SYMBOL_GPL(cpci_hp_register_controller);
-EXPORT_SYMBOL_GPL(cpci_hp_unregister_controller);
-EXPORT_SYMBOL_GPL(cpci_hp_register_bus);
-EXPORT_SYMBOL_GPL(cpci_hp_unregister_bus);
-EXPORT_SYMBOL_GPL(cpci_find_slot);
-EXPORT_SYMBOL_GPL(cpci_hp_start);
-EXPORT_SYMBOL_GPL(cpci_hp_stop);
diff -Nru a/drivers/hotplug/cpci_hotplug_pci.c b/drivers/hotplug/cpci_hotplug_pci.c
--- a/drivers/hotplug/cpci_hotplug_pci.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,647 +0,0 @@
-/*
- * CompactPCI Hot Plug Driver PCI functions
- *
- * Copyright (c) 2002 by SOMA Networks, Inc.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <scottm@somanetworks.com>
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/proc_fs.h>
-#include "pci_hotplug.h"
-#include "cpci_hotplug.h"
-
-#if !defined(CONFIG_HOTPLUG_CPCI_MODULE)
-#define MY_NAME	"cpci_hotplug"
-#else
-#define MY_NAME	THIS_MODULE->name
-#endif
-
-extern int cpci_debug;
-
-#define dbg(format, arg...)					\
-	do {							\
-		if(cpci_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 ROUND_UP(x, a)		(((x) + (a) - 1) & ~((a) - 1))
-
-
-u8 cpci_get_attention_status(struct slot* slot)
-{
-	int hs_cap;
-	u16 hs_csr;
-
-	hs_cap = pci_bus_find_capability(slot->bus,
-					 slot->devfn,
-					 PCI_CAP_ID_CHSWP);
-	if(!hs_cap) {
-		return 0;
-	}
-
-	if(pci_bus_read_config_word(slot->bus,
-				     slot->devfn,
-				     hs_cap + 2,
-				     &hs_csr)) {
-		return 0;
-	}
-	return hs_csr & 0x0008 ? 1 : 0;
-}
-
-int cpci_set_attention_status(struct slot* slot, int status)
-{
-	int hs_cap;
-	u16 hs_csr;
-
-	hs_cap = pci_bus_find_capability(slot->bus,
-					 slot->devfn,
-					 PCI_CAP_ID_CHSWP);
-	if(!hs_cap) {
-		return 0;
-	}
-
-	if(pci_bus_read_config_word(slot->bus,
-				     slot->devfn,
-				     hs_cap + 2,
-				     &hs_csr)) {
-		return 0;
-	}
-	if(status) {
-		hs_csr |= HS_CSR_LOO;
-	} else {
-		hs_csr &= ~HS_CSR_LOO;
-	}
-	if(pci_bus_write_config_word(slot->bus,
-				      slot->devfn,
-				      hs_cap + 2,
-				      hs_csr)) {
-		return 0;
-	}
-	return 1;
-}
-
-u16 cpci_get_hs_csr(struct slot* slot)
-{
-	int hs_cap;
-	u16 hs_csr;
-
-	hs_cap = pci_bus_find_capability(slot->bus,
-					 slot->devfn,
-					 PCI_CAP_ID_CHSWP);
-	if(!hs_cap) {
-		return 0xFFFF;
-	}
-
-	if(pci_bus_read_config_word(slot->bus,
-				     slot->devfn,
-				     hs_cap + 2,
-				     &hs_csr)) {
-		return 0xFFFF;
-	}
-	return hs_csr;
-}
-
-u16 cpci_set_hs_csr(struct slot* slot, u16 hs_csr)
-{
-	int hs_cap;
-	u16 new_hs_csr;
-
-	hs_cap = pci_bus_find_capability(slot->bus,
-					 slot->devfn,
-					 PCI_CAP_ID_CHSWP);
-	if(!hs_cap) {
-		return 0xFFFF;
-	}
-
-	/* Write out the new value */
-	if(pci_bus_write_config_word(slot->bus,
-				      slot->devfn,
-				      hs_cap + 2,
-				      hs_csr)) {
-		return 0xFFFF;
-	}
-
-	/* Read back what we just wrote out */
-	if(pci_bus_read_config_word(slot->bus,
-				     slot->devfn,
-				     hs_cap + 2,
-				     &new_hs_csr)) {
-		return 0xFFFF;
-	}
-	return new_hs_csr;
-}
-
-int cpci_check_and_clear_ins(struct slot* slot)
-{
-	int hs_cap;
-	u16 hs_csr;
-	int ins = 0;
-
-	hs_cap = pci_bus_find_capability(slot->bus,
-					 slot->devfn,
-					 PCI_CAP_ID_CHSWP);
-	if(!hs_cap) {
-		return 0;
-	}
-	if(pci_bus_read_config_word(slot->bus,
-				     slot->devfn,
-				     hs_cap + 2,
-				     &hs_csr)) {
-		return 0;
-	}
-	if(hs_csr & HS_CSR_INS) {
-		/* Clear INS (by setting it) */
-		if(pci_bus_write_config_word(slot->bus,
-					      slot->devfn,
-					      hs_cap + 2,
-					      hs_csr)) {
-			ins = 0;
-		}
-		ins = 1;
-	}
-	return ins;
-}
-
-int cpci_check_ext(struct slot* slot)
-{
-	int hs_cap;
-	u16 hs_csr;
-	int ext = 0;
-
-	hs_cap = pci_bus_find_capability(slot->bus,
-					 slot->devfn,
-					 PCI_CAP_ID_CHSWP);
-	if(!hs_cap) {
-		return 0;
-	}
-	if(pci_bus_read_config_word(slot->bus,
-				     slot->devfn,
-				     hs_cap + 2,
-				     &hs_csr)) {
-		return 0;
-	}
-	if(hs_csr & HS_CSR_EXT) {
-		ext = 1;
-	}
-	return ext;
-}
-
-int cpci_clear_ext(struct slot* slot)
-{
-	int hs_cap;
-	u16 hs_csr;
-
-	hs_cap = pci_bus_find_capability(slot->bus,
-					 slot->devfn,
-					 PCI_CAP_ID_CHSWP);
-	if(!hs_cap) {
-		return -ENODEV;
-	}
-	if(pci_bus_read_config_word(slot->bus,
-				     slot->devfn,
-				     hs_cap + 2,
-				     &hs_csr)) {
-		return -ENODEV;
-	}
-	if(hs_csr & HS_CSR_EXT) {
-		/* Clear EXT (by setting it) */
-		if(pci_bus_write_config_word(slot->bus,
-					      slot->devfn,
-					      hs_cap + 2,
-					      hs_csr)) {
-			return -ENODEV;
-		}
-	}
-	return 0;
-}
-
-int cpci_led_on(struct slot* slot)
-{
-	int hs_cap;
-	u16 hs_csr;
-
-	hs_cap = pci_bus_find_capability(slot->bus,
-					 slot->devfn,
-					 PCI_CAP_ID_CHSWP);
-	if(!hs_cap) {
-		return -ENODEV;
-	}
-	if(pci_bus_read_config_word(slot->bus,
-				     slot->devfn,
-				     hs_cap + 2,
-				     &hs_csr)) {
-		return -ENODEV;
-	}
-	if((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) {
-		/* Set LOO */
-		hs_csr |= HS_CSR_LOO;
-		if(pci_bus_write_config_word(slot->bus,
-					      slot->devfn,
-					      hs_cap + 2,
-					      hs_csr)) {
-			err("Could not set LOO for slot %s",
-			    slot->hotplug_slot->name);
-			return -ENODEV;
-		}
-	}
-	return 0;
-}
-
-int cpci_led_off(struct slot* slot)
-{
-	int hs_cap;
-	u16 hs_csr;
-
-	hs_cap = pci_bus_find_capability(slot->bus,
-					 slot->devfn,
-					 PCI_CAP_ID_CHSWP);
-	if(!hs_cap) {
-		return -ENODEV;
-	}
-	if(pci_bus_read_config_word(slot->bus,
-				     slot->devfn,
-				     hs_cap + 2,
-				     &hs_csr)) {
-		return -ENODEV;
-	}
-	if(hs_csr & HS_CSR_LOO) {
-		/* Clear LOO */
-		hs_csr &= ~HS_CSR_LOO;
-		if(pci_bus_write_config_word(slot->bus,
-					      slot->devfn,
-					      hs_cap + 2,
-					      hs_csr)) {
-			err("Could not clear LOO for slot %s",
-			    slot->hotplug_slot->name);
-			return -ENODEV;
-		}
-	}
-	return 0;
-}
-
-
-/*
- * Device configuration functions
- */
-
-static int cpci_configure_dev(struct pci_bus *bus, struct pci_dev *dev)
-{
-	u8 irq_pin;
-	int r;
-
-	dbg("%s - enter", __FUNCTION__);
-
-	/* NOTE: device already setup from prior scan */
-
-	/* FIXME: How would we know if we need to enable the expansion ROM? */
-	pci_write_config_word(dev, PCI_ROM_ADDRESS, 0x00L);
-
-	/* Assign resources */
-	dbg("assigning resources for %02x:%02x.%x",
-	    dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
-	for (r = 0; r < 6; r++) {
-		struct resource *res = dev->resource + r;
-		if(res->flags)
-			pci_assign_resource(dev, r);
-	}
-	dbg("finished assigning resources for %02x:%02x.%x",
-	    dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
-
-	/* Does this function have an interrupt at all? */
-	dbg("checking for function interrupt");
-	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
-	if(irq_pin) {
-		dbg("function uses interrupt pin %d", irq_pin);
-	}
-
-	/*
-	 * Need to explicitly set irq field to 0 so that it'll get assigned
-	 * by the pcibios platform dependent code called by pci_enable_device.
-	 */
-	dev->irq = 0;
-
-	dbg("enabling device");
-	pci_enable_device(dev);	/* XXX check return */
-	dbg("now dev->irq = %d", dev->irq);
-	if(irq_pin && dev->irq) {
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-	}
-
-	/* Can't use pci_insert_device at the moment, do it manually for now */
-	pci_proc_attach_device(dev);
-	dbg("notifying drivers");
-	//pci_announce_device_to_drivers(dev);
-	dbg("%s - exit", __FUNCTION__);
-	return 0;
-}
-
-static int cpci_configure_bridge(struct pci_bus* bus, struct pci_dev* dev)
-{
-	int rc;
-	struct pci_bus* child;
-	struct resource* r;
-	u8 max, n;
-	u16 command;
-
-	dbg("%s - enter", __FUNCTION__);
-
-	/* Do basic bridge initialization */
-	rc = pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
-	if(rc) {
-		printk(KERN_ERR "%s - write of PCI_LATENCY_TIMER failed\n", __FUNCTION__);
-	}
-	rc = pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 0x40);
-	if(rc) {
-		printk(KERN_ERR "%s - write of PCI_SEC_LATENCY_TIMER failed\n", __FUNCTION__);
-	}
-	rc = pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4);
-	if(rc) {
-		printk(KERN_ERR "%s - write of PCI_CACHE_LINE_SIZE failed\n", __FUNCTION__);
-	}
-
-	/*
-	 * Set parent bridge's subordinate field so that configuration space
-	 * access will work in pci_scan_bridge and friends.
-	 */
-	max = pci_max_busnr();
-	bus->subordinate = max + 1;
-	pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, max + 1);
-
-	/* Scan behind bridge */
-	n = pci_scan_bridge(bus, dev, max, 2);
-	child = pci_find_bus(max + 1);
-	if (!child)
-		return -ENODEV;
-#ifdef CONFIG_PROC_FS
-	pci_proc_attach_bus(child);
-#endif
-	/*
-	 * Update parent bridge's subordinate field if there were more bridges
-	 * behind the bridge that was scanned.
-	 */
-	if(n > max) {
-		bus->subordinate = n;
-		pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, n);
-	}
-
-	/*
-	 * Update the bridge resources of the bridge to accommodate devices
-	 * behind it.
-	 */
-	pci_bus_size_bridges(child);
-	pci_bus_assign_resources(child);
-
-	/* Enable resource mapping via command register */
-	command = PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
-	r = child->resource[0];
-	if(r && r->start) {
-		command |= PCI_COMMAND_IO;
-	}
-	r = child->resource[1];
-	if(r && r->start) {
-		command |= PCI_COMMAND_MEMORY;
-	}
-	r = child->resource[2];
-	if(r && r->start) {
-		command |= PCI_COMMAND_MEMORY;
-	}
-	rc = pci_write_config_word(dev, PCI_COMMAND, command);
-	if(rc) {
-		err("Error setting command register");
-		return rc;
-	}
-
-	/* Set bridge control register */
-	command = PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_NO_ISA;
-	rc = pci_write_config_word(dev, PCI_BRIDGE_CONTROL, command);
-	if(rc) {
-		err("Error setting bridge control register");
-		return rc;
-	}
-	dbg("%s - exit", __FUNCTION__);
-	return 0;
-}
-
-static int configure_visit_pci_dev(struct pci_dev_wrapped *wrapped_dev,
-			struct pci_bus_wrapped *wrapped_bus)
-{
-	int rc;
-	struct pci_dev *dev = wrapped_dev->dev;
-	struct pci_bus *bus = wrapped_bus->bus;
-	struct slot* slot;
-
-	dbg("%s - enter", __FUNCTION__);
-
-	/*
-	 * We need to fix up the hotplug representation with the Linux
-	 * representation.
-	 */
-	slot = cpci_find_slot(dev->bus, dev->devfn);
-	if(slot) {
-		slot->dev = dev;
-	}
-
-	/* If it's a bridge, scan behind it for devices */
-	if(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-		rc = cpci_configure_bridge(bus, dev);
-		if(rc)
-			return rc;
-	}
-
-	/* Actually configure device */
-	if(dev) {
-		rc = cpci_configure_dev(bus, dev);
-		if(rc)
-			return rc;
-	}
-	dbg("%s - exit", __FUNCTION__);
-	return 0;
-}
-
-static int unconfigure_visit_pci_dev_phase2(struct pci_dev_wrapped *wrapped_dev,
-					    struct pci_bus_wrapped *wrapped_bus)
-{
-	struct pci_dev *dev = wrapped_dev->dev;
-	struct slot* slot;
-
-	dbg("%s - enter", __FUNCTION__);
-	if(!dev)
-		return -ENODEV;
-
-	/* Remove the Linux representation */
-	if(pci_remove_device_safe(dev) == 0) {
-		kfree(dev);
-	} else {
-		err("Could not remove device\n");
-		return -1;
-	}
-
-	/*
-	 * Now remove the hotplug representation.
-	 */
-	slot = cpci_find_slot(dev->bus, dev->devfn);
-	if(slot) {
-		slot->dev = NULL;
-	} else {
-		dbg("No hotplug representation for %02x:%02x.%x",
-		    dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
-	}
-	dbg("%s - exit", __FUNCTION__);
-	return 0;
-}
-
-static int unconfigure_visit_pci_bus_phase2(struct pci_bus_wrapped *wrapped_bus,
-					    struct pci_dev_wrapped *wrapped_dev)
-{
-	struct pci_bus *bus = wrapped_bus->bus;
-	struct pci_bus *parent = bus->self->bus;
-
-	dbg("%s - enter", __FUNCTION__);
-
-	/* The cleanup code for proc entries regarding buses should be in the kernel... */
-	if(bus->procdir)
-		dbg("detach_pci_bus %s", bus->procdir->name);
-	pci_proc_detach_bus(bus);
-
-	/* The cleanup code should live in the kernel... */
-	bus->self->subordinate = NULL;
-
-	/* unlink from parent bus */
-	list_del(&bus->node);
-
-	/* Now, remove */
-	if(bus)
-		kfree(bus);
-
-	/* Update parent's subordinate field */
-	if(parent) {
-		u8 n = pci_bus_max_busnr(parent);
-		if(n < parent->subordinate) {
-			parent->subordinate = n;
-			pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, n);
-		}
-	}
-	dbg("%s - exit", __FUNCTION__);
-	return 0;
-}
-
-static struct pci_visit configure_functions = {
-	.visit_pci_dev = configure_visit_pci_dev,
-};
-
-static struct pci_visit unconfigure_functions_phase2 = {
-	.post_visit_pci_bus = unconfigure_visit_pci_bus_phase2,
-	.post_visit_pci_dev = unconfigure_visit_pci_dev_phase2
-};
-
-
-int cpci_configure_slot(struct slot* slot)
-{
-	int rc = 0;
-
-	dbg("%s - enter", __FUNCTION__);
-
-	if(slot->dev == NULL) {
-		dbg("pci_dev null, finding %02x:%02x:%x",
-		    slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn));
-		slot->dev = pci_find_slot(slot->bus->number, slot->devfn);
-	}
-
-	/* Still NULL? Well then scan for it! */
-	if(slot->dev == NULL) {
-		dbg("pci_dev still null");
-
-		/*
-		 * This will generate pci_dev structures for all functions, but
-		 * we will only call this case when lookup fails.
-		 */
-		slot->dev = pci_scan_slot(slot->bus, slot->devfn);
-		if(slot->dev == NULL) {
-			err("Could not find PCI device for slot %02x", slot->number);
-			return 0;
-		}
-	}
-	dbg("slot->dev = %p", slot->dev);
-	if(slot->dev) {
-		struct pci_dev *dev;
-		struct pci_dev_wrapped wrapped_dev;
-		struct pci_bus_wrapped wrapped_bus;
-		int i;
-
-		memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped));
-		memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped));
-
-		for (i = 0; i < 8; i++) {
-			dev = pci_find_slot(slot->bus->number,
-					    PCI_DEVFN(PCI_SLOT(slot->dev->devfn), i));
-			if(!dev)
-				continue;
-			wrapped_dev.dev = dev;
-			wrapped_bus.bus = slot->dev->bus;
-			rc = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus);
-		}
-	}
-
-	dbg("%s - exit, rc = %d", __FUNCTION__, rc);
-	return rc;
-}
-
-int cpci_unconfigure_slot(struct slot* slot)
-{
-	int rc = 0;
-	int i;
-	struct pci_dev_wrapped wrapped_dev;
-	struct pci_bus_wrapped wrapped_bus;
-	struct pci_dev *dev;
-
-	dbg("%s - enter", __FUNCTION__);
-
-	if(!slot->dev) {
-		err("No device for slot %02x\n", slot->number);
-		return -ENODEV;
-	}
-
-	memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped));
-	memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped));
-
-	for (i = 0; i < 8; i++) {
-		dev = pci_find_slot(slot->bus->number,
-				    PCI_DEVFN(PCI_SLOT(slot->devfn), i));
-		if(dev) {
-			wrapped_dev.dev = dev;
-			wrapped_bus.bus = dev->bus;
-			dbg("%s - unconfigure phase 2", __FUNCTION__);
-			rc = pci_visit_dev(&unconfigure_functions_phase2,
-					   &wrapped_dev, &wrapped_bus);
-			if(rc)
-				break;
-		}
-	}
-	dbg("%s - exit, rc = %d", __FUNCTION__, rc);
-	return rc;
-}
diff -Nru a/drivers/hotplug/cpcihp_generic.c b/drivers/hotplug/cpcihp_generic.c
--- a/drivers/hotplug/cpcihp_generic.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,290 +0,0 @@
-/*
- * cpcihp_generic.c
- *
- * Generic port I/O CompactPCI driver
- *
- * Copyright 2002 SOMA Networks, Inc.
- * Copyright 2001 Intel San Luis Obispo
- * Copyright 2000,2001 MontaVista Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * This generic CompactPCI hotplug driver should allow using the PCI hotplug
- * mechanism on any CompactPCI board that exposes the #ENUM signal as a bit
- * in a system register that can be read through standard port I/O.
- *
- * Send feedback to <scottm@somanetworks.com>
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include "cpci_hotplug.h"
-
-#define DRIVER_VERSION	"0.1"
-#define DRIVER_AUTHOR	"Scott Murray <scottm@somanetworks.com>"
-#define DRIVER_DESC	"Generic port I/O CompactPCI Hot Plug Driver"
-
-#if !defined(CONFIG_HOTPLUG_CPCI_GENERIC_MODULE)
-#define MY_NAME	"cpcihp_generic"
-#else
-#define MY_NAME	THIS_MODULE->name
-#endif
-
-#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)
-
-/* local variables */
-static int debug;
-static char* bridge;
-static u8 bridge_busnr;
-static u8 bridge_slot;
-static struct pci_bus *bus;
-static u8 first_slot;
-static u8 last_slot;
-static u16 port;
-static unsigned int enum_bit;
-static u8 enum_mask;
-
-static struct cpci_hp_controller_ops generic_hpc_ops;
-static struct cpci_hp_controller generic_hpc;
-
-/* The following allows configuring the driver when it's compiled into the kernel */
-#ifndef MODULE
-static int __init cpcihp_generic_setup(char* str)
-{
-	char* p;
-	unsigned long tmp;
-
-	if(!str)
-		return -EINVAL;
-	bridge = str;
-
-	p = strchr(str, ',');
-	str = p + 1;
-	if(!(p && *str && *p == ','))
-		goto setup_error;
-	tmp = simple_strtoul(str, &p, 0);
-	if(p == str || tmp > 0xff) {
-		err("hotplug bus first slot number out of range");
-		goto setup_error;
-	}
-	first_slot = (u8) tmp;
-
-	str = p + 1;		
-	if(!(*str && *p == ','))
-		return -EINVAL;
-	tmp = simple_strtoul(str, &p, 0);
-	if(p == str || tmp > 0xff) {
-		err("hotplug bus last slot number out of range");
-		goto setup_error;
-	}
-	last_slot = (u8) tmp;
-
-	str = p + 1;
-	if(!(*str && *p == ','))
-		goto setup_error;
-	tmp = simple_strtoul(str, &p, 0);
-	if(p == str || tmp > 0xffff) {
-		err("port number out of range");
-		goto setup_error;
-	}
-	port = (u16) tmp;
-
-	str = p + 1;
-	if(!(*str && *p == ','))
-		goto setup_error;
-	tmp = simple_strtoul(str, &p, 0);
-	if(p == str) {
-		err("invalid #ENUM bit number");
-		goto setup_error;
-	}
-	enum_bit = (u8) tmp;
-
-	str = p + 1;
-	if(*str && *p == ',') {
-		tmp = simple_strtoul(str, &p, 0);
-		if(p != str)
-			debug = (int) tmp;
-	}
-	return 0;
-setup_error:
-	bridge = NULL;
-	return -EINVAL;
-}
-
-__setup("cpcihp_generic=", cpcihp_generic_setup);
-#endif
-
-static int __init validate_parameters(void)
-{
-	char* str;
-	char* p;
-	unsigned long tmp;
-
-	if(!bridge) {
-		info("not configured, disabling.");
-		return 1;
-	}
-	str = bridge;
-	if(!*str)
-		return -EINVAL;
-
-	tmp = simple_strtoul(str, &p, 16);
-	if(p == str || tmp > 0xff) {
-		err("Invalid hotplug bus bridge device bus number");
-		return -EINVAL;
-	}
-	bridge_busnr = (u8) tmp;
-	dbg("bridge_busnr = 0x%02x", bridge_busnr);
-	if(*p != ':') {
-		err("Invalid hotplug bus bridge device");
-		return -EINVAL;
-	}
-	str = p + 1;
-	tmp = simple_strtoul(str, &p, 16);
-	if(p == str || tmp > 0x1f) {
-		err("Invalid hotplug bus bridge device slot number");
-		return -EINVAL;
-	}
-	bridge_slot = (u8) tmp;
-	dbg("bridge_slot = 0x%02x", bridge_slot);
-
-	dbg("first_slot = 0x%02x", first_slot);
-	dbg("last_slot = 0x%02x", last_slot);
-	if(!(first_slot && last_slot)) {
-		err("Need to specify first_slot and last_slot");
-		return -EINVAL;
-	}
-	if(last_slot < first_slot) {
-		err("first_slot must be less than last_slot");
-		return -EINVAL;
-	}
-
-	dbg("port = 0x%04x", port);
-	dbg("enum_bit = 0x%02x", enum_bit);
-	if(enum_bit > 7) {
-		err("Invalid #ENUM bit");
-		return -EINVAL;
-	}
-	enum_mask = 1 << enum_bit;
-	return 0;
-}
-
-static int query_enum(void)
-{
-	u8 value;
-
-	value = inb_p(port);
-	return ((value & enum_mask) == enum_mask);
-}
-
-static int __init cpcihp_generic_init(void)
-{
-	int status;
-	struct resource* r;
-	struct pci_dev* dev;
-
-	info(DRIVER_DESC " version: " DRIVER_VERSION);
-	status = validate_parameters();
-	if(status != 0)
-		return status;
-
-	r = request_region(port, 1, "#ENUM hotswap signal register");
-	if(!r)
-		return -EBUSY;
-
-	dev = pci_find_slot(bridge_busnr, PCI_DEVFN(bridge_slot, 0));
-	if(!dev || dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
-		err("Invalid bridge device %s", bridge);
-		return -EINVAL;
-	}
-	bus = dev->subordinate;
-
-	memset(&generic_hpc, 0, sizeof (struct cpci_hp_controller));
-	generic_hpc_ops.query_enum = query_enum;
-	generic_hpc.ops = &generic_hpc_ops;
-
-	status = cpci_hp_register_controller(&generic_hpc);
-	if(status != 0) {
-		err("Could not register cPCI hotplug controller");
-		return -ENODEV;
-	}
-	dbg("registered controller");
-
-	status = cpci_hp_register_bus(bus, first_slot, last_slot);
-	if(status != 0) {
-		err("Could not register cPCI hotplug bus");
-		goto init_bus_register_error;
-	}
-	dbg("registered bus");
-
-	status = cpci_hp_start();
-	if(status != 0) {
-		err("Could not started cPCI hotplug system");
-		goto init_start_error;
-	}
-	dbg("started cpci hp system");
-	return 0;
-init_start_error:
-	cpci_hp_unregister_bus(bus);
-init_bus_register_error:
-	cpci_hp_unregister_controller(&generic_hpc);
-	err("status = %d", status);
-	return status;
-
-}
-
-static void __exit cpcihp_generic_exit(void)
-{
-	cpci_hp_stop();
-	cpci_hp_unregister_bus(bus);
-	cpci_hp_unregister_controller(&generic_hpc);
-	release_region(port, 1);
-}
-
-module_init(cpcihp_generic_init);
-module_exit(cpcihp_generic_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
-MODULE_PARM(bridge, "s");
-MODULE_PARM_DESC(bridge, "Hotswap bus bridge device, <bus>:<slot> (bus and slot are in hexadecimal)");
-MODULE_PARM(first_slot, "b");
-MODULE_PARM_DESC(first_slot, "Hotswap bus first slot number");
-MODULE_PARM(last_slot, "b");
-MODULE_PARM_DESC(last_slot, "Hotswap bus last slot number");
-MODULE_PARM(port, "h");
-MODULE_PARM_DESC(port, "#ENUM signal I/O port");
-MODULE_PARM(enum_bit, "i");
-MODULE_PARM_DESC(enum_bit, "#ENUM signal bit (0-7)");
diff -Nru a/drivers/hotplug/cpcihp_zt5550.c b/drivers/hotplug/cpcihp_zt5550.c
--- a/drivers/hotplug/cpcihp_zt5550.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,306 +0,0 @@
-/*
- * cpcihp_zt5550.c
- *
- * Intel/Ziatech ZT5550 CompactPCI Host Controller driver
- *
- * Copyright 2002 SOMA Networks, Inc.
- * Copyright 2001 Intel San Luis Obispo
- * Copyright 2000,2001 MontaVista Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <scottm@somanetworks.com>
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include "cpci_hotplug.h"
-#include "cpcihp_zt5550.h"
-
-#define DRIVER_VERSION	"0.2"
-#define DRIVER_AUTHOR	"Scott Murray <scottm@somanetworks.com>"
-#define DRIVER_DESC	"ZT5550 CompactPCI Hot Plug Driver"
-
-#if !defined(CONFIG_HOTPLUG_PCI_CPCI_ZT5550_MODULE)
-#define MY_NAME	"cpcihp_zt5550"
-#else
-#define MY_NAME	THIS_MODULE->name
-#endif
-
-#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)
-
-/* local variables */
-static int debug;
-static int poll;
-static struct cpci_hp_controller_ops zt5550_hpc_ops;
-static struct cpci_hp_controller zt5550_hpc;
-
-/* Primary cPCI bus bridge device */
-static struct pci_dev *bus0_dev;
-static struct pci_bus *bus0;
-
-/* Host controller device */
-static struct pci_dev *hc_dev;
-
-/* Host controller register addresses */
-static void *hc_registers;
-static void *csr_hc_index;
-static void *csr_hc_data;
-static void *csr_int_status;
-static void *csr_int_mask;
-
-
-static int zt5550_hc_config(struct pci_dev *pdev)
-{
-	/* Since we know that no boards exist with two HC chips, treat it as an error */
-	if(hc_dev) {
-		err("too many host controller devices?");
-		return -EBUSY;
-	}
-	hc_dev = pdev;
-	dbg("hc_dev = %p", hc_dev);
-	dbg("pci resource start %lx", pci_resource_start(hc_dev, 1));
-	dbg("pci resource len %lx", pci_resource_len(hc_dev, 1));
-
-	if(!request_mem_region(pci_resource_start(hc_dev, 1),
-				pci_resource_len(hc_dev, 1), MY_NAME)) {
-		err("cannot reserve MMIO region");
-		return -ENOMEM;
-	}
-
-	hc_registers =
-	    ioremap(pci_resource_start(hc_dev, 1), pci_resource_len(hc_dev, 1));
-	if(!hc_registers) {
-		err("cannot remap MMIO region %lx @ %lx",
-		    pci_resource_len(hc_dev, 1), pci_resource_start(hc_dev, 1));
-		release_mem_region(pci_resource_start(hc_dev, 1),
-				   pci_resource_len(hc_dev, 1));
-		return -ENODEV;
-	}
-
-	csr_hc_index = hc_registers + CSR_HCINDEX;
-	csr_hc_data = hc_registers + CSR_HCDATA;
-	csr_int_status = hc_registers + CSR_INTSTAT;
-	csr_int_mask = hc_registers + CSR_INTMASK;
-
-	/*
-	 * Disable host control, fault and serial interrupts
-	 */
-	dbg("disabling host control, fault and serial interrupts");
-	writeb((u8) HC_INT_MASK_REG, csr_hc_index);
-	writeb((u8) ALL_INDEXED_INTS_MASK, csr_hc_data);
-	dbg("disabled host control, fault and serial interrupts");
-
-	/*
-	 * Disable timer0, timer1 and ENUM interrupts
-	 */
-	dbg("disabling timer0, timer1 and ENUM interrupts");
-	writeb((u8) ALL_DIRECT_INTS_MASK, csr_int_mask);
-	dbg("disabled timer0, timer1 and ENUM interrupts");
-	return 0;
-}
-
-static int zt5550_hc_cleanup(void)
-{
-	if(!hc_dev)
-		return -ENODEV;
-	release_mem_region(pci_resource_start(hc_dev, 1),
-			   pci_resource_len(hc_dev, 1));
-	return 0;
-}
-
-static int zt5550_hc_query_enum(void)
-{
-	u8 value;
-
-	value = inb_p(ENUM_PORT);
-	return ((value & ENUM_MASK) == ENUM_MASK);
-}
-
-static int zt5550_hc_check_irq(void *dev_id)
-{
-	int ret;
-	u8 reg;
-
-	ret = 0;
-	if(dev_id == zt5550_hpc.dev_id) {
-		reg = readb(csr_int_status);
-		if(reg)
-			ret = 1;
-	}
-	return ret;
-}
-
-static int zt5550_hc_enable_irq(void)
-{
-	u8 reg;
-
-	if(hc_dev == NULL) {
-		return -ENODEV;
-	}
-	reg = readb(csr_int_mask);
-	reg = reg & ~ENUM_INT_MASK;
-	writeb(reg, csr_int_mask);
-	return 0;
-}
-
-int zt5550_hc_disable_irq(void)
-{
-	u8 reg;
-
-	if(hc_dev == NULL) {
-		return -ENODEV;
-	}
-
-	reg = readb(csr_int_mask);
-	reg = reg | ENUM_INT_MASK;
-	writeb(reg, csr_int_mask);
-	return 0;
-}
-
-static int __devinit zt5550_hc_init_one (struct pci_dev *pdev,
-					 const struct pci_device_id *ent)
-{
-	int status;
-
-	status = zt5550_hc_config(pdev);
-	if(status != 0) {
-		return status;
-	}
-	dbg("returned from zt5550_hc_config");
-
-	memset(&zt5550_hpc, 0, sizeof (struct cpci_hp_controller));
-	zt5550_hpc_ops.query_enum = zt5550_hc_query_enum;
-	zt5550_hpc.ops = &zt5550_hpc_ops;
-	if(!poll) {
-		zt5550_hpc.irq = hc_dev->irq;
-		zt5550_hpc.irq_flags = SA_SHIRQ;
-		zt5550_hpc.dev_id = hc_dev;
-
-		zt5550_hpc_ops.enable_irq = zt5550_hc_enable_irq;
-		zt5550_hpc_ops.disable_irq = zt5550_hc_disable_irq;
-		zt5550_hpc_ops.check_irq = zt5550_hc_check_irq;
-	} else {
-		info("using ENUM# polling mode");
-	}
-
-	status = cpci_hp_register_controller(&zt5550_hpc);
-	if(status != 0) {
-		err("could not register cPCI hotplug controller");
-		goto init_hc_error;
-	}
-	dbg("registered controller");
-
-	/* Look for first device matching cPCI bus's bridge vendor and device IDs */
-	if(!(bus0_dev = pci_find_device(PCI_VENDOR_ID_DEC,
-					 PCI_DEVICE_ID_DEC_21154, NULL))) {
-		status = -ENODEV;
-		goto init_register_error;
-	}
-	bus0 = bus0_dev->subordinate;
-
-	status = cpci_hp_register_bus(bus0, 0x0a, 0x0f);
-	if(status != 0) {
-		err("could not register cPCI hotplug bus");
-		goto init_register_error;
-	}
-	dbg("registered bus");
-
-	status = cpci_hp_start();
-	if(status != 0) {
-		err("could not started cPCI hotplug system");
-		cpci_hp_unregister_bus(bus0);
-		goto init_register_error;
-	}
-	dbg("started cpci hp system");
-
-	return 0;
-init_register_error:
-	cpci_hp_unregister_controller(&zt5550_hpc);
-init_hc_error:
-	err("status = %d", status);
-	zt5550_hc_cleanup();
-	return status;
-
-}
-
-static void __devexit zt5550_hc_remove_one(struct pci_dev *pdev)
-{
-	cpci_hp_stop();
-	cpci_hp_unregister_bus(bus0);
-	cpci_hp_unregister_controller(&zt5550_hpc);
-	zt5550_hc_cleanup();
-}
-
-
-static struct pci_device_id zt5550_hc_pci_tbl[] __devinitdata = {
-	{ PCI_VENDOR_ID_ZIATECH, PCI_DEVICE_ID_ZIATECH_5550_HC, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci, zt5550_hc_pci_tbl);
-	
-static struct pci_driver zt5550_hc_driver = {
-	.name		= "zt5550_hc",
-	.id_table	= zt5550_hc_pci_tbl,
-	.probe		= zt5550_hc_init_one,
-	.remove		= __devexit_p(zt5550_hc_remove_one),
-};
-
-static int __init zt5550_init(void)
-{
-	struct resource* r;
-
-	info(DRIVER_DESC " version: " DRIVER_VERSION);
-	r = request_region(ENUM_PORT, 1, "#ENUM hotswap signal register");
-	if(!r)
-		return -EBUSY;
-
-	return pci_module_init(&zt5550_hc_driver);
-}
-
-static void __exit
-zt5550_exit(void)
-{
-	pci_unregister_driver(&zt5550_hc_driver);
-	release_region(ENUM_PORT, 1);
-}
-
-module_init(zt5550_init);
-module_exit(zt5550_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
-MODULE_PARM(poll, "i");
-MODULE_PARM_DESC(poll, "#ENUM polling mode enabled or not");
diff -Nru a/drivers/hotplug/cpcihp_zt5550.h b/drivers/hotplug/cpcihp_zt5550.h
--- a/drivers/hotplug/cpcihp_zt5550.h	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,79 +0,0 @@
-/*
- * cpcihp_zt5550.h
- *
- * Intel/Ziatech ZT5550 CompactPCI Host Controller driver definitions
- *
- * Copyright 2002 SOMA Networks, Inc.
- * Copyright 2001 Intel San Luis Obispo
- * Copyright 2000,2001 MontaVista Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <scottm@somanetworks.com>
- */
-
-#ifndef _CPCIHP_ZT5550_H
-#define _CPCIHP_ZT5550_H
-
-/* Direct registers */
-#define CSR_HCINDEX		0x00
-#define CSR_HCDATA		0x04
-#define CSR_INTSTAT		0x08
-#define CSR_INTMASK		0x09
-#define CSR_CNT0CMD		0x0C
-#define CSR_CNT1CMD		0x0E
-#define CSR_CNT0		0x10
-#define CSR_CNT1		0x14
-
-/* Masks for interrupt bits in CSR_INTMASK direct register */
-#define CNT0_INT_MASK		0x01
-#define CNT1_INT_MASK		0x02
-#define ENUM_INT_MASK		0x04
-#define ALL_DIRECT_INTS_MASK	0x07
-
-/* Indexed registers (through CSR_INDEX, CSR_DATA) */
-#define HC_INT_MASK_REG		0x04
-#define HC_STATUS_REG		0x08
-#define HC_CMD_REG		0x0C
-#define ARB_CONFIG_GNT_REG	0x10
-#define ARB_CONFIG_CFG_REG	0x12
-#define ARB_CONFIG_REG	 	0x10
-#define ISOL_CONFIG_REG		0x18
-#define FAULT_STATUS_REG	0x20
-#define FAULT_CONFIG_REG	0x24
-#define WD_CONFIG_REG		0x2C
-#define HC_DIAG_REG		0x30
-#define SERIAL_COMM_REG		0x34
-#define SERIAL_OUT_REG		0x38
-#define SERIAL_IN_REG		0x3C
-
-/* Masks for interrupt bits in HC_INT_MASK_REG indexed register */
-#define SERIAL_INT_MASK		0x01
-#define FAULT_INT_MASK		0x02
-#define HCF_INT_MASK		0x04
-#define ALL_INDEXED_INTS_MASK	0x07
-
-/* Digital I/O port storing ENUM# */
-#define ENUM_PORT	0xE1
-/* Mask to get to the ENUM# bit on the bus */
-#define ENUM_MASK	0x40
-
-#endif				/* _CPCIHP_ZT5550_H */
diff -Nru a/drivers/hotplug/cpqphp.h b/drivers/hotplug/cpqphp.h
--- a/drivers/hotplug/cpqphp.h	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,912 +0,0 @@
-/*
- * Compaq Hot Plug Controller Driver
- *
- * Copyright (c) 1995,2001 Compaq Computer Corporation
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001 IBM
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <greg@kroah.com>
- *
- */
-#ifndef _CPQPHP_H
-#define _CPQPHP_H
-
-#include "pci_hotplug.h"
-#include <linux/interrupt.h>
-#include <asm/io.h>		/* for read? and write? functions */
-#include <linux/delay.h>	/* for delays */
-
-#if !defined(CONFIG_HOTPLUG_PCI_COMPAQ_MODULE)
-	#define MY_NAME	"cpqphp.o"
-#else
-	#define MY_NAME	THIS_MODULE->name
-#endif
-
-#define dbg(fmt, arg...) do { if (cpqhp_debug) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0)
-#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
-#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
-
-
-
-struct smbios_system_slot {
-	u8 type;
-	u8 length;
-	u16 handle;
-	u8 name_string_num;
-	u8 slot_type;
-	u8 slot_width;
-	u8 slot_current_usage;
-	u8 slot_length;
-	u16 slot_number;
-	u8 properties1;
-	u8 properties2;
-} __attribute__ ((packed));
-
-/* offsets to the smbios generic type based on the above structure layout */
-enum smbios_system_slot_offsets {
-	SMBIOS_SLOT_GENERIC_TYPE =	offsetof(struct smbios_system_slot, type),
-	SMBIOS_SLOT_GENERIC_LENGTH =	offsetof(struct smbios_system_slot, length),
-	SMBIOS_SLOT_GENERIC_HANDLE =	offsetof(struct smbios_system_slot, handle),
-	SMBIOS_SLOT_NAME_STRING_NUM =	offsetof(struct smbios_system_slot, name_string_num),
-	SMBIOS_SLOT_TYPE =		offsetof(struct smbios_system_slot, slot_type),
-	SMBIOS_SLOT_WIDTH =		offsetof(struct smbios_system_slot, slot_width),
-	SMBIOS_SLOT_CURRENT_USAGE =	offsetof(struct smbios_system_slot, slot_current_usage),
-	SMBIOS_SLOT_LENGTH =		offsetof(struct smbios_system_slot, slot_length),
-	SMBIOS_SLOT_NUMBER =		offsetof(struct smbios_system_slot, slot_number),
-	SMBIOS_SLOT_PROPERTIES1 =	offsetof(struct smbios_system_slot, properties1),
-	SMBIOS_SLOT_PROPERTIES2 =	offsetof(struct smbios_system_slot, properties2),
-};
-
-struct smbios_generic {
-	u8 type;
-	u8 length;
-	u16 handle;
-} __attribute__ ((packed));
-
-/* offsets to the smbios generic type based on the above structure layout */
-enum smbios_generic_offsets {
-	SMBIOS_GENERIC_TYPE =	offsetof(struct smbios_generic, type),
-	SMBIOS_GENERIC_LENGTH =	offsetof(struct smbios_generic, length),
-	SMBIOS_GENERIC_HANDLE =	offsetof(struct smbios_generic, handle),
-};
-
-struct smbios_entry_point {
-	char anchor[4];
-	u8 ep_checksum;
-	u8 ep_length;
-	u8 major_version;
-	u8 minor_version;
-	u16 max_size_entry;
-	u8 ep_rev;
-	u8 reserved[5];
-	char int_anchor[5];
-	u8 int_checksum;
-	u16 st_length;
-	u32 st_address;
-	u16 number_of_entrys;
-	u8 bcd_rev;
-} __attribute__ ((packed));
-
-/* offsets to the smbios entry point based on the above structure layout */
-enum smbios_entry_point_offsets {
-	ANCHOR =		offsetof(struct smbios_entry_point, anchor[0]),
-	EP_CHECKSUM =		offsetof(struct smbios_entry_point, ep_checksum),
-	EP_LENGTH =		offsetof(struct smbios_entry_point, ep_length),
-	MAJOR_VERSION =		offsetof(struct smbios_entry_point, major_version),
-	MINOR_VERSION =		offsetof(struct smbios_entry_point, minor_version),
-	MAX_SIZE_ENTRY =	offsetof(struct smbios_entry_point, max_size_entry),
-	EP_REV =		offsetof(struct smbios_entry_point, ep_rev),
-	INT_ANCHOR =		offsetof(struct smbios_entry_point, int_anchor[0]),
-	INT_CHECKSUM =		offsetof(struct smbios_entry_point, int_checksum),
-	ST_LENGTH =		offsetof(struct smbios_entry_point, st_length),
-	ST_ADDRESS =		offsetof(struct smbios_entry_point, st_address),
-	NUMBER_OF_ENTRYS =	offsetof(struct smbios_entry_point, number_of_entrys),
-	BCD_REV =		offsetof(struct smbios_entry_point, bcd_rev),
-};
-
-struct ctrl_reg {			/* offset */
-	u8	slot_RST;		/* 0x00 */
-	u8	slot_enable;		/* 0x01 */
-	u16	misc;			/* 0x02 */
-	u32	led_control;		/* 0x04 */
-	u32	int_input_clear;	/* 0x08 */
-	u32	int_mask;		/* 0x0a */
-	u8	reserved0;		/* 0x10 */
-	u8	reserved1;		/* 0x11 */
-	u8	reserved2;		/* 0x12 */
-	u8	gen_output_AB;		/* 0x13 */
-	u32	non_int_input;		/* 0x14 */
-	u32	reserved3;		/* 0x18 */
-	u32	reserved4;		/* 0x1a */
-	u32	reserved5;		/* 0x20 */
-	u8	reserved6;		/* 0x24 */
-	u8	reserved7;		/* 0x25 */
-	u16	reserved8;		/* 0x26 */
-	u8	slot_mask;		/* 0x28 */
-	u8	reserved9;		/* 0x29 */
-	u8	reserved10;		/* 0x2a */
-	u8	reserved11;		/* 0x2b */
-	u8	slot_SERR;		/* 0x2c */
-	u8	slot_power;		/* 0x2d */
-	u8	reserved12;		/* 0x2e */
-	u8	reserved13;		/* 0x2f */
-	u8	next_curr_freq;		/* 0x30 */
-	u8	reset_freq_mode;	/* 0x31 */
-} __attribute__ ((packed));
-
-/* offsets to the controller registers based on the above structure layout */
-enum ctrl_offsets {
-	SLOT_RST = 		offsetof(struct ctrl_reg, slot_RST),
-	SLOT_ENABLE =		offsetof(struct ctrl_reg, slot_enable),
-	MISC =			offsetof(struct ctrl_reg, misc),
-	LED_CONTROL =		offsetof(struct ctrl_reg, led_control),
-	INT_INPUT_CLEAR =	offsetof(struct ctrl_reg, int_input_clear),
-	INT_MASK = 		offsetof(struct ctrl_reg, int_mask),
-	CTRL_RESERVED0 = 	offsetof(struct ctrl_reg, reserved0),
-	CTRL_RESERVED1 =	offsetof(struct ctrl_reg, reserved1),
-	CTRL_RESERVED2 =	offsetof(struct ctrl_reg, reserved1),
-	GEN_OUTPUT_AB = 	offsetof(struct ctrl_reg, gen_output_AB),
-	NON_INT_INPUT = 	offsetof(struct ctrl_reg, non_int_input),
-	CTRL_RESERVED3 =	offsetof(struct ctrl_reg, reserved3),
-	CTRL_RESERVED4 =	offsetof(struct ctrl_reg, reserved4),
-	CTRL_RESERVED5 =	offsetof(struct ctrl_reg, reserved5),
-	CTRL_RESERVED6 =	offsetof(struct ctrl_reg, reserved6),
-	CTRL_RESERVED7 =	offsetof(struct ctrl_reg, reserved7),
-	CTRL_RESERVED8 =	offsetof(struct ctrl_reg, reserved8),
-	SLOT_MASK = 		offsetof(struct ctrl_reg, slot_mask),
-	CTRL_RESERVED9 = 	offsetof(struct ctrl_reg, reserved9),
-	CTRL_RESERVED10 =	offsetof(struct ctrl_reg, reserved10),
-	CTRL_RESERVED11 =	offsetof(struct ctrl_reg, reserved11),
-	SLOT_SERR =		offsetof(struct ctrl_reg, slot_SERR),
-	SLOT_POWER =		offsetof(struct ctrl_reg, slot_power),
-	NEXT_CURR_FREQ =	offsetof(struct ctrl_reg, next_curr_freq),
-	RESET_FREQ_MODE =	offsetof(struct ctrl_reg, reset_freq_mode),
-};
-
-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;
-};
-
-#define SLOT_MAGIC	0x67267321
-struct slot {
-	u32 magic;
-	struct slot *next;
-	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;
-};
-
-struct pci_resource {
-	struct pci_resource * next;
-	u32 base;
-	u32 length;
-};
-
-struct event_info {
-	u32 event_type;
-	u8 hp_slot;
-};
-
-struct controller {
-	struct controller *next;
-	u32 ctrl_int_comp;
-	struct semaphore crit_sect;	/* critical section semaphore */
-	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 event_info event_queue[10];
-	struct slot *slot;
-	u8 next_event;
-	u8 interrupt;
-	u8 cfgspc_irq;
-	u8 bus;				/* bus number for the pci hotplug controller */
-	u8 rev;
-	u8 slot_device_offset;
-	u8 first_slot;
-	u8 add_support;
-	u8 push_flag;
-	enum pci_bus_speed speed;
-	enum pci_bus_speed speed_capability;
-	u8 push_button;			/* 0 = no pushbutton, 1 = pushbutton present */
-	u8 slot_switch_type;		/* 0 = no switch, 1 = switch present */
-	u8 defeature_PHP;		/* 0 = PHP not supported, 1 = PHP supported */
-	u8 alternate_base_address;	/* 0 = not supported, 1 = supported */
-	u8 pci_config_space;		/* Index/data access to working registers 0 = not supported, 1 = supported */
-	u8 pcix_speed_capability;	/* PCI-X */
-	u8 pcix_support;		/* PCI-X */
-	u16 vendor_id;
-	struct work_struct int_task_event;
-	wait_queue_head_t queue;	/* sleep & wake process */
-};
-
-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 PCI_HPC_ID			0xA0F7
-#define PCI_SUB_HPC_ID			0xA2F7
-#define PCI_SUB_HPC_ID2			0xA2F8
-#define PCI_SUB_HPC_ID3			0xA2F9
-#define PCI_SUB_HPC_ID_INTC		0xA2FA
-#define PCI_SUB_HPC_ID4			0xA2FD
-
-#define INT_BUTTON_IGNORE		0
-#define INT_PRESENCE_ON			1
-#define INT_PRESENCE_OFF		2
-#define INT_SWITCH_CLOSE		3
-#define INT_SWITCH_OPEN			4
-#define INT_POWER_FAULT			5
-#define INT_POWER_FAULT_CLEAR		6
-#define INT_BUTTON_PRESS		7
-#define INT_BUTTON_RELEASE		8
-#define INT_BUTTON_CANCEL		9
-
-#define STATIC_STATE			0
-#define BLINKINGON_STATE		1
-#define BLINKINGOFF_STATE		2
-#define POWERON_STATE			3
-#define POWEROFF_STATE			4
-
-#define PCISLOT_INTERLOCK_CLOSED	0x00000001
-#define PCISLOT_ADAPTER_PRESENT		0x00000002
-#define PCISLOT_POWERED			0x00000004
-#define PCISLOT_66_MHZ_OPERATION	0x00000008
-#define PCISLOT_64_BIT_OPERATION	0x00000010
-#define PCISLOT_REPLACE_SUPPORTED	0x00000020
-#define PCISLOT_ADD_SUPPORTED		0x00000040
-#define PCISLOT_INTERLOCK_SUPPORTED	0x00000080
-#define PCISLOT_66_MHZ_SUPPORTED	0x00000100
-#define PCISLOT_64_BIT_SUPPORTED	0x00000200
-
-
-
-#define PCI_TO_PCI_BRIDGE_CLASS		0x00060400
-
-
-#define INTERLOCK_OPEN			0x00000002
-#define ADD_NOT_SUPPORTED		0x00000003
-#define CARD_FUNCTIONING		0x00000005
-#define ADAPTER_NOT_SAME		0x00000006
-#define NO_ADAPTER_PRESENT		0x00000009
-#define NOT_ENOUGH_RESOURCES		0x0000000B
-#define DEVICE_TYPE_NOT_SUPPORTED	0x0000000C
-#define POWER_FAILURE			0x0000000E
-
-#define REMOVE_NOT_SUPPORTED		0x00000003
-
-
-/*
- * error Messages
- */
-#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_compaq_or_intel	"The PCI hot plug controller is not supported by this driver.\n"
-#define msg_HPC_not_supported	"this system is not supported by this version of cpqphpd. Upgrade to a newer version of cpqphpd\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"
-#define msg_button_on		"PCI slot #%d - powering on due to button press.\n"
-#define msg_button_off		"PCI slot #%d - powering off due to button press.\n"
-#define msg_button_cancel	"PCI slot #%d - action canceled due to button press.\n"
-#define msg_button_ignore	"PCI slot #%d - button press ignored.  (action in progress...)\n"
-
-
-/* sysfs functions for the hotplug controller info */
-extern void cpqhp_create_ctrl_files		(struct controller *ctrl);
-
-/* controller functions */
-extern void	cpqhp_pushbutton_thread		(unsigned long event_pointer);
-extern irqreturn_t cpqhp_ctrl_intr		(int IRQ, void *data, struct pt_regs *regs);
-extern int	cpqhp_find_available_resources	(struct controller *ctrl, void *rom_start);
-extern int	cpqhp_event_start_thread	(void);
-extern void	cpqhp_event_stop_thread		(void);
-extern struct pci_func *cpqhp_slot_create	(unsigned char busnumber);
-extern struct pci_func *cpqhp_slot_find		(unsigned char bus, unsigned char device, unsigned char index);
-extern int	cpqhp_process_SI		(struct controller *ctrl, struct pci_func *func);
-extern int	cpqhp_process_SS		(struct controller *ctrl, struct pci_func *func);
-extern int	cpqhp_hardware_test		(struct controller *ctrl, int test_num);
-
-/* resource functions */
-extern int	cpqhp_resource_sort_and_combine	(struct pci_resource **head);
-
-/* pci functions */
-extern int	cpqhp_set_irq			(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
-extern int	cpqhp_get_bus_dev		(struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot);
-extern int	cpqhp_save_config		(struct controller *ctrl, int busnumber, int is_hot_plug);
-extern int	cpqhp_save_base_addr_length	(struct controller *ctrl, struct pci_func * func);
-extern int	cpqhp_save_used_resources	(struct controller *ctrl, struct pci_func * func);
-extern int	cpqhp_configure_board		(struct controller *ctrl, struct pci_func * func);
-extern int	cpqhp_save_slot_config		(struct controller *ctrl, struct pci_func * new_slot);
-extern int	cpqhp_valid_replace		(struct controller *ctrl, struct pci_func * func);
-extern void	cpqhp_destroy_board_resources	(struct pci_func * func);
-extern int	cpqhp_return_board_resources	(struct pci_func * func, struct resource_lists * resources);
-extern void	cpqhp_destroy_resource_list	(struct resource_lists * resources);
-extern int	cpqhp_configure_device		(struct controller* ctrl, struct pci_func* func);
-extern int	cpqhp_unconfigure_device	(struct pci_func* func);
-extern struct slot *cpqhp_find_slot		(struct controller *ctrl, u8 device);
-
-/* Global variables */
-extern int cpqhp_debug;
-extern struct controller *cpqhp_ctrl_list;
-extern struct pci_func *cpqhp_slot_list[256];
-
-/* these can be gotten rid of, but for debugging they are purty */
-extern u8 cpqhp_nic_irq;
-extern u8 cpqhp_disk_irq;
-
-
-
-/* inline functions */
-
-
-/* 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;
-}               
-
-/*
- * 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)
-{
-	if (!node || !head)
-		return;
-	node->next = *head;
-	*head = node;
-}
-
-static inline void set_SOGO (struct controller *ctrl)
-{
-	u16 misc;
-	
-	misc = readw(ctrl->hpc_reg + MISC);
-	misc = (misc | 0x0001) & 0xFFFB;
-	writew(misc, ctrl->hpc_reg + MISC);
-}
-
-
-static inline void amber_LED_on (struct controller *ctrl, u8 slot)
-{
-	u32 led_control;
-	
-	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
-	led_control |= (0x01010000L << slot);
-	writel(led_control, ctrl->hpc_reg + LED_CONTROL);
-}
-
-
-static inline void amber_LED_off (struct controller *ctrl, u8 slot)
-{
-	u32 led_control;
-	
-	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
-	led_control &= ~(0x01010000L << slot);
-	writel(led_control, ctrl->hpc_reg + LED_CONTROL);
-}
-
-
-static inline int read_amber_LED (struct controller *ctrl, u8 slot)
-{
-	u32 led_control;
-
-	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
-	led_control &= (0x01010000L << slot);
-	
-	return led_control ? 1 : 0;
-}
-
-
-static inline void green_LED_on (struct controller *ctrl, u8 slot)
-{
-	u32 led_control;
-	
-	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
-	led_control |= 0x0101L << slot;
-	writel(led_control, ctrl->hpc_reg + LED_CONTROL);
-}
-
-static inline void green_LED_off (struct controller *ctrl, u8 slot)
-{
-	u32 led_control;
-	
-	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
-	led_control &= ~(0x0101L << slot);
-	writel(led_control, ctrl->hpc_reg + LED_CONTROL);
-}
-
-
-static inline void green_LED_blink (struct controller *ctrl, u8 slot)
-{
-	u32 led_control;
-	
-	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
-	led_control &= ~(0x0101L << slot);
-	led_control |= (0x0001L << slot);
-	writel(led_control, ctrl->hpc_reg + LED_CONTROL);
-}
-
-
-static inline void slot_disable (struct controller *ctrl, u8 slot)
-{
-	u8 slot_enable;
-
-	slot_enable = readb(ctrl->hpc_reg + SLOT_ENABLE);
-	slot_enable &= ~(0x01 << slot);
-	writeb(slot_enable, ctrl->hpc_reg + SLOT_ENABLE);
-}
-
-
-static inline void slot_enable (struct controller *ctrl, u8 slot)
-{
-	u8 slot_enable;
-
-	slot_enable = readb(ctrl->hpc_reg + SLOT_ENABLE);
-	slot_enable |= (0x01 << slot);
-	writeb(slot_enable, ctrl->hpc_reg + SLOT_ENABLE);
-}
-
-
-static inline u8 is_slot_enabled (struct controller *ctrl, u8 slot)
-{
-	u8 slot_enable;
-
-	slot_enable = readb(ctrl->hpc_reg + SLOT_ENABLE);
-	slot_enable &= (0x01 << slot);
-	return slot_enable ? 1 : 0;
-}
-
-
-static inline u8 read_slot_enable (struct controller *ctrl)
-{
-	return readb(ctrl->hpc_reg + SLOT_ENABLE);
-}
-
-
-/*
- * get_controller_speed - find the current frequency/mode of controller.
- *
- * @ctrl: controller to get frequency/mode for.
- *
- * Returns controller speed.
- *
- */
-static inline u8 get_controller_speed (struct controller *ctrl)
-{
-	u8 curr_freq;
- 	u16 misc;
- 	
-	if (ctrl->pcix_support) {
-		curr_freq = readb(ctrl->hpc_reg + NEXT_CURR_FREQ);
-		if ((curr_freq & 0xB0) == 0xB0) 
-			return PCI_SPEED_133MHz_PCIX;
-		if ((curr_freq & 0xA0) == 0xA0)
-			return PCI_SPEED_100MHz_PCIX;
-		if ((curr_freq & 0x90) == 0x90)
-			return PCI_SPEED_66MHz_PCIX;
-		if (curr_freq & 0x10)
-			return PCI_SPEED_66MHz;
-
-		return PCI_SPEED_33MHz;
-	}
-
- 	misc = readw(ctrl->hpc_reg + MISC);
- 	return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
-}
- 
-
-/*
- * get_adapter_speed - find the max supported frequency/mode of adapter.
- *
- * @ctrl: hotplug controller.
- * @hp_slot: hotplug slot where adapter is installed.
- *
- * Returns adapter speed.
- *
- */
-static inline u8 get_adapter_speed (struct controller *ctrl, u8 hp_slot)
-{
-	u32 temp_dword = readl(ctrl->hpc_reg + NON_INT_INPUT);
-	dbg("slot: %d, PCIXCAP: %8x\n", hp_slot, temp_dword);
-	if (ctrl->pcix_support) {
-		if (temp_dword & (0x10000 << hp_slot))
-			return PCI_SPEED_133MHz_PCIX;
-		if (temp_dword & (0x100 << hp_slot))
-			return PCI_SPEED_66MHz_PCIX;
-	}
-
-	if (temp_dword & (0x01 << hp_slot))
-		return PCI_SPEED_66MHz;
-
-	return PCI_SPEED_33MHz;
-}
-
-static inline void enable_slot_power (struct controller *ctrl, u8 slot)
-{
-	u8 slot_power;
-
-	slot_power = readb(ctrl->hpc_reg + SLOT_POWER);
-	slot_power |= (0x01 << slot);
-	writeb(slot_power, ctrl->hpc_reg + SLOT_POWER);
-}
-
-static inline void disable_slot_power (struct controller *ctrl, u8 slot)
-{
-	u8 slot_power;
-
-	slot_power = readb(ctrl->hpc_reg + SLOT_POWER);
-	slot_power &= ~(0x01 << slot);
-	writeb(slot_power, ctrl->hpc_reg + SLOT_POWER);
-}
-
-
-static inline int cpq_get_attention_status (struct controller *ctrl, struct slot *slot)
-{
-	u8 hp_slot;
-
-	if (slot == NULL)
-		return 1;
-
-	hp_slot = slot->device - ctrl->slot_device_offset;
-
-	return read_amber_LED (ctrl, hp_slot);
-}
-
-
-static inline int get_slot_enabled (struct controller *ctrl, struct slot *slot)
-{
-	u8 hp_slot;
-
-	if (slot == NULL)
-		return 1;
-
-	hp_slot = slot->device - ctrl->slot_device_offset;
-
-	return is_slot_enabled (ctrl, hp_slot);
-}
-
-
-static inline int cpq_get_latch_status (struct controller *ctrl, struct slot *slot)
-{
-	u32 status;
-	u8 hp_slot;
-
-	if (slot == NULL)
-		return 1;
-
-	hp_slot = slot->device - ctrl->slot_device_offset;
-	dbg("%s: slot->device = %d, ctrl->slot_device_offset = %d \n",
-	    __FUNCTION__, slot->device, ctrl->slot_device_offset);
-
-	status = (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot));
-
-	return(status == 0) ? 1 : 0;
-}
-
-
-static inline int get_presence_status (struct controller *ctrl, struct slot *slot)
-{
-	int presence_save = 0;
-	u8 hp_slot;
-	u32 tempdword;
-
-	if (slot == NULL)
-		return 0;
-
-	hp_slot = slot->device - ctrl->slot_device_offset;
-
-	tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
-	presence_save = (int) ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> hp_slot) & 0x02;
-
-	return presence_save;
-}
-
-#define SLOT_NAME_SIZE 10
-
-static inline void make_slot_name (char *buffer, int buffer_size, struct slot *slot)
-{
-	snprintf (buffer, buffer_size, "%d", slot->number);
-}
-
-
-static inline int wait_for_ctrl_irq (struct controller *ctrl)
-{
-        DECLARE_WAITQUEUE(wait, current);
-	int retval = 0;
-
-	dbg("%s - start\n", __FUNCTION__);
-	add_wait_queue(&ctrl->queue, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	/* Sleep for up to 1 second to wait for the LED to change. */
-	schedule_timeout(1*HZ);
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&ctrl->queue, &wait);
-	if (signal_pending(current))
-		retval =  -EINTR;
-
-	dbg("%s - end\n", __FUNCTION__);
-	return retval;
-}
-
-
-/**
- * set_controller_speed - set the frequency and/or mode of a specific
- * controller segment.
- *
- * @ctrl: controller to change frequency/mode for.
- * @adapter_speed: the speed of the adapter we want to match.
- * @hp_slot: the slot number where the adapter is installed.
- *
- * Returns 0 if we successfully change frequency and/or mode to match the
- * adapter speed.
- * 
- */
-static inline u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot)
-{
-	struct slot *slot;
-	u8 reg;
-	u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER);
-	u16 reg16;
-	u32 leds = readl(ctrl->hpc_reg + LED_CONTROL);
-	
-	if (ctrl->speed == adapter_speed)
-		return 0;
-	
-	/* We don't allow freq/mode changes if we find another adapter running
-	 * in another slot on this controller */
-	for(slot = ctrl->slot; slot; slot = slot->next) {
-		if (slot->device == (hp_slot + ctrl->slot_device_offset)) 
-			continue;
-		if (!slot->hotplug_slot && !slot->hotplug_slot->info) 
-			continue;
-		if (slot->hotplug_slot->info->adapter_status == 0) 
-			continue;
-		/* If another adapter is running on the same segment but at a
-		 * lower speed/mode, we allow the new adapter to function at
-		 * this rate if supported */
-		if (ctrl->speed < adapter_speed) 
-			return 0;
-
-		return 1;
-	}
-	
-	/* If the controller doesn't support freq/mode changes and the
-	 * controller is running at a higher mode, we bail */
-	if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability))
-		return 1;
-	
-	/* But we allow the adapter to run at a lower rate if possible */
-	if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability))
-		return 0;
-
-	/* We try to set the max speed supported by both the adapter and
-	 * controller */
-	if (ctrl->speed_capability < adapter_speed) {
-		if (ctrl->speed == ctrl->speed_capability)
-			return 0;
-		adapter_speed = ctrl->speed_capability;
-	}
-
-	writel(0x0L, ctrl->hpc_reg + LED_CONTROL);
-	writeb(0x00, ctrl->hpc_reg + SLOT_ENABLE);
-	
-	set_SOGO(ctrl); 
-	wait_for_ctrl_irq(ctrl);
-	
-	if (adapter_speed != PCI_SPEED_133MHz_PCIX)
-		reg = 0xF5;
-	else
-		reg = 0xF4;	
-	pci_write_config_byte(ctrl->pci_dev, 0x41, reg);
-	
-	reg16 = readw(ctrl->hpc_reg + NEXT_CURR_FREQ);
-	reg16 &= ~0x000F;
-	switch(adapter_speed) {
-		case(PCI_SPEED_133MHz_PCIX): 
-			reg = 0x75;
-			reg16 |= 0xB; 
-			break;
-		case(PCI_SPEED_100MHz_PCIX):
-			reg = 0x74;
-			reg16 |= 0xA;
-			break;
-		case(PCI_SPEED_66MHz_PCIX):
-			reg = 0x73;
-			reg16 |= 0x9;
-			break;
-		case(PCI_SPEED_66MHz):
-			reg = 0x73;
-			reg16 |= 0x1;
-			break;
-		default: /* 33MHz PCI 2.2 */
-			reg = 0x71;
-			break;
-			
-	}
-	reg16 |= 0xB << 12;
-	writew(reg16, ctrl->hpc_reg + NEXT_CURR_FREQ);
-	
-	mdelay(5); 
-	
-	/* Reenable interrupts */
-	writel(0, ctrl->hpc_reg + INT_MASK);
-
-	pci_write_config_byte(ctrl->pci_dev, 0x41, reg); 
-	
-	/* Restart state machine */
-	reg = ~0xF;
-	pci_read_config_byte(ctrl->pci_dev, 0x43, &reg);
-	pci_write_config_byte(ctrl->pci_dev, 0x43, reg);
-	
-	/* Only if mode change...*/
-	if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) ||
-		((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) 
-			set_SOGO(ctrl);
-	
-	wait_for_ctrl_irq(ctrl);
-	mdelay(1100);
-	
-	/* Restore LED/Slot state */
-	writel(leds, ctrl->hpc_reg + LED_CONTROL);
-	writeb(slot_power, ctrl->hpc_reg + SLOT_ENABLE);
-	
-	set_SOGO(ctrl);
-	wait_for_ctrl_irq(ctrl);
-
-	ctrl->speed = adapter_speed;
-	slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-
-	info("Successfully changed frequency/mode for adapter in slot %d\n", 
-			slot->number);
-	return 0;
-}
-
-#endif
-
diff -Nru a/drivers/hotplug/cpqphp_core.c b/drivers/hotplug/cpqphp_core.c
--- a/drivers/hotplug/cpqphp_core.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1541 +0,0 @@
-/*
- * Compaq Hot Plug Controller Driver
- *
- * Copyright (c) 1995,2001 Compaq Computer Corporation
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001 IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <greg@kroah.com>
- *
- * Jan 12, 2003 -	Added 66/100/133MHz PCI-X support,
- * 			Torben Mathiasen <torben.mathiasen@hp.com>
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/miscdevice.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-
-#include <asm/uaccess.h>
-
-#include "cpqphp.h"
-#include "cpqphp_nvram.h"
-#include "../../arch/i386/pci/pci.h"	/* horrible hack showing how processor dependent we are... */
-
-
-/* Global variables */
-int cpqhp_debug;
-struct controller *cpqhp_ctrl_list;	/* = NULL */
-struct pci_func *cpqhp_slot_list[256];
-
-/* local variables */
-static void *smbios_table;
-static void *smbios_start;
-static void *cpqhp_rom_start;
-static u8 power_mode;
-static int debug;
-
-#define DRIVER_VERSION	"0.9.7"
-#define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>"
-#define DRIVER_DESC	"Compaq Hot Plug PCI Controller Driver"
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
-MODULE_PARM(power_mode, "b");
-MODULE_PARM_DESC(power_mode, "Power mode enabled or not");
-
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
-
-#define CPQHPC_MODULE_MINOR 208
-
-static int one_time_init (void);
-static int set_attention_status (struct hotplug_slot *slot, u8 value);
-static int process_SI		(struct hotplug_slot *slot);
-static int process_SS		(struct hotplug_slot *slot);
-static int hardware_test	(struct hotplug_slot *slot, u32 value);
-static int get_power_status	(struct hotplug_slot *slot, u8 *value);
-static int get_attention_status	(struct hotplug_slot *slot, u8 *value);
-static int get_latch_status	(struct hotplug_slot *slot, u8 *value);
-static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
-static int get_max_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
-static int get_cur_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
-
-static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = {
-	.owner =		THIS_MODULE,
-	.set_attention_status =	set_attention_status,
-	.enable_slot =		process_SI,
-	.disable_slot =		process_SS,
-	.hardware_test =	hardware_test,
-	.get_power_status =	get_power_status,
-	.get_attention_status =	get_attention_status,
-	.get_latch_status =	get_latch_status,
-	.get_adapter_status =	get_adapter_status,
-  	.get_max_bus_speed =	get_max_bus_speed,
-  	.get_cur_bus_speed =	get_cur_bus_speed,
-};
-
-
-static inline int is_slot64bit (struct slot *slot)
-{
-	if (!slot || !slot->p_sm_slot)
-		return 0;
-
-	if (readb(slot->p_sm_slot + SMBIOS_SLOT_WIDTH) == 0x06)
-		return 1;
-
-	return 0;
-}
-
-static inline int is_slot66mhz (struct slot *slot)
-{
-	if (!slot || !slot->p_sm_slot)
-		return 0;
-
-	if (readb(slot->p_sm_slot + SMBIOS_SLOT_TYPE) == 0x0E)
-		return 1;
-
-	return 0;
-}
-
-/**
- * detect_SMBIOS_pointer - find the system Management BIOS Table in the specified region of memory.
- *
- * @begin: begin pointer for region to be scanned.
- * @end: end pointer for region to be scanned.
- *
- * Returns pointer to the head of the SMBIOS tables (or NULL)
- *
- */
-static void * detect_SMBIOS_pointer(void *begin, void *end)
-{
-	void *fp;
-	void *endp;
-	u8 temp1, temp2, temp3, temp4;
-	int status = 0;
-
-	endp = (end - sizeof(u32) + 1);
-
-	for (fp = begin; fp <= endp; fp += 16) {
-		temp1 = readb(fp);
-		temp2 = readb(fp+1);
-		temp3 = readb(fp+2);
-		temp4 = readb(fp+3);
-		if (temp1 == '_' &&
-		    temp2 == 'S' &&
-		    temp3 == 'M' &&
-		    temp4 == '_') {
-			status = 1;
-			break;
-		}
-	}
-	
-	if (!status)
-		fp = NULL;
-
-	dbg("Discovered SMBIOS Entry point at %p\n", fp);
-
-	return fp;
-}
-
-/**
- * init_SERR - Initializes the per slot SERR generation.
- *
- * For unexpected switch opens
- *
- */
-static int init_SERR(struct controller * ctrl)
-{
-	u32 tempdword;
-	u32 number_of_slots;
-	u8 physical_slot;
-
-	if (!ctrl)
-		return 1;
-
-	tempdword = ctrl->first_slot;
-
-	number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
-	// Loop through slots
-	while (number_of_slots) {
-		physical_slot = tempdword;
-		writeb(0, ctrl->hpc_reg + SLOT_SERR);
-		tempdword++;
-		number_of_slots--;
-	}
-
-	return 0;
-}
-
-
-/* nice debugging output */
-static int pci_print_IRQ_route (void)
-{
-	struct irq_routing_table *routing_table;
-	int len;
-	int loop;
-
-	u8 tbus, tdevice, tslot;
-
-	routing_table = pcibios_get_irq_routing_table();
-	if (routing_table == NULL) {
-		err("No BIOS Routing Table??? Not good\n");
-		return -ENOMEM;
-	}
-
-	len = (routing_table->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
-	// Make sure I got at least one entry
-	if (len == 0) {
-		kfree(routing_table);
-		return -1;
-	}
-
-	dbg("bus dev func slot\n");
-
-	for (loop = 0; loop < len; ++loop) {
-		tbus = routing_table->slots[loop].bus;
-		tdevice = routing_table->slots[loop].devfn;
-		tslot = routing_table->slots[loop].slot;
-		dbg("%d %d %d %d\n", tbus, tdevice >> 3, tdevice & 0x7, tslot);
-
-	}
-	kfree(routing_table);
-	return 0;
-}
-
-
-/*
- * get_subsequent_smbios_entry
- *
- * Gets the first entry if previous == NULL
- * Otherwise, returns the next entry
- * Uses global SMBIOS Table pointer
- *
- * @curr: %NULL or pointer to previously returned structure
- *
- * returns a pointer to an SMBIOS structure or NULL if none found
- */
-static void * get_subsequent_smbios_entry(void *smbios_start, void *smbios_table, void *curr)
-{
-	u8 bail = 0;
-	u8 previous_byte = 1;
-	void *p_temp;
-	void *p_max;
-
-	if (!smbios_table || !curr)
-		return(NULL);
-
-	// set p_max to the end of the table
-	p_max = smbios_start + readw(smbios_table + ST_LENGTH);
-
-	p_temp = curr;
-	p_temp += readb(curr + SMBIOS_GENERIC_LENGTH);
-
-	while ((p_temp < p_max) && !bail) {
-		// Look for the double NULL terminator
-		// The first condition is the previous byte and the second is the curr
-		if (!previous_byte && !(readb(p_temp))) {
-			bail = 1;
-		}
-
-		previous_byte = readb(p_temp);
-		p_temp++;
-	}
-
-	if (p_temp < p_max) {
-		return p_temp;
-	} else {
-		return NULL;
-	}
-}
-
-
-/**
- * get_SMBIOS_entry
- *
- * @type:SMBIOS structure type to be returned
- * @previous: %NULL or pointer to previously returned structure
- *
- * Gets the first entry of the specified type if previous == NULL
- * Otherwise, returns the next entry of the given type.
- * Uses global SMBIOS Table pointer
- * Uses get_subsequent_smbios_entry
- *
- * returns a pointer to an SMBIOS structure or %NULL if none found
- */
-static void *get_SMBIOS_entry (void *smbios_start, void *smbios_table, u8 type, void * previous)
-{
-	if (!smbios_table)
-		return NULL;
-
-	if (!previous) {		  
-		previous = smbios_start;
-	} else {
-		previous = get_subsequent_smbios_entry(smbios_start, smbios_table, previous);
-	}
-
-	while (previous) {
-	       	if (readb(previous + SMBIOS_GENERIC_TYPE) != type) {
-			previous = get_subsequent_smbios_entry(smbios_start, smbios_table, previous);
-		} else {
-			break;
-		}
-	}
-
-	return previous;
-}
-
-
-static int ctrl_slot_setup (struct controller * ctrl, void *smbios_start, void *smbios_table)
-{
-	struct slot *new_slot;
-	u8 number_of_slots;
-	u8 slot_device;
-	u8 slot_number;
-	u8 ctrl_slot;
-	u32 tempdword;
-	void *slot_entry= NULL;
-	int result;
-
-	dbg("%s\n", __FUNCTION__);
-
-	tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
-
-	number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
-	slot_device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
-	slot_number = ctrl->first_slot;
-
-	while (number_of_slots) {
-		new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL);
-		if (!new_slot)
-			return -ENOMEM;
-
-		memset(new_slot, 0, sizeof(struct slot));
-		new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL);
-		if (!new_slot->hotplug_slot) {
-			kfree (new_slot);
-			return -ENOMEM;
-		}
-		memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot));
-
-		new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
-		if (!new_slot->hotplug_slot->info) {
-			kfree (new_slot->hotplug_slot);
-			kfree (new_slot);
-			return -ENOMEM;
-		}
-		memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info));
-		new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL);
-		if (!new_slot->hotplug_slot->name) {
-			kfree (new_slot->hotplug_slot->info);
-			kfree (new_slot->hotplug_slot);
-			kfree (new_slot);
-			return -ENOMEM;
-		}
-
-		new_slot->magic = SLOT_MAGIC;
-		new_slot->ctrl = ctrl;
-		new_slot->bus = ctrl->bus;
-		new_slot->device = slot_device;
-		new_slot->number = slot_number;
-		dbg("slot->number = %d\n",new_slot->number);
-
-		slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, slot_entry);
-
-		while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) != new_slot->number)) {
-			slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, slot_entry);
-		}
-
-		new_slot->p_sm_slot = slot_entry;
-
-		init_timer(&new_slot->task_event);
-		new_slot->task_event.expires = jiffies + 5 * HZ;
-		new_slot->task_event.function = cpqhp_pushbutton_thread;
-
-		//FIXME: these capabilities aren't used but if they are
-		//       they need to be correctly implemented
-		new_slot->capabilities |= PCISLOT_REPLACE_SUPPORTED;
-		new_slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED;
-
-		if (is_slot64bit(new_slot))
-			new_slot->capabilities |= PCISLOT_64_BIT_SUPPORTED;
-		if (is_slot66mhz(new_slot))
-			new_slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED;
-		if (ctrl->speed == PCI_SPEED_66MHz)
-			new_slot->capabilities |= PCISLOT_66_MHZ_OPERATION;
-
-		ctrl_slot = slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4);
-
-		// Check presence
-		new_slot->capabilities |= ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> ctrl_slot) & 0x02;
-		// Check the switch state
-		new_slot->capabilities |= ((~tempdword & 0xFF) >> ctrl_slot) & 0x01;
-		// Check the slot enable
-		new_slot->capabilities |= ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04;
-
-		/* register this slot with the hotplug pci core */
-		new_slot->hotplug_slot->private = new_slot;
-		make_slot_name (new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot);
-		new_slot->hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
-		
-		new_slot->hotplug_slot->info->power_status = get_slot_enabled(ctrl, new_slot);
-		new_slot->hotplug_slot->info->attention_status = cpq_get_attention_status(ctrl, new_slot);
-		new_slot->hotplug_slot->info->latch_status = cpq_get_latch_status(ctrl, new_slot);
-		new_slot->hotplug_slot->info->adapter_status = get_presence_status(ctrl, new_slot);
-		
-		dbg ("registering bus %d, dev %d, number %d, ctrl->slot_device_offset %d, slot %d\n", 
-		     new_slot->bus, new_slot->device, new_slot->number, ctrl->slot_device_offset, slot_number);
-		result = pci_hp_register (new_slot->hotplug_slot);
-		if (result) {
-			err ("pci_hp_register failed with error %d\n", result);
-			kfree (new_slot->hotplug_slot->info);
-			kfree (new_slot->hotplug_slot->name);
-			kfree (new_slot->hotplug_slot);
-			kfree (new_slot);
-			return result;
-		}
-		
-		new_slot->next = ctrl->slot;
-		ctrl->slot = new_slot;
-
-		number_of_slots--;
-		slot_device++;
-		slot_number++;
-	}
-
-	return(0);
-}
-
-
-static int ctrl_slot_cleanup (struct controller * ctrl)
-{
-	struct slot *old_slot, *next_slot;
-
-	old_slot = ctrl->slot;
-	ctrl->slot = NULL;
-
-	while (old_slot) {
-		next_slot = old_slot->next;
-		pci_hp_deregister (old_slot->hotplug_slot);
-		kfree(old_slot->hotplug_slot->info);
-		kfree(old_slot->hotplug_slot->name);
-		kfree(old_slot->hotplug_slot);
-		kfree(old_slot);
-		old_slot = next_slot;
-	}
-
-	//Free IRQ associated with hot plug device
-	free_irq(ctrl->interrupt, ctrl);
-	//Unmap the memory
-	iounmap(ctrl->hpc_reg);
-	//Finally reclaim PCI mem
-	release_mem_region(pci_resource_start(ctrl->pci_dev, 0),
-			   pci_resource_len(ctrl->pci_dev, 0));
-
-	return(0);
-}
-
-
-//============================================================================
-// function:	get_slot_mapping
-//
-// Description: Attempts to determine a logical slot mapping for a PCI
-//		device.  Won't work for more than one PCI-PCI bridge
-//		in a slot.
-//
-// Input:	u8 bus_num - bus number of PCI device
-//		u8 dev_num - device number of PCI device
-//		u8 *slot - Pointer to u8 where slot number will
-//			be returned
-//
-// Output:	SUCCESS or FAILURE
-//=============================================================================
-static int get_slot_mapping (struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot)
-{
-	struct irq_routing_table *PCIIRQRoutingInfoLength;
-	u32 work;
-	long len;
-	long loop;
-
-	u8 tbus, tdevice, tslot, bridgeSlot;
-
-	dbg("%s: %p, %d, %d, %p\n", __FUNCTION__, bus, bus_num, dev_num, slot);
-
-	bridgeSlot = 0xFF;
-
-	PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table();
-	if (!PCIIRQRoutingInfoLength)
-		return -1;
-
-	len = (PCIIRQRoutingInfoLength->size -
-	       sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
-	// Make sure I got at least one entry
-	if (len == 0) {
-		if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength );
-		return -1;
-	}
-
-	for (loop = 0; loop < len; ++loop) {
-		tbus = PCIIRQRoutingInfoLength->slots[loop].bus;
-		tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn >> 3;
-		tslot = PCIIRQRoutingInfoLength->slots[loop].slot;
-
-		if ((tbus == bus_num) && (tdevice == dev_num)) {
-			*slot = tslot;
-
-			if (PCIIRQRoutingInfoLength != NULL)
-				kfree(PCIIRQRoutingInfoLength);
-			return 0;
-		} else {
-			// Didn't get a match on the target PCI device. Check if the
-			// current IRQ table entry is a PCI-to-PCI bridge device.  If so,
-			// and it's secondary bus matches the bus number for the target 
-			// device, I need to save the bridge's slot number.  If I can't 
-			// find an entry for the target device, I will have to assume it's 
-			// on the other side of the bridge, and assign it the bridge's slot.
-			bus->number = tbus;
-			pci_bus_read_config_dword (bus, PCI_DEVFN(tdevice, 0), PCI_REVISION_ID, &work);
-
-			if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
-				pci_bus_read_config_dword (bus, PCI_DEVFN(tdevice, 0), PCI_PRIMARY_BUS, &work);
-				// See if bridge's secondary bus matches target bus.
-				if (((work >> 8) & 0x000000FF) == (long) bus_num) {
-					bridgeSlot = tslot;
-				}
-			}
-		}
-
-	}
-
-	// If we got here, we didn't find an entry in the IRQ mapping table 
-	// for the target PCI device.  If we did determine that the target 
-	// device is on the other side of a PCI-to-PCI bridge, return the 
-	// slot number for the bridge.
-	if (bridgeSlot != 0xFF) {
-		*slot = bridgeSlot;
-		if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength );
-		return 0;
-	}
-	if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength );
-	// Couldn't find an entry in the routing table for this PCI device
-	return -1;
-}
-
-
-/**
- * cpqhp_set_attention_status - Turns the Amber LED for a slot on or off
- *
- */
-static int cpqhp_set_attention_status (struct controller *ctrl, struct pci_func *func, u32 status)
-{
-	u8 hp_slot;
-
-	hp_slot = func->device - ctrl->slot_device_offset;
-
-	if (func == NULL)
-		return(1);
-
-	// Wait for exclusive access to hardware
-	down(&ctrl->crit_sect);
-
-	if (status == 1) {
-		amber_LED_on (ctrl, hp_slot);
-	} else if (status == 0) {
-		amber_LED_off (ctrl, hp_slot);
-	} else {
-		// Done with exclusive hardware access
-		up(&ctrl->crit_sect);
-		return(1);
-	}
-
-	set_SOGO(ctrl);
-
-	// Wait for SOBS to be unset
-	wait_for_ctrl_irq (ctrl);
-
-	// Done with exclusive hardware access
-	up(&ctrl->crit_sect);
-
-	return(0);
-}
-
-
-/**
- * set_attention_status - Turns the Amber LED for a slot on or off
- *
- */
-static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
-{
-	struct pci_func *slot_func;
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
-	struct controller *ctrl;
-	u8 bus;
-	u8 devfn;
-	u8 device;
-	u8 function;
-	
-	if (slot == NULL)
-		return -ENODEV;
-	
-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-
-	ctrl = slot->ctrl;
-	if (ctrl == NULL)
-		return -ENODEV;
-	
-	if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
-		return -ENODEV;
-
-	device = devfn >> 3;
-	function = devfn & 0x7;
-	dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function);
-
-	slot_func = cpqhp_slot_find(bus, device, function);
-	if (!slot_func) {
-		return -ENODEV;
-	}
-
-	return cpqhp_set_attention_status(ctrl, slot_func, status);
-}
-
-
-static int process_SI (struct hotplug_slot *hotplug_slot)
-{
-	struct pci_func *slot_func;
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
-	struct controller *ctrl;
-	u8 bus;
-	u8 devfn;
-	u8 device;
-	u8 function;
-	
-	if (slot == NULL)
-		return -ENODEV;
-	
-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-
-	ctrl = slot->ctrl;
-	if (ctrl == NULL)
-		return -ENODEV;
-	
-	if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
-		return -ENODEV;
-
-	device = devfn >> 3;
-	function = devfn & 0x7;
-	dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function);
-
-	slot_func = cpqhp_slot_find(bus, device, function);
-	if (!slot_func) {
-		return -ENODEV;
-	}
-
-	slot_func->bus = bus;
-	slot_func->device = device;
-	slot_func->function = function;
-	slot_func->configured = 0;
-	dbg("board_added(%p, %p)\n", slot_func, ctrl);
-	return cpqhp_process_SI(ctrl, slot_func);
-}
-
-
-static int process_SS (struct hotplug_slot *hotplug_slot)
-{
-	struct pci_func *slot_func;
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
-	struct controller *ctrl;
-	u8 bus;
-	u8 devfn;
-	u8 device;
-	u8 function;
-	
-	if (slot == NULL)
-		return -ENODEV;
-	
-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-
-	ctrl = slot->ctrl;
-	if (ctrl == NULL)
-		return -ENODEV;
-	
-	if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
-		return -ENODEV;
-
-	device = devfn >> 3;
-	function = devfn & 0x7;
-	dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function);
-
-	slot_func = cpqhp_slot_find(bus, device, function);
-	if (!slot_func) {
-		return -ENODEV;
-	}
-	
-	dbg("In power_down_board, slot_func = %p, ctrl = %p\n", slot_func, ctrl);
-	return cpqhp_process_SS(ctrl, slot_func);
-}
-
-
-static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value)
-{
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
-	struct controller *ctrl;
-
-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-
-	if (slot == NULL)
-		return -ENODEV;
-
-	ctrl = slot->ctrl;
-	if (ctrl == NULL)
-		return -ENODEV;
-
-	return cpqhp_hardware_test (ctrl, value);	
-}
-
-
-static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
-{
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
-	struct controller *ctrl;
-	
-	if (slot == NULL)
-		return -ENODEV;
-	
-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-
-	ctrl = slot->ctrl;
-	if (ctrl == NULL)
-		return -ENODEV;
-	
-	*value = get_slot_enabled(ctrl, slot);
-	return 0;
-}
-
-static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
-{
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
-	struct controller *ctrl;
-	
-	if (slot == NULL)
-		return -ENODEV;
-	
-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-
-	ctrl = slot->ctrl;
-	if (ctrl == NULL)
-		return -ENODEV;
-	
-	*value = cpq_get_attention_status(ctrl, slot);
-	return 0;
-}
-
-static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
-{
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
-	struct controller *ctrl;
-	
-	if (slot == NULL)
-		return -ENODEV;
-	
-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-
-	ctrl = slot->ctrl;
-	if (ctrl == NULL)
-		return -ENODEV;
-	
-	*value = cpq_get_latch_status (ctrl, slot);
-
-	return 0;
-}
-
-static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
-{
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
-	struct controller *ctrl;
-	
-	if (slot == NULL)
-		return -ENODEV;
-
-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-
-	ctrl = slot->ctrl;
-	if (ctrl == NULL)
-		return -ENODEV;
-	
-	*value = get_presence_status (ctrl, slot);
-
-	return 0;
-}
-
-static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
-{
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
-	struct controller *ctrl;
-	
-	if (slot == NULL)
-		return -ENODEV;
-
-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-
-	ctrl = slot->ctrl;
-	if (ctrl == NULL)
-		return -ENODEV;
-	
-	*value = ctrl->speed_capability;
-
-	return 0;
-}
-
-static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
-{
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
-	struct controller *ctrl;
-	
-	if (slot == NULL)
-		return -ENODEV;
-
-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-
-	ctrl = slot->ctrl;
-	if (ctrl == NULL)
-		return -ENODEV;
-	
-	*value = ctrl->speed;
-
-	return 0;
-}
-
-static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	u8 num_of_slots = 0;
-	u8 hp_slot = 0;
-	u8 device;
-	u8 rev;
-	u8 bus_cap;
-	u16 temp_word;
-	u16 vendor_id;
-	u16 subsystem_vid;
-	u16 subsystem_deviceid;
-	u32 rc;
-	struct controller *ctrl;
-	struct pci_func *func;
-
-	// Need to read VID early b/c it's used to differentiate CPQ and INTC discovery
-	rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
-	if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) {
-		err(msg_HPC_non_compaq_or_intel);
-		return -ENODEV;
-	}
-	dbg("Vendor ID: %x\n", vendor_id);
-
-	rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-	dbg("revision: %d\n", rev);
-	if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!rev))) {
-		err(msg_HPC_rev_error);
-		return -ENODEV;
-	}
-
-	/* Check for the proper subsytem ID's
-	 * Intel uses a different SSID programming model than Compaq.  
-	 * For Intel, each SSID bit identifies a PHP capability.
-	 * Also Intel HPC's may have RID=0.
-	 */
-	if ((rev > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) {
-		// TODO: This code can be made to support non-Compaq or Intel subsystem IDs
-		rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
-		if (rc) {
-			err("%s : pci_read_config_word failed\n", __FUNCTION__);
-			return rc;
-		}
-		dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
-		if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
-			err(msg_HPC_non_compaq_or_intel);
-			return -ENODEV;
-		}
-
-		ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
-		if (!ctrl) {
-			err("%s : out of memory\n", __FUNCTION__);
-			return -ENOMEM;
-		}
-		memset(ctrl, 0, sizeof(struct controller));
-
-		rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
-		if (rc) {
-			err("%s : pci_read_config_word failed\n", __FUNCTION__);
-			goto err_free_ctrl;
-		}
-
-		info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid);
-
-		/* Set Vendor ID, so it can be accessed later from other functions */
-		ctrl->vendor_id = vendor_id;
-
-		switch (subsystem_vid) {
-			case PCI_VENDOR_ID_COMPAQ:
-				if (rev >= 0x13) { /* CIOBX */
-					ctrl->push_flag = 1;
-					ctrl->slot_switch_type = 1;		// Switch is present
-					ctrl->push_button = 1;			// Pushbutton is present
-					ctrl->pci_config_space = 1;		// Index/data access to working registers 0 = not supported, 1 = supported
-					ctrl->defeature_PHP = 1;		// PHP is supported
-					ctrl->pcix_support = 1;			// PCI-X supported
-					ctrl->pcix_speed_capability = 1;
-					pci_read_config_byte(pdev, 0x41, &bus_cap);
-					if (bus_cap & 0x80) {
-						dbg("bus max supports 133MHz PCI-X\n");
-						ctrl->speed_capability = PCI_SPEED_133MHz_PCIX;
-						break;
-					}
-					if (bus_cap & 0x40) {
-						dbg("bus max supports 100MHz PCI-X\n");
-						ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
-						break;
-					}
-					if (bus_cap & 20) {
-						dbg("bus max supports 66MHz PCI-X\n");
-						ctrl->speed_capability = PCI_SPEED_66MHz_PCIX;
-						break;
-					}
-					if (bus_cap & 10) {
-						dbg("bus max supports 66MHz PCI\n");
-						ctrl->speed_capability = PCI_SPEED_66MHz;
-						break;
-					}
-
-					break;
-				}
-
-				switch (subsystem_deviceid) {
-					case PCI_SUB_HPC_ID:
-						/* Original 6500/7000 implementation */
-						ctrl->slot_switch_type = 1;		// Switch is present
-						ctrl->speed_capability = PCI_SPEED_33MHz;
-						ctrl->push_button = 0;			// No pushbutton
-						ctrl->pci_config_space = 1;		// Index/data access to working registers 0 = not supported, 1 = supported
-						ctrl->defeature_PHP = 1;		// PHP is supported
-						ctrl->pcix_support = 0;			// PCI-X not supported
-						ctrl->pcix_speed_capability = 0;	// N/A since PCI-X not supported
-						break;
-					case PCI_SUB_HPC_ID2:
-						/* First Pushbutton implementation */
-						ctrl->push_flag = 1;
-						ctrl->slot_switch_type = 1;		// Switch is present
-						ctrl->speed_capability = PCI_SPEED_33MHz;
-						ctrl->push_button = 1;			// Pushbutton is present
-						ctrl->pci_config_space = 1;		// Index/data access to working registers 0 = not supported, 1 = supported
-						ctrl->defeature_PHP = 1;		// PHP is supported
-						ctrl->pcix_support = 0;			// PCI-X not supported
-						ctrl->pcix_speed_capability = 0;	// N/A since PCI-X not supported
-						break;
-					case PCI_SUB_HPC_ID_INTC:
-						/* Third party (6500/7000) */
-						ctrl->slot_switch_type = 1;		// Switch is present
-						ctrl->speed_capability = PCI_SPEED_33MHz;
-						ctrl->push_button = 0;			// No pushbutton
-						ctrl->pci_config_space = 1;		// Index/data access to working registers 0 = not supported, 1 = supported
-						ctrl->defeature_PHP = 1;			// PHP is supported
-						ctrl->pcix_support = 0;			// PCI-X not supported
-						ctrl->pcix_speed_capability = 0;		// N/A since PCI-X not supported
-						break;
-					case PCI_SUB_HPC_ID3:
-						/* First 66 Mhz implementation */
-						ctrl->push_flag = 1;
-						ctrl->slot_switch_type = 1;		// Switch is present
-						ctrl->speed_capability = PCI_SPEED_66MHz;
-						ctrl->push_button = 1;			// Pushbutton is present
-						ctrl->pci_config_space = 1;		// Index/data access to working registers 0 = not supported, 1 = supported
-						ctrl->defeature_PHP = 1;		// PHP is supported
-						ctrl->pcix_support = 0;			// PCI-X not supported
-						ctrl->pcix_speed_capability = 0;	// N/A since PCI-X not supported
-						break;
-					case PCI_SUB_HPC_ID4:
-						/* First PCI-X implementation, 100MHz */
-						ctrl->push_flag = 1;
-						ctrl->slot_switch_type = 1;		// Switch is present
-						ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
-						ctrl->push_button = 1;			// Pushbutton is present
-						ctrl->pci_config_space = 1;		// Index/data access to working registers 0 = not supported, 1 = supported
-						ctrl->defeature_PHP = 1;		// PHP is supported
-						ctrl->pcix_support = 1;			// PCI-X supported
-						ctrl->pcix_speed_capability = 0;	
-						break;
-					default:
-						err(msg_HPC_not_supported);
-						rc = -ENODEV;
-						goto err_free_ctrl;
-				}
-				break;
-
-			case PCI_VENDOR_ID_INTEL:
-				/* Check for speed capability (0=33, 1=66) */
-				if (subsystem_deviceid & 0x0001) {
-					ctrl->speed_capability = PCI_SPEED_66MHz;
-				} else {
-					ctrl->speed_capability = PCI_SPEED_33MHz;
-				}
-
-				/* Check for push button */
-				if (subsystem_deviceid & 0x0002) {
-					/* no push button */
-					ctrl->push_button = 0;
-				} else {
-					/* push button supported */
-					ctrl->push_button = 1;
-				}
-
-				/* Check for slot switch type (0=mechanical, 1=not mechanical) */
-				if (subsystem_deviceid & 0x0004) {
-					/* no switch */
-					ctrl->slot_switch_type = 0;
-				} else {
-					/* switch */
-					ctrl->slot_switch_type = 1;
-				}
-
-				/* PHP Status (0=De-feature PHP, 1=Normal operation) */
-				if (subsystem_deviceid & 0x0008) {
-					ctrl->defeature_PHP = 1;	// PHP supported
-				} else {
-					ctrl->defeature_PHP = 0;	// PHP not supported
-				}
-
-				/* Alternate Base Address Register Interface (0=not supported, 1=supported) */
-				if (subsystem_deviceid & 0x0010) {
-					ctrl->alternate_base_address = 1;	// supported
-				} else {
-					ctrl->alternate_base_address = 0;	// not supported
-				}
-
-				/* PCI Config Space Index (0=not supported, 1=supported) */
-				if (subsystem_deviceid & 0x0020) {
-					ctrl->pci_config_space = 1;		// supported
-				} else {
-					ctrl->pci_config_space = 0;		// not supported
-				}
-
-				/* PCI-X support */
-				if (subsystem_deviceid & 0x0080) {
-					/* PCI-X capable */
-					ctrl->pcix_support = 1;
-					/* Frequency of operation in PCI-X mode */
-					if (subsystem_deviceid & 0x0040) {
-						/* 133MHz PCI-X if bit 7 is 1 */
-						ctrl->pcix_speed_capability = 1;
-					} else {
-						/* 100MHz PCI-X if bit 7 is 1 and bit 0 is 0, */
-						/* 66MHz PCI-X if bit 7 is 1 and bit 0 is 1 */
-						ctrl->pcix_speed_capability = 0;
-					}
-				} else {
-					/* Conventional PCI */
-					ctrl->pcix_support = 0;
-					ctrl->pcix_speed_capability = 0;
-				}
-				break;
-
-			default:
-				err(msg_HPC_not_supported);
-				rc = -ENODEV;
-				goto err_free_ctrl;
-		}
-
-	} else {
-		err(msg_HPC_not_supported);
-		return -ENODEV;
-	}
-
-	// Tell the user that we found one.
-	info("Initializing the PCI hot plug controller residing on PCI bus %d\n", pdev->bus->number);
-
-	dbg ("Hotplug controller capabilities:\n");
-	dbg ("    speed_capability       %d\n", ctrl->speed_capability);
-	dbg ("    slot_switch_type       %s\n", ctrl->slot_switch_type == 0 ? "no switch" : "switch present");
-	dbg ("    defeature_PHP          %s\n", ctrl->defeature_PHP == 0 ? "PHP not supported" : "PHP supported");
-	dbg ("    alternate_base_address %s\n", ctrl->alternate_base_address == 0 ? "not supported" : "supported");
-	dbg ("    pci_config_space       %s\n", ctrl->pci_config_space == 0 ? "not supported" : "supported");
-	dbg ("    pcix_speed_capability  %s\n", ctrl->pcix_speed_capability == 0 ? "not supported" : "supported");
-	dbg ("    pcix_support           %s\n", ctrl->pcix_support == 0 ? "not supported" : "supported");
-
-	ctrl->pci_dev = pdev;
-	pci_set_drvdata(pdev, ctrl);
-
-	/* make our own copy of the pci bus structure, as we like tweaking it a lot */
-	ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL);
-	if (!ctrl->pci_bus) {
-		err("out of memory\n");
-		rc = -ENOMEM;
-		goto err_free_ctrl;
-	}
-	memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus));
-
-	ctrl->bus = pdev->bus->number;
-	ctrl->rev = rev;
-	dbg("bus device function rev: %d %d %d %d\n", ctrl->bus,
-	     PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev);
-
-	init_MUTEX(&ctrl->crit_sect);
-	init_waitqueue_head(&ctrl->queue);
-
-	/* initialize our threads if they haven't already been started up */
-	rc = one_time_init();
-	if (rc) {
-		goto err_free_bus;
-	}
-	
-	dbg("pdev = %p\n", pdev);
-	dbg("pci resource start %lx\n", pci_resource_start(pdev, 0));
-	dbg("pci resource len %lx\n", pci_resource_len(pdev, 0));
-
-	if (!request_mem_region(pci_resource_start(pdev, 0),
-				pci_resource_len(pdev, 0), MY_NAME)) {
-		err("cannot reserve MMIO region\n");
-		rc = -ENOMEM;
-		goto err_free_bus;
-	}
-
-	ctrl->hpc_reg = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
-	if (!ctrl->hpc_reg) {
-		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;
-	}
-
-	// Check for 66Mhz operation
-	ctrl->speed = get_controller_speed(ctrl);
-
-
-	//**************************************************
-	//
-	//              Save configuration headers for this and
-	//              subordinate PCI buses
-	//
-	//**************************************************
-
-	// find the physical slot number of the first hot plug slot
-
-	// Get slot won't work for devices behind bridges, but
-	// in this case it will always be called for the "base"
-	// bus/dev/func of a slot.
-	// CS: this is leveraging the PCIIRQ routing code from the kernel (pci-pc.c: get_irq_routing_table)
-	rc = get_slot_mapping(ctrl->pci_bus, pdev->bus->number, (readb(ctrl->hpc_reg + SLOT_MASK) >> 4), &(ctrl->first_slot));
-	dbg("get_slot_mapping: first_slot = %d, returned = %d\n", ctrl->first_slot, rc);
-	if (rc) {
-		err(msg_initialization_err, rc);
-		goto err_iounmap;
-	}
-
-	// Store PCI Config Space for all devices on this bus
-	rc = cpqhp_save_config(ctrl, ctrl->bus, readb(ctrl->hpc_reg + SLOT_MASK));
-	if (rc) {
-		err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
-		goto err_iounmap;
-	}
-
-	/*
-	 * Get IO, memory, and IRQ resources for new devices
-	 */
-	// The next line is required for cpqhp_find_available_resources
-	ctrl->interrupt = pdev->irq;
-
-	ctrl->cfgspc_irq = 0;
-	pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ctrl->cfgspc_irq);
-
-	rc = cpqhp_find_available_resources(ctrl, cpqhp_rom_start);
-	ctrl->add_support = !rc;
-	if (rc) {
-		dbg("cpqhp_find_available_resources = 0x%x\n", rc);
-		err("unable to locate PCI configuration resources for hot plug add.\n");
-		goto err_iounmap;
-	}
-
-	/*
-	 * Finish setting up the hot plug ctrl device
-	 */
-	ctrl->slot_device_offset = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
-	dbg("NumSlots %d \n", ctrl->slot_device_offset);
-
-	ctrl->next_event = 0;
-
-	/* Setup the slot information structures */
-	rc = ctrl_slot_setup(ctrl, smbios_start, smbios_table);
-	if (rc) {
-		err(msg_initialization_err, 6);
-		err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
-		goto err_iounmap;
-	}
-	
-	/* Mask all general input interrupts */
-	writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_MASK);
-
-	/* set up the interrupt */
-	dbg("HPC interrupt = %d \n", ctrl->interrupt);
-	if (request_irq(ctrl->interrupt, cpqhp_ctrl_intr,
-			SA_SHIRQ, MY_NAME, ctrl)) {
-		err("Can't get irq %d for the hotplug pci controller\n", ctrl->interrupt);
-		rc = -ENODEV;
-		goto err_iounmap;
-	}
-
-	/* Enable Shift Out interrupt and clear it, also enable SERR on power fault */
-	temp_word = readw(ctrl->hpc_reg + MISC);
-	temp_word |= 0x4006;
-	writew(temp_word, ctrl->hpc_reg + MISC);
-
-	// Changed 05/05/97 to clear all interrupts at start
-	writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_INPUT_CLEAR);
-
-	ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
-
-	writel(0x0L, ctrl->hpc_reg + INT_MASK);
-
-	if (!cpqhp_ctrl_list) {
-		cpqhp_ctrl_list = ctrl;
-		ctrl->next = NULL;
-	} else {
-		ctrl->next = cpqhp_ctrl_list;
-		cpqhp_ctrl_list = ctrl;
-	}
-
-	// turn off empty slots here unless command line option "ON" set
-	// Wait for exclusive access to hardware
-	down(&ctrl->crit_sect);
-
-	num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
-
-	// find first device number for the ctrl
-	device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
-
-	while (num_of_slots) {
-		dbg("num_of_slots: %d\n", num_of_slots);
-		func = cpqhp_slot_find(ctrl->bus, device, 0);
-		if (!func)
-			break;
-
-		hp_slot = func->device - ctrl->slot_device_offset;
-		dbg("hp_slot: %d\n", hp_slot);
-
-		// We have to save the presence info for these slots
-		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)) {
-			func->switch_save = 0;
-		} else {
-			func->switch_save = 0x10;
-		}
-
-		if (!power_mode) {
-			if (!func->is_a_board) {
-				green_LED_off (ctrl, hp_slot);
-				slot_disable (ctrl, hp_slot);
-			}
-		}
-
-		device++;
-		num_of_slots--;
-	}
-
-	if (!power_mode) {
-		set_SOGO(ctrl);
-		// Wait for SOBS to be unset
-		wait_for_ctrl_irq (ctrl);
-	}
-
-	rc = init_SERR(ctrl);
-	if (rc) {
-		err("init_SERR failed\n");
-		up(&ctrl->crit_sect);
-		goto err_free_irq;
-	}
-
-	// Done with exclusive hardware access
-	up(&ctrl->crit_sect);
-
-	cpqhp_create_ctrl_files (ctrl);
-
-	return 0;
-
-err_free_irq:
-	free_irq(ctrl->interrupt, ctrl);
-err_iounmap:
-	iounmap(ctrl->hpc_reg);
-err_free_mem_region:
-	release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
-err_free_bus:
-	kfree(ctrl->pci_bus);
-err_free_ctrl:
-	kfree(ctrl);
-	return rc;
-}
-
-
-static int one_time_init(void)
-{
-	int loop;
-	int retval = 0;
-	static int initialized = 0;
-
-	if (initialized)
-		return 0;
-
-	power_mode = 0;
-
-	retval = pci_print_IRQ_route();
-	if (retval)
-		goto error;
-
-	dbg("Initialize + Start the notification mechanism \n");
-
-	retval = cpqhp_event_start_thread();
-	if (retval)
-		goto error;
-
-	dbg("Initialize slot lists\n");
-	for (loop = 0; loop < 256; loop++) {
-		cpqhp_slot_list[loop] = NULL;
-	}
-
-	// FIXME: We also need to hook the NMI handler eventually.
-	// this also needs to be worked with Christoph
-	// register_NMI_handler();
-
-	// Map rom address
-	cpqhp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
-	if (!cpqhp_rom_start) {
-		err ("Could not ioremap memory region for ROM\n");
-		retval = -EIO;;
-		goto error;
-	}
-	
-	/* Now, map the int15 entry point if we are on compaq specific hardware */
-	compaq_nvram_init(cpqhp_rom_start);
-	
-	/* Map smbios table entry point structure */
-	smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start, cpqhp_rom_start + ROM_PHY_LEN);
-	if (!smbios_table) {
-		err ("Could not find the SMBIOS pointer in memory\n");
-		retval = -EIO;;
-		goto error;
-	}
-
-	smbios_start = ioremap(readl(smbios_table + ST_ADDRESS), readw(smbios_table + ST_LENGTH));
-	if (!smbios_start) {
-		err ("Could not ioremap memory region taken from SMBIOS values\n");
-		retval = -EIO;;
-		goto error;
-	}
-
-	initialized = 1;
-
-	return retval;
-
-error:
-	if (cpqhp_rom_start)
-		iounmap(cpqhp_rom_start);
-	if (smbios_start)
-		iounmap(smbios_start);
-	
-	return retval;
-}
-
-
-static void unload_cpqphpd(void)
-{
-	struct pci_func *next;
-	struct pci_func *TempSlot;
-	int loop;
-	u32 rc;
-	struct controller *ctrl;
-	struct controller *tctrl;
-	struct pci_resource *res;
-	struct pci_resource *tres;
-
-	rc = compaq_nvram_store(cpqhp_rom_start);
-
-	ctrl = cpqhp_ctrl_list;
-
-	while (ctrl) {
-		if (ctrl->hpc_reg) {
-			u16 misc;
-			rc = read_slot_enable (ctrl);
-			
-			writeb(0, ctrl->hpc_reg + SLOT_SERR);
-			writel(0xFFFFFFC0L | ~rc, ctrl->hpc_reg + INT_MASK);
-			
-			misc = readw(ctrl->hpc_reg + MISC);
-			misc &= 0xFFFD;
-			writew(misc, ctrl->hpc_reg + MISC);
-		}
-
-		ctrl_slot_cleanup(ctrl);
-
-		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);
-		}
-
-		kfree (ctrl->pci_bus);
-
-		tctrl = ctrl;
-		ctrl = ctrl->next;
-		kfree(tctrl);
-	}
-
-	for (loop = 0; loop < 256; loop++) {
-		next = cpqhp_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);
-		}
-	}
-
-	// Stop the notification mechanism
-	cpqhp_event_stop_thread();
-
-	//unmap the rom address
-	if (cpqhp_rom_start)
-		iounmap(cpqhp_rom_start);
-	if (smbios_start)
-		iounmap(smbios_start);
-}
-
-
-
-static struct pci_device_id hpcd_pci_tbl[] __devinitdata = {
-	{
-	/* handle any PCI Hotplug controller */
-	.class =        ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00),
-	.class_mask =   ~0,
-	
-	/* no matter who makes it */
-	.vendor =       PCI_ANY_ID,
-	.device =       PCI_ANY_ID,
-	.subvendor =    PCI_ANY_ID,
-	.subdevice =    PCI_ANY_ID,
-	
-	}, { /* end: all zeroes */ }
-};
-
-MODULE_DEVICE_TABLE(pci, hpcd_pci_tbl);
-
-
-
-static struct pci_driver cpqhpc_driver = {
-	.name =		"pci_hotplug",
-	.id_table =	hpcd_pci_tbl,
-	.probe =	cpqhpc_probe,
-	/* remove:	cpqhpc_remove_one, */
-};
-
-
-
-static int __init cpqhpc_init(void)
-{
-	int result;
-
-	cpqhp_debug = debug;
-
-	result = pci_module_init(&cpqhpc_driver);
-	dbg("pci_module_init = %d\n", result);
-	if (result)
-		return result;
-	info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
-	return 0;
-}
-
-
-static void __exit cpqhpc_cleanup(void)
-{
-	dbg("unload_cpqphpd()\n");
-	unload_cpqphpd();
-
-	dbg("pci_unregister_driver\n");
-	pci_unregister_driver(&cpqhpc_driver);
-}
-
-
-module_init(cpqhpc_init);
-module_exit(cpqhpc_cleanup);
-
-
diff -Nru a/drivers/hotplug/cpqphp_ctrl.c b/drivers/hotplug/cpqphp_ctrl.c
--- a/drivers/hotplug/cpqphp_ctrl.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,3084 +0,0 @@
-/*
- * Compaq Hot Plug Controller Driver
- *
- * Copyright (c) 1995,2001 Compaq Computer Corporation
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001 IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <greg@kroah.com>
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
-#include <linux/smp_lock.h>
-#include <linux/pci.h>
-#include "cpqphp.h"
-
-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);
-static void interrupt_event_handler(struct controller *ctrl);
-
-static struct semaphore event_semaphore;	/* mutex for process loop (up if something to process) */
-static struct semaphore event_exit;		/* guard ensure thread has exited before calling it quits */
-static int event_finished;
-static unsigned long pushbutton_pending;	/* = 0 */
-
-/* things needed for the long_delay function */
-static struct semaphore		delay_sem;
-static wait_queue_head_t	delay_wait;
-
-/* delay is in jiffies to wait for */
-static void long_delay (int delay)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	
-	/* only allow 1 customer into the delay queue at once
-	 * yes this makes some people wait even longer, but who really cares?
-	 * this is for _huge_ delays to make the hardware happy as the 
-	 * signals bounce around
-	 */
-	down (&delay_sem);
-
-	init_waitqueue_head (&delay_wait);
-
-	add_wait_queue(&delay_wait, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(delay);
-	remove_wait_queue(&delay_wait, &wait);
-	set_current_state(TASK_RUNNING);
-	
-	up (&delay_sem);
-}
-
-
-//FIXME: The following line needs to be somewhere else...
-#define WRONG_BUS_FREQUENCY 0x07
-static u8 handle_switch_change(u8 change, struct controller * ctrl)
-{
-	int hp_slot;
-	u8 rc = 0;
-	u16 temp_word;
-	struct pci_func *func;
-	struct event_info *taskInfo;
-
-	if (!change)
-		return 0;
-
-	// Switch Change
-	dbg("cpqsbd:  Switch interrupt received.\n");
-
-	for (hp_slot = 0; hp_slot < 6; hp_slot++) {
-		if (change & (0x1L << hp_slot)) {
-			//*********************************
-			// this one changed.
-			//*********************************
-			func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0);
-
-			//this is the structure that tells the worker thread
-			//what to do
-			taskInfo = &(ctrl->event_queue[ctrl->next_event]);
-			ctrl->next_event = (ctrl->next_event + 1) % 10;
-			taskInfo->hp_slot = hp_slot;
-
-			rc++;
-
-			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)) {
-				//*********************************
-				// Switch opened
-				//*********************************
-
-				func->switch_save = 0;
-
-				taskInfo->event_type = INT_SWITCH_OPEN;
-			} else {
-				//*********************************
-				// Switch closed
-				//*********************************
-
-				func->switch_save = 0x10;
-
-				taskInfo->event_type = INT_SWITCH_CLOSE;
-			}
-		}
-	}
-
-	return rc;
-}
-
-
-/*
- * cpqhp_find_slot
- */
-struct slot *cpqhp_find_slot (struct controller * ctrl, u8 device)
-{
-	struct slot *slot;
-
-	if (!ctrl)
-		return NULL;
-
-	slot = ctrl->slot;
-
-	while (slot && (slot->device != device)) {
-		slot = slot->next;
-	}
-
-	return slot;
-}
-
-
-static u8 handle_presence_change(u16 change, struct controller * ctrl)
-{
-	int hp_slot;
-	u8 rc = 0;
-	u8 temp_byte;
-	u16 temp_word;
-	struct pci_func *func;
-	struct event_info *taskInfo;
-	struct slot *p_slot;
-
-	if (!change)
-		return 0;
-
-	//*********************************
-	// Presence Change
-	//*********************************
-	dbg("cpqsbd:  Presence/Notify input change.\n");
-	dbg("         Changed bits are 0x%4.4x\n", change );
-
-	for (hp_slot = 0; hp_slot < 6; hp_slot++) {
-		if (change & (0x0101 << hp_slot)) {
-			//*********************************
-			// this one changed.
-			//*********************************
-			func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0);
-
-			taskInfo = &(ctrl->event_queue[ctrl->next_event]);
-			ctrl->next_event = (ctrl->next_event + 1) % 10;
-			taskInfo->hp_slot = hp_slot;
-
-			rc++;
-
-			p_slot = cpqhp_find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4));
-			if (!p_slot)
-				return 0;
-
-			// If the switch closed, must be a button
-			// If not in button mode, nevermind
-			if (func->switch_save && (ctrl->push_button == 1)) {
-				temp_word = ctrl->ctrl_int_comp >> 16;
-				temp_byte = (temp_word >> hp_slot) & 0x01;
-				temp_byte |= (temp_word >> (hp_slot + 7)) & 0x02;
-
-				if (temp_byte != func->presence_save) {
-					//*********************************
-					// button Pressed (doesn't do anything)
-					//*********************************
-					dbg("hp_slot %d button pressed\n", hp_slot);
-					taskInfo->event_type = INT_BUTTON_PRESS;
-				} else {
-					//*********************************
-					// button Released - TAKE ACTION!!!!
-					//*********************************
-					dbg("hp_slot %d button released\n", hp_slot);
-					taskInfo->event_type = INT_BUTTON_RELEASE;
-
-					// Cancel if we are still blinking
-					if ((p_slot->state == BLINKINGON_STATE)
-					    || (p_slot->state == BLINKINGOFF_STATE)) {
-						taskInfo->event_type = INT_BUTTON_CANCEL;
-						dbg("hp_slot %d button cancel\n", hp_slot);
-					} else if ((p_slot->state == POWERON_STATE)
-						   || (p_slot->state == POWEROFF_STATE)) {
-						//info(msg_button_ignore, p_slot->number);
-						taskInfo->event_type = INT_BUTTON_IGNORE;
-						dbg("hp_slot %d button ignore\n", hp_slot);
-					}
-				}
-			} else {
-				// Switch is open, assume a presence change
-				// Save the presence state
-				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 & (0x010000 << hp_slot))) ||
-				    (!(ctrl->ctrl_int_comp & (0x01000000 << hp_slot)))) {
-					//*********************************
-					// Present
-					//*********************************
-					taskInfo->event_type = INT_PRESENCE_ON;
-				} else {
-					//*********************************
-					// Not Present
-					//*********************************
-					taskInfo->event_type = INT_PRESENCE_OFF;
-				}
-			}
-		}
-	}
-
-	return rc;
-}
-
-
-static u8 handle_power_fault(u8 change, struct controller * ctrl)
-{
-	int hp_slot;
-	u8 rc = 0;
-	struct pci_func *func;
-	struct event_info *taskInfo;
-
-	if (!change)
-		return 0;
-
-	//*********************************
-	// power fault
-	//*********************************
-
-	info("power fault interrupt\n");
-
-	for (hp_slot = 0; hp_slot < 6; hp_slot++) {
-		if (change & (0x01 << hp_slot)) {
-			//*********************************
-			// this one changed.
-			//*********************************
-			func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0);
-
-			taskInfo = &(ctrl->event_queue[ctrl->next_event]);
-			ctrl->next_event = (ctrl->next_event + 1) % 10;
-			taskInfo->hp_slot = hp_slot;
-
-			rc++;
-
-			if (ctrl->ctrl_int_comp & (0x00000100 << hp_slot)) {
-				//*********************************
-				// power fault Cleared
-				//*********************************
-				func->status = 0x00;
-
-				taskInfo->event_type = INT_POWER_FAULT_CLEAR;
-			} else {
-				//*********************************
-				// power fault
-				//*********************************
-				taskInfo->event_type = INT_POWER_FAULT;
-
-				if (ctrl->rev < 4) {
-					amber_LED_on (ctrl, hp_slot);
-					green_LED_off (ctrl, hp_slot);
-					set_SOGO (ctrl);
-
-					// this is a fatal condition, we want to crash the
-					// machine to protect from data corruption
-					// simulated_NMI shouldn't ever return
-					//FIXME
-					//simulated_NMI(hp_slot, ctrl);
-
-					//The following code causes a software crash just in
-					//case simulated_NMI did return
-					//FIXME
-					//panic(msg_power_fault);
-				} else {
-					// set power fault status for this board
-					func->status = 0xFF;
-					info("power fault bit %x set\n", hp_slot);
-				}
-			}
-		}
-	}
-
-	return rc;
-}
-
-
-/*
- * 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);
-}
-
-
-/*
- * 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);
-}
-
-
-/*
- * 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("do_pre_bridge_resource_split\n");
-
-	if (!(*head) || !(*orig_head))
-		return(NULL);
-
-	rc = cpqhp_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 = cpqhp_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);
-}
-
-
-/*
- * 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 ( cpqhp_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_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 (cpqhp_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_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 ( cpqhp_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);
-}
-
-
-/*
- * cpqhp_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 cpqhp_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("*head->next = %p\n",(*head)->next);
-
-	if (!(*head)->next)
-		return(0);	/* only one item on the list, already sorted! */
-
-	dbg("*head->base = 0x%x\n",(*head)->base);
-	dbg("*head->next->base = 0x%x\n",(*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("8..\n");
-			node1->length += node1->next->length;
-			node2 = node1->next;
-			node1->next = node1->next->next;
-			kfree(node2);
-		} else
-			node1 = node1->next;
-	}
-
-	return(0);
-}
-
-
-irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data, struct pt_regs *regs)
-{
-	struct controller *ctrl = data;
-	u8 schedule_flag = 0;
-	u8 reset;
-	u16 misc;
-	u32 Diff;
-	u32 temp_dword;
-
-	
-	misc = readw(ctrl->hpc_reg + MISC);
-	//*********************************
-	// Check to see if it was our interrupt
-	//*********************************
-	if (!(misc & 0x000C)) {
-		return IRQ_NONE;
-	}
-
-	if (misc & 0x0004) {
-		//*********************************
-		// Serial Output interrupt Pending
-		//*********************************
-
-		// Clear the interrupt
-		misc |= 0x0004;
-		writew(misc, ctrl->hpc_reg + MISC);
-
-		// Read to clear posted writes
-		misc = readw(ctrl->hpc_reg + MISC);
-
-		dbg ("%s - waking up\n", __FUNCTION__);
-		wake_up_interruptible(&ctrl->queue);
-	}
-
-	if (misc & 0x0008) {
-		// General-interrupt-input interrupt Pending
-		Diff = readl(ctrl->hpc_reg + INT_INPUT_CLEAR) ^ ctrl->ctrl_int_comp;
-
-		ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
-
-		// Clear the interrupt
-		writel(Diff, ctrl->hpc_reg + INT_INPUT_CLEAR);
-
-		// Read it back to clear any posted writes
-		temp_dword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
-
-		if (!Diff) {
-			// Clear all interrupts
-			writel(0xFFFFFFFF, ctrl->hpc_reg + INT_INPUT_CLEAR);
-		}
-
-		schedule_flag += handle_switch_change((u8)(Diff & 0xFFL), ctrl);
-		schedule_flag += handle_presence_change((u16)((Diff & 0xFFFF0000L) >> 16), ctrl);
-		schedule_flag += handle_power_fault((u8)((Diff & 0xFF00L) >> 8), ctrl);
-	}
-
-	reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE);
-	if (reset & 0x40) {
-		/* Bus reset has completed */
-		reset &= 0xCF;
-		writeb(reset, ctrl->hpc_reg + RESET_FREQ_MODE);
-		reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE);
-		wake_up_interruptible(&ctrl->queue);
-	}
-
-	if (schedule_flag) {
-		up(&event_semaphore);
-		dbg("Signal event_semaphore\n");
-	}
-	return IRQ_HANDLED;
-}
-
-
-/**
- * cpqhp_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 *cpqhp_slot_create(u8 busnumber)
-{
-	struct pci_func *new_slot;
-	struct pci_func *next;
-
-	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 (cpqhp_slot_list[busnumber] == NULL) {
-		cpqhp_slot_list[busnumber] = new_slot;
-	} else {
-		next = cpqhp_slot_list[busnumber];
-		while (next->next != NULL)
-			next = next->next;
-		next->next = new_slot;
-	}
-	return(new_slot);
-}
-
-
-/*
- * 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;
-
-	if (old_slot == NULL)
-		return(1);
-
-	next = cpqhp_slot_list[old_slot->bus];
-
-	if (next == NULL) {
-		return(1);
-	}
-
-	if (next == old_slot) {
-		cpqhp_slot_list[old_slot->bus] = old_slot->next;
-		cpqhp_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;
-		cpqhp_destroy_board_resources(old_slot);
-		kfree(old_slot);
-		return(0);
-	} else
-		return(2);
-}
-
-
-/**
- * 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;
-
-	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 = cpqhp_slot_list[tempBus];
-
-		while (!slot_remove(next)) {
-			next = cpqhp_slot_list[tempBus];
-		}
-	}
-
-	next = cpqhp_slot_list[bridge->bus];
-
-	if (next == NULL) {
-		return(1);
-	}
-
-	if (next == bridge) {
-		cpqhp_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);
-}
-
-
-/**
- * cpqhp_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 *cpqhp_slot_find(u8 bus, u8 device, u8 index)
-{
-	int found = -1;
-	struct pci_func *func;
-
-	func = cpqhp_slot_list[bus];
-
-	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);
-}
-
-
-// DJZ: I don't think is_bridge will work as is.
-//FIXME
-static int is_bridge(struct pci_func * func)
-{
-	// Check the header type
-	if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)
-		return 1;
-	else
-		return 0;
-}
-
-
-/* the following routines constitute the bulk of the 
-   hotplug controller logic
- */
-
-
-/**
- * board_replaced - Called after a board has been replaced in the system.
- *
- * This is only used if we don't have resources for hot add
- * Turns power on for the board
- * Checks to see if board is the same
- * If board is same, reconfigures it
- * If board isn't same, turns it back off.
- *
- */
-static u32 board_replaced(struct pci_func * func, struct controller * ctrl)
-{
-	u8 hp_slot;
-	u8 temp_byte;
-	u8 adapter_speed;
-	u32 index;
-	u32 rc = 0;
-	u32 src = 8;
-
-	hp_slot = func->device - ctrl->slot_device_offset;
-
-	if (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot)) {
-		//*********************************
-		// The switch is open.
-		//*********************************
-		rc = INTERLOCK_OPEN;
-	} else if (is_slot_enabled (ctrl, hp_slot)) {
-		//*********************************
-		// The board is already on
-		//*********************************
-		rc = CARD_FUNCTIONING;
-	} else {
-		// Wait for exclusive access to hardware
-		down(&ctrl->crit_sect);
-
-		// turn on board without attaching to the bus
-		enable_slot_power (ctrl, hp_slot);
-
-		set_SOGO(ctrl);
-
-		// Wait for SOBS to be unset
-		wait_for_ctrl_irq (ctrl);
-
-		// Change bits in slot power register to force another shift out
-		// NOTE: this is to work around the timer bug
-		temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
-		writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
-		writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
-
-		set_SOGO(ctrl);
-
-		// Wait for SOBS to be unset
-		wait_for_ctrl_irq (ctrl);
-		
-		adapter_speed = get_adapter_speed(ctrl, hp_slot);
-		if (ctrl->speed != adapter_speed)
-			if (set_controller_speed(ctrl, adapter_speed, hp_slot))
-				rc = WRONG_BUS_FREQUENCY;
-
-		// turn off board without attaching to the bus
-		disable_slot_power (ctrl, hp_slot);
-
-		set_SOGO(ctrl);
-
-		// Wait for SOBS to be unset
-		wait_for_ctrl_irq (ctrl);
-
-		// Done with exclusive hardware access
-		up(&ctrl->crit_sect);
-
-		if (rc)
-			return(rc);
-
-		// Wait for exclusive access to hardware
-		down(&ctrl->crit_sect);
-
-		slot_enable (ctrl, hp_slot);
-		green_LED_blink (ctrl, hp_slot);
-
-		amber_LED_off (ctrl, hp_slot);
-
-		set_SOGO(ctrl);
-
-		// Wait for SOBS to be unset
-		wait_for_ctrl_irq (ctrl);
-
-		// Done with exclusive hardware access
-		up(&ctrl->crit_sect);
-
-		// Wait for ~1 second because of hot plug spec
-		long_delay(1*HZ);
-
-		// Check for a power fault
-		if (func->status == 0xFF) {
-			// power fault occurred, but it was benign
-			rc = POWER_FAILURE;
-			func->status = 0;
-		} else
-			rc = cpqhp_valid_replace(ctrl, func);
-
-		if (!rc) {
-			// It must be the same board
-
-			rc = cpqhp_configure_board(ctrl, func);
-
-			if (rc || src) {
-				// If configuration fails, turn it off
-				// Get slot won't work for devices behind bridges, but
-				// in this case it will always be called for the "base"
-				// bus/dev/func of an adapter.
-
-				// Wait for exclusive access to hardware
-				down(&ctrl->crit_sect);
-
-				amber_LED_on (ctrl, hp_slot);
-				green_LED_off (ctrl, hp_slot);
-				slot_disable (ctrl, hp_slot);
-
-				set_SOGO(ctrl);
-
-				// Wait for SOBS to be unset
-				wait_for_ctrl_irq (ctrl);
-
-				// Done with exclusive hardware access
-				up(&ctrl->crit_sect);
-
-				if (rc)
-					return(rc);
-				else
-					return(1);
-			}
-
-			func->status = 0;
-			func->switch_save = 0x10;
-
-			index = 1;
-			while (((func = cpqhp_slot_find(func->bus, func->device, index)) != NULL) && !rc) {
-				rc |= cpqhp_configure_board(ctrl, func);
-				index++;
-			}
-
-			if (rc) {
-				// If configuration fails, turn it off
-				// Get slot won't work for devices behind bridges, but
-				// in this case it will always be called for the "base"
-				// bus/dev/func of an adapter.
-
-				// Wait for exclusive access to hardware
-				down(&ctrl->crit_sect);
-
-				amber_LED_on (ctrl, hp_slot);
-				green_LED_off (ctrl, hp_slot);
-				slot_disable (ctrl, hp_slot);
-
-				set_SOGO(ctrl);
-
-				// Wait for SOBS to be unset
-				wait_for_ctrl_irq (ctrl);
-
-				// Done with exclusive hardware access
-				up(&ctrl->crit_sect);
-
-				return(rc);
-			}
-			// Done configuring so turn LED on full time
-
-			// Wait for exclusive access to hardware
-			down(&ctrl->crit_sect);
-
-			green_LED_on (ctrl, hp_slot);
-
-			set_SOGO(ctrl);
-
-			// Wait for SOBS to be unset
-			wait_for_ctrl_irq (ctrl);
-
-			// Done with exclusive hardware access
-			up(&ctrl->crit_sect);
-			rc = 0;
-		} else {
-			// Something is wrong
-
-			// Get slot won't work for devices behind bridges, but
-			// in this case it will always be called for the "base"
-			// bus/dev/func of an adapter.
-
-			// Wait for exclusive access to hardware
-			down(&ctrl->crit_sect);
-
-			amber_LED_on (ctrl, hp_slot);
-			green_LED_off (ctrl, hp_slot);
-			slot_disable (ctrl, hp_slot);
-
-			set_SOGO(ctrl);
-
-			// Wait for SOBS to be unset
-			wait_for_ctrl_irq (ctrl);
-
-			// Done with exclusive hardware access
-			up(&ctrl->crit_sect);
-		}
-
-	}
-	return(rc);
-
-}
-
-
-/**
- * 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)
-{
-	u8 hp_slot;
-	u8 temp_byte;
-	u8 adapter_speed;
-	int index;
-	u32 temp_register = 0xFFFFFFFF;
-	u32 rc = 0;
-	struct pci_func *new_slot = NULL;
-	struct slot *p_slot;
-	struct resource_lists res_lists;
-
-	hp_slot = func->device - ctrl->slot_device_offset;
-	dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n",
-	    __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
-
-	// Wait for exclusive access to hardware
-	down(&ctrl->crit_sect);
-
-	// turn on board without attaching to the bus
-	enable_slot_power (ctrl, hp_slot);
-
-	set_SOGO(ctrl);
-
-	// Wait for SOBS to be unset
-	wait_for_ctrl_irq (ctrl);
-
-	// Change bits in slot power register to force another shift out
-	// NOTE: this is to work around the timer bug
-	temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
-	writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
-	writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
-
-	set_SOGO(ctrl);
-
-	// Wait for SOBS to be unset
-	wait_for_ctrl_irq (ctrl);
-	
-	adapter_speed = get_adapter_speed(ctrl, hp_slot);
-	if (ctrl->speed != adapter_speed)
-		if (set_controller_speed(ctrl, adapter_speed, hp_slot))
-			rc = WRONG_BUS_FREQUENCY;
-	
-	// turn off board without attaching to the bus
-	disable_slot_power (ctrl, hp_slot);
-
-	set_SOGO(ctrl);
-
-	// Wait for SOBS to be unset
-	wait_for_ctrl_irq (ctrl);
-
-	// Done with exclusive hardware access
-	up(&ctrl->crit_sect);
-
-	if (rc)
-		return(rc);
-	
-	p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-
-	// turn on board and blink green LED
-
-	// Wait for exclusive access to hardware
-	dbg("%s: before down\n", __FUNCTION__);
-	down(&ctrl->crit_sect);
-	dbg("%s: after down\n", __FUNCTION__);
-
-	dbg("%s: before slot_enable\n", __FUNCTION__);
-	slot_enable (ctrl, hp_slot);
-
-	dbg("%s: before green_LED_blink\n", __FUNCTION__);
-	green_LED_blink (ctrl, hp_slot);
-
-	dbg("%s: before amber_LED_blink\n", __FUNCTION__);
-	amber_LED_off (ctrl, hp_slot);
-
-	dbg("%s: before set_SOGO\n", __FUNCTION__);
-	set_SOGO(ctrl);
-
-	// Wait for SOBS to be unset
-	dbg("%s: before wait_for_ctrl_irq\n", __FUNCTION__);
-	wait_for_ctrl_irq (ctrl);
-	dbg("%s: after wait_for_ctrl_irq\n", __FUNCTION__);
-
-	// Done with exclusive hardware access
-	dbg("%s: before up\n", __FUNCTION__);
-	up(&ctrl->crit_sect);
-	dbg("%s: after up\n", __FUNCTION__);
-
-	// Wait for ~1 second because of hot plug spec
-	dbg("%s: before long_delay\n", __FUNCTION__);
-	long_delay(1*HZ);
-	dbg("%s: after long_delay\n", __FUNCTION__);
-
-	dbg("%s: func status = %x\n", __FUNCTION__, func->status);
-	// Check for a power fault
-	if (func->status == 0xFF) {
-		// power fault occurred, but it was benign
-		temp_register = 0xFFFFFFFF;
-		dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register);
-		rc = POWER_FAILURE;
-		func->status = 0;
-	} else {
-		// Get vendor/device ID u32
-		ctrl->pci_bus->number = func->bus;
-		rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(func->device, func->function), PCI_VENDOR_ID, &temp_register);
-		dbg("%s: pci_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;
-
-		cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
-		cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
-		cpqhp_resource_sort_and_combine(&(ctrl->io_head));
-		cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
-
-		if (rc) {
-			// Wait for exclusive access to hardware
-			down(&ctrl->crit_sect);
-
-			amber_LED_on (ctrl, hp_slot);
-			green_LED_off (ctrl, hp_slot);
-			slot_disable (ctrl, hp_slot);
-
-			set_SOGO(ctrl);
-
-			// Wait for SOBS to be unset
-			wait_for_ctrl_irq (ctrl);
-
-			// Done with exclusive hardware access
-			up(&ctrl->crit_sect);
-			return(rc);
-		} else {
-			cpqhp_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 = cpqhp_slot_find(ctrl->bus, func->device, index++);
-			if (new_slot && !new_slot->pci_dev) {
-				cpqhp_configure_device(ctrl, new_slot);
-			}
-		} while (new_slot);
-
-		// Wait for exclusive access to hardware
-		down(&ctrl->crit_sect);
-
-		green_LED_on (ctrl, hp_slot);
-
-		set_SOGO(ctrl);
-
-		// Wait for SOBS to be unset
-		wait_for_ctrl_irq (ctrl);
-
-		// Done with exclusive hardware access
-		up(&ctrl->crit_sect);
-	} else {
-		// Wait for exclusive access to hardware
-		down(&ctrl->crit_sect);
-
-		amber_LED_on (ctrl, hp_slot);
-		green_LED_off (ctrl, hp_slot);
-		slot_disable (ctrl, hp_slot);
-
-		set_SOGO(ctrl);
-
-		// Wait for SOBS to be unset
-		wait_for_ctrl_irq (ctrl);
-
-		// Done with exclusive hardware access
-		up(&ctrl->crit_sect);
-
-		return(rc);
-	}
-	return 0;
-}
-
-
-/**
- * remove_board - Turns off slot and LED's
- *
- */
-static u32 remove_board(struct pci_func * func, u32 replace_flag, struct controller * ctrl)
-{
-	int index;
-	u8 skip = 0;
-	u8 device;
-	u8 hp_slot;
-	u8 temp_byte;
-	u32 rc;
-	struct resource_lists res_lists;
-	struct pci_func *temp_func;
-
-	if (func == NULL)
-		return(1);
-
-	if (cpqhp_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 = cpqhp_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 = cpqhp_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 = cpqhp_slot_find(temp_func->bus, temp_func->device, index++);
-		}
-
-		if (!skip)
-			rc = cpqhp_save_used_resources(ctrl, func);
-	}
-	// Change status to shutdown
-	if (func->is_a_board)
-		func->status = 0x01;
-	func->configured = 0;
-
-	// Wait for exclusive access to hardware
-	down(&ctrl->crit_sect);
-
-	green_LED_off (ctrl, hp_slot);
-	slot_disable (ctrl, hp_slot);
-
-	set_SOGO(ctrl);
-
-	// turn off SERR for slot
-	temp_byte = readb(ctrl->hpc_reg + SLOT_SERR);
-	temp_byte &= ~(0x01 << hp_slot);
-	writeb(temp_byte, ctrl->hpc_reg + SLOT_SERR);
-
-	// Wait for SOBS to be unset
-	wait_for_ctrl_irq (ctrl);
-
-	// Done with exclusive hardware access
-	up(&ctrl->crit_sect);
-
-	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;
-
-			cpqhp_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;
-
-			cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
-			cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
-			cpqhp_resource_sort_and_combine(&(ctrl->io_head));
-			cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
-
-			if (is_bridge(func)) {
-				bridge_slot_remove(func);
-			} else
-				slot_remove(func);
-
-			func = cpqhp_slot_find(ctrl->bus, device, 0);
-		}
-
-		// Setup slot structure with entry for empty slot
-		func = cpqhp_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;
-}
-
-
-static void pushbutton_helper_thread (unsigned long data)
-{
-	pushbutton_pending = data;
-	up(&event_semaphore);
-}
-
-
-// this is the main worker thread
-static int event_thread(void* data)
-{
-	struct controller *ctrl;
-	lock_kernel();
-	daemonize("phpd_event");
-	
-	unlock_kernel();
-
-	while (1) {
-		dbg("!!!!event_thread sleeping\n");
-		down_interruptible (&event_semaphore);
-		dbg("event_thread woken finished = %d\n", event_finished);
-		if (event_finished) break;
-		/* Do stuff here */
-		if (pushbutton_pending)
-			cpqhp_pushbutton_thread(pushbutton_pending);
-		else
-			for (ctrl = cpqhp_ctrl_list; ctrl; ctrl=ctrl->next)
-				interrupt_event_handler(ctrl);
-	}
-	dbg("event_thread signals exit\n");
-	up(&event_exit);
-	return 0;
-}
-
-
-int cpqhp_event_start_thread (void)
-{
-	int pid;
-
-	/* initialize our semaphores */
-	init_MUTEX(&delay_sem);
-	init_MUTEX_LOCKED(&event_semaphore);
-	init_MUTEX_LOCKED(&event_exit);
-	event_finished=0;
-
-	pid = kernel_thread(event_thread, 0, 0);
-	if (pid < 0) {
-		err ("Can't start up our event thread\n");
-		return -1;
-	}
-	dbg("Our event thread pid = %d\n", pid);
-	return 0;
-}
-
-
-void cpqhp_event_stop_thread (void)
-{
-	event_finished = 1;
-	dbg("event_thread finish command given\n");
-	up(&event_semaphore);
-	dbg("wait for event_thread to exit\n");
-	down(&event_exit);
-}
-
-
-static int update_slot_info (struct controller *ctrl, struct slot *slot)
-{
-	struct hotplug_slot_info *info;
-	int result;
-
-	info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
-	if (!info)
-		return -ENOMEM;
-
-	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(slot->hotplug_slot, info);
-	kfree (info);
-	return result;
-}
-
-static void interrupt_event_handler(struct controller *ctrl)
-{
-	int loop = 0;
-	int change = 1;
-	struct pci_func *func;
-	u8 hp_slot;
-	struct slot *p_slot;
-
-	while (change) {
-		change = 0;
-
-		for (loop = 0; loop < 10; loop++) {
-			//dbg("loop %d\n", loop);
-			if (ctrl->event_queue[loop].event_type != 0) {
-				hp_slot = ctrl->event_queue[loop].hp_slot;
-
-				func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0);
-				if (!func)
-					return;
-
-				p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-				if (!p_slot)
-					return;
-
-				dbg("hp_slot %d, func %p, p_slot %p\n",
-				    hp_slot, func, p_slot);
-
-				if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) {
-					dbg("button pressed\n");
-				} else if (ctrl->event_queue[loop].event_type == 
-					   INT_BUTTON_CANCEL) {
-					dbg("button cancel\n");
-					del_timer(&p_slot->task_event);
-
-					// Wait for exclusive access to hardware
-					down(&ctrl->crit_sect);
-
-					if (p_slot->state == BLINKINGOFF_STATE) {
-						// slot is on
-						// turn on green LED
-						dbg("turn on green LED\n");
-						green_LED_on (ctrl, hp_slot);
-					} else if (p_slot->state == BLINKINGON_STATE) {
-						// slot is off
-						// turn off green LED
-						dbg("turn off green LED\n");
-						green_LED_off (ctrl, hp_slot);
-					}
-
-					info(msg_button_cancel, p_slot->number);
-
-					p_slot->state = STATIC_STATE;
-
-					amber_LED_off (ctrl, hp_slot);
-
-					set_SOGO(ctrl);
-
-					// Wait for SOBS to be unset
-					wait_for_ctrl_irq (ctrl);
-
-					// Done with exclusive hardware access
-					up(&ctrl->crit_sect);
-				}
-				// ***********button Released (No action on press...)
-				else if (ctrl->event_queue[loop].event_type == INT_BUTTON_RELEASE) {
-					dbg("button release\n");
-
-					if (is_slot_enabled (ctrl, hp_slot)) {
-						// slot is on
-						dbg("slot is on\n");
-						p_slot->state = BLINKINGOFF_STATE;
-						info(msg_button_off, p_slot->number);
-					} else {
-						// slot is off
-						dbg("slot is off\n");
-						p_slot->state = BLINKINGON_STATE;
-						info(msg_button_on, p_slot->number);
-					}
-					// Wait for exclusive access to hardware
-					down(&ctrl->crit_sect);
-					
-					dbg("blink green LED and turn off amber\n");
-					
-					amber_LED_off (ctrl, hp_slot);
-					green_LED_blink (ctrl, hp_slot);
-					
-					set_SOGO(ctrl);
-
-					// Wait for SOBS to be unset
-					wait_for_ctrl_irq (ctrl);
-
-					// Done with exclusive hardware access
-					up(&ctrl->crit_sect);
-					init_timer(&p_slot->task_event);
-					p_slot->hp_slot = hp_slot;
-					p_slot->ctrl = ctrl;
-//					p_slot->physical_slot = physical_slot;
-					p_slot->task_event.expires = jiffies + 5 * HZ;   // 5 second delay
-					p_slot->task_event.function = pushbutton_helper_thread;
-					p_slot->task_event.data = (u32) p_slot;
-
-					dbg("add_timer p_slot = %p\n", p_slot);
-					add_timer(&p_slot->task_event);
-				}
-				// ***********POWER FAULT
-				else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
-					dbg("power fault\n");
-				} else {
-					/* refresh notification */
-					if (p_slot)
-						update_slot_info(ctrl, p_slot);
-				}
-
-				ctrl->event_queue[loop].event_type = 0;
-
-				change = 1;
-			}
-		}		// End of FOR loop
-	}
-
-	return;
-}
-
-
-/**
- * cpqhp_pushbutton_thread
- *
- * Scheduled procedure to handle blocking stuff for the pushbuttons
- * Handles all pending events and exits.
- *
- */
-void cpqhp_pushbutton_thread (unsigned long slot)
-{
-	u8 hp_slot;
-	u8 device;
-	struct pci_func *func;
-	struct slot *p_slot = (struct slot *) slot;
-	struct controller *ctrl = (struct controller *) p_slot->ctrl;
-
-	pushbutton_pending = 0;
-	hp_slot = p_slot->hp_slot;
-
-	device = p_slot->device;
-
-	if (is_slot_enabled (ctrl, hp_slot)) {
-		p_slot->state = POWEROFF_STATE;
-		// power Down board
-		func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0);
-		dbg("In power_down_board, func = %p, ctrl = %p\n", func, ctrl);
-		if (!func) {
-			dbg("Error! func NULL in %s\n", __FUNCTION__);
-			return ;
-		}
-
-		if (func != NULL && ctrl != NULL) {
-			if (cpqhp_process_SS(ctrl, func) != 0) {
-				amber_LED_on (ctrl, hp_slot);
-				green_LED_on (ctrl, hp_slot);
-				
-				set_SOGO(ctrl);
-
-				// Wait for SOBS to be unset
-				wait_for_ctrl_irq (ctrl);
-			}
-		}
-
-		p_slot->state = STATIC_STATE;
-	} else {
-		p_slot->state = POWERON_STATE;
-		// slot is off
-
-		func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0);
-		dbg("In add_board, func = %p, ctrl = %p\n", func, ctrl);
-		if (!func) {
-			dbg("Error! func NULL in %s\n", __FUNCTION__);
-			return ;
-		}
-
-		if (func != NULL && ctrl != NULL) {
-			if (cpqhp_process_SI(ctrl, func) != 0) {
-				amber_LED_on (ctrl, hp_slot);
-				green_LED_off (ctrl, hp_slot);
-				
-				set_SOGO(ctrl);
-
-				// Wait for SOBS to be unset
-				wait_for_ctrl_irq (ctrl);
-			}
-		}
-
-		p_slot->state = STATIC_STATE;
-	}
-
-	return;
-}
-
-
-int cpqhp_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;
-
-	if (!ctrl)
-		return(1);
-
-	tempdword = 0;
-
-	device = func->device;
-	hp_slot = device - ctrl->slot_device_offset;
-	p_slot = cpqhp_find_slot(ctrl, device);
-	if (p_slot) {
-		physical_slot = p_slot->number;
-	}
-
-	// Check to see if the interlock is closed
-	tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
-
-	if (tempdword & (0x01 << hp_slot)) {
-		return(1);
-	}
-
-	if (func->is_a_board) {
-		rc = board_replaced(func, ctrl);
-	} else {
-		// add board
-		slot_remove(func);
-
-		func = cpqhp_slot_create(ctrl->bus);
-		if (func == NULL) {
-			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;
-
-		if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) {
-			func->switch_save = 0;
-		} else {
-			func->switch_save = 0x10;
-		}
-
-		rc = board_added(func, ctrl);
-		if (rc) {
-			if (is_bridge(func)) {
-				bridge_slot_remove(func);
-			} else
-				slot_remove(func);
-
-			// Setup slot structure with entry for empty slot
-			func = cpqhp_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->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)) {
-				func->switch_save = 0;
-			} else {
-				func->switch_save = 0x10;
-			}
-		}
-	}
-
-	if (rc) {
-		dbg("%s: rc = %d\n", __FUNCTION__, rc);
-	}
-
-	if (p_slot)
-		update_slot_info(ctrl, p_slot);
-
-	return rc;
-}
-
-
-int cpqhp_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;
-	unsigned int devfn;
-	struct slot* p_slot;
-	struct pci_bus *pci_bus = ctrl->pci_bus;
-	int physical_slot=0;
-
-	device = func->device; 
-	func = cpqhp_slot_find(ctrl->bus, device, index++);
-	p_slot = cpqhp_find_slot(ctrl, device);
-	if (p_slot) {
-		physical_slot = p_slot->number;
-	}
-
-	// Make sure there are no video controllers here
-	while (func && !rc) {
-		pci_bus->number = func->bus;
-		devfn = PCI_DEVFN(func->device, func->function);
-
-		// Check the Class Code
-		rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
-		if (rc)
-			return rc;
-
-		if (class_code == PCI_BASE_CLASS_DISPLAY) {
-			/* Display/Video adapter (not supported) */
-			rc = REMOVE_NOT_SUPPORTED;
-		} else {
-			// See if it's a bridge
-			rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
-			if (rc)
-				return rc;
-
-			// If it's a bridge, check the VGA Enable bit
-			if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
-				rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);
-				if (rc)
-					return rc;
-
-				// If the VGA Enable bit is set, remove isn't supported
-				if (BCR & PCI_BRIDGE_CTL_VGA) {
-					rc = REMOVE_NOT_SUPPORTED;
-				}
-			}
-		}
-
-		func = cpqhp_slot_find(ctrl->bus, device, index++);
-	}
-
-	func = cpqhp_slot_find(ctrl->bus, device, 0);
-	if ((func != NULL) && !rc) {
-		//FIXME: Replace flag should be passed into process_SS
-		replace_flag = !(ctrl->add_support);
-		rc = remove_board(func, replace_flag, ctrl);
-	} else if (!rc) {
-		rc = 1;
-	}
-
-	if (p_slot)
-		update_slot_info(ctrl, p_slot);
-
-	return(rc);
-}
-
-
-
-/**
- * hardware_test - runs hardware tests
- *
- * For hot plug ctrl folks to play with.
- * test_num is the number entered in the GUI
- *
- */
-int cpqhp_hardware_test(struct controller *ctrl, int test_num)
-{
-	u32 save_LED;
-	u32 work_LED;
-	int loop;
-	int num_of_slots;
-
-	num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0f;
-
-	switch (test_num) {
-		case 1:
-			// Do stuff here!
-
-			// Do that funky LED thing
-			save_LED = readl(ctrl->hpc_reg + LED_CONTROL);	// so we can restore them later
-			work_LED = 0x01010101;
-			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-			for (loop = 0; loop < num_of_slots; loop++) {
-				set_SOGO(ctrl);
-
-				// Wait for SOGO interrupt
-				wait_for_ctrl_irq (ctrl);
-
-				// Get ready for next iteration
-				work_LED = work_LED << 1;
-				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-				long_delay((2*HZ)/10);
-			}
-			for (loop = 0; loop < num_of_slots; loop++) {
-				work_LED = work_LED >> 1;
-				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-				
-				set_SOGO(ctrl);
-
-				// Wait for SOGO interrupt
-				wait_for_ctrl_irq (ctrl);
-
-				// Get ready for next iteration
-				long_delay((2*HZ)/10);
-			}
-			for (loop = 0; loop < num_of_slots; loop++) {
-				work_LED = work_LED << 1;
-				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-				
-				set_SOGO(ctrl);
-
-				// Wait for SOGO interrupt
-				wait_for_ctrl_irq (ctrl);
-
-				// Get ready for next iteration
-				long_delay((2*HZ)/10);
-			}
-			for (loop = 0; loop < num_of_slots; loop++) {
-				work_LED = work_LED >> 1;
-				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-				
-				set_SOGO(ctrl);
-
-				// Wait for SOGO interrupt
-				wait_for_ctrl_irq (ctrl);
-
-				// Get ready for next iteration
-				long_delay((2*HZ)/10);
-			}
-
-			work_LED = 0x01010000;
-			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-			for (loop = 0; loop < num_of_slots; loop++) {
-				set_SOGO(ctrl);
-
-				// Wait for SOGO interrupt
-				wait_for_ctrl_irq (ctrl);
-
-				// Get ready for next iteration
-				work_LED = work_LED << 1;
-				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-				long_delay((2*HZ)/10);
-			}
-			for (loop = 0; loop < num_of_slots; loop++) {
-				work_LED = work_LED >> 1;
-				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-				
-				set_SOGO(ctrl);
-
-				// Wait for SOGO interrupt
-				wait_for_ctrl_irq (ctrl);
-
-				// Get ready for next iteration
-				long_delay((2*HZ)/10);
-			}
-			work_LED = 0x00000101;
-			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-			for (loop = 0; loop < num_of_slots; loop++) {
-				work_LED = work_LED << 1;
-				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-				
-				set_SOGO(ctrl);
-
-				// Wait for SOGO interrupt
-				wait_for_ctrl_irq (ctrl);
-
-				// Get ready for next iteration
-				long_delay((2*HZ)/10);
-			}
-			for (loop = 0; loop < num_of_slots; loop++) {
-				work_LED = work_LED >> 1;
-				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-				
-				set_SOGO(ctrl);
-
-				// Wait for SOGO interrupt
-				wait_for_ctrl_irq (ctrl);
-
-				// Get ready for next iteration
-				long_delay((2*HZ)/10);
-			}
-
-
-			work_LED = 0x01010000;
-			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-			for (loop = 0; loop < num_of_slots; loop++) {
-				set_SOGO(ctrl);
-
-				// Wait for SOGO interrupt
-				wait_for_ctrl_irq (ctrl);
-
-				// Get ready for next iteration
-				long_delay((3*HZ)/10);
-				work_LED = work_LED >> 16;
-				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-				
-				set_SOGO(ctrl);
-
-				// Wait for SOGO interrupt
-				wait_for_ctrl_irq (ctrl);
-
-				// Get ready for next iteration
-				long_delay((3*HZ)/10);
-				work_LED = work_LED << 16;
-				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-				work_LED = work_LED << 1;
-				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-			}
-
-			writel (save_LED, ctrl->hpc_reg + LED_CONTROL);	// put it back the way it was
-
-			set_SOGO(ctrl);
-
-			// Wait for SOBS to be unset
-			wait_for_ctrl_irq (ctrl);
-			break;
-		case 2:
-			// Do other stuff here!
-			break;
-		case 3:
-			// and more...
-			break;
-	}
-	return 0;
-}
-
-
-/**
- * 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\n", __FUNCTION__);
-	// Check for Multi-function device
-	ctrl->pci_bus->number = func->bus;
-	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("configure_new_function failed %d\n",rc);
-			index = 0;
-
-			while (new_slot) {
-				new_slot = cpqhp_slot_find(new_slot->bus, new_slot->device, index++);
-
-				if (new_slot)
-					cpqhp_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 = cpqhp_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("returning from configure_new_device\n");
-
-	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;
-	unsigned int devfn;
-	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 pci_bus *pci_bus;
-	struct resource_lists temp_resources;
-
-	pci_bus = ctrl->pci_bus;
-	pci_bus->number = func->bus;
-	devfn = PCI_DEVFN(func->device, func->function);
-
-	// Check for Bridge
-	rc = pci_bus_read_config_byte (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("set Primary bus = %d\n", func->bus);
-		rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_PRIMARY_BUS, func->bus);
-		if (rc)
-			return rc;
-
-		// find range of busses to use
-		dbg("find ranges of buses to use\n");
-		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("set Secondary bus = %d\n", bus_node->base);
-		rc = pci_bus_write_config_byte (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("set subordinate bus = %d\n", bus_node->base + bus_node->length - 1);
-		rc = pci_bus_write_config_byte (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 (pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
-		if (rc)
-			return rc;
-		rc = pci_bus_write_config_byte (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 (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);
-		if (!io_node)
-			return -ENOMEM;
-		mem_node = get_max_resource(&(resources->mem_head), 0x100000);
-		if (!mem_node)
-			return -ENOMEM;
-		p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000);
-		if (!p_mem_node)
-			return -ENOMEM;
-		dbg("Setup the IO, memory, and prefetchable windows\n");
-		dbg("io_node\n");
-		dbg("(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next);
-		dbg("mem_node\n");
-		dbg("(base, len, next) (%x, %x, %p)\n", mem_node->base, mem_node->length, mem_node->next);
-		dbg("p_mem_node\n");
-		dbg("(base, len, next) (%x, %x, %p)\n", 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 (pci_bus, devfn, PCI_IO_BASE, temp_byte);
-
-			temp_byte = (io_node->base + io_node->length - 1) >> 8;
-			rc = pci_bus_write_config_byte (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;
-			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
-
-			temp_word = (mem_node->base + mem_node->length - 1) >> 16;
-			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-		} else {
-			temp_word = 0xFFFF;
-			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
-
-			temp_word = 0x0000;
-			rc = pci_bus_write_config_word (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;
-			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
-			temp_word = (p_mem_node->base + p_mem_node->length - 1) >> 16;
-			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-		} else {
-			temp_word = 0xFFFF;
-			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
-			temp_word = 0x0000;
-			rc = pci_bus_write_config_word (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->number = hold_bus_node->base;
-			pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), 0x00, &ID);
-			pci_bus->number = func->bus;
-
-			if (ID != 0xFFFFFFFF) {	  //  device Present
-				// Setup slot structure.
-				new_slot = cpqhp_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("configure_new_device rc=0x%x\n",rc);
-			}	// End of IF (device in slot?)
-		}		// End of FOR loop
-
-		if (rc) {
-			cpqhp_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 = cpqhp_set_irq(func->bus, func->device,
-							   0x0A + cloop, irqs.interrupt[cloop]);
-					if (rc) {
-						cpqhp_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
-			rc = pci_bus_write_config_byte (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;
-				rc = pci_bus_write_config_word (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;
-					rc = pci_bus_write_config_byte (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;
-					rc = pci_bus_write_config_word (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;
-				rc = pci_bus_write_config_word (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;
-					rc = pci_bus_write_config_word (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;
-					rc = pci_bus_write_config_word (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;
-				rc = pci_bus_write_config_word (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;
-					rc = pci_bus_write_config_word (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;
-					rc = pci_bus_write_config_word (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
-		rc = pci_bus_write_config_word (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
-		rc = pci_bus_write_config_word (pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
-	} else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
-		// Standard device
-		rc = pci_bus_read_config_byte (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("CND: bus=%d, devfn=%d, offset=%d\n", pci_bus->number, devfn, cloop);
-			rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
-
-			rc = pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp_register);
-			dbg("CND: base = 0x%x\n", 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("CND:      length = 0x%x\n", base);
-					io_node = get_io_resource(&(resources->io_head), base);
-					dbg("Got io_node start = %8.8x, length = %8.8x next (%p)\n",
-					    io_node->base, io_node->length, io_node->next);
-					dbg("func (%p) io_head (%p)\n", 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("CND:      length = 0x%x\n", 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("CND:      length = 0x%x\n", 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("CND:      length = 0x%x\n", 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);
-				}
-
-				rc = pci_bus_write_config_dword (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;
-					rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, base);
-				}
-			}
-		}		// End of base register loop
-
-		// Figure out which interrupt pin this function uses
-		rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_INTERRUPT_PIN, &temp_byte);
-
-		// If this function needs an interrupt and we are behind a bridge
-		// and the pin is tied to something that's alread 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];
-		} else {
-			// Program IRQ based on card type
-			rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
-
-			if (class_code == PCI_BASE_CLASS_STORAGE) {
-				IRQ = cpqhp_disk_irq;
-			} else {
-				IRQ = cpqhp_nic_irq;
-			}
-		}
-
-		// IRQ Line
-		rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ);
-
-		if (!behind_bridge) {
-			rc = cpqhp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ);
-			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;
-		rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
-
-		// Cache Line size
-		temp_byte = 0x08;
-		rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
-
-		// disable ROM base Address
-		temp_dword = 0x00L;
-		rc = pci_bus_write_config_word (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
-		rc = pci_bus_write_config_word (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;
-}
-
diff -Nru a/drivers/hotplug/cpqphp_nvram.c b/drivers/hotplug/cpqphp_nvram.c
--- a/drivers/hotplug/cpqphp_nvram.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,667 +0,0 @@
-/*
- * Compaq Hot Plug Controller Driver
- *
- * Copyright (c) 1995,2001 Compaq Computer Corporation
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001 IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <greg@kroah.com>
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/miscdevice.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include "cpqphp.h"
-#include "cpqphp_nvram.h"
-
-
-#define ROM_INT15_PHY_ADDR		0x0FF859
-#define READ_EV				0xD8A4
-#define WRITE_EV			0xD8A5
-
-struct register_foo {
-	union {
-		unsigned long lword;		/* eax */
-		unsigned short word;		/* ax */
-
-		struct {
-			unsigned char low;	/* al */
-			unsigned char high;	/* ah */
-		} byte;
-	} data;
-
-	unsigned char opcode;	/* see below */
-	unsigned long length;	/* if the reg. is a pointer, how much data */
-} __attribute__ ((packed));
-
-struct all_reg {
-	struct register_foo eax_reg;
-	struct register_foo ebx_reg;
-	struct register_foo ecx_reg;
-	struct register_foo edx_reg;
-	struct register_foo edi_reg;
-	struct register_foo esi_reg;
-	struct register_foo eflags_reg;
-} __attribute__ ((packed));
-
-
-struct ev_hrt_header {
-	u8 Version;
-	u8 num_of_ctrl;
-	u8 next;
-};
-
-struct ev_hrt_ctrl {
-	u8 bus;
-	u8 device;
-	u8 function;
-	u8 mem_avail;
-	u8 p_mem_avail;
-	u8 io_avail;
-	u8 bus_avail;
-	u8 next;
-};
-
-
-static u8 evbuffer_init;
-static u8 evbuffer_length;
-static u8 evbuffer[1024];
-
-static void *compaq_int15_entry_point;
-
-static spinlock_t int15_lock;		/* lock for ordering int15_bios_call() */
-
-
-/* This is a series of function that deals with
-   setting & getting the hotplug resource table in some environment variable.
-*/
-
-/*
- * We really shouldn't be doing this unless there is a _very_ good reason to!!!
- * greg k-h
- */
-
-
-static u32 add_byte( u32 **p_buffer, u8 value, u32 *used, u32 *avail)
-{
-	u8 **tByte;
-
-	if ((*used + 1) > *avail)
-		return(1);
-	
-	*((u8*)*p_buffer) = value;
-	tByte = (u8**)p_buffer;
-	(*tByte)++;
-	*used+=1;
-	return(0);
-}
-
-
-static u32 add_dword( u32 **p_buffer, u32 value, u32 *used, u32 *avail)
-{
-	if ((*used + 4) > *avail)
-		return(1);
-
-	**p_buffer = value;
-	(*p_buffer)++;
-	*used+=4;
-	return(0);
-}
-
-
-/*
- * check_for_compaq_ROM
- *
- * this routine verifies that the ROM OEM string is 'COMPAQ'
- *
- * returns 0 for non-Compaq ROM, 1 for Compaq ROM
- */
-static int check_for_compaq_ROM (void *rom_start)
-{
-	u8 temp1, temp2, temp3, temp4, temp5, temp6;
-	int result = 0;
-
-	temp1 = readb(rom_start + 0xffea + 0);
-	temp2 = readb(rom_start + 0xffea + 1);
-	temp3 = readb(rom_start + 0xffea + 2);
-	temp4 = readb(rom_start + 0xffea + 3);
-	temp5 = readb(rom_start + 0xffea + 4);
-	temp6 = readb(rom_start + 0xffea + 5);
-	if ((temp1 == 'C') &&
-	    (temp2 == 'O') &&
-	    (temp3 == 'M') &&
-	    (temp4 == 'P') &&
-	    (temp5 == 'A') &&
-	    (temp6 == 'Q')) {
-		result = 1;
-	}
-	dbg ("%s - returned %d\n", __FUNCTION__, result);
-	return result;
-}
-
-
-static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)
-{
-	unsigned long flags;
-	int op = operation;
-	int ret_val;
-	
-	if (!compaq_int15_entry_point)
-		return -ENODEV;
-	
-	spin_lock_irqsave(&int15_lock, flags);
-	__asm__ (
-		"xorl   %%ebx,%%ebx\n" \
-		"xorl    %%edx,%%edx\n" \
-		"pushf\n" \
-		"push %%cs\n" \
-		"cli\n" \
-		"call *%6\n"
-		: "=c" (*buf_size), "=a" (ret_val)
-		: "a" (op), "c" (*buf_size), "S" (ev_name),
-		"D" (buffer), "m" (compaq_int15_entry_point)
-		: "%ebx", "%edx");
-	spin_unlock_irqrestore(&int15_lock, flags);
-	
-	return((ret_val & 0xFF00) >> 8);
-}
-
-
-/*
- * load_HRT
- *
- * Read the hot plug Resource Table from NVRAM
- */
-static int load_HRT (void *rom_start)
-{
-	u32 available;
-	u32 temp_dword;
-	u8 temp_byte = 0xFF;
-	u32 rc;
-
-	if (!check_for_compaq_ROM(rom_start)) {
-		return -ENODEV;
-	}
-
-	available = 1024;
-
-	// Now load the EV
-	temp_dword = available;
-
-	rc = access_EV(READ_EV, "CQTHPS", evbuffer, &temp_dword);
-
-	evbuffer_length = temp_dword;
-
-	// We're maintaining the resource lists so write FF to invalidate old info
-	temp_dword = 1;
-
-	rc = access_EV(WRITE_EV, "CQTHPS", &temp_byte, &temp_dword);
-
-	return rc;
-}
-
-
-/*
- * store_HRT
- *
- * Save the hot plug Resource Table in NVRAM
- */
-static u32 store_HRT (void *rom_start)
-{
-	u32 *buffer;
-	u32 *pFill;
-	u32 usedbytes;
-	u32 available;
-	u32 temp_dword;
-	u32 rc;
-	u8 loop;
-	u8 numCtrl = 0;
-	struct controller *ctrl;
-	struct pci_resource *resNode;
-	struct ev_hrt_header *p_EV_header;
-	struct ev_hrt_ctrl *p_ev_ctrl;
-
-	available = 1024;
-
-	if (!check_for_compaq_ROM(rom_start)) {
-		return(1);
-	}
-
-	buffer = (u32*) evbuffer;
-
-	if (!buffer)
-		return(1);
-
-	pFill = buffer;
-	usedbytes = 0;
-
-	p_EV_header = (struct ev_hrt_header *) pFill;
-
-	ctrl = cpqhp_ctrl_list;
-	
-	// The revision of this structure
-	rc = add_byte( &pFill, 1 + ctrl->push_flag, &usedbytes, &available);
-	if (rc)
-		return(rc);
-
-	// The number of controllers
-	rc = add_byte( &pFill, 1, &usedbytes, &available);
-	if (rc)
-		return(rc);
-
-	while (ctrl) {
-		p_ev_ctrl = (struct ev_hrt_ctrl *) pFill;
-
-		numCtrl++;
-
-		// The bus number
-		rc = add_byte( &pFill, ctrl->bus, &usedbytes, &available);
-		if (rc)
-			return(rc);
-
-		// The device Number
-		rc = add_byte( &pFill, PCI_SLOT(ctrl->pci_dev->devfn), &usedbytes, &available);
-		if (rc)
-			return(rc);
-
-		// The function Number
-		rc = add_byte( &pFill, PCI_FUNC(ctrl->pci_dev->devfn), &usedbytes, &available);
-		if (rc)
-			return(rc);
-
-		// Skip the number of available entries
-		rc = add_dword( &pFill, 0, &usedbytes, &available);
-		if (rc)
-			return(rc);
-
-		// Figure out memory Available
-
-		resNode = ctrl->mem_head;
-
-		loop = 0;
-
-		while (resNode) {
-			loop ++;
-
-			// base
-			rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
-			if (rc)
-				return(rc);
-
-			// length
-			rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
-			if (rc)
-				return(rc);
-
-			resNode = resNode->next;
-		}
-
-		// Fill in the number of entries
-		p_ev_ctrl->mem_avail = loop;
-
-		// Figure out prefetchable memory Available
-
-		resNode = ctrl->p_mem_head;
-
-		loop = 0;
-
-		while (resNode) {
-			loop ++;
-
-			// base
-			rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
-			if (rc)
-				return(rc);
-
-			// length
-			rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
-			if (rc)
-				return(rc);
-
-			resNode = resNode->next;
-		}
-
-		// Fill in the number of entries
-		p_ev_ctrl->p_mem_avail = loop;
-
-		// Figure out IO Available
-
-		resNode = ctrl->io_head;
-
-		loop = 0;
-
-		while (resNode) {
-			loop ++;
-
-			// base
-			rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
-			if (rc)
-				return(rc);
-
-			// length
-			rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
-			if (rc)
-				return(rc);
-
-			resNode = resNode->next;
-		}
-
-		// Fill in the number of entries
-		p_ev_ctrl->io_avail = loop;
-
-		// Figure out bus Available
-
-		resNode = ctrl->bus_head;
-
-		loop = 0;
-
-		while (resNode) {
-			loop ++;
-
-			// base
-			rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
-			if (rc)
-				return(rc);
-
-			// length
-			rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
-			if (rc)
-				return(rc);
-
-			resNode = resNode->next;
-		}
-
-		// Fill in the number of entries
-		p_ev_ctrl->bus_avail = loop;
-
-		ctrl = ctrl->next;
-	}
-	
-	p_EV_header->num_of_ctrl = numCtrl;
-
-	// Now store the EV
-
-	temp_dword = usedbytes;
-
-	rc = access_EV(WRITE_EV, "CQTHPS", (u8*) buffer, &temp_dword);
-
-	dbg("usedbytes = 0x%x, length = 0x%x\n", usedbytes, temp_dword);
-
-	evbuffer_length = temp_dword;
-
-	if (rc) {
-		err(msg_unable_to_save);
-		return(1);
-	}
-
-	return(0);
-}
-
-
-void compaq_nvram_init (void *rom_start)
-{
-	if (rom_start) {
-		compaq_int15_entry_point = (rom_start + ROM_INT15_PHY_ADDR - ROM_PHY_ADDR);
-	}
-	dbg("int15 entry  = %p\n", compaq_int15_entry_point);
-
-	/* initialize our int15 lock */
-	spin_lock_init(&int15_lock);
-}
-
-
-int compaq_nvram_load (void *rom_start, struct controller *ctrl)
-{
-	u8 bus, device, function;
-	u8 nummem, numpmem, numio, numbus;
-	u32 rc;
-	u8 *p_byte;
-	struct pci_resource *mem_node;
-	struct pci_resource *p_mem_node;
-	struct pci_resource *io_node;
-	struct pci_resource *bus_node;
-	struct ev_hrt_ctrl *p_ev_ctrl;
-	struct ev_hrt_header *p_EV_header;
-
-	if (!evbuffer_init) {
-		// Read the resource list information in from NVRAM
-		if (load_HRT(rom_start))
-			memset (evbuffer, 0, 1024);
-
-		evbuffer_init = 1;
-	}
-
-	// If we saved information in NVRAM, use it now
-	p_EV_header = (struct ev_hrt_header *) evbuffer;
-
-	// The following code is for systems where version 1.0 of this
-	// driver has been loaded, but doesn't support the hardware.
-	// In that case, the driver would incorrectly store something
-	// in NVRAM.
-	if ((p_EV_header->Version == 2) ||
-	    ((p_EV_header->Version == 1) && !ctrl->push_flag)) {
-		p_byte = &(p_EV_header->next);
-
-		p_ev_ctrl = (struct ev_hrt_ctrl *) &(p_EV_header->next);
-
-		p_byte += 3;
-
-		if (p_byte > ((u8*)p_EV_header + evbuffer_length))
-			return 2;
-
-		bus = p_ev_ctrl->bus;
-		device = p_ev_ctrl->device;
-		function = p_ev_ctrl->function;
-
-		while ((bus != ctrl->bus) ||
-		       (device != PCI_SLOT(ctrl->pci_dev->devfn)) || 
-		       (function != PCI_FUNC(ctrl->pci_dev->devfn))) {
-			nummem = p_ev_ctrl->mem_avail;
-			numpmem = p_ev_ctrl->p_mem_avail;
-			numio = p_ev_ctrl->io_avail;
-			numbus = p_ev_ctrl->bus_avail;
-
-			p_byte += 4;
-
-			if (p_byte > ((u8*)p_EV_header + evbuffer_length))
-				return 2;
-
-			// Skip forward to the next entry
-			p_byte += (nummem + numpmem + numio + numbus) * 8;
-
-			if (p_byte > ((u8*)p_EV_header + evbuffer_length))
-				return 2;
-
-			p_ev_ctrl = (struct ev_hrt_ctrl *) p_byte;
-
-			p_byte += 3;
-
-			if (p_byte > ((u8*)p_EV_header + evbuffer_length))
-				return 2;
-
-			bus = p_ev_ctrl->bus;
-			device = p_ev_ctrl->device;
-			function = p_ev_ctrl->function;
-		}
-
-		nummem = p_ev_ctrl->mem_avail;
-		numpmem = p_ev_ctrl->p_mem_avail;
-		numio = p_ev_ctrl->io_avail;
-		numbus = p_ev_ctrl->bus_avail;
-
-		p_byte += 4;
-
-		if (p_byte > ((u8*)p_EV_header + evbuffer_length))
-			return 2;
-
-		while (nummem--) {
-			mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-
-			if (!mem_node)
-				break;
-
-			mem_node->base = *(u32*)p_byte;
-			dbg("mem base = %8.8x\n",mem_node->base);
-			p_byte += 4;
-
-			if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
-				kfree(mem_node);
-				return 2;
-			}
-
-			mem_node->length = *(u32*)p_byte;
-			dbg("mem length = %8.8x\n",mem_node->length);
-			p_byte += 4;
-
-			if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
-				kfree(mem_node);
-				return 2;
-			}
-
-			mem_node->next = ctrl->mem_head;
-			ctrl->mem_head = mem_node;
-		}
-
-		while (numpmem--) {
-			p_mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-
-			if (!p_mem_node)
-				break;
-
-			p_mem_node->base = *(u32*)p_byte;
-			dbg("pre-mem base = %8.8x\n",p_mem_node->base);
-			p_byte += 4;
-
-			if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
-				kfree(p_mem_node);
-				return 2;
-			}
-
-			p_mem_node->length = *(u32*)p_byte;
-			dbg("pre-mem length = %8.8x\n",p_mem_node->length);
-			p_byte += 4;
-
-			if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
-				kfree(p_mem_node);
-				return 2;
-			}
-
-			p_mem_node->next = ctrl->p_mem_head;
-			ctrl->p_mem_head = p_mem_node;
-		}
-
-		while (numio--) {
-			io_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-
-			if (!io_node)
-				break;
-
-			io_node->base = *(u32*)p_byte;
-			dbg("io base = %8.8x\n",io_node->base);
-			p_byte += 4;
-
-			if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
-				kfree(io_node);
-				return 2;
-			}
-
-			io_node->length = *(u32*)p_byte;
-			dbg("io length = %8.8x\n",io_node->length);
-			p_byte += 4;
-
-			if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
-				kfree(io_node);
-				return 2;
-			}
-
-			io_node->next = ctrl->io_head;
-			ctrl->io_head = io_node;
-		}
-
-		while (numbus--) {
-			bus_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-
-			if (!bus_node)
-				break;
-
-			bus_node->base = *(u32*)p_byte;
-			p_byte += 4;
-
-			if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
-				kfree(bus_node);
-				return 2;
-			}
-
-			bus_node->length = *(u32*)p_byte;
-			p_byte += 4;
-
-			if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
-				kfree(bus_node);
-				return 2;
-			}
-
-			bus_node->next = ctrl->bus_head;
-			ctrl->bus_head = bus_node;
-		}
-
-		// If all of the following fail, we don't have any resources for
-		// hot plug add
-		rc = 1;
-		rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
-		rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
-		rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head));
-		rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
-
-		if (rc)
-			return(rc);
-	} else {
-		if ((evbuffer[0] != 0) && (!ctrl->push_flag)) 
-			return 1;
-	}
-
-	return 0;
-}
-
-	
-int compaq_nvram_store (void *rom_start)
-{
-	int rc = 1;
-
-	if (rom_start == NULL)
-		return -ENODEV;
-
-	if (evbuffer_init) {
-		rc = store_HRT(rom_start);
-		if (rc) {
-			err(msg_unable_to_save);
-		}
-	}
-	return rc;
-}
-
diff -Nru a/drivers/hotplug/cpqphp_nvram.h b/drivers/hotplug/cpqphp_nvram.h
--- a/drivers/hotplug/cpqphp_nvram.h	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,57 +0,0 @@
-/*
- * Compaq Hot Plug Controller Driver
- *
- * Copyright (c) 1995,2001 Compaq Computer Corporation
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <greg@kroah.com>
- *
- */
-
-#ifndef _CPQPHP_NVRAM_H
-#define _CPQPHP_NVRAM_H
-
-#ifndef CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM
-
-static inline void compaq_nvram_init (void *rom_start)
-{
-	return;
-}
-
-static inline int compaq_nvram_load (void *rom_start, struct controller *ctrl)
-{
-	return 0;
-}
-
-static inline int compaq_nvram_store (void *rom_start)
-{
-	return 0;
-}
-
-#else
-
-extern void compaq_nvram_init	(void *rom_start);
-extern int compaq_nvram_load	(void *rom_start, struct controller *ctrl);
-extern int compaq_nvram_store	(void *rom_start);
-
-#endif
-
-#endif
-
diff -Nru a/drivers/hotplug/cpqphp_pci.c b/drivers/hotplug/cpqphp_pci.c
--- a/drivers/hotplug/cpqphp_pci.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1548 +0,0 @@
-/*
- * Compaq Hot Plug Controller Driver
- *
- * Copyright (c) 1995,2001 Compaq Computer Corporation
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001 IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <greg@kroah.com>
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/proc_fs.h>
-#include <linux/pci.h>
-#include "cpqphp.h"
-#include "cpqphp_nvram.h"
-#include "../../arch/i386/pci/pci.h"	/* horrible hack showing how processor dependent we are... */
-
-
-u8 cpqhp_nic_irq;
-u8 cpqhp_disk_irq;
-
-static u16 unused_IRQ;
-
-/*
- * detect_HRT_floating_pointer
- *
- * find the Hot Plug Resource Table in the specified region of memory.
- *
- */
-static void *detect_HRT_floating_pointer(void *begin, void *end)
-{
-	void *fp;
-	void *endp;
-	u8 temp1, temp2, temp3, temp4;
-	int status = 0;
-
-	endp = (end - sizeof(struct hrt) + 1);
-
-	for (fp = begin; fp <= endp; fp += 16) {
-		temp1 = readb(fp + SIG0);
-		temp2 = readb(fp + SIG1);
-		temp3 = readb(fp + SIG2);
-		temp4 = readb(fp + SIG3);
-		if (temp1 == '$' &&
-		    temp2 == 'H' &&
-		    temp3 == 'R' &&
-		    temp4 == 'T') {
-			status = 1;
-			break;
-		}
-	}
-
-	if (!status)
-		fp = NULL;
-
-	dbg("Discovered Hotplug Resource Table at %p\n", fp);
-	return fp;
-}
-
-
-int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)  
-{
-	unsigned char bus;
-	struct pci_bus *child;
-	int num;
-
-	if (func->pci_dev == NULL)
-		func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
-
-	/* No pci device, we need to create it then */
-	if (func->pci_dev == NULL) {
-		dbg("INFO: pci_dev still null\n");
-
-		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 cpqhp_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_bus *bus, unsigned int devfn, u8 offset, u32 *value)
-{
-	u32 vendID = 0;
-
-	if (pci_bus_read_config_dword (bus, devfn, PCI_VENDOR_ID, &vendID) == -1)
-		return -1;
-	if (vendID == 0xffffffff)
-		return -1;
-	return pci_bus_read_config_dword (bus, devfn, offset, value);
-}
-
-
-/*
- * cpqhp_set_irq
- *
- * @bus_num: bus number of PCI device
- * @dev_num: device number of PCI device
- * @slot: pointer to u8 where slot number will be returned
- */
-int cpqhp_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;
-}
-
-
-/*
- * 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;
-
-	ctrl->pci_bus->number = bus_num;
-
-	for (tdevice = 0; tdevice < 0x100; tdevice++) {
-		//Scan for access first
-		if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
-			continue;
-		dbg("Looking for nonbridge bus_num %d dev_num %d\n", bus_num, tdevice);
-		//Yep we got one. Not a bridge ?
-		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_bus, tdevice, 0x08, &work) == -1)
-			continue;
-		dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice);
-		//Yep we got one. bridge ?
-		if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
-			pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(tdevice, 0), PCI_SECONDARY_BUS, &tbus);
-			dbg("Recurse on bus_num %d tdevice %d\n", tbus, tdevice);
-			if (PCI_ScanBusNonBridge(tbus, tdevice) == 0)
-				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();
-	if (!PCIIRQRoutingInfoLength)
-		return -1;
-
-	len = (PCIIRQRoutingInfoLength->size -
-	       sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
-	// Make sure I got at least one entry
-	if (len == 0) {
-		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;
-
-		if (tslot == slot) {
-			*bus_num = tbus;
-			*dev_num = tdevice;
-			ctrl->pci_bus->number = tbus;
-			pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_VENDOR_ID, &work);
-			if (!nobridge || (work == 0xffffffff)) {
-				if (PCIIRQRoutingInfoLength != NULL)
-					kfree(PCIIRQRoutingInfoLength );
-				return 0;
-			}
-
-			dbg("bus_num %d devfn %d\n", *bus_num, *dev_num);
-			pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_CLASS_REVISION, &work);
-			dbg("work >> 8 (%x) = BRIDGE (%x)\n", work >> 8, PCI_TO_PCI_BRIDGE_CLASS);
-
-			if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
-				pci_bus_read_config_byte (ctrl->pci_bus, *dev_num, PCI_SECONDARY_BUS, &tbus);
-				dbg("Scan bus for Non Bridge: bus %d\n", tbus);
-				if (PCI_ScanBusForNonBridge(ctrl, tbus, dev_num) == 0) {
-					*bus_num = tbus;
-					if (PCIIRQRoutingInfoLength != NULL)
-						kfree(PCIIRQRoutingInfoLength );
-					return 0;
-				}
-			} else {
-				if (PCIIRQRoutingInfoLength != NULL)
-					kfree(PCIIRQRoutingInfoLength );
-				return 0;
-			}
-
-		}
-	}
-	if (PCIIRQRoutingInfoLength != NULL)
-		kfree(PCIIRQRoutingInfoLength );
-	return -1;
-}
-
-
-int cpqhp_get_bus_dev (struct controller *ctrl, u8 * bus_num, u8 * dev_num, u8 slot)
-{
-	return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0);	//plain (bridges allowed)
-}
-
-
-/* More PCI configuration routines; this time centered around hotplug controller */
-
-
-/*
- * cpqhp_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 cpqhp_save_config(struct controller *ctrl, int busnumber, int 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) {
-		//*********************************
-		// is_hot_plug is the slot mask
-		//*********************************
-		FirstSupported = is_hot_plug >> 4;
-		LastSupported = FirstSupported + (is_hot_plug & 0x0F) - 1;
-	} else {
-		FirstSupported = 0;
-		LastSupported = 0x1F;
-	}
-
-	//     Save PCI configuration space for all devices in supported slots
-	ctrl->pci_bus->number = busnumber;
-	for (device = FirstSupported; device <= LastSupported; device++) {
-		ID = 0xFFFFFFFF;
-		rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
-
-		if (ID != 0xFFFFFFFF) {	  //  device in slot
-			rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code);
-			if (rc)
-				return rc;
-
-			rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type);
-			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 = cpqhp_save_config(ctrl, sub_bus, 0);
-						if (rc)
-							return rc;
-						ctrl->pci_bus->number = busnumber;
-					}
-				}
-
-				index = 0;
-				new_slot = cpqhp_slot_find(busnumber, device, index++);
-				while (new_slot && 
-				       (new_slot->function != (u8) function))
-					new_slot = cpqhp_slot_find(busnumber, device, index++);
-
-				if (!new_slot) {
-					// Setup slot structure.
-					new_slot = cpqhp_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);
-
-				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 = cpqhp_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;
-		}
-	}			// End of FOR loop
-
-	return(0);
-}
-
-
-/*
- * cpqhp_save_slot_config
- *
- * Saves configuration info for all PCI devices in a given slot
- * including subordinate busses.
- *
- * returns 0 if success
- */
-int cpqhp_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;
-
-	ctrl->pci_bus->number = new_slot->bus;
-	pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID);
-
-	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 = cpqhp_save_config(ctrl, sub_bus, 0);
-				if (rc)
-					return(rc);
-				ctrl->pci_bus->number = new_slot->bus;
-
-			}	// 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);
-}
-
-
-/*
- * cpqhp_save_base_addr_length
- *
- * Saves the length of all base address registers for the
- * specified slot.  this is for hot plug REPLACE
- *
- * returns 0 if success
- */
-int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func)
-{
-	u8 cloop;
-	u8 header_type;
-	u8 secondary_bus;
-	u8 type;
-	int sub_bus;
-	u32 temp_register;
-	u32 base;
-	u32 rc;
-	struct pci_func *next;
-	int index = 0;
-	struct pci_bus *pci_bus = ctrl->pci_bus;
-	unsigned int devfn;
-
-	func = cpqhp_slot_find(func->bus, func->device, index++);
-
-	while (func != NULL) {
-		pci_bus->number = func->bus;
-		devfn = PCI_DEVFN(func->device, func->function);
-
-		// Check for Bridge
-		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
-
-		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
-			// PCI-PCI Bridge
-			pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
-
-			sub_bus = (int) secondary_bus;
-
-			next = cpqhp_slot_list[sub_bus];
-
-			while (next != NULL) {
-				rc = cpqhp_save_base_addr_length(ctrl, next);
-
-				if (rc)
-					return(rc);
-
-				next = next->next;
-			}
-			pci_bus->number = func->bus;
-
-			//FIXME: this loop is duplicated in the non-bridge case.  The two could be rolled together
-			// Figure out IO and memory base lengths
-			for (cloop = 0x10; cloop <= 0x14; cloop += 4) {
-				temp_register = 0xFFFFFFFF;
-				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
-				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
-
-				if (base) {  // If this register is implemented
-					if (base & 0x01L) {
-						// IO base
-						// set base = amount of IO space requested
-						base = base & 0xFFFFFFFE;
-						base = (~base) + 1;
-
-						type = 1;
-					} else {
-						// memory base
-						base = base & 0xFFFFFFF0;
-						base = (~base) + 1;
-
-						type = 0;
-					}
-				} else {
-					base = 0x0L;
-					type = 0;
-				}
-
-				// Save information in slot structure
-				func->base_length[(cloop - 0x10) >> 2] =
-				base;
-				func->base_type[(cloop - 0x10) >> 2] = type;
-
-			}	// End of base register loop
-
-
-		} else if ((header_type & 0x7F) == 0x00) {	  // PCI-PCI Bridge
-			// Figure out IO and memory base lengths
-			for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
-				temp_register = 0xFFFFFFFF;
-				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
-				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
-
-				if (base) {  // If this register is implemented
-					if (base & 0x01L) {
-						// IO base
-						// base = amount of IO space requested
-						base = base & 0xFFFFFFFE;
-						base = (~base) + 1;
-
-						type = 1;
-					} else {
-						// memory base
-						// base = amount of memory space requested
-						base = base & 0xFFFFFFF0;
-						base = (~base) + 1;
-
-						type = 0;
-					}
-				} else {
-					base = 0x0L;
-					type = 0;
-				}
-
-				// Save information in slot structure
-				func->base_length[(cloop - 0x10) >> 2] = base;
-				func->base_type[(cloop - 0x10) >> 2] = type;
-
-			}	// End of base register loop
-
-		} else {	  // Some other unknown header type
-		}
-
-		// find the next device in this slot
-		func = cpqhp_slot_find(func->bus, func->device, index++);
-	}
-
-	return(0);
-}
-
-
-/*
- * cpqhp_save_used_resources
- *
- * Stores used resource information for existing boards.  this is
- * for boards that were in the system when this driver was loaded.
- * this function is for hot plug ADD
- *
- * returns 0 if success
- */
-int cpqhp_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;
-	struct pci_bus *pci_bus = ctrl->pci_bus;
-	unsigned int devfn;
-
-	func = cpqhp_slot_find(func->bus, func->device, index++);
-
-	while ((func != NULL) && func->is_a_board) {
-		pci_bus->number = func->bus;
-		devfn = PCI_DEVFN(func->device, func->function);
-
-		// Save the command register
-		pci_bus_read_config_word (pci_bus, devfn, PCI_COMMAND, &save_command);
-
-		// disable card
-		command = 0x00;
-		pci_bus_write_config_word (pci_bus, devfn, PCI_COMMAND, command);
-
-		// Check for Bridge
-		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
-
-		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  // PCI-PCI Bridge
-			// Clear Bridge Control Register
-			command = 0x00;
-			pci_bus_write_config_word (pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
-			pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
-			pci_bus_read_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);
-
-			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 (pci_bus, devfn, PCI_IO_BASE, &b_base);
-			pci_bus_read_config_byte (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 (pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
-			pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
-
-			if ((w_base <= w_length) && (save_command & 0x02)) {
-				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 (pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
-			pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
-
-			if ((w_base <= w_length) && (save_command & 0x02)) {
-				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 (pci_bus, devfn, cloop, &save_base);
-
-				temp_register = 0xFFFFFFFF;
-				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
-				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
-
-				temp_register = base;
-
-				if (base) {  // If this register is implemented
-					if (((base & 0x03L) == 0x01)
-					    && (save_command & 0x01)) {
-						// IO base
-						// set temp_register = amount of IO space requested
-						temp_register = base & 0xFFFFFFFE;
-						temp_register = (~temp_register) + 1;
-
-						io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-						if (!io_node)
-							return -ENOMEM;
-
-						io_node->base =
-						save_base & (~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 (pci_bus, devfn, cloop, &save_base);
-
-				temp_register = 0xFFFFFFFF;
-				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
-				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
-
-				temp_register = base;
-
-				if (base) {	  // If this register is implemented
-					if (((base & 0x03L) == 0x01)
-					    && (save_command & 0x01)) {
-						// IO base
-						// set temp_register = amount of IO space requested
-						temp_register = base & 0xFFFFFFFE;
-						temp_register = (~temp_register) + 1;
-
-						io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-						if (!io_node)
-							return -ENOMEM;
-
-						io_node->base = save_base & (~0x01L);
-						io_node->length = temp_register;
-
-						io_node->next = func->io_head;
-						func->io_head = io_node;
-					} else
-						if (((base & 0x0BL) == 0x08)
-						    && (save_command & 0x02)) {
-						// prefetchable memory base
-						temp_register = base & 0xFFFFFFF0;
-						temp_register = (~temp_register) + 1;
-
-						p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-						if (!p_mem_node)
-							return -ENOMEM;
-
-						p_mem_node->base = save_base & (~0x0FL);
-						p_mem_node->length = temp_register;
-
-						p_mem_node->next = func->p_mem_head;
-						func->p_mem_head = p_mem_node;
-					} else
-						if (((base & 0x0BL) == 0x00)
-						    && (save_command & 0x02)) {
-						// prefetchable memory base
-						temp_register = base & 0xFFFFFFF0;
-						temp_register = (~temp_register) + 1;
-
-						mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-						if (!mem_node)
-							return -ENOMEM;
-
-						mem_node->base = save_base & (~0x0FL);
-						mem_node->length = temp_register;
-
-						mem_node->next = func->mem_head;
-						func->mem_head = mem_node;
-					} else
-						return(1);
-				}
-			}	// End of base register loop
-		} else {	  // Some other unknown header type
-		}
-
-		// find the next device in this slot
-		func = cpqhp_slot_find(func->bus, func->device, index++);
-	}
-
-	return(0);
-}
-
-
-/*
- * cpqhp_configure_board
- *
- * Copies saved configuration information to one slot.
- * this is called recursively for bridge devices.
- * this is for hot plug REPLACE!
- *
- * returns 0 if success
- */
-int cpqhp_configure_board(struct controller *ctrl, struct pci_func * func)
-{
-	int cloop;
-	u8 header_type;
-	u8 secondary_bus;
-	int sub_bus;
-	struct pci_func *next;
-	u32 temp;
-	u32 rc;
-	int index = 0;
-	struct pci_bus *pci_bus = ctrl->pci_bus;
-	unsigned int devfn;
-
-	func = cpqhp_slot_find(func->bus, func->device, index++);
-
-	while (func != NULL) {
-		pci_bus->number = func->bus;
-		devfn = PCI_DEVFN(func->device, func->function);
-
-		// Start at the top of config space so that the control
-		// registers are programmed last
-		for (cloop = 0x3C; cloop > 0; cloop -= 4) {
-			pci_bus_write_config_dword (pci_bus, devfn, cloop, func->config_space[cloop >> 2]);
-		}
-
-		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
-
-		// If this is a bridge device, restore subordinate devices
-		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  // PCI-PCI Bridge
-			pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
-
-			sub_bus = (int) secondary_bus;
-
-			next = cpqhp_slot_list[sub_bus];
-
-			while (next != NULL) {
-				rc = cpqhp_configure_board(ctrl, next);
-
-				if (rc)
-					return rc;
-
-				next = next->next;
-			}
-		} else {
-
-			// Check all the base Address Registers to make sure
-			// they are the same.  If not, the board is different.
-
-			for (cloop = 16; cloop < 40; cloop += 4) {
-				pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp);
-
-				if (temp != func->config_space[cloop >> 2]) {
-					dbg("Config space compare failure!!! offset = %x\n", cloop);
-					dbg("bus = %x, device = %x, function = %x\n", func->bus, func->device, func->function);
-					dbg("temp = %x, config space = %x\n\n", temp, func->config_space[cloop >> 2]);
-					return 1;
-				}
-			}
-		}
-
-		func->configured = 1;
-
-		func = cpqhp_slot_find(func->bus, func->device, index++);
-	}
-
-	return 0;
-}
-
-
-/*
- * cpqhp_valid_replace
- *
- * this function checks to see if a board is the same as the
- * one it is replacing.  this check will detect if the device's
- * vendor or device id's are the same
- *
- * returns 0 if the board is the same nonzero otherwise
- */
-int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func)
-{
-	u8 cloop;
-	u8 header_type;
-	u8 secondary_bus;
-	u8 type;
-	u32 temp_register = 0;
-	u32 base;
-	u32 rc;
-	struct pci_func *next;
-	int index = 0;
-	struct pci_bus *pci_bus = ctrl->pci_bus;
-	unsigned int devfn;
-
-	if (!func->is_a_board)
-		return(ADD_NOT_SUPPORTED);
-
-	func = cpqhp_slot_find(func->bus, func->device, index++);
-
-	while (func != NULL) {
-		pci_bus->number = func->bus;
-		devfn = PCI_DEVFN(func->device, func->function);
-
-		pci_bus_read_config_dword (pci_bus, devfn, PCI_VENDOR_ID, &temp_register);
-
-		// No adapter present
-		if (temp_register == 0xFFFFFFFF)
-			return(NO_ADAPTER_PRESENT);
-
-		if (temp_register != func->config_space[0])
-			return(ADAPTER_NOT_SAME);
-
-		// Check for same revision number and class code
-		pci_bus_read_config_dword (pci_bus, devfn, PCI_CLASS_REVISION, &temp_register);
-
-		// Adapter not the same
-		if (temp_register != func->config_space[0x08 >> 2])
-			return(ADAPTER_NOT_SAME);
-
-		// Check for Bridge
-		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
-
-		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  // PCI-PCI Bridge
-			// In order to continue checking, we must program the
-			// bus registers in the bridge to respond to accesses
-			// for it's subordinate bus(es)
-
-			temp_register = func->config_space[0x18 >> 2];
-			pci_bus_write_config_dword (pci_bus, devfn, PCI_PRIMARY_BUS, temp_register);
-
-			secondary_bus = (temp_register >> 8) & 0xFF;
-
-			next = cpqhp_slot_list[secondary_bus];
-
-			while (next != NULL) {
-				rc = cpqhp_valid_replace(ctrl, next);
-
-				if (rc)
-					return(rc);
-
-				next = next->next;
-			}
-
-		}
-		// Check to see if it is a standard config header
-		else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
-			// Check subsystem vendor and ID
-			pci_bus_read_config_dword (pci_bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &temp_register);
-
-			if (temp_register != func->config_space[0x2C >> 2]) {
-				// If it's a SMART-2 and the register isn't filled
-				// in, ignore the difference because
-				// they just have an old rev of the firmware
-
-				if (!((func->config_space[0] == 0xAE100E11)
-				      && (temp_register == 0x00L)))
-					return(ADAPTER_NOT_SAME);
-			}
-			// Figure out IO and memory base lengths
-			for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
-				temp_register = 0xFFFFFFFF;
-				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
-				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
-				if (base) {	  // If this register is implemented
-					if (base & 0x01L) {
-						// IO base
-						// set base = amount of IO space requested
-						base = base & 0xFFFFFFFE;
-						base = (~base) + 1;
-
-						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 = cpqhp_slot_find(func->bus, func->device, index++);
-	}
-
-
-	return(0);
-}
-
-
-/*
- * cpqhp_find_available_resources
- *
- * Finds available memory, IO, and IRQ resources for programming
- * devices which may be added to the system
- * this function is for hot plug ADD!
- *
- * returns 0 if success
- */  
-int cpqhp_find_available_resources (struct controller *ctrl, void *rom_start)
-{
-	u8 temp;
-	u8 populated_slot;
-	u8 bridged_slot;
-	void *one_slot;
-	struct pci_func *func = NULL;
-	int i = 10, index;
-	u32 temp_dword, rc;
-	struct pci_resource *mem_node;
-	struct pci_resource *p_mem_node;
-	struct pci_resource *io_node;
-	struct pci_resource *bus_node;
-	void *rom_resource_table;
-
-	rom_resource_table = detect_HRT_floating_pointer(rom_start, rom_start+0xffff);
-	dbg("rom_resource_table = %p\n", rom_resource_table);
-
-	if (rom_resource_table == NULL) {
-		return -ENODEV;
-	}
-	// Sum all resources and setup resource maps
-	unused_IRQ = readl(rom_resource_table + UNUSED_IRQ);
-	dbg("unused_IRQ = %x\n", unused_IRQ);
-
-	temp = 0;
-	while (unused_IRQ) {
-		if (unused_IRQ & 1) {
-			cpqhp_disk_irq = temp;
-			break;
-		}
-		unused_IRQ = unused_IRQ >> 1;
-		temp++;
-	}
-
-	dbg("cpqhp_disk_irq= %d\n", cpqhp_disk_irq);
-	unused_IRQ = unused_IRQ >> 1;
-	temp++;
-
-	while (unused_IRQ) {
-		if (unused_IRQ & 1) {
-			cpqhp_nic_irq = temp;
-			break;
-		}
-		unused_IRQ = unused_IRQ >> 1;
-		temp++;
-	}
-
-	dbg("cpqhp_nic_irq= %d\n", cpqhp_nic_irq);
-	unused_IRQ = readl(rom_resource_table + PCIIRQ);
-
-	temp = 0;
-
-	if (!cpqhp_nic_irq) {
-		cpqhp_nic_irq = ctrl->cfgspc_irq;
-	}
-
-	if (!cpqhp_disk_irq) {
-		cpqhp_disk_irq = ctrl->cfgspc_irq;
-	}
-
-	dbg("cpqhp_disk_irq, cpqhp_nic_irq= %d, %d\n", cpqhp_disk_irq, cpqhp_nic_irq);
-
-	rc = compaq_nvram_load(rom_start, ctrl);
-	if (rc)
-		return rc;
-
-	one_slot = rom_resource_table + sizeof (struct hrt);
-
-	i = readb(rom_resource_table + NUMBER_OF_ENTRIES);
-	dbg("number_of_entries = %d\n", i);
-
-	if (!readb(one_slot + SECONDARY_BUS)) {
-		return(1);
-	}
-
-	dbg("dev|IO base|length|Mem base|length|Pre base|length|PB SB MB\n");
-
-	while (i && readb(one_slot + SECONDARY_BUS)) {
-		u8 dev_func = readb(one_slot + DEV_FUNC);
-		u8 primary_bus = readb(one_slot + PRIMARY_BUS);
-		u8 secondary_bus = readb(one_slot + SECONDARY_BUS);
-		u8 max_bus = readb(one_slot + MAX_BUS);
-		u16 io_base = readw(one_slot + IO_BASE);
-		u16 io_length = readw(one_slot + IO_LENGTH);
-		u16 mem_base = readw(one_slot + MEM_BASE);
-		u16 mem_length = readw(one_slot + MEM_LENGTH);
-		u16 pre_mem_base = readw(one_slot + PRE_MEM_BASE);
-		u16 pre_mem_length = readw(one_slot + PRE_MEM_LENGTH);
-
-		dbg("%2.2x | %4.4x  | %4.4x | %4.4x   | %4.4x | %4.4x   | %4.4x |%2.2x %2.2x %2.2x\n",
-		    dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length,
-		    primary_bus, secondary_bus, max_bus);
-
-		// If this entry isn't for our controller's bus, ignore it
-		if (primary_bus != ctrl->bus) {
-			i--;
-			one_slot += sizeof (struct slot_rt);
-			continue;
-		}
-		// find out if this entry is for an occupied slot
-		ctrl->pci_bus->number = primary_bus;
-		pci_bus_read_config_dword (ctrl->pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword);
-		dbg("temp_D_word = %x\n", temp_dword);
-
-		if (temp_dword != 0xFFFFFFFF) {
-			index = 0;
-			func = cpqhp_slot_find(primary_bus, dev_func >> 3, 0);
-
-			while (func && (func->function != (dev_func & 0x07))) {
-				dbg("func = %p (bus, dev, fun) = (%d, %d, %d)\n", func, primary_bus, dev_func >> 3, index);
-				func = cpqhp_slot_find(primary_bus, dev_func >> 3, index++);
-			}
-
-			// If we can't find a match, skip this table entry
-			if (!func) {
-				i--;
-				one_slot += sizeof (struct slot_rt);
-				continue;
-			}
-			// this may not work and shouldn't be used
-			if (secondary_bus != primary_bus)
-				bridged_slot = 1;
-			else
-				bridged_slot = 0;
-
-			populated_slot = 1;
-		} else {
-			populated_slot = 0;
-			bridged_slot = 0;
-		}
-
-
-		// If we've got a valid IO base, use it
-
-		temp_dword = io_base + io_length;
-
-		if ((io_base) && (temp_dword < 0x10000)) {
-			io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-			if (!io_node)
-				return -ENOMEM;
-
-			io_node->base = io_base;
-			io_node->length = io_length;
-
-			dbg("found io_node(base, length) = %x, %x\n", io_node->base, io_node->length);
-			dbg("populated slot =%d \n", populated_slot);
-			if (!populated_slot) {
-				io_node->next = ctrl->io_head;
-				ctrl->io_head = io_node;
-			} else {
-				io_node->next = func->io_head;
-				func->io_head = io_node;
-			}
-		}
-
-		// If we've got a valid memory base, use it
-		temp_dword = mem_base + mem_length;
-		if ((mem_base) && (temp_dword < 0x10000)) {
-			mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-			if (!mem_node)
-				return -ENOMEM;
-
-			mem_node->base = mem_base << 16;
-
-			mem_node->length = mem_length << 16;
-
-			dbg("found mem_node(base, length) = %x, %x\n", mem_node->base, mem_node->length);
-			dbg("populated slot =%d \n", populated_slot);
-			if (!populated_slot) {
-				mem_node->next = ctrl->mem_head;
-				ctrl->mem_head = mem_node;
-			} else {
-				mem_node->next = func->mem_head;
-				func->mem_head = mem_node;
-			}
-		}
-
-		// If we've got a valid prefetchable memory base, and
-		// the base + length isn't greater than 0xFFFF
-		temp_dword = pre_mem_base + pre_mem_length;
-		if ((pre_mem_base) && (temp_dword < 0x10000)) {
-			p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-			if (!p_mem_node)
-				return -ENOMEM;
-
-			p_mem_node->base = pre_mem_base << 16;
-
-			p_mem_node->length = pre_mem_length << 16;
-			dbg("found p_mem_node(base, length) = %x, %x\n", p_mem_node->base, p_mem_node->length);
-			dbg("populated slot =%d \n", populated_slot);
-
-			if (!populated_slot) {
-				p_mem_node->next = ctrl->p_mem_head;
-				ctrl->p_mem_head = p_mem_node;
-			} else {
-				p_mem_node->next = func->p_mem_head;
-				func->p_mem_head = p_mem_node;
-			}
-		}
-
-		// If we've got a valid bus number, use it
-		// The second condition is to ignore bus numbers on
-		// populated slots that don't have PCI-PCI bridges
-		if (secondary_bus && (secondary_bus != primary_bus)) {
-			bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-			if (!bus_node)
-				return -ENOMEM;
-
-			bus_node->base = secondary_bus;
-			bus_node->length = max_bus - secondary_bus + 1;
-			dbg("found bus_node(base, length) = %x, %x\n", bus_node->base, bus_node->length);
-			dbg("populated slot =%d \n", populated_slot);
-			if (!populated_slot) {
-				bus_node->next = ctrl->bus_head;
-				ctrl->bus_head = bus_node;
-			} else {
-				bus_node->next = func->bus_head;
-				func->bus_head = bus_node;
-			}
-		}
-
-		i--;
-		one_slot += sizeof (struct slot_rt);
-	}
-
-	// If all of the following fail, we don't have any resources for
-	// hot plug add
-	rc = 1;
-	rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
-	rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
-	rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head));
-	rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
-
-	return(rc);
-}
-
-
-/*
- * cpqhp_return_board_resources
- *
- * this routine returns all resources allocated to a board to
- * the available pool.
- *
- * returns 0 if success
- */
-int cpqhp_return_board_resources(struct pci_func * func, struct resource_lists * resources)
-{
-	int rc = 0;
-	struct pci_resource *node;
-	struct pci_resource *t_node;
-	dbg("%s\n", __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 |= cpqhp_resource_sort_and_combine(&(resources->mem_head));
-	rc |= cpqhp_resource_sort_and_combine(&(resources->p_mem_head));
-	rc |= cpqhp_resource_sort_and_combine(&(resources->io_head));
-	rc |= cpqhp_resource_sort_and_combine(&(resources->bus_head));
-
-	return(rc);
-}
-
-
-/*
- * cpqhp_destroy_resource_list
- *
- * Puts node back in the resource list pointed to by head
- */
-void cpqhp_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);
-	}
-}
-
-
-/*
- * cpqhp_destroy_board_resources
- *
- * Puts node back in the resource list pointed to by head
- */
-void cpqhp_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);
-	}
-}
-
diff -Nru a/drivers/hotplug/cpqphp_sysfs.c b/drivers/hotplug/cpqphp_sysfs.c
--- a/drivers/hotplug/cpqphp_sysfs.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,143 +0,0 @@
-/*
- * Compaq Hot Plug Controller Driver
- *
- * Copyright (c) 1995,2001 Compaq Computer Corporation
- * Copyright (c) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001 IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <greg@kroah.com>
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/workqueue.h>
-#include <linux/pci.h>
-#include "cpqphp.h"
-
-
-/* A few routines that create sysfs entries for the hot plug controller */
-
-static int show_ctrl (struct device *dev, char *buf)
-{
-	struct pci_dev *pci_dev;
-	struct controller *ctrl;
-	char * out = buf;
-	int index;
-	struct pci_resource *res;
-
-	pci_dev = container_of (dev, struct pci_dev, dev);
-	ctrl = pci_get_drvdata(pci_dev);
-
-	out += sprintf(buf, "Free resources: memory\n");
-	index = 11;
-	res = ctrl->mem_head;
-	while (res && index--) {
-		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-		res = res->next;
-	}
-	out += sprintf(out, "Free resources: prefetchable memory\n");
-	index = 11;
-	res = ctrl->p_mem_head;
-	while (res && index--) {
-		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-		res = res->next;
-	}
-	out += sprintf(out, "Free resources: IO\n");
-	index = 11;
-	res = ctrl->io_head;
-	while (res && index--) {
-		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-		res = res->next;
-	}
-	out += sprintf(out, "Free resources: bus numbers\n");
-	index = 11;
-	res = ctrl->bus_head;
-	while (res && index--) {
-		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-		res = res->next;
-	}
-
-	return out - buf;
-}
-static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
-
-static int show_dev (struct device *dev, char *buf)
-{
-	struct pci_dev *pci_dev;
-	struct controller *ctrl;
-	char * out = buf;
-	int index;
-	struct pci_resource *res;
-	struct pci_func *new_slot;
-	struct slot *slot;
-
-	pci_dev = container_of (dev, struct pci_dev, dev);
-	ctrl = pci_get_drvdata(pci_dev);
-
-	slot=ctrl->slot;
-
-	while (slot) {
-		new_slot = cpqhp_slot_find(slot->bus, slot->device, 0);
-		if (!new_slot)
-			break;
-		out += sprintf(out, "assigned resources: memory\n");
-		index = 11;
-		res = new_slot->mem_head;
-		while (res && index--) {
-			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-			res = res->next;
-		}
-		out += sprintf(out, "assigned resources: prefetchable memory\n");
-		index = 11;
-		res = new_slot->p_mem_head;
-		while (res && index--) {
-			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-			res = res->next;
-		}
-		out += sprintf(out, "assigned resources: IO\n");
-		index = 11;
-		res = new_slot->io_head;
-		while (res && index--) {
-			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-			res = res->next;
-		}
-		out += sprintf(out, "assigned resources: bus numbers\n");
-		index = 11;
-		res = new_slot->bus_head;
-		while (res && index--) {
-			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-			res = res->next;
-		}
-		slot=slot->next;
-	}
-
-	return out - buf;
-}
-static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL);
-
-void cpqhp_create_ctrl_files (struct controller *ctrl)
-{
-	device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
-	device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev);
-}
diff -Nru a/drivers/hotplug/ibmphp.h b/drivers/hotplug/ibmphp.h
--- a/drivers/hotplug/ibmphp.h	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,772 +0,0 @@
-#ifndef __IBMPHP_H
-#define __IBMPHP_H
-
-/*
- * IBM Hot Plug Controller Driver
- *
- * Written By: Jyoti Shah, Tong Yu, Irene Zubarev, IBM Corporation
- *
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001,2002 IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <gregkh@us.ibm.com>
- *
- */
-
-#include "pci_hotplug.h"
-
-extern int ibmphp_debug;
-
-#if !defined(CONFIG_HOTPLUG_PCI_IBM_MODULE)
-	#define MY_NAME "ibmphpd"
-#else
-	#define MY_NAME THIS_MODULE->name
-#endif
-#define debug(fmt, arg...) do { if (ibmphp_debug == 1) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0)
-#define debug_pci(fmt, arg...) do { if (ibmphp_debug) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0)
-#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
-#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
-
-
-/* EBDA stuff */
-
-/***********************************************************
-* SLOT CAPABILITY                                          *
-***********************************************************/
-
-#define EBDA_SLOT_133_MAX		0x20
-#define EBDA_SLOT_100_MAX		0x10
-#define EBDA_SLOT_66_MAX		0x02
-#define EBDA_SLOT_PCIX_CAP		0x08
-
-
-/************************************************************
-*  RESOURE TYPE                                             *
-************************************************************/
-
-#define EBDA_RSRC_TYPE_MASK		0x03
-#define EBDA_IO_RSRC_TYPE		0x00
-#define EBDA_MEM_RSRC_TYPE		0x01
-#define EBDA_PFM_RSRC_TYPE		0x03
-#define EBDA_RES_RSRC_TYPE		0x02
-
-
-/*************************************************************
-*  IO RESTRICTION TYPE                                       *
-*************************************************************/
-
-#define EBDA_IO_RESTRI_MASK		0x0c
-#define EBDA_NO_RESTRI			0x00
-#define EBDA_AVO_VGA_ADDR		0x04
-#define EBDA_AVO_VGA_ADDR_AND_ALIA	0x08
-#define EBDA_AVO_ISA_ADDR		0x0c
-
-
-/**************************************************************
-*  DEVICE TYPE DEF                                            *
-**************************************************************/
-
-#define EBDA_DEV_TYPE_MASK		0x10
-#define EBDA_PCI_DEV			0x10
-#define EBDA_NON_PCI_DEV		0x00
-
-
-/***************************************************************
-*  PRIMARY DEF DEFINITION                                      *
-***************************************************************/
-
-#define EBDA_PRI_DEF_MASK		0x20
-#define EBDA_PRI_PCI_BUS_INFO		0x20
-#define EBDA_NORM_DEV_RSRC_INFO		0x00
-
-
-//--------------------------------------------------------------
-// RIO TABLE DATA STRUCTURE
-//--------------------------------------------------------------
-
-struct rio_table_hdr {
-	u8 ver_num; 
-	u8 scal_count;
-	u8 riodev_count;
-	u16 offset;
-};
-
-//-------------------------------------------------------------
-// SCALABILITY DETAIL
-//-------------------------------------------------------------
-
-struct scal_detail {
-	u8 node_id;
-	u32 cbar;
-	u8 port0_node_connect;
-	u8 port0_port_connect;
-	u8 port1_node_connect;
-	u8 port1_port_connect;
-	u8 port2_node_connect;
-	u8 port2_port_connect;
-	u8 chassis_num;
-//	struct list_head scal_detail_list;
-};
-
-//--------------------------------------------------------------
-// RIO DETAIL 
-//--------------------------------------------------------------
-
-struct rio_detail {
-	u8 rio_node_id;
-	u32 bbar;
-	u8 rio_type;
-	u8 owner_id;
-	u8 port0_node_connect;
-	u8 port0_port_connect;
-	u8 port1_node_connect;
-	u8 port1_port_connect;
-	u8 first_slot_num;
-	u8 status;
-	u8 wpindex;
-	u8 chassis_num;
-	struct list_head rio_detail_list;
-};
-
-struct opt_rio {
-	u8 rio_type;
-	u8 chassis_num;
-	u8 first_slot_num;
-	u8 middle_num;
-	struct list_head opt_rio_list;
-};	
-
-struct opt_rio_lo {
-	u8 rio_type;
-	u8 chassis_num;
-	u8 first_slot_num;
-	u8 middle_num;
-	u8 pack_count;
-	struct list_head opt_rio_lo_list;
-};	
-
-/****************************************************************
-*  HPC DESCRIPTOR NODE                                          *
-****************************************************************/
-
-struct ebda_hpc_list {
-	u8 format;
-	u16 num_ctlrs;
-	short phys_addr;
-//      struct list_head ebda_hpc_list;
-};
-/*****************************************************************
-*   IN HPC DATA STRUCTURE, THE ASSOCIATED SLOT AND BUS           *
-*   STRUCTURE                                                    *
-*****************************************************************/
-
-struct ebda_hpc_slot {
-	u8 slot_num;
-	u32 slot_bus_num;
-	u8 ctl_index;
-	u8 slot_cap;
-};
-
-struct ebda_hpc_bus {
-	u32 bus_num;
-	u8 slots_at_33_conv;
-	u8 slots_at_66_conv;
-	u8 slots_at_66_pcix;
-	u8 slots_at_100_pcix;
-	u8 slots_at_133_pcix;
-};
-
-
-/********************************************************************
-*   THREE TYPE OF HOT PLUG CONTROLER                                *
-********************************************************************/
-
-struct isa_ctlr_access {
-	u16 io_start;
-	u16 io_end;
-};
-
-struct pci_ctlr_access {
-	u8 bus;
-	u8 dev_fun;
-};
-
-struct wpeg_i2c_ctlr_access {
-	ulong wpegbbar;
-	u8 i2c_addr;
-};
-
-#define HPC_DEVICE_ID		0x0246
-#define HPC_SUBSYSTEM_ID	0x0247
-#define HPC_PCI_OFFSET		0x40
-/*************************************************************************
-*   RSTC DESCRIPTOR NODE                                                 *
-*************************************************************************/
-
-struct ebda_rsrc_list {
-	u8 format;
-	u16 num_entries;
-	u16 phys_addr;
-	struct ebda_rsrc_list *next;
-};
-
-
-/***************************************************************************
-*   PCI RSRC NODE                                                          *
-***************************************************************************/
-
-struct ebda_pci_rsrc {
-	u8 rsrc_type;
-	u8 bus_num;
-	u8 dev_fun;
-	u32 start_addr;
-	u32 end_addr;
-	u8 marked;	/* for NVRAM */
-	struct list_head ebda_pci_rsrc_list;
-};
-
-
-/***********************************************************
-* BUS_INFO DATE STRUCTURE                                  *
-***********************************************************/
-
-struct bus_info {
-	u8 slot_min;
-	u8 slot_max;
-	u8 slot_count;
-	u8 busno;
-	u8 controller_id;
-	u8 current_speed;
-	u8 current_bus_mode;
-	u8 index;
-	u8 slots_at_33_conv;
-	u8 slots_at_66_conv;
-	u8 slots_at_66_pcix;
-	u8 slots_at_100_pcix;
-	u8 slots_at_133_pcix;
-	struct list_head bus_info_list;
-};
-
-
-/***********************************************************
-* GLOBAL VARIABLES                                         *
-***********************************************************/
-extern struct list_head ibmphp_ebda_pci_rsrc_head;
-extern struct list_head ibmphp_slot_head;
-extern struct list_head ibmphp_res_head;
-/***********************************************************
-* FUNCTION PROTOTYPES                                      *
-***********************************************************/
-
-extern void ibmphp_free_ebda_hpc_queue (void);
-extern int ibmphp_access_ebda (void);
-extern struct slot *ibmphp_get_slot_from_physical_num (u8);
-extern int ibmphp_get_total_hp_slots (void);
-extern void ibmphp_free_ibm_slot (struct slot *);
-extern void ibmphp_free_bus_info_queue (void);
-extern void ibmphp_free_ebda_pci_rsrc_queue (void);
-extern struct bus_info *ibmphp_find_same_bus_num (u32);
-extern int ibmphp_get_bus_index (u8);
-extern u16 ibmphp_get_total_controllers (void);
-extern int ibmphp_register_pci (void);
-
-/* passed parameters */
-#define MEM		0
-#define IO		1
-#define PFMEM		2
-
-/* bit masks */
-#define RESTYPE		0x03
-#define IOMASK		0x00	/* will need to take its complement */
-#define MMASK		0x01
-#define PFMASK		0x03
-#define PCIDEVMASK	0x10	/* we should always have PCI devices */
-#define PRIMARYBUSMASK	0x20
-
-/* pci specific defines */
-#define PCI_VENDOR_ID_NOTVALID		0xFFFF
-#define PCI_HEADER_TYPE_MULTIDEVICE	0x80
-#define PCI_HEADER_TYPE_MULTIBRIDGE	0x81
-
-#define LATENCY		0x64
-#define CACHE		64
-#define DEVICEENABLE	0x015F		/* CPQ has 0x0157 */
-
-#define IOBRIDGE	0x1000		/* 4k */
-#define MEMBRIDGE	0x100000	/* 1M */
-
-/* irqs */
-#define SCSI_IRQ	0x09
-#define LAN_IRQ		0x0A
-#define OTHER_IRQ	0x0B
-
-/* Data Structures */
-
-/* type is of the form x x xx xx
- *                     | |  |  |_ 00 - I/O, 01 - Memory, 11 - PFMemory
- *                     | |  - 00 - No Restrictions, 01 - Avoid VGA, 10 - Avoid
- *                     | |    VGA and their aliases, 11 - Avoid ISA
- *                     | - 1 - PCI device, 0 - non pci device
- *                     - 1 - Primary PCI Bus Information (0 if Normal device)
- * the IO restrictions [2:3] are only for primary buses
- */
-
-
-/* we need this struct because there could be several resource blocks
- * allocated per primary bus in the EBDA
- */
-struct range_node {
-	int rangeno;
-	u32 start;
-	u32 end;
-	struct range_node *next;
-};
-
-struct bus_node {
-	u8 busno;
-	int noIORanges;
-	struct range_node *rangeIO;
-	int noMemRanges;
-	struct range_node *rangeMem;
-	int noPFMemRanges;
-	struct range_node *rangePFMem;
-	int needIOUpdate;
-	int needMemUpdate;
-	int needPFMemUpdate;
-	struct resource_node *firstIO;	/* first IO resource on the Bus */
-	struct resource_node *firstMem;	/* first memory resource on the Bus */
-	struct resource_node *firstPFMem;	/* first prefetchable memory resource on the Bus */
-	struct resource_node *firstPFMemFromMem;	/* when run out of pfmem available, taking from Mem */
-	struct list_head bus_list;
-};
-
-struct resource_node {
-	int rangeno;
-	u8 busno;
-	u8 devfunc;
-	u32 start;
-	u32 end;
-	u32 len;
-	int type;		/* MEM, IO, PFMEM */
-	u8 fromMem;		/* this is to indicate that the range is from
-				 * from the Memory bucket rather than from PFMem */
-	struct resource_node *next;
-	struct resource_node *nextRange;	/* for the other mem range on bus */
-};
-
-struct res_needed {
-	u32 mem;
-	u32 pfmem;
-	u32 io;
-	u8 not_correct;		/* needed for return */
-	int devices[32];	/* for device numbers behind this bridge */
-};
-
-/* functions */
-
-extern int ibmphp_rsrc_init (void);
-extern int ibmphp_add_resource (struct resource_node *);
-extern int ibmphp_remove_resource (struct resource_node *);
-extern int ibmphp_find_resource (struct bus_node *, u32, struct resource_node **, int);
-extern int ibmphp_check_resource (struct resource_node *, u8);
-extern int ibmphp_remove_bus (struct bus_node *, u8);
-extern void ibmphp_free_resources (void);
-extern int ibmphp_add_pfmem_from_mem (struct resource_node *);
-extern struct bus_node *ibmphp_find_res_bus (u8);
-extern void ibmphp_print_test (void);	/* for debugging purposes */
-
-extern void ibmphp_hpc_initvars (void);
-extern int ibmphp_hpc_readslot (struct slot *, u8, u8 *);
-extern int ibmphp_hpc_writeslot (struct slot *, u8);
-extern void ibmphp_lock_operations (void);
-extern void ibmphp_unlock_operations (void);
-extern int ibmphp_hpc_fillhpslotinfo (struct hotplug_slot *);
-extern int ibmphp_hpc_start_poll_thread (void);
-extern void ibmphp_hpc_stop_poll_thread (void);
-
-//----------------------------------------------------------------------------
-
-
-//----------------------------------------------------------------------------
-// HPC return codes
-//----------------------------------------------------------------------------
-#define FALSE				0x00
-#define TRUE				0x01
-#define HPC_ERROR			0xFF
-
-//-----------------------------------------------------------------------------
-// BUS INFO
-//-----------------------------------------------------------------------------
-#define BUS_SPEED			0x30
-#define BUS_MODE			0x40
-#define BUS_MODE_PCIX			0x01
-#define BUS_MODE_PCI			0x00
-#define BUS_SPEED_2			0x20
-#define BUS_SPEED_1			0x10
-#define BUS_SPEED_33			0x00
-#define BUS_SPEED_66			0x01
-#define BUS_SPEED_100			0x02
-#define BUS_SPEED_133			0x03
-#define BUS_SPEED_66PCIX		0x04
-#define BUS_SPEED_66UNKNOWN		0x05
-#define BUS_STATUS_AVAILABLE		0x01
-#define BUS_CONTROL_AVAILABLE		0x02
-#define SLOT_LATCH_REGS_SUPPORTED	0x10
-
-#define PRGM_MODEL_REV_LEVEL		0xF0
-#define MAX_ADAPTER_NONE		0x09
-
-//----------------------------------------------------------------------------
-// HPC 'write' operations/commands
-//----------------------------------------------------------------------------
-//	Command			Code	State	Write to reg
-//					Machine	at index
-//-------------------------	----	-------	------------
-#define HPC_CTLR_ENABLEIRQ	0x00	// N	15
-#define HPC_CTLR_DISABLEIRQ	0x01	// N	15
-#define HPC_SLOT_OFF		0x02	// Y	0-14
-#define HPC_SLOT_ON		0x03	// Y	0-14
-#define HPC_SLOT_ATTNOFF	0x04	// N	0-14
-#define HPC_SLOT_ATTNON		0x05	// N	0-14
-#define HPC_CTLR_CLEARIRQ	0x06	// N	15
-#define HPC_CTLR_RESET		0x07	// Y	15
-#define HPC_CTLR_IRQSTEER	0x08	// N	15
-#define HPC_BUS_33CONVMODE	0x09	// Y	31-34
-#define HPC_BUS_66CONVMODE	0x0A	// Y	31-34
-#define HPC_BUS_66PCIXMODE	0x0B	// Y	31-34
-#define HPC_BUS_100PCIXMODE	0x0C	// Y	31-34
-#define HPC_BUS_133PCIXMODE	0x0D	// Y	31-34
-#define HPC_ALLSLOT_OFF		0x11	// Y	15
-#define HPC_ALLSLOT_ON		0x12	// Y	15
-#define HPC_SLOT_BLINKLED	0x13	// N	0-14
-
-//----------------------------------------------------------------------------
-// read commands
-//----------------------------------------------------------------------------
-#define READ_SLOTSTATUS		0x01
-#define READ_EXTSLOTSTATUS	0x02
-#define READ_BUSSTATUS		0x03
-#define READ_CTLRSTATUS		0x04
-#define READ_ALLSTAT		0x05
-#define READ_ALLSLOT		0x06
-#define READ_SLOTLATCHLOWREG	0x07
-#define READ_REVLEVEL		0x08
-#define READ_HPCOPTIONS		0x09
-//----------------------------------------------------------------------------
-// slot status
-//----------------------------------------------------------------------------
-#define HPC_SLOT_POWER		0x01
-#define HPC_SLOT_CONNECT	0x02
-#define HPC_SLOT_ATTN		0x04
-#define HPC_SLOT_PRSNT2		0x08
-#define HPC_SLOT_PRSNT1		0x10
-#define HPC_SLOT_PWRGD		0x20
-#define HPC_SLOT_BUS_SPEED	0x40
-#define HPC_SLOT_LATCH		0x80
-
-//----------------------------------------------------------------------------
-// HPC_SLOT_POWER status return codes
-//----------------------------------------------------------------------------
-#define HPC_SLOT_POWER_OFF	0x00
-#define HPC_SLOT_POWER_ON	0x01
-
-//----------------------------------------------------------------------------
-// HPC_SLOT_CONNECT status return codes
-//----------------------------------------------------------------------------
-#define HPC_SLOT_CONNECTED	0x00
-#define HPC_SLOT_DISCONNECTED	0x01
-
-//----------------------------------------------------------------------------
-// HPC_SLOT_ATTN status return codes
-//----------------------------------------------------------------------------
-#define HPC_SLOT_ATTN_OFF	0x00
-#define HPC_SLOT_ATTN_ON	0x01
-#define HPC_SLOT_ATTN_BLINK	0x02
-
-//----------------------------------------------------------------------------
-// HPC_SLOT_PRSNT status return codes
-//----------------------------------------------------------------------------
-#define HPC_SLOT_EMPTY		0x00
-#define HPC_SLOT_PRSNT_7	0x01
-#define HPC_SLOT_PRSNT_15	0x02
-#define HPC_SLOT_PRSNT_25	0x03
-
-//----------------------------------------------------------------------------
-// HPC_SLOT_PWRGD status return codes
-//----------------------------------------------------------------------------
-#define HPC_SLOT_PWRGD_FAULT_NONE	0x00
-#define HPC_SLOT_PWRGD_GOOD		0x01
-
-//----------------------------------------------------------------------------
-// HPC_SLOT_BUS_SPEED status return codes
-//----------------------------------------------------------------------------
-#define HPC_SLOT_BUS_SPEED_OK	0x00
-#define HPC_SLOT_BUS_SPEED_MISM	0x01
-
-//----------------------------------------------------------------------------
-// HPC_SLOT_LATCH status return codes
-//----------------------------------------------------------------------------
-#define HPC_SLOT_LATCH_OPEN	0x01	// NOTE : in PCI spec bit off = open
-#define HPC_SLOT_LATCH_CLOSED	0x00	// NOTE : in PCI spec bit on  = closed
-
-
-//----------------------------------------------------------------------------
-// extended slot status
-//----------------------------------------------------------------------------
-#define HPC_SLOT_PCIX		0x01
-#define HPC_SLOT_SPEED1		0x02
-#define HPC_SLOT_SPEED2		0x04
-#define HPC_SLOT_BLINK_ATTN	0x08
-#define HPC_SLOT_RSRVD1		0x10
-#define HPC_SLOT_RSRVD2		0x20
-#define HPC_SLOT_BUS_MODE	0x40
-#define HPC_SLOT_RSRVD3		0x80
-
-//----------------------------------------------------------------------------
-// HPC_XSLOT_PCIX_CAP status return codes
-//----------------------------------------------------------------------------
-#define HPC_SLOT_PCIX_NO	0x00
-#define HPC_SLOT_PCIX_YES	0x01
-
-//----------------------------------------------------------------------------
-// HPC_XSLOT_SPEED status return codes
-//----------------------------------------------------------------------------
-#define HPC_SLOT_SPEED_33	0x00
-#define HPC_SLOT_SPEED_66	0x01
-#define HPC_SLOT_SPEED_133	0x02
-
-//----------------------------------------------------------------------------
-// HPC_XSLOT_ATTN_BLINK status return codes
-//----------------------------------------------------------------------------
-#define HPC_SLOT_ATTN_BLINK_OFF	0x00
-#define HPC_SLOT_ATTN_BLINK_ON	0x01
-
-//----------------------------------------------------------------------------
-// HPC_XSLOT_BUS_MODE status return codes
-//----------------------------------------------------------------------------
-#define HPC_SLOT_BUS_MODE_OK	0x00
-#define HPC_SLOT_BUS_MODE_MISM	0x01
-
-//----------------------------------------------------------------------------
-// Controller status
-//----------------------------------------------------------------------------
-#define HPC_CTLR_WORKING	0x01
-#define HPC_CTLR_FINISHED	0x02
-#define HPC_CTLR_RESULT0	0x04
-#define HPC_CTLR_RESULT1	0x08
-#define HPC_CTLR_RESULE2	0x10
-#define HPC_CTLR_RESULT3	0x20
-#define HPC_CTLR_IRQ_ROUTG	0x40
-#define HPC_CTLR_IRQ_PENDG	0x80
-
-//----------------------------------------------------------------------------
-// HPC_CTLR_WROKING status return codes
-//----------------------------------------------------------------------------
-#define HPC_CTLR_WORKING_NO	0x00
-#define HPC_CTLR_WORKING_YES	0x01
-
-//----------------------------------------------------------------------------
-// HPC_CTLR_FINISHED status return codes
-//----------------------------------------------------------------------------
-#define HPC_CTLR_FINISHED_NO	0x00
-#define HPC_CTLR_FINISHED_YES	0x01
-
-//----------------------------------------------------------------------------
-// HPC_CTLR_RESULT status return codes
-//----------------------------------------------------------------------------
-#define HPC_CTLR_RESULT_SUCCESS	0x00
-#define HPC_CTLR_RESULT_FAILED	0x01
-#define HPC_CTLR_RESULT_RSVD	0x02
-#define HPC_CTLR_RESULT_NORESP	0x03
-
-
-//----------------------------------------------------------------------------
-// macro for slot info
-//----------------------------------------------------------------------------
-#define SLOT_POWER(s)	((u8) ((s & HPC_SLOT_POWER) \
-	? HPC_SLOT_POWER_ON : HPC_SLOT_POWER_OFF))
-
-#define SLOT_CONNECT(s)	((u8) ((s & HPC_SLOT_CONNECT) \
-	? HPC_SLOT_DISCONNECTED : HPC_SLOT_CONNECTED))
-
-#define SLOT_ATTN(s,es)	((u8) ((es & HPC_SLOT_BLINK_ATTN) \
-	? HPC_SLOT_ATTN_BLINK \
-	: ((s & HPC_SLOT_ATTN) ? HPC_SLOT_ATTN_ON : HPC_SLOT_ATTN_OFF)))
-
-#define SLOT_PRESENT(s)	((u8) ((s & HPC_SLOT_PRSNT1) \
-	? ((s & HPC_SLOT_PRSNT2) ? HPC_SLOT_EMPTY : HPC_SLOT_PRSNT_15) \
-	: ((s & HPC_SLOT_PRSNT2) ? HPC_SLOT_PRSNT_25 : HPC_SLOT_PRSNT_7)))
-
-#define SLOT_PWRGD(s)	((u8) ((s & HPC_SLOT_PWRGD) \
-	? HPC_SLOT_PWRGD_GOOD : HPC_SLOT_PWRGD_FAULT_NONE))
-
-#define SLOT_BUS_SPEED(s)	((u8) ((s & HPC_SLOT_BUS_SPEED) \
-	? HPC_SLOT_BUS_SPEED_MISM : HPC_SLOT_BUS_SPEED_OK))
-
-#define SLOT_LATCH(s)	((u8) ((s & HPC_SLOT_LATCH) \
-	? HPC_SLOT_LATCH_CLOSED : HPC_SLOT_LATCH_OPEN))
-
-#define SLOT_PCIX(es)	((u8) ((es & HPC_SLOT_PCIX) \
-	? HPC_SLOT_PCIX_YES : HPC_SLOT_PCIX_NO))
-
-#define SLOT_SPEED(es)	((u8) ((es & HPC_SLOT_SPEED2) \
-	? ((es & HPC_SLOT_SPEED1) ? HPC_SLOT_SPEED_133   \
-				: HPC_SLOT_SPEED_66)   \
-	: HPC_SLOT_SPEED_33))
-
-#define SLOT_BUS_MODE(es)	((u8) ((es & HPC_SLOT_BUS_MODE) \
-	? HPC_SLOT_BUS_MODE_MISM : HPC_SLOT_BUS_MODE_OK))
-
-//--------------------------------------------------------------------------
-// macro for bus info
-//---------------------------------------------------------------------------
-#define CURRENT_BUS_SPEED(s)	((u8) (s & BUS_SPEED_2) \
-	? ((s & BUS_SPEED_1) ? BUS_SPEED_133 : BUS_SPEED_100) \
-	: ((s & BUS_SPEED_1) ? BUS_SPEED_66 : BUS_SPEED_33))
-
-#define CURRENT_BUS_MODE(s)	((u8) (s & BUS_MODE) ? BUS_MODE_PCIX : BUS_MODE_PCI)
-
-#define READ_BUS_STATUS(s)	((u8) (s->options & BUS_STATUS_AVAILABLE))
-
-#define READ_BUS_MODE(s)	((s->revision & PRGM_MODEL_REV_LEVEL) >= 0x20)
-
-#define SET_BUS_STATUS(s)	((u8) (s->options & BUS_CONTROL_AVAILABLE))
-
-#define READ_SLOT_LATCH(s)	((u8) (s->options & SLOT_LATCH_REGS_SUPPORTED))
-
-//----------------------------------------------------------------------------
-// macro for controller info
-//----------------------------------------------------------------------------
-#define CTLR_WORKING(c) ((u8) ((c & HPC_CTLR_WORKING) \
-	? HPC_CTLR_WORKING_YES : HPC_CTLR_WORKING_NO))
-#define CTLR_FINISHED(c) ((u8) ((c & HPC_CTLR_FINISHED) \
-	? HPC_CTLR_FINISHED_YES : HPC_CTLR_FINISHED_NO))
-#define CTLR_RESULT(c) ((u8) ((c & HPC_CTLR_RESULT1)  \
-	? ((c & HPC_CTLR_RESULT0) ? HPC_CTLR_RESULT_NORESP \
-				: HPC_CTLR_RESULT_RSVD)  \
-	: ((c & HPC_CTLR_RESULT0) ? HPC_CTLR_RESULT_FAILED \
-				: HPC_CTLR_RESULT_SUCCESS)))
-
-// command that affect the state machine of HPC
-#define NEEDTOCHECK_CMDSTATUS(c) ((c == HPC_SLOT_OFF)        || \
-				  (c == HPC_SLOT_ON)         || \
-				  (c == HPC_CTLR_RESET)      || \
-				  (c == HPC_BUS_33CONVMODE)  || \
-				  (c == HPC_BUS_66CONVMODE)  || \
-				  (c == HPC_BUS_66PCIXMODE)  || \
-				  (c == HPC_BUS_100PCIXMODE) || \
-				  (c == HPC_BUS_133PCIXMODE) || \
-				  (c == HPC_ALLSLOT_OFF)     || \
-				  (c == HPC_ALLSLOT_ON))
-
-
-/* Core part of the driver */
-
-#define ENABLE		1
-#define DISABLE		0
-
-#define CARD_INFO	0x07
-#define PCIX133		0x07
-#define PCIX66		0x05
-#define PCI66		0x04
-
-extern struct pci_bus *ibmphp_pci_bus;
-
-/* Variables */
-
-struct pci_func {
-	struct pci_dev *dev;	/* from the OS */
-	u8 busno;
-	u8 device;
-	u8 function;
-	struct resource_node *io[6];
-	struct resource_node *mem[6];
-	struct resource_node *pfmem[6];
-	struct pci_func *next;
-	int devices[32];	/* for bridge config */
-	u8 irq[4];		/* for interrupt config */
-	u8 bus;			/* flag for unconfiguring, to say if PPB */
-};
-
-struct slot {
-	u8 bus;
-	u8 device;
-	u8 number;
-	u8 real_physical_slot_num;
-	char name[100];
-	u32 capabilities;
-	u8 supported_speed;
-	u8 supported_bus_mode;
-	struct hotplug_slot *hotplug_slot;
-	struct controller *ctrl;
-	struct pci_func *func;
-	u8 irq[4];
-	u8 flag;		/* this is for disable slot and polling */
-	int bit_mode;		/* 0 = 32, 1 = 64 */
-	u8 ctlr_index;
-	struct bus_info *bus_on;
-	struct list_head ibm_slot_list;
-	u8 status;
-	u8 ext_status;
-	u8 busstatus;
-};
-
-struct controller {
-	struct ebda_hpc_slot *slots;
-	struct ebda_hpc_bus *buses;
-	struct pci_dev *ctrl_dev; /* in case where controller is PCI */
-	u8 starting_slot_num;	/* starting and ending slot #'s this ctrl controls*/
-	u8 ending_slot_num;
-	u8 revision;
-	u8 options;		/* which options HPC supports */
-	u8 status;
-	u8 ctlr_id;
-	u8 slot_count;
-	u8 bus_count;
-	u8 ctlr_relative_id;
-	u32 irq;
-	union {
-		struct isa_ctlr_access isa_ctlr;
-		struct pci_ctlr_access pci_ctlr;
-		struct wpeg_i2c_ctlr_access wpeg_ctlr;
-	} u;
-	u8 ctlr_type;
-	struct list_head ebda_hpc_list;
-};
-
-/* Functions */
-
-extern int ibmphp_init_devno (struct slot **);	/* This function is called from EBDA, so we need it not be static */
-extern int ibmphp_disable_slot (struct hotplug_slot *);	/* This function is called from HPC, so we need it to not be static */
-extern int ibmphp_do_disable_slot (struct slot *slot_cur);
-extern int ibmphp_update_slot_info (struct slot *);	/* This function is called from HPC, so we need it to not be be static */
-extern int ibmphp_configure_card (struct pci_func *, u8);
-extern int ibmphp_unconfigure_card (struct slot **, int);
-extern struct hotplug_slot_ops ibmphp_hotplug_slot_ops;
-
-static inline void long_delay (int delay)
-{
-	set_current_state (TASK_INTERRUPTIBLE);
-	schedule_timeout (delay);
-}
-
-#endif				//__IBMPHP_H
-
diff -Nru a/drivers/hotplug/ibmphp_core.c b/drivers/hotplug/ibmphp_core.c
--- a/drivers/hotplug/ibmphp_core.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1417 +0,0 @@
-/*
- * IBM Hot Plug Controller Driver
- *
- * Written By: Chuck Cole, Jyoti Shah, Tong Yu, Irene Zubarev, IBM Corporation
- *
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001,2002 IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <gregkh@us.ibm.com>
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
-#include <linux/smp_lock.h>
-#include "../../arch/i386/pci/pci.h"	/* for struct irq_routing_table */
-#include "ibmphp.h"
-
-#define attn_on(sl)  ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNON)
-#define attn_off(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNOFF)
-#define attn_LED_blink(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_BLINKLED)
-#define get_ctrl_revision(sl, rev) ibmphp_hpc_readslot (sl, READ_REVLEVEL, rev)
-#define get_hpc_options(sl, opt) ibmphp_hpc_readslot (sl, READ_HPCOPTIONS, opt)
-
-#define DRIVER_VERSION	"0.6"
-#define DRIVER_DESC	"IBM Hot Plug PCI Controller Driver"
-
-int ibmphp_debug;
-
-static int debug;
-MODULE_PARM (debug, "i");
-MODULE_PARM_DESC (debug, "Debugging mode enabled or not");
-MODULE_LICENSE ("GPL");
-MODULE_DESCRIPTION (DRIVER_DESC);
-
-struct pci_bus *ibmphp_pci_bus;
-static int max_slots;
-
-static int irqs[16];    /* PIC mode IRQ's we're using so far (in case MPS tables don't provide default info for empty slots */
-
-static int init_flag;
-
-/*
-static int get_max_adapter_speed_1 (struct hotplug_slot *, u8 *, u8);
-
-static inline int get_max_adapter_speed (struct hotplug_slot *hs, u8 *value)
-{
-	return get_max_adapter_speed_1 (hs, value, 1);
-}
-*/
-static inline int get_cur_bus_info (struct slot **sl) 
-{
-	int rc = 1;
-	struct slot * slot_cur = *sl;
-
-	debug ("options = %x\n", slot_cur->ctrl->options);
-	debug ("revision = %x\n", slot_cur->ctrl->revision);	
-
-	if (READ_BUS_STATUS (slot_cur->ctrl)) 
-		rc = ibmphp_hpc_readslot (slot_cur, READ_BUSSTATUS, NULL);
-	
-	if (rc) 
-		return rc;
-	  
-	slot_cur->bus_on->current_speed = CURRENT_BUS_SPEED (slot_cur->busstatus);
-	if (READ_BUS_MODE (slot_cur->ctrl))
-		slot_cur->bus_on->current_bus_mode = CURRENT_BUS_MODE (slot_cur->busstatus);
-	else
-		slot_cur->bus_on->current_bus_mode = 0xFF;
-
-	debug ("busstatus = %x, bus_speed = %x, bus_mode = %x\n", slot_cur->busstatus, slot_cur->bus_on->current_speed, slot_cur->bus_on->current_bus_mode);
-	
-	*sl = slot_cur;
-	return 0;
-}
-
-static inline int slot_update (struct slot **sl)
-{
-	int rc;
- 	rc = ibmphp_hpc_readslot (*sl, READ_ALLSTAT, NULL);
-	if (rc) 
-		return rc;
-	if (!init_flag)
-		return get_cur_bus_info (sl);
-	return rc;
-}
-
-static int __init get_max_slots (void)
-{
-	struct slot * slot_cur;
-	struct list_head * tmp;
-	u8 slot_count = 0;
-
-	list_for_each (tmp, &ibmphp_slot_head) {
-		slot_cur = list_entry (tmp, struct slot, ibm_slot_list);
-		/* sometimes the hot-pluggable slots start with 4 (not always from 1 */
-		slot_count = max (slot_count, slot_cur->number);
-	}
-	return slot_count;
-}
-
-/* This routine will put the correct slot->device information per slot.  It's
- * called from initialization of the slot structures. It will also assign
- * interrupt numbers per each slot.
- * Parameters: struct slot
- * Returns 0 or errors
- */
-int ibmphp_init_devno (struct slot **cur_slot)
-{
-	struct irq_routing_table *rtable;
-	int len;
-	int loop;
-	int i;
-
-	rtable = pcibios_get_irq_routing_table ();
-	if (!rtable) {
-		err ("no BIOS routing table...\n");
-		return -ENOMEM;
-	}
-
-	len = (rtable->size - sizeof (struct irq_routing_table)) / sizeof (struct irq_info);
-
-	if (!len)
-		return -1;
-	for (loop = 0; loop < len; loop++) {
-		if ((*cur_slot)->number == rtable->slots[loop].slot) {
-		if ((*cur_slot)->bus == rtable->slots[loop].bus) {
-			(*cur_slot)->device = PCI_SLOT (rtable->slots[loop].devfn);
-			for (i = 0; i < 4; i++)
-				(*cur_slot)->irq[i] = IO_APIC_get_PCI_irq_vector ((int) (*cur_slot)->bus, (int) (*cur_slot)->device, i);
-
-				debug ("(*cur_slot)->irq[0] = %x\n", (*cur_slot)->irq[0]);
-				debug ("(*cur_slot)->irq[1] = %x\n", (*cur_slot)->irq[1]);
-				debug ("(*cur_slot)->irq[2] = %x\n", (*cur_slot)->irq[2]);
-				debug ("(*cur_slot)->irq[3] = %x\n", (*cur_slot)->irq[3]);
-
-				debug ("rtable->exlusive_irqs = %x\n", rtable->exclusive_irqs);
-				debug ("rtable->slots[loop].irq[0].bitmap = %x\n", rtable->slots[loop].irq[0].bitmap);
-				debug ("rtable->slots[loop].irq[1].bitmap = %x\n", rtable->slots[loop].irq[1].bitmap);
-				debug ("rtable->slots[loop].irq[2].bitmap = %x\n", rtable->slots[loop].irq[2].bitmap);
-				debug ("rtable->slots[loop].irq[3].bitmap = %x\n", rtable->slots[loop].irq[3].bitmap);
-
-				debug ("rtable->slots[loop].irq[0].link= %x\n", rtable->slots[loop].irq[0].link);
-				debug ("rtable->slots[loop].irq[1].link = %x\n", rtable->slots[loop].irq[1].link);
-				debug ("rtable->slots[loop].irq[2].link = %x\n", rtable->slots[loop].irq[2].link);
-				debug ("rtable->slots[loop].irq[3].link = %x\n", rtable->slots[loop].irq[3].link);
-				debug ("end of init_devno\n");
-				return 0;
-			}
-		}
-	}
-
-	return -1;
-}
-
-static inline int power_on (struct slot *slot_cur)
-{
-	u8 cmd = HPC_SLOT_ON;
-	int retval;
-
-	retval = ibmphp_hpc_writeslot (slot_cur, cmd);
-	if (retval) {
-		err ("power on failed\n");
-		return retval;
-	}
-	if (CTLR_RESULT (slot_cur->ctrl->status)) {
-		err ("command not completed successfully in power_on \n");
-		return -EIO;
-	}
-	long_delay (3 * HZ); /* For ServeRAID cards, and some 66 PCI */
-	return 0;
-}
-
-static inline int power_off (struct slot *slot_cur)
-{
-	u8 cmd = HPC_SLOT_OFF;
-	int retval;
-
-	retval = ibmphp_hpc_writeslot (slot_cur, cmd);
-	if (retval) {
-		err ("power off failed \n");
-		return retval;
-	}
-	if (CTLR_RESULT (slot_cur->ctrl->status)) {
-		err ("command not completed successfully in power_off \n");
-		return -EIO;
-	}
-	return 0;
-}
-
-static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 value)
-{
-	int rc = 0;
-	struct slot *pslot;
-	u8 cmd;
-	int hpcrc = 0;
-
-	debug ("set_attention_status - Entry hotplug_slot[%lx] value[%x]\n", (ulong) hotplug_slot, value);
-	ibmphp_lock_operations ();
-	cmd = 0x00;     // avoid compiler warning
-
-	if (hotplug_slot) {
-		switch (value) {
-		case HPC_SLOT_ATTN_OFF:
-			cmd = HPC_SLOT_ATTNOFF;
-			break;
-		case HPC_SLOT_ATTN_ON:
-			cmd = HPC_SLOT_ATTNON;
-			break;
-		case HPC_SLOT_ATTN_BLINK:
-			cmd = HPC_SLOT_BLINKLED;
-			break;
-		default:
-			rc = -ENODEV;
-			err ("set_attention_status - Error : invalid input [%x]\n", value);
-			break;
-		}
-		if (rc == 0) {
-			pslot = (struct slot *) hotplug_slot->private;
-			if (pslot)
-				hpcrc = ibmphp_hpc_writeslot (pslot, cmd);
-			else
-				rc = -ENODEV;
-		}
-	} else	
-		rc = -ENODEV;
-
-	if (hpcrc)
-		rc = hpcrc;
-
-	ibmphp_unlock_operations ();
-
-	debug ("set_attention_status - Exit rc[%d]\n", rc);
-	return rc;
-}
-
-static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 * value)
-{
-	int rc = -ENODEV;
-	struct slot *pslot;
-	int hpcrc = 0;
-	struct slot myslot;
-
-	debug ("get_attention_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value);
-        
-	ibmphp_lock_operations ();
-	if (hotplug_slot && value) {
-		pslot = (struct slot *) hotplug_slot->private;
-		if (pslot) {
-			memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
-			hpcrc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &(myslot.status));
-			if (!hpcrc)
-				hpcrc = ibmphp_hpc_readslot (pslot, READ_EXTSLOTSTATUS, &(myslot.ext_status));
-			if (!hpcrc) {
-				*value = SLOT_ATTN (myslot.status, myslot.ext_status);
-				rc = 0;
-			}
-		}
-	} else
-		rc = -ENODEV;
-
-	if (hpcrc)
-		rc = hpcrc;
-
-	ibmphp_unlock_operations ();
-	debug ("get_attention_status - Exit rc[%d] hpcrc[%x] value[%x]\n", rc, hpcrc, *value);
-	return rc;
-}
-
-static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 * value)
-{
-	int rc = -ENODEV;
-	struct slot *pslot;
-	int hpcrc = 0;
-	struct slot myslot;
-
-	debug ("get_latch_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value);
-	ibmphp_lock_operations ();
-	if (hotplug_slot && value) {
-		pslot = (struct slot *) hotplug_slot->private;
-		if (pslot) {
-			memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
-			hpcrc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &(myslot.status));
-			if (!hpcrc) {
-				*value = SLOT_LATCH (myslot.status);
-				rc = 0;
-			}
-		}
-	} else
-		rc = -ENODEV;
-
-	if (hpcrc)
-		rc = hpcrc;
-
-	ibmphp_unlock_operations ();
-	debug ("get_latch_status - Exit rc[%d] hpcrc[%x] value[%x]\n", rc, hpcrc, *value);
-	return rc;
-}
-
-
-static int get_power_status (struct hotplug_slot *hotplug_slot, u8 * value)
-{
-	int rc = -ENODEV;
-	struct slot *pslot;
-	int hpcrc = 0;
-	struct slot myslot;
-
-	debug ("get_power_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value);
-	ibmphp_lock_operations ();
-	if (hotplug_slot && value) {
-		pslot = (struct slot *) hotplug_slot->private;
-		if (pslot) {
-			memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
-			hpcrc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &(myslot.status));
-			if (!hpcrc) {
-				*value = SLOT_PWRGD (myslot.status);
-				rc = 0;
-			}
-		}
-	} else
-		rc = -ENODEV;
-
-	if (hpcrc)
-		rc = hpcrc;
-
-	ibmphp_unlock_operations ();
-	debug ("get_power_status - Exit rc[%d] hpcrc[%x] value[%x]\n", rc, hpcrc, *value);
-	return rc;
-}
-
-static int get_adapter_present (struct hotplug_slot *hotplug_slot, u8 * value)
-{
-	int rc = -ENODEV;
-	struct slot *pslot;
-	u8 present;
-	int hpcrc = 0;
-	struct slot myslot;
-
-	debug ("get_adapter_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value);
-	ibmphp_lock_operations ();
-	if (hotplug_slot && value) {
-		pslot = (struct slot *) hotplug_slot->private;
-		if (pslot) {
-			memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
-			hpcrc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &(myslot.status));
-			if (!hpcrc) {
-				present = SLOT_PRESENT (myslot.status);
-				if (present == HPC_SLOT_EMPTY)
-					*value = 0;
-				else
-					*value = 1;
-				rc = 0;
-			}
-		}
-	} else
-		rc = -ENODEV;
-	if (hpcrc)
-		rc = hpcrc;
-
-	ibmphp_unlock_operations ();
-	debug ("get_adapter_present - Exit rc[%d] hpcrc[%x] value[%x]\n", rc, hpcrc, *value);
-	return rc;
-}
-
-static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
-{
-	int rc = -ENODEV;
-	struct slot *pslot;
-	u8 mode = 0;
-
-	debug ("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __FUNCTION__,
-		hotplug_slot, value);
-
-	ibmphp_lock_operations ();
-
-	if (hotplug_slot && value) {
-		pslot = (struct slot *) hotplug_slot->private;
-		if (pslot) {
-			rc = 0;
-			mode = pslot->supported_bus_mode;
-			*value = pslot->supported_speed; 
-			switch (*value) {
-			case BUS_SPEED_33:
-				break;
-			case BUS_SPEED_66:
-				if (mode == BUS_MODE_PCIX) 
-					*value += 0x01;
-				break;
-			case BUS_SPEED_100:
-			case BUS_SPEED_133:
-				*value = pslot->supported_speed + 0x01;
-				break;
-			default:
-				/* Note (will need to change): there would be soon 256, 512 also */
-				rc = -ENODEV;
-			}
-		}
-	} else
-		rc = -ENODEV;
-
-	ibmphp_unlock_operations ();
-	debug ("%s - Exit rc[%d] value[%x]\n", __FUNCTION__, rc, *value);
-	return rc;
-}
-
-static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
-{
-	int rc = -ENODEV;
-	struct slot *pslot;
-	u8 mode = 0;
-
-	debug ("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __FUNCTION__,
-		hotplug_slot, value);
-
-	ibmphp_lock_operations ();
-
-	if (hotplug_slot && value) {
-		pslot = (struct slot *) hotplug_slot->private;
-		if (pslot) {
-			rc = get_cur_bus_info (&pslot);
-			if (!rc) {
-				mode = pslot->bus_on->current_bus_mode;
-				*value = pslot->bus_on->current_speed;
-				switch (*value) {
-				case BUS_SPEED_33:
-					break;
-				case BUS_SPEED_66:
-					if (mode == BUS_MODE_PCIX) 
-						*value += 0x01;
-					else if (mode == BUS_MODE_PCI)
-						;
-					else
-						*value = PCI_SPEED_UNKNOWN;
-					break;
-				case BUS_SPEED_100:
-				case BUS_SPEED_133:
-					*value += 0x01;
-					break;
-				default:
-					/* Note of change: there would also be 256, 512 soon */
-					rc = -ENODEV;
-				}
-			}
-		}
-	} else
-		rc = -ENODEV;
-
-	ibmphp_unlock_operations ();
-	debug ("%s - Exit rc[%d] value[%x]\n", __FUNCTION__, rc, *value);
-	return rc;
-}
-/*
-static int get_max_adapter_speed_1 (struct hotplug_slot *hotplug_slot, u8 * value, u8 flag)
-{
-	int rc = -ENODEV;
-	struct slot *pslot;
-	int hpcrc = 0;
-	struct slot myslot;
-
-	debug ("get_max_adapter_speed_1 - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong)hotplug_slot, (ulong) value);
-
-	if (flag)
-		ibmphp_lock_operations ();
-
-	if (hotplug_slot && value) {
-		pslot = (struct slot *) hotplug_slot->private;
-		if (pslot) {
-			memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
-			hpcrc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &(myslot.status));
-
-			if (!(SLOT_LATCH (myslot.status)) && (SLOT_PRESENT (myslot.status))) {
-				hpcrc = ibmphp_hpc_readslot (pslot, READ_EXTSLOTSTATUS, &(myslot.ext_status));
-				if (!hpcrc) {
-					*value = SLOT_SPEED (myslot.ext_status);
-					rc = 0;
-				}
-			} else {
-				*value = MAX_ADAPTER_NONE;
-				rc = 0;
-			}
-                }
-        } else
-		rc = -ENODEV;
-
-	if (hpcrc)
-		rc = hpcrc;
-
-	if (flag)
-		ibmphp_unlock_operations ();
-
-	debug ("get_max_adapter_speed_1 - Exit rc[%d] hpcrc[%x] value[%x]\n", rc, hpcrc, *value);
-	return rc;
-}
-
-static int get_bus_name (struct hotplug_slot *hotplug_slot, char * value)
-{
-	int rc = -ENODEV;
-	struct slot *pslot = NULL;
-
-	debug ("get_bus_name - Entry hotplug_slot[%lx] \n", (ulong)hotplug_slot);
-
-	ibmphp_lock_operations ();
-
-	if (hotplug_slot) {
-		pslot = (struct slot *) hotplug_slot->private;
-		if (pslot) {
-			rc = 0;
-			snprintf (value, 100, "Bus %x", pslot->bus);
-		}
-	} else
-		rc = -ENODEV;
-
-	ibmphp_unlock_operations ();
-	debug ("get_bus_name - Exit rc[%d] value[%x]\n", rc, *value);
-	return rc;
-}
-*/
-
-/*******************************************************************************
- * This routine will initialize the ops data structure used in the validate
- * function. It will also power off empty slots that are powered on since BIOS
- * leaves those on, albeit disconnected
- ******************************************************************************/
-static int __init init_ops (void)
-{
-	struct slot *slot_cur;
-	struct list_head *tmp;
-	int retval;
-	int rc;
-
-	list_for_each (tmp, &ibmphp_slot_head) {
-		slot_cur = list_entry (tmp, struct slot, ibm_slot_list);
-
-		if (!slot_cur)
-			return -ENODEV;
-
-		debug ("BEFORE GETTING SLOT STATUS, slot # %x\n", slot_cur->number);
-		if (slot_cur->ctrl->revision == 0xFF) 
-			if (get_ctrl_revision (slot_cur, &slot_cur->ctrl->revision))
-				return -1;
-
-		if (slot_cur->bus_on->current_speed == 0xFF) 
-			if (get_cur_bus_info (&slot_cur)) 
-				return -1;
-
-		if (slot_cur->ctrl->options == 0xFF)
-			if (get_hpc_options (slot_cur, &slot_cur->ctrl->options))
-				return -1;
-
-		retval = slot_update (&slot_cur);
-		if (retval)
-			return retval;
-
-		debug ("status = %x\n", slot_cur->status);
-		debug ("ext_status = %x\n", slot_cur->ext_status);
-		debug ("SLOT_POWER = %x\n", SLOT_POWER (slot_cur->status));
-		debug ("SLOT_PRESENT = %x\n", SLOT_PRESENT (slot_cur->status));
-		debug ("SLOT_LATCH = %x\n", SLOT_LATCH (slot_cur->status));
-
-		if ((SLOT_PWRGD (slot_cur->status)) && 
-		    !(SLOT_PRESENT (slot_cur->status)) && 
-		    !(SLOT_LATCH (slot_cur->status))) {
-			debug ("BEFORE POWER OFF COMMAND\n");
-				rc = power_off (slot_cur);
-				if (rc)
-					return rc;
-
-	/*		retval = slot_update (&slot_cur);
-	 *		if (retval)
-	 *			return retval;
-	 *		ibmphp_update_slot_info (slot_cur);
-	 */
-		}
-	}
-	init_flag = 0;
-	return 0;
-}
-
-/* This operation will check whether the slot is within the bounds and
- * the operation is valid to perform on that slot
- * Parameters: slot, operation
- * Returns: 0 or error codes
- */
-static int validate (struct slot *slot_cur, int opn)
-{
-	int number;
-	int retval;
-
-	if (!slot_cur)
-		return -ENODEV;
-	number = slot_cur->number;
-	if ((number > max_slots) || (number < 0))
-		return -EBADSLT;
-	debug ("slot_number in validate is %d\n", slot_cur->number);
-
-	retval = slot_update (&slot_cur);
-	if (retval)
-		return retval;
-
-	switch (opn) {
-		case ENABLE:
-			if (!(SLOT_PWRGD (slot_cur->status)) && 
-			     (SLOT_PRESENT (slot_cur->status)) && 
-			     !(SLOT_LATCH (slot_cur->status)))
-				return 0;
-			break;
-		case DISABLE:
-			if ((SLOT_PWRGD (slot_cur->status)) && 
-			    (SLOT_PRESENT (slot_cur->status)) &&
-			    !(SLOT_LATCH (slot_cur->status)))
-				return 0;
-			break;
-		default:
-			break;
-	}
-	err ("validate failed....\n");
-	return -EINVAL;
-}
-
-/********************************************************************************
- * This routine is for updating the data structures in the hotplug core
- * Parameters: struct slot
- * Returns: 0 or error
- *******************************************************************************/
-int ibmphp_update_slot_info (struct slot *slot_cur)
-{
-	struct hotplug_slot_info *info;
-	int rc;
-	u8 bus_speed;
-	u8 mode;
-
-	info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
-	if (!info) {
-		err ("out of system memory \n");
-		return -ENOMEM;
-	}
-        
-	info->power_status = SLOT_PWRGD (slot_cur->status);
-	info->attention_status = SLOT_ATTN (slot_cur->status, slot_cur->ext_status);
-	info->latch_status = SLOT_LATCH (slot_cur->status);
-        if (!SLOT_PRESENT (slot_cur->status)) {
-                info->adapter_status = 0;
-//		info->max_adapter_speed_status = MAX_ADAPTER_NONE;
-	} else {
-                info->adapter_status = 1;
-//		get_max_adapter_speed_1 (slot_cur->hotplug_slot, &info->max_adapter_speed_status, 0);
-	}
-
-	bus_speed = slot_cur->bus_on->current_speed;
-	mode = slot_cur->bus_on->current_bus_mode;
-
-	switch (bus_speed) {
-	case BUS_SPEED_33:
-		break;
-	case BUS_SPEED_66:
-		if (mode == BUS_MODE_PCIX) 
-			bus_speed += 0x01;
-		else if (mode == BUS_MODE_PCI)
-			;
-		else
-			bus_speed = PCI_SPEED_UNKNOWN;
-		break;
-	case BUS_SPEED_100:
-	case BUS_SPEED_133:
-		bus_speed += 0x01;
-		break;
-	default:
-		bus_speed = PCI_SPEED_UNKNOWN;
-	}
-
-	info->cur_bus_speed = bus_speed;
-	info->max_bus_speed = slot_cur->hotplug_slot->info->max_bus_speed;
-	// To do: bus_names 
-	
-	rc = pci_hp_change_slot_info (slot_cur->hotplug_slot, info);
-	kfree (info);
-	return rc;
-}
-
-
-/******************************************************************************
- * This function will return the pci_func, given bus and devfunc, or NULL.  It
- * is called from visit routines
- ******************************************************************************/
-
-static struct pci_func *ibm_slot_find (u8 busno, u8 device, u8 function)
-{
-	struct pci_func *func_cur;
-	struct slot *slot_cur;
-	struct list_head * tmp;
-	list_for_each (tmp, &ibmphp_slot_head) {
-		slot_cur = list_entry (tmp, struct slot, ibm_slot_list);
-		if (slot_cur->func) {
-			func_cur = slot_cur->func;
-			while (func_cur) {
-				if ((func_cur->busno == busno) && (func_cur->device == device) && (func_cur->function == function))
-					return func_cur;
-				func_cur = func_cur->next;
-			}
-		}
-	}
-	return NULL;
-}
-
-/*************************************************************
- * This routine frees up memory used by struct slot, including
- * the pointers to pci_func, bus, hotplug_slot, controller,
- * and deregistering from the hotplug core
- *************************************************************/
-static void free_slots (void)
-{
-	struct slot *slot_cur;
-	struct list_head * tmp;
-	struct list_head * next;
-
-	debug ("%s -- enter\n", __FUNCTION__);
-
-	list_for_each_safe (tmp, next, &ibmphp_slot_head) {
-	
-		slot_cur = list_entry (tmp, struct slot, ibm_slot_list);
-
-		pci_hp_deregister (slot_cur->hotplug_slot);
-
-		if (slot_cur->hotplug_slot) {
-			kfree (slot_cur->hotplug_slot);
-			slot_cur->hotplug_slot = NULL;
-		}
-
-		if (slot_cur->ctrl) 
-			slot_cur->ctrl = NULL;
-		
-		if (slot_cur->bus_on) 
-			slot_cur->bus_on = NULL;
-
-		ibmphp_unconfigure_card (&slot_cur, -1);  /* we don't want to actually remove the resources, since free_resources will do just that */
-
-		kfree (slot_cur);
-		slot_cur = NULL;
-	}
-	debug ("%s -- exit\n", __FUNCTION__);
-}
-
-static int ibm_unconfigure_device (struct pci_func *func)
-{
-	struct pci_dev *temp;
-	u8 j;
-
-	debug ("inside %s\n", __FUNCTION__);
-	debug ("func->device = %x, func->function = %x\n", func->device, func->function);
-	debug ("func->device << 3 | 0x0  = %x\n", func->device << 3 | 0x0);
-
-	for (j = 0; j < 0x08; j++) {
-		temp = pci_find_slot (func->busno, (func->device << 3) | j);
-		if (temp)
-			pci_remove_bus_device(temp);
-	}
-	return 0;
-}
-
-/*
- * The following function is to fix kernel bug regarding 
- * getting bus entries, here we manually add those primary 
- * bus entries to kernel bus structure whenever apply
- */
-
-static u8 bus_structure_fixup (u8 busno)
-{
-	struct pci_bus *bus;
-	struct pci_dev *dev;
-	u16 l;
-
-	if (pci_find_bus(busno) || !(ibmphp_find_same_bus_num (busno)))
-		return 1;
-
-	bus = kmalloc (sizeof (*bus), GFP_KERNEL);
-	if (!bus) {
-		err ("%s - out of memory\n", __FUNCTION__);
-		return 1;
-	}
-	dev = kmalloc (sizeof (*dev), GFP_KERNEL);
-	if (!dev) {
-		kfree (bus);
-		err ("%s - out of memory\n", __FUNCTION__);
-		return 1;
-	}
-
-	bus->number = busno;
-	bus->ops = ibmphp_pci_bus->ops;
-	dev->bus = bus;
-	for (dev->devfn = 0; dev->devfn < 256; dev->devfn += 8) {
-		if (!pci_read_config_word (dev, PCI_VENDOR_ID, &l) &&  l != 0x0000 && l != 0xffff) {
-			debug ("%s - Inside bus_struture_fixup() \n", __FUNCTION__);
-			pci_scan_bus (busno, ibmphp_pci_bus->ops, NULL);
-			break;
-		}
-	}
-
-	kfree (dev);
-	kfree (bus);
-
-	return 0;
-}
-
-static int ibm_configure_device (struct pci_func *func)
-{
-	unsigned char bus;
-	struct pci_bus *child;
-	int num;
-	int flag = 0;	/* this is to make sure we don't double scan the bus, for bridged devices primarily */
-
-	if (!(bus_structure_fixup (func->busno)))
-		flag = 1;
-	if (func->dev == NULL)
-		func->dev = pci_find_slot (func->busno, PCI_DEVFN(func->device, func->function));
-
-	if (func->dev == NULL) {
-		struct pci_bus *bus = pci_find_bus(func->busno);
-		if (!bus)
-			return 0;
-
-		num = pci_scan_slot(bus, PCI_DEVFN(func->device, func->function));
-		if (num)
-			pci_bus_add_devices(bus);
-
-		func->dev = pci_find_slot(func->busno, PCI_DEVFN(func->device, func->function));
-		if (func->dev == NULL) {
-			err ("ERROR... : pci_dev still NULL \n");
-			return 0;
-		}
-	}
-	if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) {
-		pci_read_config_byte (func->dev, PCI_SECONDARY_BUS, &bus);
-		child = (struct pci_bus *) pci_add_new_bus (func->dev->bus, (func->dev), bus);
-		pci_do_scan_bus (child);
-	}
-
-	return 0;
-}
-
-/*******************************************************
- * Returns whether the bus is empty or not 
- *******************************************************/
-static int is_bus_empty (struct slot * slot_cur)
-{
-	int rc;
-	struct slot * tmp_slot;
-	u8 i = slot_cur->bus_on->slot_min;
-
-	while (i <= slot_cur->bus_on->slot_max) {
-		if (i == slot_cur->number) {
-			i++;
-			continue;
-		}
-		tmp_slot = ibmphp_get_slot_from_physical_num (i);
-		if (!tmp_slot)
-			return 0;
-		rc = slot_update (&tmp_slot);
-		if (rc)
-			return 0;
-		if (SLOT_PRESENT (tmp_slot->status) && SLOT_PWRGD (tmp_slot->status))
-			return 0;
-		i++;
-	}
-	return 1;
-}
-
-/***********************************************************
- * If the HPC permits and the bus currently empty, tries to set the 
- * bus speed and mode at the maximum card and bus capability
- * Parameters: slot
- * Returns: bus is set (0) or error code
- ***********************************************************/
-static int set_bus (struct slot * slot_cur)
-{
-	int rc;
-	u8 speed;
-	u8 cmd = 0x0;
-	struct pci_dev * dev;
-	int retval;
-
-	debug ("%s - entry slot # %d \n", __FUNCTION__, slot_cur->number);
-	if (SET_BUS_STATUS (slot_cur->ctrl) && is_bus_empty (slot_cur)) {
-		rc = slot_update (&slot_cur);
-		if (rc)
-			return rc;
-		speed = SLOT_SPEED (slot_cur->ext_status);
-		debug ("ext_status = %x, speed = %x\n", slot_cur->ext_status, speed);
-		switch (speed) {
-		case HPC_SLOT_SPEED_33:
-			cmd = HPC_BUS_33CONVMODE;
-			break;
-		case HPC_SLOT_SPEED_66:
-			if (SLOT_PCIX (slot_cur->ext_status)) {
-				if ((slot_cur->supported_speed >= BUS_SPEED_66) && (slot_cur->supported_bus_mode == BUS_MODE_PCIX))
-					cmd = HPC_BUS_66PCIXMODE;
-				else if (!SLOT_BUS_MODE (slot_cur->ext_status))
-					/* if max slot/bus capability is 66 pci
-					and there's no bus mode mismatch, then
-					the adapter supports 66 pci */ 
-					cmd = HPC_BUS_66CONVMODE;
-				else
-					cmd = HPC_BUS_33CONVMODE;
-			} else {
-				if (slot_cur->supported_speed >= BUS_SPEED_66)
-					cmd = HPC_BUS_66CONVMODE;
-				else
-					cmd = HPC_BUS_33CONVMODE;
-			}
-			break;
-		case HPC_SLOT_SPEED_133:
-			switch (slot_cur->supported_speed) {
-			case BUS_SPEED_33:
-				cmd = HPC_BUS_33CONVMODE;
-				break;
-			case BUS_SPEED_66:
-				if (slot_cur->supported_bus_mode == BUS_MODE_PCIX)
-					cmd = HPC_BUS_66PCIXMODE;
-				else
-					cmd = HPC_BUS_66CONVMODE;
-				break;
-			case BUS_SPEED_100:
-				cmd = HPC_BUS_100PCIXMODE;
-				break;
-			case BUS_SPEED_133:
-				/* This is to take care of the bug in CIOBX chip */
-				pci_for_each_dev(dev) {
-					if ((dev->vendor == PCI_VENDOR_ID_SERVERWORKS) &&
-					    (dev->device == 0x0101))
-						ibmphp_hpc_writeslot (slot_cur, HPC_BUS_100PCIXMODE);
-				}
-				cmd = HPC_BUS_133PCIXMODE;
-				break;
-			default:
-				err ("Wrong bus speed \n");
-				return -ENODEV;
-			}
-			break;
-		default:
-			err ("wrong slot speed \n");
-			return -ENODEV;
-		}
-		debug ("setting bus speed for slot %d, cmd %x\n", slot_cur->number, cmd);
-		retval = ibmphp_hpc_writeslot (slot_cur, cmd);
-		if (retval) {
-			err ("setting bus speed failed\n");
-			return retval;
-		}
-		if (CTLR_RESULT (slot_cur->ctrl->status)) {
-			err ("command not completed successfully in set_bus \n");
-			return -EIO;
-		}
-	}
-	/* This is for x440, once Brandon fixes the firmware, 
-	will not need this delay */
-	long_delay (1 * HZ);
-	debug ("%s -Exit \n", __FUNCTION__);
-	return 0;
-}
-
-/* This routine checks the bus limitations that the slot is on from the BIOS.
- * This is used in deciding whether or not to power up the slot.  
- * (electrical/spec limitations. For example, >1 133 MHz or >2 66 PCI cards on
- * same bus) 
- * Parameters: slot
- * Returns: 0 = no limitations, -EINVAL = exceeded limitations on the bus
- */
-static int check_limitations (struct slot *slot_cur)
-{
-	u8 i;
-	struct slot * tmp_slot;
-	u8 count = 0;
-	u8 limitation = 0;
-
-	for (i = slot_cur->bus_on->slot_min; i <= slot_cur->bus_on->slot_max; i++) {
-		tmp_slot = ibmphp_get_slot_from_physical_num (i);
-		if (!tmp_slot)
-			return -ENODEV;
-		if ((SLOT_PWRGD (tmp_slot->status)) && !(SLOT_CONNECT (tmp_slot->status))) 
-			count++;
-	}
-	get_cur_bus_info (&slot_cur);
-	switch (slot_cur->bus_on->current_speed) {
-	case BUS_SPEED_33:
-		limitation = slot_cur->bus_on->slots_at_33_conv;
-		break;
-	case BUS_SPEED_66:
-		if (slot_cur->bus_on->current_bus_mode == BUS_MODE_PCIX)
-			limitation = slot_cur->bus_on->slots_at_66_pcix;
-		else
-			limitation = slot_cur->bus_on->slots_at_66_conv;
-		break;
-	case BUS_SPEED_100:
-		limitation = slot_cur->bus_on->slots_at_100_pcix;
-		break;
-	case BUS_SPEED_133:
-		limitation = slot_cur->bus_on->slots_at_133_pcix;
-		break;
-	}
-
-	if ((count + 1) > limitation)
-		return -EINVAL;
-	return 0;
-}
-
-static inline void print_card_capability (struct slot *slot_cur)
-{
-	info ("capability of the card is ");
-	if ((slot_cur->ext_status & CARD_INFO) == PCIX133) 
-		info ("   133 MHz PCI-X \n");
-	else if ((slot_cur->ext_status & CARD_INFO) == PCIX66)
-		info ("    66 MHz PCI-X \n");
-	else if ((slot_cur->ext_status & CARD_INFO) == PCI66)
-		info ("    66 MHz PCI \n");
-	else
-		info ("    33 MHz PCI \n");
-
-}
-
-/* This routine will power on the slot, configure the device(s) and find the
- * drivers for them.
- * Parameters: hotplug_slot
- * Returns: 0 or failure codes
- */
-static int enable_slot (struct hotplug_slot *hs)
-{
-	int rc, i, rcpr;
-	struct slot *slot_cur;
-	u8 function;
-	struct pci_func *tmp_func;
-
-	ibmphp_lock_operations ();
-
-	debug ("ENABLING SLOT........ \n");
-	slot_cur = (struct slot *) hs->private;
-
-	if ((rc = validate (slot_cur, ENABLE))) {
-		err ("validate function failed \n");
-		goto error_nopower;
-	}
-
-	attn_LED_blink (slot_cur);
-	
-	rc = set_bus (slot_cur);
-	if (rc) {
-		err ("was not able to set the bus \n");
-		goto error_nopower;
-	}
-
-	/*-----------------debugging------------------------------*/
-	get_cur_bus_info (&slot_cur);
-	debug ("the current bus speed right after set_bus = %x \n", slot_cur->bus_on->current_speed); 
-	/*----------------------------------------------------------*/
-
-	rc = check_limitations (slot_cur);
-	if (rc) {
-		err ("Adding this card exceeds the limitations of this bus.\n");
-		err ("(i.e., >1 133MHz cards running on same bus, or "
-		     ">2 66 PCI cards running on same bus\n.");
-		err ("Try hot-adding into another bus \n");
-		rc = -EINVAL;
-		goto error_nopower;
-	}
-
-	rc = power_on (slot_cur);
-
-	if (rc) {
-		err ("something wrong when powering up... please see below for details\n");
-		/* need to turn off before on, otherwise, blinking overwrites */
-		attn_off(slot_cur);
-		attn_on (slot_cur);
-		if (slot_update (&slot_cur)) {
-			attn_off (slot_cur);
-			attn_on (slot_cur);
-			rc = -ENODEV;
-			goto exit;
-		}
-		/* Check to see the error of why it failed */
-		if ((SLOT_POWER (slot_cur->status)) && !(SLOT_PWRGD (slot_cur->status)))
-			err ("power fault occurred trying to power up \n");
-		else if (SLOT_BUS_SPEED (slot_cur->status)) {
-			err ("bus speed mismatch occurred.  please check current bus speed and card capability \n");
-			print_card_capability (slot_cur);
-		} else if (SLOT_BUS_MODE (slot_cur->ext_status)) {
-			err ("bus mode mismatch occurred.  please check current bus mode and card capability \n");
-			print_card_capability (slot_cur);
-		}
-		ibmphp_update_slot_info (slot_cur);
-		goto exit;
-	}
-	debug ("after power_on\n");
-	/*-----------------------debugging---------------------------*/
-	get_cur_bus_info (&slot_cur);
-	debug ("the current bus speed right after power_on = %x \n", slot_cur->bus_on->current_speed);
-	/*----------------------------------------------------------*/
-
-	rc = slot_update (&slot_cur);
-	if (rc)
-		goto error_power;
-	
-	rc = -EINVAL;
-	if (SLOT_POWER (slot_cur->status) && !(SLOT_PWRGD (slot_cur->status))) {
-		err ("power fault occurred trying to power up... \n");
-		goto error_power;
-	}
-	if (SLOT_POWER (slot_cur->status) && (SLOT_BUS_SPEED (slot_cur->status))) {
-		err ("bus speed mismatch occurred.  please check current bus speed and card capability \n");
-		print_card_capability (slot_cur);
-		goto error_power;
-	} 
-	/* Don't think this case will happen after above checks... but just in case, for paranoia sake */
-	if (!(SLOT_POWER (slot_cur->status))) {
-		err ("power on failed... \n");
-		goto error_power;
-	}
-
-	slot_cur->func = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
-	if (!slot_cur->func) {
-		/* We cannot do update_slot_info here, since no memory for
-		 * kmalloc n.e.ways, and update_slot_info allocates some */
-		err ("out of system memory \n");
-		rc = -ENOMEM;
-		goto error_power;
-	}
-	memset (slot_cur->func, 0, sizeof (struct pci_func));
-	slot_cur->func->busno = slot_cur->bus;
-	slot_cur->func->device = slot_cur->device;
-	for (i = 0; i < 4; i++)
-		slot_cur->func->irq[i] = slot_cur->irq[i];
-
-	debug ("b4 configure_card, slot_cur->bus = %x, slot_cur->device = %x\n", slot_cur->bus, slot_cur->device);
-
-	if (ibmphp_configure_card (slot_cur->func, slot_cur->number)) {
-		err ("configure_card was unsuccessful... \n");
-		ibmphp_unconfigure_card (&slot_cur, 1); /* true because don't need to actually deallocate resources, just remove references */
-		debug ("after unconfigure_card\n");
-		slot_cur->func = NULL;
-		rc = -ENOMEM;
-		goto error_power;
-	}
-
-	function = 0x00;
-	do {
-		tmp_func = ibm_slot_find (slot_cur->bus, slot_cur->func->device, function++);
-		if (tmp_func && !(tmp_func->dev))
-			ibm_configure_device (tmp_func);
-	} while (tmp_func);
-
-	attn_off (slot_cur);
-	if (slot_update (&slot_cur)) {
-		rc = -EFAULT;
-		goto exit;
-	}
-	ibmphp_print_test ();
-	rc = ibmphp_update_slot_info (slot_cur);
-exit:
-	ibmphp_unlock_operations(); 
-	return rc;
-
-error_nopower:
-	attn_off (slot_cur);	/* need to turn off if was blinking b4 */
-	attn_on (slot_cur);
-error_cont:
-	rcpr = slot_update (&slot_cur);
-	if (rcpr) {
-		rc = rcpr;
-		goto exit;
-	}
-	ibmphp_update_slot_info (slot_cur);
-	goto exit;
-
-error_power:
-	attn_off (slot_cur);	/* need to turn off if was blinking b4 */
-	attn_on (slot_cur);
-	rcpr = power_off (slot_cur);
-	if (rcpr) {
-		rc = rcpr;
-		goto exit;
-	}
-	goto error_cont;
-}
-
-/**************************************************************
-* HOT REMOVING ADAPTER CARD                                   *
-* INPUT: POINTER TO THE HOTPLUG SLOT STRUCTURE                *
-* OUTPUT: SUCCESS 0 ; FAILURE: UNCONFIGURE , VALIDATE         *
-          DISABLE POWER ,                                    *
-**************************************************************/
-int ibmphp_disable_slot (struct hotplug_slot *hotplug_slot)
-{
-	struct slot *slot = hotplug_slot->private;
-	int rc;
-	
-	ibmphp_lock_operations();
-	rc = ibmphp_do_disable_slot(slot);
-	ibmphp_unlock_operations();
-	return rc;
-}
-
-int ibmphp_do_disable_slot (struct slot *slot_cur)
-{
-	int rc;
-	u8 flag;
-	int parm = 0;
-
-	debug ("DISABLING SLOT... \n"); 
-		
-	if ((slot_cur == NULL) || (slot_cur->ctrl == NULL)) {
-		return -ENODEV;
-	}
-	
-	flag = slot_cur->flag;
-	slot_cur->flag = TRUE;
-
-	if (flag == TRUE) {
-		rc = validate (slot_cur, DISABLE);	/* checking if powered off already & valid slot # */
-		if (rc)
-			goto error;
-	}
-	attn_LED_blink (slot_cur);
-
-	if (slot_cur->func == NULL) {
-		/* We need this for fncs's that were there on bootup */
-		slot_cur->func = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
-		if (!slot_cur->func) {
-			err ("out of system memory \n");
-			rc = -ENOMEM;
-			goto error;
-		}
-		memset (slot_cur->func, 0, sizeof (struct pci_func));
-		slot_cur->func->busno = slot_cur->bus;
-		slot_cur->func->device = slot_cur->device;
-	}
-
-	if ((rc = ibm_unconfigure_device (slot_cur->func))) {
-		err ("removing from kernel failed... \n");
-		err ("Please check to see if it was statically linked or is "
-		     "in use otherwise. (perhaps the driver is not 'hot-removable')\n");
-		goto error;
-	}
-        
-	/* If we got here from latch suddenly opening on operating card or 
-	a power fault, there's no power to the card, so cannot
-	read from it to determine what resources it occupied.  This operation
-	is forbidden anyhow.  The best we can do is remove it from kernel
-	lists at least */
-
-	if (!flag) {
-		attn_off (slot_cur);
-		return 0;
-	}
-
-	rc = ibmphp_unconfigure_card (&slot_cur, parm);
-	slot_cur->func = NULL;
-	debug ("in disable_slot. after unconfigure_card\n");
-	if (rc) {
-		err ("could not unconfigure card.\n");
-		goto error;
-	}
-
-	rc = ibmphp_hpc_writeslot (slot_cur, HPC_SLOT_OFF);
-	if (rc)
-		goto error;
-
-	attn_off (slot_cur);
-	rc = slot_update (&slot_cur);
-	if (rc)
-		goto exit;
-
-	rc = ibmphp_update_slot_info (slot_cur);
-	ibmphp_print_test ();
-exit:
-	return rc;
-
-error:
-	/*  Need to turn off if was blinking b4 */
-	attn_off (slot_cur);
-	attn_on (slot_cur);
-	if (slot_update (&slot_cur)) {
-		rc = -EFAULT;
-		goto exit;
-	}
-	if (flag)		
-		ibmphp_update_slot_info (slot_cur);
-	goto exit;
-}
-
-struct hotplug_slot_ops ibmphp_hotplug_slot_ops = {
-	.owner =			THIS_MODULE,
-	.set_attention_status =		set_attention_status,
-	.enable_slot =			enable_slot,
-	.disable_slot =			ibmphp_disable_slot,
-	.hardware_test =		NULL,
-	.get_power_status =		get_power_status,
-	.get_attention_status =		get_attention_status,
-	.get_latch_status =		get_latch_status,
-	.get_adapter_status =		get_adapter_present,
-	.get_max_bus_speed =		get_max_bus_speed,
-	.get_cur_bus_speed =		get_cur_bus_speed,
-/*	.get_max_adapter_speed =	get_max_adapter_speed,
-	.get_bus_name_status =		get_bus_name,
-*/
-};
-
-static void ibmphp_unload (void)
-{
-	free_slots ();
-	debug ("after slots \n");
-	ibmphp_free_resources ();
-	debug ("after resources \n");
-	ibmphp_free_bus_info_queue ();
-	debug ("after bus info \n");
-	ibmphp_free_ebda_hpc_queue ();
-	debug ("after ebda hpc \n");
-	ibmphp_free_ebda_pci_rsrc_queue ();
-	debug ("after ebda pci rsrc \n");
-	kfree (ibmphp_pci_bus);
-}
-
-static int __init ibmphp_init (void)
-{
-	struct pci_bus *bus;
-	int i = 0;
-	int rc = 0;
-
-	init_flag = 1;
-
-	info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
-
-	ibmphp_pci_bus = kmalloc (sizeof (*ibmphp_pci_bus), GFP_KERNEL);
-	if (!ibmphp_pci_bus) {
-		err ("out of memory\n");
-		rc = -ENOMEM;
-		goto exit;
-	}
-
-	bus = pci_find_bus(0);
-	if (!bus) {
-		err ("Can't find the root pci bus, can not continue\n");
-		rc = -ENODEV;
-		goto error;
-	}
-	memcpy (ibmphp_pci_bus, bus, sizeof (*ibmphp_pci_bus));
-
-	ibmphp_debug = debug;
-
-	ibmphp_hpc_initvars ();
-
-	for (i = 0; i < 16; i++)
-		irqs[i] = 0;
-
-	if ((rc = ibmphp_access_ebda ()))
-		goto error;
-	debug ("after ibmphp_access_ebda ()\n");
-
-	if ((rc = ibmphp_rsrc_init ()))
-		goto error;
-	debug ("AFTER Resource & EBDA INITIALIZATIONS\n");
-
-	max_slots = get_max_slots ();
-	
-	if ((rc = ibmphp_register_pci ()))
-		goto error;
-
-	if (init_ops ()) {
-		rc = -ENODEV;
-		goto error;
-	}
-
-	ibmphp_print_test ();
-	if ((rc = ibmphp_hpc_start_poll_thread ())) {
-		goto error;
-	}
-
-	/* lock ourselves into memory with a module 
-	 * count of -1 so that no one can unload us. */
-	module_put(THIS_MODULE);
-
-exit:
-	return rc;
-
-error:
-	ibmphp_unload ();
-	goto exit;
-}
-
-static void __exit ibmphp_exit (void)
-{
-	ibmphp_hpc_stop_poll_thread ();
-	debug ("after polling\n");
-	ibmphp_unload ();
-	debug ("done\n");
-}
-
-module_init (ibmphp_init);
-module_exit (ibmphp_exit);
diff -Nru a/drivers/hotplug/ibmphp_ebda.c b/drivers/hotplug/ibmphp_ebda.c
--- a/drivers/hotplug/ibmphp_ebda.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1228 +0,0 @@
-/*
- * IBM Hot Plug Controller Driver
- *
- * Written By: Tong Yu, IBM Corporation
- *
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001,2002 IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <gregkh@us.ibm.com>
- *
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/list.h>
-#include <linux/init.h>
-#include "ibmphp.h"
-
-/*
- * POST builds data blocks(in this data block definition, a char-1
- * byte, short(or word)-2 byte, long(dword)-4 byte) in the Extended
- * BIOS Data Area which describe the configuration of the hot-plug
- * controllers and resources used by the PCI Hot-Plug devices.
- *
- * This file walks EBDA, maps data block from physical addr,
- * reconstruct linked lists about all system resource(MEM, PFM, IO)
- * already assigned by POST, as well as linked lists about hot plug
- * controllers (ctlr#, slot#, bus&slot features...)
- */
-
-/* Global lists */
-LIST_HEAD (ibmphp_ebda_pci_rsrc_head);
-LIST_HEAD (ibmphp_slot_head);
-
-/* Local variables */
-static struct ebda_hpc_list *hpc_list_ptr;
-static struct ebda_rsrc_list *rsrc_list_ptr;
-static struct rio_table_hdr *rio_table_ptr = NULL;
-static LIST_HEAD (ebda_hpc_head);
-static LIST_HEAD (bus_info_head);
-static LIST_HEAD (rio_vg_head);
-static LIST_HEAD (rio_lo_head);
-static LIST_HEAD (opt_vg_head);
-static LIST_HEAD (opt_lo_head);
-static void *io_mem;
-
-/* Local functions */
-static int ebda_rsrc_controller (void);
-static int ebda_rsrc_rsrc (void);
-static int ebda_rio_table (void);
-
-static struct ebda_hpc_list * __init alloc_ebda_hpc_list (void)
-{
-	struct ebda_hpc_list *list;
-
-	list = kmalloc (sizeof (struct ebda_hpc_list), GFP_KERNEL);
-	if (!list)
-		return NULL;
-	memset (list, 0, sizeof (*list));
-	return list;
-}
-
-static struct controller *alloc_ebda_hpc (u32 slot_count, u32 bus_count)
-{
-	struct controller *controller;
-	struct ebda_hpc_slot *slots;
-	struct ebda_hpc_bus *buses;
-
-	controller = kmalloc (sizeof (struct controller), GFP_KERNEL);
-	if (!controller)
-		return NULL;
-	memset (controller, 0, sizeof (*controller));
-
-	slots = kmalloc (sizeof (struct ebda_hpc_slot) * slot_count, GFP_KERNEL);
-	if (!slots) {
-		kfree (controller);
-		return NULL;
-	}
-	memset (slots, 0, sizeof (*slots) * slot_count);
-	controller->slots = slots;
-
-	buses = kmalloc (sizeof (struct ebda_hpc_bus) * bus_count, GFP_KERNEL);
-	if (!buses) {
-		kfree (controller->slots);
-		kfree (controller);
-		return NULL;
-	}
-	memset (buses, 0, sizeof (*buses) * bus_count);
-	controller->buses = buses;
-
-	return controller;
-}
-
-static void free_ebda_hpc (struct controller *controller)
-{
-	kfree (controller->slots);
-	controller->slots = NULL;
-	kfree (controller->buses);
-	controller->buses = NULL;
-	controller->ctrl_dev = NULL;
-	kfree (controller);
-}
-
-static struct ebda_rsrc_list * __init alloc_ebda_rsrc_list (void)
-{
-	struct ebda_rsrc_list *list;
-
-	list = kmalloc (sizeof (struct ebda_rsrc_list), GFP_KERNEL);
-	if (!list)
-		return NULL;
-	memset (list, 0, sizeof (*list));
-	return list;
-}
-
-static struct ebda_pci_rsrc *alloc_ebda_pci_rsrc (void)
-{
-	struct ebda_pci_rsrc *resource;
-
-	resource = kmalloc (sizeof (struct ebda_pci_rsrc), GFP_KERNEL);
-	if (!resource)
-		return NULL;
-	memset (resource, 0, sizeof (*resource));
-	return resource;
-}
-
-static void __init print_bus_info (void)
-{
-	struct bus_info *ptr;
-	struct list_head *ptr1;
-	
-	list_for_each (ptr1, &bus_info_head) {
-		ptr = list_entry (ptr1, struct bus_info, bus_info_list);
-		debug ("%s - slot_min = %x\n", __FUNCTION__, ptr->slot_min);
-		debug ("%s - slot_max = %x\n", __FUNCTION__, ptr->slot_max);
-		debug ("%s - slot_count = %x\n", __FUNCTION__, ptr->slot_count);
-		debug ("%s - bus# = %x\n", __FUNCTION__, ptr->busno);
-		debug ("%s - current_speed = %x\n", __FUNCTION__, ptr->current_speed);
-		debug ("%s - controller_id = %x\n", __FUNCTION__, ptr->controller_id);
-		
-		debug ("%s - slots_at_33_conv = %x\n", __FUNCTION__, ptr->slots_at_33_conv);
-		debug ("%s - slots_at_66_conv = %x\n", __FUNCTION__, ptr->slots_at_66_conv);
-		debug ("%s - slots_at_66_pcix = %x\n", __FUNCTION__, ptr->slots_at_66_pcix);
-		debug ("%s - slots_at_100_pcix = %x\n", __FUNCTION__, ptr->slots_at_100_pcix);
-		debug ("%s - slots_at_133_pcix = %x\n", __FUNCTION__, ptr->slots_at_133_pcix);
-
-	}
-}
-
-static void print_lo_info (void)
-{
-	struct rio_detail *ptr;
-	struct list_head *ptr1;
-	debug ("print_lo_info ---- \n");	
-	list_for_each (ptr1, &rio_lo_head) {
-		ptr = list_entry (ptr1, struct rio_detail, rio_detail_list);
-		debug ("%s - rio_node_id = %x\n", __FUNCTION__, ptr->rio_node_id);
-		debug ("%s - rio_type = %x\n", __FUNCTION__, ptr->rio_type);
-		debug ("%s - owner_id = %x\n", __FUNCTION__, ptr->owner_id);
-		debug ("%s - first_slot_num = %x\n", __FUNCTION__, ptr->first_slot_num);
-		debug ("%s - wpindex = %x\n", __FUNCTION__, ptr->wpindex);
-		debug ("%s - chassis_num = %x\n", __FUNCTION__, ptr->chassis_num);
-
-	}
-}
-
-static void print_vg_info (void)
-{
-	struct rio_detail *ptr;
-	struct list_head *ptr1;
-	debug ("%s --- \n", __FUNCTION__);
-	list_for_each (ptr1, &rio_vg_head) {
-		ptr = list_entry (ptr1, struct rio_detail, rio_detail_list);
-		debug ("%s - rio_node_id = %x\n", __FUNCTION__, ptr->rio_node_id);
-		debug ("%s - rio_type = %x\n", __FUNCTION__, ptr->rio_type);
-		debug ("%s - owner_id = %x\n", __FUNCTION__, ptr->owner_id);
-		debug ("%s - first_slot_num = %x\n", __FUNCTION__, ptr->first_slot_num);
-		debug ("%s - wpindex = %x\n", __FUNCTION__, ptr->wpindex);
-		debug ("%s - chassis_num = %x\n", __FUNCTION__, ptr->chassis_num);
-
-	}
-}
-
-static void __init print_ebda_pci_rsrc (void)
-{
-	struct ebda_pci_rsrc *ptr;
-	struct list_head *ptr1;
-
-	list_for_each (ptr1, &ibmphp_ebda_pci_rsrc_head) {
-		ptr = list_entry (ptr1, struct ebda_pci_rsrc, ebda_pci_rsrc_list);
-		debug ("%s - rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n", 
-			__FUNCTION__, ptr->rsrc_type ,ptr->bus_num, ptr->dev_fun,ptr->start_addr, ptr->end_addr);
-	}
-}
-
-static void __init print_ibm_slot (void)
-{
-	struct slot *ptr;
-	struct list_head *ptr1;
-
-	list_for_each (ptr1, &ibmphp_slot_head) {
-		ptr = list_entry (ptr1, struct slot, ibm_slot_list);
-		debug ("%s - slot_number: %x \n", __FUNCTION__, ptr->number); 
-	}
-}
-
-static void __init print_opt_vg (void)
-{
-	struct opt_rio *ptr;
-	struct list_head *ptr1;
-	debug ("%s --- \n", __FUNCTION__);
-	list_for_each (ptr1, &opt_vg_head) {
-		ptr = list_entry (ptr1, struct opt_rio, opt_rio_list);
-		debug ("%s - rio_type %x \n", __FUNCTION__, ptr->rio_type); 
-		debug ("%s - chassis_num: %x \n", __FUNCTION__, ptr->chassis_num); 
-		debug ("%s - first_slot_num: %x \n", __FUNCTION__, ptr->first_slot_num); 
-		debug ("%s - middle_num: %x \n", __FUNCTION__, ptr->middle_num); 
-	}
-}
-
-static void __init print_ebda_hpc (void)
-{
-	struct controller *hpc_ptr;
-	struct list_head *ptr1;
-	u16 index;
-
-	list_for_each (ptr1, &ebda_hpc_head) {
-
-		hpc_ptr = list_entry (ptr1, struct controller, ebda_hpc_list); 
-
-		for (index = 0; index < hpc_ptr->slot_count; index++) {
-			debug ("%s - physical slot#: %x\n", __FUNCTION__, hpc_ptr->slots[index].slot_num);
-			debug ("%s - pci bus# of the slot: %x\n", __FUNCTION__, hpc_ptr->slots[index].slot_bus_num);
-			debug ("%s - index into ctlr addr: %x\n", __FUNCTION__, hpc_ptr->slots[index].ctl_index);
-			debug ("%s - cap of the slot: %x\n", __FUNCTION__, hpc_ptr->slots[index].slot_cap);
-		}
-
-		for (index = 0; index < hpc_ptr->bus_count; index++) {
-			debug ("%s - bus# of each bus controlled by this ctlr: %x\n", __FUNCTION__, hpc_ptr->buses[index].bus_num);
-		}
-
-		debug ("%s - type of hpc: %x\n", __FUNCTION__, hpc_ptr->ctlr_type);
-		switch (hpc_ptr->ctlr_type) {
-		case 1:
-			debug ("%s - bus: %x\n", __FUNCTION__, hpc_ptr->u.pci_ctlr.bus);
-			debug ("%s - dev_fun: %x\n", __FUNCTION__, hpc_ptr->u.pci_ctlr.dev_fun);
-			debug ("%s - irq: %x\n", __FUNCTION__, hpc_ptr->irq);
-			break;
-
-		case 0:
-			debug ("%s - io_start: %x\n", __FUNCTION__, hpc_ptr->u.isa_ctlr.io_start);
-			debug ("%s - io_end: %x\n", __FUNCTION__, hpc_ptr->u.isa_ctlr.io_end);
-			debug ("%s - irq: %x\n", __FUNCTION__, hpc_ptr->irq);
-			break;
-
-		case 2:
-		case 4:
-			debug ("%s - wpegbbar: %lx\n", __FUNCTION__, hpc_ptr->u.wpeg_ctlr.wpegbbar);
-			debug ("%s - i2c_addr: %x\n", __FUNCTION__, hpc_ptr->u.wpeg_ctlr.i2c_addr);
-			debug ("%s - irq: %x\n", __FUNCTION__, hpc_ptr->irq);
-			break;
-		}
-	}
-}
-
-int __init ibmphp_access_ebda (void)
-{
-	u8 format, num_ctlrs, rio_complete, hs_complete;
-	u16 ebda_seg, num_entries, next_offset, offset, blk_id, sub_addr, rc, re, rc_id, re_id, base;
-
-
-	rio_complete = 0;
-	hs_complete = 0;
-
-	io_mem = ioremap ((0x40 << 4) + 0x0e, 2);
-	if (!io_mem )
-		return -ENOMEM;
-	ebda_seg = readw (io_mem);
-	iounmap (io_mem);
-	debug ("returned ebda segment: %x\n", ebda_seg);
-	
-	io_mem = ioremap (ebda_seg<<4, 65000);
-	if (!io_mem )
-		return -ENOMEM;
-	next_offset = 0x180;
-
-	for (;;) {
-		offset = next_offset;
-		next_offset = readw (io_mem + offset);	/* offset of next blk */
-
-		offset += 2;
-		if (next_offset == 0)	/* 0 indicate it's last blk */
-			break;
-		blk_id = readw (io_mem + offset);	/* this blk id */
-
-		offset += 2;
-		/* check if it is hot swap block or rio block */
-		if (blk_id != 0x4853 && blk_id != 0x4752)
-			continue;
-		/* found hs table */
-		if (blk_id == 0x4853) {
-			debug ("now enter hot swap block---\n");
-			debug ("hot blk id: %x\n", blk_id);
-			format = readb (io_mem + offset);
-
-			offset += 1;
-			if (format != 4) {
-				iounmap (io_mem);
-				return -ENODEV;
-			}
-			debug ("hot blk format: %x\n", format);
-			/* hot swap sub blk */
-			base = offset;
-
-			sub_addr = base;
-			re = readw (io_mem + sub_addr);	/* next sub blk */
-
-			sub_addr += 2;
-			rc_id = readw (io_mem + sub_addr); 	/* sub blk id */
-
-			sub_addr += 2;
-			if (rc_id != 0x5243) {
-				iounmap (io_mem);
-				return -ENODEV;
-			}
-			/* rc sub blk signature  */
-			num_ctlrs = readb (io_mem + sub_addr);
-
-			sub_addr += 1;
-			hpc_list_ptr = alloc_ebda_hpc_list ();
-			if (!hpc_list_ptr) {
-				iounmap (io_mem);
-				return -ENOMEM;
-			}
-			hpc_list_ptr->format = format;
-			hpc_list_ptr->num_ctlrs = num_ctlrs;
-			hpc_list_ptr->phys_addr = sub_addr;	/*  offset of RSRC_CONTROLLER blk */
-			debug ("info about hpc descriptor---\n");
-			debug ("hot blk format: %x\n", format);
-			debug ("num of controller: %x\n", num_ctlrs);
-			debug ("offset of hpc data structure enteries: %x\n ", sub_addr);
-
-			sub_addr = base + re;	/* re sub blk */
-			rc = readw (io_mem + sub_addr);	/* next sub blk */
-
-			sub_addr += 2;
-			re_id = readw (io_mem + sub_addr);	/* sub blk id */
-
-			sub_addr += 2;
-			if (re_id != 0x5245) {
-				iounmap (io_mem);
-				return -ENODEV;
-			}
-
-			/* signature of re */
-			num_entries = readw (io_mem + sub_addr);
-
-			sub_addr += 2;	/* offset of RSRC_ENTRIES blk */
-			rsrc_list_ptr = alloc_ebda_rsrc_list ();
-			if (!rsrc_list_ptr ) {
-				iounmap (io_mem);
-				return -ENOMEM;
-			}
-			rsrc_list_ptr->format = format;
-			rsrc_list_ptr->num_entries = num_entries;
-			rsrc_list_ptr->phys_addr = sub_addr;
-
-			debug ("info about rsrc descriptor---\n");
-			debug ("format: %x\n", format);
-			debug ("num of rsrc: %x\n", num_entries);
-			debug ("offset of rsrc data structure enteries: %x\n ", sub_addr);
-
-			hs_complete = 1;
-		}
-		/* found rio table */
-		else if (blk_id == 0x4752) {
-			debug ("now enter io table ---\n");
-			debug ("rio blk id: %x\n", blk_id);
-
-			rio_table_ptr = kmalloc (sizeof (struct rio_table_hdr), GFP_KERNEL);
-			if (!rio_table_ptr)
-				return -ENOMEM; 
-			memset (rio_table_ptr, 0, sizeof (struct rio_table_hdr) );
-			rio_table_ptr->ver_num = readb (io_mem + offset);
-			rio_table_ptr->scal_count = readb (io_mem + offset + 1);
-			rio_table_ptr->riodev_count = readb (io_mem + offset + 2);
-			rio_table_ptr->offset = offset +3 ;
-			
-			debug ("info about rio table hdr ---\n");
-			debug ("ver_num: %x\nscal_count: %x\nriodev_count: %x\noffset of rio table: %x\n ", rio_table_ptr->ver_num, rio_table_ptr->scal_count, rio_table_ptr->riodev_count, rio_table_ptr->offset);
-
-			rio_complete = 1;
-		}
-	}
-
-	if (!hs_complete && !rio_complete) {
-		iounmap (io_mem);
-		return -ENODEV;
-	}
-
-	if (rio_table_ptr) {
-		if (rio_complete == 1 && rio_table_ptr->ver_num == 3) {
-			rc = ebda_rio_table ();
-			if (rc) {
-				iounmap (io_mem);
-				return rc;
-			}
-		}
-	}
-	rc = ebda_rsrc_controller ();
-	if (rc) {
-		iounmap (io_mem);
-		return rc;
-	}
-
-	rc = ebda_rsrc_rsrc ();
-	if (rc) {
-		iounmap (io_mem);
-		return rc;
-	}
-
-	iounmap (io_mem);
-	return 0;
-}
-
-/*
- * map info of scalability details and rio details from physical address
- */
-static int __init ebda_rio_table (void)
-{
-	u16 offset;
-	u8 i;
-	struct rio_detail *rio_detail_ptr;
-
-	offset = rio_table_ptr->offset;
-	offset += 12 * rio_table_ptr->scal_count;
-
-	// we do concern about rio details
-	for (i = 0; i < rio_table_ptr->riodev_count; i++) {
-		rio_detail_ptr = kmalloc (sizeof (struct rio_detail), GFP_KERNEL);
-		if (!rio_detail_ptr)
-			return -ENOMEM;
-		memset (rio_detail_ptr, 0, sizeof (struct rio_detail));
-		rio_detail_ptr->rio_node_id = readb (io_mem + offset);
-		rio_detail_ptr->bbar = readl (io_mem + offset + 1);
-		rio_detail_ptr->rio_type = readb (io_mem + offset + 5);
-		rio_detail_ptr->owner_id = readb (io_mem + offset + 6);
-		rio_detail_ptr->port0_node_connect = readb (io_mem + offset + 7);
-		rio_detail_ptr->port0_port_connect = readb (io_mem + offset + 8);
-		rio_detail_ptr->port1_node_connect = readb (io_mem + offset + 9);
-		rio_detail_ptr->port1_port_connect = readb (io_mem + offset + 10);
-		rio_detail_ptr->first_slot_num = readb (io_mem + offset + 11);
-		rio_detail_ptr->status = readb (io_mem + offset + 12);
-		rio_detail_ptr->wpindex = readb (io_mem + offset + 13);
-		rio_detail_ptr->chassis_num = readb (io_mem + offset + 14);
-//		debug ("rio_node_id: %x\nbbar: %x\nrio_type: %x\nowner_id: %x\nport0_node: %x\nport0_port: %x\nport1_node: %x\nport1_port: %x\nfirst_slot_num: %x\nstatus: %x\n", rio_detail_ptr->rio_node_id, rio_detail_ptr->bbar, rio_detail_ptr->rio_type, rio_detail_ptr->owner_id, rio_detail_ptr->port0_node_connect, rio_detail_ptr->port0_port_connect, rio_detail_ptr->port1_node_connect, rio_detail_ptr->port1_port_connect, rio_detail_ptr->first_slot_num, rio_detail_ptr->status);
-		//create linked list of chassis
-		if (rio_detail_ptr->rio_type == 4 || rio_detail_ptr->rio_type == 5) 
-			list_add (&rio_detail_ptr->rio_detail_list, &rio_vg_head);
-		//create linked list of expansion box				
-		else if (rio_detail_ptr->rio_type == 6 || rio_detail_ptr->rio_type == 7) 
-			list_add (&rio_detail_ptr->rio_detail_list, &rio_lo_head);
-		else 
-			// not in my concern
-			kfree (rio_detail_ptr);
-		offset += 15;
-	}
-	print_lo_info ();
-	print_vg_info ();
-	return 0;
-}
-
-/*
- * reorganizing linked list of chassis	 
- */
-static struct opt_rio *search_opt_vg (u8 chassis_num)
-{
-	struct opt_rio *ptr;
-	struct list_head *ptr1;
-	list_for_each (ptr1, &opt_vg_head) {
-		ptr = list_entry (ptr1, struct opt_rio, opt_rio_list);
-		if (ptr->chassis_num == chassis_num)
-			return ptr;
-	}		
-	return NULL;
-}
-
-static int __init combine_wpg_for_chassis (void)
-{
-	struct opt_rio *opt_rio_ptr = NULL;
-	struct rio_detail *rio_detail_ptr = NULL;
-	struct list_head *list_head_ptr = NULL;
-	
-	list_for_each (list_head_ptr, &rio_vg_head) {
-		rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list);
-		opt_rio_ptr = search_opt_vg (rio_detail_ptr->chassis_num);
-		if (!opt_rio_ptr) {
-			opt_rio_ptr = (struct opt_rio *) kmalloc (sizeof (struct opt_rio), GFP_KERNEL);
-			if (!opt_rio_ptr)
-				return -ENOMEM;
-			memset (opt_rio_ptr, 0, sizeof (struct opt_rio));
-			opt_rio_ptr->rio_type = rio_detail_ptr->rio_type;
-			opt_rio_ptr->chassis_num = rio_detail_ptr->chassis_num;
-			opt_rio_ptr->first_slot_num = rio_detail_ptr->first_slot_num;
-			opt_rio_ptr->middle_num = rio_detail_ptr->first_slot_num;
-			list_add (&opt_rio_ptr->opt_rio_list, &opt_vg_head);
-		} else {	
-			opt_rio_ptr->first_slot_num = min (opt_rio_ptr->first_slot_num, rio_detail_ptr->first_slot_num);
-			opt_rio_ptr->middle_num = max (opt_rio_ptr->middle_num, rio_detail_ptr->first_slot_num);
-		}	
-	}
-	print_opt_vg ();
-	return 0;	
-}	
-
-/*
- * reorgnizing linked list of expansion box	 
- */
-static struct opt_rio_lo *search_opt_lo (u8 chassis_num)
-{
-	struct opt_rio_lo *ptr;
-	struct list_head *ptr1;
-	list_for_each (ptr1, &opt_lo_head) {
-		ptr = list_entry (ptr1, struct opt_rio_lo, opt_rio_lo_list);
-		if (ptr->chassis_num == chassis_num)
-			return ptr;
-	}		
-	return NULL;
-}
-
-static int combine_wpg_for_expansion (void)
-{
-	struct opt_rio_lo *opt_rio_lo_ptr = NULL;
-	struct rio_detail *rio_detail_ptr = NULL;
-	struct list_head *list_head_ptr = NULL;
-	
-	list_for_each (list_head_ptr, &rio_lo_head) {
-		rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list);
-		opt_rio_lo_ptr = search_opt_lo (rio_detail_ptr->chassis_num);
-		if (!opt_rio_lo_ptr) {
-			opt_rio_lo_ptr = (struct opt_rio_lo *) kmalloc (sizeof (struct opt_rio_lo), GFP_KERNEL);
-			if (!opt_rio_lo_ptr)
-				return -ENOMEM;
-			memset (opt_rio_lo_ptr, 0, sizeof (struct opt_rio_lo));
-			opt_rio_lo_ptr->rio_type = rio_detail_ptr->rio_type;
-			opt_rio_lo_ptr->chassis_num = rio_detail_ptr->chassis_num;
-			opt_rio_lo_ptr->first_slot_num = rio_detail_ptr->first_slot_num;
-			opt_rio_lo_ptr->middle_num = rio_detail_ptr->first_slot_num;
-			opt_rio_lo_ptr->pack_count = 1;
-			
-			list_add (&opt_rio_lo_ptr->opt_rio_lo_list, &opt_lo_head);
-		} else {	
-			opt_rio_lo_ptr->first_slot_num = min (opt_rio_lo_ptr->first_slot_num, rio_detail_ptr->first_slot_num);
-			opt_rio_lo_ptr->middle_num = max (opt_rio_lo_ptr->middle_num, rio_detail_ptr->first_slot_num);
-			opt_rio_lo_ptr->pack_count = 2;
-		}	
-	}
-	return 0;	
-}
-	
-
-/* Since we don't know the max slot number per each chassis, hence go
- * through the list of all chassis to find out the range
- * Arguments: slot_num, 1st slot number of the chassis we think we are on, 
- * var (0 = chassis, 1 = expansion box) 
- */
-static int first_slot_num (u8 slot_num, u8 first_slot, u8 var)
-{
-	struct opt_rio *opt_vg_ptr = NULL;
-	struct opt_rio_lo *opt_lo_ptr = NULL;
-	struct list_head *ptr = NULL;
-	int rc = 0;
-
-	if (!var) {
-		list_for_each (ptr, &opt_vg_head) {
-			opt_vg_ptr = list_entry (ptr, struct opt_rio, opt_rio_list);
-			if ((first_slot < opt_vg_ptr->first_slot_num) && (slot_num >= opt_vg_ptr->first_slot_num)) { 
-				rc = -ENODEV;
-				break;
-			}
-		}
-	} else {
-		list_for_each (ptr, &opt_lo_head) {
-			opt_lo_ptr = list_entry (ptr, struct opt_rio_lo, opt_rio_lo_list);
-			if ((first_slot < opt_lo_ptr->first_slot_num) && (slot_num >= opt_lo_ptr->first_slot_num)) {
-				rc = -ENODEV;
-				break;
-			}
-		}
-	}
-	return rc;
-}
-
-static struct opt_rio_lo * find_rxe_num (u8 slot_num)
-{
-	struct opt_rio_lo *opt_lo_ptr;
-	struct list_head *ptr;
-
-	list_for_each (ptr, &opt_lo_head) {
-		opt_lo_ptr = list_entry (ptr, struct opt_rio_lo, opt_rio_lo_list);
-		//check to see if this slot_num belongs to expansion box
-		if ((slot_num >= opt_lo_ptr->first_slot_num) && (!first_slot_num (slot_num, opt_lo_ptr->first_slot_num, 1))) 
-			return opt_lo_ptr;
-	}
-	return NULL;
-}
-
-static struct opt_rio * find_chassis_num (u8 slot_num)
-{
-	struct opt_rio *opt_vg_ptr;
-	struct list_head *ptr;
-
-	list_for_each (ptr, &opt_vg_head) {
-		opt_vg_ptr = list_entry (ptr, struct opt_rio, opt_rio_list);
-		//check to see if this slot_num belongs to chassis 
-		if ((slot_num >= opt_vg_ptr->first_slot_num) && (!first_slot_num (slot_num, opt_vg_ptr->first_slot_num, 0))) 
-			return opt_vg_ptr;
-	}
-	return NULL;
-}
-
-/* This routine will find out how many slots are in the chassis, so that
- * the slot numbers for rxe100 would start from 1, and not from 7, or 6 etc
- */
-static u8 calculate_first_slot (u8 slot_num)
-{
-	u8 first_slot = 1;
-	struct list_head * list;
-	struct slot * slot_cur;
-	
-	list_for_each (list, &ibmphp_slot_head) {
-		slot_cur = list_entry (list, struct slot, ibm_slot_list);
-		if (slot_cur->ctrl) {
-			if ((slot_cur->ctrl->ctlr_type != 4) && (slot_cur->ctrl->ending_slot_num > first_slot) && (slot_num > slot_cur->ctrl->ending_slot_num)) 
-				first_slot = slot_cur->ctrl->ending_slot_num;
-		}
-	}			
-	return first_slot + 1;
-
-}
-static char *create_file_name (struct slot * slot_cur)
-{
-	struct opt_rio *opt_vg_ptr = NULL;
-	struct opt_rio_lo *opt_lo_ptr = NULL;
-	static char str[30];
-	int which = 0; /* rxe = 1, chassis = 0 */
-	u8 number = 1; /* either chassis or rxe # */
-	u8 first_slot = 1;
-	u8 slot_num;
-	u8 flag = 0;
-
-	if (!slot_cur) {
-		err ("Structure passed is empty \n");
-		return NULL;
-	}
-	
-	slot_num = slot_cur->number;
-
-	memset (str, 0, sizeof(str));
-	
-	if (rio_table_ptr) {
-		if (rio_table_ptr->ver_num == 3) {
-			opt_vg_ptr = find_chassis_num (slot_num);
-			opt_lo_ptr = find_rxe_num (slot_num);
-		}
-	}
-	if (opt_vg_ptr) {
-		if (opt_lo_ptr) {
-			if ((slot_num - opt_vg_ptr->first_slot_num) > (slot_num - opt_lo_ptr->first_slot_num)) {
-				number = opt_lo_ptr->chassis_num;
-				first_slot = opt_lo_ptr->first_slot_num;
-				which = 1; /* it is RXE */
-			} else {
-				first_slot = opt_vg_ptr->first_slot_num;
-				number = opt_vg_ptr->chassis_num;
-				which = 0;
-			}
-		} else {
-			first_slot = opt_vg_ptr->first_slot_num;
-			number = opt_vg_ptr->chassis_num;
-			which = 0;
-		}
-		++flag;
-	} else if (opt_lo_ptr) {
-		number = opt_lo_ptr->chassis_num;
-		first_slot = opt_lo_ptr->first_slot_num;
-		which = 1;
-		++flag;
-	} else if (rio_table_ptr) {
-		if (rio_table_ptr->ver_num == 3) {
-			/* if both NULL and we DO have correct RIO table in BIOS */
-			return NULL;
-		}
-	} 
-	if (!flag) {
-		if (slot_cur->ctrl->ctlr_type == 4) {
-			first_slot = calculate_first_slot (slot_num);
-			which = 1;
-		} else {
-			which = 0;
-		}
-	}
-
-	sprintf(str, "%s%dslot%d",
-		which == 0 ? "chassis" : "rxe",
-		number, slot_num - first_slot + 1);
-	return str;
-}
-
-static struct pci_driver ibmphp_driver;
-
-/*
- * map info (ctlr-id, slot count, slot#.. bus count, bus#, ctlr type...) of
- * each hpc from physical address to a list of hot plug controllers based on
- * hpc descriptors.
- */
-static int __init ebda_rsrc_controller (void)
-{
-	u16 addr, addr_slot, addr_bus;
-	u8 ctlr_id, temp, bus_index;
-	u16 ctlr, slot, bus;
-	u16 slot_num, bus_num, index;
-	struct hotplug_slot *hp_slot_ptr;
-	struct controller *hpc_ptr;
-	struct ebda_hpc_bus *bus_ptr;
-	struct ebda_hpc_slot *slot_ptr;
-	struct bus_info *bus_info_ptr1, *bus_info_ptr2;
-	int rc;
-	struct slot *tmp_slot;
-	struct list_head *list;
-
-	addr = hpc_list_ptr->phys_addr;
-	for (ctlr = 0; ctlr < hpc_list_ptr->num_ctlrs; ctlr++) {
-		bus_index = 1;
-		ctlr_id = readb (io_mem + addr);
-		addr += 1;
-		slot_num = readb (io_mem + addr);
-
-		addr += 1;
-		addr_slot = addr;	/* offset of slot structure */
-		addr += (slot_num * 4);
-
-		bus_num = readb (io_mem + addr);
-
-		addr += 1;
-		addr_bus = addr;	/* offset of bus */
-		addr += (bus_num * 9);	/* offset of ctlr_type */
-		temp = readb (io_mem + addr);
-
-		addr += 1;
-		/* init hpc structure */
-		hpc_ptr = alloc_ebda_hpc (slot_num, bus_num);
-		if (!hpc_ptr ) {
-			rc = -ENOMEM;
-			goto error_no_hpc;
-		}
-		hpc_ptr->ctlr_id = ctlr_id;
-		hpc_ptr->ctlr_relative_id = ctlr;
-		hpc_ptr->slot_count = slot_num;
-		hpc_ptr->bus_count = bus_num;
-		debug ("now enter ctlr data struture ---\n");
-		debug ("ctlr id: %x\n", ctlr_id);
-		debug ("ctlr_relative_id: %x\n", hpc_ptr->ctlr_relative_id);
-		debug ("count of slots controlled by this ctlr: %x\n", slot_num);
-		debug ("count of buses controlled by this ctlr: %x\n", bus_num);
-
-		/* init slot structure, fetch slot, bus, cap... */
-		slot_ptr = hpc_ptr->slots;
-		for (slot = 0; slot < slot_num; slot++) {
-			slot_ptr->slot_num = readb (io_mem + addr_slot);
-			slot_ptr->slot_bus_num = readb (io_mem + addr_slot + slot_num);
-			slot_ptr->ctl_index = readb (io_mem + addr_slot + 2*slot_num);
-			slot_ptr->slot_cap = readb (io_mem + addr_slot + 3*slot_num);
-
-			// create bus_info lined list --- if only one slot per bus: slot_min = slot_max 
-
-			bus_info_ptr2 = ibmphp_find_same_bus_num (slot_ptr->slot_bus_num);
-			if (!bus_info_ptr2) {
-				bus_info_ptr1 = (struct bus_info *) kmalloc (sizeof (struct bus_info), GFP_KERNEL);
-				if (!bus_info_ptr1) {
-					rc = -ENOMEM;
-					goto error_no_hp_slot;
-				}
-				memset (bus_info_ptr1, 0, sizeof (struct bus_info));
-				bus_info_ptr1->slot_min = slot_ptr->slot_num;
-				bus_info_ptr1->slot_max = slot_ptr->slot_num;
-				bus_info_ptr1->slot_count += 1;
-				bus_info_ptr1->busno = slot_ptr->slot_bus_num;
-				bus_info_ptr1->index = bus_index++;
-				bus_info_ptr1->current_speed = 0xff;
-				bus_info_ptr1->current_bus_mode = 0xff;
-				
-				bus_info_ptr1->controller_id = hpc_ptr->ctlr_id;
-				
-				list_add_tail (&bus_info_ptr1->bus_info_list, &bus_info_head);
-
-			} else {
-				bus_info_ptr2->slot_min = min (bus_info_ptr2->slot_min, slot_ptr->slot_num);
-				bus_info_ptr2->slot_max = max (bus_info_ptr2->slot_max, slot_ptr->slot_num);
-				bus_info_ptr2->slot_count += 1;
-
-			}
-
-			// end of creating the bus_info linked list
-
-			slot_ptr++;
-			addr_slot += 1;
-		}
-
-		/* init bus structure */
-		bus_ptr = hpc_ptr->buses;
-		for (bus = 0; bus < bus_num; bus++) {
-			bus_ptr->bus_num = readb (io_mem + addr_bus + bus);
-			bus_ptr->slots_at_33_conv = readb (io_mem + addr_bus + bus_num + 8 * bus);
-			bus_ptr->slots_at_66_conv = readb (io_mem + addr_bus + bus_num + 8 * bus + 1);
-
-			bus_ptr->slots_at_66_pcix = readb (io_mem + addr_bus + bus_num + 8 * bus + 2);
-
-			bus_ptr->slots_at_100_pcix = readb (io_mem + addr_bus + bus_num + 8 * bus + 3);
-
-			bus_ptr->slots_at_133_pcix = readb (io_mem + addr_bus + bus_num + 8 * bus + 4);
-
-			bus_info_ptr2 = ibmphp_find_same_bus_num (bus_ptr->bus_num);
-			if (bus_info_ptr2) {
-				bus_info_ptr2->slots_at_33_conv = bus_ptr->slots_at_33_conv;
-				bus_info_ptr2->slots_at_66_conv = bus_ptr->slots_at_66_conv;
-				bus_info_ptr2->slots_at_66_pcix = bus_ptr->slots_at_66_pcix;
-				bus_info_ptr2->slots_at_100_pcix = bus_ptr->slots_at_100_pcix;
-				bus_info_ptr2->slots_at_133_pcix = bus_ptr->slots_at_133_pcix; 
-			}
-			bus_ptr++;
-		}
-
-		hpc_ptr->ctlr_type = temp;
-
-		switch (hpc_ptr->ctlr_type) {
-			case 1:
-				hpc_ptr->u.pci_ctlr.bus = readb (io_mem + addr);
-				hpc_ptr->u.pci_ctlr.dev_fun = readb (io_mem + addr + 1);
-				hpc_ptr->irq = readb (io_mem + addr + 2);
-				addr += 3;
-				debug ("ctrl bus = %x, ctlr devfun = %x, irq = %x\n", 
-					hpc_ptr->u.pci_ctlr.bus,
-					hpc_ptr->u.pci_ctlr.dev_fun, hpc_ptr->irq);
-				break;
-
-			case 0:
-				hpc_ptr->u.isa_ctlr.io_start = readw (io_mem + addr);
-				hpc_ptr->u.isa_ctlr.io_end = readw (io_mem + addr + 2);
-				if (!request_region (hpc_ptr->u.isa_ctlr.io_start,
-						     (hpc_ptr->u.isa_ctlr.io_end - hpc_ptr->u.isa_ctlr.io_start + 1),
-						     "ibmphp")) {
-					rc = -ENODEV;
-					goto error_no_hp_slot;
-				}
-				hpc_ptr->irq = readb (io_mem + addr + 4);
-				addr += 5;
-				break;
-
-			case 2:
-			case 4:
-				hpc_ptr->u.wpeg_ctlr.wpegbbar = readl (io_mem + addr);
-				hpc_ptr->u.wpeg_ctlr.i2c_addr = readb (io_mem + addr + 4);
-				hpc_ptr->irq = readb (io_mem + addr + 5);
-				addr += 6;
-				break;
-			default:
-				rc = -ENODEV;
-				goto error_no_hp_slot;
-		}
-
-		//reorganize chassis' linked list
-		combine_wpg_for_chassis ();
-		combine_wpg_for_expansion ();
-		hpc_ptr->revision = 0xff;
-		hpc_ptr->options = 0xff;
-		hpc_ptr->starting_slot_num = hpc_ptr->slots[0].slot_num;
-		hpc_ptr->ending_slot_num = hpc_ptr->slots[slot_num-1].slot_num;
-
-		// register slots with hpc core as well as create linked list of ibm slot
-		for (index = 0; index < hpc_ptr->slot_count; index++) {
-
-			hp_slot_ptr = (struct hotplug_slot *) kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL);
-			if (!hp_slot_ptr) {
-				rc = -ENOMEM;
-				goto error_no_hp_slot;
-			}
-			memset (hp_slot_ptr, 0, sizeof (struct hotplug_slot));
-
-			hp_slot_ptr->info = (struct hotplug_slot_info *) kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
-			if (!hp_slot_ptr->info) {
-				rc = -ENOMEM;
-				goto error_no_hp_info;
-			}
-			memset (hp_slot_ptr->info, 0, sizeof (struct hotplug_slot_info));
-
-			hp_slot_ptr->name = (char *) kmalloc (30, GFP_KERNEL);
-			if (!hp_slot_ptr->name) {
-				rc = -ENOMEM;
-				goto error_no_hp_name;
-			}
-
-			tmp_slot = kmalloc (sizeof (struct slot), GFP_KERNEL);
-			if (!tmp_slot) {
-				rc = -ENOMEM;
-				goto error_no_slot;
-			}
-			memset (tmp_slot, 0, sizeof (*tmp_slot));
-
-			tmp_slot->flag = TRUE;
-
-			tmp_slot->capabilities = hpc_ptr->slots[index].slot_cap;
-			if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_133_MAX) == EBDA_SLOT_133_MAX)
-				tmp_slot->supported_speed =  3;
-			else if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_100_MAX) == EBDA_SLOT_100_MAX)
-				tmp_slot->supported_speed =  2;
-			else if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_66_MAX) == EBDA_SLOT_66_MAX)
-				tmp_slot->supported_speed =  1;
-				
-			if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_PCIX_CAP) == EBDA_SLOT_PCIX_CAP)
-				tmp_slot->supported_bus_mode = 1;
-			else
-				tmp_slot->supported_bus_mode = 0;
-
-
-			tmp_slot->bus = hpc_ptr->slots[index].slot_bus_num;
-
-			bus_info_ptr1 = ibmphp_find_same_bus_num (hpc_ptr->slots[index].slot_bus_num);
-			if (!bus_info_ptr1) {
-				rc = -ENODEV;
-				goto error;
-			}
-			tmp_slot->bus_on = bus_info_ptr1;
-			bus_info_ptr1 = NULL;
-			tmp_slot->ctrl = hpc_ptr;
-
-			tmp_slot->ctlr_index = hpc_ptr->slots[index].ctl_index;
-			tmp_slot->number = hpc_ptr->slots[index].slot_num;
-			tmp_slot->hotplug_slot = hp_slot_ptr;
-
-			hp_slot_ptr->private = tmp_slot;
-
-			rc = ibmphp_hpc_fillhpslotinfo (hp_slot_ptr);
-			if (rc)
-				goto error;
-
-			rc = ibmphp_init_devno ((struct slot **) &hp_slot_ptr->private);
-			if (rc)
-				goto error;
-			hp_slot_ptr->ops = &ibmphp_hotplug_slot_ops;
-
-			// end of registering ibm slot with hotplug core
-
-			list_add (& ((struct slot *)(hp_slot_ptr->private))->ibm_slot_list, &ibmphp_slot_head);
-		}
-
-		print_bus_info ();
-		list_add (&hpc_ptr->ebda_hpc_list, &ebda_hpc_head );
-
-	}			/* each hpc  */
-
-	list_for_each (list, &ibmphp_slot_head) {
-		tmp_slot = list_entry (list, struct slot, ibm_slot_list);
-
-		snprintf (tmp_slot->hotplug_slot->name, 30, "%s", create_file_name (tmp_slot));
-		pci_hp_register (tmp_slot->hotplug_slot);
-	}
-
-	print_ebda_hpc ();
-	print_ibm_slot ();
-	return 0;
-
-error:
-	kfree (hp_slot_ptr->private);
-error_no_slot:
-	kfree (hp_slot_ptr->name);
-error_no_hp_name:
-	kfree (hp_slot_ptr->info);
-error_no_hp_info:
-	kfree (hp_slot_ptr);
-error_no_hp_slot:
-	free_ebda_hpc (hpc_ptr);
-error_no_hpc:
-	iounmap (io_mem);
-	return rc;
-}
-
-/* 
- * map info (bus, devfun, start addr, end addr..) of i/o, memory,
- * pfm from the physical addr to a list of resource.
- */
-static int __init ebda_rsrc_rsrc (void)
-{
-	u16 addr;
-	short rsrc;
-	u8 type, rsrc_type;
-	struct ebda_pci_rsrc *rsrc_ptr;
-
-	addr = rsrc_list_ptr->phys_addr;
-	debug ("now entering rsrc land\n");
-	debug ("offset of rsrc: %x\n", rsrc_list_ptr->phys_addr);
-
-	for (rsrc = 0; rsrc < rsrc_list_ptr->num_entries; rsrc++) {
-		type = readb (io_mem + addr);
-
-		addr += 1;
-		rsrc_type = type & EBDA_RSRC_TYPE_MASK;
-
-		if (rsrc_type == EBDA_IO_RSRC_TYPE) {
-			rsrc_ptr = alloc_ebda_pci_rsrc ();
-			if (!rsrc_ptr) {
-				iounmap (io_mem);
-				return -ENOMEM;
-			}
-			rsrc_ptr->rsrc_type = type;
-
-			rsrc_ptr->bus_num = readb (io_mem + addr);
-			rsrc_ptr->dev_fun = readb (io_mem + addr + 1);
-			rsrc_ptr->start_addr = readw (io_mem + addr + 2);
-			rsrc_ptr->end_addr = readw (io_mem + addr + 4);
-			addr += 6;
-
-			debug ("rsrc from io type ----\n");
-			debug ("rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n",
-				rsrc_ptr->rsrc_type, rsrc_ptr->bus_num, rsrc_ptr->dev_fun, rsrc_ptr->start_addr, rsrc_ptr->end_addr);
-
-			list_add (&rsrc_ptr->ebda_pci_rsrc_list, &ibmphp_ebda_pci_rsrc_head);
-		}
-
-		if (rsrc_type == EBDA_MEM_RSRC_TYPE || rsrc_type == EBDA_PFM_RSRC_TYPE) {
-			rsrc_ptr = alloc_ebda_pci_rsrc ();
-			if (!rsrc_ptr ) {
-				iounmap (io_mem);
-				return -ENOMEM;
-			}
-			rsrc_ptr->rsrc_type = type;
-
-			rsrc_ptr->bus_num = readb (io_mem + addr);
-			rsrc_ptr->dev_fun = readb (io_mem + addr + 1);
-			rsrc_ptr->start_addr = readl (io_mem + addr + 2);
-			rsrc_ptr->end_addr = readl (io_mem + addr + 6);
-			addr += 10;
-
-			debug ("rsrc from mem or pfm ---\n");
-			debug ("rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n", 
-				rsrc_ptr->rsrc_type, rsrc_ptr->bus_num, rsrc_ptr->dev_fun, rsrc_ptr->start_addr, rsrc_ptr->end_addr);
-
-			list_add (&rsrc_ptr->ebda_pci_rsrc_list, &ibmphp_ebda_pci_rsrc_head);
-		}
-	}
-	kfree (rsrc_list_ptr);
-	rsrc_list_ptr = NULL;
-	print_ebda_pci_rsrc ();
-	return 0;
-}
-
-u16 ibmphp_get_total_controllers (void)
-{
-	return hpc_list_ptr->num_ctlrs;
-}
-
-struct slot *ibmphp_get_slot_from_physical_num (u8 physical_num)
-{
-	struct slot *slot;
-	struct list_head *list;
-
-	list_for_each (list, &ibmphp_slot_head) {
-		slot = list_entry (list, struct slot, ibm_slot_list);
-		if (slot->number == physical_num)
-			return slot;
-	}
-	return NULL;
-}
-
-/* To find:
- *	- the smallest slot number
- *	- the largest slot number
- *	- the total number of the slots based on each bus
- *	  (if only one slot per bus slot_min = slot_max )
- */
-struct bus_info *ibmphp_find_same_bus_num (u32 num)
-{
-	struct bus_info *ptr;
-	struct list_head  *ptr1;
-
-	list_for_each (ptr1, &bus_info_head) {
-		ptr = list_entry (ptr1, struct bus_info, bus_info_list); 
-		if (ptr->busno == num) 
-			 return ptr;
-	}
-	return NULL;
-}
-
-/*  Finding relative bus number, in order to map corresponding
- *  bus register
- */
-int ibmphp_get_bus_index (u8 num)
-{
-	struct bus_info *ptr;
-	struct list_head  *ptr1;
-
-	list_for_each (ptr1, &bus_info_head) {
-		ptr = list_entry (ptr1, struct bus_info, bus_info_list);
-		if (ptr->busno == num)  
-			return ptr->index;
-	}
-	return -ENODEV;
-}
-
-void ibmphp_free_bus_info_queue (void)
-{
-	struct bus_info *bus_info;
-	struct list_head *list;
-	struct list_head *next;
-
-	list_for_each_safe (list, next, &bus_info_head ) {
-		bus_info = list_entry (list, struct bus_info, bus_info_list);
-		kfree (bus_info);
-	}
-}
-
-void ibmphp_free_ebda_hpc_queue (void)
-{
-	struct controller *controller = NULL;
-	struct list_head *list;
-	struct list_head *next;
-	int pci_flag = 0;
-
-	list_for_each_safe (list, next, &ebda_hpc_head) {
-		controller = list_entry (list, struct controller, ebda_hpc_list);
-		if (controller->ctlr_type == 0)
-			release_region (controller->u.isa_ctlr.io_start, (controller->u.isa_ctlr.io_end - controller->u.isa_ctlr.io_start + 1));
-		else if ((controller->ctlr_type == 1) && (!pci_flag)) {
-			++pci_flag;
-			pci_unregister_driver (&ibmphp_driver);
-		}
-		free_ebda_hpc (controller);
-	}
-}
-
-void ibmphp_free_ebda_pci_rsrc_queue (void)
-{
-	struct ebda_pci_rsrc *resource;
-	struct list_head *list;
-	struct list_head *next;
-
-	list_for_each_safe (list, next, &ibmphp_ebda_pci_rsrc_head) {
-		resource = list_entry (list, struct ebda_pci_rsrc, ebda_pci_rsrc_list);
-		kfree (resource);
-		resource = NULL;
-	}
-}
-
-static struct pci_device_id id_table[] __devinitdata = {
-	{
-		.vendor		= PCI_VENDOR_ID_IBM,
-		.device		= HPC_DEVICE_ID,
-		.subvendor	= PCI_VENDOR_ID_IBM,
-		.subdevice	= HPC_SUBSYSTEM_ID,
-		.class		= ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00),
-	}, {}
-};		
-
-MODULE_DEVICE_TABLE(pci, id_table);
-
-static int ibmphp_probe (struct pci_dev *, const struct pci_device_id *);
-static struct pci_driver ibmphp_driver = {
-	.name		= "ibmphp",
-	.id_table	= id_table,
-	.probe		= ibmphp_probe,
-};
-
-int ibmphp_register_pci (void)
-{
-	struct controller *ctrl;
-	struct list_head *tmp;
-	int rc = 0;
-
-	list_for_each (tmp, &ebda_hpc_head) {
-		ctrl = list_entry (tmp, struct controller, ebda_hpc_list);
-		if (ctrl->ctlr_type == 1) {
-			rc = pci_module_init (&ibmphp_driver);
-			break;
-		}
-	}
-	return rc;
-}
-static int ibmphp_probe (struct pci_dev * dev, const struct pci_device_id *ids)
-{
-	struct controller *ctrl;
-	struct list_head *tmp;
-
-	debug ("inside ibmphp_probe \n");
-	
-	list_for_each (tmp, &ebda_hpc_head) {
-		ctrl = list_entry (tmp, struct controller, ebda_hpc_list);
-		if (ctrl->ctlr_type == 1) {
-			if ((dev->devfn == ctrl->u.pci_ctlr.dev_fun) && (dev->bus->number == ctrl->u.pci_ctlr.bus)) {
-				ctrl->ctrl_dev = dev;
-				debug ("found device!!! \n");
-				debug ("dev->device = %x, dev->subsystem_device = %x\n", dev->device, dev->subsystem_device);
-				return 0;
-			}
-		}
-	}
-	return -ENODEV;
-}
-
diff -Nru a/drivers/hotplug/ibmphp_hpc.c b/drivers/hotplug/ibmphp_hpc.c
--- a/drivers/hotplug/ibmphp_hpc.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1228 +0,0 @@
-/*
- * IBM Hot Plug Controller Driver
- *
- * Written By: Jyoti Shah, IBM Corporation
- *
- * Copyright (c) 2001-2002 IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <gregkh@us.ibm.com>
- *                  <jshah@us.ibm.com>
- *
- */
-
-#include <linux/wait.h>
-#include <linux/time.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include "ibmphp.h"
-
-static int to_debug = FALSE;
-#define debug_polling(fmt, arg...)	do { if (to_debug) debug (fmt, arg); } while (0)
-
-//----------------------------------------------------------------------------
-// timeout values
-//----------------------------------------------------------------------------
-#define CMD_COMPLETE_TOUT_SEC	60	// give HPC 60 sec to finish cmd
-#define HPC_CTLR_WORKING_TOUT	60	// give HPC 60 sec to finish cmd
-#define HPC_GETACCESS_TIMEOUT	60	// seconds
-#define POLL_INTERVAL_SEC	2	// poll HPC every 2 seconds
-#define POLL_LATCH_CNT		5	// poll latch 5 times, then poll slots
-
-//----------------------------------------------------------------------------
-// Winnipeg Architected Register Offsets
-//----------------------------------------------------------------------------
-#define WPG_I2CMBUFL_OFFSET	0x08	// I2C Message Buffer Low
-#define WPG_I2CMOSUP_OFFSET	0x10	// I2C Master Operation Setup Reg
-#define WPG_I2CMCNTL_OFFSET	0x20	// I2C Master Control Register
-#define WPG_I2CPARM_OFFSET	0x40	// I2C Parameter Register
-#define WPG_I2CSTAT_OFFSET	0x70	// I2C Status Register
-
-//----------------------------------------------------------------------------
-// Winnipeg Store Type commands (Add this commands to the register offset)
-//----------------------------------------------------------------------------
-#define WPG_I2C_AND		0x1000	// I2C AND operation
-#define WPG_I2C_OR		0x2000	// I2C OR operation
-
-//----------------------------------------------------------------------------
-// Command set for I2C Master Operation Setup Regisetr
-//----------------------------------------------------------------------------
-#define WPG_READATADDR_MASK	0x00010000	// read,bytes,I2C shifted,index
-#define WPG_WRITEATADDR_MASK	0x40010000	// write,bytes,I2C shifted,index
-#define WPG_READDIRECT_MASK	0x10010000
-#define WPG_WRITEDIRECT_MASK	0x60010000
-
-
-//----------------------------------------------------------------------------
-// bit masks for I2C Master Control Register
-//----------------------------------------------------------------------------
-#define WPG_I2CMCNTL_STARTOP_MASK	0x00000002	// Start the Operation
-
-//----------------------------------------------------------------------------
-//
-//----------------------------------------------------------------------------
-#define WPG_I2C_IOREMAP_SIZE	0x2044	// size of linear address interval
-
-//----------------------------------------------------------------------------
-// command index
-//----------------------------------------------------------------------------
-#define WPG_1ST_SLOT_INDEX	0x01	// index - 1st slot for ctlr
-#define WPG_CTLR_INDEX		0x0F	// index - ctlr
-#define WPG_1ST_EXTSLOT_INDEX	0x10	// index - 1st ext slot for ctlr
-#define WPG_1ST_BUS_INDEX	0x1F	// index - 1st bus for ctlr
-
-//----------------------------------------------------------------------------
-// macro utilities
-//----------------------------------------------------------------------------
-// if bits 20,22,25,26,27,29,30 are OFF return TRUE
-#define HPC_I2CSTATUS_CHECK(s)	((u8)((s & 0x00000A76) ? FALSE : TRUE))
-
-//----------------------------------------------------------------------------
-// global variables
-//----------------------------------------------------------------------------
-static int ibmphp_shutdown;
-static int tid_poll;
-static struct semaphore sem_hpcaccess;	// lock access to HPC
-static struct semaphore semOperations;	// lock all operations and
-					// access to data structures
-static struct semaphore sem_exit;	// make sure polling thread goes away
-//----------------------------------------------------------------------------
-// local function prototypes
-//----------------------------------------------------------------------------
-static u8 i2c_ctrl_read (struct controller *, void *, u8);
-static u8 i2c_ctrl_write (struct controller *, void *, u8, u8);
-static u8 hpc_writecmdtoindex (u8, u8);
-static u8 hpc_readcmdtoindex (u8, u8);
-static void get_hpc_access (void);
-static void free_hpc_access (void);
-static void poll_hpc (void);
-static int update_slot (struct slot *, u8);
-static int process_changeinstatus (struct slot *, struct slot *);
-static int process_changeinlatch (u8, u8, struct controller *);
-static int hpc_poll_thread (void *);
-static int hpc_wait_ctlr_notworking (int, struct controller *, void *, u8 *);
-//----------------------------------------------------------------------------
-
-
-/*----------------------------------------------------------------------
-* Name:    ibmphp_hpc_initvars
-*
-* Action:  initialize semaphores and variables
-*---------------------------------------------------------------------*/
-void __init ibmphp_hpc_initvars (void)
-{
-	debug ("%s - Entry\n", __FUNCTION__);
-
-	init_MUTEX (&sem_hpcaccess);
-	init_MUTEX (&semOperations);
-	init_MUTEX_LOCKED (&sem_exit);
-	to_debug = FALSE;
-	ibmphp_shutdown = FALSE;
-	tid_poll = 0;
-
-	debug ("%s - Exit\n", __FUNCTION__);
-}
-
-/*----------------------------------------------------------------------
-* Name:    i2c_ctrl_read
-*
-* Action:  read from HPC over I2C
-*
-*---------------------------------------------------------------------*/
-static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void *WPGBbar, u8 index)
-{
-	u8 status;
-	int i;
-	void *wpg_addr;		// base addr + offset
-	ulong wpg_data,		// data to/from WPG LOHI format
-	ultemp, data;		// actual data HILO format
-
-
-	debug_polling ("%s - Entry WPGBbar[%lx] index[%x] \n", __FUNCTION__, (ulong) WPGBbar, index);
-
-	//--------------------------------------------------------------------
-	// READ - step 1
-	// read at address, byte length, I2C address (shifted), index
-	// or read direct, byte length, index
-	if (ctlr_ptr->ctlr_type == 0x02) {
-		data = WPG_READATADDR_MASK;
-		// fill in I2C address
-		ultemp = (ulong) ctlr_ptr->u.wpeg_ctlr.i2c_addr;
-		ultemp = ultemp >> 1;
-		data |= (ultemp << 8);
-
-		// fill in index
-		data |= (ulong) index;
-	} else if (ctlr_ptr->ctlr_type == 0x04) {
-		data = WPG_READDIRECT_MASK;
-
-		// fill in index
-		ultemp = (ulong) index;
-		ultemp = ultemp << 8;
-		data |= ultemp;
-	} else {
-		err ("this controller type is not supported \n");
-		return HPC_ERROR;
-	}
-
-	wpg_data = swab32 (data);	// swap data before writing
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMOSUP_OFFSET;
-	writel (wpg_data, wpg_addr);
-
-	//--------------------------------------------------------------------
-	// READ - step 2 : clear the message buffer
-	data = 0x00000000;
-	wpg_data = swab32 (data);
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMBUFL_OFFSET;
-	writel (wpg_data, wpg_addr);
-
-	//--------------------------------------------------------------------
-	// READ - step 3 : issue start operation, I2C master control bit 30:ON
-	//                 2020 : [20] OR operation at [20] offset 0x20
-	data = WPG_I2CMCNTL_STARTOP_MASK;
-	wpg_data = swab32 (data);
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET + (ulong) WPG_I2C_OR;
-	writel (wpg_data, wpg_addr);
-
-	//--------------------------------------------------------------------
-	// READ - step 4 : wait until start operation bit clears
-	i = CMD_COMPLETE_TOUT_SEC;
-	while (i) {
-		long_delay (1 * HZ / 100);
-		(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET;
-		wpg_data = readl (wpg_addr);
-		data = swab32 (wpg_data);
-		if (!(data & WPG_I2CMCNTL_STARTOP_MASK))
-			break;
-		i--;
-	}
-	if (i == 0) {
-		debug ("%s - Error : WPG timeout\n", __FUNCTION__);
-		return HPC_ERROR;
-	}
-	//--------------------------------------------------------------------
-	// READ - step 5 : read I2C status register
-	i = CMD_COMPLETE_TOUT_SEC;
-	while (i) {
-		long_delay (1 * HZ / 100);
-		(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CSTAT_OFFSET;
-		wpg_data = readl (wpg_addr);
-		data = swab32 (wpg_data);
-		if (HPC_I2CSTATUS_CHECK (data))
-			break;
-		i--;
-	}
-	if (i == 0) {
-		debug ("ctrl_read - Exit Error:I2C timeout\n");
-		return HPC_ERROR;
-	}
-
-	//--------------------------------------------------------------------
-	// READ - step 6 : get DATA
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMBUFL_OFFSET;
-	wpg_data = readl (wpg_addr);
-	data = swab32 (wpg_data);
-
-	status = (u8) data;
-
-	debug_polling ("%s - Exit index[%x] status[%x]\n", __FUNCTION__, index, status);
-
-	return (status);
-}
-
-/*----------------------------------------------------------------------
-* Name:    i2c_ctrl_write
-*
-* Action:  write to HPC over I2C
-*
-* Return   0 or error codes
-*---------------------------------------------------------------------*/
-static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void *WPGBbar, u8 index, u8 cmd)
-{
-	u8 rc;
-	void *wpg_addr;		// base addr + offset
-	ulong wpg_data,		// data to/from WPG LOHI format 
-	ultemp, data;		// actual data HILO format
-	int i;
-
-
-	debug_polling ("%s - Entry WPGBbar[%lx] index[%x] cmd[%x]\n", __FUNCTION__, (ulong) WPGBbar, index, cmd);
-
-	rc = 0;
-	//--------------------------------------------------------------------
-	// WRITE - step 1
-	// write at address, byte length, I2C address (shifted), index
-	// or write direct, byte length, index
-	data = 0x00000000;
-
-	if (ctlr_ptr->ctlr_type == 0x02) {
-		data = WPG_WRITEATADDR_MASK;
-		// fill in I2C address
-		ultemp = (ulong) ctlr_ptr->u.wpeg_ctlr.i2c_addr;
-		ultemp = ultemp >> 1;
-		data |= (ultemp << 8);
-
-		// fill in index
-		data |= (ulong) index;
-	} else if (ctlr_ptr->ctlr_type == 0x04) {
-		data = WPG_WRITEDIRECT_MASK;
-
-		// fill in index
-		ultemp = (ulong) index;
-		ultemp = ultemp << 8;
-		data |= ultemp;
-	} else {
-		err ("this controller type is not supported \n");
-		return HPC_ERROR;
-	}
-
-	wpg_data = swab32 (data);	// swap data before writing
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMOSUP_OFFSET;
-	writel (wpg_data, wpg_addr);
-
-	//--------------------------------------------------------------------
-	// WRITE - step 2 : clear the message buffer
-	data = 0x00000000 | (ulong) cmd;
-	wpg_data = swab32 (data);
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMBUFL_OFFSET;
-	writel (wpg_data, wpg_addr);
-
-	//--------------------------------------------------------------------
-	// WRITE - step 3 : issue start operation,I2C master control bit 30:ON
-	//                 2020 : [20] OR operation at [20] offset 0x20
-	data = WPG_I2CMCNTL_STARTOP_MASK;
-	wpg_data = swab32 (data);
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET + (ulong) WPG_I2C_OR;
-	writel (wpg_data, wpg_addr);
-
-	//--------------------------------------------------------------------
-	// WRITE - step 4 : wait until start operation bit clears
-	i = CMD_COMPLETE_TOUT_SEC;
-	while (i) {
-		long_delay (1 * HZ / 100);
-		(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET;
-		wpg_data = readl (wpg_addr);
-		data = swab32 (wpg_data);
-		if (!(data & WPG_I2CMCNTL_STARTOP_MASK))
-			break;
-		i--;
-	}
-	if (i == 0) {
-		debug ("%s - Exit Error:WPG timeout\n", __FUNCTION__);
-		rc = HPC_ERROR;
-	}
-
-	//--------------------------------------------------------------------
-	// WRITE - step 5 : read I2C status register
-	i = CMD_COMPLETE_TOUT_SEC;
-	while (i) {
-		long_delay (1 * HZ / 100);
-		(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CSTAT_OFFSET;
-		wpg_data = readl (wpg_addr);
-		data = swab32 (wpg_data);
-		if (HPC_I2CSTATUS_CHECK (data))
-			break;
-		i--;
-	}
-	if (i == 0) {
-		debug ("ctrl_read - Error : I2C timeout\n");
-		rc = HPC_ERROR;
-	}
-
-	debug_polling ("%s Exit rc[%x]\n", __FUNCTION__, rc);
-	return (rc);
-}
-
-//------------------------------------------------------------
-//  Read from ISA type HPC 
-//------------------------------------------------------------
-static u8 isa_ctrl_read (struct controller *ctlr_ptr, u8 offset)
-{
-	u16 start_address;
-	u16 end_address;
-	u8 data;
-
-	start_address = ctlr_ptr->u.isa_ctlr.io_start;
-	end_address = ctlr_ptr->u.isa_ctlr.io_end;
-	data = inb (start_address + offset);
-	return data;
-}
-
-//--------------------------------------------------------------
-// Write to ISA type HPC
-//--------------------------------------------------------------
-static void isa_ctrl_write (struct controller *ctlr_ptr, u8 offset, u8 data)
-{
-	u16 start_address;
-	u16 port_address;
-	
-	start_address = ctlr_ptr->u.isa_ctlr.io_start;
-	port_address = start_address + (u16) offset;
-	outb (data, port_address);
-}
-
-static u8 pci_ctrl_read (struct controller *ctrl, u8 offset)
-{
-	u8 data = 0x00;
-	debug ("inside pci_ctrl_read\n");
-	if (ctrl->ctrl_dev)
-		pci_read_config_byte (ctrl->ctrl_dev, HPC_PCI_OFFSET + offset, &data);
-	return data;
-}
-
-static u8 pci_ctrl_write (struct controller *ctrl, u8 offset, u8 data)
-{
-	u8 rc = -ENODEV;
-	debug ("inside pci_ctrl_write\n");
-	if (ctrl->ctrl_dev) {
-		pci_write_config_byte (ctrl->ctrl_dev, HPC_PCI_OFFSET + offset, data);
-		rc = 0;
-	}
-	return rc;
-}
-
-static u8 ctrl_read (struct controller *ctlr, void *base, u8 offset)
-{
-	u8 rc;
-	switch (ctlr->ctlr_type) {
-	case 0:
-		rc = isa_ctrl_read (ctlr, offset);
-		break;
-	case 1:
-		rc = pci_ctrl_read (ctlr, offset);
-		break;
-	case 2:
-	case 4:
-		rc = i2c_ctrl_read (ctlr, base, offset);
-		break;
-	default:
-		return -ENODEV;
-	}
-	return rc;
-}
-
-static u8 ctrl_write (struct controller *ctlr, void *base, u8 offset, u8 data)
-{
-	u8 rc = 0;
-	switch (ctlr->ctlr_type) {
-	case 0:
-		isa_ctrl_write(ctlr, offset, data);
-		break;
-	case 1:
-		rc = pci_ctrl_write (ctlr, offset, data);
-		break;
-	case 2:
-	case 4:
-		rc = i2c_ctrl_write(ctlr, base, offset, data);
-		break;
-	default:
-		return -ENODEV;
-	}
-	return rc;
-}
-/*----------------------------------------------------------------------
-* Name:    hpc_writecmdtoindex()
-*
-* Action:  convert a write command to proper index within a controller
-*
-* Return   index, HPC_ERROR
-*---------------------------------------------------------------------*/
-static u8 hpc_writecmdtoindex (u8 cmd, u8 index)
-{
-	u8 rc;
-
-	switch (cmd) {
-	case HPC_CTLR_ENABLEIRQ:	// 0x00.N.15
-	case HPC_CTLR_CLEARIRQ:	// 0x06.N.15
-	case HPC_CTLR_RESET:	// 0x07.N.15
-	case HPC_CTLR_IRQSTEER:	// 0x08.N.15
-	case HPC_CTLR_DISABLEIRQ:	// 0x01.N.15
-	case HPC_ALLSLOT_ON:	// 0x11.N.15
-	case HPC_ALLSLOT_OFF:	// 0x12.N.15
-		rc = 0x0F;
-		break;
-
-	case HPC_SLOT_OFF:	// 0x02.Y.0-14
-	case HPC_SLOT_ON:	// 0x03.Y.0-14
-	case HPC_SLOT_ATTNOFF:	// 0x04.N.0-14
-	case HPC_SLOT_ATTNON:	// 0x05.N.0-14
-	case HPC_SLOT_BLINKLED:	// 0x13.N.0-14
-		rc = index;
-		break;
-
-	case HPC_BUS_33CONVMODE:
-	case HPC_BUS_66CONVMODE:
-	case HPC_BUS_66PCIXMODE:
-	case HPC_BUS_100PCIXMODE:
-	case HPC_BUS_133PCIXMODE:
-		rc = index + WPG_1ST_BUS_INDEX - 1;
-		break;
-
-	default:
-		err ("hpc_writecmdtoindex - Error invalid cmd[%x]\n", cmd);
-		rc = HPC_ERROR;
-	}
-
-	return rc;
-}
-
-/*----------------------------------------------------------------------
-* Name:    hpc_readcmdtoindex()
-*
-* Action:  convert a read command to proper index within a controller
-*
-* Return   index, HPC_ERROR
-*---------------------------------------------------------------------*/
-static u8 hpc_readcmdtoindex (u8 cmd, u8 index)
-{
-	u8 rc;
-
-	switch (cmd) {
-	case READ_CTLRSTATUS:
-		rc = 0x0F;
-		break;
-	case READ_SLOTSTATUS:
-	case READ_ALLSTAT:
-		rc = index;
-		break;
-	case READ_EXTSLOTSTATUS:
-		rc = index + WPG_1ST_EXTSLOT_INDEX;
-		break;
-	case READ_BUSSTATUS:
-		rc = index + WPG_1ST_BUS_INDEX - 1;
-		break;
-	case READ_SLOTLATCHLOWREG:
-		rc = 0x28;
-		break;
-	case READ_REVLEVEL:
-		rc = 0x25;
-		break;
-	case READ_HPCOPTIONS:
-		rc = 0x27;
-		break;
-	default:
-		rc = HPC_ERROR;
-	}
-	return rc;
-}
-
-/*----------------------------------------------------------------------
-* Name:    HPCreadslot()
-*
-* Action:  issue a READ command to HPC
-*
-* Input:   pslot   - can not be NULL for READ_ALLSTAT
-*          pstatus - can be NULL for READ_ALLSTAT
-*
-* Return   0 or error codes
-*---------------------------------------------------------------------*/
-int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)
-{
-	void *wpg_bbar = NULL;
-	struct controller *ctlr_ptr;
-	struct list_head *pslotlist;
-	u8 index, status;
-	int rc = 0;
-	int busindex;
-
-	debug_polling ("%s - Entry pslot[%lx] cmd[%x] pstatus[%lx]\n", __FUNCTION__, (ulong) pslot, cmd, (ulong) pstatus);
-
-	if ((pslot == NULL)
-	    || ((pstatus == NULL) && (cmd != READ_ALLSTAT) && (cmd != READ_BUSSTATUS))) {
-		rc = -EINVAL;
-		err ("%s - Error invalid pointer, rc[%d]\n", __FUNCTION__, rc);
-		return rc;
-	}
-
-	if (cmd == READ_BUSSTATUS) {
-		busindex = ibmphp_get_bus_index (pslot->bus);
-		if (busindex < 0) {
-			rc = -EINVAL;
-			err ("%s - Exit Error:invalid bus, rc[%d]\n", __FUNCTION__, rc);
-			return rc;
-		} else
-			index = (u8) busindex;
-	} else
-		index = pslot->ctlr_index;
-
-	index = hpc_readcmdtoindex (cmd, index);
-
-	if (index == HPC_ERROR) {
-		rc = -EINVAL;
-		err ("%s - Exit Error:invalid index, rc[%d]\n", __FUNCTION__, rc);
-		return rc;
-	}
-
-	ctlr_ptr = pslot->ctrl;
-
-	get_hpc_access ();
-
-	//--------------------------------------------------------------------
-	// map physical address to logical address
-	//--------------------------------------------------------------------
-	if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4))
-		wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE);
-
-	//--------------------------------------------------------------------
-	// check controller status before reading
-	//--------------------------------------------------------------------
-	rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, &status);
-	if (!rc) {
-		switch (cmd) {
-		case READ_ALLSTAT:
-			// update the slot structure
-			pslot->ctrl->status = status;
-			pslot->status = ctrl_read (ctlr_ptr, wpg_bbar, index);
-			rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar,
-						       &status);
-			if (!rc)
-				pslot->ext_status = ctrl_read (ctlr_ptr, wpg_bbar, index + WPG_1ST_EXTSLOT_INDEX);
-
-			break;
-
-		case READ_SLOTSTATUS:
-			// DO NOT update the slot structure
-			*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
-			break;
-
-		case READ_EXTSLOTSTATUS:
-			// DO NOT update the slot structure
-			*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
-			break;
-
-		case READ_CTLRSTATUS:
-			// DO NOT update the slot structure
-			*pstatus = status;
-			break;
-
-		case READ_BUSSTATUS:
-			pslot->busstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
-			break;
-		case READ_REVLEVEL:
-			*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
-			break;
-		case READ_HPCOPTIONS:
-			*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
-			break;
-		case READ_SLOTLATCHLOWREG:
-			// DO NOT update the slot structure
-			*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
-			break;
-
-			// Not used
-		case READ_ALLSLOT:
-			list_for_each (pslotlist, &ibmphp_slot_head) {
-				pslot = list_entry (pslotlist, struct slot, ibm_slot_list);
-				index = pslot->ctlr_index;
-				rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr,
-								wpg_bbar, &status);
-				if (!rc) {
-					pslot->status = ctrl_read (ctlr_ptr, wpg_bbar, index);
-					rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT,
-									ctlr_ptr, wpg_bbar, &status);
-					if (!rc)
-						pslot->ext_status =
-						    ctrl_read (ctlr_ptr, wpg_bbar,
-								index + WPG_1ST_EXTSLOT_INDEX);
-				} else {
-					err ("%s - Error ctrl_read failed\n", __FUNCTION__);
-					rc = -EINVAL;
-					break;
-				}
-			}
-			break;
-		default:
-			rc = -EINVAL;
-			break;
-		}
-	}
-	//--------------------------------------------------------------------
-	// cleanup
-	//--------------------------------------------------------------------
-	
-	// remove physical to logical address mapping
-	if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4))
-		iounmap (wpg_bbar);	
-	
-	free_hpc_access ();
-
-	debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
-	return rc;
-}
-
-/*----------------------------------------------------------------------
-* Name:    ibmphp_hpc_writeslot()
-*
-* Action: issue a WRITE command to HPC
-*---------------------------------------------------------------------*/
-int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
-{
-	void *wpg_bbar = NULL;
-	struct controller *ctlr_ptr;
-	u8 index, status;
-	int busindex;
-	u8 done;
-	int rc = 0;
-	int timeout;
-
-	debug_polling ("%s - Entry pslot[%lx] cmd[%x]\n", __FUNCTION__, (ulong) pslot, cmd);
-	if (pslot == NULL) {
-		rc = -EINVAL;
-		err ("%s - Error Exit rc[%d]\n", __FUNCTION__, rc);
-		return rc;
-	}
-
-	if ((cmd == HPC_BUS_33CONVMODE) || (cmd == HPC_BUS_66CONVMODE) ||
-		(cmd == HPC_BUS_66PCIXMODE) || (cmd == HPC_BUS_100PCIXMODE) ||
-		(cmd == HPC_BUS_133PCIXMODE)) {
-		busindex = ibmphp_get_bus_index (pslot->bus);
-		if (busindex < 0) {
-			rc = -EINVAL;
-			err ("%s - Exit Error:invalid bus, rc[%d]\n", __FUNCTION__, rc);
-			return rc;
-		} else
-			index = (u8) busindex;
-	} else
-		index = pslot->ctlr_index;
-
-	index = hpc_writecmdtoindex (cmd, index);
-
-	if (index == HPC_ERROR) {
-		rc = -EINVAL;
-		err ("%s - Error Exit rc[%d]\n", __FUNCTION__, rc);
-		return rc;
-	}
-
-	ctlr_ptr = pslot->ctrl;
-
-	get_hpc_access ();
-
-	//--------------------------------------------------------------------
-	// map physical address to logical address
-	//--------------------------------------------------------------------
-	if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) {
-		wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE);
-
-		debug ("%s - ctlr id[%x] physical[%lx] logical[%lx] i2c[%x]\n", __FUNCTION__,
-		ctlr_ptr->ctlr_id, (ulong) (ctlr_ptr->u.wpeg_ctlr.wpegbbar), (ulong) wpg_bbar,
-		ctlr_ptr->u.wpeg_ctlr.i2c_addr);
-	}
-	//--------------------------------------------------------------------
-	// check controller status before writing
-	//--------------------------------------------------------------------
-	rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, &status);
-	if (!rc) {
-
-		ctrl_write (ctlr_ptr, wpg_bbar, index, cmd);
-
-		//--------------------------------------------------------------------
-		// check controller is still not working on the command
-		//--------------------------------------------------------------------
-		timeout = CMD_COMPLETE_TOUT_SEC;
-		done = FALSE;
-		while (!done) {
-			rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar,
-							&status);
-			if (!rc) {
-				if (NEEDTOCHECK_CMDSTATUS (cmd)) {
-					if (CTLR_FINISHED (status) == HPC_CTLR_FINISHED_YES)
-						done = TRUE;
-				} else
-					done = TRUE;
-			}
-			if (!done) {
-				long_delay (1 * HZ);
-				if (timeout < 1) {
-					done = TRUE;
-					err ("%s - Error command complete timeout\n", __FUNCTION__);
-					rc = -EFAULT;
-				} else
-					timeout--;
-			}
-		}
-		ctlr_ptr->status = status;
-	}
-	// cleanup
-
-	// remove physical to logical address mapping
-	if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4))
-		iounmap (wpg_bbar);	
-	free_hpc_access ();
-
-	debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
-	return rc;
-}
-
-/*----------------------------------------------------------------------
-* Name:    get_hpc_access()
-*
-* Action: make sure only one process can access HPC at one time
-*---------------------------------------------------------------------*/
-static void get_hpc_access (void)
-{
-	down (&sem_hpcaccess);
-}
-
-/*----------------------------------------------------------------------
-* Name:    free_hpc_access()
-*---------------------------------------------------------------------*/
-void free_hpc_access (void)
-{
-	up (&sem_hpcaccess);
-}
-
-/*----------------------------------------------------------------------
-* Name:    ibmphp_lock_operations()
-*
-* Action: make sure only one process can change the data structure
-*---------------------------------------------------------------------*/
-void ibmphp_lock_operations (void)
-{
-	down (&semOperations);
-	to_debug = TRUE;
-}
-
-/*----------------------------------------------------------------------
-* Name:    ibmphp_unlock_operations()
-*---------------------------------------------------------------------*/
-void ibmphp_unlock_operations (void)
-{
-	debug ("%s - Entry\n", __FUNCTION__);
-	up (&semOperations);
-	to_debug = FALSE;
-	debug ("%s - Exit\n", __FUNCTION__);
-}
-
-/*----------------------------------------------------------------------
-* Name:    poll_hpc()
-*---------------------------------------------------------------------*/
-#define POLL_LATCH_REGISTER	0
-#define POLL_SLOTS		1
-#define POLL_SLEEP		2
-static void poll_hpc (void)
-{
-	struct slot myslot;
-	struct slot *pslot = NULL;
-	struct list_head *pslotlist;
-	int rc;
-	int poll_state = POLL_LATCH_REGISTER;
-	u8 oldlatchlow = 0x00;
-	u8 curlatchlow = 0x00;
-	int poll_count = 0;
-	u8 ctrl_count = 0x00;
-
-	debug ("%s - Entry\n", __FUNCTION__);
-
-	while (!ibmphp_shutdown) {
-		if (ibmphp_shutdown) 
-			break;
-		
-		/* try to get the lock to do some kind of harware access */
-		down (&semOperations);
-
-		switch (poll_state) {
-		case POLL_LATCH_REGISTER: 
-			oldlatchlow = curlatchlow;
-			ctrl_count = 0x00;
-			list_for_each (pslotlist, &ibmphp_slot_head) {
-				if (ctrl_count >= ibmphp_get_total_controllers())
-					break;
-				pslot = list_entry (pslotlist, struct slot, ibm_slot_list);
-				if (pslot->ctrl->ctlr_relative_id == ctrl_count) {
-					ctrl_count++;
-					if (READ_SLOT_LATCH (pslot->ctrl)) {
-						rc = ibmphp_hpc_readslot (pslot,
-									  READ_SLOTLATCHLOWREG,
-									  &curlatchlow);
-						if (oldlatchlow != curlatchlow)
-							process_changeinlatch (oldlatchlow,
-									       curlatchlow,
-									       pslot->ctrl);
-					}
-				}
-			}
-			++poll_count;
-			poll_state = POLL_SLEEP;
-			break;
-		case POLL_SLOTS:
-			list_for_each (pslotlist, &ibmphp_slot_head) {
-				pslot = list_entry (pslotlist, struct slot, ibm_slot_list);
-				// make a copy of the old status
-				memcpy ((void *) &myslot, (void *) pslot,
-					sizeof (struct slot));
-				rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL);
-				if ((myslot.status != pslot->status)
-				    || (myslot.ext_status != pslot->ext_status))
-					process_changeinstatus (pslot, &myslot);
-			}
-			ctrl_count = 0x00;
-			list_for_each (pslotlist, &ibmphp_slot_head) {
-				if (ctrl_count >= ibmphp_get_total_controllers())
-					break;
-				pslot = list_entry (pslotlist, struct slot, ibm_slot_list);
-				if (pslot->ctrl->ctlr_relative_id == ctrl_count) {
-					ctrl_count++;
-					if (READ_SLOT_LATCH (pslot->ctrl))
-						rc = ibmphp_hpc_readslot (pslot,
-									  READ_SLOTLATCHLOWREG,
-									  &curlatchlow);
-				}
-			}
-			++poll_count;
-			poll_state = POLL_SLEEP;
-			break;
-		case POLL_SLEEP:
-			/* don't sleep with a lock on the hardware */
-			up (&semOperations);
-			long_delay (POLL_INTERVAL_SEC * HZ);
-
-			if (ibmphp_shutdown) 
-				break;
-			
-			down (&semOperations);
-			
-			if (poll_count >= POLL_LATCH_CNT) {
-				poll_count = 0;
-				poll_state = POLL_SLOTS;
-			} else
-				poll_state = POLL_LATCH_REGISTER;
-			break;
-		}	
-		/* give up the harware semaphore */
-		up (&semOperations);
-		/* sleep for a short time just for good measure */
-		set_current_state (TASK_INTERRUPTIBLE);
-		schedule_timeout (HZ/10);
-	}
-	up (&sem_exit);
-	debug ("%s - Exit\n", __FUNCTION__);
-}
-
-
-/* ----------------------------------------------------------------------
- *  Name:    ibmphp_hpc_fillhpslotinfo(hotplug_slot * phpslot)
- *
- *  Action:  fill out the hotplug_slot info
- *
- *  Input:   pointer to hotplug_slot
- *
- *  Return
- *  Value:   0 or error codes
- *-----------------------------------------------------------------------*/
-int ibmphp_hpc_fillhpslotinfo (struct hotplug_slot *phpslot)
-{
-	int rc = 0;
-	struct slot *pslot;
-
-	if (phpslot && phpslot->private) {
-		pslot = (struct slot *) phpslot->private;
-		rc = update_slot (pslot, (u8) TRUE);
-		if (!rc) {
-
-			// power - enabled:1  not:0
-			phpslot->info->power_status = SLOT_POWER (pslot->status);
-
-			// attention - off:0, on:1, blinking:2
-			phpslot->info->attention_status = SLOT_ATTN (pslot->status, pslot->ext_status);
-
-			// latch - open:1 closed:0
-			phpslot->info->latch_status = SLOT_LATCH (pslot->status);
-
-			// pci board - present:1 not:0
-			if (SLOT_PRESENT (pslot->status))
-				phpslot->info->adapter_status = 1;
-			else
-				phpslot->info->adapter_status = 0;
-/*
-			if (pslot->bus_on->supported_bus_mode
-				&& (pslot->bus_on->supported_speed == BUS_SPEED_66))
-				phpslot->info->max_bus_speed_status = BUS_SPEED_66PCIX;
-			else
-				phpslot->info->max_bus_speed_status = pslot->bus_on->supported_speed;
-*/		} else
-			rc = -EINVAL;
-	} else
-		rc = -EINVAL;
-
-	return rc;
-}
-
-/*----------------------------------------------------------------------
-* Name:    update_slot
-*
-* Action:  fill out slot status and extended status, controller status
-*
-* Input:   pointer to slot struct
-*---------------------------------------------------------------------*/
-static int update_slot (struct slot *pslot, u8 update)
-{
-	int rc = 0;
-
-	debug ("%s - Entry pslot[%lx]\n", __FUNCTION__, (ulong) pslot);
-	rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL);
-	debug ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
-	return rc;
-}
-
-/*----------------------------------------------------------------------
-* Name:    process_changeinstatus
-*
-* Action:  compare old and new slot status, process the change in status
-*
-* Input:   pointer to slot struct, old slot struct
-*
-* Return   0 or error codes
-* Value:
-*
-* Side
-* Effects: None.
-*
-* Notes:
-*---------------------------------------------------------------------*/
-static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)
-{
-	u8 status;
-	int rc = 0;
-	u8 disable = FALSE;
-	u8 update = FALSE;
-
-	debug ("process_changeinstatus - Entry pslot[%lx], poldslot[%lx]\n", (ulong) pslot,
-	       (ulong) poldslot);
-
-	// bit 0 - HPC_SLOT_POWER
-	if ((pslot->status & 0x01) != (poldslot->status & 0x01))
-		update = TRUE;
-
-	// bit 1 - HPC_SLOT_CONNECT
-	// ignore
-
-	// bit 2 - HPC_SLOT_ATTN
-	if ((pslot->status & 0x04) != (poldslot->status & 0x04))
-		update = TRUE;
-
-	// bit 3 - HPC_SLOT_PRSNT2
-	// bit 4 - HPC_SLOT_PRSNT1
-	if (((pslot->status & 0x08) != (poldslot->status & 0x08))
-		|| ((pslot->status & 0x10) != (poldslot->status & 0x10)))
-		update = TRUE;
-
-	// bit 5 - HPC_SLOT_PWRGD
-	if ((pslot->status & 0x20) != (poldslot->status & 0x20))
-		// OFF -> ON: ignore, ON -> OFF: disable slot
-		if ((poldslot->status & 0x20) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) 
-			disable = TRUE;
-
-	// bit 6 - HPC_SLOT_BUS_SPEED
-	// ignore
-
-	// bit 7 - HPC_SLOT_LATCH
-	if ((pslot->status & 0x80) != (poldslot->status & 0x80)) {
-		update = TRUE;
-		// OPEN -> CLOSE
-		if (pslot->status & 0x80) {
-			if (SLOT_PWRGD (pslot->status)) {
-				// power goes on and off after closing latch
-				// check again to make sure power is still ON
-				long_delay (1 * HZ);
-				rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status);
-				if (SLOT_PWRGD (status))
-					update = TRUE;
-				else	// overwrite power in pslot to OFF
-					pslot->status &= ~HPC_SLOT_POWER;
-			}
-		}
-		// CLOSE -> OPEN 
-		else if ((SLOT_PWRGD (poldslot->status) == HPC_SLOT_PWRGD_GOOD)
-			&& (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) {
-			disable = TRUE;
-		}
-		// else - ignore
-	}
-	// bit 4 - HPC_SLOT_BLINK_ATTN
-	if ((pslot->ext_status & 0x08) != (poldslot->ext_status & 0x08))
-		update = TRUE;
-
-	if (disable) {
-		debug ("process_changeinstatus - disable slot\n");
-		pslot->flag = FALSE;
-		rc = ibmphp_do_disable_slot (pslot);
-	}
-
-	if (update || disable) {
-		ibmphp_update_slot_info (pslot);
-	}
-
-	debug ("%s - Exit rc[%d] disable[%x] update[%x]\n", __FUNCTION__, rc, disable, update);
-
-	return rc;
-}
-
-/*----------------------------------------------------------------------
-* Name:    process_changeinlatch
-*
-* Action:  compare old and new latch reg status, process the change
-*
-* Input:   old and current latch register status
-*
-* Return   0 or error codes
-* Value:
-*---------------------------------------------------------------------*/
-static int process_changeinlatch (u8 old, u8 new, struct controller *ctrl)
-{
-	struct slot myslot, *pslot;
-	u8 i;
-	u8 mask;
-	int rc = 0;
-
-	debug ("%s - Entry old[%x], new[%x]\n", __FUNCTION__, old, new);
-	// bit 0 reserved, 0 is LSB, check bit 1-6 for 6 slots
-
-	for (i = ctrl->starting_slot_num; i <= ctrl->ending_slot_num; i++) {
-		mask = 0x01 << i;
-		if ((mask & old) != (mask & new)) {
-			pslot = ibmphp_get_slot_from_physical_num (i);
-			if (pslot) {
-				memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
-				rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL);
-				debug ("%s - call process_changeinstatus for slot[%d]\n", __FUNCTION__, i);
-				process_changeinstatus (pslot, &myslot);
-			} else {
-				rc = -EINVAL;
-				err ("%s - Error bad pointer for slot[%d]\n", __FUNCTION__, i);
-			}
-		}
-	}
-	debug ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
-	return rc;
-}
-
-/*----------------------------------------------------------------------
-* Name:    hpc_poll_thread
-*
-* Action:  polling
-*
-* Return   0
-* Value:
-*---------------------------------------------------------------------*/
-static int hpc_poll_thread (void *data)
-{
-	debug ("%s - Entry\n", __FUNCTION__);
-
-	daemonize("hpc_poll");
-	allow_signal(SIGKILL);
-
-	poll_hpc ();
-
-	tid_poll = 0;
-	debug ("%s - Exit\n", __FUNCTION__);
-	return 0;
-}
-
-
-/*----------------------------------------------------------------------
-* Name:    ibmphp_hpc_start_poll_thread
-*
-* Action:  start polling thread
-*---------------------------------------------------------------------*/
-int __init ibmphp_hpc_start_poll_thread (void)
-{
-	int rc = 0;
-
-	debug ("%s - Entry\n", __FUNCTION__);
-
-	tid_poll = kernel_thread (hpc_poll_thread, 0, 0);
-	if (tid_poll < 0) {
-		err ("%s - Error, thread not started\n", __FUNCTION__);
-		rc = -1;
-	}
-
-	debug ("%s - Exit tid_poll[%d] rc[%d]\n", __FUNCTION__, tid_poll, rc);
-	return rc;
-}
-
-/*----------------------------------------------------------------------
-* Name:    ibmphp_hpc_stop_poll_thread
-*
-* Action:  stop polling thread and cleanup
-*---------------------------------------------------------------------*/
-void __exit ibmphp_hpc_stop_poll_thread (void)
-{
-	debug ("%s - Entry\n", __FUNCTION__);
-
-	ibmphp_shutdown = TRUE;
-	debug ("before locking operations \n");
-	ibmphp_lock_operations ();
-	debug ("after locking operations \n");
-	
-	// wait for poll thread to exit
-	debug ("before sem_exit down \n");
-	down (&sem_exit);
-	debug ("after sem_exit down \n");
-
-	// cleanup
-	debug ("before free_hpc_access \n");
-	free_hpc_access ();
-	debug ("after free_hpc_access \n");
-	ibmphp_unlock_operations ();
-	debug ("after unlock operations \n");
-	up (&sem_exit);
-	debug ("after sem exit up\n");
-
-	debug ("%s - Exit\n", __FUNCTION__);
-}
-
-/*----------------------------------------------------------------------
-* Name:    hpc_wait_ctlr_notworking
-*
-* Action:  wait until the controller is in a not working state
-*
-* Return   0, HPC_ERROR
-* Value:
-*---------------------------------------------------------------------*/
-static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, void *wpg_bbar,
-				    u8 * pstatus)
-{
-	int rc = 0;
-	u8 done = FALSE;
-
-	debug_polling ("hpc_wait_ctlr_notworking - Entry timeout[%d]\n", timeout);
-
-	while (!done) {
-		*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, WPG_CTLR_INDEX);
-		if (*pstatus == HPC_ERROR) {
-			rc = HPC_ERROR;
-			done = TRUE;
-		}
-		if (CTLR_WORKING (*pstatus) == HPC_CTLR_WORKING_NO)
-			done = TRUE;
-		if (!done) {
-			long_delay (1 * HZ);
-			if (timeout < 1) {
-				done = TRUE;
-				err ("HPCreadslot - Error ctlr timeout\n");
-				rc = HPC_ERROR;
-			} else
-				timeout--;
-		}
-	}
-	debug_polling ("hpc_wait_ctlr_notworking - Exit rc[%x] status[%x]\n", rc, *pstatus);
-	return rc;
-}
diff -Nru a/drivers/hotplug/ibmphp_pci.c b/drivers/hotplug/ibmphp_pci.c
--- a/drivers/hotplug/ibmphp_pci.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1758 +0,0 @@
-/*
- * IBM Hot Plug Controller Driver
- * 
- * Written By: Irene Zubarev, IBM Corporation
- * 
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001,2002 IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <gregkh@us.ibm.com>
- *
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/list.h>
-#include "ibmphp.h"
-
-
-static int configure_device(struct pci_func *);
-static int configure_bridge(struct pci_func **, u8);
-static struct res_needed *scan_behind_bridge(struct pci_func *, u8);
-static int add_new_bus (struct bus_node *, struct resource_node *, struct resource_node *, struct resource_node *, u8);
-static u8 find_sec_number (u8 primary_busno, u8 slotno);
-
-/*
- * NOTE..... If BIOS doesn't provide default routing, we assign:
- * 9 for SCSI, 10 for LAN adapters, and 11 for everything else. 
- * If adapter is bridged, then we assign 11 to it and devices behind it.
- * We also assign the same irq numbers for multi function devices.
- * These are PIC mode, so shouldn't matter n.e.ways (hopefully)
- */
-static void assign_alt_irq (struct pci_func * cur_func, u8 class_code)
-{
-	int j = 0;
-	for (j = 0; j < 4; j++) {
-		if (cur_func->irq[j] == 0xff) {
-			switch (class_code) {
-				case PCI_BASE_CLASS_STORAGE:
-					cur_func->irq[j] = SCSI_IRQ;
-					break;
-				case PCI_BASE_CLASS_NETWORK:
-					cur_func->irq[j] = LAN_IRQ;
-					break;
-				default:
-					cur_func->irq[j] = OTHER_IRQ;
-					break;
-			}
-		}
-	}
-}
-
-/*
- * Configures the device to be added (will allocate needed resources if it
- * can), the device can be a bridge or a regular pci device, can also be
- * multi-functional
- * 
- * Input: function to be added
- * 
- * TO DO:  The error case with Multifunction device or multi function bridge,
- * if there is an error, will need to go through all previous functions and 
- * unconfigure....or can add some code into unconfigure_card....
- */
-int ibmphp_configure_card (struct pci_func *func, u8 slotno)
-{
-	u16 vendor_id;
-	u32 class;
-	u8 class_code;
-	u8 hdr_type, device, sec_number;
-	u8 function;
-	struct pci_func *newfunc;	/* for multi devices */
-	struct pci_func *cur_func, *prev_func;
-	int rc, i, j;
-	int cleanup_count;
-	u8 flag;
-	u8 valid_device = 0x00; /* to see if we are able to read from card any device info at all */
-
-	debug ("inside configure_card, func->busno = %x \n", func->busno);
-
-	device = func->device;
-	cur_func = func;
-
-	/* We only get bus and device from IRQ routing table.  So at this point,
-	 * func->busno is correct, and func->device contains only device (at the 5 
-	 * highest bits)
-	 */
-
-	/* For every function on the card */
-	for (function = 0x00; function < 0x08; function++) {
-		unsigned int devfn = PCI_DEVFN(device, function);
-		ibmphp_pci_bus->number = cur_func->busno;
-
-		cur_func->function = function;
-
-		debug ("inside the loop, cur_func->busno = %x, cur_func->device = %x, cur_func->funcion = %x\n",
-			cur_func->busno, cur_func->device, cur_func->function);
-
-		pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id);
-
-		debug ("vendor_id is %x\n", vendor_id);
-		if (vendor_id != PCI_VENDOR_ID_NOTVALID) {
-			/* found correct device!!! */
-			debug ("found valid device, vendor_id = %x\n", vendor_id);
-
-			++valid_device;
-
-			/* header: x x x x x x x x
-			 *         | |___________|=> 1=PPB bridge, 0=normal device, 2=CardBus Bridge
-			 *         |_=> 0 = single function device, 1 = multi-function device
-			 */
-
-			pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type);
-			pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class);
-
-			class_code = class >> 24;
-			debug ("hrd_type = %x, class = %x, class_code %x \n", hdr_type, class, class_code);
-			class >>= 8;	/* to take revision out, class = class.subclass.prog i/f */
-			if (class == PCI_CLASS_NOT_DEFINED_VGA) {
-				err ("The device %x is VGA compatible and as is not supported for hot plugging. "
-				     "Please choose another device.\n", cur_func->device);
-				return -ENODEV;
-			} else if (class == PCI_CLASS_DISPLAY_VGA) {
-				err ("The device %x is not supported for hot plugging. "
-				     "Please choose another device.\n", cur_func->device);
-				return -ENODEV;
-			}
-			switch (hdr_type) {
-				case PCI_HEADER_TYPE_NORMAL:
-					debug ("single device case.... vendor id = %x, hdr_type = %x, class = %x\n", vendor_id, hdr_type, class);
-					assign_alt_irq (cur_func, class_code);
-					if ((rc = configure_device (cur_func)) < 0) {
-						/* We need to do this in case some other BARs were properly inserted */
-						err ("was not able to configure devfunc %x on bus %x. \n",
-						     cur_func->device, cur_func->busno);
-						cleanup_count = 6;
-						goto error;
-					}	
-					cur_func->next = NULL;
-					function = 0x8;
-					break;
-				case PCI_HEADER_TYPE_MULTIDEVICE:
-					assign_alt_irq (cur_func, class_code);
-					if ((rc = configure_device (cur_func)) < 0) {
-						/* We need to do this in case some other BARs were properly inserted */
-						err ("was not able to configure devfunc %x on bus %x...bailing out\n",
-						     cur_func->device, cur_func->busno);
-						cleanup_count = 6;
-						goto error;
-					}
-					newfunc = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
-					if (!newfunc) {
-						err ("out of system memory \n");
-						return -ENOMEM;
-					}
-					memset (newfunc, 0, sizeof (struct pci_func));
-					newfunc->busno = cur_func->busno;
-					newfunc->device = device;
-					cur_func->next = newfunc;
-					cur_func = newfunc;
-					for (j = 0; j < 4; j++)
-						newfunc->irq[j] = cur_func->irq[j];
-					break;
-				case PCI_HEADER_TYPE_MULTIBRIDGE:
-					class >>= 8;
-					if (class != PCI_CLASS_BRIDGE_PCI) {
-						err ("This %x is not PCI-to-PCI bridge, and as is not supported for hot-plugging. "
-						     "Please insert another card.\n", cur_func->device);
-						return -ENODEV;
-					}
-					assign_alt_irq (cur_func, class_code);
-					rc = configure_bridge (&cur_func, slotno);
-					if (rc == -ENODEV) {
-						err ("You chose to insert Single Bridge, or nested bridges, this is not supported...\n");
-						err ("Bus %x, devfunc %x \n", cur_func->busno, cur_func->device);
-						return rc;
-					}
-					if (rc) {
-						/* We need to do this in case some other BARs were properly inserted */
-						err ("was not able to hot-add PPB properly.\n");
-						func->bus = 1; /* To indicate to the unconfigure function that this is a PPB */
-						cleanup_count = 2;
-						goto error;
-					}
-
-					pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
-					flag = FALSE;
-					for (i = 0; i < 32; i++) {
-						if (func->devices[i]) {
-							newfunc = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
-							if (!newfunc) {
-								err ("out of system memory \n");
-								return -ENOMEM;
-							}
-							memset (newfunc, 0, sizeof (struct pci_func));
-							newfunc->busno = sec_number;
-							newfunc->device = (u8) i;
-							for (j = 0; j < 4; j++)
-								newfunc->irq[j] = cur_func->irq[j];
-
-							if (flag) {
-								for (prev_func = cur_func; prev_func->next; prev_func = prev_func->next) ;
-								prev_func->next = newfunc;
-							} else
-								cur_func->next = newfunc;
-
-							rc = ibmphp_configure_card (newfunc, slotno);
-							/* This could only happen if kmalloc failed */
-							if (rc) {
-								/* We need to do this in case bridge itself got configured properly, but devices behind it failed */
-								func->bus = 1; /* To indicate to the unconfigure function that this is a PPB */
-								cleanup_count = 2;
-								goto error;
-							}
-							flag = TRUE;
-						}
-					}
-
-					newfunc = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
-					if (!newfunc) {
-						err ("out of system memory \n");
-						return -ENOMEM;
-					}
-					memset (newfunc, 0, sizeof (struct pci_func));
-					newfunc->busno = cur_func->busno;
-					newfunc->device = device;
-					for (j = 0; j < 4; j++)
-						newfunc->irq[j] = cur_func->irq[j];
-					for (prev_func = cur_func; prev_func->next; prev_func = prev_func->next) ;
-					prev_func->next = newfunc;
-					cur_func = newfunc;
-					break;
-				case PCI_HEADER_TYPE_BRIDGE:
-					class >>= 8;
-					debug ("class now is %x\n", class);
-					if (class != PCI_CLASS_BRIDGE_PCI) {
-						err ("This %x is not PCI-to-PCI bridge, and as is not supported for hot-plugging. "
-						     "Please insert another card.\n", cur_func->device);
-						return -ENODEV;
-					}
-
-					assign_alt_irq (cur_func, class_code);
-
-					debug ("cur_func->busno b4 configure_bridge is %x\n", cur_func->busno);
-					rc = configure_bridge (&cur_func, slotno);
-					if (rc == -ENODEV) {
-						err ("You chose to insert Single Bridge, or nested bridges, this is not supported...\n");
-						err ("Bus %x, devfunc %x \n", cur_func->busno, cur_func->device);
-						return rc;
-					}
-					if (rc) {
-						/* We need to do this in case some other BARs were properly inserted */
-						func->bus = 1; /* To indicate to the unconfigure function that this is a PPB */
-						err ("was not able to hot-add PPB properly.\n");
-						cleanup_count = 2;
-						goto error;
-					}
-					debug ("cur_func->busno = %x, device = %x, function = %x\n",
-						cur_func->busno, device, function);
-					pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
-					debug ("after configuring bridge..., sec_number = %x\n", sec_number);
-					flag = FALSE;
-					for (i = 0; i < 32; i++) {
-						if (func->devices[i]) {
-							debug ("inside for loop, device is %x\n", i);
-							newfunc = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
-							if (!newfunc) {
-								err (" out of system memory \n");
-								return -ENOMEM;
-							}
-							memset (newfunc, 0, sizeof (struct pci_func));
-							newfunc->busno = sec_number;
-							newfunc->device = (u8) i;
-							for (j = 0; j < 4; j++)
-								newfunc->irq[j] = cur_func->irq[j];
-
-							if (flag) {
-								for (prev_func = cur_func; prev_func->next; prev_func = prev_func->next) ;
-								prev_func->next = newfunc;
-							} else
-								cur_func->next = newfunc;
-
-							rc = ibmphp_configure_card (newfunc, slotno);
-
-							/* Again, this case should not happen... For complete paranoia, will need to call remove_bus */
-							if (rc) {
-								/* We need to do this in case some other BARs were properly inserted */
-								func->bus = 1; /* To indicate to the unconfigure function that this is a PPB */
-								cleanup_count = 2;
-								goto error;
-							}
-							flag = TRUE;
-						}
-					}
-
-					function = 0x8;
-					break;
-				default:
-					err ("MAJOR PROBLEM!!!!, header type not supported? %x\n", hdr_type);
-					return -ENXIO;
-					break;
-			}	/* end of switch */
-		}	/* end of valid device */
-	}	/* end of for */
-
-	if (!valid_device) {
-		err ("Cannot find any valid devices on the card.  Or unable to read from card.\n");
-		return -ENODEV;
-	}
-
-	return 0;
-
-error:
-	for (i = 0; i < cleanup_count; i++) {
-		if (cur_func->io[i]) {
-			ibmphp_remove_resource (cur_func->io[i]);
-			cur_func->io[i] = NULL;
-		} else if (cur_func->pfmem[i]) {
-			ibmphp_remove_resource (cur_func->pfmem[i]);
-			cur_func->pfmem[i] = NULL;
-		} else if (cur_func->mem[i]) {
-			ibmphp_remove_resource (cur_func->mem[i]);
-			cur_func->mem[i] = NULL;
-		}
-	}
-	return rc;
-}
-
-/*
- * This function configures the pci BARs of a single device.  
- * Input: pointer to the pci_func
- * Output: configured PCI, 0, or error
- */
-static int configure_device (struct pci_func *func)
-{
-	u32 bar[6];
-	u32 address[] = {
-		PCI_BASE_ADDRESS_0,
-		PCI_BASE_ADDRESS_1,
-		PCI_BASE_ADDRESS_2,
-		PCI_BASE_ADDRESS_3,
-		PCI_BASE_ADDRESS_4,
-		PCI_BASE_ADDRESS_5,
-		0
-	};
-	u8 irq;
-	int count;
-	int len[6];
-	struct resource_node *io[6];
-	struct resource_node *mem[6];
-	struct resource_node *mem_tmp;
-	struct resource_node *pfmem[6];
-	unsigned int devfn;
-
-	debug ("%s - inside\n", __FUNCTION__);
-
-	devfn = PCI_DEVFN(func->device, func->function);
-	ibmphp_pci_bus->number = func->busno;
-
-	for (count = 0; address[count]; count++) {	/* for 6 BARs */
-
-		/* not sure if i need this.  per scott, said maybe need smth like this
-		   if devices don't adhere 100% to the spec, so don't want to write
-		   to the reserved bits
-
-		pcibios_read_config_byte(cur_func->busno, cur_func->device, 
-		PCI_BASE_ADDRESS_0 + 4 * count, &tmp);
-		if (tmp & 0x01) // IO
-			pcibios_write_config_dword(cur_func->busno, cur_func->device, 
-			PCI_BASE_ADDRESS_0 + 4 * count, 0xFFFFFFFD);
-		else  // Memory
-			pcibios_write_config_dword(cur_func->busno, cur_func->device, 
-			PCI_BASE_ADDRESS_0 + 4 * count, 0xFFFFFFFF);
-		 */
-		pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF);
-		pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]);
-
-		if (!bar[count])	/* This BAR is not implemented */
-			continue;
-
-		debug ("Device %x BAR %d wants %x\n", func->device, count, bar[count]);
-
-		if (bar[count] & PCI_BASE_ADDRESS_SPACE_IO) {
-			/* This is IO */
-			debug ("inside IO SPACE\n");
-
-			len[count] = bar[count] & 0xFFFFFFFC;
-			len[count] = ~len[count] + 1;
-
-			debug ("len[count] in IO %x, count %d\n", len[count], count);
-
-			io[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
-
-			if (!io[count]) {
-				err ("out of system memory \n");
-				return -ENOMEM;
-			}
-			memset (io[count], 0, sizeof (struct resource_node));
-			io[count]->type = IO;
-			io[count]->busno = func->busno;
-			io[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
-			io[count]->len = len[count];
-			if (ibmphp_check_resource(io[count], 0) == 0) {
-				ibmphp_add_resource (io[count]);
-				func->io[count] = io[count];
-			} else {
-				err ("cannot allocate requested io for bus %x device %x function %x len %x\n",
-				     func->busno, func->device, func->function, len[count]);
-				kfree (io[count]);
-				return -EIO;
-			}
-			pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->io[count]->start);
-	
-			/* _______________This is for debugging purposes only_____________________ */ 
-			debug ("b4 writing, the IO address is %x\n", func->io[count]->start);
-			pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]);
-			debug ("after writing.... the start address is %x\n", bar[count]);
-			/* _________________________________________________________________________*/
-
-		} else {
-			/* This is Memory */
-			if (bar[count] & PCI_BASE_ADDRESS_MEM_PREFETCH) {
-				/* pfmem */
-				debug ("PFMEM SPACE\n");
-
-				len[count] = bar[count] & 0xFFFFFFF0;
-				len[count] = ~len[count] + 1;
-
-				debug ("len[count] in PFMEM %x, count %d\n", len[count], count);
-
-				pfmem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
-				if (!pfmem[count]) {
-					err ("out of system memory \n");
-					return -ENOMEM;
-				}
-				memset (pfmem[count], 0, sizeof (struct resource_node));
-				pfmem[count]->type = PFMEM;
-				pfmem[count]->busno = func->busno;
-				pfmem[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
-				pfmem[count]->len = len[count];
-				pfmem[count]->fromMem = FALSE;
-				if (ibmphp_check_resource (pfmem[count], 0) == 0) {
-					ibmphp_add_resource (pfmem[count]);
-					func->pfmem[count] = pfmem[count];
-				} else {
-					mem_tmp = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
-					if (!mem_tmp) {
-						err ("out of system memory \n");
-						kfree (pfmem[count]);
-						return -ENOMEM;
-					}
-					memset (mem_tmp, 0, sizeof (struct resource_node));
-					mem_tmp->type = MEM;
-					mem_tmp->busno = pfmem[count]->busno;
-					mem_tmp->devfunc = pfmem[count]->devfunc;
-					mem_tmp->len = pfmem[count]->len;
-					debug ("there's no pfmem... going into mem.\n");
-					if (ibmphp_check_resource (mem_tmp, 0) == 0) {
-						ibmphp_add_resource (mem_tmp);
-						pfmem[count]->fromMem = TRUE;
-						pfmem[count]->rangeno = mem_tmp->rangeno;
-						pfmem[count]->start = mem_tmp->start;
-						pfmem[count]->end = mem_tmp->end;
-						ibmphp_add_pfmem_from_mem (pfmem[count]);
-						func->pfmem[count] = pfmem[count];
-					} else {
-						err ("cannot allocate requested pfmem for bus %x, device %x, len %x\n",
-						     func->busno, func->device, len[count]);
-						kfree (mem_tmp);
-						kfree (pfmem[count]);
-						return -EIO;
-					}
-				}
-
-				pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->pfmem[count]->start);
-
-				/*_______________This is for debugging purposes only______________________________*/				
-				debug ("b4 writing, start address is %x\n", func->pfmem[count]->start);
-				pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]);
-				debug ("after writing, start address is %x\n", bar[count]);
-				/*_________________________________________________________________________________*/
-
-				if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) {	/* takes up another dword */
-					debug ("inside the mem 64 case, count %d\n", count);
-					count += 1;
-					/* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */
-					pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0x00000000);
-				}
-			} else {
-				/* regular memory */
-				debug ("REGULAR MEM SPACE\n");
-
-				len[count] = bar[count] & 0xFFFFFFF0;
-				len[count] = ~len[count] + 1;
-
-				debug ("len[count] in Mem %x, count %d\n", len[count], count);
-
-				mem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
-				if (!mem[count]) {
-					err ("out of system memory \n");
-					return -ENOMEM;
-				}
-				memset (mem[count], 0, sizeof (struct resource_node));
-				mem[count]->type = MEM;
-				mem[count]->busno = func->busno;
-				mem[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
-				mem[count]->len = len[count];
-				if (ibmphp_check_resource (mem[count], 0) == 0) {
-					ibmphp_add_resource (mem[count]);
-					func->mem[count] = mem[count];
-				} else {
-					err ("cannot allocate requested mem for bus %x, device %x, len %x\n",
-					     func->busno, func->device, len[count]);
-					kfree (mem[count]);
-					return -EIO;
-				}
-				pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->mem[count]->start);
-				/* _______________________This is for debugging purposes only _______________________*/
-				debug ("b4 writing, start address is %x\n", func->mem[count]->start);
-				pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]);
-				debug ("after writing, the address is %x\n", bar[count]);
-				/* __________________________________________________________________________________*/
-
-				if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-					/* takes up another dword */
-					debug ("inside mem 64 case, reg. mem, count %d\n", count);
-					count += 1;
-					/* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */
-					pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0x00000000);
-				}
-			}
-		}		/* end of mem */
-	}			/* end of for */
-
-	func->bus = 0;		/* To indicate that this is not a PPB */
-	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_INTERRUPT_PIN, &irq);
-	if ((irq > 0x00) && (irq < 0x05))
-		pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_INTERRUPT_LINE, func->irq[irq - 1]);
-
-	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE);
-	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY);
-
-	pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L);
-	pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE);
-
-	return 0;
-}
-
-/******************************************************************************
- * This routine configures a PCI-2-PCI bridge and the functions behind it
- * Parameters: pci_func
- * Returns: 
- ******************************************************************************/
-static int configure_bridge (struct pci_func **func_passed, u8 slotno)
-{
-	int count;
-	int i;
-	int rc;
-	u8 sec_number;
-	u8 io_base;
-	u16 pfmem_base;
-	u32 bar[2];
-	u32 len[2];
-	u8 flag_io = FALSE;
-	u8 flag_mem = FALSE;
-	u8 flag_pfmem = FALSE;
-	u8 need_io_upper = FALSE;
-	u8 need_pfmem_upper = FALSE;
-	struct res_needed *amount_needed = NULL;
-	struct resource_node *io = NULL;
-	struct resource_node *bus_io[2] = {NULL, NULL};
-	struct resource_node *mem = NULL;
-	struct resource_node *bus_mem[2] = {NULL, NULL};
-	struct resource_node *mem_tmp = NULL;
-	struct resource_node *pfmem = NULL;
-	struct resource_node *bus_pfmem[2] = {NULL, NULL};
-	struct bus_node *bus;
-	u32 address[] = {
-		PCI_BASE_ADDRESS_0,
-		PCI_BASE_ADDRESS_1,
-		0
-	};
-	struct pci_func *func = *func_passed;
-	unsigned int devfn;
-	u8 irq;
-	int retval;
-
-	debug ("%s - enter\n", __FUNCTION__);
-
-	devfn = PCI_DEVFN(func->function, func->device);
-	ibmphp_pci_bus->number = func->busno;
-
-	/* Configuring necessary info for the bridge so that we could see the devices
-	 * behind it
-	 */
-
-	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, func->busno);
-
-	/* _____________________For debugging purposes only __________________________
-	pci_bus_config_byte (ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, &pri_number);
-	debug ("primary # written into the bridge is %x\n", pri_number);
-	 ___________________________________________________________________________*/
-
-	/* in EBDA, only get allocated 1 additional bus # per slot */
-	sec_number = find_sec_number (func->busno, slotno);
-	if (sec_number == 0xff) {
-		err ("cannot allocate secondary bus number for the bridged device \n");
-		return -EINVAL;
-	}
-
-	debug ("after find_sec_number, the number we got is %x\n", sec_number);
-	debug ("AFTER FIND_SEC_NUMBER, func->busno IS %x\n", func->busno);
-
-	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, sec_number);
-	
-	/* __________________For debugging purposes only __________________________________
-	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
-	debug ("sec_number after write/read is %x\n", sec_number);
-	 ________________________________________________________________________________*/
-
-	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, sec_number);
-
-	/* __________________For debugging purposes only ____________________________________
-	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, &sec_number);
-	debug ("subordinate number after write/read is %x\n", sec_number);
-	 __________________________________________________________________________________*/
-
-	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE);
-	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY);
-	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_SEC_LATENCY_TIMER, LATENCY);
-
-	debug ("func->busno is %x\n", func->busno);
-	debug ("sec_number after writing is %x\n", sec_number);
-
-
-	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-	   !!!!!!!!!!!!!!!NEED TO ADD!!!  FAST BACK-TO-BACK ENABLE!!!!!!!!!!!!!!!!!!!! 
-	   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
-
-
-	/* First we need to allocate mem/io for the bridge itself in case it needs it */
-	for (count = 0; address[count]; count++) {	/* for 2 BARs */
-		pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF);
-		pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]);
-
-		if (!bar[count]) {
-			/* This BAR is not implemented */
-			debug ("so we come here then, eh?, count = %d\n", count);
-			continue;
-		}
-		//  tmp_bar = bar[count];
-
-		debug ("Bar %d wants %x\n", count, bar[count]);
-
-		if (bar[count] & PCI_BASE_ADDRESS_SPACE_IO) {
-			/* This is IO */
-			len[count] = bar[count] & 0xFFFFFFFC;
-			len[count] = ~len[count] + 1;
-
-			debug ("len[count] in IO = %x\n", len[count]);
-
-			bus_io[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
-		
-			if (!bus_io[count]) {
-				err ("out of system memory \n");
-				retval = -ENOMEM;
-				goto error;
-			}
-			memset (bus_io[count], 0, sizeof (struct resource_node));
-			bus_io[count]->type = IO;
-			bus_io[count]->busno = func->busno;
-			bus_io[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
-			bus_io[count]->len = len[count];
-			if (ibmphp_check_resource (bus_io[count], 0) == 0) {
-				ibmphp_add_resource (bus_io[count]);
-				func->io[count] = bus_io[count];
-			} else {
-				err ("cannot allocate requested io for bus %x, device %x, len %x\n",
-				     func->busno, func->device, len[count]);
-				kfree (bus_io[count]);
-				return -EIO;
-			}
-
-			pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->io[count]->start);
-
-		} else {
-			/* This is Memory */
-			if (bar[count] & PCI_BASE_ADDRESS_MEM_PREFETCH) {
-				/* pfmem */
-				len[count] = bar[count] & 0xFFFFFFF0;
-				len[count] = ~len[count] + 1;
-
-				debug ("len[count] in PFMEM = %x\n", len[count]);
-
-				bus_pfmem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
-				if (!bus_pfmem[count]) {
-					err ("out of system memory \n");
-					retval = -ENOMEM;
-					goto error;
-				}
-				memset (bus_pfmem[count], 0, sizeof (struct resource_node));
-				bus_pfmem[count]->type = PFMEM;
-				bus_pfmem[count]->busno = func->busno;
-				bus_pfmem[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
-				bus_pfmem[count]->len = len[count];
-				bus_pfmem[count]->fromMem = FALSE;
-				if (ibmphp_check_resource (bus_pfmem[count], 0) == 0) {
-					ibmphp_add_resource (bus_pfmem[count]);
-					func->pfmem[count] = bus_pfmem[count];
-				} else {
-					mem_tmp = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
-					if (!mem_tmp) {
-						err ("out of system memory \n");
-						retval = -ENOMEM;
-						goto error;
-					}
-					memset (mem_tmp, 0, sizeof (struct resource_node));
-					mem_tmp->type = MEM;
-					mem_tmp->busno = bus_pfmem[count]->busno;
-					mem_tmp->devfunc = bus_pfmem[count]->devfunc;
-					mem_tmp->len = bus_pfmem[count]->len;
-					if (ibmphp_check_resource (mem_tmp, 0) == 0) {
-						ibmphp_add_resource (mem_tmp);
-						bus_pfmem[count]->fromMem = TRUE;
-						bus_pfmem[count]->rangeno = mem_tmp->rangeno;
-						ibmphp_add_pfmem_from_mem (bus_pfmem[count]);
-						func->pfmem[count] = bus_pfmem[count];
-					} else {
-						err ("cannot allocate requested pfmem for bus %x, device %x, len %x\n", 
-						     func->busno, func->device, len[count]);
-						kfree (mem_tmp);
-						kfree (bus_pfmem[count]);
-						return -EIO;
-					}
-				}
-
-				pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->pfmem[count]->start);
-
-				if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-					/* takes up another dword */
-					count += 1;
-					/* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */
-					pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0x00000000);
-
-				}
-			} else {
-				/* regular memory */
-				len[count] = bar[count] & 0xFFFFFFF0;
-				len[count] = ~len[count] + 1;
-
-				debug ("len[count] in Memory is %x\n", len[count]);
-
-				bus_mem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
-				if (!bus_mem[count]) {
-					err ("out of system memory \n");
-					retval = -ENOMEM;
-					goto error;
-				}
-				memset (bus_mem[count], 0, sizeof (struct resource_node));
-				bus_mem[count]->type = MEM;
-				bus_mem[count]->busno = func->busno;
-				bus_mem[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
-				bus_mem[count]->len = len[count];
-				if (ibmphp_check_resource (bus_mem[count], 0) == 0) {
-					ibmphp_add_resource (bus_mem[count]);
-					func->mem[count] = bus_mem[count];
-				} else {
-					err ("cannot allocate requested mem for bus %x, device %x, len %x\n",
-					     func->busno, func->device, len[count]);
-					kfree (bus_mem[count]);
-					return -EIO;
-				}
-
-				pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->mem[count]->start);
-
-				if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-					/* takes up another dword */
-					count += 1;
-					/* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */
-					pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0x00000000);
-
-				}
-			}
-		}		/* end of mem */
-	}			/* end of for  */
-
-	/* Now need to see how much space the devices behind the bridge needed */
-	amount_needed = scan_behind_bridge (func, sec_number);
-	if (amount_needed == NULL)
-		return -ENOMEM;
-
-	ibmphp_pci_bus->number = func->busno;
-	debug ("after coming back from scan_behind_bridge\n");
-	debug ("amount_needed->not_correct = %x\n", amount_needed->not_correct);
-	debug ("amount_needed->io = %x\n", amount_needed->io);
-	debug ("amount_needed->mem = %x\n", amount_needed->mem);
-	debug ("amount_needed->pfmem =  %x\n", amount_needed->pfmem);
-
-	if (amount_needed->not_correct) {		
-		debug ("amount_needed is not correct \n");
-		for (count = 0; address[count]; count++) {
-			/* for 2 BARs */
-			if (bus_io[count]) {
-				ibmphp_remove_resource (bus_io[count]);
-				func->io[count] = NULL;
-			} else if (bus_pfmem[count]) {
-				ibmphp_remove_resource (bus_pfmem[count]);
-				func->pfmem[count] = NULL;
-			} else if (bus_mem[count]) {
-				ibmphp_remove_resource (bus_mem[count]);
-				func->mem[count] = NULL;
-			}
-		}
-		kfree (amount_needed);
-		return -ENODEV;
-	}
-
-	if (!amount_needed->io) {
-		debug ("it doesn't want IO?\n");
-		flag_io = TRUE;
-	} else {
-		debug ("it wants %x IO behind the bridge \n", amount_needed->io);
-		io = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
-		
-		if (!io) {
-			err ("out of system memory \n");
-			retval = -ENOMEM;
-			goto error;
-		}
-		memset (io, 0, sizeof (struct resource_node));
-		io->type = IO;
-		io->busno = func->busno;
-		io->devfunc = ((func->device << 3) | (func->function & 0x7));
-		io->len = amount_needed->io;
-		if (ibmphp_check_resource (io, 1) == 0) {
-			debug ("were we able to add io\n");
-			ibmphp_add_resource (io);
-			flag_io = TRUE;
-		}
-	}
-
-	if (!amount_needed->mem) {
-		debug ("it doesn't want n.e.memory?\n");
-		flag_mem = TRUE;
-	} else {
-		debug ("it wants %x memory behind the bridge\n", amount_needed->mem);
-		mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
-		if (!mem) {
-			err ("out of system memory \n");
-			retval = -ENOMEM;
-			goto error;
-		}
-		memset (mem, 0, sizeof (struct resource_node));
-		mem->type = MEM;
-		mem->busno = func->busno;
-		mem->devfunc = ((func->device << 3) | (func->function & 0x7));
-		mem->len = amount_needed->mem;
-		if (ibmphp_check_resource (mem, 1) == 0) {
-			ibmphp_add_resource (mem);
-			flag_mem = TRUE;
-			debug ("were we able to add mem\n");
-		}
-	}
-
-	if (!amount_needed->pfmem) {
-		debug ("it doesn't want n.e.pfmem mem?\n");
-		flag_pfmem = TRUE;
-	} else {
-		debug ("it wants %x pfmemory behind the bridge\n", amount_needed->pfmem);
-		pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
-		if (!pfmem) {
-			err ("out of system memory \n");
-			retval = -ENOMEM;
-			goto error;
-		}
-		memset (pfmem, 0, sizeof (struct resource_node));
-		pfmem->type = PFMEM;
-		pfmem->busno = func->busno;
-		pfmem->devfunc = ((func->device << 3) | (func->function & 0x7));
-		pfmem->len = amount_needed->pfmem;
-		pfmem->fromMem = FALSE;
-		if (ibmphp_check_resource (pfmem, 1) == 0) {
-			ibmphp_add_resource (pfmem);
-			flag_pfmem = TRUE;
-		} else {
-			mem_tmp = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
-			if (!mem_tmp) {
-				err ("out of system memory \n");
-				retval = -ENOMEM;
-				goto error;
-			}
-			memset (mem_tmp, 0, sizeof (struct resource_node));
-			mem_tmp->type = MEM;
-			mem_tmp->busno = pfmem->busno;
-			mem_tmp->devfunc = pfmem->devfunc;
-			mem_tmp->len = pfmem->len;
-			if (ibmphp_check_resource (mem_tmp, 1) == 0) {
-				ibmphp_add_resource (mem_tmp);
-				pfmem->fromMem = TRUE;
-				pfmem->rangeno = mem_tmp->rangeno;
-				ibmphp_add_pfmem_from_mem (pfmem);
-				flag_pfmem = TRUE;
-			}
-		}
-	}
-
-	debug ("b4 if (flag_io && flag_mem && flag_pfmem)\n");
-	debug ("flag_io = %x, flag_mem = %x, flag_pfmem = %x\n", flag_io, flag_mem, flag_pfmem);
-
-	if (flag_io && flag_mem && flag_pfmem) {
-		/* If on bootup, there was a bridged card in this slot,
-		 * then card was removed and ibmphp got unloaded and loaded
-		 * back again, there's no way for us to remove the bus
-		 * struct, so no need to kmalloc, can use existing node
-		 */
-		bus = ibmphp_find_res_bus (sec_number);
-		if (!bus) {
-			bus = kmalloc (sizeof (struct bus_node), GFP_KERNEL);
-			if (!bus) {
-				err ("out of system memory \n");
-				retval = -ENOMEM;
-				goto error;
-			}
-			memset (bus, 0, sizeof (struct bus_node));
-			bus->busno = sec_number;
-			debug ("b4 adding new bus\n");
-			rc = add_new_bus (bus, io, mem, pfmem, func->busno);
-		} else if (!(bus->rangeIO) && !(bus->rangeMem) && !(bus->rangePFMem))
-			rc = add_new_bus (bus, io, mem, pfmem, 0xFF);
-		else {
-			err ("expected bus structure not empty? \n");
-			retval = -EIO;
-			goto error;
-		}
-		if (rc) {
-			if (rc == -ENOMEM) {
-				ibmphp_remove_bus (bus, func->busno);
-				kfree (amount_needed);
-				return rc;
-			}
-			retval = rc;
-			goto error;
-		}
-		pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, &io_base);
-		pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, &pfmem_base);
-
-		if ((io_base & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
-			debug ("io 32\n");
-			need_io_upper = TRUE;
-		}
-		if ((io_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
-			debug ("pfmem 64\n");
-			need_pfmem_upper = TRUE;
-		}
-
-		if (bus->noIORanges) {
-			pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, 0x00 | bus->rangeIO->start >> 8);
-			pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, 0x00 | bus->rangeIO->end >> 8);	
-
-			/* _______________This is for debugging purposes only ____________________
-			pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, &temp);
-			debug ("io_base = %x\n", (temp & PCI_IO_RANGE_TYPE_MASK) << 8);
-			pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, &temp);
-			debug ("io_limit = %x\n", (temp & PCI_IO_RANGE_TYPE_MASK) << 8);
-			 ________________________________________________________________________*/
-
-			if (need_io_upper) {	/* since can't support n.e.ways */
-				pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_IO_BASE_UPPER16, 0x0000);
-				pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_IO_LIMIT_UPPER16, 0x0000);
-			}
-		} else {
-			pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, 0x00);
-			pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, 0x00);
-		}
-
-		if (bus->noMemRanges) {
-			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, 0x0000 | bus->rangeMem->start >> 16);
-			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, 0x0000 | bus->rangeMem->end >> 16);
-			
-			/* ____________________This is for debugging purposes only ________________________
-			pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, &temp);
-			debug ("mem_base = %x\n", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16);
-			pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, &temp);
-			debug ("mem_limit = %x\n", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16);
-			 __________________________________________________________________________________*/
-
-		} else {
-			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, 0xffff);
-			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, 0x0000);
-		}
-		if (bus->noPFMemRanges) {
-			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, 0x0000 | bus->rangePFMem->start >> 16);
-			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, 0x0000 | bus->rangePFMem->end >> 16);
-
-			/* __________________________This is for debugging purposes only _______________________
-			pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, &temp);
-			debug ("pfmem_base = %x", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16);
-			pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &temp);
-			debug ("pfmem_limit = %x\n", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16);
-			 ______________________________________________________________________________________*/
-
-			if (need_pfmem_upper) {	/* since can't support n.e.ways */
-				pci_bus_write_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_BASE_UPPER32, 0x00000000);
-				pci_bus_write_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_LIMIT_UPPER32, 0x00000000);
-			}
-		} else {
-			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, 0xffff);
-			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, 0x0000);
-		}
-
-		debug ("b4 writing control information\n");
-
-		pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_INTERRUPT_PIN, &irq);
-		if ((irq > 0x00) && (irq < 0x05))
-			pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_INTERRUPT_LINE, func->irq[irq - 1]);
-		/*    
-		pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, ctrl);
-		pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_PARITY);
-		pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_SERR);
-		 */
-
-		pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE);
-		pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, 0x07);
-		for (i = 0; i < 32; i++) {
-			if (amount_needed->devices[i]) {
-				debug ("device where devices[i] is 1 = %x\n", i);
-				func->devices[i] = 1;
-			}
-		}
-		func->bus = 1;	/* For unconfiguring, to indicate it's PPB */
-		func_passed = &func;
-		debug ("func->busno b4 returning is %x\n", func->busno);
-		debug ("func->busno b4 returning in the other structure is %x\n", (*func_passed)->busno);
-		kfree (amount_needed);
-		return 0;
-	} else {
-		err ("Configuring bridge was unsuccessful... \n");
-		mem_tmp = NULL;
-		retval = -EIO;
-		goto error;
-	}
-
-error:
-	if (amount_needed)
-		kfree (amount_needed);
-	if (pfmem)
-		ibmphp_remove_resource (pfmem);
-	if (io)
-		ibmphp_remove_resource (io);
-	if (mem)
-		ibmphp_remove_resource (mem);
-	for (i = 0; i < 2; i++) {	/* for 2 BARs */
-		if (bus_io[i]) {
-			ibmphp_remove_resource (bus_io[i]);
-			func->io[i] = NULL;
-		} else if (bus_pfmem[i]) {
-			ibmphp_remove_resource (bus_pfmem[i]);
-			func->pfmem[i] = NULL;
-		} else if (bus_mem[i]) {
-			ibmphp_remove_resource (bus_mem[i]);
-			func->mem[i] = NULL;
-		}
-	}
-	return retval;
-}
-
-/*****************************************************************************
- * This function adds up the amount of resources needed behind the PPB bridge
- * and passes it to the configure_bridge function
- * Input: bridge function
- * Ouput: amount of resources needed
- *****************************************************************************/
-static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno)
-{
-	int count, len[6];
-	u16 vendor_id;
-	u8 hdr_type;
-	u8 device, function;
-	unsigned int devfn;
-	int howmany = 0;	/*this is to see if there are any devices behind the bridge */
-
-	u32 bar[6], class;
-	u32 address[] = {
-		PCI_BASE_ADDRESS_0,
-		PCI_BASE_ADDRESS_1,
-		PCI_BASE_ADDRESS_2,
-		PCI_BASE_ADDRESS_3,
-		PCI_BASE_ADDRESS_4,
-		PCI_BASE_ADDRESS_5,
-		0
-	};
-	struct res_needed *amount;
-
-	amount = kmalloc (sizeof (struct res_needed), GFP_KERNEL);
-	if (amount == NULL)
-		return NULL;
-	memset (amount, 0, sizeof (struct res_needed));
-
-	ibmphp_pci_bus->number = busno;
-
-	debug ("the bus_no behind the bridge is %x\n", busno);
-	debug ("scanning devices behind the bridge...\n");
-	for (device = 0; device < 32; device++) {
-		amount->devices[device] = 0;
-		for (function = 0; function < 8; function++) {
-			devfn = PCI_DEVFN(device, function);
-
-			pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id);
-
-			if (vendor_id != PCI_VENDOR_ID_NOTVALID) {
-				/* found correct device!!! */
-				howmany++;
-
-				pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type);
-				pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class);
-
-				debug ("hdr_type behind the bridge is %x\n", hdr_type);
-				if (hdr_type & PCI_HEADER_TYPE_BRIDGE) {
-					err ("embedded bridges not supported for hot-plugging.\n");
-					amount->not_correct = TRUE;
-					return amount;
-				}
-
-				class >>= 8;	/* to take revision out, class = class.subclass.prog i/f */
-				if (class == PCI_CLASS_NOT_DEFINED_VGA) {
-					err ("The device %x is VGA compatible and as is not supported for hot plugging. "
-					     "Please choose another device.\n", device);
-					amount->not_correct = TRUE;
-					return amount;
-				} else if (class == PCI_CLASS_DISPLAY_VGA) {
-					err ("The device %x is not supported for hot plugging. "
-					     "Please choose another device.\n", device);
-					amount->not_correct = TRUE;
-					return amount;
-				}
-
-				amount->devices[device] = 1;
-
-				for (count = 0; address[count]; count++) {
-					/* for 6 BARs */
-					/*
-					pci_bus_read_config_byte (ibmphp_pci_bus, devfn, address[count], &tmp);
-					if (tmp & 0x01) // IO
-						pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFD);
-					else // MEMORY
-						pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF);
-					*/
-					pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF);
-					pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]);
-
-					debug ("what is bar[count]? %x, count = %d\n", bar[count], count);
-
-					if (!bar[count])	/* This BAR is not implemented */
-						continue;
-
-					//tmp_bar = bar[count];
-
-					debug ("count %d device %x function %x wants %x resources \n", count, device, function, bar[count]);
-
-					if (bar[count] & PCI_BASE_ADDRESS_SPACE_IO) {
-						/* This is IO */
-						len[count] = bar[count] & 0xFFFFFFFC;
-						len[count] = ~len[count] + 1;
-						amount->io += len[count];
-					} else {
-						/* This is Memory */
-						if (bar[count] & PCI_BASE_ADDRESS_MEM_PREFETCH) {
-							/* pfmem */
-							len[count] = bar[count] & 0xFFFFFFF0;
-							len[count] = ~len[count] + 1;
-							amount->pfmem += len[count];
-							if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64)
-								/* takes up another dword */
-								count += 1;
-
-						} else {
-							/* regular memory */
-							len[count] = bar[count] & 0xFFFFFFF0;
-							len[count] = ~len[count] + 1;
-							amount->mem += len[count];
-							if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-								/* takes up another dword */
-								count += 1;
-							}
-						}
-					}
-				}	/* end for */
-			}	/* end if (valid) */
-		}	/* end for */
-	}	/* end for */
-
-	if (!howmany)
-		amount->not_correct = TRUE;
-	else
-		amount->not_correct = FALSE;
-	if ((amount->io) && (amount->io < IOBRIDGE))
-		amount->io = IOBRIDGE;
-	if ((amount->mem) && (amount->mem < MEMBRIDGE))
-		amount->mem = MEMBRIDGE;
-	if ((amount->pfmem) && (amount->pfmem < MEMBRIDGE))
-		amount->pfmem = MEMBRIDGE;
-	return amount;
-}
-
-/* The following 3 unconfigure_boot_ routines deal with the case when we had the card 
- * upon bootup in the system, since we don't allocate func to such case, we need to read 
- * the start addresses from pci config space and then find the corresponding entries in 
- * our resource lists.  The functions return either 0, -ENODEV, or -1 (general failure)
- * Change: we also call these functions even if we configured the card ourselves (i.e., not
- * the bootup case), since it should work same way
- */
-static int unconfigure_boot_device (u8 busno, u8 device, u8 function)
-{
-	u32 start_address;
-	u32 address[] = {
-		PCI_BASE_ADDRESS_0,
-		PCI_BASE_ADDRESS_1,
-		PCI_BASE_ADDRESS_2,
-		PCI_BASE_ADDRESS_3,
-		PCI_BASE_ADDRESS_4,
-		PCI_BASE_ADDRESS_5,
-		0
-	};
-	int count;
-	struct resource_node *io;
-	struct resource_node *mem;
-	struct resource_node *pfmem;
-	struct bus_node *bus;
-	u32 end_address;
-	u32 temp_end;
-	u32 size;
-	u32 tmp_address;
-	unsigned int devfn;
-
-	debug ("%s - enter\n", __FUNCTION__);
-
-	bus = ibmphp_find_res_bus (busno);
-	if (!bus) {
-		debug ("cannot find corresponding bus.\n");
-		return -EINVAL;
-	}
-
-	devfn = PCI_DEVFN(device, function);
-	ibmphp_pci_bus->number = busno;
-	for (count = 0; address[count]; count++) {	/* for 6 BARs */
-		pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &start_address);
-
-		/* We can do this here, b/c by that time the device driver of the card has been stopped */
-
-		pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF);
-		pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &size);
-		pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], start_address);
-
-		debug ("start_address is %x\n", start_address);
-		debug ("busno, device, function %x %x %x\n", busno, device, function);
-		if (!size) {
-			/* This BAR is not implemented */
-			debug ("is this bar no implemented?, count = %d\n", count);
-			continue;
-		}
-		tmp_address = start_address;
-		if (start_address & PCI_BASE_ADDRESS_SPACE_IO) {
-			/* This is IO */
-			start_address &= PCI_BASE_ADDRESS_IO_MASK;
-			size = size & 0xFFFFFFFC;
-			size = ~size + 1;
-			end_address = start_address + size - 1;
-			if (ibmphp_find_resource (bus, start_address, &io, IO) < 0) {
-				err ("cannot find corresponding IO resource to remove\n");
-				return -EIO;
-			}
-			debug ("io->start = %x\n", io->start);
-			temp_end = io->end;
-			start_address = io->end + 1;
-			ibmphp_remove_resource (io);
-			/* This is needed b/c of the old I/O restrictions in the BIOS */
-			while (temp_end < end_address) {
-				if (ibmphp_find_resource (bus, start_address, &io, IO) < 0) {
-					err ("cannot find corresponding IO resource to remove\n");
-					return -EIO;
-				}
-				debug ("io->start = %x\n", io->start);
-				temp_end = io->end;
-				start_address = io->end + 1;
-				ibmphp_remove_resource (io);
-			}
-
-			/* ????????? DO WE NEED TO WRITE ANYTHING INTO THE PCI CONFIG SPACE BACK ?????????? */
-		} else {
-			/* This is Memory */
-			if (start_address & PCI_BASE_ADDRESS_MEM_PREFETCH) {
-				/* pfmem */
-				start_address &= PCI_BASE_ADDRESS_MEM_MASK;
-				debug ("start address of pfmem is %x\n", start_address);
-
-				if (ibmphp_find_resource (bus, start_address, &pfmem, PFMEM) < 0) {
-					err ("cannot find corresponding PFMEM resource to remove\n");
-					return -EIO;
-				}
-				if (pfmem)
-					debug ("pfmem->start = %x\n", pfmem->start);
-
-				ibmphp_remove_resource (pfmem);
-
-				if (tmp_address & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-					/* takes up another dword */
-					count += 1;
-				}
-
-			} else {
-				/* regular memory */
-				start_address &= PCI_BASE_ADDRESS_MEM_MASK;
-				debug ("start address of mem is %x\n", start_address);
-				if (ibmphp_find_resource (bus, start_address, &mem, MEM) < 0) {
-					err ("cannot find corresponding MEM resource to remove\n");
-					return -EIO;
-				}
-				if (mem)
-					debug ("mem->start = %x\n", mem->start);
-
-				ibmphp_remove_resource (mem);
-
-				if (tmp_address & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-					/* takes up another dword */
-					count += 1;
-				}
-			}
-		}	/* end of mem */
-	}	/* end of for */
-
-	return 0;
-}
-
-static int unconfigure_boot_bridge (u8 busno, u8 device, u8 function)
-{
-	int count;
-	int bus_no, pri_no, sub_no, sec_no = 0;
-	u32 start_address, tmp_address;
-	u8 sec_number, sub_number, pri_number;
-	struct resource_node *io = NULL;
-	struct resource_node *mem = NULL;
-	struct resource_node *pfmem = NULL;
-	struct bus_node *bus;
-	u32 address[] = {
-		PCI_BASE_ADDRESS_0,
-		PCI_BASE_ADDRESS_1,
-		0
-	};
-	unsigned int devfn;
-
-	devfn = PCI_DEVFN(device, function);
-	ibmphp_pci_bus->number = busno;
-	bus_no = (int) busno;
-	debug ("busno is %x\n", busno);
-	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, &pri_number);
-	debug ("%s - busno = %x, primary_number = %x\n", __FUNCTION__, busno, pri_number);
-
-	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
-	debug ("sec_number is %x\n", sec_number);
-	sec_no = (int) sec_number;
-	pri_no = (int) pri_number;
-	if (pri_no != bus_no) {
-		err ("primary numbers in our structures and pci config space don't match.\n");
-		return -EINVAL;
-	}
-
-	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
-	sec_no = (int) sec_no;
-
-	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, &sub_number);
-	sub_no = (int) sub_number;
-	debug ("sub_no is %d, sec_no is %d\n", sub_no, sec_no);
-	if (sec_no != sub_number) {
-		err ("there're more buses behind this bridge.  Hot removal is not supported.  Please choose another card\n");
-		return -ENODEV;
-	}
-
-	bus = ibmphp_find_res_bus (sec_number);
-	debug ("bus->busno is %x\n", bus->busno);
-	debug ("sec_number is %x\n", sec_number);
-	if (!bus) {
-		err ("cannot find Bus structure for the bridged device\n");
-		return -EINVAL;
-	}
-
-	ibmphp_remove_bus (bus, busno);
-
-	for (count = 0; address[count]; count++) {
-		/* for 2 BARs */
-		pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &start_address);
-
-		if (!start_address) {
-			/* This BAR is not implemented */
-			continue;
-		}
-
-		tmp_address = start_address;
-
-		if (start_address & PCI_BASE_ADDRESS_SPACE_IO) {
-			/* This is IO */
-			start_address &= PCI_BASE_ADDRESS_IO_MASK;
-			if (ibmphp_find_resource (bus, start_address, &io, IO) < 0) {
-				err ("cannot find corresponding IO resource to remove\n");
-				return -EIO;
-			}
-			if (io)
-				debug ("io->start = %x\n", io->start);
-
-			ibmphp_remove_resource (io);
-
-			/* ????????? DO WE NEED TO WRITE ANYTHING INTO THE PCI CONFIG SPACE BACK ?????????? */
-		} else {
-			/* This is Memory */
-			if (start_address & PCI_BASE_ADDRESS_MEM_PREFETCH) {
-				/* pfmem */
-				start_address &= PCI_BASE_ADDRESS_MEM_MASK;
-				if (ibmphp_find_resource (bus, start_address, &pfmem, PFMEM) < 0) {
-					err ("cannot find corresponding PFMEM resource to remove\n");
-					return -EINVAL;
-				}
-				if (pfmem)
-					debug ("pfmem->start = %x\n", pfmem->start);
-
-				ibmphp_remove_resource (pfmem);
-
-				if (tmp_address & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-					/* takes up another dword */
-					count += 1;
-				}
-
-			} else {
-				/* regular memory */
-				start_address &= PCI_BASE_ADDRESS_MEM_MASK;
-				if (ibmphp_find_resource (bus, start_address, &mem, MEM) < 0) {
-					err ("cannot find corresponding MEM resource to remove\n");
-					return -EINVAL;
-				}
-				if (mem)
-					debug ("mem->start = %x\n", mem->start);
-
-				ibmphp_remove_resource (mem);
-
-				if (tmp_address & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-					/* takes up another dword */
-					count += 1;
-				}
-			}
-		}	/* end of mem */
-	}	/* end of for */
-	debug ("%s - exiting, returning success\n", __FUNCTION__);
-	return 0;
-}
-
-static int unconfigure_boot_card (struct slot *slot_cur)
-{
-	u16 vendor_id;
-	u32 class;
-	u8 hdr_type;
-	u8 device;
-	u8 busno;
-	u8 function;
-	int rc;
-	unsigned int devfn;
-	u8 valid_device = 0x00; /* To see if we are ever able to find valid device and read it */
-
-	debug ("%s - enter\n", __FUNCTION__);
-
-	device = slot_cur->device;
-	busno = slot_cur->bus;
-
-	debug ("b4 for loop, device is %x\n", device);
-	/* For every function on the card */
-	for (function = 0x0; function < 0x08; function++) {
-		devfn = PCI_DEVFN(device, function);
-		ibmphp_pci_bus->number = busno;
-
-		pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id);
-
-		if (vendor_id != PCI_VENDOR_ID_NOTVALID) {
-			/* found correct device!!! */
-			++valid_device;
-
-			debug ("%s - found correct device\n", __FUNCTION__);
-
-			/* header: x x x x x x x x
-			 *         | |___________|=> 1=PPB bridge, 0=normal device, 2=CardBus Bridge
-			 *         |_=> 0 = single function device, 1 = multi-function device
-			 */
-
-			pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type);
-			pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class);
-
-			debug ("hdr_type %x, class %x\n", hdr_type, class);
-			class >>= 8;	/* to take revision out, class = class.subclass.prog i/f */
-			if (class == PCI_CLASS_NOT_DEFINED_VGA) {
-				err ("The device %x function %x is VGA compatible and is not supported for hot removing. "
-				     "Please choose another device.\n", device, function);
-				return -ENODEV;
-			} else if (class == PCI_CLASS_DISPLAY_VGA) {
-				err ("The device %x function %x is not supported for hot removing. "
-				     "Please choose another device.\n", device, function);
-				return -ENODEV;
-			}
-
-			switch (hdr_type) {
-				case PCI_HEADER_TYPE_NORMAL:
-					rc = unconfigure_boot_device (busno, device, function);
-					if (rc) {
-						err ("was not able to unconfigure device %x func %x on bus %x. bailing out... \n",
-						     device, function, busno);
-						return rc;
-					}
-					function = 0x8;
-					break;
-				case PCI_HEADER_TYPE_MULTIDEVICE:
-					rc = unconfigure_boot_device (busno, device, function);
-					if (rc) {
-						err ("was not able to unconfigure device %x func %x on bus %x. bailing out... \n",
-						     device, function, busno);
-						return rc;
-					}
-					break;
-				case PCI_HEADER_TYPE_BRIDGE:
-					class >>= 8;
-					if (class != PCI_CLASS_BRIDGE_PCI) {
-						err ("This device %x function %x is not PCI-to-PCI bridge, "
-						     "and is not supported for hot-removing. "
-						     "Please try another card.\n", device, function);
-						return -ENODEV;
-					}
-					rc = unconfigure_boot_bridge (busno, device, function);
-					if (rc != 0) {
-						err ("was not able to hot-remove PPB properly.\n");
-						return rc;
-					}
-
-					function = 0x8;
-					break;
-				case PCI_HEADER_TYPE_MULTIBRIDGE:
-					class >>= 8;
-					if (class != PCI_CLASS_BRIDGE_PCI) {
-						err ("This device %x function %x is not PCI-to-PCI bridge, "
-						     "and is not supported for hot-removing. "
-						     "Please try another card.\n", device, function);
-						return -ENODEV;
-					}
-					rc = unconfigure_boot_bridge (busno, device, function);
-					if (rc != 0) {
-						err ("was not able to hot-remove PPB properly.\n");
-						return rc;
-					}
-					break;
-				default:
-					err ("MAJOR PROBLEM!!!! Cannot read device's header \n");
-					return -1;
-					break;
-			}	/* end of switch */
-		}	/* end of valid device */
-	}	/* end of for */
-
-	if (!valid_device) {
-		err ("Could not find device to unconfigure.  Or could not read the card. \n");
-		return -1;
-	}
-	return 0;
-}
-
-/*
- * free the resources of the card (multi, single, or bridged)
- * Parameters: slot, flag to say if this is for removing entire module or just
- * unconfiguring the device
- * TO DO:  will probably need to add some code in case there was some resource,
- * to remove it... this is from when we have errors in the configure_card...
- * 			!!!!!!!!!!!!!!!!!!!!!!!!!FOR BUSES!!!!!!!!!!!!
- * Returns: 0, -1, -ENODEV 
- */
-int ibmphp_unconfigure_card (struct slot **slot_cur, int the_end)
-{
-	int i;
-	int count;
-	int rc;
-	struct slot *sl = *slot_cur;
-	struct pci_func *cur_func = NULL;
-	struct pci_func *temp_func;
-
-	debug ("%s - enter\n", __FUNCTION__);
-
-	if (!the_end) {
-		/* Need to unconfigure the card */
-		rc = unconfigure_boot_card (sl);
-		if ((rc == -ENODEV) || (rc == -EIO) || (rc == -EINVAL)) {
-			/* In all other cases, will still need to get rid of func structure if it exists */
-			return rc;
-		}
-	}
-
-	if (sl->func) {
-		cur_func = sl->func;
-		while (cur_func) {
-			/* TO DO: WILL MOST LIKELY NEED TO GET RID OF THE BUS STRUCTURE FROM RESOURCES AS WELL */
-			if (cur_func->bus) {
-				/* in other words, it's a PPB */
-				count = 2;
-			} else {
-				count = 6;
-			}
-
-			for (i = 0; i < count; i++) {
-				if (cur_func->io[i]) {
-					debug ("io[%d] exists \n", i);
-					if (the_end > 0)
-						ibmphp_remove_resource (cur_func->io[i]);
-					cur_func->io[i] = NULL;
-				}
-				if (cur_func->mem[i]) {
-					debug ("mem[%d] exists \n", i);
-					if (the_end > 0)
-						ibmphp_remove_resource (cur_func->mem[i]);
-					cur_func->mem[i] = NULL;
-				}
-				if (cur_func->pfmem[i]) {
-					debug ("pfmem[%d] exists \n", i);
-					if (the_end > 0)
-						ibmphp_remove_resource (cur_func->pfmem[i]);
-					cur_func->pfmem[i] = NULL;
-				}
-			}
-
-			temp_func = cur_func->next;
-			kfree (cur_func);
-			cur_func = temp_func;
-		}
-	}
-
-	sl->func = NULL;
-	*slot_cur = sl;
-	debug ("%s - exit\n", __FUNCTION__);
-	return 0;
-}
-
-/*
- * add a new bus resulting from hot-plugging a PPB bridge with devices
- *
- * Input: bus and the amount of resources needed (we know we can assign those,
- *        since they've been checked already
- * Output: bus added to the correct spot
- *         0, -1, error 
- */
-static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct resource_node *mem, struct resource_node *pfmem, u8 parent_busno)
-{
-	struct range_node *io_range = NULL;
-	struct range_node *mem_range = NULL;
-	struct range_node *pfmem_range = NULL;
-	struct bus_node *cur_bus = NULL;
-
-	/* Trying to find the parent bus number */
-	if (parent_busno != 0xFF) {
-		cur_bus	= ibmphp_find_res_bus (parent_busno);
-		if (!cur_bus) {
-			err ("strange, cannot find bus which is supposed to be at the system... something is terribly wrong...\n");
-			return -ENODEV;
-		}
-	
-		list_add (&bus->bus_list, &cur_bus->bus_list);
-	}
-	if (io) {
-		io_range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
-		if (!io_range) {
-			err ("out of system memory \n");
-			return -ENOMEM;
-		}
-		memset (io_range, 0, sizeof (struct range_node));
-		io_range->start = io->start;
-		io_range->end = io->end;
-		io_range->rangeno = 1;
-		bus->noIORanges = 1;
-		bus->rangeIO = io_range;
-	}
-	if (mem) {
-		mem_range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
-		if (!mem_range) {
-			err ("out of system memory \n");
-			return -ENOMEM;
-		}
-		memset (mem_range, 0, sizeof (struct range_node));
-		mem_range->start = mem->start;
-		mem_range->end = mem->end;
-		mem_range->rangeno = 1;
-		bus->noMemRanges = 1;
-		bus->rangeMem = mem_range;
-	}
-	if (pfmem) {
-		pfmem_range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
-		if (!pfmem_range) {	
-			err ("out of system memory \n");
-			return -ENOMEM;
-		}
-		memset (pfmem_range, 0, sizeof (struct range_node));
-		pfmem_range->start = pfmem->start;
-		pfmem_range->end = pfmem->end;
-		pfmem_range->rangeno = 1;
-		bus->noPFMemRanges = 1;
-		bus->rangePFMem = pfmem_range;
-	}
-	return 0;
-}
-
-/*
- * find the 1st available bus number for PPB to set as its secondary bus
- * Parameters: bus_number of the primary bus
- * Returns: bus_number of the secondary bus or 0xff in case of failure
- */
-static u8 find_sec_number (u8 primary_busno, u8 slotno)
-{
-	int min, max;
-	u8 busno;
-	struct bus_info *bus;
-	struct bus_node *bus_cur;
-
-	bus = ibmphp_find_same_bus_num (primary_busno);
-	if (!bus) {
-		err ("cannot get slot range of the bus from the BIOS\n");
-		return 0xff;
-	}
-	max = bus->slot_max;
-	min = bus->slot_min;
-	if ((slotno > max) || (slotno < min)) {
-		err ("got the wrong range\n");
-		return 0xff;
-	}
-	busno = (u8) (slotno - (u8) min);
-	busno += primary_busno + 0x01;
-	bus_cur = ibmphp_find_res_bus (busno);
-	/* either there is no such bus number, or there are no ranges, which
-	 * can only happen if we removed the bridged device in previous load
-	 * of the driver, and now only have the skeleton bus struct
-	 */
-	if ((!bus_cur) || (!(bus_cur->rangeIO) && !(bus_cur->rangeMem) && !(bus_cur->rangePFMem)))
-		return busno;
-	return 0xff;
-}
-
diff -Nru a/drivers/hotplug/ibmphp_res.c b/drivers/hotplug/ibmphp_res.c
--- a/drivers/hotplug/ibmphp_res.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,2157 +0,0 @@
-/*
- * IBM Hot Plug Controller Driver
- *
- * Written By: Irene Zubarev, IBM Corporation
- *
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001,2002 IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <gregkh@us.ibm.com>
- *
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/list.h>
-#include <linux/init.h>
-#include "ibmphp.h"
-
-static int flags = 0;		/* for testing */
-
-static void update_resources (struct bus_node *bus_cur, int type, int rangeno);
-static int once_over (void);
-static int remove_ranges (struct bus_node *, struct bus_node *);
-static int update_bridge_ranges (struct bus_node **);
-static int add_range (int type, struct range_node *, struct bus_node *);
-static void fix_resources (struct bus_node *);
-static inline struct bus_node *find_bus_wprev (u8, struct bus_node **, u8);
-
-static LIST_HEAD(gbuses);
-LIST_HEAD(ibmphp_res_head);
-
-static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc * curr, u8 busno, int flag)
-{
-	struct bus_node * newbus;
-
-	if (!(curr) && !(flag)) {
-		err ("NULL pointer passed \n");
-		return NULL;
-	}
-
-	newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL);
-	if (!newbus) {
-		err ("out of system memory \n");
-		return NULL;
-	}
-
-	memset (newbus, 0, sizeof (struct bus_node));
-	if (flag)
-		newbus->busno = busno;
-	else
-		newbus->busno = curr->bus_num;
-	list_add_tail (&newbus->bus_list, &gbuses);
-	return newbus;
-}
-
-static struct resource_node * __init alloc_resources (struct ebda_pci_rsrc * curr)
-{
-	struct resource_node *rs;
-	
-	if (!curr) {
-		err ("NULL passed to allocate \n");
-		return NULL;
-	}
-
-	rs = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
-	if (!rs) {
-		err ("out of system memory \n");
-		return NULL;
-	}
-	memset (rs, 0, sizeof (struct resource_node));
-	rs->busno = curr->bus_num;
-	rs->devfunc = curr->dev_fun;
-	rs->start = curr->start_addr;
-	rs->end = curr->end_addr;
-	rs->len = curr->end_addr - curr->start_addr + 1;
-	return rs;
-}
-
-static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node **new_range, struct ebda_pci_rsrc *curr, int flag, u8 first_bus)
-{
-	struct bus_node * newbus;
-	struct range_node *newrange;
-	u8 num_ranges = 0;
-
-	if (first_bus) {
-		newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL);
-		if (!newbus) {
-			err ("out of system memory. \n");
-			return -ENOMEM;
-		}
-		memset (newbus, 0, sizeof (struct bus_node));
-		newbus->busno = curr->bus_num;
-	} else {
-		newbus = *new_bus;
-		switch (flag) {
-			case MEM:
-				num_ranges = newbus->noMemRanges;
-				break;
-			case PFMEM:
-				num_ranges = newbus->noPFMemRanges;
-				break;
-			case IO:
-				num_ranges = newbus->noIORanges;
-				break;
-		}
-	}
-
-	newrange = kmalloc (sizeof (struct range_node), GFP_KERNEL);
-	if (!newrange) {
-		if (first_bus)
-			kfree (newbus);
-		err ("out of system memory \n");
-		return -ENOMEM;
-	}
-	memset (newrange, 0, sizeof (struct range_node));
-	newrange->start = curr->start_addr;
-	newrange->end = curr->end_addr;
-		
-	if (first_bus || (!num_ranges))
-		newrange->rangeno = 1;
-	else {
-		/* need to insert our range */
-		add_range (flag, newrange, newbus);
-		debug ("%d resource Primary Bus inserted on bus %x [%x - %x]\n", flag, newbus->busno, newrange->start, newrange->end);
-	}
-
-	switch (flag) {
-		case MEM:
-			newbus->rangeMem = newrange;
-			if (first_bus)
-				newbus->noMemRanges = 1;
-			else {
-				debug ("First Memory Primary on bus %x, [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
-				++newbus->noMemRanges;
-				fix_resources (newbus);
-			}
-			break;
-		case IO:
-			newbus->rangeIO = newrange;
-			if (first_bus)
-				newbus->noIORanges = 1;
-			else {
-				debug ("First IO Primary on bus %x, [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
-				++newbus->noIORanges;
-				fix_resources (newbus);
-			}
-			break;
-		case PFMEM:
-			newbus->rangePFMem = newrange;
-			if (first_bus)
-				newbus->noPFMemRanges = 1;
-			else {	
-				debug ("1st PFMemory Primary on Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
-				++newbus->noPFMemRanges;
-				fix_resources (newbus);
-			}
-
-			break;
-	}
-
-	*new_bus = newbus;
-	*new_range = newrange;
-	return 0;
-}
-
-
-/* Notes:
- * 1. The ranges are ordered.  The buses are not ordered.  (First come)
- *
- * 2. If cannot allocate out of PFMem range, allocate from Mem ranges.  PFmemFromMem
- * are not sorted. (no need since use mem node). To not change the entire code, we
- * also add mem node whenever this case happens so as not to change
- * ibmphp_check_mem_resource etc (and since it really is taking Mem resource)
- */
-
-/*****************************************************************************
- * This is the Resource Management initialization function.  It will go through
- * the Resource list taken from EBDA and fill in this module's data structures
- *
- * THIS IS NOT TAKING INTO CONSIDERATION IO RESTRICTIONS OF PRIMARY BUSES, 
- * SINCE WE'RE GOING TO ASSUME FOR NOW WE DON'T HAVE THOSE ON OUR BUSES FOR NOW
- *
- * Input: ptr to the head of the resource list from EBDA
- * Output: 0, -1 or error codes
- ***************************************************************************/
-int __init ibmphp_rsrc_init (void)
-{
-	struct ebda_pci_rsrc *curr;
-	struct range_node *newrange = NULL;
-	struct bus_node *newbus = NULL;
-	struct bus_node *bus_cur;
-	struct bus_node *bus_prev;
-	struct list_head *tmp;
-	struct resource_node *new_io = NULL;
-	struct resource_node *new_mem = NULL;
-	struct resource_node *new_pfmem = NULL;
-	int rc;
-	struct list_head *tmp_ebda;
-
-	list_for_each (tmp_ebda, &ibmphp_ebda_pci_rsrc_head) {
-		curr = list_entry (tmp_ebda, struct ebda_pci_rsrc, ebda_pci_rsrc_list);
-		if (!(curr->rsrc_type & PCIDEVMASK)) {
-			/* EBDA still lists non PCI devices, so ignore... */
-			debug ("this is not a PCI DEVICE in rsrc_init, please take care\n");
-			// continue;
-		}
-
-		/* this is a primary bus resource */
-		if (curr->rsrc_type & PRIMARYBUSMASK) {
-			/* memory */
-			if ((curr->rsrc_type & RESTYPE) == MMASK) {
-				/* no bus structure exists in place yet */
-				if (list_empty (&gbuses)) {
-					if ((rc = alloc_bus_range (&newbus, &newrange, curr, MEM, 1)))
-						return rc;
-					list_add_tail (&newbus->bus_list, &gbuses);
-					debug ("gbuses = NULL, Memory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
-				} else {
-					bus_cur = find_bus_wprev (curr->bus_num, &bus_prev, 1);
-					/* found our bus */
-					if (bus_cur) {
-						rc = alloc_bus_range (&bus_cur, &newrange, curr, MEM, 0);
-						if (rc)
-							return rc;
-					} else {
-						/* went through all the buses and didn't find ours, need to create a new bus node */
-						if ((rc = alloc_bus_range (&newbus, &newrange, curr, MEM, 1)))
-							return rc;
-
-						list_add_tail (&newbus->bus_list, &gbuses);
-						debug ("New Bus, Memory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
-					}
-				}
-			} else if ((curr->rsrc_type & RESTYPE) == PFMASK) {
-				/* prefetchable memory */
-				if (list_empty (&gbuses)) {
-					/* no bus structure exists in place yet */
-					if ((rc = alloc_bus_range (&newbus, &newrange, curr, PFMEM, 1)))
-						return rc;
-					list_add_tail (&newbus->bus_list, &gbuses);
-					debug ("gbuses = NULL, PFMemory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
-				} else {
-					bus_cur = find_bus_wprev (curr->bus_num, &bus_prev, 1);
-					if (bus_cur) {
-						/* found our bus */
-						rc = alloc_bus_range (&bus_cur, &newrange, curr, PFMEM, 0);
-						if (rc)
-							return rc;
-					} else {
-						/* went through all the buses and didn't find ours, need to create a new bus node */
-						if ((rc = alloc_bus_range (&newbus, &newrange, curr, PFMEM, 1)))
-							return rc;
-						list_add_tail (&newbus->bus_list, &gbuses);
-						debug ("1st Bus, PFMemory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
-					}
-				}
-			} else if ((curr->rsrc_type & RESTYPE) == IOMASK) {
-				/* IO */
-				if (list_empty (&gbuses)) {
-					/* no bus structure exists in place yet */
-					if ((rc = alloc_bus_range (&newbus, &newrange, curr, IO, 1)))
-						return rc;
-					list_add_tail (&newbus->bus_list, &gbuses);
-					debug ("gbuses = NULL, IO Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
-				} else {
-					bus_cur = find_bus_wprev (curr->bus_num, &bus_prev, 1);
-					if (bus_cur) {
-						rc = alloc_bus_range (&bus_cur, &newrange, curr, IO, 0);
-						if (rc)
-							return rc;
-					} else {
-						/* went through all the buses and didn't find ours, need to create a new bus node */
-						if ((rc = alloc_bus_range (&newbus, &newrange, curr, IO, 1)))
-							return rc;
-						list_add_tail (&newbus->bus_list, &gbuses);
-						debug ("1st Bus, IO Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
-					}
-				}
-
-			} else {
-				;	/* type is reserved  WHAT TO DO IN THIS CASE???
-					   NOTHING TO DO??? */
-			}
-		} else {
-			/* regular pci device resource */
-			if ((curr->rsrc_type & RESTYPE) == MMASK) {
-				/* Memory resource */
-				new_mem = alloc_resources (curr);
-				if (!new_mem)
-					return -ENOMEM;
-				new_mem->type = MEM;
-				/*
-				 * if it didn't find the bus, means PCI dev
-				 * came b4 the Primary Bus info, so need to
-				 * create a bus rangeno becomes a problem...
-				 * assign a -1 and then update once the range
-				 * actually appears...
-				 */
-				if (ibmphp_add_resource (new_mem) < 0) {
-					newbus = alloc_error_bus (curr, 0, 0);
-					if (!newbus)
-						return -ENOMEM;
-					newbus->firstMem = new_mem;
-					++newbus->needMemUpdate;
-					new_mem->rangeno = -1;
-				}
-				debug ("Memory resource for device %x, bus %x, [%x - %x]\n", new_mem->devfunc, new_mem->busno, new_mem->start, new_mem->end);
-
-			} else if ((curr->rsrc_type & RESTYPE) == PFMASK) {
-				/* PFMemory resource */
-				new_pfmem = alloc_resources (curr);
-				if (!new_pfmem)
-					return -ENOMEM;
-				new_pfmem->type = PFMEM;
-				new_pfmem->fromMem = FALSE;
-				if (ibmphp_add_resource (new_pfmem) < 0) {
-					newbus = alloc_error_bus (curr, 0, 0);
-					if (!newbus)
-						return -ENOMEM;
-					newbus->firstPFMem = new_pfmem;
-					++newbus->needPFMemUpdate;
-					new_pfmem->rangeno = -1;
-				}
-
-				debug ("PFMemory resource for device %x, bus %x, [%x - %x]\n", new_pfmem->devfunc, new_pfmem->busno, new_pfmem->start, new_pfmem->end);
-			} else if ((curr->rsrc_type & RESTYPE) == IOMASK) {
-				/* IO resource */
-				new_io = alloc_resources (curr);
-				if (!new_io)
-					return -ENOMEM;
-				new_io->type = IO;
-
-				/*
-				 * if it didn't find the bus, means PCI dev
-				 * came b4 the Primary Bus info, so need to
-				 * create a bus rangeno becomes a problem...
-				 * Can assign a -1 and then update once the
-				 * range actually appears...
-				 */
-				if (ibmphp_add_resource (new_io) < 0) {
-					newbus = alloc_error_bus (curr, 0, 0);
-					if (!newbus)
-						return -ENOMEM;
-					newbus->firstIO = new_io;
-					++newbus->needIOUpdate;
-					new_io->rangeno = -1;
-				}
-				debug ("IO resource for device %x, bus %x, [%x - %x]\n", new_io->devfunc, new_io->busno, new_io->start, new_io->end);
-			}
-		}
-	}
-
-	list_for_each (tmp, &gbuses) {
-		bus_cur = list_entry (tmp, struct bus_node, bus_list);
-		/* This is to get info about PPB resources, since EBDA doesn't put this info into the primary bus info */
-		rc = update_bridge_ranges (&bus_cur);
-		if (rc)
-			return rc;
-	}
-	rc = once_over ();  /* This is to align ranges (so no -1) */
-	if (rc)
-		return rc;
-	return 0;
-}
-
-/********************************************************************************
- * This function adds a range into a sorted list of ranges per bus for a particular
- * range type, it then calls another routine to update the range numbers on the
- * pci devices' resources for the appropriate resource
- *
- * Input: type of the resource, range to add, current bus
- * Output: 0 or -1, bus and range ptrs 
- ********************************************************************************/
-static int add_range (int type, struct range_node *range, struct bus_node *bus_cur)
-{
-	struct range_node *range_cur = NULL;
-	struct range_node *range_prev;
-	int count = 0, i_init;
-	int noRanges = 0;
-
-	switch (type) {
-		case MEM:
-			range_cur = bus_cur->rangeMem;
-			noRanges = bus_cur->noMemRanges;
-			break;
-		case PFMEM:
-			range_cur = bus_cur->rangePFMem;
-			noRanges = bus_cur->noPFMemRanges;
-			break;
-		case IO:
-			range_cur = bus_cur->rangeIO;
-			noRanges = bus_cur->noIORanges;
-			break;
-	}
-
-	range_prev = NULL;
-	while (range_cur) {
-		if (range->start < range_cur->start)
-			break;
-		range_prev = range_cur;
-		range_cur = range_cur->next;
-		count = count + 1;
-	}
-	if (!count) {
-		/* our range will go at the beginning of the list */
-		switch (type) {
-			case MEM:
-				bus_cur->rangeMem = range;
-				break;
-			case PFMEM:
-				bus_cur->rangePFMem = range;
-				break;
-			case IO:
-				bus_cur->rangeIO = range;
-				break;
-		}
-		range->next = range_cur;
-		range->rangeno = 1;
-		i_init = 0;
-	} else if (!range_cur) {
-		/* our range will go at the end of the list */
-		range->next = NULL;
-		range_prev->next = range;
-		range->rangeno = range_prev->rangeno + 1;
-		return 0;
-	} else {
-		/* the range is in the middle */
-		range_prev->next = range;
-		range->next = range_cur;
-		range->rangeno = range_cur->rangeno;
-		i_init = range_prev->rangeno;
-	}
-
-	for (count = i_init; count < noRanges; ++count) {
-		++range_cur->rangeno;
-		range_cur = range_cur->next;
-	}
-
-	update_resources (bus_cur, type, i_init + 1);
-	return 0;
-}
-
-/*******************************************************************************
- * This routine goes through the list of resources of type 'type' and updates
- * the range numbers that they correspond to.  It was called from add_range fnc
- *
- * Input: bus, type of the resource, the rangeno starting from which to update
- ******************************************************************************/
-static void update_resources (struct bus_node *bus_cur, int type, int rangeno)
-{
-	struct resource_node *res = NULL;
-	u8 eol = FALSE;	/* end of list indicator */
-
-	switch (type) {
-		case MEM:
-			if (bus_cur->firstMem) 
-				res = bus_cur->firstMem;
-			break;
-		case PFMEM:
-			if (bus_cur->firstPFMem)
-				res = bus_cur->firstPFMem;
-			break;
-		case IO:
-			if (bus_cur->firstIO)
-				res = bus_cur->firstIO;
-			break;
-	}
-
-	if (res) {
-		while (res) {
-			if (res->rangeno == rangeno)
-				break;
-			if (res->next)
-				res = res->next;
-			else if (res->nextRange)
-				res = res->nextRange;
-			else {
-				eol = TRUE;
-				break;
-			}
-		}
-
-		if (!eol) {
-			/* found the range */
-			while (res) {
-				++res->rangeno;
-				res = res->next;
-			}
-		}
-	}
-}
-
-static void fix_me (struct resource_node *res, struct bus_node *bus_cur, struct range_node *range)
-{
-	char * str = "";
-	switch (res->type) {
-		case IO:
-			str = "io";
-			break;
-		case MEM:
-			str = "mem";
-			break;
-		case PFMEM:
-			str = "pfmem";
-			break;
-	}
-
-	while (res) {
-		if (res->rangeno == -1) {
-			while (range) {
-				if ((res->start >= range->start) && (res->end <= range->end)) {
-					res->rangeno = range->rangeno;
-					debug ("%s->rangeno in fix_resources is %d\n", str, res->rangeno);
-					switch (res->type) {
-						case IO:
-							--bus_cur->needIOUpdate;
-							break;
-						case MEM:
-							--bus_cur->needMemUpdate;
-							break;
-						case PFMEM:
-							--bus_cur->needPFMemUpdate;
-							break;
-					}
-					break;
-				}
-				range = range->next;
-			}
-		}
-		if (res->next)
-			res = res->next;
-		else
-			res = res->nextRange;
-	}
-
-}
-
-/*****************************************************************************
- * This routine reassigns the range numbers to the resources that had a -1
- * This case can happen only if upon initialization, resources taken by pci dev
- * appear in EBDA before the resources allocated for that bus, since we don't
- * know the range, we assign -1, and this routine is called after a new range
- * is assigned to see the resources with unknown range belong to the added range
- *
- * Input: current bus
- * Output: none, list of resources for that bus are fixed if can be
- *******************************************************************************/
-static void fix_resources (struct bus_node *bus_cur)
-{
-	struct range_node *range;
-	struct resource_node *res;
-
-	debug ("%s - bus_cur->busno = %d\n", __FUNCTION__, bus_cur->busno);
-
-	if (bus_cur->needIOUpdate) {
-		res = bus_cur->firstIO;
-		range = bus_cur->rangeIO;
-		fix_me (res, bus_cur, range);
-	}
-	if (bus_cur->needMemUpdate) {
-		res = bus_cur->firstMem;
-		range = bus_cur->rangeMem;
-		fix_me (res, bus_cur, range);
-	}
-	if (bus_cur->needPFMemUpdate) {
-		res = bus_cur->firstPFMem;
-		range = bus_cur->rangePFMem;
-		fix_me (res, bus_cur, range);
-	}
-}
-
-/*******************************************************************************
- * This routine adds a resource to the list of resources to the appropriate bus 
- * based on their resource type and sorted by their starting addresses.  It assigns
- * the ptrs to next and nextRange if needed.
- *
- * Input: resource ptr
- * Output: ptrs assigned (to the node)
- * 0 or -1
- *******************************************************************************/
-int ibmphp_add_resource (struct resource_node *res)
-{
-	struct resource_node *res_cur;
-	struct resource_node *res_prev;
-	struct bus_node *bus_cur;
-	struct range_node *range_cur = NULL;
-	struct resource_node *res_start = NULL;
-
-	debug ("%s - enter\n", __FUNCTION__);
-
-	if (!res) {
-		err ("NULL passed to add \n");
-		return -ENODEV;
-	}
-	
-	bus_cur = find_bus_wprev (res->busno, NULL, 0);
-	
-	if (!bus_cur) {
-		/* didn't find a bus, smth's wrong!!! */
-		debug ("no bus in the system, either pci_dev's wrong or allocation failed\n");
-		return -ENODEV;
-	}
-
-	/* Normal case */
-	switch (res->type) {
-		case IO:
-			range_cur = bus_cur->rangeIO;
-			res_start = bus_cur->firstIO;
-			break;
-		case MEM:
-			range_cur = bus_cur->rangeMem;
-			res_start = bus_cur->firstMem;
-			break;
-		case PFMEM:
-			range_cur = bus_cur->rangePFMem;
-			res_start = bus_cur->firstPFMem;
-			break;
-		default:
-			err ("cannot read the type of the resource to add... problem \n");
-			return -EINVAL;
-	}
-	while (range_cur) {
-		if ((res->start >= range_cur->start) && (res->end <= range_cur->end)) {
-			res->rangeno = range_cur->rangeno;
-			break;
-		}
-		range_cur = range_cur->next;
-	}
-
-	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-	 * this is again the case of rangeno = -1
-	 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-	 */
-
-	if (!range_cur) {
-		switch (res->type) {
-			case IO:
-				++bus_cur->needIOUpdate;					
-				break;
-			case MEM:
-				++bus_cur->needMemUpdate;
-				break;
-			case PFMEM:
-				++bus_cur->needPFMemUpdate;
-				break;
-		}
-		res->rangeno = -1;
-	}
-	
-	debug ("The range is %d\n", res->rangeno);
-	if (!res_start) {
-		/* no first{IO,Mem,Pfmem} on the bus, 1st IO/Mem/Pfmem resource ever */
-		switch (res->type) {
-			case IO:
-				bus_cur->firstIO = res;					
-				break;
-			case MEM:
-				bus_cur->firstMem = res;
-				break;
-			case PFMEM:
-				bus_cur->firstPFMem = res;
-				break;
-		}	
-		res->next = NULL;
-		res->nextRange = NULL;
-	} else {
-		res_cur = res_start;
-		res_prev = NULL;
-
-		debug ("res_cur->rangeno is %d\n", res_cur->rangeno);
-
-		while (res_cur) {
-			if (res_cur->rangeno >= res->rangeno)
-				break;
-			res_prev = res_cur;
-			if (res_cur->next)
-				res_cur = res_cur->next;
-			else
-				res_cur = res_cur->nextRange;
-		}
-
-		if (!res_cur) {
-			/* at the end of the resource list */
-			debug ("i should be here, [%x - %x]\n", res->start, res->end);
-			res_prev->nextRange = res;
-			res->next = NULL;
-			res->nextRange = NULL;
-		} else if (res_cur->rangeno == res->rangeno) {
-			/* in the same range */
-			while (res_cur) {
-				if (res->start < res_cur->start)
-					break;
-				res_prev = res_cur;
-				res_cur = res_cur->next;
-			}
-			if (!res_cur) {
-				/* the last resource in this range */
-				res_prev->next = res;
-				res->next = NULL;
-				res->nextRange = res_prev->nextRange;
-				res_prev->nextRange = NULL;
-			} else if (res->start < res_cur->start) {
-				/* at the beginning or middle of the range */
-				if (!res_prev)	{
-					switch (res->type) {
-						case IO:
-							bus_cur->firstIO = res;
-							break;
-						case MEM:
-							bus_cur->firstMem = res;
-							break;
-						case PFMEM:
-							bus_cur->firstPFMem = res;
-							break;
-					}
-				} else if (res_prev->rangeno == res_cur->rangeno)
-					res_prev->next = res;
-				else
-					res_prev->nextRange = res;
-
-				res->next = res_cur;
-				res->nextRange = NULL;
-			}
-		} else {
-			/* this is the case where it is 1st occurrence of the range */
-			if (!res_prev) {
-				/* at the beginning of the resource list */
-				res->next = NULL;
-				switch (res->type) {
-					case IO:
-						res->nextRange = bus_cur->firstIO;
-						bus_cur->firstIO = res;
-						break;
-					case MEM:
-						res->nextRange = bus_cur->firstMem;
-						bus_cur->firstMem = res;
-						break;
-					case PFMEM:
-						res->nextRange = bus_cur->firstPFMem;
-						bus_cur->firstPFMem = res;
-						break;
-				}
-			} else if (res_cur->rangeno > res->rangeno) {
-				/* in the middle of the resource list */
-				res_prev->nextRange = res;
-				res->next = NULL;
-				res->nextRange = res_cur;
-			}
-		}
-	}
-
-	debug ("%s - exit\n", __FUNCTION__);
-	return 0;
-}
-
-/****************************************************************************
- * This routine will remove the resource from the list of resources
- *
- * Input: io, mem, and/or pfmem resource to be deleted
- * Ouput: modified resource list
- *        0 or error code
- ****************************************************************************/
-int ibmphp_remove_resource (struct resource_node *res)
-{
-	struct bus_node *bus_cur;
-	struct resource_node *res_cur = NULL;
-	struct resource_node *res_prev;
-	struct resource_node *mem_cur;
-	char * type = "";
-
-	if (!res)  {
-		err ("resource to remove is NULL \n");
-		return -ENODEV;
-	}
-
-	bus_cur = find_bus_wprev (res->busno, NULL, 0);
-
-	if (!bus_cur) {
-		err ("cannot find corresponding bus of the io resource to remove  "
-			"bailing out...\n");
-		return -ENODEV;
-	}
-
-	switch (res->type) {
-		case IO:
-			res_cur = bus_cur->firstIO;
-			type = "io";
-			break;
-		case MEM:
-			res_cur = bus_cur->firstMem;
-			type = "mem";
-			break;
-		case PFMEM:
-			res_cur = bus_cur->firstPFMem;
-			type = "pfmem";
-			break;
-		default:
-			err ("unknown type for resource to remove \n");
-			return -EINVAL;
-	}
-	res_prev = NULL;
-
-	while (res_cur) {
-		if ((res_cur->start == res->start) && (res_cur->end == res->end))
-			break;
-		res_prev = res_cur;
-		if (res_cur->next)
-			res_cur = res_cur->next;
-		else
-			res_cur = res_cur->nextRange;
-	}
-
-	if (!res_cur) {
-		if (res->type == PFMEM) {
-			/* 
-			 * case where pfmem might be in the PFMemFromMem list
-			 * so will also need to remove the corresponding mem
-			 * entry
-			 */
-			res_cur = bus_cur->firstPFMemFromMem;
-			res_prev = NULL;
-
-			while (res_cur) {
-				if ((res_cur->start == res->start) && (res_cur->end == res->end)) {
-					mem_cur = bus_cur->firstMem;
-					while (mem_cur) {
-						if ((mem_cur->start == res_cur->start)
-						    && (mem_cur->end == res_cur->end))
-							break;
-						if (mem_cur->next)
-							mem_cur = mem_cur->next;
-						else
-							mem_cur = mem_cur->nextRange;
-					}
-					if (!mem_cur) {
-						err ("cannot find corresponding mem node for pfmem...\n");
-						return -EINVAL;
-					}
-
-					ibmphp_remove_resource (mem_cur);
-					if (!res_prev)
-						bus_cur->firstPFMemFromMem = res_cur->next;
-					else
-						res_prev->next = res_cur->next;
-					kfree (res_cur);
-					return 0;
-				}
-				res_prev = res_cur;
-				if (res_cur->next)
-					res_cur = res_cur->next;
-				else
-					res_cur = res_cur->nextRange;
-			}
-			if (!res_cur) {
-				err ("cannot find pfmem to delete...\n");
-				return -EINVAL;
-			}
-		} else {
-			err ("the %s resource is not in the list to be deleted...\n", type);
-			return -EINVAL;
-		}
-	}
-	if (!res_prev) {
-		/* first device to be deleted */
-		if (res_cur->next) {
-			switch (res->type) {
-				case IO:
-					bus_cur->firstIO = res_cur->next;
-					break;
-				case MEM:
-					bus_cur->firstMem = res_cur->next;
-					break;
-				case PFMEM:
-					bus_cur->firstPFMem = res_cur->next;
-					break;
-			}
-		} else if (res_cur->nextRange) {
-			switch (res->type) {
-				case IO:
-					bus_cur->firstIO = res_cur->nextRange;
-					break;
-				case MEM:
-					bus_cur->firstMem = res_cur->nextRange;
-					break;
-				case PFMEM:
-					bus_cur->firstPFMem = res_cur->nextRange;
-					break;
-			}
-		} else {
-			switch (res->type) {
-				case IO:
-					bus_cur->firstIO = NULL;
-					break;
-				case MEM:
-					bus_cur->firstMem = NULL;
-					break;
-				case PFMEM:
-					bus_cur->firstPFMem = NULL;
-					break;
-			}
-		}
-		kfree (res_cur);
-		return 0;
-	} else {
-		if (res_cur->next) {
-			if (res_prev->rangeno == res_cur->rangeno)
-				res_prev->next = res_cur->next;
-			else
-				res_prev->nextRange = res_cur->next;
-		} else if (res_cur->nextRange) {
-			res_prev->next = NULL;
-			res_prev->nextRange = res_cur->nextRange;
-		} else {
-			res_prev->next = NULL;
-			res_prev->nextRange = NULL;
-		}
-		kfree (res_cur);
-		return 0;
-	}
-
-	return 0;
-}
-
-static struct range_node * find_range (struct bus_node *bus_cur, struct resource_node * res)
-{
-	struct range_node * range = NULL;
-
-	switch (res->type) {
-		case IO:
-			range = bus_cur->rangeIO;
-			break;
-		case MEM:
-			range = bus_cur->rangeMem;
-			break;
-		case PFMEM:
-			range = bus_cur->rangePFMem;
-			break;
-		default:
-			err ("cannot read resource type in find_range \n");
-	}
-
-	while (range) {
-		if (res->rangeno == range->rangeno)
-			break;
-		range = range->next;
-	}
-	return range;
-}
-
-/*****************************************************************************
- * This routine will check to make sure the io/mem/pfmem->len that the device asked for 
- * can fit w/i our list of available IO/MEM/PFMEM resources.  If cannot, returns -EINVAL,
- * otherwise, returns 0
- *
- * Input: resource
- * Ouput: the correct start and end address are inputted into the resource node,
- *        0 or -EINVAL
- *****************************************************************************/
-int ibmphp_check_resource (struct resource_node *res, u8 bridge)
-{
-	struct bus_node *bus_cur;
-	struct range_node *range = NULL;
-	struct resource_node *res_prev;
-	struct resource_node *res_cur = NULL;
-	u32 len_cur = 0, start_cur = 0, len_tmp = 0;
-	int noranges = 0;
-	u32 tmp_start;		/* this is to make sure start address is divisible by the length needed */
-	u32 tmp_divide;
-	u8 flag = FALSE;
-
-	if (!res)
-		return -EINVAL;
-
-	if (bridge) {
-		/* The rules for bridges are different, 4K divisible for IO, 1M for (pf)mem*/
-		if (res->type == IO)
-			tmp_divide = IOBRIDGE;
-		else
-			tmp_divide = MEMBRIDGE;
-	} else
-		tmp_divide = res->len;
-
-	bus_cur = find_bus_wprev (res->busno, NULL, 0);
-
-	if (!bus_cur) {
-		/* didn't find a bus, smth's wrong!!! */
-		debug ("no bus in the system, either pci_dev's wrong or allocation failed \n");
-		return -EINVAL;
-	}
-
-	debug ("%s - enter\n", __FUNCTION__);
-	debug ("bus_cur->busno is %d\n", bus_cur->busno);
-
-	/* This is a quick fix to not mess up with the code very much.  i.e.,
-	 * 2000-2fff, len = 1000, but when we compare, we need it to be fff */
-	res->len -= 1;
-
-	switch (res->type) {
-		case IO:
-			res_cur = bus_cur->firstIO;
-			noranges = bus_cur->noIORanges;
-			break;
-		case MEM:
-			res_cur = bus_cur->firstMem;
-			noranges = bus_cur->noMemRanges;
-			break;
-		case PFMEM:
-			res_cur = bus_cur->firstPFMem;
-			noranges = bus_cur->noPFMemRanges;
-			break;
-		default:
-			err ("wrong type of resource to check \n");
-			return -EINVAL;
-	}
-	res_prev = NULL;
-
-	while (res_cur) {
-		range = find_range (bus_cur, res_cur);
-		debug ("%s - rangeno = %d\n", __FUNCTION__, res_cur->rangeno);
-
-		if (!range) {
-			err ("no range for the device exists... bailing out...\n");
-			return -EINVAL;
-		}
-
-		/* found our range */
-		if (!res_prev) {
-			/* first time in the loop */
-			if ((res_cur->start != range->start) && ((len_tmp = res_cur->start - 1 - range->start) >= res->len)) {
-				debug ("len_tmp = %x\n", len_tmp);
-
-				if ((len_tmp < len_cur) || (len_cur == 0)) {
-
-					if ((range->start % tmp_divide) == 0) {
-						/* just perfect, starting address is divisible by length */
-						flag = TRUE;
-						len_cur = len_tmp;
-						start_cur = range->start;
-					} else {
-						/* Needs adjusting */
-						tmp_start = range->start;
-						flag = FALSE;
-
-						while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
-							if ((tmp_start % tmp_divide) == 0) {
-								flag = TRUE;
-								len_cur = len_tmp;
-								start_cur = tmp_start;
-								break;
-							}
-							tmp_start += tmp_divide - tmp_start % tmp_divide;
-							if (tmp_start >= res_cur->start - 1)
-								break;
-						}
-					}
-			
-					if (flag && len_cur == res->len) {
-						debug ("but we are not here, right?\n");
-						res->start = start_cur;
-						res->len += 1; /* To restore the balance */
-						res->end = res->start + res->len - 1;
-						return 0;
-					}
-				}
-			}
-		}
-		if (!res_cur->next) {
-			/* last device on the range */
-			if ((range->end != res_cur->end) && ((len_tmp = range->end - (res_cur->end + 1)) >= res->len)) {
-				debug ("len_tmp = %x\n", len_tmp);
-				if ((len_tmp < len_cur) || (len_cur == 0)) {
-
-					if (((res_cur->end + 1) % tmp_divide) == 0) {
-						/* just perfect, starting address is divisible by length */
-						flag = TRUE;
-						len_cur = len_tmp;
-						start_cur = res_cur->end + 1;
-					} else {
-						/* Needs adjusting */
-						tmp_start = res_cur->end + 1;
-						flag = FALSE;
-
-						while ((len_tmp = range->end - tmp_start) >= res->len) {
-							if ((tmp_start % tmp_divide) == 0) {
-								flag = TRUE;
-								len_cur = len_tmp;
-								start_cur = tmp_start;
-								break;
-							}
-							tmp_start += tmp_divide - tmp_start % tmp_divide;
-							if (tmp_start >= range->end)
-								break;
-						}
-					}
-					if (flag && len_cur == res->len) {
-						res->start = start_cur;
-						res->len += 1; /* To restore the balance */
-						res->end = res->start + res->len - 1;
-						return 0;
-					}
-				}
-			}
-		}
-
-		if (res_prev) {
-			if (res_prev->rangeno != res_cur->rangeno) {
-				/* 1st device on this range */
-				if ((res_cur->start != range->start) && 
-					((len_tmp = res_cur->start - 1 - range->start) >= res->len)) {
-					if ((len_tmp < len_cur) || (len_cur == 0)) {
-						if ((range->start % tmp_divide) == 0) {	
-							/* just perfect, starting address is divisible by length */
-							flag = TRUE;
-							len_cur = len_tmp;
-							start_cur = range->start;
-						} else {
-							/* Needs adjusting */
-							tmp_start = range->start;
-							flag = FALSE;
-
-							while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
-								if ((tmp_start % tmp_divide) == 0) {
-									flag = TRUE;
-									len_cur = len_tmp;
-									start_cur = tmp_start;
-									break;
-								}
-								tmp_start += tmp_divide - tmp_start % tmp_divide;
-								if (tmp_start >= res_cur->start - 1)
-									break;
-							}
-						}
-
-						if (flag && len_cur == res->len) {
-							res->start = start_cur;
-							res->len += 1; /* To restore the balance */
-							res->end = res->start + res->len - 1;
-							return 0;
-						}
-					}
-				}
-			} else {
-				/* in the same range */
-				if ((len_tmp = res_cur->start - 1 - res_prev->end - 1) >= res->len) {
-					if ((len_tmp < len_cur) || (len_cur == 0)) {
-						if (((res_prev->end + 1) % tmp_divide) == 0) {
-							/* just perfect, starting address's divisible by length */
-							flag = TRUE;
-							len_cur = len_tmp;
-							start_cur = res_prev->end + 1;
-						} else {
-							/* Needs adjusting */
-							tmp_start = res_prev->end + 1;
-							flag = FALSE;
-
-							while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
-								if ((tmp_start % tmp_divide) == 0) {
-									flag = TRUE;
-									len_cur = len_tmp;
-									start_cur = tmp_start;
-									break;
-								}
-								tmp_start += tmp_divide - tmp_start % tmp_divide;
-								if (tmp_start >= res_cur->start - 1)
-									break;
-							}
-						}
-
-						if (flag && len_cur == res->len) {
-							res->start = start_cur;
-							res->len += 1; /* To restore the balance */
-							res->end = res->start + res->len - 1;
-							return 0;
-						}
-					}
-				}
-			}
-		}
-		/* end if (res_prev) */
-		res_prev = res_cur;
-		if (res_cur->next)
-			res_cur = res_cur->next;
-		else
-			res_cur = res_cur->nextRange;
-	}	/* end of while */
-
-
-	if (!res_prev) {
-		/* 1st device ever */
-		/* need to find appropriate range */
-		switch (res->type) {
-			case IO:
-				range = bus_cur->rangeIO;
-				break;
-			case MEM:
-				range = bus_cur->rangeMem;
-				break;
-			case PFMEM:
-				range = bus_cur->rangePFMem;
-				break;
-		}
-		while (range) {
-			if ((len_tmp = range->end - range->start) >= res->len) {
-				if ((len_tmp < len_cur) || (len_cur == 0)) {
-					if ((range->start % tmp_divide) == 0) {
-						/* just perfect, starting address's divisible by length */
-						flag = TRUE;
-						len_cur = len_tmp;
-						start_cur = range->start;
-					} else {
-						/* Needs adjusting */
-						tmp_start = range->start;
-						flag = FALSE;
-
-						while ((len_tmp = range->end - tmp_start) >= res->len) {
-							if ((tmp_start % tmp_divide) == 0) {
-								flag = TRUE;
-								len_cur = len_tmp;
-								start_cur = tmp_start;
-								break;
-							}
-							tmp_start += tmp_divide - tmp_start % tmp_divide;
-							if (tmp_start >= range->end)
-								break;
-						}
-					}
-
-					if (flag && len_cur == res->len) {
-						res->start = start_cur;
-						res->len += 1; /* To restore the balance */
-						res->end = res->start + res->len - 1;
-						return 0;
-					}
-				}
-			}
-			range = range->next;
-		}		/* end of while */
-
-		if ((!range) && (len_cur == 0)) {
-			/* have gone through the list of devices and ranges and haven't found n.e.thing */
-			err ("no appropriate range.. bailing out...\n");
-			return -EINVAL;
-		} else if (len_cur) {
-			res->start = start_cur;
-			res->len += 1; /* To restore the balance */
-			res->end = res->start + res->len - 1;
-			return 0;
-		}
-	}
-
-	if (!res_cur) {
-		debug ("prev->rangeno = %d, noranges = %d\n", res_prev->rangeno, noranges);
-		if (res_prev->rangeno < noranges) {
-			/* if there're more ranges out there to check */
-			switch (res->type) {
-				case IO:
-					range = bus_cur->rangeIO;
-					break;
-				case MEM:
-					range = bus_cur->rangeMem;
-					break;
-				case PFMEM:
-					range = bus_cur->rangePFMem;
-					break;
-			}
-			while (range) {
-				if ((len_tmp = range->end - range->start) >= res->len) {
-					if ((len_tmp < len_cur) || (len_cur == 0)) {
-						if ((range->start % tmp_divide) == 0) {
-							/* just perfect, starting address's divisible by length */
-							flag = TRUE;
-							len_cur = len_tmp;
-							start_cur = range->start;
-						} else {
-							/* Needs adjusting */
-							tmp_start = range->start;
-							flag = FALSE;
-
-							while ((len_tmp = range->end - tmp_start) >= res->len) {
-								if ((tmp_start % tmp_divide) == 0) {
-									flag = TRUE;
-									len_cur = len_tmp;
-									start_cur = tmp_start;
-									break;
-								}
-								tmp_start += tmp_divide - tmp_start % tmp_divide;
-								if (tmp_start >= range->end)
-									break;
-							}
-						}
-
-						if (flag && len_cur == res->len) {
-							res->start = start_cur;
-							res->len += 1; /* To restore the balance */
-							res->end = res->start + res->len - 1;
-							return 0;
-						}
-					}
-				}
-				range = range->next;
-			}	/* end of while */
-
-			if ((!range) && (len_cur == 0)) {
-				/* have gone through the list of devices and ranges and haven't found n.e.thing */
-				err ("no appropriate range.. bailing out...\n");
-				return -EINVAL;
-			} else if (len_cur) {
-				res->start = start_cur;
-				res->len += 1; /* To restore the balance */
-				res->end = res->start + res->len - 1;
-				return 0;
-			}
-		} else {
-			/* no more ranges to check on */
-			if (len_cur) {
-				res->start = start_cur;
-				res->len += 1; /* To restore the balance */
-				res->end = res->start + res->len - 1;
-				return 0;
-			} else {
-				/* have gone through the list of devices and haven't found n.e.thing */
-				err ("no appropriate range.. bailing out...\n");
-				return -EINVAL;
-			}
-		}
-	}	/* end if(!res_cur) */
-	return -EINVAL;
-}
-
-/********************************************************************************
- * This routine is called from remove_card if the card contained PPB.
- * It will remove all the resources on the bus as well as the bus itself
- * Input: Bus
- * Ouput: 0, -ENODEV
- ********************************************************************************/
-int ibmphp_remove_bus (struct bus_node *bus, u8 parent_busno)
-{
-	struct resource_node *res_cur;
-	struct resource_node *res_tmp;
-	struct bus_node *prev_bus;
-	int rc;
-
-	prev_bus = find_bus_wprev (parent_busno, NULL, 0);	
-
-	if (!prev_bus) {
-		debug ("something terribly wrong. Cannot find parent bus to the one to remove\n");
-		return -ENODEV;
-	}
-
-	debug ("In ibmphp_remove_bus... prev_bus->busno is %x\n", prev_bus->busno);
-
-	rc = remove_ranges (bus, prev_bus);
-	if (rc)
-		return rc;
-
-	if (bus->firstIO) {
-		res_cur = bus->firstIO;
-		while (res_cur) {
-			res_tmp = res_cur;
-			if (res_cur->next)
-				res_cur = res_cur->next;
-			else
-				res_cur = res_cur->nextRange;
-			kfree (res_tmp);
-			res_tmp = NULL;
-		}
-		bus->firstIO = NULL;
-	}
-	if (bus->firstMem) {
-		res_cur = bus->firstMem;
-		while (res_cur) {
-			res_tmp = res_cur;
-			if (res_cur->next)
-				res_cur = res_cur->next;
-			else
-				res_cur = res_cur->nextRange;
-			kfree (res_tmp);
-			res_tmp = NULL;
-		}
-		bus->firstMem = NULL;
-	}
-	if (bus->firstPFMem) {
-		res_cur = bus->firstPFMem;
-		while (res_cur) {
-			res_tmp = res_cur;
-			if (res_cur->next)
-				res_cur = res_cur->next;
-			else
-				res_cur = res_cur->nextRange;
-			kfree (res_tmp);
-			res_tmp = NULL;
-		}
-		bus->firstPFMem = NULL;
-	}
-
-	if (bus->firstPFMemFromMem) {
-		res_cur = bus->firstPFMemFromMem;
-		while (res_cur) {
-			res_tmp = res_cur;
-			res_cur = res_cur->next;
-
-			kfree (res_tmp);
-			res_tmp = NULL;
-		}
-		bus->firstPFMemFromMem = NULL;
-	}
-
-	list_del (&bus->bus_list);
-	kfree (bus);
-	return 0;
-}
-
-/******************************************************************************
- * This routine deletes the ranges from a given bus, and the entries from the 
- * parent's bus in the resources
- * Input: current bus, previous bus
- * Output: 0, -EINVAL
- ******************************************************************************/
-static int remove_ranges (struct bus_node *bus_cur, struct bus_node *bus_prev)
-{
-	struct range_node *range_cur;
-	struct range_node *range_tmp;
-	int i;
-	struct resource_node *res = NULL;
-
-	if (bus_cur->noIORanges) {
-		range_cur = bus_cur->rangeIO;
-		for (i = 0; i < bus_cur->noIORanges; i++) {
-			if (ibmphp_find_resource (bus_prev, range_cur->start, &res, IO) < 0)
-				return -EINVAL;
-			ibmphp_remove_resource (res);
-
-			range_tmp = range_cur;
-			range_cur = range_cur->next;
-			kfree (range_tmp);
-			range_tmp = NULL;
-		}
-		bus_cur->rangeIO = NULL;
-	}
-	if (bus_cur->noMemRanges) {
-		range_cur = bus_cur->rangeMem;
-		for (i = 0; i < bus_cur->noMemRanges; i++) {
-			if (ibmphp_find_resource (bus_prev, range_cur->start, &res, MEM) < 0) 
-				return -EINVAL;
-
-			ibmphp_remove_resource (res);
-			range_tmp = range_cur;
-			range_cur = range_cur->next;
-			kfree (range_tmp);
-			range_tmp = NULL;
-		}
-		bus_cur->rangeMem = NULL;
-	}
-	if (bus_cur->noPFMemRanges) {
-		range_cur = bus_cur->rangePFMem;
-		for (i = 0; i < bus_cur->noPFMemRanges; i++) {
-			if (ibmphp_find_resource (bus_prev, range_cur->start, &res, PFMEM) < 0) 
-				return -EINVAL;
-
-			ibmphp_remove_resource (res);
-			range_tmp = range_cur;
-			range_cur = range_cur->next;
-			kfree (range_tmp);
-			range_tmp = NULL;
-		}
-		bus_cur->rangePFMem = NULL;
-	}
-	return 0;
-}
-
-/*
- * find the resource node in the bus 
- * Input: Resource needed, start address of the resource, type of resource
- */
-int ibmphp_find_resource (struct bus_node *bus, u32 start_address, struct resource_node **res, int flag)
-{
-	struct resource_node *res_cur = NULL;
-	char * type = "";
-
-	if (!bus) {
-		err ("The bus passed in NULL to find resource \n");
-		return -ENODEV;
-	}
-
-	switch (flag) {
-		case IO:
-			res_cur = bus->firstIO;
-			type = "io";
-			break;
-		case MEM:
-			res_cur = bus->firstMem;
-			type = "mem";
-			break;
-		case PFMEM:
-			res_cur = bus->firstPFMem;
-			type = "pfmem";
-			break;
-		default:
-			err ("wrong type of flag \n");
-			return -EINVAL;
-	}
-	
-	while (res_cur) {
-		if (res_cur->start == start_address) {
-			*res = res_cur;
-			break;
-		}
-		if (res_cur->next)
-			res_cur = res_cur->next;
-		else
-			res_cur = res_cur->nextRange;
-	}
-
-	if (!res_cur) {
-		if (flag == PFMEM) {
-			res_cur = bus->firstPFMemFromMem;
-			while (res_cur) {
-				if (res_cur->start == start_address) {
-					*res = res_cur;
-					break;
-				}
-				res_cur = res_cur->next;
-			}
-			if (!res_cur) {
-				debug ("SOS...cannot find %s resource in the bus. \n", type);
-				return -EINVAL;
-			}
-		} else {
-			debug ("SOS... cannot find %s resource in the bus. \n", type);
-			return -EINVAL;
-		}
-	}
-
-	if (*res)
-		debug ("*res->start = %x \n", (*res)->start);
-
-	return 0;
-}
-
-/***********************************************************************
- * This routine will free the resource structures used by the
- * system.  It is called from cleanup routine for the module
- * Parameters: none
- * Returns: none
- ***********************************************************************/
-void ibmphp_free_resources (void)
-{
-	struct bus_node *bus_cur = NULL;
-	struct bus_node *bus_tmp;
-	struct range_node *range_cur;
-	struct range_node *range_tmp;
-	struct resource_node *res_cur;
-	struct resource_node *res_tmp;
-	struct list_head *tmp;
-	struct list_head *next;
-	int i = 0;
-	flags = 1;
-
-	list_for_each_safe (tmp, next, &gbuses) {
-		bus_cur = list_entry (tmp, struct bus_node, bus_list);
-		if (bus_cur->noIORanges) {
-			range_cur = bus_cur->rangeIO;
-			for (i = 0; i < bus_cur->noIORanges; i++) {
-				if (!range_cur)
-					break;
-				range_tmp = range_cur;
-				range_cur = range_cur->next;
-				kfree (range_tmp);
-				range_tmp = NULL;
-			}
-		}
-		if (bus_cur->noMemRanges) {
-			range_cur = bus_cur->rangeMem;
-			for (i = 0; i < bus_cur->noMemRanges; i++) {
-				if (!range_cur)
-					break;
-				range_tmp = range_cur;
-				range_cur = range_cur->next;
-				kfree (range_tmp);
-				range_tmp = NULL;
-			}
-		}
-		if (bus_cur->noPFMemRanges) {
-			range_cur = bus_cur->rangePFMem;
-			for (i = 0; i < bus_cur->noPFMemRanges; i++) {
-				if (!range_cur)
-					break;
-				range_tmp = range_cur;
-				range_cur = range_cur->next;
-				kfree (range_tmp);
-				range_tmp = NULL;
-			}
-		}
-
-		if (bus_cur->firstIO) {
-			res_cur = bus_cur->firstIO;
-			while (res_cur) {
-				res_tmp = res_cur;
-				if (res_cur->next)
-					res_cur = res_cur->next;
-				else
-					res_cur = res_cur->nextRange;
-				kfree (res_tmp);
-				res_tmp = NULL;
-			}
-			bus_cur->firstIO = NULL;
-		}
-		if (bus_cur->firstMem) {
-			res_cur = bus_cur->firstMem;
-			while (res_cur) {
-				res_tmp = res_cur;
-				if (res_cur->next)
-					res_cur = res_cur->next;
-				else
-					res_cur = res_cur->nextRange;
-				kfree (res_tmp);
-				res_tmp = NULL;
-			}
-			bus_cur->firstMem = NULL;
-		}
-		if (bus_cur->firstPFMem) {
-			res_cur = bus_cur->firstPFMem;
-			while (res_cur) {
-				res_tmp = res_cur;
-				if (res_cur->next)
-					res_cur = res_cur->next;
-				else
-					res_cur = res_cur->nextRange;
-				kfree (res_tmp);
-				res_tmp = NULL;
-			}
-			bus_cur->firstPFMem = NULL;
-		}
-
-		if (bus_cur->firstPFMemFromMem) {
-			res_cur = bus_cur->firstPFMemFromMem;
-			while (res_cur) {
-				res_tmp = res_cur;
-				res_cur = res_cur->next;
-
-				kfree (res_tmp);
-				res_tmp = NULL;
-			}
-			bus_cur->firstPFMemFromMem = NULL;
-		}
-
-		bus_tmp = bus_cur;
-		list_del (&bus_cur->bus_list);
-		kfree (bus_tmp);
-		bus_tmp = NULL;
-	}
-}
-
-/*********************************************************************************
- * This function will go over the PFmem resources to check if the EBDA allocated
- * pfmem out of memory buckets of the bus.  If so, it will change the range numbers
- * and a flag to indicate that this resource is out of memory. It will also move the
- * Pfmem out of the pfmem resource list to the PFMemFromMem list, and will create
- * a new Mem node
- * This routine is called right after initialization
- *******************************************************************************/
-static int __init once_over (void)
-{
-	struct resource_node *pfmem_cur;
-	struct resource_node *pfmem_prev;
-	struct resource_node *mem;
-	struct bus_node *bus_cur;
-	struct list_head *tmp;
-
-	list_for_each (tmp, &gbuses) {
-		bus_cur = list_entry (tmp, struct bus_node, bus_list);
-		if ((!bus_cur->rangePFMem) && (bus_cur->firstPFMem)) {
-			for (pfmem_cur = bus_cur->firstPFMem, pfmem_prev = NULL; pfmem_cur; pfmem_prev = pfmem_cur, pfmem_cur = pfmem_cur->next) {
-				pfmem_cur->fromMem = TRUE;
-				if (pfmem_prev)
-					pfmem_prev->next = pfmem_cur->next;
-				else
-					bus_cur->firstPFMem = pfmem_cur->next;
-
-				if (!bus_cur->firstPFMemFromMem)
-					pfmem_cur->next = NULL;
-				else
-					/* we don't need to sort PFMemFromMem since we're using mem node for
-					   all the real work anyways, so just insert at the beginning of the
-					   list
-					 */
-					pfmem_cur->next = bus_cur->firstPFMemFromMem;
-
-				bus_cur->firstPFMemFromMem = pfmem_cur;
-
-				mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);		
-				if (!mem) {
-					err ("out of system memory \n");
-					return -ENOMEM;
-				}
-				memset (mem, 0, sizeof (struct resource_node));
-				mem->type = MEM;
-				mem->busno = pfmem_cur->busno;
-				mem->devfunc = pfmem_cur->devfunc;
-				mem->start = pfmem_cur->start;
-				mem->end = pfmem_cur->end;
-				mem->len = pfmem_cur->len;
-				if (ibmphp_add_resource (mem) < 0)
-					err ("Trouble...trouble... EBDA allocated pfmem from mem, but system doesn't display it has this space... unless not PCI device...\n");
-				pfmem_cur->rangeno = mem->rangeno;
-			}	/* end for pfmem */
-		}	/* end if */
-	}	/* end list_for_each bus */
-	return 0; 
-}
-
-int ibmphp_add_pfmem_from_mem (struct resource_node *pfmem)
-{
-	struct bus_node *bus_cur = find_bus_wprev (pfmem->busno, NULL, 0);
-
-	if (!bus_cur) {
-		err ("cannot find bus of pfmem to add...\n");
-		return -ENODEV;
-	}
-
-	if (bus_cur->firstPFMemFromMem)
-		pfmem->next = bus_cur->firstPFMemFromMem;
-	else
-		pfmem->next = NULL;
-
-	bus_cur->firstPFMemFromMem = pfmem;
-
-	return 0;
-}
-
-/* This routine just goes through the buses to see if the bus already exists.
- * It is called from ibmphp_find_sec_number, to find out a secondary bus number for
- * bridged cards
- * Parameters: bus_number
- * Returns: Bus pointer or NULL
- */
-struct bus_node *ibmphp_find_res_bus (u8 bus_number)
-{
-	return find_bus_wprev (bus_number, NULL, 0);
-}
-
-static inline struct bus_node *find_bus_wprev (u8 bus_number, struct bus_node **prev, u8 flag)
-{
-	struct bus_node *bus_cur;
-	struct list_head *tmp;
-	struct list_head *tmp_prev;
-
-	list_for_each (tmp, &gbuses) {
-		tmp_prev = tmp->prev;
-		bus_cur = list_entry (tmp, struct bus_node, bus_list);
-		if (flag) 
-			*prev = list_entry (tmp_prev, struct bus_node, bus_list);
-		if (bus_cur->busno == bus_number) 
-			return bus_cur;
-	}
-
-	return NULL;
-}
-
-void ibmphp_print_test (void)
-{
-	int i = 0;
-	struct bus_node *bus_cur = NULL;
-	struct range_node *range;
-	struct resource_node *res;
-	struct list_head *tmp;
-	
-	debug_pci ("*****************START**********************\n");
-
-	if ((!list_empty(&gbuses)) && flags) {
-		err ("The GBUSES is not NULL?!?!?!?!?\n");
-		return;
-	}
-
-	list_for_each (tmp, &gbuses) {
-		bus_cur = list_entry (tmp, struct bus_node, bus_list);
-		debug_pci ("This is bus # %d.  There are \n", bus_cur->busno);
-		debug_pci ("IORanges = %d\t", bus_cur->noIORanges);
-		debug_pci ("MemRanges = %d\t", bus_cur->noMemRanges);
-		debug_pci ("PFMemRanges = %d\n", bus_cur->noPFMemRanges);
-		debug_pci ("The IO Ranges are as follows:\n");
-		if (bus_cur->rangeIO) {
-			range = bus_cur->rangeIO;
-			for (i = 0; i < bus_cur->noIORanges; i++) {
-				debug_pci ("rangeno is %d\n", range->rangeno);
-				debug_pci ("[%x - %x]\n", range->start, range->end);
-				range = range->next;
-			}
-		}
-
-		debug_pci ("The Mem Ranges are as follows:\n");
-		if (bus_cur->rangeMem) {
-			range = bus_cur->rangeMem;
-			for (i = 0; i < bus_cur->noMemRanges; i++) {
-				debug_pci ("rangeno is %d\n", range->rangeno);
-				debug_pci ("[%x - %x]\n", range->start, range->end);
-				range = range->next;
-			}
-		}
-
-		debug_pci ("The PFMem Ranges are as follows:\n");
-
-		if (bus_cur->rangePFMem) {
-			range = bus_cur->rangePFMem;
-			for (i = 0; i < bus_cur->noPFMemRanges; i++) {
-				debug_pci ("rangeno is %d\n", range->rangeno);
-				debug_pci ("[%x - %x]\n", range->start, range->end);
-				range = range->next;
-			}
-		}
-
-		debug_pci ("The resources on this bus are as follows\n");
-
-		debug_pci ("IO...\n");
-		if (bus_cur->firstIO) {
-			res = bus_cur->firstIO;
-			while (res) {
-				debug_pci ("The range # is %d\n", res->rangeno);
-				debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
-				debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);
-				if (res->next)
-					res = res->next;
-				else if (res->nextRange)
-					res = res->nextRange;
-				else
-					break;
-			}
-		}
-		debug_pci ("Mem...\n");
-		if (bus_cur->firstMem) {
-			res = bus_cur->firstMem;
-			while (res) {
-				debug_pci ("The range # is %d\n", res->rangeno);
-				debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
-				debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);
-				if (res->next)
-					res = res->next;
-				else if (res->nextRange)
-					res = res->nextRange;
-				else
-					break;
-			}
-		}
-		debug_pci ("PFMem...\n");
-		if (bus_cur->firstPFMem) {
-			res = bus_cur->firstPFMem;
-			while (res) {
-				debug_pci ("The range # is %d\n", res->rangeno);
-				debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
-				debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);
-				if (res->next)
-					res = res->next;
-				else if (res->nextRange)
-					res = res->nextRange;
-				else
-					break;
-			}
-		}
-
-		debug_pci ("PFMemFromMem...\n");
-		if (bus_cur->firstPFMemFromMem) {
-			res = bus_cur->firstPFMemFromMem;
-			while (res) {
-				debug_pci ("The range # is %d\n", res->rangeno);
-				debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
-				debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);
-				res = res->next;
-			}
-		}
-	}
-	debug_pci ("***********************END***********************\n");
-}
-
-static int range_exists_already (struct range_node * range, struct bus_node * bus_cur, u8 type)
-{
-	struct range_node * range_cur = NULL;
-	switch (type) {
-		case IO:
-			range_cur = bus_cur->rangeIO;
-			break;
-		case MEM:
-			range_cur = bus_cur->rangeMem;
-			break;
-		case PFMEM:
-			range_cur = bus_cur->rangePFMem;
-			break;
-		default:
-			err ("wrong type passed to find out if range already exists \n");
-			return -ENODEV;
-	}
-
-	while (range_cur) {
-		if ((range_cur->start == range->start) && (range_cur->end == range->end))
-			return 1;
-		range_cur = range_cur->next;
-	}
-	
-	return 0;
-}
-
-/* This routine will read the windows for any PPB we have and update the
- * range info for the secondary bus, and will also input this info into
- * primary bus, since BIOS doesn't. This is for PPB that are in the system
- * on bootup.  For bridged cards that were added during previous load of the
- * driver, only the ranges and the bus structure are added, the devices are
- * added from NVRAM
- * Input: primary busno
- * Returns: none
- * Note: this function doesn't take into account IO restrictions etc,
- *	 so will only work for bridges with no video/ISA devices behind them It
- *	 also will not work for onboard PPB's that can have more than 1 *bus
- *	 behind them All these are TO DO.
- *	 Also need to add more error checkings... (from fnc returns etc)
- */
-static int __init update_bridge_ranges (struct bus_node **bus)
-{
-	u8 sec_busno, device, function, hdr_type, start_io_address, end_io_address;
-	u16 vendor_id, upper_io_start, upper_io_end, start_mem_address, end_mem_address;
-	u32 start_address, end_address, upper_start, upper_end;
-	struct bus_node *bus_sec;
-	struct bus_node *bus_cur;
-	struct resource_node *io;
-	struct resource_node *mem;
-	struct resource_node *pfmem;
-	struct range_node *range;
-	unsigned int devfn;
-
-	bus_cur = *bus;
-	if (!bus_cur)
-		return -ENODEV;
-	ibmphp_pci_bus->number = bus_cur->busno;
-
-	debug ("inside %s \n", __FUNCTION__);
-	debug ("bus_cur->busno = %x\n", bus_cur->busno);
-
-	for (device = 0; device < 32; device++) {
-		for (function = 0x00; function < 0x08; function++) {
-			devfn = PCI_DEVFN(device, function);
-			pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id);
-
-			if (vendor_id != PCI_VENDOR_ID_NOTVALID) {
-				/* found correct device!!! */
-				pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type);
-
-				switch (hdr_type) {
-					case PCI_HEADER_TYPE_NORMAL:
-						function = 0x8;
-						break;
-					case PCI_HEADER_TYPE_MULTIDEVICE:
-						break;
-					case PCI_HEADER_TYPE_BRIDGE:
-						function = 0x8;
-					case PCI_HEADER_TYPE_MULTIBRIDGE:
-						/* We assume here that only 1 bus behind the bridge 
-						   TO DO: add functionality for several:
-						   temp = secondary;
-						   while (temp < subordinate) {
-						   ...
-						   temp++;
-						   }
-						 */
-						pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_busno);
-						bus_sec = find_bus_wprev (sec_busno, NULL, 0); 
-						/* this bus structure doesn't exist yet, PPB was configured during previous loading of ibmphp */
-						if (!bus_sec) {
-							bus_sec = alloc_error_bus (NULL, sec_busno, 1);
-							/* the rest will be populated during NVRAM call */
-							return 0;
-						}
-						pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, &start_io_address);
-						pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, &end_io_address);
-						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_IO_BASE_UPPER16, &upper_io_start);
-						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_IO_LIMIT_UPPER16, &upper_io_end);
-						start_address = (start_io_address & PCI_IO_RANGE_MASK) << 8;
-						start_address |= (upper_io_start << 16);
-						end_address = (end_io_address & PCI_IO_RANGE_MASK) << 8;
-						end_address |= (upper_io_end << 16);
-
-						if ((start_address) && (start_address <= end_address)) {
-							range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
-							if (!range) {
-								err ("out of system memory \n");
-								return -ENOMEM;
-							}
-							memset (range, 0, sizeof (struct range_node));
-							range->start = start_address;
-							range->end = end_address + 0xfff;
-
-							if (bus_sec->noIORanges > 0) {
-								if (!range_exists_already (range, bus_sec, IO)) {
-									add_range (IO, range, bus_sec);
-									++bus_sec->noIORanges;
-								} else {
-									kfree (range);
-									range = NULL;
-								}
-							} else {
-								/* 1st IO Range on the bus */
-								range->rangeno = 1;
-								bus_sec->rangeIO = range;
-								++bus_sec->noIORanges;
-							}
-							fix_resources (bus_sec);
-
-							if (ibmphp_find_resource (bus_cur, start_address, &io, IO)) {
-								io = kmalloc (sizeof (struct resource_node), GFP_KERNEL);							
-								if (!io) {
-									kfree (range);
-									err ("out of system memory \n");
-									return -ENOMEM;
-								}
-								memset (io, 0, sizeof (struct resource_node));
-								io->type = IO;
-								io->busno = bus_cur->busno;
-								io->devfunc = ((device << 3) | (function & 0x7));
-								io->start = start_address;
-								io->end = end_address + 0xfff;
-								io->len = io->end - io->start + 1;
-								ibmphp_add_resource (io);
-							}
-						}	
-
-						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, &start_mem_address);
-						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, &end_mem_address);
-
-						start_address = 0x00000000 | (start_mem_address & PCI_MEMORY_RANGE_MASK) << 16;
-						end_address = 0x00000000 | (end_mem_address & PCI_MEMORY_RANGE_MASK) << 16;
-
-						if ((start_address) && (start_address <= end_address)) {
-
-							range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
-							if (!range) {
-								err ("out of system memory \n");
-								return -ENOMEM;
-							}
-							memset (range, 0, sizeof (struct range_node));
-							range->start = start_address;
-							range->end = end_address + 0xfffff;
-
-							if (bus_sec->noMemRanges > 0) {
-								if (!range_exists_already (range, bus_sec, MEM)) {
-									add_range (MEM, range, bus_sec);
-									++bus_sec->noMemRanges;
-								} else {
-									kfree (range);
-									range = NULL;
-								}
-							} else {
-								/* 1st Mem Range on the bus */
-								range->rangeno = 1;
-								bus_sec->rangeMem = range;
-								++bus_sec->noMemRanges;
-							}
-
-							fix_resources (bus_sec);
-
-							if (ibmphp_find_resource (bus_cur, start_address, &mem, MEM)) {
-								mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
-								if (!mem) {
-									kfree (range);
-									err ("out of system memory \n");
-									return -ENOMEM;
-								}
-								memset (mem, 0, sizeof (struct resource_node));
-								mem->type = MEM;
-								mem->busno = bus_cur->busno;
-								mem->devfunc = ((device << 3) | (function & 0x7));
-								mem->start = start_address;
-								mem->end = end_address + 0xfffff;
-								mem->len = mem->end - mem->start + 1;
-								ibmphp_add_resource (mem);
-							}
-						}
-						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, &start_mem_address);
-						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &end_mem_address);
-						pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_BASE_UPPER32, &upper_start);
-						pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_LIMIT_UPPER32, &upper_end);
-						start_address = 0x00000000 | (start_mem_address & PCI_MEMORY_RANGE_MASK) << 16;
-						end_address = 0x00000000 | (end_mem_address & PCI_MEMORY_RANGE_MASK) << 16;
-#if BITS_PER_LONG == 64
-						start_address |= ((long) upper_start) << 32;
-						end_address |= ((long) upper_end) << 32;
-#endif
-
-						if ((start_address) && (start_address <= end_address)) {
-
-							range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
-							if (!range) {
-								err ("out of system memory \n");
-								return -ENOMEM;
-							}
-							memset (range, 0, sizeof (struct range_node));
-							range->start = start_address;
-							range->end = end_address + 0xfffff;
-
-							if (bus_sec->noPFMemRanges > 0) {
-								if (!range_exists_already (range, bus_sec, PFMEM)) {
-									add_range (PFMEM, range, bus_sec);
-									++bus_sec->noPFMemRanges;
-								} else {
-									kfree (range);
-									range = NULL;
-								}
-							} else {
-								/* 1st PFMem Range on the bus */
-								range->rangeno = 1;
-								bus_sec->rangePFMem = range;
-								++bus_sec->noPFMemRanges;
-							}
-
-							fix_resources (bus_sec);
-							if (ibmphp_find_resource (bus_cur, start_address, &pfmem, PFMEM)) {
-								pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
-								if (!pfmem) {
-									kfree (range);
-									err ("out of system memory \n");
-									return -ENOMEM;
-								}
-								memset (pfmem, 0, sizeof (struct resource_node));
-								pfmem->type = PFMEM;
-								pfmem->busno = bus_cur->busno;
-								pfmem->devfunc = ((device << 3) | (function & 0x7));
-								pfmem->start = start_address;
-								pfmem->end = end_address + 0xfffff;
-								pfmem->len = pfmem->end - pfmem->start + 1;
-								pfmem->fromMem = FALSE;
-
-								ibmphp_add_resource (pfmem);
-							}
-						}
-						break;
-				}	/* end of switch */
-			}	/* end if vendor */
-		}	/* end for function */
-	}	/* end for device */
-
-	bus = &bus_cur;
-	return 0;
-}
diff -Nru a/drivers/hotplug/pci_hotplug.h b/drivers/hotplug/pci_hotplug.h
--- a/drivers/hotplug/pci_hotplug.h	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,146 +0,0 @@
-/*
- * PCI HotPlug Core Functions
- *
- * Copyright (c) 1995,2001 Compaq Computer Corporation
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001 IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <greg@kroah.com>
- *
- */
-#ifndef _PCI_HOTPLUG_H
-#define _PCI_HOTPLUG_H
-
-
-/* These values come from the PCI Hotplug Spec */
-enum pci_bus_speed {
-	PCI_SPEED_33MHz			= 0x00,
-	PCI_SPEED_66MHz			= 0x01,
-	PCI_SPEED_66MHz_PCIX		= 0x02,
-	PCI_SPEED_100MHz_PCIX		= 0x03,
-	PCI_SPEED_133MHz_PCIX		= 0x04,
-	PCI_SPEED_66MHz_PCIX_266	= 0x09,
-	PCI_SPEED_100MHz_PCIX_266	= 0x0a,
-	PCI_SPEED_133MHz_PCIX_266	= 0x0b,
-	PCI_SPEED_66MHz_PCIX_533	= 0x11,
-	PCI_SPEED_100MHz_PCIX_533	= 0X12,
-	PCI_SPEED_133MHz_PCIX_533	= 0x13,
-	PCI_SPEED_UNKNOWN		= 0xff,
-};
-
-struct hotplug_slot;
-struct hotplug_slot_attribute {
-	struct attribute attr;
-	ssize_t (*show)(struct hotplug_slot *, char *);
-	ssize_t (*store)(struct hotplug_slot *, const char *, size_t);
-};
-/**
- * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use
- * @owner: The module owner of this structure
- * @enable_slot: Called when the user wants to enable a specific pci slot
- * @disable_slot: Called when the user wants to disable a specific pci slot
- * @set_attention_status: Called to set the specific slot's attention LED to
- * the specified value
- * @hardware_test: Called to run a specified hardware test on the specified
- * slot.
- * @get_power_status: Called to get the current power status of a slot.
- * 	If this field is NULL, the value passed in the struct hotplug_slot_info
- * 	will be used when this value is requested by a user.
- * @get_attention_status: Called to get the current attention status of a slot.
- *	If this field is NULL, the value passed in the struct hotplug_slot_info
- *	will be used when this value is requested by a user.
- * @get_latch_status: Called to get the current latch status of a slot.
- *	If this field is NULL, the value passed in the struct hotplug_slot_info
- *	will be used when this value is requested by a user.
- * @get_adapter_status: Called to get see if an adapter is present in the slot or not.
- *	If this field is NULL, the value passed in the struct hotplug_slot_info
- *	will be used when this value is requested by a user.
- * @get_max_bus_speed: Called to get the max bus speed for a slot.
- *	If this field is NULL, the value passed in the struct hotplug_slot_info
- *	will be used when this value is requested by a user.
- * @get_cur_bus_speed: Called to get the current bus speed for a slot.
- *	If this field is NULL, the value passed in the struct hotplug_slot_info
- *	will be used when this value is requested by a user.
- *
- * The table of function pointers that is passed to the hotplug pci core by a
- * hotplug pci driver.  These functions are called by the hotplug pci core when
- * the user wants to do something to a specific slot (query it for information,
- * set an LED, enable / disable power, etc.)
- */
-struct hotplug_slot_ops {
-	struct module *owner;
-	int (*enable_slot)		(struct hotplug_slot *slot);
-	int (*disable_slot)		(struct hotplug_slot *slot);
-	int (*set_attention_status)	(struct hotplug_slot *slot, u8 value);
-	int (*hardware_test)		(struct hotplug_slot *slot, u32 value);
-	int (*get_power_status)		(struct hotplug_slot *slot, u8 *value);
-	int (*get_attention_status)	(struct hotplug_slot *slot, u8 *value);
-	int (*get_latch_status)		(struct hotplug_slot *slot, u8 *value);
-	int (*get_adapter_status)	(struct hotplug_slot *slot, u8 *value);
-	int (*get_max_bus_speed)	(struct hotplug_slot *slot, enum pci_bus_speed *value);
-	int (*get_cur_bus_speed)	(struct hotplug_slot *slot, enum pci_bus_speed *value);
-};
-
-/**
- * struct hotplug_slot_info - used to notify the hotplug pci core of the state of the slot
- * @power: if power is enabled or not (1/0)
- * @attention_status: if the attention light is enabled or not (1/0)
- * @latch_status: if the latch (if any) is open or closed (1/0)
- * @adapter_present: if there is a pci board present in the slot or not (1/0)
- *
- * Used to notify the hotplug pci core of the status of a specific slot.
- */
-struct hotplug_slot_info {
-	u8	power_status;
-	u8	attention_status;
-	u8	latch_status;
-	u8	adapter_status;
-	enum pci_bus_speed	max_bus_speed;
-	enum pci_bus_speed	cur_bus_speed;
-};
-
-/**
- * struct hotplug_slot - used to register a physical slot with the hotplug pci core
- * @name: the name of the slot being registered.  This string must
- * be unique amoung slots registered on this system.
- * @ops: pointer to the &struct hotplug_slot_ops to be used for this slot
- * @info: pointer to the &struct hotplug_slot_info for the inital values for
- * this slot.
- * @private: used by the hotplug pci controller driver to store whatever it
- * needs.
- */
-struct hotplug_slot {
-	char				*name;
-	struct hotplug_slot_ops		*ops;
-	struct hotplug_slot_info	*info;
-	void				*private;
-
-	/* Variables below this are for use only by the hotplug pci core. */
-	struct list_head		slot_list;
-	struct kobject			kobj;
-};
-
-extern int pci_hp_register		(struct hotplug_slot *slot);
-extern int pci_hp_deregister		(struct hotplug_slot *slot);
-extern int pci_hp_change_slot_info	(struct hotplug_slot *slot,
-					 struct hotplug_slot_info *info);
-
-#endif
-
diff -Nru a/drivers/hotplug/pci_hotplug_core.c b/drivers/hotplug/pci_hotplug_core.c
--- a/drivers/hotplug/pci_hotplug_core.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,666 +0,0 @@
-/*
- * PCI HotPlug Controller Core
- *
- * Copyright (c) 2001-2002 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001-2002 IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <greg@kroah.com>
- *
- * Filesystem portion based on work done by Pat Mochel on ddfs/driverfs
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/list.h>
-#include <linux/pagemap.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <linux/mount.h>
-#include <linux/namei.h>
-#include <linux/pci.h>
-#include <asm/uaccess.h>
-#include <linux/kobject.h>
-#include <linux/sysfs.h>
-#include "pci_hotplug.h"
-
-
-#if !defined(CONFIG_HOTPLUG_PCI_MODULE)
-	#define MY_NAME	"pci_hotplug"
-#else
-	#define MY_NAME	THIS_MODULE->name
-#endif
-
-#define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## arg); } while (0)
-#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
-#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
-
-
-/* local variables */
-static int debug;
-
-#define DRIVER_VERSION	"0.5"
-#define DRIVER_AUTHOR	"Greg Kroah-Hartman <greg@kroah.com>, Scott Murray <scottm@somanetworks.com>"
-#define DRIVER_DESC	"PCI Hot Plug PCI Core"
-
-
-//////////////////////////////////////////////////////////////////
-
-static LIST_HEAD(pci_hotplug_slot_list);
-
-static struct subsystem hotplug_slots_subsys;
-
-static ssize_t hotplug_slot_attr_show(struct kobject *kobj,
-		struct attribute *attr, char *buf)
-{
-	struct hotplug_slot *slot=container_of(kobj,
-			struct hotplug_slot,kobj);
-	struct hotplug_slot_attribute *attribute =
-		container_of(attr, struct hotplug_slot_attribute, attr);
-	return attribute->show ? attribute->show(slot, buf) : 0;
-}
-
-static ssize_t hotplug_slot_attr_store(struct kobject *kobj,
-		struct attribute *attr, const char *buf, size_t len)
-{
-	struct hotplug_slot *slot=container_of(kobj,
-			struct hotplug_slot,kobj);
-	struct hotplug_slot_attribute *attribute =
-		container_of(attr, struct hotplug_slot_attribute, attr);
-	return attribute->store ? attribute->store(slot, buf, len) : 0;
-}
-
-static struct sysfs_ops hotplug_slot_sysfs_ops = {
-	.show = hotplug_slot_attr_show,
-	.store = hotplug_slot_attr_store,
-};
-
-static struct kobj_type hotplug_slot_ktype = {
-	.sysfs_ops = &hotplug_slot_sysfs_ops
-};
-
-static decl_subsys(hotplug_slots, &hotplug_slot_ktype, NULL);
-
-
-/* these strings match up with the values in pci_bus_speed */
-static char *pci_bus_speed_strings[] = {
-	"33 MHz PCI",		/* 0x00 */
-	"66 MHz PCI",		/* 0x01 */
-	"66 MHz PCIX", 		/* 0x02 */
-	"100 MHz PCIX",		/* 0x03 */
-	"133 MHz PCIX",		/* 0x04 */
-	NULL,			/* 0x05 */
-	NULL,			/* 0x06 */
-	NULL,			/* 0x07 */
-	NULL,			/* 0x08 */
-	"66 MHz PCIX 266",	/* 0x09 */
-	"100 MHz PCIX 266",	/* 0x0a */
-	"133 MHz PCIX 266",	/* 0x0b */
-	NULL,			/* 0x0c */
-	NULL,			/* 0x0d */
-	NULL,			/* 0x0e */
-	NULL,			/* 0x0f */
-	NULL,			/* 0x10 */
-	"66 MHz PCIX 533",	/* 0x11 */
-	"100 MHz PCIX 533",	/* 0x12 */
-	"133 MHz PCIX 533",	/* 0x13 */
-};
-
-#ifdef CONFIG_HOTPLUG_PCI_CPCI
-extern int cpci_hotplug_init(int debug);
-extern void cpci_hotplug_exit(void);
-#else
-static inline int cpci_hotplug_init(int debug) { return 0; }
-static inline void cpci_hotplug_exit(void) { }
-#endif
-
-/* Weee, fun with macros... */
-#define GET_STATUS(name,type)	\
-static int get_##name (struct hotplug_slot *slot, type *value)		\
-{									\
-	struct hotplug_slot_ops *ops = slot->ops;			\
-	int retval = 0;							\
-	if (try_module_get(ops->owner)) {				\
-		if (ops->get_##name)					\
-			retval = ops->get_##name (slot, value);		\
-		else							\
-			*value = slot->info->name;			\
-		module_put(ops->owner);					\
-	}								\
-	return retval;							\
-}
-
-GET_STATUS(power_status, u8)
-GET_STATUS(attention_status, u8)
-GET_STATUS(latch_status, u8)
-GET_STATUS(adapter_status, u8)
-GET_STATUS(max_bus_speed, enum pci_bus_speed)
-GET_STATUS(cur_bus_speed, enum pci_bus_speed)
-
-static ssize_t power_read_file (struct hotplug_slot *slot, char *buf)
-{
-	int retval;
-	u8 value;
-
-	retval = get_power_status (slot, &value);
-	if (retval)
-		goto exit;
-	retval = sprintf (buf, "%d\n", value);
-exit:
-	return retval;
-}
-
-static ssize_t power_write_file (struct hotplug_slot *slot, const char *buf,
-		size_t count)
-{
-	unsigned long lpower;
-	u8 power;
-	int retval = 0;
-
-	lpower = simple_strtoul (buf, NULL, 10);
-	power = (u8)(lpower & 0xff);
-	dbg ("power = %d\n", power);
-
-	if (!try_module_get(slot->ops->owner)) {
-		retval = -ENODEV;
-		goto exit;
-	}
-	switch (power) {
-		case 0:
-			if (slot->ops->disable_slot)
-				retval = slot->ops->disable_slot(slot);
-			break;
-
-		case 1:
-			if (slot->ops->enable_slot)
-				retval = slot->ops->enable_slot(slot);
-			break;
-
-		default:
-			err ("Illegal value specified for power\n");
-			retval = -EINVAL;
-	}
-	module_put(slot->ops->owner);
-
-exit:	
-	if (retval)
-		return retval;
-	return count;
-}
-
-static struct hotplug_slot_attribute hotplug_slot_attr_power = {
-	.attr = {.name = "power", .mode = S_IFREG | S_IRUGO | S_IWUSR},
-	.show = power_read_file,
-	.store = power_write_file
-};
-
-static ssize_t attention_read_file (struct hotplug_slot *slot, char *buf)
-{
-	int retval;
-	u8 value;
-
-	retval = get_attention_status (slot, &value);
-	if (retval)
-		goto exit;
-	retval = sprintf (buf, "%d\n", value);
-
-exit:
-	return retval;
-}
-
-static ssize_t attention_write_file (struct hotplug_slot *slot, const char *buf,
-		size_t count)
-{
-	unsigned long lattention;
-	u8 attention;
-	int retval = 0;
-
-	lattention = simple_strtoul (buf, NULL, 10);
-	attention = (u8)(lattention & 0xff);
-	dbg (" - attention = %d\n", attention);
-
-	if (!try_module_get(slot->ops->owner)) {
-		retval = -ENODEV;
-		goto exit;
-	}
-	if (slot->ops->set_attention_status)
-		retval = slot->ops->set_attention_status(slot, attention);
-	module_put(slot->ops->owner);
-
-exit:	
-	if (retval)
-		return retval;
-	return count;
-}
-
-static struct hotplug_slot_attribute hotplug_slot_attr_attention = {
-	.attr = {.name = "attention", .mode = S_IFREG | S_IRUGO | S_IWUSR},
-	.show = attention_read_file,
-	.store = attention_write_file
-};
-
-static ssize_t latch_read_file (struct hotplug_slot *slot, char *buf)
-{
-	int retval;
-	u8 value;
-
-	retval = get_latch_status (slot, &value);
-	if (retval)
-		goto exit;
-	retval = sprintf (buf, "%d\n", value);
-
-exit:
-	return retval;
-}
-
-static struct hotplug_slot_attribute hotplug_slot_attr_latch = {
-	.attr = {.name = "latch", .mode = S_IFREG | S_IRUGO | S_IWUSR},
-	.show = latch_read_file,
-};
-
-static ssize_t presence_read_file (struct hotplug_slot *slot, char *buf)
-{
-	int retval;
-	u8 value;
-
-	retval = get_adapter_status (slot, &value);
-	if (retval)
-		goto exit;
-	retval = sprintf (buf, "%d\n", value);
-
-exit:
-	return retval;
-}
-
-static struct hotplug_slot_attribute hotplug_slot_attr_presence = {
-	.attr = {.name = "adapter", .mode = S_IFREG | S_IRUGO | S_IWUSR},
-	.show = presence_read_file,
-};
-
-static char *unknown_speed = "Unknown bus speed";
-
-static ssize_t max_bus_speed_read_file (struct hotplug_slot *slot, char *buf)
-{
-	char *speed_string;
-	int retval;
-	enum pci_bus_speed value;
-	
-	retval = get_max_bus_speed (slot, &value);
-	if (retval)
-		goto exit;
-
-	if (value == PCI_SPEED_UNKNOWN)
-		speed_string = unknown_speed;
-	else
-		speed_string = pci_bus_speed_strings[value];
-	
-	retval = sprintf (buf, "%s\n", speed_string);
-
-exit:
-	return retval;
-}
-
-static struct hotplug_slot_attribute hotplug_slot_attr_max_bus_speed = {
-	.attr = {.name = "max_bus_speed", .mode = S_IFREG | S_IRUGO | S_IWUSR},
-	.show = max_bus_speed_read_file,
-};
-
-static ssize_t cur_bus_speed_read_file (struct hotplug_slot *slot, char *buf)
-{
-	char *speed_string;
-	int retval;
-	enum pci_bus_speed value;
-
-	retval = get_cur_bus_speed (slot, &value);
-	if (retval)
-		goto exit;
-
-	if (value == PCI_SPEED_UNKNOWN)
-		speed_string = unknown_speed;
-	else
-		speed_string = pci_bus_speed_strings[value];
-	
-	retval = sprintf (buf, "%s\n", speed_string);
-
-exit:
-	return retval;
-}
-
-static struct hotplug_slot_attribute hotplug_slot_attr_cur_bus_speed = {
-	.attr = {.name = "cur_bus_speed", .mode = S_IFREG | S_IRUGO | S_IWUSR},
-	.show = cur_bus_speed_read_file,
-};
-
-static ssize_t test_write_file (struct hotplug_slot *slot, const char *buf,
-		size_t count)
-{
-	unsigned long ltest;
-	u32 test;
-	int retval = 0;
-
-	ltest = simple_strtoul (buf, NULL, 10);
-	test = (u32)(ltest & 0xffffffff);
-	dbg ("test = %d\n", test);
-
-	if (!try_module_get(slot->ops->owner)) {
-		retval = -ENODEV;
-		goto exit;
-	}
-	if (slot->ops->hardware_test)
-		retval = slot->ops->hardware_test(slot, test);
-	module_put(slot->ops->owner);
-
-exit:	
-	if (retval)
-		return retval;
-	return count;
-}
-
-static struct hotplug_slot_attribute hotplug_slot_attr_test = {
-	.attr = {.name = "test", .mode = S_IFREG | S_IRUGO | S_IWUSR},
-	.store = test_write_file
-};
-
-static int has_power_file (struct hotplug_slot *slot)
-{
-	if ((!slot) || (!slot->ops))
-		return -ENODEV;
-	if ((slot->ops->enable_slot) ||
-	    (slot->ops->disable_slot) ||
-	    (slot->ops->get_power_status))
-		return 0;
-	return -ENOENT;
-}
-
-static int has_attention_file (struct hotplug_slot *slot)
-{
-	if ((!slot) || (!slot->ops))
-		return -ENODEV;
-	if ((slot->ops->set_attention_status) ||
-	    (slot->ops->get_attention_status))
-		return 0;
-	return -ENOENT;
-}
-
-static int has_latch_file (struct hotplug_slot *slot)
-{
-	if ((!slot) || (!slot->ops))
-		return -ENODEV;
-	if (slot->ops->get_latch_status)
-		return 0;
-	return -ENOENT;
-}
-
-static int has_adapter_file (struct hotplug_slot *slot)
-{
-	if ((!slot) || (!slot->ops))
-		return -ENODEV;
-	if (slot->ops->get_adapter_status)
-		return 0;
-	return -ENOENT;
-}
-
-static int has_max_bus_speed_file (struct hotplug_slot *slot)
-{
-	if ((!slot) || (!slot->ops))
-		return -ENODEV;
-	if (slot->ops->get_max_bus_speed)
-		return 0;
-	return -ENOENT;
-}
-
-static int has_cur_bus_speed_file (struct hotplug_slot *slot)
-{
-	if ((!slot) || (!slot->ops))
-		return -ENODEV;
-	if (slot->ops->get_cur_bus_speed)
-		return 0;
-	return -ENOENT;
-}
-
-static int has_test_file (struct hotplug_slot *slot)
-{
-	if ((!slot) || (!slot->ops))
-		return -ENODEV;
-	if (slot->ops->hardware_test)
-		return 0;
-	return -ENOENT;
-}
-
-static int fs_add_slot (struct hotplug_slot *slot)
-{
-	if (has_power_file(slot) == 0)
-		sysfs_create_file(&slot->kobj, &hotplug_slot_attr_power.attr);
-
-	if (has_attention_file(slot) == 0)
-		sysfs_create_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
-
-	if (has_latch_file(slot) == 0)
-		sysfs_create_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
-
-	if (has_adapter_file(slot) == 0)
-		sysfs_create_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
-
-	if (has_max_bus_speed_file(slot) == 0)
-		sysfs_create_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
-
-	if (has_cur_bus_speed_file(slot) == 0)
-		sysfs_create_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
-
-	if (has_test_file(slot) == 0)
-		sysfs_create_file(&slot->kobj, &hotplug_slot_attr_test.attr);
-
-	return 0;
-}
-
-static void fs_remove_slot (struct hotplug_slot *slot)
-{
-	if (has_power_file(slot) == 0)
-		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
-
-	if (has_attention_file(slot) == 0)
-		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
-
-	if (has_latch_file(slot) == 0)
-		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
-
-	if (has_adapter_file(slot) == 0)
-		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
-
-	if (has_max_bus_speed_file(slot) == 0)
-		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
-
-	if (has_cur_bus_speed_file(slot) == 0)
-		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
-
-	if (has_test_file(slot) == 0)
-		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr);
-}
-
-static struct hotplug_slot *get_slot_from_name (const char *name)
-{
-	struct hotplug_slot *slot;
-	struct list_head *tmp;
-
-	list_for_each (tmp, &pci_hotplug_slot_list) {
-		slot = list_entry (tmp, struct hotplug_slot, slot_list);
-		if (strcmp(slot->name, name) == 0)
-			return slot;
-	}
-	return NULL;
-}
-
-/**
- * pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem
- * @slot: pointer to the &struct hotplug_slot to register
- *
- * Registers a hotplug slot with the pci hotplug subsystem, which will allow
- * userspace interaction to the slot.
- *
- * Returns 0 if successful, anything else for an error.
- */
-int pci_hp_register (struct hotplug_slot *slot)
-{
-	int result;
-
-	if (slot == NULL)
-		return -ENODEV;
-	if ((slot->info == NULL) || (slot->ops == NULL))
-		return -EINVAL;
-
-	strlcpy(slot->kobj.name, slot->name, KOBJ_NAME_LEN);
-	kobj_set_kset_s(slot, hotplug_slots_subsys);
-
-	/* this can fail if we have already registered a slot with the same name */
-	if (kobject_register(&slot->kobj)) {
-		err("Unable to register kobject");
-		return -EINVAL;
-	}
-		
-	list_add (&slot->slot_list, &pci_hotplug_slot_list);
-
-	result = fs_add_slot (slot);
-	dbg ("Added slot %s to the list\n", slot->name);
-	return result;
-}
-
-/**
- * pci_hp_deregister - deregister a hotplug_slot with the PCI hotplug subsystem
- * @slot: pointer to the &struct hotplug_slot to deregister
- *
- * The @slot must have been registered with the pci hotplug subsystem
- * previously with a call to pci_hp_register().
- *
- * Returns 0 if successful, anything else for an error.
- */
-int pci_hp_deregister (struct hotplug_slot *slot)
-{
-	struct hotplug_slot *temp;
-
-	if (slot == NULL)
-		return -ENODEV;
-
-	temp = get_slot_from_name (slot->name);
-	if (temp != slot) {
-		return -ENODEV;
-	}
-	list_del (&slot->slot_list);
-
-	fs_remove_slot (slot);
-	dbg ("Removed slot %s from the list\n", slot->name);
-	kobject_unregister(&slot->kobj);
-	return 0;
-}
-
-/**
- * pci_hp_change_slot_info - changes the slot's information structure in the core
- * @slot: pointer to the slot whose info has changed
- * @info: pointer to the info copy into the slot's info structure
- *
- * @slot must have been registered with the pci 
- * hotplug subsystem previously with a call to pci_hp_register().
- *
- * Returns 0 if successful, anything else for an error.
- */
-int pci_hp_change_slot_info (struct hotplug_slot *slot, struct hotplug_slot_info *info)
-{
-	if ((slot == NULL) || (info == NULL))
-		return -ENODEV;
-
-	/*
-	* check all fields in the info structure, and update timestamps
-	* for the files referring to the fields that have now changed.
-	*/
-	if ((has_power_file(slot) == 0) &&
-	    (slot->info->power_status != info->power_status))
-		sysfs_update_file(&slot->kobj, &hotplug_slot_attr_power.attr);
-
-	if ((has_attention_file(slot) == 0) &&
-	    (slot->info->attention_status != info->attention_status))
-		sysfs_update_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
-
-	if ((has_latch_file(slot) == 0) &&
-	    (slot->info->latch_status != info->latch_status))
-		sysfs_update_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
-
-	if ((has_adapter_file(slot) == 0) &&
-	    (slot->info->adapter_status != info->adapter_status))
-		sysfs_update_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
-
-	if ((has_max_bus_speed_file(slot) == 0) &&
-	    (slot->info->max_bus_speed != info->max_bus_speed))
-		sysfs_update_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
-
-	if ((has_cur_bus_speed_file(slot) == 0) &&
-	    (slot->info->cur_bus_speed != info->cur_bus_speed))
-		sysfs_update_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
-
-	memcpy (slot->info, info, sizeof (struct hotplug_slot_info));
-
-	return 0;
-}
-
-static int __init pci_hotplug_init (void)
-{
-	int result;
-
-	kset_set_kset_s(&hotplug_slots_subsys, pci_bus_type.subsys);
-	result = subsystem_register(&hotplug_slots_subsys);
-	if (result) {
-		err("Register subsys with error %d\n", result);
-		goto exit;
-	}
-	result = cpci_hotplug_init(debug);
-	if (result) {
-		err ("cpci_hotplug_init with error %d\n", result);
-		goto err_subsys;
-	}
-
-	info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
-	goto exit;
-	
-err_subsys:
-	subsystem_unregister(&hotplug_slots_subsys);
-exit:
-	return result;
-}
-
-static void __exit pci_hotplug_exit (void)
-{
-	cpci_hotplug_exit();
-	subsystem_unregister(&hotplug_slots_subsys);
-}
-
-module_init(pci_hotplug_init);
-module_exit(pci_hotplug_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
-
-EXPORT_SYMBOL_GPL(pci_hp_register);
-EXPORT_SYMBOL_GPL(pci_hp_deregister);
-EXPORT_SYMBOL_GPL(pci_hp_change_slot_info);
diff -Nru a/drivers/hotplug/pcihp_skeleton.c b/drivers/hotplug/pcihp_skeleton.c
--- a/drivers/hotplug/pcihp_skeleton.c	Wed Jun  4 18:11:56 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,432 +0,0 @@
-/*
- * PCI Hot Plug Controller Skeleton Driver - 0.1
- *
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001 IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * 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 <greg@kroah.com>
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include "pci_hotplug.h"
-
-
-#define SLOT_MAGIC	0x67267322
-struct slot {
-	u32 magic;
-	u8 number;
-	struct hotplug_slot *hotplug_slot;
-	struct list_head slot_list;
-};
-
-static LIST_HEAD(slot_list);
-
-#if !defined(CONFIG_HOTPLUG_PCI_SKELETON_MODULE)
-	#define MY_NAME	"pcihp_skeleton"
-#else
-	#define MY_NAME	THIS_MODULE->name
-#endif
-
-#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)
-
-
-
-/* local variables */
-static int debug;
-static int num_slots;
-
-#define DRIVER_VERSION	"0.1"
-#define DRIVER_AUTHOR	"Greg Kroah-Hartman <greg@kroah.com>"
-#define DRIVER_DESC	"Hot Plug PCI Controller Skeleton Driver"
-
-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);
-
-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__);
-	int retval = 0;
-	
-	if (slot == NULL)
-		return -ENODEV;
-	
-	dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-
-	/*
-	 * Fill in code here to enable the specified slot
-	 */
-
-	return retval;
-}
-
-
-static int disable_slot (struct hotplug_slot *hotplug_slot)
-{
-	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);
-
-	/*
-	 * Fill in code here to disable the specified slot
-	 */
-
-	return retval;
-}
-
-static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
-{
-	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);
-
-	switch (status) {
-		case 0:
-			/*
-			 * Fill in code here to turn light off
-			 */
-			break;
-
-		case 1:
-		default:
-			/*
-			 * Fill in code here to turn light on
-			 */
-			break;
-	}
-
-	return retval;
-}
-
-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 */
-	
-	return retval;
-}
-
-static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
-{
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
-	int retval = 0;
-	
-	if (slot == NULL)
-		return -ENODEV;
-	
-	dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
-
-	/*
-	 * Fill in logic to get the current power status of the specific
-	 * slot and store it in the *value location.
-	 */
-
-	return retval;
-}
-
-static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
-{
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
-	int retval = 0;
-	
-	if (slot == NULL)
-		return -ENODEV;
-	
-	dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
-
-	/*
-	 * Fill in logic to get the current attention status of the specific
-	 * slot and store it in the *value location.
-	 */
-
-	return retval;
-}
-
-static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
-{
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
-	int retval = 0;
-	
-	if (slot == NULL)
-		return -ENODEV;
-	
-	dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
-
-	/*
-	 * Fill in logic to get the current latch status of the specific
-	 * slot and store it in the *value location.
-	 */
-
-	return retval;
-}
-
-static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
-{
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
-	int retval = 0;
-	
-	if (slot == NULL)
-		return -ENODEV;
-	
-	dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
-
-	/*
-	 * Fill in logic to get the current adapter status of the specific
-	 * slot and store it in the *value location.
-	 */
-
-	return retval;
-}
-
-#define SLOT_NAME_SIZE	10
-static void make_slot_name (struct slot *slot)
-{
-	/*
-	 * Stupid way to make a filename out of the slot name.
-	 * replace this if your hardware provides a better way to name slots.
-	 */
-	snprintf (slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d", slot->number);
-}
-
-static int init_slots (void)
-{
-	struct slot *slot;
-	struct hotplug_slot *hotplug_slot;
-	struct hotplug_slot_info *info;
-	char *name;
-	int retval = 0;
-	int i;
-
-	/*
-	 * 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;
-
-		hotplug_slot->private = slot;
-		make_slot_name (slot);
-		hotplug_slot->ops = &skel_hotplug_slot_ops;
-		
-		/*
-		 * Initilize the slot info structure with some known
-		 * good values.
-		 */
-		info->power_status = get_skel_power_status(slot);
-		info->attention_status = get_skel_attention_status(slot);
-		info->latch_status = get_skel_latch_status(slot);
-		info->adapter_status = get_skel_adapter_status(slot);
-		
-		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 void cleanup_slots (void)
-{
-	struct list_head *tmp;
-	struct slot *slot;
-
-	/*
-	 * Unregister all of our slots with the pci_hotplug subsystem,
-	 * and free up all memory that we had allocated.
-	 */
-	list_for_each (tmp, &slot_list) {
-		slot = list_entry (tmp, struct slot, slot_list);
-		list_del (&slot->slot_list);
-		pci_hp_deregister (slot->hotplug_slot);
-		kfree (slot->hotplug_slot->info);
-		kfree (slot->hotplug_slot->name);
-		kfree (slot->hotplug_slot);
-		kfree (slot);
-	}
-
-	return;
-}
-		
-static int __init pcihp_skel_init(void)
-{
-	int retval;
-
-	/*
-	 * 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.
-	 */
-	num_slots = 5;
-
-	retval = init_slots();
-	if (retval)
-		return retval;
-
-	info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
-	return 0;
-}
-
-static void __exit pcihp_skel_exit(void)
-{
-	/*
-	 * Clean everything up.
-	 */
-	cleanup_slots();
-}
-
-module_init(pcihp_skel_init);
-module_exit(pcihp_skel_exit);
-
diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile
--- a/drivers/pci/Makefile	Wed Jun  4 18:11:56 2003
+++ b/drivers/pci/Makefile	Wed Jun  4 18:11:56 2003
@@ -12,6 +12,9 @@
 obj-$(CONFIG_PCI) += setup-res.o
 endif
 
+# Build the PCI Hotplug drivers if we were asked to
+obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
+
 #
 # Some architectures use the generic PCI setup functions
 #
diff -Nru a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/Kconfig	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,120 @@
+#
+# PCI Hotplug support
+#
+
+menu "PCI Hotplug Support"
+	depends on HOTPLUG
+
+config HOTPLUG_PCI
+	tristate "Support for PCI Hotplug (EXPERIMENTAL)"
+	depends on PCI && EXPERIMENTAL
+	---help---
+	  Say Y here if you have a motherboard with a PCI Hotplug controller.
+	  This allows you to add and remove PCI cards while the machine is
+	  powered up and running.  The file system pcihpfs must be mounted
+	  in order to interact with any PCI Hotplug controllers.
+
+	  This code is also available as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called pci_hotplug. If you want to compile it
+	  as a module, say M here and read <file:Documentation/modules.txt>.
+
+	  When in doubt, say N.
+
+config HOTPLUG_PCI_COMPAQ
+	tristate "Compaq PCI Hotplug driver"
+	depends on HOTPLUG_PCI && X86
+	help
+	  Say Y here if you have a motherboard with a Compaq PCI Hotplug
+	  controller.
+
+	  This code is also available as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called cpqphp. If you want to compile it
+	  as a module, say M here and read <file:Documentation/modules.txt>.
+
+	  When in doubt, say N.
+
+config HOTPLUG_PCI_COMPAQ_NVRAM
+	bool "Save configuration into NVRAM on Compaq servers"
+	depends on HOTPLUG_PCI_COMPAQ
+	help
+	  Say Y here if you have a Compaq server that has a PCI Hotplug
+	  controller.  This will allow the PCI Hotplug driver to store the PCI
+	  system configuration options in NVRAM.
+
+	  When in doubt, say N.
+
+config HOTPLUG_PCI_IBM
+	tristate "IBM PCI Hotplug driver"
+	depends on HOTPLUG_PCI && X86_IO_APIC && X86
+	help
+	  Say Y here if you have a motherboard with a IBM PCI Hotplug
+	  controller.
+
+	  This code is also available as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called cpqphp. If you want to compile it
+	  as a module, say M here and read <file:Documentation/modules.txt>.
+
+	  When in doubt, say N.
+
+config HOTPLUG_PCI_ACPI
+	tristate "ACPI PCI Hotplug driver"
+	depends on ACPI_BUS && HOTPLUG_PCI
+	help
+	  Say Y here if you have a system that supports PCI Hotplug using
+	  ACPI.
+
+	  This code is also available as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called acpiphp. If you want to compile it
+	  as a module, say M here and read <file:Documentation/modules.txt>.
+
+	  When in doubt, say N.
+
+config HOTPLUG_PCI_CPCI
+	tristate "CompactPCI Hotplug driver"
+	depends on HOTPLUG_PCI
+	help
+	  Say Y here if you have a CompactPCI system card with CompactPCI
+	  hotswap support per the PICMG 2.1 specification.
+
+	  This code is also available as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called cpci_hotplug. If you want to compile it
+	  as a module, say M here and read <file:Documentation/modules.txt>.
+
+	  When in doubt, say N.
+
+config HOTPLUG_PCI_CPCI_ZT5550
+	tristate "Ziatech ZT5550 CompactPCI Hotplug driver"
+	depends on HOTPLUG_PCI_CPCI && X86
+	help
+	  Say Y here if you have an Performance Technologies (formerly Intel,
+          formerly just Ziatech) Ziatech ZT5550 CompactPCI system card.
+
+	  This code is also available as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called cpcihp_zt5550. If you want to compile it
+	  as a module, say M here and read <file:Documentation/modules.txt>.
+
+	  When in doubt, say N.
+
+config HOTPLUG_PCI_CPCI_GENERIC
+	tristate "Generic port I/O CompactPCI Hotplug driver"
+	depends on HOTPLUG_PCI_CPCI && X86
+	help
+	  Say Y here if you have a CompactPCI system card that exposes the #ENUM
+	  hotswap signal as a bit in a system register that can be read through
+	  standard port I/O.
+
+	  This code is also available as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called cpcihp_generic. If you want to compile it
+	  as a module, say M here and read <file:Documentation/modules.txt>.
+
+	  When in doubt, say N.
+
+endmenu
+
diff -Nru a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/Makefile	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,44 @@
+#
+# Makefile for the Linux kernel pci hotplug controller drivers.
+#
+
+obj-$(CONFIG_HOTPLUG_PCI)		+= pci_hotplug.o
+obj-$(CONFIG_HOTPLUG_PCI_COMPAQ)	+= cpqphp.o
+obj-$(CONFIG_HOTPLUG_PCI_IBM)		+= ibmphp.o
+obj-$(CONFIG_HOTPLUG_PCI_ACPI)		+= acpiphp.o
+obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550)	+= cpcihp_zt5550.o
+obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC)	+= cpcihp_generic.o
+
+pci_hotplug-objs	:=	pci_hotplug_core.o
+
+ifdef CONFIG_HOTPLUG_PCI_CPCI
+pci_hotplug-objs	+=	cpci_hotplug_core.o	\
+				cpci_hotplug_pci.o
+endif
+
+cpqphp-objs		:=	cpqphp_core.o	\
+				cpqphp_ctrl.o	\
+				cpqphp_sysfs.o	\
+				cpqphp_pci.o
+
+ibmphp-objs		:=	ibmphp_core.o	\
+				ibmphp_ebda.o	\
+				ibmphp_pci.o	\
+				ibmphp_res.o	\
+				ibmphp_hpc.o
+
+acpiphp-objs		:=	acpiphp_core.o	\
+				acpiphp_glue.o	\
+				acpiphp_pci.o	\
+				acpiphp_res.o
+
+ifdef CONFIG_HOTPLUG_PCI_ACPI
+  EXTRA_CFLAGS  += -D_LINUX -I$(TOPDIR)/drivers/acpi
+  ifdef CONFIG_ACPI_DEBUG
+    EXTRA_CFLAGS += -DACPI_DEBUG_OUTPUT
+  endif
+endif
+
+ifeq ($(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM),y)
+	cpqphp-objs += cpqphp_nvram.o
+endif
diff -Nru a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/acpiphp.h	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,262 @@
+/*
+ * ACPI PCI Hot Plug Controller Driver
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
+ * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com)
+ * Copyright (c) 2002 NEC Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gregkh@us.ibm.com>,
+ *		    <h-aono@ap.jp.nec.com>,
+ *		    <t-kouchi@cq.jp.nec.com>
+ *
+ */
+
+#ifndef _ACPIPHP_H
+#define _ACPIPHP_H
+
+#include <linux/acpi.h>
+#include "pci_hotplug.h"
+
+#define dbg(format, arg...)					\
+	do {							\
+		if (acpiphp_debug)				\
+			printk(KERN_DEBUG "%s: " format,	\
+				MY_NAME , ## arg); 		\
+	} while (0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
+
+#define SLOT_MAGIC	0x67267322
+/* name size which is used for entries in pcihpfs */
+#define SLOT_NAME_SIZE	32		/* ACPI{_SUN}-{BUS}:{DEV} */
+
+struct acpiphp_bridge;
+struct acpiphp_slot;
+struct pci_resource;
+
+/*
+ * struct slot - slot information for each *physical* slot
+ */
+struct slot {
+	u32 magic;
+	u8 number;
+	struct hotplug_slot	*hotplug_slot;
+	struct list_head	slot_list;
+
+	struct acpiphp_slot	*acpi_slot;
+};
+
+/*
+ * struct pci_resource - describes pci resource (mem, pfmem, io, bus)
+ */
+struct pci_resource {
+	struct pci_resource * next;
+	u64 base;
+	u32 length;
+};
+
+/**
+ * struct hpp_param - ACPI 2.0 _HPP Hot Plug Parameters
+ * @cache_line_size in DWORD
+ * @latency_timer in PCI clock
+ * @enable_SERR 0 or 1
+ * @enable_PERR 0 or 1
+ */
+struct hpp_param {
+	u8 cache_line_size;
+	u8 latency_timer;
+	u8 enable_SERR;
+	u8 enable_PERR;
+};
+
+
+/**
+ * struct acpiphp_bridge - PCI bridge information
+ *
+ * for each bridge device in ACPI namespace
+ */
+struct acpiphp_bridge {
+	struct list_head list;
+	acpi_handle handle;
+	struct acpiphp_slot *slots;
+	int type;
+	int nr_slots;
+
+	u8 seg;
+	u8 bus;
+	u8 sub;
+
+	u32 flags;
+
+	/* This bus (host bridge) or Secondary bus (PCI-to-PCI bridge) */
+	struct pci_bus *pci_bus;
+
+	/* PCI-to-PCI bridge device */
+	struct pci_dev *pci_dev;
+
+	/* ACPI 2.0 _HPP parameters */
+	struct hpp_param hpp;
+
+	spinlock_t res_lock;
+
+	/* available resources on this bus */
+	struct pci_resource *mem_head;
+	struct pci_resource *p_mem_head;
+	struct pci_resource *io_head;
+	struct pci_resource *bus_head;
+};
+
+
+/**
+ * struct acpiphp_slot - PCI slot information
+ *
+ * PCI slot information for each *physical* PCI slot
+ */
+struct acpiphp_slot {
+	struct acpiphp_slot *next;
+	struct acpiphp_bridge *bridge;	/* parent */
+	struct list_head funcs;		/* one slot may have different
+					   objects (i.e. for each function) */
+	struct semaphore crit_sect;
+
+	u32		id;		/* slot id (serial #) for hotplug core */
+	u8		device;		/* pci device# */
+
+	u32		sun;		/* ACPI _SUN (slot unique number) */
+	u32		slotno;		/* slot number relative to bridge */
+	u32		flags;		/* see below */
+};
+
+
+/**
+ * struct acpiphp_func - PCI function information
+ *
+ * PCI function information for each object in ACPI namespace
+ * typically 8 objects per slot (i.e. for each PCI function)
+ */
+struct acpiphp_func {
+	struct acpiphp_slot *slot;	/* parent */
+
+	struct list_head sibling;
+	struct pci_dev *pci_dev;
+
+	acpi_handle	handle;
+
+	u8		function;	/* pci function# */
+	u32		flags;		/* see below */
+
+	/* resources used for this function */
+	struct pci_resource *mem_head;
+	struct pci_resource *p_mem_head;
+	struct pci_resource *io_head;
+	struct pci_resource *bus_head;
+};
+
+
+/* PCI bus bridge HID */
+#define ACPI_PCI_HOST_HID		"PNP0A03"
+
+/* PCI BRIDGE type */
+#define BRIDGE_TYPE_HOST		0
+#define BRIDGE_TYPE_P2P			1
+
+/* ACPI _STA method value (ignore bit 4; battery present) */
+#define ACPI_STA_PRESENT		(0x00000001)
+#define ACPI_STA_ENABLED		(0x00000002)
+#define ACPI_STA_SHOW_IN_UI		(0x00000004)
+#define ACPI_STA_FUNCTIONING		(0x00000008)
+#define ACPI_STA_ALL			(0x0000000f)
+
+/* bridge flags */
+#define BRIDGE_HAS_STA		(0x00000001)
+#define BRIDGE_HAS_EJ0		(0x00000002)
+#define BRIDGE_HAS_HPP		(0x00000004)
+#define BRIDGE_HAS_PS0		(0x00000010)
+#define BRIDGE_HAS_PS1		(0x00000020)
+#define BRIDGE_HAS_PS2		(0x00000040)
+#define BRIDGE_HAS_PS3		(0x00000080)
+
+/* slot flags */
+
+#define SLOT_POWEREDON		(0x00000001)
+#define SLOT_ENABLED		(0x00000002)
+#define SLOT_MULTIFUNCTION	(x000000004)
+
+/* function flags */
+
+#define FUNC_HAS_STA		(0x00000001)
+#define FUNC_HAS_EJ0		(0x00000002)
+#define FUNC_HAS_PS0		(0x00000010)
+#define FUNC_HAS_PS1		(0x00000020)
+#define FUNC_HAS_PS2		(0x00000040)
+#define FUNC_HAS_PS3		(0x00000080)
+
+/* not yet */
+#define SLOT_SUPPORT_66MHZ	(0x00010000)
+#define SLOT_SUPPORT_100MHZ	(0x00020000)
+#define SLOT_SUPPORT_133MHZ	(0x00040000)
+#define SLOT_SUPPORT_PCIX	(0x00080000)
+
+/* function prototypes */
+
+/* acpiphp_glue.c */
+extern int acpiphp_glue_init (void);
+extern void acpiphp_glue_exit (void);
+extern int acpiphp_get_num_slots (void);
+extern struct acpiphp_slot *get_slot_from_id (int id);
+typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
+extern int acpiphp_for_each_slot (acpiphp_callback fn, void *data);
+
+extern int acpiphp_check_bridge (struct acpiphp_bridge *bridge);
+extern int acpiphp_enable_slot (struct acpiphp_slot *slot);
+extern int acpiphp_disable_slot (struct acpiphp_slot *slot);
+extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot);
+extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot);
+extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
+extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot);
+
+/* acpiphp_pci.c */
+extern struct pci_dev *acpiphp_allocate_pcidev (struct pci_bus *pbus, int dev, int fn);
+extern int acpiphp_configure_slot (struct acpiphp_slot *slot);
+extern int acpiphp_configure_function (struct acpiphp_func *func);
+extern int acpiphp_unconfigure_function (struct acpiphp_func *func);
+extern int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge);
+extern int acpiphp_init_func_resource (struct acpiphp_func *func);
+
+/* acpiphp_res.c */
+extern struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 size);
+extern struct pci_resource *acpiphp_get_max_resource (struct pci_resource **head, u32 size);
+extern struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size);
+extern struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, u64 base, u32 size);
+extern int acpiphp_resource_sort_and_combine (struct pci_resource **head);
+extern struct pci_resource *acpiphp_make_resource (u64 base, u32 length);
+extern void acpiphp_move_resource (struct pci_resource **from, struct pci_resource **to);
+extern void acpiphp_free_resource (struct pci_resource **res);
+extern void acpiphp_dump_resource (struct acpiphp_bridge *bridge); /* debug */
+extern void acpiphp_dump_func_resource (struct acpiphp_func *func); /* debug */
+
+/* variables */
+extern int acpiphp_debug;
+
+#endif /* _ACPIPHP_H */
diff -Nru a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/acpiphp_core.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,505 @@
+/*
+ * ACPI PCI Hot Plug Controller Driver
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
+ * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com)
+ * Copyright (c) 2002 NEC Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gregkh@us.ibm.com>,
+ *                  <h-aono@ap.jp.nec.com>,
+ *		    <t-kouchi@cq.jp.nec.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include "pci_hotplug.h"
+#include "acpiphp.h"
+
+static LIST_HEAD(slot_list);
+
+#if !defined(CONFIG_HOTPLUG_PCI_ACPI_MODULE)
+	#define MY_NAME	"acpiphp"
+#else
+	#define MY_NAME	THIS_MODULE->name
+#endif
+
+static int debug;
+int acpiphp_debug;
+
+/* local variables */
+static int num_slots;
+
+#define DRIVER_VERSION	"0.4"
+#define DRIVER_AUTHOR	"Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-kouchi@cq.jp.nec.com>"
+#define DRIVER_DESC	"ACPI Hot Plug PCI Controller Driver"
+
+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);
+static int get_max_bus_speed	(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value);
+static int get_cur_bus_speed	(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value);
+
+static struct hotplug_slot_ops acpi_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,
+	.get_max_bus_speed	= get_max_bus_speed,
+	.get_cur_bus_speed	= get_cur_bus_speed,
+};
+
+
+/* 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\n", function);
+		return -1;
+	}
+	if (slot->magic != SLOT_MAGIC) {
+		dbg("%s - bad magic number for slot\n", function);
+		return -1;
+	}
+	if (!slot->hotplug_slot) {
+		dbg("%s - slot->hotplug_slot == NULL!\n", 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;
+}
+
+
+/**
+ * enable_slot - power on and enable a slot
+ * @hotplug_slot: slot to enable
+ *
+ * Actual tasks are done in acpiphp_enable_slot()
+ *
+ */
+static int enable_slot (struct hotplug_slot *hotplug_slot)
+{
+	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);
+
+	/* enable the specified slot */
+	retval = acpiphp_enable_slot(slot->acpi_slot);
+
+	return retval;
+}
+
+
+/**
+ * disable_slot - disable and power off a slot
+ * @hotplug_slot: slot to disable
+ *
+ * Actual tasks are done in acpiphp_disable_slot()
+ *
+ */
+static int disable_slot (struct hotplug_slot *hotplug_slot)
+{
+	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);
+
+	/* disable the specified slot */
+	retval = acpiphp_disable_slot(slot->acpi_slot);
+
+	return retval;
+}
+
+
+/**
+ * set_attention_status - set attention LED
+ *
+ * TBD:
+ * ACPI doesn't have known method to manipulate
+ * attention status LED.
+ *
+ */
+static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
+{
+	int retval = 0;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	switch (status) {
+		case 0:
+			/* FIXME turn light off */
+			hotplug_slot->info->attention_status = 0;
+			break;
+
+		case 1:
+		default:
+			/* FIXME turn light on */
+			hotplug_slot->info->attention_status = 1;
+			break;
+	}
+
+	return retval;
+}
+
+
+/**
+ * hardware_test - hardware test
+ *
+ * We have nothing to do for now...
+ *
+ */
+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\n");
+	retval = -ENODEV;
+
+	return retval;
+}
+
+
+/**
+ * get_power_status - get power status of a slot
+ * @hotplug_slot: slot to get status
+ * @value: pointer to store status
+ *
+ * Some platforms may not implement _STA method properly.
+ * In that case, the value returned may not be reliable.
+ *
+ */
+static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *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);
+
+	*value = acpiphp_get_power_status(slot->acpi_slot);
+
+	return retval;
+}
+
+
+/**
+ * get_attention_status - get attention LED status
+ *
+ * TBD:
+ * ACPI doesn't provide any formal means to access attention LED status.
+ *
+ */
+static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	int retval = 0;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	*value = hotplug_slot->info->attention_status;
+
+	return retval;
+}
+
+
+/**
+ * get_latch_status - get latch status of a slot
+ * @hotplug_slot: slot to get status
+ * @value: pointer to store status
+ *
+ * ACPI doesn't provide any formal means to access latch status.
+ * Instead, we fake latch status from _STA
+ *
+ */
+static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *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);
+
+	*value = acpiphp_get_latch_status(slot->acpi_slot);
+
+	return retval;
+}
+
+
+/**
+ * get_adapter_status - get adapter status of a slot
+ * @hotplug_slot: slot to get status
+ * @value: pointer to store status
+ *
+ * ACPI doesn't provide any formal means to access adapter status.
+ * Instead, we fake adapter status from _STA
+ *
+ */
+static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *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);
+
+	*value = acpiphp_get_adapter_status(slot->acpi_slot);
+
+	return retval;
+}
+
+
+/* return dummy value because ACPI doesn't provide any method... */
+static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+{
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	*value = PCI_SPEED_UNKNOWN;
+
+	return 0;
+}
+
+
+/* return dummy value because ACPI doesn't provide any method... */
+static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+{
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	*value = PCI_SPEED_UNKNOWN;
+
+	return 0;
+}
+
+
+static int init_acpi (void)
+{
+	int retval;
+
+	/* initialize internal data structure etc. */
+	retval = acpiphp_glue_init();
+
+	/* read initial number of slots */
+	if (!retval) {
+		num_slots = acpiphp_get_num_slots();
+		if (num_slots == 0)
+			retval = -ENODEV;
+	}
+
+	return retval;
+}
+
+
+/**
+ * make_slot_name - make a slot name that appears in pcihpfs
+ * @slot: slot to name
+ *
+ */
+static void make_slot_name (struct slot *slot)
+{
+	snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "ACPI%d-%02x:%02x",
+		 slot->acpi_slot->sun,
+		 slot->acpi_slot->bridge->bus,
+		 slot->acpi_slot->device);
+}
+
+/**
+ * init_slots - initialize 'struct slot' structures for each slot
+ *
+ */
+static int init_slots (void)
+{
+	struct slot *slot;
+	int retval = 0;
+	int i;
+
+	for (i = 0; i < num_slots; ++i) {
+		slot = kmalloc(sizeof(struct slot), GFP_KERNEL);
+		if (!slot)
+			return -ENOMEM;
+		memset(slot, 0, sizeof(struct slot));
+
+		slot->hotplug_slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
+		if (!slot->hotplug_slot) {
+			kfree(slot);
+			return -ENOMEM;
+		}
+		memset(slot->hotplug_slot, 0, sizeof(struct hotplug_slot));
+
+		slot->hotplug_slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
+		if (!slot->hotplug_slot->info) {
+			kfree(slot->hotplug_slot);
+			kfree(slot);
+			return -ENOMEM;
+		}
+		memset(slot->hotplug_slot->info, 0, sizeof(struct hotplug_slot_info));
+
+		slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
+		if (!slot->hotplug_slot->name) {
+			kfree(slot->hotplug_slot->info);
+			kfree(slot->hotplug_slot);
+			kfree(slot);
+			return -ENOMEM;
+		}
+
+		slot->magic = SLOT_MAGIC;
+		slot->number = i;
+
+		slot->hotplug_slot->private = slot;
+		slot->hotplug_slot->ops = &acpi_hotplug_slot_ops;
+
+		slot->acpi_slot = get_slot_from_id(i);
+		slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot);
+		slot->hotplug_slot->info->attention_status = acpiphp_get_attention_status(slot->acpi_slot);
+		slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot);
+		slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot);
+
+		make_slot_name(slot);
+
+		retval = pci_hp_register(slot->hotplug_slot);
+		if (retval) {
+			err("pci_hp_register failed with error %d\n", retval);
+			kfree(slot->hotplug_slot->info);
+			kfree(slot->hotplug_slot->name);
+			kfree(slot->hotplug_slot);
+			kfree(slot);
+			return retval;
+		}
+
+		/* add slot to our internal list */
+		list_add(&slot->slot_list, &slot_list);
+		info("Slot [%s] registered\n", slot->hotplug_slot->name);
+	}
+
+	return retval;
+}
+
+
+static void cleanup_slots (void)
+{
+	struct list_head *tmp, *n;
+	struct slot *slot;
+
+	list_for_each_safe (tmp, n, &slot_list) {
+		slot = list_entry(tmp, struct slot, slot_list);
+		list_del(&slot->slot_list);
+		pci_hp_deregister(slot->hotplug_slot);
+		kfree(slot->hotplug_slot->info);
+		kfree(slot->hotplug_slot->name);
+		kfree(slot->hotplug_slot);
+		kfree(slot);
+	}
+
+	return;
+}
+
+
+static int __init acpiphp_init(void)
+{
+	int retval;
+
+	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+
+	acpiphp_debug = debug;
+
+	/* read all the ACPI info from the system */
+	retval = init_acpi();
+	if (retval)
+		return retval;
+
+	retval = init_slots();
+	if (retval)
+		return retval;
+
+	return 0;
+}
+
+
+static void __exit acpiphp_exit(void)
+{
+	cleanup_slots();
+	/* deallocate internal data structures etc. */
+	acpiphp_glue_exit();
+}
+
+module_init(acpiphp_init);
+module_exit(acpiphp_exit);
diff -Nru a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/acpiphp_glue.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,1335 @@
+/*
+ * ACPI PCI HotPlug glue functions to ACPI CA subsystem
+ *
+ * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com)
+ * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
+ * Copyright (c) 2002 NEC Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <t-kouchi@cq.jp.nec.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <asm/semaphore.h>
+
+#include "pci_hotplug.h"
+#include "acpiphp.h"
+
+static LIST_HEAD(bridge_list);
+
+#define MY_NAME "acpiphp_glue"
+
+static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
+static void handle_hotplug_event_func (acpi_handle, u32, void *);
+
+/*
+ * initialization & terminatation routines
+ */
+
+/**
+ * is_ejectable - determine if a slot is ejectable
+ * @handle: handle to acpi namespace
+ *
+ * Ejectable slot should satisfy at least these conditions:
+ *
+ *  1. has _ADR method
+ *  2. has _EJ0 method
+ *
+ * optionally
+ *
+ *  1. has _STA method
+ *  2. has _PS0 method
+ *  3. has _PS3 method
+ *  4. ..
+ *
+ */
+static int is_ejectable (acpi_handle handle)
+{
+	acpi_status status;
+	acpi_handle tmp;
+
+	status = acpi_get_handle(handle, "_ADR", &tmp);
+	if (ACPI_FAILURE(status)) {
+		return 0;
+	}
+
+	status = acpi_get_handle(handle, "_EJ0", &tmp);
+	if (ACPI_FAILURE(status)) {
+		return 0;
+	}
+
+	return 1;
+}
+
+
+/* callback routine to check the existence of ejectable slots */
+static acpi_status
+is_ejectable_slot (acpi_handle handle, u32 lvl,	void *context, void **rv)
+{
+	int *count = (int *)context;
+
+	if (is_ejectable(handle)) {
+		(*count)++;
+		/* only one ejectable slot is enough */
+		return AE_CTRL_TERMINATE;
+	} else {
+		return AE_OK;
+	}
+}
+
+
+/* callback routine to register each ACPI PCI slot object */
+static acpi_status
+register_slot (acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+	struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context;
+	struct acpiphp_slot *slot;
+	struct acpiphp_func *newfunc;
+	acpi_handle tmp;
+	acpi_status status = AE_OK;
+	unsigned long adr, sun;
+	int device, function;
+	static int num_slots = 0;	/* XXX if we support I/O node hotplug... */
+
+	status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
+
+	if (ACPI_FAILURE(status))
+		return AE_OK;
+
+	status = acpi_get_handle(handle, "_EJ0", &tmp);
+
+	if (ACPI_FAILURE(status))
+		return AE_OK;
+
+	device = (adr >> 16) & 0xffff;
+	function = adr & 0xffff;
+
+	newfunc = kmalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
+	if (!newfunc)
+		return AE_NO_MEMORY;
+	memset(newfunc, 0, sizeof(struct acpiphp_func));
+
+	INIT_LIST_HEAD(&newfunc->sibling);
+	newfunc->handle = handle;
+	newfunc->function = function;
+	newfunc->flags = FUNC_HAS_EJ0;
+
+	if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp)))
+		newfunc->flags |= FUNC_HAS_STA;
+
+	if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS0", &tmp)))
+		newfunc->flags |= FUNC_HAS_PS0;
+
+	if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp)))
+		newfunc->flags |= FUNC_HAS_PS3;
+
+	status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun);
+	if (ACPI_FAILURE(status))
+		sun = -1;
+
+	/* search for objects that share the same slot */
+	for (slot = bridge->slots; slot; slot = slot->next)
+		if (slot->device == device) {
+			if (slot->sun != sun)
+				warn("sibling found, but _SUN doesn't match!\n");
+			break;
+		}
+
+	if (!slot) {
+		slot = kmalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
+		if (!slot) {
+			kfree(newfunc);
+			return AE_NO_MEMORY;
+		}
+
+		memset(slot, 0, sizeof(struct acpiphp_slot));
+		slot->bridge = bridge;
+		slot->id = num_slots++;
+		slot->device = device;
+		slot->sun = sun;
+		INIT_LIST_HEAD(&slot->funcs);
+		init_MUTEX(&slot->crit_sect);
+
+		slot->next = bridge->slots;
+		bridge->slots = slot;
+
+		bridge->nr_slots++;
+
+		dbg("found ACPI PCI Hotplug slot at PCI %02x:%02x Slot:%d\n",
+		    slot->bridge->bus, slot->device, slot->sun);
+	}
+
+	newfunc->slot = slot;
+	list_add_tail(&newfunc->sibling, &slot->funcs);
+
+	/* associate corresponding pci_dev */
+	newfunc->pci_dev = pci_find_slot(bridge->bus,
+					 PCI_DEVFN(device, function));
+	if (newfunc->pci_dev) {
+		if (acpiphp_init_func_resource(newfunc) < 0) {
+			kfree(newfunc);
+			return AE_ERROR;
+		}
+		slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
+	}
+
+	/* install notify handler */
+	status = acpi_install_notify_handler(handle,
+					     ACPI_SYSTEM_NOTIFY,
+					     handle_hotplug_event_func,
+					     newfunc);
+
+	if (ACPI_FAILURE(status)) {
+		err("failed to register interrupt notify handler\n");
+		kfree(newfunc);
+		return status;
+	}
+
+	return AE_OK;
+}
+
+
+/* see if it's worth looking at this bridge */
+static int detect_ejectable_slots (acpi_handle *bridge_handle)
+{
+	acpi_status status;
+	int count;
+
+	count = 0;
+
+	/* only check slots defined directly below bridge object */
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1,
+				     is_ejectable_slot, (void *)&count, NULL);
+
+	return count;
+}
+
+
+/* decode ACPI _CRS data and convert into our internal resource list
+ * TBD: _TRA, etc.
+ */
+static acpi_status
+decode_acpi_resource (struct acpi_resource *resource, void *context)
+{
+	struct acpiphp_bridge *bridge = (struct acpiphp_bridge *) context;
+	struct acpi_resource_address64 address;
+	struct pci_resource *res;
+
+	if (resource->id != ACPI_RSTYPE_ADDRESS16 &&
+	    resource->id != ACPI_RSTYPE_ADDRESS32 &&
+	    resource->id != ACPI_RSTYPE_ADDRESS64)
+		return AE_OK;
+
+	acpi_resource_to_address64(resource, &address);
+
+	if (address.producer_consumer == ACPI_PRODUCER && address.address_length > 0) {
+		dbg("resource type: %d: 0x%llx - 0x%llx\n", address.resource_type, address.min_address_range, address.max_address_range);
+		res = acpiphp_make_resource(address.min_address_range,
+				    address.address_length);
+		if (!res) {
+			err("out of memory\n");
+			return AE_OK;
+		}
+
+		switch (address.resource_type) {
+		case ACPI_MEMORY_RANGE:
+			if (address.attribute.memory.cache_attribute == ACPI_PREFETCHABLE_MEMORY) {
+				res->next = bridge->p_mem_head;
+				bridge->p_mem_head = res;
+			} else {
+				res->next = bridge->mem_head;
+				bridge->mem_head = res;
+			}
+			break;
+		case ACPI_IO_RANGE:
+			res->next = bridge->io_head;
+			bridge->io_head = res;
+			break;
+		case ACPI_BUS_NUMBER_RANGE:
+			res->next = bridge->bus_head;
+			bridge->bus_head = res;
+			break;
+		default:
+			/* invalid type */
+			kfree(res);
+			break;
+		}
+	}
+
+	return AE_OK;
+}
+
+/* decode ACPI 2.0 _HPP hot plug parameters */
+static void decode_hpp(struct acpiphp_bridge *bridge)
+{
+	acpi_status status;
+	struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER,
+				      .pointer = NULL};
+	union acpi_object *package;
+	int i;
+
+	/* default numbers */
+	bridge->hpp.cache_line_size = 0x10;
+	bridge->hpp.latency_timer = 0x40;
+	bridge->hpp.enable_SERR = 0;
+	bridge->hpp.enable_PERR = 0;
+
+	status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer);
+
+	if (ACPI_FAILURE(status)) {
+		dbg("_HPP evaluation failed\n");
+		return;
+	}
+
+	package = (union acpi_object *) buffer.pointer;
+
+	if (!package || package->type != ACPI_TYPE_PACKAGE ||
+	    package->package.count != 4 || !package->package.elements) {
+		err("invalid _HPP object; ignoring\n");
+		goto err_exit;
+	}
+
+	for (i = 0; i < 4; i++) {
+		if (package->package.elements[i].type != ACPI_TYPE_INTEGER) {
+			err("invalid _HPP parameter type; ignoring\n");
+			goto err_exit;
+		}
+	}
+
+	bridge->hpp.cache_line_size = package->package.elements[0].integer.value;
+	bridge->hpp.latency_timer = package->package.elements[1].integer.value;
+	bridge->hpp.enable_SERR = package->package.elements[2].integer.value;
+	bridge->hpp.enable_PERR = package->package.elements[3].integer.value;
+
+	dbg("_HPP parameter = (%02x, %02x, %02x, %02x)\n",
+	    bridge->hpp.cache_line_size,
+	    bridge->hpp.latency_timer,
+	    bridge->hpp.enable_SERR,
+	    bridge->hpp.enable_PERR);
+
+	bridge->flags |= BRIDGE_HAS_HPP;
+
+ err_exit:
+	kfree(buffer.pointer);
+}
+
+
+/* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */
+static void init_bridge_misc (struct acpiphp_bridge *bridge)
+{
+	acpi_status status;
+
+	/* decode ACPI 2.0 _HPP (hot plug parameters) */
+	decode_hpp(bridge);
+
+	/* subtract all resources already allocated */
+	acpiphp_detect_pci_resource(bridge);
+
+	/* register all slot objects under this bridge */
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
+				     register_slot, bridge, NULL);
+
+	/* install notify handler */
+	status = acpi_install_notify_handler(bridge->handle,
+					     ACPI_SYSTEM_NOTIFY,
+					     handle_hotplug_event_bridge,
+					     bridge);
+
+	if (ACPI_FAILURE(status)) {
+		err("failed to register interrupt notify handler\n");
+	}
+
+	list_add(&bridge->list, &bridge_list);
+
+	dbg("Bridge resource:\n");
+	acpiphp_dump_resource(bridge);
+}
+
+
+/* allocate and initialize host bridge data structure */
+static void add_host_bridge (acpi_handle *handle, int seg, int bus)
+{
+	acpi_status status;
+	struct acpiphp_bridge *bridge;
+
+	bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
+	if (bridge == NULL)
+		return;
+
+	memset(bridge, 0, sizeof(struct acpiphp_bridge));
+
+	bridge->type = BRIDGE_TYPE_HOST;
+	bridge->handle = handle;
+	bridge->seg = seg;
+	bridge->bus = bus;
+
+	bridge->pci_bus = pci_find_bus(bus);
+
+	bridge->res_lock = SPIN_LOCK_UNLOCKED;
+
+	/* to be overridden when we decode _CRS	*/
+	bridge->sub = bridge->bus;
+
+	/* decode resources */
+
+	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+		decode_acpi_resource, bridge);
+
+	if (ACPI_FAILURE(status)) {
+		err("failed to decode bridge resources\n");
+		kfree(bridge);
+		return;
+	}
+
+	acpiphp_resource_sort_and_combine(&bridge->io_head);
+	acpiphp_resource_sort_and_combine(&bridge->mem_head);
+	acpiphp_resource_sort_and_combine(&bridge->p_mem_head);
+	acpiphp_resource_sort_and_combine(&bridge->bus_head);
+
+	dbg("ACPI _CRS resource:\n");
+	acpiphp_dump_resource(bridge);
+
+	if (bridge->bus_head) {
+		bridge->bus = bridge->bus_head->base;
+		bridge->sub = bridge->bus_head->base + bridge->bus_head->length - 1;
+	}
+
+	init_bridge_misc(bridge);
+}
+
+
+/* allocate and initialize PCI-to-PCI bridge data structure */
+static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int fn)
+{
+	struct acpiphp_bridge *bridge;
+	u8 tmp8;
+	u16 tmp16;
+	u64 base64, limit64;
+	u32 base, limit, base32u, limit32u;
+
+	bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
+	if (bridge == NULL) {
+		err("out of memory\n");
+		return;
+	}
+
+	memset(bridge, 0, sizeof(struct acpiphp_bridge));
+
+	bridge->type = BRIDGE_TYPE_P2P;
+	bridge->handle = handle;
+	bridge->seg = seg;
+
+	bridge->pci_dev = pci_find_slot(bus, PCI_DEVFN(dev, fn));
+	if (!bridge->pci_dev) {
+		err("Can't get pci_dev\n");
+		kfree(bridge);
+		return;
+	}
+
+	bridge->pci_bus = bridge->pci_dev->subordinate;
+	if (!bridge->pci_bus) {
+		err("This is not a PCI-to-PCI bridge!\n");
+		kfree(bridge);
+		return;
+	}
+
+	bridge->res_lock = SPIN_LOCK_UNLOCKED;
+
+	bridge->bus = bridge->pci_bus->number;
+	bridge->sub = bridge->pci_bus->subordinate;
+
+	/*
+	 * decode resources under this P2P bridge
+	 */
+
+	/* I/O resources */
+	pci_read_config_byte(bridge->pci_dev, PCI_IO_BASE, &tmp8);
+	base = tmp8;
+	pci_read_config_byte(bridge->pci_dev, PCI_IO_LIMIT, &tmp8);
+	limit = tmp8;
+
+	switch (base & PCI_IO_RANGE_TYPE_MASK) {
+	case PCI_IO_RANGE_TYPE_16:
+		base = (base << 8) & 0xf000;
+		limit = ((limit << 8) & 0xf000) + 0xfff;
+		bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);
+		if (!bridge->io_head) {
+			err("out of memory\n");
+			kfree(bridge);
+			return;
+		}
+		dbg("16bit I/O range: %04x-%04x\n",
+		    (u32)bridge->io_head->base,
+		    (u32)(bridge->io_head->base + bridge->io_head->length - 1));
+		break;
+	case PCI_IO_RANGE_TYPE_32:
+		pci_read_config_word(bridge->pci_dev, PCI_IO_BASE_UPPER16, &tmp16);
+		base = ((u32)tmp16 << 16) | ((base << 8) & 0xf000);
+		pci_read_config_word(bridge->pci_dev, PCI_IO_LIMIT_UPPER16, &tmp16);
+		limit = (((u32)tmp16 << 16) | ((limit << 8) & 0xf000)) + 0xfff;
+		bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);
+		if (!bridge->io_head) {
+			err("out of memory\n");
+			kfree(bridge);
+			return;
+		}
+		dbg("32bit I/O range: %08x-%08x\n",
+		    (u32)bridge->io_head->base,
+		    (u32)(bridge->io_head->base + bridge->io_head->length - 1));
+		break;
+	case 0x0f:
+		dbg("I/O space unsupported\n");
+		break;
+	default:
+		warn("Unknown I/O range type\n");
+	}
+
+	/* Memory resources (mandatory for P2P bridge) */
+	pci_read_config_word(bridge->pci_dev, PCI_MEMORY_BASE, &tmp16);
+	base = (tmp16 & 0xfff0) << 16;
+	pci_read_config_word(bridge->pci_dev, PCI_MEMORY_LIMIT, &tmp16);
+	limit = ((tmp16 & 0xfff0) << 16) | 0xfffff;
+	bridge->mem_head = acpiphp_make_resource((u64)base, limit - base + 1);
+	if (!bridge->mem_head) {
+		err("out of memory\n");
+		kfree(bridge);
+		return;
+	}
+	dbg("32bit Memory range: %08x-%08x\n",
+	    (u32)bridge->mem_head->base,
+	    (u32)(bridge->mem_head->base + bridge->mem_head->length-1));
+
+	/* Prefetchable Memory resources (optional) */
+	pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_BASE, &tmp16);
+	base = tmp16;
+	pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_LIMIT, &tmp16);
+	limit = tmp16;
+
+	switch (base & PCI_MEMORY_RANGE_TYPE_MASK) {
+	case PCI_PREF_RANGE_TYPE_32:
+		base = (base & 0xfff0) << 16;
+		limit = ((limit & 0xfff0) << 16) | 0xfffff;
+		bridge->p_mem_head = acpiphp_make_resource((u64)base, limit - base + 1);
+		if (!bridge->p_mem_head) {
+			err("out of memory\n");
+			kfree(bridge);
+			return;
+		}
+		dbg("32bit Prefetchable memory range: %08x-%08x\n",
+		    (u32)bridge->p_mem_head->base,
+		    (u32)(bridge->p_mem_head->base + bridge->p_mem_head->length - 1));
+		break;
+	case PCI_PREF_RANGE_TYPE_64:
+		pci_read_config_dword(bridge->pci_dev, PCI_PREF_BASE_UPPER32, &base32u);
+		pci_read_config_dword(bridge->pci_dev, PCI_PREF_LIMIT_UPPER32, &limit32u);
+		base64 = ((u64)base32u << 32) | ((base & 0xfff0) << 16);
+		limit64 = (((u64)limit32u << 32) | ((limit & 0xfff0) << 16)) + 0xfffff;
+
+		bridge->p_mem_head = acpiphp_make_resource(base64, limit64 - base64 + 1);
+		if (!bridge->p_mem_head) {
+			err("out of memory\n");
+			kfree(bridge);
+			return;
+		}
+		dbg("64bit Prefetchable memory range: %08x%08x-%08x%08x\n",
+		    (u32)(bridge->p_mem_head->base >> 32),
+		    (u32)(bridge->p_mem_head->base & 0xffffffff),
+		    (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) >> 32),
+		    (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) & 0xffffffff));
+		break;
+	case 0x0f:
+		break;
+	default:
+		warn("Unknown prefetchale memory type\n");
+	}
+
+	init_bridge_misc(bridge);
+}
+
+
+/* callback routine to find P2P bridges */
+static acpi_status
+find_p2p_bridge (acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+	acpi_status status;
+	acpi_handle dummy_handle;
+	unsigned long *segbus = context;
+	unsigned long tmp;
+	int seg, bus, device, function;
+	struct pci_dev *dev;
+
+	/* get PCI address */
+	seg = (*segbus >> 8) & 0xff;
+	bus = *segbus & 0xff;
+
+	status = acpi_get_handle(handle, "_ADR", &dummy_handle);
+	if (ACPI_FAILURE(status))
+		return AE_OK;		/* continue */
+
+	status = acpi_evaluate_integer(handle, "_ADR", NULL, &tmp);
+	if (ACPI_FAILURE(status)) {
+		dbg("%s: _ADR evaluation failure\n", __FUNCTION__);
+		return AE_OK;
+	}
+
+	device = (tmp >> 16) & 0xffff;
+	function = tmp & 0xffff;
+
+	dev = pci_find_slot(bus, PCI_DEVFN(device, function));
+
+	if (!dev)
+		return AE_OK;
+
+	if (!dev->subordinate)
+		return AE_OK;
+
+	/* check if this bridge has ejectable slots */
+	if (detect_ejectable_slots(handle) > 0) {
+		dbg("found PCI-to-PCI bridge at PCI %s\n", dev->slot_name);
+		add_p2p_bridge(handle, seg, bus, device, function);
+	}
+
+	return AE_OK;
+}
+
+
+/* find hot-pluggable slots, and then find P2P bridge */
+static int add_bridges(struct acpi_device *device)
+{
+	acpi_handle *handle = device->handle;
+	acpi_status status;
+	unsigned long tmp;
+	int seg, bus;
+	acpi_handle dummy_handle;
+
+	/* if the bridge doesn't have _STA, we assume it is always there */
+	status = acpi_get_handle(handle, "_STA", &dummy_handle);
+	if (ACPI_SUCCESS(status)) {
+		status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp);
+		if (ACPI_FAILURE(status)) {
+			dbg("%s: _STA evaluation failure\n", __FUNCTION__);
+			return 0;
+		}
+		if ((tmp & ACPI_STA_FUNCTIONING) == 0)
+			/* don't register this object */
+			return 0;
+	}
+
+	/* get PCI segment number */
+	status = acpi_evaluate_integer(handle, "_SEG", NULL, &tmp);
+
+	seg = ACPI_SUCCESS(status) ? tmp : 0;
+
+	/* get PCI bus number */
+	status = acpi_evaluate_integer(handle, "_BBN", NULL, &tmp);
+
+	if (ACPI_SUCCESS(status)) {
+		bus = tmp;
+	} else {
+		warn("can't get bus number, assuming 0\n");
+		bus = 0;
+	}
+
+	/* check if this bridge has ejectable slots */
+	if (detect_ejectable_slots(handle) > 0) {
+		dbg("found PCI host-bus bridge with hot-pluggable slots\n");
+		add_host_bridge(handle, seg, bus);
+		return 0;
+	}
+
+	tmp = seg << 8 | bus;
+
+	/* search P2P bridges under this host bridge */
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
+				     find_p2p_bridge, &tmp, NULL);
+
+	if (ACPI_FAILURE(status))
+		warn("find_p2p_bridge faied (error code = 0x%x)\n",status);
+
+	return 0;
+}
+
+
+static int power_on_slot (struct acpiphp_slot *slot)
+{
+	acpi_status status;
+	struct acpiphp_func *func;
+	struct list_head *l;
+	int retval = 0;
+
+	/* is this already enabled? */
+	if (slot->flags & SLOT_POWEREDON)
+		goto err_exit;
+
+	list_for_each (l, &slot->funcs) {
+		func = list_entry(l, struct acpiphp_func, sibling);
+
+		if (func->flags & FUNC_HAS_PS0) {
+			dbg("%s: executing _PS0 on %s\n", __FUNCTION__,
+			    func->pci_dev->slot_name);
+			status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL);
+			if (ACPI_FAILURE(status)) {
+				warn("%s: _PS0 failed\n", __FUNCTION__);
+				retval = -1;
+				goto err_exit;
+			}
+		}
+	}
+
+	/* TBD: evaluate _STA to check if the slot is enabled */
+
+	slot->flags |= SLOT_POWEREDON;
+
+ err_exit:
+	return retval;
+}
+
+
+static int power_off_slot (struct acpiphp_slot *slot)
+{
+	acpi_status status;
+	struct acpiphp_func *func;
+	struct list_head *l;
+	struct acpi_object_list arg_list;
+	union acpi_object arg;
+
+	int retval = 0;
+
+	/* is this already enabled? */
+	if ((slot->flags & SLOT_POWEREDON) == 0)
+		goto err_exit;
+
+	list_for_each (l, &slot->funcs) {
+		func = list_entry(l, struct acpiphp_func, sibling);
+
+		if (func->flags & FUNC_HAS_PS3) {
+			dbg("%s: executing _PS3 on %s\n", __FUNCTION__,
+			    func->pci_dev->slot_name);
+			status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);
+			if (ACPI_FAILURE(status)) {
+				warn("%s: _PS3 failed\n", __FUNCTION__);
+				retval = -1;
+				goto err_exit;
+			}
+		}
+	}
+
+	list_for_each (l, &slot->funcs) {
+		func = list_entry(l, struct acpiphp_func, sibling);
+
+		if (func->flags & FUNC_HAS_EJ0) {
+			dbg("%s: executing _EJ0 on %s\n", __FUNCTION__,
+			    func->pci_dev->slot_name);
+
+			/* _EJ0 method take one argument */
+			arg_list.count = 1;
+			arg_list.pointer = &arg;
+			arg.type = ACPI_TYPE_INTEGER;
+			arg.integer.value = 1;
+
+			status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);
+			if (ACPI_FAILURE(status)) {
+				warn("%s: _EJ0 failed\n", __FUNCTION__);
+				retval = -1;
+				goto err_exit;
+			}
+		}
+	}
+
+	/* TBD: evaluate _STA to check if the slot is disabled */
+
+	slot->flags &= (~SLOT_POWEREDON);
+
+ err_exit:
+	return retval;
+}
+
+
+/**
+ * enable_device - enable, configure a slot
+ * @slot: slot to be enabled
+ *
+ * This function should be called per *physical slot*,
+ * not per each slot object in ACPI namespace.
+ *
+ */
+static int enable_device (struct acpiphp_slot *slot)
+{
+	u8 bus;
+	struct pci_dev *dev;
+	struct pci_bus *child;
+	struct list_head *l;
+	struct acpiphp_func *func;
+	int retval = 0;
+	int num;
+
+	if (slot->flags & SLOT_ENABLED)
+		goto err_exit;
+
+	/* sanity check: dev should be NULL when hot-plugged in */
+	dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0));
+	if (dev) {
+		/* This case shouldn't happen */
+		err("pci_dev structure already exists.\n");
+		retval = -1;
+		goto err_exit;
+	}
+
+	/* allocate resources to device */
+	retval = acpiphp_configure_slot(slot);
+	if (retval)
+		goto err_exit;
+
+	/* returned `dev' is the *first function* only! */
+	num = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0));
+	if (num)
+		pci_bus_add_devices(slot->bridge->pci_bus);
+	dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0));
+
+	if (!dev) {
+		err("No new device found\n");
+		retval = -1;
+		goto err_exit;
+	}
+
+	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+		pci_read_config_byte(dev, PCI_SECONDARY_BUS, &bus);
+		child = (struct pci_bus*) pci_add_new_bus(dev->bus, dev, bus);
+		pci_do_scan_bus(child);
+	}
+
+	/* associate pci_dev to our representation */
+	list_for_each (l, &slot->funcs) {
+		func = list_entry(l, struct acpiphp_func, sibling);
+
+		func->pci_dev = pci_find_slot(slot->bridge->bus,
+					      PCI_DEVFN(slot->device,
+							func->function));
+		if (!func->pci_dev)
+			continue;
+
+		/* configure device */
+		retval = acpiphp_configure_function(func);
+		if (retval)
+			goto err_exit;
+	}
+
+	slot->flags |= SLOT_ENABLED;
+
+	dbg("Available resources:\n");
+	acpiphp_dump_resource(slot->bridge);
+
+ err_exit:
+	return retval;
+}
+
+
+/**
+ * disable_device - disable a slot
+ */
+static int disable_device (struct acpiphp_slot *slot)
+{
+	int retval = 0;
+	struct acpiphp_func *func;
+	struct list_head *l;
+
+	/* is this slot already disabled? */
+	if (!(slot->flags & SLOT_ENABLED))
+		goto err_exit;
+
+	list_for_each (l, &slot->funcs) {
+		func = list_entry(l, struct acpiphp_func, sibling);
+
+		if (func->pci_dev) {
+			if (acpiphp_unconfigure_function(func) == 0) {
+				func->pci_dev = NULL;
+			} else {
+				err("failed to unconfigure device\n");
+				retval = -1;
+				goto err_exit;
+			}
+		}
+	}
+
+	slot->flags &= (~SLOT_ENABLED);
+
+ err_exit:
+	return retval;
+}
+
+
+/**
+ * get_slot_status - get ACPI slot status
+ *
+ * if a slot has _STA for each function and if any one of them
+ * returned non-zero status, return it
+ *
+ * if a slot doesn't have _STA and if any one of its functions'
+ * configuration space is configured, return 0x0f as a _STA
+ *
+ * otherwise return 0
+ */
+static unsigned int get_slot_status (struct acpiphp_slot *slot)
+{
+	acpi_status status;
+	unsigned long sta = 0;
+	u32 dvid;
+	struct list_head *l;
+	struct acpiphp_func *func;
+
+	list_for_each (l, &slot->funcs) {
+		func = list_entry(l, struct acpiphp_func, sibling);
+
+		if (func->flags & FUNC_HAS_STA) {
+			status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta);
+			if (ACPI_SUCCESS(status) && sta)
+				break;
+		} else {
+			pci_bus_read_config_dword(slot->bridge->pci_bus,
+						  PCI_DEVFN(slot->device,
+							    func->function),
+						  PCI_VENDOR_ID, &dvid);
+			if (dvid != 0xffffffff) {
+				sta = ACPI_STA_ALL;
+				break;
+			}
+		}
+	}
+
+	return (unsigned int)sta;
+}
+
+
+/*
+ * ACPI event handlers
+ */
+
+/**
+ * handle_hotplug_event_bridge - handle ACPI event on bridges
+ *
+ * @handle: Notify()'ed acpi_handle
+ * @type: Notify code
+ * @context: pointer to acpiphp_bridge structure
+ *
+ * handles ACPI event notification on {host,p2p} bridges
+ *
+ */
+static void handle_hotplug_event_bridge (acpi_handle handle, u32 type, void *context)
+{
+	struct acpiphp_bridge *bridge;
+	char objname[64];
+	struct acpi_buffer buffer = { .length = sizeof(objname),
+				      .pointer = objname };
+
+	bridge = (struct acpiphp_bridge *)context;
+
+	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+		/* bus re-enumerate */
+		dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
+		acpiphp_check_bridge(bridge);
+		break;
+
+	case ACPI_NOTIFY_DEVICE_CHECK:
+		/* device check */
+		dbg("%s: Device check notify on %s\n", __FUNCTION__, objname);
+		acpiphp_check_bridge(bridge);
+		break;
+
+	case ACPI_NOTIFY_DEVICE_WAKE:
+		/* wake event */
+		dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname);
+		break;
+
+	case ACPI_NOTIFY_EJECT_REQUEST:
+		/* request device eject */
+		dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
+		break;
+
+	default:
+		warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
+		break;
+	}
+}
+
+
+/**
+ * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
+ *
+ * @handle: Notify()'ed acpi_handle
+ * @type: Notify code
+ * @context: pointer to acpiphp_func structure
+ *
+ * handles ACPI event notification on slots
+ *
+ */
+static void handle_hotplug_event_func (acpi_handle handle, u32 type, void *context)
+{
+	struct acpiphp_func *func;
+	char objname[64];
+	struct acpi_buffer buffer = { .length = sizeof(objname),
+				      .pointer = objname };
+
+	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+
+	func = (struct acpiphp_func *)context;
+
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+		/* bus re-enumerate */
+		dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
+		acpiphp_enable_slot(func->slot);
+		break;
+
+	case ACPI_NOTIFY_DEVICE_CHECK:
+		/* device check : re-enumerate from parent bus */
+		dbg("%s: Device check notify on %s\n", __FUNCTION__, objname);
+		acpiphp_check_bridge(func->slot->bridge);
+		break;
+
+	case ACPI_NOTIFY_DEVICE_WAKE:
+		/* wake event */
+		dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname);
+		break;
+
+	case ACPI_NOTIFY_EJECT_REQUEST:
+		/* request device eject */
+		dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
+		acpiphp_disable_slot(func->slot);
+		break;
+
+	default:
+		warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
+		break;
+	}
+}
+
+static struct acpi_driver acpi_pci_hp_driver = {
+	.name =		"pci_hp",
+	.class =	"",
+	.ids =		ACPI_PCI_HOST_HID,
+	.ops =	{
+		.add =	add_bridges,
+	}
+};
+
+/**
+ * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures
+ *
+ */
+int acpiphp_glue_init (void)
+{
+	acpi_status status;
+
+	if (list_empty(&pci_root_buses))
+		return -1;
+
+	status = acpi_bus_register_driver(&acpi_pci_hp_driver);
+
+	if (ACPI_FAILURE(status)) {
+		err("%s: acpi_walk_namespace() failed\n", __FUNCTION__);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/**
+ * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures
+ *
+ * This function frees all data allocated in acpiphp_glue_init()
+ */
+void acpiphp_glue_exit (void)
+{
+	struct list_head *l1, *l2, *n1, *n2;
+	struct acpiphp_bridge *bridge;
+	struct acpiphp_slot *slot, *next;
+	struct acpiphp_func *func;
+	acpi_status status;
+
+	list_for_each_safe (l1, n1, &bridge_list) {
+		bridge = (struct acpiphp_bridge *)l1;
+		slot = bridge->slots;
+		while (slot) {
+			next = slot->next;
+			list_for_each_safe (l2, n2, &slot->funcs) {
+				func = list_entry(l2, struct acpiphp_func, sibling);
+				acpiphp_free_resource(&func->io_head);
+				acpiphp_free_resource(&func->mem_head);
+				acpiphp_free_resource(&func->p_mem_head);
+				acpiphp_free_resource(&func->bus_head);
+				status = acpi_remove_notify_handler(func->handle,
+								    ACPI_SYSTEM_NOTIFY,
+								    handle_hotplug_event_func);
+				if (ACPI_FAILURE(status))
+					err("failed to remove notify handler\n");
+				kfree(func);
+			}
+			kfree(slot);
+			slot = next;
+		}
+		status = acpi_remove_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY,
+						    handle_hotplug_event_bridge);
+		if (ACPI_FAILURE(status))
+			err("failed to remove notify handler\n");
+
+		acpiphp_free_resource(&bridge->io_head);
+		acpiphp_free_resource(&bridge->mem_head);
+		acpiphp_free_resource(&bridge->p_mem_head);
+		acpiphp_free_resource(&bridge->bus_head);
+
+		kfree(bridge);
+	}
+}
+
+
+/**
+ * acpiphp_get_num_slots - count number of slots in a system
+ */
+int acpiphp_get_num_slots (void)
+{
+	struct list_head *node;
+	struct acpiphp_bridge *bridge;
+	int num_slots;
+
+	num_slots = 0;
+
+	list_for_each (node, &bridge_list) {
+		bridge = (struct acpiphp_bridge *)node;
+		dbg("Bus%d %dslot(s)\n", bridge->bus, bridge->nr_slots);
+		num_slots += bridge->nr_slots;
+	}
+
+	dbg("Total %dslots\n", num_slots);
+	return num_slots;
+}
+
+
+/**
+ * acpiphp_for_each_slot - call function for each slot
+ * @fn: callback function
+ * @data: context to be passed to callback function
+ *
+ */
+int acpiphp_for_each_slot(acpiphp_callback fn, void *data)
+{
+	struct list_head *node;
+	struct acpiphp_bridge *bridge;
+	struct acpiphp_slot *slot;
+	int retval = 0;
+
+	list_for_each (node, &bridge_list) {
+		bridge = (struct acpiphp_bridge *)node;
+		for (slot = bridge->slots; slot; slot = slot->next) {
+			retval = fn(slot, data);
+			if (!retval)
+				goto err_exit;
+		}
+	}
+
+ err_exit:
+	return retval;
+}
+
+
+/* search matching slot from id  */
+struct acpiphp_slot *get_slot_from_id (int id)
+{
+	struct list_head *node;
+	struct acpiphp_bridge *bridge;
+	struct acpiphp_slot *slot;
+
+	list_for_each (node, &bridge_list) {
+		bridge = (struct acpiphp_bridge *)node;
+		for (slot = bridge->slots; slot; slot = slot->next)
+			if (slot->id == id)
+				return slot;
+	}
+
+	/* should never happen! */
+	err("%s: no object for id %d\n",__FUNCTION__, id);
+	return 0;
+}
+
+
+/**
+ * acpiphp_enable_slot - power on slot
+ */
+int acpiphp_enable_slot (struct acpiphp_slot *slot)
+{
+	int retval;
+
+	down(&slot->crit_sect);
+
+	/* wake up all functions */
+	retval = power_on_slot(slot);
+	if (retval)
+		goto err_exit;
+
+	if (get_slot_status(slot) == ACPI_STA_ALL)
+		/* configure all functions */
+		retval = enable_device(slot);
+
+ err_exit:
+	up(&slot->crit_sect);
+	return retval;
+}
+
+
+/**
+ * acpiphp_disable_slot - power off slot
+ */
+int acpiphp_disable_slot (struct acpiphp_slot *slot)
+{
+	int retval = 0;
+
+	down(&slot->crit_sect);
+
+	/* unconfigure all functions */
+	retval = disable_device(slot);
+	if (retval)
+		goto err_exit;
+
+	/* power off all functions */
+	retval = power_off_slot(slot);
+	if (retval)
+		goto err_exit;
+
+	acpiphp_resource_sort_and_combine(&slot->bridge->io_head);
+	acpiphp_resource_sort_and_combine(&slot->bridge->mem_head);
+	acpiphp_resource_sort_and_combine(&slot->bridge->p_mem_head);
+	acpiphp_resource_sort_and_combine(&slot->bridge->bus_head);
+	dbg("Available resources:\n");
+	acpiphp_dump_resource(slot->bridge);
+
+ err_exit:
+	up(&slot->crit_sect);
+	return retval;
+}
+
+
+/**
+ * acpiphp_check_bridge - re-enumerate devices
+ */
+int acpiphp_check_bridge (struct acpiphp_bridge *bridge)
+{
+	struct acpiphp_slot *slot;
+	unsigned int sta;
+	int retval = 0;
+	int enabled, disabled;
+
+	enabled = disabled = 0;
+
+	for (slot = bridge->slots; slot; slot = slot->next) {
+		sta = get_slot_status(slot);
+		if (slot->flags & SLOT_ENABLED) {
+			/* if enabled but not present, disable */
+			if (sta != ACPI_STA_ALL) {
+				retval = acpiphp_disable_slot(slot);
+				if (retval) {
+					err("Error occurred in enabling\n");
+					up(&slot->crit_sect);
+					goto err_exit;
+				}
+				enabled++;
+			}
+		} else {
+			/* if disabled but present, enable */
+			if (sta == ACPI_STA_ALL) {
+				retval = acpiphp_enable_slot(slot);
+				if (retval) {
+					err("Error occurred in enabling\n");
+					up(&slot->crit_sect);
+					goto err_exit;
+				}
+				disabled++;
+			}
+		}
+	}
+
+	dbg("%s: %d enabled, %d disabled\n", __FUNCTION__, enabled, disabled);
+
+ err_exit:
+	return retval;
+}
+
+
+/*
+ * slot enabled:  1
+ * slot disabled: 0
+ */
+u8 acpiphp_get_power_status (struct acpiphp_slot *slot)
+{
+	unsigned int sta;
+
+	sta = get_slot_status(slot);
+
+	return (sta & ACPI_STA_ENABLED) ? 1 : 0;
+}
+
+
+/*
+ * attention LED ON: 1
+ *              OFF: 0
+ *
+ * TBD
+ * no direct attention led status information via ACPI
+ *
+ */
+u8 acpiphp_get_attention_status (struct acpiphp_slot *slot)
+{
+	return 0;
+}
+
+
+/*
+ * latch closed:  1
+ * latch   open:  0
+ */
+u8 acpiphp_get_latch_status (struct acpiphp_slot *slot)
+{
+	unsigned int sta;
+
+	sta = get_slot_status(slot);
+
+	return (sta & ACPI_STA_SHOW_IN_UI) ? 1 : 0;
+}
+
+
+/*
+ * adapter presence : 1
+ *          absence : 0
+ */
+u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot)
+{
+	unsigned int sta;
+
+	sta = get_slot_status(slot);
+
+	return (sta == 0) ? 0 : 1;
+}
diff -Nru a/drivers/pci/hotplug/acpiphp_pci.c b/drivers/pci/hotplug/acpiphp_pci.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/acpiphp_pci.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,510 @@
+/*
+ * ACPI PCI HotPlug PCI configuration space management
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001,2002 IBM Corp.
+ * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com)
+ * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
+ * Copyright (c) 2002 NEC Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <t-kouchi@cq.jp.nec.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include "pci_hotplug.h"
+#include "acpiphp.h"
+
+#define MY_NAME "acpiphp_pci"
+
+
+/* allocate mem/pmem/io resource to a new function */
+static int init_config_space (struct acpiphp_func *func)
+{
+	u32 bar, len;
+	u32 address[] = {
+		PCI_BASE_ADDRESS_0,
+		PCI_BASE_ADDRESS_1,
+		PCI_BASE_ADDRESS_2,
+		PCI_BASE_ADDRESS_3,
+		PCI_BASE_ADDRESS_4,
+		PCI_BASE_ADDRESS_5,
+		0
+	};
+	int count;
+	struct acpiphp_bridge *bridge;
+	struct pci_resource *res;
+	struct pci_bus *pbus;
+	int bus, device, function;
+	unsigned int devfn;
+	u16 tmp;
+
+	bridge = func->slot->bridge;
+	pbus = bridge->pci_bus;
+	bus = bridge->bus;
+	device = func->slot->device;
+	function = func->function;
+	devfn = PCI_DEVFN(device, function);
+
+	for (count = 0; address[count]; count++) {	/* for 6 BARs */
+		pci_bus_write_config_dword(pbus, devfn,
+					   address[count], 0xFFFFFFFF);
+		pci_bus_read_config_dword(pbus, devfn, address[count], &bar);
+
+		if (!bar)	/* This BAR is not implemented */
+			continue;
+
+		dbg("Device %02x.%02x BAR %d wants %x\n", device, function, count, bar);
+
+		if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
+			/* This is IO */
+
+			len = bar & 0xFFFFFFFC;
+			len = ~len + 1;
+
+			dbg("len in IO %x, BAR %d\n", len, count);
+
+			spin_lock(&bridge->res_lock);
+			res = acpiphp_get_io_resource(&bridge->io_head, len);
+			spin_unlock(&bridge->res_lock);
+
+			if (!res) {
+				err("cannot allocate requested io for %02x:%02x.%d len %x\n",
+				    bus, device, function, len);
+				return -1;
+			}
+			pci_bus_write_config_dword(pbus, devfn,
+						   address[count],
+						   (u32)res->base);
+			res->next = func->io_head;
+			func->io_head = res;
+
+		} else {
+			/* This is Memory */
+			if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+				/* pfmem */
+
+				len = bar & 0xFFFFFFF0;
+				len = ~len + 1;
+
+				dbg("len in PFMEM %x, BAR %d\n", len, count);
+
+				spin_lock(&bridge->res_lock);
+				res = acpiphp_get_resource(&bridge->p_mem_head, len);
+				spin_unlock(&bridge->res_lock);
+
+				if (!res) {
+					err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
+					    bus, device, function, len);
+					return -1;
+				}
+
+				pci_bus_write_config_dword(pbus, devfn,
+							   address[count],
+							   (u32)res->base);
+
+				if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {	/* takes up another dword */
+					dbg("inside the pfmem 64 case, count %d\n", count);
+					count += 1;
+					pci_bus_write_config_dword(pbus, devfn,
+								   address[count],
+								   (u32)(res->base >> 32));
+				}
+
+				res->next = func->p_mem_head;
+				func->p_mem_head = res;
+
+			} else {
+				/* regular memory */
+
+				len = bar & 0xFFFFFFF0;
+				len = ~len + 1;
+
+				dbg("len in MEM %x, BAR %d\n", len, count);
+
+				spin_lock(&bridge->res_lock);
+				res = acpiphp_get_resource(&bridge->mem_head, len);
+				spin_unlock(&bridge->res_lock);
+
+				if (!res) {
+					err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
+					    bus, device, function, len);
+					return -1;
+				}
+
+				pci_bus_write_config_dword(pbus, devfn,
+							   address[count],
+							   (u32)res->base);
+
+				if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+					/* takes up another dword */
+					dbg("inside mem 64 case, reg. mem, count %d\n", count);
+					count += 1;
+					pci_bus_write_config_dword(pbus, devfn,
+								   address[count],
+								   (u32)(res->base >> 32));
+				}
+
+				res->next = func->mem_head;
+				func->mem_head = res;
+
+			}
+		}
+	}
+
+	/* disable expansion rom */
+	pci_bus_write_config_dword(pbus, devfn, PCI_ROM_ADDRESS, 0x00000000);
+
+	/* set PCI parameters from _HPP */
+	pci_bus_write_config_byte(pbus, devfn, PCI_CACHE_LINE_SIZE,
+				  bridge->hpp.cache_line_size);
+	pci_bus_write_config_byte(pbus, devfn, PCI_LATENCY_TIMER,
+				  bridge->hpp.latency_timer);
+
+	pci_bus_read_config_word(pbus, devfn, PCI_COMMAND, &tmp);
+	if (bridge->hpp.enable_SERR)
+		tmp |= PCI_COMMAND_SERR;
+	if (bridge->hpp.enable_PERR)
+		tmp |= PCI_COMMAND_PARITY;
+	pci_bus_write_config_word(pbus, devfn, PCI_COMMAND, tmp);
+
+	return 0;
+}
+
+/* detect_used_resource - subtract resource under dev from bridge */
+static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *dev)
+{
+	u32 bar, len;
+	u64 base;
+	u32 address[] = {
+		PCI_BASE_ADDRESS_0,
+		PCI_BASE_ADDRESS_1,
+		PCI_BASE_ADDRESS_2,
+		PCI_BASE_ADDRESS_3,
+		PCI_BASE_ADDRESS_4,
+		PCI_BASE_ADDRESS_5,
+		0
+	};
+	int count;
+	struct pci_resource *res;
+
+	dbg("Device %s\n", dev->slot_name);
+
+	for (count = 0; address[count]; count++) {	/* for 6 BARs */
+		pci_read_config_dword(dev, address[count], &bar);
+
+		if (!bar)	/* This BAR is not implemented */
+			continue;
+
+		pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
+		pci_read_config_dword(dev, address[count], &len);
+
+		if (len & PCI_BASE_ADDRESS_SPACE_IO) {
+			/* This is IO */
+			base = bar & 0xFFFFFFFC;
+			len &= 0xFFFFFFFC;
+			len = ~len + 1;
+
+			dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
+
+			spin_lock(&bridge->res_lock);
+			res = acpiphp_get_resource_with_base(&bridge->io_head, base, len);
+			spin_unlock(&bridge->res_lock);
+			if (res)
+				kfree(res);
+		} else {
+			/* This is Memory */
+			base = bar & 0xFFFFFFF0;
+			if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+				/* pfmem */
+
+				len &= 0xFFFFFFF0;
+				len = ~len + 1;
+
+				if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {	/* takes up another dword */
+					dbg("prefetch mem 64\n");
+					count += 1;
+				}
+				dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
+				spin_lock(&bridge->res_lock);
+				res = acpiphp_get_resource_with_base(&bridge->p_mem_head, base, len);
+				spin_unlock(&bridge->res_lock);
+				if (res)
+					kfree(res);
+			} else {
+				/* regular memory */
+
+				len &= 0xFFFFFFF0;
+				len = ~len + 1;
+
+				if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+					/* takes up another dword */
+					dbg("mem 64\n");
+					count += 1;
+				}
+				dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
+				spin_lock(&bridge->res_lock);
+				res = acpiphp_get_resource_with_base(&bridge->mem_head, base, len);
+				spin_unlock(&bridge->res_lock);
+				if (res)
+					kfree(res);
+			}
+		}
+
+		pci_write_config_dword(dev, address[count], bar);
+	}
+
+	return 0;
+}
+
+
+/* detect_pci_resource_bus - subtract resource under pci_bus */
+static void detect_used_resource_bus(struct acpiphp_bridge *bridge, struct pci_bus *bus)
+{
+	struct list_head *l;
+	struct pci_dev *dev;
+
+	list_for_each (l, &bus->devices) {
+		dev = pci_dev_b(l);
+		detect_used_resource(bridge, dev);
+		/* XXX recursive call */
+		if (dev->subordinate)
+			detect_used_resource_bus(bridge, dev->subordinate);
+	}
+}
+
+
+/**
+ * acpiphp_detect_pci_resource - detect resources under bridge
+ * @bridge: detect all resources already used under this bridge
+ *
+ * collect all resources already allocated for all devices under a bridge.
+ */
+int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge)
+{
+	detect_used_resource_bus(bridge, bridge->pci_bus);
+
+	return 0;
+}
+
+
+/**
+ * acpiphp_init_slot_resource - gather resource usage information of a slot
+ * @slot: ACPI slot object to be checked, should have valid pci_dev member
+ *
+ * TBD: PCI-to-PCI bridge case
+ *      use pci_dev->resource[]
+ */
+int acpiphp_init_func_resource (struct acpiphp_func *func)
+{
+	u64 base;
+	u32 bar, len;
+	u32 address[] = {
+		PCI_BASE_ADDRESS_0,
+		PCI_BASE_ADDRESS_1,
+		PCI_BASE_ADDRESS_2,
+		PCI_BASE_ADDRESS_3,
+		PCI_BASE_ADDRESS_4,
+		PCI_BASE_ADDRESS_5,
+		0
+	};
+	int count;
+	struct pci_resource *res;
+	struct pci_dev *dev;
+
+	dev = func->pci_dev;
+	dbg("Hot-pluggable device %s\n", dev->slot_name);
+
+	for (count = 0; address[count]; count++) {	/* for 6 BARs */
+		pci_read_config_dword(dev, address[count], &bar);
+
+		if (!bar)	/* This BAR is not implemented */
+			continue;
+
+		pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
+		pci_read_config_dword(dev, address[count], &len);
+
+		if (len & PCI_BASE_ADDRESS_SPACE_IO) {
+			/* This is IO */
+			base = bar & 0xFFFFFFFC;
+			len &= 0xFFFFFFFC;
+			len = ~len + 1;
+
+			dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
+
+			res = acpiphp_make_resource(base, len);
+			if (!res)
+				goto no_memory;
+
+			res->next = func->io_head;
+			func->io_head = res;
+
+		} else {
+			/* This is Memory */
+			base = bar & 0xFFFFFFF0;
+			if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+				/* pfmem */
+
+				len &= 0xFFFFFFF0;
+				len = ~len + 1;
+
+				if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {	/* takes up another dword */
+					dbg("prefetch mem 64\n");
+					count += 1;
+				}
+				dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
+				res = acpiphp_make_resource(base, len);
+				if (!res)
+					goto no_memory;
+
+				res->next = func->p_mem_head;
+				func->p_mem_head = res;
+
+			} else {
+				/* regular memory */
+
+				len &= 0xFFFFFFF0;
+				len = ~len + 1;
+
+				if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+					/* takes up another dword */
+					dbg("mem 64\n");
+					count += 1;
+				}
+				dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
+				res = acpiphp_make_resource(base, len);
+				if (!res)
+					goto no_memory;
+
+				res->next = func->mem_head;
+				func->mem_head = res;
+
+			}
+		}
+
+		pci_write_config_dword(dev, address[count], bar);
+	}
+#if 1
+	acpiphp_dump_func_resource(func);
+#endif
+
+	return 0;
+
+ no_memory:
+	err("out of memory\n");
+	acpiphp_free_resource(&func->io_head);
+	acpiphp_free_resource(&func->mem_head);
+	acpiphp_free_resource(&func->p_mem_head);
+
+	return -1;
+}
+
+
+/**
+ * acpiphp_configure_slot - allocate PCI resources
+ * @slot: slot to be configured
+ *
+ * initializes a PCI functions on a device inserted
+ * into the slot
+ *
+ */
+int acpiphp_configure_slot (struct acpiphp_slot *slot)
+{
+	struct acpiphp_func *func;
+	struct list_head *l;
+	u8 hdr;
+	u32 dvid;
+	int retval = 0;
+	int is_multi = 0;
+
+	pci_bus_read_config_byte(slot->bridge->pci_bus,
+				 PCI_DEVFN(slot->device, 0),
+				 PCI_HEADER_TYPE, &hdr);
+
+	if (hdr & 0x80)
+		is_multi = 1;
+
+	list_for_each (l, &slot->funcs) {
+		func = list_entry(l, struct acpiphp_func, sibling);
+		if (is_multi || func->function == 0) {
+			pci_bus_read_config_dword(slot->bridge->pci_bus,
+						  PCI_DEVFN(slot->device,
+							    func->function),
+						  PCI_VENDOR_ID, &dvid);
+			if (dvid != 0xffffffff) {
+				retval = init_config_space(func);
+				if (retval)
+					break;
+			}
+		}
+	}
+
+	return retval;
+}
+
+/**
+ * acpiphp_configure_function - configure PCI function
+ * @func: function to be configured
+ *
+ * initializes a PCI functions on a device inserted
+ * into the slot
+ *
+ */
+int acpiphp_configure_function (struct acpiphp_func *func)
+{
+	/* all handled by the pci core now */
+	return 0;
+}
+
+/**
+ * acpiphp_unconfigure_function - unconfigure PCI function
+ * @func: function to be unconfigured
+ *
+ */
+int acpiphp_unconfigure_function (struct acpiphp_func *func)
+{
+	struct acpiphp_bridge *bridge;
+	int retval = 0;
+
+	/* if pci_dev is NULL, ignore it */
+	if (!func->pci_dev)
+		goto err_exit;
+
+	pci_remove_bus_device(func->pci_dev);
+
+	/* free all resources */
+	bridge = func->slot->bridge;
+
+	spin_lock(&bridge->res_lock);
+	acpiphp_move_resource(&func->io_head, &bridge->io_head);
+	acpiphp_move_resource(&func->mem_head, &bridge->mem_head);
+	acpiphp_move_resource(&func->p_mem_head, &bridge->p_mem_head);
+	acpiphp_move_resource(&func->bus_head, &bridge->bus_head);
+	spin_unlock(&bridge->res_lock);
+
+ err_exit:
+	return retval;
+}
diff -Nru a/drivers/pci/hotplug/acpiphp_res.c b/drivers/pci/hotplug/acpiphp_res.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/acpiphp_res.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,699 @@
+/*
+ * ACPI PCI HotPlug Utility functions
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
+ * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com)
+ * Copyright (c) 2002 NEC Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gregkh@us.ibm.com>,<h-aono@ap.jp.nec.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/sysctl.h>
+#include <linux/pci.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+
+#include <linux/ioctl.h>
+#include <linux/fcntl.h>
+
+#include <linux/list.h>
+
+#include "pci_hotplug.h"
+#include "acpiphp.h"
+
+#define MY_NAME "acpiphp_res"
+
+
+/*
+ * sort_by_size - sort nodes 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;
+}
+
+
+/*
+ * sort_by_max_size - sort nodes 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_io_resource - get resource for I/O ports
+ *
+ * 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.
+ *
+ * difference from get_resource is handling of ISA aliasing space.
+ *
+ */
+struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 size)
+{
+	struct pci_resource *prevnode;
+	struct pci_resource *node;
+	struct pci_resource *split_node;
+	u64 temp_qword;
+
+	if (!(*head))
+		return NULL;
+
+	if (acpiphp_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_qword = (node->base | (size-1)) + 1;
+
+			/* Short circuit if adjusted size is too small */
+			if ((node->length - (temp_qword - node->base)) < size)
+				continue;
+
+			split_node = acpiphp_make_resource(node->base, temp_qword - node->base);
+
+			if (!split_node)
+				return NULL;
+
+			node->base = temp_qword;
+			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 = acpiphp_make_resource(node->base + size, node->length - size);
+
+			if (!split_node)
+				return NULL;
+
+			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_max_resource - get the largest 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.
+ */
+struct pci_resource *acpiphp_get_max_resource (struct pci_resource **head, u32 size)
+{
+	struct pci_resource *max;
+	struct pci_resource *temp;
+	struct pci_resource *split_node;
+	u64 temp_qword;
+
+	if (!(*head))
+		return NULL;
+
+	if (acpiphp_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_qword = (max->base | (size-1)) + 1;
+
+			/* Short circuit if adjusted size is too small */
+			if ((max->length - (temp_qword - max->base)) < size)
+				continue;
+
+			split_node = acpiphp_make_resource(max->base, temp_qword - max->base);
+
+			if (!split_node)
+				return NULL;
+
+			max->base = temp_qword;
+			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 */
+			temp_qword = ((max->base + max->length) & ~(size - 1));
+
+			split_node = acpiphp_make_resource(temp_qword,
+							   max->length + max->base - temp_qword);
+
+			if (!split_node)
+				return NULL;
+
+			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_resource - get resource (mem, pfmem)
+ *
+ * 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.
+ *
+ */
+struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size)
+{
+	struct pci_resource *prevnode;
+	struct pci_resource *node;
+	struct pci_resource *split_node;
+	u64 temp_qword;
+
+	if (!(*head))
+		return NULL;
+
+	if (acpiphp_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, (u32)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_qword = (node->base | (size-1)) + 1;
+
+			/* Short circuit if adjusted size is too small */
+			if ((node->length - (temp_qword - node->base)) < size)
+				continue;
+
+			split_node = acpiphp_make_resource(node->base, temp_qword - node->base);
+
+			if (!split_node)
+				return NULL;
+
+			node->base = temp_qword;
+			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 = acpiphp_make_resource(node->base + size, node->length - size);
+
+			if (!split_node)
+				return NULL;
+
+			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;
+}
+
+/**
+ * get_resource_with_base - get resource with specific base address
+ *
+ * this function
+ * returns the first node of "size" length located at specified base address.
+ * If it finds a node larger than "size" it will split it up.
+ *
+ * size must be a power of two.
+ *
+ */
+struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, u64 base, u32 size)
+{
+	struct pci_resource *prevnode;
+	struct pci_resource *node;
+	struct pci_resource *split_node;
+	u64 temp_qword;
+
+	if (!(*head))
+		return NULL;
+
+	if (acpiphp_resource_sort_and_combine(head))
+		return NULL;
+
+	for (node = *head; node; node = node->next) {
+		dbg(": 1st req_base=%x req_size =%x node=%p, base=%x, length=%x\n",
+		    (u32)base, size, node, (u32)node->base, node->length);
+		if (node->base > base)
+			continue;
+
+		if ((node->base + node->length) < (base + size))
+			continue;
+
+		if (node->base < base) {
+			dbg(": split 1\n");
+			/* this one isn't base aligned properly
+			   so we'll make a new entry and split it up */
+			temp_qword = base;
+
+			/* Short circuit if adjusted size is too small */
+			if ((node->length - (temp_qword - node->base)) < size)
+				continue;
+
+			split_node = acpiphp_make_resource(node->base, temp_qword - node->base);
+
+			if (!split_node)
+				return NULL;
+
+			node->base = temp_qword;
+			node->length -= split_node->length;
+
+			/* Put it in the list */
+			split_node->next = node->next;
+			node->next = split_node;
+		}
+
+		dbg(": 2nd req_base=%x req_size =%x node=%p, base=%x, length=%x\n",
+		    (u32)base, size, node, (u32)node->base, node->length);
+
+		/* Don't need to check if too small since we already did */
+		if (node->length > size) {
+			dbg(": split 2\n");
+			/* this one is longer than we need
+			   so we'll make a new entry and split it up */
+			split_node = acpiphp_make_resource(node->base + size, node->length - size);
+
+			if (!split_node)
+				return NULL;
+
+			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(": got one!!!\n");
+		/* 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;
+}
+
+
+/**
+ * acpiphp_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 acpiphp_resource_sort_and_combine (struct pci_resource **head)
+{
+	struct pci_resource *node1;
+	struct pci_resource *node2;
+	int out_of_order = 1;
+
+	if (!(*head))
+		return 1;
+
+	dbg("*head->next = %p\n",(*head)->next);
+
+	if (!(*head)->next)
+		return 0;	/* only one item on the list, already sorted! */
+
+	dbg("*head->base = 0x%x\n",(u32)(*head)->base);
+	dbg("*head->next->base = 0x%x\n", (u32)(*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("8..\n");
+			node1->length += node1->next->length;
+			node2 = node1->next;
+			node1->next = node1->next->next;
+			kfree(node2);
+		} else
+			node1 = node1->next;
+	}
+
+	return 0;
+}
+
+
+/**
+ * acpiphp_make_resource - make resource structure
+ * @base: base address of a resource
+ * @length: length of a resource
+ */
+struct pci_resource *acpiphp_make_resource (u64 base, u32 length)
+{
+	struct pci_resource *res;
+
+	res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+	if (res) {
+		memset(res, 0, sizeof(struct pci_resource));
+		res->base = base;
+		res->length = length;
+	}
+
+	return res;
+}
+
+
+/**
+ * acpiphp_move_resource - move linked resources from one to another
+ * @from: head of linked resource list
+ * @to: head of linked resource list
+ */
+void acpiphp_move_resource (struct pci_resource **from, struct pci_resource **to)
+{
+	struct pci_resource *tmp;
+
+	while (*from) {
+		tmp = (*from)->next;
+		(*from)->next = *to;
+		*to = *from;
+		*from = tmp;
+	}
+
+	/* *from = NULL is guaranteed */
+}
+
+
+/**
+ * acpiphp_free_resource - free all linked resources
+ * @res: head of linked resource list
+ */
+void acpiphp_free_resource (struct pci_resource **res)
+{
+	struct pci_resource *tmp;
+
+	while (*res) {
+		tmp = (*res)->next;
+		kfree(*res);
+		*res = tmp;
+	}
+
+	/* *res = NULL is guaranteed */
+}
+
+
+/* debug support functions;  will go away sometime :) */
+static void dump_resource(struct pci_resource *head)
+{
+	struct pci_resource *p;
+	int cnt;
+
+	p = head;
+	cnt = 0;
+
+	while (p) {
+		dbg("[%02d] %08x - %08x\n",
+		    cnt++, (u32)p->base, (u32)p->base + p->length - 1);
+		p = p->next;
+	}
+}
+
+void acpiphp_dump_resource(struct acpiphp_bridge *bridge)
+{
+	dbg("I/O resource:\n");
+	dump_resource(bridge->io_head);
+	dbg("MEM resource:\n");
+	dump_resource(bridge->mem_head);
+	dbg("PMEM resource:\n");
+	dump_resource(bridge->p_mem_head);
+	dbg("BUS resource:\n");
+	dump_resource(bridge->bus_head);
+}
+
+void acpiphp_dump_func_resource(struct acpiphp_func *func)
+{
+	dbg("I/O resource:\n");
+	dump_resource(func->io_head);
+	dbg("MEM resource:\n");
+	dump_resource(func->mem_head);
+	dbg("PMEM resource:\n");
+	dump_resource(func->p_mem_head);
+	dbg("BUS resource:\n");
+	dump_resource(func->bus_head);
+}
diff -Nru a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/cpci_hotplug.h	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,100 @@
+/*
+ * CompactPCI Hot Plug Core Functions
+ *
+ * Copyright (c) 2002 SOMA Networks, Inc.
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <scottm@somanetworks.com>
+ */
+
+#ifndef _CPCI_HOTPLUG_H
+#define _CPCI_HOTPLUG_H
+
+#include <linux/types.h>
+#include <linux/pci.h>
+
+/* PICMG 2.12 R2.0 HS CSR bits: */
+#define HS_CSR_INS	0x0080
+#define HS_CSR_EXT	0x0040
+#define HS_CSR_PI	0x0030
+#define HS_CSR_LOO	0x0008
+#define HS_CSR_PIE	0x0004
+#define HS_CSR_EIM	0x0002
+#define HS_CSR_DHA	0x0001
+
+#define SLOT_MAGIC	0x67267322
+struct slot {
+	u32 magic;
+	u8 number;
+	unsigned int devfn;
+	struct pci_bus *bus;
+	struct pci_dev *dev;
+	unsigned int extracting;
+	struct hotplug_slot *hotplug_slot;
+	struct list_head slot_list;
+};
+
+struct cpci_hp_controller_ops {
+	int (*query_enum) (void);
+	int (*enable_irq) (void);
+	int (*disable_irq) (void);
+	int (*check_irq) (void *dev_id);
+	int (*hardware_test) (struct slot* slot, u32 value);
+	u8  (*get_power) (struct slot* slot);
+	int (*set_power) (struct slot* slot, int value);
+};
+
+struct cpci_hp_controller {
+	unsigned int irq;
+	unsigned long irq_flags;
+	char *devname;
+	void *dev_id;
+	char *name;
+	struct cpci_hp_controller_ops *ops;
+};
+
+extern int cpci_hp_register_controller(struct cpci_hp_controller *controller);
+extern int cpci_hp_unregister_controller(struct cpci_hp_controller *controller);
+extern int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last);
+extern int cpci_hp_unregister_bus(struct pci_bus *bus);
+extern struct slot *cpci_find_slot(struct pci_bus *bus, unsigned int devfn);
+extern int cpci_hp_start(void);
+extern int cpci_hp_stop(void);
+
+/*
+ * Internal function prototypes, these functions should not be used by
+ * board/chassis drivers.
+ */
+extern u8 cpci_get_attention_status(struct slot *slot);
+extern u8 cpci_get_latch_status(struct slot *slot);
+extern u8 cpci_get_adapter_status(struct slot *slot);
+extern u16 cpci_get_hs_csr(struct slot * slot);
+extern u16 cpci_set_hs_csr(struct slot * slot, u16 hs_csr);
+extern int cpci_set_attention_status(struct slot *slot, int status);
+extern int cpci_check_and_clear_ins(struct slot * slot);
+extern int cpci_check_ext(struct slot * slot);
+extern int cpci_clear_ext(struct slot * slot);
+extern int cpci_led_on(struct slot * slot);
+extern int cpci_led_off(struct slot * slot);
+extern int cpci_configure_slot(struct slot *slot);
+extern int cpci_unconfigure_slot(struct slot *slot);
+
+#endif	/* _CPCI_HOTPLUG_H */
diff -Nru a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,919 @@
+/*
+ * CompactPCI Hot Plug Driver
+ *
+ * Copyright (c) 2002 SOMA Networks, Inc.
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <scottm@somanetworks.com>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/smp_lock.h>
+#include "pci_hotplug.h"
+#include "cpci_hotplug.h"
+
+#define DRIVER_VERSION	"0.2"
+#define DRIVER_AUTHOR	"Scott Murray <scottm@somanetworks.com>"
+#define DRIVER_DESC	"CompactPCI Hot Plug Core"
+
+#if !defined(CONFIG_HOTPLUG_CPCI_MODULE)
+#define MY_NAME	"cpci_hotplug"
+#else
+#define MY_NAME	THIS_MODULE->name
+#endif
+
+#define dbg(format, arg...)					\
+	do {							\
+		if(cpci_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)
+
+/* local variables */
+static spinlock_t list_lock;
+static LIST_HEAD(slot_list);
+static int slots;
+int cpci_debug;
+static struct cpci_hp_controller *controller;
+static struct semaphore event_semaphore;	/* mutex for process loop (up if something to process) */
+static struct semaphore thread_exit;		/* guard ensure thread has exited before calling it quits */
+static int thread_finished = 1;
+
+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 get_power_status(struct hotplug_slot *slot, u8 * value);
+static int get_attention_status(struct hotplug_slot *slot, u8 * value);
+static int get_latch_status(struct hotplug_slot *slot, u8 * value);
+static int get_adapter_status(struct hotplug_slot *slot, u8 * value);
+
+static struct hotplug_slot_ops cpci_hotplug_slot_ops = {
+	.owner = THIS_MODULE,
+	.enable_slot = enable_slot,
+	.disable_slot = disable_slot,
+	.set_attention_status = set_attention_status,
+	.hardware_test = NULL,
+	.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", function);
+		return NULL;
+	}
+
+	slot = (struct slot *) hotplug_slot->private;
+	if(slot_paranoia_check(slot, function))
+		return NULL;
+	return slot;
+}
+
+static int
+update_latch_status(struct hotplug_slot *hotplug_slot, u8 value)
+{
+	struct hotplug_slot_info info;
+
+	if(!(hotplug_slot && hotplug_slot->info))
+		return -EINVAL;
+	memcpy(&info, hotplug_slot->info, sizeof(struct hotplug_slot_info));
+	info.latch_status = value;
+	return pci_hp_change_slot_info(hotplug_slot, &info);
+}
+
+static int
+update_adapter_status(struct hotplug_slot *hotplug_slot, u8 value)
+{
+	struct hotplug_slot_info info;
+
+	if(!(hotplug_slot && hotplug_slot->info))
+		return -EINVAL;
+	memcpy(&info, hotplug_slot->info, sizeof(struct hotplug_slot_info));
+	info.adapter_status = value;
+	return pci_hp_change_slot_info(hotplug_slot, &info);
+}
+
+static int
+enable_slot(struct hotplug_slot *hotplug_slot)
+{
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+	int retval = 0;
+
+	if(slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
+
+	if(controller->ops->set_power) {
+		retval = controller->ops->set_power(slot, 1);
+	}
+
+	return retval;
+}
+
+static int
+disable_slot(struct hotplug_slot *hotplug_slot)
+{
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+	int retval = 0;
+
+	if(slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
+
+	/* Unconfigure device */
+	dbg("%s - unconfiguring slot %s",
+	    __FUNCTION__, slot->hotplug_slot->name);
+	if((retval = cpci_unconfigure_slot(slot))) {
+		err("%s - could not unconfigure slot %s",
+		    __FUNCTION__, slot->hotplug_slot->name);
+		return retval;
+	}
+	dbg("%s - finished unconfiguring slot %s",
+	    __FUNCTION__, slot->hotplug_slot->name);
+
+	/* Clear EXT (by setting it) */
+	if(cpci_clear_ext(slot)) {
+		err("%s - could not clear EXT for slot %s",
+		    __FUNCTION__, slot->hotplug_slot->name);
+		retval = -ENODEV;
+	}
+	cpci_led_on(slot);
+
+	if(controller->ops->set_power) {
+		retval = controller->ops->set_power(slot, 0);
+	}
+
+	if(update_adapter_status(slot->hotplug_slot, 0)) {
+		warn("failure to update adapter file");
+	}
+
+	slot->extracting = 0;
+
+	return retval;
+}
+
+static u8
+cpci_get_power_status(struct slot *slot)
+{
+	u8 power = 1;
+
+	if(controller->ops->get_power) {
+		power = controller->ops->get_power(slot);
+	}
+	return power;
+}
+
+static int
+get_power_status(struct hotplug_slot *hotplug_slot, u8 * value)
+{
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+
+	if(slot == NULL)
+		return -ENODEV;
+	*value = cpci_get_power_status(slot);
+	return 0;
+}
+
+static int
+get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value)
+{
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+
+	if(slot == NULL)
+		return -ENODEV;
+	*value = cpci_get_attention_status(slot);
+	return 0;
+}
+
+static int
+set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
+{
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+
+	if(slot == NULL)
+		return -ENODEV;
+	switch (status) {
+	case 0:
+		cpci_set_attention_status(slot, 0);
+		break;
+
+	case 1:
+	default:
+		cpci_set_attention_status(slot, 1);
+		break;
+	}
+
+	return 0;
+}
+
+static int
+get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value)
+{
+	if(hotplug_slot == NULL || hotplug_slot->info == NULL)
+		return -ENODEV;
+	*value = hotplug_slot->info->latch_status;
+	return 0;
+}
+
+static int
+get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value)
+{
+	if(hotplug_slot == NULL || hotplug_slot->info == NULL)
+		return -ENODEV;
+	*value = hotplug_slot->info->adapter_status;
+	return 0;
+}
+
+#define SLOT_NAME_SIZE	6
+static void
+make_slot_name(struct slot *slot)
+{
+	snprintf(slot->hotplug_slot->name,
+		 SLOT_NAME_SIZE, "%02x:%02x", slot->bus->number, slot->number);
+}
+
+int
+cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
+{
+	struct slot *slot;
+	struct hotplug_slot *hotplug_slot;
+	struct hotplug_slot_info *info;
+	char *name;
+	int status = 0;
+	int i;
+
+	if(!(controller && bus)) {
+		return -ENODEV;
+	}
+	if(last < first) {
+		return -EINVAL;
+	}
+
+	/*
+	 * Create a structure for each slot, and register that slot
+	 * with the pci_hotplug subsystem.
+	 */
+	for (i = first; i <= last; ++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->bus = bus;
+		slot->number = i;
+		slot->devfn = PCI_DEVFN(i, 0);
+
+		hotplug_slot->private = slot;
+		make_slot_name(slot);
+		hotplug_slot->ops = &cpci_hotplug_slot_ops;
+
+		/*
+		 * Initialize the slot info structure with some known
+		 * good values.
+		 */
+		dbg("initializing slot %s", slot->hotplug_slot->name);
+		info->power_status = cpci_get_power_status(slot);
+		info->attention_status = cpci_get_attention_status(slot);
+
+		dbg("registering slot %s", slot->hotplug_slot->name);
+		status = pci_hp_register(slot->hotplug_slot);
+		if(status) {
+			err("pci_hp_register failed with error %d", status);
+			kfree(info);
+			kfree(name);
+			kfree(hotplug_slot);
+			kfree(slot);
+			return status;
+		}
+
+		/* Add slot to our internal list */
+		spin_lock(&list_lock);
+		list_add(&slot->slot_list, &slot_list);
+		slots++;
+		spin_unlock(&list_lock);
+	}
+	return status;
+}
+
+int
+cpci_hp_unregister_bus(struct pci_bus *bus)
+{
+	struct slot *slot;
+	struct list_head *tmp;
+	int status;
+
+	if(!bus) {
+		return -ENODEV;
+	}
+
+	spin_lock(&list_lock);
+	if(!slots) {
+		spin_unlock(&list_lock);
+		return -1;
+	}
+	list_for_each(tmp, &slot_list) {
+		slot = list_entry(tmp, struct slot, slot_list);
+		if(slot->bus == bus) {
+			dbg("deregistering slot %s", slot->hotplug_slot->name);
+			status = pci_hp_deregister(slot->hotplug_slot);
+			if(status) {
+				err("pci_hp_deregister failed with error %d",
+				    status);
+				return status;
+			}
+
+			list_del(&slot->slot_list);
+			kfree(slot->hotplug_slot->info);
+			kfree(slot->hotplug_slot->name);
+			kfree(slot->hotplug_slot);
+			kfree(slot);
+
+			slots--;
+		}
+	}
+	spin_unlock(&list_lock);
+	return 0;
+}
+
+struct slot *
+cpci_find_slot(struct pci_bus *bus, unsigned int devfn)
+{
+	struct slot *slot;
+	struct slot *found;
+	struct list_head *tmp;
+
+	if(!bus) {
+		return NULL;
+	}
+
+	spin_lock(&list_lock);
+	if(!slots) {
+		spin_unlock(&list_lock);
+		return NULL;
+	}
+	found = NULL;
+	list_for_each(tmp, &slot_list) {
+		slot = list_entry(tmp, struct slot, slot_list);
+		if(slot->bus == bus && slot->devfn == devfn) {
+			found = slot;
+			break;
+		}
+	}
+	spin_unlock(&list_lock);
+	return found;
+}
+
+/* This is the interrupt mode interrupt handler */
+irqreturn_t
+cpci_hp_intr(int irq, void *data, struct pt_regs *regs)
+{
+	dbg("entered cpci_hp_intr");
+
+	/* Check to see if it was our interrupt */
+	if((controller->irq_flags & SA_SHIRQ) &&
+	    !controller->ops->check_irq(controller->dev_id)) {
+		dbg("exited cpci_hp_intr, not our interrupt");
+		return IRQ_NONE;
+	}
+
+	/* Disable ENUM interrupt */
+	controller->ops->disable_irq();
+
+	/* Trigger processing by the event thread */
+	dbg("Signal event_semaphore");
+	up(&event_semaphore);
+	dbg("exited cpci_hp_intr");
+	return IRQ_HANDLED;
+}
+
+/*
+ * According to PICMG 2.12 R2.0, section 6.3.2, upon
+ * initialization, the system driver shall clear the
+ * INS bits of the cold-inserted devices.
+ */
+static int
+init_slots(void)
+{
+	struct slot *slot;
+	struct list_head *tmp;
+	struct pci_dev* dev;
+
+	dbg("%s - enter", __FUNCTION__);
+	spin_lock(&list_lock);
+	if(!slots) {
+		spin_unlock(&list_lock);
+		return -1;
+	}
+	list_for_each(tmp, &slot_list) {
+		slot = list_entry(tmp, struct slot, slot_list);
+		dbg("%s - looking at slot %s",
+		    __FUNCTION__, slot->hotplug_slot->name);
+		if(cpci_check_and_clear_ins(slot)) {
+			dbg("%s - cleared INS for slot %s",
+			    __FUNCTION__, slot->hotplug_slot->name);
+			dev = pci_find_slot(slot->bus->number, PCI_DEVFN(slot->number, 0));
+			if(dev) {
+				if(update_adapter_status(slot->hotplug_slot, 1)) {
+					warn("failure to update adapter file");
+				}
+				if(update_latch_status(slot->hotplug_slot, 1)) {
+					warn("failure to update latch file");
+				}
+				slot->dev = dev;
+			} else {
+				err("%s - no driver attached to device in slot %s",
+				    __FUNCTION__, slot->hotplug_slot->name);
+			}
+		}
+	}
+	spin_unlock(&list_lock);
+	dbg("%s - exit", __FUNCTION__);
+	return 0;
+}
+
+static int
+check_slots(void)
+{
+	struct slot *slot;
+	struct list_head *tmp;
+	int extracted;
+	int inserted;
+
+	spin_lock(&list_lock);
+	if(!slots) {
+		spin_unlock(&list_lock);
+		err("no slots registered, shutting down");
+		return -1;
+	}
+	extracted = inserted = 0;
+	list_for_each(tmp, &slot_list) {
+		slot = list_entry(tmp, struct slot, slot_list);
+		dbg("%s - looking at slot %s",
+		    __FUNCTION__, slot->hotplug_slot->name);
+		if(cpci_check_and_clear_ins(slot)) {
+			u16 hs_csr;
+
+			/* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# twice... */
+			if(slot->dev) {
+				warn("slot %s already inserted", slot->hotplug_slot->name);
+				inserted++;
+				continue;
+			}
+
+			/* Process insertion */
+			dbg("%s - slot %s inserted",
+			    __FUNCTION__, slot->hotplug_slot->name);
+
+			/* GSM, debug */
+			hs_csr = cpci_get_hs_csr(slot);
+			dbg("%s - slot %s HS_CSR (1) = %04x",
+			    __FUNCTION__, slot->hotplug_slot->name, hs_csr);
+
+			/* Configure device */
+			dbg("%s - configuring slot %s",
+			    __FUNCTION__, slot->hotplug_slot->name);
+			if(cpci_configure_slot(slot)) {
+				err("%s - could not configure slot %s",
+				    __FUNCTION__, slot->hotplug_slot->name);
+				continue;
+			}
+			dbg("%s - finished configuring slot %s",
+			    __FUNCTION__, slot->hotplug_slot->name);
+
+			/* GSM, debug */
+			hs_csr = cpci_get_hs_csr(slot);
+			dbg("%s - slot %s HS_CSR (2) = %04x",
+			    __FUNCTION__, slot->hotplug_slot->name, hs_csr);
+
+			if(update_latch_status(slot->hotplug_slot, 1)) {
+				warn("failure to update latch file");
+			}
+
+			if(update_adapter_status(slot->hotplug_slot, 1)) {
+				warn("failure to update adapter file");
+			}
+
+			cpci_led_off(slot);
+
+			/* GSM, debug */
+			hs_csr = cpci_get_hs_csr(slot);
+			dbg("%s - slot %s HS_CSR (3) = %04x",
+			    __FUNCTION__, slot->hotplug_slot->name, hs_csr);
+
+			inserted++;
+		} else if(cpci_check_ext(slot)) {
+			u16 hs_csr;
+
+			/* Process extraction request */
+			dbg("%s - slot %s extracted",
+			    __FUNCTION__, slot->hotplug_slot->name);
+
+			/* GSM, debug */
+			hs_csr = cpci_get_hs_csr(slot);
+			dbg("%s - slot %s HS_CSR = %04x",
+			    __FUNCTION__, slot->hotplug_slot->name, hs_csr);
+
+			if(!slot->extracting) {
+				if(update_latch_status(slot->hotplug_slot, 0)) {
+					warn("failure to update latch file");
+				}
+				slot->extracting = 1;
+			}
+			extracted++;
+		}
+	}
+	spin_unlock(&list_lock);
+	if(inserted || extracted) {
+		return extracted;
+	}
+	else {
+		err("cannot find ENUM# source, shutting down");
+		return -1;
+	}
+}
+
+/* This is the interrupt mode worker thread body */
+static int
+event_thread(void *data)
+{
+	int rc;
+	struct slot *slot;
+	struct list_head *tmp;
+
+	lock_kernel();
+	daemonize("cpci_hp_eventd");
+	unlock_kernel();
+
+	dbg("%s - event thread started", __FUNCTION__);
+	while(1) {
+		dbg("event thread sleeping");
+		down_interruptible(&event_semaphore);
+		dbg("event thread woken, thread_finished = %d",
+		    thread_finished);
+		if(thread_finished || signal_pending(current))
+			break;
+		while(controller->ops->query_enum()) {
+			rc = check_slots();
+			if(rc > 0) {
+				/* Give userspace a chance to handle extraction */
+				set_current_state(TASK_INTERRUPTIBLE);
+				schedule_timeout(HZ / 2);
+			} else if(rc < 0) {
+				dbg("%s - error checking slots", __FUNCTION__);
+				thread_finished = 1;
+				break;
+			}
+		}
+		/* Check for someone yanking out a board */
+		list_for_each(tmp, &slot_list) {
+			slot = list_entry(tmp, struct slot, slot_list);
+			if(slot->extracting) {
+				/*
+				 * Hmmm, we're likely hosed at this point, should we
+				 * bother trying to tell the driver or not?
+				 */
+				err("card in slot %s was improperly removed",
+				    slot->hotplug_slot->name);
+				if(update_adapter_status(slot->hotplug_slot, 0)) {
+					warn("failure to update adapter file");
+				}
+				slot->extracting = 0;
+			}
+		}
+
+		/* Re-enable ENUM# interrupt */
+		dbg("%s - re-enabling irq", __FUNCTION__);
+		controller->ops->enable_irq();
+	}
+
+	dbg("%s - event thread signals exit", __FUNCTION__);
+	up(&thread_exit);
+	return 0;
+}
+
+/* This is the polling mode worker thread body */
+static int
+poll_thread(void *data)
+{
+	int rc;
+	struct slot *slot;
+	struct list_head *tmp;
+
+	lock_kernel();
+	daemonize("cpci_hp_polld");
+	unlock_kernel();
+
+	while(1) {
+		if(thread_finished || signal_pending(current))
+			break;
+
+		while(controller->ops->query_enum()) {
+			rc = check_slots();
+			if(rc > 0) {
+				/* Give userspace a chance to handle extraction */
+				set_current_state(TASK_INTERRUPTIBLE);
+				schedule_timeout(HZ / 2);
+			} else if(rc < 0) {
+				dbg("%s - error checking slots", __FUNCTION__);
+				thread_finished = 1;
+				break;
+			}
+		}
+		/* Check for someone yanking out a board */
+		list_for_each(tmp, &slot_list) {
+			slot = list_entry(tmp, struct slot, slot_list);
+			if(slot->extracting) {
+				/*
+				 * Hmmm, we're likely hosed at this point, should we
+				 * bother trying to tell the driver or not?
+				 */
+				err("card in slot %s was improperly removed",
+				    slot->hotplug_slot->name);
+				if(update_adapter_status(slot->hotplug_slot, 0)) {
+					warn("failure to update adapter file");
+				}
+				slot->extracting = 0;
+			}
+		}
+
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ / 10);
+	}
+	dbg("poll thread signals exit");
+	up(&thread_exit);
+	return 0;
+}
+
+static int
+cpci_start_thread(void)
+{
+	int pid;
+
+	/* initialize our semaphores */
+	init_MUTEX_LOCKED(&event_semaphore);
+	init_MUTEX_LOCKED(&thread_exit);
+	thread_finished = 0;
+
+	if(controller->irq) {
+		pid = kernel_thread(event_thread, 0, 0);
+	} else {
+		pid = kernel_thread(poll_thread, 0, 0);
+	}
+	if(pid < 0) {
+		err("Can't start up our thread");
+		return -1;
+	}
+	dbg("Our thread pid = %d", pid);
+	return 0;
+}
+
+static void
+cpci_stop_thread(void)
+{
+	thread_finished = 1;
+	dbg("thread finish command given");
+	if(controller->irq) {
+		up(&event_semaphore);
+	}
+	dbg("wait for thread to exit");
+	down(&thread_exit);
+}
+
+int
+cpci_hp_register_controller(struct cpci_hp_controller *new_controller)
+{
+	int status = 0;
+
+	if(!controller) {
+		controller = new_controller;
+		if(controller->irq) {
+			if(request_irq(controller->irq,
+					cpci_hp_intr,
+					controller->irq_flags,
+					MY_NAME, controller->dev_id)) {
+				err("Can't get irq %d for the hotplug cPCI controller", controller->irq);
+				status = -ENODEV;
+			}
+			dbg("%s - acquired controller irq %d", __FUNCTION__,
+			    controller->irq);
+		}
+	} else {
+		err("cPCI hotplug controller already registered");
+		status = -1;
+	}
+	return status;
+}
+
+int
+cpci_hp_unregister_controller(struct cpci_hp_controller *old_controller)
+{
+	int status = 0;
+
+	if(controller) {
+		if(!thread_finished) {
+			cpci_stop_thread();
+		}
+		if(controller->irq) {
+			free_irq(controller->irq, controller->dev_id);
+		}
+		controller = NULL;
+	} else {
+		status = -ENODEV;
+	}
+	return status;
+}
+
+int
+cpci_hp_start(void)
+{
+	static int first = 1;
+	int status;
+
+	dbg("%s - enter", __FUNCTION__);
+	if(!controller) {
+		return -ENODEV;
+	}
+
+	spin_lock(&list_lock);
+	if(!slots) {
+		spin_unlock(&list_lock);
+		return -ENODEV;
+	}
+	spin_unlock(&list_lock);
+
+	if(first) {
+		status = init_slots();
+		if(status) {
+			return status;
+		}
+		first = 0;
+	}
+
+	status = cpci_start_thread();
+	if(status) {
+		return status;
+	}
+	dbg("%s - thread started", __FUNCTION__);
+
+	if(controller->irq) {
+		/* Start enum interrupt processing */
+		dbg("%s - enabling irq", __FUNCTION__);
+		controller->ops->enable_irq();
+	}
+	dbg("%s - exit", __FUNCTION__);
+	return 0;
+}
+
+int
+cpci_hp_stop(void)
+{
+	if(!controller) {
+		return -ENODEV;
+	}
+
+	if(controller->irq) {
+		/* Stop enum interrupt processing */
+		dbg("%s - disabling irq", __FUNCTION__);
+		controller->ops->disable_irq();
+	}
+	cpci_stop_thread();
+	return 0;
+}
+
+static void __exit
+cleanup_slots(void)
+{
+	struct list_head *tmp;
+	struct slot *slot;
+
+	/*
+	 * Unregister all of our slots with the pci_hotplug subsystem,
+	 * and free up all memory that we had allocated.
+	 */
+	spin_lock(&list_lock);
+	if(!slots) {
+		goto null_cleanup;
+	}
+	list_for_each(tmp, &slot_list) {
+		slot = list_entry(tmp, struct slot, slot_list);
+		list_del(&slot->slot_list);
+		pci_hp_deregister(slot->hotplug_slot);
+		kfree(slot->hotplug_slot->info);
+		kfree(slot->hotplug_slot->name);
+		kfree(slot->hotplug_slot);
+		kfree(slot);
+	}
+      null_cleanup:
+	spin_unlock(&list_lock);
+	return;
+}
+
+int __init
+cpci_hotplug_init(int debug)
+{
+	spin_lock_init(&list_lock);
+	cpci_debug = debug;
+
+	info(DRIVER_DESC " version: " DRIVER_VERSION);
+	return 0;
+}
+
+void __exit
+cpci_hotplug_exit(void)
+{
+	/*
+	 * Clean everything up.
+	 */
+	cleanup_slots();
+}
+
+
+EXPORT_SYMBOL_GPL(cpci_hp_register_controller);
+EXPORT_SYMBOL_GPL(cpci_hp_unregister_controller);
+EXPORT_SYMBOL_GPL(cpci_hp_register_bus);
+EXPORT_SYMBOL_GPL(cpci_hp_unregister_bus);
+EXPORT_SYMBOL_GPL(cpci_find_slot);
+EXPORT_SYMBOL_GPL(cpci_hp_start);
+EXPORT_SYMBOL_GPL(cpci_hp_stop);
diff -Nru a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,647 @@
+/*
+ * CompactPCI Hot Plug Driver PCI functions
+ *
+ * Copyright (c) 2002 by SOMA Networks, Inc.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <scottm@somanetworks.com>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include "pci_hotplug.h"
+#include "cpci_hotplug.h"
+
+#if !defined(CONFIG_HOTPLUG_CPCI_MODULE)
+#define MY_NAME	"cpci_hotplug"
+#else
+#define MY_NAME	THIS_MODULE->name
+#endif
+
+extern int cpci_debug;
+
+#define dbg(format, arg...)					\
+	do {							\
+		if(cpci_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 ROUND_UP(x, a)		(((x) + (a) - 1) & ~((a) - 1))
+
+
+u8 cpci_get_attention_status(struct slot* slot)
+{
+	int hs_cap;
+	u16 hs_csr;
+
+	hs_cap = pci_bus_find_capability(slot->bus,
+					 slot->devfn,
+					 PCI_CAP_ID_CHSWP);
+	if(!hs_cap) {
+		return 0;
+	}
+
+	if(pci_bus_read_config_word(slot->bus,
+				     slot->devfn,
+				     hs_cap + 2,
+				     &hs_csr)) {
+		return 0;
+	}
+	return hs_csr & 0x0008 ? 1 : 0;
+}
+
+int cpci_set_attention_status(struct slot* slot, int status)
+{
+	int hs_cap;
+	u16 hs_csr;
+
+	hs_cap = pci_bus_find_capability(slot->bus,
+					 slot->devfn,
+					 PCI_CAP_ID_CHSWP);
+	if(!hs_cap) {
+		return 0;
+	}
+
+	if(pci_bus_read_config_word(slot->bus,
+				     slot->devfn,
+				     hs_cap + 2,
+				     &hs_csr)) {
+		return 0;
+	}
+	if(status) {
+		hs_csr |= HS_CSR_LOO;
+	} else {
+		hs_csr &= ~HS_CSR_LOO;
+	}
+	if(pci_bus_write_config_word(slot->bus,
+				      slot->devfn,
+				      hs_cap + 2,
+				      hs_csr)) {
+		return 0;
+	}
+	return 1;
+}
+
+u16 cpci_get_hs_csr(struct slot* slot)
+{
+	int hs_cap;
+	u16 hs_csr;
+
+	hs_cap = pci_bus_find_capability(slot->bus,
+					 slot->devfn,
+					 PCI_CAP_ID_CHSWP);
+	if(!hs_cap) {
+		return 0xFFFF;
+	}
+
+	if(pci_bus_read_config_word(slot->bus,
+				     slot->devfn,
+				     hs_cap + 2,
+				     &hs_csr)) {
+		return 0xFFFF;
+	}
+	return hs_csr;
+}
+
+u16 cpci_set_hs_csr(struct slot* slot, u16 hs_csr)
+{
+	int hs_cap;
+	u16 new_hs_csr;
+
+	hs_cap = pci_bus_find_capability(slot->bus,
+					 slot->devfn,
+					 PCI_CAP_ID_CHSWP);
+	if(!hs_cap) {
+		return 0xFFFF;
+	}
+
+	/* Write out the new value */
+	if(pci_bus_write_config_word(slot->bus,
+				      slot->devfn,
+				      hs_cap + 2,
+				      hs_csr)) {
+		return 0xFFFF;
+	}
+
+	/* Read back what we just wrote out */
+	if(pci_bus_read_config_word(slot->bus,
+				     slot->devfn,
+				     hs_cap + 2,
+				     &new_hs_csr)) {
+		return 0xFFFF;
+	}
+	return new_hs_csr;
+}
+
+int cpci_check_and_clear_ins(struct slot* slot)
+{
+	int hs_cap;
+	u16 hs_csr;
+	int ins = 0;
+
+	hs_cap = pci_bus_find_capability(slot->bus,
+					 slot->devfn,
+					 PCI_CAP_ID_CHSWP);
+	if(!hs_cap) {
+		return 0;
+	}
+	if(pci_bus_read_config_word(slot->bus,
+				     slot->devfn,
+				     hs_cap + 2,
+				     &hs_csr)) {
+		return 0;
+	}
+	if(hs_csr & HS_CSR_INS) {
+		/* Clear INS (by setting it) */
+		if(pci_bus_write_config_word(slot->bus,
+					      slot->devfn,
+					      hs_cap + 2,
+					      hs_csr)) {
+			ins = 0;
+		}
+		ins = 1;
+	}
+	return ins;
+}
+
+int cpci_check_ext(struct slot* slot)
+{
+	int hs_cap;
+	u16 hs_csr;
+	int ext = 0;
+
+	hs_cap = pci_bus_find_capability(slot->bus,
+					 slot->devfn,
+					 PCI_CAP_ID_CHSWP);
+	if(!hs_cap) {
+		return 0;
+	}
+	if(pci_bus_read_config_word(slot->bus,
+				     slot->devfn,
+				     hs_cap + 2,
+				     &hs_csr)) {
+		return 0;
+	}
+	if(hs_csr & HS_CSR_EXT) {
+		ext = 1;
+	}
+	return ext;
+}
+
+int cpci_clear_ext(struct slot* slot)
+{
+	int hs_cap;
+	u16 hs_csr;
+
+	hs_cap = pci_bus_find_capability(slot->bus,
+					 slot->devfn,
+					 PCI_CAP_ID_CHSWP);
+	if(!hs_cap) {
+		return -ENODEV;
+	}
+	if(pci_bus_read_config_word(slot->bus,
+				     slot->devfn,
+				     hs_cap + 2,
+				     &hs_csr)) {
+		return -ENODEV;
+	}
+	if(hs_csr & HS_CSR_EXT) {
+		/* Clear EXT (by setting it) */
+		if(pci_bus_write_config_word(slot->bus,
+					      slot->devfn,
+					      hs_cap + 2,
+					      hs_csr)) {
+			return -ENODEV;
+		}
+	}
+	return 0;
+}
+
+int cpci_led_on(struct slot* slot)
+{
+	int hs_cap;
+	u16 hs_csr;
+
+	hs_cap = pci_bus_find_capability(slot->bus,
+					 slot->devfn,
+					 PCI_CAP_ID_CHSWP);
+	if(!hs_cap) {
+		return -ENODEV;
+	}
+	if(pci_bus_read_config_word(slot->bus,
+				     slot->devfn,
+				     hs_cap + 2,
+				     &hs_csr)) {
+		return -ENODEV;
+	}
+	if((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) {
+		/* Set LOO */
+		hs_csr |= HS_CSR_LOO;
+		if(pci_bus_write_config_word(slot->bus,
+					      slot->devfn,
+					      hs_cap + 2,
+					      hs_csr)) {
+			err("Could not set LOO for slot %s",
+			    slot->hotplug_slot->name);
+			return -ENODEV;
+		}
+	}
+	return 0;
+}
+
+int cpci_led_off(struct slot* slot)
+{
+	int hs_cap;
+	u16 hs_csr;
+
+	hs_cap = pci_bus_find_capability(slot->bus,
+					 slot->devfn,
+					 PCI_CAP_ID_CHSWP);
+	if(!hs_cap) {
+		return -ENODEV;
+	}
+	if(pci_bus_read_config_word(slot->bus,
+				     slot->devfn,
+				     hs_cap + 2,
+				     &hs_csr)) {
+		return -ENODEV;
+	}
+	if(hs_csr & HS_CSR_LOO) {
+		/* Clear LOO */
+		hs_csr &= ~HS_CSR_LOO;
+		if(pci_bus_write_config_word(slot->bus,
+					      slot->devfn,
+					      hs_cap + 2,
+					      hs_csr)) {
+			err("Could not clear LOO for slot %s",
+			    slot->hotplug_slot->name);
+			return -ENODEV;
+		}
+	}
+	return 0;
+}
+
+
+/*
+ * Device configuration functions
+ */
+
+static int cpci_configure_dev(struct pci_bus *bus, struct pci_dev *dev)
+{
+	u8 irq_pin;
+	int r;
+
+	dbg("%s - enter", __FUNCTION__);
+
+	/* NOTE: device already setup from prior scan */
+
+	/* FIXME: How would we know if we need to enable the expansion ROM? */
+	pci_write_config_word(dev, PCI_ROM_ADDRESS, 0x00L);
+
+	/* Assign resources */
+	dbg("assigning resources for %02x:%02x.%x",
+	    dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+	for (r = 0; r < 6; r++) {
+		struct resource *res = dev->resource + r;
+		if(res->flags)
+			pci_assign_resource(dev, r);
+	}
+	dbg("finished assigning resources for %02x:%02x.%x",
+	    dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+
+	/* Does this function have an interrupt at all? */
+	dbg("checking for function interrupt");
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
+	if(irq_pin) {
+		dbg("function uses interrupt pin %d", irq_pin);
+	}
+
+	/*
+	 * Need to explicitly set irq field to 0 so that it'll get assigned
+	 * by the pcibios platform dependent code called by pci_enable_device.
+	 */
+	dev->irq = 0;
+
+	dbg("enabling device");
+	pci_enable_device(dev);	/* XXX check return */
+	dbg("now dev->irq = %d", dev->irq);
+	if(irq_pin && dev->irq) {
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+	}
+
+	/* Can't use pci_insert_device at the moment, do it manually for now */
+	pci_proc_attach_device(dev);
+	dbg("notifying drivers");
+	//pci_announce_device_to_drivers(dev);
+	dbg("%s - exit", __FUNCTION__);
+	return 0;
+}
+
+static int cpci_configure_bridge(struct pci_bus* bus, struct pci_dev* dev)
+{
+	int rc;
+	struct pci_bus* child;
+	struct resource* r;
+	u8 max, n;
+	u16 command;
+
+	dbg("%s - enter", __FUNCTION__);
+
+	/* Do basic bridge initialization */
+	rc = pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
+	if(rc) {
+		printk(KERN_ERR "%s - write of PCI_LATENCY_TIMER failed\n", __FUNCTION__);
+	}
+	rc = pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 0x40);
+	if(rc) {
+		printk(KERN_ERR "%s - write of PCI_SEC_LATENCY_TIMER failed\n", __FUNCTION__);
+	}
+	rc = pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4);
+	if(rc) {
+		printk(KERN_ERR "%s - write of PCI_CACHE_LINE_SIZE failed\n", __FUNCTION__);
+	}
+
+	/*
+	 * Set parent bridge's subordinate field so that configuration space
+	 * access will work in pci_scan_bridge and friends.
+	 */
+	max = pci_max_busnr();
+	bus->subordinate = max + 1;
+	pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, max + 1);
+
+	/* Scan behind bridge */
+	n = pci_scan_bridge(bus, dev, max, 2);
+	child = pci_find_bus(max + 1);
+	if (!child)
+		return -ENODEV;
+#ifdef CONFIG_PROC_FS
+	pci_proc_attach_bus(child);
+#endif
+	/*
+	 * Update parent bridge's subordinate field if there were more bridges
+	 * behind the bridge that was scanned.
+	 */
+	if(n > max) {
+		bus->subordinate = n;
+		pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, n);
+	}
+
+	/*
+	 * Update the bridge resources of the bridge to accommodate devices
+	 * behind it.
+	 */
+	pci_bus_size_bridges(child);
+	pci_bus_assign_resources(child);
+
+	/* Enable resource mapping via command register */
+	command = PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+	r = child->resource[0];
+	if(r && r->start) {
+		command |= PCI_COMMAND_IO;
+	}
+	r = child->resource[1];
+	if(r && r->start) {
+		command |= PCI_COMMAND_MEMORY;
+	}
+	r = child->resource[2];
+	if(r && r->start) {
+		command |= PCI_COMMAND_MEMORY;
+	}
+	rc = pci_write_config_word(dev, PCI_COMMAND, command);
+	if(rc) {
+		err("Error setting command register");
+		return rc;
+	}
+
+	/* Set bridge control register */
+	command = PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_NO_ISA;
+	rc = pci_write_config_word(dev, PCI_BRIDGE_CONTROL, command);
+	if(rc) {
+		err("Error setting bridge control register");
+		return rc;
+	}
+	dbg("%s - exit", __FUNCTION__);
+	return 0;
+}
+
+static int configure_visit_pci_dev(struct pci_dev_wrapped *wrapped_dev,
+			struct pci_bus_wrapped *wrapped_bus)
+{
+	int rc;
+	struct pci_dev *dev = wrapped_dev->dev;
+	struct pci_bus *bus = wrapped_bus->bus;
+	struct slot* slot;
+
+	dbg("%s - enter", __FUNCTION__);
+
+	/*
+	 * We need to fix up the hotplug representation with the Linux
+	 * representation.
+	 */
+	slot = cpci_find_slot(dev->bus, dev->devfn);
+	if(slot) {
+		slot->dev = dev;
+	}
+
+	/* If it's a bridge, scan behind it for devices */
+	if(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+		rc = cpci_configure_bridge(bus, dev);
+		if(rc)
+			return rc;
+	}
+
+	/* Actually configure device */
+	if(dev) {
+		rc = cpci_configure_dev(bus, dev);
+		if(rc)
+			return rc;
+	}
+	dbg("%s - exit", __FUNCTION__);
+	return 0;
+}
+
+static int unconfigure_visit_pci_dev_phase2(struct pci_dev_wrapped *wrapped_dev,
+					    struct pci_bus_wrapped *wrapped_bus)
+{
+	struct pci_dev *dev = wrapped_dev->dev;
+	struct slot* slot;
+
+	dbg("%s - enter", __FUNCTION__);
+	if(!dev)
+		return -ENODEV;
+
+	/* Remove the Linux representation */
+	if(pci_remove_device_safe(dev) == 0) {
+		kfree(dev);
+	} else {
+		err("Could not remove device\n");
+		return -1;
+	}
+
+	/*
+	 * Now remove the hotplug representation.
+	 */
+	slot = cpci_find_slot(dev->bus, dev->devfn);
+	if(slot) {
+		slot->dev = NULL;
+	} else {
+		dbg("No hotplug representation for %02x:%02x.%x",
+		    dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+	}
+	dbg("%s - exit", __FUNCTION__);
+	return 0;
+}
+
+static int unconfigure_visit_pci_bus_phase2(struct pci_bus_wrapped *wrapped_bus,
+					    struct pci_dev_wrapped *wrapped_dev)
+{
+	struct pci_bus *bus = wrapped_bus->bus;
+	struct pci_bus *parent = bus->self->bus;
+
+	dbg("%s - enter", __FUNCTION__);
+
+	/* The cleanup code for proc entries regarding buses should be in the kernel... */
+	if(bus->procdir)
+		dbg("detach_pci_bus %s", bus->procdir->name);
+	pci_proc_detach_bus(bus);
+
+	/* The cleanup code should live in the kernel... */
+	bus->self->subordinate = NULL;
+
+	/* unlink from parent bus */
+	list_del(&bus->node);
+
+	/* Now, remove */
+	if(bus)
+		kfree(bus);
+
+	/* Update parent's subordinate field */
+	if(parent) {
+		u8 n = pci_bus_max_busnr(parent);
+		if(n < parent->subordinate) {
+			parent->subordinate = n;
+			pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, n);
+		}
+	}
+	dbg("%s - exit", __FUNCTION__);
+	return 0;
+}
+
+static struct pci_visit configure_functions = {
+	.visit_pci_dev = configure_visit_pci_dev,
+};
+
+static struct pci_visit unconfigure_functions_phase2 = {
+	.post_visit_pci_bus = unconfigure_visit_pci_bus_phase2,
+	.post_visit_pci_dev = unconfigure_visit_pci_dev_phase2
+};
+
+
+int cpci_configure_slot(struct slot* slot)
+{
+	int rc = 0;
+
+	dbg("%s - enter", __FUNCTION__);
+
+	if(slot->dev == NULL) {
+		dbg("pci_dev null, finding %02x:%02x:%x",
+		    slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn));
+		slot->dev = pci_find_slot(slot->bus->number, slot->devfn);
+	}
+
+	/* Still NULL? Well then scan for it! */
+	if(slot->dev == NULL) {
+		dbg("pci_dev still null");
+
+		/*
+		 * This will generate pci_dev structures for all functions, but
+		 * we will only call this case when lookup fails.
+		 */
+		slot->dev = pci_scan_slot(slot->bus, slot->devfn);
+		if(slot->dev == NULL) {
+			err("Could not find PCI device for slot %02x", slot->number);
+			return 0;
+		}
+	}
+	dbg("slot->dev = %p", slot->dev);
+	if(slot->dev) {
+		struct pci_dev *dev;
+		struct pci_dev_wrapped wrapped_dev;
+		struct pci_bus_wrapped wrapped_bus;
+		int i;
+
+		memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped));
+		memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped));
+
+		for (i = 0; i < 8; i++) {
+			dev = pci_find_slot(slot->bus->number,
+					    PCI_DEVFN(PCI_SLOT(slot->dev->devfn), i));
+			if(!dev)
+				continue;
+			wrapped_dev.dev = dev;
+			wrapped_bus.bus = slot->dev->bus;
+			rc = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus);
+		}
+	}
+
+	dbg("%s - exit, rc = %d", __FUNCTION__, rc);
+	return rc;
+}
+
+int cpci_unconfigure_slot(struct slot* slot)
+{
+	int rc = 0;
+	int i;
+	struct pci_dev_wrapped wrapped_dev;
+	struct pci_bus_wrapped wrapped_bus;
+	struct pci_dev *dev;
+
+	dbg("%s - enter", __FUNCTION__);
+
+	if(!slot->dev) {
+		err("No device for slot %02x\n", slot->number);
+		return -ENODEV;
+	}
+
+	memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped));
+	memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped));
+
+	for (i = 0; i < 8; i++) {
+		dev = pci_find_slot(slot->bus->number,
+				    PCI_DEVFN(PCI_SLOT(slot->devfn), i));
+		if(dev) {
+			wrapped_dev.dev = dev;
+			wrapped_bus.bus = dev->bus;
+			dbg("%s - unconfigure phase 2", __FUNCTION__);
+			rc = pci_visit_dev(&unconfigure_functions_phase2,
+					   &wrapped_dev, &wrapped_bus);
+			if(rc)
+				break;
+		}
+	}
+	dbg("%s - exit, rc = %d", __FUNCTION__, rc);
+	return rc;
+}
diff -Nru a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/cpcihp_generic.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,290 @@
+/*
+ * cpcihp_generic.c
+ *
+ * Generic port I/O CompactPCI driver
+ *
+ * Copyright 2002 SOMA Networks, Inc.
+ * Copyright 2001 Intel San Luis Obispo
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * This generic CompactPCI hotplug driver should allow using the PCI hotplug
+ * mechanism on any CompactPCI board that exposes the #ENUM signal as a bit
+ * in a system register that can be read through standard port I/O.
+ *
+ * Send feedback to <scottm@somanetworks.com>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include "cpci_hotplug.h"
+
+#define DRIVER_VERSION	"0.1"
+#define DRIVER_AUTHOR	"Scott Murray <scottm@somanetworks.com>"
+#define DRIVER_DESC	"Generic port I/O CompactPCI Hot Plug Driver"
+
+#if !defined(CONFIG_HOTPLUG_CPCI_GENERIC_MODULE)
+#define MY_NAME	"cpcihp_generic"
+#else
+#define MY_NAME	THIS_MODULE->name
+#endif
+
+#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)
+
+/* local variables */
+static int debug;
+static char* bridge;
+static u8 bridge_busnr;
+static u8 bridge_slot;
+static struct pci_bus *bus;
+static u8 first_slot;
+static u8 last_slot;
+static u16 port;
+static unsigned int enum_bit;
+static u8 enum_mask;
+
+static struct cpci_hp_controller_ops generic_hpc_ops;
+static struct cpci_hp_controller generic_hpc;
+
+/* The following allows configuring the driver when it's compiled into the kernel */
+#ifndef MODULE
+static int __init cpcihp_generic_setup(char* str)
+{
+	char* p;
+	unsigned long tmp;
+
+	if(!str)
+		return -EINVAL;
+	bridge = str;
+
+	p = strchr(str, ',');
+	str = p + 1;
+	if(!(p && *str && *p == ','))
+		goto setup_error;
+	tmp = simple_strtoul(str, &p, 0);
+	if(p == str || tmp > 0xff) {
+		err("hotplug bus first slot number out of range");
+		goto setup_error;
+	}
+	first_slot = (u8) tmp;
+
+	str = p + 1;		
+	if(!(*str && *p == ','))
+		return -EINVAL;
+	tmp = simple_strtoul(str, &p, 0);
+	if(p == str || tmp > 0xff) {
+		err("hotplug bus last slot number out of range");
+		goto setup_error;
+	}
+	last_slot = (u8) tmp;
+
+	str = p + 1;
+	if(!(*str && *p == ','))
+		goto setup_error;
+	tmp = simple_strtoul(str, &p, 0);
+	if(p == str || tmp > 0xffff) {
+		err("port number out of range");
+		goto setup_error;
+	}
+	port = (u16) tmp;
+
+	str = p + 1;
+	if(!(*str && *p == ','))
+		goto setup_error;
+	tmp = simple_strtoul(str, &p, 0);
+	if(p == str) {
+		err("invalid #ENUM bit number");
+		goto setup_error;
+	}
+	enum_bit = (u8) tmp;
+
+	str = p + 1;
+	if(*str && *p == ',') {
+		tmp = simple_strtoul(str, &p, 0);
+		if(p != str)
+			debug = (int) tmp;
+	}
+	return 0;
+setup_error:
+	bridge = NULL;
+	return -EINVAL;
+}
+
+__setup("cpcihp_generic=", cpcihp_generic_setup);
+#endif
+
+static int __init validate_parameters(void)
+{
+	char* str;
+	char* p;
+	unsigned long tmp;
+
+	if(!bridge) {
+		info("not configured, disabling.");
+		return 1;
+	}
+	str = bridge;
+	if(!*str)
+		return -EINVAL;
+
+	tmp = simple_strtoul(str, &p, 16);
+	if(p == str || tmp > 0xff) {
+		err("Invalid hotplug bus bridge device bus number");
+		return -EINVAL;
+	}
+	bridge_busnr = (u8) tmp;
+	dbg("bridge_busnr = 0x%02x", bridge_busnr);
+	if(*p != ':') {
+		err("Invalid hotplug bus bridge device");
+		return -EINVAL;
+	}
+	str = p + 1;
+	tmp = simple_strtoul(str, &p, 16);
+	if(p == str || tmp > 0x1f) {
+		err("Invalid hotplug bus bridge device slot number");
+		return -EINVAL;
+	}
+	bridge_slot = (u8) tmp;
+	dbg("bridge_slot = 0x%02x", bridge_slot);
+
+	dbg("first_slot = 0x%02x", first_slot);
+	dbg("last_slot = 0x%02x", last_slot);
+	if(!(first_slot && last_slot)) {
+		err("Need to specify first_slot and last_slot");
+		return -EINVAL;
+	}
+	if(last_slot < first_slot) {
+		err("first_slot must be less than last_slot");
+		return -EINVAL;
+	}
+
+	dbg("port = 0x%04x", port);
+	dbg("enum_bit = 0x%02x", enum_bit);
+	if(enum_bit > 7) {
+		err("Invalid #ENUM bit");
+		return -EINVAL;
+	}
+	enum_mask = 1 << enum_bit;
+	return 0;
+}
+
+static int query_enum(void)
+{
+	u8 value;
+
+	value = inb_p(port);
+	return ((value & enum_mask) == enum_mask);
+}
+
+static int __init cpcihp_generic_init(void)
+{
+	int status;
+	struct resource* r;
+	struct pci_dev* dev;
+
+	info(DRIVER_DESC " version: " DRIVER_VERSION);
+	status = validate_parameters();
+	if(status != 0)
+		return status;
+
+	r = request_region(port, 1, "#ENUM hotswap signal register");
+	if(!r)
+		return -EBUSY;
+
+	dev = pci_find_slot(bridge_busnr, PCI_DEVFN(bridge_slot, 0));
+	if(!dev || dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
+		err("Invalid bridge device %s", bridge);
+		return -EINVAL;
+	}
+	bus = dev->subordinate;
+
+	memset(&generic_hpc, 0, sizeof (struct cpci_hp_controller));
+	generic_hpc_ops.query_enum = query_enum;
+	generic_hpc.ops = &generic_hpc_ops;
+
+	status = cpci_hp_register_controller(&generic_hpc);
+	if(status != 0) {
+		err("Could not register cPCI hotplug controller");
+		return -ENODEV;
+	}
+	dbg("registered controller");
+
+	status = cpci_hp_register_bus(bus, first_slot, last_slot);
+	if(status != 0) {
+		err("Could not register cPCI hotplug bus");
+		goto init_bus_register_error;
+	}
+	dbg("registered bus");
+
+	status = cpci_hp_start();
+	if(status != 0) {
+		err("Could not started cPCI hotplug system");
+		goto init_start_error;
+	}
+	dbg("started cpci hp system");
+	return 0;
+init_start_error:
+	cpci_hp_unregister_bus(bus);
+init_bus_register_error:
+	cpci_hp_unregister_controller(&generic_hpc);
+	err("status = %d", status);
+	return status;
+
+}
+
+static void __exit cpcihp_generic_exit(void)
+{
+	cpci_hp_stop();
+	cpci_hp_unregister_bus(bus);
+	cpci_hp_unregister_controller(&generic_hpc);
+	release_region(port, 1);
+}
+
+module_init(cpcihp_generic_init);
+module_exit(cpcihp_generic_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
+MODULE_PARM(bridge, "s");
+MODULE_PARM_DESC(bridge, "Hotswap bus bridge device, <bus>:<slot> (bus and slot are in hexadecimal)");
+MODULE_PARM(first_slot, "b");
+MODULE_PARM_DESC(first_slot, "Hotswap bus first slot number");
+MODULE_PARM(last_slot, "b");
+MODULE_PARM_DESC(last_slot, "Hotswap bus last slot number");
+MODULE_PARM(port, "h");
+MODULE_PARM_DESC(port, "#ENUM signal I/O port");
+MODULE_PARM(enum_bit, "i");
+MODULE_PARM_DESC(enum_bit, "#ENUM signal bit (0-7)");
diff -Nru a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/cpcihp_zt5550.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,306 @@
+/*
+ * cpcihp_zt5550.c
+ *
+ * Intel/Ziatech ZT5550 CompactPCI Host Controller driver
+ *
+ * Copyright 2002 SOMA Networks, Inc.
+ * Copyright 2001 Intel San Luis Obispo
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <scottm@somanetworks.com>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include "cpci_hotplug.h"
+#include "cpcihp_zt5550.h"
+
+#define DRIVER_VERSION	"0.2"
+#define DRIVER_AUTHOR	"Scott Murray <scottm@somanetworks.com>"
+#define DRIVER_DESC	"ZT5550 CompactPCI Hot Plug Driver"
+
+#if !defined(CONFIG_HOTPLUG_PCI_CPCI_ZT5550_MODULE)
+#define MY_NAME	"cpcihp_zt5550"
+#else
+#define MY_NAME	THIS_MODULE->name
+#endif
+
+#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)
+
+/* local variables */
+static int debug;
+static int poll;
+static struct cpci_hp_controller_ops zt5550_hpc_ops;
+static struct cpci_hp_controller zt5550_hpc;
+
+/* Primary cPCI bus bridge device */
+static struct pci_dev *bus0_dev;
+static struct pci_bus *bus0;
+
+/* Host controller device */
+static struct pci_dev *hc_dev;
+
+/* Host controller register addresses */
+static void *hc_registers;
+static void *csr_hc_index;
+static void *csr_hc_data;
+static void *csr_int_status;
+static void *csr_int_mask;
+
+
+static int zt5550_hc_config(struct pci_dev *pdev)
+{
+	/* Since we know that no boards exist with two HC chips, treat it as an error */
+	if(hc_dev) {
+		err("too many host controller devices?");
+		return -EBUSY;
+	}
+	hc_dev = pdev;
+	dbg("hc_dev = %p", hc_dev);
+	dbg("pci resource start %lx", pci_resource_start(hc_dev, 1));
+	dbg("pci resource len %lx", pci_resource_len(hc_dev, 1));
+
+	if(!request_mem_region(pci_resource_start(hc_dev, 1),
+				pci_resource_len(hc_dev, 1), MY_NAME)) {
+		err("cannot reserve MMIO region");
+		return -ENOMEM;
+	}
+
+	hc_registers =
+	    ioremap(pci_resource_start(hc_dev, 1), pci_resource_len(hc_dev, 1));
+	if(!hc_registers) {
+		err("cannot remap MMIO region %lx @ %lx",
+		    pci_resource_len(hc_dev, 1), pci_resource_start(hc_dev, 1));
+		release_mem_region(pci_resource_start(hc_dev, 1),
+				   pci_resource_len(hc_dev, 1));
+		return -ENODEV;
+	}
+
+	csr_hc_index = hc_registers + CSR_HCINDEX;
+	csr_hc_data = hc_registers + CSR_HCDATA;
+	csr_int_status = hc_registers + CSR_INTSTAT;
+	csr_int_mask = hc_registers + CSR_INTMASK;
+
+	/*
+	 * Disable host control, fault and serial interrupts
+	 */
+	dbg("disabling host control, fault and serial interrupts");
+	writeb((u8) HC_INT_MASK_REG, csr_hc_index);
+	writeb((u8) ALL_INDEXED_INTS_MASK, csr_hc_data);
+	dbg("disabled host control, fault and serial interrupts");
+
+	/*
+	 * Disable timer0, timer1 and ENUM interrupts
+	 */
+	dbg("disabling timer0, timer1 and ENUM interrupts");
+	writeb((u8) ALL_DIRECT_INTS_MASK, csr_int_mask);
+	dbg("disabled timer0, timer1 and ENUM interrupts");
+	return 0;
+}
+
+static int zt5550_hc_cleanup(void)
+{
+	if(!hc_dev)
+		return -ENODEV;
+	release_mem_region(pci_resource_start(hc_dev, 1),
+			   pci_resource_len(hc_dev, 1));
+	return 0;
+}
+
+static int zt5550_hc_query_enum(void)
+{
+	u8 value;
+
+	value = inb_p(ENUM_PORT);
+	return ((value & ENUM_MASK) == ENUM_MASK);
+}
+
+static int zt5550_hc_check_irq(void *dev_id)
+{
+	int ret;
+	u8 reg;
+
+	ret = 0;
+	if(dev_id == zt5550_hpc.dev_id) {
+		reg = readb(csr_int_status);
+		if(reg)
+			ret = 1;
+	}
+	return ret;
+}
+
+static int zt5550_hc_enable_irq(void)
+{
+	u8 reg;
+
+	if(hc_dev == NULL) {
+		return -ENODEV;
+	}
+	reg = readb(csr_int_mask);
+	reg = reg & ~ENUM_INT_MASK;
+	writeb(reg, csr_int_mask);
+	return 0;
+}
+
+int zt5550_hc_disable_irq(void)
+{
+	u8 reg;
+
+	if(hc_dev == NULL) {
+		return -ENODEV;
+	}
+
+	reg = readb(csr_int_mask);
+	reg = reg | ENUM_INT_MASK;
+	writeb(reg, csr_int_mask);
+	return 0;
+}
+
+static int __devinit zt5550_hc_init_one (struct pci_dev *pdev,
+					 const struct pci_device_id *ent)
+{
+	int status;
+
+	status = zt5550_hc_config(pdev);
+	if(status != 0) {
+		return status;
+	}
+	dbg("returned from zt5550_hc_config");
+
+	memset(&zt5550_hpc, 0, sizeof (struct cpci_hp_controller));
+	zt5550_hpc_ops.query_enum = zt5550_hc_query_enum;
+	zt5550_hpc.ops = &zt5550_hpc_ops;
+	if(!poll) {
+		zt5550_hpc.irq = hc_dev->irq;
+		zt5550_hpc.irq_flags = SA_SHIRQ;
+		zt5550_hpc.dev_id = hc_dev;
+
+		zt5550_hpc_ops.enable_irq = zt5550_hc_enable_irq;
+		zt5550_hpc_ops.disable_irq = zt5550_hc_disable_irq;
+		zt5550_hpc_ops.check_irq = zt5550_hc_check_irq;
+	} else {
+		info("using ENUM# polling mode");
+	}
+
+	status = cpci_hp_register_controller(&zt5550_hpc);
+	if(status != 0) {
+		err("could not register cPCI hotplug controller");
+		goto init_hc_error;
+	}
+	dbg("registered controller");
+
+	/* Look for first device matching cPCI bus's bridge vendor and device IDs */
+	if(!(bus0_dev = pci_find_device(PCI_VENDOR_ID_DEC,
+					 PCI_DEVICE_ID_DEC_21154, NULL))) {
+		status = -ENODEV;
+		goto init_register_error;
+	}
+	bus0 = bus0_dev->subordinate;
+
+	status = cpci_hp_register_bus(bus0, 0x0a, 0x0f);
+	if(status != 0) {
+		err("could not register cPCI hotplug bus");
+		goto init_register_error;
+	}
+	dbg("registered bus");
+
+	status = cpci_hp_start();
+	if(status != 0) {
+		err("could not started cPCI hotplug system");
+		cpci_hp_unregister_bus(bus0);
+		goto init_register_error;
+	}
+	dbg("started cpci hp system");
+
+	return 0;
+init_register_error:
+	cpci_hp_unregister_controller(&zt5550_hpc);
+init_hc_error:
+	err("status = %d", status);
+	zt5550_hc_cleanup();
+	return status;
+
+}
+
+static void __devexit zt5550_hc_remove_one(struct pci_dev *pdev)
+{
+	cpci_hp_stop();
+	cpci_hp_unregister_bus(bus0);
+	cpci_hp_unregister_controller(&zt5550_hpc);
+	zt5550_hc_cleanup();
+}
+
+
+static struct pci_device_id zt5550_hc_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_ZIATECH, PCI_DEVICE_ID_ZIATECH_5550_HC, PCI_ANY_ID, PCI_ANY_ID, },
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, zt5550_hc_pci_tbl);
+	
+static struct pci_driver zt5550_hc_driver = {
+	.name		= "zt5550_hc",
+	.id_table	= zt5550_hc_pci_tbl,
+	.probe		= zt5550_hc_init_one,
+	.remove		= __devexit_p(zt5550_hc_remove_one),
+};
+
+static int __init zt5550_init(void)
+{
+	struct resource* r;
+
+	info(DRIVER_DESC " version: " DRIVER_VERSION);
+	r = request_region(ENUM_PORT, 1, "#ENUM hotswap signal register");
+	if(!r)
+		return -EBUSY;
+
+	return pci_module_init(&zt5550_hc_driver);
+}
+
+static void __exit
+zt5550_exit(void)
+{
+	pci_unregister_driver(&zt5550_hc_driver);
+	release_region(ENUM_PORT, 1);
+}
+
+module_init(zt5550_init);
+module_exit(zt5550_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
+MODULE_PARM(poll, "i");
+MODULE_PARM_DESC(poll, "#ENUM polling mode enabled or not");
diff -Nru a/drivers/pci/hotplug/cpcihp_zt5550.h b/drivers/pci/hotplug/cpcihp_zt5550.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/cpcihp_zt5550.h	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,79 @@
+/*
+ * cpcihp_zt5550.h
+ *
+ * Intel/Ziatech ZT5550 CompactPCI Host Controller driver definitions
+ *
+ * Copyright 2002 SOMA Networks, Inc.
+ * Copyright 2001 Intel San Luis Obispo
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <scottm@somanetworks.com>
+ */
+
+#ifndef _CPCIHP_ZT5550_H
+#define _CPCIHP_ZT5550_H
+
+/* Direct registers */
+#define CSR_HCINDEX		0x00
+#define CSR_HCDATA		0x04
+#define CSR_INTSTAT		0x08
+#define CSR_INTMASK		0x09
+#define CSR_CNT0CMD		0x0C
+#define CSR_CNT1CMD		0x0E
+#define CSR_CNT0		0x10
+#define CSR_CNT1		0x14
+
+/* Masks for interrupt bits in CSR_INTMASK direct register */
+#define CNT0_INT_MASK		0x01
+#define CNT1_INT_MASK		0x02
+#define ENUM_INT_MASK		0x04
+#define ALL_DIRECT_INTS_MASK	0x07
+
+/* Indexed registers (through CSR_INDEX, CSR_DATA) */
+#define HC_INT_MASK_REG		0x04
+#define HC_STATUS_REG		0x08
+#define HC_CMD_REG		0x0C
+#define ARB_CONFIG_GNT_REG	0x10
+#define ARB_CONFIG_CFG_REG	0x12
+#define ARB_CONFIG_REG	 	0x10
+#define ISOL_CONFIG_REG		0x18
+#define FAULT_STATUS_REG	0x20
+#define FAULT_CONFIG_REG	0x24
+#define WD_CONFIG_REG		0x2C
+#define HC_DIAG_REG		0x30
+#define SERIAL_COMM_REG		0x34
+#define SERIAL_OUT_REG		0x38
+#define SERIAL_IN_REG		0x3C
+
+/* Masks for interrupt bits in HC_INT_MASK_REG indexed register */
+#define SERIAL_INT_MASK		0x01
+#define FAULT_INT_MASK		0x02
+#define HCF_INT_MASK		0x04
+#define ALL_INDEXED_INTS_MASK	0x07
+
+/* Digital I/O port storing ENUM# */
+#define ENUM_PORT	0xE1
+/* Mask to get to the ENUM# bit on the bus */
+#define ENUM_MASK	0x40
+
+#endif				/* _CPCIHP_ZT5550_H */
diff -Nru a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/cpqphp.h	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,912 @@
+/*
+ * Compaq Hot Plug Controller Driver
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001 IBM
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>
+ *
+ */
+#ifndef _CPQPHP_H
+#define _CPQPHP_H
+
+#include "pci_hotplug.h"
+#include <linux/interrupt.h>
+#include <asm/io.h>		/* for read? and write? functions */
+#include <linux/delay.h>	/* for delays */
+
+#if !defined(CONFIG_HOTPLUG_PCI_COMPAQ_MODULE)
+	#define MY_NAME	"cpqphp.o"
+#else
+	#define MY_NAME	THIS_MODULE->name
+#endif
+
+#define dbg(fmt, arg...) do { if (cpqhp_debug) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
+
+
+
+struct smbios_system_slot {
+	u8 type;
+	u8 length;
+	u16 handle;
+	u8 name_string_num;
+	u8 slot_type;
+	u8 slot_width;
+	u8 slot_current_usage;
+	u8 slot_length;
+	u16 slot_number;
+	u8 properties1;
+	u8 properties2;
+} __attribute__ ((packed));
+
+/* offsets to the smbios generic type based on the above structure layout */
+enum smbios_system_slot_offsets {
+	SMBIOS_SLOT_GENERIC_TYPE =	offsetof(struct smbios_system_slot, type),
+	SMBIOS_SLOT_GENERIC_LENGTH =	offsetof(struct smbios_system_slot, length),
+	SMBIOS_SLOT_GENERIC_HANDLE =	offsetof(struct smbios_system_slot, handle),
+	SMBIOS_SLOT_NAME_STRING_NUM =	offsetof(struct smbios_system_slot, name_string_num),
+	SMBIOS_SLOT_TYPE =		offsetof(struct smbios_system_slot, slot_type),
+	SMBIOS_SLOT_WIDTH =		offsetof(struct smbios_system_slot, slot_width),
+	SMBIOS_SLOT_CURRENT_USAGE =	offsetof(struct smbios_system_slot, slot_current_usage),
+	SMBIOS_SLOT_LENGTH =		offsetof(struct smbios_system_slot, slot_length),
+	SMBIOS_SLOT_NUMBER =		offsetof(struct smbios_system_slot, slot_number),
+	SMBIOS_SLOT_PROPERTIES1 =	offsetof(struct smbios_system_slot, properties1),
+	SMBIOS_SLOT_PROPERTIES2 =	offsetof(struct smbios_system_slot, properties2),
+};
+
+struct smbios_generic {
+	u8 type;
+	u8 length;
+	u16 handle;
+} __attribute__ ((packed));
+
+/* offsets to the smbios generic type based on the above structure layout */
+enum smbios_generic_offsets {
+	SMBIOS_GENERIC_TYPE =	offsetof(struct smbios_generic, type),
+	SMBIOS_GENERIC_LENGTH =	offsetof(struct smbios_generic, length),
+	SMBIOS_GENERIC_HANDLE =	offsetof(struct smbios_generic, handle),
+};
+
+struct smbios_entry_point {
+	char anchor[4];
+	u8 ep_checksum;
+	u8 ep_length;
+	u8 major_version;
+	u8 minor_version;
+	u16 max_size_entry;
+	u8 ep_rev;
+	u8 reserved[5];
+	char int_anchor[5];
+	u8 int_checksum;
+	u16 st_length;
+	u32 st_address;
+	u16 number_of_entrys;
+	u8 bcd_rev;
+} __attribute__ ((packed));
+
+/* offsets to the smbios entry point based on the above structure layout */
+enum smbios_entry_point_offsets {
+	ANCHOR =		offsetof(struct smbios_entry_point, anchor[0]),
+	EP_CHECKSUM =		offsetof(struct smbios_entry_point, ep_checksum),
+	EP_LENGTH =		offsetof(struct smbios_entry_point, ep_length),
+	MAJOR_VERSION =		offsetof(struct smbios_entry_point, major_version),
+	MINOR_VERSION =		offsetof(struct smbios_entry_point, minor_version),
+	MAX_SIZE_ENTRY =	offsetof(struct smbios_entry_point, max_size_entry),
+	EP_REV =		offsetof(struct smbios_entry_point, ep_rev),
+	INT_ANCHOR =		offsetof(struct smbios_entry_point, int_anchor[0]),
+	INT_CHECKSUM =		offsetof(struct smbios_entry_point, int_checksum),
+	ST_LENGTH =		offsetof(struct smbios_entry_point, st_length),
+	ST_ADDRESS =		offsetof(struct smbios_entry_point, st_address),
+	NUMBER_OF_ENTRYS =	offsetof(struct smbios_entry_point, number_of_entrys),
+	BCD_REV =		offsetof(struct smbios_entry_point, bcd_rev),
+};
+
+struct ctrl_reg {			/* offset */
+	u8	slot_RST;		/* 0x00 */
+	u8	slot_enable;		/* 0x01 */
+	u16	misc;			/* 0x02 */
+	u32	led_control;		/* 0x04 */
+	u32	int_input_clear;	/* 0x08 */
+	u32	int_mask;		/* 0x0a */
+	u8	reserved0;		/* 0x10 */
+	u8	reserved1;		/* 0x11 */
+	u8	reserved2;		/* 0x12 */
+	u8	gen_output_AB;		/* 0x13 */
+	u32	non_int_input;		/* 0x14 */
+	u32	reserved3;		/* 0x18 */
+	u32	reserved4;		/* 0x1a */
+	u32	reserved5;		/* 0x20 */
+	u8	reserved6;		/* 0x24 */
+	u8	reserved7;		/* 0x25 */
+	u16	reserved8;		/* 0x26 */
+	u8	slot_mask;		/* 0x28 */
+	u8	reserved9;		/* 0x29 */
+	u8	reserved10;		/* 0x2a */
+	u8	reserved11;		/* 0x2b */
+	u8	slot_SERR;		/* 0x2c */
+	u8	slot_power;		/* 0x2d */
+	u8	reserved12;		/* 0x2e */
+	u8	reserved13;		/* 0x2f */
+	u8	next_curr_freq;		/* 0x30 */
+	u8	reset_freq_mode;	/* 0x31 */
+} __attribute__ ((packed));
+
+/* offsets to the controller registers based on the above structure layout */
+enum ctrl_offsets {
+	SLOT_RST = 		offsetof(struct ctrl_reg, slot_RST),
+	SLOT_ENABLE =		offsetof(struct ctrl_reg, slot_enable),
+	MISC =			offsetof(struct ctrl_reg, misc),
+	LED_CONTROL =		offsetof(struct ctrl_reg, led_control),
+	INT_INPUT_CLEAR =	offsetof(struct ctrl_reg, int_input_clear),
+	INT_MASK = 		offsetof(struct ctrl_reg, int_mask),
+	CTRL_RESERVED0 = 	offsetof(struct ctrl_reg, reserved0),
+	CTRL_RESERVED1 =	offsetof(struct ctrl_reg, reserved1),
+	CTRL_RESERVED2 =	offsetof(struct ctrl_reg, reserved1),
+	GEN_OUTPUT_AB = 	offsetof(struct ctrl_reg, gen_output_AB),
+	NON_INT_INPUT = 	offsetof(struct ctrl_reg, non_int_input),
+	CTRL_RESERVED3 =	offsetof(struct ctrl_reg, reserved3),
+	CTRL_RESERVED4 =	offsetof(struct ctrl_reg, reserved4),
+	CTRL_RESERVED5 =	offsetof(struct ctrl_reg, reserved5),
+	CTRL_RESERVED6 =	offsetof(struct ctrl_reg, reserved6),
+	CTRL_RESERVED7 =	offsetof(struct ctrl_reg, reserved7),
+	CTRL_RESERVED8 =	offsetof(struct ctrl_reg, reserved8),
+	SLOT_MASK = 		offsetof(struct ctrl_reg, slot_mask),
+	CTRL_RESERVED9 = 	offsetof(struct ctrl_reg, reserved9),
+	CTRL_RESERVED10 =	offsetof(struct ctrl_reg, reserved10),
+	CTRL_RESERVED11 =	offsetof(struct ctrl_reg, reserved11),
+	SLOT_SERR =		offsetof(struct ctrl_reg, slot_SERR),
+	SLOT_POWER =		offsetof(struct ctrl_reg, slot_power),
+	NEXT_CURR_FREQ =	offsetof(struct ctrl_reg, next_curr_freq),
+	RESET_FREQ_MODE =	offsetof(struct ctrl_reg, reset_freq_mode),
+};
+
+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;
+};
+
+#define SLOT_MAGIC	0x67267321
+struct slot {
+	u32 magic;
+	struct slot *next;
+	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;
+};
+
+struct pci_resource {
+	struct pci_resource * next;
+	u32 base;
+	u32 length;
+};
+
+struct event_info {
+	u32 event_type;
+	u8 hp_slot;
+};
+
+struct controller {
+	struct controller *next;
+	u32 ctrl_int_comp;
+	struct semaphore crit_sect;	/* critical section semaphore */
+	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 event_info event_queue[10];
+	struct slot *slot;
+	u8 next_event;
+	u8 interrupt;
+	u8 cfgspc_irq;
+	u8 bus;				/* bus number for the pci hotplug controller */
+	u8 rev;
+	u8 slot_device_offset;
+	u8 first_slot;
+	u8 add_support;
+	u8 push_flag;
+	enum pci_bus_speed speed;
+	enum pci_bus_speed speed_capability;
+	u8 push_button;			/* 0 = no pushbutton, 1 = pushbutton present */
+	u8 slot_switch_type;		/* 0 = no switch, 1 = switch present */
+	u8 defeature_PHP;		/* 0 = PHP not supported, 1 = PHP supported */
+	u8 alternate_base_address;	/* 0 = not supported, 1 = supported */
+	u8 pci_config_space;		/* Index/data access to working registers 0 = not supported, 1 = supported */
+	u8 pcix_speed_capability;	/* PCI-X */
+	u8 pcix_support;		/* PCI-X */
+	u16 vendor_id;
+	struct work_struct int_task_event;
+	wait_queue_head_t queue;	/* sleep & wake process */
+};
+
+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 PCI_HPC_ID			0xA0F7
+#define PCI_SUB_HPC_ID			0xA2F7
+#define PCI_SUB_HPC_ID2			0xA2F8
+#define PCI_SUB_HPC_ID3			0xA2F9
+#define PCI_SUB_HPC_ID_INTC		0xA2FA
+#define PCI_SUB_HPC_ID4			0xA2FD
+
+#define INT_BUTTON_IGNORE		0
+#define INT_PRESENCE_ON			1
+#define INT_PRESENCE_OFF		2
+#define INT_SWITCH_CLOSE		3
+#define INT_SWITCH_OPEN			4
+#define INT_POWER_FAULT			5
+#define INT_POWER_FAULT_CLEAR		6
+#define INT_BUTTON_PRESS		7
+#define INT_BUTTON_RELEASE		8
+#define INT_BUTTON_CANCEL		9
+
+#define STATIC_STATE			0
+#define BLINKINGON_STATE		1
+#define BLINKINGOFF_STATE		2
+#define POWERON_STATE			3
+#define POWEROFF_STATE			4
+
+#define PCISLOT_INTERLOCK_CLOSED	0x00000001
+#define PCISLOT_ADAPTER_PRESENT		0x00000002
+#define PCISLOT_POWERED			0x00000004
+#define PCISLOT_66_MHZ_OPERATION	0x00000008
+#define PCISLOT_64_BIT_OPERATION	0x00000010
+#define PCISLOT_REPLACE_SUPPORTED	0x00000020
+#define PCISLOT_ADD_SUPPORTED		0x00000040
+#define PCISLOT_INTERLOCK_SUPPORTED	0x00000080
+#define PCISLOT_66_MHZ_SUPPORTED	0x00000100
+#define PCISLOT_64_BIT_SUPPORTED	0x00000200
+
+
+
+#define PCI_TO_PCI_BRIDGE_CLASS		0x00060400
+
+
+#define INTERLOCK_OPEN			0x00000002
+#define ADD_NOT_SUPPORTED		0x00000003
+#define CARD_FUNCTIONING		0x00000005
+#define ADAPTER_NOT_SAME		0x00000006
+#define NO_ADAPTER_PRESENT		0x00000009
+#define NOT_ENOUGH_RESOURCES		0x0000000B
+#define DEVICE_TYPE_NOT_SUPPORTED	0x0000000C
+#define POWER_FAILURE			0x0000000E
+
+#define REMOVE_NOT_SUPPORTED		0x00000003
+
+
+/*
+ * error Messages
+ */
+#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_compaq_or_intel	"The PCI hot plug controller is not supported by this driver.\n"
+#define msg_HPC_not_supported	"this system is not supported by this version of cpqphpd. Upgrade to a newer version of cpqphpd\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"
+#define msg_button_on		"PCI slot #%d - powering on due to button press.\n"
+#define msg_button_off		"PCI slot #%d - powering off due to button press.\n"
+#define msg_button_cancel	"PCI slot #%d - action canceled due to button press.\n"
+#define msg_button_ignore	"PCI slot #%d - button press ignored.  (action in progress...)\n"
+
+
+/* sysfs functions for the hotplug controller info */
+extern void cpqhp_create_ctrl_files		(struct controller *ctrl);
+
+/* controller functions */
+extern void	cpqhp_pushbutton_thread		(unsigned long event_pointer);
+extern irqreturn_t cpqhp_ctrl_intr		(int IRQ, void *data, struct pt_regs *regs);
+extern int	cpqhp_find_available_resources	(struct controller *ctrl, void *rom_start);
+extern int	cpqhp_event_start_thread	(void);
+extern void	cpqhp_event_stop_thread		(void);
+extern struct pci_func *cpqhp_slot_create	(unsigned char busnumber);
+extern struct pci_func *cpqhp_slot_find		(unsigned char bus, unsigned char device, unsigned char index);
+extern int	cpqhp_process_SI		(struct controller *ctrl, struct pci_func *func);
+extern int	cpqhp_process_SS		(struct controller *ctrl, struct pci_func *func);
+extern int	cpqhp_hardware_test		(struct controller *ctrl, int test_num);
+
+/* resource functions */
+extern int	cpqhp_resource_sort_and_combine	(struct pci_resource **head);
+
+/* pci functions */
+extern int	cpqhp_set_irq			(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
+extern int	cpqhp_get_bus_dev		(struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot);
+extern int	cpqhp_save_config		(struct controller *ctrl, int busnumber, int is_hot_plug);
+extern int	cpqhp_save_base_addr_length	(struct controller *ctrl, struct pci_func * func);
+extern int	cpqhp_save_used_resources	(struct controller *ctrl, struct pci_func * func);
+extern int	cpqhp_configure_board		(struct controller *ctrl, struct pci_func * func);
+extern int	cpqhp_save_slot_config		(struct controller *ctrl, struct pci_func * new_slot);
+extern int	cpqhp_valid_replace		(struct controller *ctrl, struct pci_func * func);
+extern void	cpqhp_destroy_board_resources	(struct pci_func * func);
+extern int	cpqhp_return_board_resources	(struct pci_func * func, struct resource_lists * resources);
+extern void	cpqhp_destroy_resource_list	(struct resource_lists * resources);
+extern int	cpqhp_configure_device		(struct controller* ctrl, struct pci_func* func);
+extern int	cpqhp_unconfigure_device	(struct pci_func* func);
+extern struct slot *cpqhp_find_slot		(struct controller *ctrl, u8 device);
+
+/* Global variables */
+extern int cpqhp_debug;
+extern struct controller *cpqhp_ctrl_list;
+extern struct pci_func *cpqhp_slot_list[256];
+
+/* these can be gotten rid of, but for debugging they are purty */
+extern u8 cpqhp_nic_irq;
+extern u8 cpqhp_disk_irq;
+
+
+
+/* inline functions */
+
+
+/* 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;
+}               
+
+/*
+ * 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)
+{
+	if (!node || !head)
+		return;
+	node->next = *head;
+	*head = node;
+}
+
+static inline void set_SOGO (struct controller *ctrl)
+{
+	u16 misc;
+	
+	misc = readw(ctrl->hpc_reg + MISC);
+	misc = (misc | 0x0001) & 0xFFFB;
+	writew(misc, ctrl->hpc_reg + MISC);
+}
+
+
+static inline void amber_LED_on (struct controller *ctrl, u8 slot)
+{
+	u32 led_control;
+	
+	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
+	led_control |= (0x01010000L << slot);
+	writel(led_control, ctrl->hpc_reg + LED_CONTROL);
+}
+
+
+static inline void amber_LED_off (struct controller *ctrl, u8 slot)
+{
+	u32 led_control;
+	
+	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
+	led_control &= ~(0x01010000L << slot);
+	writel(led_control, ctrl->hpc_reg + LED_CONTROL);
+}
+
+
+static inline int read_amber_LED (struct controller *ctrl, u8 slot)
+{
+	u32 led_control;
+
+	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
+	led_control &= (0x01010000L << slot);
+	
+	return led_control ? 1 : 0;
+}
+
+
+static inline void green_LED_on (struct controller *ctrl, u8 slot)
+{
+	u32 led_control;
+	
+	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
+	led_control |= 0x0101L << slot;
+	writel(led_control, ctrl->hpc_reg + LED_CONTROL);
+}
+
+static inline void green_LED_off (struct controller *ctrl, u8 slot)
+{
+	u32 led_control;
+	
+	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
+	led_control &= ~(0x0101L << slot);
+	writel(led_control, ctrl->hpc_reg + LED_CONTROL);
+}
+
+
+static inline void green_LED_blink (struct controller *ctrl, u8 slot)
+{
+	u32 led_control;
+	
+	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
+	led_control &= ~(0x0101L << slot);
+	led_control |= (0x0001L << slot);
+	writel(led_control, ctrl->hpc_reg + LED_CONTROL);
+}
+
+
+static inline void slot_disable (struct controller *ctrl, u8 slot)
+{
+	u8 slot_enable;
+
+	slot_enable = readb(ctrl->hpc_reg + SLOT_ENABLE);
+	slot_enable &= ~(0x01 << slot);
+	writeb(slot_enable, ctrl->hpc_reg + SLOT_ENABLE);
+}
+
+
+static inline void slot_enable (struct controller *ctrl, u8 slot)
+{
+	u8 slot_enable;
+
+	slot_enable = readb(ctrl->hpc_reg + SLOT_ENABLE);
+	slot_enable |= (0x01 << slot);
+	writeb(slot_enable, ctrl->hpc_reg + SLOT_ENABLE);
+}
+
+
+static inline u8 is_slot_enabled (struct controller *ctrl, u8 slot)
+{
+	u8 slot_enable;
+
+	slot_enable = readb(ctrl->hpc_reg + SLOT_ENABLE);
+	slot_enable &= (0x01 << slot);
+	return slot_enable ? 1 : 0;
+}
+
+
+static inline u8 read_slot_enable (struct controller *ctrl)
+{
+	return readb(ctrl->hpc_reg + SLOT_ENABLE);
+}
+
+
+/*
+ * get_controller_speed - find the current frequency/mode of controller.
+ *
+ * @ctrl: controller to get frequency/mode for.
+ *
+ * Returns controller speed.
+ *
+ */
+static inline u8 get_controller_speed (struct controller *ctrl)
+{
+	u8 curr_freq;
+ 	u16 misc;
+ 	
+	if (ctrl->pcix_support) {
+		curr_freq = readb(ctrl->hpc_reg + NEXT_CURR_FREQ);
+		if ((curr_freq & 0xB0) == 0xB0) 
+			return PCI_SPEED_133MHz_PCIX;
+		if ((curr_freq & 0xA0) == 0xA0)
+			return PCI_SPEED_100MHz_PCIX;
+		if ((curr_freq & 0x90) == 0x90)
+			return PCI_SPEED_66MHz_PCIX;
+		if (curr_freq & 0x10)
+			return PCI_SPEED_66MHz;
+
+		return PCI_SPEED_33MHz;
+	}
+
+ 	misc = readw(ctrl->hpc_reg + MISC);
+ 	return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
+}
+ 
+
+/*
+ * get_adapter_speed - find the max supported frequency/mode of adapter.
+ *
+ * @ctrl: hotplug controller.
+ * @hp_slot: hotplug slot where adapter is installed.
+ *
+ * Returns adapter speed.
+ *
+ */
+static inline u8 get_adapter_speed (struct controller *ctrl, u8 hp_slot)
+{
+	u32 temp_dword = readl(ctrl->hpc_reg + NON_INT_INPUT);
+	dbg("slot: %d, PCIXCAP: %8x\n", hp_slot, temp_dword);
+	if (ctrl->pcix_support) {
+		if (temp_dword & (0x10000 << hp_slot))
+			return PCI_SPEED_133MHz_PCIX;
+		if (temp_dword & (0x100 << hp_slot))
+			return PCI_SPEED_66MHz_PCIX;
+	}
+
+	if (temp_dword & (0x01 << hp_slot))
+		return PCI_SPEED_66MHz;
+
+	return PCI_SPEED_33MHz;
+}
+
+static inline void enable_slot_power (struct controller *ctrl, u8 slot)
+{
+	u8 slot_power;
+
+	slot_power = readb(ctrl->hpc_reg + SLOT_POWER);
+	slot_power |= (0x01 << slot);
+	writeb(slot_power, ctrl->hpc_reg + SLOT_POWER);
+}
+
+static inline void disable_slot_power (struct controller *ctrl, u8 slot)
+{
+	u8 slot_power;
+
+	slot_power = readb(ctrl->hpc_reg + SLOT_POWER);
+	slot_power &= ~(0x01 << slot);
+	writeb(slot_power, ctrl->hpc_reg + SLOT_POWER);
+}
+
+
+static inline int cpq_get_attention_status (struct controller *ctrl, struct slot *slot)
+{
+	u8 hp_slot;
+
+	if (slot == NULL)
+		return 1;
+
+	hp_slot = slot->device - ctrl->slot_device_offset;
+
+	return read_amber_LED (ctrl, hp_slot);
+}
+
+
+static inline int get_slot_enabled (struct controller *ctrl, struct slot *slot)
+{
+	u8 hp_slot;
+
+	if (slot == NULL)
+		return 1;
+
+	hp_slot = slot->device - ctrl->slot_device_offset;
+
+	return is_slot_enabled (ctrl, hp_slot);
+}
+
+
+static inline int cpq_get_latch_status (struct controller *ctrl, struct slot *slot)
+{
+	u32 status;
+	u8 hp_slot;
+
+	if (slot == NULL)
+		return 1;
+
+	hp_slot = slot->device - ctrl->slot_device_offset;
+	dbg("%s: slot->device = %d, ctrl->slot_device_offset = %d \n",
+	    __FUNCTION__, slot->device, ctrl->slot_device_offset);
+
+	status = (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot));
+
+	return(status == 0) ? 1 : 0;
+}
+
+
+static inline int get_presence_status (struct controller *ctrl, struct slot *slot)
+{
+	int presence_save = 0;
+	u8 hp_slot;
+	u32 tempdword;
+
+	if (slot == NULL)
+		return 0;
+
+	hp_slot = slot->device - ctrl->slot_device_offset;
+
+	tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
+	presence_save = (int) ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> hp_slot) & 0x02;
+
+	return presence_save;
+}
+
+#define SLOT_NAME_SIZE 10
+
+static inline void make_slot_name (char *buffer, int buffer_size, struct slot *slot)
+{
+	snprintf (buffer, buffer_size, "%d", slot->number);
+}
+
+
+static inline int wait_for_ctrl_irq (struct controller *ctrl)
+{
+        DECLARE_WAITQUEUE(wait, current);
+	int retval = 0;
+
+	dbg("%s - start\n", __FUNCTION__);
+	add_wait_queue(&ctrl->queue, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	/* Sleep for up to 1 second to wait for the LED to change. */
+	schedule_timeout(1*HZ);
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&ctrl->queue, &wait);
+	if (signal_pending(current))
+		retval =  -EINTR;
+
+	dbg("%s - end\n", __FUNCTION__);
+	return retval;
+}
+
+
+/**
+ * set_controller_speed - set the frequency and/or mode of a specific
+ * controller segment.
+ *
+ * @ctrl: controller to change frequency/mode for.
+ * @adapter_speed: the speed of the adapter we want to match.
+ * @hp_slot: the slot number where the adapter is installed.
+ *
+ * Returns 0 if we successfully change frequency and/or mode to match the
+ * adapter speed.
+ * 
+ */
+static inline u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot)
+{
+	struct slot *slot;
+	u8 reg;
+	u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER);
+	u16 reg16;
+	u32 leds = readl(ctrl->hpc_reg + LED_CONTROL);
+	
+	if (ctrl->speed == adapter_speed)
+		return 0;
+	
+	/* We don't allow freq/mode changes if we find another adapter running
+	 * in another slot on this controller */
+	for(slot = ctrl->slot; slot; slot = slot->next) {
+		if (slot->device == (hp_slot + ctrl->slot_device_offset)) 
+			continue;
+		if (!slot->hotplug_slot && !slot->hotplug_slot->info) 
+			continue;
+		if (slot->hotplug_slot->info->adapter_status == 0) 
+			continue;
+		/* If another adapter is running on the same segment but at a
+		 * lower speed/mode, we allow the new adapter to function at
+		 * this rate if supported */
+		if (ctrl->speed < adapter_speed) 
+			return 0;
+
+		return 1;
+	}
+	
+	/* If the controller doesn't support freq/mode changes and the
+	 * controller is running at a higher mode, we bail */
+	if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability))
+		return 1;
+	
+	/* But we allow the adapter to run at a lower rate if possible */
+	if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability))
+		return 0;
+
+	/* We try to set the max speed supported by both the adapter and
+	 * controller */
+	if (ctrl->speed_capability < adapter_speed) {
+		if (ctrl->speed == ctrl->speed_capability)
+			return 0;
+		adapter_speed = ctrl->speed_capability;
+	}
+
+	writel(0x0L, ctrl->hpc_reg + LED_CONTROL);
+	writeb(0x00, ctrl->hpc_reg + SLOT_ENABLE);
+	
+	set_SOGO(ctrl); 
+	wait_for_ctrl_irq(ctrl);
+	
+	if (adapter_speed != PCI_SPEED_133MHz_PCIX)
+		reg = 0xF5;
+	else
+		reg = 0xF4;	
+	pci_write_config_byte(ctrl->pci_dev, 0x41, reg);
+	
+	reg16 = readw(ctrl->hpc_reg + NEXT_CURR_FREQ);
+	reg16 &= ~0x000F;
+	switch(adapter_speed) {
+		case(PCI_SPEED_133MHz_PCIX): 
+			reg = 0x75;
+			reg16 |= 0xB; 
+			break;
+		case(PCI_SPEED_100MHz_PCIX):
+			reg = 0x74;
+			reg16 |= 0xA;
+			break;
+		case(PCI_SPEED_66MHz_PCIX):
+			reg = 0x73;
+			reg16 |= 0x9;
+			break;
+		case(PCI_SPEED_66MHz):
+			reg = 0x73;
+			reg16 |= 0x1;
+			break;
+		default: /* 33MHz PCI 2.2 */
+			reg = 0x71;
+			break;
+			
+	}
+	reg16 |= 0xB << 12;
+	writew(reg16, ctrl->hpc_reg + NEXT_CURR_FREQ);
+	
+	mdelay(5); 
+	
+	/* Reenable interrupts */
+	writel(0, ctrl->hpc_reg + INT_MASK);
+
+	pci_write_config_byte(ctrl->pci_dev, 0x41, reg); 
+	
+	/* Restart state machine */
+	reg = ~0xF;
+	pci_read_config_byte(ctrl->pci_dev, 0x43, &reg);
+	pci_write_config_byte(ctrl->pci_dev, 0x43, reg);
+	
+	/* Only if mode change...*/
+	if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) ||
+		((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) 
+			set_SOGO(ctrl);
+	
+	wait_for_ctrl_irq(ctrl);
+	mdelay(1100);
+	
+	/* Restore LED/Slot state */
+	writel(leds, ctrl->hpc_reg + LED_CONTROL);
+	writeb(slot_power, ctrl->hpc_reg + SLOT_ENABLE);
+	
+	set_SOGO(ctrl);
+	wait_for_ctrl_irq(ctrl);
+
+	ctrl->speed = adapter_speed;
+	slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+	info("Successfully changed frequency/mode for adapter in slot %d\n", 
+			slot->number);
+	return 0;
+}
+
+#endif
+
diff -Nru a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/cpqphp_core.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,1541 @@
+/*
+ * Compaq Hot Plug Controller Driver
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>
+ *
+ * Jan 12, 2003 -	Added 66/100/133MHz PCI-X support,
+ * 			Torben Mathiasen <torben.mathiasen@hp.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <asm/uaccess.h>
+
+#include "cpqphp.h"
+#include "cpqphp_nvram.h"
+#include "../../../arch/i386/pci/pci.h"	/* horrible hack showing how processor dependent we are... */
+
+
+/* Global variables */
+int cpqhp_debug;
+struct controller *cpqhp_ctrl_list;	/* = NULL */
+struct pci_func *cpqhp_slot_list[256];
+
+/* local variables */
+static void *smbios_table;
+static void *smbios_start;
+static void *cpqhp_rom_start;
+static u8 power_mode;
+static int debug;
+
+#define DRIVER_VERSION	"0.9.7"
+#define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>"
+#define DRIVER_DESC	"Compaq Hot Plug PCI Controller Driver"
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(power_mode, "b");
+MODULE_PARM_DESC(power_mode, "Power mode enabled or not");
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
+
+#define CPQHPC_MODULE_MINOR 208
+
+static int one_time_init (void);
+static int set_attention_status (struct hotplug_slot *slot, u8 value);
+static int process_SI		(struct hotplug_slot *slot);
+static int process_SS		(struct hotplug_slot *slot);
+static int hardware_test	(struct hotplug_slot *slot, u32 value);
+static int get_power_status	(struct hotplug_slot *slot, u8 *value);
+static int get_attention_status	(struct hotplug_slot *slot, u8 *value);
+static int get_latch_status	(struct hotplug_slot *slot, u8 *value);
+static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
+static int get_max_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
+static int get_cur_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
+
+static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = {
+	.owner =		THIS_MODULE,
+	.set_attention_status =	set_attention_status,
+	.enable_slot =		process_SI,
+	.disable_slot =		process_SS,
+	.hardware_test =	hardware_test,
+	.get_power_status =	get_power_status,
+	.get_attention_status =	get_attention_status,
+	.get_latch_status =	get_latch_status,
+	.get_adapter_status =	get_adapter_status,
+  	.get_max_bus_speed =	get_max_bus_speed,
+  	.get_cur_bus_speed =	get_cur_bus_speed,
+};
+
+
+static inline int is_slot64bit (struct slot *slot)
+{
+	if (!slot || !slot->p_sm_slot)
+		return 0;
+
+	if (readb(slot->p_sm_slot + SMBIOS_SLOT_WIDTH) == 0x06)
+		return 1;
+
+	return 0;
+}
+
+static inline int is_slot66mhz (struct slot *slot)
+{
+	if (!slot || !slot->p_sm_slot)
+		return 0;
+
+	if (readb(slot->p_sm_slot + SMBIOS_SLOT_TYPE) == 0x0E)
+		return 1;
+
+	return 0;
+}
+
+/**
+ * detect_SMBIOS_pointer - find the system Management BIOS Table in the specified region of memory.
+ *
+ * @begin: begin pointer for region to be scanned.
+ * @end: end pointer for region to be scanned.
+ *
+ * Returns pointer to the head of the SMBIOS tables (or NULL)
+ *
+ */
+static void * detect_SMBIOS_pointer(void *begin, void *end)
+{
+	void *fp;
+	void *endp;
+	u8 temp1, temp2, temp3, temp4;
+	int status = 0;
+
+	endp = (end - sizeof(u32) + 1);
+
+	for (fp = begin; fp <= endp; fp += 16) {
+		temp1 = readb(fp);
+		temp2 = readb(fp+1);
+		temp3 = readb(fp+2);
+		temp4 = readb(fp+3);
+		if (temp1 == '_' &&
+		    temp2 == 'S' &&
+		    temp3 == 'M' &&
+		    temp4 == '_') {
+			status = 1;
+			break;
+		}
+	}
+	
+	if (!status)
+		fp = NULL;
+
+	dbg("Discovered SMBIOS Entry point at %p\n", fp);
+
+	return fp;
+}
+
+/**
+ * init_SERR - Initializes the per slot SERR generation.
+ *
+ * For unexpected switch opens
+ *
+ */
+static int init_SERR(struct controller * ctrl)
+{
+	u32 tempdword;
+	u32 number_of_slots;
+	u8 physical_slot;
+
+	if (!ctrl)
+		return 1;
+
+	tempdword = ctrl->first_slot;
+
+	number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
+	// Loop through slots
+	while (number_of_slots) {
+		physical_slot = tempdword;
+		writeb(0, ctrl->hpc_reg + SLOT_SERR);
+		tempdword++;
+		number_of_slots--;
+	}
+
+	return 0;
+}
+
+
+/* nice debugging output */
+static int pci_print_IRQ_route (void)
+{
+	struct irq_routing_table *routing_table;
+	int len;
+	int loop;
+
+	u8 tbus, tdevice, tslot;
+
+	routing_table = pcibios_get_irq_routing_table();
+	if (routing_table == NULL) {
+		err("No BIOS Routing Table??? Not good\n");
+		return -ENOMEM;
+	}
+
+	len = (routing_table->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
+	// Make sure I got at least one entry
+	if (len == 0) {
+		kfree(routing_table);
+		return -1;
+	}
+
+	dbg("bus dev func slot\n");
+
+	for (loop = 0; loop < len; ++loop) {
+		tbus = routing_table->slots[loop].bus;
+		tdevice = routing_table->slots[loop].devfn;
+		tslot = routing_table->slots[loop].slot;
+		dbg("%d %d %d %d\n", tbus, tdevice >> 3, tdevice & 0x7, tslot);
+
+	}
+	kfree(routing_table);
+	return 0;
+}
+
+
+/*
+ * get_subsequent_smbios_entry
+ *
+ * Gets the first entry if previous == NULL
+ * Otherwise, returns the next entry
+ * Uses global SMBIOS Table pointer
+ *
+ * @curr: %NULL or pointer to previously returned structure
+ *
+ * returns a pointer to an SMBIOS structure or NULL if none found
+ */
+static void * get_subsequent_smbios_entry(void *smbios_start, void *smbios_table, void *curr)
+{
+	u8 bail = 0;
+	u8 previous_byte = 1;
+	void *p_temp;
+	void *p_max;
+
+	if (!smbios_table || !curr)
+		return(NULL);
+
+	// set p_max to the end of the table
+	p_max = smbios_start + readw(smbios_table + ST_LENGTH);
+
+	p_temp = curr;
+	p_temp += readb(curr + SMBIOS_GENERIC_LENGTH);
+
+	while ((p_temp < p_max) && !bail) {
+		// Look for the double NULL terminator
+		// The first condition is the previous byte and the second is the curr
+		if (!previous_byte && !(readb(p_temp))) {
+			bail = 1;
+		}
+
+		previous_byte = readb(p_temp);
+		p_temp++;
+	}
+
+	if (p_temp < p_max) {
+		return p_temp;
+	} else {
+		return NULL;
+	}
+}
+
+
+/**
+ * get_SMBIOS_entry
+ *
+ * @type:SMBIOS structure type to be returned
+ * @previous: %NULL or pointer to previously returned structure
+ *
+ * Gets the first entry of the specified type if previous == NULL
+ * Otherwise, returns the next entry of the given type.
+ * Uses global SMBIOS Table pointer
+ * Uses get_subsequent_smbios_entry
+ *
+ * returns a pointer to an SMBIOS structure or %NULL if none found
+ */
+static void *get_SMBIOS_entry (void *smbios_start, void *smbios_table, u8 type, void * previous)
+{
+	if (!smbios_table)
+		return NULL;
+
+	if (!previous) {		  
+		previous = smbios_start;
+	} else {
+		previous = get_subsequent_smbios_entry(smbios_start, smbios_table, previous);
+	}
+
+	while (previous) {
+	       	if (readb(previous + SMBIOS_GENERIC_TYPE) != type) {
+			previous = get_subsequent_smbios_entry(smbios_start, smbios_table, previous);
+		} else {
+			break;
+		}
+	}
+
+	return previous;
+}
+
+
+static int ctrl_slot_setup (struct controller * ctrl, void *smbios_start, void *smbios_table)
+{
+	struct slot *new_slot;
+	u8 number_of_slots;
+	u8 slot_device;
+	u8 slot_number;
+	u8 ctrl_slot;
+	u32 tempdword;
+	void *slot_entry= NULL;
+	int result;
+
+	dbg("%s\n", __FUNCTION__);
+
+	tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
+
+	number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
+	slot_device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
+	slot_number = ctrl->first_slot;
+
+	while (number_of_slots) {
+		new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL);
+		if (!new_slot)
+			return -ENOMEM;
+
+		memset(new_slot, 0, sizeof(struct slot));
+		new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL);
+		if (!new_slot->hotplug_slot) {
+			kfree (new_slot);
+			return -ENOMEM;
+		}
+		memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot));
+
+		new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
+		if (!new_slot->hotplug_slot->info) {
+			kfree (new_slot->hotplug_slot);
+			kfree (new_slot);
+			return -ENOMEM;
+		}
+		memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info));
+		new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL);
+		if (!new_slot->hotplug_slot->name) {
+			kfree (new_slot->hotplug_slot->info);
+			kfree (new_slot->hotplug_slot);
+			kfree (new_slot);
+			return -ENOMEM;
+		}
+
+		new_slot->magic = SLOT_MAGIC;
+		new_slot->ctrl = ctrl;
+		new_slot->bus = ctrl->bus;
+		new_slot->device = slot_device;
+		new_slot->number = slot_number;
+		dbg("slot->number = %d\n",new_slot->number);
+
+		slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, slot_entry);
+
+		while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) != new_slot->number)) {
+			slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, slot_entry);
+		}
+
+		new_slot->p_sm_slot = slot_entry;
+
+		init_timer(&new_slot->task_event);
+		new_slot->task_event.expires = jiffies + 5 * HZ;
+		new_slot->task_event.function = cpqhp_pushbutton_thread;
+
+		//FIXME: these capabilities aren't used but if they are
+		//       they need to be correctly implemented
+		new_slot->capabilities |= PCISLOT_REPLACE_SUPPORTED;
+		new_slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED;
+
+		if (is_slot64bit(new_slot))
+			new_slot->capabilities |= PCISLOT_64_BIT_SUPPORTED;
+		if (is_slot66mhz(new_slot))
+			new_slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED;
+		if (ctrl->speed == PCI_SPEED_66MHz)
+			new_slot->capabilities |= PCISLOT_66_MHZ_OPERATION;
+
+		ctrl_slot = slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4);
+
+		// Check presence
+		new_slot->capabilities |= ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> ctrl_slot) & 0x02;
+		// Check the switch state
+		new_slot->capabilities |= ((~tempdword & 0xFF) >> ctrl_slot) & 0x01;
+		// Check the slot enable
+		new_slot->capabilities |= ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04;
+
+		/* register this slot with the hotplug pci core */
+		new_slot->hotplug_slot->private = new_slot;
+		make_slot_name (new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot);
+		new_slot->hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
+		
+		new_slot->hotplug_slot->info->power_status = get_slot_enabled(ctrl, new_slot);
+		new_slot->hotplug_slot->info->attention_status = cpq_get_attention_status(ctrl, new_slot);
+		new_slot->hotplug_slot->info->latch_status = cpq_get_latch_status(ctrl, new_slot);
+		new_slot->hotplug_slot->info->adapter_status = get_presence_status(ctrl, new_slot);
+		
+		dbg ("registering bus %d, dev %d, number %d, ctrl->slot_device_offset %d, slot %d\n", 
+		     new_slot->bus, new_slot->device, new_slot->number, ctrl->slot_device_offset, slot_number);
+		result = pci_hp_register (new_slot->hotplug_slot);
+		if (result) {
+			err ("pci_hp_register failed with error %d\n", result);
+			kfree (new_slot->hotplug_slot->info);
+			kfree (new_slot->hotplug_slot->name);
+			kfree (new_slot->hotplug_slot);
+			kfree (new_slot);
+			return result;
+		}
+		
+		new_slot->next = ctrl->slot;
+		ctrl->slot = new_slot;
+
+		number_of_slots--;
+		slot_device++;
+		slot_number++;
+	}
+
+	return(0);
+}
+
+
+static int ctrl_slot_cleanup (struct controller * ctrl)
+{
+	struct slot *old_slot, *next_slot;
+
+	old_slot = ctrl->slot;
+	ctrl->slot = NULL;
+
+	while (old_slot) {
+		next_slot = old_slot->next;
+		pci_hp_deregister (old_slot->hotplug_slot);
+		kfree(old_slot->hotplug_slot->info);
+		kfree(old_slot->hotplug_slot->name);
+		kfree(old_slot->hotplug_slot);
+		kfree(old_slot);
+		old_slot = next_slot;
+	}
+
+	//Free IRQ associated with hot plug device
+	free_irq(ctrl->interrupt, ctrl);
+	//Unmap the memory
+	iounmap(ctrl->hpc_reg);
+	//Finally reclaim PCI mem
+	release_mem_region(pci_resource_start(ctrl->pci_dev, 0),
+			   pci_resource_len(ctrl->pci_dev, 0));
+
+	return(0);
+}
+
+
+//============================================================================
+// function:	get_slot_mapping
+//
+// Description: Attempts to determine a logical slot mapping for a PCI
+//		device.  Won't work for more than one PCI-PCI bridge
+//		in a slot.
+//
+// Input:	u8 bus_num - bus number of PCI device
+//		u8 dev_num - device number of PCI device
+//		u8 *slot - Pointer to u8 where slot number will
+//			be returned
+//
+// Output:	SUCCESS or FAILURE
+//=============================================================================
+static int get_slot_mapping (struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot)
+{
+	struct irq_routing_table *PCIIRQRoutingInfoLength;
+	u32 work;
+	long len;
+	long loop;
+
+	u8 tbus, tdevice, tslot, bridgeSlot;
+
+	dbg("%s: %p, %d, %d, %p\n", __FUNCTION__, bus, bus_num, dev_num, slot);
+
+	bridgeSlot = 0xFF;
+
+	PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table();
+	if (!PCIIRQRoutingInfoLength)
+		return -1;
+
+	len = (PCIIRQRoutingInfoLength->size -
+	       sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
+	// Make sure I got at least one entry
+	if (len == 0) {
+		if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength );
+		return -1;
+	}
+
+	for (loop = 0; loop < len; ++loop) {
+		tbus = PCIIRQRoutingInfoLength->slots[loop].bus;
+		tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn >> 3;
+		tslot = PCIIRQRoutingInfoLength->slots[loop].slot;
+
+		if ((tbus == bus_num) && (tdevice == dev_num)) {
+			*slot = tslot;
+
+			if (PCIIRQRoutingInfoLength != NULL)
+				kfree(PCIIRQRoutingInfoLength);
+			return 0;
+		} else {
+			// Didn't get a match on the target PCI device. Check if the
+			// current IRQ table entry is a PCI-to-PCI bridge device.  If so,
+			// and it's secondary bus matches the bus number for the target 
+			// device, I need to save the bridge's slot number.  If I can't 
+			// find an entry for the target device, I will have to assume it's 
+			// on the other side of the bridge, and assign it the bridge's slot.
+			bus->number = tbus;
+			pci_bus_read_config_dword (bus, PCI_DEVFN(tdevice, 0), PCI_REVISION_ID, &work);
+
+			if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
+				pci_bus_read_config_dword (bus, PCI_DEVFN(tdevice, 0), PCI_PRIMARY_BUS, &work);
+				// See if bridge's secondary bus matches target bus.
+				if (((work >> 8) & 0x000000FF) == (long) bus_num) {
+					bridgeSlot = tslot;
+				}
+			}
+		}
+
+	}
+
+	// If we got here, we didn't find an entry in the IRQ mapping table 
+	// for the target PCI device.  If we did determine that the target 
+	// device is on the other side of a PCI-to-PCI bridge, return the 
+	// slot number for the bridge.
+	if (bridgeSlot != 0xFF) {
+		*slot = bridgeSlot;
+		if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength );
+		return 0;
+	}
+	if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength );
+	// Couldn't find an entry in the routing table for this PCI device
+	return -1;
+}
+
+
+/**
+ * cpqhp_set_attention_status - Turns the Amber LED for a slot on or off
+ *
+ */
+static int cpqhp_set_attention_status (struct controller *ctrl, struct pci_func *func, u32 status)
+{
+	u8 hp_slot;
+
+	hp_slot = func->device - ctrl->slot_device_offset;
+
+	if (func == NULL)
+		return(1);
+
+	// Wait for exclusive access to hardware
+	down(&ctrl->crit_sect);
+
+	if (status == 1) {
+		amber_LED_on (ctrl, hp_slot);
+	} else if (status == 0) {
+		amber_LED_off (ctrl, hp_slot);
+	} else {
+		// Done with exclusive hardware access
+		up(&ctrl->crit_sect);
+		return(1);
+	}
+
+	set_SOGO(ctrl);
+
+	// Wait for SOBS to be unset
+	wait_for_ctrl_irq (ctrl);
+
+	// Done with exclusive hardware access
+	up(&ctrl->crit_sect);
+
+	return(0);
+}
+
+
+/**
+ * set_attention_status - Turns the Amber LED for a slot on or off
+ *
+ */
+static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
+{
+	struct pci_func *slot_func;
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct controller *ctrl;
+	u8 bus;
+	u8 devfn;
+	u8 device;
+	u8 function;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	ctrl = slot->ctrl;
+	if (ctrl == NULL)
+		return -ENODEV;
+	
+	if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
+		return -ENODEV;
+
+	device = devfn >> 3;
+	function = devfn & 0x7;
+	dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function);
+
+	slot_func = cpqhp_slot_find(bus, device, function);
+	if (!slot_func) {
+		return -ENODEV;
+	}
+
+	return cpqhp_set_attention_status(ctrl, slot_func, status);
+}
+
+
+static int process_SI (struct hotplug_slot *hotplug_slot)
+{
+	struct pci_func *slot_func;
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct controller *ctrl;
+	u8 bus;
+	u8 devfn;
+	u8 device;
+	u8 function;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	ctrl = slot->ctrl;
+	if (ctrl == NULL)
+		return -ENODEV;
+	
+	if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
+		return -ENODEV;
+
+	device = devfn >> 3;
+	function = devfn & 0x7;
+	dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function);
+
+	slot_func = cpqhp_slot_find(bus, device, function);
+	if (!slot_func) {
+		return -ENODEV;
+	}
+
+	slot_func->bus = bus;
+	slot_func->device = device;
+	slot_func->function = function;
+	slot_func->configured = 0;
+	dbg("board_added(%p, %p)\n", slot_func, ctrl);
+	return cpqhp_process_SI(ctrl, slot_func);
+}
+
+
+static int process_SS (struct hotplug_slot *hotplug_slot)
+{
+	struct pci_func *slot_func;
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct controller *ctrl;
+	u8 bus;
+	u8 devfn;
+	u8 device;
+	u8 function;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	ctrl = slot->ctrl;
+	if (ctrl == NULL)
+		return -ENODEV;
+	
+	if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
+		return -ENODEV;
+
+	device = devfn >> 3;
+	function = devfn & 0x7;
+	dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function);
+
+	slot_func = cpqhp_slot_find(bus, device, function);
+	if (!slot_func) {
+		return -ENODEV;
+	}
+	
+	dbg("In power_down_board, slot_func = %p, ctrl = %p\n", slot_func, ctrl);
+	return cpqhp_process_SS(ctrl, slot_func);
+}
+
+
+static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct controller *ctrl;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	ctrl = slot->ctrl;
+	if (ctrl == NULL)
+		return -ENODEV;
+
+	return cpqhp_hardware_test (ctrl, value);	
+}
+
+
+static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct controller *ctrl;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	ctrl = slot->ctrl;
+	if (ctrl == NULL)
+		return -ENODEV;
+	
+	*value = get_slot_enabled(ctrl, slot);
+	return 0;
+}
+
+static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct controller *ctrl;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	ctrl = slot->ctrl;
+	if (ctrl == NULL)
+		return -ENODEV;
+	
+	*value = cpq_get_attention_status(ctrl, slot);
+	return 0;
+}
+
+static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct controller *ctrl;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	ctrl = slot->ctrl;
+	if (ctrl == NULL)
+		return -ENODEV;
+	
+	*value = cpq_get_latch_status (ctrl, slot);
+
+	return 0;
+}
+
+static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct controller *ctrl;
+	
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	ctrl = slot->ctrl;
+	if (ctrl == NULL)
+		return -ENODEV;
+	
+	*value = get_presence_status (ctrl, slot);
+
+	return 0;
+}
+
+static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct controller *ctrl;
+	
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	ctrl = slot->ctrl;
+	if (ctrl == NULL)
+		return -ENODEV;
+	
+	*value = ctrl->speed_capability;
+
+	return 0;
+}
+
+static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct controller *ctrl;
+	
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	ctrl = slot->ctrl;
+	if (ctrl == NULL)
+		return -ENODEV;
+	
+	*value = ctrl->speed;
+
+	return 0;
+}
+
+static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	u8 num_of_slots = 0;
+	u8 hp_slot = 0;
+	u8 device;
+	u8 rev;
+	u8 bus_cap;
+	u16 temp_word;
+	u16 vendor_id;
+	u16 subsystem_vid;
+	u16 subsystem_deviceid;
+	u32 rc;
+	struct controller *ctrl;
+	struct pci_func *func;
+
+	// Need to read VID early b/c it's used to differentiate CPQ and INTC discovery
+	rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
+	if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) {
+		err(msg_HPC_non_compaq_or_intel);
+		return -ENODEV;
+	}
+	dbg("Vendor ID: %x\n", vendor_id);
+
+	rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+	dbg("revision: %d\n", rev);
+	if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!rev))) {
+		err(msg_HPC_rev_error);
+		return -ENODEV;
+	}
+
+	/* Check for the proper subsytem ID's
+	 * Intel uses a different SSID programming model than Compaq.  
+	 * For Intel, each SSID bit identifies a PHP capability.
+	 * Also Intel HPC's may have RID=0.
+	 */
+	if ((rev > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) {
+		// TODO: This code can be made to support non-Compaq or Intel subsystem IDs
+		rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
+		if (rc) {
+			err("%s : pci_read_config_word failed\n", __FUNCTION__);
+			return rc;
+		}
+		dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
+		if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
+			err(msg_HPC_non_compaq_or_intel);
+			return -ENODEV;
+		}
+
+		ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
+		if (!ctrl) {
+			err("%s : out of memory\n", __FUNCTION__);
+			return -ENOMEM;
+		}
+		memset(ctrl, 0, sizeof(struct controller));
+
+		rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
+		if (rc) {
+			err("%s : pci_read_config_word failed\n", __FUNCTION__);
+			goto err_free_ctrl;
+		}
+
+		info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid);
+
+		/* Set Vendor ID, so it can be accessed later from other functions */
+		ctrl->vendor_id = vendor_id;
+
+		switch (subsystem_vid) {
+			case PCI_VENDOR_ID_COMPAQ:
+				if (rev >= 0x13) { /* CIOBX */
+					ctrl->push_flag = 1;
+					ctrl->slot_switch_type = 1;		// Switch is present
+					ctrl->push_button = 1;			// Pushbutton is present
+					ctrl->pci_config_space = 1;		// Index/data access to working registers 0 = not supported, 1 = supported
+					ctrl->defeature_PHP = 1;		// PHP is supported
+					ctrl->pcix_support = 1;			// PCI-X supported
+					ctrl->pcix_speed_capability = 1;
+					pci_read_config_byte(pdev, 0x41, &bus_cap);
+					if (bus_cap & 0x80) {
+						dbg("bus max supports 133MHz PCI-X\n");
+						ctrl->speed_capability = PCI_SPEED_133MHz_PCIX;
+						break;
+					}
+					if (bus_cap & 0x40) {
+						dbg("bus max supports 100MHz PCI-X\n");
+						ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
+						break;
+					}
+					if (bus_cap & 20) {
+						dbg("bus max supports 66MHz PCI-X\n");
+						ctrl->speed_capability = PCI_SPEED_66MHz_PCIX;
+						break;
+					}
+					if (bus_cap & 10) {
+						dbg("bus max supports 66MHz PCI\n");
+						ctrl->speed_capability = PCI_SPEED_66MHz;
+						break;
+					}
+
+					break;
+				}
+
+				switch (subsystem_deviceid) {
+					case PCI_SUB_HPC_ID:
+						/* Original 6500/7000 implementation */
+						ctrl->slot_switch_type = 1;		// Switch is present
+						ctrl->speed_capability = PCI_SPEED_33MHz;
+						ctrl->push_button = 0;			// No pushbutton
+						ctrl->pci_config_space = 1;		// Index/data access to working registers 0 = not supported, 1 = supported
+						ctrl->defeature_PHP = 1;		// PHP is supported
+						ctrl->pcix_support = 0;			// PCI-X not supported
+						ctrl->pcix_speed_capability = 0;	// N/A since PCI-X not supported
+						break;
+					case PCI_SUB_HPC_ID2:
+						/* First Pushbutton implementation */
+						ctrl->push_flag = 1;
+						ctrl->slot_switch_type = 1;		// Switch is present
+						ctrl->speed_capability = PCI_SPEED_33MHz;
+						ctrl->push_button = 1;			// Pushbutton is present
+						ctrl->pci_config_space = 1;		// Index/data access to working registers 0 = not supported, 1 = supported
+						ctrl->defeature_PHP = 1;		// PHP is supported
+						ctrl->pcix_support = 0;			// PCI-X not supported
+						ctrl->pcix_speed_capability = 0;	// N/A since PCI-X not supported
+						break;
+					case PCI_SUB_HPC_ID_INTC:
+						/* Third party (6500/7000) */
+						ctrl->slot_switch_type = 1;		// Switch is present
+						ctrl->speed_capability = PCI_SPEED_33MHz;
+						ctrl->push_button = 0;			// No pushbutton
+						ctrl->pci_config_space = 1;		// Index/data access to working registers 0 = not supported, 1 = supported
+						ctrl->defeature_PHP = 1;			// PHP is supported
+						ctrl->pcix_support = 0;			// PCI-X not supported
+						ctrl->pcix_speed_capability = 0;		// N/A since PCI-X not supported
+						break;
+					case PCI_SUB_HPC_ID3:
+						/* First 66 Mhz implementation */
+						ctrl->push_flag = 1;
+						ctrl->slot_switch_type = 1;		// Switch is present
+						ctrl->speed_capability = PCI_SPEED_66MHz;
+						ctrl->push_button = 1;			// Pushbutton is present
+						ctrl->pci_config_space = 1;		// Index/data access to working registers 0 = not supported, 1 = supported
+						ctrl->defeature_PHP = 1;		// PHP is supported
+						ctrl->pcix_support = 0;			// PCI-X not supported
+						ctrl->pcix_speed_capability = 0;	// N/A since PCI-X not supported
+						break;
+					case PCI_SUB_HPC_ID4:
+						/* First PCI-X implementation, 100MHz */
+						ctrl->push_flag = 1;
+						ctrl->slot_switch_type = 1;		// Switch is present
+						ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
+						ctrl->push_button = 1;			// Pushbutton is present
+						ctrl->pci_config_space = 1;		// Index/data access to working registers 0 = not supported, 1 = supported
+						ctrl->defeature_PHP = 1;		// PHP is supported
+						ctrl->pcix_support = 1;			// PCI-X supported
+						ctrl->pcix_speed_capability = 0;	
+						break;
+					default:
+						err(msg_HPC_not_supported);
+						rc = -ENODEV;
+						goto err_free_ctrl;
+				}
+				break;
+
+			case PCI_VENDOR_ID_INTEL:
+				/* Check for speed capability (0=33, 1=66) */
+				if (subsystem_deviceid & 0x0001) {
+					ctrl->speed_capability = PCI_SPEED_66MHz;
+				} else {
+					ctrl->speed_capability = PCI_SPEED_33MHz;
+				}
+
+				/* Check for push button */
+				if (subsystem_deviceid & 0x0002) {
+					/* no push button */
+					ctrl->push_button = 0;
+				} else {
+					/* push button supported */
+					ctrl->push_button = 1;
+				}
+
+				/* Check for slot switch type (0=mechanical, 1=not mechanical) */
+				if (subsystem_deviceid & 0x0004) {
+					/* no switch */
+					ctrl->slot_switch_type = 0;
+				} else {
+					/* switch */
+					ctrl->slot_switch_type = 1;
+				}
+
+				/* PHP Status (0=De-feature PHP, 1=Normal operation) */
+				if (subsystem_deviceid & 0x0008) {
+					ctrl->defeature_PHP = 1;	// PHP supported
+				} else {
+					ctrl->defeature_PHP = 0;	// PHP not supported
+				}
+
+				/* Alternate Base Address Register Interface (0=not supported, 1=supported) */
+				if (subsystem_deviceid & 0x0010) {
+					ctrl->alternate_base_address = 1;	// supported
+				} else {
+					ctrl->alternate_base_address = 0;	// not supported
+				}
+
+				/* PCI Config Space Index (0=not supported, 1=supported) */
+				if (subsystem_deviceid & 0x0020) {
+					ctrl->pci_config_space = 1;		// supported
+				} else {
+					ctrl->pci_config_space = 0;		// not supported
+				}
+
+				/* PCI-X support */
+				if (subsystem_deviceid & 0x0080) {
+					/* PCI-X capable */
+					ctrl->pcix_support = 1;
+					/* Frequency of operation in PCI-X mode */
+					if (subsystem_deviceid & 0x0040) {
+						/* 133MHz PCI-X if bit 7 is 1 */
+						ctrl->pcix_speed_capability = 1;
+					} else {
+						/* 100MHz PCI-X if bit 7 is 1 and bit 0 is 0, */
+						/* 66MHz PCI-X if bit 7 is 1 and bit 0 is 1 */
+						ctrl->pcix_speed_capability = 0;
+					}
+				} else {
+					/* Conventional PCI */
+					ctrl->pcix_support = 0;
+					ctrl->pcix_speed_capability = 0;
+				}
+				break;
+
+			default:
+				err(msg_HPC_not_supported);
+				rc = -ENODEV;
+				goto err_free_ctrl;
+		}
+
+	} else {
+		err(msg_HPC_not_supported);
+		return -ENODEV;
+	}
+
+	// Tell the user that we found one.
+	info("Initializing the PCI hot plug controller residing on PCI bus %d\n", pdev->bus->number);
+
+	dbg ("Hotplug controller capabilities:\n");
+	dbg ("    speed_capability       %d\n", ctrl->speed_capability);
+	dbg ("    slot_switch_type       %s\n", ctrl->slot_switch_type == 0 ? "no switch" : "switch present");
+	dbg ("    defeature_PHP          %s\n", ctrl->defeature_PHP == 0 ? "PHP not supported" : "PHP supported");
+	dbg ("    alternate_base_address %s\n", ctrl->alternate_base_address == 0 ? "not supported" : "supported");
+	dbg ("    pci_config_space       %s\n", ctrl->pci_config_space == 0 ? "not supported" : "supported");
+	dbg ("    pcix_speed_capability  %s\n", ctrl->pcix_speed_capability == 0 ? "not supported" : "supported");
+	dbg ("    pcix_support           %s\n", ctrl->pcix_support == 0 ? "not supported" : "supported");
+
+	ctrl->pci_dev = pdev;
+	pci_set_drvdata(pdev, ctrl);
+
+	/* make our own copy of the pci bus structure, as we like tweaking it a lot */
+	ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL);
+	if (!ctrl->pci_bus) {
+		err("out of memory\n");
+		rc = -ENOMEM;
+		goto err_free_ctrl;
+	}
+	memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus));
+
+	ctrl->bus = pdev->bus->number;
+	ctrl->rev = rev;
+	dbg("bus device function rev: %d %d %d %d\n", ctrl->bus,
+	     PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev);
+
+	init_MUTEX(&ctrl->crit_sect);
+	init_waitqueue_head(&ctrl->queue);
+
+	/* initialize our threads if they haven't already been started up */
+	rc = one_time_init();
+	if (rc) {
+		goto err_free_bus;
+	}
+	
+	dbg("pdev = %p\n", pdev);
+	dbg("pci resource start %lx\n", pci_resource_start(pdev, 0));
+	dbg("pci resource len %lx\n", pci_resource_len(pdev, 0));
+
+	if (!request_mem_region(pci_resource_start(pdev, 0),
+				pci_resource_len(pdev, 0), MY_NAME)) {
+		err("cannot reserve MMIO region\n");
+		rc = -ENOMEM;
+		goto err_free_bus;
+	}
+
+	ctrl->hpc_reg = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+	if (!ctrl->hpc_reg) {
+		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;
+	}
+
+	// Check for 66Mhz operation
+	ctrl->speed = get_controller_speed(ctrl);
+
+
+	//**************************************************
+	//
+	//              Save configuration headers for this and
+	//              subordinate PCI buses
+	//
+	//**************************************************
+
+	// find the physical slot number of the first hot plug slot
+
+	// Get slot won't work for devices behind bridges, but
+	// in this case it will always be called for the "base"
+	// bus/dev/func of a slot.
+	// CS: this is leveraging the PCIIRQ routing code from the kernel (pci-pc.c: get_irq_routing_table)
+	rc = get_slot_mapping(ctrl->pci_bus, pdev->bus->number, (readb(ctrl->hpc_reg + SLOT_MASK) >> 4), &(ctrl->first_slot));
+	dbg("get_slot_mapping: first_slot = %d, returned = %d\n", ctrl->first_slot, rc);
+	if (rc) {
+		err(msg_initialization_err, rc);
+		goto err_iounmap;
+	}
+
+	// Store PCI Config Space for all devices on this bus
+	rc = cpqhp_save_config(ctrl, ctrl->bus, readb(ctrl->hpc_reg + SLOT_MASK));
+	if (rc) {
+		err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
+		goto err_iounmap;
+	}
+
+	/*
+	 * Get IO, memory, and IRQ resources for new devices
+	 */
+	// The next line is required for cpqhp_find_available_resources
+	ctrl->interrupt = pdev->irq;
+
+	ctrl->cfgspc_irq = 0;
+	pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ctrl->cfgspc_irq);
+
+	rc = cpqhp_find_available_resources(ctrl, cpqhp_rom_start);
+	ctrl->add_support = !rc;
+	if (rc) {
+		dbg("cpqhp_find_available_resources = 0x%x\n", rc);
+		err("unable to locate PCI configuration resources for hot plug add.\n");
+		goto err_iounmap;
+	}
+
+	/*
+	 * Finish setting up the hot plug ctrl device
+	 */
+	ctrl->slot_device_offset = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
+	dbg("NumSlots %d \n", ctrl->slot_device_offset);
+
+	ctrl->next_event = 0;
+
+	/* Setup the slot information structures */
+	rc = ctrl_slot_setup(ctrl, smbios_start, smbios_table);
+	if (rc) {
+		err(msg_initialization_err, 6);
+		err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
+		goto err_iounmap;
+	}
+	
+	/* Mask all general input interrupts */
+	writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_MASK);
+
+	/* set up the interrupt */
+	dbg("HPC interrupt = %d \n", ctrl->interrupt);
+	if (request_irq(ctrl->interrupt, cpqhp_ctrl_intr,
+			SA_SHIRQ, MY_NAME, ctrl)) {
+		err("Can't get irq %d for the hotplug pci controller\n", ctrl->interrupt);
+		rc = -ENODEV;
+		goto err_iounmap;
+	}
+
+	/* Enable Shift Out interrupt and clear it, also enable SERR on power fault */
+	temp_word = readw(ctrl->hpc_reg + MISC);
+	temp_word |= 0x4006;
+	writew(temp_word, ctrl->hpc_reg + MISC);
+
+	// Changed 05/05/97 to clear all interrupts at start
+	writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_INPUT_CLEAR);
+
+	ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
+
+	writel(0x0L, ctrl->hpc_reg + INT_MASK);
+
+	if (!cpqhp_ctrl_list) {
+		cpqhp_ctrl_list = ctrl;
+		ctrl->next = NULL;
+	} else {
+		ctrl->next = cpqhp_ctrl_list;
+		cpqhp_ctrl_list = ctrl;
+	}
+
+	// turn off empty slots here unless command line option "ON" set
+	// Wait for exclusive access to hardware
+	down(&ctrl->crit_sect);
+
+	num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
+
+	// find first device number for the ctrl
+	device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
+
+	while (num_of_slots) {
+		dbg("num_of_slots: %d\n", num_of_slots);
+		func = cpqhp_slot_find(ctrl->bus, device, 0);
+		if (!func)
+			break;
+
+		hp_slot = func->device - ctrl->slot_device_offset;
+		dbg("hp_slot: %d\n", hp_slot);
+
+		// We have to save the presence info for these slots
+		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)) {
+			func->switch_save = 0;
+		} else {
+			func->switch_save = 0x10;
+		}
+
+		if (!power_mode) {
+			if (!func->is_a_board) {
+				green_LED_off (ctrl, hp_slot);
+				slot_disable (ctrl, hp_slot);
+			}
+		}
+
+		device++;
+		num_of_slots--;
+	}
+
+	if (!power_mode) {
+		set_SOGO(ctrl);
+		// Wait for SOBS to be unset
+		wait_for_ctrl_irq (ctrl);
+	}
+
+	rc = init_SERR(ctrl);
+	if (rc) {
+		err("init_SERR failed\n");
+		up(&ctrl->crit_sect);
+		goto err_free_irq;
+	}
+
+	// Done with exclusive hardware access
+	up(&ctrl->crit_sect);
+
+	cpqhp_create_ctrl_files (ctrl);
+
+	return 0;
+
+err_free_irq:
+	free_irq(ctrl->interrupt, ctrl);
+err_iounmap:
+	iounmap(ctrl->hpc_reg);
+err_free_mem_region:
+	release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+err_free_bus:
+	kfree(ctrl->pci_bus);
+err_free_ctrl:
+	kfree(ctrl);
+	return rc;
+}
+
+
+static int one_time_init(void)
+{
+	int loop;
+	int retval = 0;
+	static int initialized = 0;
+
+	if (initialized)
+		return 0;
+
+	power_mode = 0;
+
+	retval = pci_print_IRQ_route();
+	if (retval)
+		goto error;
+
+	dbg("Initialize + Start the notification mechanism \n");
+
+	retval = cpqhp_event_start_thread();
+	if (retval)
+		goto error;
+
+	dbg("Initialize slot lists\n");
+	for (loop = 0; loop < 256; loop++) {
+		cpqhp_slot_list[loop] = NULL;
+	}
+
+	// FIXME: We also need to hook the NMI handler eventually.
+	// this also needs to be worked with Christoph
+	// register_NMI_handler();
+
+	// Map rom address
+	cpqhp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
+	if (!cpqhp_rom_start) {
+		err ("Could not ioremap memory region for ROM\n");
+		retval = -EIO;;
+		goto error;
+	}
+	
+	/* Now, map the int15 entry point if we are on compaq specific hardware */
+	compaq_nvram_init(cpqhp_rom_start);
+	
+	/* Map smbios table entry point structure */
+	smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start, cpqhp_rom_start + ROM_PHY_LEN);
+	if (!smbios_table) {
+		err ("Could not find the SMBIOS pointer in memory\n");
+		retval = -EIO;;
+		goto error;
+	}
+
+	smbios_start = ioremap(readl(smbios_table + ST_ADDRESS), readw(smbios_table + ST_LENGTH));
+	if (!smbios_start) {
+		err ("Could not ioremap memory region taken from SMBIOS values\n");
+		retval = -EIO;;
+		goto error;
+	}
+
+	initialized = 1;
+
+	return retval;
+
+error:
+	if (cpqhp_rom_start)
+		iounmap(cpqhp_rom_start);
+	if (smbios_start)
+		iounmap(smbios_start);
+	
+	return retval;
+}
+
+
+static void unload_cpqphpd(void)
+{
+	struct pci_func *next;
+	struct pci_func *TempSlot;
+	int loop;
+	u32 rc;
+	struct controller *ctrl;
+	struct controller *tctrl;
+	struct pci_resource *res;
+	struct pci_resource *tres;
+
+	rc = compaq_nvram_store(cpqhp_rom_start);
+
+	ctrl = cpqhp_ctrl_list;
+
+	while (ctrl) {
+		if (ctrl->hpc_reg) {
+			u16 misc;
+			rc = read_slot_enable (ctrl);
+			
+			writeb(0, ctrl->hpc_reg + SLOT_SERR);
+			writel(0xFFFFFFC0L | ~rc, ctrl->hpc_reg + INT_MASK);
+			
+			misc = readw(ctrl->hpc_reg + MISC);
+			misc &= 0xFFFD;
+			writew(misc, ctrl->hpc_reg + MISC);
+		}
+
+		ctrl_slot_cleanup(ctrl);
+
+		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);
+		}
+
+		kfree (ctrl->pci_bus);
+
+		tctrl = ctrl;
+		ctrl = ctrl->next;
+		kfree(tctrl);
+	}
+
+	for (loop = 0; loop < 256; loop++) {
+		next = cpqhp_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);
+		}
+	}
+
+	// Stop the notification mechanism
+	cpqhp_event_stop_thread();
+
+	//unmap the rom address
+	if (cpqhp_rom_start)
+		iounmap(cpqhp_rom_start);
+	if (smbios_start)
+		iounmap(smbios_start);
+}
+
+
+
+static struct pci_device_id hpcd_pci_tbl[] __devinitdata = {
+	{
+	/* handle any PCI Hotplug controller */
+	.class =        ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00),
+	.class_mask =   ~0,
+	
+	/* no matter who makes it */
+	.vendor =       PCI_ANY_ID,
+	.device =       PCI_ANY_ID,
+	.subvendor =    PCI_ANY_ID,
+	.subdevice =    PCI_ANY_ID,
+	
+	}, { /* end: all zeroes */ }
+};
+
+MODULE_DEVICE_TABLE(pci, hpcd_pci_tbl);
+
+
+
+static struct pci_driver cpqhpc_driver = {
+	.name =		"pci_hotplug",
+	.id_table =	hpcd_pci_tbl,
+	.probe =	cpqhpc_probe,
+	/* remove:	cpqhpc_remove_one, */
+};
+
+
+
+static int __init cpqhpc_init(void)
+{
+	int result;
+
+	cpqhp_debug = debug;
+
+	result = pci_module_init(&cpqhpc_driver);
+	dbg("pci_module_init = %d\n", result);
+	if (result)
+		return result;
+	info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
+	return 0;
+}
+
+
+static void __exit cpqhpc_cleanup(void)
+{
+	dbg("unload_cpqphpd()\n");
+	unload_cpqphpd();
+
+	dbg("pci_unregister_driver\n");
+	pci_unregister_driver(&cpqhpc_driver);
+}
+
+
+module_init(cpqhpc_init);
+module_exit(cpqhpc_cleanup);
+
+
diff -Nru a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/cpqphp_ctrl.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,3084 @@
+/*
+ * Compaq Hot Plug Controller Driver
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/smp_lock.h>
+#include <linux/pci.h>
+#include "cpqphp.h"
+
+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);
+static void interrupt_event_handler(struct controller *ctrl);
+
+static struct semaphore event_semaphore;	/* mutex for process loop (up if something to process) */
+static struct semaphore event_exit;		/* guard ensure thread has exited before calling it quits */
+static int event_finished;
+static unsigned long pushbutton_pending;	/* = 0 */
+
+/* things needed for the long_delay function */
+static struct semaphore		delay_sem;
+static wait_queue_head_t	delay_wait;
+
+/* delay is in jiffies to wait for */
+static void long_delay (int delay)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	
+	/* only allow 1 customer into the delay queue at once
+	 * yes this makes some people wait even longer, but who really cares?
+	 * this is for _huge_ delays to make the hardware happy as the 
+	 * signals bounce around
+	 */
+	down (&delay_sem);
+
+	init_waitqueue_head (&delay_wait);
+
+	add_wait_queue(&delay_wait, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(delay);
+	remove_wait_queue(&delay_wait, &wait);
+	set_current_state(TASK_RUNNING);
+	
+	up (&delay_sem);
+}
+
+
+//FIXME: The following line needs to be somewhere else...
+#define WRONG_BUS_FREQUENCY 0x07
+static u8 handle_switch_change(u8 change, struct controller * ctrl)
+{
+	int hp_slot;
+	u8 rc = 0;
+	u16 temp_word;
+	struct pci_func *func;
+	struct event_info *taskInfo;
+
+	if (!change)
+		return 0;
+
+	// Switch Change
+	dbg("cpqsbd:  Switch interrupt received.\n");
+
+	for (hp_slot = 0; hp_slot < 6; hp_slot++) {
+		if (change & (0x1L << hp_slot)) {
+			//*********************************
+			// this one changed.
+			//*********************************
+			func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0);
+
+			//this is the structure that tells the worker thread
+			//what to do
+			taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+			ctrl->next_event = (ctrl->next_event + 1) % 10;
+			taskInfo->hp_slot = hp_slot;
+
+			rc++;
+
+			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)) {
+				//*********************************
+				// Switch opened
+				//*********************************
+
+				func->switch_save = 0;
+
+				taskInfo->event_type = INT_SWITCH_OPEN;
+			} else {
+				//*********************************
+				// Switch closed
+				//*********************************
+
+				func->switch_save = 0x10;
+
+				taskInfo->event_type = INT_SWITCH_CLOSE;
+			}
+		}
+	}
+
+	return rc;
+}
+
+
+/*
+ * cpqhp_find_slot
+ */
+struct slot *cpqhp_find_slot (struct controller * ctrl, u8 device)
+{
+	struct slot *slot;
+
+	if (!ctrl)
+		return NULL;
+
+	slot = ctrl->slot;
+
+	while (slot && (slot->device != device)) {
+		slot = slot->next;
+	}
+
+	return slot;
+}
+
+
+static u8 handle_presence_change(u16 change, struct controller * ctrl)
+{
+	int hp_slot;
+	u8 rc = 0;
+	u8 temp_byte;
+	u16 temp_word;
+	struct pci_func *func;
+	struct event_info *taskInfo;
+	struct slot *p_slot;
+
+	if (!change)
+		return 0;
+
+	//*********************************
+	// Presence Change
+	//*********************************
+	dbg("cpqsbd:  Presence/Notify input change.\n");
+	dbg("         Changed bits are 0x%4.4x\n", change );
+
+	for (hp_slot = 0; hp_slot < 6; hp_slot++) {
+		if (change & (0x0101 << hp_slot)) {
+			//*********************************
+			// this one changed.
+			//*********************************
+			func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0);
+
+			taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+			ctrl->next_event = (ctrl->next_event + 1) % 10;
+			taskInfo->hp_slot = hp_slot;
+
+			rc++;
+
+			p_slot = cpqhp_find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4));
+			if (!p_slot)
+				return 0;
+
+			// If the switch closed, must be a button
+			// If not in button mode, nevermind
+			if (func->switch_save && (ctrl->push_button == 1)) {
+				temp_word = ctrl->ctrl_int_comp >> 16;
+				temp_byte = (temp_word >> hp_slot) & 0x01;
+				temp_byte |= (temp_word >> (hp_slot + 7)) & 0x02;
+
+				if (temp_byte != func->presence_save) {
+					//*********************************
+					// button Pressed (doesn't do anything)
+					//*********************************
+					dbg("hp_slot %d button pressed\n", hp_slot);
+					taskInfo->event_type = INT_BUTTON_PRESS;
+				} else {
+					//*********************************
+					// button Released - TAKE ACTION!!!!
+					//*********************************
+					dbg("hp_slot %d button released\n", hp_slot);
+					taskInfo->event_type = INT_BUTTON_RELEASE;
+
+					// Cancel if we are still blinking
+					if ((p_slot->state == BLINKINGON_STATE)
+					    || (p_slot->state == BLINKINGOFF_STATE)) {
+						taskInfo->event_type = INT_BUTTON_CANCEL;
+						dbg("hp_slot %d button cancel\n", hp_slot);
+					} else if ((p_slot->state == POWERON_STATE)
+						   || (p_slot->state == POWEROFF_STATE)) {
+						//info(msg_button_ignore, p_slot->number);
+						taskInfo->event_type = INT_BUTTON_IGNORE;
+						dbg("hp_slot %d button ignore\n", hp_slot);
+					}
+				}
+			} else {
+				// Switch is open, assume a presence change
+				// Save the presence state
+				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 & (0x010000 << hp_slot))) ||
+				    (!(ctrl->ctrl_int_comp & (0x01000000 << hp_slot)))) {
+					//*********************************
+					// Present
+					//*********************************
+					taskInfo->event_type = INT_PRESENCE_ON;
+				} else {
+					//*********************************
+					// Not Present
+					//*********************************
+					taskInfo->event_type = INT_PRESENCE_OFF;
+				}
+			}
+		}
+	}
+
+	return rc;
+}
+
+
+static u8 handle_power_fault(u8 change, struct controller * ctrl)
+{
+	int hp_slot;
+	u8 rc = 0;
+	struct pci_func *func;
+	struct event_info *taskInfo;
+
+	if (!change)
+		return 0;
+
+	//*********************************
+	// power fault
+	//*********************************
+
+	info("power fault interrupt\n");
+
+	for (hp_slot = 0; hp_slot < 6; hp_slot++) {
+		if (change & (0x01 << hp_slot)) {
+			//*********************************
+			// this one changed.
+			//*********************************
+			func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0);
+
+			taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+			ctrl->next_event = (ctrl->next_event + 1) % 10;
+			taskInfo->hp_slot = hp_slot;
+
+			rc++;
+
+			if (ctrl->ctrl_int_comp & (0x00000100 << hp_slot)) {
+				//*********************************
+				// power fault Cleared
+				//*********************************
+				func->status = 0x00;
+
+				taskInfo->event_type = INT_POWER_FAULT_CLEAR;
+			} else {
+				//*********************************
+				// power fault
+				//*********************************
+				taskInfo->event_type = INT_POWER_FAULT;
+
+				if (ctrl->rev < 4) {
+					amber_LED_on (ctrl, hp_slot);
+					green_LED_off (ctrl, hp_slot);
+					set_SOGO (ctrl);
+
+					// this is a fatal condition, we want to crash the
+					// machine to protect from data corruption
+					// simulated_NMI shouldn't ever return
+					//FIXME
+					//simulated_NMI(hp_slot, ctrl);
+
+					//The following code causes a software crash just in
+					//case simulated_NMI did return
+					//FIXME
+					//panic(msg_power_fault);
+				} else {
+					// set power fault status for this board
+					func->status = 0xFF;
+					info("power fault bit %x set\n", hp_slot);
+				}
+			}
+		}
+	}
+
+	return rc;
+}
+
+
+/*
+ * 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);
+}
+
+
+/*
+ * 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);
+}
+
+
+/*
+ * 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("do_pre_bridge_resource_split\n");
+
+	if (!(*head) || !(*orig_head))
+		return(NULL);
+
+	rc = cpqhp_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 = cpqhp_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);
+}
+
+
+/*
+ * 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 ( cpqhp_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_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 (cpqhp_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_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 ( cpqhp_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);
+}
+
+
+/*
+ * cpqhp_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 cpqhp_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("*head->next = %p\n",(*head)->next);
+
+	if (!(*head)->next)
+		return(0);	/* only one item on the list, already sorted! */
+
+	dbg("*head->base = 0x%x\n",(*head)->base);
+	dbg("*head->next->base = 0x%x\n",(*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("8..\n");
+			node1->length += node1->next->length;
+			node2 = node1->next;
+			node1->next = node1->next->next;
+			kfree(node2);
+		} else
+			node1 = node1->next;
+	}
+
+	return(0);
+}
+
+
+irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data, struct pt_regs *regs)
+{
+	struct controller *ctrl = data;
+	u8 schedule_flag = 0;
+	u8 reset;
+	u16 misc;
+	u32 Diff;
+	u32 temp_dword;
+
+	
+	misc = readw(ctrl->hpc_reg + MISC);
+	//*********************************
+	// Check to see if it was our interrupt
+	//*********************************
+	if (!(misc & 0x000C)) {
+		return IRQ_NONE;
+	}
+
+	if (misc & 0x0004) {
+		//*********************************
+		// Serial Output interrupt Pending
+		//*********************************
+
+		// Clear the interrupt
+		misc |= 0x0004;
+		writew(misc, ctrl->hpc_reg + MISC);
+
+		// Read to clear posted writes
+		misc = readw(ctrl->hpc_reg + MISC);
+
+		dbg ("%s - waking up\n", __FUNCTION__);
+		wake_up_interruptible(&ctrl->queue);
+	}
+
+	if (misc & 0x0008) {
+		// General-interrupt-input interrupt Pending
+		Diff = readl(ctrl->hpc_reg + INT_INPUT_CLEAR) ^ ctrl->ctrl_int_comp;
+
+		ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
+
+		// Clear the interrupt
+		writel(Diff, ctrl->hpc_reg + INT_INPUT_CLEAR);
+
+		// Read it back to clear any posted writes
+		temp_dword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
+
+		if (!Diff) {
+			// Clear all interrupts
+			writel(0xFFFFFFFF, ctrl->hpc_reg + INT_INPUT_CLEAR);
+		}
+
+		schedule_flag += handle_switch_change((u8)(Diff & 0xFFL), ctrl);
+		schedule_flag += handle_presence_change((u16)((Diff & 0xFFFF0000L) >> 16), ctrl);
+		schedule_flag += handle_power_fault((u8)((Diff & 0xFF00L) >> 8), ctrl);
+	}
+
+	reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE);
+	if (reset & 0x40) {
+		/* Bus reset has completed */
+		reset &= 0xCF;
+		writeb(reset, ctrl->hpc_reg + RESET_FREQ_MODE);
+		reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE);
+		wake_up_interruptible(&ctrl->queue);
+	}
+
+	if (schedule_flag) {
+		up(&event_semaphore);
+		dbg("Signal event_semaphore\n");
+	}
+	return IRQ_HANDLED;
+}
+
+
+/**
+ * cpqhp_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 *cpqhp_slot_create(u8 busnumber)
+{
+	struct pci_func *new_slot;
+	struct pci_func *next;
+
+	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 (cpqhp_slot_list[busnumber] == NULL) {
+		cpqhp_slot_list[busnumber] = new_slot;
+	} else {
+		next = cpqhp_slot_list[busnumber];
+		while (next->next != NULL)
+			next = next->next;
+		next->next = new_slot;
+	}
+	return(new_slot);
+}
+
+
+/*
+ * 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;
+
+	if (old_slot == NULL)
+		return(1);
+
+	next = cpqhp_slot_list[old_slot->bus];
+
+	if (next == NULL) {
+		return(1);
+	}
+
+	if (next == old_slot) {
+		cpqhp_slot_list[old_slot->bus] = old_slot->next;
+		cpqhp_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;
+		cpqhp_destroy_board_resources(old_slot);
+		kfree(old_slot);
+		return(0);
+	} else
+		return(2);
+}
+
+
+/**
+ * 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;
+
+	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 = cpqhp_slot_list[tempBus];
+
+		while (!slot_remove(next)) {
+			next = cpqhp_slot_list[tempBus];
+		}
+	}
+
+	next = cpqhp_slot_list[bridge->bus];
+
+	if (next == NULL) {
+		return(1);
+	}
+
+	if (next == bridge) {
+		cpqhp_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);
+}
+
+
+/**
+ * cpqhp_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 *cpqhp_slot_find(u8 bus, u8 device, u8 index)
+{
+	int found = -1;
+	struct pci_func *func;
+
+	func = cpqhp_slot_list[bus];
+
+	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);
+}
+
+
+// DJZ: I don't think is_bridge will work as is.
+//FIXME
+static int is_bridge(struct pci_func * func)
+{
+	// Check the header type
+	if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)
+		return 1;
+	else
+		return 0;
+}
+
+
+/* the following routines constitute the bulk of the 
+   hotplug controller logic
+ */
+
+
+/**
+ * board_replaced - Called after a board has been replaced in the system.
+ *
+ * This is only used if we don't have resources for hot add
+ * Turns power on for the board
+ * Checks to see if board is the same
+ * If board is same, reconfigures it
+ * If board isn't same, turns it back off.
+ *
+ */
+static u32 board_replaced(struct pci_func * func, struct controller * ctrl)
+{
+	u8 hp_slot;
+	u8 temp_byte;
+	u8 adapter_speed;
+	u32 index;
+	u32 rc = 0;
+	u32 src = 8;
+
+	hp_slot = func->device - ctrl->slot_device_offset;
+
+	if (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot)) {
+		//*********************************
+		// The switch is open.
+		//*********************************
+		rc = INTERLOCK_OPEN;
+	} else if (is_slot_enabled (ctrl, hp_slot)) {
+		//*********************************
+		// The board is already on
+		//*********************************
+		rc = CARD_FUNCTIONING;
+	} else {
+		// Wait for exclusive access to hardware
+		down(&ctrl->crit_sect);
+
+		// turn on board without attaching to the bus
+		enable_slot_power (ctrl, hp_slot);
+
+		set_SOGO(ctrl);
+
+		// Wait for SOBS to be unset
+		wait_for_ctrl_irq (ctrl);
+
+		// Change bits in slot power register to force another shift out
+		// NOTE: this is to work around the timer bug
+		temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
+		writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
+		writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
+
+		set_SOGO(ctrl);
+
+		// Wait for SOBS to be unset
+		wait_for_ctrl_irq (ctrl);
+		
+		adapter_speed = get_adapter_speed(ctrl, hp_slot);
+		if (ctrl->speed != adapter_speed)
+			if (set_controller_speed(ctrl, adapter_speed, hp_slot))
+				rc = WRONG_BUS_FREQUENCY;
+
+		// turn off board without attaching to the bus
+		disable_slot_power (ctrl, hp_slot);
+
+		set_SOGO(ctrl);
+
+		// Wait for SOBS to be unset
+		wait_for_ctrl_irq (ctrl);
+
+		// Done with exclusive hardware access
+		up(&ctrl->crit_sect);
+
+		if (rc)
+			return(rc);
+
+		// Wait for exclusive access to hardware
+		down(&ctrl->crit_sect);
+
+		slot_enable (ctrl, hp_slot);
+		green_LED_blink (ctrl, hp_slot);
+
+		amber_LED_off (ctrl, hp_slot);
+
+		set_SOGO(ctrl);
+
+		// Wait for SOBS to be unset
+		wait_for_ctrl_irq (ctrl);
+
+		// Done with exclusive hardware access
+		up(&ctrl->crit_sect);
+
+		// Wait for ~1 second because of hot plug spec
+		long_delay(1*HZ);
+
+		// Check for a power fault
+		if (func->status == 0xFF) {
+			// power fault occurred, but it was benign
+			rc = POWER_FAILURE;
+			func->status = 0;
+		} else
+			rc = cpqhp_valid_replace(ctrl, func);
+
+		if (!rc) {
+			// It must be the same board
+
+			rc = cpqhp_configure_board(ctrl, func);
+
+			if (rc || src) {
+				// If configuration fails, turn it off
+				// Get slot won't work for devices behind bridges, but
+				// in this case it will always be called for the "base"
+				// bus/dev/func of an adapter.
+
+				// Wait for exclusive access to hardware
+				down(&ctrl->crit_sect);
+
+				amber_LED_on (ctrl, hp_slot);
+				green_LED_off (ctrl, hp_slot);
+				slot_disable (ctrl, hp_slot);
+
+				set_SOGO(ctrl);
+
+				// Wait for SOBS to be unset
+				wait_for_ctrl_irq (ctrl);
+
+				// Done with exclusive hardware access
+				up(&ctrl->crit_sect);
+
+				if (rc)
+					return(rc);
+				else
+					return(1);
+			}
+
+			func->status = 0;
+			func->switch_save = 0x10;
+
+			index = 1;
+			while (((func = cpqhp_slot_find(func->bus, func->device, index)) != NULL) && !rc) {
+				rc |= cpqhp_configure_board(ctrl, func);
+				index++;
+			}
+
+			if (rc) {
+				// If configuration fails, turn it off
+				// Get slot won't work for devices behind bridges, but
+				// in this case it will always be called for the "base"
+				// bus/dev/func of an adapter.
+
+				// Wait for exclusive access to hardware
+				down(&ctrl->crit_sect);
+
+				amber_LED_on (ctrl, hp_slot);
+				green_LED_off (ctrl, hp_slot);
+				slot_disable (ctrl, hp_slot);
+
+				set_SOGO(ctrl);
+
+				// Wait for SOBS to be unset
+				wait_for_ctrl_irq (ctrl);
+
+				// Done with exclusive hardware access
+				up(&ctrl->crit_sect);
+
+				return(rc);
+			}
+			// Done configuring so turn LED on full time
+
+			// Wait for exclusive access to hardware
+			down(&ctrl->crit_sect);
+
+			green_LED_on (ctrl, hp_slot);
+
+			set_SOGO(ctrl);
+
+			// Wait for SOBS to be unset
+			wait_for_ctrl_irq (ctrl);
+
+			// Done with exclusive hardware access
+			up(&ctrl->crit_sect);
+			rc = 0;
+		} else {
+			// Something is wrong
+
+			// Get slot won't work for devices behind bridges, but
+			// in this case it will always be called for the "base"
+			// bus/dev/func of an adapter.
+
+			// Wait for exclusive access to hardware
+			down(&ctrl->crit_sect);
+
+			amber_LED_on (ctrl, hp_slot);
+			green_LED_off (ctrl, hp_slot);
+			slot_disable (ctrl, hp_slot);
+
+			set_SOGO(ctrl);
+
+			// Wait for SOBS to be unset
+			wait_for_ctrl_irq (ctrl);
+
+			// Done with exclusive hardware access
+			up(&ctrl->crit_sect);
+		}
+
+	}
+	return(rc);
+
+}
+
+
+/**
+ * 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)
+{
+	u8 hp_slot;
+	u8 temp_byte;
+	u8 adapter_speed;
+	int index;
+	u32 temp_register = 0xFFFFFFFF;
+	u32 rc = 0;
+	struct pci_func *new_slot = NULL;
+	struct slot *p_slot;
+	struct resource_lists res_lists;
+
+	hp_slot = func->device - ctrl->slot_device_offset;
+	dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n",
+	    __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
+
+	// Wait for exclusive access to hardware
+	down(&ctrl->crit_sect);
+
+	// turn on board without attaching to the bus
+	enable_slot_power (ctrl, hp_slot);
+
+	set_SOGO(ctrl);
+
+	// Wait for SOBS to be unset
+	wait_for_ctrl_irq (ctrl);
+
+	// Change bits in slot power register to force another shift out
+	// NOTE: this is to work around the timer bug
+	temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
+	writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
+	writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
+
+	set_SOGO(ctrl);
+
+	// Wait for SOBS to be unset
+	wait_for_ctrl_irq (ctrl);
+	
+	adapter_speed = get_adapter_speed(ctrl, hp_slot);
+	if (ctrl->speed != adapter_speed)
+		if (set_controller_speed(ctrl, adapter_speed, hp_slot))
+			rc = WRONG_BUS_FREQUENCY;
+	
+	// turn off board without attaching to the bus
+	disable_slot_power (ctrl, hp_slot);
+
+	set_SOGO(ctrl);
+
+	// Wait for SOBS to be unset
+	wait_for_ctrl_irq (ctrl);
+
+	// Done with exclusive hardware access
+	up(&ctrl->crit_sect);
+
+	if (rc)
+		return(rc);
+	
+	p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+	// turn on board and blink green LED
+
+	// Wait for exclusive access to hardware
+	dbg("%s: before down\n", __FUNCTION__);
+	down(&ctrl->crit_sect);
+	dbg("%s: after down\n", __FUNCTION__);
+
+	dbg("%s: before slot_enable\n", __FUNCTION__);
+	slot_enable (ctrl, hp_slot);
+
+	dbg("%s: before green_LED_blink\n", __FUNCTION__);
+	green_LED_blink (ctrl, hp_slot);
+
+	dbg("%s: before amber_LED_blink\n", __FUNCTION__);
+	amber_LED_off (ctrl, hp_slot);
+
+	dbg("%s: before set_SOGO\n", __FUNCTION__);
+	set_SOGO(ctrl);
+
+	// Wait for SOBS to be unset
+	dbg("%s: before wait_for_ctrl_irq\n", __FUNCTION__);
+	wait_for_ctrl_irq (ctrl);
+	dbg("%s: after wait_for_ctrl_irq\n", __FUNCTION__);
+
+	// Done with exclusive hardware access
+	dbg("%s: before up\n", __FUNCTION__);
+	up(&ctrl->crit_sect);
+	dbg("%s: after up\n", __FUNCTION__);
+
+	// Wait for ~1 second because of hot plug spec
+	dbg("%s: before long_delay\n", __FUNCTION__);
+	long_delay(1*HZ);
+	dbg("%s: after long_delay\n", __FUNCTION__);
+
+	dbg("%s: func status = %x\n", __FUNCTION__, func->status);
+	// Check for a power fault
+	if (func->status == 0xFF) {
+		// power fault occurred, but it was benign
+		temp_register = 0xFFFFFFFF;
+		dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register);
+		rc = POWER_FAILURE;
+		func->status = 0;
+	} else {
+		// Get vendor/device ID u32
+		ctrl->pci_bus->number = func->bus;
+		rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(func->device, func->function), PCI_VENDOR_ID, &temp_register);
+		dbg("%s: pci_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;
+
+		cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
+		cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
+		cpqhp_resource_sort_and_combine(&(ctrl->io_head));
+		cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
+
+		if (rc) {
+			// Wait for exclusive access to hardware
+			down(&ctrl->crit_sect);
+
+			amber_LED_on (ctrl, hp_slot);
+			green_LED_off (ctrl, hp_slot);
+			slot_disable (ctrl, hp_slot);
+
+			set_SOGO(ctrl);
+
+			// Wait for SOBS to be unset
+			wait_for_ctrl_irq (ctrl);
+
+			// Done with exclusive hardware access
+			up(&ctrl->crit_sect);
+			return(rc);
+		} else {
+			cpqhp_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 = cpqhp_slot_find(ctrl->bus, func->device, index++);
+			if (new_slot && !new_slot->pci_dev) {
+				cpqhp_configure_device(ctrl, new_slot);
+			}
+		} while (new_slot);
+
+		// Wait for exclusive access to hardware
+		down(&ctrl->crit_sect);
+
+		green_LED_on (ctrl, hp_slot);
+
+		set_SOGO(ctrl);
+
+		// Wait for SOBS to be unset
+		wait_for_ctrl_irq (ctrl);
+
+		// Done with exclusive hardware access
+		up(&ctrl->crit_sect);
+	} else {
+		// Wait for exclusive access to hardware
+		down(&ctrl->crit_sect);
+
+		amber_LED_on (ctrl, hp_slot);
+		green_LED_off (ctrl, hp_slot);
+		slot_disable (ctrl, hp_slot);
+
+		set_SOGO(ctrl);
+
+		// Wait for SOBS to be unset
+		wait_for_ctrl_irq (ctrl);
+
+		// Done with exclusive hardware access
+		up(&ctrl->crit_sect);
+
+		return(rc);
+	}
+	return 0;
+}
+
+
+/**
+ * remove_board - Turns off slot and LED's
+ *
+ */
+static u32 remove_board(struct pci_func * func, u32 replace_flag, struct controller * ctrl)
+{
+	int index;
+	u8 skip = 0;
+	u8 device;
+	u8 hp_slot;
+	u8 temp_byte;
+	u32 rc;
+	struct resource_lists res_lists;
+	struct pci_func *temp_func;
+
+	if (func == NULL)
+		return(1);
+
+	if (cpqhp_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 = cpqhp_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 = cpqhp_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 = cpqhp_slot_find(temp_func->bus, temp_func->device, index++);
+		}
+
+		if (!skip)
+			rc = cpqhp_save_used_resources(ctrl, func);
+	}
+	// Change status to shutdown
+	if (func->is_a_board)
+		func->status = 0x01;
+	func->configured = 0;
+
+	// Wait for exclusive access to hardware
+	down(&ctrl->crit_sect);
+
+	green_LED_off (ctrl, hp_slot);
+	slot_disable (ctrl, hp_slot);
+
+	set_SOGO(ctrl);
+
+	// turn off SERR for slot
+	temp_byte = readb(ctrl->hpc_reg + SLOT_SERR);
+	temp_byte &= ~(0x01 << hp_slot);
+	writeb(temp_byte, ctrl->hpc_reg + SLOT_SERR);
+
+	// Wait for SOBS to be unset
+	wait_for_ctrl_irq (ctrl);
+
+	// Done with exclusive hardware access
+	up(&ctrl->crit_sect);
+
+	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;
+
+			cpqhp_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;
+
+			cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
+			cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
+			cpqhp_resource_sort_and_combine(&(ctrl->io_head));
+			cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
+
+			if (is_bridge(func)) {
+				bridge_slot_remove(func);
+			} else
+				slot_remove(func);
+
+			func = cpqhp_slot_find(ctrl->bus, device, 0);
+		}
+
+		// Setup slot structure with entry for empty slot
+		func = cpqhp_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;
+}
+
+
+static void pushbutton_helper_thread (unsigned long data)
+{
+	pushbutton_pending = data;
+	up(&event_semaphore);
+}
+
+
+// this is the main worker thread
+static int event_thread(void* data)
+{
+	struct controller *ctrl;
+	lock_kernel();
+	daemonize("phpd_event");
+	
+	unlock_kernel();
+
+	while (1) {
+		dbg("!!!!event_thread sleeping\n");
+		down_interruptible (&event_semaphore);
+		dbg("event_thread woken finished = %d\n", event_finished);
+		if (event_finished) break;
+		/* Do stuff here */
+		if (pushbutton_pending)
+			cpqhp_pushbutton_thread(pushbutton_pending);
+		else
+			for (ctrl = cpqhp_ctrl_list; ctrl; ctrl=ctrl->next)
+				interrupt_event_handler(ctrl);
+	}
+	dbg("event_thread signals exit\n");
+	up(&event_exit);
+	return 0;
+}
+
+
+int cpqhp_event_start_thread (void)
+{
+	int pid;
+
+	/* initialize our semaphores */
+	init_MUTEX(&delay_sem);
+	init_MUTEX_LOCKED(&event_semaphore);
+	init_MUTEX_LOCKED(&event_exit);
+	event_finished=0;
+
+	pid = kernel_thread(event_thread, 0, 0);
+	if (pid < 0) {
+		err ("Can't start up our event thread\n");
+		return -1;
+	}
+	dbg("Our event thread pid = %d\n", pid);
+	return 0;
+}
+
+
+void cpqhp_event_stop_thread (void)
+{
+	event_finished = 1;
+	dbg("event_thread finish command given\n");
+	up(&event_semaphore);
+	dbg("wait for event_thread to exit\n");
+	down(&event_exit);
+}
+
+
+static int update_slot_info (struct controller *ctrl, struct slot *slot)
+{
+	struct hotplug_slot_info *info;
+	int result;
+
+	info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	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(slot->hotplug_slot, info);
+	kfree (info);
+	return result;
+}
+
+static void interrupt_event_handler(struct controller *ctrl)
+{
+	int loop = 0;
+	int change = 1;
+	struct pci_func *func;
+	u8 hp_slot;
+	struct slot *p_slot;
+
+	while (change) {
+		change = 0;
+
+		for (loop = 0; loop < 10; loop++) {
+			//dbg("loop %d\n", loop);
+			if (ctrl->event_queue[loop].event_type != 0) {
+				hp_slot = ctrl->event_queue[loop].hp_slot;
+
+				func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0);
+				if (!func)
+					return;
+
+				p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+				if (!p_slot)
+					return;
+
+				dbg("hp_slot %d, func %p, p_slot %p\n",
+				    hp_slot, func, p_slot);
+
+				if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) {
+					dbg("button pressed\n");
+				} else if (ctrl->event_queue[loop].event_type == 
+					   INT_BUTTON_CANCEL) {
+					dbg("button cancel\n");
+					del_timer(&p_slot->task_event);
+
+					// Wait for exclusive access to hardware
+					down(&ctrl->crit_sect);
+
+					if (p_slot->state == BLINKINGOFF_STATE) {
+						// slot is on
+						// turn on green LED
+						dbg("turn on green LED\n");
+						green_LED_on (ctrl, hp_slot);
+					} else if (p_slot->state == BLINKINGON_STATE) {
+						// slot is off
+						// turn off green LED
+						dbg("turn off green LED\n");
+						green_LED_off (ctrl, hp_slot);
+					}
+
+					info(msg_button_cancel, p_slot->number);
+
+					p_slot->state = STATIC_STATE;
+
+					amber_LED_off (ctrl, hp_slot);
+
+					set_SOGO(ctrl);
+
+					// Wait for SOBS to be unset
+					wait_for_ctrl_irq (ctrl);
+
+					// Done with exclusive hardware access
+					up(&ctrl->crit_sect);
+				}
+				// ***********button Released (No action on press...)
+				else if (ctrl->event_queue[loop].event_type == INT_BUTTON_RELEASE) {
+					dbg("button release\n");
+
+					if (is_slot_enabled (ctrl, hp_slot)) {
+						// slot is on
+						dbg("slot is on\n");
+						p_slot->state = BLINKINGOFF_STATE;
+						info(msg_button_off, p_slot->number);
+					} else {
+						// slot is off
+						dbg("slot is off\n");
+						p_slot->state = BLINKINGON_STATE;
+						info(msg_button_on, p_slot->number);
+					}
+					// Wait for exclusive access to hardware
+					down(&ctrl->crit_sect);
+					
+					dbg("blink green LED and turn off amber\n");
+					
+					amber_LED_off (ctrl, hp_slot);
+					green_LED_blink (ctrl, hp_slot);
+					
+					set_SOGO(ctrl);
+
+					// Wait for SOBS to be unset
+					wait_for_ctrl_irq (ctrl);
+
+					// Done with exclusive hardware access
+					up(&ctrl->crit_sect);
+					init_timer(&p_slot->task_event);
+					p_slot->hp_slot = hp_slot;
+					p_slot->ctrl = ctrl;
+//					p_slot->physical_slot = physical_slot;
+					p_slot->task_event.expires = jiffies + 5 * HZ;   // 5 second delay
+					p_slot->task_event.function = pushbutton_helper_thread;
+					p_slot->task_event.data = (u32) p_slot;
+
+					dbg("add_timer p_slot = %p\n", p_slot);
+					add_timer(&p_slot->task_event);
+				}
+				// ***********POWER FAULT
+				else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
+					dbg("power fault\n");
+				} else {
+					/* refresh notification */
+					if (p_slot)
+						update_slot_info(ctrl, p_slot);
+				}
+
+				ctrl->event_queue[loop].event_type = 0;
+
+				change = 1;
+			}
+		}		// End of FOR loop
+	}
+
+	return;
+}
+
+
+/**
+ * cpqhp_pushbutton_thread
+ *
+ * Scheduled procedure to handle blocking stuff for the pushbuttons
+ * Handles all pending events and exits.
+ *
+ */
+void cpqhp_pushbutton_thread (unsigned long slot)
+{
+	u8 hp_slot;
+	u8 device;
+	struct pci_func *func;
+	struct slot *p_slot = (struct slot *) slot;
+	struct controller *ctrl = (struct controller *) p_slot->ctrl;
+
+	pushbutton_pending = 0;
+	hp_slot = p_slot->hp_slot;
+
+	device = p_slot->device;
+
+	if (is_slot_enabled (ctrl, hp_slot)) {
+		p_slot->state = POWEROFF_STATE;
+		// power Down board
+		func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0);
+		dbg("In power_down_board, func = %p, ctrl = %p\n", func, ctrl);
+		if (!func) {
+			dbg("Error! func NULL in %s\n", __FUNCTION__);
+			return ;
+		}
+
+		if (func != NULL && ctrl != NULL) {
+			if (cpqhp_process_SS(ctrl, func) != 0) {
+				amber_LED_on (ctrl, hp_slot);
+				green_LED_on (ctrl, hp_slot);
+				
+				set_SOGO(ctrl);
+
+				// Wait for SOBS to be unset
+				wait_for_ctrl_irq (ctrl);
+			}
+		}
+
+		p_slot->state = STATIC_STATE;
+	} else {
+		p_slot->state = POWERON_STATE;
+		// slot is off
+
+		func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0);
+		dbg("In add_board, func = %p, ctrl = %p\n", func, ctrl);
+		if (!func) {
+			dbg("Error! func NULL in %s\n", __FUNCTION__);
+			return ;
+		}
+
+		if (func != NULL && ctrl != NULL) {
+			if (cpqhp_process_SI(ctrl, func) != 0) {
+				amber_LED_on (ctrl, hp_slot);
+				green_LED_off (ctrl, hp_slot);
+				
+				set_SOGO(ctrl);
+
+				// Wait for SOBS to be unset
+				wait_for_ctrl_irq (ctrl);
+			}
+		}
+
+		p_slot->state = STATIC_STATE;
+	}
+
+	return;
+}
+
+
+int cpqhp_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;
+
+	if (!ctrl)
+		return(1);
+
+	tempdword = 0;
+
+	device = func->device;
+	hp_slot = device - ctrl->slot_device_offset;
+	p_slot = cpqhp_find_slot(ctrl, device);
+	if (p_slot) {
+		physical_slot = p_slot->number;
+	}
+
+	// Check to see if the interlock is closed
+	tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
+
+	if (tempdword & (0x01 << hp_slot)) {
+		return(1);
+	}
+
+	if (func->is_a_board) {
+		rc = board_replaced(func, ctrl);
+	} else {
+		// add board
+		slot_remove(func);
+
+		func = cpqhp_slot_create(ctrl->bus);
+		if (func == NULL) {
+			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;
+
+		if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) {
+			func->switch_save = 0;
+		} else {
+			func->switch_save = 0x10;
+		}
+
+		rc = board_added(func, ctrl);
+		if (rc) {
+			if (is_bridge(func)) {
+				bridge_slot_remove(func);
+			} else
+				slot_remove(func);
+
+			// Setup slot structure with entry for empty slot
+			func = cpqhp_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->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)) {
+				func->switch_save = 0;
+			} else {
+				func->switch_save = 0x10;
+			}
+		}
+	}
+
+	if (rc) {
+		dbg("%s: rc = %d\n", __FUNCTION__, rc);
+	}
+
+	if (p_slot)
+		update_slot_info(ctrl, p_slot);
+
+	return rc;
+}
+
+
+int cpqhp_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;
+	unsigned int devfn;
+	struct slot* p_slot;
+	struct pci_bus *pci_bus = ctrl->pci_bus;
+	int physical_slot=0;
+
+	device = func->device; 
+	func = cpqhp_slot_find(ctrl->bus, device, index++);
+	p_slot = cpqhp_find_slot(ctrl, device);
+	if (p_slot) {
+		physical_slot = p_slot->number;
+	}
+
+	// Make sure there are no video controllers here
+	while (func && !rc) {
+		pci_bus->number = func->bus;
+		devfn = PCI_DEVFN(func->device, func->function);
+
+		// Check the Class Code
+		rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
+		if (rc)
+			return rc;
+
+		if (class_code == PCI_BASE_CLASS_DISPLAY) {
+			/* Display/Video adapter (not supported) */
+			rc = REMOVE_NOT_SUPPORTED;
+		} else {
+			// See if it's a bridge
+			rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+			if (rc)
+				return rc;
+
+			// If it's a bridge, check the VGA Enable bit
+			if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+				rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);
+				if (rc)
+					return rc;
+
+				// If the VGA Enable bit is set, remove isn't supported
+				if (BCR & PCI_BRIDGE_CTL_VGA) {
+					rc = REMOVE_NOT_SUPPORTED;
+				}
+			}
+		}
+
+		func = cpqhp_slot_find(ctrl->bus, device, index++);
+	}
+
+	func = cpqhp_slot_find(ctrl->bus, device, 0);
+	if ((func != NULL) && !rc) {
+		//FIXME: Replace flag should be passed into process_SS
+		replace_flag = !(ctrl->add_support);
+		rc = remove_board(func, replace_flag, ctrl);
+	} else if (!rc) {
+		rc = 1;
+	}
+
+	if (p_slot)
+		update_slot_info(ctrl, p_slot);
+
+	return(rc);
+}
+
+
+
+/**
+ * hardware_test - runs hardware tests
+ *
+ * For hot plug ctrl folks to play with.
+ * test_num is the number entered in the GUI
+ *
+ */
+int cpqhp_hardware_test(struct controller *ctrl, int test_num)
+{
+	u32 save_LED;
+	u32 work_LED;
+	int loop;
+	int num_of_slots;
+
+	num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0f;
+
+	switch (test_num) {
+		case 1:
+			// Do stuff here!
+
+			// Do that funky LED thing
+			save_LED = readl(ctrl->hpc_reg + LED_CONTROL);	// so we can restore them later
+			work_LED = 0x01010101;
+			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+			for (loop = 0; loop < num_of_slots; loop++) {
+				set_SOGO(ctrl);
+
+				// Wait for SOGO interrupt
+				wait_for_ctrl_irq (ctrl);
+
+				// Get ready for next iteration
+				work_LED = work_LED << 1;
+				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+				long_delay((2*HZ)/10);
+			}
+			for (loop = 0; loop < num_of_slots; loop++) {
+				work_LED = work_LED >> 1;
+				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+				
+				set_SOGO(ctrl);
+
+				// Wait for SOGO interrupt
+				wait_for_ctrl_irq (ctrl);
+
+				// Get ready for next iteration
+				long_delay((2*HZ)/10);
+			}
+			for (loop = 0; loop < num_of_slots; loop++) {
+				work_LED = work_LED << 1;
+				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+				
+				set_SOGO(ctrl);
+
+				// Wait for SOGO interrupt
+				wait_for_ctrl_irq (ctrl);
+
+				// Get ready for next iteration
+				long_delay((2*HZ)/10);
+			}
+			for (loop = 0; loop < num_of_slots; loop++) {
+				work_LED = work_LED >> 1;
+				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+				
+				set_SOGO(ctrl);
+
+				// Wait for SOGO interrupt
+				wait_for_ctrl_irq (ctrl);
+
+				// Get ready for next iteration
+				long_delay((2*HZ)/10);
+			}
+
+			work_LED = 0x01010000;
+			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+			for (loop = 0; loop < num_of_slots; loop++) {
+				set_SOGO(ctrl);
+
+				// Wait for SOGO interrupt
+				wait_for_ctrl_irq (ctrl);
+
+				// Get ready for next iteration
+				work_LED = work_LED << 1;
+				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+				long_delay((2*HZ)/10);
+			}
+			for (loop = 0; loop < num_of_slots; loop++) {
+				work_LED = work_LED >> 1;
+				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+				
+				set_SOGO(ctrl);
+
+				// Wait for SOGO interrupt
+				wait_for_ctrl_irq (ctrl);
+
+				// Get ready for next iteration
+				long_delay((2*HZ)/10);
+			}
+			work_LED = 0x00000101;
+			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+			for (loop = 0; loop < num_of_slots; loop++) {
+				work_LED = work_LED << 1;
+				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+				
+				set_SOGO(ctrl);
+
+				// Wait for SOGO interrupt
+				wait_for_ctrl_irq (ctrl);
+
+				// Get ready for next iteration
+				long_delay((2*HZ)/10);
+			}
+			for (loop = 0; loop < num_of_slots; loop++) {
+				work_LED = work_LED >> 1;
+				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+				
+				set_SOGO(ctrl);
+
+				// Wait for SOGO interrupt
+				wait_for_ctrl_irq (ctrl);
+
+				// Get ready for next iteration
+				long_delay((2*HZ)/10);
+			}
+
+
+			work_LED = 0x01010000;
+			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+			for (loop = 0; loop < num_of_slots; loop++) {
+				set_SOGO(ctrl);
+
+				// Wait for SOGO interrupt
+				wait_for_ctrl_irq (ctrl);
+
+				// Get ready for next iteration
+				long_delay((3*HZ)/10);
+				work_LED = work_LED >> 16;
+				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+				
+				set_SOGO(ctrl);
+
+				// Wait for SOGO interrupt
+				wait_for_ctrl_irq (ctrl);
+
+				// Get ready for next iteration
+				long_delay((3*HZ)/10);
+				work_LED = work_LED << 16;
+				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+				work_LED = work_LED << 1;
+				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+			}
+
+			writel (save_LED, ctrl->hpc_reg + LED_CONTROL);	// put it back the way it was
+
+			set_SOGO(ctrl);
+
+			// Wait for SOBS to be unset
+			wait_for_ctrl_irq (ctrl);
+			break;
+		case 2:
+			// Do other stuff here!
+			break;
+		case 3:
+			// and more...
+			break;
+	}
+	return 0;
+}
+
+
+/**
+ * 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\n", __FUNCTION__);
+	// Check for Multi-function device
+	ctrl->pci_bus->number = func->bus;
+	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("configure_new_function failed %d\n",rc);
+			index = 0;
+
+			while (new_slot) {
+				new_slot = cpqhp_slot_find(new_slot->bus, new_slot->device, index++);
+
+				if (new_slot)
+					cpqhp_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 = cpqhp_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("returning from configure_new_device\n");
+
+	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;
+	unsigned int devfn;
+	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 pci_bus *pci_bus;
+	struct resource_lists temp_resources;
+
+	pci_bus = ctrl->pci_bus;
+	pci_bus->number = func->bus;
+	devfn = PCI_DEVFN(func->device, func->function);
+
+	// Check for Bridge
+	rc = pci_bus_read_config_byte (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("set Primary bus = %d\n", func->bus);
+		rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_PRIMARY_BUS, func->bus);
+		if (rc)
+			return rc;
+
+		// find range of busses to use
+		dbg("find ranges of buses to use\n");
+		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("set Secondary bus = %d\n", bus_node->base);
+		rc = pci_bus_write_config_byte (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("set subordinate bus = %d\n", bus_node->base + bus_node->length - 1);
+		rc = pci_bus_write_config_byte (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 (pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
+		if (rc)
+			return rc;
+		rc = pci_bus_write_config_byte (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 (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);
+		if (!io_node)
+			return -ENOMEM;
+		mem_node = get_max_resource(&(resources->mem_head), 0x100000);
+		if (!mem_node)
+			return -ENOMEM;
+		p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000);
+		if (!p_mem_node)
+			return -ENOMEM;
+		dbg("Setup the IO, memory, and prefetchable windows\n");
+		dbg("io_node\n");
+		dbg("(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next);
+		dbg("mem_node\n");
+		dbg("(base, len, next) (%x, %x, %p)\n", mem_node->base, mem_node->length, mem_node->next);
+		dbg("p_mem_node\n");
+		dbg("(base, len, next) (%x, %x, %p)\n", 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 (pci_bus, devfn, PCI_IO_BASE, temp_byte);
+
+			temp_byte = (io_node->base + io_node->length - 1) >> 8;
+			rc = pci_bus_write_config_byte (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;
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+
+			temp_word = (mem_node->base + mem_node->length - 1) >> 16;
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+		} else {
+			temp_word = 0xFFFF;
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+
+			temp_word = 0x0000;
+			rc = pci_bus_write_config_word (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;
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+
+			temp_word = (p_mem_node->base + p_mem_node->length - 1) >> 16;
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+		} else {
+			temp_word = 0xFFFF;
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+
+			temp_word = 0x0000;
+			rc = pci_bus_write_config_word (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->number = hold_bus_node->base;
+			pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), 0x00, &ID);
+			pci_bus->number = func->bus;
+
+			if (ID != 0xFFFFFFFF) {	  //  device Present
+				// Setup slot structure.
+				new_slot = cpqhp_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("configure_new_device rc=0x%x\n",rc);
+			}	// End of IF (device in slot?)
+		}		// End of FOR loop
+
+		if (rc) {
+			cpqhp_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 = cpqhp_set_irq(func->bus, func->device,
+							   0x0A + cloop, irqs.interrupt[cloop]);
+					if (rc) {
+						cpqhp_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
+			rc = pci_bus_write_config_byte (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;
+				rc = pci_bus_write_config_word (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;
+					rc = pci_bus_write_config_byte (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;
+					rc = pci_bus_write_config_word (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;
+				rc = pci_bus_write_config_word (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;
+					rc = pci_bus_write_config_word (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;
+					rc = pci_bus_write_config_word (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;
+				rc = pci_bus_write_config_word (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;
+					rc = pci_bus_write_config_word (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;
+					rc = pci_bus_write_config_word (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
+		rc = pci_bus_write_config_word (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
+		rc = pci_bus_write_config_word (pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
+	} else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
+		// Standard device
+		rc = pci_bus_read_config_byte (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("CND: bus=%d, devfn=%d, offset=%d\n", pci_bus->number, devfn, cloop);
+			rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
+
+			rc = pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp_register);
+			dbg("CND: base = 0x%x\n", 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("CND:      length = 0x%x\n", base);
+					io_node = get_io_resource(&(resources->io_head), base);
+					dbg("Got io_node start = %8.8x, length = %8.8x next (%p)\n",
+					    io_node->base, io_node->length, io_node->next);
+					dbg("func (%p) io_head (%p)\n", 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("CND:      length = 0x%x\n", 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("CND:      length = 0x%x\n", 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("CND:      length = 0x%x\n", 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);
+				}
+
+				rc = pci_bus_write_config_dword (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;
+					rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, base);
+				}
+			}
+		}		// End of base register loop
+
+		// Figure out which interrupt pin this function uses
+		rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_INTERRUPT_PIN, &temp_byte);
+
+		// If this function needs an interrupt and we are behind a bridge
+		// and the pin is tied to something that's alread 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];
+		} else {
+			// Program IRQ based on card type
+			rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
+
+			if (class_code == PCI_BASE_CLASS_STORAGE) {
+				IRQ = cpqhp_disk_irq;
+			} else {
+				IRQ = cpqhp_nic_irq;
+			}
+		}
+
+		// IRQ Line
+		rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ);
+
+		if (!behind_bridge) {
+			rc = cpqhp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ);
+			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;
+		rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
+
+		// Cache Line size
+		temp_byte = 0x08;
+		rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
+
+		// disable ROM base Address
+		temp_dword = 0x00L;
+		rc = pci_bus_write_config_word (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
+		rc = pci_bus_write_config_word (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;
+}
+
diff -Nru a/drivers/pci/hotplug/cpqphp_nvram.c b/drivers/pci/hotplug/cpqphp_nvram.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/cpqphp_nvram.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,667 @@
+/*
+ * Compaq Hot Plug Controller Driver
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include "cpqphp.h"
+#include "cpqphp_nvram.h"
+
+
+#define ROM_INT15_PHY_ADDR		0x0FF859
+#define READ_EV				0xD8A4
+#define WRITE_EV			0xD8A5
+
+struct register_foo {
+	union {
+		unsigned long lword;		/* eax */
+		unsigned short word;		/* ax */
+
+		struct {
+			unsigned char low;	/* al */
+			unsigned char high;	/* ah */
+		} byte;
+	} data;
+
+	unsigned char opcode;	/* see below */
+	unsigned long length;	/* if the reg. is a pointer, how much data */
+} __attribute__ ((packed));
+
+struct all_reg {
+	struct register_foo eax_reg;
+	struct register_foo ebx_reg;
+	struct register_foo ecx_reg;
+	struct register_foo edx_reg;
+	struct register_foo edi_reg;
+	struct register_foo esi_reg;
+	struct register_foo eflags_reg;
+} __attribute__ ((packed));
+
+
+struct ev_hrt_header {
+	u8 Version;
+	u8 num_of_ctrl;
+	u8 next;
+};
+
+struct ev_hrt_ctrl {
+	u8 bus;
+	u8 device;
+	u8 function;
+	u8 mem_avail;
+	u8 p_mem_avail;
+	u8 io_avail;
+	u8 bus_avail;
+	u8 next;
+};
+
+
+static u8 evbuffer_init;
+static u8 evbuffer_length;
+static u8 evbuffer[1024];
+
+static void *compaq_int15_entry_point;
+
+static spinlock_t int15_lock;		/* lock for ordering int15_bios_call() */
+
+
+/* This is a series of function that deals with
+   setting & getting the hotplug resource table in some environment variable.
+*/
+
+/*
+ * We really shouldn't be doing this unless there is a _very_ good reason to!!!
+ * greg k-h
+ */
+
+
+static u32 add_byte( u32 **p_buffer, u8 value, u32 *used, u32 *avail)
+{
+	u8 **tByte;
+
+	if ((*used + 1) > *avail)
+		return(1);
+	
+	*((u8*)*p_buffer) = value;
+	tByte = (u8**)p_buffer;
+	(*tByte)++;
+	*used+=1;
+	return(0);
+}
+
+
+static u32 add_dword( u32 **p_buffer, u32 value, u32 *used, u32 *avail)
+{
+	if ((*used + 4) > *avail)
+		return(1);
+
+	**p_buffer = value;
+	(*p_buffer)++;
+	*used+=4;
+	return(0);
+}
+
+
+/*
+ * check_for_compaq_ROM
+ *
+ * this routine verifies that the ROM OEM string is 'COMPAQ'
+ *
+ * returns 0 for non-Compaq ROM, 1 for Compaq ROM
+ */
+static int check_for_compaq_ROM (void *rom_start)
+{
+	u8 temp1, temp2, temp3, temp4, temp5, temp6;
+	int result = 0;
+
+	temp1 = readb(rom_start + 0xffea + 0);
+	temp2 = readb(rom_start + 0xffea + 1);
+	temp3 = readb(rom_start + 0xffea + 2);
+	temp4 = readb(rom_start + 0xffea + 3);
+	temp5 = readb(rom_start + 0xffea + 4);
+	temp6 = readb(rom_start + 0xffea + 5);
+	if ((temp1 == 'C') &&
+	    (temp2 == 'O') &&
+	    (temp3 == 'M') &&
+	    (temp4 == 'P') &&
+	    (temp5 == 'A') &&
+	    (temp6 == 'Q')) {
+		result = 1;
+	}
+	dbg ("%s - returned %d\n", __FUNCTION__, result);
+	return result;
+}
+
+
+static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)
+{
+	unsigned long flags;
+	int op = operation;
+	int ret_val;
+	
+	if (!compaq_int15_entry_point)
+		return -ENODEV;
+	
+	spin_lock_irqsave(&int15_lock, flags);
+	__asm__ (
+		"xorl   %%ebx,%%ebx\n" \
+		"xorl    %%edx,%%edx\n" \
+		"pushf\n" \
+		"push %%cs\n" \
+		"cli\n" \
+		"call *%6\n"
+		: "=c" (*buf_size), "=a" (ret_val)
+		: "a" (op), "c" (*buf_size), "S" (ev_name),
+		"D" (buffer), "m" (compaq_int15_entry_point)
+		: "%ebx", "%edx");
+	spin_unlock_irqrestore(&int15_lock, flags);
+	
+	return((ret_val & 0xFF00) >> 8);
+}
+
+
+/*
+ * load_HRT
+ *
+ * Read the hot plug Resource Table from NVRAM
+ */
+static int load_HRT (void *rom_start)
+{
+	u32 available;
+	u32 temp_dword;
+	u8 temp_byte = 0xFF;
+	u32 rc;
+
+	if (!check_for_compaq_ROM(rom_start)) {
+		return -ENODEV;
+	}
+
+	available = 1024;
+
+	// Now load the EV
+	temp_dword = available;
+
+	rc = access_EV(READ_EV, "CQTHPS", evbuffer, &temp_dword);
+
+	evbuffer_length = temp_dword;
+
+	// We're maintaining the resource lists so write FF to invalidate old info
+	temp_dword = 1;
+
+	rc = access_EV(WRITE_EV, "CQTHPS", &temp_byte, &temp_dword);
+
+	return rc;
+}
+
+
+/*
+ * store_HRT
+ *
+ * Save the hot plug Resource Table in NVRAM
+ */
+static u32 store_HRT (void *rom_start)
+{
+	u32 *buffer;
+	u32 *pFill;
+	u32 usedbytes;
+	u32 available;
+	u32 temp_dword;
+	u32 rc;
+	u8 loop;
+	u8 numCtrl = 0;
+	struct controller *ctrl;
+	struct pci_resource *resNode;
+	struct ev_hrt_header *p_EV_header;
+	struct ev_hrt_ctrl *p_ev_ctrl;
+
+	available = 1024;
+
+	if (!check_for_compaq_ROM(rom_start)) {
+		return(1);
+	}
+
+	buffer = (u32*) evbuffer;
+
+	if (!buffer)
+		return(1);
+
+	pFill = buffer;
+	usedbytes = 0;
+
+	p_EV_header = (struct ev_hrt_header *) pFill;
+
+	ctrl = cpqhp_ctrl_list;
+	
+	// The revision of this structure
+	rc = add_byte( &pFill, 1 + ctrl->push_flag, &usedbytes, &available);
+	if (rc)
+		return(rc);
+
+	// The number of controllers
+	rc = add_byte( &pFill, 1, &usedbytes, &available);
+	if (rc)
+		return(rc);
+
+	while (ctrl) {
+		p_ev_ctrl = (struct ev_hrt_ctrl *) pFill;
+
+		numCtrl++;
+
+		// The bus number
+		rc = add_byte( &pFill, ctrl->bus, &usedbytes, &available);
+		if (rc)
+			return(rc);
+
+		// The device Number
+		rc = add_byte( &pFill, PCI_SLOT(ctrl->pci_dev->devfn), &usedbytes, &available);
+		if (rc)
+			return(rc);
+
+		// The function Number
+		rc = add_byte( &pFill, PCI_FUNC(ctrl->pci_dev->devfn), &usedbytes, &available);
+		if (rc)
+			return(rc);
+
+		// Skip the number of available entries
+		rc = add_dword( &pFill, 0, &usedbytes, &available);
+		if (rc)
+			return(rc);
+
+		// Figure out memory Available
+
+		resNode = ctrl->mem_head;
+
+		loop = 0;
+
+		while (resNode) {
+			loop ++;
+
+			// base
+			rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
+			if (rc)
+				return(rc);
+
+			// length
+			rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
+			if (rc)
+				return(rc);
+
+			resNode = resNode->next;
+		}
+
+		// Fill in the number of entries
+		p_ev_ctrl->mem_avail = loop;
+
+		// Figure out prefetchable memory Available
+
+		resNode = ctrl->p_mem_head;
+
+		loop = 0;
+
+		while (resNode) {
+			loop ++;
+
+			// base
+			rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
+			if (rc)
+				return(rc);
+
+			// length
+			rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
+			if (rc)
+				return(rc);
+
+			resNode = resNode->next;
+		}
+
+		// Fill in the number of entries
+		p_ev_ctrl->p_mem_avail = loop;
+
+		// Figure out IO Available
+
+		resNode = ctrl->io_head;
+
+		loop = 0;
+
+		while (resNode) {
+			loop ++;
+
+			// base
+			rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
+			if (rc)
+				return(rc);
+
+			// length
+			rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
+			if (rc)
+				return(rc);
+
+			resNode = resNode->next;
+		}
+
+		// Fill in the number of entries
+		p_ev_ctrl->io_avail = loop;
+
+		// Figure out bus Available
+
+		resNode = ctrl->bus_head;
+
+		loop = 0;
+
+		while (resNode) {
+			loop ++;
+
+			// base
+			rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
+			if (rc)
+				return(rc);
+
+			// length
+			rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
+			if (rc)
+				return(rc);
+
+			resNode = resNode->next;
+		}
+
+		// Fill in the number of entries
+		p_ev_ctrl->bus_avail = loop;
+
+		ctrl = ctrl->next;
+	}
+	
+	p_EV_header->num_of_ctrl = numCtrl;
+
+	// Now store the EV
+
+	temp_dword = usedbytes;
+
+	rc = access_EV(WRITE_EV, "CQTHPS", (u8*) buffer, &temp_dword);
+
+	dbg("usedbytes = 0x%x, length = 0x%x\n", usedbytes, temp_dword);
+
+	evbuffer_length = temp_dword;
+
+	if (rc) {
+		err(msg_unable_to_save);
+		return(1);
+	}
+
+	return(0);
+}
+
+
+void compaq_nvram_init (void *rom_start)
+{
+	if (rom_start) {
+		compaq_int15_entry_point = (rom_start + ROM_INT15_PHY_ADDR - ROM_PHY_ADDR);
+	}
+	dbg("int15 entry  = %p\n", compaq_int15_entry_point);
+
+	/* initialize our int15 lock */
+	spin_lock_init(&int15_lock);
+}
+
+
+int compaq_nvram_load (void *rom_start, struct controller *ctrl)
+{
+	u8 bus, device, function;
+	u8 nummem, numpmem, numio, numbus;
+	u32 rc;
+	u8 *p_byte;
+	struct pci_resource *mem_node;
+	struct pci_resource *p_mem_node;
+	struct pci_resource *io_node;
+	struct pci_resource *bus_node;
+	struct ev_hrt_ctrl *p_ev_ctrl;
+	struct ev_hrt_header *p_EV_header;
+
+	if (!evbuffer_init) {
+		// Read the resource list information in from NVRAM
+		if (load_HRT(rom_start))
+			memset (evbuffer, 0, 1024);
+
+		evbuffer_init = 1;
+	}
+
+	// If we saved information in NVRAM, use it now
+	p_EV_header = (struct ev_hrt_header *) evbuffer;
+
+	// The following code is for systems where version 1.0 of this
+	// driver has been loaded, but doesn't support the hardware.
+	// In that case, the driver would incorrectly store something
+	// in NVRAM.
+	if ((p_EV_header->Version == 2) ||
+	    ((p_EV_header->Version == 1) && !ctrl->push_flag)) {
+		p_byte = &(p_EV_header->next);
+
+		p_ev_ctrl = (struct ev_hrt_ctrl *) &(p_EV_header->next);
+
+		p_byte += 3;
+
+		if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+			return 2;
+
+		bus = p_ev_ctrl->bus;
+		device = p_ev_ctrl->device;
+		function = p_ev_ctrl->function;
+
+		while ((bus != ctrl->bus) ||
+		       (device != PCI_SLOT(ctrl->pci_dev->devfn)) || 
+		       (function != PCI_FUNC(ctrl->pci_dev->devfn))) {
+			nummem = p_ev_ctrl->mem_avail;
+			numpmem = p_ev_ctrl->p_mem_avail;
+			numio = p_ev_ctrl->io_avail;
+			numbus = p_ev_ctrl->bus_avail;
+
+			p_byte += 4;
+
+			if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+				return 2;
+
+			// Skip forward to the next entry
+			p_byte += (nummem + numpmem + numio + numbus) * 8;
+
+			if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+				return 2;
+
+			p_ev_ctrl = (struct ev_hrt_ctrl *) p_byte;
+
+			p_byte += 3;
+
+			if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+				return 2;
+
+			bus = p_ev_ctrl->bus;
+			device = p_ev_ctrl->device;
+			function = p_ev_ctrl->function;
+		}
+
+		nummem = p_ev_ctrl->mem_avail;
+		numpmem = p_ev_ctrl->p_mem_avail;
+		numio = p_ev_ctrl->io_avail;
+		numbus = p_ev_ctrl->bus_avail;
+
+		p_byte += 4;
+
+		if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+			return 2;
+
+		while (nummem--) {
+			mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!mem_node)
+				break;
+
+			mem_node->base = *(u32*)p_byte;
+			dbg("mem base = %8.8x\n",mem_node->base);
+			p_byte += 4;
+
+			if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
+				kfree(mem_node);
+				return 2;
+			}
+
+			mem_node->length = *(u32*)p_byte;
+			dbg("mem length = %8.8x\n",mem_node->length);
+			p_byte += 4;
+
+			if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
+				kfree(mem_node);
+				return 2;
+			}
+
+			mem_node->next = ctrl->mem_head;
+			ctrl->mem_head = mem_node;
+		}
+
+		while (numpmem--) {
+			p_mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!p_mem_node)
+				break;
+
+			p_mem_node->base = *(u32*)p_byte;
+			dbg("pre-mem base = %8.8x\n",p_mem_node->base);
+			p_byte += 4;
+
+			if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
+				kfree(p_mem_node);
+				return 2;
+			}
+
+			p_mem_node->length = *(u32*)p_byte;
+			dbg("pre-mem length = %8.8x\n",p_mem_node->length);
+			p_byte += 4;
+
+			if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
+				kfree(p_mem_node);
+				return 2;
+			}
+
+			p_mem_node->next = ctrl->p_mem_head;
+			ctrl->p_mem_head = p_mem_node;
+		}
+
+		while (numio--) {
+			io_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!io_node)
+				break;
+
+			io_node->base = *(u32*)p_byte;
+			dbg("io base = %8.8x\n",io_node->base);
+			p_byte += 4;
+
+			if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
+				kfree(io_node);
+				return 2;
+			}
+
+			io_node->length = *(u32*)p_byte;
+			dbg("io length = %8.8x\n",io_node->length);
+			p_byte += 4;
+
+			if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
+				kfree(io_node);
+				return 2;
+			}
+
+			io_node->next = ctrl->io_head;
+			ctrl->io_head = io_node;
+		}
+
+		while (numbus--) {
+			bus_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!bus_node)
+				break;
+
+			bus_node->base = *(u32*)p_byte;
+			p_byte += 4;
+
+			if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
+				kfree(bus_node);
+				return 2;
+			}
+
+			bus_node->length = *(u32*)p_byte;
+			p_byte += 4;
+
+			if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
+				kfree(bus_node);
+				return 2;
+			}
+
+			bus_node->next = ctrl->bus_head;
+			ctrl->bus_head = bus_node;
+		}
+
+		// If all of the following fail, we don't have any resources for
+		// hot plug add
+		rc = 1;
+		rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
+		rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
+		rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head));
+		rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
+
+		if (rc)
+			return(rc);
+	} else {
+		if ((evbuffer[0] != 0) && (!ctrl->push_flag)) 
+			return 1;
+	}
+
+	return 0;
+}
+
+	
+int compaq_nvram_store (void *rom_start)
+{
+	int rc = 1;
+
+	if (rom_start == NULL)
+		return -ENODEV;
+
+	if (evbuffer_init) {
+		rc = store_HRT(rom_start);
+		if (rc) {
+			err(msg_unable_to_save);
+		}
+	}
+	return rc;
+}
+
diff -Nru a/drivers/pci/hotplug/cpqphp_nvram.h b/drivers/pci/hotplug/cpqphp_nvram.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/cpqphp_nvram.h	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,57 @@
+/*
+ * Compaq Hot Plug Controller Driver
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>
+ *
+ */
+
+#ifndef _CPQPHP_NVRAM_H
+#define _CPQPHP_NVRAM_H
+
+#ifndef CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM
+
+static inline void compaq_nvram_init (void *rom_start)
+{
+	return;
+}
+
+static inline int compaq_nvram_load (void *rom_start, struct controller *ctrl)
+{
+	return 0;
+}
+
+static inline int compaq_nvram_store (void *rom_start)
+{
+	return 0;
+}
+
+#else
+
+extern void compaq_nvram_init	(void *rom_start);
+extern int compaq_nvram_load	(void *rom_start, struct controller *ctrl);
+extern int compaq_nvram_store	(void *rom_start);
+
+#endif
+
+#endif
+
diff -Nru a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/cpqphp_pci.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,1548 @@
+/*
+ * Compaq Hot Plug Controller Driver
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/proc_fs.h>
+#include <linux/pci.h>
+#include "cpqphp.h"
+#include "cpqphp_nvram.h"
+#include "../../../arch/i386/pci/pci.h"	/* horrible hack showing how processor dependent we are... */
+
+
+u8 cpqhp_nic_irq;
+u8 cpqhp_disk_irq;
+
+static u16 unused_IRQ;
+
+/*
+ * detect_HRT_floating_pointer
+ *
+ * find the Hot Plug Resource Table in the specified region of memory.
+ *
+ */
+static void *detect_HRT_floating_pointer(void *begin, void *end)
+{
+	void *fp;
+	void *endp;
+	u8 temp1, temp2, temp3, temp4;
+	int status = 0;
+
+	endp = (end - sizeof(struct hrt) + 1);
+
+	for (fp = begin; fp <= endp; fp += 16) {
+		temp1 = readb(fp + SIG0);
+		temp2 = readb(fp + SIG1);
+		temp3 = readb(fp + SIG2);
+		temp4 = readb(fp + SIG3);
+		if (temp1 == '$' &&
+		    temp2 == 'H' &&
+		    temp3 == 'R' &&
+		    temp4 == 'T') {
+			status = 1;
+			break;
+		}
+	}
+
+	if (!status)
+		fp = NULL;
+
+	dbg("Discovered Hotplug Resource Table at %p\n", fp);
+	return fp;
+}
+
+
+int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)  
+{
+	unsigned char bus;
+	struct pci_bus *child;
+	int num;
+
+	if (func->pci_dev == NULL)
+		func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
+
+	/* No pci device, we need to create it then */
+	if (func->pci_dev == NULL) {
+		dbg("INFO: pci_dev still null\n");
+
+		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 cpqhp_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_bus *bus, unsigned int devfn, u8 offset, u32 *value)
+{
+	u32 vendID = 0;
+
+	if (pci_bus_read_config_dword (bus, devfn, PCI_VENDOR_ID, &vendID) == -1)
+		return -1;
+	if (vendID == 0xffffffff)
+		return -1;
+	return pci_bus_read_config_dword (bus, devfn, offset, value);
+}
+
+
+/*
+ * cpqhp_set_irq
+ *
+ * @bus_num: bus number of PCI device
+ * @dev_num: device number of PCI device
+ * @slot: pointer to u8 where slot number will be returned
+ */
+int cpqhp_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;
+}
+
+
+/*
+ * 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;
+
+	ctrl->pci_bus->number = bus_num;
+
+	for (tdevice = 0; tdevice < 0x100; tdevice++) {
+		//Scan for access first
+		if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
+			continue;
+		dbg("Looking for nonbridge bus_num %d dev_num %d\n", bus_num, tdevice);
+		//Yep we got one. Not a bridge ?
+		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_bus, tdevice, 0x08, &work) == -1)
+			continue;
+		dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice);
+		//Yep we got one. bridge ?
+		if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
+			pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(tdevice, 0), PCI_SECONDARY_BUS, &tbus);
+			dbg("Recurse on bus_num %d tdevice %d\n", tbus, tdevice);
+			if (PCI_ScanBusNonBridge(tbus, tdevice) == 0)
+				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();
+	if (!PCIIRQRoutingInfoLength)
+		return -1;
+
+	len = (PCIIRQRoutingInfoLength->size -
+	       sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
+	// Make sure I got at least one entry
+	if (len == 0) {
+		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;
+
+		if (tslot == slot) {
+			*bus_num = tbus;
+			*dev_num = tdevice;
+			ctrl->pci_bus->number = tbus;
+			pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_VENDOR_ID, &work);
+			if (!nobridge || (work == 0xffffffff)) {
+				if (PCIIRQRoutingInfoLength != NULL)
+					kfree(PCIIRQRoutingInfoLength );
+				return 0;
+			}
+
+			dbg("bus_num %d devfn %d\n", *bus_num, *dev_num);
+			pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_CLASS_REVISION, &work);
+			dbg("work >> 8 (%x) = BRIDGE (%x)\n", work >> 8, PCI_TO_PCI_BRIDGE_CLASS);
+
+			if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
+				pci_bus_read_config_byte (ctrl->pci_bus, *dev_num, PCI_SECONDARY_BUS, &tbus);
+				dbg("Scan bus for Non Bridge: bus %d\n", tbus);
+				if (PCI_ScanBusForNonBridge(ctrl, tbus, dev_num) == 0) {
+					*bus_num = tbus;
+					if (PCIIRQRoutingInfoLength != NULL)
+						kfree(PCIIRQRoutingInfoLength );
+					return 0;
+				}
+			} else {
+				if (PCIIRQRoutingInfoLength != NULL)
+					kfree(PCIIRQRoutingInfoLength );
+				return 0;
+			}
+
+		}
+	}
+	if (PCIIRQRoutingInfoLength != NULL)
+		kfree(PCIIRQRoutingInfoLength );
+	return -1;
+}
+
+
+int cpqhp_get_bus_dev (struct controller *ctrl, u8 * bus_num, u8 * dev_num, u8 slot)
+{
+	return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0);	//plain (bridges allowed)
+}
+
+
+/* More PCI configuration routines; this time centered around hotplug controller */
+
+
+/*
+ * cpqhp_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 cpqhp_save_config(struct controller *ctrl, int busnumber, int 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) {
+		//*********************************
+		// is_hot_plug is the slot mask
+		//*********************************
+		FirstSupported = is_hot_plug >> 4;
+		LastSupported = FirstSupported + (is_hot_plug & 0x0F) - 1;
+	} else {
+		FirstSupported = 0;
+		LastSupported = 0x1F;
+	}
+
+	//     Save PCI configuration space for all devices in supported slots
+	ctrl->pci_bus->number = busnumber;
+	for (device = FirstSupported; device <= LastSupported; device++) {
+		ID = 0xFFFFFFFF;
+		rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
+
+		if (ID != 0xFFFFFFFF) {	  //  device in slot
+			rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code);
+			if (rc)
+				return rc;
+
+			rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type);
+			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 = cpqhp_save_config(ctrl, sub_bus, 0);
+						if (rc)
+							return rc;
+						ctrl->pci_bus->number = busnumber;
+					}
+				}
+
+				index = 0;
+				new_slot = cpqhp_slot_find(busnumber, device, index++);
+				while (new_slot && 
+				       (new_slot->function != (u8) function))
+					new_slot = cpqhp_slot_find(busnumber, device, index++);
+
+				if (!new_slot) {
+					// Setup slot structure.
+					new_slot = cpqhp_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);
+
+				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 = cpqhp_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;
+		}
+	}			// End of FOR loop
+
+	return(0);
+}
+
+
+/*
+ * cpqhp_save_slot_config
+ *
+ * Saves configuration info for all PCI devices in a given slot
+ * including subordinate busses.
+ *
+ * returns 0 if success
+ */
+int cpqhp_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;
+
+	ctrl->pci_bus->number = new_slot->bus;
+	pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID);
+
+	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 = cpqhp_save_config(ctrl, sub_bus, 0);
+				if (rc)
+					return(rc);
+				ctrl->pci_bus->number = new_slot->bus;
+
+			}	// 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);
+}
+
+
+/*
+ * cpqhp_save_base_addr_length
+ *
+ * Saves the length of all base address registers for the
+ * specified slot.  this is for hot plug REPLACE
+ *
+ * returns 0 if success
+ */
+int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func)
+{
+	u8 cloop;
+	u8 header_type;
+	u8 secondary_bus;
+	u8 type;
+	int sub_bus;
+	u32 temp_register;
+	u32 base;
+	u32 rc;
+	struct pci_func *next;
+	int index = 0;
+	struct pci_bus *pci_bus = ctrl->pci_bus;
+	unsigned int devfn;
+
+	func = cpqhp_slot_find(func->bus, func->device, index++);
+
+	while (func != NULL) {
+		pci_bus->number = func->bus;
+		devfn = PCI_DEVFN(func->device, func->function);
+
+		// Check for Bridge
+		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+
+		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+			// PCI-PCI Bridge
+			pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
+
+			sub_bus = (int) secondary_bus;
+
+			next = cpqhp_slot_list[sub_bus];
+
+			while (next != NULL) {
+				rc = cpqhp_save_base_addr_length(ctrl, next);
+
+				if (rc)
+					return(rc);
+
+				next = next->next;
+			}
+			pci_bus->number = func->bus;
+
+			//FIXME: this loop is duplicated in the non-bridge case.  The two could be rolled together
+			// Figure out IO and memory base lengths
+			for (cloop = 0x10; cloop <= 0x14; cloop += 4) {
+				temp_register = 0xFFFFFFFF;
+				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
+				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
+
+				if (base) {  // If this register is implemented
+					if (base & 0x01L) {
+						// IO base
+						// set base = amount of IO space requested
+						base = base & 0xFFFFFFFE;
+						base = (~base) + 1;
+
+						type = 1;
+					} else {
+						// memory base
+						base = base & 0xFFFFFFF0;
+						base = (~base) + 1;
+
+						type = 0;
+					}
+				} else {
+					base = 0x0L;
+					type = 0;
+				}
+
+				// Save information in slot structure
+				func->base_length[(cloop - 0x10) >> 2] =
+				base;
+				func->base_type[(cloop - 0x10) >> 2] = type;
+
+			}	// End of base register loop
+
+
+		} else if ((header_type & 0x7F) == 0x00) {	  // PCI-PCI Bridge
+			// Figure out IO and memory base lengths
+			for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
+				temp_register = 0xFFFFFFFF;
+				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
+				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
+
+				if (base) {  // If this register is implemented
+					if (base & 0x01L) {
+						// IO base
+						// base = amount of IO space requested
+						base = base & 0xFFFFFFFE;
+						base = (~base) + 1;
+
+						type = 1;
+					} else {
+						// memory base
+						// base = amount of memory space requested
+						base = base & 0xFFFFFFF0;
+						base = (~base) + 1;
+
+						type = 0;
+					}
+				} else {
+					base = 0x0L;
+					type = 0;
+				}
+
+				// Save information in slot structure
+				func->base_length[(cloop - 0x10) >> 2] = base;
+				func->base_type[(cloop - 0x10) >> 2] = type;
+
+			}	// End of base register loop
+
+		} else {	  // Some other unknown header type
+		}
+
+		// find the next device in this slot
+		func = cpqhp_slot_find(func->bus, func->device, index++);
+	}
+
+	return(0);
+}
+
+
+/*
+ * cpqhp_save_used_resources
+ *
+ * Stores used resource information for existing boards.  this is
+ * for boards that were in the system when this driver was loaded.
+ * this function is for hot plug ADD
+ *
+ * returns 0 if success
+ */
+int cpqhp_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;
+	struct pci_bus *pci_bus = ctrl->pci_bus;
+	unsigned int devfn;
+
+	func = cpqhp_slot_find(func->bus, func->device, index++);
+
+	while ((func != NULL) && func->is_a_board) {
+		pci_bus->number = func->bus;
+		devfn = PCI_DEVFN(func->device, func->function);
+
+		// Save the command register
+		pci_bus_read_config_word (pci_bus, devfn, PCI_COMMAND, &save_command);
+
+		// disable card
+		command = 0x00;
+		pci_bus_write_config_word (pci_bus, devfn, PCI_COMMAND, command);
+
+		// Check for Bridge
+		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+
+		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  // PCI-PCI Bridge
+			// Clear Bridge Control Register
+			command = 0x00;
+			pci_bus_write_config_word (pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
+			pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
+			pci_bus_read_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);
+
+			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 (pci_bus, devfn, PCI_IO_BASE, &b_base);
+			pci_bus_read_config_byte (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 (pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
+			pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
+
+			if ((w_base <= w_length) && (save_command & 0x02)) {
+				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 (pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
+			pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
+
+			if ((w_base <= w_length) && (save_command & 0x02)) {
+				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 (pci_bus, devfn, cloop, &save_base);
+
+				temp_register = 0xFFFFFFFF;
+				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
+				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
+
+				temp_register = base;
+
+				if (base) {  // If this register is implemented
+					if (((base & 0x03L) == 0x01)
+					    && (save_command & 0x01)) {
+						// IO base
+						// set temp_register = amount of IO space requested
+						temp_register = base & 0xFFFFFFFE;
+						temp_register = (~temp_register) + 1;
+
+						io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+						if (!io_node)
+							return -ENOMEM;
+
+						io_node->base =
+						save_base & (~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 (pci_bus, devfn, cloop, &save_base);
+
+				temp_register = 0xFFFFFFFF;
+				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
+				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
+
+				temp_register = base;
+
+				if (base) {	  // If this register is implemented
+					if (((base & 0x03L) == 0x01)
+					    && (save_command & 0x01)) {
+						// IO base
+						// set temp_register = amount of IO space requested
+						temp_register = base & 0xFFFFFFFE;
+						temp_register = (~temp_register) + 1;
+
+						io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+						if (!io_node)
+							return -ENOMEM;
+
+						io_node->base = save_base & (~0x01L);
+						io_node->length = temp_register;
+
+						io_node->next = func->io_head;
+						func->io_head = io_node;
+					} else
+						if (((base & 0x0BL) == 0x08)
+						    && (save_command & 0x02)) {
+						// prefetchable memory base
+						temp_register = base & 0xFFFFFFF0;
+						temp_register = (~temp_register) + 1;
+
+						p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+						if (!p_mem_node)
+							return -ENOMEM;
+
+						p_mem_node->base = save_base & (~0x0FL);
+						p_mem_node->length = temp_register;
+
+						p_mem_node->next = func->p_mem_head;
+						func->p_mem_head = p_mem_node;
+					} else
+						if (((base & 0x0BL) == 0x00)
+						    && (save_command & 0x02)) {
+						// prefetchable memory base
+						temp_register = base & 0xFFFFFFF0;
+						temp_register = (~temp_register) + 1;
+
+						mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+						if (!mem_node)
+							return -ENOMEM;
+
+						mem_node->base = save_base & (~0x0FL);
+						mem_node->length = temp_register;
+
+						mem_node->next = func->mem_head;
+						func->mem_head = mem_node;
+					} else
+						return(1);
+				}
+			}	// End of base register loop
+		} else {	  // Some other unknown header type
+		}
+
+		// find the next device in this slot
+		func = cpqhp_slot_find(func->bus, func->device, index++);
+	}
+
+	return(0);
+}
+
+
+/*
+ * cpqhp_configure_board
+ *
+ * Copies saved configuration information to one slot.
+ * this is called recursively for bridge devices.
+ * this is for hot plug REPLACE!
+ *
+ * returns 0 if success
+ */
+int cpqhp_configure_board(struct controller *ctrl, struct pci_func * func)
+{
+	int cloop;
+	u8 header_type;
+	u8 secondary_bus;
+	int sub_bus;
+	struct pci_func *next;
+	u32 temp;
+	u32 rc;
+	int index = 0;
+	struct pci_bus *pci_bus = ctrl->pci_bus;
+	unsigned int devfn;
+
+	func = cpqhp_slot_find(func->bus, func->device, index++);
+
+	while (func != NULL) {
+		pci_bus->number = func->bus;
+		devfn = PCI_DEVFN(func->device, func->function);
+
+		// Start at the top of config space so that the control
+		// registers are programmed last
+		for (cloop = 0x3C; cloop > 0; cloop -= 4) {
+			pci_bus_write_config_dword (pci_bus, devfn, cloop, func->config_space[cloop >> 2]);
+		}
+
+		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+
+		// If this is a bridge device, restore subordinate devices
+		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  // PCI-PCI Bridge
+			pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
+
+			sub_bus = (int) secondary_bus;
+
+			next = cpqhp_slot_list[sub_bus];
+
+			while (next != NULL) {
+				rc = cpqhp_configure_board(ctrl, next);
+
+				if (rc)
+					return rc;
+
+				next = next->next;
+			}
+		} else {
+
+			// Check all the base Address Registers to make sure
+			// they are the same.  If not, the board is different.
+
+			for (cloop = 16; cloop < 40; cloop += 4) {
+				pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp);
+
+				if (temp != func->config_space[cloop >> 2]) {
+					dbg("Config space compare failure!!! offset = %x\n", cloop);
+					dbg("bus = %x, device = %x, function = %x\n", func->bus, func->device, func->function);
+					dbg("temp = %x, config space = %x\n\n", temp, func->config_space[cloop >> 2]);
+					return 1;
+				}
+			}
+		}
+
+		func->configured = 1;
+
+		func = cpqhp_slot_find(func->bus, func->device, index++);
+	}
+
+	return 0;
+}
+
+
+/*
+ * cpqhp_valid_replace
+ *
+ * this function checks to see if a board is the same as the
+ * one it is replacing.  this check will detect if the device's
+ * vendor or device id's are the same
+ *
+ * returns 0 if the board is the same nonzero otherwise
+ */
+int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func)
+{
+	u8 cloop;
+	u8 header_type;
+	u8 secondary_bus;
+	u8 type;
+	u32 temp_register = 0;
+	u32 base;
+	u32 rc;
+	struct pci_func *next;
+	int index = 0;
+	struct pci_bus *pci_bus = ctrl->pci_bus;
+	unsigned int devfn;
+
+	if (!func->is_a_board)
+		return(ADD_NOT_SUPPORTED);
+
+	func = cpqhp_slot_find(func->bus, func->device, index++);
+
+	while (func != NULL) {
+		pci_bus->number = func->bus;
+		devfn = PCI_DEVFN(func->device, func->function);
+
+		pci_bus_read_config_dword (pci_bus, devfn, PCI_VENDOR_ID, &temp_register);
+
+		// No adapter present
+		if (temp_register == 0xFFFFFFFF)
+			return(NO_ADAPTER_PRESENT);
+
+		if (temp_register != func->config_space[0])
+			return(ADAPTER_NOT_SAME);
+
+		// Check for same revision number and class code
+		pci_bus_read_config_dword (pci_bus, devfn, PCI_CLASS_REVISION, &temp_register);
+
+		// Adapter not the same
+		if (temp_register != func->config_space[0x08 >> 2])
+			return(ADAPTER_NOT_SAME);
+
+		// Check for Bridge
+		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+
+		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  // PCI-PCI Bridge
+			// In order to continue checking, we must program the
+			// bus registers in the bridge to respond to accesses
+			// for it's subordinate bus(es)
+
+			temp_register = func->config_space[0x18 >> 2];
+			pci_bus_write_config_dword (pci_bus, devfn, PCI_PRIMARY_BUS, temp_register);
+
+			secondary_bus = (temp_register >> 8) & 0xFF;
+
+			next = cpqhp_slot_list[secondary_bus];
+
+			while (next != NULL) {
+				rc = cpqhp_valid_replace(ctrl, next);
+
+				if (rc)
+					return(rc);
+
+				next = next->next;
+			}
+
+		}
+		// Check to see if it is a standard config header
+		else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
+			// Check subsystem vendor and ID
+			pci_bus_read_config_dword (pci_bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &temp_register);
+
+			if (temp_register != func->config_space[0x2C >> 2]) {
+				// If it's a SMART-2 and the register isn't filled
+				// in, ignore the difference because
+				// they just have an old rev of the firmware
+
+				if (!((func->config_space[0] == 0xAE100E11)
+				      && (temp_register == 0x00L)))
+					return(ADAPTER_NOT_SAME);
+			}
+			// Figure out IO and memory base lengths
+			for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
+				temp_register = 0xFFFFFFFF;
+				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
+				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
+				if (base) {	  // If this register is implemented
+					if (base & 0x01L) {
+						// IO base
+						// set base = amount of IO space requested
+						base = base & 0xFFFFFFFE;
+						base = (~base) + 1;
+
+						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 = cpqhp_slot_find(func->bus, func->device, index++);
+	}
+
+
+	return(0);
+}
+
+
+/*
+ * cpqhp_find_available_resources
+ *
+ * Finds available memory, IO, and IRQ resources for programming
+ * devices which may be added to the system
+ * this function is for hot plug ADD!
+ *
+ * returns 0 if success
+ */  
+int cpqhp_find_available_resources (struct controller *ctrl, void *rom_start)
+{
+	u8 temp;
+	u8 populated_slot;
+	u8 bridged_slot;
+	void *one_slot;
+	struct pci_func *func = NULL;
+	int i = 10, index;
+	u32 temp_dword, rc;
+	struct pci_resource *mem_node;
+	struct pci_resource *p_mem_node;
+	struct pci_resource *io_node;
+	struct pci_resource *bus_node;
+	void *rom_resource_table;
+
+	rom_resource_table = detect_HRT_floating_pointer(rom_start, rom_start+0xffff);
+	dbg("rom_resource_table = %p\n", rom_resource_table);
+
+	if (rom_resource_table == NULL) {
+		return -ENODEV;
+	}
+	// Sum all resources and setup resource maps
+	unused_IRQ = readl(rom_resource_table + UNUSED_IRQ);
+	dbg("unused_IRQ = %x\n", unused_IRQ);
+
+	temp = 0;
+	while (unused_IRQ) {
+		if (unused_IRQ & 1) {
+			cpqhp_disk_irq = temp;
+			break;
+		}
+		unused_IRQ = unused_IRQ >> 1;
+		temp++;
+	}
+
+	dbg("cpqhp_disk_irq= %d\n", cpqhp_disk_irq);
+	unused_IRQ = unused_IRQ >> 1;
+	temp++;
+
+	while (unused_IRQ) {
+		if (unused_IRQ & 1) {
+			cpqhp_nic_irq = temp;
+			break;
+		}
+		unused_IRQ = unused_IRQ >> 1;
+		temp++;
+	}
+
+	dbg("cpqhp_nic_irq= %d\n", cpqhp_nic_irq);
+	unused_IRQ = readl(rom_resource_table + PCIIRQ);
+
+	temp = 0;
+
+	if (!cpqhp_nic_irq) {
+		cpqhp_nic_irq = ctrl->cfgspc_irq;
+	}
+
+	if (!cpqhp_disk_irq) {
+		cpqhp_disk_irq = ctrl->cfgspc_irq;
+	}
+
+	dbg("cpqhp_disk_irq, cpqhp_nic_irq= %d, %d\n", cpqhp_disk_irq, cpqhp_nic_irq);
+
+	rc = compaq_nvram_load(rom_start, ctrl);
+	if (rc)
+		return rc;
+
+	one_slot = rom_resource_table + sizeof (struct hrt);
+
+	i = readb(rom_resource_table + NUMBER_OF_ENTRIES);
+	dbg("number_of_entries = %d\n", i);
+
+	if (!readb(one_slot + SECONDARY_BUS)) {
+		return(1);
+	}
+
+	dbg("dev|IO base|length|Mem base|length|Pre base|length|PB SB MB\n");
+
+	while (i && readb(one_slot + SECONDARY_BUS)) {
+		u8 dev_func = readb(one_slot + DEV_FUNC);
+		u8 primary_bus = readb(one_slot + PRIMARY_BUS);
+		u8 secondary_bus = readb(one_slot + SECONDARY_BUS);
+		u8 max_bus = readb(one_slot + MAX_BUS);
+		u16 io_base = readw(one_slot + IO_BASE);
+		u16 io_length = readw(one_slot + IO_LENGTH);
+		u16 mem_base = readw(one_slot + MEM_BASE);
+		u16 mem_length = readw(one_slot + MEM_LENGTH);
+		u16 pre_mem_base = readw(one_slot + PRE_MEM_BASE);
+		u16 pre_mem_length = readw(one_slot + PRE_MEM_LENGTH);
+
+		dbg("%2.2x | %4.4x  | %4.4x | %4.4x   | %4.4x | %4.4x   | %4.4x |%2.2x %2.2x %2.2x\n",
+		    dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length,
+		    primary_bus, secondary_bus, max_bus);
+
+		// If this entry isn't for our controller's bus, ignore it
+		if (primary_bus != ctrl->bus) {
+			i--;
+			one_slot += sizeof (struct slot_rt);
+			continue;
+		}
+		// find out if this entry is for an occupied slot
+		ctrl->pci_bus->number = primary_bus;
+		pci_bus_read_config_dword (ctrl->pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword);
+		dbg("temp_D_word = %x\n", temp_dword);
+
+		if (temp_dword != 0xFFFFFFFF) {
+			index = 0;
+			func = cpqhp_slot_find(primary_bus, dev_func >> 3, 0);
+
+			while (func && (func->function != (dev_func & 0x07))) {
+				dbg("func = %p (bus, dev, fun) = (%d, %d, %d)\n", func, primary_bus, dev_func >> 3, index);
+				func = cpqhp_slot_find(primary_bus, dev_func >> 3, index++);
+			}
+
+			// If we can't find a match, skip this table entry
+			if (!func) {
+				i--;
+				one_slot += sizeof (struct slot_rt);
+				continue;
+			}
+			// this may not work and shouldn't be used
+			if (secondary_bus != primary_bus)
+				bridged_slot = 1;
+			else
+				bridged_slot = 0;
+
+			populated_slot = 1;
+		} else {
+			populated_slot = 0;
+			bridged_slot = 0;
+		}
+
+
+		// If we've got a valid IO base, use it
+
+		temp_dword = io_base + io_length;
+
+		if ((io_base) && (temp_dword < 0x10000)) {
+			io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!io_node)
+				return -ENOMEM;
+
+			io_node->base = io_base;
+			io_node->length = io_length;
+
+			dbg("found io_node(base, length) = %x, %x\n", io_node->base, io_node->length);
+			dbg("populated slot =%d \n", populated_slot);
+			if (!populated_slot) {
+				io_node->next = ctrl->io_head;
+				ctrl->io_head = io_node;
+			} else {
+				io_node->next = func->io_head;
+				func->io_head = io_node;
+			}
+		}
+
+		// If we've got a valid memory base, use it
+		temp_dword = mem_base + mem_length;
+		if ((mem_base) && (temp_dword < 0x10000)) {
+			mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!mem_node)
+				return -ENOMEM;
+
+			mem_node->base = mem_base << 16;
+
+			mem_node->length = mem_length << 16;
+
+			dbg("found mem_node(base, length) = %x, %x\n", mem_node->base, mem_node->length);
+			dbg("populated slot =%d \n", populated_slot);
+			if (!populated_slot) {
+				mem_node->next = ctrl->mem_head;
+				ctrl->mem_head = mem_node;
+			} else {
+				mem_node->next = func->mem_head;
+				func->mem_head = mem_node;
+			}
+		}
+
+		// If we've got a valid prefetchable memory base, and
+		// the base + length isn't greater than 0xFFFF
+		temp_dword = pre_mem_base + pre_mem_length;
+		if ((pre_mem_base) && (temp_dword < 0x10000)) {
+			p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!p_mem_node)
+				return -ENOMEM;
+
+			p_mem_node->base = pre_mem_base << 16;
+
+			p_mem_node->length = pre_mem_length << 16;
+			dbg("found p_mem_node(base, length) = %x, %x\n", p_mem_node->base, p_mem_node->length);
+			dbg("populated slot =%d \n", populated_slot);
+
+			if (!populated_slot) {
+				p_mem_node->next = ctrl->p_mem_head;
+				ctrl->p_mem_head = p_mem_node;
+			} else {
+				p_mem_node->next = func->p_mem_head;
+				func->p_mem_head = p_mem_node;
+			}
+		}
+
+		// If we've got a valid bus number, use it
+		// The second condition is to ignore bus numbers on
+		// populated slots that don't have PCI-PCI bridges
+		if (secondary_bus && (secondary_bus != primary_bus)) {
+			bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!bus_node)
+				return -ENOMEM;
+
+			bus_node->base = secondary_bus;
+			bus_node->length = max_bus - secondary_bus + 1;
+			dbg("found bus_node(base, length) = %x, %x\n", bus_node->base, bus_node->length);
+			dbg("populated slot =%d \n", populated_slot);
+			if (!populated_slot) {
+				bus_node->next = ctrl->bus_head;
+				ctrl->bus_head = bus_node;
+			} else {
+				bus_node->next = func->bus_head;
+				func->bus_head = bus_node;
+			}
+		}
+
+		i--;
+		one_slot += sizeof (struct slot_rt);
+	}
+
+	// If all of the following fail, we don't have any resources for
+	// hot plug add
+	rc = 1;
+	rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
+	rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
+	rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head));
+	rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
+
+	return(rc);
+}
+
+
+/*
+ * cpqhp_return_board_resources
+ *
+ * this routine returns all resources allocated to a board to
+ * the available pool.
+ *
+ * returns 0 if success
+ */
+int cpqhp_return_board_resources(struct pci_func * func, struct resource_lists * resources)
+{
+	int rc = 0;
+	struct pci_resource *node;
+	struct pci_resource *t_node;
+	dbg("%s\n", __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 |= cpqhp_resource_sort_and_combine(&(resources->mem_head));
+	rc |= cpqhp_resource_sort_and_combine(&(resources->p_mem_head));
+	rc |= cpqhp_resource_sort_and_combine(&(resources->io_head));
+	rc |= cpqhp_resource_sort_and_combine(&(resources->bus_head));
+
+	return(rc);
+}
+
+
+/*
+ * cpqhp_destroy_resource_list
+ *
+ * Puts node back in the resource list pointed to by head
+ */
+void cpqhp_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);
+	}
+}
+
+
+/*
+ * cpqhp_destroy_board_resources
+ *
+ * Puts node back in the resource list pointed to by head
+ */
+void cpqhp_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);
+	}
+}
+
diff -Nru a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,143 @@
+/*
+ * Compaq Hot Plug Controller Driver
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/workqueue.h>
+#include <linux/pci.h>
+#include "cpqphp.h"
+
+
+/* A few routines that create sysfs entries for the hot plug controller */
+
+static int show_ctrl (struct device *dev, char *buf)
+{
+	struct pci_dev *pci_dev;
+	struct controller *ctrl;
+	char * out = buf;
+	int index;
+	struct pci_resource *res;
+
+	pci_dev = container_of (dev, struct pci_dev, dev);
+	ctrl = pci_get_drvdata(pci_dev);
+
+	out += sprintf(buf, "Free resources: memory\n");
+	index = 11;
+	res = ctrl->mem_head;
+	while (res && index--) {
+		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+		res = res->next;
+	}
+	out += sprintf(out, "Free resources: prefetchable memory\n");
+	index = 11;
+	res = ctrl->p_mem_head;
+	while (res && index--) {
+		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+		res = res->next;
+	}
+	out += sprintf(out, "Free resources: IO\n");
+	index = 11;
+	res = ctrl->io_head;
+	while (res && index--) {
+		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+		res = res->next;
+	}
+	out += sprintf(out, "Free resources: bus numbers\n");
+	index = 11;
+	res = ctrl->bus_head;
+	while (res && index--) {
+		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+		res = res->next;
+	}
+
+	return out - buf;
+}
+static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
+
+static int show_dev (struct device *dev, char *buf)
+{
+	struct pci_dev *pci_dev;
+	struct controller *ctrl;
+	char * out = buf;
+	int index;
+	struct pci_resource *res;
+	struct pci_func *new_slot;
+	struct slot *slot;
+
+	pci_dev = container_of (dev, struct pci_dev, dev);
+	ctrl = pci_get_drvdata(pci_dev);
+
+	slot=ctrl->slot;
+
+	while (slot) {
+		new_slot = cpqhp_slot_find(slot->bus, slot->device, 0);
+		if (!new_slot)
+			break;
+		out += sprintf(out, "assigned resources: memory\n");
+		index = 11;
+		res = new_slot->mem_head;
+		while (res && index--) {
+			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+			res = res->next;
+		}
+		out += sprintf(out, "assigned resources: prefetchable memory\n");
+		index = 11;
+		res = new_slot->p_mem_head;
+		while (res && index--) {
+			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+			res = res->next;
+		}
+		out += sprintf(out, "assigned resources: IO\n");
+		index = 11;
+		res = new_slot->io_head;
+		while (res && index--) {
+			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+			res = res->next;
+		}
+		out += sprintf(out, "assigned resources: bus numbers\n");
+		index = 11;
+		res = new_slot->bus_head;
+		while (res && index--) {
+			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+			res = res->next;
+		}
+		slot=slot->next;
+	}
+
+	return out - buf;
+}
+static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL);
+
+void cpqhp_create_ctrl_files (struct controller *ctrl)
+{
+	device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
+	device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev);
+}
diff -Nru a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/ibmphp.h	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,772 @@
+#ifndef __IBMPHP_H
+#define __IBMPHP_H
+
+/*
+ * IBM Hot Plug Controller Driver
+ *
+ * Written By: Jyoti Shah, Tong Yu, Irene Zubarev, IBM Corporation
+ *
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001,2002 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gregkh@us.ibm.com>
+ *
+ */
+
+#include "pci_hotplug.h"
+
+extern int ibmphp_debug;
+
+#if !defined(CONFIG_HOTPLUG_PCI_IBM_MODULE)
+	#define MY_NAME "ibmphpd"
+#else
+	#define MY_NAME THIS_MODULE->name
+#endif
+#define debug(fmt, arg...) do { if (ibmphp_debug == 1) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0)
+#define debug_pci(fmt, arg...) do { if (ibmphp_debug) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
+
+
+/* EBDA stuff */
+
+/***********************************************************
+* SLOT CAPABILITY                                          *
+***********************************************************/
+
+#define EBDA_SLOT_133_MAX		0x20
+#define EBDA_SLOT_100_MAX		0x10
+#define EBDA_SLOT_66_MAX		0x02
+#define EBDA_SLOT_PCIX_CAP		0x08
+
+
+/************************************************************
+*  RESOURE TYPE                                             *
+************************************************************/
+
+#define EBDA_RSRC_TYPE_MASK		0x03
+#define EBDA_IO_RSRC_TYPE		0x00
+#define EBDA_MEM_RSRC_TYPE		0x01
+#define EBDA_PFM_RSRC_TYPE		0x03
+#define EBDA_RES_RSRC_TYPE		0x02
+
+
+/*************************************************************
+*  IO RESTRICTION TYPE                                       *
+*************************************************************/
+
+#define EBDA_IO_RESTRI_MASK		0x0c
+#define EBDA_NO_RESTRI			0x00
+#define EBDA_AVO_VGA_ADDR		0x04
+#define EBDA_AVO_VGA_ADDR_AND_ALIA	0x08
+#define EBDA_AVO_ISA_ADDR		0x0c
+
+
+/**************************************************************
+*  DEVICE TYPE DEF                                            *
+**************************************************************/
+
+#define EBDA_DEV_TYPE_MASK		0x10
+#define EBDA_PCI_DEV			0x10
+#define EBDA_NON_PCI_DEV		0x00
+
+
+/***************************************************************
+*  PRIMARY DEF DEFINITION                                      *
+***************************************************************/
+
+#define EBDA_PRI_DEF_MASK		0x20
+#define EBDA_PRI_PCI_BUS_INFO		0x20
+#define EBDA_NORM_DEV_RSRC_INFO		0x00
+
+
+//--------------------------------------------------------------
+// RIO TABLE DATA STRUCTURE
+//--------------------------------------------------------------
+
+struct rio_table_hdr {
+	u8 ver_num; 
+	u8 scal_count;
+	u8 riodev_count;
+	u16 offset;
+};
+
+//-------------------------------------------------------------
+// SCALABILITY DETAIL
+//-------------------------------------------------------------
+
+struct scal_detail {
+	u8 node_id;
+	u32 cbar;
+	u8 port0_node_connect;
+	u8 port0_port_connect;
+	u8 port1_node_connect;
+	u8 port1_port_connect;
+	u8 port2_node_connect;
+	u8 port2_port_connect;
+	u8 chassis_num;
+//	struct list_head scal_detail_list;
+};
+
+//--------------------------------------------------------------
+// RIO DETAIL 
+//--------------------------------------------------------------
+
+struct rio_detail {
+	u8 rio_node_id;
+	u32 bbar;
+	u8 rio_type;
+	u8 owner_id;
+	u8 port0_node_connect;
+	u8 port0_port_connect;
+	u8 port1_node_connect;
+	u8 port1_port_connect;
+	u8 first_slot_num;
+	u8 status;
+	u8 wpindex;
+	u8 chassis_num;
+	struct list_head rio_detail_list;
+};
+
+struct opt_rio {
+	u8 rio_type;
+	u8 chassis_num;
+	u8 first_slot_num;
+	u8 middle_num;
+	struct list_head opt_rio_list;
+};	
+
+struct opt_rio_lo {
+	u8 rio_type;
+	u8 chassis_num;
+	u8 first_slot_num;
+	u8 middle_num;
+	u8 pack_count;
+	struct list_head opt_rio_lo_list;
+};	
+
+/****************************************************************
+*  HPC DESCRIPTOR NODE                                          *
+****************************************************************/
+
+struct ebda_hpc_list {
+	u8 format;
+	u16 num_ctlrs;
+	short phys_addr;
+//      struct list_head ebda_hpc_list;
+};
+/*****************************************************************
+*   IN HPC DATA STRUCTURE, THE ASSOCIATED SLOT AND BUS           *
+*   STRUCTURE                                                    *
+*****************************************************************/
+
+struct ebda_hpc_slot {
+	u8 slot_num;
+	u32 slot_bus_num;
+	u8 ctl_index;
+	u8 slot_cap;
+};
+
+struct ebda_hpc_bus {
+	u32 bus_num;
+	u8 slots_at_33_conv;
+	u8 slots_at_66_conv;
+	u8 slots_at_66_pcix;
+	u8 slots_at_100_pcix;
+	u8 slots_at_133_pcix;
+};
+
+
+/********************************************************************
+*   THREE TYPE OF HOT PLUG CONTROLER                                *
+********************************************************************/
+
+struct isa_ctlr_access {
+	u16 io_start;
+	u16 io_end;
+};
+
+struct pci_ctlr_access {
+	u8 bus;
+	u8 dev_fun;
+};
+
+struct wpeg_i2c_ctlr_access {
+	ulong wpegbbar;
+	u8 i2c_addr;
+};
+
+#define HPC_DEVICE_ID		0x0246
+#define HPC_SUBSYSTEM_ID	0x0247
+#define HPC_PCI_OFFSET		0x40
+/*************************************************************************
+*   RSTC DESCRIPTOR NODE                                                 *
+*************************************************************************/
+
+struct ebda_rsrc_list {
+	u8 format;
+	u16 num_entries;
+	u16 phys_addr;
+	struct ebda_rsrc_list *next;
+};
+
+
+/***************************************************************************
+*   PCI RSRC NODE                                                          *
+***************************************************************************/
+
+struct ebda_pci_rsrc {
+	u8 rsrc_type;
+	u8 bus_num;
+	u8 dev_fun;
+	u32 start_addr;
+	u32 end_addr;
+	u8 marked;	/* for NVRAM */
+	struct list_head ebda_pci_rsrc_list;
+};
+
+
+/***********************************************************
+* BUS_INFO DATE STRUCTURE                                  *
+***********************************************************/
+
+struct bus_info {
+	u8 slot_min;
+	u8 slot_max;
+	u8 slot_count;
+	u8 busno;
+	u8 controller_id;
+	u8 current_speed;
+	u8 current_bus_mode;
+	u8 index;
+	u8 slots_at_33_conv;
+	u8 slots_at_66_conv;
+	u8 slots_at_66_pcix;
+	u8 slots_at_100_pcix;
+	u8 slots_at_133_pcix;
+	struct list_head bus_info_list;
+};
+
+
+/***********************************************************
+* GLOBAL VARIABLES                                         *
+***********************************************************/
+extern struct list_head ibmphp_ebda_pci_rsrc_head;
+extern struct list_head ibmphp_slot_head;
+extern struct list_head ibmphp_res_head;
+/***********************************************************
+* FUNCTION PROTOTYPES                                      *
+***********************************************************/
+
+extern void ibmphp_free_ebda_hpc_queue (void);
+extern int ibmphp_access_ebda (void);
+extern struct slot *ibmphp_get_slot_from_physical_num (u8);
+extern int ibmphp_get_total_hp_slots (void);
+extern void ibmphp_free_ibm_slot (struct slot *);
+extern void ibmphp_free_bus_info_queue (void);
+extern void ibmphp_free_ebda_pci_rsrc_queue (void);
+extern struct bus_info *ibmphp_find_same_bus_num (u32);
+extern int ibmphp_get_bus_index (u8);
+extern u16 ibmphp_get_total_controllers (void);
+extern int ibmphp_register_pci (void);
+
+/* passed parameters */
+#define MEM		0
+#define IO		1
+#define PFMEM		2
+
+/* bit masks */
+#define RESTYPE		0x03
+#define IOMASK		0x00	/* will need to take its complement */
+#define MMASK		0x01
+#define PFMASK		0x03
+#define PCIDEVMASK	0x10	/* we should always have PCI devices */
+#define PRIMARYBUSMASK	0x20
+
+/* pci specific defines */
+#define PCI_VENDOR_ID_NOTVALID		0xFFFF
+#define PCI_HEADER_TYPE_MULTIDEVICE	0x80
+#define PCI_HEADER_TYPE_MULTIBRIDGE	0x81
+
+#define LATENCY		0x64
+#define CACHE		64
+#define DEVICEENABLE	0x015F		/* CPQ has 0x0157 */
+
+#define IOBRIDGE	0x1000		/* 4k */
+#define MEMBRIDGE	0x100000	/* 1M */
+
+/* irqs */
+#define SCSI_IRQ	0x09
+#define LAN_IRQ		0x0A
+#define OTHER_IRQ	0x0B
+
+/* Data Structures */
+
+/* type is of the form x x xx xx
+ *                     | |  |  |_ 00 - I/O, 01 - Memory, 11 - PFMemory
+ *                     | |  - 00 - No Restrictions, 01 - Avoid VGA, 10 - Avoid
+ *                     | |    VGA and their aliases, 11 - Avoid ISA
+ *                     | - 1 - PCI device, 0 - non pci device
+ *                     - 1 - Primary PCI Bus Information (0 if Normal device)
+ * the IO restrictions [2:3] are only for primary buses
+ */
+
+
+/* we need this struct because there could be several resource blocks
+ * allocated per primary bus in the EBDA
+ */
+struct range_node {
+	int rangeno;
+	u32 start;
+	u32 end;
+	struct range_node *next;
+};
+
+struct bus_node {
+	u8 busno;
+	int noIORanges;
+	struct range_node *rangeIO;
+	int noMemRanges;
+	struct range_node *rangeMem;
+	int noPFMemRanges;
+	struct range_node *rangePFMem;
+	int needIOUpdate;
+	int needMemUpdate;
+	int needPFMemUpdate;
+	struct resource_node *firstIO;	/* first IO resource on the Bus */
+	struct resource_node *firstMem;	/* first memory resource on the Bus */
+	struct resource_node *firstPFMem;	/* first prefetchable memory resource on the Bus */
+	struct resource_node *firstPFMemFromMem;	/* when run out of pfmem available, taking from Mem */
+	struct list_head bus_list;
+};
+
+struct resource_node {
+	int rangeno;
+	u8 busno;
+	u8 devfunc;
+	u32 start;
+	u32 end;
+	u32 len;
+	int type;		/* MEM, IO, PFMEM */
+	u8 fromMem;		/* this is to indicate that the range is from
+				 * from the Memory bucket rather than from PFMem */
+	struct resource_node *next;
+	struct resource_node *nextRange;	/* for the other mem range on bus */
+};
+
+struct res_needed {
+	u32 mem;
+	u32 pfmem;
+	u32 io;
+	u8 not_correct;		/* needed for return */
+	int devices[32];	/* for device numbers behind this bridge */
+};
+
+/* functions */
+
+extern int ibmphp_rsrc_init (void);
+extern int ibmphp_add_resource (struct resource_node *);
+extern int ibmphp_remove_resource (struct resource_node *);
+extern int ibmphp_find_resource (struct bus_node *, u32, struct resource_node **, int);
+extern int ibmphp_check_resource (struct resource_node *, u8);
+extern int ibmphp_remove_bus (struct bus_node *, u8);
+extern void ibmphp_free_resources (void);
+extern int ibmphp_add_pfmem_from_mem (struct resource_node *);
+extern struct bus_node *ibmphp_find_res_bus (u8);
+extern void ibmphp_print_test (void);	/* for debugging purposes */
+
+extern void ibmphp_hpc_initvars (void);
+extern int ibmphp_hpc_readslot (struct slot *, u8, u8 *);
+extern int ibmphp_hpc_writeslot (struct slot *, u8);
+extern void ibmphp_lock_operations (void);
+extern void ibmphp_unlock_operations (void);
+extern int ibmphp_hpc_fillhpslotinfo (struct hotplug_slot *);
+extern int ibmphp_hpc_start_poll_thread (void);
+extern void ibmphp_hpc_stop_poll_thread (void);
+
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+// HPC return codes
+//----------------------------------------------------------------------------
+#define FALSE				0x00
+#define TRUE				0x01
+#define HPC_ERROR			0xFF
+
+//-----------------------------------------------------------------------------
+// BUS INFO
+//-----------------------------------------------------------------------------
+#define BUS_SPEED			0x30
+#define BUS_MODE			0x40
+#define BUS_MODE_PCIX			0x01
+#define BUS_MODE_PCI			0x00
+#define BUS_SPEED_2			0x20
+#define BUS_SPEED_1			0x10
+#define BUS_SPEED_33			0x00
+#define BUS_SPEED_66			0x01
+#define BUS_SPEED_100			0x02
+#define BUS_SPEED_133			0x03
+#define BUS_SPEED_66PCIX		0x04
+#define BUS_SPEED_66UNKNOWN		0x05
+#define BUS_STATUS_AVAILABLE		0x01
+#define BUS_CONTROL_AVAILABLE		0x02
+#define SLOT_LATCH_REGS_SUPPORTED	0x10
+
+#define PRGM_MODEL_REV_LEVEL		0xF0
+#define MAX_ADAPTER_NONE		0x09
+
+//----------------------------------------------------------------------------
+// HPC 'write' operations/commands
+//----------------------------------------------------------------------------
+//	Command			Code	State	Write to reg
+//					Machine	at index
+//-------------------------	----	-------	------------
+#define HPC_CTLR_ENABLEIRQ	0x00	// N	15
+#define HPC_CTLR_DISABLEIRQ	0x01	// N	15
+#define HPC_SLOT_OFF		0x02	// Y	0-14
+#define HPC_SLOT_ON		0x03	// Y	0-14
+#define HPC_SLOT_ATTNOFF	0x04	// N	0-14
+#define HPC_SLOT_ATTNON		0x05	// N	0-14
+#define HPC_CTLR_CLEARIRQ	0x06	// N	15
+#define HPC_CTLR_RESET		0x07	// Y	15
+#define HPC_CTLR_IRQSTEER	0x08	// N	15
+#define HPC_BUS_33CONVMODE	0x09	// Y	31-34
+#define HPC_BUS_66CONVMODE	0x0A	// Y	31-34
+#define HPC_BUS_66PCIXMODE	0x0B	// Y	31-34
+#define HPC_BUS_100PCIXMODE	0x0C	// Y	31-34
+#define HPC_BUS_133PCIXMODE	0x0D	// Y	31-34
+#define HPC_ALLSLOT_OFF		0x11	// Y	15
+#define HPC_ALLSLOT_ON		0x12	// Y	15
+#define HPC_SLOT_BLINKLED	0x13	// N	0-14
+
+//----------------------------------------------------------------------------
+// read commands
+//----------------------------------------------------------------------------
+#define READ_SLOTSTATUS		0x01
+#define READ_EXTSLOTSTATUS	0x02
+#define READ_BUSSTATUS		0x03
+#define READ_CTLRSTATUS		0x04
+#define READ_ALLSTAT		0x05
+#define READ_ALLSLOT		0x06
+#define READ_SLOTLATCHLOWREG	0x07
+#define READ_REVLEVEL		0x08
+#define READ_HPCOPTIONS		0x09
+//----------------------------------------------------------------------------
+// slot status
+//----------------------------------------------------------------------------
+#define HPC_SLOT_POWER		0x01
+#define HPC_SLOT_CONNECT	0x02
+#define HPC_SLOT_ATTN		0x04
+#define HPC_SLOT_PRSNT2		0x08
+#define HPC_SLOT_PRSNT1		0x10
+#define HPC_SLOT_PWRGD		0x20
+#define HPC_SLOT_BUS_SPEED	0x40
+#define HPC_SLOT_LATCH		0x80
+
+//----------------------------------------------------------------------------
+// HPC_SLOT_POWER status return codes
+//----------------------------------------------------------------------------
+#define HPC_SLOT_POWER_OFF	0x00
+#define HPC_SLOT_POWER_ON	0x01
+
+//----------------------------------------------------------------------------
+// HPC_SLOT_CONNECT status return codes
+//----------------------------------------------------------------------------
+#define HPC_SLOT_CONNECTED	0x00
+#define HPC_SLOT_DISCONNECTED	0x01
+
+//----------------------------------------------------------------------------
+// HPC_SLOT_ATTN status return codes
+//----------------------------------------------------------------------------
+#define HPC_SLOT_ATTN_OFF	0x00
+#define HPC_SLOT_ATTN_ON	0x01
+#define HPC_SLOT_ATTN_BLINK	0x02
+
+//----------------------------------------------------------------------------
+// HPC_SLOT_PRSNT status return codes
+//----------------------------------------------------------------------------
+#define HPC_SLOT_EMPTY		0x00
+#define HPC_SLOT_PRSNT_7	0x01
+#define HPC_SLOT_PRSNT_15	0x02
+#define HPC_SLOT_PRSNT_25	0x03
+
+//----------------------------------------------------------------------------
+// HPC_SLOT_PWRGD status return codes
+//----------------------------------------------------------------------------
+#define HPC_SLOT_PWRGD_FAULT_NONE	0x00
+#define HPC_SLOT_PWRGD_GOOD		0x01
+
+//----------------------------------------------------------------------------
+// HPC_SLOT_BUS_SPEED status return codes
+//----------------------------------------------------------------------------
+#define HPC_SLOT_BUS_SPEED_OK	0x00
+#define HPC_SLOT_BUS_SPEED_MISM	0x01
+
+//----------------------------------------------------------------------------
+// HPC_SLOT_LATCH status return codes
+//----------------------------------------------------------------------------
+#define HPC_SLOT_LATCH_OPEN	0x01	// NOTE : in PCI spec bit off = open
+#define HPC_SLOT_LATCH_CLOSED	0x00	// NOTE : in PCI spec bit on  = closed
+
+
+//----------------------------------------------------------------------------
+// extended slot status
+//----------------------------------------------------------------------------
+#define HPC_SLOT_PCIX		0x01
+#define HPC_SLOT_SPEED1		0x02
+#define HPC_SLOT_SPEED2		0x04
+#define HPC_SLOT_BLINK_ATTN	0x08
+#define HPC_SLOT_RSRVD1		0x10
+#define HPC_SLOT_RSRVD2		0x20
+#define HPC_SLOT_BUS_MODE	0x40
+#define HPC_SLOT_RSRVD3		0x80
+
+//----------------------------------------------------------------------------
+// HPC_XSLOT_PCIX_CAP status return codes
+//----------------------------------------------------------------------------
+#define HPC_SLOT_PCIX_NO	0x00
+#define HPC_SLOT_PCIX_YES	0x01
+
+//----------------------------------------------------------------------------
+// HPC_XSLOT_SPEED status return codes
+//----------------------------------------------------------------------------
+#define HPC_SLOT_SPEED_33	0x00
+#define HPC_SLOT_SPEED_66	0x01
+#define HPC_SLOT_SPEED_133	0x02
+
+//----------------------------------------------------------------------------
+// HPC_XSLOT_ATTN_BLINK status return codes
+//----------------------------------------------------------------------------
+#define HPC_SLOT_ATTN_BLINK_OFF	0x00
+#define HPC_SLOT_ATTN_BLINK_ON	0x01
+
+//----------------------------------------------------------------------------
+// HPC_XSLOT_BUS_MODE status return codes
+//----------------------------------------------------------------------------
+#define HPC_SLOT_BUS_MODE_OK	0x00
+#define HPC_SLOT_BUS_MODE_MISM	0x01
+
+//----------------------------------------------------------------------------
+// Controller status
+//----------------------------------------------------------------------------
+#define HPC_CTLR_WORKING	0x01
+#define HPC_CTLR_FINISHED	0x02
+#define HPC_CTLR_RESULT0	0x04
+#define HPC_CTLR_RESULT1	0x08
+#define HPC_CTLR_RESULE2	0x10
+#define HPC_CTLR_RESULT3	0x20
+#define HPC_CTLR_IRQ_ROUTG	0x40
+#define HPC_CTLR_IRQ_PENDG	0x80
+
+//----------------------------------------------------------------------------
+// HPC_CTLR_WROKING status return codes
+//----------------------------------------------------------------------------
+#define HPC_CTLR_WORKING_NO	0x00
+#define HPC_CTLR_WORKING_YES	0x01
+
+//----------------------------------------------------------------------------
+// HPC_CTLR_FINISHED status return codes
+//----------------------------------------------------------------------------
+#define HPC_CTLR_FINISHED_NO	0x00
+#define HPC_CTLR_FINISHED_YES	0x01
+
+//----------------------------------------------------------------------------
+// HPC_CTLR_RESULT status return codes
+//----------------------------------------------------------------------------
+#define HPC_CTLR_RESULT_SUCCESS	0x00
+#define HPC_CTLR_RESULT_FAILED	0x01
+#define HPC_CTLR_RESULT_RSVD	0x02
+#define HPC_CTLR_RESULT_NORESP	0x03
+
+
+//----------------------------------------------------------------------------
+// macro for slot info
+//----------------------------------------------------------------------------
+#define SLOT_POWER(s)	((u8) ((s & HPC_SLOT_POWER) \
+	? HPC_SLOT_POWER_ON : HPC_SLOT_POWER_OFF))
+
+#define SLOT_CONNECT(s)	((u8) ((s & HPC_SLOT_CONNECT) \
+	? HPC_SLOT_DISCONNECTED : HPC_SLOT_CONNECTED))
+
+#define SLOT_ATTN(s,es)	((u8) ((es & HPC_SLOT_BLINK_ATTN) \
+	? HPC_SLOT_ATTN_BLINK \
+	: ((s & HPC_SLOT_ATTN) ? HPC_SLOT_ATTN_ON : HPC_SLOT_ATTN_OFF)))
+
+#define SLOT_PRESENT(s)	((u8) ((s & HPC_SLOT_PRSNT1) \
+	? ((s & HPC_SLOT_PRSNT2) ? HPC_SLOT_EMPTY : HPC_SLOT_PRSNT_15) \
+	: ((s & HPC_SLOT_PRSNT2) ? HPC_SLOT_PRSNT_25 : HPC_SLOT_PRSNT_7)))
+
+#define SLOT_PWRGD(s)	((u8) ((s & HPC_SLOT_PWRGD) \
+	? HPC_SLOT_PWRGD_GOOD : HPC_SLOT_PWRGD_FAULT_NONE))
+
+#define SLOT_BUS_SPEED(s)	((u8) ((s & HPC_SLOT_BUS_SPEED) \
+	? HPC_SLOT_BUS_SPEED_MISM : HPC_SLOT_BUS_SPEED_OK))
+
+#define SLOT_LATCH(s)	((u8) ((s & HPC_SLOT_LATCH) \
+	? HPC_SLOT_LATCH_CLOSED : HPC_SLOT_LATCH_OPEN))
+
+#define SLOT_PCIX(es)	((u8) ((es & HPC_SLOT_PCIX) \
+	? HPC_SLOT_PCIX_YES : HPC_SLOT_PCIX_NO))
+
+#define SLOT_SPEED(es)	((u8) ((es & HPC_SLOT_SPEED2) \
+	? ((es & HPC_SLOT_SPEED1) ? HPC_SLOT_SPEED_133   \
+				: HPC_SLOT_SPEED_66)   \
+	: HPC_SLOT_SPEED_33))
+
+#define SLOT_BUS_MODE(es)	((u8) ((es & HPC_SLOT_BUS_MODE) \
+	? HPC_SLOT_BUS_MODE_MISM : HPC_SLOT_BUS_MODE_OK))
+
+//--------------------------------------------------------------------------
+// macro for bus info
+//---------------------------------------------------------------------------
+#define CURRENT_BUS_SPEED(s)	((u8) (s & BUS_SPEED_2) \
+	? ((s & BUS_SPEED_1) ? BUS_SPEED_133 : BUS_SPEED_100) \
+	: ((s & BUS_SPEED_1) ? BUS_SPEED_66 : BUS_SPEED_33))
+
+#define CURRENT_BUS_MODE(s)	((u8) (s & BUS_MODE) ? BUS_MODE_PCIX : BUS_MODE_PCI)
+
+#define READ_BUS_STATUS(s)	((u8) (s->options & BUS_STATUS_AVAILABLE))
+
+#define READ_BUS_MODE(s)	((s->revision & PRGM_MODEL_REV_LEVEL) >= 0x20)
+
+#define SET_BUS_STATUS(s)	((u8) (s->options & BUS_CONTROL_AVAILABLE))
+
+#define READ_SLOT_LATCH(s)	((u8) (s->options & SLOT_LATCH_REGS_SUPPORTED))
+
+//----------------------------------------------------------------------------
+// macro for controller info
+//----------------------------------------------------------------------------
+#define CTLR_WORKING(c) ((u8) ((c & HPC_CTLR_WORKING) \
+	? HPC_CTLR_WORKING_YES : HPC_CTLR_WORKING_NO))
+#define CTLR_FINISHED(c) ((u8) ((c & HPC_CTLR_FINISHED) \
+	? HPC_CTLR_FINISHED_YES : HPC_CTLR_FINISHED_NO))
+#define CTLR_RESULT(c) ((u8) ((c & HPC_CTLR_RESULT1)  \
+	? ((c & HPC_CTLR_RESULT0) ? HPC_CTLR_RESULT_NORESP \
+				: HPC_CTLR_RESULT_RSVD)  \
+	: ((c & HPC_CTLR_RESULT0) ? HPC_CTLR_RESULT_FAILED \
+				: HPC_CTLR_RESULT_SUCCESS)))
+
+// command that affect the state machine of HPC
+#define NEEDTOCHECK_CMDSTATUS(c) ((c == HPC_SLOT_OFF)        || \
+				  (c == HPC_SLOT_ON)         || \
+				  (c == HPC_CTLR_RESET)      || \
+				  (c == HPC_BUS_33CONVMODE)  || \
+				  (c == HPC_BUS_66CONVMODE)  || \
+				  (c == HPC_BUS_66PCIXMODE)  || \
+				  (c == HPC_BUS_100PCIXMODE) || \
+				  (c == HPC_BUS_133PCIXMODE) || \
+				  (c == HPC_ALLSLOT_OFF)     || \
+				  (c == HPC_ALLSLOT_ON))
+
+
+/* Core part of the driver */
+
+#define ENABLE		1
+#define DISABLE		0
+
+#define CARD_INFO	0x07
+#define PCIX133		0x07
+#define PCIX66		0x05
+#define PCI66		0x04
+
+extern struct pci_bus *ibmphp_pci_bus;
+
+/* Variables */
+
+struct pci_func {
+	struct pci_dev *dev;	/* from the OS */
+	u8 busno;
+	u8 device;
+	u8 function;
+	struct resource_node *io[6];
+	struct resource_node *mem[6];
+	struct resource_node *pfmem[6];
+	struct pci_func *next;
+	int devices[32];	/* for bridge config */
+	u8 irq[4];		/* for interrupt config */
+	u8 bus;			/* flag for unconfiguring, to say if PPB */
+};
+
+struct slot {
+	u8 bus;
+	u8 device;
+	u8 number;
+	u8 real_physical_slot_num;
+	char name[100];
+	u32 capabilities;
+	u8 supported_speed;
+	u8 supported_bus_mode;
+	struct hotplug_slot *hotplug_slot;
+	struct controller *ctrl;
+	struct pci_func *func;
+	u8 irq[4];
+	u8 flag;		/* this is for disable slot and polling */
+	int bit_mode;		/* 0 = 32, 1 = 64 */
+	u8 ctlr_index;
+	struct bus_info *bus_on;
+	struct list_head ibm_slot_list;
+	u8 status;
+	u8 ext_status;
+	u8 busstatus;
+};
+
+struct controller {
+	struct ebda_hpc_slot *slots;
+	struct ebda_hpc_bus *buses;
+	struct pci_dev *ctrl_dev; /* in case where controller is PCI */
+	u8 starting_slot_num;	/* starting and ending slot #'s this ctrl controls*/
+	u8 ending_slot_num;
+	u8 revision;
+	u8 options;		/* which options HPC supports */
+	u8 status;
+	u8 ctlr_id;
+	u8 slot_count;
+	u8 bus_count;
+	u8 ctlr_relative_id;
+	u32 irq;
+	union {
+		struct isa_ctlr_access isa_ctlr;
+		struct pci_ctlr_access pci_ctlr;
+		struct wpeg_i2c_ctlr_access wpeg_ctlr;
+	} u;
+	u8 ctlr_type;
+	struct list_head ebda_hpc_list;
+};
+
+/* Functions */
+
+extern int ibmphp_init_devno (struct slot **);	/* This function is called from EBDA, so we need it not be static */
+extern int ibmphp_disable_slot (struct hotplug_slot *);	/* This function is called from HPC, so we need it to not be static */
+extern int ibmphp_do_disable_slot (struct slot *slot_cur);
+extern int ibmphp_update_slot_info (struct slot *);	/* This function is called from HPC, so we need it to not be be static */
+extern int ibmphp_configure_card (struct pci_func *, u8);
+extern int ibmphp_unconfigure_card (struct slot **, int);
+extern struct hotplug_slot_ops ibmphp_hotplug_slot_ops;
+
+static inline void long_delay (int delay)
+{
+	set_current_state (TASK_INTERRUPTIBLE);
+	schedule_timeout (delay);
+}
+
+#endif				//__IBMPHP_H
+
diff -Nru a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/ibmphp_core.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,1417 @@
+/*
+ * IBM Hot Plug Controller Driver
+ *
+ * Written By: Chuck Cole, Jyoti Shah, Tong Yu, Irene Zubarev, IBM Corporation
+ *
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001,2002 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gregkh@us.ibm.com>
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/smp_lock.h>
+#include "../../../arch/i386/pci/pci.h"	/* for struct irq_routing_table */
+#include "ibmphp.h"
+
+#define attn_on(sl)  ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNON)
+#define attn_off(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNOFF)
+#define attn_LED_blink(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_BLINKLED)
+#define get_ctrl_revision(sl, rev) ibmphp_hpc_readslot (sl, READ_REVLEVEL, rev)
+#define get_hpc_options(sl, opt) ibmphp_hpc_readslot (sl, READ_HPCOPTIONS, opt)
+
+#define DRIVER_VERSION	"0.6"
+#define DRIVER_DESC	"IBM Hot Plug PCI Controller Driver"
+
+int ibmphp_debug;
+
+static int debug;
+MODULE_PARM (debug, "i");
+MODULE_PARM_DESC (debug, "Debugging mode enabled or not");
+MODULE_LICENSE ("GPL");
+MODULE_DESCRIPTION (DRIVER_DESC);
+
+struct pci_bus *ibmphp_pci_bus;
+static int max_slots;
+
+static int irqs[16];    /* PIC mode IRQ's we're using so far (in case MPS tables don't provide default info for empty slots */
+
+static int init_flag;
+
+/*
+static int get_max_adapter_speed_1 (struct hotplug_slot *, u8 *, u8);
+
+static inline int get_max_adapter_speed (struct hotplug_slot *hs, u8 *value)
+{
+	return get_max_adapter_speed_1 (hs, value, 1);
+}
+*/
+static inline int get_cur_bus_info (struct slot **sl) 
+{
+	int rc = 1;
+	struct slot * slot_cur = *sl;
+
+	debug ("options = %x\n", slot_cur->ctrl->options);
+	debug ("revision = %x\n", slot_cur->ctrl->revision);	
+
+	if (READ_BUS_STATUS (slot_cur->ctrl)) 
+		rc = ibmphp_hpc_readslot (slot_cur, READ_BUSSTATUS, NULL);
+	
+	if (rc) 
+		return rc;
+	  
+	slot_cur->bus_on->current_speed = CURRENT_BUS_SPEED (slot_cur->busstatus);
+	if (READ_BUS_MODE (slot_cur->ctrl))
+		slot_cur->bus_on->current_bus_mode = CURRENT_BUS_MODE (slot_cur->busstatus);
+	else
+		slot_cur->bus_on->current_bus_mode = 0xFF;
+
+	debug ("busstatus = %x, bus_speed = %x, bus_mode = %x\n", slot_cur->busstatus, slot_cur->bus_on->current_speed, slot_cur->bus_on->current_bus_mode);
+	
+	*sl = slot_cur;
+	return 0;
+}
+
+static inline int slot_update (struct slot **sl)
+{
+	int rc;
+ 	rc = ibmphp_hpc_readslot (*sl, READ_ALLSTAT, NULL);
+	if (rc) 
+		return rc;
+	if (!init_flag)
+		return get_cur_bus_info (sl);
+	return rc;
+}
+
+static int __init get_max_slots (void)
+{
+	struct slot * slot_cur;
+	struct list_head * tmp;
+	u8 slot_count = 0;
+
+	list_for_each (tmp, &ibmphp_slot_head) {
+		slot_cur = list_entry (tmp, struct slot, ibm_slot_list);
+		/* sometimes the hot-pluggable slots start with 4 (not always from 1 */
+		slot_count = max (slot_count, slot_cur->number);
+	}
+	return slot_count;
+}
+
+/* This routine will put the correct slot->device information per slot.  It's
+ * called from initialization of the slot structures. It will also assign
+ * interrupt numbers per each slot.
+ * Parameters: struct slot
+ * Returns 0 or errors
+ */
+int ibmphp_init_devno (struct slot **cur_slot)
+{
+	struct irq_routing_table *rtable;
+	int len;
+	int loop;
+	int i;
+
+	rtable = pcibios_get_irq_routing_table ();
+	if (!rtable) {
+		err ("no BIOS routing table...\n");
+		return -ENOMEM;
+	}
+
+	len = (rtable->size - sizeof (struct irq_routing_table)) / sizeof (struct irq_info);
+
+	if (!len)
+		return -1;
+	for (loop = 0; loop < len; loop++) {
+		if ((*cur_slot)->number == rtable->slots[loop].slot) {
+		if ((*cur_slot)->bus == rtable->slots[loop].bus) {
+			(*cur_slot)->device = PCI_SLOT (rtable->slots[loop].devfn);
+			for (i = 0; i < 4; i++)
+				(*cur_slot)->irq[i] = IO_APIC_get_PCI_irq_vector ((int) (*cur_slot)->bus, (int) (*cur_slot)->device, i);
+
+				debug ("(*cur_slot)->irq[0] = %x\n", (*cur_slot)->irq[0]);
+				debug ("(*cur_slot)->irq[1] = %x\n", (*cur_slot)->irq[1]);
+				debug ("(*cur_slot)->irq[2] = %x\n", (*cur_slot)->irq[2]);
+				debug ("(*cur_slot)->irq[3] = %x\n", (*cur_slot)->irq[3]);
+
+				debug ("rtable->exlusive_irqs = %x\n", rtable->exclusive_irqs);
+				debug ("rtable->slots[loop].irq[0].bitmap = %x\n", rtable->slots[loop].irq[0].bitmap);
+				debug ("rtable->slots[loop].irq[1].bitmap = %x\n", rtable->slots[loop].irq[1].bitmap);
+				debug ("rtable->slots[loop].irq[2].bitmap = %x\n", rtable->slots[loop].irq[2].bitmap);
+				debug ("rtable->slots[loop].irq[3].bitmap = %x\n", rtable->slots[loop].irq[3].bitmap);
+
+				debug ("rtable->slots[loop].irq[0].link= %x\n", rtable->slots[loop].irq[0].link);
+				debug ("rtable->slots[loop].irq[1].link = %x\n", rtable->slots[loop].irq[1].link);
+				debug ("rtable->slots[loop].irq[2].link = %x\n", rtable->slots[loop].irq[2].link);
+				debug ("rtable->slots[loop].irq[3].link = %x\n", rtable->slots[loop].irq[3].link);
+				debug ("end of init_devno\n");
+				return 0;
+			}
+		}
+	}
+
+	return -1;
+}
+
+static inline int power_on (struct slot *slot_cur)
+{
+	u8 cmd = HPC_SLOT_ON;
+	int retval;
+
+	retval = ibmphp_hpc_writeslot (slot_cur, cmd);
+	if (retval) {
+		err ("power on failed\n");
+		return retval;
+	}
+	if (CTLR_RESULT (slot_cur->ctrl->status)) {
+		err ("command not completed successfully in power_on \n");
+		return -EIO;
+	}
+	long_delay (3 * HZ); /* For ServeRAID cards, and some 66 PCI */
+	return 0;
+}
+
+static inline int power_off (struct slot *slot_cur)
+{
+	u8 cmd = HPC_SLOT_OFF;
+	int retval;
+
+	retval = ibmphp_hpc_writeslot (slot_cur, cmd);
+	if (retval) {
+		err ("power off failed \n");
+		return retval;
+	}
+	if (CTLR_RESULT (slot_cur->ctrl->status)) {
+		err ("command not completed successfully in power_off \n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 value)
+{
+	int rc = 0;
+	struct slot *pslot;
+	u8 cmd;
+	int hpcrc = 0;
+
+	debug ("set_attention_status - Entry hotplug_slot[%lx] value[%x]\n", (ulong) hotplug_slot, value);
+	ibmphp_lock_operations ();
+	cmd = 0x00;     // avoid compiler warning
+
+	if (hotplug_slot) {
+		switch (value) {
+		case HPC_SLOT_ATTN_OFF:
+			cmd = HPC_SLOT_ATTNOFF;
+			break;
+		case HPC_SLOT_ATTN_ON:
+			cmd = HPC_SLOT_ATTNON;
+			break;
+		case HPC_SLOT_ATTN_BLINK:
+			cmd = HPC_SLOT_BLINKLED;
+			break;
+		default:
+			rc = -ENODEV;
+			err ("set_attention_status - Error : invalid input [%x]\n", value);
+			break;
+		}
+		if (rc == 0) {
+			pslot = (struct slot *) hotplug_slot->private;
+			if (pslot)
+				hpcrc = ibmphp_hpc_writeslot (pslot, cmd);
+			else
+				rc = -ENODEV;
+		}
+	} else	
+		rc = -ENODEV;
+
+	if (hpcrc)
+		rc = hpcrc;
+
+	ibmphp_unlock_operations ();
+
+	debug ("set_attention_status - Exit rc[%d]\n", rc);
+	return rc;
+}
+
+static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 * value)
+{
+	int rc = -ENODEV;
+	struct slot *pslot;
+	int hpcrc = 0;
+	struct slot myslot;
+
+	debug ("get_attention_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value);
+        
+	ibmphp_lock_operations ();
+	if (hotplug_slot && value) {
+		pslot = (struct slot *) hotplug_slot->private;
+		if (pslot) {
+			memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
+			hpcrc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &(myslot.status));
+			if (!hpcrc)
+				hpcrc = ibmphp_hpc_readslot (pslot, READ_EXTSLOTSTATUS, &(myslot.ext_status));
+			if (!hpcrc) {
+				*value = SLOT_ATTN (myslot.status, myslot.ext_status);
+				rc = 0;
+			}
+		}
+	} else
+		rc = -ENODEV;
+
+	if (hpcrc)
+		rc = hpcrc;
+
+	ibmphp_unlock_operations ();
+	debug ("get_attention_status - Exit rc[%d] hpcrc[%x] value[%x]\n", rc, hpcrc, *value);
+	return rc;
+}
+
+static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 * value)
+{
+	int rc = -ENODEV;
+	struct slot *pslot;
+	int hpcrc = 0;
+	struct slot myslot;
+
+	debug ("get_latch_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value);
+	ibmphp_lock_operations ();
+	if (hotplug_slot && value) {
+		pslot = (struct slot *) hotplug_slot->private;
+		if (pslot) {
+			memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
+			hpcrc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &(myslot.status));
+			if (!hpcrc) {
+				*value = SLOT_LATCH (myslot.status);
+				rc = 0;
+			}
+		}
+	} else
+		rc = -ENODEV;
+
+	if (hpcrc)
+		rc = hpcrc;
+
+	ibmphp_unlock_operations ();
+	debug ("get_latch_status - Exit rc[%d] hpcrc[%x] value[%x]\n", rc, hpcrc, *value);
+	return rc;
+}
+
+
+static int get_power_status (struct hotplug_slot *hotplug_slot, u8 * value)
+{
+	int rc = -ENODEV;
+	struct slot *pslot;
+	int hpcrc = 0;
+	struct slot myslot;
+
+	debug ("get_power_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value);
+	ibmphp_lock_operations ();
+	if (hotplug_slot && value) {
+		pslot = (struct slot *) hotplug_slot->private;
+		if (pslot) {
+			memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
+			hpcrc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &(myslot.status));
+			if (!hpcrc) {
+				*value = SLOT_PWRGD (myslot.status);
+				rc = 0;
+			}
+		}
+	} else
+		rc = -ENODEV;
+
+	if (hpcrc)
+		rc = hpcrc;
+
+	ibmphp_unlock_operations ();
+	debug ("get_power_status - Exit rc[%d] hpcrc[%x] value[%x]\n", rc, hpcrc, *value);
+	return rc;
+}
+
+static int get_adapter_present (struct hotplug_slot *hotplug_slot, u8 * value)
+{
+	int rc = -ENODEV;
+	struct slot *pslot;
+	u8 present;
+	int hpcrc = 0;
+	struct slot myslot;
+
+	debug ("get_adapter_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value);
+	ibmphp_lock_operations ();
+	if (hotplug_slot && value) {
+		pslot = (struct slot *) hotplug_slot->private;
+		if (pslot) {
+			memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
+			hpcrc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &(myslot.status));
+			if (!hpcrc) {
+				present = SLOT_PRESENT (myslot.status);
+				if (present == HPC_SLOT_EMPTY)
+					*value = 0;
+				else
+					*value = 1;
+				rc = 0;
+			}
+		}
+	} else
+		rc = -ENODEV;
+	if (hpcrc)
+		rc = hpcrc;
+
+	ibmphp_unlock_operations ();
+	debug ("get_adapter_present - Exit rc[%d] hpcrc[%x] value[%x]\n", rc, hpcrc, *value);
+	return rc;
+}
+
+static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+{
+	int rc = -ENODEV;
+	struct slot *pslot;
+	u8 mode = 0;
+
+	debug ("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __FUNCTION__,
+		hotplug_slot, value);
+
+	ibmphp_lock_operations ();
+
+	if (hotplug_slot && value) {
+		pslot = (struct slot *) hotplug_slot->private;
+		if (pslot) {
+			rc = 0;
+			mode = pslot->supported_bus_mode;
+			*value = pslot->supported_speed; 
+			switch (*value) {
+			case BUS_SPEED_33:
+				break;
+			case BUS_SPEED_66:
+				if (mode == BUS_MODE_PCIX) 
+					*value += 0x01;
+				break;
+			case BUS_SPEED_100:
+			case BUS_SPEED_133:
+				*value = pslot->supported_speed + 0x01;
+				break;
+			default:
+				/* Note (will need to change): there would be soon 256, 512 also */
+				rc = -ENODEV;
+			}
+		}
+	} else
+		rc = -ENODEV;
+
+	ibmphp_unlock_operations ();
+	debug ("%s - Exit rc[%d] value[%x]\n", __FUNCTION__, rc, *value);
+	return rc;
+}
+
+static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+{
+	int rc = -ENODEV;
+	struct slot *pslot;
+	u8 mode = 0;
+
+	debug ("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __FUNCTION__,
+		hotplug_slot, value);
+
+	ibmphp_lock_operations ();
+
+	if (hotplug_slot && value) {
+		pslot = (struct slot *) hotplug_slot->private;
+		if (pslot) {
+			rc = get_cur_bus_info (&pslot);
+			if (!rc) {
+				mode = pslot->bus_on->current_bus_mode;
+				*value = pslot->bus_on->current_speed;
+				switch (*value) {
+				case BUS_SPEED_33:
+					break;
+				case BUS_SPEED_66:
+					if (mode == BUS_MODE_PCIX) 
+						*value += 0x01;
+					else if (mode == BUS_MODE_PCI)
+						;
+					else
+						*value = PCI_SPEED_UNKNOWN;
+					break;
+				case BUS_SPEED_100:
+				case BUS_SPEED_133:
+					*value += 0x01;
+					break;
+				default:
+					/* Note of change: there would also be 256, 512 soon */
+					rc = -ENODEV;
+				}
+			}
+		}
+	} else
+		rc = -ENODEV;
+
+	ibmphp_unlock_operations ();
+	debug ("%s - Exit rc[%d] value[%x]\n", __FUNCTION__, rc, *value);
+	return rc;
+}
+/*
+static int get_max_adapter_speed_1 (struct hotplug_slot *hotplug_slot, u8 * value, u8 flag)
+{
+	int rc = -ENODEV;
+	struct slot *pslot;
+	int hpcrc = 0;
+	struct slot myslot;
+
+	debug ("get_max_adapter_speed_1 - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong)hotplug_slot, (ulong) value);
+
+	if (flag)
+		ibmphp_lock_operations ();
+
+	if (hotplug_slot && value) {
+		pslot = (struct slot *) hotplug_slot->private;
+		if (pslot) {
+			memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
+			hpcrc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &(myslot.status));
+
+			if (!(SLOT_LATCH (myslot.status)) && (SLOT_PRESENT (myslot.status))) {
+				hpcrc = ibmphp_hpc_readslot (pslot, READ_EXTSLOTSTATUS, &(myslot.ext_status));
+				if (!hpcrc) {
+					*value = SLOT_SPEED (myslot.ext_status);
+					rc = 0;
+				}
+			} else {
+				*value = MAX_ADAPTER_NONE;
+				rc = 0;
+			}
+                }
+        } else
+		rc = -ENODEV;
+
+	if (hpcrc)
+		rc = hpcrc;
+
+	if (flag)
+		ibmphp_unlock_operations ();
+
+	debug ("get_max_adapter_speed_1 - Exit rc[%d] hpcrc[%x] value[%x]\n", rc, hpcrc, *value);
+	return rc;
+}
+
+static int get_bus_name (struct hotplug_slot *hotplug_slot, char * value)
+{
+	int rc = -ENODEV;
+	struct slot *pslot = NULL;
+
+	debug ("get_bus_name - Entry hotplug_slot[%lx] \n", (ulong)hotplug_slot);
+
+	ibmphp_lock_operations ();
+
+	if (hotplug_slot) {
+		pslot = (struct slot *) hotplug_slot->private;
+		if (pslot) {
+			rc = 0;
+			snprintf (value, 100, "Bus %x", pslot->bus);
+		}
+	} else
+		rc = -ENODEV;
+
+	ibmphp_unlock_operations ();
+	debug ("get_bus_name - Exit rc[%d] value[%x]\n", rc, *value);
+	return rc;
+}
+*/
+
+/*******************************************************************************
+ * This routine will initialize the ops data structure used in the validate
+ * function. It will also power off empty slots that are powered on since BIOS
+ * leaves those on, albeit disconnected
+ ******************************************************************************/
+static int __init init_ops (void)
+{
+	struct slot *slot_cur;
+	struct list_head *tmp;
+	int retval;
+	int rc;
+
+	list_for_each (tmp, &ibmphp_slot_head) {
+		slot_cur = list_entry (tmp, struct slot, ibm_slot_list);
+
+		if (!slot_cur)
+			return -ENODEV;
+
+		debug ("BEFORE GETTING SLOT STATUS, slot # %x\n", slot_cur->number);
+		if (slot_cur->ctrl->revision == 0xFF) 
+			if (get_ctrl_revision (slot_cur, &slot_cur->ctrl->revision))
+				return -1;
+
+		if (slot_cur->bus_on->current_speed == 0xFF) 
+			if (get_cur_bus_info (&slot_cur)) 
+				return -1;
+
+		if (slot_cur->ctrl->options == 0xFF)
+			if (get_hpc_options (slot_cur, &slot_cur->ctrl->options))
+				return -1;
+
+		retval = slot_update (&slot_cur);
+		if (retval)
+			return retval;
+
+		debug ("status = %x\n", slot_cur->status);
+		debug ("ext_status = %x\n", slot_cur->ext_status);
+		debug ("SLOT_POWER = %x\n", SLOT_POWER (slot_cur->status));
+		debug ("SLOT_PRESENT = %x\n", SLOT_PRESENT (slot_cur->status));
+		debug ("SLOT_LATCH = %x\n", SLOT_LATCH (slot_cur->status));
+
+		if ((SLOT_PWRGD (slot_cur->status)) && 
+		    !(SLOT_PRESENT (slot_cur->status)) && 
+		    !(SLOT_LATCH (slot_cur->status))) {
+			debug ("BEFORE POWER OFF COMMAND\n");
+				rc = power_off (slot_cur);
+				if (rc)
+					return rc;
+
+	/*		retval = slot_update (&slot_cur);
+	 *		if (retval)
+	 *			return retval;
+	 *		ibmphp_update_slot_info (slot_cur);
+	 */
+		}
+	}
+	init_flag = 0;
+	return 0;
+}
+
+/* This operation will check whether the slot is within the bounds and
+ * the operation is valid to perform on that slot
+ * Parameters: slot, operation
+ * Returns: 0 or error codes
+ */
+static int validate (struct slot *slot_cur, int opn)
+{
+	int number;
+	int retval;
+
+	if (!slot_cur)
+		return -ENODEV;
+	number = slot_cur->number;
+	if ((number > max_slots) || (number < 0))
+		return -EBADSLT;
+	debug ("slot_number in validate is %d\n", slot_cur->number);
+
+	retval = slot_update (&slot_cur);
+	if (retval)
+		return retval;
+
+	switch (opn) {
+		case ENABLE:
+			if (!(SLOT_PWRGD (slot_cur->status)) && 
+			     (SLOT_PRESENT (slot_cur->status)) && 
+			     !(SLOT_LATCH (slot_cur->status)))
+				return 0;
+			break;
+		case DISABLE:
+			if ((SLOT_PWRGD (slot_cur->status)) && 
+			    (SLOT_PRESENT (slot_cur->status)) &&
+			    !(SLOT_LATCH (slot_cur->status)))
+				return 0;
+			break;
+		default:
+			break;
+	}
+	err ("validate failed....\n");
+	return -EINVAL;
+}
+
+/********************************************************************************
+ * This routine is for updating the data structures in the hotplug core
+ * Parameters: struct slot
+ * Returns: 0 or error
+ *******************************************************************************/
+int ibmphp_update_slot_info (struct slot *slot_cur)
+{
+	struct hotplug_slot_info *info;
+	int rc;
+	u8 bus_speed;
+	u8 mode;
+
+	info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
+	if (!info) {
+		err ("out of system memory \n");
+		return -ENOMEM;
+	}
+        
+	info->power_status = SLOT_PWRGD (slot_cur->status);
+	info->attention_status = SLOT_ATTN (slot_cur->status, slot_cur->ext_status);
+	info->latch_status = SLOT_LATCH (slot_cur->status);
+        if (!SLOT_PRESENT (slot_cur->status)) {
+                info->adapter_status = 0;
+//		info->max_adapter_speed_status = MAX_ADAPTER_NONE;
+	} else {
+                info->adapter_status = 1;
+//		get_max_adapter_speed_1 (slot_cur->hotplug_slot, &info->max_adapter_speed_status, 0);
+	}
+
+	bus_speed = slot_cur->bus_on->current_speed;
+	mode = slot_cur->bus_on->current_bus_mode;
+
+	switch (bus_speed) {
+	case BUS_SPEED_33:
+		break;
+	case BUS_SPEED_66:
+		if (mode == BUS_MODE_PCIX) 
+			bus_speed += 0x01;
+		else if (mode == BUS_MODE_PCI)
+			;
+		else
+			bus_speed = PCI_SPEED_UNKNOWN;
+		break;
+	case BUS_SPEED_100:
+	case BUS_SPEED_133:
+		bus_speed += 0x01;
+		break;
+	default:
+		bus_speed = PCI_SPEED_UNKNOWN;
+	}
+
+	info->cur_bus_speed = bus_speed;
+	info->max_bus_speed = slot_cur->hotplug_slot->info->max_bus_speed;
+	// To do: bus_names 
+	
+	rc = pci_hp_change_slot_info (slot_cur->hotplug_slot, info);
+	kfree (info);
+	return rc;
+}
+
+
+/******************************************************************************
+ * This function will return the pci_func, given bus and devfunc, or NULL.  It
+ * is called from visit routines
+ ******************************************************************************/
+
+static struct pci_func *ibm_slot_find (u8 busno, u8 device, u8 function)
+{
+	struct pci_func *func_cur;
+	struct slot *slot_cur;
+	struct list_head * tmp;
+	list_for_each (tmp, &ibmphp_slot_head) {
+		slot_cur = list_entry (tmp, struct slot, ibm_slot_list);
+		if (slot_cur->func) {
+			func_cur = slot_cur->func;
+			while (func_cur) {
+				if ((func_cur->busno == busno) && (func_cur->device == device) && (func_cur->function == function))
+					return func_cur;
+				func_cur = func_cur->next;
+			}
+		}
+	}
+	return NULL;
+}
+
+/*************************************************************
+ * This routine frees up memory used by struct slot, including
+ * the pointers to pci_func, bus, hotplug_slot, controller,
+ * and deregistering from the hotplug core
+ *************************************************************/
+static void free_slots (void)
+{
+	struct slot *slot_cur;
+	struct list_head * tmp;
+	struct list_head * next;
+
+	debug ("%s -- enter\n", __FUNCTION__);
+
+	list_for_each_safe (tmp, next, &ibmphp_slot_head) {
+	
+		slot_cur = list_entry (tmp, struct slot, ibm_slot_list);
+
+		pci_hp_deregister (slot_cur->hotplug_slot);
+
+		if (slot_cur->hotplug_slot) {
+			kfree (slot_cur->hotplug_slot);
+			slot_cur->hotplug_slot = NULL;
+		}
+
+		if (slot_cur->ctrl) 
+			slot_cur->ctrl = NULL;
+		
+		if (slot_cur->bus_on) 
+			slot_cur->bus_on = NULL;
+
+		ibmphp_unconfigure_card (&slot_cur, -1);  /* we don't want to actually remove the resources, since free_resources will do just that */
+
+		kfree (slot_cur);
+		slot_cur = NULL;
+	}
+	debug ("%s -- exit\n", __FUNCTION__);
+}
+
+static int ibm_unconfigure_device (struct pci_func *func)
+{
+	struct pci_dev *temp;
+	u8 j;
+
+	debug ("inside %s\n", __FUNCTION__);
+	debug ("func->device = %x, func->function = %x\n", func->device, func->function);
+	debug ("func->device << 3 | 0x0  = %x\n", func->device << 3 | 0x0);
+
+	for (j = 0; j < 0x08; j++) {
+		temp = pci_find_slot (func->busno, (func->device << 3) | j);
+		if (temp)
+			pci_remove_bus_device(temp);
+	}
+	return 0;
+}
+
+/*
+ * The following function is to fix kernel bug regarding 
+ * getting bus entries, here we manually add those primary 
+ * bus entries to kernel bus structure whenever apply
+ */
+
+static u8 bus_structure_fixup (u8 busno)
+{
+	struct pci_bus *bus;
+	struct pci_dev *dev;
+	u16 l;
+
+	if (pci_find_bus(busno) || !(ibmphp_find_same_bus_num (busno)))
+		return 1;
+
+	bus = kmalloc (sizeof (*bus), GFP_KERNEL);
+	if (!bus) {
+		err ("%s - out of memory\n", __FUNCTION__);
+		return 1;
+	}
+	dev = kmalloc (sizeof (*dev), GFP_KERNEL);
+	if (!dev) {
+		kfree (bus);
+		err ("%s - out of memory\n", __FUNCTION__);
+		return 1;
+	}
+
+	bus->number = busno;
+	bus->ops = ibmphp_pci_bus->ops;
+	dev->bus = bus;
+	for (dev->devfn = 0; dev->devfn < 256; dev->devfn += 8) {
+		if (!pci_read_config_word (dev, PCI_VENDOR_ID, &l) &&  l != 0x0000 && l != 0xffff) {
+			debug ("%s - Inside bus_struture_fixup() \n", __FUNCTION__);
+			pci_scan_bus (busno, ibmphp_pci_bus->ops, NULL);
+			break;
+		}
+	}
+
+	kfree (dev);
+	kfree (bus);
+
+	return 0;
+}
+
+static int ibm_configure_device (struct pci_func *func)
+{
+	unsigned char bus;
+	struct pci_bus *child;
+	int num;
+	int flag = 0;	/* this is to make sure we don't double scan the bus, for bridged devices primarily */
+
+	if (!(bus_structure_fixup (func->busno)))
+		flag = 1;
+	if (func->dev == NULL)
+		func->dev = pci_find_slot (func->busno, PCI_DEVFN(func->device, func->function));
+
+	if (func->dev == NULL) {
+		struct pci_bus *bus = pci_find_bus(func->busno);
+		if (!bus)
+			return 0;
+
+		num = pci_scan_slot(bus, PCI_DEVFN(func->device, func->function));
+		if (num)
+			pci_bus_add_devices(bus);
+
+		func->dev = pci_find_slot(func->busno, PCI_DEVFN(func->device, func->function));
+		if (func->dev == NULL) {
+			err ("ERROR... : pci_dev still NULL \n");
+			return 0;
+		}
+	}
+	if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) {
+		pci_read_config_byte (func->dev, PCI_SECONDARY_BUS, &bus);
+		child = (struct pci_bus *) pci_add_new_bus (func->dev->bus, (func->dev), bus);
+		pci_do_scan_bus (child);
+	}
+
+	return 0;
+}
+
+/*******************************************************
+ * Returns whether the bus is empty or not 
+ *******************************************************/
+static int is_bus_empty (struct slot * slot_cur)
+{
+	int rc;
+	struct slot * tmp_slot;
+	u8 i = slot_cur->bus_on->slot_min;
+
+	while (i <= slot_cur->bus_on->slot_max) {
+		if (i == slot_cur->number) {
+			i++;
+			continue;
+		}
+		tmp_slot = ibmphp_get_slot_from_physical_num (i);
+		if (!tmp_slot)
+			return 0;
+		rc = slot_update (&tmp_slot);
+		if (rc)
+			return 0;
+		if (SLOT_PRESENT (tmp_slot->status) && SLOT_PWRGD (tmp_slot->status))
+			return 0;
+		i++;
+	}
+	return 1;
+}
+
+/***********************************************************
+ * If the HPC permits and the bus currently empty, tries to set the 
+ * bus speed and mode at the maximum card and bus capability
+ * Parameters: slot
+ * Returns: bus is set (0) or error code
+ ***********************************************************/
+static int set_bus (struct slot * slot_cur)
+{
+	int rc;
+	u8 speed;
+	u8 cmd = 0x0;
+	struct pci_dev * dev;
+	int retval;
+
+	debug ("%s - entry slot # %d \n", __FUNCTION__, slot_cur->number);
+	if (SET_BUS_STATUS (slot_cur->ctrl) && is_bus_empty (slot_cur)) {
+		rc = slot_update (&slot_cur);
+		if (rc)
+			return rc;
+		speed = SLOT_SPEED (slot_cur->ext_status);
+		debug ("ext_status = %x, speed = %x\n", slot_cur->ext_status, speed);
+		switch (speed) {
+		case HPC_SLOT_SPEED_33:
+			cmd = HPC_BUS_33CONVMODE;
+			break;
+		case HPC_SLOT_SPEED_66:
+			if (SLOT_PCIX (slot_cur->ext_status)) {
+				if ((slot_cur->supported_speed >= BUS_SPEED_66) && (slot_cur->supported_bus_mode == BUS_MODE_PCIX))
+					cmd = HPC_BUS_66PCIXMODE;
+				else if (!SLOT_BUS_MODE (slot_cur->ext_status))
+					/* if max slot/bus capability is 66 pci
+					and there's no bus mode mismatch, then
+					the adapter supports 66 pci */ 
+					cmd = HPC_BUS_66CONVMODE;
+				else
+					cmd = HPC_BUS_33CONVMODE;
+			} else {
+				if (slot_cur->supported_speed >= BUS_SPEED_66)
+					cmd = HPC_BUS_66CONVMODE;
+				else
+					cmd = HPC_BUS_33CONVMODE;
+			}
+			break;
+		case HPC_SLOT_SPEED_133:
+			switch (slot_cur->supported_speed) {
+			case BUS_SPEED_33:
+				cmd = HPC_BUS_33CONVMODE;
+				break;
+			case BUS_SPEED_66:
+				if (slot_cur->supported_bus_mode == BUS_MODE_PCIX)
+					cmd = HPC_BUS_66PCIXMODE;
+				else
+					cmd = HPC_BUS_66CONVMODE;
+				break;
+			case BUS_SPEED_100:
+				cmd = HPC_BUS_100PCIXMODE;
+				break;
+			case BUS_SPEED_133:
+				/* This is to take care of the bug in CIOBX chip */
+				pci_for_each_dev(dev) {
+					if ((dev->vendor == PCI_VENDOR_ID_SERVERWORKS) &&
+					    (dev->device == 0x0101))
+						ibmphp_hpc_writeslot (slot_cur, HPC_BUS_100PCIXMODE);
+				}
+				cmd = HPC_BUS_133PCIXMODE;
+				break;
+			default:
+				err ("Wrong bus speed \n");
+				return -ENODEV;
+			}
+			break;
+		default:
+			err ("wrong slot speed \n");
+			return -ENODEV;
+		}
+		debug ("setting bus speed for slot %d, cmd %x\n", slot_cur->number, cmd);
+		retval = ibmphp_hpc_writeslot (slot_cur, cmd);
+		if (retval) {
+			err ("setting bus speed failed\n");
+			return retval;
+		}
+		if (CTLR_RESULT (slot_cur->ctrl->status)) {
+			err ("command not completed successfully in set_bus \n");
+			return -EIO;
+		}
+	}
+	/* This is for x440, once Brandon fixes the firmware, 
+	will not need this delay */
+	long_delay (1 * HZ);
+	debug ("%s -Exit \n", __FUNCTION__);
+	return 0;
+}
+
+/* This routine checks the bus limitations that the slot is on from the BIOS.
+ * This is used in deciding whether or not to power up the slot.  
+ * (electrical/spec limitations. For example, >1 133 MHz or >2 66 PCI cards on
+ * same bus) 
+ * Parameters: slot
+ * Returns: 0 = no limitations, -EINVAL = exceeded limitations on the bus
+ */
+static int check_limitations (struct slot *slot_cur)
+{
+	u8 i;
+	struct slot * tmp_slot;
+	u8 count = 0;
+	u8 limitation = 0;
+
+	for (i = slot_cur->bus_on->slot_min; i <= slot_cur->bus_on->slot_max; i++) {
+		tmp_slot = ibmphp_get_slot_from_physical_num (i);
+		if (!tmp_slot)
+			return -ENODEV;
+		if ((SLOT_PWRGD (tmp_slot->status)) && !(SLOT_CONNECT (tmp_slot->status))) 
+			count++;
+	}
+	get_cur_bus_info (&slot_cur);
+	switch (slot_cur->bus_on->current_speed) {
+	case BUS_SPEED_33:
+		limitation = slot_cur->bus_on->slots_at_33_conv;
+		break;
+	case BUS_SPEED_66:
+		if (slot_cur->bus_on->current_bus_mode == BUS_MODE_PCIX)
+			limitation = slot_cur->bus_on->slots_at_66_pcix;
+		else
+			limitation = slot_cur->bus_on->slots_at_66_conv;
+		break;
+	case BUS_SPEED_100:
+		limitation = slot_cur->bus_on->slots_at_100_pcix;
+		break;
+	case BUS_SPEED_133:
+		limitation = slot_cur->bus_on->slots_at_133_pcix;
+		break;
+	}
+
+	if ((count + 1) > limitation)
+		return -EINVAL;
+	return 0;
+}
+
+static inline void print_card_capability (struct slot *slot_cur)
+{
+	info ("capability of the card is ");
+	if ((slot_cur->ext_status & CARD_INFO) == PCIX133) 
+		info ("   133 MHz PCI-X \n");
+	else if ((slot_cur->ext_status & CARD_INFO) == PCIX66)
+		info ("    66 MHz PCI-X \n");
+	else if ((slot_cur->ext_status & CARD_INFO) == PCI66)
+		info ("    66 MHz PCI \n");
+	else
+		info ("    33 MHz PCI \n");
+
+}
+
+/* This routine will power on the slot, configure the device(s) and find the
+ * drivers for them.
+ * Parameters: hotplug_slot
+ * Returns: 0 or failure codes
+ */
+static int enable_slot (struct hotplug_slot *hs)
+{
+	int rc, i, rcpr;
+	struct slot *slot_cur;
+	u8 function;
+	struct pci_func *tmp_func;
+
+	ibmphp_lock_operations ();
+
+	debug ("ENABLING SLOT........ \n");
+	slot_cur = (struct slot *) hs->private;
+
+	if ((rc = validate (slot_cur, ENABLE))) {
+		err ("validate function failed \n");
+		goto error_nopower;
+	}
+
+	attn_LED_blink (slot_cur);
+	
+	rc = set_bus (slot_cur);
+	if (rc) {
+		err ("was not able to set the bus \n");
+		goto error_nopower;
+	}
+
+	/*-----------------debugging------------------------------*/
+	get_cur_bus_info (&slot_cur);
+	debug ("the current bus speed right after set_bus = %x \n", slot_cur->bus_on->current_speed); 
+	/*----------------------------------------------------------*/
+
+	rc = check_limitations (slot_cur);
+	if (rc) {
+		err ("Adding this card exceeds the limitations of this bus.\n");
+		err ("(i.e., >1 133MHz cards running on same bus, or "
+		     ">2 66 PCI cards running on same bus\n.");
+		err ("Try hot-adding into another bus \n");
+		rc = -EINVAL;
+		goto error_nopower;
+	}
+
+	rc = power_on (slot_cur);
+
+	if (rc) {
+		err ("something wrong when powering up... please see below for details\n");
+		/* need to turn off before on, otherwise, blinking overwrites */
+		attn_off(slot_cur);
+		attn_on (slot_cur);
+		if (slot_update (&slot_cur)) {
+			attn_off (slot_cur);
+			attn_on (slot_cur);
+			rc = -ENODEV;
+			goto exit;
+		}
+		/* Check to see the error of why it failed */
+		if ((SLOT_POWER (slot_cur->status)) && !(SLOT_PWRGD (slot_cur->status)))
+			err ("power fault occurred trying to power up \n");
+		else if (SLOT_BUS_SPEED (slot_cur->status)) {
+			err ("bus speed mismatch occurred.  please check current bus speed and card capability \n");
+			print_card_capability (slot_cur);
+		} else if (SLOT_BUS_MODE (slot_cur->ext_status)) {
+			err ("bus mode mismatch occurred.  please check current bus mode and card capability \n");
+			print_card_capability (slot_cur);
+		}
+		ibmphp_update_slot_info (slot_cur);
+		goto exit;
+	}
+	debug ("after power_on\n");
+	/*-----------------------debugging---------------------------*/
+	get_cur_bus_info (&slot_cur);
+	debug ("the current bus speed right after power_on = %x \n", slot_cur->bus_on->current_speed);
+	/*----------------------------------------------------------*/
+
+	rc = slot_update (&slot_cur);
+	if (rc)
+		goto error_power;
+	
+	rc = -EINVAL;
+	if (SLOT_POWER (slot_cur->status) && !(SLOT_PWRGD (slot_cur->status))) {
+		err ("power fault occurred trying to power up... \n");
+		goto error_power;
+	}
+	if (SLOT_POWER (slot_cur->status) && (SLOT_BUS_SPEED (slot_cur->status))) {
+		err ("bus speed mismatch occurred.  please check current bus speed and card capability \n");
+		print_card_capability (slot_cur);
+		goto error_power;
+	} 
+	/* Don't think this case will happen after above checks... but just in case, for paranoia sake */
+	if (!(SLOT_POWER (slot_cur->status))) {
+		err ("power on failed... \n");
+		goto error_power;
+	}
+
+	slot_cur->func = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
+	if (!slot_cur->func) {
+		/* We cannot do update_slot_info here, since no memory for
+		 * kmalloc n.e.ways, and update_slot_info allocates some */
+		err ("out of system memory \n");
+		rc = -ENOMEM;
+		goto error_power;
+	}
+	memset (slot_cur->func, 0, sizeof (struct pci_func));
+	slot_cur->func->busno = slot_cur->bus;
+	slot_cur->func->device = slot_cur->device;
+	for (i = 0; i < 4; i++)
+		slot_cur->func->irq[i] = slot_cur->irq[i];
+
+	debug ("b4 configure_card, slot_cur->bus = %x, slot_cur->device = %x\n", slot_cur->bus, slot_cur->device);
+
+	if (ibmphp_configure_card (slot_cur->func, slot_cur->number)) {
+		err ("configure_card was unsuccessful... \n");
+		ibmphp_unconfigure_card (&slot_cur, 1); /* true because don't need to actually deallocate resources, just remove references */
+		debug ("after unconfigure_card\n");
+		slot_cur->func = NULL;
+		rc = -ENOMEM;
+		goto error_power;
+	}
+
+	function = 0x00;
+	do {
+		tmp_func = ibm_slot_find (slot_cur->bus, slot_cur->func->device, function++);
+		if (tmp_func && !(tmp_func->dev))
+			ibm_configure_device (tmp_func);
+	} while (tmp_func);
+
+	attn_off (slot_cur);
+	if (slot_update (&slot_cur)) {
+		rc = -EFAULT;
+		goto exit;
+	}
+	ibmphp_print_test ();
+	rc = ibmphp_update_slot_info (slot_cur);
+exit:
+	ibmphp_unlock_operations(); 
+	return rc;
+
+error_nopower:
+	attn_off (slot_cur);	/* need to turn off if was blinking b4 */
+	attn_on (slot_cur);
+error_cont:
+	rcpr = slot_update (&slot_cur);
+	if (rcpr) {
+		rc = rcpr;
+		goto exit;
+	}
+	ibmphp_update_slot_info (slot_cur);
+	goto exit;
+
+error_power:
+	attn_off (slot_cur);	/* need to turn off if was blinking b4 */
+	attn_on (slot_cur);
+	rcpr = power_off (slot_cur);
+	if (rcpr) {
+		rc = rcpr;
+		goto exit;
+	}
+	goto error_cont;
+}
+
+/**************************************************************
+* HOT REMOVING ADAPTER CARD                                   *
+* INPUT: POINTER TO THE HOTPLUG SLOT STRUCTURE                *
+* OUTPUT: SUCCESS 0 ; FAILURE: UNCONFIGURE , VALIDATE         *
+          DISABLE POWER ,                                    *
+**************************************************************/
+int ibmphp_disable_slot (struct hotplug_slot *hotplug_slot)
+{
+	struct slot *slot = hotplug_slot->private;
+	int rc;
+	
+	ibmphp_lock_operations();
+	rc = ibmphp_do_disable_slot(slot);
+	ibmphp_unlock_operations();
+	return rc;
+}
+
+int ibmphp_do_disable_slot (struct slot *slot_cur)
+{
+	int rc;
+	u8 flag;
+	int parm = 0;
+
+	debug ("DISABLING SLOT... \n"); 
+		
+	if ((slot_cur == NULL) || (slot_cur->ctrl == NULL)) {
+		return -ENODEV;
+	}
+	
+	flag = slot_cur->flag;
+	slot_cur->flag = TRUE;
+
+	if (flag == TRUE) {
+		rc = validate (slot_cur, DISABLE);	/* checking if powered off already & valid slot # */
+		if (rc)
+			goto error;
+	}
+	attn_LED_blink (slot_cur);
+
+	if (slot_cur->func == NULL) {
+		/* We need this for fncs's that were there on bootup */
+		slot_cur->func = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
+		if (!slot_cur->func) {
+			err ("out of system memory \n");
+			rc = -ENOMEM;
+			goto error;
+		}
+		memset (slot_cur->func, 0, sizeof (struct pci_func));
+		slot_cur->func->busno = slot_cur->bus;
+		slot_cur->func->device = slot_cur->device;
+	}
+
+	if ((rc = ibm_unconfigure_device (slot_cur->func))) {
+		err ("removing from kernel failed... \n");
+		err ("Please check to see if it was statically linked or is "
+		     "in use otherwise. (perhaps the driver is not 'hot-removable')\n");
+		goto error;
+	}
+        
+	/* If we got here from latch suddenly opening on operating card or 
+	a power fault, there's no power to the card, so cannot
+	read from it to determine what resources it occupied.  This operation
+	is forbidden anyhow.  The best we can do is remove it from kernel
+	lists at least */
+
+	if (!flag) {
+		attn_off (slot_cur);
+		return 0;
+	}
+
+	rc = ibmphp_unconfigure_card (&slot_cur, parm);
+	slot_cur->func = NULL;
+	debug ("in disable_slot. after unconfigure_card\n");
+	if (rc) {
+		err ("could not unconfigure card.\n");
+		goto error;
+	}
+
+	rc = ibmphp_hpc_writeslot (slot_cur, HPC_SLOT_OFF);
+	if (rc)
+		goto error;
+
+	attn_off (slot_cur);
+	rc = slot_update (&slot_cur);
+	if (rc)
+		goto exit;
+
+	rc = ibmphp_update_slot_info (slot_cur);
+	ibmphp_print_test ();
+exit:
+	return rc;
+
+error:
+	/*  Need to turn off if was blinking b4 */
+	attn_off (slot_cur);
+	attn_on (slot_cur);
+	if (slot_update (&slot_cur)) {
+		rc = -EFAULT;
+		goto exit;
+	}
+	if (flag)		
+		ibmphp_update_slot_info (slot_cur);
+	goto exit;
+}
+
+struct hotplug_slot_ops ibmphp_hotplug_slot_ops = {
+	.owner =			THIS_MODULE,
+	.set_attention_status =		set_attention_status,
+	.enable_slot =			enable_slot,
+	.disable_slot =			ibmphp_disable_slot,
+	.hardware_test =		NULL,
+	.get_power_status =		get_power_status,
+	.get_attention_status =		get_attention_status,
+	.get_latch_status =		get_latch_status,
+	.get_adapter_status =		get_adapter_present,
+	.get_max_bus_speed =		get_max_bus_speed,
+	.get_cur_bus_speed =		get_cur_bus_speed,
+/*	.get_max_adapter_speed =	get_max_adapter_speed,
+	.get_bus_name_status =		get_bus_name,
+*/
+};
+
+static void ibmphp_unload (void)
+{
+	free_slots ();
+	debug ("after slots \n");
+	ibmphp_free_resources ();
+	debug ("after resources \n");
+	ibmphp_free_bus_info_queue ();
+	debug ("after bus info \n");
+	ibmphp_free_ebda_hpc_queue ();
+	debug ("after ebda hpc \n");
+	ibmphp_free_ebda_pci_rsrc_queue ();
+	debug ("after ebda pci rsrc \n");
+	kfree (ibmphp_pci_bus);
+}
+
+static int __init ibmphp_init (void)
+{
+	struct pci_bus *bus;
+	int i = 0;
+	int rc = 0;
+
+	init_flag = 1;
+
+	info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
+
+	ibmphp_pci_bus = kmalloc (sizeof (*ibmphp_pci_bus), GFP_KERNEL);
+	if (!ibmphp_pci_bus) {
+		err ("out of memory\n");
+		rc = -ENOMEM;
+		goto exit;
+	}
+
+	bus = pci_find_bus(0);
+	if (!bus) {
+		err ("Can't find the root pci bus, can not continue\n");
+		rc = -ENODEV;
+		goto error;
+	}
+	memcpy (ibmphp_pci_bus, bus, sizeof (*ibmphp_pci_bus));
+
+	ibmphp_debug = debug;
+
+	ibmphp_hpc_initvars ();
+
+	for (i = 0; i < 16; i++)
+		irqs[i] = 0;
+
+	if ((rc = ibmphp_access_ebda ()))
+		goto error;
+	debug ("after ibmphp_access_ebda ()\n");
+
+	if ((rc = ibmphp_rsrc_init ()))
+		goto error;
+	debug ("AFTER Resource & EBDA INITIALIZATIONS\n");
+
+	max_slots = get_max_slots ();
+	
+	if ((rc = ibmphp_register_pci ()))
+		goto error;
+
+	if (init_ops ()) {
+		rc = -ENODEV;
+		goto error;
+	}
+
+	ibmphp_print_test ();
+	if ((rc = ibmphp_hpc_start_poll_thread ())) {
+		goto error;
+	}
+
+	/* lock ourselves into memory with a module 
+	 * count of -1 so that no one can unload us. */
+	module_put(THIS_MODULE);
+
+exit:
+	return rc;
+
+error:
+	ibmphp_unload ();
+	goto exit;
+}
+
+static void __exit ibmphp_exit (void)
+{
+	ibmphp_hpc_stop_poll_thread ();
+	debug ("after polling\n");
+	ibmphp_unload ();
+	debug ("done\n");
+}
+
+module_init (ibmphp_init);
+module_exit (ibmphp_exit);
diff -Nru a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/ibmphp_ebda.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,1228 @@
+/*
+ * IBM Hot Plug Controller Driver
+ *
+ * Written By: Tong Yu, IBM Corporation
+ *
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001,2002 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gregkh@us.ibm.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include "ibmphp.h"
+
+/*
+ * POST builds data blocks(in this data block definition, a char-1
+ * byte, short(or word)-2 byte, long(dword)-4 byte) in the Extended
+ * BIOS Data Area which describe the configuration of the hot-plug
+ * controllers and resources used by the PCI Hot-Plug devices.
+ *
+ * This file walks EBDA, maps data block from physical addr,
+ * reconstruct linked lists about all system resource(MEM, PFM, IO)
+ * already assigned by POST, as well as linked lists about hot plug
+ * controllers (ctlr#, slot#, bus&slot features...)
+ */
+
+/* Global lists */
+LIST_HEAD (ibmphp_ebda_pci_rsrc_head);
+LIST_HEAD (ibmphp_slot_head);
+
+/* Local variables */
+static struct ebda_hpc_list *hpc_list_ptr;
+static struct ebda_rsrc_list *rsrc_list_ptr;
+static struct rio_table_hdr *rio_table_ptr = NULL;
+static LIST_HEAD (ebda_hpc_head);
+static LIST_HEAD (bus_info_head);
+static LIST_HEAD (rio_vg_head);
+static LIST_HEAD (rio_lo_head);
+static LIST_HEAD (opt_vg_head);
+static LIST_HEAD (opt_lo_head);
+static void *io_mem;
+
+/* Local functions */
+static int ebda_rsrc_controller (void);
+static int ebda_rsrc_rsrc (void);
+static int ebda_rio_table (void);
+
+static struct ebda_hpc_list * __init alloc_ebda_hpc_list (void)
+{
+	struct ebda_hpc_list *list;
+
+	list = kmalloc (sizeof (struct ebda_hpc_list), GFP_KERNEL);
+	if (!list)
+		return NULL;
+	memset (list, 0, sizeof (*list));
+	return list;
+}
+
+static struct controller *alloc_ebda_hpc (u32 slot_count, u32 bus_count)
+{
+	struct controller *controller;
+	struct ebda_hpc_slot *slots;
+	struct ebda_hpc_bus *buses;
+
+	controller = kmalloc (sizeof (struct controller), GFP_KERNEL);
+	if (!controller)
+		return NULL;
+	memset (controller, 0, sizeof (*controller));
+
+	slots = kmalloc (sizeof (struct ebda_hpc_slot) * slot_count, GFP_KERNEL);
+	if (!slots) {
+		kfree (controller);
+		return NULL;
+	}
+	memset (slots, 0, sizeof (*slots) * slot_count);
+	controller->slots = slots;
+
+	buses = kmalloc (sizeof (struct ebda_hpc_bus) * bus_count, GFP_KERNEL);
+	if (!buses) {
+		kfree (controller->slots);
+		kfree (controller);
+		return NULL;
+	}
+	memset (buses, 0, sizeof (*buses) * bus_count);
+	controller->buses = buses;
+
+	return controller;
+}
+
+static void free_ebda_hpc (struct controller *controller)
+{
+	kfree (controller->slots);
+	controller->slots = NULL;
+	kfree (controller->buses);
+	controller->buses = NULL;
+	controller->ctrl_dev = NULL;
+	kfree (controller);
+}
+
+static struct ebda_rsrc_list * __init alloc_ebda_rsrc_list (void)
+{
+	struct ebda_rsrc_list *list;
+
+	list = kmalloc (sizeof (struct ebda_rsrc_list), GFP_KERNEL);
+	if (!list)
+		return NULL;
+	memset (list, 0, sizeof (*list));
+	return list;
+}
+
+static struct ebda_pci_rsrc *alloc_ebda_pci_rsrc (void)
+{
+	struct ebda_pci_rsrc *resource;
+
+	resource = kmalloc (sizeof (struct ebda_pci_rsrc), GFP_KERNEL);
+	if (!resource)
+		return NULL;
+	memset (resource, 0, sizeof (*resource));
+	return resource;
+}
+
+static void __init print_bus_info (void)
+{
+	struct bus_info *ptr;
+	struct list_head *ptr1;
+	
+	list_for_each (ptr1, &bus_info_head) {
+		ptr = list_entry (ptr1, struct bus_info, bus_info_list);
+		debug ("%s - slot_min = %x\n", __FUNCTION__, ptr->slot_min);
+		debug ("%s - slot_max = %x\n", __FUNCTION__, ptr->slot_max);
+		debug ("%s - slot_count = %x\n", __FUNCTION__, ptr->slot_count);
+		debug ("%s - bus# = %x\n", __FUNCTION__, ptr->busno);
+		debug ("%s - current_speed = %x\n", __FUNCTION__, ptr->current_speed);
+		debug ("%s - controller_id = %x\n", __FUNCTION__, ptr->controller_id);
+		
+		debug ("%s - slots_at_33_conv = %x\n", __FUNCTION__, ptr->slots_at_33_conv);
+		debug ("%s - slots_at_66_conv = %x\n", __FUNCTION__, ptr->slots_at_66_conv);
+		debug ("%s - slots_at_66_pcix = %x\n", __FUNCTION__, ptr->slots_at_66_pcix);
+		debug ("%s - slots_at_100_pcix = %x\n", __FUNCTION__, ptr->slots_at_100_pcix);
+		debug ("%s - slots_at_133_pcix = %x\n", __FUNCTION__, ptr->slots_at_133_pcix);
+
+	}
+}
+
+static void print_lo_info (void)
+{
+	struct rio_detail *ptr;
+	struct list_head *ptr1;
+	debug ("print_lo_info ---- \n");	
+	list_for_each (ptr1, &rio_lo_head) {
+		ptr = list_entry (ptr1, struct rio_detail, rio_detail_list);
+		debug ("%s - rio_node_id = %x\n", __FUNCTION__, ptr->rio_node_id);
+		debug ("%s - rio_type = %x\n", __FUNCTION__, ptr->rio_type);
+		debug ("%s - owner_id = %x\n", __FUNCTION__, ptr->owner_id);
+		debug ("%s - first_slot_num = %x\n", __FUNCTION__, ptr->first_slot_num);
+		debug ("%s - wpindex = %x\n", __FUNCTION__, ptr->wpindex);
+		debug ("%s - chassis_num = %x\n", __FUNCTION__, ptr->chassis_num);
+
+	}
+}
+
+static void print_vg_info (void)
+{
+	struct rio_detail *ptr;
+	struct list_head *ptr1;
+	debug ("%s --- \n", __FUNCTION__);
+	list_for_each (ptr1, &rio_vg_head) {
+		ptr = list_entry (ptr1, struct rio_detail, rio_detail_list);
+		debug ("%s - rio_node_id = %x\n", __FUNCTION__, ptr->rio_node_id);
+		debug ("%s - rio_type = %x\n", __FUNCTION__, ptr->rio_type);
+		debug ("%s - owner_id = %x\n", __FUNCTION__, ptr->owner_id);
+		debug ("%s - first_slot_num = %x\n", __FUNCTION__, ptr->first_slot_num);
+		debug ("%s - wpindex = %x\n", __FUNCTION__, ptr->wpindex);
+		debug ("%s - chassis_num = %x\n", __FUNCTION__, ptr->chassis_num);
+
+	}
+}
+
+static void __init print_ebda_pci_rsrc (void)
+{
+	struct ebda_pci_rsrc *ptr;
+	struct list_head *ptr1;
+
+	list_for_each (ptr1, &ibmphp_ebda_pci_rsrc_head) {
+		ptr = list_entry (ptr1, struct ebda_pci_rsrc, ebda_pci_rsrc_list);
+		debug ("%s - rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n", 
+			__FUNCTION__, ptr->rsrc_type ,ptr->bus_num, ptr->dev_fun,ptr->start_addr, ptr->end_addr);
+	}
+}
+
+static void __init print_ibm_slot (void)
+{
+	struct slot *ptr;
+	struct list_head *ptr1;
+
+	list_for_each (ptr1, &ibmphp_slot_head) {
+		ptr = list_entry (ptr1, struct slot, ibm_slot_list);
+		debug ("%s - slot_number: %x \n", __FUNCTION__, ptr->number); 
+	}
+}
+
+static void __init print_opt_vg (void)
+{
+	struct opt_rio *ptr;
+	struct list_head *ptr1;
+	debug ("%s --- \n", __FUNCTION__);
+	list_for_each (ptr1, &opt_vg_head) {
+		ptr = list_entry (ptr1, struct opt_rio, opt_rio_list);
+		debug ("%s - rio_type %x \n", __FUNCTION__, ptr->rio_type); 
+		debug ("%s - chassis_num: %x \n", __FUNCTION__, ptr->chassis_num); 
+		debug ("%s - first_slot_num: %x \n", __FUNCTION__, ptr->first_slot_num); 
+		debug ("%s - middle_num: %x \n", __FUNCTION__, ptr->middle_num); 
+	}
+}
+
+static void __init print_ebda_hpc (void)
+{
+	struct controller *hpc_ptr;
+	struct list_head *ptr1;
+	u16 index;
+
+	list_for_each (ptr1, &ebda_hpc_head) {
+
+		hpc_ptr = list_entry (ptr1, struct controller, ebda_hpc_list); 
+
+		for (index = 0; index < hpc_ptr->slot_count; index++) {
+			debug ("%s - physical slot#: %x\n", __FUNCTION__, hpc_ptr->slots[index].slot_num);
+			debug ("%s - pci bus# of the slot: %x\n", __FUNCTION__, hpc_ptr->slots[index].slot_bus_num);
+			debug ("%s - index into ctlr addr: %x\n", __FUNCTION__, hpc_ptr->slots[index].ctl_index);
+			debug ("%s - cap of the slot: %x\n", __FUNCTION__, hpc_ptr->slots[index].slot_cap);
+		}
+
+		for (index = 0; index < hpc_ptr->bus_count; index++) {
+			debug ("%s - bus# of each bus controlled by this ctlr: %x\n", __FUNCTION__, hpc_ptr->buses[index].bus_num);
+		}
+
+		debug ("%s - type of hpc: %x\n", __FUNCTION__, hpc_ptr->ctlr_type);
+		switch (hpc_ptr->ctlr_type) {
+		case 1:
+			debug ("%s - bus: %x\n", __FUNCTION__, hpc_ptr->u.pci_ctlr.bus);
+			debug ("%s - dev_fun: %x\n", __FUNCTION__, hpc_ptr->u.pci_ctlr.dev_fun);
+			debug ("%s - irq: %x\n", __FUNCTION__, hpc_ptr->irq);
+			break;
+
+		case 0:
+			debug ("%s - io_start: %x\n", __FUNCTION__, hpc_ptr->u.isa_ctlr.io_start);
+			debug ("%s - io_end: %x\n", __FUNCTION__, hpc_ptr->u.isa_ctlr.io_end);
+			debug ("%s - irq: %x\n", __FUNCTION__, hpc_ptr->irq);
+			break;
+
+		case 2:
+		case 4:
+			debug ("%s - wpegbbar: %lx\n", __FUNCTION__, hpc_ptr->u.wpeg_ctlr.wpegbbar);
+			debug ("%s - i2c_addr: %x\n", __FUNCTION__, hpc_ptr->u.wpeg_ctlr.i2c_addr);
+			debug ("%s - irq: %x\n", __FUNCTION__, hpc_ptr->irq);
+			break;
+		}
+	}
+}
+
+int __init ibmphp_access_ebda (void)
+{
+	u8 format, num_ctlrs, rio_complete, hs_complete;
+	u16 ebda_seg, num_entries, next_offset, offset, blk_id, sub_addr, rc, re, rc_id, re_id, base;
+
+
+	rio_complete = 0;
+	hs_complete = 0;
+
+	io_mem = ioremap ((0x40 << 4) + 0x0e, 2);
+	if (!io_mem )
+		return -ENOMEM;
+	ebda_seg = readw (io_mem);
+	iounmap (io_mem);
+	debug ("returned ebda segment: %x\n", ebda_seg);
+	
+	io_mem = ioremap (ebda_seg<<4, 65000);
+	if (!io_mem )
+		return -ENOMEM;
+	next_offset = 0x180;
+
+	for (;;) {
+		offset = next_offset;
+		next_offset = readw (io_mem + offset);	/* offset of next blk */
+
+		offset += 2;
+		if (next_offset == 0)	/* 0 indicate it's last blk */
+			break;
+		blk_id = readw (io_mem + offset);	/* this blk id */
+
+		offset += 2;
+		/* check if it is hot swap block or rio block */
+		if (blk_id != 0x4853 && blk_id != 0x4752)
+			continue;
+		/* found hs table */
+		if (blk_id == 0x4853) {
+			debug ("now enter hot swap block---\n");
+			debug ("hot blk id: %x\n", blk_id);
+			format = readb (io_mem + offset);
+
+			offset += 1;
+			if (format != 4) {
+				iounmap (io_mem);
+				return -ENODEV;
+			}
+			debug ("hot blk format: %x\n", format);
+			/* hot swap sub blk */
+			base = offset;
+
+			sub_addr = base;
+			re = readw (io_mem + sub_addr);	/* next sub blk */
+
+			sub_addr += 2;
+			rc_id = readw (io_mem + sub_addr); 	/* sub blk id */
+
+			sub_addr += 2;
+			if (rc_id != 0x5243) {
+				iounmap (io_mem);
+				return -ENODEV;
+			}
+			/* rc sub blk signature  */
+			num_ctlrs = readb (io_mem + sub_addr);
+
+			sub_addr += 1;
+			hpc_list_ptr = alloc_ebda_hpc_list ();
+			if (!hpc_list_ptr) {
+				iounmap (io_mem);
+				return -ENOMEM;
+			}
+			hpc_list_ptr->format = format;
+			hpc_list_ptr->num_ctlrs = num_ctlrs;
+			hpc_list_ptr->phys_addr = sub_addr;	/*  offset of RSRC_CONTROLLER blk */
+			debug ("info about hpc descriptor---\n");
+			debug ("hot blk format: %x\n", format);
+			debug ("num of controller: %x\n", num_ctlrs);
+			debug ("offset of hpc data structure enteries: %x\n ", sub_addr);
+
+			sub_addr = base + re;	/* re sub blk */
+			rc = readw (io_mem + sub_addr);	/* next sub blk */
+
+			sub_addr += 2;
+			re_id = readw (io_mem + sub_addr);	/* sub blk id */
+
+			sub_addr += 2;
+			if (re_id != 0x5245) {
+				iounmap (io_mem);
+				return -ENODEV;
+			}
+
+			/* signature of re */
+			num_entries = readw (io_mem + sub_addr);
+
+			sub_addr += 2;	/* offset of RSRC_ENTRIES blk */
+			rsrc_list_ptr = alloc_ebda_rsrc_list ();
+			if (!rsrc_list_ptr ) {
+				iounmap (io_mem);
+				return -ENOMEM;
+			}
+			rsrc_list_ptr->format = format;
+			rsrc_list_ptr->num_entries = num_entries;
+			rsrc_list_ptr->phys_addr = sub_addr;
+
+			debug ("info about rsrc descriptor---\n");
+			debug ("format: %x\n", format);
+			debug ("num of rsrc: %x\n", num_entries);
+			debug ("offset of rsrc data structure enteries: %x\n ", sub_addr);
+
+			hs_complete = 1;
+		}
+		/* found rio table */
+		else if (blk_id == 0x4752) {
+			debug ("now enter io table ---\n");
+			debug ("rio blk id: %x\n", blk_id);
+
+			rio_table_ptr = kmalloc (sizeof (struct rio_table_hdr), GFP_KERNEL);
+			if (!rio_table_ptr)
+				return -ENOMEM; 
+			memset (rio_table_ptr, 0, sizeof (struct rio_table_hdr) );
+			rio_table_ptr->ver_num = readb (io_mem + offset);
+			rio_table_ptr->scal_count = readb (io_mem + offset + 1);
+			rio_table_ptr->riodev_count = readb (io_mem + offset + 2);
+			rio_table_ptr->offset = offset +3 ;
+			
+			debug ("info about rio table hdr ---\n");
+			debug ("ver_num: %x\nscal_count: %x\nriodev_count: %x\noffset of rio table: %x\n ", rio_table_ptr->ver_num, rio_table_ptr->scal_count, rio_table_ptr->riodev_count, rio_table_ptr->offset);
+
+			rio_complete = 1;
+		}
+	}
+
+	if (!hs_complete && !rio_complete) {
+		iounmap (io_mem);
+		return -ENODEV;
+	}
+
+	if (rio_table_ptr) {
+		if (rio_complete == 1 && rio_table_ptr->ver_num == 3) {
+			rc = ebda_rio_table ();
+			if (rc) {
+				iounmap (io_mem);
+				return rc;
+			}
+		}
+	}
+	rc = ebda_rsrc_controller ();
+	if (rc) {
+		iounmap (io_mem);
+		return rc;
+	}
+
+	rc = ebda_rsrc_rsrc ();
+	if (rc) {
+		iounmap (io_mem);
+		return rc;
+	}
+
+	iounmap (io_mem);
+	return 0;
+}
+
+/*
+ * map info of scalability details and rio details from physical address
+ */
+static int __init ebda_rio_table (void)
+{
+	u16 offset;
+	u8 i;
+	struct rio_detail *rio_detail_ptr;
+
+	offset = rio_table_ptr->offset;
+	offset += 12 * rio_table_ptr->scal_count;
+
+	// we do concern about rio details
+	for (i = 0; i < rio_table_ptr->riodev_count; i++) {
+		rio_detail_ptr = kmalloc (sizeof (struct rio_detail), GFP_KERNEL);
+		if (!rio_detail_ptr)
+			return -ENOMEM;
+		memset (rio_detail_ptr, 0, sizeof (struct rio_detail));
+		rio_detail_ptr->rio_node_id = readb (io_mem + offset);
+		rio_detail_ptr->bbar = readl (io_mem + offset + 1);
+		rio_detail_ptr->rio_type = readb (io_mem + offset + 5);
+		rio_detail_ptr->owner_id = readb (io_mem + offset + 6);
+		rio_detail_ptr->port0_node_connect = readb (io_mem + offset + 7);
+		rio_detail_ptr->port0_port_connect = readb (io_mem + offset + 8);
+		rio_detail_ptr->port1_node_connect = readb (io_mem + offset + 9);
+		rio_detail_ptr->port1_port_connect = readb (io_mem + offset + 10);
+		rio_detail_ptr->first_slot_num = readb (io_mem + offset + 11);
+		rio_detail_ptr->status = readb (io_mem + offset + 12);
+		rio_detail_ptr->wpindex = readb (io_mem + offset + 13);
+		rio_detail_ptr->chassis_num = readb (io_mem + offset + 14);
+//		debug ("rio_node_id: %x\nbbar: %x\nrio_type: %x\nowner_id: %x\nport0_node: %x\nport0_port: %x\nport1_node: %x\nport1_port: %x\nfirst_slot_num: %x\nstatus: %x\n", rio_detail_ptr->rio_node_id, rio_detail_ptr->bbar, rio_detail_ptr->rio_type, rio_detail_ptr->owner_id, rio_detail_ptr->port0_node_connect, rio_detail_ptr->port0_port_connect, rio_detail_ptr->port1_node_connect, rio_detail_ptr->port1_port_connect, rio_detail_ptr->first_slot_num, rio_detail_ptr->status);
+		//create linked list of chassis
+		if (rio_detail_ptr->rio_type == 4 || rio_detail_ptr->rio_type == 5) 
+			list_add (&rio_detail_ptr->rio_detail_list, &rio_vg_head);
+		//create linked list of expansion box				
+		else if (rio_detail_ptr->rio_type == 6 || rio_detail_ptr->rio_type == 7) 
+			list_add (&rio_detail_ptr->rio_detail_list, &rio_lo_head);
+		else 
+			// not in my concern
+			kfree (rio_detail_ptr);
+		offset += 15;
+	}
+	print_lo_info ();
+	print_vg_info ();
+	return 0;
+}
+
+/*
+ * reorganizing linked list of chassis	 
+ */
+static struct opt_rio *search_opt_vg (u8 chassis_num)
+{
+	struct opt_rio *ptr;
+	struct list_head *ptr1;
+	list_for_each (ptr1, &opt_vg_head) {
+		ptr = list_entry (ptr1, struct opt_rio, opt_rio_list);
+		if (ptr->chassis_num == chassis_num)
+			return ptr;
+	}		
+	return NULL;
+}
+
+static int __init combine_wpg_for_chassis (void)
+{
+	struct opt_rio *opt_rio_ptr = NULL;
+	struct rio_detail *rio_detail_ptr = NULL;
+	struct list_head *list_head_ptr = NULL;
+	
+	list_for_each (list_head_ptr, &rio_vg_head) {
+		rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list);
+		opt_rio_ptr = search_opt_vg (rio_detail_ptr->chassis_num);
+		if (!opt_rio_ptr) {
+			opt_rio_ptr = (struct opt_rio *) kmalloc (sizeof (struct opt_rio), GFP_KERNEL);
+			if (!opt_rio_ptr)
+				return -ENOMEM;
+			memset (opt_rio_ptr, 0, sizeof (struct opt_rio));
+			opt_rio_ptr->rio_type = rio_detail_ptr->rio_type;
+			opt_rio_ptr->chassis_num = rio_detail_ptr->chassis_num;
+			opt_rio_ptr->first_slot_num = rio_detail_ptr->first_slot_num;
+			opt_rio_ptr->middle_num = rio_detail_ptr->first_slot_num;
+			list_add (&opt_rio_ptr->opt_rio_list, &opt_vg_head);
+		} else {	
+			opt_rio_ptr->first_slot_num = min (opt_rio_ptr->first_slot_num, rio_detail_ptr->first_slot_num);
+			opt_rio_ptr->middle_num = max (opt_rio_ptr->middle_num, rio_detail_ptr->first_slot_num);
+		}	
+	}
+	print_opt_vg ();
+	return 0;	
+}	
+
+/*
+ * reorgnizing linked list of expansion box	 
+ */
+static struct opt_rio_lo *search_opt_lo (u8 chassis_num)
+{
+	struct opt_rio_lo *ptr;
+	struct list_head *ptr1;
+	list_for_each (ptr1, &opt_lo_head) {
+		ptr = list_entry (ptr1, struct opt_rio_lo, opt_rio_lo_list);
+		if (ptr->chassis_num == chassis_num)
+			return ptr;
+	}		
+	return NULL;
+}
+
+static int combine_wpg_for_expansion (void)
+{
+	struct opt_rio_lo *opt_rio_lo_ptr = NULL;
+	struct rio_detail *rio_detail_ptr = NULL;
+	struct list_head *list_head_ptr = NULL;
+	
+	list_for_each (list_head_ptr, &rio_lo_head) {
+		rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list);
+		opt_rio_lo_ptr = search_opt_lo (rio_detail_ptr->chassis_num);
+		if (!opt_rio_lo_ptr) {
+			opt_rio_lo_ptr = (struct opt_rio_lo *) kmalloc (sizeof (struct opt_rio_lo), GFP_KERNEL);
+			if (!opt_rio_lo_ptr)
+				return -ENOMEM;
+			memset (opt_rio_lo_ptr, 0, sizeof (struct opt_rio_lo));
+			opt_rio_lo_ptr->rio_type = rio_detail_ptr->rio_type;
+			opt_rio_lo_ptr->chassis_num = rio_detail_ptr->chassis_num;
+			opt_rio_lo_ptr->first_slot_num = rio_detail_ptr->first_slot_num;
+			opt_rio_lo_ptr->middle_num = rio_detail_ptr->first_slot_num;
+			opt_rio_lo_ptr->pack_count = 1;
+			
+			list_add (&opt_rio_lo_ptr->opt_rio_lo_list, &opt_lo_head);
+		} else {	
+			opt_rio_lo_ptr->first_slot_num = min (opt_rio_lo_ptr->first_slot_num, rio_detail_ptr->first_slot_num);
+			opt_rio_lo_ptr->middle_num = max (opt_rio_lo_ptr->middle_num, rio_detail_ptr->first_slot_num);
+			opt_rio_lo_ptr->pack_count = 2;
+		}	
+	}
+	return 0;	
+}
+	
+
+/* Since we don't know the max slot number per each chassis, hence go
+ * through the list of all chassis to find out the range
+ * Arguments: slot_num, 1st slot number of the chassis we think we are on, 
+ * var (0 = chassis, 1 = expansion box) 
+ */
+static int first_slot_num (u8 slot_num, u8 first_slot, u8 var)
+{
+	struct opt_rio *opt_vg_ptr = NULL;
+	struct opt_rio_lo *opt_lo_ptr = NULL;
+	struct list_head *ptr = NULL;
+	int rc = 0;
+
+	if (!var) {
+		list_for_each (ptr, &opt_vg_head) {
+			opt_vg_ptr = list_entry (ptr, struct opt_rio, opt_rio_list);
+			if ((first_slot < opt_vg_ptr->first_slot_num) && (slot_num >= opt_vg_ptr->first_slot_num)) { 
+				rc = -ENODEV;
+				break;
+			}
+		}
+	} else {
+		list_for_each (ptr, &opt_lo_head) {
+			opt_lo_ptr = list_entry (ptr, struct opt_rio_lo, opt_rio_lo_list);
+			if ((first_slot < opt_lo_ptr->first_slot_num) && (slot_num >= opt_lo_ptr->first_slot_num)) {
+				rc = -ENODEV;
+				break;
+			}
+		}
+	}
+	return rc;
+}
+
+static struct opt_rio_lo * find_rxe_num (u8 slot_num)
+{
+	struct opt_rio_lo *opt_lo_ptr;
+	struct list_head *ptr;
+
+	list_for_each (ptr, &opt_lo_head) {
+		opt_lo_ptr = list_entry (ptr, struct opt_rio_lo, opt_rio_lo_list);
+		//check to see if this slot_num belongs to expansion box
+		if ((slot_num >= opt_lo_ptr->first_slot_num) && (!first_slot_num (slot_num, opt_lo_ptr->first_slot_num, 1))) 
+			return opt_lo_ptr;
+	}
+	return NULL;
+}
+
+static struct opt_rio * find_chassis_num (u8 slot_num)
+{
+	struct opt_rio *opt_vg_ptr;
+	struct list_head *ptr;
+
+	list_for_each (ptr, &opt_vg_head) {
+		opt_vg_ptr = list_entry (ptr, struct opt_rio, opt_rio_list);
+		//check to see if this slot_num belongs to chassis 
+		if ((slot_num >= opt_vg_ptr->first_slot_num) && (!first_slot_num (slot_num, opt_vg_ptr->first_slot_num, 0))) 
+			return opt_vg_ptr;
+	}
+	return NULL;
+}
+
+/* This routine will find out how many slots are in the chassis, so that
+ * the slot numbers for rxe100 would start from 1, and not from 7, or 6 etc
+ */
+static u8 calculate_first_slot (u8 slot_num)
+{
+	u8 first_slot = 1;
+	struct list_head * list;
+	struct slot * slot_cur;
+	
+	list_for_each (list, &ibmphp_slot_head) {
+		slot_cur = list_entry (list, struct slot, ibm_slot_list);
+		if (slot_cur->ctrl) {
+			if ((slot_cur->ctrl->ctlr_type != 4) && (slot_cur->ctrl->ending_slot_num > first_slot) && (slot_num > slot_cur->ctrl->ending_slot_num)) 
+				first_slot = slot_cur->ctrl->ending_slot_num;
+		}
+	}			
+	return first_slot + 1;
+
+}
+static char *create_file_name (struct slot * slot_cur)
+{
+	struct opt_rio *opt_vg_ptr = NULL;
+	struct opt_rio_lo *opt_lo_ptr = NULL;
+	static char str[30];
+	int which = 0; /* rxe = 1, chassis = 0 */
+	u8 number = 1; /* either chassis or rxe # */
+	u8 first_slot = 1;
+	u8 slot_num;
+	u8 flag = 0;
+
+	if (!slot_cur) {
+		err ("Structure passed is empty \n");
+		return NULL;
+	}
+	
+	slot_num = slot_cur->number;
+
+	memset (str, 0, sizeof(str));
+	
+	if (rio_table_ptr) {
+		if (rio_table_ptr->ver_num == 3) {
+			opt_vg_ptr = find_chassis_num (slot_num);
+			opt_lo_ptr = find_rxe_num (slot_num);
+		}
+	}
+	if (opt_vg_ptr) {
+		if (opt_lo_ptr) {
+			if ((slot_num - opt_vg_ptr->first_slot_num) > (slot_num - opt_lo_ptr->first_slot_num)) {
+				number = opt_lo_ptr->chassis_num;
+				first_slot = opt_lo_ptr->first_slot_num;
+				which = 1; /* it is RXE */
+			} else {
+				first_slot = opt_vg_ptr->first_slot_num;
+				number = opt_vg_ptr->chassis_num;
+				which = 0;
+			}
+		} else {
+			first_slot = opt_vg_ptr->first_slot_num;
+			number = opt_vg_ptr->chassis_num;
+			which = 0;
+		}
+		++flag;
+	} else if (opt_lo_ptr) {
+		number = opt_lo_ptr->chassis_num;
+		first_slot = opt_lo_ptr->first_slot_num;
+		which = 1;
+		++flag;
+	} else if (rio_table_ptr) {
+		if (rio_table_ptr->ver_num == 3) {
+			/* if both NULL and we DO have correct RIO table in BIOS */
+			return NULL;
+		}
+	} 
+	if (!flag) {
+		if (slot_cur->ctrl->ctlr_type == 4) {
+			first_slot = calculate_first_slot (slot_num);
+			which = 1;
+		} else {
+			which = 0;
+		}
+	}
+
+	sprintf(str, "%s%dslot%d",
+		which == 0 ? "chassis" : "rxe",
+		number, slot_num - first_slot + 1);
+	return str;
+}
+
+static struct pci_driver ibmphp_driver;
+
+/*
+ * map info (ctlr-id, slot count, slot#.. bus count, bus#, ctlr type...) of
+ * each hpc from physical address to a list of hot plug controllers based on
+ * hpc descriptors.
+ */
+static int __init ebda_rsrc_controller (void)
+{
+	u16 addr, addr_slot, addr_bus;
+	u8 ctlr_id, temp, bus_index;
+	u16 ctlr, slot, bus;
+	u16 slot_num, bus_num, index;
+	struct hotplug_slot *hp_slot_ptr;
+	struct controller *hpc_ptr;
+	struct ebda_hpc_bus *bus_ptr;
+	struct ebda_hpc_slot *slot_ptr;
+	struct bus_info *bus_info_ptr1, *bus_info_ptr2;
+	int rc;
+	struct slot *tmp_slot;
+	struct list_head *list;
+
+	addr = hpc_list_ptr->phys_addr;
+	for (ctlr = 0; ctlr < hpc_list_ptr->num_ctlrs; ctlr++) {
+		bus_index = 1;
+		ctlr_id = readb (io_mem + addr);
+		addr += 1;
+		slot_num = readb (io_mem + addr);
+
+		addr += 1;
+		addr_slot = addr;	/* offset of slot structure */
+		addr += (slot_num * 4);
+
+		bus_num = readb (io_mem + addr);
+
+		addr += 1;
+		addr_bus = addr;	/* offset of bus */
+		addr += (bus_num * 9);	/* offset of ctlr_type */
+		temp = readb (io_mem + addr);
+
+		addr += 1;
+		/* init hpc structure */
+		hpc_ptr = alloc_ebda_hpc (slot_num, bus_num);
+		if (!hpc_ptr ) {
+			rc = -ENOMEM;
+			goto error_no_hpc;
+		}
+		hpc_ptr->ctlr_id = ctlr_id;
+		hpc_ptr->ctlr_relative_id = ctlr;
+		hpc_ptr->slot_count = slot_num;
+		hpc_ptr->bus_count = bus_num;
+		debug ("now enter ctlr data struture ---\n");
+		debug ("ctlr id: %x\n", ctlr_id);
+		debug ("ctlr_relative_id: %x\n", hpc_ptr->ctlr_relative_id);
+		debug ("count of slots controlled by this ctlr: %x\n", slot_num);
+		debug ("count of buses controlled by this ctlr: %x\n", bus_num);
+
+		/* init slot structure, fetch slot, bus, cap... */
+		slot_ptr = hpc_ptr->slots;
+		for (slot = 0; slot < slot_num; slot++) {
+			slot_ptr->slot_num = readb (io_mem + addr_slot);
+			slot_ptr->slot_bus_num = readb (io_mem + addr_slot + slot_num);
+			slot_ptr->ctl_index = readb (io_mem + addr_slot + 2*slot_num);
+			slot_ptr->slot_cap = readb (io_mem + addr_slot + 3*slot_num);
+
+			// create bus_info lined list --- if only one slot per bus: slot_min = slot_max 
+
+			bus_info_ptr2 = ibmphp_find_same_bus_num (slot_ptr->slot_bus_num);
+			if (!bus_info_ptr2) {
+				bus_info_ptr1 = (struct bus_info *) kmalloc (sizeof (struct bus_info), GFP_KERNEL);
+				if (!bus_info_ptr1) {
+					rc = -ENOMEM;
+					goto error_no_hp_slot;
+				}
+				memset (bus_info_ptr1, 0, sizeof (struct bus_info));
+				bus_info_ptr1->slot_min = slot_ptr->slot_num;
+				bus_info_ptr1->slot_max = slot_ptr->slot_num;
+				bus_info_ptr1->slot_count += 1;
+				bus_info_ptr1->busno = slot_ptr->slot_bus_num;
+				bus_info_ptr1->index = bus_index++;
+				bus_info_ptr1->current_speed = 0xff;
+				bus_info_ptr1->current_bus_mode = 0xff;
+				
+				bus_info_ptr1->controller_id = hpc_ptr->ctlr_id;
+				
+				list_add_tail (&bus_info_ptr1->bus_info_list, &bus_info_head);
+
+			} else {
+				bus_info_ptr2->slot_min = min (bus_info_ptr2->slot_min, slot_ptr->slot_num);
+				bus_info_ptr2->slot_max = max (bus_info_ptr2->slot_max, slot_ptr->slot_num);
+				bus_info_ptr2->slot_count += 1;
+
+			}
+
+			// end of creating the bus_info linked list
+
+			slot_ptr++;
+			addr_slot += 1;
+		}
+
+		/* init bus structure */
+		bus_ptr = hpc_ptr->buses;
+		for (bus = 0; bus < bus_num; bus++) {
+			bus_ptr->bus_num = readb (io_mem + addr_bus + bus);
+			bus_ptr->slots_at_33_conv = readb (io_mem + addr_bus + bus_num + 8 * bus);
+			bus_ptr->slots_at_66_conv = readb (io_mem + addr_bus + bus_num + 8 * bus + 1);
+
+			bus_ptr->slots_at_66_pcix = readb (io_mem + addr_bus + bus_num + 8 * bus + 2);
+
+			bus_ptr->slots_at_100_pcix = readb (io_mem + addr_bus + bus_num + 8 * bus + 3);
+
+			bus_ptr->slots_at_133_pcix = readb (io_mem + addr_bus + bus_num + 8 * bus + 4);
+
+			bus_info_ptr2 = ibmphp_find_same_bus_num (bus_ptr->bus_num);
+			if (bus_info_ptr2) {
+				bus_info_ptr2->slots_at_33_conv = bus_ptr->slots_at_33_conv;
+				bus_info_ptr2->slots_at_66_conv = bus_ptr->slots_at_66_conv;
+				bus_info_ptr2->slots_at_66_pcix = bus_ptr->slots_at_66_pcix;
+				bus_info_ptr2->slots_at_100_pcix = bus_ptr->slots_at_100_pcix;
+				bus_info_ptr2->slots_at_133_pcix = bus_ptr->slots_at_133_pcix; 
+			}
+			bus_ptr++;
+		}
+
+		hpc_ptr->ctlr_type = temp;
+
+		switch (hpc_ptr->ctlr_type) {
+			case 1:
+				hpc_ptr->u.pci_ctlr.bus = readb (io_mem + addr);
+				hpc_ptr->u.pci_ctlr.dev_fun = readb (io_mem + addr + 1);
+				hpc_ptr->irq = readb (io_mem + addr + 2);
+				addr += 3;
+				debug ("ctrl bus = %x, ctlr devfun = %x, irq = %x\n", 
+					hpc_ptr->u.pci_ctlr.bus,
+					hpc_ptr->u.pci_ctlr.dev_fun, hpc_ptr->irq);
+				break;
+
+			case 0:
+				hpc_ptr->u.isa_ctlr.io_start = readw (io_mem + addr);
+				hpc_ptr->u.isa_ctlr.io_end = readw (io_mem + addr + 2);
+				if (!request_region (hpc_ptr->u.isa_ctlr.io_start,
+						     (hpc_ptr->u.isa_ctlr.io_end - hpc_ptr->u.isa_ctlr.io_start + 1),
+						     "ibmphp")) {
+					rc = -ENODEV;
+					goto error_no_hp_slot;
+				}
+				hpc_ptr->irq = readb (io_mem + addr + 4);
+				addr += 5;
+				break;
+
+			case 2:
+			case 4:
+				hpc_ptr->u.wpeg_ctlr.wpegbbar = readl (io_mem + addr);
+				hpc_ptr->u.wpeg_ctlr.i2c_addr = readb (io_mem + addr + 4);
+				hpc_ptr->irq = readb (io_mem + addr + 5);
+				addr += 6;
+				break;
+			default:
+				rc = -ENODEV;
+				goto error_no_hp_slot;
+		}
+
+		//reorganize chassis' linked list
+		combine_wpg_for_chassis ();
+		combine_wpg_for_expansion ();
+		hpc_ptr->revision = 0xff;
+		hpc_ptr->options = 0xff;
+		hpc_ptr->starting_slot_num = hpc_ptr->slots[0].slot_num;
+		hpc_ptr->ending_slot_num = hpc_ptr->slots[slot_num-1].slot_num;
+
+		// register slots with hpc core as well as create linked list of ibm slot
+		for (index = 0; index < hpc_ptr->slot_count; index++) {
+
+			hp_slot_ptr = (struct hotplug_slot *) kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL);
+			if (!hp_slot_ptr) {
+				rc = -ENOMEM;
+				goto error_no_hp_slot;
+			}
+			memset (hp_slot_ptr, 0, sizeof (struct hotplug_slot));
+
+			hp_slot_ptr->info = (struct hotplug_slot_info *) kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
+			if (!hp_slot_ptr->info) {
+				rc = -ENOMEM;
+				goto error_no_hp_info;
+			}
+			memset (hp_slot_ptr->info, 0, sizeof (struct hotplug_slot_info));
+
+			hp_slot_ptr->name = (char *) kmalloc (30, GFP_KERNEL);
+			if (!hp_slot_ptr->name) {
+				rc = -ENOMEM;
+				goto error_no_hp_name;
+			}
+
+			tmp_slot = kmalloc (sizeof (struct slot), GFP_KERNEL);
+			if (!tmp_slot) {
+				rc = -ENOMEM;
+				goto error_no_slot;
+			}
+			memset (tmp_slot, 0, sizeof (*tmp_slot));
+
+			tmp_slot->flag = TRUE;
+
+			tmp_slot->capabilities = hpc_ptr->slots[index].slot_cap;
+			if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_133_MAX) == EBDA_SLOT_133_MAX)
+				tmp_slot->supported_speed =  3;
+			else if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_100_MAX) == EBDA_SLOT_100_MAX)
+				tmp_slot->supported_speed =  2;
+			else if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_66_MAX) == EBDA_SLOT_66_MAX)
+				tmp_slot->supported_speed =  1;
+				
+			if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_PCIX_CAP) == EBDA_SLOT_PCIX_CAP)
+				tmp_slot->supported_bus_mode = 1;
+			else
+				tmp_slot->supported_bus_mode = 0;
+
+
+			tmp_slot->bus = hpc_ptr->slots[index].slot_bus_num;
+
+			bus_info_ptr1 = ibmphp_find_same_bus_num (hpc_ptr->slots[index].slot_bus_num);
+			if (!bus_info_ptr1) {
+				rc = -ENODEV;
+				goto error;
+			}
+			tmp_slot->bus_on = bus_info_ptr1;
+			bus_info_ptr1 = NULL;
+			tmp_slot->ctrl = hpc_ptr;
+
+			tmp_slot->ctlr_index = hpc_ptr->slots[index].ctl_index;
+			tmp_slot->number = hpc_ptr->slots[index].slot_num;
+			tmp_slot->hotplug_slot = hp_slot_ptr;
+
+			hp_slot_ptr->private = tmp_slot;
+
+			rc = ibmphp_hpc_fillhpslotinfo (hp_slot_ptr);
+			if (rc)
+				goto error;
+
+			rc = ibmphp_init_devno ((struct slot **) &hp_slot_ptr->private);
+			if (rc)
+				goto error;
+			hp_slot_ptr->ops = &ibmphp_hotplug_slot_ops;
+
+			// end of registering ibm slot with hotplug core
+
+			list_add (& ((struct slot *)(hp_slot_ptr->private))->ibm_slot_list, &ibmphp_slot_head);
+		}
+
+		print_bus_info ();
+		list_add (&hpc_ptr->ebda_hpc_list, &ebda_hpc_head );
+
+	}			/* each hpc  */
+
+	list_for_each (list, &ibmphp_slot_head) {
+		tmp_slot = list_entry (list, struct slot, ibm_slot_list);
+
+		snprintf (tmp_slot->hotplug_slot->name, 30, "%s", create_file_name (tmp_slot));
+		pci_hp_register (tmp_slot->hotplug_slot);
+	}
+
+	print_ebda_hpc ();
+	print_ibm_slot ();
+	return 0;
+
+error:
+	kfree (hp_slot_ptr->private);
+error_no_slot:
+	kfree (hp_slot_ptr->name);
+error_no_hp_name:
+	kfree (hp_slot_ptr->info);
+error_no_hp_info:
+	kfree (hp_slot_ptr);
+error_no_hp_slot:
+	free_ebda_hpc (hpc_ptr);
+error_no_hpc:
+	iounmap (io_mem);
+	return rc;
+}
+
+/* 
+ * map info (bus, devfun, start addr, end addr..) of i/o, memory,
+ * pfm from the physical addr to a list of resource.
+ */
+static int __init ebda_rsrc_rsrc (void)
+{
+	u16 addr;
+	short rsrc;
+	u8 type, rsrc_type;
+	struct ebda_pci_rsrc *rsrc_ptr;
+
+	addr = rsrc_list_ptr->phys_addr;
+	debug ("now entering rsrc land\n");
+	debug ("offset of rsrc: %x\n", rsrc_list_ptr->phys_addr);
+
+	for (rsrc = 0; rsrc < rsrc_list_ptr->num_entries; rsrc++) {
+		type = readb (io_mem + addr);
+
+		addr += 1;
+		rsrc_type = type & EBDA_RSRC_TYPE_MASK;
+
+		if (rsrc_type == EBDA_IO_RSRC_TYPE) {
+			rsrc_ptr = alloc_ebda_pci_rsrc ();
+			if (!rsrc_ptr) {
+				iounmap (io_mem);
+				return -ENOMEM;
+			}
+			rsrc_ptr->rsrc_type = type;
+
+			rsrc_ptr->bus_num = readb (io_mem + addr);
+			rsrc_ptr->dev_fun = readb (io_mem + addr + 1);
+			rsrc_ptr->start_addr = readw (io_mem + addr + 2);
+			rsrc_ptr->end_addr = readw (io_mem + addr + 4);
+			addr += 6;
+
+			debug ("rsrc from io type ----\n");
+			debug ("rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n",
+				rsrc_ptr->rsrc_type, rsrc_ptr->bus_num, rsrc_ptr->dev_fun, rsrc_ptr->start_addr, rsrc_ptr->end_addr);
+
+			list_add (&rsrc_ptr->ebda_pci_rsrc_list, &ibmphp_ebda_pci_rsrc_head);
+		}
+
+		if (rsrc_type == EBDA_MEM_RSRC_TYPE || rsrc_type == EBDA_PFM_RSRC_TYPE) {
+			rsrc_ptr = alloc_ebda_pci_rsrc ();
+			if (!rsrc_ptr ) {
+				iounmap (io_mem);
+				return -ENOMEM;
+			}
+			rsrc_ptr->rsrc_type = type;
+
+			rsrc_ptr->bus_num = readb (io_mem + addr);
+			rsrc_ptr->dev_fun = readb (io_mem + addr + 1);
+			rsrc_ptr->start_addr = readl (io_mem + addr + 2);
+			rsrc_ptr->end_addr = readl (io_mem + addr + 6);
+			addr += 10;
+
+			debug ("rsrc from mem or pfm ---\n");
+			debug ("rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n", 
+				rsrc_ptr->rsrc_type, rsrc_ptr->bus_num, rsrc_ptr->dev_fun, rsrc_ptr->start_addr, rsrc_ptr->end_addr);
+
+			list_add (&rsrc_ptr->ebda_pci_rsrc_list, &ibmphp_ebda_pci_rsrc_head);
+		}
+	}
+	kfree (rsrc_list_ptr);
+	rsrc_list_ptr = NULL;
+	print_ebda_pci_rsrc ();
+	return 0;
+}
+
+u16 ibmphp_get_total_controllers (void)
+{
+	return hpc_list_ptr->num_ctlrs;
+}
+
+struct slot *ibmphp_get_slot_from_physical_num (u8 physical_num)
+{
+	struct slot *slot;
+	struct list_head *list;
+
+	list_for_each (list, &ibmphp_slot_head) {
+		slot = list_entry (list, struct slot, ibm_slot_list);
+		if (slot->number == physical_num)
+			return slot;
+	}
+	return NULL;
+}
+
+/* To find:
+ *	- the smallest slot number
+ *	- the largest slot number
+ *	- the total number of the slots based on each bus
+ *	  (if only one slot per bus slot_min = slot_max )
+ */
+struct bus_info *ibmphp_find_same_bus_num (u32 num)
+{
+	struct bus_info *ptr;
+	struct list_head  *ptr1;
+
+	list_for_each (ptr1, &bus_info_head) {
+		ptr = list_entry (ptr1, struct bus_info, bus_info_list); 
+		if (ptr->busno == num) 
+			 return ptr;
+	}
+	return NULL;
+}
+
+/*  Finding relative bus number, in order to map corresponding
+ *  bus register
+ */
+int ibmphp_get_bus_index (u8 num)
+{
+	struct bus_info *ptr;
+	struct list_head  *ptr1;
+
+	list_for_each (ptr1, &bus_info_head) {
+		ptr = list_entry (ptr1, struct bus_info, bus_info_list);
+		if (ptr->busno == num)  
+			return ptr->index;
+	}
+	return -ENODEV;
+}
+
+void ibmphp_free_bus_info_queue (void)
+{
+	struct bus_info *bus_info;
+	struct list_head *list;
+	struct list_head *next;
+
+	list_for_each_safe (list, next, &bus_info_head ) {
+		bus_info = list_entry (list, struct bus_info, bus_info_list);
+		kfree (bus_info);
+	}
+}
+
+void ibmphp_free_ebda_hpc_queue (void)
+{
+	struct controller *controller = NULL;
+	struct list_head *list;
+	struct list_head *next;
+	int pci_flag = 0;
+
+	list_for_each_safe (list, next, &ebda_hpc_head) {
+		controller = list_entry (list, struct controller, ebda_hpc_list);
+		if (controller->ctlr_type == 0)
+			release_region (controller->u.isa_ctlr.io_start, (controller->u.isa_ctlr.io_end - controller->u.isa_ctlr.io_start + 1));
+		else if ((controller->ctlr_type == 1) && (!pci_flag)) {
+			++pci_flag;
+			pci_unregister_driver (&ibmphp_driver);
+		}
+		free_ebda_hpc (controller);
+	}
+}
+
+void ibmphp_free_ebda_pci_rsrc_queue (void)
+{
+	struct ebda_pci_rsrc *resource;
+	struct list_head *list;
+	struct list_head *next;
+
+	list_for_each_safe (list, next, &ibmphp_ebda_pci_rsrc_head) {
+		resource = list_entry (list, struct ebda_pci_rsrc, ebda_pci_rsrc_list);
+		kfree (resource);
+		resource = NULL;
+	}
+}
+
+static struct pci_device_id id_table[] __devinitdata = {
+	{
+		.vendor		= PCI_VENDOR_ID_IBM,
+		.device		= HPC_DEVICE_ID,
+		.subvendor	= PCI_VENDOR_ID_IBM,
+		.subdevice	= HPC_SUBSYSTEM_ID,
+		.class		= ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00),
+	}, {}
+};		
+
+MODULE_DEVICE_TABLE(pci, id_table);
+
+static int ibmphp_probe (struct pci_dev *, const struct pci_device_id *);
+static struct pci_driver ibmphp_driver = {
+	.name		= "ibmphp",
+	.id_table	= id_table,
+	.probe		= ibmphp_probe,
+};
+
+int ibmphp_register_pci (void)
+{
+	struct controller *ctrl;
+	struct list_head *tmp;
+	int rc = 0;
+
+	list_for_each (tmp, &ebda_hpc_head) {
+		ctrl = list_entry (tmp, struct controller, ebda_hpc_list);
+		if (ctrl->ctlr_type == 1) {
+			rc = pci_module_init (&ibmphp_driver);
+			break;
+		}
+	}
+	return rc;
+}
+static int ibmphp_probe (struct pci_dev * dev, const struct pci_device_id *ids)
+{
+	struct controller *ctrl;
+	struct list_head *tmp;
+
+	debug ("inside ibmphp_probe \n");
+	
+	list_for_each (tmp, &ebda_hpc_head) {
+		ctrl = list_entry (tmp, struct controller, ebda_hpc_list);
+		if (ctrl->ctlr_type == 1) {
+			if ((dev->devfn == ctrl->u.pci_ctlr.dev_fun) && (dev->bus->number == ctrl->u.pci_ctlr.bus)) {
+				ctrl->ctrl_dev = dev;
+				debug ("found device!!! \n");
+				debug ("dev->device = %x, dev->subsystem_device = %x\n", dev->device, dev->subsystem_device);
+				return 0;
+			}
+		}
+	}
+	return -ENODEV;
+}
+
diff -Nru a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/ibmphp_hpc.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,1228 @@
+/*
+ * IBM Hot Plug Controller Driver
+ *
+ * Written By: Jyoti Shah, IBM Corporation
+ *
+ * Copyright (c) 2001-2002 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gregkh@us.ibm.com>
+ *                  <jshah@us.ibm.com>
+ *
+ */
+
+#include <linux/wait.h>
+#include <linux/time.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include "ibmphp.h"
+
+static int to_debug = FALSE;
+#define debug_polling(fmt, arg...)	do { if (to_debug) debug (fmt, arg); } while (0)
+
+//----------------------------------------------------------------------------
+// timeout values
+//----------------------------------------------------------------------------
+#define CMD_COMPLETE_TOUT_SEC	60	// give HPC 60 sec to finish cmd
+#define HPC_CTLR_WORKING_TOUT	60	// give HPC 60 sec to finish cmd
+#define HPC_GETACCESS_TIMEOUT	60	// seconds
+#define POLL_INTERVAL_SEC	2	// poll HPC every 2 seconds
+#define POLL_LATCH_CNT		5	// poll latch 5 times, then poll slots
+
+//----------------------------------------------------------------------------
+// Winnipeg Architected Register Offsets
+//----------------------------------------------------------------------------
+#define WPG_I2CMBUFL_OFFSET	0x08	// I2C Message Buffer Low
+#define WPG_I2CMOSUP_OFFSET	0x10	// I2C Master Operation Setup Reg
+#define WPG_I2CMCNTL_OFFSET	0x20	// I2C Master Control Register
+#define WPG_I2CPARM_OFFSET	0x40	// I2C Parameter Register
+#define WPG_I2CSTAT_OFFSET	0x70	// I2C Status Register
+
+//----------------------------------------------------------------------------
+// Winnipeg Store Type commands (Add this commands to the register offset)
+//----------------------------------------------------------------------------
+#define WPG_I2C_AND		0x1000	// I2C AND operation
+#define WPG_I2C_OR		0x2000	// I2C OR operation
+
+//----------------------------------------------------------------------------
+// Command set for I2C Master Operation Setup Regisetr
+//----------------------------------------------------------------------------
+#define WPG_READATADDR_MASK	0x00010000	// read,bytes,I2C shifted,index
+#define WPG_WRITEATADDR_MASK	0x40010000	// write,bytes,I2C shifted,index
+#define WPG_READDIRECT_MASK	0x10010000
+#define WPG_WRITEDIRECT_MASK	0x60010000
+
+
+//----------------------------------------------------------------------------
+// bit masks for I2C Master Control Register
+//----------------------------------------------------------------------------
+#define WPG_I2CMCNTL_STARTOP_MASK	0x00000002	// Start the Operation
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+#define WPG_I2C_IOREMAP_SIZE	0x2044	// size of linear address interval
+
+//----------------------------------------------------------------------------
+// command index
+//----------------------------------------------------------------------------
+#define WPG_1ST_SLOT_INDEX	0x01	// index - 1st slot for ctlr
+#define WPG_CTLR_INDEX		0x0F	// index - ctlr
+#define WPG_1ST_EXTSLOT_INDEX	0x10	// index - 1st ext slot for ctlr
+#define WPG_1ST_BUS_INDEX	0x1F	// index - 1st bus for ctlr
+
+//----------------------------------------------------------------------------
+// macro utilities
+//----------------------------------------------------------------------------
+// if bits 20,22,25,26,27,29,30 are OFF return TRUE
+#define HPC_I2CSTATUS_CHECK(s)	((u8)((s & 0x00000A76) ? FALSE : TRUE))
+
+//----------------------------------------------------------------------------
+// global variables
+//----------------------------------------------------------------------------
+static int ibmphp_shutdown;
+static int tid_poll;
+static struct semaphore sem_hpcaccess;	// lock access to HPC
+static struct semaphore semOperations;	// lock all operations and
+					// access to data structures
+static struct semaphore sem_exit;	// make sure polling thread goes away
+//----------------------------------------------------------------------------
+// local function prototypes
+//----------------------------------------------------------------------------
+static u8 i2c_ctrl_read (struct controller *, void *, u8);
+static u8 i2c_ctrl_write (struct controller *, void *, u8, u8);
+static u8 hpc_writecmdtoindex (u8, u8);
+static u8 hpc_readcmdtoindex (u8, u8);
+static void get_hpc_access (void);
+static void free_hpc_access (void);
+static void poll_hpc (void);
+static int update_slot (struct slot *, u8);
+static int process_changeinstatus (struct slot *, struct slot *);
+static int process_changeinlatch (u8, u8, struct controller *);
+static int hpc_poll_thread (void *);
+static int hpc_wait_ctlr_notworking (int, struct controller *, void *, u8 *);
+//----------------------------------------------------------------------------
+
+
+/*----------------------------------------------------------------------
+* Name:    ibmphp_hpc_initvars
+*
+* Action:  initialize semaphores and variables
+*---------------------------------------------------------------------*/
+void __init ibmphp_hpc_initvars (void)
+{
+	debug ("%s - Entry\n", __FUNCTION__);
+
+	init_MUTEX (&sem_hpcaccess);
+	init_MUTEX (&semOperations);
+	init_MUTEX_LOCKED (&sem_exit);
+	to_debug = FALSE;
+	ibmphp_shutdown = FALSE;
+	tid_poll = 0;
+
+	debug ("%s - Exit\n", __FUNCTION__);
+}
+
+/*----------------------------------------------------------------------
+* Name:    i2c_ctrl_read
+*
+* Action:  read from HPC over I2C
+*
+*---------------------------------------------------------------------*/
+static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void *WPGBbar, u8 index)
+{
+	u8 status;
+	int i;
+	void *wpg_addr;		// base addr + offset
+	ulong wpg_data,		// data to/from WPG LOHI format
+	ultemp, data;		// actual data HILO format
+
+
+	debug_polling ("%s - Entry WPGBbar[%lx] index[%x] \n", __FUNCTION__, (ulong) WPGBbar, index);
+
+	//--------------------------------------------------------------------
+	// READ - step 1
+	// read at address, byte length, I2C address (shifted), index
+	// or read direct, byte length, index
+	if (ctlr_ptr->ctlr_type == 0x02) {
+		data = WPG_READATADDR_MASK;
+		// fill in I2C address
+		ultemp = (ulong) ctlr_ptr->u.wpeg_ctlr.i2c_addr;
+		ultemp = ultemp >> 1;
+		data |= (ultemp << 8);
+
+		// fill in index
+		data |= (ulong) index;
+	} else if (ctlr_ptr->ctlr_type == 0x04) {
+		data = WPG_READDIRECT_MASK;
+
+		// fill in index
+		ultemp = (ulong) index;
+		ultemp = ultemp << 8;
+		data |= ultemp;
+	} else {
+		err ("this controller type is not supported \n");
+		return HPC_ERROR;
+	}
+
+	wpg_data = swab32 (data);	// swap data before writing
+	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMOSUP_OFFSET;
+	writel (wpg_data, wpg_addr);
+
+	//--------------------------------------------------------------------
+	// READ - step 2 : clear the message buffer
+	data = 0x00000000;
+	wpg_data = swab32 (data);
+	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMBUFL_OFFSET;
+	writel (wpg_data, wpg_addr);
+
+	//--------------------------------------------------------------------
+	// READ - step 3 : issue start operation, I2C master control bit 30:ON
+	//                 2020 : [20] OR operation at [20] offset 0x20
+	data = WPG_I2CMCNTL_STARTOP_MASK;
+	wpg_data = swab32 (data);
+	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET + (ulong) WPG_I2C_OR;
+	writel (wpg_data, wpg_addr);
+
+	//--------------------------------------------------------------------
+	// READ - step 4 : wait until start operation bit clears
+	i = CMD_COMPLETE_TOUT_SEC;
+	while (i) {
+		long_delay (1 * HZ / 100);
+		(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET;
+		wpg_data = readl (wpg_addr);
+		data = swab32 (wpg_data);
+		if (!(data & WPG_I2CMCNTL_STARTOP_MASK))
+			break;
+		i--;
+	}
+	if (i == 0) {
+		debug ("%s - Error : WPG timeout\n", __FUNCTION__);
+		return HPC_ERROR;
+	}
+	//--------------------------------------------------------------------
+	// READ - step 5 : read I2C status register
+	i = CMD_COMPLETE_TOUT_SEC;
+	while (i) {
+		long_delay (1 * HZ / 100);
+		(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CSTAT_OFFSET;
+		wpg_data = readl (wpg_addr);
+		data = swab32 (wpg_data);
+		if (HPC_I2CSTATUS_CHECK (data))
+			break;
+		i--;
+	}
+	if (i == 0) {
+		debug ("ctrl_read - Exit Error:I2C timeout\n");
+		return HPC_ERROR;
+	}
+
+	//--------------------------------------------------------------------
+	// READ - step 6 : get DATA
+	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMBUFL_OFFSET;
+	wpg_data = readl (wpg_addr);
+	data = swab32 (wpg_data);
+
+	status = (u8) data;
+
+	debug_polling ("%s - Exit index[%x] status[%x]\n", __FUNCTION__, index, status);
+
+	return (status);
+}
+
+/*----------------------------------------------------------------------
+* Name:    i2c_ctrl_write
+*
+* Action:  write to HPC over I2C
+*
+* Return   0 or error codes
+*---------------------------------------------------------------------*/
+static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void *WPGBbar, u8 index, u8 cmd)
+{
+	u8 rc;
+	void *wpg_addr;		// base addr + offset
+	ulong wpg_data,		// data to/from WPG LOHI format 
+	ultemp, data;		// actual data HILO format
+	int i;
+
+
+	debug_polling ("%s - Entry WPGBbar[%lx] index[%x] cmd[%x]\n", __FUNCTION__, (ulong) WPGBbar, index, cmd);
+
+	rc = 0;
+	//--------------------------------------------------------------------
+	// WRITE - step 1
+	// write at address, byte length, I2C address (shifted), index
+	// or write direct, byte length, index
+	data = 0x00000000;
+
+	if (ctlr_ptr->ctlr_type == 0x02) {
+		data = WPG_WRITEATADDR_MASK;
+		// fill in I2C address
+		ultemp = (ulong) ctlr_ptr->u.wpeg_ctlr.i2c_addr;
+		ultemp = ultemp >> 1;
+		data |= (ultemp << 8);
+
+		// fill in index
+		data |= (ulong) index;
+	} else if (ctlr_ptr->ctlr_type == 0x04) {
+		data = WPG_WRITEDIRECT_MASK;
+
+		// fill in index
+		ultemp = (ulong) index;
+		ultemp = ultemp << 8;
+		data |= ultemp;
+	} else {
+		err ("this controller type is not supported \n");
+		return HPC_ERROR;
+	}
+
+	wpg_data = swab32 (data);	// swap data before writing
+	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMOSUP_OFFSET;
+	writel (wpg_data, wpg_addr);
+
+	//--------------------------------------------------------------------
+	// WRITE - step 2 : clear the message buffer
+	data = 0x00000000 | (ulong) cmd;
+	wpg_data = swab32 (data);
+	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMBUFL_OFFSET;
+	writel (wpg_data, wpg_addr);
+
+	//--------------------------------------------------------------------
+	// WRITE - step 3 : issue start operation,I2C master control bit 30:ON
+	//                 2020 : [20] OR operation at [20] offset 0x20
+	data = WPG_I2CMCNTL_STARTOP_MASK;
+	wpg_data = swab32 (data);
+	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET + (ulong) WPG_I2C_OR;
+	writel (wpg_data, wpg_addr);
+
+	//--------------------------------------------------------------------
+	// WRITE - step 4 : wait until start operation bit clears
+	i = CMD_COMPLETE_TOUT_SEC;
+	while (i) {
+		long_delay (1 * HZ / 100);
+		(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET;
+		wpg_data = readl (wpg_addr);
+		data = swab32 (wpg_data);
+		if (!(data & WPG_I2CMCNTL_STARTOP_MASK))
+			break;
+		i--;
+	}
+	if (i == 0) {
+		debug ("%s - Exit Error:WPG timeout\n", __FUNCTION__);
+		rc = HPC_ERROR;
+	}
+
+	//--------------------------------------------------------------------
+	// WRITE - step 5 : read I2C status register
+	i = CMD_COMPLETE_TOUT_SEC;
+	while (i) {
+		long_delay (1 * HZ / 100);
+		(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CSTAT_OFFSET;
+		wpg_data = readl (wpg_addr);
+		data = swab32 (wpg_data);
+		if (HPC_I2CSTATUS_CHECK (data))
+			break;
+		i--;
+	}
+	if (i == 0) {
+		debug ("ctrl_read - Error : I2C timeout\n");
+		rc = HPC_ERROR;
+	}
+
+	debug_polling ("%s Exit rc[%x]\n", __FUNCTION__, rc);
+	return (rc);
+}
+
+//------------------------------------------------------------
+//  Read from ISA type HPC 
+//------------------------------------------------------------
+static u8 isa_ctrl_read (struct controller *ctlr_ptr, u8 offset)
+{
+	u16 start_address;
+	u16 end_address;
+	u8 data;
+
+	start_address = ctlr_ptr->u.isa_ctlr.io_start;
+	end_address = ctlr_ptr->u.isa_ctlr.io_end;
+	data = inb (start_address + offset);
+	return data;
+}
+
+//--------------------------------------------------------------
+// Write to ISA type HPC
+//--------------------------------------------------------------
+static void isa_ctrl_write (struct controller *ctlr_ptr, u8 offset, u8 data)
+{
+	u16 start_address;
+	u16 port_address;
+	
+	start_address = ctlr_ptr->u.isa_ctlr.io_start;
+	port_address = start_address + (u16) offset;
+	outb (data, port_address);
+}
+
+static u8 pci_ctrl_read (struct controller *ctrl, u8 offset)
+{
+	u8 data = 0x00;
+	debug ("inside pci_ctrl_read\n");
+	if (ctrl->ctrl_dev)
+		pci_read_config_byte (ctrl->ctrl_dev, HPC_PCI_OFFSET + offset, &data);
+	return data;
+}
+
+static u8 pci_ctrl_write (struct controller *ctrl, u8 offset, u8 data)
+{
+	u8 rc = -ENODEV;
+	debug ("inside pci_ctrl_write\n");
+	if (ctrl->ctrl_dev) {
+		pci_write_config_byte (ctrl->ctrl_dev, HPC_PCI_OFFSET + offset, data);
+		rc = 0;
+	}
+	return rc;
+}
+
+static u8 ctrl_read (struct controller *ctlr, void *base, u8 offset)
+{
+	u8 rc;
+	switch (ctlr->ctlr_type) {
+	case 0:
+		rc = isa_ctrl_read (ctlr, offset);
+		break;
+	case 1:
+		rc = pci_ctrl_read (ctlr, offset);
+		break;
+	case 2:
+	case 4:
+		rc = i2c_ctrl_read (ctlr, base, offset);
+		break;
+	default:
+		return -ENODEV;
+	}
+	return rc;
+}
+
+static u8 ctrl_write (struct controller *ctlr, void *base, u8 offset, u8 data)
+{
+	u8 rc = 0;
+	switch (ctlr->ctlr_type) {
+	case 0:
+		isa_ctrl_write(ctlr, offset, data);
+		break;
+	case 1:
+		rc = pci_ctrl_write (ctlr, offset, data);
+		break;
+	case 2:
+	case 4:
+		rc = i2c_ctrl_write(ctlr, base, offset, data);
+		break;
+	default:
+		return -ENODEV;
+	}
+	return rc;
+}
+/*----------------------------------------------------------------------
+* Name:    hpc_writecmdtoindex()
+*
+* Action:  convert a write command to proper index within a controller
+*
+* Return   index, HPC_ERROR
+*---------------------------------------------------------------------*/
+static u8 hpc_writecmdtoindex (u8 cmd, u8 index)
+{
+	u8 rc;
+
+	switch (cmd) {
+	case HPC_CTLR_ENABLEIRQ:	// 0x00.N.15
+	case HPC_CTLR_CLEARIRQ:	// 0x06.N.15
+	case HPC_CTLR_RESET:	// 0x07.N.15
+	case HPC_CTLR_IRQSTEER:	// 0x08.N.15
+	case HPC_CTLR_DISABLEIRQ:	// 0x01.N.15
+	case HPC_ALLSLOT_ON:	// 0x11.N.15
+	case HPC_ALLSLOT_OFF:	// 0x12.N.15
+		rc = 0x0F;
+		break;
+
+	case HPC_SLOT_OFF:	// 0x02.Y.0-14
+	case HPC_SLOT_ON:	// 0x03.Y.0-14
+	case HPC_SLOT_ATTNOFF:	// 0x04.N.0-14
+	case HPC_SLOT_ATTNON:	// 0x05.N.0-14
+	case HPC_SLOT_BLINKLED:	// 0x13.N.0-14
+		rc = index;
+		break;
+
+	case HPC_BUS_33CONVMODE:
+	case HPC_BUS_66CONVMODE:
+	case HPC_BUS_66PCIXMODE:
+	case HPC_BUS_100PCIXMODE:
+	case HPC_BUS_133PCIXMODE:
+		rc = index + WPG_1ST_BUS_INDEX - 1;
+		break;
+
+	default:
+		err ("hpc_writecmdtoindex - Error invalid cmd[%x]\n", cmd);
+		rc = HPC_ERROR;
+	}
+
+	return rc;
+}
+
+/*----------------------------------------------------------------------
+* Name:    hpc_readcmdtoindex()
+*
+* Action:  convert a read command to proper index within a controller
+*
+* Return   index, HPC_ERROR
+*---------------------------------------------------------------------*/
+static u8 hpc_readcmdtoindex (u8 cmd, u8 index)
+{
+	u8 rc;
+
+	switch (cmd) {
+	case READ_CTLRSTATUS:
+		rc = 0x0F;
+		break;
+	case READ_SLOTSTATUS:
+	case READ_ALLSTAT:
+		rc = index;
+		break;
+	case READ_EXTSLOTSTATUS:
+		rc = index + WPG_1ST_EXTSLOT_INDEX;
+		break;
+	case READ_BUSSTATUS:
+		rc = index + WPG_1ST_BUS_INDEX - 1;
+		break;
+	case READ_SLOTLATCHLOWREG:
+		rc = 0x28;
+		break;
+	case READ_REVLEVEL:
+		rc = 0x25;
+		break;
+	case READ_HPCOPTIONS:
+		rc = 0x27;
+		break;
+	default:
+		rc = HPC_ERROR;
+	}
+	return rc;
+}
+
+/*----------------------------------------------------------------------
+* Name:    HPCreadslot()
+*
+* Action:  issue a READ command to HPC
+*
+* Input:   pslot   - can not be NULL for READ_ALLSTAT
+*          pstatus - can be NULL for READ_ALLSTAT
+*
+* Return   0 or error codes
+*---------------------------------------------------------------------*/
+int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)
+{
+	void *wpg_bbar = NULL;
+	struct controller *ctlr_ptr;
+	struct list_head *pslotlist;
+	u8 index, status;
+	int rc = 0;
+	int busindex;
+
+	debug_polling ("%s - Entry pslot[%lx] cmd[%x] pstatus[%lx]\n", __FUNCTION__, (ulong) pslot, cmd, (ulong) pstatus);
+
+	if ((pslot == NULL)
+	    || ((pstatus == NULL) && (cmd != READ_ALLSTAT) && (cmd != READ_BUSSTATUS))) {
+		rc = -EINVAL;
+		err ("%s - Error invalid pointer, rc[%d]\n", __FUNCTION__, rc);
+		return rc;
+	}
+
+	if (cmd == READ_BUSSTATUS) {
+		busindex = ibmphp_get_bus_index (pslot->bus);
+		if (busindex < 0) {
+			rc = -EINVAL;
+			err ("%s - Exit Error:invalid bus, rc[%d]\n", __FUNCTION__, rc);
+			return rc;
+		} else
+			index = (u8) busindex;
+	} else
+		index = pslot->ctlr_index;
+
+	index = hpc_readcmdtoindex (cmd, index);
+
+	if (index == HPC_ERROR) {
+		rc = -EINVAL;
+		err ("%s - Exit Error:invalid index, rc[%d]\n", __FUNCTION__, rc);
+		return rc;
+	}
+
+	ctlr_ptr = pslot->ctrl;
+
+	get_hpc_access ();
+
+	//--------------------------------------------------------------------
+	// map physical address to logical address
+	//--------------------------------------------------------------------
+	if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4))
+		wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE);
+
+	//--------------------------------------------------------------------
+	// check controller status before reading
+	//--------------------------------------------------------------------
+	rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, &status);
+	if (!rc) {
+		switch (cmd) {
+		case READ_ALLSTAT:
+			// update the slot structure
+			pslot->ctrl->status = status;
+			pslot->status = ctrl_read (ctlr_ptr, wpg_bbar, index);
+			rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar,
+						       &status);
+			if (!rc)
+				pslot->ext_status = ctrl_read (ctlr_ptr, wpg_bbar, index + WPG_1ST_EXTSLOT_INDEX);
+
+			break;
+
+		case READ_SLOTSTATUS:
+			// DO NOT update the slot structure
+			*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
+			break;
+
+		case READ_EXTSLOTSTATUS:
+			// DO NOT update the slot structure
+			*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
+			break;
+
+		case READ_CTLRSTATUS:
+			// DO NOT update the slot structure
+			*pstatus = status;
+			break;
+
+		case READ_BUSSTATUS:
+			pslot->busstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
+			break;
+		case READ_REVLEVEL:
+			*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
+			break;
+		case READ_HPCOPTIONS:
+			*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
+			break;
+		case READ_SLOTLATCHLOWREG:
+			// DO NOT update the slot structure
+			*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
+			break;
+
+			// Not used
+		case READ_ALLSLOT:
+			list_for_each (pslotlist, &ibmphp_slot_head) {
+				pslot = list_entry (pslotlist, struct slot, ibm_slot_list);
+				index = pslot->ctlr_index;
+				rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr,
+								wpg_bbar, &status);
+				if (!rc) {
+					pslot->status = ctrl_read (ctlr_ptr, wpg_bbar, index);
+					rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT,
+									ctlr_ptr, wpg_bbar, &status);
+					if (!rc)
+						pslot->ext_status =
+						    ctrl_read (ctlr_ptr, wpg_bbar,
+								index + WPG_1ST_EXTSLOT_INDEX);
+				} else {
+					err ("%s - Error ctrl_read failed\n", __FUNCTION__);
+					rc = -EINVAL;
+					break;
+				}
+			}
+			break;
+		default:
+			rc = -EINVAL;
+			break;
+		}
+	}
+	//--------------------------------------------------------------------
+	// cleanup
+	//--------------------------------------------------------------------
+	
+	// remove physical to logical address mapping
+	if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4))
+		iounmap (wpg_bbar);	
+	
+	free_hpc_access ();
+
+	debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
+	return rc;
+}
+
+/*----------------------------------------------------------------------
+* Name:    ibmphp_hpc_writeslot()
+*
+* Action: issue a WRITE command to HPC
+*---------------------------------------------------------------------*/
+int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
+{
+	void *wpg_bbar = NULL;
+	struct controller *ctlr_ptr;
+	u8 index, status;
+	int busindex;
+	u8 done;
+	int rc = 0;
+	int timeout;
+
+	debug_polling ("%s - Entry pslot[%lx] cmd[%x]\n", __FUNCTION__, (ulong) pslot, cmd);
+	if (pslot == NULL) {
+		rc = -EINVAL;
+		err ("%s - Error Exit rc[%d]\n", __FUNCTION__, rc);
+		return rc;
+	}
+
+	if ((cmd == HPC_BUS_33CONVMODE) || (cmd == HPC_BUS_66CONVMODE) ||
+		(cmd == HPC_BUS_66PCIXMODE) || (cmd == HPC_BUS_100PCIXMODE) ||
+		(cmd == HPC_BUS_133PCIXMODE)) {
+		busindex = ibmphp_get_bus_index (pslot->bus);
+		if (busindex < 0) {
+			rc = -EINVAL;
+			err ("%s - Exit Error:invalid bus, rc[%d]\n", __FUNCTION__, rc);
+			return rc;
+		} else
+			index = (u8) busindex;
+	} else
+		index = pslot->ctlr_index;
+
+	index = hpc_writecmdtoindex (cmd, index);
+
+	if (index == HPC_ERROR) {
+		rc = -EINVAL;
+		err ("%s - Error Exit rc[%d]\n", __FUNCTION__, rc);
+		return rc;
+	}
+
+	ctlr_ptr = pslot->ctrl;
+
+	get_hpc_access ();
+
+	//--------------------------------------------------------------------
+	// map physical address to logical address
+	//--------------------------------------------------------------------
+	if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) {
+		wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE);
+
+		debug ("%s - ctlr id[%x] physical[%lx] logical[%lx] i2c[%x]\n", __FUNCTION__,
+		ctlr_ptr->ctlr_id, (ulong) (ctlr_ptr->u.wpeg_ctlr.wpegbbar), (ulong) wpg_bbar,
+		ctlr_ptr->u.wpeg_ctlr.i2c_addr);
+	}
+	//--------------------------------------------------------------------
+	// check controller status before writing
+	//--------------------------------------------------------------------
+	rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, &status);
+	if (!rc) {
+
+		ctrl_write (ctlr_ptr, wpg_bbar, index, cmd);
+
+		//--------------------------------------------------------------------
+		// check controller is still not working on the command
+		//--------------------------------------------------------------------
+		timeout = CMD_COMPLETE_TOUT_SEC;
+		done = FALSE;
+		while (!done) {
+			rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar,
+							&status);
+			if (!rc) {
+				if (NEEDTOCHECK_CMDSTATUS (cmd)) {
+					if (CTLR_FINISHED (status) == HPC_CTLR_FINISHED_YES)
+						done = TRUE;
+				} else
+					done = TRUE;
+			}
+			if (!done) {
+				long_delay (1 * HZ);
+				if (timeout < 1) {
+					done = TRUE;
+					err ("%s - Error command complete timeout\n", __FUNCTION__);
+					rc = -EFAULT;
+				} else
+					timeout--;
+			}
+		}
+		ctlr_ptr->status = status;
+	}
+	// cleanup
+
+	// remove physical to logical address mapping
+	if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4))
+		iounmap (wpg_bbar);	
+	free_hpc_access ();
+
+	debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
+	return rc;
+}
+
+/*----------------------------------------------------------------------
+* Name:    get_hpc_access()
+*
+* Action: make sure only one process can access HPC at one time
+*---------------------------------------------------------------------*/
+static void get_hpc_access (void)
+{
+	down (&sem_hpcaccess);
+}
+
+/*----------------------------------------------------------------------
+* Name:    free_hpc_access()
+*---------------------------------------------------------------------*/
+void free_hpc_access (void)
+{
+	up (&sem_hpcaccess);
+}
+
+/*----------------------------------------------------------------------
+* Name:    ibmphp_lock_operations()
+*
+* Action: make sure only one process can change the data structure
+*---------------------------------------------------------------------*/
+void ibmphp_lock_operations (void)
+{
+	down (&semOperations);
+	to_debug = TRUE;
+}
+
+/*----------------------------------------------------------------------
+* Name:    ibmphp_unlock_operations()
+*---------------------------------------------------------------------*/
+void ibmphp_unlock_operations (void)
+{
+	debug ("%s - Entry\n", __FUNCTION__);
+	up (&semOperations);
+	to_debug = FALSE;
+	debug ("%s - Exit\n", __FUNCTION__);
+}
+
+/*----------------------------------------------------------------------
+* Name:    poll_hpc()
+*---------------------------------------------------------------------*/
+#define POLL_LATCH_REGISTER	0
+#define POLL_SLOTS		1
+#define POLL_SLEEP		2
+static void poll_hpc (void)
+{
+	struct slot myslot;
+	struct slot *pslot = NULL;
+	struct list_head *pslotlist;
+	int rc;
+	int poll_state = POLL_LATCH_REGISTER;
+	u8 oldlatchlow = 0x00;
+	u8 curlatchlow = 0x00;
+	int poll_count = 0;
+	u8 ctrl_count = 0x00;
+
+	debug ("%s - Entry\n", __FUNCTION__);
+
+	while (!ibmphp_shutdown) {
+		if (ibmphp_shutdown) 
+			break;
+		
+		/* try to get the lock to do some kind of harware access */
+		down (&semOperations);
+
+		switch (poll_state) {
+		case POLL_LATCH_REGISTER: 
+			oldlatchlow = curlatchlow;
+			ctrl_count = 0x00;
+			list_for_each (pslotlist, &ibmphp_slot_head) {
+				if (ctrl_count >= ibmphp_get_total_controllers())
+					break;
+				pslot = list_entry (pslotlist, struct slot, ibm_slot_list);
+				if (pslot->ctrl->ctlr_relative_id == ctrl_count) {
+					ctrl_count++;
+					if (READ_SLOT_LATCH (pslot->ctrl)) {
+						rc = ibmphp_hpc_readslot (pslot,
+									  READ_SLOTLATCHLOWREG,
+									  &curlatchlow);
+						if (oldlatchlow != curlatchlow)
+							process_changeinlatch (oldlatchlow,
+									       curlatchlow,
+									       pslot->ctrl);
+					}
+				}
+			}
+			++poll_count;
+			poll_state = POLL_SLEEP;
+			break;
+		case POLL_SLOTS:
+			list_for_each (pslotlist, &ibmphp_slot_head) {
+				pslot = list_entry (pslotlist, struct slot, ibm_slot_list);
+				// make a copy of the old status
+				memcpy ((void *) &myslot, (void *) pslot,
+					sizeof (struct slot));
+				rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL);
+				if ((myslot.status != pslot->status)
+				    || (myslot.ext_status != pslot->ext_status))
+					process_changeinstatus (pslot, &myslot);
+			}
+			ctrl_count = 0x00;
+			list_for_each (pslotlist, &ibmphp_slot_head) {
+				if (ctrl_count >= ibmphp_get_total_controllers())
+					break;
+				pslot = list_entry (pslotlist, struct slot, ibm_slot_list);
+				if (pslot->ctrl->ctlr_relative_id == ctrl_count) {
+					ctrl_count++;
+					if (READ_SLOT_LATCH (pslot->ctrl))
+						rc = ibmphp_hpc_readslot (pslot,
+									  READ_SLOTLATCHLOWREG,
+									  &curlatchlow);
+				}
+			}
+			++poll_count;
+			poll_state = POLL_SLEEP;
+			break;
+		case POLL_SLEEP:
+			/* don't sleep with a lock on the hardware */
+			up (&semOperations);
+			long_delay (POLL_INTERVAL_SEC * HZ);
+
+			if (ibmphp_shutdown) 
+				break;
+			
+			down (&semOperations);
+			
+			if (poll_count >= POLL_LATCH_CNT) {
+				poll_count = 0;
+				poll_state = POLL_SLOTS;
+			} else
+				poll_state = POLL_LATCH_REGISTER;
+			break;
+		}	
+		/* give up the harware semaphore */
+		up (&semOperations);
+		/* sleep for a short time just for good measure */
+		set_current_state (TASK_INTERRUPTIBLE);
+		schedule_timeout (HZ/10);
+	}
+	up (&sem_exit);
+	debug ("%s - Exit\n", __FUNCTION__);
+}
+
+
+/* ----------------------------------------------------------------------
+ *  Name:    ibmphp_hpc_fillhpslotinfo(hotplug_slot * phpslot)
+ *
+ *  Action:  fill out the hotplug_slot info
+ *
+ *  Input:   pointer to hotplug_slot
+ *
+ *  Return
+ *  Value:   0 or error codes
+ *-----------------------------------------------------------------------*/
+int ibmphp_hpc_fillhpslotinfo (struct hotplug_slot *phpslot)
+{
+	int rc = 0;
+	struct slot *pslot;
+
+	if (phpslot && phpslot->private) {
+		pslot = (struct slot *) phpslot->private;
+		rc = update_slot (pslot, (u8) TRUE);
+		if (!rc) {
+
+			// power - enabled:1  not:0
+			phpslot->info->power_status = SLOT_POWER (pslot->status);
+
+			// attention - off:0, on:1, blinking:2
+			phpslot->info->attention_status = SLOT_ATTN (pslot->status, pslot->ext_status);
+
+			// latch - open:1 closed:0
+			phpslot->info->latch_status = SLOT_LATCH (pslot->status);
+
+			// pci board - present:1 not:0
+			if (SLOT_PRESENT (pslot->status))
+				phpslot->info->adapter_status = 1;
+			else
+				phpslot->info->adapter_status = 0;
+/*
+			if (pslot->bus_on->supported_bus_mode
+				&& (pslot->bus_on->supported_speed == BUS_SPEED_66))
+				phpslot->info->max_bus_speed_status = BUS_SPEED_66PCIX;
+			else
+				phpslot->info->max_bus_speed_status = pslot->bus_on->supported_speed;
+*/		} else
+			rc = -EINVAL;
+	} else
+		rc = -EINVAL;
+
+	return rc;
+}
+
+/*----------------------------------------------------------------------
+* Name:    update_slot
+*
+* Action:  fill out slot status and extended status, controller status
+*
+* Input:   pointer to slot struct
+*---------------------------------------------------------------------*/
+static int update_slot (struct slot *pslot, u8 update)
+{
+	int rc = 0;
+
+	debug ("%s - Entry pslot[%lx]\n", __FUNCTION__, (ulong) pslot);
+	rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL);
+	debug ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
+	return rc;
+}
+
+/*----------------------------------------------------------------------
+* Name:    process_changeinstatus
+*
+* Action:  compare old and new slot status, process the change in status
+*
+* Input:   pointer to slot struct, old slot struct
+*
+* Return   0 or error codes
+* Value:
+*
+* Side
+* Effects: None.
+*
+* Notes:
+*---------------------------------------------------------------------*/
+static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)
+{
+	u8 status;
+	int rc = 0;
+	u8 disable = FALSE;
+	u8 update = FALSE;
+
+	debug ("process_changeinstatus - Entry pslot[%lx], poldslot[%lx]\n", (ulong) pslot,
+	       (ulong) poldslot);
+
+	// bit 0 - HPC_SLOT_POWER
+	if ((pslot->status & 0x01) != (poldslot->status & 0x01))
+		update = TRUE;
+
+	// bit 1 - HPC_SLOT_CONNECT
+	// ignore
+
+	// bit 2 - HPC_SLOT_ATTN
+	if ((pslot->status & 0x04) != (poldslot->status & 0x04))
+		update = TRUE;
+
+	// bit 3 - HPC_SLOT_PRSNT2
+	// bit 4 - HPC_SLOT_PRSNT1
+	if (((pslot->status & 0x08) != (poldslot->status & 0x08))
+		|| ((pslot->status & 0x10) != (poldslot->status & 0x10)))
+		update = TRUE;
+
+	// bit 5 - HPC_SLOT_PWRGD
+	if ((pslot->status & 0x20) != (poldslot->status & 0x20))
+		// OFF -> ON: ignore, ON -> OFF: disable slot
+		if ((poldslot->status & 0x20) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) 
+			disable = TRUE;
+
+	// bit 6 - HPC_SLOT_BUS_SPEED
+	// ignore
+
+	// bit 7 - HPC_SLOT_LATCH
+	if ((pslot->status & 0x80) != (poldslot->status & 0x80)) {
+		update = TRUE;
+		// OPEN -> CLOSE
+		if (pslot->status & 0x80) {
+			if (SLOT_PWRGD (pslot->status)) {
+				// power goes on and off after closing latch
+				// check again to make sure power is still ON
+				long_delay (1 * HZ);
+				rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status);
+				if (SLOT_PWRGD (status))
+					update = TRUE;
+				else	// overwrite power in pslot to OFF
+					pslot->status &= ~HPC_SLOT_POWER;
+			}
+		}
+		// CLOSE -> OPEN 
+		else if ((SLOT_PWRGD (poldslot->status) == HPC_SLOT_PWRGD_GOOD)
+			&& (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) {
+			disable = TRUE;
+		}
+		// else - ignore
+	}
+	// bit 4 - HPC_SLOT_BLINK_ATTN
+	if ((pslot->ext_status & 0x08) != (poldslot->ext_status & 0x08))
+		update = TRUE;
+
+	if (disable) {
+		debug ("process_changeinstatus - disable slot\n");
+		pslot->flag = FALSE;
+		rc = ibmphp_do_disable_slot (pslot);
+	}
+
+	if (update || disable) {
+		ibmphp_update_slot_info (pslot);
+	}
+
+	debug ("%s - Exit rc[%d] disable[%x] update[%x]\n", __FUNCTION__, rc, disable, update);
+
+	return rc;
+}
+
+/*----------------------------------------------------------------------
+* Name:    process_changeinlatch
+*
+* Action:  compare old and new latch reg status, process the change
+*
+* Input:   old and current latch register status
+*
+* Return   0 or error codes
+* Value:
+*---------------------------------------------------------------------*/
+static int process_changeinlatch (u8 old, u8 new, struct controller *ctrl)
+{
+	struct slot myslot, *pslot;
+	u8 i;
+	u8 mask;
+	int rc = 0;
+
+	debug ("%s - Entry old[%x], new[%x]\n", __FUNCTION__, old, new);
+	// bit 0 reserved, 0 is LSB, check bit 1-6 for 6 slots
+
+	for (i = ctrl->starting_slot_num; i <= ctrl->ending_slot_num; i++) {
+		mask = 0x01 << i;
+		if ((mask & old) != (mask & new)) {
+			pslot = ibmphp_get_slot_from_physical_num (i);
+			if (pslot) {
+				memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
+				rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL);
+				debug ("%s - call process_changeinstatus for slot[%d]\n", __FUNCTION__, i);
+				process_changeinstatus (pslot, &myslot);
+			} else {
+				rc = -EINVAL;
+				err ("%s - Error bad pointer for slot[%d]\n", __FUNCTION__, i);
+			}
+		}
+	}
+	debug ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
+	return rc;
+}
+
+/*----------------------------------------------------------------------
+* Name:    hpc_poll_thread
+*
+* Action:  polling
+*
+* Return   0
+* Value:
+*---------------------------------------------------------------------*/
+static int hpc_poll_thread (void *data)
+{
+	debug ("%s - Entry\n", __FUNCTION__);
+
+	daemonize("hpc_poll");
+	allow_signal(SIGKILL);
+
+	poll_hpc ();
+
+	tid_poll = 0;
+	debug ("%s - Exit\n", __FUNCTION__);
+	return 0;
+}
+
+
+/*----------------------------------------------------------------------
+* Name:    ibmphp_hpc_start_poll_thread
+*
+* Action:  start polling thread
+*---------------------------------------------------------------------*/
+int __init ibmphp_hpc_start_poll_thread (void)
+{
+	int rc = 0;
+
+	debug ("%s - Entry\n", __FUNCTION__);
+
+	tid_poll = kernel_thread (hpc_poll_thread, 0, 0);
+	if (tid_poll < 0) {
+		err ("%s - Error, thread not started\n", __FUNCTION__);
+		rc = -1;
+	}
+
+	debug ("%s - Exit tid_poll[%d] rc[%d]\n", __FUNCTION__, tid_poll, rc);
+	return rc;
+}
+
+/*----------------------------------------------------------------------
+* Name:    ibmphp_hpc_stop_poll_thread
+*
+* Action:  stop polling thread and cleanup
+*---------------------------------------------------------------------*/
+void __exit ibmphp_hpc_stop_poll_thread (void)
+{
+	debug ("%s - Entry\n", __FUNCTION__);
+
+	ibmphp_shutdown = TRUE;
+	debug ("before locking operations \n");
+	ibmphp_lock_operations ();
+	debug ("after locking operations \n");
+	
+	// wait for poll thread to exit
+	debug ("before sem_exit down \n");
+	down (&sem_exit);
+	debug ("after sem_exit down \n");
+
+	// cleanup
+	debug ("before free_hpc_access \n");
+	free_hpc_access ();
+	debug ("after free_hpc_access \n");
+	ibmphp_unlock_operations ();
+	debug ("after unlock operations \n");
+	up (&sem_exit);
+	debug ("after sem exit up\n");
+
+	debug ("%s - Exit\n", __FUNCTION__);
+}
+
+/*----------------------------------------------------------------------
+* Name:    hpc_wait_ctlr_notworking
+*
+* Action:  wait until the controller is in a not working state
+*
+* Return   0, HPC_ERROR
+* Value:
+*---------------------------------------------------------------------*/
+static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, void *wpg_bbar,
+				    u8 * pstatus)
+{
+	int rc = 0;
+	u8 done = FALSE;
+
+	debug_polling ("hpc_wait_ctlr_notworking - Entry timeout[%d]\n", timeout);
+
+	while (!done) {
+		*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, WPG_CTLR_INDEX);
+		if (*pstatus == HPC_ERROR) {
+			rc = HPC_ERROR;
+			done = TRUE;
+		}
+		if (CTLR_WORKING (*pstatus) == HPC_CTLR_WORKING_NO)
+			done = TRUE;
+		if (!done) {
+			long_delay (1 * HZ);
+			if (timeout < 1) {
+				done = TRUE;
+				err ("HPCreadslot - Error ctlr timeout\n");
+				rc = HPC_ERROR;
+			} else
+				timeout--;
+		}
+	}
+	debug_polling ("hpc_wait_ctlr_notworking - Exit rc[%x] status[%x]\n", rc, *pstatus);
+	return rc;
+}
diff -Nru a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/ibmphp_pci.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,1758 @@
+/*
+ * IBM Hot Plug Controller Driver
+ * 
+ * Written By: Irene Zubarev, IBM Corporation
+ * 
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001,2002 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gregkh@us.ibm.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include "ibmphp.h"
+
+
+static int configure_device(struct pci_func *);
+static int configure_bridge(struct pci_func **, u8);
+static struct res_needed *scan_behind_bridge(struct pci_func *, u8);
+static int add_new_bus (struct bus_node *, struct resource_node *, struct resource_node *, struct resource_node *, u8);
+static u8 find_sec_number (u8 primary_busno, u8 slotno);
+
+/*
+ * NOTE..... If BIOS doesn't provide default routing, we assign:
+ * 9 for SCSI, 10 for LAN adapters, and 11 for everything else. 
+ * If adapter is bridged, then we assign 11 to it and devices behind it.
+ * We also assign the same irq numbers for multi function devices.
+ * These are PIC mode, so shouldn't matter n.e.ways (hopefully)
+ */
+static void assign_alt_irq (struct pci_func * cur_func, u8 class_code)
+{
+	int j = 0;
+	for (j = 0; j < 4; j++) {
+		if (cur_func->irq[j] == 0xff) {
+			switch (class_code) {
+				case PCI_BASE_CLASS_STORAGE:
+					cur_func->irq[j] = SCSI_IRQ;
+					break;
+				case PCI_BASE_CLASS_NETWORK:
+					cur_func->irq[j] = LAN_IRQ;
+					break;
+				default:
+					cur_func->irq[j] = OTHER_IRQ;
+					break;
+			}
+		}
+	}
+}
+
+/*
+ * Configures the device to be added (will allocate needed resources if it
+ * can), the device can be a bridge or a regular pci device, can also be
+ * multi-functional
+ * 
+ * Input: function to be added
+ * 
+ * TO DO:  The error case with Multifunction device or multi function bridge,
+ * if there is an error, will need to go through all previous functions and 
+ * unconfigure....or can add some code into unconfigure_card....
+ */
+int ibmphp_configure_card (struct pci_func *func, u8 slotno)
+{
+	u16 vendor_id;
+	u32 class;
+	u8 class_code;
+	u8 hdr_type, device, sec_number;
+	u8 function;
+	struct pci_func *newfunc;	/* for multi devices */
+	struct pci_func *cur_func, *prev_func;
+	int rc, i, j;
+	int cleanup_count;
+	u8 flag;
+	u8 valid_device = 0x00; /* to see if we are able to read from card any device info at all */
+
+	debug ("inside configure_card, func->busno = %x \n", func->busno);
+
+	device = func->device;
+	cur_func = func;
+
+	/* We only get bus and device from IRQ routing table.  So at this point,
+	 * func->busno is correct, and func->device contains only device (at the 5 
+	 * highest bits)
+	 */
+
+	/* For every function on the card */
+	for (function = 0x00; function < 0x08; function++) {
+		unsigned int devfn = PCI_DEVFN(device, function);
+		ibmphp_pci_bus->number = cur_func->busno;
+
+		cur_func->function = function;
+
+		debug ("inside the loop, cur_func->busno = %x, cur_func->device = %x, cur_func->funcion = %x\n",
+			cur_func->busno, cur_func->device, cur_func->function);
+
+		pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id);
+
+		debug ("vendor_id is %x\n", vendor_id);
+		if (vendor_id != PCI_VENDOR_ID_NOTVALID) {
+			/* found correct device!!! */
+			debug ("found valid device, vendor_id = %x\n", vendor_id);
+
+			++valid_device;
+
+			/* header: x x x x x x x x
+			 *         | |___________|=> 1=PPB bridge, 0=normal device, 2=CardBus Bridge
+			 *         |_=> 0 = single function device, 1 = multi-function device
+			 */
+
+			pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type);
+			pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class);
+
+			class_code = class >> 24;
+			debug ("hrd_type = %x, class = %x, class_code %x \n", hdr_type, class, class_code);
+			class >>= 8;	/* to take revision out, class = class.subclass.prog i/f */
+			if (class == PCI_CLASS_NOT_DEFINED_VGA) {
+				err ("The device %x is VGA compatible and as is not supported for hot plugging. "
+				     "Please choose another device.\n", cur_func->device);
+				return -ENODEV;
+			} else if (class == PCI_CLASS_DISPLAY_VGA) {
+				err ("The device %x is not supported for hot plugging. "
+				     "Please choose another device.\n", cur_func->device);
+				return -ENODEV;
+			}
+			switch (hdr_type) {
+				case PCI_HEADER_TYPE_NORMAL:
+					debug ("single device case.... vendor id = %x, hdr_type = %x, class = %x\n", vendor_id, hdr_type, class);
+					assign_alt_irq (cur_func, class_code);
+					if ((rc = configure_device (cur_func)) < 0) {
+						/* We need to do this in case some other BARs were properly inserted */
+						err ("was not able to configure devfunc %x on bus %x. \n",
+						     cur_func->device, cur_func->busno);
+						cleanup_count = 6;
+						goto error;
+					}	
+					cur_func->next = NULL;
+					function = 0x8;
+					break;
+				case PCI_HEADER_TYPE_MULTIDEVICE:
+					assign_alt_irq (cur_func, class_code);
+					if ((rc = configure_device (cur_func)) < 0) {
+						/* We need to do this in case some other BARs were properly inserted */
+						err ("was not able to configure devfunc %x on bus %x...bailing out\n",
+						     cur_func->device, cur_func->busno);
+						cleanup_count = 6;
+						goto error;
+					}
+					newfunc = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
+					if (!newfunc) {
+						err ("out of system memory \n");
+						return -ENOMEM;
+					}
+					memset (newfunc, 0, sizeof (struct pci_func));
+					newfunc->busno = cur_func->busno;
+					newfunc->device = device;
+					cur_func->next = newfunc;
+					cur_func = newfunc;
+					for (j = 0; j < 4; j++)
+						newfunc->irq[j] = cur_func->irq[j];
+					break;
+				case PCI_HEADER_TYPE_MULTIBRIDGE:
+					class >>= 8;
+					if (class != PCI_CLASS_BRIDGE_PCI) {
+						err ("This %x is not PCI-to-PCI bridge, and as is not supported for hot-plugging. "
+						     "Please insert another card.\n", cur_func->device);
+						return -ENODEV;
+					}
+					assign_alt_irq (cur_func, class_code);
+					rc = configure_bridge (&cur_func, slotno);
+					if (rc == -ENODEV) {
+						err ("You chose to insert Single Bridge, or nested bridges, this is not supported...\n");
+						err ("Bus %x, devfunc %x \n", cur_func->busno, cur_func->device);
+						return rc;
+					}
+					if (rc) {
+						/* We need to do this in case some other BARs were properly inserted */
+						err ("was not able to hot-add PPB properly.\n");
+						func->bus = 1; /* To indicate to the unconfigure function that this is a PPB */
+						cleanup_count = 2;
+						goto error;
+					}
+
+					pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
+					flag = FALSE;
+					for (i = 0; i < 32; i++) {
+						if (func->devices[i]) {
+							newfunc = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
+							if (!newfunc) {
+								err ("out of system memory \n");
+								return -ENOMEM;
+							}
+							memset (newfunc, 0, sizeof (struct pci_func));
+							newfunc->busno = sec_number;
+							newfunc->device = (u8) i;
+							for (j = 0; j < 4; j++)
+								newfunc->irq[j] = cur_func->irq[j];
+
+							if (flag) {
+								for (prev_func = cur_func; prev_func->next; prev_func = prev_func->next) ;
+								prev_func->next = newfunc;
+							} else
+								cur_func->next = newfunc;
+
+							rc = ibmphp_configure_card (newfunc, slotno);
+							/* This could only happen if kmalloc failed */
+							if (rc) {
+								/* We need to do this in case bridge itself got configured properly, but devices behind it failed */
+								func->bus = 1; /* To indicate to the unconfigure function that this is a PPB */
+								cleanup_count = 2;
+								goto error;
+							}
+							flag = TRUE;
+						}
+					}
+
+					newfunc = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
+					if (!newfunc) {
+						err ("out of system memory \n");
+						return -ENOMEM;
+					}
+					memset (newfunc, 0, sizeof (struct pci_func));
+					newfunc->busno = cur_func->busno;
+					newfunc->device = device;
+					for (j = 0; j < 4; j++)
+						newfunc->irq[j] = cur_func->irq[j];
+					for (prev_func = cur_func; prev_func->next; prev_func = prev_func->next) ;
+					prev_func->next = newfunc;
+					cur_func = newfunc;
+					break;
+				case PCI_HEADER_TYPE_BRIDGE:
+					class >>= 8;
+					debug ("class now is %x\n", class);
+					if (class != PCI_CLASS_BRIDGE_PCI) {
+						err ("This %x is not PCI-to-PCI bridge, and as is not supported for hot-plugging. "
+						     "Please insert another card.\n", cur_func->device);
+						return -ENODEV;
+					}
+
+					assign_alt_irq (cur_func, class_code);
+
+					debug ("cur_func->busno b4 configure_bridge is %x\n", cur_func->busno);
+					rc = configure_bridge (&cur_func, slotno);
+					if (rc == -ENODEV) {
+						err ("You chose to insert Single Bridge, or nested bridges, this is not supported...\n");
+						err ("Bus %x, devfunc %x \n", cur_func->busno, cur_func->device);
+						return rc;
+					}
+					if (rc) {
+						/* We need to do this in case some other BARs were properly inserted */
+						func->bus = 1; /* To indicate to the unconfigure function that this is a PPB */
+						err ("was not able to hot-add PPB properly.\n");
+						cleanup_count = 2;
+						goto error;
+					}
+					debug ("cur_func->busno = %x, device = %x, function = %x\n",
+						cur_func->busno, device, function);
+					pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
+					debug ("after configuring bridge..., sec_number = %x\n", sec_number);
+					flag = FALSE;
+					for (i = 0; i < 32; i++) {
+						if (func->devices[i]) {
+							debug ("inside for loop, device is %x\n", i);
+							newfunc = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
+							if (!newfunc) {
+								err (" out of system memory \n");
+								return -ENOMEM;
+							}
+							memset (newfunc, 0, sizeof (struct pci_func));
+							newfunc->busno = sec_number;
+							newfunc->device = (u8) i;
+							for (j = 0; j < 4; j++)
+								newfunc->irq[j] = cur_func->irq[j];
+
+							if (flag) {
+								for (prev_func = cur_func; prev_func->next; prev_func = prev_func->next) ;
+								prev_func->next = newfunc;
+							} else
+								cur_func->next = newfunc;
+
+							rc = ibmphp_configure_card (newfunc, slotno);
+
+							/* Again, this case should not happen... For complete paranoia, will need to call remove_bus */
+							if (rc) {
+								/* We need to do this in case some other BARs were properly inserted */
+								func->bus = 1; /* To indicate to the unconfigure function that this is a PPB */
+								cleanup_count = 2;
+								goto error;
+							}
+							flag = TRUE;
+						}
+					}
+
+					function = 0x8;
+					break;
+				default:
+					err ("MAJOR PROBLEM!!!!, header type not supported? %x\n", hdr_type);
+					return -ENXIO;
+					break;
+			}	/* end of switch */
+		}	/* end of valid device */
+	}	/* end of for */
+
+	if (!valid_device) {
+		err ("Cannot find any valid devices on the card.  Or unable to read from card.\n");
+		return -ENODEV;
+	}
+
+	return 0;
+
+error:
+	for (i = 0; i < cleanup_count; i++) {
+		if (cur_func->io[i]) {
+			ibmphp_remove_resource (cur_func->io[i]);
+			cur_func->io[i] = NULL;
+		} else if (cur_func->pfmem[i]) {
+			ibmphp_remove_resource (cur_func->pfmem[i]);
+			cur_func->pfmem[i] = NULL;
+		} else if (cur_func->mem[i]) {
+			ibmphp_remove_resource (cur_func->mem[i]);
+			cur_func->mem[i] = NULL;
+		}
+	}
+	return rc;
+}
+
+/*
+ * This function configures the pci BARs of a single device.  
+ * Input: pointer to the pci_func
+ * Output: configured PCI, 0, or error
+ */
+static int configure_device (struct pci_func *func)
+{
+	u32 bar[6];
+	u32 address[] = {
+		PCI_BASE_ADDRESS_0,
+		PCI_BASE_ADDRESS_1,
+		PCI_BASE_ADDRESS_2,
+		PCI_BASE_ADDRESS_3,
+		PCI_BASE_ADDRESS_4,
+		PCI_BASE_ADDRESS_5,
+		0
+	};
+	u8 irq;
+	int count;
+	int len[6];
+	struct resource_node *io[6];
+	struct resource_node *mem[6];
+	struct resource_node *mem_tmp;
+	struct resource_node *pfmem[6];
+	unsigned int devfn;
+
+	debug ("%s - inside\n", __FUNCTION__);
+
+	devfn = PCI_DEVFN(func->device, func->function);
+	ibmphp_pci_bus->number = func->busno;
+
+	for (count = 0; address[count]; count++) {	/* for 6 BARs */
+
+		/* not sure if i need this.  per scott, said maybe need smth like this
+		   if devices don't adhere 100% to the spec, so don't want to write
+		   to the reserved bits
+
+		pcibios_read_config_byte(cur_func->busno, cur_func->device, 
+		PCI_BASE_ADDRESS_0 + 4 * count, &tmp);
+		if (tmp & 0x01) // IO
+			pcibios_write_config_dword(cur_func->busno, cur_func->device, 
+			PCI_BASE_ADDRESS_0 + 4 * count, 0xFFFFFFFD);
+		else  // Memory
+			pcibios_write_config_dword(cur_func->busno, cur_func->device, 
+			PCI_BASE_ADDRESS_0 + 4 * count, 0xFFFFFFFF);
+		 */
+		pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF);
+		pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]);
+
+		if (!bar[count])	/* This BAR is not implemented */
+			continue;
+
+		debug ("Device %x BAR %d wants %x\n", func->device, count, bar[count]);
+
+		if (bar[count] & PCI_BASE_ADDRESS_SPACE_IO) {
+			/* This is IO */
+			debug ("inside IO SPACE\n");
+
+			len[count] = bar[count] & 0xFFFFFFFC;
+			len[count] = ~len[count] + 1;
+
+			debug ("len[count] in IO %x, count %d\n", len[count], count);
+
+			io[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+
+			if (!io[count]) {
+				err ("out of system memory \n");
+				return -ENOMEM;
+			}
+			memset (io[count], 0, sizeof (struct resource_node));
+			io[count]->type = IO;
+			io[count]->busno = func->busno;
+			io[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
+			io[count]->len = len[count];
+			if (ibmphp_check_resource(io[count], 0) == 0) {
+				ibmphp_add_resource (io[count]);
+				func->io[count] = io[count];
+			} else {
+				err ("cannot allocate requested io for bus %x device %x function %x len %x\n",
+				     func->busno, func->device, func->function, len[count]);
+				kfree (io[count]);
+				return -EIO;
+			}
+			pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->io[count]->start);
+	
+			/* _______________This is for debugging purposes only_____________________ */ 
+			debug ("b4 writing, the IO address is %x\n", func->io[count]->start);
+			pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]);
+			debug ("after writing.... the start address is %x\n", bar[count]);
+			/* _________________________________________________________________________*/
+
+		} else {
+			/* This is Memory */
+			if (bar[count] & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+				/* pfmem */
+				debug ("PFMEM SPACE\n");
+
+				len[count] = bar[count] & 0xFFFFFFF0;
+				len[count] = ~len[count] + 1;
+
+				debug ("len[count] in PFMEM %x, count %d\n", len[count], count);
+
+				pfmem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+				if (!pfmem[count]) {
+					err ("out of system memory \n");
+					return -ENOMEM;
+				}
+				memset (pfmem[count], 0, sizeof (struct resource_node));
+				pfmem[count]->type = PFMEM;
+				pfmem[count]->busno = func->busno;
+				pfmem[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
+				pfmem[count]->len = len[count];
+				pfmem[count]->fromMem = FALSE;
+				if (ibmphp_check_resource (pfmem[count], 0) == 0) {
+					ibmphp_add_resource (pfmem[count]);
+					func->pfmem[count] = pfmem[count];
+				} else {
+					mem_tmp = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+					if (!mem_tmp) {
+						err ("out of system memory \n");
+						kfree (pfmem[count]);
+						return -ENOMEM;
+					}
+					memset (mem_tmp, 0, sizeof (struct resource_node));
+					mem_tmp->type = MEM;
+					mem_tmp->busno = pfmem[count]->busno;
+					mem_tmp->devfunc = pfmem[count]->devfunc;
+					mem_tmp->len = pfmem[count]->len;
+					debug ("there's no pfmem... going into mem.\n");
+					if (ibmphp_check_resource (mem_tmp, 0) == 0) {
+						ibmphp_add_resource (mem_tmp);
+						pfmem[count]->fromMem = TRUE;
+						pfmem[count]->rangeno = mem_tmp->rangeno;
+						pfmem[count]->start = mem_tmp->start;
+						pfmem[count]->end = mem_tmp->end;
+						ibmphp_add_pfmem_from_mem (pfmem[count]);
+						func->pfmem[count] = pfmem[count];
+					} else {
+						err ("cannot allocate requested pfmem for bus %x, device %x, len %x\n",
+						     func->busno, func->device, len[count]);
+						kfree (mem_tmp);
+						kfree (pfmem[count]);
+						return -EIO;
+					}
+				}
+
+				pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->pfmem[count]->start);
+
+				/*_______________This is for debugging purposes only______________________________*/				
+				debug ("b4 writing, start address is %x\n", func->pfmem[count]->start);
+				pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]);
+				debug ("after writing, start address is %x\n", bar[count]);
+				/*_________________________________________________________________________________*/
+
+				if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) {	/* takes up another dword */
+					debug ("inside the mem 64 case, count %d\n", count);
+					count += 1;
+					/* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */
+					pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0x00000000);
+				}
+			} else {
+				/* regular memory */
+				debug ("REGULAR MEM SPACE\n");
+
+				len[count] = bar[count] & 0xFFFFFFF0;
+				len[count] = ~len[count] + 1;
+
+				debug ("len[count] in Mem %x, count %d\n", len[count], count);
+
+				mem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+				if (!mem[count]) {
+					err ("out of system memory \n");
+					return -ENOMEM;
+				}
+				memset (mem[count], 0, sizeof (struct resource_node));
+				mem[count]->type = MEM;
+				mem[count]->busno = func->busno;
+				mem[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
+				mem[count]->len = len[count];
+				if (ibmphp_check_resource (mem[count], 0) == 0) {
+					ibmphp_add_resource (mem[count]);
+					func->mem[count] = mem[count];
+				} else {
+					err ("cannot allocate requested mem for bus %x, device %x, len %x\n",
+					     func->busno, func->device, len[count]);
+					kfree (mem[count]);
+					return -EIO;
+				}
+				pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->mem[count]->start);
+				/* _______________________This is for debugging purposes only _______________________*/
+				debug ("b4 writing, start address is %x\n", func->mem[count]->start);
+				pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]);
+				debug ("after writing, the address is %x\n", bar[count]);
+				/* __________________________________________________________________________________*/
+
+				if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+					/* takes up another dword */
+					debug ("inside mem 64 case, reg. mem, count %d\n", count);
+					count += 1;
+					/* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */
+					pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0x00000000);
+				}
+			}
+		}		/* end of mem */
+	}			/* end of for */
+
+	func->bus = 0;		/* To indicate that this is not a PPB */
+	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_INTERRUPT_PIN, &irq);
+	if ((irq > 0x00) && (irq < 0x05))
+		pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_INTERRUPT_LINE, func->irq[irq - 1]);
+
+	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE);
+	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY);
+
+	pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L);
+	pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE);
+
+	return 0;
+}
+
+/******************************************************************************
+ * This routine configures a PCI-2-PCI bridge and the functions behind it
+ * Parameters: pci_func
+ * Returns: 
+ ******************************************************************************/
+static int configure_bridge (struct pci_func **func_passed, u8 slotno)
+{
+	int count;
+	int i;
+	int rc;
+	u8 sec_number;
+	u8 io_base;
+	u16 pfmem_base;
+	u32 bar[2];
+	u32 len[2];
+	u8 flag_io = FALSE;
+	u8 flag_mem = FALSE;
+	u8 flag_pfmem = FALSE;
+	u8 need_io_upper = FALSE;
+	u8 need_pfmem_upper = FALSE;
+	struct res_needed *amount_needed = NULL;
+	struct resource_node *io = NULL;
+	struct resource_node *bus_io[2] = {NULL, NULL};
+	struct resource_node *mem = NULL;
+	struct resource_node *bus_mem[2] = {NULL, NULL};
+	struct resource_node *mem_tmp = NULL;
+	struct resource_node *pfmem = NULL;
+	struct resource_node *bus_pfmem[2] = {NULL, NULL};
+	struct bus_node *bus;
+	u32 address[] = {
+		PCI_BASE_ADDRESS_0,
+		PCI_BASE_ADDRESS_1,
+		0
+	};
+	struct pci_func *func = *func_passed;
+	unsigned int devfn;
+	u8 irq;
+	int retval;
+
+	debug ("%s - enter\n", __FUNCTION__);
+
+	devfn = PCI_DEVFN(func->function, func->device);
+	ibmphp_pci_bus->number = func->busno;
+
+	/* Configuring necessary info for the bridge so that we could see the devices
+	 * behind it
+	 */
+
+	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, func->busno);
+
+	/* _____________________For debugging purposes only __________________________
+	pci_bus_config_byte (ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, &pri_number);
+	debug ("primary # written into the bridge is %x\n", pri_number);
+	 ___________________________________________________________________________*/
+
+	/* in EBDA, only get allocated 1 additional bus # per slot */
+	sec_number = find_sec_number (func->busno, slotno);
+	if (sec_number == 0xff) {
+		err ("cannot allocate secondary bus number for the bridged device \n");
+		return -EINVAL;
+	}
+
+	debug ("after find_sec_number, the number we got is %x\n", sec_number);
+	debug ("AFTER FIND_SEC_NUMBER, func->busno IS %x\n", func->busno);
+
+	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, sec_number);
+	
+	/* __________________For debugging purposes only __________________________________
+	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
+	debug ("sec_number after write/read is %x\n", sec_number);
+	 ________________________________________________________________________________*/
+
+	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, sec_number);
+
+	/* __________________For debugging purposes only ____________________________________
+	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, &sec_number);
+	debug ("subordinate number after write/read is %x\n", sec_number);
+	 __________________________________________________________________________________*/
+
+	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE);
+	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY);
+	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_SEC_LATENCY_TIMER, LATENCY);
+
+	debug ("func->busno is %x\n", func->busno);
+	debug ("sec_number after writing is %x\n", sec_number);
+
+
+	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+	   !!!!!!!!!!!!!!!NEED TO ADD!!!  FAST BACK-TO-BACK ENABLE!!!!!!!!!!!!!!!!!!!! 
+	   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+
+
+	/* First we need to allocate mem/io for the bridge itself in case it needs it */
+	for (count = 0; address[count]; count++) {	/* for 2 BARs */
+		pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF);
+		pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]);
+
+		if (!bar[count]) {
+			/* This BAR is not implemented */
+			debug ("so we come here then, eh?, count = %d\n", count);
+			continue;
+		}
+		//  tmp_bar = bar[count];
+
+		debug ("Bar %d wants %x\n", count, bar[count]);
+
+		if (bar[count] & PCI_BASE_ADDRESS_SPACE_IO) {
+			/* This is IO */
+			len[count] = bar[count] & 0xFFFFFFFC;
+			len[count] = ~len[count] + 1;
+
+			debug ("len[count] in IO = %x\n", len[count]);
+
+			bus_io[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+		
+			if (!bus_io[count]) {
+				err ("out of system memory \n");
+				retval = -ENOMEM;
+				goto error;
+			}
+			memset (bus_io[count], 0, sizeof (struct resource_node));
+			bus_io[count]->type = IO;
+			bus_io[count]->busno = func->busno;
+			bus_io[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
+			bus_io[count]->len = len[count];
+			if (ibmphp_check_resource (bus_io[count], 0) == 0) {
+				ibmphp_add_resource (bus_io[count]);
+				func->io[count] = bus_io[count];
+			} else {
+				err ("cannot allocate requested io for bus %x, device %x, len %x\n",
+				     func->busno, func->device, len[count]);
+				kfree (bus_io[count]);
+				return -EIO;
+			}
+
+			pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->io[count]->start);
+
+		} else {
+			/* This is Memory */
+			if (bar[count] & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+				/* pfmem */
+				len[count] = bar[count] & 0xFFFFFFF0;
+				len[count] = ~len[count] + 1;
+
+				debug ("len[count] in PFMEM = %x\n", len[count]);
+
+				bus_pfmem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+				if (!bus_pfmem[count]) {
+					err ("out of system memory \n");
+					retval = -ENOMEM;
+					goto error;
+				}
+				memset (bus_pfmem[count], 0, sizeof (struct resource_node));
+				bus_pfmem[count]->type = PFMEM;
+				bus_pfmem[count]->busno = func->busno;
+				bus_pfmem[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
+				bus_pfmem[count]->len = len[count];
+				bus_pfmem[count]->fromMem = FALSE;
+				if (ibmphp_check_resource (bus_pfmem[count], 0) == 0) {
+					ibmphp_add_resource (bus_pfmem[count]);
+					func->pfmem[count] = bus_pfmem[count];
+				} else {
+					mem_tmp = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+					if (!mem_tmp) {
+						err ("out of system memory \n");
+						retval = -ENOMEM;
+						goto error;
+					}
+					memset (mem_tmp, 0, sizeof (struct resource_node));
+					mem_tmp->type = MEM;
+					mem_tmp->busno = bus_pfmem[count]->busno;
+					mem_tmp->devfunc = bus_pfmem[count]->devfunc;
+					mem_tmp->len = bus_pfmem[count]->len;
+					if (ibmphp_check_resource (mem_tmp, 0) == 0) {
+						ibmphp_add_resource (mem_tmp);
+						bus_pfmem[count]->fromMem = TRUE;
+						bus_pfmem[count]->rangeno = mem_tmp->rangeno;
+						ibmphp_add_pfmem_from_mem (bus_pfmem[count]);
+						func->pfmem[count] = bus_pfmem[count];
+					} else {
+						err ("cannot allocate requested pfmem for bus %x, device %x, len %x\n", 
+						     func->busno, func->device, len[count]);
+						kfree (mem_tmp);
+						kfree (bus_pfmem[count]);
+						return -EIO;
+					}
+				}
+
+				pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->pfmem[count]->start);
+
+				if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+					/* takes up another dword */
+					count += 1;
+					/* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */
+					pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0x00000000);
+
+				}
+			} else {
+				/* regular memory */
+				len[count] = bar[count] & 0xFFFFFFF0;
+				len[count] = ~len[count] + 1;
+
+				debug ("len[count] in Memory is %x\n", len[count]);
+
+				bus_mem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+				if (!bus_mem[count]) {
+					err ("out of system memory \n");
+					retval = -ENOMEM;
+					goto error;
+				}
+				memset (bus_mem[count], 0, sizeof (struct resource_node));
+				bus_mem[count]->type = MEM;
+				bus_mem[count]->busno = func->busno;
+				bus_mem[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
+				bus_mem[count]->len = len[count];
+				if (ibmphp_check_resource (bus_mem[count], 0) == 0) {
+					ibmphp_add_resource (bus_mem[count]);
+					func->mem[count] = bus_mem[count];
+				} else {
+					err ("cannot allocate requested mem for bus %x, device %x, len %x\n",
+					     func->busno, func->device, len[count]);
+					kfree (bus_mem[count]);
+					return -EIO;
+				}
+
+				pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->mem[count]->start);
+
+				if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+					/* takes up another dword */
+					count += 1;
+					/* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */
+					pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0x00000000);
+
+				}
+			}
+		}		/* end of mem */
+	}			/* end of for  */
+
+	/* Now need to see how much space the devices behind the bridge needed */
+	amount_needed = scan_behind_bridge (func, sec_number);
+	if (amount_needed == NULL)
+		return -ENOMEM;
+
+	ibmphp_pci_bus->number = func->busno;
+	debug ("after coming back from scan_behind_bridge\n");
+	debug ("amount_needed->not_correct = %x\n", amount_needed->not_correct);
+	debug ("amount_needed->io = %x\n", amount_needed->io);
+	debug ("amount_needed->mem = %x\n", amount_needed->mem);
+	debug ("amount_needed->pfmem =  %x\n", amount_needed->pfmem);
+
+	if (amount_needed->not_correct) {		
+		debug ("amount_needed is not correct \n");
+		for (count = 0; address[count]; count++) {
+			/* for 2 BARs */
+			if (bus_io[count]) {
+				ibmphp_remove_resource (bus_io[count]);
+				func->io[count] = NULL;
+			} else if (bus_pfmem[count]) {
+				ibmphp_remove_resource (bus_pfmem[count]);
+				func->pfmem[count] = NULL;
+			} else if (bus_mem[count]) {
+				ibmphp_remove_resource (bus_mem[count]);
+				func->mem[count] = NULL;
+			}
+		}
+		kfree (amount_needed);
+		return -ENODEV;
+	}
+
+	if (!amount_needed->io) {
+		debug ("it doesn't want IO?\n");
+		flag_io = TRUE;
+	} else {
+		debug ("it wants %x IO behind the bridge \n", amount_needed->io);
+		io = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+		
+		if (!io) {
+			err ("out of system memory \n");
+			retval = -ENOMEM;
+			goto error;
+		}
+		memset (io, 0, sizeof (struct resource_node));
+		io->type = IO;
+		io->busno = func->busno;
+		io->devfunc = ((func->device << 3) | (func->function & 0x7));
+		io->len = amount_needed->io;
+		if (ibmphp_check_resource (io, 1) == 0) {
+			debug ("were we able to add io\n");
+			ibmphp_add_resource (io);
+			flag_io = TRUE;
+		}
+	}
+
+	if (!amount_needed->mem) {
+		debug ("it doesn't want n.e.memory?\n");
+		flag_mem = TRUE;
+	} else {
+		debug ("it wants %x memory behind the bridge\n", amount_needed->mem);
+		mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+		if (!mem) {
+			err ("out of system memory \n");
+			retval = -ENOMEM;
+			goto error;
+		}
+		memset (mem, 0, sizeof (struct resource_node));
+		mem->type = MEM;
+		mem->busno = func->busno;
+		mem->devfunc = ((func->device << 3) | (func->function & 0x7));
+		mem->len = amount_needed->mem;
+		if (ibmphp_check_resource (mem, 1) == 0) {
+			ibmphp_add_resource (mem);
+			flag_mem = TRUE;
+			debug ("were we able to add mem\n");
+		}
+	}
+
+	if (!amount_needed->pfmem) {
+		debug ("it doesn't want n.e.pfmem mem?\n");
+		flag_pfmem = TRUE;
+	} else {
+		debug ("it wants %x pfmemory behind the bridge\n", amount_needed->pfmem);
+		pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+		if (!pfmem) {
+			err ("out of system memory \n");
+			retval = -ENOMEM;
+			goto error;
+		}
+		memset (pfmem, 0, sizeof (struct resource_node));
+		pfmem->type = PFMEM;
+		pfmem->busno = func->busno;
+		pfmem->devfunc = ((func->device << 3) | (func->function & 0x7));
+		pfmem->len = amount_needed->pfmem;
+		pfmem->fromMem = FALSE;
+		if (ibmphp_check_resource (pfmem, 1) == 0) {
+			ibmphp_add_resource (pfmem);
+			flag_pfmem = TRUE;
+		} else {
+			mem_tmp = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+			if (!mem_tmp) {
+				err ("out of system memory \n");
+				retval = -ENOMEM;
+				goto error;
+			}
+			memset (mem_tmp, 0, sizeof (struct resource_node));
+			mem_tmp->type = MEM;
+			mem_tmp->busno = pfmem->busno;
+			mem_tmp->devfunc = pfmem->devfunc;
+			mem_tmp->len = pfmem->len;
+			if (ibmphp_check_resource (mem_tmp, 1) == 0) {
+				ibmphp_add_resource (mem_tmp);
+				pfmem->fromMem = TRUE;
+				pfmem->rangeno = mem_tmp->rangeno;
+				ibmphp_add_pfmem_from_mem (pfmem);
+				flag_pfmem = TRUE;
+			}
+		}
+	}
+
+	debug ("b4 if (flag_io && flag_mem && flag_pfmem)\n");
+	debug ("flag_io = %x, flag_mem = %x, flag_pfmem = %x\n", flag_io, flag_mem, flag_pfmem);
+
+	if (flag_io && flag_mem && flag_pfmem) {
+		/* If on bootup, there was a bridged card in this slot,
+		 * then card was removed and ibmphp got unloaded and loaded
+		 * back again, there's no way for us to remove the bus
+		 * struct, so no need to kmalloc, can use existing node
+		 */
+		bus = ibmphp_find_res_bus (sec_number);
+		if (!bus) {
+			bus = kmalloc (sizeof (struct bus_node), GFP_KERNEL);
+			if (!bus) {
+				err ("out of system memory \n");
+				retval = -ENOMEM;
+				goto error;
+			}
+			memset (bus, 0, sizeof (struct bus_node));
+			bus->busno = sec_number;
+			debug ("b4 adding new bus\n");
+			rc = add_new_bus (bus, io, mem, pfmem, func->busno);
+		} else if (!(bus->rangeIO) && !(bus->rangeMem) && !(bus->rangePFMem))
+			rc = add_new_bus (bus, io, mem, pfmem, 0xFF);
+		else {
+			err ("expected bus structure not empty? \n");
+			retval = -EIO;
+			goto error;
+		}
+		if (rc) {
+			if (rc == -ENOMEM) {
+				ibmphp_remove_bus (bus, func->busno);
+				kfree (amount_needed);
+				return rc;
+			}
+			retval = rc;
+			goto error;
+		}
+		pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, &io_base);
+		pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, &pfmem_base);
+
+		if ((io_base & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
+			debug ("io 32\n");
+			need_io_upper = TRUE;
+		}
+		if ((io_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
+			debug ("pfmem 64\n");
+			need_pfmem_upper = TRUE;
+		}
+
+		if (bus->noIORanges) {
+			pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, 0x00 | bus->rangeIO->start >> 8);
+			pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, 0x00 | bus->rangeIO->end >> 8);	
+
+			/* _______________This is for debugging purposes only ____________________
+			pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, &temp);
+			debug ("io_base = %x\n", (temp & PCI_IO_RANGE_TYPE_MASK) << 8);
+			pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, &temp);
+			debug ("io_limit = %x\n", (temp & PCI_IO_RANGE_TYPE_MASK) << 8);
+			 ________________________________________________________________________*/
+
+			if (need_io_upper) {	/* since can't support n.e.ways */
+				pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_IO_BASE_UPPER16, 0x0000);
+				pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_IO_LIMIT_UPPER16, 0x0000);
+			}
+		} else {
+			pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, 0x00);
+			pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, 0x00);
+		}
+
+		if (bus->noMemRanges) {
+			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, 0x0000 | bus->rangeMem->start >> 16);
+			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, 0x0000 | bus->rangeMem->end >> 16);
+			
+			/* ____________________This is for debugging purposes only ________________________
+			pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, &temp);
+			debug ("mem_base = %x\n", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16);
+			pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, &temp);
+			debug ("mem_limit = %x\n", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16);
+			 __________________________________________________________________________________*/
+
+		} else {
+			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, 0xffff);
+			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, 0x0000);
+		}
+		if (bus->noPFMemRanges) {
+			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, 0x0000 | bus->rangePFMem->start >> 16);
+			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, 0x0000 | bus->rangePFMem->end >> 16);
+
+			/* __________________________This is for debugging purposes only _______________________
+			pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, &temp);
+			debug ("pfmem_base = %x", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16);
+			pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &temp);
+			debug ("pfmem_limit = %x\n", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16);
+			 ______________________________________________________________________________________*/
+
+			if (need_pfmem_upper) {	/* since can't support n.e.ways */
+				pci_bus_write_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_BASE_UPPER32, 0x00000000);
+				pci_bus_write_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_LIMIT_UPPER32, 0x00000000);
+			}
+		} else {
+			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, 0xffff);
+			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, 0x0000);
+		}
+
+		debug ("b4 writing control information\n");
+
+		pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_INTERRUPT_PIN, &irq);
+		if ((irq > 0x00) && (irq < 0x05))
+			pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_INTERRUPT_LINE, func->irq[irq - 1]);
+		/*    
+		pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, ctrl);
+		pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_PARITY);
+		pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_SERR);
+		 */
+
+		pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE);
+		pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, 0x07);
+		for (i = 0; i < 32; i++) {
+			if (amount_needed->devices[i]) {
+				debug ("device where devices[i] is 1 = %x\n", i);
+				func->devices[i] = 1;
+			}
+		}
+		func->bus = 1;	/* For unconfiguring, to indicate it's PPB */
+		func_passed = &func;
+		debug ("func->busno b4 returning is %x\n", func->busno);
+		debug ("func->busno b4 returning in the other structure is %x\n", (*func_passed)->busno);
+		kfree (amount_needed);
+		return 0;
+	} else {
+		err ("Configuring bridge was unsuccessful... \n");
+		mem_tmp = NULL;
+		retval = -EIO;
+		goto error;
+	}
+
+error:
+	if (amount_needed)
+		kfree (amount_needed);
+	if (pfmem)
+		ibmphp_remove_resource (pfmem);
+	if (io)
+		ibmphp_remove_resource (io);
+	if (mem)
+		ibmphp_remove_resource (mem);
+	for (i = 0; i < 2; i++) {	/* for 2 BARs */
+		if (bus_io[i]) {
+			ibmphp_remove_resource (bus_io[i]);
+			func->io[i] = NULL;
+		} else if (bus_pfmem[i]) {
+			ibmphp_remove_resource (bus_pfmem[i]);
+			func->pfmem[i] = NULL;
+		} else if (bus_mem[i]) {
+			ibmphp_remove_resource (bus_mem[i]);
+			func->mem[i] = NULL;
+		}
+	}
+	return retval;
+}
+
+/*****************************************************************************
+ * This function adds up the amount of resources needed behind the PPB bridge
+ * and passes it to the configure_bridge function
+ * Input: bridge function
+ * Ouput: amount of resources needed
+ *****************************************************************************/
+static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno)
+{
+	int count, len[6];
+	u16 vendor_id;
+	u8 hdr_type;
+	u8 device, function;
+	unsigned int devfn;
+	int howmany = 0;	/*this is to see if there are any devices behind the bridge */
+
+	u32 bar[6], class;
+	u32 address[] = {
+		PCI_BASE_ADDRESS_0,
+		PCI_BASE_ADDRESS_1,
+		PCI_BASE_ADDRESS_2,
+		PCI_BASE_ADDRESS_3,
+		PCI_BASE_ADDRESS_4,
+		PCI_BASE_ADDRESS_5,
+		0
+	};
+	struct res_needed *amount;
+
+	amount = kmalloc (sizeof (struct res_needed), GFP_KERNEL);
+	if (amount == NULL)
+		return NULL;
+	memset (amount, 0, sizeof (struct res_needed));
+
+	ibmphp_pci_bus->number = busno;
+
+	debug ("the bus_no behind the bridge is %x\n", busno);
+	debug ("scanning devices behind the bridge...\n");
+	for (device = 0; device < 32; device++) {
+		amount->devices[device] = 0;
+		for (function = 0; function < 8; function++) {
+			devfn = PCI_DEVFN(device, function);
+
+			pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id);
+
+			if (vendor_id != PCI_VENDOR_ID_NOTVALID) {
+				/* found correct device!!! */
+				howmany++;
+
+				pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type);
+				pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class);
+
+				debug ("hdr_type behind the bridge is %x\n", hdr_type);
+				if (hdr_type & PCI_HEADER_TYPE_BRIDGE) {
+					err ("embedded bridges not supported for hot-plugging.\n");
+					amount->not_correct = TRUE;
+					return amount;
+				}
+
+				class >>= 8;	/* to take revision out, class = class.subclass.prog i/f */
+				if (class == PCI_CLASS_NOT_DEFINED_VGA) {
+					err ("The device %x is VGA compatible and as is not supported for hot plugging. "
+					     "Please choose another device.\n", device);
+					amount->not_correct = TRUE;
+					return amount;
+				} else if (class == PCI_CLASS_DISPLAY_VGA) {
+					err ("The device %x is not supported for hot plugging. "
+					     "Please choose another device.\n", device);
+					amount->not_correct = TRUE;
+					return amount;
+				}
+
+				amount->devices[device] = 1;
+
+				for (count = 0; address[count]; count++) {
+					/* for 6 BARs */
+					/*
+					pci_bus_read_config_byte (ibmphp_pci_bus, devfn, address[count], &tmp);
+					if (tmp & 0x01) // IO
+						pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFD);
+					else // MEMORY
+						pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF);
+					*/
+					pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF);
+					pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]);
+
+					debug ("what is bar[count]? %x, count = %d\n", bar[count], count);
+
+					if (!bar[count])	/* This BAR is not implemented */
+						continue;
+
+					//tmp_bar = bar[count];
+
+					debug ("count %d device %x function %x wants %x resources \n", count, device, function, bar[count]);
+
+					if (bar[count] & PCI_BASE_ADDRESS_SPACE_IO) {
+						/* This is IO */
+						len[count] = bar[count] & 0xFFFFFFFC;
+						len[count] = ~len[count] + 1;
+						amount->io += len[count];
+					} else {
+						/* This is Memory */
+						if (bar[count] & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+							/* pfmem */
+							len[count] = bar[count] & 0xFFFFFFF0;
+							len[count] = ~len[count] + 1;
+							amount->pfmem += len[count];
+							if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64)
+								/* takes up another dword */
+								count += 1;
+
+						} else {
+							/* regular memory */
+							len[count] = bar[count] & 0xFFFFFFF0;
+							len[count] = ~len[count] + 1;
+							amount->mem += len[count];
+							if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+								/* takes up another dword */
+								count += 1;
+							}
+						}
+					}
+				}	/* end for */
+			}	/* end if (valid) */
+		}	/* end for */
+	}	/* end for */
+
+	if (!howmany)
+		amount->not_correct = TRUE;
+	else
+		amount->not_correct = FALSE;
+	if ((amount->io) && (amount->io < IOBRIDGE))
+		amount->io = IOBRIDGE;
+	if ((amount->mem) && (amount->mem < MEMBRIDGE))
+		amount->mem = MEMBRIDGE;
+	if ((amount->pfmem) && (amount->pfmem < MEMBRIDGE))
+		amount->pfmem = MEMBRIDGE;
+	return amount;
+}
+
+/* The following 3 unconfigure_boot_ routines deal with the case when we had the card 
+ * upon bootup in the system, since we don't allocate func to such case, we need to read 
+ * the start addresses from pci config space and then find the corresponding entries in 
+ * our resource lists.  The functions return either 0, -ENODEV, or -1 (general failure)
+ * Change: we also call these functions even if we configured the card ourselves (i.e., not
+ * the bootup case), since it should work same way
+ */
+static int unconfigure_boot_device (u8 busno, u8 device, u8 function)
+{
+	u32 start_address;
+	u32 address[] = {
+		PCI_BASE_ADDRESS_0,
+		PCI_BASE_ADDRESS_1,
+		PCI_BASE_ADDRESS_2,
+		PCI_BASE_ADDRESS_3,
+		PCI_BASE_ADDRESS_4,
+		PCI_BASE_ADDRESS_5,
+		0
+	};
+	int count;
+	struct resource_node *io;
+	struct resource_node *mem;
+	struct resource_node *pfmem;
+	struct bus_node *bus;
+	u32 end_address;
+	u32 temp_end;
+	u32 size;
+	u32 tmp_address;
+	unsigned int devfn;
+
+	debug ("%s - enter\n", __FUNCTION__);
+
+	bus = ibmphp_find_res_bus (busno);
+	if (!bus) {
+		debug ("cannot find corresponding bus.\n");
+		return -EINVAL;
+	}
+
+	devfn = PCI_DEVFN(device, function);
+	ibmphp_pci_bus->number = busno;
+	for (count = 0; address[count]; count++) {	/* for 6 BARs */
+		pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &start_address);
+
+		/* We can do this here, b/c by that time the device driver of the card has been stopped */
+
+		pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF);
+		pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &size);
+		pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], start_address);
+
+		debug ("start_address is %x\n", start_address);
+		debug ("busno, device, function %x %x %x\n", busno, device, function);
+		if (!size) {
+			/* This BAR is not implemented */
+			debug ("is this bar no implemented?, count = %d\n", count);
+			continue;
+		}
+		tmp_address = start_address;
+		if (start_address & PCI_BASE_ADDRESS_SPACE_IO) {
+			/* This is IO */
+			start_address &= PCI_BASE_ADDRESS_IO_MASK;
+			size = size & 0xFFFFFFFC;
+			size = ~size + 1;
+			end_address = start_address + size - 1;
+			if (ibmphp_find_resource (bus, start_address, &io, IO) < 0) {
+				err ("cannot find corresponding IO resource to remove\n");
+				return -EIO;
+			}
+			debug ("io->start = %x\n", io->start);
+			temp_end = io->end;
+			start_address = io->end + 1;
+			ibmphp_remove_resource (io);
+			/* This is needed b/c of the old I/O restrictions in the BIOS */
+			while (temp_end < end_address) {
+				if (ibmphp_find_resource (bus, start_address, &io, IO) < 0) {
+					err ("cannot find corresponding IO resource to remove\n");
+					return -EIO;
+				}
+				debug ("io->start = %x\n", io->start);
+				temp_end = io->end;
+				start_address = io->end + 1;
+				ibmphp_remove_resource (io);
+			}
+
+			/* ????????? DO WE NEED TO WRITE ANYTHING INTO THE PCI CONFIG SPACE BACK ?????????? */
+		} else {
+			/* This is Memory */
+			if (start_address & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+				/* pfmem */
+				start_address &= PCI_BASE_ADDRESS_MEM_MASK;
+				debug ("start address of pfmem is %x\n", start_address);
+
+				if (ibmphp_find_resource (bus, start_address, &pfmem, PFMEM) < 0) {
+					err ("cannot find corresponding PFMEM resource to remove\n");
+					return -EIO;
+				}
+				if (pfmem)
+					debug ("pfmem->start = %x\n", pfmem->start);
+
+				ibmphp_remove_resource (pfmem);
+
+				if (tmp_address & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+					/* takes up another dword */
+					count += 1;
+				}
+
+			} else {
+				/* regular memory */
+				start_address &= PCI_BASE_ADDRESS_MEM_MASK;
+				debug ("start address of mem is %x\n", start_address);
+				if (ibmphp_find_resource (bus, start_address, &mem, MEM) < 0) {
+					err ("cannot find corresponding MEM resource to remove\n");
+					return -EIO;
+				}
+				if (mem)
+					debug ("mem->start = %x\n", mem->start);
+
+				ibmphp_remove_resource (mem);
+
+				if (tmp_address & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+					/* takes up another dword */
+					count += 1;
+				}
+			}
+		}	/* end of mem */
+	}	/* end of for */
+
+	return 0;
+}
+
+static int unconfigure_boot_bridge (u8 busno, u8 device, u8 function)
+{
+	int count;
+	int bus_no, pri_no, sub_no, sec_no = 0;
+	u32 start_address, tmp_address;
+	u8 sec_number, sub_number, pri_number;
+	struct resource_node *io = NULL;
+	struct resource_node *mem = NULL;
+	struct resource_node *pfmem = NULL;
+	struct bus_node *bus;
+	u32 address[] = {
+		PCI_BASE_ADDRESS_0,
+		PCI_BASE_ADDRESS_1,
+		0
+	};
+	unsigned int devfn;
+
+	devfn = PCI_DEVFN(device, function);
+	ibmphp_pci_bus->number = busno;
+	bus_no = (int) busno;
+	debug ("busno is %x\n", busno);
+	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, &pri_number);
+	debug ("%s - busno = %x, primary_number = %x\n", __FUNCTION__, busno, pri_number);
+
+	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
+	debug ("sec_number is %x\n", sec_number);
+	sec_no = (int) sec_number;
+	pri_no = (int) pri_number;
+	if (pri_no != bus_no) {
+		err ("primary numbers in our structures and pci config space don't match.\n");
+		return -EINVAL;
+	}
+
+	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
+	sec_no = (int) sec_no;
+
+	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, &sub_number);
+	sub_no = (int) sub_number;
+	debug ("sub_no is %d, sec_no is %d\n", sub_no, sec_no);
+	if (sec_no != sub_number) {
+		err ("there're more buses behind this bridge.  Hot removal is not supported.  Please choose another card\n");
+		return -ENODEV;
+	}
+
+	bus = ibmphp_find_res_bus (sec_number);
+	debug ("bus->busno is %x\n", bus->busno);
+	debug ("sec_number is %x\n", sec_number);
+	if (!bus) {
+		err ("cannot find Bus structure for the bridged device\n");
+		return -EINVAL;
+	}
+
+	ibmphp_remove_bus (bus, busno);
+
+	for (count = 0; address[count]; count++) {
+		/* for 2 BARs */
+		pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &start_address);
+
+		if (!start_address) {
+			/* This BAR is not implemented */
+			continue;
+		}
+
+		tmp_address = start_address;
+
+		if (start_address & PCI_BASE_ADDRESS_SPACE_IO) {
+			/* This is IO */
+			start_address &= PCI_BASE_ADDRESS_IO_MASK;
+			if (ibmphp_find_resource (bus, start_address, &io, IO) < 0) {
+				err ("cannot find corresponding IO resource to remove\n");
+				return -EIO;
+			}
+			if (io)
+				debug ("io->start = %x\n", io->start);
+
+			ibmphp_remove_resource (io);
+
+			/* ????????? DO WE NEED TO WRITE ANYTHING INTO THE PCI CONFIG SPACE BACK ?????????? */
+		} else {
+			/* This is Memory */
+			if (start_address & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+				/* pfmem */
+				start_address &= PCI_BASE_ADDRESS_MEM_MASK;
+				if (ibmphp_find_resource (bus, start_address, &pfmem, PFMEM) < 0) {
+					err ("cannot find corresponding PFMEM resource to remove\n");
+					return -EINVAL;
+				}
+				if (pfmem)
+					debug ("pfmem->start = %x\n", pfmem->start);
+
+				ibmphp_remove_resource (pfmem);
+
+				if (tmp_address & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+					/* takes up another dword */
+					count += 1;
+				}
+
+			} else {
+				/* regular memory */
+				start_address &= PCI_BASE_ADDRESS_MEM_MASK;
+				if (ibmphp_find_resource (bus, start_address, &mem, MEM) < 0) {
+					err ("cannot find corresponding MEM resource to remove\n");
+					return -EINVAL;
+				}
+				if (mem)
+					debug ("mem->start = %x\n", mem->start);
+
+				ibmphp_remove_resource (mem);
+
+				if (tmp_address & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+					/* takes up another dword */
+					count += 1;
+				}
+			}
+		}	/* end of mem */
+	}	/* end of for */
+	debug ("%s - exiting, returning success\n", __FUNCTION__);
+	return 0;
+}
+
+static int unconfigure_boot_card (struct slot *slot_cur)
+{
+	u16 vendor_id;
+	u32 class;
+	u8 hdr_type;
+	u8 device;
+	u8 busno;
+	u8 function;
+	int rc;
+	unsigned int devfn;
+	u8 valid_device = 0x00; /* To see if we are ever able to find valid device and read it */
+
+	debug ("%s - enter\n", __FUNCTION__);
+
+	device = slot_cur->device;
+	busno = slot_cur->bus;
+
+	debug ("b4 for loop, device is %x\n", device);
+	/* For every function on the card */
+	for (function = 0x0; function < 0x08; function++) {
+		devfn = PCI_DEVFN(device, function);
+		ibmphp_pci_bus->number = busno;
+
+		pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id);
+
+		if (vendor_id != PCI_VENDOR_ID_NOTVALID) {
+			/* found correct device!!! */
+			++valid_device;
+
+			debug ("%s - found correct device\n", __FUNCTION__);
+
+			/* header: x x x x x x x x
+			 *         | |___________|=> 1=PPB bridge, 0=normal device, 2=CardBus Bridge
+			 *         |_=> 0 = single function device, 1 = multi-function device
+			 */
+
+			pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type);
+			pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class);
+
+			debug ("hdr_type %x, class %x\n", hdr_type, class);
+			class >>= 8;	/* to take revision out, class = class.subclass.prog i/f */
+			if (class == PCI_CLASS_NOT_DEFINED_VGA) {
+				err ("The device %x function %x is VGA compatible and is not supported for hot removing. "
+				     "Please choose another device.\n", device, function);
+				return -ENODEV;
+			} else if (class == PCI_CLASS_DISPLAY_VGA) {
+				err ("The device %x function %x is not supported for hot removing. "
+				     "Please choose another device.\n", device, function);
+				return -ENODEV;
+			}
+
+			switch (hdr_type) {
+				case PCI_HEADER_TYPE_NORMAL:
+					rc = unconfigure_boot_device (busno, device, function);
+					if (rc) {
+						err ("was not able to unconfigure device %x func %x on bus %x. bailing out... \n",
+						     device, function, busno);
+						return rc;
+					}
+					function = 0x8;
+					break;
+				case PCI_HEADER_TYPE_MULTIDEVICE:
+					rc = unconfigure_boot_device (busno, device, function);
+					if (rc) {
+						err ("was not able to unconfigure device %x func %x on bus %x. bailing out... \n",
+						     device, function, busno);
+						return rc;
+					}
+					break;
+				case PCI_HEADER_TYPE_BRIDGE:
+					class >>= 8;
+					if (class != PCI_CLASS_BRIDGE_PCI) {
+						err ("This device %x function %x is not PCI-to-PCI bridge, "
+						     "and is not supported for hot-removing. "
+						     "Please try another card.\n", device, function);
+						return -ENODEV;
+					}
+					rc = unconfigure_boot_bridge (busno, device, function);
+					if (rc != 0) {
+						err ("was not able to hot-remove PPB properly.\n");
+						return rc;
+					}
+
+					function = 0x8;
+					break;
+				case PCI_HEADER_TYPE_MULTIBRIDGE:
+					class >>= 8;
+					if (class != PCI_CLASS_BRIDGE_PCI) {
+						err ("This device %x function %x is not PCI-to-PCI bridge, "
+						     "and is not supported for hot-removing. "
+						     "Please try another card.\n", device, function);
+						return -ENODEV;
+					}
+					rc = unconfigure_boot_bridge (busno, device, function);
+					if (rc != 0) {
+						err ("was not able to hot-remove PPB properly.\n");
+						return rc;
+					}
+					break;
+				default:
+					err ("MAJOR PROBLEM!!!! Cannot read device's header \n");
+					return -1;
+					break;
+			}	/* end of switch */
+		}	/* end of valid device */
+	}	/* end of for */
+
+	if (!valid_device) {
+		err ("Could not find device to unconfigure.  Or could not read the card. \n");
+		return -1;
+	}
+	return 0;
+}
+
+/*
+ * free the resources of the card (multi, single, or bridged)
+ * Parameters: slot, flag to say if this is for removing entire module or just
+ * unconfiguring the device
+ * TO DO:  will probably need to add some code in case there was some resource,
+ * to remove it... this is from when we have errors in the configure_card...
+ * 			!!!!!!!!!!!!!!!!!!!!!!!!!FOR BUSES!!!!!!!!!!!!
+ * Returns: 0, -1, -ENODEV 
+ */
+int ibmphp_unconfigure_card (struct slot **slot_cur, int the_end)
+{
+	int i;
+	int count;
+	int rc;
+	struct slot *sl = *slot_cur;
+	struct pci_func *cur_func = NULL;
+	struct pci_func *temp_func;
+
+	debug ("%s - enter\n", __FUNCTION__);
+
+	if (!the_end) {
+		/* Need to unconfigure the card */
+		rc = unconfigure_boot_card (sl);
+		if ((rc == -ENODEV) || (rc == -EIO) || (rc == -EINVAL)) {
+			/* In all other cases, will still need to get rid of func structure if it exists */
+			return rc;
+		}
+	}
+
+	if (sl->func) {
+		cur_func = sl->func;
+		while (cur_func) {
+			/* TO DO: WILL MOST LIKELY NEED TO GET RID OF THE BUS STRUCTURE FROM RESOURCES AS WELL */
+			if (cur_func->bus) {
+				/* in other words, it's a PPB */
+				count = 2;
+			} else {
+				count = 6;
+			}
+
+			for (i = 0; i < count; i++) {
+				if (cur_func->io[i]) {
+					debug ("io[%d] exists \n", i);
+					if (the_end > 0)
+						ibmphp_remove_resource (cur_func->io[i]);
+					cur_func->io[i] = NULL;
+				}
+				if (cur_func->mem[i]) {
+					debug ("mem[%d] exists \n", i);
+					if (the_end > 0)
+						ibmphp_remove_resource (cur_func->mem[i]);
+					cur_func->mem[i] = NULL;
+				}
+				if (cur_func->pfmem[i]) {
+					debug ("pfmem[%d] exists \n", i);
+					if (the_end > 0)
+						ibmphp_remove_resource (cur_func->pfmem[i]);
+					cur_func->pfmem[i] = NULL;
+				}
+			}
+
+			temp_func = cur_func->next;
+			kfree (cur_func);
+			cur_func = temp_func;
+		}
+	}
+
+	sl->func = NULL;
+	*slot_cur = sl;
+	debug ("%s - exit\n", __FUNCTION__);
+	return 0;
+}
+
+/*
+ * add a new bus resulting from hot-plugging a PPB bridge with devices
+ *
+ * Input: bus and the amount of resources needed (we know we can assign those,
+ *        since they've been checked already
+ * Output: bus added to the correct spot
+ *         0, -1, error 
+ */
+static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct resource_node *mem, struct resource_node *pfmem, u8 parent_busno)
+{
+	struct range_node *io_range = NULL;
+	struct range_node *mem_range = NULL;
+	struct range_node *pfmem_range = NULL;
+	struct bus_node *cur_bus = NULL;
+
+	/* Trying to find the parent bus number */
+	if (parent_busno != 0xFF) {
+		cur_bus	= ibmphp_find_res_bus (parent_busno);
+		if (!cur_bus) {
+			err ("strange, cannot find bus which is supposed to be at the system... something is terribly wrong...\n");
+			return -ENODEV;
+		}
+	
+		list_add (&bus->bus_list, &cur_bus->bus_list);
+	}
+	if (io) {
+		io_range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
+		if (!io_range) {
+			err ("out of system memory \n");
+			return -ENOMEM;
+		}
+		memset (io_range, 0, sizeof (struct range_node));
+		io_range->start = io->start;
+		io_range->end = io->end;
+		io_range->rangeno = 1;
+		bus->noIORanges = 1;
+		bus->rangeIO = io_range;
+	}
+	if (mem) {
+		mem_range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
+		if (!mem_range) {
+			err ("out of system memory \n");
+			return -ENOMEM;
+		}
+		memset (mem_range, 0, sizeof (struct range_node));
+		mem_range->start = mem->start;
+		mem_range->end = mem->end;
+		mem_range->rangeno = 1;
+		bus->noMemRanges = 1;
+		bus->rangeMem = mem_range;
+	}
+	if (pfmem) {
+		pfmem_range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
+		if (!pfmem_range) {	
+			err ("out of system memory \n");
+			return -ENOMEM;
+		}
+		memset (pfmem_range, 0, sizeof (struct range_node));
+		pfmem_range->start = pfmem->start;
+		pfmem_range->end = pfmem->end;
+		pfmem_range->rangeno = 1;
+		bus->noPFMemRanges = 1;
+		bus->rangePFMem = pfmem_range;
+	}
+	return 0;
+}
+
+/*
+ * find the 1st available bus number for PPB to set as its secondary bus
+ * Parameters: bus_number of the primary bus
+ * Returns: bus_number of the secondary bus or 0xff in case of failure
+ */
+static u8 find_sec_number (u8 primary_busno, u8 slotno)
+{
+	int min, max;
+	u8 busno;
+	struct bus_info *bus;
+	struct bus_node *bus_cur;
+
+	bus = ibmphp_find_same_bus_num (primary_busno);
+	if (!bus) {
+		err ("cannot get slot range of the bus from the BIOS\n");
+		return 0xff;
+	}
+	max = bus->slot_max;
+	min = bus->slot_min;
+	if ((slotno > max) || (slotno < min)) {
+		err ("got the wrong range\n");
+		return 0xff;
+	}
+	busno = (u8) (slotno - (u8) min);
+	busno += primary_busno + 0x01;
+	bus_cur = ibmphp_find_res_bus (busno);
+	/* either there is no such bus number, or there are no ranges, which
+	 * can only happen if we removed the bridged device in previous load
+	 * of the driver, and now only have the skeleton bus struct
+	 */
+	if ((!bus_cur) || (!(bus_cur->rangeIO) && !(bus_cur->rangeMem) && !(bus_cur->rangePFMem)))
+		return busno;
+	return 0xff;
+}
+
diff -Nru a/drivers/pci/hotplug/ibmphp_res.c b/drivers/pci/hotplug/ibmphp_res.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/ibmphp_res.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,2157 @@
+/*
+ * IBM Hot Plug Controller Driver
+ *
+ * Written By: Irene Zubarev, IBM Corporation
+ *
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001,2002 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gregkh@us.ibm.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include "ibmphp.h"
+
+static int flags = 0;		/* for testing */
+
+static void update_resources (struct bus_node *bus_cur, int type, int rangeno);
+static int once_over (void);
+static int remove_ranges (struct bus_node *, struct bus_node *);
+static int update_bridge_ranges (struct bus_node **);
+static int add_range (int type, struct range_node *, struct bus_node *);
+static void fix_resources (struct bus_node *);
+static inline struct bus_node *find_bus_wprev (u8, struct bus_node **, u8);
+
+static LIST_HEAD(gbuses);
+LIST_HEAD(ibmphp_res_head);
+
+static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc * curr, u8 busno, int flag)
+{
+	struct bus_node * newbus;
+
+	if (!(curr) && !(flag)) {
+		err ("NULL pointer passed \n");
+		return NULL;
+	}
+
+	newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL);
+	if (!newbus) {
+		err ("out of system memory \n");
+		return NULL;
+	}
+
+	memset (newbus, 0, sizeof (struct bus_node));
+	if (flag)
+		newbus->busno = busno;
+	else
+		newbus->busno = curr->bus_num;
+	list_add_tail (&newbus->bus_list, &gbuses);
+	return newbus;
+}
+
+static struct resource_node * __init alloc_resources (struct ebda_pci_rsrc * curr)
+{
+	struct resource_node *rs;
+	
+	if (!curr) {
+		err ("NULL passed to allocate \n");
+		return NULL;
+	}
+
+	rs = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+	if (!rs) {
+		err ("out of system memory \n");
+		return NULL;
+	}
+	memset (rs, 0, sizeof (struct resource_node));
+	rs->busno = curr->bus_num;
+	rs->devfunc = curr->dev_fun;
+	rs->start = curr->start_addr;
+	rs->end = curr->end_addr;
+	rs->len = curr->end_addr - curr->start_addr + 1;
+	return rs;
+}
+
+static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node **new_range, struct ebda_pci_rsrc *curr, int flag, u8 first_bus)
+{
+	struct bus_node * newbus;
+	struct range_node *newrange;
+	u8 num_ranges = 0;
+
+	if (first_bus) {
+		newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL);
+		if (!newbus) {
+			err ("out of system memory. \n");
+			return -ENOMEM;
+		}
+		memset (newbus, 0, sizeof (struct bus_node));
+		newbus->busno = curr->bus_num;
+	} else {
+		newbus = *new_bus;
+		switch (flag) {
+			case MEM:
+				num_ranges = newbus->noMemRanges;
+				break;
+			case PFMEM:
+				num_ranges = newbus->noPFMemRanges;
+				break;
+			case IO:
+				num_ranges = newbus->noIORanges;
+				break;
+		}
+	}
+
+	newrange = kmalloc (sizeof (struct range_node), GFP_KERNEL);
+	if (!newrange) {
+		if (first_bus)
+			kfree (newbus);
+		err ("out of system memory \n");
+		return -ENOMEM;
+	}
+	memset (newrange, 0, sizeof (struct range_node));
+	newrange->start = curr->start_addr;
+	newrange->end = curr->end_addr;
+		
+	if (first_bus || (!num_ranges))
+		newrange->rangeno = 1;
+	else {
+		/* need to insert our range */
+		add_range (flag, newrange, newbus);
+		debug ("%d resource Primary Bus inserted on bus %x [%x - %x]\n", flag, newbus->busno, newrange->start, newrange->end);
+	}
+
+	switch (flag) {
+		case MEM:
+			newbus->rangeMem = newrange;
+			if (first_bus)
+				newbus->noMemRanges = 1;
+			else {
+				debug ("First Memory Primary on bus %x, [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
+				++newbus->noMemRanges;
+				fix_resources (newbus);
+			}
+			break;
+		case IO:
+			newbus->rangeIO = newrange;
+			if (first_bus)
+				newbus->noIORanges = 1;
+			else {
+				debug ("First IO Primary on bus %x, [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
+				++newbus->noIORanges;
+				fix_resources (newbus);
+			}
+			break;
+		case PFMEM:
+			newbus->rangePFMem = newrange;
+			if (first_bus)
+				newbus->noPFMemRanges = 1;
+			else {	
+				debug ("1st PFMemory Primary on Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
+				++newbus->noPFMemRanges;
+				fix_resources (newbus);
+			}
+
+			break;
+	}
+
+	*new_bus = newbus;
+	*new_range = newrange;
+	return 0;
+}
+
+
+/* Notes:
+ * 1. The ranges are ordered.  The buses are not ordered.  (First come)
+ *
+ * 2. If cannot allocate out of PFMem range, allocate from Mem ranges.  PFmemFromMem
+ * are not sorted. (no need since use mem node). To not change the entire code, we
+ * also add mem node whenever this case happens so as not to change
+ * ibmphp_check_mem_resource etc (and since it really is taking Mem resource)
+ */
+
+/*****************************************************************************
+ * This is the Resource Management initialization function.  It will go through
+ * the Resource list taken from EBDA and fill in this module's data structures
+ *
+ * THIS IS NOT TAKING INTO CONSIDERATION IO RESTRICTIONS OF PRIMARY BUSES, 
+ * SINCE WE'RE GOING TO ASSUME FOR NOW WE DON'T HAVE THOSE ON OUR BUSES FOR NOW
+ *
+ * Input: ptr to the head of the resource list from EBDA
+ * Output: 0, -1 or error codes
+ ***************************************************************************/
+int __init ibmphp_rsrc_init (void)
+{
+	struct ebda_pci_rsrc *curr;
+	struct range_node *newrange = NULL;
+	struct bus_node *newbus = NULL;
+	struct bus_node *bus_cur;
+	struct bus_node *bus_prev;
+	struct list_head *tmp;
+	struct resource_node *new_io = NULL;
+	struct resource_node *new_mem = NULL;
+	struct resource_node *new_pfmem = NULL;
+	int rc;
+	struct list_head *tmp_ebda;
+
+	list_for_each (tmp_ebda, &ibmphp_ebda_pci_rsrc_head) {
+		curr = list_entry (tmp_ebda, struct ebda_pci_rsrc, ebda_pci_rsrc_list);
+		if (!(curr->rsrc_type & PCIDEVMASK)) {
+			/* EBDA still lists non PCI devices, so ignore... */
+			debug ("this is not a PCI DEVICE in rsrc_init, please take care\n");
+			// continue;
+		}
+
+		/* this is a primary bus resource */
+		if (curr->rsrc_type & PRIMARYBUSMASK) {
+			/* memory */
+			if ((curr->rsrc_type & RESTYPE) == MMASK) {
+				/* no bus structure exists in place yet */
+				if (list_empty (&gbuses)) {
+					if ((rc = alloc_bus_range (&newbus, &newrange, curr, MEM, 1)))
+						return rc;
+					list_add_tail (&newbus->bus_list, &gbuses);
+					debug ("gbuses = NULL, Memory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
+				} else {
+					bus_cur = find_bus_wprev (curr->bus_num, &bus_prev, 1);
+					/* found our bus */
+					if (bus_cur) {
+						rc = alloc_bus_range (&bus_cur, &newrange, curr, MEM, 0);
+						if (rc)
+							return rc;
+					} else {
+						/* went through all the buses and didn't find ours, need to create a new bus node */
+						if ((rc = alloc_bus_range (&newbus, &newrange, curr, MEM, 1)))
+							return rc;
+
+						list_add_tail (&newbus->bus_list, &gbuses);
+						debug ("New Bus, Memory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
+					}
+				}
+			} else if ((curr->rsrc_type & RESTYPE) == PFMASK) {
+				/* prefetchable memory */
+				if (list_empty (&gbuses)) {
+					/* no bus structure exists in place yet */
+					if ((rc = alloc_bus_range (&newbus, &newrange, curr, PFMEM, 1)))
+						return rc;
+					list_add_tail (&newbus->bus_list, &gbuses);
+					debug ("gbuses = NULL, PFMemory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
+				} else {
+					bus_cur = find_bus_wprev (curr->bus_num, &bus_prev, 1);
+					if (bus_cur) {
+						/* found our bus */
+						rc = alloc_bus_range (&bus_cur, &newrange, curr, PFMEM, 0);
+						if (rc)
+							return rc;
+					} else {
+						/* went through all the buses and didn't find ours, need to create a new bus node */
+						if ((rc = alloc_bus_range (&newbus, &newrange, curr, PFMEM, 1)))
+							return rc;
+						list_add_tail (&newbus->bus_list, &gbuses);
+						debug ("1st Bus, PFMemory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
+					}
+				}
+			} else if ((curr->rsrc_type & RESTYPE) == IOMASK) {
+				/* IO */
+				if (list_empty (&gbuses)) {
+					/* no bus structure exists in place yet */
+					if ((rc = alloc_bus_range (&newbus, &newrange, curr, IO, 1)))
+						return rc;
+					list_add_tail (&newbus->bus_list, &gbuses);
+					debug ("gbuses = NULL, IO Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
+				} else {
+					bus_cur = find_bus_wprev (curr->bus_num, &bus_prev, 1);
+					if (bus_cur) {
+						rc = alloc_bus_range (&bus_cur, &newrange, curr, IO, 0);
+						if (rc)
+							return rc;
+					} else {
+						/* went through all the buses and didn't find ours, need to create a new bus node */
+						if ((rc = alloc_bus_range (&newbus, &newrange, curr, IO, 1)))
+							return rc;
+						list_add_tail (&newbus->bus_list, &gbuses);
+						debug ("1st Bus, IO Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
+					}
+				}
+
+			} else {
+				;	/* type is reserved  WHAT TO DO IN THIS CASE???
+					   NOTHING TO DO??? */
+			}
+		} else {
+			/* regular pci device resource */
+			if ((curr->rsrc_type & RESTYPE) == MMASK) {
+				/* Memory resource */
+				new_mem = alloc_resources (curr);
+				if (!new_mem)
+					return -ENOMEM;
+				new_mem->type = MEM;
+				/*
+				 * if it didn't find the bus, means PCI dev
+				 * came b4 the Primary Bus info, so need to
+				 * create a bus rangeno becomes a problem...
+				 * assign a -1 and then update once the range
+				 * actually appears...
+				 */
+				if (ibmphp_add_resource (new_mem) < 0) {
+					newbus = alloc_error_bus (curr, 0, 0);
+					if (!newbus)
+						return -ENOMEM;
+					newbus->firstMem = new_mem;
+					++newbus->needMemUpdate;
+					new_mem->rangeno = -1;
+				}
+				debug ("Memory resource for device %x, bus %x, [%x - %x]\n", new_mem->devfunc, new_mem->busno, new_mem->start, new_mem->end);
+
+			} else if ((curr->rsrc_type & RESTYPE) == PFMASK) {
+				/* PFMemory resource */
+				new_pfmem = alloc_resources (curr);
+				if (!new_pfmem)
+					return -ENOMEM;
+				new_pfmem->type = PFMEM;
+				new_pfmem->fromMem = FALSE;
+				if (ibmphp_add_resource (new_pfmem) < 0) {
+					newbus = alloc_error_bus (curr, 0, 0);
+					if (!newbus)
+						return -ENOMEM;
+					newbus->firstPFMem = new_pfmem;
+					++newbus->needPFMemUpdate;
+					new_pfmem->rangeno = -1;
+				}
+
+				debug ("PFMemory resource for device %x, bus %x, [%x - %x]\n", new_pfmem->devfunc, new_pfmem->busno, new_pfmem->start, new_pfmem->end);
+			} else if ((curr->rsrc_type & RESTYPE) == IOMASK) {
+				/* IO resource */
+				new_io = alloc_resources (curr);
+				if (!new_io)
+					return -ENOMEM;
+				new_io->type = IO;
+
+				/*
+				 * if it didn't find the bus, means PCI dev
+				 * came b4 the Primary Bus info, so need to
+				 * create a bus rangeno becomes a problem...
+				 * Can assign a -1 and then update once the
+				 * range actually appears...
+				 */
+				if (ibmphp_add_resource (new_io) < 0) {
+					newbus = alloc_error_bus (curr, 0, 0);
+					if (!newbus)
+						return -ENOMEM;
+					newbus->firstIO = new_io;
+					++newbus->needIOUpdate;
+					new_io->rangeno = -1;
+				}
+				debug ("IO resource for device %x, bus %x, [%x - %x]\n", new_io->devfunc, new_io->busno, new_io->start, new_io->end);
+			}
+		}
+	}
+
+	list_for_each (tmp, &gbuses) {
+		bus_cur = list_entry (tmp, struct bus_node, bus_list);
+		/* This is to get info about PPB resources, since EBDA doesn't put this info into the primary bus info */
+		rc = update_bridge_ranges (&bus_cur);
+		if (rc)
+			return rc;
+	}
+	rc = once_over ();  /* This is to align ranges (so no -1) */
+	if (rc)
+		return rc;
+	return 0;
+}
+
+/********************************************************************************
+ * This function adds a range into a sorted list of ranges per bus for a particular
+ * range type, it then calls another routine to update the range numbers on the
+ * pci devices' resources for the appropriate resource
+ *
+ * Input: type of the resource, range to add, current bus
+ * Output: 0 or -1, bus and range ptrs 
+ ********************************************************************************/
+static int add_range (int type, struct range_node *range, struct bus_node *bus_cur)
+{
+	struct range_node *range_cur = NULL;
+	struct range_node *range_prev;
+	int count = 0, i_init;
+	int noRanges = 0;
+
+	switch (type) {
+		case MEM:
+			range_cur = bus_cur->rangeMem;
+			noRanges = bus_cur->noMemRanges;
+			break;
+		case PFMEM:
+			range_cur = bus_cur->rangePFMem;
+			noRanges = bus_cur->noPFMemRanges;
+			break;
+		case IO:
+			range_cur = bus_cur->rangeIO;
+			noRanges = bus_cur->noIORanges;
+			break;
+	}
+
+	range_prev = NULL;
+	while (range_cur) {
+		if (range->start < range_cur->start)
+			break;
+		range_prev = range_cur;
+		range_cur = range_cur->next;
+		count = count + 1;
+	}
+	if (!count) {
+		/* our range will go at the beginning of the list */
+		switch (type) {
+			case MEM:
+				bus_cur->rangeMem = range;
+				break;
+			case PFMEM:
+				bus_cur->rangePFMem = range;
+				break;
+			case IO:
+				bus_cur->rangeIO = range;
+				break;
+		}
+		range->next = range_cur;
+		range->rangeno = 1;
+		i_init = 0;
+	} else if (!range_cur) {
+		/* our range will go at the end of the list */
+		range->next = NULL;
+		range_prev->next = range;
+		range->rangeno = range_prev->rangeno + 1;
+		return 0;
+	} else {
+		/* the range is in the middle */
+		range_prev->next = range;
+		range->next = range_cur;
+		range->rangeno = range_cur->rangeno;
+		i_init = range_prev->rangeno;
+	}
+
+	for (count = i_init; count < noRanges; ++count) {
+		++range_cur->rangeno;
+		range_cur = range_cur->next;
+	}
+
+	update_resources (bus_cur, type, i_init + 1);
+	return 0;
+}
+
+/*******************************************************************************
+ * This routine goes through the list of resources of type 'type' and updates
+ * the range numbers that they correspond to.  It was called from add_range fnc
+ *
+ * Input: bus, type of the resource, the rangeno starting from which to update
+ ******************************************************************************/
+static void update_resources (struct bus_node *bus_cur, int type, int rangeno)
+{
+	struct resource_node *res = NULL;
+	u8 eol = FALSE;	/* end of list indicator */
+
+	switch (type) {
+		case MEM:
+			if (bus_cur->firstMem) 
+				res = bus_cur->firstMem;
+			break;
+		case PFMEM:
+			if (bus_cur->firstPFMem)
+				res = bus_cur->firstPFMem;
+			break;
+		case IO:
+			if (bus_cur->firstIO)
+				res = bus_cur->firstIO;
+			break;
+	}
+
+	if (res) {
+		while (res) {
+			if (res->rangeno == rangeno)
+				break;
+			if (res->next)
+				res = res->next;
+			else if (res->nextRange)
+				res = res->nextRange;
+			else {
+				eol = TRUE;
+				break;
+			}
+		}
+
+		if (!eol) {
+			/* found the range */
+			while (res) {
+				++res->rangeno;
+				res = res->next;
+			}
+		}
+	}
+}
+
+static void fix_me (struct resource_node *res, struct bus_node *bus_cur, struct range_node *range)
+{
+	char * str = "";
+	switch (res->type) {
+		case IO:
+			str = "io";
+			break;
+		case MEM:
+			str = "mem";
+			break;
+		case PFMEM:
+			str = "pfmem";
+			break;
+	}
+
+	while (res) {
+		if (res->rangeno == -1) {
+			while (range) {
+				if ((res->start >= range->start) && (res->end <= range->end)) {
+					res->rangeno = range->rangeno;
+					debug ("%s->rangeno in fix_resources is %d\n", str, res->rangeno);
+					switch (res->type) {
+						case IO:
+							--bus_cur->needIOUpdate;
+							break;
+						case MEM:
+							--bus_cur->needMemUpdate;
+							break;
+						case PFMEM:
+							--bus_cur->needPFMemUpdate;
+							break;
+					}
+					break;
+				}
+				range = range->next;
+			}
+		}
+		if (res->next)
+			res = res->next;
+		else
+			res = res->nextRange;
+	}
+
+}
+
+/*****************************************************************************
+ * This routine reassigns the range numbers to the resources that had a -1
+ * This case can happen only if upon initialization, resources taken by pci dev
+ * appear in EBDA before the resources allocated for that bus, since we don't
+ * know the range, we assign -1, and this routine is called after a new range
+ * is assigned to see the resources with unknown range belong to the added range
+ *
+ * Input: current bus
+ * Output: none, list of resources for that bus are fixed if can be
+ *******************************************************************************/
+static void fix_resources (struct bus_node *bus_cur)
+{
+	struct range_node *range;
+	struct resource_node *res;
+
+	debug ("%s - bus_cur->busno = %d\n", __FUNCTION__, bus_cur->busno);
+
+	if (bus_cur->needIOUpdate) {
+		res = bus_cur->firstIO;
+		range = bus_cur->rangeIO;
+		fix_me (res, bus_cur, range);
+	}
+	if (bus_cur->needMemUpdate) {
+		res = bus_cur->firstMem;
+		range = bus_cur->rangeMem;
+		fix_me (res, bus_cur, range);
+	}
+	if (bus_cur->needPFMemUpdate) {
+		res = bus_cur->firstPFMem;
+		range = bus_cur->rangePFMem;
+		fix_me (res, bus_cur, range);
+	}
+}
+
+/*******************************************************************************
+ * This routine adds a resource to the list of resources to the appropriate bus 
+ * based on their resource type and sorted by their starting addresses.  It assigns
+ * the ptrs to next and nextRange if needed.
+ *
+ * Input: resource ptr
+ * Output: ptrs assigned (to the node)
+ * 0 or -1
+ *******************************************************************************/
+int ibmphp_add_resource (struct resource_node *res)
+{
+	struct resource_node *res_cur;
+	struct resource_node *res_prev;
+	struct bus_node *bus_cur;
+	struct range_node *range_cur = NULL;
+	struct resource_node *res_start = NULL;
+
+	debug ("%s - enter\n", __FUNCTION__);
+
+	if (!res) {
+		err ("NULL passed to add \n");
+		return -ENODEV;
+	}
+	
+	bus_cur = find_bus_wprev (res->busno, NULL, 0);
+	
+	if (!bus_cur) {
+		/* didn't find a bus, smth's wrong!!! */
+		debug ("no bus in the system, either pci_dev's wrong or allocation failed\n");
+		return -ENODEV;
+	}
+
+	/* Normal case */
+	switch (res->type) {
+		case IO:
+			range_cur = bus_cur->rangeIO;
+			res_start = bus_cur->firstIO;
+			break;
+		case MEM:
+			range_cur = bus_cur->rangeMem;
+			res_start = bus_cur->firstMem;
+			break;
+		case PFMEM:
+			range_cur = bus_cur->rangePFMem;
+			res_start = bus_cur->firstPFMem;
+			break;
+		default:
+			err ("cannot read the type of the resource to add... problem \n");
+			return -EINVAL;
+	}
+	while (range_cur) {
+		if ((res->start >= range_cur->start) && (res->end <= range_cur->end)) {
+			res->rangeno = range_cur->rangeno;
+			break;
+		}
+		range_cur = range_cur->next;
+	}
+
+	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+	 * this is again the case of rangeno = -1
+	 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+	 */
+
+	if (!range_cur) {
+		switch (res->type) {
+			case IO:
+				++bus_cur->needIOUpdate;					
+				break;
+			case MEM:
+				++bus_cur->needMemUpdate;
+				break;
+			case PFMEM:
+				++bus_cur->needPFMemUpdate;
+				break;
+		}
+		res->rangeno = -1;
+	}
+	
+	debug ("The range is %d\n", res->rangeno);
+	if (!res_start) {
+		/* no first{IO,Mem,Pfmem} on the bus, 1st IO/Mem/Pfmem resource ever */
+		switch (res->type) {
+			case IO:
+				bus_cur->firstIO = res;					
+				break;
+			case MEM:
+				bus_cur->firstMem = res;
+				break;
+			case PFMEM:
+				bus_cur->firstPFMem = res;
+				break;
+		}	
+		res->next = NULL;
+		res->nextRange = NULL;
+	} else {
+		res_cur = res_start;
+		res_prev = NULL;
+
+		debug ("res_cur->rangeno is %d\n", res_cur->rangeno);
+
+		while (res_cur) {
+			if (res_cur->rangeno >= res->rangeno)
+				break;
+			res_prev = res_cur;
+			if (res_cur->next)
+				res_cur = res_cur->next;
+			else
+				res_cur = res_cur->nextRange;
+		}
+
+		if (!res_cur) {
+			/* at the end of the resource list */
+			debug ("i should be here, [%x - %x]\n", res->start, res->end);
+			res_prev->nextRange = res;
+			res->next = NULL;
+			res->nextRange = NULL;
+		} else if (res_cur->rangeno == res->rangeno) {
+			/* in the same range */
+			while (res_cur) {
+				if (res->start < res_cur->start)
+					break;
+				res_prev = res_cur;
+				res_cur = res_cur->next;
+			}
+			if (!res_cur) {
+				/* the last resource in this range */
+				res_prev->next = res;
+				res->next = NULL;
+				res->nextRange = res_prev->nextRange;
+				res_prev->nextRange = NULL;
+			} else if (res->start < res_cur->start) {
+				/* at the beginning or middle of the range */
+				if (!res_prev)	{
+					switch (res->type) {
+						case IO:
+							bus_cur->firstIO = res;
+							break;
+						case MEM:
+							bus_cur->firstMem = res;
+							break;
+						case PFMEM:
+							bus_cur->firstPFMem = res;
+							break;
+					}
+				} else if (res_prev->rangeno == res_cur->rangeno)
+					res_prev->next = res;
+				else
+					res_prev->nextRange = res;
+
+				res->next = res_cur;
+				res->nextRange = NULL;
+			}
+		} else {
+			/* this is the case where it is 1st occurrence of the range */
+			if (!res_prev) {
+				/* at the beginning of the resource list */
+				res->next = NULL;
+				switch (res->type) {
+					case IO:
+						res->nextRange = bus_cur->firstIO;
+						bus_cur->firstIO = res;
+						break;
+					case MEM:
+						res->nextRange = bus_cur->firstMem;
+						bus_cur->firstMem = res;
+						break;
+					case PFMEM:
+						res->nextRange = bus_cur->firstPFMem;
+						bus_cur->firstPFMem = res;
+						break;
+				}
+			} else if (res_cur->rangeno > res->rangeno) {
+				/* in the middle of the resource list */
+				res_prev->nextRange = res;
+				res->next = NULL;
+				res->nextRange = res_cur;
+			}
+		}
+	}
+
+	debug ("%s - exit\n", __FUNCTION__);
+	return 0;
+}
+
+/****************************************************************************
+ * This routine will remove the resource from the list of resources
+ *
+ * Input: io, mem, and/or pfmem resource to be deleted
+ * Ouput: modified resource list
+ *        0 or error code
+ ****************************************************************************/
+int ibmphp_remove_resource (struct resource_node *res)
+{
+	struct bus_node *bus_cur;
+	struct resource_node *res_cur = NULL;
+	struct resource_node *res_prev;
+	struct resource_node *mem_cur;
+	char * type = "";
+
+	if (!res)  {
+		err ("resource to remove is NULL \n");
+		return -ENODEV;
+	}
+
+	bus_cur = find_bus_wprev (res->busno, NULL, 0);
+
+	if (!bus_cur) {
+		err ("cannot find corresponding bus of the io resource to remove  "
+			"bailing out...\n");
+		return -ENODEV;
+	}
+
+	switch (res->type) {
+		case IO:
+			res_cur = bus_cur->firstIO;
+			type = "io";
+			break;
+		case MEM:
+			res_cur = bus_cur->firstMem;
+			type = "mem";
+			break;
+		case PFMEM:
+			res_cur = bus_cur->firstPFMem;
+			type = "pfmem";
+			break;
+		default:
+			err ("unknown type for resource to remove \n");
+			return -EINVAL;
+	}
+	res_prev = NULL;
+
+	while (res_cur) {
+		if ((res_cur->start == res->start) && (res_cur->end == res->end))
+			break;
+		res_prev = res_cur;
+		if (res_cur->next)
+			res_cur = res_cur->next;
+		else
+			res_cur = res_cur->nextRange;
+	}
+
+	if (!res_cur) {
+		if (res->type == PFMEM) {
+			/* 
+			 * case where pfmem might be in the PFMemFromMem list
+			 * so will also need to remove the corresponding mem
+			 * entry
+			 */
+			res_cur = bus_cur->firstPFMemFromMem;
+			res_prev = NULL;
+
+			while (res_cur) {
+				if ((res_cur->start == res->start) && (res_cur->end == res->end)) {
+					mem_cur = bus_cur->firstMem;
+					while (mem_cur) {
+						if ((mem_cur->start == res_cur->start)
+						    && (mem_cur->end == res_cur->end))
+							break;
+						if (mem_cur->next)
+							mem_cur = mem_cur->next;
+						else
+							mem_cur = mem_cur->nextRange;
+					}
+					if (!mem_cur) {
+						err ("cannot find corresponding mem node for pfmem...\n");
+						return -EINVAL;
+					}
+
+					ibmphp_remove_resource (mem_cur);
+					if (!res_prev)
+						bus_cur->firstPFMemFromMem = res_cur->next;
+					else
+						res_prev->next = res_cur->next;
+					kfree (res_cur);
+					return 0;
+				}
+				res_prev = res_cur;
+				if (res_cur->next)
+					res_cur = res_cur->next;
+				else
+					res_cur = res_cur->nextRange;
+			}
+			if (!res_cur) {
+				err ("cannot find pfmem to delete...\n");
+				return -EINVAL;
+			}
+		} else {
+			err ("the %s resource is not in the list to be deleted...\n", type);
+			return -EINVAL;
+		}
+	}
+	if (!res_prev) {
+		/* first device to be deleted */
+		if (res_cur->next) {
+			switch (res->type) {
+				case IO:
+					bus_cur->firstIO = res_cur->next;
+					break;
+				case MEM:
+					bus_cur->firstMem = res_cur->next;
+					break;
+				case PFMEM:
+					bus_cur->firstPFMem = res_cur->next;
+					break;
+			}
+		} else if (res_cur->nextRange) {
+			switch (res->type) {
+				case IO:
+					bus_cur->firstIO = res_cur->nextRange;
+					break;
+				case MEM:
+					bus_cur->firstMem = res_cur->nextRange;
+					break;
+				case PFMEM:
+					bus_cur->firstPFMem = res_cur->nextRange;
+					break;
+			}
+		} else {
+			switch (res->type) {
+				case IO:
+					bus_cur->firstIO = NULL;
+					break;
+				case MEM:
+					bus_cur->firstMem = NULL;
+					break;
+				case PFMEM:
+					bus_cur->firstPFMem = NULL;
+					break;
+			}
+		}
+		kfree (res_cur);
+		return 0;
+	} else {
+		if (res_cur->next) {
+			if (res_prev->rangeno == res_cur->rangeno)
+				res_prev->next = res_cur->next;
+			else
+				res_prev->nextRange = res_cur->next;
+		} else if (res_cur->nextRange) {
+			res_prev->next = NULL;
+			res_prev->nextRange = res_cur->nextRange;
+		} else {
+			res_prev->next = NULL;
+			res_prev->nextRange = NULL;
+		}
+		kfree (res_cur);
+		return 0;
+	}
+
+	return 0;
+}
+
+static struct range_node * find_range (struct bus_node *bus_cur, struct resource_node * res)
+{
+	struct range_node * range = NULL;
+
+	switch (res->type) {
+		case IO:
+			range = bus_cur->rangeIO;
+			break;
+		case MEM:
+			range = bus_cur->rangeMem;
+			break;
+		case PFMEM:
+			range = bus_cur->rangePFMem;
+			break;
+		default:
+			err ("cannot read resource type in find_range \n");
+	}
+
+	while (range) {
+		if (res->rangeno == range->rangeno)
+			break;
+		range = range->next;
+	}
+	return range;
+}
+
+/*****************************************************************************
+ * This routine will check to make sure the io/mem/pfmem->len that the device asked for 
+ * can fit w/i our list of available IO/MEM/PFMEM resources.  If cannot, returns -EINVAL,
+ * otherwise, returns 0
+ *
+ * Input: resource
+ * Ouput: the correct start and end address are inputted into the resource node,
+ *        0 or -EINVAL
+ *****************************************************************************/
+int ibmphp_check_resource (struct resource_node *res, u8 bridge)
+{
+	struct bus_node *bus_cur;
+	struct range_node *range = NULL;
+	struct resource_node *res_prev;
+	struct resource_node *res_cur = NULL;
+	u32 len_cur = 0, start_cur = 0, len_tmp = 0;
+	int noranges = 0;
+	u32 tmp_start;		/* this is to make sure start address is divisible by the length needed */
+	u32 tmp_divide;
+	u8 flag = FALSE;
+
+	if (!res)
+		return -EINVAL;
+
+	if (bridge) {
+		/* The rules for bridges are different, 4K divisible for IO, 1M for (pf)mem*/
+		if (res->type == IO)
+			tmp_divide = IOBRIDGE;
+		else
+			tmp_divide = MEMBRIDGE;
+	} else
+		tmp_divide = res->len;
+
+	bus_cur = find_bus_wprev (res->busno, NULL, 0);
+
+	if (!bus_cur) {
+		/* didn't find a bus, smth's wrong!!! */
+		debug ("no bus in the system, either pci_dev's wrong or allocation failed \n");
+		return -EINVAL;
+	}
+
+	debug ("%s - enter\n", __FUNCTION__);
+	debug ("bus_cur->busno is %d\n", bus_cur->busno);
+
+	/* This is a quick fix to not mess up with the code very much.  i.e.,
+	 * 2000-2fff, len = 1000, but when we compare, we need it to be fff */
+	res->len -= 1;
+
+	switch (res->type) {
+		case IO:
+			res_cur = bus_cur->firstIO;
+			noranges = bus_cur->noIORanges;
+			break;
+		case MEM:
+			res_cur = bus_cur->firstMem;
+			noranges = bus_cur->noMemRanges;
+			break;
+		case PFMEM:
+			res_cur = bus_cur->firstPFMem;
+			noranges = bus_cur->noPFMemRanges;
+			break;
+		default:
+			err ("wrong type of resource to check \n");
+			return -EINVAL;
+	}
+	res_prev = NULL;
+
+	while (res_cur) {
+		range = find_range (bus_cur, res_cur);
+		debug ("%s - rangeno = %d\n", __FUNCTION__, res_cur->rangeno);
+
+		if (!range) {
+			err ("no range for the device exists... bailing out...\n");
+			return -EINVAL;
+		}
+
+		/* found our range */
+		if (!res_prev) {
+			/* first time in the loop */
+			if ((res_cur->start != range->start) && ((len_tmp = res_cur->start - 1 - range->start) >= res->len)) {
+				debug ("len_tmp = %x\n", len_tmp);
+
+				if ((len_tmp < len_cur) || (len_cur == 0)) {
+
+					if ((range->start % tmp_divide) == 0) {
+						/* just perfect, starting address is divisible by length */
+						flag = TRUE;
+						len_cur = len_tmp;
+						start_cur = range->start;
+					} else {
+						/* Needs adjusting */
+						tmp_start = range->start;
+						flag = FALSE;
+
+						while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
+							if ((tmp_start % tmp_divide) == 0) {
+								flag = TRUE;
+								len_cur = len_tmp;
+								start_cur = tmp_start;
+								break;
+							}
+							tmp_start += tmp_divide - tmp_start % tmp_divide;
+							if (tmp_start >= res_cur->start - 1)
+								break;
+						}
+					}
+			
+					if (flag && len_cur == res->len) {
+						debug ("but we are not here, right?\n");
+						res->start = start_cur;
+						res->len += 1; /* To restore the balance */
+						res->end = res->start + res->len - 1;
+						return 0;
+					}
+				}
+			}
+		}
+		if (!res_cur->next) {
+			/* last device on the range */
+			if ((range->end != res_cur->end) && ((len_tmp = range->end - (res_cur->end + 1)) >= res->len)) {
+				debug ("len_tmp = %x\n", len_tmp);
+				if ((len_tmp < len_cur) || (len_cur == 0)) {
+
+					if (((res_cur->end + 1) % tmp_divide) == 0) {
+						/* just perfect, starting address is divisible by length */
+						flag = TRUE;
+						len_cur = len_tmp;
+						start_cur = res_cur->end + 1;
+					} else {
+						/* Needs adjusting */
+						tmp_start = res_cur->end + 1;
+						flag = FALSE;
+
+						while ((len_tmp = range->end - tmp_start) >= res->len) {
+							if ((tmp_start % tmp_divide) == 0) {
+								flag = TRUE;
+								len_cur = len_tmp;
+								start_cur = tmp_start;
+								break;
+							}
+							tmp_start += tmp_divide - tmp_start % tmp_divide;
+							if (tmp_start >= range->end)
+								break;
+						}
+					}
+					if (flag && len_cur == res->len) {
+						res->start = start_cur;
+						res->len += 1; /* To restore the balance */
+						res->end = res->start + res->len - 1;
+						return 0;
+					}
+				}
+			}
+		}
+
+		if (res_prev) {
+			if (res_prev->rangeno != res_cur->rangeno) {
+				/* 1st device on this range */
+				if ((res_cur->start != range->start) && 
+					((len_tmp = res_cur->start - 1 - range->start) >= res->len)) {
+					if ((len_tmp < len_cur) || (len_cur == 0)) {
+						if ((range->start % tmp_divide) == 0) {	
+							/* just perfect, starting address is divisible by length */
+							flag = TRUE;
+							len_cur = len_tmp;
+							start_cur = range->start;
+						} else {
+							/* Needs adjusting */
+							tmp_start = range->start;
+							flag = FALSE;
+
+							while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
+								if ((tmp_start % tmp_divide) == 0) {
+									flag = TRUE;
+									len_cur = len_tmp;
+									start_cur = tmp_start;
+									break;
+								}
+								tmp_start += tmp_divide - tmp_start % tmp_divide;
+								if (tmp_start >= res_cur->start - 1)
+									break;
+							}
+						}
+
+						if (flag && len_cur == res->len) {
+							res->start = start_cur;
+							res->len += 1; /* To restore the balance */
+							res->end = res->start + res->len - 1;
+							return 0;
+						}
+					}
+				}
+			} else {
+				/* in the same range */
+				if ((len_tmp = res_cur->start - 1 - res_prev->end - 1) >= res->len) {
+					if ((len_tmp < len_cur) || (len_cur == 0)) {
+						if (((res_prev->end + 1) % tmp_divide) == 0) {
+							/* just perfect, starting address's divisible by length */
+							flag = TRUE;
+							len_cur = len_tmp;
+							start_cur = res_prev->end + 1;
+						} else {
+							/* Needs adjusting */
+							tmp_start = res_prev->end + 1;
+							flag = FALSE;
+
+							while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
+								if ((tmp_start % tmp_divide) == 0) {
+									flag = TRUE;
+									len_cur = len_tmp;
+									start_cur = tmp_start;
+									break;
+								}
+								tmp_start += tmp_divide - tmp_start % tmp_divide;
+								if (tmp_start >= res_cur->start - 1)
+									break;
+							}
+						}
+
+						if (flag && len_cur == res->len) {
+							res->start = start_cur;
+							res->len += 1; /* To restore the balance */
+							res->end = res->start + res->len - 1;
+							return 0;
+						}
+					}
+				}
+			}
+		}
+		/* end if (res_prev) */
+		res_prev = res_cur;
+		if (res_cur->next)
+			res_cur = res_cur->next;
+		else
+			res_cur = res_cur->nextRange;
+	}	/* end of while */
+
+
+	if (!res_prev) {
+		/* 1st device ever */
+		/* need to find appropriate range */
+		switch (res->type) {
+			case IO:
+				range = bus_cur->rangeIO;
+				break;
+			case MEM:
+				range = bus_cur->rangeMem;
+				break;
+			case PFMEM:
+				range = bus_cur->rangePFMem;
+				break;
+		}
+		while (range) {
+			if ((len_tmp = range->end - range->start) >= res->len) {
+				if ((len_tmp < len_cur) || (len_cur == 0)) {
+					if ((range->start % tmp_divide) == 0) {
+						/* just perfect, starting address's divisible by length */
+						flag = TRUE;
+						len_cur = len_tmp;
+						start_cur = range->start;
+					} else {
+						/* Needs adjusting */
+						tmp_start = range->start;
+						flag = FALSE;
+
+						while ((len_tmp = range->end - tmp_start) >= res->len) {
+							if ((tmp_start % tmp_divide) == 0) {
+								flag = TRUE;
+								len_cur = len_tmp;
+								start_cur = tmp_start;
+								break;
+							}
+							tmp_start += tmp_divide - tmp_start % tmp_divide;
+							if (tmp_start >= range->end)
+								break;
+						}
+					}
+
+					if (flag && len_cur == res->len) {
+						res->start = start_cur;
+						res->len += 1; /* To restore the balance */
+						res->end = res->start + res->len - 1;
+						return 0;
+					}
+				}
+			}
+			range = range->next;
+		}		/* end of while */
+
+		if ((!range) && (len_cur == 0)) {
+			/* have gone through the list of devices and ranges and haven't found n.e.thing */
+			err ("no appropriate range.. bailing out...\n");
+			return -EINVAL;
+		} else if (len_cur) {
+			res->start = start_cur;
+			res->len += 1; /* To restore the balance */
+			res->end = res->start + res->len - 1;
+			return 0;
+		}
+	}
+
+	if (!res_cur) {
+		debug ("prev->rangeno = %d, noranges = %d\n", res_prev->rangeno, noranges);
+		if (res_prev->rangeno < noranges) {
+			/* if there're more ranges out there to check */
+			switch (res->type) {
+				case IO:
+					range = bus_cur->rangeIO;
+					break;
+				case MEM:
+					range = bus_cur->rangeMem;
+					break;
+				case PFMEM:
+					range = bus_cur->rangePFMem;
+					break;
+			}
+			while (range) {
+				if ((len_tmp = range->end - range->start) >= res->len) {
+					if ((len_tmp < len_cur) || (len_cur == 0)) {
+						if ((range->start % tmp_divide) == 0) {
+							/* just perfect, starting address's divisible by length */
+							flag = TRUE;
+							len_cur = len_tmp;
+							start_cur = range->start;
+						} else {
+							/* Needs adjusting */
+							tmp_start = range->start;
+							flag = FALSE;
+
+							while ((len_tmp = range->end - tmp_start) >= res->len) {
+								if ((tmp_start % tmp_divide) == 0) {
+									flag = TRUE;
+									len_cur = len_tmp;
+									start_cur = tmp_start;
+									break;
+								}
+								tmp_start += tmp_divide - tmp_start % tmp_divide;
+								if (tmp_start >= range->end)
+									break;
+							}
+						}
+
+						if (flag && len_cur == res->len) {
+							res->start = start_cur;
+							res->len += 1; /* To restore the balance */
+							res->end = res->start + res->len - 1;
+							return 0;
+						}
+					}
+				}
+				range = range->next;
+			}	/* end of while */
+
+			if ((!range) && (len_cur == 0)) {
+				/* have gone through the list of devices and ranges and haven't found n.e.thing */
+				err ("no appropriate range.. bailing out...\n");
+				return -EINVAL;
+			} else if (len_cur) {
+				res->start = start_cur;
+				res->len += 1; /* To restore the balance */
+				res->end = res->start + res->len - 1;
+				return 0;
+			}
+		} else {
+			/* no more ranges to check on */
+			if (len_cur) {
+				res->start = start_cur;
+				res->len += 1; /* To restore the balance */
+				res->end = res->start + res->len - 1;
+				return 0;
+			} else {
+				/* have gone through the list of devices and haven't found n.e.thing */
+				err ("no appropriate range.. bailing out...\n");
+				return -EINVAL;
+			}
+		}
+	}	/* end if(!res_cur) */
+	return -EINVAL;
+}
+
+/********************************************************************************
+ * This routine is called from remove_card if the card contained PPB.
+ * It will remove all the resources on the bus as well as the bus itself
+ * Input: Bus
+ * Ouput: 0, -ENODEV
+ ********************************************************************************/
+int ibmphp_remove_bus (struct bus_node *bus, u8 parent_busno)
+{
+	struct resource_node *res_cur;
+	struct resource_node *res_tmp;
+	struct bus_node *prev_bus;
+	int rc;
+
+	prev_bus = find_bus_wprev (parent_busno, NULL, 0);	
+
+	if (!prev_bus) {
+		debug ("something terribly wrong. Cannot find parent bus to the one to remove\n");
+		return -ENODEV;
+	}
+
+	debug ("In ibmphp_remove_bus... prev_bus->busno is %x\n", prev_bus->busno);
+
+	rc = remove_ranges (bus, prev_bus);
+	if (rc)
+		return rc;
+
+	if (bus->firstIO) {
+		res_cur = bus->firstIO;
+		while (res_cur) {
+			res_tmp = res_cur;
+			if (res_cur->next)
+				res_cur = res_cur->next;
+			else
+				res_cur = res_cur->nextRange;
+			kfree (res_tmp);
+			res_tmp = NULL;
+		}
+		bus->firstIO = NULL;
+	}
+	if (bus->firstMem) {
+		res_cur = bus->firstMem;
+		while (res_cur) {
+			res_tmp = res_cur;
+			if (res_cur->next)
+				res_cur = res_cur->next;
+			else
+				res_cur = res_cur->nextRange;
+			kfree (res_tmp);
+			res_tmp = NULL;
+		}
+		bus->firstMem = NULL;
+	}
+	if (bus->firstPFMem) {
+		res_cur = bus->firstPFMem;
+		while (res_cur) {
+			res_tmp = res_cur;
+			if (res_cur->next)
+				res_cur = res_cur->next;
+			else
+				res_cur = res_cur->nextRange;
+			kfree (res_tmp);
+			res_tmp = NULL;
+		}
+		bus->firstPFMem = NULL;
+	}
+
+	if (bus->firstPFMemFromMem) {
+		res_cur = bus->firstPFMemFromMem;
+		while (res_cur) {
+			res_tmp = res_cur;
+			res_cur = res_cur->next;
+
+			kfree (res_tmp);
+			res_tmp = NULL;
+		}
+		bus->firstPFMemFromMem = NULL;
+	}
+
+	list_del (&bus->bus_list);
+	kfree (bus);
+	return 0;
+}
+
+/******************************************************************************
+ * This routine deletes the ranges from a given bus, and the entries from the 
+ * parent's bus in the resources
+ * Input: current bus, previous bus
+ * Output: 0, -EINVAL
+ ******************************************************************************/
+static int remove_ranges (struct bus_node *bus_cur, struct bus_node *bus_prev)
+{
+	struct range_node *range_cur;
+	struct range_node *range_tmp;
+	int i;
+	struct resource_node *res = NULL;
+
+	if (bus_cur->noIORanges) {
+		range_cur = bus_cur->rangeIO;
+		for (i = 0; i < bus_cur->noIORanges; i++) {
+			if (ibmphp_find_resource (bus_prev, range_cur->start, &res, IO) < 0)
+				return -EINVAL;
+			ibmphp_remove_resource (res);
+
+			range_tmp = range_cur;
+			range_cur = range_cur->next;
+			kfree (range_tmp);
+			range_tmp = NULL;
+		}
+		bus_cur->rangeIO = NULL;
+	}
+	if (bus_cur->noMemRanges) {
+		range_cur = bus_cur->rangeMem;
+		for (i = 0; i < bus_cur->noMemRanges; i++) {
+			if (ibmphp_find_resource (bus_prev, range_cur->start, &res, MEM) < 0) 
+				return -EINVAL;
+
+			ibmphp_remove_resource (res);
+			range_tmp = range_cur;
+			range_cur = range_cur->next;
+			kfree (range_tmp);
+			range_tmp = NULL;
+		}
+		bus_cur->rangeMem = NULL;
+	}
+	if (bus_cur->noPFMemRanges) {
+		range_cur = bus_cur->rangePFMem;
+		for (i = 0; i < bus_cur->noPFMemRanges; i++) {
+			if (ibmphp_find_resource (bus_prev, range_cur->start, &res, PFMEM) < 0) 
+				return -EINVAL;
+
+			ibmphp_remove_resource (res);
+			range_tmp = range_cur;
+			range_cur = range_cur->next;
+			kfree (range_tmp);
+			range_tmp = NULL;
+		}
+		bus_cur->rangePFMem = NULL;
+	}
+	return 0;
+}
+
+/*
+ * find the resource node in the bus 
+ * Input: Resource needed, start address of the resource, type of resource
+ */
+int ibmphp_find_resource (struct bus_node *bus, u32 start_address, struct resource_node **res, int flag)
+{
+	struct resource_node *res_cur = NULL;
+	char * type = "";
+
+	if (!bus) {
+		err ("The bus passed in NULL to find resource \n");
+		return -ENODEV;
+	}
+
+	switch (flag) {
+		case IO:
+			res_cur = bus->firstIO;
+			type = "io";
+			break;
+		case MEM:
+			res_cur = bus->firstMem;
+			type = "mem";
+			break;
+		case PFMEM:
+			res_cur = bus->firstPFMem;
+			type = "pfmem";
+			break;
+		default:
+			err ("wrong type of flag \n");
+			return -EINVAL;
+	}
+	
+	while (res_cur) {
+		if (res_cur->start == start_address) {
+			*res = res_cur;
+			break;
+		}
+		if (res_cur->next)
+			res_cur = res_cur->next;
+		else
+			res_cur = res_cur->nextRange;
+	}
+
+	if (!res_cur) {
+		if (flag == PFMEM) {
+			res_cur = bus->firstPFMemFromMem;
+			while (res_cur) {
+				if (res_cur->start == start_address) {
+					*res = res_cur;
+					break;
+				}
+				res_cur = res_cur->next;
+			}
+			if (!res_cur) {
+				debug ("SOS...cannot find %s resource in the bus. \n", type);
+				return -EINVAL;
+			}
+		} else {
+			debug ("SOS... cannot find %s resource in the bus. \n", type);
+			return -EINVAL;
+		}
+	}
+
+	if (*res)
+		debug ("*res->start = %x \n", (*res)->start);
+
+	return 0;
+}
+
+/***********************************************************************
+ * This routine will free the resource structures used by the
+ * system.  It is called from cleanup routine for the module
+ * Parameters: none
+ * Returns: none
+ ***********************************************************************/
+void ibmphp_free_resources (void)
+{
+	struct bus_node *bus_cur = NULL;
+	struct bus_node *bus_tmp;
+	struct range_node *range_cur;
+	struct range_node *range_tmp;
+	struct resource_node *res_cur;
+	struct resource_node *res_tmp;
+	struct list_head *tmp;
+	struct list_head *next;
+	int i = 0;
+	flags = 1;
+
+	list_for_each_safe (tmp, next, &gbuses) {
+		bus_cur = list_entry (tmp, struct bus_node, bus_list);
+		if (bus_cur->noIORanges) {
+			range_cur = bus_cur->rangeIO;
+			for (i = 0; i < bus_cur->noIORanges; i++) {
+				if (!range_cur)
+					break;
+				range_tmp = range_cur;
+				range_cur = range_cur->next;
+				kfree (range_tmp);
+				range_tmp = NULL;
+			}
+		}
+		if (bus_cur->noMemRanges) {
+			range_cur = bus_cur->rangeMem;
+			for (i = 0; i < bus_cur->noMemRanges; i++) {
+				if (!range_cur)
+					break;
+				range_tmp = range_cur;
+				range_cur = range_cur->next;
+				kfree (range_tmp);
+				range_tmp = NULL;
+			}
+		}
+		if (bus_cur->noPFMemRanges) {
+			range_cur = bus_cur->rangePFMem;
+			for (i = 0; i < bus_cur->noPFMemRanges; i++) {
+				if (!range_cur)
+					break;
+				range_tmp = range_cur;
+				range_cur = range_cur->next;
+				kfree (range_tmp);
+				range_tmp = NULL;
+			}
+		}
+
+		if (bus_cur->firstIO) {
+			res_cur = bus_cur->firstIO;
+			while (res_cur) {
+				res_tmp = res_cur;
+				if (res_cur->next)
+					res_cur = res_cur->next;
+				else
+					res_cur = res_cur->nextRange;
+				kfree (res_tmp);
+				res_tmp = NULL;
+			}
+			bus_cur->firstIO = NULL;
+		}
+		if (bus_cur->firstMem) {
+			res_cur = bus_cur->firstMem;
+			while (res_cur) {
+				res_tmp = res_cur;
+				if (res_cur->next)
+					res_cur = res_cur->next;
+				else
+					res_cur = res_cur->nextRange;
+				kfree (res_tmp);
+				res_tmp = NULL;
+			}
+			bus_cur->firstMem = NULL;
+		}
+		if (bus_cur->firstPFMem) {
+			res_cur = bus_cur->firstPFMem;
+			while (res_cur) {
+				res_tmp = res_cur;
+				if (res_cur->next)
+					res_cur = res_cur->next;
+				else
+					res_cur = res_cur->nextRange;
+				kfree (res_tmp);
+				res_tmp = NULL;
+			}
+			bus_cur->firstPFMem = NULL;
+		}
+
+		if (bus_cur->firstPFMemFromMem) {
+			res_cur = bus_cur->firstPFMemFromMem;
+			while (res_cur) {
+				res_tmp = res_cur;
+				res_cur = res_cur->next;
+
+				kfree (res_tmp);
+				res_tmp = NULL;
+			}
+			bus_cur->firstPFMemFromMem = NULL;
+		}
+
+		bus_tmp = bus_cur;
+		list_del (&bus_cur->bus_list);
+		kfree (bus_tmp);
+		bus_tmp = NULL;
+	}
+}
+
+/*********************************************************************************
+ * This function will go over the PFmem resources to check if the EBDA allocated
+ * pfmem out of memory buckets of the bus.  If so, it will change the range numbers
+ * and a flag to indicate that this resource is out of memory. It will also move the
+ * Pfmem out of the pfmem resource list to the PFMemFromMem list, and will create
+ * a new Mem node
+ * This routine is called right after initialization
+ *******************************************************************************/
+static int __init once_over (void)
+{
+	struct resource_node *pfmem_cur;
+	struct resource_node *pfmem_prev;
+	struct resource_node *mem;
+	struct bus_node *bus_cur;
+	struct list_head *tmp;
+
+	list_for_each (tmp, &gbuses) {
+		bus_cur = list_entry (tmp, struct bus_node, bus_list);
+		if ((!bus_cur->rangePFMem) && (bus_cur->firstPFMem)) {
+			for (pfmem_cur = bus_cur->firstPFMem, pfmem_prev = NULL; pfmem_cur; pfmem_prev = pfmem_cur, pfmem_cur = pfmem_cur->next) {
+				pfmem_cur->fromMem = TRUE;
+				if (pfmem_prev)
+					pfmem_prev->next = pfmem_cur->next;
+				else
+					bus_cur->firstPFMem = pfmem_cur->next;
+
+				if (!bus_cur->firstPFMemFromMem)
+					pfmem_cur->next = NULL;
+				else
+					/* we don't need to sort PFMemFromMem since we're using mem node for
+					   all the real work anyways, so just insert at the beginning of the
+					   list
+					 */
+					pfmem_cur->next = bus_cur->firstPFMemFromMem;
+
+				bus_cur->firstPFMemFromMem = pfmem_cur;
+
+				mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);		
+				if (!mem) {
+					err ("out of system memory \n");
+					return -ENOMEM;
+				}
+				memset (mem, 0, sizeof (struct resource_node));
+				mem->type = MEM;
+				mem->busno = pfmem_cur->busno;
+				mem->devfunc = pfmem_cur->devfunc;
+				mem->start = pfmem_cur->start;
+				mem->end = pfmem_cur->end;
+				mem->len = pfmem_cur->len;
+				if (ibmphp_add_resource (mem) < 0)
+					err ("Trouble...trouble... EBDA allocated pfmem from mem, but system doesn't display it has this space... unless not PCI device...\n");
+				pfmem_cur->rangeno = mem->rangeno;
+			}	/* end for pfmem */
+		}	/* end if */
+	}	/* end list_for_each bus */
+	return 0; 
+}
+
+int ibmphp_add_pfmem_from_mem (struct resource_node *pfmem)
+{
+	struct bus_node *bus_cur = find_bus_wprev (pfmem->busno, NULL, 0);
+
+	if (!bus_cur) {
+		err ("cannot find bus of pfmem to add...\n");
+		return -ENODEV;
+	}
+
+	if (bus_cur->firstPFMemFromMem)
+		pfmem->next = bus_cur->firstPFMemFromMem;
+	else
+		pfmem->next = NULL;
+
+	bus_cur->firstPFMemFromMem = pfmem;
+
+	return 0;
+}
+
+/* This routine just goes through the buses to see if the bus already exists.
+ * It is called from ibmphp_find_sec_number, to find out a secondary bus number for
+ * bridged cards
+ * Parameters: bus_number
+ * Returns: Bus pointer or NULL
+ */
+struct bus_node *ibmphp_find_res_bus (u8 bus_number)
+{
+	return find_bus_wprev (bus_number, NULL, 0);
+}
+
+static inline struct bus_node *find_bus_wprev (u8 bus_number, struct bus_node **prev, u8 flag)
+{
+	struct bus_node *bus_cur;
+	struct list_head *tmp;
+	struct list_head *tmp_prev;
+
+	list_for_each (tmp, &gbuses) {
+		tmp_prev = tmp->prev;
+		bus_cur = list_entry (tmp, struct bus_node, bus_list);
+		if (flag) 
+			*prev = list_entry (tmp_prev, struct bus_node, bus_list);
+		if (bus_cur->busno == bus_number) 
+			return bus_cur;
+	}
+
+	return NULL;
+}
+
+void ibmphp_print_test (void)
+{
+	int i = 0;
+	struct bus_node *bus_cur = NULL;
+	struct range_node *range;
+	struct resource_node *res;
+	struct list_head *tmp;
+	
+	debug_pci ("*****************START**********************\n");
+
+	if ((!list_empty(&gbuses)) && flags) {
+		err ("The GBUSES is not NULL?!?!?!?!?\n");
+		return;
+	}
+
+	list_for_each (tmp, &gbuses) {
+		bus_cur = list_entry (tmp, struct bus_node, bus_list);
+		debug_pci ("This is bus # %d.  There are \n", bus_cur->busno);
+		debug_pci ("IORanges = %d\t", bus_cur->noIORanges);
+		debug_pci ("MemRanges = %d\t", bus_cur->noMemRanges);
+		debug_pci ("PFMemRanges = %d\n", bus_cur->noPFMemRanges);
+		debug_pci ("The IO Ranges are as follows:\n");
+		if (bus_cur->rangeIO) {
+			range = bus_cur->rangeIO;
+			for (i = 0; i < bus_cur->noIORanges; i++) {
+				debug_pci ("rangeno is %d\n", range->rangeno);
+				debug_pci ("[%x - %x]\n", range->start, range->end);
+				range = range->next;
+			}
+		}
+
+		debug_pci ("The Mem Ranges are as follows:\n");
+		if (bus_cur->rangeMem) {
+			range = bus_cur->rangeMem;
+			for (i = 0; i < bus_cur->noMemRanges; i++) {
+				debug_pci ("rangeno is %d\n", range->rangeno);
+				debug_pci ("[%x - %x]\n", range->start, range->end);
+				range = range->next;
+			}
+		}
+
+		debug_pci ("The PFMem Ranges are as follows:\n");
+
+		if (bus_cur->rangePFMem) {
+			range = bus_cur->rangePFMem;
+			for (i = 0; i < bus_cur->noPFMemRanges; i++) {
+				debug_pci ("rangeno is %d\n", range->rangeno);
+				debug_pci ("[%x - %x]\n", range->start, range->end);
+				range = range->next;
+			}
+		}
+
+		debug_pci ("The resources on this bus are as follows\n");
+
+		debug_pci ("IO...\n");
+		if (bus_cur->firstIO) {
+			res = bus_cur->firstIO;
+			while (res) {
+				debug_pci ("The range # is %d\n", res->rangeno);
+				debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
+				debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);
+				if (res->next)
+					res = res->next;
+				else if (res->nextRange)
+					res = res->nextRange;
+				else
+					break;
+			}
+		}
+		debug_pci ("Mem...\n");
+		if (bus_cur->firstMem) {
+			res = bus_cur->firstMem;
+			while (res) {
+				debug_pci ("The range # is %d\n", res->rangeno);
+				debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
+				debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);
+				if (res->next)
+					res = res->next;
+				else if (res->nextRange)
+					res = res->nextRange;
+				else
+					break;
+			}
+		}
+		debug_pci ("PFMem...\n");
+		if (bus_cur->firstPFMem) {
+			res = bus_cur->firstPFMem;
+			while (res) {
+				debug_pci ("The range # is %d\n", res->rangeno);
+				debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
+				debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);
+				if (res->next)
+					res = res->next;
+				else if (res->nextRange)
+					res = res->nextRange;
+				else
+					break;
+			}
+		}
+
+		debug_pci ("PFMemFromMem...\n");
+		if (bus_cur->firstPFMemFromMem) {
+			res = bus_cur->firstPFMemFromMem;
+			while (res) {
+				debug_pci ("The range # is %d\n", res->rangeno);
+				debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
+				debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);
+				res = res->next;
+			}
+		}
+	}
+	debug_pci ("***********************END***********************\n");
+}
+
+static int range_exists_already (struct range_node * range, struct bus_node * bus_cur, u8 type)
+{
+	struct range_node * range_cur = NULL;
+	switch (type) {
+		case IO:
+			range_cur = bus_cur->rangeIO;
+			break;
+		case MEM:
+			range_cur = bus_cur->rangeMem;
+			break;
+		case PFMEM:
+			range_cur = bus_cur->rangePFMem;
+			break;
+		default:
+			err ("wrong type passed to find out if range already exists \n");
+			return -ENODEV;
+	}
+
+	while (range_cur) {
+		if ((range_cur->start == range->start) && (range_cur->end == range->end))
+			return 1;
+		range_cur = range_cur->next;
+	}
+	
+	return 0;
+}
+
+/* This routine will read the windows for any PPB we have and update the
+ * range info for the secondary bus, and will also input this info into
+ * primary bus, since BIOS doesn't. This is for PPB that are in the system
+ * on bootup.  For bridged cards that were added during previous load of the
+ * driver, only the ranges and the bus structure are added, the devices are
+ * added from NVRAM
+ * Input: primary busno
+ * Returns: none
+ * Note: this function doesn't take into account IO restrictions etc,
+ *	 so will only work for bridges with no video/ISA devices behind them It
+ *	 also will not work for onboard PPB's that can have more than 1 *bus
+ *	 behind them All these are TO DO.
+ *	 Also need to add more error checkings... (from fnc returns etc)
+ */
+static int __init update_bridge_ranges (struct bus_node **bus)
+{
+	u8 sec_busno, device, function, hdr_type, start_io_address, end_io_address;
+	u16 vendor_id, upper_io_start, upper_io_end, start_mem_address, end_mem_address;
+	u32 start_address, end_address, upper_start, upper_end;
+	struct bus_node *bus_sec;
+	struct bus_node *bus_cur;
+	struct resource_node *io;
+	struct resource_node *mem;
+	struct resource_node *pfmem;
+	struct range_node *range;
+	unsigned int devfn;
+
+	bus_cur = *bus;
+	if (!bus_cur)
+		return -ENODEV;
+	ibmphp_pci_bus->number = bus_cur->busno;
+
+	debug ("inside %s \n", __FUNCTION__);
+	debug ("bus_cur->busno = %x\n", bus_cur->busno);
+
+	for (device = 0; device < 32; device++) {
+		for (function = 0x00; function < 0x08; function++) {
+			devfn = PCI_DEVFN(device, function);
+			pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id);
+
+			if (vendor_id != PCI_VENDOR_ID_NOTVALID) {
+				/* found correct device!!! */
+				pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type);
+
+				switch (hdr_type) {
+					case PCI_HEADER_TYPE_NORMAL:
+						function = 0x8;
+						break;
+					case PCI_HEADER_TYPE_MULTIDEVICE:
+						break;
+					case PCI_HEADER_TYPE_BRIDGE:
+						function = 0x8;
+					case PCI_HEADER_TYPE_MULTIBRIDGE:
+						/* We assume here that only 1 bus behind the bridge 
+						   TO DO: add functionality for several:
+						   temp = secondary;
+						   while (temp < subordinate) {
+						   ...
+						   temp++;
+						   }
+						 */
+						pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_busno);
+						bus_sec = find_bus_wprev (sec_busno, NULL, 0); 
+						/* this bus structure doesn't exist yet, PPB was configured during previous loading of ibmphp */
+						if (!bus_sec) {
+							bus_sec = alloc_error_bus (NULL, sec_busno, 1);
+							/* the rest will be populated during NVRAM call */
+							return 0;
+						}
+						pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, &start_io_address);
+						pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, &end_io_address);
+						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_IO_BASE_UPPER16, &upper_io_start);
+						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_IO_LIMIT_UPPER16, &upper_io_end);
+						start_address = (start_io_address & PCI_IO_RANGE_MASK) << 8;
+						start_address |= (upper_io_start << 16);
+						end_address = (end_io_address & PCI_IO_RANGE_MASK) << 8;
+						end_address |= (upper_io_end << 16);
+
+						if ((start_address) && (start_address <= end_address)) {
+							range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
+							if (!range) {
+								err ("out of system memory \n");
+								return -ENOMEM;
+							}
+							memset (range, 0, sizeof (struct range_node));
+							range->start = start_address;
+							range->end = end_address + 0xfff;
+
+							if (bus_sec->noIORanges > 0) {
+								if (!range_exists_already (range, bus_sec, IO)) {
+									add_range (IO, range, bus_sec);
+									++bus_sec->noIORanges;
+								} else {
+									kfree (range);
+									range = NULL;
+								}
+							} else {
+								/* 1st IO Range on the bus */
+								range->rangeno = 1;
+								bus_sec->rangeIO = range;
+								++bus_sec->noIORanges;
+							}
+							fix_resources (bus_sec);
+
+							if (ibmphp_find_resource (bus_cur, start_address, &io, IO)) {
+								io = kmalloc (sizeof (struct resource_node), GFP_KERNEL);							
+								if (!io) {
+									kfree (range);
+									err ("out of system memory \n");
+									return -ENOMEM;
+								}
+								memset (io, 0, sizeof (struct resource_node));
+								io->type = IO;
+								io->busno = bus_cur->busno;
+								io->devfunc = ((device << 3) | (function & 0x7));
+								io->start = start_address;
+								io->end = end_address + 0xfff;
+								io->len = io->end - io->start + 1;
+								ibmphp_add_resource (io);
+							}
+						}	
+
+						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, &start_mem_address);
+						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, &end_mem_address);
+
+						start_address = 0x00000000 | (start_mem_address & PCI_MEMORY_RANGE_MASK) << 16;
+						end_address = 0x00000000 | (end_mem_address & PCI_MEMORY_RANGE_MASK) << 16;
+
+						if ((start_address) && (start_address <= end_address)) {
+
+							range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
+							if (!range) {
+								err ("out of system memory \n");
+								return -ENOMEM;
+							}
+							memset (range, 0, sizeof (struct range_node));
+							range->start = start_address;
+							range->end = end_address + 0xfffff;
+
+							if (bus_sec->noMemRanges > 0) {
+								if (!range_exists_already (range, bus_sec, MEM)) {
+									add_range (MEM, range, bus_sec);
+									++bus_sec->noMemRanges;
+								} else {
+									kfree (range);
+									range = NULL;
+								}
+							} else {
+								/* 1st Mem Range on the bus */
+								range->rangeno = 1;
+								bus_sec->rangeMem = range;
+								++bus_sec->noMemRanges;
+							}
+
+							fix_resources (bus_sec);
+
+							if (ibmphp_find_resource (bus_cur, start_address, &mem, MEM)) {
+								mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+								if (!mem) {
+									kfree (range);
+									err ("out of system memory \n");
+									return -ENOMEM;
+								}
+								memset (mem, 0, sizeof (struct resource_node));
+								mem->type = MEM;
+								mem->busno = bus_cur->busno;
+								mem->devfunc = ((device << 3) | (function & 0x7));
+								mem->start = start_address;
+								mem->end = end_address + 0xfffff;
+								mem->len = mem->end - mem->start + 1;
+								ibmphp_add_resource (mem);
+							}
+						}
+						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, &start_mem_address);
+						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &end_mem_address);
+						pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_BASE_UPPER32, &upper_start);
+						pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_LIMIT_UPPER32, &upper_end);
+						start_address = 0x00000000 | (start_mem_address & PCI_MEMORY_RANGE_MASK) << 16;
+						end_address = 0x00000000 | (end_mem_address & PCI_MEMORY_RANGE_MASK) << 16;
+#if BITS_PER_LONG == 64
+						start_address |= ((long) upper_start) << 32;
+						end_address |= ((long) upper_end) << 32;
+#endif
+
+						if ((start_address) && (start_address <= end_address)) {
+
+							range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
+							if (!range) {
+								err ("out of system memory \n");
+								return -ENOMEM;
+							}
+							memset (range, 0, sizeof (struct range_node));
+							range->start = start_address;
+							range->end = end_address + 0xfffff;
+
+							if (bus_sec->noPFMemRanges > 0) {
+								if (!range_exists_already (range, bus_sec, PFMEM)) {
+									add_range (PFMEM, range, bus_sec);
+									++bus_sec->noPFMemRanges;
+								} else {
+									kfree (range);
+									range = NULL;
+								}
+							} else {
+								/* 1st PFMem Range on the bus */
+								range->rangeno = 1;
+								bus_sec->rangePFMem = range;
+								++bus_sec->noPFMemRanges;
+							}
+
+							fix_resources (bus_sec);
+							if (ibmphp_find_resource (bus_cur, start_address, &pfmem, PFMEM)) {
+								pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+								if (!pfmem) {
+									kfree (range);
+									err ("out of system memory \n");
+									return -ENOMEM;
+								}
+								memset (pfmem, 0, sizeof (struct resource_node));
+								pfmem->type = PFMEM;
+								pfmem->busno = bus_cur->busno;
+								pfmem->devfunc = ((device << 3) | (function & 0x7));
+								pfmem->start = start_address;
+								pfmem->end = end_address + 0xfffff;
+								pfmem->len = pfmem->end - pfmem->start + 1;
+								pfmem->fromMem = FALSE;
+
+								ibmphp_add_resource (pfmem);
+							}
+						}
+						break;
+				}	/* end of switch */
+			}	/* end if vendor */
+		}	/* end for function */
+	}	/* end for device */
+
+	bus = &bus_cur;
+	return 0;
+}
diff -Nru a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/pci_hotplug.h	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,146 @@
+/*
+ * PCI HotPlug Core Functions
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>
+ *
+ */
+#ifndef _PCI_HOTPLUG_H
+#define _PCI_HOTPLUG_H
+
+
+/* These values come from the PCI Hotplug Spec */
+enum pci_bus_speed {
+	PCI_SPEED_33MHz			= 0x00,
+	PCI_SPEED_66MHz			= 0x01,
+	PCI_SPEED_66MHz_PCIX		= 0x02,
+	PCI_SPEED_100MHz_PCIX		= 0x03,
+	PCI_SPEED_133MHz_PCIX		= 0x04,
+	PCI_SPEED_66MHz_PCIX_266	= 0x09,
+	PCI_SPEED_100MHz_PCIX_266	= 0x0a,
+	PCI_SPEED_133MHz_PCIX_266	= 0x0b,
+	PCI_SPEED_66MHz_PCIX_533	= 0x11,
+	PCI_SPEED_100MHz_PCIX_533	= 0X12,
+	PCI_SPEED_133MHz_PCIX_533	= 0x13,
+	PCI_SPEED_UNKNOWN		= 0xff,
+};
+
+struct hotplug_slot;
+struct hotplug_slot_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct hotplug_slot *, char *);
+	ssize_t (*store)(struct hotplug_slot *, const char *, size_t);
+};
+/**
+ * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use
+ * @owner: The module owner of this structure
+ * @enable_slot: Called when the user wants to enable a specific pci slot
+ * @disable_slot: Called when the user wants to disable a specific pci slot
+ * @set_attention_status: Called to set the specific slot's attention LED to
+ * the specified value
+ * @hardware_test: Called to run a specified hardware test on the specified
+ * slot.
+ * @get_power_status: Called to get the current power status of a slot.
+ * 	If this field is NULL, the value passed in the struct hotplug_slot_info
+ * 	will be used when this value is requested by a user.
+ * @get_attention_status: Called to get the current attention status of a slot.
+ *	If this field is NULL, the value passed in the struct hotplug_slot_info
+ *	will be used when this value is requested by a user.
+ * @get_latch_status: Called to get the current latch status of a slot.
+ *	If this field is NULL, the value passed in the struct hotplug_slot_info
+ *	will be used when this value is requested by a user.
+ * @get_adapter_status: Called to get see if an adapter is present in the slot or not.
+ *	If this field is NULL, the value passed in the struct hotplug_slot_info
+ *	will be used when this value is requested by a user.
+ * @get_max_bus_speed: Called to get the max bus speed for a slot.
+ *	If this field is NULL, the value passed in the struct hotplug_slot_info
+ *	will be used when this value is requested by a user.
+ * @get_cur_bus_speed: Called to get the current bus speed for a slot.
+ *	If this field is NULL, the value passed in the struct hotplug_slot_info
+ *	will be used when this value is requested by a user.
+ *
+ * The table of function pointers that is passed to the hotplug pci core by a
+ * hotplug pci driver.  These functions are called by the hotplug pci core when
+ * the user wants to do something to a specific slot (query it for information,
+ * set an LED, enable / disable power, etc.)
+ */
+struct hotplug_slot_ops {
+	struct module *owner;
+	int (*enable_slot)		(struct hotplug_slot *slot);
+	int (*disable_slot)		(struct hotplug_slot *slot);
+	int (*set_attention_status)	(struct hotplug_slot *slot, u8 value);
+	int (*hardware_test)		(struct hotplug_slot *slot, u32 value);
+	int (*get_power_status)		(struct hotplug_slot *slot, u8 *value);
+	int (*get_attention_status)	(struct hotplug_slot *slot, u8 *value);
+	int (*get_latch_status)		(struct hotplug_slot *slot, u8 *value);
+	int (*get_adapter_status)	(struct hotplug_slot *slot, u8 *value);
+	int (*get_max_bus_speed)	(struct hotplug_slot *slot, enum pci_bus_speed *value);
+	int (*get_cur_bus_speed)	(struct hotplug_slot *slot, enum pci_bus_speed *value);
+};
+
+/**
+ * struct hotplug_slot_info - used to notify the hotplug pci core of the state of the slot
+ * @power: if power is enabled or not (1/0)
+ * @attention_status: if the attention light is enabled or not (1/0)
+ * @latch_status: if the latch (if any) is open or closed (1/0)
+ * @adapter_present: if there is a pci board present in the slot or not (1/0)
+ *
+ * Used to notify the hotplug pci core of the status of a specific slot.
+ */
+struct hotplug_slot_info {
+	u8	power_status;
+	u8	attention_status;
+	u8	latch_status;
+	u8	adapter_status;
+	enum pci_bus_speed	max_bus_speed;
+	enum pci_bus_speed	cur_bus_speed;
+};
+
+/**
+ * struct hotplug_slot - used to register a physical slot with the hotplug pci core
+ * @name: the name of the slot being registered.  This string must
+ * be unique amoung slots registered on this system.
+ * @ops: pointer to the &struct hotplug_slot_ops to be used for this slot
+ * @info: pointer to the &struct hotplug_slot_info for the inital values for
+ * this slot.
+ * @private: used by the hotplug pci controller driver to store whatever it
+ * needs.
+ */
+struct hotplug_slot {
+	char				*name;
+	struct hotplug_slot_ops		*ops;
+	struct hotplug_slot_info	*info;
+	void				*private;
+
+	/* Variables below this are for use only by the hotplug pci core. */
+	struct list_head		slot_list;
+	struct kobject			kobj;
+};
+
+extern int pci_hp_register		(struct hotplug_slot *slot);
+extern int pci_hp_deregister		(struct hotplug_slot *slot);
+extern int pci_hp_change_slot_info	(struct hotplug_slot *slot,
+					 struct hotplug_slot_info *info);
+
+#endif
+
diff -Nru a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/pci_hotplug_core.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,666 @@
+/*
+ * PCI HotPlug Controller Core
+ *
+ * Copyright (c) 2001-2002 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001-2002 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>
+ *
+ * Filesystem portion based on work done by Pat Mochel on ddfs/driverfs
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/pci.h>
+#include <asm/uaccess.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include "pci_hotplug.h"
+
+
+#if !defined(CONFIG_HOTPLUG_PCI_MODULE)
+	#define MY_NAME	"pci_hotplug"
+#else
+	#define MY_NAME	THIS_MODULE->name
+#endif
+
+#define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## arg); } while (0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
+
+
+/* local variables */
+static int debug;
+
+#define DRIVER_VERSION	"0.5"
+#define DRIVER_AUTHOR	"Greg Kroah-Hartman <greg@kroah.com>, Scott Murray <scottm@somanetworks.com>"
+#define DRIVER_DESC	"PCI Hot Plug PCI Core"
+
+
+//////////////////////////////////////////////////////////////////
+
+static LIST_HEAD(pci_hotplug_slot_list);
+
+static struct subsystem hotplug_slots_subsys;
+
+static ssize_t hotplug_slot_attr_show(struct kobject *kobj,
+		struct attribute *attr, char *buf)
+{
+	struct hotplug_slot *slot=container_of(kobj,
+			struct hotplug_slot,kobj);
+	struct hotplug_slot_attribute *attribute =
+		container_of(attr, struct hotplug_slot_attribute, attr);
+	return attribute->show ? attribute->show(slot, buf) : 0;
+}
+
+static ssize_t hotplug_slot_attr_store(struct kobject *kobj,
+		struct attribute *attr, const char *buf, size_t len)
+{
+	struct hotplug_slot *slot=container_of(kobj,
+			struct hotplug_slot,kobj);
+	struct hotplug_slot_attribute *attribute =
+		container_of(attr, struct hotplug_slot_attribute, attr);
+	return attribute->store ? attribute->store(slot, buf, len) : 0;
+}
+
+static struct sysfs_ops hotplug_slot_sysfs_ops = {
+	.show = hotplug_slot_attr_show,
+	.store = hotplug_slot_attr_store,
+};
+
+static struct kobj_type hotplug_slot_ktype = {
+	.sysfs_ops = &hotplug_slot_sysfs_ops
+};
+
+static decl_subsys(hotplug_slots, &hotplug_slot_ktype, NULL);
+
+
+/* these strings match up with the values in pci_bus_speed */
+static char *pci_bus_speed_strings[] = {
+	"33 MHz PCI",		/* 0x00 */
+	"66 MHz PCI",		/* 0x01 */
+	"66 MHz PCIX", 		/* 0x02 */
+	"100 MHz PCIX",		/* 0x03 */
+	"133 MHz PCIX",		/* 0x04 */
+	NULL,			/* 0x05 */
+	NULL,			/* 0x06 */
+	NULL,			/* 0x07 */
+	NULL,			/* 0x08 */
+	"66 MHz PCIX 266",	/* 0x09 */
+	"100 MHz PCIX 266",	/* 0x0a */
+	"133 MHz PCIX 266",	/* 0x0b */
+	NULL,			/* 0x0c */
+	NULL,			/* 0x0d */
+	NULL,			/* 0x0e */
+	NULL,			/* 0x0f */
+	NULL,			/* 0x10 */
+	"66 MHz PCIX 533",	/* 0x11 */
+	"100 MHz PCIX 533",	/* 0x12 */
+	"133 MHz PCIX 533",	/* 0x13 */
+};
+
+#ifdef CONFIG_HOTPLUG_PCI_CPCI
+extern int cpci_hotplug_init(int debug);
+extern void cpci_hotplug_exit(void);
+#else
+static inline int cpci_hotplug_init(int debug) { return 0; }
+static inline void cpci_hotplug_exit(void) { }
+#endif
+
+/* Weee, fun with macros... */
+#define GET_STATUS(name,type)	\
+static int get_##name (struct hotplug_slot *slot, type *value)		\
+{									\
+	struct hotplug_slot_ops *ops = slot->ops;			\
+	int retval = 0;							\
+	if (try_module_get(ops->owner)) {				\
+		if (ops->get_##name)					\
+			retval = ops->get_##name (slot, value);		\
+		else							\
+			*value = slot->info->name;			\
+		module_put(ops->owner);					\
+	}								\
+	return retval;							\
+}
+
+GET_STATUS(power_status, u8)
+GET_STATUS(attention_status, u8)
+GET_STATUS(latch_status, u8)
+GET_STATUS(adapter_status, u8)
+GET_STATUS(max_bus_speed, enum pci_bus_speed)
+GET_STATUS(cur_bus_speed, enum pci_bus_speed)
+
+static ssize_t power_read_file (struct hotplug_slot *slot, char *buf)
+{
+	int retval;
+	u8 value;
+
+	retval = get_power_status (slot, &value);
+	if (retval)
+		goto exit;
+	retval = sprintf (buf, "%d\n", value);
+exit:
+	return retval;
+}
+
+static ssize_t power_write_file (struct hotplug_slot *slot, const char *buf,
+		size_t count)
+{
+	unsigned long lpower;
+	u8 power;
+	int retval = 0;
+
+	lpower = simple_strtoul (buf, NULL, 10);
+	power = (u8)(lpower & 0xff);
+	dbg ("power = %d\n", power);
+
+	if (!try_module_get(slot->ops->owner)) {
+		retval = -ENODEV;
+		goto exit;
+	}
+	switch (power) {
+		case 0:
+			if (slot->ops->disable_slot)
+				retval = slot->ops->disable_slot(slot);
+			break;
+
+		case 1:
+			if (slot->ops->enable_slot)
+				retval = slot->ops->enable_slot(slot);
+			break;
+
+		default:
+			err ("Illegal value specified for power\n");
+			retval = -EINVAL;
+	}
+	module_put(slot->ops->owner);
+
+exit:	
+	if (retval)
+		return retval;
+	return count;
+}
+
+static struct hotplug_slot_attribute hotplug_slot_attr_power = {
+	.attr = {.name = "power", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+	.show = power_read_file,
+	.store = power_write_file
+};
+
+static ssize_t attention_read_file (struct hotplug_slot *slot, char *buf)
+{
+	int retval;
+	u8 value;
+
+	retval = get_attention_status (slot, &value);
+	if (retval)
+		goto exit;
+	retval = sprintf (buf, "%d\n", value);
+
+exit:
+	return retval;
+}
+
+static ssize_t attention_write_file (struct hotplug_slot *slot, const char *buf,
+		size_t count)
+{
+	unsigned long lattention;
+	u8 attention;
+	int retval = 0;
+
+	lattention = simple_strtoul (buf, NULL, 10);
+	attention = (u8)(lattention & 0xff);
+	dbg (" - attention = %d\n", attention);
+
+	if (!try_module_get(slot->ops->owner)) {
+		retval = -ENODEV;
+		goto exit;
+	}
+	if (slot->ops->set_attention_status)
+		retval = slot->ops->set_attention_status(slot, attention);
+	module_put(slot->ops->owner);
+
+exit:	
+	if (retval)
+		return retval;
+	return count;
+}
+
+static struct hotplug_slot_attribute hotplug_slot_attr_attention = {
+	.attr = {.name = "attention", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+	.show = attention_read_file,
+	.store = attention_write_file
+};
+
+static ssize_t latch_read_file (struct hotplug_slot *slot, char *buf)
+{
+	int retval;
+	u8 value;
+
+	retval = get_latch_status (slot, &value);
+	if (retval)
+		goto exit;
+	retval = sprintf (buf, "%d\n", value);
+
+exit:
+	return retval;
+}
+
+static struct hotplug_slot_attribute hotplug_slot_attr_latch = {
+	.attr = {.name = "latch", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+	.show = latch_read_file,
+};
+
+static ssize_t presence_read_file (struct hotplug_slot *slot, char *buf)
+{
+	int retval;
+	u8 value;
+
+	retval = get_adapter_status (slot, &value);
+	if (retval)
+		goto exit;
+	retval = sprintf (buf, "%d\n", value);
+
+exit:
+	return retval;
+}
+
+static struct hotplug_slot_attribute hotplug_slot_attr_presence = {
+	.attr = {.name = "adapter", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+	.show = presence_read_file,
+};
+
+static char *unknown_speed = "Unknown bus speed";
+
+static ssize_t max_bus_speed_read_file (struct hotplug_slot *slot, char *buf)
+{
+	char *speed_string;
+	int retval;
+	enum pci_bus_speed value;
+	
+	retval = get_max_bus_speed (slot, &value);
+	if (retval)
+		goto exit;
+
+	if (value == PCI_SPEED_UNKNOWN)
+		speed_string = unknown_speed;
+	else
+		speed_string = pci_bus_speed_strings[value];
+	
+	retval = sprintf (buf, "%s\n", speed_string);
+
+exit:
+	return retval;
+}
+
+static struct hotplug_slot_attribute hotplug_slot_attr_max_bus_speed = {
+	.attr = {.name = "max_bus_speed", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+	.show = max_bus_speed_read_file,
+};
+
+static ssize_t cur_bus_speed_read_file (struct hotplug_slot *slot, char *buf)
+{
+	char *speed_string;
+	int retval;
+	enum pci_bus_speed value;
+
+	retval = get_cur_bus_speed (slot, &value);
+	if (retval)
+		goto exit;
+
+	if (value == PCI_SPEED_UNKNOWN)
+		speed_string = unknown_speed;
+	else
+		speed_string = pci_bus_speed_strings[value];
+	
+	retval = sprintf (buf, "%s\n", speed_string);
+
+exit:
+	return retval;
+}
+
+static struct hotplug_slot_attribute hotplug_slot_attr_cur_bus_speed = {
+	.attr = {.name = "cur_bus_speed", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+	.show = cur_bus_speed_read_file,
+};
+
+static ssize_t test_write_file (struct hotplug_slot *slot, const char *buf,
+		size_t count)
+{
+	unsigned long ltest;
+	u32 test;
+	int retval = 0;
+
+	ltest = simple_strtoul (buf, NULL, 10);
+	test = (u32)(ltest & 0xffffffff);
+	dbg ("test = %d\n", test);
+
+	if (!try_module_get(slot->ops->owner)) {
+		retval = -ENODEV;
+		goto exit;
+	}
+	if (slot->ops->hardware_test)
+		retval = slot->ops->hardware_test(slot, test);
+	module_put(slot->ops->owner);
+
+exit:	
+	if (retval)
+		return retval;
+	return count;
+}
+
+static struct hotplug_slot_attribute hotplug_slot_attr_test = {
+	.attr = {.name = "test", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+	.store = test_write_file
+};
+
+static int has_power_file (struct hotplug_slot *slot)
+{
+	if ((!slot) || (!slot->ops))
+		return -ENODEV;
+	if ((slot->ops->enable_slot) ||
+	    (slot->ops->disable_slot) ||
+	    (slot->ops->get_power_status))
+		return 0;
+	return -ENOENT;
+}
+
+static int has_attention_file (struct hotplug_slot *slot)
+{
+	if ((!slot) || (!slot->ops))
+		return -ENODEV;
+	if ((slot->ops->set_attention_status) ||
+	    (slot->ops->get_attention_status))
+		return 0;
+	return -ENOENT;
+}
+
+static int has_latch_file (struct hotplug_slot *slot)
+{
+	if ((!slot) || (!slot->ops))
+		return -ENODEV;
+	if (slot->ops->get_latch_status)
+		return 0;
+	return -ENOENT;
+}
+
+static int has_adapter_file (struct hotplug_slot *slot)
+{
+	if ((!slot) || (!slot->ops))
+		return -ENODEV;
+	if (slot->ops->get_adapter_status)
+		return 0;
+	return -ENOENT;
+}
+
+static int has_max_bus_speed_file (struct hotplug_slot *slot)
+{
+	if ((!slot) || (!slot->ops))
+		return -ENODEV;
+	if (slot->ops->get_max_bus_speed)
+		return 0;
+	return -ENOENT;
+}
+
+static int has_cur_bus_speed_file (struct hotplug_slot *slot)
+{
+	if ((!slot) || (!slot->ops))
+		return -ENODEV;
+	if (slot->ops->get_cur_bus_speed)
+		return 0;
+	return -ENOENT;
+}
+
+static int has_test_file (struct hotplug_slot *slot)
+{
+	if ((!slot) || (!slot->ops))
+		return -ENODEV;
+	if (slot->ops->hardware_test)
+		return 0;
+	return -ENOENT;
+}
+
+static int fs_add_slot (struct hotplug_slot *slot)
+{
+	if (has_power_file(slot) == 0)
+		sysfs_create_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+
+	if (has_attention_file(slot) == 0)
+		sysfs_create_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
+
+	if (has_latch_file(slot) == 0)
+		sysfs_create_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
+
+	if (has_adapter_file(slot) == 0)
+		sysfs_create_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
+
+	if (has_max_bus_speed_file(slot) == 0)
+		sysfs_create_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
+
+	if (has_cur_bus_speed_file(slot) == 0)
+		sysfs_create_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
+
+	if (has_test_file(slot) == 0)
+		sysfs_create_file(&slot->kobj, &hotplug_slot_attr_test.attr);
+
+	return 0;
+}
+
+static void fs_remove_slot (struct hotplug_slot *slot)
+{
+	if (has_power_file(slot) == 0)
+		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+
+	if (has_attention_file(slot) == 0)
+		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
+
+	if (has_latch_file(slot) == 0)
+		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
+
+	if (has_adapter_file(slot) == 0)
+		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
+
+	if (has_max_bus_speed_file(slot) == 0)
+		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
+
+	if (has_cur_bus_speed_file(slot) == 0)
+		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
+
+	if (has_test_file(slot) == 0)
+		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr);
+}
+
+static struct hotplug_slot *get_slot_from_name (const char *name)
+{
+	struct hotplug_slot *slot;
+	struct list_head *tmp;
+
+	list_for_each (tmp, &pci_hotplug_slot_list) {
+		slot = list_entry (tmp, struct hotplug_slot, slot_list);
+		if (strcmp(slot->name, name) == 0)
+			return slot;
+	}
+	return NULL;
+}
+
+/**
+ * pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem
+ * @slot: pointer to the &struct hotplug_slot to register
+ *
+ * Registers a hotplug slot with the pci hotplug subsystem, which will allow
+ * userspace interaction to the slot.
+ *
+ * Returns 0 if successful, anything else for an error.
+ */
+int pci_hp_register (struct hotplug_slot *slot)
+{
+	int result;
+
+	if (slot == NULL)
+		return -ENODEV;
+	if ((slot->info == NULL) || (slot->ops == NULL))
+		return -EINVAL;
+
+	strlcpy(slot->kobj.name, slot->name, KOBJ_NAME_LEN);
+	kobj_set_kset_s(slot, hotplug_slots_subsys);
+
+	/* this can fail if we have already registered a slot with the same name */
+	if (kobject_register(&slot->kobj)) {
+		err("Unable to register kobject");
+		return -EINVAL;
+	}
+		
+	list_add (&slot->slot_list, &pci_hotplug_slot_list);
+
+	result = fs_add_slot (slot);
+	dbg ("Added slot %s to the list\n", slot->name);
+	return result;
+}
+
+/**
+ * pci_hp_deregister - deregister a hotplug_slot with the PCI hotplug subsystem
+ * @slot: pointer to the &struct hotplug_slot to deregister
+ *
+ * The @slot must have been registered with the pci hotplug subsystem
+ * previously with a call to pci_hp_register().
+ *
+ * Returns 0 if successful, anything else for an error.
+ */
+int pci_hp_deregister (struct hotplug_slot *slot)
+{
+	struct hotplug_slot *temp;
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	temp = get_slot_from_name (slot->name);
+	if (temp != slot) {
+		return -ENODEV;
+	}
+	list_del (&slot->slot_list);
+
+	fs_remove_slot (slot);
+	dbg ("Removed slot %s from the list\n", slot->name);
+	kobject_unregister(&slot->kobj);
+	return 0;
+}
+
+/**
+ * pci_hp_change_slot_info - changes the slot's information structure in the core
+ * @slot: pointer to the slot whose info has changed
+ * @info: pointer to the info copy into the slot's info structure
+ *
+ * @slot must have been registered with the pci 
+ * hotplug subsystem previously with a call to pci_hp_register().
+ *
+ * Returns 0 if successful, anything else for an error.
+ */
+int pci_hp_change_slot_info (struct hotplug_slot *slot, struct hotplug_slot_info *info)
+{
+	if ((slot == NULL) || (info == NULL))
+		return -ENODEV;
+
+	/*
+	* check all fields in the info structure, and update timestamps
+	* for the files referring to the fields that have now changed.
+	*/
+	if ((has_power_file(slot) == 0) &&
+	    (slot->info->power_status != info->power_status))
+		sysfs_update_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+
+	if ((has_attention_file(slot) == 0) &&
+	    (slot->info->attention_status != info->attention_status))
+		sysfs_update_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
+
+	if ((has_latch_file(slot) == 0) &&
+	    (slot->info->latch_status != info->latch_status))
+		sysfs_update_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
+
+	if ((has_adapter_file(slot) == 0) &&
+	    (slot->info->adapter_status != info->adapter_status))
+		sysfs_update_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
+
+	if ((has_max_bus_speed_file(slot) == 0) &&
+	    (slot->info->max_bus_speed != info->max_bus_speed))
+		sysfs_update_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
+
+	if ((has_cur_bus_speed_file(slot) == 0) &&
+	    (slot->info->cur_bus_speed != info->cur_bus_speed))
+		sysfs_update_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
+
+	memcpy (slot->info, info, sizeof (struct hotplug_slot_info));
+
+	return 0;
+}
+
+static int __init pci_hotplug_init (void)
+{
+	int result;
+
+	kset_set_kset_s(&hotplug_slots_subsys, pci_bus_type.subsys);
+	result = subsystem_register(&hotplug_slots_subsys);
+	if (result) {
+		err("Register subsys with error %d\n", result);
+		goto exit;
+	}
+	result = cpci_hotplug_init(debug);
+	if (result) {
+		err ("cpci_hotplug_init with error %d\n", result);
+		goto err_subsys;
+	}
+
+	info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
+	goto exit;
+	
+err_subsys:
+	subsystem_unregister(&hotplug_slots_subsys);
+exit:
+	return result;
+}
+
+static void __exit pci_hotplug_exit (void)
+{
+	cpci_hotplug_exit();
+	subsystem_unregister(&hotplug_slots_subsys);
+}
+
+module_init(pci_hotplug_init);
+module_exit(pci_hotplug_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
+
+EXPORT_SYMBOL_GPL(pci_hp_register);
+EXPORT_SYMBOL_GPL(pci_hp_deregister);
+EXPORT_SYMBOL_GPL(pci_hp_change_slot_info);
diff -Nru a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/hotplug/pcihp_skeleton.c	Wed Jun  4 18:11:56 2003
@@ -0,0 +1,432 @@
+/*
+ * PCI Hot Plug Controller Skeleton Driver - 0.1
+ *
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * 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 <greg@kroah.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include "pci_hotplug.h"
+
+
+#define SLOT_MAGIC	0x67267322
+struct slot {
+	u32 magic;
+	u8 number;
+	struct hotplug_slot *hotplug_slot;
+	struct list_head slot_list;
+};
+
+static LIST_HEAD(slot_list);
+
+#if !defined(CONFIG_HOTPLUG_PCI_SKELETON_MODULE)
+	#define MY_NAME	"pcihp_skeleton"
+#else
+	#define MY_NAME	THIS_MODULE->name
+#endif
+
+#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)
+
+
+
+/* local variables */
+static int debug;
+static int num_slots;
+
+#define DRIVER_VERSION	"0.1"
+#define DRIVER_AUTHOR	"Greg Kroah-Hartman <greg@kroah.com>"
+#define DRIVER_DESC	"Hot Plug PCI Controller Skeleton Driver"
+
+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);
+
+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__);
+	int retval = 0;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	/*
+	 * Fill in code here to enable the specified slot
+	 */
+
+	return retval;
+}
+
+
+static int disable_slot (struct hotplug_slot *hotplug_slot)
+{
+	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);
+
+	/*
+	 * Fill in code here to disable the specified slot
+	 */
+
+	return retval;
+}
+
+static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
+{
+	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);
+
+	switch (status) {
+		case 0:
+			/*
+			 * Fill in code here to turn light off
+			 */
+			break;
+
+		case 1:
+		default:
+			/*
+			 * Fill in code here to turn light on
+			 */
+			break;
+	}
+
+	return retval;
+}
+
+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 */
+	
+	return retval;
+}
+
+static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval = 0;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
+
+	/*
+	 * Fill in logic to get the current power status of the specific
+	 * slot and store it in the *value location.
+	 */
+
+	return retval;
+}
+
+static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval = 0;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
+
+	/*
+	 * Fill in logic to get the current attention status of the specific
+	 * slot and store it in the *value location.
+	 */
+
+	return retval;
+}
+
+static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval = 0;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
+
+	/*
+	 * Fill in logic to get the current latch status of the specific
+	 * slot and store it in the *value location.
+	 */
+
+	return retval;
+}
+
+static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval = 0;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
+
+	/*
+	 * Fill in logic to get the current adapter status of the specific
+	 * slot and store it in the *value location.
+	 */
+
+	return retval;
+}
+
+#define SLOT_NAME_SIZE	10
+static void make_slot_name (struct slot *slot)
+{
+	/*
+	 * Stupid way to make a filename out of the slot name.
+	 * replace this if your hardware provides a better way to name slots.
+	 */
+	snprintf (slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d", slot->number);
+}
+
+static int init_slots (void)
+{
+	struct slot *slot;
+	struct hotplug_slot *hotplug_slot;
+	struct hotplug_slot_info *info;
+	char *name;
+	int retval = 0;
+	int i;
+
+	/*
+	 * 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;
+
+		hotplug_slot->private = slot;
+		make_slot_name (slot);
+		hotplug_slot->ops = &skel_hotplug_slot_ops;
+		
+		/*
+		 * Initilize the slot info structure with some known
+		 * good values.
+		 */
+		info->power_status = get_skel_power_status(slot);
+		info->attention_status = get_skel_attention_status(slot);
+		info->latch_status = get_skel_latch_status(slot);
+		info->adapter_status = get_skel_adapter_status(slot);
+		
+		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 void cleanup_slots (void)
+{
+	struct list_head *tmp;
+	struct slot *slot;
+
+	/*
+	 * Unregister all of our slots with the pci_hotplug subsystem,
+	 * and free up all memory that we had allocated.
+	 */
+	list_for_each (tmp, &slot_list) {
+		slot = list_entry (tmp, struct slot, slot_list);
+		list_del (&slot->slot_list);
+		pci_hp_deregister (slot->hotplug_slot);
+		kfree (slot->hotplug_slot->info);
+		kfree (slot->hotplug_slot->name);
+		kfree (slot->hotplug_slot);
+		kfree (slot);
+	}
+
+	return;
+}
+		
+static int __init pcihp_skel_init(void)
+{
+	int retval;
+
+	/*
+	 * 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.
+	 */
+	num_slots = 5;
+
+	retval = init_slots();
+	if (retval)
+		return retval;
+
+	info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
+	return 0;
+}
+
+static void __exit pcihp_skel_exit(void)
+{
+	/*
+	 * Clean everything up.
+	 */
+	cleanup_slots();
+}
+
+module_init(pcihp_skel_init);
+module_exit(pcihp_skel_exit);
+
