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

📄 8253xtty.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* 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 |			/* SAB82532_ISR0_TIME |*/			SAB82532_ISR0_TCD ;		save_flags(flags); 	cli();	sab8253x_cec_wait(port);	sab8253x_tec_wait(port);	WRITEB(port,dafo,dafo);	WRITEB(port,bgr,ebrg);	ccr2 |= READB(port,ccr2) & ~(0xc0);	WRITEB(port,ccr2,ccr2);	ccr4 |= READB(port,ccr4) & ~(SAB82532_CCR4_EBRG);	WRITEB(port,ccr4,ccr4);		if (port->flags & FLAG8253X_CTS_FLOW) 	{		mode = READB(port,mode) & ~(SAB82532_MODE_RTS);		mode |= SAB82532_MODE_FRTS;		mode  &= ~(SAB82532_MODE_FCTS);	} 	else 	{		mode = READB(port,mode) & ~(SAB82532_MODE_FRTS);		mode |= SAB82532_MODE_RTS;		mode |= SAB82532_MODE_FCTS;	}	WRITEB(port,mode,mode);	mode |= SAB82532_MODE_RAC;	WRITEB(port,mode,mode);	restore_flags(flags);}static void sab8253x_flush_chars(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)	{		return;	}		sab8253x_start_tx(port);}static int sab8253x_write(struct tty_struct * tty, int from_user,		   const unsigned char *buf, int count){	struct sab_port *port = (struct sab_port *)tty->driver_data;	struct sk_buff *skb = NULL;	int truelength = 0;	int do_queue = 1;		if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_write"))	{		return 0;	}		if(count == 0)	{		return 0;	}		if(port->active2.transmit == NULL)	{		return 0;	}		if((port->active2.transmit->Count & OWNER) == OWN_SAB)	{		sab8253x_start_tx(port);		return 0;	}	#ifndef FREEININTERRUPT	skb = port->active2.transmit->HostVaddr; /* current slot value */		if(port->buffergreedy == 0)	/* are we avoiding buffer free's */	{				/* no */		if((skb != 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);		}		skb = NULL;		/* buffer was freed */	}		if(skb != NULL)		/* potentially useful */	{		truelength = (skb->end - skb->head);		if(truelength >= count)		{			skb->data = skb->head; /* this buffer is already queued */			skb->tail = skb->head;			do_queue = 0;		}		else		{			skb_unlink(skb);			dev_kfree_skb_any(skb);			skb = NULL;			port->active2.transmit->HostVaddr = NULL;		}	}	/* in all cases the following is allowed */	port->active2.transmit->sendcrc = 0;	port->active2.transmit->crcindex = 0;#endif		if(skb == NULL)	{		if(port->DoingInterrupt)		{			skb = alloc_skb(count, GFP_ATOMIC);		}		else		{			skb = alloc_skb(count, GFP_KERNEL);		}	}		if(skb == NULL)	{		printk(KERN_ALERT "sab8253xt: no skbuffs available.\n");		return 0;	}	if(from_user)	{		copy_from_user(skb->data, buf, count);	}	else	{		memcpy(skb->data, buf, count);	}	skb->tail = (skb->data + count);	skb->data_len = count;	skb->len = count;		if(do_queue)	{		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|count);	port->active2.transmit = port->active2.transmit->VNext;		sab8253x_start_tx(port);	return count;}static int sab8253x_write_room(struct tty_struct *tty){	struct sab_port *port = (struct sab_port *)tty->driver_data;		if(sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_write_room"))	{		return 0;	}		if(port->active2.transmit == NULL)	{		return 0;	}		if((port->active2.transmit->Count & OWNER) == OWN_SAB)	{		return 0;	}	return ((sab8253xt_rbufsize) * /* really should not send buffs bigger than 32 I guess */		(sab8253xt_listsize - 		 Sab8253xCountTransmitDescriptors(port)));}static int sab8253x_chars_in_buffer(struct tty_struct *tty){	struct sab_port *port = (struct sab_port *)tty->driver_data;		if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_chars_in_bufferS"))	{		return 0;	}		return Sab8253xCountTransmit(port);}/* * This function is used to send a high-priority XON/XOFF character to * the device */static void sab8253x_send_xchar(struct tty_struct *tty, char ch){	struct sab_port *port = (struct sab_port *)tty->driver_data;	unsigned long flags;		if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_send_xchar"))	{		return;	}		save_flags(flags); 	cli();	sab8253x_tec_wait(port);	WRITEB(port, tic, ch);	restore_flags(flags);}/* * ------------------------------------------------------------ * sab8253x_throttle() *  * This routine is called by the upper-layer tty layer to signal that * incoming characters should be throttled. * ------------------------------------------------------------ */static void sab8253x_throttle(struct tty_struct * tty){	struct sab_port *port = (struct sab_port *)tty->driver_data;		if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_throttle"))	{		return;	}		if (I_IXOFF(tty))	{		sab8253x_send_xchar(tty, STOP_CHAR(tty));	}}static void sab8253x_unthrottle(struct tty_struct * tty){	struct sab_port *port = (struct sab_port *)tty->driver_data;		if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_unthrottle"))	{		return;	}		if (I_IXOFF(tty)) 	{		if (port->x_char)		{			port->x_char = 0;		}		else		{			sab8253x_send_xchar(tty, START_CHAR(tty));		}	}}/* * ------------------------------------------------------------ * sab8253x_ioctl() and friends * ------------------------------------------------------------ */static int sab8253x_get_serial_info(struct sab_port *port,			     struct serial_struct *retinfo){	struct serial_struct tmp;		if (!retinfo)	{		return -EFAULT;	}	memset(&tmp, 0, sizeof(tmp));	tmp.type = port->type;	tmp.line = port->line;	tmp.port = (unsigned long)port->regs;	tmp.irq = port->irq;	tmp.flags = port->flags;	tmp.xmit_fifo_size = port->xmit_fifo_size;	tmp.baud_base = 0;	tmp.close_delay = port->close_delay;	tmp.closing_wait = port->closing_wait;	tmp.custom_divisor = port->custom_divisor;	tmp.hub6 = 0;	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))	{		return -EFAULT;	}	return 0;}static int sab8253x_set_serial_info(struct sab_port *port,			     struct serial_struct *new_info){	return 0;}/* * get_lsr_info - get line status register info * * Purpose: Let user call ioctl() to get info when the UART physically * 	    is emptied.  On bus types like RS485, the transmitter must * 	    release the bus after transmitting. This must be done when * 	    the transmit shift register is empty, not be done when the * 	    transmit holding register is empty.  This functionality * 	    allows an RS485 driver to be written in user space.  */static int sab8253x_get_lsr_info(struct sab_port * port, unsigned int *value){	unsigned int result;		result = (((Sab8253xCountTransmit(port) <= 0) && port->all_sent) ? TIOCSER_TEMT : 0);	return put_user(result, value);}static int sab8253x_get_modem_info(struct sab_port * port, unsigned int *value){	unsigned int result;		/* Using the cached values !! After all when changed int occurs	   and the cache is updated */	result=  		((port->dtr.val) ? TIOCM_DTR : 0)		| ((port->rts.val) ? TIOCM_RTS : 0)		| ((port->cts.val) ? TIOCM_CTS : 0)		| ((port->dsr.val) ? TIOCM_DSR : 0)		| ((port->dcd.val) ? TIOCM_CAR : 0);		return put_user(result,value);}static int sab8253x_set_modem_info(struct sab_port * port, unsigned int cmd,				   unsigned int *value){	int error;	unsigned int arg;	unsigned long flags;		error = get_user(arg, value);	if (error)	{		return error;	}		save_flags(flags);	cli();	switch (cmd) 	{	case TIOCMBIS: 		if (arg & TIOCM_RTS) 		{			RAISE(port, rts);		}		if (arg & TIOCM_DTR) 		{			RAISE(port, dtr);		}		break;	case TIOCMBIC:		if (arg & TIOCM_RTS) 		{			LOWER(port,rts);		}		if (arg & TIOCM_DTR) 		{			LOWER(port,dtr);		}		break;	case TIOCMSET:		if (arg & TIOCM_RTS) 		{			RAISE(port, rts);		} 		else 		{			LOWER(port,rts);		}		if (arg & TIOCM_DTR) 		{			RAISE(port, dtr);		} 

⌨️ 快捷键说明

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