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

📄 8139too.c

📁 我实现的一个基于零拷贝技术高速捕包的原型代码
💻 C
📖 第 1 页 / 共 5 页
字号:
            if (mii_status != 0xffff  &&  mii_status != 0x0000)
            {
                tp->phys[phy_idx++] = phy;
                tp->advertising = mdio_read(dev, phy, 4);
                printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x "
                       "advertising %4.4x.\n",
                       dev->name, phy, mii_status, tp->advertising);
            }
        }
        if (phy_idx == 0)
        {
            printk(KERN_INFO "%s: No MII transceivers found!  Assuming SYM "
                   "transceiver.\n",
                   dev->name);
            tp->phys[0] = 32;
        }
    }
    else
        tp->phys[0] = 32;

    /* Put the chip into low-power mode. */
    RTL_W8_F (Cfg9346, Cfg9346_Unlock);

    tmp = RTL_R8 (Config1) & Config1Clear;
    tmp |= (tp->chipset == CH_8139B) ? 3 : 1; /* Enable PM/VPD */
    RTL_W8_F (Config1, tmp);

    RTL_W8_F (HltClk, 'H');	/* 'R' would leave the clock running. */

    /* The lower four bits are the media type. */
    option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx];
    tp->AutoNegoAbility = option&0xF;

    if (option > 0)
    {
        tp->full_duplex = (option & 0x210) ? 1 : 0;
        tp->default_port = option & 0xFF;
        if (tp->default_port)
            tp->medialock = 1;
    }
    if (board_idx < MAX_UNITS  &&  full_duplex[board_idx] > 0)
        tp->full_duplex = full_duplex[board_idx];
    if (tp->full_duplex)
    {
        printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
        /* Changing the MII-advertised media because might prevent
           re-connection. */
        tp->duplex_lock = 1;
    }

    if (tp->default_port)
    {
        printk(KERN_INFO "%s: Forcing %dMbs %s-duplex operation.\n", dev->name,
               (option & 0x0C ? 100 : 10),
               (option & 0x0A ? "full" : "half"));
        mdio_write(dev, tp->phys[0], 0,
                   ((option & 0x20) ? 0x2000 : 0) | 	/* 100mbps? */
                   ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */
    }


#ifdef RTL8139_PROC_DEBUG
    //-----------------------------------------------------------------------------
    // Add proc file system
    //-----------------------------------------------------------------------------
    rtl8139_init_proc(dev);
#endif	//#ifdef RTL8139_PROC_DEBUG


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


static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
{
    struct net_device *dev = pdev->driver_data;
    struct rtl8139_private *np;


    DPRINTK ("ENTER\n");

    assert (dev != NULL);

    np = (struct rtl8139_private *) (dev->priv);
    assert (np != NULL);


#ifndef USE_IO_OPS

    iounmap (np->mmio_addr);
    pci_release_regions (pdev);
#endif /* !USE_IO_OPS */

#ifdef RTL8139_PROC_DEBUG
    //-----------------------------------------------------------------------------
    // Remove proc file system
    //-----------------------------------------------------------------------------
    rtl8139_remove_proc(dev);
#endif	//#ifdef RTL8139_PROC_DEBUG


    unregister_netdev (dev);

    pdev->driver_data = NULL;

    pci_disable_device (pdev);

    DPRINTK ("EXIT\n");
}


/* Serial EEPROM section. */

/*  EEPROM_Ctrl bits. */
#define EE_SHIFT_CLK	0x04	/* EEPROM shift clock. */
#define EE_CS			0x08	/* EEPROM chip select. */
#define EE_DATA_WRITE	0x02	/* EEPROM chip data in. */
#define EE_WRITE_0		0x00
#define EE_WRITE_1		0x02
#define EE_DATA_READ	0x01	/* EEPROM chip data out. */
#define EE_ENB			(0x80 | EE_CS)

/* Delay between EEPROM clock transitions.
   No extra delay is needed with 33Mhz PCI, but 66Mhz may change this.
 */

#define eeprom_delay()	readl(ee_addr)

/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD	(5)
#define EE_READ_CMD		(6)
#define EE_ERASE_CMD	(7)

static int __devinit read_eeprom (void *ioaddr, int location, int addr_len)
{
    int i;
    unsigned retval = 0;
    void *ee_addr = ioaddr + Cfg9346;
    int read_cmd = location | (EE_READ_CMD << addr_len);

    DPRINTK ("ENTER\n");

    writeb (EE_ENB & ~EE_CS, ee_addr);
    writeb (EE_ENB, ee_addr);
    eeprom_delay ();

    /* Shift the read command bits out. */
    for (i = 4 + addr_len; i >= 0; i--)
    {
        int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
        writeb (EE_ENB | dataval, ee_addr);
        eeprom_delay ();
        writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
        eeprom_delay ();
    }
    writeb (EE_ENB, ee_addr);
    eeprom_delay ();

    for (i = 16; i > 0; i--)
    {
        writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);
        eeprom_delay ();
        retval =
            (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 :
                             0);
        writeb (EE_ENB, ee_addr);
        eeprom_delay ();
    }

    /* Terminate the EEPROM access. */
    writeb (~EE_CS, ee_addr);
    eeprom_delay ();

    DPRINTK ("EXIT - returning %d\n", retval);
    return retval;
}

/* MII serial management: mostly bogus for now. */
/* Read and write the MII management registers using software-generated
   serial MDIO protocol.
   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. */
#define MDIO_DIR		0x80
#define MDIO_DATA_OUT	0x04
#define MDIO_DATA_IN	0x02
#define MDIO_CLK		0x01
#define MDIO_WRITE0 (MDIO_DIR)
#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT)

#define mdio_delay(mdio_addr)	readb(mdio_addr)


static char mii_2_8139_map[8] = {
                                    BasicModeCtrl,
                                    BasicModeStatus,
                                    0,
                                    0,
                                    NWayAdvert,
                                    NWayLPAR,
                                    NWayExpansion,
                                    0
                                };


/* Syncronize the MII management interface by shifting 32 one bits out. */
static void mdio_sync (void *mdio_addr)
{
    int i;

    DPRINTK ("ENTER\n");

    for (i = 32; i >= 0; i--)
    {
        writeb (MDIO_WRITE1, mdio_addr);
        mdio_delay (mdio_addr);
        writeb (MDIO_WRITE1 | MDIO_CLK, mdio_addr);
        mdio_delay (mdio_addr);
    }

    DPRINTK ("EXIT\n");
}


static int mdio_read (struct net_device *dev, int phy_id, int location)
{
    struct rtl8139_private *tp = dev->priv;
    void *mdio_addr = tp->mmio_addr + Config4;
    int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
    int retval = 0;
    int i;

    DPRINTK ("ENTER\n");

    if (phy_id > 31)
    {	/* Really a 8139.  Use internal registers. */
        DPRINTK ("EXIT after directly using 8139 internal regs\n");
        return location < 8 && mii_2_8139_map[location] ?
               readw (tp->mmio_addr + mii_2_8139_map[location]) : 0;
    }
    mdio_sync (mdio_addr);
    /* Shift the read command bits out. */
    for (i = 15; i >= 0; i--)
    {
        int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;

        writeb (MDIO_DIR | dataval, mdio_addr);
        mdio_delay (mdio_addr);
        writeb (MDIO_DIR | dataval | MDIO_CLK, mdio_addr);
        mdio_delay (mdio_addr);
    }

    /* Read the two transition, 16 data, and wire-idle bits. */
    for (i = 19; i > 0; i--)
    {
        writeb (0, mdio_addr);
        mdio_delay (mdio_addr);
        retval = (retval << 1) | ((readb (mdio_addr) & MDIO_DATA_IN) ? 1 : 0);
        writeb (MDIO_CLK, mdio_addr);
        mdio_delay (mdio_addr);
    }

    DPRINTK ("EXIT, returning %d\n", (retval >> 1) & 0xffff);
    return (retval >> 1) & 0xffff;
}


