]> git.proxmox.com Git - mirror_qemu.git/blobdiff - vl.c
Update Changelog
[mirror_qemu.git] / vl.c
diff --git a/vl.c b/vl.c
index 9cb81ce47cd288f81d1f664f2b494e3496ab3d6c..6aa27c28090648aeb98ff6ae425986d64f1dfb73 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -1,7 +1,7 @@
 /*
  * QEMU System Emulator
  *
- * Copyright (c) 2003-2007 Fabrice Bellard
+ * Copyright (c) 2003-2008 Fabrice Bellard
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -26,9 +26,9 @@
 #include "hw/usb.h"
 #include "hw/pcmcia.h"
 #include "hw/pc.h"
-#include "hw/fdc.h"
 #include "hw/audiodev.h"
 #include "hw/isa.h"
+#include "hw/baum.h"
 #include "net.h"
 #include "console.h"
 #include "sysemu.h"
@@ -109,7 +109,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
 #ifdef _WIN32
 #include <malloc.h>
 #include <sys/timeb.h>
-#include <windows.h>
+#include <mmsystem.h>
 #define getopt_long_only getopt_long
 #define memalign(align, size) malloc(size)
 #endif
@@ -172,6 +172,7 @@ BlockDriverState *bs_snapshots;
 int vga_ram_size;
 static DisplayState display_state;
 int nographic;
+int curses;
 const char* keyboard_layout = NULL;
 int64_t ticks_per_sec;
 int ram_size;
@@ -179,8 +180,8 @@ int pit_min_timer_count = 0;
 int nb_nics;
 NICInfo nd_table[MAX_NICS];
 int vm_running;
-int rtc_utc = 1;
-int rtc_start_date = -1; /* -1 means now */
+static int rtc_utc = 1;
+static int rtc_date_offset = -1; /* -1 means no change */
 int cirrus_vga_enabled = 1;
 int vmsvga_enabled = 0;
 #ifdef TARGET_SPARC
@@ -231,11 +232,14 @@ unsigned int nb_prom_envs = 0;
 const char *prom_envs[MAX_PROM_ENVS];
 #endif
 int nb_drives_opt;
-char drives_opt[MAX_DRIVES][1024];
+struct drive_opt {
+    const char *file;
+    char opt[1024];
+} drives_opt[MAX_DRIVES];
 
 static CPUState *cur_cpu;
 static CPUState *next_cpu;
-static int event_pending;
+static int event_pending = 1;
 
 #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
 
@@ -584,7 +588,7 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
             if (qemu_put_mouse_event_current->qemu_put_mouse_event_absolute)
                 width = 0x7fff;
             else
-                width = graphic_width;
+                width = graphic_width - 1;
             mouse_event(mouse_event_opaque,
                                  width - dy, dx, dz, buttons_state);
         } else
@@ -822,6 +826,7 @@ struct qemu_alarm_timer {
 };
 
 #define ALARM_FLAG_DYNTICKS  0x1
+#define ALARM_FLAG_EXPIRED   0x2
 
 static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
 {
@@ -894,7 +899,7 @@ static struct qemu_alarm_timer alarm_timers[] = {
     {NULL, }
 };
 
-static void show_available_alarms()
+static void show_available_alarms(void)
 {
     int i;
 
@@ -911,7 +916,7 @@ static void configure_alarms(char const *opt)
     char *arg;
     char *name;
 
-    if (!strcmp(opt, "help")) {
+    if (!strcmp(opt, "?")) {
         show_available_alarms();
         exit(0);
     }
@@ -953,10 +958,10 @@ next:
        /* Disable remaining timers */
         for (i = cur; i < count; i++)
             alarm_timers[i].name = NULL;
+    } else {
+        show_available_alarms();
+        exit(1);
     }
-
-    /* debug */
-    show_available_alarms();
 }
 
 QEMUClock *rt_clock;
@@ -1033,6 +1038,11 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
     ts->expire_time = expire_time;
     ts->next = *pt;
     *pt = ts;
+
+    /* Rearm if necessary  */
+    if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0 &&
+        pt == &active_timers[ts->clock->type])
+        qemu_rearm_alarm_timer(alarm_timer);
 }
 
 int qemu_timer_pending(QEMUTimer *ts)
@@ -1067,7 +1077,6 @@ static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time)
         /* run the callback (the timer list can be modified) */
         ts->cb(ts->opaque);
     }
-    qemu_rearm_alarm_timer(alarm_timer);
 }
 
 int64_t qemu_get_clock(QEMUClock *clock)
@@ -1119,9 +1128,9 @@ static void timer_save(QEMUFile *f, void *opaque)
     if (cpu_ticks_enabled) {
         hw_error("cannot save state if virtual timers are running");
     }
-    qemu_put_be64s(f, &cpu_ticks_offset);
-    qemu_put_be64s(f, &ticks_per_sec);
-    qemu_put_be64s(f, &cpu_clock_offset);
+    qemu_put_be64(f, cpu_ticks_offset);
+    qemu_put_be64(f, ticks_per_sec);
+    qemu_put_be64(f, cpu_clock_offset);
 }
 
 static int timer_load(QEMUFile *f, void *opaque, int version_id)
@@ -1131,10 +1140,10 @@ static int timer_load(QEMUFile *f, void *opaque, int version_id)
     if (cpu_ticks_enabled) {
         return -EINVAL;
     }
-    qemu_get_be64s(f, &cpu_ticks_offset);
-    qemu_get_be64s(f, &ticks_per_sec);
+    cpu_ticks_offset=qemu_get_be64(f);
+    ticks_per_sec=qemu_get_be64(f);
     if (version_id == 2) {
-        qemu_get_be64s(f, &cpu_clock_offset);
+        cpu_clock_offset=qemu_get_be64(f);
     }
     return 0;
 }
@@ -1186,13 +1195,17 @@ static void host_alarm_handler(int host_signum)
 #endif
         CPUState *env = next_cpu;
 
-        /* stop the currently executing cpu because a timer occured */
-        cpu_interrupt(env, CPU_INTERRUPT_EXIT);
+        alarm_timer->flags |= ALARM_FLAG_EXPIRED;
+
+        if (env) {
+            /* stop the currently executing cpu because a timer occured */
+            cpu_interrupt(env, CPU_INTERRUPT_EXIT);
 #ifdef USE_KQEMU
-        if (env->kqemu_enabled) {
-            kqemu_cpu_interrupt(env);
-        }
+            if (env->kqemu_enabled) {
+                kqemu_cpu_interrupt(env);
+            }
 #endif
+        }
         event_pending = 1;
     }
 }
@@ -1293,11 +1306,14 @@ static void hpet_stop_timer(struct qemu_alarm_timer *t)
 static int rtc_start_timer(struct qemu_alarm_timer *t)
 {
     int rtc_fd;
+    unsigned long current_rtc_freq = 0;
 
     TFR(rtc_fd = open("/dev/rtc", O_RDONLY));
     if (rtc_fd < 0)
         return -1;
-    if (ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) {
+    ioctl(rtc_fd, RTC_IRQP_READ, &current_rtc_freq);
+    if (current_rtc_freq != RTC_FREQ &&
+        ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) {
         fprintf(stderr, "Could not configure '/dev/rtc' to have a 1024 Hz timer. This is not a fatal\n"
                 "error, but for better emulation accuracy either use a 2.6 host Linux kernel or\n"
                 "type 'echo 1024 > /proc/sys/dev/rtc/max-user-freq' as root.\n");
@@ -1369,7 +1385,7 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
 
     if (!active_timers[QEMU_TIMER_REALTIME] &&
                 !active_timers[QEMU_TIMER_VIRTUAL])
-            return;
+        return;
 
     nearest_delta_us = qemu_next_deadline();
 
@@ -1496,7 +1512,7 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t)
 
     if (!active_timers[QEMU_TIMER_REALTIME] &&
                 !active_timers[QEMU_TIMER_VIRTUAL])
-            return;
+        return;
 
     nearest_delta_us = qemu_next_deadline();
     nearest_delta_us /= 1000;
@@ -1548,6 +1564,43 @@ static void quit_timers(void)
     alarm_timer = NULL;
 }
 
+/***********************************************************/
+/* host time/date access */
+void qemu_get_timedate(struct tm *tm, int offset)
+{
+    time_t ti;
+    struct tm *ret;
+
+    time(&ti);
+    ti += offset;
+    if (rtc_date_offset == -1) {
+        if (rtc_utc)
+            ret = gmtime(&ti);
+        else
+            ret = localtime(&ti);
+    } else {
+        ti -= rtc_date_offset;
+        ret = gmtime(&ti);
+    }
+
+    memcpy(tm, ret, sizeof(struct tm));
+}
+
+int qemu_timedate_diff(struct tm *tm)
+{
+    time_t seconds;
+
+    if (rtc_date_offset == -1)
+        if (rtc_utc)
+            seconds = mktimegm(tm);
+        else
+            seconds = mktime(tm);
+    else
+        seconds = mktimegm(tm) + rtc_date_offset;
+
+    return seconds - time(NULL);
+}
+
 /***********************************************************/
 /* character device */
 
@@ -1610,7 +1663,7 @@ void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
     va_list ap;
     va_start(ap, fmt);
     vsnprintf(buf, sizeof(buf), fmt, ap);
-    qemu_chr_write(s, buf, strlen(buf));
+    qemu_chr_write(s, (uint8_t *)buf, strlen(buf));
     va_end(ap);
 }
 
@@ -1699,7 +1752,7 @@ static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
                          (secs / 60) % 60,
                          secs % 60,
                          (int)((ti / 1000000) % 1000));
-                d->drv->chr_write(d->drv, buf1, strlen(buf1));
+                d->drv->chr_write(d->drv, (uint8_t *)buf1, strlen(buf1));
             }
         }
     }
@@ -1728,15 +1781,16 @@ static void mux_print_help(CharDriverState *chr)
         sprintf(cbuf,"\n\r");
         sprintf(ebuf,"C-%c", term_escape_char - 1 + 'a');
     } else {
-        sprintf(cbuf,"\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r", term_escape_char);
+        sprintf(cbuf,"\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r",
+            term_escape_char);
     }
-    chr->chr_write(chr, cbuf, strlen(cbuf));
+    chr->chr_write(chr, (uint8_t *)cbuf, strlen(cbuf));
     for (i = 0; mux_help[i] != NULL; i++) {
         for (j=0; mux_help[i][j] != '\0'; j++) {
             if (mux_help[i][j] == '%')
-                chr->chr_write(chr, ebuf, strlen(ebuf));
+                chr->chr_write(chr, (uint8_t *)ebuf, strlen(ebuf));
             else
-                chr->chr_write(chr, &mux_help[i][j], 1);
+                chr->chr_write(chr, (uint8_t *)&mux_help[i][j], 1);
         }
     }
 }
@@ -1755,7 +1809,7 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
         case 'x':
             {
                  char *term =  "QEMU: Terminated\n\r";
-                 chr->chr_write(chr,term,strlen(term));
+                 chr->chr_write(chr,(uint8_t *)term,strlen(term));
                  exit(0);
                  break;
             }
@@ -2037,6 +2091,20 @@ static void fd_chr_update_read_handler(CharDriverState *chr)
     }
 }
 
+static void fd_chr_close(struct CharDriverState *chr)
+{
+    FDCharDriver *s = chr->opaque;
+
+    if (s->fd_in >= 0) {
+        if (nographic && s->fd_in == 0) {
+        } else {
+            qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL);
+        }
+    }
+
+    qemu_free(s);
+}
+
 /* open a character device to a unix fd */
 static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
 {
@@ -2056,6 +2124,7 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
     chr->opaque = s;
     chr->chr_write = fd_chr_write;
     chr->chr_update_read_handler = fd_chr_update_read_handler;
+    chr->chr_close = fd_chr_close;
 
     qemu_chr_reset(chr);
 
@@ -2142,6 +2211,7 @@ static void stdio_read(void *opaque)
 /* init terminal so that we can grab keys */
 static struct termios oldtty;
 static int old_fd0_flags;
+static int term_atexit_done;
 
 static void term_exit(void)
 {
@@ -2171,11 +2241,20 @@ static void term_init(void)
 
     tcsetattr (0, TCSANOW, &tty);
 
-    atexit(term_exit);
+    if (!term_atexit_done++)
+        atexit(term_exit);
 
     fcntl(0, F_SETFL, O_NONBLOCK);
 }
 
+static void qemu_chr_close_stdio(struct CharDriverState *chr)
+{
+    term_exit();
+    stdio_nb_clients--;
+    qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL);
+    fd_chr_close(chr);
+}
+
 static CharDriverState *qemu_chr_open_stdio(void)
 {
     CharDriverState *chr;
@@ -2183,6 +2262,7 @@ static CharDriverState *qemu_chr_open_stdio(void)
     if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
         return NULL;
     chr = qemu_chr_open_fd(0, 1);
+    chr->chr_close = qemu_chr_close_stdio;
     qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr);
     stdio_nb_clients++;
     term_init();
