static void
vcons_rx_intr (NkPort* port)
{
    unsigned int		size;
    int				i;
    int				count = 0;

    while ((size = vcons_rxfifo_count(port))) {
        if (port->count == 0) {
            return;
        }

        if (port->stoprx) {
            break;
        }

        /* ask how many characters we can read */
        size = tty_buffer_request_room(port->tty, size);
        if (size == 0) {
            return;
        }

        size = os_ctx->cops.read(port->id, port->buf, size);
        count += size;
        for (i = 0; i < size; i++) {
            tty_insert_flip_char(port->tty, port->buf[i], TTY_NORMAL);
        }
    }

    if (count > 0) {
        tty_schedule_flip(port->tty);
    }
}
示例#2
0
/* Poll for input on the console, and if there's any, deliver it to the
   tty driver.  */
void simcons_poll_tty (struct tty_struct *tty)
{
	char buf[32];	/* Not the nicest way to do it but I need it correct first */
	int flip = 0, send_break = 0;
	struct pollfd pfd;
	pfd.fd = 0;
	pfd.events = POLLIN;

	if (V850_SIM_SYSCALL (poll, &pfd, 1, 0) > 0) {
		if (pfd.revents & POLLIN) {
			/* Real block hardware knows the transfer size before
			   transfer so the new tty buffering doesn't try to handle
			   this rather weird simulator specific case well */
			int rd = V850_SIM_SYSCALL (read, 0, buf, 32);
			if (rd > 0) {
				tty_insert_flip_string(tty, buf, rd);
				flip = 1;
			} else
				send_break = 1;
		} else if (pfd.revents & POLLERR)
			send_break = 1;
	}

	if (send_break) {
		tty_insert_flip_char (tty, 0, TTY_BREAK);		
		flip = 1;
	}

	if (flip)
		tty_schedule_flip (tty);
}
示例#3
0
static void tiny_timer (unsigned long data)
{
	struct tiny_serial *tiny = (struct tiny_serial *)data;
	struct tty_struct *tty;

	if (!tiny)
		return;

	tty = tiny->tty;

	if (tty->flip.count >= TTY_FLIPBUF_SIZE)
		tty_flip_buffer_push(tty);

	/* add two characters to the tty port */
	/* this doesn't actually push the data through unless tty->low_latency is set */
	tty_insert_flip_char(tty, TINY_DATA_CHARACTER, 0);
	tty_insert_flip_char(tty, '\n', 0);

	tty_flip_buffer_push(tty);
	tty_schedule_flip (tty);
	
	/* resubmit the timer again */
	tiny->timer->expires = jiffies + DELAY_TIME;
	add_timer (tiny->timer);
}
示例#4
0
文件: stty.c 项目: ShinySide/SM-G361H
static void stty_handler (int event, void* data)
{
	struct stty_device *stty = data;
	int i, cnt = 0;
	unsigned char buf[STTY_MAX_DATA_LEN] = {0};

	pr_debug("stty handler event=%d \n", event);

	switch(event) {
		case SBUF_NOTIFY_WRITE:
			break;
		case SBUF_NOTIFY_READ:
			cnt = sbuf_read(stty->pdata->dst, stty->pdata->channel,
					stty->pdata->bufid,(void *)buf, STTY_MAX_DATA_LEN, 0);
			pr_debug("stty handler read data len =%d \n", cnt);
			mutex_lock(&(stty->stat_lock));
			if ((stty->state == STTY_STATE_OPEN) && (cnt > 0)) {
				for(i = 0; i < cnt; i++) {
					tty_insert_flip_char(stty->port, buf[i], TTY_NORMAL);
				}
				tty_schedule_flip(stty->port);
			}
			mutex_unlock(&(stty->stat_lock));
			break;
		default:
			printk(KERN_ERR "Received event is invalid(event=%d)\n", event);
	}

	return;
}
示例#5
0
static irqreturn_t v850e_uart_rx_irq(int irq, void *data, struct pt_regs *regs)
{
	struct uart_port *port = data;
	unsigned ch_stat = TTY_NORMAL;
	unsigned ch = v850e_uart_getc (port->line);
	unsigned err = v850e_uart_err (port->line);

	if (err) {
		if (err & V850E_UART_ERR_OVERRUN) {
			ch_stat = TTY_OVERRUN;
			port->icount.overrun++;
		} else if (err & V850E_UART_ERR_FRAME) {
			ch_stat = TTY_FRAME;
			port->icount.frame++;
		} else if (err & V850E_UART_ERR_PARITY) {
			ch_stat = TTY_PARITY;
			port->icount.parity++;
		}
	}

	port->icount.rx++;

	tty_insert_flip_char (port->info->tty, ch, ch_stat);
	tty_schedule_flip (port->info->tty);

	return IRQ_HANDLED;
}
示例#6
0
static void send_intr(void)
{
	if (!tty)
		return;
	tty_insert_flip_char(tty, 0, TTY_BREAK);
	tty_schedule_flip(tty);
}
示例#7
0
static void __serial_lpc32xx_rx(struct uart_port *port)
{
	unsigned int tmp, flag;

	/* Read data from FIFO and push into terminal */
	tmp = __raw_readl(LPC32XX_HSUART_FIFO(port->membase));
	while (!(tmp & LPC32XX_HSU_RX_EMPTY)) {
		flag = TTY_NORMAL;
		port->icount.rx++;

		if (tmp & LPC32XX_HSU_ERROR_DATA) {
			/* Framing error */
			__raw_writel(LPC32XX_HSU_FE_INT,
				LPC32XX_HSUART_IIR(port->membase));
			port->icount.frame++;
			flag = TTY_FRAME;
			tty_insert_flip_char(port->state->port.tty, 0,
				TTY_FRAME);
			tty_schedule_flip(port->state->port.tty);
		}

		tty_insert_flip_char(port->state->port.tty, (tmp & 0xFF),
			flag);

		tmp = __raw_readl(LPC32XX_HSUART_FIFO(port->membase));
	}
}
示例#8
0
static void put_queue(int ch)
{
	wake_up(&keypress_wait);
	if (tty) {
		tty_insert_flip_char(tty, ch, 0);
		tty_schedule_flip(tty);
	}
}
示例#9
0
static void puts_queue(struct vc_data *vc, char *cp)
{
	while (*cp) {
		tty_insert_flip_char(&vc->port, *cp, 0);
		cp++;
	}
	tty_schedule_flip(&vc->port);
}
示例#10
0
static void receive_chars(struct m68k_serial *info, unsigned short rx)
{
	struct tty_struct *tty = info->tty;
	m68328_uart *uart = &uart_addr[info->line];
	unsigned char ch, flag;

	/*
	 * This do { } while() loop will get ALL chars out of Rx FIFO
         */
#ifndef CONFIG_XCOPILOT_BUGS
	do {
#endif
		ch = GET_FIELD(rx, URX_RXDATA);

		if(info->is_cons) {
			if(URX_BREAK & rx) { /* whee, break received */
				status_handle(info, rx);
				return;
#ifdef CONFIG_MAGIC_SYSRQ
			} else if (ch == 0x10) { /* ^P */
				show_state();
				show_free_areas(0);
				show_buffers();
/*				show_net_buffers(); */
				return;
			} else if (ch == 0x12) { /* ^R */
				emergency_restart();
				return;
#endif /* CONFIG_MAGIC_SYSRQ */
			}
		}

		if(!tty)
			goto clear_and_exit;

		flag = TTY_NORMAL;

		if(rx & URX_PARITY_ERROR) {
			flag = TTY_PARITY;
			status_handle(info, rx);
		} else if(rx & URX_OVRUN) {
			flag = TTY_OVERRUN;
			status_handle(info, rx);
		} else if(rx & URX_FRAME_ERROR) {
			flag = TTY_FRAME;
			status_handle(info, rx);
		}
		tty_insert_flip_char(tty, ch, flag);
#ifndef CONFIG_XCOPILOT_BUGS
	} while((rx = uart->urx.w) & URX_DATA_READY);
#endif

	tty_schedule_flip(tty);

clear_and_exit:
	return;
}
示例#11
0
static _INLINE_ void receive_break(ser_info_t *info)
{
	struct tty_struct *tty = info->port.tty;

	info->state->icount.brk++;
	/* Check to see if there is room in the tty buffer for
	 * the break.  If not, we exit now, losing the break.  FIXME
	 */
	tty_insert_flip_char(tty, 0, TTY_BREAK);
	tty_schedule_flip(tty);
}
示例#12
0
void gs_got_break(struct gs_port *port)
{
	func_enter ();

	tty_insert_flip_char(port->tty, 0, TTY_BREAK);
	tty_schedule_flip(port->tty);
	if (port->flags & ASYNC_SAK) {
		do_SAK (port->tty);
	}

	func_exit ();
}
示例#13
0
static void puts_queue(char *cp)
{
	wake_up(&keypress_wait);
	if (!tty)
		return;

	while (*cp) {
		tty_insert_flip_char(tty, *cp, 0);
		cp++;
	}
	tty_schedule_flip(tty);
}
示例#14
0
static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id)
{
	struct uart_port *port = dev_id;
	u32 status;

	spin_lock(&port->lock);

	/* Read UART status and clear latched interrupts */
	status = __raw_readl(LPC32XX_HSUART_IIR(port->membase));

	if (status & LPC32XX_HSU_BRK_INT) {
		/* Break received */
		__raw_writel(LPC32XX_HSU_BRK_INT,
			LPC32XX_HSUART_IIR(port->membase));
		port->icount.brk++;
		uart_handle_break(port);
	}

	/* Framing error */
	if (status & LPC32XX_HSU_FE_INT)
		__raw_writel(LPC32XX_HSU_FE_INT,
			LPC32XX_HSUART_IIR(port->membase));

	if (status & LPC32XX_HSU_RX_OE_INT) {
		/* Receive FIFO overrun */
		__raw_writel(LPC32XX_HSU_RX_OE_INT,
			LPC32XX_HSUART_IIR(port->membase));
		port->icount.overrun++;
		tty_insert_flip_char(port->state->port.tty, 0, TTY_OVERRUN);
		tty_schedule_flip(port->state->port.tty);
	}

	/* Data received? */
	if (status & (LPC32XX_HSU_RX_TIMEOUT_INT | LPC32XX_HSU_RX_TRIG_INT)) {
		__serial_lpc32xx_rx(port);
		spin_unlock(&port->lock);
		tty_flip_buffer_push(port->state->port.tty);
		spin_lock(&port->lock);
	}

	/* Transmit data request? */
	if ((status & LPC32XX_HSU_TX_INT) && (!uart_tx_stopped(port))) {
		__raw_writel(LPC32XX_HSU_TX_INT,
			LPC32XX_HSUART_IIR(port->membase));
		__serial_lpc32xx_tx(port);
	}

	spin_unlock(&port->lock);

	return IRQ_HANDLED;
}
static void hvc_poll(int index)
{
	struct hvc_struct *hp = &hvc_struct[index];
	struct tty_struct *tty;
	int i, n;
	char buf[16] __ALIGNED__;
	unsigned long flags;

	spin_lock_irqsave(&hp->lock, flags);

	if (hp->n_outbuf > 0)
		hvc_push(hp);

	tty = hp->tty;
	if (tty) {
		for (;;) {
			if (TTY_FLIPBUF_SIZE - tty->flip.count < sizeof(buf))
				break;
			n = hvc_get_chars(index + hvc_offset, buf, sizeof(buf));
			if (n <= 0)
				break;
			for (i = 0; i < n; ++i) {
#ifdef CONFIG_MAGIC_SYSRQ		/* Handle the SysRq Hack */
				if (buf[i] == '\x0f') {	/* ^O -- should support a sequence */
					sysrq_pressed = 1;
					continue;
				} else if (sysrq_pressed) {
					handle_sysrq(buf[i], NULL, NULL, tty);
					sysrq_pressed = 0;
					continue;
				}
#endif
				tty_insert_flip_char(tty, buf[i], 0);
			}
		}
		if (tty->flip.count)
			tty_schedule_flip(tty);

		if (hp->do_wakeup) {
			hp->do_wakeup = 0;
			if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
			    && tty->ldisc.write_wakeup)
				(tty->ldisc.write_wakeup)(tty);
			wake_up_interruptible(&tty->write_wait);
		}
	}

	spin_unlock_irqrestore(&hp->lock, flags);
}
示例#16
0
/* Called with callback_lock held */
static int softuart_do_receive_chars(struct tty_struct *tty)
{
	int len = 0;
	char buf[1024];
	int n;

	/* Need to check to see if anything's available */
	len = hv_dev_pread(softuart_fd, 0, (HV_VirtAddr)(buf),
			   1024, SOFTUART_DATA_READ);
	if (len > 0) {
		for (n = 0; n < len; n++)
			tty_insert_flip_char(tty, buf[n], 0);
		tty_schedule_flip(tty);
	} else if (len < 0)
		pr_err("softuart:  Couldn't read from HV: %d\n", len);

	return len;
}
static inline void receive_chars(struct mcf_serial *info)
{
	volatile unsigned char	*uartp;
	struct tty_struct	*tty = info->port.tty;
	unsigned char		status, ch, flag;

	if (!tty)
		return;

	uartp = info->addr;

	while ((status = uartp[MCFUART_USR]) & MCFUART_USR_RXREADY) {
		ch = uartp[MCFUART_URB];
		info->stats.rx++;

#ifdef CONFIG_MAGIC_SYSRQ
		if (mcfrs_console_inited && (info->line == mcfrs_console_port)) {
			if (magic_sysrq_key(ch))
				continue;
		}
#endif

		flag = TTY_NORMAL;
		if (status & MCFUART_USR_RXERR) {
			uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR;
			if (status & MCFUART_USR_RXBREAK) {
				info->stats.rxbreak++;
				flag = TTY_BREAK;
			} else if (status & MCFUART_USR_RXPARITY) {
				info->stats.rxparity++;
				flag = TTY_PARITY;
			} else if (status & MCFUART_USR_RXOVERRUN) {
				info->stats.rxoverrun++;
				flag = TTY_OVERRUN;
			} else if (status & MCFUART_USR_RXFRAMING) {
				info->stats.rxframing++;
				flag = TTY_FRAME;
			}
		}
		tty_insert_flip_char(tty, ch, flag);
	}
	tty_schedule_flip(tty);
	return;
}
示例#18
0
/* called with callback_lock held */
static int
srmcons_do_receive_chars(struct tty_port *port)
{
	srmcons_result result;
	int count = 0, loops = 0;

	do {
		result.as_long = callback_getc(0);
		if (result.bits.status < 2) {
			tty_insert_flip_char(port, (char)result.bits.c, 0);
			count++;
		}
	} while((result.bits.status & 1) && (++loops < 10));

	if (count)
		tty_schedule_flip(port);

	return count;
}
示例#19
0
static irqreturn_t goldfish_tty_interrupt(int irq, void *dev_id)
{
	struct goldfish_tty *qtty = dev_id;
	void __iomem *base = qtty->base;
	unsigned long address;
	unsigned char *buf;
	u32 count;

	count = readl(base + GOLDFISH_TTY_REG_BYTES_READY);
	if (count == 0)
		return IRQ_NONE;

	count = tty_prepare_flip_string(&qtty->port, &buf, count);

	address = (unsigned long)(void *)buf;
	goldfish_tty_rw(qtty, address, count, 0);

	tty_schedule_flip(&qtty->port);
	return IRQ_HANDLED;
}
示例#20
0
static irqreturn_t goldfish_tty_interrupt(int irq, void *dev_id)
{
	struct platform_device *pdev = dev_id;
	struct goldfish_tty *qtty = &goldfish_ttys[pdev->id];
	uint32_t base = qtty->base;
	unsigned long irq_flags;
	unsigned char *buf;
	uint32_t count;

	count = readl(base + GOLDFISH_TTY_BYTES_READY);
	if(count == 0) {
		return IRQ_NONE;
	}
	count = tty_prepare_flip_string(qtty->tty, &buf, count);
	spin_lock_irqsave(&qtty->lock, irq_flags);
	writel(buf, base + GOLDFISH_TTY_DATA_PTR);
	writel(count, base + GOLDFISH_TTY_DATA_LEN);
	writel(GOLDFISH_TTY_CMD_READ_BUFFER, base + GOLDFISH_TTY_CMD);
	spin_unlock_irqrestore(&qtty->lock, irq_flags);
	tty_schedule_flip(qtty->tty);
	return IRQ_HANDLED;
}
示例#21
0
文件: spk_ttyio.c 项目: mkrufky/linux
static unsigned char ttyio_in(int timeout)
{
	struct spk_ldisc_data *ldisc_data = speakup_tty->disc_data;
	char rv;

	if (down_timeout(&ldisc_data->sem, usecs_to_jiffies(timeout)) == -ETIME) {
		if (timeout)
			pr_warn("spk_ttyio: timeout (%d)  while waiting for input\n",
				timeout);
		return 0xff;
	}

	rv = ldisc_data->buf;
	/* Make sure we have read buf before we set buf_free to let
	 * the producer overwrite it */
	mb();
	ldisc_data->buf_free = true;
	/* Let TTY push more characters */
	tty_schedule_flip(speakup_tty->port);

	return rv;
}
示例#22
0
void nb85e_uart_tty_rx_irq (int irq, void *data, struct pt_regs *regs)
{
	struct nb85e_uart_tty_port *port = data;

	if (port->gs.flags & GS_ACTIVE) {
		unsigned ch_stat;
		unsigned err = NB85E_UART_ASIS (port->chan);
		unsigned ch = NB85E_UART_RXB (port->chan);

		if (err & NB85E_UART_ASIS_OVE)
			ch_stat = TTY_OVERRUN;
		else if (err & NB85E_UART_ASIS_FE)
			ch_stat = TTY_FRAME;
		else if (err & NB85E_UART_ASIS_PE)
			ch_stat = TTY_PARITY;
		else
			ch_stat = TTY_NORMAL;

		tty_insert_flip_char (port->gs.tty, ch, ch_stat);
		tty_schedule_flip (port->gs.tty);
	} else
		nb85e_uart_tty_disable_rx_interrupts (port);
}
示例#23
0
/* Poll for input on the console, and if there's any, deliver it to the
   tty driver.  */
