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

📄 ltpc.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 3 页
字号:
	}	memset(dev->priv, 0, sizeof(struct ltpc_private));	dev->get_stats = ltpc_get_stats;	/* add the ltpc-specific things */	dev->do_ioctl = &ltpc_ioctl;	dev->set_multicast_list = &set_multicast_list;	dev->mc_list = NULL;	return 0;}static int ltpc_poll_counter;static void ltpc_poll(unsigned long l){	struct net_device *dev = (struct net_device *) l;	del_timer(&ltpc_timer);	if(debug&DEBUG_VERBOSE) {		if (!ltpc_poll_counter) {			ltpc_poll_counter = 50;			printk("ltpc poll is alive\n");		}		ltpc_poll_counter--;	}  	if (!dev)		return;  /* we've been downed */	idle(dev);	ltpc_timer.expires = jiffies+5;		add_timer(&ltpc_timer);}/* DDP to LLAP translation */static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev){	/* in kernel 1.3.xx, on entry skb->data points to ddp header,	 * and skb->len is the length of the ddp data + ddp header	 */	struct net_device_stats *stats = &((struct ltpc_private *)dev->priv)->stats;	int i;	struct lt_sendlap cbuf;	cbuf.command = LT_SENDLAP;	cbuf.dnode = skb->data[0];	cbuf.laptype = skb->data[2];	skb_pull(skb,3);	/* skip past LLAP header */	cbuf.length = skb->len;	/* this is host order */	skb->h.raw=skb->data;	if(debug&DEBUG_UPPER) {		printk("command ");		for(i=0;i<6;i++)			printk("%02x ",((unsigned char *)&cbuf)[i]);		printk("\n");	}	do_write(dev,&cbuf,sizeof(cbuf),skb->h.raw,skb->len);	if(debug&DEBUG_UPPER) {		printk("sent %d ddp bytes\n",skb->len);		for(i=0;i<skb->len;i++) printk("%02x ",skb->h.raw[i]);		printk("\n");	}	stats->tx_packets++;	stats->tx_bytes+=skb->len;	dev_kfree_skb(skb);	return 0;}static struct net_device_stats *ltpc_get_stats(struct net_device *dev){	struct net_device_stats *stats = &((struct ltpc_private *) dev->priv)->stats;	return stats;}/* initialization stuff */  static int __init ltpc_probe_dma(int base){	int dma = 0;  	int timeout;  	unsigned long f;    	if (!request_dma(1,"ltpc")) {  		f=claim_dma_lock();  		disable_dma(1);  		clear_dma_ff(1);		set_dma_mode(1,DMA_MODE_WRITE);		set_dma_addr(1,virt_to_bus(ltdmabuf));		set_dma_count(1,sizeof(struct lt_mem));		enable_dma(1);		release_dma_lock(f);		dma|=1;	}	if (!request_dma(3,"ltpc")) {		f=claim_dma_lock();		disable_dma(3);		clear_dma_ff(3);		set_dma_mode(3,DMA_MODE_WRITE);		set_dma_addr(3,virt_to_bus(ltdmabuf));		set_dma_count(3,sizeof(struct lt_mem));		enable_dma(3);		release_dma_lock(f);		dma|=2;	}	/* set up request */	/* FIXME -- do timings better! */	ltdmabuf[0] = LT_READMEM;	ltdmabuf[1] = 1;  /* mailbox */	ltdmabuf[2] = 0; ltdmabuf[3] = 0;  /* address */	ltdmabuf[4] = 0; ltdmabuf[5] = 1;  /* read 0x0100 bytes */	ltdmabuf[6] = 0; /* dunno if this is necessary */	inb_p(io+1);	inb_p(io+0);	timeout = jiffies+100*HZ/100;	while(time_before(jiffies, timeout)) {		if ( 0xfa == inb_p(io+6) ) break;	}	inb_p(io+3);	inb_p(io+2);	while(time_before(jiffies, timeout)) {		if ( 0xfb == inb_p(io+6) ) break;	}	/* release the other dma channel (if we opened both of them) */	if ( (dma&0x2) && (get_dma_residue(3)==sizeof(struct lt_mem)) ){		dma&=1;		free_dma(3);	}  	if ( (dma&0x1) && (get_dma_residue(1)==sizeof(struct lt_mem)) ){		dma&=0x2;		free_dma(1);	}	/* fix up dma number */	dma|=1;	return dma;}int __init ltpc_probe(struct net_device *dev){	int err;	int x=0,y=0;	int timeout;	int autoirq;	unsigned long flags;	unsigned long f;	SET_MODULE_OWNER(dev);	save_flags(flags);	/* probe for the I/O port address */	if (io != 0x240 && !check_region(0x220,8)) {		x = inb_p(0x220+6);		if ( (x!=0xff) && (x>=0xf0) ) io = 0x220;	}		if (io != 0x220 && !check_region(0x240,8)) {		y = inb_p(0x240+6);		if ( (y!=0xff) && (y>=0xf0) ) io = 0x240;	} 	if(io) {		/* found it, now grab it */		request_region(io,8,"ltpc");	} else {		/* give up in despair */		printk ("LocalTalk card not found; 220 = %02x, 240 = %02x.\n",			x,y);		restore_flags(flags);		return -1;	}	/* probe for the IRQ line */	if (irq < 2) {		autoirq_setup(2);		/* reset the interrupt line */		inb_p(io+7);		inb_p(io+7);		/* trigger an interrupt (I hope) */		inb_p(io+6);		autoirq = autoirq_report(1);		if (autoirq == 0) {			printk("ltpc: probe at %#x failed to detect IRQ line.\n",				io);		}		else {			irq = autoirq;		}	}	/* allocate a DMA buffer */	ltdmabuf = (unsigned char *) dma_mem_alloc(1000);	if (ltdmabuf) ltdmacbuf = &ltdmabuf[800];	if (!ltdmabuf) {		printk("ltpc: mem alloc failed\n");		restore_flags(flags);		return(-1);	}	if(debug&DEBUG_VERBOSE) {		printk("ltdmabuf pointer %08lx\n",(unsigned long) ltdmabuf);	}	/* reset the card */	inb_p(io+1);	inb_p(io+3);	timeout = jiffies+2*HZ/100;	while(time_before(jiffies, timeout)) ; /* hold it in reset for a coupla jiffies */	inb_p(io+0);	inb_p(io+2);	inb_p(io+7); /* clear reset */	inb_p(io+4); 	inb_p(io+5);	inb_p(io+5); /* enable dma */	inb_p(io+6); /* tri-state interrupt line */	timeout = jiffies+100*HZ/100;		while(time_before(jiffies, timeout)) {		/* wait for the card to complete initialization */	} 	/* now, figure out which dma channel we're using, unless it's	   already been specified */	/* well, 0 is a legal DMA channel, but the LTPC card doesn't	   use it... */	if (dma == 0) {		dma = ltpc_probe_dma(io);		if (!dma) {  /* no dma channel */			printk("No DMA channel found on ltpc card.\n");			restore_flags(flags);			return -1;		}	}	/* print out friendly message */	if(irq)		printk("Apple/Farallon LocalTalk-PC card at %03x, IR%d, DMA%d.\n",io,irq,dma);	else		printk("Apple/Farallon LocalTalk-PC card at %03x, DMA%d.  Using polled mode.\n",io,dma);	/* seems more logical to do this *after* probing the card... */	err = ltpc_init(dev);	if (err) return err;	dev->base_addr = io;	dev->irq = irq;	dev->dma = dma;	/* the card will want to send a result at this point */	/* (I think... leaving out this part makes the kernel crash,           so I put it back in...) */	f=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,0x100);	enable_dma(dma);	release_dma_lock(f);	(void) inb_p(io+3);	(void) inb_p(io+2);	timeout = jiffies+100*HZ/100;	while(time_before(jiffies, timeout)) {		if( 0xf9 == inb_p(io+6)) break;	}	if(debug&DEBUG_VERBOSE) {		printk("setting up timer and irq\n");	}	if (irq) {		/* grab it and don't let go :-) */		(void) request_irq( irq, &ltpc_interrupt, 0, "ltpc", dev);		(void) inb_p(io+7);  /* enable interrupts from board */		(void) inb_p(io+7);  /* and reset irq line */	} else {		/* polled mode -- 20 times per second */		/* this is really, really slow... should it poll more often? */		init_timer(&ltpc_timer);		ltpc_timer.function=ltpc_poll;		ltpc_timer.data = (unsigned long) dev;		ltpc_timer.expires = jiffies + 5;		add_timer(&ltpc_timer);		restore_flags(flags); 	}	return 0;}#ifndef MODULE/* handles "ltpc=io,irq,dma" kernel command lines */static int __init ltpc_setup(char *str){	int ints[5];	str = get_options(str, ARRAY_SIZE(ints), ints);	if (ints[0] == 0) {		if (str && !strncmp(str, "auto", 4)) {			/* do nothing :-) */		}		else {			/* usage message */			printk (KERN_ERR				"ltpc: usage: ltpc=auto|iobase[,irq[,dma]]\n");			return 0;		}	} else {		io = ints[1];		if (ints[0] > 1) {			irq = ints[2];		}		if (ints[0] > 2) {			dma = ints[3];		}		/* ignore any other paramters */	}	return 1;}__setup("ltpc=", ltpc_setup);#endif /* MODULE */static struct net_device dev_ltpc;#ifdef MODULEMODULE_LICENSE("GPL");MODULE_PARM(debug, "i");MODULE_PARM(io, "i");MODULE_PARM(irq, "i");MODULE_PARM(dma, "i");int __init init_module(void){	int err, result;	        if(io == 0)		printk(KERN_NOTICE		       "ltpc: Autoprobing is not recommended for modules\n");	/* Find a name for this unit */	dev_ltpc.init = ltpc_probe;	err=dev_alloc_name(&dev_ltpc,"lt%d");		if(err<0)		return err;	if ((result = register_netdev(&dev_ltpc)) != 0) {		printk(KERN_DEBUG "could not register Localtalk-PC device\n");		return result;	} else {		if(debug&DEBUG_VERBOSE) printk("0 from register_netdev\n");		return 0;	}}#endifstatic void __exit ltpc_cleanup(void){	long timeout;	ltpc_timer.data = 0;  /* signal the poll routine that we're done */	if(debug&DEBUG_VERBOSE) printk("freeing irq\n");	if(dev_ltpc.irq) {		free_irq(dev_ltpc.irq,&dev_ltpc);		dev_ltpc.irq = 0;	}	if(del_timer(&ltpc_timer)) 	{		/* either the poll was never started, or a poll is in process */		if(debug&DEBUG_VERBOSE) printk("waiting\n");		/* if it's in process, wait a bit for it to finish */		timeout = jiffies+HZ; 		add_timer(&ltpc_timer);		while(del_timer(&ltpc_timer) && time_after(timeout, jiffies))		{			add_timer(&ltpc_timer);			schedule();		}	}	if(debug&DEBUG_VERBOSE) printk("freeing dma\n");	if(dev_ltpc.dma) {		free_dma(dev_ltpc.dma);		dev_ltpc.dma = 0;	}	if(debug&DEBUG_VERBOSE) printk("freeing ioaddr\n");	if(dev_ltpc.base_addr) {		release_region(dev_ltpc.base_addr,8);		dev_ltpc.base_addr = 0;	}	if(debug&DEBUG_VERBOSE) printk("free_pages\n");	free_pages( (unsigned long) ltdmabuf, get_order(1000));	ltdmabuf=NULL;	ltdmacbuf=NULL;	if(debug&DEBUG_VERBOSE) printk("unregister_netdev\n");	unregister_netdev(&dev_ltpc);	if(debug&DEBUG_VERBOSE) printk("returning from cleanup_module\n");}module_exit(ltpc_cleanup);

⌨️ 快捷键说明

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