📄 epic100.c
字号:
dev = alloc_etherdev(sizeof (*ep)); if (!dev) { printk (KERN_ERR "card %d: no memory for eth device\n", card_idx); return -ENOMEM; } SET_MODULE_OWNER(dev); if (pci_request_regions(pdev, DRV_NAME)) goto err_out_free_netdev;#ifdef USE_IO_OPS ioaddr = pci_resource_start (pdev, 0);#else ioaddr = pci_resource_start (pdev, 1); ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1)); if (!ioaddr) { printk (KERN_ERR DRV_NAME " %d: ioremap failed\n", card_idx); goto err_out_free_res; }#endif pci_set_drvdata(pdev, dev); ep = dev->priv; ep->mii.dev = dev; ep->mii.mdio_read = mdio_read; ep->mii.mdio_write = mdio_write; ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma); if (!ring_space) goto err_out_iounmap; ep->tx_ring = (struct epic_tx_desc *)ring_space; ep->tx_ring_dma = ring_dma; ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma); if (!ring_space) goto err_out_unmap_tx; ep->rx_ring = (struct epic_rx_desc *)ring_space; ep->rx_ring_dma = ring_dma; if (dev->mem_start) { option = dev->mem_start; duplex = (dev->mem_start & 16) ? 1 : 0; } else if (card_idx >= 0 && card_idx < MAX_UNITS) { if (options[card_idx] >= 0) option = options[card_idx]; if (full_duplex[card_idx] >= 0) duplex = full_duplex[card_idx]; } dev->base_addr = ioaddr; dev->irq = irq; spin_lock_init (&ep->lock); /* Bring the chip out of low-power mode. */ outl(0x4200, ioaddr + GENCTL); /* Magic?! If we don't set this bit the MII interface won't work. */ outl(0x0008, ioaddr + TEST1); /* Turn on the MII transceiver. */ outl(0x12, ioaddr + MIICfg); if (chip_idx == 1) outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL); outl(0x0200, ioaddr + GENCTL); /* Note: the '175 does not have a serial EEPROM. */ for (i = 0; i < 3; i++) ((u16 *)dev->dev_addr)[i] = le16_to_cpu(inw(ioaddr + LAN0 + i*4)); if (debug > 2) { printk(KERN_DEBUG DRV_NAME "(%s): EEPROM contents\n", pdev->slot_name); for (i = 0; i < 64; i++) printk(" %4.4x%s", read_eeprom(ioaddr, i), i % 16 == 15 ? "\n" : ""); } ep->pci_dev = pdev; ep->chip_id = chip_idx; ep->chip_flags = pci_id_tbl[chip_idx].drv_flags; /* Find the connected MII xcvrs. Doing this in open() would allow detecting external xcvrs later, but takes much time and no cards have external MII. */ { int phy, phy_idx = 0; for (phy = 1; phy < 32 && phy_idx < sizeof(ep->phys); phy++) { int mii_status = mdio_read(dev, phy, MII_BMSR); if (mii_status != 0xffff && mii_status != 0x0000) { ep->phys[phy_idx++] = phy; printk(KERN_INFO DRV_NAME "(%s): MII transceiver #%d control " "%4.4x status %4.4x.\n", pdev->slot_name, phy, mdio_read(dev, phy, 0), mii_status); } } ep->mii_phy_cnt = phy_idx; if (phy_idx != 0) { phy = ep->phys[0]; ep->mii.advertising = mdio_read(dev, phy, MII_ADVERTISE); printk(KERN_INFO DRV_NAME "(%s): Autonegotiation advertising %4.4x link " "partner %4.4x.\n", pdev->slot_name, ep->mii.advertising, mdio_read(dev, phy, 5)); } else if ( ! (ep->chip_flags & NO_MII)) { printk(KERN_WARNING DRV_NAME "(%s): ***WARNING***: No MII transceiver found!\n", pdev->slot_name); /* Use the known PHY address of the EPII. */ ep->phys[0] = 3; } ep->mii.phy_id = ep->phys[0]; } /* Turn off the MII xcvr (175 only!), leave the chip in low-power mode. */ if (ep->chip_flags & MII_PWRDWN) outl(inl(ioaddr + NVCTL) & ~0x483C, ioaddr + NVCTL); outl(0x0008, ioaddr + GENCTL); /* The lower four bits are the media type. */ if (duplex) { ep->mii.duplex_lock = ep->mii.full_duplex = 1; printk(KERN_INFO DRV_NAME "(%s): Forced full duplex operation requested.\n", pdev->slot_name); } dev->if_port = ep->default_port = option; /* The Epic-specific entries in the device structure. */ dev->open = &epic_open; dev->hard_start_xmit = &epic_start_xmit; dev->stop = &epic_close; dev->get_stats = &epic_get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &netdev_ioctl; dev->watchdog_timeo = TX_TIMEOUT; dev->tx_timeout = &epic_tx_timeout; i = register_netdev(dev); if (i) goto err_out_unmap_tx; printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq); for (i = 0; i < 5; i++) printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x.\n", dev->dev_addr[i]); return 0;err_out_unmap_tx: pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma);err_out_iounmap:#ifndef USE_IO_OPS iounmap(ioaddr);err_out_free_res:#endif pci_release_regions(pdev);err_out_free_netdev: kfree(dev); return -ENODEV;}/* Serial EEPROM section. *//* EEPROM_Ctrl bits. */#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */#define EE_CS 0x02 /* EEPROM chip select. */#define EE_DATA_WRITE 0x08 /* EEPROM chip data in. */#define EE_WRITE_0 0x01#define EE_WRITE_1 0x09#define EE_DATA_READ 0x10 /* EEPROM chip data out. */#define EE_ENB (0x0001 | EE_CS)/* Delay between EEPROM clock transitions. This serves to flush the operation to the PCI bus. */#define eeprom_delay() inl(ee_addr)/* The EEPROM commands include the alway-set leading bit. */#define EE_WRITE_CMD (5 << 6)#define EE_READ64_CMD (6 << 6)#define EE_READ256_CMD (6 << 8)#define EE_ERASE_CMD (7 << 6)static int read_eeprom(long ioaddr, int location){ int i; int retval = 0; long ee_addr = ioaddr + EECTL; int read_cmd = location | (inl(ee_addr) & 0x40 ? EE_READ64_CMD : EE_READ256_CMD); outl(EE_ENB & ~EE_CS, ee_addr); outl(EE_ENB, ee_addr); /* Shift the read command bits out. */ for (i = 12; i >= 0; i--) { short dataval = (read_cmd & (1 << i)) ? EE_WRITE_1 : EE_WRITE_0; outl(EE_ENB | dataval, ee_addr); eeprom_delay(); outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); eeprom_delay(); } outl(EE_ENB, ee_addr); for (i = 16; i > 0; i--) { outl(EE_ENB | EE_SHIFT_CLK, ee_addr); eeprom_delay(); retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0); outl(EE_ENB, ee_addr); eeprom_delay(); } /* Terminate the EEPROM access. */ outl(EE_ENB & ~EE_CS, ee_addr); return retval;}#define MII_READOP 1#define MII_WRITEOP 2static int mdio_read(struct net_device *dev, int phy_id, int location){ long ioaddr = dev->base_addr; int read_cmd = (phy_id << 9) | (location << 4) | MII_READOP; int i; outl(read_cmd, ioaddr + MIICtrl); /* Typical operation takes 25 loops. */ for (i = 400; i > 0; i--) { barrier(); if ((inl(ioaddr + MIICtrl) & MII_READOP) == 0) { /* Work around read failure bug. */ if (phy_id == 1 && location < 6 && inw(ioaddr + MIIData) == 0xffff) { outl(read_cmd, ioaddr + MIICtrl); continue; } return inw(ioaddr + MIIData); } } return 0xffff;}static void mdio_write(struct net_device *dev, int phy_id, int loc, int value){ long ioaddr = dev->base_addr; int i; outw(value, ioaddr + MIIData); outl((phy_id << 9) | (loc << 4) | MII_WRITEOP, ioaddr + MIICtrl); for (i = 10000; i > 0; i--) { barrier(); if ((inl(ioaddr + MIICtrl) & MII_WRITEOP) == 0) break; } return;}static int epic_open(struct net_device *dev){ struct epic_private *ep = dev->priv; long ioaddr = dev->base_addr; int i; int retval; /* Soft reset the chip. */ outl(0x4001, ioaddr + GENCTL); if ((retval = request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, dev->name, dev))) return retval; epic_init_ring(dev); outl(0x4000, ioaddr + GENCTL); /* This magic is documented in SMSC app note 7.15 */ outl(0x0008, ioaddr + TEST1); /* Pull the chip out of low-power mode, enable interrupts, and set for PCI read multiple. The MIIcfg setting and strange write order are required by the details of which bits are reset and the transceiver wiring on the Ositech CardBus card. */ outl(0x12, ioaddr + MIICfg); if (ep->chip_flags & MII_PWRDWN) outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);#if defined(__powerpc__) || defined(__sparc__) /* Big endian */ outl(0x4432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL); inl(ioaddr + GENCTL); outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);#else outl(0x4412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL); inl(ioaddr + GENCTL); outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);#endif for (i = 0; i < 3; i++) outl(cpu_to_le16(((u16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4); ep->tx_threshold = TX_FIFO_THRESH; outl(ep->tx_threshold, ioaddr + TxThresh); if (media2miictl[dev->if_port & 15]) { if (ep->mii_phy_cnt) mdio_write(dev, ep->phys[0], MII_BMCR, media2miictl[dev->if_port&15]); if (dev->if_port == 1) { if (debug > 1) printk(KERN_INFO "%s: Using the 10base2 transceiver, MII " "status %4.4x.\n", dev->name, mdio_read(dev, ep->phys[0], MII_BMSR)); } } else { int mii_lpa = mdio_read(dev, ep->phys[0], MII_LPA); if (mii_lpa != 0xffff) { if ((mii_lpa & LPA_100FULL) || (mii_lpa & 0x01C0) == LPA_10FULL) ep->mii.full_duplex = 1; else if (! (mii_lpa & LPA_LPACK)) mdio_write(dev, ep->phys[0], MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART); if (debug > 1) printk(KERN_INFO "%s: Setting %s-duplex based on MII xcvr %d" " register read of %4.4x.\n", dev->name, ep->mii.full_duplex ? "full" : "half", ep->phys[0], mii_lpa); } } outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl); outl(ep->rx_ring_dma, ioaddr + PRxCDAR); outl(ep->tx_ring_dma, ioaddr + PTxCDAR); /* Start the chip's Rx process. */ set_rx_mode(dev); outl(StartRx | RxQueued, ioaddr + COMMAND); netif_start_queue(dev); /* Enable interrupts by setting the interrupt mask. */ outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) | CntFull | TxUnderrun | TxDone | TxEmpty | RxError | RxOverflow | RxFull | RxHeader | RxDone, ioaddr + INTMASK); if (debug > 1) printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x " "%s-duplex.\n", dev->name, ioaddr, dev->irq, (int)inl(ioaddr + GENCTL), ep->mii.full_duplex ? "full" : "half"); /* Set the timer to switch to check for link beat and perhaps switch to an alternate media type. */ init_timer(&ep->timer); ep->timer.expires = jiffies + 3*HZ; ep->timer.data = (unsigned long)dev; ep->timer.function = &epic_timer; /* timer handler */ add_timer(&ep->timer); return 0;}/* Reset the chip to recover from a PCI transaction error. This may occur at interrupt time. */static void epic_pause(struct net_device *dev){ long ioaddr = dev->base_addr; struct epic_private *ep = dev->priv; netif_stop_queue (dev); /* Disable interrupts by clearing the interrupt mask. */ outl(0x00000000, ioaddr + INTMASK); /* Stop the chip's Tx and Rx DMA processes. */ outw(StopRx | StopTxDMA | StopRxDMA, ioaddr + COMMAND); /* Update the error counts. */ if (inw(ioaddr + COMMAND) != 0xffff) { ep->stats.rx_missed_errors += inb(ioaddr + MPCNT); ep->stats.rx_frame_errors += inb(ioaddr + ALICNT); ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT); } /* Remove the packets on the Rx queue. */ epic_rx(dev);}static void epic_restart(struct net_device *dev){ long ioaddr = dev->base_addr; struct epic_private *ep = dev->priv; int i; /* Soft reset the chip. */ outl(0x4001, ioaddr + GENCTL); printk(KERN_DEBUG "%s: Restarting the EPIC chip, Rx %d/%d Tx %d/%d.\n", dev->name, ep->cur_rx, ep->dirty_rx, ep->dirty_tx, ep->cur_tx); udelay(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -