📄 xircom_tulip_cb.c
字号:
break; } else if (link == 0) { break; } }}/* * locate the MII interfaces and initialize them. * we disable full-duplex modes here, * because we don't know how to handle them. */static void find_mii_transceivers(struct net_device *dev){ struct xircom_private *tp = netdev_priv(dev); int phy, phy_idx; if (media_cap[tp->default_port] & MediaIsMII) { u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 }; tp->to_advertise = media2advert[tp->default_port - 9]; } else tp->to_advertise = /*ADVERTISE_100BASE4 | ADVERTISE_100FULL |*/ ADVERTISE_100HALF | /*ADVERTISE_10FULL |*/ ADVERTISE_10HALF | ADVERTISE_CSMA; /* Find the connected MII xcvrs. Doing this in open() would allow detecting external xcvrs later, but takes much time. */ for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { int mii_status = mdio_read(dev, phy, MII_BMSR); if ((mii_status & (BMSR_100BASE4 | BMSR_100HALF | BMSR_10HALF)) == BMSR_100BASE4 || ((mii_status & BMSR_100BASE4) == 0 && (mii_status & (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL | BMSR_10HALF)) != 0)) { int mii_reg0 = mdio_read(dev, phy, MII_BMCR); int mii_advert = mdio_read(dev, phy, MII_ADVERTISE); int reg4 = ((mii_status >> 6) & tp->to_advertise) | ADVERTISE_CSMA; tp->phys[phy_idx] = phy; tp->advertising[phy_idx++] = reg4; printk(KERN_INFO "%s: MII transceiver #%d " "config %4.4x status %4.4x advertising %4.4x.\n", dev->name, phy, mii_reg0, mii_status, mii_advert); } } tp->mii_cnt = phy_idx; if (phy_idx == 0) { printk(KERN_INFO "%s: ***WARNING***: No MII transceiver found!\n", dev->name); tp->phys[0] = 0; }}/* * To quote Arjan van de Ven: * transceiver_voodoo() enables the external UTP plug thingy. * it's called voodoo as I stole this code and cannot cross-reference * it with the specification. * Actually it seems to go like this: * - GPIO2 enables the MII itself so we can talk to it. The MII gets reset * so any prior MII settings are lost. * - GPIO0 enables the TP port so the MII can talk to the network. * - a software reset will reset both GPIO pins. * I also moved the software reset here, because doing it in xircom_up() * required enabling the GPIO pins each time, which reset the MII each time. * Thus we couldn't control the MII -- which sucks because we don't know * how to handle full-duplex modes so we *must* disable them. */static void transceiver_voodoo(struct net_device *dev){ struct xircom_private *tp = netdev_priv(dev); long ioaddr = dev->base_addr; /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */ outl(SoftwareReset, ioaddr + CSR0); udelay(2); /* Deassert reset. */ outl(tp->csr0, ioaddr + CSR0); /* Reset the xcvr interface and turn on heartbeat. */ outl(0x0008, ioaddr + CSR15); udelay(5); /* The delays are Xircom-recommended to give the * chipset time to reset the actual hardware * on the PCMCIA card */ outl(0xa8050000, ioaddr + CSR15); udelay(5); outl(0xa00f0000, ioaddr + CSR15); udelay(5); outl_CSR6(0, ioaddr); //outl_CSR6(FullDuplexBit, ioaddr);}static int __devinit xircom_init_one(struct pci_dev *pdev, const struct pci_device_id *id){ struct net_device *dev; struct xircom_private *tp; static int board_idx = -1; int chip_idx = id->driver_data; long ioaddr; int i; u8 chip_rev;/* when built into the kernel, we only print version if device is found */#ifndef MODULE static int printed_version; if (!printed_version++) printk(version);#endif //printk(KERN_INFO "xircom_init_one(%s)\n", pci_name(pdev)); board_idx++; if (pci_enable_device(pdev)) return -ENODEV; pci_set_master(pdev); ioaddr = pci_resource_start(pdev, 0); dev = alloc_etherdev(sizeof(*tp)); if (!dev) { printk (KERN_ERR DRV_NAME "%d: cannot alloc etherdev, aborting\n", board_idx); return -ENOMEM; } SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); dev->base_addr = ioaddr; dev->irq = pdev->irq; if (pci_request_regions(pdev, dev->name)) { printk (KERN_ERR DRV_NAME " %d: cannot reserve PCI resources, aborting\n", board_idx); goto err_out_free_netdev; } /* Bring the chip out of sleep mode. Caution: Snooze mode does not work with some boards! */ if (xircom_tbl[chip_idx].flags & HAS_ACPI) pci_write_config_dword(pdev, PCI_POWERMGMT, 0); /* Stop the chip's Tx and Rx processes. */ outl_CSR6(inl(ioaddr + CSR6) & ~EnableTxRx, ioaddr); /* Clear the missed-packet counter. */ (volatile int)inl(ioaddr + CSR8); tp = netdev_priv(dev); spin_lock_init(&tp->lock); tp->pdev = pdev; tp->chip_id = chip_idx; /* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles. */ /* XXX: is this necessary for Xircom? */ tp->csr0 = csr0 & ~EnableMWI; pci_set_drvdata(pdev, dev); /* The lower four bits are the media type. */ if (board_idx >= 0 && board_idx < MAX_UNITS) { tp->default_port = options[board_idx] & 15; if ((options[board_idx] & 0x90) || full_duplex[board_idx] > 0) tp->full_duplex = 1; if (mtu[board_idx] > 0) dev->mtu = mtu[board_idx]; } if (dev->mem_start) tp->default_port = dev->mem_start; if (tp->default_port) { if (media_cap[tp->default_port] & MediaAlwaysFD) tp->full_duplex = 1; } if (tp->full_duplex) tp->autoneg = 0; else tp->autoneg = 1; tp->speed100 = 1; /* The Xircom-specific entries in the device structure. */ dev->open = &xircom_open; dev->hard_start_xmit = &xircom_start_xmit; dev->stop = &xircom_close; dev->get_stats = &xircom_get_stats; dev->do_ioctl = &xircom_ioctl;#ifdef HAVE_MULTICAST dev->set_multicast_list = &set_rx_mode;#endif dev->tx_timeout = xircom_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; SET_ETHTOOL_OPS(dev, &ops); transceiver_voodoo(dev); read_mac_address(dev); if (register_netdev(dev)) goto err_out_cleardev; pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev); printk(KERN_INFO "%s: %s rev %d at %#3lx,", dev->name, xircom_tbl[chip_idx].chip_name, chip_rev, ioaddr); for (i = 0; i < 6; i++) printk("%c%2.2X", i ? ':' : ' ', dev->dev_addr[i]); printk(", IRQ %d.\n", dev->irq); if (xircom_tbl[chip_idx].flags & HAS_MII) { find_mii_transceivers(dev); check_duplex(dev); } return 0;err_out_cleardev: pci_set_drvdata(pdev, NULL); pci_release_regions(pdev);err_out_free_netdev: free_netdev(dev); return -ENODEV;}/* MII transceiver control section. Read and write the MII registers using software-generated serial MDIO protocol. See the MII specifications or DP83840A data sheet for details. *//* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually met by back-to-back PCI I/O cycles, but we insert a delay to avoid "overclocking" issues or future 66Mhz PCI. */#define mdio_delay() inl(mdio_addr)/* Read and write the MII registers using software-generated serial MDIO protocol. It is just different enough from the EEPROM protocol to not share code. The maxium data clock rate is 2.5 Mhz. */#define MDIO_SHIFT_CLK 0x10000#define MDIO_DATA_WRITE0 0x00000#define MDIO_DATA_WRITE1 0x20000#define MDIO_ENB 0x00000 /* Ignore the 0x02000 databook setting. */#define MDIO_ENB_IN 0x40000#define MDIO_DATA_READ 0x80000static int mdio_read(struct net_device *dev, int phy_id, int location){ int i; int read_cmd = (0xf6 << 10) | (phy_id << 5) | location; int retval = 0; long ioaddr = dev->base_addr; long mdio_addr = ioaddr + CSR9; /* Establish sync by sending at least 32 logic ones. */ for (i = 32; i >= 0; i--) { outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); mdio_delay(); outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); mdio_delay(); } /* Shift the read command bits out. */ for (i = 15; i >= 0; i--) { int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; outl(MDIO_ENB | dataval, mdio_addr); mdio_delay(); outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr); mdio_delay(); } /* Read the two transition, 16 data, and wire-idle bits. */ for (i = 19; i > 0; i--) { outl(MDIO_ENB_IN, mdio_addr); mdio_delay(); retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0); outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); mdio_delay(); } return (retval>>1) & 0xffff;}static void mdio_write(struct net_device *dev, int phy_id, int location, int value){ int i; int cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; long ioaddr = dev->base_addr; long mdio_addr = ioaddr + CSR9; /* Establish sync by sending 32 logic ones. */ for (i = 32; i >= 0; i--) { outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); mdio_delay(); outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); mdio_delay(); } /* Shift the command bits out. */ for (i = 31; i >= 0; i--) { int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; outl(MDIO_ENB | dataval, mdio_addr); mdio_delay(); outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr); mdio_delay(); } /* Clear out extra bits. */ for (i = 2; i > 0; i--) { outl(MDIO_ENB_IN, mdio_addr); mdio_delay(); outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); mdio_delay(); } return;}static voidxircom_up(struct net_device *dev){ struct xircom_private *tp = netdev_priv(dev); long ioaddr = dev->base_addr; int i; xircom_init_ring(dev); /* Clear the tx ring */ for (i = 0; i < TX_RING_SIZE; i++) { tp->tx_skbuff[i] = NULL; tp->tx_ring[i].status = 0; } if (xircom_debug > 1) printk(KERN_DEBUG "%s: xircom_up() irq %d.\n", dev->name, dev->irq); outl(virt_to_bus(tp->rx_ring), ioaddr + CSR3); outl(virt_to_bus(tp->tx_ring), ioaddr + CSR4); tp->saved_if_port = dev->if_port; if (dev->if_port == 0) dev->if_port = tp->default_port; tp->csr6 = TxThresh10 /*| FullDuplexBit*/; /* XXX: why 10 and not 100? */ set_rx_mode(dev); /* Start the chip's Tx to process setup frame. */ outl_CSR6(tp->csr6, ioaddr); outl_CSR6(tp->csr6 | EnableTx, ioaddr); /* Acknowledge all outstanding interrupts sources */ outl(xircom_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5); /* Enable interrupts by setting the interrupt mask. */ outl(xircom_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); /* Enable Rx */ outl_CSR6(tp->csr6 | EnableTxRx, ioaddr); /* Rx poll demand */ outl(0, ioaddr + CSR2); /* Tell the net layer we're ready */ netif_start_queue (dev); /* Check current media state */ xircom_media_change(dev); if (xircom_debug > 2) { printk(KERN_DEBUG "%s: Done xircom_up(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n", dev->name, inl(ioaddr + CSR0), inl(ioaddr + CSR5), inl(ioaddr + CSR6)); }}static intxircom_open(struct net_device *dev){ struct xircom_private *tp = netdev_priv(dev); if (request_irq(dev->irq, &xircom_interrupt, SA_SHIRQ, dev->name, dev)) return -EAGAIN; xircom_up(dev); tp->open = 1; return 0;}static void xircom_tx_timeout(struct net_device *dev){ struct xircom_private *tp = netdev_priv(dev); long ioaddr = dev->base_addr; if (media_cap[dev->if_port] & MediaIsMII) { /* Do nothing -- the media monitor should handle this. */ if (xircom_debug > 1) printk(KERN_WARNING "%s: Transmit timeout using MII device.\n", dev->name); }#if defined(way_too_many_messages) if (xircom_debug > 3) { int i; for (i = 0; i < RX_RING_SIZE; i++) { u8 *buf = (u8 *)(tp->rx_ring[i].buffer1); int j; printk(KERN_DEBUG "%2d: %8.8x %8.8x %8.8x %8.8x " "%2.2x %2.2x %2.2x.\n", i, (unsigned int)tp->rx_ring[i].status, (unsigned int)tp->rx_ring[i].length, (unsigned int)tp->rx_ring[i].buffer1, (unsigned int)tp->rx_ring[i].buffer2, buf[0], buf[1], buf[2]); for (j = 0; buf[j] != 0xee && j < 1600; j++) if (j < 100) printk(" %2.2x", buf[j]); printk(" j=%d.\n", j); } printk(KERN_DEBUG " Rx ring %8.8x: ", (int)tp->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) printk(" %8.8x", (unsigned int)tp->rx_ring[i].status); printk("\n" KERN_DEBUG " Tx ring %8.8x: ", (int)tp->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) printk(" %8.8x", (unsigned int)tp->tx_ring[i].status); printk("\n"); }#endif /* Stop and restart the chip's Tx/Rx processes . */ outl_CSR6(tp->csr6 | EnableRx, ioaddr); outl_CSR6(tp->csr6 | EnableTxRx, ioaddr); /* Trigger an immediate transmit demand. */ outl(0, ioaddr + CSR1); dev->trans_start = jiffies; netif_wake_queue (dev); tp->stats.tx_errors++;}/* Initialize the Rx and Tx rings, along with various 'dev' bits. */static void xircom_init_ring(struct net_device *dev){ struct xircom_private *tp = netdev_priv(dev); int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -