From mboxrd@z Thu Jan 1 00:00:00 1970 From: Michael Tokarev Subject: Re: more about serial ports: do they even work? Date: Mon, 26 Jan 2009 23:39:25 +0300 Message-ID: <497E1F7D.90300@msgid.tls.msk.ru> References: <497E1B15.2090908@msgid.tls.msk.ru> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7BIT Cc: "David S. Ahern" To: KVM list Return-path: Received: from isrv.corpit.ru ([81.13.33.159]:39876 "EHLO isrv.corpit.ru" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753417AbZAZUj2 (ORCPT ); Mon, 26 Jan 2009 15:39:28 -0500 In-Reply-To: <497E1B15.2090908@msgid.tls.msk.ru> Sender: kvm-owner@vger.kernel.org List-ID: Michael Tokarev ?????: > After some debugging and debugging, with a help > Hollis Blanchard on #kvm@freenode, I discovered > that kvm (or, rather, qemu) does not work correctly > with serial ports, at least on linux. One problem > report has already here, author Cc'd -- see e.g. > http://marc.info/?l=kvm&m=122995568009533&w=2 . > > Here's what's going on. > > When opening a host's port, kvm resets the status > lines, doing this: > > ioctl(13, TIOCMGET, [TIOCM_DTR|TIOCM_RTS|TIOCM_CTS|TIOCM_DSR|0x4000]) > ioctl(13, TIOCMSET, [TIOCM_DTR|TIOCM_RTS]) > > which results in the following set > > ioctl(13, TIOCMGET, [TIOCM_DTR|TIOCM_RTS|TIOCM_CTS|TIOCM_DSR]) Here's the possible solution (NotAPAtch(tm)): In kvm-xx/qemu/qemu-char.c: case CHR_IOCTL_SERIAL_SET_TIOCM: { int sarg = *(int *)arg; int targ = 0; <==== change this 0 to 0x4000 if (sarg | CHR_TIOCM_DTR) targ |= TIOCM_DTR; if (sarg | CHR_TIOCM_RTS) targ |= TIOCM_RTS; ioctl(s->fd_in, TIOCMSET, &targ); } break; This is obviously a hack, esp. since this bit is not always present even on linux (after reading 8250.c driver). Real fix will be, I guess, to read the full set first, and combine it with DTR|RTS received from guest, something like this: case CHR_IOCTL_SERIAL_SET_TIOCM: { int sarg = *(int *)arg; int targ = 0; ioctl(s->fd_in, TIOCMGET, &targ); if (!(sarg | CHR_TIOCM_DTR)) targ &= ~TIOCM_DTR; if (!(sarg | CHR_TIOCM_RTS)) targ ~= ~TIOCM_RTS; ioctl(s->fd_in, TIOCMSET, &targ); } break; I.e., to always keep all the other bits, but allow changing DTR and RTS. Again, I don't know how it's linux-specific, but it seems the solution above should work on other platforms just fine. /mjt