As I needed support for DTR/DSR hardware handshake to communicate with
a serial printer (and the "wire RTS/CTS to DTR/DSR" tip from the
serial-HOWTO works fine for a demo, but is not applicable for a few
thousand POS terminals *gg*), I implemented this functionality.

I append patches for serial.c on 2.0.38/2.2.16/2.4.0-test5, and a
patch to include/asm-*/termbits.h (which adds a flag DTRDSR).

In order to use this patch, add the following #define to your code:
        #define DTRDSR          004000000000
and use DTRDSR as you used CRTSCTS.

I guess this patch is trivial enough to go into the next kernel versions

Martin
*** linux-old/drivers/char/serial.c     Tue Aug  1 18:15:20 2000
--- linux/drivers/char/serial.c Tue Aug  1 18:24:01 2000
***************
*** 21,26 ****
--- 21,30 ----
   * 
   * Added Support for PCI serial boards which contain 16x50 Chips
   * 31.10.1998 Henning P. Schmiedehausen <[EMAIL PROTECTED]>
+  *
+  *  8/00: Added support for DTR/DRS hardware handshake (using flag DTRDRS)
+  *      Martin Schenk <[EMAIL PROTECTED]>
+  *
   * 
   * This module exports the following rs232 io functions:
   *
***************
*** 585,594 ****
                }
        }
        if (info->flags & ASYNC_CTS_FLOW) {
                if (info->tty->hw_stopped) {
!                       if (status & UART_MSR_CTS) {
  #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
!                               printk("CTS tx start...");
  #endif
                                info->tty->hw_stopped = 0;
                                info->IER |= UART_IER_THRI;
--- 589,601 ----
                }
        }
        if (info->flags & ASYNC_CTS_FLOW) {
+               int flg=(info->tty->termios->c_cflag & DTRDSR) ? UART_MSR_DSR : 
+UART_MSR_CTS;
+ 
                if (info->tty->hw_stopped) {
!                       if (status & flg) {
  #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
!                               if (info->tty->termios->c_cflag & DTRDSR) printk("DSR 
tx start...");
!                               else printk("CTS tx start...");
  #endif
                                info->tty->hw_stopped = 0;
                                info->IER |= UART_IER_THRI;
***************
*** 597,605 ****
                                return;
                        }
                } else {
!                       if (!(status & UART_MSR_CTS)) {
  #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
!                               printk("CTS tx stop...");
  #endif
                                info->tty->hw_stopped = 1;
                                info->IER &= ~UART_IER_THRI;
--- 604,613 ----
                                return;
                        }
                } else {
!                       if (!(status & flg)) {
  #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
!                               if (info->tty->termios->c_cflag & DTRDSR) printk("DSR 
tx ...");
!                               else printk("CTS tx stop...");
  #endif
                                info->tty->hw_stopped = 1;
                                info->IER &= ~UART_IER_THRI;
***************
*** 1336,1341 ****
--- 1344,1353 ----
                info->flags |= ASYNC_CTS_FLOW;
                info->IER |= UART_IER_MSI;
        } else
+       if (cflag & DTRDSR) {
+               info->flags |= ASYNC_CTS_FLOW;
+               info->IER |= UART_IER_MSI;
+       } else
                info->flags &= ~ASYNC_CTS_FLOW;
        if (cflag & CLOCAL)
                info->flags &= ~ASYNC_CHECK_CD;
***************
*** 1524,1529 ****
--- 1536,1542 ----
  static void rs_throttle(struct tty_struct * tty)
  {
        struct async_struct *info = (struct async_struct *)tty->driver_data;
+       int flg=0;
  #ifdef SERIAL_DEBUG_THROTTLE
        char    buf[64];
        
***************
*** 1537,1544 ****
        if (I_IXOFF(tty))
                info->x_char = STOP_CHAR(tty);
  
!       info->MCR &= ~UART_MCR_RTS;
!       info->MCR_noint &= ~UART_MCR_RTS;
        cli();
        serial_out(info, UART_MCR, info->MCR);
        sti();
--- 1550,1560 ----
        if (I_IXOFF(tty))
                info->x_char = STOP_CHAR(tty);
  
!       if (tty->termios->c_cflag & CRTSCTS) flg=UART_MCR_RTS;
!       if (tty->termios->c_cflag & DTRDSR) flg=UART_MCR_DTR;
! 
!       info->MCR &= ~flg;
!       info->MCR_noint &= ~flg;
        cli();
        serial_out(info, UART_MCR, info->MCR);
        sti();
***************
*** 1547,1552 ****
--- 1563,1569 ----
  static void rs_unthrottle(struct tty_struct * tty)
  {
        struct async_struct *info = (struct async_struct *)tty->driver_data;
+       int flg=0;
  #ifdef SERIAL_DEBUG_THROTTLE
        char    buf[64];
        
***************
*** 1563,1570 ****
                else
                        info->x_char = START_CHAR(tty);
        }
!       info->MCR |= UART_MCR_RTS;
!       info->MCR_noint |= UART_MCR_RTS;
        cli();
        serial_out(info, UART_MCR, info->MCR);
        sti();
--- 1580,1590 ----
                else
                        info->x_char = START_CHAR(tty);
        }
!       if (tty->termios->c_cflag & CRTSCTS) flg=UART_MCR_RTS;
!       if (tty->termios->c_cflag & DTRDSR) flg=UART_MCR_DTR;
! 
!       info->MCR |= flg;
!       info->MCR_noint |= flg;
        cli();
        serial_out(info, UART_MCR, info->MCR);
        sti();
***************
*** 2210,2215 ****
--- 2230,2240 ----
  
        if ((old_termios->c_cflag & CRTSCTS) &&
            !(tty->termios->c_cflag & CRTSCTS)) {
+               tty->hw_stopped = 0;
+               rs_start(tty);
+       }
+       if ((old_termios->c_cflag & DTRDSR) &&
+           !(tty->termios->c_cflag & DTRDSR)) {
                tty->hw_stopped = 0;
                rs_start(tty);
        }
*** linux-old/drivers/char/serial.c     Tue Aug  1 17:48:13 2000
--- linux/drivers/char/serial.c Tue Aug  1 17:50:48 2000
***************
*** 32,37 ****
--- 32,40 ----
   *  4/98: Added changes to support the ARM architecture proposed by
   *      Russell King
   *
+  *  8/00: Added support for DTR/DRS hardware handshake (using flag DTRDRS)
+  *      Martin Schenk <[EMAIL PROTECTED]>
+  *
   * This module exports the following rs232 io functions:
   *
   *    int rs_init(void);
***************
*** 543,552 ****
                }
        }
        if (info->flags & ASYNC_CTS_FLOW) {
                if (info->tty->hw_stopped) {
!                       if (status & UART_MSR_CTS) {
  #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
!                               printk("CTS tx start...");
  #endif
                                info->tty->hw_stopped = 0;
                                info->IER |= UART_IER_THRI;
--- 546,558 ----
                }
        }
        if (info->flags & ASYNC_CTS_FLOW) {
+               int flg=(info->tty->termios->c_cflag & DTRDSR) ? UART_MSR_DSR : 
+UART_MSR_CTS;
+ 
                if (info->tty->hw_stopped) {
!                       if (status & flg) {
  #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
!                               if (info->tty->termios->c_cflag & DTRDSR) printk("DSR 
tx start...");
!                               else printk("CTS tx start...");
  #endif
                                info->tty->hw_stopped = 0;
                                info->IER |= UART_IER_THRI;
***************
*** 555,563 ****
                                return;
                        }
                } else {
!                       if (!(status & UART_MSR_CTS)) {
  #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
!                               printk("CTS tx stop...");
  #endif
                                info->tty->hw_stopped = 1;
                                info->IER &= ~UART_IER_THRI;
--- 561,570 ----
                                return;
                        }
                } else {
!                       if (!(status & flg)) {
  #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
!                               if (info->tty->termios->c_cflag & DTRDSR) printk("DSR 
tx ...");
!                               else printk("CTS tx stop...");
  #endif
                                info->tty->hw_stopped = 1;
                                info->IER &= ~UART_IER_THRI;
***************
*** 1332,1337 ****
--- 1339,1348 ----
                info->flags |= ASYNC_CTS_FLOW;
                info->IER |= UART_IER_MSI;
        } else
+       if (cflag & DTRDSR) {
+               info->flags |= ASYNC_CTS_FLOW;
+               info->IER |= UART_IER_MSI;
+       } else
                info->flags &= ~ASYNC_CTS_FLOW;
        if (cflag & CLOCAL)
                info->flags &= ~ASYNC_CHECK_CD;
***************
*** 1591,1596 ****
--- 1602,1610 ----
        if (tty->termios->c_cflag & CRTSCTS)
                info->MCR &= ~UART_MCR_RTS;
  
+       if (tty->termios->c_cflag & DTRDSR)
+               info->MCR &= ~UART_MCR_DTR;
+ 
        save_flags(flags); cli();
        serial_out(info, UART_MCR, info->MCR);
        restore_flags(flags);
***************
*** 1618,1623 ****
--- 1632,1639 ----
        }
        if (tty->termios->c_cflag & CRTSCTS)
                info->MCR |= UART_MCR_RTS;
+       if (tty->termios->c_cflag & DTRDSR)
+               info->MCR |= UART_MCR_DTR;
        save_flags(flags); cli();
        serial_out(info, UART_MCR, info->MCR);
        restore_flags(flags);
***************
*** 2193,2200 ****
        /* Handle transition away from B0 status */
        if (!(old_termios->c_cflag & CBAUD) &&
            (cflag & CBAUD)) {
!               info->MCR |= UART_MCR_DTR;
! 
                if (!(tty->termios->c_cflag & CRTSCTS) || 
                    !test_bit(TTY_THROTTLED, &tty->flags)) {
                        info->MCR |= UART_MCR_RTS;
--- 2209,2218 ----
        /* Handle transition away from B0 status */
        if (!(old_termios->c_cflag & CBAUD) &&
            (cflag & CBAUD)) {
!               if (!(tty->termios->c_cflag & DTRDSR) ||
!                   !test_bit(TTY_THROTTLED, &tty->flags)) {
!                       info->MCR |= UART_MCR_DTR;
!               }
                if (!(tty->termios->c_cflag & CRTSCTS) || 
                    !test_bit(TTY_THROTTLED, &tty->flags)) {
                        info->MCR |= UART_MCR_RTS;
***************
*** 2207,2212 ****
--- 2225,2236 ----
        /* Handle turning off CRTSCTS */
        if ((old_termios->c_cflag & CRTSCTS) &&
            !(tty->termios->c_cflag & CRTSCTS)) {
+               tty->hw_stopped = 0;
+               rs_start(tty);
+       }
+       /* Handle turning off DTRDSR */
+       if ((old_termios->c_cflag & DTRDSR) &&
+           !(tty->termios->c_cflag & DTRDSR)) {
                tty->hw_stopped = 0;
                rs_start(tty);
        }
*** linux-old/drivers/char/serial.c     Tue Aug  1 18:03:05 2000
--- linux/drivers/char/serial.c Tue Aug  1 18:11:08 2000
***************
*** 51,56 ****
--- 51,59 ----
   *
   *  7/00: Support Timedia/Sunix/Exsys PCI cards
   *
+  *  8/00: Added support for DTR/DRS hardware handshake (using flag DTRDRS)
+  *      Martin Schenk <[EMAIL PROTECTED]>
+  *
   * This module exports the following rs232 io functions:
   *
   *    int rs_init(void);
***************
*** 740,749 ****
                }
        }
        if (info->flags & ASYNC_CTS_FLOW) {
                if (info->tty->hw_stopped) {
!                       if (status & UART_MSR_CTS) {
  #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
!                               printk("CTS tx start...");
  #endif
                                info->tty->hw_stopped = 0;
                                info->IER |= UART_IER_THRI;
--- 743,755 ----
                }
        }
        if (info->flags & ASYNC_CTS_FLOW) {
+               int flg=(info->tty->termios->c_cflag & DTRDSR) ? UART_MSR_DSR : 
+UART_MSR_CTS;
+ 
                if (info->tty->hw_stopped) {
!                       if (status & flg) {
  #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
!                               if (info->tty->termios->c_cflag & DTRDSR) printk("DSR 
tx start...");
!                               else printk("CTS tx start...");
  #endif
                                info->tty->hw_stopped = 0;
                                info->IER |= UART_IER_THRI;
***************
*** 752,760 ****
                                return;
                        }
                } else {
!                       if (!(status & UART_MSR_CTS)) {
  #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
!                               printk("CTS tx stop...");
  #endif
                                info->tty->hw_stopped = 1;
                                info->IER &= ~UART_IER_THRI;
--- 758,767 ----
                                return;
                        }
                } else {
!                       if (!(status & flg)) {
  #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
!                               if (info->tty->termios->c_cflag & DTRDSR) printk("DSR 
tx ...");
!                               else printk("CTS tx stop...");
  #endif
                                info->tty->hw_stopped = 1;
                                info->IER &= ~UART_IER_THRI;
***************
*** 1700,1705 ****
--- 1707,1716 ----
                info->flags |= ASYNC_CTS_FLOW;
                info->IER |= UART_IER_MSI;
        } else
+       if (cflag & DTRDSR) {
+               info->flags |= ASYNC_CTS_FLOW;
+               info->IER |= UART_IER_MSI;
+       } else
                info->flags &= ~ASYNC_CTS_FLOW;
        if (cflag & CLOCAL)
                info->flags &= ~ASYNC_CHECK_CD;
***************
*** 1968,1973 ****
--- 1979,1987 ----
        if (tty->termios->c_cflag & CRTSCTS)
                info->MCR &= ~UART_MCR_RTS;
  
+       if (tty->termios->c_cflag & DTRDSR)
+               info->MCR &= ~UART_MCR_DTR;
+ 
        save_flags(flags); cli();
        serial_out(info, UART_MCR, info->MCR);
        restore_flags(flags);
***************
*** 1995,2000 ****
--- 2009,2016 ----
        }
        if (tty->termios->c_cflag & CRTSCTS)
                info->MCR |= UART_MCR_RTS;
+       if (tty->termios->c_cflag & DTRDSR)
+               info->MCR |= UART_MCR_DTR;
        save_flags(flags); cli();
        serial_out(info, UART_MCR, info->MCR);
        restore_flags(flags);
***************
*** 2676,2682 ****
        /* Handle transition away from B0 status */
        if (!(old_termios->c_cflag & CBAUD) &&
            (cflag & CBAUD)) {
!               info->MCR |= UART_MCR_DTR;
                if (!(tty->termios->c_cflag & CRTSCTS) || 
                    !test_bit(TTY_THROTTLED, &tty->flags)) {
                        info->MCR |= UART_MCR_RTS;
--- 2692,2701 ----
        /* Handle transition away from B0 status */
        if (!(old_termios->c_cflag & CBAUD) &&
            (cflag & CBAUD)) {
!               if (!(tty->termios->c_cflag & DTRDSR) ||
!                   !test_bit(TTY_THROTTLED, &tty->flags)) {
!                       info->MCR |= UART_MCR_DTR;
!               }
                if (!(tty->termios->c_cflag & CRTSCTS) || 
                    !test_bit(TTY_THROTTLED, &tty->flags)) {
                        info->MCR |= UART_MCR_RTS;
***************
*** 2689,2694 ****
--- 2708,2719 ----
        /* Handle turning off CRTSCTS */
        if ((old_termios->c_cflag & CRTSCTS) &&
            !(tty->termios->c_cflag & CRTSCTS)) {
+               tty->hw_stopped = 0;
+               rs_start(tty);
+       }
+       /* Handle turning off DTRDSR */
+       if ((old_termios->c_cflag & DTRDSR) &&
+           !(tty->termios->c_cflag & DTRDSR)) {
                tty->hw_stopped = 0;
                rs_start(tty);
        }
*** linux-old/include/asm-i386/termbits.h       Tue Aug  1 17:54:03 2000
--- linux/include/asm-i386/termbits.h   Tue Aug  1 17:53:59 2000
***************
*** 135,140 ****
--- 135,141 ----
  #define CIBAUD          002003600000  /* input baud rate (not used) */
  #define CMSPAR          010000000000          /* mark or space (stick) parity */
  #define CRTSCTS         020000000000          /* flow control */
+ #define DTRDSR          004000000000          /* DTRDSR flow control */
  
  /* c_lflag bits */
  #define ISIG  0000001

Reply via email to