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

📄 8139too.c

📁 我实现的一个基于零拷贝技术高速捕包的原型代码
💻 C
📖 第 1 页 / 共 5 页
字号:

    tp->cur_rx = 0;

    /* This is check_duplex() */
    if (tp->phys[0] >= 0  ||  (tp->drv_flags & HAS_MII_XCVR))
    {
        u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5);
        if (mii_reg5 == 0xffff)
            ;					/* Not there */
        else if ((mii_reg5 & 0x0100) == 0x0100
                 || (mii_reg5 & 0x00C0) == 0x0040)
            tp->full_duplex = 1;
        printk(KERN_INFO"%s: Setting %s%s-duplex based on"
               " auto-negotiated partner ability %4.4x.\n", dev->name,
               mii_reg5 == 0 ? "" :
               (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",
               tp->full_duplex ? "full" : "half", mii_reg5);
    }

    if (tp->chipset >= CH_8139A)
    {
        tmp = RTL_R8 (Config1) & Config1Clear;
        tmp |= Cfg1_Driver_Load;
        tmp |= (tp->chipset == CH_8139B) ? 3 : 1; /* Enable PM/VPD */
        RTL_W8_F (Config1, tmp);
    }
    else
    {
        u8 foo = RTL_R8 (Config1) & Config1Clear;
        RTL_W8 (Config1, tp->full_duplex ? (foo|0x60) : (foo|0x20));
    }

    if (tp->chipset >= CH_8139B)
    {
        tmp = RTL_R8 (Config4) & ~(1<<2);
        /* chip will clear Rx FIFO overflow automatically */
        tmp |= (1<<7);
        RTL_W8 (Config4, tmp);

        /* disable magic packet scanning, which is enabled
         * when PM is enabled above (Config1) */
        RTL_W8 (Config3, RTL_R8 (Config3) & ~(1<<5));
    }

    /* Lock Config[01234] and BMCR register writes */
    RTL_W8_F (Cfg9346, Cfg9346_Lock);
    udelay (10);
    //初始化接收环缓冲区dma地址
    /* init Rx ring buffer DMA address */
#ifdef ZERO_COPY

#else

    RTL_W32_F (RxBuf, tp->rx_ring_dma);
#endif


    /* init Tx buffer DMA addresses */
    for (i = 0; i < NUM_TX_DESC; i++)
        RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs));

    RTL_W32_F (RxMissed, 0);

    rtl8139_set_rx_mode (dev);

    /* no early-rx interrupts */
    RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear);

    /* make sure RxTx has started */
    RTL_W8_F (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear) |
              CmdRxEnb | CmdTxEnb);

    /* Enable all known interrupts by setting the interrupt mask. */
    RTL_W16_F (IntrMask, rtl8139_intr_mask);

    netif_start_queue (dev);

    DPRINTK ("EXIT\n");
}


/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
static void rtl8139_init_ring (struct net_device *dev)
{
    struct rtl8139_private *tp = dev->priv;
    int i;

    DPRINTK ("ENTER\n");

    tp->cur_rx = 0;
    tp->cur_tx = 0;
    tp->dirty_tx = 0;

    for (i = 0; i < NUM_TX_DESC; i++)
    {
        tp->tx_info[i].skb = NULL;
        tp->tx_info[i].mapping = 0;
        tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE];
    }

    DPRINTK ("EXIT\n");
}


