static bool receive_chars(struct uart_port *port) { struct tty_port *tport = NULL; int limit = 10000; unsigned char ch; char flag; u8 status; /* FIXME what is this trying to achieve? */ if (port->state != NULL) /* Unopened serial console */ tport = &port->state->port; while (limit-- > 0) { status = READ_SC_PORT(port, SR); if (!(status & SR_RXRDY)) break; ch = READ_SC_PORT(port, RHR); flag = TTY_NORMAL; port->icount.rx++; if (unlikely(status & (SR_BREAK | SR_FRAME | SR_PARITY | SR_OVERRUN))) { if (status & SR_BREAK) { status &= ~(SR_PARITY | SR_FRAME); port->icount.brk++; if (uart_handle_break(port)) continue; } else if (status & SR_PARITY) port->icount.parity++; else if (status & SR_FRAME) port->icount.frame++; if (status & SR_OVERRUN) port->icount.overrun++; status &= port->read_status_mask; if (status & SR_BREAK) flag = TTY_BREAK; else if (status & SR_PARITY) flag = TTY_PARITY; else if (status & SR_FRAME) flag = TTY_FRAME; } if (uart_handle_sysrq_char(port, ch)) continue; if (status & port->ignore_status_mask) continue; tty_insert_flip_char(tport, ch, flag); } return !!tport; }
static struct tty_struct *receive_chars(struct uart_port *port) { struct tty_struct *tty = NULL; int limit = 10000; unsigned char ch; char flag; u8 status; if (port->state != NULL) tty = port->state->port.tty; while (limit-- > 0) { status = READ_SC_PORT(port, SR); if (!(status & SR_RXRDY)) break; ch = READ_SC_PORT(port, RHR); flag = TTY_NORMAL; port->icount.rx++; if (unlikely(status & (SR_BREAK | SR_FRAME | SR_PARITY | SR_OVERRUN))) { if (status & SR_BREAK) { status &= ~(SR_PARITY | SR_FRAME); port->icount.brk++; if (uart_handle_break(port)) continue; } else if (status & SR_PARITY) port->icount.parity++; else if (status & SR_FRAME) port->icount.frame++; if (status & SR_OVERRUN) port->icount.overrun++; status &= port->read_status_mask; if (status & SR_BREAK) flag = TTY_BREAK; else if (status & SR_PARITY) flag = TTY_PARITY; else if (status & SR_FRAME) flag = TTY_FRAME; } if (uart_handle_sysrq_char(port, ch)) continue; if (status & port->ignore_status_mask) continue; tty_insert_flip_char(tty, ch, flag); } return tty; }
/* port->lock held by caller. */ static void sc26xx_start_tx(struct uart_port *port) { struct circ_buf *xmit = &port->state->xmit; while (!uart_circ_empty(xmit)) { if (!(READ_SC_PORT(port, SR) & SR_TXRDY)) { sc26xx_enable_irq(port, IMR_TXRDY); break; } WRITE_SC_PORT(port, THR, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; } }
static void sc26xx_console_putchar(struct uart_port *port, char c) { unsigned long flags; int limit = 1000000; spin_lock_irqsave(&port->lock, flags); while (limit-- > 0) { if (READ_SC_PORT(port, SR) & SR_TXRDY) { WRITE_SC_PORT(port, THR, c); break; } udelay(2); } spin_unlock_irqrestore(&port->lock, flags); }
static void transmit_chars(struct uart_port *port) { struct circ_buf *xmit; if (!port->state) return; xmit = &port->state->xmit; if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { sc26xx_disable_irq(port, IMR_TXRDY); return; } while (!uart_circ_empty(xmit)) { if (!(READ_SC_PORT(port, SR) & SR_TXRDY)) break; WRITE_SC_PORT(port, THR, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); }
/* port->lock is not held. */ static void sc26xx_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000); unsigned int quot = uart_get_divisor(port, baud); unsigned int iflag, cflag; unsigned long flags; u8 mr1, mr2, csr; spin_lock_irqsave(&port->lock, flags); while ((READ_SC_PORT(port, SR) & ((1 << 3) | (1 << 2))) != 0xc) udelay(2); WRITE_SC_PORT(port, CR, CR_DIS_TX | CR_DIS_RX); iflag = termios->c_iflag; cflag = termios->c_cflag; port->read_status_mask = SR_OVERRUN; if (iflag & INPCK) port->read_status_mask |= SR_PARITY | SR_FRAME; if (iflag & (BRKINT | PARMRK)) port->read_status_mask |= SR_BREAK; port->ignore_status_mask = 0; if (iflag & IGNBRK) port->ignore_status_mask |= SR_BREAK; if ((cflag & CREAD) == 0) port->ignore_status_mask |= SR_BREAK | SR_FRAME | SR_PARITY | SR_OVERRUN; switch (cflag & CSIZE) { case CS5: mr1 = 0x00; break; case CS6: mr1 = 0x01; break; case CS7: mr1 = 0x02; break; default: case CS8: mr1 = 0x03; break; } mr2 = 0x07; if (cflag & CSTOPB) mr2 = 0x0f; if (cflag & PARENB) { if (cflag & PARODD) mr1 |= (1 << 2); } else mr1 |= (2 << 3); switch (baud) { case 50: csr = 0x00; break; case 110: csr = 0x11; break; case 134: csr = 0x22; break; case 200: csr = 0x33; break; case 300: csr = 0x44; break; case 600: csr = 0x55; break; case 1200: csr = 0x66; break; case 2400: csr = 0x88; break; case 4800: csr = 0x99; break; default: case 9600: csr = 0xbb; break; case 19200: csr = 0xcc; break; } WRITE_SC_PORT(port, CR, CR_RES_MR); WRITE_SC_PORT(port, MRx, mr1); WRITE_SC_PORT(port, MRx, mr2); WRITE_SC(port, ACR, 0x80); WRITE_SC_PORT(port, CSR, csr); /* reset tx and rx */ WRITE_SC_PORT(port, CR, CR_RES_RX); WRITE_SC_PORT(port, CR, CR_RES_TX); WRITE_SC_PORT(port, CR, CR_ENA_TX | CR_ENA_RX); while ((READ_SC_PORT(port, SR) & ((1 << 3) | (1 << 2))) != 0xc) udelay(2); /* XXX */ uart_update_timeout(port, cflag, (port->uartclk / (16 * quot))); spin_unlock_irqrestore(&port->lock, flags); }
/* port->lock is not held. */ static unsigned int sc26xx_tx_empty(struct uart_port *port) { return (READ_SC_PORT(port, SR) & SR_TXRDY) ? TIOCSER_TEMT : 0; }