This patch contains many isapnp improvements including true get resource support
which is necessary to get active configs on boot and to ensure a resource set
was accepted. It also adds some initial MEM32 support, more work in that area
will come in the near future.
Please apply,
Adam
--- linux-2.5.58/drivers/pnp/isapnp/core.c Tue Jan 14 05:58:55 2003
+++ a/drivers/pnp/isapnp/core.c Sun Feb 9 10:42:49 2003
@@ -101,7 +101,6 @@
/* some prototypes */
-static int isapnp_config_prepare(struct pnp_dev *dev);
extern struct pnp_protocol isapnp_protocol;
static inline void write_data(unsigned char x)
@@ -260,7 +259,7 @@
* We cannot use NE2000 probe spaces for ISAPnP or we
* 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;
return 0;
@@ -580,14 +579,18 @@
int depnum, int size)
{
unsigned char tmp[17];
- struct pnp_mem32 *mem32;
+ struct pnp_mem *mem;
isapnp_peek(tmp, size);
- mem32 = isapnp_alloc(sizeof(struct pnp_mem32));
- if (!mem32)
+ mem = isapnp_alloc(sizeof(struct pnp_mem));
+ if (!mem)
return;
- memcpy(mem32->data, tmp, 17);
- pnp_add_mem32_resource(dev,depnum,mem32);
+ mem->min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
+ 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_fixed_mem32_resource(struct pnp_dev *dev,
int depnum, int size)
{
- unsigned char tmp[17];
- struct pnp_mem32 *mem32;
+ unsigned char tmp[9];
+ struct pnp_mem *mem;
isapnp_peek(tmp, size);
- mem32 = isapnp_alloc(sizeof(struct pnp_mem32));
- if (!mem32)
+ mem = isapnp_alloc(sizeof(struct pnp_mem));
+ if (!mem)
return;
- memcpy(mem32->data, tmp, 17);
- pnp_add_mem32_resource(dev,depnum,mem32);
+ mem->min = mem->max = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
+ 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 @@
switch (type) {
case _STAG_LOGDEVID:
if (size >= 5 && size <= 6) {
- isapnp_config_prepare(dev);
if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
return 1;
pnp_build_resource(dev,0);
@@ -723,7 +728,7 @@
size = 0;
break;
case _LTAG_ANSISTR:
- isapnp_parse_name(dev->name, sizeof(dev->name), &size);
+ isapnp_parse_name(dev->dev.name, sizeof(dev->dev.name), &size);
break;
case _LTAG_UNICODESTR:
/* silently ignore */
@@ -738,7 +743,7 @@
size = 0;
break;
case _LTAG_FIXEDMEM32RANGE:
- if (size != 17)
+ if (size != 9)
goto __skip;
isapnp_add_fixed_mem32_resource(dev, depnum, size);
size = 0;
@@ -746,7 +751,6 @@
case _STAG_END:
if (size > 0)
isapnp_skip_bytes(size);
- isapnp_config_prepare(dev);
return 1;
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);
@@ -755,7 +759,6 @@
if (size > 0)
isapnp_skip_bytes(size);
}
- isapnp_config_prepare(dev);
return 0;
}
@@ -790,7 +793,7 @@
case _STAG_VENDOR:
break;
case _LTAG_ANSISTR:
- isapnp_parse_name(card->name, sizeof(card->name), &size);
+ isapnp_parse_name(card->dev.name, sizeof(card->dev.name), &size);
break;
case _LTAG_UNICODESTR:
/* silently ignore */
@@ -852,6 +855,64 @@
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.
*/
@@ -861,6 +922,7 @@
int csn;
unsigned char header[9], checksum;
struct pnp_card *card;
+ struct pnp_dev *dev;
isapnp_wait();
isapnp_key();
@@ -893,8 +955,17 @@
printk(KERN_ERR "isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value);
card->checksum = isapnp_checksum_value;
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);
}
+ isapnp_wait();
return 0;
}
@@ -948,39 +1019,6 @@
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.
@@ -999,44 +1037,35 @@
EXPORT_SYMBOL(isapnp_wake);
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 */
- if (pnp_port_valid(dev, 0) == 0 &&
- pnp_mem_valid(dev, 0) == 0 &&
- pnp_irq_valid(dev, 0) == 0 &&
- pnp_dma_valid(dev, 0) == 0)
- dev->active = 0;
- else
- dev->active = 1;
- return 0;
+ int ret;
+ pnp_init_resource_table(res);
+ isapnp_cfg_begin(dev->card->number, dev->number);
+ ret = isapnp_parse_current_resources(dev, res);
+ isapnp_cfg_end();
+ return ret;
}
-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;
- isapnp_cfg_begin(dev->card->number, dev->number);
+
+ isapnp_cfg_begin(dev->card->number, dev->number);
dev->active = 1;
- dev->irq_resource[0] = cfg->request.irq_resource[0];
- dev->irq_resource[1] = cfg->request.irq_resource[1];
- dev->dma_resource[0] = cfg->request.dma_resource[0];
- dev->dma_resource[1] = cfg->request.dma_resource[1];
- 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);
+ for (tmp = 0; tmp < PNP_MAX_PORT && res->port_resource[tmp].flags & IORESOURCE_IO; tmp++)
+ isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), res->port_resource[tmp].start);
+ for (tmp = 0; tmp < PNP_MAX_IRQ && res->irq_resource[tmp].flags & IORESOURCE_IRQ; tmp++) {
+ int irq = res->irq_resource[tmp].start;
if (irq == 2)
irq = 9;
isapnp_write_byte(ISAPNP_CFG_IRQ+(tmp<<1), irq);
}
- for (tmp = 0; tmp < 2 && pnp_dma_valid(dev, tmp); tmp++)
- isapnp_write_byte(ISAPNP_CFG_DMA+tmp, pnp_dma(dev, tmp));
- for (tmp = 0; tmp < 4 && pnp_mem_valid(dev, tmp); tmp++)
- isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<2), (pnp_mem_start(dev, tmp) >> 8) & 0xffff);
+ for (tmp = 0; tmp < PNP_MAX_DMA && res->dma_resource[tmp].flags & IORESOURCE_DMA; tmp++)
+ isapnp_write_byte(ISAPNP_CFG_DMA+tmp, res->dma_resource[tmp].start);
+ for (tmp = 0; tmp < PNP_MAX_MEM && res->mem_resource[tmp].flags & IORESOURCE_MEM; tmp++)
+ 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_cfg_end();
return 0;
@@ -1046,7 +1075,7 @@
{
if (!dev || !dev->active)
return -EINVAL;
- isapnp_cfg_begin(dev->card->number, dev->number);
+ isapnp_cfg_begin(dev->card->number, dev->number);
isapnp_deactivate(dev->number);
dev->active = 0;
isapnp_cfg_end();
@@ -1127,11 +1156,11 @@
protocol_for_each_card(&isapnp_protocol,card) {
cards++;
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)
continue;
- pnp_card_for_each_dev(card,dev) {
- printk(KERN_INFO "isapnp: Device '%s'\n", dev->name[0]?dev->name:"Unknown");
+ card_for_each_dev(card,dev) {
+ printk(KERN_INFO "isapnp: Device '%s'\n", dev->dev.name[0]?dev->dev.name:"Unknown");
}
}
}