void simcons_poll_tty (struct tty_struct *tty)
{
	int flip = 0, send_break = 0;
	struct pollfd pfd;
	pfd.fd = 0;
	pfd.events = POLLIN;

	if (V850_SIM_SYSCALL (poll, &pfd, 1, 0) > 0) {
		if (pfd.revents & POLLIN) {
			int left = TTY_FLIPBUF_SIZE - tty->flip.count;

			if (left > 0) {
				unsigned char *buf = tty->flip.char_buf_ptr;
				int rd = V850_SIM_SYSCALL (read, 0, buf, left);

				if (rd > 0) {
					tty->flip.count += rd;
					tty->flip.char_buf_ptr += rd;
					memset (tty->flip.flag_buf_ptr, 0, rd);
					tty->flip.flag_buf_ptr += rd;
					flip = 1;
				} else
					send_break = 1;
			}
		} else if (pfd.revents & POLLERR)
			send_break = 1;
	}

	if (send_break) {
		tty_insert_flip_char (tty, 0, TTY_BREAK);		
		flip = 1;
	}

	if (flip)
		tty_schedule_flip (tty);
}
示例#24
0
static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *regs, unsigned short rx)
{
	struct tty_struct *tty = info->tty;
	m68328_uart *uart = &uart_addr[info->line];
	unsigned char ch, flag;

	/*
	 * This do { } while() loop will get ALL chars out of Rx FIFO 
         */
#ifndef CONFIG_XCOPILOT_BUGS
	do {
#endif	
		ch = GET_FIELD(rx, URX_RXDATA);
	
		if(info->is_cons) {
			if(URX_BREAK & rx) { /* whee, break received */
				status_handle(info, rx);
				return;
#ifdef CONFIG_MAGIC_SYSRQ
			} else if (ch == 0x10) { /* ^P */
				show_state();
				show_free_areas();
				show_buffers();
/*				show_net_buffers(); */
				return;
			} else if (ch == 0x12) { /* ^R */
				emergency_restart();
				return;
#endif /* CONFIG_MAGIC_SYSRQ */
			}
			/* It is a 'keyboard interrupt' ;-) */
#ifdef CONFIG_CONSOLE
			wake_up(&keypress_wait);
#endif			
		}

		if(!tty)
			goto clear_and_exit;
		
		/*
		 * Make sure that we do not overflow the buffer
		 */
		if (tty_request_buffer_room(tty, 1) == 0) {
			tty_schedule_flip(tty);
			return;
		}

		flag = TTY_NORMAL;

		if(rx & URX_PARITY_ERROR) {
			flag = TTY_PARITY;
			status_handle(info, rx);
		} else if(rx & URX_OVRUN) {
			flag = TTY_OVERRUN;
			status_handle(info, rx);
		} else if(rx & URX_FRAME_ERROR) {
			flag = TTY_FRAME;
			status_handle(info, rx);
		}
		tty_insert_flip_char(tty, ch, flag);
#ifndef CONFIG_XCOPILOT_BUGS
	} while((rx = uart->urx.w) & URX_DATA_READY);
#endif

	tty_schedule_flip(tty);

clear_and_exit:
	return;
}
示例#25
0
void jsm_input(struct jsm_channel *ch)
{
	struct jsm_board *bd;
	struct tty_struct *tp;
	u32 rmask;
	u16 head;
	u16 tail;
	int data_len;
	unsigned long lock_flags;
	int flip_len;
	int len = 0;
	int n = 0;
	char *buf = NULL;
	char *buf2 = NULL;
	int s = 0;
	int i = 0;

	jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start\n");

	if (!ch)
		return;

	tp = ch->uart_port.info->tty;

	bd = ch->ch_bd;
	if(!bd)
		return;

	spin_lock_irqsave(&ch->ch_lock, lock_flags);

	/*
	 *Figure the number of characters in the buffer.
	 *Exit immediately if none.
	 */

	rmask = RQUEUEMASK;

	head = ch->ch_r_head & rmask;
	tail = ch->ch_r_tail & rmask;

	data_len = (head - tail) & rmask;
	if (data_len == 0) {
		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
		return;
	}

	jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start\n");

	/*
	 *If the device is not open, or CREAD is off, flush
	 *input data and return immediately.
	 */
	if (!tp ||
		!(tp->termios->c_cflag & CREAD) ) {

		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
			"input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum);
		ch->ch_r_head = tail;

		/* Force queue flow control to be released, if needed */
		jsm_check_queue_flow_control(ch);

		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
		return;
	}

	/*
	 * If we are throttled, simply don't read any data.
	 */
	if (ch->ch_flags & CH_STOPI) {
		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
			"Port %d throttled, not reading any data. head: %x tail: %x\n",
			ch->ch_portnum, head, tail);
		return;
	}

	jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start 2\n");

	/*
	 * If the rxbuf is empty and we are not throttled, put as much
	 * as we can directly into the linux TTY flip buffer.
	 * The jsm_rawreadok case takes advantage of carnal knowledge that
	 * the char_buf and the flag_buf are next to each other and
	 * are each of (2 * TTY_FLIPBUF_SIZE) size.
	 *
	 * NOTE: if(!tty->real_raw), the call to ldisc.receive_buf
	 *actually still uses the flag buffer, so you can't
	 *use it for input data
	 */
	if (jsm_rawreadok) {
		if (tp->real_raw)
			flip_len = MYFLIPLEN;
		else
			flip_len = 2 * TTY_FLIPBUF_SIZE;
	} else
		flip_len = TTY_FLIPBUF_SIZE - tp->flip.count;

	len = min(data_len, flip_len);
	len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt);

	if (len <= 0) {
		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n");
		return;
	}

	/*
	 * If we're bypassing flip buffers on rx, we can blast it
	 * right into the beginning of the buffer.
	 */
	if (jsm_rawreadok) {
		if (tp->real_raw) {
			if (ch->ch_flags & CH_FLIPBUF_IN_USE) {
				jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
					"JSM - FLIPBUF in use. delaying input\n");
				spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
				return;
			}
			ch->ch_flags |= CH_FLIPBUF_IN_USE;
			buf = ch->ch_bd->flipbuf;
			buf2 = NULL;
		} else {
			buf = tp->flip.char_buf;
			buf2 = tp->flip.flag_buf;
		}
	} else {
		buf = tp->flip.char_buf_ptr;
		buf2 = tp->flip.flag_buf_ptr;
	}

	n = len;

	/*
	 * n now contains the most amount of data we can copy,
	 * bounded either by the flip buffer size or the amount
	 * of data the card actually has pending...
	 */
	while (n) {
		s = ((head >= tail) ? head : RQUEUESIZE) - tail;
		s = min(s, n);

		if (s <= 0)
			break;

		memcpy(buf, ch->ch_rqueue + tail, s);

		/* buf2 is only set when port isn't raw */
		if (buf2)
			memcpy(buf2, ch->ch_equeue + tail, s);

		tail += s;
		buf += s;
		if (buf2)
			buf2 += s;
		n -= s;
		/* Flip queue if needed */
		tail &= rmask;
	}

	/*
	 * In high performance mode, we don't have to update
	 * flag_buf or any of the counts or pointers into flip buf.
	 */
	if (!jsm_rawreadok) {
		if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
			for (i = 0; i < len; i++) {
				/*
				 * Give the Linux ld the flags in the
				 * format it likes.
				 */
				if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI)
					tp->flip.flag_buf_ptr[i] = TTY_BREAK;
				else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE)
					tp->flip.flag_buf_ptr[i] = TTY_PARITY;
				else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE)
					tp->flip.flag_buf_ptr[i] = TTY_FRAME;
				else
					tp->flip.flag_buf_ptr[i] = TTY_NORMAL;
			}
		} else {
			memset(tp->flip.flag_buf_ptr, 0, len);
		}

		tp->flip.char_buf_ptr += len;
		tp->flip.flag_buf_ptr += len;
		tp->flip.count += len;
	}
	else if (!tp->real_raw) {
		if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
			for (i = 0; i < len; i++) {
				/*
				 * Give the Linux ld the flags in the
				 * format it likes.
				 */
				if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI)
					tp->flip.flag_buf_ptr[i] = TTY_BREAK;
				else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE)
					tp->flip.flag_buf_ptr[i] = TTY_PARITY;
				else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE)
					tp->flip.flag_buf_ptr[i] = TTY_FRAME;
				else
					tp->flip.flag_buf_ptr[i] = TTY_NORMAL;
			}
		} else
			memset(tp->flip.flag_buf, 0, len);
	}

	/*
	 * If we're doing raw reads, jam it right into the
	 * line disc bypassing the flip buffers.
	 */
	if (jsm_rawreadok) {
		if (tp->real_raw) {
			ch->ch_r_tail = tail & rmask;
			ch->ch_e_tail = tail & rmask;

			jsm_check_queue_flow_control(ch);

			/* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */

			spin_unlock_irqrestore(&ch->ch_lock, lock_flags);

			jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
				"jsm_input. %d real_raw len:%d calling receive_buf for board %d\n",
				__LINE__, len, ch->ch_bd->boardnum);
			tp->ldisc.receive_buf(tp, ch->ch_bd->flipbuf, NULL, len);

			/* Allow use of channel flip buffer again */
			spin_lock_irqsave(&ch->ch_lock, lock_flags);
			ch->ch_flags &= ~CH_FLIPBUF_IN_USE;
			spin_unlock_irqrestore(&ch->ch_lock, lock_flags);

		} else {
			ch->ch_r_tail = tail & rmask;
			ch->ch_e_tail = tail & rmask;

			jsm_check_queue_flow_control(ch);

			/* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */
			spin_unlock_irqrestore(&ch->ch_lock, lock_flags);

			jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
				"jsm_input. %d not real_raw len:%d calling receive_buf for board %d\n",
				__LINE__, len, ch->ch_bd->boardnum);

			tp->ldisc.receive_buf(tp, tp->flip.char_buf, tp->flip.flag_buf, len);
		}
	} else {
		ch->ch_r_tail = tail & rmask;
		ch->ch_e_tail = tail & rmask;

		jsm_check_queue_flow_control(ch);

		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);

		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
			"jsm_input. %d not jsm_read raw okay scheduling flip\n", __LINE__);
		tty_schedule_flip(tp);
	}

	jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
}
示例#26
0
/*
 * Helper Functions.
 */
