|
@@ -166,6 +166,7 @@ static void dz_enable_ms(struct uart_port *port)
|
|
*/
|
|
*/
|
|
static inline void dz_receive_chars(struct dz_port *dport_in)
|
|
static inline void dz_receive_chars(struct dz_port *dport_in)
|
|
{
|
|
{
|
|
|
|
+ struct uart_port *uport;
|
|
struct dz_port *dport;
|
|
struct dz_port *dport;
|
|
struct tty_struct *tty = NULL;
|
|
struct tty_struct *tty = NULL;
|
|
struct uart_icount *icount;
|
|
struct uart_icount *icount;
|
|
@@ -176,57 +177,56 @@ static inline void dz_receive_chars(struct dz_port *dport_in)
|
|
|
|
|
|
while ((status = dz_in(dport_in, DZ_RBUF)) & DZ_DVAL) {
|
|
while ((status = dz_in(dport_in, DZ_RBUF)) & DZ_DVAL) {
|
|
dport = &dz_ports[LINE(status)];
|
|
dport = &dz_ports[LINE(status)];
|
|
- tty = dport->port.info->tty; /* point to the proper dev */
|
|
|
|
|
|
+ uport = &dport->port;
|
|
|
|
+ tty = uport->info->tty; /* point to the proper dev */
|
|
|
|
|
|
ch = UCHAR(status); /* grab the char */
|
|
ch = UCHAR(status); /* grab the char */
|
|
|
|
+ flag = TTY_NORMAL;
|
|
|
|
|
|
- icount = &dport->port.icount;
|
|
|
|
|
|
+ icount = &uport->icount;
|
|
icount->rx++;
|
|
icount->rx++;
|
|
|
|
|
|
- flag = TTY_NORMAL;
|
|
|
|
- if (status & DZ_FERR) { /* frame error */
|
|
|
|
|
|
+ if (unlikely(status & (DZ_OERR | DZ_FERR | DZ_PERR))) {
|
|
|
|
+
|
|
/*
|
|
/*
|
|
- * There is no separate BREAK status bit, so
|
|
|
|
- * treat framing errors as BREAKs for Magic SysRq
|
|
|
|
- * and SAK; normally, otherwise.
|
|
|
|
|
|
+ * There is no separate BREAK status bit, so treat
|
|
|
|
+ * null characters with framing errors as BREAKs;
|
|
|
|
+ * normally, otherwise. For this move the Framing
|
|
|
|
+ * Error bit to a simulated BREAK bit.
|
|
*/
|
|
*/
|
|
- if (uart_handle_break(&dport->port))
|
|
|
|
- continue;
|
|
|
|
- if (dport->port.flags & UPF_SAK)
|
|
|
|
|
|
+ if (!ch) {
|
|
|
|
+ status |= (status & DZ_FERR) >>
|
|
|
|
+ (ffs(DZ_FERR) - ffs(DZ_BREAK));
|
|
|
|
+ status &= ~DZ_FERR;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Handle SysRq/SAK & keep track of the statistics. */
|
|
|
|
+ if (status & DZ_BREAK) {
|
|
|
|
+ icount->brk++;
|
|
|
|
+ if (uart_handle_break(uport))
|
|
|
|
+ continue;
|
|
|
|
+ } else if (status & DZ_FERR)
|
|
|
|
+ icount->frame++;
|
|
|
|
+ else if (status & DZ_PERR)
|
|
|
|
+ icount->parity++;
|
|
|
|
+ if (status & DZ_OERR)
|
|
|
|
+ icount->overrun++;
|
|
|
|
+
|
|
|
|
+ status &= uport->read_status_mask;
|
|
|
|
+ if (status & DZ_BREAK)
|
|
flag = TTY_BREAK;
|
|
flag = TTY_BREAK;
|
|
- else
|
|
|
|
|
|
+ else if (status & DZ_FERR)
|
|
flag = TTY_FRAME;
|
|
flag = TTY_FRAME;
|
|
- } else if (status & DZ_OERR) /* overrun error */
|
|
|
|
- flag = TTY_OVERRUN;
|
|
|
|
- else if (status & DZ_PERR) /* parity error */
|
|
|
|
- flag = TTY_PARITY;
|
|
|
|
-
|
|
|
|
- /* keep track of the statistics */
|
|
|
|
- switch (flag) {
|
|
|
|
- case TTY_FRAME:
|
|
|
|
- icount->frame++;
|
|
|
|
- break;
|
|
|
|
- case TTY_PARITY:
|
|
|
|
- icount->parity++;
|
|
|
|
- break;
|
|
|
|
- case TTY_OVERRUN:
|
|
|
|
- icount->overrun++;
|
|
|
|
- break;
|
|
|
|
- case TTY_BREAK:
|
|
|
|
- icount->brk++;
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- break;
|
|
|
|
|
|
+ else if (status & DZ_PERR)
|
|
|
|
+ flag = TTY_PARITY;
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
- if (uart_handle_sysrq_char(&dport->port, ch))
|
|
|
|
|
|
+ if (uart_handle_sysrq_char(uport, ch))
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- if ((status & dport->port.ignore_status_mask) == 0) {
|
|
|
|
- uart_insert_char(&dport->port,
|
|
|
|
- status, DZ_OERR, ch, flag);
|
|
|
|
- lines_rx[LINE(status)] = 1;
|
|
|
|
- }
|
|
|
|
|
|
+ uart_insert_char(uport, status, DZ_OERR, ch, flag);
|
|
|
|
+ lines_rx[LINE(status)] = 1;
|
|
}
|
|
}
|
|
for (i = 0; i < DZ_NB_PORT; i++)
|
|
for (i = 0; i < DZ_NB_PORT; i++)
|
|
if (lines_rx[i])
|
|
if (lines_rx[i])
|
|
@@ -556,11 +556,17 @@ static void dz_set_termios(struct uart_port *uport, struct ktermios *termios,
|
|
dport->port.read_status_mask = DZ_OERR;
|
|
dport->port.read_status_mask = DZ_OERR;
|
|
if (termios->c_iflag & INPCK)
|
|
if (termios->c_iflag & INPCK)
|
|
dport->port.read_status_mask |= DZ_FERR | DZ_PERR;
|
|
dport->port.read_status_mask |= DZ_FERR | DZ_PERR;
|
|
|
|
+ if (termios->c_iflag & (BRKINT | PARMRK))
|
|
|
|
+ dport->port.read_status_mask |= DZ_BREAK;
|
|
|
|
|
|
/* characters to ignore */
|
|
/* characters to ignore */
|
|
uport->ignore_status_mask = 0;
|
|
uport->ignore_status_mask = 0;
|
|
|
|
+ if ((termios->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
|
|
|
|
+ dport->port.ignore_status_mask |= DZ_OERR;
|
|
if (termios->c_iflag & IGNPAR)
|
|
if (termios->c_iflag & IGNPAR)
|
|
dport->port.ignore_status_mask |= DZ_FERR | DZ_PERR;
|
|
dport->port.ignore_status_mask |= DZ_FERR | DZ_PERR;
|
|
|
|
+ if (termios->c_iflag & IGNBRK)
|
|
|
|
+ dport->port.ignore_status_mask |= DZ_BREAK;
|
|
|
|
|
|
spin_unlock_irqrestore(&dport->port.lock, flags);
|
|
spin_unlock_irqrestore(&dport->port.lock, flags);
|
|
}
|
|
}
|