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

📄 sunlance.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: sunlance.c,v 1.85 1999/03/21 05:22:05 davem Exp $ * lance.c: Linux/Sparc/Lance driver * *	Written 1995, 1996 by Miguel de Icaza * Sources: *	The Linux  depca driver *	The Linux  lance driver. *	The Linux  skeleton driver. *	The NetBSD Sparc/Lance driver. *	Theo de Raadt (deraadt@openbsd.org) *	NCR92C990 Lan Controller manual * * 1.4: *	Added support to run with a ledma on the Sun4m * * 1.5: *	Added multiple card detection. * *	 4/17/96: Burst sizes and tpe selection on sun4m by Eddie C. Dost *		  (ecd@skynet.be) * *	 5/15/96: auto carrier detection on sun4m by Eddie C. Dost *		  (ecd@skynet.be) * *	 5/17/96: lebuffer on scsi/ether cards now work David S. Miller *		  (davem@caip.rutgers.edu) * *	 5/29/96: override option 'tpe-link-test?', if it is 'false', as *		  this disables auto carrier detection on sun4m. Eddie C. Dost *		  (ecd@skynet.be) * * 1.7: *	 6/26/96: Bug fix for multiple ledmas, miguel. * * 1.8: *		  Stole multicast code from depca.c, fixed lance_tx. * * 1.9: *	 8/21/96: Fixed the multicast code (Pedro Roque) * *	 8/28/96: Send fake packet in lance_open() if auto_select is true, *		  so we can detect the carrier loss condition in time. *		  Eddie C. Dost (ecd@skynet.be) * *	 9/15/96: Align rx_buf so that eth_copy_and_sum() won't cause an *		  MNA trap during chksum_partial_copy(). (ecd@skynet.be) * *	11/17/96: Handle LE_C0_MERR in lance_interrupt(). (ecd@skynet.be) * *	12/22/96: Don't loop forever in lance_rx() on incomplete packets. *		  This was the sun4c killer. Shit, stupid bug. *		  (ecd@skynet.be) * * 1.10: *	 1/26/97: Modularize driver. (ecd@skynet.be) * * 1.11: *	12/27/97: Added sun4d support. (jj@sunsite.mff.cuni.cz) * * 1.12: * 	 11/3/99: Fixed SMP race in lance_start_xmit found by davem. * 	          Anton Blanchard (anton@progsoc.uts.edu.au) */#undef DEBUG_DRIVERstatic char *version =	"sunlance.c:v1.12 11/Mar/99 Miguel de Icaza (miguel@nuclecu.unam.mx)\n";static char *lancestr = "LANCE";static char *lancedma = "LANCE DMA";#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/interrupt.h>#include <linux/ptrace.h>#include <linux/ioport.h>#include <linux/in.h>#include <linux/malloc.h>#include <linux/string.h>#include <linux/delay.h>#include <linux/init.h>#include <asm/system.h>#include <asm/bitops.h>#include <asm/io.h>#include <asm/dma.h>#include <asm/pgtable.h>#include <linux/errno.h>#include <asm/byteorder.h>	/* Used by the checksum routines *//* Used for the temporal inet entries and routing */#include <linux/socket.h>#include <linux/route.h>#include <asm/idprom.h>#include <asm/sbus.h>#include <asm/openprom.h>#include <asm/oplib.h>#include <asm/auxio.h>		/* For tpe-link-test? setting */#include <asm/irq.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <asm/idprom.h>#include <asm/machines.h>/* Define: 2^4 Tx buffers and 2^4 Rx buffers */#ifndef LANCE_LOG_TX_BUFFERS#define LANCE_LOG_TX_BUFFERS 4#define LANCE_LOG_RX_BUFFERS 4#endif#define CRC_POLYNOMIAL_BE 0x04c11db7UL  /* Ethernet CRC, big endian */#define CRC_POLYNOMIAL_LE 0xedb88320UL  /* Ethernet CRC, little endian */#define LE_CSR0 0#define LE_CSR1 1#define LE_CSR2 2#define LE_CSR3 3#define LE_MO_PROM      0x8000  /* Enable promiscuous mode */#define	LE_C0_ERR	0x8000	/* Error: set if BAB, SQE, MISS or ME is set */#define	LE_C0_BABL	0x4000	/* BAB:  Babble: tx timeout. */#define	LE_C0_CERR	0x2000	/* SQE:  Signal quality error */#define	LE_C0_MISS	0x1000	/* MISS: Missed a packet */#define	LE_C0_MERR	0x0800	/* ME:   Memory error */#define	LE_C0_RINT	0x0400	/* Received interrupt */#define	LE_C0_TINT	0x0200	/* Transmitter Interrupt */#define	LE_C0_IDON	0x0100	/* IFIN: Init finished. */#define	LE_C0_INTR	0x0080	/* Interrupt or error */#define	LE_C0_INEA	0x0040	/* Interrupt enable */#define	LE_C0_RXON	0x0020	/* Receiver on */#define	LE_C0_TXON	0x0010	/* Transmitter on */#define	LE_C0_TDMD	0x0008	/* Transmitter demand */#define	LE_C0_STOP	0x0004	/* Stop the card */#define	LE_C0_STRT	0x0002	/* Start the card */#define	LE_C0_INIT	0x0001	/* Init the card */#define	LE_C3_BSWP	0x4     /* SWAP */#define	LE_C3_ACON	0x2	/* ALE Control */#define	LE_C3_BCON	0x1	/* Byte control *//* Receive message descriptor 1 */#define LE_R1_OWN       0x80    /* Who owns the entry */#define LE_R1_ERR       0x40    /* Error: if FRA, OFL, CRC or BUF is set */#define LE_R1_FRA       0x20    /* FRA: Frame error */#define LE_R1_OFL       0x10    /* OFL: Frame overflow */#define LE_R1_CRC       0x08    /* CRC error */#define LE_R1_BUF       0x04    /* BUF: Buffer error */#define LE_R1_SOP       0x02    /* Start of packet */#define LE_R1_EOP       0x01    /* End of packet */#define LE_R1_POK       0x03    /* Packet is complete: SOP + EOP */#define LE_T1_OWN       0x80    /* Lance owns the packet */#define LE_T1_ERR       0x40    /* Error summary */#define LE_T1_EMORE     0x10    /* Error: more than one retry needed */#define LE_T1_EONE      0x08    /* Error: one retry needed */#define LE_T1_EDEF      0x04    /* Error: deferred */#define LE_T1_SOP       0x02    /* Start of packet */#define LE_T1_EOP       0x01    /* End of packet */#define LE_T1_POK	0x03	/* Packet is complete: SOP + EOP */#define LE_T3_BUF       0x8000  /* Buffer error */#define LE_T3_UFL       0x4000  /* Error underflow */#define LE_T3_LCOL      0x1000  /* Error late collision */#define LE_T3_CLOS      0x0800  /* Error carrier loss */#define LE_T3_RTY       0x0400  /* Error retry */#define LE_T3_TDR       0x03ff  /* Time Domain Reflectometry counter */#define TX_RING_SIZE			(1 << (LANCE_LOG_TX_BUFFERS))#define TX_RING_MOD_MASK		(TX_RING_SIZE - 1)#define TX_RING_LEN_BITS		((LANCE_LOG_TX_BUFFERS) << 29)#define RX_RING_SIZE			(1 << (LANCE_LOG_RX_BUFFERS))#define RX_RING_MOD_MASK		(RX_RING_SIZE - 1)#define RX_RING_LEN_BITS		((LANCE_LOG_RX_BUFFERS) << 29)#define PKT_BUF_SZ		1544#define RX_BUFF_SIZE            PKT_BUF_SZ#define TX_BUFF_SIZE            PKT_BUF_SZstruct lance_rx_desc {	unsigned short rmd0;        /* low address of packet */	unsigned char  rmd1_bits;   /* descriptor bits */	unsigned char  rmd1_hadr;   /* high address of packet */	short    length;    	    /* This length is 2s complement (negative)!				     * Buffer length				     */	unsigned short mblength;    /* This is the actual number of bytes received */};struct lance_tx_desc {	unsigned short tmd0;        /* low address of packet */	unsigned char  tmd1_bits;   /* descriptor bits */	unsigned char  tmd1_hadr;   /* high address of packet */	short length;          	    /* Length is 2s complement (negative)! */	unsigned short misc;};		/* The LANCE initialization block, described in databook. *//* On the Sparc, this block should be on a DMA region     */struct lance_init_block {	unsigned short mode;		/* Pre-set mode (reg. 15) */	unsigned char phys_addr[6];     /* Physical ethernet address */	unsigned filter[2];		/* Multicast filter. */	/* Receive and transmit ring base, along with extra bits. */	unsigned short rx_ptr;		/* receive descriptor addr */	unsigned short rx_len;		/* receive len and high addr */	unsigned short tx_ptr;		/* transmit descriptor addr */	unsigned short tx_len;		/* transmit len and high addr */    	/* The Tx and Rx ring entries must aligned on 8-byte boundaries. */	struct lance_rx_desc brx_ring[RX_RING_SIZE];	struct lance_tx_desc btx_ring[TX_RING_SIZE];    	char   tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];	char   pad[2];			/* align rx_buf for copy_and_sum(). */	char   rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];};#define libdesc_offset(rt, elem) \((__u32)(((unsigned long)(&(((struct lance_init_block *)0)->rt[elem])))))#define libbuff_offset(rt, elem) \((__u32)(((unsigned long)(&(((struct lance_init_block *)0)->rt[elem][0])))))struct lance_private {	char *name;	volatile struct lance_regs *ll;	volatile struct lance_init_block *init_block;	__u32 init_block_dvma;    	int rx_new, tx_new;	int rx_old, tx_old;    	struct net_device_stats	stats;	struct Linux_SBus_DMA *ledma; /* If set this points to ledma    */				      /* and arch = sun4m		*/	int tpe;		      /* cable-selection is TPE		*/	int auto_select;	      /* cable-selection by carrier	*/	int burst_sizes;	      /* ledma SBus burst sizes		*/	unsigned short busmaster_regval;	unsigned short pio_buffer;	struct device		 *dev;		  /* Backpointer	*/	struct lance_private	 *next_module;	struct linux_sbus        *sbus;	struct timer_list         multicast_timer;};#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\			lp->tx_old+TX_RING_MOD_MASK-lp->tx_new:\			lp->tx_old - lp->tx_new-1)/* On the sparc, the lance control ports are memory mapped */struct lance_regs {	unsigned short rdp;			/* register data port */	unsigned short rap;			/* register address port */};int sparc_lance_debug = 2;/* The Lance uses 24 bit addresses *//* On the Sun4c the DVMA will provide the remaining bytes for us *//* On the Sun4m we have to instruct the ledma to provide them    *//* Even worse, on scsi/ether SBUS cards, the init block and the * transmit/receive buffers are addresses as offsets from absolute * zero on the lebuffer PIO area. -davem */#define LANCE_ADDR(x) ((long)(x) & ~0xff000000)#ifdef MODULEstatic struct lance_private *root_lance_dev = NULL;#endif/* Load the CSR registers */static void load_csrs (struct lance_private *lp){	volatile struct lance_regs *ll = lp->ll;	__u32 ib_dvma = lp->init_block_dvma;	int leptr;	/* This is right now because when we are using a PIO buffered	 * init block, init_block_dvma is set to zero. -DaveM	 */	leptr = LANCE_ADDR (ib_dvma);	ll->rap = LE_CSR1;	ll->rdp = (leptr & 0xFFFF);	ll->rap = LE_CSR2;	ll->rdp = leptr >> 16;	ll->rap = LE_CSR3;	ll->rdp = lp->busmaster_regval;	/* Point back to csr0 */	ll->rap = LE_CSR0;}#define ZERO 0/* Setup the Lance Rx and Tx rings *//* Sets dev->tbusy */static void lance_init_ring (struct device *dev){	struct lance_private *lp = (struct lance_private *) dev->priv;	volatile struct lance_init_block *ib = lp->init_block;	__u32 ib_dvma = lp->init_block_dvma;	__u32 aib; /* for LANCE_ADDR computations */	int leptr;	int i;    	/* This is right now because when we are using a PIO buffered	 * init block, init_block_dvma is set to zero. -DaveM	 */	aib = ib_dvma;	/* Lock out other processes while setting up hardware */	dev->tbusy = 1;	lp->rx_new = lp->tx_new = 0;	lp->rx_old = lp->tx_old = 0;	/* Copy the ethernet address to the lance init block	 * Note that on the sparc you need to swap the ethernet address.	 * Note also we want the CPU ptr of the init_block here.	 */	ib->phys_addr [0] = dev->dev_addr [1];	ib->phys_addr [1] = dev->dev_addr [0];	ib->phys_addr [2] = dev->dev_addr [3];	ib->phys_addr [3] = dev->dev_addr [2];	ib->phys_addr [4] = dev->dev_addr [5];	ib->phys_addr [5] = dev->dev_addr [4];	if (ZERO)		printk ("TX rings:\n");    	/* Setup the Tx ring entries */	for (i = 0; i <= TX_RING_SIZE; i++) {		leptr = LANCE_ADDR(aib + libbuff_offset(tx_buf, i));		ib->btx_ring [i].tmd0      = leptr;		ib->btx_ring [i].tmd1_hadr = leptr >> 16;		ib->btx_ring [i].tmd1_bits = 0;		ib->btx_ring [i].length    = 0xf000; /* The ones required by tmd2 */		ib->btx_ring [i].misc      = 0;		if (i < 3)			if (ZERO) printk ("%d: 0x%8.8x\n", i, leptr);	}	/* Setup the Rx ring entries */	if (ZERO)		printk ("RX rings:\n");	for (i = 0; i < RX_RING_SIZE; i++) {		leptr = LANCE_ADDR(aib + libbuff_offset(rx_buf, i));		ib->brx_ring [i].rmd0      = leptr;		ib->brx_ring [i].rmd1_hadr = leptr >> 16;		ib->brx_ring [i].rmd1_bits = LE_R1_OWN;		ib->brx_ring [i].length    = -RX_BUFF_SIZE | 0xf000;		ib->brx_ring [i].mblength  = 0;		if (i < 3 && ZERO)			printk ("%d: 0x%8.8x\n", i, leptr);	}	/* Setup the initialization block */    	/* Setup rx descriptor pointer */	leptr = LANCE_ADDR(aib + libdesc_offset(brx_ring, 0));	ib->rx_len = (LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16);	ib->rx_ptr = leptr;	if (ZERO)		printk ("RX ptr: %8.8x\n", leptr);    	/* Setup tx descriptor pointer */	leptr = LANCE_ADDR(aib + libdesc_offset(btx_ring, 0));	ib->tx_len = (LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16);	ib->tx_ptr = leptr;	if (ZERO)		printk ("TX ptr: %8.8x\n", leptr);}static int init_restart_lance (struct lance_private *lp){	volatile struct lance_regs *ll = lp->ll;	int i;	if (lp->ledma) {		struct sparc_dma_registers *dregs = lp->ledma->regs;		unsigned long creg;		if (!(dregs->cond_reg & DMA_HNDL_ERROR)) {			/* E-Cache draining */			while (dregs->cond_reg & DMA_FIFO_ISDRAIN)				barrier();		}		creg = dregs->cond_reg;		if (lp->burst_sizes & DMA_BURST32)			creg |= DMA_E_BURST8;		else			creg &= ~DMA_E_BURST8;		creg |= (DMA_DSBL_RD_DRN | DMA_DSBL_WR_INV | DMA_FIFO_INV);		if (lp->tpe)			creg |= DMA_EN_ENETAUI;		else

⌨️ 快捷键说明

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