summary refs log tree commit diff
path: root/drivers/pnp
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-04-30 11:52:52 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-30 11:52:52 -0700
commit08acd4f8af42affd8cbed81cc1b69fa12ddb213f (patch)
tree988d15db6233b20db6a500cd5f590c6d2041462d /drivers/pnp
parentccf2779544eecfcc5447e2028d1029b6d4ff7bb6 (diff)
parent008238b54ac2350babf195084ecedbcf7851a202 (diff)
downloadlinux-08acd4f8af42affd8cbed81cc1b69fa12ddb213f.tar.gz
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (179 commits)
  ACPI: Fix acpi_processor_idle and idle= boot parameters interaction
  acpi: fix section mismatch warning in pnpacpi
  intel_menlo: fix build warning
  ACPI: Cleanup: Remove unneeded, multiple local dummy variables
  ACPI: video - fix permissions on some proc entries
  ACPI: video - properly handle errors when registering proc elements
  ACPI: video - do not store invalid entries in attached_array list
  ACPI: re-name acpi_pm_ops to acpi_suspend_ops
  ACER_WMI/ASUS_LAPTOP: fix build bug
  thinkpad_acpi: fix possible NULL pointer dereference if kstrdup failed
  ACPI: check a return value correctly in acpi_power_get_context()
  #if 0 acpi/bay.c:eject_removable_drive()
  eeepc-laptop: add hwmon fan control
  eeepc-laptop: add backlight
  eeepc-laptop: add base driver
  ACPI: thinkpad-acpi: bump up version to 0.20
  ACPI: thinkpad-acpi: fix selects in Kconfig
  ACPI: thinkpad-acpi: use a private workqueue
  ACPI: thinkpad-acpi: fluff really minor fix
  ACPI: thinkpad-acpi: use uppercase for "LED" on user documentation
  ...

Fixed conflicts in drivers/acpi/video.c and drivers/misc/intel_menlow.c
manually.
Diffstat (limited to 'drivers/pnp')
-rw-r--r--drivers/pnp/base.h74
-rw-r--r--drivers/pnp/card.c55
-rw-r--r--drivers/pnp/core.c46
-rw-r--r--drivers/pnp/driver.c28
-rw-r--r--drivers/pnp/interface.c111
-rw-r--r--drivers/pnp/isapnp/Makefile4
-rw-r--r--drivers/pnp/isapnp/core.c340
-rw-r--r--drivers/pnp/manager.c356
-rw-r--r--drivers/pnp/pnpacpi/Makefile4
-rw-r--r--drivers/pnp/pnpacpi/core.c92
-rw-r--r--drivers/pnp/pnpacpi/pnpacpi.h8
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c589
-rw-r--r--drivers/pnp/pnpbios/Makefile4
-rw-r--r--drivers/pnp/pnpbios/bioscalls.c1
-rw-r--r--drivers/pnp/pnpbios/core.c31
-rw-r--r--drivers/pnp/pnpbios/pnpbios.h140
-rw-r--r--drivers/pnp/pnpbios/proc.c2
-rw-r--r--drivers/pnp/pnpbios/rsparser.c326
-rw-r--r--drivers/pnp/quirks.c15
-rw-r--r--drivers/pnp/resource.c361
-rw-r--r--drivers/pnp/support.c63
-rw-r--r--drivers/pnp/system.c21
22 files changed, 1576 insertions, 1095 deletions
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index 31a633f65547..4fe7c58f57e9 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -1,12 +1,78 @@
 extern spinlock_t pnp_lock;
 void *pnp_alloc(long size);
+
+int pnp_register_protocol(struct pnp_protocol *protocol);
+void pnp_unregister_protocol(struct pnp_protocol *protocol);
+
+#define PNP_EISA_ID_MASK 0x7fffffff
+void pnp_eisa_id_to_string(u32 id, char *str);
+struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id, char *pnpid);
+struct pnp_card *pnp_alloc_card(struct pnp_protocol *, int id, char *pnpid);
+
+int pnp_add_device(struct pnp_dev *dev);
+struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id);
 int pnp_interface_attach_device(struct pnp_dev *dev);
+
+int pnp_add_card(struct pnp_card *card);
+struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id);
+void pnp_remove_card(struct pnp_card *card);
+int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev);
+void pnp_remove_card_device(struct pnp_dev *dev);
+
+struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev);
+struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
+						 int priority);
+int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
+			      struct pnp_irq *data);
+int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option,
+			      struct pnp_dma *data);
+int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option,
+			       struct pnp_port *data);
+int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option,
+			      struct pnp_mem *data);
+void pnp_init_resources(struct pnp_dev *dev);
+
 void pnp_fixup_device(struct pnp_dev *dev);
 void pnp_free_option(struct pnp_option *option);
 int __pnp_add_device(struct pnp_dev *dev);
 void __pnp_remove_device(struct pnp_dev *dev);
 
-int pnp_check_port(struct pnp_dev * dev, int idx);
-int pnp_check_mem(struct pnp_dev * dev, int idx);
-int pnp_check_irq(struct pnp_dev * dev, int idx);
-int pnp_check_dma(struct pnp_dev * dev, int idx);
+int pnp_check_port(struct pnp_dev *dev, struct resource *res);
+int pnp_check_mem(struct pnp_dev *dev, struct resource *res);
+int pnp_check_irq(struct pnp_dev *dev, struct resource *res);
+int pnp_check_dma(struct pnp_dev *dev, struct resource *res);
+
+void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc);
+
+void pnp_init_resource(struct resource *res);
+
+struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
+					  unsigned int type, unsigned int num);
+
+#define PNP_MAX_PORT		40
+#define PNP_MAX_MEM		24
+#define PNP_MAX_IRQ		 2
+#define PNP_MAX_DMA		 2
+
+struct pnp_resource {
+	struct resource res;
+	unsigned int index;		/* ISAPNP config register index */
+};
+
+struct pnp_resource_table {
+	struct pnp_resource port[PNP_MAX_PORT];
+	struct pnp_resource mem[PNP_MAX_MEM];
+	struct pnp_resource dma[PNP_MAX_DMA];
+	struct pnp_resource irq[PNP_MAX_IRQ];
+};
+
+struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
+					  int flags);
+struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
+					  int flags);
+struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
+					 resource_size_t start,
+					 resource_size_t end, int flags);
+struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
+					  resource_size_t start,
+					  resource_size_t end, int flags);
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index da1c9909eb44..a762a4176736 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -5,6 +5,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/ctype.h>
 #include <linux/slab.h>
 #include <linux/pnp.h>
 #include "base.h"
@@ -100,19 +101,33 @@ static int card_probe(struct pnp_card *card, struct pnp_card_driver *drv)
  * @id: pointer to a pnp_id structure
  * @card: pointer to the desired card
  */
-int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card)
+struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id)
 {
-	struct pnp_id *ptr;
+	struct pnp_id *dev_id, *ptr;
 
-	id->next = NULL;
+	dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
+	if (!dev_id)
+		return NULL;
+
+	dev_id->id[0] = id[0];
+	dev_id->id[1] = id[1];
+	dev_id->id[2] = id[2];
+	dev_id->id[3] = tolower(id[3]);
+	dev_id->id[4] = tolower(id[4]);
+	dev_id->id[5] = tolower(id[5]);
+	dev_id->id[6] = tolower(id[6]);
+	dev_id->id[7] = '\0';
+
+	dev_id->next = NULL;
 	ptr = card->id;
 	while (ptr && ptr->next)
 		ptr = ptr->next;
 	if (ptr)
-		ptr->next = id;
+		ptr->next = dev_id;
 	else
-		card->id = id;
-	return 0;
+		card->id = dev_id;
+
+	return dev_id;
 }
 
 static void pnp_free_card_ids(struct pnp_card *card)
@@ -136,6 +151,31 @@ static void pnp_release_card(struct device *dmdev)
 	kfree(card);
 }
 
+struct pnp_card *pnp_alloc_card(struct pnp_protocol *protocol, int id, char *pnpid)
+{
+	struct pnp_card *card;
+	struct pnp_id *dev_id;
+
+	card = kzalloc(sizeof(struct pnp_card), GFP_KERNEL);
+	if (!card)
+		return NULL;
+
+	card->protocol = protocol;
+	card->number = id;
+
+	card->dev.parent = &card->protocol->dev;
+	sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number,
+		card->number);
+
+	dev_id = pnp_add_card_id(card, pnpid);
+	if (!dev_id) {
+		kfree(card);
+		return NULL;
+	}
+
+	return card;
+}
+
 static ssize_t pnp_show_card_name(struct device *dmdev,
 				  struct device_attribute *attr, char *buf)
 {
@@ -191,9 +231,6 @@ int pnp_add_card(struct pnp_card *card)
 	int error;
 	struct list_head *pos, *temp;
 
-	sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number,
-		card->number);
-	card->dev.parent = &card->protocol->dev;
 	card->dev.bus = NULL;
 	card->dev.release = &pnp_release_card;
 	error = device_register(&card->dev);
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index 7d366ca672d3..20771b7d4482 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -106,18 +106,53 @@ static void pnp_release_device(struct device *dmdev)
 	pnp_free_option(dev->independent);
 	pnp_free_option(dev->dependent);
 	pnp_free_ids(dev);
+	kfree(dev->res);
 	kfree(dev);
 }
 
-int __pnp_add_device(struct pnp_dev *dev)
+struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid)
 {
-	int ret;
+	struct pnp_dev *dev;
+	struct pnp_id *dev_id;
 
-	pnp_fixup_device(dev);
+	dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	dev->res = kzalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
+	if (!dev->res) {
+		kfree(dev);
+		return NULL;
+	}
+
+	dev->protocol = protocol;
+	dev->number = id;
+	dev->dma_mask = DMA_24BIT_MASK;
+
+	dev->dev.parent = &dev->protocol->dev;
 	dev->dev.bus = &pnp_bus_type;
 	dev->dev.dma_mask = &dev->dma_mask;
-	dev->dma_mask = dev->dev.coherent_dma_mask = DMA_24BIT_MASK;
+	dev->dev.coherent_dma_mask = dev->dma_mask;
 	dev->dev.release = &pnp_release_device;
+
+	sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number,
+		dev->number);
+
+	dev_id = pnp_add_id(dev, pnpid);
+	if (!dev_id) {
+		kfree(dev->res);
+		kfree(dev);
+		return NULL;
+	}
+
+	return dev;
+}
+
+int __pnp_add_device(struct pnp_dev *dev)
+{
+	int ret;
+
+	pnp_fixup_device(dev);
 	dev->status = PNP_READY;
 	spin_lock(&pnp_lock);
 	list_add_tail(&dev->global_list, &pnp_global);
@@ -145,9 +180,6 @@ int pnp_add_device(struct pnp_dev *dev)
 	if (dev->card)
 		return -EINVAL;
 
-	dev->dev.parent = &dev->protocol->dev;
-	sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number,
-		dev->number);
 	ret = __pnp_add_device(dev);
 	if (ret)
 		return ret;
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index e85cbf116db1..d3f869ee1d92 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -226,22 +226,36 @@ void pnp_unregister_driver(struct pnp_driver *drv)
 
 /**
  * pnp_add_id - adds an EISA id to the specified device
- * @id: pointer to a pnp_id structure
  * @dev: pointer to the desired device
+ * @id: pointer to an EISA id string
  */
-int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev)
+struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id)
 {
-	struct pnp_id *ptr;
+	struct pnp_id *dev_id, *ptr;
 
-	id->next = NULL;
+	dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
+	if (!dev_id)
+		return NULL;
+
+	dev_id->id[0] = id[0];
+	dev_id->id[1] = id[1];
+	dev_id->id[2] = id[2];
+	dev_id->id[3] = tolower(id[3]);
+	dev_id->id[4] = tolower(id[4]);
+	dev_id->id[5] = tolower(id[5]);
+	dev_id->id[6] = tolower(id[6]);
+	dev_id->id[7] = '\0';
+
+	dev_id->next = NULL;
 	ptr = dev->id;
 	while (ptr && ptr->next)
 		ptr = ptr->next;
 	if (ptr)
-		ptr->next = id;
+		ptr->next = dev_id;
 	else
-		dev->id = id;
-	return 0;
+		dev->id = dev_id;
+
+	return dev_id;
 }
 
 EXPORT_SYMBOL(pnp_register_driver);
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index 982658477a58..5d9301de1778 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -248,6 +248,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev,
 					  char *buf)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
+	struct resource *res;
 	int i, ret;
 	pnp_info_buffer_t *buffer;
 
@@ -267,50 +268,46 @@ static ssize_t pnp_show_current_resources(struct device *dmdev,
 	else
 		pnp_printf(buffer, "disabled\n");
 
-	for (i = 0; i < PNP_MAX_PORT; i++) {
-		if (pnp_port_valid(dev, i)) {
+	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
+		if (pnp_resource_valid(res)) {
 			pnp_printf(buffer, "io");
-			if (pnp_port_flags(dev, i) & IORESOURCE_DISABLED)
+			if (res->flags & IORESOURCE_DISABLED)
 				pnp_printf(buffer, " disabled\n");
 			else
 				pnp_printf(buffer, " 0x%llx-0x%llx\n",
-					   (unsigned long long)
-					   pnp_port_start(dev, i),
-					   (unsigned long long)pnp_port_end(dev,
-									    i));
+					   (unsigned long long) res->start,
+					   (unsigned long long) res->end);
 		}
 	}
-	for (i = 0; i < PNP_MAX_MEM; i++) {
-		if (pnp_mem_valid(dev, i)) {
+	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
+		if (pnp_resource_valid(res)) {
 			pnp_printf(buffer, "mem");
-			if (pnp_mem_flags(dev, i) & IORESOURCE_DISABLED)
+			if (res->flags & IORESOURCE_DISABLED)
 				pnp_printf(buffer, " disabled\n");
 			else
 				pnp_printf(buffer, " 0x%llx-0x%llx\n",
-					   (unsigned long long)
-					   pnp_mem_start(dev, i),
-					   (unsigned long long)pnp_mem_end(dev,
-									   i));
+					   (unsigned long long) res->start,
+					   (unsigned long long) res->end);
 		}
 	}
-	for (i = 0; i < PNP_MAX_IRQ; i++) {
-		if (pnp_irq_valid(dev, i)) {
+	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) {
+		if (pnp_resource_valid(res)) {
 			pnp_printf(buffer, "irq");
-			if (pnp_irq_flags(dev, i) & IORESOURCE_DISABLED)
+			if (res->flags & IORESOURCE_DISABLED)
 				pnp_printf(buffer, " disabled\n");
 			else
 				pnp_printf(buffer, " %lld\n",
-					   (unsigned long long)pnp_irq(dev, i));
+					   (unsigned long long) res->start);
 		}
 	}
-	for (i = 0; i < PNP_MAX_DMA; i++) {
-		if (pnp_dma_valid(dev, i)) {
+	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) {
+		if (pnp_resource_valid(res)) {
 			pnp_printf(buffer, "dma");
-			if (pnp_dma_flags(dev, i) & IORESOURCE_DISABLED)
+			if (res->flags & IORESOURCE_DISABLED)
 				pnp_printf(buffer, " disabled\n");
 			else
 				pnp_printf(buffer, " %lld\n",
-					   (unsigned long long)pnp_dma(dev, i));
+					   (unsigned long long) res->start);
 		}
 	}
 	ret = (buffer->curr - buf);
@@ -323,8 +320,10 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
 			  const char *ubuf, size_t count)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
+	struct pnp_resource *pnp_res;
 	char *buf = (void *)ubuf;
 	int retval = 0;
