static inline int ether3_probe_bus_8(struct net_device *dev, int val) { int write_low, write_high, read_low, read_high; write_low = val & 255; write_high = val >> 8; printk(KERN_DEBUG "ether3_probe: write8 [%02X:%02X]", write_high, write_low); ether3_outb(write_low, REG_RECVPTR); ether3_outb(write_high, REG_RECVPTR + 4); read_low = ether3_inb(REG_RECVPTR); read_high = ether3_inb(REG_RECVPTR + 4); printk(", read8 [%02X:%02X]\n", read_high, read_low); return read_low == write_low && read_high == write_high; }
static int __init ether3_init_2(struct net_device *dev) { struct dev_priv *priv = (struct dev_priv *)dev->priv; int i; priv->regs.config1 = CFG1_RECVCOMPSTAT0|CFG1_DMABURST8; priv->regs.config2 = CFG2_CTRLO|CFG2_RECVCRC|CFG2_ERRENCRC; priv->regs.command = 0; /* * Set up our hardware address */ ether3_outw(priv->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1); for (i = 0; i < 6; i++) ether3_outb(dev->dev_addr[i], REG_BUFWIN); if (dev->flags & IFF_PROMISC) priv->regs.config1 |= CFG1_RECVPROMISC; else if (dev->flags & IFF_MULTICAST) priv->regs.config1 |= CFG1_RECVSPECBRMULTI; else priv->regs.config1 |= CFG1_RECVSPECBROAD; /* * There is a problem with the NQ8005 in that it occasionally loses the * last two bytes. To get round this problem, we receive the CRC as * well. That way, if we do loose the last two, then it doesn't matter. */ ether3_outw(priv->regs.config1 | CFG1_TRANSEND, REG_CONFIG1); ether3_outw((TX_END>>8) - 1, REG_BUFWIN); ether3_outw(priv->rx_head, REG_RECVPTR); ether3_outw(0, REG_TRANSMITPTR); ether3_outw(priv->rx_head >> 8, REG_RECVEND); ether3_outw(priv->regs.config2, REG_CONFIG2); ether3_outw(priv->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1); ether3_outw(priv->regs.command, REG_COMMAND); i = ether3_ramtest(dev, 0x5A); if(i) return i; i = ether3_ramtest(dev, 0x1E); if(i) return i; ether3_setbuffer(dev, buffer_write, 0); ether3_writelong(dev, 0); return 0; }
/* * The inverse routine to ether3_open(). */ static int ether3_close(struct net_device *dev) { netif_stop_queue(dev); disable_irq(dev->irq); ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND); priv(dev)->regs.command = 0; while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON)) barrier(); ether3_outb(0x80, REG_CONFIG2 + 4); ether3_outw(0, REG_COMMAND); free_irq(dev->irq, dev); return 0; }
/* * The inverse routine to ether3_open(). */ static int ether3_close(struct device *dev) { struct dev_priv *priv = (struct dev_priv *)dev->priv; dev->tbusy = 1; dev->start = 0; disable_irq(dev->irq); ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND); priv->regs.command = 0; while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON)); ether3_outb(0x80, REG_CONFIG2 + 1); ether3_outw(0, REG_COMMAND); free_irq(dev->irq, dev); MOD_DEC_USE_COUNT; return 0; }
static void ether3_init_for_open(struct net_device *dev) { struct dev_priv *priv = (struct dev_priv *)dev->priv; int i; memset(&priv->stats, 0, sizeof(struct net_device_stats)); /* Reset the chip */ ether3_outw(CFG2_RESET, REG_CONFIG2); udelay(4); priv->regs.command = 0; ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND); while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON)); ether3_outw(priv->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1); for (i = 0; i < 6; i++) ether3_outb(dev->dev_addr[i], REG_BUFWIN); priv->tx_head = 0; priv->tx_tail = 0; priv->regs.config2 |= CFG2_CTRLO; priv->rx_head = RX_START; ether3_outw(priv->regs.config1 | CFG1_TRANSEND, REG_CONFIG1); ether3_outw((TX_END>>8) - 1, REG_BUFWIN); ether3_outw(priv->rx_head, REG_RECVPTR); ether3_outw(priv->rx_head >> 8, REG_RECVEND); ether3_outw(0, REG_TRANSMITPTR); ether3_outw(priv->regs.config2, REG_CONFIG2); ether3_outw(priv->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1); ether3_setbuffer(dev, buffer_write, 0); ether3_writelong(dev, 0); priv->regs.command = CMD_ENINTRX | CMD_ENINTTX; ether3_outw(priv->regs.command | CMD_RXON, REG_COMMAND); }
/* * This is the real probe routine. */ __initfunc(static int ether3_probe1(struct device *dev)) { static unsigned version_printed = 0; struct dev_priv *priv; unsigned int i, bus_type, error = ENODEV; if (net_debug && version_printed++ == 0) printk(version); if (!dev->priv) { dev->priv = kmalloc(sizeof (struct dev_priv), GFP_KERNEL); if (!dev->priv) { printk(KERN_ERR "ether3_probe1: no memory\n"); return -ENOMEM; } } priv = (struct dev_priv *) dev->priv; memset(priv, 0, sizeof(struct dev_priv)); request_region(dev->base_addr, 128, "ether3"); /* Reset card... */ ether3_outb(0x80, REG_CONFIG2 + 1); bus_type = BUS_UNKNOWN; udelay(4); /* Test using Receive Pointer (16-bit register) to find out * how the ether3 is connected to the bus... */ if (ether3_probe_bus_8(dev, 0x100) && ether3_probe_bus_8(dev, 0x201)) bus_type = BUS_8; if (bus_type == BUS_UNKNOWN && ether3_probe_bus_16(dev, 0x101) && ether3_probe_bus_16(dev, 0x201)) bus_type = BUS_16; switch (bus_type) { case BUS_UNKNOWN: printk(KERN_ERR "%s: unable to identify podule bus width\n", dev->name); goto failed; case BUS_8: printk(KERN_ERR "%s: ether3 found, but is an unsupported 8-bit card\n", dev->name); goto failed; default: break; } printk("%s: ether3 found at %lx, IRQ%d, ether address ", dev->name, dev->base_addr, dev->irq); for (i = 0; i < 6; i++) printk(i == 5 ? "%2.2x\n" : "%2.2x:", dev->dev_addr[i]); if (!ether3_init_2(dev)) { dev->open = ether3_open; dev->stop = ether3_close; dev->hard_start_xmit = ether3_sendpacket; dev->get_stats = ether3_getstats; dev->set_multicast_list = ether3_setmulticastlist; /* Fill in the fields of the device structure with ethernet values. */ ether_setup(dev); return 0; } failed: kfree(dev->priv); dev->priv = NULL; release_region(dev->base_addr, 128); return error; }