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

📄 cops.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 3 页
字号:
/*      cops.c: LocalTalk driver for Linux. * *	Authors: *      - Jay Schulist <jschlst@samba.org> * *	With more than a little help from; *	- Alan Cox <Alan.Cox@linux.org>  * *      Derived from: *      - skeleton.c: A network driver outline for linux. *        Written 1993-94 by Donald Becker. *	- ltpc.c: A driver for the LocalTalk PC card. *	  Written by Bradford W. Johnson. * *      Copyright 1993 United States Government as represented by the *      Director, National Security Agency. * *      This software may be used and distributed according to the terms *      of the GNU General Public License, incorporated herein by reference. * *	Changes: *	19970608	Alan Cox	Allowed dual card type support *					Can set board type in insmod *					Hooks for cops_setup routine *					(not yet implemented). *	19971101	Jay Schulist	Fixes for multiple lt* devices. *	19980607	Steven Hirsch	Fixed the badly broken support *					for Tangent type cards. Only *                                      tested on Daystar LT200. Some *                                      cleanup of formatting and program *                                      logic.  Added emacs 'local-vars' *                                      setup for Jay's brace style. *	20000211	Alan Cox	Cleaned up for softnet */static const char *version ="cops.c:v0.04 6/7/98 Jay Schulist <jschlst@samba.org>\n";/* *  Sources: *      COPS Localtalk SDK. This provides almost all of the information *      needed. *//* * insmod/modprobe configurable stuff. *	- IO Port, choose one your card supports or 0 if you dare. *	- IRQ, also choose one your card supports or nothing and let *	  the driver figure it out. */#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/slab.h>#include <linux/string.h>#include <asm/system.h>#include <asm/bitops.h>#include <asm/io.h>#include <asm/dma.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/if_arp.h>#include <linux/if_ltalk.h>	/* For ltalk_setup() */#include <linux/delay.h>	/* For udelay() */#include <linux/atalk.h>#include "cops.h"		/* Our Stuff */#include "cops_ltdrv.h"		/* Firmware code for Tangent type cards. */#include "cops_ffdrv.h"		/* Firmware code for Dayna type cards. *//* *      The name of the card. Is used for messages and in the requests for *      io regions, irqs and dma channels */static const char *cardname = "cops";#ifdef CONFIG_COPS_DAYNAstatic int board_type = DAYNA;	/* Module exported */#elsestatic int board_type = TANGENT;#endif#ifdef MODULEstatic int io = 0x240;		/* Default IO for Dayna */static int irq = 5;		/* Default IRQ */#elsestatic int io;			/* Default IO for Dayna */#endif/* *	COPS Autoprobe information. *	Right now if port address is right but IRQ is not 5 this will *      return a 5 no matter what since we will still get a status response. *      Need one more additional check to narrow down after we have gotten *      the ioaddr. But since only other possible IRQs is 3 and 4 so no real *	hurry on this. I *STRONGLY* recommend using IRQ 5 for your card with *	this driver. *  *	This driver has 2 modes and they are: Dayna mode and Tangent mode. *	Each mode corresponds with the type of card. It has been found *	that there are 2 main types of cards and all other cards are *	the same and just have different names or only have minor differences *	such as more IO ports. As this driver is tested it will *	become more clear on exactly what cards are supported. The driver *	defaults to using Dayna mode. To change the drivers mode, simply *	select Dayna or Tangent mode when configuring the kernel. * *      This driver should support: *      TANGENT driver mode: *              Tangent ATB-II, Novell NL-1000, Daystar Digital LT-200, *		COPS LT-1 *      DAYNA driver mode: *              Dayna DL2000/DaynaTalk PC (Half Length), COPS LT-95,  *		Farallon PhoneNET PC III, Farallon PhoneNET PC II *	Other cards possibly supported mode unkown though: *		Dayna DL2000 (Full length), COPS LT/M (Micro-Channel) * *	Cards NOT supported by this driver but supported by the ltpc.c *	driver written by Bradford W. Johnson <johns393@maroon.tc.umn.edu> *		Farallon PhoneNET PC *		Original Apple LocalTalk PC card *  *      N.B. * *      The Daystar Digital LT200 boards do not support interrupt-driven *      IO.  You must specify 'irq=0xff' as a module parameter to invoke *      polled mode.  I also believe that the port probing logic is quite *      dangerous at best and certainly hopeless for a polled card.  Best to  *      specify both. - Steve H. * *//* * Zero terminated list of IO ports to probe. */static unsigned int cops_portlist[] = { 	0x240, 0x340, 0x200, 0x210, 0x220, 0x230, 0x260, 	0x2A0, 0x300, 0x310, 0x320, 0x330, 0x350, 0x360,	0};/* * Zero terminated list of IRQ ports to probe. */static int cops_irqlist[] = {	5, 4, 3, 0 };static struct timer_list cops_timer;/* use 0 for production, 1 for verification, 2 for debug, 3 for verbose debug */#ifndef COPS_DEBUG#define COPS_DEBUG 1 #endifstatic unsigned int cops_debug = COPS_DEBUG;/* The number of low I/O ports used by the card. */#define COPS_IO_EXTENT       8/* Information that needs to be kept for each board. */struct cops_local{        struct net_device_stats stats;        int board;			/* Holds what board type is. */	int nodeid;			/* Set to 1 once have nodeid. */        unsigned char node_acquire;	/* Node ID when acquired. */        struct at_addr node_addr;	/* Full node address */};/* Index to functions, as function prototypes. */extern int  cops_probe (struct net_device *dev);static int  cops_probe1 (struct net_device *dev, int ioaddr);static int  cops_irq (int ioaddr, int board);static int  cops_open (struct net_device *dev);static int  cops_jumpstart (struct net_device *dev);static void cops_reset (struct net_device *dev, int sleep);static void cops_load (struct net_device *dev);static int  cops_nodeid (struct net_device *dev, int nodeid);static void cops_interrupt (int irq, void *dev_id, struct pt_regs *regs);static void cops_poll (unsigned long ltdev);static void cops_timeout(struct net_device *dev);static void cops_rx (struct net_device *dev);static int  cops_send_packet (struct sk_buff *skb, struct net_device *dev);static void set_multicast_list (struct net_device *dev);static int  cops_hard_header (struct sk_buff *skb, struct net_device *dev,			      unsigned short type, void *daddr, void *saddr, 			      unsigned len);static int  cops_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);static int  cops_close (struct net_device *dev);static struct net_device_stats *cops_get_stats (struct net_device *dev);/* *      Check for a network adaptor of this type, and return '0' iff one exists. *      If dev->base_addr == 0, probe all likely locations. *      If dev->base_addr in [1..0x1ff], always return failure. *        otherwise go with what we pass in. */int __init cops_probe(struct net_device *dev){	int i;        int base_addr = dev->base_addr;	SET_MODULE_OWNER(dev);        if(base_addr == 0 && io)        	base_addr=io;        if(base_addr > 0x1ff)    /* Check a single specified location. */                return cops_probe1(dev, base_addr);	else if(base_addr != 0)  /* Don't probe at all. */               	return -ENXIO;		/* FIXME  Does this really work for cards which generate irq?	 * It's definitely N.G. for polled Tangent. sh	 * Dayna cards don't autoprobe well at all, but if your card is	 * at IRQ 5 & IO 0x240 we find it every time. ;) JS	 */        for(i=0; cops_portlist[i]; i++)                if(cops_probe1(dev, cops_portlist[i]) == 0)                        return 0;	        return -ENODEV;}/* *      This is the real probe routine. Linux has a history of friendly device *      probes on the ISA bus. A good device probes avoids doing writes, and *      verifies that the correct device exists and functions. */static int __init cops_probe1(struct net_device *dev, int ioaddr){        struct cops_local *lp;	static unsigned version_printed;	int board = board_type;	int retval;	        if(cops_debug && version_printed++ == 0)		printk("%s", version);	/* Grab the region so no one else tries to probe our ioports. */	if (!request_region(ioaddr, COPS_IO_EXTENT, dev->name))		return -EBUSY;        /*         * Since this board has jumpered interrupts, allocate the interrupt         * vector now. There is no point in waiting since no other device         * can use the interrupt, and this marks the irq as busy. Jumpered         * interrupts are typically not reported by the boards, and we must         * used AutoIRQ to find them.	 */	switch (dev->irq)	{		case 0:			/* COPS AutoIRQ routine */			dev->irq = cops_irq(ioaddr, board);			if(!dev->irq) {				retval = -EINVAL;	/* No IRQ found on this port */				goto err_out;			}		case 1:			retval = -EINVAL;			goto err_out;		/* Fixup for users that don't know that IRQ 2 is really		 * IRQ 9, or don't know which one to set.		 */		case 2:			dev->irq = 9;			break;		/* Polled operation requested. Although irq of zero passed as		 * a parameter tells the init routines to probe, we'll		 * overload it to denote polled operation at runtime.		 */		case 0xff:			dev->irq = 0;			break;		default:			break;	}	/* Reserve any actual interrupt. */	if(dev->irq) {		retval = request_irq(dev->irq, &cops_interrupt, 0, dev->name, dev);		if (retval)			goto err_out;	}	dev->base_addr		= ioaddr;	/* Initialize the private device structure. */        dev->priv = kmalloc(sizeof(struct cops_local), GFP_KERNEL);        if(dev->priv == NULL) {		if (dev->irq)			free_irq(dev->irq, dev);        	retval = -ENOMEM;		goto err_out;	}        lp = (struct cops_local *)dev->priv;        memset(lp, 0, sizeof(struct cops_local));	/* Copy local board variable to lp struct. */	lp->board               = board;	/* Fill in the fields of the device structure with LocalTalk values. */	ltalk_setup(dev);	dev->hard_start_xmit    = cops_send_packet;	dev->tx_timeout		= cops_timeout;	dev->watchdog_timeo	= HZ * 2;	dev->hard_header	= cops_hard_header;        dev->get_stats          = cops_get_stats;	dev->open               = cops_open;        dev->stop               = cops_close;        dev->do_ioctl           = cops_ioctl;	dev->set_multicast_list = set_multicast_list;        dev->mc_list            = NULL;	/* Tell the user where the card is and what mode we're in. */	if(board==DAYNA)		printk("%s: %s at %#3x, using IRQ %d, in Dayna mode.\n", 			dev->name, cardname, ioaddr, dev->irq);	if(board==TANGENT) {		if(dev->irq)			printk("%s: %s at %#3x, IRQ %d, in Tangent mode\n", 				dev->name, cardname, ioaddr, dev->irq);		else			printk("%s: %s at %#3x, using polled IO, in Tangent mode.\n", 				dev->name, cardname, ioaddr);

⌨️ 快捷键说明

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