This source file includes following definitions.
- wait_until_sent
- unset_locked_termios
- set_termios
- get_termio
- inq_canon
- n_tty_ioctl
1
2
3
4
5
6
7
8
9
10
11 #include <linux/types.h>
12 #include <linux/termios.h>
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/config.h>
16 #include <linux/kernel.h>
17 #include <linux/major.h>
18 #include <linux/tty.h>
19 #include <linux/fcntl.h>
20 #include <linux/string.h>
21
22 #include <asm/io.h>
23 #include <asm/bitops.h>
24 #include <asm/segment.h>
25 #include <asm/system.h>
26
27 #undef DEBUG
28 #ifdef DEBUG
29 # define PRINTK(x) printk (x)
30 #else
31 # define PRINTK(x)
32 #endif
33
34
35
36
37 #define TERMIOS_FLUSH 1
38 #define TERMIOS_WAIT 2
39 #define TERMIOS_TERMIO 4
40
41 void wait_until_sent(struct tty_struct * tty, int timeout)
42 {
43 struct wait_queue wait = { current, NULL };
44
45 if (!tty->driver.chars_in_buffer ||
46 !tty->driver.chars_in_buffer(tty))
47 return;
48 add_wait_queue(&tty->write_wait, &wait);
49 current->counter = 0;
50 if (timeout)
51 current->timeout = timeout + jiffies;
52 else
53 current->timeout = (unsigned) -1;
54 do {
55 current->state = TASK_INTERRUPTIBLE;
56 if (current->signal & ~current->blocked)
57 break;
58 if (!tty->driver.chars_in_buffer(tty))
59 break;
60 schedule();
61 } while (current->timeout);
62 current->state = TASK_RUNNING;
63 remove_wait_queue(&tty->write_wait, &wait);
64 }
65
66 static void unset_locked_termios(struct termios *termios,
67 struct termios *old,
68 struct termios *locked)
69 {
70 int i;
71
72 #define NOSET_MASK(x,y,z) (x = ((x) & ~(z)) | ((y) & (z)))
73
74 if (!locked) {
75 printk("Warning?!? termios_locked is NULL.\n");
76 return;
77 }
78
79 NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
80 NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
81 NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
82 NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
83 termios->c_line = locked->c_line ? old->c_line : termios->c_line;
84 for (i=0; i < NCCS; i++)
85 termios->c_cc[i] = locked->c_cc[i] ?
86 old->c_cc[i] : termios->c_cc[i];
87 }
88
89 static int set_termios(struct tty_struct * tty, unsigned long arg, int opt)
90 {
91 struct termio tmp_termio;
92 struct termios tmp_termios;
93 struct termios old_termios = *tty->termios;
94 int retval, canon_change;
95
96 retval = tty_check_change(tty);
97 if (retval)
98 return retval;
99
100 if (opt & TERMIOS_TERMIO) {
101 tmp_termios = *tty->termios;
102 memcpy_fromfs(&tmp_termio, (struct termio *) arg,
103 sizeof (struct termio));
104
105 #define SET_LOW_BITS(x,y) ((x) = (0xffff0000 & (x)) | (y))
106 SET_LOW_BITS(tmp_termios.c_iflag, tmp_termio.c_iflag);
107 SET_LOW_BITS(tmp_termios.c_oflag, tmp_termio.c_oflag);
108 SET_LOW_BITS(tmp_termios.c_cflag, tmp_termio.c_cflag);
109 SET_LOW_BITS(tmp_termios.c_lflag, tmp_termio.c_lflag);
110 memcpy(&tmp_termios.c_cc, &tmp_termio.c_cc, NCC);
111 #undef SET_LOW_BITS
112 } else
113 memcpy_fromfs(&tmp_termios, (struct termios *) arg,
114 sizeof (struct termios));
115
116 if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer)
117 tty->ldisc.flush_buffer(tty);
118
119 if (opt & TERMIOS_WAIT)
120 wait_until_sent(tty, 0);
121
122 cli();
123 *tty->termios = tmp_termios;
124 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
125 canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
126 if (canon_change) {
127 memset(&tty->read_flags, 0, sizeof tty->read_flags);
128 tty->canon_head = tty->read_tail;
129 tty->canon_data = 0;
130 tty->erasing = 0;
131 }
132 sti();
133 if (canon_change && !L_ICANON(tty) && tty->read_cnt)
134
135 wake_up_interruptible(&tty->read_wait);
136
137
138
139 if (tty->link && tty->link->packet) {
140 int old_flow = ((old_termios.c_iflag & IXON) &&
141 (old_termios.c_cc[VSTOP] == '\023') &&
142 (old_termios.c_cc[VSTART] == '\021'));
143 int new_flow = (I_IXON(tty) &&
144 STOP_CHAR(tty) == '\023' &&
145 START_CHAR(tty) == '\021');
146 if (old_flow != new_flow) {
147 tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
148 if (new_flow)
149 tty->ctrl_status |= TIOCPKT_DOSTOP;
150 else
151 tty->ctrl_status |= TIOCPKT_NOSTOP;
152 wake_up_interruptible(&tty->link->read_wait);
153 }
154 }
155
156 if (tty->driver.set_termios)
157 (*tty->driver.set_termios)(tty, &old_termios);
158
159 if (tty->ldisc.set_termios)
160 (*tty->ldisc.set_termios)(tty, &old_termios);
161
162 return 0;
163 }
164
165 static int get_termio(struct tty_struct * tty, struct termio * termio)
166 {
167 int i;
168 struct termio tmp_termio;
169
170 i = verify_area(VERIFY_WRITE, termio, sizeof (struct termio));
171 if (i)
172 return i;
173 tmp_termio.c_iflag = tty->termios->c_iflag;
174 tmp_termio.c_oflag = tty->termios->c_oflag;
175 tmp_termio.c_cflag = tty->termios->c_cflag;
176 tmp_termio.c_lflag = tty->termios->c_lflag;
177 tmp_termio.c_line = tty->termios->c_line;
178 for(i=0 ; i < NCC ; i++)
179 tmp_termio.c_cc[i] = tty->termios->c_cc[i];
180 memcpy_tofs(termio, &tmp_termio, sizeof (struct termio));
181 return 0;
182 }
183
184 static unsigned long inq_canon(struct tty_struct * tty)
185 {
186 int nr, head, tail;
187
188 if (!tty->canon_data || !tty->read_buf)
189 return 0;
190 head = tty->canon_head;
191 tail = tty->read_tail;
192 nr = (head - tail) & (N_TTY_BUF_SIZE-1);
193
194 while (head != tail) {
195 if (test_bit(tail, &tty->read_flags) &&
196 tty->read_buf[tail] == __DISABLED_CHAR)
197 nr--;
198 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
199 }
200 return nr;
201 }
202
203 int n_tty_ioctl(struct tty_struct * tty, struct file * file,
204 unsigned int cmd, unsigned long arg)
205 {
206 struct tty_struct * real_tty;
207 int retval;
208 int opt = 0;
209
210 if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
211 tty->driver.subtype == PTY_TYPE_MASTER)
212 real_tty = tty->link;
213 else
214 real_tty = tty;
215
216 switch (cmd) {
217 case TCGETS:
218 retval = verify_area(VERIFY_WRITE, (void *) arg,
219 sizeof (struct termios));
220 if (retval)
221 return retval;
222 memcpy_tofs((struct termios *) arg,
223 real_tty->termios,
224 sizeof (struct termios));
225 return 0;
226 case TCSETSF:
227 opt |= TERMIOS_FLUSH;
228 case TCSETSW:
229 opt |= TERMIOS_WAIT;
230 case TCSETS:
231 return set_termios(real_tty, arg, opt);
232 case TCGETA:
233 return get_termio(real_tty,(struct termio *) arg);
234 case TCSETAF:
235 opt |= TERMIOS_FLUSH;
236 case TCSETAW:
237 opt |= TERMIOS_WAIT;
238 case TCSETA:
239 return set_termios(real_tty, arg, opt|TERMIOS_TERMIO);
240 case TCXONC:
241 retval = tty_check_change(tty);
242 if (retval)
243 return retval;
244 switch (arg) {
245 case TCOOFF:
246 stop_tty(tty);
247 break;
248 case TCOON:
249 start_tty(tty);
250 break;
251 case TCIOFF:
252 if (STOP_CHAR(tty) != __DISABLED_CHAR)
253 tty->driver.write(tty, 0,
254 &STOP_CHAR(tty), 1);
255 break;
256 case TCION:
257 if (START_CHAR(tty) != __DISABLED_CHAR)
258 tty->driver.write(tty, 0,
259 &START_CHAR(tty), 1);
260 break;
261 default:
262 return -EINVAL;
263 }
264 return 0;
265 case TCFLSH:
266 retval = tty_check_change(tty);
267 if (retval)
268 return retval;
269 switch (arg) {
270 case TCIFLUSH:
271 if (tty->ldisc.flush_buffer)
272 tty->ldisc.flush_buffer(tty);
273 break;
274 case TCIOFLUSH:
275 if (tty->ldisc.flush_buffer)
276 tty->ldisc.flush_buffer(tty);
277
278 case TCOFLUSH:
279 if (tty->driver.flush_buffer)
280 tty->driver.flush_buffer(tty);
281 break;
282 default:
283 return -EINVAL;
284 }
285 return 0;
286 case TIOCOUTQ:
287 retval = verify_area(VERIFY_WRITE, (void *) arg,
288 sizeof (unsigned long));
289 if (retval)
290 return retval;
291 if (tty->driver.chars_in_buffer)
292 put_fs_long(tty->driver.chars_in_buffer(tty),
293 (unsigned long *) arg);
294 else
295 put_fs_long(0, (unsigned long *) arg);
296 return 0;
297 case TIOCINQ:
298 retval = verify_area(VERIFY_WRITE, (void *) arg,
299 sizeof (unsigned long));
300 if (retval)
301 return retval;
302 if (L_ICANON(tty))
303 put_fs_long(inq_canon(tty),
304 (unsigned long *) arg);
305 else
306 put_fs_long(tty->read_cnt,
307 (unsigned long *) arg);
308 return 0;
309 case TIOCGLCKTRMIOS:
310 arg = get_fs_long((unsigned long *) arg);
311 retval = verify_area(VERIFY_WRITE, (void *) arg,
312 sizeof (struct termios));
313 if (retval)
314 return retval;
315 memcpy_tofs((struct termios *) arg,
316 &real_tty->termios_locked,
317 sizeof (struct termios));
318 return 0;
319 case TIOCSLCKTRMIOS:
320 if (!suser())
321 return -EPERM;
322 arg = get_fs_long((unsigned long *) arg);
323 memcpy_fromfs(&real_tty->termios_locked,
324 (struct termios *) arg,
325 sizeof (struct termios));
326 return 0;
327 case TIOCPKT:
328 if (tty->driver.type != TTY_DRIVER_TYPE_PTY ||
329 tty->driver.subtype != PTY_TYPE_MASTER)
330 return -ENOTTY;
331 retval = verify_area(VERIFY_READ, (void *) arg,
332 sizeof (unsigned long));
333 if (retval)
334 return retval;
335 if (get_fs_long(arg)) {
336 if (!tty->packet) {
337 tty->packet = 1;
338 tty->link->ctrl_status = 0;
339 }
340 } else
341 tty->packet = 0;
342 return 0;
343
344
345 case TCSBRK: case TCSBRKP:
346 retval = tty_check_change(tty);
347 if (retval)
348 return retval;
349 wait_until_sent(tty, 0);
350 if (!tty->driver.ioctl)
351 return 0;
352 tty->driver.ioctl(tty, file, cmd, arg);
353 return 0;
354 default:
355 return -ENOIOCTLCMD;
356 }
357 }