]> xenbits.xensource.com Git - qemu-xen-4.4-testing.git/commitdiff
Merge branch 'upstream' into qemu qemu
authorIan Jackson <ian.jackson@eu.citrix.com>
Wed, 28 Jan 2009 17:15:40 +0000 (17:15 +0000)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Wed, 28 Jan 2009 17:15:40 +0000 (17:15 +0000)
Conflicts:

.gitignore
Makefile
audio/audio.c
block-qcow2.c
block-vvfat.c
block.c
cutils.c
dyngen.c
hw/ide.c
monitor.c
readline.c
target-ppc/translate_init.c
usb-linux.c
vl.c
vnc.c

30 files changed:
1  2 
.gitignore
Makefile
block-cloop.c
block-dmg.c
block-qcow.c
block-qcow2.c
block-raw-posix.c
block-vmdk.c
block-vvfat.c
block.c
block.h
block_int.h
bt-host.c
configure
darwin-user/machload.c
elf_ops.h
hw/ide.c
hw/pci.c
hw/scsi-disk.c
loader.c
osdep.c
osdep.h
qemu-char.c
qemu-common.h
qemu-sockets.c
qemu_socket.h
target-ppc/translate_init.c
tests/linux-test.c
tests/qruncom.c
usb-linux.c

diff --cc .gitignore
index 4f27830fbc3b848991f5757744bc22aaf41acc3d,6fdc7e701a675cd8d5846d91ce8804cec5e0b3e9..3407943384cbe29573d006245fe4eab72bf1b580
@@@ -31,5 -30,7 +30,9 @@@ qemu-nbd.po
  *.tp
  *.vr
  *.d
 +*.o
 +*~
