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 - Riase 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->raise_dtr_rts)
151 port->ops->raise_dtr_rts(port);
153 EXPORT_SYMBOL(tty_port_raise_dtr_rts);
156 * tty_port_block_til_ready - Waiting logic for tty open
157 * @port: the tty port being opened
158 * @tty: the tty device being bound
159 * @filp: the file pointer of the opener
161 * Implement the core POSIX/SuS tty behaviour when opening a tty device.
163 * - hangup (both before and during)
164 * - non blocking open
167 * - port flags and counts
169 * The passed tty_port must implement the carrier_raised method if it can
170 * do carrier detect and the raise_dtr_rts method if it supports software
171 * management of these lines. Note that the dtr/rts raise is done each
172 * iteration as a hangup may have previously dropped them while we wait.
175 int tty_port_block_til_ready(struct tty_port *port,
176 struct tty_struct *tty, struct file *filp)
178 int do_clocal = 0, retval;
180 DECLARE_WAITQUEUE(wait, current);
183 /* block if port is in the process of being closed */
184 if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
185 interruptible_sleep_on(&port->close_wait);
186 if (port->flags & ASYNC_HUP_NOTIFY)
192 /* if non-blocking mode is set we can pass directly to open unless
193 the port has just hung up or is in another error state */
194 if ((filp->f_flags & O_NONBLOCK) ||
195 (tty->flags & (1 << TTY_IO_ERROR))) {
196 port->flags |= ASYNC_NORMAL_ACTIVE;
203 /* Block waiting until we can proceed. We may need to wait for the
204 carrier, but we must also wait for any close that is in progress
205 before the next open may complete */
208 add_wait_queue(&port->open_wait, &wait);
210 /* The port lock protects the port counts */
211 spin_lock_irqsave(&port->lock, flags);
212 if (!tty_hung_up_p(filp))
214 port->blocked_open++;
215 spin_unlock_irqrestore(&port->lock, flags);
218 /* Indicate we are open */
219 if (tty->termios->c_cflag & CBAUD)
220 tty_port_raise_dtr_rts(port);
222 set_current_state(TASK_INTERRUPTIBLE);
223 /* Check for a hangup or uninitialised port. Return accordingly */
224 if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
225 if (port->flags & ASYNC_HUP_NOTIFY)
228 retval = -ERESTARTSYS;
231 /* Probe the carrier. For devices with no carrier detect this
232 will always return true */
233 cd = tty_port_carrier_raised(port);
234 if (!(port->flags & ASYNC_CLOSING) &&
237 if (signal_pending(current)) {
238 retval = -ERESTARTSYS;
243 set_current_state(TASK_RUNNING);
244 remove_wait_queue(&port->open_wait, &wait);
246 /* Update counts. A parallel hangup will have set count to zero and
247 we must not mess that up further */
248 spin_lock_irqsave(&port->lock, flags);
249 if (!tty_hung_up_p(filp))
251 port->blocked_open--;
253 port->flags |= ASYNC_NORMAL_ACTIVE;
254 spin_unlock_irqrestore(&port->lock, flags);
258 EXPORT_SYMBOL(tty_port_block_til_ready);
260 int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp)
264 spin_lock_irqsave(&port->lock, flags);
265 if (tty_hung_up_p(filp)) {
266 spin_unlock_irqrestore(&port->lock, flags);
270 if( tty->count == 1 && port->count != 1) {
272 "tty_port_close_start: tty->count = 1 port count = %d.\n",
276 if (--port->count < 0) {
277 printk(KERN_WARNING "tty_port_close_start: count = %d\n",
283 spin_unlock_irqrestore(&port->lock, flags);
286 port->flags |= ASYNC_CLOSING;
288 spin_unlock_irqrestore(&port->lock, flags);
289 /* Don't block on a stalled port, just pull the chain */
290 if (tty->flow_stopped)
291 tty_driver_flush_buffer(tty);
292 if (port->flags & ASYNC_INITIALIZED &&
293 port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
294 tty_wait_until_sent(tty, port->closing_wait);
297 EXPORT_SYMBOL(tty_port_close_start);
299 void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
303 tty_ldisc_flush(tty);
305 spin_lock_irqsave(&port->lock, flags);
308 if (port->blocked_open) {
309 spin_unlock_irqrestore(&port->lock, flags);
310 if (port->close_delay) {
311 msleep_interruptible(
312 jiffies_to_msecs(port->close_delay));
314 spin_lock_irqsave(&port->lock, flags);
315 wake_up_interruptible(&port->open_wait);
317 port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
318 wake_up_interruptible(&port->close_wait);
319 spin_unlock_irqrestore(&port->lock, flags);
321 EXPORT_SYMBOL(tty_port_close_end);