/*
 * ------------------------------------------------------------
 * xmbrs_throttle()
 * 
 * This routine is called by the upper-layer tty layer to signal that
 * incoming characters should be throttled.
 * ------------------------------------------------------------
 */
static void xmbrs_throttle(struct tty_struct * tty)
{
	struct xmb_serial *info = (struct xmb_serial *)tty->driver_data;
#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, "xmbrs_throttle"))
		return;
	
	if (I_IXOFF(tty)) {
		/* Force STOP_CHAR (xoff) out */
		volatile unsigned int *uartp;
		unsigned long		flags;
		info->x_char = STOP_CHAR(tty);
		uartp = (volatile unsigned int *) info->addr;
		save_flags_cli(flags);
		EnableInterrupts(uartp);
		force_tx_fifo_fill(info);
		restore_flags(flags);
	}

}
Пример #2
0
/*
 * ------------------------------------------------------------
 * rs_throttle()
 * 
 * This routine is called by the upper-layer tty layer to signal that
 * incoming characters should be throttled.
 * ------------------------------------------------------------
 */
static void rs_360_throttle(struct tty_struct * tty)
{
	ser_info_t *info = (ser_info_t *)tty->driver_data;
#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->name, "rs_throttle"))
		return;
	
	if (I_IXOFF(tty))
		rs_360_send_xchar(tty, STOP_CHAR(tty));

#ifdef modem_control
	if (tty->termios->c_cflag & CRTSCTS)
		info->MCR &= ~UART_MCR_RTS;

	local_irq_disable();
	serial_out(info, UART_MCR, info->MCR);
	local_irq_enable();
#endif
}
Пример #3
0
static void change_termios(struct tty_struct * tty, struct termios * new_termios)
{
	int canon_change;
	struct termios old_termios = *tty->termios;
	struct tty_ldisc *ld;
	
	/*
	 *	Perform the actual termios internal changes under lock.
	 */
	 

	/* FIXME: we need to decide on some locking/ordering semantics
	   for the set_termios notification eventually */
	down(&tty->termios_sem);

	*tty->termios = *new_termios;
	unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
	canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
	if (canon_change) {
		memset(&tty->read_flags, 0, sizeof tty->read_flags);
		tty->canon_head = tty->read_tail;
		tty->canon_data = 0;
		tty->erasing = 0;
	}
	
	
	if (canon_change && !L_ICANON(tty) && tty->read_cnt)
		/* Get characters left over from canonical mode. */
		wake_up_interruptible(&tty->read_wait);

	/* See if packet mode change of state. */

	if (tty->link && tty->link->packet) {
		int old_flow = ((old_termios.c_iflag & IXON) &&
				(old_termios.c_cc[VSTOP] == '\023') &&
				(old_termios.c_cc[VSTART] == '\021'));
		int new_flow = (I_IXON(tty) &&
				STOP_CHAR(tty) == '\023' &&
				START_CHAR(tty) == '\021');
		if (old_flow != new_flow) {
			tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
			if (new_flow)
				tty->ctrl_status |= TIOCPKT_DOSTOP;
			else
				tty->ctrl_status |= TIOCPKT_NOSTOP;
			wake_up_interruptible(&tty->link->read_wait);
		}
	}
	   
	if (tty->driver->set_termios)
		(*tty->driver->set_termios)(tty, &old_termios);

	ld = tty_ldisc_ref(tty);
	if (ld != NULL) {
		if (ld->set_termios)
			(ld->set_termios)(tty, &old_termios);
		tty_ldisc_deref(ld);
	}
	up(&tty->termios_sem);
}
Пример #4
0
/*
 * ------------------------------------------------------------
 * 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)
{
	if (I_IXOFF(tty))
		rs_send_xchar(tty, STOP_CHAR(tty));

	printk(KERN_INFO "simrs_throttle called\n");
}
Пример #5
0
static void pty_set_termios(struct tty_struct *tty,
					struct ktermios *old_termios)
{
	/* See if packet mode change of state. */
	if (tty->link && tty->link->packet) {
		int extproc = (old_termios->c_lflag & EXTPROC) |
				(tty->termios.c_lflag & EXTPROC);
		int old_flow = ((old_termios->c_iflag & IXON) &&
				(old_termios->c_cc[VSTOP] == '\023') &&
				(old_termios->c_cc[VSTART] == '\021'));
		int new_flow = (I_IXON(tty) &&
				STOP_CHAR(tty) == '\023' &&
				START_CHAR(tty) == '\021');
		if ((old_flow != new_flow) || extproc) {
			spin_lock_irq(&tty->ctrl_lock);
			if (old_flow != new_flow) {
				tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
				if (new_flow)
					tty->ctrl_status |= TIOCPKT_DOSTOP;
				else
					tty->ctrl_status |= TIOCPKT_NOSTOP;
			}
			if (extproc)
				tty->ctrl_status |= TIOCPKT_IOCTL;
			spin_unlock_irq(&tty->ctrl_lock);
			wake_up_interruptible(&tty->link->read_wait);
		}
	}

	tty->termios.c_cflag &= ~(CSIZE | PARENB);
	tty->termios.c_cflag |= (CS8 | CREAD);
}
Пример #6
0
/*
 * ------------------------------------------------------------
 * dz_throttle () and dz_unthrottle ()
 * 
 * This routine is called by the upper-layer tty layer to signal that
 * incoming characters should be throttled (or not).
 * ------------------------------------------------------------
 */