static int rtl8139CP_open (struct net_device *dev)
{
    struct rtl8139_private *tp = dev->priv;
    int retval;
    u8 diff;			//for 8139C+
    u32 txPhyAddr, rxPhyAddr;	//for 8139C+

#ifdef RTL8139_DEBUG

    void *ioaddr = tp->mmio_addr;
#endif

    DPRINTK ("ENTER\n");

    retval = request_irq (dev->irq, rtl8139CP_interrupt, SA_SHIRQ, dev->name, dev);
    if (retval)
    {
        DPRINTK ("EXIT, returning %d\n", retval);
        return retval;
    }

    //////////////////////////////////////////////////////////////////////////////
    tp->TxDescArrays= kmalloc(NUM_CP_TX_DESC*sizeof(struct CPlusTxDesc)+256 , GFP_KERNEL);
    // Tx Desscriptor needs 256 bytes alignment;
    txPhyAddr=virt_to_bus(tp->TxDescArrays);
    diff=txPhyAddr-((txPhyAddr >> 8)<< 8);
    diff=256-diff;
    txPhyAddr +=diff;
    tp->TxDescArray = (struct CPlusTxDesc *)(tp->TxDescArrays + diff);

    tp->RxDescArrays= kmalloc(NUM_CP_RX_DESC*sizeof(struct CPlusRxDesc)+256 , GFP_KERNEL);
    // Rx Desscriptor needs 256 bytes alignment;
    rxPhyAddr=virt_to_bus(tp->RxDescArrays);
    diff=rxPhyAddr-((rxPhyAddr >> 8)<< 8);
    diff=256-diff;
    rxPhyAddr +=diff;
    tp->RxDescArray = (struct CPlusRxDesc *)(tp->RxDescArrays + diff);

    if (tp->TxDescArrays == NULL || tp->RxDescArrays == NULL)
    {
        printk(KERN_INFO"Allocate RxDescArray or TxDescArray failed\n");
        free_irq(dev->irq, dev);
        if (tp->TxDescArrays)
            kfree(tp->TxDescArrays);
        if (tp->RxDescArrays)
            kfree(tp->RxDescArrays);
        DPRINTK ("EXIT, returning -ENOMEM\n");
        return -ENOMEM;
    }
    tp->RxBufferRings=kmalloc( CP_RX_BUF_SIZE*NUM_CP_RX_DESC, GFP_KERNEL);
    if(tp->RxBufferRings==NULL)
    {
        printk(KERN_INFO"Allocate RxBufferRing failed\n");
    }
    //////////////////////////////////////////////////////////////////////////////
    tp->full_duplex = tp->duplex_lock;
    tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
    tp->twistie = 1;

    rtl8139CP_init_ring (dev);
    rtl8139CP_hw_start (dev);

    DPRINTK ("%s: rtl8139_open() ioaddr %#lx IRQ %d"
             " GP Pins %2.2x %s-duplex.\n",
             dev->name, pci_resource_start (tp->pci_dev, 1),
             dev->irq, RTL_R8 (MediaStatus),
             tp->full_duplex ? "full" : "half");


    DPRINTK ("EXIT, returning 0\n");
    return 0;
}


