Apply patch for sync serial support from Paul Fulghum.
authorPaul Mackerras <paulus@samba.org>
Tue, 30 Mar 1999 06:33:10 +0000 (06:33 +0000)
committerPaul Mackerras <paulus@samba.org>
Tue, 30 Mar 1999 06:33:10 +0000 (06:33 +0000)
include/linux/if_ppp.h
include/linux/if_pppvar.h
linux/ppp.c
pppd/options.c
pppd/pppd.8
pppd/pppd.h
pppd/sys-linux.c

index 02c2b7ce6327aa1e903c898c8aa5df6de940df67..95c552e8ab027052e21a276ea7287897aa8fa3c3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: if_ppp.h,v 1.17 1999/03/02 05:37:51 paulus Exp $   */
+/*     $Id: if_ppp.h,v 1.18 1999/03/30 06:33:07 paulus Exp $   */
 
 /*
  * if_ppp.h - Point-to-Point Protocol definitions.
 
 /*
  * if_ppp.h - Point-to-Point Protocol definitions.
@@ -21,7 +21,7 @@
  */
 
 /*
  */
 
 /*
- *  ==FILEVERSION 990226==
+ *  ==FILEVERSION 990325==
  *
  *  NOTE TO MAINTAINERS:
  *     If you modify this file at all, please set the above date.
  *
  *  NOTE TO MAINTAINERS:
  *     If you modify this file at all, please set the above date.
@@ -67,7 +67,8 @@
 #define SC_LOG_OUTPKT  0x00040000      /* log contents of pkts sent */
 #define SC_LOG_RAWIN   0x00080000      /* log all chars received */
 #define SC_LOG_FLUSH   0x00100000      /* log all chars flushed */
 #define SC_LOG_OUTPKT  0x00040000      /* log contents of pkts sent */
 #define SC_LOG_RAWIN   0x00080000      /* log all chars received */
 #define SC_LOG_FLUSH   0x00100000      /* log all chars flushed */
-#define        SC_MASK         0x0f0000ff      /* bits that user can change */
+#define        SC_SYNC         0x00200000      /* synchronous serial mode */
+#define        SC_MASK         0x0f2000ff      /* bits that user can change */
 
 /* state bits */
 #define SC_XMIT_BUSY   0x10000000      /* (used by isdn_ppp?) */
 
 /* state bits */
 #define SC_XMIT_BUSY   0x10000000      /* (used by isdn_ppp?) */
index 6fae4b94bda05f967a033a576fbff406f9de404f..d6cd0c25bb17397d9619b8ea01cac8a7dc901055 100644 (file)
@@ -42,7 +42,7 @@
  */
 
 /*
  */
 
 /*
- *  ==FILEVERSION 990114==
+ *  ==FILEVERSION 990325==
  *
  *  NOTE TO MAINTAINERS:
  *   If you modify this file at all, please set the above date.
  *
  *  NOTE TO MAINTAINERS:
  *   If you modify this file at all, please set the above date.
@@ -89,6 +89,7 @@ struct ppp {
        __u8            escape;         /* 0x20 if prev char was PPP_ESC */
        __u8            toss;           /* toss this frame              */
        volatile __u8   tty_pushing;    /* internal state flag          */
        __u8            escape;         /* 0x20 if prev char was PPP_ESC */
        __u8            toss;           /* toss this frame              */
        volatile __u8   tty_pushing;    /* internal state flag          */
+       volatile __u8   woke_up;        /* internal state flag          */
        __u32           xmit_async_map[8]; /* 1 bit means that given control 
                                           character is quoted on output*/
        __u32           recv_async_map; /* 1 bit means that given control 
        __u32           xmit_async_map[8]; /* 1 bit means that given control 
                                           character is quoted on output*/
        __u32           recv_async_map; /* 1 bit means that given control 
index 333c7fa95ea705b8ede5c297e018bfffe2f088b1..777afa793ab73d84ffa43e243bdaa5144840bf91 100644 (file)
@@ -4,7 +4,7 @@
  *  Al Longyear <longyear@netcom.com>
  *  Extensively rewritten by Paul Mackerras <paulus@cs.anu.edu.au>
  *
  *  Al Longyear <longyear@netcom.com>
  *  Extensively rewritten by Paul Mackerras <paulus@cs.anu.edu.au>
  *
- *  ==FILEVERSION 990114==
+ *  ==FILEVERSION 990325==
  *
  *  NOTE TO MAINTAINERS:
  *     If you modify this file at all, please set the number above to the
  *
  *  NOTE TO MAINTAINERS:
  *     If you modify this file at all, please set the number above to the
@@ -45,7 +45,7 @@
 
 #define PPP_MAX_RCV_QLEN       32      /* max # frames we queue up for pppd */
 
 
 #define PPP_MAX_RCV_QLEN       32      /* max # frames we queue up for pppd */
 
