Commit 0f55fea4 authored by Adam Belay's avatar Adam Belay

ISAPnP Updates

Adds support for reading currently set resources.  Also a few other updates.
parent 91ff8c75
...@@ -101,7 +101,6 @@ static int isapnp_detected; ...@@ -101,7 +101,6 @@ static int isapnp_detected;
/* some prototypes */ /* some prototypes */
static int isapnp_config_prepare(struct pnp_dev *dev);
extern struct pnp_protocol isapnp_protocol; extern struct pnp_protocol isapnp_protocol;
static inline void write_data(unsigned char x) static inline void write_data(unsigned char x)
...@@ -260,7 +259,7 @@ static int isapnp_next_rdp(void) ...@@ -260,7 +259,7 @@ static int isapnp_next_rdp(void)
* We cannot use NE2000 probe spaces for ISAPnP or we * We cannot use NE2000 probe spaces for ISAPnP or we
* will lock up machines. * will lock up machines.
*/ */
if ((rdp < 0x280 || rdp > 0x380) && !check_region(rdp, 1)) if ((rdp < 0x280 || rdp > 0x380) && !check_region(rdp, 1))
{ {
isapnp_rdp = rdp; isapnp_rdp = rdp;
return 0; return 0;
...@@ -580,14 +579,18 @@ static void __init isapnp_add_mem32_resource(struct pnp_dev *dev, ...@@ -580,14 +579,18 @@ static void __init isapnp_add_mem32_resource(struct pnp_dev *dev,
int depnum, int size) int depnum, int size)
{ {
unsigned char tmp[17]; unsigned char tmp[17];
struct pnp_mem32 *mem32; struct pnp_mem *mem;
isapnp_peek(tmp, size); isapnp_peek(tmp, size);
mem32 = isapnp_alloc(sizeof(struct pnp_mem32)); mem = isapnp_alloc(sizeof(struct pnp_mem));
if (!mem32) if (!mem)
return; return;
memcpy(mem32->data, tmp, 17); mem->min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
pnp_add_mem32_resource(dev,depnum,mem32); mem->max = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
mem->align = (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9];
mem->size = (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13];
mem->flags = tmp[0];
pnp_add_mem_resource(dev,depnum,mem);
} }
/* /*
...@@ -597,15 +600,18 @@ static void __init isapnp_add_mem32_resource(struct pnp_dev *dev, ...@@ -597,15 +600,18 @@ static void __init isapnp_add_mem32_resource(struct pnp_dev *dev,
static void __init isapnp_add_fixed_mem32_resource(struct pnp_dev *dev, static void __init isapnp_add_fixed_mem32_resource(struct pnp_dev *dev,
int depnum, int size) int depnum, int size)
{ {
unsigned char tmp[17]; unsigned char tmp[9];
struct pnp_mem32 *mem32; struct pnp_mem *mem;
isapnp_peek(tmp, size); isapnp_peek(tmp, size);
mem32 = isapnp_alloc(sizeof(struct pnp_mem32)); mem = isapnp_alloc(sizeof(struct pnp_mem));
if (!mem32) if (!mem)
return; return;
memcpy(mem32->data, tmp, 17); mem->min = mem->max = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
pnp_add_mem32_resource(dev,depnum,mem32); mem->size = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
mem->align = 0;
mem->flags = tmp[0];
pnp_add_mem_resource(dev,depnum,mem);
} }
/* /*
...@@ -650,7 +656,6 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -650,7 +656,6 @@ static int __init isapnp_create_device(struct pnp_card *card,
switch (type) { switch (type) {
case _STAG_LOGDEVID: case _STAG_LOGDEVID:
if (size >= 5 && size <= 6) { if (size >= 5 && size <= 6) {
isapnp_config_prepare(dev);
if ((dev = isapnp_parse_device(card, size, number++)) == NULL) if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
return 1; return 1;
pnp_build_resource(dev,0); pnp_build_resource(dev,0);
...@@ -723,7 +728,7 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -723,7 +728,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
size = 0; size = 0;
break; break;
case _LTAG_ANSISTR: case _LTAG_ANSISTR:
isapnp_parse_name(dev->name, sizeof(dev->name), &size); isapnp_parse_name(dev->dev.name, sizeof(dev->dev.name), &size);
break; break;
case _LTAG_UNICODESTR: case _LTAG_UNICODESTR:
/* silently ignore */ /* silently ignore */
...@@ -738,7 +743,7 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -738,7 +743,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
size = 0; size = 0;
break; break;
case _LTAG_FIXEDMEM32RANGE: case _LTAG_FIXEDMEM32RANGE:
if (size != 17) if (size != 9)
goto __skip; goto __skip;
isapnp_add_fixed_mem32_resource(dev, depnum, size); isapnp_add_fixed_mem32_resource(dev, depnum, size);
size = 0; size = 0;
...@@ -746,7 +751,6 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -746,7 +751,6 @@ static int __init isapnp_create_device(struct pnp_card *card,
case _STAG_END: case _STAG_END:
if (size > 0) if (size > 0)
isapnp_skip_bytes(size); isapnp_skip_bytes(size);
isapnp_config_prepare(dev);
return 1; return 1;
default: default:
printk(KERN_ERR "isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n", type, dev->number, card->number); printk(KERN_ERR "isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n", type, dev->number, card->number);
...@@ -755,7 +759,6 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -755,7 +759,6 @@ static int __init isapnp_create_device(struct pnp_card *card,
if (size > 0) if (size > 0)
isapnp_skip_bytes(size); isapnp_skip_bytes(size);
} }
isapnp_config_prepare(dev);
return 0; return 0;
} }
...@@ -790,7 +793,7 @@ static void __init isapnp_parse_resource_map(struct pnp_card *card) ...@@ -790,7 +793,7 @@ static void __init isapnp_parse_resource_map(struct pnp_card *card)
case _STAG_VENDOR: case _STAG_VENDOR:
break; break;
case _LTAG_ANSISTR: case _LTAG_ANSISTR:
isapnp_parse_name(card->name, sizeof(card->name), &size); isapnp_parse_name(card->dev.name, sizeof(card->dev.name), &size);
break; break;
case _LTAG_UNICODESTR: case _LTAG_UNICODESTR:
/* silently ignore */ /* silently ignore */
...@@ -852,6 +855,64 @@ static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor, ...@@ -852,6 +855,64 @@ static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor,
pnpc_add_id(id,card); pnpc_add_id(id,card);
} }
static int isapnp_parse_current_resources(struct pnp_dev *dev, struct pnp_resource_table * res)
{
int tmp, ret;
struct pnp_rule_table rule;
if (dev->rule)
rule = *dev->rule;
else {
if (!pnp_generate_rule(dev,1,&rule))
return -EINVAL;
}
dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE);
if (dev->active) {
for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {
ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1));
if (!ret)
continue;
res->port_resource[tmp].start = ret;
if (rule.port[tmp])
res->port_resource[tmp].end = ret + rule.port[tmp]->size - 1;
else
res->port_resource[tmp].end = ret + 1; /* all we can do is assume 1 :-( */
res->port_resource[tmp].flags = IORESOURCE_IO;
}
for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) {
ret = isapnp_read_dword(ISAPNP_CFG_MEM + (tmp << 3));
if (!ret)
continue;
res->mem_resource[tmp].start = ret;
if (rule.mem[tmp])
res->mem_resource[tmp].end = ret + rule.mem[tmp]->size - 1;
else
res->mem_resource[tmp].end = ret + 1; /* all we can do is assume 1 :-( */
res->mem_resource[tmp].flags = IORESOURCE_MEM;
}
for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) {
ret = (isapnp_read_word(ISAPNP_CFG_IRQ + (tmp << 1)) >> 8);
if (!ret)
continue;
res->irq_resource[tmp].start = res->irq_resource[tmp].end = ret;
res->irq_resource[tmp].flags = IORESOURCE_IRQ;
}
for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) {
ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp);
pnp_info("dma %d", tmp);
if (ret == 4)
continue;
if (rule.dma[tmp]) { /* some isapnp systems forget to set this to 4 so we have to check */
res->dma_resource[tmp].start = res->dma_resource[tmp].end = ret;
res->dma_resource[tmp].flags = IORESOURCE_DMA;
}
}
}
return 0;
}
/* /*
* Build device list for all present ISA PnP devices. * Build device list for all present ISA PnP devices.
*/ */
...@@ -861,6 +922,7 @@ static int __init isapnp_build_device_list(void) ...@@ -861,6 +922,7 @@ static int __init isapnp_build_device_list(void)
int csn; int csn;
unsigned char header[9], checksum; unsigned char header[9], checksum;
struct pnp_card *card; struct pnp_card *card;
struct pnp_dev *dev;
isapnp_wait(); isapnp_wait();
isapnp_key(); isapnp_key();
...@@ -893,8 +955,17 @@ static int __init isapnp_build_device_list(void) ...@@ -893,8 +955,17 @@ static int __init isapnp_build_device_list(void)
printk(KERN_ERR "isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value); printk(KERN_ERR "isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value);
card->checksum = isapnp_checksum_value; card->checksum = isapnp_checksum_value;
card->protocol = &isapnp_protocol; card->protocol = &isapnp_protocol;
/* read the current resource data */
card_for_each_dev(card,dev) {
isapnp_device(dev->number);
pnp_init_resource_table(&dev->res);
isapnp_parse_current_resources(dev, &dev->res);
}
pnpc_add_card(card); pnpc_add_card(card);
} }
isapnp_wait();
return 0; return 0;
} }
...@@ -948,39 +1019,6 @@ int isapnp_cfg_end(void) ...@@ -948,39 +1019,6 @@ int isapnp_cfg_end(void)
return 0; return 0;
} }
static int isapnp_config_prepare(struct pnp_dev *dev)
{
int idx;
if (dev == NULL)
return -EINVAL;
if (dev->active || dev->lock_resources)
return -EBUSY;
for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++) {
dev->irq_resource[idx].name = NULL;
dev->irq_resource[idx].start = -1;
dev->irq_resource[idx].end = -1;
dev->irq_resource[idx].flags = IORESOURCE_IRQ|IORESOURCE_UNSET;
}
for (idx = 0; idx < DEVICE_COUNT_DMA; idx++) {
dev->dma_resource[idx].name = NULL;
dev->dma_resource[idx].start = -1;
dev->dma_resource[idx].end = -1;
dev->dma_resource[idx].flags = IORESOURCE_DMA|IORESOURCE_UNSET;
}
for (idx = 0; idx < DEVICE_COUNT_IO; idx++) {
dev->io_resource[idx].name = NULL;
dev->io_resource[idx].start = 0;
dev->io_resource[idx].end = 0;
dev->io_resource[idx].flags = IORESOURCE_IO|IORESOURCE_UNSET;
}
for (idx = 0; idx < DEVICE_COUNT_MEM; idx++) {
dev->mem_resource[idx].name = NULL;
dev->mem_resource[idx].start = 0;
dev->mem_resource[idx].end = 0;
dev->mem_resource[idx].flags = IORESOURCE_MEM|IORESOURCE_UNSET;
}
return 0;
}
/* /*
* Inititialization. * Inititialization.
...@@ -999,44 +1037,35 @@ EXPORT_SYMBOL(isapnp_write_dword); ...@@ -999,44 +1037,35 @@ EXPORT_SYMBOL(isapnp_write_dword);
EXPORT_SYMBOL(isapnp_wake); EXPORT_SYMBOL(isapnp_wake);
EXPORT_SYMBOL(isapnp_device); EXPORT_SYMBOL(isapnp_device);
static int isapnp_get_resources(struct pnp_dev *dev) static int isapnp_get_resources(struct pnp_dev *dev, struct pnp_resource_table * res)
{ {
/* We don't need to do anything but this, the rest is taken care of */ int ret;
if (pnp_port_valid(dev, 0) == 0 && pnp_init_resource_table(res);
pnp_mem_valid(dev, 0) == 0 && isapnp_cfg_begin(dev->card->number, dev->number);
pnp_irq_valid(dev, 0) == 0 && ret = isapnp_parse_current_resources(dev, res);
pnp_dma_valid(dev, 0) == 0) isapnp_cfg_end();
dev->active = 0; return ret;
else
dev->active = 1;
return 0;
} }
static int isapnp_set_resources(struct pnp_dev *dev, struct pnp_cfg *cfg) static int isapnp_set_resources(struct pnp_dev *dev, struct pnp_resource_table * res)
{ {
int tmp; int tmp;
isapnp_cfg_begin(dev->card->number, dev->number);
isapnp_cfg_begin(dev->card->number, dev->number);
dev->active = 1; dev->active = 1;
dev->irq_resource[0] = cfg->request.irq_resource[0]; for (tmp = 0; tmp < PNP_MAX_PORT && res->port_resource[tmp].flags & IORESOURCE_IO; tmp++)
dev->irq_resource[1] = cfg->request.irq_resource[1]; isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), res->port_resource[tmp].start);
dev->dma_resource[0] = cfg->request.dma_resource[0]; for (tmp = 0; tmp < PNP_MAX_IRQ && res->irq_resource[tmp].flags & IORESOURCE_IRQ; tmp++) {
dev->dma_resource[1] = cfg->request.dma_resource[1]; int irq = res->irq_resource[tmp].start;
for (tmp = 0; tmp < DEVICE_COUNT_IO; tmp++)
dev->io_resource[tmp] = cfg->request.io_resource[tmp];
for (tmp = 0; tmp < DEVICE_COUNT_MEM; tmp++)
dev->mem_resource[tmp] = cfg->request.mem_resource[tmp];
for (tmp = 0; tmp < 8 && pnp_port_valid(dev, tmp); tmp++)
isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), pnp_port_start(dev, tmp));
for (tmp = 0; tmp < 2 && pnp_irq_valid(dev, tmp); tmp++) {
int irq = pnp_irq(dev, tmp);
if (irq == 2) if (irq == 2)
irq = 9; irq = 9;
isapnp_write_byte(ISAPNP_CFG_IRQ+(tmp<<1), irq); isapnp_write_byte(ISAPNP_CFG_IRQ+(tmp<<1), irq);
} }
for (tmp = 0; tmp < 2 && pnp_dma_valid(dev, tmp); tmp++) for (tmp = 0; tmp < PNP_MAX_DMA && res->dma_resource[tmp].flags & IORESOURCE_DMA; tmp++)
isapnp_write_byte(ISAPNP_CFG_DMA+tmp, pnp_dma(dev, tmp)); isapnp_write_byte(ISAPNP_CFG_DMA+tmp, res->dma_resource[tmp].start);
for (tmp = 0; tmp < 4 && pnp_mem_valid(dev, tmp); tmp++) for (tmp = 0; tmp < PNP_MAX_MEM && res->mem_resource[tmp].flags & IORESOURCE_MEM; tmp++)
isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<2), (pnp_mem_start(dev, tmp) >> 8) & 0xffff); isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<2), (res->mem_resource[tmp].start >> 8) & 0xffff);
/* FIXME: We aren't handling 32bit mems properly here */
isapnp_activate(dev->number); isapnp_activate(dev->number);
isapnp_cfg_end(); isapnp_cfg_end();
return 0; return 0;
...@@ -1046,7 +1075,7 @@ static int isapnp_disable_resources(struct pnp_dev *dev) ...@@ -1046,7 +1075,7 @@ static int isapnp_disable_resources(struct pnp_dev *dev)
{ {
if (!dev || !dev->active) if (!dev || !dev->active)
return -EINVAL; return -EINVAL;
isapnp_cfg_begin(dev->card->number, dev->number); isapnp_cfg_begin(dev->card->number, dev->number);
isapnp_deactivate(dev->number); isapnp_deactivate(dev->number);
dev->active = 0; dev->active = 0;
isapnp_cfg_end(); isapnp_cfg_end();
...@@ -1127,11 +1156,11 @@ int __init isapnp_init(void) ...@@ -1127,11 +1156,11 @@ 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", card->name[0]?card->name:"Unknown"); printk(KERN_INFO "isapnp: Card '%s'\n", card->dev.name[0]?card->dev.name:"Unknown");
if (isapnp_verbose < 2) if (isapnp_verbose < 2)
continue; continue;
pnp_card_for_each_dev(card,dev) { card_for_each_dev(card,dev) {
printk(KERN_INFO "isapnp: Device '%s'\n", dev->name[0]?dev->name:"Unknown"); printk(KERN_INFO "isapnp: Device '%s'\n", dev->dev.name[0]?dev->dev.name:"Unknown");
} }
} }
} }
......
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