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

📄 sbni.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Driver for Granch SBNI-12 leased line network adapters. *  * Copyright 1997 - 1999, Granch ltd. * Written 1999 by Yaroslav Polyakov (xenon@granch.ru). * * This software may be used and distributed according to the terms * of the GNU Public License, incorporated herein by reference. *  *   // Whole developers team: *   //   Yaroslav Polyakov (xenon@granch.ru) *   //      - main developer of this version *   //   Alexey Zverev (zverev@granch.ru) *   //      - previous SBNI driver for linux *   //   Alexey Chirkov (chirkov@granch.ru) *   //      - all the hardware work and consulting *   //   Max Khon (max@iclub.nsu.ru) *   //      - first SBNI driver for linux *   // -------------------------------------------- *   // also I thank:  *   //   Max Krasnyansky (max@uznet.net) *   //      - for bug hunting and many ideas *   //   Alan Cox (Alan.Cox@linux.org) *   //	     - for consulting in some hardcore questions *   //   Donald Becker (becker@cesdis.gsfc.nasa.gov) *   //      - for pretty nice skeleton  *  *   More info and useful utilities to work w/ SBNI you can find at  *   http://www.granch.ru. * *  3.0.0 = Initial Revision, Yaroslav Polyakov (24 Feb 1999) *        - added pre-calculation for CRC, fixed bug with "len-2" frames,  *        - removed outbound fragmentation (MTU=1000), written CRC-calculation  *        - on asm, added work with hard_headers and now we have our own cache  *        - for them, optionally supported word-interchange on some chipsets, *        - something else I cant remember ;)  *  *  3.0.1 = just fixed some bugs (14 apr 1999). * 	  - fixed statistical tx bug  *        - fixed wrong creation dates (1998 -> 1999) in driver source code ;) * 	  - fixed source address bug. *        - fixed permanent nirvana bug  *  *  3.1.0 = (Katyusha) (26 apr 1999) *        - Added balancing feature *  *  3.1.1 = (Medea) (5 aug 1999) *        - Fixed mac.raw bug *	  - Thanks to tolix@olviko.ru and  *        - to Barnaul Brewery, producers of my favorite beer "Medea". * * */#undef GOODBUS16#define CRCASM#define KATYUSHA#include <linux/version.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/ptrace.h>#include <linux/fcntl.h>#include <linux/ioport.h>#include <linux/interrupt.h>#include <linux/malloc.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/spinlock.h>#include <asm/io.h>#include <asm/types.h>#include <asm/byteorder.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/timer.h>#include <linux/config.h>	/* for CONFIG_INET. do we need this?*/#include <net/arp.h>#include <asm/uaccess.h>#include <linux/init.h>#include "sbni.h"static const char *version = "sbni.c: ver. 3.1.1 Medea 5 Aug 1999 Yaroslav Polyakov (xenon@granch.ru)\n";int sbni_probe(struct net_device *dev);static int  sbni_probe1(struct net_device *dev, int ioaddr);static int  sbni_open(struct net_device *dev);static int  sbni_start_xmit(struct sk_buff *skb, struct net_device *dev);static void sbni_interrupt(int irq, void *dev_id, struct pt_regs *regs);static int  sbni_close(struct net_device *dev);static void sbni_drop_tx_queue(struct net_device *dev);static struct net_device_stats *sbni_get_stats(struct net_device *dev);static void card_start(struct net_device *dev);static inline unsigned short sbni_recv(struct net_device *dev);void change_level(struct net_device *dev);static inline void sbni_xmit(struct net_device *dev);static inline void sbni_get_packet(struct net_device* dev);static void sbni_watchdog(unsigned long arg);static void set_multicast_list(struct net_device *dev);static int sbni_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);static int sbni_set_mac_address(struct net_device *dev, void *addr);unsigned long calc_crc(char *mem, int len, unsigned initial);void sbni_nirvana(struct net_device *dev);static int sbni_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,		void *daddr, void *saddr, unsigned len);static int sbni_rebuild_header(struct sk_buff *skb);static int sbni_header_cache(struct neighbour *neigh, struct hh_cache *hh);static inline void sbni_outs(int port, void *data, int len);static inline void sbni_ins(int port, void *data, int len);#define SIZE_OF_TIMEOUT_RXL_TAB 4static u_char timeout_rxl_tab[] = {  0x03, 0x05, 0x08, 0x0b};static u_char rxl_tab[] = {  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08,   0x0a, 0x0c, 0x0f, 0x16, 0x18, 0x1a, 0x1c, 0x1f};/* A zero-terminated list of I/O addresses to be probed */static unsigned int netcard_portlist[] =  { 	0x210, 0x2c0, 0x2d0, 0x2f0, 0x220, 0x230, 0x240, 0x250, 	0x260, 0x290, 0x2a0, 0x2b0, 0x224, 0x234, 0x244, 0x254, 	0x264, 0x294, 0x2a4, 0x2b4, 0};static unsigned char magic_reply[] = {	0x5a,0x06,0x30,0x00,0x00,0x50,0x65,0x44,0x20};static int def_baud = DEF_RATE;static int def_rxl = DEF_RXL_DELTA;static long def_mac = 0;/* * CRC-32 stuff */#define CRC32(c,crc) (crc32tab[((size_t)(crc) ^ (c)) & 0xff] ^ (((crc) >> 8) & 0x00FFFFFF))/* CRC generator 0xEDB88320 *//* CRC remainder 0x2144DF1C *//* CRC initial value 0x00000000 */#define CRC32_REMAINDER 0x2144DF1C#define CRC32_INITIAL 0x00000000static unsigned long crc32tab[] = {	0xD202EF8D,  0xA505DF1B,  0x3C0C8EA1,  0x4B0BBE37,	0xD56F2B94,  0xA2681B02,  0x3B614AB8,  0x4C667A2E,	0xDCD967BF,  0xABDE5729,  0x32D70693,  0x45D03605,	0xDBB4A3A6,  0xACB39330,  0x35BAC28A,  0x42BDF21C,	0xCFB5FFE9,  0xB8B2CF7F,  0x21BB9EC5,  0x56BCAE53,	0xC8D83BF0,  0xBFDF0B66,  0x26D65ADC,  0x51D16A4A,	0xC16E77DB,  0xB669474D,  0x2F6016F7,  0x58672661,	0xC603B3C2,  0xB1048354,  0x280DD2EE,  0x5F0AE278,	0xE96CCF45,  0x9E6BFFD3,  0x0762AE69,  0x70659EFF,	0xEE010B5C,  0x99063BCA,  0x000F6A70,  0x77085AE6,	0xE7B74777,  0x90B077E1,  0x09B9265B,  0x7EBE16CD,	0xE0DA836E,  0x97DDB3F8,  0x0ED4E242,  0x79D3D2D4,	0xF4DBDF21,  0x83DCEFB7,  0x1AD5BE0D,  0x6DD28E9B,	0xF3B61B38,  0x84B12BAE,  0x1DB87A14,  0x6ABF4A82,	0xFA005713,  0x8D076785,  0x140E363F,  0x630906A9,	0xFD6D930A,  0x8A6AA39C,  0x1363F226,  0x6464C2B0,	0xA4DEAE1D,  0xD3D99E8B,  0x4AD0CF31,  0x3DD7FFA7,	0xA3B36A04,  0xD4B45A92,  0x4DBD0B28,  0x3ABA3BBE,	0xAA05262F,  0xDD0216B9,  0x440B4703,  0x330C7795,	0xAD68E236,  0xDA6FD2A0,  0x4366831A,  0x3461B38C,	0xB969BE79,  0xCE6E8EEF,  0x5767DF55,  0x2060EFC3,	0xBE047A60,  0xC9034AF6,  0x500A1B4C,  0x270D2BDA,	0xB7B2364B,  0xC0B506DD,  0x59BC5767,  0x2EBB67F1,	0xB0DFF252,  0xC7D8C2C4,  0x5ED1937E,  0x29D6A3E8,	0x9FB08ED5,  0xE8B7BE43,  0x71BEEFF9,  0x06B9DF6F,	0x98DD4ACC,  0xEFDA7A5A,  0x76D32BE0,  0x01D41B76,	0x916B06E7,  0xE66C3671,  0x7F6567CB,  0x0862575D,	0x9606C2FE,  0xE101F268,  0x7808A3D2,  0x0F0F9344,	0x82079EB1,  0xF500AE27,  0x6C09FF9D,  0x1B0ECF0B,	0x856A5AA8,  0xF26D6A3E,  0x6B643B84,  0x1C630B12,		0x8CDC1683,  0xFBDB2615,  0x62D277AF,  0x15D54739,	0x8BB1D29A,  0xFCB6E20C,  0x65BFB3B6,  0x12B88320,	0x3FBA6CAD,  0x48BD5C3B,  0xD1B40D81,  0xA6B33D17,	0x38D7A8B4,  0x4FD09822,  0xD6D9C998,  0xA1DEF90E,	0x3161E49F,  0x4666D409,  0xDF6F85B3,  0xA868B525,	0x360C2086,  0x410B1010,  0xD80241AA,  0xAF05713C,	0x220D7CC9,  0x550A4C5F,  0xCC031DE5,  0xBB042D73,	0x2560B8D0,  0x52678846,  0xCB6ED9FC,  0xBC69E96A,	0x2CD6F4FB,  0x5BD1C46D,  0xC2D895D7,  0xB5DFA541,	0x2BBB30E2,  0x5CBC0074,  0xC5B551CE,  0xB2B26158,	0x04D44C65,  0x73D37CF3,  0xEADA2D49,  0x9DDD1DDF,	0x03B9887C,  0x74BEB8EA,  0xEDB7E950,  0x9AB0D9C6,	0x0A0FC457,  0x7D08F4C1,  0xE401A57B,  0x930695ED,	0x0D62004E,  0x7A6530D8,  0xE36C6162,  0x946B51F4,	0x19635C01,  0x6E646C97,  0xF76D3D2D,  0x806A0DBB,	0x1E0E9818,  0x6909A88E,  0xF000F934,  0x8707C9A2,	0x17B8D433,  0x60BFE4A5,  0xF9B6B51F,  0x8EB18589,	0x10D5102A,  0x67D220BC,  0xFEDB7106,  0x89DC4190,	0x49662D3D,  0x3E611DAB,  0xA7684C11,  0xD06F7C87,	0x4E0BE924,  0x390CD9B2,  0xA0058808,  0xD702B89E,	0x47BDA50F,  0x30BA9599,  0xA9B3C423,  0xDEB4F4B5,	0x40D06116,  0x37D75180,  0xAEDE003A,  0xD9D930AC,	0x54D13D59,  0x23D60DCF,  0xBADF5C75,  0xCDD86CE3,	0x53BCF940,  0x24BBC9D6,  0xBDB2986C,  0xCAB5A8FA,	0x5A0AB56B,  0x2D0D85FD,  0xB404D447,  0xC303E4D1,	0x5D677172,  0x2A6041E4,  0xB369105E,  0xC46E20C8,	0x72080DF5,  0x050F3D63,  0x9C066CD9,  0xEB015C4F,	0x7565C9EC,  0x0262F97A,  0x9B6BA8C0,  0xEC6C9856,	0x7CD385C7,  0x0BD4B551,  0x92DDE4EB,  0xE5DAD47D,	0x7BBE41DE,  0x0CB97148,  0x95B020F2,  0xE2B71064,	0x6FBF1D91,  0x18B82D07,  0x81B17CBD,  0xF6B64C2B,	0x68D2D988,  0x1FD5E91E,  0x86DCB8A4,  0xF1DB8832,	0x616495A3,  0x1663A535,  0x8F6AF48F,  0xF86DC419,	0x660951BA,  0x110E612C,  0x88073096,  0xFF000000};static inline void sbni_outs(int port, void *data, int len){#ifdef GOODBUS16	outsw(port,data,len/2);	if(len & 1)		outb(((char*)data)[len - 1],port);#else	outsb(port,data,len);#endif}static inline void sbni_ins(int port, void *data, int len){#ifdef GOODBUS16	insw(port,data,len/2);	if(len & 1)		((char*)data)[len - 1] = inb(port);#else	insb(port,data,len);#endif}static int sbni_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,	   void *daddr, void *saddr, unsigned len){	struct sbni_hard_header *hh = (struct sbni_hard_header *) 			skb_push(skb, sizeof(struct sbni_hard_header));    	if(type!=ETH_P_802_3) 		hh->h_proto = htons(type);	else		hh->h_proto = htons(len);  	if(saddr)		memcpy(hh->h_source,saddr,dev->addr_len);	else		memcpy(hh->h_source,dev->dev_addr,dev->addr_len);	if(daddr)	{		memcpy(hh->h_dest,daddr,dev->addr_len);		return dev->hard_header_len;	} 	return -dev->hard_header_len;}int sbni_header_cache(struct neighbour *neigh, struct hh_cache *hh){	unsigned short type = hh->hh_type;	struct sbni_hard_header *sbni = (struct sbni_hard_header*)						(((u8*)hh->hh_data) - 8);	struct net_device *dev = neigh->dev;    	if (type == __constant_htons(ETH_P_802_3))		return -1;  	sbni->h_proto = type;	memcpy(sbni->h_source, dev->dev_addr, dev->addr_len);	memcpy(sbni->h_dest, neigh->ha, dev->addr_len);	return 0;}static int sbni_rebuild_header(struct sk_buff *skb){	struct sbni_hard_header *hh = (struct sbni_hard_header *)skb;	/*	 *	Only ARP/IP is currently supported	 */	/*	 *	Try to get ARP to resolve the header.	 */  #ifdef CONFIG_INET  	return arp_find((unsigned char*)hh->h_dest, skb)? 1 : 0;  #else	return 0;	#endif	}static void sbni_header_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr){	memcpy(((u8*)hh->hh_data) + 2, haddr, dev->addr_len);}#ifdef HAVE_DEVLISTstruct netdev_entry sbni_drv = {	"sbni", sbni_probe1, SBNI_IO_EXTENT, netcard_portlist };#elseint __init sbni_probe(struct net_device *dev){	int i;	int base_addr = dev ? dev->base_addr : 0;		DP( printk("%s: sbni_probe\n", dev->name); )	if(base_addr > 0x1ff)	/* Check a single specified location. */		return sbni_probe1(dev, base_addr);	else if(base_addr != 0)	/* Don't probe at all. */		return -ENXIO;	for(i = 0; (base_addr = netcard_portlist[i]); i++)	{ 		if(!check_region(base_addr, SBNI_IO_EXTENT) && base_addr != 1)		{			/* Lock this address, or later we'll try it again */			netcard_portlist[i] = 1;			if(sbni_probe1(dev, base_addr) == 0)				return 0;		}	}	return -ENODEV;}#endif /* have devlist*//* *	The actual probe.  *//*	Valid combinations in CSR0 (for probing):	VALID_DECODER	0000,0011,1011,1010				    	; 0   ; -				TR_REQ	; 1   ; +			TR_RDY	    	; 2   ; -			TR_RDY	TR_REQ	; 3   ; +		BU_EMP		    	; 4   ; +		BU_EMP	     	TR_REQ	; 5   ; +		BU_EMP	TR_RDY	    	; 6   ; -		BU_EMP	TR_RDY	TR_REQ	; 7   ; +	RC_RDY 		     		; 8   ; +	RC_RDY			TR_REQ	; 9   ; +	RC_RDY		TR_RDY		; 10  ; -	RC_RDY		TR_RDY	TR_REQ	; 11  ; -	RC_RDY	BU_EMP			; 12  ; -	RC_RDY	BU_EMP		TR_REQ	; 13  ; -	RC_RDY	BU_EMP	TR_RDY		; 14  ; -	RC_RDY	BU_EMP	TR_RDY	TR_REQ	; 15  ; -*/#define VALID_DECODER (2 + 8 + 0x10 + 0x20 + 0x80 + 0x100 + 0x200)static int __init sbni_probe1(struct net_device *dev, int ioaddr){	int autoirq = 0;	int bad_card = 0;	unsigned char csr0;	struct net_local* lp;	static int version_printed = 0;	DP( printk("%s: sbni_probe1 ioaddr=%d\n", dev->name, ioaddr); )       	if(check_region(ioaddr, SBNI_IO_EXTENT) < 0)		return -ENODEV;	if(version_printed++ == 0)		printk(version);     	/* check for valid combination in CSR0 */	csr0 = inb(ioaddr + CSR0);	if(csr0 == 0xff || csr0 == 0)		bad_card = 1;	else 	{		csr0 &= ~EN_INT;		if(csr0 & BU_EMP)			csr0 |= EN_INT;		if((VALID_DECODER & (1 << (csr0 >> 4))) == 0)			bad_card = 1;	}	if(bad_card)		return -ENODEV;	else		outb(0, ioaddr + CSR0); 	if(dev->irq < 2)	{		DP( printk("%s: autoprobing\n", dev->name); );		autoirq_setup(5);		outb(EN_INT | TR_REQ, ioaddr + CSR0);		outb(PR_RES, ioaddr + CSR1);		autoirq = autoirq_report(5);		if(autoirq == 0)		{			printk("sbni probe at %#x failed to detect IRQ line\n", ioaddr);			return -EAGAIN;		}	}	/* clear FIFO buffer */	outb(0, ioaddr + CSR0);   	if(autoirq)		dev->irq = autoirq;	{   		int irqval=request_irq(dev->irq, sbni_interrupt, 0, dev->name, dev);		if (irqval) 		{			printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval);			return -EAGAIN;		}	}

⌨️ 快捷键说明

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