qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] Serial Port Bug: HOWTO reproduce


From: Nile Geisinger
Subject: [Qemu-devel] Serial Port Bug: HOWTO reproduce
Date: Wed, 18 Aug 2004 12:16:28 +0000
User-agent: KMail/1.6

Hi everyone,

First of all, a big thanks to the individual(s) who recently cleaned up the 
serial code. It is significantly easier to understand than before and
has been nicely refactored. Qemu is advancing very rapidlly.

In the process, though, one bug appears to have been fixed and another
introduced. Previously, in the 0.60 release, additional serial ports would 
allow the guest to transfer data to the host, but would be unreliable in the 
other direction. In the latest, the problem has been exactly flipped, as 
Darryl discovered (most of the time it allows no data transfer at all). I've
verified the bug independently using named pipes and separate programs.

I haven't been able to solve the bug yet and would appreciate any help. The 
postscript to this email contains 4 simple steps for reproducing the bug. 

thanks,

Nile

P.S. To reproduce the bug, do the following. I've attached the two files 
read.c and write.c below.

1. First download and apply Darryl's patch from 
www.dad-answers.com/qemu/patches/Serial/ to the latest snapshot.

2. Create a named pipe and test it on the host.

        a. Create the pipe on the host
        mkfifo mypipe

        b. Test the pipe:

        cat < mypipe &
        echo hello > mypipe

        (should print hello)

3. Start up a guest operating system (preferably i386/Linux for these tests) 
and pass qemu the option "-com2_serial mypipe" (Supply your own kernel and 
hard drive image names below):

./qemu -nographic -com2-serial mypipe -hda myimage -kernel mykernel -append 
"console=ttyS0 root=/dev/hda1 sb=0x220,5,1,5 ide2=noprobe ide3=noprobe 
ide4=noprobe ide5=noprobe"

4. Test the bug:

        a. Copy read.c and write.c to the guest. Compile them
            as the programs 'read' and 'write'

                gcc read.c -o read
                gcc write.c -o write

        b. Verify that reading works

                In guest:

                        ./read /dev/ttyS1 

                In host:

                        echo hello > mypipe

                (hello will appear in the guest)

        c. Verify that writing doesn't

                In host:
                        cat < mypipe

                In guest:
                        ./write /dev/ttyS1

                (both will hang)

Given the fact that this bug is recent, there's probably some small change 
that caused it. Any help would be appreciated!

=========================== read.c ===========================

#include <stdio.h>
#include <termio.h>
#include <sys/fcntl.h>
#include <sys/file.h>

/* Read example */

main(int argc, char *argv[]) 
{
        struct termios initial_tp;
        struct termios tp;
        int fd;

        int datalength = 6;
        int bytes_read = 0;
        char data_buffer[4096];
        long baud = B38400;

        if ((fd = open(argv[1], O_RDONLY)) < 0) {
                perror("bad terminal device, try another");
                exit(-1);
        }
        
        if (tcgetattr(fd, &initial_tp) < 0) {
                perror("Couldn't get term attributes");
                exit(-1);
        }
        
        /* 8 bits + baud rate + local control */
        tp = initial_tp;
        tp.c_cflag = CS8|CLOCAL|baud|CREAD;
        tp.c_oflag = 0;
        
        /* XON/XOFF flow control, ignore CR, ignore parity */
        tp.c_iflag = IGNCR|IGNPAR;
        tp.c_lflag = 0;
        
        /* set output and input baud rates */
        cfsetospeed(&tp, baud);
        cfsetispeed(&tp, baud);
        if (tcsetattr(fd, TCSANOW, &tp) < 0) {
                perror("Couldn't set term attributes");
                exit(-1);
        }

        /* read the data */
        printf("Trying to read %d bytes of data from %s.\n", datalength, 
argv[1]);
        bytes_read = read(fd, data_buffer, datalength);
        data_buffer[bytes_read] = '\0';
        printf("Successfully read %d bytes of data (%s).\n", bytes_read, 
data_buffer);

        /* reset the term attributes */
        if (tcsetattr(fd, TCSANOW, &initial_tp) < 0) {
                perror("Couldn't set term attributes");
                exit(-1);
        }
                
        exit(0);
}

=========================== write.c ===========================

#include <stdio.h>
#include <termio.h>
#include <sys/fcntl.h>
#include <sys/file.h>
#include <string.h>

/* Write example */

main(int argc, char *argv[]) 
{
        struct termios initial_tp;
        struct termios tp;
        int fd;
        int bytes_written = 0;
        long baud = B38400;

        char * data = "goodbye";
        int datalength; 
        datalength = strlen(data);
        
        if ((fd = open(argv[1], O_RDWR)) < 0) {
                perror("bad terminal device, try another");
                exit(-1);
        }
        
        if (tcgetattr(fd, &initial_tp) < 0) {
                perror("Couldn't get term attributes");
                exit(-1);
        }
        
        /* 8 bits + baud rate + local control */
        tp = initial_tp;
        tp.c_cflag = CS8|CLOCAL|baud;
        tp.c_oflag = 0;
        
        /* XON/XOFF flow control, ignore CR, ignore parity */
        tp.c_iflag = IXON|IGNBRK|IGNCR|IGNPAR;
        tp.c_lflag = 0;
        
        /* set output and input baud rates */
        cfsetospeed(&tp, baud);
        cfsetispeed(&tp, baud);
        if (tcsetattr(fd, TCSANOW, &tp) < 0) {
                perror("Couldn't set term attributes");
                exit(-1);
        }

        /* write the data */
        printf("Trying to write data %s to %s.\n", data, argv[1]);
        bytes_written = write(fd, data, datalength);
        printf("Wrote %d bytes of the data.\n", bytes_written);
        
        /* reset the term attributes */
        if (tcsetattr(fd, TCSANOW, &initial_tp) < 0) {
                perror("Couldn't set term attributes");
                exit(-1);
        }

        exit(0);
}





reply via email to

[Prev in Thread] Current Thread [Next in Thread]