diff options
| author | Linus Torvalds <torvalds@home.transmeta.com> | 2002-12-29 23:37:08 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-12-29 23:37:08 -0800 |
| commit | 3c363821bedf97dbeba6cf39593eddd6d39fb551 (patch) | |
| tree | 0339622444c3108c220930f8380f54faa6296f30 /drivers | |
| parent | 8e5cae4ebd85434babf5e4ffaf07893aac68fa1c (diff) | |
| parent | 4513bc2fb92aa9407cea9c9b56053f38c211b6aa (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.c | 26 | ||||
| -rw-r--r-- | drivers/pnp/card.c | 14 | ||||
| -rw-r--r-- | drivers/pnp/core.c | 3 | ||||
| -rw-r--r-- | drivers/pnp/driver.c | 16 | ||||
| -rw-r--r-- | drivers/pnp/idlist.h | 3 | ||||
| -rw-r--r-- | drivers/pnp/interface.c | 20 | ||||
| -rw-r--r-- | drivers/pnp/isapnp/Makefile | 4 | ||||
| -rw-r--r-- | drivers/pnp/isapnp/compat.c | 25 | ||||
| -rw-r--r-- | drivers/pnp/isapnp/core.c | 58 | ||||
| -rw-r--r-- | drivers/pnp/isapnp/proc.c | 1 | ||||
| -rw-r--r-- | drivers/pnp/pnpbios/core.c | 27 | ||||
| -rw-r--r-- | drivers/pnp/resource.c | 107 | ||||
| -rw-r--r-- | drivers/serial/8250_pnp.c | 7 |
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)); |
