diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 0f9b0783ed37605e8720c004c720544021b4a1b2..0237a5524e07b68b9cd6566160902e9a08601fe0 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -239,14 +239,13 @@ config BLK_DEV_CMD640_ENHANCED
 	  and your BIOS does not already do this for you, then say Y here.
 	  Otherwise say N.
 
-config BLK_DEV_ISAPNP
-	bool "ISA-PNP EIDE support"
-	depends on BLK_DEV_IDE && ISAPNP
+config BLK_DEV_IDEPNP
+	bool "PNP EIDE support"
+	depends on BLK_DEV_IDE && PNP
 	help
-	  If you have an ISA EIDE card that is PnP (Plug and Play) and
-	  requires setup first before scanning for devices, say Y here.
-
-	  If unsure, say N.
+	  If you have a PnP (Plug and Play) compatible EIDE card and
+	  would like the kernel to automatically detect and activate
+	  it, say Y here.
 
 config BLK_DEV_IDEPCI
 	bool "PCI IDE chipset support" if PCI
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 13bc8113953657c1f1a5d60370f94580b164e3a4..83ee41a73b97b0d8d9aba937ff12eb4a8a65d60a 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -21,7 +21,7 @@ obj-$(CONFIG_BLK_DEV_IDEFLOPPY)		+= ide-floppy.o
 obj-$(CONFIG_BLK_DEV_IDEPCI)		+= setup-pci.o
 obj-$(CONFIG_BLK_DEV_IDEDMA_PCI)	+= ide-dma.o
 obj-$(CONFIG_BLK_DEV_IDE_TCQ)		+= ide-tcq.o
-obj-$(CONFIG_BLK_DEV_ISAPNP)		+= ide-pnp.o
+obj-$(CONFIG_BLK_DEV_IDEPNP)		+= ide-pnp.o
 
 ifeq ($(CONFIG_BLK_DEV_IDE),y)
 obj-$(CONFIG_PROC_FS)			+= ide-proc.o
diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
index 63085d6d00d1763769bd8a065d3b20c27575f626..00a240f73c090b702cd0ae2c87cde6d6b71ac35e 100644
--- a/drivers/ide/ide-pnp.c
+++ b/drivers/ide/ide-pnp.c
@@ -19,9 +19,7 @@
 #include <linux/ide.h>
 #include <linux/init.h>
 
-#include <linux/isapnp.h>
-
-#define DEV_NAME(dev) (dev->name)
+#include <linux/pnp.h>
 
 #define GENERIC_HD_DATA		0
 #define GENERIC_HD_ERROR	1
@@ -32,31 +30,27 @@
 #define GENERIC_HD_SELECT	6
 #define GENERIC_HD_STATUS	7
 
-static int generic_ide_offsets[IDE_NR_PORTS] __initdata = {
+static int generic_ide_offsets[IDE_NR_PORTS] = {
 	GENERIC_HD_DATA, GENERIC_HD_ERROR, GENERIC_HD_NSECTOR, 
 	GENERIC_HD_SECTOR, GENERIC_HD_LCYL, GENERIC_HD_HCYL,
 	GENERIC_HD_SELECT, GENERIC_HD_STATUS, -1, -1
 };
 
-/* ISA PnP device table entry */
-struct pnp_dev_t {
-	unsigned short card_vendor, card_device, vendor, device;
-	int (*init_fn)(struct pnp_dev *dev, int enable);
+/* Add your devices here :)) */
+struct pnp_device_id idepnp_devices[] = {
+  	/* Generic ESDI/IDE/ATA compatible hard disk controller */
+	{.id = "PNP0600", .driver_data = 0},
+	{.id = ""}
 };
 
-/* Generic initialisation function for ISA PnP IDE interface */
-
-static int __init pnpide_generic_init(struct pnp_dev *dev, int enable)
+static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id)
 {
 	hw_regs_t hw;
 	ide_hwif_t *hwif;
 	int index;
 
-	if (!enable)
-		return 0;
-
 	if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && pnp_irq_valid(dev, 0)))
-		return 1;
+		return -1;
 
 	ide_setup_ports(&hw, (unsigned long) pnp_port_start(dev, 0),
 			generic_ide_offsets,
@@ -68,82 +62,36 @@ static int __init pnpide_generic_init(struct pnp_dev *dev, int enable)
 	index = ide_register_hw(&hw, &hwif);
 
 	if (index != -1) {
-	    	printk(KERN_INFO "ide%d: %s IDE interface\n", index, DEV_NAME(dev));
+	    	printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index);
+		pnp_set_drvdata(dev,hwif);
 		hwif->pnp_dev = dev;
 		return 0;
 	}
 
-	return 1;
+	return -1;
 }
 
-/* Add your devices here :)) */
-struct pnp_dev_t idepnp_devices[] __initdata = {
-  	/* Generic ESDI/IDE/ATA compatible hard disk controller */
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0600),
-		pnpide_generic_init },
-	{	0 }
-};
+static void idepnp_remove(struct pnp_dev * dev)
+{
+	ide_hwif_t *hwif = pnp_get_drvdata(dev);
+	if (hwif) {
+		ide_unregister(hwif->index);
+	} else
+		printk(KERN_ERR "idepnp: Unable to remove device, please report.\n");
+}
 
-#define NR_PNP_DEVICES 8
-struct pnp_dev_inst {
-	struct pnp_dev *dev;
-	struct pnp_dev_t *dev_type;
+static struct pnp_driver idepnp_driver = {
+	.name		= "ide",
+	.id_table	= idepnp_devices,
+	.probe		= idepnp_probe,
+	.remove		= idepnp_remove,
 };
-static struct pnp_dev_inst devices[NR_PNP_DEVICES];
-static int pnp_ide_dev_idx = 0;
 
-/*
- * Probe for ISA PnP IDE interfaces.
- */
 
-void __init pnpide_init(int enable)
+void pnpide_init(int enable)
 {
-	struct pnp_dev *dev = NULL;
-	struct pnp_dev_t *dev_type;
-
-	if (!isapnp_present())
-		return;
-
-	/* Module unload, deactivate all registered devices. */
-	if (!enable) {
-		int i;
-		for (i = 0; i < pnp_ide_dev_idx; i++) {
-			dev = devices[i].dev;
-			devices[i].dev_type->init_fn(dev, 0);
-			pnp_device_detach(dev);
-		}
-		return;
-	}
-
-	for (dev_type = idepnp_devices; dev_type->vendor; dev_type++) {
-		while ((dev = pnp_find_dev(NULL, dev_type->vendor,
-			dev_type->device, dev))) {
-			
-			if (pnp_device_attach(dev) < 0)
-				continue;
-				
-			if (pnp_activate_dev(dev, NULL) < 0) {
-				printk(KERN_ERR"ide: %s activate failed\n", DEV_NAME(dev));
-				continue;
-			}
-
-			/* Call device initialization function */
-			if (dev_type->init_fn(dev, 1)) {
-				pnp_device_detach(dev);
-			} else {
-#ifdef MODULE
-				/*
-				 * Register device in the array to
-				 * deactivate it on a module unload.
-				 */
-				if (pnp_ide_dev_idx >= NR_PNP_DEVICES)
-					return;
-				devices[pnp_ide_dev_idx].dev = dev;
-				devices[pnp_ide_dev_idx].dev_type = dev_type;
-				pnp_ide_dev_idx++;
-#endif
-			}
-		}
-	}
+	if(enable)
+		pnp_register_driver(&idepnp_driver);
+	else
+		pnp_unregister_driver(&idepnp_driver);
 }
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 46fa224180d4bfecef59632cc9af23bb3eaa3731..e4df5743e77f10ac01bde1235d7b9fbb8bb07a60 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -818,6 +818,7 @@ void ide_unregister (unsigned int index)
 
 EXPORT_SYMBOL(ide_unregister);
 
+
 /**
  *	ide_setup_ports 	-	set up IDE interface ports
  *	@hw: register descriptions
@@ -2145,12 +2146,12 @@ static void __init probe_for_hwifs (void)
 		buddha_init();
 	}
 #endif /* CONFIG_BLK_DEV_BUDDHA */
-#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP)
+#if defined(CONFIG_BLK_DEV_IDEPNP) && defined(CONFIG_PNP)
 	{
 		extern void pnpide_init(int enable);
 		pnpide_init(1);
 	}
-#endif /* CONFIG_BLK_DEV_ISAPNP */
+#endif /* CONFIG_BLK_DEV_IDEPNP */
 }
 
 void __init ide_init_builtin_drivers (void)
@@ -2321,9 +2322,9 @@ int ide_unregister_subdriver (ide_drive_t *drive)
 		spin_unlock_irqrestore(&ide_lock, flags);
 		return 1;
 	}
-#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) && defined(MODULE)
+#if defined(CONFIG_BLK_DEV_IDEPNP) && defined(CONFIG_PNP) && defined(MODULE)
 	pnpide_init(0);
-#endif /* CONFIG_BLK_DEV_ISAPNP */
+#endif /* CONFIG_BLK_DEV_IDEPNP */
 #ifdef CONFIG_PROC_FS
 	ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc);
 	ide_remove_proc_entries(drive->proc, generic_subdriver_entries);
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 7ac2ad722baf120ea057f71b363fc185bc035586..13f0b59942569a8318fd82fada9290c849ca9302 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -1,4 +1,4 @@
-/* radio-cadet.c - A video4linux driver for the ADS Cadet AM/FM Radio Card 
+/* radio-cadet.c - A video4linux driver for the ADS Cadet AM/FM Radio Card
  *
  * by Fred Gleason <fredg@wava.com>
  * Version 0.3.3
@@ -20,6 +20,9 @@
  *		Removed dead CONFIG_RADIO_CADET_PORT code
  *		PnP detection on load is now default (no args necessary)
  *
+ * 2002-01-17	Adam Belay <ambx1@neo.rr.com>
+ *		Updated to latest pnp code
+ *
 */
 
 #include <linux/module.h>	/* Modules 			*/
@@ -30,7 +33,7 @@
 #include <asm/uaccess.h>	/* copy to/from user		*/
 #include <linux/videodev.h>	/* kernel radio structs		*/
 #include <linux/param.h>
-#include <linux/isapnp.h>
+#include <linux/pnp.h>
 
 #define RDS_BUFFER 256
 
@@ -47,8 +50,6 @@ static unsigned char rdsbuf[RDS_BUFFER];
 static int cadet_lock=0;
 
 static int cadet_probe(void);
-static struct pnp_dev *dev = NULL;
-static int isapnp_cadet_probe(void);
 
 /*
  * Signal Strength Threshold Values
@@ -152,7 +153,7 @@ static unsigned cadet_gettune(void)
          */
         outb(curvol,io+1);
 	cadet_lock--;
-	
+
 	return fifo;
 }
 
@@ -541,22 +542,23 @@ static struct video_device cadet_radio=
 	.fops           = &cadet_fops,
 };
 
-static int isapnp_cadet_probe(void)
-{
-	dev = pnp_find_dev (NULL, ISAPNP_VENDOR('M','S','M'),
-			    ISAPNP_FUNCTION(0x0c24), NULL);
+static struct pnp_device_id cadet_pnp_devices[] = {
+	/* ADS Cadet AM/FM Radio Card */
+	{.id = "MSM0c24", .driver_data = 0},
+	{.id = ""}
+};
 
+MODULE_DEVICE_TABLE(pnp, id_table);
+
+static int cadet_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id)
+{
 	if (!dev)
 		return -ENODEV;
-	if (pnp_device_attach(dev) < 0)
-		return -EAGAIN;
-	if (pnp_activate_dev(dev, NULL) < 0) {
-		printk ("radio-cadet: pnp configure failed (out of resources?)\n");
-		pnp_device_detach(dev);
-		return -EIO;
-	}
+	/* only support one device */
+	if (io > 0)
+		return -EBUSY;
+
 	if (!pnp_port_valid(dev, 0)) {
-		pnp_device_detach(dev);
 		return -ENODEV;
 	}
 
@@ -567,6 +569,13 @@ static int isapnp_cadet_probe(void)
 	return io;
 }
 
+static struct pnp_driver cadet_pnp_driver = {
+	.name		= "radio-cadet",
+	.id_table	= cadet_pnp_devices,
+	.probe		= cadet_pnp_probe,
+	.remove		= NULL,
+};
+
 static int cadet_probe(void)
 {
         static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e};
@@ -597,7 +606,7 @@ static int __init cadet_init(void)
 	 *	If a probe was requested then probe ISAPnP first (safest)
 	 */
 	if (io < 0)
-		io = isapnp_cadet_probe();
+		pnp_register_driver(&cadet_pnp_driver);
 	/*
 	 *	If that fails then probe unsafely if probe is requested
 	 */
@@ -612,16 +621,19 @@ static int __init cadet_init(void)
 #ifdef MODULE        
 		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
 #endif
-	        return -EINVAL;
+	        goto fail;
 	}
 	if (!request_region(io,2,"cadet"))
-		return -EBUSY;
+		goto fail;
 	if(video_register_device(&cadet_radio,VFL_TYPE_RADIO,radio_nr)==-1) {
 		release_region(io,2);
-		return -EINVAL;
+		goto fail;
 	}
 	printk(KERN_INFO "ADS Cadet Radio Card at 0x%x\n",io);
 	return 0;
+fail:
+	pnp_unregister_driver(&cadet_pnp_driver);
+	return -1;
 }
 
 
@@ -634,21 +646,11 @@ MODULE_PARM(io, "i");
 MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e)");
 MODULE_PARM(radio_nr, "i");
 
-static struct isapnp_device_id id_table[] __devinitdata = {
-	{ 	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('M','S','M'), ISAPNP_FUNCTION(0x0c24), 0 },
-	{0}
-};
-
-MODULE_DEVICE_TABLE(isapnp, id_table);
-
 static void __exit cadet_cleanup_module(void)
 {
 	video_unregister_device(&cadet_radio);
 	release_region(io,2);
-
-	if (dev)
-		pnp_device_detach(dev);
+	pnp_unregister_driver(&cadet_pnp_driver);
 }
 
 module_init(cadet_init);
diff --git a/drivers/pnp/Makefile b/drivers/pnp/Makefile
index 9d42052d9472a0c5450c8fc947297314bee68e4b..a6a6ee3bba627579f9e4767640d7762fce3a6342 100644
--- a/drivers/pnp/Makefile
+++ b/drivers/pnp/Makefile
@@ -4,8 +4,7 @@
 
 pnp-card-$(CONFIG_PNP_CARD) = card.o
 
-obj-y		:= core.o driver.o resource.o interface.o quirks.o names.o system.o $(pnp-card-y)
+obj-y		:= core.o driver.o resource.o manager.o support.o interface.o quirks.o names.o system.o $(pnp-card-y)
 
 obj-$(CONFIG_PNPBIOS)		+= pnpbios/
 obj-$(CONFIG_ISAPNP)		+= isapnp/
-
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index 4a022d3d8ee955965212c8e40ec05ac590f4f9a0..e991aa70220ec14140cb57c11cfdbd0fb53478d8 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -1,9 +1,32 @@
 extern struct bus_type pnp_bus_type;
 extern spinlock_t pnp_lock;
-extern void *pnp_alloc(long size);
-extern int pnp_interface_attach_device(struct pnp_dev *dev);
-extern void pnp_name_device(struct pnp_dev *dev);
-extern void pnp_fixup_device(struct pnp_dev *dev);
-extern void pnp_free_resources(struct pnp_resources *resources);
-extern int __pnp_add_device(struct pnp_dev *dev);
-extern void __pnp_remove_device(struct pnp_dev *dev);
+void *pnp_alloc(long size);
+int pnp_interface_attach_device(struct pnp_dev *dev);
+void pnp_name_device(struct pnp_dev *dev);
+void pnp_fixup_device(struct pnp_dev *dev);
+void pnp_free_resources(struct pnp_resources *resources);
+int __pnp_add_device(struct pnp_dev *dev);
+void __pnp_remove_device(struct pnp_dev *dev);
+
+/* resource conflict types */
+#define CONFLICT_TYPE_NONE	0x0000	/* there are no conflicts, other than those in the link */
+#define CONFLICT_TYPE_RESERVED	0x0001	/* the resource requested was reserved */
+#define CONFLICT_TYPE_IN_USE	0x0002	/* there is a conflict because the resource is in use */
+#define CONFLICT_TYPE_PCI	0x0004	/* there is a conflict with a pci device */
+#define CONFLICT_TYPE_INVALID	0x0008	/* the resource requested is invalid */
+#define CONFLICT_TYPE_INTERNAL	0x0010	/* resources within the device conflict with each ohter */
+#define CONFLICT_TYPE_PNP_WARM	0x0020	/* there is a conflict with a pnp device that is active */
+#define CONFLICT_TYPE_PNP_COLD	0x0040	/* there is a conflict with a pnp device that is disabled */
+
+/* conflict search modes */
+#define SEARCH_WARM 1	/* check for conflicts with active devices */
+#define SEARCH_COLD 0	/* check for conflicts with disabled devices */
+
+struct pnp_dev * pnp_check_port_conflicts(struct pnp_dev * dev, int idx, int mode);
+int pnp_check_port(struct pnp_dev * dev, int idx);
+struct pnp_dev * pnp_check_mem_conflicts(struct pnp_dev * dev, int idx, int mode);
+int pnp_check_mem(struct pnp_dev * dev, int idx);
+struct pnp_dev * pnp_check_irq_conflicts(struct pnp_dev * dev, int idx, int mode);
+int pnp_check_irq(struct pnp_dev * dev, int idx);
+struct pnp_dev * pnp_check_dma_conflicts(struct pnp_dev * dev, int idx, int mode);
+int pnp_check_dma(struct pnp_dev * dev, int idx);
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index 19318f322d542af77e674b989648a7729de22d89..fb628c3dfbc6abcb0249db47f9a6e20639bd6472 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -22,9 +22,9 @@
 
 LIST_HEAD(pnp_cards);
 
-static const struct pnp_card_device_id * match_card(struct pnpc_driver *drv, struct pnp_card *card)
+static const struct pnp_card_id * match_card(struct pnpc_driver *drv, struct pnp_card *card)
 {
-	const struct pnp_card_device_id *drv_id = drv->id_table;
+	const struct pnp_card_id *drv_id = drv->id_table;
 	while (*drv_id->id){
 		if (compare_pnp_id(card->id,drv_id->id))
 			return drv_id;
@@ -43,8 +43,8 @@ static int card_bus_match(struct device *dev, struct device_driver *drv)
 }
 
 struct bus_type pnpc_bus_type = {
-	name:	"pnp_card",
-	match:	card_bus_match,
+	.name	= "pnp_card",
+	.match	= card_bus_match,
 };
 
 
@@ -106,7 +106,6 @@ int pnpc_add_card(struct pnp_card *card)
 		return -EINVAL;
 	sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number, card->number);
 	INIT_LIST_HEAD(&card->rdevs);
-	strcpy(card->dev.name,card->name);
 	card->dev.parent = &card->protocol->dev;
 	card->dev.bus = &pnpc_bus_type;
 	card->dev.release = &pnp_release_card;
@@ -144,7 +143,6 @@ void pnpc_remove_card(struct pnp_card *card)
 	list_for_each_safe(pos,temp,&card->devices){
 		struct pnp_dev *dev = card_to_pnp_dev(pos);
 		pnpc_remove_device(dev);
-		__pnp_remove_device(dev);
 	}
 }
 
@@ -221,7 +219,7 @@ struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id,
 	cdrv = to_pnpc_driver(card->dev.driver);
 	if (dev->active == 0) {
 		if (!(cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE)) {
-			if(pnp_activate_dev(dev,NULL)<0) {
+			if(pnp_activate_dev(dev)<0) {
 				pnp_device_detach(dev);
 				return NULL;
 			}
@@ -286,7 +284,7 @@ static int pnpc_card_probe(struct device *dev)
 	int error = 0;
 	struct pnpc_driver *drv = to_pnpc_driver(dev->driver);
 	struct pnp_card *card = to_pnp_card(dev);
-	const struct pnp_card_device_id *card_id = NULL;
+	const struct pnp_card_id *card_id = NULL;
 
 	pnp_dbg("pnp: match found with the PnP card '%s' and the driver '%s'", dev->bus_id,drv->name);
 
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index 6e4552115cbd9dce8bc2cd32f56158c21bc9b9ec..07ece270ba65ff7f8ddf7ca3140b3db5a60db737 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -104,31 +104,29 @@ static void pnp_free_ids(struct pnp_dev *dev)
 static void pnp_release_device(struct device *dmdev)
 {
 	struct pnp_dev * dev = to_pnp_dev(dmdev);
-	if (dev->res)
-		pnp_free_resources(dev->res);
+	if (dev->possible)
+		pnp_free_resources(dev->possible);
 	pnp_free_ids(dev);
 	kfree(dev);
 }
 
 int __pnp_add_device(struct pnp_dev *dev)
 {
-	int error = 0;
+	int ret;
 	pnp_name_device(dev);
 	pnp_fixup_device(dev);
-	strncpy(dev->dev.name,dev->name,DEVICE_NAME_SIZE-1);
-	dev->dev.name[DEVICE_NAME_SIZE-1] = '\0';
 	dev->dev.bus = &pnp_bus_type;
 	dev->dev.release = &pnp_release_device;
 	dev->status = PNP_READY;
-	error = device_register(&dev->dev);
-	if (error == 0){
-		spin_lock(&pnp_lock);
-		list_add_tail(&dev->global_list, &pnp_global);
-		list_add_tail(&dev->protocol_list, &dev->protocol->devices);
-		spin_unlock(&pnp_lock);
+	spin_lock(&pnp_lock);
+	list_add_tail(&dev->global_list, &pnp_global);
+	list_add_tail(&dev->protocol_list, &dev->protocol->devices);
+	spin_unlock(&pnp_lock);
+	pnp_auto_config_dev(dev);
+	ret = device_register(&dev->dev);
+	if (ret == 0)
 		pnp_interface_attach_device(dev);
-	}
-	return error;
+	return ret;
 }
 
 /*
@@ -172,7 +170,7 @@ void pnp_remove_device(struct pnp_dev *dev)
 
 static int __init pnp_init(void)
 {
-	printk(KERN_INFO "Linux Plug and Play Support v0.94 (c) Adam Belay\n");
+	printk(KERN_INFO "Linux Plug and Play Support v0.95 (c) Adam Belay\n");
 	return bus_register(&pnp_bus_type);
 }
 
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index 1c56e16bf49c6ef0899ad0989ac0fab5988a2d03..451585f46bcefe30e9f8ca92dd08d7a1b893a12b 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -95,7 +95,7 @@ static int pnp_device_probe(struct device *dev)
 	pnp_dev = to_pnp_dev(dev);
 	pnp_drv = to_pnp_driver(dev->driver);
 
-	pnp_dbg("pnp: match found with the PnP device '%s' and the driver '%s'", dev->bus_id,pnp_drv->name);
+	pnp_dbg("match found with the PnP device '%s' and the driver '%s'", dev->bus_id,pnp_drv->name);
 
 	error = pnp_device_attach(pnp_dev);
 	if (error < 0)
@@ -103,13 +103,10 @@ static int pnp_device_probe(struct device *dev)
 
 	if (pnp_dev->active == 0) {
 		if (!(pnp_drv->flags & PNP_DRIVER_DO_NOT_ACTIVATE)) {
-			error = pnp_activate_dev(pnp_dev, NULL);
+			error = pnp_activate_dev(pnp_dev);
 			if (error < 0)
 				return error;
 		}
-	} else {
-		if ((pnp_drv->flags & PNP_DRIVER_DO_NOT_ACTIVATE))
-			pnp_disable_dev(pnp_dev);
 	}
 	error = 0;
 	if (pnp_drv->probe && pnp_dev->active) {
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index 20c9557b7b4e28895b4d324d96b1a380877a1c6f..2520f9ec4ad54e5bfd0d07dfed11025d0fd8d56f 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -1,7 +1,7 @@
 /*
  * interface.c - contains everything related to the user interface
  *
- * Some code is based on isapnp_proc.c (c) Jaroslav Kysela <perex@suse.cz>
+ * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@suse.cz>
  * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
  *
  */
@@ -12,6 +12,8 @@
 #include <linux/list.h>
 #include <linux/types.h>
 #include <linux/stat.h>
+#include <linux/ctype.h>
+#include <asm/uaccess.h>
 
 #include "base.h"
 
@@ -158,27 +160,15 @@ static void pnp_print_mem(pnp_info_buffer_t *buffer, char *space, struct pnp_mem
 	case IORESOURCE_MEM_8AND16BIT:
 		s = "8-bit&16-bit";
 		break;
+	case IORESOURCE_MEM_32BIT:
+		s = "32-bit";
+		break;
 	default:
 		s = "16-bit";
 	}
 	pnp_printf(buffer, ", %s\n", s);
 }
 
-static void pnp_print_mem32(pnp_info_buffer_t *buffer, char *space, struct pnp_mem32 *mem32)
-{
-	int first = 1, i;
-
-	pnp_printf(buffer, "%s32-bit memory ", space);
-	for (i = 0; i < 17; i++) {
-		if (first) {
-			first = 0;
-		} else {
-			pnp_printf(buffer, ":");
-		}
-		pnp_printf(buffer, "%02x", mem32->data[i]);
-	}
-}
-
 static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct pnp_resources *res, int dep)
 {
 	char *s;
@@ -186,7 +176,6 @@ static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct p
 	struct pnp_irq *irq;
 	struct pnp_dma *dma;
 	struct pnp_mem *mem;
-	struct pnp_mem32 *mem32;
 
 	switch (res->priority) {
 	case PNP_RES_PRIORITY_PREFERRED:
@@ -211,18 +200,15 @@ static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct p
 		pnp_print_dma(buffer, space, dma);
 	for (mem = res->mem; mem; mem = mem->next)
 		pnp_print_mem(buffer, space, mem);
-	for (mem32 = res->mem32; mem32; mem32 = mem32->next)
-		pnp_print_mem32(buffer, space, mem32);
 }
 
 static ssize_t pnp_show_possible_resources(struct device *dmdev, char *buf)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
-	struct pnp_resources * res = dev->res;
-	int dep = 0;
-	pnp_info_buffer_t *buffer;
-
-	buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t));
+	struct pnp_resources * res = dev->possible;
+	int ret, dep = 0;
+	pnp_info_buffer_t *buffer = (pnp_info_buffer_t *)
+				 pnp_alloc(sizeof(pnp_info_buffer_t));
 	if (!buffer)
 		return -ENOMEM;
 	buffer->len = PAGE_SIZE;
@@ -236,97 +222,301 @@ static ssize_t pnp_show_possible_resources(struct device *dmdev, char *buf)
 		res = res->dep;
 		dep++;
 	}
-	return (buffer->curr - buf);
+	ret = (buffer->curr - buf);
+	kfree(buffer);
+	return ret;
 }
 
 static DEVICE_ATTR(possible,S_IRUGO,pnp_show_possible_resources,NULL);
 
+static void pnp_print_conflict_node(pnp_info_buffer_t *buffer, struct pnp_dev * dev)
+{
+	if (!dev)
+		return;
+	pnp_printf(buffer, "'%s'.\n", dev->dev.bus_id);
+}
+
+static void pnp_print_conflict_desc(pnp_info_buffer_t *buffer, int conflict)
+{
+	if (!conflict)
+		return;
+	pnp_printf(buffer, "  Conflict Detected: %2x - ", conflict);
+	switch (conflict) {
+	case CONFLICT_TYPE_RESERVED:
+		pnp_printf(buffer, "manually reserved.\n");
+		break;
+
+	case CONFLICT_TYPE_IN_USE:
+		pnp_printf(buffer, "currently in use.\n");
+		break;
+
+	case CONFLICT_TYPE_PCI:
+		pnp_printf(buffer, "PCI device.\n");
+		break;
+
+	case CONFLICT_TYPE_INVALID:
+		pnp_printf(buffer, "invalid.\n");
+		break;
+
+	case CONFLICT_TYPE_INTERNAL:
+		pnp_printf(buffer, "another resource on this device.\n");
+		break;
+
+	case CONFLICT_TYPE_PNP_WARM:
+		pnp_printf(buffer, "active PnP device ");
+		break;
+
+	case CONFLICT_TYPE_PNP_COLD:
+		pnp_printf(buffer, "disabled PnP device ");
+		break;
+	default:
+		pnp_printf(buffer, "Unknown conflict.\n");
+		break;
+	}
+}
+
+static void pnp_print_conflict(pnp_info_buffer_t *buffer, struct pnp_dev * dev, int idx, int type)
+{
+	struct pnp_dev * cdev, * wdev = NULL;
+	int conflict;
+	switch (type) {
+	case IORESOURCE_IO:
+		conflict = pnp_check_port(dev, idx);
+		if (conflict == CONFLICT_TYPE_PNP_WARM)
+			wdev = pnp_check_port_conflicts(dev, idx, SEARCH_WARM);
+		cdev = pnp_check_port_conflicts(dev, idx, SEARCH_COLD);
+		break;
+	case IORESOURCE_MEM:
+		conflict = pnp_check_mem(dev, idx);
+		if (conflict == CONFLICT_TYPE_PNP_WARM)
+			wdev = pnp_check_mem_conflicts(dev, idx, SEARCH_WARM);
+		cdev = pnp_check_mem_conflicts(dev, idx, SEARCH_COLD);
+		break;
+	case IORESOURCE_IRQ:
+		conflict = pnp_check_irq(dev, idx);
+		if (conflict == CONFLICT_TYPE_PNP_WARM)
+			wdev = pnp_check_irq_conflicts(dev, idx, SEARCH_WARM);
+		cdev = pnp_check_irq_conflicts(dev, idx, SEARCH_COLD);
+		break;
+	case IORESOURCE_DMA:
+		conflict = pnp_check_dma(dev, idx);
+		if (conflict == CONFLICT_TYPE_PNP_WARM)
+			wdev = pnp_check_dma_conflicts(dev, idx, SEARCH_WARM);
+		cdev = pnp_check_dma_conflicts(dev, idx, SEARCH_COLD);
+		break;
+	default:
+		return;
+	}
+
+	pnp_print_conflict_desc(buffer, conflict);
+
+	if (wdev)
+		pnp_print_conflict_node(buffer, wdev);
+
+	if (cdev) {
+		pnp_print_conflict_desc(buffer, CONFLICT_TYPE_PNP_COLD);
+		pnp_print_conflict_node(buffer, cdev);
+	}
+}
+
 static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
-	char *str = buf;
-	int i;
+	int i, ret;
+	pnp_info_buffer_t *buffer = (pnp_info_buffer_t *)
+				pnp_alloc(sizeof(pnp_info_buffer_t));
+	if (!buffer)
+		return -ENOMEM;
+	if (!dev)
+		return -EINVAL;
+	buffer->len = PAGE_SIZE;
+	buffer->buffer = buf;
+	buffer->curr = buffer->buffer;
 
