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

📄 8253xsyn.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- linux-c -*- *//* $Id: 8253xsyn.c,v 1.17 2002/02/10 22:17:25 martillo Exp $ * 8253xsyn.c: SYNC TTY Driver for the SIEMENS SAB8253X DUSCC. * * Implementation, modifications and extensions * 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. *//* Standard in kernel modules */#define DEFINE_VARIABLE#include <linux/module.h>   /* Specifically, a module */#include <asm/io.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <linux/tty.h>#include <linux/tty_flip.h>#include <linux/mm.h>#include <linux/version.h>#include <asm/uaccess.h>#include "8253xctl.h"#include "8253x.h"#include <linux/pci.h>#include <linux/fs.h>#ifdef MODULE#undef XCONFIG_SERIAL_CONSOLE#endifstatic void sab8253x_flush_to_ldiscS(void *private_) /* need a separate version for sync						 there are no flags associated with						 received sync TTY data*/{	struct tty_struct *tty = (struct tty_struct *) private_;	unsigned char	*cp;	int		count;	struct sab_port *port;	struct sk_buff *skb;  		if(tty)	{		port = (struct sab_port *)tty->driver_data;	}	else	{		return;	}	if(port == NULL)	{		return;	}		if (test_bit(TTY_DONT_FLIP, &tty->flags)) 	{		queue_task(&tty->flip.tqueue, &tq_timer);		return;	}	/* note that a hangup may have occurred -- perhaps should check for that */	port->DoingInterrupt = 1;	while(port->sab8253xc_rcvbuflist && (skb_queue_len(port->sab8253xc_rcvbuflist) > 0))	{		skb = skb_dequeue(port->sab8253xc_rcvbuflist);		count = skb->data_len;		cp = skb->data;		(*tty->ldisc.receive_buf)(tty, cp, 0, count);		dev_kfree_skb_any(skb);	}	port->DoingInterrupt = 0;}void sab8253x_flush_charsS(struct tty_struct *tty){	struct sab_port *port = (struct sab_port *)tty->driver_data;		if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_flush_chars"))	{		return;	}		if ((Sab8253xCountTransmit(port) <= 0) || tty->stopped || tty->hw_stopped)	{				/* can't flush */		return;	}		sab8253x_start_txS(port);}/* * ------------------------------------------------------------ * sab8253x_stopS() and sab8253x_startS() * * This routines are called before setting or resetting tty->stopped. * They enable or disable transmitter interrupts, as necessary. * ------------------------------------------------------------ */void sab8253x_stopS(struct tty_struct *tty){	struct sab_port *port = (struct sab_port *)tty->driver_data;	/* can't do anything here */	if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_stop"))	{		return;	}	/*  interrupt handles it all*/	/* turning off XPR is not an option in sync mode */}void sab8253x_startS(struct tty_struct *tty){	struct sab_port *port = (struct sab_port *)tty->driver_data;		if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_start"))	{		return;	}	sab8253x_start_txS(port);}static void sab8253x_receive_charsS(struct sab_port *port,			     union sab8253x_irq_status *stat){	struct tty_struct *tty = port->tty;	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;	#ifdef CONSOLE_SUPPORT	if (port->is_console)	{		wake_up(&keypress_wait);	}#endif		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 (!tty)		{			return;		}		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);		}		queue_task(&tty->flip.tqueue, &tq_timer); /* clear out flip buffer as fast as possible							   * maybe should not be done unconditionally hear							   * but should be within the above consequence							   * clause */	}}static void sab8253x_check_statusS(struct sab_port *port,			    union sab8253x_irq_status *stat){	struct tty_struct *tty = port->tty;	int modem_change = 0;	mctlsig_t         *sig;		if (!tty)	{		return;	}		/* check_modem:*/	/* 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);		}		else if (!((port->flags & FLAG8253X_CALLOUT_ACTIVE) &&			   (port->flags & FLAG8253X_CALLOUT_NOHUP))) 		{#if 0				/* requires more investigation */			MOD_INC_USE_COUNT;			if (schedule_task(&port->tqueue_hangup) == 0)			{				MOD_DEC_USE_COUNT;			}#endif		}	}		sig = &port->cts;	if (port->flags & FLAG8253X_CTS_FLOW) 	{				/* not setting this yet */		if (port->tty->hw_stopped) 		{			if (sig->val) 			{				port->tty->hw_stopped = 0;				sab8253x_sched_event(port, SAB8253X_EVENT_WRITE_WAKEUP);				sab8253x_start_txS(port);			}		} 				else 		{			if(!(getccr2configS(port) & SAB82532_CCR2_TOE))			{				if (!(sig->val)) 				{					port->tty->hw_stopped = 1;				}			}		}	}}/* * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */static void sab8253x_change_speedS(struct sab_port *port){	unsigned long	flags,baud;	tcflag_t	cflag;	u8	        ccr2=0,ccr4=0,ebrg=0;	int		i, bits;#ifdef DEBUGGING	printk("Change speed!  ");#endif	if (!port->tty || !port->tty->termios) 	{#ifdef DEBUGGING		printk("NOT!\n");#endif		return;	}	#ifdef DEBUGGING	printk(" for real.\n");#endif		cflag = port->tty->termios->c_cflag;		/* Byte size and parity */	switch (cflag & CSIZE) 	{	case CS5: 		bits = 7; 		break;	case CS6: 		bits = 8; 		break;	case CS7: 		bits = 9; 		break;	default:	case CS8: 		bits = 10; 		break;	}		if (cflag & CSTOPB) 	{		bits++;	}		if (cflag & PARENB) 	{		bits++;	}		/* Determine EBRG values based on the "encoded"baud rate */	i = cflag & CBAUD;	switch(i)	{	case B0:		baud=0;		break;	case  B50:		baud=100;		break;	case  B75:		baud=150;		break;	case  B110:		baud=220;		break;	case  B134:		baud=269;		break;	case  B150:		baud=300;		break;	case  B200:		baud=400;		break;	case B300:		baud=600;		break;	case B600:		baud=1200;		break;	case B1200:		baud=2400;		break;	case B1800:		baud=3600;		break;	case B2400:		baud=4800;		break;	case B4800:		baud=9600;		break;	case B9600:		baud=19200;		break;	case B19200:		baud=38400;		break;	case  B38400:		if(port->custspeed)		{			baud=port->custspeed<<1;		}		else		{			baud=76800;		}		break;	case B57600:		baud=115200;		break;#ifdef SKIPTHIS	case B76800:		baud=153600;		break;	case B153600:		baud=307200;		break;#endif	case B230400:		baud=460800;		break;	case  B460800:		baud=921600;		break;	case B115200:	default:		baud=230400;		break;	}		if(!sab8253x_baud(port,baud,&ebrg,&ccr2,&ccr4,&(port->baud))) 	{		printk("Aurora Warning. baudrate %ld could not be set! Using 115200",baud);		baud=230400;		sab8253x_baud(port,baud,&ebrg,&ccr2,&ccr4,&(port->baud));	}		if (port->baud)		port->timeout = (port->xmit_fifo_size * HZ * bits) / port->baud;	else		port->timeout = 0;	port->timeout += HZ / 50;		/* Add .02 seconds of slop */		/* CTS flow control flags */	if (cflag & CRTSCTS)		port->flags |= FLAG8253X_CTS_FLOW;	else		port->flags &= ~(FLAG8253X_CTS_FLOW);		if (cflag & CLOCAL)		port->flags &= ~(FLAG8253X_CHECK_CD);	else		port->flags |= FLAG8253X_CHECK_CD;	if (port->tty)		port->tty->hw_stopped = 0;		/*	 * Set up parity check flag	 * XXX: not implemented, yet.	 */#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))		/*	 * Characters to ignore	 * XXX: not implemented, yet.	 */		/*	 * !!! ignore all characters if CREAD is not set	 * XXX: not implemented, yet.	 */	if ((cflag & CREAD) == 0)		port->ignore_status_mask |= SAB82532_ISR0_RPF;		save_flags(flags); 	cli();	sab8253x_cec_wait(port);		WRITEB(port, bgr, ebrg);	WRITEB(port, ccr2, READB(port, ccr2) & ~(0xc0)); /* clear out current baud rage */	WRITEB(port, ccr2, READB(port, ccr2) | ccr2);	WRITEB(port, ccr4, (READB(port,ccr4) & ~SAB82532_CCR4_EBRG) | ccr4);		if (port->flags & FLAG8253X_CTS_FLOW) 	{		WRITEB(port, mode, READB(port,mode) & ~(SAB82532_MODE_RTS));		port->interrupt_mask1 &= ~(SAB82532_IMR1_CSC);		WRITEB(port, imr1, port->interrupt_mask1);	} 	else 	{		WRITEB(port, mode, READB(port,mode) | SAB82532_MODE_RTS);		port->interrupt_mask1 |= SAB82532_IMR1_CSC;		WRITEB(port, imr1, port->interrupt_mask1);	}	WRITEB(port, mode, READB(port, mode) | SAB82532_MODE_RAC);	restore_flags(flags);}void sab8253x_set_termiosS(struct tty_struct *tty,			   struct termios *old_termios){	struct sab_port *port = (struct sab_port *)tty->driver_data;		if((tty->termios->c_cflag == old_termios->c_cflag) && 	   (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag)))	{		return;	}	if(!port)	{		return;	}	sab8253x_change_speedS(port);		/* Handle transition to B0 status */	if ((old_termios->c_cflag & CBAUD) &&	    !(tty->termios->c_cflag & CBAUD)) 	{		LOWER(port,rts);		LOWER(port,dtr);	}		/* Handle transition away from B0 status */	if (!(old_termios->c_cflag & CBAUD) &&	    (tty->termios->c_cflag & CBAUD)) 	{		RAISE(port,dtr);		if (!tty->hw_stopped ||		    !(tty->termios->c_cflag & CRTSCTS)) 		{			RAISE(port,rts);		}	}		/* Handle turning off CRTSCTS */	if ((old_termios->c_cflag & CRTSCTS) &&	    !(tty->termios->c_cflag & CRTSCTS)) 	{		tty->hw_stopped = 0;		sab8253x_startS(tty);	}}static int sab8253x_startupS(struct sab_port *port){	unsigned long flags;	int retval = 0;		save_flags(flags); cli();		port->msgbufindex = 0;	port->xmit_buf = NULL;	port->buffergreedy = 0;		if (port->flags & FLAG8253X_INITIALIZED) 	{		goto errout;	}		if (!port->regs) 	{		if (port->tty)		{			set_bit(TTY_IO_ERROR, &port->tty->flags);		}		retval = -ENODEV;		goto errout;	}	/*	 * Initialize the Hardware	 */	sab8253x_init_lineS(port);	#if 0				/* maybe should be conditional */	if (port->tty->termios->c_cflag & CBAUD) 	{#endif		/* Activate RTS */		RAISE(port,rts);		/* Activate DTR */		RAISE(port,dtr);#if 0	}#endif		/*	 * Initialize the modem signals values	 */	port->dcd.val=ISON(port,dcd);	port->cts.val=ISON(port,cts);	port->dsr.val=ISON(port,dsr);	/*	 * Finally, enable interrupts	 */		port->interrupt_mask0 = SAB82532_IMR0_RFS | SAB82532_IMR0_PCE |		SAB82532_IMR0_PLLA | SAB82532_IMR0_RSC | SAB82532_IMR0_CDSC;		/*((port->ccontrol.ccr2 & SAB82532_CCR2_TOE) ? SAB82532_IMR0_CDSC : 0); */		WRITEB(port,imr0,port->interrupt_mask0);	port->interrupt_mask1 = SAB82532_IMR1_EOP | SAB82532_IMR1_XMR |		SAB82532_IMR1_TIN | SAB82532_IMR1_XPR;	WRITEB(port, imr1, port->interrupt_mask1);	port->all_sent = 1;		if (port->tty)	{		clear_bit(TTY_IO_ERROR, &port->tty->flags);	}	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;		/*	 * and set the speed of the serial port	 */

⌨️ 快捷键说明

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