+	resource_size_t start, end;
 
 	if (dev->status & PNP_ATTACHED) {
 		retval = -EBUSY;
@@ -351,20 +350,20 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
 	if (!strnicmp(buf, "auto", 4)) {
 		if (dev->active)
 			goto done;
-		pnp_init_resource_table(&dev->res);
+		pnp_init_resources(dev);
 		retval = pnp_auto_config_dev(dev);
 		goto done;
 	}
 	if (!strnicmp(buf, "clear", 5)) {
 		if (dev->active)
 			goto done;
-		pnp_init_resource_table(&dev->res);
+		pnp_init_resources(dev);
 		goto done;
 	}
 	if (!strnicmp(buf, "get", 3)) {
 		mutex_lock(&pnp_res_mutex);
 		if (pnp_can_read(dev))
-			dev->protocol->get(dev, &dev->res);
+			dev->protocol->get(dev);
 		mutex_unlock(&pnp_res_mutex);
 		goto done;
 	}
@@ -373,7 +372,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
 		if (dev->active)
 			goto done;
 		buf += 3;
-		pnp_init_resource_table(&dev->res);
+		pnp_init_resources(dev);
 		mutex_lock(&pnp_res_mutex);
 		while (1) {
 			while (isspace(*buf))
@@ -382,76 +381,60 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
 				buf += 2;
 				while (isspace(*buf))
 					++buf;
-				dev->res.port_resource[nport].start =
-				    simple_strtoul(buf, &buf, 0);
+				start = simple_strtoul(buf, &buf, 0);
 				while (isspace(*buf))
 					++buf;
 				if (*buf == '-') {
 					buf += 1;
 					while (isspace(*buf))
 						++buf;
-					dev->res.port_resource[nport].end =
-					    simple_strtoul(buf, &buf, 0);
+					end = simple_strtoul(buf, &buf, 0);
 				} else
-					dev->res.port_resource[nport].end =
-					    dev->res.port_resource[nport].start;
-				dev->res.port_resource[nport].flags =
-				    IORESOURCE_IO;
-				nport++;
-				if (nport >= PNP_MAX_PORT)
-					break;
+					end = start;
+				pnp_res = pnp_add_io_resource(dev, start, end,
+							      0);
+				if (pnp_res)
+					pnp_res->index = nport++;
 				continue;
 			}
 			if (!strnicmp(buf, "mem", 3)) {
 				buf += 3;
 				while (isspace(*buf))
 					++buf;
-				dev->res.mem_resource[nmem].start =
-				    simple_strtoul(buf, &buf, 0);
+				start = simple_strtoul(buf, &buf, 0);
 				while (isspace(*buf))
 					++buf;
 				if (*buf == '-') {
 					buf += 1;
 					while (isspace(*buf))
 						++buf;
-					dev->res.mem_resource[nmem].end =
-					    simple_strtoul(buf, &buf, 0);
+					end = simple_strtoul(buf, &buf, 0);
 				} else
-					dev->res.mem_resource[nmem].end =
-					    dev->res.mem_resource[nmem].start;
-				dev->res.mem_resource[nmem].flags =
-				    IORESOURCE_MEM;
-				nmem++;
-				if (nmem >= PNP_MAX_MEM)
-					break;
+					end = start;
+				pnp_res = pnp_add_mem_resource(dev, start, end,
+							       0);
+				if (pnp_res)
+					pnp_res->index = nmem++;
 				continue;
 			}
 			if (!strnicmp(buf, "irq", 3)) {
 				buf += 3;
 				while (isspace(*buf))
 					++buf;
-				dev->res.irq_resource[nirq].start =
-				    dev->res.irq_resource[nirq].end =
-				    simple_strtoul(buf, &buf, 0);
-				dev->res.irq_resource[nirq].flags =
-				    IORESOURCE_IRQ;
-				nirq++;
-				if (nirq >= PNP_MAX_IRQ)
-					break;
+				start = simple_strtoul(buf, &buf, 0);
+				pnp_res = pnp_add_irq_resource(dev, start, 0);
+				if (pnp_res)
+					nirq++;
 				continue;
 			}
 			if (!strnicmp(buf, "dma", 3)) {
 				buf += 3;
 				while (isspace(*buf))
 					++buf;
-				dev->res.dma_resource[ndma].start =
-				    dev->res.dma_resource[ndma].end =
-				    simple_strtoul(buf, &buf, 0);
-				dev->res.dma_resource[ndma].flags =
-				    IORESOURCE_DMA;
-				ndma++;
-				if (ndma >= PNP_MAX_DMA)
-					break;
+				start = simple_strtoul(buf, &buf, 0);
+				pnp_res = pnp_add_dma_resource(dev, start, 0);
+				if (pnp_res)
+					pnp_res->index = ndma++;
 				continue;
 			}
 			break;
diff --git a/drivers/pnp/isapnp/Makefile b/drivers/pnp/isapnp/Makefile
index cac18bbfb817..3e38f06f8d78 100644
--- a/drivers/pnp/isapnp/Makefile
+++ b/drivers/pnp/isapnp/Makefile
@@ -5,3 +5,7 @@
 isapnp-proc-$(CONFIG_PROC_FS) = proc.o
 
 obj-y := core.o compat.o $(isapnp-proc-y)
+
+ifeq ($(CONFIG_PNP_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index 257f5d827d83..f1bccdbdeb08 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -44,6 +44,8 @@
 #include <linux/mutex.h>
 #include <asm/io.h>
 
+#include "../base.h"
+
 #if 0
 #define ISAPNP_REGION_OK
 #endif
@@ -88,6 +90,14 @@ MODULE_LICENSE("GPL");
 #define _LTAG_MEM32RANGE	0x85
 #define _LTAG_FIXEDMEM32RANGE	0x86
 
+/* Logical device control and configuration registers */
+
+#define ISAPNP_CFG_ACTIVATE	0x30	/* byte */
+#define ISAPNP_CFG_MEM		0x40	/* 4 * dword */
+#define ISAPNP_CFG_PORT		0x60	/* 8 * word */
+#define ISAPNP_CFG_IRQ		0x70	/* 2 * word */
+#define ISAPNP_CFG_DMA		0x74	/* 2 * byte */
+
 /*
  * Sizes of ISAPNP logical device configuration register sets.
  * See PNP-ISA-v1.0a.pdf, Appendix A.
@@ -388,28 +398,6 @@ static void __init isapnp_skip_bytes(int count)
 }
 
 /*
- *  Parse EISA id.
- */
-static void isapnp_parse_id(struct pnp_dev *dev, unsigned short vendor,
-			    unsigned short device)
-{
-	struct pnp_id *id;
-
-	if (!dev)
-		return;
-	id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
-	if (!id)
-		return;
-	sprintf(id->id, "%c%c%c%x%x%x%x",
-		'A' + ((vendor >> 2) & 0x3f) - 1,
-		'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
-		'A' + ((vendor >> 8) & 0x1f) - 1,
-		(device >> 4) & 0x0f,
-		device & 0x0f, (device >> 12) & 0x0f, (device >> 8) & 0x0f);
-	pnp_add_id(id, dev);
-}
-
-/*
  *  Parse logical device tag.
  */
 static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card,
@@ -417,30 +405,31 @@ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card,
 {
 	unsigned char tmp[6];
 	struct pnp_dev *dev;
+	u32 eisa_id;
+	char id[8];
 
 	isapnp_peek(tmp, size);
-	dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
+	eisa_id = tmp[0] | tmp[1] << 8 | tmp[2] << 16 | tmp[3] << 24;
+	pnp_eisa_id_to_string(eisa_id, id);
+
+	dev = pnp_alloc_dev(&isapnp_protocol, number, id);
 	if (!dev)
 		return NULL;
-	dev->number = number;
-	isapnp_parse_id(dev, (tmp[1] << 8) | tmp[0], (tmp[3] << 8) | tmp[2]);
-	dev->regs = tmp[4];
+
 	dev->card = card;
-	if (size > 5)
-		dev->regs |= tmp[5] << 8;
-	dev->protocol = &isapnp_protocol;
 	dev->capabilities |= PNP_CONFIGURABLE;
 	dev->capabilities |= PNP_READ;
 	dev->capabilities |= PNP_WRITE;
 	dev->capabilities |= PNP_DISABLE;
-	pnp_init_resource_table(&dev->res);
+	pnp_init_resources(dev);
 	return dev;
 }
 
 /*
  *  Add IRQ resource to resources list.
  */
-static void __init isapnp_parse_irq_resource(struct pnp_option *option,
+static void __init isapnp_parse_irq_resource(struct pnp_dev *dev,
+					     struct pnp_option *option,
 					     int size)
 {
 	unsigned char tmp[3];
@@ -457,13 +446,14 @@ static void __init isapnp_parse_irq_resource(struct pnp_option *option,
 		irq->flags = tmp[2];
 	else
 		irq->flags = IORESOURCE_IRQ_HIGHEDGE;
-	pnp_register_irq_resource(option, irq);
+	pnp_register_irq_resource(dev, option, irq);
 }
 
 /*
  *  Add DMA resource to resources list.
  */
-static void __init isapnp_parse_dma_resource(struct pnp_option *option,
+static void __init isapnp_parse_dma_resource(struct pnp_dev *dev,
+					     struct pnp_option *option,
 					     int size)
 {
 	unsigned char tmp[2];
@@ -475,13 +465,14 @@ static void __init isapnp_parse_dma_resource(struct pnp_option *option,
 		return;
 	dma->map = tmp[0];
 	dma->flags = tmp[1];
-	pnp_register_dma_resource(option, dma);
+	pnp_register_dma_resource(dev, option, dma);
 }
 
 /*
  *  Add port resource to resources list.
  */
-static void __init isapnp_parse_port_resource(struct pnp_option *option,
+static void __init isapnp_parse_port_resource(struct pnp_dev *dev,
+					      struct pnp_option *option,
 					      int size)
 {
 	unsigned char tmp[7];
@@ -496,13 +487,14 @@ static void __init isapnp_parse_port_resource(struct pnp_option *option,
 	port->align = tmp[5];
 	port->size = tmp[6];
 	port->flags = tmp[0] ? PNP_PORT_FLAG_16BITADDR : 0;
-	pnp_register_port_resource(option, port);
+	pnp_register_port_resource(dev, option, port);
 }
 
 /*
  *  Add fixed port resource to resources list.
  */
-static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option,
+static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev,
+						    struct pnp_option *option,
 						    int size)
 {
 	unsigned char tmp[3];
@@ -516,13 +508,14 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option,
 	port->size = tmp[2];
 	port->align = 0;
 	port->flags = PNP_PORT_FLAG_FIXED;
-	pnp_register_port_resource(option, port);
+	pnp_register_port_resource(dev, option, port);
 }
 
 /*
  *  Add memory resource to resources list.
  */
-static void __init isapnp_parse_mem_resource(struct pnp_option *option,
+static void __init isapnp_parse_mem_resource(struct pnp_dev *dev,
+					     struct pnp_option *option,
 					     int size)
 {
 	unsigned char tmp[9];
@@ -537,13 +530,14 @@ static void __init isapnp_parse_mem_resource(struct pnp_option *option,
 	mem->align = (tmp[6] << 8) | tmp[5];
 	mem->size = ((tmp[8] << 8) | tmp[7]) << 8;
 	mem->flags = tmp[0];
-	pnp_register_mem_resource(option, mem);
+	pnp_register_mem_resource(dev, option, mem);
 }
 
 /*
  *  Add 32-bit memory resource to resources list.
  */
-static void __init isapnp_parse_mem32_resource(struct pnp_option *option,
+static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev,
+					       struct pnp_option *option,
 					       int size)
 {
 	unsigned char tmp[17];
@@ -560,13 +554,14 @@ static void __init isapnp_parse_mem32_resource(struct pnp_option *option,
 	mem->size =
 	    (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13];
 	mem->flags = tmp[0];
-	pnp_register_mem_resource(option, mem);
+	pnp_register_mem_resource(dev, option, mem);
 }
 
 /*
  *  Add 32-bit fixed memory resource to resources list.
  */
-static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option,
+static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev,
+						     struct pnp_option *option,
 						     int size)
 {
 	unsigned char tmp[9];
@@ -581,7 +576,7 @@ static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option,
 	mem->size = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
 	mem->align = 0;
 	mem->flags = tmp[0];
-	pnp_register_mem_resource(option, mem);
+	pnp_register_mem_resource(dev, option, mem);
 }
 
 /*
@@ -613,6 +608,8 @@ static int __init isapnp_create_device(struct pnp_card *card,
 	unsigned char type, tmp[17];
 	struct pnp_option *option;
 	struct pnp_dev *dev;
+	u32 eisa_id;
+	char id[8];
 
 	if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
 		return 1;
@@ -652,8 +649,10 @@ static int __init isapnp_create_device(struct pnp_card *card,
 		case _STAG_COMPATDEVID:
 			if (size == 4 && compat < DEVICE_COUNT_COMPATIBLE) {
 				isapnp_peek(tmp, 4);
-				isapnp_parse_id(dev, (tmp[1] << 8) | tmp[0],
-						(tmp[3] << 8) | tmp[2]);
+				eisa_id = tmp[0] | tmp[1] << 8 |
+					  tmp[2] << 16 | tmp[3] << 24;
+				pnp_eisa_id_to_string(eisa_id, id);
+				pnp_add_id(dev, id);
 				compat++;
 				size = 0;
 			}
@@ -661,13 +660,13 @@ static int __init isapnp_create_device(struct pnp_card *card,
 		case _STAG_IRQ:
 			if (size < 2 || size > 3)
 				goto __skip;
-			isapnp_parse_irq_resource(option, size);
+			isapnp_parse_irq_resource(dev, option, size);
 			size = 0;
 			break;
 		case _STAG_DMA:
 			if (size != 2)
 				goto __skip;
-			isapnp_parse_dma_resource(option, size);
+			isapnp_parse_dma_resource(dev, option, size);
 			size = 0;
 			break;
 		case _STAG_STARTDEP:
@@ -687,17 +686,18 @@ static int __init isapnp_create_device(struct pnp_card *card,
 			if (size != 0)
 				goto __skip;
 			priority = 0;
+			dev_dbg(&dev->dev, "end dependent options\n");
 			break;
 		case _STAG_IOPORT:
 			if (size != 7)
 				goto __skip;
-			isapnp_parse_port_resource(option, size);
+			isapnp_parse_port_resource(dev, option, size);
 			size = 0;
 			break;
 		case _STAG_FIXEDIO:
 			if (size != 3)
 				goto __skip;
-			isapnp_parse_fixed_port_resource(option, size);
+			isapnp_parse_fixed_port_resource(dev, option, size);
 			size = 0;
 			break;
 		case _STAG_VENDOR:
@@ -705,7 +705,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
 		case _LTAG_MEMRANGE:
 			if (size != 9)
 				goto __skip;
-			isapnp_parse_mem_resource(option, size);
+			isapnp_parse_mem_resource(dev, option, size);
 			size = 0;
 			break;
 		case _LTAG_ANSISTR:
@@ -720,13 +720,13 @@ static int __init isapnp_create_device(struct pnp_card *card,
 		case _LTAG_MEM32RANGE:
 			if (size != 17)
 				goto __skip;
-			isapnp_parse_mem32_resource(option, size);
+			isapnp_parse_mem32_resource(dev, option, size);
 			size = 0;
 			break;
 		case _LTAG_FIXEDMEM32RANGE:
 			if (size != 9)
 				goto __skip;
-			isapnp_parse_fixed_mem32_resource(option, size);
+			isapnp_parse_fixed_mem32_resource(dev, option, size);
 			size = 0;
 			break;
 		case _STAG_END:
@@ -734,9 +734,8 @@ static int __init isapnp_create_device(struct pnp_card *card,
 				isapnp_skip_bytes(size);
 			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);
+			dev_err(&dev->dev, "unknown tag %#x (card %i), "
+				"ignored\n", type, card->number);
 		}
 __skip:
 		if (size > 0)
@@ -789,9 +788,8 @@ static void __init isapnp_parse_resource_map(struct pnp_card *card)
 				isapnp_skip_bytes(size);
 			return;
 		default:
-			printk(KERN_ERR
-			       "isapnp: unexpected or unknown tag type 0x%x for device %i, ignored\n",
-			       type, card->number);
+			dev_err(&card->dev, "unknown tag %#x, ignored\n",
+			       type);
 		}
 __skip:
 		if (size > 0)
@@ -822,25 +820,6 @@ static unsigned char __init isapnp_checksum(unsigned char *data)
 }
 
 /*
- *  Parse EISA id for ISA PnP card.
- */
-static void isapnp_parse_card_id(struct pnp_card *card, unsigned short vendor,
-				 unsigned short device)
-{
-	struct pnp_id *id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
-
-	if (!id)
-		return;
-	sprintf(id->id, "%c%c%c%x%x%x%x",
-		'A' + ((vendor >> 2) & 0x3f) - 1,
-		'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
-		'A' + ((vendor >> 8) & 0x1f) - 1,
-		(device >> 4) & 0x0f,
-		device & 0x0f, (device >> 12) & 0x0f, (device >> 8) & 0x0f);
-	pnp_add_card_id(id, card);
-}
-
-/*
  *  Build device list for all present ISA PnP devices.
  */
 static int __init isapnp_build_device_list(void)
@@ -848,6 +827,8 @@ static int __init isapnp_build_device_list(void)
 	int csn;
 	unsigned char header[9], checksum;
 	struct pnp_card *card;
+	u32 eisa_id;
+	char id[8];
 
 	isapnp_wait();
 	isapnp_key();
@@ -855,32 +836,30 @@ static int __init isapnp_build_device_list(void)
 		isapnp_wake(csn);
 		isapnp_peek(header, 9);
 		checksum = isapnp_checksum(header);
+		eisa_id = header[0] | header[1] << 8 |
+			  header[2] << 16 | header[3] << 24;
+		pnp_eisa_id_to_string(eisa_id, id);
+		card = pnp_alloc_card(&isapnp_protocol, csn, id);
+		if (!card)
+			continue;
+
 #if 0
-		printk(KERN_DEBUG
+		dev_info(&card->dev,
 		       "vendor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
 		       header[0], header[1], header[2], header[3], header[4],
 		       header[5], header[6], header[7], header[8]);
-		printk(KERN_DEBUG "checksum = 0x%x\n", checksum);
+		dev_info(&card->dev, "checksum = %#x\n", checksum);
 #endif
-		if ((card =
-		     kzalloc(sizeof(struct pnp_card), GFP_KERNEL)) == NULL)
-			continue;
-
-		card->number = csn;
 		INIT_LIST_HEAD(&card->devices);
-		isapnp_parse_card_id(card, (header[1] << 8) | header[0],
-				     (header[3] << 8) | header[2]);
 		card->serial =
 		    (header[7] << 24) | (header[6] << 16) | (header[5] << 8) |
 		    header[4];
 		isapnp_checksum_value = 0x00;
 		isapnp_parse_resource_map(card);
 		if (isapnp_checksum_value != 0x00)
-			printk(KERN_ERR
-			       "isapnp: checksum for device %i is not valid (0x%x)\n",
-			       csn, isapnp_checksum_value);
+			dev_err(&card->dev, "invalid checksum %#x\n",
+				isapnp_checksum_value);
 		card->checksum = isapnp_checksum_value;
-		card->protocol = &isapnp_protocol;
 
 		pnp_add_card(card);
 	}
@@ -947,100 +926,117 @@ EXPORT_SYMBOL(isapnp_cfg_begin);
 EXPORT_SYMBOL(isapnp_cfg_end);
 EXPORT_SYMBOL(isapnp_write_byte);
 
-static int isapnp_read_resources(struct pnp_dev *dev,
-				 struct pnp_resource_table *res)
+static int isapnp_get_resources(struct pnp_dev *dev)
 {
-	int tmp, ret;
+	struct pnp_resource *pnp_res;
+	int i, ret;
 
+	dev_dbg(&dev->dev, "get resources\n");
+	pnp_init_resources(dev);
+	isapnp_cfg_begin(dev->card->number, dev->number);
 	dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE);
-	if (dev->active) {
-		for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) {
-			ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1));
-			if (!ret)
-				continue;
-			res->port_resource[tmp].start = ret;
-			res->port_resource[tmp].flags = IORESOURCE_IO;
+	if (!dev->active)
+		goto __end;
+
+	for (i = 0; i < ISAPNP_MAX_PORT; i++) {
+		ret = isapnp_read_word(ISAPNP_CFG_PORT + (i << 1));
+		if (ret) {
+			pnp_res = pnp_add_io_resource(dev, ret, ret, 0);
+			if (pnp_res)
+				pnp_res->index = i;
 		}
-		for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) {
-			ret =
-			    isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8;
-			if (!ret)
-				continue;
-			res->mem_resource[tmp].start = ret;
-			res->mem_resource[tmp].flags = IORESOURCE_MEM;
+	}
+	for (i = 0; i < ISAPNP_MAX_MEM; i++) {
+		ret = isapnp_read_word(ISAPNP_CFG_MEM + (i << 3)) << 8;
+		if (ret) {
+			pnp_res = pnp_add_mem_resource(dev, ret, ret, 0);
+			if (pnp_res)
+				pnp_res->index = i;
 		}
-		for (tmp = 0; tmp < ISAPNP_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 (i = 0; i < ISAPNP_MAX_IRQ; i++) {
+		ret = isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1)) >> 8;
+		if (ret) {
+			pnp_res = pnp_add_irq_resource(dev, ret, 0);
+			if (pnp_res)
+				pnp_res->index = i;
 		}
-		for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) {
-			ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp);
-			if (ret == 4)
-				continue;
-			res->dma_resource[tmp].start =
-			    res->dma_resource[tmp].end = ret;
-			res->dma_resource[tmp].flags = IORESOURCE_DMA;
+	}
+	for (i = 0; i < ISAPNP_MAX_DMA; i++) {
+		ret = isapnp_read_byte(ISAPNP_CFG_DMA + i);
+		if (ret != 4) {
+			pnp_res = pnp_add_dma_resource(dev, ret, 0);
+			if  (pnp_res)
+				pnp_res->index = i;
 		}
 	}
-	return 0;
-}
-
-static int isapnp_get_resources(struct pnp_dev *dev,
-				struct pnp_resource_table *res)
-{
-	int ret;
 
-	pnp_init_resource_table(res);
-	isapnp_cfg_begin(dev->card->number, dev->number);
-	ret = isapnp_read_resources(dev, res);
+__end:
 	isapnp_cfg_end();
-	return ret;
+	return 0;
 }
 
-static int isapnp_set_resources(struct pnp_dev *dev,
-				struct pnp_resource_table *res)
+static int isapnp_set_resources(struct pnp_dev *dev)
 {
-	int tmp;
+	struct pnp_resource *pnp_res;
+	struct resource *res;
+	int tmp, index;
 
+	dev_dbg(&dev->dev, "set resources\n");
 	isapnp_cfg_begin(dev->card->number, dev->number);
 	dev->active = 1;
-	for (tmp = 0;
-	     tmp < ISAPNP_MAX_PORT
-	     && (res->port_resource[tmp].
-		 flags & (IORESOURCE_IO | IORESOURCE_UNSET)) == IORESOURCE_IO;
-	     tmp++)
-		isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1),
-				  res->port_resource[tmp].start);
-	for (tmp = 0;
-	     tmp < ISAPNP_MAX_IRQ
-	     && (res->irq_resource[tmp].
-		 flags & (IORESOURCE_IRQ | IORESOURCE_UNSET)) == 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 < ISAPNP_MAX_PORT; tmp++) {
+		pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, tmp);
+		if (!pnp_res)
+			continue;
+		res = &pnp_res->res;
+		if (pnp_resource_valid(res)) {
+			index = pnp_res->index;
+			dev_dbg(&dev->dev, "  set io  %d to %#llx\n",
+				index, (unsigned long long) res->start);
+			isapnp_write_word(ISAPNP_CFG_PORT + (index << 1),
+					  res->start);
+		}
+	}
+	for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) {
+		pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, tmp);
+		if (!pnp_res)
+			continue;
+		res = &pnp_res->res;
+		if (pnp_resource_valid(res)) {
+			int irq = res->start;
+			if (irq == 2)
+				irq = 9;
+			index = pnp_res->index;
+			dev_dbg(&dev->dev, "  set irq %d to %d\n", index, irq);
+			isapnp_write_byte(ISAPNP_CFG_IRQ + (index << 1), irq);
+		}
+	}
+	for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) {
+		pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, tmp);
+		if (!pnp_res)
+			continue;
+		res = &pnp_res->res;
+		if (pnp_resource_valid(res)) {
+			index = pnp_res->index;
+			dev_dbg(&dev->dev, "  set dma %d to %lld\n",
+				index, (unsigned long long) res->start);
+			isapnp_write_byte(ISAPNP_CFG_DMA + index, res->start);
+		}
+	}
+	for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) {
+		pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, tmp);
+		if (!pnp_res)
+			continue;
+		res = &pnp_res->res;
+		if (pnp_resource_valid(res)) {
+			index = pnp_res->index;
+			dev_dbg(&dev->dev, "  set mem %d to %#llx\n",
+				index, (unsigned long long) res->start);
+			isapnp_write_word(ISAPNP_CFG_MEM + (index << 3),
+					  (res->start >> 8) & 0xffff);
+		}
 	}
-	for (tmp = 0;
-	     tmp < ISAPNP_MAX_DMA
-	     && (res->dma_resource[tmp].
-		 flags & (IORESOURCE_DMA | IORESOURCE_UNSET)) == IORESOURCE_DMA;
-	     tmp++)
-		isapnp_write_byte(ISAPNP_CFG_DMA + tmp,
-				  res->dma_resource[tmp].start);
-	for (tmp = 0;
-	     tmp < ISAPNP_MAX_MEM
-	     && (res->mem_resource[tmp].
-		 flags & (IORESOURCE_MEM | IORESOURCE_UNSET)) == IORESOURCE_MEM;
-	     tmp++)
-		isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3),
-				  (res->mem_resource[tmp].start >> 8) & 0xffff);
 	/* FIXME: We aren't handling 32bit mems properly here */
 	isapnp_activate(dev->number);
 	isapnp_cfg_end();
