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