summaryrefslogtreecommitdiffstats
path: root/src/kernel/chr_drv/tty_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/chr_drv/tty_ioctl.c')
-rw-r--r--src/kernel/chr_drv/tty_ioctl.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/src/kernel/chr_drv/tty_ioctl.c b/src/kernel/chr_drv/tty_ioctl.c
new file mode 100644
index 0000000..e4e3745
--- /dev/null
+++ b/src/kernel/chr_drv/tty_ioctl.c
@@ -0,0 +1,204 @@
1/*
2 * linux/kernel/chr_drv/tty_ioctl.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7#include <errno.h>
8#include <termios.h>
9
10#include <linux/sched.h>
11#include <linux/kernel.h>
12#include <linux/tty.h>
13
14#include <asm/io.h>
15#include <asm/segment.h>
16#include <asm/system.h>
17
18static unsigned short quotient[] = {
19 0, 2304, 1536, 1047, 857,
20 768, 576, 384, 192, 96,
21 64, 48, 24, 12, 6, 3
22};
23
24static void change_speed(struct tty_struct * tty)
25{
26 unsigned short port,quot;
27
28 if (!(port = tty->read_q.data))
29 return;
30 quot = quotient[tty->termios.c_cflag & CBAUD];
31 cli();
32 outb_p(0x80,port+3); /* set DLAB */
33 outb_p(quot & 0xff,port); /* LS of divisor */
34 outb_p(quot >> 8,port+1); /* MS of divisor */
35 outb(0x03,port+3); /* reset DLAB */
36 sti();
37}
38
39static void flush(struct tty_queue * queue)
40{
41 cli();
42 queue->head = queue->tail;
43 sti();
44}
45
46static void wait_until_sent(struct tty_struct * tty)
47{
48 /* do nothing - not implemented */
49}
50
51static void send_break(struct tty_struct * tty)
52{
53 /* do nothing - not implemented */
54}
55
56static int get_termios(struct tty_struct * tty, struct termios * termios)
57{
58 int i;
59
60 verify_area(termios, sizeof (*termios));
61 for (i=0 ; i< (sizeof (*termios)) ; i++)
62 put_fs_byte( ((char *)&tty->termios)[i] , i+(char *)termios );
63 return 0;
64}
65
66static int set_termios(struct tty_struct * tty, struct termios * termios)
67{
68 int i;
69
70 for (i=0 ; i< (sizeof (*termios)) ; i++)
71 ((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios);
72 change_speed(tty);
73 return 0;
74}
75
76static int get_termio(struct tty_struct * tty, struct termio * termio)
77{
78 int i;
79 struct termio tmp_termio;
80
81 verify_area(termio, sizeof (*termio));
82 tmp_termio.c_iflag = tty->termios.c_iflag;
83 tmp_termio.c_oflag = tty->termios.c_oflag;
84 tmp_termio.c_cflag = tty->termios.c_cflag;
85 tmp_termio.c_lflag = tty->termios.c_lflag;
86 tmp_termio.c_line = tty->termios.c_line;
87 for(i=0 ; i < NCC ; i++)
88 tmp_termio.c_cc[i] = tty->termios.c_cc[i];
89 for (i=0 ; i< (sizeof (*termio)) ; i++)
90 put_fs_byte( ((char *)&tmp_termio)[i] , i+(char *)termio );
91 return 0;
92}
93
94/*
95 * This only works as the 386 is low-byt-first
96 */
97static int set_termio(struct tty_struct * tty, struct termio * termio)
98{
99 int i;
100 struct termio tmp_termio;
101
102 for (i=0 ; i< (sizeof (*termio)) ; i++)
103 ((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio);
104 *(unsigned short *)&tty->termios.c_iflag = tmp_termio.c_iflag;
105 *(unsigned short *)&tty->termios.c_oflag = tmp_termio.c_oflag;
106 *(unsigned short *)&tty->termios.c_cflag = tmp_termio.c_cflag;
107 *(unsigned short *)&tty->termios.c_lflag = tmp_termio.c_lflag;
108 tty->termios.c_line = tmp_termio.c_line;
109 for(i=0 ; i < NCC ; i++)
110 tty->termios.c_cc[i] = tmp_termio.c_cc[i];
111 change_speed(tty);
112 return 0;
113}
114
115int tty_ioctl(int dev, int cmd, int arg)
116{
117 struct tty_struct * tty;
118 if (MAJOR(dev) == 5) {
119 dev=current->tty;
120 if (dev<0)
121 panic("tty_ioctl: dev<0");
122 } else
123 dev=MINOR(dev);
124 tty = dev + tty_table;
125 switch (cmd) {
126 case TCGETS:
127 return get_termios(tty,(struct termios *) arg);
128 case TCSETSF:
129 flush(&tty->read_q); /* fallthrough */
130 case TCSETSW:
131 wait_until_sent(tty); /* fallthrough */
132 case TCSETS:
133 return set_termios(tty,(struct termios *) arg);
134 case TCGETA:
135 return get_termio(tty,(struct termio *) arg);
136 case TCSETAF:
137 flush(&tty->read_q); /* fallthrough */
138 case TCSETAW:
139 wait_until_sent(tty); /* fallthrough */
140 case TCSETA:
141 return set_termio(tty,(struct termio *) arg);
142 case TCSBRK:
143 if (!arg) {
144 wait_until_sent(tty);
145 send_break(tty);
146 }
147 return 0;
148 case TCXONC:
149 return -EINVAL; /* not implemented */
150 case TCFLSH:
151 if (arg==0)
152 flush(&tty->read_q);
153 else if (arg==1)
154 flush(&tty->write_q);
155 else if (arg==2) {
156 flush(&tty->read_q);
157 flush(&tty->write_q);
158 } else
159 return -EINVAL;
160 return 0;
161 case TIOCEXCL:
162 return -EINVAL; /* not implemented */
163 case TIOCNXCL:
164 return -EINVAL; /* not implemented */
165 case TIOCSCTTY:
166 return -EINVAL; /* set controlling term NI */
167 case TIOCGPGRP:
168 verify_area((void *) arg,4);
169 put_fs_long(tty->pgrp,(unsigned long *) arg);
170 return 0;
171 case TIOCSPGRP:
172 tty->pgrp=get_fs_long((unsigned long *) arg);
173 return 0;
174 case TIOCOUTQ:
175 verify_area((void *) arg,4);
176 put_fs_long(CHARS(tty->write_q),(unsigned long *) arg);
177 return 0;
178 case TIOCINQ:
179 verify_area((void *) arg,4);
180 put_fs_long(CHARS(tty->secondary),
181 (unsigned long *) arg);
182 return 0;
183 case TIOCSTI:
184 return -EINVAL; /* not implemented */
185 case TIOCGWINSZ:
186 return -EINVAL; /* not implemented */
187 case TIOCSWINSZ:
188 return -EINVAL; /* not implemented */
189 case TIOCMGET:
190 return -EINVAL; /* not implemented */
191 case TIOCMBIS:
192 return -EINVAL; /* not implemented */
193 case TIOCMBIC:
194 return -EINVAL; /* not implemented */
195 case TIOCMSET:
196 return -EINVAL; /* not implemented */
197 case TIOCGSOFTCAR:
198 return -EINVAL; /* not implemented */
199 case TIOCSSOFTCAR:
200 return -EINVAL; /* not implemented */
201 default:
202 return -EINVAL;
203 }
204}