starfire.c
来自「linux 内核源代码」· C语言 代码 · 共 2,081 行 · 第 1/5 页
C
2,081 行
MiiSoftReset=0x8000, MIILoopback=0x4000, TxFlowEnable=0x0800, RxFlowEnable=0x0400, PadEnable=0x04, FullDuplex=0x02, HugeFrame=0x01,};/* Bits in the TxDescCtrl register. */enum tx_ctrl_bits { TxDescSpaceUnlim=0x00, TxDescSpace32=0x10, TxDescSpace64=0x20, TxDescSpace128=0x30, TxDescSpace256=0x40, TxDescType0=0x00, TxDescType1=0x01, TxDescType2=0x02, TxDescType3=0x03, TxDescType4=0x04, TxNoDMACompletion=0x08, TxDescQAddr64bit=0x80, TxDescQAddr32bit=0, TxHiPriFIFOThreshShift=24, TxPadLenShift=16, TxDMABurstSizeShift=8,};/* Bits in the RxDescQCtrl register. */enum rx_ctrl_bits { RxBufferLenShift=16, RxMinDescrThreshShift=0, RxPrefetchMode=0x8000, RxVariableQ=0x2000, Rx2048QEntries=0x4000, Rx256QEntries=0, RxDescAddr64bit=0x1000, RxDescAddr32bit=0, RxDescQAddr64bit=0x0100, RxDescQAddr32bit=0, RxDescSpace4=0x000, RxDescSpace8=0x100, RxDescSpace16=0x200, RxDescSpace32=0x300, RxDescSpace64=0x400, RxDescSpace128=0x500, RxConsumerWrEn=0x80,};/* Bits in the RxDMACtrl register. */enum rx_dmactrl_bits { RxReportBadFrames=0x80000000, RxDMAShortFrames=0x40000000, RxDMABadFrames=0x20000000, RxDMACrcErrorFrames=0x10000000, RxDMAControlFrame=0x08000000, RxDMAPauseFrame=0x04000000, RxChecksumIgnore=0, RxChecksumRejectTCPUDP=0x02000000, RxChecksumRejectTCPOnly=0x01000000, RxCompletionQ2Enable=0x800000, RxDMAQ2Disable=0, RxDMAQ2FPOnly=0x100000, RxDMAQ2SmallPkt=0x200000, RxDMAQ2HighPrio=0x300000, RxDMAQ2NonIP=0x400000, RxUseBackupQueue=0x080000, RxDMACRC=0x040000, RxEarlyIntThreshShift=12, RxHighPrioThreshShift=8, RxBurstSizeShift=0,};/* Bits in the RxCompletionAddr register */enum rx_compl_bits { RxComplQAddr64bit=0x80, RxComplQAddr32bit=0, RxComplProducerWrEn=0x40, RxComplType0=0x00, RxComplType1=0x10, RxComplType2=0x20, RxComplType3=0x30, RxComplThreshShift=0,};/* Bits in the TxCompletionAddr register */enum tx_compl_bits { TxComplQAddr64bit=0x80, TxComplQAddr32bit=0, TxComplProducerWrEn=0x40, TxComplIntrStatus=0x20, CommonQueueMode=0x10, TxComplThreshShift=0,};/* Bits in the GenCtrl register */enum gen_ctrl_bits { RxEnable=0x05, TxEnable=0x0a, RxGFPEnable=0x10, TxGFPEnable=0x20,};/* Bits in the IntrTimerCtrl register */enum intr_ctrl_bits { Timer10X=0x800, EnableIntrMasking=0x60, SmallFrameBypass=0x100, SmallFrame64=0, SmallFrame128=0x200, SmallFrame256=0x400, SmallFrame512=0x600, IntrLatencyMask=0x1f,};/* The Rx and Tx buffer descriptors. */struct starfire_rx_desc { netdrv_addr_t rxaddr;};enum rx_desc_bits { RxDescValid=1, RxDescEndRing=2,};/* Completion queue entry. */struct short_rx_done_desc { __le32 status; /* Low 16 bits is length. */};struct basic_rx_done_desc { __le32 status; /* Low 16 bits is length. */ __le16 vlanid; __le16 status2;};struct csum_rx_done_desc { __le32 status; /* Low 16 bits is length. */ __le16 csum; /* Partial checksum */ __le16 status2;};struct full_rx_done_desc { __le32 status; /* Low 16 bits is length. */ __le16 status3; __le16 status2; __le16 vlanid; __le16 csum; /* partial checksum */ __le32 timestamp;};/* XXX: this is ugly and I'm not sure it's worth the trouble -Ion */#ifdef VLAN_SUPPORTtypedef struct full_rx_done_desc rx_done_desc;#define RxComplType RxComplType3#else /* not VLAN_SUPPORT */typedef struct csum_rx_done_desc rx_done_desc;#define RxComplType RxComplType2#endif /* not VLAN_SUPPORT */enum rx_done_bits { RxOK=0x20000000, RxFIFOErr=0x10000000, RxBufQ2=0x08000000,};/* Type 1 Tx descriptor. */struct starfire_tx_desc_1 { __le32 status; /* Upper bits are status, lower 16 length. */ __le32 addr;};/* Type 2 Tx descriptor. */struct starfire_tx_desc_2 { __le32 status; /* Upper bits are status, lower 16 length. */ __le32 reserved; __le64 addr;};#ifdef ADDR_64BITStypedef struct starfire_tx_desc_2 starfire_tx_desc;#define TX_DESC_TYPE TxDescType2#else /* not ADDR_64BITS */typedef struct starfire_tx_desc_1 starfire_tx_desc;#define TX_DESC_TYPE TxDescType1#endif /* not ADDR_64BITS */#define TX_DESC_SPACING TxDescSpaceUnlimenum tx_desc_bits { TxDescID=0xB0000000, TxCRCEn=0x01000000, TxDescIntr=0x08000000, TxRingWrap=0x04000000, TxCalTCP=0x02000000,};struct tx_done_desc { __le32 status; /* timestamp, index. */#if 0 __le32 intrstatus; /* interrupt status */#endif};struct rx_ring_info { struct sk_buff *skb; dma_addr_t mapping;};struct tx_ring_info { struct sk_buff *skb; dma_addr_t mapping; unsigned int used_slots;};#define PHY_CNT 2struct netdev_private { /* Descriptor rings first for alignment. */ struct starfire_rx_desc *rx_ring; starfire_tx_desc *tx_ring; dma_addr_t rx_ring_dma; dma_addr_t tx_ring_dma; /* The addresses of rx/tx-in-place skbuffs. */ struct rx_ring_info rx_info[RX_RING_SIZE]; struct tx_ring_info tx_info[TX_RING_SIZE]; /* Pointers to completion queues (full pages). */ rx_done_desc *rx_done_q; dma_addr_t rx_done_q_dma; unsigned int rx_done; struct tx_done_desc *tx_done_q; dma_addr_t tx_done_q_dma; unsigned int tx_done; struct napi_struct napi; struct net_device *dev; struct net_device_stats stats; struct pci_dev *pci_dev;#ifdef VLAN_SUPPORT struct vlan_group *vlgrp;#endif void *queue_mem; dma_addr_t queue_mem_dma; size_t queue_mem_size; /* Frequently used values: keep some adjacent for cache effect. */ spinlock_t lock; unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ unsigned int cur_tx, dirty_tx, reap_tx; unsigned int rx_buf_sz; /* Based on MTU+slack. */ /* These values keep track of the transceiver/media in use. */ int speed100; /* Set if speed == 100MBit. */ u32 tx_mode; u32 intr_timer_ctrl; u8 tx_threshold; /* MII transceiver section. */ struct mii_if_info mii_if; /* MII lib hooks/info */ int phy_cnt; /* MII device addresses. */ unsigned char phys[PHY_CNT]; /* MII device addresses. */ void __iomem *base;};static int mdio_read(struct net_device *dev, int phy_id, int location);static void mdio_write(struct net_device *dev, int phy_id, int location, int value);static int netdev_open(struct net_device *dev);static void check_duplex(struct net_device *dev);static void tx_timeout(struct net_device *dev);static void init_ring(struct net_device *dev);static int start_tx(struct sk_buff *skb, struct net_device *dev);static irqreturn_t intr_handler(int irq, void *dev_instance);static void netdev_error(struct net_device *dev, int intr_status);static int __netdev_rx(struct net_device *dev, int *quota);static void refill_rx_ring(struct net_device *dev);static void netdev_error(struct net_device *dev, int intr_status);static void set_rx_mode(struct net_device *dev);static struct net_device_stats *get_stats(struct net_device *dev);static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static int netdev_close(struct net_device *dev);static void netdev_media_change(struct net_device *dev);static const struct ethtool_ops ethtool_ops;#ifdef VLAN_SUPPORTstatic void netdev_vlan_rx_register(struct net_device *dev, struct vlan_group *grp){ struct netdev_private *np = netdev_priv(dev); spin_lock(&np->lock); if (debug > 2) printk("%s: Setting vlgrp to %p\n", dev->name, grp); np->vlgrp = grp; set_rx_mode(dev); spin_unlock(&np->lock);}static void netdev_vlan_rx_add_vid(struct net_device *dev, unsigned short vid){ struct netdev_private *np = netdev_priv(dev); spin_lock(&np->lock); if (debug > 1) printk("%s: Adding vlanid %d to vlan filter\n", dev->name, vid); set_rx_mode(dev); spin_unlock(&np->lock);}static void netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid){ struct netdev_private *np = netdev_priv(dev); spin_lock(&np->lock); if (debug > 1) printk("%s: removing vlanid %d from vlan filter\n", dev->name, vid); vlan_group_set_device(np->vlgrp, vid, NULL); set_rx_mode(dev); spin_unlock(&np->lock);}#endif /* VLAN_SUPPORT */static int __devinit starfire_init_one(struct pci_dev *pdev, const struct pci_device_id *ent){ struct netdev_private *np; int i, irq, option, chip_idx = ent->driver_data; struct net_device *dev; static int card_idx = -1; long ioaddr; void __iomem *base; int drv_flags, io_size; int boguscnt; DECLARE_MAC_BUF(mac);/* when built into the kernel, we only print version if device is found */#ifndef MODULE static int printed_version; if (!printed_version++) printk(version);#endif card_idx++; if (pci_enable_device (pdev)) return -EIO; ioaddr = pci_resource_start(pdev, 0); io_size = pci_resource_len(pdev, 0); if (!ioaddr || ((pci_resource_flags(pdev, 0) & IORESOURCE_MEM) == 0)) { printk(KERN_ERR DRV_NAME " %d: no PCI MEM resources, aborting\n", card_idx); return -ENODEV; } dev = alloc_etherdev(sizeof(*np)); if (!dev) { printk(KERN_ERR DRV_NAME " %d: cannot alloc etherdev, aborting\n", card_idx); return -ENOMEM; } SET_NETDEV_DEV(dev, &pdev->dev); irq = pdev->irq; if (pci_request_regions (pdev, DRV_NAME)) { printk(KERN_ERR DRV_NAME " %d: cannot reserve PCI resources, aborting\n", card_idx); goto err_out_free_netdev; } base = ioremap(ioaddr, io_size); if (!base) { printk(KERN_ERR DRV_NAME " %d: cannot remap %#x @ %#lx, aborting\n", card_idx, io_size, ioaddr); goto err_out_free_res; } pci_set_master(pdev); /* enable MWI -- it vastly improves Rx performance on sparc64 */ pci_try_set_mwi(pdev);#ifdef ZEROCOPY /* Starfire can do TCP/UDP checksumming */ if (enable_hw_cksum) dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;#endif /* ZEROCOPY */#ifdef VLAN_SUPPORT dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; dev->vlan_rx_register = netdev_vlan_rx_register; dev->vlan_rx_add_vid = netdev_vlan_rx_add_vid; dev->vlan_rx_kill_vid = netdev_vlan_rx_kill_vid;#endif /* VLAN_RX_KILL_VID */#ifdef ADDR_64BITS dev->features |= NETIF_F_HIGHDMA;#endif /* ADDR_64BITS */ /* Serial EEPROM reads are hidden by the hardware. */ for (i = 0; i < 6; i++) dev->dev_addr[i] = readb(base + EEPROMCtrl + 20 - i);#if ! defined(final_version) /* Dump the EEPROM contents during development. */ if (debug > 4) for (i = 0; i < 0x20; i++) printk("%2.2x%s", (unsigned int)readb(base + EEPROMCtrl + i), i % 16 != 15 ? " " : "\n");#endif /* Issue soft reset */ writel(MiiSoftReset, base + TxMode); udelay(1000); writel(0, base + TxMode); /* Reset the chip to erase previous misconfiguration. */ writel(1, base + PCIDeviceConfig); boguscnt = 1000; while (--boguscnt > 0) { udelay(10); if ((readl(base + PCIDeviceConfig) & 1) == 0) break; } if (boguscnt == 0) printk("%s: chipset reset never completed!\n", dev->name); /* wait a little longer */ udelay(1000); dev->base_addr = (unsigned long)base; dev->irq = irq; np = netdev_priv(dev); np->dev = dev; np->base = base; spin_lock_init(&np->lock); pci_set_drvdata(pdev, dev); np->pci_dev = pdev; np->mii_if.dev = dev; np->mii_if.mdio_read = mdio_read; np->mii_if.mdio_write = mdio_write; np->mii_if.phy_id_mask = 0x1f; np->mii_if.reg_num_mask = 0x1f; drv_flags = netdrv_tbl[chip_idx].drv_flags; option = card_idx < MAX_UNITS ? options[card_idx] : 0; if (dev->mem_start) option = dev->mem_start; /* The lower four bits are the media type. */ if (option & 0x200) np->mii_if.full_duplex = 1; if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0) np->mii_if.full_duplex = 1; if (np->mii_if.full_duplex) np->mii_if.force_media = 1; else np->mii_if.force_media = 0; np->speed100 = 1; /* timer resolution is 128 * 0.8us */ np->intr_timer_ctrl = (((intr_latency * 10) / 1024) & IntrLatencyMask) | Timer10X | EnableIntrMasking; if (small_frames > 0) { np->intr_timer_ctrl |= SmallFrameBypass; switch (small_frames) { case 1 ... 64: np->intr_timer_ctrl |= SmallFrame64; break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?