typo
[qemu] / vl.c
diff --git a/vl.c b/vl.c
index 94e989f..e828d31 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -47,6 +47,7 @@
 #include <libutil.h>
 #endif
 #else
+#ifndef __sun__
 #include <linux/if.h>
 #include <linux/if_tun.h>
 #include <pty.h>
@@ -55,6 +56,7 @@
 #include <linux/ppdev.h>
 #endif
 #endif
+#endif
 
 #if defined(CONFIG_SLIRP)
 #include "libslirp.h"
@@ -68,6 +70,8 @@
 #define memalign(align, size) malloc(size)
 #endif
 
+#include "qemu_socket.h"
+
 #ifdef CONFIG_SDL
 #ifdef __APPLE__
 #include <SDL/SDL.h>
@@ -135,7 +139,6 @@ int graphic_height = 600;
 #endif
 int graphic_depth = 15;
 int full_screen = 0;
-TextConsole *vga_console;
 CharDriverState *serial_hds[MAX_SERIAL_PORTS];
 CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
 #ifdef TARGET_I386
@@ -146,6 +149,7 @@ USBPort *vm_usb_ports[MAX_VM_USB_PORTS];
 USBDevice *vm_usb_hub;
 static VLANState *first_vlan;
 int smp_cpus = 1;
+int vnc_display = -1;
 #if defined(TARGET_SPARC)
 #define MAX_CPUS 16
 #elif defined(TARGET_I386)
@@ -153,6 +157,7 @@ int smp_cpus = 1;
 #else
 #define MAX_CPUS 1
 #endif
+int acpi_enabled = 1;
 
 /***********************************************************/
 /* x86 ISA bus support */
@@ -331,35 +336,6 @@ int strstart(const char *str, const char *val, const char **ptr)
     return 1;
 }
 
-/* return the size or -1 if error */
-int get_image_size(const char *filename)
-{
-    int fd, size;
-    fd = open(filename, O_RDONLY | O_BINARY);
-    if (fd < 0)
-        return -1;
-    size = lseek(fd, 0, SEEK_END);
-    close(fd);
-    return size;
-}
-
-/* return the size or -1 if error */
-int load_image(const char *filename, uint8_t *addr)
-{
-    int fd, size;
-    fd = open(filename, O_RDONLY | O_BINARY);
-    if (fd < 0)
-        return -1;
-    size = lseek(fd, 0, SEEK_END);
-    lseek(fd, 0, SEEK_SET);
-    if (read(fd, addr, size) != size) {
-        close(fd);
-        return -1;
-    }
-    close(fd);
-    return size;
-}
-
 void cpu_outb(CPUState *env, int addr, int val)
 {
 #ifdef DEBUG_IOPORT
@@ -367,6 +343,10 @@ void cpu_outb(CPUState *env, int addr, int val)
         fprintf(logfile, "outb: %04x %02x\n", addr, val);
 #endif    
     ioport_write_table[0][addr](ioport_opaque[addr], addr, val);
+#ifdef USE_KQEMU
+    if (env)
+        env->last_io_time = cpu_get_time_fast();
+#endif
 }
 
 void cpu_outw(CPUState *env, int addr, int val)
@@ -376,6 +356,10 @@ void cpu_outw(CPUState *env, int addr, int val)
         fprintf(logfile, "outw: %04x %04x\n", addr, val);
 #endif    
     ioport_write_table[1][addr](ioport_opaque[addr], addr, val);
+#ifdef USE_KQEMU
+    if (env)
+        env->last_io_time = cpu_get_time_fast();
+#endif
 }
 
 void cpu_outl(CPUState *env, int addr, int val)
@@ -385,6 +369,10 @@ void cpu_outl(CPUState *env, int addr, int val)
         fprintf(logfile, "outl: %04x %08x\n", addr, val);
 #endif
     ioport_write_table[2][addr](ioport_opaque[addr], addr, val);
+#ifdef USE_KQEMU
+    if (env)
+        env->last_io_time = cpu_get_time_fast();
+#endif
 }
 
 int cpu_inb(CPUState *env, int addr)
@@ -395,6 +383,10 @@ int cpu_inb(CPUState *env, int addr)
     if (loglevel & CPU_LOG_IOPORT)
         fprintf(logfile, "inb : %04x %02x\n", addr, val);
 #endif
+#ifdef USE_KQEMU
+    if (env)
+        env->last_io_time = cpu_get_time_fast();
+#endif
     return val;
 }
 
@@ -406,6 +398,10 @@ int cpu_inw(CPUState *env, int addr)
     if (loglevel & CPU_LOG_IOPORT)
         fprintf(logfile, "inw : %04x %04x\n", addr, val);
 #endif
+#ifdef USE_KQEMU
+    if (env)
+        env->last_io_time = cpu_get_time_fast();
+#endif
     return val;
 }
 
@@ -417,6 +413,10 @@ int cpu_inl(CPUState *env, int addr)
     if (loglevel & CPU_LOG_IOPORT)
         fprintf(logfile, "inl : %04x %08x\n", addr, val);
 #endif
+#ifdef USE_KQEMU
+    if (env)
+        env->last_io_time = cpu_get_time_fast();
+#endif
     return val;
 }
 
@@ -449,6 +449,7 @@ static QEMUPutKBDEvent *qemu_put_kbd_event;
 static void *qemu_put_kbd_event_opaque;
 static QEMUPutMouseEvent *qemu_put_mouse_event;
 static void *qemu_put_mouse_event_opaque;
+static int qemu_put_mouse_event_absolute;
 
 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
 {
@@ -456,10 +457,11 @@ void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
     qemu_put_kbd_event = func;
 }
 
-void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque)
+void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int absolute)
 {
     qemu_put_mouse_event_opaque = opaque;
     qemu_put_mouse_event = func;
+    qemu_put_mouse_event_absolute = absolute;
 }
 
 void kbd_put_keycode(int keycode)
@@ -477,6 +479,11 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
     }
 }
 
+int kbd_mouse_is_absolute(void)
+{
+    return qemu_put_mouse_event_absolute;
+}
+
 /***********************************************************/
 /* timers */
 
@@ -512,9 +519,15 @@ int64_t cpu_get_real_ticks(void)
 
 int64_t cpu_get_real_ticks(void)
 {
+#ifdef _WIN32
+    LARGE_INTEGER ti;
+    QueryPerformanceCounter(&ti);
+    return ti.QuadPart;
+#else
     int64_t val;
     asm volatile ("rdtsc" : "=A" (val));
     return val;
+#endif
 }
 
 #elif defined(__x86_64__)
@@ -552,6 +565,7 @@ int64_t cpu_get_real_ticks(void)
 #error unsupported CPU
 #endif
 
+static int64_t cpu_ticks_prev;
 static int64_t cpu_ticks_offset;
 static int cpu_ticks_enabled;
 
@@ -560,7 +574,15 @@ static inline int64_t cpu_get_ticks(void)
     if (!cpu_ticks_enabled) {
         return cpu_ticks_offset;
     } else {
-        return cpu_get_real_ticks() + cpu_ticks_offset;
+        int64_t ticks;
+        ticks = cpu_get_real_ticks();
+        if (cpu_ticks_prev > ticks) {
+            /* Note: non increasing ticks may happen if the host uses
+               software suspend */
+            cpu_ticks_offset += cpu_ticks_prev - ticks;
+        }
+        cpu_ticks_prev = ticks;
+        return ticks + cpu_ticks_offset;
     }
 }
 
@@ -583,17 +605,26 @@ void cpu_disable_ticks(void)
     }
 }
 
-static int64_t get_clock(void)
-{
 #ifdef _WIN32
-    struct _timeb tb;
-    _ftime(&tb);
-    return ((int64_t)tb.time * 1000 + (int64_t)tb.millitm) * 1000;
+void cpu_calibrate_ticks(void)
+{
+    LARGE_INTEGER freq;
+    int ret;
+
+    ret = QueryPerformanceFrequency(&freq);
+    if (ret == 0) {
+        fprintf(stderr, "Could not calibrate ticks\n");
+        exit(1);
+    }
+    ticks_per_sec = freq.QuadPart;
+}
+
 #else
+static int64_t get_clock(void)
+{
     struct timeval tv;
     gettimeofday(&tv, NULL);
     return tv.tv_sec * 1000000LL + tv.tv_usec;
-#endif
 }
 
 void cpu_calibrate_ticks(void)
@@ -602,15 +633,12 @@ void cpu_calibrate_ticks(void)
 
     usec = get_clock();
     ticks = cpu_get_real_ticks();
-#ifdef _WIN32
-    Sleep(50);
-#else
     usleep(50 * 1000);
-#endif
     usec = get_clock() - usec;
     ticks = cpu_get_real_ticks() - ticks;
     ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec;
 }
+#endif /* !_WIN32 */
 
 /* compute with 96 bit intermediate result: (a*b)/c */
 uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
@@ -658,6 +686,8 @@ QEMUClock *vm_clock;
 static QEMUTimer *active_timers[2];
 #ifdef _WIN32
 static MMRESULT timerID;
+static HANDLE host_alarm = NULL;
+static unsigned int period = 1;
 #else
 /* frequency of the times() clock tick */
 static int timer_freq;
@@ -880,6 +910,9 @@ static void host_alarm_handler(int host_signum)
                            qemu_get_clock(vm_clock)) ||
         qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME],
                            qemu_get_clock(rt_clock))) {
+#ifdef _WIN32
+        SetEvent(host_alarm);
+#endif
         CPUState *env = cpu_single_env;
         if (env) {
             /* stop the currently executing cpu because a timer occured */
@@ -940,8 +973,15 @@ static void init_timers(void)
 #ifdef _WIN32
     {
         int count=0;
+        TIMECAPS tc;
+
+        ZeroMemory(&tc, sizeof(TIMECAPS));
+        timeGetDevCaps(&tc, sizeof(TIMECAPS));
+        if (period < tc.wPeriodMin)
+            period = tc.wPeriodMin;
+        timeBeginPeriod(period);
         timerID = timeSetEvent(1,     // interval (ms)
-                               0,     // resolution
+                               period,     // resolution
                                host_alarm_handler, // function
                                (DWORD)&count,  // user parameter
                                TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
@@ -949,6 +989,12 @@ static void init_timers(void)
             perror("failed timer alarm");
             exit(1);
        }
+        host_alarm = CreateEvent(NULL, FALSE, FALSE, NULL);
+        if (!host_alarm) {
+            perror("failed CreateEvent");
+            exit(1);
+        }
+        ResetEvent(host_alarm);
     }
     pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000;
 #else
@@ -978,7 +1024,11 @@ static void init_timers(void)
         getitimer(ITIMER_REAL, &itv);
 
 #if defined(__linux__)
-        if (itv.it_interval.tv_usec > 1000) {
+        /* XXX: force /dev/rtc usage because even 2.6 kernels may not
+           have timers with 1 ms resolution. The correct solution will
+           be to use the POSIX real time timers available in recent
+           2.6 kernels */
+        if (itv.it_interval.tv_usec > 1000 || 1) {
             /* try to use /dev/rtc to have a faster timer */
             if (start_rtc_timer() < 0)
                 goto use_itimer;
@@ -1008,6 +1058,11 @@ void quit_timers(void)
 {
 #ifdef _WIN32
     timeKillEvent(timerID);
+    timeEndPeriod(period);
+    if (host_alarm) {
+        CloseHandle(host_alarm);
+        host_alarm = NULL;
+    }
 #endif
 }
 
@@ -1077,20 +1132,58 @@ CharDriverState *qemu_chr_open_null(void)
     return chr;
 }
 
-#ifndef _WIN32
+#ifdef _WIN32
 
-typedef struct {
-    int fd_in, fd_out;
-    IOCanRWHandler *fd_can_read; 
-    IOReadHandler *fd_read;
-    void *fd_opaque;
-    int max_size;
-} FDCharDriver;
+static void socket_cleanup(void)
+{
+    WSACleanup();
+}
 
-#define STDIO_MAX_CLIENTS 2
+static int socket_init(void)
+{
+    WSADATA Data;
+    int ret, err;
 
-static int stdio_nb_clients;
-static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];
+    ret = WSAStartup(MAKEWORD(2,2), &Data);
+    if (ret != 0) {
+        err = WSAGetLastError();
+        fprintf(stderr, "WSAStartup: %d\n", err);
+        return -1;
+    }
+    atexit(socket_cleanup);
+    return 0;
+}
+
+static int send_all(int fd, const uint8_t *buf, int len1)
+{
+    int ret, len;
+    
+    len = len1;
+    while (len > 0) {
+        ret = send(fd, buf, len, 0);
+        if (ret < 0) {
+            int errno;
+            errno = WSAGetLastError();
+            if (errno != WSAEWOULDBLOCK) {
+                return -1;
+            }
+        } else if (ret == 0) {
+            break;
+        } else {
+            buf += ret;
+            len -= ret;
+        }
+    }
+    return len1 - len;
+}
+
+void socket_set_nonblock(int fd)
+{
+    unsigned long opt = 1;
+    ioctlsocket(fd, FIONBIO, &opt);
+}
+
+#else
 
 static int unix_write(int fd, const uint8_t *buf, int len1)
 {
@@ -1112,6 +1205,32 @@ static int unix_write(int fd, const uint8_t *buf, int len1)
     return len1 - len;
 }
 
+static inline int send_all(int fd, const uint8_t *buf, int len1)
+{
+    return unix_write(fd, buf, len1);
+}
+
+void socket_set_nonblock(int fd)
+{
+    fcntl(fd, F_SETFL, O_NONBLOCK);
+}
+#endif /* !_WIN32 */
+
+#ifndef _WIN32
+
+typedef struct {
+    int fd_in, fd_out;
+    IOCanRWHandler *fd_can_read; 
+    IOReadHandler *fd_read;
+    void *fd_opaque;
+    int max_size;
+} FDCharDriver;
+
+#define STDIO_MAX_CLIENTS 2
+
+static int stdio_nb_clients;
+static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];
+
 static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     FDCharDriver *s = chr->opaque;
@@ -1189,7 +1308,7 @@ CharDriverState *qemu_chr_open_file_out(const char *file_out)
 {
     int fd_out;
 
-    fd_out = open(file_out, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY);
+    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);
@@ -1615,9 +1734,382 @@ CharDriverState *qemu_chr_open_pty(void)
 
 #endif /* !defined(_WIN32) */
 
+#ifdef _WIN32
+typedef struct {
+    IOCanRWHandler *fd_can_read; 
+    IOReadHandler *fd_read;
+    void *win_opaque;
+    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_close2(WinCharState *s)
+{
+    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, s);
+    else
+        qemu_del_polling_cb(win_chr_poll, s);
+}
+
+static void win_chr_close(CharDriverState *chr)
+{
+    WinCharState *s = chr->opaque;
+    win_chr_close2(s);
+}
+
+static int win_chr_init(WinCharState *s, const char *filename)
+{
+    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, s);
+    return 0;
+
+ fail:
+    win_chr_close2(s);
+    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(WinCharState *s)
+{
+    s->max_size = s->fd_can_read(s->win_opaque);
+    return s->max_size;
+}
+            
+static void win_chr_readfile(WinCharState *s)
+{
+    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) {
+        s->fd_read(s->win_opaque, buf, size);
+    }
+}
+
+static void win_chr_read(WinCharState *s)
+{
+    if (s->len > s->max_size)
+        s->len = s->max_size;
+    if (s->len == 0)
+        return;
+    
+    win_chr_readfile(s);
+}
+
+static int win_chr_poll(void *opaque)
+{
+    WinCharState *s = opaque;
+    COMSTAT status;
+    DWORD comerr;
+    
+    ClearCommError(s->hcom, &comerr, &status);
+    if (status.cbInQue > 0) {
+        s->len = status.cbInQue;
+        win_chr_read_poll(s);
+        win_chr_read(s);
+        return 1;
+    }
+    return 0;
+}
+
+static void win_chr_add_read_handler(CharDriverState *chr, 
+                                    IOCanRWHandler *fd_can_read, 
+                                    IOReadHandler *fd_read, void *opaque)
+{
+    WinCharState *s = chr->opaque;
+
+    s->fd_can_read = fd_can_read;
+    s->fd_read = fd_read;
+    s->win_opaque = opaque;
+}
+
+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_add_read_handler = win_chr_add_read_handler;
+    chr->chr_close = win_chr_close;
+
+    if (win_chr_init(s, filename) < 0) {
+        free(s);
+        free(chr);
+        return NULL;
+    }
+    return chr;
+}
+
+static int win_chr_pipe_poll(void *opaque)
+{
+    WinCharState *s = opaque;
+    DWORD size;
+
+    PeekNamedPipe(s->hcom, NULL, 0, NULL, &size, NULL);
+    if (size > 0) {
+        s->len = size;
+        win_chr_read_poll(s);
+        win_chr_read(s);
+        return 1;
+    }
+    return 0;
+}
+
+static int win_chr_pipe_init(WinCharState *s, const char *filename)
+{
+    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, s);
+    return 0;
+
+ fail:
+    win_chr_close2(s);
+    return -1;
+}
+
+
+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_add_read_handler = win_chr_add_read_handler;
+    chr->chr_close = win_chr_close;
+    
+    if (win_chr_pipe_init(s, filename) < 0) {
+        free(s);
+        free(chr);
+        return NULL;
+    }
+    return chr;
+}
+
+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;
+    chr->chr_add_read_handler = win_chr_add_read_handler;
+    return chr;
+}
+    
+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
+
 CharDriverState *qemu_chr_open(const char *filename)
 {
     const char *p;
+
     if (!strcmp(filename, "vc")) {
         return text_console_init(&display_state);
     } else if (!strcmp(filename, "null")) {
@@ -1642,11 +2134,28 @@ CharDriverState *qemu_chr_open(const char *filename)
         return qemu_chr_open_tty(filename);
     } else 
 #endif
+#ifdef _WIN32
+    if (strstart(filename, "COM", NULL)) {
+        return qemu_chr_open_win(filename);
+    } else
+    if (strstart(filename, "pipe:", &p)) {
+        return qemu_chr_open_win_pipe(p);
+    } else
+    if (strstart(filename, "file:", &p)) {
+        return qemu_chr_open_win_file_out(p);
+    }
+#endif
     {
         return NULL;
     }
 }
 
+void qemu_chr_close(CharDriverState *chr)
+{
+    if (chr->chr_close)
+        chr->chr_close(chr);
+}
+
 /***********************************************************/
 /* network device redirectors */
 
@@ -1731,13 +2240,9 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str)
             if (!inet_aton(buf, &saddr->sin_addr))
                 return -1;
         } else {
-#ifdef _WIN32
-            return -1;
-#else
             if ((he = gethostbyname(buf)) == NULL)
                 return - 1;
             saddr->sin_addr = *(struct in_addr *)he->h_addr;
-#endif
         }
     }
     port = strtol(p, (char **)&r, 0);
@@ -1768,13 +2273,16 @@ VLANState *qemu_find_vlan(int id)
 }
 
 VLANClientState *qemu_new_vlan_client(VLANState *vlan,
-                                      IOReadHandler *fd_read, void *opaque)
+                                      IOReadHandler *fd_read,
+                                      IOCanRWHandler *fd_can_read,
+                                      void *opaque)
 {
     VLANClientState *vc, **pvc;
     vc = qemu_mallocz(sizeof(VLANClientState));
     if (!vc)
         return NULL;
     vc->fd_read = fd_read;
+    vc->fd_can_read = fd_can_read;
     vc->opaque = opaque;
     vc->vlan = vlan;
 
@@ -1786,6 +2294,20 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
     return vc;
 }
 
+int qemu_can_send_packet(VLANClientState *vc1)
+{
+    VLANState *vlan = vc1->vlan;
+    VLANClientState *vc;
+
+    for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
+        if (vc != vc1) {
+            if (vc->fd_can_read && !vc->fd_can_read(vc->opaque))
+                return 0;
+        }
+    }
+    return 1;
+}
+
 void qemu_send_packet(VLANClientState *vc1, const uint8_t *buf, int size)
 {
     VLANState *vlan = vc1->vlan;
@@ -1811,7 +2333,7 @@ static VLANClientState *slirp_vc;
 
 int slirp_can_output(void)
 {
-    return 1;
+    return !slirp_vc || qemu_can_send_packet(slirp_vc);
 }
 
 void slirp_output(const uint8_t *pkt, int pkt_len)
@@ -1820,6 +2342,8 @@ void slirp_output(const uint8_t *pkt, int pkt_len)
     printf("slirp output:\n");
     hex_dump(stdout, pkt, pkt_len);
 #endif
+    if (!slirp_vc)
+        return;
     qemu_send_packet(slirp_vc, pkt, pkt_len);
 }
 
@@ -1839,7 +2363,7 @@ static int net_slirp_init(VLANState *vlan)
         slirp_init();
     }
     slirp_vc = qemu_new_vlan_client(vlan, 
-                                    slirp_receive, NULL);
+                                    slirp_receive, NULL, NULL);
     snprintf(slirp_vc->info_str, sizeof(slirp_vc->info_str), "user redirector");
     return 0;
 }
@@ -2024,7 +2548,7 @@ static TAPState *net_tap_fd_init(VLANState *vlan, int fd)
     if (!s)
         return NULL;
     s->fd = fd;
-    s->vc = qemu_new_vlan_client(vlan, tap_receive, s);
+    s->vc = qemu_new_vlan_client(vlan, tap_receive, NULL, s);
     qemu_set_fd_handler(s->fd, tap_send, NULL, s);
     snprintf(s->vc->info_str, sizeof(s->vc->info_str), "tap: fd=%d", fd);
     return s;
@@ -2050,6 +2574,12 @@ static int tap_open(char *ifname, int ifname_size)
     fcntl(fd, F_SETFL, O_NONBLOCK);
     return fd;
 }
+#elif defined(__sun__)
+static int tap_open(char *ifname, int ifname_size)
+{
+    fprintf(stderr, "warning: tap_open not yet implemented\n");
+    return -1;
+}
 #else
 static int tap_open(char *ifname, int ifname_size)
 {
@@ -2127,6 +2657,8 @@ static int net_tap_init(VLANState *vlan, const char *ifname1,
     return 0;
 }
 
+#endif /* !_WIN32 */
+
 /* network connection */
 typedef struct NetSocketState {
     VLANClientState *vc;
@@ -2150,8 +2682,8 @@ static void net_socket_receive(void *opaque, const uint8_t *buf, int size)
     uint32_t len;
     len = htonl(size);
 
-    unix_write(s->fd, (const uint8_t *)&len, sizeof(len));
-    unix_write(s->fd, buf, size);
+    send_all(s->fd, (const uint8_t *)&len, sizeof(len));
+    send_all(s->fd, buf, size);
 }
 
 static void net_socket_receive_dgram(void *opaque, const uint8_t *buf, int size)
@@ -2164,16 +2696,20 @@ static void net_socket_receive_dgram(void *opaque, const uint8_t *buf, int size)
 static void net_socket_send(void *opaque)
 {
     NetSocketState *s = opaque;
-    int l, size;
+    int l, size, err;
     uint8_t buf1[4096];
     const uint8_t *buf;
 
-    size = read(s->fd, buf1, sizeof(buf1));
-    if (size < 0) 
-        return;
-    if (size == 0) {
+    size = recv(s->fd, buf1, sizeof(buf1), 0);
+    if (size < 0) {
+        err = socket_error();
+        if (err != EWOULDBLOCK) 
+            goto eoc;
+    } else if (size == 0) {
         /* end of connection */
+    eoc:
         qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+        closesocket(s->fd);
         return;
     }
     buf = buf1;
@@ -2236,7 +2772,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr)
     int val, ret;
     if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) {
        fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) does not contain a multicast address\n",
-               inet_ntoa(mcastaddr->sin_addr), ntohl(mcastaddr->sin_addr.s_addr));
+               inet_ntoa(mcastaddr->sin_addr), 
+                (int)ntohl(mcastaddr->sin_addr.s_addr));
        return -1;
 
     }
@@ -2246,11 +2783,26 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr)
         return -1;
     }
 
+    val = 1;
+    ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 
+                   (const char *)&val, sizeof(val));
+    if (ret < 0) {
+       perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
+       goto fail;
+    }
+
+    ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
+    if (ret < 0) {
+        perror("bind");
+        goto fail;
+    }
+    
     /* Add host to multicast group */
     imr.imr_multiaddr = mcastaddr->sin_addr;
     imr.imr_interface.s_addr = htonl(INADDR_ANY);
 
-    ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *) &imr, sizeof(struct ip_mreq));
+    ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, 
+                     (const char *)&imr, sizeof(struct ip_mreq));
     if (ret < 0) {
        perror("setsockopt(IP_ADD_MEMBERSHIP)");
        goto fail;
@@ -2258,25 +2810,14 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr)
 
     /* Force mcast msgs to loopback (eg. several QEMUs in same host */
     val = 1;
-    ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &val, sizeof(val));
+    ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, 
+                   (const char *)&val, sizeof(val));
     if (ret < 0) {
        perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
        goto fail;
     }
 
-    ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
-    if (ret < 0) {
-       perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
-       goto fail;
-    }
-    
-    ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
-    if (ret < 0) {
-        perror("bind");
-        goto fail;
-    }
-    
-    fcntl(fd, F_SETFL, O_NONBLOCK);
+    socket_set_nonblock(fd);
     return fd;
 fail:
     if (fd>=0) close(fd);
@@ -2327,7 +2868,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd,
         return NULL;
     s->fd = fd;
 
-    s->vc = qemu_new_vlan_client(vlan, net_socket_receive_dgram, s);
+    s->vc = qemu_new_vlan_client(vlan, net_socket_receive_dgram, NULL, s);
     qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s);
 
     /* mcast: save bound address as dst */
@@ -2355,7 +2896,7 @@ static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, int fd,
         return NULL;
     s->fd = fd;
     s->vc = qemu_new_vlan_client(vlan, 
-                                 net_socket_receive, s);
+                                 net_socket_receive, NULL, s);
     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
              "socket: fd=%d", fd);
     if (is_connected) {
@@ -2371,7 +2912,7 @@ static NetSocketState *net_socket_fd_init(VLANState *vlan, int fd,
 {
     int so_type=-1, optlen=sizeof(so_type);
 
-    if(getsockopt(fd, SOL_SOCKET,SO_TYPE, &so_type, &optlen)< 0) {
+    if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type, &optlen)< 0) {
        fprintf(stderr, "qemu: error: setsockopt(SO_TYPE) for fd=%d failed\n", fd);
        return NULL;
     }
@@ -2433,11 +2974,11 @@ static int net_socket_listen_init(VLANState *vlan, const char *host_str)
         perror("socket");
         return -1;
     }
-    fcntl(fd, F_SETFL, O_NONBLOCK);
+    socket_set_nonblock(fd);
 
     /* allow fast reuse */
     val = 1;
-    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
+    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
     
     ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
     if (ret < 0) {
@@ -2458,7 +2999,7 @@ static int net_socket_listen_init(VLANState *vlan, const char *host_str)
 static int net_socket_connect_init(VLANState *vlan, const char *host_str)
 {
     NetSocketState *s;
-    int fd, connected, ret;
+    int fd, connected, ret, err;
     struct sockaddr_in saddr;
 
     if (parse_host_port(&saddr, host_str) < 0)
@@ -2469,18 +3010,19 @@ static int net_socket_connect_init(VLANState *vlan, const char *host_str)
         perror("socket");
         return -1;
     }
-    fcntl(fd, F_SETFL, O_NONBLOCK);
+    socket_set_nonblock(fd);
 
     connected = 0;
     for(;;) {
         ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
         if (ret < 0) {
-            if (errno == EINTR || errno == EAGAIN) {
-            } else if (errno == EINPROGRESS) {
+            err = socket_error();
+            if (err == EINTR || err == EWOULDBLOCK) {
+            } else if (err == EINPROGRESS) {
                 break;
             } else {
                 perror("connect");
-                close(fd);
+                closesocket(fd);
                 return -1;
             }
         } else {
@@ -2524,8 +3066,6 @@ static int net_socket_mcast_init(VLANState *vlan, const char *host_str)
 
 }
 
-#endif /* !_WIN32 */
-
 static int get_param_value(char *buf, int buf_size,
                            const char *tag, const char *str)
 {
@@ -2617,6 +3157,9 @@ int net_client_init(const char *str)
                 return -1;
             }
         }
+        if (get_param_value(buf, sizeof(buf), "model", p)) {
+            nd->model = strdup(buf);
+        }
         nd->vlan = vlan;
         nb_nics++;
         ret = 0;
@@ -2628,10 +3171,22 @@ int net_client_init(const char *str)
     } else
 #ifdef CONFIG_SLIRP
     if (!strcmp(device, "user")) {
+        if (get_param_value(buf, sizeof(buf), "hostname", p)) {
+            pstrcpy(slirp_hostname, sizeof(slirp_hostname), buf);
+        }
         ret = net_slirp_init(vlan);
     } else
 #endif
-#ifndef _WIN32
+#ifdef _WIN32
+    if (!strcmp(device, "tap")) {
+        char ifname[64];
+        if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
+            fprintf(stderr, "tap: no interface name\n");
+            return -1;
+        }
+        ret = tap_win32_init(vlan, ifname);
+    } else
+#else
     if (!strcmp(device, "tap")) {
         char ifname[64];
         char setup_script[1024];
@@ -2649,6 +3204,7 @@ int net_client_init(const char *str)
             ret = net_tap_init(vlan, ifname, setup_script);
         }
     } else
+#endif
     if (!strcmp(device, "socket")) {
         if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
             int fd;
@@ -2667,7 +3223,6 @@ int net_client_init(const char *str)
             return -1;
         }
     } else
-#endif
     {
         fprintf(stderr, "Unknown network device: %s\n", device);
         return -1;
@@ -2717,6 +3272,10 @@ static int usb_device_add(const char *devname)
         dev = usb_mouse_init();
         if (!dev)
             return -1;
+    } else if (!strcmp(devname, "tablet")) {
+       dev = usb_tablet_init();
+       if (!dev)
+           return -1;
     } else {
         return -1;
     }
@@ -2855,7 +3414,7 @@ static void dumb_resize(DisplayState *ds, int w, int h)
 
 static void dumb_refresh(DisplayState *ds)
 {
-    vga_update_display();
+    vga_hw_update();
 }
 
 void dumb_display_init(DisplayState *ds)
@@ -2918,6 +3477,7 @@ int qemu_set_fd_handler2(int fd,
                 break;
             if (ioh->fd == fd) {
                 *pioh = ioh->next;
+                qemu_free(ioh);
                 break;
             }
             pioh = &ioh->next;
@@ -2951,6 +3511,43 @@ int qemu_set_fd_handler(int fd,
 }
 
 /***********************************************************/
+/* Polling handling */
+
+typedef struct PollingEntry {
+    PollingFunc *func;
+    void *opaque;
+    struct PollingEntry *next;
+} PollingEntry;
+
+static PollingEntry *first_polling_entry;
+
+int qemu_add_polling_cb(PollingFunc *func, void *opaque)
+{
+    PollingEntry **ppe, *pe;
+    pe = qemu_mallocz(sizeof(PollingEntry));
+    if (!pe)
+        return -1;
+    pe->func = func;
+    pe->opaque = opaque;
+    for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next);
+    *ppe = pe;
+    return 0;
+}
+
+void qemu_del_polling_cb(PollingFunc *func, void *opaque)
+{
+    PollingEntry **ppe, *pe;
+    for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) {
+        pe = *ppe;
+        if (pe->func == func && pe->opaque == opaque) {
+            *ppe = pe->next;
+            qemu_free(pe);
+            break;
+        }
+    }
+}
+
+/***********************************************************/
 /* savevm/loadvm support */
 
 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
@@ -3812,80 +4409,106 @@ void qemu_system_powerdown_request(void)
 
 void main_loop_wait(int timeout)
 {
-#ifndef _WIN32
-    struct pollfd ufds[MAX_IO_HANDLERS + 1], *pf;
     IOHandlerRecord *ioh, *ioh_next;
-#endif
-    int ret;
+    fd_set rfds, wfds, xfds;
+    int ret, nfds;
+    struct timeval tv;
+    PollingEntry *pe;
+
 
+    /* XXX: need to suppress polling by better using win32 events */
+    ret = 0;
+    for(pe = first_polling_entry; pe != NULL; pe = pe->next) {
+        ret |= pe->func(pe->opaque);
+    }
 #ifdef _WIN32
-        if (timeout > 0)
-            Sleep(timeout);
-#else
-        /* poll any events */
-        /* XXX: separate device handlers from system ones */
-        pf = ufds;
-        for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) {
-            pf->events = 0;
-            pf->fd = ioh->fd;
-            if (ioh->fd_read &&
-                (!ioh->fd_read_poll ||
-                 ioh->fd_read_poll(ioh->opaque) != 0)) {
-                pf->events |= POLLIN;
-            }
-            if (ioh->fd_write) {
-                pf->events |= POLLOUT;
+    if (ret == 0 && timeout > 0) {
+            int err;
+            HANDLE hEvents[1];
+
+            hEvents[0] = host_alarm;
+            ret = WaitForMultipleObjects(1, hEvents, FALSE, timeout);
+            switch(ret) {
+            case WAIT_OBJECT_0 + 0:
+                break;
+            case WAIT_TIMEOUT:
+                break;
+            default:
+                err = GetLastError();
+                fprintf(stderr, "Wait error %d %d\n", ret, err);
+                break;
             }
-            ioh->ufd = pf;
-            pf++;
+    }
+#endif
+    /* poll any events */
+    /* XXX: separate device handlers from system ones */
+    nfds = -1;
+    FD_ZERO(&rfds);
+    FD_ZERO(&wfds);
+    FD_ZERO(&xfds);
+    for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) {
+        if (ioh->fd_read &&
+            (!ioh->fd_read_poll ||
+             ioh->fd_read_poll(ioh->opaque) != 0)) {
+            FD_SET(ioh->fd, &rfds);
+            if (ioh->fd > nfds)
+                nfds = ioh->fd;
         }
-        
-        ret = poll(ufds, pf - ufds, timeout);
-        if (ret > 0) {
-            /* XXX: better handling of removal */
-            for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) {
-                ioh_next = ioh->next;
-                pf = ioh->ufd;
-                if (pf->revents & POLLIN) {
-                    ioh->fd_read(ioh->opaque);
-                }
-                if (pf->revents & POLLOUT) {
-                    ioh->fd_write(ioh->opaque);
-                }
+        if (ioh->fd_write) {
+            FD_SET(ioh->fd, &wfds);
+            if (ioh->fd > nfds)
+                nfds = ioh->fd;
+        }
+    }
+    
+    tv.tv_sec = 0;
+#ifdef _WIN32
+    tv.tv_usec = 0;
+#else
+    tv.tv_usec = timeout * 1000;
+#endif
+#if defined(CONFIG_SLIRP)
+    if (slirp_inited) {
+        slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
+    }
+#endif
+    ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
+    if (ret > 0) {
+        /* XXX: better handling of removal */
+        for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) {
+            ioh_next = ioh->next;
+            if (FD_ISSET(ioh->fd, &rfds)) {
+                ioh->fd_read(ioh->opaque);
+            }
+            if (FD_ISSET(ioh->fd, &wfds)) {
+                ioh->fd_write(ioh->opaque);
             }
         }
-#endif /* !defined(_WIN32) */
+    }
 #if defined(CONFIG_SLIRP)
-        /* XXX: merge with poll() */
-        if (slirp_inited) {
-            fd_set rfds, wfds, xfds;
-            int nfds;
-            struct timeval tv;
-
-            nfds = -1;
+    if (slirp_inited) {
+        if (ret < 0) {
             FD_ZERO(&rfds);
             FD_ZERO(&wfds);
             FD_ZERO(&xfds);
-            slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
-            tv.tv_sec = 0;
-            tv.tv_usec = 0;
-            ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
-            if (ret >= 0) {
-                slirp_select_poll(&rfds, &wfds, &xfds);
-            }
         }
+        slirp_select_poll(&rfds, &wfds, &xfds);
+    }
+#endif
+#ifdef _WIN32
+    tap_win32_poll();
 #endif
 
-        if (vm_running) {
-            qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], 
-                            qemu_get_clock(vm_clock));
-            /* run dma transfers, if any */
-            DMA_run();
-        }
-
-        /* real time timers */
-        qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME], 
-                        qemu_get_clock(rt_clock));
+    if (vm_running) {
+        qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], 
+                        qemu_get_clock(vm_clock));
+        /* run dma transfers, if any */
+        DMA_run();
+    }
+    
+    /* real time timers */
+    qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME], 
+                    qemu_get_clock(rt_clock));
 }
 
 static CPUState *cur_cpu;
@@ -3893,6 +4516,9 @@ static CPUState *cur_cpu;
 int main_loop(void)
 {
     int ret, timeout;
+#ifdef CONFIG_PROFILER
+    int64_t ti;
+#endif
     CPUState *env;
 
     cur_cpu = first_cpu;
@@ -3905,7 +4531,13 @@ int main_loop(void)
                 env = env->next_cpu;
                 if (!env)
                     env = first_cpu;
+#ifdef CONFIG_PROFILER
+                ti = profile_getclock();
+#endif
                 ret = cpu_exec(env);
+#ifdef CONFIG_PROFILER
+                qemu_time += profile_getclock() - ti;
+#endif
                 if (ret != EXCP_HALTED)
                     break;
                 /* all CPUs are halted ? */
@@ -3942,7 +4574,13 @@ int main_loop(void)
         } else {
             timeout = 10;
         }
+#ifdef CONFIG_PROFILER
+        ti = profile_getclock();
+#endif
         main_loop_wait(timeout);
+#ifdef CONFIG_PROFILER
+        dev_time += profile_getclock() - ti;
+#endif
     }
     cpu_disable_ticks();
     return ret;
@@ -3988,22 +4626,26 @@ void help(void)
 #endif
            "\n"
            "Network options:\n"
-           "-net nic[,vlan=n][,macaddr=addr]\n"
+           "-net nic[,vlan=n][,macaddr=addr][,model=type]\n"
            "                create a new Network Interface Card and connect it to VLAN 'n'\n"
 #ifdef CONFIG_SLIRP
-           "-net user[,vlan=n]\n"
-           "                connect the user mode network stack to VLAN 'n'\n"
+           "-net user[,vlan=n][,hostname=host]\n"
+           "                connect the user mode network stack to VLAN 'n' and send\n"
+           "                hostname 'host' to DHCP clients\n"
 #endif
-#ifndef _WIN32
+#ifdef _WIN32
+           "-net tap[,vlan=n],ifname=name\n"
+           "                connect the host TAP network interface to VLAN 'n'\n"
+#else
            "-net tap[,vlan=n][,fd=h][,ifname=name][,script=file]\n"
            "                connect the host TAP network interface to VLAN 'n' and use\n"
            "                the network script 'file' (default=%s);\n"
            "                use 'fd=h' to connect to an already opened TAP interface\n"
