Statistics
| Branch: | Revision:

root / vl.c @ 9e89a4be

History | View | Annotate | Download (87.4 kB)

1 0824d6fc bellard
/*
2 80cabfad bellard
 * QEMU System Emulator
3 0824d6fc bellard
 * 
4 80cabfad bellard
 * Copyright (c) 2003-2004 Fabrice Bellard
5 0824d6fc bellard
 * 
6 1df912cf bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 1df912cf bellard
 * of this software and associated documentation files (the "Software"), to deal
8 1df912cf bellard
 * in the Software without restriction, including without limitation the rights
9 1df912cf bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 1df912cf bellard
 * copies of the Software, and to permit persons to whom the Software is
11 1df912cf bellard
 * furnished to do so, subject to the following conditions:
12 1df912cf bellard
 *
13 1df912cf bellard
 * The above copyright notice and this permission notice shall be included in
14 1df912cf bellard
 * all copies or substantial portions of the Software.
15 1df912cf bellard
 *
16 1df912cf bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 1df912cf bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 1df912cf bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 1df912cf bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 1df912cf bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 1df912cf bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 1df912cf bellard
 * THE SOFTWARE.
23 0824d6fc bellard
 */
24 67b915a5 bellard
#include "vl.h"
25 67b915a5 bellard
26 0824d6fc bellard
#include <unistd.h>
27 0824d6fc bellard
#include <fcntl.h>
28 0824d6fc bellard
#include <signal.h>
29 0824d6fc bellard
#include <time.h>
30 0824d6fc bellard
#include <errno.h>
31 67b915a5 bellard
#include <sys/time.h>
32 67b915a5 bellard
33 67b915a5 bellard
#ifndef _WIN32
34 67b915a5 bellard
#include <sys/times.h>
35 f1510b2c bellard
#include <sys/wait.h>
36 67b915a5 bellard
#include <termios.h>
37 67b915a5 bellard
#include <sys/poll.h>
38 67b915a5 bellard
#include <sys/mman.h>
39 f1510b2c bellard
#include <sys/ioctl.h>
40 f1510b2c bellard
#include <sys/socket.h>
41 c94c8d64 bellard
#include <netinet/in.h>
42 9d728e8c bellard
#include <dirent.h>
43 7d3505c5 bellard
#ifdef _BSD
44 7d3505c5 bellard
#include <sys/stat.h>
45 83fb7adf bellard
#ifndef __APPLE__
46 7d3505c5 bellard
#include <libutil.h>
47 83fb7adf bellard
#endif
48 7d3505c5 bellard
#else
49 f1510b2c bellard
#include <linux/if.h>
50 f1510b2c bellard
#include <linux/if_tun.h>
51 7d3505c5 bellard
#include <pty.h>
52 7d3505c5 bellard
#include <malloc.h>
53 fd872598 bellard
#include <linux/rtc.h>
54 67b915a5 bellard
#endif
55 7d3505c5 bellard
#endif
56 67b915a5 bellard
57 c20709aa bellard
#if defined(CONFIG_SLIRP)
58 c20709aa bellard
#include "libslirp.h"
59 c20709aa bellard
#endif
60 c20709aa bellard
61 67b915a5 bellard
#ifdef _WIN32
62 7d3505c5 bellard
#include <malloc.h>
63 67b915a5 bellard
#include <sys/timeb.h>
64 67b915a5 bellard
#include <windows.h>
65 67b915a5 bellard
#define getopt_long_only getopt_long
66 67b915a5 bellard
#define memalign(align, size) malloc(size)
67 67b915a5 bellard
#endif
68 67b915a5 bellard
69 73332e5c bellard
#ifdef CONFIG_SDL
70 96bcd4f8 bellard
#ifdef __APPLE__
71 83fb7adf bellard
#include <SDL/SDL.h>
72 96bcd4f8 bellard
#endif
73 73332e5c bellard
#endif /* CONFIG_SDL */
74 0824d6fc bellard
75 0824d6fc bellard
#include "disas.h"
76 fc01f7e7 bellard
77 8a7ddc38 bellard
#include "exec-all.h"
78 0824d6fc bellard
79 a541f297 bellard
//#define DO_TB_FLUSH
80 a541f297 bellard
81 5a67135a bellard
#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
82 f1510b2c bellard
83 0824d6fc bellard
//#define DEBUG_UNUSED_IOPORT
84 fd872598 bellard
//#define DEBUG_IOPORT
85 330d0414 bellard
86 bb551faa bellard
#if !defined(CONFIG_SOFTMMU)
87 7916e224 bellard
#define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024)
88 bb551faa bellard
#else
89 bb551faa bellard
#define PHYS_RAM_MAX_SIZE (2047 * 1024 * 1024)
90 bb551faa bellard
#endif
91 7916e224 bellard
92 77d4bc34 bellard
#ifdef TARGET_PPC
93 77d4bc34 bellard
#define DEFAULT_RAM_SIZE 144
94 77d4bc34 bellard
#else
95 1bfe856e bellard
#define DEFAULT_RAM_SIZE 128
96 77d4bc34 bellard
#endif
97 8a7ddc38 bellard
/* in ms */
98 8a7ddc38 bellard
#define GUI_REFRESH_INTERVAL 30
99 313aa567 bellard
100 7dea1da4 bellard
/* XXX: use a two level table to limit memory usage */
101 7dea1da4 bellard
#define MAX_IOPORTS 65536
102 0824d6fc bellard
103 80cabfad bellard
const char *bios_dir = CONFIG_QEMU_SHAREDIR;
104 0824d6fc bellard
char phys_ram_file[1024];
105 c45886db bellard
CPUState *global_env;
106 c45886db bellard
CPUState *cpu_single_env;
107 c4b1fcc0 bellard
void *ioport_opaque[MAX_IOPORTS];
108 fc01f7e7 bellard
IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
109 fc01f7e7 bellard
IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
110 c45886db bellard
BlockDriverState *bs_table[MAX_DISKS], *fd_table[MAX_FD];
111 313aa567 bellard
int vga_ram_size;
112 0ced6589 bellard
int bios_size;
113 313aa567 bellard
static DisplayState display_state;
114 a20dd508 bellard
int nographic;
115 313aa567 bellard
int64_t ticks_per_sec;
116 36b486bb bellard
int boot_device = 'c';
117 0ced6589 bellard
int ram_size;
118 80cabfad bellard
static char network_script[1024];
119 80cabfad bellard
int pit_min_timer_count = 0;
120 c4b1fcc0 bellard
int nb_nics;
121 c4b1fcc0 bellard
NetDriverState nd_table[MAX_NICS];
122 8a7ddc38 bellard
QEMUTimer *gui_timer;
123 8a7ddc38 bellard
int vm_running;
124 aaaa7df6 bellard
int audio_enabled = 0;
125 fb065187 bellard
int sb16_enabled = 1;
126 fb065187 bellard
int adlib_enabled = 1;
127 fb065187 bellard
int gus_enabled = 1;
128 bb0c6722 bellard
int pci_enabled = 1;
129 77d4bc34 bellard
int prep_enabled = 0;
130 ee22c2f7 bellard
int rtc_utc = 1;
131 1bfe856e bellard
int cirrus_vga_enabled = 1;
132 1bfe856e bellard
int graphic_width = 800;
133 1bfe856e bellard
int graphic_height = 600;
134 e9b137c2 bellard
int graphic_depth = 15;
135 d63d307f bellard
int full_screen = 0;
136 82c643ff bellard
TextConsole *vga_console;
137 8d11df9e bellard
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
138 0824d6fc bellard
139 0824d6fc bellard
/***********************************************************/
140 26aa7d72 bellard
/* x86 ISA bus support */
141 26aa7d72 bellard
142 26aa7d72 bellard
target_phys_addr_t isa_mem_base = 0;
143 0824d6fc bellard
144 c4b1fcc0 bellard
uint32_t default_ioport_readb(void *opaque, uint32_t address)
145 0824d6fc bellard
{
146 0824d6fc bellard
#ifdef DEBUG_UNUSED_IOPORT
147 0824d6fc bellard
    fprintf(stderr, "inb: port=0x%04x\n", address);
148 0824d6fc bellard
#endif
149 fc01f7e7 bellard
    return 0xff;
150 0824d6fc bellard
}
151 0824d6fc bellard
152 c4b1fcc0 bellard
void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data)
153 0824d6fc bellard
{
154 0824d6fc bellard
#ifdef DEBUG_UNUSED_IOPORT
155 0824d6fc bellard
    fprintf(stderr, "outb: port=0x%04x data=0x%02x\n", address, data);
156 0824d6fc bellard
#endif
157 0824d6fc bellard
}
158 0824d6fc bellard
159 0824d6fc bellard
/* default is to make two byte accesses */
160 c4b1fcc0 bellard
uint32_t default_ioport_readw(void *opaque, uint32_t address)
161 0824d6fc bellard
{
162 0824d6fc bellard
    uint32_t data;
163 db45c29a bellard
    data = ioport_read_table[0][address](ioport_opaque[address], address);
164 db45c29a bellard
    address = (address + 1) & (MAX_IOPORTS - 1);
165 db45c29a bellard
    data |= ioport_read_table[0][address](ioport_opaque[address], address) << 8;
166 0824d6fc bellard
    return data;
167 0824d6fc bellard
}
168 0824d6fc bellard
169 c4b1fcc0 bellard
void default_ioport_writew(void *opaque, uint32_t address, uint32_t data)
170 0824d6fc bellard
{
171 db45c29a bellard
    ioport_write_table[0][address](ioport_opaque[address], address, data & 0xff);
172 db45c29a bellard
    address = (address + 1) & (MAX_IOPORTS - 1);
173 db45c29a bellard
    ioport_write_table[0][address](ioport_opaque[address], address, (data >> 8) & 0xff);
174 0824d6fc bellard
}
175 0824d6fc bellard
176 c4b1fcc0 bellard
uint32_t default_ioport_readl(void *opaque, uint32_t address)
177 0824d6fc bellard
{
178 fc01f7e7 bellard
#ifdef DEBUG_UNUSED_IOPORT
179 fc01f7e7 bellard
    fprintf(stderr, "inl: port=0x%04x\n", address);
180 fc01f7e7 bellard
#endif
181 fc01f7e7 bellard
    return 0xffffffff;
182 0824d6fc bellard
}
183 0824d6fc bellard
184 c4b1fcc0 bellard
void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
185 0824d6fc bellard
{
186 fc01f7e7 bellard
#ifdef DEBUG_UNUSED_IOPORT
187 fc01f7e7 bellard
    fprintf(stderr, "outl: port=0x%04x data=0x%02x\n", address, data);
188 fc01f7e7 bellard
#endif
189 0824d6fc bellard
}
190 0824d6fc bellard
191 fc01f7e7 bellard
void init_ioports(void)
192 0824d6fc bellard
{
193 0824d6fc bellard
    int i;
194 0824d6fc bellard
195 fc01f7e7 bellard
    for(i = 0; i < MAX_IOPORTS; i++) {
196 fc01f7e7 bellard
        ioport_read_table[0][i] = default_ioport_readb;
197 fc01f7e7 bellard
        ioport_write_table[0][i] = default_ioport_writeb;
198 fc01f7e7 bellard
        ioport_read_table[1][i] = default_ioport_readw;
199 fc01f7e7 bellard
        ioport_write_table[1][i] = default_ioport_writew;
200 fc01f7e7 bellard
        ioport_read_table[2][i] = default_ioport_readl;
201 fc01f7e7 bellard
        ioport_write_table[2][i] = default_ioport_writel;
202 fc01f7e7 bellard
    }
203 0824d6fc bellard
}
204 0824d6fc bellard
205 fc01f7e7 bellard
/* size is the word size in byte */
206 c4b1fcc0 bellard
int register_ioport_read(int start, int length, int size, 
207 c4b1fcc0 bellard
                         IOPortReadFunc *func, void *opaque)
208 f1510b2c bellard
{
209 fc01f7e7 bellard
    int i, bsize;
210 f1510b2c bellard
211 c4b1fcc0 bellard
    if (size == 1) {
212 fc01f7e7 bellard
        bsize = 0;
213 c4b1fcc0 bellard
    } else if (size == 2) {
214 fc01f7e7 bellard
        bsize = 1;
215 c4b1fcc0 bellard
    } else if (size == 4) {
216 fc01f7e7 bellard
        bsize = 2;
217 c4b1fcc0 bellard
    } else {
218 c4b1fcc0 bellard
        hw_error("register_ioport_read: invalid size");
219 fc01f7e7 bellard
        return -1;
220 c4b1fcc0 bellard
    }
221 c4b1fcc0 bellard
    for(i = start; i < start + length; i += size) {
222 fc01f7e7 bellard
        ioport_read_table[bsize][i] = func;
223 c4b1fcc0 bellard
        if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
224 c4b1fcc0 bellard
            hw_error("register_ioport_read: invalid opaque");
225 c4b1fcc0 bellard
        ioport_opaque[i] = opaque;
226 c4b1fcc0 bellard
    }
227 f1510b2c bellard
    return 0;
228 f1510b2c bellard
}
229 f1510b2c bellard
230 fc01f7e7 bellard
/* size is the word size in byte */
231 c4b1fcc0 bellard
int register_ioport_write(int start, int length, int size, 
232 c4b1fcc0 bellard
                          IOPortWriteFunc *func, void *opaque)
233 f1510b2c bellard
{
234 fc01f7e7 bellard
    int i, bsize;
235 f1510b2c bellard
236 c4b1fcc0 bellard
    if (size == 1) {
237 fc01f7e7 bellard
        bsize = 0;
238 c4b1fcc0 bellard
    } else if (size == 2) {
239 fc01f7e7 bellard
        bsize = 1;
240 c4b1fcc0 bellard
    } else if (size == 4) {
241 fc01f7e7 bellard
        bsize = 2;
242 c4b1fcc0 bellard
    } else {
243 c4b1fcc0 bellard
        hw_error("register_ioport_write: invalid size");
244 fc01f7e7 bellard
        return -1;
245 c4b1fcc0 bellard
    }
246 c4b1fcc0 bellard
    for(i = start; i < start + length; i += size) {
247 fc01f7e7 bellard
        ioport_write_table[bsize][i] = func;
248 c4b1fcc0 bellard
        if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
249 c4b1fcc0 bellard
            hw_error("register_ioport_read: invalid opaque");
250 c4b1fcc0 bellard
        ioport_opaque[i] = opaque;
251 c4b1fcc0 bellard
    }
252 f1510b2c bellard
    return 0;
253 f1510b2c bellard
}
254 f1510b2c bellard
255 69b91039 bellard
void isa_unassign_ioport(int start, int length)
256 69b91039 bellard
{
257 69b91039 bellard
    int i;
258 69b91039 bellard
259 69b91039 bellard
    for(i = start; i < start + length; i++) {
260 69b91039 bellard
        ioport_read_table[0][i] = default_ioport_readb;
261 69b91039 bellard
        ioport_read_table[1][i] = default_ioport_readw;
262 69b91039 bellard
        ioport_read_table[2][i] = default_ioport_readl;
263 69b91039 bellard
264 69b91039 bellard
        ioport_write_table[0][i] = default_ioport_writeb;
265 69b91039 bellard
        ioport_write_table[1][i] = default_ioport_writew;
266 69b91039 bellard
        ioport_write_table[2][i] = default_ioport_writel;
267 69b91039 bellard
    }
268 69b91039 bellard
}
269 69b91039 bellard
270 0824d6fc bellard
void pstrcpy(char *buf, int buf_size, const char *str)
271 0824d6fc bellard
{
272 0824d6fc bellard
    int c;
273 0824d6fc bellard
    char *q = buf;
274 0824d6fc bellard
275 0824d6fc bellard
    if (buf_size <= 0)
276 0824d6fc bellard
        return;
277 0824d6fc bellard
278 0824d6fc bellard
    for(;;) {
279 0824d6fc bellard
        c = *str++;
280 0824d6fc bellard
        if (c == 0 || q >= buf + buf_size - 1)
281 0824d6fc bellard
            break;
282 0824d6fc bellard
        *q++ = c;
283 0824d6fc bellard
    }
284 0824d6fc bellard
    *q = '\0';
285 0824d6fc bellard
}
286 0824d6fc bellard
287 0824d6fc bellard
/* strcat and truncate. */
288 0824d6fc bellard
char *pstrcat(char *buf, int buf_size, const char *s)
289 0824d6fc bellard
{
290 0824d6fc bellard
    int len;
291 0824d6fc bellard
    len = strlen(buf);
292 0824d6fc bellard
    if (len < buf_size) 
293 0824d6fc bellard
        pstrcpy(buf + len, buf_size - len, s);
294 0824d6fc bellard
    return buf;
295 0824d6fc bellard
}
296 0824d6fc bellard
297 82c643ff bellard
int strstart(const char *str, const char *val, const char **ptr)
298 82c643ff bellard
{
299 82c643ff bellard
    const char *p, *q;
300 82c643ff bellard
    p = str;
301 82c643ff bellard
    q = val;
302 82c643ff bellard
    while (*q != '\0') {
303 82c643ff bellard
        if (*p != *q)
304 82c643ff bellard
            return 0;
305 82c643ff bellard
        p++;
306 82c643ff bellard
        q++;
307 82c643ff bellard
    }
308 82c643ff bellard
    if (ptr)
309 82c643ff bellard
        *ptr = p;
310 82c643ff bellard
    return 1;
311 82c643ff bellard
}
312 82c643ff bellard
313 0824d6fc bellard
/* return the size or -1 if error */
314 7587cf44 bellard
int get_image_size(const char *filename)
315 7587cf44 bellard
{
316 7587cf44 bellard
    int fd, size;
317 7587cf44 bellard
    fd = open(filename, O_RDONLY | O_BINARY);
318 7587cf44 bellard
    if (fd < 0)
319 7587cf44 bellard
        return -1;
320 7587cf44 bellard
    size = lseek(fd, 0, SEEK_END);
321 7587cf44 bellard
    close(fd);
322 7587cf44 bellard
    return size;
323 7587cf44 bellard
}
324 7587cf44 bellard
325 7587cf44 bellard
/* return the size or -1 if error */
326 0824d6fc bellard
int load_image(const char *filename, uint8_t *addr)
327 0824d6fc bellard
{
328 0824d6fc bellard
    int fd, size;
329 40c3bac3 bellard
    fd = open(filename, O_RDONLY | O_BINARY);
330 0824d6fc bellard
    if (fd < 0)
331 0824d6fc bellard
        return -1;
332 0824d6fc bellard
    size = lseek(fd, 0, SEEK_END);
333 0824d6fc bellard
    lseek(fd, 0, SEEK_SET);
334 0824d6fc bellard
    if (read(fd, addr, size) != size) {
335 0824d6fc bellard
        close(fd);
336 0824d6fc bellard
        return -1;
337 0824d6fc bellard
    }
338 0824d6fc bellard
    close(fd);
339 0824d6fc bellard
    return size;
340 0824d6fc bellard
}
341 0824d6fc bellard
342 c45886db bellard
void cpu_outb(CPUState *env, int addr, int val)
343 0824d6fc bellard
{
344 fd872598 bellard
#ifdef DEBUG_IOPORT
345 fd872598 bellard
    if (loglevel & CPU_LOG_IOPORT)
346 fd872598 bellard
        fprintf(logfile, "outb: %04x %02x\n", addr, val);
347 fd872598 bellard
#endif    
348 c4b1fcc0 bellard
    ioport_write_table[0][addr](ioport_opaque[addr], addr, val);
349 0824d6fc bellard
}
350 0824d6fc bellard
351 c45886db bellard
void cpu_outw(CPUState *env, int addr, int val)
352 0824d6fc bellard
{
353 fd872598 bellard
#ifdef DEBUG_IOPORT
354 fd872598 bellard
    if (loglevel & CPU_LOG_IOPORT)
355 fd872598 bellard
        fprintf(logfile, "outw: %04x %04x\n", addr, val);
356 fd872598 bellard
#endif    
357 c4b1fcc0 bellard
    ioport_write_table[1][addr](ioport_opaque[addr], addr, val);
358 0824d6fc bellard
}
359 0824d6fc bellard
360 c45886db bellard
void cpu_outl(CPUState *env, int addr, int val)
361 0824d6fc bellard
{
362 fd872598 bellard
#ifdef DEBUG_IOPORT
363 fd872598 bellard
    if (loglevel & CPU_LOG_IOPORT)
364 fd872598 bellard
        fprintf(logfile, "outl: %04x %08x\n", addr, val);
365 fd872598 bellard
#endif
366 c4b1fcc0 bellard
    ioport_write_table[2][addr](ioport_opaque[addr], addr, val);
367 0824d6fc bellard
}
368 0824d6fc bellard
369 c45886db bellard
int cpu_inb(CPUState *env, int addr)
370 0824d6fc bellard
{
371 fd872598 bellard
    int val;
372 fd872598 bellard
    val = ioport_read_table[0][addr](ioport_opaque[addr], addr);
373 fd872598 bellard
#ifdef DEBUG_IOPORT
374 fd872598 bellard
    if (loglevel & CPU_LOG_IOPORT)
375 fd872598 bellard
        fprintf(logfile, "inb : %04x %02x\n", addr, val);
376 fd872598 bellard
#endif
377 fd872598 bellard
    return val;
378 0824d6fc bellard
}
379 0824d6fc bellard
380 c45886db bellard
int cpu_inw(CPUState *env, int addr)
381 0824d6fc bellard
{
382 fd872598 bellard
    int val;
383 fd872598 bellard
    val = ioport_read_table[1][addr](ioport_opaque[addr], addr);
384 fd872598 bellard
#ifdef DEBUG_IOPORT
385 fd872598 bellard
    if (loglevel & CPU_LOG_IOPORT)
386 fd872598 bellard
        fprintf(logfile, "inw : %04x %04x\n", addr, val);
387 fd872598 bellard
#endif
388 fd872598 bellard
    return val;
389 0824d6fc bellard
}
390 0824d6fc bellard
391 c45886db bellard
int cpu_inl(CPUState *env, int addr)
392 0824d6fc bellard
{
393 fd872598 bellard
    int val;
394 fd872598 bellard
    val = ioport_read_table[2][addr](ioport_opaque[addr], addr);
395 fd872598 bellard
#ifdef DEBUG_IOPORT
396 fd872598 bellard
    if (loglevel & CPU_LOG_IOPORT)
397 fd872598 bellard
        fprintf(logfile, "inl : %04x %08x\n", addr, val);
398 fd872598 bellard
#endif
399 fd872598 bellard
    return val;
400 0824d6fc bellard
}
401 0824d6fc bellard
402 0824d6fc bellard
/***********************************************************/
403 0824d6fc bellard
void hw_error(const char *fmt, ...)
404 0824d6fc bellard
{
405 0824d6fc bellard
    va_list ap;
406 0824d6fc bellard
407 0824d6fc bellard
    va_start(ap, fmt);
408 0824d6fc bellard
    fprintf(stderr, "qemu: hardware error: ");
409 0824d6fc bellard
    vfprintf(stderr, fmt, ap);
410 0824d6fc bellard
    fprintf(stderr, "\n");
411 0824d6fc bellard
#ifdef TARGET_I386
412 7fe48483 bellard
    cpu_dump_state(global_env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
413 c45886db bellard
#else
414 7fe48483 bellard
    cpu_dump_state(global_env, stderr, fprintf, 0);
415 0824d6fc bellard
#endif
416 0824d6fc bellard
    va_end(ap);
417 0824d6fc bellard
    abort();
418 0824d6fc bellard
}
419 0824d6fc bellard
420 8a7ddc38 bellard
/***********************************************************/
421 63066f4f bellard
/* keyboard/mouse */
422 63066f4f bellard
423 63066f4f bellard
static QEMUPutKBDEvent *qemu_put_kbd_event;
424 63066f4f bellard
static void *qemu_put_kbd_event_opaque;
425 63066f4f bellard
static QEMUPutMouseEvent *qemu_put_mouse_event;
426 63066f4f bellard
static void *qemu_put_mouse_event_opaque;
427 63066f4f bellard
428 63066f4f bellard
void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
429 63066f4f bellard
{
430 63066f4f bellard
    qemu_put_kbd_event_opaque = opaque;
431 63066f4f bellard
    qemu_put_kbd_event = func;
432 63066f4f bellard
}
433 63066f4f bellard
434 63066f4f bellard
void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque)
435 63066f4f bellard
{
436 63066f4f bellard
    qemu_put_mouse_event_opaque = opaque;
437 63066f4f bellard
    qemu_put_mouse_event = func;
438 63066f4f bellard
}
439 63066f4f bellard
440 63066f4f bellard
void kbd_put_keycode(int keycode)
441 63066f4f bellard
{
442 63066f4f bellard
    if (qemu_put_kbd_event) {
443 63066f4f bellard
        qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
444 63066f4f bellard
    }
445 63066f4f bellard
}
446 63066f4f bellard
447 63066f4f bellard
void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
448 63066f4f bellard
{
449 63066f4f bellard
    if (qemu_put_mouse_event) {
450 63066f4f bellard
        qemu_put_mouse_event(qemu_put_mouse_event_opaque, 
451 63066f4f bellard
                             dx, dy, dz, buttons_state);
452 63066f4f bellard
    }
453 63066f4f bellard
}
454 63066f4f bellard
455 63066f4f bellard
/***********************************************************/
456 8a7ddc38 bellard
/* timers */
457 8a7ddc38 bellard
458 34865134 bellard
#if defined(__powerpc__)
459 34865134 bellard
460 34865134 bellard
static inline uint32_t get_tbl(void) 
461 0824d6fc bellard
{
462 34865134 bellard
    uint32_t tbl;
463 34865134 bellard
    asm volatile("mftb %0" : "=r" (tbl));
464 34865134 bellard
    return tbl;
465 0824d6fc bellard
}
466 0824d6fc bellard
467 34865134 bellard
static inline uint32_t get_tbu(void) 
468 34865134 bellard
{
469 34865134 bellard
        uint32_t tbl;
470 34865134 bellard
        asm volatile("mftbu %0" : "=r" (tbl));
471 34865134 bellard
        return tbl;
472 34865134 bellard
}
473 34865134 bellard
474 34865134 bellard
int64_t cpu_get_real_ticks(void)
475 34865134 bellard
{
476 34865134 bellard
    uint32_t l, h, h1;
477 34865134 bellard
    /* NOTE: we test if wrapping has occurred */
478 34865134 bellard
    do {
479 34865134 bellard
        h = get_tbu();
480 34865134 bellard
        l = get_tbl();
481 34865134 bellard
        h1 = get_tbu();
482 34865134 bellard
    } while (h != h1);
483 34865134 bellard
    return ((int64_t)h << 32) | l;
484 34865134 bellard
}
485 34865134 bellard
486 34865134 bellard
#elif defined(__i386__)
487 34865134 bellard
488 34865134 bellard
int64_t cpu_get_real_ticks(void)
489 0824d6fc bellard
{
490 0824d6fc bellard
    int64_t val;
491 e463b581 bellard
    asm volatile ("rdtsc" : "=A" (val));
492 0824d6fc bellard
    return val;
493 0824d6fc bellard
}
494 0824d6fc bellard
495 1115dde7 bellard
#elif defined(__x86_64__)
496 1115dde7 bellard
497 1115dde7 bellard
int64_t cpu_get_real_ticks(void)
498 1115dde7 bellard
{
499 1115dde7 bellard
    uint32_t low,high;
500 1115dde7 bellard
    int64_t val;
501 1115dde7 bellard
    asm volatile("rdtsc" : "=a" (low), "=d" (high));
502 1115dde7 bellard
    val = high;
503 1115dde7 bellard
    val <<= 32;
504 1115dde7 bellard
    val |= low;
505 1115dde7 bellard
    return val;
506 1115dde7 bellard
}
507 1115dde7 bellard
508 34865134 bellard
#else
509 34865134 bellard
#error unsupported CPU
510 34865134 bellard
#endif
511 34865134 bellard
512 34865134 bellard
static int64_t cpu_ticks_offset;
513 8a7ddc38 bellard
static int cpu_ticks_enabled;
514 34865134 bellard
515 8a7ddc38 bellard
static inline int64_t cpu_get_ticks(void)
516 34865134 bellard
{
517 8a7ddc38 bellard
    if (!cpu_ticks_enabled) {
518 8a7ddc38 bellard
        return cpu_ticks_offset;
519 8a7ddc38 bellard
    } else {
520 8a7ddc38 bellard
        return cpu_get_real_ticks() + cpu_ticks_offset;
521 8a7ddc38 bellard
    }
522 34865134 bellard
}
523 34865134 bellard
524 34865134 bellard
/* enable cpu_get_ticks() */
525 34865134 bellard
void cpu_enable_ticks(void)
526 34865134 bellard
{
527 8a7ddc38 bellard
    if (!cpu_ticks_enabled) {
528 8a7ddc38 bellard
        cpu_ticks_offset -= cpu_get_real_ticks();
529 8a7ddc38 bellard
        cpu_ticks_enabled = 1;
530 8a7ddc38 bellard
    }
531 34865134 bellard
}
532 34865134 bellard
533 34865134 bellard
/* disable cpu_get_ticks() : the clock is stopped. You must not call
534 34865134 bellard
   cpu_get_ticks() after that.  */
