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

📄 ltpc.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
			get_dma_residue(dev->dma) );		release_dma_lock(flags);	}}static void handleread(struct net_device *dev){	/* on entry, 0xfb */	/* on exit, 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_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,0xfb) ) printk("timed out in handleread\n");}static void handlecommand(struct net_device *dev){	/* on entry, 0xfa and ltdmacbuf holds command */	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(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,0xfa) ) printk("timed out in handlecommand\n");} /* ready made command for getting the result from the card */static unsigned char rescbuf[2] = {LT_GETRESULT,0};static unsigned char resdbuf[2];static int QInIdle;/* idle expects to be called with the IRQ line high -- either because of * an interrupt, or because the line is tri-stated */static void idle(struct net_device *dev){	unsigned long flags;	int state;	/* FIXME This is initialized to shut the warning up, but I need to	 * think this through again.	 */	struct xmitQel *q = NULL;	int oops;	int i;	int base = dev->base_addr;	spin_lock_irqsave(&txqueue_lock, flags);	if(QInIdle) {		spin_unlock_irqrestore(&txqueue_lock, flags);		return;	}	QInIdle = 1;	spin_unlock_irqrestore(&txqueue_lock, flags);	/* this tri-states the IRQ line */	(void) inb_p(base+6);	oops = 100;loop:	if (0>oops--) { 		printk("idle: looped too many times\n");		goto done;	}	state = inb_p(base+6);	if (state != inb_p(base+6)) goto loop;	switch(state) {		case 0xfc:			/* incoming command */			if (debug & DEBUG_LOWER) printk("idle: fc\n");			handlefc(dev); 			break;		case 0xfd:			/* incoming data */			if(debug & DEBUG_LOWER) printk("idle: fd\n");			handlefd(dev); 			break;		case 0xf9:			/* result ready */			if (debug & DEBUG_LOWER) printk("idle: f9\n");			if(!mboxinuse[0]) {				mboxinuse[0] = 1;				qels[0].cbuf = rescbuf;				qels[0].cbuflen = 2;				qels[0].dbuf = resdbuf;				qels[0].dbuflen = 2;				qels[0].QWrite = 0;				qels[0].mailbox = 0;				enQ(&qels[0]);			}			inb_p(dev->base_addr+1);			inb_p(dev->base_addr+0);			if( wait_timeout(dev,0xf9) )				printk("timed out idle f9\n");			break;		case 0xf8:			/* ?? */			if (xmQhd) {				inb_p(dev->base_addr+1);				inb_p(dev->base_addr+0);				if(wait_timeout(dev,0xf8) )					printk("timed out idle f8\n");			} else {				goto done;			}			break;		case 0xfa:			/* waiting for command */			if(debug & DEBUG_LOWER) printk("idle: fa\n");			if (xmQhd) {				q=deQ();				memcpy(ltdmacbuf,q->cbuf,q->cbuflen);				ltdmacbuf[1] = q->mailbox;				if (debug>1) { 					int n;					printk("ltpc: sent command     ");					n = q->cbuflen;					if (n>100) n=100;					for(i=0;i<n;i++)						printk("%02x ",ltdmacbuf[i]);					printk("\n");				}				handlecommand(dev);					if(0xfa==inb_p(base+6)) {						/* we timed out, so return */						goto done;					} 			} else {				/* we don't seem to have a command */				if (!mboxinuse[0]) {					mboxinuse[0] = 1;					qels[0].cbuf = rescbuf;					qels[0].cbuflen = 2;					qels[0].dbuf = resdbuf;					qels[0].dbuflen = 2;					qels[0].QWrite = 0;					qels[0].mailbox = 0;					enQ(&qels[0]);				} else {					printk("trouble: response command already queued\n");					goto done;				}			} 			break;		case 0Xfb:			/* data transfer ready */			if(debug & DEBUG_LOWER) printk("idle: fb\n");			if(q->QWrite) {				memcpy(ltdmabuf,q->dbuf,q->dbuflen);				handlewrite(dev);			} else {				handleread(dev);				/* non-zero mailbox numbers are for				   commmands, 0 is for GETRESULT				   requests */				if(q->mailbox) {					memcpy(q->dbuf,ltdmabuf,q->dbuflen);				} else { 					/* this was a result */					mailbox[ 0x0f & ltdmabuf[0] ] = ltdmabuf[1];					mboxinuse[0]=0;				}			}			break;	}	goto loop;done:	QInIdle=0;	/* now set the interrupts back as appropriate */	/* the first read takes it out of tri-state (but still high) */	/* the second resets it */	/* note that after this point, any read of base+6 will	   trigger an interrupt */	if (dev->irq) {		inb_p(base+7);		inb_p(base+7);	}	return;}static int do_write(struct net_device *dev, void *cbuf, int cbuflen,	void *dbuf, int dbuflen){	int i = getmbox();	int ret;	if(i) {		qels[i].cbuf = (unsigned char *) cbuf;		qels[i].cbuflen = cbuflen;		qels[i].dbuf = (unsigned char *) dbuf;		qels[i].dbuflen = dbuflen;		qels[i].QWrite = 1;		qels[i].mailbox = i;  /* this should be initted rather */		enQ(&qels[i]);		idle(dev);		ret = mailbox[i];		mboxinuse[i]=0;		return ret;	}	printk("ltpc: could not allocate mbox\n");	return -1;}static int do_read(struct net_device *dev, void *cbuf, int cbuflen,	void *dbuf, int dbuflen){	int i = getmbox();	int ret;	if(i) {		qels[i].cbuf = (unsigned char *) cbuf;		qels[i].cbuflen = cbuflen;		qels[i].dbuf = (unsigned char *) dbuf;		qels[i].dbuflen = dbuflen;		qels[i].QWrite = 0;		qels[i].mailbox = i;  /* this should be initted rather */		enQ(&qels[i]);		idle(dev);		ret = mailbox[i];		mboxinuse[i]=0;		return ret;	}	printk("ltpc: could not allocate mbox\n");	return -1;}/* end of idle handlers -- what should be seen is do_read, do_write */static struct timer_list ltpc_timer;static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev);static struct net_device_stats *ltpc_get_stats(struct net_device *dev);static int read_30 ( struct net_device *dev){	lt_command c;	c.getflags.command = LT_GETFLAGS;	return do_read(dev, &c, sizeof(c.getflags),&c,0);}static int set_30 (struct net_device *dev,int x){	lt_command c;	c.setflags.command = LT_SETFLAGS;	c.setflags.flags = x;	return do_write(dev, &c, sizeof(c.setflags),&c,0);}/* LLAP to DDP translation */static int sendup_buffer (struct net_device *dev){	/* on entry, command is in ltdmacbuf, data in ltdmabuf */	/* called from idle, non-reentrant */	int dnode, snode, llaptype, len; 	int sklen;	struct sk_buff *skb;	struct net_device_stats *stats = &((struct ltpc_private *)dev->priv)->stats;	struct lt_rcvlap *ltc = (struct lt_rcvlap *) ltdmacbuf;	if (ltc->command != LT_RCVLAP) {		printk("unknown command 0x%02x from ltpc card\n",ltc->command);		return(-1);	}	dnode = ltc->dnode;	snode = ltc->snode;	llaptype = ltc->laptype;	len = ltc->length; 	sklen = len;	if (llaptype == 1) 		sklen += 8;  /* correct for short ddp */	if(sklen > 800) {		printk(KERN_INFO "%s: nonsense length in ltpc command 0x14: 0x%08x\n",			dev->name,sklen);		return -1;	}	if ( (llaptype==0) || (llaptype>2) ) {		printk(KERN_INFO "%s: unknown LLAP type: %d\n",dev->name,llaptype);		return -1;	}	skb = dev_alloc_skb(3+sklen);	if (skb == NULL) 	{		printk("%s: dropping packet due to memory squeeze.\n",			dev->name);		return -1;	}	skb->dev = dev;	if (sklen > len)		skb_reserve(skb,8);	skb_put(skb,len+3);	skb->protocol = htons(ETH_P_LOCALTALK);	/* add LLAP header */	skb->data[0] = dnode;	skb->data[1] = snode;	skb->data[2] = llaptype;	skb->mac.raw = skb->data;	/* save pointer to llap header */	skb_pull(skb,3);	/* copy ddp(s,e)hdr + contents */	memcpy(skb->data,(void*)ltdmabuf,len);	skb->h.raw = skb->data;	stats->rx_packets++;	stats->rx_bytes+=skb->len;	/* toss it onwards */	netif_rx(skb);	dev->last_rx = jiffies;	return 0;}/* the handler for the board interrupt */ static irqreturn_tltpc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr){	struct net_device *dev = dev_id;	if (dev==NULL) {		printk("ltpc_interrupt: unknown device.\n");		return IRQ_NONE;	}	inb_p(dev->base_addr+6);  /* disable further interrupts from board */	idle(dev); /* handle whatever is coming in */ 	/* idle re-enables interrupts from board */ 	return IRQ_HANDLED;}/*** * *    The ioctls that the driver responds to are: * *    SIOCSIFADDR -- do probe using the passed node hint. *    SIOCGIFADDR -- return net, node. * *    some of this stuff should be done elsewhere. * ***/static int ltpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){	struct sockaddr_at *sa = (struct sockaddr_at *) &ifr->ifr_addr;	/* we'll keep the localtalk node address in dev->pa_addr */	struct atalk_addr *aa = &((struct ltpc_private *)dev->priv)->my_addr;	struct lt_init c;	int ltflags;	if(debug & DEBUG_VERBOSE) printk("ltpc_ioctl called\n");	switch(cmd) {		case SIOCSIFADDR:			aa->s_net  = sa->sat_addr.s_net;      			/* this does the probe and returns the node addr */			c.command = LT_INIT;			c.hint = sa->sat_addr.s_node;			aa->s_node = do_read(dev,&c,sizeof(c),&c,0);			/* get all llap frames raw */			ltflags = read_30(dev);			ltflags |= LT_FLAG_ALLLAP;			set_30 (dev,ltflags);  			dev->broadcast[0] = 0xFF;			dev->dev_addr[0] = aa->s_node;			dev->addr_len=1;   			return 0;		case SIOCGIFADDR:			sa->sat_addr.s_net = aa->s_net;			sa->sat_addr.s_node = aa->s_node;			return 0;		default: 			return -EINVAL;	}}static void set_multicast_list(struct net_device *dev){	/* This needs to be present to keep netatalk happy. */	/* Actually netatalk needs fixing! */}static int ltpc_hard_header (struct sk_buff *skb, struct net_device *dev, 	unsigned short type, void *daddr, void *saddr, unsigned len){	if(debug & DEBUG_VERBOSE)

⌨️ 快捷键说明

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