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); }
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 void sa1100_int(int irq, void *dev_id, struct pt_regs *regs) { struct uart_info *info = dev_id; struct uart_port *port = info->port; unsigned int status, pass_counter = 0; status = UART_GET_UTSR0(port); status &= (SM_TO_UTSR0(port->read_status_mask) | ~UTSR0_TFS); do { if (status & (UTSR0_RFS | UTSR0_RID)) { /* Clear the receiver idle bit, if set */ if (status & UTSR0_RID) UART_PUT_UTSR0(port, UTSR0_RID); sa1100_rx_chars(info, regs); } /* Clear the relevent break bits */ if (status & (UTSR0_RBB | UTSR0_REB)) UART_PUT_UTSR0(port, status & (UTSR0_RBB | UTSR0_REB)); if (status & UTSR0_RBB) port->icount.brk++; if (status & UTSR0_REB) { #ifdef SUPPORT_SYSRQ if (port->line == sa1100_console.index && !info->sysrq) { info->sysrq = jiffies + HZ*5; } #endif } if (status & UTSR0_TFS) sa1100_tx_chars(info); if (pass_counter++ > SA1100_ISR_PASS_LIMIT) break; status = UART_GET_UTSR0(port); status &= (SM_TO_UTSR0(port->read_status_mask) | ~UTSR0_TFS); } while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID)); }
static irqreturn_t sa1100_int(int irq, void *dev_id) { struct sa1100_port *sport = dev_id; unsigned int status, pass_counter = 0; spin_lock(&sport->port.lock); status = UART_GET_UTSR0(sport); status &= SM_TO_UTSR0(sport->port.read_status_mask) | ~UTSR0_TFS; do { if (status & (UTSR0_RFS | UTSR0_RID)) { /* Clear the receiver idle bit, if set */ if (status & UTSR0_RID) UART_PUT_UTSR0(sport, UTSR0_RID); sa1100_rx_chars(sport); } /* Clear the relevant break bits */ if (status & (UTSR0_RBB | UTSR0_REB)) UART_PUT_UTSR0(sport, status & (UTSR0_RBB | UTSR0_REB)); if (status & UTSR0_RBB) sport->port.icount.brk++; if (status & UTSR0_REB) uart_handle_break(&sport->port); if (status & UTSR0_TFS) sa1100_tx_chars(sport); if (pass_counter++ > SA1100_ISR_PASS_LIMIT) break; status = UART_GET_UTSR0(sport); status &= SM_TO_UTSR0(sport->port.read_status_mask) | ~UTSR0_TFS; } while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID)); spin_unlock(&sport->port.lock); return IRQ_HANDLED; }
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; }