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