5 #include <linux/types.h>
6 #include <linux/errno.h>
8 #include <linux/tty_driver.h>
9 #include <linux/tty_flip.h>
10 #include <linux/serial.h>
11 #include <linux/timer.h>
12 #include <linux/string.h>
13 #include <linux/slab.h>
14 #include <linux/sched.h>
15 #include <linux/init.h>
16 #include <linux/wait.h>
17 #include <linux/bitops.h>
18 #include <linux/delay.h>
19 #include <linux/module.h>
21 void tty_port_init(struct tty_port *port)
23 memset(port, 0, sizeof(*port));
24 init_waitqueue_head(&port->open_wait);
25 init_waitqueue_head(&port->close_wait);
26 mutex_init(&port->mutex);
27 spin_lock_init(&port->lock);
28 port->close_delay = (50 * HZ) / 100;
29 port->closing_wait = (3000 * HZ) / 100;
31 EXPORT_SYMBOL(tty_port_init);
33 int tty_port_alloc_xmit_buf(struct tty_port *port)
35 /* We may sleep in get_zeroed_page() */
36 mutex_lock(&port->mutex);
37 if (port->xmit_buf == NULL)
38 port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
39 mutex_unlock(&port->mutex);
40 if (port->xmit_buf == NULL)
44 EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
46 void tty_port_free_xmit_buf(struct tty_port *port)
48 mutex_lock(&port->mutex);
49 if (port->xmit_buf != NULL) {
50 free_page((unsigned long)port->xmit_buf);
51 port->xmit_buf = NULL;
53 mutex_unlock(&port->mutex);
55 EXPORT_SYMBOL(tty_port_free_xmit_buf);
59 * tty_port_tty_get - get a tty reference
62 * Return a refcount protected tty instance or NULL if the port is not
63 * associated with a tty (eg due to close or hangup)
66 struct tty_struct *tty_port_tty_get(struct tty_port *port)
69 struct tty_struct *tty;
71 spin_lock_irqsave(&port->lock, flags);
72 tty = tty_kref_get(port->tty);
73 spin_unlock_irqrestore(&port->lock, flags);
76 EXPORT_SYMBOL(tty_port_tty_get);
79 * tty_port_tty_set - set the tty of a port
83 * Associate the port and tty pair. Manages any internal refcounts.
84 * Pass NULL to deassociate a port
87 void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
91 spin_lock_irqsave(&port->lock, flags);
93 tty_kref_put(port->tty);
94 port->tty = tty_kref_get(tty);
95 spin_unlock_irqrestore(&port->lock, flags);
97 EXPORT_SYMBOL(tty_port_tty_set);
100 * tty_port_hangup - hangup helper
103 * Perform port level tty hangup flag and count changes. Drop the tty
107 void tty_port_hangup(struct tty_port *port)
111 spin_lock_irqsave(&port->lock, flags);
113 port->flags &= ~ASYNC_NORMAL_ACTIVE;
115 tty_kref_put(port->tty);
117 spin_unlock_irqrestore(&port->lock, flags);
118 wake_up_interruptible(&port->open_wait);
120 EXPORT_SYMBOL(tty_port_hangup);
123 * tty_port_carrier_raised - carrier raised check
126 * Wrapper for the carrier detect logic. For the moment this is used
127 * to hide some internal details. This will eventually become entirely
128 * internal to the tty port.
131 int tty_port_carrier_raised(struct tty_port *port)
133 if (port->ops->carrier_raised == NULL)
135 return port->ops->carrier_raised(port);
137 EXPORT_SYMBOL(tty_port_carrier_raised);
140 * tty_port_raise_dtr_rts - Raise DTR/RTS
143 * Wrapper for the DTR/RTS raise logic. For the moment this is used
144 * to hide some internal details. This will eventually become entirely
145 * internal to the tty port.
148 void tty_port_raise_dtr_rts(struct tty_port *port)
150 if (port->ops->dtr_rts)
151 port->ops->dtr_rts(port, 1);
153 EXPORT_SYMBOL(tty_port_raise_dtr_rts);
156 * tty_port_lower_dtr_rts - Lower DTR/RTS
159 * Wrapper for the DTR/RTS raise logic. For the moment this is used
160 * to hide some internal details. This will eventually become entirely
161 * internal to the tty port.
164 void tty_port_lower_dtr_rts(struct tty_port *port)
166 if (port->ops->dtr_rts)
167 port->ops->dtr_rts(port, 0);
169 EXPORT_SYMBOL(tty_port_lower_dtr_rts);
172 * tty_port_block_til_ready - Waiting logic for tty open
173 * @port: the tty port being opened
174 * @tty: the tty device being bound
175 * @filp: the file pointer of the opener
177 * Implement the core POSIX/SuS tty behaviour when opening a tty device.
179 * - hangup (both before and during)
180 * - non blocking open
183 * - port flags and counts
185 * The passed tty_port must implement the carrier_raised method if it can
186 * do carrier detect and the dtr_rts method if it supports software
187 * management of these lines. Note that the dtr/rts raise is done each
188 * iteration as a hangup may have previously dropped them while we wait.
191 int tty_port_block_til_ready(struct tty_port *port,
192 struct tty_struct *tty, struct file *filp)
194 int do_clocal = 0, retval;
196 DECLARE_WAITQUEUE(wait, current);
199 /* block if port is in the process of being closed */
200 if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
201 wait_event_interruptible(port->close_wait,
202 !(port->flags & ASYNC_CLOSING));
203 if (port->flags & ASYNC_HUP_NOTIFY)
209 /* if non-blocking mode is set we can pass directly to open unless
210 the port has just hung up or is in another error state */
211 if ((filp->f_flags & O_NONBLOCK) ||
212 (tty->flags & (1 << TTY_IO_ERROR))) {
213 port->flags |= ASYNC_NORMAL_ACTIVE;
220 /* Block waiting until we can proceed. We may need to wait for the
221 carrier, but we must also wait for any close that is in progress
222 before the next open may complete */
226 /* The port lock protects the port counts */
227 spin_lock_irqsave(&port->lock, flags);
228 if (!tty_hung_up_p(filp))
230 port->blocked_open++;
231 spin_unlock_irqrestore(&port->lock, flags);
234 /* Indicate we are open */
235 if (tty->termios->c_cflag & CBAUD)
236 tty_port_raise_dtr_rts(port);
238 prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
239 /* Check for a hangup or uninitialised port. Return accordingly */
240 if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
241 if (port->flags & ASYNC_HUP_NOTIFY)
244 retval = -ERESTARTSYS;
247 /* Probe the carrier. For devices with no carrier detect this
248 will always return true */
249 cd = tty_port_carrier_raised(port);
250 if (!(port->flags & ASYNC_CLOSING) &&
253 if (signal_pending(current)) {
254 retval = -ERESTARTSYS;
259 finish_wait(&port->open_wait, &wait);
261 /* Update counts. A parallel hangup will have set count to zero and
262 we must not mess that up further */
263 spin_lock_irqsave(&port->lock, flags);
264 if (!tty_hung_up_p(filp))
266 port->blocked_open--;
268 port->flags |= ASYNC_NORMAL_ACTIVE;
269 spin_unlock_irqrestore(&port->lock, flags);
273 EXPORT_SYMBOL(tty_port_block_til_ready);
275 int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp)
279 spin_lock_irqsave(&port->lock, flags);
280 if (tty_hung_up_p(filp)) {
281 spin_unlock_irqrestore(&port->lock, flags);
285 if( tty->count == 1 && port->count != 1) {
287 "tty_port_close_start: tty->count = 1 port count = %d.\n",
291 if (--port->count < 0) {
292 printk(KERN_WARNING "tty_port_close_start: count = %d\n",
298 spin_unlock_irqrestore(&port->lock, flags);
301 port->flags |= ASYNC_CLOSING;
303 spin_unlock_irqrestore(&port->lock, flags);
304 /* Don't block on a stalled port, just pull the chain */
305 if (tty->flow_stopped)
306 tty_driver_flush_buffer(tty);
307 if (port->flags & ASYNC_INITIALIZED &&
308 port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
309 tty_wait_until_sent(tty, port->closing_wait);
310 if (port->drain_delay) {
311 unsigned int bps = tty_get_baud_rate(tty);
315 timeout = max_t(long, (HZ * 10 * port->drain_delay) / bps,
319 schedule_timeout_interruptible(timeout);
323 EXPORT_SYMBOL(tty_port_close_start);
325 void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
329 tty_ldisc_flush(tty);
331 if (tty->termios->c_cflag & HUPCL)
332 tty_port_lower_dtr_rts(port);
334 spin_lock_irqsave(&port->lock, flags);
337 if (port->blocked_open) {
338 spin_unlock_irqrestore(&port->lock, flags);
339 if (port->close_delay) {
340 msleep_interruptible(
341 jiffies_to_msecs(port->close_delay));
343 spin_lock_irqsave(&port->lock, flags);
344 wake_up_interruptible(&port->open_wait);
346 port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
347 wake_up_interruptible(&port->close_wait);
348 spin_unlock_irqrestore(&port->lock, flags);
350 EXPORT_SYMBOL(tty_port_close_end);