I've revised the PnP code and found numerous of simple bugs. Also,
my opinion is that the resctriction of resources to only ones hardcoded by
hardware vendors is not a good idea. Hardware usually supports more
configurations (especially ISA PnP devices).
I've tried to implement a configuration template, so driver can
pass it's own resource map in the probe phase. Also, I've added a new
member to the driver structures - flags. The flag
PNP_DRIVER_DO_NOT_ACTIVATE instructs the pnp code that the device
shouldn't be activated before the probe() callback is entered. It's
necessary to implement this behaviour to allow passing of a new
configuration template (thus calling pnp_activate_dev() from the probe()
callback).
Also, the resources can be locked now (I've changed the ro flag to
lock_resources).
Jaroslav
You can import this changeset into BK by piping this whole message to:
'| bk receive [path to repository]' or apply the patch as usual.
===================================================================
ChangeSet@1.901, 2002-12-26 16:56:19+01:00, perex@suse.cz
PnP update
- added configuration templates - configuration can be changed from the probe() callback
- new PnP ID - NSC6001
- fixes in PnP BIOS code - no more oopses
- fixed typos and thinkos in 8250_pnp.c
Documentation/isapnp.txt | 193 +--------------------------------------------
drivers/pnp/card.c | 14 ++-
drivers/pnp/core.c | 3
drivers/pnp/driver.c | 16 ++-
drivers/pnp/idlist.h | 3
drivers/pnp/interface.c | 20 ++++
drivers/pnp/isapnp/core.c | 4
drivers/pnp/pnpbios/core.c | 27 +++---
drivers/pnp/resource.c | 107 +++++++++++++++++-------
drivers/serial/8250_pnp.c | 7 +
include/linux/pnp.h | 35 ++++++--
11 files changed, 176 insertions(+), 253 deletions(-)
diff -Nru a/Documentation/isapnp.txt b/Documentation/isapnp.txt
--- a/Documentation/isapnp.txt Thu Dec 26 19:45:04 2002
+++ b/Documentation/isapnp.txt Thu Dec 26 19:45:04 2002
@@ -4,199 +4,11 @@
Interface /proc/isapnp
======================
-Read commands:
---------------
+The interface has been removed. See pnp.txt for more details.
-No comment.
-
-Write commands:
----------------
-
-With the write interface you can activate or modify the configuration of
-ISA Plug & Play devices. It is mainly useful for drivers which have not
-been rewritten to use the ISA Plug & Play kernel support yet.
-
-card <idx> <vendor> - select PnP device by vendor identification
-csn <CSN> - select PnP device by CSN
-dev <idx> <logdev> - select logical device
-auto - run autoconfigure
-activate - activate logical device
-deactivate - deactivate logical device
-port <idx> <value> - set port 0-7 to value
-irq <idx> <value> - set IRQ 0-1 to value
-dma <idx> <value> - set DMA 0-1 to value
-memory <idx> <value> - set memory 0-3 to value
-poke <reg> <value> - poke configuration byte to selected register
-pokew <reg> <value> - poke configuration word to selected register
-poked <reg> <value> - poke configuration dword to selected register
-allow_dma0 <value> - allow dma channel 0 during auto activation: 0=off, 1=on
-
-Explanation:
- - variable <idx> begins with zero
- - variable <CSN> begins with one
- - <vendor> is in the standard format 'ABC1234'
- - <logdev> is in the standard format 'ABC1234'
-
-Example:
-
-cat > /proc/isapnp <<EOF
-card 0 CSC7537
-dev 0 CSC0000
-port 0 0x534
-port 1 0x388
-port 2 0x220
-irq 0 5
-dma 0 1
-dma 1 3
-poke 0x70 9
-activate
-logdev 0 CSC0001
-port 0 0x240
-activate
-EOF
-
-
-Information for developers
+Interface /proc/bus/isapnp
==========================
-Finding a device
-----------------
-
-extern struct pci_bus *isapnp_find_card(unsigned short vendor,
- unsigned short device,
- struct pci_bus *from);
-
-This function finds an ISA PnP card. For the vendor argument, the
-ISAPNP_VENDOR(a,b,c) macro should be used, where a,b,c are characters or
-integers. For the device argument the ISAPNP_DEVICE(x) macro should be
-used, where x is an integer value. Both vendor and device arguments
-can be taken from contents of the /proc/isapnp file.
-
-extern struct pci_dev *isapnp_find_dev(struct pci_bus *card,
- unsigned short vendor,
- unsigned short function,
- struct pci_dev *from);
-
-This function finds an ISA PnP device. If card is NULL, then the global
-search mode is used (all devices are used for the searching). Otherwise
-only devices which belong to the specified card are checked. For the
-function number the ISAPNP_FUNCTION(x) macro can be used; it works
-similarly to the ISAPNP_DEVICE(x) macro.
-
-extern int isapnp_probe_cards(const struct isapnp_card_id *ids,
- int (*probe)(struct pci_bus *card,
- const struct isapnp_card_id *id));
-
-
-This function is a helper for drivers which need to use more than
-one device from an ISA PnP card. The probe callback is called with
-appropriate arguments for each card.
-
-Example for ids parameter initialization:
-
-static struct isapnp_card_id card_ids[] __devinitdata = {
- {
- ISAPNP_CARD_ID('A','D','V', 0x550a),
- devs: {
- ISAPNP_DEVICE_ID('A', 'D', 'V', 0x0010),
- ISAPNP_DEVICE_ID('A', 'D', 'V', 0x0011)
- },
- driver_data: 0x1234,
- },
- {
- ISAPNP_CARD_END,
- }
-};
-ISAPNP_CARD_TABLE(card_ids);
-
-extern int isapnp_probe_devs(const struct isapnp_device_id *ids,
- int (*probe)(struct pci_bus *card,
- const struct isapnp_device_id *id));
-
-
-This function is a helper for drivers which need to use one
-device from an ISA PnP card. The probe callback is called with
-appropriate arguments for each matched device.
-
-Example for ids parameter initialization:
-
-static struct isapnp_device_id device_ids[] __devinitdata = {
- { ISAPNP_DEVICE_SINGLE('E','S','S', 0x0968, 'E','S','S', 0x0968), },
- { ISAPNP_DEVICE_SINGLE_END, }
-};
-MODULE_DEVICE_TABLE(isapnp, device_ids);
-
-
-ISA PnP configuration
-=====================
-
-There are two ways in which the ISA PnP interface can be used.
-
-First way: low-level
---------------------
-
-All ISA PNP configuration registers are accessible via the low-level
-isapnp_(read|write)_(byte|word|dword) functions.
-
-The function isapnp_cfg_begin() must be called before any lowlevel function.
-The function isapnp_cfg_end() must be always called after configuration
-otherwise the access to the ISA PnP configuration functions will be blocked.
-
-Second way: auto-configuration
-------------------------------
-
-This feature gives to the driver the real power of the ISA PnP driver.
-The function dev->prepare() initializes the resource members in the device
-structure. This structure contains all resources set to auto configuration
-values after the initialization. The device driver may modify some resources
-to skip the auto configuration for a given resource.
-
-Once the device structure contains all requested resource values, the function
-dev->activate() must be called to assign free resources to resource members
-with the auto configuration value.
-
-Function dev->activate() does:
- - resources with the auto configuration value are configured
- - the auto configuration is created using ISA PnP resource map
- - the function writes configuration to ISA PnP configuration registers
- - the function returns to the caller actual used resources
-
-When the device driver is removed, function dev->deactivate() has to be
-called to free all assigned resources.
-
-Example (game port initialization)
-==================================
-
-/*** initialization ***/
-
- struct pci_dev *dev;
-
- /* find the first game port, use standard PnP IDs */
- dev = isapnp_find_dev(NULL,
- ISAPNP_VENDOR('P','N','P'),
- ISAPNP_FUNCTION(0xb02f),
- NULL);
- if (!dev)
- return -ENODEV;
- if (dev->active)
- return -EBUSY;
- if (dev->prepare(dev)<0)
- return -EAGAIN;
- if (!(dev->resource[0].flags & IORESOURCE_IO))
- return -ENODEV;
- if (!dev->ro) {
- /* override resource */
- if (user_port != USER_PORT_AUTO_VALUE)
- isapnp_resource_change(&dev->resource[0], user_port, 1);
- }
- if (dev->activate(dev)<0) {
- printk("isapnp configure failed (out of resources?)\n");
- return -ENOMEM;
- }
- user_port = dev->resource[0].start; /* get real port */
-
-/*** deactivation ***/
-
- /* to deactivate use: */
- if (dev)
- dev->deactivate(dev);
+This directory allows access to ISA PnP cards and logical devices.
+The regular files contain the contents of ISA PnP registers for
+a logical device.
diff -Nru a/drivers/pnp/card.c b/drivers/pnp/card.c
--- a/drivers/pnp/card.c Thu Dec 26 19:45:04 2002
+++ b/drivers/pnp/card.c Thu Dec 26 19:45:04 2002
@@ -192,6 +192,7 @@
{
struct list_head *pos;
struct pnp_dev *dev;
+ struct pnpc_driver *cdrv;
if (!card || !id)
goto done;
if (!from) {
@@ -212,9 +213,16 @@
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 -Nru a/drivers/pnp/core.c b/drivers/pnp/core.c
--- a/drivers/pnp/core.c Thu Dec 26 19:45:04 2002
+++ b/drivers/pnp/core.c Thu Dec 26 19:45:04 2002
@@ -115,7 +115,8 @@
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 -Nru a/drivers/pnp/driver.c b/drivers/pnp/driver.c
--- a/drivers/pnp/driver.c Thu Dec 26 19:45:04 2002
+++ b/drivers/pnp/driver.c Thu Dec 26 19:45:04 2002
@@ -66,7 +66,7 @@
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 @@
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 -Nru a/drivers/pnp/idlist.h b/drivers/pnp/idlist.h
--- a/drivers/pnp/idlist.h Thu Dec 26 19:45:04 2002
+++ b/drivers/pnp/idlist.h Thu Dec 26 19:45:04 2002
@@ -5,6 +5,7 @@
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("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("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 -Nru a/drivers/pnp/interface.c b/drivers/pnp/interface.c
--- a/drivers/pnp/interface.c Thu Dec 26 19:45:04 2002
+++ b/drivers/pnp/interface.c Thu Dec 26 19:45:04 2002
@@ -295,12 +295,28 @@
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 @@
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 -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
--- a/drivers/pnp/isapnp/core.c Thu Dec 26 19:45:04 2002
+++ b/drivers/pnp/isapnp/core.c Thu Dec 26 19:45:04 2002
@@ -631,7 +631,7 @@
*/
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];
@@ -947,7 +947,7 @@
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;
diff -Nru a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
--- a/drivers/pnp/pnpbios/core.c Thu Dec 26 19:45:04 2002
+++ b/drivers/pnp/pnpbios/core.c Thu Dec 26 19:45:04 2002
@@ -1058,6 +1058,7 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
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 -Nru a/drivers/pnp/resource.c b/drivers/pnp/resource.c
--- a/drivers/pnp/resource.c Thu Dec 26 19:45:04 2002
+++ b/drivers/pnp/resource.c Thu Dec 26 19:45:04 2002
@@ -588,45 +588,65 @@
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 @@
* 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 @@
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 @@
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 @@
{
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_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 @@
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_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 -Nru a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
--- a/drivers/serial/8250_pnp.c Thu Dec 26 19:45:04 2002
+++ b/drivers/serial/8250_pnp.c Thu Dec 26 19:45:04 2002
@@ -360,7 +360,7 @@
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 @@
{
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));
diff -Nru a/include/linux/pnp.h b/include/linux/pnp.h
--- a/include/linux/pnp.h Thu Dec 26 19:45:04 2002
+++ b/include/linux/pnp.h Thu Dec 26 19:45:04 2002
@@ -26,6 +26,7 @@
struct pnp_resource;
struct pnp_protocol;
struct pnp_id;
+struct pnp_cfg;
struct pnp_card {
char name[80];
@@ -79,7 +80,6 @@
struct pnp_dev {
char name[80]; /* device name */
int active; /* status of the device */
- int ro; /* read only */
struct list_head global_list; /* node in global list of devices */
struct list_head protocol_list; /* node in list of device's protocol */
struct list_head card_list; /* node in card's list of devices */
@@ -93,6 +93,7 @@
unsigned short regs; /* ISAPnP: supported registers */
struct pnp_resources *res; /* possible resource information */
+ int lock_resources; /* resources are locked */
struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
struct resource dma_resource[DEVICE_COUNT_DMA];
struct resource irq_resource[DEVICE_COUNT_IRQ];
@@ -112,6 +113,13 @@
dev != global_to_pnp_dev(&pnp_global); \
dev = global_to_pnp_dev(dev->global_list.next))
+static inline int pnp_dev_has_driver(struct pnp_dev *pdev)
+{
+ if (pdev->driver || (pdev->card && pdev->card->driver))
+ return 1;
+ return 0;
+}
+
static inline void *pnp_get_drvdata (struct pnp_dev *pdev)
{
return dev_get_drvdata(&pdev->dev);
@@ -160,10 +168,13 @@
} devs[MAX_DEVICES]; /* logical devices */
};
+#define PNP_DRIVER_DO_NOT_ACTIVATE (1<<0)
+
struct pnp_driver {
struct list_head node;
char *name;
const struct pnp_device_id *id_table;
+ unsigned int flags;
int (*probe) (struct pnp_dev *dev, const struct pnp_device_id *dev_id);
void (*remove) (struct pnp_dev *dev);
struct device_driver driver;
@@ -171,10 +182,13 @@
#define to_pnp_driver(drv) container_of(drv,struct pnp_driver, driver)
+#define PNPC_DRIVER_DO_NOT_ACTIVATE (1<<0)
+
struct pnpc_driver {
struct list_head node;
char *name;
const struct pnp_card_id *id_table;
+ unsigned int flags;
int (*probe) (struct pnp_card *card, const struct pnp_card_id *card_id);
void (*remove) (struct pnp_card *card);
struct device_driver driver;
@@ -279,6 +293,12 @@
struct pnp_resources *dep; /* dependent resources */
};
+struct pnp_res_cfg {
+ struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
+ struct resource dma_resource[DEVICE_COUNT_DMA];
+ struct resource irq_resource[DEVICE_COUNT_IRQ];
+};
+
#define PNP_DYNAMIC 0 /* get or set current resource */
#define PNP_STATIC 1 /* get or set resource for next boot */
@@ -287,7 +307,7 @@
struct pnp_irq *irq[2];
struct pnp_dma *dma[2];
struct pnp_mem *mem[4];
- struct pnp_dev request;
+ struct pnp_res_cfg request;
};
@@ -340,9 +360,11 @@
int pnp_add_port_resource(struct pnp_dev *dev, int depnum, struct pnp_port *data);
int pnp_add_mem_resource(struct pnp_dev *dev, int depnum, struct pnp_mem *data);
int pnp_add_mem32_resource(struct pnp_dev *dev, int depnum, struct pnp_mem32 *data);
-int pnp_activate_dev(struct pnp_dev *dev);
+int pnp_init_res_cfg(struct pnp_res_cfg *template);
+int pnp_activate_dev(struct pnp_dev *dev, struct pnp_res_cfg *template);
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);
+void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size);
/* driver */
int compare_pnp_id(struct pnp_id * pos, const char * id);
@@ -366,9 +388,10 @@
static inline int pnp_add_port_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; }
static inline int pnp_add_mem_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; }
static inline int pnp_add_mem32_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; }
-static inline int pnp_activate_dev(struct pnp_dev *dev) { return -ENODEV; }
+static inline int pnp_init_res_cfg(struct pnp_res_cfg *template) { return -ENODEV; }
+static inline int pnp_activate_dev(struct pnp_dev *dev, struct pnp_res_cfg *template) { return -ENODEV; }
static inline int pnp_disable_dev(struct pnp_dev *dev) { return -ENODEV; }
-static inline int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, int mode) { return -ENODEV; }
+static inline int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, struct pnp_res_cfg *template, int mode) { return -ENODEV; }
static inline int compare_pnp_id(struct list_head * id_list, const char * id) { return -ENODEV; }
static inline int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) { return -ENODEV; }
static inline int pnp_register_driver(struct pnp_driver *drv) { return -ENODEV; }
===================================================================
This BitKeeper patch contains the following changesets:
1.901
## Wrapped with gzip_uu ##
begin 664 bkpatch857
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
`
end
-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SuSE Labs
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/