Commit 40ca599a authored by Adam Belay's avatar Adam Belay

[PNP] Resource Management Cleanups and Updates

This patch does the following...
1.) changes struct pnp_resources to pnp_option for clarity
2.) greatly cleans up resource option registration
3.) removes some of the current conflict prevention code in
order to increase flexibility, (users will have more control)
4.) various manager cleanups, resulting code is more efficient
5.) fixes the locking bugs many have reported (now uses a mutex)
6.) removes the conflict displaying interface
 - it is better to handle such things in user space
7.) also many misc. cleanups
parent 015744f5
...@@ -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,23 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count ...@@ -400,41 +314,23 @@ 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;
}
if (!strnicmp(buf,"get",3)) {
spin_lock(&pnp_lock);
if (pnp_can_read(dev))
dev->protocol->get(dev, &dev->res);
spin_unlock(&pnp_lock);
goto done; goto done;
} }
if (!strnicmp(buf,"set",3)) { if (!strnicmp(buf,"set",3)) {
...@@ -442,9 +338,8 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count ...@@ -442,9 +338,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 +409,7 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count ...@@ -514,7 +409,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 +438,7 @@ static DEVICE_ATTR(id,S_IRUGO,pnp_show_current_ids,NULL); ...@@ -543,7 +438,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;
......
This diff is collapsed.
This diff is collapsed.
...@@ -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;
} }
......
This diff is collapsed.
/* /*
* 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,7 +251,7 @@ unsigned char * pnp_parse_current_resources(unsigned char * p, unsigned char * e ...@@ -250,7 +251,7 @@ 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));
...@@ -261,11 +262,11 @@ static void possible_mem(unsigned char *p, int size, int depnum, struct pnp_dev ...@@ -261,11 +262,11 @@ static void possible_mem(unsigned char *p, int size, int depnum, struct pnp_dev
mem->align = (p[7] << 8) | p[6]; mem->align = (p[7] << 8) | p[6];
mem->size = ((p[9] << 8) | p[8]) << 8; mem->size = ((p[9] << 8) | p[8]) << 8;
mem->flags = p[1]; mem->flags = p[1];
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));
...@@ -276,11 +277,11 @@ static void possible_mem32(unsigned char *p, int size, int depnum, struct pnp_de ...@@ -276,11 +277,11 @@ static void possible_mem32(unsigned char *p, int size, int depnum, struct pnp_de
mem->align = (p[13] << 24) | (p[12] << 16) | (p[11] << 8) | p[10]; mem->align = (p[13] << 24) | (p[12] << 16) | (p[11] << 8) | p[10];
mem->size = (p[17] << 24) | (p[16] << 16) | (p[15] << 8) | p[14]; mem->size = (p[17] << 24) | (p[16] << 16) | (p[15] << 8) | p[14];
mem->flags = p[1]; mem->flags = p[1];
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));
...@@ -290,11 +291,11 @@ static void possible_fixed_mem32(unsigned char *p, int size, int depnum, struct ...@@ -290,11 +291,11 @@ static void possible_fixed_mem32(unsigned char *p, int size, int depnum, struct
mem->size = (p[9] << 24) | (p[8] << 16) | (p[7] << 8) | p[6]; mem->size = (p[9] << 24) | (p[8] << 16) | (p[7] << 8) | p[6];
mem->align = 0; mem->align = 0;
mem->flags = p[1]; mem->flags = p[1];
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:
......
...@@ -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);
......
This diff is collapsed.
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