-	if (!dev->active){
-		str += sprintf(str,"DISABLED\n");
-		goto done;
-	}
-	for (i = 0; i < DEVICE_COUNT_IO; i++) {
+	pnp_printf(buffer,"state = ");
+	if (dev->active)
+		pnp_printf(buffer,"active\n");
+	else
+		pnp_printf(buffer,"disabled\n");
+	for (i = 0; i < PNP_MAX_PORT; i++) {
 		if (pnp_port_valid(dev, i)) {
-			str += sprintf(str,"io");
-			str += sprintf(str," 0x%lx-0x%lx \n",
+			pnp_printf(buffer,"io");
+			pnp_printf(buffer," 0x%lx-0x%lx \n",
 						pnp_port_start(dev, i),
 						pnp_port_end(dev, i));
+			pnp_print_conflict(buffer, dev, i, IORESOURCE_IO);
 		}
 	}
-	for (i = 0; i < DEVICE_COUNT_MEM; i++) {
+	for (i = 0; i < PNP_MAX_MEM; i++) {
 		if (pnp_mem_valid(dev, i)) {
-			str += sprintf(str,"mem");
-			str += sprintf(str," 0x%lx-0x%lx \n",
+			pnp_printf(buffer,"mem");
+			pnp_printf(buffer," 0x%lx-0x%lx \n",
 						pnp_mem_start(dev, i),
 						pnp_mem_end(dev, i));
+			pnp_print_conflict(buffer, dev, i, IORESOURCE_MEM);
 		}
 	}
-	for (i = 0; i < DEVICE_COUNT_IRQ; i++) {
+	for (i = 0; i < PNP_MAX_IRQ; i++) {
 		if (pnp_irq_valid(dev, i)) {
-			str += sprintf(str,"irq");
-			str += sprintf(str," %ld \n", pnp_irq(dev, i));
+			pnp_printf(buffer,"irq");
+			pnp_printf(buffer," %ld \n", pnp_irq(dev, i));
+			pnp_print_conflict(buffer, dev, i, IORESOURCE_IRQ);
 		}
 	}
-	for (i = 0; i < DEVICE_COUNT_DMA; i++) {
+	for (i = 0; i < PNP_MAX_DMA; i++) {
 		if (pnp_dma_valid(dev, i)) {
-			str += sprintf(str,"dma");
-			str += sprintf(str," %ld \n", pnp_dma(dev, i));
+			pnp_printf(buffer,"dma");
+			pnp_printf(buffer," %ld \n", pnp_dma(dev, i));
+			pnp_print_conflict(buffer, dev, i, IORESOURCE_DMA);
 		}
 	}
-	done:
-	return (str - buf);
+	ret = (buffer->curr - buf);
+	kfree(buffer);
+	return ret;
 }
 
+extern int pnp_resolve_conflicts(struct pnp_dev *dev);
+
 static ssize_t
-pnp_set_current_resources(struct device * dmdev, const char * buf, size_t count)
+pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
-	char	command[20];
-	int	num_args;
-	int	error = 0;
-	int	depnum;
+	char	*buf = (void *)ubuf;
+	int	retval = 0;
 
-	num_args = sscanf(buf,"%10s %i",command,&depnum);
-	if (!num_args)
+	while (isspace(*buf))
+		++buf;
+	if (!strnicmp(buf,"disable",7)) {
+		retval = pnp_disable_dev(dev);
 		goto done;
-	if (!strnicmp(command,"lock",4)) {
-		if (dev->active) {
-			dev->lock_resources = 1;
-		} else {
-			error = -EINVAL;
-		}
+	}
+	if (!strnicmp(buf,"activate",8)) {
+		retval = pnp_activate_dev(dev);
 		goto done;
 	}
-	if (!strnicmp(command,"unlock",6)) {
-		if (dev->lock_resources) {
-			dev->lock_resources = 0;
-		} else {
-			error = -EINVAL;
-		}
+	if (!strnicmp(buf,"reset",5)) {
+		if (!dev->active)
+			goto done;
+		retval = pnp_disable_dev(dev);
+		if (retval)
+			goto done;
+		retval = pnp_activate_dev(dev);
 		goto done;
 	}
-	if (!strnicmp(command,"disable",7)) {
-		error = pnp_disable_dev(dev);
+	if (!strnicmp(buf,"auto-config",11)) {
+		if (dev->active)
+			goto done;
+		retval = pnp_auto_config_dev(dev);
 		goto done;
 	}
-	if (!strnicmp(command,"auto",4)) {
-		error = pnp_activate_dev(dev,NULL);
+	if (!strnicmp(buf,"clear-config",12)) {
+		if (dev->active)
+			goto done;
+		spin_lock(&pnp_lock);
+		dev->config_mode = PNP_CONFIG_MANUAL;
+		pnp_init_resource_table(&dev->res);
+		if (dev->rule)
+			dev->rule->depnum = 0;
+		spin_unlock(&pnp_lock);
 		goto done;
 	}
-	if (!strnicmp(command,"manual",6)) {
-		if (num_args != 2)
+	if (!strnicmp(buf,"resolve",7)) {
+		retval = pnp_resolve_conflicts(dev);
+		goto done;
+	}
+	if (!strnicmp(buf,"get",3)) {
+		spin_lock(&pnp_lock);
+		if (pnp_can_read(dev))
+			dev->protocol->get(dev, &dev->res);
+		spin_unlock(&pnp_lock);
+		goto done;
+	}
+	if (!strnicmp(buf,"set",3)) {
+		if (dev->active)
 			goto done;
-		error = pnp_raw_set_dev(dev,depnum,NULL);
+		buf += 3;
+		struct pnp_resource_table res;
+		int nport = 0, nmem = 0, nirq = 0, ndma = 0;
+		pnp_init_resource_table(&res);
+		while (1) {
+			while (isspace(*buf))
+				++buf;
+			if (!strnicmp(buf,"io",2)) {
+				buf += 2;
+				while (isspace(*buf))
+					++buf;
+				res.port_resource[nport].start = simple_strtoul(buf,&buf,0);
+				while (isspace(*buf))
+					++buf;
+				if(*buf == '-') {
+					buf += 1;
+					while (isspace(*buf))
+						++buf;
+					res.port_resource[nport].end = simple_strtoul(buf,&buf,0);
+				} else
+					res.port_resource[nport].end = res.port_resource[nport].start;
+				res.port_resource[nport].flags = IORESOURCE_IO;
+				nport++;
+				if (nport >= PNP_MAX_PORT)
+					break;
+				continue;
+			}
+			if (!strnicmp(buf,"mem",3)) {
+				buf += 3;
+				while (isspace(*buf))
+					++buf;
+				res.mem_resource[nmem].start = simple_strtoul(buf,&buf,0);
+				while (isspace(*buf))
+					++buf;
+				if(*buf == '-') {
+					buf += 1;
+					while (isspace(*buf))
+						++buf;
+					res.mem_resource[nmem].end = simple_strtoul(buf,&buf,0);
+				} else
+					res.mem_resource[nmem].end = res.mem_resource[nmem].start;
+				res.mem_resource[nmem].flags = IORESOURCE_MEM;
+				nmem++;
+				if (nmem >= PNP_MAX_MEM)
+					break;
+				continue;
+			}
+			if (!strnicmp(buf,"irq",3)) {
+				buf += 3;
+				while (isspace(*buf))
+					++buf;
+				res.irq_resource[nirq].start =
+				res.irq_resource[nirq].end = simple_strtoul(buf,&buf,0);
+				res.irq_resource[nirq].flags = IORESOURCE_IRQ;
+				nirq++;
+				if (nirq >= PNP_MAX_IRQ)
+					break;
+				continue;
+			}
+			if (!strnicmp(buf,"dma",3)) {
+				buf += 3;
+				while (isspace(*buf))
+					++buf;
+				res.dma_resource[ndma].start =
+				res.dma_resource[ndma].end = simple_strtoul(buf,&buf,0);
+				res.dma_resource[ndma].flags = IORESOURCE_DMA;
+				ndma++;
+				if (ndma >= PNP_MAX_DMA)
+					break;
+				continue;
+			}
+			break;
+		}
+		spin_lock(&pnp_lock);
+		dev->config_mode = PNP_CONFIG_MANUAL;
+		dev->res = res;
+		spin_unlock(&pnp_lock);
 		goto done;
 	}
  done:
-	return error < 0 ? error : count;
+	if (retval)
+		return retval;
+	return count;
 }
 
 static DEVICE_ATTR(resources,S_IRUGO | S_IWUSR,
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index ec79ed4727c8171cf5825b70d4cc15a793bd4ce5..eb30153aae85338aea4d1dca89cd218f92900024 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -101,7 +101,6 @@ static int isapnp_detected;
 
 /* some prototypes */
 
-static int isapnp_config_prepare(struct pnp_dev *dev);
 extern struct pnp_protocol isapnp_protocol;
 
 static inline void write_data(unsigned char x)
@@ -260,7 +259,7 @@ static int isapnp_next_rdp(void)
 		 *	We cannot use NE2000 probe spaces for ISAPnP or we
 		 *	will lock up machines.
 		 */
-		if ((rdp < 0x280 || rdp >  0x380) && !check_region(rdp, 1)) 
+		if ((rdp < 0x280 || rdp >  0x380) && !check_region(rdp, 1))
 		{
 			isapnp_rdp = rdp;
 			return 0;
@@ -580,14 +579,18 @@ static void __init isapnp_add_mem32_resource(struct pnp_dev *dev,
 						 int depnum, int size)
 {
 	unsigned char tmp[17];
-	struct pnp_mem32 *mem32;
+	struct pnp_mem *mem;
 
 	isapnp_peek(tmp, size);
-	mem32 = isapnp_alloc(sizeof(struct pnp_mem32));
-	if (!mem32)
+	mem = isapnp_alloc(sizeof(struct pnp_mem));
+	if (!mem)
 		return;
-	memcpy(mem32->data, tmp, 17);
-	pnp_add_mem32_resource(dev,depnum,mem32);
+	mem->min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
+	mem->max = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
+	mem->align = (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9];
+	mem->size = (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13];
+	mem->flags = tmp[0];
+	pnp_add_mem_resource(dev,depnum,mem);
 }
 
 /*
@@ -597,15 +600,18 @@ static void __init isapnp_add_mem32_resource(struct pnp_dev *dev,
 static void __init isapnp_add_fixed_mem32_resource(struct pnp_dev *dev,
 						       int depnum, int size)
 {
-	unsigned char tmp[17];
-	struct pnp_mem32 *mem32;
+	unsigned char tmp[9];
+	struct pnp_mem *mem;
 
 	isapnp_peek(tmp, size);
-	mem32 = isapnp_alloc(sizeof(struct pnp_mem32));
-	if (!mem32)
+	mem = isapnp_alloc(sizeof(struct pnp_mem));
+	if (!mem)
 		return;
-	memcpy(mem32->data, tmp, 17);
-	pnp_add_mem32_resource(dev,depnum,mem32);
+	mem->min = mem->max = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
+	mem->size = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
+	mem->align = 0;
+	mem->flags = tmp[0];
+	pnp_add_mem_resource(dev,depnum,mem);
 }
 
 /*
@@ -650,7 +656,6 @@ static int __init isapnp_create_device(struct pnp_card *card,
 		switch (type) {
 		case _STAG_LOGDEVID:
 			if (size >= 5 && size <= 6) {
-				isapnp_config_prepare(dev);
 				if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
 					return 1;
 				pnp_build_resource(dev,0);
@@ -723,7 +728,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
 			size = 0;
 			break;
 		case _LTAG_ANSISTR:
-			isapnp_parse_name(dev->name, sizeof(dev->name), &size);
+			isapnp_parse_name(dev->dev.name, sizeof(dev->dev.name), &size);
 			break;
 		case _LTAG_UNICODESTR:
 			/* silently ignore */
@@ -738,7 +743,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
 			size = 0;
 			break;
 		case _LTAG_FIXEDMEM32RANGE:
-			if (size != 17)
+			if (size != 9)
 				goto __skip;
 			isapnp_add_fixed_mem32_resource(dev, depnum, size);
 			size = 0;
@@ -746,7 +751,6 @@ static int __init isapnp_create_device(struct pnp_card *card,
 		case _STAG_END:
 			if (size > 0)
 				isapnp_skip_bytes(size);
-			isapnp_config_prepare(dev);
 			return 1;
 		default:
 			printk(KERN_ERR "isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n", type, dev->number, card->number);
@@ -755,14 +759,13 @@ static int __init isapnp_create_device(struct pnp_card *card,
 	      	if (size > 0)
 		      	isapnp_skip_bytes(size);
 	}
-	isapnp_config_prepare(dev);
 	return 0;
 }
 
 /*
  *  Parse resource map for ISA PnP card.
  */
- 
+
 static void __init isapnp_parse_resource_map(struct pnp_card *card)
 {
 	unsigned char type, tmp[17];
@@ -790,7 +793,7 @@ static void __init isapnp_parse_resource_map(struct pnp_card *card)
 		case _STAG_VENDOR:
 			break;
 		case _LTAG_ANSISTR:
-			isapnp_parse_name(card->name, sizeof(card->name), &size);
+			isapnp_parse_name(card->dev.name, sizeof(card->dev.name), &size);
 			break;
 		case _LTAG_UNICODESTR:
 			/* silently ignore */
@@ -819,7 +822,7 @@ static unsigned char __init isapnp_checksum(unsigned char *data)
 {
 	int i, j;
 	unsigned char checksum = 0x6a, bit, b;
-	
+
 	for (i = 0; i < 8; i++) {
 		b = data[i];
 		for (j = 0; j < 8; j++) {
@@ -852,6 +855,63 @@ static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor,
 	pnpc_add_id(id,card);
 }
 
+
+static int isapnp_parse_current_resources(struct pnp_dev *dev, struct pnp_resource_table * res)
+{
+	int tmp, ret;
+	struct pnp_rule_table rule;
+	if (dev->rule)
+		rule = *dev->rule;
+	else {
+		if (!pnp_generate_rule(dev,1,&rule))
+			return -EINVAL;
+	}
+
+	dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE);
+	if (dev->active) {
+		for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {
+			ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1));
+			if (!ret)
+				continue;
+			res->port_resource[tmp].start = ret;
+			if (rule.port[tmp])
+				res->port_resource[tmp].end = ret + rule.port[tmp]->size - 1;
+			else
+				res->port_resource[tmp].end = ret + 1; /* all we can do is assume 1 :-( */
+			res->port_resource[tmp].flags = IORESOURCE_IO;
+		}
+		for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) {
+			ret = isapnp_read_dword(ISAPNP_CFG_MEM + (tmp << 3));
+			if (!ret)
+				continue;
+			res->mem_resource[tmp].start = ret;
+			if (rule.mem[tmp])
+				res->mem_resource[tmp].end = ret + rule.mem[tmp]->size - 1;
+			else
+				res->mem_resource[tmp].end = ret + 1; /* all we can do is assume 1 :-( */
+			res->mem_resource[tmp].flags = IORESOURCE_MEM;
+		}
+		for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) {
+			ret = (isapnp_read_word(ISAPNP_CFG_IRQ + (tmp << 1)) >> 8);
+			if (!ret)
+				continue;
+			res->irq_resource[tmp].start = res->irq_resource[tmp].end = ret;
+			res->irq_resource[tmp].flags = IORESOURCE_IRQ;
+		}
+		for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) {
+			ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp);
+			if (ret == 4)
+				continue;
+			if (rule.dma[tmp]) { /* some isapnp systems forget to set this to 4 so we have to check */
+				res->dma_resource[tmp].start = res->dma_resource[tmp].end = ret;
+				res->dma_resource[tmp].flags = IORESOURCE_DMA;
+			}
+		}
+	}
+	return 0;
+}
+
+
 /*
  *  Build device list for all present ISA PnP devices.
  */
@@ -861,6 +921,7 @@ static int __init isapnp_build_device_list(void)
 	int csn;
 	unsigned char header[9], checksum;
 	struct pnp_card *card;
+	struct pnp_dev *dev;
 
 	isapnp_wait();
 	isapnp_key();
@@ -893,8 +954,17 @@ static int __init isapnp_build_device_list(void)
 			printk(KERN_ERR "isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value);
 		card->checksum = isapnp_checksum_value;
 		card->protocol = &isapnp_protocol;
+
+		/* read the current resource data */
+		card_for_each_dev(card,dev) {
+			isapnp_device(dev->number);
+		pnp_init_resource_table(&dev->res);
+			isapnp_parse_current_resources(dev, &dev->res);
+		}
+
 		pnpc_add_card(card);
 	}
+	isapnp_wait();
 	return 0;
 }
 
@@ -948,39 +1018,6 @@ int isapnp_cfg_end(void)
 	return 0;
 }
 
-static int isapnp_config_prepare(struct pnp_dev *dev)
-{
-	int idx;
-	if (dev == NULL)
-		return -EINVAL;
-	if (dev->active || dev->lock_resources)
-		return -EBUSY;
-	for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++) {
-		dev->irq_resource[idx].name = NULL;
-		dev->irq_resource[idx].start = -1;
-		dev->irq_resource[idx].end = -1;
-		dev->irq_resource[idx].flags = IORESOURCE_IRQ|IORESOURCE_UNSET;
-	}
-	for (idx = 0; idx < DEVICE_COUNT_DMA; idx++) {
-		dev->dma_resource[idx].name = NULL;
-		dev->dma_resource[idx].start = -1;
-		dev->dma_resource[idx].end = -1;
-		dev->dma_resource[idx].flags = IORESOURCE_DMA|IORESOURCE_UNSET;
-	}
-	for (idx = 0; idx < DEVICE_COUNT_IO; idx++) {
-		dev->io_resource[idx].name = NULL;
-		dev->io_resource[idx].start = 0;
-		dev->io_resource[idx].end = 0;
-		dev->io_resource[idx].flags = IORESOURCE_IO|IORESOURCE_UNSET;
-	}
-	for (idx = 0; idx < DEVICE_COUNT_MEM; idx++) {
-		dev->mem_resource[idx].name = NULL;
-		dev->mem_resource[idx].start = 0;
-		dev->mem_resource[idx].end = 0;
-		dev->mem_resource[idx].flags = IORESOURCE_MEM|IORESOURCE_UNSET;
-	}
-	return 0;
-}
 
 /*
  *  Inititialization.
@@ -999,44 +1036,35 @@ EXPORT_SYMBOL(isapnp_write_dword);
 EXPORT_SYMBOL(isapnp_wake);
 EXPORT_SYMBOL(isapnp_device);
 
-static int isapnp_get_resources(struct pnp_dev *dev)
+static int isapnp_get_resources(struct pnp_dev *dev, struct pnp_resource_table * res)
 {
-	/* We don't need to do anything but this, the rest is taken care of */
-	if (pnp_port_valid(dev, 0) == 0 &&
-	    pnp_mem_valid(dev, 0) == 0 &&
-	    pnp_irq_valid(dev, 0) == 0 &&
-	    pnp_dma_valid(dev, 0) == 0)
-		dev->active = 0;
-	else
-		dev->active = 1;
-	return 0;
+	int ret;
+	pnp_init_resource_table(res);
+	isapnp_cfg_begin(dev->card->number, dev->number);
+	ret = isapnp_parse_current_resources(dev, res);
+	isapnp_cfg_end();
+	return ret;
 }
 
-static int isapnp_set_resources(struct pnp_dev *dev, struct pnp_cfg *cfg)
+static int isapnp_set_resources(struct pnp_dev *dev, struct pnp_resource_table * res)
 {
 	int tmp;
-      	isapnp_cfg_begin(dev->card->number, dev->number);
+
+	isapnp_cfg_begin(dev->card->number, dev->number);
 	dev->active = 1;
-	dev->irq_resource[0] = cfg->request.irq_resource[0];
-	dev->irq_resource[1] = cfg->request.irq_resource[1];
-	dev->dma_resource[0] = cfg->request.dma_resource[0];
-	dev->dma_resource[1] = cfg->request.dma_resource[1];
-	for (tmp = 0; tmp < DEVICE_COUNT_IO; tmp++)
-		dev->io_resource[tmp] = cfg->request.io_resource[tmp];
-	for (tmp = 0; tmp < DEVICE_COUNT_MEM; tmp++)
-		dev->mem_resource[tmp] = cfg->request.mem_resource[tmp];
-	for (tmp = 0; tmp < 8 && pnp_port_valid(dev, tmp); tmp++)
-		isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), pnp_port_start(dev, tmp));
-	for (tmp = 0; tmp < 2 && pnp_irq_valid(dev, tmp); tmp++) {
-		int irq = pnp_irq(dev, tmp);
+	for (tmp = 0; tmp < PNP_MAX_PORT && res->port_resource[tmp].flags & IORESOURCE_IO; tmp++)
+		isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), res->port_resource[tmp].start);
+	for (tmp = 0; tmp < PNP_MAX_IRQ && res->irq_resource[tmp].flags & IORESOURCE_IRQ; tmp++) {
+		int irq = res->irq_resource[tmp].start;
 		if (irq == 2)
 			irq = 9;
 		isapnp_write_byte(ISAPNP_CFG_IRQ+(tmp<<1), irq);
 	}
-	for (tmp = 0; tmp < 2 && pnp_dma_valid(dev, tmp); tmp++)
-		isapnp_write_byte(ISAPNP_CFG_DMA+tmp, pnp_dma(dev, tmp));
-	for (tmp = 0; tmp < 4 && pnp_mem_valid(dev, tmp); tmp++)
-		isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<2), (pnp_mem_start(dev, tmp) >> 8) & 0xffff);
+	for (tmp = 0; tmp < PNP_MAX_DMA && res->dma_resource[tmp].flags & IORESOURCE_DMA; tmp++)
+		isapnp_write_byte(ISAPNP_CFG_DMA+tmp, res->dma_resource[tmp].start);
+	for (tmp = 0; tmp < PNP_MAX_MEM && res->mem_resource[tmp].flags & IORESOURCE_MEM; tmp++)
+		isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<2), (res->mem_resource[tmp].start >> 8) & 0xffff);
+	/* FIXME: We aren't handling 32bit mems properly here */
 	isapnp_activate(dev->number);
 	isapnp_cfg_end();
 	return 0;
