Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / tty / ipwireless / tty.c
1 /*
2  * IPWireless 3G PCMCIA Network Driver
3  *
4  * Original code
5  *   by Stephen Blackheath <stephen@blacksapphire.com>,
6  *      Ben Martel <benm@symmetric.co.nz>
7  *
8  * Copyrighted as follows:
9  *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
10  *
11  * Various driver changes and rewrites, port to new kernels
12  *   Copyright (C) 2006-2007 Jiri Kosina
13  *
14  * Misc code cleanups and updates
15  *   Copyright (C) 2007 David Sterba
16  */
17
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/mutex.h>
21 #include <linux/ppp_defs.h>
22 #include <linux/if.h>
23 #include <linux/ppp-ioctl.h>
24 #include <linux/sched.h>
25 #include <linux/serial.h>
26 #include <linux/slab.h>
27 #include <linux/tty.h>
28 #include <linux/tty_driver.h>
29 #include <linux/tty_flip.h>
30 #include <linux/uaccess.h>
31
32 #include "tty.h"
33 #include "network.h"
34 #include "hardware.h"
35 #include "main.h"
36
37 #define IPWIRELESS_PCMCIA_START         (0)
38 #define IPWIRELESS_PCMCIA_MINORS        (24)
39 #define IPWIRELESS_PCMCIA_MINOR_RANGE   (8)
40
41 #define TTYTYPE_MODEM    (0)
42 #define TTYTYPE_MONITOR  (1)
43 #define TTYTYPE_RAS_RAW  (2)
44
45 struct ipw_tty {
46         struct tty_port port;
47         int index;
48         struct ipw_hardware *hardware;
49         unsigned int channel_idx;
50         unsigned int secondary_channel_idx;
51         int tty_type;
52         struct ipw_network *network;
53         unsigned int control_lines;
54         struct mutex ipw_tty_mutex;
55         int tx_bytes_queued;
56         int closing;
57 };
58
59 static struct ipw_tty *ttys[IPWIRELESS_PCMCIA_MINORS];
60
61 static struct tty_driver *ipw_tty_driver;
62
63 static char *tty_type_name(int tty_type)
64 {
65         static char *channel_names[] = {
66                 "modem",
67                 "monitor",
68                 "RAS-raw"
69         };
70
71         return channel_names[tty_type];
72 }
73
74 static struct ipw_tty *get_tty(int index)
75 {
76         /*
77          * The 'ras_raw' channel is only available when 'loopback' mode
78          * is enabled.
79          * Number of minor starts with 16 (_RANGE * _RAS_RAW).
80          */
81         if (!ipwireless_loopback && index >=
82                          IPWIRELESS_PCMCIA_MINOR_RANGE * TTYTYPE_RAS_RAW)
83                 return NULL;
84
85         return ttys[index];
86 }
87
88 static int ipw_open(struct tty_struct *linux_tty, struct file *filp)
89 {
90         struct ipw_tty *tty = get_tty(linux_tty->index);
91
92         if (!tty)
93                 return -ENODEV;
94
95         mutex_lock(&tty->ipw_tty_mutex);
96         if (tty->port.count == 0)
97                 tty->tx_bytes_queued = 0;
98
99         tty->port.count++;
100
101         tty->port.tty = linux_tty;
102         linux_tty->driver_data = tty;
103         tty->port.low_latency = 1;
104
105         if (tty->tty_type == TTYTYPE_MODEM)
106                 ipwireless_ppp_open(tty->network);
107
108         mutex_unlock(&tty->ipw_tty_mutex);
109
110         return 0;
111 }
112
113 static void do_ipw_close(struct ipw_tty *tty)
114 {
115         tty->port.count--;
116
117         if (tty->port.count == 0) {
118                 struct tty_struct *linux_tty = tty->port.tty;
119
120                 if (linux_tty != NULL) {
121                         tty->port.tty = NULL;
122                         linux_tty->driver_data = NULL;
123
124                         if (tty->tty_type == TTYTYPE_MODEM)
125                                 ipwireless_ppp_close(tty->network);
126                 }
127         }
128 }
129
130 static void ipw_hangup(struct tty_struct *linux_tty)
131 {
132         struct ipw_tty *tty = linux_tty->driver_data;
133
134         if (!tty)
135                 return;
136
137         mutex_lock(&tty->ipw_tty_mutex);
138         if (tty->port.count == 0) {
139                 mutex_unlock(&tty->ipw_tty_mutex);
140                 return;
141         }
142
143         do_ipw_close(tty);
144
145         mutex_unlock(&tty->ipw_tty_mutex);
146 }
147
148 static void ipw_close(struct tty_struct *linux_tty, struct file *filp)
149 {
150         ipw_hangup(linux_tty);
151 }
152
153 /* Take data received from hardware, and send it out the tty */
154 void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data,
155                         unsigned int length)
156 {
157         int work = 0;
158
159         mutex_lock(&tty->ipw_tty_mutex);
160
161         if (!tty->port.count) {
162                 mutex_unlock(&tty->ipw_tty_mutex);
163                 return;
164         }
165         mutex_unlock(&tty->ipw_tty_mutex);
166
167         work = tty_insert_flip_string(&tty->port, data, length);
168
169         if (work != length)
170                 printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
171                                 ": %d chars not inserted to flip buffer!\n",
172                                 length - work);
173
174         if (work)
175                 tty_flip_buffer_push(&tty->port);
176 }
177
178 static void ipw_write_packet_sent_callback(void *callback_data,
179                                            unsigned int packet_length)
180 {
181         struct ipw_tty *tty = callback_data;
182
183         /*
184          * Packet has been sent, so we subtract the number of bytes from our
185          * tally of outstanding TX bytes.
186          */
187         tty->tx_bytes_queued -= packet_length;
188 }
189
190 static int ipw_write(struct tty_struct *linux_tty,
191                      const unsigned char *buf, int count)
192 {
193         struct ipw_tty *tty = linux_tty->driver_data;
194         int room, ret;
195
196         if (!tty)
197                 return -ENODEV;
198
199         mutex_lock(&tty->ipw_tty_mutex);
200         if (!tty->port.count) {
201                 mutex_unlock(&tty->ipw_tty_mutex);
202                 return -EINVAL;
203         }
204
205         room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
206         if (room < 0)
207                 room = 0;
208         /* Don't allow caller to write any more than we have room for */
209         if (count > room)
210                 count = room;
211
212         if (count == 0) {
213                 mutex_unlock(&tty->ipw_tty_mutex);
214                 return 0;
215         }
216
217         ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS,
218                                buf, count,
219                                ipw_write_packet_sent_callback, tty);
220         if (ret == -1) {
221                 mutex_unlock(&tty->ipw_tty_mutex);
222                 return 0;
223         }
224
225         tty->tx_bytes_queued += count;
226         mutex_unlock(&tty->ipw_tty_mutex);
227
228         return count;
229 }
230
231 static int ipw_write_room(struct tty_struct *linux_tty)
232 {
233         struct ipw_tty *tty = linux_tty->driver_data;
234         int room;
235
236         /* FIXME: Exactly how is the tty object locked here .. */
237         if (!tty)
238                 return -ENODEV;
239
240         if (!tty->port.count)
241                 return -EINVAL;
242
243         room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
244         if (room < 0)
245                 room = 0;
246
247         return room;
248 }
249
250 static int ipwireless_get_serial_info(struct ipw_tty *tty,
251                                       struct serial_struct __user *retinfo)
252 {
253         struct serial_struct tmp;
254
255         if (!retinfo)
256                 return (-EFAULT);
257
258         memset(&tmp, 0, sizeof(tmp));
259         tmp.type = PORT_UNKNOWN;
260         tmp.line = tty->index;
261         tmp.port = 0;
262         tmp.irq = 0;
263         tmp.flags = 0;
264         tmp.baud_base = 115200;
265         tmp.close_delay = 0;
266         tmp.closing_wait = 0;
267         tmp.custom_divisor = 0;
268         tmp.hub6 = 0;
269         if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
270                 return -EFAULT;
271
272         return 0;
273 }
274
275 static int ipw_chars_in_buffer(struct tty_struct *linux_tty)
276 {
277         struct ipw_tty *tty = linux_tty->driver_data;
278
279         if (!tty)
280                 return 0;
281
282         if (!tty->port.count)
283                 return 0;
284
285         return tty->tx_bytes_queued;
286 }
287
288 static int get_control_lines(struct ipw_tty *tty)
289 {
290         unsigned int my = tty->control_lines;
291         unsigned int out = 0;
292
293         if (my & IPW_CONTROL_LINE_RTS)
294                 out |= TIOCM_RTS;
295         if (my & IPW_CONTROL_LINE_DTR)
296                 out |= TIOCM_DTR;
297         if (my & IPW_CONTROL_LINE_CTS)
298                 out |= TIOCM_CTS;
299         if (my & IPW_CONTROL_LINE_DSR)
300                 out |= TIOCM_DSR;
301         if (my & IPW_CONTROL_LINE_DCD)
302                 out |= TIOCM_CD;
303
304         return out;
305 }
306
307 static int set_control_lines(struct ipw_tty *tty, unsigned int set,
308                              unsigned int clear)
309 {
310         int ret;
311
312         if (set & TIOCM_RTS) {
313                 ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 1);
314                 if (ret)
315                         return ret;
316                 if (tty->secondary_channel_idx != -1) {
317                         ret = ipwireless_set_RTS(tty->hardware,
318                                           tty->secondary_channel_idx, 1);
319                         if (ret)
320                                 return ret;
321                 }
322         }
323         if (set & TIOCM_DTR) {
324                 ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 1);
325                 if (ret)
326                         return ret;
327                 if (tty->secondary_channel_idx != -1) {
328                         ret = ipwireless_set_DTR(tty->hardware,
329                                           tty->secondary_channel_idx, 1);
330                         if (ret)
331                                 return ret;
332                 }
333         }
334         if (clear & TIOCM_RTS) {
335                 ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 0);
336                 if (tty->secondary_channel_idx != -1) {
337                         ret = ipwireless_set_RTS(tty->hardware,
338                                           tty->secondary_channel_idx, 0);
339                         if (ret)
340                                 return ret;
341                 }
342         }
343         if (clear & TIOCM_DTR) {
344                 ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 0);
345                 if (tty->secondary_channel_idx != -1) {
346                         ret = ipwireless_set_DTR(tty->hardware,
347                                           tty->secondary_channel_idx, 0);
348                         if (ret)
349                                 return ret;
350                 }
351         }
352         return 0;
353 }
354
355 static int ipw_tiocmget(struct tty_struct *linux_tty)
356 {
357         struct ipw_tty *tty = linux_tty->driver_data;
358         /* FIXME: Exactly how is the tty object locked here .. */
359
360         if (!tty)
361                 return -ENODEV;
362
363         if (!tty->port.count)
364                 return -EINVAL;
365
366         return get_control_lines(tty);
367 }
368
369 static int
370 ipw_tiocmset(struct tty_struct *linux_tty,
371              unsigned int set, unsigned int clear)
372 {
373         struct ipw_tty *tty = linux_tty->driver_data;
374         /* FIXME: Exactly how is the tty object locked here .. */
375
376         if (!tty)
377                 return -ENODEV;
378
379         if (!tty->port.count)
380                 return -EINVAL;
381
382         return set_control_lines(tty, set, clear);
383 }
384
385 static int ipw_ioctl(struct tty_struct *linux_tty,
386                      unsigned int cmd, unsigned long arg)
387 {
388         struct ipw_tty *tty = linux_tty->driver_data;
389
390         if (!tty)
391                 return -ENODEV;
392
393         if (!tty->port.count)
394                 return -EINVAL;
395
396         /* FIXME: Exactly how is the tty object locked here .. */
397
398         switch (cmd) {
399         case TIOCGSERIAL:
400                 return ipwireless_get_serial_info(tty, (void __user *) arg);
401
402         case TIOCSSERIAL:
403                 return 0;       /* Keeps the PCMCIA scripts happy. */
404         }
405
406         if (tty->tty_type == TTYTYPE_MODEM) {
407                 switch (cmd) {
408                 case PPPIOCGCHAN:
409                         {
410                                 int chan = ipwireless_ppp_channel_index(
411                                                         tty->network);
412
413                                 if (chan < 0)
414                                         return -ENODEV;
415                                 if (put_user(chan, (int __user *) arg))
416                                         return -EFAULT;
417                         }
418                         return 0;
419
420                 case PPPIOCGUNIT:
421                         {
422                                 int unit = ipwireless_ppp_unit_number(
423                                                 tty->network);
424
425                                 if (unit < 0)
426                                         return -ENODEV;
427                                 if (put_user(unit, (int __user *) arg))
428                                         return -EFAULT;
429                         }
430                         return 0;
431
432                 case FIONREAD:
433                         {
434                                 int val = 0;
435
436                                 if (put_user(val, (int __user *) arg))
437                                         return -EFAULT;
438                         }
439                         return 0;
440                 case TCFLSH:
441                         return tty_perform_flush(linux_tty, arg);
442                 }
443         }
444         return -ENOIOCTLCMD;
445 }
446
447 static int add_tty(int j,
448                     struct ipw_hardware *hardware,
449                     struct ipw_network *network, int channel_idx,
450                     int secondary_channel_idx, int tty_type)
451 {
452         ttys[j] = kzalloc(sizeof(struct ipw_tty), GFP_KERNEL);
453         if (!ttys[j])
454                 return -ENOMEM;
455         ttys[j]->index = j;
456         ttys[j]->hardware = hardware;
457         ttys[j]->channel_idx = channel_idx;
458         ttys[j]->secondary_channel_idx = secondary_channel_idx;
459         ttys[j]->network = network;
460         ttys[j]->tty_type = tty_type;
461         mutex_init(&ttys[j]->ipw_tty_mutex);
462         tty_port_init(&ttys[j]->port);
463
464         tty_port_register_device(&ttys[j]->port, ipw_tty_driver, j, NULL);
465         ipwireless_associate_network_tty(network, channel_idx, ttys[j]);
466
467         if (secondary_channel_idx != -1)
468                 ipwireless_associate_network_tty(network,
469                                                  secondary_channel_idx,
470                                                  ttys[j]);
471         /* check if we provide raw device (if loopback is enabled) */
472         if (get_tty(j))
473                 printk(KERN_INFO IPWIRELESS_PCCARD_NAME
474                        ": registering %s device ttyIPWp%d\n",
475                        tty_type_name(tty_type), j);
476
477         return 0;
478 }
479
480 struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hardware,
481                                       struct ipw_network *network)
482 {
483         int i, j;
484
485         for (i = 0; i < IPWIRELESS_PCMCIA_MINOR_RANGE; i++) {
486                 int allfree = 1;
487
488                 for (j = i; j < IPWIRELESS_PCMCIA_MINORS;
489                                 j += IPWIRELESS_PCMCIA_MINOR_RANGE)
490                         if (ttys[j] != NULL) {
491                                 allfree = 0;
492                                 break;
493                         }
494
495                 if (allfree) {
496                         j = i;
497
498                         if (add_tty(j, hardware, network,
499                                         IPW_CHANNEL_DIALLER, IPW_CHANNEL_RAS,
500                                         TTYTYPE_MODEM))
501                                 return NULL;
502
503                         j += IPWIRELESS_PCMCIA_MINOR_RANGE;
504                         if (add_tty(j, hardware, network,
505                                         IPW_CHANNEL_DIALLER, -1,
506                                         TTYTYPE_MONITOR))
507                                 return NULL;
508
509                         j += IPWIRELESS_PCMCIA_MINOR_RANGE;
510                         if (add_tty(j, hardware, network,
511                                         IPW_CHANNEL_RAS, -1,
512                                         TTYTYPE_RAS_RAW))
513                                 return NULL;
514
515                         return ttys[i];
516                 }
517         }
518         return NULL;
519 }
520
521 /*
522  * Must be called before ipwireless_network_free().
523  */
524 void ipwireless_tty_free(struct ipw_tty *tty)
525 {
526         int j;
527         struct ipw_network *network = ttys[tty->index]->network;
528
529         for (j = tty->index; j < IPWIRELESS_PCMCIA_MINORS;
530                         j += IPWIRELESS_PCMCIA_MINOR_RANGE) {
531                 struct ipw_tty *ttyj = ttys[j];
532
533                 if (ttyj) {
534                         mutex_lock(&ttyj->ipw_tty_mutex);
535                         if (get_tty(j))
536                                 printk(KERN_INFO IPWIRELESS_PCCARD_NAME
537                                        ": deregistering %s device ttyIPWp%d\n",
538                                        tty_type_name(ttyj->tty_type), j);
539                         ttyj->closing = 1;
540                         if (ttyj->port.tty != NULL) {
541                                 mutex_unlock(&ttyj->ipw_tty_mutex);
542                                 tty_vhangup(ttyj->port.tty);
543                                 /* FIXME: Exactly how is the tty object locked here
544                                    against a parallel ioctl etc */
545                                 /* FIXME2: hangup does not mean all processes
546                                  * are gone */
547                                 mutex_lock(&ttyj->ipw_tty_mutex);
548                         }
549                         while (ttyj->port.count)
550                                 do_ipw_close(ttyj);
551                         ipwireless_disassociate_network_ttys(network,
552                                                              ttyj->channel_idx);
553                         tty_unregister_device(ipw_tty_driver, j);
554                         tty_port_destroy(&ttyj->port);
555                         ttys[j] = NULL;
556                         mutex_unlock(&ttyj->ipw_tty_mutex);
557                         kfree(ttyj);
558                 }
559         }
560 }
561
562 static const struct tty_operations tty_ops = {
563         .open = ipw_open,
564         .close = ipw_close,
565         .hangup = ipw_hangup,
566         .write = ipw_write,
567         .write_room = ipw_write_room,
568         .ioctl = ipw_ioctl,
569         .chars_in_buffer = ipw_chars_in_buffer,
570         .tiocmget = ipw_tiocmget,
571         .tiocmset = ipw_tiocmset,
572 };
573
574 int ipwireless_tty_init(void)
575 {
576         int result;
577
578         ipw_tty_driver = alloc_tty_driver(IPWIRELESS_PCMCIA_MINORS);
579         if (!ipw_tty_driver)
580                 return -ENOMEM;
581
582         ipw_tty_driver->driver_name = IPWIRELESS_PCCARD_NAME;
583         ipw_tty_driver->name = "ttyIPWp";
584         ipw_tty_driver->major = 0;
585         ipw_tty_driver->minor_start = IPWIRELESS_PCMCIA_START;
586         ipw_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
587         ipw_tty_driver->subtype = SERIAL_TYPE_NORMAL;
588         ipw_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
589         ipw_tty_driver->init_termios = tty_std_termios;
590         ipw_tty_driver->init_termios.c_cflag =
591             B9600 | CS8 | CREAD | HUPCL | CLOCAL;
592         ipw_tty_driver->init_termios.c_ispeed = 9600;
593         ipw_tty_driver->init_termios.c_ospeed = 9600;
594         tty_set_operations(ipw_tty_driver, &tty_ops);
595         result = tty_register_driver(ipw_tty_driver);
596         if (result) {
597                 printk(KERN_ERR IPWIRELESS_PCCARD_NAME
598                        ": failed to register tty driver\n");
599                 put_tty_driver(ipw_tty_driver);
600                 return result;
601         }
602
603         return 0;
604 }
605
606 void ipwireless_tty_release(void)
607 {
608         int ret;
609
610         ret = tty_unregister_driver(ipw_tty_driver);
611         put_tty_driver(ipw_tty_driver);
612         if (ret != 0)
613                 printk(KERN_ERR IPWIRELESS_PCCARD_NAME
614                         ": tty_unregister_driver failed with code %d\n", ret);
615 }
616
617 int ipwireless_tty_is_modem(struct ipw_tty *tty)
618 {
619         return tty->tty_type == TTYTYPE_MODEM;
620 }
621
622 void
623 ipwireless_tty_notify_control_line_change(struct ipw_tty *tty,
624                                           unsigned int channel_idx,
625                                           unsigned int control_lines,
626                                           unsigned int changed_mask)
627 {
628         unsigned int old_control_lines = tty->control_lines;
629
630         tty->control_lines = (tty->control_lines & ~changed_mask)
631                 | (control_lines & changed_mask);
632
633         /*
634          * If DCD is de-asserted, we close the tty so pppd can tell that we
635          * have gone offline.
636          */
637         if ((old_control_lines & IPW_CONTROL_LINE_DCD)
638                         && !(tty->control_lines & IPW_CONTROL_LINE_DCD)
639                         && tty->port.tty) {
640                 tty_hangup(tty->port.tty);
641         }
642 }
643