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

📄 ctctty.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 3 页
字号:
static intctc_tty_startup(ctc_tty_info * info){	if (info->flags & CTC_ASYNC_INITIALIZED)		return 0;#ifdef CTC_DEBUG_MODEM_OPEN	printk(KERN_DEBUG "starting up %s%d ...\n", CTC_TTY_NAME, info->line);#endif	/*	 * Now, initialize the UART	 */	info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;	if (info->tty)		clear_bit(TTY_IO_ERROR, &info->tty->flags);	/*	 * and set the speed of the serial port	 */	ctc_tty_change_speed(info);	info->flags |= CTC_ASYNC_INITIALIZED;	if (!(info->flags & CTC_ASYNC_NETDEV_OPEN))		info->netdev->open(info->netdev);	info->flags |= CTC_ASYNC_NETDEV_OPEN;	return 0;}static voidctc_tty_stopdev(unsigned long data){	ctc_tty_info *info = (ctc_tty_info *)data;	if ((!info) || (!info->netdev) ||	    (info->flags & CTC_ASYNC_INITIALIZED))		return;	info->netdev->stop(info->netdev);	info->flags &= ~CTC_ASYNC_NETDEV_OPEN;}/* * This routine will shutdown a serial port; interrupts are disabled, and * DTR is dropped if the hangup on close termio flag is on. */static voidctc_tty_shutdown(ctc_tty_info * info){	if (!(info->flags & CTC_ASYNC_INITIALIZED))		return;#ifdef CTC_DEBUG_MODEM_OPEN	printk(KERN_DEBUG "Shutting down %s%d ....\n", CTC_TTY_NAME, info->line);#endif	info->msr &= ~UART_MSR_RI;	if (!info->tty || (info->tty->termios->c_cflag & HUPCL))		info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);	if (info->tty)		set_bit(TTY_IO_ERROR, &info->tty->flags);	mod_timer(&info->stoptimer, jiffies + (10 * HZ));	skb_queue_purge(&info->tx_queue);	skb_queue_purge(&info->rx_queue);	info->flags &= ~CTC_ASYNC_INITIALIZED;}/* ctc_tty_write() is the main send-routine. It is called from the upper * levels within the kernel to perform sending data. Depending on the * online-flag it either directs output to the at-command-interpreter or * to the lower level. Additional tasks done here: *  - If online, check for escape-sequence (+++) *  - If sending audio-data, call ctc_tty_DLEdown() to parse DLE-codes. *  - If receiving audio-data, call ctc_tty_end_vrx() to abort if needed. *  - If dialing, abort dial. */static intctc_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count){	int c;	int total = 0;	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;	if (ctc_tty_shuttingdown)		return 0;	if (ctc_tty_paranoia_check(info, tty->device, "ctc_tty_write"))		return 0;	if (!tty)		return 0;	if (!info->netdev)		return -ENODEV;	if (from_user)		down(&info->write_sem);	while (1) {		struct sk_buff *skb;		int skb_res;		c = (count < CTC_TTY_XMIT_SIZE) ? count : CTC_TTY_XMIT_SIZE;		if (c <= 0)			break;				skb_res = info->netdev->hard_header_len + sizeof(info->mcr) +			+ sizeof(__u32);		skb = dev_alloc_skb(skb_res + c);		if (!skb) {			printk(KERN_WARNING			       "ctc_tty: Out of memory in %s%d write\n",			       CTC_TTY_NAME, info->line);			break;		}		skb_reserve(skb, skb_res);		if (from_user)			copy_from_user(skb_put(skb, c), buf, c);		else			memcpy(skb_put(skb, c), buf, c);		skb_queue_tail(&info->tx_queue, skb);		buf += c;		total += c;		count -= c;	}	if (skb_queue_len(&info->tx_queue)) {		info->lsr &= ~UART_LSR_TEMT;		queue_task(&info->tq, &tq_immediate);		mark_bh(IMMEDIATE_BH);	}	if (from_user)		up(&info->write_sem);	return total;}static intctc_tty_write_room(struct tty_struct *tty){	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;	if (ctc_tty_paranoia_check(info, tty->device, "ctc_tty_write_room"))		return 0;	return CTC_TTY_XMIT_SIZE;}static intctc_tty_chars_in_buffer(struct tty_struct *tty){	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;	if (ctc_tty_paranoia_check(info, tty->device, "ctc_tty_chars_in_buffer"))		return 0;	return 0;}static voidctc_tty_flush_buffer(struct tty_struct *tty){	ctc_tty_info *info;	unsigned long flags;	save_flags(flags);	cli();	if (!tty) {		restore_flags(flags);		return;	}	info = (ctc_tty_info *) tty->driver_data;	if (ctc_tty_paranoia_check(info, tty->device, "ctc_tty_flush_buffer")) {		restore_flags(flags);		return;	}	skb_queue_purge(&info->tx_queue);	info->lsr |= UART_LSR_TEMT;	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);}static voidctc_tty_flush_chars(struct tty_struct *tty){	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;	if (ctc_tty_shuttingdown)		return;	if (ctc_tty_paranoia_check(info, tty->device, "ctc_tty_flush_chars"))		return;	if (tty->stopped || tty->hw_stopped || (!skb_queue_len(&info->tx_queue)))		return;	queue_task(&info->tq, &tq_immediate);	mark_bh(IMMEDIATE_BH);}/* * ------------------------------------------------------------ * ctc_tty_throttle() * * This routine is called by the upper-layer tty layer to signal that * incoming characters should be throttled. * ------------------------------------------------------------ */static voidctc_tty_throttle(struct tty_struct *tty){	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;	if (ctc_tty_paranoia_check(info, tty->device, "ctc_tty_throttle"))		return;	info->mcr &= ~UART_MCR_RTS;	if (I_IXOFF(tty))		ctc_tty_inject(info, STOP_CHAR(tty));	ctc_tty_transmit_status(info);}static voidctc_tty_unthrottle(struct tty_struct *tty){	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;	if (ctc_tty_paranoia_check(info, tty->device, "ctc_tty_unthrottle"))		return;	info->mcr |= UART_MCR_RTS;	if (I_IXOFF(tty))		ctc_tty_inject(info, START_CHAR(tty));	ctc_tty_transmit_status(info);}/* * ------------------------------------------------------------ * ctc_tty_ioctl() and friends * ------------------------------------------------------------ *//* * ctc_tty_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 RS485 driver to be written in user space. */static intctc_tty_get_lsr_info(ctc_tty_info * info, uint * value){	u_char status;	uint result;	ulong flags;	save_flags(flags);	cli();	status = info->lsr;	restore_flags(flags);	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);	put_user(result, (uint *) value);	return 0;}static intctc_tty_get_ctc_tty_info(ctc_tty_info * info, uint * value){	u_char control,	 status;	uint result;	ulong flags;	control = info->mcr;	save_flags(flags);	cli();	status = info->msr;	restore_flags(flags);	result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)	    | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)	    | ((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);	put_user(result, (uint *) value);	return 0;}static intctc_tty_set_ctc_tty_info(ctc_tty_info * info, uint cmd, uint * value){	uint arg;	int old_mcr = info->mcr & (UART_MCR_RTS | UART_MCR_DTR);	get_user(arg, (uint *) value);	switch (cmd) {		case TIOCMBIS:#ifdef CTC_DEBUG_MODEM_IOCTL			printk(KERN_DEBUG "%s%d ioctl TIOCMBIS\n", CTC_TTY_NAME,			       info->line);#endif			if (arg & TIOCM_RTS)				info->mcr |= UART_MCR_RTS;			if (arg & TIOCM_DTR)				info->mcr |= UART_MCR_DTR;			break;		case TIOCMBIC:#ifdef CTC_DEBUG_MODEM_IOCTL			printk(KERN_DEBUG "%s%d ioctl TIOCMBIC\n", CTC_TTY_NAME,			       info->line);#endif			if (arg & TIOCM_RTS)				info->mcr &= ~UART_MCR_RTS;			if (arg & TIOCM_DTR)				info->mcr &= ~UART_MCR_DTR;			break;		case TIOCMSET:#ifdef CTC_DEBUG_MODEM_IOCTL			printk(KERN_DEBUG "%s%d ioctl TIOCMSET\n", CTC_TTY_NAME,			       info->line);#endif			info->mcr = ((info->mcr & ~(UART_MCR_RTS | UART_MCR_DTR))				 | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)			       | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));			break;		default:			return -EINVAL;	}	if ((info->mcr  & (UART_MCR_RTS | UART_MCR_DTR)) != old_mcr)		ctc_tty_transmit_status(info);	return 0;}static intctc_tty_ioctl(struct tty_struct *tty, struct file *file,	       uint cmd, ulong arg){	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;	int error;	int retval;	if (ctc_tty_paranoia_check(info, tty->device, "ctc_tty_ioctl"))		return -ENODEV;	if (tty->flags & (1 << TTY_IO_ERROR))		return -EIO;	switch (cmd) {		case TCSBRK:   /* SVID version: non-zero arg --> no break */#ifdef CTC_DEBUG_MODEM_IOCTL			printk(KERN_DEBUG "%s%d ioctl TCSBRK\n", CTC_TTY_NAME, info->line);#endif			retval = tty_check_change(tty);			if (retval)				return retval;			tty_wait_until_sent(tty, 0);			return 0;		case TCSBRKP:  /* support for POSIX tcsendbreak() */#ifdef CTC_DEBUG_MODEM_IOCTL			printk(KERN_DEBUG "%s%d ioctl TCSBRKP\n", CTC_TTY_NAME, info->line);#endif			retval = tty_check_change(tty);			if (retval)				return retval;			tty_wait_until_sent(tty, 0);			return 0;		case TIOCGSOFTCAR:#ifdef CTC_DEBUG_MODEM_IOCTL			printk(KERN_DEBUG "%s%d ioctl TIOCGSOFTCAR\n", CTC_TTY_NAME,			       info->line);#endif			error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));			if (error)				return error;			put_user(C_CLOCAL(tty) ? 1 : 0, (ulong *) arg);			return 0;		case TIOCSSOFTCAR:#ifdef CTC_DEBUG_MODEM_IOCTL			printk(KERN_DEBUG "%s%d ioctl TIOCSSOFTCAR\n", CTC_TTY_NAME,			       info->line);#endif			error = verify_area(VERIFY_READ, (void *) arg, sizeof(long));			if (error)				return error;			get_user(arg, (ulong *) arg);			tty->termios->c_cflag =			    ((tty->termios->c_cflag & ~CLOCAL) |			     (arg ? CLOCAL : 0));			return 0;		case TIOCMGET:#ifdef CTC_DEBUG_MODEM_IOCTL			printk(KERN_DEBUG "%s%d ioctl TIOCMGET\n", CTC_TTY_NAME,			       info->line);#endif			error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));			if (error)				return error;			return ctc_tty_get_ctc_tty_info(info, (uint *) arg);		case TIOCMBIS:		case TIOCMBIC:		case TIOCMSET:			error = verify_area(VERIFY_READ, (void *) arg, sizeof(uint));			if (error)				return error;			return ctc_tty_set_ctc_tty_info(info, cmd, (uint *) arg);		case TIOCSERGETLSR:	/* Get line status register */#ifdef CTC_DEBUG_MODEM_IOCTL			printk(KERN_DEBUG "%s%d ioctl TIOCSERGETLSR\n", CTC_TTY_NAME,			       info->line);#endif			error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));			if (error)				return error;			else				return ctc_tty_get_lsr_info(info, (uint *) arg);		default:#ifdef CTC_DEBUG_MODEM_IOCTL			printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on %s%d\n", cmd,			       CTC_TTY_NAME, info->line);#endif			return -ENOIOCTLCMD;	}	return 0;}static voidctc_tty_set_termios(struct tty_struct *tty, struct termios *old_termios){	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;	unsigned int cflag = tty->termios->c_cflag;	ctc_tty_change_speed(info);	/* Handle transition to B0 */	if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) {		info->mcr &= ~(UART_MCR_DTR|UART_MCR_RTS);		ctc_tty_transmit_status(info);	}	/* Handle transition from B0 to other */	if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {		info->mcr |= UART_MCR_DTR;		if (!(tty->termios->c_cflag & CRTSCTS) ||                    !test_bit(TTY_THROTTLED, &tty->flags)) {                        info->mcr |= UART_MCR_RTS;                }		ctc_tty_transmit_status(info);	}	/* Handle turning off CRTSCTS */	if ((old_termios->c_cflag & CRTSCTS) &&            !(tty->termios->c_cflag & CRTSCTS))                tty->hw_stopped = 0;}/* * ------------------------------------------------------------ * ctc_tty_open() and friends * ------------------------------------------------------------ */static int

⌨️ 快捷键说明

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