535 34865134 bellard
void cpu_disable_ticks(void)
536 34865134 bellard
{
537 8a7ddc38 bellard
    if (cpu_ticks_enabled) {
538 8a7ddc38 bellard
        cpu_ticks_offset = cpu_get_ticks();
539 8a7ddc38 bellard
        cpu_ticks_enabled = 0;
540 8a7ddc38 bellard
    }
541 34865134 bellard
}
542 34865134 bellard
543 67b915a5 bellard
static int64_t get_clock(void)
544 34865134 bellard
{
545 67b915a5 bellard
#ifdef _WIN32
546 67b915a5 bellard
    struct _timeb tb;
547 67b915a5 bellard
    _ftime(&tb);
548 67b915a5 bellard
    return ((int64_t)tb.time * 1000 + (int64_t)tb.millitm) * 1000;
549 67b915a5 bellard
#else
550 34865134 bellard
    struct timeval tv;
551 34865134 bellard
    gettimeofday(&tv, NULL);
552 34865134 bellard
    return tv.tv_sec * 1000000LL + tv.tv_usec;
553 67b915a5 bellard
#endif
554 34865134 bellard
}
555 34865134 bellard
556 0824d6fc bellard
void cpu_calibrate_ticks(void)
557 0824d6fc bellard
{
558 0824d6fc bellard
    int64_t usec, ticks;
559 0824d6fc bellard
560 0824d6fc bellard
    usec = get_clock();
561 8a7ddc38 bellard
    ticks = cpu_get_real_ticks();
562 67b915a5 bellard
#ifdef _WIN32
563 67b915a5 bellard
    Sleep(50);
564 67b915a5 bellard
#else
565 0824d6fc bellard
    usleep(50 * 1000);
566 67b915a5 bellard
#endif
567 0824d6fc bellard
    usec = get_clock() - usec;
568 8a7ddc38 bellard
    ticks = cpu_get_real_ticks() - ticks;
569 0824d6fc bellard
    ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec;
570 0824d6fc bellard
}
571 0824d6fc bellard
572 87858c89 bellard
/* compute with 96 bit intermediate result: (a*b)/c */
573 80cabfad bellard
uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
574 87858c89 bellard
{
575 87858c89 bellard
    union {
576 87858c89 bellard
        uint64_t ll;
577 87858c89 bellard
        struct {
578 87858c89 bellard
#ifdef WORDS_BIGENDIAN
579 87858c89 bellard
            uint32_t high, low;
580 87858c89 bellard
#else
581 87858c89 bellard
            uint32_t low, high;
582 87858c89 bellard
#endif            
583 87858c89 bellard
        } l;
584 87858c89 bellard
    } u, res;
585 87858c89 bellard
    uint64_t rl, rh;
586 87858c89 bellard
587 87858c89 bellard
    u.ll = a;
588 87858c89 bellard
    rl = (uint64_t)u.l.low * (uint64_t)b;
589 87858c89 bellard
    rh = (uint64_t)u.l.high * (uint64_t)b;
590 87858c89 bellard
    rh += (rl >> 32);
591 87858c89 bellard
    res.l.high = rh / c;
592 87858c89 bellard
    res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
593 87858c89 bellard
    return res.ll;
594 87858c89 bellard
}
595 87858c89 bellard
596 8a7ddc38 bellard
#define QEMU_TIMER_REALTIME 0
597 8a7ddc38 bellard
#define QEMU_TIMER_VIRTUAL  1
598 8a7ddc38 bellard
599 8a7ddc38 bellard
struct QEMUClock {
600 8a7ddc38 bellard
    int type;
601 8a7ddc38 bellard
    /* XXX: add frequency */
602 8a7ddc38 bellard
};
603 8a7ddc38 bellard
604 8a7ddc38 bellard
struct QEMUTimer {
605 8a7ddc38 bellard
    QEMUClock *clock;
606 8a7ddc38 bellard
    int64_t expire_time;
607 8a7ddc38 bellard
    QEMUTimerCB *cb;
608 8a7ddc38 bellard
    void *opaque;
609 8a7ddc38 bellard
    struct QEMUTimer *next;
610 8a7ddc38 bellard
};
611 8a7ddc38 bellard
612 8a7ddc38 bellard
QEMUClock *rt_clock;
613 8a7ddc38 bellard
QEMUClock *vm_clock;
614 8a7ddc38 bellard
615 8a7ddc38 bellard
static QEMUTimer *active_timers[2];
616 40c3bac3 bellard
#ifdef _WIN32
617 40c3bac3 bellard
static MMRESULT timerID;
618 40c3bac3 bellard
#else
619 8a7ddc38 bellard
/* frequency of the times() clock tick */
620 8a7ddc38 bellard
static int timer_freq;
621 67b915a5 bellard
#endif
622 8a7ddc38 bellard
623 8a7ddc38 bellard
QEMUClock *qemu_new_clock(int type)
624 8a7ddc38 bellard
{
625 8a7ddc38 bellard
    QEMUClock *clock;
626 8a7ddc38 bellard
    clock = qemu_mallocz(sizeof(QEMUClock));
627 8a7ddc38 bellard
    if (!clock)
628 8a7ddc38 bellard
        return NULL;
629 8a7ddc38 bellard
    clock->type = type;
630 8a7ddc38 bellard
    return clock;
631 8a7ddc38 bellard
}
632 8a7ddc38 bellard
633 8a7ddc38 bellard
QEMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque)
634 8a7ddc38 bellard
{
635 8a7ddc38 bellard
    QEMUTimer *ts;
636 8a7ddc38 bellard
637 8a7ddc38 bellard
    ts = qemu_mallocz(sizeof(QEMUTimer));
638 8a7ddc38 bellard
    ts->clock = clock;
639 8a7ddc38 bellard
    ts->cb = cb;
640 8a7ddc38 bellard
    ts->opaque = opaque;
641 8a7ddc38 bellard
    return ts;
642 8a7ddc38 bellard
}
643 8a7ddc38 bellard
644 8a7ddc38 bellard
void qemu_free_timer(QEMUTimer *ts)
645 8a7ddc38 bellard
{
646 8a7ddc38 bellard
    qemu_free(ts);
647 8a7ddc38 bellard
}
648 8a7ddc38 bellard
649 8a7ddc38 bellard
/* stop a timer, but do not dealloc it */
650 8a7ddc38 bellard
void qemu_del_timer(QEMUTimer *ts)
651 8a7ddc38 bellard
{
652 8a7ddc38 bellard
    QEMUTimer **pt, *t;
653 8a7ddc38 bellard
654 8a7ddc38 bellard
    /* NOTE: this code must be signal safe because
655 8a7ddc38 bellard
       qemu_timer_expired() can be called from a signal. */
656 8a7ddc38 bellard
    pt = &active_timers[ts->clock->type];
657 8a7ddc38 bellard
    for(;;) {
658 8a7ddc38 bellard
        t = *pt;
659 8a7ddc38 bellard
        if (!t)
660 8a7ddc38 bellard
            break;
661 8a7ddc38 bellard
        if (t == ts) {
662 8a7ddc38 bellard
            *pt = t->next;
663 8a7ddc38 bellard
            break;
664 8a7ddc38 bellard
        }
665 8a7ddc38 bellard
        pt = &t->next;
666 8a7ddc38 bellard
    }
667 8a7ddc38 bellard
}
668 8a7ddc38 bellard
669 8a7ddc38 bellard
/* modify the current timer so that it will be fired when current_time
670 8a7ddc38 bellard
   >= expire_time. The corresponding callback will be called. */
671 8a7ddc38 bellard
void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
672 8a7ddc38 bellard
{
673 8a7ddc38 bellard
    QEMUTimer **pt, *t;
674 8a7ddc38 bellard
675 8a7ddc38 bellard
    qemu_del_timer(ts);
676 8a7ddc38 bellard
677 8a7ddc38 bellard
    /* add the timer in the sorted list */
678 8a7ddc38 bellard
    /* NOTE: this code must be signal safe because
679 8a7ddc38 bellard
       qemu_timer_expired() can be called from a signal. */
680 8a7ddc38 bellard
    pt = &active_timers[ts->clock->type];
681 8a7ddc38 bellard
    for(;;) {
682 8a7ddc38 bellard
        t = *pt;
683 8a7ddc38 bellard
        if (!t)
684 8a7ddc38 bellard
            break;
685 8a7ddc38 bellard
        if (t->expire_time > expire_time) 
686 8a7ddc38 bellard
            break;
687 8a7ddc38 bellard
        pt = &t->next;
688 8a7ddc38 bellard
    }
689 8a7ddc38 bellard
    ts->expire_time = expire_time;
690 8a7ddc38 bellard
    ts->next = *pt;
691 8a7ddc38 bellard
    *pt = ts;
692 8a7ddc38 bellard
}
693 8a7ddc38 bellard
694 8a7ddc38 bellard
int qemu_timer_pending(QEMUTimer *ts)
695 8a7ddc38 bellard
{
696 8a7ddc38 bellard
    QEMUTimer *t;
697 8a7ddc38 bellard
    for(t = active_timers[ts->clock->type]; t != NULL; t = t->next) {
698 8a7ddc38 bellard
        if (t == ts)
699 8a7ddc38 bellard
            return 1;
700 8a7ddc38 bellard
    }
701 8a7ddc38 bellard
    return 0;
702 8a7ddc38 bellard
}
703 8a7ddc38 bellard
704 8a7ddc38 bellard
static inline int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
705 8a7ddc38 bellard
{
706 8a7ddc38 bellard
    if (!timer_head)
707 8a7ddc38 bellard
        return 0;
708 8a7ddc38 bellard
    return (timer_head->expire_time <= current_time);
709 8a7ddc38 bellard
}
710 8a7ddc38 bellard
711 8a7ddc38 bellard
static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time)
712 8a7ddc38 bellard
{
713 8a7ddc38 bellard
    QEMUTimer *ts;
714 8a7ddc38 bellard
    
715 8a7ddc38 bellard
    for(;;) {
716 8a7ddc38 bellard
        ts = *ptimer_head;
717 e95c8d51 bellard
        if (!ts || ts->expire_time > current_time)
718 8a7ddc38 bellard
            break;
719 8a7ddc38 bellard
        /* remove timer from the list before calling the callback */
720 8a7ddc38 bellard
        *ptimer_head = ts->next;
721 8a7ddc38 bellard
        ts->next = NULL;
722 8a7ddc38 bellard
        
723 8a7ddc38 bellard
        /* run the callback (the timer list can be modified) */
724 8a7ddc38 bellard
        ts->cb(ts->opaque);
725 8a7ddc38 bellard
    }
726 8a7ddc38 bellard
}
727 8a7ddc38 bellard
728 8a7ddc38 bellard
int64_t qemu_get_clock(QEMUClock *clock)
729 8a7ddc38 bellard
{
730 8a7ddc38 bellard
    switch(clock->type) {
731 8a7ddc38 bellard
    case QEMU_TIMER_REALTIME:
732 67b915a5 bellard
#ifdef _WIN32
733 67b915a5 bellard
        return GetTickCount();
734 67b915a5 bellard
#else
735 7d3505c5 bellard
        {
736 7d3505c5 bellard
            struct tms tp;
737 7d3505c5 bellard
738 7d3505c5 bellard
            /* Note that using gettimeofday() is not a good solution
739 7d3505c5 bellard
               for timers because its value change when the date is
740 7d3505c5 bellard
               modified. */
741 7d3505c5 bellard
            if (timer_freq == 100) {
742 7d3505c5 bellard
                return times(&tp) * 10;
743 7d3505c5 bellard
            } else {
744 7d3505c5 bellard
                return ((int64_t)times(&tp) * 1000) / timer_freq;
745 7d3505c5 bellard
            }
746 8a7ddc38 bellard
        }
747 67b915a5 bellard
#endif
748 8a7ddc38 bellard
    default:
749 8a7ddc38 bellard
    case QEMU_TIMER_VIRTUAL:
750 8a7ddc38 bellard
        return cpu_get_ticks();
751 8a7ddc38 bellard
    }
752 8a7ddc38 bellard
}
753 8a7ddc38 bellard
754 8a7ddc38 bellard
/* save a timer */
755 8a7ddc38 bellard
void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
756 8a7ddc38 bellard
{
757 8a7ddc38 bellard
    uint64_t expire_time;
758 8a7ddc38 bellard
759 8a7ddc38 bellard
    if (qemu_timer_pending(ts)) {
760 8a7ddc38 bellard
        expire_time = ts->expire_time;
761 8a7ddc38 bellard
    } else {
762 8a7ddc38 bellard
        expire_time = -1;
763 8a7ddc38 bellard
    }
764 8a7ddc38 bellard
    qemu_put_be64(f, expire_time);
765 8a7ddc38 bellard
}
766 8a7ddc38 bellard
767 8a7ddc38 bellard
void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
768 8a7ddc38 bellard
{
769 8a7ddc38 bellard
    uint64_t expire_time;
770 8a7ddc38 bellard
771 8a7ddc38 bellard
    expire_time = qemu_get_be64(f);
772 8a7ddc38 bellard
    if (expire_time != -1) {
773 8a7ddc38 bellard
        qemu_mod_timer(ts, expire_time);
774 8a7ddc38 bellard
    } else {
775 8a7ddc38 bellard
        qemu_del_timer(ts);
776 8a7ddc38 bellard
    }
777 8a7ddc38 bellard
}
778 8a7ddc38 bellard
779 8a7ddc38 bellard
static void timer_save(QEMUFile *f, void *opaque)
780 8a7ddc38 bellard
{
781 8a7ddc38 bellard
    if (cpu_ticks_enabled) {
782 8a7ddc38 bellard
        hw_error("cannot save state if virtual timers are running");
783 8a7ddc38 bellard
    }
784 8a7ddc38 bellard
    qemu_put_be64s(f, &cpu_ticks_offset);
785 8a7ddc38 bellard
    qemu_put_be64s(f, &ticks_per_sec);
786 8a7ddc38 bellard
}
787 8a7ddc38 bellard
788 8a7ddc38 bellard
static int timer_load(QEMUFile *f, void *opaque, int version_id)
789 8a7ddc38 bellard
{
790 8a7ddc38 bellard
    if (version_id != 1)
791 8a7ddc38 bellard
        return -EINVAL;
792 8a7ddc38 bellard
    if (cpu_ticks_enabled) {
793 8a7ddc38 bellard
        return -EINVAL;
794 8a7ddc38 bellard
    }
795 8a7ddc38 bellard
    qemu_get_be64s(f, &cpu_ticks_offset);
796 8a7ddc38 bellard
    qemu_get_be64s(f, &ticks_per_sec);
797 8a7ddc38 bellard
    return 0;
798 8a7ddc38 bellard
}
799 8a7ddc38 bellard
800 67b915a5 bellard
#ifdef _WIN32
801 67b915a5 bellard
void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg, 
802 67b915a5 bellard
                                 DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
803 67b915a5 bellard
#else
804 8a7ddc38 bellard
static void host_alarm_handler(int host_signum)
805 67b915a5 bellard
#endif
806 8a7ddc38 bellard
{
807 02ba45c5 bellard
#if 0
808 02ba45c5 bellard
#define DISP_FREQ 1000
809 02ba45c5 bellard
    {
810 02ba45c5 bellard
        static int64_t delta_min = INT64_MAX;
811 02ba45c5 bellard
        static int64_t delta_max, delta_cum, last_clock, delta, ti;
812 02ba45c5 bellard
        static int count;
813 02ba45c5 bellard
        ti = qemu_get_clock(vm_clock);
814 02ba45c5 bellard
        if (last_clock != 0) {
815 02ba45c5 bellard
            delta = ti - last_clock;
816 02ba45c5 bellard
            if (delta < delta_min)
817 02ba45c5 bellard
                delta_min = delta;
818 02ba45c5 bellard
            if (delta > delta_max)
819 02ba45c5 bellard
                delta_max = delta;
820 02ba45c5 bellard
            delta_cum += delta;
821 02ba45c5 bellard
            if (++count == DISP_FREQ) {
822 02ba45c5 bellard
                printf("timer: min=%lld us max=%lld us avg=%lld us avg_freq=%0.3f Hz\n",
823 02ba45c5 bellard
                       muldiv64(delta_min, 1000000, ticks_per_sec),
824 02ba45c5 bellard
                       muldiv64(delta_max, 1000000, ticks_per_sec),
825 02ba45c5 bellard
                       muldiv64(delta_cum, 1000000 / DISP_FREQ, ticks_per_sec),
826 02ba45c5 bellard
                       (double)ticks_per_sec / ((double)delta_cum / DISP_FREQ));
827 02ba45c5 bellard
                count = 0;
828 02ba45c5 bellard
                delta_min = INT64_MAX;
829 02ba45c5 bellard
                delta_max = 0;
830 02ba45c5 bellard
                delta_cum = 0;
831 02ba45c5 bellard
            }
832 02ba45c5 bellard
        }
833 02ba45c5 bellard
        last_clock = ti;
834 02ba45c5 bellard
    }
835 02ba45c5 bellard
#endif
836 8a7ddc38 bellard
    if (qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL],
837 8a7ddc38 bellard
                           qemu_get_clock(vm_clock)) ||
838 8a7ddc38 bellard
        qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME],
839 8a7ddc38 bellard
                           qemu_get_clock(rt_clock))) {
840 8a7ddc38 bellard
        /* stop the cpu because a timer occured */
841 8a7ddc38 bellard
        cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
842 8a7ddc38 bellard
    }
843 8a7ddc38 bellard
}
844 8a7ddc38 bellard
845 fd872598 bellard
#ifndef _WIN32
846 fd872598 bellard
847 829309c7 bellard
#if defined(__linux__)
848 829309c7 bellard
849 fd872598 bellard
#define RTC_FREQ 1024
850 fd872598 bellard
851 fd872598 bellard
static int rtc_fd;
852 829309c7 bellard
853 fd872598 bellard
static int start_rtc_timer(void)
854 fd872598 bellard
{
855 fd872598 bellard
    rtc_fd = open("/dev/rtc", O_RDONLY);
856 fd872598 bellard
    if (rtc_fd < 0)
857 fd872598 bellard
        return -1;
858 fd872598 bellard
    if (ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) {
859 fd872598 bellard
        fprintf(stderr, "Could not configure '/dev/rtc' to have a 1024 Hz timer. This is not a fatal\n"
860 fd872598 bellard
                "error, but for better emulation accuracy either use a 2.6 host Linux kernel or\n"
861 fd872598 bellard
                "type 'echo 1024 > /proc/sys/dev/rtc/max-user-freq' as root.\n");
862 fd872598 bellard
        goto fail;
863 fd872598 bellard
    }
864 fd872598 bellard
    if (ioctl(rtc_fd, RTC_PIE_ON, 0) < 0) {
865 fd872598 bellard
    fail:
866 fd872598 bellard
        close(rtc_fd);
867 fd872598 bellard
        return -1;
868 fd872598 bellard
    }
869 fd872598 bellard
    pit_min_timer_count = PIT_FREQ / RTC_FREQ;
870 fd872598 bellard
    return 0;
871 fd872598 bellard
}
872 fd872598 bellard
873 829309c7 bellard
#else
874 829309c7 bellard
875 829309c7 bellard
static int start_rtc_timer(void)
876 829309c7 bellard
{
877 829309c7 bellard
    return -1;
878 829309c7 bellard
}
879 829309c7 bellard
880 829309c7 bellard
#endif /* !defined(__linux__) */
881 829309c7 bellard
882 829309c7 bellard
#endif /* !defined(_WIN32) */
883 fd872598 bellard
884 8a7ddc38 bellard
static void init_timers(void)
885 8a7ddc38 bellard
{
886 8a7ddc38 bellard
    rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME);
887 8a7ddc38 bellard
    vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL);
888 8a7ddc38 bellard
889 67b915a5 bellard
#ifdef _WIN32
890 67b915a5 bellard
    {
891 67b915a5 bellard
        int count=0;
892 40c3bac3 bellard
        timerID = timeSetEvent(10,    // interval (ms)
893 40c3bac3 bellard
                               0,     // resolution
894 40c3bac3 bellard
                               host_alarm_handler, // function
895 40c3bac3 bellard
                               (DWORD)&count,  // user parameter
896 40c3bac3 bellard
                               TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
897 67b915a5 bellard
         if( !timerID ) {
898 67b915a5 bellard
            perror("failed timer alarm");
899 67b915a5 bellard
            exit(1);
900 67b915a5 bellard
         }
901 67b915a5 bellard
    }
902 67b915a5 bellard
    pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000;
903 67b915a5 bellard
#else
904 67b915a5 bellard
    {
905 67b915a5 bellard
        struct sigaction act;
906 67b915a5 bellard
        struct itimerval itv;
907 67b915a5 bellard
        
908 67b915a5 bellard
        /* get times() syscall frequency */
909 67b915a5 bellard
        timer_freq = sysconf(_SC_CLK_TCK);
910 67b915a5 bellard
        
911 67b915a5 bellard
        /* timer signal */
912 67b915a5 bellard
        sigfillset(&act.sa_mask);
913 67b915a5 bellard
        act.sa_flags = 0;
914 8a7ddc38 bellard
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
915 67b915a5 bellard
        act.sa_flags |= SA_ONSTACK;
916 67b915a5 bellard
#endif
917 67b915a5 bellard
        act.sa_handler = host_alarm_handler;
918 67b915a5 bellard
        sigaction(SIGALRM, &act, NULL);
919 fd872598 bellard
920 67b915a5 bellard
        itv.it_interval.tv_sec = 0;
921 67b915a5 bellard
        itv.it_interval.tv_usec = 1000;
922 67b915a5 bellard
        itv.it_value.tv_sec = 0;
923 67b915a5 bellard
        itv.it_value.tv_usec = 10 * 1000;
924 67b915a5 bellard
        setitimer(ITIMER_REAL, &itv, NULL);
925 67b915a5 bellard
        /* we probe the tick duration of the kernel to inform the user if
926 67b915a5 bellard
           the emulated kernel requested a too high timer frequency */
927 67b915a5 bellard
        getitimer(ITIMER_REAL, &itv);
928 fd872598 bellard
929 83fb7adf bellard
#if defined(__linux__)
930 fd872598 bellard
        if (itv.it_interval.tv_usec > 1000) {
931 fd872598 bellard
            /* try to use /dev/rtc to have a faster timer */
932 fd872598 bellard
            if (start_rtc_timer() < 0)
933 fd872598 bellard
                goto use_itimer;
934 fd872598 bellard
            /* disable itimer */
935 fd872598 bellard
            itv.it_interval.tv_sec = 0;
936 fd872598 bellard
            itv.it_interval.tv_usec = 0;
937 fd872598 bellard
            itv.it_value.tv_sec = 0;
938 fd872598 bellard
            itv.it_value.tv_usec = 0;
939 fd872598 bellard
            setitimer(ITIMER_REAL, &itv, NULL);
940 fd872598 bellard
941 fd872598 bellard
            /* use the RTC */
942 a1968d71 bellard
            sigaction(SIGIO, &act, NULL);
943 fd872598 bellard
            fcntl(rtc_fd, F_SETFL, O_ASYNC);
944 fd872598 bellard
            fcntl(rtc_fd, F_SETOWN, getpid());
945 83fb7adf bellard
        } else 
946 83fb7adf bellard
#endif /* defined(__linux__) */
947 83fb7adf bellard
        {
948 fd872598 bellard
        use_itimer:
949 fd872598 bellard
            pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * 
950 fd872598 bellard
                                   PIT_FREQ) / 1000000;
951 fd872598 bellard
        }
952 67b915a5 bellard
    }
953 8a7ddc38 bellard
#endif
954 8a7ddc38 bellard
}
955 8a7ddc38 bellard
956 40c3bac3 bellard
void quit_timers(void)
957 40c3bac3 bellard
{
958 40c3bac3 bellard
#ifdef _WIN32
959 40c3bac3 bellard
    timeKillEvent(timerID);
960 40c3bac3 bellard
#endif
961 40c3bac3 bellard
}
962 40c3bac3 bellard
963 c4b1fcc0 bellard
/***********************************************************/
964 82c643ff bellard
/* character device */
965 313aa567 bellard
966 82c643ff bellard
int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
967 82c643ff bellard
{
968 82c643ff bellard
    return s->chr_write(s, buf, len);
969 82c643ff bellard
}
970 67b915a5 bellard
971 82c643ff bellard
void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
972 67b915a5 bellard
{
973 82c643ff bellard
    char buf[4096];
974 82c643ff bellard
    va_list ap;
975 82c643ff bellard
    va_start(ap, fmt);
976 82c643ff bellard
    vsnprintf(buf, sizeof(buf), fmt, ap);
977 82c643ff bellard
    qemu_chr_write(s, buf, strlen(buf));
978 82c643ff bellard
    va_end(ap);
979 67b915a5 bellard
}
980 67b915a5 bellard
981 5905b2e5 bellard
void qemu_chr_send_event(CharDriverState *s, int event)
982 5905b2e5 bellard
{
983 5905b2e5 bellard
    if (s->chr_send_event)
984 5905b2e5 bellard
        s->chr_send_event(s, event);
985 5905b2e5 bellard
}
986 5905b2e5 bellard
987 82c643ff bellard
void qemu_chr_add_read_handler(CharDriverState *s, 
988 82c643ff bellard
                               IOCanRWHandler *fd_can_read, 
989 82c643ff bellard
                               IOReadHandler *fd_read, void *opaque)
990 82c643ff bellard
{
991 82c643ff bellard
    s->chr_add_read_handler(s, fd_can_read, fd_read, opaque);
992 82c643ff bellard
}
993 82c643ff bellard
             
994 82c643ff bellard
void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event)
995 82c643ff bellard
{
996 82c643ff bellard
    s->chr_event = chr_event;
997 82c643ff bellard
}
998 67b915a5 bellard
999 82c643ff bellard
static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
1000 313aa567 bellard
{
1001 82c643ff bellard
    return len;
1002 82c643ff bellard
}
1003 82c643ff bellard
1004 82c643ff bellard
static void null_chr_add_read_handler(CharDriverState *chr, 
1005 82c643ff bellard
                                    IOCanRWHandler *fd_can_read, 
1006 82c643ff bellard
                                    IOReadHandler *fd_read, void *opaque)
1007 82c643ff bellard
{
1008 82c643ff bellard
}
1009 82c643ff bellard
1010 82c643ff bellard
CharDriverState *qemu_chr_open_null(void)
1011 82c643ff bellard
{
1012 82c643ff bellard
    CharDriverState *chr;
1013 82c643ff bellard
1014 82c643ff bellard
    chr = qemu_mallocz(sizeof(CharDriverState));
1015 82c643ff bellard
    if (!chr)
1016 82c643ff bellard
        return NULL;
1017 82c643ff bellard
    chr->chr_write = null_chr_write;
1018 82c643ff bellard
    chr->chr_add_read_handler = null_chr_add_read_handler;
1019 82c643ff bellard
    return chr;
1020 82c643ff bellard
}
1021 82c643ff bellard
1022 82c643ff bellard
#ifndef _WIN32
1023 82c643ff bellard
1024 82c643ff bellard
typedef struct {
1025 82c643ff bellard
    int fd_in, fd_out;
1026 82c643ff bellard
    /* for nographic stdio only */
1027 82c643ff bellard
    IOCanRWHandler *fd_can_read; 
1028 82c643ff bellard
    IOReadHandler *fd_read;
1029 82c643ff bellard
    void *fd_opaque;
1030 82c643ff bellard
} FDCharDriver;
1031 82c643ff bellard
1032 82c643ff bellard
#define STDIO_MAX_CLIENTS 2
1033 82c643ff bellard
1034 82c643ff bellard
static int stdio_nb_clients;
1035 82c643ff bellard
static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];
1036 82c643ff bellard
1037 1d96905d bellard
static int unix_write(int fd, const uint8_t *buf, int len1)
1038 1d96905d bellard
{
1039 1d96905d bellard
    int ret, len;
1040 1d96905d bellard
1041 1d96905d bellard
    len = len1;
1042 1d96905d bellard
    while (len > 0) {
1043 1d96905d bellard
        ret = write(fd, buf, len);
1044 1d96905d bellard
        if (ret < 0) {
1045 1d96905d bellard
            if (errno != EINTR && errno != EAGAIN)
1046 1d96905d bellard
                return -1;
1047 1d96905d bellard
        } else if (ret == 0) {
1048 1d96905d bellard
            break;
1049 1d96905d bellard
        } else {
1050 1d96905d bellard
            buf += ret;
1051 1d96905d bellard
            len -= ret;
1052 1d96905d bellard
        }
1053 1d96905d bellard
    }
1054 1d96905d bellard
    return len1 - len;
1055 1d96905d bellard
}
1056 1d96905d bellard
1057 82c643ff bellard
static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
1058 82c643ff bellard
{
1059 82c643ff bellard
    FDCharDriver *s = chr->opaque;
1060 1d96905d bellard
    return unix_write(s->fd_out, buf, len);
1061 82c643ff bellard
}
1062 82c643ff bellard
1063 82c643ff bellard
static void fd_chr_add_read_handler(CharDriverState *chr, 
1064 82c643ff bellard
                                    IOCanRWHandler *fd_can_read, 
1065 82c643ff bellard
                                    IOReadHandler *fd_read, void *opaque)
1066 82c643ff bellard
{
1067 82c643ff bellard
    FDCharDriver *s = chr->opaque;
1068 82c643ff bellard
1069 82c643ff bellard
    if (nographic && s->fd_in == 0) {
1070 82c643ff bellard
        s->fd_can_read = fd_can_read;
1071 82c643ff bellard
        s->fd_read = fd_read;
1072 82c643ff bellard
        s->fd_opaque = opaque;
1073 80cabfad bellard
    } else {
1074 82c643ff bellard
        qemu_add_fd_read_handler(s->fd_in, fd_can_read, fd_read, opaque);
1075 82c643ff bellard
    }
1076 82c643ff bellard
}
1077 82c643ff bellard
1078 82c643ff bellard
/* open a character device to a unix fd */
1079 82c643ff bellard
CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
1080 82c643ff bellard
{
1081 82c643ff bellard
    CharDriverState *chr;
1082 82c643ff bellard
    FDCharDriver *s;
1083 82c643ff bellard
1084 82c643ff bellard
    chr = qemu_mallocz(sizeof(CharDriverState));
1085 82c643ff bellard
    if (!chr)
1086 82c643ff bellard
        return NULL;
1087 82c643ff bellard
    s = qemu_mallocz(sizeof(FDCharDriver));
1088 82c643ff bellard
    if (!s) {
1089 82c643ff bellard
        free(chr);
1090 82c643ff bellard
        return NULL;
1091 82c643ff bellard
    }
1092 82c643ff bellard
    s->fd_in = fd_in;
1093 82c643ff bellard
    s->fd_out = fd_out;
1094 82c643ff bellard
    chr->opaque = s;
1095 82c643ff bellard
    chr->chr_write = fd_chr_write;
1096 82c643ff bellard
    chr->chr_add_read_handler = fd_chr_add_read_handler;
1097 82c643ff bellard
    return chr;
1098 82c643ff bellard
}
1099 82c643ff bellard
1100 82c643ff bellard
/* for STDIO, we handle the case where several clients use it
1101 82c643ff bellard
   (nographic mode) */
1102 82c643ff bellard
1103 82c643ff bellard
#define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */
1104 82c643ff bellard
1105 82c643ff bellard
static int term_got_escape, client_index;
1106 82c643ff bellard
1107 82c643ff bellard
void term_print_help(void)
1108 82c643ff bellard
{
1109 82c643ff bellard
    printf("\n"
1110 82c643ff bellard
           "C-a h    print this help\n"
1111 82c643ff bellard
           "C-a x    exit emulator\n"
1112 82c643ff bellard
           "C-a s    save disk data back to file (if -snapshot)\n"
1113 82c643ff bellard
           "C-a b    send break (magic sysrq)\n"
1114 82c643ff bellard
           "C-a c    switch between console and monitor\n"
1115 82c643ff bellard
           "C-a C-a  send C-a\n"
1116 82c643ff bellard
           );
1117 82c643ff bellard
}
1118 82c643ff bellard
1119 82c643ff bellard
/* called when a char is received */
1120 82c643ff bellard
static void stdio_received_byte(int ch)
1121 82c643ff bellard
{
1122 82c643ff bellard
    if (term_got_escape) {
1123 82c643ff bellard
        term_got_escape = 0;
1124 82c643ff bellard
        switch(ch) {
1125 82c643ff bellard
        case 'h':
1126 82c643ff bellard
            term_print_help();
1127 82c643ff bellard
            break;
1128 82c643ff bellard
        case 'x':
1129 82c643ff bellard
            exit(0);
1130 82c643ff bellard
            break;
1131 82c643ff bellard
        case 's': 
1132 82c643ff bellard
            {
1133 82c643ff bellard
                int i;
1134 82c643ff bellard
                for (i = 0; i < MAX_DISKS; i++) {
1135 82c643ff bellard
                    if (bs_table[i])
1136 82c643ff bellard
                        bdrv_commit(bs_table[i]);
1137 82c643ff bellard
                }
1138 82c643ff bellard
            }
1139 82c643ff bellard
            break;
1140 82c643ff bellard
        case 'b':
1141 82c643ff bellard
            if (client_index < stdio_nb_clients) {
1142 82c643ff bellard
                CharDriverState *chr;
1143 82c643ff bellard
                FDCharDriver *s;
1144 82c643ff bellard
1145 82c643ff bellard
                chr = stdio_clients[client_index];
1146 82c643ff bellard
                s = chr->opaque;
1147 82c643ff bellard
                chr->chr_event(s->fd_opaque, CHR_EVENT_BREAK);
1148 82c643ff bellard
            }
1149 82c643ff bellard
            break;
1150 82c643ff bellard
        case 'c':
1151 82c643ff bellard
            client_index++;
1152 82c643ff bellard
            if (client_index >= stdio_nb_clients)
1153 82c643ff bellard
                client_index = 0;
1154 82c643ff bellard
            if (client_index == 0) {
1155 82c643ff bellard
                /* send a new line in the monitor to get the prompt */
1156 82c643ff bellard
                ch = '\r';
1157 82c643ff bellard
                goto send_char;
1158 82c643ff bellard
            }
1159 82c643ff bellard
            break;
1160 82c643ff bellard
        case TERM_ESCAPE:
1161 82c643ff bellard
            goto send_char;
1162 82c643ff bellard
        }
1163 82c643ff bellard
    } else if (ch == TERM_ESCAPE) {
1164 82c643ff bellard
        term_got_escape = 1;
1165 82c643ff bellard
    } else {
1166 82c643ff bellard
    send_char:
1167 82c643ff bellard
        if (client_index < stdio_nb_clients) {
1168 82c643ff bellard
            uint8_t buf[1];
1169 82c643ff bellard
            CharDriverState *chr;
1170 82c643ff bellard
            FDCharDriver *s;
1171 82c643ff bellard
            
1172 82c643ff bellard
            chr = stdio_clients[client_index];
1173 82c643ff bellard
            s = chr->opaque;
1174 82c643ff bellard
            buf[0] = ch;
1175 82c643ff bellard
            /* XXX: should queue the char if the device is not
1176 82c643ff bellard
               ready */
1177 82c643ff bellard
            if (s->fd_can_read(s->fd_opaque) > 0) 
1178 82c643ff bellard
                s->fd_read(s->fd_opaque, buf, 1);
1179 c4b1fcc0 bellard
        }
1180 330d0414 bellard
    }
1181 330d0414 bellard
}
1182 330d0414 bellard
1183 82c643ff bellard
static int stdio_can_read(void *opaque)
1184 82c643ff bellard
{
1185 82c643ff bellard
    /* XXX: not strictly correct */
1186 82c643ff bellard
    return 1;
1187 82c643ff bellard
}
1188 82c643ff bellard
1189 82c643ff bellard
static void stdio_read(void *opaque, const uint8_t *buf, int size)
1190 82c643ff bellard
{
1191 82c643ff bellard
    int i;
1192 82c643ff bellard
    for(i = 0; i < size; i++)
1193 82c643ff bellard
        stdio_received_byte(buf[i]);
1194 82c643ff bellard
}
1195 82c643ff bellard
1196 8d11df9e bellard
/* init terminal so that we can grab keys */
1197 8d11df9e bellard
static struct termios oldtty;
1198 8d11df9e bellard
static int old_fd0_flags;
1199 8d11df9e bellard
1200 8d11df9e bellard
static void term_exit(void)
1201 8d11df9e bellard
{
1202 8d11df9e bellard
    tcsetattr (0, TCSANOW, &oldtty);
1203 8d11df9e bellard
    fcntl(0, F_SETFL, old_fd0_flags);
1204 8d11df9e bellard
}
1205 8d11df9e bellard
1206 8d11df9e bellard
static void term_init(void)
1207 8d11df9e bellard
{
1208 8d11df9e bellard
    struct termios tty;
1209 8d11df9e bellard
1210 8d11df9e bellard
    tcgetattr (0, &tty);
1211 8d11df9e bellard
    oldtty = tty;
1212 8d11df9e bellard
    old_fd0_flags = fcntl(0, F_GETFL);
1213 8d11df9e bellard
1214 8d11df9e bellard
    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
1215 8d11df9e bellard
                          |INLCR|IGNCR|ICRNL|IXON);
1216 8d11df9e bellard
    tty.c_oflag |= OPOST;
1217 8d11df9e bellard
    tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
1218 8d11df9e bellard
    /* if graphical mode, we allow Ctrl-C handling */
1219 8d11df9e bellard
    if (nographic)
1220 8d11df9e bellard
        tty.c_lflag &= ~ISIG;
1221 8d11df9e bellard
    tty.c_cflag &= ~(CSIZE|PARENB);
1222 8d11df9e bellard
    tty.c_cflag |= CS8;
1223 8d11df9e bellard
    tty.c_cc[VMIN] = 1;
1224 8d11df9e bellard
    tty.c_cc[VTIME] = 0;
1225 8d11df9e bellard
    
1226 8d11df9e bellard
    tcsetattr (0, TCSANOW, &tty);
1227 8d11df9e bellard
1228 8d11df9e bellard
    atexit(term_exit);
1229 8d11df9e bellard
1230 8d11df9e bellard
    fcntl(0, F_SETFL, O_NONBLOCK);
1231 8d11df9e bellard
}
1232 8d11df9e bellard
1233 82c643ff bellard
CharDriverState *qemu_chr_open_stdio(void)
1234 82c643ff bellard
{
1235 82c643ff bellard
    CharDriverState *chr;
1236 82c643ff bellard
1237 82c643ff bellard
    if (nographic) {
1238 82c643ff bellard
        if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
1239 82c643ff bellard
            return NULL;
1240 82c643ff bellard
        chr = qemu_chr_open_fd(0, 1);
1241 82c643ff bellard
        if (stdio_nb_clients == 0)
1242 82c643ff bellard
            qemu_add_fd_read_handler(0, stdio_can_read, stdio_read, NULL);
1243 82c643ff bellard
        client_index = stdio_nb_clients;
1244 82c643ff bellard
    } else {
1245 82c643ff bellard
        if (stdio_nb_clients != 0)
1246 82c643ff bellard
            return NULL;
1247 82c643ff bellard
        chr = qemu_chr_open_fd(0, 1);
1248 82c643ff bellard
    }
1249 82c643ff bellard
    stdio_clients[stdio_nb_clients++] = chr;
1250 8d11df9e bellard
    if (stdio_nb_clients == 1) {
1251 8d11df9e bellard
        /* set the terminal in raw mode */
1252 8d11df9e bellard
        term_init();
1253 8d11df9e bellard
    }
1254 82c643ff bellard
    return chr;
1255 82c643ff bellard
}
1256 82c643ff bellard
1257 82c643ff bellard
#if defined(__linux__)
1258 82c643ff bellard
CharDriverState *qemu_chr_open_pty(void)
1259 82c643ff bellard
{
1260 82c643ff bellard
    char slave_name[1024];
1261 82c643ff bellard
    int master_fd, slave_fd;
1262 82c643ff bellard
    
1263 82c643ff bellard
    /* Not satisfying */
1264 82c643ff bellard
    if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) < 0) {
1265 82c643ff bellard
        return NULL;
1266 82c643ff bellard
    }
1267 82c643ff bellard
    fprintf(stderr, "char device redirected to %s\n", slave_name);
1268 82c643ff bellard
    return qemu_chr_open_fd(master_fd, master_fd);
1269 82c643ff bellard
}
1270 82c643ff bellard
#else
1271 82c643ff bellard
CharDriverState *qemu_chr_open_pty(void)
1272 82c643ff bellard
{
1273 82c643ff bellard
    return NULL;
1274 82c643ff bellard
}
1275 67b915a5 bellard
#endif
1276 67b915a5 bellard
1277 82c643ff bellard
#endif /* !defined(_WIN32) */
1278 82c643ff bellard
1279 82c643ff bellard
CharDriverState *qemu_chr_open(const char *filename)
1280 82c643ff bellard
{
1281 82c643ff bellard
    if (!strcmp(filename, "vc")) {
1282 82c643ff bellard
        return text_console_init(&display_state);
1283 82c643ff bellard
    } else if (!strcmp(filename, "null")) {
1284 82c643ff bellard
        return qemu_chr_open_null();
1285 82c643ff bellard
    } else 
1286 82c643ff bellard
#ifndef _WIN32
1287 82c643ff bellard
    if (!strcmp(filename, "pty")) {
1288 82c643ff bellard
        return qemu_chr_open_pty();
1289 82c643ff bellard
    } else if (!strcmp(filename, "stdio")) {
1290 82c643ff bellard
        return qemu_chr_open_stdio();
1291 82c643ff bellard
    } else 
1292 82c643ff bellard
#endif
1293 82c643ff bellard
    {
1294 82c643ff bellard
        return NULL;
1295 82c643ff bellard
    }
1296 82c643ff bellard
}
1297 82c643ff bellard
1298 80cabfad bellard
/***********************************************************/
1299 c20709aa bellard
/* Linux network device redirectors */
1300 330d0414 bellard
1301 c20709aa bellard
void hex_dump(FILE *f, const uint8_t *buf, int size)
1302 c20709aa bellard
{
1303 c20709aa bellard
    int len, i, j, c;
1304 c20709aa bellard
1305 c20709aa bellard
    for(i=0;i<size;i+=16) {
1306 c20709aa bellard
        len = size - i;
1307 c20709aa bellard
        if (len > 16)
1308 c20709aa bellard
            len = 16;
1309 c20709aa bellard
        fprintf(f, "%08x ", i);
1310 c20709aa bellard
        for(j=0;j<16;j++) {
1311 c20709aa bellard
            if (j < len)
1312 c20709aa bellard
                fprintf(f, " %02x", buf[i+j]);
1313 c20709aa bellard
            else
1314 c20709aa bellard
                fprintf(f, "   ");
1315 c20709aa bellard
        }
1316 c20709aa bellard
        fprintf(f, " ");
1317 c20709aa bellard
        for(j=0;j<len;j++) {
1318 c20709aa bellard
            c = buf[i+j];
1319 c20709aa bellard
            if (c < ' ' || c > '~')
1320 c20709aa bellard
                c = '.';
1321 c20709aa bellard
            fprintf(f, "%c", c);
1322 c20709aa bellard
        }
1323 c20709aa bellard
        fprintf(f, "\n");
1324 c20709aa bellard
    }
1325 c20709aa bellard
}
1326 c20709aa bellard
1327 c20709aa bellard
void qemu_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
1328 c20709aa bellard
{
1329 c20709aa bellard
    nd->send_packet(nd, buf, size);
1330 c20709aa bellard
}
1331 67b915a5 bellard
1332 c20709aa bellard
void qemu_add_read_packet(NetDriverState *nd, IOCanRWHandler *fd_can_read, 
1333 c20709aa bellard
                          IOReadHandler *fd_read, void *opaque)
1334 67b915a5 bellard
{
1335 c20709aa bellard
    nd->add_read_packet(nd, fd_can_read, fd_read, opaque);
1336 c20709aa bellard
}
1337 c20709aa bellard
1338 c20709aa bellard
/* dummy network adapter */
1339 c20709aa bellard
1340 c20709aa bellard
static void dummy_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
1341 c20709aa bellard
{
1342 c20709aa bellard
}
1343 c20709aa bellard
1344 c20709aa bellard
static void dummy_add_read_packet(NetDriverState *nd, 
1345 c20709aa bellard
                                  IOCanRWHandler *fd_can_read, 
1346 c20709aa bellard
                                  IOReadHandler *fd_read, void *opaque)
1347 c20709aa bellard
{
1348 c20709aa bellard
}
1349 c20709aa bellard
1350 c20709aa bellard
static int net_dummy_init(NetDriverState *nd)
1351 c20709aa bellard
{
1352 c20709aa bellard
    nd->send_packet = dummy_send_packet;
1353 c20709aa bellard
    nd->add_read_packet = dummy_add_read_packet;
1354 c20709aa bellard
    pstrcpy(nd->ifname, sizeof(nd->ifname), "dummy");
1355 67b915a5 bellard
    return 0;
1356 67b915a5 bellard
}
1357 67b915a5 bellard
1358 c20709aa bellard
#if defined(CONFIG_SLIRP)
1359 c20709aa bellard
1360 c20709aa bellard
/* slirp network adapter */
1361 c20709aa bellard
1362 c20709aa bellard
static void *slirp_fd_opaque;
1363 c20709aa bellard
static IOCanRWHandler *slirp_fd_can_read;
1364 c20709aa bellard
static IOReadHandler *slirp_fd_read;
1365 c20709aa bellard
static int slirp_inited;
1366 c20709aa bellard
1367 c20709aa bellard
int slirp_can_output(void)
1368 c20709aa bellard
{
1369 c20709aa bellard
    return slirp_fd_can_read(slirp_fd_opaque);
1370 c20709aa bellard
}
1371 c20709aa bellard
1372 c20709aa bellard
void slirp_output(const uint8_t *pkt, int pkt_len)
1373 67b915a5 bellard
{
1374 c20709aa bellard
#if 0
1375 c20709aa bellard
    printf("output:\n");
1376 c20709aa bellard
    hex_dump(stdout, pkt, pkt_len);
1377 c20709aa bellard
#endif
1378 c20709aa bellard
    slirp_fd_read(slirp_fd_opaque, pkt, pkt_len);
1379 67b915a5 bellard
}
1380 67b915a5 bellard
1381 c20709aa bellard
static void slirp_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
1382 c20709aa bellard
{
1383 c20709aa bellard
#if 0
1384 c20709aa bellard
    printf("input:\n");
1385 c20709aa bellard
    hex_dump(stdout, buf, size);
1386 c20709aa bellard
#endif
1387 c20709aa bellard
    slirp_input(buf, size);
1388 c20709aa bellard
}
1389 c20709aa bellard
1390 c20709aa bellard
static void slirp_add_read_packet(NetDriverState *nd, 
1391 c20709aa bellard
                                  IOCanRWHandler *fd_can_read, 
1392 c20709aa bellard
                                  IOReadHandler *fd_read, void *opaque)
1393 c20709aa bellard
{
1394 c20709aa bellard
    slirp_fd_opaque = opaque;
1395 c20709aa bellard
    slirp_fd_can_read = fd_can_read;
1396 c20709aa bellard
    slirp_fd_read = fd_read;
1397 c20709aa bellard
}
1398 c20709aa bellard
1399 c20709aa bellard
static int net_slirp_init(NetDriverState *nd)
1400 c20709aa bellard
{
1401 c20709aa bellard
    if (!slirp_inited) {
1402 c20709aa bellard
        slirp_inited = 1;
1403 c20709aa bellard
        slirp_init();
1404 c20709aa bellard
    }
1405 c20709aa bellard
    nd->send_packet = slirp_send_packet;
1406 c20709aa bellard
    nd->add_read_packet = slirp_add_read_packet;
1407 c20709aa bellard
    pstrcpy(nd->ifname, sizeof(nd->ifname), "slirp");
1408 c20709aa bellard
    return 0;
1409 c20709aa bellard
}
1410 c20709aa bellard
1411 9bf05444 bellard
static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
1412 9bf05444 bellard
{
1413 9bf05444 bellard
    const char *p, *p1;
1414 9bf05444 bellard
    int len;
1415 9bf05444 bellard
    p = *pp;
1416 9bf05444 bellard
    p1 = strchr(p, sep);
1417 9bf05444 bellard
    if (!p1)
1418 9bf05444 bellard
        return -1;
1419 9bf05444 bellard
    len = p1 - p;
1420 9bf05444 bellard
    p1++;
1421 9bf05444 bellard
    if (buf_size > 0) {
1422 9bf05444 bellard
        if (len > buf_size - 1)
1423 9bf05444 bellard
            len = buf_size - 1;
1424 9bf05444 bellard
        memcpy(buf, p, len);
1425 9bf05444 bellard
        buf[len] = '\0';
1426 9bf05444 bellard
    }
1427 9bf05444 bellard
    *pp = p1;
1428 9bf05444 bellard
    return 0;
1429 9bf05444 bellard
}
1430 9bf05444 bellard
1431 9bf05444 bellard
static void net_slirp_redir(const char *redir_str)
1432 9bf05444 bellard
{
1433 9bf05444 bellard
    int is_udp;
1434 9bf05444 bellard
    char buf[256], *r;
1435 9bf05444 bellard
    const char *p;
1436 9bf05444 bellard
    struct in_addr guest_addr;
1437 9bf05444 bellard
    int host_port, guest_port;
1438 9bf05444 bellard
    
1439 9bf05444 bellard
    if (!slirp_inited) {
1440 9bf05444 bellard
        slirp_inited = 1;
1441 9bf05444 bellard
        slirp_init();
1442 9bf05444 bellard
    }
1443 9bf05444 bellard
1444 9bf05444 bellard
    p = redir_str;
1445 9bf05444 bellard
    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
1446 9bf05444 bellard
        goto fail;
1447 9bf05444 bellard
    if (!strcmp(buf, "tcp")) {
1448 9bf05444 bellard
        is_udp = 0;
1449 9bf05444 bellard
    } else if (!strcmp(buf, "udp")) {
1450 9bf05444 bellard
        is_udp = 1;
1451 9bf05444 bellard
    } else {
1452 9bf05444 bellard
        goto fail;
1453 9bf05444 bellard
    }
1454 9bf05444 bellard
1455 9bf05444 bellard
    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
1456 9bf05444 bellard
        goto fail;
1457 9bf05444 bellard
    host_port = strtol(buf, &r, 0);
1458 9bf05444 bellard
    if (r == buf)
1459 9bf05444 bellard
        goto fail;
1460 9bf05444 bellard
1461 9bf05444 bellard
    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
1462 9bf05444 bellard
        goto fail;
1463 9bf05444 bellard
    if (buf[0] == '\0') {
1464 9bf05444 bellard
        pstrcpy(buf, sizeof(buf), "10.0.2.15");
1465 9bf05444 bellard
    }
1466 9bf05444 bellard
    if (!inet_aton(buf, &guest_addr))
1467 9bf05444 bellard
        goto fail;
1468 9bf05444 bellard
    
1469 9bf05444 bellard
    guest_port = strtol(p, &r, 0);
1470 9bf05444 bellard
    if (r == p)
1471 9bf05444 bellard
        goto fail;
1472 9bf05444 bellard
    
1473 9bf05444 bellard
    if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) {
1474 9bf05444 bellard
        fprintf(stderr, "qemu: could not set up redirection\n");
1475 9bf05444 bellard
        exit(1);
1476 9bf05444 bellard
    }
1477 9bf05444 bellard
    return;
1478 9bf05444 bellard
 fail:
1479 9bf05444 bellard
    fprintf(stderr, "qemu: syntax: -redir [tcp|udp]:host-port:[guest-host]:guest-port\n");
1480 9bf05444 bellard
    exit(1);
1481 9bf05444 bellard
}
1482 9d728e8c bellard
    
1483 c94c8d64 bellard
#ifndef _WIN32
1484 c94c8d64 bellard
1485 9d728e8c bellard
char smb_dir[1024];
1486 9d728e8c bellard
1487 9d728e8c bellard
static void smb_exit(void)
1488 9d728e8c bellard
{
1489 9d728e8c bellard
    DIR *d;
1490 9d728e8c bellard
    struct dirent *de;
1491 9d728e8c bellard
    char filename[1024];
1492 9d728e8c bellard
1493 9d728e8c bellard
    /* erase all the files in the directory */
1494 9d728e8c bellard
    d = opendir(smb_dir);
1495 9d728e8c bellard
    for(;;) {
1496 9d728e8c bellard
        de = readdir(d);
1497 9d728e8c bellard
        if (!de)
1498 9d728e8c bellard
            break;
1499 9d728e8c bellard
        if (strcmp(de->d_name, ".") != 0 &&
1500 9d728e8c bellard
            strcmp(de->d_name, "..") != 0) {
1501 9d728e8c bellard
            snprintf(filename, sizeof(filename), "%s/%s", 
1502 9d728e8c bellard
                     smb_dir, de->d_name);
1503 9d728e8c bellard
            unlink(filename);
1504 9d728e8c bellard
        }
1505 9d728e8c bellard
    }
1506 03ffbb69 bellard
    closedir(d);
1507 9d728e8c bellard
    rmdir(smb_dir);
1508 9d728e8c bellard
}
1509 9d728e8c bellard
1510 9d728e8c bellard
/* automatic user mode samba server configuration */
1511 9d728e8c bellard
void net_slirp_smb(const char *exported_dir)
1512 9d728e8c bellard
{
1513 9d728e8c bellard
    char smb_conf[1024];
1514 9d728e8c bellard
    char smb_cmdline[1024];
1515 9d728e8c bellard
    FILE *f;
1516 9d728e8c bellard
1517 9d728e8c bellard
    if (!slirp_inited) {
1518 9d728e8c bellard
        slirp_inited = 1;
1519 9d728e8c bellard
        slirp_init();
1520 9d728e8c bellard
    }
1521 9d728e8c bellard
1522 9d728e8c bellard
    /* XXX: better tmp dir construction */
1523 9d728e8c bellard
    snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%d", getpid());
1524 9d728e8c bellard
    if (mkdir(smb_dir, 0700) < 0) {
1525 9d728e8c bellard
        fprintf(stderr, "qemu: could not create samba server dir '%s'\n", smb_dir);
1526 9d728e8c bellard
        exit(1);
1527 9d728e8c bellard
    }
1528 9d728e8c bellard
    snprintf(smb_conf, sizeof(smb_conf), "%s/%s", smb_dir, "smb.conf");
1529 9d728e8c bellard
    
1530 9d728e8c bellard
    f = fopen(smb_conf, "w");
1531 9d728e8c bellard
    if (!f) {
1532 9d728e8c bellard
        fprintf(stderr, "qemu: could not create samba server configuration file '%s'\n", smb_conf);
1533 9d728e8c bellard
        exit(1);
1534 9d728e8c bellard
    }
1535 9d728e8c bellard
    fprintf(f, 
1536 9d728e8c bellard
            "[global]\n"
1537 9d728e8c bellard
            "pid directory=%s\n"
1538 9d728e8c bellard
            "lock directory=%s\n"
1539 9d728e8c bellard
            "log file=%s/log.smbd\n"
1540 9d728e8c bellard
            "smb passwd file=%s/smbpasswd\n"
1541 03ffbb69 bellard
            "security = share\n"
1542 9d728e8c bellard
            "[qemu]\n"
1543 9d728e8c bellard
            "path=%s\n"
1544 9d728e8c bellard
            "read only=no\n"
1545 9d728e8c bellard
            "guest ok=yes\n",
1546 9d728e8c bellard
            smb_dir,
1547 9d728e8c bellard
            smb_dir,
1548 9d728e8c bellard
            smb_dir,
1549 9d728e8c bellard
            smb_dir,
1550 9d728e8c bellard
            exported_dir
1551 9d728e8c bellard
            );
1552 9d728e8c bellard
    fclose(f);
1553 9d728e8c bellard
    atexit(smb_exit);
1554 9d728e8c bellard
1555 9d728e8c bellard
    snprintf(smb_cmdline, sizeof(smb_cmdline), "/usr/sbin/smbd -s %s",
1556 9d728e8c bellard
             smb_conf);
1557 9d728e8c bellard
    
1558 9d728e8c bellard
    slirp_add_exec(0, smb_cmdline, 4, 139);
1559 9d728e8c bellard
}
1560 9bf05444 bellard
1561 c94c8d64 bellard
#endif /* !defined(_WIN32) */
1562 c94c8d64 bellard
1563 c20709aa bellard
#endif /* CONFIG_SLIRP */
1564 c20709aa bellard
1565 c20709aa bellard
#if !defined(_WIN32)
1566 7d3505c5 bellard
#ifdef _BSD
1567 7d3505c5 bellard
static int tun_open(char *ifname, int ifname_size)
1568 7d3505c5 bellard
{
1569 7d3505c5 bellard
    int fd;
1570 7d3505c5 bellard
    char *dev;
1571 7d3505c5 bellard
    struct stat s;
1572 67b915a5 bellard
1573 7d3505c5 bellard
    fd = open("/dev/tap", O_RDWR);
1574 7d3505c5 bellard
    if (fd < 0) {
1575 7d3505c5 bellard
        fprintf(stderr, "warning: could not open /dev/tap: no virtual network emulation\n");
1576 7d3505c5 bellard
        return -1;
1577 7d3505c5 bellard
    }
1578 7d3505c5 bellard
1579 7d3505c5 bellard
    fstat(fd, &s);
1580 7d3505c5 bellard
    dev = devname(s.st_rdev, S_IFCHR);
1581 7d3505c5 bellard
    pstrcpy(ifname, ifname_size, dev);
1582 7d3505c5 bellard
1583 7d3505c5 bellard
    fcntl(fd, F_SETFL, O_NONBLOCK);
1584 7d3505c5 bellard
    return fd;
1585 7d3505c5 bellard
}
1586 7d3505c5 bellard
#else
1587 c4b1fcc0 bellard
static int tun_open(char *ifname, int ifname_size)
1588 330d0414 bellard
{
1589 80cabfad bellard
    struct ifreq ifr;
1590 c4b1fcc0 bellard
    int fd, ret;
1591 80cabfad bellard
    
1592 80cabfad bellard
    fd = open("/dev/net/tun", O_RDWR);
1593 80cabfad bellard
    if (fd < 0) {
1594 80cabfad bellard
        fprintf(stderr, "warning: could not open /dev/net/tun: no virtual network emulation\n");
1595 80cabfad bellard
        return -1;
1596 330d0414 bellard
    }
1597 80cabfad bellard
    memset(&ifr, 0, sizeof(ifr));
1598 80cabfad bellard
    ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
1599 80cabfad bellard
    pstrcpy(ifr.ifr_name, IFNAMSIZ, "tun%d");
1600 80cabfad bellard
    ret = ioctl(fd, TUNSETIFF, (void *) &ifr);
1601 80cabfad bellard
    if (ret != 0) {
1602 80cabfad bellard
        fprintf(stderr, "warning: could not configure /dev/net/tun: no virtual network emulation\n");
1603 80cabfad bellard
        close(fd);
1604 80cabfad bellard
        return -1;
1605 80cabfad bellard
    }
1606 80cabfad bellard
    printf("Connected to host network interface: %s\n", ifr.ifr_name);
1607 c4b1fcc0 bellard
    pstrcpy(ifname, ifname_size, ifr.ifr_name);
1608 80cabfad bellard
    fcntl(fd, F_SETFL, O_NONBLOCK);
1609 c4b1fcc0 bellard
    return fd;
1610 c4b1fcc0 bellard
}
1611 7d3505c5 bellard
#endif
1612 330d0414 bellard
1613 c20709aa bellard
static void tun_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
1614 c20709aa bellard
{
1615 c20709aa bellard
    write(nd->fd, buf, size);
1616 c20709aa bellard
}
1617 c20709aa bellard
1618 c20709aa bellard
static void tun_add_read_packet(NetDriverState *nd, 
1619 c20709aa bellard
                                IOCanRWHandler *fd_can_read, 
1620 c20709aa bellard
                                IOReadHandler *fd_read, void *opaque)
1621 c4b1fcc0 bellard
{
1622 c20709aa bellard
    qemu_add_fd_read_handler(nd->fd, fd_can_read, fd_read, opaque);
1623 c20709aa bellard
}
1624 c20709aa bellard
1625 c20709aa bellard
static int net_tun_init(NetDriverState *nd)
1626 c20709aa bellard
{
1627 c20709aa bellard
    int pid, status;
1628 c20709aa bellard
    char *args[3];
1629 c4b1fcc0 bellard
    char **parg;
1630 c4b1fcc0 bellard
1631 c20709aa bellard
    nd->fd = tun_open(nd->ifname, sizeof(nd->ifname));
1632 c20709aa bellard
    if (nd->fd < 0)
1633 c20709aa bellard
        return -1;
1634 c4b1fcc0 bellard
1635 c20709aa bellard
    /* try to launch network init script */
1636 c20709aa bellard
    pid = fork();
1637 c20709aa bellard
    if (pid >= 0) {
1638 c20709aa bellard
        if (pid == 0) {
1639 c20709aa bellard
            parg = args;
1640 c20709aa bellard
            *parg++ = network_script;
1641 c20709aa bellard
            *parg++ = nd->ifname;
1642 c20709aa bellard
            *parg++ = NULL;
1643 c20709aa bellard
            execv(network_script, args);
1644 c20709aa bellard
            exit(1);
1645 c20709aa bellard
        }
1646 c20709aa bellard
        while (waitpid(pid, &status, 0) != pid);
1647 c20709aa bellard
        if (!WIFEXITED(status) ||
1648 c20709aa bellard
            WEXITSTATUS(status) != 0) {
1649 c20709aa bellard
            fprintf(stderr, "%s: could not launch network script\n",
1650 c20709aa bellard
                    network_script);
1651 80cabfad bellard
        }
1652 330d0414 bellard
    }
1653 c20709aa bellard
    nd->send_packet = tun_send_packet;
1654 c20709aa bellard
    nd->add_read_packet = tun_add_read_packet;
1655 80cabfad bellard
    return 0;
1656 330d0414 bellard
}
1657 330d0414 bellard
1658 c20709aa bellard
static int net_fd_init(NetDriverState *nd, int fd)
1659 330d0414 bellard
{
1660 c20709aa bellard
    nd->fd = fd;
1661 c20709aa bellard
    nd->send_packet = tun_send_packet;
1662 c20709aa bellard
    nd->add_read_packet = tun_add_read_packet;
1663 c20709aa bellard
    pstrcpy(nd->ifname, sizeof(nd->ifname), "tunfd");
1664 c20709aa bellard
    return 0;
1665 80cabfad bellard
}
1666 330d0414 bellard
1667 c20709aa bellard
#endif /* !_WIN32 */
1668 67b915a5 bellard
1669 330d0414 bellard
/***********************************************************/
1670 313aa567 bellard
/* dumb display */
1671 313aa567 bellard
1672 313aa567 bellard
static void dumb_update(DisplayState *ds, int x, int y, int w, int h)
1673 313aa567 bellard
{
1674 313aa567 bellard
}
1675 313aa567 bellard
1676 313aa567 bellard
static void dumb_resize(DisplayState *ds, int w, int h)
1677 313aa567 bellard
{
1678 313aa567 bellard
}
1679 313aa567 bellard
1680 313aa567 bellard
static void dumb_refresh(DisplayState *ds)
1681 313aa567 bellard
{
1682 313aa567 bellard
    vga_update_display();
1683 313aa567 bellard
}
1684 313aa567 bellard
1685 313aa567 bellard
void dumb_display_init(DisplayState *ds)
1686 313aa567 bellard
{
1687 313aa567 bellard
    ds->data = NULL;
1688 313aa567 bellard
    ds->linesize = 0;
1689 313aa567 bellard
    ds->depth = 0;
1690 313aa567 bellard
    ds->dpy_update = dumb_update;
1691 313aa567 bellard
    ds->dpy_resize = dumb_resize;
1692 313aa567 bellard
    ds->dpy_refresh = dumb_refresh;
1693 313aa567 bellard
}
1694 313aa567 bellard
1695 3a51dee6 bellard
#if !defined(CONFIG_SOFTMMU)
1696 313aa567 bellard
/***********************************************************/
1697 0824d6fc bellard
/* cpu signal handler */
1698 0824d6fc bellard
static void host_segv_handler(int host_signum, siginfo_t *info, 
1699 0824d6fc bellard
                              void *puc)
1700 0824d6fc bellard
{
1701 0824d6fc bellard
    if (cpu_signal_handler(host_signum, info, puc))
1702 0824d6fc bellard
        return;
1703 8d11df9e bellard
    if (stdio_nb_clients > 0)
1704 8d11df9e bellard
        term_exit();
1705 0824d6fc bellard
    abort();
1706 0824d6fc bellard
}
1707 3a51dee6 bellard
#endif
1708 0824d6fc bellard
1709 8a7ddc38 bellard
/***********************************************************/
1710 8a7ddc38 bellard
/* I/O handling */
1711 0824d6fc bellard
1712 c4b1fcc0 bellard
#define MAX_IO_HANDLERS 64
1713 c4b1fcc0 bellard
1714 c4b1fcc0 bellard
typedef struct IOHandlerRecord {
1715 c4b1fcc0 bellard
    int fd;
1716 c4b1fcc0 bellard
    IOCanRWHandler *fd_can_read;
1717 c4b1fcc0 bellard
    IOReadHandler *fd_read;
1718 c4b1fcc0 bellard
    void *opaque;
1719 c4b1fcc0 bellard
    /* temporary data */
1720 c4b1fcc0 bellard
    struct pollfd *ufd;
1721 c4b1fcc0 bellard
    int max_size;
1722 8a7ddc38 bellard
    struct IOHandlerRecord *next;
1723 c4b1fcc0 bellard
} IOHandlerRecord;
1724 c4b1fcc0 bellard
1725 8a7ddc38 bellard
static IOHandlerRecord *first_io_handler;
1726 c4b1fcc0 bellard
1727 8a7ddc38 bellard
int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read, 
1728 8a7ddc38 bellard
                             IOReadHandler *fd_read, void *opaque)
1729 c4b1fcc0 bellard
{
1730 c4b1fcc0 bellard
    IOHandlerRecord *ioh;
1731 c4b1fcc0 bellard
1732 8a7ddc38 bellard
    ioh = qemu_mallocz(sizeof(IOHandlerRecord));
1733 8a7ddc38 bellard
    if (!ioh)
1734 c4b1fcc0 bellard
        return -1;
1735 c4b1fcc0 bellard
    ioh->fd = fd;
1736 c4b1fcc0 bellard
    ioh->fd_can_read = fd_can_read;
1737 c4b1fcc0 bellard
    ioh->fd_read = fd_read;
1738 c4b1fcc0 bellard
    ioh->opaque = opaque;
1739 8a7ddc38 bellard
    ioh->next = first_io_handler;
1740 8a7ddc38 bellard
    first_io_handler = ioh;
1741 c4b1fcc0 bellard
    return 0;
1742 c4b1fcc0 bellard
}
1743 c4b1fcc0 bellard
1744 8a7ddc38 bellard
void qemu_del_fd_read_handler(int fd)
1745 8a7ddc38 bellard
{
1746 8a7ddc38 bellard
    IOHandlerRecord **pioh, *ioh;
1747 b4608c04 bellard
1748 8a7ddc38 bellard
    pioh = &first_io_handler;
1749 8a7ddc38 bellard
    for(;;) {
1750 8a7ddc38 bellard
        ioh = *pioh;
1751 8a7ddc38 bellard
        if (ioh == NULL)
1752 8a7ddc38 bellard
            break;
1753 8a7ddc38 bellard
        if (ioh->fd == fd) {
1754 8a7ddc38 bellard
            *pioh = ioh->next;
1755 8a7ddc38 bellard
            break;
1756 8a7ddc38 bellard
        }
1757 8a7ddc38 bellard
        pioh = &ioh->next;
1758 8a7ddc38 bellard
    }
1759 8a7ddc38 bellard
}
1760 8a7ddc38 bellard
1761 8a7ddc38 bellard
/***********************************************************/
1762 8a7ddc38 bellard
/* savevm/loadvm support */
1763 8a7ddc38 bellard
1764 8a7ddc38 bellard
void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
1765 b4608c04 bellard
{
1766 8a7ddc38 bellard
    fwrite(buf, 1, size, f);
1767 b4608c04 bellard
}
1768 b4608c04 bellard
1769 8a7ddc38 bellard
void qemu_put_byte(QEMUFile *f, int v)
1770 b4608c04 bellard
{
1771 8a7ddc38 bellard
    fputc(v, f);
1772 8a7ddc38 bellard
}
1773 8a7ddc38 bellard
1774 8a7ddc38 bellard
void qemu_put_be16(QEMUFile *f, unsigned int v)
1775 8a7ddc38 bellard
{
1776 8a7ddc38 bellard
    qemu_put_byte(f, v >> 8);
1777 8a7ddc38 bellard
    qemu_put_byte(f, v);
1778 8a7ddc38 bellard
}
1779 8a7ddc38 bellard
1780 8a7ddc38 bellard
void qemu_put_be32(QEMUFile *f, unsigned int v)
1781 8a7ddc38 bellard
{
1782 8a7ddc38 bellard
    qemu_put_byte(f, v >> 24);
1783 8a7ddc38 bellard
    qemu_put_byte(f, v >> 16);
1784 8a7ddc38 bellard
    qemu_put_byte(f, v >> 8);
1785 8a7ddc38 bellard
    qemu_put_byte(f, v);
1786 8a7ddc38 bellard
}
1787 8a7ddc38 bellard
1788 8a7ddc38 bellard
void qemu_put_be64(QEMUFile *f, uint64_t v)
1789 8a7ddc38 bellard
{
1790 8a7ddc38 bellard
    qemu_put_be32(f, v >> 32);
1791 8a7ddc38 bellard
    qemu_put_be32(f, v);
1792 8a7ddc38 bellard
}
1793 8a7ddc38 bellard
1794 8a7ddc38 bellard
int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
1795 8a7ddc38 bellard
{
1796 8a7ddc38 bellard
    return fread(buf, 1, size, f);
1797 8a7ddc38 bellard
}
1798 8a7ddc38 bellard
1799 8a7ddc38 bellard
int qemu_get_byte(QEMUFile *f)
1800 8a7ddc38 bellard
{
1801 8a7ddc38 bellard
    int v;
1802 8a7ddc38 bellard
    v = fgetc(f);
1803 8a7ddc38 bellard
    if (v == EOF)
1804 8a7ddc38 bellard
        return 0;
1805 8a7ddc38 bellard
    else
1806 8a7ddc38 bellard
        return v;
1807 8a7ddc38 bellard
}
1808 8a7ddc38 bellard
1809 8a7ddc38 bellard
unsigned int qemu_get_be16(QEMUFile *f)
1810 8a7ddc38 bellard
{
1811 8a7ddc38 bellard
    unsigned int v;
1812 8a7ddc38 bellard
    v = qemu_get_byte(f) << 8;
1813 8a7ddc38 bellard
    v |= qemu_get_byte(f);
1814 8a7ddc38 bellard
    return v;
1815 8a7ddc38 bellard
}
1816 8a7ddc38 bellard
1817 8a7ddc38 bellard
unsigned int qemu_get_be32(QEMUFile *f)
1818 8a7ddc38 bellard
{
1819 8a7ddc38 bellard
    unsigned int v;
1820 8a7ddc38 bellard
    v = qemu_get_byte(f) << 24;
1821 8a7ddc38 bellard
    v |= qemu_get_byte(f) << 16;
1822 8a7ddc38 bellard
    v |= qemu_get_byte(f) << 8;
1823 8a7ddc38 bellard
    v |= qemu_get_byte(f);
1824 8a7ddc38 bellard
    return v;
1825 8a7ddc38 bellard
}
1826 8a7ddc38 bellard
1827 8a7ddc38 bellard
uint64_t qemu_get_be64(QEMUFile *f)
1828 8a7ddc38 bellard
{
1829 8a7ddc38 bellard
    uint64_t v;
1830 8a7ddc38 bellard
    v = (uint64_t)qemu_get_be32(f) << 32;
1831 8a7ddc38 bellard
    v |= qemu_get_be32(f);
1832 8a7ddc38 bellard
    return v;
1833 8a7ddc38 bellard
}
1834 8a7ddc38 bellard
1835 8a7ddc38 bellard
int64_t qemu_ftell(QEMUFile *f)
1836 8a7ddc38 bellard
{
1837 8a7ddc38 bellard
    return ftell(f);
1838 8a7ddc38 bellard
}
1839 8a7ddc38 bellard
1840 8a7ddc38 bellard
int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence)
1841 8a7ddc38 bellard
{
1842 8a7ddc38 bellard
    if (fseek(f, pos, whence) < 0)
1843 8a7ddc38 bellard
        return -1;
1844 8a7ddc38 bellard
    return ftell(f);
1845 8a7ddc38 bellard
}
1846 8a7ddc38 bellard
1847 8a7ddc38 bellard
typedef struct SaveStateEntry {
1848 8a7ddc38 bellard
    char idstr[256];
1849 8a7ddc38 bellard
    int instance_id;
1850 8a7ddc38 bellard
    int version_id;
1851 8a7ddc38 bellard
    SaveStateHandler *save_state;
1852 8a7ddc38 bellard
    LoadStateHandler *load_state;
1853 8a7ddc38 bellard
    void *opaque;
1854 8a7ddc38 bellard
    struct SaveStateEntry *next;
1855 8a7ddc38 bellard
} SaveStateEntry;
1856 b4608c04 bellard
1857 8a7ddc38 bellard
static SaveStateEntry *first_se;
1858 8a7ddc38 bellard
1859 8a7ddc38 bellard
int register_savevm(const char *idstr, 
1860 8a7ddc38 bellard
                    int instance_id, 
1861 8a7ddc38 bellard
                    int version_id,
1862 8a7ddc38 bellard
                    SaveStateHandler *save_state,
1863 8a7ddc38 bellard
                    LoadStateHandler *load_state,
1864 8a7ddc38 bellard
                    void *opaque)
1865 8a7ddc38 bellard
{
1866 8a7ddc38 bellard
    SaveStateEntry *se, **pse;
1867 8a7ddc38 bellard
1868 8a7ddc38 bellard
    se = qemu_malloc(sizeof(SaveStateEntry));
1869 8a7ddc38 bellard
    if (!se)
1870 8a7ddc38 bellard
        return -1;
1871 8a7ddc38 bellard
    pstrcpy(se->idstr, sizeof(se->idstr), idstr);
1872 8a7ddc38 bellard
    se->instance_id = instance_id;
1873 8a7ddc38 bellard
    se->version_id = version_id;
1874 8a7ddc38 bellard
    se->save_state = save_state;
1875 8a7ddc38 bellard
    se->load_state = load_state;
1876 8a7ddc38 bellard
    se->opaque = opaque;
1877 8a7ddc38 bellard
    se->next = NULL;
1878 8a7ddc38 bellard
1879 8a7ddc38 bellard
    /* add at the end of list */
1880 8a7ddc38 bellard
    pse = &first_se;
1881 8a7ddc38 bellard
    while (*pse != NULL)
1882 8a7ddc38 bellard
        pse = &(*pse)->next;
1883 8a7ddc38 bellard
    *pse = se;
1884 8a7ddc38 bellard
    return 0;
1885 8a7ddc38 bellard
}
1886 8a7ddc38 bellard
1887 8a7ddc38 bellard
#define QEMU_VM_FILE_MAGIC   0x5145564d
1888 8a7ddc38 bellard
#define QEMU_VM_FILE_VERSION 0x00000001
1889 8a7ddc38 bellard
1890 8a7ddc38 bellard
int qemu_savevm(const char *filename)
1891 8a7ddc38 bellard
{
1892 8a7ddc38 bellard
    SaveStateEntry *se;
1893 8a7ddc38 bellard
    QEMUFile *f;
1894 8a7ddc38 bellard
    int len, len_pos, cur_pos, saved_vm_running, ret;
1895 8a7ddc38 bellard
1896 8a7ddc38 bellard
    saved_vm_running = vm_running;
1897 8a7ddc38 bellard
    vm_stop(0);
1898 8a7ddc38 bellard
1899 8a7ddc38 bellard
    f = fopen(filename, "wb");
1900 8a7ddc38 bellard
    if (!f) {
1901 8a7ddc38 bellard
        ret = -1;
1902 8a7ddc38 bellard
        goto the_end;
1903 313aa567 bellard
    }
1904 313aa567 bellard
1905 8a7ddc38 bellard
    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
1906 8a7ddc38 bellard
    qemu_put_be32(f, QEMU_VM_FILE_VERSION);
1907 8a7ddc38 bellard
1908 8a7ddc38 bellard
    for(se = first_se; se != NULL; se = se->next) {
1909 8a7ddc38 bellard
        /* ID string */
1910 8a7ddc38 bellard
        len = strlen(se->idstr);
1911 8a7ddc38 bellard
        qemu_put_byte(f, len);
1912 8a7ddc38 bellard
        qemu_put_buffer(f, se->idstr, len);
1913 8a7ddc38 bellard
1914 8a7ddc38 bellard
        qemu_put_be32(f, se->instance_id);
1915 8a7ddc38 bellard
        qemu_put_be32(f, se->version_id);
1916 8a7ddc38 bellard
1917 8a7ddc38 bellard
        /* record size: filled later */
1918 8a7ddc38 bellard
        len_pos = ftell(f);
1919 8a7ddc38 bellard
        qemu_put_be32(f, 0);
1920 8a7ddc38 bellard
        
1921 8a7ddc38 bellard
        se->save_state(f, se->opaque);
1922 8a7ddc38 bellard
1923 8a7ddc38 bellard
        /* fill record size */
1924 8a7ddc38 bellard
        cur_pos = ftell(f);
1925 8a7ddc38 bellard
        len = ftell(f) - len_pos - 4;
1926 8a7ddc38 bellard
        fseek(f, len_pos, SEEK_SET);
1927 8a7ddc38 bellard
        qemu_put_be32(f, len);
1928 8a7ddc38 bellard
        fseek(f, cur_pos, SEEK_SET);
1929 8a7ddc38 bellard
    }
1930 8a7ddc38 bellard
1931 8a7ddc38 bellard
    fclose(f);
1932 8a7ddc38 bellard
    ret = 0;
1933 8a7ddc38 bellard
 the_end:
1934 8a7ddc38 bellard
    if (saved_vm_running)
1935 8a7ddc38 bellard
        vm_start();
1936 8a7ddc38 bellard
    return ret;
1937 8a7ddc38 bellard
}
1938 8a7ddc38 bellard
1939 8a7ddc38 bellard
static SaveStateEntry *find_se(const char *idstr, int instance_id)
1940 8a7ddc38 bellard
{
1941 8a7ddc38 bellard
    SaveStateEntry *se;
1942 8a7ddc38 bellard
1943 8a7ddc38 bellard
    for(se = first_se; se != NULL; se = se->next) {
1944 8a7ddc38 bellard
        if (!strcmp(se->idstr, idstr) && 
1945 8a7ddc38 bellard
            instance_id == se->instance_id)
1946 8a7ddc38 bellard
            return se;
1947 8a7ddc38 bellard
    }
1948 8a7ddc38 bellard
    return NULL;
1949 8a7ddc38 bellard
}
1950 8a7ddc38 bellard
1951 8a7ddc38 bellard
int qemu_loadvm(const char *filename)
1952 8a7ddc38 bellard
{
1953 8a7ddc38 bellard
    SaveStateEntry *se;
1954 8a7ddc38 bellard
    QEMUFile *f;
1955 8a7ddc38 bellard
    int len, cur_pos, ret, instance_id, record_len, version_id;
1956 8a7ddc38 bellard
    int saved_vm_running;
1957 8a7ddc38 bellard
    unsigned int v;
1958 8a7ddc38 bellard
    char idstr[256];
1959 8a7ddc38 bellard
    
1960 8a7ddc38 bellard
    saved_vm_running = vm_running;
1961 8a7ddc38 bellard
    vm_stop(0);
1962 8a7ddc38 bellard
1963 8a7ddc38 bellard
    f = fopen(filename, "rb");
1964 8a7ddc38 bellard
    if (!f) {
1965 8a7ddc38 bellard
        ret = -1;
1966 8a7ddc38 bellard
        goto the_end;
1967 8a7ddc38 bellard
    }
1968 8a7ddc38 bellard
1969 8a7ddc38 bellard
    v = qemu_get_be32(f);
1970 8a7ddc38 bellard
    if (v != QEMU_VM_FILE_MAGIC)
1971 8a7ddc38 bellard
        goto fail;
1972 8a7ddc38 bellard
    v = qemu_get_be32(f);
1973 8a7ddc38 bellard
    if (v != QEMU_VM_FILE_VERSION) {
1974 8a7ddc38 bellard
    fail:
1975 8a7ddc38 bellard
        fclose(f);
1976 8a7ddc38 bellard
        ret = -1;
1977 8a7ddc38 bellard
        goto the_end;
1978 8a7ddc38 bellard
    }
1979 b4608c04 bellard
    for(;;) {
1980 a541f297 bellard
#if defined (DO_TB_FLUSH)
1981 d927637d bellard
        tb_flush(global_env);
1982 a541f297 bellard
#endif
1983 8a7ddc38 bellard
        len = qemu_get_byte(f);
1984 8a7ddc38 bellard
        if (feof(f))
1985 cd4c3e88 bellard
            break;
1986 8a7ddc38 bellard
        qemu_get_buffer(f, idstr, len);
1987 8a7ddc38 bellard
        idstr[len] = '\0';
1988 8a7ddc38 bellard
        instance_id = qemu_get_be32(f);
1989 8a7ddc38 bellard
        version_id = qemu_get_be32(f);
1990 8a7ddc38 bellard
        record_len = qemu_get_be32(f);
1991 8a7ddc38 bellard
#if 0
1992 8a7ddc38 bellard
        printf("idstr=%s instance=0x%x version=%d len=%d\n", 
1993 8a7ddc38 bellard
               idstr, instance_id, version_id, record_len);
1994 8a7ddc38 bellard
#endif
1995 8a7ddc38 bellard
        cur_pos = ftell(f);
1996 8a7ddc38 bellard
        se = find_se(idstr, instance_id);
1997 8a7ddc38 bellard
        if (!se) {
1998 8a7ddc38 bellard
            fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n", 
1999 8a7ddc38 bellard
                    instance_id, idstr);
2000 8a7ddc38 bellard
        } else {
2001 8a7ddc38 bellard
            ret = se->load_state(f, se->opaque, version_id);
2002 8a7ddc38 bellard
            if (ret < 0) {
2003 8a7ddc38 bellard
                fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n", 
2004 8a7ddc38 bellard
                        instance_id, idstr);
2005 8a7ddc38 bellard
            }
2006 34865134 bellard
        }
2007 8a7ddc38 bellard
        /* always seek to exact end of record */
2008 8a7ddc38 bellard
        qemu_fseek(f, cur_pos + record_len, SEEK_SET);
2009 8a7ddc38 bellard
    }
2010 8a7ddc38 bellard
    fclose(f);
2011 8a7ddc38 bellard
    ret = 0;
2012 8a7ddc38 bellard
 the_end:
2013 8a7ddc38 bellard
    if (saved_vm_running)
2014 8a7ddc38 bellard
        vm_start();
2015 8a7ddc38 bellard
    return ret;
2016 8a7ddc38 bellard
}
2017 8a7ddc38 bellard
2018 8a7ddc38 bellard
/***********************************************************/
2019 8a7ddc38 bellard
/* cpu save/restore */
2020 8a7ddc38 bellard
2021 8a7ddc38 bellard
#if defined(TARGET_I386)
2022 8a7ddc38 bellard
2023 8a7ddc38 bellard
static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)
2024 8a7ddc38 bellard
{
2025 02ba45c5 bellard
    qemu_put_be32(f, dt->selector);
2026 8a7ddc38 bellard
    qemu_put_be32(f, (uint32_t)dt->base);
2027 8a7ddc38 bellard
    qemu_put_be32(f, dt->limit);
2028 8a7ddc38 bellard
    qemu_put_be32(f, dt->flags);
2029 8a7ddc38 bellard
}
2030 8a7ddc38 bellard
2031 8a7ddc38 bellard
static void cpu_get_seg(QEMUFile *f, SegmentCache *dt)
2032 8a7ddc38 bellard
{
2033 02ba45c5 bellard
    dt->selector = qemu_get_be32(f);
2034 8a7ddc38 bellard
    dt->base = (uint8_t *)qemu_get_be32(f);
2035 8a7ddc38 bellard
    dt->limit = qemu_get_be32(f);
2036 8a7ddc38 bellard
    dt->flags = qemu_get_be32(f);
2037 8a7ddc38 bellard
}
2038 8a7ddc38 bellard
2039 8a7ddc38 bellard
void cpu_save(QEMUFile *f, void *opaque)
2040 8a7ddc38 bellard
{
2041 8a7ddc38 bellard
    CPUState *env = opaque;
2042 8a7ddc38 bellard
    uint16_t fptag, fpus, fpuc;
2043 8a7ddc38 bellard
    uint32_t hflags;
2044 8a7ddc38 bellard
    int i;
2045 8a7ddc38 bellard
2046 8a7ddc38 bellard
    for(i = 0; i < 8; i++)
2047 8a7ddc38 bellard
        qemu_put_be32s(f, &env->regs[i]);
2048 8a7ddc38 bellard
    qemu_put_be32s(f, &env->eip);
2049 8a7ddc38 bellard
    qemu_put_be32s(f, &env->eflags);
2050 8a7ddc38 bellard
    qemu_put_be32s(f, &env->eflags);
2051 8a7ddc38 bellard
    hflags = env->hflags; /* XXX: suppress most of the redundant hflags */
2052 8a7ddc38 bellard
    qemu_put_be32s(f, &hflags);
2053 8a7ddc38 bellard
    
2054 8a7ddc38 bellard
    /* FPU */
2055 8a7ddc38 bellard
    fpuc = env->fpuc;
2056 8a7ddc38 bellard
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2057 8a7ddc38 bellard
    fptag = 0;
2058 8a7ddc38 bellard
    for (i=7; i>=0; i--) {
2059 8a7ddc38 bellard
        fptag <<= 2;
2060 8a7ddc38 bellard
        if (env->fptags[i]) {
2061 8a7ddc38 bellard
            fptag |= 3;
2062 8a7ddc38 bellard
        }
2063 8a7ddc38 bellard
    }
2064 8a7ddc38 bellard
    
2065 8a7ddc38 bellard
    qemu_put_be16s(f, &fpuc);
2066 8a7ddc38 bellard
    qemu_put_be16s(f, &fpus);
2067 8a7ddc38 bellard
    qemu_put_be16s(f, &fptag);
2068 8a7ddc38 bellard
2069 8a7ddc38 bellard
    for(i = 0; i < 8; i++) {
2070 8a7ddc38 bellard
        uint64_t mant;
2071 8a7ddc38 bellard
        uint16_t exp;
2072 8a7ddc38 bellard
        cpu_get_fp80(&mant, &exp, env->fpregs[i]);
2073 8a7ddc38 bellard
        qemu_put_be64(f, mant);
2074 8a7ddc38 bellard
        qemu_put_be16(f, exp);
2075 8a7ddc38 bellard
    }
2076 8a7ddc38 bellard
2077 8a7ddc38 bellard
    for(i = 0; i < 6; i++)
2078 8a7ddc38 bellard
        cpu_put_seg(f, &env->segs[i]);
2079 8a7ddc38 bellard
    cpu_put_seg(f, &env->ldt);
2080 8a7ddc38 bellard
    cpu_put_seg(f, &env->tr);
2081 8a7ddc38 bellard
    cpu_put_seg(f, &env->gdt);
2082 8a7ddc38 bellard
    cpu_put_seg(f, &env->idt);
2083 8a7ddc38 bellard
    
2084 8a7ddc38 bellard
    qemu_put_be32s(f, &env->sysenter_cs);
2085 8a7ddc38 bellard
    qemu_put_be32s(f, &env->sysenter_esp);
2086 8a7ddc38 bellard
    qemu_put_be32s(f, &env->sysenter_eip);
2087 8a7ddc38 bellard
    
2088 8a7ddc38 bellard
    qemu_put_be32s(f, &env->cr[0]);
2089 8a7ddc38 bellard
    qemu_put_be32s(f, &env->cr[2]);
2090 8a7ddc38 bellard
    qemu_put_be32s(f, &env->cr[3]);
2091 8a7ddc38 bellard
    qemu_put_be32s(f, &env->cr[4]);
2092 8a7ddc38 bellard
    
2093 8a7ddc38 bellard
    for(i = 0; i < 8; i++)
2094 8a7ddc38 bellard
        qemu_put_be32s(f, &env->dr[i]);
2095 8a7ddc38 bellard
2096 8a7ddc38 bellard
    /* MMU */
2097 8a7ddc38 bellard
    qemu_put_be32s(f, &env->a20_mask);
2098 8a7ddc38 bellard
}
2099 8a7ddc38 bellard
2100 8a7ddc38 bellard
int cpu_load(QEMUFile *f, void *opaque, int version_id)
2101 8a7ddc38 bellard
{
2102 8a7ddc38 bellard
    CPUState *env = opaque;
2103 8a7ddc38 bellard
    int i;
2104 8a7ddc38 bellard
    uint32_t hflags;
2105 8a7ddc38 bellard
    uint16_t fpus, fpuc, fptag;
2106 8a7ddc38 bellard
2107 02ba45c5 bellard
    if (version_id != 2)
2108 8a7ddc38 bellard
        return -EINVAL;
2109 8a7ddc38 bellard
    for(i = 0; i < 8; i++)
2110 8a7ddc38 bellard
        qemu_get_be32s(f, &env->regs[i]);
2111 8a7ddc38 bellard
    qemu_get_be32s(f, &env->eip);
2112 8a7ddc38 bellard
    qemu_get_be32s(f, &env->eflags);
2113 8a7ddc38 bellard
    qemu_get_be32s(f, &env->eflags);
2114 8a7ddc38 bellard
    qemu_get_be32s(f, &hflags);
2115 8a7ddc38 bellard
2116 8a7ddc38 bellard
    qemu_get_be16s(f, &fpuc);
2117 8a7ddc38 bellard
    qemu_get_be16s(f, &fpus);
2118 8a7ddc38 bellard
    qemu_get_be16s(f, &fptag);
2119 8a7ddc38 bellard
2120 8a7ddc38 bellard
    for(i = 0; i < 8; i++) {
2121 8a7ddc38 bellard
        uint64_t mant;
2122 8a7ddc38 bellard
        uint16_t exp;
2123 8a7ddc38 bellard
        mant = qemu_get_be64(f);
2124 8a7ddc38 bellard
        exp = qemu_get_be16(f);
2125 8a7ddc38 bellard
        env->fpregs[i] = cpu_set_fp80(mant, exp);
2126 8a7ddc38 bellard
    }
2127 8a7ddc38 bellard
2128 8a7ddc38 bellard
    env->fpuc = fpuc;
2129 8a7ddc38 bellard
    env->fpstt = (fpus >> 11) & 7;
2130 8a7ddc38 bellard
    env->fpus = fpus & ~0x3800;
2131 8a7ddc38 bellard
    for(i = 0; i < 8; i++) {
2132 8a7ddc38 bellard
        env->fptags[i] = ((fptag & 3) == 3);
2133 8a7ddc38 bellard
        fptag >>= 2;
2134 8a7ddc38 bellard
    }
2135 8a7ddc38 bellard
    
2136 8a7ddc38 bellard
    for(i = 0; i < 6; i++)
2137 8a7ddc38 bellard
        cpu_get_seg(f, &env->segs[i]);
2138 8a7ddc38 bellard
    cpu_get_seg(f, &env->ldt);
2139 8a7ddc38 bellard
    cpu_get_seg(f, &env->tr);
2140 8a7ddc38 bellard
    cpu_get_seg(f, &env->gdt);
2141 8a7ddc38 bellard
    cpu_get_seg(f, &env->idt);
2142 8a7ddc38 bellard
    
2143 8a7ddc38 bellard
    qemu_get_be32s(f, &env->sysenter_cs);
2144 8a7ddc38 bellard
    qemu_get_be32s(f, &env->sysenter_esp);
2145 8a7ddc38 bellard
    qemu_get_be32s(f, &env->sysenter_eip);
2146 8a7ddc38 bellard
    
2147 8a7ddc38 bellard
    qemu_get_be32s(f, &env->cr[0]);
2148 8a7ddc38 bellard
    qemu_get_be32s(f, &env->cr[2]);
2149 8a7ddc38 bellard
    qemu_get_be32s(f, &env->cr[3]);
2150 8a7ddc38 bellard
    qemu_get_be32s(f, &env->cr[4]);
2151 8a7ddc38 bellard
    
2152 8a7ddc38 bellard
    for(i = 0; i < 8; i++)
2153 8a7ddc38 bellard
        qemu_get_be32s(f, &env->dr[i]);
2154 8a7ddc38 bellard
2155 8a7ddc38 bellard
    /* MMU */
2156 8a7ddc38 bellard
    qemu_get_be32s(f, &env->a20_mask);
2157 8a7ddc38 bellard
2158 8a7ddc38 bellard
    /* XXX: compute hflags from scratch, except for CPL and IIF */
2159 8a7ddc38 bellard
    env->hflags = hflags;
2160 8a7ddc38 bellard
    tlb_flush(env, 1);
2161 8a7ddc38 bellard
    return 0;
2162 8a7ddc38 bellard
}
2163 8a7ddc38 bellard
2164 a541f297 bellard
#elif defined(TARGET_PPC)
2165 a541f297 bellard
void cpu_save(QEMUFile *f, void *opaque)
2166 a541f297 bellard
{
2167 a541f297 bellard
}
2168 a541f297 bellard
2169 a541f297 bellard
int cpu_load(QEMUFile *f, void *opaque, int version_id)
2170 a541f297 bellard
{
2171 a541f297 bellard
    return 0;
2172 a541f297 bellard
}
2173 e95c8d51 bellard
#elif defined(TARGET_SPARC)
2174 e95c8d51 bellard
void cpu_save(QEMUFile *f, void *opaque)
2175 e95c8d51 bellard
{
2176 e95c8d51 bellard
}
2177 e95c8d51 bellard
2178 e95c8d51 bellard
int cpu_load(QEMUFile *f, void *opaque, int version_id)
2179 e95c8d51 bellard
{
2180 e95c8d51 bellard
    return 0;
2181 e95c8d51 bellard
}
2182 8a7ddc38 bellard
#else
2183 8a7ddc38 bellard
2184 8a7ddc38 bellard
#warning No CPU save/restore functions
2185 8a7ddc38 bellard
2186 8a7ddc38 bellard
#endif
2187 8a7ddc38 bellard
2188 8a7ddc38 bellard
/***********************************************************/
2189 8a7ddc38 bellard
/* ram save/restore */
2190 8a7ddc38 bellard
2191 8a7ddc38 bellard
/* we just avoid storing empty pages */
2192 8a7ddc38 bellard
static void ram_put_page(QEMUFile *f, const uint8_t *buf, int len)
2193 8a7ddc38 bellard
{
2194 8a7ddc38 bellard
    int i, v;
2195 8a7ddc38 bellard
2196 8a7ddc38 bellard
    v = buf[0];
2197 8a7ddc38 bellard
    for(i = 1; i < len; i++) {
2198 8a7ddc38 bellard
        if (buf[i] != v)
2199 8a7ddc38 bellard
            goto normal_save;
2200 8a7ddc38 bellard
    }
2201 8a7ddc38 bellard
    qemu_put_byte(f, 1);
2202 8a7ddc38 bellard
    qemu_put_byte(f, v);
2203 8a7ddc38 bellard
    return;
2204 8a7ddc38 bellard
 normal_save:
2205 8a7ddc38 bellard
    qemu_put_byte(f, 0); 
2206 8a7ddc38 bellard
    qemu_put_buffer(f, buf, len);
2207 8a7ddc38 bellard
}
2208 8a7ddc38 bellard
2209 8a7ddc38 bellard
static int ram_get_page(QEMUFile *f, uint8_t *buf, int len)
2210 8a7ddc38 bellard
{
2211 8a7ddc38 bellard
    int v;
2212 8a7ddc38 bellard
2213 8a7ddc38 bellard
    v = qemu_get_byte(f);
2214 8a7ddc38 bellard
    switch(v) {
2215 8a7ddc38 bellard
    case 0:
2216 8a7ddc38 bellard
        if (qemu_get_buffer(f, buf, len) != len)
2217 8a7ddc38 bellard
            return -EIO;
2218 8a7ddc38 bellard
        break;
2219 8a7ddc38 bellard
    case 1:
2220 8a7ddc38 bellard
        v = qemu_get_byte(f);
2221 8a7ddc38 bellard
        memset(buf, v, len);
2222 8a7ddc38 bellard
        break;
2223 8a7ddc38 bellard
    default:
2224 8a7ddc38 bellard
        return -EINVAL;
2225 8a7ddc38 bellard
    }
2226 8a7ddc38 bellard
    return 0;
2227 8a7ddc38 bellard
}
2228 8a7ddc38 bellard
2229 8a7ddc38 bellard
static void ram_save(QEMUFile *f, void *opaque)
2230 8a7ddc38 bellard
{
2231 8a7ddc38 bellard
    int i;
2232 8a7ddc38 bellard
    qemu_put_be32(f, phys_ram_size);
2233 8a7ddc38 bellard
    for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) {
2234 8a7ddc38 bellard
        ram_put_page(f, phys_ram_base + i, TARGET_PAGE_SIZE);
2235 8a7ddc38 bellard
    }
2236 8a7ddc38 bellard
}
2237 8a7ddc38 bellard
2238 8a7ddc38 bellard
static int ram_load(QEMUFile *f, void *opaque, int version_id)
2239 8a7ddc38 bellard
{
2240 8a7ddc38 bellard
    int i, ret;
2241 8a7ddc38 bellard
2242 8a7ddc38 bellard
    if (version_id != 1)
2243 8a7ddc38 bellard
        return -EINVAL;
2244 8a7ddc38 bellard
    if (qemu_get_be32(f) != phys_ram_size)
2245 8a7ddc38 bellard
        return -EINVAL;
2246 8a7ddc38 bellard
    for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) {
2247 8a7ddc38 bellard
        ret = ram_get_page(f, phys_ram_base + i, TARGET_PAGE_SIZE);
2248 8a7ddc38 bellard
        if (ret)
2249 8a7ddc38 bellard
            return ret;
2250 8a7ddc38 bellard
    }
2251 8a7ddc38 bellard
    return 0;
2252 8a7ddc38 bellard
}
2253 8a7ddc38 bellard
2254 8a7ddc38 bellard
/***********************************************************/
2255 8a7ddc38 bellard
/* main execution loop */
2256 8a7ddc38 bellard
2257 8a7ddc38 bellard
void gui_update(void *opaque)
2258 8a7ddc38 bellard
{
2259 8a7ddc38 bellard
    display_state.dpy_refresh(&display_state);
2260 8a7ddc38 bellard
    qemu_mod_timer(gui_timer, GUI_REFRESH_INTERVAL + qemu_get_clock(rt_clock));
2261 8a7ddc38 bellard
}
2262 8a7ddc38 bellard
2263 8a7ddc38 bellard
/* XXX: support several handlers */
2264 8a7ddc38 bellard
VMStopHandler *vm_stop_cb;
2265 8a7ddc38 bellard
VMStopHandler *vm_stop_opaque;
2266 8a7ddc38 bellard
2267 8a7ddc38 bellard
int qemu_add_vm_stop_handler(VMStopHandler *cb, void *opaque)
2268 8a7ddc38 bellard
{
2269 8a7ddc38 bellard
    vm_stop_cb = cb;
2270 8a7ddc38 bellard
    vm_stop_opaque = opaque;
2271 8a7ddc38 bellard
    return 0;
2272 8a7ddc38 bellard
}
2273 8a7ddc38 bellard
2274 8a7ddc38 bellard
void qemu_del_vm_stop_handler(VMStopHandler *cb, void *opaque)
2275 8a7ddc38 bellard
{
2276 8a7ddc38 bellard
    vm_stop_cb = NULL;
2277 8a7ddc38 bellard
}
2278 8a7ddc38 bellard
2279 8a7ddc38 bellard
void vm_start(void)
2280 8a7ddc38 bellard
{
2281 8a7ddc38 bellard
    if (!vm_running) {
2282 8a7ddc38 bellard
        cpu_enable_ticks();
2283 8a7ddc38 bellard
        vm_running = 1;
2284 8a7ddc38 bellard
    }
2285 8a7ddc38 bellard
}
2286 8a7ddc38 bellard
2287 8a7ddc38 bellard
void vm_stop(int reason) 
2288 8a7ddc38 bellard
{
2289 8a7ddc38 bellard
    if (vm_running) {
2290 8a7ddc38 bellard
        cpu_disable_ticks();
2291 8a7ddc38 bellard
        vm_running = 0;
2292 8a7ddc38 bellard
        if (reason != 0) {
2293 8a7ddc38 bellard
            if (vm_stop_cb) {
2294 8a7ddc38 bellard
                vm_stop_cb(vm_stop_opaque, reason);
2295 8a7ddc38 bellard
            }
2296 34865134 bellard
        }
2297 8a7ddc38 bellard
    }
2298 8a7ddc38 bellard
}
2299 8a7ddc38 bellard
2300 bb0c6722 bellard
/* reset/shutdown handler */
2301 bb0c6722 bellard
2302 bb0c6722 bellard
typedef struct QEMUResetEntry {
2303 bb0c6722 bellard
    QEMUResetHandler *func;
2304 bb0c6722 bellard
    void *opaque;
2305 bb0c6722 bellard
    struct QEMUResetEntry *next;
2306 bb0c6722 bellard
} QEMUResetEntry;
2307 bb0c6722 bellard
2308 bb0c6722 bellard
static QEMUResetEntry *first_reset_entry;
2309 bb0c6722 bellard
static int reset_requested;
2310 bb0c6722 bellard
static int shutdown_requested;
2311 bb0c6722 bellard
2312 bb0c6722 bellard
void qemu_register_reset(QEMUResetHandler *func, void *opaque)
2313 bb0c6722 bellard
{
2314 bb0c6722 bellard
    QEMUResetEntry **pre, *re;
2315 bb0c6722 bellard
2316 bb0c6722 bellard
    pre = &first_reset_entry;
2317 bb0c6722 bellard
    while (*pre != NULL)
2318 bb0c6722 bellard
        pre = &(*pre)->next;
2319 bb0c6722 bellard
    re = qemu_mallocz(sizeof(QEMUResetEntry));
2320 bb0c6722 bellard
    re->func = func;
2321 bb0c6722 bellard
    re->opaque = opaque;
2322 bb0c6722 bellard
    re->next = NULL;
2323 bb0c6722 bellard
    *pre = re;
2324 bb0c6722 bellard
}
2325 bb0c6722 bellard
2326 bb0c6722 bellard
void qemu_system_reset(void)
2327 bb0c6722 bellard
{
2328 bb0c6722 bellard
    QEMUResetEntry *re;
2329 bb0c6722 bellard
2330 bb0c6722 bellard
    /* reset all devices */
2331 bb0c6722 bellard
    for(re = first_reset_entry; re != NULL; re = re->next) {
2332 bb0c6722 bellard
        re->func(re->opaque);
2333 bb0c6722 bellard
    }
2334 bb0c6722 bellard
}
2335 bb0c6722 bellard
2336 bb0c6722 bellard
void qemu_system_reset_request(void)
2337 bb0c6722 bellard
{
2338 bb0c6722 bellard
    reset_requested = 1;
2339 bb0c6722 bellard
    cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
2340 bb0c6722 bellard
}
2341 bb0c6722 bellard
2342 bb0c6722 bellard
void qemu_system_shutdown_request(void)
2343 bb0c6722 bellard
{
2344 bb0c6722 bellard
    shutdown_requested = 1;
2345 bb0c6722 bellard
    cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
2346 bb0c6722 bellard
}
2347 bb0c6722 bellard
2348 bb0c6722 bellard
static void main_cpu_reset(void *opaque)
2349 bb0c6722 bellard
{
2350 bb0c6722 bellard
#ifdef TARGET_I386
2351 bb0c6722 bellard
    CPUState *env = opaque;
2352 bb0c6722 bellard
    cpu_reset(env);
2353 bb0c6722 bellard
#endif
2354 bb0c6722 bellard
}
2355 bb0c6722 bellard
2356 5905b2e5 bellard
void main_loop_wait(int timeout)
2357 8a7ddc38 bellard
{
2358 67b915a5 bellard
#ifndef _WIN32
2359 8a7ddc38 bellard
    struct pollfd ufds[MAX_IO_HANDLERS + 1], *pf;
2360 8a7ddc38 bellard
    IOHandlerRecord *ioh, *ioh_next;
2361 67b915a5 bellard
    uint8_t buf[4096];
2362 67b915a5 bellard
    int n, max_size;
2363 67b915a5 bellard
#endif
2364 5905b2e5 bellard
    int ret;
2365 c4b1fcc0 bellard
2366 38e205a2 bellard
#ifdef _WIN32
2367 38e205a2 bellard
        if (timeout > 0)
2368 38e205a2 bellard
            Sleep(timeout);
2369 38e205a2 bellard
#else
2370 b4608c04 bellard
        /* poll any events */
2371 8a7ddc38 bellard
        /* XXX: separate device handlers from system ones */
2372 b4608c04 bellard
        pf = ufds;
2373 8a7ddc38 bellard
        for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) {
2374 8a7ddc38 bellard
            if (!ioh->fd_can_read) {
2375 8a7ddc38 bellard
                max_size = 0;
2376 c4b1fcc0 bellard
                pf->fd = ioh->fd;
2377 c4b1fcc0 bellard
                pf->events = POLLIN;
2378 c4b1fcc0 bellard
                ioh->ufd = pf;
2379 c4b1fcc0 bellard
                pf++;
2380 c4b1fcc0 bellard
            } else {
2381 8a7ddc38 bellard
                max_size = ioh->fd_can_read(ioh->opaque);
2382 8a7ddc38 bellard
                if (max_size > 0) {
2383 8a7ddc38 bellard
                    if (max_size > sizeof(buf))
2384 8a7ddc38 bellard
                        max_size = sizeof(buf);
2385 8a7ddc38 bellard
                    pf->fd = ioh->fd;
2386 8a7ddc38 bellard
                    pf->events = POLLIN;
2387 8a7ddc38 bellard
                    ioh->ufd = pf;
2388 8a7ddc38 bellard
                    pf++;
2389 8a7ddc38 bellard
                } else {
2390 8a7ddc38 bellard
                    ioh->ufd = NULL;
2391 8a7ddc38 bellard
                }
2392 c4b1fcc0 bellard
            }
2393 c4b1fcc0 bellard
            ioh->max_size = max_size;
2394 b4608c04 bellard
        }
2395 73332e5c bellard
        
2396 b4608c04 bellard
        ret = poll(ufds, pf - ufds, timeout);
2397 b4608c04 bellard
        if (ret > 0) {
2398 8a7ddc38 bellard
            /* XXX: better handling of removal */
2399 8a7ddc38 bellard
            for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) {
2400 8a7ddc38 bellard
                ioh_next = ioh->next;
2401 c4b1fcc0 bellard
                pf = ioh->ufd;
2402 c4b1fcc0 bellard
                if (pf) {
2403 8a7ddc38 bellard
                    if (pf->revents & POLLIN) {
2404 8a7ddc38 bellard
                        if (ioh->max_size == 0) {
2405 8a7ddc38 bellard
                            /* just a read event */
2406 8a7ddc38 bellard
                            ioh->fd_read(ioh->opaque, NULL, 0);
2407 8a7ddc38 bellard
                        } else {
2408 8a7ddc38 bellard
                            n = read(ioh->fd, buf, ioh->max_size);
2409 8a7ddc38 bellard
                            if (n >= 0) {
2410 8a7ddc38 bellard
                                ioh->fd_read(ioh->opaque, buf, n);
2411 158156d1 bellard
                            } else if (errno != EAGAIN) {
2412 8a7ddc38 bellard
                                ioh->fd_read(ioh->opaque, NULL, -errno);
2413 8a7ddc38 bellard
                            }
2414 8a7ddc38 bellard
                        }
2415 b4608c04 bellard
                    }
2416 b4608c04 bellard
                }
2417 b4608c04 bellard
            }
2418 b4608c04 bellard
        }
2419 5905b2e5 bellard
#endif /* !defined(_WIN32) */
2420 c20709aa bellard
#if defined(CONFIG_SLIRP)
2421 c20709aa bellard
        /* XXX: merge with poll() */
2422 c20709aa bellard
        if (slirp_inited) {
2423 c20709aa bellard
            fd_set rfds, wfds, xfds;
2424 c20709aa bellard
            int nfds;
2425 c20709aa bellard
            struct timeval tv;
2426 c20709aa bellard
2427 c20709aa bellard
            nfds = -1;
2428 c20709aa bellard
            FD_ZERO(&rfds);
2429 c20709aa bellard
            FD_ZERO(&wfds);
2430 c20709aa bellard
            FD_ZERO(&xfds);
2431 c20709aa bellard
            slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
2432 c20709aa bellard
            tv.tv_sec = 0;
2433 c20709aa bellard
            tv.tv_usec = 0;
2434 c20709aa bellard
            ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
2435 c20709aa bellard
            if (ret >= 0) {
2436 c20709aa bellard
                slirp_select_poll(&rfds, &wfds, &xfds);
2437 c20709aa bellard
            }
2438 c20709aa bellard
        }
2439 c20709aa bellard
#endif
2440 c20709aa bellard
2441 8a7ddc38 bellard
        if (vm_running) {
2442 8a7ddc38 bellard
            qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], 
2443 8a7ddc38 bellard
                            qemu_get_clock(vm_clock));
2444 8a7ddc38 bellard
            /* run dma transfers, if any */
2445 8a7ddc38 bellard
            DMA_run();
2446 b4608c04 bellard
        }
2447 313aa567 bellard
2448 8a7ddc38 bellard
        /* real time timers */
2449 8a7ddc38 bellard
        qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME], 
2450 8a7ddc38 bellard
                        qemu_get_clock(rt_clock));
2451 5905b2e5 bellard
}
2452 5905b2e5 bellard
2453 5905b2e5 bellard
int main_loop(void)
2454 5905b2e5 bellard
{
2455 5905b2e5 bellard
    int ret, timeout;
2456 5905b2e5 bellard
    CPUState *env = global_env;
2457 5905b2e5 bellard
2458 5905b2e5 bellard
    for(;;) {
2459 5905b2e5 bellard
        if (vm_running) {
2460 5905b2e5 bellard
            ret = cpu_exec(env);
2461 5905b2e5 bellard
            if (shutdown_requested) {
2462 5905b2e5 bellard
                ret = EXCP_INTERRUPT; 
2463 5905b2e5 bellard
                break;
2464 5905b2e5 bellard
            }
2465 5905b2e5 bellard
            if (reset_requested) {
2466 5905b2e5 bellard
                reset_requested = 0;
2467 5905b2e5 bellard
                qemu_system_reset();
2468 5905b2e5 bellard
                ret = EXCP_INTERRUPT; 
2469 5905b2e5 bellard
            }
2470 5905b2e5 bellard
            if (ret == EXCP_DEBUG) {
2471 5905b2e5 bellard
                vm_stop(EXCP_DEBUG);
2472 5905b2e5 bellard
            }
2473 5905b2e5 bellard
            /* if hlt instruction, we wait until the next IRQ */
2474 5905b2e5 bellard
            /* XXX: use timeout computed from timers */
2475 5905b2e5 bellard
            if (ret == EXCP_HLT) 
2476 5905b2e5 bellard
                timeout = 10;
2477 5905b2e5 bellard
            else
2478 5905b2e5 bellard
                timeout = 0;
2479 5905b2e5 bellard
        } else {
2480 5905b2e5 bellard
            timeout = 10;
2481 5905b2e5 bellard
        }
2482 5905b2e5 bellard
        main_loop_wait(timeout);
2483 b4608c04 bellard
    }
2484 34865134 bellard
    cpu_disable_ticks();
2485 34865134 bellard
    return ret;
2486 b4608c04 bellard
}
2487 b4608c04 bellard
2488 0824d6fc bellard
void help(void)
2489 0824d6fc bellard
{
2490 aaaa7df6 bellard
    printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
2491 0db63474 bellard
           "usage: %s [options] [disk_image]\n"
2492 0824d6fc bellard
           "\n"
2493 a20dd508 bellard
           "'disk_image' is a raw hard image image for IDE hard disk 0\n"
2494 fc01f7e7 bellard
           "\n"
2495 a20dd508 bellard
           "Standard options:\n"
2496 c45886db bellard
           "-fda/-fdb file  use 'file' as floppy disk 0/1 image\n"
2497 36b486bb bellard
           "-hda/-hdb file  use 'file' as IDE hard disk 0/1 image\n"
2498 36b486bb bellard
           "-hdc/-hdd file  use 'file' as IDE hard disk 2/3 image\n"
2499 c4b1fcc0 bellard
           "-cdrom file     use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
2500 9e89a4be bellard
           "-boot [a|c|d]   boot on floppy (a), hard disk (c) or CD-ROM (d)\n"
2501 a20dd508 bellard
           "-snapshot       write to temporary files instead of disk image files\n"
2502 a00bad7e bellard
           "-m megs         set virtual RAM size to megs MB [default=%d]\n"
2503 c4b1fcc0 bellard
           "-nographic      disable graphical output and redirect serial I/Os to console\n"
2504 aaaa7df6 bellard
           "-enable-audio   enable audio support\n"
2505 89980284 bellard
           "-localtime      set the real time clock to local time [default=utc]\n"
2506 d63d307f bellard
           "-full-screen    start in full screen\n"
2507 bb0c6722 bellard
#ifdef TARGET_PPC
2508 bb0c6722 bellard
           "-prep           Simulate a PREP system (default is PowerMAC)\n"
2509 e9b137c2 bellard
           "-g WxH[xDEPTH]  Set the initial VGA graphic mode\n"
2510 bb0c6722 bellard
#endif
2511 c4b1fcc0 bellard
           "\n"
2512 c4b1fcc0 bellard
           "Network options:\n"
2513 c20709aa bellard
           "-nics n         simulate 'n' network cards [default=1]\n"
2514 702c651c bellard
           "-macaddr addr   set the mac address of the first interface\n"
2515 c20709aa bellard
           "-n script       set tap/tun network init script [default=%s]\n"
2516 c20709aa bellard
           "-tun-fd fd      use this fd as already opened tap/tun interface\n"
2517 c20709aa bellard
#ifdef CONFIG_SLIRP
2518 c20709aa bellard
           "-user-net       use user mode network stack [default if no tap/tun script]\n"
2519 9bf05444 bellard
           "-tftp prefix    allow tftp access to files starting with prefix [-user-net]\n"
2520 c94c8d64 bellard
#ifndef _WIN32
2521 9d728e8c bellard
           "-smb dir        allow SMB access to files in 'dir' [-user-net]\n"
2522 c94c8d64 bellard
#endif
2523 9bf05444 bellard
           "-redir [tcp|udp]:host-port:[guest-host]:guest-port\n"
2524 9bf05444 bellard
           "                redirect TCP or UDP connections from host to guest [-user-net]\n"
2525 c20709aa bellard
#endif
2526 c20709aa bellard
           "-dummy-net      use dummy network stack\n"
2527 a20dd508 bellard
           "\n"
2528 c4b1fcc0 bellard
           "Linux boot specific:\n"
2529 a20dd508 bellard
           "-kernel bzImage use 'bzImage' as kernel image\n"
2530 a20dd508 bellard
           "-append cmdline use 'cmdline' as kernel command line\n"
2531 a20dd508 bellard
           "-initrd file    use 'file' as initial ram disk\n"
2532 fc01f7e7 bellard
           "\n"
2533 330d0414 bellard
           "Debug/Expert options:\n"
2534 82c643ff bellard
           "-monitor dev    redirect the monitor to char device 'dev'\n"
2535 82c643ff bellard
           "-serial dev     redirect the serial port to char device 'dev'\n"
2536 cd6f1169 bellard
           "-S              freeze CPU at startup (use 'c' to start execution)\n"
2537 a20dd508 bellard
           "-s              wait gdb connection to port %d\n"
2538 a20dd508 bellard
           "-p port         change gdb connection port\n"
2539 f193c797 bellard
           "-d item1,...    output log to %s (use -d ? for a list of log items)\n"
2540 a20dd508 bellard
           "-hdachs c,h,s   force hard disk 0 geometry (usually qemu can guess it)\n"
2541 a20dd508 bellard
           "-L path         set the directory for the BIOS and VGA BIOS\n"
2542 77fef8c1 bellard
#ifdef USE_CODE_COPY
2543 77fef8c1 bellard
           "-no-code-copy   disable code copy acceleration\n"
2544 77fef8c1 bellard
#endif
2545 bb0c6722 bellard
#ifdef TARGET_I386
2546 bb0c6722 bellard
           "-isa            simulate an ISA-only system (default is PCI system)\n"
2547 1bfe856e bellard
           "-std-vga        simulate a standard VGA card with VESA Bochs Extensions\n"
2548 1bfe856e bellard
           "                (default is CL-GD5446 PCI VGA)\n"
2549 bb0c6722 bellard
#endif
2550 d63d307f bellard
           "-loadvm file    start right away with a saved state (loadvm in monitor)\n"
2551 0824d6fc bellard
           "\n"
2552 82c643ff bellard
           "During emulation, the following keys are useful:\n"
2553 032a8c9e bellard
           "ctrl-alt-f      toggle full screen\n"
2554 032a8c9e bellard
           "ctrl-alt-n      switch to virtual console 'n'\n"
2555 032a8c9e bellard
           "ctrl-alt        toggle mouse and keyboard grab\n"
2556 82c643ff bellard
           "\n"
2557 82c643ff bellard
           "When using -nographic, press 'ctrl-a h' to get some help.\n"
2558 82c643ff bellard
           ,
2559 0db63474 bellard
#ifdef CONFIG_SOFTMMU
2560 0db63474 bellard
           "qemu",
2561 0db63474 bellard
#else
2562 0db63474 bellard
           "qemu-fast",
2563 0db63474 bellard
#endif
2564 a00bad7e bellard
           DEFAULT_RAM_SIZE,
2565 a00bad7e bellard
           DEFAULT_NETWORK_SCRIPT,
2566 6e44ba7f bellard
           DEFAULT_GDBSTUB_PORT,
2567 6e44ba7f bellard
           "/tmp/qemu.log");
2568 0db63474 bellard
#ifndef CONFIG_SOFTMMU
2569 0db63474 bellard
    printf("\n"
2570 0db63474 bellard
           "NOTE: this version of QEMU is faster but it needs slightly patched OSes to\n"
2571 0db63474 bellard
           "work. Please use the 'qemu' executable to have a more accurate (but slower)\n"
2572 0db63474 bellard
           "PC emulation.\n");
2573 0db63474 bellard
#endif
2574 0824d6fc bellard
    exit(1);
