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