-/* $Id: ppp.c,v 1.21 1999/02/26 06:48:21 paulus Exp $ */
+/* $Id: ppp.c,v 1.22 1999/03/30 06:33:07 paulus Exp $ */
 
 #include <linux/version.h>
 #include <linux/config.h>
 
 #include <linux/version.h>
 #include <linux/config.h>
@@ -185,9 +185,11 @@ static void ppp_unregister_compressor (struct compressor *cp);
 
 static void ppp_async_init(struct ppp *ppp);
 static void ppp_async_release(struct ppp *ppp);
 
 static void ppp_async_init(struct ppp *ppp);
 static void ppp_async_release(struct ppp *ppp);
+static int ppp_tty_sync_push(struct ppp *ppp);
 static int ppp_tty_push(struct ppp *ppp);
 static int ppp_async_encode(struct ppp *ppp);
 static int ppp_async_send(struct ppp *, struct sk_buff *);
 static int ppp_tty_push(struct ppp *ppp);
 static int ppp_async_encode(struct ppp *ppp);
 static int ppp_async_send(struct ppp *, struct sk_buff *);
+static int ppp_sync_send(struct ppp *, struct sk_buff *);
 
 static int ppp_ioctl(struct ppp *, unsigned int, unsigned long);
 static int ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp);
 
 static int ppp_ioctl(struct ppp *, unsigned int, unsigned long);
 static int ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp);
@@ -954,6 +956,135 @@ ppp_tty_wakeup (struct tty_struct *tty)
                ppp_output_wakeup(ppp);
 }
 
                ppp_output_wakeup(ppp);
 }
 
