Commit 008238b5 authored by Len Brown's avatar Len Brown

Merge branch 'pnp' into release

parents 96916090 dfd2e1b4
extern spinlock_t pnp_lock; extern spinlock_t pnp_lock;
void *pnp_alloc(long size); void *pnp_alloc(long size);
int pnp_register_protocol(struct pnp_protocol *protocol);
void pnp_unregister_protocol(struct pnp_protocol *protocol);
#define PNP_EISA_ID_MASK 0x7fffffff
void pnp_eisa_id_to_string(u32 id, char *str);
struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id, char *pnpid);
struct pnp_card *pnp_alloc_card(struct pnp_protocol *, int id, char *pnpid);
int pnp_add_device(struct pnp_dev *dev);
struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id);
int pnp_interface_attach_device(struct pnp_dev *dev); int pnp_interface_attach_device(struct pnp_dev *dev);
int pnp_add_card(struct pnp_card *card);
struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id);
void pnp_remove_card(struct pnp_card *card);
int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev);
void pnp_remove_card_device(struct pnp_dev *dev);
struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev);
struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
int priority);
int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
struct pnp_irq *data);
int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option,
struct pnp_dma *data);
int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option,
struct pnp_port *data);
int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option,
struct pnp_mem *data);
void pnp_init_resources(struct pnp_dev *dev);
void pnp_fixup_device(struct pnp_dev *dev); void pnp_fixup_device(struct pnp_dev *dev);
void pnp_free_option(struct pnp_option *option); 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);
int pnp_check_port(struct pnp_dev * dev, int idx); int pnp_check_port(struct pnp_dev *dev, struct resource *res);
int pnp_check_mem(struct pnp_dev * dev, int idx); int pnp_check_mem(struct pnp_dev *dev, struct resource *res);
int pnp_check_irq(struct pnp_dev * dev, int idx); int pnp_check_irq(struct pnp_dev *dev, struct resource *res);
int pnp_check_dma(struct pnp_dev * dev, int idx); int pnp_check_dma(struct pnp_dev *dev, struct resource *res);
void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc);
void pnp_init_resource(struct resource *res);
struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
unsigned int type, unsigned int num);
#define PNP_MAX_PORT 40
#define PNP_MAX_MEM 24
#define PNP_MAX_IRQ 2
#define PNP_MAX_DMA 2
struct pnp_resource {
struct resource res;
unsigned int index; /* ISAPNP config register index */
};
struct pnp_resource_table {
struct pnp_resource port[PNP_MAX_PORT];
struct pnp_resource mem[PNP_MAX_MEM];
struct pnp_resource dma[PNP_MAX_DMA];
struct pnp_resource irq[PNP_MAX_IRQ];
};
struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
int flags);
struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
int flags);
struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
resource_size_t start,
resource_size_t end, int flags);
struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
resource_size_t start,
resource_size_t end, int flags);
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/ctype.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pnp.h> #include <linux/pnp.h>
#include "base.h" #include "base.h"
...@@ -100,19 +101,33 @@ static int card_probe(struct pnp_card *card, struct pnp_card_driver *drv) ...@@ -100,19 +101,33 @@ static int card_probe(struct pnp_card *card, struct pnp_card_driver *drv)
* @id: pointer to a pnp_id structure * @id: pointer to a pnp_id structure
* @card: pointer to the desired card * @card: pointer to the desired card
*/ */
int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card) struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id)
{ {
struct pnp_id *ptr; struct pnp_id *dev_id, *ptr;
id->next = NULL; dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
if (!dev_id)
return NULL;
dev_id->id[0] = id[0];
dev_id->id[1] = id[1];
dev_id->id[2] = id[2];
dev_id->id[3] = tolower(id[3]);
dev_id->id[4] = tolower(id[4]);
dev_id->id[5] = tolower(id[5]);
dev_id->id[6] = tolower(id[6]);
dev_id->id[7] = '\0';
dev_id->next = NULL;
ptr = card->id; ptr = card->id;
while (ptr && ptr->next) while (ptr && ptr->next)
ptr = ptr->next; ptr = ptr->next;
if (ptr) if (ptr)
ptr->next = id; ptr->next = dev_id;
else else
card->id = id; card->id = dev_id;
return 0;
return dev_id;
} }
static void pnp_free_card_ids(struct pnp_card *card) static void pnp_free_card_ids(struct pnp_card *card)
...@@ -136,6 +151,31 @@ static void pnp_release_card(struct device *dmdev) ...@@ -136,6 +151,31 @@ static void pnp_release_card(struct device *dmdev)
kfree(card); kfree(card);
} }
struct pnp_card *pnp_alloc_card(struct pnp_protocol *protocol, int id, char *pnpid)
{
struct pnp_card *card;
struct pnp_id *dev_id;
card = kzalloc(sizeof(struct pnp_card), GFP_KERNEL);
if (!card)
return NULL;
card->protocol = protocol;
card->number = id;
card->dev.parent = &card->protocol->dev;
sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number,
card->number);
dev_id = pnp_add_card_id(card, pnpid);
if (!dev_id) {
kfree(card);
return NULL;
}
return card;
}
static ssize_t pnp_show_card_name(struct device *dmdev, static ssize_t pnp_show_card_name(struct device *dmdev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
...@@ -191,9 +231,6 @@ int pnp_add_card(struct pnp_card *card) ...@@ -191,9 +231,6 @@ int pnp_add_card(struct pnp_card *card)
int error; int error;
struct list_head *pos, *temp; struct list_head *pos, *temp;
sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number,
card->number);
card->dev.parent = &card->protocol->dev;
card->dev.bus = NULL; card->dev.bus = NULL;
card->dev.release = &pnp_release_card; card->dev.release = &pnp_release_card;
error = device_register(&card->dev); error = device_register(&card->dev);
......
...@@ -106,18 +106,53 @@ static void pnp_release_device(struct device *dmdev) ...@@ -106,18 +106,53 @@ static void pnp_release_device(struct device *dmdev)
pnp_free_option(dev->independent); pnp_free_option(dev->independent);
pnp_free_option(dev->dependent); pnp_free_option(dev->dependent);
pnp_free_ids(dev); pnp_free_ids(dev);
kfree(dev->res);
kfree(dev); kfree(dev);
} }
int __pnp_add_device(struct pnp_dev *dev) struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid)
{ {
int ret; struct pnp_dev *dev;
struct pnp_id *dev_id;
pnp_fixup_device(dev); dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
if (!dev)
return NULL;
dev->res = kzalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
if (!dev->res) {
kfree(dev);
return NULL;
}
dev->protocol = protocol;
dev->number = id;
dev->dma_mask = DMA_24BIT_MASK;
dev->dev.parent = &dev->protocol->dev;
dev->dev.bus = &pnp_bus_type; dev->dev.bus = &pnp_bus_type;
dev->dev.dma_mask = &dev->dma_mask; dev->dev.dma_mask = &dev->dma_mask;
dev->dma_mask = dev->dev.coherent_dma_mask = DMA_24BIT_MASK; dev->dev.coherent_dma_mask = dev->dma_mask;
dev->dev.release = &pnp_release_device; dev->dev.release = &pnp_release_device;
sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number,
dev->number);
dev_id = pnp_add_id(dev, pnpid);
if (!dev_id) {
kfree(dev->res);
kfree(dev);
return NULL;
}
return dev;
}
int __pnp_add_device(struct pnp_dev *dev)
{
int ret;
pnp_fixup_device(dev);
dev->status = PNP_READY; dev->status = PNP_READY;
spin_lock(&pnp_lock); spin_lock(&pnp_lock);
list_add_tail(&dev->global_list, &pnp_global); list_add_tail(&dev->global_list, &pnp_global);
...@@ -145,9 +180,6 @@ int pnp_add_device(struct pnp_dev *dev) ...@@ -145,9 +180,6 @@ int pnp_add_device(struct pnp_dev *dev)
if (dev->card) if (dev->card)
return -EINVAL; return -EINVAL;
dev->dev.parent = &dev->protocol->dev;
sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number,
dev->number);
ret = __pnp_add_device(dev); ret = __pnp_add_device(dev);
if (ret) if (ret)
return ret; return ret;
......
...@@ -226,22 +226,36 @@ void pnp_unregister_driver(struct pnp_driver *drv) ...@@ -226,22 +226,36 @@ void pnp_unregister_driver(struct pnp_driver *drv)
/** /**
* pnp_add_id - adds an EISA id to the specified device * pnp_add_id - adds an EISA id to the specified device
* @id: pointer to a pnp_id structure
* @dev: pointer to the desired device * @dev: pointer to the desired device
* @id: pointer to an EISA id string
*/ */
int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id)
{ {
struct pnp_id *ptr; struct pnp_id *dev_id, *ptr;
id->next = NULL; dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
if (!dev_id)
return NULL;
dev_id->id[0] = id[0];
dev_id->id[1] = id[1];
dev_id->id[2] = id[2];
dev_id->id[3] = tolower(id[3]);
dev_id->id[4] = tolower(id[4]);
dev_id->id[5] = tolower(id[5]);
dev_id->id[6] = tolower(id[6]);
dev_id->id[7] = '\0';
dev_id->next = NULL;
ptr = dev->id; ptr = dev->id;
while (ptr && ptr->next) while (ptr && ptr->next)
ptr = ptr->next; ptr = ptr->next;
if (ptr) if (ptr)
ptr->next = id; ptr->next = dev_id;
else else
dev->id = id; dev->id = dev_id;
return 0;
return dev_id;
} }
EXPORT_SYMBOL(pnp_register_driver); EXPORT_SYMBOL(pnp_register_driver);
......
...@@ -248,6 +248,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, ...@@ -248,6 +248,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev,
char *buf) char *buf)
{ {
struct pnp_dev *dev = to_pnp_dev(dmdev); struct pnp_dev *dev = to_pnp_dev(dmdev);
struct resource *res;
int i, ret; int i, ret;
pnp_info_buffer_t *buffer; pnp_info_buffer_t *buffer;
...@@ -267,50 +268,46 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, ...@@ -267,50 +268,46 @@ static ssize_t pnp_show_current_resources(struct device *dmdev,
else else
pnp_printf(buffer, "disabled\n"); pnp_printf(buffer, "disabled\n");
for (i = 0; i < PNP_MAX_PORT; i++) { for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
if (pnp_port_valid(dev, i)) { if (pnp_resource_valid(res)) {
pnp_printf(buffer, "io"); pnp_printf(buffer, "io");
if (pnp_port_flags(dev, i) & IORESOURCE_DISABLED) if (res->flags & IORESOURCE_DISABLED)
pnp_printf(buffer, " disabled\n"); pnp_printf(buffer, " disabled\n");
else else
pnp_printf(buffer, " 0x%llx-0x%llx\n", pnp_printf(buffer, " 0x%llx-0x%llx\n",
(unsigned long long) (unsigned long long) res->start,
pnp_port_start(dev, i), (unsigned long long) res->end);
(unsigned long long)pnp_port_end(dev,
i));
} }
} }
for (i = 0; i < PNP_MAX_MEM; i++) { for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
if (pnp_mem_valid(dev, i)) { if (pnp_resource_valid(res)) {
pnp_printf(buffer, "mem"); pnp_printf(buffer, "mem");
if (pnp_mem_flags(dev, i) & IORESOURCE_DISABLED) if (res->flags & IORESOURCE_DISABLED)
pnp_printf(buffer, " disabled\n"); pnp_printf(buffer, " disabled\n");
else else
pnp_printf(buffer, " 0x%llx-0x%llx\n", pnp_printf(buffer, " 0x%llx-0x%llx\n",
(unsigned long long) (unsigned long long) res->start,
pnp_mem_start(dev, i), (unsigned long long) res->end);
(unsigned long long)pnp_mem_end(dev,
i));
} }
} }
for (i = 0; i < PNP_MAX_IRQ; i++) { for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) {
if (pnp_irq_valid(dev, i)) { if (pnp_resource_valid(res)) {
pnp_printf(buffer, "irq"); pnp_printf(buffer, "irq");
if (pnp_irq_flags(dev, i) & IORESOURCE_DISABLED) if (res->flags & IORESOURCE_DISABLED)
pnp_printf(buffer, " disabled\n"); pnp_printf(buffer, " disabled\n");
else else
pnp_printf(buffer, " %lld\n", pnp_printf(buffer, " %lld\n",
(unsigned long long)pnp_irq(dev, i)); (unsigned long long) res->start);
} }
} }
for (i = 0; i < PNP_MAX_DMA; i++) { for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) {
if (pnp_dma_valid(dev, i)) { if (pnp_resource_valid(res)) {
pnp_printf(buffer, "dma"); pnp_printf(buffer, "dma");
if (pnp_dma_flags(dev, i) & IORESOURCE_DISABLED) if (res->flags & IORESOURCE_DISABLED)
pnp_printf(buffer, " disabled\n"); pnp_printf(buffer, " disabled\n");
else else
pnp_printf(buffer, " %lld\n", pnp_printf(buffer, " %lld\n",
(unsigned long long)pnp_dma(dev, i)); (unsigned long long) res->start);
} }
} }
ret = (buffer->curr - buf); ret = (buffer->curr - buf);
...@@ -323,8 +320,10 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, ...@@ -323,8 +320,10 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
const char *ubuf, size_t count) const char *ubuf, size_t count)
{ {
struct pnp_dev *dev = to_pnp_dev(dmdev); struct pnp_dev *dev = to_pnp_dev(dmdev);
struct pnp_resource *pnp_res;
char *buf = (void *)ubuf; char *buf = (void *)ubuf;
int retval = 0; int retval = 0;
resource_size_t start, end;
if (dev->status & PNP_ATTACHED) { if (dev->status & PNP_ATTACHED) {
retval = -EBUSY; retval = -EBUSY;
...@@ -351,20 +350,20 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, ...@@ -351,20 +350,20 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
if (!strnicmp(buf, "auto", 4)) { if (!strnicmp(buf, "auto", 4)) {
if (dev->active) if (dev->active)
goto done; goto done;
pnp_init_resource_table(&dev->res); pnp_init_resources(dev);
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;
pnp_init_resource_table(&dev->res); pnp_init_resources(dev);
goto done; goto done;
} }
if (!strnicmp(buf, "get", 3)) { if (!strnicmp(buf, "get", 3)) {
mutex_lock(&pnp_res_mutex); mutex_lock(&pnp_res_mutex);
if (pnp_can_read(dev)) if (pnp_can_read(dev))
dev->protocol->get(dev, &dev->res); dev->protocol->get(dev);
mutex_unlock(&pnp_res_mutex); mutex_unlock(&pnp_res_mutex);
goto done; goto done;
} }
...@@ -373,7 +372,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, ...@@ -373,7 +372,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
if (dev->active) if (dev->active)
goto done; goto done;
buf += 3; buf += 3;
pnp_init_resource_table(&dev->res); pnp_init_resources(dev);
mutex_lock(&pnp_res_mutex); mutex_lock(&pnp_res_mutex);
while (1) { while (1) {
while (isspace(*buf)) while (isspace(*buf))
...@@ -382,76 +381,60 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, ...@@ -382,76 +381,60 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
buf += 2; buf += 2;
while (isspace(*buf)) while (isspace(*buf))
++buf; ++buf;
dev->res.port_resource[nport].start = start = simple_strtoul(buf, &buf, 0);
simple_strtoul(buf, &buf, 0);
while (isspace(*buf)) while (isspace(*buf))
++buf; ++buf;
if (*buf == '-') { if (*buf == '-') {
buf += 1; buf += 1;
while (isspace(*buf)) while (isspace(*buf))
++buf; ++buf;
dev->res.port_resource[nport].end = end = simple_strtoul(buf, &buf, 0);
simple_strtoul(buf, &buf, 0);
} else } else
dev->res.port_resource[nport].end = end = start;
dev->res.port_resource[nport].start; pnp_res = pnp_add_io_resource(dev, start, end,
dev->res.port_resource[nport].flags = 0);
IORESOURCE_IO; if (pnp_res)
nport++; pnp_res->index = nport++;
if (nport >= PNP_MAX_PORT)
break;
continue; continue;
} }
if (!strnicmp(buf, "mem", 3)) { if (!strnicmp(buf, "mem", 3)) {
buf += 3; buf += 3;
while (isspace(*buf)) while (isspace(*buf))
++buf; ++buf;
dev->res.mem_resource[nmem].start = start = simple_strtoul(buf, &buf, 0);
simple_strtoul(buf, &buf, 0);
while (isspace(*buf)) while (isspace(*buf))
++buf; ++buf;
if (*buf == '-') { if (*buf == '-') {
buf += 1; buf += 1;
while (isspace(*buf)) while (isspace(*buf))
++buf; ++buf;
dev->res.mem_resource[nmem].end = end = simple_strtoul(buf, &buf, 0);
simple_strtoul(buf, &buf, 0);
} else } else
dev->res.mem_resource[nmem].end = end = start;
dev->res.mem_resource[nmem].start; pnp_res = pnp_add_mem_resource(dev, start, end,
dev->res.mem_resource[nmem].flags = 0);
IORESOURCE_MEM; if (pnp_res)
nmem++; pnp_res->index = nmem++;
if (nmem >= PNP_MAX_MEM)
break;
continue; continue;
} }
if (!strnicmp(buf, "irq", 3)) { if (!strnicmp(buf, "irq", 3)) {
buf += 3; buf += 3;
while (isspace(*buf)) while (isspace(*buf))
++buf; ++buf;
dev->res.irq_resource[nirq].start = start = simple_strtoul(buf, &buf, 0);
dev->res.irq_resource[nirq].end = pnp_res = pnp_add_irq_resource(dev, start, 0);
simple_strtoul(buf, &buf, 0); if (pnp_res)
dev->res.irq_resource[nirq].flags = nirq++;
IORESOURCE_IRQ;
nirq++;
if (nirq >= PNP_MAX_IRQ)
break;
continue; continue;
} }
if (!strnicmp(buf, "dma", 3)) { if (!strnicmp(buf, "dma", 3)) {
buf += 3; buf += 3;
while (isspace(*buf)) while (isspace(*buf))
++buf; ++buf;
dev->res.dma_resource[ndma].start = start = simple_strtoul(buf, &buf, 0);
dev->res.dma_resource[ndma].end = pnp_res = pnp_add_dma_resource(dev, start, 0);
simple_strtoul(buf, &buf, 0); if (pnp_res)
dev->res.dma_resource[ndma].flags = pnp_res->index = ndma++;
IORESOURCE_DMA;
ndma++;
if (ndma >= PNP_MAX_DMA)
break;
continue; continue;
} }
break; break;
......
...@@ -5,3 +5,7 @@ ...@@ -5,3 +5,7 @@
isapnp-proc-$(CONFIG_PROC_FS) = proc.o isapnp-proc-$(CONFIG_PROC_FS) = proc.o
obj-y := core.o compat.o $(isapnp-proc-y) obj-y := core.o compat.o $(isapnp-proc-y)
ifeq ($(CONFIG_PNP_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
...@@ -44,6 +44,8 @@ ...@@ -44,6 +44,8 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <asm/io.h> #include <asm/io.h>
#include "../base.h"
#if 0 #if 0
#define ISAPNP_REGION_OK #define ISAPNP_REGION_OK
#endif #endif
...@@ -88,6 +90,14 @@ MODULE_LICENSE("GPL"); ...@@ -88,6 +90,14 @@ MODULE_LICENSE("GPL");
#define _LTAG_MEM32RANGE 0x85 #define _LTAG_MEM32RANGE 0x85
#define _LTAG_FIXEDMEM32RANGE 0x86 #define _LTAG_FIXEDMEM32RANGE 0x86
/* Logical device control and configuration registers */
#define ISAPNP_CFG_ACTIVATE 0x30 /* byte */
#define ISAPNP_CFG_MEM 0x40 /* 4 * dword */
#define ISAPNP_CFG_PORT 0x60 /* 8 * word */
#define ISAPNP_CFG_IRQ 0x70 /* 2 * word */
#define ISAPNP_CFG_DMA 0x74 /* 2 * byte */
/* /*
* Sizes of ISAPNP logical device configuration register sets. * Sizes of ISAPNP logical device configuration register sets.
* See PNP-ISA-v1.0a.pdf, Appendix A. * See PNP-ISA-v1.0a.pdf, Appendix A.
...@@ -387,28 +397,6 @@ static void __init isapnp_skip_bytes(int count) ...@@ -387,28 +397,6 @@ static void __init isapnp_skip_bytes(int count)
isapnp_peek(NULL, count); isapnp_peek(NULL, count);
} }
/*
* Parse EISA id.
*/
static void isapnp_parse_id(struct pnp_dev *dev, unsigned short vendor,
unsigned short device)
{
struct pnp_id *id;
if (!dev)
return;
id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
if (!id)
return;
sprintf(id->id, "%c%c%c%x%x%x%x",
'A' + ((vendor >> 2) & 0x3f) - 1,
'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
'A' + ((vendor >> 8) & 0x1f) - 1,
(device >> 4) & 0x0f,
device & 0x0f, (device >> 12) & 0x0f, (device >> 8) & 0x0f);
pnp_add_id(id, dev);
}
/* /*
* Parse logical device tag. * Parse logical device tag.
*/ */
...@@ -417,30 +405,31 @@ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card, ...@@ -417,30 +405,31 @@ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card,
{ {
unsigned char tmp[6]; unsigned char tmp[6];
struct pnp_dev *dev; struct pnp_dev *dev;
u32 eisa_id;
char id[8];
isapnp_peek(tmp, size); isapnp_peek(tmp, size);
dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); eisa_id = tmp[0] | tmp[1] << 8 | tmp[2] << 16 | tmp[3] << 24;
pnp_eisa_id_to_string(eisa_id, id);
dev = pnp_alloc_dev(&isapnp_protocol, number, id);
if (!dev) if (!dev)
return NULL; return NULL;
dev->number = number;
isapnp_parse_id(dev, (tmp[1] << 8) | tmp[0], (tmp[3] << 8) | tmp[2]);
dev->regs = tmp[4];
dev->card = card; dev->card = card;
if (size > 5)
dev->regs |= tmp[5] << 8;
dev->protocol = &isapnp_protocol;
dev->capabilities |= PNP_CONFIGURABLE; dev->capabilities |= PNP_CONFIGURABLE;
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_resource_table(&dev->res); pnp_init_resources(dev);
return dev; return dev;
} }
/* /*
* Add IRQ resource to resources list. * Add IRQ resource to resources list.
*/ */
static void __init isapnp_parse_irq_resource(struct pnp_option *option, static void __init isapnp_parse_irq_resource(struct pnp_dev *dev,
struct pnp_option *option,
int size) int size)
{ {
unsigned char tmp[3]; unsigned char tmp[3];
...@@ -457,13 +446,14 @@ static void __init isapnp_parse_irq_resource(struct pnp_option *option, ...@@ -457,13 +446,14 @@ static void __init isapnp_parse_irq_resource(struct pnp_option *option,
irq->flags = tmp[2]; irq->flags = tmp[2];
else else
irq->flags = IORESOURCE_IRQ_HIGHEDGE; irq->flags = IORESOURCE_IRQ_HIGHEDGE;
pnp_register_irq_resource(option, irq); pnp_register_irq_resource(dev, option, irq);
} }
/* /*
* Add DMA resource to resources list. * Add DMA resource to resources list.
*/ */
static void __init isapnp_parse_dma_resource(struct pnp_option *option, static void __init isapnp_parse_dma_resource(struct pnp_dev *dev,
struct pnp_option *option,
int size) int size)
{ {
unsigned char tmp[2]; unsigned char tmp[2];
...@@ -475,13 +465,14 @@ static void __init isapnp_parse_dma_resource(struct pnp_option *option, ...@@ -475,13 +465,14 @@ static void __init isapnp_parse_dma_resource(struct pnp_option *option,
return; return;
dma->map = tmp[0]; dma->map = tmp[0];
dma->flags = tmp[1]; dma->flags = tmp[1];
pnp_register_dma_resource(option, dma); pnp_register_dma_resource(dev, option, dma);
} }
/* /*
* Add port resource to resources list. * Add port resource to resources list.
*/ */
static void __init isapnp_parse_port_resource(struct pnp_option *option, static void __init isapnp_parse_port_resource(struct pnp_dev *dev,
struct pnp_option *option,
int size) int size)
{ {
unsigned char tmp[7]; unsigned char tmp[7];
...@@ -496,13 +487,14 @@ static void __init isapnp_parse_port_resource(struct pnp_option *option, ...@@ -496,13 +487,14 @@ static void __init isapnp_parse_port_resource(struct pnp_option *option,
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_register_port_resource(option, port); pnp_register_port_resource(dev, option, port);
} }
/* /*
* Add fixed port resource to resources list. * Add fixed port resource to resources list.
*/ */
static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option, static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev,
struct pnp_option *option,
int size) int size)
{ {
unsigned char tmp[3]; unsigned char tmp[3];
...@@ -516,13 +508,14 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option, ...@@ -516,13 +508,14 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option,
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_register_port_resource(option, port); pnp_register_port_resource(dev, option, port);
} }
/* /*
* Add memory resource to resources list. * Add memory resource to resources list.
*/ */
static void __init isapnp_parse_mem_resource(struct pnp_option *option, static void __init isapnp_parse_mem_resource(struct pnp_dev *dev,
struct pnp_option *option,
int size) int size)
{ {
unsigned char tmp[9]; unsigned char tmp[9];
...@@ -537,13 +530,14 @@ static void __init isapnp_parse_mem_resource(struct pnp_option *option, ...@@ -537,13 +530,14 @@ static void __init isapnp_parse_mem_resource(struct pnp_option *option,
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_register_mem_resource(option, mem); pnp_register_mem_resource(dev, option, mem);
} }
/* /*
* Add 32-bit memory resource to resources list. * Add 32-bit memory resource to resources list.
*/ */
static void __init isapnp_parse_mem32_resource(struct pnp_option *option, static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev,
struct pnp_option *option,
int size) int size)
{ {
unsigned char tmp[17]; unsigned char tmp[17];
...@@ -560,13 +554,14 @@ static void __init isapnp_parse_mem32_resource(struct pnp_option *option, ...@@ -560,13 +554,14 @@ static void __init isapnp_parse_mem32_resource(struct pnp_option *option,
mem->size = mem->size =
(tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13]; (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13];
mem->flags = tmp[0]; mem->flags = tmp[0];
pnp_register_mem_resource(option, mem); pnp_register_mem_resource(dev, option, mem);
} }
/* /*
* Add 32-bit fixed memory resource to resources list. * Add 32-bit fixed memory resource to resources list.
*/ */
static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option, static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev,
struct pnp_option *option,
int size) int size)
{ {
unsigned char tmp[9]; unsigned char tmp[9];
...@@ -581,7 +576,7 @@ static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option, ...@@ -581,7 +576,7 @@ static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option,
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_register_mem_resource(option, mem); pnp_register_mem_resource(dev, option, mem);
} }
/* /*
...@@ -613,6 +608,8 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -613,6 +608,8 @@ static int __init isapnp_create_device(struct pnp_card *card,
unsigned char type, tmp[17]; unsigned char type, tmp[17];
struct pnp_option *option; struct pnp_option *option;
struct pnp_dev *dev; struct pnp_dev *dev;
u32 eisa_id;
char id[8];
if ((dev = isapnp_parse_device(card, size, number++)) == NULL) if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
return 1; return 1;
...@@ -652,8 +649,10 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -652,8 +649,10 @@ static int __init isapnp_create_device(struct pnp_card *card,
case _STAG_COMPATDEVID: case _STAG_COMPATDEVID:
if (size == 4 && compat < DEVICE_COUNT_COMPATIBLE) { if (size == 4 && compat < DEVICE_COUNT_COMPATIBLE) {
isapnp_peek(tmp, 4); isapnp_peek(tmp, 4);
isapnp_parse_id(dev, (tmp[1] << 8) | tmp[0], eisa_id = tmp[0] | tmp[1] << 8 |
(tmp[3] << 8) | tmp[2]); tmp[2] << 16 | tmp[3] << 24;
pnp_eisa_id_to_string(eisa_id, id);
pnp_add_id(dev, id);
compat++; compat++;
size = 0; size = 0;
} }
...@@ -661,13 +660,13 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -661,13 +660,13 @@ 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_parse_irq_resource(option, size); isapnp_parse_irq_resource(dev, 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_parse_dma_resource(option, size); isapnp_parse_dma_resource(dev, option, size);
size = 0; size = 0;
break; break;
case _STAG_STARTDEP: case _STAG_STARTDEP:
...@@ -687,17 +686,18 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -687,17 +686,18 @@ static int __init isapnp_create_device(struct pnp_card *card,
if (size != 0) if (size != 0)
goto __skip; goto __skip;
priority = 0; priority = 0;
dev_dbg(&dev->dev, "end dependent options\n");
break; break;
case _STAG_IOPORT: case _STAG_IOPORT:
if (size != 7) if (size != 7)
goto __skip; goto __skip;
isapnp_parse_port_resource(option, size); isapnp_parse_port_resource(dev, 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_parse_fixed_port_resource(option, size); isapnp_parse_fixed_port_resource(dev, option, size);
size = 0; size = 0;
break; break;
case _STAG_VENDOR: case _STAG_VENDOR:
...@@ -705,7 +705,7 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -705,7 +705,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_parse_mem_resource(option, size); isapnp_parse_mem_resource(dev, option, size);
size = 0; size = 0;
break; break;
case _LTAG_ANSISTR: case _LTAG_ANSISTR:
...@@ -720,13 +720,13 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -720,13 +720,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_parse_mem32_resource(option, size); isapnp_parse_mem32_resource(dev, 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_parse_fixed_mem32_resource(option, size); isapnp_parse_fixed_mem32_resource(dev, option, size);
size = 0; size = 0;
break; break;
case _STAG_END: case _STAG_END:
...@@ -734,9 +734,8 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -734,9 +734,8 @@ static int __init isapnp_create_device(struct pnp_card *card,
isapnp_skip_bytes(size); isapnp_skip_bytes(size);
return 1; return 1;
default: default:
printk(KERN_ERR dev_err(&dev->dev, "unknown tag %#x (card %i), "
"isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n", "ignored\n", type, card->number);
type, dev->number, card->number);
} }
__skip: __skip:
if (size > 0) if (size > 0)
...@@ -789,9 +788,8 @@ static void __init isapnp_parse_resource_map(struct pnp_card *card) ...@@ -789,9 +788,8 @@ static void __init isapnp_parse_resource_map(struct pnp_card *card)
isapnp_skip_bytes(size); isapnp_skip_bytes(size);
return; return;
default: default:
printk(KERN_ERR dev_err(&card->dev, "unknown tag %#x, ignored\n",
"isapnp: unexpected or unknown tag type 0x%x for device %i, ignored\n", type);
type, card->number);
} }
__skip: __skip:
if (size > 0) if (size > 0)
...@@ -821,25 +819,6 @@ static unsigned char __init isapnp_checksum(unsigned char *data) ...@@ -821,25 +819,6 @@ static unsigned char __init isapnp_checksum(unsigned char *data)
return checksum; return checksum;
} }
/*
* Parse EISA id for ISA PnP card.
*/
static void isapnp_parse_card_id(struct pnp_card *card, unsigned short vendor,
unsigned short device)
{
struct pnp_id *id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
if (!id)
return;
sprintf(id->id, "%c%c%c%x%x%x%x",
'A' + ((vendor >> 2) & 0x3f) - 1,
'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
'A' + ((vendor >> 8) & 0x1f) - 1,
(device >> 4) & 0x0f,
device & 0x0f, (device >> 12) & 0x0f, (device >> 8) & 0x0f);
pnp_add_card_id(id, card);
}
/* /*
* Build device list for all present ISA PnP devices. * Build device list for all present ISA PnP devices.
*/ */
...@@ -848,6 +827,8 @@ static int __init isapnp_build_device_list(void) ...@@ -848,6 +827,8 @@ 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;
u32 eisa_id;
char id[8];
isapnp_wait(); isapnp_wait();
isapnp_key(); isapnp_key();
...@@ -855,32 +836,30 @@ static int __init isapnp_build_device_list(void) ...@@ -855,32 +836,30 @@ static int __init isapnp_build_device_list(void)
isapnp_wake(csn); isapnp_wake(csn);
isapnp_peek(header, 9); isapnp_peek(header, 9);
checksum = isapnp_checksum(header); checksum = isapnp_checksum(header);
eisa_id = header[0] | header[1] << 8 |
header[2] << 16 | header[3] << 24;
pnp_eisa_id_to_string(eisa_id, id);
card = pnp_alloc_card(&isapnp_protocol, csn, id);
if (!card)
continue;
#if 0 #if 0
printk(KERN_DEBUG dev_info(&card->dev,
"vendor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", "vendor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
header[0], header[1], header[2], header[3], header[4], header[0], header[1], header[2], header[3], header[4],
header[5], header[6], header[7], header[8]); header[5], header[6], header[7], header[8]);
printk(KERN_DEBUG "checksum = 0x%x\n", checksum); dev_info(&card->dev, "checksum = %#x\n", checksum);
#endif #endif
if ((card =
kzalloc(sizeof(struct pnp_card), GFP_KERNEL)) == NULL)
continue;
card->number = csn;
INIT_LIST_HEAD(&card->devices); INIT_LIST_HEAD(&card->devices);
isapnp_parse_card_id(card, (header[1] << 8) | header[0],
(header[3] << 8) | header[2]);
card->serial = card->serial =
(header[7] << 24) | (header[6] << 16) | (header[5] << 8) | (header[7] << 24) | (header[6] << 16) | (header[5] << 8) |
header[4]; header[4];
isapnp_checksum_value = 0x00; isapnp_checksum_value = 0x00;
isapnp_parse_resource_map(card); isapnp_parse_resource_map(card);
if (isapnp_checksum_value != 0x00) if (isapnp_checksum_value != 0x00)
printk(KERN_ERR dev_err(&card->dev, "invalid checksum %#x\n",
"isapnp: checksum for device %i is not valid (0x%x)\n", isapnp_checksum_value);
csn, isapnp_checksum_value);
card->checksum = isapnp_checksum_value; card->checksum = isapnp_checksum_value;
card->protocol = &isapnp_protocol;
pnp_add_card(card); pnp_add_card(card);
} }
...@@ -947,100 +926,117 @@ EXPORT_SYMBOL(isapnp_cfg_begin); ...@@ -947,100 +926,117 @@ EXPORT_SYMBOL(isapnp_cfg_begin);
EXPORT_SYMBOL(isapnp_cfg_end); EXPORT_SYMBOL(isapnp_cfg_end);
EXPORT_SYMBOL(isapnp_write_byte); EXPORT_SYMBOL(isapnp_write_byte);
static int isapnp_read_resources(struct pnp_dev *dev, static int isapnp_get_resources(struct pnp_dev *dev)
struct pnp_resource_table *res)
{ {
int tmp, ret; struct pnp_resource *pnp_res;
int i, ret;
dev_dbg(&dev->dev, "get resources\n");
pnp_init_resources(dev);
isapnp_cfg_begin(dev->card->number, dev->number);
dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE); dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE);
if (dev->active) { if (!dev->active)
for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) { goto __end;
ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1));
if (!ret) for (i = 0; i < ISAPNP_MAX_PORT; i++) {
continue; ret = isapnp_read_word(ISAPNP_CFG_PORT + (i << 1));
res->port_resource[tmp].start = ret; if (ret) {
res->port_resource[tmp].flags = IORESOURCE_IO; pnp_res = pnp_add_io_resource(dev, ret, ret, 0);
if (pnp_res)
pnp_res->index = i;
} }
for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) { }
ret = for (i = 0; i < ISAPNP_MAX_MEM; i++) {
isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8; ret = isapnp_read_word(ISAPNP_CFG_MEM + (i << 3)) << 8;
if (!ret) if (ret) {
continue; pnp_res = pnp_add_mem_resource(dev, ret, ret, 0);
res->mem_resource[tmp].start = ret; if (pnp_res)
res->mem_resource[tmp].flags = IORESOURCE_MEM; pnp_res->index = i;
} }
for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) { }
ret = for (i = 0; i < ISAPNP_MAX_IRQ; i++) {
(isapnp_read_word(ISAPNP_CFG_IRQ + (tmp << 1)) >> ret = isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1)) >> 8;
8); if (ret) {
if (!ret) pnp_res = pnp_add_irq_resource(dev, ret, 0);
continue; if (pnp_res)
res->irq_resource[tmp].start = pnp_res->index = i;
res->irq_resource[tmp].end = ret;
res->irq_resource[tmp].flags = IORESOURCE_IRQ;
} }
for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) { }
ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp); for (i = 0; i < ISAPNP_MAX_DMA; i++) {
if (ret == 4) ret = isapnp_read_byte(ISAPNP_CFG_DMA + i);
continue; if (ret != 4) {
res->dma_resource[tmp].start = pnp_res = pnp_add_dma_resource(dev, ret, 0);
res->dma_resource[tmp].end = ret; if (pnp_res)
res->dma_resource[tmp].flags = IORESOURCE_DMA; pnp_res->index = i;
} }
} }
return 0;
}
static int isapnp_get_resources(struct pnp_dev *dev,
struct pnp_resource_table *res)
{
int ret;
pnp_init_resource_table(res); __end:
isapnp_cfg_begin(dev->card->number, dev->number);
ret = isapnp_read_resources(dev, res);
isapnp_cfg_end(); isapnp_cfg_end();
return ret; return 0;
} }
static int isapnp_set_resources(struct pnp_dev *dev, static int isapnp_set_resources(struct pnp_dev *dev)
struct pnp_resource_table *res)
{ {
int tmp; struct pnp_resource *pnp_res;
struct resource *res;
int tmp, index;
dev_dbg(&dev->dev, "set resources\n");
isapnp_cfg_begin(dev->card->number, dev->number); isapnp_cfg_begin(dev->card->number, dev->number);
dev->active = 1; dev->active = 1;
for (tmp = 0; for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) {
tmp < ISAPNP_MAX_PORT pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, tmp);
&& (res->port_resource[tmp]. if (!pnp_res)
flags & (IORESOURCE_IO | IORESOURCE_UNSET)) == IORESOURCE_IO; continue;
tmp++) res = &pnp_res->res;
isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1), if (pnp_resource_valid(res)) {
res->port_resource[tmp].start); index = pnp_res->index;
for (tmp = 0; dev_dbg(&dev->dev, " set io %d to %#llx\n",
tmp < ISAPNP_MAX_IRQ index, (unsigned long long) res->start);
&& (res->irq_resource[tmp]. isapnp_write_word(ISAPNP_CFG_PORT + (index << 1),
flags & (IORESOURCE_IRQ | IORESOURCE_UNSET)) == IORESOURCE_IRQ; res->start);
tmp++) { }
int irq = res->irq_resource[tmp].start; }
if (irq == 2) for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) {
irq = 9; pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, tmp);
isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq); if (!pnp_res)
continue;
res = &pnp_res->res;
if (pnp_resource_valid(res)) {
int irq = res->start;
if (irq == 2)
irq = 9;
index = pnp_res->index;
dev_dbg(&dev->dev, " set irq %d to %d\n", index, irq);
isapnp_write_byte(ISAPNP_CFG_IRQ + (index << 1), irq);
}
}
for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) {
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, tmp);
if (!pnp_res)
continue;
res = &pnp_res->res;
if (pnp_resource_valid(res)) {
index = pnp_res->index;
dev_dbg(&dev->dev, " set dma %d to %lld\n",
index, (unsigned long long) res->start);
isapnp_write_byte(ISAPNP_CFG_DMA + index, res->start);
}
}
for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) {
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, tmp);
if (!pnp_res)
continue;
res = &pnp_res->res;
if (pnp_resource_valid(res)) {
index = pnp_res->index;
dev_dbg(&dev->dev, " set mem %d to %#llx\n",
index, (unsigned long long) res->start);
isapnp_write_word(ISAPNP_CFG_MEM + (index << 3),
(res->start >> 8) & 0xffff);
}
} }
for (tmp = 0;
tmp < ISAPNP_MAX_DMA
&& (res->dma_resource[tmp].
flags & (IORESOURCE_DMA | IORESOURCE_UNSET)) == IORESOURCE_DMA;
tmp++)
isapnp_write_byte(ISAPNP_CFG_DMA + tmp,
res->dma_resource[tmp].start);
for (tmp = 0;
tmp < ISAPNP_MAX_MEM
&& (res->mem_resource[tmp].
flags & (IORESOURCE_MEM | IORESOURCE_UNSET)) == IORESOURCE_MEM;
tmp++)
isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3),
(res->mem_resource[tmp].start >> 8) & 0xffff);
/* FIXME: We aren't handling 32bit mems properly here */ /* FIXME: We aren't handling 32bit mems properly here */
isapnp_activate(dev->number); isapnp_activate(dev->number);
isapnp_cfg_end(); isapnp_cfg_end();
...@@ -1138,13 +1134,13 @@ static int __init isapnp_init(void) ...@@ -1138,13 +1134,13 @@ static int __init isapnp_init(void)
protocol_for_each_card(&isapnp_protocol, card) { protocol_for_each_card(&isapnp_protocol, card) {
cards++; cards++;
if (isapnp_verbose) { if (isapnp_verbose) {
printk(KERN_INFO "isapnp: Card '%s'\n", dev_info(&card->dev, "card '%s'\n",
card->name[0] ? card->name : "Unknown"); card->name[0] ? card->name : "unknown");
if (isapnp_verbose < 2) if (isapnp_verbose < 2)
continue; continue;
card_for_each_dev(card, dev) { card_for_each_dev(card, dev) {
printk(KERN_INFO "isapnp: Device '%s'\n", dev_info(&card->dev, "device '%s'\n",
dev->name[0] ? dev->name : "Unknown"); dev->name[0] ? dev->name : "unknown");
} }
} }
} }
......
...@@ -19,100 +19,118 @@ DEFINE_MUTEX(pnp_res_mutex); ...@@ -19,100 +19,118 @@ DEFINE_MUTEX(pnp_res_mutex);
static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
{ {
resource_size_t *start, *end; struct pnp_resource *pnp_res;
unsigned long *flags; struct resource *res;
if (idx >= PNP_MAX_PORT) { pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, idx);
if (!pnp_res) {
dev_err(&dev->dev, "too many I/O port resources\n"); dev_err(&dev->dev, "too many I/O port resources\n");
/* pretend we were successful so at least the manager won't try again */ /* pretend we were successful so at least the manager won't try again */
return 1; return 1;
} }
res = &pnp_res->res;
/* check if this resource has been manually set, if so skip */ /* check if this resource has been manually set, if so skip */
if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO)) if (!(res->flags & IORESOURCE_AUTO)) {
dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx "
"flags %#lx\n", idx, (unsigned long long) res->start,
(unsigned long long) res->end, res->flags);
return 1; return 1;
}
start = &dev->res.port_resource[idx].start;
end = &dev->res.port_resource[idx].end;
flags = &dev->res.port_resource[idx].flags;
/* set the initial values */ /* set the initial values */
*flags |= rule->flags | IORESOURCE_IO; pnp_res->index = idx;
*flags &= ~IORESOURCE_UNSET; res->flags |= rule->flags | IORESOURCE_IO;
res->flags &= ~IORESOURCE_UNSET;
if (!rule->size) { if (!rule->size) {
*flags |= IORESOURCE_DISABLED; res->flags |= IORESOURCE_DISABLED;
dev_dbg(&dev->dev, " io %d disabled\n", idx);
return 1; /* skip disabled resource requests */ return 1; /* skip disabled resource requests */
} }
*start = rule->min; res->start = rule->min;
*end = *start + rule->size - 1; res->end = res->start + rule->size - 1;
/* run through until pnp_check_port is happy */ /* run through until pnp_check_port is happy */
while (!pnp_check_port(dev, idx)) { while (!pnp_check_port(dev, res)) {
*start += rule->align; res->start += rule->align;
*end = *start + rule->size - 1; res->end = res->start + rule->size - 1;
if (*start > rule->max || !rule->align) if (res->start > rule->max || !rule->align) {
dev_dbg(&dev->dev, " couldn't assign io %d\n", idx);
return 0; return 0;
}
} }
dev_dbg(&dev->dev, " assign io %d %#llx-%#llx\n", idx,
(unsigned long long) res->start, (unsigned long long) res->end);
return 1; return 1;
} }
static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
{ {
resource_size_t *start, *end; struct pnp_resource *pnp_res;
unsigned long *flags; struct resource *res;
if (idx >= PNP_MAX_MEM) { pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, idx);
if (!pnp_res) {
dev_err(&dev->dev, "too many memory resources\n"); dev_err(&dev->dev, "too many memory resources\n");
/* pretend we were successful so at least the manager won't try again */ /* pretend we were successful so at least the manager won't try again */
return 1; return 1;
} }
res = &pnp_res->res;
/* check if this resource has been manually set, if so skip */ /* check if this resource has been manually set, if so skip */
if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO)) if (!(res->flags & IORESOURCE_AUTO)) {
dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx "
"flags %#lx\n", idx, (unsigned long long) res->start,
(unsigned long long) res->end, res->flags);
return 1; return 1;
}
start = &dev->res.mem_resource[idx].start;
end = &dev->res.mem_resource[idx].end;
flags = &dev->res.mem_resource[idx].flags;
/* set the initial values */ /* set the initial values */
*flags |= rule->flags | IORESOURCE_MEM; pnp_res->index = idx;
*flags &= ~IORESOURCE_UNSET; res->flags |= rule->flags | IORESOURCE_MEM;
res->flags &= ~IORESOURCE_UNSET;
/* convert pnp flags to standard Linux flags */ /* convert pnp flags to standard Linux flags */
if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) if (!(rule->flags & IORESOURCE_MEM_WRITEABLE))
*flags |= IORESOURCE_READONLY; res->flags |= IORESOURCE_READONLY;
if (rule->flags & IORESOURCE_MEM_CACHEABLE) if (rule->flags & IORESOURCE_MEM_CACHEABLE)
*flags |= IORESOURCE_CACHEABLE; res->flags |= IORESOURCE_CACHEABLE;
if (rule->flags & IORESOURCE_MEM_RANGELENGTH) if (rule->flags & IORESOURCE_MEM_RANGELENGTH)
*flags |= IORESOURCE_RANGELENGTH; res->flags |= IORESOURCE_RANGELENGTH;
if (rule->flags & IORESOURCE_MEM_SHADOWABLE) if (rule->flags & IORESOURCE_MEM_SHADOWABLE)
*flags |= IORESOURCE_SHADOWABLE; res->flags |= IORESOURCE_SHADOWABLE;
if (!rule->size) { if (!rule->size) {
*flags |= IORESOURCE_DISABLED; res->flags |= IORESOURCE_DISABLED;
dev_dbg(&dev->dev, " mem %d disabled\n", idx);
return 1; /* skip disabled resource requests */ return 1; /* skip disabled resource requests */
} }
*start = rule->min; res->start = rule->min;
*end = *start + rule->size - 1; res->end = res->start + rule->size - 1;
/* run through until pnp_check_mem is happy */ /* run through until pnp_check_mem is happy */
while (!pnp_check_mem(dev, idx)) { while (!pnp_check_mem(dev, res)) {
*start += rule->align; res->start += rule->align;
*end = *start + rule->size - 1; res->end = res->start + rule->size - 1;
if (*start > rule->max || !rule->align) if (res->start > rule->max || !rule->align) {
dev_dbg(&dev->dev, " couldn't assign mem %d\n", idx);
return 0; return 0;
}
} }
dev_dbg(&dev->dev, " assign mem %d %#llx-%#llx\n", idx,
(unsigned long long) res->start, (unsigned long long) res->end);
return 1; return 1;
} }
static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
{ {
resource_size_t *start, *end; struct pnp_resource *pnp_res;
unsigned long *flags; struct resource *res;
int i; int i;
/* IRQ priority: this table is good for i386 */ /* IRQ priority: this table is good for i386 */
...@@ -120,49 +138,59 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) ...@@ -120,49 +138,59 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
}; };
if (idx >= PNP_MAX_IRQ) { pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, idx);
if (!pnp_res) {
dev_err(&dev->dev, "too many IRQ resources\n"); dev_err(&dev->dev, "too many IRQ resources\n");
/* pretend we were successful so at least the manager won't try again */ /* pretend we were successful so at least the manager won't try again */
return 1; return 1;
} }
res = &pnp_res->res;
/* check if this resource has been manually set, if so skip */ /* check if this resource has been manually set, if so skip */
if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO)) if (!(res->flags & IORESOURCE_AUTO)) {
dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n",
idx, (int) res->start, res->flags);
return 1; return 1;
}
start = &dev->res.irq_resource[idx].start;
end = &dev->res.irq_resource[idx].end;
flags = &dev->res.irq_resource[idx].flags;
/* set the initial values */ /* set the initial values */
*flags |= rule->flags | IORESOURCE_IRQ; pnp_res->index = idx;
*flags &= ~IORESOURCE_UNSET; res->flags |= rule->flags | IORESOURCE_IRQ;
res->flags &= ~IORESOURCE_UNSET;
if (bitmap_empty(rule->map, PNP_IRQ_NR)) { if (bitmap_empty(rule->map, PNP_IRQ_NR)) {
*flags |= IORESOURCE_DISABLED; res->flags |= IORESOURCE_DISABLED;
dev_dbg(&dev->dev, " irq %d disabled\n", idx);
return 1; /* skip disabled resource requests */ return 1; /* skip disabled resource requests */
} }
/* TBD: need check for >16 IRQ */ /* TBD: need check for >16 IRQ */
*start = find_next_bit(rule->map, PNP_IRQ_NR, 16); res->start = find_next_bit(rule->map, PNP_IRQ_NR, 16);
if (*start < PNP_IRQ_NR) { if (res->start < PNP_IRQ_NR) {
*end = *start; res->end = res->start;
dev_dbg(&dev->dev, " assign irq %d %d\n", idx,
(int) res->start);
return 1; return 1;
} }
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
if (test_bit(xtab[i], rule->map)) { if (test_bit(xtab[i], rule->map)) {
*start = *end = xtab[i]; res->start = res->end = xtab[i];
if (pnp_check_irq(dev, idx)) if (pnp_check_irq(dev, res)) {
dev_dbg(&dev->dev, " assign irq %d %d\n", idx,
(int) res->start);
return 1; return 1;
}
} }
} }
dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx);
return 0; return 0;
} }
static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
{ {
resource_size_t *start, *end; struct pnp_resource *pnp_res;
unsigned long *flags; struct resource *res;
int i; int i;
/* DMA priority: this table is good for i386 */ /* DMA priority: this table is good for i386 */
...@@ -170,71 +198,89 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) ...@@ -170,71 +198,89 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
1, 3, 5, 6, 7, 0, 2, 4 1, 3, 5, 6, 7, 0, 2, 4
}; };
if (idx >= PNP_MAX_DMA) { pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, idx);
if (!pnp_res) {
dev_err(&dev->dev, "too many DMA resources\n"); dev_err(&dev->dev, "too many DMA resources\n");
return; return;
} }
res = &pnp_res->res;
/* check if this resource has been manually set, if so skip */ /* check if this resource has been manually set, if so skip */
if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO)) if (!(res->flags & IORESOURCE_AUTO)) {
dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n",
idx, (int) res->start, res->flags);
return; return;
}
start = &dev->res.dma_resource[idx].start;
end = &dev->res.dma_resource[idx].end;
flags = &dev->res.dma_resource[idx].flags;
/* set the initial values */ /* set the initial values */
*flags |= rule->flags | IORESOURCE_DMA; pnp_res->index = idx;
*flags &= ~IORESOURCE_UNSET; res->flags |= rule->flags | IORESOURCE_DMA;
res->flags &= ~IORESOURCE_UNSET;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
if (rule->map & (1 << xtab[i])) { if (rule->map & (1 << xtab[i])) {
*start = *end = xtab[i]; res->start = res->end = xtab[i];
if (pnp_check_dma(dev, idx)) if (pnp_check_dma(dev, res)) {
dev_dbg(&dev->dev, " assign dma %d %d\n", idx,
(int) res->start);
return; return;
}
} }
} }
#ifdef MAX_DMA_CHANNELS #ifdef MAX_DMA_CHANNELS
*start = *end = MAX_DMA_CHANNELS; res->start = res->end = MAX_DMA_CHANNELS;
#endif #endif
*flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
dev_dbg(&dev->dev, " disable dma %d\n", idx);
}
void pnp_init_resource(struct resource *res)
{
unsigned long type;
type = res->flags & (IORESOURCE_IO | IORESOURCE_MEM |
IORESOURCE_IRQ | IORESOURCE_DMA);
res->name = NULL;
res->flags = type | IORESOURCE_AUTO | IORESOURCE_UNSET;
if (type == IORESOURCE_IRQ || type == IORESOURCE_DMA) {
res->start = -1;
res->end = -1;
} else {
res->start = 0;
res->end = 0;
}
} }
/** /**
* pnp_init_resources - Resets a resource table to default values. * pnp_init_resources - Resets a resource table to default values.
* @table: pointer to the desired resource table * @table: pointer to the desired resource table
*/ */
void pnp_init_resource_table(struct pnp_resource_table *table) void pnp_init_resources(struct pnp_dev *dev)
{ {
struct resource *res;
int idx; int idx;
for (idx = 0; idx < PNP_MAX_IRQ; idx++) { for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
table->irq_resource[idx].name = NULL; res = &dev->res->irq[idx].res;
table->irq_resource[idx].start = -1; res->flags = IORESOURCE_IRQ;
table->irq_resource[idx].end = -1; pnp_init_resource(res);
table->irq_resource[idx].flags =
IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET;
} }
for (idx = 0; idx < PNP_MAX_DMA; idx++) { for (idx = 0; idx < PNP_MAX_DMA; idx++) {
table->dma_resource[idx].name = NULL; res = &dev->res->dma[idx].res;
table->dma_resource[idx].start = -1; res->flags = IORESOURCE_DMA;
table->dma_resource[idx].end = -1; pnp_init_resource(res);
table->dma_resource[idx].flags =
IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET;
} }
for (idx = 0; idx < PNP_MAX_PORT; idx++) { for (idx = 0; idx < PNP_MAX_PORT; idx++) {
table->port_resource[idx].name = NULL; res = &dev->res->port[idx].res;
table->port_resource[idx].start = 0; res->flags = IORESOURCE_IO;
table->port_resource[idx].end = 0; pnp_init_resource(res);
table->port_resource[idx].flags =
IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET;
} }
for (idx = 0; idx < PNP_MAX_MEM; idx++) { for (idx = 0; idx < PNP_MAX_MEM; idx++) {
table->mem_resource[idx].name = NULL; res = &dev->res->mem[idx].res;
table->mem_resource[idx].start = 0; res->flags = IORESOURCE_MEM;
table->mem_resource[idx].end = 0; pnp_init_resource(res);
table->mem_resource[idx].flags =
IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET;
} }
} }
...@@ -242,41 +288,38 @@ void pnp_init_resource_table(struct pnp_resource_table *table) ...@@ -242,41 +288,38 @@ void pnp_init_resource_table(struct pnp_resource_table *table)
* pnp_clean_resources - clears resources that were not manually set * pnp_clean_resources - clears resources that were not manually set
* @res: the resources to clean * @res: the resources to clean
*/ */
static void pnp_clean_resource_table(struct pnp_resource_table *res) static void pnp_clean_resource_table(struct pnp_dev *dev)
{ {
struct resource *res;
int idx; int idx;
for (idx = 0; idx < PNP_MAX_IRQ; idx++) { for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
if (!(res->irq_resource[idx].flags & IORESOURCE_AUTO)) res = &dev->res->irq[idx].res;
continue; if (res->flags & IORESOURCE_AUTO) {
res->irq_resource[idx].start = -1; res->flags = IORESOURCE_IRQ;
res->irq_resource[idx].end = -1; pnp_init_resource(res);
res->irq_resource[idx].flags = }
IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET;
} }
for (idx = 0; idx < PNP_MAX_DMA; idx++) { for (idx = 0; idx < PNP_MAX_DMA; idx++) {
if (!(res->dma_resource[idx].flags & IORESOURCE_AUTO)) res = &dev->res->dma[idx].res;
continue; if (res->flags & IORESOURCE_AUTO) {
res->dma_resource[idx].start = -1; res->flags = IORESOURCE_DMA;
res->dma_resource[idx].end = -1; pnp_init_resource(res);
res->dma_resource[idx].flags = }
IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET;
} }
for (idx = 0; idx < PNP_MAX_PORT; idx++) { for (idx = 0; idx < PNP_MAX_PORT; idx++) {
if (!(res->port_resource[idx].flags & IORESOURCE_AUTO)) res = &dev->res->port[idx].res;
continue; if (res->flags & IORESOURCE_AUTO) {
res->port_resource[idx].start = 0; res->flags = IORESOURCE_IO;
res->port_resource[idx].end = 0; pnp_init_resource(res);
res->port_resource[idx].flags = }
IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET;
} }
for (idx = 0; idx < PNP_MAX_MEM; idx++) { for (idx = 0; idx < PNP_MAX_MEM; idx++) {
if (!(res->mem_resource[idx].flags & IORESOURCE_AUTO)) res = &dev->res->mem[idx].res;
continue; if (res->flags & IORESOURCE_AUTO) {
res->mem_resource[idx].start = 0; res->flags = IORESOURCE_MEM;
res->mem_resource[idx].end = 0; pnp_init_resource(res);
res->mem_resource[idx].flags = }
IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET;
} }
} }
...@@ -298,9 +341,11 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) ...@@ -298,9 +341,11 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
if (!pnp_can_configure(dev)) if (!pnp_can_configure(dev))
return -ENODEV; return -ENODEV;
dbg_pnp_show_resources(dev, "before pnp_assign_resources");
mutex_lock(&pnp_res_mutex); mutex_lock(&pnp_res_mutex);
pnp_clean_resource_table(&dev->res); /* start with a fresh slate */ pnp_clean_resource_table(dev);
if (dev->independent) { if (dev->independent) {
dev_dbg(&dev->dev, "assigning independent options\n");
port = dev->independent->port; port = dev->independent->port;
mem = dev->independent->mem; mem = dev->independent->mem;
irq = dev->independent->irq; irq = dev->independent->irq;
...@@ -333,6 +378,8 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) ...@@ -333,6 +378,8 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
if (depnum) { if (depnum) {
struct pnp_option *dep; struct pnp_option *dep;
int i; int i;
dev_dbg(&dev->dev, "assigning dependent option %d\n", depnum);
for (i = 1, dep = dev->dependent; i < depnum; for (i = 1, dep = dev->dependent; i < depnum;
i++, dep = dep->next) i++, dep = dep->next)
if (!dep) if (!dep)
...@@ -368,67 +415,16 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) ...@@ -368,67 +415,16 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
goto fail; goto fail;
mutex_unlock(&pnp_res_mutex); mutex_unlock(&pnp_res_mutex);
dbg_pnp_show_resources(dev, "after pnp_assign_resources");
return 1; return 1;
fail: fail:
pnp_clean_resource_table(&dev->res); pnp_clean_resource_table(dev);
mutex_unlock(&pnp_res_mutex); mutex_unlock(&pnp_res_mutex);
dbg_pnp_show_resources(dev, "after pnp_assign_resources (failed)");
return 0; return 0;
} }
/**
* pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table
* @dev: pointer to the desired device
* @res: pointer to the new resource config
* @mode: 0 or PNP_CONFIG_FORCE
*
* 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 i;
struct pnp_resource_table *bak;
if (!pnp_can_configure(dev))
return -ENODEV;
bak = pnp_alloc(sizeof(struct pnp_resource_table));
if (!bak)
return -ENOMEM;
*bak = dev->res;
mutex_lock(&pnp_res_mutex);
dev->res = *res;
if (!(mode & PNP_CONFIG_FORCE)) {
for (i = 0; i < PNP_MAX_PORT; i++) {
if (!pnp_check_port(dev, i))
goto fail;
}
for (i = 0; i < PNP_MAX_MEM; i++) {
if (!pnp_check_mem(dev, i))
goto fail;
}
for (i = 0; i < PNP_MAX_IRQ; i++) {
if (!pnp_check_irq(dev, i))
goto fail;
}
for (i = 0; i < PNP_MAX_DMA; i++) {
if (!pnp_check_dma(dev, i))
goto fail;
}
}
mutex_unlock(&pnp_res_mutex);
kfree(bak);
return 0;
fail:
dev->res = *bak;
mutex_unlock(&pnp_res_mutex);
kfree(bak);
return -EINVAL;
}
/** /**
* pnp_auto_config_dev - automatically assigns resources to a device * pnp_auto_config_dev - automatically assigns resources to a device
* @dev: pointer to the desired device * @dev: pointer to the desired device
...@@ -473,7 +469,8 @@ int pnp_start_dev(struct pnp_dev *dev) ...@@ -473,7 +469,8 @@ int pnp_start_dev(struct pnp_dev *dev)
return -EINVAL; return -EINVAL;
} }
if (dev->protocol->set(dev, &dev->res) < 0) { dbg_pnp_show_resources(dev, "pnp_start_dev");
if (dev->protocol->set(dev) < 0) {
dev_err(&dev->dev, "activation failed\n"); dev_err(&dev->dev, "activation failed\n");
return -EIO; return -EIO;
} }
...@@ -549,30 +546,13 @@ int pnp_disable_dev(struct pnp_dev *dev) ...@@ -549,30 +546,13 @@ int pnp_disable_dev(struct pnp_dev *dev)
/* release the resources so that other devices can use them */ /* release the resources so that other devices can use them */
mutex_lock(&pnp_res_mutex); mutex_lock(&pnp_res_mutex);
pnp_clean_resource_table(&dev->res); pnp_clean_resource_table(dev);
mutex_unlock(&pnp_res_mutex); mutex_unlock(&pnp_res_mutex);
return 0; return 0;
} }
/**
* pnp_resource_change - change one resource
* @resource: pointer to resource to be changed
* @start: start of region
* @size: size of region
*/
void pnp_resource_change(struct resource *resource, resource_size_t start,
resource_size_t size)
{
resource->flags &= ~(IORESOURCE_AUTO | IORESOURCE_UNSET);
resource->start = start;
resource->end = start + size - 1;
}
EXPORT_SYMBOL(pnp_manual_config_dev);
EXPORT_SYMBOL(pnp_start_dev); EXPORT_SYMBOL(pnp_start_dev);
EXPORT_SYMBOL(pnp_stop_dev); EXPORT_SYMBOL(pnp_stop_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_init_resource_table);
...@@ -3,3 +3,7 @@ ...@@ -3,3 +3,7 @@
# #
obj-y := core.o rsparser.o obj-y := core.o rsparser.o
ifeq ($(CONFIG_PNP_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <acpi/acpi_bus.h> #include <acpi/acpi_bus.h>
#include <acpi/actypes.h> #include <acpi/actypes.h>
#include "../base.h"
#include "pnpacpi.h" #include "pnpacpi.h"
static int num = 0; static int num = 0;
...@@ -72,40 +73,24 @@ static int __init ispnpidacpi(char *id) ...@@ -72,40 +73,24 @@ static int __init ispnpidacpi(char *id)
return 1; return 1;
} }
static void __init pnpidacpi_to_pnpid(char *id, char *str) static int pnpacpi_get_resources(struct pnp_dev *dev)
{ {
str[0] = id[0]; dev_dbg(&dev->dev, "get resources\n");
str[1] = id[1]; return pnpacpi_parse_allocated_resource(dev);
str[2] = id[2];
str[3] = tolower(id[3]);
str[4] = tolower(id[4]);
str[5] = tolower(id[5]);
str[6] = tolower(id[6]);
str[7] = '\0';
} }
static int pnpacpi_get_resources(struct pnp_dev *dev, static int pnpacpi_set_resources(struct pnp_dev *dev)
struct pnp_resource_table *res)
{
acpi_status status;
status = pnpacpi_parse_allocated_resource((acpi_handle) dev->data,
&dev->res);
return ACPI_FAILURE(status) ? -ENODEV : 0;
}
static int pnpacpi_set_resources(struct pnp_dev *dev,
struct pnp_resource_table *res)
{ {
acpi_handle handle = dev->data; acpi_handle handle = dev->data;
struct acpi_buffer buffer; struct acpi_buffer buffer;
int ret = 0; int ret;
acpi_status status; acpi_status status;
ret = pnpacpi_build_resource_template(handle, &buffer); dev_dbg(&dev->dev, "set resources\n");
ret = pnpacpi_build_resource_template(dev, &buffer);
if (ret) if (ret)
return ret; return ret;
ret = pnpacpi_encode_resources(res, &buffer); ret = pnpacpi_encode_resources(dev, &buffer);
if (ret) { if (ret) {
kfree(buffer.pointer); kfree(buffer.pointer);
return ret; return ret;
...@@ -163,7 +148,6 @@ static int __init pnpacpi_add_device(struct acpi_device *device) ...@@ -163,7 +148,6 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
{ {
acpi_handle temp = NULL; acpi_handle temp = NULL;
acpi_status status; acpi_status status;
struct pnp_id *dev_id;
struct pnp_dev *dev; struct pnp_dev *dev;
status = acpi_get_handle(device->handle, "_CRS", &temp); status = acpi_get_handle(device->handle, "_CRS", &temp);
...@@ -171,11 +155,10 @@ static int __init pnpacpi_add_device(struct acpi_device *device) ...@@ -171,11 +155,10 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
is_exclusive_device(device)) is_exclusive_device(device))
return 0; return 0;
dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device));
if (!dev) { if (!dev)
pnp_err("Out of memory");
return -ENOMEM; return -ENOMEM;
}
dev->data = device->handle; dev->data = device->handle;
/* .enabled means the device can decode the resources */ /* .enabled means the device can decode the resources */
dev->active = device->status.enabled; dev->active = device->status.enabled;
...@@ -191,44 +174,17 @@ static int __init pnpacpi_add_device(struct acpi_device *device) ...@@ -191,44 +174,17 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
if (ACPI_SUCCESS(status)) if (ACPI_SUCCESS(status))
dev->capabilities |= PNP_DISABLE; dev->capabilities |= PNP_DISABLE;
dev->protocol = &pnpacpi_protocol;
if (strlen(acpi_device_name(device))) if (strlen(acpi_device_name(device)))
strncpy(dev->name, acpi_device_name(device), sizeof(dev->name)); strncpy(dev->name, acpi_device_name(device), sizeof(dev->name));
else else
strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name)); strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name));
dev->number = num; if (dev->active)
pnpacpi_parse_allocated_resource(dev);
/* set the initial values for the PnP device */
dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
if (!dev_id)
goto err;
pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id);
pnp_add_id(dev_id, dev);
if (dev->active) {
/* parse allocated resource */
status = pnpacpi_parse_allocated_resource(device->handle,
&dev->res);
if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
pnp_err("PnPACPI: METHOD_NAME__CRS failure for %s",
dev_id->id);
goto err1;
}
}
if (dev->capabilities & PNP_CONFIGURABLE) { if (dev->capabilities & PNP_CONFIGURABLE)
status = pnpacpi_parse_resource_option_data(device->handle, pnpacpi_parse_resource_option_data(dev);
dev);
if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
pnp_err("PnPACPI: METHOD_NAME__PRS failure for %s",
dev_id->id);
goto err1;
}
}
/* parse compatible ids */
if (device->flags.compatible_ids) { if (device->flags.compatible_ids) {
struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
int i; int i;
...@@ -236,27 +192,17 @@ static int __init pnpacpi_add_device(struct acpi_device *device) ...@@ -236,27 +192,17 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
for (i = 0; i < cid_list->count; i++) { for (i = 0; i < cid_list->count; i++) {
if (!ispnpidacpi(cid_list->id[i].value)) if (!ispnpidacpi(cid_list->id[i].value))
continue; continue;
dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); pnp_add_id(dev, cid_list->id[i].value);
if (!dev_id)
continue;
pnpidacpi_to_pnpid(cid_list->id[i].value, dev_id->id);
pnp_add_id(dev_id, dev);
} }
} }
/* clear out the damaged flags */ /* clear out the damaged flags */
if (!dev->active) if (!dev->active)
pnp_init_resource_table(&dev->res); pnp_init_resources(dev);
pnp_add_device(dev); pnp_add_device(dev);
num++; num++;
return AE_OK; return AE_OK;
err1:
kfree(dev_id);
err:
kfree(dev);
return -EINVAL;
} }
static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle, static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle,
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/pnp.h> #include <linux/pnp.h>
acpi_status pnpacpi_parse_allocated_resource(acpi_handle, struct pnp_resource_table*); int pnpacpi_parse_allocated_resource(struct pnp_dev *);
acpi_status pnpacpi_parse_resource_option_data(acpi_handle, struct pnp_dev*); int pnpacpi_parse_resource_option_data(struct pnp_dev *);
int pnpacpi_encode_resources(struct pnp_resource_table *, struct acpi_buffer *); int pnpacpi_encode_resources(struct pnp_dev *, struct acpi_buffer *);
int pnpacpi_build_resource_template(acpi_handle, struct acpi_buffer*); int pnpacpi_build_resource_template(struct pnp_dev *, struct acpi_buffer *);
#endif #endif
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/pnp.h>
#include "../base.h"
#include "pnpacpi.h" #include "pnpacpi.h"
#ifdef CONFIG_IA64 #ifdef CONFIG_IA64
...@@ -32,19 +34,26 @@ ...@@ -32,19 +34,26 @@
/* /*
* Allocated Resources * Allocated Resources
*/ */
static int irq_flags(int triggering, int polarity) static int irq_flags(int triggering, int polarity, int shareable)
{ {
int flags;
if (triggering == ACPI_LEVEL_SENSITIVE) { if (triggering == ACPI_LEVEL_SENSITIVE) {
if (polarity == ACPI_ACTIVE_LOW) if (polarity == ACPI_ACTIVE_LOW)
return IORESOURCE_IRQ_LOWLEVEL; flags = IORESOURCE_IRQ_LOWLEVEL;
else else
return IORESOURCE_IRQ_HIGHLEVEL; flags = IORESOURCE_IRQ_HIGHLEVEL;
} else { } else {
if (polarity == ACPI_ACTIVE_LOW) if (polarity == ACPI_ACTIVE_LOW)
return IORESOURCE_IRQ_LOWEDGE; flags = IORESOURCE_IRQ_LOWEDGE;
else else
return IORESOURCE_IRQ_HIGHEDGE; flags = IORESOURCE_IRQ_HIGHEDGE;
} }
if (shareable)
flags |= IORESOURCE_IRQ_SHAREABLE;
return flags;
} }
static void decode_irq_flags(int flag, int *triggering, int *polarity) static void decode_irq_flags(int flag, int *triggering, int *polarity)
...@@ -69,29 +78,16 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity) ...@@ -69,29 +78,16 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity)
} }
} }
static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
u32 gsi, int triggering, u32 gsi, int triggering,
int polarity, int shareable) int polarity, int shareable)
{ {
int i = 0; int irq, flags;
int irq;
int p, t; int p, t;
static unsigned char warned;
if (!valid_IRQ(gsi)) if (!valid_IRQ(gsi))
return; return;
while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) &&
i < PNP_MAX_IRQ)
i++;
if (i >= PNP_MAX_IRQ) {
if (!warned) {
printk(KERN_WARNING "pnpacpi: exceeded the max number"
" of IRQ resources: %d\n", PNP_MAX_IRQ);
warned = 1;
}
return;
}
/* /*
* in IO-APIC mode, use overrided attribute. Two reasons: * in IO-APIC mode, use overrided attribute. Two reasons:
* 1. BIOS bug in DSDT * 1. BIOS bug in DSDT
...@@ -102,27 +98,21 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, ...@@ -102,27 +98,21 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
if (triggering != t || polarity != p) { if (triggering != t || polarity != p) {
pnp_warn("IRQ %d override to %s, %s", dev_warn(&dev->dev, "IRQ %d override to %s, %s\n",
gsi, t ? "edge":"level", p ? "low":"high"); gsi, t ? "edge":"level", p ? "low":"high");
triggering = t; triggering = t;
polarity = p; polarity = p;
} }
} }
res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag flags = irq_flags(triggering, polarity, shareable);
res->irq_resource[i].flags |= irq_flags(triggering, polarity);
irq = acpi_register_gsi(gsi, triggering, polarity); irq = acpi_register_gsi(gsi, triggering, polarity);
if (irq < 0) { if (irq >= 0)
res->irq_resource[i].flags |= IORESOURCE_DISABLED; pcibios_penalize_isa_irq(irq, 1);
return; else
} flags |= IORESOURCE_DISABLED;
if (shareable)
res->irq_resource[i].flags |= IORESOURCE_IRQ_SHAREABLE;
res->irq_resource[i].start = irq; pnp_add_irq_resource(dev, irq, flags);
res->irq_resource[i].end = irq;
pcibios_penalize_isa_irq(irq, 1);
} }
static int dma_flags(int type, int bus_master, int transfer) static int dma_flags(int type, int bus_master, int transfer)
...@@ -168,88 +158,36 @@ static int dma_flags(int type, int bus_master, int transfer) ...@@ -168,88 +158,36 @@ static int dma_flags(int type, int bus_master, int transfer)
return flags; return flags;
} }
static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
u32 dma, int type, u64 len, int io_decode)
int bus_master, int transfer)
{ {
int i = 0; int flags = 0;
static unsigned char warned; u64 end = start + len - 1;
while (i < PNP_MAX_DMA &&
!(res->dma_resource[i].flags & IORESOURCE_UNSET))
i++;
if (i < PNP_MAX_DMA) {
res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag
res->dma_resource[i].flags |=
dma_flags(type, bus_master, transfer);
if (dma == -1) {
res->dma_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
res->dma_resource[i].start = dma;
res->dma_resource[i].end = dma;
} else if (!warned) {
printk(KERN_WARNING "pnpacpi: exceeded the max number of DMA "
"resources: %d \n", PNP_MAX_DMA);
warned = 1;
}
}
static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, if (io_decode == ACPI_DECODE_16)
u64 io, u64 len, int io_decode) flags |= PNP_PORT_FLAG_16BITADDR;
{ if (len == 0 || end >= 0x10003)
int i = 0; flags |= IORESOURCE_DISABLED;
static unsigned char warned;
while (!(res->port_resource[i].flags & IORESOURCE_UNSET) && pnp_add_io_resource(dev, start, end, flags);
i < PNP_MAX_PORT)
i++;
if (i < PNP_MAX_PORT) {
res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag
if (io_decode == ACPI_DECODE_16)
res->port_resource[i].flags |= PNP_PORT_FLAG_16BITADDR;
if (len <= 0 || (io + len - 1) >= 0x10003) {
res->port_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
res->port_resource[i].start = io;
res->port_resource[i].end = io + len - 1;
} else if (!warned) {
printk(KERN_WARNING "pnpacpi: exceeded the max number of IO "
"resources: %d \n", PNP_MAX_PORT);
warned = 1;
}
} }
static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res, static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
u64 mem, u64 len, u64 start, u64 len,
int write_protect) int write_protect)
{ {
int i = 0; int flags = 0;
static unsigned char warned; u64 end = start + len - 1;
while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) && if (len == 0)
(i < PNP_MAX_MEM)) flags |= IORESOURCE_DISABLED;
i++; if (write_protect == ACPI_READ_WRITE_MEMORY)
if (i < PNP_MAX_MEM) { flags |= IORESOURCE_MEM_WRITEABLE;
res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag
if (len <= 0) { pnp_add_mem_resource(dev, start, end, flags);
res->mem_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
if (write_protect == ACPI_READ_WRITE_MEMORY)
res->mem_resource[i].flags |= IORESOURCE_MEM_WRITEABLE;
res->mem_resource[i].start = mem;
res->mem_resource[i].end = mem + len - 1;
} else if (!warned) {
printk(KERN_WARNING "pnpacpi: exceeded the max number of mem "
"resources: %d\n", PNP_MAX_MEM);
warned = 1;
}
} }
static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table, static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
struct acpi_resource *res) struct acpi_resource *res)
{ {
struct acpi_resource_address64 addr, *p = &addr; struct acpi_resource_address64 addr, *p = &addr;
...@@ -257,7 +195,7 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res ...@@ -257,7 +195,7 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res
status = acpi_resource_to_address64(res, p); status = acpi_resource_to_address64(res, p);
if (!ACPI_SUCCESS(status)) { if (!ACPI_SUCCESS(status)) {
pnp_warn("PnPACPI: failed to convert resource type %d", dev_warn(&dev->dev, "failed to convert resource type %d\n",
res->type); res->type);
return; return;
} }
...@@ -266,11 +204,11 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res ...@@ -266,11 +204,11 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res
return; return;
if (p->resource_type == ACPI_MEMORY_RANGE) if (p->resource_type == ACPI_MEMORY_RANGE)
pnpacpi_parse_allocated_memresource(res_table, pnpacpi_parse_allocated_memresource(dev,
p->minimum, p->address_length, p->minimum, p->address_length,
p->info.mem.write_protect); p->info.mem.write_protect);
else if (p->resource_type == ACPI_IO_RANGE) else if (p->resource_type == ACPI_IO_RANGE)
pnpacpi_parse_allocated_ioresource(res_table, pnpacpi_parse_allocated_ioresource(dev,
p->minimum, p->address_length, p->minimum, p->address_length,
p->granularity == 0xfff ? ACPI_DECODE_10 : p->granularity == 0xfff ? ACPI_DECODE_10 :
ACPI_DECODE_16); ACPI_DECODE_16);
...@@ -279,8 +217,16 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res ...@@ -279,8 +217,16 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res
static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
void *data) void *data)
{ {
struct pnp_resource_table *res_table = data; struct pnp_dev *dev = data;
int i; struct acpi_resource_irq *irq;
struct acpi_resource_dma *dma;
struct acpi_resource_io *io;
struct acpi_resource_fixed_io *fixed_io;
struct acpi_resource_memory24 *memory24;
struct acpi_resource_memory32 *memory32;
struct acpi_resource_fixed_memory32 *fixed_memory32;
struct acpi_resource_extended_irq *extended_irq;
int i, flags;
switch (res->type) { switch (res->type) {
case ACPI_RESOURCE_TYPE_IRQ: case ACPI_RESOURCE_TYPE_IRQ:
...@@ -288,29 +234,33 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, ...@@ -288,29 +234,33 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
* Per spec, only one interrupt per descriptor is allowed in * Per spec, only one interrupt per descriptor is allowed in
* _CRS, but some firmware violates this, so parse them all. * _CRS, but some firmware violates this, so parse them all.
*/ */
for (i = 0; i < res->data.irq.interrupt_count; i++) { irq = &res->data.irq;
pnpacpi_parse_allocated_irqresource(res_table, for (i = 0; i < irq->interrupt_count; i++) {
res->data.irq.interrupts[i], pnpacpi_parse_allocated_irqresource(dev,
res->data.irq.triggering, irq->interrupts[i],
res->data.irq.polarity, irq->triggering,
res->data.irq.sharable); irq->polarity,
irq->sharable);
} }
break; break;
case ACPI_RESOURCE_TYPE_DMA: case ACPI_RESOURCE_TYPE_DMA:
if (res->data.dma.channel_count > 0) dma = &res->data.dma;
pnpacpi_parse_allocated_dmaresource(res_table, if (dma->channel_count > 0) {
res->data.dma.channels[0], flags = dma_flags(dma->type, dma->bus_master,
res->data.dma.type, dma->transfer);
res->data.dma.bus_master, if (dma->channels[0] == (u8) -1)
res->data.dma.transfer); flags |= IORESOURCE_DISABLED;
pnp_add_dma_resource(dev, dma->channels[0], flags);
}
break; break;
case ACPI_RESOURCE_TYPE_IO: case ACPI_RESOURCE_TYPE_IO:
pnpacpi_parse_allocated_ioresource(res_table, io = &res->data.io;
res->data.io.minimum, pnpacpi_parse_allocated_ioresource(dev,
res->data.io.address_length, io->minimum,
res->data.io.io_decode); io->address_length,
io->io_decode);
break; break;
case ACPI_RESOURCE_TYPE_START_DEPENDENT: case ACPI_RESOURCE_TYPE_START_DEPENDENT:
...@@ -318,9 +268,10 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, ...@@ -318,9 +268,10 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
break; break;
case ACPI_RESOURCE_TYPE_FIXED_IO: case ACPI_RESOURCE_TYPE_FIXED_IO:
pnpacpi_parse_allocated_ioresource(res_table, fixed_io = &res->data.fixed_io;
res->data.fixed_io.address, pnpacpi_parse_allocated_ioresource(dev,
res->data.fixed_io.address_length, fixed_io->address,
fixed_io->address_length,
ACPI_DECODE_10); ACPI_DECODE_10);
break; break;
...@@ -331,27 +282,30 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, ...@@ -331,27 +282,30 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
break; break;
case ACPI_RESOURCE_TYPE_MEMORY24: case ACPI_RESOURCE_TYPE_MEMORY24:
pnpacpi_parse_allocated_memresource(res_table, memory24 = &res->data.memory24;
res->data.memory24.minimum, pnpacpi_parse_allocated_memresource(dev,
res->data.memory24.address_length, memory24->minimum,
res->data.memory24.write_protect); memory24->address_length,
memory24->write_protect);
break; break;
case ACPI_RESOURCE_TYPE_MEMORY32: case ACPI_RESOURCE_TYPE_MEMORY32:
pnpacpi_parse_allocated_memresource(res_table, memory32 = &res->data.memory32;
res->data.memory32.minimum, pnpacpi_parse_allocated_memresource(dev,
res->data.memory32.address_length, memory32->minimum,
res->data.memory32.write_protect); memory32->address_length,
memory32->write_protect);
break; break;
case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
pnpacpi_parse_allocated_memresource(res_table, fixed_memory32 = &res->data.fixed_memory32;
res->data.fixed_memory32.address, pnpacpi_parse_allocated_memresource(dev,
res->data.fixed_memory32.address_length, fixed_memory32->address,
res->data.fixed_memory32.write_protect); fixed_memory32->address_length,
fixed_memory32->write_protect);
break; break;
case ACPI_RESOURCE_TYPE_ADDRESS16: case ACPI_RESOURCE_TYPE_ADDRESS16:
case ACPI_RESOURCE_TYPE_ADDRESS32: case ACPI_RESOURCE_TYPE_ADDRESS32:
case ACPI_RESOURCE_TYPE_ADDRESS64: case ACPI_RESOURCE_TYPE_ADDRESS64:
pnpacpi_parse_allocated_address_space(res_table, res); pnpacpi_parse_allocated_address_space(dev, res);
break; break;
case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
...@@ -360,15 +314,16 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, ...@@ -360,15 +314,16 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
break; break;
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
if (res->data.extended_irq.producer_consumer == ACPI_PRODUCER) extended_irq = &res->data.extended_irq;
if (extended_irq->producer_consumer == ACPI_PRODUCER)
return AE_OK; return AE_OK;
for (i = 0; i < res->data.extended_irq.interrupt_count; i++) { for (i = 0; i < extended_irq->interrupt_count; i++) {
pnpacpi_parse_allocated_irqresource(res_table, pnpacpi_parse_allocated_irqresource(dev,
res->data.extended_irq.interrupts[i], extended_irq->interrupts[i],
res->data.extended_irq.triggering, extended_irq->triggering,
res->data.extended_irq.polarity, extended_irq->polarity,
res->data.extended_irq.sharable); extended_irq->sharable);
} }
break; break;
...@@ -376,24 +331,36 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, ...@@ -376,24 +331,36 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
break; break;
default: default:
pnp_warn("PnPACPI: unknown resource type %d", res->type); dev_warn(&dev->dev, "unknown resource type %d in _CRS\n",
res->type);
return AE_ERROR; return AE_ERROR;
} }
return AE_OK; return AE_OK;
} }
acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
struct pnp_resource_table * res)
{ {
/* Blank the resource table values */ acpi_handle handle = dev->data;
pnp_init_resource_table(res); acpi_status status;
dev_dbg(&dev->dev, "parse allocated resources\n");
return acpi_walk_resources(handle, METHOD_NAME__CRS, pnp_init_resources(dev);
pnpacpi_allocated_resource, res);
status = acpi_walk_resources(handle, METHOD_NAME__CRS,
pnpacpi_allocated_resource, dev);
if (ACPI_FAILURE(status)) {
if (status != AE_NOT_FOUND)
dev_err(&dev->dev, "can't evaluate _CRS: %d", status);
return -EPERM;
}
return 0;
} }
static __init void pnpacpi_parse_dma_option(struct pnp_option *option, static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
struct pnp_option *option,
struct acpi_resource_dma *p) struct acpi_resource_dma *p)
{ {
int i; int i;
...@@ -410,10 +377,11 @@ static __init void pnpacpi_parse_dma_option(struct pnp_option *option, ...@@ -410,10 +377,11 @@ static __init void pnpacpi_parse_dma_option(struct pnp_option *option,
dma->flags = dma_flags(p->type, p->bus_master, p->transfer); dma->flags = dma_flags(p->type, p->bus_master, p->transfer);
pnp_register_dma_resource(option, dma); pnp_register_dma_resource(dev, option, dma);
} }
static __init void pnpacpi_parse_irq_option(struct pnp_option *option, static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
struct pnp_option *option,
struct acpi_resource_irq *p) struct acpi_resource_irq *p)
{ {
int i; int i;
...@@ -428,12 +396,13 @@ static __init void pnpacpi_parse_irq_option(struct pnp_option *option, ...@@ -428,12 +396,13 @@ static __init void pnpacpi_parse_irq_option(struct pnp_option *option,
for (i = 0; i < p->interrupt_count; i++) for (i = 0; i < p->interrupt_count; i++)
if (p->interrupts[i]) if (p->interrupts[i])
__set_bit(p->interrupts[i], irq->map); __set_bit(p->interrupts[i], irq->map);
irq->flags = irq_flags(p->triggering, p->polarity); irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
pnp_register_irq_resource(option, irq); pnp_register_irq_resource(dev, option, irq);
} }
static __init void pnpacpi_parse_ext_irq_option(struct pnp_option *option, static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
struct pnp_option *option,
struct acpi_resource_extended_irq *p) struct acpi_resource_extended_irq *p)
{ {
int i; int i;
...@@ -448,12 +417,13 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_option *option, ...@@ -448,12 +417,13 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
for (i = 0; i < p->interrupt_count; i++) for (i = 0; i < p->interrupt_count; i++)
if (p->interrupts[i]) if (p->interrupts[i])
__set_bit(p->interrupts[i], irq->map); __set_bit(p->interrupts[i], irq->map);
irq->flags = irq_flags(p->triggering, p->polarity); irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
pnp_register_irq_resource(option, irq); pnp_register_irq_resource(dev, option, irq);
} }
static __init void pnpacpi_parse_port_option(struct pnp_option *option, static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
struct pnp_option *option,
struct acpi_resource_io *io) struct acpi_resource_io *io)
{ {
struct pnp_port *port; struct pnp_port *port;
...@@ -469,10 +439,11 @@ static __init void pnpacpi_parse_port_option(struct pnp_option *option, ...@@ -469,10 +439,11 @@ static __init void pnpacpi_parse_port_option(struct pnp_option *option,
port->size = io->address_length; port->size = io->address_length;
port->flags = ACPI_DECODE_16 == io->io_decode ? port->flags = ACPI_DECODE_16 == io->io_decode ?
PNP_PORT_FLAG_16BITADDR : 0; PNP_PORT_FLAG_16BITADDR : 0;
pnp_register_port_resource(option, port); pnp_register_port_resource(dev, option, port);
} }
static __init void pnpacpi_parse_fixed_port_option(struct pnp_option *option, static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
struct pnp_option *option,
struct acpi_resource_fixed_io *io) struct acpi_resource_fixed_io *io)
{ {
struct pnp_port *port; struct pnp_port *port;
...@@ -486,10 +457,11 @@ static __init void pnpacpi_parse_fixed_port_option(struct pnp_option *option, ...@@ -486,10 +457,11 @@ static __init void pnpacpi_parse_fixed_port_option(struct pnp_option *option,
port->size = io->address_length; port->size = io->address_length;
port->align = 0; port->align = 0;
port->flags = PNP_PORT_FLAG_FIXED; port->flags = PNP_PORT_FLAG_FIXED;
pnp_register_port_resource(option, port); pnp_register_port_resource(dev, option, port);
} }
static __init void pnpacpi_parse_mem24_option(struct pnp_option *option, static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
struct pnp_option *option,
struct acpi_resource_memory24 *p) struct acpi_resource_memory24 *p)
{ {
struct pnp_mem *mem; struct pnp_mem *mem;
...@@ -507,10 +479,11 @@ static __init void pnpacpi_parse_mem24_option(struct pnp_option *option, ...@@ -507,10 +479,11 @@ static __init void pnpacpi_parse_mem24_option(struct pnp_option *option,
mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
IORESOURCE_MEM_WRITEABLE : 0; IORESOURCE_MEM_WRITEABLE : 0;
pnp_register_mem_resource(option, mem); pnp_register_mem_resource(dev, option, mem);
} }
static __init void pnpacpi_parse_mem32_option(struct pnp_option *option, static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
struct pnp_option *option,
struct acpi_resource_memory32 *p) struct acpi_resource_memory32 *p)
{ {
struct pnp_mem *mem; struct pnp_mem *mem;
...@@ -528,10 +501,11 @@ static __init void pnpacpi_parse_mem32_option(struct pnp_option *option, ...@@ -528,10 +501,11 @@ static __init void pnpacpi_parse_mem32_option(struct pnp_option *option,
mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
IORESOURCE_MEM_WRITEABLE : 0; IORESOURCE_MEM_WRITEABLE : 0;
pnp_register_mem_resource(option, mem); pnp_register_mem_resource(dev, option, mem);
} }
static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
struct pnp_option *option,
struct acpi_resource_fixed_memory32 *p) struct acpi_resource_fixed_memory32 *p)
{ {
struct pnp_mem *mem; struct pnp_mem *mem;
...@@ -548,10 +522,11 @@ static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, ...@@ -548,10 +522,11 @@ static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
IORESOURCE_MEM_WRITEABLE : 0; IORESOURCE_MEM_WRITEABLE : 0;
pnp_register_mem_resource(option, mem); pnp_register_mem_resource(dev, option, mem);
} }
static __init void pnpacpi_parse_address_option(struct pnp_option *option, static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
struct pnp_option *option,
struct acpi_resource *r) struct acpi_resource *r)
{ {
struct acpi_resource_address64 addr, *p = &addr; struct acpi_resource_address64 addr, *p = &addr;
...@@ -579,7 +554,7 @@ static __init void pnpacpi_parse_address_option(struct pnp_option *option, ...@@ -579,7 +554,7 @@ static __init void pnpacpi_parse_address_option(struct pnp_option *option,
mem->flags = (p->info.mem.write_protect == mem->flags = (p->info.mem.write_protect ==
ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE
: 0; : 0;
pnp_register_mem_resource(option, mem); pnp_register_mem_resource(dev, option, mem);
} else if (p->resource_type == ACPI_IO_RANGE) { } else if (p->resource_type == ACPI_IO_RANGE) {
port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
if (!port) if (!port)
...@@ -588,7 +563,7 @@ static __init void pnpacpi_parse_address_option(struct pnp_option *option, ...@@ -588,7 +563,7 @@ static __init void pnpacpi_parse_address_option(struct pnp_option *option,
port->size = p->address_length; port->size = p->address_length;
port->align = 0; port->align = 0;
port->flags = PNP_PORT_FLAG_FIXED; port->flags = PNP_PORT_FLAG_FIXED;
pnp_register_port_resource(option, port); pnp_register_port_resource(dev, option, port);
} }
} }
...@@ -608,11 +583,11 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, ...@@ -608,11 +583,11 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
switch (res->type) { switch (res->type) {
case ACPI_RESOURCE_TYPE_IRQ: case ACPI_RESOURCE_TYPE_IRQ:
pnpacpi_parse_irq_option(option, &res->data.irq); pnpacpi_parse_irq_option(dev, option, &res->data.irq);
break; break;
case ACPI_RESOURCE_TYPE_DMA: case ACPI_RESOURCE_TYPE_DMA:
pnpacpi_parse_dma_option(option, &res->data.dma); pnpacpi_parse_dma_option(dev, option, &res->data.dma);
break; break;
case ACPI_RESOURCE_TYPE_START_DEPENDENT: case ACPI_RESOURCE_TYPE_START_DEPENDENT:
...@@ -642,19 +617,22 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, ...@@ -642,19 +617,22 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
case ACPI_RESOURCE_TYPE_END_DEPENDENT: case ACPI_RESOURCE_TYPE_END_DEPENDENT:
/*only one EndDependentFn is allowed */ /*only one EndDependentFn is allowed */
if (!parse_data->option_independent) { if (!parse_data->option_independent) {
pnp_warn("PnPACPI: more than one EndDependentFn"); dev_warn(&dev->dev, "more than one EndDependentFn "
"in _PRS\n");
return AE_ERROR; return AE_ERROR;
} }
parse_data->option = parse_data->option_independent; parse_data->option = parse_data->option_independent;
parse_data->option_independent = NULL; parse_data->option_independent = NULL;
dev_dbg(&dev->dev, "end dependent options\n");
break; break;
case ACPI_RESOURCE_TYPE_IO: case ACPI_RESOURCE_TYPE_IO:
pnpacpi_parse_port_option(option, &res->data.io); pnpacpi_parse_port_option(dev, option, &res->data.io);
break; break;
case ACPI_RESOURCE_TYPE_FIXED_IO: case ACPI_RESOURCE_TYPE_FIXED_IO:
pnpacpi_parse_fixed_port_option(option, &res->data.fixed_io); pnpacpi_parse_fixed_port_option(dev, option,
&res->data.fixed_io);
break; break;
case ACPI_RESOURCE_TYPE_VENDOR: case ACPI_RESOURCE_TYPE_VENDOR:
...@@ -662,57 +640,67 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, ...@@ -662,57 +640,67 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
break; break;
case ACPI_RESOURCE_TYPE_MEMORY24: case ACPI_RESOURCE_TYPE_MEMORY24:
pnpacpi_parse_mem24_option(option, &res->data.memory24); pnpacpi_parse_mem24_option(dev, option, &res->data.memory24);
break; break;
case ACPI_RESOURCE_TYPE_MEMORY32: case ACPI_RESOURCE_TYPE_MEMORY32:
pnpacpi_parse_mem32_option(option, &res->data.memory32); pnpacpi_parse_mem32_option(dev, option, &res->data.memory32);
break; break;
case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
pnpacpi_parse_fixed_mem32_option(option, pnpacpi_parse_fixed_mem32_option(dev, option,
&res->data.fixed_memory32); &res->data.fixed_memory32);
break; break;
case ACPI_RESOURCE_TYPE_ADDRESS16: case ACPI_RESOURCE_TYPE_ADDRESS16:
case ACPI_RESOURCE_TYPE_ADDRESS32: case ACPI_RESOURCE_TYPE_ADDRESS32:
case ACPI_RESOURCE_TYPE_ADDRESS64: case ACPI_RESOURCE_TYPE_ADDRESS64:
pnpacpi_parse_address_option(option, res); pnpacpi_parse_address_option(dev, option, res);
break; break;
case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
break; break;
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
pnpacpi_parse_ext_irq_option(option, &res->data.extended_irq); pnpacpi_parse_ext_irq_option(dev, option,
&res->data.extended_irq);
break; break;
case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
break; break;
default: default:
pnp_warn("PnPACPI: unknown resource type %d", res->type); dev_warn(&dev->dev, "unknown resource type %d in _PRS\n",
res->type);
return AE_ERROR; return AE_ERROR;
} }
return AE_OK; return AE_OK;
} }
acpi_status __init pnpacpi_parse_resource_option_data(acpi_handle handle, int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
struct pnp_dev *dev)
{ {
acpi_handle handle = dev->data;
acpi_status status; acpi_status status;
struct acpipnp_parse_option_s parse_data; struct acpipnp_parse_option_s parse_data;
dev_dbg(&dev->dev, "parse resource options\n");
parse_data.option = pnp_register_independent_option(dev); parse_data.option = pnp_register_independent_option(dev);
if (!parse_data.option) if (!parse_data.option)
return AE_ERROR; return -ENOMEM;
parse_data.option_independent = parse_data.option; parse_data.option_independent = parse_data.option;
parse_data.dev = dev; parse_data.dev = dev;
status = acpi_walk_resources(handle, METHOD_NAME__PRS, status = acpi_walk_resources(handle, METHOD_NAME__PRS,
pnpacpi_option_resource, &parse_data); pnpacpi_option_resource, &parse_data);
return status; if (ACPI_FAILURE(status)) {
if (status != AE_NOT_FOUND)
dev_err(&dev->dev, "can't evaluate _PRS: %d", status);
return -EPERM;
}
return 0;
} }
static int pnpacpi_supported_resource(struct acpi_resource *res) static int pnpacpi_supported_resource(struct acpi_resource *res)
...@@ -760,9 +748,10 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data) ...@@ -760,9 +748,10 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
return AE_OK; return AE_OK;
} }
int pnpacpi_build_resource_template(acpi_handle handle, int pnpacpi_build_resource_template(struct pnp_dev *dev,
struct acpi_buffer *buffer) struct acpi_buffer *buffer)
{ {
acpi_handle handle = dev->data;
struct acpi_resource *resource; struct acpi_resource *resource;
int res_cnt = 0; int res_cnt = 0;
acpi_status status; acpi_status status;
...@@ -770,7 +759,7 @@ int pnpacpi_build_resource_template(acpi_handle handle, ...@@ -770,7 +759,7 @@ int pnpacpi_build_resource_template(acpi_handle handle,
status = acpi_walk_resources(handle, METHOD_NAME__CRS, status = acpi_walk_resources(handle, METHOD_NAME__CRS,
pnpacpi_count_resources, &res_cnt); pnpacpi_count_resources, &res_cnt);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
pnp_err("Evaluate _CRS failed"); dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);
return -EINVAL; return -EINVAL;
} }
if (!res_cnt) if (!res_cnt)
...@@ -779,13 +768,13 @@ int pnpacpi_build_resource_template(acpi_handle handle, ...@@ -779,13 +768,13 @@ int pnpacpi_build_resource_template(acpi_handle handle,
buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL); buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL);
if (!buffer->pointer) if (!buffer->pointer)
return -ENOMEM; return -ENOMEM;
pnp_dbg("Res cnt %d", res_cnt);
resource = (struct acpi_resource *)buffer->pointer; resource = (struct acpi_resource *)buffer->pointer;
status = acpi_walk_resources(handle, METHOD_NAME__CRS, status = acpi_walk_resources(handle, METHOD_NAME__CRS,
pnpacpi_type_resources, &resource); pnpacpi_type_resources, &resource);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
kfree(buffer->pointer); kfree(buffer->pointer);
pnp_err("Evaluate _CRS failed"); dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);
return -EINVAL; return -EINVAL;
} }
/* resource will pointer the end resource now */ /* resource will pointer the end resource now */
...@@ -794,129 +783,184 @@ int pnpacpi_build_resource_template(acpi_handle handle, ...@@ -794,129 +783,184 @@ int pnpacpi_build_resource_template(acpi_handle handle,
return 0; return 0;
} }
static void pnpacpi_encode_irq(struct acpi_resource *resource, static void pnpacpi_encode_irq(struct pnp_dev *dev,
struct acpi_resource *resource,
struct resource *p) struct resource *p)
{ {
struct acpi_resource_irq *irq = &resource->data.irq;
int triggering, polarity; int triggering, polarity;
decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
resource->data.irq.triggering = triggering; irq->triggering = triggering;
resource->data.irq.polarity = polarity; irq->polarity = polarity;
if (triggering == ACPI_EDGE_SENSITIVE) if (triggering == ACPI_EDGE_SENSITIVE)
resource->data.irq.sharable = ACPI_EXCLUSIVE; irq->sharable = ACPI_EXCLUSIVE;
else else
resource->data.irq.sharable = ACPI_SHARED; irq->sharable = ACPI_SHARED;
resource->data.irq.interrupt_count = 1; irq->interrupt_count = 1;
resource->data.irq.interrupts[0] = p->start; irq->interrupts[0] = p->start;
dev_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start,
triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
polarity == ACPI_ACTIVE_LOW ? "low" : "high",
irq->sharable == ACPI_SHARED ? "shared" : "exclusive");
} }
static void pnpacpi_encode_ext_irq(struct acpi_resource *resource, static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
struct acpi_resource *resource,
struct resource *p) struct resource *p)
{ {
struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
int triggering, polarity; int triggering, polarity;
decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
resource->data.extended_irq.producer_consumer = ACPI_CONSUMER; extended_irq->producer_consumer = ACPI_CONSUMER;
resource->data.extended_irq.triggering = triggering; extended_irq->triggering = triggering;
resource->data.extended_irq.polarity = polarity; extended_irq->polarity = polarity;
if (triggering == ACPI_EDGE_SENSITIVE) if (triggering == ACPI_EDGE_SENSITIVE)
resource->data.irq.sharable = ACPI_EXCLUSIVE; extended_irq->sharable = ACPI_EXCLUSIVE;
else else
resource->data.irq.sharable = ACPI_SHARED; extended_irq->sharable = ACPI_SHARED;
resource->data.extended_irq.interrupt_count = 1; extended_irq->interrupt_count = 1;
resource->data.extended_irq.interrupts[0] = p->start; extended_irq->interrupts[0] = p->start;
dev_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start,
triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
polarity == ACPI_ACTIVE_LOW ? "low" : "high",
extended_irq->sharable == ACPI_SHARED ? "shared" : "exclusive");
} }
static void pnpacpi_encode_dma(struct acpi_resource *resource, static void pnpacpi_encode_dma(struct pnp_dev *dev,
struct acpi_resource *resource,
struct resource *p) struct resource *p)
{ {
struct acpi_resource_dma *dma = &resource->data.dma;
/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
switch (p->flags & IORESOURCE_DMA_SPEED_MASK) { switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
case IORESOURCE_DMA_TYPEA: case IORESOURCE_DMA_TYPEA:
resource->data.dma.type = ACPI_TYPE_A; dma->type = ACPI_TYPE_A;
break; break;
case IORESOURCE_DMA_TYPEB: case IORESOURCE_DMA_TYPEB:
resource->data.dma.type = ACPI_TYPE_B; dma->type = ACPI_TYPE_B;
break; break;
case IORESOURCE_DMA_TYPEF: case IORESOURCE_DMA_TYPEF:
resource->data.dma.type = ACPI_TYPE_F; dma->type = ACPI_TYPE_F;
break; break;
default: default:
resource->data.dma.type = ACPI_COMPATIBILITY; dma->type = ACPI_COMPATIBILITY;
} }
switch (p->flags & IORESOURCE_DMA_TYPE_MASK) { switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {
case IORESOURCE_DMA_8BIT: case IORESOURCE_DMA_8BIT:
resource->data.dma.transfer = ACPI_TRANSFER_8; dma->transfer = ACPI_TRANSFER_8;
break; break;
case IORESOURCE_DMA_8AND16BIT: case IORESOURCE_DMA_8AND16BIT:
resource->data.dma.transfer = ACPI_TRANSFER_8_16; dma->transfer = ACPI_TRANSFER_8_16;
break; break;
default: default:
resource->data.dma.transfer = ACPI_TRANSFER_16; dma->transfer = ACPI_TRANSFER_16;
} }
resource->data.dma.bus_master = !!(p->flags & IORESOURCE_DMA_MASTER); dma->bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
resource->data.dma.channel_count = 1; dma->channel_count = 1;
resource->data.dma.channels[0] = p->start; dma->channels[0] = p->start;
dev_dbg(&dev->dev, " encode dma %d "
"type %#x transfer %#x master %d\n",
(int) p->start, dma->type, dma->transfer, dma->bus_master);
} }
static void pnpacpi_encode_io(struct acpi_resource *resource, static void pnpacpi_encode_io(struct pnp_dev *dev,
struct acpi_resource *resource,
struct resource *p) struct resource *p)
{ {
struct acpi_resource_io *io = &resource->data.io;
/* Note: pnp_assign_port will copy pnp_port->flags into p->flags */ /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ? io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
ACPI_DECODE_16 : ACPI_DECODE_10; ACPI_DECODE_16 : ACPI_DECODE_10;
resource->data.io.minimum = p->start; io->minimum = p->start;
resource->data.io.maximum = p->end; io->maximum = p->end;
resource->data.io.alignment = 0; /* Correct? */ io->alignment = 0; /* Correct? */
resource->data.io.address_length = p->end - p->start + 1; io->address_length = p->end - p->start + 1;
dev_dbg(&dev->dev, " encode io %#llx-%#llx decode %#x\n",
(unsigned long long) p->start, (unsigned long long) p->end,
io->io_decode);
} }
static void pnpacpi_encode_fixed_io(struct acpi_resource *resource, static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
struct acpi_resource *resource,
struct resource *p) struct resource *p)
{ {
resource->data.fixed_io.address = p->start; struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io;
resource->data.fixed_io.address_length = p->end - p->start + 1;
fixed_io->address = p->start;
fixed_io->address_length = p->end - p->start + 1;
dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n",
(unsigned long long) p->start, (unsigned long long) p->end);
} }
static void pnpacpi_encode_mem24(struct acpi_resource *resource, static void pnpacpi_encode_mem24(struct pnp_dev *dev,
struct acpi_resource *resource,
struct resource *p) struct resource *p)
{ {
struct acpi_resource_memory24 *memory24 = &resource->data.memory24;
/* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */ /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
resource->data.memory24.write_protect = memory24->write_protect =
(p->flags & IORESOURCE_MEM_WRITEABLE) ? (p->flags & IORESOURCE_MEM_WRITEABLE) ?
ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
resource->data.memory24.minimum = p->start; memory24->minimum = p->start;
resource->data.memory24.maximum = p->end; memory24->maximum = p->end;
resource->data.memory24.alignment = 0; memory24->alignment = 0;
resource->data.memory24.address_length = p->end - p->start + 1; memory24->address_length = p->end - p->start + 1;
dev_dbg(&dev->dev, " encode mem24 %#llx-%#llx write_protect %#x\n",
(unsigned long long) p->start, (unsigned long long) p->end,
memory24->write_protect);
} }
static void pnpacpi_encode_mem32(struct acpi_resource *resource, static void pnpacpi_encode_mem32(struct pnp_dev *dev,
struct acpi_resource *resource,
struct resource *p) struct resource *p)
{ {
resource->data.memory32.write_protect = struct acpi_resource_memory32 *memory32 = &resource->data.memory32;
memory32->write_protect =
(p->flags & IORESOURCE_MEM_WRITEABLE) ? (p->flags & IORESOURCE_MEM_WRITEABLE) ?
ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
resource->data.memory32.minimum = p->start; memory32->minimum = p->start;
resource->data.memory32.maximum = p->end; memory32->maximum = p->end;
resource->data.memory32.alignment = 0; memory32->alignment = 0;
resource->data.memory32.address_length = p->end - p->start + 1; memory32->address_length = p->end - p->start + 1;
dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx write_protect %#x\n",
(unsigned long long) p->start, (unsigned long long) p->end,
memory32->write_protect);
} }
static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource, static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
struct acpi_resource *resource,
struct resource *p) struct resource *p)
{ {
resource->data.fixed_memory32.write_protect = struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32;
fixed_memory32->write_protect =
(p->flags & IORESOURCE_MEM_WRITEABLE) ? (p->flags & IORESOURCE_MEM_WRITEABLE) ?
ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
resource->data.fixed_memory32.address = p->start; fixed_memory32->address = p->start;
resource->data.fixed_memory32.address_length = p->end - p->start + 1; fixed_memory32->address_length = p->end - p->start + 1;
dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx "
"write_protect %#x\n",
(unsigned long long) p->start, (unsigned long long) p->end,
fixed_memory32->write_protect);
} }
int pnpacpi_encode_resources(struct pnp_resource_table *res_table, int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer)
struct acpi_buffer *buffer)
{ {
int i = 0; int i = 0;
/* pnpacpi_build_resource_template allocates extra mem */ /* pnpacpi_build_resource_template allocates extra mem */
...@@ -924,58 +968,48 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table, ...@@ -924,58 +968,48 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
struct acpi_resource *resource = buffer->pointer; struct acpi_resource *resource = buffer->pointer;
int port = 0, irq = 0, dma = 0, mem = 0; int port = 0, irq = 0, dma = 0, mem = 0;
pnp_dbg("res cnt %d", res_cnt); dev_dbg(&dev->dev, "encode %d resources\n", res_cnt);
while (i < res_cnt) { while (i < res_cnt) {
switch (resource->type) { switch (resource->type) {
case ACPI_RESOURCE_TYPE_IRQ: case ACPI_RESOURCE_TYPE_IRQ:
pnp_dbg("Encode irq"); pnpacpi_encode_irq(dev, resource,
pnpacpi_encode_irq(resource, pnp_get_resource(dev, IORESOURCE_IRQ, irq));
&res_table->irq_resource[irq]);
irq++; irq++;
break; break;
case ACPI_RESOURCE_TYPE_DMA: case ACPI_RESOURCE_TYPE_DMA:
pnp_dbg("Encode dma"); pnpacpi_encode_dma(dev, resource,
pnpacpi_encode_dma(resource, pnp_get_resource(dev, IORESOURCE_DMA, dma));
&res_table->dma_resource[dma]);
dma++; dma++;
break; break;
case ACPI_RESOURCE_TYPE_IO: case ACPI_RESOURCE_TYPE_IO:
pnp_dbg("Encode io"); pnpacpi_encode_io(dev, resource,
pnpacpi_encode_io(resource, pnp_get_resource(dev, IORESOURCE_IO, port));
&res_table->port_resource[port]);
port++; port++;
break; break;
case ACPI_RESOURCE_TYPE_FIXED_IO: case ACPI_RESOURCE_TYPE_FIXED_IO:
pnp_dbg("Encode fixed io"); pnpacpi_encode_fixed_io(dev, resource,
pnpacpi_encode_fixed_io(resource, pnp_get_resource(dev, IORESOURCE_IO, port));
&res_table->
port_resource[port]);
port++; port++;
break; break;
case ACPI_RESOURCE_TYPE_MEMORY24: case ACPI_RESOURCE_TYPE_MEMORY24:
pnp_dbg("Encode mem24"); pnpacpi_encode_mem24(dev, resource,
pnpacpi_encode_mem24(resource, pnp_get_resource(dev, IORESOURCE_MEM, mem));
&res_table->mem_resource[mem]);
mem++; mem++;
break; break;
case ACPI_RESOURCE_TYPE_MEMORY32: case ACPI_RESOURCE_TYPE_MEMORY32:
pnp_dbg("Encode mem32"); pnpacpi_encode_mem32(dev, resource,
pnpacpi_encode_mem32(resource, pnp_get_resource(dev, IORESOURCE_MEM, mem));
&res_table->mem_resource[mem]);
mem++; mem++;
break; break;
case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
pnp_dbg("Encode fixed mem32"); pnpacpi_encode_fixed_mem32(dev, resource,
pnpacpi_encode_fixed_mem32(resource, pnp_get_resource(dev, IORESOURCE_MEM, mem));
&res_table->
mem_resource[mem]);
mem++; mem++;
break; break;
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
pnp_dbg("Encode ext irq"); pnpacpi_encode_ext_irq(dev, resource,
pnpacpi_encode_ext_irq(resource, pnp_get_resource(dev, IORESOURCE_IRQ, irq));
&res_table->irq_resource[irq]);
irq++; irq++;
break; break;
case ACPI_RESOURCE_TYPE_START_DEPENDENT: case ACPI_RESOURCE_TYPE_START_DEPENDENT:
...@@ -988,7 +1022,8 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table, ...@@ -988,7 +1022,8 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
default: /* other type */ default: /* other type */
pnp_warn("unknown resource type %d", resource->type); dev_warn(&dev->dev, "can't encode unknown resource "
"type %d\n", resource->type);
return -EINVAL; return -EINVAL;
} }
resource++; resource++;
......
...@@ -5,3 +5,7 @@ ...@@ -5,3 +5,7 @@
pnpbios-proc-$(CONFIG_PNPBIOS_PROC_FS) = proc.o pnpbios-proc-$(CONFIG_PNPBIOS_PROC_FS) = proc.o
obj-y := core.o bioscalls.o rsparser.o $(pnpbios-proc-y) obj-y := core.o bioscalls.o rsparser.o $(pnpbios-proc-y)
ifeq ($(CONFIG_PNP_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/pnpbios.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/pnp.h> #include <linux/pnp.h>
#include <linux/mm.h> #include <linux/mm.h>
......
...@@ -50,7 +50,6 @@ ...@@ -50,7 +50,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/pnpbios.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/pnp.h> #include <linux/pnp.h>
#include <linux/mm.h> #include <linux/mm.h>
...@@ -69,6 +68,7 @@ ...@@ -69,6 +68,7 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include "../base.h"
#include "pnpbios.h" #include "pnpbios.h"
/* /*
...@@ -203,8 +203,7 @@ static int pnp_dock_thread(void *unused) ...@@ -203,8 +203,7 @@ static int pnp_dock_thread(void *unused)
#endif /* CONFIG_HOTPLUG */ #endif /* CONFIG_HOTPLUG */
static int pnpbios_get_resources(struct pnp_dev *dev, static int pnpbios_get_resources(struct pnp_dev *dev)
struct pnp_resource_table *res)
{ {
u8 nodenum = dev->number; u8 nodenum = dev->number;
struct pnp_bios_node *node; struct pnp_bios_node *node;
...@@ -212,6 +211,7 @@ static int pnpbios_get_resources(struct pnp_dev *dev, ...@@ -212,6 +211,7 @@ static int pnpbios_get_resources(struct pnp_dev *dev,
if (!pnpbios_is_dynamic(dev)) if (!pnpbios_is_dynamic(dev))
return -EPERM; return -EPERM;
dev_dbg(&dev->dev, "get resources\n");
node = kzalloc(node_info.max_node_size, GFP_KERNEL); node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node) if (!node)
return -1; return -1;
...@@ -219,14 +219,13 @@ static int pnpbios_get_resources(struct pnp_dev *dev, ...@@ -219,14 +219,13 @@ static int pnpbios_get_resources(struct pnp_dev *dev,
kfree(node); kfree(node);
return -ENODEV; return -ENODEV;
} }
pnpbios_read_resources_from_node(res, node); pnpbios_read_resources_from_node(dev, node);
dev->active = pnp_is_active(dev); dev->active = pnp_is_active(dev);
kfree(node); kfree(node);
return 0; return 0;
} }
static int pnpbios_set_resources(struct pnp_dev *dev, static int pnpbios_set_resources(struct pnp_dev *dev)
struct pnp_resource_table *res)
{ {
u8 nodenum = dev->number; u8 nodenum = dev->number;
struct pnp_bios_node *node; struct pnp_bios_node *node;
...@@ -235,6 +234,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev, ...@@ -235,6 +234,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev,
if (!pnpbios_is_dynamic(dev)) if (!pnpbios_is_dynamic(dev))
return -EPERM; return -EPERM;
dev_dbg(&dev->dev, "set resources\n");
node = kzalloc(node_info.max_node_size, GFP_KERNEL); node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node) if (!node)
return -1; return -1;
...@@ -242,7 +242,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev, ...@@ -242,7 +242,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev,
kfree(node); kfree(node);
return -ENODEV; return -ENODEV;
} }
if (pnpbios_write_resources_to_node(res, node) < 0) { if (pnpbios_write_resources_to_node(dev, node) < 0) {
kfree(node); kfree(node);
return -1; return -1;
} }
...@@ -317,7 +317,6 @@ static int __init insert_device(struct pnp_bios_node *node) ...@@ -317,7 +317,6 @@ static int __init insert_device(struct pnp_bios_node *node)
{ {
struct list_head *pos; struct list_head *pos;
struct pnp_dev *dev; struct pnp_dev *dev;
struct pnp_id *dev_id;
char id[8]; char id[8];
/* check if the device is already added */ /* check if the device is already added */
...@@ -327,20 +326,11 @@ static int __init insert_device(struct pnp_bios_node *node) ...@@ -327,20 +326,11 @@ static int __init insert_device(struct pnp_bios_node *node)
return -1; return -1;
} }
dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); pnp_eisa_id_to_string(node->eisa_id & PNP_EISA_ID_MASK, id);
dev = pnp_alloc_dev(&pnpbios_protocol, node->handle, id);
if (!dev) if (!dev)
return -1; return -1;
dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
if (!dev_id) {
kfree(dev);
return -1;
}
dev->number = node->handle;
pnpid32_to_pnpid(node->eisa_id, id);
memcpy(dev_id->id, id, 7);
pnp_add_id(dev_id, dev);
pnpbios_parse_data_stream(dev, node); pnpbios_parse_data_stream(dev, node);
dev->active = pnp_is_active(dev); dev->active = pnp_is_active(dev);
dev->flags = node->flags; dev->flags = node->flags;
...@@ -353,11 +343,10 @@ static int __init insert_device(struct pnp_bios_node *node) ...@@ -353,11 +343,10 @@ static int __init insert_device(struct pnp_bios_node *node)
dev->capabilities |= PNP_WRITE; dev->capabilities |= PNP_WRITE;
if (dev->flags & PNPBIOS_REMOVABLE) if (dev->flags & PNPBIOS_REMOVABLE)
dev->capabilities |= PNP_REMOVABLE; dev->capabilities |= PNP_REMOVABLE;
dev->protocol = &pnpbios_protocol;
/* clear out the damaged flags */ /* clear out the damaged flags */
if (!dev->active) if (!dev->active)
pnp_init_resource_table(&dev->res); pnp_init_resources(dev);
pnp_add_device(dev); pnp_add_device(dev);
pnpbios_interface_attach_device(node); pnpbios_interface_attach_device(node);
......
...@@ -2,6 +2,142 @@ ...@@ -2,6 +2,142 @@
* pnpbios.h - contains local definitions * pnpbios.h - contains local definitions
*/ */
/*
* Include file for the interface to a PnP BIOS
*
* Original BIOS code (C) 1998 Christian Schmidt (chr.schmidt@tu-bs.de)
* PnP handler parts (c) 1998 Tom Lees <tom@lpsg.demon.co.uk>
* Minor reorganizations by David Hinds <dahinds@users.sourceforge.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Return codes
*/
#define PNP_SUCCESS 0x00
#define PNP_NOT_SET_STATICALLY 0x7f
#define PNP_UNKNOWN_FUNCTION 0x81
#define PNP_FUNCTION_NOT_SUPPORTED 0x82
#define PNP_INVALID_HANDLE 0x83
#define PNP_BAD_PARAMETER 0x84
#define PNP_SET_FAILED 0x85
#define PNP_EVENTS_NOT_PENDING 0x86
#define PNP_SYSTEM_NOT_DOCKED 0x87
#define PNP_NO_ISA_PNP_CARDS 0x88
#define PNP_UNABLE_TO_DETERMINE_DOCK_CAPABILITIES 0x89
#define PNP_CONFIG_CHANGE_FAILED_NO_BATTERY 0x8a
#define PNP_CONFIG_CHANGE_FAILED_RESOURCE_CONFLICT 0x8b
#define PNP_BUFFER_TOO_SMALL 0x8c
#define PNP_USE_ESCD_SUPPORT 0x8d
#define PNP_MESSAGE_NOT_SUPPORTED 0x8e
#define PNP_HARDWARE_ERROR 0x8f
#define ESCD_SUCCESS 0x00
#define ESCD_IO_ERROR_READING 0x55
#define ESCD_INVALID 0x56
#define ESCD_BUFFER_TOO_SMALL 0x59
#define ESCD_NVRAM_TOO_SMALL 0x5a
#define ESCD_FUNCTION_NOT_SUPPORTED 0x81
/*
* Events that can be received by "get event"
*/
#define PNPEV_ABOUT_TO_CHANGE_CONFIG 0x0001
#define PNPEV_DOCK_CHANGED 0x0002
#define PNPEV_SYSTEM_DEVICE_CHANGED 0x0003
#define PNPEV_CONFIG_CHANGED_FAILED 0x0004
#define PNPEV_UNKNOWN_SYSTEM_EVENT 0xffff
/* 0x8000 through 0xfffe are OEM defined */
/*
* Messages that should be sent through "send message"
*/
#define PNPMSG_OK 0x00
#define PNPMSG_ABORT 0x01
#define PNPMSG_UNDOCK_DEFAULT_ACTION 0x40
#define PNPMSG_POWER_OFF 0x41
#define PNPMSG_PNP_OS_ACTIVE 0x42
#define PNPMSG_PNP_OS_INACTIVE 0x43
/*
* Plug and Play BIOS flags
*/
#define PNPBIOS_NO_DISABLE 0x0001
#define PNPBIOS_NO_CONFIG 0x0002
#define PNPBIOS_OUTPUT 0x0004
#define PNPBIOS_INPUT 0x0008
#define PNPBIOS_BOOTABLE 0x0010
#define PNPBIOS_DOCK 0x0020
#define PNPBIOS_REMOVABLE 0x0040
#define pnpbios_is_static(x) (((x)->flags & 0x0100) == 0x0000)
#define pnpbios_is_dynamic(x) ((x)->flags & 0x0080)
/*
* Function Parameters
*/
#define PNPMODE_STATIC 1
#define PNPMODE_DYNAMIC 0
/* 0x8000 through 0xffff are OEM defined */
#pragma pack(1)
struct pnp_dev_node_info {
__u16 no_nodes;
__u16 max_node_size;
};
struct pnp_docking_station_info {
__u32 location_id;
__u32 serial;
__u16 capabilities;
};
struct pnp_isa_config_struc {
__u8 revision;
__u8 no_csns;
__u16 isa_rd_data_port;
__u16 reserved;
};
struct escd_info_struc {
__u16 min_escd_write_size;
__u16 escd_size;
__u32 nv_storage_base;
};
struct pnp_bios_node {
__u16 size;
__u8 handle;
__u32 eisa_id;
__u8 type_code[3];
__u16 flags;
__u8 data[0];
};
#pragma pack()
/* non-exported */
extern struct pnp_dev_node_info node_info;
extern int pnp_bios_dev_node_info(struct pnp_dev_node_info *data);
extern int pnp_bios_get_dev_node(u8 *nodenum, char config,
struct pnp_bios_node *data);
extern int pnp_bios_set_dev_node(u8 nodenum, char config,
struct pnp_bios_node *data);
extern int pnp_bios_get_stat_res(char *info);
extern int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data);
extern int pnp_bios_escd_info(struct escd_info_struc *data);
extern int pnp_bios_read_escd(char *data, u32 nvram_base);
extern int pnp_bios_dock_station_info(struct pnp_docking_station_info *data);
#pragma pack(1) #pragma pack(1)
union pnp_bios_install_struct { union pnp_bios_install_struct {
struct { struct {
...@@ -28,8 +164,8 @@ extern int pnp_bios_present(void); ...@@ -28,8 +164,8 @@ extern int pnp_bios_present(void);
extern int pnpbios_dont_use_current_config; extern int pnpbios_dont_use_current_config;
extern int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node * node); extern int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node * node);
extern int pnpbios_read_resources_from_node(struct pnp_resource_table *res, struct pnp_bios_node * node); extern int pnpbios_read_resources_from_node(struct pnp_dev *dev, struct pnp_bios_node *node);
extern int pnpbios_write_resources_to_node(struct pnp_resource_table *res, struct pnp_bios_node * node); extern int pnpbios_write_resources_to_node(struct pnp_dev *dev, struct pnp_bios_node *node);
extern void pnpid32_to_pnpid(u32 id, char *str); extern void pnpid32_to_pnpid(u32 id, char *str);
extern void pnpbios_print_status(const char * module, u16 status); extern void pnpbios_print_status(const char * module, u16 status);
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/pnpbios.h> #include <linux/pnp.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/pnp.h> #include <linux/pnp.h>
#include <linux/pnpbios.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -16,6 +15,7 @@ inline void pcibios_penalize_isa_irq(int irq, int active) ...@@ -16,6 +15,7 @@ inline void pcibios_penalize_isa_irq(int irq, int active)
} }
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
#include "../base.h"
#include "pnpbios.h" #include "pnpbios.h"
/* standard resource tags */ /* standard resource tags */
...@@ -53,97 +53,43 @@ inline void pcibios_penalize_isa_irq(int irq, int active) ...@@ -53,97 +53,43 @@ inline void pcibios_penalize_isa_irq(int irq, int active)
* Allocated Resources * Allocated Resources
*/ */
static void pnpbios_parse_allocated_irqresource(struct pnp_resource_table *res, static void pnpbios_parse_allocated_ioresource(struct pnp_dev *dev,
int irq) int start, int len)
{ {
int i = 0; int flags = 0;
int end = start + len - 1;
while (!(res->irq_resource[i].flags & IORESOURCE_UNSET)
&& i < PNP_MAX_IRQ)
i++;
if (i < PNP_MAX_IRQ) {
res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
if (irq == -1) {
res->irq_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
res->irq_resource[i].start =
res->irq_resource[i].end = (unsigned long)irq;
pcibios_penalize_isa_irq(irq, 1);
}
}
static void pnpbios_parse_allocated_dmaresource(struct pnp_resource_table *res, if (len <= 0 || end >= 0x10003)
int dma) flags |= IORESOURCE_DISABLED;
{
int i = 0;
while (i < PNP_MAX_DMA &&
!(res->dma_resource[i].flags & IORESOURCE_UNSET))
i++;
if (i < PNP_MAX_DMA) {
res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag
if (dma == -1) {
res->dma_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
res->dma_resource[i].start =
res->dma_resource[i].end = (unsigned long)dma;
}
}
static void pnpbios_parse_allocated_ioresource(struct pnp_resource_table *res, pnp_add_io_resource(dev, start, end, flags);
int io, int len)
{
int i = 0;
while (!(res->port_resource[i].flags & IORESOURCE_UNSET)
&& i < PNP_MAX_PORT)
i++;
if (i < PNP_MAX_PORT) {
res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag
if (len <= 0 || (io + len - 1) >= 0x10003) {
res->port_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
res->port_resource[i].start = (unsigned long)io;
res->port_resource[i].end = (unsigned long)(io + len - 1);
}
} }
static void pnpbios_parse_allocated_memresource(struct pnp_resource_table *res, static void pnpbios_parse_allocated_memresource(struct pnp_dev *dev,
int mem, int len) int start, int len)
{ {
int i = 0; int flags = 0;
int end = start + len - 1;
while (!(res->mem_resource[i].flags & IORESOURCE_UNSET)
&& i < PNP_MAX_MEM) if (len <= 0)
i++; flags |= IORESOURCE_DISABLED;
if (i < PNP_MAX_MEM) {
res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag pnp_add_mem_resource(dev, start, end, flags);
if (len <= 0) {
res->mem_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
res->mem_resource[i].start = (unsigned long)mem;
res->mem_resource[i].end = (unsigned long)(mem + len - 1);
}
} }
static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev,
unsigned char *end, unsigned char *p,
struct unsigned char *end)
pnp_resource_table
*res)
{ {
unsigned int len, tag; unsigned int len, tag;
int io, size, mask, i; int io, size, mask, i, flags;
if (!p) if (!p)
return NULL; return NULL;
/* Blank the resource table values */ dev_dbg(&dev->dev, "parse allocated resources\n");
pnp_init_resource_table(res);
pnp_init_resources(dev);
while ((char *)p < (char *)end) { while ((char *)p < (char *)end) {
...@@ -163,7 +109,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, ...@@ -163,7 +109,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
goto len_err; goto len_err;
io = *(short *)&p[4]; io = *(short *)&p[4];
size = *(short *)&p[10]; size = *(short *)&p[10];
pnpbios_parse_allocated_memresource(res, io, size); pnpbios_parse_allocated_memresource(dev, io, size);
break; break;
case LARGE_TAG_ANSISTR: case LARGE_TAG_ANSISTR:
...@@ -179,7 +125,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, ...@@ -179,7 +125,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
goto len_err; goto len_err;
io = *(int *)&p[4]; io = *(int *)&p[4];
size = *(int *)&p[16]; size = *(int *)&p[16];
pnpbios_parse_allocated_memresource(res, io, size); pnpbios_parse_allocated_memresource(dev, io, size);
break; break;
case LARGE_TAG_FIXEDMEM32: case LARGE_TAG_FIXEDMEM32:
...@@ -187,29 +133,37 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, ...@@ -187,29 +133,37 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
goto len_err; goto len_err;
io = *(int *)&p[4]; io = *(int *)&p[4];
size = *(int *)&p[8]; size = *(int *)&p[8];
pnpbios_parse_allocated_memresource(res, io, size); pnpbios_parse_allocated_memresource(dev, io, size);
break; break;
case SMALL_TAG_IRQ: case SMALL_TAG_IRQ:
if (len < 2 || len > 3) if (len < 2 || len > 3)
goto len_err; goto len_err;
flags = 0;
io = -1; io = -1;
mask = p[1] + p[2] * 256; mask = p[1] + p[2] * 256;
for (i = 0; i < 16; i++, mask = mask >> 1) for (i = 0; i < 16; i++, mask = mask >> 1)
if (mask & 0x01) if (mask & 0x01)
io = i; io = i;
pnpbios_parse_allocated_irqresource(res, io); if (io != -1)
pcibios_penalize_isa_irq(io, 1);
else
flags = IORESOURCE_DISABLED;
pnp_add_irq_resource(dev, io, flags);
break; break;
case SMALL_TAG_DMA: case SMALL_TAG_DMA:
if (len != 2) if (len != 2)
goto len_err; goto len_err;
flags = 0;
io = -1; io = -1;
mask = p[1]; mask = p[1];
for (i = 0; i < 8; i++, mask = mask >> 1) for (i = 0; i < 8; i++, mask = mask >> 1)
if (mask & 0x01) if (mask & 0x01)
io = i; io = i;
pnpbios_parse_allocated_dmaresource(res, io); if (io == -1)
flags = IORESOURCE_DISABLED;
pnp_add_dma_resource(dev, io, flags);
break; break;
case SMALL_TAG_PORT: case SMALL_TAG_PORT:
...@@ -217,7 +171,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, ...@@ -217,7 +171,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
goto len_err; goto len_err;
io = p[2] + p[3] * 256; io = p[2] + p[3] * 256;
size = p[7]; size = p[7];
pnpbios_parse_allocated_ioresource(res, io, size); pnpbios_parse_allocated_ioresource(dev, io, size);
break; break;
case SMALL_TAG_VENDOR: case SMALL_TAG_VENDOR:
...@@ -229,7 +183,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, ...@@ -229,7 +183,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
goto len_err; goto len_err;
io = p[1] + p[2] * 256; io = p[1] + p[2] * 256;
size = p[3]; size = p[3];
pnpbios_parse_allocated_ioresource(res, io, size); pnpbios_parse_allocated_ioresource(dev, io, size);
break; break;
case SMALL_TAG_END: case SMALL_TAG_END:
...@@ -239,9 +193,8 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, ...@@ -239,9 +193,8 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
default: /* an unkown tag */ default: /* an unkown tag */
len_err: len_err:
printk(KERN_ERR dev_err(&dev->dev, "unknown tag %#x length %d\n",
"PnPBIOS: Unknown tag '0x%x', length '%d'.\n", tag, len);
tag, len);
break; break;
} }
...@@ -252,8 +205,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, ...@@ -252,8 +205,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
p += len + 1; p += len + 1;
} }
printk(KERN_ERR dev_err(&dev->dev, "no end tag in resource structure\n");
"PnPBIOS: Resource structure does not contain an end tag.\n");
return NULL; return NULL;
} }
...@@ -262,7 +214,8 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, ...@@ -262,7 +214,8 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
* Resource Configuration Options * Resource Configuration Options
*/ */
static __init void pnpbios_parse_mem_option(unsigned char *p, int size, static __init void pnpbios_parse_mem_option(struct pnp_dev *dev,
unsigned char *p, int size,
struct pnp_option *option) struct pnp_option *option)
{ {
struct pnp_mem *mem; struct pnp_mem *mem;
...@@ -275,10 +228,11 @@ static __init void pnpbios_parse_mem_option(unsigned char *p, int size, ...@@ -275,10 +228,11 @@ static __init void pnpbios_parse_mem_option(unsigned char *p, int size,
mem->align = (p[9] << 8) | p[8]; mem->align = (p[9] << 8) | p[8];
mem->size = ((p[11] << 8) | p[10]) << 8; mem->size = ((p[11] << 8) | p[10]) << 8;
mem->flags = p[3]; mem->flags = p[3];
pnp_register_mem_resource(option, mem); pnp_register_mem_resource(dev, option, mem);
} }
static __init void pnpbios_parse_mem32_option(unsigned char *p, int size, static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev,
unsigned char *p, int size,
struct pnp_option *option) struct pnp_option *option)
{ {
struct pnp_mem *mem; struct pnp_mem *mem;
...@@ -291,10 +245,11 @@ static __init void pnpbios_parse_mem32_option(unsigned char *p, int size, ...@@ -291,10 +245,11 @@ static __init void pnpbios_parse_mem32_option(unsigned char *p, int size,
mem->align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12]; mem->align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12];
mem->size = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16]; mem->size = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16];
mem->flags = p[3]; mem->flags = p[3];
pnp_register_mem_resource(option, mem); pnp_register_mem_resource(dev, option, mem);
} }
static __init void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev,
unsigned char *p, int size,
struct pnp_option *option) struct pnp_option *option)
{ {
struct pnp_mem *mem; struct pnp_mem *mem;
...@@ -306,11 +261,12 @@ static __init void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, ...@@ -306,11 +261,12 @@ static __init void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size,
mem->size = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8]; mem->size = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
mem->align = 0; mem->align = 0;
mem->flags = p[3]; mem->flags = p[3];
pnp_register_mem_resource(option, mem); pnp_register_mem_resource(dev, option, mem);
} }
static __init void pnpbios_parse_irq_option(unsigned char *p, int size, static __init void pnpbios_parse_irq_option(struct pnp_dev *dev,
struct pnp_option *option) unsigned char *p, int size,
struct pnp_option *option)
{ {
struct pnp_irq *irq; struct pnp_irq *irq;
unsigned long bits; unsigned long bits;
...@@ -324,11 +280,12 @@ static __init void pnpbios_parse_irq_option(unsigned char *p, int size, ...@@ -324,11 +280,12 @@ static __init void pnpbios_parse_irq_option(unsigned char *p, int size,
irq->flags = p[3]; irq->flags = p[3];
else else
irq->flags = IORESOURCE_IRQ_HIGHEDGE; irq->flags = IORESOURCE_IRQ_HIGHEDGE;
pnp_register_irq_resource(option, irq); pnp_register_irq_resource(dev, option, irq);
} }
static __init void pnpbios_parse_dma_option(unsigned char *p, int size, static __init void pnpbios_parse_dma_option(struct pnp_dev *dev,
struct pnp_option *option) unsigned char *p, int size,
struct pnp_option *option)
{ {
struct pnp_dma *dma; struct pnp_dma *dma;
...@@ -337,10 +294,11 @@ static __init void pnpbios_parse_dma_option(unsigned char *p, int size, ...@@ -337,10 +294,11 @@ static __init void pnpbios_parse_dma_option(unsigned char *p, int size,
return; return;
dma->map = p[1]; dma->map = p[1];
dma->flags = p[2]; dma->flags = p[2];
pnp_register_dma_resource(option, dma); pnp_register_dma_resource(dev, option, dma);
} }
static __init void pnpbios_parse_port_option(unsigned char *p, int size, static __init void pnpbios_parse_port_option(struct pnp_dev *dev,
unsigned char *p, int size,
struct pnp_option *option) struct pnp_option *option)
{ {
struct pnp_port *port; struct pnp_port *port;
...@@ -353,10 +311,11 @@ static __init void pnpbios_parse_port_option(unsigned char *p, int size, ...@@ -353,10 +311,11 @@ static __init void pnpbios_parse_port_option(unsigned char *p, int size,
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_register_port_resource(option, port); pnp_register_port_resource(dev, option, port);
} }
static __init void pnpbios_parse_fixed_port_option(unsigned char *p, int size, static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev,
unsigned char *p, int size,
struct pnp_option *option) struct pnp_option *option)
{ {
struct pnp_port *port; struct pnp_port *port;
...@@ -368,7 +327,7 @@ static __init void pnpbios_parse_fixed_port_option(unsigned char *p, int size, ...@@ -368,7 +327,7 @@ static __init void pnpbios_parse_fixed_port_option(unsigned char *p, int size,
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_register_port_resource(option, port); pnp_register_port_resource(dev, option, port);
} }
static __init unsigned char * static __init unsigned char *
...@@ -382,6 +341,8 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, ...@@ -382,6 +341,8 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
if (!p) if (!p)
return NULL; return NULL;
dev_dbg(&dev->dev, "parse resource options\n");
option_independent = option = pnp_register_independent_option(dev); option_independent = option = pnp_register_independent_option(dev);
if (!option) if (!option)
return NULL; return NULL;
...@@ -402,37 +363,37 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, ...@@ -402,37 +363,37 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
case LARGE_TAG_MEM: case LARGE_TAG_MEM:
if (len != 9) if (len != 9)
goto len_err; goto len_err;
pnpbios_parse_mem_option(p, len, option); pnpbios_parse_mem_option(dev, p, len, option);
break; break;
case LARGE_TAG_MEM32: case LARGE_TAG_MEM32:
if (len != 17) if (len != 17)
goto len_err; goto len_err;
pnpbios_parse_mem32_option(p, len, option); pnpbios_parse_mem32_option(dev, p, len, option);
break; break;
case LARGE_TAG_FIXEDMEM32: case LARGE_TAG_FIXEDMEM32:
if (len != 9) if (len != 9)
goto len_err; goto len_err;
pnpbios_parse_fixed_mem32_option(p, len, option); pnpbios_parse_fixed_mem32_option(dev, p, len, option);
break; break;
case SMALL_TAG_IRQ: case SMALL_TAG_IRQ:
if (len < 2 || len > 3) if (len < 2 || len > 3)
goto len_err; goto len_err;
pnpbios_parse_irq_option(p, len, option); pnpbios_parse_irq_option(dev, p, len, option);
break; break;
case SMALL_TAG_DMA: case SMALL_TAG_DMA:
if (len != 2) if (len != 2)
goto len_err; goto len_err;
pnpbios_parse_dma_option(p, len, option); pnpbios_parse_dma_option(dev, p, len, option);
break; break;
case SMALL_TAG_PORT: case SMALL_TAG_PORT:
if (len != 7) if (len != 7)
goto len_err; goto len_err;
pnpbios_parse_port_option(p, len, option); pnpbios_parse_port_option(dev, p, len, option);
break; break;
case SMALL_TAG_VENDOR: case SMALL_TAG_VENDOR:
...@@ -442,7 +403,7 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, ...@@ -442,7 +403,7 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
case SMALL_TAG_FIXEDPORT: case SMALL_TAG_FIXEDPORT:
if (len != 3) if (len != 3)
goto len_err; goto len_err;
pnpbios_parse_fixed_port_option(p, len, option); pnpbios_parse_fixed_port_option(dev, p, len, option);
break; break;
case SMALL_TAG_STARTDEP: case SMALL_TAG_STARTDEP:
...@@ -460,9 +421,10 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, ...@@ -460,9 +421,10 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
if (len != 0) if (len != 0)
goto len_err; goto len_err;
if (option_independent == option) if (option_independent == option)
printk(KERN_WARNING dev_warn(&dev->dev, "missing "
"PnPBIOS: Missing SMALL_TAG_STARTDEP tag\n"); "SMALL_TAG_STARTDEP tag\n");
option = option_independent; option = option_independent;
dev_dbg(&dev->dev, "end dependent options\n");
break; break;
case SMALL_TAG_END: case SMALL_TAG_END:
...@@ -470,9 +432,8 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, ...@@ -470,9 +432,8 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
default: /* an unkown tag */ default: /* an unkown tag */
len_err: len_err:
printk(KERN_ERR dev_err(&dev->dev, "unknown tag %#x length %d\n",
"PnPBIOS: Unknown tag '0x%x', length '%d'.\n", tag, len);
tag, len);
break; break;
} }
...@@ -483,8 +444,7 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, ...@@ -483,8 +444,7 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
p += len + 1; p += len + 1;
} }
printk(KERN_ERR dev_err(&dev->dev, "no end tag in resource structure\n");
"PnPBIOS: Resource structure does not contain an end tag.\n");
return NULL; return NULL;
} }
...@@ -493,32 +453,12 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, ...@@ -493,32 +453,12 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
* Compatible Device IDs * Compatible Device IDs
*/ */
#define HEX(id,a) hex[((id)>>a) & 15]
#define CHAR(id,a) (0x40 + (((id)>>a) & 31))
void pnpid32_to_pnpid(u32 id, char *str)
{
const char *hex = "0123456789abcdef";
id = be32_to_cpu(id);
str[0] = CHAR(id, 26);
str[1] = CHAR(id, 21);
str[2] = CHAR(id, 16);
str[3] = HEX(id, 12);
str[4] = HEX(id, 8);
str[5] = HEX(id, 4);
str[6] = HEX(id, 0);
str[7] = '\0';
}
#undef CHAR
#undef HEX
static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
unsigned char *end, unsigned char *end,
struct pnp_dev *dev) struct pnp_dev *dev)
{ {
int len, tag; int len, tag;
u32 eisa_id;
char id[8]; char id[8];
struct pnp_id *dev_id; struct pnp_id *dev_id;
...@@ -548,13 +488,11 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, ...@@ -548,13 +488,11 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
case SMALL_TAG_COMPATDEVID: /* compatible ID */ case SMALL_TAG_COMPATDEVID: /* compatible ID */
if (len != 4) if (len != 4)
goto len_err; goto len_err;
dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); eisa_id = p[1] | p[2] << 8 | p[3] << 16 | p[4] << 24;
pnp_eisa_id_to_string(eisa_id & PNP_EISA_ID_MASK, id);
dev_id = pnp_add_id(dev, id);
if (!dev_id) if (!dev_id)
return NULL; return NULL;
pnpid32_to_pnpid(p[1] | p[2] << 8 | p[3] << 16 | p[4] <<
24, id);
memcpy(&dev_id->id, id, 7);
pnp_add_id(dev_id, dev);
break; break;
case SMALL_TAG_END: case SMALL_TAG_END:
...@@ -564,9 +502,8 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, ...@@ -564,9 +502,8 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
default: /* an unkown tag */ default: /* an unkown tag */
len_err: len_err:
printk(KERN_ERR dev_err(&dev->dev, "unknown tag %#x length %d\n",
"PnPBIOS: Unknown tag '0x%x', length '%d'.\n", tag, len);
tag, len);
break; break;
} }
...@@ -577,8 +514,7 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, ...@@ -577,8 +514,7 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
p += len + 1; p += len + 1;
} }
printk(KERN_ERR dev_err(&dev->dev, "no end tag in resource structure\n");
"PnPBIOS: Resource structure does not contain an end tag.\n");
return NULL; return NULL;
} }
...@@ -587,7 +523,8 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, ...@@ -587,7 +523,8 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
* Allocated Resource Encoding * Allocated Resource Encoding
*/ */
static void pnpbios_encode_mem(unsigned char *p, struct resource *res) static void pnpbios_encode_mem(struct pnp_dev *dev, 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;
...@@ -598,9 +535,13 @@ static void pnpbios_encode_mem(unsigned char *p, struct resource *res) ...@@ -598,9 +535,13 @@ static void pnpbios_encode_mem(unsigned char *p, struct resource *res)
p[7] = ((base >> 8) >> 8) & 0xff; p[7] = ((base >> 8) >> 8) & 0xff;
p[10] = (len >> 8) & 0xff; p[10] = (len >> 8) & 0xff;
p[11] = ((len >> 8) >> 8) & 0xff; p[11] = ((len >> 8) >> 8) & 0xff;
dev_dbg(&dev->dev, " encode mem %#llx-%#llx\n",
(unsigned long long) res->start, (unsigned long long) res->end);
} }
static void pnpbios_encode_mem32(unsigned char *p, struct resource *res) static void pnpbios_encode_mem32(struct pnp_dev *dev, 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;
...@@ -617,9 +558,13 @@ static void pnpbios_encode_mem32(unsigned char *p, struct resource *res) ...@@ -617,9 +558,13 @@ static void pnpbios_encode_mem32(unsigned char *p, struct resource *res)
p[17] = (len >> 8) & 0xff; p[17] = (len >> 8) & 0xff;
p[18] = (len >> 16) & 0xff; p[18] = (len >> 16) & 0xff;
p[19] = (len >> 24) & 0xff; p[19] = (len >> 24) & 0xff;
dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx\n",
(unsigned long long) res->start, (unsigned long long) res->end);
} }
static void pnpbios_encode_fixed_mem32(unsigned char *p, struct resource *res) static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, 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;
...@@ -632,26 +577,36 @@ static void pnpbios_encode_fixed_mem32(unsigned char *p, struct resource *res) ...@@ -632,26 +577,36 @@ static void pnpbios_encode_fixed_mem32(unsigned char *p, struct resource *res)
p[9] = (len >> 8) & 0xff; p[9] = (len >> 8) & 0xff;
p[10] = (len >> 16) & 0xff; p[10] = (len >> 16) & 0xff;
p[11] = (len >> 24) & 0xff; p[11] = (len >> 24) & 0xff;
dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx\n",
(unsigned long long) res->start, (unsigned long long) res->end);
} }
static void pnpbios_encode_irq(unsigned char *p, struct resource *res) static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p,
struct resource *res)
{ {
unsigned long map = 0; unsigned long map = 0;
map = 1 << res->start; map = 1 << res->start;
p[1] = map & 0xff; p[1] = map & 0xff;
p[2] = (map >> 8) & 0xff; p[2] = (map >> 8) & 0xff;
dev_dbg(&dev->dev, " encode irq %d\n", res->start);
} }
static void pnpbios_encode_dma(unsigned char *p, struct resource *res) static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p,
struct resource *res)
{ {
unsigned long map = 0; unsigned long map = 0;
map = 1 << res->start; map = 1 << res->start;
p[1] = map & 0xff; p[1] = map & 0xff;
dev_dbg(&dev->dev, " encode dma %d\n", res->start);
} }
static void pnpbios_encode_port(unsigned char *p, struct resource *res) static void pnpbios_encode_port(struct pnp_dev *dev, 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;
...@@ -661,9 +616,13 @@ static void pnpbios_encode_port(unsigned char *p, struct resource *res) ...@@ -661,9 +616,13 @@ static void pnpbios_encode_port(unsigned char *p, struct resource *res)
p[4] = base & 0xff; p[4] = base & 0xff;
p[5] = (base >> 8) & 0xff; p[5] = (base >> 8) & 0xff;
p[7] = len & 0xff; p[7] = len & 0xff;
dev_dbg(&dev->dev, " encode io %#llx-%#llx\n",
(unsigned long long) res->start, (unsigned long long) res->end);
} }
static void pnpbios_encode_fixed_port(unsigned char *p, struct resource *res) static void pnpbios_encode_fixed_port(struct pnp_dev *dev, 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;
...@@ -671,13 +630,15 @@ static void pnpbios_encode_fixed_port(unsigned char *p, struct resource *res) ...@@ -671,13 +630,15 @@ static void pnpbios_encode_fixed_port(unsigned char *p, struct resource *res)
p[1] = base & 0xff; p[1] = base & 0xff;
p[2] = (base >> 8) & 0xff; p[2] = (base >> 8) & 0xff;
p[3] = len & 0xff; p[3] = len & 0xff;
dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n",
(unsigned long long) res->start, (unsigned long long) res->end);
} }
static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p, static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev
unsigned char *end, *dev,
struct unsigned char *p,
pnp_resource_table unsigned char *end)
*res)
{ {
unsigned int len, tag; unsigned int len, tag;
int port = 0, irq = 0, dma = 0, mem = 0; int port = 0, irq = 0, dma = 0, mem = 0;
...@@ -701,42 +662,48 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p, ...@@ -701,42 +662,48 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p,
case LARGE_TAG_MEM: case LARGE_TAG_MEM:
if (len != 9) if (len != 9)
goto len_err; goto len_err;
pnpbios_encode_mem(p, &res->mem_resource[mem]); pnpbios_encode_mem(dev, p,
pnp_get_resource(dev, IORESOURCE_MEM, mem));
mem++; mem++;
break; break;
case LARGE_TAG_MEM32: case LARGE_TAG_MEM32:
if (len != 17) if (len != 17)
goto len_err; goto len_err;
pnpbios_encode_mem32(p, &res->mem_resource[mem]); pnpbios_encode_mem32(dev, p,
pnp_get_resource(dev, IORESOURCE_MEM, mem));
mem++; mem++;
break; break;
case LARGE_TAG_FIXEDMEM32: case LARGE_TAG_FIXEDMEM32:
if (len != 9) if (len != 9)
goto len_err; goto len_err;
pnpbios_encode_fixed_mem32(p, &res->mem_resource[mem]); pnpbios_encode_fixed_mem32(dev, p,
pnp_get_resource(dev, IORESOURCE_MEM, mem));
mem++; mem++;
break; break;
case SMALL_TAG_IRQ: case SMALL_TAG_IRQ:
if (len < 2 || len > 3) if (len < 2 || len > 3)
goto len_err; goto len_err;
pnpbios_encode_irq(p, &res->irq_resource[irq]); pnpbios_encode_irq(dev, p,
pnp_get_resource(dev, IORESOURCE_IRQ, irq));
irq++; irq++;
break; break;
case SMALL_TAG_DMA: case SMALL_TAG_DMA:
if (len != 2) if (len != 2)
goto len_err; goto len_err;
pnpbios_encode_dma(p, &res->dma_resource[dma]); pnpbios_encode_dma(dev, p,
pnp_get_resource(dev, IORESOURCE_DMA, dma));
dma++; dma++;
break; break;
case SMALL_TAG_PORT: case SMALL_TAG_PORT:
if (len != 7) if (len != 7)
goto len_err; goto len_err;
pnpbios_encode_port(p, &res->port_resource[port]); pnpbios_encode_port(dev, p,
pnp_get_resource(dev, IORESOURCE_IO, port));
port++; port++;
break; break;
...@@ -747,7 +714,8 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p, ...@@ -747,7 +714,8 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p,
case SMALL_TAG_FIXEDPORT: case SMALL_TAG_FIXEDPORT:
if (len != 3) if (len != 3)
goto len_err; goto len_err;
pnpbios_encode_fixed_port(p, &res->port_resource[port]); pnpbios_encode_fixed_port(dev, p,
pnp_get_resource(dev, IORESOURCE_IO, port));
port++; port++;
break; break;
...@@ -758,9 +726,8 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p, ...@@ -758,9 +726,8 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p,
default: /* an unkown tag */ default: /* an unkown tag */
len_err: len_err:
printk(KERN_ERR dev_err(&dev->dev, "unknown tag %#x length %d\n",
"PnPBIOS: Unknown tag '0x%x', length '%d'.\n", tag, len);
tag, len);
break; break;
} }
...@@ -771,8 +738,7 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p, ...@@ -771,8 +738,7 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p,
p += len + 1; p += len + 1;
} }
printk(KERN_ERR dev_err(&dev->dev, "no end tag in resource structure\n");
"PnPBIOS: Resource structure does not contain an end tag.\n");
return NULL; return NULL;
} }
...@@ -787,7 +753,7 @@ int __init pnpbios_parse_data_stream(struct pnp_dev *dev, ...@@ -787,7 +753,7 @@ int __init pnpbios_parse_data_stream(struct pnp_dev *dev,
unsigned char *p = (char *)node->data; unsigned char *p = (char *)node->data;
unsigned char *end = (char *)(node->data + node->size); unsigned char *end = (char *)(node->data + node->size);
p = pnpbios_parse_allocated_resource_data(p, end, &dev->res); p = pnpbios_parse_allocated_resource_data(dev, p, end);
if (!p) if (!p)
return -EIO; return -EIO;
p = pnpbios_parse_resource_option_data(p, end, dev); p = pnpbios_parse_resource_option_data(p, end, dev);
...@@ -799,25 +765,25 @@ int __init pnpbios_parse_data_stream(struct pnp_dev *dev, ...@@ -799,25 +765,25 @@ int __init pnpbios_parse_data_stream(struct pnp_dev *dev,
return 0; return 0;
} }
int pnpbios_read_resources_from_node(struct pnp_resource_table *res, int pnpbios_read_resources_from_node(struct pnp_dev *dev,
struct pnp_bios_node *node) struct pnp_bios_node *node)
{ {
unsigned char *p = (char *)node->data; unsigned char *p = (char *)node->data;
unsigned char *end = (char *)(node->data + node->size); unsigned char *end = (char *)(node->data + node->size);
p = pnpbios_parse_allocated_resource_data(p, end, res); p = pnpbios_parse_allocated_resource_data(dev, p, end);
if (!p) if (!p)
return -EIO; return -EIO;
return 0; return 0;
} }
int pnpbios_write_resources_to_node(struct pnp_resource_table *res, int pnpbios_write_resources_to_node(struct pnp_dev *dev,
struct pnp_bios_node *node) struct pnp_bios_node *node)
{ {
unsigned char *p = (char *)node->data; unsigned char *p = (char *)node->data;
unsigned char *end = (char *)(node->data + node->size); unsigned char *end = (char *)(node->data + node->size);
p = pnpbios_encode_allocated_resource_data(p, end, res); p = pnpbios_encode_allocated_resource_data(dev, p, end);
if (!p) if (!p)
return -EIO; return -EIO;
return 0; return 0;
......
...@@ -117,6 +117,7 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev) ...@@ -117,6 +117,7 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev)
static void quirk_system_pci_resources(struct pnp_dev *dev) static void quirk_system_pci_resources(struct pnp_dev *dev)
{ {
struct pci_dev *pdev = NULL; struct pci_dev *pdev = NULL;
struct resource *res;
resource_size_t pnp_start, pnp_end, pci_start, pci_end; resource_size_t pnp_start, pnp_end, pci_start, pci_end;
int i, j; int i, j;
...@@ -137,13 +138,15 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) ...@@ -137,13 +138,15 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
pci_start = pci_resource_start(pdev, i); pci_start = pci_resource_start(pdev, i);
pci_end = pci_resource_end(pdev, i); pci_end = pci_resource_end(pdev, i);
for (j = 0; j < PNP_MAX_MEM; j++) { for (j = 0;
if (!pnp_mem_valid(dev, j) || (res = pnp_get_resource(dev, IORESOURCE_MEM, j));
pnp_mem_len(dev, j) == 0) j++) {
if (res->flags & IORESOURCE_UNSET ||
(res->start == 0 && res->end == 0))
continue; continue;
pnp_start = pnp_mem_start(dev, j); pnp_start = res->start;
pnp_end = pnp_mem_end(dev, j); pnp_end = res->end;
/* /*
* If the PNP region doesn't overlap the PCI * If the PNP region doesn't overlap the PCI
...@@ -176,7 +179,7 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) ...@@ -176,7 +179,7 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
pci_name(pdev), i, pci_name(pdev), i,
(unsigned long long) pci_start, (unsigned long long) pci_start,
(unsigned long long) pci_end); (unsigned long long) pci_end);
pnp_mem_flags(dev, j) = 0; res->flags = 0;
} }
} }
} }
......
...@@ -53,6 +53,8 @@ struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev) ...@@ -53,6 +53,8 @@ struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev)
if (dev->independent) if (dev->independent)
dev_err(&dev->dev, "independent resource already registered\n"); dev_err(&dev->dev, "independent resource already registered\n");
dev->independent = option; dev->independent = option;
dev_dbg(&dev->dev, "new independent option\n");
return option; return option;
} }
...@@ -70,12 +72,18 @@ struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, ...@@ -70,12 +72,18 @@ struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
parent->next = option; parent->next = option;
} else } else
dev->dependent = option; dev->dependent = option;
dev_dbg(&dev->dev, "new dependent option (priority %#x)\n", priority);
return option; return option;
} }
int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data) int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
struct pnp_irq *data)
{ {
struct pnp_irq *ptr; struct pnp_irq *ptr;
#ifdef DEBUG
char buf[PNP_IRQ_NR]; /* hex-encoded, so this is overkill but safe */
#endif
ptr = option->irq; ptr = option->irq;
while (ptr && ptr->next) while (ptr && ptr->next)
...@@ -94,10 +102,17 @@ int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data) ...@@ -94,10 +102,17 @@ int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data)
pcibios_penalize_isa_irq(i, 0); pcibios_penalize_isa_irq(i, 0);
} }
#endif #endif
#ifdef DEBUG
bitmap_scnprintf(buf, sizeof(buf), data->map, PNP_IRQ_NR);
dev_dbg(&dev->dev, " irq bitmask %s flags %#x\n", buf,
data->flags);
#endif
return 0; return 0;
} }
int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data) int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option,
struct pnp_dma *data)
{ {
struct pnp_dma *ptr; struct pnp_dma *ptr;
...@@ -109,10 +124,13 @@ int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data) ...@@ -109,10 +124,13 @@ int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data)
else else
option->dma = data; option->dma = data;
dev_dbg(&dev->dev, " dma bitmask %#x flags %#x\n", data->map,
data->flags);
return 0; return 0;
} }
int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data) int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option,
struct pnp_port *data)
{ {
struct pnp_port *ptr; struct pnp_port *ptr;
...@@ -124,10 +142,14 @@ int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data) ...@@ -124,10 +142,14 @@ int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data)
else else
option->port = data; option->port = data;
dev_dbg(&dev->dev, " io "
"min %#x max %#x align %d size %d flags %#x\n",
data->min, data->max, data->align, data->size, data->flags);
return 0; return 0;
} }
int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data) int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option,
struct pnp_mem *data)
{ {
struct pnp_mem *ptr; struct pnp_mem *ptr;
...@@ -138,6 +160,10 @@ int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data) ...@@ -138,6 +160,10 @@ int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data)
ptr->next = data; ptr->next = data;
else else
option->mem = data; option->mem = data;
dev_dbg(&dev->dev, " mem "
"min %#x max %#x align %d size %d flags %#x\n",
data->min, data->max, data->align, data->size, data->flags);
return 0; return 0;
} }
...@@ -213,17 +239,18 @@ void pnp_free_option(struct pnp_option *option) ...@@ -213,17 +239,18 @@ void pnp_free_option(struct pnp_option *option)
#define cannot_compare(flags) \ #define cannot_compare(flags) \
((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED)) ((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED))
int pnp_check_port(struct pnp_dev *dev, int idx) int pnp_check_port(struct pnp_dev *dev, struct resource *res)
{ {
int tmp; int i;
struct pnp_dev *tdev; struct pnp_dev *tdev;
struct resource *tres;
resource_size_t *port, *end, *tport, *tend; resource_size_t *port, *end, *tport, *tend;
port = &dev->res.port_resource[idx].start; port = &res->start;
end = &dev->res.port_resource[idx].end; end = &res->end;
/* if the resource doesn't exist, don't complain about it */ /* if the resource doesn't exist, don't complain about it */
if (cannot_compare(dev->res.port_resource[idx].flags)) if (cannot_compare(res->flags))
return 1; return 1;
/* check if the resource is already in use, skip if the /* check if the resource is already in use, skip if the
...@@ -234,18 +261,18 @@ int pnp_check_port(struct pnp_dev *dev, int idx) ...@@ -234,18 +261,18 @@ int pnp_check_port(struct pnp_dev *dev, int idx)
} }
/* check if the resource is reserved */ /* check if the resource is reserved */
for (tmp = 0; tmp < 8; tmp++) { for (i = 0; i < 8; i++) {
int rport = pnp_reserve_io[tmp << 1]; int rport = pnp_reserve_io[i << 1];
int rend = pnp_reserve_io[(tmp << 1) + 1] + rport - 1; int rend = pnp_reserve_io[(i << 1) + 1] + rport - 1;
if (ranged_conflict(port, end, &rport, &rend)) if (ranged_conflict(port, end, &rport, &rend))
return 0; return 0;
} }
/* check for internal conflicts */ /* check for internal conflicts */
for (tmp = 0; tmp < PNP_MAX_PORT && tmp != idx; tmp++) { for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
if (dev->res.port_resource[tmp].flags & IORESOURCE_IO) { if (tres != res && tres->flags & IORESOURCE_IO) {
tport = &dev->res.port_resource[tmp].start; tport = &tres->start;
tend = &dev->res.port_resource[tmp].end; tend = &tres->end;
if (ranged_conflict(port, end, tport, tend)) if (ranged_conflict(port, end, tport, tend))
return 0; return 0;
} }
...@@ -255,13 +282,14 @@ int pnp_check_port(struct pnp_dev *dev, int idx) ...@@ -255,13 +282,14 @@ int pnp_check_port(struct pnp_dev *dev, int idx)
pnp_for_each_dev(tdev) { pnp_for_each_dev(tdev) {
if (tdev == dev) if (tdev == dev)
continue; continue;
for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) { for (i = 0;
if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) { (tres = pnp_get_resource(tdev, IORESOURCE_IO, i));
if (cannot_compare i++) {
(tdev->res.port_resource[tmp].flags)) if (tres->flags & IORESOURCE_IO) {
if (cannot_compare(tres->flags))
continue; continue;
tport = &tdev->res.port_resource[tmp].start; tport = &tres->start;
tend = &tdev->res.port_resource[tmp].end; tend = &tres->end;
if (ranged_conflict(port, end, tport, tend)) if (ranged_conflict(port, end, tport, tend))
return 0; return 0;
} }
...@@ -271,17 +299,18 @@ int pnp_check_port(struct pnp_dev *dev, int idx) ...@@ -271,17 +299,18 @@ int pnp_check_port(struct pnp_dev *dev, int idx)
return 1; return 1;
} }
int pnp_check_mem(struct pnp_dev *dev, int idx) int pnp_check_mem(struct pnp_dev *dev, struct resource *res)
{ {
int tmp; int i;
struct pnp_dev *tdev; struct pnp_dev *tdev;
struct resource *tres;
resource_size_t *addr, *end, *taddr, *tend; resource_size_t *addr, *end, *taddr, *tend;
addr = &dev->res.mem_resource[idx].start; addr = &res->start;
end = &dev->res.mem_resource[idx].end; end = &res->end;
/* if the resource doesn't exist, don't complain about it */ /* if the resource doesn't exist, don't complain about it */
if (cannot_compare(dev->res.mem_resource[idx].flags)) if (cannot_compare(res->flags))
return 1; return 1;
/* check if the resource is already in use, skip if the /* check if the resource is already in use, skip if the
...@@ -292,18 +321,18 @@ int pnp_check_mem(struct pnp_dev *dev, int idx) ...@@ -292,18 +321,18 @@ int pnp_check_mem(struct pnp_dev *dev, int idx)
} }
/* check if the resource is reserved */ /* check if the resource is reserved */
for (tmp = 0; tmp < 8; tmp++) { for (i = 0; i < 8; i++) {
int raddr = pnp_reserve_mem[tmp << 1]; int raddr = pnp_reserve_mem[i << 1];
int rend = pnp_reserve_mem[(tmp << 1) + 1] + raddr - 1; int rend = pnp_reserve_mem[(i << 1) + 1] + raddr - 1;
if (ranged_conflict(addr, end, &raddr, &rend)) if (ranged_conflict(addr, end, &raddr, &rend))
return 0; return 0;
} }
/* check for internal conflicts */ /* check for internal conflicts */
for (tmp = 0; tmp < PNP_MAX_MEM && tmp != idx; tmp++) { for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
if (dev->res.mem_resource[tmp].flags & IORESOURCE_MEM) { if (tres != res && tres->flags & IORESOURCE_MEM) {
taddr = &dev->res.mem_resource[tmp].start; taddr = &tres->start;
tend = &dev->res.mem_resource[tmp].end; tend = &tres->end;
if (ranged_conflict(addr, end, taddr, tend)) if (ranged_conflict(addr, end, taddr, tend))
return 0; return 0;
} }
...@@ -313,13 +342,14 @@ int pnp_check_mem(struct pnp_dev *dev, int idx) ...@@ -313,13 +342,14 @@ int pnp_check_mem(struct pnp_dev *dev, int idx)
pnp_for_each_dev(tdev) { pnp_for_each_dev(tdev) {
if (tdev == dev) if (tdev == dev)
continue; continue;
for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) { for (i = 0;
if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) { (tres = pnp_get_resource(tdev, IORESOURCE_MEM, i));
if (cannot_compare i++) {
(tdev->res.mem_resource[tmp].flags)) if (tres->flags & IORESOURCE_MEM) {
if (cannot_compare(tres->flags))
continue; continue;
taddr = &tdev->res.mem_resource[tmp].start; taddr = &tres->start;
tend = &tdev->res.mem_resource[tmp].end; tend = &tres->end;
if (ranged_conflict(addr, end, taddr, tend)) if (ranged_conflict(addr, end, taddr, tend))
return 0; return 0;
} }
...@@ -334,14 +364,17 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id) ...@@ -334,14 +364,17 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
int pnp_check_irq(struct pnp_dev *dev, int idx) int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
{ {
int tmp; int i;
struct pnp_dev *tdev; struct pnp_dev *tdev;
resource_size_t *irq = &dev->res.irq_resource[idx].start; struct resource *tres;
resource_size_t *irq;
irq = &res->start;
/* if the resource doesn't exist, don't complain about it */ /* if the resource doesn't exist, don't complain about it */
if (cannot_compare(dev->res.irq_resource[idx].flags)) if (cannot_compare(res->flags))
return 1; return 1;
/* check if the resource is valid */ /* check if the resource is valid */
...@@ -349,15 +382,15 @@ int pnp_check_irq(struct pnp_dev *dev, int idx) ...@@ -349,15 +382,15 @@ int pnp_check_irq(struct pnp_dev *dev, int idx)
return 0; return 0;
/* check if the resource is reserved */ /* check if the resource is reserved */
for (tmp = 0; tmp < 16; tmp++) { for (i = 0; i < 16; i++) {
if (pnp_reserve_irq[tmp] == *irq) if (pnp_reserve_irq[i] == *irq)
return 0; return 0;
} }
/* check for internal conflicts */ /* check for internal conflicts */
for (tmp = 0; tmp < PNP_MAX_IRQ && tmp != idx; tmp++) { for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) {
if (dev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) { if (tres != res && tres->flags & IORESOURCE_IRQ) {
if (dev->res.irq_resource[tmp].start == *irq) if (tres->start == *irq)
return 0; return 0;
} }
} }
...@@ -388,12 +421,13 @@ int pnp_check_irq(struct pnp_dev *dev, int idx) ...@@ -388,12 +421,13 @@ int pnp_check_irq(struct pnp_dev *dev, int idx)
pnp_for_each_dev(tdev) { pnp_for_each_dev(tdev) {
if (tdev == dev) if (tdev == dev)
continue; continue;
for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) { for (i = 0;
if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) { (tres = pnp_get_resource(tdev, IORESOURCE_IRQ, i));
if (cannot_compare i++) {
(tdev->res.irq_resource[tmp].flags)) if (tres->flags & IORESOURCE_IRQ) {
if (cannot_compare(tres->flags))
continue; continue;
if ((tdev->res.irq_resource[tmp].start == *irq)) if (tres->start == *irq)
return 0; return 0;
} }
} }
...@@ -402,15 +436,18 @@ int pnp_check_irq(struct pnp_dev *dev, int idx) ...@@ -402,15 +436,18 @@ int pnp_check_irq(struct pnp_dev *dev, int idx)
return 1; return 1;
} }
int pnp_check_dma(struct pnp_dev *dev, int idx) int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
{ {
#ifndef CONFIG_IA64 #ifndef CONFIG_IA64
int tmp; int i;
struct pnp_dev *tdev; struct pnp_dev *tdev;
resource_size_t *dma = &dev->res.dma_resource[idx].start; struct resource *tres;
resource_size_t *dma;
dma = &res->start;
/* if the resource doesn't exist, don't complain about it */ /* if the resource doesn't exist, don't complain about it */
if (cannot_compare(dev->res.dma_resource[idx].flags)) if (cannot_compare(res->flags))
return 1; return 1;
/* check if the resource is valid */ /* check if the resource is valid */
...@@ -418,15 +455,15 @@ int pnp_check_dma(struct pnp_dev *dev, int idx) ...@@ -418,15 +455,15 @@ int pnp_check_dma(struct pnp_dev *dev, int idx)
return 0; return 0;
/* check if the resource is reserved */ /* check if the resource is reserved */
for (tmp = 0; tmp < 8; tmp++) { for (i = 0; i < 8; i++) {
if (pnp_reserve_dma[tmp] == *dma) if (pnp_reserve_dma[i] == *dma)
return 0; return 0;
} }
/* check for internal conflicts */ /* check for internal conflicts */
for (tmp = 0; tmp < PNP_MAX_DMA && tmp != idx; tmp++) { for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) {
if (dev->res.dma_resource[tmp].flags & IORESOURCE_DMA) { if (tres != res && tres->flags & IORESOURCE_DMA) {
if (dev->res.dma_resource[tmp].start == *dma) if (tres->start == *dma)
return 0; return 0;
} }
} }
...@@ -443,12 +480,13 @@ int pnp_check_dma(struct pnp_dev *dev, int idx) ...@@ -443,12 +480,13 @@ int pnp_check_dma(struct pnp_dev *dev, int idx)
pnp_for_each_dev(tdev) { pnp_for_each_dev(tdev) {
if (tdev == dev) if (tdev == dev)
continue; continue;
for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) { for (i = 0;
if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) { (tres = pnp_get_resource(tdev, IORESOURCE_DMA, i));
if (cannot_compare i++) {
(tdev->res.dma_resource[tmp].flags)) if (tres->flags & IORESOURCE_DMA) {
if (cannot_compare(tres->flags))
continue; continue;
if ((tdev->res.dma_resource[tmp].start == *dma)) if (tres->start == *dma)
return 0; return 0;
} }
} }
...@@ -461,6 +499,193 @@ int pnp_check_dma(struct pnp_dev *dev, int idx) ...@@ -461,6 +499,193 @@ int pnp_check_dma(struct pnp_dev *dev, int idx)
#endif #endif
} }
struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
unsigned int type, unsigned int num)
{
struct pnp_resource_table *res = dev->res;
switch (type) {
case IORESOURCE_IO:
if (num >= PNP_MAX_PORT)
return NULL;
return &res->port[num];
case IORESOURCE_MEM:
if (num >= PNP_MAX_MEM)
return NULL;
return &res->mem[num];
case IORESOURCE_IRQ:
if (num >= PNP_MAX_IRQ)
return NULL;
return &res->irq[num];
case IORESOURCE_DMA:
if (num >= PNP_MAX_DMA)
return NULL;
return &res->dma[num];
}
return NULL;
}
struct resource *pnp_get_resource(struct pnp_dev *dev,
unsigned int type, unsigned int num)
{
struct pnp_resource *pnp_res;
pnp_res = pnp_get_pnp_resource(dev, type, num);
if (pnp_res)
return &pnp_res->res;
return NULL;
}
EXPORT_SYMBOL(pnp_get_resource);
static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev, int type)
{
struct pnp_resource *pnp_res;
int i;
switch (type) {
case IORESOURCE_IO:
for (i = 0; i < PNP_MAX_PORT; i++) {
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, i);
if (pnp_res && !pnp_resource_valid(&pnp_res->res))
return pnp_res;
}
break;
case IORESOURCE_MEM:
for (i = 0; i < PNP_MAX_MEM; i++) {
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, i);
if (pnp_res && !pnp_resource_valid(&pnp_res->res))
return pnp_res;
}
break;
case IORESOURCE_IRQ:
for (i = 0; i < PNP_MAX_IRQ; i++) {
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, i);
if (pnp_res && !pnp_resource_valid(&pnp_res->res))
return pnp_res;
}
break;
case IORESOURCE_DMA:
for (i = 0; i < PNP_MAX_DMA; i++) {
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, i);
if (pnp_res && !pnp_resource_valid(&pnp_res->res))
return pnp_res;
}
break;
}
return NULL;
}
struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
int flags)
{
struct pnp_resource *pnp_res;
struct resource *res;
static unsigned char warned;
pnp_res = pnp_new_resource(dev, IORESOURCE_IRQ);
if (!pnp_res) {
if (!warned) {
dev_err(&dev->dev, "can't add resource for IRQ %d\n",
irq);
warned = 1;
}
return NULL;
}
res = &pnp_res->res;
res->flags = IORESOURCE_IRQ | flags;
res->start = irq;
res->end = irq;
dev_dbg(&dev->dev, " add irq %d flags %#x\n", irq, flags);
return pnp_res;
}
struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
int flags)
{
struct pnp_resource *pnp_res;
struct resource *res;
static unsigned char warned;
pnp_res = pnp_new_resource(dev, IORESOURCE_DMA);
if (!pnp_res) {
if (!warned) {
dev_err(&dev->dev, "can't add resource for DMA %d\n",
dma);
warned = 1;
}
return NULL;
}
res = &pnp_res->res;
res->flags = IORESOURCE_DMA | flags;
res->start = dma;
res->end = dma;
dev_dbg(&dev->dev, " add dma %d flags %#x\n", dma, flags);
return pnp_res;
}
struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
resource_size_t start,
resource_size_t end, int flags)
{
struct pnp_resource *pnp_res;
struct resource *res;
static unsigned char warned;
pnp_res = pnp_new_resource(dev, IORESOURCE_IO);
if (!pnp_res) {
if (!warned) {
dev_err(&dev->dev, "can't add resource for IO "
"%#llx-%#llx\n",(unsigned long long) start,
(unsigned long long) end);
warned = 1;
}
return NULL;
}
res = &pnp_res->res;
res->flags = IORESOURCE_IO | flags;
res->start = start;
res->end = end;
dev_dbg(&dev->dev, " add io %#llx-%#llx flags %#x\n",
(unsigned long long) start, (unsigned long long) end, flags);
return pnp_res;
}
struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
resource_size_t start,
resource_size_t end, int flags)
{
struct pnp_resource *pnp_res;
struct resource *res;
static unsigned char warned;
pnp_res = pnp_new_resource(dev, IORESOURCE_MEM);
if (!pnp_res) {
if (!warned) {
dev_err(&dev->dev, "can't add resource for MEM "
"%#llx-%#llx\n",(unsigned long long) start,
(unsigned long long) end);
warned = 1;
}
return NULL;
}
res = &pnp_res->res;
res->flags = IORESOURCE_MEM | flags;
res->start = start;
res->end = end;
dev_dbg(&dev->dev, " add mem %#llx-%#llx flags %#x\n",
(unsigned long long) start, (unsigned long long) end, flags);
return pnp_res;
}
/* format is: pnp_reserve_irq=irq1[,irq2] .... */ /* format is: pnp_reserve_irq=irq1[,irq2] .... */
static int __init pnp_setup_reserve_irq(char *str) static int __init pnp_setup_reserve_irq(char *str)
{ {
......
...@@ -25,3 +25,66 @@ int pnp_is_active(struct pnp_dev *dev) ...@@ -25,3 +25,66 @@ int pnp_is_active(struct pnp_dev *dev)
} }
EXPORT_SYMBOL(pnp_is_active); EXPORT_SYMBOL(pnp_is_active);
/*
* Functionally similar to acpi_ex_eisa_id_to_string(), but that's
* buried in the ACPI CA, and we can't depend on it being present.
*/
void pnp_eisa_id_to_string(u32 id, char *str)
{
id = be32_to_cpu(id);
/*
* According to the specs, the first three characters are five-bit
* compressed ASCII, and the left-over high order bit should be zero.
* However, the Linux ISAPNP code historically used six bits for the
* first character, and there seem to be IDs that depend on that,
* e.g., "nEC8241" in the Linux 8250_pnp serial driver and the
* FreeBSD sys/pc98/cbus/sio_cbus.c driver.
*/
str[0] = 'A' + ((id >> 26) & 0x3f) - 1;
str[1] = 'A' + ((id >> 21) & 0x1f) - 1;
str[2] = 'A' + ((id >> 16) & 0x1f) - 1;
str[3] = hex_asc((id >> 12) & 0xf);
str[4] = hex_asc((id >> 8) & 0xf);
str[5] = hex_asc((id >> 4) & 0xf);
str[6] = hex_asc((id >> 0) & 0xf);
str[7] = '\0';
}
void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
{
#ifdef DEBUG
struct resource *res;
int i;
dev_dbg(&dev->dev, "current resources: %s\n", desc);
for (i = 0; i < PNP_MAX_IRQ; i++) {
res = pnp_get_resource(dev, IORESOURCE_IRQ, i);
if (res && !(res->flags & IORESOURCE_UNSET))
dev_dbg(&dev->dev, " irq %lld flags %#lx\n",
(unsigned long long) res->start, res->flags);
}
for (i = 0; i < PNP_MAX_DMA; i++) {
res = pnp_get_resource(dev, IORESOURCE_DMA, i);
if (res && !(res->flags & IORESOURCE_UNSET))
dev_dbg(&dev->dev, " dma %lld flags %#lx\n",
(unsigned long long) res->start, res->flags);
}
for (i = 0; i < PNP_MAX_PORT; i++) {
res = pnp_get_resource(dev, IORESOURCE_IO, i);
if (res && !(res->flags & IORESOURCE_UNSET))
dev_dbg(&dev->dev, " io %#llx-%#llx flags %#lx\n",
(unsigned long long) res->start,
(unsigned long long) res->end, res->flags);
}
for (i = 0; i < PNP_MAX_MEM; i++) {
res = pnp_get_resource(dev, IORESOURCE_MEM, i);
if (res && !(res->flags & IORESOURCE_UNSET))
dev_dbg(&dev->dev, " mem %#llx-%#llx flags %#lx\n",
(unsigned long long) res->start,
(unsigned long long) res->end, res->flags);
}
#endif
}
...@@ -56,14 +56,15 @@ static void reserve_range(struct pnp_dev *dev, resource_size_t start, ...@@ -56,14 +56,15 @@ static void reserve_range(struct pnp_dev *dev, resource_size_t start,
static void reserve_resources_of_dev(struct pnp_dev *dev) static void reserve_resources_of_dev(struct pnp_dev *dev)
{ {
struct resource *res;
int i; int i;
for (i = 0; i < PNP_MAX_PORT; i++) { for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
if (!pnp_port_valid(dev, i)) if (res->flags & IORESOURCE_UNSET)
continue; continue;
if (pnp_port_start(dev, i) == 0) if (res->start == 0)
continue; /* disabled */ continue; /* disabled */
if (pnp_port_start(dev, i) < 0x100) if (res->start < 0x100)
/* /*
* Below 0x100 is only standard PC hardware * Below 0x100 is only standard PC hardware
* (pics, kbd, timer, dma, ...) * (pics, kbd, timer, dma, ...)
...@@ -73,19 +74,17 @@ static void reserve_resources_of_dev(struct pnp_dev *dev) ...@@ -73,19 +74,17 @@ static void reserve_resources_of_dev(struct pnp_dev *dev)
* So, do nothing * So, do nothing
*/ */
continue; continue;
if (pnp_port_end(dev, i) < pnp_port_start(dev, i)) if (res->end < res->start)
continue; /* invalid */ continue; /* invalid */
reserve_range(dev, pnp_port_start(dev, i), reserve_range(dev, res->start, res->end, 1);
pnp_port_end(dev, i), 1);
} }
for (i = 0; i < PNP_MAX_MEM; i++) { for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
if (!pnp_mem_valid(dev, i)) if (res->flags & IORESOURCE_UNSET)
continue; continue;
reserve_range(dev, pnp_mem_start(dev, i), reserve_range(dev, res->start, res->end, 0);
pnp_mem_end(dev, i), 0);
} }
} }
......
...@@ -854,11 +854,12 @@ cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) ...@@ -854,11 +854,12 @@ cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
* don't define the IRQ. It should always be safe to * don't define the IRQ. It should always be safe to
* hardcode it in these cases * hardcode it in these cases
*/ */
return cmos_do_probe(&pnp->dev, &pnp->res.port_resource[0], 8); return cmos_do_probe(&pnp->dev,
pnp_get_resource(pnp, IORESOURCE_IO, 0), 8);
else else
return cmos_do_probe(&pnp->dev, return cmos_do_probe(&pnp->dev,
&pnp->res.port_resource[0], pnp_get_resource(pnp, IORESOURCE_IO, 0),
pnp->res.irq_resource[0].start); pnp_irq(pnp, 0));
} }
static void __exit cmos_pnp_remove(struct pnp_dev *pnp) static void __exit cmos_pnp_remove(struct pnp_dev *pnp)
......
...@@ -25,16 +25,6 @@ ...@@ -25,16 +25,6 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/pnp.h> #include <linux/pnp.h>
/*
* Configuration registers (TODO: change by specification)
*/
#define ISAPNP_CFG_ACTIVATE 0x30 /* byte */
#define ISAPNP_CFG_MEM 0x40 /* 4 * dword */
#define ISAPNP_CFG_PORT 0x60 /* 8 * word */
#define ISAPNP_CFG_IRQ 0x70 /* 2 * word */
#define ISAPNP_CFG_DMA 0x74 /* 2 * byte */
/* /*
* *
*/ */
......
...@@ -13,59 +13,122 @@ ...@@ -13,59 +13,122 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#define PNP_MAX_PORT 40
#define PNP_MAX_MEM 24
#define PNP_MAX_IRQ 2
#define PNP_MAX_DMA 2
#define PNP_NAME_LEN 50 #define PNP_NAME_LEN 50
struct pnp_protocol; struct pnp_protocol;
struct pnp_dev; struct pnp_dev;
struct pnp_resource_table;
/* /*
* Resource Management * Resource Management
*/ */
struct resource *pnp_get_resource(struct pnp_dev *, unsigned int, unsigned int);
static inline int pnp_resource_valid(struct resource *res)
{
if (res && !(res->flags & IORESOURCE_UNSET))
return 1;
return 0;
}
static inline resource_size_t pnp_resource_len(struct resource *res)
{
if (res->start == 0 && res->end == 0)
return 0;
return res->end - res->start + 1;
}
static inline resource_size_t pnp_port_start(struct pnp_dev *dev,
unsigned int bar)
{
return pnp_get_resource(dev, IORESOURCE_IO, bar)->start;
}
static inline resource_size_t pnp_port_end(struct pnp_dev *dev,
unsigned int bar)
{
return pnp_get_resource(dev, IORESOURCE_IO, bar)->end;
}
static inline unsigned long pnp_port_flags(struct pnp_dev *dev,
unsigned int bar)
{
return pnp_get_resource(dev, IORESOURCE_IO, bar)->flags;
}
static inline int pnp_port_valid(struct pnp_dev *dev, unsigned int bar)
{
return pnp_resource_valid(pnp_get_resource(dev, IORESOURCE_IO, bar));
}
static inline resource_size_t pnp_port_len(struct pnp_dev *dev,
unsigned int bar)
{
return pnp_resource_len(pnp_get_resource(dev, IORESOURCE_IO, bar));
}
static inline resource_size_t pnp_mem_start(struct pnp_dev *dev,
unsigned int bar)
{
return pnp_get_resource(dev, IORESOURCE_MEM, bar)->start;
}
static inline resource_size_t pnp_mem_end(struct pnp_dev *dev,
unsigned int bar)
{
return pnp_get_resource(dev, IORESOURCE_MEM, bar)->end;
}
static inline unsigned long pnp_mem_flags(struct pnp_dev *dev, unsigned int bar)
{
return pnp_get_resource(dev, IORESOURCE_MEM, bar)->flags;
}
static inline int pnp_mem_valid(struct pnp_dev *dev, unsigned int bar)
{
return pnp_resource_valid(pnp_get_resource(dev, IORESOURCE_MEM, bar));
}
static inline resource_size_t pnp_mem_len(struct pnp_dev *dev,
unsigned int bar)
{
return pnp_resource_len(pnp_get_resource(dev, IORESOURCE_MEM, bar));
}
static inline resource_size_t pnp_irq(struct pnp_dev *dev, unsigned int bar)
{
return pnp_get_resource(dev, IORESOURCE_IRQ, bar)->start;
}
static inline unsigned long pnp_irq_flags(struct pnp_dev *dev, unsigned int bar)
{
return pnp_get_resource(dev, IORESOURCE_IRQ, bar)->flags;
}
static inline int pnp_irq_valid(struct pnp_dev *dev, unsigned int bar)
{
return pnp_resource_valid(pnp_get_resource(dev, IORESOURCE_IRQ, bar));
}
static inline resource_size_t pnp_dma(struct pnp_dev *dev, unsigned int bar)
{
return pnp_get_resource(dev, IORESOURCE_DMA, bar)->start;
}
static inline unsigned long pnp_dma_flags(struct pnp_dev *dev, unsigned int bar)
{
return pnp_get_resource(dev, IORESOURCE_DMA, bar)->flags;
}
static inline int pnp_dma_valid(struct pnp_dev *dev, unsigned int bar)
{
return pnp_resource_valid(pnp_get_resource(dev, IORESOURCE_DMA, bar));
}
/* Use these instead of directly reading pnp_dev to get resource information */
#define pnp_port_start(dev,bar) ((dev)->res.port_resource[(bar)].start)
#define pnp_port_end(dev,bar) ((dev)->res.port_resource[(bar)].end)
#define pnp_port_flags(dev,bar) ((dev)->res.port_resource[(bar)].flags)
#define pnp_port_valid(dev,bar) \
((pnp_port_flags((dev),(bar)) & (IORESOURCE_IO | IORESOURCE_UNSET)) \
== IORESOURCE_IO)
#define pnp_port_len(dev,bar) \
((pnp_port_start((dev),(bar)) == 0 && \
pnp_port_end((dev),(bar)) == \
pnp_port_start((dev),(bar))) ? 0 : \
\
(pnp_port_end((dev),(bar)) - \
pnp_port_start((dev),(bar)) + 1))
#define pnp_mem_start(dev,bar) ((dev)->res.mem_resource[(bar)].start)
#define pnp_mem_end(dev,bar) ((dev)->res.mem_resource[(bar)].end)
#define pnp_mem_flags(dev,bar) ((dev)->res.mem_resource[(bar)].flags)
#define pnp_mem_valid(dev,bar) \
((pnp_mem_flags((dev),(bar)) & (IORESOURCE_MEM | IORESOURCE_UNSET)) \
== IORESOURCE_MEM)
#define pnp_mem_len(dev,bar) \
((pnp_mem_start((dev),(bar)) == 0 && \
pnp_mem_end((dev),(bar)) == \
pnp_mem_start((dev),(bar))) ? 0 : \
\
(pnp_mem_end((dev),(bar)) - \
pnp_mem_start((dev),(bar)) + 1))
#define pnp_irq(dev,bar) ((dev)->res.irq_resource[(bar)].start)
#define pnp_irq_flags(dev,bar) ((dev)->res.irq_resource[(bar)].flags)
#define pnp_irq_valid(dev,bar) \
((pnp_irq_flags((dev),(bar)) & (IORESOURCE_IRQ | IORESOURCE_UNSET)) \
== IORESOURCE_IRQ)
#define pnp_dma(dev,bar) ((dev)->res.dma_resource[(bar)].start)
#define pnp_dma_flags(dev,bar) ((dev)->res.dma_resource[(bar)].flags)
#define pnp_dma_valid(dev,bar) \
((pnp_dma_flags((dev),(bar)) & (IORESOURCE_DMA | IORESOURCE_UNSET)) \
== IORESOURCE_DMA)
#define PNP_PORT_FLAG_16BITADDR (1<<0) #define PNP_PORT_FLAG_16BITADDR (1<<0)
#define PNP_PORT_FLAG_FIXED (1<<1) #define PNP_PORT_FLAG_FIXED (1<<1)
...@@ -118,13 +181,6 @@ struct pnp_option { ...@@ -118,13 +181,6 @@ struct pnp_option {
struct pnp_option *next; /* used to chain dependent resources */ struct pnp_option *next; /* used to chain dependent resources */
}; };
struct pnp_resource_table {
struct resource port_resource[PNP_MAX_PORT];
struct resource mem_resource[PNP_MAX_MEM];
struct resource dma_resource[PNP_MAX_DMA];
struct resource irq_resource[PNP_MAX_IRQ];
};
/* /*
* Device Management * Device Management
*/ */
...@@ -194,10 +250,9 @@ struct pnp_dev { ...@@ -194,10 +250,9 @@ struct pnp_dev {
int capabilities; int capabilities;
struct pnp_option *independent; struct pnp_option *independent;
struct pnp_option *dependent; struct pnp_option *dependent;
struct pnp_resource_table res; struct pnp_resource_table *res;
char name[PNP_NAME_LEN]; /* contains a human-readable name */ char name[PNP_NAME_LEN]; /* contains a human-readable name */
unsigned short regs; /* ISAPnP: supported registers */
int flags; /* used by protocols */ int flags; /* used by protocols */
struct proc_dir_entry *procent; /* device entry in /proc/bus/isapnp */ struct proc_dir_entry *procent; /* device entry in /proc/bus/isapnp */
void *data; void *data;
...@@ -328,8 +383,8 @@ struct pnp_protocol { ...@@ -328,8 +383,8 @@ struct pnp_protocol {
char *name; char *name;
/* resource control functions */ /* resource control functions */
int (*get) (struct pnp_dev *dev, struct pnp_resource_table *res); int (*get) (struct pnp_dev *dev);
int (*set) (struct pnp_dev *dev, struct pnp_resource_table *res); int (*set) (struct pnp_dev *dev);
int (*disable) (struct pnp_dev *dev); int (*disable) (struct pnp_dev *dev);
/* protocol specific suspend/resume */ /* protocol specific suspend/resume */
...@@ -358,20 +413,12 @@ extern struct bus_type pnp_bus_type; ...@@ -358,20 +413,12 @@ extern struct bus_type pnp_bus_type;
#if defined(CONFIG_PNP) #if defined(CONFIG_PNP)
/* device management */ /* device management */
int pnp_register_protocol(struct pnp_protocol *protocol);
void pnp_unregister_protocol(struct pnp_protocol *protocol);
int pnp_add_device(struct pnp_dev *dev);
int pnp_device_attach(struct pnp_dev *pnp_dev); 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;
extern int pnp_platform_devices; extern int pnp_platform_devices;
/* multidevice card support */ /* multidevice card support */
int pnp_add_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);
void pnp_remove_card_device(struct pnp_dev *dev);
int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card);
struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink, struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink,
const char *id, struct pnp_dev *from); const char *id, struct pnp_dev *from);
void pnp_release_card_device(struct pnp_dev *dev); void pnp_release_card_device(struct pnp_dev *dev);
...@@ -380,77 +427,42 @@ void pnp_unregister_card_driver(struct pnp_card_driver *drv); ...@@ -380,77 +427,42 @@ void pnp_unregister_card_driver(struct pnp_card_driver *drv);
extern struct list_head pnp_cards; extern struct list_head pnp_cards;
/* resource management */ /* resource management */
struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev);
struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
int priority);
int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data);
int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data);
int pnp_register_port_resource(struct pnp_option *option,
struct pnp_port *data);
int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data);
void pnp_init_resource_table(struct pnp_resource_table *table);
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); int pnp_auto_config_dev(struct pnp_dev *dev);
int pnp_validate_config(struct pnp_dev *dev);
int pnp_start_dev(struct pnp_dev *dev); int pnp_start_dev(struct pnp_dev *dev);
int pnp_stop_dev(struct pnp_dev *dev); int pnp_stop_dev(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, resource_size_t start,
resource_size_t size);
/* protocol helpers */ /* protocol helpers */
int pnp_is_active(struct pnp_dev *dev); int pnp_is_active(struct pnp_dev *dev);
int compare_pnp_id(struct pnp_id *pos, const char *id); 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); int pnp_register_driver(struct pnp_driver *drv);
void pnp_unregister_driver(struct pnp_driver *drv); void pnp_unregister_driver(struct pnp_driver *drv);
#else #else
/* device management */ /* device management */
static inline int pnp_register_protocol(struct pnp_protocol *protocol) { return -ENODEV; }
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_add_device(struct pnp_dev *dev) { return -ENODEV; }
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) { }
#define pnp_platform_devices 0 #define pnp_platform_devices 0
/* multidevice card support */ /* multidevice card support */
static inline int pnp_add_card(struct pnp_card *card) { return -ENODEV; }
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 void pnp_remove_card_device(struct pnp_dev *dev) { }
static inline int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card) { return -ENODEV; }
static inline struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink, const char *id, struct pnp_dev *from) { return NULL; } static inline struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink, const char *id, struct pnp_dev *from) { return NULL; }
static inline void pnp_release_card_device(struct pnp_dev *dev) { } 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 management */ /* resource management */
static inline struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev) { return NULL; }
static inline struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, int priority) { return NULL; }
static inline int pnp_register_irq_resource(struct pnp_option *option, 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_register_port_resource(struct pnp_option *option, struct pnp_port *data) { return -ENODEV; }
static inline int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data) { return -ENODEV; }
static inline void pnp_init_resource_table(struct pnp_resource_table *table) { }
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_start_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_start_dev(struct pnp_dev *dev) { return -ENODEV; }
static inline int pnp_stop_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_stop_dev(struct pnp_dev *dev) { return -ENODEV; }
static inline int pnp_activate_dev(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 int pnp_disable_dev(struct pnp_dev *dev) { return -ENODEV; }
static inline void pnp_resource_change(struct resource *resource, resource_size_t start, resource_size_t size) { }
/* protocol helpers */ /* protocol helpers */
static inline int pnp_is_active(struct pnp_dev *dev) { return 0; } static inline int pnp_is_active(struct pnp_dev *dev) { return 0; }
static inline int compare_pnp_id(struct pnp_id *pos, const char *id) { return -ENODEV; } 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 int pnp_register_driver(struct pnp_driver *drv) { return -ENODEV; }
static inline void pnp_unregister_driver(struct pnp_driver *drv) { } static inline void pnp_unregister_driver(struct pnp_driver *drv) { }
......
/*
* Include file for the interface to a PnP BIOS
*
* Original BIOS code (C) 1998 Christian Schmidt (chr.schmidt@tu-bs.de)
* PnP handler parts (c) 1998 Tom Lees <tom@lpsg.demon.co.uk>
* Minor reorganizations by David Hinds <dahinds@users.sourceforge.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LINUX_PNPBIOS_H
#define _LINUX_PNPBIOS_H
#ifdef __KERNEL__
#include <linux/types.h>
#include <linux/pnp.h>
/*
* Return codes
*/
#define PNP_SUCCESS 0x00
#define PNP_NOT_SET_STATICALLY 0x7f
#define PNP_UNKNOWN_FUNCTION 0x81
#define PNP_FUNCTION_NOT_SUPPORTED 0x82
#define PNP_INVALID_HANDLE 0x83
#define PNP_BAD_PARAMETER 0x84
#define PNP_SET_FAILED 0x85
#define PNP_EVENTS_NOT_PENDING 0x86
#define PNP_SYSTEM_NOT_DOCKED 0x87
#define PNP_NO_ISA_PNP_CARDS 0x88
#define PNP_UNABLE_TO_DETERMINE_DOCK_CAPABILITIES 0x89
#define PNP_CONFIG_CHANGE_FAILED_NO_BATTERY 0x8a
#define PNP_CONFIG_CHANGE_FAILED_RESOURCE_CONFLICT 0x8b
#define PNP_BUFFER_TOO_SMALL 0x8c
#define PNP_USE_ESCD_SUPPORT 0x8d
#define PNP_MESSAGE_NOT_SUPPORTED 0x8e
#define PNP_HARDWARE_ERROR 0x8f
#define ESCD_SUCCESS 0x00
#define ESCD_IO_ERROR_READING 0x55
#define ESCD_INVALID 0x56
#define ESCD_BUFFER_TOO_SMALL 0x59
#define ESCD_NVRAM_TOO_SMALL 0x5a
#define ESCD_FUNCTION_NOT_SUPPORTED 0x81
/*
* Events that can be received by "get event"
*/
#define PNPEV_ABOUT_TO_CHANGE_CONFIG 0x0001
#define PNPEV_DOCK_CHANGED 0x0002
#define PNPEV_SYSTEM_DEVICE_CHANGED 0x0003
#define PNPEV_CONFIG_CHANGED_FAILED 0x0004
#define PNPEV_UNKNOWN_SYSTEM_EVENT 0xffff
/* 0x8000 through 0xfffe are OEM defined */
/*
* Messages that should be sent through "send message"
*/
#define PNPMSG_OK 0x00
#define PNPMSG_ABORT 0x01
#define PNPMSG_UNDOCK_DEFAULT_ACTION 0x40
#define PNPMSG_POWER_OFF 0x41
#define PNPMSG_PNP_OS_ACTIVE 0x42
#define PNPMSG_PNP_OS_INACTIVE 0x43
/*
* Plug and Play BIOS flags
*/
#define PNPBIOS_NO_DISABLE 0x0001
#define PNPBIOS_NO_CONFIG 0x0002
#define PNPBIOS_OUTPUT 0x0004
#define PNPBIOS_INPUT 0x0008
#define PNPBIOS_BOOTABLE 0x0010
#define PNPBIOS_DOCK 0x0020
#define PNPBIOS_REMOVABLE 0x0040
#define pnpbios_is_static(x) (((x)->flags & 0x0100) == 0x0000)
#define pnpbios_is_dynamic(x) ((x)->flags & 0x0080)
/*
* Function Parameters
*/
#define PNPMODE_STATIC 1
#define PNPMODE_DYNAMIC 0
/* 0x8000 through 0xffff are OEM defined */
#pragma pack(1)
struct pnp_dev_node_info {
__u16 no_nodes;
__u16 max_node_size;
};
struct pnp_docking_station_info {
__u32 location_id;
__u32 serial;
__u16 capabilities;
};
struct pnp_isa_config_struc {
__u8 revision;
__u8 no_csns;
__u16 isa_rd_data_port;
__u16 reserved;
};
struct escd_info_struc {
__u16 min_escd_write_size;
__u16 escd_size;
__u32 nv_storage_base;
};
struct pnp_bios_node {
__u16 size;
__u8 handle;
__u32 eisa_id;
__u8 type_code[3];
__u16 flags;
__u8 data[0];
};
#pragma pack()
#ifdef CONFIG_PNPBIOS
/* non-exported */
extern struct pnp_dev_node_info node_info;
extern int pnp_bios_dev_node_info(struct pnp_dev_node_info *data);
extern int pnp_bios_get_dev_node(u8 *nodenum, char config,
struct pnp_bios_node *data);
extern int pnp_bios_set_dev_node(u8 nodenum, char config,
struct pnp_bios_node *data);
extern int pnp_bios_get_stat_res(char *info);
extern int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data);
extern int pnp_bios_escd_info(struct escd_info_struc *data);
extern int pnp_bios_read_escd(char *data, u32 nvram_base);
extern int pnp_bios_dock_station_info(struct pnp_docking_station_info *data);
#endif /* CONFIG_PNPBIOS */
#endif /* __KERNEL__ */
#endif /* _LINUX_PNPBIOS_H */
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