Merge tag 'stable/for-linus-3.16-rc1-tag' of git://git.kernel.org/pub/scm/linux/kerne...
[deliverable/linux.git] / drivers / staging / dgrp / dgrp_common.c
CommitLineData
0b52b749
BP
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 */
47void 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}
This page took 0.132831 seconds and 5 git commands to generate.