/* Start the hardware at open or resume. */
static void rtl8139CP_hw_start (struct net_device *dev)
{
    struct rtl8139_private *tp = dev->priv;
    void *ioaddr = tp->mmio_addr;
    u32 i;
    u8 tmp;
    u16 BasicModeCtrlReg;
    u8 MediaStatusReg;

    DPRINTK ("ENTER\n");

    /* Soft reset the chip. */
    RTL_W8 (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear) | CmdReset);
    udelay (100);

    /* Check that the chip has finished the reset. */
    for (i = 1000; i > 0; i--)
        if ((RTL_R8 (ChipCmd) & CmdReset) == 0)
            break;

    /* unlock Config[01234] and BMCR register writes */
    RTL_W8_F (Cfg9346, Cfg9346_Unlock);

    RTL_W16 (CPlusCmd, CPlusTxEnb | CPlusRxEnb | CPlusCheckSumEnb);	//C+ mode only

    /* Restore our idea of the MAC address. */
    RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0)));
    RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4)));

    /* Must enable Tx/Rx before setting transfer thresholds! */
    RTL_W8 (ChipCmd,CmdRxEnb | CmdTxEnb);					//C+ mode only
    RTL_W8 (CPlusEarlyTxThldReg, CPlusEarlyTxThld);			//C+ mode only


    i = rtl8139_rx_config | (RTL_R32 (RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
    RTL_W32_F (RxConfig, i);

    /* Check this value: the documentation for IFG contradicts ifself. */
    RTL_W32 (TxConfig, (TX_DMA_BURST << TxDMAShift)|0x03000000);

    tp->CP_cur_rx = 0;

    /*
    	//////////////////////////////////////////////////////////////
    	RTL_W8_F (Cfg9346, Cfg9346_Unlock);
    	RTL_W16 (NWayAdvert, AutoNegoAbility10half | AutoNegoAbility10full | AutoNegoAbility100half | AutoNegoAbility100full);
    	RTL_W16_F (BasicModeCtrl, AutoNegotiationEnable|AutoNegotiationRestart);
    	RTL_W8_F (Cfg9346, Cfg9346_Lock);
    	//////////////////////////////////////////////////////////////
    */
    MediaStatusReg = RTL_R8(MediaStatus);
    BasicModeCtrlReg = RTL_R16(BasicModeCtrl);

    /* This is check_duplex() */
    if (tp->phys[0] >= 0  ||  (tp->drv_flags & HAS_MII_XCVR))
    {
        u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5);
        if (mii_reg5 == 0xffff)
            ;					/* Not there */
        else if ((mii_reg5 & 0x0100) == 0x0100
                 || (mii_reg5 & 0x00C0) == 0x0040)
            tp->full_duplex = 1;
        /*
        		printk(KERN_INFO"%s: Setting %s%s-duplex based on"
        			   " auto-negotiated partner ability %4.4x.\n", dev->name,
        			   mii_reg5 == 0 ? "" :
        			   (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",
        			   tp->full_duplex ? "full" : "half", mii_reg5);
        */
        printk(KERN_INFO"%s: Setting %s%s-duplex based on"
               " auto-negotiated partner ability %4.4x.\n", dev->name,
               (MediaStatusReg & Speed_10) ? "10mbps " : "100mbps ",
               (BasicModeCtrlReg & DuplexMode) ? "full" : "half", mii_reg5);
    }

    if (tp->chipset >= CH_8139A)
    {
        tmp = RTL_R8 (Config1) & Config1Clear;
        tmp |= Cfg1_Driver_Load;
        tmp |= (tp->chipset == CH_8139B) ? 3 : 1; /* Enable PM/VPD */
        RTL_W8_F (Config1, tmp);
    }
    else
    {
        u8 foo = RTL_R8 (Config1) & Config1Clear;
        RTL_W8 (Config1, tp->full_duplex ? (foo|0x60) : (foo|0x20));
    }

    if (tp->chipset >= CH_8139B)
    {
        tmp = RTL_R8 (Config4) & ~(1<<2);
        /* chip will clear Rx FIFO overflow automatically */
        tmp |= (1<<7);
        RTL_W8 (Config4, tmp);

        /* disable magic packet scanning, which is enabled
         * when PM is enabled above (Config1) */
        RTL_W8 (Config3, RTL_R8 (Config3) & ~(1<<5));
    }

    RTL_W32 ( CPlusTxStartAddr, virt_to_bus(tp->TxDescArray) );	//C+ mode only
    RTL_W32 ( CPlusRxStartAddr, virt_to_bus(tp->RxDescArray) );	//C+ mode only

    /* Lock Config[01234] and BMCR register writes */
    RTL_W8_F (Cfg9346, Cfg9346_Lock);
    udelay (10);

    RTL_W32_F (RxMissed, 0);

    rtl8139_set_rx_mode (dev);

    /* no early-rx interrupts */
    RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear);

    /* Enable all known interrupts by setting the interrupt mask. */
    RTL_W16_F (IntrMask, rtl8139_intr_mask);

    netif_start_queue (dev);

    DPRINTK ("EXIT\n");
}