@@ -1138,13 +1134,13 @@ static 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");
+			dev_info(&card->dev, "card '%s'\n",
+			       card->name[0] ? card->name : "unknown");
 			if (isapnp_verbose < 2)
 				continue;
 			card_for_each_dev(card, dev) {
-				printk(KERN_INFO "isapnp:   Device '%s'\n",
-				       dev->name[0] ? dev->name : "Unknown");
+				dev_info(&card->dev, "device '%s'\n",
+				       dev->name[0] ? dev->name : "unknown");
 			}
 		}
 	}
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index c28caf272c11..bea0914ff947 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -19,100 +19,118 @@ DEFINE_MUTEX(pnp_res_mutex);
 
 static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
 {
-	resource_size_t *start, *end;
-	unsigned long *flags;
+	struct pnp_resource *pnp_res;
+	struct resource *res;
 
-	if (idx >= PNP_MAX_PORT) {
+	pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, idx);
+	if (!pnp_res) {
 		dev_err(&dev->dev, "too many I/O port resources\n");
 		/* pretend we were successful so at least the manager won't try again */
 		return 1;
 	}
 
+	res = &pnp_res->res;
+
 	/* check if this resource has been manually set, if so skip */
-	if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO))
+	if (!(res->flags & IORESOURCE_AUTO)) {
+		dev_dbg(&dev->dev, "  io %d already set to %#llx-%#llx "
+			"flags %#lx\n", idx, (unsigned long long) res->start,
+			(unsigned long long) res->end, res->flags);
 		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 */
-	*flags |= rule->flags | IORESOURCE_IO;
-	*flags &= ~IORESOURCE_UNSET;
+	pnp_res->index = idx;
+	res->flags |= rule->flags | IORESOURCE_IO;
+	res->flags &= ~IORESOURCE_UNSET;
 
 	if (!rule->size) {
-		*flags |= IORESOURCE_DISABLED;
+		res->flags |= IORESOURCE_DISABLED;
+		dev_dbg(&dev->dev, "  io %d disabled\n", idx);
 		return 1;	/* skip disabled resource requests */
 	}
 
-	*start = rule->min;
-	*end = *start + rule->size - 1;
+	res->start = rule->min;
+	res->end = res->start + rule->size - 1;
 
 	/* run through until pnp_check_port is happy */
-	while (!pnp_check_port(dev, idx)) {
-		*start += rule->align;
-		*end = *start + rule->size - 1;
-		if (*start > rule->max || !rule->align)
+	while (!pnp_check_port(dev, res)) {
+		res->start += rule->align;
+		res->end = res->start + rule->size - 1;
+		if (res->start > rule->max || !rule->align) {
+			dev_dbg(&dev->dev, "  couldn't assign io %d\n", idx);
 			return 0;
+		}
 	}
+	dev_dbg(&dev->dev, "  assign io  %d %#llx-%#llx\n", idx,
+		(unsigned long long) res->start, (unsigned long long) res->end);
 	return 1;
 }
 
 static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
 {
-	resource_size_t *start, *end;
-	unsigned long *flags;
+	struct pnp_resource *pnp_res;
+	struct resource *res;
 
-	if (idx >= PNP_MAX_MEM) {
+	pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, idx);
+	if (!pnp_res) {
 		dev_err(&dev->dev, "too many memory resources\n");
 		/* pretend we were successful so at least the manager won't try again */
 		return 1;
 	}
 
+	res = &pnp_res->res;
+
 	/* check if this resource has been manually set, if so skip */
-	if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO))
+	if (!(res->flags & IORESOURCE_AUTO)) {
+		dev_dbg(&dev->dev, "  mem %d already set to %#llx-%#llx "
+			"flags %#lx\n", idx, (unsigned long long) res->start,
+			(unsigned long long) res->end, res->flags);
 		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 */
-	*flags |= rule->flags | IORESOURCE_MEM;
-	*flags &= ~IORESOURCE_UNSET;
+	pnp_res->index = idx;
+	res->flags |= rule->flags | IORESOURCE_MEM;
+	res->flags &= ~IORESOURCE_UNSET;
 
 	/* convert pnp flags to standard Linux flags */
 	if (!(rule->flags & IORESOURCE_MEM_WRITEABLE))
-		*flags |= IORESOURCE_READONLY;
+		res->flags |= IORESOURCE_READONLY;
 	if (rule->flags & IORESOURCE_MEM_CACHEABLE)
-		*flags |= IORESOURCE_CACHEABLE;
+		res->flags |= IORESOURCE_CACHEABLE;
 	if (rule->flags & IORESOURCE_MEM_RANGELENGTH)
-		*flags |= IORESOURCE_RANGELENGTH;
+		res->flags |= IORESOURCE_RANGELENGTH;
 	if (rule->flags & IORESOURCE_MEM_SHADOWABLE)
-		*flags |= IORESOURCE_SHADOWABLE;
+		res->flags |= IORESOURCE_SHADOWABLE;
 
 	if (!rule->size) {
-		*flags |= IORESOURCE_DISABLED;
+		res->flags |= IORESOURCE_DISABLED;
+		dev_dbg(&dev->dev, "  mem %d disabled\n", idx);
 		return 1;	/* skip disabled resource requests */
 	}
 
-	*start = rule->min;
-	*end = *start + rule->size - 1;
+	res->start = rule->min;
+	res->end = res->start + rule->size - 1;
 
 	/* run through until pnp_check_mem is happy */
-	while (!pnp_check_mem(dev, idx)) {
-		*start += rule->align;
-		*end = *start + rule->size - 1;
-		if (*start > rule->max || !rule->align)
+	while (!pnp_check_mem(dev, res)) {
+		res->start += rule->align;
+		res->end = res->start + rule->size - 1;
+		if (res->start > rule->max || !rule->align) {
+			dev_dbg(&dev->dev, "  couldn't assign mem %d\n", idx);
 			return 0;
+		}
 	}
+	dev_dbg(&dev->dev, "  assign mem %d %#llx-%#llx\n", idx,
+		(unsigned long long) res->start, (unsigned long long) res->end);
 	return 1;
 }
 
 static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
 {
-	resource_size_t *start, *end;
-	unsigned long *flags;
+	struct pnp_resource *pnp_res;
+	struct resource *res;
 	int i;
 
 	/* IRQ priority: this table is good for i386 */
@@ -120,49 +138,59 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
 		5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
 	};
 
-	if (idx >= PNP_MAX_IRQ) {
+	pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, idx);
+	if (!pnp_res) {
 		dev_err(&dev->dev, "too many IRQ resources\n");
 		/* pretend we were successful so at least the manager won't try again */
 		return 1;
 	}
 
+	res = &pnp_res->res;
+
 	/* check if this resource has been manually set, if so skip */
-	if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO))
+	if (!(res->flags & IORESOURCE_AUTO)) {
+		dev_dbg(&dev->dev, "  irq %d already set to %d flags %#lx\n",
+			idx, (int) res->start, res->flags);
 		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 */
-	*flags |= rule->flags | IORESOURCE_IRQ;
-	*flags &= ~IORESOURCE_UNSET;
+	pnp_res->index = idx;
+	res->flags |= rule->flags | IORESOURCE_IRQ;
+	res->flags &= ~IORESOURCE_UNSET;
 
 	if (bitmap_empty(rule->map, PNP_IRQ_NR)) {
-		*flags |= IORESOURCE_DISABLED;
+		res->flags |= IORESOURCE_DISABLED;
+		dev_dbg(&dev->dev, "  irq %d disabled\n", idx);
 		return 1;	/* skip disabled resource requests */
 	}
 
 	/* TBD: need check for >16 IRQ */
-	*start = find_next_bit(rule->map, PNP_IRQ_NR, 16);
-	if (*start < PNP_IRQ_NR) {
-		*end = *start;
+	res->start = find_next_bit(rule->map, PNP_IRQ_NR, 16);
+	if (res->start < PNP_IRQ_NR) {
+		res->end = res->start;
+		dev_dbg(&dev->dev, "  assign irq %d %d\n", idx,
+			(int) res->start);
 		return 1;
 	}
 	for (i = 0; i < 16; i++) {
 		if (test_bit(xtab[i], rule->map)) {
-			*start = *end = xtab[i];
-			if (pnp_check_irq(dev, idx))
+			res->start = res->end = xtab[i];
+			if (pnp_check_irq(dev, res)) {
+				dev_dbg(&dev->dev, "  assign irq %d %d\n", idx,
+					(int) res->start);
 				return 1;
+			}
 		}
 	}
+	dev_dbg(&dev->dev, "  couldn't assign irq %d\n", idx);
 	return 0;
 }
 
 static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
 {
-	resource_size_t *start, *end;
-	unsigned long *flags;
+	struct pnp_resource *pnp_res;
+	struct resource *res;
 	int i;
 
 	/* DMA priority: this table is good for i386 */
@@ -170,71 +198,89 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
 		1, 3, 5, 6, 7, 0, 2, 4
 	};
 
-	if (idx >= PNP_MAX_DMA) {
+	pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, idx);
+	if (!pnp_res) {
 		dev_err(&dev->dev, "too many DMA resources\n");
 		return;
 	}
 
+	res = &pnp_res->res;
+
 	/* check if this resource has been manually set, if so skip */
-	if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO))
+	if (!(res->flags & IORESOURCE_AUTO)) {
+		dev_dbg(&dev->dev, "  dma %d already set to %d flags %#lx\n",
+			idx, (int) res->start, res->flags);
 		return;
-
-	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 */
-	*flags |= rule->flags | IORESOURCE_DMA;
-	*flags &= ~IORESOURCE_UNSET;
+	pnp_res->index = idx;
+	res->flags |= rule->flags | IORESOURCE_DMA;
+	res->flags &= ~IORESOURCE_UNSET;
 
 	for (i = 0; i < 8; i++) {
 		if (rule->map & (1 << xtab[i])) {
-			*start = *end = xtab[i];
-			if (pnp_check_dma(dev, idx))
+			res->start = res->end = xtab[i];
+			if (pnp_check_dma(dev, res)) {
+				dev_dbg(&dev->dev, "  assign dma %d %d\n", idx,
+					(int) res->start);
 				return;
+			}
 		}
 	}
 #ifdef MAX_DMA_CHANNELS
-	*start = *end = MAX_DMA_CHANNELS;
+	res->start = res->end = MAX_DMA_CHANNELS;
 #endif
-	*flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
+	res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
+	dev_dbg(&dev->dev, "  disable dma %d\n", idx);
+}
+
+void pnp_init_resource(struct resource *res)
+{
+	unsigned long type;
+
+	type = res->flags & (IORESOURCE_IO  | IORESOURCE_MEM |
+			     IORESOURCE_IRQ | IORESOURCE_DMA);
+
+	res->name = NULL;
+	res->flags = type | IORESOURCE_AUTO | IORESOURCE_UNSET;
+	if (type == IORESOURCE_IRQ || type == IORESOURCE_DMA) {
+		res->start = -1;
+		res->end = -1;
+	} else {
+		res->start = 0;
+		res->end = 0;
+	}
 }
 
 /**
  * pnp_init_resources - Resets a resource table to default values.
  * @table: pointer to the desired resource table
  */
-void pnp_init_resource_table(struct pnp_resource_table *table)
+void pnp_init_resources(struct pnp_dev *dev)
 {
+	struct resource *res;
 	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 =
-		    IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET;
+		res = &dev->res->irq[idx].res;
+		res->flags = IORESOURCE_IRQ;
+		pnp_init_resource(res);
 	}
 	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 =
-		    IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET;
+		res = &dev->res->dma[idx].res;
+		res->flags = IORESOURCE_DMA;
+		pnp_init_resource(res);
 	}
 	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 =
-		    IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET;
+		res = &dev->res->port[idx].res;
+		res->flags = IORESOURCE_IO;
+		pnp_init_resource(res);
 	}
 	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 =
-		    IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET;
+		res = &dev->res->mem[idx].res;
+		res->flags = IORESOURCE_MEM;
+		pnp_init_resource(res);
 	}
 }
 
@@ -242,41 +288,38 @@ void pnp_init_resource_table(struct pnp_resource_table *table)
  * pnp_clean_resources - clears resources that were not manually set
  * @res: the resources to clean
  */
-static void pnp_clean_resource_table(struct pnp_resource_table *res)
+static void pnp_clean_resource_table(struct pnp_dev *dev)
 {
+	struct resource *res;
 	int idx;
 
 	for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
-		if (!(res->irq_resource[idx].flags & IORESOURCE_AUTO))
-			continue;
-		res->irq_resource[idx].start = -1;
-		res->irq_resource[idx].end = -1;
-		res->irq_resource[idx].flags =
-		    IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET;
+		res = &dev->res->irq[idx].res;
+		if (res->flags & IORESOURCE_AUTO) {
+			res->flags = IORESOURCE_IRQ;
+			pnp_init_resource(res);
+		}
 	}
 	for (idx = 0; idx < PNP_MAX_DMA; idx++) {
-		if (!(res->dma_resource[idx].flags & IORESOURCE_AUTO))
-			continue;
-		res->dma_resource[idx].start = -1;
-		res->dma_resource[idx].end = -1;
-		res->dma_resource[idx].flags =
-		    IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET;
+		res = &dev->res->dma[idx].res;
+		if (res->flags & IORESOURCE_AUTO) {
+			res->flags = IORESOURCE_DMA;
+			pnp_init_resource(res);
+		}
 	}
 	for (idx = 0; idx < PNP_MAX_PORT; idx++) {
-		if (!(res->port_resource[idx].flags & IORESOURCE_AUTO))
-			continue;
-		res->port_resource[idx].start = 0;
-		res->port_resource[idx].end = 0;
-		res->port_resource[idx].flags =
-		    IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET;
+		res = &dev->res->port[idx].res;
+		if (res->flags & IORESOURCE_AUTO) {
+			res->flags = IORESOURCE_IO;
+			pnp_init_resource(res);
+		}
 	}
 	for (idx = 0; idx < PNP_MAX_MEM; idx++) {
-		if (!(res->mem_resource[idx].flags & IORESOURCE_AUTO))
-			continue;
-		res->mem_resource[idx].start = 0;
-		res->mem_resource[idx].end = 0;
-		res->mem_resource[idx].flags =
-		    IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET;
+		res = &dev->res->mem[idx].res;
+		if (res->flags & IORESOURCE_AUTO) {
+			res->flags = IORESOURCE_MEM;
+			pnp_init_resource(res);
+		}
 	}
 }
 
@@ -298,9 +341,11 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
 	if (!pnp_can_configure(dev))
 		return -ENODEV;
 
+	dbg_pnp_show_resources(dev, "before pnp_assign_resources");
 	mutex_lock(&pnp_res_mutex);
-	pnp_clean_resource_table(&dev->res);	/* start with a fresh slate */
+	pnp_clean_resource_table(dev);
 	if (dev->independent) {
+		dev_dbg(&dev->dev, "assigning independent options\n");
 		port = dev->independent->port;
 		mem = dev->independent->mem;
 		irq = dev->independent->irq;
@@ -333,6 +378,8 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
 	if (depnum) {
 		struct pnp_option *dep;
 		int i;
+
+		dev_dbg(&dev->dev, "assigning dependent option %d\n", depnum);
 		for (i = 1, dep = dev->dependent; i < depnum;
 		     i++, dep = dep->next)
 			if (!dep)
@@ -368,68 +415,17 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
 		goto fail;
 
 	mutex_unlock(&pnp_res_mutex);
+	dbg_pnp_show_resources(dev, "after pnp_assign_resources");
 	return 1;
 
 fail:
-	pnp_clean_resource_table(&dev->res);
+	pnp_clean_resource_table(dev);
 	mutex_unlock(&pnp_res_mutex);
+	dbg_pnp_show_resources(dev, "after pnp_assign_resources (failed)");
 	return 0;
 }
 
 /**
- * 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
- * @mode: 0 or PNP_CONFIG_FORCE
- *
- * 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;
-
-	if (!pnp_can_configure(dev))
-		return -ENODEV;
-	bak = pnp_alloc(sizeof(struct pnp_resource_table));
-	if (!bak)
-		return -ENOMEM;
-	*bak = dev->res;
-
-	mutex_lock(&pnp_res_mutex);
-	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;
-		}
-	}
-	mutex_unlock(&pnp_res_mutex);
-
-	kfree(bak);
-	return 0;
-
-fail:
-	dev->res = *bak;
-	mutex_unlock(&pnp_res_mutex);
-	kfree(bak);
-	return -EINVAL;
-}
-
-/**
  * pnp_auto_config_dev - automatically assigns resources to a device
  * @dev: pointer to the desired device
  */
@@ -473,7 +469,8 @@ int pnp_start_dev(struct pnp_dev *dev)
 		return -EINVAL;
 	}
 
-	if (dev->protocol->set(dev, &dev->res) < 0) {
+	dbg_pnp_show_resources(dev, "pnp_start_dev");
+	if (dev->protocol->set(dev) < 0) {
 		dev_err(&dev->dev, "activation failed\n");
 		return -EIO;
 	}
@@ -549,30 +546,13 @@ int pnp_disable_dev(struct pnp_dev *dev)
 
 	/* release the resources so that other devices can use them */
 	mutex_lock(&pnp_res_mutex);
-	pnp_clean_resource_table(&dev->res);
+	pnp_clean_resource_table(dev);
 	mutex_unlock(&pnp_res_mutex);
 
 	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, resource_size_t start,
-			 resource_size_t size)
-{
-	resource->flags &= ~(IORESOURCE_AUTO | IORESOURCE_UNSET);
-	resource->start = start;
-	resource->end = start + size - 1;
-}
-
-EXPORT_SYMBOL(pnp_manual_config_dev);
 EXPORT_SYMBOL(pnp_start_dev);
 EXPORT_SYMBOL(pnp_stop_dev);
 EXPORT_SYMBOL(pnp_activate_dev);
 EXPORT_SYMBOL(pnp_disable_dev);
-EXPORT_SYMBOL(pnp_resource_change);
-EXPORT_SYMBOL(pnp_init_resource_table);
diff --git a/drivers/pnp/pnpacpi/Makefile b/drivers/pnp/pnpacpi/Makefile
index 905326fcca85..2d7a1e6908be 100644
--- a/drivers/pnp/pnpacpi/Makefile
+++ b/drivers/pnp/pnpacpi/Makefile
@@ -3,3 +3,7 @@
 #
 
 obj-y := core.o rsparser.o
+
+ifeq ($(CONFIG_PNP_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index c283a9a70d83..50902773beaf 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -25,6 +25,7 @@
 #include <acpi/acpi_bus.h>
 #include <acpi/actypes.h>
 
+#include "../base.h"
 #include "pnpacpi.h"
 
 static int num = 0;
@@ -44,7 +45,7 @@ static struct acpi_device_id excluded_id_list[] __initdata = {
 	{"", 0},
 };
 
-static inline int is_exclusive_device(struct acpi_device *dev)
+static inline int __init is_exclusive_device(struct acpi_device *dev)
 {
 	return (!acpi_match_device_ids(dev, excluded_id_list));
 }
@@ -72,40 +73,24 @@ static int __init ispnpidacpi(char *id)
 	return 1;
 }
 
-static void __init pnpidacpi_to_pnpid(char *id, char *str)
+static int pnpacpi_get_resources(struct pnp_dev *dev)
 {
-	str[0] = id[0];
-	str[1] = id[1];
-	str[2] = id[2];
-	str[3] = tolower(id[3]);
-	str[4] = tolower(id[4]);
-	str[5] = tolower(id[5]);
-	str[6] = tolower(id[6]);
-	str[7] = '\0';
+	dev_dbg(&dev->dev, "get resources\n");
+	return pnpacpi_parse_allocated_resource(dev);
 }
 
-static int pnpacpi_get_resources(struct pnp_dev *dev,
-				 struct pnp_resource_table *res)
-{
-	acpi_status status;
-
-	status = pnpacpi_parse_allocated_resource((acpi_handle) dev->data,
-						  &dev->res);
-	return ACPI_FAILURE(status) ? -ENODEV : 0;
-}
-
-static int pnpacpi_set_resources(struct pnp_dev *dev,
-				 struct pnp_resource_table *res)
+static int pnpacpi_set_resources(struct pnp_dev *dev)
 {
 	acpi_handle handle = dev->data;
 	struct acpi_buffer buffer;
-	int ret = 0;
+	int ret;
 	acpi_status status;
 
-	ret = pnpacpi_build_resource_template(handle, &buffer);
+	dev_dbg(&dev->dev, "set resources\n");
+	ret = pnpacpi_build_resource_template(dev, &buffer);
 	if (ret)
 		return ret;
-	ret = pnpacpi_encode_resources(res, &buffer);
+	ret = pnpacpi_encode_resources(dev, &buffer);
 	if (ret) {
 		kfree(buffer.pointer);
 		return ret;
@@ -163,7 +148,6 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
 {
 	acpi_handle temp = NULL;
 	acpi_status status;
-	struct pnp_id *dev_id;
 	struct pnp_dev *dev;
 
 	status = acpi_get_handle(device->handle, "_CRS", &temp);
@@ -171,11 +155,10 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
 	    is_exclusive_device(device))
 		return 0;
 
-	dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
-	if (!dev) {
-		pnp_err("Out of memory");
+	dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device));
+	if (!dev)
 		return -ENOMEM;
-	}
+
 	dev->data = device->handle;
 	/* .enabled means the device can decode the resources */
 	dev->active = device->status.enabled;
@@ -191,44 +174,17 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
 	if (ACPI_SUCCESS(status))
 		dev->capabilities |= PNP_DISABLE;
 
-	dev->protocol = &pnpacpi_protocol;
-
 	if (strlen(acpi_device_name(device)))
 		strncpy(dev->name, acpi_device_name(device), sizeof(dev->name));
 	else
 		strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name));
 