static void mdio_write (struct net_device *dev, int phy_id, int location,
                        int value)
{
    struct rtl8139_private *tp = dev->priv;
    void *mdio_addr = tp->mmio_addr + Config4;
    int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
    int i;

    DPRINTK ("ENTER\n");

    if (phy_id > 31)
    {	/* Really a 8139.  Use internal registers. */
        void *ioaddr = tp->mmio_addr;
        if (location == 0)
        {
            RTL_W8_F (Cfg9346, Cfg9346_Unlock);
            //////////////////////////////////////////////////////////////
            switch(tp->AutoNegoAbility)
            {
            case 1:
                RTL_W16 (NWayAdvert, AutoNegoAbility10half);
                break;
            case 2:
                RTL_W16 (NWayAdvert, AutoNegoAbility10full);
                break;
            case 4:
                RTL_W16 (NWayAdvert, AutoNegoAbility100half);
                break;
            case 8:
                RTL_W16 (NWayAdvert, AutoNegoAbility100full);
                break;
            default:
                break;
            }
            RTL_W16_F (BasicModeCtrl, AutoNegotiationEnable|AutoNegotiationRestart);
            //////////////////////////////////////////////////////////////
            //			RTL_W16_F (BasicModeCtrl, value);
            RTL_W8_F (Cfg9346, Cfg9346_Lock);
        }
        else if (location < 8 && mii_2_8139_map[location])
            RTL_W16_F (mii_2_8139_map[location], value);

        return;
    }
    mdio_sync (mdio_addr);

    /* Shift the command bits out. */
    for (i = 31; i >= 0; i--)
    {
        int dataval =
            (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
        writeb (dataval, mdio_addr);
        mdio_delay (mdio_addr);
        writeb (dataval | MDIO_CLK, mdio_addr);
        mdio_delay (mdio_addr);
    }
    /* Clear out extra bits. */
    for (i = 2; i > 0; i--)
    {
        writeb (0, mdio_addr);
        mdio_delay (mdio_addr);
        writeb (MDIO_CLK, mdio_addr);
        mdio_delay (mdio_addr);
    }
    return;
}

static int rtl8139_open (struct net_device *dev)
{
    struct rtl8139_private *tp = dev->priv;
    int retval;
#ifdef RTL8139_DEBUG

    void *ioaddr = tp->mmio_addr;
#endif

    DPRINTK ("ENTER\n");

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

    tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN,
                                       &tp->tx_bufs_dma);
    tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
                                       &tp->rx_ring_dma);

    //初始化接收环,利用全局导出符号完成
#ifdef ZERO_COPY

    tp->rx_q = &(base_addr->rx_q);
    tp->free_q = &(base_addr->free_q);
    tp->phy_addr_table = base_addr->phy_addr_table;
#endif

    if (tp->tx_bufs == NULL || tp->rx_ring == NULL)
    {
        free_irq(dev->irq, dev);

        if (tp->tx_bufs)
            pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN,
                                tp->tx_bufs, tp->tx_bufs_dma);
        if (tp->rx_ring)
            pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
                                tp->rx_ring, tp->rx_ring_dma);

        DPRINTK ("EXIT, returning -ENOMEM\n");
        return -ENOMEM;

    }

    tp->full_duplex = tp->duplex_lock;
    tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
    tp->twistie = 1;

    rtl8139_init_ring (dev);
    rtl8139_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 rtl8139_hw_start (struct net_device *dev)
{
    struct rtl8139_private *tp = dev->priv;
    void *ioaddr = tp->mmio_addr;
    u32 i;
    u8 tmp;

    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);
    /* 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_F (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear) |
              CmdRxEnb | CmdTxEnb);

    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));

⌨️ 快捷键说明

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