Commit 91ff8c75 authored by Adam Belay's avatar Adam Belay

Interface Updates

Includes the ability to report exactly where conflicts are occuring and 
several set resource improvements.
parent 6a5d3d2c
/* /*
* interface.c - contains everything related to the user interface * interface.c - contains everything related to the user interface
* *
* Some code is based on isapnp_proc.c (c) Jaroslav Kysela <perex@suse.cz> * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@suse.cz>
* Copyright 2002 Adam Belay <ambx1@neo.rr.com> * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
* *
*/ */
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/ctype.h>
#include <asm/uaccess.h>
#include "base.h" #include "base.h"
...@@ -158,27 +160,15 @@ static void pnp_print_mem(pnp_info_buffer_t *buffer, char *space, struct pnp_mem ...@@ -158,27 +160,15 @@ static void pnp_print_mem(pnp_info_buffer_t *buffer, char *space, struct pnp_mem
case IORESOURCE_MEM_8AND16BIT: case IORESOURCE_MEM_8AND16BIT:
s = "8-bit&16-bit"; s = "8-bit&16-bit";
break; break;
case IORESOURCE_MEM_32BIT:
s = "32-bit";
break;
default: default:
s = "16-bit"; s = "16-bit";
} }
pnp_printf(buffer, ", %s\n", s); pnp_printf(buffer, ", %s\n", s);
} }
static void pnp_print_mem32(pnp_info_buffer_t *buffer, char *space, struct pnp_mem32 *mem32)
{
int first = 1, i;
pnp_printf(buffer, "%s32-bit memory ", space);
for (i = 0; i < 17; i++) {
if (first) {
first = 0;
} else {
pnp_printf(buffer, ":");
}
pnp_printf(buffer, "%02x", mem32->data[i]);
}
}
static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct pnp_resources *res, int dep) static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct pnp_resources *res, int dep)
{ {
char *s; char *s;
...@@ -186,7 +176,6 @@ static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct p ...@@ -186,7 +176,6 @@ static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct p
struct pnp_irq *irq; struct pnp_irq *irq;
struct pnp_dma *dma; struct pnp_dma *dma;
struct pnp_mem *mem; struct pnp_mem *mem;
struct pnp_mem32 *mem32;
switch (res->priority) { switch (res->priority) {
case PNP_RES_PRIORITY_PREFERRED: case PNP_RES_PRIORITY_PREFERRED:
...@@ -211,18 +200,15 @@ static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct p ...@@ -211,18 +200,15 @@ static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct p
pnp_print_dma(buffer, space, dma); pnp_print_dma(buffer, space, dma);
for (mem = res->mem; mem; mem = mem->next) for (mem = res->mem; mem; mem = mem->next)
pnp_print_mem(buffer, space, mem); pnp_print_mem(buffer, space, mem);
for (mem32 = res->mem32; mem32; mem32 = mem32->next)
pnp_print_mem32(buffer, space, mem32);
} }
static ssize_t pnp_show_possible_resources(struct device *dmdev, char *buf) static ssize_t pnp_show_possible_resources(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->res; struct pnp_resources * res = dev->possible;
int dep = 0; int ret, dep = 0;
pnp_info_buffer_t *buffer; pnp_info_buffer_t *buffer = (pnp_info_buffer_t *)
pnp_alloc(sizeof(pnp_info_buffer_t));
buffer = (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;
...@@ -236,97 +222,272 @@ static ssize_t pnp_show_possible_resources(struct device *dmdev, char *buf) ...@@ -236,97 +222,272 @@ static ssize_t pnp_show_possible_resources(struct device *dmdev, char *buf)
res = res->dep; res = res->dep;
dep++; dep++;
} }
return (buffer->curr - buf); ret = (buffer->curr - buf);
kfree(buffer);
return ret;
} }
static DEVICE_ATTR(possible,S_IRUGO,pnp_show_possible_resources,NULL); static DEVICE_ATTR(possible,S_IRUGO,pnp_show_possible_resources,NULL);
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, "This resource was manually reserved.\n");
break;
case CONFLICT_TYPE_IN_USE:
pnp_printf(buffer, "This resource resource is currently in use.\n");
break;
case CONFLICT_TYPE_PCI:
pnp_printf(buffer, "This resource conflicts with a PCI device.\n");
break;
case CONFLICT_TYPE_INVALID:
pnp_printf(buffer, "This resource is invalid.\n");
break;
case CONFLICT_TYPE_INTERNAL:
pnp_printf(buffer, "This resource conflicts with another resource on this device.\n");
break;
case CONFLICT_TYPE_PNP_WARM:
pnp_printf(buffer, "This resource conflicts with the active PnP device ");
break;
case CONFLICT_TYPE_PNP_COLD:
pnp_printf(buffer, "This resource conflicts with the resources that PnP plans to assign to the device ");
break;
default:
pnp_printf(buffer, "Unknown conflict.\n");
break;
}
}
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(pnp_info_buffer_t *buffer, struct pnp_dev * dev, int idx, int type)
{
struct pnp_dev * cdev, * wdev;
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 (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)
{ {
struct pnp_dev *dev = to_pnp_dev(dmdev); struct pnp_dev *dev = to_pnp_dev(dmdev);
char *str = buf; int i, ret;
int i; pnp_info_buffer_t *buffer = (pnp_info_buffer_t *)
pnp_alloc(sizeof(pnp_info_buffer_t));
if (!buffer)
return -ENOMEM;
if (!dev)
return -EINVAL;
buffer->len = PAGE_SIZE;
buffer->buffer = buf;
buffer->curr = buffer->buffer;
if (!dev->active){ pnp_printf(buffer,"state = ");
str += sprintf(str,"DISABLED\n"); if (dev->active)
goto done; pnp_printf(buffer,"active\n");
} else
for (i = 0; i < DEVICE_COUNT_IO; i++) { pnp_printf(buffer,"disabled\n");
for (i = 0; i < PNP_MAX_PORT; i++) {
if (pnp_port_valid(dev, i)) { if (pnp_port_valid(dev, i)) {
str += sprintf(str,"io"); pnp_printf(buffer,"io");
str += sprintf(str," 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 < DEVICE_COUNT_MEM; i++) { for (i = 0; i < PNP_MAX_MEM; i++) {
if (pnp_mem_valid(dev, i)) { if (pnp_mem_valid(dev, i)) {
str += sprintf(str,"mem"); pnp_printf(buffer,"mem");
str += sprintf(str," 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 < DEVICE_COUNT_IRQ; i++) { for (i = 0; i < PNP_MAX_IRQ; i++) {
if (pnp_irq_valid(dev, i)) { if (pnp_irq_valid(dev, i)) {
str += sprintf(str,"irq"); pnp_printf(buffer,"irq");
str += sprintf(str," %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 < DEVICE_COUNT_DMA; i++) { for (i = 0; i < PNP_MAX_DMA; i++) {
if (pnp_dma_valid(dev, i)) { if (pnp_dma_valid(dev, i)) {
str += sprintf(str,"dma"); pnp_printf(buffer,"dma");
str += sprintf(str," %ld \n", pnp_dma(dev, i)); pnp_printf(buffer," %ld \n", pnp_dma(dev, i));
pnp_print_conflict(buffer, dev, i, IORESOURCE_DMA);
} }
} }
done: ret = (buffer->curr - buf);
return (str - buf); kfree(buffer);
return ret;
} }
extern int pnp_resolve_conflicts(struct pnp_dev *dev);
static ssize_t static ssize_t
pnp_set_current_resources(struct device * dmdev, const char * buf, size_t count) pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count)
{ {
struct pnp_dev *dev = to_pnp_dev(dmdev); struct pnp_dev *dev = to_pnp_dev(dmdev);
char command[20]; char *buf = (void *)ubuf;
int num_args; int retval = 0;
int error = 0;
int depnum;
num_args = sscanf(buf,"%10s %i",command,&depnum); while (isspace(*buf))
if (!num_args) ++buf;
goto done; if (!strnicmp(buf,"disable",7)) {
if (!strnicmp(command,"lock",4)) { retval = pnp_disable_dev(dev);
if (dev->active) {
dev->lock_resources = 1;
} else {
error = -EINVAL;
}
goto done; goto done;
} }
if (!strnicmp(command,"unlock",6)) { if (!strnicmp(buf,"activate",8)) {
if (dev->lock_resources) { retval = pnp_activate_dev(dev);
dev->lock_resources = 0;
} else {
error = -EINVAL;
}
goto done; goto done;
} }
if (!strnicmp(command,"disable",7)) { if (!strnicmp(buf,"auto-config",11)) {
error = pnp_disable_dev(dev); if (dev->active)
goto done;
retval = pnp_auto_config_dev(dev);
goto done; goto done;
} }
if (!strnicmp(command,"auto",4)) { if (!strnicmp(buf,"resolve",7)) {
error = pnp_activate_dev(dev,NULL); retval = pnp_resolve_conflicts(dev);
goto done; goto done;
} }
if (!strnicmp(command,"manual",6)) { if (!strnicmp(buf,"set",3)) {
if (num_args != 2) if (dev->active)
goto done; goto done;
error = pnp_raw_set_dev(dev,depnum,NULL); buf += 3;
struct pnp_resource_table res;
int nport = 0, nmem = 0, nirq = 0, ndma = 0;
pnp_init_resource_table(&res);
while (1) {
while (isspace(*buf))
++buf;
if (!strnicmp(buf,"io",2)) {
buf += 2;
while (isspace(*buf))
++buf;
res.port_resource[nport].start = simple_strtoul(buf,&buf,0);
while (isspace(*buf))
++buf;
if(*buf == '-') {
buf += 1;
while (isspace(*buf))
++buf;
res.port_resource[nport].end = simple_strtoul(buf,&buf,0);
} else
res.port_resource[nport].end = res.port_resource[nport].start;
res.port_resource[nport].flags = IORESOURCE_IO;
nport++;
if (nport >= PNP_MAX_PORT)
break;
continue;
}
if (!strnicmp(buf,"mem",3)) {
buf += 3;
while (isspace(*buf))
++buf;
res.mem_resource[nmem].start = simple_strtoul(buf,&buf,0);
while (isspace(*buf))
++buf;
if(*buf == '-') {
buf += 1;
while (isspace(*buf))
++buf;
res.mem_resource[nmem].end = simple_strtoul(buf,&buf,0);
} else
res.mem_resource[nmem].end = res.mem_resource[nmem].start;
res.mem_resource[nmem].flags = IORESOURCE_MEM;
nmem++;
if (nmem >= PNP_MAX_MEM)
break;
continue;
}
if (!strnicmp(buf,"irq",3)) {
buf += 3;
while (isspace(*buf))
++buf;
res.irq_resource[nirq].start =
res.irq_resource[nirq].end = simple_strtoul(buf,&buf,0);
res.irq_resource[nirq].flags = IORESOURCE_IRQ;
nirq++;
if (nirq >= PNP_MAX_IRQ)
break;
continue;
}
if (!strnicmp(buf,"dma",3)) {
buf += 3;
while (isspace(*buf))
++buf;
res.dma_resource[ndma].start =
res.dma_resource[ndma].end = simple_strtoul(buf,&buf,0);
res.dma_resource[ndma].flags = IORESOURCE_DMA;
ndma++;
if (ndma >= PNP_MAX_DMA)
break;
continue;
}
break;
}
spin_lock(&pnp_lock);
dev->config_mode = PNP_CONFIG_MANUAL;
dev->res = res;
spin_unlock(&pnp_lock);
goto done; goto done;
} }
done: done:
return error < 0 ? error : count; if (retval)
return retval;
return count;
} }
static DEVICE_ATTR(resources,S_IRUGO | S_IWUSR, static DEVICE_ATTR(resources,S_IRUGO | S_IWUSR,
......
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