Commit d3899e3c authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linux-pnp.bkbits.net/pnp-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 77518190 8397ceac
...@@ -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;
......
This diff is collapsed.
This diff is collapsed.
...@@ -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;
} }
......
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,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);
......
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