@@ -1046,7 +1074,7 @@ static int isapnp_disable_resources(struct pnp_dev *dev)
 {
 	if (!dev || !dev->active)
 		return -EINVAL;
-      	isapnp_cfg_begin(dev->card->number, dev->number);
+	isapnp_cfg_begin(dev->card->number, dev->number);
 	isapnp_deactivate(dev->number);
 	dev->active = 0;
 	isapnp_cfg_end();
@@ -1127,11 +1155,11 @@ int __init isapnp_init(void)
 	protocol_for_each_card(&isapnp_protocol,card) {
 		cards++;
 		if (isapnp_verbose) {
-			printk(KERN_INFO "isapnp: Card '%s'\n", card->name[0]?card->name:"Unknown");
+			printk(KERN_INFO "isapnp: Card '%s'\n", card->dev.name[0]?card->dev.name:"Unknown");
 			if (isapnp_verbose < 2)
 				continue;
-			pnp_card_for_each_dev(card,dev) {
-				printk(KERN_INFO "isapnp:   Device '%s'\n", dev->name[0]?dev->name:"Unknown");
+			card_for_each_dev(card,dev) {
+				printk(KERN_INFO "isapnp:   Device '%s'\n", dev->dev.name[0]?dev->dev.name:"Unknown");
 			}
 		}
 	}
@@ -1145,7 +1173,7 @@ int __init isapnp_init(void)
 	return 0;
 }
 
-subsys_initcall(isapnp_init);
+device_initcall(isapnp_init);
 
 /* format is: noisapnp */
 
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
new file mode 100644
index 0000000000000000000000000000000000000000..90e70be2a3a2929b0f1cc834c089f104aa854d93
--- /dev/null
+++ b/drivers/pnp/manager.c
@@ -0,0 +1,711 @@
+/*
+ * manager.c - Resource Management, Conflict Resolution, Activation and Disabling of Devices
+ *
+ * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#ifdef CONFIG_PNP_DEBUG
+	#define DEBUG
+#else
+	#undef DEBUG
+#endif
+
+#include <linux/pnp.h>
+#include "base.h"
+
+
+int pnp_max_moves = 4;
+
+
+static int pnp_next_port(struct pnp_dev * dev, int idx)
+{
+	struct pnp_port *port;
+	unsigned long *start, *end, *flags;
+	if (!dev || idx < 0 || idx >= PNP_MAX_PORT)
+		return 0;
+	port = dev->rule->port[idx];
+	if (!port)
+		return 1;
+
+	start = &dev->res.port_resource[idx].start;
+	end = &dev->res.port_resource[idx].end;
+	flags = &dev->res.port_resource[idx].flags;
+
+	/* set the initial values if this is the first time */
+	if (*start == 0) {
+		*start = port->min;
+		*end = *start + port->size - 1;
+		*flags = port->flags | IORESOURCE_IO;
+		if (!pnp_check_port(dev, idx))
+			return 1;
+	}
+
+	/* run through until pnp_check_port is happy */
+	do {
+		*start += port->align;
+		*end = *start + port->size - 1;
+		if (*start > port->max || !port->align)
+			return 0;
+	} while (pnp_check_port(dev, idx));
+	return 1;
+}
+
+static int pnp_next_mem(struct pnp_dev * dev, int idx)
+{
+	struct pnp_mem *mem;
+	unsigned long *start, *end, *flags;
+	if (!dev || idx < 0 || idx >= PNP_MAX_MEM)
+		return 0;
+	mem = dev->rule->mem[idx];
+	if (!mem)
+		return 1;
+
+	start = &dev->res.mem_resource[idx].start;
+	end = &dev->res.mem_resource[idx].end;
+	flags = &dev->res.mem_resource[idx].flags;
+
+	/* set the initial values if this is the first time */
+	if (*start == 0) {
+		*start = mem->min;
+		*end = *start + mem->size -1;
+		*flags = mem->flags | IORESOURCE_MEM;
+		if (!(mem->flags & IORESOURCE_MEM_WRITEABLE))
+			*flags |= IORESOURCE_READONLY;
+		if (mem->flags & IORESOURCE_MEM_CACHEABLE)
+			*flags |= IORESOURCE_CACHEABLE;
+		if (mem->flags & IORESOURCE_MEM_RANGELENGTH)
+			*flags |= IORESOURCE_RANGELENGTH;
+		if (mem->flags & IORESOURCE_MEM_SHADOWABLE)
+			*flags |= IORESOURCE_SHADOWABLE;
+		if (!pnp_check_mem(dev, idx))
+			return 1;
+	}
+
+	/* run through until pnp_check_mem is happy */
+	do {
+		*start += mem->align;
+		*end = *start + mem->size - 1;
+		if (*start > mem->max || !mem->align)
+			return 0;
+	} while (pnp_check_mem(dev, idx));
+	return 1;
+}
+
+static int pnp_next_irq(struct pnp_dev * dev, int idx)
+{
+	struct pnp_irq *irq;
+	unsigned long *start, *end, *flags;
+	int i, mask;
+	if (!dev || idx < 0 || idx >= PNP_MAX_IRQ)
+		return 0;
+	irq = dev->rule->irq[idx];
+	if (!irq)
+		return 1;
+
+	start = &dev->res.irq_resource[idx].start;
+	end = &dev->res.irq_resource[idx].end;
+	flags = &dev->res.irq_resource[idx].flags;
+
+	/* set the initial values if this is the first time */
+	if (*start == -1) {
+		*start = *end = 0;
+		*flags = irq->flags | IORESOURCE_IRQ;
+		if (!pnp_check_irq(dev, idx))
+			return 1;
+	}
+
+	mask = irq->map;
+	for (i = *start + 1; i < 16; i++)
+	{
+		if(mask>>i & 0x01) {
+			*start = *end = i;
+			if(!pnp_check_irq(dev, idx))
+				return 1;
+		}
+	}
+	return 0;
+}
+
+static int pnp_next_dma(struct pnp_dev * dev, int idx)
+{
+	struct pnp_dma *dma;
+	unsigned long *start, *end, *flags;
+	int i, mask;
+	if (!dev || idx < 0 || idx >= PNP_MAX_DMA)
+		return -EINVAL;
+	dma = dev->rule->dma[idx];
+	if (!dma)
+		return 1;
+
+	start = &dev->res.dma_resource[idx].start;
+	end = &dev->res.dma_resource[idx].end;
+	flags = &dev->res.dma_resource[idx].flags;
+
+	/* set the initial values if this is the first time */
+	if (*start == -1) {
+		*start = *end = 0;
+		*flags = dma->flags | IORESOURCE_DMA;
+		if (!pnp_check_dma(dev, idx))
+			return 1;
+	}
+
+	mask = dma->map;
+	for (i = *start + 1; i < 8; i++)
+	{
+		if(mask>>i & 0x01) {
+			*start = *end = i;
+			if(!pnp_check_dma(dev, idx))
+				return 1;
+		}
+	}
+	return 0;
+}
+
+static int pnp_next_rule(struct pnp_dev *dev)
+{
+	int depnum = dev->rule->depnum;
+        int max = pnp_get_max_depnum(dev);
+	int priority = PNP_RES_PRIORITY_PREFERRED;
+
+	if (depnum < 0)
+		return 0;
+
+	if (max == 0) {
+		if (pnp_generate_rule(dev, 0, dev->rule)) {
+			dev->rule->depnum = -1;
+			return 1;
+		}
+	}
+
+	if(depnum > 0) {
+		struct pnp_resources * res = pnp_find_resources(dev, depnum);
+		priority = res->priority;
+	}
+
+	for (; priority <= PNP_RES_PRIORITY_FUNCTIONAL; priority++, depnum = 0) {
+		depnum += 1;
+		for (; depnum <= max; depnum++) {
+			struct pnp_resources * res = pnp_find_resources(dev, depnum);
+			if (res->priority == priority) {
+				if(pnp_generate_rule(dev, depnum, dev->rule)) {
+					dev->rule->depnum = depnum;
+					return 1;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+struct pnp_change {
+	struct list_head change_list;
+	struct list_head changes;
+	struct pnp_resource_table res_bak;
+	struct pnp_rule_table rule_bak;
+	struct pnp_dev * dev;
+};
+
+static void pnp_free_changes(struct pnp_change * parent)
+{
+	struct list_head * pos, * temp;
+	list_for_each_safe(pos, temp, &parent->changes) {
+		struct pnp_change * change = list_entry(pos, struct pnp_change, change_list);
+		list_del(&change->change_list);
+		kfree(change);
+	}
+}
+
+static void pnp_undo_changes(struct pnp_change * parent)
+{
+	struct list_head * pos, * temp;
+	list_for_each_safe(pos, temp, &parent->changes) {
+		struct pnp_change * change = list_entry(pos, struct pnp_change, change_list);
+		*change->dev->rule = change->rule_bak;
+		change->dev->res = change->res_bak;
+		list_del(&change->change_list);
+		kfree(change);
+	}
+}
+
+static struct pnp_change * pnp_add_change(struct pnp_change * parent, struct pnp_dev * dev)
+{
+	struct pnp_change * change = pnp_alloc(sizeof(struct pnp_change));
+	if (!change)
+		return NULL;
+	change->res_bak = dev->res;
+	change->rule_bak = *dev->rule;
+	change->dev = dev;
+	INIT_LIST_HEAD(&change->changes);
+	if (parent)
+		list_add(&change->change_list, &parent->changes);
+	return change;
+}
+
+static void pnp_commit_changes(struct pnp_change * parent, struct pnp_change * change)
+{
+	/* check if it's the root change */
+	if (!parent)
+		return;
+	if (!list_empty(&change->changes))
+		list_splice_init(&change->changes, &parent->changes);
+}
+
+static int pnp_next_config(struct pnp_dev * dev, int move, struct pnp_change * parent);
+
+static int pnp_next_request(struct pnp_dev * dev, int move, struct pnp_change * parent, struct pnp_change * change)
+{
+	int i;
+	struct pnp_dev * cdev;
+
+	for (i = 0; i < PNP_MAX_PORT; i++) {
+		if (dev->res.port_resource[i].start == 0
+		 || pnp_check_port_conflicts(dev,i,SEARCH_WARM)) {
+			if (!pnp_next_port(dev,i))
+				return 0;
+		}
+		do {
+			cdev = pnp_check_port_conflicts(dev,i,SEARCH_COLD);
+			if (cdev && (!move || !pnp_next_config(cdev,move,change))) {
+				pnp_undo_changes(change);
+				if (!pnp_next_port(dev,i))
+					return 0;
+			}
+		} while (cdev);
+		pnp_commit_changes(parent, change);
+	}
+	for (i = 0; i < PNP_MAX_MEM; i++) {
+		if (dev->res.mem_resource[i].start == 0
+		 || pnp_check_mem_conflicts(dev,i,SEARCH_WARM)) {
+			if (!pnp_next_mem(dev,i))
+				return 0;
+		}
+		do {
+			cdev = pnp_check_mem_conflicts(dev,i,SEARCH_COLD);
+			if (cdev && (!move || !pnp_next_config(cdev,move,change))) {
+				pnp_undo_changes(change);
+				if (!pnp_next_mem(dev,i))
+					return 0;
+			}
+		} while (cdev);
+		pnp_commit_changes(parent, change);
+	}
+	for (i = 0; i < PNP_MAX_IRQ; i++) {
+		if (dev->res.irq_resource[i].start == -1
+		 || pnp_check_irq_conflicts(dev,i,SEARCH_WARM)) {
+			if (!pnp_next_irq(dev,i))
+				return 0;
+		}
+		do {
+			cdev = pnp_check_irq_conflicts(dev,i,SEARCH_COLD);
+			if (cdev && (!move || !pnp_next_config(cdev,move,change))) {
+				pnp_undo_changes(change);
+				if (!pnp_next_irq(dev,i))
+					return 0;
+			}
+		} while (cdev);
+		pnp_commit_changes(parent, change);
+	}
+	for (i = 0; i < PNP_MAX_DMA; i++) {
+		if (dev->res.dma_resource[i].start == -1
+		 || pnp_check_dma_conflicts(dev,i,SEARCH_WARM)) {
+			if (!pnp_next_dma(dev,i))
+				return 0;
+		}
+		do {
+			cdev = pnp_check_dma_conflicts(dev,i,SEARCH_COLD);
+			if (cdev && (!move || !pnp_next_config(cdev,move,change))) {
+				pnp_undo_changes(change);
+				if (!pnp_next_dma(dev,i))
+					return 0;
+			}
+		} while (cdev);
+		pnp_commit_changes(parent, change);
+	}
+	return 1;
+}
+
+static int pnp_next_config(struct pnp_dev * dev, int move, struct pnp_change * parent)
+{
+	struct pnp_change * change;
+	move--;
+	if (!dev->rule)
+		return 0;
+	change = pnp_add_change(parent,dev);
+	if (!change)
+		return 0;
+	if (!pnp_can_configure(dev))
+		goto fail;
+	if (!dev->rule->depnum) {
+		if (!pnp_next_rule(dev))
+			goto fail;
+	}
+	while (!pnp_next_request(dev, move, parent, change)) {
+		if(!pnp_next_rule(dev))
+			goto fail;
+		pnp_init_resource_table(&dev->res);
+	}
+	if (!parent) {
+		pnp_free_changes(change);
+		kfree(change);
+	}
+	return 1;
+
+fail:
+	if (!parent)
+		kfree(change);
+	return 0;
+}
+
+/* this advanced algorithm will shuffle other configs to make room and ensure that the most possible devices have configs */
+static int pnp_advanced_config(struct pnp_dev * dev)
+{
+	int move;
+	/* if the device cannot be configured skip it */
+	if (!pnp_can_configure(dev))
+		return 1;
+	if (!dev->rule) {
+		dev->rule = pnp_alloc(sizeof(struct pnp_rule_table));
+		if (!dev->rule)
+			return -ENOMEM;
+	}
+
+	spin_lock(&pnp_lock);
+	for (move = 1; move <= pnp_max_moves; move++) {
+		dev->rule->depnum = 0;
+		pnp_init_resource_table(&dev->res);
+		if (pnp_next_config(dev,move,NULL)) {
+			spin_unlock(&pnp_lock);
+			return 1;
+		}
+	}
+
+	pnp_init_resource_table(&dev->res);
+	dev->rule->depnum = 0;
+	spin_unlock(&pnp_lock);
+	pnp_err("res: Unable to resolve resource conflicts for the device '%s', some devices may not be usable.", dev->dev.bus_id);
+	return 0;
+}
+
+int pnp_resolve_conflicts(struct pnp_dev *dev)
+{
+	int i;
+	struct pnp_dev * cdev;
+
+	for (i = 0; i < PNP_MAX_PORT; i++)
+	{
+		do {
+			cdev = pnp_check_port_conflicts(dev,i,SEARCH_COLD);
+			if (cdev)
+				pnp_advanced_config(cdev);
+		} while (cdev);
+	}
+	for (i = 0; i < PNP_MAX_MEM; i++)
+	{
+		do {
+			cdev = pnp_check_mem_conflicts(dev,i,SEARCH_COLD);
+			if (cdev)
+				pnp_advanced_config(cdev);
+		} while (cdev);
+	}
+	for (i = 0; i < PNP_MAX_IRQ; i++)
+	{
+		do {
+			cdev = pnp_check_irq_conflicts(dev,i,SEARCH_COLD);
+			if (cdev)
+				pnp_advanced_config(cdev);
+		} while (cdev);
+	}
+	for (i = 0; i < PNP_MAX_DMA; i++)
+	{
+		do {
+			cdev = pnp_check_dma_conflicts(dev,i,SEARCH_COLD);
+			if (cdev)
+				pnp_advanced_config(cdev);
+		} while (cdev);
+	}
+	return 1;
+}
+
+/* this is a much faster algorithm but it may not leave resources for other devices to use */
+static int pnp_simple_config(struct pnp_dev * dev)
+{
+	int i;
+	spin_lock(&pnp_lock);
+	if (dev->active) {
+		spin_unlock(&pnp_lock);
+		return 1;
+	}
+	if (!dev->rule) {
+		dev->rule = pnp_alloc(sizeof(struct pnp_rule_table));
+		if (!dev->rule) {
+			spin_unlock(&pnp_lock);
+			return -ENOMEM;
+		}
+	}
+	dev->rule->depnum = 0;
+	pnp_init_resource_table(&dev->res);
+	while (pnp_next_rule(dev)) {
+		for (i = 0; i < PNP_MAX_PORT; i++) {
+			if (!pnp_next_port(dev,i))
+				continue;
+		}
+		for (i = 0; i < PNP_MAX_MEM; i++) {
+			if (!pnp_next_mem(dev,i))
+				continue;
+		}
+		for (i = 0; i < PNP_MAX_IRQ; i++) {
+			if (!pnp_next_irq(dev,i))
+				continue;
+		}
+		for (i = 0; i < PNP_MAX_DMA; i++) {
+			if (!pnp_next_dma(dev,i))
+				continue;
+		}
+		goto done;
+	}
+	pnp_init_resource_table(&dev->res);
+	dev->rule->depnum = 0;
+	spin_unlock(&pnp_lock);
+	return 0;
+
+done:
+	pnp_resolve_conflicts(dev);	/* this is required or we will break the advanced configs */
+	return 1;
+}
+
+static int pnp_compare_resources(struct pnp_resource_table * resa, struct pnp_resource_table * resb)
+{
+	int idx;
+	for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
+		if (resa->irq_resource[idx].start != resb->irq_resource[idx].start)
+			return 1;
+	}
+	for (idx = 0; idx < PNP_MAX_DMA; idx++) {
+		if (resa->dma_resource[idx].start != resb->dma_resource[idx].start)
+			return 1;
+	}
+	for (idx = 0; idx < PNP_MAX_PORT; idx++) {
+		if (resa->port_resource[idx].start != resb->port_resource[idx].start)
+			return 1;
+		if (resa->port_resource[idx].end != resb->port_resource[idx].end)
+			return 1;
+	}
+	for (idx = 0; idx < PNP_MAX_MEM; idx++) {
+		if (resa->mem_resource[idx].start != resb->mem_resource[idx].start)
+			return 1;
+		if (resa->mem_resource[idx].end != resb->mem_resource[idx].end)
+			return 1;
+	}
+	return 0;
+}
+
+
+/*
+ * PnP Device Resource Management
+ */
+
+/**
+ * pnp_auto_config_dev - determines the best possible resource configuration based on available information
+ * @dev: pointer to the desired device
+ *
+ */
+
+int pnp_auto_config_dev(struct pnp_dev *dev)
+{
+	int error;
+	if(!dev)
+		return -EINVAL;
+
+	dev->config_mode = PNP_CONFIG_AUTO;
+
+	if(dev->active)
+		error = pnp_resolve_conflicts(dev);
+	else
+		error = pnp_advanced_config(dev);
+	return error;
+}
+
+/**
+ * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table
+ * @dev: pointer to the desired device
+ * @res: pointer to the new resource config
+ *
+ * This function can be used by drivers that want to manually set thier resources.
+ */
+
+int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table * res, int mode)
+{
+	int i;
+	struct pnp_resource_table bak = dev->res;
+	if (!dev || !res)
+		return -EINVAL;
+	if (dev->active)
+		return -EBUSY;
+	spin_lock(&pnp_lock);
+	dev->res = *res;
+
+	if (!(mode & PNP_CONFIG_FORCE)) {
+		for (i = 0; i < PNP_MAX_PORT; i++) {
+			if(pnp_check_port(dev,i))
+				goto fail;
+		}
+		for (i = 0; i < PNP_MAX_MEM; i++) {
+			if(pnp_check_mem(dev,i))
+				goto fail;
+		}
+		for (i = 0; i < PNP_MAX_IRQ; i++) {
+			if(pnp_check_irq(dev,i))
+				goto fail;
+		}
+		for (i = 0; i < PNP_MAX_DMA; i++) {
+			if(pnp_check_dma(dev,i))
+				goto fail;
+		}
+	}
+	spin_unlock(&pnp_lock);
+
+	pnp_resolve_conflicts(dev);
+	dev->config_mode = PNP_CONFIG_MANUAL;
+	return 0;
+
+fail:
+	dev->res = bak;
+	spin_unlock(&pnp_lock);
+	return -EINVAL;
+}
+
+/**
+ * pnp_activate_dev - activates a PnP device for use
+ * @dev: pointer to the desired device
+ *
+ * finds the best resource configuration and then informs the correct pnp protocol
+ */
+
+int pnp_activate_dev(struct pnp_dev *dev)
+{
+	if (!dev)
+		return -EINVAL;
+	if (dev->active) {
+		pnp_info("res: The PnP device '%s' is already active.", dev->dev.bus_id);
+		return -EBUSY;
+	}
+	spin_lock(&pnp_lock);	/* we lock just in case the device is being configured during this call */
+	dev->active = 1;
+	spin_unlock(&pnp_lock); /* once the device is claimed active we know it won't be configured so we can unlock */
+
+	/* If this condition is true, advanced configuration failed, we need to get this device up and running
+	 * so we use the simple config engine which ignores cold conflicts, this of course may lead to new failures */
+	if (!pnp_is_active(dev)) {
+		if (!pnp_simple_config(dev)) {
+			pnp_err("res: Unable to resolve resource conflicts for the device '%s'.", dev->dev.bus_id);
+			goto fail;
+		}
+	}
+	if (dev->config_mode & PNP_CONFIG_INVALID) {
+		pnp_info("res: Unable to activate the PnP device '%s' because its resource configuration is invalid.", dev->dev.bus_id);
+		goto fail;
+	}
+	if (dev->status != PNP_READY && dev->status != PNP_ATTACHED){
+		pnp_err("res: Activation failed because the PnP device '%s' is busy.", dev->dev.bus_id);
+		goto fail;
+	}
+	if (!pnp_can_write(dev)) {
+		pnp_info("res: Unable to activate the PnP device '%s' because this feature is not supported.", dev->dev.bus_id);
+		goto fail;
+	}
+	if (dev->protocol->set(dev, &dev->res)<0) {
+		pnp_err("res: The protocol '%s' reports that activating the PnP device '%s' has failed.", dev->protocol->name, dev->dev.bus_id);
+		goto fail;
+	}
+	if (pnp_can_read(dev)) {
+		struct pnp_resource_table res;
+		dev->protocol->get(dev, &res);
+		if (pnp_compare_resources(&dev->res, &res)) /* if this happens we may be in big trouble but it's best just to continue */
+			pnp_err("res: The resources requested do not match those set for the PnP device '%s'.", dev->dev.bus_id);
+	} else
+		dev->active = pnp_is_active(dev);
+	pnp_dbg("res: the device '%s' has been activated.", dev->dev.bus_id);
+	if (dev->rule) {
+		kfree(dev->rule);
+		dev->rule = NULL;
+	}
+	return 0;
+
+fail:
+	dev->active = 0; /* fixes incorrect active state */
+	return -EINVAL;
+}
+
+/**
+ * pnp_disable_dev - disables device
+ * @dev: pointer to the desired device
+ *
+ * inform the correct pnp protocol so that resources can be used by other devices
+ */
+
+int pnp_disable_dev(struct pnp_dev *dev)
+{
+        if (!dev)
+                return -EINVAL;
+	if (!dev->active) {
+		pnp_info("res: The PnP device '%s' is already disabled.", dev->dev.bus_id);
+		return -EINVAL;
+	}
+	if (dev->status != PNP_READY){
+		pnp_info("res: Disable failed becuase the PnP device '%s' is busy.", dev->dev.bus_id);
+		return -EINVAL;
+	}
+	if (!pnp_can_disable(dev)) {
+		pnp_info("res: Unable to disable the PnP device '%s' because this feature is not supported.", dev->dev.bus_id);
+		return -EINVAL;
+	}
+	if (dev->protocol->disable(dev)<0) {
+		pnp_err("res: The protocol '%s' reports that disabling the PnP device '%s' has failed.", dev->protocol->name, dev->dev.bus_id);
+		return -1;
+	}
+	dev->active = 0; /* just in case the protocol doesn't do this */
+	pnp_dbg("the device '%s' has been disabled.", dev->dev.bus_id);
+	return 0;
+}
+
+/**
+ * pnp_resource_change - change one resource
+ * @resource: pointer to resource to be changed
+ * @start: start of region
+ * @size: size of region
+ *
+ */
+
+void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size)
+{
+	if (resource == NULL)
+		return;
+	resource->flags &= ~IORESOURCE_AUTO;
+	resource->start = start;
+	resource->end = start + size - 1;
+}
+
+
+EXPORT_SYMBOL(pnp_auto_config_dev);
+EXPORT_SYMBOL(pnp_manual_config_dev);
+EXPORT_SYMBOL(pnp_activate_dev);
+EXPORT_SYMBOL(pnp_disable_dev);
+EXPORT_SYMBOL(pnp_resource_change);
+
+
+/* format is: pnp_max_moves=num */
+
+static int __init pnp_setup_max_moves(char *str)
+{
+	get_option(&str,&pnp_max_moves);
+	return 1;
+}
+
+__setup("pnp_max_moves=", pnp_setup_max_moves);
diff --git a/drivers/pnp/names.c b/drivers/pnp/names.c
index 297f4c30899080d30433a6799fd12e2ebeeefde1..bdef0ea165392f992cb930a6c48fda3f9ed7d86e 100644
--- a/drivers/pnp/names.c
+++ b/drivers/pnp/names.c
@@ -30,10 +30,10 @@ void
 pnp_name_device(struct pnp_dev *dev)
 {
 	int i;
-	char *name = dev->name;
+	char *name = dev->dev.name;
 	for(i=0; i<sizeof(pnp_id_eisaid)/sizeof(pnp_id_eisaid[0]); i++){
 		if (compare_pnp_id(dev->id,pnp_id_eisaid[i])){
-			sprintf(name, "%s", pnp_id_names[i]);
+			snprintf(name, DEVICE_NAME_SIZE, "%s", pnp_id_names[i]);
 			return;
 		}
 	}
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index cde17aa6823bb23394fc46b440e82a68a1c4786b..69176c1ef8751cffb2875baa2ec8fe44c64ce942 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -142,11 +142,13 @@ set_base(cpu_gdt_table[cpu][(selname) >> 3], (u32)(address)); \
 set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \
 } while(0)
 
+static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
+
 /*
  * At some point we want to use this stack frame pointer to unwind
- * after PnP BIOS oopses. 
+ * after PnP BIOS oopses.
  */
- 
+
 u32 pnp_bios_fault_esp;
 u32 pnp_bios_fault_eip;
 u32 pnp_bios_is_utter_crap = 0;
@@ -160,6 +162,8 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
 {
 	unsigned long flags;
 	u16 status;
+	struct desc_struct save_desc_40;
+	int cpu;
 
 	/*
 	 * PnP BIOSes are generally not terribly re-entrant.
@@ -168,6 +172,10 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
 	if(pnp_bios_is_utter_crap)
 		return PNP_FUNCTION_NOT_SUPPORTED;
 
+	cpu = get_cpu();
+	save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
+	cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
+
 	/* On some boxes IRQ's during PnP BIOS calls are deadly.  */
 	spin_lock_irqsave(&pnp_bios_lock, flags);
 
@@ -207,6 +215,9 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
 		: "memory"
 	);
 	spin_unlock_irqrestore(&pnp_bios_lock, flags);
+
+	cpu_gdt_table[cpu][0x40 / 8] = save_desc_40;
+	put_cpu();
 	
 	/* If we get here and this is set then the PnP BIOS faulted on us. */
 	if(pnp_bios_is_utter_crap)
@@ -236,6 +247,8 @@ void *pnpbios_kmalloc(size_t size, int f)
 	void *p = kmalloc( size, f );
 	if ( p == NULL )
 		printk(KERN_ERR "PnPBIOS: kmalloc() failed\n");
+	else
+		memset(p, 0, size);
 	return p;
 }
 
@@ -664,381 +677,6 @@ static int pnp_dock_thread(void * unused)
 
 #endif   /* CONFIG_HOTPLUG */
 
-
-/* pnp current resource reading functions */
-
-
-static void add_irqresource(struct pnp_dev *dev, int irq)
-{
-	int i = 0;
-	while (pnp_irq_valid(dev, i) && i < DEVICE_COUNT_IRQ) i++;
-	if (i < DEVICE_COUNT_IRQ) {
-		dev->irq_resource[i].start = 
-		dev->irq_resource[i].end = (unsigned long) irq;
-		dev->irq_resource[i].flags = IORESOURCE_IRQ;  // Also clears _UNSET flag
-	}
-}
-
-static void add_dmaresource(struct pnp_dev *dev, int dma)
-{
-	int i = 0;
-	while (pnp_dma_valid(dev, i) && i < DEVICE_COUNT_DMA) i++;
-	if (i < DEVICE_COUNT_DMA) {
-		dev->dma_resource[i].start =
-		dev->dma_resource[i].end = (unsigned long) dma;
-		dev->dma_resource[i].flags = IORESOURCE_DMA;  // Also clears _UNSET flag
-	}
-}
-
-static void add_ioresource(struct pnp_dev *dev, int io, int len)
-{
-	int i = 0;
-	while (pnp_port_valid(dev, i) && i < DEVICE_COUNT_IO) i++;
-	if (i < DEVICE_COUNT_RESOURCE) {
-		dev->io_resource[i].start = (unsigned long) io;
-		dev->io_resource[i].end = (unsigned long)(io + len - 1);
-		dev->io_resource[i].flags = IORESOURCE_IO;  // Also clears _UNSET flag
-	}
-}
-
-static void add_memresource(struct pnp_dev *dev, int mem, int len)
-{
-	int i = 0;
-	while (pnp_mem_valid(dev, i) && i < DEVICE_COUNT_MEM) i++;
-	if (i < DEVICE_COUNT_RESOURCE) {
-		dev->mem_resource[i].start = (unsigned long) mem;
-		dev->mem_resource[i].end = (unsigned long)(mem + len - 1);
-		dev->mem_resource[i].flags = IORESOURCE_MEM;  // Also clears _UNSET flag
-	}
-}
-
-static unsigned char *node_current_resource_data_to_dev(struct pnp_bios_node *node, struct pnp_dev *dev)
-{
-	unsigned char *p = node->data, *lastp=NULL;
-	int i;
-
-	/*
-	 * First, set resource info to default values
-	 */
-	for (i=0;i<DEVICE_COUNT_IO;i++) {
-		dev->io_resource[i].start = 0;
-		dev->io_resource[i].end = 0;
-		dev->io_resource[i].flags = IORESOURCE_IO|IORESOURCE_UNSET;
-	}
-	for (i=0;i<DEVICE_COUNT_MEM;i++) {
-		dev->mem_resource[i].start = 0;
-		dev->mem_resource[i].end = 0;
-		dev->mem_resource[i].flags = IORESOURCE_MEM|IORESOURCE_UNSET;
-	}
-	for (i=0;i<DEVICE_COUNT_IRQ;i++) {
-		dev->irq_resource[i].start = (unsigned long)-1;
-		dev->irq_resource[i].end = (unsigned long)-1;
-		dev->irq_resource[i].flags = IORESOURCE_IRQ|IORESOURCE_UNSET;
-	}
-	for (i=0;i<DEVICE_COUNT_DMA;i++) {
-		dev->dma_resource[i].start = (unsigned long)-1;
-		dev->dma_resource[i].end = (unsigned long)-1;
-		dev->dma_resource[i].flags = IORESOURCE_DMA|IORESOURCE_UNSET;
-	}
-
-	/*
-	 * Fill in dev resource info
-	 */
-        while ( (char *)p < ((char *)node->data + node->size )) {
-        	if(p==lastp) break;
-
-                if( p[0] & 0x80 ) {// large item
-			switch (p[0] & 0x7f) {
-			case 0x01: // memory
-			{
-				int io = *(short *) &p[4];
-				int len = *(short *) &p[10];
-				add_memresource(dev, io, len);
-				break;
-			}
-			case 0x02: // device name
-			{
-				int len = *(short *) &p[1];
-				memcpy(dev->name, p + 3, len >= 80 ? 79 : len);
-				break;
-			}
-			case 0x05: // 32-bit memory
-			{
-				int io = *(int *) &p[4];
-				int len = *(int *) &p[16];
-				add_memresource(dev, io, len);
-				break;
-			}
-			case 0x06: // fixed location 32-bit memory
-			{
-				int io = *(int *) &p[4];
-				int len = *(int *) &p[8];
-				add_memresource(dev, io, len);
-				break;
-			}
-			} /* switch */
-                        lastp = p+3;
-                        p = p + p[1] + p[2]*256 + 3;
-                        continue;
-                }
-                if ((p[0]>>3) == 0x0f){ // end tag
-			p = p + 2;
-			goto end;
-                        break;
-			}
-                switch (p[0]>>3) {
-                case 0x04: // irq
-                {
-                        int i, mask, irq = -1;
-                        mask= p[1] + p[2]*256;
-                        for (i=0;i<16;i++, mask=mask>>1)
-                                if(mask & 0x01) irq=i;
-			add_irqresource(dev, irq);
-                        break;
-                }
-                case 0x05: // dma
-                {
-                        int i, mask, dma = -1;
-                        mask = p[1];
-                        for (i=0;i<8;i++, mask = mask>>1)
-                                if(mask & 0x01) dma=i;
-			add_dmaresource(dev, dma);
-                        break;
-                }
-                case 0x08: // io
-                {
-			int io= p[2] + p[3] *256;
-			int len = p[7];
-			add_ioresource(dev, io, len);
-                        break;
-                }
-		case 0x09: // fixed location io
-		{
-			int io = p[1] + p[2] * 256;
-			int len = p[3];
-			add_ioresource(dev, io, len);
-			break;
-		}
-                } /* switch */
-                lastp=p+1;
-                p = p + (p[0] & 0x07) + 1;
-
-        } /* while */
-	end:
-	if (pnp_port_valid(dev, 0) == 0 &&
-	    pnp_mem_valid(dev, 0) == 0 &&
-	    pnp_irq_valid(dev, 0) == 0 &&
-	    pnp_dma_valid(dev, 0) == 0)
-		dev->active = 0;
-	else
-		dev->active = 1;
-        return (unsigned char *)p;
-}
-
-
-/* pnp possible resource reading functions */
-
-static void read_lgtag_mem(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
-{
-	struct pnp_mem * mem;
-	mem = pnpbios_kmalloc(sizeof(struct pnp_mem),GFP_KERNEL);
-	if (!mem)
-		return;
-	memset(mem,0,sizeof(struct pnp_mem));
-	mem->min = ((p[3] << 8) | p[2]) << 8;
-	mem->max = ((p[5] << 8) | p[4]) << 8;
-	mem->align = (p[7] << 8) | p[6];
-	mem->size = ((p[9] << 8) | p[8]) << 8;
-	mem->flags = p[1];
-	pnp_add_mem_resource(dev,depnum,mem);
-	return;
-}
-
-static void read_lgtag_mem32(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
-{
-	struct pnp_mem32 * mem;
-	mem = pnpbios_kmalloc(sizeof(struct pnp_mem32),GFP_KERNEL);
-	if (!mem)
-		return;
-	memset(mem,0,sizeof(struct pnp_mem32));
-	memcpy(mem->data, p, 17);
-	pnp_add_mem32_resource(dev,depnum,mem);
-	return;
-}
-
-static void read_lgtag_fmem32(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
-{
-	struct pnp_mem32 * mem;
-	mem = pnpbios_kmalloc(sizeof(struct pnp_mem32),GFP_KERNEL);
-	if (!mem)
-		return;
-	memset(mem,0,sizeof(struct pnp_mem32));
-	memcpy(mem->data, p, 17);
-	pnp_add_mem32_resource(dev,depnum,mem);
-	return;
-}
-
-static void read_smtag_irq(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
-{
-	struct pnp_irq * irq;
-	irq = pnpbios_kmalloc(sizeof(struct pnp_irq),GFP_KERNEL);
-	if (!irq)
-		return;
-	memset(irq,0,sizeof(struct pnp_irq));
-	irq->map = (p[2] << 8) | p[1];
-	if (size > 2)
-		irq->flags = p[3];
-	pnp_add_irq_resource(dev,depnum,irq);
-	return;
-}
-
-static void read_smtag_dma(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
-{
-	struct pnp_dma * dma;
-	dma = pnpbios_kmalloc(sizeof(struct pnp_dma),GFP_KERNEL);
-	if (!dma)
-		return;
-	memset(dma,0,sizeof(struct pnp_dma));
-	dma->map = p[1];
-	dma->flags = p[2];
-	pnp_add_dma_resource(dev,depnum,dma);
-	return;
-}
-
-static void read_smtag_port(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
-{
-	struct pnp_port * port;
-	port = pnpbios_kmalloc(sizeof(struct pnp_port),GFP_KERNEL);
-	if (!port)
-		return;
-	memset(port,0,sizeof(struct pnp_port));
-	port->min = (p[3] << 8) | p[2];
-	port->max = (p[5] << 8) | p[4];
-	port->align = p[6];
-	port->size = p[7];
-	port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0;
-	pnp_add_port_resource(dev,depnum,port);
-	return;
-}
-
-static void read_smtag_fport(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
-{
-	struct pnp_port * port;
-	port = pnpbios_kmalloc(sizeof(struct pnp_port),GFP_KERNEL);
-	if (!port)
-		return;
-	memset(port,0,sizeof(struct pnp_port));
-	port->min = port->max = (p[2] << 8) | p[1];
-	port->size = p[3];
-	port->align = 0;
-	port->flags = PNP_PORT_FLAG_FIXED;
-	pnp_add_port_resource(dev,depnum,port);
-	return;
-}
-
-static unsigned char *node_possible_resource_data_to_dev(unsigned char *p, struct pnp_bios_node *node, struct pnp_dev *dev)
-{
-	int len, depnum, dependent;
-
-	if ((char *)p == NULL)
-		return NULL;
-	if (pnp_build_resource(dev, 0) == NULL)
-		return NULL;
-	depnum = 0; /*this is the first so it should be 0 */
-	dependent = 0;
-        while ( (char *)p < ((char *)node->data + node->size )) {
-
-                if( p[0] & 0x80 ) {// large item
-			len = (p[2] << 8) | p[1];
-			switch (p[0] & 0x7f) {
-			case 0x01: // memory
-			{
-				if (len != 9)
-					goto __skip;
-				read_lgtag_mem(p,len,depnum,dev);
-				break;
-			}
-			case 0x05: // 32-bit memory
-			{
-				if (len != 17)
-					goto __skip;
-				read_lgtag_mem32(p,len,depnum,dev);
-				break;
-			}
-			case 0x06: // fixed location 32-bit memory
-			{
-				if (len != 17)
-					goto __skip;
-				read_lgtag_fmem32(p,len,depnum,dev);
-				break;
-			}
-			} /* switch */
-                        p += len + 3;
-                        continue;
-                }
-		len = p[0] & 0x07;
-                switch ((p[0]>>3) & 0x0f) {
-		case 0x0f:
-		{
-			p = p + 2;
-        		return (unsigned char *)p;
-			break;
-		}
-                case 0x04: // irq
-                {
-			if (len < 2 || len > 3)
-				goto __skip;
-			read_smtag_irq(p,len,depnum,dev);
-			break;
-                }
-                case 0x05: // dma
-                {
-			if (len != 2)
-				goto __skip;
-			read_smtag_dma(p,len,depnum,dev);
-                        break;
-                }
-                case 0x06: // start dep
-                {
-			if (len > 1)
-				goto __skip;
-			dependent = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;
-			if (len > 0)
-				dependent = 0x100 | p[1];
-			pnp_build_resource(dev,dependent);
-			depnum = pnp_get_max_depnum(dev);
-                        break;
-                }
-                case 0x07: // end dep
-                {
-			if (len != 0)
-				goto __skip;
-			depnum = 0;
-                        break;
-                }
-                case 0x08: // io
-                {
-			if (len != 7)
-				goto __skip;
-			read_smtag_port(p,len,depnum,dev);
-                        break;
-                }
-		case 0x09: // fixed location io
-		{
-			if (len != 3)
-				goto __skip;
-			read_smtag_fport(p,len,depnum,dev);
-			break;
-		}
-                } /* switch */
-		__skip:
-                p += len + 1;
-
-        } /* while */
-
-        return NULL;
-}
-
 /* pnp EISA ids */
 
 #define HEX(id,a) hex[((id)>>a) & 15]
@@ -1075,20 +713,26 @@ static void node_id_data_to_dev(unsigned char *p, struct pnp_bios_node *node, st
 		return;
         while ( (char *)p < ((char *)node->data + node->size )) {
 
-                if( p[0] & 0x80 ) {// large item
+                if( p[0] & 0x80 ) {
 			len = (p[2] << 8) | p[1];
-                        p += len + 3;
-                        continue;
-                }
+			if ((p[0] & 0x7f) == 0x02) /* human readable name */
+			{
+				int size = *(short *) &p[1];
+				memcpy(dev->dev.name, p + 3, len >= 80 ? 79 : size);
+				break;
+			}
+			p += len + 3;
+			continue;
+		}
 		len = p[0] & 0x07;
-                switch ((p[0]>>3) & 0x0f) {
-		case 0x0f:
+		switch ((p[0]>>3) & 0x0f) {
+		case 0x0f: /* end tag */
 		{
         		return;
 			break;
 		}
-                case 0x03: // compatible ID
-                {
+		case 0x03: /* compatible ID */
+		{
 			if (len != 4)
 				goto __skip;
 			dev_id =  pnpbios_kmalloc(sizeof (struct pnp_id), GFP_KERNEL);
@@ -1099,177 +743,20 @@ static void node_id_data_to_dev(unsigned char *p, struct pnp_bios_node *node, st
 			memcpy(&dev_id->id, id, 7);
 			pnp_add_id(dev_id, dev);
 			break;
-                }
-                } /* switch */
-		__skip:
-                p += len + 1;
-
-        } /* while */
-}
-
-/* pnp resource writing functions */
-
-static void write_lgtag_mem(unsigned char *p, int size, struct pnp_mem *mem)
-{
-	if (!mem)
-		return;
-	p[2] = (mem->min >> 8) & 0xff;
-	p[3] = ((mem->min >> 8) >> 8) & 0xff;
-	p[4] = (mem->max >> 8) & 0xff;
-	p[5] = ((mem->max >> 8) >> 8) & 0xff;
-	p[6] = mem->align & 0xff;
-	p[7] = (mem->align >> 8) & 0xff;
-	p[8] = (mem->size >> 8) & 0xff;
-	p[9] = ((mem->size >> 8) >> 8) & 0xff;
-	p[1] = mem->flags & 0xff;
-	return;
-}
-
-static void write_smtag_irq(unsigned char *p, int size, struct pnp_irq *irq)
-{
-	if (!irq)
-		return;
-	p[1] = irq->map & 0xff;
-	p[2] = (irq->map >> 8) & 0xff;
-	if (size > 2)
-		p[3] = irq->flags & 0xff;
-	return;
-}
-
-static void write_smtag_dma(unsigned char *p, int size, struct pnp_dma *dma)
-{
-	if (!dma)
-		return;
-	p[1] = dma->map & 0xff;
-	p[2] = dma->flags & 0xff;
-	return;
-}
-
-static void write_smtag_port(unsigned char *p, int size, struct pnp_port *port)
-{
-	if (!port)
-		return;
-	p[2] = port->min & 0xff;
-	p[3] = (port->min >> 8) & 0xff;
-	p[4] = port->max & 0xff;
-	p[5] = (port->max >> 8) & 0xff;
-	p[6] = port->align & 0xff;
-	p[7] = port->size & 0xff;
-	p[1] = port->flags & 0xff;
-	return;
-}
-
-static void write_smtag_fport(unsigned char *p, int size, struct pnp_port *port)
-{
-	if (!port)
-		return;
-	p[1] = port->min & 0xff;
-	p[2] = (port->min >> 8) & 0xff;
-	p[3] = port->size & 0xff;
-	return;
-}
-
-static int node_set_resources(struct pnp_bios_node *node, struct pnp_cfg *config)
-{
-	int error = 0;
-	unsigned char *p = (char *)node->data, *lastp = NULL;
-	int len, port = 0, irq = 0, dma = 0, mem = 0;
-
-	if (!node)
-		return -EINVAL;
-	if ((char *)p == NULL)
-		return -EINVAL;
-        while ( (char *)p < ((char *)node->data + node->size )) {
-
-                if( p[0] & 0x80 ) {// large item
-			len = (p[2] << 8) | p[1];
-			switch (p[0] & 0x7f) {
-			case 0x01: // memory
-			{
-				if (len != 9)
-					goto __skip;
-				write_lgtag_mem(p,len,config->mem[mem]);
-				mem++;
-				break;
-			}
-			case 0x05: // 32-bit memory
-			{
-				if (len != 17)
-					goto __skip;
-				/* FIXME */
-				break;
-			}
-			case 0x06: // fixed location 32-bit memory
-			{
-				if (len != 17)
-					goto __skip;
-				/* FIXME */
-				break;
-			}
-			} /* switch */
-                        lastp = p+3;
-                        p = p + p[1] + p[2]*256 + 3;
-                        continue;
-                }
-		len = p[0] & 0x07;
-                switch ((p[0]>>3) & 0x0f) {
-		case 0x0f:
-		{
-        		goto done;
-			break;
 		}
-                case 0x04: // irq
-                {
-			if (len < 2 || len > 3)
-				goto __skip;
-			write_smtag_irq(p,len,config->irq[irq]);
-			irq++;
-			break;
-                }
-                case 0x05: // dma
-                {
-			if (len != 2)
-				goto __skip;
-			write_smtag_dma(p,len,config->dma[dma]);
-			dma++;
-                        break;
-                }
-                case 0x08: // io
-                {
-			if (len != 7)
-				goto __skip;
-			write_smtag_port(p,len,config->port[port]);
-			port++;
-                        break;
-                }
-		case 0x09: // fixed location io
-		{
-			if (len != 3)
-				goto __skip;
-			write_smtag_fport(p,len,config->port[port]);
-			port++;
-			break;
 		}
-                } /* switch */
 		__skip:
-                p += len + 1;
-
-        } /* while */
+		p += len + 1;
 
-	/* we never got an end tag so this data is corrupt or invalid */
-	return -EINVAL;
-
-	done:
-	error = pnp_bios_set_dev_node(node->handle, (char)0, node);
-        return error;
+	}
 }
 
-static int pnpbios_get_resources(struct pnp_dev *dev)
+static int pnpbios_get_resources(struct pnp_dev * dev, struct pnp_resource_table * res)
 {
 	struct pnp_dev_node_info node_info;
 	u8 nodenum = dev->number;
 	struct pnp_bios_node * node;
-		
+
 	/* just in case */
 	if(!pnpbios_is_dynamic(dev))
 		return -EPERM;
@@ -1278,18 +765,22 @@ static int pnpbios_get_resources(struct pnp_dev *dev)
 	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node)
 		return -1;
-	if (pnp_bios_get_dev_node(&nodenum, (char )0, node))
+	if (pnp_bios_get_dev_node(&nodenum, (char )0, node)) {
+		kfree(node);
 		return -ENODEV;
-	node_current_resource_data_to_dev(node,dev);
+	}
+	pnp_parse_current_resources((char *)node->data,(char *)node->data + node->size,res);
+	dev->active = pnp_is_active(dev);
 	kfree(node);
 	return 0;
 }
 
-static int pnpbios_set_resources(struct pnp_dev *dev, struct pnp_cfg *config)
+static int pnpbios_set_resources(struct pnp_dev * dev, struct pnp_resource_table * res)
 {
 	struct pnp_dev_node_info node_info;
 	u8 nodenum = dev->number;
 	struct pnp_bios_node * node;
+	int ret;
 
 	/* just in case */
 	if (!pnpbios_is_dynamic(dev))
@@ -1301,83 +792,42 @@ static int pnpbios_set_resources(struct pnp_dev *dev, struct pnp_cfg *config)
 		return -1;
 	if (pnp_bios_get_dev_node(&nodenum, (char )1, node))
 		return -ENODEV;
-	if(node_set_resources(node, config)<0){
+	if(!pnp_write_resources((char *)node->data,(char *)node->data + node->size,res)){
+		kfree(node);
 		return -1;
 	}
+	ret = pnp_bios_set_dev_node(node->handle, (char)0, node);
 	kfree(node);
-	return 0;
+	if (ret > 0)
+		ret = -1;
+	return ret;
 }
 
 static int pnpbios_disable_resources(struct pnp_dev *dev)
 {
-	struct pnp_cfg * config = kmalloc(sizeof(struct pnp_cfg), GFP_KERNEL);
-	/* first we need to set everything to a disabled value */
-	struct pnp_port	port = {
-	.max	= 0,
-	.min	= 0,
-	.align	= 0,
-	.size	= 0,
-	.flags	= 0,
-	.pad	= 0,
-	};
-	struct pnp_mem	mem = {
-	.max	= 0,
-	.min	= 0,
-	.align	= 0,
-	.size	= 0,
-	.flags	= 0,
-	.pad	= 0,
-	};
-	struct pnp_dma	dma = {
-	.map	= 0,
-	.flags	= 0,
-	};
-	struct pnp_irq	irq = {
-	.map	= 0,
-	.flags	= 0,
-	.pad	= 0,
-	};
-	int i;
 	struct pnp_dev_node_info node_info;
-	u8 nodenum = dev->number;
 	struct pnp_bios_node * node;
-	if (!config)
-		return -1;
+	int ret;
+	
 	/* just in case */
 	if(dev->flags & PNPBIOS_NO_DISABLE || !pnpbios_is_dynamic(dev))
 		return -EPERM;
-	memset(config, 0, sizeof(struct pnp_cfg));
 	if (!dev || !dev->active)
 		return -EINVAL;
-	for (i=0; i < 8; i++)
-		config->port[i] = &port;
-	for (i=0; i < 4; i++)
-		config->mem[i] = &mem;
-	for (i=0; i < 2; i++)
-		config->irq[i] = &irq;
-	for (i=0; i < 2; i++)
-		config->dma[i] = &dma;
-	dev->active = 0;
-
 	if (pnp_bios_dev_node_info(&node_info) != 0)
 		return -ENODEV;
+	/* the value of this will be zero */
 	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node)
-		return -1;
-	if (pnp_bios_get_dev_node(&nodenum, (char )1, node))
-		goto failed;
-	if(node_set_resources(node, config)<0)
-		goto failed;
-	kfree(config);
-	kfree(node);
-	return 0;
- failed:
+		return -ENOMEM;
+	ret = pnp_bios_set_dev_node(dev->number, (char)0, node);
+	dev->active = 0;
 	kfree(node);
-	kfree(config);
-	return -1;
+	if (ret > 0)
+		ret = -1;
+	return ret;
 }
 
-
 /* PnP Layer support */
 
 static struct pnp_protocol pnpbios_protocol = {
@@ -1387,15 +837,47 @@ static struct pnp_protocol pnpbios_protocol = {
 	.disable = pnpbios_disable_resources,
 };
 
-static inline int insert_device(struct pnp_dev *dev)
+static int insert_device(struct pnp_dev *dev, struct pnp_bios_node * node)
 {
 	struct list_head * pos;
+	unsigned char * p;
 	struct pnp_dev * pnp_dev;
+	struct pnp_id *dev_id;
+	char id[8];
+
+	/* check if the device is already added */
+	dev->number = node->handle;
 	list_for_each (pos, &pnpbios_protocol.devices){
 		pnp_dev = list_entry(pos, struct pnp_dev, protocol_list);
 		if (dev->number == pnp_dev->number)
 			return -1;
 	}
+
+	/* set the initial values for the PnP device */
+	dev_id = pnpbios_kmalloc(sizeof(struct pnp_id), GFP_KERNEL);
+	if (!dev_id)
+		return -1;
+	pnpid32_to_pnpid(node->eisa_id,id);
+	memcpy(dev_id->id,id,7);
+	pnp_add_id(dev_id, dev);
+	p = pnp_parse_current_resources((char *)node->data,
+		(char *)node->data + node->size,&dev->res);
+	p = pnp_parse_possible_resources((char *)p,
+		(char *)node->data + node->size,dev);
+	node_id_data_to_dev(p,node,dev);
+	dev->active = pnp_is_active(dev);
+	dev->flags = node->flags;
+	if (!(dev->flags & PNPBIOS_NO_CONFIG))
+		dev->capabilities |= PNP_CONFIGURABLE;
+	if (!(dev->flags & PNPBIOS_NO_DISABLE))
+		dev->capabilities |= PNP_DISABLE;
+	dev->capabilities |= PNP_READ;
+	if (pnpbios_is_dynamic(dev))
+		dev->capabilities |= PNP_WRITE;
+	if (dev->flags & PNPBIOS_REMOVABLE)
+		dev->capabilities |= PNP_REMOVABLE;
+	dev->protocol = &pnpbios_protocol;
+
 	pnp_add_device(dev);
 	return 0;
 }
@@ -1403,14 +885,11 @@ static inline int insert_device(struct pnp_dev *dev)
 static void __init build_devlist(void)
 {
 	u8 nodenum;
-	char id[8];
-	unsigned char *pos;
 	unsigned int nodes_got = 0;
 	unsigned int devs = 0;
 	struct pnp_bios_node *node;
 	struct pnp_dev_node_info node_info;
 	struct pnp_dev *dev;
-	struct pnp_id *dev_id;
 
 	if (!pnp_bios_present())
 		return;
@@ -1424,51 +903,15 @@ static void __init build_devlist(void)
 
 	for(nodenum=0; nodenum<0xff; ) {
 		u8 thisnodenum = nodenum;
-		/* We build the list from the "boot" config because
-		 * we know that the resources couldn't have changed
-		 * at this stage.  Furthermore some buggy PnP BIOSes
-		 * will crash if we request the "current" config
-		 * from devices that are can only be static such as
-		 * those controlled by the "system" driver.
-		 */
-		if (pnp_bios_get_dev_node(&nodenum, (char )1, node))
+		if (pnp_bios_get_dev_node(&nodenum, (char )0, node))
 			break;
 		nodes_got++;
 		dev =  pnpbios_kmalloc(sizeof (struct pnp_dev), GFP_KERNEL);
 		if (!dev)
 			break;
-		memset(dev,0,sizeof(struct pnp_dev));
-		dev_id =  pnpbios_kmalloc(sizeof (struct pnp_id), GFP_KERNEL);
-		if (!dev_id) {
-			kfree(dev);
-			break;
-		}
-		memset(dev_id,0,sizeof(struct pnp_id));
-		dev->number = thisnodenum;
-		strcpy(dev->name,"Unknown Device");
-		pnpid32_to_pnpid(node->eisa_id,id);
-		memcpy(dev_id->id,id,7);
-		pnp_add_id(dev_id, dev);
-		pos = node_current_resource_data_to_dev(node,dev);
-		pos = node_possible_resource_data_to_dev(pos,node,dev);
-		node_id_data_to_dev(pos,node,dev);
-		dev->flags = node->flags;
-		if (!(dev->flags & PNPBIOS_NO_CONFIG))
-			dev->capabilities |= PNP_CONFIGURABLE;
-		if (!(dev->flags & PNPBIOS_NO_DISABLE))
-			dev->capabilities |= PNP_DISABLE;
-		dev->capabilities |= PNP_READ;
-		if (pnpbios_is_dynamic(dev))
-			dev->capabilities |= PNP_WRITE;
-		if (dev->flags & PNPBIOS_REMOVABLE)
-			dev->capabilities |= PNP_REMOVABLE;
-
-		dev->protocol = &pnpbios_protocol;
-
-		if(insert_device(dev)<0) {
-			kfree(dev_id);
+		if(insert_device(dev,node)<0)
 			kfree(dev);
-		} else
+		else
 			devs++;
 		if (nodenum <= thisnodenum) {
 			printk(KERN_ERR "PnPBIOS: build_devlist: Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", (unsigned int)nodenum, (unsigned int)thisnodenum);
@@ -1563,6 +1006,8 @@ int __init pnpbios_init(void)
 		pnp_bios_callpoint.segment = PNP_CS16;
 		pnp_bios_hdr = check;
 
+		set_base(bad_bios_desc, __va((unsigned long)0x40 << 4));
+		_set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4));
 		for(i=0; i < NR_CPUS; i++)
 		{
 			Q2_SET_SEL(i, PNP_CS32, &pnp_bios_callfunc, 64 * 1024);
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 455b2dcf45728085a6d2a7f81efe6222b29d420c..4ea00c18615324a4f2424d4031908bc920d03693 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -29,7 +29,7 @@
 static void quirk_awe32_resources(struct pnp_dev *dev)
 {
 	struct pnp_port *port, *port2, *port3;
-	struct pnp_resources *res = dev->res->dep;
+	struct pnp_resources *res = dev->possible->dep;
 
 	/*
 	 * Unfortunately the isapnp_add_port_resource is too tightly bound
@@ -57,7 +57,7 @@ static void quirk_awe32_resources(struct pnp_dev *dev)
 
 static void quirk_cmi8330_resources(struct pnp_dev *dev)
 {
-	struct pnp_resources *res = dev->res->dep;
+	struct pnp_resources *res = dev->possible->dep;
 
 	for ( ; res ; res = res->dep ) {
 
@@ -77,7 +77,7 @@ static void quirk_cmi8330_resources(struct pnp_dev *dev)
 static void quirk_sb16audio_resources(struct pnp_dev *dev)
 {
 	struct pnp_port *port;
-	struct pnp_resources *res = dev->res->dep;
+	struct pnp_resources *res = dev->possible->dep;
 	int    changed = 0;
 
 	/*
@@ -115,7 +115,7 @@ static void quirk_opl3sax_resources(struct pnp_dev *dev)
 	 */
 	struct pnp_resources *res;
 	int max;
-	res = dev->res;
+	res = dev->possible;
 	max = 0;
 	for (res = res->dep; res; res = res->dep) {
 		if (res->dma->map > max)
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index 6d4b3d6bc18e872851064362e912f93300d7a7a2..1b0ac165450c492eea9ecdf23f3449b0a83a4ff8 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -1,8 +1,8 @@
 /*
- * resource.c - contains resource management algorithms
+ * resource.c - Contains functions for registering and analyzing resource information
  *
  * based on isapnp.c resource management (c) Jaroslav Kysela <perex@suse.cz>
- * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
+ * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
  *
  */
 
@@ -16,15 +16,8 @@
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <linux/ioport.h>
-#include <linux/config.h>
 #include <linux/init.h>
 
-#ifdef CONFIG_PNP_DEBUG
-	#define DEBUG
-#else
-	#undef DEBUG
-#endif
-
 #include <linux/pnp.h>
 #include "base.h"
 
@@ -36,7 +29,9 @@ int pnp_reserve_io[16] = { [0 ... 15] = -1 };	/* reserve (don't use) some I/O re
 int pnp_reserve_mem[16] = { [0 ... 15] = -1 };	/* reserve (don't use) some memory region */
 
 
-/* resource information adding functions */
+/*
+ * possible resource registration
+ */
 
 struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent)
 {
@@ -45,8 +40,8 @@ struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent)
 	res = pnp_alloc(sizeof(struct pnp_resources));
 	if (!res)
 		return NULL;
-	ptr = dev->res;
-	if (ptr && ptr->dependent && dependent) { /* add to another list */
+	ptr = dev->possible;
+	if (ptr) { /* add to another list */
 		ptra = ptr->dep;
 		while (ptra && ptra->dep)
 			ptra = ptra->dep;
@@ -54,24 +49,14 @@ struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent)
 			ptr->dep = res;
 		else
 			ptra->dep = res;
-	} else {
-		if (!ptr){
-			dev->res = res;
-		}
-		else{
-			kfree(res);
-			return NULL;
-		}
-	}
+	} else
+		dev->possible = res;
 	if (dependent) {
 		res->priority = dependent & 0xff;
 		if (res->priority > PNP_RES_PRIORITY_FUNCTIONAL)
 			res->priority = PNP_RES_PRIORITY_INVALID;
-		res->dependent = 1;
-	} else {
+	} else
 		res->priority = PNP_RES_PRIORITY_PREFERRED;
-		res->dependent = 1;
-	}
 	return res;
 }
 
@@ -81,7 +66,7 @@ struct pnp_resources * pnp_find_resources(struct pnp_dev *dev, int depnum)
 	struct pnp_resources *res;
 	if (!dev)
 		return NULL;
-	res = dev->res;
+	res = dev->possible;
 	if (!res)
 		return NULL;
 	for (i = 0; i < depnum; i++)
@@ -100,7 +85,7 @@ int pnp_get_max_depnum(struct pnp_dev *dev)
 	struct pnp_resources *res;
 	if (!dev)
 		return -EINVAL;
-	res = dev->res;
+	res = dev->possible;
 	if (!res)
 		return -EINVAL;
 	while (res->dep){
@@ -110,10 +95,6 @@ int pnp_get_max_depnum(struct pnp_dev *dev)
 	return num;
 }
 
-/*
- *  Add IRQ resource to resources list.
- */
-
 int pnp_add_irq_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data)
 {
 	int i;
@@ -139,10 +120,6 @@ int pnp_add_irq_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data)
 	return 0;
 }
 
-/*
- *  Add DMA resource to resources list.
- */
-
 int pnp_add_dma_resource(struct pnp_dev *dev, int depnum, struct pnp_dma *data)
 {
 	struct pnp_resources *res;
@@ -162,20 +139,15 @@ int pnp_add_dma_resource(struct pnp_dev *dev, int depnum, struct pnp_dma *data)
 	return 0;
 }
 
-/*
- *  Add port resource to resources list.
- */
-
 int pnp_add_port_resource(struct pnp_dev *dev, int depnum, struct pnp_port *data)
 {
 	struct pnp_resources *res;
 	struct pnp_port *ptr;
 	res = pnp_find_resources(dev,depnum);
-	if (res==NULL)
+	if (!res)
 		return -EINVAL;
 	if (!data)
 		return -EINVAL;
-	data->res = res;
 	ptr = res->port;
 	while (ptr && ptr->next)
 		ptr = ptr->next;
@@ -186,10 +158,6 @@ int pnp_add_port_resource(struct pnp_dev *dev, int depnum, struct pnp_port *data
 	return 0;
 }
 
-/*
- *  Add memory resource to resources list.
- */
-
 int pnp_add_mem_resource(struct pnp_dev *dev, int depnum, struct pnp_mem *data)
 {
 	struct pnp_resources *res;
@@ -209,32 +177,6 @@ int pnp_add_mem_resource(struct pnp_dev *dev, int depnum, struct pnp_mem *data)
 	return 0;
 }
 
-/*
- *  Add 32-bit memory resource to resources list.
- */
-
-int pnp_add_mem32_resource(struct pnp_dev *dev, int depnum, struct pnp_mem32 *data)
-{
-	struct pnp_resources *res;
-	struct pnp_mem32 *ptr;
-	res = pnp_find_resources(dev,depnum);
-	if (!res)
-		return -EINVAL;
-	if (!data)
-		return -EINVAL;
-	ptr = res->mem32;
-	while (ptr && ptr->next)
-		ptr = ptr->next;
-	if (ptr)
-		ptr->next = data;
-	else
-		res->mem32 = data;
-	return 0;
-}
-
-
-/* resource removing functions */
-
 static void pnp_free_port(struct pnp_port *port)
 {
 	struct pnp_port *next;
@@ -279,17 +221,6 @@ static void pnp_free_mem(struct pnp_mem *mem)
 	}
 }
 
-static void pnp_free_mem32(struct pnp_mem32 *mem32)
-{
-	struct pnp_mem32 *next;
-
-	while (mem32) {
-		next = mem32->next;
-		kfree(mem32);
-		mem32 = next;
-	}
-}
-
 void pnp_free_resources(struct pnp_resources *resources)
 {
 	struct pnp_resources *next;
@@ -300,597 +231,449 @@ void pnp_free_resources(struct pnp_resources *resources)
 		pnp_free_irq(resources->irq);
 		pnp_free_dma(resources->dma);
 		pnp_free_mem(resources->mem);
-		pnp_free_mem32(resources->mem32);
 		kfree(resources);
 		resources = next;
 	}
 }
 
 
-/* resource validity checking functions */
+/*
+ * resource validity checking
+ */
+
+#define length(start, end) (*(end) - *(start) + 1)
+
+/* ranged_conflict - used to determine if two resource ranges conflict
+ * condition 1: check if the start of a is within b
+ * condition 2: check if the end of a is within b
+ * condition 3: check if b is engulfed by a */
+
+#define ranged_conflict(starta, enda, startb, endb) \
+((*(starta) >= *(startb) && *(starta) <= *(endb)) || \
+ (*(enda) >= *(startb) && *(enda) <= *(endb)) || \
+ (*(starta) < *(startb) && *(enda) > *(endb)))
 
-static int pnp_check_port(int port, int size, int idx, struct pnp_cfg *config)
+struct pnp_dev * pnp_check_port_conflicts(struct pnp_dev * dev, int idx, int mode)
 {
-	int i, tmp, rport, rsize;
-	struct pnp_dev *dev;
+	int tmp;
+	unsigned long *port, *end, *tport, *tend;
+	struct pnp_dev *tdev;
+	port = &dev->res.port_resource[idx].start;
+	end = &dev->res.port_resource[idx].end;
 
-	if (check_region(port, size))
-		return 1;
-	for (i = 0; i < 8; i++) {
-		rport = pnp_reserve_io[i << 1];
-		rsize = pnp_reserve_io[(i << 1) + 1];
-		if (port >= rport && port < rport + rsize)
-			return 1;
-		if (port + size > rport && port + size < (rport + rsize) - 1)
-			return 1;
-	}
-
-	pnp_for_each_dev(dev) {
-		if (dev->active) {
-			for (tmp = 0; tmp < 8; tmp++) {
-				if (pnp_port_valid(dev, tmp)) {
-					rport = pnp_port_start(dev, tmp);
-					rsize = pnp_port_len(dev, tmp);
-					if (port >= rport && port < rport + rsize)
-						return 1;
-					if (port + size > rport && port + size < (rport + rsize) - 1)
-						return 1;
-				}
+	/* if the resource doesn't exist, don't complain about it */
+	if (dev->res.port_resource[idx].start == 0)
+		return NULL;
+
+	/* check for cold conflicts */
+	pnp_for_each_dev(tdev) {
+		/* Is the device configurable? */
+		if (tdev == dev || (mode ? !dev->active : dev->active))
+			continue;
+		for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {
+			if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) {
+				tport = &tdev->res.port_resource[tmp].start;
+				tend = &tdev->res.port_resource[tmp].end;
+				if (ranged_conflict(port,end,tport,tend))
+					return tdev;
 			}
 		}
 	}
-	for (tmp = 0; tmp < 8 && tmp != idx; tmp++) {
-		if (pnp_port_valid(dev, tmp) &&
-		    pnp_flags_valid(&config->request.io_resource[tmp])) {
-			rport = config->request.io_resource[tmp].start;
-			rsize = (config->request.io_resource[tmp].end - rport) + 1;
-			if (port >= rport && port < rport + rsize)
-				return 1;
-			if (port + size > rport && port + size < (rport + rsize) - 1)
-				return 1;
+	return NULL;
+}
+
+int pnp_check_port(struct pnp_dev * dev, int idx)
+{
+	int tmp;
+	unsigned long *port, *end, *tport, *tend;
+	port = &dev->res.port_resource[idx].start;
+	end = &dev->res.port_resource[idx].end;
+
+	/* if the resource doesn't exist, don't complain about it */
+	if (dev->res.port_resource[idx].start == 0)
+		return 0;
+
+	/* check if the resource is already in use, skip if the device is active because it itself may be in use */
+	if(!dev->active) {
+		if (check_region(*port, length(port,end)))
+			return CONFLICT_TYPE_IN_USE;
+	}
+
+	/* check if the resource is reserved */
+	for (tmp = 0; tmp < 8; tmp++) {
+		int rport = pnp_reserve_io[tmp << 1];
+		int rend = pnp_reserve_io[(tmp << 1) + 1] + rport - 1;
+		if (ranged_conflict(port,end,&rport,&rend))
+			return CONFLICT_TYPE_RESERVED;
+	}
+
+	/* check for internal conflicts */
+	for (tmp = 0; tmp < PNP_MAX_PORT && tmp != idx; tmp++) {
+		if (dev->res.port_resource[tmp].flags & IORESOURCE_IO) {
+			tport = &dev->res.port_resource[tmp].start;
+			tend = &dev->res.port_resource[tmp].end;
+			if (ranged_conflict(port,end,tport,tend))
+				return CONFLICT_TYPE_INTERNAL;
 		}
 	}
+
+	/* check for warm conflicts */
+	if (pnp_check_port_conflicts(dev, idx, SEARCH_WARM))
+		return CONFLICT_TYPE_PNP_WARM;
+
 	return 0;
 }
 
-static int pnp_check_mem(unsigned int addr, unsigned int size, int idx, struct pnp_cfg *config)
+struct pnp_dev * pnp_check_mem_conflicts(struct pnp_dev * dev, int idx, int mode)
 {
-	int i, tmp;
-	unsigned int raddr, rsize;
-	struct pnp_dev *dev;
-
-	for (i = 0; i < 8; i++) {
-		raddr = (unsigned int)pnp_reserve_mem[i << 1];
-		rsize = (unsigned int)pnp_reserve_mem[(i << 1) + 1];
-		if (addr >= raddr && addr < raddr + rsize)
-			return 1;
-		if (addr + size > raddr && addr + size < (raddr + rsize) - 1)
-			return 1;
-		if (__check_region(&iomem_resource, addr, size))
-			return 1;
-	}
-	pnp_for_each_dev(dev) {
-		if (dev->active) {
-			for (tmp = 0; tmp < 4; tmp++) {
-				if (pnp_mem_valid(dev, tmp)) {
-					raddr = pnp_mem_start(dev, tmp);
-					rsize = pnp_mem_len(dev, tmp);
-					if (addr >= raddr && addr < raddr + rsize)
-						return 1;
-					if (addr + size > raddr && addr + size < (raddr + rsize) - 1)
-						return 1;
-				}
+	int tmp;
+	unsigned long *addr, *end, *taddr, *tend;
+	struct pnp_dev *tdev;
+	addr = &dev->res.mem_resource[idx].start;
+	end = &dev->res.mem_resource[idx].end;
+
+	/* if the resource doesn't exist, don't complain about it */
+	if (dev->res.mem_resource[idx].start == 0)
+		return NULL;
+
+	/* check for cold conflicts */
+	pnp_for_each_dev(tdev) {
+		/* Is the device configurable? */
+		if (tdev == dev || (mode ? !dev->active : dev->active))
+			continue;
+		for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) {
+			if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) {
+				taddr = &tdev->res.mem_resource[tmp].start;
+				tend = &tdev->res.mem_resource[tmp].end;
+				if (ranged_conflict(addr,end,taddr,tend))
+					return tdev;
 			}
 		}
 	}
-	for (tmp = 0; tmp < 4 && tmp != idx; tmp++) {
-		if (pnp_mem_valid(dev, tmp) &&
-		    pnp_flags_valid(&config->request.mem_resource[tmp])) {
-			raddr = config->request.mem_resource[tmp].start;
-			rsize = (config->request.mem_resource[tmp].end - raddr) + 1;
-			if (addr >= raddr && addr < raddr + rsize)
-				return 1;
-			if (addr + size > raddr && addr + size < (raddr + rsize) - 1)
-				return 1;
+	return NULL;
+}
+
+int pnp_check_mem(struct pnp_dev * dev, int idx)
+{
+	int tmp;
+	unsigned long *addr, *end, *taddr, *tend;
+	addr = &dev->res.mem_resource[idx].start;
+	end = &dev->res.mem_resource[idx].end;
+
+	/* if the resource doesn't exist, don't complain about it */
+	if (dev->res.mem_resource[idx].start == 0)
+		return 0;
+
+	/* check if the resource is already in use, skip if the device is active because it itself may be in use */
+	if(!dev->active) {
+		if (__check_region(&iomem_resource, *addr, length(addr,end)))
+			return CONFLICT_TYPE_IN_USE;
+	}
+
+	/* check if the resource is reserved */
+	for (tmp = 0; tmp < 8; tmp++) {
+		int raddr = pnp_reserve_mem[tmp << 1];
+		int rend = pnp_reserve_mem[(tmp << 1) + 1] + raddr - 1;
+		if (ranged_conflict(addr,end,&raddr,&rend))
+			return CONFLICT_TYPE_RESERVED;
+	}
+
+	/* check for internal conflicts */
+	for (tmp = 0; tmp < PNP_MAX_MEM && tmp != idx; tmp++) {
+		if (dev->res.mem_resource[tmp].flags & IORESOURCE_MEM) {
+			taddr = &dev->res.mem_resource[tmp].start;
+			tend = &dev->res.mem_resource[tmp].end;
+			if (ranged_conflict(addr,end,taddr,tend))
+				return CONFLICT_TYPE_INTERNAL;
 		}
 	}
+
+	/* check for warm conflicts */
+	if (pnp_check_mem_conflicts(dev, idx, SEARCH_WARM))
+		return CONFLICT_TYPE_PNP_WARM;
+
 	return 0;
 }
 
+struct pnp_dev * pnp_check_irq_conflicts(struct pnp_dev * dev, int idx, int mode)
+{
+	int tmp;
+	struct pnp_dev * tdev;
+	unsigned long * irq = &dev->res.irq_resource[idx].start;
+
+	/* if the resource doesn't exist, don't complain about it */
+	if (dev->res.irq_resource[idx].start == -1)
+		return NULL;
+
+	/* check for cold conflicts */
+	pnp_for_each_dev(tdev) {
+		/* Is the device configurable? */
+		if (tdev == dev || (mode ? !dev->active : dev->active))
+			continue;
+		for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) {
+			if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) {
+				if ((tdev->res.irq_resource[tmp].start == *irq))
+					return tdev;
+			}
+		}
+	}
+	return NULL;
+}
+
 static void pnp_test_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 }
 
-static int pnp_check_interrupt(int irq, struct pnp_cfg *config)
+int pnp_check_irq(struct pnp_dev * dev, int idx)
 {
-	int i;
-#ifdef CONFIG_PCI
-	struct pci_dev *pci;
-#endif
-	struct pnp_dev *dev;
-	if (!config)
-		return 1;
+	int tmp;
+	unsigned long * irq = &dev->res.irq_resource[idx].start;
 
-	if (irq < 0 || irq > 15)
-		return 1;
-	for (i = 0; i < 16; i++) {
-		if (pnp_reserve_irq[i] == irq)
-			return 1;
-	}
-	pnp_for_each_dev(dev) {
-		if (dev->active) {
-			if ((pnp_irq_valid(dev, 0) && dev->irq_resource[0].start == irq) ||
-			    (pnp_irq_valid(dev, 1) && dev->irq_resource[1].start == irq))
-				return 1;
+	/* if the resource doesn't exist, don't complain about it */
+	if (dev->res.irq_resource[idx].start == -1)
+		return 0;
+
+	/* check if the resource is valid */
+	if (*irq < 0 || *irq > 15)
+		return CONFLICT_TYPE_INVALID;
+
+	/* check if the resource is reserved */
+	for (tmp = 0; tmp < 16; tmp++) {
+		if (pnp_reserve_irq[tmp] == *irq)
+			return CONFLICT_TYPE_RESERVED;
+	}
+
+	/* check for internal conflicts */
+	for (tmp = 0; tmp < PNP_MAX_IRQ && tmp != idx; tmp++) {
+		if (dev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) {
+			if (dev->res.irq_resource[tmp].start == *irq)
+				return CONFLICT_TYPE_INTERNAL;
 		}
 	}
-	if (pnp_flags_valid(&config->request.irq_resource[0]) &&
-	    pnp_flags_valid(&config->request.irq_resource[1]) &&
-	    (config->request.irq_resource[0].start == irq))
-		return 1;
+
 #ifdef CONFIG_PCI
+	/* check if the resource is being used by a pci device */
 	if (!pnp_skip_pci_scan) {
+		struct pci_dev * pci;
 		pci_for_each_dev(pci) {
-			if (pci->irq == irq)
-				return 1;
+			if (pci->irq == *irq)
+				return CONFLICT_TYPE_PCI;
 		}
 	}
 #endif
-	if (request_irq(irq, pnp_test_handler, SA_INTERRUPT, "pnp", NULL))
-		return 1;
-	free_irq(irq, NULL);
-	return 0;
-}
-
-static int pnp_check_dma(int dma, struct pnp_cfg *config)
-{
-	int i, mindma = 1;
-	struct pnp_dev *dev;
-	if (!config)
-		return 1;
 
-	if (pnp_allow_dma0 == 1)
-		mindma = 0;
-	if (dma < mindma || dma == 4 || dma > 7)
-		return 1;
-	for (i = 0; i < 8; i++) {
-		if (pnp_reserve_dma[i] == dma)
-			return 1;
-	}
-	pnp_for_each_dev(dev) {
-		if (dev->active) {
-			if ((pnp_dma_valid(dev, 0) && pnp_dma(dev, 0) == dma) ||
-			    (pnp_dma_valid(dev, 1) && pnp_dma(dev, 1) == dma))
-				return 1;
-		}
+	/* check if the resource is already in use, skip if the device is active because it itself may be in use */
+	if(!dev->active) {
+		if (request_irq(*irq, pnp_test_handler, SA_INTERRUPT, "pnp", NULL))
+			return CONFLICT_TYPE_IN_USE;
+		free_irq(*irq, NULL);
 	}
-	if (pnp_flags_valid(&config->request.dma_resource[0]) &&
-	    pnp_flags_valid(&config->request.dma_resource[1]) &&
-	    (config->request.dma_resource[0].start == dma))
-		return 1;
-	if (request_dma(dma, "pnp"))
-		return 1;
-	free_dma(dma);
-	return 0;
-}
 
+	/* check for warm conflicts */
+	if (pnp_check_irq_conflicts(dev, idx, SEARCH_WARM))
+		return CONFLICT_TYPE_PNP_WARM;
 
-/* config generation functions */
-static int pnp_generate_port(struct pnp_cfg *config, int num)
-{
-	struct pnp_port *port;
-	unsigned long *value1, *value2, *value3;
-	if (!config || num < 0 || num > 7)
-		return -EINVAL;
-	port = config->port[num];
-	if (!port)
-		return 0;
-	value1 = &config->request.io_resource[num].start;
-	value2 = &config->request.io_resource[num].end;
-	value3 = &config->request.io_resource[num].flags;
-	*value1 = port->min;
-	*value2 = *value1 + port->size - 1;
-	*value3 = port->flags | IORESOURCE_IO;
-	while (pnp_check_port(*value1, port->size, num, config)) {
-		*value1 += port->align;
-		*value2 = *value1 + port->size - 1;
-		if (*value1 > port->max || !port->align)
-			return -ENOENT;
-	}
 	return 0;
 }
 
-static int pnp_generate_mem(struct pnp_cfg *config, int num)
-{
-	struct pnp_mem *mem;
-	unsigned long *value1, *value2, *value3;
-	if (!config || num < 0 || num > 3)
-		return -EINVAL;
-	mem = config->mem[num];
-	if (!mem)
-		return 0;
-	value1 = &config->request.mem_resource[num].start;
-	value2 = &config->request.mem_resource[num].end;
-	value3 = &config->request.mem_resource[num].flags;
-	*value1 = mem->min;
-	*value2 = *value1 + mem->size - 1;
-	*value3 = mem->flags | IORESOURCE_MEM;
-	if (!(mem->flags & IORESOURCE_MEM_WRITEABLE))
-		*value3 |= IORESOURCE_READONLY;
-	if (mem->flags & IORESOURCE_MEM_CACHEABLE)
-		*value3 |= IORESOURCE_CACHEABLE;
-	if (mem->flags & IORESOURCE_MEM_RANGELENGTH)
-		*value3 |= IORESOURCE_RANGELENGTH;
-	if (mem->flags & IORESOURCE_MEM_SHADOWABLE)
-		*value3 |= IORESOURCE_SHADOWABLE;
-	while (pnp_check_mem(*value1, mem->size, num, config)) {
-		*value1 += mem->align;
-		*value2 = *value1 + mem->size - 1;
-		if (*value1 > mem->max || !mem->align)
-			return -ENOENT;
-	}
-	return 0;
-}
 
-static int pnp_generate_irq(struct pnp_cfg *config, int num)
+struct pnp_dev * pnp_check_dma_conflicts(struct pnp_dev * dev, int idx, int mode)
 {
-	struct pnp_irq *irq;
-	unsigned long *value1, *value2, *value3;
-	/* IRQ priority: this table is good for i386 */
-	static unsigned short xtab[16] = {
-		5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
-	};
-	int i;
-	if (!config || num < 0 || num > 1)
-		return -EINVAL;
-	irq = config->irq[num];
-	if (!irq)
-		return 0;
-	value1 = &config->request.irq_resource[num].start;
-	value2 = &config->request.irq_resource[num].end;
-	value3 = &config->request.irq_resource[num].flags;
-	*value3 = irq->flags | IORESOURCE_IRQ;
+	int tmp;
+	struct pnp_dev * tdev;
+	unsigned long * dma = &dev->res.dma_resource[idx].start;
 
-	for (i=0; i < 16; i++)
-	{
-		if(irq->map & (1<<xtab[i])) {
-		*value1 = *value2 = xtab[i];
-		if(pnp_check_interrupt(*value1,config)==0)
-			return 0;
+	/* if the resource doesn't exist, don't complain about it */
+	if (dev->res.dma_resource[idx].start == -1)
+		return NULL;
+
+	/* check for cold conflicts */
+	pnp_for_each_dev(tdev) {
+		/* Is the device configurable? */
+		if (tdev == dev || (mode ? !dev->active : dev->active))
+			continue;
+		for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) {
+			if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) {
+				if ((tdev->res.dma_resource[tmp].start == *dma))
+					return tdev;
+			}
 		}
 	}
-	return -ENOENT;
+	return NULL;
 }
 
-static int pnp_generate_dma(struct pnp_cfg *config, int num)
+int pnp_check_dma(struct pnp_dev * dev, int idx)
 {
-	struct pnp_dma *dma;
-	unsigned long *value1, *value2, *value3;
-	/* DMA priority: this table is good for i386 */
-	static unsigned short xtab[16] = {
-		1, 3, 5, 6, 7, 0, 2, 4
-	};
-	int i;
-	if (!config || num < 0 || num > 1)
-		return -EINVAL;
-	dma = config->dma[num];
-	if (!dma)
+	int tmp, mindma = 1;
+	unsigned long * dma = &dev->res.dma_resource[idx].start;
+
+	/* if the resource doesn't exist, don't complain about it */
+	if (dev->res.dma_resource[idx].start == -1)
 		return 0;
-	value1 = &config->request.dma_resource[num].start;
-	value2 = &config->request.dma_resource[num].end;
-	value3 = &config->request.dma_resource[num].flags;
-	*value3 = dma->flags | IORESOURCE_DMA;
 
-	for (i=0; i < 8; i++)
-	{
-		if(dma->map & (1<<xtab[i])) {
-		*value1 = *value2 = xtab[i];
-		if(pnp_check_dma(*value1,config)==0)
-			return 0;
-		}
+	/* check if the resource is valid */
+	if (pnp_allow_dma0 == 1)
+		mindma = 0;
+	if (*dma < mindma || *dma == 4 || *dma > 7)
+		return CONFLICT_TYPE_INVALID;
+
+	/* check if the resource is reserved */
+	for (tmp = 0; tmp < 8; tmp++) {
+		if (pnp_reserve_dma[tmp] == *dma)
+			return CONFLICT_TYPE_RESERVED;
 	}
-	return -ENOENT;
-}
 
-int pnp_init_res_cfg(struct pnp_res_cfg *res_config)
-{
-	int idx;
+	/* check for internal conflicts */
+	for (tmp = 0; tmp < PNP_MAX_DMA && tmp != idx; tmp++) {
+		if (dev->res.dma_resource[tmp].flags & IORESOURCE_DMA) {
+			if (dev->res.dma_resource[tmp].start == *dma)
+				return CONFLICT_TYPE_INTERNAL;
+		}
+	}
 
-	if (!res_config)
-		return -EINVAL;
-	for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++) {
-		res_config->irq_resource[idx].start = -1;
-		res_config->irq_resource[idx].end = -1;
-		res_config->irq_resource[idx].flags = IORESOURCE_IRQ|IORESOURCE_UNSET;
-	}
-	for (idx = 0; idx < DEVICE_COUNT_DMA; idx++) {
-		res_config->dma_resource[idx].name = NULL;
-		res_config->dma_resource[idx].start = -1;
-		res_config->dma_resource[idx].end = -1;
-		res_config->dma_resource[idx].flags = IORESOURCE_DMA|IORESOURCE_UNSET;
-	}
-	for (idx = 0; idx < DEVICE_COUNT_IO; idx++) {
-		res_config->io_resource[idx].name = NULL;
-		res_config->io_resource[idx].start = 0;
-		res_config->io_resource[idx].end = 0;
-		res_config->io_resource[idx].flags = IORESOURCE_IO|IORESOURCE_UNSET;
-	}
-	for (idx = 0; idx < DEVICE_COUNT_MEM; idx++) {
-		res_config->mem_resource[idx].name = NULL;
-		res_config->mem_resource[idx].start = 0;
-		res_config->mem_resource[idx].end = 0;
-		res_config->mem_resource[idx].flags = IORESOURCE_MEM|IORESOURCE_UNSET;
+	/* check if the resource is already in use, skip if the device is active because it itself may be in use */
+	if(!dev->active) {
+		if (request_dma(*dma, "pnp"))
+			return CONFLICT_TYPE_IN_USE;
+		free_dma(*dma);
 	}
-	return 0;
-}
 
-static int pnp_prepare_request(struct pnp_dev *dev, struct pnp_cfg *config, struct pnp_res_cfg *template)
-{
-	int idx, err;
-	if (!config)
-		return -EINVAL;
-	if (dev->lock_resources)
-		return -EPERM;
-	if (dev->active)
-		return -EBUSY;
-	err = pnp_init_res_cfg(&config->request);
-	if (err < 0)
-		return err;
-	if (!template)
-		return 0;
-	for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++)
-		if (pnp_flags_valid(&template->irq_resource[idx]))
-			config->request.irq_resource[idx] = template->irq_resource[idx];
-	for (idx = 0; idx < DEVICE_COUNT_DMA; idx++)
-		if (pnp_flags_valid(&template->dma_resource[idx]))
-			config->request.dma_resource[idx] = template->dma_resource[idx];
-	for (idx = 0; idx < DEVICE_COUNT_IO; idx++)
-		if (pnp_flags_valid(&template->io_resource[idx]))
-			config->request.io_resource[idx] = template->io_resource[idx];
-	for (idx = 0; idx < DEVICE_COUNT_MEM; idx++)
-		if (pnp_flags_valid(&template->io_resource[idx]))
-			config->request.mem_resource[idx] = template->mem_resource[idx];
+	/* check for warm conflicts */
+	if (pnp_check_dma_conflicts(dev, idx, SEARCH_WARM))
+		return CONFLICT_TYPE_PNP_WARM;
 	return 0;
 }
 
-static int pnp_generate_request(struct pnp_dev *dev, struct pnp_cfg *config, struct pnp_res_cfg *template)
+
+/**
+ * pnp_init_resource_table - Resets a resource table to default values.
+ * @table: pointer to the desired resource table
+ *
+ */
+
+void pnp_init_resource_table(struct pnp_resource_table *table)
 {
-	int i, err;
-	if (!config)
-		return -EINVAL;
-	if ((err = pnp_prepare_request(dev, config, template))<0)
-		return err;
-	for (i=0; i<=7; i++)
-	{
-		if(pnp_generate_port(config,i)<0)
-			return -ENOENT;
+	int idx;
+	for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
+		table->irq_resource[idx].name = NULL;
+		table->irq_resource[idx].start = -1;
+		table->irq_resource[idx].end = -1;
+		table->irq_resource[idx].flags = 0;
 	}
-	for (i=0; i<=3; i++)
-	{
-		if(pnp_generate_mem(config,i)<0)
-			return -ENOENT;
+	for (idx = 0; idx < PNP_MAX_DMA; idx++) {
+		table->dma_resource[idx].name = NULL;
+		table->dma_resource[idx].start = -1;
+		table->dma_resource[idx].end = -1;
+		table->dma_resource[idx].flags = 0;
 	}
-	for (i=0; i<=1; i++)
-	{
-		if(pnp_generate_irq(config,i)<0)
-			return -ENOENT;
+	for (idx = 0; idx < PNP_MAX_PORT; idx++) {
+		table->port_resource[idx].name = NULL;
+		table->port_resource[idx].start = 0;
+		table->port_resource[idx].end = 0;
+		table->port_resource[idx].flags = 0;
 	}
-	for (i=0; i<=1; i++)
-	{
-		if(pnp_generate_dma(config,i)<0)
-			return -ENOENT;
+	for (idx = 0; idx < PNP_MAX_MEM; idx++) {
+		table->mem_resource[idx].name = NULL;
+		table->mem_resource[idx].start = 0;
+		table->mem_resource[idx].end = 0;
+		table->mem_resource[idx].flags = 0;
 	}
-	return 0;
 }
 
 
+/**
+ * pnp_generate_rule - Creates a rule table structure based on depnum and device.
+ * @dev: pointer to the desired device
+ * @depnum: dependent function, if not valid will return an error
+ * @rule: pointer to a rule structure to record data to
+ *
+ */
 
-static struct pnp_cfg * pnp_generate_config(struct pnp_dev *dev, int depnum)
+int pnp_generate_rule(struct pnp_dev * dev, int depnum, struct pnp_rule_table * rule)
 {
-	struct pnp_cfg * config;
 	int nport = 0, nirq = 0, ndma = 0, nmem = 0;
 	struct pnp_resources * res;
 	struct pnp_port * port;
 	struct pnp_mem * mem;
 	struct pnp_irq * irq;
 	struct pnp_dma * dma;
-	if (!dev)
-		return NULL;
-	if (depnum < 0)
-		return NULL;
-	config = pnp_alloc(sizeof(struct pnp_cfg));
-	if (!config)
-		return NULL;
+
+	if (depnum < 0 || !rule)
+		return -EINVAL;
 
 	/* independent */
 	res = pnp_find_resources(dev, 0);
 	if (!res)
-		goto fail;
+		return -ENODEV;
 	port = res->port;
 	mem = res->mem;
 	irq = res->irq;
 	dma = res->dma;
 	while (port){
-		config->port[nport] = port;
+		rule->port[nport] = port;
 		nport++;
 		port = port->next;
 	}
 	while (mem){
-		config->mem[nmem] = mem;
+		rule->mem[nmem] = mem;
 		nmem++;
 		mem = mem->next;
 	}
 	while (irq){
-		config->irq[nirq] = irq;
+		rule->irq[nirq] = irq;
 		nirq++;
 		irq = irq->next;
 	}
 	while (dma){
-		config->dma[ndma] = dma;
+		rule->dma[ndma] = dma;
 		ndma++;
 		dma = dma->next;
 	}
 
 	/* dependent */
 	if (depnum == 0)
-		return config;
+		return 1;
 	res = pnp_find_resources(dev, depnum);
 	if (!res)
-		goto fail;
+		return -ENODEV;
 	port = res->port;
 	mem = res->mem;
 	irq = res->irq;
 	dma = res->dma;
 	while (port){
-		config->port[nport] = port;
+		rule->port[nport] = port;
 		nport++;
 		port = port->next;
 	}
 	while (mem){
-		config->mem[nmem] = mem;
+		rule->mem[nmem] = mem;
 		nmem++;
 		mem = mem->next;
 	}
 
 	while (irq){
-		config->irq[nirq] = irq;
+		rule->irq[nirq] = irq;
 		nirq++;
 		irq = irq->next;
 	}
 	while (dma){
-		config->dma[ndma] = dma;
+		rule->dma[ndma] = dma;
 		ndma++;
 		dma = dma->next;
 	}
-	return config;
-
-	fail:
-	kfree(config);
-	return NULL;
-}
-
-/* PnP Device Resource Management */
-
-/**
- * pnp_activate_dev - activates a PnP device for use
- * @dev: pointer to the desired device
- *
- * finds the best resource configuration and then informs the correct pnp protocol
- */
-
-int pnp_activate_dev(struct pnp_dev *dev, struct pnp_res_cfg *template)
-{
-	int depnum, max;
-	struct pnp_cfg *config;
-	if (!dev)
-		return -EINVAL;
-        max = pnp_get_max_depnum(dev);
-	if (!pnp_can_configure(dev))
-		return -EBUSY;
-	if (dev->status != PNP_READY && dev->status != PNP_ATTACHED){
-		printk(KERN_INFO "pnp: Automatic configuration failed because the PnP device '%s' is busy\n", dev->dev.bus_id);
-		return -EINVAL;
-	}
-	if (!pnp_can_write(dev))
-		return -EINVAL;
-	if (max == 0)
-		return 0;
-	for (depnum=1; depnum <= max; depnum++)
-	{
-		config = pnp_generate_config(dev,depnum);
-		if (!config)
-			return -EINVAL;
-		if (pnp_generate_request(dev,config,template)==0)
-			goto done;
-		kfree(config);
-	}
-	printk(KERN_ERR "pnp: Automatic configuration failed for device '%s' due to resource conflicts\n", dev->dev.bus_id);
-	return -ENOENT;
-
-	done:
-	pnp_dbg("the device '%s' has been activated", dev->dev.bus_id);
-	dev->protocol->set(dev,config);
-	if (pnp_can_read(dev))
-		dev->protocol->get(dev);
-	kfree(config);
-	return 0;
-}
-
-/**
- * pnp_disable_dev - disables device
- * @dev: pointer to the desired device
- *
- * inform the correct pnp protocol so that resources can be used by other devices
- */
-
-int pnp_disable_dev(struct pnp_dev *dev)
-{
-        if (!dev)
-                return -EINVAL;
-	if (dev->status != PNP_READY){
-		printk(KERN_INFO "pnp: Disable failed becuase the PnP device '%s' is busy\n", dev->dev.bus_id);
-		return -EINVAL;
-	}
-	if (dev->lock_resources)
-		return -EPERM;
-	if (!pnp_can_disable(dev) || !dev->active)
-		return -EINVAL;
-	pnp_dbg("the device '%s' has been disabled", dev->dev.bus_id);
-	return dev->protocol->disable(dev);
-}
 
-/**
- * pnp_raw_set_dev - same as pnp_activate_dev except the resource config can be specified
- * @dev: pointer to the desired device
- * @depnum: resource dependent function
- * @mode: static or dynamic
- *
- */
-
-int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, struct pnp_res_cfg *template)
-{
-	struct pnp_cfg *config;
-	if (!dev)
-		return -EINVAL;
-	if (dev->status != PNP_READY){
-		printk(KERN_INFO "pnp: Unable to set resources because the PnP device '%s' is busy\n", dev->dev.bus_id);
-		return -EINVAL;
-	}
-	if (!pnp_can_write(dev) || !pnp_can_configure(dev))
-		return -EINVAL;
-        config = pnp_generate_config(dev,depnum);
-	if (!config)
-		return -EINVAL;
-	if (pnp_generate_request(dev,config,template)==0)
-		goto done;
-	kfree(config);
-	printk(KERN_ERR "pnp: Manual configuration failed for device '%s' due to resource conflicts\n", dev->dev.bus_id);
-	return -ENOENT;
-
-	done:
-	dev->protocol->set(dev,config);
-	if (pnp_can_read(dev))
-		dev->protocol->get(dev);
-	kfree(config);
-	return 0;
+	/* clear the remaining values */
+	for (; nport < PNP_MAX_PORT; nport++)
+		rule->port[nport] = NULL;
+	for (; nmem < PNP_MAX_MEM; nmem++)
+		rule->mem[nmem] = NULL;
+	for (; nirq < PNP_MAX_IRQ; nirq++)
+		rule->irq[nirq] = NULL;
+	for (; ndma < PNP_MAX_DMA; ndma++)
+		rule->dma[ndma] = NULL;
+	return 1;
 }
 
-/**
- * pnp_resource_change - change one resource
- * @resource: pointer to resource to be changed
- * @start: start of region
- * @size: size of region
- *
- */
- 
-void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size)
-{
-	if (resource == NULL)
-		return;
-	resource->flags &= ~(IORESOURCE_AUTO|IORESOURCE_UNSET);
-	resource->start = start;
-	resource->end = start + size - 1;
-}
 
 EXPORT_SYMBOL(pnp_build_resource);
 EXPORT_SYMBOL(pnp_find_resources);
@@ -899,12 +682,9 @@ EXPORT_SYMBOL(pnp_add_irq_resource);
 EXPORT_SYMBOL(pnp_add_dma_resource);
 EXPORT_SYMBOL(pnp_add_port_resource);
 EXPORT_SYMBOL(pnp_add_mem_resource);
-EXPORT_SYMBOL(pnp_add_mem32_resource);
-EXPORT_SYMBOL(pnp_init_res_cfg);
-EXPORT_SYMBOL(pnp_activate_dev);
-EXPORT_SYMBOL(pnp_disable_dev);
-EXPORT_SYMBOL(pnp_raw_set_dev);
-EXPORT_SYMBOL(pnp_resource_change);
+EXPORT_SYMBOL(pnp_init_resource_table);
+EXPORT_SYMBOL(pnp_generate_rule);
+
 
 /* format is: allowdma0 */
 
diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c
new file mode 100644
index 0000000000000000000000000000000000000000..c54cf87fb8cc566cf3782fcb9a22a686a8af5372
--- /dev/null
+++ b/drivers/pnp/support.c
@@ -0,0 +1,676 @@
+/*
+ * support.c - provides standard pnp functions for the use of pnp protocol drivers,
+ *
+ * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
+ *
+ * Resource parsing functions are based on those in the linux pnpbios driver.
+ * Copyright Christian Schmidt, Tom Lees, David Hinds, Alan Cox, Thomas Hood,
+ * Brian Gerst and Adam Belay.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#ifdef CONFIG_PNP_DEBUG
+	#define DEBUG
+#else
+	#undef DEBUG
+#endif
+
+#include <linux/pnp.h>
+#include "base.h"
+
+#define SMALL_TAG_PNPVERNO		0x01
+#define SMALL_TAG_LOGDEVID		0x02
+#define SMALL_TAG_COMPATDEVID		0x03
+#define SMALL_TAG_IRQ			0x04
+#define SMALL_TAG_DMA			0x05
+#define SMALL_TAG_STARTDEP		0x06
+#define SMALL_TAG_ENDDEP		0x07
+#define SMALL_TAG_PORT			0x08
+#define SMALL_TAG_FIXEDPORT		0x09
+#define SMALL_TAG_VENDOR		0x0e
+#define SMALL_TAG_END			0x0f
+#define LARGE_TAG			0x80
+#define LARGE_TAG_MEM			0x01
+#define LARGE_TAG_ANSISTR		0x02
+#define LARGE_TAG_UNICODESTR		0x03
+#define LARGE_TAG_VENDOR		0x04
+#define LARGE_TAG_MEM32			0x05
+#define LARGE_TAG_FIXEDMEM32		0x06
+
+
+/**
+ * pnp_is_active - Determines if a device is active based on its current resources
+ * @dev: pointer to the desired PnP device
+ *
+ */
+
+int pnp_is_active(struct pnp_dev * dev)
+{
+	if (!pnp_port_start(dev, 0) && pnp_port_len(dev, 0) <= 1 &&
+	    !pnp_mem_start(dev, 0) && pnp_mem_len(dev, 0) <= 1 &&
+	    pnp_irq(dev, 0) == -1 &&
+	    pnp_dma(dev, 0) == -1)
+	    	return 0;
+	else
+		return 1;
+}
+
+
+/*
+ * Current resource reading functions *
+ */
+
+static void current_irqresource(struct pnp_resource_table * res, int irq)
+{
+	int i = 0;
+	while ((res->irq_resource[i].flags & IORESOURCE_IRQ) && i < PNP_MAX_IRQ) i++;
+	if (i < PNP_MAX_IRQ) {
+		res->irq_resource[i].start =
+		res->irq_resource[i].end = (unsigned long) irq;
+		res->irq_resource[i].flags = IORESOURCE_IRQ;  // Also clears _UNSET flag
+	}
+}
+
+static void current_dmaresource(struct pnp_resource_table * res, int dma)
+{
+	int i = 0;
+	while ((res->dma_resource[i].flags & IORESOURCE_DMA) && i < PNP_MAX_DMA) i++;
+	if (i < PNP_MAX_DMA) {
+		res->dma_resource[i].start =
+		res->dma_resource[i].end = (unsigned long) dma;
+		res->dma_resource[i].flags = IORESOURCE_DMA;  // Also clears _UNSET flag
+	}
+}
+
+static void current_ioresource(struct pnp_resource_table * res, int io, int len)
+{
+	int i = 0;
+	while ((res->port_resource[i].flags & IORESOURCE_IO) && i < PNP_MAX_PORT) i++;
+	if (i < PNP_MAX_PORT) {
+		res->port_resource[i].start = (unsigned long) io;
+		res->port_resource[i].end = (unsigned long)(io + len - 1);
+		res->port_resource[i].flags = IORESOURCE_IO;  // Also clears _UNSET flag
+	}
+}
+
+static void current_memresource(struct pnp_resource_table * res, int mem, int len)
+{
+	int i = 0;
+	while ((res->mem_resource[i].flags & IORESOURCE_MEM) && i < PNP_MAX_MEM) i++;
+	if (i < PNP_MAX_MEM) {
+		res->mem_resource[i].start = (unsigned long) mem;
+		res->mem_resource[i].end = (unsigned long)(mem + len - 1);
+		res->mem_resource[i].flags = IORESOURCE_MEM;  // Also clears _UNSET flag
+	}
+}
+
+/**
+ * pnp_parse_current_resources - Extracts current resource information from a raw PnP resource structure
+ * @p: pointer to the start of the structure
+ * @end: pointer to the end of the structure
+ * @res: pointer to the resource table to record to
+ *
+ */
+
+unsigned char * pnp_parse_current_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res)
+{
+	int len;
+
+	if (!p)
+		return NULL;
+
+	/* Blank the resource table values */
+	pnp_init_resource_table(res);
+
+	while ((char *)p < (char *)end) {
+
+		if(p[0] & LARGE_TAG) { /* large tag */
+			len = (p[2] << 8) | p[1];
+			switch (p[0] & 0x7f) {
+			case LARGE_TAG_MEM:
+			{
+				int io = *(short *) &p[4];
+				int size = *(short *) &p[10];
+				if (len != 9)
+					goto lrg_err;
+				current_memresource(res, io, size);
+				break;
+			}
+			case LARGE_TAG_ANSISTR:
+			{
+				/* ignore this for now */
+				break;
+			}
+			case LARGE_TAG_VENDOR:
+			{
+				/* do nothing */
+				break;
+			}
+			case LARGE_TAG_MEM32:
+			{
+				int io = *(int *) &p[4];
+				int size = *(int *) &p[16];
+				if (len != 17)
+					goto lrg_err;
+				current_memresource(res, io, size);
+				break;
+			}
+			case LARGE_TAG_FIXEDMEM32:
+			{
+				int io = *(int *) &p[4];
+				int size = *(int *) &p[8];
+				if (len != 9)
+					goto lrg_err;
+				current_memresource(res, io, size);
+				break;
+			}
+			default: /* an unkown tag */
+			{
+				lrg_err:
+				pnp_warn("parser: Unknown large tag '0x%x'.", p[0] & 0x7f);
+				break;
+			}
+			} /* switch */
+			p += len + 3;
+			continue;
+		} /* end large tag */
+
+		/* small tag */
+		len = p[0] & 0x07;
+		switch ((p[0]>>3) & 0x0f) {
+		case SMALL_TAG_IRQ:
+		{
+			int i, mask, irq = -1;
+			if (len < 2 || len > 3)
+				goto sm_err;
+			mask= p[1] + p[2]*256;
+			for (i=0;i<16;i++, mask=mask>>1)
+				if(mask & 0x01) irq=i;
+			current_irqresource(res, irq);
+			break;
+		}
+		case SMALL_TAG_DMA:
+		{
+			int i, mask, dma = -1;
+			if (len != 2)
+				goto sm_err;
+			mask = p[1];
+			for (i=0;i<8;i++, mask = mask>>1)
+				if(mask & 0x01) dma=i;
+			current_dmaresource(res, dma);
+			break;
+		}
+		case SMALL_TAG_PORT:
+		{
+			int io= p[2] + p[3] *256;
+			int size = p[7];
+			if (len != 7)
+				goto sm_err;
+			current_ioresource(res, io, size);
+			break;
+		}
+		case SMALL_TAG_VENDOR:
+		{
+			/* do nothing */
+			break;
+		}
+		case SMALL_TAG_FIXEDPORT:
+		{
+			int io = p[1] + p[2] * 256;
+			int size = p[3];
+			if (len != 3)
+				goto sm_err;
+			current_ioresource(res, io, size);
+			break;
+		}
+		case SMALL_TAG_END:
+		{
+			p = p + 2;
+        		return (unsigned char *)p;
+			break;
+		}
+		default: /* an unkown tag */
+		{
+			sm_err:
+			pnp_warn("parser: Unknown small tag '0x%x'.", p[0]>>3);
+			break;
+		}
+		}
+                p += len + 1;
+	}
+	pnp_err("parser: Resource structure does not contain an end tag.");
+
+	return NULL;
+}
+
+
+/*
+ * Possible resource reading functions *
+ */
+
+static void possible_mem(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
+{
+	struct pnp_mem * mem;
+	mem = pnp_alloc(sizeof(struct pnp_mem));
+	if (!mem)
+		return;
+	mem->min = ((p[3] << 8) | p[2]) << 8;
+	mem->max = ((p[5] << 8) | p[4]) << 8;
+	mem->align = (p[7] << 8) | p[6];
+	mem->size = ((p[9] << 8) | p[8]) << 8;
+	mem->flags = p[1];
+	pnp_add_mem_resource(dev,depnum,mem);
+	return;
+}
+
+static void possible_mem32(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
+{
+	struct pnp_mem * mem;
+	mem = pnp_alloc(sizeof(struct pnp_mem));
+	if (!mem)
+		return;
+	mem->min = (p[5] << 24) | (p[4] << 16) | (p[3] << 8) | p[2];
+	mem->max = (p[9] << 24) | (p[8] << 16) | (p[7] << 8) | p[6];
+	mem->align = (p[13] << 24) | (p[12] << 16) | (p[11] << 8) | p[10];
+	mem->size = (p[17] << 24) | (p[16] << 16) | (p[15] << 8) | p[14];
+	mem->flags = p[1];
+	pnp_add_mem_resource(dev,depnum,mem);
+	return;
+}
+
+static void possible_fixed_mem32(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
+{
+	struct pnp_mem * mem;
+	mem = pnp_alloc(sizeof(struct pnp_mem));
+	if (!mem)
+		return;
+	mem->min = mem->max = (p[5] << 24) | (p[4] << 16) | (p[3] << 8) | p[2];
+	mem->size = (p[9] << 24) | (p[8] << 16) | (p[7] << 8) | p[6];
+	mem->align = 0;
+	mem->flags = p[1];
+	pnp_add_mem_resource(dev,depnum,mem);
+	return;
+}
+
+static void possible_irq(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
+{
+	struct pnp_irq * irq;
+	irq = pnp_alloc(sizeof(struct pnp_irq));
+	if (!irq)
+		return;
+	irq->map = (p[2] << 8) | p[1];
+	if (size > 2)
+		irq->flags = p[3];
+	pnp_add_irq_resource(dev,depnum,irq);
+	return;
+}
+
+static void possible_dma(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
+{
+	struct pnp_dma * dma;
+	dma = pnp_alloc(sizeof(struct pnp_dma));
+	if (!dma)
+		return;
+	dma->map = p[1];
+	dma->flags = p[2];
+	pnp_add_dma_resource(dev,depnum,dma);
+	return;
+}
+
+static void possible_port(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
+{
+	struct pnp_port * port;
+	port = pnp_alloc(sizeof(struct pnp_port));
+	if (!port)
+		return;
+	port->min = (p[3] << 8) | p[2];
+	port->max = (p[5] << 8) | p[4];
+	port->align = p[6];
+	port->size = p[7];
+	port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0;
+	pnp_add_port_resource(dev,depnum,port);
+	return;
+}
+
+static void possible_fixed_port(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
+{
+	struct pnp_port * port;
+	port = pnp_alloc(sizeof(struct pnp_port));
+	if (!port)
+		return;
+	port->min = port->max = (p[2] << 8) | p[1];
+	port->size = p[3];
+	port->align = 0;
+	port->flags = PNP_PORT_FLAG_FIXED;
+	pnp_add_port_resource(dev,depnum,port);
+	return;
+}
+
+/**
+ * pnp_parse_possible_resources - Extracts possible resource information from a raw PnP resource structure
+ * @p: pointer to the start of the structure
+ * @end: pointer to the end of the structure
+ * @dev: pointer to the desired PnP device
+ *
+ */
+
+unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char * end, struct pnp_dev *dev)
+{
+	int len, depnum = 0, dependent = 0;
+
+	if (!p)
+		return NULL;
+
+	if (pnp_build_resource(dev, 0) == NULL)
+		return NULL;
+
+	while ((char *)p < (char *)end) {
+
+		if(p[0] & LARGE_TAG) { /* large tag */
+			len = (p[2] << 8) | p[1];
+			switch (p[0] & 0x7f) {
+			case LARGE_TAG_MEM:
+			{
+				if (len != 9)
+					goto lrg_err;
+				possible_mem(p,len,depnum,dev);
+				break;
+			}
+			case LARGE_TAG_MEM32:
+			{
+				if (len != 17)
+					goto lrg_err;
+				possible_mem32(p,len,depnum,dev);
+				break;
+			}
+			case LARGE_TAG_FIXEDMEM32:
+			{
+				if (len != 9)
+					goto lrg_err;
+				possible_fixed_mem32(p,len,depnum,dev);
+				break;
+			}
+			default: /* an unkown tag */
+			{
+				lrg_err:
+				pnp_warn("parser: Unknown large tag '0x%x'.", p[0] & 0x7f);
+				break;
+			}
+			} /* switch */
+                        p += len + 3;
+			continue;
+		} /* end large tag */
+
+		/* small tag */
+		len = p[0] & 0x07;
+		switch ((p[0]>>3) & 0x0f) {
+		case SMALL_TAG_IRQ:
+		{
+			if (len < 2 || len > 3)
+				goto sm_err;
+			possible_irq(p,len,depnum,dev);
+			break;
+		}
+		case SMALL_TAG_DMA:
+		{
+			if (len != 2)
+				goto sm_err;
+			possible_dma(p,len,depnum,dev);
+			break;
+		}
+		case SMALL_TAG_STARTDEP:
+		{
+			if (len > 1)
+				goto sm_err;
+			dependent = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;
+			if (len > 0)
+				dependent = 0x100 | p[1];
+			pnp_build_resource(dev,dependent);
+			depnum = pnp_get_max_depnum(dev);
+			break;
+		}
+		case SMALL_TAG_ENDDEP:
+		{
+			if (len != 0)
+				goto sm_err;
+			depnum = 0;
+			break;
+		}
+		case SMALL_TAG_PORT:
+		{
+			if (len != 7)
+				goto sm_err;
+			possible_port(p,len,depnum,dev);
+			break;
+		}
+		case SMALL_TAG_FIXEDPORT:
+		{
+			if (len != 3)
+				goto sm_err;
+			possible_fixed_port(p,len,depnum,dev);
+			break;
+		}
+		case SMALL_TAG_END:
+		{
+			p = p + 2;
+			return (unsigned char *)p;
+			break;
+		}
+		default: /* an unkown tag */
+		{
+			sm_err:
+			pnp_warn("parser: Unknown small tag '0x%x'.", p[0]>>3);
+			break;
+		}
+		}
+                p += len + 1;
+	}
+	pnp_err("parser: Resource structure does not contain an end tag.");
+
+	return NULL;
+}
+
+
+/*
+ * Resource Writing functions
+ */
+
+static void write_mem(unsigned char *p, struct resource * res)
+{
+	unsigned long base = res->start;
+	unsigned long len = res->end - res->start + 1;
+	p[2] = (base >> 8) & 0xff;
+	p[3] = ((base >> 8) >> 8) & 0xff;
+	p[4] = (base >> 8) & 0xff;
+	p[5] = ((base >> 8) >> 8) & 0xff;
+	p[8] = (len >> 8) & 0xff;
+	p[9] = ((len >> 8) >> 8) & 0xff;
+	return;
+}
+
+static void write_mem32(unsigned char *p, struct resource * res)
+{
+	unsigned long base = res->start;
+	unsigned long len = res->end - res->start + 1;
+	p[2] = base & 0xff;
+	p[3] = (base >> 8) & 0xff;
+	p[4] = (base >> 16) & 0xff;
+	p[5] = (base >> 24) & 0xff;
+	p[6] = base & 0xff;
+	p[7] = (base >> 8) & 0xff;
+	p[8] = (base >> 16) & 0xff;
+	p[9] = (base >> 24) & 0xff;
+	p[14] = len & 0xff;
+	p[15] = (len >> 8) & 0xff;
+	p[16] = (len >> 16) & 0xff;
+	p[17] = (len >> 24) & 0xff;
+	return;
+}
+
+static void write_fixed_mem32(unsigned char *p, struct resource * res)
+{	unsigned long base = res->start;
+	unsigned long len = res->end - res->start + 1;
+	p[2] = base & 0xff;
+	p[3] = (base >> 8) & 0xff;
+	p[4] = (base >> 16) & 0xff;
+	p[5] = (base >> 24) & 0xff;
+	p[6] = len & 0xff;
+	p[7] = (len >> 8) & 0xff;
+	p[8] = (len >> 16) & 0xff;
+	p[9] = (len >> 24) & 0xff;
+	return;
+}
+
+static void write_irq(unsigned char *p, struct resource * res)
+{
+	unsigned long map = 0;
+	map = 1 << res->start;
+	p[1] = map & 0xff;
+	p[2] = (map >> 8) & 0xff;
+	return;
+}
+
+static void write_dma(unsigned char *p, struct resource * res)
+{
+	unsigned long map = 0;
+	map = 1 << res->start;
+	p[1] = map & 0xff;
+	return;
+}
+
+static void write_port(unsigned char *p, struct resource * res)
+{
+	unsigned long base = res->start;
+	unsigned long len = res->end - res->start + 1;
+	p[2] = base & 0xff;
+	p[3] = (base >> 8) & 0xff;
+	p[4] = base & 0xff;
+	p[5] = (base >> 8) & 0xff;
+	p[7] = len & 0xff;
+	return;
+}
+
+static void write_fixed_port(unsigned char *p, struct resource * res)
+{
+	unsigned long base = res->start;
+	unsigned long len = res->end - res->start + 1;
+	p[1] = base & 0xff;
+	p[2] = (base >> 8) & 0xff;
+	p[3] = len & 0xff;
+	return;
+}
+
+/**
+ * pnp_write_resources - Writes resource information to a raw PnP resource structure
+ * @p: pointer to the start of the structure
+ * @end: pointer to the end of the structure
+ * @res: pointer to a resource table containing the resources to set
+ *
+ */
+
+unsigned char * pnp_write_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res)
+{
+	int len, port = 0, irq = 0, dma = 0, mem = 0;
+
+	if (!p)
+		return NULL;
+
+	while ((char *)p < (char *)end) {
+
+		if(p[0] & LARGE_TAG) { /* large tag */
+			len = (p[2] << 8) | p[1];
+			switch (p[0] & 0x7f) {
+			case LARGE_TAG_MEM:
+			{
+				if (len != 9)
+					goto lrg_err;
+				write_mem(p, &res->mem_resource[mem]);
+				mem++;
+				break;
+			}
+			case LARGE_TAG_MEM32:
+			{
+				if (len != 17)
+					goto lrg_err;
+				write_mem32(p, &res->mem_resource[mem]);
+				break;
+			}
+			case LARGE_TAG_FIXEDMEM32:
+			{
+				if (len != 9)
+					goto lrg_err;
+				write_fixed_mem32(p, &res->mem_resource[mem]);
+				break;
+			}
+			default: /* an unkown tag */
+			{
+				lrg_err:
+				pnp_warn("parser: Unknown large tag '0x%x'.", p[0] & 0x7f);
+				break;
+			}
+			} /* switch */
+                        p += len + 3;
+			continue;
+		} /* end large tag */
+
+		/* small tag */
+		len = p[0] & 0x07;
+		switch ((p[0]>>3) & 0x0f) {
+		case SMALL_TAG_IRQ:
+		{
+			if (len < 2 || len > 3)
+				goto sm_err;
+			write_irq(p, &res->irq_resource[irq]);
+			irq++;
+			break;
+		}
+		case SMALL_TAG_DMA:
+		{
+			if (len != 2)
+				goto sm_err;
+			write_dma(p, &res->dma_resource[irq]);
+			dma++;
+			break;
+		}
+		case SMALL_TAG_PORT:
+		{
+			if (len != 7)
+				goto sm_err;
+			write_port(p, &res->port_resource[port]);
+			port++;
+			break;
+		}
+		case SMALL_TAG_FIXEDPORT:
+		{
+			if (len != 3)
+				goto sm_err;
+			write_fixed_port(p, &res->port_resource[port]);
+			port++;
+			break;
+		}
+		case SMALL_TAG_END:
+		{
+			p = p + 2;
+			return (unsigned char *)p;
+			break;
+		}
+		default: /* an unkown tag */
+		{
+			sm_err:
+			pnp_warn("parser: Unknown small tag '0x%x'.", p[0]>>3);
+			break;
+		}
+		}
+                p += len + 1;
+	}
+	pnp_err("parser: Resource structure does not contain an end tag.");
+
+	return NULL;
+}
+
+EXPORT_SYMBOL(pnp_is_active);
+EXPORT_SYMBOL(pnp_parse_current_resources);
+EXPORT_SYMBOL(pnp_parse_possible_resources);
+EXPORT_SYMBOL(pnp_write_resources);
diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c
index d32e9b5805978ff0259d12f9c07a2c1954c84be9..cadcdcdbe1f7a12838617c6e1a0f040e97a902cb 100644
--- a/drivers/pnp/system.c
+++ b/drivers/pnp/system.c
@@ -53,7 +53,7 @@ static void __init reserve_resources_of_dev( struct pnp_dev *dev )
 {
 	int i;
 
-	for (i=0;i<DEVICE_COUNT_IO;i++) {
+	for (i=0;i<PNP_MAX_PORT;i++) {
 		if (pnp_port_valid(dev, i))
 			/* end of resources */
 			continue;
@@ -93,6 +93,7 @@ static int system_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *de
 
 static struct pnp_driver system_pnp_driver = {
 	.name		= "system",
+	.flags		= PNP_DRIVER_DO_NOT_ACTIVATE, 
 	.id_table	= pnp_dev_table,
 	.probe		= system_pnp_probe,
 	.remove		= NULL,
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
index 7ba1705a688ccd6d09baf4c4c2236fcd9be5cf04..957b709c5c3d7649bc5cee2b00c5f05e81e4d789 100644
--- a/drivers/serial/8250_pnp.c
+++ b/drivers/serial/8250_pnp.c
@@ -317,7 +317,7 @@ static inline void avoid_irq_share(struct pnp_dev *dev)
 {
 	unsigned int map = 0x1FF8;
 	struct pnp_irq *irq;
-	struct pnp_resources *res = dev->res;
+	struct pnp_resources *res = dev->possible;
 
 	serial8250_get_irq_map(&map);
 
@@ -357,10 +357,10 @@ static int __devinit check_name(char *name)
  */
 static int serial_pnp_guess_board(struct pnp_dev *dev, int *flags)
 {
-	struct pnp_resources *res = dev->res;
+	struct pnp_resources *res = dev->possible;
 	struct pnp_resources *resa;
 
-	if (!(check_name(dev->name) || (dev->card && check_name(dev->card->name))))
+	if (!(check_name(dev->dev.name) || (dev->card && check_name(dev->card->dev.name))))
 		return -ENODEV;
 
 	if (!res)
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 32f4e6650463341acd4363acccfaf20634731deb..7510ad7d1aa4200afc0b1004f2f4f5e25f59bcc1 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1705,6 +1705,7 @@ static inline void ide_release_dma(ide_hwif_t *drive) {;}
 #endif
 
 extern void hwif_unregister(ide_hwif_t *);
+extern void ide_unregister (unsigned int index);
 
 extern void export_ide_init_queue(ide_drive_t *);
 extern u8 export_probe_for_drive(ide_drive_t *);
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index edd1eadb98b82fe37533e0cdf5226e94a044c1ac..7a9431f4673f3bb9ed870eb239c7c2734b8d4210 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -77,6 +77,7 @@ struct resource_list {
 #define IORESOURCE_MEM_8BIT		(0<<3)
 #define IORESOURCE_MEM_16BIT		(1<<3)
 #define IORESOURCE_MEM_8AND16BIT	(2<<3)
+#define IORESOURCE_MEM_32BIT		(3<<3)
 #define IORESOURCE_MEM_SHADOWABLE	(1<<5)	/* dup: IORESOURCE_SHADOWABLE */
 #define IORESOURCE_MEM_EXPANSIONROM	(1<<6)
 
diff --git a/include/linux/pnp.h b/include/linux/pnp.h
index d138647ff235db37e4296e8817e5c488e3968d3d..caf54014088eb8a00f62abab509a5d239e4d2399 100644
--- a/include/linux/pnp.h
+++ b/include/linux/pnp.h
@@ -13,42 +13,144 @@
 #include <linux/list.h>
 #include <linux/errno.h>
 
+#define PNP_MAX_PORT		8
+#define PNP_MAX_MEM		4
+#define PNP_MAX_IRQ		2
+#define PNP_MAX_DMA		2
+#define PNP_MAX_DEVICES		8
+#define PNP_ID_LEN		8
+
+struct pnp_protocol;
+struct pnp_dev;
+
 
 /*
- * Device Managemnt
+ * Resource Management
  */
 
-#define DEVICE_COUNT_IRQ	2
-#define DEVICE_COUNT_DMA	2
-#define DEVICE_COUNT_IO		8
-#define DEVICE_COUNT_MEM	4
-#define MAX_DEVICES		8
+/* Use these instead of directly reading pnp_dev to get resource information */
+#define pnp_port_start(dev,bar)   ((dev)->res.port_resource[(bar)].start)
+#define pnp_port_end(dev,bar)     ((dev)->res.port_resource[(bar)].end)
+#define pnp_port_flags(dev,bar)   ((dev)->res.port_resource[(bar)].flags)
+#define pnp_port_valid(dev,bar)   (pnp_port_flags((dev),(bar)) & IORESOURCE_IO)
+#define pnp_port_len(dev,bar) \
+	((pnp_port_start((dev),(bar)) == 0 &&	\
+	  pnp_port_end((dev),(bar)) ==		\
+	  pnp_port_start((dev),(bar))) ? 0 :	\
+	  					\
+	 (pnp_port_end((dev),(bar)) -		\
+	  pnp_port_start((dev),(bar)) + 1))
+
+#define pnp_mem_start(dev,bar)   ((dev)->res.mem_resource[(bar)].start)
+#define pnp_mem_end(dev,bar)     ((dev)->res.mem_resource[(bar)].end)
+#define pnp_mem_flags(dev,bar)   ((dev)->res.mem_resource[(bar)].flags)
+#define pnp_mem_valid(dev,bar)   (pnp_mem_flags((dev),(bar)) & IORESOURCE_MEM)
+#define pnp_mem_len(dev,bar) \
+	((pnp_mem_start((dev),(bar)) == 0 &&	\
+	  pnp_mem_end((dev),(bar)) ==		\
+	  pnp_mem_start((dev),(bar))) ? 0 :	\
+	  					\
+	 (pnp_mem_end((dev),(bar)) -		\
+	  pnp_mem_start((dev),(bar)) + 1))
+
+#define pnp_irq(dev,bar)	 ((dev)->res.irq_resource[(bar)].start)
+#define pnp_irq_flags(dev,bar)	 ((dev)->res.irq_resource[(bar)].flags)
+#define pnp_irq_valid(dev,bar)   (pnp_irq_flags((dev),(bar)) & IORESOURCE_IRQ)
+
+#define pnp_dma(dev,bar)	 ((dev)->res.dma_resource[(bar)].start)
+#define pnp_dma_flags(dev,bar)	 ((dev)->res.dma_resource[(bar)].flags)
+#define pnp_dma_valid(dev,bar)   (pnp_dma_flags((dev),(bar)) & IORESOURCE_DMA)
+
+#define PNP_PORT_FLAG_16BITADDR	(1<<0)
+#define PNP_PORT_FLAG_FIXED	(1<<1)
+
+struct pnp_port {
+	unsigned short min;		/* min base number */
+	unsigned short max;		/* max base number */
+	unsigned char align;		/* align boundary */
+	unsigned char size;		/* size of range */
+	unsigned char flags;		/* port flags */
+	unsigned char pad;		/* pad */
+	struct pnp_port *next;		/* next port */
+};
+
+struct pnp_irq {
+	unsigned short map;		/* bitmaks for IRQ lines */
+	unsigned char flags;		/* IRQ flags */
+	unsigned char pad;		/* pad */
+	struct pnp_irq *next;		/* next IRQ */
+};
+
+struct pnp_dma {
+	unsigned char map;		/* bitmask for DMA channels */
+	unsigned char flags;		/* DMA flags */
+	struct pnp_dma *next;		/* next port */
+};
+
+struct pnp_mem {
+	unsigned int min;		/* min base number */
+	unsigned int max;		/* max base number */
+	unsigned int align;		/* align boundary */
+	unsigned int size;		/* size of range */
+	unsigned char flags;		/* memory flags */
+	unsigned char pad;		/* pad */
+	struct pnp_mem *next;		/* next memory resource */
+};
+
+#define PNP_RES_PRIORITY_PREFERRED	0
+#define PNP_RES_PRIORITY_ACCEPTABLE	1
+#define PNP_RES_PRIORITY_FUNCTIONAL	2
+#define PNP_RES_PRIORITY_INVALID	65535
+
+struct pnp_resources {
+	unsigned short priority;	/* priority */
+	struct pnp_port *port;		/* first port */
+	struct pnp_irq *irq;		/* first IRQ */
+	struct pnp_dma *dma;		/* first DMA */
+	struct pnp_mem *mem;		/* first memory resource */
+	struct pnp_dev *dev;		/* parent */
+	struct pnp_resources *dep;	/* dependent resources */
+};
+
+struct pnp_rule_table {
+	int depnum;
+	struct pnp_port *port[PNP_MAX_PORT];
+	struct pnp_irq *irq[PNP_MAX_IRQ];
+	struct pnp_dma *dma[PNP_MAX_DMA];
+	struct pnp_mem *mem[PNP_MAX_MEM];
+};
+
+struct pnp_resource_table {
+	struct resource port_resource[PNP_MAX_PORT];
+	struct resource mem_resource[PNP_MAX_MEM];
+	struct resource dma_resource[PNP_MAX_DMA];
+	struct resource irq_resource[PNP_MAX_IRQ];
+};
 
-struct pnp_resource;
-struct pnp_protocol;
-struct pnp_id;
-struct pnp_cfg;
+
+/*
+ * Device Managemnt
+ */
 
 struct pnp_card {
-	char name[80];
-	int status;			/* status of the card */
-	unsigned char number;		/* card number */
+	struct device dev;		/* Driver Model device interface */
+	unsigned char number;		/* used as an index, must be unique */
 	struct list_head global_list;	/* node in global list of cards */
 	struct list_head protocol_list;	/* node in protocol's list of cards */
 	struct list_head devices;	/* devices attached to the card */
+	struct list_head rdevs;		/* a list of devices requested by the card driver */
+	int status;
+
 	struct pnp_protocol * protocol;
+	struct pnpc_driver * driver;
 	struct pnp_id * id;		/* contains supported EISA IDs*/
 
+	void	      * protocol_data;	/* Used to store protocol specific data */
 	unsigned char	pnpver;		/* Plug & Play version */
 	unsigned char	productver;	/* product version */
 	unsigned int	serial;		/* serial number */
 	unsigned char	checksum;	/* if zero - checksum passed */
-	void	      * protocol_data;	/* Used to store protocol specific data */
-
-	struct pnpc_driver * driver;	/* pointer to the driver bound to this device */
-	struct list_head rdevs;		/* a list of devices requested by the card driver */
 	struct proc_dir_entry *procdir;	/* directory entry in /proc/bus/isapnp */
-	struct	device	dev;		/* Driver Model device interface */
 };
 
 #define global_to_pnp_card(n) list_entry(n, struct pnp_card, global_list)
@@ -58,10 +160,6 @@ struct pnp_card {
 	for((card) = global_to_pnp_card(pnp_cards.next); \
 	(card) != global_to_pnp_card(&pnp_cards); \
 	(card) = global_to_pnp_card((card)->global_list.next))
-#define pnp_card_for_each_dev(card,dev) \
-	for((dev) = card_to_pnp_dev((card)->devices.next); \
-	(dev) != card_to_pnp_dev(&(card)->devices); \
-	(dev) = card_to_pnp_dev((dev)->card_list.next))
 
 static inline void *pnpc_get_drvdata (struct pnp_card *pcard)
 {
@@ -84,8 +182,9 @@ static inline void pnpc_set_protodata (struct pnp_card *pcard, void *data)
 }
 
 struct pnp_dev {
-	char name[80];			/* device name */
-	int active;			/* status of the device */
+	struct device dev;		/* Driver Model device interface */
+	unsigned char number;		/* used as an index, must be unique */
+	int active;
 	int capabilities;
 	int status;
 
@@ -93,24 +192,20 @@ struct pnp_dev {
 	struct list_head protocol_list;	/* node in list of device's protocol */
 	struct list_head card_list;	/* node in card's list of devices */
 	struct list_head rdev_list;	/* node in cards list of requested devices */
+
 	struct pnp_protocol * protocol;
-	struct pnp_card * card;
-	struct pnp_id * id;		/* contains supported EISA IDs*/
+	struct pnp_card * card;		/* card the device is attached to, none if NULL */
+	struct pnp_driver * driver;
+
+	struct pnp_id		      * id;		/* supported EISA IDs*/
+	struct pnp_resource_table	res;		/* contains the currently chosen resources */
+	struct pnp_resources	      * possible;	/* a list of possible resources */
+	struct pnp_rule_table	      * rule;		/* the current possible resource set */
+	int 				config_mode;	/* flags that determine how the device's resources should be configured */
 
 	void * protocol_data;		/* Used to store protocol specific data */
-	unsigned char number;		/* must be unique */
 	unsigned short	regs;		/* ISAPnP: supported registers */
-	
-	struct pnp_resources *res;	/* possible resource information */
-	int lock_resources;		/* resources are locked */
-	struct resource io_resource[DEVICE_COUNT_IO];   /* port regions */
-	struct resource mem_resource[DEVICE_COUNT_MEM]; /* memory regions + expansion ROMs */
-	struct resource dma_resource[DEVICE_COUNT_DMA];
-	struct resource irq_resource[DEVICE_COUNT_IRQ];
-
-	struct pnp_driver * driver;	/* pointer to the driver bound to this device */
-	struct	device	    dev;	/* Driver Model device interface */
-	int		    flags;	/* used by protocols */
+	int 		flags;		/* used by protocols */
 	struct proc_dir_entry *procent;	/* device entry in /proc/bus/isapnp */
 };
 
@@ -119,13 +214,14 @@ struct pnp_dev {
 #define protocol_to_pnp_dev(n) list_entry(n, struct pnp_dev, protocol_list)
 #define	to_pnp_dev(n) container_of(n, struct pnp_dev, dev)
 #define pnp_for_each_dev(dev) \
-	for(dev = global_to_pnp_dev(pnp_global.next); \
-	dev != global_to_pnp_dev(&pnp_global); \
-	dev = global_to_pnp_dev(dev->global_list.next))
+	for((dev) = global_to_pnp_dev(pnp_global.next); \
+	(dev) != global_to_pnp_dev(&pnp_global); \
+	(dev) = global_to_pnp_dev((dev)->global_list.next))
 #define card_for_each_dev(card,dev) \
 	for((dev) = card_to_pnp_dev((card)->devices.next); \
 	(dev) != card_to_pnp_dev(&(card)->devices); \
 	(dev) = card_to_pnp_dev((dev)->card_list.next))
+#define pnp_dev_name(dev) (dev)->dev.name
 
 static inline void *pnp_get_drvdata (struct pnp_dev *pdev)
 {
@@ -152,6 +248,12 @@ struct pnp_fixup {
 	void (*quirk_function)(struct pnp_dev *dev);	/* fixup function */
 };
 
+/* config modes */
+#define PNP_CONFIG_AUTO		0x0001	/* Use the Resource Configuration Engine to determine resource settings */
+#define PNP_CONFIG_MANUAL	0x0002	/* the config has been manually specified */
+#define PNP_CONFIG_FORCE	0x0004	/* disables validity checking */
+#define PNP_CONFIG_INVALID	0x0008	/* If this flag is set, the pnp layer will refuse to activate the device */
+
 /* capabilities */
 #define PNP_READ		0x0001
 #define PNP_WRITE		0x0002
@@ -165,14 +267,14 @@ struct pnp_fixup {
 				 ((dev)->capabilities & PNP_WRITE))
 #define pnp_can_disable(dev)	(((dev)->protocol) && ((dev)->protocol->disable) && \
 				 ((dev)->capabilities & PNP_DISABLE))
-#define pnp_can_configure(dev)	((!(dev)->active) && ((dev)->capabilities & PNP_CONFIGURABLE))
+#define pnp_can_configure(dev)	((!(dev)->active) && ((dev)->config_mode & PNP_CONFIG_AUTO) && \
+				 ((dev)->capabilities & PNP_CONFIGURABLE))
 
 /* status */
-#define PNP_INIT		0x0000
-#define PNP_READY		0x0001
-#define PNP_ATTACHED		0x0002
-#define PNP_BUSY		0x0004
-#define PNP_FAULTY		0x0008
+#define PNP_READY		0x0000
+#define PNP_ATTACHED		0x0001
+#define PNP_BUSY		0x0002
+#define PNP_FAULTY		0x0004
 
 
 /*
@@ -180,21 +282,21 @@ struct pnp_fixup {
  */
 
 struct pnp_id {
-	char id[7];
+	char id[PNP_ID_LEN];
 	struct pnp_id * next;
 };
 
 struct pnp_device_id {
-	char id[7];
+	char id[PNP_ID_LEN];
 	unsigned long driver_data;	/* data private to the driver */
 };
 
-struct pnp_card_device_id {
-	char id[7];
+struct pnp_card_id {
+	char id[PNP_ID_LEN];
 	unsigned long driver_data;	/* data private to the driver */
 	struct {
-		char id[7];
-	} devs[MAX_DEVICES];		/* logical devices */
+		char id[PNP_ID_LEN];
+	} devs[PNP_MAX_DEVICES];	/* logical devices */
 };
 
 #define PNP_DRIVER_DO_NOT_ACTIVATE	(1<<0)
@@ -216,9 +318,9 @@ struct pnp_driver {
 struct pnpc_driver {
 	struct list_head node;
 	char *name;
-	const struct pnp_card_device_id *id_table;
+	const struct pnp_card_id *id_table;
 	unsigned int flags;
-	int  (*probe)  (struct pnp_card *card, const struct pnp_card_device_id *card_id);
+	int  (*probe)  (struct pnp_card *card, const struct pnp_card_id *card_id);
 	void (*remove) (struct pnp_card *card);
 	struct device_driver driver;
 };
@@ -227,135 +329,16 @@ struct pnpc_driver {
 
 
 /*
- * Resource Management
- */
-
-#define pnp_flags_valid(resrc)	(((resrc)->flags & IORESOURCE_UNSET) == 0 && \
-				 ((resrc)->flags & (IORESOURCE_IO|IORESOURCE_MEM|IORESOURCE_IRQ|IORESOURCE_DMA)) != 0)
-
-/* Use these instead of directly reading pnp_dev to get resource information */
-#define pnp_port_start(dev,bar)	((dev)->io_resource[(bar)].start)
-#define pnp_port_end(dev,bar)	((dev)->io_resource[(bar)].end)
-#define pnp_port_flags(dev,bar)	((dev)->io_resource[(bar)].flags)
-#define pnp_port_valid(dev,bar)	pnp_flags_valid(&(dev)->io_resource[(bar)])
-#define pnp_port_len(dev,bar) \
-	((pnp_port_start((dev),(bar)) == 0 &&	\
-	  pnp_port_end((dev),(bar)) ==		\
-	  pnp_port_start((dev),(bar))) ? 0 :	\
-	  					\
-	 (pnp_port_end((dev),(bar)) -		\
-	  pnp_port_start((dev),(bar)) + 1))
-
-#define pnp_mem_start(dev,bar)	((dev)->mem_resource[(bar)].start)
-#define pnp_mem_end(dev,bar)	((dev)->mem_resource[(bar)].end)
-#define pnp_mem_flags(dev,bar)	((dev)->mem_resource[(bar)].flags)
-#define pnp_mem_valid(dev,bar)	pnp_flags_valid(&(dev)->mem_resource[(bar)])
-#define pnp_mem_len(dev,bar) \
-	((pnp_mem_start((dev),(bar)) == 0 &&	\
-	  pnp_mem_end((dev),(bar)) ==		\
-	  pnp_mem_start((dev),(bar))) ? 0 :	\
-	  					\
-	 (pnp_mem_end((dev),(bar)) -		\
-	  pnp_mem_start((dev),(bar)) + 1))
-
-#define pnp_irq(dev,bar)	((dev)->irq_resource[(bar)].start)
-#define pnp_irq_flags(dev,bar)	((dev)->irq_resource[(bar)].flags)
-#define pnp_irq_valid(dev,bar)	pnp_flags_valid(&(dev)->irq_resource[(bar)])
-
-#define pnp_dma(dev,bar)	((dev)->dma_resource[(bar)].start)
-#define pnp_dma_flags(dev,bar)	((dev)->dma_resource[(bar)].flags)
-#define pnp_dma_valid(dev,bar)	pnp_flags_valid(&(dev)->dma_resource[(bar)])
-
-#define PNP_PORT_FLAG_16BITADDR	(1<<0)
-#define PNP_PORT_FLAG_FIXED	(1<<1)
-
-struct pnp_port {
-	unsigned short min;		/* min base number */
-	unsigned short max;		/* max base number */
-	unsigned char align;		/* align boundary */
-	unsigned char size;		/* size of range */
-	unsigned char flags;		/* port flags */
-	unsigned char pad;		/* pad */
-	struct pnp_resources *res;	/* parent */
-	struct pnp_port *next;		/* next port */
-};
-
-struct pnp_irq {
-	unsigned short map;		/* bitmaks for IRQ lines */
-	unsigned char flags;		/* IRQ flags */
-	unsigned char pad;		/* pad */
-	struct pnp_resources *res;	/* parent */
-	struct pnp_irq *next;		/* next IRQ */
-};
-
-struct pnp_dma {
-	unsigned char map;		/* bitmask for DMA channels */
-	unsigned char flags;		/* DMA flags */
-	struct pnp_resources *res;	/* parent */
-	struct pnp_dma *next;		/* next port */
-};
-
-struct pnp_mem {
-	unsigned int min;		/* min base number */
-	unsigned int max;		/* max base number */
-	unsigned int align;		/* align boundary */
-	unsigned int size;		/* size of range */
-	unsigned char flags;		/* memory flags */
-	unsigned char pad;		/* pad */
-	struct pnp_resources *res;	/* parent */
-	struct pnp_mem *next;		/* next memory resource */
-};
-
-struct pnp_mem32 {
-	unsigned char data[17];
-	struct pnp_resources *res;	/* parent */
-	struct pnp_mem32 *next;		/* next 32-bit memory resource */
-};
-
-#define PNP_RES_PRIORITY_PREFERRED	0
-#define PNP_RES_PRIORITY_ACCEPTABLE	1
-#define PNP_RES_PRIORITY_FUNCTIONAL	2
-#define PNP_RES_PRIORITY_INVALID	65535
-
-struct pnp_resources {
-	unsigned short priority;	/* priority */
-	unsigned short dependent;	/* dependent resources */
-	struct pnp_port *port;		/* first port */
-	struct pnp_irq *irq;		/* first IRQ */
-	struct pnp_dma *dma;		/* first DMA */
-	struct pnp_mem *mem;		/* first memory resource */
-	struct pnp_mem32 *mem32;	/* first 32-bit memory */
-	struct pnp_dev *dev;		/* parent */
-	struct pnp_resources *dep;	/* dependent resources */
-};
-
-struct pnp_res_cfg {
-	struct resource io_resource[DEVICE_COUNT_IO];	/* I/O ports */
-	struct resource mem_resource[DEVICE_COUNT_MEM]; /* memory regions + expansion ROMs */
-	struct resource dma_resource[DEVICE_COUNT_DMA];
-	struct resource irq_resource[DEVICE_COUNT_IRQ];
-};
-
-struct pnp_cfg {
-	struct pnp_port *port[8];
-	struct pnp_irq *irq[2];
-	struct pnp_dma *dma[2];
-	struct pnp_mem *mem[4];
-	struct pnp_res_cfg request;
-};
-
-
-/* 
  * Protocol Management
  */
 
 struct pnp_protocol {
 	struct list_head	protocol_list;
-	char			name[DEVICE_NAME_SIZE];
+	char		      * name;
 
-	/* functions */
-	int (*get)(struct pnp_dev *dev);
-	int (*set)(struct pnp_dev *dev, struct pnp_cfg *config);
+	/* resource control functions */
+	int (*get)(struct pnp_dev *dev, struct pnp_resource_table *res);
+	int (*set)(struct pnp_dev *dev, struct pnp_resource_table *res);
 	int (*disable)(struct pnp_dev *dev);
 
 	/* used by pnp layer only (look but don't touch) */
@@ -384,6 +367,8 @@ void pnp_unregister_protocol(struct pnp_protocol *protocol);
 int pnp_add_device(struct pnp_dev *dev);
 void pnp_remove_device(struct pnp_dev *dev);
 extern struct list_head pnp_global;
+int pnp_device_attach(struct pnp_dev *pnp_dev);
+void pnp_device_detach(struct pnp_dev *pnp_dev);
 
 /* resource */
 struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent);
@@ -393,29 +378,42 @@ int pnp_add_irq_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data);
 int pnp_add_dma_resource(struct pnp_dev *dev, int depnum, struct pnp_dma *data);
 int pnp_add_port_resource(struct pnp_dev *dev, int depnum, struct pnp_port *data);
 int pnp_add_mem_resource(struct pnp_dev *dev, int depnum, struct pnp_mem *data);
-int pnp_add_mem32_resource(struct pnp_dev *dev, int depnum, struct pnp_mem32 *data);
-int pnp_init_res_cfg(struct pnp_res_cfg *template);
-int pnp_activate_dev(struct pnp_dev *dev, struct pnp_res_cfg *template);
+void pnp_init_resource_table(struct pnp_resource_table *table);
+int pnp_generate_rule(struct pnp_dev * dev, int depnum, struct pnp_rule_table * rule);
+
+/* manager */
+int pnp_activate_dev(struct pnp_dev *dev);
 int pnp_disable_dev(struct pnp_dev *dev);
-int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, struct pnp_res_cfg *template);
 void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size);
+int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode);
+int pnp_auto_config_dev(struct pnp_dev *dev);
 
 /* driver */
 int compare_pnp_id(struct pnp_id * pos, const char * id);
 int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev);
 int pnp_register_driver(struct pnp_driver *drv);
 void pnp_unregister_driver(struct pnp_driver *drv);
-int pnp_device_attach(struct pnp_dev *pnp_dev);
-void pnp_device_detach(struct pnp_dev *pnp_dev);
+
+/* support */
+int pnp_is_active(struct pnp_dev * dev);
+unsigned char * pnp_parse_current_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res);
+unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char * end, struct pnp_dev * dev);
+unsigned char * pnp_write_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res);
 
 #else
 
 /* just in case anyone decides to call these without PnP Support Enabled */
+
+/* core */
 static inline int pnp_register_protocol(struct pnp_protocol *protocol) { return -ENODEV; }
 static inline void pnp_unregister_protocol(struct pnp_protocol *protocol) { }
 static inline int pnp_init_device(struct pnp_dev *dev) { return -ENODEV; }
 static inline int pnp_add_device(struct pnp_dev *dev) { return -ENODEV; }
 static inline void pnp_remove_device(struct pnp_dev *dev) { }
+static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; }
+static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { ; }
+
+/* resource */
 static inline struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent) { return NULL; }
 static inline struct pnp_resources * pnp_find_resources(struct pnp_dev *dev, int depnum) { return NULL; }
 static inline int pnp_get_max_depnum(struct pnp_dev *dev) { return -ENODEV; }
@@ -423,19 +421,27 @@ static inline int pnp_add_irq_resource(struct pnp_dev *dev, int depnum, struct p
 static inline int pnp_add_dma_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; }
 static inline int pnp_add_port_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; }
 static inline int pnp_add_mem_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; }
-static inline int pnp_add_mem32_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; }
-static inline int pnp_init_res_cfg(struct pnp_res_cfg *template) { return -ENODEV; }
-static inline int pnp_activate_dev(struct pnp_dev *dev, struct pnp_res_cfg *template) { return -ENODEV; }
+static inline void pnp_init_resource_table(struct pnp_resource_table *table) { ; }
+static inline int pnp_generate_rule(struct pnp_dev * dev, int depnum, struct pnp_rule_table * rule) { return -ENODEV; }
+
+/* manager */
+static inline int pnp_activate_dev(struct pnp_dev *dev) { return -ENODEV; }
 static inline int pnp_disable_dev(struct pnp_dev *dev) { return -ENODEV; }
-static inline int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, struct pnp_res_cfg *template) { return -ENODEV; }
 static inline void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size) { ; }
+static inline int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode) { return -ENODEV; }
+static inline int pnp_auto_config_dev(struct pnp_dev *dev) { return -ENODEV; }
+
+/* driver */
 static inline int compare_pnp_id(struct list_head * id_list, const char * id) { return -ENODEV; }
 static inline int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) { return -ENODEV; }
 static inline int pnp_register_driver(struct pnp_driver *drv) { return -ENODEV; }
 static inline void pnp_unregister_driver(struct pnp_driver *drv) { ; }
 
-static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; }
-static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { ; }
+/* support */
+static inline int pnp_is_active(struct pnp_dev * dev) { return -ENODEV; )
+static inline unsigned char * pnp_parse_current_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res) { return NULL; }
+static inline unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char * end, struct pnp_dev * dev) { return NULL; }
+static inline unsigned char * pnp_write_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res) { return NULL; )
 
 #endif /* CONFIG_PNP */
 
@@ -458,6 +464,7 @@ void pnpc_detach(struct pnp_card *card);
 
 #else
 
+/* card */
 static inline int pnpc_add_card(struct pnp_card *card) { return -ENODEV; }
 static inline void pnpc_remove_card(struct pnp_card *card) { ; }
 static inline int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev) { return -ENODEV; }
@@ -467,11 +474,12 @@ static inline void pnp_release_card_device(struct pnp_dev *dev) { ; }
 static inline int pnpc_register_driver(struct pnpc_driver *drv) { return -ENODEV; }
 static inline void pnpc_unregister_driver(struct pnpc_driver *drv) { ; }
 static inline int pnpc_add_id(struct pnp_id *id, struct pnp_card *card) { return -ENODEV; }
-static inline int pnpc_attach(struct pnp_card *card) { return -ENODEV; }
-static inline void pnpc_detach(struct pnp_card *card) { ; }
 
 #endif /* CONFIG_PNP_CARD */
 
+#define pnp_err(format, arg...) printk(KERN_ERR "pnp: " format "\n" , ## arg)
+#define pnp_info(format, arg...) printk(KERN_INFO "pnp: " format "\n" , ## arg)
+#define pnp_warn(format, arg...) printk(KERN_WARNING "pnp: " format "\n" , ## arg)
 
 #ifdef DEBUG
 #define pnp_dbg(format, arg...) printk(KERN_DEBUG "pnp: " format "\n" , ## arg)
diff --git a/sound/oss/sb_card.c b/sound/oss/sb_card.c
index 2689d6277418f556ba3205a53b00d937e917592d..999c69afb161726bff61b975c947e63b76b8b96f 100644
--- a/sound/oss/sb_card.c
+++ b/sound/oss/sb_card.c
@@ -1,1035 +1,329 @@
 /*
- * sound/sb_card.c
+ * sound/oss/sb_card.c
  *
- * Detection routine for the Sound Blaster cards.
+ * Detection routine for the ISA Sound Blaster and compatable sound
+ * cards.
  *
+ * This file is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * Version 2 (June 1991). See the "COPYING" file distributed with this
+ * software for more info.
  *
- * Copyright (C) by Hannu Savolainen 1993-1997
+ * This is a complete rewrite of the detection routines. This was
+ * prompted by the PnP API change during v2.5 and the ugly state the
+ * code was in.
  *
- * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
- * Version 2 (June 1991). See the "COPYING" file distributed with this software
- * for more info.
+ * Copyright (C) by Paul Laufer 2002. Based on code originally by
+ * Hannu Savolainen which was modified by many others over the
+ * years. Authors specifically mentioned in the previous version were:
+ * Daniel Stone, Alessandro Zummo, Jeff Garzik, Arnaldo Carvalho de
+ * Melo, Daniel Church, and myself.
  *
- * 26-11-1999 Patched to compile without ISA PnP support in the
- * kernel - Daniel Stone (tamriel@ductape.net) 
- *
- * 06-01-2000 Refined and bugfixed ISA PnP support, added
- *  CMI 8330 support - Alessandro Zummo <azummo@ita.flashnet.it>
- *
- * 18-01-2000 Separated sb_card and sb_common
- *  Jeff Garzik <jgarzik@pobox.com>
- *
- * 04-02-2000 Added Soundblaster AWE 64 PnP support, isapnpjump
- *  Alessandro Zummo <azummo@ita.flashnet.it>
- *
- * 11-02-2000 Added Soundblaster AWE 32 PnP support, refined PnP code
- *  Alessandro Zummo <azummo@ita.flashnet.it>
- *
- * 13-02-2000 Hopefully fixed awe/sb16 related bugs, code cleanup
- *  Alessandro Zummo <azummo@ita.flashnet.it>
- *
- * 13-03-2000 Added some more cards, thanks to Torsten Werner.
- *  Removed joystick and wavetable code, there are better places for them.
- *  Code cleanup plus some fixes. 
- *  Alessandro Zummo <azummo@ita.flashnet.it>
- * 
- * 26-03-2000 Fixed acer, esstype and sm_games module options.
- *  Alessandro Zummo <azummo@ita.flashnet.it>
- *
- * 12-04-2000 ISAPnP cleanup, reorg, fixes, and multiple card support.
- *  Thanks to Gaël Quéri and Alessandro Zummo for testing and fixes.
- *  Paul E. Laufer <pelaufer@csupomona.edu>
- *
- * 06-05-2000 added another card. Daniel M. Newman <dmnewman@pobox.com>
- *
- * 25-05-2000 Added Creative SB AWE64 Gold (CTL00B2). 
- * 	Pål-Kristian Engstad <engstad@att.net>
- *
- * 12-08-2000 Added Creative SB32 PnP (CTL009F).
- * 	Kasatenko Ivan Alex. <skywriter@rnc.ru>
- *
- * 21-09-2000 Got rid of attach_sbmpu
- * 	Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- *
- * 28-10-2000 Added pnplegacy support
- * 	Daniel Church <dchurch@mbhs.edu>
- *
- * 01-10-2001 Added a new flavor of Creative SB AWE64 PnP (CTL00E9).
- *      Jerome Cornet <jcornet@free.fr>
+ * 02-05-2003 Original Release, Paul Laufer <paul@laufernet.com>
+ * 02-07-2003 Bug made it into first release. Take two.
  */
 
 #include <linux/config.h>
-#include <linux/mca.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
-#include <linux/isapnp.h>
-
+#ifdef CONFIG_MCA
+#include <linux/mca.h>
+#endif /* CONFIG_MCA */
 #include "sound_config.h"
-
 #include "sb_mixer.h"
 #include "sb.h"
-
-#ifdef __ISAPNP__
-#define SB_CARDS_MAX 5
-#else
-#define SB_CARDS_MAX 1
+#ifdef CONFIG_PNP_CARD
+#include <linux/pnp.h>
 #endif
+#include "sb_card.h"
 
-static int sbmpu[SB_CARDS_MAX] = {0};
-static int sb_cards_num = 0;
+MODULE_DESCRIPTION("OSS Soundblaster ISA PnP and legacy sound driver");
+MODULE_LICENSE("GPL");
 
 extern void *smw_free;
 
-/*
- *    Note DMA2 of -1 has the right meaning in the SB16 driver as well
- *    as here. It will cause either an error if it is needed or a fallback
- *    to the 8bit channel.
- */
-
 static int __initdata mpu_io	= 0;
 static int __initdata io	= -1;
 static int __initdata irq	= -1;
 static int __initdata dma	= -1;
-static int __initdata dma16	= -1;   /* Set this for modules that need it */
-static int __initdata type	= 0;    /* Can set this to a specific card type */
-static int __initdata esstype   = 0;	/* ESS chip type */
-static int __initdata acer 	= 0;	/* Do acer notebook init? */
-static int __initdata sm_games 	= 0;	/* Logitech soundman games? */
+static int __initdata dma16	= -1;
+static int __initdata type	= 0; /* Can set this to a specific card type */
+static int __initdata esstype   = 0; /* ESS chip type */
+static int __initdata acer 	= 0; /* Do acer notebook init? */
+static int __initdata sm_games 	= 0; /* Logitech soundman games? */
 
-static void __init attach_sb_card(struct address_info *hw_config)
-{
-	if(!sb_dsp_init(hw_config, THIS_MODULE))
-		hw_config->slots[0] = -1;
-}
+struct sb_card_config *legacy = NULL;
 
-static int __init probe_sb(struct address_info *hw_config)
-{
-	struct sb_module_options sbmo;
+#ifdef CONFIG_PNP_CARD
+static int __initdata pnp       = 1;
+/*
+static int __initdata uart401	= 0;
+*/
+#else
+static int __initdata pnp       = 0;
+#endif
 
-	if (hw_config->io_base == -1 || hw_config->dma == -1 || hw_config->irq == -1)
-	{
-		printk(KERN_ERR "sb: I/O, IRQ, and DMA are mandatory\n");
-		return -EINVAL;
+module_param(io, int, 000);
+MODULE_PARM_DESC(io,       "Soundblaster i/o base address (0x220,0x240,0x260,0x280)");
+module_param(irq, int, 000);
+MODULE_PARM_DESC(irq,	   "IRQ (5,7,9,10)");
+module_param(dma, int, 000);
+MODULE_PARM_DESC(dma,	   "8-bit DMA channel (0,1,3)");
+module_param(dma16, int, 000);
+MODULE_PARM_DESC(dma16,	   "16-bit DMA channel (5,6,7)");
+module_param(mpu_io, int, 000);
+MODULE_PARM_DESC(mpu_io,   "MPU base address");
+module_param(type, int, 000);
+MODULE_PARM_DESC(type,	   "You can set this to specific card type (doesn't " \
+		 "work with pnp)");
+module_param(sm_games, int, 000);
+MODULE_PARM_DESC(sm_games, "Enable support for Logitech soundman games " \
+		 "(doesn't work with pnp)");
+module_param(esstype, int, 000);
+MODULE_PARM_DESC(esstype,  "ESS chip type (doesn't work with pnp)");
+module_param(acer, int, 000);
+MODULE_PARM_DESC(acer,	   "Set this to detect cards in some ACER notebooks "\
+		 "(doesn't work with pnp)");
+
+#ifdef CONFIG_PNP_CARD
+module_param(pnp, int, 000);
+MODULE_PARM_DESC(pnp,     "Went set to 0 will disable detection using PnP. "\
+		  "Default is 1.\n");
+/* Not done yet.... */
+/*
+module_param(uart401, int, 000);
+MODULE_PARM_DESC(uart401,  "When set to 1, will attempt to detect and enable"\
+		 "the mpu on some clones");
+*/
+#endif /* CONFIG_PNP_CARD */
+
+/* OSS subsystem card registration shared by PnP and legacy routines */
+static int sb_register_oss(struct sb_card_config *scc, struct sb_module_options *sbmo)
+{
+	if(!sb_dsp_detect(&scc->conf, 0, 0, sbmo)) {
+		printk(KERN_ERR "sb: Failed DSP Detect.\n");
+		kfree(scc);
+		return -ENODEV;
 	}
-
-#ifdef CONFIG_MCA
-	/* MCA code added by ZP Gu (zpg@castle.net) */
-	if (MCA_bus) {               /* no multiple REPLY card probing */
-		int slot;
-		u8 pos2, pos3, pos4;
-
-		slot = mca_find_adapter( 0x5138, 0 );
-		if( slot == MCA_NOTFOUND ) 
-		{
-			slot = mca_find_adapter( 0x5137, 0 );
-
-			if (slot != MCA_NOTFOUND)
-				mca_set_adapter_name( slot, "REPLY SB16 & SCSI Adapter" );
-		}
-		else
-		{
-			mca_set_adapter_name( slot, "REPLY SB16 Adapter" );
-		}
-
-		if (slot != MCA_NOTFOUND) 
-		{
-			mca_mark_as_used(slot);
-			pos2 = mca_read_stored_pos( slot, 2 );
-			pos3 = mca_read_stored_pos( slot, 3 );
-			pos4 = mca_read_stored_pos( slot, 4 );
-
-			if (pos2 & 0x4) 
-			{
-				/* enabled? */
-				static unsigned short irq[] = { 0, 5, 7, 10 };
-				/*
-				static unsigned short midiaddr[] = {0, 0x330, 0, 0x300 };
-       				*/
-
-				hw_config->io_base = 0x220 + 0x20 * (pos2 >> 6);
-				hw_config->irq = irq[(pos4 >> 5) & 0x3];
-				hw_config->dma = pos3 & 0xf;
-				/* Reply ADF wrong on High DMA, pos[1] should start w/ 00 */
-				hw_config->dma2 = (pos3 >> 4) & 0x3;
-				if (hw_config->dma2 == 0)
-					hw_config->dma2 = hw_config->dma;
-				else
-					hw_config->dma2 += 4;
-				/*
-					hw_config->driver_use_2 = midiaddr[(pos2 >> 3) & 0x3];
-				*/
-	
-				printk(KERN_INFO "sb: Reply MCA SB at slot=%d \
-iobase=0x%x irq=%d lo_dma=%d hi_dma=%d\n",
-						slot+1,
-				        	hw_config->io_base, hw_config->irq,
-	        				hw_config->dma, hw_config->dma2);
-			}
-			else
-			{
-				printk (KERN_INFO "sb: Reply SB Base I/O address disabled\n");
-			}
-		}
+	if(!sb_dsp_init(&scc->conf, THIS_MODULE)) {
+		printk(KERN_ERR "sb: Failed DSP init.\n");
+		kfree(scc);
+		return -ENODEV;
+	}
+	if(scc->mpucnf.io_base > 0) {
+		scc->mpu = 1;
+		printk(KERN_INFO "sb: Turning on MPU\n");
+		if(!probe_sbmpu(&scc->mpucnf, THIS_MODULE))
+			scc->mpu = 0;
 	}
-#endif
-
-	/* Setup extra module options */
-
-	sbmo.acer 	= acer;
-	sbmo.sm_games	= sm_games;
-	sbmo.esstype	= esstype;
 
-	return sb_dsp_detect(hw_config, 0, 0, &sbmo);
+	return 1;
 }
 
-static void __exit unload_sb(struct address_info *hw_config, int card)
+static void sb_unload(struct sb_card_config *scc)
 {
-	if(hw_config->slots[0]!=-1)
-		sb_dsp_unload(hw_config, sbmpu[card]);
+	sb_dsp_unload(&scc->conf, 0);
+	if(scc->mpu)
+		unload_sbmpu(&scc->mpucnf);
+	kfree(scc);
 }
 
-static struct address_info cfg[SB_CARDS_MAX];
-static struct address_info cfg_mpu[SB_CARDS_MAX];
-
-struct pci_dev 	*sb_dev[SB_CARDS_MAX] 	= {NULL}, 
-		*mpu_dev[SB_CARDS_MAX]	= {NULL},
-		*opl_dev[SB_CARDS_MAX]	= {NULL};
-
-
-#ifdef __ISAPNP__
-static int isapnp	= 1;
-static int isapnpjump	= 0;
-static int multiple	= 1;
-static int pnplegacy	= 0;
-static int reverse	= 0;
-static int uart401	= 0;
-
-static int audio_activated[SB_CARDS_MAX] = {0};
-static int mpu_activated[SB_CARDS_MAX]   = {0};
-static int opl_activated[SB_CARDS_MAX]   = {0};
-#else
-static int isapnp	= 0;
-static int multiple	= 0;
-static int pnplegacy	= 0;
-#endif
-
-MODULE_DESCRIPTION("Soundblaster driver");
-MODULE_LICENSE("GPL");
-
-MODULE_PARM(io,		"i");
-MODULE_PARM(irq,	"i");
-MODULE_PARM(dma,	"i");
-MODULE_PARM(dma16,	"i");
-MODULE_PARM(mpu_io,	"i");
-MODULE_PARM(type,	"i");
-MODULE_PARM(sm_games,	"i");
-MODULE_PARM(esstype,	"i");
-MODULE_PARM(acer,	"i");
-
-#ifdef __ISAPNP__
-MODULE_PARM(isapnp,	"i");
-MODULE_PARM(isapnpjump,	"i");
-MODULE_PARM(multiple,	"i");
-MODULE_PARM(pnplegacy,	"i");
-MODULE_PARM(reverse,	"i");
-MODULE_PARM(uart401,	"i");
-MODULE_PARM_DESC(isapnp,	"When set to 0, Plug & Play support will be disabled");
-MODULE_PARM_DESC(isapnpjump,	"Jumps to a specific slot in the driver's PnP table. Use the source, Luke.");
-MODULE_PARM_DESC(multiple,	"When set to 0, will not search for multiple cards");
-MODULE_PARM_DESC(pnplegacy,	"When set to 1, will search for a legacy SB card along with any PnP cards.");
-MODULE_PARM_DESC(reverse,	"When set to 1, will reverse ISAPnP search order");
-MODULE_PARM_DESC(uart401,	"When set to 1, will attempt to detect and enable the mpu on some clones");
-#endif
-
-MODULE_PARM_DESC(io,		"Soundblaster i/o base address (0x220,0x240,0x260,0x280)");
-MODULE_PARM_DESC(irq,		"IRQ (5,7,9,10)");
-MODULE_PARM_DESC(dma,		"8-bit DMA channel (0,1,3)");
-MODULE_PARM_DESC(dma16,		"16-bit DMA channel (5,6,7)");
-MODULE_PARM_DESC(mpu_io,	"Mpu base address");
-MODULE_PARM_DESC(type,		"You can set this to specific card type");
-MODULE_PARM_DESC(sm_games,	"Enable support for Logitech soundman games");
-MODULE_PARM_DESC(esstype,	"ESS chip type");
-MODULE_PARM_DESC(acer,		"Set this to detect cards in some ACER notebooks");
-
-#ifdef __ISAPNP__
-
-/* Please add new entries at the end of the table */
-static struct {
-	char *name; 
-	unsigned short	card_vendor, card_device, 
-			audio_vendor, audio_function,
-			mpu_vendor, mpu_function,
-			opl_vendor, opl_function;
-	short dma, dma2, mpu_io, mpu_irq; /* see sb_init() */
-} sb_isapnp_list[] __initdata = {
-	{"Sound Blaster 16", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0024),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster 16",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0025),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster 16", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0026), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster 16", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0027), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster 16", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0028), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster 16", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0029), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster 16",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002a),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster 16", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002b), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster 16", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster 16", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster 16", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00ed), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster 16", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster 16", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster Vibra16S", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0051), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster Vibra16C", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0070), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster Vibra16CL", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0080), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster Vibra16X", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00F0), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 32", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0039), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 32",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 32",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 32",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-        {"Sound Blaster AWE 32",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 32",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0046),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 32",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0047),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 32",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0048), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 32",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0054), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 32",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009C), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Creative SB32 PnP",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009F),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 64",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009D), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 64 Gold",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009E), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 64 Gold",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00B2),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 64",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C1), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 64",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C3), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 64",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C5), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 64",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C7), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 64",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E4), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
-		0,0,0,0,
-		0,1,1,-1},
-	{"Sound Blaster AWE 64",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E9), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
-		0,0,0,0,
-		0,1,1,-1},
-	{"ESS 1688",
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0968), 
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968),
-		0,0,0,0,
-		0,1,2,-1},
-	{"ESS 1868",
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868),
-		0,0,0,0,
-		0,1,2,-1},
-	{"ESS 1868",
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611),
-		0,0,0,0,
-		0,1,2,-1},
-	{"ESS 1869 PnP AudioDrive", 
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0003), 
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869),
-		0,0,0,0,
-		0,1,2,-1},
-	{"ESS 1869",
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1869), 
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869),
-		0,0,0,0,
-		0,1,2,-1},
-	{"ESS 1878",
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1878), 
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878),
-		0,0,0,0,
-		0,1,2,-1},
-	{"ESS 1879",
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1879), 
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879),
-		0,0,0,0,
-		0,1,2,-1},
-	{"CMI 8330 SoundPRO",
-		ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), 
-		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
-		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
-		0,1,0,-1},
-	{"Diamond DT0197H",
-		ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688), 
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
-		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
-		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
-		0,-1,0,0},
-	{"ALS007",
-		ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
-		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
-		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
-		0,-1,0,0},
-	{"ALS100",
-		ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), 
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
-		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
-		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
-		1,0,0,0},
-	{"ALS110",
-		ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x1001),
-		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x1001),
-		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
-		1,0,0,0},
-	{"ALS120",
-		ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001),
-		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001),
-		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
-		1,0,0,0},
-	{"ALS200",
-		ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0020),
-		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0020),
-		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
-		1,0,0,0},
-	{"RTL3000",
-		ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001),
-		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001),
-		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
-		1,0,0,0},
-	{0}
-};
-
-static struct isapnp_device_id id_table[] __devinitdata = {
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0024),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0025),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0026), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0027), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0028), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0029), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002a),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002b), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00ed), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0051), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0070), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0080), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00F0), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0039), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0048), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0054), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009C), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009F),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009D), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009E), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00B2),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C1), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C3), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C5), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C7), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E4), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
-
-	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E9),
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
-
-	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0968), 
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968), 0 },
-
-	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868), 0 },
-
-	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611), 0 },
-
-	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0003), 
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), 0 },
-
-	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1869), 
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), 0 },
-
-	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1878), 
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878), 0 },
-
-	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1879), 
-		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879), 0 },
-
-	{	ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), 
-		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
-
-	{	ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), 
-		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
-
-	{	ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), 
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
-
-	{	ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688), 
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
-
-	{	ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688), 
-		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
-
-	{	ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688), 
-		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
-
-	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
-
-	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
-		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
-
-	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
-		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
-
-	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), 
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
-
-	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), 
-		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
-
-	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), 
-		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
-
-	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x1001), 0 },
-
-	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
-		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x1001), 0 },
-
-	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
-		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
-
-	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001), 0 },
-
-	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
-		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001), 0 },
-
-	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
-		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
-
-	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0020), 0 },
+/* Register legacy card with OSS subsystem */
+static int sb_init_legacy(void)
+{
+	struct sb_module_options sbmo = {0};
 
-	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
-		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0020), 0 },
+	if((legacy = kmalloc(sizeof(struct sb_card_config), GFP_KERNEL)) == NULL) {
+		printk(KERN_ERR "sb: Error: Could not allocate memory\n");
+		return -ENOMEM;
+	}
+	memset(legacy, 0, sizeof(struct sb_card_config));
 
-	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
-		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
+	legacy->conf.io_base      = io;
+	legacy->conf.irq          = irq;
+	legacy->conf.dma          = dma;
+	legacy->conf.dma2         = dma16;
+	legacy->conf.card_subtype = type;
 
-	{	ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001), 0 },
+	legacy->mpucnf.io_base = mpu_io;
+	legacy->mpucnf.irq     = -1;
+	legacy->mpucnf.dma     = -1;
+	legacy->mpucnf.dma2    = -1;
 
-	{	ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
-		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001), 0 },
+	sbmo.esstype  = esstype;
+	sbmo.sm_games = sm_games;
+	sbmo.acer     = acer;
 
-	{	ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
-		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
-	{0}
-};
+	return sb_register_oss(legacy, &sbmo);
+}
 
-MODULE_DEVICE_TABLE(isapnp, id_table);
+#ifdef CONFIG_PNP_CARD
 
-static struct pci_dev *activate_dev(char *devname, char *resname, struct pci_dev *dev)
+/* Populate the OSS subsystem structures with information from PnP */
+static void sb_dev2cfg(struct pnp_dev *dev, struct sb_card_config *scc)
 {
-	int err;
-
-	/* Device already active? Let's use it */
-	if(dev->active)
-		return(dev);
-	
-	if((err = dev->activate(dev)) < 0) {
-		printk(KERN_ERR "sb: %s %s config failed (out of resources?)[%d]\n", devname, resname, err);
-
-		dev->deactivate(dev);
-
-		return(NULL);
+	scc->conf.io_base   = -1;
+	scc->conf.irq       = -1;
+	scc->conf.dma       = -1;
+	scc->conf.dma2      = -1;
+	scc->mpucnf.io_base = -1;
+	scc->mpucnf.irq     = -1;
+	scc->mpucnf.dma     = -1;
+	scc->mpucnf.dma2    = -1;
+
+	/* All clones layout their PnP tables differently and some use
+	   different logical devices for the MPU */
+	if(!strncmp("CTL",scc->card_id,3)) {
+		scc->conf.io_base   = pnp_port_start(dev,0);
+		scc->conf.irq       = pnp_irq(dev,0);
+		scc->conf.dma       = pnp_dma(dev,0);
+		scc->conf.dma2      = pnp_dma(dev,1);
+		scc->mpucnf.io_base = pnp_port_start(dev,1);
+		return;
 	}
-	return(dev);
-}
-
-static struct pci_dev *sb_init(struct pci_bus *bus, struct address_info *hw_config, struct address_info *mpu_config, int slot, int card)
-{
-
-	/* Configure Audio device */
-	if((sb_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].audio_vendor, sb_isapnp_list[slot].audio_function, NULL)))
-	{
-		int ret;
-		ret = sb_dev[card]->prepare(sb_dev[card]);
-		/* If device is active, assume configured with /proc/isapnp
-		 * and use anyway. Some other way to check this? */
-		if(ret && ret != -EBUSY) {
-			printk(KERN_ERR "sb: ISAPnP found device that could not be autoconfigured.\n");
-			return(NULL);
-		}
-		if(ret == -EBUSY)
-			audio_activated[card] = 1;
-		
-		if((sb_dev[card] = activate_dev(sb_isapnp_list[slot].name, "sb", sb_dev[card])))
-		{
-			hw_config->io_base 	= sb_dev[card]->resource[0].start;
-			hw_config->irq 		= sb_dev[card]->irq_resource[0].start;
-			hw_config->dma 		= sb_dev[card]->dma_resource[sb_isapnp_list[slot].dma].start;
-			if(sb_isapnp_list[slot].dma2 != -1)
-				hw_config->dma2 = sb_dev[card]->dma_resource[sb_isapnp_list[slot].dma2].start;
-			else
-				hw_config->dma2 = -1;
-		} else
-			return(NULL);
-	} else
-		return(NULL);
-
-	/* Cards with separate OPL3 device (ALS, CMI, etc.)
-	 * This is just to activate the device so the OPL module can use it */
-	if(sb_isapnp_list[slot].opl_vendor || sb_isapnp_list[slot].opl_function) {
-		if((opl_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].opl_vendor, sb_isapnp_list[slot].opl_function, NULL))) {
-			int ret = opl_dev[card]->prepare(opl_dev[card]);
-			/* If device is active, assume configured with
-			 * /proc/isapnp and use anyway */
-			if(ret && ret != -EBUSY) {
-				printk(KERN_ERR "sb: OPL device could not be autoconfigured.\n");
-				return(sb_dev[card]);
-			}
-			if(ret == -EBUSY)
-				opl_activated[card] = 1;
-
-			/* Some have irq and dma for opl. the opl3 driver wont
-			 * use 'em so don't configure 'em and hope it works -PEL */
-			opl_dev[card]->irq_resource[0].flags = 0;
-			opl_dev[card]->dma_resource[0].flags = 0;
-
-			opl_dev[card] = activate_dev(sb_isapnp_list[slot].name, "opl3", opl_dev[card]);
-		} else
-			printk(KERN_ERR "sb: %s isapnp panic: opl3 device not found\n", sb_isapnp_list[slot].name);
+	if(!strncmp("ESS",scc->card_id,3)) {
+		scc->conf.io_base   = pnp_port_start(dev,0);
+		scc->conf.irq       = pnp_irq(dev,0);
+		scc->conf.dma       = pnp_dma(dev,0);
+		scc->conf.dma2      = pnp_dma(dev,1);
+	       	scc->mpucnf.io_base = pnp_port_start(dev,2);
+		return;
 	}
