pci-bridge/i82801b11: clear bridge registers on platform reset
[qemu/ar7.git] / chardev / char-serial.c
blob93392c528c1e9bb5db5a17f561fa293c8d3b2f55
1 /*
2 * QEMU System Emulator
4 * Copyright (c) 2003-2008 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
24 #include "qemu/osdep.h"
25 #include "qemu/sockets.h"
26 #include "io/channel-file.h"
27 #include "qapi/error.h"
29 #ifdef _WIN32
30 #include "chardev/char-win.h"
31 #else
32 #include <sys/ioctl.h>
33 #include <termios.h>
34 #include "chardev/char-fd.h"
35 #endif
37 #include "chardev/char-serial.h"
39 #ifdef _WIN32
41 static void qmp_chardev_open_serial(Chardev *chr,
42 ChardevBackend *backend,
43 bool *be_opened,
44 Error **errp)
46 ChardevHostdev *serial = backend->u.serial.data;
48 win_chr_serial_init(chr, serial->device, errp);
51 #elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
52 || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
53 || defined(__GLIBC__)
55 static void tty_serial_init(int fd, int speed,
56 int parity, int data_bits, int stop_bits)
58 struct termios tty;
59 speed_t spd;
61 #if 0
62 printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n",
63 speed, parity, data_bits, stop_bits);
64 #endif
65 tcgetattr(fd, &tty);
67 #define check_speed(val) \
68 if (speed <= val) { \
69 spd = B##val; \
70 goto done; \
73 speed = speed * 10 / 11;
74 check_speed(50);
75 check_speed(75);
76 check_speed(110);
77 check_speed(134);
78 check_speed(150);
79 check_speed(200);
80 check_speed(300);
81 check_speed(600);
82 check_speed(1200);
83 check_speed(1800);
84 check_speed(2400);
85 check_speed(4800);
86 check_speed(9600);
87 check_speed(19200);
88 check_speed(38400);
89 /* Non-Posix values follow. They may be unsupported on some systems. */
90 check_speed(57600);
91 check_speed(115200);
92 #ifdef B230400
93 check_speed(230400);
94 #endif
95 #ifdef B460800
96 check_speed(460800);
97 #endif
98 #ifdef B500000
99 check_speed(500000);
100 #endif
101 #ifdef B576000
102 check_speed(576000);
103 #endif
104 #ifdef B921600
105 check_speed(921600);
106 #endif
107 #ifdef B1000000
108 check_speed(1000000);
109 #endif
110 #ifdef B1152000
111 check_speed(1152000);
112 #endif
113 #ifdef B1500000
114 check_speed(1500000);
115 #endif
116 #ifdef B2000000
117 check_speed(2000000);
118 #endif
119 #ifdef B2500000
120 check_speed(2500000);
121 #endif
122 #ifdef B3000000
123 check_speed(3000000);
124 #endif
125 #ifdef B3500000
126 check_speed(3500000);
127 #endif
128 #ifdef B4000000
129 check_speed(4000000);
130 #endif
131 spd = B115200;
133 #undef check_speed
134 done:
135 cfsetispeed(&tty, spd);
136 cfsetospeed(&tty, spd);
138 tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
139 | INLCR | IGNCR | ICRNL | IXON);
140 tty.c_oflag |= OPOST;
141 tty.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
142 tty.c_cflag &= ~(CSIZE | PARENB | PARODD | CRTSCTS | CSTOPB);
143 switch (data_bits) {
144 default:
145 case 8:
146 tty.c_cflag |= CS8;
147 break;
148 case 7:
149 tty.c_cflag |= CS7;
150 break;
151 case 6:
152 tty.c_cflag |= CS6;
153 break;
154 case 5:
155 tty.c_cflag |= CS5;
156 break;
158 switch (parity) {
159 default:
160 case 'N':
161 break;
162 case 'E':
163 tty.c_cflag |= PARENB;
164 break;
165 case 'O':
166 tty.c_cflag |= PARENB | PARODD;
167 break;
169 if (stop_bits == 2) {
170 tty.c_cflag |= CSTOPB;
173 tcsetattr(fd, TCSANOW, &tty);
176 static int tty_serial_ioctl(Chardev *chr, int cmd, void *arg)
178 FDChardev *s = FD_CHARDEV(chr);
179 QIOChannelFile *fioc = QIO_CHANNEL_FILE(s->ioc_in);
181 switch (cmd) {
182 case CHR_IOCTL_SERIAL_SET_PARAMS:
184 QEMUSerialSetParams *ssp = arg;
185 tty_serial_init(fioc->fd,
186 ssp->speed, ssp->parity,
187 ssp->data_bits, ssp->stop_bits);
189 break;
190 case CHR_IOCTL_SERIAL_SET_BREAK:
192 int enable = *(int *)arg;
193 if (enable) {
194 tcsendbreak(fioc->fd, 1);
197 break;
198 case CHR_IOCTL_SERIAL_GET_TIOCM:
200 int sarg = 0;
201 int *targ = (int *)arg;
202 ioctl(fioc->fd, TIOCMGET, &sarg);
203 *targ = 0;
204 if (sarg & TIOCM_CTS) {
205 *targ |= CHR_TIOCM_CTS;
207 if (sarg & TIOCM_CAR) {
208 *targ |= CHR_TIOCM_CAR;
210 if (sarg & TIOCM_DSR) {
211 *targ |= CHR_TIOCM_DSR;
213 if (sarg & TIOCM_RI) {
214 *targ |= CHR_TIOCM_RI;
216 if (sarg & TIOCM_DTR) {
217 *targ |= CHR_TIOCM_DTR;
219 if (sarg & TIOCM_RTS) {
220 *targ |= CHR_TIOCM_RTS;
223 break;
224 case CHR_IOCTL_SERIAL_SET_TIOCM:
226 int sarg = *(int *)arg;
227 int targ = 0;
228 ioctl(fioc->fd, TIOCMGET, &targ);
229 targ &= ~(CHR_TIOCM_CTS | CHR_TIOCM_CAR | CHR_TIOCM_DSR
230 | CHR_TIOCM_RI | CHR_TIOCM_DTR | CHR_TIOCM_RTS);
231 if (sarg & CHR_TIOCM_CTS) {
232 targ |= TIOCM_CTS;
234 if (sarg & CHR_TIOCM_CAR) {
235 targ |= TIOCM_CAR;
237 if (sarg & CHR_TIOCM_DSR) {
238 targ |= TIOCM_DSR;
240 if (sarg & CHR_TIOCM_RI) {
241 targ |= TIOCM_RI;
243 if (sarg & CHR_TIOCM_DTR) {
244 targ |= TIOCM_DTR;
246 if (sarg & CHR_TIOCM_RTS) {
247 targ |= TIOCM_RTS;
249 ioctl(fioc->fd, TIOCMSET, &targ);
251 break;
252 default:
253 return -ENOTSUP;
255 return 0;
258 static void qmp_chardev_open_serial(Chardev *chr,
259 ChardevBackend *backend,
260 bool *be_opened,
261 Error **errp)
263 ChardevHostdev *serial = backend->u.serial.data;
264 int fd;
266 fd = qmp_chardev_open_file_source(serial->device, O_RDWR, errp);
267 if (fd < 0) {
268 return;
270 qemu_set_nonblock(fd);
271 tty_serial_init(fd, 115200, 'N', 8, 1);
273 qemu_chr_open_fd(chr, fd, fd);
275 #endif /* __linux__ || __sun__ */
277 #ifdef HAVE_CHARDEV_SERIAL
278 static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
279 Error **errp)
281 const char *device = qemu_opt_get(opts, "path");
282 ChardevHostdev *serial;
284 if (device == NULL) {
285 error_setg(errp, "chardev: serial/tty: no device path given");
286 return;
288 backend->type = CHARDEV_BACKEND_KIND_SERIAL;
289 serial = backend->u.serial.data = g_new0(ChardevHostdev, 1);
290 qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(serial));
291 serial->device = g_strdup(device);
294 static void char_serial_class_init(ObjectClass *oc, void *data)
296 ChardevClass *cc = CHARDEV_CLASS(oc);
298 cc->parse = qemu_chr_parse_serial;
299 cc->open = qmp_chardev_open_serial;
300 #ifndef _WIN32
301 cc->chr_ioctl = tty_serial_ioctl;
302 #endif
306 static const TypeInfo char_serial_type_info = {
307 .name = TYPE_CHARDEV_SERIAL,
308 #ifdef _WIN32
309 .parent = TYPE_CHARDEV_WIN,
310 #else
311 .parent = TYPE_CHARDEV_FD,
312 #endif
313 .class_init = char_serial_class_init,
316 static void register_types(void)
318 type_register_static(&char_serial_type_info);
321 type_init(register_types);
323 #endif