linux/drivers/char/n_hdlc.c
<<
>>
Prefs
   1/* generic HDLC line discipline for Linux
   2 *
   3 * Written by Paul Fulghum paulkf@microgate.com
   4 * for Microgate Corporation
   5 *
   6 * Microgate and SyncLink are registered trademarks of Microgate Corporation
   7 *
   8 * Adapted from ppp.c, written by Michael Callahan <callahan@maths.ox.ac.uk>,
   9 *      Al Longyear <longyear@netcom.com>,
  10 *      Paul Mackerras <Paul.Mackerras@cs.anu.edu.au>
  11 *
  12 * Original release 01/11/99
  13 * $Id: n_hdlc.c,v 4.8 2003/05/06 21:18:51 paulkf Exp $
  14 *
  15 * This code is released under the GNU General Public License (GPL)
  16 *
  17 * This module implements the tty line discipline N_HDLC for use with
  18 * tty device drivers that support bit-synchronous HDLC communications.
  19 *
  20 * All HDLC data is frame oriented which means:
  21 *
  22 * 1. tty write calls represent one complete transmit frame of data
  23 *    The device driver should accept the complete frame or none of 
  24 *    the frame (busy) in the write method. Each write call should have
  25 *    a byte count in the range of 2-65535 bytes (2 is min HDLC frame
  26 *    with 1 addr byte and 1 ctrl byte). The max byte count of 65535
  27 *    should include any crc bytes required. For example, when using
  28 *    CCITT CRC32, 4 crc bytes are required, so the maximum size frame
  29 *    the application may transmit is limited to 65531 bytes. For CCITT
  30 *    CRC16, the maximum application frame size would be 65533.
  31 *
  32 *
  33 * 2. receive callbacks from the device driver represents
  34 *    one received frame. The device driver should bypass
  35 *    the tty flip buffer and call the line discipline receive
  36 *    callback directly to avoid fragmenting or concatenating
  37 *    multiple frames into a single receive callback.
  38 *
  39 *    The HDLC line discipline queues the receive frames in separate
  40 *    buffers so complete receive frames can be returned by the
  41 *    tty read calls.
  42 *
  43 * 3. tty read calls returns an entire frame of data or nothing.
  44 *    
  45 * 4. all send and receive data is considered raw. No processing
  46 *    or translation is performed by the line discipline, regardless
  47 *    of the tty flags
  48 *
  49 * 5. When line discipline is queried for the amount of receive
  50 *    data available (FIOC), 0 is returned if no data available,
  51 *    otherwise the count of the next available frame is returned.
  52 *    (instead of the sum of all received frame counts).
  53 *
  54 * These conventions allow the standard tty programming interface
  55 * to be used for synchronous HDLC applications when used with
  56 * this line discipline (or another line discipline that is frame
  57 * oriented such as N_PPP).
  58 *
  59 * The SyncLink driver (synclink.c) implements both asynchronous
  60 * (using standard line discipline N_TTY) and synchronous HDLC
  61 * (using N_HDLC) communications, with the latter using the above
  62 * conventions.
  63 *
  64 * This implementation is very basic and does not maintain
  65 * any statistics. The main point is to enforce the raw data
  66 * and frame orientation of HDLC communications.
  67 *
  68 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  69 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  70 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  71 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  72 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  73 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  74 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  75 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  76 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  77 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  78 * OF THE POSSIBILITY OF SUCH DAMAGE.
  79 */
  80
  81#define HDLC_MAGIC 0x239e
  82#define HDLC_VERSION "$Revision: 4.8 $"
  83
  84#include <linux/module.h>
  85#include <linux/init.h>
  86#include <linux/kernel.h>
  87#include <linux/sched.h>
  88#include <linux/types.h>
  89#include <linux/fcntl.h>
  90#include <linux/interrupt.h>
  91#include <linux/ptrace.h>
  92
  93#undef VERSION
  94#define VERSION(major,minor,patch) (((((major)<<8)+(minor))<<8)+(patch))
  95
  96#include <linux/poll.h>
  97#include <linux/in.h>
  98#include <linux/ioctl.h>
  99#include <linux/slab.h>
 100#include <linux/tty.h>
 101#include <linux/errno.h>
 102#include <linux/string.h>       /* used in new tty drivers */
 103#include <linux/signal.h>       /* used in new tty drivers */
 104#include <linux/if.h>
 105#include <linux/bitops.h>
 106
 107#include <asm/system.h>
 108#include <asm/termios.h>
 109#include <asm/uaccess.h>
 110
 111/*
 112 * Buffers for individual HDLC frames
 113 */
 114#define MAX_HDLC_FRAME_SIZE 65535 
 115#define DEFAULT_RX_BUF_COUNT 10
 116#define MAX_RX_BUF_COUNT 60
 117#define DEFAULT_TX_BUF_COUNT 1
 118
 119struct n_hdlc_buf {
 120        struct n_hdlc_buf *link;
 121        int               count;
 122        char              buf[1];
 123};
 124
 125#define N_HDLC_BUF_SIZE (sizeof(struct n_hdlc_buf) + maxframe)
 126
 127struct n_hdlc_buf_list {
 128        struct n_hdlc_buf *head;
 129        struct n_hdlc_buf *tail;
 130        int               count;
 131        spinlock_t        spinlock;
 132};
 133
 134/**
 135 * struct n_hdlc - per device instance data structure
 136 * @magic - magic value for structure
 137 * @flags - miscellaneous control flags
 138 * @tty - ptr to TTY structure
 139 * @backup_tty - TTY to use if tty gets closed
 140 * @tbusy - reentrancy flag for tx wakeup code
 141 * @woke_up - FIXME: describe this field
 142 * @tbuf - currently transmitting tx buffer
 143 * @tx_buf_list - list of pending transmit frame buffers
 144 * @rx_buf_list - list of received frame buffers
 145 * @tx_free_buf_list - list unused transmit frame buffers
 146 * @rx_free_buf_list - list unused received frame buffers
 147 */
 148struct n_hdlc {
 149        int                     magic;
 150        __u32                   flags;
 151        struct tty_struct       *tty;
 152        struct tty_struct       *backup_tty;
 153        int                     tbusy;
 154        int                     woke_up;
 155        struct n_hdlc_buf       *tbuf;
 156        struct n_hdlc_buf_list  tx_buf_list;
 157        struct n_hdlc_buf_list  rx_buf_list;
 158        struct n_hdlc_buf_list  tx_free_buf_list;
 159        struct n_hdlc_buf_list  rx_free_buf_list;
 160};
 161
 162/*
 163 * HDLC buffer list manipulation functions
 164 */
 165static void n_hdlc_buf_list_init(struct n_hdlc_buf_list *list);
 166static void n_hdlc_buf_put(struct n_hdlc_buf_list *list,
 167                           struct n_hdlc_buf *buf);
 168static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *list);
 169
 170/* Local functions */
 171
 172static struct n_hdlc *n_hdlc_alloc (void);
 173
 174/* debug level can be set by insmod for debugging purposes */
 175#define DEBUG_LEVEL_INFO        1
 176static int debuglevel;
 177
 178/* max frame size for memory allocations */
 179static int maxframe = 4096;
 180
 181/* TTY callbacks */
 182
 183static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
 184                           __u8 __user *buf, size_t nr);
 185static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
 186                            const unsigned char *buf, size_t nr);
 187static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,
 188                            unsigned int cmd, unsigned long arg);
 189static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,
 190                                    poll_table *wait);
 191static int n_hdlc_tty_open(struct tty_struct *tty);
 192static void n_hdlc_tty_close(struct tty_struct *tty);
 193static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *cp,
 194                               char *fp, int count);
 195static void n_hdlc_tty_wakeup(struct tty_struct *tty);
 196
 197#define bset(p,b)       ((p)[(b) >> 5] |= (1 << ((b) & 0x1f)))
 198
 199#define tty2n_hdlc(tty) ((struct n_hdlc *) ((tty)->disc_data))
 200#define n_hdlc2tty(n_hdlc)      ((n_hdlc)->tty)
 201
 202static struct tty_ldisc_ops n_hdlc_ldisc = {
 203        .owner          = THIS_MODULE,
 204        .magic          = TTY_LDISC_MAGIC,
 205        .name           = "hdlc",
 206        .open           = n_hdlc_tty_open,
 207        .close          = n_hdlc_tty_close,
 208        .read           = n_hdlc_tty_read,
 209        .write          = n_hdlc_tty_write,
 210        .ioctl          = n_hdlc_tty_ioctl,
 211        .poll           = n_hdlc_tty_poll,
 212        .receive_buf    = n_hdlc_tty_receive,
 213        .write_wakeup   = n_hdlc_tty_wakeup,
 214};
 215
 216/**
 217 * n_hdlc_release - release an n_hdlc per device line discipline info structure
 218 * @n_hdlc - per device line discipline info structure
 219 */
 220static void n_hdlc_release(struct n_hdlc *n_hdlc)
 221{
 222        struct tty_struct *tty = n_hdlc2tty (n_hdlc);
 223        struct n_hdlc_buf *buf;
 224        
 225        if (debuglevel >= DEBUG_LEVEL_INFO)     
 226                printk("%s(%d)n_hdlc_release() called\n",__FILE__,__LINE__);
 227                
 228        /* Ensure that the n_hdlcd process is not hanging on select()/poll() */
 229        wake_up_interruptible (&tty->read_wait);
 230        wake_up_interruptible (&tty->write_wait);
 231
 232        if (tty->disc_data == n_hdlc)
 233                tty->disc_data = NULL;  /* Break the tty->n_hdlc link */
 234
 235        /* Release transmit and receive buffers */
 236        for(;;) {
 237                buf = n_hdlc_buf_get(&n_hdlc->rx_free_buf_list);
 238                if (buf) {
 239                        kfree(buf);
 240                } else
 241                        break;
 242        }
 243        for(;;) {
 244                buf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list);
 245                if (buf) {
 246                        kfree(buf);
 247                } else
 248                        break;
 249        }
 250        for(;;) {
 251                buf = n_hdlc_buf_get(&n_hdlc->rx_buf_list);
 252                if (buf) {
 253                        kfree(buf);
 254                } else
 255                        break;
 256        }
 257        for(;;) {
 258                buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);
 259                if (buf) {
 260                        kfree(buf);
 261                } else
 262                        break;
 263        }
 264        kfree(n_hdlc->tbuf);
 265        kfree(n_hdlc);
 266        
 267}       /* end of n_hdlc_release() */
 268
 269/**
 270 * n_hdlc_tty_close - line discipline close
 271 * @tty - pointer to tty info structure
 272 *
 273 * Called when the line discipline is changed to something
 274 * else, the tty is closed, or the tty detects a hangup.
 275 */
 276static void n_hdlc_tty_close(struct tty_struct *tty)
 277{
 278        struct n_hdlc *n_hdlc = tty2n_hdlc (tty);
 279
 280        if (debuglevel >= DEBUG_LEVEL_INFO)     
 281                printk("%s(%d)n_hdlc_tty_close() called\n",__FILE__,__LINE__);
 282                
 283        if (n_hdlc != NULL) {
 284                if (n_hdlc->magic != HDLC_MAGIC) {
 285                        printk (KERN_WARNING"n_hdlc: trying to close unopened tty!\n");
 286                        return;
 287                }
 288#if defined(TTY_NO_WRITE_SPLIT)
 289                clear_bit(TTY_NO_WRITE_SPLIT,&tty->flags);
 290#endif
 291                tty->disc_data = NULL;
 292                if (tty == n_hdlc->backup_tty)
 293                        n_hdlc->backup_tty = NULL;
 294                if (tty != n_hdlc->tty)
 295                        return;
 296                if (n_hdlc->backup_tty) {
 297                        n_hdlc->tty = n_hdlc->backup_tty;
 298                } else {
 299                        n_hdlc_release (n_hdlc);
 300                }
 301        }
 302        
 303        if (debuglevel >= DEBUG_LEVEL_INFO)     
 304                printk("%s(%d)n_hdlc_tty_close() success\n",__FILE__,__LINE__);
 305                
 306}       /* end of n_hdlc_tty_close() */
 307
 308/**
 309 * n_hdlc_tty_open - called when line discipline changed to n_hdlc
 310 * @tty - pointer to tty info structure
 311 *
 312 * Returns 0 if success, otherwise error code
 313 */
 314static int n_hdlc_tty_open (struct tty_struct *tty)
 315{
 316        struct n_hdlc *n_hdlc = tty2n_hdlc (tty);
 317
 318        if (debuglevel >= DEBUG_LEVEL_INFO)     
 319                printk("%s(%d)n_hdlc_tty_open() called (device=%s)\n",
 320                __FILE__,__LINE__,
 321                tty->name);
 322                
 323        /* There should not be an existing table for this slot. */
 324        if (n_hdlc) {
 325                printk (KERN_ERR"n_hdlc_tty_open:tty already associated!\n" );
 326                return -EEXIST;
 327        }
 328        
 329        n_hdlc = n_hdlc_alloc();
 330        if (!n_hdlc) {
 331                printk (KERN_ERR "n_hdlc_alloc failed\n");
 332                return -ENFILE;
 333        }
 334                
 335        tty->disc_data = n_hdlc;
 336        n_hdlc->tty    = tty;
 337        tty->receive_room = 65536;
 338        
 339#if defined(TTY_NO_WRITE_SPLIT)
 340        /* change tty_io write() to not split large writes into 8K chunks */
 341        set_bit(TTY_NO_WRITE_SPLIT,&tty->flags);
 342#endif
 343        
 344        /* Flush any pending characters in the driver and discipline. */
 345        if (tty->ldisc.ops->flush_buffer)
 346                tty->ldisc.ops->flush_buffer(tty);
 347
 348        tty_driver_flush_buffer(tty);
 349                
 350        if (debuglevel >= DEBUG_LEVEL_INFO)     
 351                printk("%s(%d)n_hdlc_tty_open() success\n",__FILE__,__LINE__);
 352                
 353        return 0;
 354        
 355}       /* end of n_tty_hdlc_open() */
 356
 357/**
 358 * n_hdlc_send_frames - send frames on pending send buffer list
 359 * @n_hdlc - pointer to ldisc instance data
 360 * @tty - pointer to tty instance data
 361 *
 362 * Send frames on pending send buffer list until the driver does not accept a
 363 * frame (busy) this function is called after adding a frame to the send buffer
 364 * list and by the tty wakeup callback.
 365 */
 366static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)
 367{
 368        register int actual;
 369        unsigned long flags;
 370        struct n_hdlc_buf *tbuf;
 371
 372        if (debuglevel >= DEBUG_LEVEL_INFO)     
 373                printk("%s(%d)n_hdlc_send_frames() called\n",__FILE__,__LINE__);
 374 check_again:
 375                
 376        spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags);
 377        if (n_hdlc->tbusy) {
 378                n_hdlc->woke_up = 1;
 379                spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);
 380                return;
 381        }
 382        n_hdlc->tbusy = 1;
 383        n_hdlc->woke_up = 0;
 384        spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);
 385
 386        /* get current transmit buffer or get new transmit */
 387        /* buffer from list of pending transmit buffers */
 388                
 389        tbuf = n_hdlc->tbuf;
 390        if (!tbuf)
 391                tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);
 392                
 393        while (tbuf) {
 394                if (debuglevel >= DEBUG_LEVEL_INFO)     
 395                        printk("%s(%d)sending frame %p, count=%d\n",
 396                                __FILE__,__LINE__,tbuf,tbuf->count);
 397                        
 398                /* Send the next block of data to device */
 399                tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
 400                actual = tty->ops->write(tty, tbuf->buf, tbuf->count);
 401
 402                /* rollback was possible and has been done */
 403                if (actual == -ERESTARTSYS) {
 404                        n_hdlc->tbuf = tbuf;
 405                        break;
 406                }
 407                /* if transmit error, throw frame away by */
 408                /* pretending it was accepted by driver */
 409                if (actual < 0)
 410                        actual = tbuf->count;
 411                
 412                if (actual == tbuf->count) {
 413                        if (debuglevel >= DEBUG_LEVEL_INFO)     
 414                                printk("%s(%d)frame %p completed\n",
 415                                        __FILE__,__LINE__,tbuf);
 416                                        
 417                        /* free current transmit buffer */
 418                        n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, tbuf);
 419                        
 420                        /* this tx buffer is done */
 421                        n_hdlc->tbuf = NULL;
 422                        
 423                        /* wait up sleeping writers */
 424                        wake_up_interruptible(&tty->write_wait);
 425        
 426                        /* get next pending transmit buffer */
 427                        tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);
 428                } else {
 429                        if (debuglevel >= DEBUG_LEVEL_INFO)     
 430                                printk("%s(%d)frame %p pending\n",
 431                                        __FILE__,__LINE__,tbuf);
 432                                        
 433                        /* buffer not accepted by driver */
 434                        /* set this buffer as pending buffer */
 435                        n_hdlc->tbuf = tbuf;
 436                        break;
 437                }
 438        }
 439        
 440        if (!tbuf)
 441                tty->flags  &= ~(1 << TTY_DO_WRITE_WAKEUP);
 442        
 443        /* Clear the re-entry flag */
 444        spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags);
 445        n_hdlc->tbusy = 0;
 446        spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); 
 447        
 448        if (n_hdlc->woke_up)
 449          goto check_again;
 450
 451        if (debuglevel >= DEBUG_LEVEL_INFO)     
 452                printk("%s(%d)n_hdlc_send_frames() exit\n",__FILE__,__LINE__);
 453                
 454}       /* end of n_hdlc_send_frames() */
 455
 456/**
 457 * n_hdlc_tty_wakeup - Callback for transmit wakeup
 458 * @tty - pointer to associated tty instance data
 459 *
 460 * Called when low level device driver can accept more send data.
 461 */
 462static void n_hdlc_tty_wakeup(struct tty_struct *tty)
 463{
 464        struct n_hdlc *n_hdlc = tty2n_hdlc(tty);
 465
 466        if (debuglevel >= DEBUG_LEVEL_INFO)     
 467                printk("%s(%d)n_hdlc_tty_wakeup() called\n",__FILE__,__LINE__);
 468                
 469        if (!n_hdlc)
 470                return;
 471
 472        if (tty != n_hdlc->tty) {
 473                tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 474                return;
 475        }
 476
 477        n_hdlc_send_frames (n_hdlc, tty);
 478                
 479}       /* end of n_hdlc_tty_wakeup() */
 480
 481/**
 482 * n_hdlc_tty_receive - Called by tty driver when receive data is available
 483 * @tty - pointer to tty instance data
 484 * @data - pointer to received data
 485 * @flags - pointer to flags for data
 486 * @count - count of received data in bytes
 487 *
 488 * Called by tty low level driver when receive data is available. Data is
 489 * interpreted as one HDLC frame.
 490 */
 491static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,
 492                               char *flags, int count)
 493{
 494        register struct n_hdlc *n_hdlc = tty2n_hdlc (tty);
 495        register struct n_hdlc_buf *buf;
 496
 497        if (debuglevel >= DEBUG_LEVEL_INFO)     
 498                printk("%s(%d)n_hdlc_tty_receive() called count=%d\n",
 499                        __FILE__,__LINE__, count);
 500                
 501        /* This can happen if stuff comes in on the backup tty */
 502        if (!n_hdlc || tty != n_hdlc->tty)
 503                return;
 504                
 505        /* verify line is using HDLC discipline */
 506        if (n_hdlc->magic != HDLC_MAGIC) {
 507                printk("%s(%d) line not using HDLC discipline\n",
 508                        __FILE__,__LINE__);
 509                return;
 510        }
 511        
 512        if ( count>maxframe ) {
 513                if (debuglevel >= DEBUG_LEVEL_INFO)     
 514                        printk("%s(%d) rx count>maxframesize, data discarded\n",
 515                               __FILE__,__LINE__);
 516                return;
 517        }
 518
 519        /* get a free HDLC buffer */    
 520        buf = n_hdlc_buf_get(&n_hdlc->rx_free_buf_list);
 521        if (!buf) {
 522                /* no buffers in free list, attempt to allocate another rx buffer */
 523                /* unless the maximum count has been reached */
 524                if (n_hdlc->rx_buf_list.count < MAX_RX_BUF_COUNT)
 525                        buf = kmalloc(N_HDLC_BUF_SIZE, GFP_ATOMIC);
 526        }
 527        
 528        if (!buf) {
 529                if (debuglevel >= DEBUG_LEVEL_INFO)     
 530                        printk("%s(%d) no more rx buffers, data discarded\n",
 531                               __FILE__,__LINE__);
 532                return;
 533        }
 534                
 535        /* copy received data to HDLC buffer */
 536        memcpy(buf->buf,data,count);
 537        buf->count=count;
 538
 539        /* add HDLC buffer to list of received frames */
 540        n_hdlc_buf_put(&n_hdlc->rx_buf_list, buf);
 541        
 542        /* wake up any blocked reads and perform async signalling */
 543        wake_up_interruptible (&tty->read_wait);
 544        if (n_hdlc->tty->fasync != NULL)
 545                kill_fasync (&n_hdlc->tty->fasync, SIGIO, POLL_IN);
 546
 547}       /* end of n_hdlc_tty_receive() */
 548
 549/**
 550 * n_hdlc_tty_read - Called to retrieve one frame of data (if available)
 551 * @tty - pointer to tty instance data
 552 * @file - pointer to open file object
 553 * @buf - pointer to returned data buffer
 554 * @nr - size of returned data buffer
 555 *      
 556 * Returns the number of bytes returned or error code.
 557 */
 558static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
 559                           __u8 __user *buf, size_t nr)
 560{
 561        struct n_hdlc *n_hdlc = tty2n_hdlc(tty);
 562        int ret;
 563        struct n_hdlc_buf *rbuf;
 564
 565        if (debuglevel >= DEBUG_LEVEL_INFO)     
 566                printk("%s(%d)n_hdlc_tty_read() called\n",__FILE__,__LINE__);
 567                
 568        /* Validate the pointers */
 569        if (!n_hdlc)
 570                return -EIO;
 571
 572        /* verify user access to buffer */
 573        if (!access_ok(VERIFY_WRITE, buf, nr)) {
 574                printk(KERN_WARNING "%s(%d) n_hdlc_tty_read() can't verify user "
 575                "buffer\n", __FILE__, __LINE__);
 576                return -EFAULT;
 577        }
 578
 579        lock_kernel();
 580
 581        for (;;) {
 582                if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
 583                        unlock_kernel();
 584                        return -EIO;
 585                }
 586
 587                n_hdlc = tty2n_hdlc (tty);
 588                if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC ||
 589                         tty != n_hdlc->tty) {
 590                        unlock_kernel();
 591                        return 0;
 592                }
 593
 594                rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list);
 595                if (rbuf)
 596                        break;
 597                        
 598                /* no data */
 599                if (file->f_flags & O_NONBLOCK) {
 600                        unlock_kernel();
 601                        return -EAGAIN;
 602                }
 603                        
 604                interruptible_sleep_on (&tty->read_wait);
 605                if (signal_pending(current)) {
 606                        unlock_kernel();
 607                        return -EINTR;
 608                }
 609        }
 610                
 611        if (rbuf->count > nr)
 612                /* frame too large for caller's buffer (discard frame) */
 613                ret = -EOVERFLOW;
 614        else {
 615                /* Copy the data to the caller's buffer */
 616                if (copy_to_user(buf, rbuf->buf, rbuf->count))
 617                        ret = -EFAULT;
 618                else
 619                        ret = rbuf->count;
 620        }
 621        
 622        /* return HDLC buffer to free list unless the free list */
 623        /* count has exceeded the default value, in which case the */
 624        /* buffer is freed back to the OS to conserve memory */
 625        if (n_hdlc->rx_free_buf_list.count > DEFAULT_RX_BUF_COUNT)
 626                kfree(rbuf);
 627        else    
 628                n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf);
 629        unlock_kernel();
 630        return ret;
 631        
 632}       /* end of n_hdlc_tty_read() */
 633
 634/**
 635 * n_hdlc_tty_write - write a single frame of data to device
 636 * @tty - pointer to associated tty device instance data
 637 * @file - pointer to file object data
 638 * @data - pointer to transmit data (one frame)
 639 * @count - size of transmit frame in bytes
 640 *              
 641 * Returns the number of bytes written (or error code).
 642 */
 643static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
 644                            const unsigned char *data, size_t count)
 645{
 646        struct n_hdlc *n_hdlc = tty2n_hdlc (tty);
 647        int error = 0;
 648        DECLARE_WAITQUEUE(wait, current);
 649        struct n_hdlc_buf *tbuf;
 650
 651        if (debuglevel >= DEBUG_LEVEL_INFO)     
 652                printk("%s(%d)n_hdlc_tty_write() called count=%Zd\n",
 653                        __FILE__,__LINE__,count);
 654                
 655        /* Verify pointers */
 656        if (!n_hdlc)
 657                return -EIO;
 658
 659        if (n_hdlc->magic != HDLC_MAGIC)
 660                return -EIO;
 661
 662        /* verify frame size */
 663        if (count > maxframe ) {
 664                if (debuglevel & DEBUG_LEVEL_INFO)
 665                        printk (KERN_WARNING
 666                                "n_hdlc_tty_write: truncating user packet "
 667                                "from %lu to %d\n", (unsigned long) count,
 668                                maxframe );
 669                count = maxframe;
 670        }
 671        
 672        lock_kernel();
 673
 674        add_wait_queue(&tty->write_wait, &wait);
 675        set_current_state(TASK_INTERRUPTIBLE);
 676        
 677        /* Allocate transmit buffer */
 678        /* sleep until transmit buffer available */             
 679        while (!(tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list))) {
 680                if (file->f_flags & O_NONBLOCK) {
 681                        error = -EAGAIN;
 682                        break;
 683                }
 684                schedule();
 685                        
 686                n_hdlc = tty2n_hdlc (tty);
 687                if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || 
 688                    tty != n_hdlc->tty) {
 689                        printk("n_hdlc_tty_write: %p invalid after wait!\n", n_hdlc);
 690                        error = -EIO;
 691                        break;
 692                }
 693                        
 694                if (signal_pending(current)) {
 695                        error = -EINTR;
 696                        break;
 697                }
 698        }
 699
 700        set_current_state(TASK_RUNNING);
 701        remove_wait_queue(&tty->write_wait, &wait);
 702
 703        if (!error) {           
 704                /* Retrieve the user's buffer */
 705                memcpy(tbuf->buf, data, count);
 706
 707                /* Send the data */
 708                tbuf->count = error = count;
 709                n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf);
 710                n_hdlc_send_frames(n_hdlc,tty);
 711        }
 712        unlock_kernel();
 713        return error;
 714        
 715}       /* end of n_hdlc_tty_write() */
 716
 717/**
 718 * n_hdlc_tty_ioctl - process IOCTL system call for the tty device.
 719 * @tty - pointer to tty instance data
 720 * @file - pointer to open file object for device
 721 * @cmd - IOCTL command code
 722 * @arg - argument for IOCTL call (cmd dependent)
 723 *
 724 * Returns command dependent result.
 725 */
 726static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,
 727                            unsigned int cmd, unsigned long arg)
 728{
 729        struct n_hdlc *n_hdlc = tty2n_hdlc (tty);
 730        int error = 0;
 731        int count;
 732        unsigned long flags;
 733        
 734        if (debuglevel >= DEBUG_LEVEL_INFO)     
 735                printk("%s(%d)n_hdlc_tty_ioctl() called %d\n",
 736                        __FILE__,__LINE__,cmd);
 737                
 738        /* Verify the status of the device */
 739        if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC)
 740                return -EBADF;
 741
 742        switch (cmd) {
 743        case FIONREAD:
 744                /* report count of read data available */
 745                /* in next available frame (if any) */
 746                spin_lock_irqsave(&n_hdlc->rx_buf_list.spinlock,flags);
 747                if (n_hdlc->rx_buf_list.head)
 748                        count = n_hdlc->rx_buf_list.head->count;
 749                else
 750                        count = 0;
 751                spin_unlock_irqrestore(&n_hdlc->rx_buf_list.spinlock,flags);
 752                error = put_user(count, (int __user *)arg);
 753                break;
 754
 755        case TIOCOUTQ:
 756                /* get the pending tx byte count in the driver */
 757                count = tty_chars_in_buffer(tty);
 758                /* add size of next output frame in queue */
 759                spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock,flags);
 760                if (n_hdlc->tx_buf_list.head)
 761                        count += n_hdlc->tx_buf_list.head->count;
 762                spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock,flags);
 763                error = put_user(count, (int __user *)arg);
 764                break;
 765
 766        default:
 767                error = n_tty_ioctl_helper(tty, file, cmd, arg);
 768                break;
 769        }
 770        return error;
 771        
 772}       /* end of n_hdlc_tty_ioctl() */
 773
 774/**
 775 * n_hdlc_tty_poll - TTY callback for poll system call
 776 * @tty - pointer to tty instance data
 777 * @filp - pointer to open file object for device
 778 * @poll_table - wait queue for operations
 779 * 
 780 * Determine which operations (read/write) will not block and return info
 781 * to caller.
 782 * Returns a bit mask containing info on which ops will not block.
 783 */
 784static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,
 785                                    poll_table *wait)
 786{
 787        struct n_hdlc *n_hdlc = tty2n_hdlc (tty);
 788        unsigned int mask = 0;
 789
 790        if (debuglevel >= DEBUG_LEVEL_INFO)     
 791                printk("%s(%d)n_hdlc_tty_poll() called\n",__FILE__,__LINE__);
 792                
 793        if (n_hdlc && n_hdlc->magic == HDLC_MAGIC && tty == n_hdlc->tty) {
 794                /* queue current process into any wait queue that */
 795                /* may awaken in the future (read and write) */
 796
 797                poll_wait(filp, &tty->read_wait, wait);
 798                poll_wait(filp, &tty->write_wait, wait);
 799
 800                /* set bits for operations that won't block */
 801                if (n_hdlc->rx_buf_list.head)
 802                        mask |= POLLIN | POLLRDNORM;    /* readable */
 803                if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
 804                        mask |= POLLHUP;
 805                if (tty_hung_up_p(filp))
 806                        mask |= POLLHUP;
 807                if (!tty_is_writelocked(tty) &&
 808                                n_hdlc->tx_free_buf_list.head)
 809                        mask |= POLLOUT | POLLWRNORM;   /* writable */
 810        }
 811        return mask;
 812}       /* end of n_hdlc_tty_poll() */
 813
 814/**
 815 * n_hdlc_alloc - allocate an n_hdlc instance data structure
 816 *
 817 * Returns a pointer to newly created structure if success, otherwise %NULL
 818 */
 819static struct n_hdlc *n_hdlc_alloc(void)
 820{
 821        struct n_hdlc_buf *buf;
 822        int i;
 823        struct n_hdlc *n_hdlc = kmalloc(sizeof(*n_hdlc), GFP_KERNEL);
 824
 825        if (!n_hdlc)
 826                return NULL;
 827
 828        memset(n_hdlc, 0, sizeof(*n_hdlc));
 829
 830        n_hdlc_buf_list_init(&n_hdlc->rx_free_buf_list);
 831        n_hdlc_buf_list_init(&n_hdlc->tx_free_buf_list);
 832        n_hdlc_buf_list_init(&n_hdlc->rx_buf_list);
 833        n_hdlc_buf_list_init(&n_hdlc->tx_buf_list);
 834        
 835        /* allocate free rx buffer list */
 836        for(i=0;i<DEFAULT_RX_BUF_COUNT;i++) {
 837                buf = kmalloc(N_HDLC_BUF_SIZE, GFP_KERNEL);
 838                if (buf)
 839                        n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,buf);
 840                else if (debuglevel >= DEBUG_LEVEL_INFO)        
 841                        printk("%s(%d)n_hdlc_alloc(), kalloc() failed for rx buffer %d\n",__FILE__,__LINE__, i);
 842        }
 843        
 844        /* allocate free tx buffer list */
 845        for(i=0;i<DEFAULT_TX_BUF_COUNT;i++) {
 846                buf = kmalloc(N_HDLC_BUF_SIZE, GFP_KERNEL);
 847                if (buf)
 848                        n_hdlc_buf_put(&n_hdlc->tx_free_buf_list,buf);
 849                else if (debuglevel >= DEBUG_LEVEL_INFO)        
 850                        printk("%s(%d)n_hdlc_alloc(), kalloc() failed for tx buffer %d\n",__FILE__,__LINE__, i);
 851        }
 852        
 853        /* Initialize the control block */
 854        n_hdlc->magic  = HDLC_MAGIC;
 855        n_hdlc->flags  = 0;
 856        
 857        return n_hdlc;
 858        
 859}       /* end of n_hdlc_alloc() */
 860
 861/**
 862 * n_hdlc_buf_list_init - initialize specified HDLC buffer list
 863 * @list - pointer to buffer list
 864 */
 865static void n_hdlc_buf_list_init(struct n_hdlc_buf_list *list)
 866{
 867        memset(list, 0, sizeof(*list));
 868        spin_lock_init(&list->spinlock);
 869}       /* end of n_hdlc_buf_list_init() */
 870
 871/**
 872 * n_hdlc_buf_put - add specified HDLC buffer to tail of specified list
 873 * @list - pointer to buffer list
 874 * @buf - pointer to buffer
 875 */
 876static void n_hdlc_buf_put(struct n_hdlc_buf_list *list,
 877                           struct n_hdlc_buf *buf)
 878{
 879        unsigned long flags;
 880        spin_lock_irqsave(&list->spinlock,flags);
 881        
 882        buf->link=NULL;
 883        if (list->tail)
 884                list->tail->link = buf;
 885        else
 886                list->head = buf;
 887        list->tail = buf;
 888        (list->count)++;
 889        
 890        spin_unlock_irqrestore(&list->spinlock,flags);
 891        
 892}       /* end of n_hdlc_buf_put() */
 893
 894/**
 895 * n_hdlc_buf_get - remove and return an HDLC buffer from list
 896 * @list - pointer to HDLC buffer list
 897 * 
 898 * Remove and return an HDLC buffer from the head of the specified HDLC buffer
 899 * list.
 900 * Returns a pointer to HDLC buffer if available, otherwise %NULL.
 901 */
 902static struct n_hdlc_buf* n_hdlc_buf_get(struct n_hdlc_buf_list *list)
 903{
 904        unsigned long flags;
 905        struct n_hdlc_buf *buf;
 906        spin_lock_irqsave(&list->spinlock,flags);
 907        
 908        buf = list->head;
 909        if (buf) {
 910                list->head = buf->link;
 911                (list->count)--;
 912        }
 913        if (!list->head)
 914                list->tail = NULL;
 915        
 916        spin_unlock_irqrestore(&list->spinlock,flags);
 917        return buf;
 918        
 919}       /* end of n_hdlc_buf_get() */
 920
 921static char hdlc_banner[] __initdata =
 922        KERN_INFO "HDLC line discipline: version " HDLC_VERSION
 923        ", maxframe=%u\n";
 924static char hdlc_register_ok[] __initdata =
 925        KERN_INFO "N_HDLC line discipline registered.\n";
 926static char hdlc_register_fail[] __initdata =
 927        KERN_ERR "error registering line discipline: %d\n";
 928static char hdlc_init_fail[] __initdata =
 929        KERN_INFO "N_HDLC: init failure %d\n";
 930
 931static int __init n_hdlc_init(void)
 932{
 933        int status;
 934
 935        /* range check maxframe arg */
 936        if (maxframe < 4096)
 937                maxframe = 4096;
 938        else if (maxframe > 65535)
 939                maxframe = 65535;
 940
 941        printk(hdlc_banner, maxframe);
 942
 943        status = tty_register_ldisc(N_HDLC, &n_hdlc_ldisc);
 944        if (!status)
 945                printk(hdlc_register_ok);
 946        else
 947                printk(hdlc_register_fail, status);
 948
 949        if (status)
 950                printk(hdlc_init_fail, status);
 951        return status;
 952        
 953}       /* end of init_module() */
 954
 955static char hdlc_unregister_ok[] __exitdata =
 956        KERN_INFO "N_HDLC: line discipline unregistered\n";
 957static char hdlc_unregister_fail[] __exitdata =
 958        KERN_ERR "N_HDLC: can't unregister line discipline (err = %d)\n";
 959
 960static void __exit n_hdlc_exit(void)
 961{
 962        /* Release tty registration of line discipline */
 963        int status = tty_unregister_ldisc(N_HDLC);
 964
 965        if (status)
 966                printk(hdlc_unregister_fail, status);
 967        else
 968                printk(hdlc_unregister_ok);
 969}
 970
 971module_init(n_hdlc_init);
 972module_exit(n_hdlc_exit);
 973
 974MODULE_LICENSE("GPL");
 975MODULE_AUTHOR("Paul Fulghum paulkf@microgate.com");
 976module_param(debuglevel, int, 0);
 977module_param(maxframe, int, 0);
 978MODULE_ALIAS_LDISC(N_HDLC);
 979
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.