static void dz_throttle(struct tty_struct *tty)
{
	struct dz_serial *info = (struct dz_serial *) tty->driver_data;

	if (I_IXOFF(tty))
		info->x_char = STOP_CHAR(tty);
}
Пример #7
0
static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
{
	if (!tty)
		return;
	
	tty->icanon = (L_ICANON(tty) != 0);
	if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||
	    I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
	    I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
	    I_PARMRK(tty)) {
		cli();
		memset(tty->process_char_map, 0, 256/8);

		if (I_IGNCR(tty) || I_ICRNL(tty))
			set_bit('\r', &tty->process_char_map);
		if (I_INLCR(tty))
			set_bit('\n', &tty->process_char_map);

		if (L_ICANON(tty)) {
			set_bit(ERASE_CHAR(tty), &tty->process_char_map);
			set_bit(KILL_CHAR(tty), &tty->process_char_map);
			set_bit(EOF_CHAR(tty), &tty->process_char_map);
			set_bit('\n', &tty->process_char_map);
			set_bit(EOL_CHAR(tty), &tty->process_char_map);
			if (L_IEXTEN(tty)) {
				set_bit(WERASE_CHAR(tty),
					&tty->process_char_map);
				set_bit(LNEXT_CHAR(tty),
					&tty->process_char_map);
				set_bit(EOL2_CHAR(tty),
					&tty->process_char_map);
				if (L_ECHO(tty))
					set_bit(REPRINT_CHAR(tty),
						&tty->process_char_map);
			}
		}
		if (I_IXON(tty)) {
			set_bit(START_CHAR(tty), &tty->process_char_map);
			set_bit(STOP_CHAR(tty), &tty->process_char_map);
		}
		if (L_ISIG(tty)) {
			set_bit(INTR_CHAR(tty), &tty->process_char_map);
			set_bit(QUIT_CHAR(tty), &tty->process_char_map);
			set_bit(SUSP_CHAR(tty), &tty->process_char_map);
		}
		clear_bit(__DISABLED_CHAR, &tty->process_char_map);
		sti();
		tty->raw = 0;
		tty->real_raw = 0;
	} else {
		tty->raw = 1;
		if ((I_IGNBRK(tty) || (!I_BRKINT(tty) && !I_PARMRK(tty))) &&
		    (I_IGNPAR(tty) || !I_INPCK(tty)) &&
		    (tty->driver.flags & TTY_DRIVER_REAL_RAW))
			tty->real_raw = 1;
		else
			tty->real_raw = 0;
	}
}
Пример #8
0
static void xencons_throttle(struct tty_struct *tty)
{
	if (DUMMY_TTY(tty))
		return;

	if (I_IXOFF(tty))
		xencons_send_xchar(tty, STOP_CHAR(tty));
}
Пример #9
0
/**
 *	tty_set_termios		-	update termios values
 *	@tty: tty to update
 *	@new_termios: desired new value
 *
 *	Perform updates to the termios values set on this terminal. There
 *	is a bit of layering violation here with n_tty in terms of the
 *	internal knowledge of this function.
 *
 *	Locking: termios_mutex
 */
int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
{
	struct ktermios old_termios;
	struct tty_ldisc *ld;
	unsigned long flags;

	/*
	 *	Perform the actual termios internal changes under lock.
	 */


	/* FIXME: we need to decide on some locking/ordering semantics
	   for the set_termios notification eventually */
	mutex_lock(&tty->termios_mutex);
	old_termios = *tty->termios;
	*tty->termios = *new_termios;
	unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);

	/* See if packet mode change of state. */
	if (tty->link && tty->link->packet) {
		int extproc = (old_termios.c_lflag & EXTPROC) |
				(tty->termios->c_lflag & EXTPROC);
		int old_flow = ((old_termios.c_iflag & IXON) &&
				(old_termios.c_cc[VSTOP] == '\023') &&
				(old_termios.c_cc[VSTART] == '\021'));
		int new_flow = (I_IXON(tty) &&
				STOP_CHAR(tty) == '\023' &&
				START_CHAR(tty) == '\021');
		if ((old_flow != new_flow) || extproc) {
			spin_lock_irqsave(&tty->ctrl_lock, flags);
			if (old_flow != new_flow) {
				tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
				if (new_flow)
					tty->ctrl_status |= TIOCPKT_DOSTOP;
				else
					tty->ctrl_status |= TIOCPKT_NOSTOP;
			}
			if (extproc)
				tty->ctrl_status |= TIOCPKT_IOCTL;
			spin_unlock_irqrestore(&tty->ctrl_lock, flags);
			wake_up_interruptible(&tty->link->read_wait);
		}
	}

	if (tty->ops->set_termios)
		(*tty->ops->set_termios)(tty, &old_termios);
	else
		tty_termios_copy_hw(tty->termios, &old_termios);

	ld = tty_ldisc_ref(tty);
	if (ld != NULL) {
		if (ld->ops->set_termios)
			(ld->ops->set_termios)(tty, &old_termios);
		tty_ldisc_deref(ld);
	}
	mutex_unlock(&tty->termios_mutex);
	return 0;
}
Пример #10
0
static void uart_throttle(struct tty_struct *tty)
{
	struct uart_state *state = tty->driver_data;

	if (I_IXOFF(tty))
		uart_send_xchar(tty, STOP_CHAR(tty));

	if (tty->termios->c_cflag & CRTSCTS)
		uart_clear_mctrl(state->uart_port, TIOCM_RTS);
}
Пример #11
0
/*
 * ------------------------------------------------------------
 * 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 m68k_serial *info = (struct m68k_serial *)tty->driver_data;

	if (serial_paranoia_check(info, tty->name, "rs_throttle"))
		return;

	if (I_IXOFF(tty))
		info->x_char = STOP_CHAR(tty);

	/* Turn off RTS line (do this atomic) */
}
Пример #12
0
/*
 * ------------------------------------------------------------
 * ctc_tty_throttle()
 *
 * This routine is called by the upper-layer tty layer to signal that
 * incoming characters should be throttled.
 * ------------------------------------------------------------
 */
static void
ctc_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);
}
Пример #13
0
static void scc_throttle (struct tty_struct * tty)
{
	struct scc_port *port = tty->driver_data;
	unsigned long	flags;
	SCC_ACCESS_INIT(port);

	if (tty->termios->c_cflag & CRTSCTS) {
		local_irq_save(flags);
		SCCmod(TX_CTRL_REG, ~TCR_RTS, 0);
		local_irq_restore(flags);
	}
	if (I_IXOFF(tty))
		scc_send_xchar(tty, STOP_CHAR(tty));
}
Пример #14
0
/*
 * Throttle characters as directed by upper tty layer
 */
