diff options
Diffstat (limited to 'drivers/net/arcnet/com90xx.c')
-rw-r--r-- | drivers/net/arcnet/com90xx.c | 132 |
1 files changed, 94 insertions, 38 deletions
diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index 6c2c9b9ac6db..43150b2bd13f 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -53,7 +53,7 @@ /* Internal function declarations */ -static int com90xx_found(int ioaddr, int airq, u_long shmem); +static int com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem *); static void com90xx_command(struct net_device *dev, int command); static int com90xx_status(struct net_device *dev); static void com90xx_setmask(struct net_device *dev, int mask); @@ -116,14 +116,26 @@ static void __init com90xx_probe(void) unsigned long airqmask; int ports[(0x3f0 - 0x200) / 16 + 1] = {0}; - u_long shmems[(0xFF800 - 0xA0000) / 2048 + 1] = - {0}; + unsigned long *shmems; + void __iomem **iomem; int numports, numshmems, *port; u_long *p; + int index; if (!io && !irq && !shmem && !*device && com90xx_skip_probe) return; + shmems = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(unsigned long), + GFP_KERNEL); + if (!shmems) + return; + iomem = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(void __iomem *), + GFP_KERNEL); + if (!iomem) { + kfree(shmems); + return; + } + BUGLVL(D_NORMAL) printk(VERSION); /* set up the arrays where we'll store the possible probe addresses */ @@ -179,6 +191,8 @@ static void __init com90xx_probe(void) if (!numports) { BUGMSG2(D_NORMAL, "S1: No ARCnet cards found.\n"); + kfree(shmems); + kfree(iomem); return; } /* Stage 2: we have now reset any possible ARCnet cards, so we can't @@ -202,8 +216,8 @@ static void __init com90xx_probe(void) * 0xD1 byte in the right place, or are read-only. */ numprint = -1; - for (p = &shmems[0]; p < shmems + numshmems; p++) { - u_long ptr = *p; + for (index = 0, p = &shmems[0]; index < numshmems; p++, index++) { + void __iomem *base; numprint++; numprint %= 8; @@ -213,38 +227,49 @@ static void __init com90xx_probe(void) } BUGMSG2(D_INIT, "%lXh ", *p); - if (!request_mem_region(*p, BUFFER_SIZE, "arcnet (90xx)")) { + if (!request_mem_region(*p, MIRROR_SIZE, "arcnet (90xx)")) { BUGMSG2(D_INIT_REASONS, "(request_mem_region)\n"); BUGMSG2(D_INIT_REASONS, "Stage 3: "); BUGLVL(D_INIT_REASONS) numprint = 0; - *p-- = shmems[--numshmems]; - continue; + goto out; + } + base = ioremap(*p, MIRROR_SIZE); + if (!base) { + BUGMSG2(D_INIT_REASONS, "(ioremap)\n"); + BUGMSG2(D_INIT_REASONS, "Stage 3: "); + BUGLVL(D_INIT_REASONS) numprint = 0; + goto out1; } - if (isa_readb(ptr) != TESTvalue) { + if (readb(base) != TESTvalue) { BUGMSG2(D_INIT_REASONS, "(%02Xh != %02Xh)\n", - isa_readb(ptr), TESTvalue); + readb(base), TESTvalue); BUGMSG2(D_INIT_REASONS, "S3: "); BUGLVL(D_INIT_REASONS) numprint = 0; - release_mem_region(*p, BUFFER_SIZE); - *p-- = shmems[--numshmems]; - continue; + goto out2; } /* By writing 0x42 to the TESTvalue location, we also make * sure no "mirror" shmem areas show up - if they occur * in another pass through this loop, they will be discarded * because *cptr != TESTvalue. */ - isa_writeb(0x42, ptr); - if (isa_readb(ptr) != 0x42) { + writeb(0x42, base); + if (readb(base) != 0x42) { BUGMSG2(D_INIT_REASONS, "(read only)\n"); BUGMSG2(D_INIT_REASONS, "S3: "); - release_mem_region(*p, BUFFER_SIZE); - *p-- = shmems[--numshmems]; - continue; + goto out2; } BUGMSG2(D_INIT_REASONS, "\n"); BUGMSG2(D_INIT_REASONS, "S3: "); BUGLVL(D_INIT_REASONS) numprint = 0; + iomem[index] = base; + continue; + out2: + iounmap(base); + out1: + release_mem_region(*p, MIRROR_SIZE); + out: + *p-- = shmems[--numshmems]; + index--; } BUGMSG2(D_INIT, "\n"); @@ -252,6 +277,8 @@ static void __init com90xx_probe(void) BUGMSG2(D_NORMAL, "S3: No ARCnet cards found.\n"); for (port = &ports[0]; port < ports + numports; port++) release_region(*port, ARCNET_TOTAL_SIZE); + kfree(shmems); + kfree(iomem); return; } /* Stage 4: something of a dummy, to report the shmems that are @@ -351,30 +378,32 @@ static void __init com90xx_probe(void) mdelay(RESETtime); } else { /* just one shmem and port, assume they match */ - isa_writeb(TESTvalue, shmems[0]); + writeb(TESTvalue, iomem[0]); } #else inb(_RESET); mdelay(RESETtime); #endif - for (p = &shmems[0]; p < shmems + numshmems; p++) { - u_long ptr = *p; + for (index = 0; index < numshmems; index++) { + u_long ptr = shmems[index]; + void __iomem *base = iomem[index]; - if (isa_readb(ptr) == TESTvalue) { /* found one */ + if (readb(base) == TESTvalue) { /* found one */ BUGMSG2(D_INIT, "%lXh)\n", *p); openparen = 0; /* register the card */ - if (com90xx_found(*port, airq, *p) == 0) + if (com90xx_found(*port, airq, ptr, base) == 0) found = 1; numprint = -1; /* remove shmem from the list */ - *p = shmems[--numshmems]; + shmems[index] = shmems[--numshmems]; + iomem[index] = iomem[numshmems]; break; /* go to the next I/O port */ } else { - BUGMSG2(D_INIT_REASONS, "%Xh-", isa_readb(ptr)); + BUGMSG2(D_INIT_REASONS, "%Xh-", readb(base)); } } @@ -391,17 +420,40 @@ static void __init com90xx_probe(void) BUGLVL(D_INIT_REASONS) printk("\n"); /* Now put back TESTvalue on all leftover shmems. */ - for (p = &shmems[0]; p < shmems + numshmems; p++) { - isa_writeb(TESTvalue, *p); - release_mem_region(*p, BUFFER_SIZE); + for (index = 0; index < numshmems; index++) { + writeb(TESTvalue, iomem[index]); + iounmap(iomem[index]); + release_mem_region(shmems[index], MIRROR_SIZE); } + kfree(shmems); + kfree(iomem); } +static int check_mirror(unsigned long addr, size_t size) +{ + void __iomem *p; + int res = -1; + + if (!request_mem_region(addr, size, "arcnet (90xx)")) + return -1; + + p = ioremap(addr, size); + if (p) { + if (readb(p) == TESTvalue) + res = 1; + else + res = 0; + iounmap(p); + } + + release_mem_region(addr, size); + return res; +} /* Set up the struct net_device associated with this card. Called after * probing succeeds. */ -static int __init com90xx_found(int ioaddr, int airq, u_long shmem) +static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem *p) { struct net_device *dev = NULL; struct arcnet_local *lp; @@ -412,7 +464,8 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem) dev = alloc_arcdev(device); if (!dev) { BUGMSG2(D_NORMAL, "com90xx: Can't allocate device!\n"); - release_mem_region(shmem, BUFFER_SIZE); + iounmap(p); + release_mem_region(shmem, MIRROR_SIZE); return -ENOMEM; } lp = dev->priv; @@ -423,24 +476,27 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem) * 2k (or there are no mirrors at all) but on some, it's 4k. */ mirror_size = MIRROR_SIZE; - if (isa_readb(shmem) == TESTvalue - && isa_readb(shmem - mirror_size) != TESTvalue - && isa_readb(shmem - 2 * mirror_size) == TESTvalue) - mirror_size *= 2; + if (readb(p) == TESTvalue && + check_mirror(shmem - MIRROR_SIZE, MIRROR_SIZE) == 0 && + check_mirror(shmem - 2 * MIRROR_SIZE, MIRROR_SIZE) == 1) + mirror_size = 2 * MIRROR_SIZE; - first_mirror = last_mirror = shmem; - while (isa_readb(first_mirror) == TESTvalue) + first_mirror = shmem - mirror_size; + while (check_mirror(first_mirror, mirror_size) == 1) first_mirror -= mirror_size; first_mirror += mirror_size; - while (isa_readb(last_mirror) == TESTvalue) + last_mirror = shmem + mirror_size; + while (check_mirror(last_mirror, mirror_size) == 1) last_mirror += mirror_size; last_mirror -= mirror_size; dev->mem_start = first_mirror; dev->mem_end = last_mirror + MIRROR_SIZE - 1; - release_mem_region(shmem, BUFFER_SIZE); + iounmap(p); + release_mem_region(shmem, MIRROR_SIZE); + if (!request_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1, "arcnet (90xx)")) goto err_free_dev; |