-	dev->number = num;
-
-	/* set the initial values for the PnP device */
-	dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
-	if (!dev_id)
-		goto err;
-	pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id);
-	pnp_add_id(dev_id, dev);
-
-	if (dev->active) {
-		/* parse allocated resource */
-		status = pnpacpi_parse_allocated_resource(device->handle,
-							  &dev->res);
-		if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
-			pnp_err("PnPACPI: METHOD_NAME__CRS failure for %s",
-				dev_id->id);
-			goto err1;
-		}
-	}
+	if (dev->active)
+		pnpacpi_parse_allocated_resource(dev);
 
-	if (dev->capabilities & PNP_CONFIGURABLE) {
-		status = pnpacpi_parse_resource_option_data(device->handle,
-							    dev);
-		if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
-			pnp_err("PnPACPI: METHOD_NAME__PRS failure for %s",
-				dev_id->id);
-			goto err1;
-		}
-	}
+	if (dev->capabilities & PNP_CONFIGURABLE)
+		pnpacpi_parse_resource_option_data(dev);
 
-	/* parse compatible ids */
 	if (device->flags.compatible_ids) {
 		struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
 		int i;
@@ -236,27 +192,17 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
 		for (i = 0; i < cid_list->count; i++) {
 			if (!ispnpidacpi(cid_list->id[i].value))
 				continue;
-			dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
-			if (!dev_id)
-				continue;
-
-			pnpidacpi_to_pnpid(cid_list->id[i].value, dev_id->id);
-			pnp_add_id(dev_id, dev);
+			pnp_add_id(dev, cid_list->id[i].value);
 		}
 	}
 
 	/* clear out the damaged flags */
 	if (!dev->active)
-		pnp_init_resource_table(&dev->res);
+		pnp_init_resources(dev);
 	pnp_add_device(dev);
 	num++;
 
 	return AE_OK;
-err1:
-	kfree(dev_id);
-err:
-	kfree(dev);
-	return -EINVAL;
 }
 
 static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle,
diff --git a/drivers/pnp/pnpacpi/pnpacpi.h b/drivers/pnp/pnpacpi/pnpacpi.h
index f28e2ed66fa3..3e60225b0227 100644
--- a/drivers/pnp/pnpacpi/pnpacpi.h
+++ b/drivers/pnp/pnpacpi/pnpacpi.h
@@ -5,8 +5,8 @@
 #include <linux/acpi.h>
 #include <linux/pnp.h>
 
-acpi_status pnpacpi_parse_allocated_resource(acpi_handle, struct pnp_resource_table*);
-acpi_status pnpacpi_parse_resource_option_data(acpi_handle, struct pnp_dev*);
-int pnpacpi_encode_resources(struct pnp_resource_table *, struct acpi_buffer *);
-int pnpacpi_build_resource_template(acpi_handle, struct acpi_buffer*);
+int pnpacpi_parse_allocated_resource(struct pnp_dev *);
+int pnpacpi_parse_resource_option_data(struct pnp_dev *);
+int pnpacpi_encode_resources(struct pnp_dev *, struct acpi_buffer *);
+int pnpacpi_build_resource_template(struct pnp_dev *, struct acpi_buffer *);
 #endif
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 98cbc9f18eed..0201c8adfda7 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -21,6 +21,8 @@
 #include <linux/kernel.h>
 #include <linux/acpi.h>
 #include <linux/pci.h>
+#include <linux/pnp.h>
+#include "../base.h"
 #include "pnpacpi.h"
 
 #ifdef CONFIG_IA64
@@ -32,19 +34,26 @@
 /*
  * Allocated Resources
  */
-static int irq_flags(int triggering, int polarity)
+static int irq_flags(int triggering, int polarity, int shareable)
 {
+	int flags;
+
 	if (triggering == ACPI_LEVEL_SENSITIVE) {
 		if (polarity == ACPI_ACTIVE_LOW)
-			return IORESOURCE_IRQ_LOWLEVEL;
+			flags = IORESOURCE_IRQ_LOWLEVEL;
 		else
-			return IORESOURCE_IRQ_HIGHLEVEL;
+			flags = IORESOURCE_IRQ_HIGHLEVEL;
 	} else {
 		if (polarity == ACPI_ACTIVE_LOW)
-			return IORESOURCE_IRQ_LOWEDGE;
+			flags = IORESOURCE_IRQ_LOWEDGE;
 		else
-			return IORESOURCE_IRQ_HIGHEDGE;
+			flags = IORESOURCE_IRQ_HIGHEDGE;
 	}
+
+	if (shareable)
+		flags |= IORESOURCE_IRQ_SHAREABLE;
+
+	return flags;
 }
 
 static void decode_irq_flags(int flag, int *triggering, int *polarity)
@@ -69,29 +78,16 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity)
 	}
 }
 
-static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
+static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
 						u32 gsi, int triggering,
 						int polarity, int shareable)
 {
-	int i = 0;
-	int irq;
+	int irq, flags;
 	int p, t;
-	static unsigned char warned;
 
 	if (!valid_IRQ(gsi))
 		return;
 
-	while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) &&
-	       i < PNP_MAX_IRQ)
-		i++;
-	if (i >= PNP_MAX_IRQ) {
-		if (!warned) {
-			printk(KERN_WARNING "pnpacpi: exceeded the max number"
-				" of IRQ resources: %d\n", PNP_MAX_IRQ);
-			warned = 1;
-		}
-		return;
-	}
 	/*
 	 * in IO-APIC mode, use overrided attribute. Two reasons:
 	 * 1. BIOS bug in DSDT
@@ -102,27 +98,21 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
 		p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
 
 		if (triggering != t || polarity != p) {
-			pnp_warn("IRQ %d override to %s, %s",
+			dev_warn(&dev->dev, "IRQ %d override to %s, %s\n",
 				gsi, t ? "edge":"level", p ? "low":"high");
 			triggering = t;
 			polarity = p;
 		}
 	}
 
-	res->irq_resource[i].flags = IORESOURCE_IRQ;	// Also clears _UNSET flag
-	res->irq_resource[i].flags |= irq_flags(triggering, polarity);
+	flags = irq_flags(triggering, polarity, shareable);
 	irq = acpi_register_gsi(gsi, triggering, polarity);
-	if (irq < 0) {
-		res->irq_resource[i].flags |= IORESOURCE_DISABLED;
-		return;
-	}
-
-	if (shareable)
-		res->irq_resource[i].flags |= IORESOURCE_IRQ_SHAREABLE;
+	if (irq >= 0)
+		pcibios_penalize_isa_irq(irq, 1);
+	else
+		flags |= IORESOURCE_DISABLED;
 
-	res->irq_resource[i].start = irq;
-	res->irq_resource[i].end = irq;
-	pcibios_penalize_isa_irq(irq, 1);
+	pnp_add_irq_resource(dev, irq, flags);
 }
 
 static int dma_flags(int type, int bus_master, int transfer)
@@ -168,88 +158,36 @@ static int dma_flags(int type, int bus_master, int transfer)
 	return flags;
 }
 
-static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res,
-						u32 dma, int type,
-						int bus_master, int transfer)
+static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
+					       u64 len, int io_decode)
 {
-	int i = 0;
-	static unsigned char warned;
-
-	while (i < PNP_MAX_DMA &&
-	       !(res->dma_resource[i].flags & IORESOURCE_UNSET))
-		i++;
-	if (i < PNP_MAX_DMA) {
-		res->dma_resource[i].flags = IORESOURCE_DMA;	// Also clears _UNSET flag
-		res->dma_resource[i].flags |=
-		    dma_flags(type, bus_master, transfer);
-		if (dma == -1) {
-			res->dma_resource[i].flags |= IORESOURCE_DISABLED;
-			return;
-		}
-		res->dma_resource[i].start = dma;
-		res->dma_resource[i].end = dma;
-	} else if (!warned) {
-		printk(KERN_WARNING "pnpacpi: exceeded the max number of DMA "
-				"resources: %d \n", PNP_MAX_DMA);
-		warned = 1;
-	}
-}
+	int flags = 0;
+	u64 end = start + len - 1;
 
-static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res,
-					       u64 io, u64 len, int io_decode)
-{
-	int i = 0;
-	static unsigned char warned;
+	if (io_decode == ACPI_DECODE_16)
+		flags |= PNP_PORT_FLAG_16BITADDR;
+	if (len == 0 || end >= 0x10003)
+		flags |= IORESOURCE_DISABLED;
 
-	while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
-	       i < PNP_MAX_PORT)
-		i++;
-	if (i < PNP_MAX_PORT) {
-		res->port_resource[i].flags = IORESOURCE_IO;	// Also clears _UNSET flag
-		if (io_decode == ACPI_DECODE_16)
-			res->port_resource[i].flags |= PNP_PORT_FLAG_16BITADDR;
-		if (len <= 0 || (io + len - 1) >= 0x10003) {
-			res->port_resource[i].flags |= IORESOURCE_DISABLED;
-			return;
-		}
-		res->port_resource[i].start = io;
-		res->port_resource[i].end = io + len - 1;
-	} else if (!warned) {
-		printk(KERN_WARNING "pnpacpi: exceeded the max number of IO "
-				"resources: %d \n", PNP_MAX_PORT);
-		warned = 1;
-	}
+	pnp_add_io_resource(dev, start, end, flags);
 }
 
-static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res,
-						u64 mem, u64 len,
+static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
+						u64 start, u64 len,
 						int write_protect)
 {
-	int i = 0;
-	static unsigned char warned;
+	int flags = 0;
+	u64 end = start + len - 1;
 
-	while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) &&
-	       (i < PNP_MAX_MEM))
-		i++;
-	if (i < PNP_MAX_MEM) {
-		res->mem_resource[i].flags = IORESOURCE_MEM;	// Also clears _UNSET flag
-		if (len <= 0) {
-			res->mem_resource[i].flags |= IORESOURCE_DISABLED;
-			return;
-		}
-		if (write_protect == ACPI_READ_WRITE_MEMORY)
-			res->mem_resource[i].flags |= IORESOURCE_MEM_WRITEABLE;
-
-		res->mem_resource[i].start = mem;
-		res->mem_resource[i].end = mem + len - 1;
-	} else if (!warned) {
-		printk(KERN_WARNING "pnpacpi: exceeded the max number of mem "
-				"resources: %d\n", PNP_MAX_MEM);
-		warned = 1;
-	}
+	if (len == 0)
+		flags |= IORESOURCE_DISABLED;
+	if (write_protect == ACPI_READ_WRITE_MEMORY)
+		flags |= IORESOURCE_MEM_WRITEABLE;
+
+	pnp_add_mem_resource(dev, start, end, flags);
 }
 
-static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table,
+static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
 						  struct acpi_resource *res)
 {
 	struct acpi_resource_address64 addr, *p = &addr;
@@ -257,7 +195,7 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res
 
 	status = acpi_resource_to_address64(res, p);
 	if (!ACPI_SUCCESS(status)) {
-		pnp_warn("PnPACPI: failed to convert resource type %d",
+		dev_warn(&dev->dev, "failed to convert resource type %d\n",
 			 res->type);
 		return;
 	}
@@ -266,11 +204,11 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res
 		return;
 
 	if (p->resource_type == ACPI_MEMORY_RANGE)
-		pnpacpi_parse_allocated_memresource(res_table,
+		pnpacpi_parse_allocated_memresource(dev,
 			p->minimum, p->address_length,
 			p->info.mem.write_protect);
 	else if (p->resource_type == ACPI_IO_RANGE)
-		pnpacpi_parse_allocated_ioresource(res_table,
+		pnpacpi_parse_allocated_ioresource(dev,
 			p->minimum, p->address_length,
 			p->granularity == 0xfff ? ACPI_DECODE_10 :
 				ACPI_DECODE_16);
@@ -279,8 +217,16 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res
 static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
 					      void *data)
 {
-	struct pnp_resource_table *res_table = data;
-	int i;
+	struct pnp_dev *dev = data;
+	struct acpi_resource_irq *irq;
+	struct acpi_resource_dma *dma;
+	struct acpi_resource_io *io;
+	struct acpi_resource_fixed_io *fixed_io;
+	struct acpi_resource_memory24 *memory24;
+	struct acpi_resource_memory32 *memory32;
+	struct acpi_resource_fixed_memory32 *fixed_memory32;
+	struct acpi_resource_extended_irq *extended_irq;
+	int i, flags;
 
 	switch (res->type) {
 	case ACPI_RESOURCE_TYPE_IRQ:
@@ -288,29 +234,33 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
 		 * Per spec, only one interrupt per descriptor is allowed in
 		 * _CRS, but some firmware violates this, so parse them all.
 		 */
-		for (i = 0; i < res->data.irq.interrupt_count; i++) {
-			pnpacpi_parse_allocated_irqresource(res_table,
-				res->data.irq.interrupts[i],
-				res->data.irq.triggering,
-				res->data.irq.polarity,
-				res->data.irq.sharable);
+		irq = &res->data.irq;
+		for (i = 0; i < irq->interrupt_count; i++) {
+			pnpacpi_parse_allocated_irqresource(dev,
+				irq->interrupts[i],
+				irq->triggering,
+				irq->polarity,
+				irq->sharable);
 		}
 		break;
 
 	case ACPI_RESOURCE_TYPE_DMA:
-		if (res->data.dma.channel_count > 0)
-			pnpacpi_parse_allocated_dmaresource(res_table,
-				res->data.dma.channels[0],
-				res->data.dma.type,
-				res->data.dma.bus_master,
-				res->data.dma.transfer);
+		dma = &res->data.dma;
+		if (dma->channel_count > 0) {
+			flags = dma_flags(dma->type, dma->bus_master,
+					  dma->transfer);
+			if (dma->channels[0] == (u8) -1)
+				flags |= IORESOURCE_DISABLED;
+			pnp_add_dma_resource(dev, dma->channels[0], flags);
+		}
 		break;
 
 	case ACPI_RESOURCE_TYPE_IO:
-		pnpacpi_parse_allocated_ioresource(res_table,
-			res->data.io.minimum,
-			res->data.io.address_length,
-			res->data.io.io_decode);
+		io = &res->data.io;
+		pnpacpi_parse_allocated_ioresource(dev,
+			io->minimum,
+			io->address_length,
+			io->io_decode);
 		break;
 
 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
@@ -318,9 +268,10 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
 		break;
 
 	case ACPI_RESOURCE_TYPE_FIXED_IO:
-		pnpacpi_parse_allocated_ioresource(res_table,
-			res->data.fixed_io.address,
-			res->data.fixed_io.address_length,
+		fixed_io = &res->data.fixed_io;
+		pnpacpi_parse_allocated_ioresource(dev,
+			fixed_io->address,
+			fixed_io->address_length,
 			ACPI_DECODE_10);
 		break;
 
@@ -331,27 +282,30 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
 		break;
 
 	case ACPI_RESOURCE_TYPE_MEMORY24:
-		pnpacpi_parse_allocated_memresource(res_table,
-			res->data.memory24.minimum,
-			res->data.memory24.address_length,
-			res->data.memory24.write_protect);
+		memory24 = &res->data.memory24;
+		pnpacpi_parse_allocated_memresource(dev,
+			memory24->minimum,
+			memory24->address_length,
+			memory24->write_protect);
 		break;
 	case ACPI_RESOURCE_TYPE_MEMORY32:
-		pnpacpi_parse_allocated_memresource(res_table,
-			res->data.memory32.minimum,
-			res->data.memory32.address_length,
-			res->data.memory32.write_protect);
+		memory32 = &res->data.memory32;
+		pnpacpi_parse_allocated_memresource(dev,
+			memory32->minimum,
+			memory32->address_length,
+			memory32->write_protect);
 		break;
 	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-		pnpacpi_parse_allocated_memresource(res_table,
-			res->data.fixed_memory32.address,
-			res->data.fixed_memory32.address_length,
-			res->data.fixed_memory32.write_protect);
+		fixed_memory32 = &res->data.fixed_memory32;
+		pnpacpi_parse_allocated_memresource(dev,
+			fixed_memory32->address,
+			fixed_memory32->address_length,
+			fixed_memory32->write_protect);
 		break;
 	case ACPI_RESOURCE_TYPE_ADDRESS16:
 	case ACPI_RESOURCE_TYPE_ADDRESS32:
 	case ACPI_RESOURCE_TYPE_ADDRESS64:
-		pnpacpi_parse_allocated_address_space(res_table, res);
+		pnpacpi_parse_allocated_address_space(dev, res);
 		break;
 
 	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
@@ -360,15 +314,16 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
 		break;
 
 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
-		if (res->data.extended_irq.producer_consumer == ACPI_PRODUCER)
+		extended_irq = &res->data.extended_irq;
+		if (extended_irq->producer_consumer == ACPI_PRODUCER)
 			return AE_OK;
 
-		for (i = 0; i < res->data.extended_irq.interrupt_count; i++) {
-			pnpacpi_parse_allocated_irqresource(res_table,
-				res->data.extended_irq.interrupts[i],
-				res->data.extended_irq.triggering,
-				res->data.extended_irq.polarity,
-				res->data.extended_irq.sharable);
+		for (i = 0; i < extended_irq->interrupt_count; i++) {
+			pnpacpi_parse_allocated_irqresource(dev,
+				extended_irq->interrupts[i],
+				extended_irq->triggering,
+				extended_irq->polarity,
+				extended_irq->sharable);
 		}
 		break;
 
@@ -376,24 +331,36 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
 		break;
 
 	default:
-		pnp_warn("PnPACPI: unknown resource type %d", res->type);
+		dev_warn(&dev->dev, "unknown resource type %d in _CRS\n",
+			 res->type);
 		return AE_ERROR;
 	}
 
 	return AE_OK;
 }
 
-acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle,
-					     struct pnp_resource_table * res)
+int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
 {
-	/* Blank the resource table values */
-	pnp_init_resource_table(res);
+	acpi_handle handle = dev->data;
+	acpi_status status;
+
+	dev_dbg(&dev->dev, "parse allocated resources\n");
 
-	return acpi_walk_resources(handle, METHOD_NAME__CRS,
-				   pnpacpi_allocated_resource, res);
+	pnp_init_resources(dev);
+
+	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+				     pnpacpi_allocated_resource, dev);
+
+	if (ACPI_FAILURE(status)) {
+		if (status != AE_NOT_FOUND)
+			dev_err(&dev->dev, "can't evaluate _CRS: %d", status);
+		return -EPERM;
+	}
+	return 0;
 }
 
-static __init void pnpacpi_parse_dma_option(struct pnp_option *option,
+static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
+					    struct pnp_option *option,
 					    struct acpi_resource_dma *p)
 {
 	int i;
@@ -410,10 +377,11 @@ static __init void pnpacpi_parse_dma_option(struct pnp_option *option,
 
 	dma->flags = dma_flags(p->type, p->bus_master, p->transfer);
 
-	pnp_register_dma_resource(option, dma);
+	pnp_register_dma_resource(dev, option, dma);
 }
 
-static __init void pnpacpi_parse_irq_option(struct pnp_option *option,
+static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
+					    struct pnp_option *option,
 					    struct acpi_resource_irq *p)
 {
 	int i;
@@ -428,12 +396,13 @@ static __init void pnpacpi_parse_irq_option(struct pnp_option *option,
 	for (i = 0; i < p->interrupt_count; i++)
 		if (p->interrupts[i])
 			__set_bit(p->interrupts[i], irq->map);
-	irq->flags = irq_flags(p->triggering, p->polarity);
+	irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
 
-	pnp_register_irq_resource(option, irq);
+	pnp_register_irq_resource(dev, option, irq);
 }
 
-static __init void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
+static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
+						struct pnp_option *option,
 					struct acpi_resource_extended_irq *p)
 {
 	int i;
@@ -448,12 +417,13 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
 	for (i = 0; i < p->interrupt_count; i++)
 		if (p->interrupts[i])
 			__set_bit(p->interrupts[i], irq->map);
-	irq->flags = irq_flags(p->triggering, p->polarity);
+	irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
 
-	pnp_register_irq_resource(option, irq);
+	pnp_register_irq_resource(dev, option, irq);
 }
 
-static __init void pnpacpi_parse_port_option(struct pnp_option *option,
+static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
+					     struct pnp_option *option,
 					     struct acpi_resource_io *io)
 {
 	struct pnp_port *port;
@@ -469,10 +439,11 @@ static __init void pnpacpi_parse_port_option(struct pnp_option *option,
 	port->size = io->address_length;
 	port->flags = ACPI_DECODE_16 == io->io_decode ?
 	    PNP_PORT_FLAG_16BITADDR : 0;
-	pnp_register_port_resource(option, port);
+	pnp_register_port_resource(dev, option, port);
 }
 
-static __init void pnpacpi_parse_fixed_port_option(struct pnp_option *option,
+static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
+						   struct pnp_option *option,
 					struct acpi_resource_fixed_io *io)
 {
 	struct pnp_port *port;
@@ -486,10 +457,11 @@ static __init void pnpacpi_parse_fixed_port_option(struct pnp_option *option,
 	port->size = io->address_length;
 	port->align = 0;
 	port->flags = PNP_PORT_FLAG_FIXED;
-	pnp_register_port_resource(option, port);
+	pnp_register_port_resource(dev, option, port);
 }
 
-static __init void pnpacpi_parse_mem24_option(struct pnp_option *option,
+static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
+					      struct pnp_option *option,
 					      struct acpi_resource_memory24 *p)
 {
 	struct pnp_mem *mem;
@@ -507,10 +479,11 @@ static __init void pnpacpi_parse_mem24_option(struct pnp_option *option,
 	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
 	    IORESOURCE_MEM_WRITEABLE : 0;
 
-	pnp_register_mem_resource(option, mem);
+	pnp_register_mem_resource(dev, option, mem);
 }
 
-static __init void pnpacpi_parse_mem32_option(struct pnp_option *option,
+static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
+					      struct pnp_option *option,
 					      struct acpi_resource_memory32 *p)
 {
 	struct pnp_mem *mem;
@@ -528,10 +501,11 @@ static __init void pnpacpi_parse_mem32_option(struct pnp_option *option,
 	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
 	    IORESOURCE_MEM_WRITEABLE : 0;
 
-	pnp_register_mem_resource(option, mem);
+	pnp_register_mem_resource(dev, option, mem);
 }
 
-static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
+static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
+						    struct pnp_option *option,
 					struct acpi_resource_fixed_memory32 *p)
 {
 	struct pnp_mem *mem;
@@ -548,10 +522,11 @@ static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
 	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
 	    IORESOURCE_MEM_WRITEABLE : 0;
 
-	pnp_register_mem_resource(option, mem);
+	pnp_register_mem_resource(dev, option, mem);
 }
 
-static __init void pnpacpi_parse_address_option(struct pnp_option *option,
+static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
+						struct pnp_option *option,
 						struct acpi_resource *r)
 {
 	struct acpi_resource_address64 addr, *p = &addr;
@@ -579,7 +554,7 @@ static __init void pnpacpi_parse_address_option(struct pnp_option *option,
 		mem->flags = (p->info.mem.write_protect ==
 			      ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE
 		    : 0;
-		pnp_register_mem_resource(option, mem);
+		pnp_register_mem_resource(dev, option, mem);
 	} else if (p->resource_type == ACPI_IO_RANGE) {
 		port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
 		if (!port)
@@ -588,7 +563,7 @@ static __init void pnpacpi_parse_address_option(struct pnp_option *option,
 		port->size = p->address_length;
 		port->align = 0;
 		port->flags = PNP_PORT_FLAG_FIXED;
-		pnp_register_port_resource(option, port);
+		pnp_register_port_resource(dev, option, port);
 	}
 }
 
@@ -608,11 +583,11 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
 
 	switch (res->type) {
 	case ACPI_RESOURCE_TYPE_IRQ:
-		pnpacpi_parse_irq_option(option, &res->data.irq);
+		pnpacpi_parse_irq_option(dev, option, &res->data.irq);
 		break;
 
 	case ACPI_RESOURCE_TYPE_DMA:
-		pnpacpi_parse_dma_option(option, &res->data.dma);
+		pnpacpi_parse_dma_option(dev, option, &res->data.dma);
 		break;
 
 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
@@ -642,19 +617,22 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
 	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
 		/*only one EndDependentFn is allowed */
 		if (!parse_data->option_independent) {
-			pnp_warn("PnPACPI: more than one EndDependentFn");
+			dev_warn(&dev->dev, "more than one EndDependentFn "
+				 "in _PRS\n");
 			return AE_ERROR;
 		}
 		parse_data->option = parse_data->option_independent;
 		parse_data->option_independent = NULL;
+		dev_dbg(&dev->dev, "end dependent options\n");
 		break;
 
 	case ACPI_RESOURCE_TYPE_IO:
-		pnpacpi_parse_port_option(option, &res->data.io);
+		pnpacpi_parse_port_option(dev, option, &res->data.io);
 		break;
 
 	case ACPI_RESOURCE_TYPE_FIXED_IO:
-		pnpacpi_parse_fixed_port_option(option, &res->data.fixed_io);
+		pnpacpi_parse_fixed_port_option(dev, option,
+					        &res->data.fixed_io);
 		break;
 
 	case ACPI_RESOURCE_TYPE_VENDOR:
@@ -662,57 +640,67 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
 		break;
 
 	case ACPI_RESOURCE_TYPE_MEMORY24:
-		pnpacpi_parse_mem24_option(option, &res->data.memory24);
+		pnpacpi_parse_mem24_option(dev, option, &res->data.memory24);
 		break;
 
 	case ACPI_RESOURCE_TYPE_MEMORY32:
-		pnpacpi_parse_mem32_option(option, &res->data.memory32);
+		pnpacpi_parse_mem32_option(dev, option, &res->data.memory32);
 		break;
 
 	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-		pnpacpi_parse_fixed_mem32_option(option,
+		pnpacpi_parse_fixed_mem32_option(dev, option,
 						 &res->data.fixed_memory32);
 		break;
 
 	case ACPI_RESOURCE_TYPE_ADDRESS16:
 	case ACPI_RESOURCE_TYPE_ADDRESS32:
 	case ACPI_RESOURCE_TYPE_ADDRESS64:
-		pnpacpi_parse_address_option(option, res);
+		pnpacpi_parse_address_option(dev, option, res);
 		break;
 
 	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
 		break;
 
 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
-		pnpacpi_parse_ext_irq_option(option, &res->data.extended_irq);
+		pnpacpi_parse_ext_irq_option(dev, option,
+					     &res->data.extended_irq);
 		break;
 
 	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
 		break;
 
 	default:
-		pnp_warn("PnPACPI: unknown resource type %d", res->type);
+		dev_warn(&dev->dev, "unknown resource type %d in _PRS\n",
+			 res->type);
 		return AE_ERROR;
 	}
 
 	return AE_OK;
 }
 
-acpi_status __init pnpacpi_parse_resource_option_data(acpi_handle handle,
-						      struct pnp_dev *dev)
+int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
 {
+	acpi_handle handle = dev->data;
 	acpi_status status;
 	struct acpipnp_parse_option_s parse_data;
 
+	dev_dbg(&dev->dev, "parse resource options\n");
+
 	parse_data.option = pnp_register_independent_option(dev);
 	if (!parse_data.option)
-		return AE_ERROR;
+		return -ENOMEM;
+
 	parse_data.option_independent = parse_data.option;
 	parse_data.dev = dev;
 	status = acpi_walk_resources(handle, METHOD_NAME__PRS,
 				     pnpacpi_option_resource, &parse_data);
 
-	return status;
+	if (ACPI_FAILURE(status)) {
+		if (status != AE_NOT_FOUND)
+			dev_err(&dev->dev, "can't evaluate _PRS: %d", status);
+		return -EPERM;
+	}
+	return 0;
 }
 
 static int pnpacpi_supported_resource(struct acpi_resource *res)
@@ -760,9 +748,10 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
 	return AE_OK;
 }
 
-int pnpacpi_build_resource_template(acpi_handle handle,
+int pnpacpi_build_resource_template(struct pnp_dev *dev,
 				    struct acpi_buffer *buffer)
 {
+	acpi_handle handle = dev->data;
 	struct acpi_resource *resource;
 	int res_cnt = 0;
 	acpi_status status;
@@ -770,7 +759,7 @@ int pnpacpi_build_resource_template(acpi_handle handle,
 	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
 				     pnpacpi_count_resources, &res_cnt);
 	if (ACPI_FAILURE(status)) {
-		pnp_err("Evaluate _CRS failed");
+		dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);
 		return -EINVAL;
 	}
 	if (!res_cnt)
@@ -779,13 +768,13 @@ int pnpacpi_build_resource_template(acpi_handle handle,
 	buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL);
 	if (!buffer->pointer)
 		return -ENOMEM;
-	pnp_dbg("Res cnt %d", res_cnt);
+
 	resource = (struct acpi_resource *)buffer->pointer;
 	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
 				     pnpacpi_type_resources, &resource);
 	if (ACPI_FAILURE(status)) {
 		kfree(buffer->pointer);
-		pnp_err("Evaluate _CRS failed");
+		dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);
 		return -EINVAL;
 	}
 	/* resource will pointer the end resource now */
@@ -794,129 +783,184 @@ int pnpacpi_build_resource_template(acpi_handle handle,
 	return 0;
 }
 
-static void pnpacpi_encode_irq(struct acpi_resource *resource,
+static void pnpacpi_encode_irq(struct pnp_dev *dev,
+			       struct acpi_resource *resource,
 			       struct resource *p)
 {
+	struct acpi_resource_irq *irq = &resource->data.irq;
 	int triggering, polarity;
 
 	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
-	resource->data.irq.triggering = triggering;
-	resource->data.irq.polarity = polarity;
+	irq->triggering = triggering;
+	irq->polarity = polarity;
 	if (triggering == ACPI_EDGE_SENSITIVE)
-		resource->data.irq.sharable = ACPI_EXCLUSIVE;
+		irq->sharable = ACPI_EXCLUSIVE;
 	else
-		resource->data.irq.sharable = ACPI_SHARED;
-	resource->data.irq.interrupt_count = 1;
-	resource->data.irq.interrupts[0] = p->start;
+		irq->sharable = ACPI_SHARED;
+	irq->interrupt_count = 1;
+	irq->interrupts[0] = p->start;
+
+	dev_dbg(&dev->dev, "  encode irq %d %s %s %s\n", (int) p->start,
+		triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
+		polarity == ACPI_ACTIVE_LOW ? "low" : "high",
+		irq->sharable == ACPI_SHARED ? "shared" : "exclusive");
 }
 
-static void pnpacpi_encode_ext_irq(struct acpi_resource *resource,
+static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
+				   struct acpi_resource *resource,
 				   struct resource *p)
 {
+	struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
 	int triggering, polarity;
 
 	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
-	resource->data.extended_irq.producer_consumer = ACPI_CONSUMER;
-	resource->data.extended_irq.triggering = triggering;
-	resource->data.extended_irq.polarity = polarity;
+	extended_irq->producer_consumer = ACPI_CONSUMER;
+	extended_irq->triggering = triggering;
+	extended_irq->polarity = polarity;
 	if (triggering == ACPI_EDGE_SENSITIVE)
-		resource->data.irq.sharable = ACPI_EXCLUSIVE;
+		extended_irq->sharable = ACPI_EXCLUSIVE;
 	else
-		resource->data.irq.sharable = ACPI_SHARED;
-	resource->data.extended_irq.interrupt_count = 1;
-	resource->data.extended_irq.interrupts[0] = p->start;
+		extended_irq->sharable = ACPI_SHARED;
+	extended_irq->interrupt_count = 1;
+	extended_irq->interrupts[0] = p->start;
+
+	dev_dbg(&dev->dev, "  encode irq %d %s %s %s\n", (int) p->start,
+		triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
+		polarity == ACPI_ACTIVE_LOW ? "low" : "high",
+		extended_irq->sharable == ACPI_SHARED ? "shared" : "exclusive");
 }
 
-static void pnpacpi_encode_dma(struct acpi_resource *resource,
+static void pnpacpi_encode_dma(struct pnp_dev *dev,
+			       struct acpi_resource *resource,
 			       struct resource *p)
 {
+	struct acpi_resource_dma *dma = &resource->data.dma;
+
 	/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
 	switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
 	case IORESOURCE_DMA_TYPEA:
-		resource->data.dma.type = ACPI_TYPE_A;
+		dma->type = ACPI_TYPE_A;
 		break;
 	case IORESOURCE_DMA_TYPEB:
-		resource->data.dma.type = ACPI_TYPE_B;
+		dma->type = ACPI_TYPE_B;
 		break;
 	case IORESOURCE_DMA_TYPEF:
-		resource->data.dma.type = ACPI_TYPE_F;
+		dma->type = ACPI_TYPE_F;
 		break;
 	default:
-		resource->data.dma.type = ACPI_COMPATIBILITY;
+		dma->type = ACPI_COMPATIBILITY;
 	}
 
 	switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {
 	case IORESOURCE_DMA_8BIT:
-		resource->data.dma.transfer = ACPI_TRANSFER_8;
+		dma->transfer = ACPI_TRANSFER_8;
 		break;
 	case IORESOURCE_DMA_8AND16BIT:
-		resource->data.dma.transfer = ACPI_TRANSFER_8_16;
+		dma->transfer = ACPI_TRANSFER_8_16;
 		break;
 	default:
-		resource->data.dma.transfer = ACPI_TRANSFER_16;
+		dma->transfer = ACPI_TRANSFER_16;
 	}
 
-	resource->data.dma.bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
-	resource->data.dma.channel_count = 1;
-	resource->data.dma.channels[0] = p->start;
+	dma->bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
+	dma->channel_count = 1;
+	dma->channels[0] = p->start;
+
+	dev_dbg(&dev->dev, "  encode dma %d "
+		"type %#x transfer %#x master %d\n",
+		(int) p->start, dma->type, dma->transfer, dma->bus_master);
 }
 
-static void pnpacpi_encode_io(struct acpi_resource *resource,
+static void pnpacpi_encode_io(struct pnp_dev *dev,
+			      struct acpi_resource *resource,
 			      struct resource *p)
 {
+	struct acpi_resource_io *io = &resource->data.io;
+
 	/* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
-	resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
+	io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
 	    ACPI_DECODE_16 : ACPI_DECODE_10;
-	resource->data.io.minimum = p->start;
-	resource->data.io.maximum = p->end;
-	resource->data.io.alignment = 0;	/* Correct? */
-	resource->data.io.address_length = p->end - p->start + 1;
+	io->minimum = p->start;
+	io->maximum = p->end;
+	io->alignment = 0;	/* Correct? */
+	io->address_length = p->end - p->start + 1;
+
+	dev_dbg(&dev->dev, "  encode io %#llx-%#llx decode %#x\n",
+		(unsigned long long) p->start, (unsigned long long) p->end,
+		io->io_decode);
 }
 
-static void pnpacpi_encode_fixed_io(struct acpi_resource *resource,
+static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
+				    struct acpi_resource *resource,
 				    struct resource *p)
 {
-	resource->data.fixed_io.address = p->start;
-	resource->data.fixed_io.address_length = p->end - p->start + 1;
+	struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io;
+
+	fixed_io->address = p->start;
+	fixed_io->address_length = p->end - p->start + 1;
+
+	dev_dbg(&dev->dev, "  encode fixed_io %#llx-%#llx\n",
+		(unsigned long long) p->start, (unsigned long long) p->end);
 }
 
-static void pnpacpi_encode_mem24(struct acpi_resource *resource,
+static void pnpacpi_encode_mem24(struct pnp_dev *dev,
+				 struct acpi_resource *resource,
 				 struct resource *p)
 {
+	struct acpi_resource_memory24 *memory24 = &resource->data.memory24;
+
 	/* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
-	resource->data.memory24.write_protect =
+	memory24->write_protect =
 	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
 	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
-	resource->data.memory24.minimum = p->start;
-	resource->data.memory24.maximum = p->end;
-	resource->data.memory24.alignment = 0;
-	resource->data.memory24.address_length = p->end - p->start + 1;
+	memory24->minimum = p->start;
+	memory24->maximum = p->end;
+	memory24->alignment = 0;
+	memory24->address_length = p->end - p->start + 1;
+
+	dev_dbg(&dev->dev, "  encode mem24 %#llx-%#llx write_protect %#x\n",
+		(unsigned long long) p->start, (unsigned long long) p->end,
+		memory24->write_protect);
 }
 
-static void pnpacpi_encode_mem32(struct acpi_resource *resource,
+static void pnpacpi_encode_mem32(struct pnp_dev *dev,
+				 struct acpi_resource *resource,
 				 struct resource *p)
 {
-	resource->data.memory32.write_protect =
+	struct acpi_resource_memory32 *memory32 = &resource->data.memory32;
+
+	memory32->write_protect =
 	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
 	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
-	resource->data.memory32.minimum = p->start;
-	resource->data.memory32.maximum = p->end;
-	resource->data.memory32.alignment = 0;
-	resource->data.memory32.address_length = p->end - p->start + 1;
+	memory32->minimum = p->start;
+	memory32->maximum = p->end;
+	memory32->alignment = 0;
+	memory32->address_length = p->end - p->start + 1;
+
+	dev_dbg(&dev->dev, "  encode mem32 %#llx-%#llx write_protect %#x\n",
+		(unsigned long long) p->start, (unsigned long long) p->end,
+		memory32->write_protect);
 }
 
-static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource,
+static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
+				       struct acpi_resource *resource,
 				       struct resource *p)
 {
-	resource->data.fixed_memory32.write_protect =
+	struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32;
+
+	fixed_memory32->write_protect =
 	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
 	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
-	resource->data.fixed_memory32.address = p->start;
-	resource->data.fixed_memory32.address_length = p->end - p->start + 1;
+	fixed_memory32->address = p->start;
+	fixed_memory32->address_length = p->end - p->start + 1;
+
+	dev_dbg(&dev->dev, "  encode fixed_mem32 %#llx-%#llx "
+		"write_protect %#x\n",
+		(unsigned long long) p->start, (unsigned long long) p->end,
+		fixed_memory32->write_protect);
 }
 
-int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
-			     struct acpi_buffer *buffer)
+int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer)
 {
 	int i = 0;
 	/* pnpacpi_build_resource_template allocates extra mem */
@@ -924,58 +968,48 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
 	struct acpi_resource *resource = buffer->pointer;
 	int port = 0, irq = 0, dma = 0, mem = 0;
 
-	pnp_dbg("res cnt %d", res_cnt);
+	dev_dbg(&dev->dev, "encode %d resources\n", res_cnt);
 	while (i < res_cnt) {
 		switch (resource->type) {
 		case ACPI_RESOURCE_TYPE_IRQ:
-			pnp_dbg("Encode irq");
-			pnpacpi_encode_irq(resource,
-					   &res_table->irq_resource[irq]);
+			pnpacpi_encode_irq(dev, resource,
+			       pnp_get_resource(dev, IORESOURCE_IRQ, irq));
 			irq++;
 			break;
 
 		case ACPI_RESOURCE_TYPE_DMA:
-			pnp_dbg("Encode dma");
-			pnpacpi_encode_dma(resource,
-					   &res_table->dma_resource[dma]);
+			pnpacpi_encode_dma(dev, resource,
+				pnp_get_resource(dev, IORESOURCE_DMA, dma));
 			dma++;
 			break;
 		case ACPI_RESOURCE_TYPE_IO:
-			pnp_dbg("Encode io");
-			pnpacpi_encode_io(resource,
-					  &res_table->port_resource[port]);
+			pnpacpi_encode_io(dev, resource,
+				pnp_get_resource(dev, IORESOURCE_IO, port));
 			port++;
 			break;
 		case ACPI_RESOURCE_TYPE_FIXED_IO:
-			pnp_dbg("Encode fixed io");
-			pnpacpi_encode_fixed_io(resource,
-						&res_table->
-						port_resource[port]);
+			pnpacpi_encode_fixed_io(dev, resource,
+				pnp_get_resource(dev, IORESOURCE_IO, port));
 			port++;
 			break;
 		case ACPI_RESOURCE_TYPE_MEMORY24:
-			pnp_dbg("Encode mem24");
-			pnpacpi_encode_mem24(resource,
-					     &res_table->mem_resource[mem]);
+			pnpacpi_encode_mem24(dev, resource,
+				pnp_get_resource(dev, IORESOURCE_MEM, mem));
 			mem++;
 			break;
 		case ACPI_RESOURCE_TYPE_MEMORY32:
-			pnp_dbg("Encode mem32");
-			pnpacpi_encode_mem32(resource,
-					     &res_table->mem_resource[mem]);
+			pnpacpi_encode_mem32(dev, resource,
+				pnp_get_resource(dev, IORESOURCE_MEM, mem));
 			mem++;
 			break;
 		case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-			pnp_dbg("Encode fixed mem32");
-			pnpacpi_encode_fixed_mem32(resource,
-						   &res_table->
-						   mem_resource[mem]);
+			pnpacpi_encode_fixed_mem32(dev, resource,
+				pnp_get_resource(dev, IORESOURCE_MEM, mem));
 			mem++;
 			break;
 		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
-			pnp_dbg("Encode ext irq");
-			pnpacpi_encode_ext_irq(resource,
-					       &res_table->irq_resource[irq]);
+			pnpacpi_encode_ext_irq(dev, resource,
+				pnp_get_resource(dev, IORESOURCE_IRQ, irq));
 			irq++;
 			break;
 		case ACPI_RESOURCE_TYPE_START_DEPENDENT:
@@ -988,7 +1022,8 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
 		case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
 		case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
 		default:	/* other type */
-			pnp_warn("unknown resource type %d", resource->type);
+			dev_warn(&dev->dev, "can't encode unknown resource "
+				 "type %d\n", resource->type);
 			return -EINVAL;
 		}
 		resource++;
diff --git a/drivers/pnp/pnpbios/Makefile b/drivers/pnp/pnpbios/Makefile
index 3cd3ed760605..310e2b3a7710 100644
--- a/drivers/pnp/pnpbios/Makefile
+++ b/drivers/pnp/pnpbios/Makefile
@@ -5,3 +5,7 @@
 pnpbios-proc-$(CONFIG_PNPBIOS_PROC_FS) = proc.o
 
 obj-y := core.o bioscalls.o rsparser.o $(pnpbios-proc-y)
+
+ifeq ($(CONFIG_PNP_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c
index a8364d815222..7ff824496b39 100644
--- a/drivers/pnp/pnpbios/bioscalls.c
+++ b/drivers/pnp/pnpbios/bioscalls.c
@@ -7,7 +7,6 @@
 #include <linux/init.h>
 #include <linux/linkage.h>
 #include <linux/kernel.h>
-#include <linux/pnpbios.h>
 #include <linux/device.h>
 #include <linux/pnp.h>
 #include <linux/mm.h>
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index a8a51500e1e9..19a4be1a9a31 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -50,7 +50,6 @@
 #include <linux/init.h>
 #include <linux/linkage.h>
 #include <linux/kernel.h>
-#include <linux/pnpbios.h>
 #include <linux/device.h>
 #include <linux/pnp.h>
 #include <linux/mm.h>
@@ -69,6 +68,7 @@
 #include <asm/system.h>
 #include <asm/byteorder.h>
 
+#include "../base.h"
 #include "pnpbios.h"
 
 /*
@@ -203,8 +203,7 @@ static int pnp_dock_thread(void *unused)
 
 #endif				/* CONFIG_HOTPLUG */
 
-static int pnpbios_get_resources(struct pnp_dev *dev,
-				 struct pnp_resource_table *res)
+static int pnpbios_get_resources(struct pnp_dev *dev)
 {
 	u8 nodenum = dev->number;
 	struct pnp_bios_node *node;
@@ -212,6 +211,7 @@ static int pnpbios_get_resources(struct pnp_dev *dev,
 	if (!pnpbios_is_dynamic(dev))
 		return -EPERM;
 
+	dev_dbg(&dev->dev, "get resources\n");
 	node = kzalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node)
 		return -1;
@@ -219,14 +219,13 @@ static int pnpbios_get_resources(struct pnp_dev *dev,
 		kfree(node);
 		return -ENODEV;
 	}
-	pnpbios_read_resources_from_node(res, node);
+	pnpbios_read_resources_from_node(dev, node);
 	dev->active = pnp_is_active(dev);
 	kfree(node);
 	return 0;
 }
 
-static int pnpbios_set_resources(struct pnp_dev *dev,
-				 struct pnp_resource_table *res)
+static int pnpbios_set_resources(struct pnp_dev *dev)
 {
 	u8 nodenum = dev->number;
 	struct pnp_bios_node *node;
@@ -235,6 +234,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev,
 	if (!pnpbios_is_dynamic(dev))
 		return -EPERM;
 
+	dev_dbg(&dev->dev, "set resources\n");
 	node = kzalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node)
 		return -1;
@@ -242,7 +242,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev,
 		kfree(node);
 		return -ENODEV;
 	}
-	if (pnpbios_write_resources_to_node(res, node) < 0) {
+	if (pnpbios_write_resources_to_node(dev, node) < 0) {
 		kfree(node);
 		return -1;
 	}
@@ -317,7 +317,6 @@ static int __init insert_device(struct pnp_bios_node *node)
 {
 	struct list_head *pos;
 	struct pnp_dev *dev;
-	struct pnp_id *dev_id;
 	char id[8];
 
 	/* check if the device is already added */
@@ -327,20 +326,11 @@ static int __init insert_device(struct pnp_bios_node *node)
 			return -1;
 	}
 
-	dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
+	pnp_eisa_id_to_string(node->eisa_id & PNP_EISA_ID_MASK, id);
+	dev = pnp_alloc_dev(&pnpbios_protocol, node->handle, id);
 	if (!dev)
 		return -1;
 
-	dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
-	if (!dev_id) {
-		kfree(dev);
-		return -1;
-	}
-
-	dev->number = node->handle;
-	pnpid32_to_pnpid(node->eisa_id, id);
-	memcpy(dev_id->id, id, 7);
-	pnp_add_id(dev_id, dev);
 	pnpbios_parse_data_stream(dev, node);
 	dev->active = pnp_is_active(dev);
 	dev->flags = node->flags;
@@ -353,11 +343,10 @@ static int __init insert_device(struct pnp_bios_node *node)
 		dev->capabilities |= PNP_WRITE;
 	if (dev->flags & PNPBIOS_REMOVABLE)
 		dev->capabilities |= PNP_REMOVABLE;
-	dev->protocol = &pnpbios_protocol;
 
 	/* clear out the damaged flags */
 	if (!dev->active)
-		pnp_init_resource_table(&dev->res);
+		pnp_init_resources(dev);
 
 	pnp_add_device(dev);
 	pnpbios_interface_attach_device(node);
diff --git a/drivers/pnp/pnpbios/pnpbios.h b/drivers/pnp/pnpbios/pnpbios.h
index d8cb2fd1f127..b09cf6dc2075 100644
--- a/drivers/pnp/pnpbios/pnpbios.h
+++ b/drivers/pnp/pnpbios/pnpbios.h
@@ -2,6 +2,142 @@
  * pnpbios.h - contains local definitions
  */
 
+/*
+ * Include file for the interface to a PnP BIOS
+ *
+ * Original BIOS code (C) 1998 Christian Schmidt (chr.schmidt@tu-bs.de)
+ * PnP handler parts (c) 1998 Tom Lees <tom@lpsg.demon.co.uk>
+ * Minor reorganizations by David Hinds <dahinds@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Return codes
+ */
+#define PNP_SUCCESS                     0x00
+#define PNP_NOT_SET_STATICALLY          0x7f
+#define PNP_UNKNOWN_FUNCTION            0x81
+#define PNP_FUNCTION_NOT_SUPPORTED      0x82
+#define PNP_INVALID_HANDLE              0x83
+#define PNP_BAD_PARAMETER               0x84
+#define PNP_SET_FAILED                  0x85
+#define PNP_EVENTS_NOT_PENDING          0x86
+#define PNP_SYSTEM_NOT_DOCKED           0x87
+#define PNP_NO_ISA_PNP_CARDS            0x88
+#define PNP_UNABLE_TO_DETERMINE_DOCK_CAPABILITIES 0x89
+#define PNP_CONFIG_CHANGE_FAILED_NO_BATTERY 0x8a
+#define PNP_CONFIG_CHANGE_FAILED_RESOURCE_CONFLICT 0x8b
+#define PNP_BUFFER_TOO_SMALL            0x8c
+#define PNP_USE_ESCD_SUPPORT            0x8d
+#define PNP_MESSAGE_NOT_SUPPORTED       0x8e
+#define PNP_HARDWARE_ERROR              0x8f
+
+#define ESCD_SUCCESS                    0x00
+#define ESCD_IO_ERROR_READING           0x55
+#define ESCD_INVALID                    0x56
+#define ESCD_BUFFER_TOO_SMALL           0x59
+#define ESCD_NVRAM_TOO_SMALL            0x5a
+#define ESCD_FUNCTION_NOT_SUPPORTED     0x81
+
+/*
+ * Events that can be received by "get event"
+ */
+#define PNPEV_ABOUT_TO_CHANGE_CONFIG	0x0001
+#define PNPEV_DOCK_CHANGED		0x0002
+#define PNPEV_SYSTEM_DEVICE_CHANGED	0x0003
+#define PNPEV_CONFIG_CHANGED_FAILED	0x0004
+#define PNPEV_UNKNOWN_SYSTEM_EVENT	0xffff
+/* 0x8000 through 0xfffe are OEM defined */
+
+/*
+ * Messages that should be sent through "send message"
+ */
+#define PNPMSG_OK			0x00
+#define PNPMSG_ABORT			0x01
+#define PNPMSG_UNDOCK_DEFAULT_ACTION	0x40
+#define PNPMSG_POWER_OFF		0x41
+#define PNPMSG_PNP_OS_ACTIVE		0x42
+#define PNPMSG_PNP_OS_INACTIVE		0x43
+
+/*
+ * Plug and Play BIOS flags
+ */
+#define PNPBIOS_NO_DISABLE		0x0001
+#define PNPBIOS_NO_CONFIG		0x0002
+#define PNPBIOS_OUTPUT			0x0004
+#define PNPBIOS_INPUT			0x0008
+#define PNPBIOS_BOOTABLE		0x0010
+#define PNPBIOS_DOCK			0x0020
+#define PNPBIOS_REMOVABLE		0x0040
+#define pnpbios_is_static(x) (((x)->flags & 0x0100) == 0x0000)
+#define pnpbios_is_dynamic(x) ((x)->flags & 0x0080)
+
+/*
+ * Function Parameters
+ */
+#define PNPMODE_STATIC 1
+#define PNPMODE_DYNAMIC 0
+
+/* 0x8000 through 0xffff are OEM defined */
+
+#pragma pack(1)
+struct pnp_dev_node_info {
+	__u16 no_nodes;
+	__u16 max_node_size;
+};
+struct pnp_docking_station_info {
+	__u32 location_id;
+	__u32 serial;
+	__u16 capabilities;
+};
+struct pnp_isa_config_struc {
+	__u8 revision;
+	__u8 no_csns;
+	__u16 isa_rd_data_port;
+	__u16 reserved;
+};
+struct escd_info_struc {
+	__u16 min_escd_write_size;
+	__u16 escd_size;
+	__u32 nv_storage_base;
+};
+struct pnp_bios_node {
+	__u16 size;
+	__u8 handle;
+	__u32 eisa_id;
+	__u8 type_code[3];
+	__u16 flags;
+	__u8 data[0];
+};
+#pragma pack()
+
+/* non-exported */
+extern struct pnp_dev_node_info node_info;
+
+extern int pnp_bios_dev_node_info(struct pnp_dev_node_info *data);
+extern int pnp_bios_get_dev_node(u8 *nodenum, char config,
+				 struct pnp_bios_node *data);
+extern int pnp_bios_set_dev_node(u8 nodenum, char config,
+				 struct pnp_bios_node *data);
+extern int pnp_bios_get_stat_res(char *info);
+extern int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data);
+extern int pnp_bios_escd_info(struct escd_info_struc *data);
+extern int pnp_bios_read_escd(char *data, u32 nvram_base);
+extern int pnp_bios_dock_station_info(struct pnp_docking_station_info *data);
+
 #pragma pack(1)
 union pnp_bios_install_struct {
 	struct {
@@ -28,8 +164,8 @@ extern int pnp_bios_present(void);
 extern int  pnpbios_dont_use_current_config;
 
 extern int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node * node);
-extern int pnpbios_read_resources_from_node(struct pnp_resource_table *res, struct pnp_bios_node * node);
-extern int pnpbios_write_resources_to_node(struct pnp_resource_table *res, struct pnp_bios_node * node);
+extern int pnpbios_read_resources_from_node(struct pnp_dev *dev, struct pnp_bios_node *node);
+extern int pnpbios_write_resources_to_node(struct pnp_dev *dev, struct pnp_bios_node *node);
 extern void pnpid32_to_pnpid(u32 id, char *str);
 
 extern void pnpbios_print_status(const char * module, u16 status);
diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c
index 46d506f66259..b35d921bac6e 100644
--- a/drivers/pnp/pnpbios/proc.c
+++ b/drivers/pnp/pnpbios/proc.c
@@ -23,7 +23,7 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
-#include <linux/pnpbios.h>
+#include <linux/pnp.h>
 #include <linux/init.h>
 
 #include <asm/uaccess.h>
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index caade3531416..2e2c457a0fea 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -4,7 +4,6 @@
 
 #include <linux/ctype.h>
 #include <linux/pnp.h>
-#include <linux/pnpbios.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 
@@ -16,6 +15,7 @@ inline void pcibios_penalize_isa_irq(int irq, int active)
 }
 #endif				/* CONFIG_PCI */
 
+#include "../base.h"
 #include "pnpbios.h"
 
 /* standard resource tags */
@@ -53,97 +53,43 @@ inline void pcibios_penalize_isa_irq(int irq, int active)
  * Allocated Resources
  */
 
-static void pnpbios_parse_allocated_irqresource(struct pnp_resource_table *res,
-						int irq)
+static void pnpbios_parse_allocated_ioresource(struct pnp_dev *dev,
+					       int start, int len)
 {
-	int i = 0;
-
-	while (!(res->irq_resource[i].flags & IORESOURCE_UNSET)
-	       && i < PNP_MAX_IRQ)
-		i++;
-	if (i < PNP_MAX_IRQ) {
-		res->irq_resource[i].flags = IORESOURCE_IRQ;	// Also clears _UNSET flag
-		if (irq == -1) {
-			res->irq_resource[i].flags |= IORESOURCE_DISABLED;
-			return;
-		}
-		res->irq_resource[i].start =
-		    res->irq_resource[i].end = (unsigned long)irq;
-		pcibios_penalize_isa_irq(irq, 1);
-	}
-}
+	int flags = 0;
+	int end = start + len - 1;
 
-static void pnpbios_parse_allocated_dmaresource(struct pnp_resource_table *res,
-						int dma)
-{
-	int i = 0;
-
-	while (i < PNP_MAX_DMA &&
-	       !(res->dma_resource[i].flags & IORESOURCE_UNSET))
-		i++;
-	if (i < PNP_MAX_DMA) {
-		res->dma_resource[i].flags = IORESOURCE_DMA;	// Also clears _UNSET flag
-		if (dma == -1) {
-			res->dma_resource[i].flags |= IORESOURCE_DISABLED;
-			return;
-		}
-		res->dma_resource[i].start =
-		    res->dma_resource[i].end = (unsigned long)dma;
-	}
-}
+	if (len <= 0 || end >= 0x10003)
+		flags |= IORESOURCE_DISABLED;
 
-static void pnpbios_parse_allocated_ioresource(struct pnp_resource_table *res,
-					       int io, int len)
-{
-	int i = 0;
-
-	while (!(res->port_resource[i].flags & IORESOURCE_UNSET)
-	       && i < PNP_MAX_PORT)
-		i++;
-	if (i < PNP_MAX_PORT) {
-		res->port_resource[i].flags = IORESOURCE_IO;	// Also clears _UNSET flag
-		if (len <= 0 || (io + len - 1) >= 0x10003) {
-			res->port_resource[i].flags |= IORESOURCE_DISABLED;
-			return;
-		}
-		res->port_resource[i].start = (unsigned long)io;
-		res->port_resource[i].end = (unsigned long)(io + len - 1);
-	}
+	pnp_add_io_resource(dev, start, end, flags);
 }
 
-static void pnpbios_parse_allocated_memresource(struct pnp_resource_table *res,
-						int mem, int len)
+static void pnpbios_parse_allocated_memresource(struct pnp_dev *dev,
+						int start, int len)
 {
-	int i = 0;
-
-	while (!(res->mem_resource[i].flags & IORESOURCE_UNSET)
-	       && i < PNP_MAX_MEM)
-		i++;
-	if (i < PNP_MAX_MEM) {
-		res->mem_resource[i].flags = IORESOURCE_MEM;	// Also clears _UNSET flag
-		if (len <= 0) {
-			res->mem_resource[i].flags |= IORESOURCE_DISABLED;
-			return;
-		}
-		res->mem_resource[i].start = (unsigned long)mem;
-		res->mem_resource[i].end = (unsigned long)(mem + len - 1);
-	}
+	int flags = 0;
+	int end = start + len - 1;
+
+	if (len <= 0)
+		flags |= IORESOURCE_DISABLED;
+
+	pnp_add_mem_resource(dev, start, end, flags);
 }
 
-static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
-							    unsigned char *end,
-							    struct
-							    pnp_resource_table
-							    *res)
+static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev,
+							    unsigned char *p,
+							    unsigned char *end)
 {
 	unsigned int len, tag;
-	int io, size, mask, i;
+	int io, size, mask, i, flags;
 
 	if (!p)
 		return NULL;
 
-	/* Blank the resource table values */
-	pnp_init_resource_table(res);
+	dev_dbg(&dev->dev, "parse allocated resources\n");
+
+	pnp_init_resources(dev);
 
 	while ((char *)p < (char *)end) {
 
@@ -163,7 +109,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
 				goto len_err;
 			io = *(short *)&p[4];
 			size = *(short *)&p[10];
-			pnpbios_parse_allocated_memresource(res, io, size);
+			pnpbios_parse_allocated_memresource(dev, io, size);
 			break;
 
 		case LARGE_TAG_ANSISTR:
@@ -179,7 +125,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
 				goto len_err;
 			io = *(int *)&p[4];
 			size = *(int *)&p[16];
-			pnpbios_parse_allocated_memresource(res, io, size);
+			pnpbios_parse_allocated_memresource(dev, io, size);
 			break;
 
 		case LARGE_TAG_FIXEDMEM32:
@@ -187,29 +133,37 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
 				goto len_err;
 			io = *(int *)&p[4];
 			size = *(int *)&p[8];
-			pnpbios_parse_allocated_memresource(res, io, size);
+			pnpbios_parse_allocated_memresource(dev, io, size);
 			break;
 
 		case SMALL_TAG_IRQ:
 			if (len < 2 || len > 3)
 				goto len_err;
+			flags = 0;
 			io = -1;
 			mask = p[1] + p[2] * 256;
 			for (i = 0; i < 16; i++, mask = mask >> 1)
 				if (mask & 0x01)
 					io = i;
-			pnpbios_parse_allocated_irqresource(res, io);
+			if (io != -1)
+				pcibios_penalize_isa_irq(io, 1);
+			else
+				flags = IORESOURCE_DISABLED;
+			pnp_add_irq_resource(dev, io, flags);
 			break;
 
 		case SMALL_TAG_DMA:
 			if (len != 2)
 				goto len_err;
+			flags = 0;
 			io = -1;
 			mask = p[1];
 			for (i = 0; i < 8; i++, mask = mask >> 1)
 				if (mask & 0x01)
 					io = i;
-			pnpbios_parse_allocated_dmaresource(res, io);
+			if (io == -1)
+				flags = IORESOURCE_DISABLED;
+			pnp_add_dma_resource(dev, io, flags);
 			break;
 
 		case SMALL_TAG_PORT:
@@ -217,7 +171,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
 				goto len_err;
 			io = p[2] + p[3] * 256;
 			size = p[7];
-			pnpbios_parse_allocated_ioresource(res, io, size);
+			pnpbios_parse_allocated_ioresource(dev, io, size);
 			break;
 
 		case SMALL_TAG_VENDOR:
@@ -229,7 +183,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
 				goto len_err;
 			io = p[1] + p[2] * 256;
 			size = p[3];
-			pnpbios_parse_allocated_ioresource(res, io, size);
+			pnpbios_parse_allocated_ioresource(dev, io, size);
 			break;
 
 		case SMALL_TAG_END:
@@ -239,9 +193,8 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
 
 		default:	/* an unkown tag */
 len_err:
-			printk(KERN_ERR
-			       "PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
-			       tag, len);
+			dev_err(&dev->dev, "unknown tag %#x length %d\n",
+				tag, len);
 			break;
 		}
 
@@ -252,8 +205,7 @@ len_err:
 			p += len + 1;
 	}
 
-	printk(KERN_ERR
-	       "PnPBIOS: Resource structure does not contain an end tag.\n");
+	dev_err(&dev->dev, "no end tag in resource structure\n");
 
 	return NULL;
 }
@@ -262,7 +214,8 @@ len_err:
  * Resource Configuration Options
  */
 
-static __init void pnpbios_parse_mem_option(unsigned char *p, int size,
+static __init void pnpbios_parse_mem_option(struct pnp_dev *dev,
+					    unsigned char *p, int size,
 					    struct pnp_option *option)
 {
 	struct pnp_mem *mem;
@@ -275,10 +228,11 @@ static __init void pnpbios_parse_mem_option(unsigned char *p, int size,
 	mem->align = (p[9] << 8) | p[8];
 	mem->size = ((p[11] << 8) | p[10]) << 8;
 	mem->flags = p[3];
-	pnp_register_mem_resource(option, mem);
+	pnp_register_mem_resource(dev, option, mem);
 }
 
-static __init void pnpbios_parse_mem32_option(unsigned char *p, int size,
+static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev,
+					      unsigned char *p, int size,
 					      struct pnp_option *option)
 {
 	struct pnp_mem *mem;
@@ -291,10 +245,11 @@ static __init void pnpbios_parse_mem32_option(unsigned char *p, int size,
 	mem->align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12];
 	mem->size = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16];
 	mem->flags = p[3];
-	pnp_register_mem_resource(option, mem);
+	pnp_register_mem_resource(dev, option, mem);
 }
 
-static __init void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size,
+static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev,
+						    unsigned char *p, int size,
 						    struct pnp_option *option)
 {
 	struct pnp_mem *mem;
@@ -306,11 +261,12 @@ static __init void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size,
 	mem->size = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
 	mem->align = 0;
 	mem->flags = p[3];
-	pnp_register_mem_resource(option, mem);
+	pnp_register_mem_resource(dev, option, mem);
 }
 
-static __init void pnpbios_parse_irq_option(unsigned char *p, int size,
-				     struct pnp_option *option)
+static __init void pnpbios_parse_irq_option(struct pnp_dev *dev,
+					    unsigned char *p, int size,
+					    struct pnp_option *option)
 {
 	struct pnp_irq *irq;
 	unsigned long bits;
@@ -324,11 +280,12 @@ static __init void pnpbios_parse_irq_option(unsigned char *p, int size,
 		irq->flags = p[3];
 	else
 		irq->flags = IORESOURCE_IRQ_HIGHEDGE;
-	pnp_register_irq_resource(option, irq);
+	pnp_register_irq_resource(dev, option, irq);
 }
 
-static __init void pnpbios_parse_dma_option(unsigned char *p, int size,
-				     struct pnp_option *option)
+static __init void pnpbios_parse_dma_option(struct pnp_dev *dev,
+					    unsigned char *p, int size,
+					    struct pnp_option *option)
 {
 	struct pnp_dma *dma;
 
@@ -337,10 +294,11 @@ static __init void pnpbios_parse_dma_option(unsigned char *p, int size,
 		return;
 	dma->map = p[1];
 	dma->flags = p[2];
-	pnp_register_dma_resource(option, dma);
+	pnp_register_dma_resource(dev, option, dma);
 }
 
-static __init void pnpbios_parse_port_option(unsigned char *p, int size,
+static __init void pnpbios_parse_port_option(struct pnp_dev *dev,
+					     unsigned char *p, int size,
 					     struct pnp_option *option)
 {
 	struct pnp_port *port;
@@ -353,10 +311,11 @@ static __init void pnpbios_parse_port_option(unsigned char *p, int size,
 	port->align = p[6];
 	port->size = p[7];
 	port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0;
-	pnp_register_port_resource(option, port);
+	pnp_register_port_resource(dev, option, port);
 }
 
-static __init void pnpbios_parse_fixed_port_option(unsigned char *p, int size,
+static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev,
+						   unsigned char *p, int size,
 						   struct pnp_option *option)
 {
 	struct pnp_port *port;
@@ -368,7 +327,7 @@ static __init void pnpbios_parse_fixed_port_option(unsigned char *p, int size,
 	port->size = p[3];
 	port->align = 0;
 	port->flags = PNP_PORT_FLAG_FIXED;
-	pnp_register_port_resource(option, port);
+	pnp_register_port_resource(dev, option, port);
 }
 
 static __init unsigned char *
@@ -382,6 +341,8 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
 	if (!p)
 		return NULL;
 
+	dev_dbg(&dev->dev, "parse resource options\n");
+
 	option_independent = option = pnp_register_independent_option(dev);
 	if (!option)
 		return NULL;
@@ -402,37 +363,37 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
 		case LARGE_TAG_MEM:
 			if (len != 9)
 				goto len_err;
-			pnpbios_parse_mem_option(p, len, option);
+			pnpbios_parse_mem_option(dev, p, len, option);
 			break;
 
 		case LARGE_TAG_MEM32:
 			if (len != 17)
 				goto len_err;
-			pnpbios_parse_mem32_option(p, len, option);
+			pnpbios_parse_mem32_option(dev, p, len, option);
 			break;
 
 		case LARGE_TAG_FIXEDMEM32:
 			if (len != 9)
 				goto len_err;
-			pnpbios_parse_fixed_mem32_option(p, len, option);
+			pnpbios_parse_fixed_mem32_option(dev, p, len, option);
 			break;
 
 		case SMALL_TAG_IRQ:
 			if (len < 2 || len > 3)
 				goto len_err;
-			pnpbios_parse_irq_option(p, len, option);
+			pnpbios_parse_irq_option(dev, p, len, option);
 			break;
 
 		case SMALL_TAG_DMA:
 			if (len != 2)
 				goto len_err;
-			pnpbios_parse_dma_option(p, len, option);
+			pnpbios_parse_dma_option(dev, p, len, option);
 			break;
 
 		case SMALL_TAG_PORT:
 			if (len != 7)
 				goto len_err;
-			pnpbios_parse_port_option(p, len, option);
+			pnpbios_parse_port_option(dev, p, len, option);
 			break;
 
 		case SMALL_TAG_VENDOR:
@@ -442,7 +403,7 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
 		case SMALL_TAG_FIXEDPORT:
 			if (len != 3)
 				goto len_err;
-			pnpbios_parse_fixed_port_option(p, len, option);
+			pnpbios_parse_fixed_port_option(dev, p, len, option);
 			break;
 
 		case SMALL_TAG_STARTDEP:
@@ -460,9 +421,10 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
 			if (len != 0)
 				goto len_err;
 			if (option_independent == option)
-				printk(KERN_WARNING
-				       "PnPBIOS: Missing SMALL_TAG_STARTDEP tag\n");
+				dev_warn(&dev->dev, "missing "
+					 "SMALL_TAG_STARTDEP tag\n");
 			option = option_independent;
+			dev_dbg(&dev->dev, "end dependent options\n");
 			break;
 
 		case SMALL_TAG_END:
@@ -470,9 +432,8 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
 
 		default:	/* an unkown tag */
 len_err:
-			printk(KERN_ERR
-			       "PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
-			       tag, len);
+			dev_err(&dev->dev, "unknown tag %#x length %d\n",
+				tag, len);
 			break;
 		}
 
@@ -483,8 +444,7 @@ len_err:
 			p += len + 1;
 	}
 
-	printk(KERN_ERR
-	       "PnPBIOS: Resource structure does not contain an end tag.\n");
+	dev_err(&dev->dev, "no end tag in resource structure\n");
 
 	return NULL;
 }
@@ -493,32 +453,12 @@ len_err:
  * Compatible Device IDs
  */
 
-#define HEX(id,a) hex[((id)>>a) & 15]
-#define CHAR(id,a) (0x40 + (((id)>>a) & 31))
-
-void pnpid32_to_pnpid(u32 id, char *str)
-{
-	const char *hex = "0123456789abcdef";
-
-	id = be32_to_cpu(id);
-	str[0] = CHAR(id, 26);
-	str[1] = CHAR(id, 21);
-	str[2] = CHAR(id, 16);
-	str[3] = HEX(id, 12);
-	str[4] = HEX(id, 8);
-	str[5] = HEX(id, 4);
-	str[6] = HEX(id, 0);
-	str[7] = '\0';
-}
-
-#undef CHAR
-#undef HEX
-
 static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
 						   unsigned char *end,
 						   struct pnp_dev *dev)
 {
 	int len, tag;
+	u32 eisa_id;
 	char id[8];
 	struct pnp_id *dev_id;
 
@@ -548,13 +488,11 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
 		case SMALL_TAG_COMPATDEVID:	/* compatible ID */
 			if (len != 4)
 				goto len_err;
-			dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
+			eisa_id = p[1] | p[2] << 8 | p[3] << 16 | p[4] << 24;
+			pnp_eisa_id_to_string(eisa_id & PNP_EISA_ID_MASK, id);
+			dev_id = pnp_add_id(dev, id);
 			if (!dev_id)
 				return NULL;
-			pnpid32_to_pnpid(p[1] | p[2] << 8 | p[3] << 16 | p[4] <<
-					 24, id);
-			memcpy(&dev_id->id, id, 7);
-			pnp_add_id(dev_id, dev);
 			break;
 
 		case SMALL_TAG_END:
@@ -564,9 +502,8 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
 
 		default:	/* an unkown tag */
 len_err:
-			printk(KERN_ERR
-			       "PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
-			       tag, len);
+			dev_err(&dev->dev, "unknown tag %#x length %d\n",
+				tag, len);
 			break;
 		}
 
@@ -577,8 +514,7 @@ len_err:
 			p += len + 1;
 	}
 
-	printk(KERN_ERR
-	       "PnPBIOS: Resource structure does not contain an end tag.\n");
+	dev_err(&dev->dev, "no end tag in resource structure\n");
 
 	return NULL;
 }
@@ -587,7 +523,8 @@ len_err:
  * Allocated Resource Encoding
  */
 
-static void pnpbios_encode_mem(unsigned char *p, struct resource *res)
+static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
+			       struct resource *res)
 {
 	unsigned long base = res->start;
 	unsigned long len = res->end - res->start + 1;
@@ -598,9 +535,13 @@ static void pnpbios_encode_mem(unsigned char *p, struct resource *res)
 	p[7] = ((base >> 8) >> 8) & 0xff;
 	p[10] = (len >> 8) & 0xff;
 	p[11] = ((len >> 8) >> 8) & 0xff;
+
+	dev_dbg(&dev->dev, "  encode mem %#llx-%#llx\n",
+		(unsigned long long) res->start, (unsigned long long) res->end);
 }
 
-static void pnpbios_encode_mem32(unsigned char *p, struct resource *res)
+static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
+				 struct resource *res)
 {
 	unsigned long base = res->start;
 	unsigned long len = res->end - res->start + 1;
@@ -617,9 +558,13 @@ static void pnpbios_encode_mem32(unsigned char *p, struct resource *res)
 	p[17] = (len >> 8) & 0xff;
 	p[18] = (len >> 16) & 0xff;
 	p[19] = (len >> 24) & 0xff;
+
+	dev_dbg(&dev->dev, "  encode mem32 %#llx-%#llx\n",
+		(unsigned long long) res->start, (unsigned long long) res->end);
 }
 
-static void pnpbios_encode_fixed_mem32(unsigned char *p, struct resource *res)
+static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
+				       struct resource *res)
 {
 	unsigned long base = res->start;
 	unsigned long len = res->end - res->start + 1;
@@ -632,26 +577,36 @@ static void pnpbios_encode_fixed_mem32(unsigned char *p, struct resource *res)
 	p[9] = (len >> 8) & 0xff;
 	p[10] = (len >> 16) & 0xff;
 	p[11] = (len >> 24) & 0xff;
+
+	dev_dbg(&dev->dev, "  encode fixed_mem32 %#llx-%#llx\n",
+		(unsigned long long) res->start, (unsigned long long) res->end);
 }
 
-static void pnpbios_encode_irq(unsigned char *p, struct resource *res)
+static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p,
+			       struct resource *res)
 {
 	unsigned long map = 0;
 
 	map = 1 << res->start;
 	p[1] = map & 0xff;
 	p[2] = (map >> 8) & 0xff;
+
+	dev_dbg(&dev->dev, "  encode irq %d\n", res->start);
 }
 
-static void pnpbios_encode_dma(unsigned char *p, struct resource *res)
+static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p,
+			       struct resource *res)
 {
 	unsigned long map = 0;
 
 	map = 1 << res->start;
 	p[1] = map & 0xff;
+
+	dev_dbg(&dev->dev, "  encode dma %d\n", res->start);
 }
 
-static void pnpbios_encode_port(unsigned char *p, struct resource *res)
+static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
+				struct resource *res)
 {
 	unsigned long base = res->start;
 	unsigned long len = res->end - res->start + 1;
@@ -661,9 +616,13 @@ static void pnpbios_encode_port(unsigned char *p, struct resource *res)
 	p[4] = base & 0xff;
 	p[5] = (base >> 8) & 0xff;
 	p[7] = len & 0xff;
+
+	dev_dbg(&dev->dev, "  encode io %#llx-%#llx\n",
+		(unsigned long long) res->start, (unsigned long long) res->end);
 }
 
-static void pnpbios_encode_fixed_port(unsigned char *p, struct resource *res)
+static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
+				      struct resource *res)
 {
 	unsigned long base = res->start;
 	unsigned long len = res->end - res->start + 1;
@@ -671,13 +630,15 @@ static void pnpbios_encode_fixed_port(unsigned char *p, struct resource *res)
 	p[1] = base & 0xff;
 	p[2] = (base >> 8) & 0xff;
 	p[3] = len & 0xff;
+
+	dev_dbg(&dev->dev, "  encode fixed_io %#llx-%#llx\n",
+		(unsigned long long) res->start, (unsigned long long) res->end);
 }
 
-static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p,
-							     unsigned char *end,
-							     struct
-							     pnp_resource_table
-							     *res)
+static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev
+								*dev,
+							     unsigned char *p,
+							     unsigned char *end)
 {
 	unsigned int len, tag;
 	int port = 0, irq = 0, dma = 0, mem = 0;
@@ -701,42 +662,48 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p,
 		case LARGE_TAG_MEM:
 			if (len != 9)
 				goto len_err;
-			pnpbios_encode_mem(p, &res->mem_resource[mem]);
+			pnpbios_encode_mem(dev, p,
+				pnp_get_resource(dev, IORESOURCE_MEM, mem));
 			mem++;
 			break;
 
 		case LARGE_TAG_MEM32:
 			if (len != 17)
 				goto len_err;
-			pnpbios_encode_mem32(p, &res->mem_resource[mem]);
+			pnpbios_encode_mem32(dev, p,
+				pnp_get_resource(dev, IORESOURCE_MEM, mem));
 			mem++;
 			break;
 
 		case LARGE_TAG_FIXEDMEM32:
 			if (len != 9)
 				goto len_err;
-			pnpbios_encode_fixed_mem32(p, &res->mem_resource[mem]);
+			pnpbios_encode_fixed_mem32(dev, p,
+				pnp_get_resource(dev, IORESOURCE_MEM, mem));
 			mem++;
 			break;
 
 		case SMALL_TAG_IRQ:
 			if (len < 2 || len > 3)
 				goto len_err;
-			pnpbios_encode_irq(p, &res->irq_resource[irq]);
+			pnpbios_encode_irq(dev, p,
+				pnp_get_resource(dev, IORESOURCE_IRQ, irq));
 			irq++;
 			break;
 
 		case SMALL_TAG_DMA:
 			if (len != 2)
 				goto len_err;
-			pnpbios_encode_dma(p, &res->dma_resource[dma]);
+			pnpbios_encode_dma(dev, p,
+				pnp_get_resource(dev, IORESOURCE_DMA, dma));
 			dma++;
 			break;
 
 		case SMALL_TAG_PORT:
 			if (len != 7)
 				goto len_err;
-			pnpbios_encode_port(p, &res->port_resource[port]);
+			pnpbios_encode_port(dev, p,
+				pnp_get_resource(dev, IORESOURCE_IO, port));
 			port++;
 			break;
 
@@ -747,7 +714,8 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p,
 		case SMALL_TAG_FIXEDPORT:
 			if (len != 3)
 				goto len_err;
-			pnpbios_encode_fixed_port(p, &res->port_resource[port]);
+			pnpbios_encode_fixed_port(dev, p,
+				pnp_get_resource(dev, IORESOURCE_IO, port));
 			port++;
 			break;
 
@@ -758,9 +726,8 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p,
 
 		default:	/* an unkown tag */
 len_err:
-			printk(KERN_ERR
-			       "PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
-			       tag, len);
+			dev_err(&dev->dev, "unknown tag %#x length %d\n",
+				tag, len);
 			break;
 		}
 