@@ -2227,45 +2307,33 @@ static void tty_serial_init(int fd, int speed,
 #endif
     tcgetattr (fd, &tty);
 
-    switch(speed) {
-    case 50:
+#define MARGIN 1.1
+    if (speed <= 50 * MARGIN)
         spd = B50;
-        break;
-    case 75:
+    else if (speed <= 75 * MARGIN)
         spd = B75;
-        break;
-    case 300:
+    else if (speed <= 300 * MARGIN)
         spd = B300;
-        break;
-    case 600:
+    else if (speed <= 600 * MARGIN)
         spd = B600;
-        break;
-    case 1200:
+    else if (speed <= 1200 * MARGIN)
         spd = B1200;
-        break;
-    case 2400:
+    else if (speed <= 2400 * MARGIN)
         spd = B2400;
-        break;
-    case 4800:
+    else if (speed <= 4800 * MARGIN)
         spd = B4800;
-        break;
-    case 9600:
+    else if (speed <= 9600 * MARGIN)
         spd = B9600;
-        break;
-    case 19200:
+    else if (speed <= 19200 * MARGIN)
         spd = B19200;
-        break;
-    case 38400:
+    else if (speed <= 38400 * MARGIN)
         spd = B38400;
-        break;
-    case 57600:
+    else if (speed <= 57600 * MARGIN)
         spd = B57600;
-        break;
-    default:
-    case 115200:
+    else if (speed <= 115200 * MARGIN)
+        spd = B115200;
+    else
         spd = B115200;
-        break;
-    }
 
     cfsetispeed(&tty, spd);
     cfsetospeed(&tty, spd);
@@ -2876,7 +2944,7 @@ static CharDriverState *qemu_chr_open_win_file_out(const char *file_out)
 typedef struct {
     int fd;
     struct sockaddr_in daddr;
-    char buf[1024];
+    uint8_t buf[1024];
     int bufcnt;
     int bufptr;
     int max_size;
@@ -3034,7 +3102,7 @@ static int tcp_chr_read_poll(void *opaque)
 #define IAC_BREAK 243
 static void tcp_chr_process_IAC_bytes(CharDriverState *chr,
                                       TCPCharDriver *s,
-                                      char *buf, int *size)
+                                      uint8_t *buf, int *size)
 {
     /* Handle any telnet client's basic IAC options to satisfy char by
      * char mode with no echo.  All IAC options will be removed from
@@ -3406,7 +3474,12 @@ CharDriverState *qemu_chr_open(const char *filename)
     } else
     if (strstart(filename, "file:", &p)) {
         return qemu_chr_open_win_file_out(p);
-    }
+    } else
+#endif
+#ifdef CONFIG_BRLAPI
+    if (!strcmp(filename, "braille")) {
+        return chr_baum_init();
+    } else
 #endif
     {
         return NULL;
@@ -3417,6 +3490,7 @@ void qemu_chr_close(CharDriverState *chr)
 {
     if (chr->chr_close)
         chr->chr_close(chr);
+    qemu_free(chr);
 }
 
 /***********************************************************/
@@ -3452,18 +3526,33 @@ static void hex_dump(FILE *f, const uint8_t *buf, int size)
 static int parse_macaddr(uint8_t *macaddr, const char *p)
 {
     int i;
-    for(i = 0; i < 6; i++) {
-        macaddr[i] = strtol(p, (char **)&p, 16);
-        if (i == 5) {
-            if (*p != '\0')
-                return -1;
-        } else {
-            if (*p != ':')
-                return -1;
-            p++;
+    char *last_char;
+    long int offset;
+
+    errno = 0;
+    offset = strtol(p, &last_char, 0);    
+    if (0 == errno && '\0' == *last_char &&
+            offset >= 0 && offset <= 0xFFFFFF) {
+        macaddr[3] = (offset & 0xFF0000) >> 16;
+        macaddr[4] = (offset & 0xFF00) >> 8;
+        macaddr[5] = offset & 0xFF;
+        return 0;
+    } else {
+        for(i = 0; i < 6; i++) {
+            macaddr[i] = strtol(p, (char **)&p, 16);
+            if (i == 5) {
+                if (*p != '\0')
+                    return -1;
+            } else {
+                if (*p != ':' && *p != '-')
+                    return -1;
+                p++;
+            }
         }
+        return 0;    
     }
-    return 0;
+
+    return -1;
 }
 
 static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
@@ -3747,27 +3836,35 @@ static void net_slirp_redir(const char *redir_str)
 
 char smb_dir[1024];
 
-static void smb_exit(void)
+static void erase_dir(char *dir_name)
 {
     DIR *d;
     struct dirent *de;
     char filename[1024];
 
     /* erase all the files in the directory */
-    d = opendir(smb_dir);
-    for(;;) {
-        de = readdir(d);
-        if (!de)
-            break;
-        if (strcmp(de->d_name, ".") != 0 &&
-            strcmp(de->d_name, "..") != 0) {
-            snprintf(filename, sizeof(filename), "%s/%s",
-                     smb_dir, de->d_name);
-            unlink(filename);
+    if ((d = opendir(dir_name)) != 0) {
+        for(;;) {
+            de = readdir(d);
+            if (!de)
+                break;
+            if (strcmp(de->d_name, ".") != 0 &&
+                strcmp(de->d_name, "..") != 0) {
+                snprintf(filename, sizeof(filename), "%s/%s",
+                         smb_dir, de->d_name);
+                if (unlink(filename) != 0)  /* is it a directory? */
+                    erase_dir(filename);
+            }
         }
+        closedir(d);
+        rmdir(dir_name);
     }
-    closedir(d);
-    rmdir(smb_dir);
+}
+
+/* automatic user mode samba server configuration */
+static void smb_exit(void)
+{
+    erase_dir(smb_dir);
 }
 
 /* automatic user mode samba server configuration */
@@ -4397,7 +4494,8 @@ 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, (char *)&so_type, &optlen)< 0) {
+    if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
+        (socklen_t *)&optlen)< 0) {
        fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n", fd);
        return NULL;
     }
@@ -4555,24 +4653,33 @@ static int net_socket_mcast_init(VLANState *vlan, const char *host_str)
 
 }
 
-static const char *get_word(char *buf, int buf_size, const char *p)
+static const char *get_opt_name(char *buf, int buf_size, const char *p)
+{
+    char *q;
+
+    q = buf;
+    while (*p != '\0' && *p != '=') {
+        if (q && (q - buf) < buf_size - 1)
+            *q++ = *p;
+        p++;
+    }
+    if (q)
+        *q = '\0';
+
+    return p;
+}
+
+static const char *get_opt_value(char *buf, int buf_size, const char *p)
 {
     char *q;
-    int substring;
 
-    substring = 0;
     q = buf;
     while (*p != '\0') {
-        if (*p == '\\') {
-            p++;
-            if (*p == '\0')
+        if (*p == ',') {
+            if (*(p + 1) != ',')
                 break;
-        } else if (*p == '\"') {
-            substring = !substring;
             p++;
-            continue;
-        } else if (!substring && (*p == ',' || *p == '='))
-            break;
+        }
         if (q && (q - buf) < buf_size - 1)
             *q++ = *p;
         p++;
@@ -4591,15 +4698,15 @@ static int get_param_value(char *buf, int buf_size,
 
     p = str;
     for(;;) {
-        p = get_word(option, sizeof(option), p);
+        p = get_opt_name(option, sizeof(option), p);
         if (*p != '=')
             break;
         p++;
         if (!strcmp(tag, option)) {
-            (void)get_word(buf, buf_size, p);
+            (void)get_opt_value(buf, buf_size, p);
             return strlen(buf);
         } else {
-            p = get_word(NULL, 0, p);
+            p = get_opt_value(NULL, 0, p);
         }
         if (*p != ',')
             break;
@@ -4616,7 +4723,7 @@ static int check_params(char *buf, int buf_size,
 
     p = str;
     for(;;) {
-        p = get_word(buf, buf_size, p);
+        p = get_opt_name(buf, buf_size, p);
         if (*p != '=')
             return -1;
         p++;
@@ -4625,7 +4732,7 @@ static int check_params(char *buf, int buf_size,
                 break;
         if (params[i] == NULL)
             return -1;
-        p = get_word(NULL, 0, p);
+        p = get_opt_value(NULL, 0, p);
         if (*p != ',')
             break;
         p++;
@@ -4725,6 +4832,7 @@ static int net_client_init(const char *str)
         vlan->nb_host_devs++;
         if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
             fd = strtol(buf, NULL, 0);
+            fcntl(fd, F_SETFL, O_NONBLOCK);
             ret = -1;
             if (net_tap_fd_init(vlan, fd))
                 ret = 0;
@@ -4784,18 +4892,18 @@ void do_info_network(void)
     }
 }
 
-#define HD_ALIAS "file=\"%s\",index=%d,media=disk"
+#define HD_ALIAS "index=%d,media=disk"
 #ifdef TARGET_PPC
 #define CDROM_ALIAS "index=1,media=cdrom"
 #else
 #define CDROM_ALIAS "index=2,media=cdrom"
 #endif
 #define FD_ALIAS "index=%d,if=floppy"
-#define PFLASH_ALIAS "file=\"%s\",if=pflash"
-#define MTD_ALIAS "file=\"%s\",if=mtd"
+#define PFLASH_ALIAS "if=pflash"
+#define MTD_ALIAS "if=mtd"
 #define SD_ALIAS "index=0,if=sd"
 
-static int drive_add(const char *fmt, ...)
+static int drive_add(const char *file, const char *fmt, ...)
 {
     va_list ap;
 
@@ -4804,21 +4912,23 @@ static int drive_add(const char *fmt, ...)
         exit(1);
     }
 
+    drives_opt[nb_drives_opt].file = file;
     va_start(ap, fmt);
-    vsnprintf(drives_opt[nb_drives_opt], sizeof(drives_opt[0]), fmt, ap);
+    vsnprintf(drives_opt[nb_drives_opt].opt,
+              sizeof(drives_opt[0].opt), fmt, ap);
     va_end(ap);
 
     return nb_drives_opt++;
 }
 
-int drive_get_index(BlockInterfaceType interface, int bus, int unit)
+int drive_get_index(BlockInterfaceType type, int bus, int unit)
 {
     int index;
 
     /* seek interface, bus and unit */
 
     for (index = 0; index < nb_drives; index++)
-        if (drives_table[index].interface == interface &&
+        if (drives_table[index].type == type &&
            drives_table[index].bus == bus &&
            drives_table[index].unit == unit)
         return index;
@@ -4826,38 +4936,43 @@ int drive_get_index(BlockInterfaceType interface, int bus, int unit)
     return -1;
 }
 
-int drive_get_max_bus(BlockInterfaceType interface)
+int drive_get_max_bus(BlockInterfaceType type)
 {
     int max_bus;
     int index;
 
     max_bus = -1;
     for (index = 0; index < nb_drives; index++) {
-        if(drives_table[index].interface == interface &&
+        if(drives_table[index].type == type &&
            drives_table[index].bus > max_bus)
             max_bus = drives_table[index].bus;
     }
     return max_bus;
 }
 
-static int drive_init(const char *str, int snapshot, QEMUMachine *machine)
+static int drive_init(struct drive_opt *arg, int snapshot,
+                      QEMUMachine *machine)
 {
     char buf[128];
     char file[1024];
     char devname[128];
     const char *mediastr = "";
-    BlockInterfaceType interface;
+    BlockInterfaceType type;
     enum { MEDIA_DISK, MEDIA_CDROM } media;
     int bus_id, unit_id;
     int cyls, heads, secs, translation;
     BlockDriverState *bdrv;
     int max_devs;
     int index;
+    int cache;
+    int bdrv_flags;
+    char *str = arg->opt;
     char *params[] = { "bus", "unit", "if", "index", "cyls", "heads",
-                       "secs", "trans", "media", "snapshot", "file", NULL };
+                       "secs", "trans", "media", "snapshot", "file",
+                       "cache", NULL };
 
     if (check_params(buf, sizeof(buf), params, str) < 0) {
-         fprintf(stderr, "qemu: unknowm parameter '%s' in '%s'\n",
+         fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
                          buf, str);
          return -1;
     }
@@ -4868,6 +4983,7 @@ static int drive_init(const char *str, int snapshot, QEMUMachine *machine)
     unit_id = -1;
     translation = BIOS_ATA_TRANSLATION_AUTO;
     index = -1;
+    cache = 1;
 
     if (!strcmp(machine->name, "realview") ||
         !strcmp(machine->name, "SS-5") ||
@@ -4875,11 +4991,11 @@ static int drive_init(const char *str, int snapshot, QEMUMachine *machine)
         !strcmp(machine->name, "SS-600MP") ||
         !strcmp(machine->name, "versatilepb") ||
         !strcmp(machine->name, "versatileab")) {
-        interface = IF_SCSI;
+        type = IF_SCSI;
         max_devs = MAX_SCSI_DEVS;
         strcpy(devname, "scsi");
     } else {
-        interface = IF_IDE;
+        type = IF_IDE;
         max_devs = MAX_IDE_DEVS;
         strcpy(devname, "ide");
     }
@@ -4906,22 +5022,22 @@ static int drive_init(const char *str, int snapshot, QEMUMachine *machine)
     if (get_param_value(buf, sizeof(buf), "if", str)) {
         strncpy(devname, buf, sizeof(devname));
         if (!strcmp(buf, "ide")) {
-           interface = IF_IDE;
+           type = IF_IDE;
             max_devs = MAX_IDE_DEVS;
         } else if (!strcmp(buf, "scsi")) {
-           interface = IF_SCSI;
+           type = IF_SCSI;
             max_devs = MAX_SCSI_DEVS;
         } else if (!strcmp(buf, "floppy")) {
-           interface = IF_FLOPPY;
+           type = IF_FLOPPY;
             max_devs = 0;
         } else if (!strcmp(buf, "pflash")) {
-           interface = IF_PFLASH;
+           type = IF_PFLASH;
             max_devs = 0;
        } else if (!strcmp(buf, "mtd")) {
-           interface = IF_MTD;
+           type = IF_MTD;
             max_devs = 0;
        } else if (!strcmp(buf, "sd")) {
-           interface = IF_SD;
+           type = IF_SD;
             max_devs = 0;
        } else {
             fprintf(stderr, "qemu: '%s' unsupported bus type '%s'\n", str, buf);
@@ -5010,7 +5126,21 @@ static int drive_init(const char *str, int snapshot, QEMUMachine *machine)
        }
     }
 
-    get_param_value(file, sizeof(file), "file", str);
+    if (get_param_value(buf, sizeof(buf), "cache", str)) {
+        if (!strcmp(buf, "off"))
+            cache = 0;
+        else if (!strcmp(buf, "on"))
+            cache = 1;
+        else {
+           fprintf(stderr, "qemu: invalid cache option\n");
+           return -1;
+        }
+    }
+
+    if (arg->file == NULL)
+        get_param_value(file, sizeof(file), "file", str);
+    else
+        pstrcpy(file, sizeof(file), arg->file);
 
     /* compute bus and unit according index */
 
@@ -5036,7 +5166,7 @@ static int drive_init(const char *str, int snapshot, QEMUMachine *machine)
 
     if (unit_id == -1) {
        unit_id = 0;
-       while (drive_get_index(interface, bus_id, unit_id) != -1) {
+       while (drive_get_index(type, bus_id, unit_id) != -1) {
            unit_id++;
            if (max_devs && unit_id >= max_devs) {
                unit_id -= max_devs;
@@ -5057,23 +5187,27 @@ static int drive_init(const char *str, int snapshot, QEMUMachine *machine)
      * ignore multiple definitions
      */
 
-    if (drive_get_index(interface, bus_id, unit_id) != -1)
+    if (drive_get_index(type, bus_id, unit_id) != -1)
         return 0;
 
     /* init */
 
-    if (interface == IF_IDE || interface == IF_SCSI)
+    if (type == IF_IDE || type == IF_SCSI)
         mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
-    snprintf(buf, sizeof(buf), max_devs ? "%1$s%4$i%2$s%3$i" : "%s%s%i",
-             devname, mediastr, unit_id, bus_id);
+    if (max_devs)
+        snprintf(buf, sizeof(buf), "%s%i%s%i",
+                 devname, bus_id, mediastr, unit_id);
+    else
+        snprintf(buf, sizeof(buf), "%s%s%i",
+                 devname, mediastr, unit_id);
     bdrv = bdrv_new(buf);
     drives_table[nb_drives].bdrv = bdrv;
-    drives_table[nb_drives].interface = interface;
+    drives_table[nb_drives].type = type;
     drives_table[nb_drives].bus = bus_id;
     drives_table[nb_drives].unit = unit_id;
     nb_drives++;
 
-    switch(interface) {
+    switch(type) {
     case IF_IDE:
     case IF_SCSI:
         switch(media) {
@@ -5100,8 +5234,12 @@ static int drive_init(const char *str, int snapshot, QEMUMachine *machine)
     }
     if (!file[0])
         return 0;
-    if (bdrv_open(bdrv, file, snapshot ? BDRV_O_SNAPSHOT : 0) < 0 ||
-        qemu_key_check(bdrv, file)) {
+    bdrv_flags = 0;
+    if (snapshot)
+        bdrv_flags |= BDRV_O_SNAPSHOT;
+    if (!cache)
+        bdrv_flags |= BDRV_O_DIRECT;
+    if (bdrv_open(bdrv, file, bdrv_flags) < 0 || qemu_key_check(bdrv, file)) {
         fprintf(stderr, "qemu: could not open disk image %s\n",
                         file);
         return -1;
@@ -5147,6 +5285,12 @@ static int usb_device_add(const char *devname)
         dev = usb_msd_init(p);
     } else if (!strcmp(devname, "wacom-tablet")) {
         dev = usb_wacom_init();
+    } else if (strstart(devname, "serial:", &p)) {
+        dev = usb_serial_init(p);
+#ifdef CONFIG_BRLAPI
+    } else if (!strcmp(devname, "braille")) {
+        dev = usb_baum_init();
+#endif
     } else {
         return -1;
     }
@@ -5778,7 +5922,7 @@ static int qemu_savevm_state(QEMUFile *f)
         /* ID string */
         len = strlen(se->idstr);
         qemu_put_byte(f, len);
-        qemu_put_buffer(f, se->idstr, len);
+        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
 
         qemu_put_be32(f, se->instance_id);
         qemu_put_be32(f, se->version_id);
@@ -5839,7 +5983,7 @@ static int qemu_loadvm_state(QEMUFile *f)
         if (qemu_ftell(f) >= end_pos)
             break;
         len = qemu_get_byte(f);
-        qemu_get_buffer(f, idstr, len);
+        qemu_get_buffer(f, (uint8_t *)idstr, len);
         idstr[len] = '\0';
         instance_id = qemu_get_be32(f);
         version_id = qemu_get_be32(f);
@@ -7074,7 +7218,11 @@ static void gui_update(void *opaque)
 {
     DisplayState *ds = opaque;
     ds->dpy_refresh(ds);
-    qemu_mod_timer(ds->gui_timer, GUI_REFRESH_INTERVAL + qemu_get_clock(rt_clock));
+    qemu_mod_timer(ds->gui_timer,
+        (ds->gui_timer_interval ?
+           ds->gui_timer_interval :
+           GUI_REFRESH_INTERVAL)
+       + qemu_get_clock(rt_clock));
 }
 
 struct vm_change_state_entry {
@@ -7168,6 +7316,27 @@ static int reset_requested;
 static int shutdown_requested;
 static int powerdown_requested;
 
+int qemu_shutdown_requested(void)
+{
+    int r = shutdown_requested;
+    shutdown_requested = 0;
+    return r;
+}
+
+int qemu_reset_requested(void)
+{
+    int r = reset_requested;
+    reset_requested = 0;
+    return r;
+}
+
+int qemu_powerdown_requested(void)
+{
+    int r = powerdown_requested;
+    powerdown_requested = 0;
+    return r;
+}
+
 void qemu_register_reset(QEMUResetHandler *func, void *opaque)
 {
     QEMUResetEntry **pre, *re;
@@ -7182,7 +7351,7 @@ void qemu_register_reset(QEMUResetHandler *func, void *opaque)
     *pre = re;
 }
 
-static void qemu_system_reset(void)
+void qemu_system_reset(void)
 {
     QEMUResetEntry *re;
 
@@ -7346,6 +7515,11 @@ void main_loop_wait(int timeout)
     qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME],
                     qemu_get_clock(rt_clock));
 
+    if (alarm_timer->flags & ALARM_FLAG_EXPIRED) {
+        alarm_timer->flags &= ~(ALARM_FLAG_EXPIRED);
+        qemu_rearm_alarm_timer(alarm_timer);
+    }
+
     /* Check bottom-halves last in case any of the earlier events triggered
        them.  */
     qemu_bh_poll();
@@ -7376,7 +7550,7 @@ static int main_loop(void)
                 qemu_time += profile_getclock() - ti;
 #endif
                 next_cpu = env->next_cpu ?: first_cpu;
-                if (event_pending) {
+                if (event_pending && likely(ret != EXCP_DEBUG)) {
                     ret = EXCP_INTERRUPT;
                     event_pending = 0;
                     break;
@@ -7408,7 +7582,7 @@ static int main_loop(void)
                qemu_system_powerdown();
                 ret = EXCP_INTERRUPT;
             }
-            if (ret == EXCP_DEBUG) {
+            if (unlikely(ret == EXCP_DEBUG)) {
                 vm_stop(EXCP_DEBUG);
             }
             /* If all cpus are halted then wait until the next IRQ */
@@ -7434,7 +7608,7 @@ static int main_loop(void)
 
 static void help(int exitcode)
 {
-    printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2007 Fabrice Bellard\n"
+    printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n"
            "usage: %s [options] [disk_image]\n"
            "\n"
            "'disk_image' is a raw hard image image for IDE hard disk 0\n"
@@ -7447,7 +7621,8 @@ static void help(int exitcode)
            "-hdc/-hdd file  use 'file' as IDE hard disk 2/3 image\n"
            "-cdrom file     use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
           "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][index=i]\n"
-           "       [,cyls=c,heads=h,secs=s[,trans=t]][snapshot=on|off]\n"
+           "       [,cyls=c,heads=h,secs=s[,trans=t]][snapshot=on|off]"
+           "       [,cache=on|off]\n"
           "                use 'file' as a drive image\n"
            "-mtdblock file  use 'file' as on-board Flash memory image\n"
            "-sd file        use 'file' as SecureDigital card image\n"
@@ -7549,6 +7724,9 @@ static void help(int exitcode)
            "-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
+#ifdef CONFIG_CURSES
+           "-curses         use a curses/ncurses interface instead of SDL\n"
 #endif
            "-no-reboot      exit instead of rebooting\n"
            "-loadvm file    start right away with a saved state (loadvm in monitor)\n"
@@ -7561,7 +7739,8 @@ static void help(int exitcode)
            "-prom-env variable=value  set OpenBIOS nvram variables\n"
 #endif
            "-clock          force the use of the given methods for timer alarm.\n"
-           "                To see what timers are available use -clock help\n"
+           "                To see what timers are available use -clock ?\n"
+           "-startdate      select initial date of the clock\n"
            "\n"
            "During emulation, the following keys are useful:\n"
            "ctrl-alt-f      toggle full screen\n"
@@ -7654,6 +7833,7 @@ enum {
     QEMU_OPTION_smp,
     QEMU_OPTION_vnc,
     QEMU_OPTION_no_acpi,
+    QEMU_OPTION_curses,
     QEMU_OPTION_no_reboot,
     QEMU_OPTION_show_cursor,
     QEMU_OPTION_daemonize,
@@ -7750,6 +7930,9 @@ const QEMUOption qemu_options[] = {
     { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
     { "smp", HAS_ARG, QEMU_OPTION_smp },
     { "vnc", HAS_ARG, QEMU_OPTION_vnc },
+#ifdef CONFIG_CURSES
+    { "curses", 0, QEMU_OPTION_curses },
+#endif
 
     /* temporary options */
     { "usb", 0, QEMU_OPTION_usb },
@@ -7828,6 +8011,7 @@ static void register_machines(void)
     qemu_register_machine(&taihu_machine);
 #elif defined(TARGET_MIPS)
     qemu_register_machine(&mips_machine);
+    qemu_register_machine(&mips_magnum_machine);
     qemu_register_machine(&mips_malta_machine);
     qemu_register_machine(&mips_pica61_machine);
     qemu_register_machine(&mips_mipssim_machine);
@@ -7839,6 +8023,14 @@ static void register_machines(void)
     qemu_register_machine(&ss10_machine);
     qemu_register_machine(&ss600mp_machine);
     qemu_register_machine(&ss20_machine);
+    qemu_register_machine(&ss2_machine);
+    qemu_register_machine(&voyager_machine);
+    qemu_register_machine(&ss_lx_machine);
+    qemu_register_machine(&ss4_machine);
+    qemu_register_machine(&scls_machine);
+    qemu_register_machine(&sbook_machine);
+    qemu_register_machine(&ss1000_machine);
+    qemu_register_machine(&ss2000_machine);
 #endif
 #elif defined(TARGET_ARM)
     qemu_register_machine(&integratorcp_machine);
@@ -7874,7 +8066,7 @@ static void register_machines(void)
 #ifdef HAS_AUDIO
 struct soundhw soundhw[] = {
 #ifdef HAS_AUDIO_CHOICE
-#ifdef TARGET_I386
+#if defined(TARGET_I386) || defined(TARGET_MIPS)
     {
         "pcspk",
         "PC speaker",
@@ -7915,6 +8107,16 @@ struct soundhw soundhw[] = {
     },
 #endif
 
+#ifdef CONFIG_AC97
+    {
+        "ac97",
+        "Intel 82801AA AC97 Audio",
+        0,
+        0,
+        { .init_pci = ac97_init }
+    },
+#endif
+
     {
         "es1370",
         "ENSONIQ AudioPCI ES1370",
@@ -8010,21 +8212,21 @@ int main(int argc, char **argv)
     const char *boot_devices = "";
     DisplayState *ds = &display_state;
     int cyls, heads, secs, translation;
-    char net_clients[MAX_NET_CLIENTS][256];
+    const char *net_clients[MAX_NET_CLIENTS];
     int nb_net_clients;
     int hda_index;
     int optind;
     const char *r, *optarg;
     CharDriverState *monitor_hd;
-    char monitor_device[128];
-    char serial_devices[MAX_SERIAL_PORTS][128];
+    const char *monitor_device;
+    const char *serial_devices[MAX_SERIAL_PORTS];
     int serial_device_index;
-    char parallel_devices[MAX_PARALLEL_PORTS][128];
+    const char *parallel_devices[MAX_PARALLEL_PORTS];
     int parallel_device_index;
     const char *loadvm = NULL;
     QEMUMachine *machine;
     const char *cpu_model;
-    char usb_devices[MAX_USB_CMDLINE][128];
+    const char *usb_devices[MAX_USB_CMDLINE];
     int usb_devices_index;
     int fds[2];
     const char *pid_file = NULL;
@@ -8073,20 +8275,21 @@ int main(int argc, char **argv)
 #endif
     snapshot = 0;
     nographic = 0;
+    curses = 0;
     kernel_filename = NULL;
     kernel_cmdline = "";
     cyls = heads = secs = 0;
     translation = BIOS_ATA_TRANSLATION_AUTO;
-    pstrcpy(monitor_device, sizeof(monitor_device), "vc");
+    monitor_device = "vc";
 
-    pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "vc");
+    serial_devices[0] = "vc";
     for(i = 1; i < MAX_SERIAL_PORTS; i++)
-        serial_devices[i][0] = '\0';
+        serial_devices[i] = NULL;
     serial_device_index = 0;
 
-    pstrcpy(parallel_devices[0], sizeof(parallel_devices[0]), "vc");
+    parallel_devices[0] = "vc";
     for(i = 1; i < MAX_PARALLEL_PORTS; i++)
-        parallel_devices[i][0] = '\0';
+        parallel_devices[i] = NULL;
     parallel_device_index = 0;
 
     usb_devices_index = 0;
@@ -8105,7 +8308,7 @@ int main(int argc, char **argv)
             break;
         r = argv[optind];
         if (r[0] != '-') {
-           hda_index = drive_add(HD_ALIAS, argv[optind++], 0);
+           hda_index = drive_add(argv[optind++], HD_ALIAS, 0);
         } else {
             const QEMUOption *popt;
 
@@ -8166,11 +8369,11 @@ int main(int argc, char **argv)
                 break;
             case QEMU_OPTION_hda:
                 if (cyls == 0)
-                    hda_index = drive_add(HD_ALIAS, optarg, 0);
+                    hda_index = drive_add(optarg, HD_ALIAS, 0);
                 else
-                    hda_index = drive_add(HD_ALIAS
+                    hda_index = drive_add(optarg, HD_ALIAS
                             ",cyls=%d,heads=%d,secs=%d%s",
-                             optarg, 0, cyls, heads, secs,
+                             0, cyls, heads, secs,
                              translation == BIOS_ATA_TRANSLATION_LBA ?
                                  ",trans=lba" :
                              translation == BIOS_ATA_TRANSLATION_NONE ?
@@ -8179,19 +8382,19 @@ int main(int argc, char **argv)
             case QEMU_OPTION_hdb:
             case QEMU_OPTION_hdc:
             case QEMU_OPTION_hdd:
-               drive_add(HD_ALIAS, optarg, popt->index - QEMU_OPTION_hda);
+                drive_add(optarg, HD_ALIAS, popt->index - QEMU_OPTION_hda);
                 break;
             case QEMU_OPTION_drive:
-                drive_add("%s", optarg);
+                drive_add(NULL, "%s", optarg);
                break;
             case QEMU_OPTION_mtdblock:
-               drive_add(MTD_ALIAS, optarg);
+                drive_add(optarg, MTD_ALIAS);
                 break;
             case QEMU_OPTION_sd:
-                drive_add("file=\"%s\"," SD_ALIAS, optarg);
+                drive_add(optarg, SD_ALIAS);
                 break;
             case QEMU_OPTION_pflash:
-               drive_add(PFLASH_ALIAS, optarg);
+                drive_add(optarg, PFLASH_ALIAS);
                 break;
             case QEMU_OPTION_snapshot:
                 snapshot = 1;
@@ -8231,12 +8434,10 @@ int main(int argc, char **argv)
                         exit(1);
                     }
                    if (hda_index != -1)
-                       snprintf(drives_opt[hda_index] +
-                                strlen(drives_opt[hda_index]),
-                                sizeof(drives_opt[0]) -
-                                strlen(drives_opt[hda_index]),
-                                ",cyls=%d,heads=%d,secs=%d%s",
-                                cyls, heads, secs,
+                        snprintf(drives_opt[hda_index].opt,
+                                 sizeof(drives_opt[hda_index].opt),
+                                 HD_ALIAS ",cyls=%d,heads=%d,secs=%d%s",
+                                 0, cyls, heads, secs,
                                 translation == BIOS_ATA_TRANSLATION_LBA ?
                                    ",trans=lba" :
                                 translation == BIOS_ATA_TRANSLATION_NONE ?
@@ -8244,11 +8445,16 @@ int main(int argc, char **argv)
                 }
                 break;
             case QEMU_OPTION_nographic:
-                pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio");
-                pstrcpy(parallel_devices[0], sizeof(parallel_devices[0]), "null");
-                pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
+                serial_devices[0] = "stdio";
+                parallel_devices[0] = "null";
+                monitor_device = "stdio";
                 nographic = 1;
                 break;
+#ifdef CONFIG_CURSES
+            case QEMU_OPTION_curses:
+                curses = 1;
+                break;
+#endif
             case QEMU_OPTION_portrait:
                 graphic_rotate = 1;
                 break;
@@ -8259,14 +8465,14 @@ int main(int argc, char **argv)
                 kernel_cmdline = optarg;
                 break;
             case QEMU_OPTION_cdrom:
-               drive_add("file=\"%s\"," CDROM_ALIAS, optarg);
+                drive_add(optarg, CDROM_ALIAS);
                 break;
             case QEMU_OPTION_boot:
                 boot_devices = optarg;
                 /* We just do some generic consistency checks */
                 {
                     /* Could easily be extended to 64 devices if needed */
-                    const unsigned char *p;
+                    const char *p;
                     
                     boot_devices_bitmap = 0;
                     for (p = boot_devices; *p != '\0'; p++) {
@@ -8294,8 +8500,7 @@ int main(int argc, char **argv)
                 break;
             case QEMU_OPTION_fda:
             case QEMU_OPTION_fdb:
-               drive_add("file=\"%s\"," FD_ALIAS, optarg,
-                         popt->index - QEMU_OPTION_fda);
+                drive_add(optarg, FD_ALIAS, popt->index - QEMU_OPTION_fda);
                 break;
 #ifdef TARGET_I386
             case QEMU_OPTION_no_fd_bootchk:
@@ -8310,9 +8515,7 @@ int main(int argc, char **argv)
                     fprintf(stderr, "qemu: too many network clients\n");
                     exit(1);
                 }
-                pstrcpy(net_clients[nb_net_clients],
-                        sizeof(net_clients[0]),
-                        optarg);
+                net_clients[nb_net_clients] = optarg;
                 nb_net_clients++;
                 break;
 #ifdef CONFIG_SLIRP
@@ -8447,15 +8650,14 @@ int main(int argc, char **argv)
                     break;
                 }
             case QEMU_OPTION_monitor:
-                pstrcpy(monitor_device, sizeof(monitor_device), optarg);
+                monitor_device = optarg;
                 break;
             case QEMU_OPTION_serial:
                 if (serial_device_index >= MAX_SERIAL_PORTS) {
                     fprintf(stderr, "qemu: too many serial ports\n");
                     exit(1);
                 }
-                pstrcpy(serial_devices[serial_device_index],
-                        sizeof(serial_devices[0]), optarg);
+                serial_devices[serial_device_index] = optarg;
                 serial_device_index++;
                 break;
             case QEMU_OPTION_parallel:
@@ -8463,8 +8665,7 @@ int main(int argc, char **argv)
                     fprintf(stderr, "qemu: too many parallel ports\n");
                     exit(1);
                 }
-                pstrcpy(parallel_devices[parallel_device_index],
-                        sizeof(parallel_devices[0]), optarg);
+                parallel_devices[parallel_device_index] = optarg;
                 parallel_device_index++;
                 break;
            case QEMU_OPTION_loadvm:
@@ -8509,9 +8710,7 @@ int main(int argc, char **argv)
                     fprintf(stderr, "Too many USB devices\n");
                     exit(1);
                 }
-                pstrcpy(usb_devices[usb_devices_index],
-                        sizeof(usb_devices[usb_devices_index]),
-                        optarg);
+                usb_devices[usb_devices_index] = optarg;
                 usb_devices_index++;
                 break;
             case QEMU_OPTION_smp:
@@ -8563,6 +8762,7 @@ int main(int argc, char **argv)
 #ifdef TARGET_ARM
             case QEMU_OPTION_old_param:
                 old_param = 1;
+                break;
 #endif
             case QEMU_OPTION_clock:
                 configure_alarms(optarg);
@@ -8570,8 +8770,9 @@ int main(int argc, char **argv)
             case QEMU_OPTION_startdate:
                 {
                     struct tm tm;
+                    time_t rtc_start_date;
                     if (!strcmp(optarg, "now")) {
-                        rtc_start_date = -1;
+                        rtc_date_offset = -1;
                     } else {
                         if (sscanf(optarg, "%d-%d-%dT%d:%d:%d",
                                &tm.tm_year,
@@ -8600,6 +8801,7 @@ int main(int argc, char **argv)
                                     "'now' or '2006-06-17T16:01:21' or '2006-06-17'\n");
                             exit(1);
                         }
+                        rtc_date_offset = time(NULL) - rtc_start_date;
                     }
                 }
                 break;
@@ -8696,10 +8898,8 @@ int main(int argc, char **argv)
     /* init network clients */
     if (nb_net_clients == 0) {
         /* if no clients, we use a default config */
-        pstrcpy(net_clients[0], sizeof(net_clients[0]),
-                "nic");
-        pstrcpy(net_clients[1], sizeof(net_clients[0]),
-                "user");
+        net_clients[0] = "nic";
+        net_clients[1] = "user";
         nb_net_clients = 2;
     }
 
@@ -8721,7 +8921,7 @@ int main(int argc, char **argv)
     }
 
 #ifdef TARGET_I386
-    /* XXX: this should be moved in the PC machine instanciation code */
+    /* XXX: this should be moved in the PC machine instantiation code */
     if (net_boot != 0) {
         int netroms = 0;
        for (i = 0; i < nb_nics && i < 4; i++) {
@@ -8763,22 +8963,22 @@ int main(int argc, char **argv)
     /* we always create the cdrom drive, even if no disk is there */
 
     if (nb_drives_opt < MAX_DRIVES)
-        drive_add(CDROM_ALIAS);
+        drive_add(NULL, CDROM_ALIAS);
 
     /* we always create at least one floppy */
 
     if (nb_drives_opt < MAX_DRIVES)
-        drive_add(FD_ALIAS, 0);
+        drive_add(NULL, FD_ALIAS, 0);
 
     /* we always create one sd slot, even if no card is in it */
 
     if (nb_drives_opt < MAX_DRIVES)
-        drive_add(SD_ALIAS);
+        drive_add(NULL, SD_ALIAS);
 
     /* open the virtual block devices */
 
     for(i = 0; i < nb_drives_opt; i++)
-        if (drive_init(drives_opt[i], snapshot, machine) == -1)
+        if (drive_init(&drives_opt[i], snapshot, machine) == -1)
            exit(1);
 
     register_savevm("timer", 0, 2, timer_save, timer_load, NULL);
@@ -8789,13 +8989,23 @@ int main(int argc, char **argv)
     /* terminal init */
     memset(&display_state, 0, sizeof(display_state));
     if (nographic) {
+        if (curses) {
+            fprintf(stderr, "fatal: -nographic can't be used with -curses\n");
+            exit(1);
+        }
         /* nearly nothing to do */
         dumb_display_init(ds);
     } else if (vnc_display != NULL) {
         vnc_display_init(ds);
         if (vnc_display_open(ds, vnc_display) < 0)
             exit(1);
-    } else {
+    } else
+#if defined(CONFIG_CURSES)
+    if (curses) {
+        curses_display_init(ds, full_screen);
+    } else
+#endif
+    {
 #if defined(CONFIG_SDL)
         sdl_display_init(ds, full_screen, no_frame);
 #elif defined(CONFIG_COCOA)
@@ -8808,17 +9018,18 @@ int main(int argc, char **argv)
     /* Maintain compatibility with multiple stdio monitors */
     if (!strcmp(monitor_device,"stdio")) {
         for (i = 0; i < MAX_SERIAL_PORTS; i++) {
-            if (!strcmp(serial_devices[i],"mon:stdio")) {
-                monitor_device[0] = '\0';
+            const char *devname = serial_devices[i];
+            if (devname && !strcmp(devname,"mon:stdio")) {
+                monitor_device = NULL;
                 break;
-            } else if (!strcmp(serial_devices[i],"stdio")) {
-                monitor_device[0] = '\0';
-                pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "mon:stdio");
+            } else if (devname && !strcmp(devname,"stdio")) {
+                monitor_device = NULL;
+                serial_devices[i] = "mon:stdio";
                 break;
             }
         }
     }
-    if (monitor_device[0] != '\0') {
+    if (monitor_device) {
         monitor_hd = qemu_chr_open(monitor_device);
         if (!monitor_hd) {
             fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device);
@@ -8829,7 +9040,7 @@ int main(int argc, char **argv)
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         const char *devname = serial_devices[i];
-        if (devname[0] != '\0' && strcmp(devname, "none")) {
+        if (devname && strcmp(devname, "none")) {
             serial_hds[i] = qemu_chr_open(devname);
             if (!serial_hds[i]) {
                 fprintf(stderr, "qemu: could not open serial device '%s'\n",
@@ -8843,7 +9054,7 @@ int main(int argc, char **argv)
 
     for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
         const char *devname = parallel_devices[i];
-        if (devname[0] != '\0' && strcmp(devname, "none")) {
+        if (devname && strcmp(devname, "none")) {
             parallel_hds[i] = qemu_chr_open(devname);
             if (!parallel_hds[i]) {
                 fprintf(stderr, "qemu: could not open parallel device '%s'\n",
@@ -8937,7 +9148,7 @@ int main(int argc, char **argv)
                     s->down_script[0])
                     launch_script(s->down_script, ifname, s->fd);
             }
-    }
+        }
     }
 #endif
     return 0;