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); } }
/* 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); }
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); }
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; }
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; }
static void send_intr(void) { if (!tty) return; tty_insert_flip_char(tty, 0, TTY_BREAK); tty_schedule_flip(tty); }
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)); } }
static void put_queue(int ch) { wake_up(&keypress_wait); if (tty) { tty_insert_flip_char(tty, ch, 0); tty_schedule_flip(tty); } }
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); }
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; }
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); }
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 (); }
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); }
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); }
/* 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; }
/* 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; }
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; }
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; }
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; }
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); }
/* 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); }
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; }
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"); }
/* * 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); }
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; }
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); }