From c1d7b083dc15423cae75be3c8b50a9a35aceac21 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 30 Mar 1999 06:33:10 +0000 Subject: [PATCH] Apply patch for sync serial support from Paul Fulghum. --- include/linux/if_ppp.h | 7 +- include/linux/if_pppvar.h | 3 +- linux/ppp.c | 243 +++++++++++++++++++++++++++++++++++--- pppd/options.c | 5 +- pppd/pppd.8 | 8 +- pppd/pppd.h | 3 +- pppd/sys-linux.c | 1 + 7 files changed, 245 insertions(+), 25 deletions(-) diff --git a/include/linux/if_ppp.h b/include/linux/if_ppp.h index 02c2b7c..95c552e 100644 --- a/include/linux/if_ppp.h +++ b/include/linux/if_ppp.h @@ -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. @@ -21,7 +21,7 @@ */ /* - * ==FILEVERSION 990226== + * ==FILEVERSION 990325== * * 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_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?) */ diff --git a/include/linux/if_pppvar.h b/include/linux/if_pppvar.h index 6fae4b9..d6cd0c2 100644 --- a/include/linux/if_pppvar.h +++ b/include/linux/if_pppvar.h @@ -42,7 +42,7 @@ */ /* - * ==FILEVERSION 990114== + * ==FILEVERSION 990325== * * 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 */ + 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 diff --git a/linux/ppp.c b/linux/ppp.c index 333c7fa..777afa7 100644 --- a/linux/ppp.c +++ b/linux/ppp.c @@ -4,7 +4,7 @@ * Al Longyear * Extensively rewritten by Paul Mackerras * - * ==FILEVERSION 990114== + * ==FILEVERSION 990325== * * 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 */ -/* $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 #include @@ -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 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_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); @@ -954,6 +956,135 @@ ppp_tty_wakeup (struct tty_struct *tty) 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, @@ -986,6 +1117,9 @@ ppp_tty_push(struct ppp *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) @@ -1184,6 +1318,74 @@ ppp_tty_receive (struct tty_struct *tty, const __u8 * data, 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. @@ -2024,23 +2226,25 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb) 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. */ @@ -2410,7 +2614,10 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) /* * 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; diff --git a/pppd/options.c b/pppd/options.c index 3e28def..2418d28 100644 --- a/pppd/options.c +++ b/pppd/options.c @@ -18,7 +18,7 @@ */ #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 @@ -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 sync_serial = 0; /* Device is synchronous serial device */ 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" }, + { "sync", o_bool, &sync_serial, + "Use synchronous HDLC serial encoding", 1 }, #ifdef PPP_FILTER { "pdebug", o_int, &dflag, diff --git a/pppd/pppd.8 b/pppd/pppd.8 index bcf2c3a..59e8c02 100644 --- a/pppd/pppd.8 +++ b/pppd/pppd.8 @@ -1,5 +1,5 @@ .\" 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 @@ -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 +.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 diff --git a/pppd/pppd.h b/pppd/pppd.h index 04c3ff9..a51c99c 100644 --- a/pppd/pppd.h +++ b/pppd/pppd.h @@ -16,7 +16,7 @@ * 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 bool sync_serial; /* Device is synchronous serial device */ #ifdef PPP_FILTER extern struct bpf_program pass_filter; /* Filter for pkts to pass */ diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c index e859886..718a678 100644 --- a/pppd/sys-linux.c +++ b/pppd/sys-linux.c @@ -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 = sync_serial ? x | SC_SYNC : x & ~SC_SYNC; set_flags(x); } -- 2.39.2