Make sure gui_key_modifier_pressed is cleared correctly.
[qemu] / vl.c
diff --git a/vl.c b/vl.c
index 2baca1c..e0406ea 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -64,6 +64,8 @@
 #include <malloc.h>
 #include <sys/timeb.h>
 #include <windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
 #define getopt_long_only getopt_long
 #define memalign(align, size) malloc(size)
 #endif
@@ -124,13 +126,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
@@ -374,6 +369,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)
@@ -383,6 +382,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)
@@ -392,6 +395,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)
@@ -402,6 +409,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;
 }
 
@@ -413,6 +424,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;
 }
 
@@ -424,6 +439,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;
 }
 
@@ -1084,20 +1103,67 @@ 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;
+#define socket_error() WSAGetLastError()
+#undef EINTR
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define EINTR       WSAEINTR
+#define EINPROGRESS WSAEINPROGRESS
 
-#define STDIO_MAX_CLIENTS 2
+static void socket_cleanup(void)
+{
+    WSACleanup();
+}
 
-static int stdio_nb_clients;
-static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];
+static int socket_init(void)
+{
+    WSADATA Data;
+    int ret, err;
+
+    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
+
+#define socket_error() errno
+#define closesocket(s) close(s)
 
 static int unix_write(int fd, const uint8_t *buf, int len1)
 {
@@ -1119,6 +1185,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;
@@ -1398,6 +1490,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;
     
@@ -1405,6 +1498,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);
 }
@@ -1615,7 +1716,10 @@ CharDriverState *qemu_chr_open_pty(void)
 
 CharDriverState *qemu_chr_open(const char *filename)
 {
+#ifndef _WIN32
     const char *p;
+#endif
+
     if (!strcmp(filename, "vc")) {
         return text_console_init(&display_state);
     } else if (!strcmp(filename, "null")) {
@@ -1729,13 +1833,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);
@@ -1766,13 +1866,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;
 
@@ -1784,6 +1887,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;
@@ -1809,7 +1926,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)
@@ -1818,6 +1935,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);
 }
 
@@ -1837,7 +1956,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;
 }
@@ -2022,7 +2141,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;
@@ -2125,6 +2244,8 @@ static int net_tap_init(VLANState *vlan, const char *ifname1,
     return 0;
 }
 
+#endif /* !_WIN32 */
+
 /* network connection */
 typedef struct NetSocketState {
     VLANClientState *vc;
@@ -2148,8 +2269,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)
@@ -2162,16 +2283,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;
@@ -2234,7 +2359,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;
 
     }
@@ -2244,11 +2370,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;
@@ -2256,25 +2397,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, SOL_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);
@@ -2325,7 +2455,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 */
@@ -2353,7 +2483,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) {
@@ -2369,7 +2499,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;
     }
@@ -2431,11 +2561,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) {
@@ -2456,7 +2586,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)
@@ -2467,18 +2597,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 {
@@ -2522,8 +2653,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)
 {
@@ -2615,6 +2744,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;
@@ -2629,7 +2761,16 @@ int net_client_init(const char *str)
         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];
@@ -2647,6 +2788,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;
@@ -2665,7 +2807,6 @@ int net_client_init(const char *str)
             return -1;
         }
     } else
-#endif
     {
         fprintf(stderr, "Unknown network device: %s\n", device);
         return -1;
@@ -2916,6 +3057,7 @@ int qemu_set_fd_handler2(int fd,
                 break;
             if (ioh->fd == fd) {
                 *pioh = ioh->next;
+                qemu_free(ioh);
                 break;
             }
             pioh = &ioh->next;
@@ -3810,80 +3952,91 @@ 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;
+    int ret, nfds;
+    struct timeval tv;
 
 #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;
-            }
-            ioh->ufd = pf;
-            pf++;
+    /* XXX: see how to merge it with the select. The constraint is
+       that the select must be interrupted by the timer */
+    if (timeout > 0)
+        Sleep(timeout);
+#endif
+    /* poll any events */
+    /* XXX: separate device handlers from system ones */
+    nfds = -1;
+    FD_ZERO(&rfds);
+    FD_ZERO(&wfds);
+    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;
         }
-#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;
-            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);
+    }
+    
+    tv.tv_sec = 0;
+#ifdef _WIN32
+    tv.tv_usec = 0;
+#else
+    tv.tv_usec = timeout * 1000;
+#endif
+    ret = select(nfds + 1, &rfds, &wfds, NULL, &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);
             }
         }
+    }
+#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();
+#if defined(CONFIG_SLIRP)
+    /* XXX: merge with the previous select() */
+    if (slirp_inited) {
+        fd_set rfds, wfds, xfds;
+        int nfds;
+        struct timeval tv;
+        
+        nfds = -1;
+        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);
         }
+    }
+#endif
 
-        /* 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;
@@ -3891,6 +4044,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;
@@ -3903,7 +4059,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 ? */
@@ -3940,7 +4102,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;
@@ -3962,16 +4130,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"
@@ -3985,22 +4154,25 @@ 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"
 #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"
@@ -4087,7 +4259,6 @@ enum {
     QEMU_OPTION_m,
     QEMU_OPTION_nographic,
 #ifdef HAS_AUDIO
-    QEMU_OPTION_enable_audio,
     QEMU_OPTION_audio_help,
     QEMU_OPTION_soundhw,
 #endif
@@ -4120,6 +4291,7 @@ 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,
@@ -4149,7 +4321,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
@@ -4176,6 +4347,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 },
@@ -4263,65 +4435,98 @@ 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);
 #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[] = {
+    {
+        "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");
@@ -4582,13 +4787,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);
@@ -4725,6 +4923,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;
@@ -4751,6 +4952,10 @@ int main(int argc, char **argv)
         }
     }
 
+#ifdef USE_KQEMU
+    if (smp_cpus > 1)
+        kqemu_allowed = 0;
+#endif
     linux_boot = (kernel_filename != NULL);
         
     if (!linux_boot && 
@@ -4777,6 +4982,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 */