/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
static void rtl8139CP_init_ring (struct net_device *dev)
{
    struct rtl8139_private *tp = dev->priv;
    int i;


    DPRINTK ("ENTER\n");

    //////////////////////////////////////////////////////////////////////////////
    tp->CP_cur_rx = 0;
    tp->CP_cur_tx = 0;
    tp->CP_dirty_tx = 0;
    memset(tp->TxDescArray, 0x0, NUM_CP_TX_DESC*sizeof(struct CPlusTxDesc));
    memset(tp->RxDescArray, 0x0, NUM_CP_RX_DESC*sizeof(struct CPlusRxDesc));

    for (i=0 ; i<NUM_CP_TX_DESC ; i++)
    {
        tp->Tx_skbuff[i]=NULL;
    }
    for (i=0; i <NUM_CP_RX_DESC; i++)
    {
        if(i==(NUM_CP_RX_DESC-1))
            tp->RxDescArray[i].status = 0xC0000000+CP_RX_BUF_SIZE;
        else
            tp->RxDescArray[i].status = 0x80000000+CP_RX_BUF_SIZE;

        tp->RxBufferRing[i]= &(tp->RxBufferRings[i*CP_RX_BUF_SIZE]);
        tp->RxDescArray[i].buf_addr=virt_to_bus(tp->RxBufferRing[i]);
    }
    //////////////////////////////////////////////////////////////////////////////
    DPRINTK ("EXIT\n");
}





static void rtl8139_tx_clear (struct rtl8139_private *tp)
{
    int i;

    tp->cur_tx = 0;
    tp->dirty_tx = 0;

    /* Dump the unsent Tx packets. */
    for (i = 0; i < NUM_TX_DESC; i++)
    {
        struct ring_info *rp = &tp->tx_info[i];
        if (rp->mapping != 0)
        {
            pci_unmap_single (tp->pci_dev, rp->mapping,
                              rp->skb->len, PCI_DMA_TODEVICE);
            rp->mapping = 0;
        }
        if (rp->skb)
        {
            dev_kfree_skb (rp->skb);
            rp->skb = NULL;
            tp->stats.tx_dropped++;
        }
    }
}


static void rtl8139CP_tx_clear (struct rtl8139_private *tp)
{
    int i;

    tp->CP_cur_tx=0;
    for (i=0 ; i<NUM_CP_TX_DESC ; i++)
    {
        if ( tp->Tx_skbuff[i]!=NULL )
        {
            dev_kfree_skb (tp->Tx_skbuff[i]);
            tp->Tx_skbuff[i] = NULL;
            tp->stats.tx_dropped++;
        }
    }
}


static void rtl8139_tx_timeout (struct net_device *dev)
{
    struct rtl8139_private *tp = dev->priv;
    void *ioaddr = tp->mmio_addr;
    u8 tmp8;

    DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x "
             "media %2.2x.\n", dev->name,
             RTL_R8 (ChipCmd),
             RTL_R16 (IntrStatus),
             RTL_R8 (MediaStatus));

    /* disable Tx ASAP, if not already */
    tmp8 = RTL_R8 (ChipCmd);
    if (tmp8 & CmdTxEnb)
        RTL_W8 (ChipCmd, tmp8 & ~CmdTxEnb);

    /* Disable interrupts by clearing the interrupt mask. */
    RTL_W16 (IntrMask, 0x0000);

    /* Stop a shared interrupt from scavenging while we are. */
    spin_lock_irq (&tp->lock)
    ;

    rtl8139_tx_clear (tp);

    spin_unlock_irq (&tp->lock)
    ;

    /* ...and finally, reset everything */
    rtl8139_hw_start (dev);

    netif_wake_queue (dev);
}

static void rtl8139CP_tx_timeout (struct net_device *dev)
{
    struct rtl8139_private *tp = dev->priv;
    void *ioaddr = tp->mmio_addr;
    u8 tmp8;

    printk ("%s: %s - Transmit timeout, status %2.2x %4.4x "
            "media %2.2x.\n", dev->name, __FUNCTION__,
            RTL_R8 (ChipCmd),
            RTL_R16 (IntrStatus),
            RTL_R8 (MediaStatus));

    /* disable Tx ASAP, if not already */
    tmp

⌨️ 快捷键说明

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