static void put_queue(struct vc_data *vc, int ch)
{
	tty_insert_flip_char(&vc->port, ch, 0);
	tty_schedule_flip(&vc->port);
}
static inline void
dma_receive_chars(struct uart_pxa_port *up, int *status)
{
	struct tty_port *port = &up->port.state->port;
	unsigned char ch;
	int max_count = 256;
	int count = 0;
	unsigned char *tmp;
	unsigned int flag = TTY_NORMAL;
	struct uart_pxa_dma *pxa_dma = &up->uart_dma;
	struct dma_tx_state dma_state;

	/*
	 * Pause DMA channel and deal with the bytes received by DMA
	 */
	dmaengine_pause(pxa_dma->rxdma_chan);
	dmaengine_tx_status(pxa_dma->rxdma_chan, pxa_dma->rx_cookie,
			    &dma_state);
	count = DMA_BLOCK - dma_state.residue;
	tmp = pxa_dma->rxdma_addr;
	if (up->port.sysrq) {
		while (count > 0) {
			if (!uart_handle_sysrq_char(&up->port, *tmp)) {
				uart_insert_char(&up->port, *status,
						 0, *tmp, flag);
				up->port.icount.rx++;
			}
			tmp++;
			count--;
		}
	} else {
		tty_insert_flip_string(port, tmp, count);
		up->port.icount.rx += count;
	}

	/* deal with the bytes in rx FIFO */
	do {
		ch = serial_in(up, UART_RX);
		flag = TTY_NORMAL;
		up->port.icount.rx++;

		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
					UART_LSR_FE | UART_LSR_OE))) {
			/*
			 * For statistics only
			 */
			if (*status & UART_LSR_BI) {
				*status &= ~(UART_LSR_FE | UART_LSR_PE);
				up->port.icount.brk++;
				/*
				 * We do the SysRQ and SAK checking
				 * here because otherwise the break
				 * may get masked by ignore_status_mask
				 * or read_status_mask.
				 */
				if (uart_handle_break(&up->port))
					goto ignore_char2;
			} else if (*status & UART_LSR_PE) {
				up->port.icount.parity++;
			} else if (*status & UART_LSR_FE) {
				up->port.icount.frame++;
			}
			if (*status & UART_LSR_OE)
				up->port.icount.overrun++;

			/*
			 * Mask off conditions which should be ignored.
			 */
			*status &= up->port.read_status_mask;

#ifdef CONFIG_SERIAL_PXA_CONSOLE
			if (up->port.line == up->port.cons->index) {
				/* Recover the break flag from console xmit */
				*status |= up->lsr_break_flag;
				up->lsr_break_flag = 0;
			}
#endif
			if (*status & UART_LSR_BI)
				flag = TTY_BREAK;
			else if (*status & UART_LSR_PE)
				flag = TTY_PARITY;
			else if (*status & UART_LSR_FE)
				flag = TTY_FRAME;
		}
		if (!uart_handle_sysrq_char(&up->port, ch))
			uart_insert_char(&up->port, *status, UART_LSR_OE,
					 ch, flag);
