Commit a7035a19 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://are.twiddle.net/axp-2.5/

into home.transmeta.com:/home/torvalds/v2.5/linux
parents a58d5360 d3899e3c
...@@ -4,29 +4,11 @@ void *pnp_alloc(long size); ...@@ -4,29 +4,11 @@ void *pnp_alloc(long size);
int pnp_interface_attach_device(struct pnp_dev *dev); int pnp_interface_attach_device(struct pnp_dev *dev);
void pnp_name_device(struct pnp_dev *dev); void pnp_name_device(struct pnp_dev *dev);
void pnp_fixup_device(struct pnp_dev *dev); void pnp_fixup_device(struct pnp_dev *dev);
void pnp_free_resources(struct pnp_resources *resources); void pnp_free_option(struct pnp_option *option);
int __pnp_add_device(struct pnp_dev *dev); int __pnp_add_device(struct pnp_dev *dev);
void __pnp_remove_device(struct pnp_dev *dev); void __pnp_remove_device(struct pnp_dev *dev);
/* resource conflict types */
#define CONFLICT_TYPE_NONE 0x0000 /* there are no conflicts, other than those in the link */
#define CONFLICT_TYPE_RESERVED 0x0001 /* the resource requested was reserved */
#define CONFLICT_TYPE_IN_USE 0x0002 /* there is a conflict because the resource is in use */
#define CONFLICT_TYPE_PCI 0x0004 /* there is a conflict with a pci device */
#define CONFLICT_TYPE_INVALID 0x0008 /* the resource requested is invalid */
#define CONFLICT_TYPE_INTERNAL 0x0010 /* resources within the device conflict with each ohter */
#define CONFLICT_TYPE_PNP_WARM 0x0020 /* there is a conflict with a pnp device that is active */
#define CONFLICT_TYPE_PNP_COLD 0x0040 /* there is a conflict with a pnp device that is disabled */
/* conflict search modes */
#define SEARCH_WARM 1 /* check for conflicts with active devices */
#define SEARCH_COLD 0 /* check for conflicts with disabled devices */
struct pnp_dev * pnp_check_port_conflicts(struct pnp_dev * dev, int idx, int mode);
int pnp_check_port(struct pnp_dev * dev, int idx); int pnp_check_port(struct pnp_dev * dev, int idx);
struct pnp_dev * pnp_check_mem_conflicts(struct pnp_dev * dev, int idx, int mode);
int pnp_check_mem(struct pnp_dev * dev, int idx); int pnp_check_mem(struct pnp_dev * dev, int idx);
struct pnp_dev * pnp_check_irq_conflicts(struct pnp_dev * dev, int idx, int mode);
int pnp_check_irq(struct pnp_dev * dev, int idx); int pnp_check_irq(struct pnp_dev * dev, int idx);
struct pnp_dev * pnp_check_dma_conflicts(struct pnp_dev * dev, int idx, int mode);
int pnp_check_dma(struct pnp_dev * dev, int idx); int pnp_check_dma(struct pnp_dev * dev, int idx);
...@@ -104,8 +104,8 @@ static void pnp_free_ids(struct pnp_dev *dev) ...@@ -104,8 +104,8 @@ static void pnp_free_ids(struct pnp_dev *dev)
static void pnp_release_device(struct device *dmdev) static void pnp_release_device(struct device *dmdev)
{ {
struct pnp_dev * dev = to_pnp_dev(dmdev); struct pnp_dev * dev = to_pnp_dev(dmdev);
if (dev->possible) pnp_free_option(dev->independent);
pnp_free_resources(dev->possible); pnp_free_option(dev->dependent);
pnp_free_ids(dev); pnp_free_ids(dev);
kfree(dev); kfree(dev);
} }
...@@ -122,7 +122,7 @@ int __pnp_add_device(struct pnp_dev *dev) ...@@ -122,7 +122,7 @@ int __pnp_add_device(struct pnp_dev *dev)
list_add_tail(&dev->global_list, &pnp_global); list_add_tail(&dev->global_list, &pnp_global);
list_add_tail(&dev->protocol_list, &dev->protocol->devices); list_add_tail(&dev->protocol_list, &dev->protocol->devices);
spin_unlock(&pnp_lock); spin_unlock(&pnp_lock);
pnp_auto_config_dev(dev);
ret = device_register(&dev->dev); ret = device_register(&dev->dev);
if (ret == 0) if (ret == 0)
pnp_interface_attach_device(dev); pnp_interface_attach_device(dev);
......
...@@ -168,7 +168,8 @@ static void pnp_print_mem(pnp_info_buffer_t *buffer, char *space, struct pnp_mem ...@@ -168,7 +168,8 @@ static void pnp_print_mem(pnp_info_buffer_t *buffer, char *space, struct pnp_mem
pnp_printf(buffer, ", %s\n", s); pnp_printf(buffer, ", %s\n", s);
} }
static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct pnp_resources *res, int dep) static void pnp_print_option(pnp_info_buffer_t *buffer, char *space,
struct pnp_option *option, int dep)
{ {
char *s; char *s;
struct pnp_port *port; struct pnp_port *port;
...@@ -176,7 +177,8 @@ static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct p ...@@ -176,7 +177,8 @@ static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct p
struct pnp_dma *dma; struct pnp_dma *dma;
struct pnp_mem *mem; struct pnp_mem *mem;
switch (res->priority) { if (dep) {
switch (option->priority) {
case PNP_RES_PRIORITY_PREFERRED: case PNP_RES_PRIORITY_PREFERRED:
s = "preferred"; s = "preferred";
break; break;
...@@ -189,36 +191,41 @@ static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct p ...@@ -189,36 +191,41 @@ static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct p
default: default:
s = "invalid"; s = "invalid";
} }
if (dep > 0)
pnp_printf(buffer, "Dependent: %02i - Priority %s\n",dep, s); pnp_printf(buffer, "Dependent: %02i - Priority %s\n",dep, s);
for (port = res->port; port; port = port->next) }
for (port = option->port; port; port = port->next)
pnp_print_port(buffer, space, port); pnp_print_port(buffer, space, port);
for (irq = res->irq; irq; irq = irq->next) for (irq = option->irq; irq; irq = irq->next)
pnp_print_irq(buffer, space, irq); pnp_print_irq(buffer, space, irq);
for (dma = res->dma; dma; dma = dma->next) for (dma = option->dma; dma; dma = dma->next)
pnp_print_dma(buffer, space, dma); pnp_print_dma(buffer, space, dma);
for (mem = res->mem; mem; mem = mem->next) for (mem = option->mem; mem; mem = mem->next)
pnp_print_mem(buffer, space, mem); pnp_print_mem(buffer, space, mem);
} }
static ssize_t pnp_show_possible_resources(struct device *dmdev, char *buf)
static ssize_t pnp_show_options(struct device *dmdev, char *buf)
{ {
struct pnp_dev *dev = to_pnp_dev(dmdev); struct pnp_dev *dev = to_pnp_dev(dmdev);
struct pnp_resources * res = dev->possible; struct pnp_option * independent = dev->independent;
int ret, dep = 0; struct pnp_option * dependent = dev->dependent;
int ret, dep = 1;
pnp_info_buffer_t *buffer = (pnp_info_buffer_t *) pnp_info_buffer_t *buffer = (pnp_info_buffer_t *)
pnp_alloc(sizeof(pnp_info_buffer_t)); pnp_alloc(sizeof(pnp_info_buffer_t));
if (!buffer) if (!buffer)
return -ENOMEM; return -ENOMEM;
buffer->len = PAGE_SIZE; buffer->len = PAGE_SIZE;
buffer->buffer = buf; buffer->buffer = buf;
buffer->curr = buffer->buffer; buffer->curr = buffer->buffer;
while (res){ if (independent)
if (dep == 0) pnp_print_option(buffer, "", independent, 0);
pnp_print_resources(buffer, "", res, dep);
else while (dependent){
pnp_print_resources(buffer, " ", res, dep); pnp_print_option(buffer, " ", dependent, dep);
res = res->dep; dependent = dependent->next;
dep++; dep++;
} }
ret = (buffer->curr - buf); ret = (buffer->curr - buf);
...@@ -226,97 +233,8 @@ static ssize_t pnp_show_possible_resources(struct device *dmdev, char *buf) ...@@ -226,97 +233,8 @@ static ssize_t pnp_show_possible_resources(struct device *dmdev, char *buf)
return ret; return ret;
} }
static DEVICE_ATTR(possible,S_IRUGO,pnp_show_possible_resources,NULL); static DEVICE_ATTR(options,S_IRUGO,pnp_show_options,NULL);
static void pnp_print_conflict_node(pnp_info_buffer_t *buffer, struct pnp_dev * dev)
{
if (!dev)
return;
pnp_printf(buffer, "'%s'.\n", dev->dev.bus_id);
}
static void pnp_print_conflict_desc(pnp_info_buffer_t *buffer, int conflict)
{
if (!conflict)
return;
pnp_printf(buffer, " Conflict Detected: %2x - ", conflict);
switch (conflict) {
case CONFLICT_TYPE_RESERVED:
pnp_printf(buffer, "manually reserved.\n");
break;
case CONFLICT_TYPE_IN_USE:
pnp_printf(buffer, "currently in use.\n");
break;
case CONFLICT_TYPE_PCI:
pnp_printf(buffer, "PCI device.\n");
break;
case CONFLICT_TYPE_INVALID:
pnp_printf(buffer, "invalid.\n");
break;
case CONFLICT_TYPE_INTERNAL:
pnp_printf(buffer, "another resource on this device.\n");
break;
case CONFLICT_TYPE_PNP_WARM:
pnp_printf(buffer, "active PnP device ");
break;
case CONFLICT_TYPE_PNP_COLD:
pnp_printf(buffer, "disabled PnP device ");
break;
default:
pnp_printf(buffer, "Unknown conflict.\n");
break;
}
}
static void pnp_print_conflict(pnp_info_buffer_t *buffer, struct pnp_dev * dev, int idx, int type)
{
struct pnp_dev * cdev, * wdev = NULL;
int conflict;
switch (type) {
case IORESOURCE_IO:
conflict = pnp_check_port(dev, idx);
if (conflict == CONFLICT_TYPE_PNP_WARM)
wdev = pnp_check_port_conflicts(dev, idx, SEARCH_WARM);
cdev = pnp_check_port_conflicts(dev, idx, SEARCH_COLD);
break;
case IORESOURCE_MEM:
conflict = pnp_check_mem(dev, idx);
if (conflict == CONFLICT_TYPE_PNP_WARM)
wdev = pnp_check_mem_conflicts(dev, idx, SEARCH_WARM);
cdev = pnp_check_mem_conflicts(dev, idx, SEARCH_COLD);
break;
case IORESOURCE_IRQ:
conflict = pnp_check_irq(dev, idx);
if (conflict == CONFLICT_TYPE_PNP_WARM)
wdev = pnp_check_irq_conflicts(dev, idx, SEARCH_WARM);
cdev = pnp_check_irq_conflicts(dev, idx, SEARCH_COLD);
break;
case IORESOURCE_DMA:
conflict = pnp_check_dma(dev, idx);
if (conflict == CONFLICT_TYPE_PNP_WARM)
wdev = pnp_check_dma_conflicts(dev, idx, SEARCH_WARM);
cdev = pnp_check_dma_conflicts(dev, idx, SEARCH_COLD);
break;
default:
return;
}
pnp_print_conflict_desc(buffer, conflict);
if (wdev)
pnp_print_conflict_node(buffer, wdev);
if (cdev) {
pnp_print_conflict_desc(buffer, CONFLICT_TYPE_PNP_COLD);
pnp_print_conflict_node(buffer, cdev);
}
}
static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf) static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
{ {
...@@ -332,12 +250,6 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf) ...@@ -332,12 +250,6 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
buffer->buffer = buf; buffer->buffer = buf;
buffer->curr = buffer->buffer; buffer->curr = buffer->buffer;
pnp_printf(buffer,"mode = ");
if (dev->config_mode & PNP_CONFIG_MANUAL)
pnp_printf(buffer,"manual\n");
else
pnp_printf(buffer,"auto\n");
pnp_printf(buffer,"state = "); pnp_printf(buffer,"state = ");
if (dev->active) if (dev->active)
pnp_printf(buffer,"active\n"); pnp_printf(buffer,"active\n");
...@@ -350,7 +262,6 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf) ...@@ -350,7 +262,6 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
pnp_printf(buffer," 0x%lx-0x%lx \n", pnp_printf(buffer," 0x%lx-0x%lx \n",
pnp_port_start(dev, i), pnp_port_start(dev, i),
pnp_port_end(dev, i)); pnp_port_end(dev, i));
pnp_print_conflict(buffer, dev, i, IORESOURCE_IO);
} }
} }
for (i = 0; i < PNP_MAX_MEM; i++) { for (i = 0; i < PNP_MAX_MEM; i++) {
...@@ -359,21 +270,18 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf) ...@@ -359,21 +270,18 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
pnp_printf(buffer," 0x%lx-0x%lx \n", pnp_printf(buffer," 0x%lx-0x%lx \n",
pnp_mem_start(dev, i), pnp_mem_start(dev, i),
pnp_mem_end(dev, i)); pnp_mem_end(dev, i));
pnp_print_conflict(buffer, dev, i, IORESOURCE_MEM);
} }
} }
for (i = 0; i < PNP_MAX_IRQ; i++) { for (i = 0; i < PNP_MAX_IRQ; i++) {
if (pnp_irq_valid(dev, i)) { if (pnp_irq_valid(dev, i)) {
pnp_printf(buffer,"irq"); pnp_printf(buffer,"irq");
pnp_printf(buffer," %ld \n", pnp_irq(dev, i)); pnp_printf(buffer," %ld \n", pnp_irq(dev, i));
pnp_print_conflict(buffer, dev, i, IORESOURCE_IRQ);
} }
} }
for (i = 0; i < PNP_MAX_DMA; i++) { for (i = 0; i < PNP_MAX_DMA; i++) {
if (pnp_dma_valid(dev, i)) { if (pnp_dma_valid(dev, i)) {
pnp_printf(buffer,"dma"); pnp_printf(buffer,"dma");
pnp_printf(buffer," %ld \n", pnp_dma(dev, i)); pnp_printf(buffer," %ld \n", pnp_dma(dev, i));
pnp_print_conflict(buffer, dev, i, IORESOURCE_DMA);
} }
} }
ret = (buffer->curr - buf); ret = (buffer->curr - buf);
...@@ -381,7 +289,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf) ...@@ -381,7 +289,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
return ret; return ret;
} }
extern int pnp_resolve_conflicts(struct pnp_dev *dev); extern struct semaphore pnp_res_mutex;
static ssize_t static ssize_t
pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count) pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count)
...@@ -390,6 +298,12 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count ...@@ -390,6 +298,12 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count
char *buf = (void *)ubuf; char *buf = (void *)ubuf;
int retval = 0; int retval = 0;
if (dev->status & PNP_ATTACHED) {
retval = -EBUSY;
pnp_info("Device %s cannot be configured because it is in use.", dev->dev.bus_id);
goto done;
}
while (isspace(*buf)) while (isspace(*buf))
++buf; ++buf;
if (!strnicmp(buf,"disable",7)) { if (!strnicmp(buf,"disable",7)) {
...@@ -400,41 +314,30 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count ...@@ -400,41 +314,30 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count
retval = pnp_activate_dev(dev); retval = pnp_activate_dev(dev);
goto done; goto done;
} }
if (!strnicmp(buf,"reset",5)) { if (!strnicmp(buf,"fill",4)) {
if (!dev->active) if (dev->active)
goto done;
retval = pnp_disable_dev(dev);
if (retval)
goto done; goto done;
retval = pnp_activate_dev(dev); retval = pnp_auto_config_dev(dev);
goto done; goto done;
} }
if (!strnicmp(buf,"auto",4)) { if (!strnicmp(buf,"auto",4)) {
if (dev->active) if (dev->active)
goto done; goto done;
pnp_init_resources(&dev->res);
retval = pnp_auto_config_dev(dev); retval = pnp_auto_config_dev(dev);
goto done; goto done;
} }
if (!strnicmp(buf,"clear",5)) { if (!strnicmp(buf,"clear",5)) {
if (dev->active) if (dev->active)
goto done; goto done;
spin_lock(&pnp_lock); pnp_init_resources(&dev->res);
dev->config_mode = PNP_CONFIG_MANUAL;
pnp_init_resource_table(&dev->res);
if (dev->rule)
dev->rule->depnum = 0;
spin_unlock(&pnp_lock);
goto done;
}
if (!strnicmp(buf,"resolve",7)) {
retval = pnp_resolve_conflicts(dev);
goto done; goto done;
} }
if (!strnicmp(buf,"get",3)) { if (!strnicmp(buf,"get",3)) {
spin_lock(&pnp_lock); down(&pnp_res_mutex);
if (pnp_can_read(dev)) if (pnp_can_read(dev))
dev->protocol->get(dev, &dev->res); dev->protocol->get(dev, &dev->res);
spin_unlock(&pnp_lock); up(&pnp_res_mutex);
goto done; goto done;
} }
if (!strnicmp(buf,"set",3)) { if (!strnicmp(buf,"set",3)) {
...@@ -442,9 +345,8 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count ...@@ -442,9 +345,8 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count
if (dev->active) if (dev->active)
goto done; goto done;
buf += 3; buf += 3;
spin_lock(&pnp_lock); pnp_init_resources(&dev->res);
dev->config_mode = PNP_CONFIG_MANUAL; down(&pnp_res_mutex);
pnp_init_resource_table(&dev->res);
while (1) { while (1) {
while (isspace(*buf)) while (isspace(*buf))
++buf; ++buf;
...@@ -514,7 +416,7 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count ...@@ -514,7 +416,7 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count
} }
break; break;
} }
spin_unlock(&pnp_lock); up(&pnp_res_mutex);
goto done; goto done;
} }
done: done:
...@@ -543,7 +445,7 @@ static DEVICE_ATTR(id,S_IRUGO,pnp_show_current_ids,NULL); ...@@ -543,7 +445,7 @@ static DEVICE_ATTR(id,S_IRUGO,pnp_show_current_ids,NULL);
int pnp_interface_attach_device(struct pnp_dev *dev) int pnp_interface_attach_device(struct pnp_dev *dev)
{ {
device_create_file(&dev->dev,&dev_attr_possible); device_create_file(&dev->dev,&dev_attr_options);
device_create_file(&dev->dev,&dev_attr_resources); device_create_file(&dev->dev,&dev_attr_resources);
device_create_file(&dev->dev,&dev_attr_id); device_create_file(&dev->dev,&dev_attr_id);
return 0; return 0;
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
* 2002-06-06 Made the use of dma channel 0 configurable * 2002-06-06 Made the use of dma channel 0 configurable
* Gerald Teschl <gerald.teschl@univie.ac.at> * Gerald Teschl <gerald.teschl@univie.ac.at>
* 2002-10-06 Ported to PnP Layer - Adam Belay <ambx1@neo.rr.com> * 2002-10-06 Ported to PnP Layer - Adam Belay <ambx1@neo.rr.com>
* 2003-08-11 Resource Management Updates - Adam Belay <ambx1@neo.rr.com>
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -54,7 +55,6 @@ ...@@ -54,7 +55,6 @@
int isapnp_disable; /* Disable ISA PnP */ int isapnp_disable; /* Disable ISA PnP */
int isapnp_rdp; /* Read Data Port */ int isapnp_rdp; /* Read Data Port */
int isapnp_reset = 1; /* reset all PnP cards (deactivate) */ int isapnp_reset = 1; /* reset all PnP cards (deactivate) */
int isapnp_skip_pci_scan; /* skip PCI resource scanning */
int isapnp_verbose = 1; /* verbose mode */ int isapnp_verbose = 1; /* verbose mode */
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
...@@ -66,8 +66,6 @@ MODULE_PARM_DESC(isapnp_rdp, "ISA Plug & Play read data port"); ...@@ -66,8 +66,6 @@ MODULE_PARM_DESC(isapnp_rdp, "ISA Plug & Play read data port");
MODULE_PARM(isapnp_reset, "i"); MODULE_PARM(isapnp_reset, "i");
MODULE_PARM_DESC(isapnp_reset, "ISA Plug & Play reset all cards"); MODULE_PARM_DESC(isapnp_reset, "ISA Plug & Play reset all cards");
MODULE_PARM(isapnp_allow_dma0, "i"); MODULE_PARM(isapnp_allow_dma0, "i");
MODULE_PARM(isapnp_skip_pci_scan, "i");
MODULE_PARM_DESC(isapnp_skip_pci_scan, "ISA Plug & Play skip PCI resource scanning");
MODULE_PARM(isapnp_verbose, "i"); MODULE_PARM(isapnp_verbose, "i");
MODULE_PARM_DESC(isapnp_verbose, "ISA Plug & Play verbose mode"); MODULE_PARM_DESC(isapnp_verbose, "ISA Plug & Play verbose mode");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -460,6 +458,7 @@ static struct pnp_dev * __init isapnp_parse_device(struct pnp_card *card, int si ...@@ -460,6 +458,7 @@ static struct pnp_dev * __init isapnp_parse_device(struct pnp_card *card, int si
dev->capabilities |= PNP_READ; dev->capabilities |= PNP_READ;
dev->capabilities |= PNP_WRITE; dev->capabilities |= PNP_WRITE;
dev->capabilities |= PNP_DISABLE; dev->capabilities |= PNP_DISABLE;
pnp_init_resources(&dev->res);
return dev; return dev;
} }
...@@ -468,8 +467,8 @@ static struct pnp_dev * __init isapnp_parse_device(struct pnp_card *card, int si ...@@ -468,8 +467,8 @@ static struct pnp_dev * __init isapnp_parse_device(struct pnp_card *card, int si
* Add IRQ resource to resources list. * Add IRQ resource to resources list.
*/ */
static void __init isapnp_add_irq_resource(struct pnp_dev *dev, static void __init isapnp_parse_irq_resource(struct pnp_option *option,
int depnum, int size) int size)
{ {
unsigned char tmp[3]; unsigned char tmp[3];
struct pnp_irq *irq; struct pnp_irq *irq;
...@@ -483,7 +482,7 @@ static void __init isapnp_add_irq_resource(struct pnp_dev *dev, ...@@ -483,7 +482,7 @@ static void __init isapnp_add_irq_resource(struct pnp_dev *dev,
irq->flags = tmp[2]; irq->flags = tmp[2];
else else
irq->flags = IORESOURCE_IRQ_HIGHEDGE; irq->flags = IORESOURCE_IRQ_HIGHEDGE;
pnp_add_irq_resource(dev, depnum, irq); pnp_register_irq_resource(option, irq);
return; return;
} }
...@@ -491,8 +490,8 @@ static void __init isapnp_add_irq_resource(struct pnp_dev *dev, ...@@ -491,8 +490,8 @@ static void __init isapnp_add_irq_resource(struct pnp_dev *dev,
* Add DMA resource to resources list. * Add DMA resource to resources list.
*/ */
static void __init isapnp_add_dma_resource(struct pnp_dev *dev, static void __init isapnp_parse_dma_resource(struct pnp_option *option,
int depnum, int size) int size)
{ {
unsigned char tmp[2]; unsigned char tmp[2];
struct pnp_dma *dma; struct pnp_dma *dma;
...@@ -503,7 +502,7 @@ static void __init isapnp_add_dma_resource(struct pnp_dev *dev, ...@@ -503,7 +502,7 @@ static void __init isapnp_add_dma_resource(struct pnp_dev *dev,
return; return;
dma->map = tmp[0]; dma->map = tmp[0];
dma->flags = tmp[1]; dma->flags = tmp[1];
pnp_add_dma_resource(dev, depnum, dma); pnp_register_dma_resource(option, dma);
return; return;
} }
...@@ -511,8 +510,8 @@ static void __init isapnp_add_dma_resource(struct pnp_dev *dev, ...@@ -511,8 +510,8 @@ static void __init isapnp_add_dma_resource(struct pnp_dev *dev,
* Add port resource to resources list. * Add port resource to resources list.
*/ */
static void __init isapnp_add_port_resource(struct pnp_dev *dev, static void __init isapnp_parse_port_resource(struct pnp_option *option,
int depnum, int size) int size)
{ {
unsigned char tmp[7]; unsigned char tmp[7];
struct pnp_port *port; struct pnp_port *port;
...@@ -526,7 +525,7 @@ static void __init isapnp_add_port_resource(struct pnp_dev *dev, ...@@ -526,7 +525,7 @@ static void __init isapnp_add_port_resource(struct pnp_dev *dev,
port->align = tmp[5]; port->align = tmp[5];
port->size = tmp[6]; port->size = tmp[6];
port->flags = tmp[0] ? PNP_PORT_FLAG_16BITADDR : 0; port->flags = tmp[0] ? PNP_PORT_FLAG_16BITADDR : 0;
pnp_add_port_resource(dev,depnum,port); pnp_register_port_resource(option,port);
return; return;
} }
...@@ -534,8 +533,8 @@ static void __init isapnp_add_port_resource(struct pnp_dev *dev, ...@@ -534,8 +533,8 @@ static void __init isapnp_add_port_resource(struct pnp_dev *dev,
* Add fixed port resource to resources list. * Add fixed port resource to resources list.
*/ */
static void __init isapnp_add_fixed_port_resource(struct pnp_dev *dev, static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option,
int depnum, int size) int size)
{ {
unsigned char tmp[3]; unsigned char tmp[3];
struct pnp_port *port; struct pnp_port *port;
...@@ -548,7 +547,7 @@ static void __init isapnp_add_fixed_port_resource(struct pnp_dev *dev, ...@@ -548,7 +547,7 @@ static void __init isapnp_add_fixed_port_resource(struct pnp_dev *dev,
port->size = tmp[2]; port->size = tmp[2];
port->align = 0; port->align = 0;
port->flags = PNP_PORT_FLAG_FIXED; port->flags = PNP_PORT_FLAG_FIXED;
pnp_add_port_resource(dev,depnum,port); pnp_register_port_resource(option,port);
return; return;
} }
...@@ -556,8 +555,8 @@ static void __init isapnp_add_fixed_port_resource(struct pnp_dev *dev, ...@@ -556,8 +555,8 @@ static void __init isapnp_add_fixed_port_resource(struct pnp_dev *dev,
* Add memory resource to resources list. * Add memory resource to resources list.
*/ */
static void __init isapnp_add_mem_resource(struct pnp_dev *dev, static void __init isapnp_parse_mem_resource(struct pnp_option *option,
int depnum, int size) int size)
{ {
unsigned char tmp[9]; unsigned char tmp[9];
struct pnp_mem *mem; struct pnp_mem *mem;
...@@ -571,7 +570,7 @@ static void __init isapnp_add_mem_resource(struct pnp_dev *dev, ...@@ -571,7 +570,7 @@ static void __init isapnp_add_mem_resource(struct pnp_dev *dev,
mem->align = (tmp[6] << 8) | tmp[5]; mem->align = (tmp[6] << 8) | tmp[5];
mem->size = ((tmp[8] << 8) | tmp[7]) << 8; mem->size = ((tmp[8] << 8) | tmp[7]) << 8;
mem->flags = tmp[0]; mem->flags = tmp[0];
pnp_add_mem_resource(dev,depnum,mem); pnp_register_mem_resource(option,mem);
return; return;
} }
...@@ -579,8 +578,8 @@ static void __init isapnp_add_mem_resource(struct pnp_dev *dev, ...@@ -579,8 +578,8 @@ static void __init isapnp_add_mem_resource(struct pnp_dev *dev,
* Add 32-bit memory resource to resources list. * Add 32-bit memory resource to resources list.
*/ */
static void __init isapnp_add_mem32_resource(struct pnp_dev *dev, static void __init isapnp_parse_mem32_resource(struct pnp_option *option,
int depnum, int size) int size)
{ {
unsigned char tmp[17]; unsigned char tmp[17];
struct pnp_mem *mem; struct pnp_mem *mem;
...@@ -594,15 +593,15 @@ static void __init isapnp_add_mem32_resource(struct pnp_dev *dev, ...@@ -594,15 +593,15 @@ static void __init isapnp_add_mem32_resource(struct pnp_dev *dev,
mem->align = (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9]; mem->align = (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9];
mem->size = (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13]; mem->size = (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13];
mem->flags = tmp[0]; mem->flags = tmp[0];
pnp_add_mem_resource(dev,depnum,mem); pnp_register_mem_resource(option,mem);
} }
/* /*
* Add 32-bit fixed memory resource to resources list. * Add 32-bit fixed memory resource to resources list.
*/ */
static void __init isapnp_add_fixed_mem32_resource(struct pnp_dev *dev, static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option,
int depnum, int size) int size)
{ {
unsigned char tmp[9]; unsigned char tmp[9];
struct pnp_mem *mem; struct pnp_mem *mem;
...@@ -615,7 +614,7 @@ static void __init isapnp_add_fixed_mem32_resource(struct pnp_dev *dev, ...@@ -615,7 +614,7 @@ static void __init isapnp_add_fixed_mem32_resource(struct pnp_dev *dev,
mem->size = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5]; mem->size = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
mem->align = 0; mem->align = 0;
mem->flags = tmp[0]; mem->flags = tmp[0];
pnp_add_mem_resource(dev,depnum,mem); pnp_register_mem_resource(option,mem);
} }
/* /*
...@@ -644,14 +643,17 @@ isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size) ...@@ -644,14 +643,17 @@ isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size)
static int __init isapnp_create_device(struct pnp_card *card, 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; int number = 0, skip = 0, priority = 0, compat = 0;
unsigned char type, tmp[17]; unsigned char type, tmp[17];
struct pnp_option *option;
struct pnp_dev *dev; struct pnp_dev *dev;
if ((dev = isapnp_parse_device(card, size, number++)) == NULL) if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
return 1; return 1;
if (pnp_build_resource(dev, 0) == NULL) option = pnp_register_independent_option(dev);
if (!option)
return 1; return 1;
pnp_add_card_device(card,dev); pnp_add_card_device(card,dev);
while (1) { while (1) {
if (isapnp_read_tag(&type, &size)<0) if (isapnp_read_tag(&type, &size)<0)
return 1; return 1;
...@@ -662,15 +664,16 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -662,15 +664,16 @@ static int __init isapnp_create_device(struct pnp_card *card,
if (size >= 5 && size <= 6) { if (size >= 5 && size <= 6) {
if ((dev = isapnp_parse_device(card, size, number++)) == NULL) if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
return 1; return 1;
pnp_build_resource(dev,0);
pnp_add_card_device(card,dev);
size = 0; size = 0;
skip = 0; skip = 0;
option = pnp_register_independent_option(dev);
if (!option)
return 1;
pnp_add_card_device(card,dev);
} else { } else {
skip = 1; skip = 1;
} }
dependent = 0; priority = 0;
depnum = 0;
compat = 0; compat = 0;
break; break;
case _STAG_COMPATDEVID: case _STAG_COMPATDEVID:
...@@ -684,43 +687,43 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -684,43 +687,43 @@ static int __init isapnp_create_device(struct pnp_card *card,
case _STAG_IRQ: case _STAG_IRQ:
if (size < 2 || size > 3) if (size < 2 || size > 3)
goto __skip; goto __skip;
isapnp_add_irq_resource(dev, depnum, size); isapnp_parse_irq_resource(option, size);
size = 0; size = 0;
break; break;
case _STAG_DMA: case _STAG_DMA:
if (size != 2) if (size != 2)
goto __skip; goto __skip;
isapnp_add_dma_resource(dev, depnum, size); isapnp_parse_dma_resource(option, size);
size = 0; size = 0;
break; break;
case _STAG_STARTDEP: case _STAG_STARTDEP:
if (size > 1) if (size > 1)
goto __skip; goto __skip;
dependent = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE; priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;
if (size > 0) { if (size > 0) {
isapnp_peek(tmp, size); isapnp_peek(tmp, size);
dependent = 0x100 | tmp[0]; priority = 0x100 | tmp[0];
size = 0; size = 0;
} }
pnp_build_resource(dev,dependent); option = pnp_register_dependent_option(dev,priority);
depnum = pnp_get_max_depnum(dev); if (!option)
return 1;
break; break;
case _STAG_ENDDEP: case _STAG_ENDDEP:
if (size != 0) if (size != 0)
goto __skip; goto __skip;
dependent = 0; priority = 0;
depnum = 0;
break; break;
case _STAG_IOPORT: case _STAG_IOPORT:
if (size != 7) if (size != 7)
goto __skip; goto __skip;
isapnp_add_port_resource(dev, depnum, size); isapnp_parse_port_resource(option, size);
size = 0; size = 0;
break; break;
case _STAG_FIXEDIO: case _STAG_FIXEDIO:
if (size != 3) if (size != 3)
goto __skip; goto __skip;
isapnp_add_fixed_port_resource(dev, depnum, size); isapnp_parse_fixed_port_resource(option, size);
size = 0; size = 0;
break; break;
case _STAG_VENDOR: case _STAG_VENDOR:
...@@ -728,7 +731,7 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -728,7 +731,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
case _LTAG_MEMRANGE: case _LTAG_MEMRANGE:
if (size != 9) if (size != 9)
goto __skip; goto __skip;
isapnp_add_mem_resource(dev, depnum, size); isapnp_parse_mem_resource(option, size);
size = 0; size = 0;
break; break;
case _LTAG_ANSISTR: case _LTAG_ANSISTR:
...@@ -743,13 +746,13 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -743,13 +746,13 @@ static int __init isapnp_create_device(struct pnp_card *card,
case _LTAG_MEM32RANGE: case _LTAG_MEM32RANGE:
if (size != 17) if (size != 17)
goto __skip; goto __skip;
isapnp_add_mem32_resource(dev, depnum, size); isapnp_parse_mem32_resource(option, size);
size = 0; size = 0;
break; break;
case _LTAG_FIXEDMEM32RANGE: case _LTAG_FIXEDMEM32RANGE:
if (size != 9) if (size != 9)
goto __skip; goto __skip;
isapnp_add_fixed_mem32_resource(dev, depnum, size); isapnp_parse_fixed_mem32_resource(option, size);
size = 0; size = 0;
break; break;
case _STAG_END: case _STAG_END:
...@@ -859,63 +862,6 @@ static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor, ...@@ -859,63 +862,6 @@ static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor,
pnp_add_card_id(id,card); pnp_add_card_id(id,card);
} }
static int isapnp_parse_current_resources(struct pnp_dev *dev, struct pnp_resource_table * res)
{
int tmp, ret;
struct pnp_rule_table rule;
if (dev->rule)
rule = *dev->rule;
else {
if (!pnp_generate_rule(dev,1,&rule))
return -EINVAL;
}
dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE);
if (dev->active) {
for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {
ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1));
if (!ret)
continue;
res->port_resource[tmp].start = ret;
if (rule.port[tmp])
res->port_resource[tmp].end = ret + rule.port[tmp]->size - 1;
else
res->port_resource[tmp].end = ret + 1; /* all we can do is assume 1 :-( */
res->port_resource[tmp].flags = IORESOURCE_IO;
}
for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) {
ret = isapnp_read_dword(ISAPNP_CFG_MEM + (tmp << 3));
if (!ret)
continue;
res->mem_resource[tmp].start = ret;
if (rule.mem[tmp])
res->mem_resource[tmp].end = ret + rule.mem[tmp]->size - 1;
else
res->mem_resource[tmp].end = ret + 1; /* all we can do is assume 1 :-( */
res->mem_resource[tmp].flags = IORESOURCE_MEM;
}
for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) {
ret = (isapnp_read_word(ISAPNP_CFG_IRQ + (tmp << 1)) >> 8);
if (!ret)
continue;
res->irq_resource[tmp].start = res->irq_resource[tmp].end = ret;
res->irq_resource[tmp].flags = IORESOURCE_IRQ;
}
for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) {
ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp);
if (ret == 4)
continue;
if (rule.dma[tmp]) { /* some isapnp systems forget to set this to 4 so we have to check */
res->dma_resource[tmp].start = res->dma_resource[tmp].end = ret;
res->dma_resource[tmp].flags = IORESOURCE_DMA;
}
}
}
return 0;
}
/* /*
* Build device list for all present ISA PnP devices. * Build device list for all present ISA PnP devices.
*/ */
...@@ -925,7 +871,6 @@ static int __init isapnp_build_device_list(void) ...@@ -925,7 +871,6 @@ static int __init isapnp_build_device_list(void)
int csn; int csn;
unsigned char header[9], checksum; unsigned char header[9], checksum;
struct pnp_card *card; struct pnp_card *card;
struct pnp_dev *dev;
isapnp_wait(); isapnp_wait();
isapnp_key(); isapnp_key();
...@@ -959,13 +904,6 @@ static int __init isapnp_build_device_list(void) ...@@ -959,13 +904,6 @@ static int __init isapnp_build_device_list(void)
card->checksum = isapnp_checksum_value; card->checksum = isapnp_checksum_value;
card->protocol = &isapnp_protocol; card->protocol = &isapnp_protocol;
/* read the current resource data */
card_for_each_dev(card,dev) {
isapnp_device(dev->number);
pnp_init_resource_table(&dev->res);
isapnp_parse_current_resources(dev, &dev->res);
}
pnp_add_card(card); pnp_add_card(card);
} }
isapnp_wait(); isapnp_wait();
...@@ -1041,12 +979,50 @@ EXPORT_SYMBOL(isapnp_write_dword); ...@@ -1041,12 +979,50 @@ EXPORT_SYMBOL(isapnp_write_dword);
EXPORT_SYMBOL(isapnp_wake); EXPORT_SYMBOL(isapnp_wake);
EXPORT_SYMBOL(isapnp_device); EXPORT_SYMBOL(isapnp_device);
static int isapnp_read_resources(struct pnp_dev *dev, struct pnp_resource_table *res)
{
int tmp, ret;
dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE);
if (dev->active) {
for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {
ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1));
if (!ret)
continue;
res->port_resource[tmp].start = ret;
res->port_resource[tmp].flags = IORESOURCE_IO;
}
for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) {
ret = isapnp_read_dword(ISAPNP_CFG_MEM + (tmp << 3));
if (!ret)
continue;
res->mem_resource[tmp].start = ret;
res->mem_resource[tmp].flags = IORESOURCE_MEM;
}
for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) {
ret = (isapnp_read_word(ISAPNP_CFG_IRQ + (tmp << 1)) >> 8);
if (!ret)
continue;
res->irq_resource[tmp].start = res->irq_resource[tmp].end = ret;
res->irq_resource[tmp].flags = IORESOURCE_IRQ;
}
for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) {
ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp);
if (ret == 4)
continue;
res->dma_resource[tmp].start = res->dma_resource[tmp].end = ret;
res->dma_resource[tmp].flags = IORESOURCE_DMA;
}
}
return 0;
}
static int isapnp_get_resources(struct pnp_dev *dev, struct pnp_resource_table * res) static int isapnp_get_resources(struct pnp_dev *dev, struct pnp_resource_table * res)
{ {
int ret; int ret;
pnp_init_resource_table(res); pnp_init_resources(res);
isapnp_cfg_begin(dev->card->number, dev->number); isapnp_cfg_begin(dev->card->number, dev->number);
ret = isapnp_parse_current_resources(dev, res); ret = isapnp_read_resources(dev, res);
isapnp_cfg_end(); isapnp_cfg_end();
return ret; return ret;
} }
...@@ -1196,7 +1172,6 @@ static int __init isapnp_setup_isapnp(char *str) ...@@ -1196,7 +1172,6 @@ static int __init isapnp_setup_isapnp(char *str)
{ {
(void)((get_option(&str,&isapnp_rdp) == 2) && (void)((get_option(&str,&isapnp_rdp) == 2) &&
(get_option(&str,&isapnp_reset) == 2) && (get_option(&str,&isapnp_reset) == 2) &&
(get_option(&str,&isapnp_skip_pci_scan) == 2) &&
(get_option(&str,&isapnp_verbose) == 2)); (get_option(&str,&isapnp_verbose) == 2));
return 1; return 1;
} }
......
/* /*
* manager.c - Resource Management, Conflict Resolution, Activation and Disabling of Devices * manager.c - Resource Management, Conflict Resolution, Activation and Disabling of Devices
* *
* based on isapnp.c resource management (c) Jaroslav Kysela <perex@suse.cz>
* Copyright 2003 Adam Belay <ambx1@neo.rr.com> * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
* *
*/ */
...@@ -20,551 +21,341 @@ ...@@ -20,551 +21,341 @@
#include <linux/pnp.h> #include <linux/pnp.h>
#include "base.h" #include "base.h"
DECLARE_MUTEX(pnp_res_mutex);
int pnp_max_moves = 4; static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
static int pnp_next_port(struct pnp_dev * dev, int idx)
{ {
struct pnp_port *port;
unsigned long *start, *end, *flags; unsigned long *start, *end, *flags;
if (!dev || idx < 0 || idx >= PNP_MAX_PORT)
return 0; if (!dev || !rule)
port = dev->rule->port[idx]; return -EINVAL;
if (!port)
if (idx >= PNP_MAX_PORT) {
pnp_err("More than 4 ports is incompatible with pnp specifications.");
/* pretend we were successful so at least the manager won't try again */
return 1;
}
/* check if this resource has been manually set, if so skip */
if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO))
return 1; return 1;
start = &dev->res.port_resource[idx].start; start = &dev->res.port_resource[idx].start;
end = &dev->res.port_resource[idx].end; end = &dev->res.port_resource[idx].end;
flags = &dev->res.port_resource[idx].flags; flags = &dev->res.port_resource[idx].flags;
/* set the initial values if this is the first time */ /* set the initial values */
if (*start == 0) { *start = rule->min;
*start = port->min; *end = *start + rule->size - 1;
*end = *start + port->size - 1; *flags = *flags | rule->flags | IORESOURCE_IO;
*flags = port->flags | IORESOURCE_IO;
if (!pnp_check_port(dev, idx))
return 1;
}
/* run through until pnp_check_port is happy */ /* run through until pnp_check_port is happy */
do { while (!pnp_check_port(dev, idx)) {
*start += port->align; *start += rule->align;
*end = *start + port->size - 1; *end = *start + rule->size - 1;
if (*start > port->max || !port->align) if (*start > rule->max || !rule->align)
return 0; return 0;
} while (pnp_check_port(dev, idx)); }
return 1; return 1;
} }
static int pnp_next_mem(struct pnp_dev * dev, int idx) static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
{ {
struct pnp_mem *mem;
unsigned long *start, *end, *flags; unsigned long *start, *end, *flags;
if (!dev || idx < 0 || idx >= PNP_MAX_MEM)
return 0; if (!dev || !rule)
mem = dev->rule->mem[idx]; return -EINVAL;
if (!mem)
if (idx >= PNP_MAX_MEM) {
pnp_err("More than 8 mems is incompatible with pnp specifications.");
/* pretend we were successful so at least the manager won't try again */
return 1;
}
/* check if this resource has been manually set, if so skip */
if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO))
return 1; return 1;
start = &dev->res.mem_resource[idx].start; start = &dev->res.mem_resource[idx].start;
end = &dev->res.mem_resource[idx].end; end = &dev->res.mem_resource[idx].end;
flags = &dev->res.mem_resource[idx].flags; flags = &dev->res.mem_resource[idx].flags;
/* set the initial values if this is the first time */ /* set the initial values */
if (*start == 0) { *start = rule->min;
*start = mem->min; *end = *start + rule->size -1;
*end = *start + mem->size -1; *flags = *flags | rule->flags | IORESOURCE_MEM;
*flags = mem->flags | IORESOURCE_MEM;
if (!(mem->flags & IORESOURCE_MEM_WRITEABLE)) /* convert pnp flags to standard Linux flags */
if (!(rule->flags & IORESOURCE_MEM_WRITEABLE))
*flags |= IORESOURCE_READONLY; *flags |= IORESOURCE_READONLY;
if (mem->flags & IORESOURCE_MEM_CACHEABLE) if (rule->flags & IORESOURCE_MEM_CACHEABLE)
*flags |= IORESOURCE_CACHEABLE; *flags |= IORESOURCE_CACHEABLE;
if (mem->flags & IORESOURCE_MEM_RANGELENGTH) if (rule->flags & IORESOURCE_MEM_RANGELENGTH)
*flags |= IORESOURCE_RANGELENGTH; *flags |= IORESOURCE_RANGELENGTH;
if (mem->flags & IORESOURCE_MEM_SHADOWABLE) if (rule->flags & IORESOURCE_MEM_SHADOWABLE)
*flags |= IORESOURCE_SHADOWABLE; *flags |= IORESOURCE_SHADOWABLE;
if (!pnp_check_mem(dev, idx))
return 1;
}
/* run through until pnp_check_mem is happy */ /* run through until pnp_check_mem is happy */
do { while (!pnp_check_mem(dev, idx)) {
*start += mem->align; *start += rule->align;
*end = *start + mem->size - 1; *end = *start + rule->size - 1;
if (*start > mem->max || !mem->align) if (*start > rule->max || !rule->align)
return 0; return 0;
} while (pnp_check_mem(dev, idx)); }
return 1; return 1;
} }
static int pnp_next_irq(struct pnp_dev * dev, int idx) static int pnp_assign_irq(struct pnp_dev * dev, struct pnp_irq *rule, int idx)
{ {
struct pnp_irq *irq;
unsigned long *start, *end, *flags; unsigned long *start, *end, *flags;
int i, mask; int i;
if (!dev || idx < 0 || idx >= PNP_MAX_IRQ)
return 0;
irq = dev->rule->irq[idx];
if (!irq)
return 1;
start = &dev->res.irq_resource[idx].start; /* IRQ priority: this table is good for i386 */
end = &dev->res.irq_resource[idx].end; static unsigned short xtab[16] = {
flags = &dev->res.irq_resource[idx].flags; 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
};
/* set the initial values if this is the first time */ if (!dev || !rule)
if (*start == -1) {
*start = *end = 0;
*flags = irq->flags | IORESOURCE_IRQ;
if (!pnp_check_irq(dev, idx))
return 1;
}
mask = irq->map;
for (i = *start + 1; i < 16; i++)
{
if(mask>>i & 0x01) {
*start = *end = i;
if(!pnp_check_irq(dev, idx))
return 1;
}
}
return 0;
}
static int pnp_next_dma(struct pnp_dev * dev, int idx)
{
struct pnp_dma *dma;
unsigned long *start, *end, *flags;
int i, mask;
if (!dev || idx < 0 || idx >= PNP_MAX_DMA)
return -EINVAL; return -EINVAL;
dma = dev->rule->dma[idx];
if (!dma)
return 1;
start = &dev->res.dma_resource[idx].start; if (idx >= PNP_MAX_IRQ) {
end = &dev->res.dma_resource[idx].end; pnp_err("More than 2 irqs is incompatible with pnp specifications.");
flags = &dev->res.dma_resource[idx].flags; /* pretend we were successful so at least the manager won't try again */
/* set the initial values if this is the first time */
if (*start == -1) {
*start = *end = 0;
*flags = dma->flags | IORESOURCE_DMA;
if (!pnp_check_dma(dev, idx))
return 1; return 1;
} }
mask = dma->map; /* check if this resource has been manually set, if so skip */
for (i = *start + 1; i < 8; i++) if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO))
{
if(mask>>i & 0x01) {
*start = *end = i;
if(!pnp_check_dma(dev, idx))
return 1; return 1;
}
}
return 0;
}
static int pnp_next_rule(struct pnp_dev *dev)
{
int depnum = dev->rule->depnum;
int max = pnp_get_max_depnum(dev);
int priority = PNP_RES_PRIORITY_PREFERRED;
if (depnum < 0)
return 0;
if (max == 0) { start = &dev->res.irq_resource[idx].start;
if (pnp_generate_rule(dev, 0, dev->rule)) { end = &dev->res.irq_resource[idx].end;
dev->rule->depnum = -1; flags = &dev->res.irq_resource[idx].flags;
return 1;
}
}
if(depnum > 0) { /* set the initial values */
struct pnp_resources * res = pnp_find_resources(dev, depnum); *flags = *flags | rule->flags | IORESOURCE_IRQ;
priority = res->priority;
}
for (; priority <= PNP_RES_PRIORITY_FUNCTIONAL; priority++, depnum = 0) { for (i = 0; i < 16; i++) {
depnum += 1; if(rule->map & (1<<xtab[i])) {
for (; depnum <= max; depnum++) { *start = *end = xtab[i];
struct pnp_resources * res = pnp_find_resources(dev, depnum); if(pnp_check_irq(dev, idx))
if (res->priority == priority) {
if(pnp_generate_rule(dev, depnum, dev->rule)) {
dev->rule->depnum = depnum;
return 1; return 1;
} }
} }
}
}
return 0; return 0;
} }
struct pnp_change { static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
struct list_head change_list;
struct list_head changes;
struct pnp_resource_table res_bak;
struct pnp_rule_table rule_bak;
struct pnp_dev * dev;
};
static void pnp_free_changes(struct pnp_change * parent)
{
struct list_head * pos, * temp;
list_for_each_safe(pos, temp, &parent->changes) {
struct pnp_change * change = list_entry(pos, struct pnp_change, change_list);
list_del(&change->change_list);
kfree(change);
}
}
static void pnp_undo_changes(struct pnp_change * parent)
{
struct list_head * pos, * temp;
list_for_each_safe(pos, temp, &parent->changes) {
struct pnp_change * change = list_entry(pos, struct pnp_change, change_list);
*change->dev->rule = change->rule_bak;
change->dev->res = change->res_bak;
list_del(&change->change_list);
kfree(change);
}
}
static struct pnp_change * pnp_add_change(struct pnp_change * parent, struct pnp_dev * dev)
{
struct pnp_change * change = pnp_alloc(sizeof(struct pnp_change));
if (!change)
return NULL;
change->res_bak = dev->res;
change->rule_bak = *dev->rule;
change->dev = dev;
INIT_LIST_HEAD(&change->changes);
if (parent)
list_add(&change->change_list, &parent->changes);
return change;
}
static void pnp_commit_changes(struct pnp_change * parent, struct pnp_change * change)
{
/* check if it's the root change */
if (!parent)
return;
if (!list_empty(&change->changes))
list_splice_init(&change->changes, &parent->changes);
}
static int pnp_next_config(struct pnp_dev * dev, int move, struct pnp_change * parent);
static int pnp_next_request(struct pnp_dev * dev, int move, struct pnp_change * parent, struct pnp_change * change)
{ {
unsigned long *start, *end, *flags;
int i; int i;
struct pnp_dev * cdev;
for (i = 0; i < PNP_MAX_PORT; i++) { /* DMA priority: this table is good for i386 */
if (dev->res.port_resource[i].start == 0 static unsigned short xtab[8] = {
|| pnp_check_port_conflicts(dev,i,SEARCH_WARM)) { 1, 3, 5, 6, 7, 0, 2, 4
if (!pnp_next_port(dev,i)) };
return 0;
}
do {
cdev = pnp_check_port_conflicts(dev,i,SEARCH_COLD);
if (cdev && (!move || !pnp_next_config(cdev,move,change))) {
pnp_undo_changes(change);
if (!pnp_next_port(dev,i))
return 0;
}
} while (cdev);
pnp_commit_changes(parent, change);
}
for (i = 0; i < PNP_MAX_MEM; i++) {
if (dev->res.mem_resource[i].start == 0
|| pnp_check_mem_conflicts(dev,i,SEARCH_WARM)) {
if (!pnp_next_mem(dev,i))
return 0;
}
do {
cdev = pnp_check_mem_conflicts(dev,i,SEARCH_COLD);
if (cdev && (!move || !pnp_next_config(cdev,move,change))) {
pnp_undo_changes(change);
if (!pnp_next_mem(dev,i))
return 0;
}
} while (cdev);
pnp_commit_changes(parent, change);
}
for (i = 0; i < PNP_MAX_IRQ; i++) {
if (dev->res.irq_resource[i].start == -1
|| pnp_check_irq_conflicts(dev,i,SEARCH_WARM)) {
if (!pnp_next_irq(dev,i))
return 0;
}
do {
cdev = pnp_check_irq_conflicts(dev,i,SEARCH_COLD);
if (cdev && (!move || !pnp_next_config(cdev,move,change))) {
pnp_undo_changes(change);
if (!pnp_next_irq(dev,i))
return 0;
}
} while (cdev);
pnp_commit_changes(parent, change);
}
for (i = 0; i < PNP_MAX_DMA; i++) {
if (dev->res.dma_resource[i].start == -1
|| pnp_check_dma_conflicts(dev,i,SEARCH_WARM)) {
if (!pnp_next_dma(dev,i))
return 0;
}
do {
cdev = pnp_check_dma_conflicts(dev,i,SEARCH_COLD);
if (cdev && (!move || !pnp_next_config(cdev,move,change))) {
pnp_undo_changes(change);
if (!pnp_next_dma(dev,i))
return 0;
}
} while (cdev);
pnp_commit_changes(parent, change);
}
return 1;
}
static int pnp_next_config(struct pnp_dev * dev, int move, struct pnp_change * parent) if (!dev || !rule)
{ return -EINVAL;
struct pnp_change * change;
move--;
if (!dev->rule)
return 0;
change = pnp_add_change(parent,dev);
if (!change)
return 0;
if (!pnp_can_configure(dev))
goto fail;
if (!dev->rule->depnum) {
if (!pnp_next_rule(dev))
goto fail;
}
while (!pnp_next_request(dev, move, parent, change)) {
if(!pnp_next_rule(dev))
goto fail;
pnp_init_resource_table(&dev->res);
}
if (!parent) {
pnp_free_changes(change);
kfree(change);
}
return 1;
fail:
if (!parent)
kfree(change);
return 0;
}
/* this advanced algorithm will shuffle other configs to make room and ensure that the most possible devices have configs */ if (idx >= PNP_MAX_DMA) {
static int pnp_advanced_config(struct pnp_dev * dev) pnp_err("More than 2 dmas is incompatible with pnp specifications.");
{ /* pretend we were successful so at least the manager won't try again */
int move;
/* if the device cannot be configured skip it */
if (!pnp_can_configure(dev))
return 1; return 1;
if (!dev->rule) {
dev->rule = pnp_alloc(sizeof(struct pnp_rule_table));
if (!dev->rule)
return -ENOMEM;
} }
spin_lock(&pnp_lock); /* check if this resource has been manually set, if so skip */
for (move = 1; move <= pnp_max_moves; move++) { if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO))
dev->rule->depnum = 0;
pnp_init_resource_table(&dev->res);
if (pnp_next_config(dev,move,NULL)) {
spin_unlock(&pnp_lock);
return 1; return 1;
}
}
pnp_init_resource_table(&dev->res); start = &dev->res.dma_resource[idx].start;
dev->rule->depnum = 0; end = &dev->res.dma_resource[idx].end;
spin_unlock(&pnp_lock); flags = &dev->res.dma_resource[idx].flags;
pnp_err("res: Unable to resolve resource conflicts for the device '%s', some devices may not be usable.", dev->dev.bus_id);
return 0;
}
int pnp_resolve_conflicts(struct pnp_dev *dev) /* set the initial values */
{ *flags = *flags | rule->flags | IORESOURCE_DMA;
int i;
struct pnp_dev * cdev;
for (i = 0; i < PNP_MAX_PORT; i++) for (i = 0; i < 8; i++) {
{ if(rule->map & (1<<xtab[i])) {
do { *start = *end = xtab[i];
cdev = pnp_check_port_conflicts(dev,i,SEARCH_COLD); if(pnp_check_dma(dev, idx))
if (cdev)
pnp_advanced_config(cdev);
} while (cdev);
}
for (i = 0; i < PNP_MAX_MEM; i++)
{
do {
cdev = pnp_check_mem_conflicts(dev,i,SEARCH_COLD);
if (cdev)
pnp_advanced_config(cdev);
} while (cdev);
}
for (i = 0; i < PNP_MAX_IRQ; i++)
{
do {
cdev = pnp_check_irq_conflicts(dev,i,SEARCH_COLD);
if (cdev)
pnp_advanced_config(cdev);
} while (cdev);
}
for (i = 0; i < PNP_MAX_DMA; i++)
{
do {
cdev = pnp_check_dma_conflicts(dev,i,SEARCH_COLD);
if (cdev)
pnp_advanced_config(cdev);
} while (cdev);
}
return 1; return 1;
}
/* this is a much faster algorithm but it may not leave resources for other devices to use */
static int pnp_simple_config(struct pnp_dev * dev)
{
int i;
spin_lock(&pnp_lock);
if (dev->active) {
spin_unlock(&pnp_lock);
return 1;
}
if (!dev->rule) {
dev->rule = pnp_alloc(sizeof(struct pnp_rule_table));
if (!dev->rule) {
spin_unlock(&pnp_lock);
return -ENOMEM;
}
}
dev->rule->depnum = 0;
pnp_init_resource_table(&dev->res);
while (pnp_next_rule(dev)) {
for (i = 0; i < PNP_MAX_PORT; i++) {
if (!pnp_next_port(dev,i))
continue;
} }
for (i = 0; i < PNP_MAX_MEM; i++) {
if (!pnp_next_mem(dev,i))
continue;
}
for (i = 0; i < PNP_MAX_IRQ; i++) {
if (!pnp_next_irq(dev,i))
continue;
} }
for (i = 0; i < PNP_MAX_DMA; i++) {
if (!pnp_next_dma(dev,i))
continue;
}
goto done;
}
pnp_init_resource_table(&dev->res);
dev->rule->depnum = 0;
spin_unlock(&pnp_lock);
return 0; return 0;
done:
pnp_resolve_conflicts(dev); /* this is required or we will break the advanced configs */
return 1;
} }
static int pnp_compare_resources(struct pnp_resource_table * resa, struct pnp_resource_table * resb) /**
* pnp_init_resources - Resets a resource table to default values.
* @table: pointer to the desired resource table
*
*/
void pnp_init_resources(struct pnp_resource_table *table)
{ {
int idx; int idx;
down(&pnp_res_mutex);
for (idx = 0; idx < PNP_MAX_IRQ; idx++) { for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
if (resa->irq_resource[idx].start != resb->irq_resource[idx].start) table->irq_resource[idx].name = NULL;
return 1; table->irq_resource[idx].start = -1;
table->irq_resource[idx].end = -1;
table->irq_resource[idx].flags = IORESOURCE_AUTO;
} }
for (idx = 0; idx < PNP_MAX_DMA; idx++) { for (idx = 0; idx < PNP_MAX_DMA; idx++) {
if (resa->dma_resource[idx].start != resb->dma_resource[idx].start) table->dma_resource[idx].name = NULL;
return 1; table->dma_resource[idx].start = -1;
table->dma_resource[idx].end = -1;
table->dma_resource[idx].flags = IORESOURCE_AUTO;
} }
for (idx = 0; idx < PNP_MAX_PORT; idx++) { for (idx = 0; idx < PNP_MAX_PORT; idx++) {
if (resa->port_resource[idx].start != resb->port_resource[idx].start) table->port_resource[idx].name = NULL;
return 1; table->port_resource[idx].start = 0;
if (resa->port_resource[idx].end != resb->port_resource[idx].end) table->port_resource[idx].end = 0;
return 1; table->port_resource[idx].flags = IORESOURCE_AUTO;
} }
for (idx = 0; idx < PNP_MAX_MEM; idx++) { for (idx = 0; idx < PNP_MAX_MEM; idx++) {
if (resa->mem_resource[idx].start != resb->mem_resource[idx].start) table->mem_resource[idx].name = NULL;
return 1; table->mem_resource[idx].start = 0;
if (resa->mem_resource[idx].end != resb->mem_resource[idx].end) table->mem_resource[idx].end = 0;
return 1; table->mem_resource[idx].flags = IORESOURCE_AUTO;
} }
return 0; up(&pnp_res_mutex);
} }
/*
* PnP Device Resource Management
*/
/** /**
* pnp_auto_config_dev - determines the best possible resource configuration based on available information * pnp_clean_resources - clears resources that were not manually set
* @dev: pointer to the desired device * @res - the resources to clean
* *
*/ */
static void pnp_clean_resources(struct pnp_resource_table * res)
int pnp_auto_config_dev(struct pnp_dev *dev)
{
int error;
if(!dev)
return -EINVAL;
dev->config_mode = PNP_CONFIG_AUTO;
if(dev->active)
error = pnp_resolve_conflicts(dev);
else
error = pnp_advanced_config(dev);
return error;
}
static void pnp_process_manual_resources(struct pnp_resource_table * ctab, struct pnp_resource_table * ntab)
{ {
int idx; int idx;
for (idx = 0; idx < PNP_MAX_IRQ; idx++) { for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
if (ntab->irq_resource[idx].flags & IORESOURCE_AUTO) if (!(res->irq_resource[idx].flags & IORESOURCE_AUTO))
continue; continue;
ctab->irq_resource[idx].start = ntab->irq_resource[idx].start; res->irq_resource[idx].start = -1;
ctab->irq_resource[idx].end = ntab->irq_resource[idx].end; res->irq_resource[idx].end = -1;
ctab->irq_resource[idx].flags = ntab->irq_resource[idx].flags; res->irq_resource[idx].flags = IORESOURCE_AUTO;
} }
for (idx = 0; idx < PNP_MAX_DMA; idx++) { for (idx = 0; idx < PNP_MAX_DMA; idx++) {
if (ntab->dma_resource[idx].flags & IORESOURCE_AUTO) if (!(res->dma_resource[idx].flags & IORESOURCE_AUTO))
continue; continue;
ctab->dma_resource[idx].start = ntab->dma_resource[idx].start; res->dma_resource[idx].start = -1;
ctab->dma_resource[idx].end = ntab->dma_resource[idx].end; res->dma_resource[idx].end = -1;
ctab->dma_resource[idx].flags = ntab->dma_resource[idx].flags; res->dma_resource[idx].flags = IORESOURCE_AUTO;
} }
for (idx = 0; idx < PNP_MAX_PORT; idx++) { for (idx = 0; idx < PNP_MAX_PORT; idx++) {
if (ntab->port_resource[idx].flags & IORESOURCE_AUTO) if (!(res->port_resource[idx].flags & IORESOURCE_AUTO))
continue; continue;
ctab->port_resource[idx].start = ntab->port_resource[idx].start; res->port_resource[idx].start = 0;
ctab->port_resource[idx].end = ntab->port_resource[idx].end; res->port_resource[idx].end = 0;
ctab->port_resource[idx].flags = ntab->port_resource[idx].flags; res->port_resource[idx].flags = IORESOURCE_AUTO;
} }
for (idx = 0; idx < PNP_MAX_MEM; idx++) { for (idx = 0; idx < PNP_MAX_MEM; idx++) {
if (ntab->irq_resource[idx].flags & IORESOURCE_AUTO) if (!(res->mem_resource[idx].flags & IORESOURCE_AUTO))
continue; continue;
ctab->irq_resource[idx].start = ntab->mem_resource[idx].start; res->mem_resource[idx].start = 0;
ctab->irq_resource[idx].end = ntab->mem_resource[idx].end; res->mem_resource[idx].end = 0;
ctab->irq_resource[idx].flags = ntab->mem_resource[idx].flags; res->mem_resource[idx].flags = IORESOURCE_AUTO;
} }
} }
/**
* pnp_assign_resources - assigns resources to the device based on the specified dependent number
* @dev: pointer to the desired device
* @depnum: the dependent function number
*
* Only set depnum to 0 if the device does not have dependent options.
*/
int pnp_assign_resources(struct pnp_dev *dev, int depnum)
{
struct pnp_port *port;
struct pnp_mem *mem;
struct pnp_irq *irq;
struct pnp_dma *dma;
int nport = 0, nmem = 0, nirq = 0, ndma = 0;
if (!pnp_can_configure(dev))
return -ENODEV;
down(&pnp_res_mutex);
pnp_clean_resources(&dev->res); /* start with a fresh slate */
if (dev->independent) {
port = dev->independent->port;
mem = dev->independent->mem;
irq = dev->independent->irq;
dma = dev->independent->dma;
while (port) {
if (!pnp_assign_port(dev, port, nport))
goto fail;
nport++;
port = port->next;
}
while (mem) {
if (!pnp_assign_mem(dev, mem, nmem))
goto fail;
nmem++;
mem = mem->next;
}
while (irq) {
if (!pnp_assign_irq(dev, irq, nirq))
goto fail;
nirq++;
irq = irq->next;
}
while (dma) {
if (!pnp_assign_dma(dev, dma, ndma))
goto fail;
ndma++;
dma = dma->next;
}
}
if (depnum) {
struct pnp_option *dep;
int i;
for (i=1,dep=dev->dependent; i<depnum; i++, dep=dep->next)
if(!dep)
goto fail;
port =dep->port;
mem = dep->mem;
irq = dep->irq;
dma = dep->dma;
while (port) {
if (!pnp_assign_port(dev, port, nport))
goto fail;
nport++;
port = port->next;
}
while (mem) {
if (!pnp_assign_mem(dev, mem, nmem))
goto fail;
nmem++;
mem = mem->next;
}
while (irq) {
if (!pnp_assign_irq(dev, irq, nirq))
goto fail;
nirq++;
irq = irq->next;
}
while (dma) {
if (!pnp_assign_dma(dev, dma, ndma))
goto fail;
ndma++;
dma = dma->next;
}
} else if (dev->dependent)
goto fail;
up(&pnp_res_mutex);
return 1;
fail:
pnp_clean_resources(&dev->res);
up(&pnp_res_mutex);
return 0;
}
/** /**
* pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table
* @dev: pointer to the desired device * @dev: pointer to the desired device
...@@ -572,22 +363,21 @@ static void pnp_process_manual_resources(struct pnp_resource_table * ctab, struc ...@@ -572,22 +363,21 @@ static void pnp_process_manual_resources(struct pnp_resource_table * ctab, struc
* *
* This function can be used by drivers that want to manually set thier resources. * 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 pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table * res, int mode)
{ {
int i; int i;
struct pnp_resource_table * bak; struct pnp_resource_table * bak;
if (!dev || !res) if (!dev || !res)
return -EINVAL; return -EINVAL;
if (dev->active) if (!pnp_can_configure(dev))
return -EBUSY; return -ENODEV;
bak = pnp_alloc(sizeof(struct pnp_resource_table)); bak = pnp_alloc(sizeof(struct pnp_resource_table));
if (!bak) if (!bak)
return -ENOMEM; return -ENOMEM;
*bak = dev->res; *bak = dev->res;
spin_lock(&pnp_lock); down(&pnp_res_mutex);
pnp_process_manual_resources(&dev->res, res); dev->res = *res;
if (!(mode & PNP_CONFIG_FORCE)) { if (!(mode & PNP_CONFIG_FORCE)) {
for (i = 0; i < PNP_MAX_PORT; i++) { for (i = 0; i < PNP_MAX_PORT; i++) {
if(pnp_check_port(dev,i)) if(pnp_check_port(dev,i))
...@@ -606,27 +396,64 @@ int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table * res, ...@@ -606,27 +396,64 @@ int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table * res,
goto fail; goto fail;
} }
} }
dev->config_mode = PNP_CONFIG_MANUAL; up(&pnp_res_mutex);
spin_unlock(&pnp_lock);
pnp_resolve_conflicts(dev); pnp_auto_config_dev(dev);
kfree(bak); kfree(bak);
return 0; return 0;
fail: fail:
dev->res = *bak; dev->res = *bak;
spin_unlock(&pnp_lock); up(&pnp_res_mutex);
kfree(bak); kfree(bak);
return -EINVAL; return -EINVAL;
} }
/** /**
* pnp_activate_dev - activates a PnP device for use * pnp_auto_config_dev - automatically assigns resources to a device
* @dev: pointer to the desired device * @dev: pointer to the desired device
* *
* finds the best resource configuration and then informs the correct pnp protocol
*/ */
int pnp_auto_config_dev(struct pnp_dev *dev)
{
struct pnp_option *dep;
int i = 1;
if(!dev)
return -EINVAL;
if(!pnp_can_configure(dev)) {
pnp_info("Device %s does not support resource configuration.", dev->dev.bus_id);
return -ENODEV;
}
if (!dev->dependent) {
if (pnp_assign_resources(dev, 0))
return 1;
else
return 0;
}
dep = dev->dependent;
do {
if (pnp_assign_resources(dev, i))
return 1;
/* if this dependent resource failed, try the next one */
dep = dep->next;
i++;
} while (dep);
pnp_err("Unable to assign resources to device %s.", dev->dev.bus_id);
return 0;
}
/**
* pnp_activate_dev - activates a PnP device for use
* @dev: pointer to the desired device
*
* does not validate or set resources so be careful.
*/
int pnp_activate_dev(struct pnp_dev *dev) int pnp_activate_dev(struct pnp_dev *dev)
{ {
if (!dev) if (!dev)
...@@ -634,55 +461,25 @@ int pnp_activate_dev(struct pnp_dev *dev) ...@@ -634,55 +461,25 @@ int pnp_activate_dev(struct pnp_dev *dev)
if (dev->active) { if (dev->active) {
return 0; /* the device is already active */ return 0; /* the device is already active */
} }
/* If this condition is true, advanced configuration failed, we need to get this device up and running
* so we use the simple config engine which ignores cold conflicts, this of course may lead to new failures */
if (!pnp_is_active(dev)) {
if (!pnp_simple_config(dev)) {
pnp_err("res: Unable to resolve resource conflicts for the device '%s'.", dev->dev.bus_id);
goto fail;
}
}
spin_lock(&pnp_lock); /* we lock just in case the device is being configured during this call */ /* ensure resources are allocated */
dev->active = 1; if (!pnp_auto_config_dev(dev))
spin_unlock(&pnp_lock); /* once the device is claimed active we know it won't be configured so we can unlock */ return -EBUSY;
if (dev->config_mode & PNP_CONFIG_INVALID) {
pnp_info("res: Unable to activate the PnP device '%s' because its resource configuration is invalid.", dev->dev.bus_id);
goto fail;
}
if (dev->status != PNP_READY && dev->status != PNP_ATTACHED){
pnp_err("res: Activation failed because the PnP device '%s' is busy.", dev->dev.bus_id);
goto fail;
}
if (!pnp_can_write(dev)) { if (!pnp_can_write(dev)) {
pnp_info("res: Unable to activate the PnP device '%s' because this feature is not supported.", dev->dev.bus_id); pnp_info("Device %s does not supported activation.", dev->dev.bus_id);
goto fail; return -EINVAL;
} }
if (dev->protocol->set(dev, &dev->res)<0) { if (dev->protocol->set(dev, &dev->res)<0) {
pnp_err("res: The protocol '%s' reports that activating the PnP device '%s' has failed.", dev->protocol->name, dev->dev.bus_id); pnp_err("Failed to activate device %s.", dev->dev.bus_id);
goto fail; return -EIO;
}
if (pnp_can_read(dev)) {
struct pnp_resource_table * res = pnp_alloc(sizeof(struct pnp_resource_table));
if (!res)
goto fail;
dev->protocol->get(dev, res);
if (pnp_compare_resources(&dev->res, res)) /* if this happens we may be in big trouble but it's best just to continue */
pnp_err("res: The resources requested do not match those set for the PnP device '%s'.", dev->dev.bus_id);
kfree(res);
} else
dev->active = pnp_is_active(dev);
pnp_dbg("res: the device '%s' has been activated.", dev->dev.bus_id);
if (dev->rule) {
kfree(dev->rule);
dev->rule = NULL;
} }
return 0;
fail: dev->active = 1;
dev->active = 0; /* fixes incorrect active state */ pnp_info("Device %s activated.", dev->dev.bus_id);
return -EINVAL;
return 1;
} }
/** /**
...@@ -691,7 +488,6 @@ int pnp_activate_dev(struct pnp_dev *dev) ...@@ -691,7 +488,6 @@ int pnp_activate_dev(struct pnp_dev *dev)
* *
* inform the correct pnp protocol so that resources can be used by other devices * inform the correct pnp protocol so that resources can be used by other devices
*/ */
int pnp_disable_dev(struct pnp_dev *dev) int pnp_disable_dev(struct pnp_dev *dev)
{ {
if (!dev) if (!dev)
...@@ -699,21 +495,25 @@ int pnp_disable_dev(struct pnp_dev *dev) ...@@ -699,21 +495,25 @@ int pnp_disable_dev(struct pnp_dev *dev)
if (!dev->active) { if (!dev->active) {
return 0; /* the device is already disabled */ return 0; /* the device is already disabled */
} }
if (dev->status != PNP_READY){
pnp_info("res: Disable failed becuase the PnP device '%s' is busy.", dev->dev.bus_id);
return -EINVAL;
}
if (!pnp_can_disable(dev)) { if (!pnp_can_disable(dev)) {
pnp_info("res: Unable to disable the PnP device '%s' because this feature is not supported.", dev->dev.bus_id); pnp_info("Device %s does not supported disabling.", dev->dev.bus_id);
return -EINVAL; return -EINVAL;
} }
if (dev->protocol->disable(dev)<0) { if (dev->protocol->disable(dev)<0) {
pnp_err("res: The protocol '%s' reports that disabling the PnP device '%s' has failed.", dev->protocol->name, dev->dev.bus_id); pnp_err("Failed to disable device %s.", dev->dev.bus_id);
return -1; return -EIO;
} }
dev->active = 0; /* just in case the protocol doesn't do this */
pnp_dbg("res: the device '%s' has been disabled.", dev->dev.bus_id); dev->active = 0;
return 0; pnp_info("Device %s disabled.", dev->dev.bus_id);
/* release the resources so that other devices can use them */
down(&pnp_res_mutex);
pnp_clean_resources(&dev->res);
up(&pnp_res_mutex);
return 1;
} }
/** /**
...@@ -723,7 +523,6 @@ int pnp_disable_dev(struct pnp_dev *dev) ...@@ -723,7 +523,6 @@ int pnp_disable_dev(struct pnp_dev *dev)
* @size: size of region * @size: size of region
* *
*/ */
void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size) void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size)
{ {
if (resource == NULL) if (resource == NULL)
...@@ -734,19 +533,10 @@ void pnp_resource_change(struct resource *resource, unsigned long start, unsigne ...@@ -734,19 +533,10 @@ void pnp_resource_change(struct resource *resource, unsigned long start, unsigne
} }
EXPORT_SYMBOL(pnp_auto_config_dev); EXPORT_SYMBOL(pnp_assign_resources);
EXPORT_SYMBOL(pnp_manual_config_dev); EXPORT_SYMBOL(pnp_manual_config_dev);
EXPORT_SYMBOL(pnp_auto_config_dev);
EXPORT_SYMBOL(pnp_activate_dev); EXPORT_SYMBOL(pnp_activate_dev);
EXPORT_SYMBOL(pnp_disable_dev); EXPORT_SYMBOL(pnp_disable_dev);
EXPORT_SYMBOL(pnp_resource_change); EXPORT_SYMBOL(pnp_resource_change);
EXPORT_SYMBOL(pnp_init_resources);
/* format is: pnp_max_moves=num */
static int __init pnp_setup_max_moves(char *str)
{
get_option(&str,&pnp_max_moves);
return 1;
}
__setup("pnp_max_moves=", pnp_setup_max_moves);
...@@ -935,6 +935,10 @@ static int insert_device(struct pnp_dev *dev, struct pnp_bios_node * node) ...@@ -935,6 +935,10 @@ static int insert_device(struct pnp_dev *dev, struct pnp_bios_node * node)
dev->capabilities |= PNP_REMOVABLE; dev->capabilities |= PNP_REMOVABLE;
dev->protocol = &pnpbios_protocol; dev->protocol = &pnpbios_protocol;
/* clear out the damaged flags */
if (!dev->active)
pnp_init_resources(&dev->res);
pnp_add_device(dev); pnp_add_device(dev);
pnpbios_interface_attach_device(node); pnpbios_interface_attach_device(node);
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
static void quirk_awe32_resources(struct pnp_dev *dev) static void quirk_awe32_resources(struct pnp_dev *dev)
{ {
struct pnp_port *port, *port2, *port3; struct pnp_port *port, *port2, *port3;
struct pnp_resources *res = dev->possible->dep; struct pnp_option *res = dev->dependent;
/* /*
* Unfortunately the isapnp_add_port_resource is too tightly bound * Unfortunately the isapnp_add_port_resource is too tightly bound
...@@ -38,7 +38,7 @@ static void quirk_awe32_resources(struct pnp_dev *dev) ...@@ -38,7 +38,7 @@ static void quirk_awe32_resources(struct pnp_dev *dev)
* two extra ports (at offset 0x400 and 0x800 from the one given) by * two extra ports (at offset 0x400 and 0x800 from the one given) by
* hand. * hand.
*/ */
for ( ; res ; res = res->dep ) { for ( ; res ; res = res->next ) {
port2 = pnp_alloc(sizeof(struct pnp_port)); port2 = pnp_alloc(sizeof(struct pnp_port));
if (!port2) if (!port2)
return; return;
...@@ -62,9 +62,9 @@ static void quirk_awe32_resources(struct pnp_dev *dev) ...@@ -62,9 +62,9 @@ static void quirk_awe32_resources(struct pnp_dev *dev)
static void quirk_cmi8330_resources(struct pnp_dev *dev) static void quirk_cmi8330_resources(struct pnp_dev *dev)
{ {
struct pnp_resources *res = dev->possible->dep; struct pnp_option *res = dev->dependent;
for ( ; res ; res = res->dep ) { for ( ; res ; res = res->next ) {
struct pnp_irq *irq; struct pnp_irq *irq;
struct pnp_dma *dma; struct pnp_dma *dma;
...@@ -82,7 +82,7 @@ static void quirk_cmi8330_resources(struct pnp_dev *dev) ...@@ -82,7 +82,7 @@ static void quirk_cmi8330_resources(struct pnp_dev *dev)
static void quirk_sb16audio_resources(struct pnp_dev *dev) static void quirk_sb16audio_resources(struct pnp_dev *dev)
{ {
struct pnp_port *port; struct pnp_port *port;
struct pnp_resources *res = dev->possible->dep; struct pnp_option *res = dev->dependent;
int changed = 0; int changed = 0;
/* /*
...@@ -91,7 +91,7 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev) ...@@ -91,7 +91,7 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev)
* auto-configured. * auto-configured.
*/ */
for( ; res ; res = res->dep ) { for( ; res ; res = res->next ) {
port = res->port; port = res->port;
if(!port) if(!port)
continue; continue;
...@@ -118,11 +118,11 @@ static void quirk_opl3sax_resources(struct pnp_dev *dev) ...@@ -118,11 +118,11 @@ static void quirk_opl3sax_resources(struct pnp_dev *dev)
* doesn't allow a DMA channel of 0, afflicted card is an * doesn't allow a DMA channel of 0, afflicted card is an
* OPL3Sax where x=4. * OPL3Sax where x=4.
*/ */
struct pnp_resources *res; struct pnp_option *res;
int max; int max;
res = dev->possible; res = dev->dependent;
max = 0; max = 0;
for (res = res->dep; res; res = res->dep) { for (; res; res = res->next) {
if (res->dma->map > max) if (res->dma->map > max)
max = res->dma->map; max = res->dma->map;
} }
......
...@@ -10,18 +10,19 @@ ...@@ -10,18 +10,19 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <linux/pci.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/pnp.h> #include <linux/pnp.h>
#include "base.h" #include "base.h"
int pnp_allow_dma0 = -1; /* allow dma 0 during auto activation: -1=off (:default), 0=off (set by user), 1=on */ int pnp_allow_dma0 = -1; /* allow dma 0 during auto activation:
* -1=off (:default), 0=off (set by user), 1=on */
int pnp_skip_pci_scan; /* skip PCI resource scanning */ int pnp_skip_pci_scan; /* skip PCI resource scanning */
int pnp_reserve_irq[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some IRQ */ int pnp_reserve_irq[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some IRQ */
int pnp_reserve_dma[8] = { [0 ... 7] = -1 }; /* reserve (don't use) some DMA */ int pnp_reserve_dma[8] = { [0 ... 7] = -1 }; /* reserve (don't use) some DMA */
...@@ -30,88 +31,75 @@ int pnp_reserve_mem[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some memor ...@@ -30,88 +31,75 @@ int pnp_reserve_mem[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some memor
/* /*
* possible resource registration * option registration
*/ */
struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent) static struct pnp_option * pnp_build_option(int priority)
{ {
struct pnp_resources *res, *ptr, *ptra; struct pnp_option *option = pnp_alloc(sizeof(struct pnp_option));
res = pnp_alloc(sizeof(struct pnp_resources)); /* check if pnp_alloc ran out of memory */
if (!res) if (!option)
return NULL; return NULL;
ptr = dev->possible;
if (ptr) { /* add to another list */ option->priority = priority & 0xff;
ptra = ptr->dep; /* make sure the priority is valid */
while (ptra && ptra->dep) if (option->priority > PNP_RES_PRIORITY_FUNCTIONAL)
ptra = ptra->dep; option->priority = PNP_RES_PRIORITY_INVALID;
if (!ptra)
ptr->dep = res; return option;
else
ptra->dep = res;
} else
dev->possible = res;
if (dependent) {
res->priority = dependent & 0xff;
if (res->priority > PNP_RES_PRIORITY_FUNCTIONAL)
res->priority = PNP_RES_PRIORITY_INVALID;
} else
res->priority = PNP_RES_PRIORITY_PREFERRED;
return res;
} }
struct pnp_resources * pnp_find_resources(struct pnp_dev *dev, int depnum) struct pnp_option * pnp_register_independent_option(struct pnp_dev *dev)
{ {
int i; struct pnp_option *option;
struct pnp_resources *res;
if (!dev) if (!dev)
return NULL; return NULL;
res = dev->possible;
if (!res) option = pnp_build_option(PNP_RES_PRIORITY_PREFERRED);
return NULL;
for (i = 0; i < depnum; i++) /* this should never happen but if it does we'll try to continue */
{ if (dev->independent)
if (res->dep) pnp_err("independent resource already registered");
res = res->dep; dev->independent = option;
else return option;
return NULL;
}
return res;
} }
int pnp_get_max_depnum(struct pnp_dev *dev) struct pnp_option * pnp_register_dependent_option(struct pnp_dev *dev, int priority)
{ {
int num = 0; struct pnp_option *option;
struct pnp_resources *res;
if (!dev) if (!dev)
return -EINVAL; return NULL;
res = dev->possible;
if (!res) option = pnp_build_option(priority);
return -EINVAL;
while (res->dep){ if (dev->dependent) {
res = res->dep; struct pnp_option *parent = dev->dependent;
num++; while (parent->next)
} parent = parent->next;
return num; parent->next = option;
} else
dev->dependent = option;
return option;
} }
int pnp_add_irq_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data)
{ {
int i; int i;
struct pnp_resources *res;
struct pnp_irq *ptr; struct pnp_irq *ptr;
res = pnp_find_resources(dev,depnum); if (!option)
if (!res)
return -EINVAL; return -EINVAL;
if (!data) if (!data)
return -EINVAL; return -EINVAL;
ptr = res->irq;
ptr = option->irq;
while (ptr && ptr->next) while (ptr && ptr->next)
ptr = ptr->next; ptr = ptr->next;
if (ptr) if (ptr)
ptr->next = data; ptr->next = data;
else else
res->irq = data; option->irq = data;
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
for (i=0; i<16; i++) for (i=0; i<16; i++)
if (data->map & (1<<i)) if (data->map & (1<<i))
...@@ -120,60 +108,59 @@ int pnp_add_irq_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) ...@@ -120,60 +108,59 @@ int pnp_add_irq_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data)
return 0; return 0;
} }
int pnp_add_dma_resource(struct pnp_dev *dev, int depnum, struct pnp_dma *data) int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data)
{ {
struct pnp_resources *res;
struct pnp_dma *ptr; struct pnp_dma *ptr;
res = pnp_find_resources(dev,depnum); if (!option)
if (!res)
return -EINVAL; return -EINVAL;
if (!data) if (!data)
return -EINVAL; return -EINVAL;
ptr = res->dma;
ptr = option->dma;
while (ptr && ptr->next) while (ptr && ptr->next)
ptr = ptr->next; ptr = ptr->next;
if (ptr) if (ptr)
ptr->next = data; ptr->next = data;
else else
res->dma = data; option->dma = data;
return 0; return 0;
} }
int pnp_add_port_resource(struct pnp_dev *dev, int depnum, struct pnp_port *data) int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data)
{ {
struct pnp_resources *res;
struct pnp_port *ptr; struct pnp_port *ptr;
res = pnp_find_resources(dev,depnum); if (!option)
if (!res)
return -EINVAL; return -EINVAL;
if (!data) if (!data)
return -EINVAL; return -EINVAL;
ptr = res->port;
ptr = option->port;
while (ptr && ptr->next) while (ptr && ptr->next)
ptr = ptr->next; ptr = ptr->next;
if (ptr) if (ptr)
ptr->next = data; ptr->next = data;
else else
res->port = data; option->port = data;
return 0; return 0;
} }
int pnp_add_mem_resource(struct pnp_dev *dev, int depnum, struct pnp_mem *data) int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data)
{ {
struct pnp_resources *res;
struct pnp_mem *ptr; struct pnp_mem *ptr;
res = pnp_find_resources(dev,depnum); if (!option)
if (!res)
return -EINVAL; return -EINVAL;
if (!data) if (!data)
return -EINVAL; return -EINVAL;
ptr = res->mem;
ptr = option->mem;
while (ptr && ptr->next) while (ptr && ptr->next)
ptr = ptr->next; ptr = ptr->next;
if (ptr) if (ptr)
ptr->next = data; ptr->next = data;
else else
res->mem = data; option->mem = data;
return 0; return 0;
} }
...@@ -221,18 +208,18 @@ static void pnp_free_mem(struct pnp_mem *mem) ...@@ -221,18 +208,18 @@ static void pnp_free_mem(struct pnp_mem *mem)
} }
} }
void pnp_free_resources(struct pnp_resources *resources) void pnp_free_option(struct pnp_option *option)
{ {
struct pnp_resources *next; struct pnp_option *next;
while (resources) { while (option) {
next = resources->dep; next = option->next;
pnp_free_port(resources->port); pnp_free_port(option->port);
pnp_free_irq(resources->irq); pnp_free_irq(option->irq);
pnp_free_dma(resources->dma); pnp_free_dma(option->dma);
pnp_free_mem(resources->mem); pnp_free_mem(option->mem);
kfree(resources); kfree(option);
resources = next; option = next;
} }
} }
...@@ -253,50 +240,23 @@ void pnp_free_resources(struct pnp_resources *resources) ...@@ -253,50 +240,23 @@ void pnp_free_resources(struct pnp_resources *resources)
(*(enda) >= *(startb) && *(enda) <= *(endb)) || \ (*(enda) >= *(startb) && *(enda) <= *(endb)) || \
(*(starta) < *(startb) && *(enda) > *(endb))) (*(starta) < *(startb) && *(enda) > *(endb)))
struct pnp_dev * pnp_check_port_conflicts(struct pnp_dev * dev, int idx, int mode)
{
int tmp;
unsigned long *port, *end, *tport, *tend;
struct pnp_dev *tdev;
port = &dev->res.port_resource[idx].start;
end = &dev->res.port_resource[idx].end;
/* if the resource doesn't exist, don't complain about it */
if (dev->res.port_resource[idx].start == 0)
return NULL;
/* check for cold conflicts */
pnp_for_each_dev(tdev) {
/* Is the device configurable? */
if (tdev == dev || (mode ? !tdev->active : tdev->active))
continue;
for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {
if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) {
tport = &tdev->res.port_resource[tmp].start;
tend = &tdev->res.port_resource[tmp].end;
if (ranged_conflict(port,end,tport,tend))
return tdev;
}
}
}
return NULL;
}
int pnp_check_port(struct pnp_dev * dev, int idx) int pnp_check_port(struct pnp_dev * dev, int idx)
{ {
int tmp; int tmp;
struct pnp_dev *tdev;
unsigned long *port, *end, *tport, *tend; unsigned long *port, *end, *tport, *tend;
port = &dev->res.port_resource[idx].start; port = &dev->res.port_resource[idx].start;
end = &dev->res.port_resource[idx].end; end = &dev->res.port_resource[idx].end;
/* if the resource doesn't exist, don't complain about it */ /* if the resource doesn't exist, don't complain about it */
if (dev->res.port_resource[idx].start == 0) if (dev->res.port_resource[idx].start == 0)
return 0; return 1;
/* check if the resource is already in use, skip if the device is active because it itself may be in use */ /* check if the resource is already in use, skip if the
* device is active because it itself may be in use */
if(!dev->active) { if(!dev->active) {
if (check_region(*port, length(port,end))) if (__check_region(&ioport_resource, *port, length(port,end)))
return CONFLICT_TYPE_IN_USE; return 0;
} }
/* check if the resource is reserved */ /* check if the resource is reserved */
...@@ -304,7 +264,7 @@ int pnp_check_port(struct pnp_dev * dev, int idx) ...@@ -304,7 +264,7 @@ int pnp_check_port(struct pnp_dev * dev, int idx)
int rport = pnp_reserve_io[tmp << 1]; int rport = pnp_reserve_io[tmp << 1];
int rend = pnp_reserve_io[(tmp << 1) + 1] + rport - 1; int rend = pnp_reserve_io[(tmp << 1) + 1] + rport - 1;
if (ranged_conflict(port,end,&rport,&rend)) if (ranged_conflict(port,end,&rport,&rend))
return CONFLICT_TYPE_RESERVED; return 0;
} }
/* check for internal conflicts */ /* check for internal conflicts */
...@@ -313,61 +273,44 @@ int pnp_check_port(struct pnp_dev * dev, int idx) ...@@ -313,61 +273,44 @@ int pnp_check_port(struct pnp_dev * dev, int idx)
tport = &dev->res.port_resource[tmp].start; tport = &dev->res.port_resource[tmp].start;
tend = &dev->res.port_resource[tmp].end; tend = &dev->res.port_resource[tmp].end;
if (ranged_conflict(port,end,tport,tend)) if (ranged_conflict(port,end,tport,tend))
return CONFLICT_TYPE_INTERNAL; return 0;
} }
} }
/* check for warm conflicts */ /* check for conflicts with other pnp devices */
if (pnp_check_port_conflicts(dev, idx, SEARCH_WARM))
return CONFLICT_TYPE_PNP_WARM;
return 0;
}
struct pnp_dev * pnp_check_mem_conflicts(struct pnp_dev * dev, int idx, int mode)
{
int tmp;
unsigned long *addr, *end, *taddr, *tend;
struct pnp_dev *tdev;
addr = &dev->res.mem_resource[idx].start;
end = &dev->res.mem_resource[idx].end;
/* if the resource doesn't exist, don't complain about it */
if (dev->res.mem_resource[idx].start == 0)
return NULL;
/* check for cold conflicts */
pnp_for_each_dev(tdev) { pnp_for_each_dev(tdev) {
/* Is the device configurable? */ if (tdev == dev)
if (tdev == dev || (mode ? !tdev->active : tdev->active))
continue; continue;
for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) { for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {
if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) { if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) {
taddr = &tdev->res.mem_resource[tmp].start; tport = &tdev->res.port_resource[tmp].start;
tend = &tdev->res.mem_resource[tmp].end; tend = &tdev->res.port_resource[tmp].end;
if (ranged_conflict(addr,end,taddr,tend)) if (ranged_conflict(port,end,tport,tend))
return tdev; return 0;
} }
} }
} }
return NULL;
return 1;
} }
int pnp_check_mem(struct pnp_dev * dev, int idx) int pnp_check_mem(struct pnp_dev * dev, int idx)
{ {
int tmp; int tmp;
struct pnp_dev *tdev;
unsigned long *addr, *end, *taddr, *tend; unsigned long *addr, *end, *taddr, *tend;
addr = &dev->res.mem_resource[idx].start; addr = &dev->res.mem_resource[idx].start;
end = &dev->res.mem_resource[idx].end; end = &dev->res.mem_resource[idx].end;
/* if the resource doesn't exist, don't complain about it */ /* if the resource doesn't exist, don't complain about it */
if (dev->res.mem_resource[idx].start == 0) if (dev->res.mem_resource[idx].start == 0)
return 0; return 1;
/* check if the resource is already in use, skip if the device is active because it itself may be in use */ /* check if the resource is already in use, skip if the
* device is active because it itself may be in use */
if(!dev->active) { if(!dev->active) {
if (__check_region(&iomem_resource, *addr, length(addr,end))) if (check_mem_region(*addr, length(addr,end)))
return CONFLICT_TYPE_IN_USE; return 0;
} }
/* check if the resource is reserved */ /* check if the resource is reserved */
...@@ -375,7 +318,7 @@ int pnp_check_mem(struct pnp_dev * dev, int idx) ...@@ -375,7 +318,7 @@ int pnp_check_mem(struct pnp_dev * dev, int idx)
int raddr = pnp_reserve_mem[tmp << 1]; int raddr = pnp_reserve_mem[tmp << 1];
int rend = pnp_reserve_mem[(tmp << 1) + 1] + raddr - 1; int rend = pnp_reserve_mem[(tmp << 1) + 1] + raddr - 1;
if (ranged_conflict(addr,end,&raddr,&rend)) if (ranged_conflict(addr,end,&raddr,&rend))
return CONFLICT_TYPE_RESERVED; return 0;
} }
/* check for internal conflicts */ /* check for internal conflicts */
...@@ -384,40 +327,25 @@ int pnp_check_mem(struct pnp_dev * dev, int idx) ...@@ -384,40 +327,25 @@ int pnp_check_mem(struct pnp_dev * dev, int idx)
taddr = &dev->res.mem_resource[tmp].start; taddr = &dev->res.mem_resource[tmp].start;
tend = &dev->res.mem_resource[tmp].end; tend = &dev->res.mem_resource[tmp].end;
if (ranged_conflict(addr,end,taddr,tend)) if (ranged_conflict(addr,end,taddr,tend))
return CONFLICT_TYPE_INTERNAL; return 0;
} }
} }
/* check for warm conflicts */ /* check for conflicts with other pnp devices */
if (pnp_check_mem_conflicts(dev, idx, SEARCH_WARM))
return CONFLICT_TYPE_PNP_WARM;
return 0;
}
struct pnp_dev * pnp_check_irq_conflicts(struct pnp_dev * dev, int idx, int mode)
{
int tmp;
struct pnp_dev * tdev;
unsigned long * irq = &dev->res.irq_resource[idx].start;
/* if the resource doesn't exist, don't complain about it */
if (dev->res.irq_resource[idx].start == -1)
return NULL;
/* check for cold conflicts */
pnp_for_each_dev(tdev) { pnp_for_each_dev(tdev) {
/* Is the device configurable? */ if (tdev == dev)
if (tdev == dev || (mode ? !tdev->active : tdev->active))
continue; continue;
for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) { for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) {
if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) { if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) {
if ((tdev->res.irq_resource[tmp].start == *irq)) taddr = &tdev->res.mem_resource[tmp].start;
return tdev; tend = &tdev->res.mem_resource[tmp].end;
if (ranged_conflict(addr,end,taddr,tend))
return 0;
} }
} }
} }
return NULL;
return 1;
} }
static irqreturn_t pnp_test_handler(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t pnp_test_handler(int irq, void *dev_id, struct pt_regs *regs)
...@@ -428,27 +356,28 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id, struct pt_regs *regs) ...@@ -428,27 +356,28 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id, struct pt_regs *regs)
int pnp_check_irq(struct pnp_dev * dev, int idx) int pnp_check_irq(struct pnp_dev * dev, int idx)
{ {
int tmp; int tmp;
struct pnp_dev *tdev;
unsigned long * irq = &dev->res.irq_resource[idx].start; unsigned long * irq = &dev->res.irq_resource[idx].start;
/* if the resource doesn't exist, don't complain about it */ /* if the resource doesn't exist, don't complain about it */
if (dev->res.irq_resource[idx].start == -1) if (dev->res.irq_resource[idx].start == -1)
return 0; return 1;
/* check if the resource is valid */ /* check if the resource is valid */
if (*irq < 0 || *irq > 15) if (*irq < 0 || *irq > 15)
return CONFLICT_TYPE_INVALID; return 0;
/* check if the resource is reserved */ /* check if the resource is reserved */
for (tmp = 0; tmp < 16; tmp++) { for (tmp = 0; tmp < 16; tmp++) {
if (pnp_reserve_irq[tmp] == *irq) if (pnp_reserve_irq[tmp] == *irq)
return CONFLICT_TYPE_RESERVED; return 0;
} }
/* check for internal conflicts */ /* check for internal conflicts */
for (tmp = 0; tmp < PNP_MAX_IRQ && tmp != idx; tmp++) { 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].flags & IORESOURCE_IRQ) {
if (dev->res.irq_resource[tmp].start == *irq) if (dev->res.irq_resource[tmp].start == *irq)
return CONFLICT_TYPE_INTERNAL; return 0;
} }
} }
...@@ -458,233 +387,94 @@ int pnp_check_irq(struct pnp_dev * dev, int idx) ...@@ -458,233 +387,94 @@ int pnp_check_irq(struct pnp_dev * dev, int idx)
struct pci_dev * pci = NULL; struct pci_dev * pci = NULL;
while ((pci = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci)) != NULL) { while ((pci = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci)) != NULL) {
if (pci->irq == *irq) if (pci->irq == *irq)
return CONFLICT_TYPE_PCI; return 0;
} }
} }
#endif #endif
/* check if the resource is already in use, skip if the device is active because it itself may be in use */ /* check if the resource is already in use, skip if the
* device is active because it itself may be in use */
if(!dev->active) { if(!dev->active) {
if (request_irq(*irq, pnp_test_handler, SA_INTERRUPT, "pnp", NULL)) if (request_irq(*irq, pnp_test_handler, SA_INTERRUPT, "pnp", NULL))
return CONFLICT_TYPE_IN_USE; return 0;
free_irq(*irq, NULL); free_irq(*irq, NULL);
} }
/* check for warm conflicts */ /* check for conflicts with other pnp devices */
if (pnp_check_irq_conflicts(dev, idx, SEARCH_WARM))
return CONFLICT_TYPE_PNP_WARM;
return 0;
}
struct pnp_dev * pnp_check_dma_conflicts(struct pnp_dev * dev, int idx, int mode)
{
int tmp;
struct pnp_dev * tdev;
unsigned long * dma = &dev->res.dma_resource[idx].start;
/* if the resource doesn't exist, don't complain about it */
if (dev->res.dma_resource[idx].start == -1)
return NULL;
/* check for cold conflicts */
pnp_for_each_dev(tdev) { pnp_for_each_dev(tdev) {
/* Is the device configurable? */ if (tdev == dev)
if (tdev == dev || (mode ? !tdev->active : tdev->active))
continue; continue;
for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) { for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) {
if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) { if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) {
if ((tdev->res.dma_resource[tmp].start == *dma)) if ((tdev->res.irq_resource[tmp].start == *irq))
return tdev; return 0;
} }
} }
} }
return NULL;
return 1;
} }
int pnp_check_dma(struct pnp_dev * dev, int idx) int pnp_check_dma(struct pnp_dev * dev, int idx)
{ {
int tmp, mindma = 1; int tmp, mindma = 1;
struct pnp_dev *tdev;
unsigned long * dma = &dev->res.dma_resource[idx].start; unsigned long * dma = &dev->res.dma_resource[idx].start;
/* if the resource doesn't exist, don't complain about it */ /* if the resource doesn't exist, don't complain about it */
if (dev->res.dma_resource[idx].start == -1) if (dev->res.dma_resource[idx].start == -1)
return 0; return 1;
/* check if the resource is valid */ /* check if the resource is valid */
if (pnp_allow_dma0 == 1) if (pnp_allow_dma0 == 1)
mindma = 0; mindma = 0;
if (*dma < mindma || *dma == 4 || *dma > 7) if (*dma < mindma || *dma == 4 || *dma > 7)
return CONFLICT_TYPE_INVALID; return 0;
/* check if the resource is reserved */ /* check if the resource is reserved */
for (tmp = 0; tmp < 8; tmp++) { for (tmp = 0; tmp < 8; tmp++) {
if (pnp_reserve_dma[tmp] == *dma) if (pnp_reserve_dma[tmp] == *dma)
return CONFLICT_TYPE_RESERVED; return 0;
} }
/* check for internal conflicts */ /* check for internal conflicts */
for (tmp = 0; tmp < PNP_MAX_DMA && tmp != idx; tmp++) { 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].flags & IORESOURCE_DMA) {
if (dev->res.dma_resource[tmp].start == *dma) if (dev->res.dma_resource[tmp].start == *dma)
return CONFLICT_TYPE_INTERNAL; return 0;
} }
} }
/* check if the resource is already in use, skip if the device is active because it itself may be in use */ /* check if the resource is already in use, skip if the
* device is active because it itself may be in use */
if(!dev->active) { if(!dev->active) {
if (request_dma(*dma, "pnp")) if (request_dma(*dma, "pnp"))
return CONFLICT_TYPE_IN_USE; return 0;
free_dma(*dma); free_dma(*dma);
} }
/* check for warm conflicts */ /* check for conflicts with other pnp devices */
if (pnp_check_dma_conflicts(dev, idx, SEARCH_WARM)) pnp_for_each_dev(tdev) {
return CONFLICT_TYPE_PNP_WARM; if (tdev == dev)
continue;
for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) {
if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) {
if ((tdev->res.dma_resource[tmp].start == *dma))
return 0; return 0;
}
/**
* pnp_init_resource_table - Resets a resource table to default values.
* @table: pointer to the desired resource table
*
*/
void pnp_init_resource_table(struct pnp_resource_table *table)
{
int 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_AUTO;
}
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_AUTO;
}
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_AUTO;
}
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_AUTO;
} }
} }
}
/**
* pnp_generate_rule - Creates a rule table structure based on depnum and device.
* @dev: pointer to the desired device
* @depnum: dependent function, if not valid will return an error
* @rule: pointer to a rule structure to record data to
*
*/
int pnp_generate_rule(struct pnp_dev * dev, int depnum, struct pnp_rule_table * rule)
{
int nport = 0, nirq = 0, ndma = 0, nmem = 0;
struct pnp_resources * res;
struct pnp_port * port;
struct pnp_mem * mem;
struct pnp_irq * irq;
struct pnp_dma * dma;
if (depnum < 0 || !rule)
return -EINVAL;
/* independent */
res = pnp_find_resources(dev, 0);
if (!res)
return -ENODEV;
port = res->port;
mem = res->mem;
irq = res->irq;
dma = res->dma;
while (port){
rule->port[nport] = port;
nport++;
port = port->next;
}
while (mem){
rule->mem[nmem] = mem;
nmem++;
mem = mem->next;
}
while (irq){
rule->irq[nirq] = irq;
nirq++;
irq = irq->next;
}
while (dma){
rule->dma[ndma] = dma;
ndma++;
dma = dma->next;
}
/* dependent */
if (depnum == 0)
return 1;
res = pnp_find_resources(dev, depnum);
if (!res)
return -ENODEV;
port = res->port;
mem = res->mem;
irq = res->irq;
dma = res->dma;
while (port){
rule->port[nport] = port;
nport++;
port = port->next;
}
while (mem){
rule->mem[nmem] = mem;
nmem++;
mem = mem->next;
}
while (irq){
rule->irq[nirq] = irq;
nirq++;
irq = irq->next;
}
while (dma){
rule->dma[ndma] = dma;
ndma++;
dma = dma->next;
}
/* clear the remaining values */
for (; nport < PNP_MAX_PORT; nport++)
rule->port[nport] = NULL;
for (; nmem < PNP_MAX_MEM; nmem++)
rule->mem[nmem] = NULL;
for (; nirq < PNP_MAX_IRQ; nirq++)
rule->irq[nirq] = NULL;
for (; ndma < PNP_MAX_DMA; ndma++)
rule->dma[ndma] = NULL;
return 1; return 1;
} }
EXPORT_SYMBOL(pnp_build_resource); EXPORT_SYMBOL(pnp_register_dependent_option);
EXPORT_SYMBOL(pnp_find_resources); EXPORT_SYMBOL(pnp_register_independent_option);
EXPORT_SYMBOL(pnp_get_max_depnum); EXPORT_SYMBOL(pnp_register_irq_resource);
EXPORT_SYMBOL(pnp_add_irq_resource); EXPORT_SYMBOL(pnp_register_dma_resource);
EXPORT_SYMBOL(pnp_add_dma_resource); EXPORT_SYMBOL(pnp_register_port_resource);
EXPORT_SYMBOL(pnp_add_port_resource); EXPORT_SYMBOL(pnp_register_mem_resource);
EXPORT_SYMBOL(pnp_add_mem_resource);
EXPORT_SYMBOL(pnp_init_resource_table);
EXPORT_SYMBOL(pnp_generate_rule);
/* format is: allowdma0 */ /* format is: allowdma0 */
......
/* /*
* support.c - provides standard pnp functions for the use of pnp protocol drivers, * support.c - provides standard pnp functions for the use of pnp protocol drivers,
* *
* Copyright 2002 Adam Belay <ambx1@neo.rr.com> * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
* *
* Resource parsing functions are based on those in the linux pnpbios driver. * Resource parsing functions are based on those in the linux pnpbios driver.
* Copyright Christian Schmidt, Tom Lees, David Hinds, Alan Cox, Thomas Hood, * Copyright Christian Schmidt, Tom Lees, David Hinds, Alan Cox, Thomas Hood,
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/ctype.h>
#ifdef CONFIG_PNP_DEBUG #ifdef CONFIG_PNP_DEBUG
#define DEBUG #define DEBUG
...@@ -122,7 +123,7 @@ unsigned char * pnp_parse_current_resources(unsigned char * p, unsigned char * e ...@@ -122,7 +123,7 @@ unsigned char * pnp_parse_current_resources(unsigned char * p, unsigned char * e
return NULL; return NULL;
/* Blank the resource table values */ /* Blank the resource table values */
pnp_init_resource_table(res); pnp_init_resources(res);
while ((char *)p < (char *)end) { while ((char *)p < (char *)end) {
...@@ -250,51 +251,51 @@ unsigned char * pnp_parse_current_resources(unsigned char * p, unsigned char * e ...@@ -250,51 +251,51 @@ unsigned char * pnp_parse_current_resources(unsigned char * p, unsigned char * e
* Possible resource reading functions * * Possible resource reading functions *
*/ */
static void possible_mem(unsigned char *p, int size, int depnum, struct pnp_dev *dev) static void possible_mem(unsigned char *p, int size, struct pnp_option *option)
{ {
struct pnp_mem * mem; struct pnp_mem * mem;
mem = pnp_alloc(sizeof(struct pnp_mem)); mem = pnp_alloc(sizeof(struct pnp_mem));
if (!mem) if (!mem)
return; return;
mem->min = ((p[3] << 8) | p[2]) << 8; mem->min = ((p[5] << 8) | p[4]) << 8;
mem->max = ((p[5] << 8) | p[4]) << 8; mem->max = ((p[7] << 8) | p[6]) << 8;
mem->align = (p[7] << 8) | p[6]; mem->align = (p[9] << 8) | p[8];
mem->size = ((p[9] << 8) | p[8]) << 8; mem->size = ((p[11] << 8) | p[10]) << 8;
mem->flags = p[1]; mem->flags = p[3];
pnp_add_mem_resource(dev,depnum,mem); pnp_register_mem_resource(option,mem);
return; return;
} }
static void possible_mem32(unsigned char *p, int size, int depnum, struct pnp_dev *dev) static void possible_mem32(unsigned char *p, int size, struct pnp_option *option)
{ {
struct pnp_mem * mem; struct pnp_mem * mem;
mem = pnp_alloc(sizeof(struct pnp_mem)); mem = pnp_alloc(sizeof(struct pnp_mem));
if (!mem) if (!mem)
return; return;
mem->min = (p[5] << 24) | (p[4] << 16) | (p[3] << 8) | p[2]; mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
mem->max = (p[9] << 24) | (p[8] << 16) | (p[7] << 8) | p[6]; mem->max = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
mem->align = (p[13] << 24) | (p[12] << 16) | (p[11] << 8) | p[10]; mem->align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12];
mem->size = (p[17] << 24) | (p[16] << 16) | (p[15] << 8) | p[14]; mem->size = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16];
mem->flags = p[1]; mem->flags = p[3];
pnp_add_mem_resource(dev,depnum,mem); pnp_register_mem_resource(option,mem);
return; return;
} }
static void possible_fixed_mem32(unsigned char *p, int size, int depnum, struct pnp_dev *dev) static void possible_fixed_mem32(unsigned char *p, int size, struct pnp_option *option)
{ {
struct pnp_mem * mem; struct pnp_mem * mem;
mem = pnp_alloc(sizeof(struct pnp_mem)); mem = pnp_alloc(sizeof(struct pnp_mem));
if (!mem) if (!mem)
return; return;
mem->min = mem->max = (p[5] << 24) | (p[4] << 16) | (p[3] << 8) | p[2]; mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
mem->size = (p[9] << 24) | (p[8] << 16) | (p[7] << 8) | p[6]; mem->size = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
mem->align = 0; mem->align = 0;
mem->flags = p[1]; mem->flags = p[3];
pnp_add_mem_resource(dev,depnum,mem); pnp_register_mem_resource(option,mem);
return; return;
} }
static void possible_irq(unsigned char *p, int size, int depnum, struct pnp_dev *dev) static void possible_irq(unsigned char *p, int size, struct pnp_option *option)
{ {
struct pnp_irq * irq; struct pnp_irq * irq;
irq = pnp_alloc(sizeof(struct pnp_irq)); irq = pnp_alloc(sizeof(struct pnp_irq));
...@@ -303,11 +304,13 @@ static void possible_irq(unsigned char *p, int size, int depnum, struct pnp_dev ...@@ -303,11 +304,13 @@ static void possible_irq(unsigned char *p, int size, int depnum, struct pnp_dev
irq->map = (p[2] << 8) | p[1]; irq->map = (p[2] << 8) | p[1];
if (size > 2) if (size > 2)
irq->flags = p[3]; irq->flags = p[3];
pnp_add_irq_resource(dev,depnum,irq); else
irq->flags = IORESOURCE_IRQ_HIGHEDGE;
pnp_register_irq_resource(option,irq);
return; return;
} }
static void possible_dma(unsigned char *p, int size, int depnum, struct pnp_dev *dev) static void possible_dma(unsigned char *p, int size, struct pnp_option *option)
{ {
struct pnp_dma * dma; struct pnp_dma * dma;
dma = pnp_alloc(sizeof(struct pnp_dma)); dma = pnp_alloc(sizeof(struct pnp_dma));
...@@ -315,11 +318,11 @@ static void possible_dma(unsigned char *p, int size, int depnum, struct pnp_dev ...@@ -315,11 +318,11 @@ static void possible_dma(unsigned char *p, int size, int depnum, struct pnp_dev
return; return;
dma->map = p[1]; dma->map = p[1];
dma->flags = p[2]; dma->flags = p[2];
pnp_add_dma_resource(dev,depnum,dma); pnp_register_dma_resource(option,dma);
return; return;
} }
static void possible_port(unsigned char *p, int size, int depnum, struct pnp_dev *dev) static void possible_port(unsigned char *p, int size, struct pnp_option *option)
{ {
struct pnp_port * port; struct pnp_port * port;
port = pnp_alloc(sizeof(struct pnp_port)); port = pnp_alloc(sizeof(struct pnp_port));
...@@ -330,11 +333,11 @@ static void possible_port(unsigned char *p, int size, int depnum, struct pnp_dev ...@@ -330,11 +333,11 @@ static void possible_port(unsigned char *p, int size, int depnum, struct pnp_dev
port->align = p[6]; port->align = p[6];
port->size = p[7]; port->size = p[7];
port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0; port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0;
pnp_add_port_resource(dev,depnum,port); pnp_register_port_resource(option,port);
return; return;
} }
static void possible_fixed_port(unsigned char *p, int size, int depnum, struct pnp_dev *dev) static void possible_fixed_port(unsigned char *p, int size, struct pnp_option *option)
{ {
struct pnp_port * port; struct pnp_port * port;
port = pnp_alloc(sizeof(struct pnp_port)); port = pnp_alloc(sizeof(struct pnp_port));
...@@ -344,7 +347,7 @@ static void possible_fixed_port(unsigned char *p, int size, int depnum, struct p ...@@ -344,7 +347,7 @@ static void possible_fixed_port(unsigned char *p, int size, int depnum, struct p
port->size = p[3]; port->size = p[3];
port->align = 0; port->align = 0;
port->flags = PNP_PORT_FLAG_FIXED; port->flags = PNP_PORT_FLAG_FIXED;
pnp_add_port_resource(dev,depnum,port); pnp_register_port_resource(option,port);
return; return;
} }
...@@ -358,12 +361,14 @@ static void possible_fixed_port(unsigned char *p, int size, int depnum, struct p ...@@ -358,12 +361,14 @@ static void possible_fixed_port(unsigned char *p, int size, int depnum, struct p
unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char * end, struct pnp_dev *dev) unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char * end, struct pnp_dev *dev)
{ {
int len, depnum = 0, dependent = 0; int len, priority = 0;
struct pnp_option *option;
if (!p) if (!p)
return NULL; return NULL;
if (pnp_build_resource(dev, 0) == NULL) option = pnp_register_independent_option(dev);
if (!option)
return NULL; return NULL;
while ((char *)p < (char *)end) { while ((char *)p < (char *)end) {
...@@ -375,21 +380,21 @@ unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char * ...@@ -375,21 +380,21 @@ unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char *
{ {
if (len != 9) if (len != 9)
goto lrg_err; goto lrg_err;
possible_mem(p,len,depnum,dev); possible_mem(p,len,option);
break; break;
} }
case LARGE_TAG_MEM32: case LARGE_TAG_MEM32:
{ {
if (len != 17) if (len != 17)
goto lrg_err; goto lrg_err;
possible_mem32(p,len,depnum,dev); possible_mem32(p,len,option);
break; break;
} }
case LARGE_TAG_FIXEDMEM32: case LARGE_TAG_FIXEDMEM32:
{ {
if (len != 9) if (len != 9)
goto lrg_err; goto lrg_err;
possible_fixed_mem32(p,len,depnum,dev); possible_fixed_mem32(p,len,option);
break; break;
} }
default: /* an unkown tag */ default: /* an unkown tag */
...@@ -410,46 +415,46 @@ unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char * ...@@ -410,46 +415,46 @@ unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char *
{ {
if (len < 2 || len > 3) if (len < 2 || len > 3)
goto sm_err; goto sm_err;
possible_irq(p,len,depnum,dev); possible_irq(p,len,option);
break; break;
} }
case SMALL_TAG_DMA: case SMALL_TAG_DMA:
{ {
if (len != 2) if (len != 2)
goto sm_err; goto sm_err;
possible_dma(p,len,depnum,dev); possible_dma(p,len,option);
break; break;
} }
case SMALL_TAG_STARTDEP: case SMALL_TAG_STARTDEP:
{ {
if (len > 1) if (len > 1)
goto sm_err; goto sm_err;
dependent = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE; priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;
if (len > 0) if (len > 0)
dependent = 0x100 | p[1]; priority = 0x100 | p[1];
pnp_build_resource(dev,dependent); option = pnp_register_dependent_option(dev, priority);
depnum = pnp_get_max_depnum(dev); if (!option)
return NULL;
break; break;
} }
case SMALL_TAG_ENDDEP: case SMALL_TAG_ENDDEP:
{ {
if (len != 0) if (len != 0)
goto sm_err; goto sm_err;
depnum = 0;
break; break;
} }
case SMALL_TAG_PORT: case SMALL_TAG_PORT:
{ {
if (len != 7) if (len != 7)
goto sm_err; goto sm_err;
possible_port(p,len,depnum,dev); possible_port(p,len,option);
break; break;
} }
case SMALL_TAG_FIXEDPORT: case SMALL_TAG_FIXEDPORT:
{ {
if (len != 3) if (len != 3)
goto sm_err; goto sm_err;
possible_fixed_port(p,len,depnum,dev); possible_fixed_port(p,len,option);
break; break;
} }
case SMALL_TAG_END: case SMALL_TAG_END:
...@@ -481,12 +486,12 @@ static void write_mem(unsigned char *p, struct resource * res) ...@@ -481,12 +486,12 @@ static void write_mem(unsigned char *p, struct resource * res)
{ {
unsigned long base = res->start; unsigned long base = res->start;
unsigned long len = res->end - res->start + 1; unsigned long len = res->end - res->start + 1;
p[2] = (base >> 8) & 0xff;
p[3] = ((base >> 8) >> 8) & 0xff;
p[4] = (base >> 8) & 0xff; p[4] = (base >> 8) & 0xff;
p[5] = ((base >> 8) >> 8) & 0xff; p[5] = ((base >> 8) >> 8) & 0xff;
p[8] = (len >> 8) & 0xff; p[6] = (base >> 8) & 0xff;
p[9] = ((len >> 8) >> 8) & 0xff; p[7] = ((base >> 8) >> 8) & 0xff;
p[10] = (len >> 8) & 0xff;
p[11] = ((len >> 8) >> 8) & 0xff;
return; return;
} }
...@@ -494,32 +499,32 @@ static void write_mem32(unsigned char *p, struct resource * res) ...@@ -494,32 +499,32 @@ static void write_mem32(unsigned char *p, struct resource * res)
{ {
unsigned long base = res->start; unsigned long base = res->start;
unsigned long len = res->end - res->start + 1; unsigned long len = res->end - res->start + 1;
p[2] = base & 0xff; p[4] = base & 0xff;
p[3] = (base >> 8) & 0xff; p[5] = (base >> 8) & 0xff;
p[4] = (base >> 16) & 0xff; p[6] = (base >> 16) & 0xff;
p[5] = (base >> 24) & 0xff; p[7] = (base >> 24) & 0xff;
p[6] = base & 0xff; p[8] = base & 0xff;
p[7] = (base >> 8) & 0xff; p[9] = (base >> 8) & 0xff;
p[8] = (base >> 16) & 0xff; p[10] = (base >> 16) & 0xff;
p[9] = (base >> 24) & 0xff; p[11] = (base >> 24) & 0xff;
p[14] = len & 0xff; p[16] = len & 0xff;
p[15] = (len >> 8) & 0xff; p[17] = (len >> 8) & 0xff;
p[16] = (len >> 16) & 0xff; p[18] = (len >> 16) & 0xff;
p[17] = (len >> 24) & 0xff; p[19] = (len >> 24) & 0xff;
return; return;
} }
static void write_fixed_mem32(unsigned char *p, struct resource * res) static void write_fixed_mem32(unsigned char *p, struct resource * res)
{ unsigned long base = res->start; { unsigned long base = res->start;
unsigned long len = res->end - res->start + 1; unsigned long len = res->end - res->start + 1;
p[2] = base & 0xff; p[4] = base & 0xff;
p[3] = (base >> 8) & 0xff; p[5] = (base >> 8) & 0xff;
p[4] = (base >> 16) & 0xff; p[6] = (base >> 16) & 0xff;
p[5] = (base >> 24) & 0xff; p[7] = (base >> 24) & 0xff;
p[6] = len & 0xff; p[8] = len & 0xff;
p[7] = (len >> 8) & 0xff; p[9] = (len >> 8) & 0xff;
p[8] = (len >> 16) & 0xff; p[10] = (len >> 16) & 0xff;
p[9] = (len >> 24) & 0xff; p[11] = (len >> 24) & 0xff;
return; return;
} }
...@@ -630,7 +635,7 @@ unsigned char * pnp_write_resources(unsigned char * p, unsigned char * end, stru ...@@ -630,7 +635,7 @@ unsigned char * pnp_write_resources(unsigned char * p, unsigned char * end, stru
{ {
if (len != 2) if (len != 2)
goto sm_err; goto sm_err;
write_dma(p, &res->dma_resource[irq]); write_dma(p, &res->dma_resource[dma]);
dma++; dma++;
break; break;
} }
......
...@@ -315,19 +315,6 @@ static const struct pnp_device_id pnp_dev_table[] = { ...@@ -315,19 +315,6 @@ static const struct pnp_device_id pnp_dev_table[] = {
MODULE_DEVICE_TABLE(pnp, pnp_dev_table); MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
static inline void avoid_irq_share(struct pnp_dev *dev)
{
unsigned int map = 0x1FF8;
struct pnp_irq *irq;
struct pnp_resources *res = dev->possible;
serial8250_get_irq_map(&map);
for ( ; res; res = res->dep)
for (irq = res->irq; irq; irq = irq->next)
irq->map = map;
}
static char *modem_names[] __devinitdata = { static char *modem_names[] __devinitdata = {
"MODEM", "Modem", "modem", "FAX", "Fax", "fax", "MODEM", "Modem", "modem", "FAX", "Fax", "fax",
"56K", "56k", "K56", "33.6", "28.8", "14.4", "56K", "56k", "K56", "33.6", "28.8", "14.4",
...@@ -346,6 +333,29 @@ static int __devinit check_name(char *name) ...@@ -346,6 +333,29 @@ static int __devinit check_name(char *name)
return 0; return 0;
} }
static int __devinit check_resources(struct pnp_option *option)
{
struct pnp_option *tmp;
if (!option)
return 0;
for (tmp = option; tmp; tmp = tmp->next) {
struct pnp_port *port;
for (port = tmp->port; port; port = port->next)
if ((port->size == 8) &&
((port->min == 0x2f8) ||
(port->min == 0x3f8) ||
(port->min == 0x2e8) ||
#ifdef CONFIG_X86_PC9800
(port->min == 0x8b0) ||
#endif
(port->min == 0x3e8)))
return 1;
}
return 0;
}
/* /*
* Given a complete unknown PnP device, try to use some heuristics to * Given a complete unknown PnP device, try to use some heuristics to
* detect modems. Currently use such heuristic set: * detect modems. Currently use such heuristic set:
...@@ -357,30 +367,16 @@ static int __devinit check_name(char *name) ...@@ -357,30 +367,16 @@ static int __devinit check_name(char *name)
* PnP modems, alternatively we must hardcode all modems in pnp_devices[] * PnP modems, alternatively we must hardcode all modems in pnp_devices[]
* table. * table.
*/ */
static int serial_pnp_guess_board(struct pnp_dev *dev, int *flags) static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags)
{ {
struct pnp_resources *res = dev->possible;
struct pnp_resources *resa;
if (!(check_name(dev->dev.name) || (dev->card && check_name(dev->card->dev.name)))) if (!(check_name(dev->dev.name) || (dev->card && check_name(dev->card->dev.name))))
return -ENODEV; return -ENODEV;
if (!res) if (check_resources(dev->independent))
return -ENODEV; return 0;
for (resa = res->dep; resa; resa = resa->dep) { if (check_resources(dev->dependent))
struct pnp_port *port;
for (port = res->port; port; port = port->next)
if ((port->size == 8) &&
((port->min == 0x2f8) ||
(port->min == 0x3f8) ||
(port->min == 0x2e8) ||
#ifdef CONFIG_X86_PC9800
(port->min == 0x8b0) ||
#endif
(port->min == 0x3e8)))
return 0; return 0;
}
return -ENODEV; return -ENODEV;
} }
...@@ -395,8 +391,6 @@ serial_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id) ...@@ -395,8 +391,6 @@ serial_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id)
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
if (flags & SPCI_FL_NO_SHIRQ)
avoid_irq_share(dev);
memset(&serial_req, 0, sizeof(serial_req)); memset(&serial_req, 0, sizeof(serial_req));
serial_req.irq = pnp_irq(dev,0); serial_req.irq = pnp_irq(dev,0);
serial_req.port = pnp_port_start(dev, 0); serial_req.port = pnp_port_start(dev, 0);
......
...@@ -102,22 +102,13 @@ struct pnp_mem { ...@@ -102,22 +102,13 @@ struct pnp_mem {
#define PNP_RES_PRIORITY_FUNCTIONAL 2 #define PNP_RES_PRIORITY_FUNCTIONAL 2
#define PNP_RES_PRIORITY_INVALID 65535 #define PNP_RES_PRIORITY_INVALID 65535
struct pnp_resources { struct pnp_option {
unsigned short priority; /* priority */ unsigned short priority; /* priority */
struct pnp_port *port; /* first port */ struct pnp_port *port; /* first port */
struct pnp_irq *irq; /* first IRQ */ struct pnp_irq *irq; /* first IRQ */
struct pnp_dma *dma; /* first DMA */ struct pnp_dma *dma; /* first DMA */
struct pnp_mem *mem; /* first memory resource */ struct pnp_mem *mem; /* first memory resource */
struct pnp_dev *dev; /* parent */ struct pnp_option *next; /* used to chain dependent resources */
struct pnp_resources *dep; /* dependent resources */
};
struct pnp_rule_table {
int depnum;
struct pnp_port *port[PNP_MAX_PORT];
struct pnp_irq *irq[PNP_MAX_IRQ];
struct pnp_dma *dma[PNP_MAX_DMA];
struct pnp_mem *mem[PNP_MAX_MEM];
}; };
struct pnp_resource_table { struct pnp_resource_table {
...@@ -187,8 +178,6 @@ static inline void pnp_set_card_drvdata (struct pnp_card_link *pcard, void *data ...@@ -187,8 +178,6 @@ static inline void pnp_set_card_drvdata (struct pnp_card_link *pcard, void *data
struct pnp_dev { struct pnp_dev {
struct device dev; /* Driver Model device interface */ struct device dev; /* Driver Model device interface */
unsigned char number; /* used as an index, must be unique */ unsigned char number; /* used as an index, must be unique */
int active;
int capabilities;
int status; int status;
struct list_head global_list; /* node in global list of devices */ struct list_head global_list; /* node in global list of devices */
...@@ -202,10 +191,12 @@ struct pnp_dev { ...@@ -202,10 +191,12 @@ struct pnp_dev {
struct pnp_card_link * card_link; struct pnp_card_link * card_link;
struct pnp_id * id; /* supported EISA IDs*/ struct pnp_id * id; /* supported EISA IDs*/
struct pnp_resource_table res; /* contains the currently chosen resources */
struct pnp_resources * possible; /* a list of possible resources */ int active;
struct pnp_rule_table * rule; /* the current possible resource set */ int capabilities;
int config_mode; /* flags that determine how the device's resources should be configured */ struct pnp_option * independent;
struct pnp_option * dependent;
struct pnp_resource_table res;
void * protocol_data; /* Used to store protocol specific data */ void * protocol_data; /* Used to store protocol specific data */
unsigned short regs; /* ISAPnP: supported registers */ unsigned short regs; /* ISAPnP: supported registers */
...@@ -252,11 +243,9 @@ struct pnp_fixup { ...@@ -252,11 +243,9 @@ struct pnp_fixup {
void (*quirk_function)(struct pnp_dev *dev); /* fixup function */ void (*quirk_function)(struct pnp_dev *dev); /* fixup function */
}; };
/* config modes */ /* config parameters */
#define PNP_CONFIG_AUTO 0x0001 /* Use the Resource Configuration Engine to determine resource settings */ #define PNP_CONFIG_NORMAL 0x0001
#define PNP_CONFIG_MANUAL 0x0002 /* the config has been manually specified */ #define PNP_CONFIG_FORCE 0x0002 /* disables validity checking */
#define PNP_CONFIG_FORCE 0x0004 /* disables validity checking */
#define PNP_CONFIG_INVALID 0x0008 /* If this flag is set, the pnp layer will refuse to activate the device */
/* capabilities */ /* capabilities */
#define PNP_READ 0x0001 #define PNP_READ 0x0001
...@@ -271,7 +260,7 @@ struct pnp_fixup { ...@@ -271,7 +260,7 @@ struct pnp_fixup {
((dev)->capabilities & PNP_WRITE)) ((dev)->capabilities & PNP_WRITE))
#define pnp_can_disable(dev) (((dev)->protocol) && ((dev)->protocol->disable) && \ #define pnp_can_disable(dev) (((dev)->protocol) && ((dev)->protocol->disable) && \
((dev)->capabilities & PNP_DISABLE)) ((dev)->capabilities & PNP_DISABLE))
#define pnp_can_configure(dev) ((!(dev)->active) && ((dev)->config_mode & PNP_CONFIG_AUTO) && \ #define pnp_can_configure(dev) ((!(dev)->active) && \
((dev)->capabilities & PNP_CONFIGURABLE)) ((dev)->capabilities & PNP_CONFIGURABLE))
#ifdef CONFIG_ISAPNP #ifdef CONFIG_ISAPNP
...@@ -383,7 +372,7 @@ struct pnp_protocol { ...@@ -383,7 +372,7 @@ struct pnp_protocol {
#if defined(CONFIG_PNP) #if defined(CONFIG_PNP)
/* core */ /* device management */
int pnp_register_protocol(struct pnp_protocol *protocol); int pnp_register_protocol(struct pnp_protocol *protocol);
void pnp_unregister_protocol(struct pnp_protocol *protocol); void pnp_unregister_protocol(struct pnp_protocol *protocol);
int pnp_add_device(struct pnp_dev *dev); int pnp_add_device(struct pnp_dev *dev);
...@@ -392,7 +381,7 @@ int pnp_device_attach(struct pnp_dev *pnp_dev); ...@@ -392,7 +381,7 @@ int pnp_device_attach(struct pnp_dev *pnp_dev);
void pnp_device_detach(struct pnp_dev *pnp_dev); void pnp_device_detach(struct pnp_dev *pnp_dev);
extern struct list_head pnp_global; extern struct list_head pnp_global;
/* card */ /* multidevice card support */
int pnp_add_card(struct pnp_card *card); int pnp_add_card(struct pnp_card *card);
void pnp_remove_card(struct pnp_card *card); void pnp_remove_card(struct pnp_card *card);
int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev); int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev);
...@@ -404,41 +393,35 @@ int pnp_register_card_driver(struct pnp_card_driver * drv); ...@@ -404,41 +393,35 @@ int pnp_register_card_driver(struct pnp_card_driver * drv);
void pnp_unregister_card_driver(struct pnp_card_driver * drv); void pnp_unregister_card_driver(struct pnp_card_driver * drv);
extern struct list_head pnp_cards; extern struct list_head pnp_cards;
/* resource */ /* resource management */
struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent); struct pnp_option * pnp_register_independent_option(struct pnp_dev *dev);
struct pnp_resources * pnp_find_resources(struct pnp_dev *dev, int depnum); struct pnp_option * pnp_register_dependent_option(struct pnp_dev *dev, int priority);
int pnp_get_max_depnum(struct pnp_dev *dev); int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data);
int pnp_add_irq_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data); int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data);
int pnp_add_dma_resource(struct pnp_dev *dev, int depnum, struct pnp_dma *data); int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data);
int pnp_add_port_resource(struct pnp_dev *dev, int depnum, struct pnp_port *data); int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data);
int pnp_add_mem_resource(struct pnp_dev *dev, int depnum, struct pnp_mem *data); void pnp_init_resources(struct pnp_resource_table *table);
void pnp_init_resource_table(struct pnp_resource_table *table); int pnp_assign_resources(struct pnp_dev *dev, int depnum);
int pnp_generate_rule(struct pnp_dev * dev, int depnum, struct pnp_rule_table * rule); int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode);
int pnp_auto_config_dev(struct pnp_dev *dev);
/* manager */ int pnp_validate_config(struct pnp_dev *dev);
int pnp_activate_dev(struct pnp_dev *dev); int pnp_activate_dev(struct pnp_dev *dev);
int pnp_disable_dev(struct pnp_dev *dev); int pnp_disable_dev(struct pnp_dev *dev);
void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size); void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size);
int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode);
int pnp_auto_config_dev(struct pnp_dev *dev);
/* driver */
int compare_pnp_id(struct pnp_id * pos, const char * id);
int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev);
int pnp_register_driver(struct pnp_driver *drv);
void pnp_unregister_driver(struct pnp_driver *drv);
/* support */ /* protocol helpers */
int pnp_is_active(struct pnp_dev * dev); int pnp_is_active(struct pnp_dev * dev);
unsigned char * pnp_parse_current_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res); unsigned char * pnp_parse_current_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res);
unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char * end, struct pnp_dev * dev); unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char * end, struct pnp_dev * dev);
unsigned char * pnp_write_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res); unsigned char * pnp_write_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res);
int compare_pnp_id(struct pnp_id * pos, const char * id);
int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev);
int pnp_register_driver(struct pnp_driver *drv);
void pnp_unregister_driver(struct pnp_driver *drv);
#else #else
/* just in case anyone decides to call these without PnP Support Enabled */ /* device management */
/* core */
static inline int pnp_register_protocol(struct pnp_protocol *protocol) { return -ENODEV; } static inline int pnp_register_protocol(struct pnp_protocol *protocol) { return -ENODEV; }
static inline void pnp_unregister_protocol(struct pnp_protocol *protocol) { } static inline void pnp_unregister_protocol(struct pnp_protocol *protocol) { }
static inline int pnp_init_device(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_init_device(struct pnp_dev *dev) { return -ENODEV; }
...@@ -447,7 +430,7 @@ static inline void pnp_remove_device(struct pnp_dev *dev) { } ...@@ -447,7 +430,7 @@ static inline void pnp_remove_device(struct pnp_dev *dev) { }
static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; } static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; }
static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { ; } static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { ; }
/* card */ /* multidevice card support */
static inline int pnp_add_card(struct pnp_card *card) { return -ENODEV; } static inline int pnp_add_card(struct pnp_card *card) { return -ENODEV; }
static inline void pnp_remove_card(struct pnp_card *card) { ; } static inline void pnp_remove_card(struct pnp_card *card) { ; }
static inline int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev) { return -ENODEV; }
...@@ -458,35 +441,31 @@ static inline void pnp_release_card_device(struct pnp_dev * dev) { ; } ...@@ -458,35 +441,31 @@ static inline void pnp_release_card_device(struct pnp_dev * dev) { ; }
static inline int pnp_register_card_driver(struct pnp_card_driver * drv) { return -ENODEV; } static inline int pnp_register_card_driver(struct pnp_card_driver * drv) { return -ENODEV; }
static inline void pnp_unregister_card_driver(struct pnp_card_driver * drv) { ; } static inline void pnp_unregister_card_driver(struct pnp_card_driver * drv) { ; }
/* resource */ /* resource management */
static inline struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent) { return NULL; } static inline struct pnp_option * pnp_register_independent_option(struct pnp_dev *dev) { return NULL; }
static inline struct pnp_resources * pnp_find_resources(struct pnp_dev *dev, int depnum) { return NULL; } static inline struct pnp_option * pnp_register_dependent_option(struct pnp_dev *dev, int priority) { return NULL; }
static inline int pnp_get_max_depnum(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data) { return -ENODEV; }
static inline int pnp_add_irq_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; } static inline int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data) { return -ENODEV; }
static inline int pnp_add_dma_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; } static inline int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data) { return -ENODEV; }
static inline int pnp_add_port_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; } static inline int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data) { return -ENODEV; }
static inline int pnp_add_mem_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; } static inline void pnp_init_resources(struct pnp_resource_table *table) { }
static inline void pnp_init_resource_table(struct pnp_resource_table *table) { ; } static inline int pnp_assign_resources(struct pnp_dev *dev, int depnum) { return -ENODEV; }
static inline int pnp_generate_rule(struct pnp_dev * dev, int depnum, struct pnp_rule_table * rule) { return -ENODEV; }
/* manager */
static inline int pnp_activate_dev(struct pnp_dev *dev) { return -ENODEV; }
static inline int pnp_disable_dev(struct pnp_dev *dev) { return -ENODEV; }
static inline void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size) { ; }
static inline int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode) { return -ENODEV; } static inline int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode) { return -ENODEV; }
static inline int pnp_auto_config_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_auto_config_dev(struct pnp_dev *dev) { return -ENODEV; }
static inline int pnp_validate_config(struct pnp_dev *dev) { return -ENODEV; }
static inline int pnp_activate_dev(struct pnp_dev *dev) { return -ENODEV; }
static inline int pnp_disable_dev(struct pnp_dev *dev) { return -ENODEV; }
static inline void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size) { }
/* driver */ /* protocol helpers */
static inline int compare_pnp_id(struct list_head * id_list, const char * id) { return -ENODEV; } static inline int pnp_is_active(struct pnp_dev * dev) { return 0; }
static inline int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) { return -ENODEV; }
static inline int pnp_register_driver(struct pnp_driver *drv) { return -ENODEV; }
static inline void pnp_unregister_driver(struct pnp_driver *drv) { ; }
/* support */
static inline int pnp_is_active(struct pnp_dev * dev) { return -ENODEV; }
static inline unsigned char * pnp_parse_current_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res) { return NULL; } static inline unsigned char * pnp_parse_current_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res) { return NULL; }
static inline unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char * end, struct pnp_dev * dev) { return NULL; } static inline unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char * end, struct pnp_dev * dev) { return NULL; }
static inline unsigned char * pnp_write_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res) { return NULL; } static inline unsigned char * pnp_write_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res) { return NULL; }
static inline int compare_pnp_id(struct pnp_id * pos, const char * id) { return -ENODEV; }
static inline int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) { return -ENODEV; }
static inline int pnp_register_driver(struct pnp_driver *drv) { return -ENODEV; }
static inline void pnp_unregister_driver(struct pnp_driver *drv) { ; }
#endif /* CONFIG_PNP */ #endif /* CONFIG_PNP */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment