typo
[qemu] / vl.c
diff --git a/vl.c b/vl.c
index 725e954..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>
@@ -83,8 +87,6 @@
 
 #include "exec-all.h"
 
-//#define DO_TB_FLUSH
-
 #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
 
 //#define DEBUG_UNUSED_IOPORT
 
 const char *bios_dir = CONFIG_QEMU_SHAREDIR;
 char phys_ram_file[1024];
-CPUState *global_env;
-CPUState *cpu_single_env;
 void *ioport_opaque[MAX_IOPORTS];
 IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
 IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
@@ -128,13 +128,6 @@ int nb_nics;
 NICInfo nd_table[MAX_NICS];
 QEMUTimer *gui_timer;
 int vm_running;
-#ifdef HAS_AUDIO
-int audio_enabled = 0;
-int sb16_enabled = 0;
-int adlib_enabled = 0;
-int gus_enabled = 0;
-int es1370_enabled = 0;
-#endif
 int rtc_utc = 1;
 int cirrus_vga_enabled = 1;
 #ifdef TARGET_SPARC
@@ -146,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
@@ -156,6 +148,16 @@ int usb_enabled = 0;
 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)
+#define MAX_CPUS 255
+#else
+#define MAX_CPUS 1
+#endif
+int acpi_enabled = 1;
 
 /***********************************************************/
 /* x86 ISA bus support */
@@ -334,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
@@ -370,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)
@@ -379,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)
@@ -388,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)
@@ -398,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;
 }
 
@@ -409,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;
 }
 
@@ -420,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;
 }
 
@@ -427,16 +424,20 @@ int cpu_inl(CPUState *env, int addr)
 void hw_error(const char *fmt, ...)
 {
     va_list ap;
+    CPUState *env;
 
     va_start(ap, fmt);
     fprintf(stderr, "qemu: hardware error: ");
     vfprintf(stderr, fmt, ap);
     fprintf(stderr, "\n");
+    for(env = first_cpu; env != NULL; env = env->next_cpu) {
+        fprintf(stderr, "CPU #%d:\n", env->cpu_index);
 #ifdef TARGET_I386
-    cpu_dump_state(global_env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
+        cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU);
 #else
-    cpu_dump_state(global_env, stderr, fprintf, 0);
+        cpu_dump_state(env, stderr, fprintf, 0);
 #endif
+    }
     va_end(ap);
     abort();
 }
@@ -448,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)
 {
@@ -455,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)
@@ -476,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 */
 
@@ -511,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__)
@@ -551,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;
 
@@ -559,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;
     }
 }
 
@@ -582,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)
@@ -601,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)
@@ -657,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;
@@ -879,13 +910,19 @@ 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))) {
-        /* stop the cpu because a timer occured */
-        cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
+#ifdef _WIN32
+        SetEvent(host_alarm);
+#endif
+        CPUState *env = cpu_single_env;
+        if (env) {
+            /* stop the currently executing cpu because a timer occured */
+            cpu_interrupt(env, CPU_INTERRUPT_EXIT);
 #ifdef USE_KQEMU
-        if (global_env->kqemu_enabled) {
-            kqemu_cpu_interrupt(global_env);
-        }
+            if (env->kqemu_enabled) {
+                kqemu_cpu_interrupt(env);
+            }
 #endif
+        }
     }
 }
 
@@ -936,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);
@@ -945,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
@@ -974,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;
@@ -1004,6 +1058,11 @@ void quit_timers(void)
 {
 #ifdef _WIN32
     timeKillEvent(timerID);
+    timeEndPeriod(period);
+    if (host_alarm) {
+        CloseHandle(host_alarm);
+        host_alarm = NULL;
+    }
 #endif
 }
 
@@ -1073,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)
 {
@@ -1108,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;
@@ -1185,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);
@@ -1387,6 +1510,7 @@ CharDriverState *qemu_chr_open_stdio(void)
 #if defined(__linux__)
 CharDriverState *qemu_chr_open_pty(void)
 {
+    struct termios tty;
     char slave_name[1024];
     int master_fd, slave_fd;
     
@@ -1394,6 +1518,14 @@ CharDriverState *qemu_chr_open_pty(void)
     if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) < 0) {
         return NULL;
     }
+    
+    /* Disabling local echo and line-buffered output */
+    tcgetattr (master_fd, &tty);
+    tty.c_lflag &= ~(ECHO|ICANON|ISIG);
+    tty.c_cc[VMIN] = 1;
+    tty.c_cc[VTIME] = 0;
+    tcsetattr (master_fd, TCSAFLUSH, &tty);
+
     fprintf(stderr, "char device redirected to %s\n", slave_name);
     return qemu_chr_open_fd(master_fd, master_fd);
 }
@@ -1602,20 +1734,393 @@ 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")) {
         return qemu_chr_open_null();
-    } else if (strstart(filename, "file:", &p)) {
+    } else 
+#ifndef _WIN32
+    if (strstart(filename, "file:", &p)) {
         return qemu_chr_open_file_out(p);
     } else if (strstart(filename, "pipe:", &p)) {
         return qemu_chr_open_pipe(p);
-    } else 
-#ifndef _WIN32
-    if (!strcmp(filename, "pty")) {
+    } else if (!strcmp(filename, "pty")) {
         return qemu_chr_open_pty();
     } else if (!strcmp(filename, "stdio")) {
         return qemu_chr_open_stdio();
@@ -1629,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 */
 
@@ -1718,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);
@@ -1755,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;
 
@@ -1773,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;
@@ -1798,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)
@@ -1807,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);
 }
 
@@ -1826,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;
 }
@@ -2011,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;
@@ -2037,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)
 {
@@ -2095,7 +2638,7 @@ static int net_tap_init(VLANState *vlan, const char *ifname1,
                 *parg++ = ifname;
                 *parg++ = NULL;
                 execv(setup_script, args);
-                exit(1);
+                _exit(1);
             }
             while (waitpid(pid, &status, 0) != pid);
             if (!WIFEXITED(status) ||
@@ -2114,6 +2657,8 @@ static int net_tap_init(VLANState *vlan, const char *ifname1,
     return 0;
 }
 
+#endif /* !_WIN32 */
+
 /* network connection */
 typedef struct NetSocketState {
     VLANClientState *vc;
@@ -2122,6 +2667,7 @@ typedef struct NetSocketState {
     int index;
     int packet_len;
     uint8_t buf[4096];
+    struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
 } NetSocketState;
 
 typedef struct NetSocketListenState {
@@ -2136,60 +2682,203 @@ 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)
+{
+    NetSocketState *s = opaque;
+    sendto(s->fd, buf, size, 0, 
+           (struct sockaddr *)&s->dgram_dst, sizeof(s->dgram_dst));
+}
+
+static void net_socket_send(void *opaque)
+{
+    NetSocketState *s = opaque;
+    int l, size, err;
+    uint8_t buf1[4096];
+    const uint8_t *buf;
+
+    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;
+    while (size > 0) {
+        /* reassemble a packet from the network */
+        switch(s->state) {
+        case 0:
+            l = 4 - s->index;
+            if (l > size)
+                l = size;
+            memcpy(s->buf + s->index, buf, l);
+            buf += l;
+            size -= l;
+            s->index += l;
+            if (s->index == 4) {
+                /* got length */
+                s->packet_len = ntohl(*(uint32_t *)s->buf);
+                s->index = 0;
+                s->state = 1;
+            }
+            break;
+        case 1:
+            l = s->packet_len - s->index;
+            if (l > size)
+                l = size;
+            memcpy(s->buf + s->index, buf, l);
+            s->index += l;
+            buf += l;
+            size -= l;
+            if (s->index >= s->packet_len) {
+                qemu_send_packet(s->vc, s->buf, s->packet_len);
+                s->index = 0;
+                s->state = 0;
+            }
+            break;
+        }
+    }
+}
+
+static void net_socket_send_dgram(void *opaque)
+{
+    NetSocketState *s = opaque;
+    int size;
+
+    size = recv(s->fd, s->buf, sizeof(s->buf), 0);
+    if (size < 0) 
+        return;
+    if (size == 0) {
+        /* end of connection */
+        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+        return;
+    }
+    qemu_send_packet(s->vc, s->buf, size);
+}
+
+static int net_socket_mcast_create(struct sockaddr_in *mcastaddr)
+{
+    struct ip_mreq imr;
+    int fd;
+    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), 
+                (int)ntohl(mcastaddr->sin_addr.s_addr));
+       return -1;
+
+    }
+    fd = socket(PF_INET, SOCK_DGRAM, 0);
+    if (fd < 0) {
+        perror("socket(PF_INET, SOCK_DGRAM)");
+        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, 
+                     (const char *)&imr, sizeof(struct ip_mreq));
+    if (ret < 0) {
+       perror("setsockopt(IP_ADD_MEMBERSHIP)");
+       goto fail;
+    }
+
+    /* Force mcast msgs to loopback (eg. several QEMUs in same host */
+    val = 1;
+    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;
+    }
+
+    socket_set_nonblock(fd);
+    return fd;
+fail:
+    if (fd>=0) close(fd);
+    return -1;
 }
 
-static void net_socket_send(void *opaque)
+static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd, 
+                                          int is_connected)
 {
-    NetSocketState *s = opaque;
-    int l, size;
-    uint8_t buf1[4096];
-    const uint8_t *buf;
+    struct sockaddr_in saddr;
+    int newfd;
+    socklen_t saddr_len;
+    NetSocketState *s;
 
-    size = read(s->fd, buf1, sizeof(buf1));
-    if (size < 0) 
-        return;
-    if (size == 0) {
-        /* end of connection */
-        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
-        return;
-    }
-    buf = buf1;
-    while (size > 0) {
-        /* reassemble a packet from the network */
-        switch(s->state) {
-        case 0:
-            l = 4 - s->index;
-            if (l > size)
-                l = size;
-            memcpy(s->buf + s->index, buf, l);
-            buf += l;
-            size -= l;
-            s->index += l;
-            if (s->index == 4) {
-                /* got length */
-                s->packet_len = ntohl(*(uint32_t *)s->buf);
-                s->index = 0;
-                s->state = 1;
-            }
-            break;
-        case 1:
-            l = s->packet_len - s->index;
-            if (l > size)
-                l = size;
-            memcpy(s->buf + s->index, buf, l);
-            s->index += l;
-            buf += l;
-            size -= l;
-            if (s->index >= s->packet_len) {
-                qemu_send_packet(s->vc, s->buf, s->packet_len);
-                s->index = 0;
-                s->state = 0;
-            }
-            break;
-        }
+    /* fd passed: multicast: "learn" dgram_dst address from bound address and save it
+     * Because this may be "shared" socket from a "master" process, datagrams would be recv() 
+     * by ONLY ONE process: we must "clone" this dgram socket --jjo
+     */
+
+    if (is_connected) {
+       if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) {
+           /* must be bound */
+           if (saddr.sin_addr.s_addr==0) {
+               fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, cannot setup multicast dst addr\n",
+                       fd);
+               return NULL;
+           }
+           /* clone dgram socket */
+           newfd = net_socket_mcast_create(&saddr);
+           if (newfd < 0) {
+               /* error already reported by net_socket_mcast_create() */
+               close(fd);
+               return NULL;
+           }
+           /* clone newfd to fd, close newfd */
+           dup2(newfd, fd);
+           close(newfd);
+       
+       } else {
+           fprintf(stderr, "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n",
+                   fd, strerror(errno));
+           return NULL;
+       }
     }
+
+    s = qemu_mallocz(sizeof(NetSocketState));
+    if (!s)
+        return NULL;
+    s->fd = fd;
+
+    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 */
+    if (is_connected) s->dgram_dst=saddr;
+
+    snprintf(s->vc->info_str, sizeof(s->vc->info_str),
+           "socket: fd=%d (%s mcast=%s:%d)", 
+           fd, is_connected? "cloned" : "",
+           inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+    return s;
 }
 
 static void net_socket_connect(void *opaque)
@@ -2198,7 +2887,7 @@ static void net_socket_connect(void *opaque)
     qemu_set_fd_handler(s->fd, net_socket_send, NULL, s);
 }
 
-static NetSocketState *net_socket_fd_init(VLANState *vlan, int fd, 
+static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, int fd, 
                                           int is_connected)
 {
     NetSocketState *s;
@@ -2207,7 +2896,7 @@ static NetSocketState *net_socket_fd_init(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) {
@@ -2218,6 +2907,28 @@ static NetSocketState *net_socket_fd_init(VLANState *vlan, int fd,
     return s;
 }
 
+static NetSocketState *net_socket_fd_init(VLANState *vlan, int fd, 
+                                          int is_connected)
+{
+    int so_type=-1, optlen=sizeof(so_type);
+
+    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;
+    }
+    switch(so_type) {
+    case SOCK_DGRAM:
+        return net_socket_fd_init_dgram(vlan, fd, is_connected);
+    case SOCK_STREAM:
+        return net_socket_fd_init_stream(vlan, fd, is_connected);
+    default:
+        /* who knows ... this could be a eg. a pty, do warn and continue as stream */
+        fprintf(stderr, "qemu: warning: socket type=%d for fd=%d is not SOCK_DGRAM or SOCK_STREAM\n", so_type, fd);
+        return net_socket_fd_init_stream(vlan, fd, is_connected);
+    }
+    return NULL;
+}
+
 static void net_socket_accept(void *opaque)
 {
     NetSocketListenState *s = opaque;    
@@ -2263,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) {
@@ -2288,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)
@@ -2299,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 {
@@ -2327,7 +3039,32 @@ static int net_socket_connect_init(VLANState *vlan, const char *host_str)
     return 0;
 }
 
-#endif /* !_WIN32 */
+static int net_socket_mcast_init(VLANState *vlan, const char *host_str)
+{
+    NetSocketState *s;
+    int fd;
+    struct sockaddr_in saddr;
+
+    if (parse_host_port(&saddr, host_str) < 0)
+        return -1;
+
+
+    fd = net_socket_mcast_create(&saddr);
+    if (fd < 0)
+       return -1;
+
+    s = net_socket_fd_init(vlan, fd, 0);
+    if (!s)
+        return -1;
+
+    s->dgram_dst = saddr;
+    
+    snprintf(s->vc->info_str, sizeof(s->vc->info_str),
+             "socket: mcast=%s:%d", 
+             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+    return 0;
+
+}
 
 static int get_param_value(char *buf, int buf_size,
                            const char *tag, const char *str)
@@ -2420,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;
@@ -2431,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];
@@ -2452,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;
@@ -2463,12 +3216,13 @@ int net_client_init(const char *str)
             ret = net_socket_listen_init(vlan, buf);
         } else if (get_param_value(buf, sizeof(buf), "connect", p) > 0) {
             ret = net_socket_connect_init(vlan, buf);
+        } else if (get_param_value(buf, sizeof(buf), "mcast", p) > 0) {
+            ret = net_socket_mcast_init(vlan, buf);
         } else {
             fprintf(stderr, "Unknown socket options: %s\n", p);
             return -1;
         }
     } else
-#endif
     {
         fprintf(stderr, "Unknown network device: %s\n", device);
         return -1;
@@ -2518,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;
     }
@@ -2656,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)
@@ -2719,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;
@@ -2752,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)
@@ -2970,9 +3766,6 @@ int qemu_loadvm(const char *filename)
         goto the_end;
     }
     for(;;) {
-#if defined (DO_TB_FLUSH)
-        tb_flush(global_env);
-#endif
         len = qemu_get_byte(f);
         if (feof(f))
             break;
@@ -3358,6 +4151,19 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     tlb_flush(env, 1);
     return 0;
 }
+
+#elif defined(TARGET_ARM)
+
+/* ??? Need to implement these.  */
+void cpu_save(QEMUFile *f, void *opaque)
+{
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+    return 0;
+}
+
 #else
 
 #warning No CPU save/restore functions
@@ -3583,115 +4389,165 @@ void qemu_system_reset(void)
 void qemu_system_reset_request(void)
 {
     reset_requested = 1;
-    cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
+    if (cpu_single_env)
+        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
 }
 
 void qemu_system_shutdown_request(void)
 {
     shutdown_requested = 1;
-    cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
+    if (cpu_single_env)
+        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
 }
 
 void qemu_system_powerdown_request(void)
 {
     powerdown_requested = 1;
-    cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
-}
-
-static void main_cpu_reset(void *opaque)
-{
-#if defined(TARGET_I386) || defined(TARGET_SPARC)
-    CPUState *env = opaque;
-    cpu_reset(env);
-#endif
+    if (cpu_single_env)
+        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
 }
 
 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;
+
 int main_loop(void)
 {
     int ret, timeout;
-    CPUState *env = global_env;
+#ifdef CONFIG_PROFILER
+    int64_t ti;
+#endif
+    CPUState *env;
 
+    cur_cpu = first_cpu;
     for(;;) {
         if (vm_running) {
-            ret = cpu_exec(env);
+
+            env = cur_cpu;
+            for(;;) {
+                /* get next cpu */
+                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 ? */
+                if (env == cur_cpu) {
+                    ret = EXCP_HLT;
+                    break;
+                }
+            }
+            cur_cpu = env;
+
             if (shutdown_requested) {
                 ret = EXCP_INTERRUPT;
                 break;
@@ -3718,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;
@@ -3740,16 +4602,17 @@ void help(void)
            "-boot [a|c|d]   boot on floppy (a), hard disk (c) or CD-ROM (d)\n"
           "-snapshot       write to temporary files instead of disk image files\n"
            "-m megs         set virtual RAM size to megs MB [default=%d]\n"
+           "-smp n          set the number of CPUs to 'n' [default=1]\n"
            "-nographic      disable graphical output and redirect serial I/Os to console\n"
 #ifndef _WIN32
           "-k language     use keyboard layout (for example \"fr\" for French)\n"
 #endif
 #ifdef HAS_AUDIO
-           "-enable-audio   enable audio support, and all the sound cars\n"
            "-audio-help     print list of audio drivers and their options\n"
            "-soundhw c1,... enable audio support\n"
            "                and only specified sound cards (comma separated list)\n"
            "                use -soundhw ? to get the list of supported cards\n"
+           "                use -soundhw all to enable all of them\n"
 #endif
            "-localtime      set the real time clock to local time [default=utc]\n"
            "-full-screen    start in full screen\n"
@@ -3763,20 +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"
-           "-net socket[,vlan=n][,fd=x][,listen=[host]:port][,connect=host:port]\n"
-           "                connect the vlan 'n' to another VLAN using a socket connection\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"
            "-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"
@@ -3807,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
@@ -3815,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"
@@ -3863,7 +4735,6 @@ enum {
     QEMU_OPTION_m,
     QEMU_OPTION_nographic,
 #ifdef HAS_AUDIO
-    QEMU_OPTION_enable_audio,
     QEMU_OPTION_audio_help,
     QEMU_OPTION_soundhw,
 #endif
@@ -3896,9 +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 {
@@ -3924,7 +4799,6 @@ const QEMUOption qemu_options[] = {
     { "nographic", 0, QEMU_OPTION_nographic },
     { "k", HAS_ARG, QEMU_OPTION_k },
 #ifdef HAS_AUDIO
-    { "enable-audio", 0, QEMU_OPTION_enable_audio },
     { "audio-help", 0, QEMU_OPTION_audio_help },
     { "soundhw", HAS_ARG, QEMU_OPTION_soundhw },
 #endif
@@ -3951,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 },
@@ -3965,10 +4840,13 @@ const QEMUOption qemu_options[] = {
     { "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
     { "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 },
 };
 
@@ -4036,62 +4914,112 @@ void register_machines(void)
 #else
     qemu_register_machine(&sun4m_machine);
 #endif
+#elif defined(TARGET_ARM)
+    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
 }
 
 #ifdef HAS_AUDIO
-static void select_soundhw (const char *optarg)
-{
-    if (*optarg == '?') {
-    show_valid_cards:
-        printf ("Valid sound card names (comma separated):\n");
-        printf ("sb16       Creative Sound Blaster 16\n");
+struct soundhw soundhw[] = {
+#ifdef TARGET_I386
+    {
+        "pcspk",
+        "PC speaker",
+        0,
+        1,
+        { .init_isa = pcspk_audio_init }
+    },
+#endif
+    {
+        "sb16",
+        "Creative Sound Blaster 16",
+        0,
+        1,
+        { .init_isa = SB16_init }
+    },
+
 #ifdef CONFIG_ADLIB
+    {
+        "adlib",
 #ifdef HAS_YMF262
-        printf ("adlib      Yamaha YMF262 (OPL3)\n");
+        "Yamaha YMF262 (OPL3)",
 #else
-        printf ("adlib      Yamaha YM3812 (OPL2)\n");
+        "Yamaha YM3812 (OPL2)",
 #endif
+        0,
+        1,
+        { .init_isa = Adlib_init }
+    },
 #endif
+
 #ifdef CONFIG_GUS
-        printf ("gus        Gravis Ultrasound GF1\n");
+    {
+        "gus",
+        "Gravis Ultrasound GF1",
+        0,
+        1,
+        { .init_isa = GUS_init }
+    },
 #endif
-        printf ("es1370     ENSONIQ AudioPCI ES1370\n");
+
+    {
+        "es1370",
+        "ENSONIQ AudioPCI ES1370",
+        0,
+        0,
+        { .init_pci = es1370_init }
+    },
+
+    { NULL, NULL, 0, 0, { NULL } }
+};
+
+static void select_soundhw (const char *optarg)
+{
+    struct soundhw *c;
+
+    if (*optarg == '?') {
+    show_valid_cards:
+
+        printf ("Valid sound card names (comma separated):\n");
+        for (c = soundhw; c->name; ++c) {
+            printf ("%-11s %s\n", c->name, c->descr);
+        }
+        printf ("\n-soundhw all will enable all of the above\n");
         exit (*optarg != '?');
     }
     else {
-        struct {
-            char *name;
-            int *enabledp;
-        } soundhw_tab[] = {
-            { "sb16", &sb16_enabled },
-#ifdef CONFIG_ADLIB
-            { "adlib", &adlib_enabled },
-#endif
-#ifdef CONFIG_GUS
-            { "gus", &gus_enabled },
-#endif
-            { "es1370", &es1370_enabled },
-        };
-        size_t tablen, l, i;
+        size_t l;
         const char *p;
         char *e;
         int bad_card = 0;
 
-        p = optarg;
-        tablen = sizeof (soundhw_tab) / sizeof (soundhw_tab[0]);
+        if (!strcmp (optarg, "all")) {
+            for (c = soundhw; c->name; ++c) {
+                c->enabled = 1;
+            }
+            return;
+        }
 
+        p = optarg;
         while (*p) {
             e = strchr (p, ',');
             l = !e ? strlen (p) : (size_t) (e - p);
-            for (i = 0; i < tablen; ++i) {
-                if (!strncmp (soundhw_tab[i].name, p, l)) {
-                    audio_enabled = 1;
-                    *soundhw_tab[i].enabledp = 1;
+
+            for (c = soundhw; c->name; ++c) {
+                if (!strncmp (c->name, p, l)) {
+                    c->enabled = 1;
                     break;
                 }
             }
-            if (i == tablen) {
+
+            if (!c->name) {
                 if (l > 80) {
                     fprintf (stderr,
                              "Unknown sound card name (too big to show)\n");
@@ -4120,7 +5048,6 @@ int main(int argc, char **argv)
 #endif
     int i, cdrom_index;
     int snapshot, linux_boot;
-    CPUState *env;
     const char *initrd_filename;
     const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
     const char *kernel_filename, *kernel_cmdline;
@@ -4353,13 +5280,6 @@ int main(int argc, char **argv)
                 break;
 #endif
 #ifdef HAS_AUDIO
-            case QEMU_OPTION_enable_audio:
-                audio_enabled = 1;
-                sb16_enabled = 1;
-                adlib_enabled = 1;
-                gus_enabled = 1;
-                es1370_enabled = 1;
-                break;
             case QEMU_OPTION_audio_help:
                 AUD_help ();
                 exit (0);
@@ -4496,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;
@@ -4511,10 +5434,31 @@ int main(int argc, char **argv)
                         optarg);
                 usb_devices_index++;
                 break;
+            case QEMU_OPTION_smp:
+                smp_cpus = atoi(optarg);
+                if (smp_cpus < 1 || smp_cpus > MAX_CPUS) {
+                    fprintf(stderr, "Invalid number of CPUs\n");
+                    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;
             }
         }
     }
 
+#ifdef USE_KQEMU
+    if (smp_cpus > 1)
+        kqemu_allowed = 0;
+#endif
     linux_boot = (kernel_filename != NULL);
         
     if (!linux_boot && 
@@ -4541,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 */
@@ -4659,15 +5607,8 @@ int main(int argc, char **argv)
         }
     }
 
-    /* init CPU state */
-    env = cpu_init();
-    global_env = env;
-    cpu_single_env = env;
-
-    register_savevm("timer", 0, 1, timer_save, timer_load, env);
-    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+    register_savevm("timer", 0, 1, timer_save, timer_load, NULL);
     register_savevm("ram", 0, 1, ram_save, ram_load, NULL);
-    qemu_register_reset(main_cpu_reset, global_env);
 
     init_ioports();
     cpu_calibrate_ticks();
@@ -4675,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);
@@ -4685,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);