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

📄 hamachi.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
03/14/2000 KDU Further tuning:  	-adjusted boguscnt in hamachi_rx() to depend on interrupt	mitigation parameters chosen.	-Selected a set of interrupt parameters based on some extensive testing.  	These may change with more testing.TO DO:-Consider borrowing from the acenic driver code to check PCI_COMMAND forPCI_COMMAND_INVALIDATE.  Set maximum burst size to cache line size inthat case.-fix the reset procedure.  It doesn't quite work.  *//* A few values that may be tweaked. *//* Size of each temporary Rx buffer, calculated as: * 1518 bytes (ethernet packet) + 2 bytes (to get 8 byte alignment for * the card) + 8 bytes of status info + 8 bytes for the Rx Checksum + * 2 more because we use skb_reserve.   */#define PKT_BUF_SZ		1538/* For now, this is going to be set to the maximum size of an ethernet * packet.  Eventually, we may want to make it a variable that is * related to the MTU */#define MAX_FRAME_SIZE  1518/* The rest of these values should never change. */static void hamachi_timer(unsigned long data);enum capability_flags {CanHaveMII=1, };static struct chip_info {	u16	vendor_id, device_id, device_id_mask, pad;	const char *name;	void (*media_timer)(unsigned long data);	int flags;} chip_tbl[] = {	{0x1318, 0x0911, 0xffff, 0, "Hamachi GNIC-II", hamachi_timer, 0},	{0,},};/* Offsets to the Hamachi registers.  Various sizes. */enum hamachi_offsets {	TxDMACtrl=0x00, TxCmd=0x04, TxStatus=0x06, TxPtr=0x08, TxCurPtr=0x10,	RxDMACtrl=0x20, RxCmd=0x24, RxStatus=0x26, RxPtr=0x28, RxCurPtr=0x30,	PCIClkMeas=0x060, MiscStatus=0x066, ChipRev=0x68, ChipReset=0x06B,	LEDCtrl=0x06C, VirtualJumpers=0x06D, GPIO=0x6E,	TxChecksum=0x074, RxChecksum=0x076,	TxIntrCtrl=0x078, RxIntrCtrl=0x07C,	InterruptEnable=0x080, InterruptClear=0x084, IntrStatus=0x088,	EventStatus=0x08C,	MACCnfg=0x0A0, FrameGap0=0x0A2, FrameGap1=0x0A4,	/* See enum MII_offsets below. */	MACCnfg2=0x0B0, RxDepth=0x0B8, FlowCtrl=0x0BC, MaxFrameSize=0x0CE,	AddrMode=0x0D0, StationAddr=0x0D2,	/* Gigabit AutoNegotiation. */	ANCtrl=0x0E0, ANStatus=0x0E2, ANXchngCtrl=0x0E4, ANAdvertise=0x0E8,	ANLinkPartnerAbility=0x0EA,	EECmdStatus=0x0F0, EEData=0x0F1, EEAddr=0x0F2,	FIFOcfg=0x0F8,};/* Offsets to the MII-mode registers. */enum MII_offsets {	MII_Cmd=0xA6, MII_Addr=0xA8, MII_Wr_Data=0xAA, MII_Rd_Data=0xAC,	MII_Status=0xAE,};/* Bits in the interrupt status/mask registers. */enum intr_status_bits {	IntrRxDone=0x01, IntrRxPCIFault=0x02, IntrRxPCIErr=0x04,	IntrTxDone=0x100, IntrTxPCIFault=0x200, IntrTxPCIErr=0x400,	LinkChange=0x10000, NegotiationChange=0x20000, StatsMax=0x40000, };/* The Hamachi Rx and Tx buffer descriptors. */struct hamachi_desc {	u32 status_n_length;			#if ADDRLEN == 64	u32 pad;	u64 addr;#else	u32 addr;#endif};/* Bits in hamachi_desc.status_n_length */enum desc_status_bits {	DescOwn=0x80000000, DescEndPacket=0x40000000, DescEndRing=0x20000000, 	DescIntr=0x10000000,};#define PRIV_ALIGN	15  			/* Required alignment mask */#define MII_CNT		4struct hamachi_private {	/* Descriptor rings first for alignment.  Tx requires a second descriptor	   for status. */	struct hamachi_desc *rx_ring;	struct hamachi_desc *tx_ring;	struct sk_buff* rx_skbuff[RX_RING_SIZE];	struct sk_buff* tx_skbuff[TX_RING_SIZE];	dma_addr_t tx_ring_dma;	dma_addr_t rx_ring_dma;	struct net_device_stats stats;	struct timer_list timer;		/* Media selection timer. */	/* Frequently used and paired value: keep adjacent for cache effect. */	spinlock_t lock;	int chip_id;	unsigned int cur_rx, dirty_rx;		/* Producer/consumer ring indices */	unsigned int cur_tx, dirty_tx;	unsigned int rx_buf_sz;			/* Based on MTU+slack. */	unsigned int tx_full:1;			/* The Tx queue is full. */	unsigned int full_duplex:1;		/* Full-duplex operation requested. */	unsigned int duplex_lock:1;	unsigned int medialock:1;		/* Do not sense media. */	unsigned int default_port:4;		/* Last dev->if_port value. */	/* MII transceiver section. */	int mii_cnt;								/* MII device addresses. */	u16 advertising;							/* NWay media advertisement */	unsigned char phys[MII_CNT];		/* MII device addresses, only first one used. */	u32 rx_int_var, tx_int_var;	/* interrupt control variables */	u32 option;							/* Hold on to a copy of the options */	struct pci_dev *pci_dev;};MODULE_AUTHOR("Donald Becker <becker@scyld.com>, Eric Kasten <kasten@nscl.msu.edu>, Keith Underwood <keithu@parl.clemson.edu>");MODULE_DESCRIPTION("Packet Engines 'Hamachi' GNIC-II Gigabit Ethernet driver");MODULE_LICENSE("GPL");MODULE_PARM(max_interrupt_work, "i");MODULE_PARM(mtu, "i");MODULE_PARM(debug, "i");MODULE_PARM(min_rx_pkt, "i");MODULE_PARM(max_rx_gap, "i");MODULE_PARM(max_rx_latency, "i");MODULE_PARM(min_tx_pkt, "i");MODULE_PARM(max_tx_gap, "i");MODULE_PARM(max_tx_latency, "i");MODULE_PARM(rx_copybreak, "i");MODULE_PARM(rx_params, "1-" __MODULE_STRING(MAX_UNITS) "i");MODULE_PARM(tx_params, "1-" __MODULE_STRING(MAX_UNITS) "i");MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");MODULE_PARM(force32, "i");MODULE_PARM_DESC(max_interrupt_work, "GNIC-II maximum events handled per interrupt");MODULE_PARM_DESC(mtu, "GNIC-II MTU (all boards)");MODULE_PARM_DESC(debug, "GNIC-II debug level (0-7)");MODULE_PARM_DESC(min_rx_pkt, "GNIC-II minimum Rx packets processed between interrupts");MODULE_PARM_DESC(max_rx_gap, "GNIC-II maximum Rx inter-packet gap in 8.192 microsecond units");MODULE_PARM_DESC(max_rx_latency, "GNIC-II time between Rx interrupts in 8.192 microsecond units");MODULE_PARM_DESC(min_tx_pkt, "GNIC-II minimum Tx packets processed between interrupts");MODULE_PARM_DESC(max_tx_gap, "GNIC-II maximum Tx inter-packet gap in 8.192 microsecond units");MODULE_PARM_DESC(max_tx_latency, "GNIC-II time between Tx interrupts in 8.192 microsecond units");MODULE_PARM_DESC(rx_copybreak, "GNIC-II copy breakpoint for copy-only-tiny-frames");MODULE_PARM_DESC(rx_params, "GNIC-II min_rx_pkt+max_rx_gap+max_rx_latency");MODULE_PARM_DESC(tx_params, "GNIC-II min_tx_pkt+max_tx_gap+max_tx_latency");MODULE_PARM_DESC(options, "GNIC-II Bits 0-3: media type, bits 4-6: as force32, bit 7: half duplex, bit 9 full duplex");MODULE_PARM_DESC(full_duplex, "GNIC-II full duplex setting(s) (1)");MODULE_PARM_DESC(force32, "GNIC-II: Bit 0: 32 bit PCI, bit 1: disable parity, bit 2: 64 bit PCI (all boards)");                                                                        static int read_eeprom(long ioaddr, int location);static int mdio_read(long ioaddr, int phy_id, int location);static void mdio_write(long ioaddr, int phy_id, int location, int value);static int hamachi_open(struct net_device *dev);static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static void hamachi_timer(unsigned long data);static void hamachi_tx_timeout(struct net_device *dev);static void hamachi_init_ring(struct net_device *dev);static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev);static void hamachi_interrupt(int irq, void *dev_instance, struct pt_regs *regs);static inline int hamachi_rx(struct net_device *dev);static inline int hamachi_tx(struct net_device *dev);static void hamachi_error(struct net_device *dev, int intr_status);static int hamachi_close(struct net_device *dev);static struct net_device_stats *hamachi_get_stats(struct net_device *dev);static void set_rx_mode(struct net_device *dev);static int __init hamachi_init_one (struct pci_dev *pdev,				    const struct pci_device_id *ent){	struct hamachi_private *hmp;	int option, i, rx_int_var, tx_int_var, boguscnt;	int chip_id = ent->driver_data;	int irq;	long ioaddr;	static int card_idx;	struct net_device *dev;	void *ring_space;	dma_addr_t ring_dma;	int ret = -ENOMEM;/* 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	if (pci_enable_device(pdev)) {		ret = -EIO;		goto err_out;	}	ioaddr = pci_resource_start(pdev, 0);#ifdef __alpha__				/* Really "64 bit addrs" */	ioaddr |= (pci_resource_start(pdev, 1) << 32);#endif	pci_set_master(pdev);	i = pci_request_regions(pdev, DRV_NAME);	if (i) return i;	irq = pdev->irq;	ioaddr = (long) ioremap(ioaddr, 0x400);	if (!ioaddr)		goto err_out_release;	dev = alloc_etherdev(sizeof(struct hamachi_private));	if (!dev)		goto err_out_iounmap;	SET_MODULE_OWNER(dev);#ifdef TX_CHECKSUM	printk("check that skbcopy in ip_queue_xmit isn't happening\n");	dev->hard_header_len += 8;  /* for cksum tag */#endif	for (i = 0; i < 6; i++)		dev->dev_addr[i] = 1 ? read_eeprom(ioaddr, 4 + i)			: readb(ioaddr + StationAddr + i);#if ! defined(final_version)	if (hamachi_debug > 4)		for (i = 0; i < 0x10; i++)			printk("%2.2x%s",				   read_eeprom(ioaddr, i), i % 16 != 15 ? " " : "\n");#endif	hmp = dev->priv;	spin_lock_init(&hmp->lock);	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);	if (!ring_space)		goto err_out_cleardev;	hmp->tx_ring = (struct hamachi_desc *)ring_space;	hmp->tx_ring_dma = ring_dma;	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);	if (!ring_space)		goto err_out_unmap_tx;	hmp->rx_ring = (struct hamachi_desc *)ring_space;	hmp->rx_ring_dma = ring_dma;	/* Check for options being passed in */	option = card_idx < MAX_UNITS ? options[card_idx] : 0;	if (dev->mem_start)		option = dev->mem_start;	/* If the bus size is misidentified, do the following. */	force32 = force32 ? force32 : 		((option  >= 0) ? ((option & 0x00000070) >> 4) : 0 );	if (force32)		writeb(force32, ioaddr + VirtualJumpers);	/* Hmmm, do we really need to reset the chip???. */	writeb(0x01, ioaddr + ChipReset);	/* After a reset, the clock speed measurement of the PCI bus will not	 * be valid for a moment.  Wait for a little while until it is.  If	 * it takes more than 10ms, forget it.	 */	udelay(10);		i = readb(ioaddr + PCIClkMeas);	for (boguscnt = 0; (!(i & 0x080)) && boguscnt < 1000; boguscnt++){		udelay(10);			i = readb(ioaddr + PCIClkMeas);		}	dev->base_addr = ioaddr;	dev->irq = irq;	pci_set_drvdata(pdev, dev);	hmp->chip_id = chip_id;	hmp->pci_dev = pdev;	/* The lower four bits are the media type. */	if (option > 0) {		hmp->option = option;		if (option & 0x200)			hmp->full_duplex = 1;		else if (option & 0x080)			hmp->full_duplex = 0;		hmp->default_port = option & 15;		if (hmp->default_port)			hmp->medialock = 1;	}	if (card_idx < MAX_UNITS  &&  full_duplex[card_idx] > 0)		hmp->full_duplex = 1;	/* lock the duplex mode if someone specified a value */	if (hmp->full_duplex || (option & 0x080))		hmp->duplex_lock = 1;	/* Set interrupt tuning parameters */	max_rx_latency = max_rx_latency & 0x00ff;	max_rx_gap = max_rx_gap & 0x00ff;	min_rx_pkt = min_rx_pkt & 0x00ff;	max_tx_latency = max_tx_latency & 0x00ff;	max_tx_gap = max_tx_gap & 0x00ff;	min_tx_pkt = min_tx_pkt & 0x00ff;	rx_int_var = card_idx < MAX_UNITS ? rx_params[card_idx] : -1;	tx_int_var = card_idx < MAX_UNITS ? tx_params[card_idx] : -1;	hmp->rx_int_var = rx_int_var >= 0 ? rx_int_var : 		(min_rx_pkt << 16 | max_rx_gap << 8 | max_rx_latency);	hmp->tx_int_var = tx_int_var >= 0 ? tx_int_var : 		(min_tx_pkt << 16 | max_tx_gap << 8 | max_tx_latency);	/* The Hamachi-specific entries in the device structure. */	dev->open = &hamachi_open;	dev->hard_start_xmit = &hamachi_start_xmit;	dev->stop = &hamachi_close;	dev->get_stats = &hamachi_get_stats;	dev->set_multicast_list = &set_rx_mode;	dev->do_ioctl = &netdev_ioctl;	dev->tx_timeout = &hamachi_tx_timeout;	dev->watchdog_timeo = TX_TIMEOUT;	if (mtu)		dev->mtu = mtu;	i = register_netdev(dev);	if (i) {		ret = i;		goto err_out_unmap_rx;	}	printk(KERN_INFO "%s: %s type %x at 0x%lx, ",		   dev->name, chip_tbl[chip_id].name, readl(ioaddr + ChipRev),		   ioaddr);	for (i = 0; i < 5; i++)			printk("%2.2x:", dev->dev_addr[i]);	printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);	i = readb(ioaddr + PCIClkMeas);	printk(KERN_INFO "%s:  %d-bit %d Mhz PCI bus (%d), Virtual Jumpers "		   "%2.2x, LPA %4.4x.\n",		   dev->name, readw(ioaddr + MiscStatus) & 1 ? 64 : 32,		   i ? 2000/(i&0x7f) : 0, i&0x7f, (int)readb(ioaddr + VirtualJumpers),		   readw(ioaddr + ANLinkPartnerAbility));	if (chip_tbl[hmp->chip_id].flags & CanHaveMII) {		int phy, phy_idx = 0;		for (phy = 0; phy < 32 && phy_idx < MII_CNT; phy++) {			int mii_status = mdio_read(ioaddr, phy, 1);			if (mii_status != 0xffff  &&				mii_status != 0x0000) {				hmp->phys[phy_idx++] = phy;				hmp->advertising = mdio_read(ioaddr, phy, 4);				printk(KERN_INFO "%s: MII PHY found at address %d, status "					   "0x%4.4x advertising %4.4x.\n",					   dev->name, phy, mii_status, hmp->advertising);			}		}		hmp->mii_cnt = phy_idx;	}	/* Configure gigabit autonegotiation. */	writew(0x0400, ioaddr + ANXchngCtrl);	/* Enable legacy links. */	writew(0x08e0, ioaddr + ANAdvertise);	/* Set our advertise word. */	writew(0x1000, ioaddr + ANCtrl);			/* Enable negotiation */	card_idx++;	return 0;err_out_unmap_rx:	pci_free_consistent(pdev, RX_TOTAL_SIZE, hmp->rx_ring, 		hmp->rx_ring_dma);err_out_unmap_tx:	pci_free_consistent(pdev, TX_TOTAL_SIZE, hmp->tx_ring, 		hmp->tx_ring_dma);err_out_cleardev:	kfree (dev);err_out_iounmap:	iounmap((char *)ioaddr);err_out_release:	pci_release_regions(pdev);

⌨️ 快捷键说明

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