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 + -
显示快捷键?