Commit f8d179e33d71ddac580fb41f2b452099e7805d67

Authored by bellard
1 parent 3f87bf69

use host serial port


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1609 c046a42c-6fe2-441c-8c8c-71466251a162
Changelog
... ... @@ -7,7 +7,8 @@ version 0.7.3:
7 7 - new audio options: '-soundhw' and '-audio-help' (malc)
8 8 - ES1370 PCI audio device (malc)
9 9 - Initial USB support
10   -
  10 + - Linux host serial port access
  11 +
11 12 version 0.7.2:
12 13  
13 14 - x86_64 fixes (Win2000 and Linux 2.6 boot in 32 bit)
... ...
hw/serial.c
... ... @@ -85,6 +85,7 @@ struct SerialState {
85 85 int thr_ipending;
86 86 int irq;
87 87 CharDriverState *chr;
  88 + int last_break_enable;
88 89 };
89 90  
90 91 static void serial_update_irq(SerialState *s)
... ... @@ -103,6 +104,32 @@ static void serial_update_irq(SerialState *s)
103 104 }
104 105 }
105 106  
  107 +static void serial_update_parameters(SerialState *s)
  108 +{
  109 + int speed, parity, data_bits, stop_bits;
  110 +
  111 + if (s->lcr & 0x08) {
  112 + if (s->lcr & 0x10)
  113 + parity = 'E';
  114 + else
  115 + parity = 'O';
  116 + } else {
  117 + parity = 'N';
  118 + }
  119 + if (s->lcr & 0x04)
  120 + stop_bits = 2;
  121 + else
  122 + stop_bits = 1;
  123 + data_bits = (s->lcr & 0x03) + 5;
  124 + if (s->divider == 0)
  125 + return;
  126 + speed = 115200 / s->divider;
  127 +#if 0
  128 + printf("speed=%d parity=%c data=%d stop=%d\n",
  129 + speed, parity, data_bits, stop_bits);
  130 +#endif
  131 +}
  132 +
106 133 static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
107 134 {
108 135 SerialState *s = opaque;
... ... @@ -117,6 +144,7 @@ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
117 144 case 0:
118 145 if (s->lcr & UART_LCR_DLAB) {
119 146 s->divider = (s->divider & 0xff00) | val;
  147 + serial_update_parameters(s);
120 148 } else {
121 149 s->thr_ipending = 0;
122 150 s->lsr &= ~UART_LSR_THRE;
... ... @@ -132,6 +160,7 @@ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
132 160 case 1:
133 161 if (s->lcr & UART_LCR_DLAB) {
134 162 s->divider = (s->divider & 0x00ff) | (val << 8);
  163 + serial_update_parameters(s);
135 164 } else {
136 165 s->ier = val & 0x0f;
137 166 if (s->lsr & UART_LSR_THRE) {
... ... @@ -143,7 +172,16 @@ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
143 172 case 2:
144 173 break;
145 174 case 3:
146   - s->lcr = val;
  175 + {
  176 + int break_enable;
  177 + s->lcr = val;
  178 + serial_update_parameters(s);
  179 + break_enable = (val >> 6) & 1;
  180 + if (break_enable != s->last_break_enable) {
  181 + s->last_break_enable = break_enable;
  182 + qemu_chr_set_serial_break(s, break_enable);
  183 + }
  184 + }
147 185 break;
148 186 case 4:
149 187 s->mcr = val & 0x1f;
... ...
qemu-doc.texi
... ... @@ -363,8 +363,15 @@ Virtual console
363 363 [Linux only] Pseudo TTY (a new PTY is automatically allocated)
364 364 @item null
365 365 void device
  366 +@item /dev/XXX
  367 +[Linux only]Use host tty, e.g. @file{/dev/ttyS0}. The host serial port
  368 +parameters are set according to the emulated ones.
  369 +@item file:filename
  370 +Write output to filename. No character can be read.
366 371 @item stdio
367 372 [Unix only] standard input/output
  373 +@item pipe:filename
  374 +[Unix only] name pipe @var{filename}
368 375 @end table
369 376 The default device is @code{vc} in graphical mode and @code{stdio} in
370 377 non graphical mode.
... ...
... ... @@ -1013,6 +1013,21 @@ int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
1013 1013 return s->chr_write(s, buf, len);
1014 1014 }
1015 1015  
  1016 +void qemu_chr_set_serial_parameters(CharDriverState *s,
  1017 + int speed, int parity,
  1018 + int data_bits, int stop_bits)
  1019 +{
  1020 + if (s->chr_set_serial_parameters)
  1021 + s->chr_set_serial_parameters(s, speed, parity, data_bits, stop_bits);
  1022 +}
  1023 +
  1024 +void qemu_chr_set_serial_break(CharDriverState *s, int enable)
  1025 +{
  1026 + if (s->chr_set_serial_break)
  1027 + s->chr_set_serial_break(s, enable);
  1028 +}
  1029 +
  1030 +
1016 1031 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
1017 1032 {
1018 1033 char buf[4096];
... ... @@ -1111,12 +1126,14 @@ static void fd_chr_add_read_handler(CharDriverState *chr,
1111 1126 {
1112 1127 FDCharDriver *s = chr->opaque;
1113 1128  
1114   - if (nographic && s->fd_in == 0) {
1115   - s->fd_can_read = fd_can_read;
1116   - s->fd_read = fd_read;
1117   - s->fd_opaque = opaque;
1118   - } else {
1119   - qemu_add_fd_read_handler(s->fd_in, fd_can_read, fd_read, opaque);
  1129 + if (s->fd_in >= 0) {
  1130 + if (nographic && s->fd_in == 0) {
  1131 + s->fd_can_read = fd_can_read;
  1132 + s->fd_read = fd_read;
  1133 + s->fd_opaque = opaque;
  1134 + } else {
  1135 + qemu_add_fd_read_handler(s->fd_in, fd_can_read, fd_read, opaque);
  1136 + }
1120 1137 }
1121 1138 }
1122 1139  
... ... @@ -1142,6 +1159,27 @@ CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
1142 1159 return chr;
1143 1160 }
1144 1161  
  1162 +CharDriverState *qemu_chr_open_file_out(const char *file_out)
  1163 +{
  1164 + int fd_out;
  1165 +
  1166 + fd_out = open(file_out, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY);
  1167 + if (fd_out < 0)
  1168 + return NULL;
  1169 + return qemu_chr_open_fd(-1, fd_out);
  1170 +}
  1171 +
  1172 +CharDriverState *qemu_chr_open_pipe(const char *filename)
  1173 +{
  1174 + int fd;
  1175 +
  1176 + fd = open(filename, O_RDWR | O_BINARY);
  1177 + if (fd < 0)
  1178 + return NULL;
  1179 + return qemu_chr_open_fd(fd, fd);
  1180 +}
  1181 +
  1182 +
1145 1183 /* for STDIO, we handle the case where several clients use it
1146 1184 (nographic mode) */
1147 1185  
... ... @@ -1334,6 +1372,127 @@ CharDriverState *qemu_chr_open_pty(void)
1334 1372 fprintf(stderr, "char device redirected to %s\n", slave_name);
1335 1373 return qemu_chr_open_fd(master_fd, master_fd);
1336 1374 }
  1375 +
  1376 +static void tty_serial_init(int fd, int speed,
  1377 + int parity, int data_bits, int stop_bits)
  1378 +{
  1379 + struct termios tty;
  1380 + speed_t spd;
  1381 +
  1382 + tcgetattr (0, &tty);
  1383 +
  1384 + switch(speed) {
  1385 + case 50:
  1386 + spd = B50;
  1387 + break;
  1388 + case 75:
  1389 + spd = B75;
  1390 + break;
  1391 + case 300:
  1392 + spd = B300;
  1393 + break;
  1394 + case 600:
  1395 + spd = B600;
  1396 + break;
  1397 + case 1200:
  1398 + spd = B1200;
  1399 + break;
  1400 + case 2400:
  1401 + spd = B2400;
  1402 + break;
  1403 + case 4800:
  1404 + spd = B4800;
  1405 + break;
  1406 + case 9600:
  1407 + spd = B9600;
  1408 + break;
  1409 + case 19200:
  1410 + spd = B19200;
  1411 + break;
  1412 + case 38400:
  1413 + spd = B38400;
  1414 + break;
  1415 + case 57600:
  1416 + spd = B57600;
  1417 + break;
  1418 + default:
  1419 + case 115200:
  1420 + spd = B115200;
  1421 + break;
  1422 + }
  1423 +
  1424 + cfsetispeed(&tty, spd);
  1425 + cfsetospeed(&tty, spd);
  1426 +
  1427 + tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
  1428 + |INLCR|IGNCR|ICRNL|IXON);
  1429 + tty.c_oflag |= OPOST;
  1430 + tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG);
  1431 + tty.c_cflag &= ~(CSIZE|PARENB|PARODD|CRTSCTS);
  1432 + switch(data_bits) {
  1433 + default:
  1434 + case 8:
  1435 + tty.c_cflag |= CS8;
  1436 + break;
  1437 + case 7:
  1438 + tty.c_cflag |= CS7;
  1439 + break;
  1440 + case 6:
  1441 + tty.c_cflag |= CS6;
  1442 + break;
  1443 + case 5:
  1444 + tty.c_cflag |= CS5;
  1445 + break;
  1446 + }
  1447 + switch(parity) {
  1448 + default:
  1449 + case 'N':
  1450 + break;
  1451 + case 'E':
  1452 + tty.c_cflag |= PARENB;
  1453 + break;
  1454 + case 'O':
  1455 + tty.c_cflag |= PARENB | PARODD;
  1456 + break;
  1457 + }
  1458 +
  1459 + tcsetattr (fd, TCSANOW, &tty);
  1460 +}
  1461 +
  1462 +static void tty_set_serial_parameters(CharDriverState *chr,
  1463 + int speed, int parity,
  1464 + int data_bits, int stop_bits)
  1465 +{
  1466 + FDCharDriver *s = chr->opaque;
  1467 + tty_serial_init(s->fd_in, speed, parity, data_bits, stop_bits);
  1468 +}
  1469 +
  1470 +static void tty_set_serial_break(CharDriverState *chr, int enable)
  1471 +{
  1472 + FDCharDriver *s = chr->opaque;
  1473 + /* XXX: find a better solution */
  1474 + if (enable)
  1475 + tcsendbreak(s->fd_in, 1);
  1476 +}
  1477 +
  1478 +CharDriverState *qemu_chr_open_tty(const char *filename)
  1479 +{
  1480 + CharDriverState *chr;
  1481 + int fd;
  1482 +
  1483 + fd = open(filename, O_RDWR);
  1484 + if (fd < 0)
  1485 + return NULL;
  1486 + fcntl(fd, F_SETFL, O_NONBLOCK);
  1487 + tty_serial_init(fd, 115200, 'N', 8, 1);
  1488 + chr = qemu_chr_open_fd(fd, fd);
  1489 + if (!chr)
  1490 + return NULL;
  1491 + chr->chr_set_serial_parameters = tty_set_serial_parameters;
  1492 + chr->chr_set_serial_break = tty_set_serial_break;
  1493 + return chr;
  1494 +}
  1495 +
1337 1496 #else
1338 1497 CharDriverState *qemu_chr_open_pty(void)
1339 1498 {
... ... @@ -1345,10 +1504,15 @@ CharDriverState *qemu_chr_open_pty(void)
1345 1504  
1346 1505 CharDriverState *qemu_chr_open(const char *filename)
1347 1506 {
  1507 + const char *p;
1348 1508 if (!strcmp(filename, "vc")) {
1349 1509 return text_console_init(&display_state);
1350 1510 } else if (!strcmp(filename, "null")) {
1351 1511 return qemu_chr_open_null();
  1512 + } else if (strstart(filename, "file:", &p)) {
  1513 + return qemu_chr_open_file_out(p);
  1514 + } else if (strstart(filename, "pipe:", &p)) {
  1515 + return qemu_chr_open_pipe(p);
1352 1516 } else
1353 1517 #ifndef _WIN32
1354 1518 if (!strcmp(filename, "pty")) {
... ... @@ -1357,6 +1521,11 @@ CharDriverState *qemu_chr_open(const char *filename)
1357 1521 return qemu_chr_open_stdio();
1358 1522 } else
1359 1523 #endif
  1524 +#if defined(__linux__)
  1525 + if (strstart(filename, "/dev/", NULL)) {
  1526 + return qemu_chr_open_tty(filename);
  1527 + } else
  1528 +#endif
1360 1529 {
1361 1530 return NULL;
1362 1531 }
... ... @@ -3010,7 +3179,6 @@ void help(void)
3010 3179 "-no-code-copy disable code copy acceleration\n"
3011 3180 #endif
3012 3181 #ifdef TARGET_I386
3013   - "-isa simulate an ISA-only system (default is PCI system)\n"
3014 3182 "-std-vga simulate a standard VGA card with VESA Bochs Extensions\n"
3015 3183 " (default is CL-GD5446 PCI VGA)\n"
3016 3184 #endif
... ...
... ... @@ -207,6 +207,10 @@ typedef struct CharDriverState {
207 207 void (*chr_add_read_handler)(struct CharDriverState *s,
208 208 IOCanRWHandler *fd_can_read,
209 209 IOReadHandler *fd_read, void *opaque);
  210 + void (*chr_set_serial_parameters)(struct CharDriverState *s,
  211 + int speed, int parity,
  212 + int data_bits, int stop_bits);
  213 + void (*chr_set_serial_break)(struct CharDriverState *s, int enable);
210 214 IOEventHandler *chr_event;
211 215 void (*chr_send_event)(struct CharDriverState *chr, int event);
212 216 void *opaque;
... ... @@ -219,7 +223,11 @@ void qemu_chr_add_read_handler(CharDriverState *s,
219 223 IOCanRWHandler *fd_can_read,
220 224 IOReadHandler *fd_read, void *opaque);
221 225 void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event);
222   -
  226 +void qemu_chr_set_serial_parameters(CharDriverState *s,
  227 + int speed, int parity,
  228 + int data_bits, int stop_bits);
  229 +void qemu_chr_set_serial_break(CharDriverState *s, int enable);
  230 +
223 231 /* consoles */
224 232  
225 233 typedef struct DisplayState DisplayState;
... ...