static void rs_throttle(struct tty_struct * tty)
{
#ifdef TX3912_UART_DEBUG_THROTTLE
    char	buf[64];

    printk("throttle %s: %d....\n", tty_name(tty, buf),
           tty->ldisc.chars_in_buffer(tty));
#endif

    func_enter();

    if (I_IXOFF(tty))
        rs_send_xchar(tty, STOP_CHAR(tty));

    func_exit();
}
Пример #15
0
static void nullmodem_throttle(struct tty_struct * tty)
{
	unsigned long flags;
	struct nullmodem_end *end = tty->driver_data;

	dprintf("%s - #%d\n", __FUNCTION__, tty->index);

	if (I_IXOFF(tty))
		nullmodem_send_xchar(tty, STOP_CHAR(tty));

	if (tty->termios.c_cflag & CRTSCTS)
	{
		spin_lock_irqsave(&end->pair->spin, flags);
		change_pins(end, 0, TIOCM_RTS);
		spin_unlock_irqrestore(&end->pair->spin, flags);
	}
}
Пример #16
0
static int set_termios_2(struct tty_struct * tty, struct termios * termios)
{
	struct termios old_termios = *tty->termios;
	int canon_change;

	canon_change = (old_termios.c_lflag ^ termios->c_lflag) & ICANON;
	cli();
	*tty->termios = *termios;
	if (canon_change) {
		memset(&tty->secondary_flags, 0, sizeof tty->secondary_flags);
		tty->canon_head = tty->secondary.tail;
		tty->canon_data = 0;
		tty->erasing = 0;
	}
	sti();
	if (canon_change && !L_ICANON(tty) && !EMPTY(&tty->secondary))
		/* Get characters left over from canonical mode. */
		wake_up_interruptible(&tty->secondary.proc_list);

	/* see if packet mode change of state */

	if (tty->link && tty->link->packet) {
		int old_flow = ((old_termios.c_iflag & IXON) &&
				(old_termios.c_cc[VSTOP] == '\023') &&
				(old_termios.c_cc[VSTART] == '\021'));
		int new_flow = (I_IXON(tty) &&
				STOP_CHAR(tty) == '\023' &&
				START_CHAR(tty) == '\021');
		if (old_flow != new_flow) {
			tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
			if (new_flow)
				tty->ctrl_status |= TIOCPKT_DOSTOP;
			else
				tty->ctrl_status |= TIOCPKT_NOSTOP;
			wake_up_interruptible(&tty->link->secondary.proc_list);
		}
	}

	unset_locked_termios(tty->termios, &old_termios,
			     termios_locked[tty->line]);

	if (tty->set_termios)
		(*tty->set_termios)(tty, &old_termios);

	return 0;
}
Пример #17
0
static void tty_receive_char(struct tty_struct *tty, char ch)
{
	if(tty == NULL) return;

	if(I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) {
		if(ch == STOP_CHAR(tty)){
			stop_tty(tty);
			return;
		}
		else if(ch == START_CHAR(tty)){
			start_tty(tty);
			return;
		}
	}

	tty_insert_flip_char(tty, ch, TTY_NORMAL);
}
Пример #18
0
static void change_termios(struct tty_struct * tty, struct termios * new_termios)
{
	int canon_change;
	struct termios old_termios = *tty->termios;

	local_irq_disable(); // FIXME: is this safe?
	*tty->termios = *new_termios;
	unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
	canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
	if (canon_change) {
		memset(&tty->read_flags, 0, sizeof tty->read_flags);
		tty->canon_head = tty->read_tail;
		tty->canon_data = 0;
		tty->erasing = 0;
	}
	local_irq_enable(); // FIXME: is this safe?
	if (canon_change && !L_ICANON(tty) && tty->read_cnt)
		/* Get characters left over from canonical mode. */
		wake_up_interruptible(&tty->read_wait);

	/* see if packet mode change of state */

	if (tty->link && tty->link->packet) {
		int old_flow = ((old_termios.c_iflag & IXON) &&
				(old_termios.c_cc[VSTOP] == '\023') &&
				(old_termios.c_cc[VSTART] == '\021'));
		int new_flow = (I_IXON(tty) &&
				STOP_CHAR(tty) == '\023' &&
				START_CHAR(tty) == '\021');
		if (old_flow != new_flow) {
			tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
			if (new_flow)
				tty->ctrl_status |= TIOCPKT_DOSTOP;
			else
				tty->ctrl_status |= TIOCPKT_NOSTOP;
			wake_up_interruptible(&tty->link->read_wait);
		}
	}

	if (tty->driver->set_termios)
		(*tty->driver->set_termios)(tty, &old_termios);

	if (tty->ldisc.set_termios)
		(*tty->ldisc.set_termios)(tty, &old_termios);
}
Пример #19
0
/*
 * ------------------------------------------------------------
 * mcfrs_throttle()
 * 
 * This routine is called by the upper-layer tty layer to signal that
 * incoming characters should be throttled.
 * ------------------------------------------------------------
 */
static void mcfrs_throttle(struct tty_struct * tty)
{
	struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
#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->name, "mcfrs_throttle"))
		return;
	
	if (I_IXOFF(tty))
		info->x_char = STOP_CHAR(tty);

	/* Turn off RTS line (do this atomic) */
}
Пример #20
0
void sab8253x_throttleS(struct tty_struct * tty)
{
	struct sab_port *port = (struct sab_port *)tty->driver_data;
	
	if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_throttleS"))
	{
		return;
	}
	
	if (!tty)
	{
		return;
	}
	
	if (I_IXOFF(tty))
	{
		sab8253x_send_xcharS(tty, STOP_CHAR(tty));
	}
}
Пример #21
0
/*
 * ------------------------------------------------------------
 * 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 serial_state *info = tty->driver_data;
	unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
	printk("throttle %s ....\n", tty_name(tty));
#endif

	if (serial_paranoia_check(info, tty->name, "rs_throttle"))
		return;

	if (I_IXOFF(tty))
		rs_send_xchar(tty, STOP_CHAR(tty));

	if (C_CRTSCTS(tty))
		info->MCR &= ~SER_RTS;

	local_irq_save(flags);
	rtsdtr_ctrl(info->MCR);
	local_irq_restore(flags);
}
Пример #22
0
static void rs_throttle(struct tty_struct * tty)
{
	struct async_struct *info = 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->name, "rs_throttle"))
		return;

	if (I_IXOFF(tty))
		rs_send_xchar(tty, STOP_CHAR(tty));

	if (tty->termios->c_cflag & CRTSCTS)
		info->MCR &= ~SER_RTS;

	local_irq_save(flags);
	rtsdtr_ctrl(info->MCR);
	local_irq_restore(flags);
}
Пример #23
0
static void
etraxfs_uart_set_termios(struct uart_port *port, struct ktermios *termios,
			 struct ktermios *old)
{
	struct uart_cris_port *up = (struct uart_cris_port *)port;
	unsigned long flags;
	reg_ser_rw_xoff xoff;
	reg_ser_rw_xoff_clr xoff_clr = {0};
	reg_ser_rw_tr_ctrl tx_ctrl = {0};
	reg_ser_rw_tr_dma_en tx_dma_en = {0};
	reg_ser_rw_rec_ctrl rx_ctrl = {0};
	reg_ser_rw_tr_baud_div tx_baud_div = {0};
	reg_ser_rw_rec_baud_div rx_baud_div = {0};
	int baud;

	if (old &&
	    termios->c_cflag == old->c_cflag &&
	    termios->c_iflag == old->c_iflag)
		return;

	/* Tx: 8 bit, no/even parity, 1 stop bit, no cts. */
	tx_ctrl.base_freq = regk_ser_f29_493;
	tx_ctrl.en = 0;
	tx_ctrl.stop = 0;
	tx_ctrl.auto_rts = regk_ser_no;
	tx_ctrl.txd = 1;
	tx_ctrl.auto_cts = 0;
	/* Rx: 8 bit, no/even parity. */
	rx_ctrl.dma_err = regk_ser_stop;
	rx_ctrl.sampling = regk_ser_majority;
	rx_ctrl.timeout = 1;

	rx_ctrl.rts_n = regk_ser_inactive;

	/* Common for tx and rx: 8N1. */
	tx_ctrl.data_bits = regk_ser_bits8;
	rx_ctrl.data_bits = regk_ser_bits8;
	tx_ctrl.par = regk_ser_even;
	rx_ctrl.par = regk_ser_even;
	tx_ctrl.par_en = regk_ser_no;
	rx_ctrl.par_en = regk_ser_no;

	tx_ctrl.stop_bits = regk_ser_bits1;

	/*
	 * Change baud-rate and write it to the hardware.
	 *
	 * baud_clock = base_freq / (divisor*8)
	 * divisor = base_freq / (baud_clock * 8)
	 * base_freq is either:
	 * off, ext, 29.493MHz, 32.000 MHz, 32.768 MHz or 100 MHz
	 * 20.493MHz is used for standard baudrates
	 */

	/*
	 * For the console port we keep the original baudrate here.  Not very
	 * beautiful.
	 */
	if ((port != console_port) || old)
		baud = uart_get_baud_rate(port, termios, old, 0,
					  port->uartclk / 8);
	else
		baud = console_baud;

	tx_baud_div.div = 29493000 / (8 * baud);
	/* Rx uses same as tx. */
	rx_baud_div.div = tx_baud_div.div;
	rx_ctrl.base_freq = tx_ctrl.base_freq;

	if ((termios->c_cflag & CSIZE) == CS7) {
		/* Set 7 bit mode. */
		tx_ctrl.data_bits = regk_ser_bits7;
		rx_ctrl.data_bits = regk_ser_bits7;
	}

	if (termios->c_cflag & CSTOPB) {
		/* Set 2 stop bit mode. */
		tx_ctrl.stop_bits = regk_ser_bits2;
	}

	if (termios->c_cflag & PARENB) {
		/* Enable parity. */
		tx_ctrl.par_en = regk_ser_yes;
		rx_ctrl.par_en = regk_ser_yes;
	}

	if (termios->c_cflag & CMSPAR) {
		if (termios->c_cflag & PARODD) {
			/* Set mark parity if PARODD and CMSPAR. */
			tx_ctrl.par = regk_ser_mark;
			rx_ctrl.par = regk_ser_mark;
		} else {
			tx_ctrl.par = regk_ser_space;
			rx_ctrl.par = regk_ser_space;
		}
	} else {
		if (termios->c_cflag & PARODD) {
			/* Set odd parity. */
		       tx_ctrl.par = regk_ser_odd;
		       rx_ctrl.par = regk_ser_odd;
		}
	}

	if (termios->c_cflag & CRTSCTS) {
		/* Enable automatic CTS handling. */
		tx_ctrl.auto_cts = regk_ser_yes;
	}

	/* Make sure the tx and rx are enabled. */
	tx_ctrl.en = regk_ser_yes;
	rx_ctrl.en = regk_ser_yes;

	spin_lock_irqsave(&port->lock, flags);

	tx_dma_en.en = 0;
	REG_WR(ser, up->regi_ser, rw_tr_dma_en, tx_dma_en);

	/* Actually write the control regs (if modified) to the hardware. */
	uart_update_timeout(port, termios->c_cflag, port->uartclk/8);
	MODIFY_REG(up->regi_ser, rw_rec_baud_div, rx_baud_div);
	MODIFY_REG(up->regi_ser, rw_rec_ctrl, rx_ctrl);

	MODIFY_REG(up->regi_ser, rw_tr_baud_div, tx_baud_div);
	MODIFY_REG(up->regi_ser, rw_tr_ctrl, tx_ctrl);

	tx_dma_en.en = 0;
	REG_WR(ser, up->regi_ser, rw_tr_dma_en, tx_dma_en);

	xoff = REG_RD(ser, up->regi_ser, rw_xoff);

	if (up->port.state && up->port.state->port.tty &&
	    (up->port.state->port.tty->termios.c_iflag & IXON)) {
		xoff.chr = STOP_CHAR(up->port.state->port.tty);
		xoff.automatic = regk_ser_yes;
	} else
		xoff.automatic = regk_ser_no;

	MODIFY_REG(up->regi_ser, rw_xoff, xoff);

	/*
	 * Make sure we don't start in an automatically shut-off state due to
	 * a previous early exit.
	 */
	xoff_clr.clr = 1;
	REG_WR(ser, up->regi_ser, rw_xoff_clr, xoff_clr);

	etraxfs_uart_set_mctrl(&up->port, up->port.mctrl);
	spin_unlock_irqrestore(&up->port.lock, flags);
}
void copy_to_cooked(struct tty_struct * tty)
{
	signed char c;

	while (!EMPTY(tty->read_q) && !FULL(tty->secondary)) {
		GETCH(tty->read_q,c);
		if (c==13)
			if (I_CRNL(tty))
				c=10;
			else if (I_NOCR(tty))
				continue;
			else ;
		else if (c==10 && I_NLCR(tty))
			c=13;
		if (I_UCLC(tty))
			c=tolower(c);
		if (L_CANON(tty)) {
			if (c==ERASE_CHAR(tty)) {
				if (EMPTY(tty->secondary) ||
				   (c=LAST(tty->secondary))==10 ||
				   c==EOF_CHAR(tty))
					continue;
				if (L_ECHO(tty)) {
					if (c<32)
						PUTCH(127,tty->write_q);
					PUTCH(127,tty->write_q);
					tty->write(tty);
				}
				DEC(tty->secondary.head);
				continue;
			}
			if (c==STOP_CHAR(tty)) {
				tty->stopped=1;
				continue;
			}
			if (c==START_CHAR(tty)) {
				tty->stopped=0;
				continue;
			}
		}
		if (!L_ISIG(tty)) {
			if (c==INTR_CHAR(tty)) {
				tty_intr(tty,SIGINT);
				continue;
			}
		}
		if (c==10 || c==EOF_CHAR(tty))
			tty->secondary.data++;
		if (L_ECHO(tty)) {
			if (c==10) {
				PUTCH(10,tty->write_q);
				PUTCH(13,tty->write_q);
			} else if (c<32) {
				if (L_ECHOCTL(tty)) {
					PUTCH('^',tty->write_q);
					PUTCH(c+64,tty->write_q);
				}
			} else
				PUTCH(c,tty->write_q);
			tty->write(tty);
		}
		PUTCH(c,tty->secondary);
	}
	wake_up(&tty->secondary.proc_list);
}
Пример #25
0
int tty_ioctl(struct inode * inode, struct file * file,
	unsigned int cmd, unsigned int arg)
{
	struct tty_struct * tty;
	struct tty_struct * other_tty;
	int pgrp;
	int dev;

	if (MAJOR(file->f_rdev) != 4) {
		printk("tty_ioctl: tty pseudo-major != 4\n");
		return -EINVAL;
	}
	dev = MINOR(file->f_rdev);
	tty = TTY_TABLE(dev);
	if (!tty)
		return -EINVAL;

	if (IS_A_PTY(dev))
		other_tty = tty_table[PTY_OTHER(dev)];
	else
		other_tty = NULL;
		
	switch (cmd) {
		case TCGETS:
			return get_termios(tty,(struct termios *) arg);
		case TCSETSF:
			flush_input(tty);
		/* fallthrough */
		case TCSETSW:
			wait_until_sent(tty);
		/* fallthrough */
		case TCSETS:
			return set_termios(tty,(struct termios *) arg, dev);
		case TCGETA:
			return get_termio(tty,(struct termio *) arg);
		case TCSETAF:
			flush_input(tty);
		/* fallthrough */
		case TCSETAW:
			wait_until_sent(tty); /* fallthrough */
		case TCSETA:
			return set_termio(tty,(struct termio *) arg, dev);
		case TCXONC:
			switch (arg) {
			case TCOOFF:
				tty->stopped = 1;
				TTY_WRITE_FLUSH(tty);
				return 0;
			case TCOON:
				tty->stopped = 0;
				TTY_WRITE_FLUSH(tty);
				return 0;
			case TCIOFF:
				if (STOP_CHAR(tty))
					put_tty_queue(STOP_CHAR(tty),
						      &tty->write_q);
				return 0;
			case TCION:
				if (START_CHAR(tty))
					put_tty_queue(START_CHAR(tty),
						      &tty->write_q);
				return 0;
			}
			return -EINVAL; /* not implemented */
		case TCFLSH:
			if (arg==0)
				flush_input(tty);
			else if (arg==1)
				flush_output(tty);
			else if (arg==2) {
				flush_input(tty);
				flush_output(tty);
			} else
				return -EINVAL;
			return 0;
		case TIOCEXCL:
			return -EINVAL; /* not implemented */
		case TIOCNXCL:
			return -EINVAL; /* not implemented */
		case TIOCSCTTY:
			return -EINVAL; /* set controlling term NI */
		case TIOCGPGRP:
			verify_area((void *) arg,4);
			put_fs_long(tty->pgrp,(unsigned long *) arg);
			return 0;
		case TIOCSPGRP:
			if ((current->tty < 0) ||
			    (current->tty != dev) ||
			    (tty->session != current->session))
				return -ENOTTY;
			pgrp=get_fs_long((unsigned long *) arg);
			if (pgrp < 0)
				return -EINVAL;
			if (session_of_pgrp(pgrp) != current->session)
				return -EPERM;
			tty->pgrp = pgrp;			
			return 0;
		case TIOCOUTQ:
			verify_area((void *) arg,4);
			put_fs_long(CHARS(&tty->write_q),
				    (unsigned long *) arg);
			return 0;
		case TIOCINQ:
			verify_area((void *) arg,4);
			if (L_CANON(tty) && !tty->secondary.data)
				put_fs_long(0, (unsigned long *) arg);
			else
				put_fs_long(CHARS(&tty->secondary),
					(unsigned long *) arg);
			return 0;
		case TIOCSTI:
			return -EINVAL; /* not implemented */
		case TIOCGWINSZ:
			return get_window_size(tty,(struct winsize *) arg);
		case TIOCSWINSZ:
			if (IS_A_PTY_MASTER(dev))
				set_window_size(other_tty,(struct winsize *) arg);
			return set_window_size(tty,(struct winsize *) arg);
		case TIOCGSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCSSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCLINUX:
			switch (get_fs_byte((char *)arg))
			{
				case 0: 
					return do_screendump(arg);
				case 1: 
					return do_get_ps_info(arg);
				default: 
					return -EINVAL;
			}
		case TIOCCONS:
			if (!IS_A_PTY(dev))
				return -EINVAL;
			if (redirect)
				return -EBUSY;
			if (!suser())
				return -EPERM;
			if (IS_A_PTY_MASTER(dev))
				redirect = other_tty;
			else
				redirect = tty;
			return 0;
		case FIONBIO:
			if (arg)
				file->f_flags |= O_NONBLOCK;
			else
				file->f_flags &= ~O_NONBLOCK;
			return 0;
		case TIOCNOTTY:
			if (MINOR(file->f_rdev) != current->tty)
				return -EINVAL;
			current->tty = -1;
			if (current->leader) {
				if (tty->pgrp > 0)
					kill_pg(tty->pgrp, SIGHUP, 0);
				tty->pgrp = -1;
				tty->session = 0;
			}
			return 0;

	       case TIOCPKT:
			{
			   int on;
			   if (!IS_A_PTY_MASTER(dev))
			     return (-EINVAL);
			   verify_area ((unsigned long *)arg, sizeof (int));
			   on=get_fs_long ((unsigned long *)arg);
			   if (on )
			     tty->packet = 1;
			   else
			     tty->packet = 0;
			   return (0);
			}

		default:
			if (tty->ioctl)
				return (tty->ioctl)(tty, file, cmd, arg);
			else
				return -EINVAL;
	}
}
Пример #26
0
static void qt2_set_termios(struct tty_struct *tty,
			    struct usb_serial_port *port,
			    struct ktermios *old_termios)
{
	struct usb_device *dev = port->serial->dev;
	struct qt2_port_private *port_priv;
	struct ktermios *termios = &tty->termios;
	u16 baud;
	unsigned int cflag = termios->c_cflag;
	u16 new_lcr = 0;
	int status;