ignore_char2:
		*status = serial_in(up, UART_LSR);
	} while ((*status & UART_LSR_DR) && (max_count-- > 0));

	tty_schedule_flip(port);
	stop_dma(up, 1);
	if (pxa_dma->rx_stop)
		return;
	pxa_uart_receive_dma_start(up);
}
示例#28
0
static void qt_read_bulk_callback(struct urb *urb)
{

	struct usb_serial_port *port = urb->context;
	struct usb_serial *serial = get_usb_serial(port, __func__);
	struct quatech_port *qt_port = qt_get_port_private(port);
	int result;

	if (urb->status) {
		qt_port->ReadBulkStopped = 1;
		dev_dbg(&urb->dev->dev,
			"%s - nonzero write bulk status received: %d\n",
			__func__, urb->status);
		return;
	}

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

	if (port_paranoia_check(port, __func__) != 0) {
		qt_port->ReadBulkStopped = 1;
		return;
	}

	if (!serial)
		return;

	if (qt_port->closePending == 1) {
		/* Were closing , stop reading */
		dev_dbg(&port->dev,
			"%s - (qt_port->closepending == 1\n", __func__);
		qt_port->ReadBulkStopped = 1;
		return;
	}

	/*
	 * RxHolding is asserted by throttle, if we assert it, we're not
	 * receiving any more characters and let the box handle the flow
	 * control
	 */
	if (qt_port->RxHolding == 1) {
		qt_port->ReadBulkStopped = 1;
		return;
	}

	if (urb->status) {
		qt_port->ReadBulkStopped = 1;

		dev_dbg(&port->dev,
			"%s - nonzero read bulk status received: %d\n",
			__func__, urb->status);
		return;
	}

	if (urb->actual_length)
		qt_status_change_check(urb, qt_port, port);

	/* Continue trying to always read  */
	usb_fill_bulk_urb(port->read_urb, serial->dev,
			  usb_rcvbulkpipe(serial->dev,
					  port->bulk_in_endpointAddress),
			  port->read_urb->transfer_buffer,
			  port->read_urb->transfer_buffer_length,
			  qt_read_bulk_callback, port);
	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
	if (result)
		dev_dbg(&port->dev,
			"%s - failed resubmitting read urb, error %d",
			__func__, result);
	else {
		if (urb->actual_length) {
			tty_flip_buffer_push(&port->port);
			tty_schedule_flip(&port->port);
		}
	}

	schedule_work(&port->work);
}
static int	XVU_write(struct tty_struct *tty, const unsigned char *buffer,
					  int count)
{
	int			idx = 0;
	struct tty_struct	*peer = NULL;
	int			rv = -EINVAL;
	unsigned long		flags = 0;

	if (down_interruptible(&xvu_dev.sem))
		return -ERESTARTSYS;

	if (tty == NULL) {
		XVU_ERR( "Invalid (NULL) tty_struct\n");
		goto out;
	}

	if (buffer == NULL) {
		XVU_ERR( "Invalid (NULL) buffer\n");
		goto out;
	}

	if (count <= 0 ) {
		XVU_ERR( ": Invalid count = 0\n");
		goto out;
	}

	idx = tty->index;

	if ( (idx<0) || (idx >= XVU_PAIRS*2) || (idx != (int)tty->driver_data) ) {
		XVU_ERR( "Index %d out of range.\n", idx);
		goto out;
	}


	/* Is endpoint open ? */
	if (! xvu_dev.endpoint[idx].open_count ) {
		XVU_ERR( "Endpoint %d doesn't seem to be open.\n", idx);
		goto out;
	}

	/*
	* Send string to peer
	* If peer is closed, discard the string...
	* ...but return count as if we sent it.
	*/

	/* Is peer open ? */
	if (! xvu_dev.endpoint[__XVU_GetPeerIdx(idx)].open_count ) {
		/* Discard sent bytes ! */
		rv = count;
		goto out;
	}

	/* Safety ! Shouldn't happen !!! */
	peer = xvu_dev.endpoint[__XVU_GetPeerIdx(idx)].tty;
	if (! peer ) {
		/* Discard sent bytes ! */
		XVU_ERR( "endpoint[%d].tty is NULL\n", __XVU_GetPeerIdx(idx));
		rv = count;
		goto out;
	}

	rv = tty_buffer_request_room(tty->port, count);
	if (unlikely(rv == 0)) {
		XVU_ERR("tty_buffer_request_room rv:%d\n",rv);
	}
	rv = tty_insert_flip_string(peer->port, buffer, count);
	tty_schedule_flip(peer->port);

out:
	/* Update counters */
	if (rv > 0) {
		spin_lock_irqsave(&xvu_dev.endpoint[idx].sercnt_lock, flags);
		xvu_dev.endpoint[ idx ].ser_cnt.tx += rv;
		spin_unlock_irqrestore(&xvu_dev.endpoint[idx].sercnt_lock, flags);

		spin_lock_irqsave(&xvu_dev.endpoint[__XVU_GetPeerIdx(idx)].sercnt_lock, flags);
		xvu_dev.endpoint[__XVU_GetPeerIdx(idx)].ser_cnt.rx += rv;
		spin_unlock_irqrestore(&xvu_dev.endpoint[__XVU_GetPeerIdx(idx)].sercnt_lock, flags);
	}

	up(&xvu_dev.sem);
	return rv;
}
示例#30
0
static _INLINE_ void receive_chars(ser_info_t *info)
{
	struct tty_struct *tty = info->port.tty;
	unsigned char ch, flag, *cp;
	/*int	ignored = 0;*/
	int	i;
	ushort	status;
	 struct	async_icount *icount; 
	/* struct	async_icount_24 *icount; */
	volatile QUICC_BD	*bdp;

	icount = &info->state->icount;

	/* Just loop through the closed BDs and copy the characters into
	 * the buffer.
	 */
	bdp = info->rx_cur;
	for (;;) {
		if (bdp->status & BD_SC_EMPTY)	/* If this one is empty */
			break;			/*   we are all done */

		/* The read status mask tell us what we should do with
		 * incoming characters, especially if errors occur.
		 * One special case is the use of BD_SC_EMPTY.  If
		 * this is not set, we are supposed to be ignoring
		 * inputs.  In this case, just mark the buffer empty and
		 * continue.
		 */
		if (!(info->read_status_mask & BD_SC_EMPTY)) {
			bdp->status |= BD_SC_EMPTY;
			bdp->status &=
				~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);

			if (bdp->status & BD_SC_WRAP)
				bdp = info->rx_bd_base;
			else
				bdp++;
			continue;
		}

		/* Get the number of characters and the buffer pointer.
		*/
		i = bdp->length;
		/* cp = (unsigned char *)__va(bdp->buf); */
		cp = (char *)bdp->buf;
		status = bdp->status;

		while (i-- > 0) {
			ch = *cp++;
			icount->rx++;

#ifdef SERIAL_DEBUG_INTR
			printk("DR%02x:%02x...", ch, status);
#endif
			flag = TTY_NORMAL;

			if (status & (BD_SC_BR | BD_SC_FR |
				       BD_SC_PR | BD_SC_OV)) {
				/*
				 * For statistics only
				 */
				if (status & BD_SC_BR)
					icount->brk++;
				else if (status & BD_SC_PR)
					icount->parity++;
				else if (status & BD_SC_FR)
					icount->frame++;
				if (status & BD_SC_OV)
					icount->overrun++;

				/*
				 * Now check to see if character should be
				 * ignored, and mask off conditions which
				 * should be ignored.
				if (status & info->ignore_status_mask) {
					if (++ignored > 100)
						break;
					continue;
				}
				 */
				status &= info->read_status_mask;
		
				if (status & (BD_SC_BR)) {
#ifdef SERIAL_DEBUG_INTR
					printk("handling break....");
#endif
					*tty->flip.flag_buf_ptr = TTY_BREAK;
					if (info->flags & ASYNC_SAK)
						do_SAK(tty);
				} else if (status & BD_SC_PR)
					flag = TTY_PARITY;
				else if (status & BD_SC_FR)
					flag = TTY_FRAME;
			}
			tty_insert_flip_char(tty, ch, flag);
			if (status & BD_SC_OV)
				/*
				 * Overrun is special, since it's
				 * reported immediately, and doesn't
				 * affect the current character
				 */
				tty_insert_flip_char(tty, 0, TTY_OVERRUN);
		}

		/* This BD is ready to be used again.  Clear status.
		 * Get next BD.
		 */
		bdp->status |= BD_SC_EMPTY;
		bdp->status &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);

		if (bdp->status & BD_SC_WRAP)
			bdp = info->rx_bd_base;
		else
			bdp++;
	}

	info->rx_cur = (QUICC_BD *)bdp;

	tty_schedule_flip(tty);
}