-
-	/* Cards with MPU as part of Audio device (CTL and ESS) */
-	if(!sb_isapnp_list[slot].mpu_vendor) {
-		mpu_config->io_base	= sb_dev[card]->resource[sb_isapnp_list[slot].mpu_io].start;
-		return(sb_dev[card]);
+	if(!strncmp("CMI",scc->card_id,3)) {
+		scc->conf.io_base = pnp_port_start(dev,0);
+		scc->conf.irq     = pnp_irq(dev,0);
+		scc->conf.dma     = pnp_dma(dev,0);
+		scc->conf.dma2    = pnp_dma(dev,1);
+		return;
 	}
-	
-	/* Cards with separate MPU device (ALS, CMI, etc.) */
-	if(!uart401)
-		return(sb_dev[card]);
-	if((mpu_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].mpu_vendor, sb_isapnp_list[slot].mpu_function, NULL)))
-	{
-		int ret = mpu_dev[card]->prepare(mpu_dev[card]);
-		/* If device is active, assume configured with /proc/isapnp
-		 * and use anyway */
-		if(ret && ret != -EBUSY) {
-			printk(KERN_ERR "sb: MPU device could not be autoconfigured.\n");
-			return(sb_dev[card]);
-		}
-		if(ret == -EBUSY)
-			mpu_activated[card] = 1;
-		
-		/* Some cards ask for irq but don't need them - azummo */
-		if(sb_isapnp_list[slot].mpu_irq == -1)
-			mpu_dev[card]->irq_resource[0].flags = 0;
-		
-		if((mpu_dev[card] = activate_dev(sb_isapnp_list[slot].name, "mpu", mpu_dev[card]))) {
-			mpu_config->io_base = mpu_dev[card]->resource[sb_isapnp_list[slot].mpu_io].start;
-			if(sb_isapnp_list[slot].mpu_irq != -1)
-				mpu_config->irq = mpu_dev[card]->irq_resource[sb_isapnp_list[slot].mpu_irq].start;
+	if(!strncmp("RWB",scc->card_id,3)) {
+		scc->conf.io_base = pnp_port_start(dev,0);
+		scc->conf.irq     = pnp_irq(dev,0);
+		scc->conf.dma     = pnp_dma(dev,0);
+		return;
+	}
+	if(!strncmp("ALS",scc->card_id,3)) {
+		if(!strncmp("ALS0007",scc->card_id,7)) {
+			scc->conf.io_base = pnp_port_start(dev,0);
+			scc->conf.irq     = pnp_irq(dev,0);
+			scc->conf.dma     = pnp_dma(dev,0);
+		} else {
+			scc->conf.io_base = pnp_port_start(dev,0);
+			scc->conf.irq     = pnp_irq(dev,0);
+			scc->conf.dma     = pnp_dma(dev,1);
+			scc->conf.dma2    = pnp_dma(dev,0);
 		}
+		return;
+	}
+	if(!strncmp("RTL",scc->card_id,3)) {
+		scc->conf.io_base = pnp_port_start(dev,0);
+		scc->conf.irq     = pnp_irq(dev,0);
+		scc->conf.dma     = pnp_dma(dev,1);
+		scc->conf.dma2    = pnp_dma(dev,0);
 	}
-	else
-		printk(KERN_ERR "sb: %s isapnp panic: mpu not found\n", sb_isapnp_list[slot].name);
-	
-	return(sb_dev[card]);
 }
 
-static int __init sb_isapnp_init(struct address_info *hw_config, struct address_info *mpu_config, struct pci_bus *bus, int slot, int card)
+/* Probe callback function for the PnP API */
+static int sb_pnp_probe(struct pnp_card *card, const struct pnp_card_id *card_id)
 {
-	char *busname = bus->name[0] ? bus->name : sb_isapnp_list[slot].name;
-
-	printk(KERN_INFO "sb: %s detected\n", busname); 
-
-	/* Initialize this baby. */
-
-	if(sb_init(bus, hw_config, mpu_config, slot, card)) {
-		/* We got it. */
-		
-		printk(KERN_NOTICE "sb: ISAPnP reports '%s' at i/o %#x, irq %d, dma %d, %d\n",
-		       busname,
-		       hw_config->io_base, hw_config->irq, hw_config->dma,
-		       hw_config->dma2);
-		return 1;
+	struct sb_card_config *scc;
+	struct sb_module_options sbmo = {0}; /* Default to 0 for PnP */
+	struct pnp_dev *dev = pnp_request_card_device(card, card_id->devs[0].id, NULL);
+	
+	if(!dev){
+		return -EBUSY;
 	}
-	else
-		printk(KERN_INFO "sb: Failed to initialize %s\n", busname);
 
-	return 0;
-}
-
-static int __init sb_isapnp_probe(struct address_info *hw_config, struct address_info *mpu_config, int card)
-{
-	static int first = 1;
-	int i;
+	if((scc = kmalloc(sizeof(struct sb_card_config), GFP_KERNEL)) == NULL) {
+		printk(KERN_ERR "sb: Error: Could not allocate memory\n");
+		return -ENOMEM;
+	}
+	memset(scc, 0, sizeof(struct sb_card_config));
 
-	/* Count entries in sb_isapnp_list */
-	for (i = 0; sb_isapnp_list[i].card_vendor != 0; i++);
-	i--;
+	printk(KERN_INFO "sb: PnP: Found Card Named = \"%s\", Card PnP id = " \
+	       "%s, Device PnP id = %s\n", dev->dev.name, card_id->id,
+	       dev->id->id);
 
-	/* Check and adjust isapnpjump */
-	if( isapnpjump < 0 || isapnpjump > i) {
-		isapnpjump = reverse ? i : 0;
-		printk(KERN_ERR "sb: Valid range for isapnpjump is 0-%d. Adjusted to %d.\n", i, isapnpjump);
-	}
+	scc->card_id = card_id->id;
+	scc->dev_id = dev->id->id;
+	sb_dev2cfg(dev, scc);
 
-	if(!first || !reverse)
-		i = isapnpjump;
-	first = 0;
-	while(sb_isapnp_list[i].card_vendor != 0) {
-		static struct pci_bus *bus = NULL;
+	printk(KERN_INFO "sb: PnP:      Detected at: io=0x%x, irq=%d, " \
+	       "dma=%d, dma16=%d\n", scc->conf.io_base, scc->conf.irq,
+	       scc->conf.dma, scc->conf.dma2);
 
-		while ((bus = isapnp_find_card(
-				sb_isapnp_list[i].card_vendor,
-				sb_isapnp_list[i].card_device,
-				bus))) {
-	
-			if(sb_isapnp_init(hw_config, mpu_config, bus, i, card)) {
-				isapnpjump = i; /* start next search from here */
-				return 0;
-			}
-		}
-		i += reverse ? -1 : 1;
-	}
+	pnpc_set_drvdata(card, scc);
 
-	return -ENODEV;
+	return sb_register_oss(scc, &sbmo);
 }
-#endif
 
-static int __init init_sb(void)
+static void sb_pnp_remove(struct pnp_card *card)
 {
-	int card, max = (multiple && isapnp) ? SB_CARDS_MAX : 1;
+	struct sb_card_config *scc = pnpc_get_drvdata(card);
 
-	printk(KERN_INFO "Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
-	
-	for(card = 0; card < max; card++, sb_cards_num++) {
-#ifdef __ISAPNP__
-		/* Please remember that even with __ISAPNP__ defined one
-		 * should still be able to disable PNP support for this 
-		 * single driver! */
-		if((!pnplegacy||card>0) && isapnp && (sb_isapnp_probe(&cfg[card], &cfg_mpu[card], card) < 0) ) {
-			if(!sb_cards_num) {
-				/* Found no ISAPnP cards, so check for a non-pnp
-				 * card and set the detection loop for 1 cycle
-				 */
-				printk(KERN_NOTICE "sb: No ISAPnP cards found, trying standard ones...\n");
-				isapnp = 0;
-				max = 1;
-			} else
-				/* found all the ISAPnP cards so exit the
-				 * detection loop. */
-				break;
-		}
-#endif
+	if(!scc)
+		return;
 
-		if(!isapnp || (pnplegacy&&card==0)) {
-			cfg[card].io_base	= io;
-			cfg[card].irq		= irq;
-			cfg[card].dma		= dma;
-			cfg[card].dma2		= dma16;
-		}
+	printk(KERN_INFO "sb: PnP: Removing %s\n", scc->card_id);
 
-		cfg[card].card_subtype = type;
+	sb_unload(scc);
+}
 
-		if (!probe_sb(&cfg[card])) {
-			/* if one or more cards already registered, don't
-			 * return an error but print a warning. Note, this
-			 * should never really happen unless the hardware
-			 * or ISAPnP screwed up. */
-			if (sb_cards_num) {
-				printk(KERN_WARNING "sb.c: There was a " \
-				  "problem probing one of your SoundBlaster " \
-				  "ISAPnP soundcards. Continuing.\n");
-				card--;
-				sb_cards_num--;
-				continue;
-			} else if(pnplegacy && isapnp) {
-				printk(KERN_NOTICE "sb: No legacy SoundBlaster cards " \
-				  "found.  Continuing with PnP detection.\n");
-				pnplegacy=0;
-				card--;
-				continue;
-			} else
-				return -ENODEV;
-		}
-		attach_sb_card(&cfg[card]);
+static struct pnpc_driver sb_pnp_driver = {
+	.name          = "OSS SndBlstr", /* 16 character limit */
+	.id_table      = sb_pnp_card_table,
+	.probe         = sb_pnp_probe,
+	.remove        = sb_pnp_remove,
+};
+#endif /* CONFIG_PNP_CARD */
 
-		if(cfg[card].slots[0]==-1) {
-			if(card==0 && pnplegacy && isapnp) {
-				printk(KERN_NOTICE "sb: No legacy SoundBlaster cards " \
-				  "found.  Continuing with PnP detection.\n");
-				pnplegacy=0;
-				card--;
-				continue;
-			} else
-				return -ENODEV;
-		}
-		
-		if (!isapnp||(pnplegacy&&card==0))
-			cfg_mpu[card].io_base = mpu_io;
-		if (probe_sbmpu(&cfg_mpu[card], THIS_MODULE))
-			sbmpu[card] = 1;
+static int __init sb_init(void)
+{
+	int lres = 0;
+	int pres = 0;
+
+	printk(KERN_INFO "sb: Init: Starting Probe...\n");
+
+	if(io != -1 && irq != -1 && dma != -1) {
+		printk(KERN_INFO "sb: Probing legacy card with io=%x, "\
+		       "irq=%d, dma=%d, dma16=%d\n",io, irq, dma, dma16);
+		lres = sb_init_legacy();
+	} else if((io != -1 || irq != -1 || dma != -1) ||
+		  (!pnp && (io == -1 && irq == -1 && dma == -1)))
+		printk(KERN_ERR "sb: Error: At least io, irq, and dma "\
+		       "must be set for legacy cards.\n");
+
+#ifdef CONFIG_PNP_CARD
+	if(pnp) {
+		pres = pnpc_register_driver(&sb_pnp_driver);
 	}
+#endif
+	printk(KERN_INFO "sb: Init: Done\n");
 
-	if(isapnp)
-		printk(KERN_NOTICE "sb: %d Soundblaster PnP card(s) found.\n", sb_cards_num);
-
-	return 0;
+	/* If either PnP or Legacy registered a card then return
+	 * success */
+	return (pres > 0 || lres > 0) ? 0 : -ENODEV;
 }
 
-static void __exit cleanup_sb(void)
+static void __exit sb_exit(void)
 {
-	int i;
-	
-	if (smw_free) {
-		vfree(smw_free);
-		smw_free = NULL;
-	}
+	printk(KERN_INFO "sb: Unloading...\n");
 
-	for(i = 0; i < sb_cards_num; i++) {
-		unload_sb(&cfg[i], i);
-		if (sbmpu[i])
-			unload_sbmpu(&cfg_mpu[i]);
+	/* Unload legacy card */
+	if (legacy) {
+		printk (KERN_INFO "sb: Unloading legacy card\n");
+		sb_unload(legacy);
+	}
 
-#ifdef __ISAPNP__
-		if(!audio_activated[i] && sb_dev[i])
-			sb_dev[i]->deactivate(sb_dev[i]);
-		if(!mpu_activated[i] && mpu_dev[i])
-			mpu_dev[i]->deactivate(mpu_dev[i]);
-		if(!opl_activated[i] && opl_dev[i])
-			opl_dev[i]->deactivate(opl_dev[i]);
+#ifdef CONFIG_PNP_CARD
+	pnpc_unregister_driver(&sb_pnp_driver);
 #endif
+
+	if (smw_free) {
+		vfree(smw_free);
+		smw_free = NULL;
 	}
 }
 
-module_init(init_sb);
-module_exit(cleanup_sb);
-
-#ifndef MODULE
-static int __init setup_sb(char *str)
-{
-	/* io, irq, dma, dma2 - just the basics */
-	int ints[5];
-	
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-	
-	io	= ints[1];
-	irq	= ints[2];
-	dma	= ints[3];
-	dma16	= ints[4];
-
-	return 1;
-}
-__setup("sb=", setup_sb);
-#endif
+module_init(sb_init);
+module_exit(sb_exit);
diff --git a/sound/oss/sb_card.h b/sound/oss/sb_card.h
new file mode 100644
index 0000000000000000000000000000000000000000..4d61f17e2ba7ac14db4d4213a5df65be825637fb
--- /dev/null
+++ b/sound/oss/sb_card.h
@@ -0,0 +1,147 @@
+/*
+ * sound/oss/sb_card.h
+ *
+ * This file is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * Version 2 (June 1991). See the "COPYING" file distributed with this
+ * software for more info.
+ *
+ * 02-05-2002 Original Release, Paul Laufer <paul@laufernet.com>
+ */
+
+struct sb_card_config {
+	struct address_info conf;
+	struct address_info mpucnf;
+	const  char         *card_id;
+	const  char         *dev_id;
+	int                 mpu;
+};
+
+#ifdef CONFIG_PNP_CARD
+
+/*
+ * SoundBlaster PnP tables and structures.
+ */
+
+/* Card PnP ID Table */
+static struct pnp_card_id sb_pnp_card_table[] = {
+	/* Sound Blaster 16 */
+	{.id = "CTL0024", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster 16 */
+	{.id = "CTL0025", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster 16 */
+	{.id = "CTL0026", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster 16 */
+	{.id = "CTL0027", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster 16 */
+	{.id = "CTL0028", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster 16 */
+	{.id = "CTL0029", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster 16 */
+	{.id = "CTL002a", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster 16 */
+	{.id = "CTL002b", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster 16 */
+	{.id = "CTL002c", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster 16 */
+	{.id = "CTL00ed", .driver_data = 0, devs : { {.id="CTL0041"}, } },
+	/* Sound Blaster 16 */
+	{.id = "CTL0086", .driver_data = 0, devs : { {.id="CTL0041"}, } },
+	/* Sound Blaster Vibra16S */
+	{.id = "CTL0051", .driver_data = 0, devs : { {.id="CTL0001"}, } },
+	/* Sound Blaster Vibra16C */
+	{.id = "CTL0070", .driver_data = 0, devs : { {.id="CTL0001"}, } },
+	/* Sound Blaster Vibra16CL */
+	{.id = "CTL0080", .driver_data = 0, devs : { {.id="CTL0041"}, } },
+	/* Sound Blaster Vibra16CL */
+	{.id = "CTL00F0", .driver_data = 0, devs : { {.id="CTL0043"}, } },
+	/* Sound Blaster AWE 32 */
+	{.id = "CTL0039", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster AWE 32 */
+	{.id = "CTL0042", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster AWE 32 */
+	{.id = "CTL0043", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster AWE 32 */
+	{.id = "CTL0044", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster AWE 32 */
+	{.id = "CTL0045", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster AWE 32 */
+	{.id = "CTL0046", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster AWE 32 */
+	{.id = "CTL0047", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster AWE 32 */
+	{.id = "CTL0048", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster AWE 32 */
+	{.id = "CTL0054", .driver_data = 0, devs : { {.id="CTL0031"}, } },
+	/* Sound Blaster AWE 32 */
+	{.id = "CTL009C", .driver_data = 0, devs : { {.id="CTL0041"}, } },
+	/* Createive SB32 PnP */
+	{.id = "CTL009F", .driver_data = 0, devs : { {.id="CTL0041"}, } },
+	/* Sound Blaster AWE 64 */
+	{.id = "CTL009D", .driver_data = 0, devs : { {.id="CTL0042"}, } },
+	/* Sound Blaster AWE 64 Gold */
+	{.id = "CTL009E", .driver_data = 0, devs : { {.id="CTL0044"}, } },
+	/* Sound Blaster AWE 64 Gold */
+	{.id = "CTL00B2", .driver_data = 0, devs : { {.id="CTL0044"}, } },
+	/* Sound Blaster AWE 64 */
+	{.id = "CTL00C1", .driver_data = 0, devs : { {.id="CTL0042"}, } },
+	/* Sound Blaster AWE 64 */
+	{.id = "CTL00C3", .driver_data = 0, devs : { {.id="CTL0045"}, } },
+	/* Sound Blaster AWE 64 */
+	{.id = "CTL00C5", .driver_data = 0, devs : { {.id="CTL0045"}, } },
+	/* Sound Blaster AWE 64 */
+	{.id = "CTL00C7", .driver_data = 0, devs : { {.id="CTL0045"}, } },
+	/* Sound Blaster AWE 64 */
+	{.id = "CTL00E4", .driver_data = 0, devs : { {.id="CTL0045"}, } },
+	/* Sound Blaster AWE 64 */
+	{.id = "CTL00E9", .driver_data = 0, devs : { {.id="CTL0045"}, } },
+	/* ESS 1868 */
+	{.id = "ESS0968", .driver_data = 0, devs : { {.id="ESS0968"}, } },
+	/* ESS 1868 */
+	{.id = "ESS1868", .driver_data = 0, devs : { {.id="ESS1868"}, } },
+	/* ESS 1868 */
+	{.id = "ESS1868", .driver_data = 0, devs : { {.id="ESS8611"}, } },
+	/* ESS 1869 PnP AudioDrive */
+	{.id = "ESS0003", .driver_data = 0, devs : { {.id="ESS1869"}, } },
+	/* ESS 1869 */
+	{.id = "ESS1869", .driver_data = 0, devs : { {.id="ESS1869"}, } },
+	/* ESS 1878 */
+	{.id = "ESS1878", .driver_data = 0, devs : { {.id="ESS1878"}, } },
+	/* ESS 1879 */
+	{.id = "ESS1879", .driver_data = 0, devs : { {.id="ESS1879"}, } },
+	/* CMI 8330 SoundPRO */
+	{.id = "CMI0001", .driver_data = 0, devs : { {.id="@X@0001"},
+						     {.id="@H@0001"},
+						     {.id="@@@0001"}, } },
+	/* Diamond DT0197H */
+	{.id = "RWR1688", .driver_data = 0, devs : { {.id="@@@0001"},
+						     {.id="@X@0001"},
+						     {.id="@H@0001"}, } },
+	/* ALS007 */
+	{.id = "ALS0007", .driver_data = 0, devs : { {.id="@@@0001"},
+						     {.id="@X@0001"},
+						     {.id="@H@0001"}, } },
+	/* ALS100 */
+	{.id = "ALS0001", .driver_data = 0, devs : { {.id="@@@0001"},
+						     {.id="@X@0001"},
+						     {.id="@H@0001"}, } },
+	/* ALS110 */
+	{.id = "ALS0110", .driver_data = 0, devs : { {.id="@@@1001"},
+						     {.id="@X@1001"},
+						     {.id="@H@0001"}, } },
+	/* ALS120 */
+	{.id = "ALS0120", .driver_data = 0, devs : { {.id="@@@2001"},
+						     {.id="@X@2001"},
+						     {.id="@H@0001"}, } },
+	/* ALS200 */
+	{.id = "ALS0200", .driver_data = 0, devs : { {.id="@@@0020"},
+						     {.id="@X@0030"},
+						     {.id="@H@0001"}, } },
+	/* ALS200 */
+	{.id = "RTL3000", .driver_data = 0, devs : { {.id="@@@2001"},
+						     {.id="@X@2001"},
+						     {.id="@H@0001"}, } },
+	/* -end- */
+	{.id = "", }
+};
+
+#endif