static void ssauart_rx_chars (struct uart_port *port) #endif { #if 1 struct tty_struct *tty = port->info->tty; while (1) { if ((UART_GET_LSR(port) & (1 << 0)) == 0) /* no more chars available */ break; *tty->flip.char_buf_ptr++ = UART_GET_CHAR(port); *tty->flip.flag_buf_ptr++ = TTY_NORMAL; /* Fixme: we should check for overrun, parity, framing errors etc */ port->icount.rx++; tty->flip.count++; if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; } tty_flip_buffer_push (tty); #else struct tty_struct *tty = port->info->tty; unsigned int ch; unsigned int status; unsigned int max_count = 256; while (1) { status = UART_GET_LSR(port); if (((status & (1 << 0)) == 0) || (--max_count == 0)) break; if (tty->flip.count >= TTY_FLIPBUF_SIZE) { tty->flip.tqueue.routine ((void *) tty); if (tty->flip.count >= TTY_FLIPBUF_SIZE) { printk (KERN_WARNING "TTY_DONT_FLIP set\n"); return; } } *tty->flip.char_buf_ptr++ = UART_GET_CHAR(port); *tty->flip.flag_buf_ptr++ = TTY_NORMAL; /* Fixme: we should check for overrun, parity, framing errors etc */ tty->flip.count++; port->icount.rx++; } tty_flip_buffer_push (tty); #endif }
static void s3c2440_rx_int(int irq, void *dev_id, struct pt_regs *regs) { struct uart_info *info = dev_id; struct tty_struct *tty = info->tty; unsigned int status, ch, max_count = 256; struct uart_port *port = info->port; status = UART_GET_UTRSTAT(port); while ((status & UTRSTAT_RX_RDY) && max_count--) { if (tty->flip.count >= TTY_FLIPBUF_SIZE) { tty->flip.tqueue.routine((void *) tty); if (tty->flip.count >= TTY_FLIPBUF_SIZE) { printk(KERN_WARNING "TTY_DONT_FLIP set\n"); return; } } ch = UART_GET_CHAR(port); *tty->flip.char_buf_ptr = ch; *tty->flip.flag_buf_ptr = TTY_NORMAL; port->icount.rx++; tty->flip.flag_buf_ptr++; tty->flip.char_buf_ptr++; tty->flip.count++; status = UART_GET_UTRSTAT(port); } tty_flip_buffer_push(tty); return; }
static void apbuart_flush_fifo(struct uart_port *port) { int i; for (i = 0; i < port->fifosize; i++) UART_GET_CHAR(port); }
static int sa1100_console_wait_key(struct console *co) { struct uart_port *port = sa1100_ports + co->index; unsigned long flags; u_int old_utcr3, status, ch; /* * Save UTCR3 and disable interrupts */ save_flags(flags); cli(); old_utcr3 = UART_GET_UTCR3(port); UART_PUT_UTCR3(port, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)); restore_flags(flags); /* * Wait for a character */ do { status = UART_GET_UTSR1(port); } while (!(status & UTSR1_RNE)); ch = UART_GET_CHAR(port); /* * Restore UTCR3 */ UART_PUT_UTCR3(port, old_utcr3); return ch; }
static int omahauart_console_wait_key(struct console *co) { struct uart_port *port = omaha_ports + co->index; unsigned int status; do { status = UART_FIFO_STATUS(port); } while (!UART_RX_DATA(status)); return UART_GET_CHAR(port); }
/* * Characters received (called from interrupt handler) */ static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs) { struct tty_struct *tty = port->info->tty; unsigned int status, ch, flg; status = UART_GET_CSR(port) & port->read_status_mask; while (status & (AT91_US_RXRDY)) { ch = UART_GET_CHAR(port); port->icount.rx++; flg = TTY_NORMAL; /* * note that the error handling code is * out of the main execution path */ if (unlikely(status & (AT91_US_PARE | AT91_US_FRAME | AT91_US_OVRE))) { UART_PUT_CR(port, AT91_US_RSTSTA); /* clear error */ if (status & (AT91_US_PARE)) port->icount.parity++; if (status & (AT91_US_FRAME)) port->icount.frame++; if (status & (AT91_US_OVRE)) port->icount.overrun++; if (status & AT91_US_PARE) flg = TTY_PARITY; else if (status & AT91_US_FRAME) flg = TTY_FRAME; if (status & AT91_US_OVRE) { /* * overrun does *not* affect the character * we read from the FIFO */ tty_insert_flip_char(tty, ch, flg); ch = 0; flg = TTY_OVERRUN; } #ifdef SUPPORT_SYSRQ port->sysrq = 0; #endif } if (uart_handle_sysrq_char(port, ch, regs)) goto ignore_char; tty_insert_flip_char(tty, ch, flg); ignore_char: status = UART_GET_CSR(port) & port->read_status_mask; } tty_flip_buffer_push(tty); }
static irqreturn_t ks8695uart_rx_chars(int irq, void *dev_id) { struct uart_port *port = dev_id; struct tty_struct *tty = port->info->port.tty; unsigned int status, ch, lsr, flg, max_count = 256; status = UART_GET_LSR(port); /* clears pending LSR interrupts */ while ((status & URLS_URDR) && max_count--) { ch = UART_GET_CHAR(port); flg = TTY_NORMAL; port->icount.rx++; /* * Note that the error handling code is * out of the main execution path */ lsr = UART_GET_LSR(port) | UART_DUMMY_LSR_RX; if (unlikely(lsr & (URLS_URBI | URLS_URPE | URLS_URFE | URLS_URROE))) { if (lsr & URLS_URBI) { lsr &= ~(URLS_URFE | URLS_URPE); port->icount.brk++; if (uart_handle_break(port)) goto ignore_char; } if (lsr & URLS_URPE) port->icount.parity++; if (lsr & URLS_URFE) port->icount.frame++; if (lsr & URLS_URROE) port->icount.overrun++; lsr &= port->read_status_mask; if (lsr & URLS_URBI) flg = TTY_BREAK; else if (lsr & URLS_URPE) flg = TTY_PARITY; else if (lsr & URLS_URFE) flg = TTY_FRAME; } if (uart_handle_sysrq_char(port, ch)) goto ignore_char; uart_insert_char(port, lsr, URLS_URROE, ch, flg); ignore_char: status = UART_GET_LSR(port); } tty_flip_buffer_push(tty); return IRQ_HANDLED; }
static void bfin_sir_rx_chars(struct net_device *dev) { struct bfin_sir_self *self = netdev_priv(dev); struct bfin_sir_port *port = self->sir_port; unsigned char ch; UART_CLEAR_LSR(port); ch = UART_GET_CHAR(port); async_unwrap_char(dev, &self->stats, &self->rx_buff, ch); dev->last_rx = jiffies; }
static void apbuart_rx_chars(struct uart_port *port) { unsigned int status, ch, rsr, flag; unsigned int max_chars = port->fifosize; status = UART_GET_STATUS(port); while (UART_RX_DATA(status) && (max_chars--)) { ch = UART_GET_CHAR(port); flag = TTY_NORMAL; port->icount.rx++; rsr = UART_GET_STATUS(port) | UART_DUMMY_RSR_RX; UART_PUT_STATUS(port, 0); if (rsr & UART_STATUS_ERR) { if (rsr & UART_STATUS_BR) { rsr &= ~(UART_STATUS_FE | UART_STATUS_PE); port->icount.brk++; if (uart_handle_break(port)) goto ignore_char; } else if (rsr & UART_STATUS_PE) { port->icount.parity++; } else if (rsr & UART_STATUS_FE) { port->icount.frame++; } if (rsr & UART_STATUS_OE) port->icount.overrun++; rsr &= port->read_status_mask; if (rsr & UART_STATUS_PE) flag = TTY_PARITY; else if (rsr & UART_STATUS_FE) flag = TTY_FRAME; } if (uart_handle_sysrq_char(port, ch)) goto ignore_char; uart_insert_char(port, rsr, UART_STATUS_OE, ch, flag); ignore_char: status = UART_GET_STATUS(port); } spin_unlock(&port->lock); tty_flip_buffer_push(&port->state->port); spin_lock(&port->lock); }
/* * Characters received (called from interrupt handler) */ static void atmel_rx_chars(struct uart_port *port) { struct tty_struct *tty = port->info->tty; unsigned int status, ch, flg; status = UART_GET_CSR(port); while (status & ATMEL_US_RXRDY) { ch = UART_GET_CHAR(port); port->icount.rx++; flg = TTY_NORMAL; /* * note that the error handling code is * out of the main execution path */ if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME | ATMEL_US_OVRE | ATMEL_US_RXBRK))) { UART_PUT_CR(port, ATMEL_US_RSTSTA); /* clear error */ if (status & ATMEL_US_RXBRK) { status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME); /* ignore side-effect */ port->icount.brk++; if (uart_handle_break(port)) goto ignore_char; } if (status & ATMEL_US_PARE) port->icount.parity++; if (status & ATMEL_US_FRAME) port->icount.frame++; if (status & ATMEL_US_OVRE) port->icount.overrun++; status &= port->read_status_mask; if (status & ATMEL_US_RXBRK) flg = TTY_BREAK; else if (status & ATMEL_US_PARE) flg = TTY_PARITY; else if (status & ATMEL_US_FRAME) flg = TTY_FRAME; } if (uart_handle_sysrq_char(port, ch)) goto ignore_char; uart_insert_char(port, status, ATMEL_US_OVRE, ch, flg); ignore_char: status = UART_GET_CSR(port); } tty_flip_buffer_push(tty); }
static void sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs) { struct tty_struct *tty = sport->port.info->tty; unsigned int status, ch, flg; status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | UTSR0_TO_SM(UART_GET_UTSR0(sport)); while (status & UTSR1_TO_SM(UTSR1_RNE)) { ch = UART_GET_CHAR(sport); if (tty->flip.count >= TTY_FLIPBUF_SIZE) goto ignore_char; sport->port.icount.rx++; flg = TTY_NORMAL; /* * note that the error handling code is * out of the main execution path */ if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR)) { if (status & UTSR1_TO_SM(UTSR1_PRE)) sport->port.icount.parity++; else if (status & UTSR1_TO_SM(UTSR1_FRE)) sport->port.icount.frame++; if (status & UTSR1_TO_SM(UTSR1_ROR)) sport->port.icount.overrun++; status &= sport->port.read_status_mask; if (status & UTSR1_TO_SM(UTSR1_PRE)) flg = TTY_PARITY; else if (status & UTSR1_TO_SM(UTSR1_FRE)) flg = TTY_FRAME; #ifdef SUPPORT_SYSRQ sport->port.sysrq = 0; #endif } if (uart_handle_sysrq_char(&sport->port, ch, regs)) goto ignore_char; uart_insert_char(&sport->port, status, UTSR1_TO_SM(UTSR1_ROR), ch, flg); ignore_char: status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | UTSR0_TO_SM(UART_GET_UTSR0(sport)); } tty_flip_buffer_push(tty); }
pl010_rx_chars(struct uart_port *port) #endif { struct tty_struct *tty = port->info->tty; unsigned int status, ch, flag, rsr, max_count = 256; status = UART_GET_FR(port); while (UART_RX_DATA(status) && max_count--) { ch = UART_GET_CHAR(port); flag = TTY_NORMAL; port->icount.rx++; /* * Note that the error handling code is * out of the main execution path */ rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX; if (unlikely(rsr & UART01x_RSR_ANY)) { if (rsr & UART01x_RSR_BE) { rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE); port->icount.brk++; if (uart_handle_break(port)) goto ignore_char; } else if (rsr & UART01x_RSR_PE) port->icount.parity++; else if (rsr & UART01x_RSR_FE) port->icount.frame++; if (rsr & UART01x_RSR_OE) port->icount.overrun++; rsr &= port->read_status_mask; if (rsr & UART01x_RSR_BE) flag = TTY_BREAK; else if (rsr & UART01x_RSR_PE) flag = TTY_PARITY; else if (rsr & UART01x_RSR_FE) flag = TTY_FRAME; } if (uart_handle_sysrq_char(port, ch, regs)) goto ignore_char; uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag); ignore_char: status = UART_GET_FR(port); } tty_flip_buffer_push(tty); return; }
int get_char(char *buf, int i, int len) { int j = 0; UART_DIB_RIRQ(i); while(UART_GET_RSR(i)) { buf[j++] = UART_GET_CHAR(i); if(j == len) break; } UART_ENB_RIRQ(i); return j; }
static int bfin_serial_poll_get_char(struct uart_port *port) { struct bfin_serial_port *uart = (struct bfin_serial_port *)port; unsigned char chr; while (!(UART_GET_LSR(uart) & DR)) cpu_relax(); UART_CLEAR_DLAB(uart); chr = UART_GET_CHAR(uart); return chr; }
static void s3c2440_err_int(int irq, void *dev_id, struct pt_regs *regs) { struct uart_info *info = dev_id; struct uart_port *port = info->port; struct tty_struct *tty = info->tty; unsigned int ch, flg; unsigned char err; spin_lock(&info->lock); ch = UART_GET_CHAR (port); err = UART_GET_UERSTAT(port) & (UERSTAT_BRK | UERSTAT_FRAME | UERSTAT_PARITY | UERSTAT_OVERRUN); if (!err) return ; if (err & UERSTAT_BRK) port->icount.brk++; if (err & UERSTAT_FRAME) port->icount.frame++; if (err & UERSTAT_PARITY) port->icount.parity++; if (err & UERSTAT_OVERRUN) port->icount.overrun++; err &= port->read_status_mask; if (err & UERSTAT_PARITY) flg = TTY_PARITY; else if (err & UERSTAT_FRAME) flg = TTY_FRAME; else flg = TTY_NORMAL; if (err & UERSTAT_OVERRUN) { *tty->flip.char_buf_ptr = ch; *tty->flip.flag_buf_ptr = flg; tty->flip.flag_buf_ptr++; tty->flip.char_buf_ptr++; tty->flip.count++; if (tty->flip.count < TTY_FLIPBUF_SIZE) { ch = 0; flg = TTY_OVERRUN; } } *tty->flip.flag_buf_ptr++ = flg; *tty->flip.char_buf_ptr++ = ch; tty->flip.count++; spin_unlock(&info->lock); }
static void get_buf(struct serial_dev *devp) { UART_DIB_RIRQ(devp->index);//disable recvive irq while(devp->recv_full_flag == 0 && UART_GET_RSR(devp->index)) { devp->recv_buf[devp->recv_wr_point++] = UART_GET_CHAR(devp->index); if(devp->recv_wr_point >= MAX_BUF_LEN) devp->recv_wr_point = 0; if(devp->recv_wr_point == devp->recv_rd_point) devp->recv_full_flag = 1; } UART_ENB_RIRQ(devp->index); return ; }
/* * AT91_iso_getchar * * Utility to retrieve one char from USART controller * * by polling UART_CSR register, if ready, get UART_RHR. */ char AT91_iso_getchar(unsigned int nWait100cycle) { unsigned int CSR_status=0; while (!((CSR_status = UART_GET_CSR(base)) & AT91C_US_RXRDY)) { if (nWait100cycle>0) { udelay(20); // cycle time?? nWait100cycle--; if (nWait100cycle <= 0) { // timeout, break loop printk(KERN_INFO "[sam.ko] AT91_iso_getchar(): timeout\n"); return 0; } } } return (UART_GET_CHAR(base) & 0x1FF); }
static void sa1100_rx_chars(struct sa1100_port *sport) { struct tty_struct *tty = sport->port.state->port.tty; unsigned int status, ch, flg; status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | UTSR0_TO_SM(UART_GET_UTSR0(sport)); while (status & UTSR1_TO_SM(UTSR1_RNE)) { ch = UART_GET_CHAR(sport); sport->port.icount.rx++; flg = TTY_NORMAL; if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR)) { if (status & UTSR1_TO_SM(UTSR1_PRE)) sport->port.icount.parity++; else if (status & UTSR1_TO_SM(UTSR1_FRE)) sport->port.icount.frame++; if (status & UTSR1_TO_SM(UTSR1_ROR)) sport->port.icount.overrun++; status &= sport->port.read_status_mask; if (status & UTSR1_TO_SM(UTSR1_PRE)) flg = TTY_PARITY; else if (status & UTSR1_TO_SM(UTSR1_FRE)) flg = TTY_FRAME; #ifdef SUPPORT_SYSRQ sport->port.sysrq = 0; #endif } if (uart_handle_sysrq_char(&sport->port, ch)) goto ignore_char; uart_insert_char(&sport->port, status, UTSR1_TO_SM(UTSR1_ROR), ch, flg); ignore_char: status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | UTSR0_TO_SM(UART_GET_UTSR0(sport)); } tty_flip_buffer_push(tty); }
static ssize_t sam_read(struct file *file, char *buf, size_t count, loff_t *ptr) { unsigned long flags; unsigned int CSR_status=0; unsigned int i; int timeout=0; char *tmpBuf = (char *)kmalloc(count, GFP_KERNEL); int retval=0; if (!tmpBuf) return -ENOMEM; // SPIN Lock to protect reading from SAM spin_lock_irqsave(&sam_spinlock, flags); if (DEBUG) { printk(KERN_INFO "SAM Read count = %d\n", count); } for (i=0; i<count; i++) { timeout = 10000; while (!((CSR_status = UART_GET_CSR(base)) & AT91C_US_RXRDY)) { timeout--; if (timeout == 0) { printk(KERN_INFO "SAM Read Timeout == 0!\n"); break; } } tmpBuf[i] = (UART_GET_CHAR(base) & 0x1FF); if (DEBUG) printk(KERN_INFO "[%.2X]", tmpBuf[i]); } if (DEBUG) { if (timeout == 0) printk(KERN_INFO "SAM Read Timeout == 0!\n"); } spin_unlock_irqrestore(&sam_spinlock, flags); // SPIN Lock end // Move Kernel Space Memory to User Space retval = copy_to_user(buf, tmpBuf, i); // free kernel memory kfree(tmpBuf); return 0; }
static ssize_t sam_write(struct file *file, const char *buf, size_t count, loff_t * ppos) { unsigned long flags; unsigned int CSR_status=0; unsigned int i; int data; char *tmpBuf = (char *)kmalloc(count, GFP_KERNEL); if (!tmpBuf) return -ENOMEM; // Move User Space Memory to Kernel Space if (copy_from_user(tmpBuf, buf, count)) { kfree(tmpBuf); return -EFAULT; } // SPIN Lock to protect writing to SAM spin_lock_irqsave(&sam_spinlock, flags); // Part 1, clear receive buffer while (((CSR_status = UART_GET_CSR(base)) & AT91C_US_RXRDY)) { data = (UART_GET_CHAR(base) & 0x1FF); } // Part 2, write to UART's THR for (i=0; i<count; i++) { // Wait unit TX ready while (!((CSR_status = UART_GET_CSR(base)) & AT91C_US_TXRDY)); // copy buffer UART_PUT_CHAR(base, (tmpBuf[i] & 0xFF)); // Wait unit TX empty while (!((CSR_status = UART_GET_CSR(base)) & AT91C_US_TXEMPTY)); } spin_unlock_irqrestore(&sam_spinlock, flags); // SPIN Lock end // free kernel memory kfree(tmpBuf); return 0; }
ambauart_rx_chars(struct uart_port *port, unsigned short status) #endif { struct tty_struct *tty = port->info->tty; unsigned short ch, lsr, max_count = 256; while (UART_RX_DATA(status) && max_count--) { lsr = status; if (tty->flip.count >= TTY_FLIPBUF_SIZE) { tty->flip.tqueue.routine((void *)tty); if (tty->flip.count >= TTY_FLIPBUF_SIZE) { printk(KERN_WARNING "TTY_DONT_FLIP set\n"); return; } } ch = UART_GET_CHAR(port); *tty->flip.char_buf_ptr = ch; *tty->flip.flag_buf_ptr = TTY_NORMAL; port->icount.rx++; /* * Note that the error handling code is * out of the main execution path */ lsr |= UART_DUMMY_LSR_RX; if (lsr & KS8695_UART_LINES_ANY) { if (lsr & KS8695_UART_LINES_BE) { lsr &= ~(KS8695_UART_LINES_FE | KS8695_UART_LINES_PE); port->icount.brk++; if (uart_handle_break(port)) goto ignore_char; } else if (lsr & KS8695_UART_LINES_PE) port->icount.parity++; else if (lsr & KS8695_UART_LINES_FE) port->icount.frame++; if (lsr & KS8695_UART_LINES_OE) port->icount.overrun++; lsr &= port->read_status_mask; if (lsr & KS8695_UART_LINES_BE) *tty->flip.flag_buf_ptr = TTY_BREAK; else if (lsr & KS8695_UART_LINES_PE) *tty->flip.flag_buf_ptr = TTY_PARITY; else if (lsr & KS8695_UART_LINES_FE) *tty->flip.flag_buf_ptr = TTY_FRAME; } if (uart_handle_sysrq_char(port, ch, regs)) goto ignore_char; if ((lsr & port->ignore_status_mask) == 0) { tty->flip.flag_buf_ptr++; tty->flip.char_buf_ptr++; tty->flip.count++; } if ((lsr & KS8695_UART_LINES_OE) && tty->flip.count < TTY_FLIPBUF_SIZE) { /* * Overrun is special, since it's reported * immediately, and doesn't affect the current * character */ *tty->flip.char_buf_ptr++ = 0; *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; tty->flip.count++; } ignore_char: status = UART_GET_LSR(port); } tty_flip_buffer_push(tty); return; }
leonuart_rx_chars(struct uart_port *port) #endif { struct tty_struct *tty = port->info->tty; unsigned int status, ch, flag, rsr, max_count = 256; status = UART_GET_STATUS(port); while (UART_RX_DATA(status) && max_count--) { //if (tty->flip.count >= TTY_FLIPBUF_SIZE) { // if (tty->low_latency) // tty_flip_buffer_push(tty); /* * If this failed then we will throw away the * bytes but must do so to clear interrupts. */ //} ch = UART_GET_CHAR(port); flag = TTY_NORMAL; port->icount.rx++; /* * Note that the error handling code is * out of the main execution path */ rsr = UART_GET_STATUS(port) | UART_DUMMY_RSR_RX; UART_PUT_STATUS(port, 0); if (rsr & LEON_USTAT_ERROR) { if (rsr & LEON_USTAT_BR) { rsr &= ~(LEON_USTAT_FE | LEON_USTAT_PE); port->icount.brk++; if (uart_handle_break(port)) goto ignore_char; } else if (rsr & LEON_USTAT_PE) { port->icount.parity++; } else if (rsr & LEON_USTAT_FE) { port->icount.frame++; } if (rsr & LEON_USTAT_OV) port->icount.overrun++; rsr &= port->read_status_mask; if (rsr & LEON_USTAT_BR) flag = TTY_BREAK; else if (rsr & LEON_USTAT_PE) flag = TTY_PARITY; else if (rsr & LEON_USTAT_FE) flag = TTY_FRAME; } if (uart_handle_sysrq_char(port, ch)) goto ignore_char; if ((rsr & port->ignore_status_mask) == 0) { tty_insert_flip_char(tty, ch, flag); } if (rsr & LEON_USTAT_OV) { /* * Overrun is special, since it's reported * immediately, and doesn't affect the current * character */ tty_insert_flip_char(tty, 0, TTY_OVERRUN); } ignore_char: status = UART_GET_STATUS(port); } tty_flip_buffer_push(tty); return; }
static void bfin_serial_rx_chars(struct bfin_serial_port *uart) { struct tty_struct *tty = NULL; unsigned int status, ch, flg; static struct timeval anomaly_start = { .tv_sec = 0 }; status = UART_GET_LSR(uart); UART_CLEAR_LSR(uart); ch = UART_GET_CHAR(uart); uart->port.icount.rx++; #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) if (kgdb_connected && kgdboc_port_line == uart->port.line) if (ch == 0x3) {/* Ctrl + C */ kgdb_breakpoint(); return; } if (!uart->port.info || !uart->port.info->tty) return; #endif tty = uart->port.info->tty; if (ANOMALY_05000363) { /* The BF533 (and BF561) family of processors have a nice anomaly * where they continuously generate characters for a "single" break. * We have to basically ignore this flood until the "next" valid * character comes across. Due to the nature of the flood, it is * not possible to reliably catch bytes that are sent too quickly * after this break. So application code talking to the Blackfin * which sends a break signal must allow at least 1.5 character * times after the end of the break for things to stabilize. This * timeout was picked as it must absolutely be larger than 1 * character time +/- some percent. So 1.5 sounds good. All other * Blackfin families operate properly. Woo. */ if (anomaly_start.tv_sec) { struct timeval curr; suseconds_t usecs; if ((~ch & (~ch + 1)) & 0xff) goto known_good_char; do_gettimeofday(&curr); if (curr.tv_sec - anomaly_start.tv_sec > 1) goto known_good_char; usecs = 0; if (curr.tv_sec != anomaly_start.tv_sec) usecs += USEC_PER_SEC; usecs += curr.tv_usec - anomaly_start.tv_usec; if (usecs > UART_GET_ANOMALY_THRESHOLD(uart)) goto known_good_char; if (ch) anomaly_start.tv_sec = 0; else anomaly_start = curr; return; known_good_char: status &= ~BI; anomaly_start.tv_sec = 0; } } if (status & BI) { if (ANOMALY_05000363) if (bfin_revid() < 5) do_gettimeofday(&anomaly_start); uart->port.icount.brk++; if (uart_handle_break(&uart->port)) goto ignore_char; status &= ~(PE | FE); } if (status & PE) uart->port.icount.parity++; if (status & OE) uart->port.icount.overrun++; if (status & FE) uart->port.icount.frame++; status &= uart->port.read_status_mask; if (status & BI) flg = TTY_BREAK; else if (status & PE) flg = TTY_PARITY; else if (status & FE) flg = TTY_FRAME; else flg = TTY_NORMAL; if (uart_handle_sysrq_char(&uart->port, ch)) goto ignore_char; uart_insert_char(&uart->port, status, OE, ch, flg); ignore_char: tty_flip_buffer_push(tty); } static void bfin_serial_tx_chars(struct bfin_serial_port *uart) { struct circ_buf *xmit = &uart->port.info->xmit; /* * Check the modem control lines before * transmitting anything. */ bfin_serial_mctrl_check(uart); if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) { #ifdef CONFIG_BF54x /* Clear TFI bit */ UART_PUT_LSR(uart, TFI); #endif UART_CLEAR_IER(uart, ETBEI); return; } if (uart->port.x_char) { UART_PUT_CHAR(uart, uart->port.x_char); uart->port.icount.tx++; uart->port.x_char = 0; } while ((UART_GET_LSR(uart) & THRE) && xmit->tail != xmit->head) { UART_PUT_CHAR(uart, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); uart->port.icount.tx++; SSYNC(); } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&uart->port); } static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id) { struct bfin_serial_port *uart = dev_id; spin_lock(&uart->port.lock); while (UART_GET_LSR(uart) & DR) bfin_serial_rx_chars(uart); spin_unlock(&uart->port.lock); return IRQ_HANDLED; } static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id) { struct bfin_serial_port *uart = dev_id; spin_lock(&uart->port.lock); if (UART_GET_LSR(uart) & THRE) bfin_serial_tx_chars(uart); spin_unlock(&uart->port.lock); return IRQ_HANDLED; } #endif #ifdef CONFIG_SERIAL_BFIN_DMA static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart) { struct circ_buf *xmit = &uart->port.info->xmit; uart->tx_done = 0; /* * Check the modem control lines before * transmitting anything. */ bfin_serial_mctrl_check(uart); if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) { uart->tx_count = 0; uart->tx_done = 1; return; } if (uart->port.x_char) { UART_PUT_CHAR(uart, uart->port.x_char); uart->port.icount.tx++; uart->port.x_char = 0; } uart->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE); if (uart->tx_count > (UART_XMIT_SIZE - xmit->tail)) uart->tx_count = UART_XMIT_SIZE - xmit->tail; blackfin_dcache_flush_range((unsigned long)(xmit->buf+xmit->tail), (unsigned long)(xmit->buf+xmit->tail+uart->tx_count)); set_dma_config(uart->tx_dma_channel, set_bfin_dma_config(DIR_READ, DMA_FLOW_STOP, INTR_ON_BUF, DIMENSION_LINEAR, DATA_SIZE_8, DMA_SYNC_RESTART)); set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail)); set_dma_x_count(uart->tx_dma_channel, uart->tx_count); set_dma_x_modify(uart->tx_dma_channel, 1); enable_dma(uart->tx_dma_channel); UART_SET_IER(uart, ETBEI); } static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) { struct tty_struct *tty = uart->port.info->port.tty; int i, flg, status; status = UART_GET_LSR(uart); UART_CLEAR_LSR(uart); uart->port.icount.rx += CIRC_CNT(uart->rx_dma_buf.head, uart->rx_dma_buf.tail, UART_XMIT_SIZE); if (status & BI) { uart->port.icount.brk++; if (uart_handle_break(&uart->port)) goto dma_ignore_char; status &= ~(PE | FE); } if (status & PE) uart->port.icount.parity++; if (status & OE) uart->port.icount.overrun++; if (status & FE) uart->port.icount.frame++; status &= uart->port.read_status_mask; if (status & BI) flg = TTY_BREAK; else if (status & PE) flg = TTY_PARITY; else if (status & FE) flg = TTY_FRAME; else flg = TTY_NORMAL; for (i = uart->rx_dma_buf.tail; i != uart->rx_dma_buf.head; i++) { if (i >= UART_XMIT_SIZE) i = 0; if (!uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i])) uart_insert_char(&uart->port, status, OE, uart->rx_dma_buf.buf[i], flg); } dma_ignore_char: tty_flip_buffer_push(tty); } void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) { int x_pos, pos, flags; spin_lock_irqsave(&uart->port.lock, flags); uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel); x_pos = get_dma_curr_xcount(uart->rx_dma_channel); uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows; if (uart->rx_dma_nrows == DMA_RX_YCOUNT) uart->rx_dma_nrows = 0; x_pos = DMA_RX_XCOUNT - x_pos; if (x_pos == DMA_RX_XCOUNT) x_pos = 0; pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos; if (pos != uart->rx_dma_buf.tail) { uart->rx_dma_buf.head = pos; bfin_serial_dma_rx_chars(uart); uart->rx_dma_buf.tail = uart->rx_dma_buf.head; } spin_unlock_irqrestore(&uart->port.lock, flags); mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES); }
omahauart_rx_chars(struct uart_info *info) #endif { struct tty_struct *tty = info->tty; volatile unsigned int status, data, ch, rsr, max_count = 256; struct uart_port *port = info->port; status = UART_FIFO_STATUS(port); while (UART_RX_DATA(status) && max_count--) { if (tty->flip.count >= TTY_FLIPBUF_SIZE) { tty->flip.tqueue.routine((void *)tty); if (tty->flip.count >= TTY_FLIPBUF_SIZE) { printk(KERN_WARNING "TTY_DONT_FLIP set\n"); return; } } ch = UART_GET_CHAR(port); *tty->flip.char_buf_ptr = ch; *tty->flip.flag_buf_ptr = TTY_NORMAL; port->icount.rx++; /* * Note that the error handling code is * out of the main execution path */ rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX; if (rsr & 0xf) { if (rsr & OMAHA_UART_BREAK) { rsr &= ~(OMAHA_UART_FRAME | OMAHA_UART_PARITY); port->icount.brk++; if (uart_handle_break(info, &omaha_console)) goto ignore_char; } else if (rsr & OMAHA_UART_PARITY) port->icount.parity++; else if (rsr & OMAHA_UART_FRAME) port->icount.frame++; if (rsr & OMAHA_UART_OVERRUN) port->icount.overrun++; rsr &= port->read_status_mask; if (rsr & OMAHA_UART_BREAK) *tty->flip.flag_buf_ptr = TTY_BREAK; else if (rsr & OMAHA_UART_PARITY) *tty->flip.flag_buf_ptr = TTY_PARITY; else if (rsr & OMAHA_UART_FRAME) *tty->flip.flag_buf_ptr = TTY_FRAME; } if (uart_handle_sysrq_char(info, ch, regs)) goto ignore_char; if ((rsr & port->ignore_status_mask) == 0) { tty->flip.flag_buf_ptr++; tty->flip.char_buf_ptr++; tty->flip.count++; } if ((rsr & OMAHA_UART_OVERRUN) && tty->flip.count < TTY_FLIPBUF_SIZE) { /* * Overrun is special, since it's reported * immediately, and doesn't affect the current * character */ *tty->flip.char_buf_ptr++ = 0; *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; tty->flip.count++; } ignore_char: status = UART_FIFO_STATUS(port); } tty_flip_buffer_push(tty); return; }
static void uart00_rx_chars(struct uart_port *port, struct pt_regs *regs) { struct tty_struct *tty = port->info->tty; unsigned int status, ch, rds, flg, ignored = 0; status = UART_GET_RSR(port); while (UART_RX_DATA(status)) { /* * We need to read rds before reading the * character from the fifo */ rds = UART_GET_RDS(port); ch = UART_GET_CHAR(port); port->icount.rx++; if (tty->flip.count >= TTY_FLIPBUF_SIZE) goto ignore_char; flg = TTY_NORMAL; /* * Note that the error handling code is * out of the main execution path */ if (rds & (UART_RDS_BI_MSK |UART_RDS_FE_MSK| UART_RDS_PE_MSK |UART_RDS_PE_MSK)) goto handle_error; if (uart_handle_sysrq_char(port, ch, regs)) goto ignore_char; error_return: tty_insert_flip_char(tty, ch, flg); ignore_char: status = UART_GET_RSR(port); } out: tty_flip_buffer_push(tty); return; handle_error: if (rds & UART_RDS_BI_MSK) { status &= ~(UART_RDS_FE_MSK | UART_RDS_PE_MSK); port->icount.brk++; if (uart_handle_break(port)) goto ignore_char; } else if (rds & UART_RDS_PE_MSK) port->icount.parity++; else if (rds & UART_RDS_FE_MSK) port->icount.frame++; if (rds & UART_RDS_OE_MSK) port->icount.overrun++; if (rds & port->ignore_status_mask) { if (++ignored > 100) goto out; goto ignore_char; } rds &= port->read_status_mask; if (rds & UART_RDS_BI_MSK) flg = TTY_BREAK; else if (rds & UART_RDS_PE_MSK) flg = TTY_PARITY; else if (rds & UART_RDS_FE_MSK) flg = TTY_FRAME; if (rds & UART_RDS_OE_MSK) { /* * CHECK: does overrun affect the current character? * ASSUMPTION: it does not. */ tty_insert_flip_char(tty, ch, flg); ch = 0; flg = TTY_OVERRUN; } #ifdef SUPPORT_SYSRQ port->sysrq = 0; #endif goto error_return; }
leonuart_rx_chars(struct uart_port *port) #endif { struct tty_struct *tty = port->info->port.tty; unsigned int status, ch, rsr, flag; unsigned int max_chars = port->fifosize; status = UART_GET_STATUS(port); while (UART_RX_DATA(status) && (max_chars--)) { /* if (tty->flip.count >= TTY_FLIPBUF_SIZE) { tty->flip.work.func((void *)tty); if (tty->flip.count >= TTY_FLIPBUF_SIZE) { printk(KERN_WARNING "TTY_DONT_FLIP set\n"); return; } } */ ch = UART_GET_CHAR(port); flag = TTY_NORMAL; /**tty->flip.char_buf_ptr = ch; *tty->flip.flag_buf_ptr = TTY_NORMAL;*/ port->icount.rx++; /* * Note that the error handling code is * out of the main execution path */ rsr = UART_GET_STATUS(port) | UART_DUMMY_RSR_RX; UART_PUT_STATUS(port, 0); if (rsr & LEON_REG_UART_STATUS_ERR) { if (rsr & LEON_REG_UART_STATUS_BR) { rsr &= ~(LEON_REG_UART_STATUS_FE | LEON_REG_UART_STATUS_PE); port->icount.brk++; if (uart_handle_break(port)) goto ignore_char; } else if (rsr & LEON_REG_UART_STATUS_PE) { port->icount.parity++; } else if (rsr & LEON_REG_UART_STATUS_FE) { port->icount.frame++; } if (rsr & LEON_REG_UART_STATUS_OE) port->icount.overrun++; rsr &= port->read_status_mask; /* if (rsr & LEON_REG_UART_STATUS_PE) *tty->flip.flag_buf_ptr = TTY_PARITY; else if (rsr & LEON_REG_UART_STATUS_FE) *tty->flip.flag_buf_ptr = TTY_FRAME; */ if (rsr & LEON_REG_UART_STATUS_PE) flag = TTY_PARITY; else if (rsr & LEON_REG_UART_STATUS_FE) flag = TTY_FRAME; } if (uart_handle_sysrq_char(port, ch)) goto ignore_char; /* if ((rsr & port->ignore_status_mask) == 0) { tty->flip.flag_buf_ptr++; tty->flip.char_buf_ptr++; tty->flip.count++; } */ if ((rsr & port->ignore_status_mask) == 0) { tty_insert_flip_char(tty, ch, flag); } if ( rsr & LEON_REG_UART_STATUS_OE ) { /* * Overrun is special, since it's reported * immediately, and doesn't affect the current * character */ tty_insert_flip_char(tty, 0, TTY_OVERRUN); } ignore_char: status = UART_GET_STATUS(port); } tty_flip_buffer_push(tty); return; }
/* * Characters received (called from interrupt handler) */ static void atmel_rx_chars(struct uart_port *port) { struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; struct tty_struct *tty = port->info->tty; unsigned int status, ch, flg; status = UART_GET_CSR(port); while (status & ATMEL_US_RXRDY) { ch = UART_GET_CHAR(port); port->icount.rx++; flg = TTY_NORMAL; /* * note that the error handling code is * out of the main execution path */ if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME | ATMEL_US_OVRE | ATMEL_US_RXBRK) || atmel_port->break_active)) { UART_PUT_CR(port, ATMEL_US_RSTSTA); /* clear error */ if (status & ATMEL_US_RXBRK && !atmel_port->break_active) { status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME); /* ignore side-effect */ port->icount.brk++; atmel_port->break_active = 1; UART_PUT_IER(port, ATMEL_US_RXBRK); if (uart_handle_break(port)) goto ignore_char; } else { /* * This is either the end-of-break * condition or we've received at * least one character without RXBRK * being set. In both cases, the next * RXBRK will indicate start-of-break. */ UART_PUT_IDR(port, ATMEL_US_RXBRK); status &= ~ATMEL_US_RXBRK; atmel_port->break_active = 0; } if (status & ATMEL_US_PARE) port->icount.parity++; if (status & ATMEL_US_FRAME) port->icount.frame++; if (status & ATMEL_US_OVRE) port->icount.overrun++; status &= port->read_status_mask; if (status & ATMEL_US_RXBRK) flg = TTY_BREAK; else if (status & ATMEL_US_PARE) flg = TTY_PARITY; else if (status & ATMEL_US_FRAME) flg = TTY_FRAME; } if (uart_handle_sysrq_char(port, ch)) goto ignore_char; uart_insert_char(port, status, ATMEL_US_OVRE, ch, flg); ignore_char: status = UART_GET_CSR(port); } tty_flip_buffer_push(tty); }
static void sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs) { struct tty_struct *tty = sport->port.info->tty; unsigned int status, ch, flg, ignored = 0; status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | UTSR0_TO_SM(UART_GET_UTSR0(sport)); while (status & UTSR1_TO_SM(UTSR1_RNE)) { ch = UART_GET_CHAR(sport); if (tty->flip.count >= TTY_FLIPBUF_SIZE) goto ignore_char; sport->port.icount.rx++; flg = TTY_NORMAL; /* * note that the error handling code is * out of the main execution path */ if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR)) goto handle_error; if (uart_handle_sysrq_char(&sport->port, ch, regs)) goto ignore_char; error_return: *tty->flip.flag_buf_ptr++ = flg; *tty->flip.char_buf_ptr++ = ch; tty->flip.count++; ignore_char: status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | UTSR0_TO_SM(UART_GET_UTSR0(sport)); } out: tty_flip_buffer_push(tty); return; handle_error: if (status & UTSR1_TO_SM(UTSR1_PRE)) sport->port.icount.parity++; else if (status & UTSR1_TO_SM(UTSR1_FRE)) sport->port.icount.frame++; if (status & UTSR1_TO_SM(UTSR1_ROR)) sport->port.icount.overrun++; if (status & sport->port.ignore_status_mask) { if (++ignored > 100) goto out; goto ignore_char; } status &= sport->port.read_status_mask; if (status & UTSR1_TO_SM(UTSR1_PRE)) flg = TTY_PARITY; else if (status & UTSR1_TO_SM(UTSR1_FRE)) flg = TTY_FRAME; if (status & UTSR1_TO_SM(UTSR1_ROR)) { /* * overrun does *not* affect the character * we read from the FIFO */ *tty->flip.flag_buf_ptr++ = flg; *tty->flip.char_buf_ptr++ = ch; tty->flip.count++; if (tty->flip.count >= TTY_FLIPBUF_SIZE) goto ignore_char; ch = 0; flg = TTY_OVERRUN; } #ifdef SUPPORT_SYSRQ sport->port.sysrq = 0; #endif goto error_return; }
static void bfin_serial_rx_chars(struct bfin_serial_port *uart) { struct tty_struct *tty = NULL; unsigned int status, ch, flg; static struct timeval anomaly_start = { .tv_sec = 0 }; status = UART_GET_LSR(uart); UART_CLEAR_LSR(uart); ch = UART_GET_CHAR(uart); uart->port.icount.rx++; #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) if (kgdb_connected && kgdboc_port_line == uart->port.line && kgdboc_break_enabled) if (ch == 0x3) {/* Ctrl + C */ kgdb_breakpoint(); return; } if (!uart->port.state || !uart->port.state->port.tty) return; #endif tty = uart->port.state->port.tty; if (ANOMALY_05000363) { /* The BF533 (and BF561) family of processors have a nice anomaly * where they continuously generate characters for a "single" break. * We have to basically ignore this flood until the "next" valid * character comes across. Due to the nature of the flood, it is * not possible to reliably catch bytes that are sent too quickly * after this break. So application code talking to the Blackfin * which sends a break signal must allow at least 1.5 character * times after the end of the break for things to stabilize. This * timeout was picked as it must absolutely be larger than 1 * character time +/- some percent. So 1.5 sounds good. All other * Blackfin families operate properly. Woo. */ if (anomaly_start.tv_sec) { struct timeval curr; suseconds_t usecs; if ((~ch & (~ch + 1)) & 0xff) goto known_good_char; do_gettimeofday(&curr); if (curr.tv_sec - anomaly_start.tv_sec > 1) goto known_good_char; usecs = 0; if (curr.tv_sec != anomaly_start.tv_sec) usecs += USEC_PER_SEC; usecs += curr.tv_usec - anomaly_start.tv_usec; if (usecs > UART_GET_ANOMALY_THRESHOLD(uart)) goto known_good_char; if (ch) anomaly_start.tv_sec = 0; else anomaly_start = curr; return; known_good_char: status &= ~BI; anomaly_start.tv_sec = 0; } } if (status & BI) { if (ANOMALY_05000363) if (bfin_revid() < 5) do_gettimeofday(&anomaly_start); uart->port.icount.brk++; if (uart_handle_break(&uart->port)) goto ignore_char; status &= ~(PE | FE); } if (status & PE) uart->port.icount.parity++; if (status & OE) uart->port.icount.overrun++; if (status & FE) uart->port.icount.frame++; status &= uart->port.read_status_mask; if (status & BI) flg = TTY_BREAK; else if (status & PE) flg = TTY_PARITY; else if (status & FE) flg = TTY_FRAME; else flg = TTY_NORMAL; if (uart_handle_sysrq_char(&uart->port, ch)) goto ignore_char; uart_insert_char(&uart->port, status, OE, ch, flg); ignore_char: tty_flip_buffer_push(tty); } static void bfin_serial_tx_chars(struct bfin_serial_port *uart) { struct circ_buf *xmit = &uart->port.state->xmit; if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) { #ifdef CONFIG_BF54x /* Clear TFI bit */ UART_PUT_LSR(uart, TFI); #endif /* Anomaly notes: * 05000215 - we always clear ETBEI within last UART TX * interrupt to end a string. It is always set * when start a new tx. */ UART_CLEAR_IER(uart, ETBEI); return; } if (uart->port.x_char) { UART_PUT_CHAR(uart, uart->port.x_char); uart->port.icount.tx++; uart->port.x_char = 0; } while ((UART_GET_LSR(uart) & THRE) && xmit->tail != xmit->head) { UART_PUT_CHAR(uart, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); uart->port.icount.tx++; } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&uart->port); } static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id) { struct bfin_serial_port *uart = dev_id; while (UART_GET_LSR(uart) & DR) bfin_serial_rx_chars(uart); return IRQ_HANDLED; } static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id) { struct bfin_serial_port *uart = dev_id; #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS if (uart->scts && !(bfin_serial_get_mctrl(&uart->port) & TIOCM_CTS)) { uart->scts = 0; uart_handle_cts_change(&uart->port, uart->scts); } #endif spin_lock(&uart->port.lock); if (UART_GET_LSR(uart) & THRE) bfin_serial_tx_chars(uart); spin_unlock(&uart->port.lock); return IRQ_HANDLED; } #endif #ifdef CONFIG_SERIAL_BFIN_DMA static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart) { struct circ_buf *xmit = &uart->port.state->xmit; uart->tx_done = 0; if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) { uart->tx_count = 0; uart->tx_done = 1; return; } if (uart->port.x_char) { UART_PUT_CHAR(uart, uart->port.x_char); uart->port.icount.tx++; uart->port.x_char = 0; } uart->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE); if (uart->tx_count > (UART_XMIT_SIZE - xmit->tail)) uart->tx_count = UART_XMIT_SIZE - xmit->tail; blackfin_dcache_flush_range((unsigned long)(xmit->buf+xmit->tail), (unsigned long)(xmit->buf+xmit->tail+uart->tx_count)); set_dma_config(uart->tx_dma_channel, set_bfin_dma_config(DIR_READ, DMA_FLOW_STOP, INTR_ON_BUF, DIMENSION_LINEAR, DATA_SIZE_8, DMA_SYNC_RESTART)); set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail)); set_dma_x_count(uart->tx_dma_channel, uart->tx_count); set_dma_x_modify(uart->tx_dma_channel, 1); SSYNC(); enable_dma(uart->tx_dma_channel); UART_SET_IER(uart, ETBEI); } static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) { struct tty_struct *tty = uart->port.state->port.tty; int i, flg, status; status = UART_GET_LSR(uart); UART_CLEAR_LSR(uart); uart->port.icount.rx += CIRC_CNT(uart->rx_dma_buf.head, uart->rx_dma_buf.tail, UART_XMIT_SIZE); if (status & BI) { uart->port.icount.brk++; if (uart_handle_break(&uart->port)) goto dma_ignore_char; status &= ~(PE | FE); } if (status & PE) uart->port.icount.parity++; if (status & OE) uart->port.icount.overrun++; if (status & FE) uart->port.icount.frame++; status &= uart->port.read_status_mask; if (status & BI) flg = TTY_BREAK; else if (status & PE) flg = TTY_PARITY; else if (status & FE) flg = TTY_FRAME; else flg = TTY_NORMAL; for (i = uart->rx_dma_buf.tail; ; i++) { if (i >= UART_XMIT_SIZE) i = 0; if (i == uart->rx_dma_buf.head) break; if (!uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i])) uart_insert_char(&uart->port, status, OE, uart->rx_dma_buf.buf[i], flg); } dma_ignore_char: tty_flip_buffer_push(tty); } void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) { int x_pos, pos; dma_disable_irq_nosync(uart->rx_dma_channel); spin_lock_bh(&uart->rx_lock); /* 2D DMA RX buffer ring is used. Because curr_y_count and * curr_x_count can't be read as an atomic operation, * curr_y_count should be read before curr_x_count. When * curr_x_count is read, curr_y_count may already indicate * next buffer line. But, the position calculated here is * still indicate the old line. The wrong position data may * be smaller than current buffer tail, which cause garbages * are received if it is not prohibit. */ uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel); x_pos = get_dma_curr_xcount(uart->rx_dma_channel); uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows; if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0) uart->rx_dma_nrows = 0; x_pos = DMA_RX_XCOUNT - x_pos; if (x_pos == DMA_RX_XCOUNT) x_pos = 0; pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos; /* Ignore receiving data if new position is in the same line of * current buffer tail and small. */ if (pos > uart->rx_dma_buf.tail || uart->rx_dma_nrows < (uart->rx_dma_buf.tail/DMA_RX_XCOUNT)) { uart->rx_dma_buf.head = pos; bfin_serial_dma_rx_chars(uart); uart->rx_dma_buf.tail = uart->rx_dma_buf.head; } spin_unlock_bh(&uart->rx_lock); dma_enable_irq(uart->rx_dma_channel); mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES); }