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

📄 8253xchr.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- linux-c -*- *//*  * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * **/#include <linux/module.h>#include <linux/kernel.h>#include <linux/pci.h>#include <linux/stddef.h>#include <linux/string.h>#include <linux/sockios.h>#include <asm/io.h>#include <asm/byteorder.h>#include <asm/pgtable.h>#include <linux/skbuff.h>#include <linux/if_arp.h>#include <linux/fs.h>#include <linux/sched.h>#include <asm/uaccess.h>#include <linux/version.h>#include <linux/etherdevice.h>#include <linux/poll.h>#include "Reg9050.h"#include "8253xctl.h"#include "ring.h"#include "8253x.h"#include "crc32dcl.h"/* a raw character driver  -- theoretically for implementing custom protocols, * async interrupts can be used for getting indication that a packet has * been successfully transmitted. */				/* the application read routine, can block according */				/* to flag, returns one packet at a time */int sab8253xc_read(struct file *filep, char *cptr, size_t cnt, loff_t *loffp){	unsigned int length;	unsigned long flags;	SAB_PORT *port = filep->private_data;	struct sk_buff *skb;		DEBUGPRINT((KERN_ALERT "Attempting to read %i bytes.\n", cnt));			if(port->sab8253xc_rcvbuflist == NULL)	{		return -ENOMEM;	}		save_flags(flags); cli();  	if(skb_queue_len(port->sab8253xc_rcvbuflist) == 0)	{		port->rx_empty = 1;		if(filep->f_flags & O_NONBLOCK)		{			restore_flags(flags);			return -EAGAIN;		}		restore_flags(flags);		interruptible_sleep_on(&port->read_wait);	}	else	{		restore_flags(flags);	}		skb = skb_peek(port->sab8253xc_rcvbuflist);	length = skb->tail - skb->data;	if(cnt < length)	{		return -ENOMEM;	}		skb = skb_dequeue(port->sab8253xc_rcvbuflist);		save_flags(flags); cli();  	if(skb_queue_len(port->sab8253xc_rcvbuflist) <= 0)	{		port->rx_empty = 1;	}	restore_flags(flags);		DEBUGPRINT((KERN_ALERT "Copying to user space %s.\n", skb->data));	copy_to_user(cptr, skb->data, length);	dev_kfree_skb_any(skb);	return length;}/* application write */int sab8253xc_write(struct file *filep, const char *cptr, size_t cnt, loff_t *loffp){	struct sk_buff *skb;	unsigned long flags;	SAB_PORT *port = filep->private_data;		if(cnt > sab8253xc_rbufsize)	/* should not send bigger than can be received */	{		return -ENOMEM;	}		if(port->active2.transmit == NULL)	{		return -ENOMEM;	}		save_flags(flags); cli();	/* can block on write when */	/* no space in transmit circular */	/* array. */	if((port->active2.transmit->Count & OWNER) == OWN_SAB)	{		++(port->Counters.tx_drops);		port->tx_full = 1;		restore_flags(flags);		if(filep->f_flags & O_NONBLOCK)		{			return -EAGAIN;		}		interruptible_sleep_on(&port->write_wait);	}	else	{		restore_flags(flags);	}	#ifndef FREEINTERRUPT	if((port->active2.transmit->HostVaddr != NULL) || /* not OWN_SAB from above */	   (port->active2.transmit->crcindex != 0))	{		register RING_DESCRIPTOR *freeme;				freeme = port->active2.transmit;		do		{			if((freeme->crcindex == 0) && (freeme->HostVaddr == NULL))			{				break;			}			if(freeme->HostVaddr)			{				skb_unlink((struct sk_buff*)freeme->HostVaddr);				dev_kfree_skb_any((struct sk_buff*)freeme->HostVaddr);				freeme->HostVaddr = NULL;			}			freeme->sendcrc = 0;			freeme->crcindex = 0;			freeme = (RING_DESCRIPTOR*) freeme->VNext;		}		while((freeme->Count & OWNER) != OWN_SAB);	}#endif		skb = alloc_skb(cnt, GFP_KERNEL); /* not called from int as with tty */	if(skb == NULL)	{		return -ENOMEM;	}	copy_from_user(skb->data, cptr, cnt);	skb->tail = (skb->data + cnt);	skb->len = cnt;	skb->data_len = cnt;		skb_queue_head(port->sab8253xbuflist, skb);	port->active2.transmit->HostVaddr = skb;	port->active2.transmit->sendcrc = 0;	port->active2.transmit->crcindex = 0;	port->active2.transmit->Count = (OWN_SAB|cnt); /* must be this order */	port->active2.transmit = 		(RING_DESCRIPTOR*) port->active2.transmit->VNext;	port->Counters.transmitbytes += cnt;	sab8253x_start_txS(port);	return cnt;}static void sab8253x_receive_charsC(struct sab_port *port,				    union sab8253x_irq_status *stat){	unsigned char buf[32];	int free_fifo = 0;	int reset_fifo = 0;	int msg_done = 0;	int msg_bad = 0;	int count = 0;	int total_size = 0;	int rstatus = 0;	struct sk_buff *skb;		/* Read number of BYTES (Character + Status) available. */		if((stat->images[ISR1_IDX] & SAB82532_ISR1_RDO) || (stat->images[ISR0_IDX] & SAB82532_ISR0_RFO) )	{		++msg_bad;		++free_fifo;		++reset_fifo;	}	else	{		if (stat->images[ISR0_IDX] & SAB82532_ISR0_RPF) 		{			count = port->recv_fifo_size;			++free_fifo;		}				if (stat->images[ISR0_IDX] & SAB82532_ISR0_RME) 		{			count = READB(port, rbcl);			count &= (port->recv_fifo_size - 1);			++msg_done;			++free_fifo;						total_size = READB(port, rbch);			if(total_size & SAB82532_RBCH_OV) /* need to revisit for 4096 byte frames */			{				msg_bad++;			}						rstatus = READB(port, rsta);			if((rstatus & SAB82532_RSTA_VFR) == 0)			{				msg_bad++;			}			if(rstatus & SAB82532_RSTA_RDO)			{				msg_bad++;			}			if((rstatus & SAB82532_RSTA_CRC) == 0)			{				msg_bad++;			}			if(rstatus & SAB82532_RSTA_RAB)			{				msg_bad++;			}		}	}		/* Read the FIFO. */		(*port->readfifo)(port, buf, count);			/* Issue Receive Message Complete command. */		if (free_fifo) 	{		sab8253x_cec_wait(port);		WRITEB(port, cmdr, SAB82532_CMDR_RMC);	}		if(reset_fifo)	{		sab8253x_cec_wait(port);		WRITEB(port, cmdr, SAB82532_CMDR_RHR);	}		if(msg_bad)	{		port->msgbufindex = 0;		return;	}		memcpy(&port->msgbuf[port->msgbufindex], buf, count);	port->msgbufindex += count;		if(msg_done)	{				if(port->msgbufindex <= 3) /* min is 1 char + 2 CRC + status byte */		{			port->msgbufindex = 0;			return;		}				total_size = port->msgbufindex - 3; /* strip off the crc16 and the status byte */		port->msgbufindex = 0;				/* ignore the receive buffer waiting -- we know the correct size here */				if(skb = dev_alloc_skb(total_size), skb)		{			memcpy(skb->data, &port->msgbuf[0], total_size);			skb->tail = (skb->data + total_size);			skb->data_len = total_size;			skb->len = total_size;			skb_queue_tail(port->sab8253xc_rcvbuflist, skb);			if(port->rx_empty)			{				port->rx_empty = 0;				wake_up_interruptible(&port->read_wait);			}			if(port->async_queue)			{				kill_fasync(&port->async_queue, SIGIO, POLL_IN);			}		}	}}static void sab8253x_check_statusC(struct sab_port *port,				   union sab8253x_irq_status *stat){	int modem_change = 0;	mctlsig_t         *sig;		if (stat->images[ISR0_IDX] & SAB82532_ISR0_RFO) 	{		port->icount.buf_overrun++;	}		/* Checking DCD */	sig = &port->dcd;	if (stat->images[sig->irq] & sig->irqmask) 	{		sig->val = ISON(port,dcd);		port->icount.dcd++;		modem_change++;	}	/* Checking CTS */	sig = &port->cts;	if (stat->images[sig->irq] & sig->irqmask) 	{		sig->val = ISON(port,cts);		port->icount.cts++;		modem_change++;	}	/* Checking DSR */	sig = &port->dsr;	if (stat->images[sig->irq] & sig->irqmask) 	{		sig->val = ISON(port,dsr);		port->icount.dsr++;		modem_change++;	}	if (modem_change)	{		wake_up_interruptible(&port->delta_msr_wait);	}		sig = &port->dcd;	if ((port->flags & FLAG8253X_CHECK_CD) &&	    (stat->images[sig->irq] & sig->irqmask)) 	{				if (sig->val)		{			wake_up_interruptible(&port->open_wait); /* in case waiting in block_til_ready */		}		else if (!((port->flags & FLAG8253X_CALLOUT_ACTIVE) &&			   (port->flags & FLAG8253X_CALLOUT_NOHUP))) 		{			/* I think the code needs to walk through all the proces that have opened this			 * port and send a SIGHUP to them -- need to investigate somewhat more*/		}	}}static int sab8253x_startupC(struct sab_port *port){	unsigned long flags;	int retval = 0;		save_flags(flags); cli();		if (port->flags & FLAG8253X_INITIALIZED) 	{		goto errout;	}		if (!port->regs) 	{		retval = -ENODEV;		goto errout;	}

⌨️ 快捷键说明

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