@@ -771,8 +738,7 @@ len_err:
 			p += len + 1;
 	}
 
-	printk(KERN_ERR
-	       "PnPBIOS: Resource structure does not contain an end tag.\n");
+	dev_err(&dev->dev, "no end tag in resource structure\n");
 
 	return NULL;
 }
@@ -787,7 +753,7 @@ int __init pnpbios_parse_data_stream(struct pnp_dev *dev,
 	unsigned char *p = (char *)node->data;
 	unsigned char *end = (char *)(node->data + node->size);
 
-	p = pnpbios_parse_allocated_resource_data(p, end, &dev->res);
+	p = pnpbios_parse_allocated_resource_data(dev, p, end);
 	if (!p)
 		return -EIO;
 	p = pnpbios_parse_resource_option_data(p, end, dev);
@@ -799,25 +765,25 @@ int __init pnpbios_parse_data_stream(struct pnp_dev *dev,
 	return 0;
 }
 
-int pnpbios_read_resources_from_node(struct pnp_resource_table *res,
+int pnpbios_read_resources_from_node(struct pnp_dev *dev,
 				     struct pnp_bios_node *node)
 {
 	unsigned char *p = (char *)node->data;
 	unsigned char *end = (char *)(node->data + node->size);
 
-	p = pnpbios_parse_allocated_resource_data(p, end, res);
+	p = pnpbios_parse_allocated_resource_data(dev, p, end);
 	if (!p)
 		return -EIO;
 	return 0;
 }
 
-int pnpbios_write_resources_to_node(struct pnp_resource_table *res,
+int pnpbios_write_resources_to_node(struct pnp_dev *dev,
 				    struct pnp_bios_node *node)
 {
 	unsigned char *p = (char *)node->data;
 	unsigned char *end = (char *)(node->data + node->size);
 
-	p = pnpbios_encode_allocated_resource_data(p, end, res);
+	p = pnpbios_encode_allocated_resource_data(dev, p, end);
 	if (!p)
 		return -EIO;
 	return 0;
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index e4daf4635c48..d049a2279fea 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -117,6 +117,7 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev)
 static void quirk_system_pci_resources(struct pnp_dev *dev)
 {
 	struct pci_dev *pdev = NULL;
+	struct resource *res;
 	resource_size_t pnp_start, pnp_end, pci_start, pci_end;
 	int i, j;
 
@@ -137,13 +138,15 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
 
 			pci_start = pci_resource_start(pdev, i);
 			pci_end = pci_resource_end(pdev, i);
-			for (j = 0; j < PNP_MAX_MEM; j++) {
-				if (!pnp_mem_valid(dev, j) ||
-				    pnp_mem_len(dev, j) == 0)
+			for (j = 0;
+			     (res = pnp_get_resource(dev, IORESOURCE_MEM, j));
+			     j++) {
+				if (res->flags & IORESOURCE_UNSET ||
+				    (res->start == 0 && res->end == 0))
 					continue;
 
-				pnp_start = pnp_mem_start(dev, j);
-				pnp_end = pnp_mem_end(dev, j);
+				pnp_start = res->start;
+				pnp_end = res->end;
 
 				/*
 				 * If the PNP region doesn't overlap the PCI
@@ -176,7 +179,7 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
 					pci_name(pdev), i,
 					(unsigned long long) pci_start,
 					(unsigned long long) pci_end);
-				pnp_mem_flags(dev, j) = 0;
+				res->flags = 0;
 			}
 		}
 	}
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index e50ebcffb962..2041620d5682 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -53,6 +53,8 @@ struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev)
 	if (dev->independent)
 		dev_err(&dev->dev, "independent resource already registered\n");
 	dev->independent = option;
+
+	dev_dbg(&dev->dev, "new independent option\n");
 	return option;
 }
 
@@ -70,12 +72,18 @@ struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
 		parent->next = option;
 	} else
 		dev->dependent = option;
+
+	dev_dbg(&dev->dev, "new dependent option (priority %#x)\n", priority);
 	return option;
 }
 
-int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data)
+int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
+			      struct pnp_irq *data)
 {
 	struct pnp_irq *ptr;
+#ifdef DEBUG
+	char buf[PNP_IRQ_NR];   /* hex-encoded, so this is overkill but safe */
+#endif
 
 	ptr = option->irq;
 	while (ptr && ptr->next)
@@ -94,10 +102,17 @@ int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data)
 				pcibios_penalize_isa_irq(i, 0);
 	}
 #endif
+
+#ifdef DEBUG
+	bitmap_scnprintf(buf, sizeof(buf), data->map, PNP_IRQ_NR);
+	dev_dbg(&dev->dev, "  irq bitmask %s flags %#x\n", buf,
+		data->flags);
+#endif
 	return 0;
 }
 
-int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data)
+int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option,
+			      struct pnp_dma *data)
 {
 	struct pnp_dma *ptr;
 
@@ -109,10 +124,13 @@ int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data)
 	else
 		option->dma = data;
 
+	dev_dbg(&dev->dev, "  dma bitmask %#x flags %#x\n", data->map,
+		data->flags);
 	return 0;
 }
 
-int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data)
+int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option,
+			       struct pnp_port *data)
 {
 	struct pnp_port *ptr;
 
@@ -124,10 +142,14 @@ int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data)
 	else
 		option->port = data;
 
+	dev_dbg(&dev->dev, "  io  "
+		"min %#x max %#x align %d size %d flags %#x\n",
+		data->min, data->max, data->align, data->size, data->flags);
 	return 0;
 }
 
-int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data)
+int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option,
+			      struct pnp_mem *data)
 {
 	struct pnp_mem *ptr;
 
@@ -138,6 +160,10 @@ int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data)
 		ptr->next = data;
 	else
 		option->mem = data;
+
+	dev_dbg(&dev->dev, "  mem "
+		"min %#x max %#x align %d size %d flags %#x\n",
+		data->min, data->max, data->align, data->size, data->flags);
 	return 0;
 }
 
@@ -213,17 +239,18 @@ void pnp_free_option(struct pnp_option *option)
 #define cannot_compare(flags) \
 ((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED))
 
-int pnp_check_port(struct pnp_dev *dev, int idx)
+int pnp_check_port(struct pnp_dev *dev, struct resource *res)
 {
-	int tmp;
+	int i;
 	struct pnp_dev *tdev;
+	struct resource *tres;
 	resource_size_t *port, *end, *tport, *tend;
 
-	port = &dev->res.port_resource[idx].start;
-	end = &dev->res.port_resource[idx].end;
+	port = &res->start;
+	end = &res->end;
 
 	/* if the resource doesn't exist, don't complain about it */
-	if (cannot_compare(dev->res.port_resource[idx].flags))
+	if (cannot_compare(res->flags))
 		return 1;
 
 	/* check if the resource is already in use, skip if the
@@ -234,18 +261,18 @@ int pnp_check_port(struct pnp_dev *dev, int idx)
 	}
 
 	/* 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;
+	for (i = 0; i < 8; i++) {
+		int rport = pnp_reserve_io[i << 1];
+		int rend = pnp_reserve_io[(i << 1) + 1] + rport - 1;
 		if (ranged_conflict(port, end, &rport, &rend))
 			return 0;
 	}
 
 	/* 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;
+	for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
+		if (tres != res && tres->flags & IORESOURCE_IO) {
+			tport = &tres->start;
+			tend = &tres->end;
 			if (ranged_conflict(port, end, tport, tend))
 				return 0;
 		}
@@ -255,13 +282,14 @@ int pnp_check_port(struct pnp_dev *dev, int idx)
 	pnp_for_each_dev(tdev) {
 		if (tdev == dev)
 			continue;
-		for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {
-			if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) {
-				if (cannot_compare
-				    (tdev->res.port_resource[tmp].flags))
+		for (i = 0;
+		     (tres = pnp_get_resource(tdev, IORESOURCE_IO, i));
+		     i++) {
+			if (tres->flags & IORESOURCE_IO) {
+				if (cannot_compare(tres->flags))
 					continue;
-				tport = &tdev->res.port_resource[tmp].start;
-				tend = &tdev->res.port_resource[tmp].end;
+				tport = &tres->start;
+				tend = &tres->end;
 				if (ranged_conflict(port, end, tport, tend))
 					return 0;
 			}
@@ -271,17 +299,18 @@ int pnp_check_port(struct pnp_dev *dev, int idx)
 	return 1;
 }
 
-int pnp_check_mem(struct pnp_dev *dev, int idx)
+int pnp_check_mem(struct pnp_dev *dev, struct resource *res)
 {
-	int tmp;
+	int i;
 	struct pnp_dev *tdev;
+	struct resource *tres;
 	resource_size_t *addr, *end, *taddr, *tend;
 
-	addr = &dev->res.mem_resource[idx].start;
-	end = &dev->res.mem_resource[idx].end;
+	addr = &res->start;
+	end = &res->end;
 
 	/* if the resource doesn't exist, don't complain about it */
-	if (cannot_compare(dev->res.mem_resource[idx].flags))
+	if (cannot_compare(res->flags))
 		return 1;
 
 	/* check if the resource is already in use, skip if the
@@ -292,18 +321,18 @@ int pnp_check_mem(struct pnp_dev *dev, int idx)
 	}
 
 	/* 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;
+	for (i = 0; i < 8; i++) {
+		int raddr = pnp_reserve_mem[i << 1];
+		int rend = pnp_reserve_mem[(i << 1) + 1] + raddr - 1;
 		if (ranged_conflict(addr, end, &raddr, &rend))
 			return 0;
 	}
 
 	/* 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;
+	for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
+		if (tres != res && tres->flags & IORESOURCE_MEM) {
+			taddr = &tres->start;
+			tend = &tres->end;
 			if (ranged_conflict(addr, end, taddr, tend))
 				return 0;
 		}
@@ -313,13 +342,14 @@ int pnp_check_mem(struct pnp_dev *dev, int idx)
 	pnp_for_each_dev(tdev) {
 		if (tdev == dev)
 			continue;
-		for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) {
-			if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) {
-				if (cannot_compare
-				    (tdev->res.mem_resource[tmp].flags))
+		for (i = 0;
+		     (tres = pnp_get_resource(tdev, IORESOURCE_MEM, i));
+		     i++) {
+			if (tres->flags & IORESOURCE_MEM) {
+				if (cannot_compare(tres->flags))
 					continue;
-				taddr = &tdev->res.mem_resource[tmp].start;
-				tend = &tdev->res.mem_resource[tmp].end;
+				taddr = &tres->start;
+				tend = &tres->end;
 				if (ranged_conflict(addr, end, taddr, tend))
 					return 0;
 			}
@@ -334,14 +364,17 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-int pnp_check_irq(struct pnp_dev *dev, int idx)
+int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
 {
-	int tmp;
+	int i;
 	struct pnp_dev *tdev;
-	resource_size_t *irq = &dev->res.irq_resource[idx].start;
+	struct resource *tres;
+	resource_size_t *irq;
+
+	irq = &res->start;
 
 	/* if the resource doesn't exist, don't complain about it */
-	if (cannot_compare(dev->res.irq_resource[idx].flags))
+	if (cannot_compare(res->flags))
 		return 1;
 
 	/* check if the resource is valid */
@@ -349,15 +382,15 @@ int pnp_check_irq(struct pnp_dev *dev, int idx)
 		return 0;
 
 	/* check if the resource is reserved */
-	for (tmp = 0; tmp < 16; tmp++) {
-		if (pnp_reserve_irq[tmp] == *irq)
+	for (i = 0; i < 16; i++) {
+		if (pnp_reserve_irq[i] == *irq)
 			return 0;
 	}
 
 	/* 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)
+	for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) {
+		if (tres != res && tres->flags & IORESOURCE_IRQ) {
+			if (tres->start == *irq)
 				return 0;
 		}
 	}
@@ -388,12 +421,13 @@ int pnp_check_irq(struct pnp_dev *dev, int idx)
 	pnp_for_each_dev(tdev) {
 		if (tdev == dev)
 			continue;
-		for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) {
-			if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) {
-				if (cannot_compare
-				    (tdev->res.irq_resource[tmp].flags))
+		for (i = 0;
+		     (tres = pnp_get_resource(tdev, IORESOURCE_IRQ, i));
+		     i++) {
+			if (tres->flags & IORESOURCE_IRQ) {
+				if (cannot_compare(tres->flags))
 					continue;
-				if ((tdev->res.irq_resource[tmp].start == *irq))
+				if (tres->start == *irq)
 					return 0;
 			}
 		}
@@ -402,15 +436,18 @@ int pnp_check_irq(struct pnp_dev *dev, int idx)
 	return 1;
 }
 
-int pnp_check_dma(struct pnp_dev *dev, int idx)
+int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
 {
 #ifndef CONFIG_IA64
-	int tmp;
+	int i;
 	struct pnp_dev *tdev;
-	resource_size_t *dma = &dev->res.dma_resource[idx].start;
+	struct resource *tres;
+	resource_size_t *dma;
+
+	dma = &res->start;
 
 	/* if the resource doesn't exist, don't complain about it */
-	if (cannot_compare(dev->res.dma_resource[idx].flags))
+	if (cannot_compare(res->flags))
 		return 1;
 
 	/* check if the resource is valid */
@@ -418,15 +455,15 @@ int pnp_check_dma(struct pnp_dev *dev, int idx)
 		return 0;
 
 	/* check if the resource is reserved */
-	for (tmp = 0; tmp < 8; tmp++) {
-		if (pnp_reserve_dma[tmp] == *dma)
+	for (i = 0; i < 8; i++) {
+		if (pnp_reserve_dma[i] == *dma)
 			return 0;
 	}
 
 	/* 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)
+	for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) {
+		if (tres != res && tres->flags & IORESOURCE_DMA) {
+			if (tres->start == *dma)
 				return 0;
 		}
 	}
@@ -443,12 +480,13 @@ int pnp_check_dma(struct pnp_dev *dev, int idx)
 	pnp_for_each_dev(tdev) {
 		if (tdev == dev)
 			continue;
-		for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) {
-			if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) {
-				if (cannot_compare
-				    (tdev->res.dma_resource[tmp].flags))
+		for (i = 0;
+		     (tres = pnp_get_resource(tdev, IORESOURCE_DMA, i));
+		     i++) {
+			if (tres->flags & IORESOURCE_DMA) {
+				if (cannot_compare(tres->flags))
 					continue;
-				if ((tdev->res.dma_resource[tmp].start == *dma))
+				if (tres->start == *dma)
 					return 0;
 			}
 		}
@@ -461,6 +499,193 @@ int pnp_check_dma(struct pnp_dev *dev, int idx)
 #endif
 }
 
+struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
+					  unsigned int type, unsigned int num)
+{
+	struct pnp_resource_table *res = dev->res;
+
+	switch (type) {
+	case IORESOURCE_IO:
+		if (num >= PNP_MAX_PORT)
+			return NULL;
+		return &res->port[num];
+	case IORESOURCE_MEM:
+		if (num >= PNP_MAX_MEM)
+			return NULL;
+		return &res->mem[num];
+	case IORESOURCE_IRQ:
+		if (num >= PNP_MAX_IRQ)
+			return NULL;
+		return &res->irq[num];
+	case IORESOURCE_DMA:
+		if (num >= PNP_MAX_DMA)
+			return NULL;
+		return &res->dma[num];
+	}
+	return NULL;
+}
+
+struct resource *pnp_get_resource(struct pnp_dev *dev,
+				  unsigned int type, unsigned int num)
+{
+	struct pnp_resource *pnp_res;
+
+	pnp_res = pnp_get_pnp_resource(dev, type, num);
+	if (pnp_res)
+		return &pnp_res->res;
+
+	return NULL;
+}
+EXPORT_SYMBOL(pnp_get_resource);
+
+static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev, int type)
+{
+	struct pnp_resource *pnp_res;
+	int i;
+
+	switch (type) {
+	case IORESOURCE_IO:
+		for (i = 0; i < PNP_MAX_PORT; i++) {
+			pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, i);
+			if (pnp_res && !pnp_resource_valid(&pnp_res->res))
+				return pnp_res;
+		}
+		break;
+	case IORESOURCE_MEM:
+		for (i = 0; i < PNP_MAX_MEM; i++) {
+			pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, i);
+			if (pnp_res && !pnp_resource_valid(&pnp_res->res))
+				return pnp_res;
+		}
+		break;
+	case IORESOURCE_IRQ:
+		for (i = 0; i < PNP_MAX_IRQ; i++) {
+			pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, i);
+			if (pnp_res && !pnp_resource_valid(&pnp_res->res))
+				return pnp_res;
+		}
+		break;
+	case IORESOURCE_DMA:
+		for (i = 0; i < PNP_MAX_DMA; i++) {
+			pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, i);
+			if (pnp_res && !pnp_resource_valid(&pnp_res->res))
+				return pnp_res;
+		}
+		break;
+	}
+	return NULL;
+}
+
+struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
+					  int flags)
+{
+	struct pnp_resource *pnp_res;
+	struct resource *res;
+	static unsigned char warned;
+
+	pnp_res = pnp_new_resource(dev, IORESOURCE_IRQ);
+	if (!pnp_res) {
+		if (!warned) {
+			dev_err(&dev->dev, "can't add resource for IRQ %d\n",
+				irq);
+			warned = 1;
+		}
+		return NULL;
+	}
+
+	res = &pnp_res->res;
+	res->flags = IORESOURCE_IRQ | flags;
+	res->start = irq;
+	res->end = irq;
+
+	dev_dbg(&dev->dev, "  add irq %d flags %#x\n", irq, flags);
+	return pnp_res;
+}
+
+struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
+					  int flags)
+{
+	struct pnp_resource *pnp_res;
+	struct resource *res;
+	static unsigned char warned;
+
+	pnp_res = pnp_new_resource(dev, IORESOURCE_DMA);
+	if (!pnp_res) {
+		if (!warned) {
+			dev_err(&dev->dev, "can't add resource for DMA %d\n",
+				dma);
+			warned = 1;
+		}
+		return NULL;
+	}
+
+	res = &pnp_res->res;
+	res->flags = IORESOURCE_DMA | flags;
+	res->start = dma;
+	res->end = dma;
+
+	dev_dbg(&dev->dev, "  add dma %d flags %#x\n", dma, flags);
+	return pnp_res;
+}
+
+struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
+					 resource_size_t start,
+					 resource_size_t end, int flags)
+{
+	struct pnp_resource *pnp_res;
+	struct resource *res;
+	static unsigned char warned;
+
+	pnp_res = pnp_new_resource(dev, IORESOURCE_IO);
+	if (!pnp_res) {
+		if (!warned) {
+			dev_err(&dev->dev, "can't add resource for IO "
+				"%#llx-%#llx\n",(unsigned long long) start,
+				(unsigned long long) end);
+			warned = 1;
+		}
+		return NULL;
+	}
+
+	res = &pnp_res->res;
+	res->flags = IORESOURCE_IO | flags;
+	res->start = start;
+	res->end = end;
+
+	dev_dbg(&dev->dev, "  add io  %#llx-%#llx flags %#x\n",
+		(unsigned long long) start, (unsigned long long) end, flags);
+	return pnp_res;
+}
+
+struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
+					  resource_size_t start,
+					  resource_size_t end, int flags)
+{
+	struct pnp_resource *pnp_res;
+	struct resource *res;
+	static unsigned char warned;
+
+	pnp_res = pnp_new_resource(dev, IORESOURCE_MEM);
+	if (!pnp_res) {
+		if (!warned) {
+			dev_err(&dev->dev, "can't add resource for MEM "
+				"%#llx-%#llx\n",(unsigned long long) start,
+				(unsigned long long) end);
+			warned = 1;
+		}
+		return NULL;
+	}
+
+	res = &pnp_res->res;
+	res->flags = IORESOURCE_MEM | flags;
+	res->start = start;
+	res->end = end;
+
+	dev_dbg(&dev->dev, "  add mem %#llx-%#llx flags %#x\n",
+		(unsigned long long) start, (unsigned long long) end, flags);
+	return pnp_res;
+}
+
 /* format is: pnp_reserve_irq=irq1[,irq2] .... */
 static int __init pnp_setup_reserve_irq(char *str)
 {
diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c
index 13c608f5fb30..3eba85ed729c 100644
--- a/drivers/pnp/support.c
+++ b/drivers/pnp/support.c
@@ -25,3 +25,66 @@ int pnp_is_active(struct pnp_dev *dev)
 }
 
 EXPORT_SYMBOL(pnp_is_active);
+
+/*
+ * Functionally similar to acpi_ex_eisa_id_to_string(), but that's
+ * buried in the ACPI CA, and we can't depend on it being present.
+ */
+void pnp_eisa_id_to_string(u32 id, char *str)
+{
+	id = be32_to_cpu(id);
+
+	/*
+	 * According to the specs, the first three characters are five-bit
+	 * compressed ASCII, and the left-over high order bit should be zero.
+	 * However, the Linux ISAPNP code historically used six bits for the
+	 * first character, and there seem to be IDs that depend on that,
+	 * e.g., "nEC8241" in the Linux 8250_pnp serial driver and the
+	 * FreeBSD sys/pc98/cbus/sio_cbus.c driver.
+	 */
+	str[0] = 'A' + ((id >> 26) & 0x3f) - 1;
+	str[1] = 'A' + ((id >> 21) & 0x1f) - 1;
+	str[2] = 'A' + ((id >> 16) & 0x1f) - 1;
+	str[3] = hex_asc((id >> 12) & 0xf);
+	str[4] = hex_asc((id >>  8) & 0xf);
+	str[5] = hex_asc((id >>  4) & 0xf);
+	str[6] = hex_asc((id >>  0) & 0xf);
+	str[7] = '\0';
+}
+
+void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
+{
+#ifdef DEBUG
+	struct resource *res;
+	int i;
+
+	dev_dbg(&dev->dev, "current resources: %s\n", desc);
+
+	for (i = 0; i < PNP_MAX_IRQ; i++) {
+		res = pnp_get_resource(dev, IORESOURCE_IRQ, i);
+		if (res && !(res->flags & IORESOURCE_UNSET))
+			dev_dbg(&dev->dev, "  irq %lld flags %#lx\n",
+				(unsigned long long) res->start, res->flags);
+	}
+	for (i = 0; i < PNP_MAX_DMA; i++) {
+		res = pnp_get_resource(dev, IORESOURCE_DMA, i);
+		if (res && !(res->flags & IORESOURCE_UNSET))
+			dev_dbg(&dev->dev, "  dma %lld flags %#lx\n",
+				(unsigned long long) res->start, res->flags);
+	}
+	for (i = 0; i < PNP_MAX_PORT; i++) {
+		res = pnp_get_resource(dev, IORESOURCE_IO, i);
+		if (res && !(res->flags & IORESOURCE_UNSET))
+			dev_dbg(&dev->dev, "  io  %#llx-%#llx flags %#lx\n",
+				(unsigned long long) res->start,
+				(unsigned long long) res->end, res->flags);
+	}
+	for (i = 0; i < PNP_MAX_MEM; i++) {
+		res = pnp_get_resource(dev, IORESOURCE_MEM, i);
+		if (res && !(res->flags & IORESOURCE_UNSET))
+			dev_dbg(&dev->dev, "  mem %#llx-%#llx flags %#lx\n",
+				(unsigned long long) res->start,
+				(unsigned long long) res->end, res->flags);
+	}
+#endif
+}
diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c
index 55c4563986b3..9c2496dbeee4 100644
--- a/drivers/pnp/system.c
+++ b/drivers/pnp/system.c
@@ -56,14 +56,15 @@ static void reserve_range(struct pnp_dev *dev, resource_size_t start,
 
 static void reserve_resources_of_dev(struct pnp_dev *dev)
 {
+	struct resource *res;
 	int i;
 
-	for (i = 0; i < PNP_MAX_PORT; i++) {
-		if (!pnp_port_valid(dev, i))
+	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
+		if (res->flags & IORESOURCE_UNSET)
 			continue;
-		if (pnp_port_start(dev, i) == 0)
+		if (res->start == 0)
 			continue;	/* disabled */
-		if (pnp_port_start(dev, i) < 0x100)
+		if (res->start < 0x100)
 			/*
 			 * Below 0x100 is only standard PC hardware
 			 * (pics, kbd, timer, dma, ...)
@@ -73,19 +74,17 @@ static void reserve_resources_of_dev(struct pnp_dev *dev)
 			 * So, do nothing
 			 */
 			continue;
-		if (pnp_port_end(dev, i) < pnp_port_start(dev, i))
+		if (res->end < res->start)
 			continue;	/* invalid */
 
-		reserve_range(dev, pnp_port_start(dev, i),
-			      pnp_port_end(dev, i), 1);
+		reserve_range(dev, res->start, res->end, 1);
 	}
 
-	for (i = 0; i < PNP_MAX_MEM; i++) {
-		if (!pnp_mem_valid(dev, i))
+	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
+		if (res->flags & IORESOURCE_UNSET)
 			continue;
 
-		reserve_range(dev, pnp_mem_start(dev, i),
-			      pnp_mem_end(dev, i), 0);
+		reserve_range(dev, res->start, res->end, 0);
 	}
 }