qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] patch for serial port support(linux host only)
@ 2005-05-09 10:01 Cai Qiang
  2005-05-09  7:04 ` Filip Navara
  2005-05-20 16:42 ` [Qemu-devel] FreeDOS FDAPM kills Keybord Andreas Bollhalder
  0 siblings, 2 replies; 4+ messages in thread
From: Cai Qiang @ 2005-05-09 10:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: alexander.burker


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;

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2005-05-20 17:21 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-05-09 10:01 [Qemu-devel] patch for serial port support(linux host only) Cai Qiang
2005-05-09  7:04 ` Filip Navara
2005-05-09 15:31   ` Cai Qiang
2005-05-20 16:42 ` [Qemu-devel] FreeDOS FDAPM kills Keybord Andreas Bollhalder

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).