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

📄 smc9194.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
/*------------------------------------------------------------------------ . smc9194.c . This is a driver for SMC's 9000 series of Ethernet cards. . . Copyright (C) 1996 by Erik Stahlman . This software may be used and distributed according to the terms . of the GNU General Public License, incorporated herein by reference. . . "Features" of the SMC chip: .   4608 byte packet memory. ( for the 91C92.  Others have more ) .   EEPROM for configuration .   AUI/TP selection  ( mine has 10Base2/10BaseT select ) . . Arguments: . 	io     = for the base address .	irq    = for the IRQ .	ifport = 0 for autodetect, 1 for TP, 2 for AUI ( or 10base2 ) . . author: . 	Erik Stahlman				( erik@vt.edu ) . contributors: .      Arnaldo Carvalho de Melo <acme@conectiva.com.br> . . Hardware multicast code from Peter Cammaert ( pc@denkart.be ) . . Sources: .    o   SMC databook .    o   skeleton.c by Donald Becker ( becker@scyld.com ) .    o   ( a LOT of advice from Becker as well ) . . History: .	12/07/95  Erik Stahlman  written, got receive/xmit handled . 	01/03/96  Erik Stahlman  worked out some bugs, actually usable!!! :-) .	01/06/96  Erik Stahlman	 cleaned up some, better testing, etc .	01/29/96  Erik Stahlman	 fixed autoirq, added multicast . 	02/01/96  Erik Stahlman	 1. disabled all interrupts in smc_reset .		   		 2. got rid of post-decrementing bug -- UGH. .	02/13/96  Erik Stahlman  Tried to fix autoirq failure.  Added more .				 descriptive error messages. .	02/15/96  Erik Stahlman  Fixed typo that caused detection failure . 	02/23/96  Erik Stahlman	 Modified it to fit into kernel tree .				 Added support to change hardware address .				 Cleared stats on opens .	02/26/96  Erik Stahlman	 Trial support for Kernel 1.2.13 .				 Kludge for automatic IRQ detection .	03/04/96  Erik Stahlman	 Fixed kernel 1.3.70 + .				 Fixed bug reported by Gardner Buchanan in .				   smc_enable, with outw instead of outb .	03/06/96  Erik Stahlman  Added hardware multicast from Peter Cammaert .	04/14/00  Heiko Pruessing (SMA Regelsysteme)  Fixed bug in chip memory .				 allocation .      08/20/00  Arnaldo Melo   fix kfree(skb) in smc_hardware_send_packet .      12/15/00  Christian Jullien fix "Warning: kfree_skb on hard IRQ" .	06/23/01  Russell King   Separate out IO functions for different bus .				 types. .				 Use dev->name instead of CARDNAME for printk .				 Add ethtool support, full duplex support .				 Add LAN91C96 support. ----------------------------------------------------------------------------*/#define DRV_NAME	"smc9194"#define DRV_VERSION	"0.15"static const char version[] =	DRV_NAME ".c:v" DRV_VERSION " 12/15/00 by Erik Stahlman (erik@vt.edu)\n";#include <linux/config.h>#include <linux/module.h>#include <linux/version.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/slab.h>#include <linux/string.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/ethtool.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <asm/bitops.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/uaccess.h>#ifdef CONFIG_ARCH_SA1100#include <asm/hardware.h>#include <asm/arch/assabet.h>#endif	#ifdef CONFIG_ARCH_PXA#include <asm/hardware.h>#endif#include "smc9194.h"/*------------------------------------------------------------------------ . . Configuration options, for the experienced user to change. . -------------------------------------------------------------------------*//* . Do you want to use 32 bit xfers?  This should work on all chips, as . the chipset is designed to accommodate them.*/#ifdef __sh__#undef USE_32_BIT#else#define USE_32_BIT 1#endif#ifdef CONFIG_ISA/* .the SMC9194 can be at any of the following port addresses.  To change, .for a slightly different card, you can add it to the array.  Keep in .mind that the array must end in zero.*/static unsigned int smc_portlist[] __initdata = { 	0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,	0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0};#endif/* . Wait time for memory to be free.  This probably shouldn't be . tuned that much, as waiting for this means nothing else happens . in the system*/#define MEMORY_WAIT_TIME 16/* . DEBUGGING LEVELS . . 0 for normal operation . 1 for slightly more details . >2 for various levels of increasingly useless information .    2 for interrupt tracking, status flags .    3 for packet dumps, etc.*/#define SMC_DEBUG 0#if (SMC_DEBUG > 2 )#define PRINTK3(x) printk x#else#define PRINTK3(x)#endif#if SMC_DEBUG > 1#define PRINTK2(x) printk x#else#define PRINTK2(x)#endif#ifdef SMC_DEBUG#define PRINTK(x) printk x#else#define PRINTK(x)#endif/*------------------------------------------------------------------------ . . The internal workings of the driver.  If you are changing anything . here with the SMC stuff, you should have the datasheet and known . what you are doing. . -------------------------------------------------------------------------*/#define CARDNAME "SMC9194"static const char *chip_ids[15] = { 	NULL,	NULL,	NULL,	"SMC91C90/91C92",	/* 3 */	"SMC91C94/91C96",	/* 4 */	"SMC91C95",		/* 5 */	NULL,	"SMC91C100",		/* 7 */	"SMC91C100FD",		/* 8 */	NULL,	NULL,	NULL, 	NULL,	NULL,	NULL};static const char * interfaces[2] = {	"TP",	"AUI"};/*----------------------------------------------------------------- . .  The driver can be entered at any of the following entry points. . .------------------------------------------------------------------  *//* . This is called by  register_netdev().  It is responsible for . checking the portlist for the SMC9000 series chipset.  If it finds . one, then it will initialize the device, find the hardware information, . and sets up the appropriate device parameters. . NOTE: Interrupts are *OFF* when this procedure is called. . . NB:This shouldn't be static since it is referred to externally.*/int smc_init(struct net_device *dev);/* . The kernel calls this function when someone wants to use the device, . typically 'ifconfig ethX up'.*/static int smc_open(struct net_device *dev);/* . This handles the ethtool interface*/static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);/* . Our watchdog timed out. Called by the networking layer*/static void smc_timeout(struct net_device *dev);/* . This is called by the kernel in response to 'ifconfig ethX down'.  It . is responsible for cleaning up everything that the open routine . does, and maybe putting the card into a powerdown state.*/static int smc_close(struct net_device *dev);/* . This routine allows the proc file system to query the driver's . statistics.*/static struct net_device_stats * smc_query_statistics(struct net_device *dev);/* . Finally, a call to set promiscuous mode (for TCPDUMP and related . programs) and multicast modes.*/static void smc_set_multicast_list(struct net_device *dev);/* . CRC compute */static int crc32(char * s, int length);/*--------------------------------------------------------------- . . Interrupt level calls.. . ----------------------------------------------------------------*//* . Handles the actual interrupt*/static void smc_interrupt(int irq, void *, struct pt_regs *regs);/* . This is a separate procedure to handle the receipt of a packet, to . leave the interrupt code looking slightly cleaner*/static inline void smc_rcv(struct net_device *dev);/* . This handles a TX interrupt, which is only called when an error . relating to a packet is sent.*/static inline void smc_tx(struct net_device * dev);/* ------------------------------------------------------------ . . Internal routines . ------------------------------------------------------------*//* . Test if a given location contains a chip, trying to cause as . little damage as possible if it's not a SMC chip.*/static int smc_probe(struct net_device *dev, int ioaddr);/* this is called to actually send the packet to the chip */static void smc_hardware_send_packet(struct net_device * dev);/* Since I am not sure if I will have enough room in the chip's ram . to store the packet, I call this routine, which either sends it . now, or generates an interrupt when the card is ready for the . packet */static int smc_wait_to_send_packet(struct sk_buff * skb, struct net_device *dev);/* this does a soft reset on the device */static void smc_reset(struct net_device *dev);/* Enable Interrupts, Receive, and Transmit */static void smc_enable(struct net_device *dev);/* this puts the device in an inactive state */static void smc_shutdown(struct net_device *dev);/* This routine will find the IRQ of the driver if one is not . specified in the input to the device.  */static int smc_findirq(struct net_device *dev);#if defined(CONFIG_ISA)/* * These functions allow us to handle IO addressing as we wish - this * ethernet controller can be connected to a variety of busses.  Some * busses do not support 16 bit or 32 bit transfers.  --rmk */static inline u8 smc_inb(u_int base, u_int reg){	return inb(base + reg);}static inline u16 smc_inw(u_int base, u_int reg){	return inw(base + reg);}static inline void smc_ins(u_int base, u_int reg, u8 *data, u_int len){	u_int port = base + reg;#ifdef USE_32_BIT	/* QUESTION:  Like in the TX routine, do I want	   to send the DWORDs or the bytes first, or some	   mixture.  A mixture might improve already slow PIO	   performance  */	PRINTK3((" Reading %d dwords (and %d bytes) \n",		len >> 2, len & 3));	insl(port, data, len >> 2);	/* read the left over bytes */	insb(port, data + (len & ~3), len & 3);#else	PRINTK3((" Reading %d words and %d byte(s) \n",		len >> 1, len & 1));	insw(port, data, len >> 1);	if (len & 1) {		data += len & ~1;		*data = inb(port);	}#endif}static inline void smc_outb(u8 val, u_int base, u_int reg){	outb(val, base + reg);}static inline void smc_outw(u16 val, u_int base, u_int reg){	outw(val, base + reg);}static inline void smc_outl(u32 val, u_int base, u_int reg){	u_int port = base + reg;#ifdef USE_32_BIT	outl(val, port);#else	outw(val, port);	outw(val >> 16, port);#endif}static inline void smc_outs(u_int base, u_int reg, u8 *data, u_int len){	u_int port = base + reg;#ifdef USE_32_BIT	if (len & 2) {		outsl(port, data, len >> 2);		outw(*((word *)(data + (len & ~3))), port);	}	else		outsl(port, data, len >> 2);#else	outsw(port, data, len >> 1);#endif}/*------------------------------------------------------------------------- .  I define some macros to make it easier to do somewhat common . or slightly complicated, repeated tasks.  --------------------------------------------------------------------------*//* select a register bank, 0 to 3  */#define SMC_SELECT_BANK(x)				\	{						\		smc_outw(x, ioaddr, BANK_SELECT);	\	} /* define a small delay for the reset */#define SMC_DELAY()					\	{						\		smc_inw(ioaddr, RCR);			\		smc_inw(ioaddr, RCR);			\		smc_inw(ioaddr, RCR);			\	}/* this enables an interrupt in the interrupt mask register */#define SMC_ENABLE_INT(x)				\	{						\		byte mask;				\		mask = smc_inb(ioaddr, INT_MASK);	\		mask |= (x);				\		smc_outb(mask, ioaddr, INT_MASK);	\	}/* this sets the absolutel interrupt mask */#define SMC_SET_INT(x)					\	{						\		smc_outw((x), INT_MASK);		\	}#elif defined(CONFIG_ASSABET_NEPONSET)#undef SMC_IO_EXTENT#define SMC_IO_EXTENT	(16 << 2)/* * These functions allow us to handle IO addressing as we wish - this * ethernet controller can be connected to a variety of busses.  Some * busses do not support 16 bit or 32 bit transfers.  --rmk */static inline u8 smc_inb(u_int base, u_int reg){	u_int port = base + reg * 4;	return readb(port);}static inline u16 smc_inw(u_int base, u_int reg){	u_int port = base + reg * 4;	return readb(port) | readb(port + 4) << 8;}static inline void smc_ins(u_int base, u_int reg, u8 *data, u_int len){	u_int port = base + reg * 4;	insb(port, data, len);}static inline void smc_outb(u8 val, u_int base, u_int reg){	u_int port = base + reg * 4;	writeb(val, port);}static inline void smc_outw(u16 val, u_int base, u_int reg){	u_int port = base + reg * 4;	writeb(val, port);	writeb(val >> 8, port + 4);}static inline void smc_outl(u32 val, u_int base, u_int reg){	u_int port = base + reg * 4;	writeb(val, port);	writeb(val >> 8, port + 4);	writeb(val >> 16, port + 8);	writeb(val >> 24, port + 12);}static inline void smc_outs(u_int base, u_int reg, u8 *data, u_int len){	u_int port = base + reg * 4;	outsb(port, data, len & ~1);}/*------------------------------------------------------------------------- .  I define some macros to make it easier to do somewhat common . or slightly complicated, repeated tasks.  --------------------------------------------------------------------------*//* select a register bank, 0 to 3  */#define SMC_SELECT_BANK(x)				\	{						\		smc_outb(x, ioaddr, BANK_SELECT);	\	} /* define a small delay for the reset */#define SMC_DELAY()					\	{						\		smc_inb(ioaddr, RCR);			\		smc_inb(ioaddr, RCR);			\		smc_inb(ioaddr, RCR);			\	}/* this enables an interrupt in the interrupt mask register */#define SMC_ENABLE_INT(x)				\	{						\		byte mask;				\		mask = smc_inb(ioaddr, INT_MASK);	\		mask |= (x);				\		smc_outb(mask, ioaddr, INT_MASK);	\	}/* this sets the absolutel interrupt mask */#define SMC_SET_INT(x)					\	{						\		smc_outb((x), ioaddr, INT_MASK);	\	}#elif	defined(CONFIG_SA1100_GRAPHICSCLIENT) || \	defined(CONFIG_SA1100_PFS168) || \	defined(CONFIG_SA1100_FLEXANET) || \	defined(CONFIG_SA1100_GRAPHICSMASTER) || \	defined(CONFIG_ARCH_LUBBOCK) || \	defined(CONFIG_ARCH_PXA_IDP)/* * We can only do 16-bit reads and writes in the static memory space. * Byte reads must read 16 bits and return the correct byte. * Byte writes must do a read/modify/write. *//* The first two address lines aren't connected... */#undef SMC_IO_EXTENT#define SMC_IO_EXTENT	(16 << 2)static inline u8 smc_inb(u_int base, u_int reg){	u_int port = base + (reg & ~1) * 4;	u_int res = readw(port);	if (reg & 1)		res >>= 8;	return res;}static inline u16 smc_inw(u_int base, u_int reg){	u_int port = base + reg * 4;	return readw(port);}static inline void smc_ins(u_int base, u_int reg, u8 *data, u_int len){	u_int port = base + reg * 4;

⌨️ 快捷键说明

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