[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] patch for serial port support(linux host only)
From: |
Cai Qiang |
Subject: |
[Qemu-devel] patch for serial port support(linux host only) |
Date: |
Mon, 9 May 2005 10:01:07 +0000 |
User-agent: |
KMail/1.6.1 |
Hi,
Here are patch for serial port support(partial; linux host only). You
can
invoke it by adding sth like "-serial /dev/ttyS0" in arguments to let qemu
using host's serial port as its serial port. qemu will change host's serial
port setting(baudrate, databits, stopbits, parity) when guest os change them.
In my test, I use minicom's zmodem to send file. When sending file to qemu,
things works fine. When sending file from qemu, file can be sent completely,
but qemu gives many warning saying "serial8250: too much work for irq4".
I has also worked on serial port support for windows host, but my build
of
qemu always crash, althrough I have tried different method: cross-compile
using i386-mingw32msvc; mingw/msys. If anyone who has build qemu windows
port can teach me about it, I will try to finish my windows support when I
get time.
Any comments/tests are welcome.
Best Regards
Cai Qiang
--- qemu-0.7.0/vl.c 2005-04-27 20:52:05.000000000 +0000
+++ qemu-0.7.0-serialport/vl.c 2005-05-09 09:24:43.000000000 +0000
@@ -1226,13 +1226,13 @@
fcntl(0, F_SETFL, old_fd0_flags);
}
-static void term_init(void)
+static void term_init(int in)
{
struct termios tty;
- tcgetattr (0, &tty);
+ tcgetattr (in, &tty);
oldtty = tty;
- old_fd0_flags = fcntl(0, F_GETFL);
+ old_fd0_flags = fcntl(in, F_GETFL);
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
|INLCR|IGNCR|ICRNL|IXON);
@@ -1246,11 +1246,11 @@
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
- tcsetattr (0, TCSANOW, &tty);
+ tcsetattr (in, TCSANOW, &tty);
atexit(term_exit);
- fcntl(0, F_SETFL, O_NONBLOCK);
+ fcntl(in, F_SETFL, O_NONBLOCK);
}
CharDriverState *qemu_chr_open_stdio(void)
@@ -1272,7 +1272,7 @@
stdio_clients[stdio_nb_clients++] = chr;
if (stdio_nb_clients == 1) {
/* set the terminal in raw mode */
- term_init();
+ term_init(0);
}
return chr;
}
@@ -1290,6 +1290,126 @@
fprintf(stderr, "char device redirected to %s\n", slave_name);
return qemu_chr_open_fd(master_fd, master_fd);
}
+
+#include <termios.h>
+static void set_baudrate(int fd, int v)
+{
+ struct termios newtio;
+ int BaudRate;
+
+ switch (v) {
+ case 600: BaudRate = B600; break;
+ case 1200: BaudRate = B1200; break;
+ case 2400: BaudRate = B2400; break;
+ case 4800: BaudRate = B4800; break;
+ case 9600: BaudRate = B9600; break;
+ case 19200: BaudRate = B19200; break;
+ case 38400: BaudRate = B38400; break;
+ case 57600: BaudRate = B57600; break;
+ case 115200:BaudRate = B115200; break;
+ default: BaudRate=B115200; break;
+ }
+
+ tcgetattr( fd,&newtio);
+ newtio.c_cflag &= ~CBAUD;
+ newtio.c_cflag |= BaudRate;
+ tcflush(fd, TCIFLUSH);
+ tcsetattr(fd,TCSANOW,&newtio);
+}
+
+static void set_databits(int fd, int v)
+{
+ struct termios newtio;
+
+ tcgetattr( fd,&newtio);
+ newtio.c_cflag &= ~CSIZE;
+ const int databits[] = { CS5, CS6, CS7, CS8 };
+ v-=5;
+ newtio.c_cflag |=
v<sizeof(databits)/sizeof(databits[0])?databits[v]:CS8;
+ tcflush(fd, TCIFLUSH);
+ tcsetattr(fd,TCSANOW,&newtio);
+}
+
+static void set_stopbits(int fd, int v)
+{
+ struct termios newtio;
+
+ tcgetattr( fd,&newtio);
+ if (v==2)
+ newtio.c_cflag |= CSTOPB;
+ else
+ newtio.c_cflag &= ~CSTOPB;
+ tcflush(fd, TCIFLUSH);
+ tcsetattr(fd,TCSANOW,&newtio);
+}
+static void set_parity(int fd, int v)
+{
+ struct termios newtio;
+
+ tcgetattr( fd,&newtio);
+ switch (v) {
+ case 0:
+ newtio.c_iflag=0;
+ break;
+ case 1:
+ newtio.c_iflag = INPCK;
+ newtio.c_cflag |= PARENB|PARODD;
+ break;
+ case 2:
+ newtio.c_iflag = INPCK;
+ newtio.c_cflag |= PARENB;
+ newtio.c_cflag &= ~PARODD;
+ break;
+ case 3:
+ break;
+ case 4:
+ break;
+ }
+ tcflush(fd, TCIFLUSH);
+ tcsetattr(fd,TCSANOW,&newtio);
+}
+
+static void Notify_serial_param_set( CharDriverState *chr, int msg)
+{
+ if (chr != NULL) {
+ int mode=msg>>16, param=msg&0xffff;
+ int pmode;
+ switch (mode) {
+ case 0:
+ case 1:
+#define PC_CLOCK_XTL 1843200.0
+ set_baudrate(((FDCharDriver
*)(chr->opaque))->fd_in, (int)
(PC_CLOCK_XTL /(16 * param)));
+ break;
+ case 3: //lcr
+ set_databits(((FDCharDriver
*)(chr->opaque))->fd_in,(param&0x03)
+ 5);
+ set_stopbits(((FDCharDriver *)(chr->opaque))->fd_in,
(param&(1<<2)) ? 2 : 1);
+ if ((param&(1<<3)) == 0)
+ pmode = 0;
+ else
+ pmode = ((param & 0x30) >> 4) + 1;
+ set_parity(((FDCharDriver
*)(chr->opaque))->fd_in,pmode);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static CharDriverState *qemu_chr_open_dev(const char *devname)
+{
+ int fd;
+ CharDriverState *s;
+
+ if ( (fd=open(devname, O_RDWR|O_NDELAY)) < 0)
+ return NULL;
+ s = qemu_chr_open_fd(fd, fd);
+ if (s!=NULL) {
+ s->chr_send_event=Notify_serial_param_set;
+ /* set the terminal in raw mode */
+ term_init(fd);
+ }
+ return s;
+}
#else
CharDriverState *qemu_chr_open_pty(void)
{
@@ -1311,6 +1431,8 @@
return qemu_chr_open_pty();
} else if (!strcmp(filename, "stdio")) {
return qemu_chr_open_stdio();
+ } else if (!strncmp(filename, "/dev/", 5)) {
+ return qemu_chr_open_dev(filename);
} else
#endif
{
--- qemu-0.7.0/hw/serial.c 2005-04-27 20:52:05.000000000 +0000
+++ qemu-0.7.0-serialport/hw/serial.c 2005-05-09 09:14:39.000000000 +0000
@@ -117,6 +117,7 @@
case 0:
if (s->lcr & UART_LCR_DLAB) {
s->divider = (s->divider & 0xff00) | val;
+ qemu_chr_send_event(s->chr, (addr<<16)|s->divider);
} else {
s->thr_ipending = 0;
s->lsr &= ~UART_LSR_THRE;
@@ -132,6 +133,7 @@
case 1:
if (s->lcr & UART_LCR_DLAB) {
s->divider = (s->divider & 0x00ff) | (val << 8);
+ qemu_chr_send_event(s->chr, (addr<<16)|s->divider);
} else {
s->ier = val & 0x0f;
if (s->lsr & UART_LSR_THRE) {
@@ -144,6 +146,7 @@
break;
case 3:
s->lcr = val;
+ qemu_chr_send_event(s->chr, (addr<<16)|val);
break;
case 4:
s->mcr = val & 0x1f;
- [Qemu-devel] patch for serial port support(linux host only),
Cai Qiang <=