+/*
+ * Send a packet to the peer over a synchronous tty line.
+ * All encoding and FCS are handled by hardware.
+ * Addr/Ctrl and Protocol field compression implemented.
+ * Returns -1 iff the packet could not be accepted at present,
+ * 0 if the packet was accepted but we can't accept another yet, or
+ * 1 if we can accept another packet immediately.
+ * If this procedure returns 0, ppp_output_wakeup will be called
+ * exactly once.
+ */
+static int
+ppp_sync_send(struct ppp *ppp, struct sk_buff *skb)
+{
+       unsigned char *data;
+       int islcp;
+       
+       CHECK_PPP(0);
+
+       if (ppp->tpkt != NULL)
+               return -1;
+       ppp->tpkt = skb;
+
+       data = ppp->tpkt->data;
+       
+       /*
+        * LCP packets with code values between 1 (configure-reqest)
+        * and 7 (code-reject) must be sent as though no options
+        * had been negotiated.
+        */
+       islcp = PPP_PROTOCOL(data) == PPP_LCP
+               && 1 <= data[PPP_HDRLEN] && data[PPP_HDRLEN] <= 7;
+
+       /* only reset idle time for data packets */
+       if (PPP_PROTOCOL(data) < 0x8000)
+               ppp->last_xmit = jiffies;
+       ++ppp->stats.ppp_opackets;
+       ppp->stats.ppp_ooctects += ppp->tpkt->len;
+
+       if ( !(data[2]) && (ppp->flags & SC_COMP_PROT) ) {
+               /* compress protocol field */
+               data[2] = data[1];
+               data[1] = data[0];
+               skb_pull(ppp->tpkt,1);
+               data = ppp->tpkt->data;
+       }
+       
+       /*
+        * Do address/control compression
+        */
+       if ((ppp->flags & SC_COMP_AC) && !islcp
+           && PPP_ADDRESS(data) == PPP_ALLSTATIONS
+           && PPP_CONTROL(data) == PPP_UI) {
+               /* strip addr and control field */
+               skb_pull(ppp->tpkt,2);
+       }
+
+       return ppp_tty_sync_push(ppp);
+}
+
+/*
+ * Push a synchronous frame out to the tty.
+ * Returns 1 if frame accepted (or discarded), 0 otherwise.
+ */
+static int
+ppp_tty_sync_push(struct ppp *ppp)
+{
+       int sent;
+       struct tty_struct *tty = ppp2tty(ppp);
+       unsigned long flags;
+               
+       CHECK_PPP(0);
+
+       if (ppp->tpkt == NULL)
+               return 0;
+               
+       /* prevent reentrancy with tty_pushing flag */          
+       save_flags(flags);
+       cli();
+       if (ppp->tty_pushing) {
+               /* record wakeup attempt so we don't loose */
+               /* a wakeup call while doing push processing */
+               ppp->woke_up=1;
+               restore_flags(flags);
+               return 0;
+       }
+       ppp->tty_pushing = 1;
+       restore_flags(flags);
+       
+       if (tty == NULL || tty->disc_data != (void *) ppp)
+               goto flush;
+               
+       for(;;){
+               ppp->woke_up=0;
+               
+               /* Note: Sync driver accepts complete frame or nothing */
+               tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+               sent = tty->driver.write(tty, 0, ppp->tpkt->data, ppp->tpkt->len);
+               if (sent < 0) {
+                       /* write error (possible loss of CD) */
+                       /* record error and discard current packet */
+                       ppp->stats.ppp_oerrors++;
+                       break;
+               }
+               ppp->stats.ppp_obytes += sent;
+               if (sent < ppp->tpkt->len) {
+                       /* driver unable to accept frame just yet */
+                       save_flags(flags);
+                       cli();
+                       if (ppp->woke_up) {
+                               /* wake up called while processing */
+                               /* try to send the frame again */
+                               restore_flags(flags);
+                               continue;
+                       }
+                       /* wait for wakeup callback to try send again */
+                       ppp->tty_pushing = 0;
+                       restore_flags(flags);
+                       return 0;
+               }
+               break;
+       }
+flush: 
+       /* done with current packet (sent or discarded) */
+       KFREE_SKB(ppp->tpkt);
+       ppp->tpkt = 0;
+       ppp->tty_pushing = 0;
+       return 1;
+}
+
 /*
  * Send a packet to the peer over an async tty line.
  * Returns -1 iff the packet could not be accepted at present,
 /*
  * Send a packet to the peer over an async tty line.
  * Returns -1 iff the packet could not be accepted at present,
@@ -986,6 +1117,9 @@ ppp_tty_push(struct ppp *ppp)
 {
        int avail, sent, done = 0;
        struct tty_struct *tty = ppp2tty(ppp);
 {
        int avail, sent, done = 0;
        struct tty_struct *tty = ppp2tty(ppp);
+       
+       if ( ppp->flags & SC_SYNC ) 
+               return ppp_tty_sync_push(ppp);
 
        CHECK_PPP(0);
        if (ppp->tty_pushing)
 
        CHECK_PPP(0);
        if (ppp->tty_pushing)
@@ -1184,6 +1318,74 @@ ppp_tty_receive (struct tty_struct *tty, const __u8 * data,
 
        ppp->stats.ppp_ibytes += count;
        skb = ppp->rpkt;
 
        ppp->stats.ppp_ibytes += count;
        skb = ppp->rpkt;
+       
+       if ( ppp->flags & SC_SYNC ) {
+               /* synchronous mode */
+               
+               if (ppp->toss==0xE0) {
+                       /* this is the 1st frame, reset vj comp */
+                       ppp_receive_error(ppp);
+                       ppp->toss = 0;
+               }
+               
+               /*
+                * Allocate an skbuff for frame.
+                * The 128 is room for VJ header expansion.
+                */
+               
+               if (skb == NULL)
+                       skb = dev_alloc_skb(ppp->mru + 128 + PPP_HDRLEN);
+                       
+               if (skb == NULL) {
+                       if (ppp->flags & SC_DEBUG)
+                               printk(KERN_DEBUG "couldn't "
+                                      "alloc skb for recv\n");
+               } else {
+                       LIBERATE_SKB(skb);
+                       /*
+                        * Decompress A/C and protocol compression here.
+                        */
+                       p = skb_put(skb, 2);
+                       p[0] = PPP_ALLSTATIONS;
+                       p[1] = PPP_UI;
+                       if (*data == PPP_ALLSTATIONS) {
+                               data += 2;
+                               count -= 2;
+                       }
+                       if ((*data & 1) != 0) {
+                               p = skb_put(skb, 1);
+                               p[0] = 0;
+                       }
+
+                       /* copy frame to socket buffer */
+                       p = skb_put(skb, count);
+                       memcpy(p,data,count);
+                       
+                       /*
+                        * Check if we've overflowed the MRU
+                        */
+                       if (skb->len >= ppp->mru + PPP_HDRLEN + 2
+                           || skb_tailroom(skb) <= 0) {
+                               ++ppp->estats.rx_length_errors;
+                               if (ppp->flags & SC_DEBUG)
+                                       printk(KERN_DEBUG "rcv frame too long: "
+                                              "len=%d mru=%d hroom=%d troom=%d\n",
+                                              skb->len, ppp->mru, skb_headroom(skb),
+                                              skb_tailroom(skb));
+                       } else {
+                               if (!ppp_receive_frame(ppp, skb)) {
+                                       KFREE_SKB(skb);
+                                       ppp_receive_error(ppp);
+                               }
+                       }
+               
+                       /* Reset for the next frame */
+                       skb = NULL;
+               }
+               ppp->rpkt = skb;
+               return;
+       }
+       
        while (count-- > 0) {
                /*
                 * Collect the character and error condition for the character.
        while (count-- > 0) {
                /*
                 * Collect the character and error condition for the character.
@@ -2024,23 +2226,25 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb)
                return 0;
        }
 
                return 0;
        }
 
-       /*
-        * Verify the FCS of the frame and discard the FCS characters
-        * from the end of the buffer.
-        */
-       if (ppp->rfcs != PPP_GOODFCS) {
-               if (ppp->flags & SC_DEBUG) {
-                       printk(KERN_DEBUG
-                              "ppp: frame with bad fcs, length = %d\n",
-                              count);
-                       ppp_print_buffer("bad frame", data, count);
+       if ( !(ppp->flags & SC_SYNC) ) { 
+               /*
+                * Verify the FCS of the frame and discard the FCS characters
+                * from the end of the buffer.
+                */
+               if (ppp->rfcs != PPP_GOODFCS) {
+                       if (ppp->flags & SC_DEBUG) {
+                               printk(KERN_DEBUG
+                                      "ppp: frame with bad fcs, length = %d\n",
+                                      count);
+                               ppp_print_buffer("bad frame", data, count);
+                       }
+                       ++ppp->estats.rx_crc_errors;
+                       return 0;
                }
                }
-               ++ppp->estats.rx_crc_errors;
-               return 0;
+               count -= 2;             /* ignore the fcs characters */
+               skb_trim(skb, count);
        }
        }
-       count -= 2;             /* ignore the fcs characters */
-       skb_trim(skb, count);
-
+       
        /*
         * Process the active decompressor.
         */
        /*
         * Process the active decompressor.
         */
@@ -2410,7 +2614,10 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
        /*
         * Send the frame
         */
        /*
         * Send the frame
         */
-       ret = ppp_async_send(ppp, skb);
+       if ( ppp->flags & SC_SYNC ) 
+               ret = ppp_sync_send(ppp, skb);
+       else
+               ret = ppp_async_send(ppp, skb);
        if (ret > 0) {
                /* we can release the lock */
                ppp->xmit_busy = 0;
        if (ret > 0) {
                /* we can release the lock */
                ppp->xmit_busy = 0;
index 3e28def43191926347ffdfeb95559c1c45214000..2418d28642a71167175fa421b169acc4648720d2 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: options.c,v 1.55 1999/03/24 05:05:24 paulus Exp $";
+static char rcsid[] = "$Id: options.c,v 1.56 1999/03/30 06:33:08 paulus Exp $";
 #endif
 
 #include <ctype.h>
 #endif
 
 #include <ctype.h>
@@ -89,6 +89,7 @@ int   holdoff = 30;           /* # seconds to pause before reconnecting */
 bool   notty = 0;              /* Stdin/out is not a tty */
 char   *record_file = NULL;    /* File to record chars sent/received */
 int    using_pty = 0;
 bool   notty = 0;              /* Stdin/out is not a tty */
 char   *record_file = NULL;    /* File to record chars sent/received */
 int    using_pty = 0;
+bool   sync_serial = 0;        /* Device is synchronous serial device */
 
 extern option_t auth_options[];
 
 
 extern option_t auth_options[];
 
@@ -211,6 +212,8 @@ option_t general_options[] = {
       "Show brief listing of options" },
     { "-h", o_special_noarg, showhelp,
       "Show brief listing of options" },
       "Show brief listing of options" },
     { "-h", o_special_noarg, showhelp,
       "Show brief listing of options" },
+    { "sync", o_bool, &sync_serial,
+      "Use synchronous HDLC serial encoding", 1 },
 
 #ifdef PPP_FILTER
     { "pdebug", o_int, &dflag,
 
 #ifdef PPP_FILTER
     { "pdebug", o_int, &dflag,
index bcf2c3a34cbff10af9d632750a3ac05a47169a0c..59e8c0251ff4b07a0e0263ab8891efac1b4c1655 100644 (file)
@@ -1,5 +1,5 @@
 .\" manual page [] for pppd 2.3
 .\" manual page [] for pppd 2.3
-.\" $Id: pppd.8,v 1.37 1999/03/23 03:22:34 paulus Exp $
+.\" $Id: pppd.8,v 1.38 1999/03/30 06:33:09 paulus Exp $
 .\" SH section heading
 .\" SS subsection heading
 .\" LP paragraph
 .\" SH section heading
 .\" SS subsection heading
 .\" LP paragraph
@@ -690,6 +690,12 @@ With this option, pppd will not transmit LCP packets to initiate a
 connection until a valid LCP packet is received from the peer (as for
 the `passive' option with ancient versions of pppd).
 .TP
 connection until a valid LCP packet is received from the peer (as for
 the `passive' option with ancient versions of pppd).
 .TP
+.B sync
+Use synchronous HDLC serial encoding instead of asynchronous.
+The device used by pppd with this option must support synchronous
+serial communications. Currently supports Microgate SyncLink adapters
+under Linux.
+.TP
 .B usehostname
 Enforce the use of the hostname (with domain name appended, if given)
 as the name of the local system for authentication purposes (overrides
 .B usehostname
 Enforce the use of the hostname (with domain name appended, if given)
 as the name of the local system for authentication purposes (overrides
index 04c3ff9a8c794e4bf75366b473eebecf8723ee12..a51c99c80418616e1c4847e3571b227f97b27d1f 100644 (file)
@@ -16,7 +16,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * $Id: pppd.h,v 1.35 1999/03/24 05:05:25 paulus Exp $
+ * $Id: pppd.h,v 1.36 1999/03/30 06:33:09 paulus Exp $
  */
 
 /*
  */
 
 /*
@@ -181,6 +181,7 @@ extern int  idle_time_limit;/* Shut down link if idle for this long */
 extern int     holdoff;        /* Dead time before restarting */
 extern bool    notty;          /* Stdin/out is not a tty */
 extern char    *record_file;   /* File to record chars sent/received */
 extern int     holdoff;        /* Dead time before restarting */
 extern bool    notty;          /* Stdin/out is not a tty */
 extern char    *record_file;   /* File to record chars sent/received */
+extern bool    sync_serial;    /* Device is synchronous serial device */
 
 #ifdef PPP_FILTER
 extern struct  bpf_program pass_filter;   /* Filter for pkts to pass */
 
 #ifdef PPP_FILTER
 extern struct  bpf_program pass_filter;   /* Filter for pkts to pass */
index e85988665924545ac1887d1b22d5c9570b8894aa..718a678bfbc4a4abf3af87d0547636b0a3b8a5a8 100644 (file)
@@ -866,6 +866,7 @@ void ppp_send_config (int unit,int mtu,u_int32_t asyncmap,int pcomp,int accomp)
     x = get_flags();
     x = pcomp  ? x | SC_COMP_PROT : x & ~SC_COMP_PROT;
     x = accomp ? x | SC_COMP_AC   : x & ~SC_COMP_AC;
     x = get_flags();
     x = pcomp  ? x | SC_COMP_PROT : x & ~SC_COMP_PROT;
     x = accomp ? x | SC_COMP_AC   : x & ~SC_COMP_AC;
+    x = sync_serial ? x | SC_SYNC : x & ~SC_SYNC;
     set_flags(x);
 }
 
     set_flags(x);
 }