📄 dl2k.c
字号:
static intmii_getbit (struct net_device *dev){ long ioaddr = dev->base_addr + PhyCtrl; u8 data; data = (readb (ioaddr) & 0xf8) | MII_READ; writeb (data, ioaddr); mii_delay (); writeb (data | MII_CLK, ioaddr); mii_delay (); return ((readb (ioaddr) >> 1) & 1);}static voidmii_send_bits (struct net_device *dev, u32 data, int len){ int i; for (i = len - 1; i >= 0; i--) { mii_sendbit (dev, data & (1 << i)); }}static intmii_read (struct net_device *dev, int phy_addr, int reg_num){ u32 cmd; int i; u32 retval = 0; /* Preamble */ mii_send_bits (dev, 0xffffffff, 32); /* ST(2), OP(2), ADDR(5), REG#(5), TA(2), Data(16) total 32 bits */ /* ST,OP = 0110'b for read operation */ cmd = (0x06 << 10 | phy_addr << 5 | reg_num); mii_send_bits (dev, cmd, 14); /* Turnaround */ if (mii_getbit (dev)) goto err_out; /* Read data */ for (i = 0; i < 16; i++) { retval |= mii_getbit (dev); retval <<= 1; } /* End cycle */ mii_getbit (dev); return (retval >> 1) & 0xffff; err_out: return 0;}static intmii_write (struct net_device *dev, int phy_addr, int reg_num, u16 data){ u32 cmd; /* Preamble */ mii_send_bits (dev, 0xffffffff, 32); /* ST(2), OP(2), ADDR(5), REG#(5), TA(2), Data(16) total 32 bits */ /* ST,OP,AAAAA,RRRRR,TA = 0101xxxxxxxxxx10'b = 0x5002 for write */ cmd = (0x5002 << 16) | (phy_addr << 23) | (reg_num << 18) | data; mii_send_bits (dev, cmd, 32); /* End cycle */ mii_getbit (dev); return 0;}static intmii_wait_link (struct net_device *dev, int wait){ BMSR_t bmsr; int phy_addr; struct netdev_private *np; np = dev->priv; phy_addr = np->phy_addr; do { bmsr.image = mii_read (dev, phy_addr, MII_BMSR); if (bmsr.bits.link_status) return 0; mdelay (1); } while (--wait > 0); return -1;}static intmii_get_media (struct net_device *dev){ ANAR_t negotiate; BMSR_t bmsr; BMCR_t bmcr; MSCR_t mscr; MSSR_t mssr; int phy_addr; struct netdev_private *np; np = dev->priv; phy_addr = np->phy_addr; bmsr.image = mii_read (dev, phy_addr, MII_BMSR); if (np->an_enable) { if (!bmsr.bits.an_complete) { /* Auto-Negotiation not completed */ return -1; } negotiate.image = mii_read (dev, phy_addr, MII_ANAR) & mii_read (dev, phy_addr, MII_ANLPAR); mscr.image = mii_read (dev, phy_addr, MII_MSCR); mssr.image = mii_read (dev, phy_addr, MII_MSSR); if (mscr.bits.media_1000BT_FD & mssr.bits.lp_1000BT_FD) { np->speed = 1000; np->full_duplex = 1; printk (KERN_INFO "Auto 1000 Mbps, Full duplex\n"); } else if (mscr.bits.media_1000BT_HD & mssr.bits.lp_1000BT_HD) { np->speed = 1000; np->full_duplex = 0; printk (KERN_INFO "Auto 1000 Mbps, Half duplex\n"); } else if (negotiate.bits.media_100BX_FD) { np->speed = 100; np->full_duplex = 1; printk (KERN_INFO "Auto 100 Mbps, Full duplex\n"); } else if (negotiate.bits.media_100BX_HD) { np->speed = 100; np->full_duplex = 0; printk (KERN_INFO "Auto 100 Mbps, Half duplex\n"); } else if (negotiate.bits.media_10BT_FD) { np->speed = 10; np->full_duplex = 1; printk (KERN_INFO "Auto 10 Mbps, Full duplex\n"); } else if (negotiate.bits.media_10BT_HD) { np->speed = 10; np->full_duplex = 0; printk (KERN_INFO "Auto 10 Mbps, Half duplex\n"); } if (negotiate.bits.pause) { np->tx_flow &= 1; np->rx_flow &= 1; } else if (negotiate.bits.asymmetric) { np->tx_flow = 0; np->rx_flow &= 1; } /* else tx_flow, rx_flow = user select */ } else { bmcr.image = mii_read (dev, phy_addr, MII_BMCR); if (bmcr.bits.speed100 == 1 && bmcr.bits.speed1000 == 0) { printk (KERN_INFO "Operating at 100 Mbps, "); } else if (bmcr.bits.speed100 == 0 && bmcr.bits.speed1000 == 0) { printk (KERN_INFO "Operating at 10 Mbps, "); } else if (bmcr.bits.speed100 == 0 && bmcr.bits.speed1000 == 1) { printk (KERN_INFO "Operating at 1000 Mbps, "); } if (bmcr.bits.duplex_mode) { printk ("Full duplex\n"); } else { printk ("Half duplex\n"); } } if (np->tx_flow) printk(KERN_INFO "Enable Tx Flow Control\n"); else printk(KERN_INFO "Disable Tx Flow Control\n"); if (np->rx_flow) printk(KERN_INFO "Enable Rx Flow Control\n"); else printk(KERN_INFO "Disable Rx Flow Control\n"); return 0;}static intmii_set_media (struct net_device *dev){ PHY_SCR_t pscr; BMCR_t bmcr; BMSR_t bmsr; ANAR_t anar; int phy_addr; struct netdev_private *np; np = dev->priv; phy_addr = np->phy_addr; /* Does user set speed? */ if (np->an_enable) { /* Advertise capabilities */ bmsr.image = mii_read (dev, phy_addr, MII_BMSR); anar.image = mii_read (dev, phy_addr, MII_ANAR); anar.bits.media_100BX_FD = bmsr.bits.media_100BX_FD; anar.bits.media_100BX_HD = bmsr.bits.media_100BX_HD; anar.bits.media_100BT4 = bmsr.bits.media_100BT4; anar.bits.media_10BT_FD = bmsr.bits.media_10BT_FD; anar.bits.media_10BT_HD = bmsr.bits.media_10BT_HD; anar.bits.pause = 1; anar.bits.asymmetric = 1; mii_write (dev, phy_addr, MII_ANAR, anar.image); /* Enable Auto crossover */ pscr.image = mii_read (dev, phy_addr, MII_PHY_SCR); pscr.bits.mdi_crossover_mode = 3; /* 11'b */ mii_write (dev, phy_addr, MII_PHY_SCR, pscr.image); /* Soft reset PHY */ mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET); bmcr.image = 0; bmcr.bits.an_enable = 1; bmcr.bits.restart_an = 1; bmcr.bits.reset = 1; mii_write (dev, phy_addr, MII_BMCR, bmcr.image); mdelay(1); } else { /* Force speed setting */ /* 1) Disable Auto crossover */ pscr.image = mii_read (dev, phy_addr, MII_PHY_SCR); pscr.bits.mdi_crossover_mode = 0; mii_write (dev, phy_addr, MII_PHY_SCR, pscr.image); /* 2) PHY Reset */ bmcr.image = mii_read (dev, phy_addr, MII_BMCR); bmcr.bits.reset = 1; mii_write (dev, phy_addr, MII_BMCR, bmcr.image); /* 3) Power Down */ bmcr.image = 0x1940; /* must be 0x1940 */ mii_write (dev, phy_addr, MII_BMCR, bmcr.image); mdelay (100); /* wait a certain time */ /* 4) Advertise nothing */ mii_write (dev, phy_addr, MII_ANAR, 0); /* 5) Set media and Power Up */ bmcr.image = 0; bmcr.bits.power_down = 1; if (np->speed == 100) { bmcr.bits.speed100 = 1; bmcr.bits.speed1000 = 0; printk (KERN_INFO "Manual 100 Mbps, "); } else if (np->speed == 10) { bmcr.bits.speed100 = 0; bmcr.bits.speed1000 = 0; printk (KERN_INFO "Manual 10 Mbps, "); } if (np->full_duplex) { bmcr.bits.duplex_mode = 1; printk ("Full duplex\n"); } else { bmcr.bits.duplex_mode = 0; printk ("Half duplex\n"); }#if 0 /* Set 1000BaseT Master/Slave setting */ mscr.image = mii_read (dev, phy_addr, MII_MSCR); mscr.bits.cfg_enable = 1; mscr.bits.cfg_value = 0;#endif mii_write (dev, phy_addr, MII_BMCR, bmcr.image); mdelay(10); } return 0;}static intmii_get_media_pcs (struct net_device *dev){ ANAR_PCS_t negotiate; BMSR_t bmsr; BMCR_t bmcr; int phy_addr; struct netdev_private *np; np = dev->priv; phy_addr = np->phy_addr; bmsr.image = mii_read (dev, phy_addr, PCS_BMSR); if (np->an_enable) { if (!bmsr.bits.an_complete) { /* Auto-Negotiation not completed */ return -1; } negotiate.image = mii_read (dev, phy_addr, PCS_ANAR) & mii_read (dev, phy_addr, PCS_ANLPAR); np->speed = 1000; if (negotiate.bits.full_duplex) { printk (KERN_INFO "Auto 1000 Mbps, Full duplex\n"); np->full_duplex = 1; } else { printk (KERN_INFO "Auto 1000 Mbps, half duplex\n"); np->full_duplex = 0; } if (negotiate.bits.pause) { np->tx_flow &= 1; np->rx_flow &= 1; } else if (negotiate.bits.asymmetric) { np->tx_flow = 0; np->rx_flow &= 1; } /* else tx_flow, rx_flow = user select */ } else { bmcr.image = mii_read (dev, phy_addr, PCS_BMCR); printk (KERN_INFO "Operating at 1000 Mbps, "); if (bmcr.bits.duplex_mode) { printk ("Full duplex\n"); } else { printk ("Half duplex\n"); } } if (np->tx_flow) printk(KERN_INFO "Enable Tx Flow Control\n"); else printk(KERN_INFO "Disable Tx Flow Control\n"); if (np->rx_flow) printk(KERN_INFO "Enable Rx Flow Control\n"); else printk(KERN_INFO "Disable Rx Flow Control\n"); return 0;}static intmii_set_media_pcs (struct net_device *dev){ BMCR_t bmcr; ESR_t esr; ANAR_PCS_t anar; int phy_addr; struct netdev_private *np; np = dev->priv; phy_addr = np->phy_addr; /* Auto-Negotiation? */ if (np->an_enable) { /* Advertise capabilities */ esr.image = mii_read (dev, phy_addr, PCS_ESR); anar.image = mii_read (dev, phy_addr, MII_ANAR); anar.bits.half_duplex = esr.bits.media_1000BT_HD | esr.bits.media_1000BX_HD; anar.bits.full_duplex = esr.bits.media_1000BT_FD | esr.bits.media_1000BX_FD; anar.bits.pause = 1; anar.bits.asymmetric = 1; mii_write (dev, phy_addr, MII_ANAR, anar.image); /* Soft reset PHY */ mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET); bmcr.image = 0; bmcr.bits.an_enable = 1; bmcr.bits.restart_an = 1; bmcr.bits.reset = 1; mii_write (dev, phy_addr, MII_BMCR, bmcr.image); mdelay(1); } else { /* Force speed setting */ /* PHY Reset */ bmcr.image = 0; bmcr.bits.reset = 1; mii_write (dev, phy_addr, MII_BMCR, bmcr.image); mdelay(10); bmcr.image = 0; bmcr.bits.an_enable = 0; if (np->full_duplex) { bmcr.bits.duplex_mode = 1; printk (KERN_INFO "Manual full duplex\n"); } else { bmcr.bits.duplex_mode = 0; printk (KERN_INFO "Manual half duplex\n"); } mii_write (dev, phy_addr, MII_BMCR, bmcr.image); mdelay(10); /* Advertise nothing */ mii_write (dev, phy_addr, MII_ANAR, 0); } return 0;}static intrio_close (struct net_device *dev){ long ioaddr = dev->base_addr; struct netdev_private *np = dev->priv; struct sk_buff *skb; int i; netif_stop_queue (dev); /* Disable interrupts */ writew (0, ioaddr + IntEnable); /* Stop Tx and Rx logics */ writel (TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl); synchronize_irq (dev->irq); free_irq (dev->irq, dev); del_timer_sync (&np->timer); /* Free all the skbuffs in the queue. */ for (i = 0; i < RX_RING_SIZE; i++) { np->rx_ring[i].status = 0; np->rx_ring[i].fraginfo = 0; skb = np->rx_skbuff[i]; if (skb) { pci_unmap_single (np->pdev, np->rx_ring[i].fraginfo, skb->len, PCI_DMA_FROMDEVICE); dev_kfree_skb (skb); np->rx_skbuff[i] = NULL; } } for (i = 0; i < TX_RING_SIZE; i++) { skb = np->tx_skbuff[i]; if (skb) { pci_unmap_single (np->pdev, np->tx_ring[i].fraginfo, skb->len, PCI_DMA_TODEVICE); dev_kfree_skb (skb); np->tx_skbuff[i] = NULL; } } return 0;}static void __devexitrio_remove1 (struct pci_dev *pdev){ struct net_device *dev = pci_get_drvdata (pdev); if (dev) { struct netdev_private *np = dev->priv; unregister_netdev (dev); pci_free_consistent (pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma); pci_free_consistent (pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma);#ifdef MEM_MAPPING iounmap ((char *) (dev->base_addr));#endif free_netdev (dev); pci_release_regions (pdev); pci_disable_device (pdev); } pci_set_drvdata (pdev, NULL);}static struct pci_driver rio_driver = { .name = "dl2k", .id_table = rio_pci_tbl, .probe = rio_probe1, .remove = __devexit_p(rio_remove1),};static int __initrio_init (void){ return pci_module_init (&rio_driver);}static void __exitrio_exit (void){ pci_unregister_driver (&rio_driver);}module_init (rio_init);module_exit (rio_exit);/* Compile command: gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -c dl2k.cRead Documentation/networking/dl2k.txt for details.*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -