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

📄 pcnet32.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
📖 第 1 页 / 共 5 页
字号:
    outw (val, addr+PCNET32_WIO_RDP);}static u16 pcnet32_wio_read_bcr (unsigned long addr, int index){    outw (index, addr+PCNET32_WIO_RAP);    return inw (addr+PCNET32_WIO_BDP);}static void pcnet32_wio_write_bcr (unsigned long addr, int index, u16 val){    outw (index, addr+PCNET32_WIO_RAP);    outw (val, addr+PCNET32_WIO_BDP);}static u16 pcnet32_wio_read_rap (unsigned long addr){    return inw (addr+PCNET32_WIO_RAP);}static void pcnet32_wio_write_rap (unsigned long addr, u16 val){    outw (val, addr+PCNET32_WIO_RAP);}static void pcnet32_wio_reset (unsigned long addr){    inw (addr+PCNET32_WIO_RESET);}static int pcnet32_wio_check (unsigned long addr){    outw (88, addr+PCNET32_WIO_RAP);    return (inw (addr+PCNET32_WIO_RAP) == 88);}static struct pcnet32_access pcnet32_wio = {    .read_csr	= pcnet32_wio_read_csr,    .write_csr	= pcnet32_wio_write_csr,    .read_bcr	= pcnet32_wio_read_bcr,    .write_bcr	= pcnet32_wio_write_bcr,    .read_rap	= pcnet32_wio_read_rap,    .write_rap	= pcnet32_wio_write_rap,    .reset	= pcnet32_wio_reset};static u16 pcnet32_dwio_read_csr (unsigned long addr, int index){    outl (index, addr+PCNET32_DWIO_RAP);    return (inl (addr+PCNET32_DWIO_RDP) & 0xffff);}static void pcnet32_dwio_write_csr (unsigned long addr, int index, u16 val){    outl (index, addr+PCNET32_DWIO_RAP);    outl (val, addr+PCNET32_DWIO_RDP);}static u16 pcnet32_dwio_read_bcr (unsigned long addr, int index){    outl (index, addr+PCNET32_DWIO_RAP);    return (inl (addr+PCNET32_DWIO_BDP) & 0xffff);}static void pcnet32_dwio_write_bcr (unsigned long addr, int index, u16 val){    outl (index, addr+PCNET32_DWIO_RAP);    outl (val, addr+PCNET32_DWIO_BDP);}static u16 pcnet32_dwio_read_rap (unsigned long addr){    return (inl (addr+PCNET32_DWIO_RAP) & 0xffff);}static void pcnet32_dwio_write_rap (unsigned long addr, u16 val){    outl (val, addr+PCNET32_DWIO_RAP);}static void pcnet32_dwio_reset (unsigned long addr){    inl (addr+PCNET32_DWIO_RESET);}static int pcnet32_dwio_check (unsigned long addr){    outl (88, addr+PCNET32_DWIO_RAP);    return ((inl (addr+PCNET32_DWIO_RAP) & 0xffff) == 88);}static struct pcnet32_access pcnet32_dwio = {    .read_csr	= pcnet32_dwio_read_csr,    .write_csr	= pcnet32_dwio_write_csr,    .read_bcr	= pcnet32_dwio_read_bcr,    .write_bcr	= pcnet32_dwio_write_bcr,    .read_rap	= pcnet32_dwio_read_rap,    .write_rap	= pcnet32_dwio_write_rap,    .reset	= pcnet32_dwio_reset};#ifdef CONFIG_NET_POLL_CONTROLLERstatic void pcnet32_poll_controller(struct net_device *dev){    disable_irq(dev->irq);    pcnet32_interrupt(0, dev, NULL);    enable_irq(dev->irq);}#endifstatic int pcnet32_get_settings(struct net_device *dev, struct ethtool_cmd *cmd){    struct pcnet32_private *lp = dev->priv;    unsigned long flags;    int r = -EOPNOTSUPP;    if (lp->mii) {	spin_lock_irqsave(&lp->lock, flags);	mii_ethtool_gset(&lp->mii_if, cmd);	spin_unlock_irqrestore(&lp->lock, flags);	r = 0;    }    return r;}static int pcnet32_set_settings(struct net_device *dev, struct ethtool_cmd *cmd){    struct pcnet32_private *lp = dev->priv;    unsigned long flags;    int r = -EOPNOTSUPP;    if (lp->mii) {	spin_lock_irqsave(&lp->lock, flags);	r = mii_ethtool_sset(&lp->mii_if, cmd);	spin_unlock_irqrestore(&lp->lock, flags);    }    return r;}static void pcnet32_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info){    struct pcnet32_private *lp = dev->priv;    strcpy (info->driver, DRV_NAME);    strcpy (info->version, DRV_VERSION);    if (lp->pci_dev)	strcpy (info->bus_info, pci_name(lp->pci_dev));    else	sprintf(info->bus_info, "VLB 0x%lx", dev->base_addr);}static u32 pcnet32_get_link(struct net_device *dev){    struct pcnet32_private *lp = dev->priv;    unsigned long flags;    int r;    spin_lock_irqsave(&lp->lock, flags);    if (lp->mii) {	r = mii_link_ok(&lp->mii_if);    } else {	ulong ioaddr = dev->base_addr;	/* card base I/O address */	r = (lp->a.read_bcr(ioaddr, 4) != 0xc0);    }    spin_unlock_irqrestore(&lp->lock, flags);    return r;}static u32 pcnet32_get_msglevel(struct net_device *dev){    struct pcnet32_private *lp = dev->priv;    return lp->msg_enable;}static void pcnet32_set_msglevel(struct net_device *dev, u32 value){    struct pcnet32_private *lp = dev->priv;    lp->msg_enable = value;}static int pcnet32_nway_reset(struct net_device *dev){    struct pcnet32_private *lp = dev->priv;    unsigned long flags;    int r = -EOPNOTSUPP;    if (lp->mii) {	spin_lock_irqsave(&lp->lock, flags);	r = mii_nway_restart(&lp->mii_if);	spin_unlock_irqrestore(&lp->lock, flags);    }    return r;}static void pcnet32_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering){    struct pcnet32_private *lp = dev->priv;    ering->tx_max_pending = TX_MAX_RING_SIZE - 1;    ering->tx_pending = lp->tx_ring_size - 1;    ering->rx_max_pending = RX_MAX_RING_SIZE - 1;    ering->rx_pending = lp->rx_ring_size - 1;}static int pcnet32_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering){    struct pcnet32_private *lp = dev->priv;    unsigned long flags;    int i;    if (ering->rx_mini_pending || ering->rx_jumbo_pending)	return -EINVAL;    if (netif_running(dev))	pcnet32_close(dev);    spin_lock_irqsave(&lp->lock, flags);    pcnet32_free_ring(dev);    lp->tx_ring_size = min(ering->tx_pending, (unsigned int) TX_MAX_RING_SIZE);    lp->rx_ring_size = min(ering->rx_pending, (unsigned int) RX_MAX_RING_SIZE);    /* set the minimum ring size to 4, to allow the loopback test to work     * unchanged.     */    for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) {	if (lp->tx_ring_size <= (1 << i))	    break;    }    lp->tx_ring_size = (1 << i);    lp->tx_mod_mask = lp->tx_ring_size - 1;    lp->tx_len_bits = (i << 12);    for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) {	if (lp->rx_ring_size <= (1 << i))	    break;    }    lp->rx_ring_size = (1 << i);    lp->rx_mod_mask = lp->rx_ring_size - 1;    lp->rx_len_bits = (i << 4);    if (pcnet32_alloc_ring(dev, dev->name)) {	pcnet32_free_ring(dev);	spin_unlock_irqrestore(&lp->lock, flags);	return -ENOMEM;    }    spin_unlock_irqrestore(&lp->lock, flags);    if (pcnet32_debug & NETIF_MSG_DRV)	printk(KERN_INFO PFX "%s: Ring Param Settings: RX: %d, TX: %d\n",	       dev->name, lp->rx_ring_size, lp->tx_ring_size);    if (netif_running(dev))	pcnet32_open(dev);    return 0;}static void pcnet32_get_strings(struct net_device *dev, u32 stringset, u8 *data){    memcpy(data, pcnet32_gstrings_test, sizeof(pcnet32_gstrings_test));}static int pcnet32_self_test_count(struct net_device *dev){    return PCNET32_TEST_LEN;}static void pcnet32_ethtool_test(struct net_device *dev,	struct ethtool_test *test, u64 *data){    struct pcnet32_private *lp = dev->priv;    int rc;    if (test->flags == ETH_TEST_FL_OFFLINE) {	rc = pcnet32_loopback_test(dev, data);	if (rc) {	    if (netif_msg_hw(lp))		printk(KERN_DEBUG "%s: Loopback test failed.\n", dev->name);	    test->flags |= ETH_TEST_FL_FAILED;	} else if (netif_msg_hw(lp))	    printk(KERN_DEBUG "%s: Loopback test passed.\n", dev->name);    } else if (netif_msg_hw(lp))	printk(KERN_DEBUG "%s: No tests to run (specify 'Offline' on ethtool).",	    dev->name);} /* end pcnet32_ethtool_test */static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1){    struct pcnet32_private *lp = dev->priv;    struct pcnet32_access *a = &lp->a;	/* access to registers */    ulong ioaddr = dev->base_addr;	/* card base I/O address */    struct sk_buff *skb;		/* sk buff */    int x, i;				/* counters */    int numbuffs = 4;			/* number of TX/RX buffers and descs */    u16 status = 0x8300;		/* TX ring status */    u16 teststatus;			/* test of ring status */    int rc;				/* return code */    int size;				/* size of packets */    unsigned char *packet;		/* source packet data */    static int data_len = 60;		/* length of source packets */    unsigned long flags;    unsigned long ticks;    *data1 = 1;			/* status of test, default to fail */    rc = 1;			/* default to fail */    if (netif_running(dev))	pcnet32_close(dev);    spin_lock_irqsave(&lp->lock, flags);    /* Reset the PCNET32 */    lp->a.reset (ioaddr);    /* switch pcnet32 to 32bit mode */    lp->a.write_bcr (ioaddr, 20, 2);    lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);    lp->init_block.filter[0] = 0;    lp->init_block.filter[1] = 0;    /* purge & init rings but don't actually restart */    pcnet32_restart(dev, 0x0000);    lp->a.write_csr(ioaddr, 0, 0x0004);	/* Set STOP bit */    /* Initialize Transmit buffers. */    size = data_len + 15;    for (x=0; x<numbuffs; x++) {	if (!(skb = dev_alloc_skb(size))) {	    if (netif_msg_hw(lp))		printk(KERN_DEBUG "%s: Cannot allocate skb at line: %d!\n",		    dev->name, __LINE__);	    goto clean_up;	} else {	    packet = skb->data;	    skb_put(skb, size);		/* create space for data */	    lp->tx_skbuff[x] = skb;	    lp->tx_ring[x].length = le16_to_cpu(-skb->len);	    lp->tx_ring[x].misc = 0;            /* put DA and SA into the skb */	    for (i=0; i<6; i++)		*packet++ = dev->dev_addr[i];	    for (i=0; i<6; i++)		*packet++ = dev->dev_addr[i];	    /* type */	    *packet++ = 0x08;	    *packet++ = 0x06;	    /* packet number */	    *packet++ = x;	    /* fill packet with data */	    for (i=0; i<data_len; i++)		*packet++ = i;	    lp->tx_dma_addr[x] = pci_map_single(lp->pci_dev, skb->data,		    skb->len, PCI_DMA_TODEVICE);	    lp->tx_ring[x].base = (u32)le32_to_cpu(lp->tx_dma_addr[x]);	    wmb(); /* Make sure owner changes after all others are visible */	    lp->tx_ring[x].status = le16_to_cpu(status);	}    }    x = a->read_bcr(ioaddr, 32);	/* set internal loopback in BSR32 */    x = x | 0x0002;    a->write_bcr(ioaddr, 32, x);    lp->a.write_csr (ioaddr, 15, 0x0044);	/* set int loopback in CSR15 */    teststatus = le16_to_cpu(0x8000);    lp->a.write_csr(ioaddr, 0, 0x0002);		/* Set STRT bit */    /* Check status of descriptors */    for (x=0; x<numbuffs; x++) {	ticks = 0;	rmb();	while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) {	    spin_unlock_irqrestore(&lp->lock, flags);	    mdelay(1);	    spin_lock_irqsave(&lp->lock, flags);	    rmb();	    ticks++;	}	if (ticks == 200) {	    if (netif_msg_hw(lp))		printk("%s: Desc %d failed to reset!\n",dev->name,x);	    break;	}    }    lp->a.write_csr(ioaddr, 0, 0x0004);		/* Set STOP bit */    wmb();    if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) {	printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name);	for (x=0; x<numbuffs; x++) {	    printk(KERN_DEBUG "%s: Packet %d:\n", dev->name, x);	    skb = lp->rx_skbuff[x];	    for (i=0; i<size; i++) {		printk("%02x ", *(skb->data+i));	    }	    printk("\n");	}    }    x = 0;    rc = 0;    while (x<numbuffs && !rc) {	skb = lp->rx_skbuff[x];	packet = lp->tx_skbuff[x]->data;	for (i=0; i<size; i++) {	    if (*(skb->data+i) != packet[i]) {		if (netif_msg_hw(lp))		    printk(KERN_DEBUG "%s: Error in compare! %2x - %02x %02x\n",			    dev->name, i, *(skb->data+i), packet[i]);

⌨️ 快捷键说明

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