📄 pcnet32.c
字号:
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 + -