📄 com90xx.c
字号:
airq = probe_irq_off(airqmask); if (airq <= 0) { BUGMSG2(D_INIT_REASONS, "(airq=%d)\n", airq); BUGMSG2(D_INIT_REASONS, "S5: "); BUGLVL(D_INIT_REASONS) numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); *port-- = ports[--numports]; continue; } } else { airq = irq; } BUGMSG2(D_INIT, "(%d,", airq); openparen = 1; /* Everything seems okay. But which shmem, if any, puts * back its signature byte when the card is reset? * * If there are multiple cards installed, there might be * multiple shmems still in the list. */#ifdef FAST_PROBE if (numports > 1 || numshmems > 1) { inb(_RESET); mdelay(RESETtime); } else { /* just one shmem and port, assume they match */ isa_writeb(TESTvalue, shmems[0]); }#else inb(_RESET); mdelay(RESETtime);#endif for (p = &shmems[0]; p < shmems + numshmems; p++) { u_long ptr = *p; if (isa_readb(ptr) == TESTvalue) { /* found one */ BUGMSG2(D_INIT, "%lXh)\n", *p); openparen = 0; /* register the card */ if (com90xx_found(*port, airq, *p) == 0) found = 1; numprint = -1; /* remove shmem from the list */ *p = shmems[--numshmems]; break; /* go to the next I/O port */ } else { BUGMSG2(D_INIT_REASONS, "%Xh-", isa_readb(ptr)); } } if (openparen) { BUGLVL(D_INIT) printk("no matching shmem)\n"); BUGLVL(D_INIT_REASONS) printk("S5: "); BUGLVL(D_INIT_REASONS) numprint = 0; } if (!found) release_region(*port, ARCNET_TOTAL_SIZE); *port-- = ports[--numports]; } 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); }}/* 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){ struct net_device *dev = NULL; struct arcnet_local *lp; u_long first_mirror, last_mirror; int mirror_size; /* allocate struct net_device */ dev = alloc_arcdev(device); if (!dev) { BUGMSG2(D_NORMAL, "com90xx: Can't allocate device!\n"); release_mem_region(shmem, BUFFER_SIZE); return -ENOMEM; } lp = dev->priv; /* find the real shared memory start/end points, including mirrors */ /* guess the actual size of one "memory mirror" - the number of * bytes between copies of the shared memory. On most cards, it's * 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; first_mirror = last_mirror = shmem; while (isa_readb(first_mirror) == TESTvalue) first_mirror -= mirror_size; first_mirror += mirror_size; while (isa_readb(last_mirror) == TESTvalue) 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); if (!request_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1, "arcnet (90xx)")) goto err_free_dev; /* reserve the irq */ if (request_irq(airq, &arcnet_interrupt, 0, "arcnet (90xx)", dev)) { BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", airq); goto err_release_mem; } dev->irq = airq; /* Initialize the rest of the device structure. */ lp->card_name = "COM90xx"; lp->hw.command = com90xx_command; lp->hw.status = com90xx_status; lp->hw.intmask = com90xx_setmask; lp->hw.reset = com90xx_reset; lp->hw.owner = THIS_MODULE; lp->hw.copy_to_card = com90xx_copy_to_card; lp->hw.copy_from_card = com90xx_copy_from_card; lp->mem_start = ioremap(dev->mem_start, dev->mem_end - dev->mem_start + 1); if (!lp->mem_start) { BUGMSG(D_NORMAL, "Can't remap device memory!\n"); goto err_free_irq; } /* get and check the station ID from offset 1 in shmem */ dev->dev_addr[0] = readb(lp->mem_start + 1); dev->base_addr = ioaddr; BUGMSG(D_NORMAL, "COM90xx station %02Xh found at %03lXh, IRQ %d, " "ShMem %lXh (%ld*%xh).\n", dev->dev_addr[0], dev->base_addr, dev->irq, dev->mem_start, (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size); if (register_netdev(dev)) goto err_unmap; cards[numcards++] = dev; return 0;err_unmap: iounmap(lp->mem_start);err_free_irq: free_irq(dev->irq, dev);err_release_mem: release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);err_free_dev: free_netdev(dev); return -EIO;}static void com90xx_command(struct net_device *dev, int cmd){ short ioaddr = dev->base_addr; ACOMMAND(cmd);}static int com90xx_status(struct net_device *dev){ short ioaddr = dev->base_addr; return ASTATUS();}static void com90xx_setmask(struct net_device *dev, int mask){ short ioaddr = dev->base_addr; AINTMASK(mask);}/* * Do a hardware reset on the card, and set up necessary registers. * * This should be called as little as possible, because it disrupts the * token on the network (causes a RECON) and requires a significant delay. * * However, it does make sure the card is in a defined state. */int com90xx_reset(struct net_device *dev, int really_reset){ struct arcnet_local *lp = (struct arcnet_local *) dev->priv; short ioaddr = dev->base_addr; BUGMSG(D_INIT, "Resetting (status=%02Xh)\n", ASTATUS()); if (really_reset) { /* reset the card */ inb(_RESET); mdelay(RESETtime); } ACOMMAND(CFLAGScmd | RESETclear); /* clear flags & end reset */ ACOMMAND(CFLAGScmd | CONFIGclear); /* don't do this until we verify that it doesn't hurt older cards! */ /* outb(inb(_CONFIG) | ENABLE16flag, _CONFIG); */ /* verify that the ARCnet signature byte is present */ if (readb(lp->mem_start) != TESTvalue) { if (really_reset) BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); return 1; } /* enable extended (512-byte) packets */ ACOMMAND(CONFIGcmd | EXTconf); /* clean out all the memory to make debugging make more sense :) */ BUGLVL(D_DURING) memset_io(lp->mem_start, 0x42, 2048); /* done! return success. */ return 0;}static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset, void *buf, int count){ struct arcnet_local *lp = (struct arcnet_local *) dev->priv; void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count));}static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset, void *buf, int count){ struct arcnet_local *lp = (struct arcnet_local *) dev->priv; void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));}MODULE_LICENSE("GPL");static int __init com90xx_init(void){ if (irq == 2) irq = 9; com90xx_probe(); if (!numcards) return -EIO; return 0;}static void __exit com90xx_exit(void){ struct net_device *dev; struct arcnet_local *lp; int count; for (count = 0; count < numcards; count++) { dev = cards[count]; lp = (struct arcnet_local *) dev->priv; unregister_netdev(dev); free_irq(dev->irq, dev); iounmap(lp->mem_start); release_region(dev->base_addr, ARCNET_TOTAL_SIZE); release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1); free_netdev(dev); }}module_init(com90xx_init);module_exit(com90xx_exit);#ifndef MODULEstatic int __init com90xx_setup(char *s){ int ints[8]; s = get_options(s, 8, ints); if (!ints[0] && !*s) { printk("com90xx: Disabled.\n"); return 1; } switch (ints[0]) { default: /* ERROR */ printk("com90xx: Too many arguments.\n"); case 3: /* Mem address */ shmem = ints[3]; case 2: /* IRQ */ irq = ints[2]; case 1: /* IO address */ io = ints[1]; } if (*s) snprintf(device, sizeof(device), "%s", s); return 1;}__setup("com90xx=", com90xx_setup);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -