The patch titled serial/8250: implement dtr/dsr handshaking has been added to the -mm tree. Its filename is serial-8250-implement-dtr-dsr-handshaking.patch *** Remember to use Documentation/SubmitChecklist when testing your code *** See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this ------------------------------------------------------ Subject: serial/8250: implement dtr/dsr handshaking From: Michael Westermann <michael@xxxxxxxxxx> I make a driver for Point of Sale Printer, a wide range of Printers use only a DTR/DSR hardware-handshaking. When I use a handshaking in userspace, the printer has a overrun problem and our customer has a problem with the tax office. Add a simple DTR/DSR handhake with a small change of the code. Userspace can select it with cflags |= CDTRDSR; The stty tool will need updating for this. Cc: Alan Cox <alan@xxxxxxxxxxxxxxxxxxx> Cc: Russell King <rmk@xxxxxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- drivers/serial/8250.c | 11 +++++++---- drivers/serial/serial_core.c | 12 ++++++++++++ include/asm-i386/termbits.h | 1 + include/linux/serial_core.h | 16 +++++++++------- 4 files changed, 29 insertions(+), 11 deletions(-) diff -puN drivers/serial/8250.c~serial-8250-implement-dtr-dsr-handshaking drivers/serial/8250.c --- a/drivers/serial/8250.c~serial-8250-implement-dtr-dsr-handshaking +++ a/drivers/serial/8250.c @@ -1400,12 +1400,15 @@ static unsigned int check_modem_status(s up->port.info != NULL) { if (status & UART_MSR_TERI) up->port.icount.rng++; - if (status & UART_MSR_DDSR) - up->port.icount.dsr++; if (status & UART_MSR_DDCD) uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); - if (status & UART_MSR_DCTS) - uart_handle_cts_change(&up->port, status & UART_MSR_CTS); + if (status & (UART_MSR_DCTS|UART_MSR_DDSR)) { + if (status & UART_MSR_DDSR) + up->port.icount.dsr++; + else + up->port.icount.cts++; + uart_handle_dsr_cts_change(&up->port, status & UART_MSR_CTS, status & UART_MSR_DSR); + } wake_up_interruptible(&up->port.info->delta_msr_wait); } diff -puN drivers/serial/serial_core.c~serial-8250-implement-dtr-dsr-handshaking drivers/serial/serial_core.c --- a/drivers/serial/serial_core.c~serial-8250-implement-dtr-dsr-handshaking +++ a/drivers/serial/serial_core.c @@ -192,6 +192,13 @@ static int uart_startup(struct uart_stat spin_unlock_irq(&port->lock); } + if (info->flags & UIF_DSR_FLOW) { + spin_lock_irq(&port->lock); + if (!(port->ops->get_mctrl(port) & TIOCM_DSR)) + info->tty->hw_stopped = 1; + spin_unlock_irq(&port->lock); + } + info->flags |= UIF_INITIALIZED; clear_bit(TTY_IO_ERROR, &info->tty->flags); @@ -437,6 +444,11 @@ uart_change_speed(struct uart_state *sta else state->info->flags &= ~UIF_CTS_FLOW; + if (termios->c_cflag & CDTRDSR) + state->info->flags |= UIF_DSR_FLOW; + else + state->info->flags &= ~UIF_DSR_FLOW; + if (termios->c_cflag & CLOCAL) state->info->flags &= ~UIF_CHECK_CD; else diff -puN include/asm-i386/termbits.h~serial-8250-implement-dtr-dsr-handshaking include/asm-i386/termbits.h --- a/include/asm-i386/termbits.h~serial-8250-implement-dtr-dsr-handshaking +++ a/include/asm-i386/termbits.h @@ -157,6 +157,7 @@ struct ktermios { #define B3500000 0010016 #define B4000000 0010017 #define CIBAUD 002003600000 +#define CDTRDSR 004000000000 /* dtrdsr flow control */ #define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ diff -puN include/linux/serial_core.h~serial-8250-implement-dtr-dsr-handshaking include/linux/serial_core.h --- a/include/linux/serial_core.h~serial-8250-implement-dtr-dsr-handshaking +++ a/include/linux/serial_core.h @@ -335,6 +335,7 @@ struct uart_info { * Definitions for info->flags. These are _private_ to serial_core, and * are specific to this structure. They may be queried by low level drivers. */ +#define UIF_DSR_FLOW ((__force uif_t) (1 << 22)) #define UIF_CHECK_CD ((__force uif_t) (1 << 25)) #define UIF_CTS_FLOW ((__force uif_t) (1 << 26)) #define UIF_NORMAL_ACTIVE ((__force uif_t) (1 << 29)) @@ -494,26 +495,27 @@ uart_handle_dcd_change(struct uart_port /** * uart_handle_cts_change - handle a change of clear-to-send state + * when set DTR/DSR and RTS/CTS send only when both lines ok * @port: uart_port structure for the open port * @status: new clear to send status, nonzero if active */ static inline void -uart_handle_cts_change(struct uart_port *port, unsigned int status) +uart_handle_dsr_cts_change(struct uart_port *port, unsigned int status_cts, unsigned int status_dsr) { struct uart_info *info = port->info; struct tty_struct *tty = info->tty; + int cts_stop = (info->flags & UIF_CTS_FLOW) && !status_cts; + int dsr_stop = (info->flags & UIF_DSR_FLOW) && !status_dsr; - port->icount.cts++; - - if (info->flags & UIF_CTS_FLOW) { + if ((info->flags & UIF_CTS_FLOW) || (info->flags & UIF_DSR_FLOW)) { if (tty->hw_stopped) { - if (status) { + if (!(cts_stop||dsr_stop)) { tty->hw_stopped = 0; port->ops->start_tx(port); uart_write_wakeup(port); } } else { - if (!status) { + if (cts_stop||dsr_stop) { tty->hw_stopped = 1; port->ops->stop_tx(port); } @@ -544,7 +546,7 @@ uart_insert_char(struct uart_port *port, * UART_ENABLE_MS - determine if port should enable modem status irqs */ #define UART_ENABLE_MS(port,cflag) ((port)->flags & UPF_HARDPPS_CD || \ - (cflag) & CRTSCTS || \ + (cflag) & (CRTSCTS|CDTRDSR) || \ !((cflag) & CLOCAL)) #endif _ Patches currently in -mm which might be from michael@xxxxxxxxxx are serial-8250-implement-dtr-dsr-handshaking.patch serial-8250-implement-dtr-dsr-handshaking-fix.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html