+#endif
            "-net socket[,vlan=n][,fd=h][,listen=[host]:port][,connect=host:port]\n"
            "                connect the vlan 'n' to another VLAN using a socket connection\n"
            "-net socket[,vlan=n][,fd=h][,mcast=maddr:port]\n"
            "                connect the vlan 'n' to multicast maddr and port\n"
-#endif
            "-net none       use it alone to have zero network devices; if no -net option\n"
            "                is provided, the default is '-net nic -net user'\n"
            "\n"
@@ -4034,6 +4676,7 @@ void help(void)
            "                translation (t=none or lba) (usually qemu can guess them)\n"
            "-L path         set the directory for the BIOS and VGA BIOS\n"
 #ifdef USE_KQEMU
+           "-kernel-kqemu   enable KQEMU full virtualization (default is user mode only)\n"
            "-no-kqemu       disable KQEMU kernel module usage\n"
 #endif
 #ifdef USE_CODE_COPY
@@ -4042,8 +4685,10 @@ void help(void)
 #ifdef TARGET_I386
            "-std-vga        simulate a standard VGA card with VESA Bochs Extensions\n"
            "                (default is CL-GD5446 PCI VGA)\n"
+           "-no-acpi        disable ACPI\n"
 #endif
            "-loadvm file    start right away with a saved state (loadvm in monitor)\n"
+          "-vnc display    start a VNC server on display\n"
            "\n"
            "During emulation, the following keys are useful:\n"
            "ctrl-alt-f      toggle full screen\n"
@@ -4122,10 +4767,13 @@ enum {
     QEMU_OPTION_full_screen,
     QEMU_OPTION_pidfile,
     QEMU_OPTION_no_kqemu,
+    QEMU_OPTION_kernel_kqemu,
     QEMU_OPTION_win2k_hack,
     QEMU_OPTION_usb,
     QEMU_OPTION_usbdevice,
     QEMU_OPTION_smp,
+    QEMU_OPTION_vnc,
+    QEMU_OPTION_no_acpi,
 };
 
 typedef struct QEMUOption {
@@ -4177,6 +4825,7 @@ const QEMUOption qemu_options[] = {
     { "no-code-copy", 0, QEMU_OPTION_no_code_copy },
 #ifdef USE_KQEMU
     { "no-kqemu", 0, QEMU_OPTION_no_kqemu },
+    { "kernel-kqemu", 0, QEMU_OPTION_kernel_kqemu },
 #endif
 #if defined(TARGET_PPC) || defined(TARGET_SPARC)
     { "g", 1, QEMU_OPTION_g },
@@ -4192,10 +4841,12 @@ const QEMUOption qemu_options[] = {
     { "win2k-hack", 0, QEMU_OPTION_win2k_hack },
     { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
     { "smp", HAS_ARG, QEMU_OPTION_smp },
+    { "vnc", HAS_ARG, QEMU_OPTION_vnc },
     
     /* temporary options */
     { "usb", 0, QEMU_OPTION_usb },
     { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
+    { "no-acpi", 0, QEMU_OPTION_no_acpi },
     { NULL },
 };
 
@@ -4264,7 +4915,12 @@ void register_machines(void)
     qemu_register_machine(&sun4m_machine);
 #endif
 #elif defined(TARGET_ARM)
-    qemu_register_machine(&integratorcp_machine);
+    qemu_register_machine(&integratorcp926_machine);
+    qemu_register_machine(&integratorcp1026_machine);
+    qemu_register_machine(&versatilepb_machine);
+    qemu_register_machine(&versatileab_machine);
+#elif defined(TARGET_SH4)
+    qemu_register_machine(&shix_machine);
 #else
 #error unsupported CPU
 #endif
@@ -4272,6 +4928,15 @@ void register_machines(void)
 
 #ifdef HAS_AUDIO
 struct soundhw soundhw[] = {
+#ifdef TARGET_I386
+    {
+        "pcspk",
+        "PC speaker",
+        0,
+        1,
+        { .init_isa = pcspk_audio_init }
+    },
+#endif
     {
         "sb16",
         "Creative Sound Blaster 16",
@@ -4751,6 +5416,9 @@ int main(int argc, char **argv)
             case QEMU_OPTION_no_kqemu:
                 kqemu_allowed = 0;
                 break;
+            case QEMU_OPTION_kernel_kqemu:
+                kqemu_allowed = 2;
+                break;
 #endif
             case QEMU_OPTION_usb:
                 usb_enabled = 1;
@@ -4773,6 +5441,16 @@ int main(int argc, char **argv)
                     exit(1);
                 }
                 break;
+           case QEMU_OPTION_vnc:
+               vnc_display = atoi(optarg);
+               if (vnc_display < 0) {
+                   fprintf(stderr, "Invalid VNC display\n");
+                   exit(1);
+               }
+               break;
+            case QEMU_OPTION_no_acpi:
+                acpi_enabled = 0;
+                break;
             }
         }
     }
@@ -4807,6 +5485,10 @@ int main(int argc, char **argv)
     setvbuf(stdout, NULL, _IOLBF, 0);
 #endif
     
+#ifdef _WIN32
+    socket_init();
+#endif
+
     /* init network clients */
     if (nb_net_clients == 0) {
         /* if no clients, we use a default config */
@@ -4934,6 +5616,8 @@ int main(int argc, char **argv)
     /* terminal init */
     if (nographic) {
         dumb_display_init(ds);
+    } else if (vnc_display != -1) {
+       vnc_display_init(ds, vnc_display);
     } else {
 #if defined(CONFIG_SDL)
         sdl_display_init(ds, full_screen);
@@ -4944,8 +5628,6 @@ int main(int argc, char **argv)
 #endif
     }
 
-    vga_console = graphic_console_init(ds);
-    
     monitor_hd = qemu_chr_open(monitor_device);
     if (!monitor_hd) {
         fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device);