1 /* generic HDLC line discipline for Linux
3 * Written by Paul Fulghum paulkf@microgate.com
4 * for Microgate Corporation
6 * Microgate and SyncLink are registered trademarks of Microgate Corporation
8 * Adapted from ppp.c, written by Michael Callahan <callahan@maths.ox.ac.uk>,
9 * Al Longyear <longyear@netcom.com>, Paul Mackerras <Paul.Mackerras@cs.anu.edu.au>
11 * Original release 01/11/99
13 * This code is released under the GNU General Public License (GPL)
15 * This module implements the tty line discipline N_HDLC for use with
16 * tty device drivers that support bit-synchronous HDLC communications.
18 * All HDLC data is frame oriented which means:
20 * 1. tty write calls represent one complete transmit frame of data
21 * The device driver should accept the complete frame or none of
22 * the frame (busy) in the write method. Each write call should have
23 * a byte count in the range of 2-4096 bytes (2 is min HDLC frame
24 * with 1 addr byte and 1 ctrl byte).
26 * 2. receive callbacks from the device driver represents
27 * one received frame. The device driver should bypass
28 * the tty flip buffer and call the line discipline receive
29 * callback directly to avoid fragmenting or concatenating
30 * multiple frames into a single receive callback.
32 * The HDLC line discipline queues the receive frames in seperate
33 * buffers so complete receive frames can be returned by the
36 * 3. tty read calls returns an entire frame of data or nothing.
38 * 4. all send and receive data is considered raw. No processing
39 * or translation is performed by the line discipline, regardless
42 * 5. When line discipline is queried for the amount of receive
43 * data available (FIOC), 0 is returned if no data available,
44 * otherwise the count of the next available frame is returned.
45 * (instead of the sum of all received frame counts).
47 * These conventions allow the standard tty programming interface
48 * to be used for synchronous HDLC applications when used with
49 * this line discipline (or another line discipline that is frame
50 * oriented such as N_PPP).
52 * The SyncLink driver (synclink.c) implements both asynchronous
53 * (using standard line discipline N_TTY) and synchronous HDLC
54 * (using N_HDLC) communications, with the latter using the above
57 * This implementation is very basic and does not maintain
58 * any statistics. The main point is to enforce the raw data
59 * and frame orientation of HDLC communications.
61 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
62 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
63 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
64 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
65 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
66 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
67 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
69 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
70 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
71 * OF THE POSSIBILITY OF SUCH DAMAGE.
74 #define HDLC_MAGIC 0x239e
75 #define HDLC_VERSION "1.0"
77 #include <linux/version.h>
78 #include <linux/config.h>
79 #include <linux/module.h>
80 #include <linux/kernel.h>
81 #include <linux/sched.h>
82 #include <linux/types.h>
83 #include <linux/fcntl.h>
84 #include <linux/interrupt.h>
85 #include <linux/ptrace.h>
88 #define VERSION(major,minor,patch) (((((major)<<8)+(minor))<<8)+(patch))
90 #if LINUX_VERSION_CODE < VERSION(2,1,14)
91 #include <linux/ioport.h>
94 #if LINUX_VERSION_CODE >= VERSION(2,1,23)
95 #include <linux/poll.h>
99 #include <linux/malloc.h>
100 #include <linux/tty.h>
101 #include <linux/errno.h>
102 #include <linux/sched.h> /* to get the struct task_struct */
103 #include <linux/string.h> /* used in new tty drivers */
104 #include <linux/signal.h> /* used in new tty drivers */
105 #include <asm/system.h>
106 #include <asm/bitops.h>
107 #include <asm/termios.h>
108 #include <linux/if.h>
110 #include <linux/ioctl.h>
112 #ifdef CONFIG_KERNELD
113 #include <linux/kerneld.h>
116 #if LINUX_VERSION_CODE >= VERSION(2,1,4)
117 #include <asm/segment.h>
118 #define GET_USER(error,value,addr) error = get_user(value,addr)
119 #define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
120 #define PUT_USER(error,value,addr) error = put_user(value,addr)
121 #define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0
123 #if LINUX_VERSION_CODE >= VERSION(2,1,5)
124 #include <asm/uaccess.h>
127 #else /* 2.0.x and 2.1.x before 2.1.4 */
129 #define GET_USER(error,value,addr) \
131 error = verify_area (VERIFY_READ, (void *) addr, sizeof (value)); \
133 value = get_user(addr); \
136 #define COPY_FROM_USER(error,dest,src,size) \
138 error = verify_area (VERIFY_READ, (void *) src, size); \
140 memcpy_fromfs (dest, src, size); \
143 #define PUT_USER(error,value,addr) \
145 error = verify_area (VERIFY_WRITE, (void *) addr, sizeof (value)); \
147 put_user (value, addr); \
150 #define COPY_TO_USER(error,dest,src,size) \
152 error = verify_area (VERIFY_WRITE, (void *) dest, size); \
154 memcpy_tofs (dest, src, size); \
159 #if LINUX_VERSION_CODE < VERSION(2,1,0)
161 typedef int spinlock_t
;
162 #define spin_lock_irqsave(a,b) {save_flags((b));cli();}
163 #define spin_unlock_irqrestore(a,b) {restore_flags((b));}
165 #define spin_unlock(a)
166 #define schedule_timeout(a){current->timeout = jiffies + (a); schedule();}
169 #if LINUX_VERSION_CODE < VERSION(2,1,37)
170 #define test_and_set_bit(nr, addr) set_bit(nr, addr)
173 #if LINUX_VERSION_CODE < VERSION(2,1,57)
174 #define signal_pending(p) ((p)->signal & ~(p)->blocked)
177 #if LINUX_VERSION_CODE < VERSION(2,1,25)
178 #define net_device_stats enet_statistics
181 #if LINUX_VERSION_CODE < VERSION(2,1,60)
182 typedef int rw_ret_t
;
183 typedef unsigned int rw_count_t
;
185 typedef ssize_t rw_ret_t
;
186 typedef size_t rw_count_t
;
190 * Buffers for individual HDLC frames
192 #define MAX_HDLC_FRAME_SIZE 4096
193 #define DEFAULT_RX_BUF_COUNT 10
194 #define MAX_RX_BUF_COUNT 30
195 #define DEFAULT_TX_BUF_COUNT 1
197 typedef struct _n_hdlc_buf
199 struct _n_hdlc_buf
*link
;
201 char buf
[MAX_HDLC_FRAME_SIZE
];
204 typedef struct _n_hdlc_buf_list
214 * Per device instance data structure
217 int magic
; /* magic value for structure */
218 __u32 flags
; /* miscellaneous control flags */
220 struct tty_struct
*tty
; /* ptr to TTY structure */
221 struct tty_struct
*backup_tty
; /* TTY to use if tty gets closed */
223 /* Queues for select() functionality */
224 struct wait_queue
*read_wait
;
225 struct wait_queue
*write_wait
;
227 int tbusy
; /* reentrancy flag for tx wakeup code */
229 N_HDLC_BUF
*tbuf
; /* currently transmitting tx buffer */
230 N_HDLC_BUF_LIST tx_buf_list
; /* list of pending transmit frame buffers */
231 N_HDLC_BUF_LIST rx_buf_list
; /* list of received frame buffers */
232 N_HDLC_BUF_LIST tx_free_buf_list
; /* list unused transmit frame buffers */
233 N_HDLC_BUF_LIST rx_free_buf_list
; /* list unused received frame buffers */
237 * HDLC buffer list manipulation functions
239 void n_hdlc_buf_list_init(N_HDLC_BUF_LIST
*list
);
240 void n_hdlc_buf_put(N_HDLC_BUF_LIST
*list
,N_HDLC_BUF
*buf
);
241 N_HDLC_BUF
* n_hdlc_buf_get(N_HDLC_BUF_LIST
*list
);
243 /* Local functions */
245 static struct n_hdlc
*n_hdlc_alloc (void);
247 #if LINUX_VERSION_CODE >= VERSION(2,1,19)
248 MODULE_PARM(debuglevel
, "i");
251 /* debug level can be set by insmod for debugging purposes */
252 #define DEBUG_LEVEL_INFO 1
257 static rw_ret_t
n_hdlc_tty_read(struct tty_struct
*,
258 struct file
*, __u8
*, rw_count_t
);
259 static rw_ret_t
n_hdlc_tty_write(struct tty_struct
*,
260 struct file
*, const __u8
*, rw_count_t
);
261 static int n_hdlc_tty_ioctl(struct tty_struct
*,
262 struct file
*, unsigned int, unsigned long);
263 #if LINUX_VERSION_CODE < VERSION(2,1,23)
264 static int n_hdlc_tty_select (struct tty_struct
*tty
, struct inode
*inode
,
265 struct file
*filp
, int sel_type
, select_table
* wait
);
267 static unsigned int n_hdlc_tty_poll (struct tty_struct
*tty
, struct file
*filp
,
270 static int n_hdlc_tty_open (struct tty_struct
*);
271 static void n_hdlc_tty_close (struct tty_struct
*);
272 static int n_hdlc_tty_room (struct tty_struct
*tty
);
273 static void n_hdlc_tty_receive (struct tty_struct
*tty
,
274 const __u8
* cp
, char *fp
, int count
);
275 static void n_hdlc_tty_wakeup (struct tty_struct
*tty
);
277 #define bset(p,b) ((p)[(b) >> 5] |= (1 << ((b) & 0x1f)))
279 #define tty2n_hdlc(tty) ((struct n_hdlc *) ((tty)->disc_data))
280 #define n_hdlc2tty(n_hdlc) ((n_hdlc)->tty)
282 /* Define this string only once for all macro invocations */
283 static char szVersion
[] = HDLC_VERSION
;
287 * release an n_hdlc per device line discipline info structure
290 static void n_hdlc_release (struct n_hdlc
*n_hdlc
)
292 struct tty_struct
*tty
= n_hdlc2tty (n_hdlc
);
295 if (debuglevel
>= DEBUG_LEVEL_INFO
)
296 printk("%s(%d)n_hdlc_release() called\n",__FILE__
,__LINE__
);
298 /* Ensure that the n_hdlcd process is not hanging on select()/poll() */
299 wake_up_interruptible (&n_hdlc
->read_wait
);
300 wake_up_interruptible (&n_hdlc
->write_wait
);
302 if (tty
!= NULL
&& tty
->disc_data
== n_hdlc
)
303 tty
->disc_data
= NULL
; /* Break the tty->n_hdlc link */
305 /* Release transmit and receive buffers */
307 buf
= n_hdlc_buf_get(&n_hdlc
->rx_free_buf_list
);
314 buf
= n_hdlc_buf_get(&n_hdlc
->tx_free_buf_list
);
321 buf
= n_hdlc_buf_get(&n_hdlc
->rx_buf_list
);
328 buf
= n_hdlc_buf_get(&n_hdlc
->tx_buf_list
);
337 } /* end of n_hdlc_release() */
339 /* n_hdlc_tty_close()
341 * Called when the line discipline is changed to something
342 * else, the tty is closed, or the tty detects a hangup.
344 static void n_hdlc_tty_close(struct tty_struct
*tty
)
346 struct n_hdlc
*n_hdlc
= tty2n_hdlc (tty
);
348 if (debuglevel
>= DEBUG_LEVEL_INFO
)
349 printk("%s(%d)n_hdlc_tty_close() called\n",__FILE__
,__LINE__
);
351 if (n_hdlc
!= NULL
) {
352 if (n_hdlc
->magic
!= HDLC_MAGIC
) {
353 printk (KERN_WARNING
"n_hdlc: trying to close unopened tty!\n");
356 tty
->disc_data
= NULL
;
357 if (tty
== n_hdlc
->backup_tty
)
358 n_hdlc
->backup_tty
= 0;
359 if (tty
!= n_hdlc
->tty
)
361 if (n_hdlc
->backup_tty
) {
362 n_hdlc
->tty
= n_hdlc
->backup_tty
;
364 n_hdlc_release (n_hdlc
);
369 if (debuglevel
>= DEBUG_LEVEL_INFO
)
370 printk("%s(%d)n_hdlc_tty_close() success\n",__FILE__
,__LINE__
);
372 } /* end of n_hdlc_tty_close() */
376 * called when line discipline changed to n_hdlc
378 * Arguments: tty pointer to tty info structure
379 * Return Value: 0 if success, otherwise error code
381 static int n_hdlc_tty_open (struct tty_struct
*tty
)
383 struct n_hdlc
*n_hdlc
= tty2n_hdlc (tty
);
385 if (debuglevel
>= DEBUG_LEVEL_INFO
)
386 printk("%s(%d)n_hdlc_tty_open() called\n",__FILE__
,__LINE__
);
388 /* There should not be an existing table for this slot. */
390 printk (KERN_ERR
"n_hdlc_tty_open:tty already associated!\n" );
394 n_hdlc
= n_hdlc_alloc();
396 printk (KERN_ERR
"n_hdlc_alloc failed\n");
400 tty
->disc_data
= n_hdlc
;
405 /* Flush any pending characters in the driver and discipline. */
407 if (tty
->ldisc
.flush_buffer
)
408 tty
->ldisc
.flush_buffer (tty
);
410 if (tty
->driver
.flush_buffer
)
411 tty
->driver
.flush_buffer (tty
);
413 if (debuglevel
>= DEBUG_LEVEL_INFO
)
414 printk("%s(%d)n_hdlc_tty_open() success\n",__FILE__
,__LINE__
);
418 } /* end of n_tty_hdlc_open() */
420 /* n_hdlc_send_frames()
422 * send frames on pending send buffer list until the
423 * driver does not accept a frame (busy)
424 * this function is called after adding a frame to the
425 * send buffer list and by the tty wakeup callback
427 * Arguments: n_hdlc pointer to ldisc instance data
428 * tty pointer to tty instance data
431 static void n_hdlc_send_frames (struct n_hdlc
*n_hdlc
, struct tty_struct
*tty
)
437 if (debuglevel
>= DEBUG_LEVEL_INFO
)
438 printk("%s(%d)n_hdlc_send_frames() called\n",__FILE__
,__LINE__
);
444 restore_flags(flags
);
448 restore_flags(flags
);
450 /* get current transmit buffer or get new transmit */
451 /* buffer from list of pending transmit buffers */
455 tbuf
= n_hdlc_buf_get(&n_hdlc
->tx_buf_list
);
458 if (debuglevel
>= DEBUG_LEVEL_INFO
)
459 printk("%s(%d)sending frame %p, count=%d\n",
460 __FILE__
,__LINE__
,tbuf
,tbuf
->count
);
462 /* Send the next block of data to device */
464 tty
->flags
|= (1 << TTY_DO_WRITE_WAKEUP
);
465 actual
= tty
->driver
.write(tty
, 0, tbuf
->buf
, tbuf
->count
);
467 /* if transmit error, throw frame away by */
468 /* pretending it was accepted by driver */
470 actual
= tbuf
->count
;
472 if (actual
== tbuf
->count
) {
473 if (debuglevel
>= DEBUG_LEVEL_INFO
)
474 printk("%s(%d)frame %p completed\n",
475 __FILE__
,__LINE__
,tbuf
);
477 /* free current transmit buffer */
478 n_hdlc_buf_put(&n_hdlc
->tx_free_buf_list
,tbuf
);
480 /* this tx buffer is done */
483 /* wait up sleeping writers */
484 wake_up_interruptible(&n_hdlc
->write_wait
);
486 /* get next pending transmit buffer */
487 tbuf
= n_hdlc_buf_get(&n_hdlc
->tx_buf_list
);
489 if (debuglevel
>= DEBUG_LEVEL_INFO
)
490 printk("%s(%d)frame %p pending\n",
491 __FILE__
,__LINE__
,tbuf
);
493 /* buffer not accepted by driver */
495 /* check if wake up code called since last write call */
499 /* set this buffer as pending buffer */
506 tty
->flags
&= ~(1 << TTY_DO_WRITE_WAKEUP
);
508 /* Clear the re-entry flag */
512 restore_flags(flags
);
514 if (debuglevel
>= DEBUG_LEVEL_INFO
)
515 printk("%s(%d)n_hdlc_send_frames() exit\n",__FILE__
,__LINE__
);
517 } /* end of n_hdlc_send_frames() */
519 /* n_hdlc_tty_wakeup()
521 * Callback for transmit wakeup. Called when low level
522 * device driver can accept more send data.
524 * Arguments: tty pointer to associated tty instance data
527 static void n_hdlc_tty_wakeup (struct tty_struct
*tty
)
529 struct n_hdlc
*n_hdlc
= tty2n_hdlc (tty
);
531 if (debuglevel
>= DEBUG_LEVEL_INFO
)
532 printk("%s(%d)n_hdlc_tty_wakeup() called\n",__FILE__
,__LINE__
);
537 if (tty
!= n_hdlc
->tty
) {
538 tty
->flags
&= ~(1 << TTY_DO_WRITE_WAKEUP
);
543 tty
->flags
&= ~(1 << TTY_DO_WRITE_WAKEUP
);
545 n_hdlc_send_frames (n_hdlc
, tty
);
547 } /* end of n_hdlc_tty_wakeup() */
551 * Callback function from tty driver. Return the amount of
552 * space left in the receiver's buffer to decide if remote
553 * transmitter is to be throttled.
555 * Arguments: tty pointer to associated tty instance data
556 * Return Value: number of bytes left in receive buffer
558 static int n_hdlc_tty_room (struct tty_struct
*tty
)
560 if (debuglevel
>= DEBUG_LEVEL_INFO
)
561 printk("%s(%d)n_hdlc_tty_room() called\n",__FILE__
,__LINE__
);
562 /* always return a larger number to prevent */
563 /* throttling of remote transmitter. */
565 } /* end of n_hdlc_tty_root() */
567 /* n_hdlc_tty_receive()
569 * Called by tty low level driver when receive data is
570 * available. Data is interpreted as one HDLC frame.
572 * Arguments: tty pointer to tty isntance data
573 * data pointer to received data
574 * flags pointer to flags for data
575 * count count of received data in bytes
579 static void n_hdlc_tty_receive(struct tty_struct
*tty
,
580 const __u8
* data
, char *flags
, int count
)
582 register struct n_hdlc
*n_hdlc
= tty2n_hdlc (tty
);
583 register N_HDLC_BUF
*buf
;
585 if (debuglevel
>= DEBUG_LEVEL_INFO
)
586 printk("%s(%d)n_hdlc_tty_receive() called count=%d\n",
587 __FILE__
,__LINE__
, count
);
589 /* This can happen if stuff comes in on the backup tty */
590 if (n_hdlc
== 0 || tty
!= n_hdlc
->tty
)
593 /* verify line is using HDLC discipline */
594 if (n_hdlc
->magic
!= HDLC_MAGIC
) {
595 printk("%s(%d) line not using HDLC discipline\n",
600 /* get a free HDLC buffer */
601 buf
= n_hdlc_buf_get(&n_hdlc
->rx_free_buf_list
);
603 /* no buffers in free list, attempt to allocate another rx buffer */
604 /* unless the maximum count has been reached */
605 if (n_hdlc
->rx_buf_list
.count
< MAX_RX_BUF_COUNT
)
606 buf
= (N_HDLC_BUF
*)kmalloc(sizeof(N_HDLC_BUF
),GFP_ATOMIC
);
610 printk("%s(%d) no more rx buffers, data discarded\n",
615 /* copy received data to HDLC buffer */
616 memcpy(buf
->buf
,data
,count
);
619 /* add HDLC buffer to list of received frames */
620 n_hdlc_buf_put(&n_hdlc
->rx_buf_list
,buf
);
622 /* wake up any blocked reads and perform async signalling */
623 wake_up_interruptible (&n_hdlc
->read_wait
);
624 if (n_hdlc
->tty
->fasync
!= NULL
)
625 kill_fasync (n_hdlc
->tty
->fasync
, SIGIO
);
627 } /* end of n_hdlc_tty_receive() */
631 * Called to retreive one frame of data (if available)
635 * tty pointer to tty instance data
636 * file pointer to open file object
637 * buf pointer to returned data buffer
638 * nr size of returned data buffer
642 * Number of bytes returned or error code
644 static rw_ret_t
n_hdlc_tty_read (struct tty_struct
*tty
,
645 struct file
*file
, __u8
* buf
, rw_count_t nr
)
647 struct n_hdlc
*n_hdlc
= tty2n_hdlc(tty
);
652 if (debuglevel
>= DEBUG_LEVEL_INFO
)
653 printk("%s(%d)n_hdlc_tty_read() called\n",__FILE__
,__LINE__
);
655 /* Validate the pointers */
659 /* verify user access to buffer */
660 error
= verify_area (VERIFY_WRITE
, buf
, nr
);
662 printk(KERN_WARNING
"%s(%d) n_hdlc_tty_read() can't verify user "
663 "buffer\n",__FILE__
,__LINE__
);
668 n_hdlc
= tty2n_hdlc (tty
);
669 if (!n_hdlc
|| n_hdlc
->magic
!= HDLC_MAGIC
||
673 rbuf
= n_hdlc_buf_get(&n_hdlc
->rx_buf_list
);
678 if (file
->f_flags
& O_NONBLOCK
)
681 /* TODO: no timeout? current->timeout = 0;*/
682 interruptible_sleep_on (&n_hdlc
->read_wait
);
683 if (signal_pending(current
))
687 if (rbuf
->count
> nr
) {
688 /* frame too large for caller's buffer (discard frame) */
689 ret
= (rw_ret_t
)-EOVERFLOW
;
691 /* Copy the data to the caller's buffer */
692 COPY_TO_USER(error
,buf
,rbuf
->buf
,rbuf
->count
);
694 ret
= (rw_ret_t
)error
;
696 ret
= (rw_ret_t
)rbuf
->count
;
699 /* return HDLC buffer to free list unless the free list */
700 /* count has exceeded the default value, in which case the */
701 /* buffer is freed back to the OS to conserve memory */
702 if (n_hdlc
->rx_free_buf_list
.count
> DEFAULT_RX_BUF_COUNT
)
705 n_hdlc_buf_put(&n_hdlc
->rx_free_buf_list
,rbuf
);
709 } /* end of n_hdlc_tty_read() */
711 /* n_hdlc_tty_write()
713 * write a single frame of data to device
715 * Arguments: tty pointer to associated tty device instance data
716 * file pointer to file object data
717 * data pointer to transmit data (one frame)
718 * count size of transmit frame in bytes
720 * Return Value: number of bytes written (or error code)
722 static rw_ret_t
n_hdlc_tty_write (struct tty_struct
*tty
, struct file
*file
,
723 const __u8
* data
, rw_count_t count
)
725 struct n_hdlc
*n_hdlc
= tty2n_hdlc (tty
);
727 struct wait_queue wait
= {current
, NULL
};
730 if (debuglevel
>= DEBUG_LEVEL_INFO
)
731 printk("%s(%d)n_hdlc_tty_write() called count=%d\n",
732 __FILE__
,__LINE__
,count
);
734 /* Verify pointers */
738 if (n_hdlc
->magic
!= HDLC_MAGIC
)
741 /* verify frame size */
742 if (count
> MAX_HDLC_FRAME_SIZE
) {
743 if (debuglevel
& DEBUG_LEVEL_INFO
)
745 "n_hdlc_tty_write: truncating user packet "
746 "from %lu to %d\n", (unsigned long) count
,
747 MAX_HDLC_FRAME_SIZE
);
748 count
= MAX_HDLC_FRAME_SIZE
;
751 /* Allocate transmit buffer */
752 tbuf
= n_hdlc_buf_get(&n_hdlc
->tx_free_buf_list
);
754 /* sleep until transmit buffer available */
755 add_wait_queue(&n_hdlc
->write_wait
, &wait
);
757 /* TODO: no timeout? current->timeout = 0;*/
758 current
->state
= TASK_INTERRUPTIBLE
;
761 n_hdlc
= tty2n_hdlc (tty
);
762 if (!n_hdlc
|| n_hdlc
->magic
!= HDLC_MAGIC
||
763 tty
!= n_hdlc
->tty
) {
764 printk("n_hdlc_tty_write: %p invalid after wait!\n", n_hdlc
);
769 if (signal_pending(current
)) {
774 tbuf
= n_hdlc_buf_get(&n_hdlc
->tx_free_buf_list
);
776 current
->state
= TASK_RUNNING
;
777 remove_wait_queue(&n_hdlc
->write_wait
, &wait
);
781 /* Retrieve the user's buffer */
782 COPY_FROM_USER (error
, tbuf
->buf
, data
, count
);
784 /* return tx buffer to free list */
785 n_hdlc_buf_put(&n_hdlc
->tx_free_buf_list
,tbuf
);
788 tbuf
->count
= error
= count
;
789 n_hdlc_buf_put(&n_hdlc
->tx_buf_list
,tbuf
);
790 n_hdlc_send_frames(n_hdlc
,tty
);
796 } /* end of n_hdlc_tty_write() */
798 /* n_hdlc_tty_ioctl()
800 * Process IOCTL system call for the tty device.
804 * tty pointer to tty instance data
805 * file pointer to open file object for device
806 * cmd IOCTL command code
807 * arg argument for IOCTL call (cmd dependent)
809 * Return Value: Command dependent
811 static int n_hdlc_tty_ioctl (struct tty_struct
*tty
, struct file
* file
,
812 unsigned int cmd
, unsigned long arg
)
814 struct n_hdlc
*n_hdlc
= tty2n_hdlc (tty
);
817 if (debuglevel
>= DEBUG_LEVEL_INFO
)
818 printk("%s(%d)n_hdlc_tty_ioctl() called %d\n",
819 __FILE__
,__LINE__
,cmd
);
821 /* Verify the status of the device */
822 if (!n_hdlc
|| n_hdlc
->magic
!= HDLC_MAGIC
)
828 /* report count of read data available */
829 /* in next available frame (if any) */
832 spin_lock_irqsave(&n_hdlc
->rx_buf_list
.spinlock
,flags
);
833 if (n_hdlc
->rx_buf_list
.head
)
834 count
= n_hdlc
->rx_buf_list
.head
->count
;
837 spin_unlock_irqrestore(&n_hdlc
->rx_buf_list
.spinlock
,flags
);
838 PUT_USER (error
, count
, (int *) arg
);
843 error
= n_tty_ioctl (tty
, file
, cmd
, arg
);
848 } /* end of n_hdlc_tty_ioctl() */
850 #if LINUX_VERSION_CODE < VERSION(2,1,23)
851 /* n_hdlc_tty_select()
853 * Device select method. Determine if operation requires
854 * blocking and if so put appropriate wait queue in select
855 * table and return 0, otherwise return 1.
859 * tty pointer to tty device instance data
860 * inode pointer to inode for device
861 * filp pointer to file object
862 * sel_type identified the select type (read/write/exception)
863 * wait select table for adding wait queue if appropriate
867 * 1 if no need to block on operation
868 * 0 if must block and wait queue added to select table
870 static int n_hdlc_tty_select (struct tty_struct
*tty
, struct inode
*inode
,
871 struct file
*filp
, int sel_type
, select_table
* wait
)
873 struct n_hdlc
*n_hdlc
= tty2n_hdlc(tty
);
876 if (debuglevel
>= DEBUG_LEVEL_INFO
)
877 printk("%s(%d)n_hdlc_tty_select() called\n",__FILE__
,__LINE__
);
879 /* Verify the status of the device */
883 if (n_hdlc
->magic
!= HDLC_MAGIC
|| tty
!= n_hdlc
->tty
)
888 if (n_hdlc
->rx_buf_list
.head
)
891 case SEL_EX
: /* Exceptions or read errors */
892 /* Is this a pty link and the remote disconnected? */
893 if (tty
->flags
& (1 << TTY_OTHER_CLOSED
))
896 /* Is this a local link and the modem disconnected? */
897 if (tty_hung_up_p (filp
))
900 select_wait (&n_hdlc
->read_wait
, wait
);
904 /* Write mode. A write is allowed if there is no current transmission */
906 if (!n_hdlc
->tx_free_buf_list
.head
) {
907 select_wait (&n_hdlc
->write_wait
, wait
);
913 } /* end of n_hdlc_tty_select() */
915 #else /* 2.1.23 or later */
919 * TTY callback for poll system call. Determine which
920 * operations (read/write) will not block and return
925 * tty pointer to tty instance data
926 * filp pointer to open file object for device
927 * poll_table wait queue for operations
931 * bit mask containing info on which ops will not block
933 static unsigned int n_hdlc_tty_poll (struct tty_struct
*tty
,
934 struct file
*filp
, poll_table
* wait
)
936 struct n_hdlc
*n_hdlc
= tty2n_hdlc (tty
);
937 unsigned int mask
= 0;
939 if (debuglevel
>= DEBUG_LEVEL_INFO
)
940 printk("%s(%d)n_hdlc_tty_poll() called\n",__FILE__
,__LINE__
);
942 if (n_hdlc
&& n_hdlc
->magic
== HDLC_MAGIC
&& tty
== n_hdlc
->tty
) {
943 /* queue current process into any wait queue that */
944 /* may awaken in the future (read and write) */
945 #if LINUX_VERSION_CODE < VERSION(2,1,89)
946 poll_wait(&n_hdlc
->read_wait
, wait
);
947 poll_wait(&n_hdlc
->write_wait
, wait
);
949 poll_wait(filp
, &n_hdlc
->read_wait
, wait
);
950 poll_wait(filp
, &n_hdlc
->write_wait
, wait
);
952 /* set bits for operations that wont block */
953 if(n_hdlc
->rx_buf_list
.head
)
954 mask
|= POLLIN
| POLLRDNORM
; /* readable */
955 if(tty
->flags
& (1 << TTY_OTHER_CLOSED
))
957 if(tty_hung_up_p(filp
))
959 if(n_hdlc
->tx_free_buf_list
.head
)
960 mask
|= POLLOUT
| POLLWRNORM
; /* writable */
963 } /* end of n_hdlc_tty_poll() */
969 * Allocate an n_hdlc instance data structure
972 * Return Value: pointer to structure if success, otherwise 0
974 static struct n_hdlc
*n_hdlc_alloc (void)
976 struct n_hdlc
*n_hdlc
;
980 n_hdlc
= (struct n_hdlc
*)kmalloc(sizeof(struct n_hdlc
), GFP_KERNEL
);
984 memset(n_hdlc
, 0, sizeof(*n_hdlc
));
986 n_hdlc_buf_list_init(&n_hdlc
->rx_free_buf_list
);
987 n_hdlc_buf_list_init(&n_hdlc
->tx_free_buf_list
);
988 n_hdlc_buf_list_init(&n_hdlc
->rx_buf_list
);
989 n_hdlc_buf_list_init(&n_hdlc
->tx_buf_list
);
991 /* allocate free rx buffer list */
992 for(i
=0;i
<DEFAULT_RX_BUF_COUNT
;i
++) {
993 buf
= (N_HDLC_BUF
*)kmalloc(sizeof(N_HDLC_BUF
),GFP_KERNEL
);
995 n_hdlc_buf_put(&n_hdlc
->rx_free_buf_list
,buf
);
998 /* allocate free rx buffer list */
999 for(i
=0;i
<DEFAULT_TX_BUF_COUNT
;i
++) {
1000 buf
= (N_HDLC_BUF
*)kmalloc(sizeof(N_HDLC_BUF
),GFP_KERNEL
);
1002 n_hdlc_buf_put(&n_hdlc
->tx_free_buf_list
,buf
);
1005 /* Initialize the control block */
1006 n_hdlc
->magic
= HDLC_MAGIC
;
1009 n_hdlc
->read_wait
= NULL
;
1010 n_hdlc
->write_wait
= NULL
;
1014 } /* end of n_hdlc_alloc() */
1016 /* n_hdlc_buf_list_init()
1018 * initialize specified HDLC buffer list
1020 * Arguments: list pointer to buffer list
1021 * Return Value: None
1023 void n_hdlc_buf_list_init(N_HDLC_BUF_LIST
*list
)
1025 memset(list
,0,sizeof(N_HDLC_BUF_LIST
));
1027 } /* end of n_hdlc_buf_list_init() */
1031 * add specified HDLC buffer to tail of specified list
1035 * list pointer to buffer list
1036 * buf pointer to buffer
1038 * Return Value: None
1040 void n_hdlc_buf_put(N_HDLC_BUF_LIST
*list
,N_HDLC_BUF
*buf
)
1042 unsigned long flags
;
1043 spin_lock_irqsave(&list
->spinlock
,flags
);
1047 list
->tail
->link
= buf
;
1053 spin_unlock_irqrestore(&list
->spinlock
,flags
);
1055 } /* end of n_hdlc_buf_put() */
1059 * remove and return an HDLC buffer from the
1060 * head of the specified HDLC buffer list
1064 * list pointer to HDLC buffer list
1068 * pointer to HDLC buffer if available, otherwise NULL
1070 N_HDLC_BUF
* n_hdlc_buf_get(N_HDLC_BUF_LIST
*list
)
1072 unsigned long flags
;
1074 spin_lock_irqsave(&list
->spinlock
,flags
);
1078 list
->head
= buf
->link
;
1084 spin_unlock_irqrestore(&list
->spinlock
,flags
);
1087 } /* end of n_hdlc_buf_get() */
1091 * called when module is loading to register line discipline
1094 * Return Value: 0 if success, otherwise error code
1096 int init_module(void)
1098 static struct tty_ldisc n_hdlc_ldisc
;
1101 printk("HDLC line discipline: version %s\n", szVersion
);
1103 /* Register the tty discipline */
1105 memset(&n_hdlc_ldisc
, 0, sizeof (n_hdlc_ldisc
));
1106 n_hdlc_ldisc
.magic
= TTY_LDISC_MAGIC
;
1107 #if LINUX_VERSION_CODE >= VERSION(2,1,28)
1108 n_hdlc_ldisc
.name
= "hdlc";
1110 n_hdlc_ldisc
.open
= n_hdlc_tty_open
;
1111 n_hdlc_ldisc
.close
= n_hdlc_tty_close
;
1112 n_hdlc_ldisc
.read
= n_hdlc_tty_read
;
1113 n_hdlc_ldisc
.write
= n_hdlc_tty_write
;
1114 n_hdlc_ldisc
.ioctl
= n_hdlc_tty_ioctl
;
1115 #if LINUX_VERSION_CODE < VERSION(2,1,23)
1116 n_hdlc_ldisc
.select
= n_hdlc_tty_select
;
1118 n_hdlc_ldisc
.poll
= n_hdlc_tty_poll
;
1120 n_hdlc_ldisc
.receive_room
= n_hdlc_tty_room
;
1121 n_hdlc_ldisc
.receive_buf
= n_hdlc_tty_receive
;
1122 n_hdlc_ldisc
.write_wakeup
= n_hdlc_tty_wakeup
;
1124 status
= tty_register_ldisc(N_HDLC
, &n_hdlc_ldisc
);
1126 printk (KERN_INFO
"N_HDLC line discipline registered.\n");
1128 printk (KERN_ERR
"error registering line discipline: %d\n",status
);
1131 printk(KERN_INFO
"N_HDLC: init failure %d\n", status
);
1134 } /* end of init_module() */
1138 * called when module is unloading to unregister line discipline
1141 * Return Value: None
1143 void cleanup_module(void)
1146 /* Release tty registration of line discipline */
1147 if ((status
= tty_register_ldisc(N_HDLC
, NULL
)))
1148 printk("N_HDLC: can't unregister line discipline (err = %d)\n", status
);
1150 printk("N_HDLC: line discipline unregistered\n");