+ .pc
+ patches
+ pc-bios/bios-pq/status
+ pc-bios/vgabios-pq/status
diff --cc Makefile
Simple merge
diff --cc block-cloop.c
Simple merge
diff --cc block-dmg.c
Simple merge
diff --cc block-qcow.c
Simple merge
diff --cc block-qcow2.c
index 0abc1c7eeecc4462b03920cf47c9f090fecc0df9,9aa7261e3fb908d4bddfdbe3a002e6c3cff55b40..b274117927f3beec2cdccbe62b3dc74a1cac578d
@@@ -189,7 -189,15 +189,15 @@@ static int qcow_open(BlockDriverState *
      int len, i, shift, ret;
      QCowHeader header;
  
 -    ret = bdrv_file_open(&s->hd, filename, flags);
+     /* Performance is terrible right now with cache=writethrough due mainly
+      * to reference count updates.  If the user does not explicitly specify
+      * a caching type, force to writeback caching.
+      */
+     if ((flags & BDRV_O_CACHE_DEF)) {
+         flags |= BDRV_O_CACHE_WB;
+         flags &= ~BDRV_O_CACHE_DEF;
+     }
 +    ret = bdrv_file_open(&s->hd, filename, flags | BDRV_O_EXTENDABLE);
      if (ret < 0)
          return ret;
      if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
index 7e0c419814d122d8c4fcbc13876fb19977e474ef,d17af0b34e23f3d3899addce2e5c0afdf3fdf74f..7a895b457ef53beeea3b8c5b94a1be40b2ddff6a
@@@ -906,9 -822,9 +838,10 @@@ BlockDriver bdrv_raw = 
      .bdrv_aio_read = raw_aio_read,
      .bdrv_aio_write = raw_aio_write,
      .bdrv_aio_cancel = raw_aio_cancel,
 +    .bdrv_aio_flush = raw_aio_flush,
      .aiocb_size = sizeof(RawAIOCB),
  #endif
      .bdrv_pread = raw_pread,
      .bdrv_pwrite = raw_pwrite,
      .bdrv_truncate = raw_truncate,
@@@ -1266,9 -1176,9 +1195,10 @@@ BlockDriver bdrv_host_device = 
      .bdrv_aio_read = raw_aio_read,
      .bdrv_aio_write = raw_aio_write,
      .bdrv_aio_cancel = raw_aio_cancel,
 +    .bdrv_aio_flush = raw_aio_flush,
      .aiocb_size = sizeof(RawAIOCB),
  #endif
      .bdrv_pread = raw_pread,
      .bdrv_pwrite = raw_pwrite,
      .bdrv_getlength = raw_getlength,
diff --cc block-vmdk.c
Simple merge
diff --cc block-vvfat.c
Simple merge
diff --cc block.c
index e02104bf9b8ab2aafb75c333765e8360e366023e,32503271c74402ce5316f28d5f464ff9954979a1..8674d3400963c5cd4653f139b99883543a9c44a4
+++ b/block.c
@@@ -560,16 -532,6 +565,8 @@@ int bdrv_read(BlockDriverState *bs, int
      if (!drv)
          return -ENOMEDIUM;
  
-     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
-             memcpy(buf, bs->boot_sector_data, 512);
-         sector_num++;
-         nb_sectors--;
-         buf += 512;
-         if (nb_sectors == 0)
-             return 0;
-     }
 +    if (bdrv_rw_badreq_sectors(bs, sector_num, nb_sectors))
 +      return -EDOM;
      if (drv->bdrv_pread) {
          int ret, len;
          len = nb_sectors * 512;
@@@ -602,27 -564,23 +599,25 @@@ int bdrv_write(BlockDriverState *bs, in
          return -ENOMEDIUM;
      if (bs->read_only)
          return -EACCES;
-     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
-         memcpy(bs->boot_sector_data, buf, 512);
-     }
 +    if (bdrv_rw_badreq_sectors(bs, sector_num, nb_sectors))
 +      return -EDOM;
      if (drv->bdrv_pwrite) {
-         int ret, len;
+         int ret, len, count = 0;
          len = nb_sectors * 512;
-         ret = drv->bdrv_pwrite(bs, sector_num * 512, buf, len);
-         if (ret < 0)
-             return ret;
-         else if (ret != len)
-             return -EIO;
-         else {
-           bs->wr_bytes += (unsigned) len;
-           bs->wr_ops ++;
-             return 0;
-       }
-     } else {
-         return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
+         do {
+             ret = drv->bdrv_pwrite(bs, sector_num * 512, buf, len - count);
+             if (ret < 0) {
+                 printf("bdrv_write ret=%d\n", ret);
+                 return ret;
+             }
+             count += ret;
+             buf += ret;
+         } while (count != len);
+         bs->wr_bytes += (unsigned) len;
+         bs->wr_ops ++;
+         return 0;
      }
+     return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
  }
  
  static int bdrv_pread_em(BlockDriverState *bs, int64_t offset,
@@@ -1204,17 -1255,7 +1305,9 @@@ BlockDriverAIOCB *bdrv_aio_read(BlockDr
  
      if (!drv)
          return NULL;
 +    if (bdrv_rw_badreq_sectors(bs, sector_num, nb_sectors))
 +      return NULL;
  
-     /* XXX: we assume that nb_sectors == 0 is suppored by the async read */
-     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
-         memcpy(buf, bs->boot_sector_data, 512);
-         sector_num++;
-         nb_sectors--;
-         buf += 512;
-     }
      ret = drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
  
      if (ret) {
@@@ -1237,11 -1278,6 +1330,8 @@@ BlockDriverAIOCB *bdrv_aio_write(BlockD
          return NULL;
      if (bs->read_only)
          return NULL;
-     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
-         memcpy(bs->boot_sector_data, buf, 512);
-     }
 +    if (bdrv_rw_badreq_sectors(bs, sector_num, nb_sectors))
 +      return NULL;
  
      ret = drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
  
diff --cc block.h
index 77fec156bc6adab0ac67b1c1fc9d81391da58a93,c3314a1dbe32bb4fd7d26c7948471eb3cc418879..503e6f94edcca5e42abb21b427010e45d8663d79
+++ b/block.h
@@@ -49,12 -49,10 +49,13 @@@ typedef struct QEMUSnapshotInfo 
                                       bdrv_file_open()) */
  #define BDRV_O_NOCACHE     0x0020 /* do not use the host page cache */
  #define BDRV_O_CACHE_WB    0x0040 /* use write-back caching */
+ #define BDRV_O_CACHE_DEF   0x0080 /* use default caching */
  
- #define BDRV_O_CACHE_MASK  (BDRV_O_NOCACHE | BDRV_O_CACHE_WB)
+ #define BDRV_O_CACHE_MASK  (BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_CACHE_DEF)
  
 +#define BDRV_O_EXTENDABLE  0x0080 /* allow writes out of original size range;
 +                                   only effective for some drivers */
 +
  void bdrv_info(void);
  void bdrv_info_stats(void);
  
diff --cc block_int.h
Simple merge
diff --cc bt-host.c
Simple merge
diff --cc configure
index 9c08f0d1463716f8f14021d434ccef58ab159e27,f4b67ea3b28cf0d851bb07ce244064ba169b146b..f0daa82a5a0e53aaf89b733f2172f801dbff235e
+++ b/configure
@@@ -354,10 -449,9 +449,10 @@@ for opt d
    esac
  done
  
 +
  # default flags for all hosts
  CFLAGS="$CFLAGS -O2 -g -fno-strict-aliasing"
- CFLAGS="$CFLAGS -Wall -Wundef -Wendif-labels -Wwrite-strings"
+ CFLAGS="$CFLAGS -Wall -Wundef -Wendif-labels -Wwrite-strings -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls"
  LDFLAGS="$LDFLAGS -g"
  if test "$werror" = "yes" ; then
  CFLAGS="$CFLAGS -Werror"
Simple merge
diff --cc elf_ops.h
index abbc6fc095d3549fc7c998713187d0e658490727,feea12f2617a9b263553358b893218b4c3695bf1..156e661f964454fdf54a43fbbff5ef41d2a2196b
+++ b/elf_ops.h
@@@ -226,10 -226,12 +226,12 @@@ static int glue(load_elf, SZ)(int fd, i
              if (ph->p_filesz > 0) {
                  if (lseek(fd, ph->p_offset, SEEK_SET) < 0)
                      goto fail;
 -                if (read(fd, data, ph->p_filesz) != ph->p_filesz)
 +                if (qemu_read_ok(fd, data, ph->p_filesz) < 0)
                      goto fail;
              }
-             addr = ph->p_vaddr + virt_to_phys_addend;
+             /* address_offset is hack for kernel images that are
+                linked at the wrong physical address.  */
+             addr = ph->p_paddr + address_offset;
  
              cpu_physical_memory_write_rom(addr, data, mem_size);
  
diff --cc hw/ide.c
index 8cf4fdc922e06475f3dafe28a923c3e10ecdc7f6,7dd41f7aaeec43092f99ac574d305e6e089e493f..41f94d95e56db0b1db48ab7ef5e4b49f00664493
+++ b/hw/ide.c
@@@ -385,7 -386,7 +386,8 @@@ typedef struct IDEState 
      PCIDevice *pci_dev;
      struct BMDMAState *bmdma;
      int drive_serial;
 +    uint8_t write_cache;
+     char drive_serial_str[21];
      /* ide regs */
      uint8_t feature;
      uint8_t error;
@@@ -2039,11 -1994,13 +2058,15 @@@ static void cdrom_change_cb(void *opaqu
      IDEState *s = opaque;
      uint64_t nb_sectors;
  
-     /* XXX: send interrupt too */
 +    if (!s->bs) return; /* ouch! (see ide_flush_cb) */
 +
      bdrv_get_geometry(s->bs, &nb_sectors);
      s->nb_sectors = nb_sectors;
+     s->sense_key = SENSE_UNIT_ATTENTION;
+     s->asc = ASC_MEDIUM_MAY_HAVE_CHANGED;
+     ide_set_irq(s);
  }
  
  static void ide_cmd_lba48_transform(IDEState *s, int lba48)
@@@ -3202,6 -3059,71 +3138,71 @@@ static void bmdma_map(PCIDevice *pci_de
      }
  }
  
 -    if (version_id != 1)
+ static void pci_ide_save(QEMUFile* f, void *opaque)
+ {
+     PCIIDEState *d = opaque;
+     int i;
+     pci_device_save(&d->dev, f);
+     for(i = 0; i < 2; i++) {
+         BMDMAState *bm = &d->bmdma[i];
+         qemu_put_8s(f, &bm->cmd);
+         qemu_put_8s(f, &bm->status);
+         qemu_put_be32s(f, &bm->addr);
+         /* XXX: if a transfer is pending, we do not save it yet */
+     }
+     /* per IDE interface data */
+     for(i = 0; i < 2; i++) {
+         IDEState *s = &d->ide_if[i * 2];
+         uint8_t drive1_selected;
+         qemu_put_8s(f, &s->cmd);
+         drive1_selected = (s->cur_drive != s);
+         qemu_put_8s(f, &drive1_selected);
+     }
+     /* per IDE drive data */
+     for(i = 0; i < 4; i++) {
+         ide_save(f, &d->ide_if[i]);
+     }
+ }
+ static int pci_ide_load(QEMUFile* f, void *opaque, int version_id)
+ {
+     PCIIDEState *d = opaque;
+     int ret, i;
 -        ide_load(f, &d->ide_if[i]);
++    if (version_id != 1 && version_id != 2)
+         return -EINVAL;
+     ret = pci_device_load(&d->dev, f);
+     if (ret < 0)
+         return ret;
+     for(i = 0; i < 2; i++) {
+         BMDMAState *bm = &d->bmdma[i];
+         qemu_get_8s(f, &bm->cmd);
+         qemu_get_8s(f, &bm->status);
+         qemu_get_be32s(f, &bm->addr);
+         /* XXX: if a transfer is pending, we do not save it yet */
+     }
+     /* per IDE interface data */
+     for(i = 0; i < 2; i++) {
+         IDEState *s = &d->ide_if[i * 2];
+         uint8_t drive1_selected;
+         qemu_get_8s(f, &s->cmd);
+         qemu_get_8s(f, &drive1_selected);
+         s->cur_drive = &d->ide_if[i * 2 + (drive1_selected != 0)];
+     }
+     /* per IDE drive data */
+     for(i = 0; i < 4; i++) {
++        ide_load(f, &d->ide_if[i], version_id);
+     }
+     return 0;
+ }
  /* XXX: call it also when the MRDMODE is changed from the PCI config
     registers */
  static void cmd646_update_irq(PCIIDEState *d)
diff --cc hw/pci.c
Simple merge
diff --cc hw/scsi-disk.c
Simple merge
diff --cc loader.c
index dcb5a6bfa8acc4a0724d815f4ac1b625d39cd033,cf603cc09909b52fc0fb030c60f19534b263764a..8ecb61d514dc90bd45d4d97cc7625e9765ddaed7
+++ b/loader.c
@@@ -358,9 -469,9 +468,9 @@@ int load_uimage(const char *filename, t
      if (fd < 0)
          return -1;
  
 -    size = read(fd, hdr, sizeof(uboot_image_header_t));
 +    size = qemu_read(fd, hdr, sizeof(uboot_image_header_t));
      if (size < 0)
-         goto fail;
+         goto out;
  
      bswap_uboot_header(hdr);
  
      *ep = hdr->ih_ep;
      data = qemu_malloc(hdr->ih_size);
      if (!data)
-         goto fail;
+         goto out;
  
 -    if (read(fd, data, hdr->ih_size) != hdr->ih_size) {
 +    if (qemu_read_ok(fd, data, hdr->ih_size) < 0) {
          fprintf(stderr, "Error reading file\n");
-         goto fail;
+         goto out;
+     }
+     if (hdr->ih_comp == IH_COMP_GZIP) {
+         uint8_t *compressed_data;
+         size_t max_bytes;
+         ssize_t bytes;
+         compressed_data = data;
+         max_bytes = UBOOT_MAX_GUNZIP_BYTES;
+         data = qemu_malloc(max_bytes);
+         bytes = gunzip(data, max_bytes, compressed_data, hdr->ih_size);
+         qemu_free(compressed_data);
+         if (bytes < 0) {
+             fprintf(stderr, "Unable to decompress gzipped image!\n");
+             goto out;
+         }
+         hdr->ih_size = bytes;
      }
  
      cpu_physical_memory_write_rom(hdr->ih_load, data, hdr->ih_size);
diff --cc osdep.c
Simple merge
diff --cc osdep.h
index 940c283f0163f04a76692dcd0bbc7a1b582b4ea7,ffbf221d7f540f3aaf2f93a3e77d6032931c77b6..f21db732c9ff2bbe7c907bd664b3d049b8e7742f
+++ b/osdep.h
@@@ -2,8 -2,15 +2,12 @@@
  #define QEMU_OSDEP_H
  
  #include <stdarg.h>
 -#ifdef __OpenBSD__
  #include <sys/types.h>
 -#include <sys/signal.h>
 -#endif
  
+ #ifndef _WIN32
+ #include <sys/time.h>
+ #endif
  #ifndef glue
  #define xglue(x, y) x ## y
  #define glue(x, y) xglue(x, y)
diff --cc qemu-char.c
index 0000000000000000000000000000000000000000,bc024e08d989bd6d722a50ef2849ef3f7e777287..0a01e16d4e3b6e8ff91e4ed6e8ee379f84834f5e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,2233 +1,2216 @@@
 -static int unix_write(int fd, const uint8_t *buf, int len1)
 -{
 -    int ret, len;
 -
 -    len = len1;
 -    while (len > 0) {
 -        ret = write(fd, buf, len);
 -        if (ret < 0) {
 -            if (errno != EINTR && errno != EAGAIN)
 -                return -1;
 -        } else if (ret == 0) {
 -            break;
 -        } else {
 -            buf += ret;
 -            len -= ret;
 -        }
 -    }
 -    return len1 - len;
 -}
 -
+ /*
+  * QEMU System Emulator
+  *
+  * Copyright (c) 2003-2008 Fabrice Bellard
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+  * of this software and associated documentation files (the "Software"), to deal
+  * in the Software without restriction, including without limitation the rights
+  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  * copies of the Software, and to permit persons to whom the Software is
+  * furnished to do so, subject to the following conditions:
+  *
+  * The above copyright notice and this permission notice shall be included in
+  * all copies or substantial portions of the Software.
+  *
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  * THE SOFTWARE.
+  */
+ #include "qemu-common.h"
+ #include "net.h"
+ #include "console.h"
+ #include "sysemu.h"
+ #include "qemu-timer.h"
+ #include "qemu-char.h"
+ #include "block.h"
+ #include "hw/usb.h"
+ #include "hw/baum.h"
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <signal.h>
+ #include <time.h>
+ #include <errno.h>
+ #include <sys/time.h>
+ #include <zlib.h>
+ #ifndef _WIN32
+ #include <sys/times.h>
+ #include <sys/wait.h>
+ #include <termios.h>
+ #include <sys/mman.h>
+ #include <sys/ioctl.h>
+ #include <sys/resource.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <net/if.h>
+ #ifdef __NetBSD__
+ #include <net/if_tap.h>
+ #endif
+ #ifdef __linux__
+ #include <linux/if_tun.h>
+ #endif
+ #include <arpa/inet.h>
+ #include <dirent.h>
+ #include <netdb.h>
+ #include <sys/select.h>
+ #ifdef _BSD
+ #include <sys/stat.h>
+ #ifdef __FreeBSD__
+ #include <libutil.h>
+ #include <dev/ppbus/ppi.h>
+ #include <dev/ppbus/ppbconf.h>
+ #else
+ #include <util.h>
+ #endif
+ #elif defined (__GLIBC__) && defined (__FreeBSD_kernel__)
+ #include <freebsd/stdlib.h>
+ #else
+ #ifdef __linux__
+ #include <pty.h>
+ #include <linux/ppdev.h>
+ #include <linux/parport.h>
+ #endif
+ #ifdef __sun__
+ #include <sys/stat.h>
+ #include <sys/ethernet.h>
+ #include <sys/sockio.h>
+ #include <netinet/arp.h>
+ #include <netinet/in.h>
+ #include <netinet/in_systm.h>
+ #include <netinet/ip.h>
+ #include <netinet/ip_icmp.h> // must come after ip.h
+ #include <netinet/udp.h>
+ #include <netinet/tcp.h>
+ #include <net/if.h>
+ #include <syslog.h>
+ #include <stropts.h>
+ #endif
+ #endif
+ #endif
+ #include "qemu_socket.h"
+ /***********************************************************/
+ /* character device */
+ static void qemu_chr_event(CharDriverState *s, int event)
+ {
+     if (!s->chr_event)
+         return;
+     s->chr_event(s->handler_opaque, event);
+ }
+ static void qemu_chr_reset_bh(void *opaque)
+ {
+     CharDriverState *s = opaque;
+     qemu_chr_event(s, CHR_EVENT_RESET);
+     qemu_bh_delete(s->bh);
+     s->bh = NULL;
+ }
+ void qemu_chr_reset(CharDriverState *s)
+ {
+     if (s->bh == NULL) {
+       s->bh = qemu_bh_new(qemu_chr_reset_bh, s);
+       qemu_bh_schedule(s->bh);
+     }
+ }
+ int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
+ {
+     return s->chr_write(s, buf, len);
+ }
+ int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg)
+ {
+     if (!s->chr_ioctl)
+         return -ENOTSUP;
+     return s->chr_ioctl(s, cmd, arg);
+ }
+ int qemu_chr_can_read(CharDriverState *s)
+ {
+     if (!s->chr_can_read)
+         return 0;
+     return s->chr_can_read(s->handler_opaque);
+ }
+ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len)
+ {
+     s->chr_read(s->handler_opaque, buf, len);
+ }
+ void qemu_chr_accept_input(CharDriverState *s)
+ {
+     if (s->chr_accept_input)
+         s->chr_accept_input(s);
+ }
+ void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
+ {
+     char buf[4096];
+     va_list ap;
+     va_start(ap, fmt);
+     vsnprintf(buf, sizeof(buf), fmt, ap);
+     qemu_chr_write(s, (uint8_t *)buf, strlen(buf));
+     va_end(ap);
+ }
+ void qemu_chr_send_event(CharDriverState *s, int event)
+ {
+     if (s->chr_send_event)
+         s->chr_send_event(s, event);
+ }
+ void qemu_chr_add_handlers(CharDriverState *s,
+                            IOCanRWHandler *fd_can_read,
+                            IOReadHandler *fd_read,
+                            IOEventHandler *fd_event,
+                            void *opaque)
+ {
+     s->chr_can_read = fd_can_read;
+     s->chr_read = fd_read;
+     s->chr_event = fd_event;
+     s->handler_opaque = opaque;
+     if (s->chr_update_read_handler)
+         s->chr_update_read_handler(s);
+ }
+ static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+     return len;
+ }
+ static CharDriverState *qemu_chr_open_null(void)
+ {
+     CharDriverState *chr;
+     chr = qemu_mallocz(sizeof(CharDriverState));
+     if (!chr)
+         return NULL;
+     chr->chr_write = null_chr_write;
+     return chr;
+ }
+ /* MUX driver for serial I/O splitting */
+ static int term_timestamps;
+ static int64_t term_timestamps_start;
+ #define MAX_MUX 4
+ #define MUX_BUFFER_SIZE 32    /* Must be a power of 2.  */
+ #define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1)
+ typedef struct {
+     IOCanRWHandler *chr_can_read[MAX_MUX];
+     IOReadHandler *chr_read[MAX_MUX];
+     IOEventHandler *chr_event[MAX_MUX];
+     void *ext_opaque[MAX_MUX];
+     CharDriverState *drv;
+     unsigned char buffer[MUX_BUFFER_SIZE];
+     int prod;
+     int cons;
+     int mux_cnt;
+     int term_got_escape;
+     int max_size;
+ } MuxDriver;
+ static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+     MuxDriver *d = chr->opaque;
+     int ret;
+     if (!term_timestamps) {
+         ret = d->drv->chr_write(d->drv, buf, len);
+     } else {
+         int i;
+         ret = 0;
+         for(i = 0; i < len; i++) {
+             ret += d->drv->chr_write(d->drv, buf+i, 1);
+             if (buf[i] == '\n') {
+                 char buf1[64];
+                 int64_t ti;
+                 int secs;
+                 ti = qemu_get_clock(rt_clock);
+                 if (term_timestamps_start == -1)
+                     term_timestamps_start = ti;
+                 ti -= term_timestamps_start;
+                 secs = ti / 1000000000;
+                 snprintf(buf1, sizeof(buf1),
+                          "[%02d:%02d:%02d.%03d] ",
+                          secs / 3600,
+                          (secs / 60) % 60,
+                          secs % 60,
+                          (int)((ti / 1000000) % 1000));
+                 d->drv->chr_write(d->drv, (uint8_t *)buf1, strlen(buf1));
+             }
+         }
+     }
+     return ret;
+ }
+ static const char * const mux_help[] = {
+     "% h    print this help\n\r",
+     "% x    exit emulator\n\r",
+     "% s    save disk data back to file (if -snapshot)\n\r",
+     "% t    toggle console timestamps\n\r"
+     "% b    send break (magic sysrq)\n\r",
+     "% c    switch between console and monitor\n\r",
+     "% %  sends %\n\r",
+     NULL
+ };
+ int term_escape_char = 0x01; /* ctrl-a is used for escape */
+ static void mux_print_help(CharDriverState *chr)
+ {
+     int i, j;
+     char ebuf[15] = "Escape-Char";
+     char cbuf[50] = "\n\r";
+     if (term_escape_char > 0 && term_escape_char < 26) {
+         snprintf(cbuf, sizeof(cbuf), "\n\r");
+         snprintf(ebuf, sizeof(ebuf), "C-%c", term_escape_char - 1 + 'a');
+     } else {
+         snprintf(cbuf, sizeof(cbuf),
+                  "\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r",
+                  term_escape_char);
+     }
+     chr->chr_write(chr, (uint8_t *)cbuf, strlen(cbuf));
+     for (i = 0; mux_help[i] != NULL; i++) {
+         for (j=0; mux_help[i][j] != '\0'; j++) {
+             if (mux_help[i][j] == '%')
+                 chr->chr_write(chr, (uint8_t *)ebuf, strlen(ebuf));
+             else
+                 chr->chr_write(chr, (uint8_t *)&mux_help[i][j], 1);
+         }
+     }
+ }
+ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
+ {
+     if (d->term_got_escape) {
+         d->term_got_escape = 0;
+         if (ch == term_escape_char)
+             goto send_char;
+         switch(ch) {
+         case '?':
+         case 'h':
+             mux_print_help(chr);
+             break;
+         case 'x':
+             {
+                  const char *term =  "QEMU: Terminated\n\r";
+                  chr->chr_write(chr,(uint8_t *)term,strlen(term));
+                  exit(0);
+                  break;
+             }
+         case 's':
+             {
+                 int i;
+                 for (i = 0; i < nb_drives; i++) {
+                         bdrv_commit(drives_table[i].bdrv);
+                 }
+             }
+             break;
+         case 'b':
+             qemu_chr_event(chr, CHR_EVENT_BREAK);
+             break;
+         case 'c':
+             /* Switch to the next registered device */
+             chr->focus++;
+             if (chr->focus >= d->mux_cnt)
+                 chr->focus = 0;
+             break;
+        case 't':
+            term_timestamps = !term_timestamps;
+            term_timestamps_start = -1;
+            break;
+         }
+     } else if (ch == term_escape_char) {
+         d->term_got_escape = 1;
+     } else {
+     send_char:
+         return 1;
+     }
+     return 0;
+ }
+ static void mux_chr_accept_input(CharDriverState *chr)
+ {
+     int m = chr->focus;
+     MuxDriver *d = chr->opaque;
+     while (d->prod != d->cons &&
+            d->chr_can_read[m] &&
+            d->chr_can_read[m](d->ext_opaque[m])) {
+         d->chr_read[m](d->ext_opaque[m],
+                        &d->buffer[d->cons++ & MUX_BUFFER_MASK], 1);
+     }
+ }
+ static int mux_chr_can_read(void *opaque)
+ {
+     CharDriverState *chr = opaque;
+     MuxDriver *d = chr->opaque;
+     if ((d->prod - d->cons) < MUX_BUFFER_SIZE)
+         return 1;
+     if (d->chr_can_read[chr->focus])
+         return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]);
+     return 0;
+ }
+ static void mux_chr_read(void *opaque, const uint8_t *buf, int size)
+ {
+     CharDriverState *chr = opaque;
+     MuxDriver *d = chr->opaque;
+     int m = chr->focus;
+     int i;
+     mux_chr_accept_input (opaque);
+     for(i = 0; i < size; i++)
+         if (mux_proc_byte(chr, d, buf[i])) {
+             if (d->prod == d->cons &&
+                 d->chr_can_read[m] &&
+                 d->chr_can_read[m](d->ext_opaque[m]))
+                 d->chr_read[m](d->ext_opaque[m], &buf[i], 1);
+             else
+                 d->buffer[d->prod++ & MUX_BUFFER_MASK] = buf[i];
+         }
+ }
+ static void mux_chr_event(void *opaque, int event)
+ {
+     CharDriverState *chr = opaque;
+     MuxDriver *d = chr->opaque;
+     int i;
+     /* Send the event to all registered listeners */
+     for (i = 0; i < d->mux_cnt; i++)
+         if (d->chr_event[i])
+             d->chr_event[i](d->ext_opaque[i], event);
+ }
+ static void mux_chr_update_read_handler(CharDriverState *chr)
+ {
+     MuxDriver *d = chr->opaque;
+     if (d->mux_cnt >= MAX_MUX) {
+         fprintf(stderr, "Cannot add I/O handlers, MUX array is full\n");
+         return;
+     }
+     d->ext_opaque[d->mux_cnt] = chr->handler_opaque;
+     d->chr_can_read[d->mux_cnt] = chr->chr_can_read;
+     d->chr_read[d->mux_cnt] = chr->chr_read;
+     d->chr_event[d->mux_cnt] = chr->chr_event;
+     /* Fix up the real driver with mux routines */
+     if (d->mux_cnt == 0) {
+         qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read,
+                               mux_chr_event, chr);
+     }
+     chr->focus = d->mux_cnt;
+     d->mux_cnt++;
+ }
+ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
+ {
+     CharDriverState *chr;
+     MuxDriver *d;
+     chr = qemu_mallocz(sizeof(CharDriverState));
+     if (!chr)
+         return NULL;
+     d = qemu_mallocz(sizeof(MuxDriver));
+     if (!d) {
+         free(chr);
+         return NULL;
+     }
+     chr->opaque = d;
+     d->drv = drv;
+     chr->focus = -1;
+     chr->chr_write = mux_chr_write;
+     chr->chr_update_read_handler = mux_chr_update_read_handler;
+     chr->chr_accept_input = mux_chr_accept_input;
+     return chr;
+ }
+ #ifdef _WIN32
+ int send_all(int fd, const void *buf, int len1)
+ {
+     int ret, len;
+     len = len1;
+     while (len > 0) {
+         ret = send(fd, buf, len, 0);
+         if (ret < 0) {
+             errno = WSAGetLastError();
+             if (errno != WSAEWOULDBLOCK) {
+                 return -1;
+             }
+         } else if (ret == 0) {
+             break;
+         } else {
+             buf += ret;
+             len -= ret;
+         }
+     }
+     return len1 - len;
+ }
+ #else
 -    return unix_write(fd, buf, len1);
