static irqreturn_t sci_er_interrupt(int irq, void *ptr) { struct uart_port *port = ptr; /* Handle errors */ if (port->type == PORT_SCI) { if (sci_handle_errors(port)) { /* discard character in rx buffer */ sci_in(port, SCxSR); sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); } } else { #if defined(SCIF_ORER) if((sci_in(port, SCLSR) & SCIF_ORER) != 0) { struct tty_struct *tty = port->info->port.tty; sci_out(port, SCLSR, 0); tty_insert_flip_char(tty, 0, TTY_OVERRUN); tty_flip_buffer_push(tty); pr_debug("scif: overrun error\n"); } #endif sci_rx_interrupt(irq, ptr); } sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); /* Kick the transmission */ sci_tx_interrupt(irq, ptr); return IRQ_HANDLED; }
/* Get a char if there is one, else ret -1 */ static int kgdb_get_char(struct sci_port *port) { int c; if (kgdb_is_char_ready(port) == 0) c = -1; else { c = sci_in(port, SCxRDR); sci_in(port, SCxSR); /* Dummy read */ sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); } return c; }
static int sh_serial_getc(void) { unsigned short status; char ch; while (!serial_getc_check()) ; ch = sci_in(&sh_sci, SCxRDR); status = sci_in(&sh_sci, SCxSR); sci_out(&sh_sci, SCxSR, SCxSR_RDxF_CLEAR(&sh_sci)); if (status & SCIF_ERRORS) handle_error(); if (sci_in(&sh_sci, SCLSR) & SCxSR_ORER(&sh_sci)) handle_error(); return ch; }
static int get_char(struct sci_port *port) { unsigned long flags; unsigned short status; int c; save_and_cli(flags); do { status = sci_in(port, SCxSR); if (status & SCxSR_ERRORS(port)) { handle_error(port); continue; } } while (!(status & SCxSR_RDxF(port))); c = sci_in(port, SCxRDR); sci_in(port, SCxSR); /* Dummy read */ sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); restore_flags(flags); return c; }
static int get_char(struct uart_port *port) { unsigned long flags; unsigned short status; int c; spin_lock_irqsave(&port->lock, flags); do { status = sci_in(port, SCxSR); if (status & SCxSR_ERRORS(port)) { handle_error(port); continue; } } while (!(status & SCxSR_RDxF(port))); c = sci_in(port, SCxRDR); sci_in(port, SCxSR); /* Dummy read */ sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); spin_unlock_irqrestore(&port->lock, flags); return c; }
static inline void sci_receive_chars(struct uart_port *port) { struct sci_port *sci_port = (struct sci_port *)port; struct tty_struct *tty = port->info->port.tty; int i, count, copied = 0; unsigned short status; unsigned char flag; status = sci_in(port, SCxSR); if (!(status & SCxSR_RDxF(port))) return; while (1) { if (port->type == PORT_SCIF) count = scif_rxroom(port); else count = sci_rxroom(port); /* Don't copy more bytes than there is room for in the buffer */ count = tty_buffer_request_room(tty, count); /* If for any reason we can't copy more data, we're done! */ if (count == 0) break; if (port->type == PORT_SCI) { char c = sci_in(port, SCxRDR); if (uart_handle_sysrq_char(port, c) || sci_port->break_flag) count = 0; else { tty_insert_flip_char(tty, c, TTY_NORMAL); } } else { for (i=0; i<count; i++) { char c = sci_in(port, SCxRDR); status = sci_in(port, SCxSR); #if defined(CONFIG_CPU_SH3) /* Skip "chars" during break */ if (sci_port->break_flag) { if ((c == 0) && (status & SCxSR_FER(port))) { count--; i--; continue; } /* Nonzero => end-of-break */ pr_debug("scif: debounce<%02x>\n", c); sci_port->break_flag = 0; if (STEPFN(c)) { count--; i--; continue; } } #endif /* CONFIG_CPU_SH3 */ if (uart_handle_sysrq_char(port, c)) { count--; i--; continue; } /* Store data and status */ if (status&SCxSR_FER(port)) { flag = TTY_FRAME; pr_debug("sci: frame error\n"); } else if (status&SCxSR_PER(port)) { flag = TTY_PARITY; pr_debug("sci: parity error\n"); } else flag = TTY_NORMAL; tty_insert_flip_char(tty, c, flag); } } sci_in(port, SCxSR); /* dummy read */ sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); copied += count; port->icount.rx += count; } if (copied) { /* Tell the rest of the system the news. New characters! */ tty_flip_buffer_push(tty); } else { sci_in(port, SCxSR); /* dummy read */ sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); } }