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

📄 ltpc.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		printk("ltpc_hard_header called for device %s\n",			dev->name);	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 */	/* poll 20 times per second */	idle(dev);	ltpc_timer.expires = jiffies + HZ/20;		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){	int want = (dma == 3) ? 2 : (dma == 1) ? 1 : 3;  	unsigned long timeout;  	unsigned long f;    	if (want & 1) {		if (request_dma(1,"ltpc")) {			want &= ~1;		} else {			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);		}	}	if (want & 2) {		if (request_dma(3,"ltpc")) {			want &= ~2;		} else {			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);		}	}	/* 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 ((want & 2) && (get_dma_residue(3)==sizeof(struct lt_mem))) {		want &= ~2;		free_dma(3);	}	if ((want & 1) && (get_dma_residue(1)==sizeof(struct lt_mem))) {		want &= ~1;		free_dma(1);	}	if (!want)		return 0;	return (want & 2) ? 3 : 1;}struct net_device * __init ltpc_probe(void){	struct net_device *dev;	int err = -ENOMEM;	int x=0,y=0;	int autoirq;	unsigned long f;	unsigned long timeout;	dev = alloc_ltalkdev(sizeof(struct ltpc_private));	if (!dev)		goto out;	SET_MODULE_OWNER(dev);	/* probe for the I/O port address */		if (io != 0x240 && request_region(0x220,8,"ltpc")) {		x = inb_p(0x220+6);		if ( (x!=0xff) && (x>=0xf0) ) {			io = 0x220;			goto got_port;		}		release_region(0x220,8);	}	if (io != 0x220 && request_region(0x240,8,"ltpc")) {		y = inb_p(0x240+6);		if ( (y!=0xff) && (y>=0xf0) ){ 			io = 0x240;			goto got_port;		}		release_region(0x240,8);	} 	/* give up in despair */	printk(KERN_ERR "LocalTalk card not found; 220 = %02x, 240 = %02x.\n", x,y);	err = -ENODEV;	goto out1; got_port:	/* probe for the IRQ line */	if (irq < 2) {		unsigned long irq_mask;		irq_mask = probe_irq_on();		/* reset the interrupt line */		inb_p(io+7);		inb_p(io+7);		/* trigger an interrupt (I hope) */		inb_p(io+6);		mdelay(2);		autoirq = probe_irq_off(irq_mask);		if (autoirq == 0) {			printk(KERN_ERR "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) {		printk(KERN_ERR "ltpc: mem alloc failed\n");		err = -ENOMEM;		goto out2;	}	ltdmacbuf = &ltdmabuf[800];	if(debug & DEBUG_VERBOSE) {		printk("ltdmabuf pointer %08lx\n",(unsigned long) ltdmabuf);	}	/* reset the card */	inb_p(io+1);	inb_p(io+3);	msleep(20);	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 */	ssleep(1);		/* 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... */	dma = ltpc_probe_dma(io, dma);	if (!dma) {  /* no dma channel */		printk(KERN_ERR "No DMA channel found on ltpc card.\n");		err = -ENODEV;		goto out3;	}	/* print out friendly message */	if(irq)		printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, IR%d, DMA%d.\n",io,irq,dma);	else		printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, DMA%d.  Using polled mode.\n",io,dma);	/* Fill in the fields of the device structure with ethernet-generic values. */	dev->hard_start_xmit = ltpc_xmit;	dev->hard_header = ltpc_hard_header;	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;	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;		schedule();	}	if(debug & DEBUG_VERBOSE) {		printk("setting up timer and irq\n");	}	/* grab it and don't let go :-) */	if (irq && request_irq( irq, &ltpc_interrupt, 0, "ltpc", dev) >= 0)	{		(void) inb_p(io+7);  /* enable interrupts from board */		(void) inb_p(io+7);  /* and reset irq line */	} else {		if( irq )			printk(KERN_ERR "ltpc: IRQ already in use, using polled mode.\n");		dev->irq = 0;		/* 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 + HZ/20;		add_timer(&ltpc_timer);	}	err = register_netdev(dev);	if (err)		goto out4;	return NULL;out4:	del_timer_sync(&ltpc_timer);	if (dev->irq)		free_irq(dev->irq, dev);out3:	free_pages((unsigned long)ltdmabuf, get_order(1000));out2:	release_region(io, 8);out1:	free_netdev(dev);out:	return ERR_PTR(err);}#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_param(debug, int, 0);module_param(io, int, 0);module_param(irq, int, 0);module_param(dma, int, 0);int __init init_module(void){        if(io == 0)		printk(KERN_NOTICE		       "ltpc: Autoprobing is not recommended for modules\n");	dev_ltpc = ltpc_probe();	if (IS_ERR(dev_ltpc))		return PTR_ERR(dev_ltpc);	return 0;}#endifstatic void __exit ltpc_cleanup(void){	if(debug & DEBUG_VERBOSE) printk("unregister_netdev\n");	unregister_netdev(dev_ltpc);	ltpc_timer.data = 0;  /* signal the poll routine that we're done */	del_timer_sync(&ltpc_timer);	if(debug & DEBUG_VERBOSE) printk("freeing irq\n");	if (dev_ltpc->irq)		free_irq(dev_ltpc->irq, dev_ltpc);	if(debug & DEBUG_VERBOSE) printk("freeing dma\n");	if (dev_ltpc->dma)		free_dma(dev_ltpc->dma);	if(debug & DEBUG_VERBOSE) printk("freeing ioaddr\n");	if (dev_ltpc->base_addr)		release_region(dev_ltpc->base_addr,8);	free_netdev(dev_ltpc);	if(debug & DEBUG_VERBOSE) printk("free_pages\n");	free_pages( (unsigned long) ltdmabuf, get_order(1000));	if(debug & DEBUG_VERBOSE) printk("returning from cleanup_module\n");}module_exit(ltpc_cleanup);

⌨️ 快捷键说明

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