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

📄 ltpc.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/***    ltpc.c -- a driver for the LocalTalk PC card. * *      Copyright (c) 1995,1996 Bradford W. Johnson <johns393@maroon.tc.umn.edu> * *      This software may be used and distributed according to the terms *      of the GNU General Public License, incorporated herein by reference. * *      This is ALPHA code at best.  It may not work for you.  It may *      damage your equipment.  It may damage your relations with other *      users of your network.  Use it at your own risk! * *      Based in part on: *      skeleton.c      by Donald Becker *      dummy.c         by Nick Holloway and Alan Cox *      loopback.c      by Ross Biro, Fred van Kampen, Donald Becker *      the netatalk source code (UMICH) *      lots of work on the card... * *      I do not have access to the (proprietary) SDK that goes with the card. *      If you do, I don't want to know about it, and you can probably write *      a better driver yourself anyway.  This does mean that the pieces that *      talk to the card are guesswork on my part, so use at your own risk! * *      This is my first try at writing Linux networking code, and is also *      guesswork.  Again, use at your own risk!  (Although on this part, I'd *      welcome suggestions) * *      This is a loadable kernel module which seems to work at my site *      consisting of a 1.2.13 linux box running netatalk 1.3.3, and with *      the kernel support from 1.3.3b2 including patches routing.patch *      and ddp.disappears.from.chooser.  In order to run it, you will need *      to patch ddp.c and aarp.c in the kernel, but only a little... * *      I'm fairly confident that while this is arguably badly written, the *      problems that people experience will be "higher level", that is, with *      complications in the netatalk code.  The driver itself doesn't do *      anything terribly complicated -- it pretends to be an ether device *      as far as netatalk is concerned, strips the DDP data out of the ether *      frame and builds a LLAP packet to send out the card.  In the other *      direction, it receives LLAP frames from the card and builds a fake *      ether packet that it then tosses up to the networking code.  You can *      argue (correctly) that this is an ugly way to do things, but it *      requires a minimal amount of fooling with the code in ddp.c and aarp.c. * *      The card will do a lot more than is used here -- I *think* it has the *      layers up through ATP.  Even if you knew how that part works (which I *      don't) it would be a big job to carve up the kernel ddp code to insert *      things at a higher level, and probably a bad idea... * *      There are a number of other cards that do LocalTalk on the PC.  If *      nobody finds any insurmountable (at the netatalk level) problems *      here, this driver should encourage people to put some work into the *      other cards (some of which I gather are still commercially available) *      and also to put hooks for LocalTalk into the official ddp code. * *      I welcome comments and suggestions.  This is my first try at Linux *      networking stuff, and there are probably lots of things that I did *      suboptimally.   * ***//*** * * $Log: ltpc.c,v $ * Revision 1.1.2.1  2000/03/01 05:35:07  jgarzik * at and tr cleanup * * Revision 1.8  1997/01/28 05:44:54  bradford * Clean up for non-module a little. * Hacked about a bit to clean things up - Alan Cox  * Probably broken it from the origina 1.8 * * 1998/11/09: David Huggins-Daines <dhd@debian.org> * Cleaned up the initialization code to use the standard autoirq methods,   and to probe for things in the standard order of i/o, irq, dma.  This   removes the "reset the reset" hack, because I couldn't figure out an   easy way to get the card to trigger an interrupt after it. * Added support for passing configuration parameters on the kernel command   line and through insmod * Changed the device name from "ltalk0" to "lt0", both to conform with the   other localtalk driver, and to clear up the inconsistency between the   module and the non-module versions of the driver :-) * Added a bunch of comments (I was going to make some enums for the state   codes and the register offsets, but I'm still not sure exactly what their   semantics are) * Don't poll anymore in interrupt-driven mode * It seems to work as a module now (as of 2.1.127), but I don't think   I'm responsible for that... * * Revision 1.7  1996/12/12 03:42:33  bradford * DMA alloc cribbed from 3c505.c. * * Revision 1.6  1996/12/12 03:18:58  bradford * Added virt_to_bus; works in 2.1.13. * * Revision 1.5  1996/12/12 03:13:22  root * xmitQel initialization -- think through better though. * * Revision 1.4  1996/06/18 14:55:55  root * Change names to ltpc. Tabs. Took a shot at dma alloc, * although more needs to be done eventually. * * Revision 1.3  1996/05/22 14:59:39  root * Change dev->open, dev->close to track dummy.c in 1.99.(around 7) * * Revision 1.2  1996/05/22 14:58:24  root * Change tabs mostly. * * Revision 1.1  1996/04/23 04:45:09  root * Initial revision * * Revision 0.16  1996/03/05 15:59:56  root * Change ARPHRD_LOCALTLK definition to the "real" one. * * Revision 0.15  1996/03/05 06:28:30  root * Changes for kernel 1.3.70.  Still need a few patches to kernel, but * it's getting closer. * * Revision 0.14  1996/02/25 17:38:32  root * More cleanups.  Removed query to card on get_stats. * * Revision 0.13  1996/02/21  16:27:40  root * Refix debug_print_skb.  Fix mac.raw gotcha that appeared in 1.3.65. * Clean up receive code a little. * * Revision 0.12  1996/02/19  16:34:53  root * Fix debug_print_skb.  Kludge outgoing snet to 0 when using startup * range.  Change debug to mask: 1 for verbose, 2 for higher level stuff * including packet printing, 4 for lower level (card i/o) stuff. * * Revision 0.11  1996/02/12  15:53:38  root * Added router sends (requires new aarp.c patch) * * Revision 0.10  1996/02/11  00:19:35  root * Change source LTALK_LOGGING debug switch to insmod ... debug=2. * * Revision 0.9  1996/02/10  23:59:35  root * Fixed those fixes for 1.2 -- DANGER!  The at.h that comes with netatalk * has a *different* definition of struct sockaddr_at than the Linux kernel * does.  This is an "insidious and invidious" bug... * (Actually the preceding comment is false -- it's the atalk.h in the * ancient atalk-0.06 that's the problem) * * Revision 0.8  1996/02/10 19:09:00  root * Merge 1.3 changes.  Tested OK under 1.3.60. * * Revision 0.7  1996/02/10 17:56:56  root * Added debug=1 parameter on insmod for debugging prints.  Tried * to fix timer unload on rmmod, but I don't think that's the problem. * * Revision 0.6  1995/12/31  19:01:09  root * Clean up rmmod, irq comments per feedback from Corin Anderson (Thanks Corey!) * Clean up initial probing -- sometimes the card wakes up latched in reset. * * Revision 0.5  1995/12/22  06:03:44  root * Added comments in front and cleaned up a bit. * This version sent out to people. * * Revision 0.4  1995/12/18  03:46:44  root * Return shortDDP to longDDP fake to 0/0.  Added command structs. * ***//* ltpc jumpers are:**	Interrupts -- set at most one.  If none are set, the driver uses*	polled mode.  Because the card was developed in the XT era, the*	original documentation refers to IRQ2.  Since you'll be running*	this on an AT (or later) class machine, that really means IRQ9.**	SW1	IRQ 4*	SW2	IRQ 3*	SW3	IRQ 9 (2 in original card documentation only applies to XT)***	DMA -- choose DMA 1 or 3, and set both corresponding switches.**	SW4	DMA 3*	SW5	DMA 1*	SW6	DMA 3*	SW7	DMA 1***	I/O address -- choose one.  **	SW8	220 / 240*//*	To have some stuff logged, do *	insmod ltpc.o debug=1**	For a whole bunch of stuff, use higher numbers.**	The default is 0, i.e. no messages except for the probe results.*//* insmod-tweakable variables */static int debug;#define DEBUG_VERBOSE 1#define DEBUG_UPPER 2#define DEBUG_LOWER 4static int io;static int irq;static int dma;#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/spinlock.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>#include <linux/timer.h>#include <linux/atalk.h>#include <linux/bitops.h>#include <asm/system.h>#include <asm/dma.h>#include <asm/io.h>/* our stuff */#include "ltpc.h"static DEFINE_SPINLOCK(txqueue_lock);static DEFINE_SPINLOCK(mbox_lock);/* function prototypes */static int do_read(struct net_device *dev, void *cbuf, int cbuflen,	void *dbuf, int dbuflen);static int sendup_buffer (struct net_device *dev);/* Dma Memory related stuff, cribbed directly from 3c505.c */static unsigned long dma_mem_alloc(int size){        int order = get_order(size);        return __get_dma_pages(GFP_KERNEL, order);}/* DMA data buffer, DMA command buffer */static unsigned char *ltdmabuf;static unsigned char *ltdmacbuf;/* private struct, holds our appletalk address */struct ltpc_private{	struct net_device_stats stats;	struct atalk_addr my_addr;};/* transmit queue element struct */struct xmitQel {	struct xmitQel *next;	/* command buffer */	unsigned char *cbuf;	short cbuflen;	/* data buffer */	unsigned char *dbuf;	short dbuflen;	unsigned char QWrite;	/* read or write data */	unsigned char mailbox;};/* the transmit queue itself */static struct xmitQel *xmQhd, *xmQtl;static void enQ(struct xmitQel *qel){	unsigned long flags;	qel->next = NULL;		spin_lock_irqsave(&txqueue_lock, flags);	if (xmQtl) {		xmQtl->next = qel;	} else {		xmQhd = qel;	}	xmQtl = qel;	spin_unlock_irqrestore(&txqueue_lock, flags);	if (debug & DEBUG_LOWER)		printk("enqueued a 0x%02x command\n",qel->cbuf[0]);}static struct xmitQel *deQ(void){	unsigned long flags;	int i;	struct xmitQel *qel=NULL;		spin_lock_irqsave(&txqueue_lock, flags);	if (xmQhd) {		qel = xmQhd;		xmQhd = qel->next;		if(!xmQhd) xmQtl = NULL;	}	spin_unlock_irqrestore(&txqueue_lock, flags);	if ((debug & DEBUG_LOWER) && qel) {		int n;		printk(KERN_DEBUG "ltpc: dequeued command ");		n = qel->cbuflen;		if (n>100) n=100;		for(i=0;i<n;i++) printk("%02x ",qel->cbuf[i]);		printk("\n");	}	return qel;}/* and... the queue elements we'll be using */static struct xmitQel qels[16];/* and their corresponding mailboxes */static unsigned char mailbox[16];static unsigned char mboxinuse[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};static int wait_timeout(struct net_device *dev, int c){	/* returns true if it stayed c */	/* this uses base+6, but it's ok */	int i;	/* twenty second or so total */	for(i=0;i<200000;i++) {		if ( c != inb_p(dev->base_addr+6) ) return 0;		udelay(100);	}	return 1; /* timed out */}/* get the first free mailbox */static int getmbox(void){	unsigned long flags;	int i;	spin_lock_irqsave(&mbox_lock, flags);	for(i=1;i<16;i++) if(!mboxinuse[i]) {		mboxinuse[i]=1;		spin_unlock_irqrestore(&mbox_lock, flags);		return i;	}	spin_unlock_irqrestore(&mbox_lock, flags);	return 0;}/* read a command from the card */static void handlefc(struct net_device *dev){	/* called *only* from idle, non-reentrant */	int dma = dev->dma;	int base = dev->base_addr;	unsigned long flags;	flags=claim_dma_lock();	disable_dma(dma);	clear_dma_ff(dma);	set_dma_mode(dma,DMA_MODE_READ);	set_dma_addr(dma,virt_to_bus(ltdmacbuf));	set_dma_count(dma,50);	enable_dma(dma);	release_dma_lock(flags);	inb_p(base+3);	inb_p(base+2);	if ( wait_timeout(dev,0xfc) ) printk("timed out in handlefc\n");}/* read data from the card */static void handlefd(struct net_device *dev){	int dma = dev->dma;	int base = dev->base_addr;	unsigned long flags;	flags=claim_dma_lock();	disable_dma(dma);	clear_dma_ff(dma);	set_dma_mode(dma,DMA_MODE_READ);	set_dma_addr(dma,virt_to_bus(ltdmabuf));	set_dma_count(dma,800);	enable_dma(dma);	release_dma_lock(flags);	inb_p(base+3);	inb_p(base+2);	if ( wait_timeout(dev,0xfd) ) printk("timed out in handlefd\n");	sendup_buffer(dev);} static void handlewrite(struct net_device *dev){	/* called *only* from idle, non-reentrant */	/* on entry, 0xfb and ltdmabuf holds data */	int dma = dev->dma;	int base = dev->base_addr;	unsigned long flags;		flags=claim_dma_lock();	disable_dma(dma);	clear_dma_ff(dma);	set_dma_mode(dma,DMA_MODE_WRITE);	set_dma_addr(dma,virt_to_bus(ltdmabuf));	set_dma_count(dma,800);	enable_dma(dma);	release_dma_lock(flags);		inb_p(base+3);	inb_p(base+2);	if ( wait_timeout(dev,0xfb) ) {		flags=claim_dma_lock();		printk("timed out in handlewrite, dma res %d\n",

⌨️ 快捷键说明

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