Merge remote branch 'kwolf/for-anthony' into staging
Conflicts: hw/pc.c
This commit is contained in:
commit
a4673e2762
@ -44,7 +44,7 @@ fsdev-obj-$(CONFIG_LINUX) += $(addprefix fsdev/, $(fsdev-nested-y))
|
||||
# system emulation, i.e. a single QEMU executable should support all
|
||||
# CPUs and machines.
|
||||
|
||||
common-obj-y = $(block-obj-y)
|
||||
common-obj-y = $(block-obj-y) blockdev.o
|
||||
common-obj-y += $(net-obj-y)
|
||||
common-obj-y += $(qobject-obj-y)
|
||||
common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
|
||||
|
91
block.c
91
block.c
@ -331,8 +331,8 @@ static BlockDriver *find_image_format(const char *filename)
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
|
||||
/* Return the raw BlockDriver * to scsi-generic devices */
|
||||
if (bs->sg) {
|
||||
/* Return the raw BlockDriver * to scsi-generic devices or empty drives */
|
||||
if (bs->sg || !bdrv_is_inserted(bs)) {
|
||||
bdrv_delete(bs);
|
||||
return bdrv_find_format("raw");
|
||||
}
|
||||
@ -522,7 +522,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
|
||||
bdrv_delete(bs1);
|
||||
return ret;
|
||||
}
|
||||
total_size = bdrv_getlength(bs1) >> BDRV_SECTOR_BITS;
|
||||
total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK;
|
||||
|
||||
if (bs1->drv && bs1->drv->protocol_name)
|
||||
is_protocol = 1;
|
||||
@ -541,7 +541,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
|
||||
bdrv_qcow2 = bdrv_find_format("qcow2");
|
||||
options = parse_option_parameters("", bdrv_qcow2->create_options, NULL);
|
||||
|
||||
set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size * 512);
|
||||
set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size);
|
||||
set_option_parameter(options, BLOCK_OPT_BACKING_FILE, backing_filename);
|
||||
if (drv) {
|
||||
set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
|
||||
@ -648,6 +648,15 @@ void bdrv_close(BlockDriverState *bs)
|
||||
}
|
||||
}
|
||||
|
||||
void bdrv_close_all(void)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, list) {
|
||||
bdrv_close(bs);
|
||||
}
|
||||
}
|
||||
|
||||
void bdrv_delete(BlockDriverState *bs)
|
||||
{
|
||||
/* remove from list, if necessary */
|
||||
@ -684,7 +693,7 @@ int bdrv_commit(BlockDriverState *bs)
|
||||
int64_t i, total_sectors;
|
||||
int n, j, ro, open_flags;
|
||||
int ret = 0, rw_ret = 0;
|
||||
unsigned char sector[512];
|
||||
unsigned char sector[BDRV_SECTOR_SIZE];
|
||||
char filename[1024];
|
||||
BlockDriverState *bs_rw, *bs_ro;
|
||||
|
||||
@ -824,7 +833,8 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
|
||||
static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
|
||||
int nb_sectors)
|
||||
{
|
||||
return bdrv_check_byte_request(bs, sector_num * 512, nb_sectors * 512);
|
||||
return bdrv_check_byte_request(bs, sector_num * BDRV_SECTOR_SIZE,
|
||||
nb_sectors * BDRV_SECTOR_SIZE);
|
||||
}
|
||||
|
||||
/* return < 0 if error. See bdrv_write() for the return codes */
|
||||
@ -1059,7 +1069,7 @@ struct partition {
|
||||
static int guess_disk_lchs(BlockDriverState *bs,
|
||||
int *pcylinders, int *pheads, int *psectors)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
uint8_t buf[BDRV_SECTOR_SIZE];
|
||||
int ret, i, heads, sectors, cylinders;
|
||||
struct partition *p;
|
||||
uint32_t nr_sects;
|
||||
@ -1535,7 +1545,7 @@ static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
|
||||
"} }",
|
||||
bs->rd_bytes, bs->wr_bytes,
|
||||
bs->rd_ops, bs->wr_ops,
|
||||
bs->wr_highest_sector * 512);
|
||||
bs->wr_highest_sector * (long)BDRV_SECTOR_SIZE);
|
||||
dict = qobject_to_qdict(res);
|
||||
|
||||
if (*bs->device_name) {
|
||||
@ -1621,9 +1631,11 @@ int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_save_vmstate)
|
||||
return -ENOTSUP;
|
||||
return drv->bdrv_save_vmstate(bs, buf, pos, size);
|
||||
if (drv->bdrv_save_vmstate)
|
||||
return drv->bdrv_save_vmstate(bs, buf, pos, size);
|
||||
if (bs->file)
|
||||
return bdrv_save_vmstate(bs->file, buf, pos, size);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
|
||||
@ -1632,9 +1644,11 @@ int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_load_vmstate)
|
||||
return -ENOTSUP;
|
||||
return drv->bdrv_load_vmstate(bs, buf, pos, size);
|
||||
if (drv->bdrv_load_vmstate)
|
||||
return drv->bdrv_load_vmstate(bs, buf, pos, size);
|
||||
if (bs->file)
|
||||
return bdrv_load_vmstate(bs->file, buf, pos, size);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event)
|
||||
@ -1658,20 +1672,37 @@ int bdrv_snapshot_create(BlockDriverState *bs,
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_snapshot_create)
|
||||
return -ENOTSUP;
|
||||
return drv->bdrv_snapshot_create(bs, sn_info);
|
||||
if (drv->bdrv_snapshot_create)
|
||||
return drv->bdrv_snapshot_create(bs, sn_info);
|
||||
if (bs->file)
|
||||
return bdrv_snapshot_create(bs->file, sn_info);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int bdrv_snapshot_goto(BlockDriverState *bs,
|
||||
const char *snapshot_id)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
int ret, open_ret;
|
||||
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_snapshot_goto)
|
||||
return -ENOTSUP;
|
||||
return drv->bdrv_snapshot_goto(bs, snapshot_id);
|
||||
if (drv->bdrv_snapshot_goto)
|
||||
return drv->bdrv_snapshot_goto(bs, snapshot_id);
|
||||
|
||||
if (bs->file) {
|
||||
drv->bdrv_close(bs);
|
||||
ret = bdrv_snapshot_goto(bs->file, snapshot_id);
|
||||
open_ret = drv->bdrv_open(bs, bs->open_flags);
|
||||
if (open_ret < 0) {
|
||||
bdrv_delete(bs->file);
|
||||
bs->drv = NULL;
|
||||
return open_ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
|
||||
@ -1679,9 +1710,11 @@ int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_snapshot_delete)
|
||||
return -ENOTSUP;
|
||||
return drv->bdrv_snapshot_delete(bs, snapshot_id);
|
||||
if (drv->bdrv_snapshot_delete)
|
||||
return drv->bdrv_snapshot_delete(bs, snapshot_id);
|
||||
if (bs->file)
|
||||
return bdrv_snapshot_delete(bs->file, snapshot_id);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int bdrv_snapshot_list(BlockDriverState *bs,
|
||||
@ -1690,9 +1723,11 @@ int bdrv_snapshot_list(BlockDriverState *bs,
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_snapshot_list)
|
||||
return -ENOTSUP;
|
||||
return drv->bdrv_snapshot_list(bs, psn_info);
|
||||
if (drv->bdrv_snapshot_list)
|
||||
return drv->bdrv_snapshot_list(bs, psn_info);
|
||||
if (bs->file)
|
||||
return bdrv_snapshot_list(bs->file, psn_info);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
#define NB_SUFFIXES 4
|
||||
@ -2197,7 +2232,7 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
async_ret = NOT_DONE;
|
||||
iov.iov_base = (void *)buf;
|
||||
iov.iov_len = nb_sectors * 512;
|
||||
iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE;
|
||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||
acb = bdrv_aio_readv(bs, sector_num, &qiov, nb_sectors,
|
||||
bdrv_rw_em_cb, &async_ret);
|
||||
@ -2228,7 +2263,7 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
async_ret = NOT_DONE;
|
||||
iov.iov_base = (void *)buf;
|
||||
iov.iov_len = nb_sectors * 512;
|
||||
iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE;
|
||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||
acb = bdrv_aio_writev(bs, sector_num, &qiov, nb_sectors,
|
||||
bdrv_rw_em_cb, &async_ret);
|
||||
|
1
block.h
1
block.h
@ -123,6 +123,7 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
|
||||
/* Ensure contents are flushed to disk. */
|
||||
void bdrv_flush(BlockDriverState *bs);
|
||||
void bdrv_flush_all(void);
|
||||
void bdrv_close_all(void);
|
||||
|
||||
int bdrv_has_zero_init(BlockDriverState *bs);
|
||||
int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
|
||||
|
@ -392,8 +392,9 @@ static int raw_read(BlockDriverState *bs, int64_t sector_num,
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = raw_pread(bs, sector_num * 512, buf, nb_sectors * 512);
|
||||
if (ret == (nb_sectors * 512))
|
||||
ret = raw_pread(bs, sector_num * BDRV_SECTOR_SIZE, buf,
|
||||
nb_sectors * BDRV_SECTOR_SIZE);
|
||||
if (ret == (nb_sectors * BDRV_SECTOR_SIZE))
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
@ -480,8 +481,9 @@ static int raw_write(BlockDriverState *bs, int64_t sector_num,
|
||||
const uint8_t *buf, int nb_sectors)
|
||||
{
|
||||
int ret;
|
||||
ret = raw_pwrite(bs, sector_num * 512, buf, nb_sectors * 512);
|
||||
if (ret == (nb_sectors * 512))
|
||||
ret = raw_pwrite(bs, sector_num * BDRV_SECTOR_SIZE, buf,
|
||||
nb_sectors * BDRV_SECTOR_SIZE);
|
||||
if (ret == (nb_sectors * BDRV_SECTOR_SIZE))
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
@ -494,7 +496,7 @@ static int qiov_is_aligned(QEMUIOVector *qiov)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < qiov->niov; i++) {
|
||||
if ((uintptr_t) qiov->iov[i].iov_base % 512) {
|
||||
if ((uintptr_t) qiov->iov[i].iov_base % BDRV_SECTOR_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -703,7 +705,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options)
|
||||
/* Read out options */
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
||||
total_size = options->value.n / 512;
|
||||
total_size = options->value.n / BDRV_SECTOR_SIZE;
|
||||
}
|
||||
options++;
|
||||
}
|
||||
@ -713,7 +715,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options)
|
||||
if (fd < 0) {
|
||||
result = -errno;
|
||||
} else {
|
||||
if (ftruncate(fd, total_size * 512) != 0) {
|
||||
if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) {
|
||||
result = -errno;
|
||||
}
|
||||
if (close(fd) != 0) {
|
||||
@ -976,7 +978,7 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options)
|
||||
/* Read out options */
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, "size")) {
|
||||
total_size = options->value.n / 512;
|
||||
total_size = options->value.n / BDRV_SECTOR_SIZE;
|
||||
}
|
||||
options++;
|
||||
}
|
||||
@ -989,7 +991,7 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options)
|
||||
ret = -errno;
|
||||
else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
|
||||
ret = -ENODEV;
|
||||
else if (lseek(fd, 0, SEEK_END) < total_size * 512)
|
||||
else if (lseek(fd, 0, SEEK_END) < total_size * BDRV_SECTOR_SIZE)
|
||||
ret = -ENOSPC;
|
||||
|
||||
close(fd);
|
||||
|
600
blockdev.c
Normal file
600
blockdev.c
Normal file
@ -0,0 +1,600 @@
|
||||
/*
|
||||
* QEMU host block devices
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
* later. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "block.h"
|
||||
#include "blockdev.h"
|
||||
#include "monitor.h"
|
||||
#include "qerror.h"
|
||||
#include "qemu-option.h"
|
||||
#include "qemu-config.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives);
|
||||
|
||||
QemuOpts *drive_add(const char *file, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char optstr[1024];
|
||||
QemuOpts *opts;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(optstr, sizeof(optstr), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0);
|
||||
if (!opts) {
|
||||
return NULL;
|
||||
}
|
||||
if (file)
|
||||
qemu_opt_set(opts, "file", file);
|
||||
return opts;
|
||||
}
|
||||
|
||||
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
|
||||
{
|
||||
DriveInfo *dinfo;
|
||||
|
||||
/* seek interface, bus and unit */
|
||||
|
||||
QTAILQ_FOREACH(dinfo, &drives, next) {
|
||||
if (dinfo->type == type &&
|
||||
dinfo->bus == bus &&
|
||||
dinfo->unit == unit)
|
||||
return dinfo;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DriveInfo *drive_get_by_id(const char *id)
|
||||
{
|
||||
DriveInfo *dinfo;
|
||||
|
||||
QTAILQ_FOREACH(dinfo, &drives, next) {
|
||||
if (strcmp(id, dinfo->id))
|
||||
continue;
|
||||
return dinfo;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int drive_get_max_bus(BlockInterfaceType type)
|
||||
{
|
||||
int max_bus;
|
||||
DriveInfo *dinfo;
|
||||
|
||||
max_bus = -1;
|
||||
QTAILQ_FOREACH(dinfo, &drives, next) {
|
||||
if(dinfo->type == type &&
|
||||
dinfo->bus > max_bus)
|
||||
max_bus = dinfo->bus;
|
||||
}
|
||||
return max_bus;
|
||||
}
|
||||
|
||||
const char *drive_get_serial(BlockDriverState *bdrv)
|
||||
{
|
||||
DriveInfo *dinfo;
|
||||
|
||||
QTAILQ_FOREACH(dinfo, &drives, next) {
|
||||
if (dinfo->bdrv == bdrv)
|
||||
return dinfo->serial;
|
||||
}
|
||||
|
||||
return "\0";
|
||||
}
|
||||
|
||||
BlockInterfaceErrorAction drive_get_on_error(
|
||||
BlockDriverState *bdrv, int is_read)
|
||||
{
|
||||
DriveInfo *dinfo;
|
||||
|
||||
QTAILQ_FOREACH(dinfo, &drives, next) {
|
||||
if (dinfo->bdrv == bdrv)
|
||||
return is_read ? dinfo->on_read_error : dinfo->on_write_error;
|
||||
}
|
||||
|
||||
return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC;
|
||||
}
|
||||
|
||||
static void bdrv_format_print(void *opaque, const char *name)
|
||||
{
|
||||
fprintf(stderr, " %s", name);
|
||||
}
|
||||
|
||||
void drive_uninit(DriveInfo *dinfo)
|
||||
{
|
||||
qemu_opts_del(dinfo->opts);
|
||||
bdrv_delete(dinfo->bdrv);
|
||||
QTAILQ_REMOVE(&drives, dinfo, next);
|
||||
qemu_free(dinfo);
|
||||
}
|
||||
|
||||
static int parse_block_error_action(const char *buf, int is_read)
|
||||
{
|
||||
if (!strcmp(buf, "ignore")) {
|
||||
return BLOCK_ERR_IGNORE;
|
||||
} else if (!is_read && !strcmp(buf, "enospc")) {
|
||||
return BLOCK_ERR_STOP_ENOSPC;
|
||||
} else if (!strcmp(buf, "stop")) {
|
||||
return BLOCK_ERR_STOP_ANY;
|
||||
} else if (!strcmp(buf, "report")) {
|
||||
return BLOCK_ERR_REPORT;
|
||||
} else {
|
||||
fprintf(stderr, "qemu: '%s' invalid %s error action\n",
|
||||
buf, is_read ? "read" : "write");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
|
||||
{
|
||||
const char *buf;
|
||||
const char *file = NULL;
|
||||
char devname[128];
|
||||
const char *serial;
|
||||
const char *mediastr = "";
|
||||
BlockInterfaceType type;
|
||||
enum { MEDIA_DISK, MEDIA_CDROM } media;
|
||||
int bus_id, unit_id;
|
||||
int cyls, heads, secs, translation;
|
||||
BlockDriver *drv = NULL;
|
||||
int max_devs;
|
||||
int index;
|
||||
int ro = 0;
|
||||
int bdrv_flags = 0;
|
||||
int on_read_error, on_write_error;
|
||||
const char *devaddr;
|
||||
DriveInfo *dinfo;
|
||||
int snapshot = 0;
|
||||
int ret;
|
||||
|
||||
*fatal_error = 1;
|
||||
|
||||
translation = BIOS_ATA_TRANSLATION_AUTO;
|
||||
|
||||
if (default_to_scsi) {
|
||||
type = IF_SCSI;
|
||||
max_devs = MAX_SCSI_DEVS;
|
||||
pstrcpy(devname, sizeof(devname), "scsi");
|
||||
} else {
|
||||
type = IF_IDE;
|
||||
max_devs = MAX_IDE_DEVS;
|
||||
pstrcpy(devname, sizeof(devname), "ide");
|
||||
}
|
||||
media = MEDIA_DISK;
|
||||
|
||||
/* extract parameters */
|
||||
bus_id = qemu_opt_get_number(opts, "bus", 0);
|
||||
unit_id = qemu_opt_get_number(opts, "unit", -1);
|
||||
index = qemu_opt_get_number(opts, "index", -1);
|
||||
|
||||
cyls = qemu_opt_get_number(opts, "cyls", 0);
|
||||
heads = qemu_opt_get_number(opts, "heads", 0);
|
||||
secs = qemu_opt_get_number(opts, "secs", 0);
|
||||
|
||||
snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
|
||||
ro = qemu_opt_get_bool(opts, "readonly", 0);
|
||||
|
||||
file = qemu_opt_get(opts, "file");
|
||||
serial = qemu_opt_get(opts, "serial");
|
||||
|
||||
if ((buf = qemu_opt_get(opts, "if")) != NULL) {
|
||||
pstrcpy(devname, sizeof(devname), buf);
|
||||
if (!strcmp(buf, "ide")) {
|
||||
type = IF_IDE;
|
||||
max_devs = MAX_IDE_DEVS;
|
||||
} else if (!strcmp(buf, "scsi")) {
|
||||
type = IF_SCSI;
|
||||
max_devs = MAX_SCSI_DEVS;
|
||||
} else if (!strcmp(buf, "floppy")) {
|
||||
type = IF_FLOPPY;
|
||||
max_devs = 0;
|
||||
} else if (!strcmp(buf, "pflash")) {
|
||||
type = IF_PFLASH;
|
||||
max_devs = 0;
|
||||
} else if (!strcmp(buf, "mtd")) {
|
||||
type = IF_MTD;
|
||||
max_devs = 0;
|
||||
} else if (!strcmp(buf, "sd")) {
|
||||
type = IF_SD;
|
||||
max_devs = 0;
|
||||
} else if (!strcmp(buf, "virtio")) {
|
||||
type = IF_VIRTIO;
|
||||
max_devs = 0;
|
||||
} else if (!strcmp(buf, "xen")) {
|
||||
type = IF_XEN;
|
||||
max_devs = 0;
|
||||
} else if (!strcmp(buf, "none")) {
|
||||
type = IF_NONE;
|
||||
max_devs = 0;
|
||||
} else {
|
||||
fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (cyls || heads || secs) {
|
||||
if (cyls < 1 || (type == IF_IDE && cyls > 16383)) {
|
||||
fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
if (heads < 1 || (type == IF_IDE && heads > 16)) {
|
||||
fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
if (secs < 1 || (type == IF_IDE && secs > 63)) {
|
||||
fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((buf = qemu_opt_get(opts, "trans")) != NULL) {
|
||||
if (!cyls) {
|
||||
fprintf(stderr,
|
||||
"qemu: '%s' trans must be used with cyls,heads and secs\n",
|
||||
buf);
|
||||
return NULL;
|
||||
}
|
||||
if (!strcmp(buf, "none"))
|
||||
translation = BIOS_ATA_TRANSLATION_NONE;
|
||||
else if (!strcmp(buf, "lba"))
|
||||
translation = BIOS_ATA_TRANSLATION_LBA;
|
||||
else if (!strcmp(buf, "auto"))
|
||||
translation = BIOS_ATA_TRANSLATION_AUTO;
|
||||
else {
|
||||
fprintf(stderr, "qemu: '%s' invalid translation type\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((buf = qemu_opt_get(opts, "media")) != NULL) {
|
||||
if (!strcmp(buf, "disk")) {
|
||||
media = MEDIA_DISK;
|
||||
} else if (!strcmp(buf, "cdrom")) {
|
||||
if (cyls || secs || heads) {
|
||||
fprintf(stderr,
|
||||
"qemu: '%s' invalid physical CHS format\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
media = MEDIA_CDROM;
|
||||
} else {
|
||||
fprintf(stderr, "qemu: '%s' invalid media\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((buf = qemu_opt_get(opts, "cache")) != NULL) {
|
||||
if (!strcmp(buf, "off") || !strcmp(buf, "none")) {
|
||||
bdrv_flags |= BDRV_O_NOCACHE;
|
||||
} else if (!strcmp(buf, "writeback")) {
|
||||
bdrv_flags |= BDRV_O_CACHE_WB;
|
||||
} else if (!strcmp(buf, "unsafe")) {
|
||||
bdrv_flags |= BDRV_O_CACHE_WB;
|
||||
bdrv_flags |= BDRV_O_NO_FLUSH;
|
||||
} else if (!strcmp(buf, "writethrough")) {
|
||||
/* this is the default */
|
||||
} else {
|
||||
fprintf(stderr, "qemu: invalid cache option\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
if ((buf = qemu_opt_get(opts, "aio")) != NULL) {
|
||||
if (!strcmp(buf, "native")) {
|
||||
bdrv_flags |= BDRV_O_NATIVE_AIO;
|
||||
} else if (!strcmp(buf, "threads")) {
|
||||
/* this is the default */
|
||||
} else {
|
||||
fprintf(stderr, "qemu: invalid aio option\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((buf = qemu_opt_get(opts, "format")) != NULL) {
|
||||
if (strcmp(buf, "?") == 0) {
|
||||
fprintf(stderr, "qemu: Supported formats:");
|
||||
bdrv_iterate_format(bdrv_format_print, NULL);
|
||||
fprintf(stderr, "\n");
|
||||
return NULL;
|
||||
}
|
||||
drv = bdrv_find_whitelisted_format(buf);
|
||||
if (!drv) {
|
||||
fprintf(stderr, "qemu: '%s' invalid format\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
on_write_error = BLOCK_ERR_STOP_ENOSPC;
|
||||
if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
|
||||
if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
|
||||
fprintf(stderr, "werror is no supported by this format\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
on_write_error = parse_block_error_action(buf, 0);
|
||||
if (on_write_error < 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
on_read_error = BLOCK_ERR_REPORT;
|
||||
if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
|
||||
if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) {
|
||||
fprintf(stderr, "rerror is no supported by this format\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
on_read_error = parse_block_error_action(buf, 1);
|
||||
if (on_read_error < 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) {
|
||||
if (type != IF_VIRTIO) {
|
||||
fprintf(stderr, "addr is not supported\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* compute bus and unit according index */
|
||||
|
||||
if (index != -1) {
|
||||
if (bus_id != 0 || unit_id != -1) {
|
||||
fprintf(stderr,
|
||||
"qemu: index cannot be used with bus and unit\n");
|
||||
return NULL;
|
||||
}
|
||||
if (max_devs == 0)
|
||||
{
|
||||
unit_id = index;
|
||||
bus_id = 0;
|
||||
} else {
|
||||
unit_id = index % max_devs;
|
||||
bus_id = index / max_devs;
|
||||
}
|
||||
}
|
||||
|
||||
/* if user doesn't specify a unit_id,
|
||||
* try to find the first free
|
||||
*/
|
||||
|
||||
if (unit_id == -1) {
|
||||
unit_id = 0;
|
||||
while (drive_get(type, bus_id, unit_id) != NULL) {
|
||||
unit_id++;
|
||||
if (max_devs && unit_id >= max_devs) {
|
||||
unit_id -= max_devs;
|
||||
bus_id++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check unit id */
|
||||
|
||||
if (max_devs && unit_id >= max_devs) {
|
||||
fprintf(stderr, "qemu: unit %d too big (max is %d)\n",
|
||||
unit_id, max_devs - 1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* ignore multiple definitions
|
||||
*/
|
||||
|
||||
if (drive_get(type, bus_id, unit_id) != NULL) {
|
||||
*fatal_error = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* init */
|
||||
|
||||
dinfo = qemu_mallocz(sizeof(*dinfo));
|
||||
if ((buf = qemu_opts_id(opts)) != NULL) {
|
||||
dinfo->id = qemu_strdup(buf);
|
||||
} else {
|
||||
/* no id supplied -> create one */
|
||||
dinfo->id = qemu_mallocz(32);
|
||||
if (type == IF_IDE || type == IF_SCSI)
|
||||
mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
|
||||
if (max_devs)
|
||||
snprintf(dinfo->id, 32, "%s%i%s%i",
|
||||
devname, bus_id, mediastr, unit_id);
|
||||
else
|
||||
snprintf(dinfo->id, 32, "%s%s%i",
|
||||
devname, mediastr, unit_id);
|
||||
}
|
||||
dinfo->bdrv = bdrv_new(dinfo->id);
|
||||
dinfo->devaddr = devaddr;
|
||||
dinfo->type = type;
|
||||
dinfo->bus = bus_id;
|
||||
dinfo->unit = unit_id;
|
||||
dinfo->on_read_error = on_read_error;
|
||||
dinfo->on_write_error = on_write_error;
|
||||
dinfo->opts = opts;
|
||||
if (serial)
|
||||
strncpy(dinfo->serial, serial, sizeof(dinfo->serial) - 1);
|
||||
QTAILQ_INSERT_TAIL(&drives, dinfo, next);
|
||||
|
||||
switch(type) {
|
||||
case IF_IDE:
|
||||
case IF_SCSI:
|
||||
case IF_XEN:
|
||||
case IF_NONE:
|
||||
switch(media) {
|
||||
case MEDIA_DISK:
|
||||
if (cyls != 0) {
|
||||
bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs);
|
||||
bdrv_set_translation_hint(dinfo->bdrv, translation);
|
||||
}
|
||||
break;
|
||||
case MEDIA_CDROM:
|
||||
bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IF_SD:
|
||||
/* FIXME: This isn't really a floppy, but it's a reasonable
|
||||
approximation. */
|
||||
case IF_FLOPPY:
|
||||
bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY);
|
||||
break;
|
||||
case IF_PFLASH:
|
||||
case IF_MTD:
|
||||
break;
|
||||
case IF_VIRTIO:
|
||||
/* add virtio block device */
|
||||
opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
|
||||
qemu_opt_set(opts, "driver", "virtio-blk-pci");
|
||||
qemu_opt_set(opts, "drive", dinfo->id);
|
||||
if (devaddr)
|
||||
qemu_opt_set(opts, "addr", devaddr);
|
||||
break;
|
||||
case IF_COUNT:
|
||||
abort();
|
||||
}
|
||||
if (!file) {
|
||||
*fatal_error = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (snapshot) {
|
||||
/* always use cache=unsafe with snapshot */
|
||||
bdrv_flags &= ~BDRV_O_CACHE_MASK;
|
||||
bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
|
||||
}
|
||||
|
||||
if (media == MEDIA_CDROM) {
|
||||
/* CDROM is fine for any interface, don't check. */
|
||||
ro = 1;
|
||||
} else if (ro == 1) {
|
||||
if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
|
||||
fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
|
||||
|
||||
ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "qemu: could not open disk image %s: %s\n",
|
||||
file, strerror(-ret));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (bdrv_key_required(dinfo->bdrv))
|
||||
autostart = 0;
|
||||
*fatal_error = 0;
|
||||
return dinfo;
|
||||
}
|
||||
|
||||
void do_commit(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
int all_devices;
|
||||
DriveInfo *dinfo;
|
||||
const char *device = qdict_get_str(qdict, "device");
|
||||
|
||||
all_devices = !strcmp(device, "all");
|
||||
QTAILQ_FOREACH(dinfo, &drives, next) {
|
||||
if (!all_devices)
|
||||
if (strcmp(bdrv_get_device_name(dinfo->bdrv), device))
|
||||
continue;
|
||||
bdrv_commit(dinfo->bdrv);
|
||||
}
|
||||
}
|
||||
|
||||
static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
|
||||
{
|
||||
if (bdrv_is_inserted(bs)) {
|
||||
if (!force) {
|
||||
if (!bdrv_is_removable(bs)) {
|
||||
qerror_report(QERR_DEVICE_NOT_REMOVABLE,
|
||||
bdrv_get_device_name(bs));
|
||||
return -1;
|
||||
}
|
||||
if (bdrv_is_locked(bs)) {
|
||||
qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
bdrv_close(bs);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
int force = qdict_get_int(qdict, "force");
|
||||
const char *filename = qdict_get_str(qdict, "device");
|
||||
|
||||
bs = bdrv_find(filename);
|
||||
if (!bs) {
|
||||
qerror_report(QERR_DEVICE_NOT_FOUND, filename);
|
||||
return -1;
|
||||
}
|
||||
return eject_device(mon, bs, force);
|
||||
}
|
||||
|
||||
int do_block_set_passwd(Monitor *mon, const QDict *qdict,
|
||||
QObject **ret_data)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
int err;
|
||||
|
||||
bs = bdrv_find(qdict_get_str(qdict, "device"));
|
||||
if (!bs) {
|
||||
qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = bdrv_set_key(bs, qdict_get_str(qdict, "password"));
|
||||
if (err == -EINVAL) {
|
||||
qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
|
||||
return -1;
|
||||
} else if (err < 0) {
|
||||
qerror_report(QERR_INVALID_PASSWORD);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_change_block(Monitor *mon, const char *device,
|
||||
const char *filename, const char *fmt)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
BlockDriver *drv = NULL;
|
||||
int bdrv_flags;
|
||||
|
||||
bs = bdrv_find(device);
|
||||
if (!bs) {
|
||||
qerror_report(QERR_DEVICE_NOT_FOUND, device);
|
||||
return -1;
|
||||
}
|
||||
if (fmt) {
|
||||
drv = bdrv_find_whitelisted_format(fmt);
|
||||
if (!drv) {
|
||||
qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (eject_device(mon, bs, 0) < 0) {
|
||||
return -1;
|
||||
}
|
||||
bdrv_flags = bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM ? 0 : BDRV_O_RDWR;
|
||||
if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) {
|
||||
qerror_report(QERR_OPEN_FILE_FAILED, filename);
|
||||
return -1;
|
||||
}
|
||||
return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
|
||||
}
|
71
blockdev.h
Normal file
71
blockdev.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* QEMU host block devices
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
* later. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef BLOCKDEV_H
|
||||
#define BLOCKDEV_H
|
||||
|
||||
#include "block.h"
|
||||
#include "qemu-queue.h"
|
||||
|
||||
typedef enum {
|
||||
IF_NONE,
|
||||
IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
|
||||
IF_COUNT
|
||||
} BlockInterfaceType;
|
||||
|
||||
typedef enum {
|
||||
BLOCK_ERR_REPORT, BLOCK_ERR_IGNORE, BLOCK_ERR_STOP_ENOSPC,
|
||||
BLOCK_ERR_STOP_ANY
|
||||
} BlockInterfaceErrorAction;
|
||||
|
||||
#define BLOCK_SERIAL_STRLEN 20
|
||||
|
||||
typedef struct DriveInfo {
|
||||
BlockDriverState *bdrv;
|
||||
char *id;
|
||||
const char *devaddr;
|
||||
BlockInterfaceType type;
|
||||
int bus;
|
||||
int unit;
|
||||
QemuOpts *opts;
|
||||
BlockInterfaceErrorAction on_read_error;
|
||||
BlockInterfaceErrorAction on_write_error;
|
||||
char serial[BLOCK_SERIAL_STRLEN + 1];
|
||||
QTAILQ_ENTRY(DriveInfo) next;
|
||||
} DriveInfo;
|
||||
|
||||
#define MAX_IDE_DEVS 2
|
||||
#define MAX_SCSI_DEVS 7
|
||||
|
||||
extern QTAILQ_HEAD(drivelist, DriveInfo) drives;
|
||||
|
||||
extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
|
||||
extern DriveInfo *drive_get_by_id(const char *id);
|
||||
extern int drive_get_max_bus(BlockInterfaceType type);
|
||||
extern void drive_uninit(DriveInfo *dinfo);
|
||||
extern const char *drive_get_serial(BlockDriverState *bdrv);
|
||||
|
||||
extern BlockInterfaceErrorAction drive_get_on_error(
|
||||
BlockDriverState *bdrv, int is_read);
|
||||
|
||||
extern QemuOpts *drive_add(const char *file, const char *fmt, ...);
|
||||
extern DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi,
|
||||
int *fatal_error);
|
||||
|
||||
/* device-hotplug */
|
||||
|
||||
DriveInfo *add_init_drive(const char *opts);
|
||||
|
||||
void do_commit(Monitor *mon, const QDict *qdict);
|
||||
int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data);
|
||||
int do_block_set_passwd(Monitor *mon, const QDict *qdict, QObject **ret_data);
|
||||
int do_change_block(Monitor *mon, const char *device,
|
||||
const char *filename, const char *fmt);
|
||||
|
||||
#endif
|
@ -21,6 +21,7 @@
|
||||
#include "pm_smbus.h"
|
||||
#include "pci.h"
|
||||
#include "acpi.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "pci_host.h"
|
||||
#include "rwhandler.h"
|
||||
#include "apb_pci.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
/* debug APB */
|
||||
//#define DEBUG_APB
|
||||
|
@ -25,8 +25,6 @@
|
||||
#include "hw.h"
|
||||
#include "boards.h"
|
||||
#include "net.h"
|
||||
#include "block_int.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
DriveInfo *add_init_drive(const char *optstr)
|
||||
{
|
||||
@ -38,7 +36,7 @@ DriveInfo *add_init_drive(const char *optstr)
|
||||
if (!opts)
|
||||
return NULL;
|
||||
|
||||
dinfo = drive_init(opts, current_machine, &fatal_error);
|
||||
dinfo = drive_init(opts, current_machine->use_scsi, &fatal_error);
|
||||
if (!dinfo) {
|
||||
qemu_opts_del(opts);
|
||||
return NULL;
|
||||
|
1
hw/fdc.c
1
hw/fdc.c
@ -29,7 +29,6 @@
|
||||
|
||||
#include "hw.h"
|
||||
#include "fdc.h"
|
||||
#include "block.h"
|
||||
#include "qemu-timer.h"
|
||||
#include "isa.h"
|
||||
#include "sysbus.h"
|
||||
|
2
hw/fdc.h
2
hw/fdc.h
@ -2,7 +2,7 @@
|
||||
#define HW_FDC_H
|
||||
|
||||
/* fdc.c */
|
||||
#include "sysemu.h"
|
||||
#include "blockdev.h"
|
||||
#define MAX_FD 2
|
||||
|
||||
typedef struct FDCtrl FDCtrl;
|
||||
|
@ -260,8 +260,8 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
|
||||
irq = qemu_allocate_irqs(cmd646_set_irq, d, 2);
|
||||
ide_bus_new(&d->bus[0], &d->dev.qdev);
|
||||
ide_bus_new(&d->bus[1], &d->dev.qdev);
|
||||
ide_init2(&d->bus[0], NULL, NULL, irq[0]);
|
||||
ide_init2(&d->bus[1], NULL, NULL, irq[1]);
|
||||
ide_init2(&d->bus[0], irq[0]);
|
||||
ide_init2(&d->bus[1], irq[1]);
|
||||
|
||||
vmstate_register(0, &vmstate_ide_pci, d);
|
||||
qemu_register_reset(cmd646_reset, d);
|
||||
|
108
hw/ide/core.c
108
hw/ide/core.c
@ -26,8 +26,6 @@
|
||||
#include <hw/pc.h>
|
||||
#include <hw/pci.h>
|
||||
#include <hw/scsi.h>
|
||||
#include "block.h"
|
||||
#include "block_int.h"
|
||||
#include "qemu-timer.h"
|
||||
#include "sysemu.h"
|
||||
#include "dma.h"
|
||||
@ -98,6 +96,7 @@ static void ide_identify(IDEState *s)
|
||||
{
|
||||
uint16_t *p;
|
||||
unsigned int oldsize;
|
||||
IDEDevice *dev;
|
||||
|
||||
if (s->identify_set) {
|
||||
memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
|
||||
@ -165,8 +164,9 @@ static void ide_identify(IDEState *s)
|
||||
put_le16(p + 101, s->nb_sectors >> 16);
|
||||
put_le16(p + 102, s->nb_sectors >> 32);
|
||||
put_le16(p + 103, s->nb_sectors >> 48);
|
||||
if (s->conf && s->conf->physical_block_size)
|
||||
put_le16(p + 106, 0x6000 | get_physical_block_exp(s->conf));
|
||||
dev = s->unit ? s->bus->slave : s->bus->master;
|
||||
if (dev && dev->conf.physical_block_size)
|
||||
put_le16(p + 106, 0x6000 | get_physical_block_exp(&dev->conf));
|
||||
|
||||
memcpy(s->identify_data, p, sizeof(s->identify_data));
|
||||
s->identify_set = 1;
|
||||
@ -2594,39 +2594,35 @@ void ide_bus_reset(IDEBus *bus)
|
||||
ide_clear_hob(bus);
|
||||
}
|
||||
|
||||
void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf,
|
||||
const char *version)
|
||||
void ide_init_drive(IDEState *s, DriveInfo *dinfo,
|
||||
const char *version, const char *serial)
|
||||
{
|
||||
int cylinders, heads, secs;
|
||||
uint64_t nb_sectors;
|
||||
|
||||
if (dinfo && dinfo->bdrv) {
|
||||
s->bs = dinfo->bdrv;
|
||||
bdrv_get_geometry(s->bs, &nb_sectors);
|
||||
bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
|
||||
s->cylinders = cylinders;
|
||||
s->heads = heads;
|
||||
s->sectors = secs;
|
||||
s->nb_sectors = nb_sectors;
|
||||
/* The SMART values should be preserved across power cycles
|
||||
but they aren't. */
|
||||
s->smart_enabled = 1;
|
||||
s->smart_autosave = 1;
|
||||
s->smart_errors = 0;
|
||||
s->smart_selftest_count = 0;
|
||||
if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
|
||||
s->is_cdrom = 1;
|
||||
bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
|
||||
}
|
||||
strncpy(s->drive_serial_str, drive_get_serial(s->bs),
|
||||
sizeof(s->drive_serial_str));
|
||||
if (conf) {
|
||||
s->conf = conf;
|
||||
}
|
||||
s->bs = dinfo->bdrv;
|
||||
bdrv_get_geometry(s->bs, &nb_sectors);
|
||||
bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
|
||||
s->cylinders = cylinders;
|
||||
s->heads = heads;
|
||||
s->sectors = secs;
|
||||
s->nb_sectors = nb_sectors;
|
||||
/* The SMART values should be preserved across power cycles
|
||||
but they aren't. */
|
||||
s->smart_enabled = 1;
|
||||
s->smart_autosave = 1;
|
||||
s->smart_errors = 0;
|
||||
s->smart_selftest_count = 0;
|
||||
if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
|
||||
s->is_cdrom = 1;
|
||||
bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
|
||||
}
|
||||
if (strlen(s->drive_serial_str) == 0)
|
||||
if (serial && *serial) {
|
||||
strncpy(s->drive_serial_str, serial, sizeof(s->drive_serial_str));
|
||||
} else {
|
||||
snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
|
||||
"QM%05d", s->drive_serial);
|
||||
}
|
||||
if (version) {
|
||||
pstrcpy(s->version, sizeof(s->version), version);
|
||||
} else {
|
||||
@ -2635,27 +2631,47 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf,
|
||||
ide_reset(s);
|
||||
}
|
||||
|
||||
void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
|
||||
qemu_irq irq)
|
||||
static void ide_init1(IDEBus *bus, int unit)
|
||||
{
|
||||
IDEState *s;
|
||||
static int drive_serial = 1;
|
||||
IDEState *s = &bus->ifs[unit];
|
||||
|
||||
s->bus = bus;
|
||||
s->unit = unit;
|
||||
s->drive_serial = drive_serial++;
|
||||
s->io_buffer = qemu_blockalign(s->bs, IDE_DMA_BUF_SECTORS*512 + 4);
|
||||
s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
|
||||
s->smart_selftest_data = qemu_blockalign(s->bs, 512);
|
||||
s->sector_write_timer = qemu_new_timer(vm_clock,
|
||||
ide_sector_write_timer_cb, s);
|
||||
}
|
||||
|
||||
void ide_init2(IDEBus *bus, qemu_irq irq)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 2; i++) {
|
||||
s = bus->ifs + i;
|
||||
s->bus = bus;
|
||||
s->unit = i;
|
||||
s->drive_serial = drive_serial++;
|
||||
s->io_buffer = qemu_blockalign(s->bs, IDE_DMA_BUF_SECTORS*512 + 4);
|
||||
s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
|
||||
s->smart_selftest_data = qemu_blockalign(s->bs, 512);
|
||||
s->sector_write_timer = qemu_new_timer(vm_clock,
|
||||
ide_sector_write_timer_cb, s);
|
||||
if (i == 0)
|
||||
ide_init_drive(s, hd0, NULL, NULL);
|
||||
if (i == 1)
|
||||
ide_init_drive(s, hd1, NULL, NULL);
|
||||
ide_init1(bus, i);
|
||||
ide_reset(&bus->ifs[i]);
|
||||
}
|
||||
bus->irq = irq;
|
||||
}
|
||||
|
||||
/* TODO convert users to qdev and remove */
|
||||
void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
|
||||
DriveInfo *hd1, qemu_irq irq)
|
||||
{
|
||||
int i;
|
||||
DriveInfo *dinfo;
|
||||
|
||||
for(i = 0; i < 2; i++) {
|
||||
dinfo = i == 0 ? hd0 : hd1;
|
||||
ide_init1(bus, i);
|
||||
if (dinfo) {
|
||||
ide_init_drive(&bus->ifs[i], dinfo, NULL, dinfo->serial);
|
||||
} else {
|
||||
ide_reset(&bus->ifs[i]);
|
||||
}
|
||||
}
|
||||
bus->irq = irq;
|
||||
}
|
||||
|
@ -398,7 +398,6 @@ struct IDEState {
|
||||
/* set for lba48 access */
|
||||
uint8_t lba48;
|
||||
BlockDriverState *bs;
|
||||
BlockConf *conf;
|
||||
char version[9];
|
||||
/* ATAPI specific */
|
||||
uint8_t sense_key;
|
||||
@ -458,14 +457,13 @@ struct IDEDevice {
|
||||
uint32_t unit;
|
||||
BlockConf conf;
|
||||
char *version;
|
||||
char *serial;
|
||||
};
|
||||
|
||||
typedef int (*ide_qdev_initfn)(IDEDevice *dev);
|
||||
struct IDEDeviceInfo {
|
||||
DeviceInfo qdev;
|
||||
ide_qdev_initfn init;
|
||||
uint32_t unit;
|
||||
DriveInfo *drive;
|
||||
};
|
||||
|
||||
#define BM_STATUS_DMAING 0x01
|
||||
@ -557,10 +555,11 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr);
|
||||
void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
|
||||
uint32_t ide_data_readl(void *opaque, uint32_t addr);
|
||||
|
||||
void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf,
|
||||
const char *version);
|
||||
void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
|
||||
qemu_irq irq);
|
||||
void ide_init_drive(IDEState *s, DriveInfo *dinfo,
|
||||
const char *version, const char *serial);
|
||||
void ide_init2(IDEBus *bus, qemu_irq irq);
|
||||
void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
|
||||
DriveInfo *hd1, qemu_irq irq);
|
||||
void ide_init_ioport(IDEBus *bus, int iobase, int iobase2);
|
||||
|
||||
/* hw/ide/qdev.c */
|
||||
|
@ -70,7 +70,7 @@ static int isa_ide_initfn(ISADevice *dev)
|
||||
ide_bus_new(&s->bus, &s->dev.qdev);
|
||||
ide_init_ioport(&s->bus, s->iobase, s->iobase2);
|
||||
isa_init_irq(dev, &s->irq, s->isairq);
|
||||
ide_init2(&s->bus, NULL, NULL, s->irq);
|
||||
ide_init2(&s->bus, s->irq);
|
||||
vmstate_register(0, &vmstate_ide_isa, s);
|
||||
return 0;
|
||||
};
|
||||
|
@ -314,7 +314,7 @@ int pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
|
||||
int pmac_ide_memory;
|
||||
|
||||
d = qemu_mallocz(sizeof(MACIOIDEState));
|
||||
ide_init2(&d->bus, hd_table[0], hd_table[1], irq);
|
||||
ide_init2_with_non_qdev_drives(&d->bus, hd_table[0], hd_table[1], irq);
|
||||
|
||||
if (dbdma)
|
||||
DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, pmac_ide_flush, d);
|
||||
|
@ -539,7 +539,8 @@ PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv)
|
||||
md->card.cis = dscm1xxxx_cis;
|
||||
md->card.cis_len = sizeof(dscm1xxxx_cis);
|
||||
|
||||
ide_init2(&md->bus, bdrv, NULL, qemu_allocate_irqs(md_set_irq, md, 1)[0]);
|
||||
ide_init2_with_non_qdev_drives(&md->bus, bdrv, NULL,
|
||||
qemu_allocate_irqs(md_set_irq, md, 1)[0]);
|
||||
md->bus.ifs[0].is_cf = 1;
|
||||
md->bus.ifs[0].mdata_size = METADATA_SIZE;
|
||||
md->bus.ifs[0].mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE);
|
||||
|
@ -125,7 +125,7 @@ void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
|
||||
MMIOState *s = qemu_mallocz(sizeof(MMIOState));
|
||||
int mem1, mem2;
|
||||
|
||||
ide_init2(&s->bus, hd0, hd1, irq);
|
||||
ide_init2_with_non_qdev_drives(&s->bus, hd0, hd1, irq);
|
||||
|
||||
s->shift = shift;
|
||||
|
||||
|
@ -135,8 +135,8 @@ static int pci_piix_ide_initfn(PCIIDEState *d)
|
||||
ide_init_ioport(&d->bus[0], 0x1f0, 0x3f6);
|
||||
ide_init_ioport(&d->bus[1], 0x170, 0x376);
|
||||
|
||||
ide_init2(&d->bus[0], NULL, NULL, isa_reserve_irq(14));
|
||||
ide_init2(&d->bus[1], NULL, NULL, isa_reserve_irq(15));
|
||||
ide_init2(&d->bus[0], isa_reserve_irq(14));
|
||||
ide_init2(&d->bus[1], isa_reserve_irq(15));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <hw/hw.h>
|
||||
#include "sysemu.h"
|
||||
#include "dma.h"
|
||||
|
||||
#include <hw/ide/internal.h>
|
||||
@ -99,8 +98,23 @@ typedef struct IDEDrive {
|
||||
static int ide_drive_initfn(IDEDevice *dev)
|
||||
{
|
||||
IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
|
||||
ide_init_drive(bus->ifs + dev->unit, dev->conf.dinfo, &dev->conf,
|
||||
dev->version);
|
||||
IDEState *s = bus->ifs + dev->unit;
|
||||
const char *serial;
|
||||
|
||||
serial = dev->serial;
|
||||
if (!serial) {
|
||||
/* try to fall back to value set with legacy -drive serial=... */
|
||||
serial = dev->conf.dinfo->serial;
|
||||
}
|
||||
|
||||
ide_init_drive(s, dev->conf.dinfo, dev->version, serial);
|
||||
|
||||
if (!dev->version) {
|
||||
dev->version = qemu_strdup(s->version);
|
||||
}
|
||||
if (!dev->serial) {
|
||||
dev->serial = qemu_strdup(s->drive_serial_str);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -112,6 +126,7 @@ static IDEDeviceInfo ide_drive_info = {
|
||||
DEFINE_PROP_UINT32("unit", IDEDrive, dev.unit, -1),
|
||||
DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf),
|
||||
DEFINE_PROP_STRING("ver", IDEDrive, dev.version),
|
||||
DEFINE_PROP_STRING("serial", IDEDrive, dev.serial),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
}
|
||||
};
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "sysbus.h"
|
||||
#include "net.h"
|
||||
#include "devices.h"
|
||||
#include "sysemu.h"
|
||||
/* For crc32 */
|
||||
#include <zlib.h>
|
||||
|
||||
|
@ -13,9 +13,8 @@
|
||||
|
||||
# include "hw.h"
|
||||
# include "flash.h"
|
||||
# include "block.h"
|
||||
# include "blockdev.h"
|
||||
/* FIXME: Pass block device as an argument. */
|
||||
# include "sysemu.h"
|
||||
|
||||
# define NAND_CMD_READ0 0x00
|
||||
# define NAND_CMD_READ1 0x01
|
||||
|
@ -17,6 +17,8 @@
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "blockdev.h"
|
||||
#include "hw.h"
|
||||
#include "arm-misc.h"
|
||||
#include "omap.h"
|
||||
|
@ -21,8 +21,7 @@
|
||||
#include "qemu-common.h"
|
||||
#include "flash.h"
|
||||
#include "irq.h"
|
||||
#include "sysemu.h"
|
||||
#include "block.h"
|
||||
#include "blockdev.h"
|
||||
|
||||
/* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
|
||||
#define PAGE_SHIFT 11
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "qemu-char.h"
|
||||
#include "isa.h"
|
||||
#include "pc.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
//#define DEBUG_PARALLEL
|
||||
|
||||
|
1
hw/pc.c
1
hw/pc.c
@ -36,6 +36,7 @@
|
||||
#include "multiboot.h"
|
||||
#include "mc146818rtc.h"
|
||||
#include "sysbus.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
/* output Bochs bios info messages */
|
||||
//#define DEBUG_BIOS
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "boards.h"
|
||||
#include "ide.h"
|
||||
#include "kvm.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
#define MAX_IDE_BUS 2
|
||||
|
||||
|
@ -26,10 +26,8 @@
|
||||
#include "boards.h"
|
||||
#include "pci.h"
|
||||
#include "net.h"
|
||||
#include "sysemu.h"
|
||||
#include "pc.h"
|
||||
#include "monitor.h"
|
||||
#include "block_int.h"
|
||||
#include "scsi.h"
|
||||
#include "virtio-blk.h"
|
||||
#include "qemu-config.h"
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* PCMCIA/Cardbus */
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu.h"
|
||||
#include "blockdev.h"
|
||||
|
||||
typedef struct {
|
||||
qemu_irq irq;
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "sysbus.h"
|
||||
#include "sd.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
//#define DEBUG_PL181 1
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include "sysemu.h"
|
||||
#include "net.h"
|
||||
#include "qdev.h"
|
||||
#include "qerror.h"
|
||||
@ -260,6 +259,11 @@ static int parse_string(DeviceState *dev, Property *prop, const char *str)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free_string(DeviceState *dev, Property *prop)
|
||||
{
|
||||
qemu_free(*(char **)qdev_get_prop_ptr(dev, prop));
|
||||
}
|
||||
|
||||
static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
|
||||
{
|
||||
char **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
@ -274,6 +278,7 @@ PropertyInfo qdev_prop_string = {
|
||||
.size = sizeof(char*),
|
||||
.parse = parse_string,
|
||||
.print = print_string,
|
||||
.free = free_string,
|
||||
};
|
||||
|
||||
/* --- drive --- */
|
||||
@ -617,6 +622,11 @@ void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
|
||||
qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64);
|
||||
}
|
||||
|
||||
void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
|
||||
{
|
||||
qdev_prop_set(dev, name, &value, PROP_TYPE_STRING);
|
||||
}
|
||||
|
||||
void qdev_prop_set_drive(DeviceState *dev, const char *name, DriveInfo *value)
|
||||
{
|
||||
qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE);
|
||||
|
@ -334,6 +334,7 @@ void qdev_init_nofail(DeviceState *dev)
|
||||
void qdev_free(DeviceState *dev)
|
||||
{
|
||||
BusState *bus;
|
||||
Property *prop;
|
||||
|
||||
if (dev->state == DEV_STATE_INITIALIZED) {
|
||||
while (dev->num_child_bus) {
|
||||
@ -349,6 +350,11 @@ void qdev_free(DeviceState *dev)
|
||||
}
|
||||
qemu_unregister_reset(qdev_reset, dev);
|
||||
QLIST_REMOVE(dev, sibling);
|
||||
for (prop = dev->info->props; prop && prop->name; prop++) {
|
||||
if (prop->info->free) {
|
||||
prop->info->free(dev, prop);
|
||||
}
|
||||
}
|
||||
qemu_free(dev);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define QDEV_H
|
||||
|
||||
#include "hw.h"
|
||||
#include "sysemu.h"
|
||||
#include "blockdev.h"
|
||||
#include "qemu-queue.h"
|
||||
#include "qemu-char.h"
|
||||
#include "qemu-option.h"
|
||||
@ -98,6 +98,7 @@ struct PropertyInfo {
|
||||
enum PropertyType type;
|
||||
int (*parse)(DeviceState *dev, Property *prop, const char *str);
|
||||
int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
|
||||
void (*free)(DeviceState *dev, Property *prop);
|
||||
};
|
||||
|
||||
typedef struct GlobalProperty {
|
||||
@ -124,6 +125,8 @@ void qdev_machine_creation_done(void);
|
||||
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
|
||||
void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
|
||||
|
||||
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type);
|
||||
|
||||
BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
|
||||
|
||||
/*** Device API. ***/
|
||||
@ -268,6 +271,7 @@ void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value);
|
||||
void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
|
||||
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value);
|
||||
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value);
|
||||
void qdev_prop_set_string(DeviceState *dev, const char *name, char *value);
|
||||
void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value);
|
||||
void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value);
|
||||
void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value);
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include "qemu-error.h"
|
||||
#include "scsi.h"
|
||||
#include "scsi-defs.h"
|
||||
#include "block.h"
|
||||
#include "qdev.h"
|
||||
|
||||
static struct BusInfo scsi_bus_info = {
|
||||
|
@ -33,9 +33,9 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qemu-error.h"
|
||||
#include "block.h"
|
||||
#include "scsi.h"
|
||||
#include "scsi-defs.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
#define SCSI_DMA_BUF_SIZE 131072
|
||||
#define SCSI_MAX_INQUIRY_LEN 256
|
||||
@ -66,6 +66,7 @@ struct SCSIDiskState
|
||||
uint64_t max_lba;
|
||||
QEMUBH *bh;
|
||||
char *version;
|
||||
char *serial;
|
||||
};
|
||||
|
||||
static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
|
||||
@ -359,9 +360,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
|
||||
|
||||
case 0x80: /* Device serial number, optional */
|
||||
{
|
||||
const char *serial = req->dev->conf.dinfo->serial ?
|
||||
req->dev->conf.dinfo->serial : "0";
|
||||
int l = strlen(serial);
|
||||
int l = strlen(s->serial);
|
||||
|
||||
if (l > req->cmd.xfer)
|
||||
l = req->cmd.xfer;
|
||||
@ -371,7 +370,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
|
||||
DPRINTF("Inquiry EVPD[Serial number] "
|
||||
"buffer size %zd\n", req->cmd.xfer);
|
||||
outbuf[buflen++] = l;
|
||||
memcpy(outbuf+buflen, serial, l);
|
||||
memcpy(outbuf+buflen, s->serial, l);
|
||||
buflen += l;
|
||||
break;
|
||||
}
|
||||
@ -463,8 +462,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
|
||||
}
|
||||
memcpy(&outbuf[8], "QEMU ", 8);
|
||||
memset(&outbuf[32], 0, 4);
|
||||
memcpy(&outbuf[32], s->version ? s->version : QEMU_VERSION,
|
||||
MIN(4, strlen(s->version ? s->version : QEMU_VERSION)));
|
||||
memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
|
||||
/*
|
||||
* We claim conformance to SPC-3, which is required for guests
|
||||
* to ask for modern features like READ CAPACITY(16) or the
|
||||
@ -1058,6 +1056,19 @@ static int scsi_disk_initfn(SCSIDevice *dev)
|
||||
}
|
||||
s->bs = s->qdev.conf.dinfo->bdrv;
|
||||
|
||||
if (!s->serial) {
|
||||
if (*dev->conf.dinfo->serial) {
|
||||
/* try to fall back to value set with legacy -drive serial=... */
|
||||
s->serial = qemu_strdup(dev->conf.dinfo->serial);
|
||||
} else {
|
||||
s->serial = qemu_strdup("0");
|
||||
}
|
||||
}
|
||||
|
||||
if (!s->version) {
|
||||
s->version = qemu_strdup(QEMU_VERSION);
|
||||
}
|
||||
|
||||
if (bdrv_is_sg(s->bs)) {
|
||||
error_report("scsi-disk: unwanted /dev/sg*");
|
||||
return -1;
|
||||
@ -1090,6 +1101,7 @@ static SCSIDeviceInfo scsi_disk_info = {
|
||||
.qdev.props = (Property[]) {
|
||||
DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf),
|
||||
DEFINE_PROP_STRING("ver", SCSIDiskState, version),
|
||||
DEFINE_PROP_STRING("serial", SCSIDiskState, serial),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
},
|
||||
};
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qemu-error.h"
|
||||
#include "block.h"
|
||||
#include "scsi.h"
|
||||
|
||||
#ifdef __linux__
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "isa.h"
|
||||
#include "pc.h"
|
||||
#include "qemu-timer.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
//#define DEBUG_SERIAL
|
||||
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "ssi.h"
|
||||
#include "sd.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
//#define DEBUG_SSI_SD 1
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "hw.h"
|
||||
#include "console.h"
|
||||
#include "usb.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
/* HID interface requests */
|
||||
#define GET_REPORT 0xa101
|
||||
|
@ -11,10 +11,10 @@
|
||||
#include "qemu-option.h"
|
||||
#include "qemu-config.h"
|
||||
#include "usb.h"
|
||||
#include "block.h"
|
||||
#include "scsi.h"
|
||||
#include "console.h"
|
||||
#include "monitor.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
//#define DEBUG_MSD
|
||||
|
||||
@ -584,7 +584,7 @@ static USBDevice *usb_msd_init(const char *filename)
|
||||
qemu_opt_set(opts, "if", "none");
|
||||
|
||||
/* create host drive */
|
||||
dinfo = drive_init(opts, NULL, &fatal_error);
|
||||
dinfo = drive_init(opts, 0, &fatal_error);
|
||||
if (!dinfo) {
|
||||
qemu_opts_del(opts);
|
||||
return NULL;
|
||||
|
@ -12,9 +12,7 @@
|
||||
*/
|
||||
|
||||
#include <qemu-common.h>
|
||||
#include <sysemu.h>
|
||||
#include "virtio-blk.h"
|
||||
#include "block_int.h"
|
||||
#ifdef __linux__
|
||||
# include <scsi/sg.h>
|
||||
#endif
|
||||
@ -277,7 +275,7 @@ static void virtio_blk_handle_write(BlockRequest *blkreq, int *num_writes,
|
||||
}
|
||||
|
||||
blkreq[*num_writes].sector = req->out->sector;
|
||||
blkreq[*num_writes].nb_sectors = req->qiov.size / 512;
|
||||
blkreq[*num_writes].nb_sectors = req->qiov.size / BDRV_SECTOR_SIZE;
|
||||
blkreq[*num_writes].qiov = &req->qiov;
|
||||
blkreq[*num_writes].cb = virtio_blk_rw_complete;
|
||||
blkreq[*num_writes].opaque = req;
|
||||
@ -296,7 +294,8 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
|
||||
}
|
||||
|
||||
acb = bdrv_aio_readv(req->dev->bs, req->out->sector, &req->qiov,
|
||||
req->qiov.size / 512, virtio_blk_rw_complete, req);
|
||||
req->qiov.size / BDRV_SECTOR_SIZE,
|
||||
virtio_blk_rw_complete, req);
|
||||
if (!acb) {
|
||||
virtio_blk_rw_complete(req, -EIO);
|
||||
}
|
||||
@ -505,7 +504,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
|
||||
s->bs = conf->dinfo->bdrv;
|
||||
s->conf = conf;
|
||||
s->rq = NULL;
|
||||
s->sector_mask = (s->conf->logical_block_size / 512) - 1;
|
||||
s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
|
||||
bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
|
||||
|
||||
s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "qemu-error.h"
|
||||
#include "msix.h"
|
||||
#include "net.h"
|
||||
#include "block_int.h"
|
||||
#include "loader.h"
|
||||
#include "kvm.h"
|
||||
|
||||
|
104
monitor.c
104
monitor.c
@ -38,7 +38,7 @@
|
||||
#include "monitor.h"
|
||||
#include "readline.h"
|
||||
#include "console.h"
|
||||
#include "block.h"
|
||||
#include "blockdev.h"
|
||||
#include "audio/audio.h"
|
||||
#include "disas.h"
|
||||
#include "balloon.h"
|
||||
@ -530,21 +530,6 @@ static void do_help_cmd(Monitor *mon, const QDict *qdict)
|
||||
help_cmd(mon, qdict_get_try_str(qdict, "name"));
|
||||
}
|
||||
|
||||
static void do_commit(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
int all_devices;
|
||||
DriveInfo *dinfo;
|
||||
const char *device = qdict_get_str(qdict, "device");
|
||||
|
||||
all_devices = !strcmp(device, "all");
|
||||
QTAILQ_FOREACH(dinfo, &drives, next) {
|
||||
if (!all_devices)
|
||||
if (strcmp(bdrv_get_device_name(dinfo->bdrv), device))
|
||||
continue;
|
||||
bdrv_commit(dinfo->bdrv);
|
||||
}
|
||||
}
|
||||
|
||||
static void user_monitor_complete(void *opaque, QObject *ret_data)
|
||||
{
|
||||
MonitorCompletionData *data = (MonitorCompletionData *)opaque;
|
||||
@ -935,93 +920,6 @@ static int do_quit(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
|
||||
{
|
||||
if (bdrv_is_inserted(bs)) {
|
||||
if (!force) {
|
||||
if (!bdrv_is_removable(bs)) {
|
||||
qerror_report(QERR_DEVICE_NOT_REMOVABLE,
|
||||
bdrv_get_device_name(bs));
|
||||
return -1;
|
||||
}
|
||||
if (bdrv_is_locked(bs)) {
|
||||
qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
bdrv_close(bs);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
int force = qdict_get_int(qdict, "force");
|
||||
const char *filename = qdict_get_str(qdict, "device");
|
||||
|
||||
bs = bdrv_find(filename);
|
||||
if (!bs) {
|
||||
qerror_report(QERR_DEVICE_NOT_FOUND, filename);
|
||||
return -1;
|
||||
}
|
||||
return eject_device(mon, bs, force);
|
||||
}
|
||||
|
||||
static int do_block_set_passwd(Monitor *mon, const QDict *qdict,
|
||||
QObject **ret_data)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
int err;
|
||||
|
||||
bs = bdrv_find(qdict_get_str(qdict, "device"));
|
||||
if (!bs) {
|
||||
qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = bdrv_set_key(bs, qdict_get_str(qdict, "password"));
|
||||
if (err == -EINVAL) {
|
||||
qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
|
||||
return -1;
|
||||
} else if (err < 0) {
|
||||
qerror_report(QERR_INVALID_PASSWORD);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_change_block(Monitor *mon, const char *device,
|
||||
const char *filename, const char *fmt)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
BlockDriver *drv = NULL;
|
||||
int bdrv_flags;
|
||||
|
||||
bs = bdrv_find(device);
|
||||
if (!bs) {
|
||||
qerror_report(QERR_DEVICE_NOT_FOUND, device);
|
||||
return -1;
|
||||
}
|
||||
if (fmt) {
|
||||
drv = bdrv_find_whitelisted_format(fmt);
|
||||
if (!drv) {
|
||||
qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (eject_device(mon, bs, 0) < 0) {
|
||||
return -1;
|
||||
}
|
||||
bdrv_flags = bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM ? 0 : BDRV_O_RDWR;
|
||||
if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) {
|
||||
qerror_report(QERR_OPEN_FILE_FAILED, filename);
|
||||
return -1;
|
||||
}
|
||||
return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
|
||||
}
|
||||
|
||||
static int change_vnc_password(const char *password)
|
||||
{
|
||||
if (vnc_display_password(NULL, password) < 0) {
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "sysemu.h"
|
||||
#include "qemu-timer.h"
|
||||
#include "qemu-char.h"
|
||||
#include "block.h"
|
||||
#include "hw/usb.h"
|
||||
#include "hw/baum.h"
|
||||
#include "hw/msmouse.h"
|
||||
|
@ -1317,7 +1317,7 @@ truncate_f(int argc, char **argv)
|
||||
|
||||
ret = bdrv_truncate(bs, offset);
|
||||
if (ret < 0) {
|
||||
printf("truncate: %s", strerror(ret));
|
||||
printf("truncate: %s\n", strerror(-ret));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1342,7 +1342,7 @@ length_f(int argc, char **argv)
|
||||
|
||||
size = bdrv_getlength(bs);
|
||||
if (size < 0) {
|
||||
printf("getlength: %s", strerror(size));
|
||||
printf("getlength: %s\n", strerror(-size));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
2
savevm.c
2
savevm.c
@ -77,7 +77,7 @@
|
||||
#include "sysemu.h"
|
||||
#include "qemu-timer.h"
|
||||
#include "qemu-char.h"
|
||||
#include "block.h"
|
||||
#include "blockdev.h"
|
||||
#include "audio/audio.h"
|
||||
#include "migration.h"
|
||||
#include "qemu_socket.h"
|
||||
|
52
sysemu.h
52
sysemu.h
@ -142,58 +142,6 @@ extern int nb_option_roms;
|
||||
extern const char *prom_envs[MAX_PROM_ENVS];
|
||||
extern unsigned int nb_prom_envs;
|
||||
|
||||
typedef enum {
|
||||
IF_NONE,
|
||||
IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
|
||||
IF_COUNT
|
||||
} BlockInterfaceType;
|
||||
|
||||
typedef enum {
|
||||
BLOCK_ERR_REPORT, BLOCK_ERR_IGNORE, BLOCK_ERR_STOP_ENOSPC,
|
||||
BLOCK_ERR_STOP_ANY
|
||||
} BlockInterfaceErrorAction;
|
||||
|
||||
#define BLOCK_SERIAL_STRLEN 20
|
||||
|
||||
typedef struct DriveInfo {
|
||||
BlockDriverState *bdrv;
|
||||
char *id;
|
||||
const char *devaddr;
|
||||
BlockInterfaceType type;
|
||||
int bus;
|
||||
int unit;
|
||||
QemuOpts *opts;
|
||||
BlockInterfaceErrorAction on_read_error;
|
||||
BlockInterfaceErrorAction on_write_error;
|
||||
char serial[BLOCK_SERIAL_STRLEN + 1];
|
||||
QTAILQ_ENTRY(DriveInfo) next;
|
||||
} DriveInfo;
|
||||
|
||||
#define MAX_IDE_DEVS 2
|
||||
#define MAX_SCSI_DEVS 7
|
||||
#define MAX_DRIVES 32
|
||||
|
||||
extern QTAILQ_HEAD(drivelist, DriveInfo) drives;
|
||||
extern QTAILQ_HEAD(driveoptlist, DriveOpt) driveopts;
|
||||
|
||||
extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
|
||||
extern DriveInfo *drive_get_by_id(const char *id);
|
||||
extern int drive_get_max_bus(BlockInterfaceType type);
|
||||
extern void drive_uninit(DriveInfo *dinfo);
|
||||
extern const char *drive_get_serial(BlockDriverState *bdrv);
|
||||
|
||||
extern BlockInterfaceErrorAction drive_get_on_error(
|
||||
BlockDriverState *bdrv, int is_read);
|
||||
|
||||
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type);
|
||||
|
||||
extern QemuOpts *drive_add(const char *file, const char *fmt, ...);
|
||||
extern DriveInfo *drive_init(QemuOpts *arg, void *machine, int *fatal_error);
|
||||
|
||||
/* device-hotplug */
|
||||
|
||||
DriveInfo *add_init_drive(const char *opts);
|
||||
|
||||
/* pci-hotplug */
|
||||
void pci_device_hot_add(Monitor *mon, const QDict *qdict);
|
||||
void drive_hot_add(Monitor *mon, const QDict *qdict);
|
||||
|
499
vl.c
499
vl.c
@ -137,7 +137,7 @@ int main(int argc, char **argv)
|
||||
#include "qemu-char.h"
|
||||
#include "cache-utils.h"
|
||||
#include "block.h"
|
||||
#include "block_int.h"
|
||||
#include "blockdev.h"
|
||||
#include "block-migration.h"
|
||||
#include "dma.h"
|
||||
#include "audio/audio.h"
|
||||
@ -170,10 +170,6 @@ int main(int argc, char **argv)
|
||||
|
||||
static const char *data_dir;
|
||||
const char *bios_name = NULL;
|
||||
/* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
|
||||
to store the VM snapshots */
|
||||
struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives);
|
||||
struct driveoptlist driveopts = QTAILQ_HEAD_INITIALIZER(driveopts);
|
||||
enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
|
||||
DisplayType display_type = DT_DEFAULT;
|
||||
const char* keyboard_layout = NULL;
|
||||
@ -633,492 +629,12 @@ static int bt_parse(const char *opt)
|
||||
#define MTD_ALIAS "if=mtd"
|
||||
#define SD_ALIAS "index=0,if=sd"
|
||||
|
||||
QemuOpts *drive_add(const char *file, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char optstr[1024];
|
||||
QemuOpts *opts;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(optstr, sizeof(optstr), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0);
|
||||
if (!opts) {
|
||||
return NULL;
|
||||
}
|
||||
if (file)
|
||||
qemu_opt_set(opts, "file", file);
|
||||
return opts;
|
||||
}
|
||||
|
||||
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
|
||||
{
|
||||
DriveInfo *dinfo;
|
||||
|
||||
/* seek interface, bus and unit */
|
||||
|
||||
QTAILQ_FOREACH(dinfo, &drives, next) {
|
||||
if (dinfo->type == type &&
|
||||
dinfo->bus == bus &&
|
||||
dinfo->unit == unit)
|
||||
return dinfo;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DriveInfo *drive_get_by_id(const char *id)
|
||||
{
|
||||
DriveInfo *dinfo;
|
||||
|
||||
QTAILQ_FOREACH(dinfo, &drives, next) {
|
||||
if (strcmp(id, dinfo->id))
|
||||
continue;
|
||||
return dinfo;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int drive_get_max_bus(BlockInterfaceType type)
|
||||
{
|
||||
int max_bus;
|
||||
DriveInfo *dinfo;
|
||||
|
||||
max_bus = -1;
|
||||
QTAILQ_FOREACH(dinfo, &drives, next) {
|
||||
if(dinfo->type == type &&
|
||||
dinfo->bus > max_bus)
|
||||
max_bus = dinfo->bus;
|
||||
}
|
||||
return max_bus;
|
||||
}
|
||||
|
||||
const char *drive_get_serial(BlockDriverState *bdrv)
|
||||
{
|
||||
DriveInfo *dinfo;
|
||||
|
||||
QTAILQ_FOREACH(dinfo, &drives, next) {
|
||||
if (dinfo->bdrv == bdrv)
|
||||
return dinfo->serial;
|
||||
}
|
||||
|
||||
return "\0";
|
||||
}
|
||||
|
||||
BlockInterfaceErrorAction drive_get_on_error(
|
||||
BlockDriverState *bdrv, int is_read)
|
||||
{
|
||||
DriveInfo *dinfo;
|
||||
|
||||
QTAILQ_FOREACH(dinfo, &drives, next) {
|
||||
if (dinfo->bdrv == bdrv)
|
||||
return is_read ? dinfo->on_read_error : dinfo->on_write_error;
|
||||
}
|
||||
|
||||
return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC;
|
||||
}
|
||||
|
||||
static void bdrv_format_print(void *opaque, const char *name)
|
||||
{
|
||||
fprintf(stderr, " %s", name);
|
||||
}
|
||||
|
||||
void drive_uninit(DriveInfo *dinfo)
|
||||
{
|
||||
qemu_opts_del(dinfo->opts);
|
||||
bdrv_delete(dinfo->bdrv);
|
||||
QTAILQ_REMOVE(&drives, dinfo, next);
|
||||
qemu_free(dinfo);
|
||||
}
|
||||
|
||||
static int parse_block_error_action(const char *buf, int is_read)
|
||||
{
|
||||
if (!strcmp(buf, "ignore")) {
|
||||
return BLOCK_ERR_IGNORE;
|
||||
} else if (!is_read && !strcmp(buf, "enospc")) {
|
||||
return BLOCK_ERR_STOP_ENOSPC;
|
||||
} else if (!strcmp(buf, "stop")) {
|
||||
return BLOCK_ERR_STOP_ANY;
|
||||
} else if (!strcmp(buf, "report")) {
|
||||
return BLOCK_ERR_REPORT;
|
||||
} else {
|
||||
fprintf(stderr, "qemu: '%s' invalid %s error action\n",
|
||||
buf, is_read ? "read" : "write");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
DriveInfo *drive_init(QemuOpts *opts, void *opaque,
|
||||
int *fatal_error)
|
||||
{
|
||||
const char *buf;
|
||||
const char *file = NULL;
|
||||
char devname[128];
|
||||
const char *serial;
|
||||
const char *mediastr = "";
|
||||
BlockInterfaceType type;
|
||||
enum { MEDIA_DISK, MEDIA_CDROM } media;
|
||||
int bus_id, unit_id;
|
||||
int cyls, heads, secs, translation;
|
||||
BlockDriver *drv = NULL;
|
||||
QEMUMachine *machine = opaque;
|
||||
int max_devs;
|
||||
int index;
|
||||
int ro = 0;
|
||||
int bdrv_flags = 0;
|
||||
int on_read_error, on_write_error;
|
||||
const char *devaddr;
|
||||
DriveInfo *dinfo;
|
||||
int snapshot = 0;
|
||||
|
||||
*fatal_error = 1;
|
||||
|
||||
translation = BIOS_ATA_TRANSLATION_AUTO;
|
||||
|
||||
if (machine && machine->use_scsi) {
|
||||
type = IF_SCSI;
|
||||
max_devs = MAX_SCSI_DEVS;
|
||||
pstrcpy(devname, sizeof(devname), "scsi");
|
||||
} else {
|
||||
type = IF_IDE;
|
||||
max_devs = MAX_IDE_DEVS;
|
||||
pstrcpy(devname, sizeof(devname), "ide");
|
||||
}
|
||||
media = MEDIA_DISK;
|
||||
|
||||
/* extract parameters */
|
||||
bus_id = qemu_opt_get_number(opts, "bus", 0);
|
||||
unit_id = qemu_opt_get_number(opts, "unit", -1);
|
||||
index = qemu_opt_get_number(opts, "index", -1);
|
||||
|
||||
cyls = qemu_opt_get_number(opts, "cyls", 0);
|
||||
heads = qemu_opt_get_number(opts, "heads", 0);
|
||||
secs = qemu_opt_get_number(opts, "secs", 0);
|
||||
|
||||
snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
|
||||
ro = qemu_opt_get_bool(opts, "readonly", 0);
|
||||
|
||||
file = qemu_opt_get(opts, "file");
|
||||
serial = qemu_opt_get(opts, "serial");
|
||||
|
||||
if ((buf = qemu_opt_get(opts, "if")) != NULL) {
|
||||
pstrcpy(devname, sizeof(devname), buf);
|
||||
if (!strcmp(buf, "ide")) {
|
||||
type = IF_IDE;
|
||||
max_devs = MAX_IDE_DEVS;
|
||||
} else if (!strcmp(buf, "scsi")) {
|
||||
type = IF_SCSI;
|
||||
max_devs = MAX_SCSI_DEVS;
|
||||
} else if (!strcmp(buf, "floppy")) {
|
||||
type = IF_FLOPPY;
|
||||
max_devs = 0;
|
||||
} else if (!strcmp(buf, "pflash")) {
|
||||
type = IF_PFLASH;
|
||||
max_devs = 0;
|
||||
} else if (!strcmp(buf, "mtd")) {
|
||||
type = IF_MTD;
|
||||
max_devs = 0;
|
||||
} else if (!strcmp(buf, "sd")) {
|
||||
type = IF_SD;
|
||||
max_devs = 0;
|
||||
} else if (!strcmp(buf, "virtio")) {
|
||||
type = IF_VIRTIO;
|
||||
max_devs = 0;
|
||||
} else if (!strcmp(buf, "xen")) {
|
||||
type = IF_XEN;
|
||||
max_devs = 0;
|
||||
} else if (!strcmp(buf, "none")) {
|
||||
type = IF_NONE;
|
||||
max_devs = 0;
|
||||
} else {
|
||||
fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (cyls || heads || secs) {
|
||||
if (cyls < 1 || (type == IF_IDE && cyls > 16383)) {
|
||||
fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
if (heads < 1 || (type == IF_IDE && heads > 16)) {
|
||||
fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
if (secs < 1 || (type == IF_IDE && secs > 63)) {
|
||||
fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((buf = qemu_opt_get(opts, "trans")) != NULL) {
|
||||
if (!cyls) {
|
||||
fprintf(stderr,
|
||||
"qemu: '%s' trans must be used with cyls,heads and secs\n",
|
||||
buf);
|
||||
return NULL;
|
||||
}
|
||||
if (!strcmp(buf, "none"))
|
||||
translation = BIOS_ATA_TRANSLATION_NONE;
|
||||
else if (!strcmp(buf, "lba"))
|
||||
translation = BIOS_ATA_TRANSLATION_LBA;
|
||||
else if (!strcmp(buf, "auto"))
|
||||
translation = BIOS_ATA_TRANSLATION_AUTO;
|
||||
else {
|
||||
fprintf(stderr, "qemu: '%s' invalid translation type\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((buf = qemu_opt_get(opts, "media")) != NULL) {
|
||||
if (!strcmp(buf, "disk")) {
|
||||
media = MEDIA_DISK;
|
||||
} else if (!strcmp(buf, "cdrom")) {
|
||||
if (cyls || secs || heads) {
|
||||
fprintf(stderr,
|
||||
"qemu: '%s' invalid physical CHS format\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
media = MEDIA_CDROM;
|
||||
} else {
|
||||
fprintf(stderr, "qemu: '%s' invalid media\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((buf = qemu_opt_get(opts, "cache")) != NULL) {
|
||||
if (!strcmp(buf, "off") || !strcmp(buf, "none")) {
|
||||
bdrv_flags |= BDRV_O_NOCACHE;
|
||||
} else if (!strcmp(buf, "writeback")) {
|
||||
bdrv_flags |= BDRV_O_CACHE_WB;
|
||||
} else if (!strcmp(buf, "unsafe")) {
|
||||
bdrv_flags |= BDRV_O_CACHE_WB;
|
||||
bdrv_flags |= BDRV_O_NO_FLUSH;
|
||||
} else if (!strcmp(buf, "writethrough")) {
|
||||
/* this is the default */
|
||||
} else {
|
||||
fprintf(stderr, "qemu: invalid cache option\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
if ((buf = qemu_opt_get(opts, "aio")) != NULL) {
|
||||
if (!strcmp(buf, "native")) {
|
||||
bdrv_flags |= BDRV_O_NATIVE_AIO;
|
||||
} else if (!strcmp(buf, "threads")) {
|
||||
/* this is the default */
|
||||
} else {
|
||||
fprintf(stderr, "qemu: invalid aio option\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((buf = qemu_opt_get(opts, "format")) != NULL) {
|
||||
if (strcmp(buf, "?") == 0) {
|
||||
fprintf(stderr, "qemu: Supported formats:");
|
||||
bdrv_iterate_format(bdrv_format_print, NULL);
|
||||
fprintf(stderr, "\n");
|
||||
return NULL;
|
||||
}
|
||||
drv = bdrv_find_whitelisted_format(buf);
|
||||
if (!drv) {
|
||||
fprintf(stderr, "qemu: '%s' invalid format\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
on_write_error = BLOCK_ERR_STOP_ENOSPC;
|
||||
if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
|
||||
if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
|
||||
fprintf(stderr, "werror is no supported by this format\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
on_write_error = parse_block_error_action(buf, 0);
|
||||
if (on_write_error < 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
on_read_error = BLOCK_ERR_REPORT;
|
||||
if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
|
||||
if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) {
|
||||
fprintf(stderr, "rerror is no supported by this format\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
on_read_error = parse_block_error_action(buf, 1);
|
||||
if (on_read_error < 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) {
|
||||
if (type != IF_VIRTIO) {
|
||||
fprintf(stderr, "addr is not supported\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* compute bus and unit according index */
|
||||
|
||||
if (index != -1) {
|
||||
if (bus_id != 0 || unit_id != -1) {
|
||||
fprintf(stderr,
|
||||
"qemu: index cannot be used with bus and unit\n");
|
||||
return NULL;
|
||||
}
|
||||
if (max_devs == 0)
|
||||
{
|
||||
unit_id = index;
|
||||
bus_id = 0;
|
||||
} else {
|
||||
unit_id = index % max_devs;
|
||||
bus_id = index / max_devs;
|
||||
}
|
||||
}
|
||||
|
||||
/* if user doesn't specify a unit_id,
|
||||
* try to find the first free
|
||||
*/
|
||||
|
||||
if (unit_id == -1) {
|
||||
unit_id = 0;
|
||||
while (drive_get(type, bus_id, unit_id) != NULL) {
|
||||
unit_id++;
|
||||
if (max_devs && unit_id >= max_devs) {
|
||||
unit_id -= max_devs;
|
||||
bus_id++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check unit id */
|
||||
|
||||
if (max_devs && unit_id >= max_devs) {
|
||||
fprintf(stderr, "qemu: unit %d too big (max is %d)\n",
|
||||
unit_id, max_devs - 1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* ignore multiple definitions
|
||||
*/
|
||||
|
||||
if (drive_get(type, bus_id, unit_id) != NULL) {
|
||||
*fatal_error = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* init */
|
||||
|
||||
dinfo = qemu_mallocz(sizeof(*dinfo));
|
||||
if ((buf = qemu_opts_id(opts)) != NULL) {
|
||||
dinfo->id = qemu_strdup(buf);
|
||||
} else {
|
||||
/* no id supplied -> create one */
|
||||
dinfo->id = qemu_mallocz(32);
|
||||
if (type == IF_IDE || type == IF_SCSI)
|
||||
mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
|
||||
if (max_devs)
|
||||
snprintf(dinfo->id, 32, "%s%i%s%i",
|
||||
devname, bus_id, mediastr, unit_id);
|
||||
else
|
||||
snprintf(dinfo->id, 32, "%s%s%i",
|
||||
devname, mediastr, unit_id);
|
||||
}
|
||||
dinfo->bdrv = bdrv_new(dinfo->id);
|
||||
dinfo->devaddr = devaddr;
|
||||
dinfo->type = type;
|
||||
dinfo->bus = bus_id;
|
||||
dinfo->unit = unit_id;
|
||||
dinfo->on_read_error = on_read_error;
|
||||
dinfo->on_write_error = on_write_error;
|
||||
dinfo->opts = opts;
|
||||
if (serial)
|
||||
strncpy(dinfo->serial, serial, sizeof(serial));
|
||||
QTAILQ_INSERT_TAIL(&drives, dinfo, next);
|
||||
|
||||
switch(type) {
|
||||
case IF_IDE:
|
||||
case IF_SCSI:
|
||||
case IF_XEN:
|
||||
case IF_NONE:
|
||||
switch(media) {
|
||||
case MEDIA_DISK:
|
||||
if (cyls != 0) {
|
||||
bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs);
|
||||
bdrv_set_translation_hint(dinfo->bdrv, translation);
|
||||
}
|
||||
break;
|
||||
case MEDIA_CDROM:
|
||||
bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IF_SD:
|
||||
/* FIXME: This isn't really a floppy, but it's a reasonable
|
||||
approximation. */
|
||||
case IF_FLOPPY:
|
||||
bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY);
|
||||
break;
|
||||
case IF_PFLASH:
|
||||
case IF_MTD:
|
||||
break;
|
||||
case IF_VIRTIO:
|
||||
/* add virtio block device */
|
||||
opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
|
||||
qemu_opt_set(opts, "driver", "virtio-blk-pci");
|
||||
qemu_opt_set(opts, "drive", dinfo->id);
|
||||
if (devaddr)
|
||||
qemu_opt_set(opts, "addr", devaddr);
|
||||
break;
|
||||
case IF_COUNT:
|
||||
abort();
|
||||
}
|
||||
if (!file) {
|
||||
*fatal_error = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (snapshot) {
|
||||
/* always use cache=unsafe with snapshot */
|
||||
bdrv_flags &= ~BDRV_O_CACHE_MASK;
|
||||
bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
|
||||
}
|
||||
|
||||
if (media == MEDIA_CDROM) {
|
||||
/* CDROM is fine for any interface, don't check. */
|
||||
ro = 1;
|
||||
} else if (ro == 1) {
|
||||
if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
|
||||
fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
|
||||
|
||||
if (bdrv_open(dinfo->bdrv, file, bdrv_flags, drv) < 0) {
|
||||
fprintf(stderr, "qemu: could not open disk image %s: %s\n",
|
||||
file, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (bdrv_key_required(dinfo->bdrv))
|
||||
autostart = 0;
|
||||
*fatal_error = 0;
|
||||
return dinfo;
|
||||
}
|
||||
|
||||
static int drive_init_func(QemuOpts *opts, void *opaque)
|
||||
{
|
||||
QEMUMachine *machine = opaque;
|
||||
int *use_scsi = opaque;
|
||||
int fatal_error = 0;
|
||||
|
||||
if (drive_init(opts, machine, &fatal_error) == NULL) {
|
||||
if (drive_init(opts, *use_scsi, &fatal_error) == NULL) {
|
||||
if (fatal_error)
|
||||
return 1;
|
||||
}
|
||||
@ -1297,7 +813,7 @@ static void smp_parse(const char *optarg)
|
||||
/***********************************************************/
|
||||
/* USB devices */
|
||||
|
||||
static int usb_device_add(const char *devname, int is_hotplug)
|
||||
static int usb_device_add(const char *devname)
|
||||
{
|
||||
const char *p;
|
||||
USBDevice *dev = NULL;
|
||||
@ -1349,7 +865,7 @@ static int usb_device_del(const char *devname)
|
||||
static int usb_parse(const char *cmdline)
|
||||
{
|
||||
int r;
|
||||
r = usb_device_add(cmdline, 0);
|
||||
r = usb_device_add(cmdline);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "qemu: could not add USB device '%s'\n", cmdline);
|
||||
}
|
||||
@ -1359,7 +875,7 @@ static int usb_parse(const char *cmdline)
|
||||
void do_usb_add(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *devname = qdict_get_str(qdict, "devname");
|
||||
if (usb_device_add(devname, 1) < 0) {
|
||||
if (usb_device_add(devname) < 0) {
|
||||
error_report("could not add USB device '%s'", devname);
|
||||
}
|
||||
}
|
||||
@ -1841,6 +1357,7 @@ static void main_loop(void)
|
||||
vm_stop(r);
|
||||
}
|
||||
}
|
||||
bdrv_close_all();
|
||||
pause_all_vcpus();
|
||||
}
|
||||
|
||||
@ -3243,7 +2760,7 @@ int main(int argc, char **argv, char **envp)
|
||||
/* open the virtual block devices */
|
||||
if (snapshot)
|
||||
qemu_opts_foreach(&qemu_drive_opts, drive_enable_snapshot, NULL, 0);
|
||||
if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, machine, 1) != 0)
|
||||
if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, &machine->use_scsi, 1) != 0)
|
||||
exit(1);
|
||||
|
||||
register_savevm_live("ram", 0, 3, NULL, ram_save_live, NULL,
|
||||
|
Loading…
Reference in New Issue
Block a user