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

📄 8139too.c

📁 我实现的一个基于零拷贝技术高速捕包的原型代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{
    int i, j;
    unsigned long c;
    unsigned char *p=(unsigned char *)&c, *p1;
    unsigned char k;
    struct rtl8139_private *tp = dev->priv;

    ;
    atomic_set( &tp->CRC32DoubleCheck_ERR, 0 );

    c = 0x12340000;

    for (i = 0; i < 256; ++i)
    {
        k = ReverseBit((unsigned char)i);
        for (c = ((unsigned long)k) << 24, j = 8; j > 0; --j)
            c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1);
        p1 = (unsigned char *)(&crc32_table[i]);

        p1[0] = ReverseBit(p[3]);
        p1[1] = ReverseBit(p[2]);
        p1[2] = ReverseBit(p[1]);
        p1[3] = ReverseBit(p[0]);
    }
}

unsigned long crc32(unsigned char *buf, int len)
{
    unsigned char *p;
    unsigned long  crc;

    crc = 0xffffffff;       /* preload shift register, per CRC-32 spec */

    for (p = buf; len > 0; ++p, --len)
    {
        crc = crc32_table[ (crc ^ *p) & 0xff] ^ (crc >> 8);
    }
    return ~crc;    /* transmit complement, per CRC-32 spec */
}


//int DoubleCheck( &rx_ring[ring_offset + 4], pkt_size )
//----------------------------------------------------------------------
// rx_data_ptr	:	the start pointer of the received data
// pkt_size	:	the received data length excluding 4-bytes CRC
//----------------------------------------------------------------------
static inline int CRC32DoubleCheck( unsigned char *rx_data_ptr, unsigned int pkt_size )
{
    unsigned short	EtherType = *( (unsigned short *)(rx_data_ptr + 12) );
    unsigned char	IPType = *(rx_data_ptr + 23);
    unsigned long	SWCRC = 0xffffffff;
    unsigned long	HWCRC;

    //----------------------------------------------------------------------
    // If this is the packet of type TCP/IP, skip CRC32 double-check.
    //----------------------------------------------------------------------
    if( (EtherType == 0x0008) && (IPType == 0x06) )
    {
        return 0;
    }

    HWCRC = *( (unsigned long *)(rx_data_ptr + pkt_size) );

    SWCRC = crc32( rx_data_ptr, pkt_size );

    //	printk(KERN_INFO "RTL8139: %s( pkt_size = %d, EtherType = 0x%4.4x, IPType = 0x%2.2x). HWCRC = 0x%8.8lx, SWCRC = 0x%8.8lx\n",
    //				__FUNCTION__, pkt_size, EtherType, IPType, HWCRC, SWCRC );

    return ( (SWCRC == HWCRC) ? 0 : -1 );
}




#ifdef RTL8139_PROC_DEBUG
//==========================================================================================
struct proc_dir_entry *rtl8139_Proc_root;
struct proc_dir_entry *rtl8139_Proc;


static int rtl8139_proc_status(char *buffer,
                               char **buffer_location,
                               off_t offset,
                               int buffer_length,
                               int *eof,
                               void *data)
{
    char *buf = buffer;
    struct net_device *dev = (struct net_device *)data;

    buf += sprintf( buf, " ************ Current driver status ************\n\n\n" );
    buf += sprintf( buf, " MAC address = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
                    dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );

    buf += sprintf( buf, " ioaddr = 0x%8.8lx\n",  (unsigned long)dev->base_addr );
    buf += sprintf( buf, " irq = %d\n",  dev->irq );

    return (buf - buffer);
}


static void rtl8139_init_proc(struct net_device *dev)
{
    if(rtl8139_Proc_root == NULL)
        rtl8139_Proc_root = proc_mkdir("rtl8139", NULL);
    if(rtl8139_Proc_root != NULL)
    {
        rtl8139_Proc = create_proc_read_entry(
                           "status",0644, rtl8139_Proc_root, rtl8139_proc_status, (void *)dev);
    }
}

static void rtl8139_remove_proc(struct net_device *dev)
{
    if(rtl8139_Proc_root != NULL)
    {
        remove_proc_entry("status", rtl8139_Proc_root );
        remove_proc_entry("rtl8139", NULL );
    }
}
//==========================================================================================
#endif	//#ifdef RTL8139_PROC_DEBUG





//------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------
static int __devinit rtl8139_init_board (struct pci_dev *pdev, struct net_device **dev_out, void **ioaddr_out)
{
    void *ioaddr = NULL;
    struct net_device *dev;
    struct rtl8139_private *tp;
    u8 tmp8;
    int rc, i;
    u32 pio_start, pio_end, pio_flags, pio_len;
    unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
    u32 tmp;


    DPRINTK ("ENTER\n");

    assert (pdev != NULL);
    assert (ioaddr_out != NULL);

    *ioaddr_out = NULL;
    *dev_out = NULL;

    /* dev zeroed in init_etherdev */
    dev = init_etherdev (NULL, sizeof (*tp));
    if (dev == NULL)
    {
        printk (KERN_ERR PFX "unable to alloc new ethernet\n");
        DPRINTK ("EXIT, returning -ENOMEM\n");
        return -ENOMEM;
    }
    SET_MODULE_OWNER(dev);
    tp = dev->priv;

    /* enable device (incl. PCI PM wakeup and hotplug setup) */
    rc = pci_enable_device (pdev);
    if (rc)
        goto err_out;
    //不知道是否是使用mm io 还是端口io
    pio_start = pci_resource_start (pdev, 0);
    pio_end = pci_resource_end (pdev, 0);
    pio_flags = pci_resource_flags (pdev, 0);
    pio_len = pci_resource_len (pdev, 0);

    mmio_start = pci_resource_start (pdev, 1);
    mmio_end = pci_resource_end (pdev, 1);
    mmio_flags = pci_resource_flags (pdev, 1);
    mmio_len = pci_resource_len (pdev, 1);

    /* set this immediately, we need to know before
     * we talk to the chip directly */
    DPRINTK("PIO region size == 0x%02X\n", pio_len);
    DPRINTK("MMIO region size == 0x%02lX\n", mmio_len);
    if (pio_len == RTL8139B_IO_SIZE)
        tp->chipset = CH_8139B;

    /* make sure PCI base addr 0 is PIO */
    if (!(pio_flags & IORESOURCE_IO))
    {
        printk (KERN_ERR PFX "region #0 not a PIO resource, aborting\n");
        rc = -ENODEV;
        goto err_out;
    }

    /* make sure PCI base addr 1 is MMIO */
    if (!(mmio_flags & IORESOURCE_MEM))
    {
        printk (KERN_ERR PFX "region #1 not an MMIO resource, aborting\n");
        rc = -ENODEV;
        goto err_out;
    }

    /* check for weird/broken PCI region reporting */
    if ((pio_len < RTL_MIN_IO_SIZE) ||
            (mmio_len < RTL_MIN_IO_SIZE))
    {
        printk (KERN_ERR PFX "Invalid PCI region size(s), aborting\n");
        rc = -ENODEV;
        goto err_out;
    }


#ifndef USE_IO_OPS
    rc = pci_request_regions (pdev, dev->name);
    if (rc)
        goto err_out;
#endif /* !USE_IO_OPS */



    /* enable PCI bus-mastering */
    pci_set_master (pdev);
    //如果使用io空间
#ifdef USE_IO_OPS

    ioaddr = (void *) pio_start;
    printk ("%s: use pci IO map. ioaddr=0x%08lx\n", dev->name, (unsigned long)ioaddr);
#else
    /* ioremap MMIO region */
    ioaddr = ioremap (mmio_start, mmio_len);
    if (ioaddr == NULL)
    {
        printk (KERN_ERR PFX "cannot remap MMIO, aborting\n");
        rc = -EIO;
        goto err_out_free_res;
    }
    printk ("%s: use memory map. ioaddr=0x%08lx\n", dev->name, (unsigned long)ioaddr);
#endif /* USE_IO_OPS */

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

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

    /* Bring the chip out of low-power mode. */
    if (tp->chipset == CH_8139B)
    {
        RTL_W8 (Config1, RTL_R8 (Config1) & ~(1<<4));
        RTL_W8 (Config4, RTL_R8 (Config4) & ~(1<<2));
    }
    else
    {
        /* handle RTL8139A and RTL8139 cases */
        /* XXX from becker driver. is this right?? */
        RTL_W8 (Config1, 0);
    }

    /* make sure chip thinks PIO and MMIO are enabled */
    tmp8 = RTL_R8 (Config1);
    if ((tmp8 & Cfg1_PIO) == 0)
    {
        printk (KERN_ERR PFX "PIO not enabled, Cfg1=%02X, aborting\n", tmp8);
        rc = -EIO;
        goto err_out_iounmap;
    }
    if ((tmp8 & Cfg1_MMIO) == 0)
    {
        printk (KERN_ERR PFX "MMIO not enabled, Cfg1=%02X, aborting\n", tmp8);
        rc = -EIO;
        goto err_out_iounmap;
    }

    /* identify chip attached to board */
    //	tmp = RTL_R8 (ChipVersion);
    tmp = RTL_R32 (TxConfig);
    tmp = ( (tmp&0x7c000000) + ( (tmp&0x00C00000)<<2 ) )>>24;

    for (i = ARRAY_SIZE (rtl_chip_info) - 1; i >= 0; i--)
        if (tmp == rtl_chip_info[i].version)
        {
            tp->chipset = i;
            goto match;
        }

    /* if unknown chip, assume array element #0, original RTL-8139 in this case */
    printk (KERN_DEBUG PFX "PCI device %s: unknown chip version, assuming RTL-8139\n",
            pdev->slot_name);
    printk (KERN_DEBUG PFX "PCI device %s: TxConfig = 0x%lx\n", pdev->slot_name, RTL_R32 (TxConfig));
    tp->chipset = 0;

match:
#ifdef FORCE_CPlus_Mode

    if(tp->chipset >= (ARRAY_SIZE (rtl_chip_info) - 2))
        tp->chipset = ARRAY_SIZE (rtl_chip_info) - 1;
#endif
#ifdef FORCE_C_Mode

    if(tp->chipset > (ARRAY_SIZE (rtl_chip_info) - 2))
        tp->chipset = ARRAY_SIZE (rtl_chip_info) - 2;
#endif

    DPRINTK ("chipset id (%d) == index %d, '%s'\n",
             tmp,
             tp->chipset,
             rtl_chip_info[tp->chipset].name);

    DPRINTK ("EXIT, returning 0\n");
    *ioaddr_out = ioaddr;
    *dev_out = dev;
    return 0;

err_out_iounmap:
    assert (ioaddr > 0);
#ifndef USE_IO_OPS

    iounmap (ioaddr);
err_out_free_res:
    pci_release_regions (pdev);
#endif /* !USE_IO_OPS */
err_out:
    unregister_netdev (dev);
    kfree (dev);
    DPRINTK ("EXIT, returning %d\n", rc);
    return rc;
}