	port_priv = usb_get_serial_port_data(port);

	if (cflag & PARENB) {
		if (cflag & PARODD)
			new_lcr |= UART_LCR_PARITY;
		else
			new_lcr |= SERIAL_EVEN_PARITY;
	}

	switch (cflag & CSIZE) {
	case CS5:
		new_lcr |= UART_LCR_WLEN5;
		break;
	case CS6:
		new_lcr |= UART_LCR_WLEN6;
		break;
	case CS7:
		new_lcr |= UART_LCR_WLEN7;
		break;
	default:
	case CS8:
		new_lcr |= UART_LCR_WLEN8;
		break;
	}

	baud = tty_get_baud_rate(tty);
	if (!baud)
		baud = 9600;

	status = qt2_set_port_config(dev, port_priv->device_port, baud,
				     new_lcr);
	if (status < 0)
		dev_err(&port->dev, "%s - qt2_set_port_config failed: %i\n",
			__func__, status);

	if (cflag & CRTSCTS)
		status = qt2_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
					 SERIAL_CRTSCTS,
					 port_priv->device_port);
	else
		status = qt2_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
					 0, port_priv->device_port);
	if (status < 0)
		dev_err(&port->dev, "%s - set HW flow control failed: %i\n",
			__func__, status);

	if (I_IXOFF(tty) || I_IXON(tty)) {
		u16 x = ((u16) (START_CHAR(tty) << 8) | (u16) (STOP_CHAR(tty)));

		status = qt2_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
					 x, port_priv->device_port);
	} else
		status = qt2_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
					 0, port_priv->device_port);

	if (status < 0)
		dev_err(&port->dev, "%s - set SW flow control failed: %i\n",
			__func__, status);

}
Пример #27
0
static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
{
	unsigned long flags;
	int parmrk;

	if (tty->raw) {
		put_tty_queue(c, tty);
		return;
	}

	if (I_ISTRIP(tty))
		c &= 0x7f;
	if (I_IUCLC(tty) && L_IEXTEN(tty))
		c = tolower(c);

	if (L_EXTPROC(tty)) {
		put_tty_queue(c, tty);
		return;
	}

	if (tty->stopped && !tty->flow_stopped && I_IXON(tty) &&
	    I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) &&
	    c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) {
		start_tty(tty);
		process_echoes(tty);
	}

	if (tty->closing) {
		if (I_IXON(tty)) {
			if (c == START_CHAR(tty)) {
				start_tty(tty);
				process_echoes(tty);
			} else if (c == STOP_CHAR(tty))
				stop_tty(tty);
		}
		return;
	}

	if (!test_bit(c, tty->process_char_map) || tty->lnext) {
		tty->lnext = 0;
		parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
		if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
			
			if (L_ECHO(tty))
				process_output('\a', tty);
			return;
		}
		if (L_ECHO(tty)) {
			finish_erasing(tty);
			
			if (tty->canon_head == tty->read_head)
				echo_set_canon_col(tty);
			echo_char(c, tty);
			process_echoes(tty);
		}
		if (parmrk)
			put_tty_queue(c, tty);
		put_tty_queue(c, tty);
		return;
	}

	if (I_IXON(tty)) {
		if (c == START_CHAR(tty)) {
			start_tty(tty);
			process_echoes(tty);
			return;
		}
		if (c == STOP_CHAR(tty)) {
			stop_tty(tty);
			return;
		}
	}

	if (L_ISIG(tty)) {
		int signal;
		signal = SIGINT;
		if (c == INTR_CHAR(tty))
			goto send_signal;
		signal = SIGQUIT;
		if (c == QUIT_CHAR(tty))
			goto send_signal;
		signal = SIGTSTP;
		if (c == SUSP_CHAR(tty)) {
send_signal:
			if (!L_NOFLSH(tty)) {
				n_tty_flush_buffer(tty);
				tty_driver_flush_buffer(tty);
			}
			if (I_IXON(tty))
				start_tty(tty);
			if (L_ECHO(tty)) {
				echo_char(c, tty);
				process_echoes(tty);
			}
			if (tty->pgrp)
				kill_pgrp(tty->pgrp, signal, 1);
			return;
		}
	}

	if (c == '\r') {
		if (I_IGNCR(tty))
			return;
		if (I_ICRNL(tty))
			c = '\n';
	} else if (c == '\n' && I_INLCR(tty))
		c = '\r';

	if (tty->icanon) {
		if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
		    (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
			eraser(c, tty);
			process_echoes(tty);
			return;
		}
		if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {
			tty->lnext = 1;
			if (L_ECHO(tty)) {
				finish_erasing(tty);
				if (L_ECHOCTL(tty)) {
					echo_char_raw('^', tty);
					echo_char_raw('\b', tty);
					process_echoes(tty);
				}
			}
			return;
		}
		if (c == REPRINT_CHAR(tty) && L_ECHO(tty) &&
		    L_IEXTEN(tty)) {
			unsigned long tail = tty->canon_head;

			finish_erasing(tty);
			echo_char(c, tty);
			echo_char_raw('\n', tty);
			while (tail != tty->read_head) {
				echo_char(tty->read_buf[tail], tty);
				tail = (tail+1) & (N_TTY_BUF_SIZE-1);
			}
			process_echoes(tty);
			return;
		}
		if (c == '\n') {
			if (tty->read_cnt >= N_TTY_BUF_SIZE) {
				if (L_ECHO(tty))
					process_output('\a', tty);
				return;
			}
			if (L_ECHO(tty) || L_ECHONL(tty)) {
				echo_char_raw('\n', tty);
				process_echoes(tty);
			}
			goto handle_newline;
		}
		if (c == EOF_CHAR(tty)) {
			if (tty->read_cnt >= N_TTY_BUF_SIZE)
				return;
			if (tty->canon_head != tty->read_head)
				set_bit(TTY_PUSH, &tty->flags);
			c = __DISABLED_CHAR;
			goto handle_newline;
		}
		if ((c == EOL_CHAR(tty)) ||
		    (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) {
			parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty))
				 ? 1 : 0;
			if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk)) {
				if (L_ECHO(tty))
					process_output('\a', tty);
				return;
			}
			if (L_ECHO(tty)) {
				
				if (tty->canon_head == tty->read_head)
					echo_set_canon_col(tty);
				echo_char(c, tty);
				process_echoes(tty);
			}
			if (parmrk)
				put_tty_queue(c, tty);

