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

📄 serial.c

📁 In the ffuart.tar.gz it has one file. The serial.c is the source codes of the FFUART as a console
💻 C
📖 第 1 页 / 共 5 页
字号:
		}	}	return ret;}static int rs_write_room(struct tty_struct *tty){	struct async_struct *info = (struct async_struct *)tty->driver_data;	if (serial_paranoia_check(info, tty->device, "rs_write_room"))		return 0;	return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);}static int rs_chars_in_buffer(struct tty_struct *tty){	struct async_struct *info = (struct async_struct *)tty->driver_data;					if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))		return 0;	return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);}static void rs_flush_buffer(struct tty_struct *tty){	struct async_struct *info = (struct async_struct *)tty->driver_data;	unsigned long flags;		if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))		return;	save_flags(flags); cli();	info->xmit.head = info->xmit.tail = 0;	restore_flags(flags);	wake_up_interruptible(&tty->write_wait);#ifdef SERIAL_HAVE_POLL_WAIT	wake_up_interruptible(&tty->poll_wait);#endif	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&	    tty->ldisc.write_wakeup)		(tty->ldisc.write_wakeup)(tty);}/* * This function is used to send a high-priority XON/XOFF character to * the device */static void rs_send_xchar(struct tty_struct *tty, char ch){	struct async_struct *info = (struct async_struct *)tty->driver_data;	if (serial_paranoia_check(info, tty->device, "rs_send_char"))		return;	info->x_char = ch;	if (ch) {		/* Make sure transmit interrupts are on */		info->IER |= UART_IER_THRI;		serial_out(info, UART_IER, info->IER);		if (pxa_buggy_port(info->state->type))			rs_interrupt_single(info->state->irq, NULL, NULL);	}}/* * ------------------------------------------------------------ * rs_throttle() *  * This routine is called by the upper-layer tty layer to signal that * incoming characters should be throttled. * ------------------------------------------------------------ */static void rs_throttle(struct tty_struct * tty){	struct async_struct *info = (struct async_struct *)tty->driver_data;	unsigned long flags;#ifdef SERIAL_DEBUG_THROTTLE	char	buf[64];		printk("throttle %s: %d....\n", tty_name(tty, buf),	       tty->ldisc.chars_in_buffer(tty));#endif	if (serial_paranoia_check(info, tty->device, "rs_throttle"))		return;		if (I_IXOFF(tty))		rs_send_xchar(tty, STOP_CHAR(tty));	if (tty->termios->c_cflag & CRTSCTS)		info->MCR &= ~UART_MCR_RTS;	save_flags(flags); cli();	serial_out(info, UART_MCR, info->MCR);	restore_flags(flags);}static void rs_unthrottle(struct tty_struct * tty){	struct async_struct *info = (struct async_struct *)tty->driver_data;	unsigned long flags;#ifdef SERIAL_DEBUG_THROTTLE	char	buf[64];		printk("unthrottle %s: %d....\n", tty_name(tty, buf),	       tty->ldisc.chars_in_buffer(tty));#endif	if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))		return;		if (I_IXOFF(tty)) {		if (info->x_char)			info->x_char = 0;		else			rs_send_xchar(tty, START_CHAR(tty));	}	if (tty->termios->c_cflag & CRTSCTS)		info->MCR |= UART_MCR_RTS;	save_flags(flags); cli();	serial_out(info, UART_MCR, info->MCR);	restore_flags(flags);}/* * ------------------------------------------------------------ * rs_ioctl() and friends * ------------------------------------------------------------ */static int get_serial_info(struct async_struct * info,			   struct serial_struct * retinfo){	struct serial_struct tmp;	struct serial_state *state = info->state;   	if (!retinfo)		return -EFAULT;	memset(&tmp, 0, sizeof(tmp));	tmp.type = state->type;	tmp.line = state->line;	tmp.port = state->port;	if (HIGH_BITS_OFFSET)		tmp.port_high = state->port >> HIGH_BITS_OFFSET;	else		tmp.port_high = 0;	tmp.irq = state->irq;	tmp.flags = state->flags;	tmp.xmit_fifo_size = state->xmit_fifo_size;	tmp.baud_base = state->baud_base;	tmp.close_delay = state->close_delay;	tmp.closing_wait = state->closing_wait;	tmp.custom_divisor = state->custom_divisor;	tmp.hub6 = state->hub6;	tmp.io_type = state->io_type;	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))		return -EFAULT;	return 0;}static int set_serial_info(struct async_struct * info,			   struct serial_struct * new_info){	struct serial_struct new_serial; 	struct serial_state old_state, *state;	unsigned int		i,change_irq,change_port;	int 			retval = 0;	unsigned long		new_port;	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))		return -EFAULT;	state = info->state;	old_state = *state;	new_port = new_serial.port;	if (HIGH_BITS_OFFSET)		new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;	change_irq = new_serial.irq != state->irq;	change_port = (new_port != ((int) state->port)) ||		(new_serial.hub6 != state->hub6);  	if (!capable(CAP_SYS_ADMIN)) {		if (change_irq || change_port ||		    (new_serial.baud_base != state->baud_base) ||		    (new_serial.type != state->type) ||		    (new_serial.close_delay != state->close_delay) ||		    (new_serial.xmit_fifo_size != state->xmit_fifo_size) ||		    ((new_serial.flags & ~ASYNC_USR_MASK) !=		     (state->flags & ~ASYNC_USR_MASK)))			return -EPERM;		state->flags = ((state->flags & ~ASYNC_USR_MASK) |			       (new_serial.flags & ASYNC_USR_MASK));		info->flags = ((info->flags & ~ASYNC_USR_MASK) |			       (new_serial.flags & ASYNC_USR_MASK));		state->custom_divisor = new_serial.custom_divisor;		goto check_and_exit;	}	new_serial.irq = irq_cannonicalize(new_serial.irq);	if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) || 	    (new_serial.baud_base < 9600)|| (new_serial.type < PORT_UNKNOWN) ||	    (new_serial.type > PORT_MAX) || (new_serial.type == PORT_CIRRUS) ||	    (new_serial.type == PORT_STARTECH)) {		return -EINVAL;	}	if ((new_serial.type != state->type) ||	    (new_serial.xmit_fifo_size <= 0))		new_serial.xmit_fifo_size =			uart_config[new_serial.type].dfl_xmit_fifo_size;	/* Make sure address is not already in use */	if (new_serial.type) {		for (i = 0 ; i < NR_PORTS; i++)			if ((state != &rs_table[i]) &&			    (rs_table[i].port == new_port) &&			    rs_table[i].type)				return -EADDRINUSE;	}	if ((change_port || change_irq) && (state->count > 1))		return -EBUSY;	/*	 * OK, past this point, all the error checking has been done.	 * At this point, we start making changes.....	 */	state->baud_base = new_serial.baud_base;	state->flags = ((state->flags & ~ASYNC_FLAGS) |			(new_serial.flags & ASYNC_FLAGS));	info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |		       (info->flags & ASYNC_INTERNAL_FLAGS));	state->custom_divisor = new_serial.custom_divisor;	state->close_delay = new_serial.close_delay * HZ/100;	state->closing_wait = new_serial.closing_wait * HZ/100;#if (LINUX_VERSION_CODE > 0x20100)	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;#endif	info->xmit_fifo_size = state->xmit_fifo_size =		new_serial.xmit_fifo_size;	if ((state->type != PORT_UNKNOWN) && state->port) {#ifdef CONFIG_SERIAL_RSA		if (old_state.type == PORT_RSA)			release_region(state->port + UART_RSA_BASE, 16);		else#endif		release_region(state->port,8);	}	state->type = new_serial.type;	if (change_port || change_irq) {		/*		 * We need to shutdown the serial port at the old		 * port/irq combination.		 */		shutdown(info);		state->irq = new_serial.irq;		info->port = state->port = new_port;		info->hub6 = state->hub6 = new_serial.hub6;		if (info->hub6)			info->io_type = state->io_type = SERIAL_IO_HUB6;		else if (info->io_type == SERIAL_IO_HUB6)			info->io_type = state->io_type = SERIAL_IO_PORT;	}	if ((state->type != PORT_UNKNOWN) && state->port) {#ifdef CONFIG_SERIAL_RSA		if (state->type == PORT_RSA)			request_region(state->port + UART_RSA_BASE,				       16, "serial_rsa(set)");		else#endif			request_region(state->port,8,"serial(set)");	}	check_and_exit:	if (!state->port || !state->type)		return 0;	if (info->flags & ASYNC_INITIALIZED) {		if (((old_state.flags & ASYNC_SPD_MASK) !=		     (state->flags & ASYNC_SPD_MASK)) ||		    (old_state.custom_divisor != state->custom_divisor)) {#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)				info->tty->alt_speed = 57600;			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)				info->tty->alt_speed = 115200;			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)				info->tty->alt_speed = 230400;			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)				info->tty->alt_speed = 460800;#endif			change_speed(info, 0);		}	} else		retval = startup(info);	return retval;}/* * 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 get_lsr_info(struct async_struct * info, unsigned int *value){	unsigned char status;	unsigned int result;	unsigned long flags;	save_flags(flags); cli();	status = serial_in(info, UART_LSR);	restore_flags(flags);	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);	/*	 * If we're about to load something into the transmit	 * register, we'll pretend the transmitter isn't empty to	 * avoid a race condition (depending on when the transmit	 * interrupt happens).	 */	if (info->x_char || 	    ((CIRC_CNT(info->xmit.head, info->xmit.tail,		       SERIAL_XMIT_SIZE) > 0) &&	     !info->tty->stopped && !info->tty->hw_stopped))		result &= ~TIOCSER_TEMT;	if (copy_to_user(value, &result, sizeof(int)))		return -EFAULT;	return 0;}static int get_modem_info(struct async_struct * info, unsigned int *value){	unsigned char control, status;	unsigned int result;	unsigned long flags;	control = info->MCR;	save_flags(flags); cli();	status = serial_in(info, UART_MSR);	restore_flags(flags);	result =  ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)		| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)#ifdef TIOCM_OUT1		| ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0)		| ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0)#endif		| ((status  & UART_MSR_DCD) ? TIOCM_CAR : 0)		| ((status  & UART_MSR_RI) ? TIOCM_RNG : 0)		| ((status  & UART_MSR_DSR) ? TIOCM_DSR : 0)		| ((status  & UART_MSR_CTS) ? TIOCM_CTS : 0);	if (copy_to_user(value, &result, sizeof(int)))		return -EFAULT;	return 0;}static int set_modem_info(struct async_struct * info, unsigned int cmd,			  unsigned int *value){	unsigned int arg;	unsigned long flags;	if (copy_from_user(&arg, value, sizeof(int)))		return -EFAULT;	switch (cmd) {	case TIOCMBIS: 		if (arg & TIOCM_RTS)			info->MCR |= UART_MCR_RTS;		if (arg & TIOCM_DTR)			info->MCR |= UART_MCR_DTR;#ifdef TIOCM_OUT1		if (arg & TIOCM_OUT1)			info->MCR |= UART_MCR_OUT1;		if (arg & TIOCM_OUT2)			info->MCR |= UART_MCR_OUT2;#endif		if (arg & TIOCM_LOOP)			info->MCR |= UART_MCR_LOOP;		break;	case TIOCMBIC:		if (arg & TIOCM_RTS)			info->MCR &= ~UART_MCR_RTS;		if (arg & TIOCM_DTR)			info->MCR &= ~UART_MCR_DTR;#ifdef TIOCM_OUT1		if (arg & TIOCM_OUT1)			info->MCR &= ~UART_MCR_OUT1;		if (arg & TIOCM_OUT2)			info->MCR &= ~UART_MCR_OUT2;#endif		if (arg & TIOCM_LOOP)			info->MCR &= ~UART_MCR_LOOP;		break;	case TIOCMSET:		info->MCR = ((info->MCR & ~(UART_MCR_RTS |#ifdef TIOCM_OUT1					    UART_MCR_OUT1 |					    UART_MCR_OUT2 |#endif					    UART_MCR_LOOP |					    UART_MCR_DTR))			     | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)#ifdef TIOCM_OUT1			     | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0)			     | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0)#endif			     | ((arg & TIOCM_LOOP) ? UART_MCR_LOOP : 0)			     | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));		break;	default:		return -EINVAL;	}	save_flags(flags); cli();	info->MCR |= ALPHA_KLUDGE_MCR; 		/* Don't ask */	serial_out(info, UART_MCR, info->MCR);	restore_flags(flags);	return 0;}static int do_autoconfig(struct async_struct * info){	int irq, retval;		if (!capable(CAP_SYS_ADMIN))		return -EPERM;		if (info->state->count > 1)		return -EBUSY;		shutdown(info);	autoconfig(info->state);	if ((info->state->flags & ASYNC_AUTO_IRQ) &&	    (info->state->port != 0  || info->state->iomem_base != 0) &&	    (info->state->type != PORT_UNKNOWN)) {		irq = detect_uart_irq(info->state);		if (irq > 0)			info->state->irq = irq;	}	retval = startup(info);	if (retval)		return retval;	return 0;}/* * rs_break() --- routine which turns the break handling on or off */#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */static void send_break(	struct async_struct * info, int duration){	if (!CONFIGURED_SERIAL_PORT(info))		return;	current->state = TASK_INTERRUPTIBLE;	current->timeout = jiffies + duration;	cli();	info->LCR |= UART_LCR_SBC;	serial_out(info, UART_LCR, info->LCR);	schedule();	info->LCR &= ~UART_LCR_SBC;	serial_out(info, UART_LCR, info->LCR);	sti();}#elsestatic void rs_break(struct tty_struct *tty, int break_state){	struct async_struct * info = (struct async_struct *)tty->driver_data;	unsigned long flags;		if (serial_paranoia_check(info, tty->device, "rs_break"))		return;	if (!CONFIGURED_SERIAL_PORT(info))		return;	save_flags(flags); cli();	if (break_state == -1)		info->LCR |= UART_LCR_SBC;	else		info->LCR &= ~UART_LCR_

⌨️ 快捷键说明

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