typo
[qemu] / vl.c
diff --git a/vl.c b/vl.c
index 83c6716..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"
 #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
 
+#include "qemu_socket.h"
+
 #ifdef CONFIG_SDL
 #ifdef __APPLE__
 #include <SDL/SDL.h>
@@ -147,6 +149,7 @@ USBPort *vm_usb_ports[MAX_VM_USB_PORTS];
 USBDevice *vm_usb_hub;
 static VLANState *first_vlan;
 int smp_cpus = 1;
+int vnc_display = -1;
 #if defined(TARGET_SPARC)
 #define MAX_CPUS 16
 #elif defined(TARGET_I386)
@@ -154,6 +157,7 @@ int smp_cpus = 1;
 #else
 #define MAX_CPUS 1
 #endif
+int acpi_enabled = 1;
 
 /***********************************************************/
 /* x86 ISA bus support */
@@ -332,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
@@ -474,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)
 {
@@ -481,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)
@@ -502,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 */
 
@@ -537,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__)
@@ -577,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;
 
@@ -585,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;
     }
 }
 
@@ -608,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)
@@ -627,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)
@@ -683,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;
@@ -905,6 +910,9 @@ static void host_alarm_handler(int host_signum)
                            qemu_get_clock(vm_clock)) ||
         qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME],
                            qemu_get_clock(rt_clock))) {
+#ifdef _WIN32
+        SetEvent(host_alarm);
+#endif
         CPUState *env = cpu_single_env;
         if (env) {
             /* stop the currently executing cpu because a timer occured */
@@ -965,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);
@@ -974,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
@@ -1003,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;
@@ -1033,6 +1058,11 @@ void quit_timers(void)
 {
 #ifdef _WIN32
     timeKillEvent(timerID);
+    timeEndPeriod(period);
+    if (host_alarm) {
+        CloseHandle(host_alarm);
+        host_alarm = NULL;
+    }
 #endif
 }
 
@@ -1104,12 +1134,6 @@ CharDriverState *qemu_chr_open_null(void)
 
 #ifdef _WIN32
 
-#define socket_error() WSAGetLastError()
-#undef EINTR
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#define EINTR       WSAEINTR
-#define EINPROGRESS WSAEINPROGRESS
-
 static void socket_cleanup(void)
 {
     WSACleanup();
@@ -1161,9 +1185,6 @@ void socket_set_nonblock(int fd)
 
 #else
 
-#define socket_error() errno
-#define closesocket(s) close(s)
-
 static int unix_write(int fd, const uint8_t *buf, int len1)
 {
     int ret, len;
@@ -2553,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)
 {
@@ -3144,6 +3171,9 @@ 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
@@ -3242,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;
     }
@@ -4376,7 +4410,7 @@ void qemu_system_powerdown_request(void)
 void main_loop_wait(int timeout)
 {
     IOHandlerRecord *ioh, *ioh_next;
-    fd_set rfds, wfds;
+    fd_set rfds, wfds, xfds;
     int ret, nfds;
     struct timeval tv;
     PollingEntry *pe;
@@ -4389,7 +4423,21 @@ void main_loop_wait(int timeout)
     }
 #ifdef _WIN32
     if (ret == 0 && timeout > 0) {
-        Sleep(timeout);
+            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;
+            }
     }
 #endif
     /* poll any events */
@@ -4397,6 +4445,7 @@ void main_loop_wait(int timeout)
     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 ||
@@ -4418,7 +4467,12 @@ void main_loop_wait(int timeout)
 #else
     tv.tv_usec = timeout * 1000;
 #endif
-    ret = select(nfds + 1, &rfds, &wfds, NULL, &tv);
+#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) {
@@ -4431,30 +4485,19 @@ void main_loop_wait(int timeout)
             }
         }
     }
-#ifdef _WIN32
-    tap_win32_poll();
-#endif
-
 #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);
+        if (ret < 0) {
+            FD_ZERO(&rfds);
+            FD_ZERO(&wfds);
+            FD_ZERO(&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], 
@@ -4586,8 +4629,9 @@ void help(void)
            "-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
 #ifdef _WIN32
            "-net tap[,vlan=n],ifname=name\n"
@@ -4632,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
@@ -4640,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"
@@ -4725,6 +4772,8 @@ enum {
     QEMU_OPTION_usb,
     QEMU_OPTION_usbdevice,
     QEMU_OPTION_smp,
+    QEMU_OPTION_vnc,
+    QEMU_OPTION_no_acpi,
 };
 
 typedef struct QEMUOption {
@@ -4792,10 +4841,12 @@ const QEMUOption qemu_options[] = {
     { "win2k-hack", 0, QEMU_OPTION_win2k_hack },
     { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
     { "smp", HAS_ARG, QEMU_OPTION_smp },
+    { "vnc", HAS_ARG, QEMU_OPTION_vnc },
     
     /* temporary options */
     { "usb", 0, QEMU_OPTION_usb },
     { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
+    { "no-acpi", 0, QEMU_OPTION_no_acpi },
     { NULL },
 };
 
@@ -4867,6 +4918,9 @@ void register_machines(void)
     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
@@ -4874,6 +4928,15 @@ void register_machines(void)
 
 #ifdef HAS_AUDIO
 struct soundhw soundhw[] = {
+#ifdef TARGET_I386
+    {
+        "pcspk",
+        "PC speaker",
+        0,
+        1,
+        { .init_isa = pcspk_audio_init }
+    },
+#endif
     {
         "sb16",
         "Creative Sound Blaster 16",
@@ -5378,6 +5441,16 @@ int main(int argc, char **argv)
                     exit(1);
                 }
                 break;
+           case QEMU_OPTION_vnc:
+               vnc_display = atoi(optarg);
+               if (vnc_display < 0) {
+                   fprintf(stderr, "Invalid VNC display\n");
+                   exit(1);
+               }
+               break;
+            case QEMU_OPTION_no_acpi:
+                acpi_enabled = 0;
+                break;
             }
         }
     }
@@ -5543,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);