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

📄 su.c

📁 自己根据lkd和情境分析
💻 C
📖 第 1 页 / 共 5 页
字号:
		else if (baud)			quot = info->baud_base / baud;	}	/* If the quotient is zero refuse the change */	if (!quot && old_termios) {		info->tty->termios->c_cflag &= ~CBAUD;		info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);		baud = tty_get_baud_rate(info->tty);		if (!baud)			baud = 9600;		if (baud == 38400 &&		    ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))			quot = info->custom_divisor;		else {			if (baud == 134)				/* Special case since 134 is really 134.5 */				quot = (2*info->baud_base / 269);			else if (baud)				quot = info->baud_base / baud;		}	}	/* As a last resort, if the quotient is zero, default to 9600 bps */	if (!quot)		quot = info->baud_base / 9600;	info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / info->baud_base);	info->timeout += HZ/50;		/* Add .02 seconds of slop */	/* Set up FIFO's */	if (uart_config[info->type].flags & UART_USE_FIFO) {		if ((info->baud_base / quot) < 9600)			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;		else			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;	}	if (info->type == PORT_16750)		fcr |= UART_FCR7_64BYTE;	/* CTS flow control flag and modem status interrupts */	info->IER &= ~UART_IER_MSI;	if (info->flags & ASYNC_HARDPPS_CD)		info->IER |= UART_IER_MSI;	if (info->cflag & CRTSCTS) {		info->flags |= ASYNC_CTS_FLOW;		info->IER |= UART_IER_MSI;	} else		info->flags &= ~ASYNC_CTS_FLOW;	if (info->cflag & CLOCAL)		info->flags &= ~ASYNC_CHECK_CD;	else {		info->flags |= ASYNC_CHECK_CD;		info->IER |= UART_IER_MSI;	}	serial_out(info, UART_IER, info->IER);	/*	 * Set up parity check flag	 */	if (info->tty) {#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))		info->read_status_mask = UART_LSR_OE | UART_LSR_THRE |					 UART_LSR_DR;		if (I_INPCK(info->tty))			info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;		if (I_BRKINT(info->tty) || I_PARMRK(info->tty))			info->read_status_mask |= UART_LSR_BI;		/*		 * Characters to ignore		 */		info->ignore_status_mask = 0;		if (I_IGNPAR(info->tty))			info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;		if (I_IGNBRK(info->tty)) {			info->ignore_status_mask |= UART_LSR_BI;			/*			 * If we're ignore parity and break indicators, ignore 			 * overruns too.  (For real raw support).			 */			if (I_IGNPAR(info->tty))				info->ignore_status_mask |= UART_LSR_OE;		}		/*		 * !!! ignore all characters if CREAD is not set		 */		if ((info->cflag & CREAD) == 0)			info->ignore_status_mask |= UART_LSR_DR;	}	save_flags(flags); cli();	if (uart_config[info->type].flags & UART_STARTECH) {		serial_outp(info, UART_LCR, 0xBF);		serial_outp(info, UART_EFR,			    (info->cflag & CRTSCTS) ? UART_EFR_CTS : 0);	}	serial_outp(info, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */	serial_outp(info, UART_DLL, quot & 0xff);	/* LS of divisor */	serial_outp(info, UART_DLM, quot >> 8);		/* MS of divisor */	if (info->type == PORT_16750)		serial_outp(info, UART_FCR, fcr); 	/* set fcr */	serial_outp(info, UART_LCR, cval);		/* reset DLAB */	if (info->type != PORT_16750)		serial_outp(info, UART_FCR, fcr); 	/* set fcr */	restore_flags(flags);	info->quot = quot;}static voidsu_put_char(struct tty_struct *tty, unsigned char ch){	struct su_struct *info = (struct su_struct *)tty->driver_data;	unsigned long flags;	if (serial_paranoia_check(info, tty->device, "su_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 su_put_char_kbd(unsigned char c){	struct su_struct *info = su_table;	int lsr;	if (info->port_type != SU_PORT_KBD)		++info;	if (info->port_type != SU_PORT_KBD)		return;	do {		lsr = serial_in(info, UART_LSR);	} while (!(lsr & UART_LSR_THRE));	/* Send the character out. */	su_outb(info, UART_TX, c);}static voidsu_change_mouse_baud(int baud){	struct su_struct *info = su_table;	if (info->port_type != SU_PORT_MS)		++info;	if (info->port_type != SU_PORT_MS)		return;	info->cflag &= ~CBAUD;	switch (baud) {		case 1200:			info->cflag |= B1200;			break;		case 2400:			info->cflag |= B2400;			break;		case 4800:			info->cflag |= B4800;			break;		case 9600:			info->cflag |= B9600;			break;		default:			printk("su_change_mouse_baud: unknown baud rate %d, "			       "defaulting to 1200\n", baud);			info->cflag |= 1200;			break;	}	change_speed(info, 0);}static voidsu_flush_chars(struct tty_struct *tty){	struct su_struct *info = (struct su_struct *)tty->driver_data;	unsigned long flags;					if (serial_paranoia_check(info, tty->device, "su_flush_chars"))		return;	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||	    !info->xmit_buf)		return;	save_flags(flags); cli();	info->IER |= UART_IER_THRI;	serial_out(info, UART_IER, info->IER);	restore_flags(flags);}static intsu_write(struct tty_struct * tty, int from_user,		    const unsigned char *buf, int count){	int	c, ret = 0;	struct su_struct *info = (struct su_struct *)tty->driver_data;	unsigned long flags;	if (serial_paranoia_check(info, tty->device, "su_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 & UART_IER_THRI)) {		info->IER |= UART_IER_THRI;		serial_out(info, UART_IER, info->IER);	}	return ret;}static intsu_write_room(struct tty_struct *tty){	struct su_struct *info = (struct su_struct *)tty->driver_data;	int	ret;	if (serial_paranoia_check(info, tty->device, "su_write_room"))		return 0;	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;	if (ret < 0)		ret = 0;	return ret;}static intsu_chars_in_buffer(struct tty_struct *tty){	struct su_struct *info = (struct su_struct *)tty->driver_data;					if (serial_paranoia_check(info, tty->device, "su_chars_in_buffer"))		return 0;	return info->xmit_cnt;}static voidsu_flush_buffer(struct tty_struct *tty){	struct su_struct *info = (struct su_struct *)tty->driver_data;	unsigned long flags;	if (serial_paranoia_check(info, tty->device, "su_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 voidsu_send_xchar(struct tty_struct *tty, char ch){	struct su_struct *info = (struct su_struct *)tty->driver_data;	if (serial_paranoia_check(info, tty->device, "su_send_char"))		return;	if (!(info->flags & ASYNC_INITIALIZED))		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);	}}/* * ------------------------------------------------------------ * su_throttle() *  * This routine is called by the upper-layer tty layer to signal that * incoming characters should be throttled. * ------------------------------------------------------------ */static voidsu_throttle(struct tty_struct * tty){	struct su_struct *info = (struct su_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, "su_throttle"))		return;	if (I_IXOFF(tty))		su_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 voidsu_unthrottle(struct tty_struct * tty){	struct su_struct *info = (struct su_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, "su_unthrottle"))		return;	if (I_IXOFF(tty)) {		if (info->x_char)			info->x_char = 0;		else			su_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);}/* * ------------------------------------------------------------ * su_ioctl() and friends * ------------------------------------------------------------ *//* * get_serial_info - handle TIOCGSERIAL ioctl() * * Purpose: Return standard serial struct information about *          a serial port handled by this driver. * * Added:   11-May-2001 Lars Kellogg-Stedman <lars@larsshack.org> */static int get_serial_info(struct su_struct * info,			   struct serial_struct * retinfo){	struct serial_struct	tmp;	if (!retinfo)		return -EFAULT;	memset(&tmp, 0, sizeof(tmp));	tmp.type		= info->type;	tmp.line		= info->line;	tmp.port		= info->port;	tmp.irq			= info->irq;	tmp.flags		= info->flags;	tmp.xmit_fifo_size	= info->xmit_fifo_size;	tmp.baud_base		= info->baud_base;	tmp.close_delay		= info->close_delay;	tmp.closing_wait	= info->closing_wait;	tmp.custom_divisor	= info->custom_divisor;	tmp.hub6		= 0;	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))		return -EFAULT;	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 intget_lsr_info(struct su_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);	return put_user(result,value);}static intget_modem_info(struct su_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);	return put_user(result,value);}static intset_modem_info(struct su_struct * info, unsigned int cmd, unsigned int *value){	unsigned int arg;	unsigned long flags;	if (get_user(arg, value))		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)

⌨️ 快捷键说明

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