handle_newline:
			spin_lock_irqsave(&tty->read_lock, flags);
			set_bit(tty->read_head, tty->read_flags);
			put_tty_queue_nolock(c, tty);
			tty->canon_head = tty->read_head;
			tty->canon_data++;
			spin_unlock_irqrestore(&tty->read_lock, flags);
			kill_fasync(&tty->fasync, SIGIO, POLL_IN);
			if (waitqueue_active(&tty->read_wait))
				wake_up_interruptible(&tty->read_wait);
			return;
		}
	}

	parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
	if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
		
		if (L_ECHO(tty))
			process_output('\a', tty);
		return;
	}
	if (L_ECHO(tty)) {
		finish_erasing(tty);
		if (c == '\n')
			echo_char_raw('\n', tty);
		else {
			
			if (tty->canon_head == tty->read_head)
				echo_set_canon_col(tty);
			echo_char(c, tty);
		}
		process_echoes(tty);
	}

	if (parmrk)
		put_tty_queue(c, tty);

	put_tty_queue(c, tty);
}
Пример #28
0
static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
{
	int canon_change = 1;
	BUG_ON(!tty);

	if (old)
		canon_change = (old->c_lflag ^ tty->termios->c_lflag) & ICANON;
	if (canon_change) {
		memset(&tty->read_flags, 0, sizeof tty->read_flags);
		tty->canon_head = tty->read_tail;
		tty->canon_data = 0;
		tty->erasing = 0;
	}

	if (canon_change && !L_ICANON(tty) && tty->read_cnt)
		wake_up_interruptible(&tty->read_wait);

	tty->icanon = (L_ICANON(tty) != 0);
	if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
		tty->raw = 1;
		tty->real_raw = 1;
		n_tty_set_room(tty);
		return;
	}
	if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||
	    I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
	    I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
	    I_PARMRK(tty)) {
		memset(tty->process_char_map, 0, 256/8);

		if (I_IGNCR(tty) || I_ICRNL(tty))
			set_bit('\r', tty->process_char_map);
		if (I_INLCR(tty))
			set_bit('\n', tty->process_char_map);

		if (L_ICANON(tty)) {
			set_bit(ERASE_CHAR(tty), tty->process_char_map);
			set_bit(KILL_CHAR(tty), tty->process_char_map);
			set_bit(EOF_CHAR(tty), tty->process_char_map);
			set_bit('\n', tty->process_char_map);
			set_bit(EOL_CHAR(tty), tty->process_char_map);
			if (L_IEXTEN(tty)) {
				set_bit(WERASE_CHAR(tty),
					tty->process_char_map);
				set_bit(LNEXT_CHAR(tty),
					tty->process_char_map);
				set_bit(EOL2_CHAR(tty),
					tty->process_char_map);
				if (L_ECHO(tty))
					set_bit(REPRINT_CHAR(tty),
						tty->process_char_map);
			}
		}
		if (I_IXON(tty)) {
			set_bit(START_CHAR(tty), tty->process_char_map);
			set_bit(STOP_CHAR(tty), tty->process_char_map);
		}
		if (L_ISIG(tty)) {
			set_bit(INTR_CHAR(tty), tty->process_char_map);
			set_bit(QUIT_CHAR(tty), tty->process_char_map);
			set_bit(SUSP_CHAR(tty), tty->process_char_map);
		}
		clear_bit(__DISABLED_CHAR, tty->process_char_map);
		tty->raw = 0;
		tty->real_raw = 0;
	} else {
		tty->raw = 1;
		if ((I_IGNBRK(tty) || (!I_BRKINT(tty) && !I_PARMRK(tty))) &&
		    (I_IGNPAR(tty) || !I_INPCK(tty)) &&
		    (tty->driver->flags & TTY_DRIVER_REAL_RAW))
			tty->real_raw = 1;
		else
			tty->real_raw = 0;
	}
	n_tty_set_room(tty);
	
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->read_wait);
}
Пример #29
0
static void ssu100_set_termios(struct tty_struct *tty,
			       struct usb_serial_port *port,
			       struct ktermios *old_termios)
{
	struct usb_device *dev = port->serial->dev;
	struct ktermios *termios = &tty->termios;
	u16 baud, divisor, remainder;
	unsigned int cflag = termios->c_cflag;
	u16 urb_value = 0; /* will hold the new flags */
	int result;

