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

📄 cops.c

📁 linux-2.6.15.6
💻 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/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/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>#include <linux/delay.h>	/* For udelay() */#include <linux/atalk.h>#include <linux/spinlock.h>#include <linux/bitops.h>#include <asm/system.h>#include <asm/io.h>#include <asm/dma.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;#endifstatic int io = 0x240;		/* Default IO for Dayna */static int irq = 5;		/* Default IRQ *//* *	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 ports[] = { 	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 atalk_addr node_addr;	/* Full node address */	spinlock_t lock;		/* RX/TX lock */};/* Index to functions, as function prototypes. */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 irqreturn_t 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);static void cleanup_card(struct net_device *dev){	if (dev->irq)		free_irq(dev->irq, dev);	release_region(dev->base_addr, COPS_IO_EXTENT);}/* *      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. */struct net_device * __init cops_probe(int unit){	struct net_device *dev;	unsigned *port;	int base_addr;	int err = 0;	dev = alloc_ltalkdev(sizeof(struct cops_local));	if (!dev)		return ERR_PTR(-ENOMEM);	if (unit >= 0) {		sprintf(dev->name, "lt%d", unit);		netdev_boot_setup_check(dev);		irq = dev->irq;		base_addr = dev->base_addr;	} else {		base_addr = dev->base_addr = io;	}	SET_MODULE_OWNER(dev);	if (base_addr > 0x1ff) {    /* Check a single specified location. */		err = cops_probe1(dev, base_addr);	} else if (base_addr != 0) { /* Don't probe at all. */		err = -ENXIO;	} else {		/* 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 (port = ports; *port && cops_probe1(dev, *port) < 0; port++)			;		if (!*port)			err = -ENODEV;	}	if (err)		goto out;	err = register_netdev(dev);	if (err)		goto out1;	return dev;out1:	cleanup_card(dev);out:	free_netdev(dev);	return ERR_PTR(err);}/* *      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.	 */	dev->irq = irq;	switch (dev->irq)	{		case 0:			/* COPS AutoIRQ routine */			dev->irq = cops_irq(ioaddr, board);			if (dev->irq)				break;			/* No IRQ found on this port, fallthrough */		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;        lp = netdev_priv(dev);        memset(lp, 0, sizeof(struct cops_local));        spin_lock_init(&lp->lock);	/* Copy local board variable to lp struct. */	lp->board               = board;	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. */

⌨️ 快捷键说明

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