2575 0824d6fc bellard
}
2576 0824d6fc bellard
2577 cd6f1169 bellard
#define HAS_ARG 0x0001
2578 cd6f1169 bellard
2579 cd6f1169 bellard
enum {
2580 cd6f1169 bellard
    QEMU_OPTION_h,
2581 cd6f1169 bellard
2582 cd6f1169 bellard
    QEMU_OPTION_fda,
2583 cd6f1169 bellard
    QEMU_OPTION_fdb,
2584 cd6f1169 bellard
    QEMU_OPTION_hda,
2585 cd6f1169 bellard
    QEMU_OPTION_hdb,
2586 cd6f1169 bellard
    QEMU_OPTION_hdc,
2587 cd6f1169 bellard
    QEMU_OPTION_hdd,
2588 cd6f1169 bellard
    QEMU_OPTION_cdrom,
2589 cd6f1169 bellard
    QEMU_OPTION_boot,
2590 cd6f1169 bellard
    QEMU_OPTION_snapshot,
2591 cd6f1169 bellard
    QEMU_OPTION_m,
2592 cd6f1169 bellard
    QEMU_OPTION_nographic,
2593 cd6f1169 bellard
    QEMU_OPTION_enable_audio,
2594 cd6f1169 bellard
2595 cd6f1169 bellard
    QEMU_OPTION_nics,
2596 cd6f1169 bellard
    QEMU_OPTION_macaddr,
2597 cd6f1169 bellard
    QEMU_OPTION_n,
2598 cd6f1169 bellard
    QEMU_OPTION_tun_fd,
2599 cd6f1169 bellard
    QEMU_OPTION_user_net,
2600 c7f74643 bellard
    QEMU_OPTION_tftp,
2601 9d728e8c bellard
    QEMU_OPTION_smb,
2602 9bf05444 bellard
    QEMU_OPTION_redir,
2603 cd6f1169 bellard
    QEMU_OPTION_dummy_net,
2604 cd6f1169 bellard
2605 cd6f1169 bellard
    QEMU_OPTION_kernel,
2606 cd6f1169 bellard
    QEMU_OPTION_append,
2607 cd6f1169 bellard
    QEMU_OPTION_initrd,
2608 cd6f1169 bellard
2609 cd6f1169 bellard
    QEMU_OPTION_S,
2610 cd6f1169 bellard
    QEMU_OPTION_s,
2611 cd6f1169 bellard
    QEMU_OPTION_p,
2612 cd6f1169 bellard
    QEMU_OPTION_d,
2613 cd6f1169 bellard
    QEMU_OPTION_hdachs,
2614 cd6f1169 bellard
    QEMU_OPTION_L,
2615 cd6f1169 bellard
    QEMU_OPTION_no_code_copy,
2616 69b91039 bellard
    QEMU_OPTION_pci,
2617 bb0c6722 bellard
    QEMU_OPTION_isa,
2618 77d4bc34 bellard
    QEMU_OPTION_prep,
2619 ee22c2f7 bellard
    QEMU_OPTION_localtime,
2620 1f04275e bellard
    QEMU_OPTION_cirrusvga,
2621 e9b137c2 bellard
    QEMU_OPTION_g,
2622 1bfe856e bellard
    QEMU_OPTION_std_vga,
2623 82c643ff bellard
    QEMU_OPTION_monitor,
2624 82c643ff bellard
    QEMU_OPTION_serial,
2625 d63d307f bellard
    QEMU_OPTION_loadvm,
2626 d63d307f bellard
    QEMU_OPTION_full_screen,
2627 cd6f1169 bellard
};
2628 cd6f1169 bellard
2629 cd6f1169 bellard
typedef struct QEMUOption {
2630 cd6f1169 bellard
    const char *name;
2631 cd6f1169 bellard
    int flags;
2632 cd6f1169 bellard
    int index;
2633 cd6f1169 bellard
} QEMUOption;
2634 cd6f1169 bellard
2635 cd6f1169 bellard
const QEMUOption qemu_options[] = {
2636 cd6f1169 bellard
    { "h", 0, QEMU_OPTION_h },
2637 cd6f1169 bellard
2638 cd6f1169 bellard
    { "fda", HAS_ARG, QEMU_OPTION_fda },
2639 cd6f1169 bellard
    { "fdb", HAS_ARG, QEMU_OPTION_fdb },
2640 cd6f1169 bellard
    { "hda", HAS_ARG, QEMU_OPTION_hda },
2641 cd6f1169 bellard
    { "hdb", HAS_ARG, QEMU_OPTION_hdb },
2642 cd6f1169 bellard
    { "hdc", HAS_ARG, QEMU_OPTION_hdc },
2643 cd6f1169 bellard
    { "hdd", HAS_ARG, QEMU_OPTION_hdd },
2644 cd6f1169 bellard
    { "cdrom", HAS_ARG, QEMU_OPTION_cdrom },
2645 cd6f1169 bellard
    { "boot", HAS_ARG, QEMU_OPTION_boot },
2646 cd6f1169 bellard
    { "snapshot", 0, QEMU_OPTION_snapshot },
2647 cd6f1169 bellard
    { "m", HAS_ARG, QEMU_OPTION_m },
2648 cd6f1169 bellard
    { "nographic", 0, QEMU_OPTION_nographic },
2649 cd6f1169 bellard
    { "enable-audio", 0, QEMU_OPTION_enable_audio },
2650 cd6f1169 bellard
2651 cd6f1169 bellard
    { "nics", HAS_ARG, QEMU_OPTION_nics},
2652 cd6f1169 bellard
    { "macaddr", HAS_ARG, QEMU_OPTION_macaddr},
2653 69b91039 bellard
    { "n", HAS_ARG, QEMU_OPTION_n },
2654 cd6f1169 bellard
    { "tun-fd", HAS_ARG, QEMU_OPTION_tun_fd },
2655 158156d1 bellard
#ifdef CONFIG_SLIRP
2656 cd6f1169 bellard
    { "user-net", 0, QEMU_OPTION_user_net },
2657 c7f74643 bellard
    { "tftp", HAS_ARG, QEMU_OPTION_tftp },
2658 c94c8d64 bellard
#ifndef _WIN32
2659 9d728e8c bellard
    { "smb", HAS_ARG, QEMU_OPTION_smb },
2660 c94c8d64 bellard
#endif
2661 9bf05444 bellard
    { "redir", HAS_ARG, QEMU_OPTION_redir },
2662 158156d1 bellard
#endif
2663 cd6f1169 bellard
    { "dummy-net", 0, QEMU_OPTION_dummy_net },
2664 cd6f1169 bellard
2665 cd6f1169 bellard
    { "kernel", HAS_ARG, QEMU_OPTION_kernel },
2666 cd6f1169 bellard
    { "append", HAS_ARG, QEMU_OPTION_append },
2667 cd6f1169 bellard
    { "initrd", HAS_ARG, QEMU_OPTION_initrd },
2668 cd6f1169 bellard
2669 cd6f1169 bellard
    { "S", 0, QEMU_OPTION_S },
2670 cd6f1169 bellard
    { "s", 0, QEMU_OPTION_s },
2671 cd6f1169 bellard
    { "p", HAS_ARG, QEMU_OPTION_p },
2672 cd6f1169 bellard
    { "d", HAS_ARG, QEMU_OPTION_d },
2673 cd6f1169 bellard
    { "hdachs", HAS_ARG, QEMU_OPTION_hdachs },
2674 cd6f1169 bellard
    { "L", HAS_ARG, QEMU_OPTION_L },
2675 cd6f1169 bellard
    { "no-code-copy", 0, QEMU_OPTION_no_code_copy },
2676 77d4bc34 bellard
#ifdef TARGET_PPC
2677 77d4bc34 bellard
    { "prep", 0, QEMU_OPTION_prep },
2678 e9b137c2 bellard
    { "g", 1, QEMU_OPTION_g },
2679 77d4bc34 bellard
#endif
2680 ee22c2f7 bellard
    { "localtime", 0, QEMU_OPTION_localtime },
2681 bb0c6722 bellard
    { "isa", 0, QEMU_OPTION_isa },
2682 1bfe856e bellard
    { "std-vga", 0, QEMU_OPTION_std_vga },
2683 82c643ff bellard
    { "monitor", 1, QEMU_OPTION_monitor },
2684 82c643ff bellard
    { "serial", 1, QEMU_OPTION_serial },
2685 d63d307f bellard
    { "loadvm", HAS_ARG, QEMU_OPTION_loadvm },
2686 d63d307f bellard
    { "full-screen", 0, QEMU_OPTION_full_screen },
2687 82c643ff bellard
    
2688 1f04275e bellard
    /* temporary options */
2689 1f04275e bellard
    { "pci", 0, QEMU_OPTION_pci },
2690 1f04275e bellard
    { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
2691 cd6f1169 bellard
    { NULL },
2692 fc01f7e7 bellard
};
2693 fc01f7e7 bellard
2694 77fef8c1 bellard
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
2695 77fef8c1 bellard
2696 77fef8c1 bellard
/* this stack is only used during signal handling */
2697 77fef8c1 bellard
#define SIGNAL_STACK_SIZE 32768
2698 77fef8c1 bellard
2699 77fef8c1 bellard
static uint8_t *signal_stack;
2700 77fef8c1 bellard
2701 77fef8c1 bellard
#endif
2702 77fef8c1 bellard
2703 5905b2e5 bellard
/* password input */
2704 5905b2e5 bellard
2705 5905b2e5 bellard
static BlockDriverState *get_bdrv(int index)
2706 5905b2e5 bellard
{
2707 5905b2e5 bellard
    BlockDriverState *bs;
2708 5905b2e5 bellard
2709 5905b2e5 bellard
    if (index < 4) {
2710 5905b2e5 bellard
        bs = bs_table[index];
2711 5905b2e5 bellard
    } else if (index < 6) {
2712 5905b2e5 bellard
        bs = fd_table[index - 4];
2713 5905b2e5 bellard
    } else {
2714 5905b2e5 bellard
        bs = NULL;
2715 5905b2e5 bellard
    }
2716 5905b2e5 bellard
    return bs;
2717 5905b2e5 bellard
}
2718 5905b2e5 bellard
2719 5905b2e5 bellard
static void read_passwords(void)
2720 5905b2e5 bellard
{
2721 5905b2e5 bellard
    BlockDriverState *bs;
2722 5905b2e5 bellard
    int i, j;
2723 5905b2e5 bellard
    char password[256];
2724 5905b2e5 bellard
2725 5905b2e5 bellard
    for(i = 0; i < 6; i++) {
2726 5905b2e5 bellard
        bs = get_bdrv(i);
2727 5905b2e5 bellard
        if (bs && bdrv_is_encrypted(bs)) {
2728 5905b2e5 bellard
            term_printf("%s is encrypted.\n", bdrv_get_device_name(bs));
2729 5905b2e5 bellard
            for(j = 0; j < 3; j++) {
2730 5905b2e5 bellard
                monitor_readline("Password: ", 
2731 5905b2e5 bellard
                                 1, password, sizeof(password));
2732 5905b2e5 bellard
                if (bdrv_set_key(bs, password) == 0)
2733 5905b2e5 bellard
                    break;
2734 5905b2e5 bellard
                term_printf("invalid password\n");
2735 5905b2e5 bellard
            }
2736 5905b2e5 bellard
        }
2737 5905b2e5 bellard
    }
2738 5905b2e5 bellard
}
2739 5905b2e5 bellard
2740 c20709aa bellard
#define NET_IF_TUN   0
2741 c20709aa bellard
#define NET_IF_USER  1
2742 c20709aa bellard
#define NET_IF_DUMMY 2
2743 c20709aa bellard
2744 0824d6fc bellard
int main(int argc, char **argv)
2745 0824d6fc bellard
{
2746 67b915a5 bellard
#ifdef CONFIG_GDBSTUB
2747 67b915a5 bellard
    int use_gdbstub, gdbstub_port;
2748 67b915a5 bellard
#endif
2749 cd6f1169 bellard
    int i, has_cdrom;
2750 1ccde1cb bellard
    int snapshot, linux_boot;
2751 c45886db bellard
    CPUState *env;
2752 7f7f9873 bellard
    const char *initrd_filename;
2753 c45886db bellard
    const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
2754 a20dd508 bellard
    const char *kernel_filename, *kernel_cmdline;
2755 313aa567 bellard
    DisplayState *ds = &display_state;
2756 c4b1fcc0 bellard
    int cyls, heads, secs;
2757 a541f297 bellard
    int start_emulation = 1;
2758 702c651c bellard
    uint8_t macaddr[6];
2759 c20709aa bellard
    int net_if_type, nb_tun_fds, tun_fds[MAX_NICS];
2760 cd6f1169 bellard
    int optind;
2761 cd6f1169 bellard
    const char *r, *optarg;
2762 82c643ff bellard
    CharDriverState *monitor_hd;
2763 82c643ff bellard
    char monitor_device[128];
2764 8d11df9e bellard
    char serial_devices[MAX_SERIAL_PORTS][128];
2765 8d11df9e bellard
    int serial_device_index;
2766 d63d307f bellard
    const char *loadvm = NULL;
2767 8d11df9e bellard
    
2768 67b915a5 bellard
#if !defined(CONFIG_SOFTMMU)
2769 0824d6fc bellard
    /* we never want that malloc() uses mmap() */
2770 0824d6fc bellard
    mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
2771 67b915a5 bellard
#endif
2772 fc01f7e7 bellard
    initrd_filename = NULL;
2773 c45886db bellard
    for(i = 0; i < MAX_FD; i++)
2774 c45886db bellard
        fd_filename[i] = NULL;
2775 fc01f7e7 bellard
    for(i = 0; i < MAX_DISKS; i++)
2776 fc01f7e7 bellard
        hd_filename[i] = NULL;
2777 a00bad7e bellard
    ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
2778 313aa567 bellard
    vga_ram_size = VGA_RAM_SIZE;
2779 0ced6589 bellard
    bios_size = BIOS_SIZE;
2780 f1510b2c bellard
    pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT);
2781 67b915a5 bellard
#ifdef CONFIG_GDBSTUB
2782 b4608c04 bellard
    use_gdbstub = 0;
2783 b4608c04 bellard
    gdbstub_port = DEFAULT_GDBSTUB_PORT;
2784 67b915a5 bellard
#endif
2785 33e3963e bellard
    snapshot = 0;
2786 a20dd508 bellard
    nographic = 0;
2787 a20dd508 bellard
    kernel_filename = NULL;
2788 a20dd508 bellard
    kernel_cmdline = "";
2789 c4b1fcc0 bellard
    has_cdrom = 1;
2790 c4b1fcc0 bellard
    cyls = heads = secs = 0;
2791 82c643ff bellard
    pstrcpy(monitor_device, sizeof(monitor_device), "vc");
2792 c4b1fcc0 bellard
2793 8d11df9e bellard
    pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "vc");
2794 8d11df9e bellard
    for(i = 1; i < MAX_SERIAL_PORTS; i++)
2795 8d11df9e bellard
        serial_devices[i][0] = '\0';
2796 8d11df9e bellard
    serial_device_index = 0;
2797 8d11df9e bellard
    
2798 c20709aa bellard
    nb_tun_fds = 0;
2799 c20709aa bellard
    net_if_type = -1;
2800 c4b1fcc0 bellard
    nb_nics = 1;
2801 702c651c bellard
    /* default mac address of the first network interface */
2802 702c651c bellard
    macaddr[0] = 0x52;
2803 702c651c bellard
    macaddr[1] = 0x54;
2804 702c651c bellard
    macaddr[2] = 0x00;
2805 702c651c bellard
    macaddr[3] = 0x12;
2806 702c651c bellard
    macaddr[4] = 0x34;
2807 702c651c bellard
    macaddr[5] = 0x56;
2808 82c643ff bellard
    
2809 cd6f1169 bellard
    optind = 1;
2810 0824d6fc bellard
    for(;;) {
2811 cd6f1169 bellard
        if (optind >= argc)
2812 0824d6fc bellard
            break;
2813 cd6f1169 bellard
        r = argv[optind];
2814 cd6f1169 bellard
        if (r[0] != '-') {
2815 cd6f1169 bellard
            hd_filename[0] = argv[optind++];
2816 cd6f1169 bellard
        } else {
2817 cd6f1169 bellard
            const QEMUOption *popt;
2818 cd6f1169 bellard
2819 cd6f1169 bellard
            optind++;
2820 cd6f1169 bellard
            popt = qemu_options;
2821 cd6f1169 bellard
            for(;;) {
2822 cd6f1169 bellard
                if (!popt->name) {
2823 cd6f1169 bellard
                    fprintf(stderr, "%s: invalid option -- '%s'\n", 
2824 cd6f1169 bellard
                            argv[0], r);
2825 cd6f1169 bellard
                    exit(1);
2826 cd6f1169 bellard
                }
2827 cd6f1169 bellard
                if (!strcmp(popt->name, r + 1))
2828 cd6f1169 bellard
                    break;
2829 cd6f1169 bellard
                popt++;
2830 cd6f1169 bellard
            }
2831 cd6f1169 bellard
            if (popt->flags & HAS_ARG) {
2832 cd6f1169 bellard
                if (optind >= argc) {
2833 cd6f1169 bellard
                    fprintf(stderr, "%s: option '%s' requires an argument\n",
2834 cd6f1169 bellard
                            argv[0], r);
2835 cd6f1169 bellard
                    exit(1);
2836 cd6f1169 bellard
                }
2837 cd6f1169 bellard
                optarg = argv[optind++];
2838 cd6f1169 bellard
            } else {
2839 cd6f1169 bellard
                optarg = NULL;
2840 cd6f1169 bellard
            }
2841 cd6f1169 bellard
2842 cd6f1169 bellard
            switch(popt->index) {
2843 cd6f1169 bellard
            case QEMU_OPTION_initrd:
2844 fc01f7e7 bellard
                initrd_filename = optarg;
2845 fc01f7e7 bellard
                break;
2846 cd6f1169 bellard
            case QEMU_OPTION_hda:
2847 fc01f7e7 bellard
                hd_filename[0] = optarg;
2848 fc01f7e7 bellard
                break;
2849 cd6f1169 bellard
            case QEMU_OPTION_hdb:
2850 fc01f7e7 bellard
                hd_filename[1] = optarg;
2851 fc01f7e7 bellard
                break;
2852 cd6f1169 bellard
            case QEMU_OPTION_snapshot:
2853 33e3963e bellard
                snapshot = 1;
2854 33e3963e bellard
                break;
2855 cd6f1169 bellard
            case QEMU_OPTION_hdachs:
2856 330d0414 bellard
                {
2857 330d0414 bellard
                    const char *p;
2858 330d0414 bellard
                    p = optarg;
2859 330d0414 bellard
                    cyls = strtol(p, (char **)&p, 0);
2860 330d0414 bellard
                    if (*p != ',')
2861 330d0414 bellard
                        goto chs_fail;
2862 330d0414 bellard
                    p++;
2863 330d0414 bellard
                    heads = strtol(p, (char **)&p, 0);
2864 330d0414 bellard
                    if (*p != ',')
2865 330d0414 bellard
                        goto chs_fail;
2866 330d0414 bellard
                    p++;
2867 330d0414 bellard
                    secs = strtol(p, (char **)&p, 0);
2868 c4b1fcc0 bellard
                    if (*p != '\0') {
2869 c4b1fcc0 bellard
                    chs_fail:
2870 c4b1fcc0 bellard
                        cyls = 0;
2871 c4b1fcc0 bellard
                    }
2872 330d0414 bellard
                }
2873 330d0414 bellard
                break;
2874 cd6f1169 bellard
            case QEMU_OPTION_nographic:
2875 82c643ff bellard
                pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
2876 8d11df9e bellard
                pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio");
2877 a20dd508 bellard
                nographic = 1;
2878 a20dd508 bellard
                break;
2879 cd6f1169 bellard
            case QEMU_OPTION_kernel:
2880 a20dd508 bellard
                kernel_filename = optarg;
2881 a20dd508 bellard
                break;
2882 cd6f1169 bellard
            case QEMU_OPTION_append:
2883 a20dd508 bellard
                kernel_cmdline = optarg;
2884 313aa567 bellard
                break;
2885 cd6f1169 bellard
            case QEMU_OPTION_tun_fd:
2886 c4b1fcc0 bellard
                {
2887 c4b1fcc0 bellard
                    const char *p;
2888 c4b1fcc0 bellard
                    int fd;
2889 d6b86f4d bellard
                    net_if_type = NET_IF_TUN;
2890 c20709aa bellard
                    if (nb_tun_fds < MAX_NICS) {
2891 c20709aa bellard
                        fd = strtol(optarg, (char **)&p, 0);
2892 c20709aa bellard
                        if (*p != '\0') {
2893 c20709aa bellard
                            fprintf(stderr, "qemu: invalid fd for network interface %d\n", nb_tun_fds);
2894 c4b1fcc0 bellard
                            exit(1);
2895 c4b1fcc0 bellard
                        }
2896 c20709aa bellard
                        tun_fds[nb_tun_fds++] = fd;
2897 c4b1fcc0 bellard
                    }
2898 c4b1fcc0 bellard
                }
2899 42f1e0e4 bellard
                break;
2900 cd6f1169 bellard
            case QEMU_OPTION_hdc:
2901 36b486bb bellard
                hd_filename[2] = optarg;
2902 c4b1fcc0 bellard
                has_cdrom = 0;
2903 36b486bb bellard
                break;
2904 cd6f1169 bellard
            case QEMU_OPTION_hdd:
2905 36b486bb bellard
                hd_filename[3] = optarg;
2906 36b486bb bellard
                break;
2907 cd6f1169 bellard
            case QEMU_OPTION_cdrom:
2908 36b486bb bellard
                hd_filename[2] = optarg;
2909 c4b1fcc0 bellard
                has_cdrom = 1;
2910 36b486bb bellard
                break;
2911 cd6f1169 bellard
            case QEMU_OPTION_boot:
2912 36b486bb bellard
                boot_device = optarg[0];
2913 9e89a4be bellard
                if (boot_device != 'a' && 
2914 c45886db bellard
                    boot_device != 'c' && boot_device != 'd') {
2915 36b486bb bellard
                    fprintf(stderr, "qemu: invalid boot device '%c'\n", boot_device);
2916 36b486bb bellard
                    exit(1);
2917 36b486bb bellard
                }
2918 36b486bb bellard
                break;
2919 cd6f1169 bellard
            case QEMU_OPTION_fda:
2920 c45886db bellard
                fd_filename[0] = optarg;
2921 c45886db bellard
                break;
2922 cd6f1169 bellard
            case QEMU_OPTION_fdb:
2923 c45886db bellard
                fd_filename[1] = optarg;
2924 c45886db bellard
                break;
2925 cd6f1169 bellard
            case QEMU_OPTION_no_code_copy:
2926 77fef8c1 bellard
                code_copy_enabled = 0;
2927 77fef8c1 bellard
                break;
2928 cd6f1169 bellard
            case QEMU_OPTION_nics:
2929 c4b1fcc0 bellard
                nb_nics = atoi(optarg);
2930 3a1bc175 bellard
                if (nb_nics < 0 || nb_nics > MAX_NICS) {
2931 c4b1fcc0 bellard
                    fprintf(stderr, "qemu: invalid number of network interfaces\n");
2932 c4b1fcc0 bellard
                    exit(1);
2933 c4b1fcc0 bellard
                }
2934 c4b1fcc0 bellard
                break;
2935 cd6f1169 bellard
            case QEMU_OPTION_macaddr:
2936 702c651c bellard
                {
2937 702c651c bellard
                    const char *p;
2938 702c651c bellard
                    int i;
2939 702c651c bellard
                    p = optarg;
2940 702c651c bellard
                    for(i = 0; i < 6; i++) {
2941 702c651c bellard
                        macaddr[i] = strtol(p, (char **)&p, 16);
2942 702c651c bellard
                        if (i == 5) {
2943 702c651c bellard
                            if (*p != '\0') 
2944 702c651c bellard
                                goto macaddr_error;
2945 702c651c bellard
                        } else {
2946 702c651c bellard
                            if (*p != ':') {
2947 702c651c bellard
                            macaddr_error:
2948 702c651c bellard
                                fprintf(stderr, "qemu: invalid syntax for ethernet address\n");
2949 702c651c bellard
                                exit(1);
2950 702c651c bellard
                            }
2951 702c651c bellard
                            p++;
2952 702c651c bellard
                        }
2953 702c651c bellard
                    }
2954 702c651c bellard
                }
2955 702c651c bellard
                break;
2956 c7f74643 bellard
#ifdef CONFIG_SLIRP
2957 c7f74643 bellard
            case QEMU_OPTION_tftp:
2958 c7f74643 bellard
                tftp_prefix = optarg;
2959 9bf05444 bellard
                break;
2960 c94c8d64 bellard
#ifndef _WIN32
2961 9d728e8c bellard
            case QEMU_OPTION_smb:
2962 9d728e8c bellard
                net_slirp_smb(optarg);
2963 9d728e8c bellard
                break;
2964 c94c8d64 bellard
#endif
2965 cd6f1169 bellard
            case QEMU_OPTION_user_net:
2966 c20709aa bellard
                net_if_type = NET_IF_USER;
2967 c20709aa bellard
                break;
2968 9bf05444 bellard
            case QEMU_OPTION_redir:
2969 9bf05444 bellard
                net_slirp_redir(optarg);                
2970 9bf05444 bellard
                break;
2971 c7f74643 bellard
#endif
2972 cd6f1169 bellard
            case QEMU_OPTION_dummy_net:
2973 c20709aa bellard
                net_if_type = NET_IF_DUMMY;
2974 c20709aa bellard
                break;
2975 cd6f1169 bellard
            case QEMU_OPTION_enable_audio:
2976 aaaa7df6 bellard
                audio_enabled = 1;
2977 aaaa7df6 bellard
                break;
2978 cd6f1169 bellard
            case QEMU_OPTION_h:
2979 0824d6fc bellard
                help();
2980 cd6f1169 bellard
                break;
2981 cd6f1169 bellard
            case QEMU_OPTION_m:
2982 cd6f1169 bellard
                ram_size = atoi(optarg) * 1024 * 1024;
2983 cd6f1169 bellard
                if (ram_size <= 0)
2984 cd6f1169 bellard
                    help();
2985 cd6f1169 bellard
                if (ram_size > PHYS_RAM_MAX_SIZE) {
2986 cd6f1169 bellard
                    fprintf(stderr, "qemu: at most %d MB RAM can be simulated\n",
2987 cd6f1169 bellard
                            PHYS_RAM_MAX_SIZE / (1024 * 1024));
2988 cd6f1169 bellard
                    exit(1);
2989 cd6f1169 bellard
                }
2990 cd6f1169 bellard
                break;
2991 cd6f1169 bellard
            case QEMU_OPTION_d:
2992 cd6f1169 bellard
                {
2993 cd6f1169 bellard
                    int mask;
2994 cd6f1169 bellard
                    CPULogItem *item;
2995 cd6f1169 bellard
                    
2996 cd6f1169 bellard
                    mask = cpu_str_to_log_mask(optarg);
2997 cd6f1169 bellard
                    if (!mask) {
2998 cd6f1169 bellard
                        printf("Log items (comma separated):\n");
2999 f193c797 bellard
                    for(item = cpu_log_items; item->mask != 0; item++) {
3000 f193c797 bellard
                        printf("%-10s %s\n", item->name, item->help);
3001 f193c797 bellard
                    }
3002 f193c797 bellard
                    exit(1);
3003 cd6f1169 bellard
                    }
3004 cd6f1169 bellard
                    cpu_set_log(mask);
3005 f193c797 bellard
                }
3006 cd6f1169 bellard
                break;
3007 cd6f1169 bellard
            case QEMU_OPTION_n:
3008 cd6f1169 bellard
                pstrcpy(network_script, sizeof(network_script), optarg);
3009 cd6f1169 bellard
                break;
3010 67b915a5 bellard
#ifdef CONFIG_GDBSTUB
3011 cd6f1169 bellard
            case QEMU_OPTION_s:
3012 cd6f1169 bellard
                use_gdbstub = 1;
3013 cd6f1169 bellard
                break;
3014 cd6f1169 bellard
            case QEMU_OPTION_p:
3015 cd6f1169 bellard
                gdbstub_port = atoi(optarg);
3016 cd6f1169 bellard
                break;
3017 67b915a5 bellard
#endif
3018 cd6f1169 bellard
            case QEMU_OPTION_L:
3019 cd6f1169 bellard
                bios_dir = optarg;
3020 cd6f1169 bellard
                break;
3021 cd6f1169 bellard
            case QEMU_OPTION_S:
3022 cd6f1169 bellard
                start_emulation = 0;
3023 cd6f1169 bellard
                break;
3024 69b91039 bellard
            case QEMU_OPTION_pci:
3025 69b91039 bellard
                pci_enabled = 1;
3026 69b91039 bellard
                break;
3027 bb0c6722 bellard
            case QEMU_OPTION_isa:
3028 bb0c6722 bellard
                pci_enabled = 0;
3029 bb0c6722 bellard
                break;
3030 77d4bc34 bellard
            case QEMU_OPTION_prep:
3031 77d4bc34 bellard
                prep_enabled = 1;
3032 77d4bc34 bellard
                break;
3033 ee22c2f7 bellard
            case QEMU_OPTION_localtime:
3034 ee22c2f7 bellard
                rtc_utc = 0;
3035 ee22c2f7 bellard
                break;
3036 1f04275e bellard
            case QEMU_OPTION_cirrusvga:
3037 1f04275e bellard
                cirrus_vga_enabled = 1;
3038 1f04275e bellard
                break;
3039 1bfe856e bellard
            case QEMU_OPTION_std_vga:
3040 1bfe856e bellard
                cirrus_vga_enabled = 0;
3041 1bfe856e bellard
                break;
3042 e9b137c2 bellard
            case QEMU_OPTION_g:
3043 e9b137c2 bellard
                {
3044 e9b137c2 bellard
                    const char *p;
3045 e9b137c2 bellard
                    int w, h, depth;
3046 e9b137c2 bellard
                    p = optarg;
3047 e9b137c2 bellard
                    w = strtol(p, (char **)&p, 10);
3048 e9b137c2 bellard
                    if (w <= 0) {
3049 e9b137c2 bellard
                    graphic_error:
3050 e9b137c2 bellard
                        fprintf(stderr, "qemu: invalid resolution or depth\n");
3051 e9b137c2 bellard
                        exit(1);
3052 e9b137c2 bellard
                    }
3053 e9b137c2 bellard
                    if (*p != 'x')
3054 e9b137c2 bellard
                        goto graphic_error;
3055 e9b137c2 bellard
                    p++;
3056 e9b137c2 bellard
                    h = strtol(p, (char **)&p, 10);
3057 e9b137c2 bellard
                    if (h <= 0)
3058 e9b137c2 bellard
                        goto graphic_error;
3059 e9b137c2 bellard
                    if (*p == 'x') {
3060 e9b137c2 bellard
                        p++;
3061 e9b137c2 bellard
                        depth = strtol(p, (char **)&p, 10);
3062 e9b137c2 bellard
                        if (depth != 8 && depth != 15 && depth != 16 && 
3063 e9b137c2 bellard
                            depth != 24 && depth != 32)
3064 e9b137c2 bellard
                            goto graphic_error;
3065 e9b137c2 bellard
                    } else if (*p == '\0') {
3066 e9b137c2 bellard
                        depth = graphic_depth;
3067 e9b137c2 bellard
                    } else {
3068 e9b137c2 bellard
                        goto graphic_error;
3069 e9b137c2 bellard
                    }
3070 e9b137c2 bellard
                    
3071 e9b137c2 bellard
                    graphic_width = w;
3072 e9b137c2 bellard
                    graphic_height = h;
3073 e9b137c2 bellard
                    graphic_depth = depth;
3074 e9b137c2 bellard
                }
3075 e9b137c2 bellard
                break;
3076 82c643ff bellard
            case QEMU_OPTION_monitor:
3077 82c643ff bellard
                pstrcpy(monitor_device, sizeof(monitor_device), optarg);
3078 82c643ff bellard
                break;
3079 82c643ff bellard
            case QEMU_OPTION_serial:
3080 8d11df9e bellard
                if (serial_device_index >= MAX_SERIAL_PORTS) {
3081 8d11df9e bellard
                    fprintf(stderr, "qemu: too many serial ports\n");
3082 8d11df9e bellard
                    exit(1);
3083 8d11df9e bellard
                }
3084 8d11df9e bellard
                pstrcpy(serial_devices[serial_device_index], 
3085 8d11df9e bellard
                        sizeof(serial_devices[0]), optarg);
3086 8d11df9e bellard
                serial_device_index++;
3087 82c643ff bellard
                break;
3088 d63d307f bellard
            case QEMU_OPTION_loadvm:
3089 d63d307f bellard
                loadvm = optarg;
3090 d63d307f bellard
                break;
3091 d63d307f bellard
            case QEMU_OPTION_full_screen:
3092 d63d307f bellard
                full_screen = 1;
3093 d63d307f bellard
                break;
3094 cd6f1169 bellard
            }
3095 0824d6fc bellard
        }
3096 0824d6fc bellard
    }
