⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adapter.c

📁 xilinx trimode mac driver for linux
💻 C
📖 第 1 页 / 共 5 页
字号:
        case (MARVELL_88E1111_LINKSPEED_1000M):            XTemac_SetOperatingSpeed(&lp->Emac, 1000);            printk(KERN_INFO "%s: XTemac: speed set to 1000Mb/s\n", dev->name);            lp->cur_speed = 1000;            break;        case (MARVELL_88E1111_LINKSPEED_100M):            XTemac_SetOperatingSpeed(&lp->Emac, 100);            printk(KERN_INFO "%s: XTemac: speed set to 100Mb/s\n", dev->name);            lp->cur_speed = 100;            break;        case (MARVELL_88E1111_LINKSPEED_10M):            XTemac_SetOperatingSpeed(&lp->Emac, 10);            printk(KERN_INFO "%s: XTemac: speed set to 10Mb/s\n", dev->name);            lp->cur_speed = 10;            break;        default:            XTemac_SetOperatingSpeed(&lp->Emac, 1000);            printk(KERN_INFO "%s: XTemac: speed set to 1000Mb/s\n", dev->name);            lp->cur_speed = 1000;            break;    }#else    if (XTemac_mGetPhysicalInterface(&lp->Emac) == XTE_PHY_TYPE_MII) {        phylinkspeed = 100;    } else {        phylinkspeed = 1000;    }    /*     * Try to renegotiate the speed until something sticks     */    while (phylinkspeed > 1) {        ret = renegotiate_speed(dev, phylinkspeed, FULL_DUPLEX);        /*         * ret == 1 - try it again         * ret == 0 - it worked         * ret <  0 - there was some failure negotiating the speed         */        if (ret == 0) {            /* it worked, get out of the loop */            break;        }        /* it didn't work this time, but it may work if we try again */        if ((ret == 1)  && (retry_count)) {            retry_count--;            printk("trying again...\n");            continue;        }        /* reset the retry_count, becuase we're about to try a lower speed */        retry_count = 1;        phylinkspeed /= 10;    }    if (phylinkspeed == 1) {        printk(KERN_INFO "%s: XTemac: could not negotiate speed\n", dev->name);        lp->cur_speed = 0;        return;    }    XTemac_SetOperatingSpeed(&lp->Emac, phylinkspeed);    printk(KERN_INFO "%s: XTemac: speed set to %dMb/s\n", dev->name, phylinkspeed);    lp->cur_speed = phylinkspeed;#endif}/* * Helper function to reset the underlying hardware.  This is called * when we get into such deep trouble that we don't know how to handle * otherwise. *//* * This reset function should handle five different reset request types * from other functions. The reset request types include *      1. FIFO error: FifoWrite()/FifoSend()/FifoRecv()/FifoRead() fails *      2. DMA error: SgAlloc()/SgCommit()/SgFree() fails *      3. DUPLEX error: MAC DUPLEX is not full duplex or does not match *                       PHY setting *      4. TX Timeout: Timeout occurs for a TX frame given to this adapter *      5. Error Status: Temac Error interrupt occurs and asks for a reset * */static voidreset(struct net_device *dev, u32 line_num){    struct net_local *lp = (struct net_local *) dev->priv;    u16 TxThreshold, TxWaitBound, RxThreshold, RxWaitBound;    u32 Options;    static u32 reset_cnt = 0;    printk(KERN_INFO "%s: XTemac: resets (#%u) from adapter code line %d\n",                dev->name, ++reset_cnt, line_num);    /* Shouldn't really be necessary, but shouldn't hurt. */    netif_stop_queue(dev);    /* Stop device */    XTemac_Stop(&lp->Emac);    /*     * XTemac_Reset puts the device back to the default state.  We need     * to save all the settings we don't already know, reset, restore     * the settings, and then restart the temac.     */    Options = XTemac_GetOptions(&lp->Emac);    if (XTemac_mIsSgDma(&lp->Emac)) {        /*         * The following two functions will return an error if we are         * not doing scatter-gather DMA.  We just checked that so we         * can safely ignore the return values.         */        (XStatus) XTemac_IntrSgCoalGet(&lp->Emac, XTE_RECV, &RxThreshold,                                       &RxWaitBound);        (XStatus) XTemac_IntrSgCoalGet(&lp->Emac, XTE_SEND, &TxThreshold,                                       &TxWaitBound);    }    /* now we can reset the device */    XTemac_Reset(&lp->Emac, 0);    /* Reset on TEMAC also resets PHY. Give it some time to finish negotiation     * before we move on */    mdelay(2000);    /*     * The following four functions will return an error if the     * EMAC is already started.  We just stopped it by calling     * XTemac_Reset() so we can safely ignore the return values.     */    (XStatus) XTemac_SetMacAddress(&lp->Emac, dev->dev_addr);    (XStatus) XTemac_SetOptions(&lp->Emac, Options);    (XStatus) XTemac_ClearOptions(&lp->Emac, ~Options);    Options = XTemac_GetOptions(&lp->Emac);    printk(KERN_INFO "%s: XTemac: Options: 0x%x\n", dev->name, Options);    set_mac_speed(lp);    if (XTemac_mIsSgDma(&lp->Emac)) { /* SG DMA mode */        /*         * The following 2 functions will return an error if         * we are not doing scatter-gather DMA or if the EMAC is         * already started.  We just checked that we are indeed         * doing scatter-gather and we just stopped the EMAC so         * we can safely ignore the return values.         */        (XStatus) XTemac_IntrSgCoalSet(&lp->Emac, XTE_RECV, RxThreshold,                                    RxWaitBound);        (XStatus) XTemac_IntrSgCoalSet(&lp->Emac, XTE_SEND, TxThreshold,                                    TxWaitBound);        /* Enable both SEND and RECV interrupts */        XTemac_IntrSgEnable(&lp->Emac, XTE_SEND | XTE_RECV);    }    else { /* FIFO interrupt mode */        XTemac_IntrFifoEnable(&lp->Emac, XTE_RECV | XTE_SEND);    }    if (lp->deferred_skb) {        dev_kfree_skb_any(lp->deferred_skb);        lp->deferred_skb = NULL;        lp->stats.tx_errors++;    }    /*     * XTemac_Start returns an error when: if configured for     * scatter-gather DMA and a descriptor list has not yet been created     * for the send or receive channel, or if no receive buffer descriptors     * have been initialized. Those are not happening. so ignore the returned     * result checking.     */    (XStatus) XTemac_Start(&lp->Emac);    /* We're all ready to go.  Start the queue in case it was stopped. */    netif_wake_queue(dev);}/* * The PHY registers read here should be standard registers in all PHY chips */static intget_phy_status(struct net_device *dev, DUPLEX * duplex, int *linkup){    struct net_local *lp = (struct net_local *) dev->priv;    u16 reg;    XStatus xs;    xs = XTemac_PhyRead(&lp->Emac, lp->gmii_addr, MII_BMCR, &reg);    if (xs != XST_SUCCESS) {        printk(KERN_ERR               "%s: XTemac: could not read PHY control register; error %d\n",               dev->name, xs);        return -1;    }    *duplex = FULL_DUPLEX;    xs = XTemac_PhyRead(&lp->Emac, lp->gmii_addr, MII_BMSR, &reg);    if (xs != XST_SUCCESS) {        printk(KERN_ERR               "%s: XTemac: could not read PHY status register; error %d\n",               dev->name, xs);        return -1;    }    *linkup = (reg & BMSR_LSTATUS) != 0;    return 0;}/* * This routine is used for two purposes.  The first is to keep the * EMAC's duplex setting in sync with the PHY's.  The second is to keep * the system apprised of the state of the link.  Note that this driver * does not configure the PHY.  Either the PHY should be configured for * auto-negotiation or it should be handled by something like mii-tool. */static voidpoll_gmii(unsigned long data){    struct net_device *dev;    struct net_local *lp;    DUPLEX phy_duplex;    int phy_carrier;    int netif_carrier;    unsigned long flags;    spin_lock_irqsave(&XTE_spinlock, flags);    dev = (struct net_device *) data;    lp = (struct net_local *) dev->priv;    /* First, find out what's going on with the PHY. */    if (get_phy_status(dev, &phy_duplex, &phy_carrier)) {        printk(KERN_ERR "%s: XTemac: terminating link monitoring.\n",               dev->name);        spin_unlock_irqrestore(&XTE_spinlock, flags);        return;    }    netif_carrier = netif_carrier_ok(dev) != 0;    if (phy_carrier != netif_carrier) {        if (phy_carrier) {            printk(KERN_INFO "%s: XTemac: PHY Link carrier restored.\n",                   dev->name);            netif_carrier_on(dev);        } else {            printk(KERN_INFO "%s: XTemac: PHY Link carrier lost.\n", dev->name);            netif_carrier_off(dev);        }    }    /* Set up the timer so we'll get called again in 2 seconds. */    lp->phy_timer.expires = jiffies + 2 * HZ;    add_timer(&lp->phy_timer);    spin_unlock_irqrestore(&XTE_spinlock, flags);}/* * This routine is registered with the OS as the function to call when * the TEMAC interrupts.  It in turn, calls the Xilinx OS independent * interrupt function.  There are different interrupt functions for FIFO * and scatter-gather so we just set a pointer (Isr) into our private * data so we don't have to figure it out here.  The Xilinx OS * independent interrupt function will in turn call any callbacks that * we have registered for various conditions. */static irqreturn_txenet_interrupt(int irq, void *dev_id, struct pt_regs *regs){    struct net_device *dev = dev_id;    struct net_local *lp = (struct net_local *) dev->priv;    /* Call it. */    (*(lp->Isr)) (&lp->Emac);    /* Right now, our IRQ handlers do not return a status. Let's always return     * IRQ_HANDLED here for now.     */    return IRQ_HANDLED;}static intxenet_open(struct net_device *dev){    struct net_local *lp;    u32 Options;    unsigned long flags;    /*     * Just to be safe, stop TX queue and the device first.  If the device is     * already stopped, an error will be returned.  In this case, we don't     * really care.     */    netif_stop_queue(dev);    spin_lock_irqsave(&XTE_spinlock, flags);    lp = (struct net_local *) dev->priv;    XTemac_Stop(&lp->Emac);    /* Set the MAC address each time opened. */    if (XTemac_SetMacAddress(&lp->Emac, dev->dev_addr) != XST_SUCCESS) {        printk(KERN_ERR "%s: XTemac: could not set MAC address.\n", dev->name);        spin_unlock_irqrestore(&XTE_spinlock, flags);        return -EIO;    }    /*     * If the device is not configured for polled mode, connect to the     * interrupt controller and enable interrupts.  Currently, there     * isn't any code to set polled mode, so this check is probably     * superfluous.     */    Options = XTemac_GetOptions(&lp->Emac);    Options &= ~XTE_SGEND_INT_OPTION;    Options &= ~XTE_REPORT_RXERR_OPTION;    Options |= XTE_FLOW_CONTROL_OPTION;    Options |= XTE_JUMBO_OPTION;#if XTE_AUTOSTRIPPING    Options |= XTE_FCS_STRIP_OPTION;#endif    (XStatus) XTemac_SetOptions(&lp->Emac, Options);    (XStatus) XTemac_ClearOptions(&lp->Emac, ~Options);    Options = XTemac_GetOptions(&lp->Emac);    printk(KERN_INFO "%s: XTemac: Options: 0x%x\n", dev->name, Options);    /* Register interrupt handler */    if ((Options & XTE_POLLED_OPTION) == 0) {        int retval;        /* Grab the IRQ */        retval = request_irq(dev->irq, &xenet_interrupt, 0, dev->name, dev);        if (retval) {            printk(KERN_ERR                   "%s: XTemac: could not allocate interrupt %d.\n",                   dev->name, dev->irq);            spin_unlock_irqrestore(&XTE_spinlock, flags);            return retval;        }    }    /* give the system enough time to establish a link */    mdelay(2000);    set_mac_speed(lp);    INIT_LIST_HEAD(&(lp->rcv));    INIT_LIST_HEAD(&(lp->xmit));    /* Enable interrupts if not in polled mode */    if ((Options & XTE_POLLED_OPTION) == 0) {        if (!XTemac_mIsSgDma(&lp->Emac)) { /*fifo direct interrupt driver mode*/            XTemac_IntrFifoEnable(&lp->Emac, XTE_RECV | XTE_SEND);        }        else {/* SG DMA mode */            XTemac_IntrSgEnable(&lp->Emac, XTE_SEND | XTE_RECV);        }    }    /* Start TEMAC device */    if (XTemac_Start(&lp->Emac) != XST_SUCCESS) {        printk(KERN_ERR "%s: XTemac: could not start device.\n", dev->name);        free_irq(dev->irq, dev);        spin_unlock_irqrestore(&XTE_spinlock, flags);        return -EBUSY;    }    spin_unlock_irqrestore(&XTE_spinlock, flags);    if (XTemac_mIsSgDma(&lp->Emac)) {      u16 threshold_s, timer_s, threshold_r, timer_r;      (XStatus) XTemac_IntrSgCoalGet(&lp->Emac, XTE_SEND, &threshold_s, &timer_s);      (XStatus) XTemac_IntrSgCoalGet(&lp->Emac, XTE_RECV, &threshold_r, &timer_r);      printk(KERN_INFO "%s: XTemac: Send Threshold = %d, Receive Threshold = %d\n",             dev->name, threshold_s, threshold_r);      printk(KERN_INFO "%s: XTemac: Send Wait bound = %d, Receive Wait bound = %d\n",             dev->name, timer_s, timer_r);    }    /* We're ready to go. */    netif_start_queue(dev);    /* Set up the PHY monitoring timer. */    lp->phy_timer.expires = jiffies + 2 * HZ;    lp->phy_timer.data = (unsigned long) dev;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -