summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2002-12-29 23:37:08 -0800
committerLinus Torvalds <torvalds@home.transmeta.com>2002-12-29 23:37:08 -0800
commit3c363821bedf97dbeba6cf39593eddd6d39fb551 (patch)
tree0339622444c3108c220930f8380f54faa6296f30 /drivers
parent8e5cae4ebd85434babf5e4ffaf07893aac68fa1c (diff)
parent4513bc2fb92aa9407cea9c9b56053f38c211b6aa (diff)
Merge bk://kernel.bkbits.net/gregkh/linux/pnp-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pcmcia/i82365.c26
-rw-r--r--drivers/pnp/card.c14
-rw-r--r--drivers/pnp/core.c3
-rw-r--r--drivers/pnp/driver.c16
-rw-r--r--drivers/pnp/idlist.h3
-rw-r--r--drivers/pnp/interface.c20
-rw-r--r--drivers/pnp/isapnp/Makefile4
-rw-r--r--drivers/pnp/isapnp/compat.c25
-rw-r--r--drivers/pnp/isapnp/core.c58
-rw-r--r--drivers/pnp/isapnp/proc.c1
-rw-r--r--drivers/pnp/pnpbios/core.c27
-rw-r--r--drivers/pnp/resource.c107
-rw-r--r--drivers/serial/8250_pnp.c7
13 files changed, 194 insertions, 117 deletions
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 8c2cd91ad6c3..893561738443 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -814,7 +814,7 @@ static void __init add_pcic(int ns, int type)
#ifdef CONFIG_ISA
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP
static struct isapnp_device_id id_table[] __initdata = {
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'),
ISAPNP_FUNCTION(0x0e00), (unsigned long) "Intel 82365-Compatible" },
@@ -826,32 +826,28 @@ static struct isapnp_device_id id_table[] __initdata = {
};
MODULE_DEVICE_TABLE(isapnp, id_table);
-static struct pci_dev *i82365_pnpdev;
+static struct pnp_dev *i82365_pnpdev;
#endif
static void __init isa_probe(void)
{
int i, j, sock, k, ns, id;
ioaddr_t port;
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP
struct isapnp_device_id *devid;
- struct pci_dev *dev;
+ struct pnp_dev *dev;
for (devid = id_table; devid->vendor; devid++) {
- if ((dev = isapnp_find_dev(NULL, devid->vendor, devid->function, NULL))) {
- printk("ISAPNP ");
+ if ((dev = pnp_find_dev(NULL, devid->vendor, devid->function, NULL))) {
+ printk("PNP ");
- if (dev->prepare && dev->prepare(dev) < 0) {
- printk("prepare failed\n");
- break;
- }
-
- if (dev->activate && dev->activate(dev) < 0) {
+ if (pnp_activate_dev(dev, NULL) < 0) {
printk("activate failed\n");
break;
}
- if ((i365_base = pci_resource_start(dev, 0))) {
+ i365_base = pnp_port_start(dev, 0);
+ if (i365_base) {
printk("no resources ?\n");
break;
}
@@ -1644,8 +1640,8 @@ static void __exit exit_i82365(void)
release_region(socket[i].ioaddr, 2);
}
#if defined(CONFIG_ISA) && defined(__ISAPNP__)
- if (i82365_pnpdev && i82365_pnpdev->deactivate)
- i82365_pnpdev->deactivate(i82365_pnpdev);
+ if (i82365_pnpdev)
+ pnp_disable_dev(i82365_pnpdev);
#endif
} /* exit_i82365 */
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index e591e906049d..914c1e2628ee 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -192,6 +192,7 @@ struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id,
{
struct list_head *pos;
struct pnp_dev *dev;
+ struct pnpc_driver *cdrv;
if (!card || !id)
goto done;
if (!from) {
@@ -212,9 +213,16 @@ done:
return NULL;
found:
- if (dev->active == 0)
- if(pnp_activate_dev(dev)<0)
- return NULL;
+ cdrv = to_pnpc_driver(card->dev.driver);
+ if (dev->active == 0) {
+ if (!(cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE)) {
+ if(pnp_activate_dev(dev,NULL)<0)
+ return NULL;
+ }
+ } else {
+ if ((cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE))
+ pnp_disable_dev(dev);
+ }
spin_lock(&pnp_lock);
list_add_tail(&dev->rdev_list, &card->rdevs);
spin_unlock(&pnp_lock);
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index 7eed8f4f8163..979cccd2a128 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -115,7 +115,8 @@ int __pnp_add_device(struct pnp_dev *dev)
int error = 0;
pnp_name_device(dev);
pnp_fixup_device(dev);
- strcpy(dev->dev.name,dev->name);
+ strncpy(dev->dev.name,dev->name,DEVICE_NAME_SIZE-1);
+ dev->dev.name[DEVICE_NAME_SIZE-1] = '\0';
dev->dev.bus = &pnp_bus_type;
dev->dev.release = &pnp_release_device;
error = device_register(&dev->dev);
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index 8676d7941b00..e954b11ae931 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -66,7 +66,7 @@ static const struct pnp_device_id * match_device(struct pnp_driver *drv, struct
static int pnp_device_probe(struct device *dev)
{
- int error = 0;
+ int error;
struct pnp_driver *pnp_drv;
struct pnp_dev *pnp_dev;
const struct pnp_device_id *dev_id = NULL;
@@ -75,9 +75,17 @@ static int pnp_device_probe(struct device *dev)
pnp_dbg("pnp: match found with the PnP device '%s' and the driver '%s'", dev->bus_id,pnp_drv->name);
- if (pnp_dev->active == 0)
- if(pnp_activate_dev(pnp_dev)<0)
- return -1;
+ if (pnp_dev->active == 0) {
+ if (!(pnp_drv->flags & PNP_DRIVER_DO_NOT_ACTIVATE)) {
+ error = pnp_activate_dev(pnp_dev, NULL);
+ if (error < 0)
+ return error;
+ }
+ } else {
+ if ((pnp_drv->flags & PNP_DRIVER_DO_NOT_ACTIVATE))
+ pnp_disable_dev(pnp_dev);
+ }
+ error = 0;
if (pnp_drv->probe && pnp_dev->active) {
dev_id = match_device(pnp_drv, pnp_dev);
if (dev_id != NULL)
diff --git a/drivers/pnp/idlist.h b/drivers/pnp/idlist.h
index c75698a68f5c..aa2272fbd652 100644
--- a/drivers/pnp/idlist.h
+++ b/drivers/pnp/idlist.h
@@ -5,6 +5,7 @@ ID("CSC0003", "Crystal Semiconductor CS423x sound -- MPU401")
ID("IBM3780", "IBM pointing device")
ID("IBM0071", "IBM infrared communications device")
ID("IBM3760", "IBM DSP")
+ID("NSC6001", "National Semiconductor Serial Port with Fast IR")
ID("PNP0000", "AT Interrupt Controller")
ID("PNP0001", "EISA Interrupt Controller")
ID("PNP0002", "MCA Interrupt Controller")
@@ -54,6 +55,7 @@ ID("PNP0602", "Plus Hardcard IIXL/EZ")
ID("PNP0603", "Generic IDE supporting Microsoft Device Bay Specification")
ID("PNP0700", "PC standard floppy disk controller")
ID("PNP0701", "Standard floppy controller supporting MS Device Bay Spec")
+ID("PNP0802", "Microsoft Sound System or Compatible Device (obsolete)")
ID("PNP0900", "VGA Compatible")
ID("PNP0901", "Video Seven VRAM/VRAM II/1024i")
ID("PNP0902", "8514/A Compatible")
@@ -151,7 +153,6 @@ ID("PNP0f1c", "Compaq LTE Trackball PS/2-style Mouse")
ID("PNP0f1d", "Compaq LTE Trackball Serial Mouse")
ID("PNP0f1e", "Microsoft Kids Trackball Mouse")
ID("PNP8001", "Novell/Anthem NE3200")
-ID("PNP0802", "Microsoft Sound System or Compatible Device (obsolete)")
ID("PNP8004", "Compaq NE3200")
ID("PNP8006", "Intel EtherExpress/32")
ID("PNP8008", "HP EtherTwist EISA LAN Adapter/32 (HP27248A)")
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index 8746323da744..b7ad96265091 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -295,12 +295,28 @@ pnp_set_current_resources(struct device * dmdev, const char * buf, size_t count,
num_args = sscanf(buf,"%10s %i %10s",command,&depnum,type);
if (!num_args)
goto done;
+ if (!strnicmp(command,"lock",4)) {
+ if (dev->active) {
+ dev->lock_resources = 1;
+ } else {
+ error = -EINVAL;
+ }
+ goto done;
+ }
+ if (!strnicmp(command,"unlock",6)) {
+ if (dev->lock_resources) {
+ dev->lock_resources = 0;
+ } else {
+ error = -EINVAL;
+ }
+ goto done;
+ }
if (!strnicmp(command,"disable",7)) {
error = pnp_disable_dev(dev);
goto done;
}
if (!strnicmp(command,"auto",4)) {
- error = pnp_activate_dev(dev);
+ error = pnp_activate_dev(dev,NULL);
goto done;
}
if (!strnicmp(command,"manual",6)) {
@@ -308,7 +324,7 @@ pnp_set_current_resources(struct device * dmdev, const char * buf, size_t count,
goto done;
if (!strnicmp(type,"static",6))
mode = PNP_STATIC;
- error = pnp_raw_set_dev(dev,depnum,mode);
+ error = pnp_raw_set_dev(dev,depnum,NULL,mode);
goto done;
}
done:
diff --git a/drivers/pnp/isapnp/Makefile b/drivers/pnp/isapnp/Makefile
index 62c36dd5df7e..1539195169db 100644
--- a/drivers/pnp/isapnp/Makefile
+++ b/drivers/pnp/isapnp/Makefile
@@ -2,8 +2,8 @@
# Makefile for the kernel ISAPNP driver.
#
-export-objs := core.o
+export-objs := core.o compat.o
isapnp-proc-$(CONFIG_PROC_FS) = proc.o
-obj-y := core.o $(isapnp-proc-y)
+obj-y := core.o compat.o $(isapnp-proc-y)
diff --git a/drivers/pnp/isapnp/compat.c b/drivers/pnp/isapnp/compat.c
index 862c21feba05..834a4ee8b4a9 100644
--- a/drivers/pnp/isapnp/compat.c
+++ b/drivers/pnp/isapnp/compat.c
@@ -26,21 +26,20 @@ static void pnp_convert_id(char *buf, unsigned short vendor, unsigned short devi
}
struct pnp_card *pnp_find_card(unsigned short vendor,
- unsigned short device,
- struct pnp_card *from)
+ unsigned short device,
+ struct pnp_card *from)
{
char id[7];
char any[7];
struct list_head *list;
pnp_convert_id(id, vendor, device);
pnp_convert_id(any, ISAPNP_ANY_ID, ISAPNP_ANY_ID);
- list = isapnp_cards.next;
- if (from)
- list = from->node.next;
- while (list != &isapnp_cards) {
- struct pnp_card *card = to_pnp_card(list);
- if (compare_pnp_id(&card->ids,id) || (memcmp(id,any,7)==0))
+ list = from ? from->global_list.next : pnp_cards.next;
+
+ while (list != &pnp_cards) {
+ struct pnp_card *card = global_to_pnp_card(list);
+ if (compare_pnp_id(card->id,id) || (memcmp(id,any,7)==0))
return card;
list = list->next;
}
@@ -48,9 +47,9 @@ struct pnp_card *pnp_find_card(unsigned short vendor,
}
struct pnp_dev *pnp_find_dev(struct pnp_card *card,
- unsigned short vendor,
- unsigned short function,
- struct pnp_dev *from)
+ unsigned short vendor,
+ unsigned short function,
+ struct pnp_dev *from)
{
char id[7];
char any[7];
@@ -65,7 +64,7 @@ struct pnp_dev *pnp_find_dev(struct pnp_card *card,
while (list != &pnp_global) {
struct pnp_dev *dev = global_to_pnp_dev(list);
- if (compare_pnp_id(&dev->ids,id) || (memcmp(id,any,7)==0))
+ if (compare_pnp_id(dev->id,id) || (memcmp(id,any,7)==0))
return dev;
list = list->next;
}
@@ -80,7 +79,7 @@ struct pnp_dev *pnp_find_dev(struct pnp_card *card,
}
while (list != &card->devices) {
struct pnp_dev *dev = card_to_pnp_dev(list);
- if (compare_pnp_id(&dev->ids,id))
+ if (compare_pnp_id(dev->id,id))
return dev;
list = list->next;
}
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index b60bea187852..fa683efd00a3 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -42,12 +42,8 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/isapnp.h>
-#include <linux/pnp.h>
#include <asm/io.h>
-LIST_HEAD(isapnp_cards);
-LIST_HEAD(isapnp_devices);
-
#if 0
#define ISAPNP_REGION_OK
#endif
@@ -106,6 +102,8 @@ static int isapnp_detected;
/* some prototypes */
static int isapnp_config_prepare(struct pnp_dev *dev);
+extern struct pnp_protocol isapnp_card_protocol;
+extern struct pnp_protocol isapnp_protocol;
static inline void write_data(unsigned char x)
{
@@ -521,7 +519,7 @@ static void __init isapnp_add_port_resource(struct pnp_dev *dev,
port->max = (tmp[4] << 8) | tmp[3];
port->align = tmp[5];
port->size = tmp[6];
- port->flags = tmp[0] ? ISAPNP_PORT_FLAG_16BITADDR : 0;
+ port->flags = tmp[0] ? PNP_PORT_FLAG_16BITADDR : 0;
pnp_add_port_resource(dev,depnum,port);
return;
}
@@ -543,7 +541,7 @@ static void __init isapnp_add_fixed_port_resource(struct pnp_dev *dev,
port->min = port->max = (tmp[1] << 8) | tmp[0];
port->size = tmp[2];
port->align = 0;
- port->flags = ISAPNP_PORT_FLAG_FIXED;
+ port->flags = PNP_PORT_FLAG_FIXED;
pnp_add_port_resource(dev,depnum,port);
return;
}
@@ -631,7 +629,7 @@ isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size)
*/
static int __init isapnp_create_device(struct pnp_card *card,
- unsigned short size)
+ unsigned short size)
{
int number = 0, skip = 0, depnum = 0, dependent = 0, compat = 0;
unsigned char type, tmp[17];
@@ -686,7 +684,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
case _STAG_STARTDEP:
if (size > 1)
goto __skip;
- dependent = 0x100 | ISAPNP_RES_PRIORITY_ACCEPTABLE;
+ dependent = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;
if (size > 0) {
isapnp_peek(tmp, size);
dependent = 0x100 | tmp[0];
@@ -891,7 +889,7 @@ static int __init isapnp_build_device_list(void)
if (isapnp_checksum_value != 0x00)
printk(KERN_ERR "isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value);
card->checksum = isapnp_checksum_value;
- card->protocol = &isapnp_protocol;
+ card->protocol = &isapnp_card_protocol;
pnpc_add_card(card);
}
return 0;
@@ -903,7 +901,12 @@ static int __init isapnp_build_device_list(void)
int isapnp_present(void)
{
- return !list_empty(&isapnp_devices);
+ struct pnp_card *card;
+ pnp_for_each_card(card) {
+ if (card->protocol == &isapnp_card_protocol)
+ return 1;
+ }
+ return 0;
}
int isapnp_cfg_begin(int csn, int logdev)
@@ -947,7 +950,7 @@ static int isapnp_config_prepare(struct pnp_dev *dev)
int idx;
if (dev == NULL)
return -EINVAL;
- if (dev->active || dev->ro)
+ if (dev->active || dev->lock_resources)
return -EBUSY;
for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++) {
dev->irq_resource[idx].name = NULL;
@@ -970,24 +973,11 @@ static int isapnp_config_prepare(struct pnp_dev *dev)
return 0;
}
-void isapnp_resource_change(struct resource *resource,
- unsigned long start,
- unsigned long size)
-{
- if (resource == NULL)
- return;
- resource->flags &= ~IORESOURCE_AUTO;
- resource->start = start;
- resource->end = start + size - 1;
-}
-
/*
* Inititialization.
*/
-EXPORT_SYMBOL(isapnp_cards);
-EXPORT_SYMBOL(isapnp_devices);
EXPORT_SYMBOL(isapnp_present);
EXPORT_SYMBOL(isapnp_cfg_begin);
EXPORT_SYMBOL(isapnp_cfg_end);
@@ -999,7 +989,6 @@ EXPORT_SYMBOL(isapnp_write_word);
EXPORT_SYMBOL(isapnp_write_dword);
EXPORT_SYMBOL(isapnp_wake);
EXPORT_SYMBOL(isapnp_device);
-EXPORT_SYMBOL(isapnp_resource_change);
static int isapnp_get_resources(struct pnp_dev *dev)
{
@@ -1053,8 +1042,15 @@ static int isapnp_disable_resources(struct pnp_dev *dev)
return 0;
}
+struct pnp_protocol isapnp_card_protocol = {
+ .name = "ISA Plug and Play - card",
+ .get = NULL,
+ .set = NULL,
+ .disable = NULL,
+};
+
struct pnp_protocol isapnp_protocol = {
- .name = "ISA Plug and Play",
+ .name = "ISA Plug and Play - device",
.get = isapnp_get_resources,
.set = isapnp_set_resources,
.disable = isapnp_disable_resources,
@@ -1064,6 +1060,7 @@ int __init isapnp_init(void)
{
int cards;
struct pnp_card *card;
+ struct pnp_dev *dev;
if (isapnp_disable) {
isapnp_detected = 0;
@@ -1084,6 +1081,9 @@ int __init isapnp_init(void)
return -EBUSY;
}
+ if(pnp_register_protocol(&isapnp_card_protocol)<0)
+ return -EBUSY;
+
if(pnp_register_protocol(&isapnp_protocol)<0)
return -EBUSY;
@@ -1126,13 +1126,11 @@ int __init isapnp_init(void)
protocol_for_each_card(&isapnp_protocol,card) {
cards++;
if (isapnp_verbose) {
- struct list_head *devlist;
printk(KERN_INFO "isapnp: Card '%s'\n", card->name[0]?card->name:"Unknown");
if (isapnp_verbose < 2)
continue;
- for (devlist = card->devices.next; devlist != &card->devices; devlist = devlist->next) {
- struct pci_dev *dev = pci_dev_b(devlist);
- printk(KERN_INFO "isapnp: Device '%s'\n", dev->dev.name[0]?card->name:"Unknown");
+ pnp_card_for_each_dev(card,dev) {
+ printk(KERN_INFO "isapnp: Device '%s'\n", dev->name[0]?dev->name:"Unknown");
}
}
}
diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c
index f3427d078367..2330ee03f808 100644
--- a/drivers/pnp/isapnp/proc.c
+++ b/drivers/pnp/isapnp/proc.c
@@ -28,6 +28,7 @@
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
+extern struct pnp_protocol isapnp_protocol;
static struct proc_dir_entry *isapnp_proc_bus_dir = NULL;
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 2f11e1b5f746..d11383778c18 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -1058,6 +1058,7 @@ static void inline pnpid32_to_pnpid(u32 id, char *str)
static void node_id_data_to_dev(unsigned char *p, struct pnp_bios_node *node, struct pnp_dev *dev)
{
int len;
+ char id[8];
struct pnp_id *dev_id;
if ((char *)p == NULL)
@@ -1083,7 +1084,9 @@ static void node_id_data_to_dev(unsigned char *p, struct pnp_bios_node *node, st
dev_id = pnpbios_kmalloc(sizeof (struct pnp_id), GFP_KERNEL);
if (!dev_id)
return;
- pnpid32_to_pnpid(p[1] | p[2] << 8 | p[3] << 16 | p[4] << 24,dev_id->id);
+ memset(dev_id, 0, sizeof(struct pnp_id));
+ 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;
}
@@ -1258,7 +1261,7 @@ static int pnpbios_get_resources(struct pnp_dev *dev)
struct pnp_bios_node * node;
/* just in case */
- if(dev->driver)
+ if(pnp_dev_has_driver(dev))
return -EBUSY;
if(!pnp_is_dynamic(dev))
return -EPERM;
@@ -1281,7 +1284,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev, struct pnp_cfg *config, ch
struct pnp_bios_node * node;
/* just in case */
- if(dev->driver)
+ if(pnp_dev_has_driver(dev))
return -EBUSY;
if (flags == PNP_DYNAMIC && !pnp_is_dynamic(dev))
return -EPERM;
@@ -1335,7 +1338,7 @@ static int pnpbios_disable_resources(struct pnp_dev *dev)
if (!config)
return -1;
/* just in case */
- if(dev->driver)
+ if(pnp_dev_has_driver(dev))
return -EBUSY;
if(dev->flags & PNP_NO_DISABLE || !pnp_is_dynamic(dev))
return -EPERM;
@@ -1396,7 +1399,7 @@ static int inline insert_device(struct pnp_dev *dev)
static void __init build_devlist(void)
{
u8 nodenum;
- char id[7];
+ char id[8];
unsigned char *pos;
unsigned int nodes_got = 0;
unsigned int devs = 0;
@@ -1432,14 +1435,15 @@ static void __init build_devlist(void)
break;
memset(dev,0,sizeof(struct pnp_dev));
dev_id = pnpbios_kmalloc(sizeof (struct pnp_id), GFP_KERNEL);
- if (!dev_id)
+ if (!dev_id) {
+ kfree(dev);
break;
+ }
memset(dev_id,0,sizeof(struct pnp_id));
dev->number = thisnodenum;
- memcpy(dev->name,"Unknown Device",13);
- dev->name[14] = '\0';
+ strcpy(dev->name,"Unknown Device");
pnpid32_to_pnpid(node->eisa_id,id);
- memcpy(dev_id->id,id,8);
+ memcpy(dev_id->id,id,7);
pnp_add_id(dev_id, dev);
pos = node_current_resource_data_to_dev(node,dev);
pos = node_possible_resource_data_to_dev(pos,node,dev);
@@ -1448,9 +1452,10 @@ static void __init build_devlist(void)
dev->protocol = &pnpbios_protocol;
- if(insert_device(dev)<0)
+ if(insert_device(dev)<0) {
+ kfree(dev_id);
kfree(dev);
- else
+ } else
devs++;
if (nodenum <= thisnodenum) {
printk(KERN_ERR "PnPBIOS: build_devlist: Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", (unsigned int)nodenum, (unsigned int)thisnodenum);
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index d8648efb72b3..d447461caa14 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -588,45 +588,65 @@ static int pnp_generate_dma(struct pnp_cfg *config, int num)
return -ENOENT;
}
-static int pnp_prepare_request(struct pnp_cfg *config)
+int pnp_init_res_cfg(struct pnp_res_cfg *res_config)
{
- struct pnp_dev *dev;
int idx;
- if (!config)
- return -EINVAL;
- dev = &config->request;
- if (dev == NULL)
+
+ if (!res_config)
return -EINVAL;
- if (dev->active || dev->ro)
- return -EBUSY;
for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++) {
- dev->irq_resource[idx].name = NULL;
- dev->irq_resource[idx].start = -1;
- dev->irq_resource[idx].end = -1;
- dev->irq_resource[idx].flags = 0;
+ res_config->irq_resource[idx].start = -1;
+ res_config->irq_resource[idx].end = -1;
+ res_config->irq_resource[idx].flags = 0;
}
for (idx = 0; idx < DEVICE_COUNT_DMA; idx++) {
- dev->dma_resource[idx].name = NULL;
- dev->dma_resource[idx].start = -1;
- dev->dma_resource[idx].end = -1;
- dev->dma_resource[idx].flags = 0;
+ res_config->dma_resource[idx].name = NULL;
+ res_config->dma_resource[idx].start = -1;
+ res_config->dma_resource[idx].end = -1;
+ res_config->dma_resource[idx].flags = 0;
}
for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) {
- dev->resource[idx].name = NULL;
- dev->resource[idx].start = 0;
- dev->resource[idx].end = 0;
- dev->resource[idx].flags = 0;
+ res_config->resource[idx].name = NULL;
+ res_config->resource[idx].start = 0;
+ res_config->resource[idx].end = 0;
+ res_config->resource[idx].flags = 0;
}
return 0;
}
-static int pnp_generate_request(struct pnp_cfg *config)
+static int pnp_prepare_request(struct pnp_dev *dev, struct pnp_cfg *config, struct pnp_res_cfg *template)
{
- int i;
+ int idx, err;
if (!config)
return -EINVAL;
- if (pnp_prepare_request<0)
- return -ENOENT;
+ if (dev->lock_resources)
+ return -EPERM;
+ if (dev->active)
+ return -EBUSY;
+ err = pnp_init_res_cfg(&config->request);
+ if (err < 0)
+ return err;
+ if (!template)
+ return 0;
+ for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++)
+ if (template->irq_resource[idx].start >= 0)
+ config->request.irq_resource[idx] = template->irq_resource[idx];
+ for (idx = 0; idx < DEVICE_COUNT_DMA; idx++)
+ if (template->dma_resource[idx].start >= 0)
+ config->request.dma_resource[idx] = template->dma_resource[idx];
+ for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++)
+ if (template->resource[idx].start > 0)
+ config->request.resource[idx] = template->resource[idx];
+ return 0;
+}
+
+static int pnp_generate_request(struct pnp_dev *dev, struct pnp_cfg *config, struct pnp_res_cfg *template)
+{
+ int i, err;
+ if (!config)
+ return -EINVAL;
+ if ((err = pnp_prepare_request(dev, config, template))<0)
+ return err;
for (i=0; i<=7; i++)
{
if(pnp_generate_port(config,i)<0)
@@ -745,7 +765,7 @@ static struct pnp_cfg * pnp_generate_config(struct pnp_dev *dev, int depnum)
* finds the best resource configuration and then informs the correct pnp protocol
*/
-int pnp_activate_dev(struct pnp_dev *dev)
+int pnp_activate_dev(struct pnp_dev *dev, struct pnp_res_cfg *template)
{
int depnum, max;
struct pnp_cfg *config;
@@ -754,7 +774,7 @@ int pnp_activate_dev(struct pnp_dev *dev)
max = pnp_get_max_depnum(dev);
if (dev->active)
return -EBUSY;
- if (dev->driver){
+ if (pnp_dev_has_driver(dev)){
printk(KERN_INFO "pnp: Automatic configuration failed because the PnP device '%s' is busy\n", dev->dev.bus_id);
return -EINVAL;
}
@@ -767,7 +787,7 @@ int pnp_activate_dev(struct pnp_dev *dev)
config = pnp_generate_config(dev,depnum);
if (!config)
return -EINVAL;
- if (pnp_generate_request(config)==0)
+ if (pnp_generate_request(dev,config,template)==0)
goto done;
kfree(config);
}
@@ -794,10 +814,12 @@ int pnp_disable_dev(struct pnp_dev *dev)
{
if (!dev)
return -EINVAL;
- if (dev->driver){
+ if (pnp_dev_has_driver(dev)){
printk(KERN_INFO "pnp: Disable failed becuase the PnP device '%s' is busy\n", dev->dev.bus_id);
return -EINVAL;
}
+ if (dev->lock_resources)
+ return -EPERM;
if (!dev->protocol->disable || !dev->active)
return -EINVAL;
pnp_dbg("the device '%s' has been disabled", dev->dev.bus_id);
@@ -812,21 +834,21 @@ int pnp_disable_dev(struct pnp_dev *dev)
*
*/
-int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, int mode)
+int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, struct pnp_res_cfg *template, int mode)
{
struct pnp_cfg *config;
if (!dev)
return -EINVAL;
- config = pnp_generate_config(dev,depnum);
- if (dev->driver){
- printk(KERN_INFO "pnp: Unable to set resources becuase the PnP device '%s' is busy\n", dev->dev.bus_id);
+ if (pnp_dev_has_driver(dev)){
+ printk(KERN_INFO "pnp: Unable to set resources because the PnP device '%s' is busy\n", dev->dev.bus_id);
return -EINVAL;
}
if (!dev->protocol->get || !dev->protocol->set)
return -EINVAL;
+ config = pnp_generate_config(dev,depnum);
if (!config)
return -EINVAL;
- if (pnp_generate_request(config)==0)
+ if (pnp_generate_request(dev,config,template)==0)
goto done;
kfree(config);
printk(KERN_ERR "pnp: Manual configuration failed for device '%s' due to resource conflicts\n", dev->dev.bus_id);
@@ -840,6 +862,23 @@ int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, int mode)
return 0;
}
+/**
+ * pnp_resource_change - change one resource
+ * @resource: pointer to resource to be changed
+ * @start: start of region
+ * @size: size of region
+ *
+ */
+
+void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size)
+{
+ if (resource == NULL)
+ return;
+ resource->flags &= ~IORESOURCE_AUTO;
+ resource->start = start;
+ resource->end = start + size - 1;
+}
+
EXPORT_SYMBOL(pnp_build_resource);
EXPORT_SYMBOL(pnp_find_resources);
EXPORT_SYMBOL(pnp_get_max_depnum);
@@ -848,9 +887,11 @@ EXPORT_SYMBOL(pnp_add_dma_resource);
EXPORT_SYMBOL(pnp_add_port_resource);
EXPORT_SYMBOL(pnp_add_mem_resource);
EXPORT_SYMBOL(pnp_add_mem32_resource);
+EXPORT_SYMBOL(pnp_init_res_cfg);
EXPORT_SYMBOL(pnp_activate_dev);
EXPORT_SYMBOL(pnp_disable_dev);
EXPORT_SYMBOL(pnp_raw_set_dev);
+EXPORT_SYMBOL(pnp_resource_change);
/* format is: allowdma0 */
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
index aa599f3385d2..1029a1d126ce 100644
--- a/drivers/serial/8250_pnp.c
+++ b/drivers/serial/8250_pnp.c
@@ -360,7 +360,7 @@ static int serial_pnp_guess_board(struct pnp_dev *dev, int *flags)
struct pnp_resources *res = dev->res;
struct pnp_resources *resa;
- if (!(check_name(dev->name) || check_name(dev->card->name)))
+ if (!(check_name(dev->name) || (dev->card && check_name(dev->card->name))))
return -ENODEV;
if (!res)
@@ -385,8 +385,11 @@ serial_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id)
{
struct serial_struct serial_req;
int ret, line, flags = dev_id->driver_data;
- if (flags & UNKNOWN_DEV)
+ if (flags & UNKNOWN_DEV) {
ret = serial_pnp_guess_board(dev, &flags);
+ if (ret < 0)
+ return ret;
+ }
if (flags & SPCI_FL_NO_SHIRQ)
avoid_irq_share(dev);
memset(&serial_req, 0, sizeof(serial_req));