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

📄 smc9194.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 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 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 ) .    . Hardware multicast code from Peter Cammaert ( pc@denkart.be ) . . Sources: .    o   SMC databook .    o   skeleton.c by Donald Becker ( becker@cesdis.gsfc.nasa.gov ) .    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 ----------------------------------------------------------------------------*/static const char *version =	"smc9194.c:v0.12 03/06/96 by Erik Stahlman (erik@vt.edu)\n";  #ifdef MODULE#include <linux/module.h>#include <linux/version.h>#endif #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/ioport.h>#include <asm/bitops.h>#include <asm/io.h>#include <linux/errno.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include "smc9194.h"/*------------------------------------------------------------------------ .   . Configuration options, for the experienced user to change.  . -------------------------------------------------------------------------*//*  . this is for kernels > 1.2.70 */#define REALLY_NEW_KERNEL #ifndef REALLY_NEW_KERNEL#define free_irq( x, y ) free_irq( x )#define request_irq( x, y, z, u, v ) request_irq( x, y, z, u )#endif/* . Do you want to use this with old kernels.   . WARNING: this is not well tested.  #define SUPPORT_OLD_KERNEL*//* . Do you want to use 32 bit xfers?  This should work on all chips, as . the chipset is designed to accommodate them.   */#define USE_32_BIT 1/*  .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[] =   { 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,	  0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0};/*  . 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 older versions of the kernel cannot support autoprobing */#ifdef SUPPORT_OLD_KERNEL#define NO_AUTOPROBE#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"#ifdef SUPPORT_OLD_KERNELchar kernel_version[] = UTS_RELEASE;#endif /* store this information for the driver.. */ struct smc_local {	/* 	   these are things that the kernel wants me to keep, so users	   can find out semi-useless statistics of how well the card is	   performing  	*/	struct enet_statistics stats;		/* 	   If I have to wait until memory is available to send	   a packet, I will store the skbuff here, until I get the	   desired memory.  Then, I'll send it out and free it.    	*/	struct sk_buff * saved_skb;	/* 	 . This keeps track of how many packets that I have 	 . sent out.  When an TX_EMPTY interrupt comes, I know	 . that all of these have been sent.	*/	int	packets_waiting;};/*----------------------------------------------------------------- . .  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 device *dev);/* . The kernel calls this function when someone wants to use the device, . typically 'ifconfig ethX up'.   */static int smc_open(struct device *dev);/* . This is called by the kernel to send a packet out into the net.  it's . responsible for doing a best-effort send, but if it's simply not possible . to send it, the packet gets dropped. */  static int smc_send_packet(struct sk_buff *skb, struct 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 device *dev);/* . This routine allows the proc file system to query the driver's  . statistics.  */static struct enet_statistics * smc_query_statistics( struct device *dev);/* . Finally, a call to set promiscuous mode ( for TCPDUMP and related  . programs ) and multicast modes.*/#ifdef SUPPORT_OLD_KERNELstatic void smc_set_multicast_list(struct device *dev, int num_addrs,				 void *addrs);#elsestatic void smc_set_multicast_list(struct device *dev);#endif /*--------------------------------------------------------------- .  . Interrupt level calls..  . ----------------------------------------------------------------*//* . Handles the actual interrupt */#ifdef REALLY_NEW_KERNELstatic void smc_interrupt(int irq, void *, struct pt_regs *regs);#elsestatic void smc_interrupt(int irq, struct pt_regs *regs);#endif /* . This is a separate procedure to handle the receipt of a packet, to . leave the interrupt code looking slightly cleaner */ inline static void smc_rcv( struct device *dev );/* . This handles a TX interrupt, which is only called when an error . relating to a packet is sent.  */inline static void smc_tx( struct 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( int ioaddr );/* . this routine initializes the cards hardware, prints out the configuration . to the system log as well as the vanity message, and handles the setup . of a device parameter.  . It will give an error if it can't initialize the card.*/static int smc_initcard( struct device *, int ioaddr ); /* . A rather simple routine to print out a packet for debugging purposes.*/ #if SMC_DEBUG > 2 static void print_packet( byte *, int );#endif  #define tx_done(dev) 1/* this is called to actually send the packet to the chip */ static void smc_hardware_send_packet( struct 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 device *dev );/* this does a soft reset on the device */static void smc_reset( int ioaddr );/* Enable Interrupts, Receive, and Transmit */static void smc_enable( int ioaddr );/* this puts the device in an inactive state */static void smc_shutdown( int ioaddr );#ifndef NO_AUTOPROBE/* This routine will find the IRQ of the driver if one is not . specified in the input to the device.  */static int smc_findirq( int ioaddr );#endif/*  this routine will set the hardware multicast table to the specified   values given it by the higher level routines*/#ifndef SUPPORT_OLD_KERNELstatic void smc_setmulticast( int ioaddr, int count, struct dev_mc_list *  );static int crc32( char *, int );#endif#ifdef SUPPORT_OLD_KERNELextern struct device *init_etherdev(struct device *dev, int sizeof_private, 			unsigned long *mem_startp );#endif /* . Function: smc_reset( int ioaddr ) . Purpose: .  	This sets the SMC91xx chip to its normal state, hopefully from whatever . 	mess that any other DOS driver has put it in.    .  . Maybe I should reset more registers to defaults in here?  SOFTRESET  should . do that for me.   .  . Method: .	1.  send a SOFT RESET  .	2.  wait for it to finish .	3.  enable autorelease mode .	4.  reset the memory management unit .	5.  clear all interrupts .*/  static void smc_reset( int ioaddr ) { 	/* This resets the registers mostly to defaults, but doesn't	   affect EEPROM.  That seems unnecessary */	SMC_SELECT_BANK( 0 );	outw( RCR_SOFTRESET, ioaddr + RCR ); 		/* this should pause enough for the chip to be happy */	SMC_DELAY( );	/* Set the transmit and receive configuration registers to 	   default values */	outw( RCR_CLEAR, ioaddr + RCR );	outw( TCR_CLEAR, ioaddr + TCR );	/* set the control register to automatically	   release successfully transmitted packets, to make the best 	   use out of our limited memory */	SMC_SELECT_BANK( 1 );	outw( inw( ioaddr + CONTROL ) | CTL_AUTO_RELEASE , ioaddr + CONTROL );		/* Reset the MMU */	SMC_SELECT_BANK( 2 );	outw( MC_RESET, ioaddr + MMU_CMD );	/* Note:  It doesn't seem that waiting for the MMU busy is needed here, 	   but this is a place where future chipsets _COULD_ break.  Be wary 	   of issuing another MMU command right after this */	outb( 0, ioaddr + INT_MASK );}/*  . Function: smc_enable . Purpose: let the chip talk to the outside work . Method:  .	1.  Enable the transmitter .	2.  Enable the receiver .	3.  Enable interrupts*/static void smc_enable( int ioaddr ) {	SMC_SELECT_BANK( 0 );	/* see the header file for options in TCR/RCR NORMAL*/	outw( TCR_NORMAL, ioaddr + TCR );	outw( RCR_NORMAL, ioaddr + RCR );	/* now, enable interrupts */	SMC_SELECT_BANK( 2 );	outb( SMC_INTERRUPT_MASK, ioaddr + INT_MASK );} 		/* . Function: smc_shutdown . Purpose:  closes down the SMC91xxx chip. . Method:    .	1. zero the interrupt mask .	2. clear the enable receive flag .	3. clear the enable xmit flags . . TODO:  .   (1) maybe utilize power down mode. .	Why not yet?  Because while the chip will go into power down mode, .	the manual says that it will wake up in response to any I/O requests .	in the register space.   Empirical results do not show this working.*/static void smc_shutdown( int ioaddr ) {	/* no more interrupts for me */	SMC_SELECT_BANK( 2 );	outb( 0, ioaddr + INT_MASK );	/* and tell the card to stay away from that nasty outside world */	SMC_SELECT_BANK( 0 );	outb( RCR_CLEAR, ioaddr + RCR );	outb( TCR_CLEAR, ioaddr + TCR );#if 0 	/* finally, shut the chip down */	SMC_SELECT_BANK( 1 ); 	outw( inw( ioaddr + CONTROL ), CTL_POWERDOWN, ioaddr + CONTROL  );#endif }#ifndef SUPPORT_OLD_KERNEL 

⌨️ 快捷键说明

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