+ int send_all(int fd, const void *buf, int len1)
+ {
++    return qemu_write(fd, buf, len1);
+ }
+ #endif /* !_WIN32 */
+ #ifndef _WIN32
+ typedef struct {
+     int fd_in, fd_out;
+     int max_size;
+ } FDCharDriver;
+ #define STDIO_MAX_CLIENTS 1
+ static int stdio_nb_clients = 0;
+ static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+     FDCharDriver *s = chr->opaque;
+     return send_all(s->fd_out, buf, len);
+ }
+ static int fd_chr_read_poll(void *opaque)
+ {
+     CharDriverState *chr = opaque;
+     FDCharDriver *s = chr->opaque;
+     s->max_size = qemu_chr_can_read(chr);
+     return s->max_size;
+ }
+ static void fd_chr_read(void *opaque)
+ {
+     CharDriverState *chr = opaque;
+     FDCharDriver *s = chr->opaque;
+     int size, len;
+     uint8_t buf[1024];
+     len = sizeof(buf);
+     if (len > s->max_size)
+         len = s->max_size;
+     if (len == 0)
+         return;
+     size = read(s->fd_in, buf, len);
+     if (size == 0) {
+         /* FD has been closed. Remove it from the active list.  */
+         qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL);
+         return;
+     }
+     if (size > 0) {
+         qemu_chr_read(chr, buf, size);
+     }
+ }
+ static void fd_chr_update_read_handler(CharDriverState *chr)
+ {
+     FDCharDriver *s = chr->opaque;
+     if (s->fd_in >= 0) {
+         if (nographic && s->fd_in == 0) {
+         } else {
+             qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll,
+                                  fd_chr_read, NULL, chr);
+         }
+     }
+ }
+ static void fd_chr_close(struct CharDriverState *chr)
+ {
+     FDCharDriver *s = chr->opaque;
+     if (s->fd_in >= 0) {
+         if (nographic && s->fd_in == 0) {
+         } else {
+             qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL);
+         }
+     }
+     qemu_free(s);
+ }
+ /* open a character device to a unix fd */
+ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
+ {
+     CharDriverState *chr;
+     FDCharDriver *s;
++    socket_set_nonblock(fd_in);
++    socket_set_nonblock(fd_out);
++
+     chr = qemu_mallocz(sizeof(CharDriverState));
+     if (!chr)
+         return NULL;
+     s = qemu_mallocz(sizeof(FDCharDriver));
+     if (!s) {
+         free(chr);
+         return NULL;
+     }
+     s->fd_in = fd_in;
+     s->fd_out = fd_out;
+     chr->opaque = s;
+     chr->chr_write = fd_chr_write;
+     chr->chr_update_read_handler = fd_chr_update_read_handler;
+     chr->chr_close = fd_chr_close;
+     qemu_chr_reset(chr);
+     return chr;
+ }
+ static CharDriverState *qemu_chr_open_file_out(const char *file_out)
+ {
+     int fd_out;
+     TFR(fd_out = open(file_out, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666));
+     if (fd_out < 0)
+         return NULL;
+     return qemu_chr_open_fd(-1, fd_out);
+ }
+ static CharDriverState *qemu_chr_open_pipe(const char *filename)
+ {
+     int fd_in, fd_out;
+     char filename_in[256], filename_out[256];
+     snprintf(filename_in, 256, "%s.in", filename);
+     snprintf(filename_out, 256, "%s.out", filename);
+     TFR(fd_in = open(filename_in, O_RDWR | O_BINARY));
+     TFR(fd_out = open(filename_out, O_RDWR | O_BINARY));
+     if (fd_in < 0 || fd_out < 0) {
+       if (fd_in >= 0)
+           close(fd_in);
+       if (fd_out >= 0)
+           close(fd_out);
+         TFR(fd_in = fd_out = open(filename, O_RDWR | O_BINARY));
+         if (fd_in < 0)
+             return NULL;
+     }
+     return qemu_chr_open_fd(fd_in, fd_out);
+ }
+ /* for STDIO, we handle the case where several clients use it
+    (nographic mode) */
+ #define TERM_FIFO_MAX_SIZE 1
+ static uint8_t term_fifo[TERM_FIFO_MAX_SIZE];
+ static int term_fifo_size;
+ static int stdio_read_poll(void *opaque)
+ {
+     CharDriverState *chr = opaque;
+     /* try to flush the queue if needed */
+     if (term_fifo_size != 0 && qemu_chr_can_read(chr) > 0) {
+         qemu_chr_read(chr, term_fifo, 1);
+         term_fifo_size = 0;
+     }
+     /* see if we can absorb more chars */
+     if (term_fifo_size == 0)
+         return 1;
+     else
+         return 0;
+ }
+ static void stdio_read(void *opaque)
+ {
+     int size;
+     uint8_t buf[1];
+     CharDriverState *chr = opaque;
+     size = read(0, buf, 1);
+     if (size == 0) {
+         /* stdin has been closed. Remove it from the active list.  */
+         qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL);
+         return;
+     }
+     if (size > 0) {
+         if (qemu_chr_can_read(chr) > 0) {
+             qemu_chr_read(chr, buf, 1);
+         } else if (term_fifo_size == 0) {
+             term_fifo[term_fifo_size++] = buf[0];
+         }
+     }
+ }
+ /* init terminal so that we can grab keys */
+ static struct termios oldtty;
+ static int old_fd0_flags;
+ static int term_atexit_done;
+ static void term_exit(void)
+ {
+     tcsetattr (0, TCSANOW, &oldtty);
+     fcntl(0, F_SETFL, old_fd0_flags);
+ }
+ static void term_init(void)
+ {
+     struct termios tty;
+     tcgetattr (0, &tty);
+     oldtty = tty;
+     old_fd0_flags = fcntl(0, F_GETFL);
+     tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
+                           |INLCR|IGNCR|ICRNL|IXON);
+     tty.c_oflag |= OPOST;
+     tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
+     /* if graphical mode, we allow Ctrl-C handling */
+     if (nographic)
+         tty.c_lflag &= ~ISIG;
+     tty.c_cflag &= ~(CSIZE|PARENB);
+     tty.c_cflag |= CS8;
+     tty.c_cc[VMIN] = 1;
+     tty.c_cc[VTIME] = 0;
+     tcsetattr (0, TCSANOW, &tty);
+     if (!term_atexit_done++)
+         atexit(term_exit);
+     fcntl(0, F_SETFL, O_NONBLOCK);
+ }
+ static void qemu_chr_close_stdio(struct CharDriverState *chr)
+ {
+     term_exit();
+     stdio_nb_clients--;
+     qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL);
+     fd_chr_close(chr);
+ }
+ static CharDriverState *qemu_chr_open_stdio(void)
+ {
+     CharDriverState *chr;
+     if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
+         return NULL;
+     chr = qemu_chr_open_fd(0, 1);
+     chr->chr_close = qemu_chr_close_stdio;
+     qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr);
+     stdio_nb_clients++;
+     term_init();
+     return chr;
+ }
+ #ifdef __sun__
+ /* Once Solaris has openpty(), this is going to be removed. */
+ int openpty(int *amaster, int *aslave, char *name,
+             struct termios *termp, struct winsize *winp)
+ {
+         const char *slave;
+         int mfd = -1, sfd = -1;
+         *amaster = *aslave = -1;
+         mfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
+         if (mfd < 0)
+                 goto err;
+         if (grantpt(mfd) == -1 || unlockpt(mfd) == -1)
+                 goto err;
+         if ((slave = ptsname(mfd)) == NULL)
+                 goto err;
+         if ((sfd = open(slave, O_RDONLY | O_NOCTTY)) == -1)
+                 goto err;
+         if (ioctl(sfd, I_PUSH, "ptem") == -1 ||
+             (termp != NULL && tcgetattr(sfd, termp) < 0))
+                 goto err;
+         if (amaster)
+                 *amaster = mfd;
+         if (aslave)
+                 *aslave = sfd;
+         if (winp)
+                 ioctl(sfd, TIOCSWINSZ, winp);
+         return 0;
+ err:
+         if (sfd != -1)
+                 close(sfd);
+         close(mfd);
+         return -1;
+ }
+ void cfmakeraw (struct termios *termios_p)
+ {
+         termios_p->c_iflag &=
+                 ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+         termios_p->c_oflag &= ~OPOST;
+         termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+         termios_p->c_cflag &= ~(CSIZE|PARENB);
+         termios_p->c_cflag |= CS8;
+         termios_p->c_cc[VMIN] = 0;
+         termios_p->c_cc[VTIME] = 0;
+ }
+ #endif
+ #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
+     || defined(__NetBSD__) || defined(__OpenBSD__)
+ typedef struct {
+     int fd;
+     int connected;
+     int polling;
+     int read_bytes;
+     QEMUTimer *timer;
+ } PtyCharDriver;
+ static void pty_chr_update_read_handler(CharDriverState *chr);
+ static void pty_chr_state(CharDriverState *chr, int connected);
+ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+     PtyCharDriver *s = chr->opaque;
+     if (!s->connected) {
+         /* guest sends data, check for (re-)connect */
+         pty_chr_update_read_handler(chr);
+         return 0;
+     }
+     return send_all(s->fd, buf, len);
+ }
+ static int pty_chr_read_poll(void *opaque)
+ {
+     CharDriverState *chr = opaque;
+     PtyCharDriver *s = chr->opaque;
+     s->read_bytes = qemu_chr_can_read(chr);
+     return s->read_bytes;
+ }
+ static void pty_chr_read(void *opaque)
+ {
+     CharDriverState *chr = opaque;
+     PtyCharDriver *s = chr->opaque;
+     int size, len;
+     uint8_t buf[1024];
+     len = sizeof(buf);
+     if (len > s->read_bytes)
+         len = s->read_bytes;
+     if (len == 0)
+         return;
+     size = read(s->fd, buf, len);
+     if ((size == -1 && errno == EIO) ||
+         (size == 0)) {
+         pty_chr_state(chr, 0);
+         return;
+     }
+     if (size > 0) {
+         pty_chr_state(chr, 1);
+         qemu_chr_read(chr, buf, size);
+     }
+ }
+ static void pty_chr_update_read_handler(CharDriverState *chr)
+ {
+     PtyCharDriver *s = chr->opaque;
+     qemu_set_fd_handler2(s->fd, pty_chr_read_poll,
+                          pty_chr_read, NULL, chr);
+     s->polling = 1;
+     /*
+      * Short timeout here: just need wait long enougth that qemu makes
+      * it through the poll loop once.  When reconnected we want a
+      * short timeout so we notice it almost instantly.  Otherwise
+      * read() gives us -EIO instantly, making pty_chr_state() reset the
+      * timeout to the normal (much longer) poll interval before the
+      * timer triggers.
+      */
+     qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 10);
+ }
+ static void pty_chr_state(CharDriverState *chr, int connected)
+ {
+     PtyCharDriver *s = chr->opaque;
+     if (!connected) {
+         qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+         s->connected = 0;
+         s->polling = 0;
+         /* (re-)connect poll interval for idle guests: once per second.
+          * We check more frequently in case the guests sends data to
+          * the virtual device linked to our pty. */
+         qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 1000);
+     } else {
+         if (!s->connected)
+             qemu_chr_reset(chr);
+         s->connected = 1;
+     }
+ }
+ static void pty_chr_timer(void *opaque)
+ {
+     struct CharDriverState *chr = opaque;
+     PtyCharDriver *s = chr->opaque;
+     if (s->connected)
+         return;
+     if (s->polling) {
+         /* If we arrive here without polling being cleared due
+          * read returning -EIO, then we are (re-)connected */
+         pty_chr_state(chr, 1);
+         return;
+     }
+     /* Next poll ... */
+     pty_chr_update_read_handler(chr);
+ }
+ static void pty_chr_close(struct CharDriverState *chr)
+ {
+     PtyCharDriver *s = chr->opaque;
+     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+     close(s->fd);
+     qemu_free(s);
+ }
+ static CharDriverState *qemu_chr_open_pty(void)
+ {
+     CharDriverState *chr;
+     PtyCharDriver *s;
+     struct termios tty;
+     int slave_fd, len;
+ #if defined(__OpenBSD__)
+     char pty_name[PATH_MAX];
+ #define q_ptsname(x) pty_name
+ #else
+     char *pty_name = NULL;
+ #define q_ptsname(x) ptsname(x)
+ #endif
+     chr = qemu_mallocz(sizeof(CharDriverState));
+     if (!chr)
+         return NULL;
+     s = qemu_mallocz(sizeof(PtyCharDriver));
+     if (!s) {
+         qemu_free(chr);
+         return NULL;
+     }
+     if (openpty(&s->fd, &slave_fd, pty_name, NULL, NULL) < 0) {
+         return NULL;
+     }
+     /* Set raw attributes on the pty. */
+     tcgetattr(slave_fd, &tty);
+     cfmakeraw(&tty);
+     tcsetattr(slave_fd, TCSAFLUSH, &tty);
+     close(slave_fd);
+     len = strlen(q_ptsname(s->fd)) + 5;
+     chr->filename = qemu_malloc(len);
+     snprintf(chr->filename, len, "pty:%s", q_ptsname(s->fd));
+     fprintf(stderr, "char device redirected to %s\n", q_ptsname(s->fd));
+     chr->opaque = s;
+     chr->chr_write = pty_chr_write;
+     chr->chr_update_read_handler = pty_chr_update_read_handler;
+     chr->chr_close = pty_chr_close;
+     s->timer = qemu_new_timer(rt_clock, pty_chr_timer, chr);
+     return chr;
+ }
+ static void tty_serial_init(int fd, int speed,
+                             int parity, int data_bits, int stop_bits)
+ {
+     struct termios tty;
+     speed_t spd;
+ #if 0
+     printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n",
+            speed, parity, data_bits, stop_bits);
+ #endif
+     tcgetattr (fd, &tty);
+ #define MARGIN 1.1
+     if (speed <= 50 * MARGIN)
+         spd = B50;
+     else if (speed <= 75 * MARGIN)
+         spd = B75;
+     else if (speed <= 300 * MARGIN)
+         spd = B300;
+     else if (speed <= 600 * MARGIN)
+         spd = B600;
+     else if (speed <= 1200 * MARGIN)
+         spd = B1200;
+     else if (speed <= 2400 * MARGIN)
+         spd = B2400;
+     else if (speed <= 4800 * MARGIN)
+         spd = B4800;
+     else if (speed <= 9600 * MARGIN)
+         spd = B9600;
+     else if (speed <= 19200 * MARGIN)
+         spd = B19200;
+     else if (speed <= 38400 * MARGIN)
+         spd = B38400;
+     else if (speed <= 57600 * MARGIN)
+         spd = B57600;
+     else if (speed <= 115200 * MARGIN)
+         spd = B115200;
+     else
+         spd = B115200;
+     cfsetispeed(&tty, spd);
+     cfsetospeed(&tty, spd);
+     tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
+                           |INLCR|IGNCR|ICRNL|IXON);
+     tty.c_oflag |= OPOST;
+     tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG);
+     tty.c_cflag &= ~(CSIZE|PARENB|PARODD|CRTSCTS|CSTOPB);
+     switch(data_bits) {
+     default:
+     case 8:
+         tty.c_cflag |= CS8;
+         break;
+     case 7:
+         tty.c_cflag |= CS7;
+         break;
+     case 6:
+         tty.c_cflag |= CS6;
+         break;
+     case 5:
+         tty.c_cflag |= CS5;
+         break;
+     }
+     switch(parity) {
+     default:
+     case 'N':
+         break;
+     case 'E':
+         tty.c_cflag |= PARENB;
+         break;
+     case 'O':
+         tty.c_cflag |= PARENB | PARODD;
+         break;
+     }
+     if (stop_bits == 2)
+         tty.c_cflag |= CSTOPB;
+     tcsetattr (fd, TCSANOW, &tty);
+ }
+ static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg)
+ {
+     FDCharDriver *s = chr->opaque;
+     switch(cmd) {
+     case CHR_IOCTL_SERIAL_SET_PARAMS:
+         {
+             QEMUSerialSetParams *ssp = arg;
+             tty_serial_init(s->fd_in, ssp->speed, ssp->parity,
+                             ssp->data_bits, ssp->stop_bits);
+         }
+         break;
+     case CHR_IOCTL_SERIAL_SET_BREAK:
+         {
+             int enable = *(int *)arg;
+             if (enable)
+                 tcsendbreak(s->fd_in, 1);
+         }
+         break;
+     case CHR_IOCTL_SERIAL_GET_TIOCM:
+         {
+             int sarg = 0;
+             int *targ = (int *)arg;
+             ioctl(s->fd_in, TIOCMGET, &sarg);
+             *targ = 0;
+             if (sarg | TIOCM_CTS)
+                 *targ |= CHR_TIOCM_CTS;
+             if (sarg | TIOCM_CAR)
+                 *targ |= CHR_TIOCM_CAR;
+             if (sarg | TIOCM_DSR)
+                 *targ |= CHR_TIOCM_DSR;
+             if (sarg | TIOCM_RI)
+                 *targ |= CHR_TIOCM_RI;
+             if (sarg | TIOCM_DTR)
+                 *targ |= CHR_TIOCM_DTR;
+             if (sarg | TIOCM_RTS)
+                 *targ |= CHR_TIOCM_RTS;
+         }
+         break;
+     case CHR_IOCTL_SERIAL_SET_TIOCM:
+         {
+             int sarg = *(int *)arg;
+             int targ = 0;
+             if (sarg | CHR_TIOCM_DTR)
+                 targ |= TIOCM_DTR;
+             if (sarg | CHR_TIOCM_RTS)
+                 targ |= TIOCM_RTS;
+             ioctl(s->fd_in, TIOCMSET, &targ);
+         }
+         break;
+     default:
+         return -ENOTSUP;
+     }
+     return 0;
+ }
+ static CharDriverState *qemu_chr_open_tty(const char *filename)
+ {
+     CharDriverState *chr;
+     int fd;
+     TFR(fd = open(filename, O_RDWR | O_NONBLOCK));
+     tty_serial_init(fd, 115200, 'N', 8, 1);
+     chr = qemu_chr_open_fd(fd, fd);
+     if (!chr) {
+         close(fd);
+         return NULL;
+     }
+     chr->chr_ioctl = tty_serial_ioctl;
+     qemu_chr_reset(chr);
+     return chr;
+ }
+ #else  /* ! __linux__ && ! __sun__ */
+ static CharDriverState *qemu_chr_open_pty(void)
+ {
+     return NULL;
+ }
+ #endif /* __linux__ || __sun__ */
+ #if defined(__linux__)
+ typedef struct {
+     int fd;
+     int mode;
+ } ParallelCharDriver;
+ static int pp_hw_mode(ParallelCharDriver *s, uint16_t mode)
+ {
+     if (s->mode != mode) {
+       int m = mode;
+         if (ioctl(s->fd, PPSETMODE, &m) < 0)
+             return 0;
+       s->mode = mode;
+     }
+     return 1;
+ }
+ static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
+ {
+     ParallelCharDriver *drv = chr->opaque;
+     int fd = drv->fd;
+     uint8_t b;
+     switch(cmd) {
+     case CHR_IOCTL_PP_READ_DATA:
+         if (ioctl(fd, PPRDATA, &b) < 0)
+             return -ENOTSUP;
+         *(uint8_t *)arg = b;
+         break;
+     case CHR_IOCTL_PP_WRITE_DATA:
+         b = *(uint8_t *)arg;
+         if (ioctl(fd, PPWDATA, &b) < 0)
+             return -ENOTSUP;
+         break;
+     case CHR_IOCTL_PP_READ_CONTROL:
+         if (ioctl(fd, PPRCONTROL, &b) < 0)
+             return -ENOTSUP;
+       /* Linux gives only the lowest bits, and no way to know data
+          direction! For better compatibility set the fixed upper
+          bits. */
+         *(uint8_t *)arg = b | 0xc0;
+         break;
+     case CHR_IOCTL_PP_WRITE_CONTROL:
+         b = *(uint8_t *)arg;
+         if (ioctl(fd, PPWCONTROL, &b) < 0)
+             return -ENOTSUP;
+         break;
+     case CHR_IOCTL_PP_READ_STATUS:
+         if (ioctl(fd, PPRSTATUS, &b) < 0)
+             return -ENOTSUP;
+         *(uint8_t *)arg = b;
+         break;
+     case CHR_IOCTL_PP_DATA_DIR:
+         if (ioctl(fd, PPDATADIR, (int *)arg) < 0)
+             return -ENOTSUP;
+         break;
+     case CHR_IOCTL_PP_EPP_READ_ADDR:
+       if (pp_hw_mode(drv, IEEE1284_MODE_EPP|IEEE1284_ADDR)) {
+           struct ParallelIOArg *parg = arg;
+           int n = read(fd, parg->buffer, parg->count);
+           if (n != parg->count) {
+               return -EIO;
+           }
+       }
+         break;
+     case CHR_IOCTL_PP_EPP_READ:
+       if (pp_hw_mode(drv, IEEE1284_MODE_EPP)) {
+           struct ParallelIOArg *parg = arg;
+           int n = read(fd, parg->buffer, parg->count);
+           if (n != parg->count) {
+               return -EIO;
+           }
+       }
+         break;
+     case CHR_IOCTL_PP_EPP_WRITE_ADDR:
+       if (pp_hw_mode(drv, IEEE1284_MODE_EPP|IEEE1284_ADDR)) {
+           struct ParallelIOArg *parg = arg;
+           int n = write(fd, parg->buffer, parg->count);
+           if (n != parg->count) {
+               return -EIO;
+           }
+       }
+         break;
+     case CHR_IOCTL_PP_EPP_WRITE:
+       if (pp_hw_mode(drv, IEEE1284_MODE_EPP)) {
+           struct ParallelIOArg *parg = arg;
+           int n = write(fd, parg->buffer, parg->count);
+           if (n != parg->count) {
+               return -EIO;
+           }
+       }
+         break;
+     default:
+         return -ENOTSUP;
+     }
+     return 0;
+ }
+ static void pp_close(CharDriverState *chr)
+ {
+     ParallelCharDriver *drv = chr->opaque;
+     int fd = drv->fd;
+     pp_hw_mode(drv, IEEE1284_MODE_COMPAT);
+     ioctl(fd, PPRELEASE);
+     close(fd);
+     qemu_free(drv);
+ }
+ static CharDriverState *qemu_chr_open_pp(const char *filename)
+ {
+     CharDriverState *chr;
+     ParallelCharDriver *drv;
+     int fd;
+     TFR(fd = open(filename, O_RDWR));
+     if (fd < 0)
+         return NULL;
+     if (ioctl(fd, PPCLAIM) < 0) {
+         close(fd);
+         return NULL;
+     }
+     drv = qemu_mallocz(sizeof(ParallelCharDriver));
+     if (!drv) {
+         close(fd);
+         return NULL;
+     }
+     drv->fd = fd;
+     drv->mode = IEEE1284_MODE_COMPAT;
+     chr = qemu_mallocz(sizeof(CharDriverState));
+     if (!chr) {
+       qemu_free(drv);
+         close(fd);
+         return NULL;
+     }
+     chr->chr_write = null_chr_write;
+     chr->chr_ioctl = pp_ioctl;
+     chr->chr_close = pp_close;
+     chr->opaque = drv;
+     qemu_chr_reset(chr);
+     return chr;
+ }
+ #endif /* __linux__ */
+ #if defined(__FreeBSD__)
+ static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
+ {
+     int fd = (int)chr->opaque;
+     uint8_t b;
+     switch(cmd) {
+     case CHR_IOCTL_PP_READ_DATA:
+         if (ioctl(fd, PPIGDATA, &b) < 0)
+             return -ENOTSUP;
+         *(uint8_t *)arg = b;
+         break;
+     case CHR_IOCTL_PP_WRITE_DATA:
+         b = *(uint8_t *)arg;
+         if (ioctl(fd, PPISDATA, &b) < 0)
+             return -ENOTSUP;
+         break;
+     case CHR_IOCTL_PP_READ_CONTROL:
+         if (ioctl(fd, PPIGCTRL, &b) < 0)
+             return -ENOTSUP;
+         *(uint8_t *)arg = b;
+         break;
+     case CHR_IOCTL_PP_WRITE_CONTROL:
+         b = *(uint8_t *)arg;
+         if (ioctl(fd, PPISCTRL, &b) < 0)
+             return -ENOTSUP;
+         break;
+     case CHR_IOCTL_PP_READ_STATUS:
+         if (ioctl(fd, PPIGSTATUS, &b) < 0)
+             return -ENOTSUP;
+         *(uint8_t *)arg = b;
+         break;
+     default:
+         return -ENOTSUP;
+     }
+     return 0;
+ }
+ static CharDriverState *qemu_chr_open_pp(const char *filename)
+ {
+     CharDriverState *chr;
+     int fd;
+     fd = open(filename, O_RDWR);
+     if (fd < 0)
+         return NULL;
+     chr = qemu_mallocz(sizeof(CharDriverState));
+     if (!chr) {
+         close(fd);
+         return NULL;
+     }
+     chr->opaque = (void *)fd;
+     chr->chr_write = null_chr_write;
+     chr->chr_ioctl = pp_ioctl;
+     return chr;
+ }
+ #endif
+ #else /* _WIN32 */
+ typedef struct {
+     int max_size;
+     HANDLE hcom, hrecv, hsend;
+     OVERLAPPED orecv, osend;
+     BOOL fpipe;
+     DWORD len;
+ } WinCharState;
+ #define NSENDBUF 2048
+ #define NRECVBUF 2048
+ #define MAXCONNECT 1
+ #define NTIMEOUT 5000
+ static int win_chr_poll(void *opaque);
+ static int win_chr_pipe_poll(void *opaque);
+ static void win_chr_close(CharDriverState *chr)
+ {
+     WinCharState *s = chr->opaque;
+     if (s->hsend) {
+         CloseHandle(s->hsend);
+         s->hsend = NULL;
+     }
+     if (s->hrecv) {
+         CloseHandle(s->hrecv);
+         s->hrecv = NULL;
+     }
+     if (s->hcom) {
+         CloseHandle(s->hcom);
+         s->hcom = NULL;
+     }
+     if (s->fpipe)
+         qemu_del_polling_cb(win_chr_pipe_poll, chr);
+     else
+         qemu_del_polling_cb(win_chr_poll, chr);
+ }
+ static int win_chr_init(CharDriverState *chr, const char *filename)
+ {
+     WinCharState *s = chr->opaque;
+     COMMCONFIG comcfg;
+     COMMTIMEOUTS cto = { 0, 0, 0, 0, 0};
+     COMSTAT comstat;
+     DWORD size;
+     DWORD err;
+     s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
+     if (!s->hsend) {
+         fprintf(stderr, "Failed CreateEvent\n");
+         goto fail;
+     }
+     s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL);
+     if (!s->hrecv) {
+         fprintf(stderr, "Failed CreateEvent\n");
+         goto fail;
+     }
+     s->hcom = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL,
+                       OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
+     if (s->hcom == INVALID_HANDLE_VALUE) {
+         fprintf(stderr, "Failed CreateFile (%lu)\n", GetLastError());
+         s->hcom = NULL;
+         goto fail;
+     }
+     if (!SetupComm(s->hcom, NRECVBUF, NSENDBUF)) {
+         fprintf(stderr, "Failed SetupComm\n");
+         goto fail;
+     }
+     ZeroMemory(&comcfg, sizeof(COMMCONFIG));
+     size = sizeof(COMMCONFIG);
+     GetDefaultCommConfig(filename, &comcfg, &size);
+     comcfg.dcb.DCBlength = sizeof(DCB);
+     CommConfigDialog(filename, NULL, &comcfg);
+     if (!SetCommState(s->hcom, &comcfg.dcb)) {
+         fprintf(stderr, "Failed SetCommState\n");
+         goto fail;
+     }
+     if (!SetCommMask(s->hcom, EV_ERR)) {
+         fprintf(stderr, "Failed SetCommMask\n");
+         goto fail;
+     }
+     cto.ReadIntervalTimeout = MAXDWORD;
+     if (!SetCommTimeouts(s->hcom, &cto)) {
+         fprintf(stderr, "Failed SetCommTimeouts\n");
+         goto fail;
+     }
+     if (!ClearCommError(s->hcom, &err, &comstat)) {
+         fprintf(stderr, "Failed ClearCommError\n");
+         goto fail;
+     }
+     qemu_add_polling_cb(win_chr_poll, chr);
+     return 0;
+  fail:
+     win_chr_close(chr);
+     return -1;
+ }
+ static int win_chr_write(CharDriverState *chr, const uint8_t *buf, int len1)
+ {
+     WinCharState *s = chr->opaque;
+     DWORD len, ret, size, err;
+     len = len1;
+     ZeroMemory(&s->osend, sizeof(s->osend));
+     s->osend.hEvent = s->hsend;
+     while (len > 0) {
+         if (s->hsend)
+             ret = WriteFile(s->hcom, buf, len, &size, &s->osend);
+         else
+             ret = WriteFile(s->hcom, buf, len, &size, NULL);
+         if (!ret) {
+             err = GetLastError();
+             if (err == ERROR_IO_PENDING) {
+                 ret = GetOverlappedResult(s->hcom, &s->osend, &size, TRUE);
+                 if (ret) {
+                     buf += size;
+                     len -= size;
+                 } else {
+                     break;
+                 }
+             } else {
+                 break;
+             }
+         } else {
+             buf += size;
+             len -= size;
+         }
+     }
+     return len1 - len;
+ }
+ static int win_chr_read_poll(CharDriverState *chr)
+ {
+     WinCharState *s = chr->opaque;
+     s->max_size = qemu_chr_can_read(chr);
+     return s->max_size;
+ }
+ static void win_chr_readfile(CharDriverState *chr)
+ {
+     WinCharState *s = chr->opaque;
+     int ret, err;
+     uint8_t buf[1024];
+     DWORD size;
+     ZeroMemory(&s->orecv, sizeof(s->orecv));
+     s->orecv.hEvent = s->hrecv;
+     ret = ReadFile(s->hcom, buf, s->len, &size, &s->orecv);
+     if (!ret) {
+         err = GetLastError();
+         if (err == ERROR_IO_PENDING) {
+             ret = GetOverlappedResult(s->hcom, &s->orecv, &size, TRUE);
+         }
+     }
+     if (size > 0) {
+         qemu_chr_read(chr, buf, size);
+     }
+ }
+ static void win_chr_read(CharDriverState *chr)
+ {
+     WinCharState *s = chr->opaque;
+     if (s->len > s->max_size)
+         s->len = s->max_size;
+     if (s->len == 0)
+         return;
+     win_chr_readfile(chr);
+ }
+ static int win_chr_poll(void *opaque)
+ {
+     CharDriverState *chr = opaque;
+     WinCharState *s = chr->opaque;
+     COMSTAT status;
+     DWORD comerr;
+     ClearCommError(s->hcom, &comerr, &status);
+     if (status.cbInQue > 0) {
+         s->len = status.cbInQue;
+         win_chr_read_poll(chr);
+         win_chr_read(chr);
+         return 1;
+     }
+     return 0;
+ }
+ static CharDriverState *qemu_chr_open_win(const char *filename)
+ {
+     CharDriverState *chr;
+     WinCharState *s;
+     chr = qemu_mallocz(sizeof(CharDriverState));
+     if (!chr)
+         return NULL;
+     s = qemu_mallocz(sizeof(WinCharState));
+     if (!s) {
+         free(chr);
+         return NULL;
+     }
+     chr->opaque = s;
+     chr->chr_write = win_chr_write;
+     chr->chr_close = win_chr_close;
+     if (win_chr_init(chr, filename) < 0) {
+         free(s);
+         free(chr);
+         return NULL;
+     }
+     qemu_chr_reset(chr);
+     return chr;
+ }
+ static int win_chr_pipe_poll(void *opaque)
+ {
+     CharDriverState *chr = opaque;
+     WinCharState *s = chr->opaque;
+     DWORD size;
+     PeekNamedPipe(s->hcom, NULL, 0, NULL, &size, NULL);
+     if (size > 0) {
+         s->len = size;
+         win_chr_read_poll(chr);
+         win_chr_read(chr);
+         return 1;
+     }
+     return 0;
+ }
+ static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
+ {
+     WinCharState *s = chr->opaque;
+     OVERLAPPED ov;
+     int ret;
+     DWORD size;
+     char openname[256];
+     s->fpipe = TRUE;
+     s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
+     if (!s->hsend) {
+         fprintf(stderr, "Failed CreateEvent\n");
+         goto fail;
+     }
+     s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL);
+     if (!s->hrecv) {
+         fprintf(stderr, "Failed CreateEvent\n");
+         goto fail;
+     }
+     snprintf(openname, sizeof(openname), "\\\\.\\pipe\\%s", filename);
+     s->hcom = CreateNamedPipe(openname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+                               PIPE_TYPE_BYTE | PIPE_READMODE_BYTE |
+                               PIPE_WAIT,
+                               MAXCONNECT, NSENDBUF, NRECVBUF, NTIMEOUT, NULL);
+     if (s->hcom == INVALID_HANDLE_VALUE) {
+         fprintf(stderr, "Failed CreateNamedPipe (%lu)\n", GetLastError());
+         s->hcom = NULL;
+         goto fail;
+     }
+     ZeroMemory(&ov, sizeof(ov));
+     ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+     ret = ConnectNamedPipe(s->hcom, &ov);
+     if (ret) {
+         fprintf(stderr, "Failed ConnectNamedPipe\n");
+         goto fail;
+     }
+     ret = GetOverlappedResult(s->hcom, &ov, &size, TRUE);
+     if (!ret) {
+         fprintf(stderr, "Failed GetOverlappedResult\n");
+         if (ov.hEvent) {
+             CloseHandle(ov.hEvent);
+             ov.hEvent = NULL;
+         }
+         goto fail;
+     }
+     if (ov.hEvent) {
+         CloseHandle(ov.hEvent);
+         ov.hEvent = NULL;
+     }
+     qemu_add_polling_cb(win_chr_pipe_poll, chr);
+     return 0;
+  fail:
+     win_chr_close(chr);
+     return -1;
+ }
+ static CharDriverState *qemu_chr_open_win_pipe(const char *filename)
+ {
+     CharDriverState *chr;
+     WinCharState *s;
+     chr = qemu_mallocz(sizeof(CharDriverState));
+     if (!chr)
+         return NULL;
+     s = qemu_mallocz(sizeof(WinCharState));
+     if (!s) {
+         free(chr);
+         return NULL;
+     }
+     chr->opaque = s;
+     chr->chr_write = win_chr_write;
+     chr->chr_close = win_chr_close;
+     if (win_chr_pipe_init(chr, filename) < 0) {
+         free(s);
+         free(chr);
+         return NULL;
+     }
+     qemu_chr_reset(chr);
+     return chr;
+ }
+ static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
+ {
+     CharDriverState *chr;
+     WinCharState *s;
+     chr = qemu_mallocz(sizeof(CharDriverState));
+     if (!chr)
+         return NULL;
+     s = qemu_mallocz(sizeof(WinCharState));
+     if (!s) {
+         free(chr);
+         return NULL;
+     }
+     s->hcom = fd_out;
+     chr->opaque = s;
+     chr->chr_write = win_chr_write;
+     qemu_chr_reset(chr);
+     return chr;
+ }
+ static CharDriverState *qemu_chr_open_win_con(const char *filename)
+ {
+     return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE));
+ }
+ static CharDriverState *qemu_chr_open_win_file_out(const char *file_out)
+ {
+     HANDLE fd_out;
+     fd_out = CreateFile(file_out, GENERIC_WRITE, FILE_SHARE_READ, NULL,
+                         OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+     if (fd_out == INVALID_HANDLE_VALUE)
+         return NULL;
+     return qemu_chr_open_win_file(fd_out);
+ }
+ #endif /* !_WIN32 */
+ /***********************************************************/
+ /* UDP Net console */
+ typedef struct {
+     int fd;
+     struct sockaddr_in daddr;
+     uint8_t buf[1024];
+     int bufcnt;
+     int bufptr;
+     int max_size;
+ } NetCharDriver;
+ static int udp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+     NetCharDriver *s = chr->opaque;
+     return sendto(s->fd, buf, len, 0,
+                   (struct sockaddr *)&s->daddr, sizeof(struct sockaddr_in));
+ }
+ static int udp_chr_read_poll(void *opaque)
+ {
+     CharDriverState *chr = opaque;
+     NetCharDriver *s = chr->opaque;
+     s->max_size = qemu_chr_can_read(chr);
+     /* If there were any stray characters in the queue process them
+      * first
+      */
+     while (s->max_size > 0 && s->bufptr < s->bufcnt) {
+         qemu_chr_read(chr, &s->buf[s->bufptr], 1);
+         s->bufptr++;
+         s->max_size = qemu_chr_can_read(chr);
+     }
+     return s->max_size;
+ }
+ static void udp_chr_read(void *opaque)
+ {
+     CharDriverState *chr = opaque;
+     NetCharDriver *s = chr->opaque;
+     if (s->max_size == 0)
+         return;
+     s->bufcnt = recv(s->fd, s->buf, sizeof(s->buf), 0);
+     s->bufptr = s->bufcnt;
+     if (s->bufcnt <= 0)
+         return;
+     s->bufptr = 0;
+     while (s->max_size > 0 && s->bufptr < s->bufcnt) {
+         qemu_chr_read(chr, &s->buf[s->bufptr], 1);
+         s->bufptr++;
+         s->max_size = qemu_chr_can_read(chr);
+     }
+ }
+ static void udp_chr_update_read_handler(CharDriverState *chr)
+ {
+     NetCharDriver *s = chr->opaque;
+     if (s->fd >= 0) {
+         qemu_set_fd_handler2(s->fd, udp_chr_read_poll,
+                              udp_chr_read, NULL, chr);
+     }
+ }
+ static CharDriverState *qemu_chr_open_udp(const char *def)
+ {
+     CharDriverState *chr = NULL;
+     NetCharDriver *s = NULL;
+     int fd = -1;
+     struct sockaddr_in saddr;
+     chr = qemu_mallocz(sizeof(CharDriverState));
+     if (!chr)
+         goto return_err;
+     s = qemu_mallocz(sizeof(NetCharDriver));
+     if (!s)
+         goto return_err;
+     fd = socket(PF_INET, SOCK_DGRAM, 0);
+     if (fd < 0) {
+         perror("socket(PF_INET, SOCK_DGRAM)");
+         goto return_err;
+     }
+     if (parse_host_src_port(&s->daddr, &saddr, def) < 0) {
+         printf("Could not parse: %s\n", def);
+         goto return_err;
+     }
+     if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
+     {
+         perror("bind");
+         goto return_err;
+     }
+     s->fd = fd;
+     s->bufcnt = 0;
+     s->bufptr = 0;
+     chr->opaque = s;
+     chr->chr_write = udp_chr_write;
+     chr->chr_update_read_handler = udp_chr_update_read_handler;
+     return chr;
+ return_err:
+     if (chr)
+         free(chr);
+     if (s)
+         free(s);
+     if (fd >= 0)
+         closesocket(fd);
+     return NULL;
+ }
+ /***********************************************************/
+ /* TCP Net console */
+ typedef struct {
+     int fd, listen_fd;
+     int connected;
+     int max_size;
+     int do_telnetopt;
+     int do_nodelay;
+     int is_unix;
+ } TCPCharDriver;
+ static void tcp_chr_accept(void *opaque);
+ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+     TCPCharDriver *s = chr->opaque;
+     if (s->connected) {
+         return send_all(s->fd, buf, len);
+     } else {
+         /* XXX: indicate an error ? */
+         return len;
+     }
+ }
+ static int tcp_chr_read_poll(void *opaque)
+ {
+     CharDriverState *chr = opaque;
+     TCPCharDriver *s = chr->opaque;
+     if (!s->connected)
+         return 0;
+     s->max_size = qemu_chr_can_read(chr);
+     return s->max_size;
+ }
+ #define IAC 255
+ #define IAC_BREAK 243
+ static void tcp_chr_process_IAC_bytes(CharDriverState *chr,
+                                       TCPCharDriver *s,
+                                       uint8_t *buf, int *size)
+ {
+     /* Handle any telnet client's basic IAC options to satisfy char by
+      * char mode with no echo.  All IAC options will be removed from
+      * the buf and the do_telnetopt variable will be used to track the
+      * state of the width of the IAC information.
+      *
+      * IAC commands come in sets of 3 bytes with the exception of the
+      * "IAC BREAK" command and the double IAC.
+      */
+     int i;
+     int j = 0;
+     for (i = 0; i < *size; i++) {
+         if (s->do_telnetopt > 1) {
+             if ((unsigned char)buf[i] == IAC && s->do_telnetopt == 2) {
+                 /* Double IAC means send an IAC */
+                 if (j != i)
+                     buf[j] = buf[i];
+                 j++;
+                 s->do_telnetopt = 1;
+             } else {
+                 if ((unsigned char)buf[i] == IAC_BREAK && s->do_telnetopt == 2) {
+                     /* Handle IAC break commands by sending a serial break */
+                     qemu_chr_event(chr, CHR_EVENT_BREAK);
+                     s->do_telnetopt++;
+                 }
+                 s->do_telnetopt++;
+             }
+             if (s->do_telnetopt >= 4) {
+                 s->do_telnetopt = 1;
+             }
+         } else {
+             if ((unsigned char)buf[i] == IAC) {
+                 s->do_telnetopt = 2;
+             } else {
+                 if (j != i)
+                     buf[j] = buf[i];
+                 j++;
+             }
+         }
+     }
+     *size = j;
+ }
+ static void tcp_chr_read(void *opaque)
+ {
+     CharDriverState *chr = opaque;
+     TCPCharDriver *s = chr->opaque;
+     uint8_t buf[1024];
+     int len, size;
+     if (!s->connected || s->max_size <= 0)
+         return;
+     len = sizeof(buf);
+     if (len > s->max_size)
+         len = s->max_size;
+     size = recv(s->fd, buf, len, 0);
+     if (size == 0) {
+         /* connection closed */
+         s->connected = 0;
+         if (s->listen_fd >= 0) {
+             qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
+         }
+         qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+         closesocket(s->fd);
+         s->fd = -1;
+     } else if (size > 0) {
+         if (s->do_telnetopt)
+             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
+         if (size > 0)
+             qemu_chr_read(chr, buf, size);
+     }
+ }
+ static void tcp_chr_connect(void *opaque)
+ {
+     CharDriverState *chr = opaque;
+     TCPCharDriver *s = chr->opaque;
+     s->connected = 1;
+     qemu_set_fd_handler2(s->fd, tcp_chr_read_poll,
+                          tcp_chr_read, NULL, chr);
+     qemu_chr_reset(chr);
+ }
+ #define IACSET(x,a,b,c) x[0] = a; x[1] = b; x[2] = c;
+ static void tcp_chr_telnet_init(int fd)
+ {
+     char buf[3];
+     /* Send the telnet negotion to put telnet in binary, no echo, single char mode */
+     IACSET(buf, 0xff, 0xfb, 0x01);  /* IAC WILL ECHO */
+     send(fd, (char *)buf, 3, 0);
+     IACSET(buf, 0xff, 0xfb, 0x03);  /* IAC WILL Suppress go ahead */
+     send(fd, (char *)buf, 3, 0);
+     IACSET(buf, 0xff, 0xfb, 0x00);  /* IAC WILL Binary */
+     send(fd, (char *)buf, 3, 0);
+     IACSET(buf, 0xff, 0xfd, 0x00);  /* IAC DO Binary */
+     send(fd, (char *)buf, 3, 0);
+ }
+ static void socket_set_nodelay(int fd)
+ {
+     int val = 1;
+     setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
+ }
+ static void tcp_chr_accept(void *opaque)
+ {
+     CharDriverState *chr = opaque;
+     TCPCharDriver *s = chr->opaque;
+     struct sockaddr_in saddr;
+ #ifndef _WIN32
+     struct sockaddr_un uaddr;
+ #endif
+     struct sockaddr *addr;
+     socklen_t len;
+     int fd;
+     for(;;) {
+ #ifndef _WIN32
+       if (s->is_unix) {
+           len = sizeof(uaddr);
+           addr = (struct sockaddr *)&uaddr;
+       } else
+ #endif
+       {
+           len = sizeof(saddr);
+           addr = (struct sockaddr *)&saddr;
+       }
+         fd = accept(s->listen_fd, addr, &len);
+         if (fd < 0 && errno != EINTR) {
+             return;
+         } else if (fd >= 0) {
+             if (s->do_telnetopt)
+                 tcp_chr_telnet_init(fd);
+             break;
+         }
+     }
+     socket_set_nonblock(fd);
+     if (s->do_nodelay)
+         socket_set_nodelay(fd);
+     s->fd = fd;
+     qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
+     tcp_chr_connect(chr);
+ }
+ static void tcp_chr_close(CharDriverState *chr)
+ {
+     TCPCharDriver *s = chr->opaque;
+     if (s->fd >= 0)
+         closesocket(s->fd);
+     if (s->listen_fd >= 0)
+         closesocket(s->listen_fd);
+     qemu_free(s);
+ }
+ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
+                                           int is_telnet,
+                                         int is_unix)
+ {
+     CharDriverState *chr = NULL;
+     TCPCharDriver *s = NULL;
+     int fd = -1, offset = 0;
+     int is_listen = 0;
+     int is_waitconnect = 1;
+     int do_nodelay = 0;
+     const char *ptr;
+     ptr = host_str;
+     while((ptr = strchr(ptr,','))) {
+         ptr++;
+         if (!strncmp(ptr,"server",6)) {
+             is_listen = 1;
+         } else if (!strncmp(ptr,"nowait",6)) {
+             is_waitconnect = 0;
+         } else if (!strncmp(ptr,"nodelay",6)) {
+             do_nodelay = 1;
+         } else if (!strncmp(ptr,"to=",3)) {
+             /* nothing, inet_listen() parses this one */;
+         } else {
+             printf("Unknown option: %s\n", ptr);
+             goto fail;
+         }
+     }
+     if (!is_listen)
+         is_waitconnect = 0;
+     chr = qemu_mallocz(sizeof(CharDriverState));
+     if (!chr)
+         goto fail;
+     s = qemu_mallocz(sizeof(TCPCharDriver));
+     if (!s)
+         goto fail;
+     if (is_listen) {
+         chr->filename = qemu_malloc(256);
+         if (is_unix) {
+             pstrcpy(chr->filename, 256, "unix:");
+         } else if (is_telnet) {
+             pstrcpy(chr->filename, 256, "telnet:");
+         } else {
+             pstrcpy(chr->filename, 256, "tcp:");
+         }
+         offset = strlen(chr->filename);
+     }
+     if (is_unix) {
+         if (is_listen) {
+             fd = unix_listen(host_str, chr->filename + offset, 256 - offset);
+         } else {
+             fd = unix_connect(host_str);
+         }
+     } else {
+         if (is_listen) {
+             fd = inet_listen(host_str, chr->filename + offset, 256 - offset,
+                              SOCK_STREAM, 0);
+         } else {
+             fd = inet_connect(host_str, SOCK_STREAM);
+         }
+     }
+     if (fd < 0)
+         goto fail;
+     if (!is_waitconnect)
+         socket_set_nonblock(fd);
+     s->connected = 0;
+     s->fd = -1;
+     s->listen_fd = -1;
+     s->is_unix = is_unix;
+     s->do_nodelay = do_nodelay && !is_unix;
+     chr->opaque = s;
+     chr->chr_write = tcp_chr_write;
+     chr->chr_close = tcp_chr_close;
+     if (is_listen) {
+         s->listen_fd = fd;
+         qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
+         if (is_telnet)
+             s->do_telnetopt = 1;
+     } else {
+         s->connected = 1;
+         s->fd = fd;
+         socket_set_nodelay(fd);
+         tcp_chr_connect(chr);
+     }
+     if (is_listen && is_waitconnect) {
+         printf("QEMU waiting for connection on: %s\n",
+                chr->filename ? chr->filename : host_str);
+         tcp_chr_accept(chr);
+         socket_set_nonblock(s->listen_fd);
+     }
+     return chr;
+  fail:
+     if (fd >= 0)
+         closesocket(fd);
+     qemu_free(s);
+     qemu_free(chr);
+     return NULL;
+ }
+ static TAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs
+ = TAILQ_HEAD_INITIALIZER(chardevs);
+ CharDriverState *qemu_chr_open(const char *label, const char *filename)
+ {
+     const char *p;
+     CharDriverState *chr;
+     if (!strcmp(filename, "vc")) {
+         chr = text_console_init(&display_state, 0);
+     } else
+     if (strstart(filename, "vc:", &p)) {
+         chr = text_console_init(&display_state, p);
+     } else
+     if (!strcmp(filename, "null")) {
+         chr = qemu_chr_open_null();
+     } else
+     if (strstart(filename, "tcp:", &p)) {
+         chr = qemu_chr_open_tcp(p, 0, 0);
+     } else
+     if (strstart(filename, "telnet:", &p)) {
+         chr = qemu_chr_open_tcp(p, 1, 0);
+     } else
+     if (strstart(filename, "udp:", &p)) {
+         chr = qemu_chr_open_udp(p);
+     } else
+     if (strstart(filename, "mon:", &p)) {
+         chr = qemu_chr_open(label, p);
+         if (chr) {
+             chr = qemu_chr_open_mux(chr);
+             monitor_init(chr, !nographic);
+         } else {
+             printf("Unable to open driver: %s\n", p);
+         }
+     } else
+ #ifndef _WIN32
+     if (strstart(filename, "unix:", &p)) {
+       chr = qemu_chr_open_tcp(p, 0, 1);
+     } else if (strstart(filename, "file:", &p)) {
+         chr = qemu_chr_open_file_out(p);
+     } else if (strstart(filename, "pipe:", &p)) {
+         chr = qemu_chr_open_pipe(p);
+     } else if (!strcmp(filename, "pty")) {
+         chr = qemu_chr_open_pty();
+     } else if (!strcmp(filename, "stdio")) {
+         chr = qemu_chr_open_stdio();
+     } else
+ #if defined(__linux__)
+     if (strstart(filename, "/dev/parport", NULL)) {
+         chr = qemu_chr_open_pp(filename);
+     } else
+ #elif defined(__FreeBSD__)
+     if (strstart(filename, "/dev/ppi", NULL)) {
+         chr = qemu_chr_open_pp(filename);
+     } else
+ #endif
+ #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
+     || defined(__NetBSD__) || defined(__OpenBSD__)
+     if (strstart(filename, "/dev/", NULL)) {
+         chr = qemu_chr_open_tty(filename);
+     } else
+ #endif
+ #else /* !_WIN32 */
+     if (strstart(filename, "COM", NULL)) {
+         chr = qemu_chr_open_win(filename);
+     } else
+     if (strstart(filename, "pipe:", &p)) {
+         chr = qemu_chr_open_win_pipe(p);
+     } else
+     if (strstart(filename, "con:", NULL)) {
+         chr = qemu_chr_open_win_con(filename);
+     } else
+     if (strstart(filename, "file:", &p)) {
+         chr = qemu_chr_open_win_file_out(p);
+     } else
+ #endif
+ #ifdef CONFIG_BRLAPI
+     if (!strcmp(filename, "braille")) {
+         chr = chr_baum_init();
+     } else
+ #endif
+     {
+         chr = NULL;
+     }
+     if (chr) {
+         if (!chr->filename)
+             chr->filename = qemu_strdup(filename);
+         chr->label = qemu_strdup(label);
+         TAILQ_INSERT_TAIL(&chardevs, chr, next);
+     }
+     return chr;
+ }
+ void qemu_chr_close(CharDriverState *chr)
+ {
+     TAILQ_REMOVE(&chardevs, chr, next);
+     if (chr->chr_close)
+         chr->chr_close(chr);
+     qemu_free(chr->filename);
+     qemu_free(chr->label);
+     qemu_free(chr);
+ }
+ void qemu_chr_info(void)
+ {
+     CharDriverState *chr;
+     TAILQ_FOREACH(chr, &chardevs, next) {
+         term_printf("%s: filename=%s\n", chr->label, chr->filename);
+     }
+ }
diff --cc qemu-common.h
index 1c5f0a4b780b5fb05d531fab37cfcc9b54426c7a,db6c1a612ce9925a1e1964fc650c3de36ca78345..79073405b6ebc38d279eac3905f3d5e054b0412f
@@@ -85,18 -114,24 +114,35 @@@ char *pstrcat(char *buf, int buf_size, 
  int strstart(const char *str, const char *val, const char **ptr);
  int stristart(const char *str, const char *val, const char **ptr);
  time_t mktimegm(struct tm *tm);
+ int qemu_fls(int i);
+ #define qemu_isalnum(c)               isalnum((unsigned char)(c))
+ #define qemu_isalpha(c)               isalpha((unsigned char)(c))
+ #define qemu_iscntrl(c)               iscntrl((unsigned char)(c))
+ #define qemu_isdigit(c)               isdigit((unsigned char)(c))
+ #define qemu_isgraph(c)               isgraph((unsigned char)(c))
+ #define qemu_islower(c)               islower((unsigned char)(c))
+ #define qemu_isprint(c)               isprint((unsigned char)(c))
+ #define qemu_ispunct(c)               ispunct((unsigned char)(c))
+ #define qemu_isspace(c)               isspace((unsigned char)(c))
+ #define qemu_isupper(c)               isupper((unsigned char)(c))
+ #define qemu_isxdigit(c)      isxdigit((unsigned char)(c))
+ #define qemu_tolower(c)               tolower((unsigned char)(c))
+ #define qemu_toupper(c)               toupper((unsigned char)(c))
+ #define qemu_isascii(c)               isascii((unsigned char)(c))
+ #define qemu_toascii(c)               toascii((unsigned char)(c))
  
 +#define CTYPE(isfoobar,argumentchar) (isfoobar((unsigned char)(argumentchar)))
 +  /* One must not pass a plain `char' to isupper, toupper, et al.  If
 +   * it has the top bit set (ie, is negative if your chars are
 +   * signed), undefined behaviour results.  The <ctype.h> functions
 +   * are defined to take the value of an unsigned char, as an int.
 +   * So use this macro.  You may pass toupper et al for isfoobar.
 +   * Do not pass EOF as a character to this macro.  If you might have
 +   * EOF then you ought to have it in an int representing an unsigned
 +   * char, which is safe for the ctype macros directly.  Or test separately.
 +   * Obviously don't use this for floating point things like isnan! */
 +
  void *qemu_malloc(size_t size);
  void *qemu_realloc(void *ptr, size_t size);
  void *qemu_mallocz(size_t size);
diff --cc qemu-sockets.c
index 0000000000000000000000000000000000000000,4111f82b539e4b778eb26c201bbf9908892a841d..c7db5ace615d7b3f8d85b23bec01569328d1153f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,415 +1,415 @@@
 -#ifndef _WIN32
+ /*
+  *  inet and unix socket functions for qemu
+  *
+  *  (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
+  *
+  *  This program is free software; you can redistribute it and/or modify
+  *  it under the terms of the GNU General Public License as published by
+  *  the Free Software Foundation; under version 2 of the License.
+  *
+  *  This program is distributed in the hope that it will be useful,
+  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  *  GNU General Public License for more details.
+  */
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <ctype.h>
+ #include <errno.h>
+ #include <unistd.h>
+ #include "qemu_socket.h"
+ #include "qemu-common.h" /* for qemu_isdigit */
+ #ifndef AI_ADDRCONFIG
+ # define AI_ADDRCONFIG 0
+ #endif
+ static int sockets_debug = 0;
+ static const int on=1, off=0;
+ static int inet_getport(struct addrinfo *e)
+ {
+     struct sockaddr_in *i4;
+     struct sockaddr_in6 *i6;
+     switch (e->ai_family) {
+     case PF_INET6:
+         i6 = (void*)e->ai_addr;
+         return ntohs(i6->sin6_port);
+     case PF_INET:
+         i4 = (void*)e->ai_addr;
+         return ntohs(i4->sin_port);
+     default:
+         return 0;
+     }
+ }
+ static void inet_setport(struct addrinfo *e, int port)
+ {
+     struct sockaddr_in *i4;
+     struct sockaddr_in6 *i6;
+     switch (e->ai_family) {
+     case PF_INET6:
+         i6 = (void*)e->ai_addr;
+         i6->sin6_port = htons(port);
+         break;
+     case PF_INET:
+         i4 = (void*)e->ai_addr;
+         i4->sin_port = htons(port);
+         break;
+     }
+ }
+ static const char *inet_strfamily(int family)
+ {
+     switch (family) {
+     case PF_INET6: return "ipv6";
+     case PF_INET:  return "ipv4";
+     case PF_UNIX:  return "unix";
+     }
+     return "????";
+ }
+ static void inet_print_addrinfo(const char *tag, struct addrinfo *res)
+ {
+     struct addrinfo *e;
+     char uaddr[INET6_ADDRSTRLEN+1];
+     char uport[33];
+     for (e = res; e != NULL; e = e->ai_next) {
+         getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
+                     uaddr,INET6_ADDRSTRLEN,uport,32,
+                     NI_NUMERICHOST | NI_NUMERICSERV);
+         fprintf(stderr,"%s: getaddrinfo: family %s, host %s, port %s\n",
+                 tag, inet_strfamily(e->ai_family), uaddr, uport);
+     }
+ }
+ int inet_listen(const char *str, char *ostr, int olen,
+                 int socktype, int port_offset)
+ {
+     struct addrinfo ai,*res,*e;
+     char addr[64];
+     char port[33];
+     char uaddr[INET6_ADDRSTRLEN+1];
+     char uport[33];
+     const char *opts, *h;
+     int slisten,rc,pos,to,try_next;
+     memset(&ai,0, sizeof(ai));
+     ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
+     ai.ai_family = PF_UNSPEC;
+     ai.ai_socktype = socktype;
+     /* parse address */
+     if (str[0] == ':') {
+         /* no host given */
+         addr[0] = '\0';
+         if (1 != sscanf(str,":%32[^,]%n",port,&pos)) {
+             fprintf(stderr, "%s: portonly parse error (%s)\n",
+                     __FUNCTION__, str);
+             return -1;
+         }
+     } else if (str[0] == '[') {
+         /* IPv6 addr */
+         if (2 != sscanf(str,"[%64[^]]]:%32[^,]%n",addr,port,&pos)) {
+             fprintf(stderr, "%s: ipv6 parse error (%s)\n",
+                     __FUNCTION__, str);
+             return -1;
+         }
+         ai.ai_family = PF_INET6;
+     } else if (qemu_isdigit(str[0])) {
+         /* IPv4 addr */
+         if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) {
+             fprintf(stderr, "%s: ipv4 parse error (%s)\n",
+                     __FUNCTION__, str);
+             return -1;
+         }
+         ai.ai_family = PF_INET;
+     } else {
+         /* hostname */
+         if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) {
+             fprintf(stderr, "%s: hostname parse error (%s)\n",
+                     __FUNCTION__, str);
+             return -1;
+         }
+     }
+     /* parse options */
+     opts = str + pos;
+     h = strstr(opts, ",to=");
+     to = h ? atoi(h+4) : 0;
+     if (strstr(opts, ",ipv4"))
+         ai.ai_family = PF_INET;
+     if (strstr(opts, ",ipv6"))
+         ai.ai_family = PF_INET6;
+     /* lookup */
+     if (port_offset)
+         snprintf(port, sizeof(port), "%d", atoi(port) + port_offset);
+     rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res);
+     if (rc != 0) {
+         fprintf(stderr,"%s: getaddrinfo(%s,%s): %s\n", __FUNCTION__,
+                 addr, port, gai_strerror(rc));
+         return -1;
+     }
+     if (sockets_debug)
+         inet_print_addrinfo(__FUNCTION__, res);
+     /* create socket + bind */
+     for (e = res; e != NULL; e = e->ai_next) {
+       getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
+                   uaddr,INET6_ADDRSTRLEN,uport,32,
+                   NI_NUMERICHOST | NI_NUMERICSERV);
+         slisten = socket(e->ai_family, e->ai_socktype, e->ai_protocol);
+       if (slisten < 0) {
+             fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
+                     inet_strfamily(e->ai_family), strerror(errno));
+           continue;
+       }
+         setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
+ #ifdef IPV6_V6ONLY
+         if (e->ai_family == PF_INET6) {
+             /* listen on both ipv4 and ipv6 */
+             setsockopt(slisten,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&off,sizeof(off));
+         }
+ #endif
+         for (;;) {
+             if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) {
+                 if (sockets_debug)
+                     fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__,
+                             inet_strfamily(e->ai_family), uaddr, inet_getport(e));
+                 goto listen;
+             }
+             try_next = to && (inet_getport(e) <= to + port_offset);
+             if (!try_next || sockets_debug)
+                 fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__,
+                         inet_strfamily(e->ai_family), uaddr, inet_getport(e),
+                         strerror(errno));
+             if (try_next) {
+                 inet_setport(e, inet_getport(e) + 1);
+                 continue;
+             }
+             break;
+         }
+         closesocket(slisten);
+     }
+     fprintf(stderr, "%s: FAILED\n", __FUNCTION__);
+     freeaddrinfo(res);
+     return -1;
+ listen:
+     if (listen(slisten,1) != 0) {
+         perror("listen");
+         closesocket(slisten);
+         return -1;
+     }
+     if (ostr) {
+         if (e->ai_family == PF_INET6) {
+             snprintf(ostr, olen, "[%s]:%d%s", uaddr,
+                      inet_getport(e) - port_offset, opts);
+         } else {
+             snprintf(ostr, olen, "%s:%d%s", uaddr,
+                      inet_getport(e) - port_offset, opts);
+         }
+     }
+     freeaddrinfo(res);
+     return slisten;
+ }
+ int inet_connect(const char *str, int socktype)
+ {
+     struct addrinfo ai,*res,*e;
+     char addr[64];
+     char port[33];
+     char uaddr[INET6_ADDRSTRLEN+1];
+     char uport[33];
+     int sock,rc;
+     memset(&ai,0, sizeof(ai));
+     ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
+     ai.ai_family = PF_UNSPEC;
+     ai.ai_socktype = socktype;
+     /* parse address */
+     if (str[0] == '[') {
+         /* IPv6 addr */
+         if (2 != sscanf(str,"[%64[^]]]:%32[^,]",addr,port)) {
+             fprintf(stderr, "%s: ipv6 parse error (%s)\n",
+                     __FUNCTION__, str);
+             return -1;
+         }
+         ai.ai_family = PF_INET6;
+     } else if (qemu_isdigit(str[0])) {
+         /* IPv4 addr */
+         if (2 != sscanf(str,"%64[0-9.]:%32[^,]",addr,port)) {
+             fprintf(stderr, "%s: ipv4 parse error (%s)\n",
+                     __FUNCTION__, str);
+             return -1;
+         }
+         ai.ai_family = PF_INET;
+     } else {
+         /* hostname */
+         if (2 != sscanf(str,"%64[^:]:%32[^,]",addr,port)) {
+             fprintf(stderr, "%s: hostname parse error (%s)\n",
+                     __FUNCTION__, str);
+             return -1;
+         }
+     }
+     /* parse options */
+     if (strstr(str, ",ipv4"))
+         ai.ai_family = PF_INET;
+     if (strstr(str, ",ipv6"))
+         ai.ai_family = PF_INET6;
+     /* lookup */
+     if (0 != (rc = getaddrinfo(addr, port, &ai, &res))) {
+         fprintf(stderr,"getaddrinfo(%s,%s): %s\n", gai_strerror(rc),
+                 addr, port);
+       return -1;
+     }
+     if (sockets_debug)
+         inet_print_addrinfo(__FUNCTION__, res);
+     for (e = res; e != NULL; e = e->ai_next) {
+       if (getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
+                         uaddr,INET6_ADDRSTRLEN,uport,32,
+                         NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
+             fprintf(stderr,"%s: getnameinfo: oops\n", __FUNCTION__);
+           continue;
+       }
+         sock = socket(e->ai_family, e->ai_socktype, e->ai_protocol);
+       if (sock < 0) {
+             fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
+                     inet_strfamily(e->ai_family), strerror(errno));
+           continue;
+       }
+         setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
+       /* connect to peer */
+       if (connect(sock,e->ai_addr,e->ai_addrlen) < 0) {
+             if (sockets_debug || NULL == e->ai_next)
+                 fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
+                         inet_strfamily(e->ai_family),
+                         e->ai_canonname, uaddr, uport, strerror(errno));
+             closesocket(sock);
+           continue;
+       }
+         if (sockets_debug)
+             fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__,
+                     inet_strfamily(e->ai_family),
+                     e->ai_canonname, uaddr, uport);
+         freeaddrinfo(res);
+       return sock;
+     }
+     freeaddrinfo(res);
+     return -1;
+ }
++#ifndef NO_UNIX_SOCKETS
+ int unix_listen(const char *str, char *ostr, int olen)
+ {
+     struct sockaddr_un un;
+     char *path, *opts;
+     int sock, fd, len;
+     sock = socket(PF_UNIX, SOCK_STREAM, 0);
+     if (sock < 0) {
+       perror("socket(unix)");
+       return -1;
+     }
+     opts = strchr(str, ',');
+     if (opts) {
+         len = opts - str;
+         path = malloc(len+1);
+         snprintf(path, len+1, "%.*s", len, str);
+     } else
+         path = strdup(str);
+     memset(&un, 0, sizeof(un));
+     un.sun_family = AF_UNIX;
+     if (path && strlen(path)) {
+         snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
+     } else {
+         char *tmpdir = getenv("TMPDIR");
+         snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX",
+                  tmpdir ? tmpdir : "/tmp");
+         /*
+          * This dummy fd usage silences the mktemp() unsecure warning.
+          * Using mkstemp() doesn't make things more secure here
+          * though.  bind() complains about existing files, so we have
+          * to unlink first and thus re-open the race window.  The
+          * worst case possible is bind() failing, i.e. a DoS attack.
+          */
+         fd = mkstemp(un.sun_path); close(fd);
+     }
+     snprintf(ostr, olen, "%s%s", un.sun_path, opts ? opts : "");
+     unlink(un.sun_path);
+     if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
+         fprintf(stderr, "bind(unix:%s): %s\n", un.sun_path, strerror(errno));
+         goto err;
+     }
+     if (listen(sock, 1) < 0) {
+         fprintf(stderr, "listen(unix:%s): %s\n", un.sun_path, strerror(errno));
+         goto err;
+     }
+     if (sockets_debug)
+         fprintf(stderr, "bind(unix:%s): OK\n", un.sun_path);
+     free(path);
+     return sock;
+ err:
+     free(path);
+     closesocket(sock);
+     return -1;
+ }
+ int unix_connect(const char *path)
+ {
+     struct sockaddr_un un;
+     int sock;
+     sock = socket(PF_UNIX, SOCK_STREAM, 0);
+     if (sock < 0) {
+       perror("socket(unix)");
+       return -1;
+     }
+     memset(&un, 0, sizeof(un));
+     un.sun_family = AF_UNIX;
+     snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
+     if (connect(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
+         fprintf(stderr, "connect(unix:%s): %s\n", path, strerror(errno));
+       return -1;
+     }
+     if (sockets_debug)
+         fprintf(stderr, "connect(unix:%s): OK\n", path);
+     return sock;
+ }
+ #else
+ int unix_listen(const char *path, char *ostr, int olen)
+ {
+     fprintf(stderr, "unix sockets are not available on windows\n");
+     return -1;
+ }
+ int unix_connect(const char *path)
+ {
+     fprintf(stderr, "unix sockets are not available on windows\n");
+     return -1;
+ }
+ #endif
diff --cc qemu_socket.h
Simple merge
index b26366f992710b450d37b0763249828ce06ba43f,5008a3a6026e3da1787f5958d1137ee97e716a31..2196aecae6b1d444b6fb104441b966e02e4f8df1
@@@ -9459,7 -9503,7 +9504,11 @@@ const ppc_def_t *cpu_ppc_find_by_name (
          p = name;
      check_pvr:
          for (i = 0; i < 8; i++) {
++<<<<<<< HEAD/target-ppc/translate_init.c
 +            if (!CTYPE(isxdigit,*p++))
++=======
+             if (!qemu_isxdigit(*p++))
++>>>>>>> 9fd8d8d70db785c7a18fe6788a66dcf1c095a7ad/target-ppc/translate_init.c
                  break;
          }
          if (i == 8)
Simple merge
diff --cc tests/qruncom.c
Simple merge
diff --cc usb-linux.c
index 7b59a2234a23896f9004cd4b5ba2a7bbcbe12d8f,fb1153bbd445e6ff08e0546da82fbe3d482c2fbd..10f9c87ec21b56ae6149cb3042582a33b0e7e056
  #include "qemu-timer.h"
  #include "console.h"
  
- #if defined(__linux__)
  #include <dirent.h>
  #include <sys/ioctl.h>
 +/* Some versions of usbdevice_fs.h need __user to be defined for them.   */
 +/* This may (harmlessly) conflict with a definition in linux/compiler.h. */
 +#define __user
  #include <signal.h>
  
  #include <linux/usbdevice_fs.h>
@@@ -1165,13 -1163,13 +1166,14 @@@ static int usb_host_read_file(char *lin
      int ret = 0;
      char filename[PATH_MAX];
  
-     snprintf(filename, PATH_MAX, device_file, device_name);
+     snprintf(filename, PATH_MAX, USBSYSBUS_PATH "/devices/%s/%s", device_name,
+              device_file);
      f = fopen(filename, "r");
      if (f) {
 -        fgets(line, line_size, f);
 +        if (fgets(line, line_size, f) != NULL &&
 +            !ferror(f))
 +            ret = 1;
          fclose(f);
 -        ret = 1;
      } else {
          term_printf("husb: could not open %s\n", filename);
      }