Linux-libre 3.14.42-gnu
[librecmc/linux-libre.git] / drivers / staging / dgrp / dgrp_common.c
1 /*
2  *
3  * Copyright 1999 Digi International (www.digi.com)
4  *     James Puzzo <jamesp at digi dot com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
13  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  * PURPOSE.  See the GNU General Public License for more details.
15  *
16  */
17
18 /*
19  *
20  *  Filename:
21  *
22  *     dgrp_common.c
23  *
24  *  Description:
25  *
26  *     Definitions of global variables and functions which are either
27  *     shared by the tty, mon, and net drivers; or which cross them
28  *     functionally (like the poller).
29  *
30  *  Author:
31  *
32  *     James A. Puzzo
33  *
34  */
35
36 #include <linux/errno.h>
37 #include <linux/tty.h>
38 #include <linux/sched.h>
39 #include <linux/cred.h>
40
41 #include "dgrp_common.h"
42
43 /**
44  * dgrp_carrier -- check for carrier change state and act
45  * @ch: struct ch_struct *
46  */
47 void dgrp_carrier(struct ch_struct *ch)
48 {
49         struct nd_struct *nd;
50
51         int virt_carrier = 0;
52         int phys_carrier = 0;
53
54         /* fix case when the tty has already closed. */
55
56         if (!ch)
57                 return;
58         nd  = ch->ch_nd;
59         if (!nd)
60                 return;
61
62         /*
63          *  If we are currently waiting to determine the status of the port,
64          *  we don't yet know the state of the modem lines.  As a result,
65          *  we ignore state changes when we are waiting for the modem lines
66          *  to be established.  We know, as a result of code in dgrp_net_ops,
67          *  that we will be called again immediately following the reception
68          *  of the status message with the true modem status flags in it.
69          */
70         if (ch->ch_expect & RR_STATUS)
71                 return;
72
73         /*
74          * If CH_HANGUP is set, we gotta keep trying to get all the processes
75          * that have the port open to close the port.
76          * So lets just keep sending a hangup every time we get here.
77          */
78         if ((ch->ch_flag & CH_HANGUP) &&
79             (ch->ch_tun.un_open_count > 0))
80                 tty_hangup(ch->ch_tun.un_tty);
81
82         /*
83          *  Compute the effective state of both the physical and virtual
84          *  senses of carrier.
85          */
86
87         if (ch->ch_s_mlast & DM_CD)
88                 phys_carrier = 1;
89
90         if ((ch->ch_s_mlast & DM_CD) ||
91             (ch->ch_digi.digi_flags & DIGI_FORCEDCD) ||
92             (ch->ch_flag & CH_CLOCAL))
93                 virt_carrier = 1;
94
95         /*
96          *  Test for a VIRTUAL carrier transition to HIGH.
97          *
98          *  The CH_HANGUP condition is intended to prevent any action
99          *  except for close.  As a result, we ignore positive carrier
100          *  transitions during CH_HANGUP.
101          */
102         if (((ch->ch_flag & CH_HANGUP)  == 0) &&
103             ((ch->ch_flag & CH_VIRT_CD) == 0) &&
104             (virt_carrier == 1)) {
105                 /*
106                  * When carrier rises, wake any threads waiting
107                  * for carrier in the open routine.
108                  */
109                 nd->nd_tx_work = 1;
110
111                 if (waitqueue_active(&ch->ch_flag_wait))
112                         wake_up_interruptible(&ch->ch_flag_wait);
113         }
114
115         /*
116          *  Test for a PHYSICAL transition to low, so long as we aren't
117          *  currently ignoring physical transitions (which is what "virtual
118          *  carrier" indicates).
119          *
120          *  The transition of the virtual carrier to low really doesn't
121          *  matter... it really only means "ignore carrier state", not
122          *  "make pretend that carrier is there".
123          */
124         if ((virt_carrier == 0) &&
125             ((ch->ch_flag & CH_PHYS_CD) != 0) &&
126             (phys_carrier == 0)) {
127                 /*
128                  * When carrier drops:
129                  *
130                  *   Do a Hard Hangup if that is called for.
131                  *
132                  *   Drop carrier on all open units.
133                  *
134                  *   Flush queues, waking up any task waiting in the
135                  *   line discipline.
136                  *
137                  *   Send a hangup to the control terminal.
138                  *
139                  *   Enable all select calls.
140                  */
141
142                 nd->nd_tx_work = 1;
143
144                 ch->ch_flag &= ~(CH_LOW | CH_EMPTY | CH_DRAIN | CH_INPUT);
145
146                 if (waitqueue_active(&ch->ch_flag_wait))
147                         wake_up_interruptible(&ch->ch_flag_wait);
148
149                 if (ch->ch_tun.un_open_count > 0)
150                         tty_hangup(ch->ch_tun.un_tty);
151
152                 if (ch->ch_pun.un_open_count > 0)
153                         tty_hangup(ch->ch_pun.un_tty);
154         }
155
156         /*
157          *  Make sure that our cached values reflect the current reality.
158          */
159         if (virt_carrier == 1)
160                 ch->ch_flag |= CH_VIRT_CD;
161         else
162                 ch->ch_flag &= ~CH_VIRT_CD;
163
164         if (phys_carrier == 1)
165                 ch->ch_flag |= CH_PHYS_CD;
166         else
167                 ch->ch_flag &= ~CH_PHYS_CD;
168
169 }