3097 330d0414 bellard
3098 a20dd508 bellard
    linux_boot = (kernel_filename != NULL);
3099 330d0414 bellard
        
3100 c45886db bellard
    if (!linux_boot && hd_filename[0] == '\0' && hd_filename[2] == '\0' &&
3101 c45886db bellard
        fd_filename[0] == '\0')
3102 0824d6fc bellard
        help();
3103 8f2b1fb0 bellard
    
3104 8f2b1fb0 bellard
    /* boot to cd by default if no hard disk */
3105 d0309311 bellard
    if (hd_filename[0] == '\0' && boot_device == 'c') {
3106 d0309311 bellard
        if (fd_filename[0] != '\0')
3107 d0309311 bellard
            boot_device = 'a';
3108 d0309311 bellard
        else
3109 d0309311 bellard
            boot_device = 'd';
3110 d0309311 bellard
    }
3111 0824d6fc bellard
3112 dc887a4d bellard
#if !defined(CONFIG_SOFTMMU)
3113 dc887a4d bellard
    /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
3114 dc887a4d bellard
    {
3115 dc887a4d bellard
        static uint8_t stdout_buf[4096];
3116 dc887a4d bellard
        setvbuf(stdout, stdout_buf, _IOLBF, sizeof(stdout_buf));
3117 dc887a4d bellard
    }
3118 dc887a4d bellard
#else
3119 b118d61e bellard
    setvbuf(stdout, NULL, _IOLBF, 0);
3120 dc887a4d bellard
#endif
3121 0824d6fc bellard
3122 c4b1fcc0 bellard
    /* init host network redirectors */
3123 c20709aa bellard
    if (net_if_type == -1) {
3124 c20709aa bellard
        net_if_type = NET_IF_TUN;
3125 c20709aa bellard
#if defined(CONFIG_SLIRP)
3126 c20709aa bellard
        if (access(network_script, R_OK) < 0) {
3127 c20709aa bellard
            net_if_type = NET_IF_USER;
3128 c20709aa bellard
        }
3129 c20709aa bellard
#endif
3130 c20709aa bellard
    }
3131 c20709aa bellard
3132 c20709aa bellard
    for(i = 0; i < nb_nics; i++) {
3133 702c651c bellard
        NetDriverState *nd = &nd_table[i];
3134 c20709aa bellard
        nd->index = i;
3135 702c651c bellard
        /* init virtual mac address */
3136 702c651c bellard
        nd->macaddr[0] = macaddr[0];
3137 702c651c bellard
        nd->macaddr[1] = macaddr[1];
3138 702c651c bellard
        nd->macaddr[2] = macaddr[2];
3139 702c651c bellard
        nd->macaddr[3] = macaddr[3];
3140 702c651c bellard
        nd->macaddr[4] = macaddr[4];
3141 702c651c bellard
        nd->macaddr[5] = macaddr[5] + i;
3142 c20709aa bellard
        switch(net_if_type) {
3143 c20709aa bellard
#if defined(CONFIG_SLIRP)
3144 c20709aa bellard
        case NET_IF_USER:
3145 c20709aa bellard
            net_slirp_init(nd);
3146 c20709aa bellard
            break;
3147 c20709aa bellard
#endif
3148 c20709aa bellard
#if !defined(_WIN32)
3149 c20709aa bellard
        case NET_IF_TUN:
3150 c20709aa bellard
            if (i < nb_tun_fds) {
3151 c20709aa bellard
                net_fd_init(nd, tun_fds[i]);
3152 c20709aa bellard
            } else {
3153 d927637d bellard
                if (net_tun_init(nd) < 0)
3154 d927637d bellard
                    net_dummy_init(nd);
3155 c20709aa bellard
            }
3156 c20709aa bellard
            break;
3157 c20709aa bellard
#endif
3158 c20709aa bellard
        case NET_IF_DUMMY:
3159 c20709aa bellard
        default:
3160 c20709aa bellard
            net_dummy_init(nd);
3161 c20709aa bellard
            break;
3162 c20709aa bellard
        }
3163 702c651c bellard
    }
3164 f1510b2c bellard
3165 0824d6fc bellard
    /* init the memory */
3166 0ced6589 bellard
    phys_ram_size = ram_size + vga_ram_size + bios_size;
3167 7f7f9873 bellard
3168 7f7f9873 bellard
#ifdef CONFIG_SOFTMMU
3169 7d3505c5 bellard
#ifdef _BSD
3170 83fb7adf bellard
    /* mallocs are always aligned on BSD. valloc is better for correctness */
3171 83fb7adf bellard
    phys_ram_base = valloc(phys_ram_size);
3172 7d3505c5 bellard
#else
3173 1ccde1cb bellard
    phys_ram_base = memalign(TARGET_PAGE_SIZE, phys_ram_size);
3174 7d3505c5 bellard
#endif
3175 7f7f9873 bellard
    if (!phys_ram_base) {
3176 7f7f9873 bellard
        fprintf(stderr, "Could not allocate physical memory\n");
3177 0824d6fc bellard
        exit(1);
3178 0824d6fc bellard
    }
3179 7f7f9873 bellard
#else
3180 7f7f9873 bellard
    /* as we must map the same page at several addresses, we must use
3181 7f7f9873 bellard
       a fd */
3182 7f7f9873 bellard
    {
3183 7f7f9873 bellard
        const char *tmpdir;
3184 7f7f9873 bellard
3185 7f7f9873 bellard
        tmpdir = getenv("QEMU_TMPDIR");
3186 7f7f9873 bellard
        if (!tmpdir)
3187 7f7f9873 bellard
            tmpdir = "/tmp";
3188 7f7f9873 bellard
        snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/vlXXXXXX", tmpdir);
3189 7f7f9873 bellard
        if (mkstemp(phys_ram_file) < 0) {
3190 7f7f9873 bellard
            fprintf(stderr, "Could not create temporary memory file '%s'\n", 
3191 7f7f9873 bellard
                    phys_ram_file);
3192 7f7f9873 bellard
            exit(1);
3193 7f7f9873 bellard
        }
3194 7f7f9873 bellard
        phys_ram_fd = open(phys_ram_file, O_CREAT | O_TRUNC | O_RDWR, 0600);
3195 7f7f9873 bellard
        if (phys_ram_fd < 0) {
3196 7f7f9873 bellard
            fprintf(stderr, "Could not open temporary memory file '%s'\n", 
3197 7f7f9873 bellard
                    phys_ram_file);
3198 7f7f9873 bellard
            exit(1);
3199 7f7f9873 bellard
        }
3200 1ccde1cb bellard
        ftruncate(phys_ram_fd, phys_ram_size);
3201 7f7f9873 bellard
        unlink(phys_ram_file);
3202 1ccde1cb bellard
        phys_ram_base = mmap(get_mmap_addr(phys_ram_size), 
3203 1ccde1cb bellard
                             phys_ram_size, 
3204 7f7f9873 bellard
                             PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FIXED, 
3205 7f7f9873 bellard
                             phys_ram_fd, 0);
3206 7f7f9873 bellard
        if (phys_ram_base == MAP_FAILED) {
3207 7f7f9873 bellard
            fprintf(stderr, "Could not map physical memory\n");
3208 7f7f9873 bellard
            exit(1);
3209 7f7f9873 bellard
        }
3210 7f7f9873 bellard
    }
3211 7f7f9873 bellard
#endif
3212 0824d6fc bellard
3213 c4b1fcc0 bellard
    /* we always create the cdrom drive, even if no disk is there */
3214 5905b2e5 bellard
    bdrv_init();
3215 c4b1fcc0 bellard
    if (has_cdrom) {
3216 c4b1fcc0 bellard
        bs_table[2] = bdrv_new("cdrom");
3217 c4b1fcc0 bellard
        bdrv_set_type_hint(bs_table[2], BDRV_TYPE_CDROM);
3218 c4b1fcc0 bellard
    }
3219 c4b1fcc0 bellard
3220 33e3963e bellard
    /* open the virtual block devices */
3221 33e3963e bellard
    for(i = 0; i < MAX_DISKS; i++) {
3222 33e3963e bellard
        if (hd_filename[i]) {
3223 33e3963e bellard
            if (!bs_table[i]) {
3224 c4b1fcc0 bellard
                char buf[64];
3225 c4b1fcc0 bellard
                snprintf(buf, sizeof(buf), "hd%c", i + 'a');
3226 c4b1fcc0 bellard
                bs_table[i] = bdrv_new(buf);
3227 c4b1fcc0 bellard
            }
3228 c4b1fcc0 bellard
            if (bdrv_open(bs_table[i], hd_filename[i], snapshot) < 0) {
3229 5905b2e5 bellard
                fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
3230 33e3963e bellard
                        hd_filename[i]);
3231 33e3963e bellard
                exit(1);
3232 33e3963e bellard
            }
3233 c4b1fcc0 bellard
            if (i == 0 && cyls != 0) 
3234 c4b1fcc0 bellard
                bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs);
3235 c4b1fcc0 bellard
        }
3236 c4b1fcc0 bellard
    }
3237 c4b1fcc0 bellard
3238 c4b1fcc0 bellard
    /* we always create at least one floppy disk */
3239 c4b1fcc0 bellard
    fd_table[0] = bdrv_new("fda");
3240 c4b1fcc0 bellard
    bdrv_set_type_hint(fd_table[0], BDRV_TYPE_FLOPPY);
3241 c4b1fcc0 bellard
3242 c4b1fcc0 bellard
    for(i = 0; i < MAX_FD; i++) {
3243 c4b1fcc0 bellard
        if (fd_filename[i]) {
3244 c4b1fcc0 bellard
            if (!fd_table[i]) {
3245 c4b1fcc0 bellard
                char buf[64];
3246 c4b1fcc0 bellard
                snprintf(buf, sizeof(buf), "fd%c", i + 'a');
3247 c4b1fcc0 bellard
                fd_table[i] = bdrv_new(buf);
3248 c4b1fcc0 bellard
                bdrv_set_type_hint(fd_table[i], BDRV_TYPE_FLOPPY);
3249 c4b1fcc0 bellard
            }
3250 c4b1fcc0 bellard
            if (fd_filename[i] != '\0') {
3251 c4b1fcc0 bellard
                if (bdrv_open(fd_table[i], fd_filename[i], snapshot) < 0) {
3252 c20709aa bellard
                    fprintf(stderr, "qemu: could not open floppy disk image '%s'\n",
3253 c4b1fcc0 bellard
                            fd_filename[i]);
3254 c4b1fcc0 bellard
                    exit(1);
3255 c4b1fcc0 bellard
                }
3256 c4b1fcc0 bellard
            }
3257 33e3963e bellard
        }
3258 33e3963e bellard
    }
3259 33e3963e bellard
3260 330d0414 bellard
    /* init CPU state */
3261 330d0414 bellard
    env = cpu_init();
3262 330d0414 bellard
    global_env = env;
3263 330d0414 bellard
    cpu_single_env = env;
3264 330d0414 bellard
3265 8a7ddc38 bellard
    register_savevm("timer", 0, 1, timer_save, timer_load, env);
3266 02ba45c5 bellard
    register_savevm("cpu", 0, 2, cpu_save, cpu_load, env);
3267 8a7ddc38 bellard
    register_savevm("ram", 0, 1, ram_save, ram_load, NULL);
3268 bb0c6722 bellard
    qemu_register_reset(main_cpu_reset, global_env);
3269 8a7ddc38 bellard
3270 330d0414 bellard
    init_ioports();
3271 80cabfad bellard
    cpu_calibrate_ticks();
3272 0824d6fc bellard
3273 313aa567 bellard
    /* terminal init */
3274 a20dd508 bellard
    if (nographic) {
3275 313aa567 bellard
        dumb_display_init(ds);
3276 313aa567 bellard
    } else {
3277 313aa567 bellard
#ifdef CONFIG_SDL
3278 d63d307f bellard
        sdl_display_init(ds, full_screen);
3279 313aa567 bellard
#else
3280 313aa567 bellard
        dumb_display_init(ds);
3281 313aa567 bellard
#endif
3282 313aa567 bellard
    }
3283 0824d6fc bellard
3284 82c643ff bellard
    vga_console = graphic_console_init(ds);
3285 82c643ff bellard
    
3286 82c643ff bellard
    monitor_hd = qemu_chr_open(monitor_device);
3287 82c643ff bellard
    if (!monitor_hd) {
3288 82c643ff bellard
        fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device);
3289 82c643ff bellard
        exit(1);
3290 82c643ff bellard
    }
3291 82c643ff bellard
    monitor_init(monitor_hd, !nographic);
3292 82c643ff bellard
3293 8d11df9e bellard
    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
3294 8d11df9e bellard
        if (serial_devices[i][0] != '\0') {
3295 8d11df9e bellard
            serial_hds[i] = qemu_chr_open(serial_devices[i]);
3296 8d11df9e bellard
            if (!serial_hds[i]) {
3297 8d11df9e bellard
                fprintf(stderr, "qemu: could not open serial device '%s'\n", 
3298 8d11df9e bellard
                        serial_devices[i]);
3299 8d11df9e bellard
                exit(1);
3300 8d11df9e bellard
            }
3301 8d11df9e bellard
            if (!strcmp(serial_devices[i], "vc"))
3302 8d11df9e bellard
                qemu_chr_printf(serial_hds[i], "serial%d console\n", i);
3303 8d11df9e bellard
        }
3304 82c643ff bellard
    }
3305 82c643ff bellard
3306 0824d6fc bellard
    /* setup cpu signal handlers for MMU / self modifying code handling */
3307 77fef8c1 bellard
#if !defined(CONFIG_SOFTMMU)
3308 8a7ddc38 bellard
    
3309 77fef8c1 bellard
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
3310 77fef8c1 bellard
    {
3311 77fef8c1 bellard
        stack_t stk;
3312 73332e5c bellard
        signal_stack = memalign(16, SIGNAL_STACK_SIZE);
3313 77fef8c1 bellard
        stk.ss_sp = signal_stack;
3314 77fef8c1 bellard
        stk.ss_size = SIGNAL_STACK_SIZE;
3315 77fef8c1 bellard
        stk.ss_flags = 0;
3316 77fef8c1 bellard
3317 77fef8c1 bellard
        if (sigaltstack(&stk, NULL) < 0) {
3318 77fef8c1 bellard
            perror("sigaltstack");
3319 77fef8c1 bellard
            exit(1);
3320 77fef8c1 bellard
        }
3321 77fef8c1 bellard
    }
3322 77fef8c1 bellard
#endif
3323 8a7ddc38 bellard
    {
3324 8a7ddc38 bellard
        struct sigaction act;
3325 77fef8c1 bellard
        
3326 8a7ddc38 bellard
        sigfillset(&act.sa_mask);
3327 8a7ddc38 bellard
        act.sa_flags = SA_SIGINFO;
3328 77fef8c1 bellard
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
3329 8a7ddc38 bellard
        act.sa_flags |= SA_ONSTACK;
3330 77fef8c1 bellard
#endif
3331 8a7ddc38 bellard
        act.sa_sigaction = host_segv_handler;
3332 8a7ddc38 bellard
        sigaction(SIGSEGV, &act, NULL);
3333 8a7ddc38 bellard
        sigaction(SIGBUS, &act, NULL);
3334 77fef8c1 bellard
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
3335 8a7ddc38 bellard
        sigaction(SIGFPE, &act, NULL);
3336 77fef8c1 bellard
#endif
3337 8a7ddc38 bellard
    }
3338 3a51dee6 bellard
#endif
3339 0824d6fc bellard
3340 67b915a5 bellard
#ifndef _WIN32
3341 8a7ddc38 bellard
    {
3342 8a7ddc38 bellard
        struct sigaction act;
3343 8a7ddc38 bellard
        sigfillset(&act.sa_mask);
3344 8a7ddc38 bellard
        act.sa_flags = 0;
3345 8a7ddc38 bellard
        act.sa_handler = SIG_IGN;
3346 8a7ddc38 bellard
        sigaction(SIGPIPE, &act, NULL);
3347 8a7ddc38 bellard
    }
3348 67b915a5 bellard
#endif
3349 73332e5c bellard
    init_timers();
3350 73332e5c bellard
3351 73332e5c bellard
#if defined(TARGET_I386)
3352 73332e5c bellard
    pc_init(ram_size, vga_ram_size, boot_device,
3353 73332e5c bellard
            ds, fd_filename, snapshot,
3354 73332e5c bellard
            kernel_filename, kernel_cmdline, initrd_filename);
3355 73332e5c bellard
#elif defined(TARGET_PPC)
3356 a541f297 bellard
    ppc_init(ram_size, vga_ram_size, boot_device,
3357 a541f297 bellard
             ds, fd_filename, snapshot,
3358 a541f297 bellard
             kernel_filename, kernel_cmdline, initrd_filename);
3359 e95c8d51 bellard
#elif defined(TARGET_SPARC)
3360 e95c8d51 bellard
    sun4m_init(ram_size, vga_ram_size, boot_device,
3361 e95c8d51 bellard
            ds, fd_filename, snapshot,
3362 e95c8d51 bellard
            kernel_filename, kernel_cmdline, initrd_filename);
3363 73332e5c bellard
#endif
3364 73332e5c bellard
3365 8a7ddc38 bellard
    gui_timer = qemu_new_timer(rt_clock, gui_update, NULL);
3366 8a7ddc38 bellard
    qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock));
3367 7f7f9873 bellard
3368 67b915a5 bellard
#ifdef CONFIG_GDBSTUB
3369 b4608c04 bellard
    if (use_gdbstub) {
3370 8a7ddc38 bellard
        if (gdbserver_start(gdbstub_port) < 0) {
3371 8a7ddc38 bellard
            fprintf(stderr, "Could not open gdbserver socket on port %d\n", 
3372 8a7ddc38 bellard
                    gdbstub_port);
3373 8a7ddc38 bellard
            exit(1);
3374 8a7ddc38 bellard
        } else {
3375 8a7ddc38 bellard
            printf("Waiting gdb connection on port %d\n", gdbstub_port);
3376 8a7ddc38 bellard
        }
3377 67b915a5 bellard
    } else 
3378 67b915a5 bellard
#endif
3379 d63d307f bellard
    if (loadvm)
3380 d63d307f bellard
        qemu_loadvm(loadvm);
3381 d63d307f bellard
3382 67b915a5 bellard
    {
3383 5905b2e5 bellard
        /* XXX: simplify init */
3384 5905b2e5 bellard
        read_passwords();
3385 5905b2e5 bellard
        if (start_emulation) {
3386 5905b2e5 bellard
            vm_start();
3387 5905b2e5 bellard
        }
3388 0824d6fc bellard
    }
3389 8a7ddc38 bellard
    main_loop();
3390 40c3bac3 bellard
    quit_timers();
3391 0824d6fc bellard
    return 0;
3392 0824d6fc bellard
}