vserver 2.0 rc7
[linux-2.6.git] / drivers / s390 / net / ctctty.c
1 /*
2  * $Id: ctctty.c,v 1.29 2005/04/05 08:50:44 mschwide Exp $
3  *
4  * CTC / ESCON network driver, tty interface.
5  *
6  * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
7  * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2, or (at your option)
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  */
24
25 #include <linux/config.h>
26 #include <linux/module.h>
27 #include <linux/tty.h>
28 #include <linux/serial_reg.h>
29 #include <linux/interrupt.h>
30 #include <linux/delay.h>
31 #include <asm/uaccess.h>
32 #include <linux/devfs_fs_kernel.h>
33 #include "ctctty.h"
34 #include "ctcdbug.h"
35
36 #define CTC_TTY_MAJOR       43
37 #define CTC_TTY_MAX_DEVICES 64
38
39 #define CTC_ASYNC_MAGIC          0x49344C01 /* for paranoia-checking        */
40 #define CTC_ASYNC_INITIALIZED    0x80000000 /* port was initialized         */
41 #define CTC_ASYNC_NORMAL_ACTIVE  0x20000000 /* Normal device active         */
42 #define CTC_ASYNC_CLOSING        0x08000000 /* Serial port is closing       */
43 #define CTC_ASYNC_CTS_FLOW       0x04000000 /* Do CTS flow control          */
44 #define CTC_ASYNC_CHECK_CD       0x02000000 /* i.e., CLOCAL                 */
45 #define CTC_ASYNC_HUP_NOTIFY         0x0001 /* Notify tty on hangups/closes */
46 #define CTC_ASYNC_NETDEV_OPEN        0x0002 /* Underlying netdev is open    */
47 #define CTC_ASYNC_TX_LINESTAT        0x0004 /* Must send line status        */
48 #define CTC_ASYNC_SPLIT_TERMIOS      0x0008 /* Sep. termios for dialin/out  */
49 #define CTC_TTY_XMIT_SIZE              1024 /* Default bufsize for write    */
50 #define CTC_SERIAL_XMIT_MAX            4000 /* Maximum bufsize for write    */
51
52 /* Private data (similar to async_struct in <linux/serial.h>) */
53 typedef struct {
54   int                   magic;
55   int                   flags;           /* defined in tty.h               */
56   int                   mcr;             /* Modem control register         */
57   int                   msr;             /* Modem status register          */
58   int                   lsr;             /* Line status register           */
59   int                   line;
60   int                   count;           /* # of fd on device              */
61   int                   blocked_open;    /* # of blocked opens             */
62   struct net_device     *netdev;
63   struct sk_buff_head   tx_queue;        /* transmit queue                 */
64   struct sk_buff_head   rx_queue;        /* receive queue                  */
65   struct tty_struct     *tty;            /* Pointer to corresponding tty   */
66   wait_queue_head_t     open_wait;
67   wait_queue_head_t     close_wait;
68   struct semaphore      write_sem;
69   struct tasklet_struct tasklet;
70   struct timer_list     stoptimer;
71 } ctc_tty_info;
72
73 /* Description of one CTC-tty */
74 typedef struct {
75   struct tty_driver  *ctc_tty_device;              /* tty-device             */
76   ctc_tty_info       info[CTC_TTY_MAX_DEVICES];    /* Private data           */
77 } ctc_tty_driver;
78
79 static ctc_tty_driver *driver;
80
81 /* Leave this unchanged unless you know what you do! */
82 #define MODEM_PARANOIA_CHECK
83 #define MODEM_DO_RESTART
84
85 #define CTC_TTY_NAME "ctctty"
86
87 static __u32 ctc_tty_magic = CTC_ASYNC_MAGIC;
88 static int ctc_tty_shuttingdown = 0;
89
90 static spinlock_t ctc_tty_lock;
91
92 /* ctc_tty_try_read() is called from within ctc_tty_rcv_skb()
93  * to stuff incoming data directly into a tty's flip-buffer. If the
94  * flip buffer is full, the packet gets queued up.
95  *
96  * Return:
97  *  1 = Success
98  *  0 = Failure, data has to be buffered and later processed by
99  *      ctc_tty_readmodem().
100  */
101 static int
102 ctc_tty_try_read(ctc_tty_info * info, struct sk_buff *skb)
103 {
104         int c;
105         int len;
106         struct tty_struct *tty;
107
108         DBF_TEXT(trace, 5, __FUNCTION__);
109         if ((tty = info->tty)) {
110                 if (info->mcr & UART_MCR_RTS) {
111                         c = TTY_FLIPBUF_SIZE - tty->flip.count;
112                         len = skb->len;
113                         if (c >= len) {
114                                 memcpy(tty->flip.char_buf_ptr, skb->data, len);
115                                 memset(tty->flip.flag_buf_ptr, 0, len);
116                                 tty->flip.count += len;
117                                 tty->flip.char_buf_ptr += len;
118                                 tty->flip.flag_buf_ptr += len;
119                                 tty_flip_buffer_push(tty);
120                                 kfree_skb(skb);
121                                 return 1;
122                         }
123                 }
124         }
125         return 0;
126 }
127
128 /* ctc_tty_readmodem() is called periodically from within timer-interrupt.
129  * It tries getting received data from the receive queue an stuff it into
130  * the tty's flip-buffer.
131  */
132 static int
133 ctc_tty_readmodem(ctc_tty_info *info)
134 {
135         int ret = 1;
136         struct tty_struct *tty;
137
138         DBF_TEXT(trace, 5, __FUNCTION__);
139         if ((tty = info->tty)) {
140                 if (info->mcr & UART_MCR_RTS) {
141                         int c = TTY_FLIPBUF_SIZE - tty->flip.count;
142                         struct sk_buff *skb;
143                         
144                         if ((c > 0) && (skb = skb_dequeue(&info->rx_queue))) {
145                                 int len = skb->len;
146                                 if (len > c)
147                                         len = c;
148                                 memcpy(tty->flip.char_buf_ptr, skb->data, len);
149                                 skb_pull(skb, len);
150                                 memset(tty->flip.flag_buf_ptr, 0, len);
151                                 tty->flip.count += len;
152                                 tty->flip.char_buf_ptr += len;
153                                 tty->flip.flag_buf_ptr += len;
154                                 tty_flip_buffer_push(tty);
155                                 if (skb->len > 0)
156                                         skb_queue_head(&info->rx_queue, skb);
157                                 else {
158                                         kfree_skb(skb);
159                                         ret = skb_queue_len(&info->rx_queue);
160                                 }
161                         }
162                 }
163         }
164         return ret;
165 }
166
167 void
168 ctc_tty_setcarrier(struct net_device *netdev, int on)
169 {
170         int i;
171
172         DBF_TEXT(trace, 4, __FUNCTION__);
173         if ((!driver) || ctc_tty_shuttingdown)
174                 return;
175         for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
176                 if (driver->info[i].netdev == netdev) {
177                         ctc_tty_info *info = &driver->info[i];
178                         if (on)
179                                 info->msr |= UART_MSR_DCD;
180                         else
181                                 info->msr &= ~UART_MSR_DCD;
182                         if ((info->flags & CTC_ASYNC_CHECK_CD) && (!on))
183                                 tty_hangup(info->tty);
184                 }
185 }
186
187 void
188 ctc_tty_netif_rx(struct sk_buff *skb)
189 {
190         int i;
191         ctc_tty_info *info = NULL;
192
193         DBF_TEXT(trace, 5, __FUNCTION__);
194         if (!skb)
195                 return;
196         if ((!skb->dev) || (!driver) || ctc_tty_shuttingdown) {
197                 dev_kfree_skb(skb);
198                 return;
199         }
200         for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
201                 if (driver->info[i].netdev == skb->dev) {
202                         info = &driver->info[i];
203                         break;
204                 }
205         if (!info) {
206                 dev_kfree_skb(skb);
207                 return;
208         }
209         if (skb->len < 6) {
210                 dev_kfree_skb(skb);
211                 return;
212         }
213         if (memcmp(skb->data, &ctc_tty_magic, sizeof(__u32))) {
214                 dev_kfree_skb(skb);
215                 return;
216         }
217         skb_pull(skb, sizeof(__u32));
218
219         i = *((int *)skb->data);
220         skb_pull(skb, sizeof(info->mcr));
221         if (i & UART_MCR_RTS) {
222                 info->msr |= UART_MSR_CTS;
223                 if (info->flags & CTC_ASYNC_CTS_FLOW)
224                         info->tty->hw_stopped = 0;
225         } else {
226                 info->msr &= ~UART_MSR_CTS;
227                 if (info->flags & CTC_ASYNC_CTS_FLOW)
228                         info->tty->hw_stopped = 1;
229         }
230         if (i & UART_MCR_DTR)
231                 info->msr |= UART_MSR_DSR;
232         else
233                 info->msr &= ~UART_MSR_DSR;
234         if (skb->len <= 0) {
235                 kfree_skb(skb);
236                 return;
237         }
238         /* Try to deliver directly via tty-flip-buf if queue is empty */
239         if (skb_queue_empty(&info->rx_queue))
240                 if (ctc_tty_try_read(info, skb))
241                         return;
242         /* Direct deliver failed or queue wasn't empty.
243          * Queue up for later dequeueing via timer-irq.
244          */
245         skb_queue_tail(&info->rx_queue, skb);
246         /* Schedule dequeuing */
247         tasklet_schedule(&info->tasklet);
248 }
249
250 static int
251 ctc_tty_tint(ctc_tty_info * info)
252 {
253         struct sk_buff *skb = skb_dequeue(&info->tx_queue);
254         int stopped = (info->tty->hw_stopped || info->tty->stopped);
255         int wake = 1;
256         int rc;
257
258         DBF_TEXT(trace, 4, __FUNCTION__);
259         if (!info->netdev) {
260                 if (skb)
261                         kfree_skb(skb);
262                 return 0;
263         }
264         if (info->flags & CTC_ASYNC_TX_LINESTAT) {
265                 int skb_res = info->netdev->hard_header_len +
266                         sizeof(info->mcr) + sizeof(__u32);
267                 /* If we must update line status,
268                  * create an empty dummy skb and insert it.
269                  */
270                 if (skb)
271                         skb_queue_head(&info->tx_queue, skb);
272
273                 skb = dev_alloc_skb(skb_res);
274                 if (!skb) {
275                         printk(KERN_WARNING
276                                "ctc_tty: Out of memory in %s%d tint\n",
277                                CTC_TTY_NAME, info->line);
278                         return 1;
279                 }
280                 skb_reserve(skb, skb_res);
281                 stopped = 0;
282                 wake = 0;
283         }
284         if (!skb)
285                 return 0;
286         if (stopped) {
287                 skb_queue_head(&info->tx_queue, skb);
288                 return 1;
289         }
290 #if 0
291         if (skb->len > 0)
292                 printk(KERN_DEBUG "tint: %d %02x\n", skb->len, *(skb->data));
293         else
294                 printk(KERN_DEBUG "tint: %d STAT\n", skb->len);
295 #endif
296         memcpy(skb_push(skb, sizeof(info->mcr)), &info->mcr, sizeof(info->mcr));
297         memcpy(skb_push(skb, sizeof(__u32)), &ctc_tty_magic, sizeof(__u32));
298         rc = info->netdev->hard_start_xmit(skb, info->netdev);
299         if (rc) {
300                 skb_pull(skb, sizeof(info->mcr) + sizeof(__u32));
301                 if (skb->len > 0)
302                         skb_queue_head(&info->tx_queue, skb);
303                 else
304                         kfree_skb(skb);
305         } else {
306                 struct tty_struct *tty = info->tty;
307
308                 info->flags &= ~CTC_ASYNC_TX_LINESTAT;
309                 if (tty) {
310                         tty_wakeup(tty);
311                 }
312         }
313         return (skb_queue_empty(&info->tx_queue) ? 0 : 1);
314 }
315
316 /************************************************************
317  *
318  * Modem-functions
319  *
320  * mostly "stolen" from original Linux-serial.c and friends.
321  *
322  ************************************************************/
323
324 static inline int
325 ctc_tty_paranoia_check(ctc_tty_info * info, char *name, const char *routine)
326 {
327 #ifdef MODEM_PARANOIA_CHECK
328         if (!info) {
329                 printk(KERN_WARNING "ctc_tty: null info_struct for %s in %s\n",
330                        name, routine);
331                 return 1;
332         }
333         if (info->magic != CTC_ASYNC_MAGIC) {
334                 printk(KERN_WARNING "ctc_tty: bad magic for info struct %s in %s\n",
335                        name, routine);
336                 return 1;
337         }
338 #endif
339         return 0;
340 }
341
342 static void
343 ctc_tty_inject(ctc_tty_info *info, char c)
344 {
345         int skb_res;
346         struct sk_buff *skb;
347         
348         DBF_TEXT(trace, 4, __FUNCTION__);
349         if (ctc_tty_shuttingdown)
350                 return;
351         skb_res = info->netdev->hard_header_len + sizeof(info->mcr) +
352                 sizeof(__u32) + 1;
353         skb = dev_alloc_skb(skb_res);
354         if (!skb) {
355                 printk(KERN_WARNING
356                        "ctc_tty: Out of memory in %s%d tx_inject\n",
357                        CTC_TTY_NAME, info->line);
358                 return;
359         }
360         skb_reserve(skb, skb_res);
361         *(skb_put(skb, 1)) = c;
362         skb_queue_head(&info->tx_queue, skb);
363         tasklet_schedule(&info->tasklet);
364 }
365
366 static void
367 ctc_tty_transmit_status(ctc_tty_info *info)
368 {
369         DBF_TEXT(trace, 5, __FUNCTION__);
370         if (ctc_tty_shuttingdown)
371                 return;
372         info->flags |= CTC_ASYNC_TX_LINESTAT;
373         tasklet_schedule(&info->tasklet);
374 }
375
376 static void
377 ctc_tty_change_speed(ctc_tty_info * info)
378 {
379         unsigned int cflag;
380         unsigned int quot;
381         int i;
382
383         DBF_TEXT(trace, 3, __FUNCTION__);
384         if (!info->tty || !info->tty->termios)
385                 return;
386         cflag = info->tty->termios->c_cflag;
387
388         quot = i = cflag & CBAUD;
389         if (i & CBAUDEX) {
390                 i &= ~CBAUDEX;
391                 if (i < 1 || i > 2)
392                         info->tty->termios->c_cflag &= ~CBAUDEX;
393                 else
394                         i += 15;
395         }
396         if (quot) {
397                 info->mcr |= UART_MCR_DTR;
398                 info->mcr |= UART_MCR_RTS;
399                 ctc_tty_transmit_status(info);
400         } else {
401                 info->mcr &= ~UART_MCR_DTR;
402                 info->mcr &= ~UART_MCR_RTS;
403                 ctc_tty_transmit_status(info);
404                 return;
405         }
406
407         /* CTS flow control flag and modem status interrupts */
408         if (cflag & CRTSCTS) {
409                 info->flags |= CTC_ASYNC_CTS_FLOW;
410         } else
411                 info->flags &= ~CTC_ASYNC_CTS_FLOW;
412         if (cflag & CLOCAL)
413                 info->flags &= ~CTC_ASYNC_CHECK_CD;
414         else {
415                 info->flags |= CTC_ASYNC_CHECK_CD;
416         }
417 }
418
419 static int
420 ctc_tty_startup(ctc_tty_info * info)
421 {
422         DBF_TEXT(trace, 3, __FUNCTION__);
423         if (info->flags & CTC_ASYNC_INITIALIZED)
424                 return 0;
425 #ifdef CTC_DEBUG_MODEM_OPEN
426         printk(KERN_DEBUG "starting up %s%d ...\n", CTC_TTY_NAME, info->line);
427 #endif
428         /*
429          * Now, initialize the UART
430          */
431         info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
432         if (info->tty)
433                 clear_bit(TTY_IO_ERROR, &info->tty->flags);
434         /*
435          * and set the speed of the serial port
436          */
437         ctc_tty_change_speed(info);
438
439         info->flags |= CTC_ASYNC_INITIALIZED;
440         if (!(info->flags & CTC_ASYNC_NETDEV_OPEN))
441                 info->netdev->open(info->netdev);
442         info->flags |= CTC_ASYNC_NETDEV_OPEN;
443         return 0;
444 }
445
446 static void
447 ctc_tty_stopdev(unsigned long data)
448 {
449         ctc_tty_info *info = (ctc_tty_info *)data;
450
451         if ((!info) || (!info->netdev) ||
452             (info->flags & CTC_ASYNC_INITIALIZED))
453                 return;
454         info->netdev->stop(info->netdev);
455         info->flags &= ~CTC_ASYNC_NETDEV_OPEN;
456 }
457
458 /*
459  * This routine will shutdown a serial port; interrupts are disabled, and
460  * DTR is dropped if the hangup on close termio flag is on.
461  */
462 static void
463 ctc_tty_shutdown(ctc_tty_info * info)
464 {
465         DBF_TEXT(trace, 3, __FUNCTION__);
466         if (!(info->flags & CTC_ASYNC_INITIALIZED))
467                 return;
468 #ifdef CTC_DEBUG_MODEM_OPEN
469         printk(KERN_DEBUG "Shutting down %s%d ....\n", CTC_TTY_NAME, info->line);
470 #endif
471         info->msr &= ~UART_MSR_RI;
472         if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
473                 info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
474         if (info->tty)
475                 set_bit(TTY_IO_ERROR, &info->tty->flags);
476         mod_timer(&info->stoptimer, jiffies + (10 * HZ));
477         skb_queue_purge(&info->tx_queue);
478         skb_queue_purge(&info->rx_queue);
479         info->flags &= ~CTC_ASYNC_INITIALIZED;
480 }
481
482 /* ctc_tty_write() is the main send-routine. It is called from the upper
483  * levels within the kernel to perform sending data. Depending on the
484  * online-flag it either directs output to the at-command-interpreter or
485  * to the lower level. Additional tasks done here:
486  *  - If online, check for escape-sequence (+++)
487  *  - If sending audio-data, call ctc_tty_DLEdown() to parse DLE-codes.
488  *  - If receiving audio-data, call ctc_tty_end_vrx() to abort if needed.
489  *  - If dialing, abort dial.
490  */
491 static int
492 ctc_tty_write(struct tty_struct *tty, const u_char * buf, int count)
493 {
494         int c;
495         int total = 0;
496         ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
497
498         DBF_TEXT(trace, 5, __FUNCTION__);
499         if (ctc_tty_shuttingdown)
500                 goto ex;
501         if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_write"))
502                 goto ex;
503         if (!tty)
504                 goto ex;
505         if (!info->netdev) {
506                 total = -ENODEV;
507                 goto ex;
508         }
509         while (1) {
510                 struct sk_buff *skb;
511                 int skb_res;
512
513                 c = (count < CTC_TTY_XMIT_SIZE) ? count : CTC_TTY_XMIT_SIZE;
514                 if (c <= 0)
515                         break;
516                 
517                 skb_res = info->netdev->hard_header_len + sizeof(info->mcr) +
518                         + sizeof(__u32);
519                 skb = dev_alloc_skb(skb_res + c);
520                 if (!skb) {
521                         printk(KERN_WARNING
522                                "ctc_tty: Out of memory in %s%d write\n",
523                                CTC_TTY_NAME, info->line);
524                         break;
525                 }
526                 skb_reserve(skb, skb_res);
527                 memcpy(skb_put(skb, c), buf, c);
528                 skb_queue_tail(&info->tx_queue, skb);
529                 buf += c;
530                 total += c;
531                 count -= c;
532         }
533         if (skb_queue_len(&info->tx_queue)) {
534                 info->lsr &= ~UART_LSR_TEMT;
535                 tasklet_schedule(&info->tasklet);
536         }
537 ex:
538         DBF_TEXT(trace, 6, __FUNCTION__);
539         return total;
540 }
541
542 static int
543 ctc_tty_write_room(struct tty_struct *tty)
544 {
545         ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
546
547         if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_write_room"))
548                 return 0;
549         return CTC_TTY_XMIT_SIZE;
550 }
551
552 static int
553 ctc_tty_chars_in_buffer(struct tty_struct *tty)
554 {
555         ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
556
557         if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_chars_in_buffer"))
558                 return 0;
559         return 0;
560 }
561
562 static void
563 ctc_tty_flush_buffer(struct tty_struct *tty)
564 {
565         ctc_tty_info *info;
566         unsigned long flags;
567
568         DBF_TEXT(trace, 4, __FUNCTION__);
569         if (!tty)
570                 goto ex;
571         spin_lock_irqsave(&ctc_tty_lock, flags);
572         info = (ctc_tty_info *) tty->driver_data;
573         if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_buffer")) {
574                 spin_unlock_irqrestore(&ctc_tty_lock, flags);
575                 goto ex;
576         }
577         skb_queue_purge(&info->tx_queue);
578         info->lsr |= UART_LSR_TEMT;
579         spin_unlock_irqrestore(&ctc_tty_lock, flags);
580         wake_up_interruptible(&tty->write_wait);
581         tty_wakeup(tty);
582 ex:
583         DBF_TEXT_(trace, 2, "ex: %s ", __FUNCTION__);
584         return;
585 }
586
587 static void
588 ctc_tty_flush_chars(struct tty_struct *tty)
589 {
590         ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
591
592         DBF_TEXT(trace, 4, __FUNCTION__);
593         if (ctc_tty_shuttingdown)
594                 return;
595         if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_chars"))
596                 return;
597         if (tty->stopped || tty->hw_stopped || (!skb_queue_len(&info->tx_queue)))
598                 return;
599         tasklet_schedule(&info->tasklet);
600 }
601
602 /*
603  * ------------------------------------------------------------
604  * ctc_tty_throttle()
605  *
606  * This routine is called by the upper-layer tty layer to signal that
607  * incoming characters should be throttled.
608  * ------------------------------------------------------------
609  */
610 static void
611 ctc_tty_throttle(struct tty_struct *tty)
612 {
613         ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
614
615         DBF_TEXT(trace, 4, __FUNCTION__);
616         if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_throttle"))
617                 return;
618         info->mcr &= ~UART_MCR_RTS;
619         if (I_IXOFF(tty))
620                 ctc_tty_inject(info, STOP_CHAR(tty));
621         ctc_tty_transmit_status(info);
622 }
623
624 static void
625 ctc_tty_unthrottle(struct tty_struct *tty)
626 {
627         ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
628
629         DBF_TEXT(trace, 4, __FUNCTION__);
630         if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_unthrottle"))
631                 return;
632         info->mcr |= UART_MCR_RTS;
633         if (I_IXOFF(tty))
634                 ctc_tty_inject(info, START_CHAR(tty));
635         ctc_tty_transmit_status(info);
636 }
637
638 /*
639  * ------------------------------------------------------------
640  * ctc_tty_ioctl() and friends
641  * ------------------------------------------------------------
642  */
643
644 /*
645  * ctc_tty_get_lsr_info - get line status register info
646  *
647  * Purpose: Let user call ioctl() to get info when the UART physically
648  *          is emptied.  On bus types like RS485, the transmitter must
649  *          release the bus after transmitting. This must be done when
650  *          the transmit shift register is empty, not be done when the
651  *          transmit holding register is empty.  This functionality
652  *          allows RS485 driver to be written in user space.
653  */
654 static int
655 ctc_tty_get_lsr_info(ctc_tty_info * info, uint __user *value)
656 {
657         u_char status;
658         uint result;
659         ulong flags;
660
661         DBF_TEXT(trace, 4, __FUNCTION__);
662         spin_lock_irqsave(&ctc_tty_lock, flags);
663         status = info->lsr;
664         spin_unlock_irqrestore(&ctc_tty_lock, flags);
665         result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
666         put_user(result, value);
667         return 0;
668 }
669
670
671 static int ctc_tty_tiocmget(struct tty_struct *tty, struct file *file)
672 {
673         ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
674         u_char control,
675          status;
676         uint result;
677         ulong flags;
678
679         DBF_TEXT(trace, 4, __FUNCTION__);
680         if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
681                 return -ENODEV;
682         if (tty->flags & (1 << TTY_IO_ERROR))
683                 return -EIO;
684
685         control = info->mcr;
686         spin_lock_irqsave(&ctc_tty_lock, flags);
687         status = info->msr;
688         spin_unlock_irqrestore(&ctc_tty_lock, flags);
689         result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
690             | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
691             | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
692             | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
693             | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
694             | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
695         return result;
696 }
697
698 static int
699 ctc_tty_tiocmset(struct tty_struct *tty, struct file *file,
700                  unsigned int set, unsigned int clear)
701 {
702         ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
703
704         DBF_TEXT(trace, 4, __FUNCTION__);
705         if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
706                 return -ENODEV;
707         if (tty->flags & (1 << TTY_IO_ERROR))
708                 return -EIO;
709
710         if (set & TIOCM_RTS)
711                 info->mcr |= UART_MCR_RTS;
712         if (set & TIOCM_DTR)
713                 info->mcr |= UART_MCR_DTR;
714
715         if (clear & TIOCM_RTS)
716                 info->mcr &= ~UART_MCR_RTS;
717         if (clear & TIOCM_DTR)
718                 info->mcr &= ~UART_MCR_DTR;
719
720         if ((set | clear) & (TIOCM_RTS|TIOCM_DTR))
721                 ctc_tty_transmit_status(info);
722         return 0;
723 }
724
725 static int
726 ctc_tty_ioctl(struct tty_struct *tty, struct file *file,
727                uint cmd, ulong arg)
728 {
729         ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
730         int error;
731         int retval;
732
733         DBF_TEXT(trace, 4, __FUNCTION__);
734         if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
735                 return -ENODEV;
736         if (tty->flags & (1 << TTY_IO_ERROR))
737                 return -EIO;
738         switch (cmd) {
739                 case TCSBRK:   /* SVID version: non-zero arg --> no break */
740 #ifdef CTC_DEBUG_MODEM_IOCTL
741                         printk(KERN_DEBUG "%s%d ioctl TCSBRK\n", CTC_TTY_NAME, info->line);
742 #endif
743                         retval = tty_check_change(tty);
744                         if (retval)
745                                 return retval;
746                         tty_wait_until_sent(tty, 0);
747                         return 0;
748                 case TCSBRKP:  /* support for POSIX tcsendbreak() */
749 #ifdef CTC_DEBUG_MODEM_IOCTL
750                         printk(KERN_DEBUG "%s%d ioctl TCSBRKP\n", CTC_TTY_NAME, info->line);
751 #endif
752                         retval = tty_check_change(tty);
753                         if (retval)
754                                 return retval;
755                         tty_wait_until_sent(tty, 0);
756                         return 0;
757                 case TIOCGSOFTCAR:
758 #ifdef CTC_DEBUG_MODEM_IOCTL
759                         printk(KERN_DEBUG "%s%d ioctl TIOCGSOFTCAR\n", CTC_TTY_NAME,
760                                info->line);
761 #endif
762                         error = put_user(C_CLOCAL(tty) ? 1 : 0, (ulong __user *) arg);
763                         return error;
764                 case TIOCSSOFTCAR:
765 #ifdef CTC_DEBUG_MODEM_IOCTL
766                         printk(KERN_DEBUG "%s%d ioctl TIOCSSOFTCAR\n", CTC_TTY_NAME,
767                                info->line);
768 #endif
769                         error = get_user(arg, (ulong __user *) arg);
770                         if (error)
771                                 return error;
772                         tty->termios->c_cflag =
773                             ((tty->termios->c_cflag & ~CLOCAL) |
774                              (arg ? CLOCAL : 0));
775                         return 0;
776                 case TIOCSERGETLSR:     /* Get line status register */
777 #ifdef CTC_DEBUG_MODEM_IOCTL
778                         printk(KERN_DEBUG "%s%d ioctl TIOCSERGETLSR\n", CTC_TTY_NAME,
779                                info->line);
780 #endif
781                         if (access_ok(VERIFY_WRITE, (void __user *) arg, sizeof(uint)))
782                                 return ctc_tty_get_lsr_info(info, (uint __user *) arg);
783                         else
784                                 return -EFAULT;
785                 default:
786 #ifdef CTC_DEBUG_MODEM_IOCTL
787                         printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on %s%d\n", cmd,
788                                CTC_TTY_NAME, info->line);
789 #endif
790                         return -ENOIOCTLCMD;
791         }
792         return 0;
793 }
794
795 static void
796 ctc_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
797 {
798         ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
799         unsigned int cflag = tty->termios->c_cflag;
800
801         DBF_TEXT(trace, 4, __FUNCTION__);
802         ctc_tty_change_speed(info);
803
804         /* Handle transition to B0 */
805         if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) {
806                 info->mcr &= ~(UART_MCR_DTR|UART_MCR_RTS);
807                 ctc_tty_transmit_status(info);
808         }
809
810         /* Handle transition from B0 to other */
811         if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
812                 info->mcr |= UART_MCR_DTR;
813                 if (!(tty->termios->c_cflag & CRTSCTS) ||
814                     !test_bit(TTY_THROTTLED, &tty->flags)) {
815                         info->mcr |= UART_MCR_RTS;
816                 }
817                 ctc_tty_transmit_status(info);
818         }
819
820         /* Handle turning off CRTSCTS */
821         if ((old_termios->c_cflag & CRTSCTS) &&
822             !(tty->termios->c_cflag & CRTSCTS))
823                 tty->hw_stopped = 0;
824 }
825
826 /*
827  * ------------------------------------------------------------
828  * ctc_tty_open() and friends
829  * ------------------------------------------------------------
830  */
831 static int
832 ctc_tty_block_til_ready(struct tty_struct *tty, struct file *filp, ctc_tty_info *info)
833 {
834         DECLARE_WAITQUEUE(wait, NULL);
835         int do_clocal = 0;
836         unsigned long flags;
837         int retval;
838
839         DBF_TEXT(trace, 4, __FUNCTION__);
840         /*
841          * If the device is in the middle of being closed, then block
842          * until it's done, and then try again.
843          */
844         if (tty_hung_up_p(filp) ||
845             (info->flags & CTC_ASYNC_CLOSING)) {
846                 if (info->flags & CTC_ASYNC_CLOSING)
847                         wait_event(info->close_wait, 
848                                    !(info->flags & CTC_ASYNC_CLOSING));
849 #ifdef MODEM_DO_RESTART
850                 if (info->flags & CTC_ASYNC_HUP_NOTIFY)
851                         return -EAGAIN;
852                 else
853                         return -ERESTARTSYS;
854 #else
855                 return -EAGAIN;
856 #endif
857         }
858         /*
859          * If non-blocking mode is set, then make the check up front
860          * and then exit.
861          */
862         if ((filp->f_flags & O_NONBLOCK) ||
863             (tty->flags & (1 << TTY_IO_ERROR))) {
864                 info->flags |= CTC_ASYNC_NORMAL_ACTIVE;
865                 return 0;
866         }
867         if (tty->termios->c_cflag & CLOCAL)
868                 do_clocal = 1;
869         /*
870          * Block waiting for the carrier detect and the line to become
871          * free (i.e., not in use by the callout).  While we are in
872          * this loop, info->count is dropped by one, so that
873          * ctc_tty_close() knows when to free things.  We restore it upon
874          * exit, either normal or abnormal.
875          */
876         retval = 0;
877         add_wait_queue(&info->open_wait, &wait);
878 #ifdef CTC_DEBUG_MODEM_OPEN
879         printk(KERN_DEBUG "ctc_tty_block_til_ready before block: %s%d, count = %d\n",
880                CTC_TTY_NAME, info->line, info->count);
881 #endif
882         spin_lock_irqsave(&ctc_tty_lock, flags);
883         if (!(tty_hung_up_p(filp)))
884                 info->count--;
885         spin_unlock_irqrestore(&ctc_tty_lock, flags);
886         info->blocked_open++;
887         while (1) {
888                 set_current_state(TASK_INTERRUPTIBLE);
889                 if (tty_hung_up_p(filp) ||
890                     !(info->flags & CTC_ASYNC_INITIALIZED)) {
891 #ifdef MODEM_DO_RESTART
892                         if (info->flags & CTC_ASYNC_HUP_NOTIFY)
893                                 retval = -EAGAIN;
894                         else
895                                 retval = -ERESTARTSYS;
896 #else
897                         retval = -EAGAIN;
898 #endif
899                         break;
900                 }
901                 if (!(info->flags & CTC_ASYNC_CLOSING) &&
902                     (do_clocal || (info->msr & UART_MSR_DCD))) {
903                         break;
904                 }
905                 if (signal_pending(current)) {
906                         retval = -ERESTARTSYS;
907                         break;
908                 }
909 #ifdef CTC_DEBUG_MODEM_OPEN
910                 printk(KERN_DEBUG "ctc_tty_block_til_ready blocking: %s%d, count = %d\n",
911                        CTC_TTY_NAME, info->line, info->count);
912 #endif
913                 schedule();
914         }
915         current->state = TASK_RUNNING;
916         remove_wait_queue(&info->open_wait, &wait);
917         if (!tty_hung_up_p(filp))
918                 info->count++;
919         info->blocked_open--;
920 #ifdef CTC_DEBUG_MODEM_OPEN
921         printk(KERN_DEBUG "ctc_tty_block_til_ready after blocking: %s%d, count = %d\n",
922                CTC_TTY_NAME, info->line, info->count);
923 #endif
924         if (retval)
925                 return retval;
926         info->flags |= CTC_ASYNC_NORMAL_ACTIVE;
927         return 0;
928 }
929
930 /*
931  * This routine is called whenever a serial port is opened.  It
932  * enables interrupts for a serial port, linking in its async structure into
933  * the IRQ chain.   It also performs the serial-specific
934  * initialization for the tty structure.
935  */
936 static int
937 ctc_tty_open(struct tty_struct *tty, struct file *filp)
938 {
939         ctc_tty_info *info;
940         unsigned long saveflags;
941         int retval,
942          line;
943
944         DBF_TEXT(trace, 3, __FUNCTION__);
945         line = tty->index;
946         if (line < 0 || line > CTC_TTY_MAX_DEVICES)
947                 return -ENODEV;
948         info = &driver->info[line];
949         if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_open"))
950                 return -ENODEV;
951         if (!info->netdev)
952                 return -ENODEV;
953 #ifdef CTC_DEBUG_MODEM_OPEN
954         printk(KERN_DEBUG "ctc_tty_open %s, count = %d\n", tty->name,
955                info->count);
956 #endif
957         spin_lock_irqsave(&ctc_tty_lock, saveflags);
958         info->count++;
959         tty->driver_data = info;
960         info->tty = tty;
961         spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
962         /*
963          * Start up serial port
964          */
965         retval = ctc_tty_startup(info);
966         if (retval) {
967 #ifdef CTC_DEBUG_MODEM_OPEN
968                 printk(KERN_DEBUG "ctc_tty_open return after startup\n");
969 #endif
970                 return retval;
971         }
972         retval = ctc_tty_block_til_ready(tty, filp, info);
973         if (retval) {
974 #ifdef CTC_DEBUG_MODEM_OPEN
975                 printk(KERN_DEBUG "ctc_tty_open return after ctc_tty_block_til_ready \n");
976 #endif
977                 return retval;
978         }
979 #ifdef CTC_DEBUG_MODEM_OPEN
980         printk(KERN_DEBUG "ctc_tty_open %s successful...\n", tty->name);
981 #endif
982         return 0;
983 }
984
985 static void
986 ctc_tty_close(struct tty_struct *tty, struct file *filp)
987 {
988         ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
989         ulong flags;
990         ulong timeout;
991         DBF_TEXT(trace, 3, __FUNCTION__);
992         if (!info || ctc_tty_paranoia_check(info, tty->name, "ctc_tty_close"))
993                 return;
994         spin_lock_irqsave(&ctc_tty_lock, flags);
995         if (tty_hung_up_p(filp)) {
996                 spin_unlock_irqrestore(&ctc_tty_lock, flags);
997 #ifdef CTC_DEBUG_MODEM_OPEN
998                 printk(KERN_DEBUG "ctc_tty_close return after tty_hung_up_p\n");
999 #endif
1000                 return;
1001         }
1002         if ((tty->count == 1) && (info->count != 1)) {
1003                 /*
1004                  * Uh, oh.  tty->count is 1, which means that the tty
1005                  * structure will be freed.  Info->count should always
1006                  * be one in these conditions.  If it's greater than
1007                  * one, we've got real problems, since it means the
1008                  * serial port won't be shutdown.
1009                  */
1010                 printk(KERN_ERR "ctc_tty_close: bad port count; tty->count is 1, "
1011                        "info->count is %d\n", info->count);
1012                 info->count = 1;
1013         }
1014         if (--info->count < 0) {
1015                 printk(KERN_ERR "ctc_tty_close: bad port count for %s%d: %d\n",
1016                        CTC_TTY_NAME, info->line, info->count);
1017                 info->count = 0;
1018         }
1019         if (info->count) {
1020                 local_irq_restore(flags);
1021 #ifdef CTC_DEBUG_MODEM_OPEN
1022                 printk(KERN_DEBUG "ctc_tty_close after info->count != 0\n");
1023 #endif
1024                 return;
1025         }
1026         info->flags |= CTC_ASYNC_CLOSING;
1027         tty->closing = 1;
1028         /*
1029          * At this point we stop accepting input.  To do this, we
1030          * disable the receive line status interrupts, and tell the
1031          * interrupt driver to stop checking the data ready bit in the
1032          * line status register.
1033          */
1034         if (info->flags & CTC_ASYNC_INITIALIZED) {
1035                 tty_wait_until_sent(tty, 30*HZ); /* 30 seconds timeout */
1036                 /*
1037                  * Before we drop DTR, make sure the UART transmitter
1038                  * has completely drained; this is especially
1039                  * important if there is a transmit FIFO!
1040                  */
1041                 timeout = jiffies + HZ;
1042                 while (!(info->lsr & UART_LSR_TEMT)) {
1043                         spin_unlock_irqrestore(&ctc_tty_lock, flags);
1044                         msleep(500);
1045                         spin_lock_irqsave(&ctc_tty_lock, flags);
1046                         if (time_after(jiffies,timeout))
1047                                 break;
1048                 }
1049         }
1050         ctc_tty_shutdown(info);
1051         if (tty->driver->flush_buffer) {
1052                 skb_queue_purge(&info->tx_queue);
1053                 info->lsr |= UART_LSR_TEMT;
1054         }
1055         tty_ldisc_flush(tty);
1056         info->tty = 0;
1057         tty->closing = 0;
1058         if (info->blocked_open) {
1059                 msleep_interruptible(500);
1060                 wake_up_interruptible(&info->open_wait);
1061         }
1062         info->flags &= ~(CTC_ASYNC_NORMAL_ACTIVE | CTC_ASYNC_CLOSING);
1063         wake_up_interruptible(&info->close_wait);
1064         spin_unlock_irqrestore(&ctc_tty_lock, flags);
1065 #ifdef CTC_DEBUG_MODEM_OPEN
1066         printk(KERN_DEBUG "ctc_tty_close normal exit\n");
1067 #endif
1068 }
1069
1070 /*
1071  * ctc_tty_hangup() --- called by tty_hangup() when a hangup is signaled.
1072  */
1073 static void
1074 ctc_tty_hangup(struct tty_struct *tty)
1075 {
1076         ctc_tty_info *info = (ctc_tty_info *)tty->driver_data;
1077         unsigned long saveflags;
1078         DBF_TEXT(trace, 3, __FUNCTION__);
1079         if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_hangup"))
1080                 return;
1081         ctc_tty_shutdown(info);
1082         info->count = 0;
1083         info->flags &= ~CTC_ASYNC_NORMAL_ACTIVE;
1084         spin_lock_irqsave(&ctc_tty_lock, saveflags);
1085         info->tty = 0;
1086         spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
1087         wake_up_interruptible(&info->open_wait);
1088 }
1089
1090
1091 /*
1092  * For all online tty's, try sending data to
1093  * the lower levels.
1094  */
1095 static void
1096 ctc_tty_task(unsigned long arg)
1097 {
1098         ctc_tty_info *info = (void *)arg;
1099         unsigned long saveflags;
1100         int again;
1101
1102         DBF_TEXT(trace, 3, __FUNCTION__);
1103         spin_lock_irqsave(&ctc_tty_lock, saveflags);
1104         if ((!ctc_tty_shuttingdown) && info) {
1105                 again = ctc_tty_tint(info);
1106                 if (!again)
1107                         info->lsr |= UART_LSR_TEMT;
1108                 again |= ctc_tty_readmodem(info);
1109                 if (again) {
1110                         tasklet_schedule(&info->tasklet);
1111                 }
1112         }
1113         spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
1114 }
1115
1116 static struct tty_operations ctc_ops = {
1117         .open = ctc_tty_open,
1118         .close = ctc_tty_close,
1119         .write = ctc_tty_write,
1120         .flush_chars = ctc_tty_flush_chars,
1121         .write_room = ctc_tty_write_room,
1122         .chars_in_buffer = ctc_tty_chars_in_buffer,
1123         .flush_buffer = ctc_tty_flush_buffer,
1124         .ioctl = ctc_tty_ioctl,
1125         .throttle = ctc_tty_throttle,
1126         .unthrottle = ctc_tty_unthrottle,
1127         .set_termios = ctc_tty_set_termios,
1128         .hangup = ctc_tty_hangup,
1129         .tiocmget = ctc_tty_tiocmget,
1130         .tiocmset = ctc_tty_tiocmset,
1131 };
1132
1133 int
1134 ctc_tty_init(void)
1135 {
1136         int i;
1137         ctc_tty_info *info;
1138         struct tty_driver *device;
1139
1140         DBF_TEXT(trace, 2, __FUNCTION__);
1141         driver = kmalloc(sizeof(ctc_tty_driver), GFP_KERNEL);
1142         if (driver == NULL) {
1143                 printk(KERN_WARNING "Out of memory in ctc_tty_modem_init\n");
1144                 return -ENOMEM;
1145         }
1146         memset(driver, 0, sizeof(ctc_tty_driver));
1147         device = alloc_tty_driver(CTC_TTY_MAX_DEVICES);
1148         if (!device) {
1149                 kfree(driver);
1150                 printk(KERN_WARNING "Out of memory in ctc_tty_modem_init\n");
1151                 return -ENOMEM;
1152         }
1153
1154         device->devfs_name = "ctc/" CTC_TTY_NAME;
1155         device->name = CTC_TTY_NAME;
1156         device->major = CTC_TTY_MAJOR;
1157         device->minor_start = 0;
1158         device->type = TTY_DRIVER_TYPE_SERIAL;
1159         device->subtype = SERIAL_TYPE_NORMAL;
1160         device->init_termios = tty_std_termios;
1161         device->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1162         device->flags = TTY_DRIVER_REAL_RAW;
1163         device->driver_name = "ctc_tty",
1164         tty_set_operations(device, &ctc_ops);
1165         if (tty_register_driver(device)) {
1166                 printk(KERN_WARNING "ctc_tty: Couldn't register serial-device\n");
1167                 put_tty_driver(device);
1168                 kfree(driver);
1169                 return -1;
1170         }
1171         driver->ctc_tty_device = device;
1172         for (i = 0; i < CTC_TTY_MAX_DEVICES; i++) {
1173                 info = &driver->info[i];
1174                 init_MUTEX(&info->write_sem);
1175                 tasklet_init(&info->tasklet, ctc_tty_task,
1176                                 (unsigned long) info);
1177                 info->magic = CTC_ASYNC_MAGIC;
1178                 info->line = i;
1179                 info->tty = 0;
1180                 info->count = 0;
1181                 info->blocked_open = 0;
1182                 init_waitqueue_head(&info->open_wait);
1183                 init_waitqueue_head(&info->close_wait);
1184                 skb_queue_head_init(&info->tx_queue);
1185                 skb_queue_head_init(&info->rx_queue);
1186                 init_timer(&info->stoptimer);
1187                 info->stoptimer.function = ctc_tty_stopdev;
1188                 info->stoptimer.data = (unsigned long)info;
1189                 info->mcr = UART_MCR_RTS;
1190         }
1191         return 0;
1192 }
1193
1194 int
1195 ctc_tty_register_netdev(struct net_device *dev) {
1196         int ttynum;
1197         char *err;
1198         char *p;
1199
1200         DBF_TEXT(trace, 2, __FUNCTION__);
1201         if ((!dev) || (!dev->name)) {
1202                 printk(KERN_WARNING
1203                        "ctc_tty_register_netdev called "
1204                        "with NULL dev or NULL dev-name\n");
1205                 return -1;
1206         }
1207
1208         /*
1209          *      If the name is a format string the caller wants us to
1210          *      do a name allocation : format string must end with %d
1211          */
1212         if (strchr(dev->name, '%'))
1213         {
1214                 int err = dev_alloc_name(dev, dev->name);       // dev->name is changed by this
1215                 if (err < 0) {
1216                         printk(KERN_DEBUG "dev_alloc returned error %d\n", err);
1217                         return err;
1218                 }
1219
1220         }
1221
1222         for (p = dev->name; p && ((*p < '0') || (*p > '9')); p++);
1223         ttynum = simple_strtoul(p, &err, 0);
1224         if ((ttynum < 0) || (ttynum >= CTC_TTY_MAX_DEVICES) ||
1225             (err && *err)) {
1226                 printk(KERN_WARNING
1227                        "ctc_tty_register_netdev called "
1228                        "with number in name '%s'\n", dev->name);
1229                 return -1;
1230         }
1231         if (driver->info[ttynum].netdev) {
1232                 printk(KERN_WARNING
1233                        "ctc_tty_register_netdev called "
1234                        "for already registered device '%s'\n",
1235                        dev->name);
1236                 return -1;
1237         }
1238         driver->info[ttynum].netdev = dev;
1239         return 0;
1240 }
1241
1242 void
1243 ctc_tty_unregister_netdev(struct net_device *dev) {
1244         int i;
1245         unsigned long saveflags;
1246         ctc_tty_info *info = NULL;
1247
1248         DBF_TEXT(trace, 2, __FUNCTION__);
1249         spin_lock_irqsave(&ctc_tty_lock, saveflags);
1250         for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
1251                 if (driver->info[i].netdev == dev) {
1252                         info = &driver->info[i];
1253                         break;
1254                 }
1255         if (info) {
1256                 info->netdev = NULL;
1257                 skb_queue_purge(&info->tx_queue);
1258                 skb_queue_purge(&info->rx_queue);
1259         }
1260         spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
1261 }
1262
1263 void
1264 ctc_tty_cleanup(void) {
1265         unsigned long saveflags;
1266         
1267         DBF_TEXT(trace, 2, __FUNCTION__);
1268         spin_lock_irqsave(&ctc_tty_lock, saveflags);
1269         ctc_tty_shuttingdown = 1;
1270         spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
1271         tty_unregister_driver(driver->ctc_tty_device);
1272         put_tty_driver(driver->ctc_tty_device);
1273         kfree(driver);
1274         driver = NULL;
1275 }