static int __devinit rtl8139_init_one (struct pci_dev *pdev,
                                       const struct pci_device_id *ent)
{
    struct net_device *dev = NULL;
    struct rtl8139_private *tp;
    int i, addr_len, option;
    void *ioaddr = NULL;
    static int board_idx = -1;
    static int printed_version;
    u8 tmp;


    DPRINTK ("ENTER\n");

    assert (pdev != NULL);
    assert (ent != NULL);

    board_idx++;

    if (!printed_version)
    {
        printk (KERN_INFO RTL8139_DRIVER_NAME " loaded\n");
        printed_version = 1;
    }

    i = rtl8139_init_board (pdev, &dev, &ioaddr);
    if (i < 0)
    {
        DPRINTK ("EXIT, returning %d\n", i);
        return i;
    }

    tp = dev->priv;

    assert (ioaddr != NULL);
    assert (dev != NULL);
    assert (tp != NULL);

    init_crc32( dev );

    addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6;
    for (i = 0; i < 3; i++)
        ((u16 *) (dev->dev_addr))[i] =
            le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len));

    /* The Rtl8139-specific entries in the device structure. */
    if( rtl_chip_info[tp->chipset].name == "RTL-8139CP" )
    {
        dev->open = rtl8139CP_open;
        dev->hard_start_xmit = rtl8139CP_start_xmit;
        dev->stop = rtl8139CP_close;
        dev->tx_timeout = rtl8139CP_tx_timeout;
        dev->features |= NETIF_F_IP_CSUM;	/* Can checksum only TCP/UDP over IPv4. */
        printk (KERN_DEBUG "%s: Identified 8139CP chip type '%s'. Support TCP/UDP checksumOffload\n",dev->name,rtl_chip_info[tp->chipset].name);

    }
    else
    {
        dev->open = rtl8139_open;
        dev->hard_start_xmit = rtl8139_start_xmit;
        dev->stop = rtl8139_close;
        dev->tx_timeout = rtl8139_tx_timeout;
        printk (KERN_DEBUG "%s:  Identified 8139CP chip type '%s'\n", dev->name, rtl_chip_info[tp->chipset].name);
    }


    dev->get_stats = rtl8139_get_stats;
    dev->set_multicast_list = rtl8139_set_rx_mode;
    dev->do_ioctl = mii_ioctl;

    dev->watchdog_timeo = TX_TIMEOUT;
    dev->irq = pdev->irq;
    dev->base_addr = (unsigned long) ioaddr;
    /* dev->priv/tp zeroed and aligned in init_etherdev */
    tp = dev->priv;
    /* note: tp->chipset set in rtl8139_init_board */
    tp->drv_flags = board_info[ent->driver_data].hw_flags;
    tp->pci_dev = pdev;
    tp->mmio_addr = ioaddr;
    spin_lock_init (&tp->lock)
    ;


    pdev->driver_data = dev;

    printk (KERN_INFO "%s: %s at 0x%lx, "
            "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
            "IRQ %d\n",
            dev->name,
            board_info[ent->driver_data].name,
            dev->base_addr,
            dev->dev_addr[0], dev->dev_addr[1],
            dev->dev_addr[2], dev->dev_addr[3],
            dev->dev_addr[4], dev->dev_addr[5],
            dev->irq);

    //	dev->tx_queue_len=500;

    /* Find the connected MII xcvrs.
       Doing this in open() would allow detecting external xcvrs later, but
       takes too much time. */
    if (tp->drv_flags & HAS_MII_XCVR)
    {
        int phy, phy_idx = 0;
        for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++)
        {
            int mii_status = mdio_read(dev, phy, 1);

⌨️ 快捷键说明

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