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