📄 lance.c
字号:
int i, reset_val, lance_version; const char *chipname; /* Flags for specific chips or boards. */ unsigned char hpJ2405A = 0; /* HP ISA adaptor */ int hp_builtin = 0; /* HP on-board ethernet. */ static int did_version = 0; /* Already printed version info. */ unsigned long flags; /* First we look for special cases. Check for HP's on-board ethernet by looking for 'HP' in the BIOS. There are two HP versions, check the BIOS for the configuration port. This method provided by L. Julliard, Laurent_Julliard@grenoble.hp.com. */ if (readw(0x000f0102) == 0x5048) { static const short ioaddr_table[] = { 0x300, 0x320, 0x340, 0x360}; int hp_port = (readl(0x000f00f1) & 1) ? 0x499 : 0x99; /* We can have boards other than the built-in! Verify this is on-board. */ if ((inb(hp_port) & 0xc0) == 0x80 && ioaddr_table[inb(hp_port) & 3] == ioaddr) hp_builtin = hp_port; } /* We also recognize the HP Vectra on-board here, but check below. */ hpJ2405A = (inb(ioaddr) == 0x08 && inb(ioaddr+1) == 0x00 && inb(ioaddr+2) == 0x09); /* Reset the LANCE. */ reset_val = inw(ioaddr+LANCE_RESET); /* Reset the LANCE */ /* The Un-Reset needed is only needed for the real NE2100, and will confuse the HP board. */ if (!hpJ2405A) outw(reset_val, ioaddr+LANCE_RESET); outw(0x0000, ioaddr+LANCE_ADDR); /* Switch to window 0 */ if (inw(ioaddr+LANCE_DATA) != 0x0004) return -ENODEV; /* Get the version of the chip. */ outw(88, ioaddr+LANCE_ADDR); if (inw(ioaddr+LANCE_ADDR) != 88) { lance_version = 0; } else { /* Good, it's a newer chip. */ int chip_version = inw(ioaddr+LANCE_DATA); outw(89, ioaddr+LANCE_ADDR); chip_version |= inw(ioaddr+LANCE_DATA) << 16; if (lance_debug > 2) printk(" LANCE chip version is %#x.\n", chip_version); if ((chip_version & 0xfff) != 0x003) return -ENODEV; chip_version = (chip_version >> 12) & 0xffff; for (lance_version = 1; chip_table[lance_version].id_number; lance_version++) { if (chip_table[lance_version].id_number == chip_version) break; } } /* We can't use init_etherdev() to allocate dev->priv because it must a ISA DMA-able region. */ dev = init_etherdev(dev, 0); dev->open = lance_open_fail; chipname = chip_table[lance_version].name; printk("%s: %s at %#3x,", dev->name, chipname, ioaddr); /* There is a 16 byte station address PROM at the base address. The first six bytes are the station address. */ for (i = 0; i < 6; i++) printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i)); dev->base_addr = ioaddr; request_region(ioaddr, LANCE_TOTAL_SIZE, chip_table[lance_version].name); /* Make certain the data structures used by the LANCE are aligned and DMAble. */ lp = (struct lance_private *)(((unsigned long)kmalloc(sizeof(*lp)+7, GFP_DMA | GFP_KERNEL)+7) & ~7); if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp); memset(lp, 0, sizeof(*lp)); dev->priv = lp; lp->name = chipname; lp->rx_buffs = (unsigned long)kmalloc(PKT_BUF_SZ*RX_RING_SIZE, GFP_DMA | GFP_KERNEL); if (lance_need_isa_bounce_buffers) lp->tx_bounce_buffs = kmalloc(PKT_BUF_SZ*TX_RING_SIZE, GFP_DMA | GFP_KERNEL); else lp->tx_bounce_buffs = NULL; lp->chip_version = lance_version; lp->init_block.mode = 0x0003; /* Disable Rx and Tx. */ for (i = 0; i < 6; i++) lp->init_block.phys_addr[i] = dev->dev_addr[i]; lp->init_block.filter[0] = 0x00000000; lp->init_block.filter[1] = 0x00000000; lp->init_block.rx_ring = ((u32)virt_to_bus(lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS; lp->init_block.tx_ring = ((u32)virt_to_bus(lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS; outw(0x0001, ioaddr+LANCE_ADDR); inw(ioaddr+LANCE_ADDR); outw((short) (u32) virt_to_bus(&lp->init_block), ioaddr+LANCE_DATA); outw(0x0002, ioaddr+LANCE_ADDR); inw(ioaddr+LANCE_ADDR); outw(((u32)virt_to_bus(&lp->init_block)) >> 16, ioaddr+LANCE_DATA); outw(0x0000, ioaddr+LANCE_ADDR); inw(ioaddr+LANCE_ADDR); if (irq) { /* Set iff PCI card. */ dev->dma = 4; /* Native bus-master, no DMA channel needed. */ dev->irq = irq; } else if (hp_builtin) { static const char dma_tbl[4] = {3, 5, 6, 0}; static const char irq_tbl[4] = {3, 4, 5, 9}; unsigned char port_val = inb(hp_builtin); dev->dma = dma_tbl[(port_val >> 4) & 3]; dev->irq = irq_tbl[(port_val >> 2) & 3]; printk(" HP Vectra IRQ %d DMA %d.\n", dev->irq, dev->dma); } else if (hpJ2405A) { static const char dma_tbl[4] = {3, 5, 6, 7}; static const char irq_tbl[8] = {3, 4, 5, 9, 10, 11, 12, 15}; short reset_val = inw(ioaddr+LANCE_RESET); dev->dma = dma_tbl[(reset_val >> 2) & 3]; dev->irq = irq_tbl[(reset_val >> 4) & 7]; printk(" HP J2405A IRQ %d DMA %d.\n", dev->irq, dev->dma); } else if (lance_version == PCNET_ISAP) { /* The plug-n-play version. */ short bus_info; outw(8, ioaddr+LANCE_ADDR); bus_info = inw(ioaddr+LANCE_BUS_IF); dev->dma = bus_info & 0x07; dev->irq = (bus_info >> 4) & 0x0F; } else { /* The DMA channel may be passed in PARAM1. */ if (dev->mem_start & 0x07) dev->dma = dev->mem_start & 0x07; } if (dev->dma == 0) { /* Read the DMA channel status register, so that we can avoid stuck DMA channels in the DMA detection below. */ dma_channels = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) | (inb(DMA2_STAT_REG) & 0xf0); } if (dev->irq >= 2) printk(" assigned IRQ %d", dev->irq); else if (lance_version != 0) { /* 7990 boards need DMA detection first. */ /* To auto-IRQ we enable the initialization-done and DMA error interrupts. For ISA boards we get a DMA error, but VLB and PCI boards will work. */ autoirq_setup(0); /* Trigger an initialization just for the interrupt. */ outw(0x0041, ioaddr+LANCE_DATA); dev->irq = autoirq_report(2); if (dev->irq) printk(", probed IRQ %d", dev->irq); else { printk(", failed to detect IRQ line.\n"); return -ENODEV; } /* Check for the initialization done bit, 0x0100, which means that we don't need a DMA channel. */ if (inw(ioaddr+LANCE_DATA) & 0x0100) dev->dma = 4; } if (dev->dma == 4) { printk(", no DMA needed.\n"); } else if (dev->dma) { if (request_dma(dev->dma, chipname)) { printk("DMA %d allocation failed.\n", dev->dma); return -ENODEV; } else printk(", assigned DMA %d.\n", dev->dma); } else { /* OK, we have to auto-DMA. */ for (i = 0; i < 4; i++) { static const char dmas[] = { 5, 6, 7, 3 }; int dma = dmas[i]; int boguscnt; /* Don't enable a permanently busy DMA channel, or the machine will hang. */ if (test_bit(dma, &dma_channels)) continue; outw(0x7f04, ioaddr+LANCE_DATA); /* Clear the memory error bits. */ if (request_dma(dma, chipname)) continue; flags=claim_dma_lock(); set_dma_mode(dma, DMA_MODE_CASCADE); enable_dma(dma); release_dma_lock(flags); /* Trigger an initialization. */ outw(0x0001, ioaddr+LANCE_DATA); for (boguscnt = 100; boguscnt > 0; --boguscnt) if (inw(ioaddr+LANCE_DATA) & 0x0900) break; if (inw(ioaddr+LANCE_DATA) & 0x0100) { dev->dma = dma; printk(", DMA %d.\n", dev->dma); break; } else { flags=claim_dma_lock(); disable_dma(dma); release_dma_lock(flags); free_dma(dma); } } if (i == 4) { /* Failure: bail. */ printk("DMA detection failed.\n"); return -ENODEV; } } if (lance_version == 0 && dev->irq == 0) { /* We may auto-IRQ now that we have a DMA channel. */ /* Trigger an initialization just for the interrupt. */ autoirq_setup(0); outw(0x0041, ioaddr+LANCE_DATA); dev->irq = autoirq_report(4); if (dev->irq == 0) { printk(" Failed to detect the 7990 IRQ line.\n"); return -ENODEV; } printk(" Auto-IRQ detected IRQ%d.\n", dev->irq); } if (chip_table[lp->chip_version].flags & LANCE_ENABLE_AUTOSELECT) { /* Turn on auto-select of media (10baseT or BNC) so that the user can watch the LEDs even if the board isn't opened. */ outw(0x0002, ioaddr+LANCE_ADDR); /* Don't touch 10base2 power bit. */ outw(inw(ioaddr+LANCE_BUS_IF) | 0x0002, ioaddr+LANCE_BUS_IF); } if (lance_debug > 0 && did_version++ == 0) printk(version); /* The LANCE-specific entries in the device structure. */ dev->open = lance_open; dev->hard_start_xmit = lance_start_xmit; dev->stop = lance_close; dev->get_stats = lance_get_stats; dev->set_multicast_list = set_multicast_list; return 0;}static intlance_open_fail(struct device *dev){ return -ENODEV;}static intlance_open(struct device *dev){ struct lance_private *lp = (struct lance_private *)dev->priv; int ioaddr = dev->base_addr; int i; if (dev->irq == 0 || request_irq(dev->irq, &lance_interrupt, 0, lp->name, dev)) { return -EAGAIN; } MOD_INC_USE_COUNT; /* We used to allocate DMA here, but that was silly. DMA lines can't be shared! We now permanently allocate them. */ /* Reset the LANCE */ inw(ioaddr+LANCE_RESET); /* The DMA controller is used as a no-operation slave, "cascade mode". */ if (dev->dma != 4) { unsigned long flags=claim_dma_lock(); enable_dma(dev->dma); set_dma_mode(dev->dma, DMA_MODE_CASCADE); release_dma_lock(flags); } /* Un-Reset the LANCE, needed only for the NE2100. */ if (chip_table[lp->chip_version].flags & LANCE_MUST_UNRESET) outw(0, ioaddr+LANCE_RESET); if (chip_table[lp->chip_version].flags & LANCE_ENABLE_AUTOSELECT) { /* This is 79C960-specific: Turn on auto-select of media (AUI, BNC). */ outw(0x0002, ioaddr+LANCE_ADDR); /* Only touch autoselect bit. */ outw(inw(ioaddr+LANCE_BUS_IF) | 0x0002, ioaddr+LANCE_BUS_IF); } if (lance_debug > 1) printk("%s: lance_open() irq %d dma %d tx/rx rings %#x/%#x init %#x.\n", dev->name, dev->irq, dev->dma, (u32) virt_to_bus(lp->tx_ring), (u32) virt_to_bus(lp->rx_ring), (u32) virt_to_bus(&lp->init_block)); lance_init_ring(dev, GFP_KERNEL); /* Re-initialize the LANCE, and start it when done. */ outw(0x0001, ioaddr+LANCE_ADDR); outw((short) (u32) virt_to_bus(&lp->init_block), ioaddr+LANCE_DATA); outw(0x0002, ioaddr+LANCE_ADDR); outw(((u32)virt_to_bus(&lp->init_block)) >> 16, ioaddr+LANCE_DATA); outw(0x0004, ioaddr+LANCE_ADDR); outw(0x0915, ioaddr+LANCE_DATA); outw(0x0000, ioaddr+LANCE_ADDR); outw(0x0001, ioaddr+LANCE_DATA); dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; i = 0; while (i++ < 100) if (inw(ioaddr+LANCE_DATA) & 0x0100) break; /* * We used to clear the InitDone bit, 0x0100, here but Mark Stockton * reports that doing so triggers a bug in the '974. */ outw(0x0042, ioaddr+LANCE_DATA); if (lance_debug > 2) printk("%s: LANCE open after %d ticks, init block %#x csr0 %4.4x.\n", dev->name, i, (u32) virt_to_bus(&lp->init_block), inw(ioaddr+LANCE_DATA)); return 0; /* Always succeed */}/* The LANCE has been halted for one reason or another (busmaster memory arbitration error, Tx FIFO underflow, driver stopped it to reconfigure, etc.). Modern LANCE variants always reload their ring-buffer configuration when restarted, so we must reinitialize our ring context before restarting. As part of this reinitialization, find all packets still on the Tx ring and pretend that they had been sent (in effect, drop the packets on the floor) - the higher-level protocols will time out and retransmit. It'd be better to shuffle these skbs to a temp list and then actually re-Tx them after restarting the chip, but I'm too lazy to do so right now. dplatt@3do.com*/static void lance_purge_tx_ring(struct device *dev){ struct lance_private *lp = (struct lance_private *)dev->priv; int i; for (i = 0; i < TX_RING_SIZE; i++) { if (lp->tx_skbuff[i]) { dev_kfree_skb(lp->tx_skbuff[i]); lp->tx_skbuff[i] = NULL; } }}/* Initialize the LANCE Rx and Tx rings. */static voidlance_init_ring(struct device *dev, int gfp){ struct lance_private *lp = (struct lance_private *)dev->priv; int i; lp->lock = 0, lp->tx_full = 0; lp->cur_rx = lp->cur_tx = 0; lp->dirty_rx = lp->dirty_tx = 0; for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb; void *rx_buff; skb = alloc_skb(PKT_BUF_SZ, GFP_DMA | gfp); lp->rx_skbuff[i] = skb; if (skb) { skb->dev = dev; rx_buff = skb->tail; } else rx_buff = kmalloc(PKT_BUF_SZ, GFP_DMA | gfp); if (rx_buff == NULL) lp->rx_ring[i].base = 0; else lp->rx_ring[i].base = (u32)virt_to_bus(rx_buff) | 0x80000000; lp->rx_ring[i].buf_length = -PKT_BUF_SZ; } /* The Tx buffer address is filled in as needed, but we do need to clear the upper ownership bit. */ for (i = 0; i < TX_RING_SIZE; i++) { lp->tx_skbuff[i] = 0; lp->tx_ring[i].base = 0; } lp->init_block.mode = 0x0000; for (i = 0; i < 6; i++) lp->init_block.phys_addr[i] = dev->dev_addr[i]; lp->init_block.filter[0] = 0x00000000; lp->init_block.filter[1] = 0x00000000; lp->init_block.rx_ring = ((u32)virt_to_bus(lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS; lp->init_block.tx_ring = ((u32)virt_to_bus(lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;}static voidlance_restart(struct device *dev, unsigned int csr0_bits, int must_reinit){ struct lance_private *lp = (struct lance_private *)dev->priv; if (must_reinit || (chip_table[lp->chip_version].flags & LANCE_MUST_REINIT_RING)) { lance_purge_tx_ring(dev); lance_init_ring(dev, GFP_ATOMIC); } outw(0x0000, dev->base_addr + LANCE_ADDR); outw(csr0_bits, dev->base_addr + LANCE_DATA);}static int lance_start_xmit(struct sk_buff *skb, struct device *dev){ struct lance_private *lp = (struct lance_private *)dev->priv; int ioaddr = dev->base_addr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -