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

📄 vacserial.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if ((cflag & CREAD) == 0)		info->ignore_status_mask |= VAC_UART_STATUS_RX_READY;	save_flags(flags); cli();	switch (baud) {	default:	case 9600:		cval |= VAC_UART_MODE_BAUD(7);		break;	case 4800:		cval |= VAC_UART_MODE_BAUD(6);		break;	case 2400:		cval |= VAC_UART_MODE_BAUD(5);		break;	case 1200:		cval |= VAC_UART_MODE_BAUD(4);		break;	case 600:		cval |= VAC_UART_MODE_BAUD(3);		break;	case 300:		cval |= VAC_UART_MODE_BAUD(2);		break;#ifndef QUAD_UART_SPEED	case 150:#else	case 38400:#endif		cval |= VAC_UART_MODE_BAUD(1);		break;#ifndef QUAD_UART_SPEED	case 75:#else	case 19200:#endif		cval |= VAC_UART_MODE_BAUD(0);		break;	}	/* Baget VAC need some adjustments for computed value */	cval = vac_uart_mode_fixup(cval);	serial_outp(info, VAC_UART_MODE, cval);	restore_flags(flags);}static void rs_put_char(struct tty_struct *tty, unsigned char ch){	struct async_struct *info = (struct async_struct *)tty->driver_data;	unsigned long flags;	if (serial_paranoia_check(info, tty->device, "rs_put_char"))		return;	if (!tty || !info->xmit_buf)		return;	save_flags(flags); cli();	if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {		restore_flags(flags);		return;	}	info->xmit_buf[info->xmit_head++] = ch;	info->xmit_head &= SERIAL_XMIT_SIZE-1;	info->xmit_cnt++;	restore_flags(flags);}static void rs_flush_chars(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_chars"))		return;	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||	    !info->xmit_buf)		return;	save_flags(flags); cli();        info->IER |= VAC_UART_INT_TX_EMPTY;	serial_out(info, VAC_UART_INT_MASK, info->IER);	restore_flags(flags);}static int rs_write(struct tty_struct * tty, int from_user,		    const unsigned char *buf, int count){	int	c, ret = 0;	struct async_struct *info = (struct async_struct *)tty->driver_data;	unsigned long flags;			if (serial_paranoia_check(info, tty->device, "rs_write"))		return 0;	if (!tty || !info->xmit_buf || !tmp_buf)		return 0;	save_flags(flags);	if (from_user) {		down(&tmp_buf_sem);		while (1) {			c = MIN(count,				MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,				    SERIAL_XMIT_SIZE - info->xmit_head));			if (c <= 0)				break;			c -= copy_from_user(tmp_buf, buf, c);			if (!c) {				if (!ret)					ret = -EFAULT;				break;			}			cli();			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,				       SERIAL_XMIT_SIZE - info->xmit_head));			memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);			info->xmit_head = ((info->xmit_head + c) &					   (SERIAL_XMIT_SIZE-1));			info->xmit_cnt += c;			restore_flags(flags);			buf += c;			count -= c;			ret += c;		}		up(&tmp_buf_sem);	} else {		while (1) {			cli();					c = MIN(count,				MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,				    SERIAL_XMIT_SIZE - info->xmit_head));			if (c <= 0) {				restore_flags(flags);				break;			}			memcpy(info->xmit_buf + info->xmit_head, buf, c);			info->xmit_head = ((info->xmit_head + c) &					   (SERIAL_XMIT_SIZE-1));			info->xmit_cnt += c;			restore_flags(flags);			buf += c;			count -= c;			ret += c;		}	}	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped &&            !(info->IER & VAC_UART_INT_TX_EMPTY)) {                info->IER |= VAC_UART_INT_TX_EMPTY;		serial_out(info, VAC_UART_INT_MASK, info->IER);	}	return ret;}static int rs_write_room(struct tty_struct *tty){	struct async_struct *info = (struct async_struct *)tty->driver_data;	int	ret;					if (serial_paranoia_check(info, tty->device, "rs_write_room"))		return 0;	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;	if (ret < 0)		ret = 0;	return ret;}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 info->xmit_cnt;}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_cnt = info->xmit_head = info->xmit_tail = 0;	restore_flags(flags); 	wake_up_interruptible(&tty->write_wait);	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 |= VAC_UART_INT_TX_EMPTY;		serial_out(info, VAC_UART_INT_MASK, info->IER);	}}/* * ------------------------------------------------------------ * 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;#ifdef SERIAL_DEBUG_THROTTLE	char	buf[64];		baget_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));}static void rs_unthrottle(struct tty_struct * tty){	struct async_struct *info = (struct async_struct *)tty->driver_data;#ifdef SERIAL_DEBUG_THROTTLE	char	buf[64];		baget_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));	}}/* * ------------------------------------------------------------ * 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;	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;	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;	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))		return -EFAULT;	state = info->state;	old_state = *state;  	change_irq = new_serial.irq != state->irq;	change_port = (new_serial.port != 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 = ((state->flags & ~ASYNC_USR_MASK) |			       (info->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.port > 0xffff) ||	    (new_serial.baud_base == 0) || (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[state->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_serial.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->type = new_serial.type;	state->close_delay = new_serial.close_delay * HZ/100;	state->closing_wait = new_serial.closing_wait * HZ/100;	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;	info->xmit_fifo_size = state->xmit_fifo_size =		new_serial.xmit_fifo_size;	release_region(state->port,8); 	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_serial.port;		info->hub6 = state->hub6 = new_serial.hub6;	}	if (state->type != PORT_UNKNOWN)		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 ((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;			change_speed(info);		}	} 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 short status;	unsigned int result;	unsigned long flags; 	save_flags(flags); cli();	status = serial_inw(info, VAC_UART_INT_STATUS);	restore_flags(flags);	result = ((status & VAC_UART_STATUS_TX_EMPTY) ? TIOCSER_TEMT : 0);	return put_user(result,value);}static int get_modem_info(struct async_struct * info, unsigned int *value){	unsigned int result;	result = TIOCM_CAR | TIOCM_DSR;	return put_user(result,value);}static int set_modem_info(struct async_struct * info, unsigned int cmd,			  unsigned int *value){	int error;	unsigned int arg;	error = get_user(arg, value);	if (error)		return error;	switch (cmd) {	default:		return -EINVAL;	}	return 0;}static int do_autoconfig(struct async_struct * info){	int			retval;		if (!capable(CAP_SYS_ADMIN))		return -EPERM;		if (info->state->count > 1)		return -EBUSY;		shutdown(info);	autoconfig(info->state);	retval = startup(info);	if (retval)		return retval;	return 0;}/* * rs_break() --- routine which turns the break handling on or off */static void rs_break(struct tty_struct *tty, int break_state){	struct async_struct * info = (struct async_struct *)tty->driver_data;

⌨️ 快捷键说明

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