/*
* QEMU System Emulator
*
- * Copyright (c) 2003-2007 Fabrice Bellard
+ * Copyright (c) 2003-2008 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
#ifdef _WIN32
#include <malloc.h>
#include <sys/timeb.h>
-#include <windows.h>
+#include <mmsystem.h>
#define getopt_long_only getopt_long
#define memalign(align, size) malloc(size)
#endif
const char *prom_envs[MAX_PROM_ENVS];
#endif
int nb_drives_opt;
-char drives_opt[MAX_DRIVES][1024];
+struct drive_opt {
+ const char *file;
+ char opt[1024];
+} drives_opt[MAX_DRIVES];
static CPUState *cur_cpu;
static CPUState *next_cpu;
};
#define ALARM_FLAG_DYNTICKS 0x1
+#define ALARM_FLAG_EXPIRED 0x2
static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
{
ts->expire_time = expire_time;
ts->next = *pt;
*pt = ts;
+
+ /* Rearm if necessary */
+ if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0 &&
+ pt == &active_timers[ts->clock->type])
+ qemu_rearm_alarm_timer(alarm_timer);
}
int qemu_timer_pending(QEMUTimer *ts)
/* run the callback (the timer list can be modified) */
ts->cb(ts->opaque);
}
- qemu_rearm_alarm_timer(alarm_timer);
}
int64_t qemu_get_clock(QEMUClock *clock)
if (cpu_ticks_enabled) {
hw_error("cannot save state if virtual timers are running");
}
- qemu_put_be64s(f, &cpu_ticks_offset);
- qemu_put_be64s(f, &ticks_per_sec);
- qemu_put_be64s(f, &cpu_clock_offset);
+ qemu_put_be64(f, cpu_ticks_offset);
+ qemu_put_be64(f, ticks_per_sec);
+ qemu_put_be64(f, cpu_clock_offset);
}
static int timer_load(QEMUFile *f, void *opaque, int version_id)
if (cpu_ticks_enabled) {
return -EINVAL;
}
- qemu_get_be64s(f, &cpu_ticks_offset);
- qemu_get_be64s(f, &ticks_per_sec);
+ cpu_ticks_offset=qemu_get_be64(f);
+ ticks_per_sec=qemu_get_be64(f);
if (version_id == 2) {
- qemu_get_be64s(f, &cpu_clock_offset);
+ cpu_clock_offset=qemu_get_be64(f);
}
return 0;
}
#endif
CPUState *env = next_cpu;
+ alarm_timer->flags |= ALARM_FLAG_EXPIRED;
+
if (env) {
/* stop the currently executing cpu because a timer occured */
cpu_interrupt(env, CPU_INTERRUPT_EXIT);
if (!active_timers[QEMU_TIMER_REALTIME] &&
!active_timers[QEMU_TIMER_VIRTUAL])
- return;
+ return;
nearest_delta_us = qemu_next_deadline();
if (!active_timers[QEMU_TIMER_REALTIME] &&
!active_timers[QEMU_TIMER_VIRTUAL])
- return;
+ return;
nearest_delta_us = qemu_next_deadline();
nearest_delta_us /= 1000;
#endif
tcgetattr (fd, &tty);
- switch(speed) {
- case 50:
+#define MARGIN 1.1
+ if (speed <= 50 * MARGIN)
spd = B50;
- break;
- case 75:
+ else if (speed <= 75 * MARGIN)
spd = B75;
- break;
- case 300:
+ else if (speed <= 300 * MARGIN)
spd = B300;
- break;
- case 600:
+ else if (speed <= 600 * MARGIN)
spd = B600;
- break;
- case 1200:
+ else if (speed <= 1200 * MARGIN)
spd = B1200;
- break;
- case 2400:
+ else if (speed <= 2400 * MARGIN)
spd = B2400;
- break;
- case 4800:
+ else if (speed <= 4800 * MARGIN)
spd = B4800;
- break;
- case 9600:
+ else if (speed <= 9600 * MARGIN)
spd = B9600;
- break;
- case 19200:
+ else if (speed <= 19200 * MARGIN)
spd = B19200;
- break;
- case 38400:
+ else if (speed <= 38400 * MARGIN)
spd = B38400;
- break;
- case 57600:
+ else if (speed <= 57600 * MARGIN)
spd = B57600;
- break;
- default:
- case 115200:
+ else if (speed <= 115200 * MARGIN)
+ spd = B115200;
+ else
spd = B115200;
- break;
- }
cfsetispeed(&tty, spd);
cfsetospeed(&tty, spd);
char smb_dir[1024];
-static void smb_exit(void)
+static void erase_dir(char *dir_name)
{
DIR *d;
struct dirent *de;
char filename[1024];
/* erase all the files in the directory */
- d = opendir(smb_dir);
- for(;;) {
- de = readdir(d);
- if (!de)
- break;
- if (strcmp(de->d_name, ".") != 0 &&
- strcmp(de->d_name, "..") != 0) {
- snprintf(filename, sizeof(filename), "%s/%s",
- smb_dir, de->d_name);
- unlink(filename);
+ if ((d = opendir(dir_name)) != 0) {
+ for(;;) {
+ de = readdir(d);
+ if (!de)
+ break;
+ if (strcmp(de->d_name, ".") != 0 &&
+ strcmp(de->d_name, "..") != 0) {
+ snprintf(filename, sizeof(filename), "%s/%s",
+ smb_dir, de->d_name);
+ if (unlink(filename) != 0) /* is it a directory? */
+ erase_dir(filename);
+ }
}
+ closedir(d);
+ rmdir(dir_name);
}
- closedir(d);
- rmdir(smb_dir);
+}
+
+/* automatic user mode samba server configuration */
+static void smb_exit(void)
+{
+ erase_dir(smb_dir);
}
/* automatic user mode samba server configuration */
{
int so_type=-1, optlen=sizeof(so_type);
- if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type, &optlen)< 0) {
+ if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
+ (socklen_t *)&optlen)< 0) {
fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n", fd);
return NULL;
}
}
-static const char *get_word(char *buf, int buf_size, const char *p)
+static const char *get_opt_name(char *buf, int buf_size, const char *p)
+{
+ char *q;
+
+ q = buf;
+ while (*p != '\0' && *p != '=') {
+ if (q && (q - buf) < buf_size - 1)
+ *q++ = *p;
+ p++;
+ }
+ if (q)
+ *q = '\0';
+
+ return p;
+}
+
+static const char *get_opt_value(char *buf, int buf_size, const char *p)
{
char *q;
- int substring;
- substring = 0;
q = buf;
while (*p != '\0') {
- if (*p == '\\') {
- p++;
- if (*p == '\0')
+ if (*p == ',') {
+ if (*(p + 1) != ',')
break;
- } else if (*p == '\"') {
- substring = !substring;
p++;
- continue;
- } else if (!substring && (*p == ',' || *p == '='))
- break;
+ }
if (q && (q - buf) < buf_size - 1)
*q++ = *p;
p++;
p = str;
for(;;) {
- p = get_word(option, sizeof(option), p);
+ p = get_opt_name(option, sizeof(option), p);
if (*p != '=')
break;
p++;
if (!strcmp(tag, option)) {
- (void)get_word(buf, buf_size, p);
+ (void)get_opt_value(buf, buf_size, p);
return strlen(buf);
} else {
- p = get_word(NULL, 0, p);
+ p = get_opt_value(NULL, 0, p);
}
if (*p != ',')
break;
p = str;
for(;;) {
- p = get_word(buf, buf_size, p);
+ p = get_opt_name(buf, buf_size, p);
if (*p != '=')
return -1;
p++;
break;
if (params[i] == NULL)
return -1;
- p = get_word(NULL, 0, p);
+ p = get_opt_value(NULL, 0, p);
if (*p != ',')
break;
p++;
}
}
-#define HD_ALIAS "file=\"%s\",index=%d,media=disk"
+#define HD_ALIAS "index=%d,media=disk"
#ifdef TARGET_PPC
#define CDROM_ALIAS "index=1,media=cdrom"
#else
#define CDROM_ALIAS "index=2,media=cdrom"
#endif
#define FD_ALIAS "index=%d,if=floppy"
-#define PFLASH_ALIAS "file=\"%s\",if=pflash"
-#define MTD_ALIAS "file=\"%s\",if=mtd"
+#define PFLASH_ALIAS "if=pflash"
+#define MTD_ALIAS "if=mtd"
#define SD_ALIAS "index=0,if=sd"
-static int drive_add(const char *fmt, ...)
+static int drive_add(const char *file, const char *fmt, ...)
{
va_list ap;
exit(1);
}
+ drives_opt[nb_drives_opt].file = file;
va_start(ap, fmt);
- vsnprintf(drives_opt[nb_drives_opt], sizeof(drives_opt[0]), fmt, ap);
+ vsnprintf(drives_opt[nb_drives_opt].opt,
+ sizeof(drives_opt[0].opt), fmt, ap);
va_end(ap);
return nb_drives_opt++;
}
-int drive_get_index(BlockInterfaceType interface, int bus, int unit)
+int drive_get_index(BlockInterfaceType type, int bus, int unit)
{
int index;
/* seek interface, bus and unit */
for (index = 0; index < nb_drives; index++)
- if (drives_table[index].interface == interface &&
+ if (drives_table[index].type == type &&
drives_table[index].bus == bus &&
drives_table[index].unit == unit)
return index;
return -1;
}
-int drive_get_max_bus(BlockInterfaceType interface)
+int drive_get_max_bus(BlockInterfaceType type)
{
int max_bus;
int index;
max_bus = -1;
for (index = 0; index < nb_drives; index++) {
- if(drives_table[index].interface == interface &&
+ if(drives_table[index].type == type &&
drives_table[index].bus > max_bus)
max_bus = drives_table[index].bus;
}
return max_bus;
}
-static int drive_init(const char *str, int snapshot, QEMUMachine *machine)
+static int drive_init(struct drive_opt *arg, int snapshot,
+ QEMUMachine *machine)
{
char buf[128];
char file[1024];
char devname[128];
const char *mediastr = "";
- BlockInterfaceType interface;
+ BlockInterfaceType type;
enum { MEDIA_DISK, MEDIA_CDROM } media;
int bus_id, unit_id;
int cyls, heads, secs, translation;
BlockDriverState *bdrv;
int max_devs;
int index;
+ int cache;
+ int bdrv_flags;
+ char *str = arg->opt;
char *params[] = { "bus", "unit", "if", "index", "cyls", "heads",
- "secs", "trans", "media", "snapshot", "file", NULL };
+ "secs", "trans", "media", "snapshot", "file",
+ "cache", NULL };
if (check_params(buf, sizeof(buf), params, str) < 0) {
fprintf(stderr, "qemu: unknowm parameter '%s' in '%s'\n",
unit_id = -1;
translation = BIOS_ATA_TRANSLATION_AUTO;
index = -1;
+ cache = 1;
if (!strcmp(machine->name, "realview") ||
!strcmp(machine->name, "SS-5") ||
!strcmp(machine->name, "SS-600MP") ||
!strcmp(machine->name, "versatilepb") ||
!strcmp(machine->name, "versatileab")) {
- interface = IF_SCSI;
+ type = IF_SCSI;
max_devs = MAX_SCSI_DEVS;
strcpy(devname, "scsi");
} else {
- interface = IF_IDE;
+ type = IF_IDE;
max_devs = MAX_IDE_DEVS;
strcpy(devname, "ide");
}
if (get_param_value(buf, sizeof(buf), "if", str)) {
strncpy(devname, buf, sizeof(devname));
if (!strcmp(buf, "ide")) {
- interface = IF_IDE;
+ type = IF_IDE;
max_devs = MAX_IDE_DEVS;
} else if (!strcmp(buf, "scsi")) {
- interface = IF_SCSI;
+ type = IF_SCSI;
max_devs = MAX_SCSI_DEVS;
} else if (!strcmp(buf, "floppy")) {
- interface = IF_FLOPPY;
+ type = IF_FLOPPY;
max_devs = 0;
} else if (!strcmp(buf, "pflash")) {
- interface = IF_PFLASH;
+ type = IF_PFLASH;
max_devs = 0;
} else if (!strcmp(buf, "mtd")) {
- interface = IF_MTD;
+ type = IF_MTD;
max_devs = 0;
} else if (!strcmp(buf, "sd")) {
- interface = IF_SD;
+ type = IF_SD;
max_devs = 0;
} else {
fprintf(stderr, "qemu: '%s' unsupported bus type '%s'\n", str, buf);
}
}
- get_param_value(file, sizeof(file), "file", str);
+ if (get_param_value(buf, sizeof(buf), "cache", str)) {
+ if (!strcmp(buf, "off"))
+ cache = 0;
+ else if (!strcmp(buf, "on"))
+ cache = 1;
+ else {
+ fprintf(stderr, "qemu: invalid cache option\n");
+ return -1;
+ }
+ }
+
+ if (arg->file == NULL)
+ get_param_value(file, sizeof(file), "file", str);
+ else
+ pstrcpy(file, sizeof(file), arg->file);
/* compute bus and unit according index */
if (unit_id == -1) {
unit_id = 0;
- while (drive_get_index(interface, bus_id, unit_id) != -1) {
+ while (drive_get_index(type, bus_id, unit_id) != -1) {
unit_id++;
if (max_devs && unit_id >= max_devs) {
unit_id -= max_devs;
* ignore multiple definitions
*/
- if (drive_get_index(interface, bus_id, unit_id) != -1)
+ if (drive_get_index(type, bus_id, unit_id) != -1)
return 0;
/* init */
- if (interface == IF_IDE || interface == IF_SCSI)
+ if (type == IF_IDE || type == IF_SCSI)
mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
- snprintf(buf, sizeof(buf), max_devs ? "%1$s%4$i%2$s%3$i" : "%s%s%i",
- devname, mediastr, unit_id, bus_id);
+ if (max_devs)
+ snprintf(buf, sizeof(buf), "%s%i%s%i",
+ devname, bus_id, mediastr, unit_id);
+ else
+ snprintf(buf, sizeof(buf), "%s%s%i",
+ devname, mediastr, unit_id);
bdrv = bdrv_new(buf);
drives_table[nb_drives].bdrv = bdrv;
- drives_table[nb_drives].interface = interface;
+ drives_table[nb_drives].type = type;
drives_table[nb_drives].bus = bus_id;
drives_table[nb_drives].unit = unit_id;
nb_drives++;
- switch(interface) {
+ switch(type) {
case IF_IDE:
case IF_SCSI:
switch(media) {
}
if (!file[0])
return 0;
- if (bdrv_open(bdrv, file, snapshot ? BDRV_O_SNAPSHOT : 0) < 0 ||
- qemu_key_check(bdrv, file)) {
+ bdrv_flags = 0;
+ if (snapshot)
+ bdrv_flags |= BDRV_O_SNAPSHOT;
+ if (!cache)
+ bdrv_flags |= BDRV_O_DIRECT;
+ if (bdrv_open(bdrv, file, bdrv_flags) < 0 || qemu_key_check(bdrv, file)) {
fprintf(stderr, "qemu: could not open disk image %s\n",
file);
return -1;
dev = usb_msd_init(p);
} else if (!strcmp(devname, "wacom-tablet")) {
dev = usb_wacom_init();
+ } else if (strstart(devname, "serial:", &p)) {
+ dev = usb_serial_init(p);
} else {
return -1;
}
qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME],
qemu_get_clock(rt_clock));
+ if (alarm_timer->flags & ALARM_FLAG_EXPIRED) {
+ alarm_timer->flags &= ~(ALARM_FLAG_EXPIRED);
+ qemu_rearm_alarm_timer(alarm_timer);
+ }
+
/* Check bottom-halves last in case any of the earlier events triggered
them. */
qemu_bh_poll();
static void help(int exitcode)
{
- printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2007 Fabrice Bellard\n"
+ printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n"
"usage: %s [options] [disk_image]\n"
"\n"
"'disk_image' is a raw hard image image for IDE hard disk 0\n"
"-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n"
"-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
"-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][index=i]\n"
- " [,cyls=c,heads=h,secs=s[,trans=t]][snapshot=on|off]\n"
+ " [,cyls=c,heads=h,secs=s[,trans=t]][snapshot=on|off]"
+ " [,cache=on|off]\n"
" use 'file' as a drive image\n"
"-mtdblock file use 'file' as on-board Flash memory image\n"
"-sd file use 'file' as SecureDigital card image\n"
qemu_register_machine(&ss10_machine);
qemu_register_machine(&ss600mp_machine);
qemu_register_machine(&ss20_machine);
+ qemu_register_machine(&ss2_machine);
+ qemu_register_machine(&ss1000_machine);
+ qemu_register_machine(&ss2000_machine);
#endif
#elif defined(TARGET_ARM)
qemu_register_machine(&integratorcp_machine);
break;
r = argv[optind];
if (r[0] != '-') {
- hda_index = drive_add(HD_ALIAS, argv[optind++], 0);
+ hda_index = drive_add(argv[optind++], HD_ALIAS, 0);
} else {
const QEMUOption *popt;
break;
case QEMU_OPTION_hda:
if (cyls == 0)
- hda_index = drive_add(HD_ALIAS, optarg, 0);
+ hda_index = drive_add(optarg, HD_ALIAS, 0);
else
- hda_index = drive_add(HD_ALIAS
+ hda_index = drive_add(optarg, HD_ALIAS
",cyls=%d,heads=%d,secs=%d%s",
- optarg, 0, cyls, heads, secs,
+ 0, cyls, heads, secs,
translation == BIOS_ATA_TRANSLATION_LBA ?
",trans=lba" :
translation == BIOS_ATA_TRANSLATION_NONE ?
case QEMU_OPTION_hdb:
case QEMU_OPTION_hdc:
case QEMU_OPTION_hdd:
- drive_add(HD_ALIAS, optarg, popt->index - QEMU_OPTION_hda);
+ drive_add(optarg, HD_ALIAS, popt->index - QEMU_OPTION_hda);
break;
case QEMU_OPTION_drive:
- drive_add("%s", optarg);
+ drive_add(NULL, "%s", optarg);
break;
case QEMU_OPTION_mtdblock:
- drive_add(MTD_ALIAS, optarg);
+ drive_add(optarg, MTD_ALIAS);
break;
case QEMU_OPTION_sd:
- drive_add("file=\"%s\"," SD_ALIAS, optarg);
+ drive_add(optarg, SD_ALIAS);
break;
case QEMU_OPTION_pflash:
- drive_add(PFLASH_ALIAS, optarg);
+ drive_add(optarg, PFLASH_ALIAS);
break;
case QEMU_OPTION_snapshot:
snapshot = 1;
exit(1);
}
if (hda_index != -1)
- snprintf(drives_opt[hda_index] +
- strlen(drives_opt[hda_index]),
- sizeof(drives_opt[0]) -
- strlen(drives_opt[hda_index]),
- ",cyls=%d,heads=%d,secs=%d%s",
- cyls, heads, secs,
+ snprintf(drives_opt[hda_index].opt,
+ sizeof(drives_opt[hda_index].opt),
+ HD_ALIAS ",cyls=%d,heads=%d,secs=%d%s",
+ 0, cyls, heads, secs,
translation == BIOS_ATA_TRANSLATION_LBA ?
",trans=lba" :
translation == BIOS_ATA_TRANSLATION_NONE ?
kernel_cmdline = optarg;
break;
case QEMU_OPTION_cdrom:
- drive_add("file=\"%s\"," CDROM_ALIAS, optarg);
+ drive_add(optarg, CDROM_ALIAS);
break;
case QEMU_OPTION_boot:
boot_devices = optarg;
break;
case QEMU_OPTION_fda:
case QEMU_OPTION_fdb:
- drive_add("file=\"%s\"," FD_ALIAS, optarg,
- popt->index - QEMU_OPTION_fda);
+ drive_add(optarg, FD_ALIAS, popt->index - QEMU_OPTION_fda);
break;
#ifdef TARGET_I386
case QEMU_OPTION_no_fd_bootchk:
#ifdef TARGET_ARM
case QEMU_OPTION_old_param:
old_param = 1;
+ break;
#endif
case QEMU_OPTION_clock:
configure_alarms(optarg);
/* we always create the cdrom drive, even if no disk is there */
if (nb_drives_opt < MAX_DRIVES)
- drive_add(CDROM_ALIAS);
+ drive_add(NULL, CDROM_ALIAS);
/* we always create at least one floppy */
if (nb_drives_opt < MAX_DRIVES)
- drive_add(FD_ALIAS, 0);
+ drive_add(NULL, FD_ALIAS, 0);
/* we always create one sd slot, even if no card is in it */
if (nb_drives_opt < MAX_DRIVES)
- drive_add(SD_ALIAS);
+ drive_add(NULL, SD_ALIAS);
/* open the virtual block devices */
for(i = 0; i < nb_drives_opt; i++)
- if (drive_init(drives_opt[i], snapshot, machine) == -1)
+ if (drive_init(&drives_opt[i], snapshot, machine) == -1)
exit(1);
register_savevm("timer", 0, 2, timer_save, timer_load, NULL);
s->down_script[0])
launch_script(s->down_script, ifname, s->fd);
}
- }
+ }
}
#endif
return 0;