	if (cflag & PARENB) {
		if (cflag & PARODD)
			urb_value |= UART_LCR_PARITY;
		else
			urb_value |= SERIAL_EVEN_PARITY;
	}

	switch (cflag & CSIZE) {
	case CS5:
		urb_value |= UART_LCR_WLEN5;
		break;
	case CS6:
		urb_value |= UART_LCR_WLEN6;
		break;
	case CS7:
		urb_value |= UART_LCR_WLEN7;
		break;
	default:
	case CS8:
		urb_value |= UART_LCR_WLEN8;
		break;
	}

	baud = tty_get_baud_rate(tty);
	if (!baud)
		baud = 9600;

	dev_dbg(&port->dev, "%s - got baud = %d\n", __func__, baud);


	divisor = MAX_BAUD_RATE / baud;
	remainder = MAX_BAUD_RATE % baud;
	if (((remainder * 2) >= baud) && (baud != 110))
		divisor++;

	urb_value = urb_value << 8;

	result = ssu100_control_msg(dev, QT_GET_SET_UART, divisor, urb_value);
	if (result < 0)
		dev_dbg(&port->dev, "%s - set uart failed\n", __func__);

	if (cflag & CRTSCTS)
		result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
					    SERIAL_CRTSCTS, 0);
	else
		result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
					    0, 0);
	if (result < 0)
		dev_dbg(&port->dev, "%s - set HW flow control failed\n", __func__);

	if (I_IXOFF(tty) || I_IXON(tty)) {
		u16 x = ((u16)(START_CHAR(tty) << 8) | (u16)(STOP_CHAR(tty)));

		result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
					    x, 0);
	} else
		result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
					    0, 0);

	if (result < 0)
		dev_dbg(&port->dev, "%s - set SW flow control failed\n", __func__);

}
Пример #30
0
static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
{
	if (tty->raw) {
		put_tty_queue(c, tty);
		return;
	}
	
	if (tty->stopped && I_IXON(tty) && I_IXANY(tty)) {
		start_tty(tty);
		return;
	}
	
	if (I_ISTRIP(tty))
		c &= 0x7f;
	if (I_IUCLC(tty) && L_IEXTEN(tty))
		c=tolower(c);

	if (tty->closing) {
		if (I_IXON(tty)) {
			if (c == START_CHAR(tty))
				start_tty(tty);
			else if (c == STOP_CHAR(tty))
				stop_tty(tty);
		}
		return;
	}

	/*
	 * If the previous character was LNEXT, or we know that this
	 * character is not one of the characters that we'll have to
	 * handle specially, do shortcut processing to speed things
	 * up.
	 */
	if (!test_bit(c, &tty->process_char_map) || tty->lnext) {
		finish_erasing(tty);
		tty->lnext = 0;
		if (L_ECHO(tty)) {
			if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
				put_char('\a', tty); /* beep if no space */
				return;
			}
			/* Record the column of first canon char. */
			if (tty->canon_head == tty->read_head)
				tty->canon_column = tty->column;
			echo_char(c, tty);
		}
		if (I_PARMRK(tty) && c == (unsigned char) '\377')
			put_tty_queue(c, tty);
		put_tty_queue(c, tty);
		return;
	}
		
	if (c == '\r') {
		if (I_IGNCR(tty))
			return;
		if (I_ICRNL(tty))
			c = '\n';
	} else if (c == '\n' && I_INLCR(tty))
		c = '\r';
	if (I_IXON(tty)) {
		if (c == START_CHAR(tty)) {
			start_tty(tty);
			return;
		}
		if (c == STOP_CHAR(tty)) {
			stop_tty(tty);
			return;
		}
	}
	if (L_ISIG(tty)) {
		int signal;
		signal = SIGINT;
		if (c == INTR_CHAR(tty))
			goto send_signal;
		signal = SIGQUIT;
		if (c == QUIT_CHAR(tty))
			goto send_signal;
		signal = SIGTSTP;
		if (c == SUSP_CHAR(tty)) {
send_signal:
			isig(signal, tty, 0);
			return;
		}
	}
	if (L_ICANON(tty)) {
		if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
		    (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
			eraser(c, tty);
			return;
		}
		if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {
			tty->lnext = 1;
			if (L_ECHO(tty)) {
				finish_erasing(tty);
				if (L_ECHOCTL(tty)) {
					put_char('^', tty);
					put_char('\b', tty);
				}
			}
			return;
		}
		if (c == REPRINT_CHAR(tty) && L_ECHO(tty) &&
		    L_IEXTEN(tty)) {
			unsigned long tail = tty->canon_head;

			finish_erasing(tty);
			echo_char(c, tty);
			opost('\n', tty);
			while (tail != tty->read_head) {
				echo_char(tty->read_buf[tail], tty);
				tail = (tail+1) & (N_TTY_BUF_SIZE-1);
			}
			return;
		}
		if (c == '\n') {
			if (L_ECHO(tty) || L_ECHONL(tty)) {
				if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
					put_char('\a', tty);
					return;
				}
				opost('\n', tty);
			}
			goto handle_newline;
		}
		if (c == EOF_CHAR(tty)) {
		        if (tty->canon_head != tty->read_head)
			        set_bit(TTY_PUSH, &tty->flags);
			c = __DISABLED_CHAR;
			goto handle_newline;
		}
		if ((c == EOL_CHAR(tty)) ||
		    (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) {
			/*
			 * XXX are EOL_CHAR and EOL2_CHAR echoed?!?
			 */
			if (L_ECHO(tty)) {
				if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
					put_char('\a', tty);
					return;
				}
				/* Record the column of first canon char. */
				if (tty->canon_head == tty->read_head)
					tty->canon_column = tty->column;
				echo_char(c, tty);
			}
			/*
			 * XXX does PARMRK doubling happen for
			 * EOL_CHAR and EOL2_CHAR?
			 */
			if (I_PARMRK(tty) && c == (unsigned char) '\377')
				put_tty_queue(c, tty);

		handle_newline:
			set_bit(tty->read_head, &tty->read_flags);
			put_tty_queue(c, tty);
			tty->canon_head = tty->read_head;
			tty->canon_data++;
			if (tty->fasync)
				kill_fasync(tty->fasync, SIGIO);
			if (tty->read_wait)
				wake_up_interruptible(&tty->read_wait);
			return;
		}
	}
	
	finish_erasing(tty);
	if (L_ECHO(tty)) {
		if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
			put_char('\a', tty); /* beep if no space */
			return;
		}
		if (c == '\n')
			opost('\n', tty);
		else {
			/* Record the column of first canon char. */
			if (tty->canon_head == tty->read_head)
				tty->canon_column = tty->column;
			echo_char(c, tty);
		}
	}

	if (I_PARMRK(tty) && c == (unsigned char) '\377')
		put_tty_queue(c, tty);

	put_tty_queue(c, tty);
}