blob: 9f418bca4a22b37a5f8f9a3b9c6143705de51327 [file] [log] [blame]
Alan Cox9e485652008-10-13 10:37:07 +01001/*
2 * Tty port functions
3 */
4
5#include <linux/types.h>
6#include <linux/errno.h>
7#include <linux/tty.h>
8#include <linux/tty_driver.h>
9#include <linux/tty_flip.h>
Alan Cox3e616962009-01-02 13:45:26 +000010#include <linux/serial.h>
Alan Cox9e485652008-10-13 10:37:07 +010011#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>
20
21void tty_port_init(struct tty_port *port)
22{
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);
Alan Cox4a90f092008-10-13 10:39:46 +010027 spin_lock_init(&port->lock);
Alan Cox9e485652008-10-13 10:37:07 +010028 port->close_delay = (50 * HZ) / 100;
29 port->closing_wait = (3000 * HZ) / 100;
30}
31EXPORT_SYMBOL(tty_port_init);
32
33int tty_port_alloc_xmit_buf(struct tty_port *port)
34{
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)
41 return -ENOMEM;
42 return 0;
43}
44EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
45
46void tty_port_free_xmit_buf(struct tty_port *port)
47{
48 mutex_lock(&port->mutex);
49 if (port->xmit_buf != NULL) {
50 free_page((unsigned long)port->xmit_buf);
51 port->xmit_buf = NULL;
52 }
53 mutex_unlock(&port->mutex);
54}
55EXPORT_SYMBOL(tty_port_free_xmit_buf);
56
57
Alan Cox4a90f092008-10-13 10:39:46 +010058/**
59 * tty_port_tty_get - get a tty reference
60 * @port: tty port
61 *
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)
64 */
65
66struct tty_struct *tty_port_tty_get(struct tty_port *port)
67{
68 unsigned long flags;
69 struct tty_struct *tty;
70
71 spin_lock_irqsave(&port->lock, flags);
72 tty = tty_kref_get(port->tty);
73 spin_unlock_irqrestore(&port->lock, flags);
74 return tty;
75}
76EXPORT_SYMBOL(tty_port_tty_get);
77
78/**
79 * tty_port_tty_set - set the tty of a port
80 * @port: tty port
81 * @tty: the tty
82 *
83 * Associate the port and tty pair. Manages any internal refcounts.
84 * Pass NULL to deassociate a port
85 */
86
87void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
88{
89 unsigned long flags;
90
91 spin_lock_irqsave(&port->lock, flags);
92 if (port->tty)
93 tty_kref_put(port->tty);
Alan Coxcb4bca32008-10-21 13:47:44 +010094 port->tty = tty_kref_get(tty);
Alan Cox4a90f092008-10-13 10:39:46 +010095 spin_unlock_irqrestore(&port->lock, flags);
96}
97EXPORT_SYMBOL(tty_port_tty_set);
Alan Cox31f35932009-01-02 13:45:05 +000098
99/**
Alan Cox3e616962009-01-02 13:45:26 +0000100 * tty_port_hangup - hangup helper
101 * @port: tty port
102 *
103 * Perform port level tty hangup flag and count changes. Drop the tty
104 * reference.
105 */
106
107void tty_port_hangup(struct tty_port *port)
108{
109 unsigned long flags;
110
111 spin_lock_irqsave(&port->lock, flags);
112 port->count = 0;
113 port->flags &= ~ASYNC_NORMAL_ACTIVE;
114 if (port->tty)
115 tty_kref_put(port->tty);
116 port->tty = NULL;
117 spin_unlock_irqrestore(&port->lock, flags);
118 wake_up_interruptible(&port->open_wait);
119}
120EXPORT_SYMBOL(tty_port_hangup);
121
122/**
Alan Cox31f35932009-01-02 13:45:05 +0000123 * tty_port_carrier_raised - carrier raised check
124 * @port: tty port
125 *
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.
129 */
130
131int tty_port_carrier_raised(struct tty_port *port)
132{
133 if (port->ops->carrier_raised == NULL)
134 return 1;
135 return port->ops->carrier_raised(port);
136}
137EXPORT_SYMBOL(tty_port_carrier_raised);
Alan Cox5d951fb2009-01-02 13:45:19 +0000138
139/**
140 * tty_port_raise_dtr_rts - Riase DTR/RTS
141 * @port: tty port
142 *
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.
146 */
147
148void tty_port_raise_dtr_rts(struct tty_port *port)
149{
150 if (port->ops->raise_dtr_rts)
151 port->ops->raise_dtr_rts(port);
152}
153EXPORT_SYMBOL(tty_port_raise_dtr_rts);