$(call set-vpath, $(SRC_PATH):$(SRC_PATH)/hw)
QEMU_CFLAGS+=-I..
+QEMU_CFLAGS += $(GLIB_CFLAGS)
include $(SRC_PATH)/Makefile.objs
obj-y += vhost_net.o
obj-$(CONFIG_VHOST_NET) += vhost.o
obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
-obj-y += rwhandler.o
obj-$(CONFIG_KVM) += kvm.o kvm-all.o
obj-$(CONFIG_NO_KVM) += kvm-stub.o
obj-y += memory.o
{
QEMUBH *bh, **bhp, *next;
int ret;
+ static int nesting = 0;
+
+ nesting++;
ret = 0;
for (bh = first_bh; bh; bh = next) {
}
}
+ nesting--;
+
/* remove deleted bhs */
- bhp = &first_bh;
- while (*bhp) {
- bh = *bhp;
- if (bh->deleted) {
- *bhp = bh->next;
- g_free(bh);
- } else
- bhp = &bh->next;
+ if (!nesting) {
+ bhp = &first_bh;
+ while (*bhp) {
+ bh = *bhp;
+ if (bh->deleted) {
+ *bhp = bh->next;
+ g_free(bh);
+ } else {
+ bhp = &bh->next;
+ }
+ }
}
return ret;
#include <windows.h>
#endif
+static void bdrv_dev_change_media_cb(BlockDriverState *bs);
static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
}
if (!bdrv_key_required(bs)) {
- /* call the change callback */
- bs->media_changed = 1;
- if (bs->change_cb)
- bs->change_cb(bs->change_opaque, CHANGE_MEDIA);
+ bdrv_dev_change_media_cb(bs);
}
return 0;
bdrv_close(bs->file);
}
- /* call the change callback */
- bs->media_changed = 1;
- if (bs->change_cb)
- bs->change_cb(bs->change_opaque, CHANGE_MEDIA);
+ bdrv_dev_change_media_cb(bs);
}
}
void bdrv_delete(BlockDriverState *bs)
{
- assert(!bs->peer);
+ assert(!bs->dev);
/* remove from list, if necessary */
bdrv_make_anon(bs);
g_free(bs);
}
-int bdrv_attach(BlockDriverState *bs, DeviceState *qdev)
+int bdrv_attach_dev(BlockDriverState *bs, void *dev)
+/* TODO change to DeviceState *dev when all users are qdevified */
{
- if (bs->peer) {
+ if (bs->dev) {
return -EBUSY;
}
- bs->peer = qdev;
+ bs->dev = dev;
return 0;
}
-void bdrv_detach(BlockDriverState *bs, DeviceState *qdev)
+/* TODO qdevified devices don't use this, remove when devices are qdevified */
+void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev)
{
- assert(bs->peer == qdev);
- bs->peer = NULL;
- bs->change_cb = NULL;
- bs->change_opaque = NULL;
+ if (bdrv_attach_dev(bs, dev) < 0) {
+ abort();
+ }
}
-DeviceState *bdrv_get_attached(BlockDriverState *bs)
+void bdrv_detach_dev(BlockDriverState *bs, void *dev)
+/* TODO change to DeviceState *dev when all users are qdevified */
{
- return bs->peer;
+ assert(bs->dev == dev);
+ bs->dev = NULL;
+ bs->dev_ops = NULL;
+ bs->dev_opaque = NULL;
+}
+
+/* TODO change to return DeviceState * when all users are qdevified */
+void *bdrv_get_attached_dev(BlockDriverState *bs)
+{
+ return bs->dev;
+}
+
+void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops,
+ void *opaque)
+{
+ bs->dev_ops = ops;
+ bs->dev_opaque = opaque;
+}
+
+static void bdrv_dev_change_media_cb(BlockDriverState *bs)
+{
+ if (bs->dev_ops && bs->dev_ops->change_media_cb) {
+ bs->dev_ops->change_media_cb(bs->dev_opaque);
+ }
+}
+
+static void bdrv_dev_resize_cb(BlockDriverState *bs)
+{
+ if (bs->dev_ops && bs->dev_ops->resize_cb) {
+ bs->dev_ops->resize_cb(bs->dev_opaque);
+ }
}
/*
ret = drv->bdrv_truncate(bs, offset);
if (ret == 0) {
ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
- if (bs->change_cb) {
- bs->change_cb(bs->change_opaque, CHANGE_SIZE);
- }
+ bdrv_dev_resize_cb(bs);
}
return ret;
}
return bs->enable_write_cache;
}
-/* XXX: no longer used */
-void bdrv_set_change_cb(BlockDriverState *bs,
- void (*change_cb)(void *opaque, int reason),
- void *opaque)
-{
- bs->change_cb = change_cb;
- bs->change_opaque = opaque;
-}
-
int bdrv_is_encrypted(BlockDriverState *bs)
{
if (bs->backing_hd && bs->backing_hd->encrypted)
} else if (!bs->valid_key) {
bs->valid_key = 1;
/* call the change callback now, we skipped it on open */
- bs->media_changed = 1;
- if (bs->change_cb)
- bs->change_cb(bs->change_opaque, CHANGE_MEDIA);
+ bdrv_dev_change_media_cb(bs);
}
return ret;
}
BlockDriverState *bs;
QTAILQ_FOREACH(bs, &bdrv_states, list) {
- if (bs->drv && !bdrv_is_read_only(bs) &&
- (!bdrv_is_removable(bs) || bdrv_is_inserted(bs))) {
+ if (!bdrv_is_read_only(bs) && bdrv_is_inserted(bs)) {
bdrv_flush(bs);
}
}
int bdrv_can_snapshot(BlockDriverState *bs)
{
BlockDriver *drv = bs->drv;
- if (!drv || bdrv_is_removable(bs) || bdrv_is_read_only(bs)) {
+ if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
return 0;
}
}
/**
- * Return TRUE if the media changed since the last call to this
- * function. It is currently only used for floppy disks
+ * Return whether the media changed since the last call to this
+ * function, or -ENOTSUP if we don't know. Most drivers don't know.
*/
int bdrv_media_changed(BlockDriverState *bs)
{
BlockDriver *drv = bs->drv;
- int ret;
- if (!drv || !drv->bdrv_media_changed)
- ret = -ENOTSUP;
- else
- ret = drv->bdrv_media_changed(bs);
- if (ret == -ENOTSUP)
- ret = bs->media_changed;
- bs->media_changed = 0;
- return ret;
+ if (drv && drv->bdrv_media_changed) {
+ return drv->bdrv_media_changed(bs);
+ }
+ return -ENOTSUP;
}
/**
uint64_t vm_clock_nsec; /* VM clock relative to boot */
} QEMUSnapshotInfo;
+/* Callbacks for block device models */
+typedef struct BlockDevOps {
+ /*
+ * Runs when virtual media changed (monitor commands eject, change)
+ * Beware: doesn't run when a host device's physical media
+ * changes. Sure would be useful if it did.
+ */
+ void (*change_media_cb)(void *opaque);
+ /*
+ * Runs when the size changed (e.g. monitor command block_resize)
+ */
+ void (*resize_cb)(void *opaque);
+} BlockDevOps;
+
#define BDRV_O_RDWR 0x0002
#define BDRV_O_SNAPSHOT 0x0008 /* open the file read only and save writes in a snapshot */
#define BDRV_O_NOCACHE 0x0020 /* do not use the host page cache */
int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
BlockDriver *drv);
void bdrv_close(BlockDriverState *bs);
-int bdrv_attach(BlockDriverState *bs, DeviceState *qdev);
-void bdrv_detach(BlockDriverState *bs, DeviceState *qdev);
-DeviceState *bdrv_get_attached(BlockDriverState *bs);
+int bdrv_attach_dev(BlockDriverState *bs, void *dev);
+void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev);
+void bdrv_detach_dev(BlockDriverState *bs, void *dev);
+void *bdrv_get_attached_dev(BlockDriverState *bs);
+void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops,
+ void *opaque);
int bdrv_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
int bdrv_write(BlockDriverState *bs, int64_t sector_num,
int bdrv_is_locked(BlockDriverState *bs);
void bdrv_set_locked(BlockDriverState *bs, int locked);
int bdrv_eject(BlockDriverState *bs, int eject_flag);
-void bdrv_set_change_cb(BlockDriverState *bs,
- void (*change_cb)(void *opaque, int reason),
- void *opaque);
void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size);
BlockDriverState *bdrv_find(const char *name);
BlockDriverState *bdrv_next(BlockDriverState *bs);
const char *base_filename, const char *base_fmt,
char *options, uint64_t img_size, int flags);
+void *qemu_blockalign(BlockDriverState *bs, size_t size);
+
#define BDRV_SECTORS_PER_DIRTY_CHUNK 2048
void bdrv_set_dirty_tracking(BlockDriverState *bs, int enable);
int n_end;
int ret;
int cur_nr_sectors; /* number of sectors in current iteration */
- QCowL2Meta l2meta;
uint64_t cluster_offset;
QEMUIOVector hd_qiov;
uint64_t bytes_done = 0;
uint8_t *cluster_data = NULL;
+ QCowL2Meta l2meta = {
+ .nb_clusters = 0,
+ };
- l2meta.nb_clusters = 0;
qemu_co_queue_init(&l2meta.dependent_requests);
qemu_iovec_init(&hd_qiov, qiov->niov);
}
ret = qcow2_alloc_cluster_link_l2(bs, &l2meta);
-
- run_dependent_requests(s, &l2meta);
-
if (ret < 0) {
goto fail;
}
+ run_dependent_requests(s, &l2meta);
+
remaining_sectors -= cur_nr_sectors;
sector_num += cur_nr_sectors;
bytes_done += cur_nr_sectors * 512;
ret = 0;
fail:
+ run_dependent_requests(s, &l2meta);
+
qemu_co_mutex_unlock(&s->lock);
qemu_iovec_destroy(&hd_qiov);
}
#ifdef CONFIG_LINUX_AIO
+ /*
+ * Currently Linux do AIO only for files opened with O_DIRECT
+ * specified so check NOCACHE flag too
+ */
if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
(BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) {
return bdrv_is_inserted(bs->file);
}
+static int raw_media_changed(BlockDriverState *bs)
+{
+ return bdrv_media_changed(bs->file);
+}
+
static void raw_eject(BlockDriverState *bs, int eject_flag)
{
bdrv_eject(bs->file, eject_flag);
.bdrv_discard = raw_discard,
.bdrv_is_inserted = raw_is_inserted,
+ .bdrv_media_changed = raw_media_changed,
.bdrv_eject = raw_eject,
.bdrv_set_locked = raw_set_locked,
+
.bdrv_ioctl = raw_ioctl,
.bdrv_aio_ioctl = raw_aio_ioctl,
#include "qemu-common.h"
#include "block_int.h"
#include "module.h"
+#include "zlib.h"
#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
#define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
+#define VMDK4_COMPRESSION_DEFLATE 1
+#define VMDK4_FLAG_RGD (1 << 1)
+#define VMDK4_FLAG_COMPRESS (1 << 16)
+#define VMDK4_FLAG_MARKER (1 << 17)
typedef struct {
uint32_t version;
int64_t desc_offset;
int64_t desc_size;
int32_t num_gtes_per_gte;
- int64_t rgd_offset;
int64_t gd_offset;
+ int64_t rgd_offset;
int64_t grain_offset;
char filler[1];
char check_bytes[4];
+ uint16_t compressAlgorithm;
} QEMU_PACKED VMDK4Header;
#define L2_CACHE_SIZE 16
typedef struct VmdkExtent {
BlockDriverState *file;
bool flat;
+ bool compressed;
+ bool has_marker;
int64_t sectors;
int64_t end_sector;
int64_t flat_start_offset;
int valid;
} VmdkMetaData;
+typedef struct VmdkGrainMarker {
+ uint64_t lba;
+ uint32_t size;
+ uint8_t data[0];
+} VmdkGrainMarker;
+
static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
{
uint32_t magic;
g_free(s->extents);
}
+static void vmdk_free_last_extent(BlockDriverState *bs)
+{
+ BDRVVmdkState *s = bs->opaque;
+
+ if (s->num_extents == 0) {
+ return;
+ }
+ s->num_extents--;
+ s->extents = g_realloc(s->extents, s->num_extents * sizeof(VmdkExtent));
+}
+
static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
{
char desc[DESC_SIZE];
return ret;
}
-static int vmdk_open_vmdk3(BlockDriverState *bs, int flags)
+static int vmdk_open_vmdk3(BlockDriverState *bs,
+ BlockDriverState *file,
+ int flags)
{
int ret;
uint32_t magic;
VMDK3Header header;
- BDRVVmdkState *s = bs->opaque;
VmdkExtent *extent;
- s->desc_offset = 0x200;
- ret = bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header));
+ ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
if (ret < 0) {
- goto fail;
+ return ret;
}
extent = vmdk_add_extent(bs,
bs->file, false,
le32_to_cpu(header.granularity));
ret = vmdk_init_tables(bs, extent);
if (ret) {
- /* vmdk_init_tables cleans up on fail, so only free allocation of
- * vmdk_add_extent here. */
- goto fail;
+ /* free extent allocated by vmdk_add_extent */
+ vmdk_free_last_extent(bs);
}
- return 0;
- fail:
- vmdk_free_extents(bs);
return ret;
}
-static int vmdk_open_vmdk4(BlockDriverState *bs, int flags)
+static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
+ int64_t desc_offset);
+
+static int vmdk_open_vmdk4(BlockDriverState *bs,
+ BlockDriverState *file,
+ int flags)
{
int ret;
uint32_t magic;
uint32_t l1_size, l1_entry_sectors;
VMDK4Header header;
- BDRVVmdkState *s = bs->opaque;
VmdkExtent *extent;
+ int64_t l1_backup_offset = 0;
- s->desc_offset = 0x200;
- ret = bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header));
+ ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
if (ret < 0) {
- goto fail;
+ return ret;
+ }
+ if (header.capacity == 0 && header.desc_offset) {
+ return vmdk_open_desc_file(bs, flags, header.desc_offset << 9);
}
l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
* le64_to_cpu(header.granularity);
+ if (l1_entry_sectors <= 0) {
+ return -EINVAL;
+ }
l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1)
/ l1_entry_sectors;
- extent = vmdk_add_extent(bs, bs->file, false,
+ if (le32_to_cpu(header.flags) & VMDK4_FLAG_RGD) {
+ l1_backup_offset = le64_to_cpu(header.rgd_offset) << 9;
+ }
+ extent = vmdk_add_extent(bs, file, false,
le64_to_cpu(header.capacity),
le64_to_cpu(header.gd_offset) << 9,
- le64_to_cpu(header.rgd_offset) << 9,
+ l1_backup_offset,
l1_size,
le32_to_cpu(header.num_gtes_per_gte),
le64_to_cpu(header.granularity));
- if (extent->l1_entry_sectors <= 0) {
- ret = -EINVAL;
- goto fail;
- }
- /* try to open parent images, if exist */
- ret = vmdk_parent_open(bs);
- if (ret) {
- goto fail;
- }
- s->parent_cid = vmdk_read_cid(bs, 1);
+ extent->compressed =
+ le16_to_cpu(header.compressAlgorithm) == VMDK4_COMPRESSION_DEFLATE;
+ extent->has_marker = le32_to_cpu(header.flags) & VMDK4_FLAG_MARKER;
ret = vmdk_init_tables(bs, extent);
if (ret) {
- goto fail;
+ /* free extent allocated by vmdk_add_extent */
+ vmdk_free_last_extent(bs);
}
- return 0;
- fail:
- vmdk_free_extents(bs);
return ret;
}
return 0;
}
+/* Open an extent file and append to bs array */
+static int vmdk_open_sparse(BlockDriverState *bs,
+ BlockDriverState *file,
+ int flags)
+{
+ uint32_t magic;
+
+ if (bdrv_pread(file, 0, &magic, sizeof(magic)) != sizeof(magic)) {
+ return -EIO;
+ }
+
+ magic = be32_to_cpu(magic);
+ switch (magic) {
+ case VMDK3_MAGIC:
+ return vmdk_open_vmdk3(bs, file, flags);
+ break;
+ case VMDK4_MAGIC:
+ return vmdk_open_vmdk4(bs, file, flags);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+}
+
static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
const char *desc_file_path)
{
const char *p = desc;
int64_t sectors = 0;
int64_t flat_offset;
+ char extent_path[PATH_MAX];
+ BlockDriverState *extent_file;
while (*p) {
/* parse extent line:
goto next_line;
}
+ path_combine(extent_path, sizeof(extent_path),
+ desc_file_path, fname);
+ ret = bdrv_file_open(&extent_file, extent_path, bs->open_flags);
+ if (ret) {
+ return ret;
+ }
+
/* save to extents array */
if (!strcmp(type, "FLAT")) {
/* FLAT extent */
- char extent_path[PATH_MAX];
- BlockDriverState *extent_file;
VmdkExtent *extent;
- path_combine(extent_path, sizeof(extent_path),
- desc_file_path, fname);
- ret = bdrv_file_open(&extent_file, extent_path, bs->open_flags);
+ extent = vmdk_add_extent(bs, extent_file, true, sectors,
+ 0, 0, 0, 0, sectors);
+ extent->flat_start_offset = flat_offset << 9;
+ } else if (!strcmp(type, "SPARSE")) {
+ /* SPARSE extent */
+ ret = vmdk_open_sparse(bs, extent_file, bs->open_flags);
if (ret) {
+ bdrv_delete(extent_file);
return ret;
}
- extent = vmdk_add_extent(bs, extent_file, true, sectors,
- 0, 0, 0, 0, sectors);
- extent->flat_start_offset = flat_offset;
} else {
- /* SPARSE extent, not supported for now */
fprintf(stderr,
"VMDK: Not supported extent type \"%s\""".\n", type);
return -ENOTSUP;
return 0;
}
-static int vmdk_open_desc_file(BlockDriverState *bs, int flags)
+static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
+ int64_t desc_offset)
{
int ret;
char buf[2048];
char ct[128];
BDRVVmdkState *s = bs->opaque;
- ret = bdrv_pread(bs->file, 0, buf, sizeof(buf));
+ ret = bdrv_pread(bs->file, desc_offset, buf, sizeof(buf));
if (ret < 0) {
return ret;
}
if (vmdk_parse_description(buf, "createType", ct, sizeof(ct))) {
return -EINVAL;
}
- if (strcmp(ct, "monolithicFlat")) {
+ if (strcmp(ct, "monolithicFlat") &&
+ strcmp(ct, "twoGbMaxExtentSparse") &&
+ strcmp(ct, "twoGbMaxExtentFlat")) {
fprintf(stderr,
"VMDK: Not supported image type \"%s\""".\n", ct);
return -ENOTSUP;
static int vmdk_open(BlockDriverState *bs, int flags)
{
- uint32_t magic;
-
- if (bdrv_pread(bs->file, 0, &magic, sizeof(magic)) != sizeof(magic)) {
- return -EIO;
- }
+ int ret;
+ BDRVVmdkState *s = bs->opaque;
- magic = be32_to_cpu(magic);
- if (magic == VMDK3_MAGIC) {
- return vmdk_open_vmdk3(bs, flags);
- } else if (magic == VMDK4_MAGIC) {
- return vmdk_open_vmdk4(bs, flags);
+ if (vmdk_open_sparse(bs, bs->file, flags) == 0) {
+ s->desc_offset = 0x200;
+ /* try to open parent images, if exist */
+ ret = vmdk_parent_open(bs);
+ if (ret) {
+ vmdk_free_extents(bs);
+ return ret;
+ }
+ s->parent_cid = vmdk_read_cid(bs, 1);
+ return 0;
} else {
- return vmdk_open_desc_file(bs, flags);
+ return vmdk_open_desc_file(bs, flags, 0);
}
}
return 0;
}
+ offset -= (extent->end_sector - extent->sectors) * SECTOR_SIZE;
l1_index = (offset >> 9) / extent->l1_entry_sectors;
if (l1_index >= extent->l1_size) {
return -1;
/* Avoid the L2 tables update for the images that have snapshots. */
*cluster_offset = bdrv_getlength(extent->file);
- bdrv_truncate(
- extent->file,
- *cluster_offset + (extent->cluster_sectors << 9)
- );
+ if (!extent->compressed) {
+ bdrv_truncate(
+ extent->file,
+ *cluster_offset + (extent->cluster_sectors << 9)
+ );
+ }
*cluster_offset >>= 9;
tmp = cpu_to_le32(*cluster_offset);
return ret;
}
+static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
+ int64_t offset_in_cluster, const uint8_t *buf,
+ int nb_sectors, int64_t sector_num)
+{
+ int ret;
+ VmdkGrainMarker *data = NULL;
+ uLongf buf_len;
+ const uint8_t *write_buf = buf;
+ int write_len = nb_sectors * 512;
+
+ if (extent->compressed) {
+ if (!extent->has_marker) {
+ ret = -EINVAL;
+ goto out;
+ }
+ buf_len = (extent->cluster_sectors << 9) * 2;
+ data = g_malloc(buf_len + sizeof(VmdkGrainMarker));
+ if (compress(data->data, &buf_len, buf, nb_sectors << 9) != Z_OK ||
+ buf_len == 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+ data->lba = sector_num;
+ data->size = buf_len;
+ write_buf = (uint8_t *)data;
+ write_len = buf_len + sizeof(VmdkGrainMarker);
+ }
+ ret = bdrv_pwrite(extent->file,
+ cluster_offset + offset_in_cluster,
+ write_buf,
+ write_len);
+ if (ret != write_len) {
+ ret = ret < 0 ? ret : -EIO;
+ goto out;
+ }
+ ret = 0;
+ out:
+ g_free(data);
+ return ret;
+}
+
+static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
+ int64_t offset_in_cluster, uint8_t *buf,
+ int nb_sectors)
+{
+ int ret;
+ int cluster_bytes, buf_bytes;
+ uint8_t *cluster_buf, *compressed_data;
+ uint8_t *uncomp_buf;
+ uint32_t data_len;
+ VmdkGrainMarker *marker;
+ uLongf buf_len;
+
+
+ if (!extent->compressed) {
+ ret = bdrv_pread(extent->file,
+ cluster_offset + offset_in_cluster,
+ buf, nb_sectors * 512);
+ if (ret == nb_sectors * 512) {
+ return 0;
+ } else {
+ return -EIO;
+ }
+ }
+ cluster_bytes = extent->cluster_sectors * 512;
+ /* Read two clusters in case GrainMarker + compressed data > one cluster */
+ buf_bytes = cluster_bytes * 2;
+ cluster_buf = g_malloc(buf_bytes);
+ uncomp_buf = g_malloc(cluster_bytes);
+ ret = bdrv_pread(extent->file,
+ cluster_offset,
+ cluster_buf, buf_bytes);
+ if (ret < 0) {
+ goto out;
+ }
+ compressed_data = cluster_buf;
+ buf_len = cluster_bytes;
+ data_len = cluster_bytes;
+ if (extent->has_marker) {
+ marker = (VmdkGrainMarker *)cluster_buf;
+ compressed_data = marker->data;
+ data_len = le32_to_cpu(marker->size);
+ }
+ if (!data_len || data_len > buf_bytes) {
+ ret = -EINVAL;
+ goto out;
+ }
+ ret = uncompress(uncomp_buf, &buf_len, compressed_data, data_len);
+ if (ret != Z_OK) {
+ ret = -EINVAL;
+ goto out;
+
+ }
+ if (offset_in_cluster < 0 ||
+ offset_in_cluster + nb_sectors * 512 > buf_len) {
+ ret = -EINVAL;
+ goto out;
+ }
+ memcpy(buf, uncomp_buf + offset_in_cluster, nb_sectors * 512);
+ ret = 0;
+
+ out:
+ g_free(uncomp_buf);
+ g_free(cluster_buf);
+ return ret;
+}
+
static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
memset(buf, 0, 512 * n);
}
} else {
- ret = bdrv_pread(extent->file,
- cluster_offset + index_in_cluster * 512,
- buf, n * 512);
- if (ret < 0) {
+ ret = vmdk_read_extent(extent,
+ cluster_offset, index_in_cluster * 512,
+ buf, n);
+ if (ret) {
return ret;
}
}
bs,
extent,
&m_data,
- sector_num << 9, 1,
+ sector_num << 9, !extent->compressed,
&cluster_offset);
+ if (extent->compressed) {
+ if (ret == 0) {
+ /* Refuse write to allocated cluster for streamOptimized */
+ fprintf(stderr,
+ "VMDK: can't write to allocated cluster"
+ " for streamOptimized\n");
+ return -EIO;
+ } else {
+ /* allocate */
+ ret = get_cluster_offset(
+ bs,
+ extent,
+ &m_data,
+ sector_num << 9, 1,
+ &cluster_offset);
+ }
+ }
if (ret) {
return -EINVAL;
}
n = nb_sectors;
}
- ret = bdrv_pwrite(extent->file,
- cluster_offset + index_in_cluster * 512,
- buf,
- n * 512);
- if (ret < 0) {
+ ret = vmdk_write_extent(extent,
+ cluster_offset, index_in_cluster * 512,
+ buf, n, sector_num);
+ if (ret) {
return ret;
}
if (m_data.valid) {
}
-static int vmdk_create_extent(const char *filename, int64_t filesize, bool flat)
+static int vmdk_create_extent(const char *filename, int64_t filesize,
+ bool flat, bool compress)
{
int ret, i;
int fd = 0;
magic = cpu_to_be32(VMDK4_MAGIC);
memset(&header, 0, sizeof(header));
header.version = 1;
- header.flags = 3; /* ?? */
+ header.flags =
+ 3 | (compress ? VMDK4_FLAG_COMPRESS | VMDK4_FLAG_MARKER : 0);
+ header.compressAlgorithm = compress ? VMDK4_COMPRESSION_DEFLATE : 0;
header.capacity = filesize / 512;
header.granularity = 128;
header.num_gtes_per_gte = 512;
header.rgd_offset = cpu_to_le64(header.rgd_offset);
header.gd_offset = cpu_to_le64(header.gd_offset);
header.grain_offset = cpu_to_le64(header.grain_offset);
+ header.compressAlgorithm = cpu_to_le16(header.compressAlgorithm);
header.check_bytes[0] = 0xa;
header.check_bytes[1] = 0x20;
const char *fmt = NULL;
int flags = 0;
int ret = 0;
- bool flat, split;
+ bool flat, split, compress;
char ext_desc_lines[BUF_SIZE] = "";
char path[PATH_MAX], prefix[PATH_MAX], postfix[PATH_MAX];
const int64_t split_size = 0x80000000; /* VMDK has constant split size */
} else if (strcmp(fmt, "monolithicFlat") &&
strcmp(fmt, "monolithicSparse") &&
strcmp(fmt, "twoGbMaxExtentSparse") &&
- strcmp(fmt, "twoGbMaxExtentFlat")) {
+ strcmp(fmt, "twoGbMaxExtentFlat") &&
+ strcmp(fmt, "streamOptimized")) {
fprintf(stderr, "VMDK: Unknown subformat: %s\n", fmt);
return -EINVAL;
}
strcmp(fmt, "twoGbMaxExtentSparse"));
flat = !(strcmp(fmt, "monolithicFlat") &&
strcmp(fmt, "twoGbMaxExtentFlat"));
+ compress = !strcmp(fmt, "streamOptimized");
if (flat) {
desc_extent_line = "RW %lld FLAT \"%s\" 0\n";
} else {
snprintf(ext_filename, sizeof(ext_filename), "%s%s",
path, desc_filename);
- if (vmdk_create_extent(ext_filename, size, flat)) {
+ if (vmdk_create_extent(ext_filename, size, flat, compress)) {
return -EINVAL;
}
filesize -= size;
.type = OPT_STRING,
.help =
"VMDK flat extent format, can be one of "
- "{monolithicSparse (default) | monolithicFlat | twoGbMaxExtentSparse | twoGbMaxExtentFlat} "
+ "{monolithicSparse (default) | monolithicFlat | twoGbMaxExtentSparse | twoGbMaxExtentFlat | streamOptimized} "
},
{ NULL }
};
int encrypted; /* if true, the media is encrypted */
int valid_key; /* if true, a valid encryption key has been set */
int sg; /* if true, the device is a /dev/sg* */
- /* event callback when inserting/removing */
- void (*change_cb)(void *opaque, int reason);
- void *change_opaque;
BlockDriver *drv; /* NULL means no media */
void *opaque;
- DeviceState *peer;
+ void *dev; /* attached device model, if any */
+ /* TODO change to DeviceState when all users are qdevified */
+ const BlockDevOps *dev_ops;
+ void *dev_opaque;
char filename[1024];
char backing_file[1024]; /* if non zero, the image is a diff of
this file image */
char backing_format[16]; /* if non-zero and backing_file exists */
int is_temporary;
- int media_changed;
BlockDriverState *backing_hd;
BlockDriverState *file;
void *private;
};
-#define CHANGE_MEDIA 0x01
-#define CHANGE_SIZE 0x02
-
struct BlockDriverAIOCB {
AIOPool *pool;
BlockDriverState *bs;
BlockDriverCompletionFunc *cb, void *opaque);
void qemu_aio_release(void *p);
-void *qemu_blockalign(BlockDriverState *bs, size_t size);
-
#ifdef _WIN32
int is_windows_drive(const char *filename);
#endif
#include "qemu-option.h"
#include "qemu-config.h"
#include "sysemu.h"
-#include "hw/qdev.h"
#include "block_int.h"
static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
bdrv_flush(bs);
bdrv_close(bs);
- /* if we have a device associated with this BlockDriverState (bs->peer)
+ /* if we have a device attached to this BlockDriverState
* then we need to make the drive anonymous until the device
* can be removed. If this is a drive with no device backing
* then we can just get rid of the block driver state right here.
*/
- if (bs->peer) {
+ if (bdrv_get_attached_dev(bs)) {
bdrv_make_anon(bs);
} else {
drive_uninit(drive_get_by_blockdev(bs));
{ "\"\\n\"", "\n" },
{ "\"\\r\"", "\r" },
{ "\"\\t\"", "\t" },
- { "\"\\/\"", "\\/" },
+ { "\"/\"", "/" },
+ { "\"\\/\"", "/", .skip = 1 },
{ "\"\\\\\"", "\\" },
{ "\"\\\"\"", "\"" },
{ "\"hello world \\\"embedded string\\\"\"",
DIRS="$DIRS fsdev ui"
DIRS="$DIRS qapi"
DIRS="$DIRS qga trace"
-FILES="Makefile tests/Makefile"
+FILES="Makefile tests/Makefile qdict-test-data.txt"
FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
FILES="$FILES pc-bios/spapr-rtas/Makefile"
err = 0;
}
});
+ if (!err) {
+ total_open_fd++;
+ if (total_open_fd > open_fd_hw) {
+ v9fs_reclaim_fd(s);
+ }
+ }
return err;
}
-int v9fs_co_closedir(V9fsState *s, V9fsFidState *fidp)
+int v9fs_co_closedir(V9fsState *s, DIR *dir)
{
int err;
- DIR *dir;
- dir = fidp->fs.dir;
v9fs_co_run_in_worker(
{
err = s->ops->closedir(&s->ctx, dir);
err = -errno;
}
});
+ if (!err) {
+ total_open_fd--;
+ }
return err;
}
err = 0;
}
});
+ if (!err) {
+ total_open_fd++;
+ if (total_open_fd > open_fd_hw) {
+ v9fs_reclaim_fd(s);
+ }
+ }
return err;
}
err = -errno;
}
});
+ if (!err) {
+ total_open_fd++;
+ if (total_open_fd > open_fd_hw) {
+ v9fs_reclaim_fd(s);
+ }
+ }
return err;
}
-int v9fs_co_close(V9fsState *s, V9fsFidState *fidp)
+int v9fs_co_close(V9fsState *s, int fd)
{
- int fd;
int err;
- fd = fidp->fs.fd;
v9fs_co_run_in_worker(
{
err = s->ops->close(&s->ctx, fd);
err = -errno;
}
});
+ if (!err) {
+ total_open_fd--;
+ }
return err;
}
extern int v9fs_co_lsetxattr(V9fsState *, V9fsString *, V9fsString *,
void *, size_t, int);
extern int v9fs_co_lremovexattr(V9fsState *, V9fsString *, V9fsString *);
-extern int v9fs_co_closedir(V9fsState *, V9fsFidState *);
-extern int v9fs_co_close(V9fsState *, V9fsFidState *);
+extern int v9fs_co_closedir(V9fsState *, DIR *);
+extern int v9fs_co_close(V9fsState *, int);
extern int v9fs_co_fsync(V9fsState *, V9fsFidState *, int);
extern int v9fs_co_symlink(V9fsState *, V9fsFidState *, const char *,
const char *, gid_t);
s->config_size = sizeof(struct virtio_9p_config) +
s->tag_len;
s->vdev.get_config = virtio_9p_get_config;
+ s->fid_list = NULL;
if (v9fs_init_worker_threads() < 0) {
fprintf(stderr, "worker thread initialization failed\n");
static void virtio_9p_register_devices(void)
{
pci_qdev_register(&virtio_9p_info);
+ virtio_9p_set_fd_limit();
}
device_init(virtio_9p_register_devices)
#include "virtio-9p-coth.h"
int debug_9p_pdu;
+int open_fd_hw;
+int total_open_fd;
+static int open_fd_rc;
enum {
Oread = 0x00,
return str->size;
}
-static V9fsFidState *lookup_fid(V9fsState *s, int32_t fid)
+/*
+ * returns 0 if fid got re-opened, 1 if not, < 0 on error */
+static int v9fs_reopen_fid(V9fsState *s, V9fsFidState *f)
+{
+ int err = 1;
+ if (f->fid_type == P9_FID_FILE) {
+ if (f->fs.fd == -1) {
+ do {
+ err = v9fs_co_open(s, f, f->open_flags);
+ } while (err == -EINTR);
+ }
+ } else if (f->fid_type == P9_FID_DIR) {
+ if (f->fs.dir == NULL) {
+ do {
+ err = v9fs_co_opendir(s, f);
+ } while (err == -EINTR);
+ }
+ }
+ return err;
+}
+
+static V9fsFidState *get_fid(V9fsState *s, int32_t fid)
{
+ int err;
V9fsFidState *f;
for (f = s->fid_list; f; f = f->next) {
+ BUG_ON(f->clunked);
if (f->fid == fid) {
+ /*
+ * Update the fid ref upfront so that
+ * we don't get reclaimed when we yield
+ * in open later.
+ */
+ f->ref++;
+ /*
+ * check whether we need to reopen the
+ * file. We might have closed the fd
+ * while trying to free up some file
+ * descriptors.
+ */
+ err = v9fs_reopen_fid(s, f);
+ if (err < 0) {
+ f->ref--;
+ return NULL;
+ }
+ /*
+ * Mark the fid as referenced so that the LRU
+ * reclaim won't close the file descriptor
+ */
+ f->flags |= FID_REFERENCED;
return f;
}
}
-
return NULL;
}
{
V9fsFidState *f;
- f = lookup_fid(s, fid);
- if (f) {
- return NULL;
+ for (f = s->fid_list; f; f = f->next) {
+ /* If fid is already there return NULL */
+ BUG_ON(f->clunked);
+ if (f->fid == fid) {
+ return NULL;
+ }
}
-
f = g_malloc0(sizeof(V9fsFidState));
-
f->fid = fid;
f->fid_type = P9_FID_NONE;
-
+ f->ref = 1;
+ /*
+ * Mark the fid as referenced so that the LRU
+ * reclaim won't close the file descriptor
+ */
+ f->flags |= FID_REFERENCED;
f->next = s->fid_list;
s->fid_list = f;
return retval;
}
-static int free_fid(V9fsState *s, int32_t fid)
+static int free_fid(V9fsState *s, V9fsFidState *fidp)
{
int retval = 0;
+
+ if (fidp->fid_type == P9_FID_FILE) {
+ /* If we reclaimed the fd no need to close */
+ if (fidp->fs.fd != -1) {
+ retval = v9fs_co_close(s, fidp->fs.fd);
+ }
+ } else if (fidp->fid_type == P9_FID_DIR) {
+ if (fidp->fs.dir != NULL) {
+ retval = v9fs_co_closedir(s, fidp->fs.dir);
+ }
+ } else if (fidp->fid_type == P9_FID_XATTR) {
+ retval = v9fs_xattr_fid_clunk(s, fidp);
+ }
+ v9fs_string_free(&fidp->path);
+ g_free(fidp);
+ return retval;
+}
+
+static void put_fid(V9fsState *s, V9fsFidState *fidp)
+{
+ BUG_ON(!fidp->ref);
+ fidp->ref--;
+ /*
+ * Don't free the fid if it is in reclaim list
+ */
+ if (!fidp->ref && fidp->clunked) {
+ free_fid(s, fidp);
+ }
+}
+
+static int clunk_fid(V9fsState *s, int32_t fid)
+{
V9fsFidState **fidpp, *fidp;
for (fidpp = &s->fid_list; *fidpp; fidpp = &(*fidpp)->next) {
if (*fidpp == NULL) {
return -ENOENT;
}
-
fidp = *fidpp;
*fidpp = fidp->next;
+ fidp->clunked = 1;
+ return 0;
+}
- if (fidp->fid_type == P9_FID_FILE) {
- retval = v9fs_co_close(s, fidp);
- } else if (fidp->fid_type == P9_FID_DIR) {
- retval = v9fs_co_closedir(s, fidp);
- } else if (fidp->fid_type == P9_FID_XATTR) {
- retval = v9fs_xattr_fid_clunk(s, fidp);
+void v9fs_reclaim_fd(V9fsState *s)
+{
+ int reclaim_count = 0;
+ V9fsFidState *f, *reclaim_list = NULL;
+
+ for (f = s->fid_list; f; f = f->next) {
+ /*
+ * Unlink fids cannot be reclaimed. Check
+ * for them and skip them. Also skip fids
+ * currently being operated on.
+ */
+ if (f->ref || f->flags & FID_NON_RECLAIMABLE) {
+ continue;
+ }
+ /*
+ * if it is a recently referenced fid
+ * we leave the fid untouched and clear the
+ * reference bit. We come back to it later
+ * in the next iteration. (a simple LRU without
+ * moving list elements around)
+ */
+ if (f->flags & FID_REFERENCED) {
+ f->flags &= ~FID_REFERENCED;
+ continue;
+ }
+ /*
+ * Add fids to reclaim list.
+ */
+ if (f->fid_type == P9_FID_FILE) {
+ if (f->fs.fd != -1) {
+ /*
+ * Up the reference count so that
+ * a clunk request won't free this fid
+ */
+ f->ref++;
+ f->rclm_lst = reclaim_list;
+ reclaim_list = f;
+ f->fs_reclaim.fd = f->fs.fd;
+ f->fs.fd = -1;
+ reclaim_count++;
+ }
+ } else if (f->fid_type == P9_FID_DIR) {
+ if (f->fs.dir != NULL) {
+ /*
+ * Up the reference count so that
+ * a clunk request won't free this fid
+ */
+ f->ref++;
+ f->rclm_lst = reclaim_list;
+ reclaim_list = f;
+ f->fs_reclaim.dir = f->fs.dir;
+ f->fs.dir = NULL;
+ reclaim_count++;
+ }
+ }
+ if (reclaim_count >= open_fd_rc) {
+ break;
+ }
+ }
+ /*
+ * Now close the fid in reclaim list. Free them if they
+ * are already clunked.
+ */
+ while (reclaim_list) {
+ f = reclaim_list;
+ reclaim_list = f->rclm_lst;
+ if (f->fid_type == P9_FID_FILE) {
+ v9fs_co_close(s, f->fs_reclaim.fd);
+ } else if (f->fid_type == P9_FID_DIR) {
+ v9fs_co_closedir(s, f->fs_reclaim.dir);
+ }
+ f->rclm_lst = NULL;
+ /*
+ * Now drop the fid reference, free it
+ * if clunked.
+ */
+ put_fid(s, f);
}
- v9fs_string_free(&fidp->path);
- g_free(fidp);
- return retval;
+}
+
+static int v9fs_mark_fids_unreclaim(V9fsState *s, V9fsString *str)
+{
+ int err;
+ V9fsFidState *fidp, head_fid;
+
+ head_fid.next = s->fid_list;
+ for (fidp = s->fid_list; fidp; fidp = fidp->next) {
+ if (!strcmp(fidp->path.data, str->data)) {
+ /* Mark the fid non reclaimable. */
+ fidp->flags |= FID_NON_RECLAIMABLE;
+
+ /* reopen the file/dir if already closed */
+ err = v9fs_reopen_fid(s, fidp);
+ if (err < 0) {
+ return -1;
+ }
+ /*
+ * Go back to head of fid list because
+ * the list could have got updated when
+ * switched to the worker thread
+ */
+ if (err == 0) {
+ fidp = &head_fid;
+ }
+ }
+ }
+ return 0;
}
#define P9_QID_TYPE_DIR 0x80
fidp = alloc_fid(s, fid);
if (fidp == NULL) {
err = -EINVAL;
- goto out;
+ goto out_nofid;
}
fidp->uid = n_uname;
v9fs_string_sprintf(&fidp->path, "%s", "/");
err = fid_to_qid(s, fidp, &qid);
if (err < 0) {
err = -EINVAL;
- free_fid(s, fid);
+ clunk_fid(s, fid);
goto out;
}
offset += pdu_marshal(pdu, offset, "Q", &qid);
err = offset;
out:
+ put_fid(s, fidp);
+out_nofid:
complete_pdu(s, pdu, err);
v9fs_string_free(&uname);
v9fs_string_free(&aname);
V9fsState *s = pdu->s;
pdu_unmarshal(pdu, offset, "d", &fid);
- fidp = lookup_fid(s, fid);
+
+ fidp = get_fid(s, fid);
if (fidp == NULL) {
err = -ENOENT;
- goto out;
+ goto out_nofid;
}
err = v9fs_co_lstat(s, &fidp->path, &stbuf);
if (err < 0) {
err = offset;
v9fs_stat_free(&v9stat);
out:
+ put_fid(s, fidp);
+out_nofid:
complete_pdu(s, pdu, err);
}
pdu_unmarshal(pdu, offset, "dq", &fid, &request_mask);
- fidp = lookup_fid(s, fid);
+ fidp = get_fid(s, fid);
if (fidp == NULL) {
retval = -ENOENT;
- goto out;
+ goto out_nofid;
}
/*
* Currently we only support BASIC fields in stat, so there is no
retval = offset;
retval += pdu_marshal(pdu, offset, "A", &v9stat_dotl);
out:
+ put_fid(s, fidp);
+out_nofid:
complete_pdu(s, pdu, retval);
}
pdu_unmarshal(pdu, offset, "dI", &fid, &v9iattr);
- fidp = lookup_fid(s, fid);
+ fidp = get_fid(s, fid);
if (fidp == NULL) {
err = -EINVAL;
- goto out;
+ goto out_nofid;
}
if (v9iattr.valid & ATTR_MODE) {
err = v9fs_co_chmod(s, &fidp->path, v9iattr.mode);
}
err = offset;
out:
+ put_fid(s, fidp);
+out_nofid:
complete_pdu(s, pdu, err);
}
int32_t fid, newfid;
V9fsString *wnames = NULL;
V9fsFidState *fidp;
- V9fsFidState *newfidp;
+ V9fsFidState *newfidp = NULL;;
V9fsPDU *pdu = opaque;
V9fsState *s = pdu->s;
} else if (nwnames > P9_MAXWELEM) {
err = -EINVAL;
- goto out;
+ goto out_nofid;
}
- fidp = lookup_fid(s, fid);
+ fidp = get_fid(s, fid);
if (fidp == NULL) {
err = -ENOENT;
- goto out;
+ goto out_nofid;
}
if (fid == newfid) {
BUG_ON(fidp->fid_type != P9_FID_NONE);
v9fs_string_copy(&newfidp->path, &path);
err = v9fs_co_lstat(s, &newfidp->path, &stbuf);
if (err < 0) {
- free_fid(s, newfidp->fid);
+ clunk_fid(s, newfidp->fid);
v9fs_string_free(&path);
goto out;
}
}
err = v9fs_walk_marshal(pdu, nwnames, qids);
out:
+ put_fid(s, fidp);
+ if (newfidp) {
+ put_fid(s, newfidp);
+ }
+out_nofid:
complete_pdu(s, pdu, err);
if (nwnames && nwnames <= P9_MAXWELEM) {
for (name_idx = 0; name_idx < nwnames; name_idx++) {
} else {
pdu_unmarshal(pdu, offset, "db", &fid, &mode);
}
- fidp = lookup_fid(s, fid);
+ fidp = get_fid(s, fid);
if (fidp == NULL) {
err = -ENOENT;
- goto out;
+ goto out_nofid;
}
BUG_ON(fidp->fid_type != P9_FID_NONE);
goto out;
}
fidp->fid_type = P9_FID_FILE;
+ fidp->open_flags = flags;
+ if (flags & O_EXCL) {
+ /*
+ * We let the host file system do O_EXCL check
+ * We should not reclaim such fd
+ */
+ fidp->flags |= FID_NON_RECLAIMABLE;
+ }
iounit = get_iounit(s, &fidp->path);
offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
err = offset;
}
out:
+ put_fid(s, fidp);
+out_nofid:
complete_pdu(s, pdu, err);
}
pdu_unmarshal(pdu, offset, "dsddd", &dfid, &name, &flags,
&mode, &gid);
- fidp = lookup_fid(pdu->s, dfid);
+ fidp = get_fid(pdu->s, dfid);
if (fidp == NULL) {
err = -ENOENT;
- goto out;
+ goto out_nofid;
}
v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
goto out;
}
fidp->fid_type = P9_FID_FILE;
+ fidp->open_flags = flags;
+ if (flags & O_EXCL) {
+ /*
+ * We let the host file system do O_EXCL check
+ * We should not reclaim such fd
+ */
+ fidp->flags |= FID_NON_RECLAIMABLE;
+ }
iounit = get_iounit(pdu->s, &fullname);
err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
if (err < 0) {
fidp->fid_type = P9_FID_NONE;
if (fidp->fs.fd > 0) {
- close(fidp->fs.fd);
+ v9fs_co_close(pdu->s, fidp->fs.fd);
}
goto out;
}
offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
err = offset;
out:
+ put_fid(pdu->s, fidp);
+out_nofid:
complete_pdu(pdu->s, pdu, err);
v9fs_string_free(&name);
v9fs_string_free(&fullname);
V9fsState *s = pdu->s;
pdu_unmarshal(pdu, offset, "dd", &fid, &datasync);
- fidp = lookup_fid(s, fid);
+ fidp = get_fid(s, fid);
if (fidp == NULL) {
err = -ENOENT;
- goto out;
+ goto out_nofid;
}
err = v9fs_co_fsync(s, fidp, datasync);
if (!err) {
err = offset;
}
-out:
+ put_fid(s, fidp);
+out_nofid:
complete_pdu(s, pdu, err);
}
int err;
int32_t fid;
size_t offset = 7;
+ V9fsFidState *fidp;
V9fsPDU *pdu = opaque;
V9fsState *s = pdu->s;
pdu_unmarshal(pdu, offset, "d", &fid);
- err = free_fid(s, fid);
+
+ fidp = get_fid(s, fid);
+ if (fidp == NULL) {
+ err = -ENOENT;
+ goto out_nofid;
+ }
+ err = clunk_fid(s, fidp->fid);
if (err < 0) {
goto out;
}
err = offset;
out:
+ put_fid(s, fidp);
+out_nofid:
complete_pdu(s, pdu, err);
}
V9fsState *s = pdu->s;
pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &max_count);
- fidp = lookup_fid(s, fid);
+
+ fidp = get_fid(s, fid);
if (fidp == NULL) {
err = -EINVAL;
- goto out;
+ goto out_nofid;
}
if (fidp->fid_type == P9_FID_DIR) {
err = -EINVAL;
}
out:
+ put_fid(s, fidp);
+out_nofid:
complete_pdu(s, pdu, err);
}
pdu_unmarshal(pdu, offset, "dqd", &fid, &initial_offset, &max_count);
- fidp = lookup_fid(s, fid);
- if (fidp == NULL || !fidp->fs.dir) {
+ fidp = get_fid(s, fid);
+ if (fidp == NULL) {
+ retval = -EINVAL;
+ goto out_nofid;
+ }
+ if (!fidp->fs.dir) {
retval = -EINVAL;
goto out;
}
retval += pdu_marshal(pdu, offset, "d", count);
retval += count;
out:
+ put_fid(s, fidp);
+out_nofid:
complete_pdu(s, pdu, retval);
}
V9fsState *s = pdu->s;
pdu_unmarshal(pdu, offset, "dqdv", &fid, &off, &count, sg, &cnt);
- fidp = lookup_fid(s, fid);
+
+ fidp = get_fid(s, fid);
if (fidp == NULL) {
err = -EINVAL;
- goto out;
+ goto out_nofid;
}
if (fidp->fid_type == P9_FID_FILE) {
if (fidp->fs.fd == -1) {
offset += pdu_marshal(pdu, offset, "d", total);
err = offset;
out:
+ put_fid(s, fidp);
+out_nofid:
complete_pdu(s, pdu, err);
}
pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name,
&perm, &mode, &extension);
- fidp = lookup_fid(pdu->s, fid);
+ fidp = get_fid(pdu->s, fid);
if (fidp == NULL) {
err = -EINVAL;
- goto out;
+ goto out_nofid;
}
v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
}
} else if (perm & P9_STAT_MODE_LINK) {
int32_t nfid = atoi(extension.data);
- V9fsFidState *nfidp = lookup_fid(pdu->s, nfid);
+ V9fsFidState *nfidp = get_fid(pdu->s, nfid);
if (nfidp == NULL) {
err = -EINVAL;
goto out;
}
err = v9fs_co_link(pdu->s, &nfidp->path, &fullname);
if (err < 0) {
+ put_fid(pdu->s, nfidp);
goto out;
}
+ put_fid(pdu->s, nfidp);
} else if (perm & P9_STAT_MODE_DEVICE) {
char ctype;
uint32_t major, minor;
goto out;
}
fidp->fid_type = P9_FID_FILE;
+ fidp->open_flags = omode_to_uflags(mode);
+ if (fidp->open_flags & O_EXCL) {
+ /*
+ * We let the host file system do O_EXCL check
+ * We should not reclaim such fd
+ */
+ fidp->flags |= FID_NON_RECLAIMABLE;
+ }
}
err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
if (err < 0) {
fidp->fid_type = P9_FID_NONE;
if (fidp->fs.fd) {
- close(fidp->fs.fd);
+ v9fs_co_close(pdu->s, fidp->fs.fd);
}
goto out;
}
offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
err = offset;
out:
+ put_fid(pdu->s, fidp);
+out_nofid:
complete_pdu(pdu->s, pdu, err);
v9fs_string_free(&name);
v9fs_string_free(&extension);
v9fs_string_init(&fullname);
pdu_unmarshal(pdu, offset, "dssd", &dfid, &name, &symname, &gid);
- dfidp = lookup_fid(pdu->s, dfid);
+ dfidp = get_fid(pdu->s, dfid);
if (dfidp == NULL) {
err = -EINVAL;
- goto out;
+ goto out_nofid;
}
v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name.data);
offset += pdu_marshal(pdu, offset, "Q", &qid);
err = offset;
out:
+ put_fid(pdu->s, dfidp);
+out_nofid:
complete_pdu(pdu->s, pdu, err);
v9fs_string_free(&name);
v9fs_string_free(&symname);
pdu_unmarshal(pdu, offset, "dds", &dfid, &oldfid, &name);
- dfidp = lookup_fid(s, dfid);
+ dfidp = get_fid(s, dfid);
if (dfidp == NULL) {
err = -ENOENT;
- goto out;
+ goto out_nofid;
}
- oldfidp = lookup_fid(s, oldfid);
+ oldfidp = get_fid(s, oldfid);
if (oldfidp == NULL) {
err = -ENOENT;
goto out;
v9fs_string_free(&fullname);
out:
+ put_fid(s, dfidp);
+out_nofid:
v9fs_string_free(&name);
complete_pdu(s, pdu, err);
}
pdu_unmarshal(pdu, offset, "d", &fid);
- fidp = lookup_fid(pdu->s, fid);
+ fidp = get_fid(pdu->s, fid);
if (fidp == NULL) {
err = -EINVAL;
- goto out;
+ goto out_nofid;
+ }
+ /*
+ * IF the file is unlinked, we cannot reopen
+ * the file later. So don't reclaim fd
+ */
+ err = v9fs_mark_fids_unreclaim(pdu->s, &fidp->path);
+ if (err < 0) {
+ goto out_err;
}
err = v9fs_co_remove(pdu->s, &fidp->path);
if (!err) {
err = offset;
}
-
+out_err:
/* For TREMOVE we need to clunk the fid even on failed remove */
- free_fid(pdu->s, fidp->fid);
-out:
+ clunk_fid(pdu->s, fidp->fid);
+ put_fid(pdu->s, fidp);
+out_nofid:
complete_pdu(pdu->s, pdu, err);
}
{
char *end;
int err = 0;
+ V9fsFidState *dirfidp = NULL;
char *old_name, *new_name;
if (newdirfid != -1) {
- V9fsFidState *dirfidp;
- dirfidp = lookup_fid(s, newdirfid);
+ dirfidp = get_fid(s, newdirfid);
if (dirfidp == NULL) {
err = -ENOENT;
- goto out;
+ goto out_nofid;
}
BUG_ON(dirfidp->fid_type != P9_FID_NONE);
v9fs_string_copy(&fidp->path, name);
}
out:
+ if (dirfidp) {
+ put_fid(s, dirfidp);
+ }
+out_nofid:
return err;
}
pdu_unmarshal(pdu, offset, "dds", &fid, &newdirfid, &name);
- fidp = lookup_fid(s, fid);
+ fidp = get_fid(s, fid);
if (fidp == NULL) {
err = -ENOENT;
- goto out;
+ goto out_nofid;
}
BUG_ON(fidp->fid_type != P9_FID_NONE);
if (!err) {
err = offset;
}
-out:
+ put_fid(s, fidp);
+out_nofid:
complete_pdu(s, pdu, err);
v9fs_string_free(&name);
}
V9fsState *s = pdu->s;
pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat);
- fidp = lookup_fid(s, fid);
+
+ fidp = get_fid(s, fid);
if (fidp == NULL) {
err = -EINVAL;
- goto out;
+ goto out_nofid;
}
/* do we need to sync the file? */
if (donttouch_stat(&v9stat)) {
}
err = offset;
out:
+ put_fid(s, fidp);
+out_nofid:
v9fs_stat_free(&v9stat);
complete_pdu(s, pdu, err);
}
V9fsState *s = pdu->s;
pdu_unmarshal(pdu, offset, "d", &fid);
- fidp = lookup_fid(s, fid);
+ fidp = get_fid(s, fid);
if (fidp == NULL) {
retval = -ENOENT;
- goto out;
+ goto out_nofid;
}
retval = v9fs_co_statfs(s, &fidp->path, &stbuf);
if (retval < 0) {
retval = offset;
retval += v9fs_fill_statfs(s, pdu, &stbuf);
out:
+ put_fid(s, fidp);
+out_nofid:
complete_pdu(s, pdu, retval);
return;
}
pdu_unmarshal(pdu, offset, "dsdddd", &fid, &name, &mode,
&major, &minor, &gid);
- fidp = lookup_fid(s, fid);
+ fidp = get_fid(s, fid);
if (fidp == NULL) {
err = -ENOENT;
- goto out;
+ goto out_nofid;
}
v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
err = v9fs_co_mknod(s, &fullname, fidp->uid, gid,
err = offset;
err += pdu_marshal(pdu, offset, "Q", &qid);
out:
+ put_fid(s, fidp);
+out_nofid:
complete_pdu(s, pdu, err);
v9fs_string_free(&fullname);
v9fs_string_free(&name);
/* We support only block flag now (that too ignored currently) */
if (flock->flags & ~P9_LOCK_FLAGS_BLOCK) {
err = -EINVAL;
- goto out;
+ goto out_nofid;
}
- fidp = lookup_fid(s, fid);
+ fidp = get_fid(s, fid);
if (fidp == NULL) {
err = -ENOENT;
- goto out;
+ goto out_nofid;
}
err = v9fs_co_fstat(s, fidp->fs.fd, &stbuf);
if (err < 0) {
}
status = P9_LOCK_SUCCESS;
out:
+ put_fid(s, fidp);
+out_nofid:
err = offset;
err += pdu_marshal(pdu, offset, "b", status);
complete_pdu(s, pdu, err);
&glock->start, &glock->length, &glock->proc_id,
&glock->client_id);
- fidp = lookup_fid(s, fid);
+ fidp = get_fid(s, fid);
if (fidp == NULL) {
err = -ENOENT;
- goto out;
+ goto out_nofid;
}
err = v9fs_co_fstat(s, fidp->fs.fd, &stbuf);
if (err < 0) {
&glock->client_id);
err = offset;
out:
+ put_fid(s, fidp);
+out_nofid:
complete_pdu(s, pdu, err);
g_free(glock);
}
v9fs_string_init(&fullname);
pdu_unmarshal(pdu, offset, "dsdd", &fid, &name, &mode, &gid);
- fidp = lookup_fid(pdu->s, fid);
+ fidp = get_fid(pdu->s, fid);
if (fidp == NULL) {
err = -ENOENT;
- goto out;
+ goto out_nofid;
}
v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
err = v9fs_co_mkdir(pdu->s, fullname.data, mode, fidp->uid, gid);
offset += pdu_marshal(pdu, offset, "Q", &qid);
err = offset;
out:
+ put_fid(pdu->s, fidp);
+out_nofid:
complete_pdu(pdu->s, pdu, err);
v9fs_string_free(&fullname);
v9fs_string_free(&name);
size_t offset = 7;
int32_t fid, newfid;
V9fsFidState *file_fidp;
- V9fsFidState *xattr_fidp;
+ V9fsFidState *xattr_fidp = NULL;
V9fsPDU *pdu = opaque;
V9fsState *s = pdu->s;
pdu_unmarshal(pdu, offset, "dds", &fid, &newfid, &name);
- file_fidp = lookup_fid(s, fid);
+ file_fidp = get_fid(s, fid);
if (file_fidp == NULL) {
err = -ENOENT;
- goto out;
+ goto out_nofid;
}
xattr_fidp = alloc_fid(s, newfid);
if (xattr_fidp == NULL) {
size = v9fs_co_llistxattr(s, &xattr_fidp->path, NULL, 0);
if (size < 0) {
err = size;
- free_fid(s, xattr_fidp->fid);
+ clunk_fid(s, xattr_fidp->fid);
goto out;
}
/*
xattr_fidp->fs.xattr.value,
xattr_fidp->fs.xattr.len);
if (err < 0) {
- free_fid(s, xattr_fidp->fid);
+ clunk_fid(s, xattr_fidp->fid);
goto out;
}
}
&name, NULL, 0);
if (size < 0) {
err = size;
- free_fid(s, xattr_fidp->fid);
+ clunk_fid(s, xattr_fidp->fid);
goto out;
}
/*
&name, xattr_fidp->fs.xattr.value,
xattr_fidp->fs.xattr.len);
if (err < 0) {
- free_fid(s, xattr_fidp->fid);
+ clunk_fid(s, xattr_fidp->fid);
goto out;
}
}
err = offset;
}
out:
+ put_fid(s, file_fidp);
+ if (xattr_fidp) {
+ put_fid(s, xattr_fidp);
+ }
+out_nofid:
complete_pdu(s, pdu, err);
v9fs_string_free(&name);
}
pdu_unmarshal(pdu, offset, "dsqd",
&fid, &name, &size, &flags);
- file_fidp = lookup_fid(s, fid);
+ file_fidp = get_fid(s, fid);
if (file_fidp == NULL) {
err = -EINVAL;
- goto out;
+ goto out_nofid;
}
/* Make the file fid point to xattr */
xattr_fidp = file_fidp;
xattr_fidp->fs.xattr.value = NULL;
}
err = offset;
-out:
+ put_fid(s, file_fidp);
+out_nofid:
complete_pdu(s, pdu, err);
v9fs_string_free(&name);
}
V9fsFidState *fidp;
pdu_unmarshal(pdu, offset, "d", &fid);
- fidp = lookup_fid(pdu->s, fid);
+ fidp = get_fid(pdu->s, fid);
if (fidp == NULL) {
err = -ENOENT;
- goto out;
+ goto out_nofid;
}
v9fs_string_init(&target);
err = offset;
v9fs_string_free(&target);
out:
+ put_fid(pdu->s, fidp);
+out_nofid:
complete_pdu(pdu->s, pdu, err);
}
}
free_pdu(s, pdu);
}
+
+void virtio_9p_set_fd_limit(void)
+{
+ struct rlimit rlim;
+ if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
+ fprintf(stderr, "Failed to get the resource limit\n");
+ exit(1);
+ }
+ open_fd_hw = rlim.rlim_cur - MIN(400, rlim.rlim_cur/3);
+ open_fd_rc = rlim.rlim_cur/2;
+}
#include <dirent.h>
#include <sys/time.h>
#include <utime.h>
+#include <sys/resource.h>
#include "hw/virtio.h"
#include "fsdev/file-op-9p.h"
#define P9_NOTAG (u16)(~0)
#define P9_NOFID (u32)(~0)
#define P9_MAXWELEM 16
+
+#define FID_REFERENCED 0x1
+#define FID_NON_RECLAIMABLE 0x2
static inline const char *rpath(FsContext *ctx, const char *path, char *buffer)
{
snprintf(buffer, PATH_MAX, "%s/%s", ctx->fs_root, path);
int32_t fid;
V9fsString path;
union {
- int fd;
- DIR *dir;
- V9fsXattr xattr;
+ int fd;
+ DIR *dir;
+ V9fsXattr xattr;
} fs;
+ union {
+ int fd;
+ DIR *dir;
+ } fs_reclaim;
+ int flags;
+ int open_flags;
uid_t uid;
+ int ref;
+ int clunked;
V9fsFidState *next;
+ V9fsFidState *rclm_lst;
};
typedef struct V9fsState
V9fsString client_id;
} V9fsGetlock;
+extern int open_fd_hw;
+extern int total_open_fd;
+
size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
size_t offset, size_t size, int pack);
}
extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq);
+extern void virtio_9p_set_fd_limit(void);
+extern void v9fs_reclaim_fd(V9fsState *s);
#endif
#include "boards.h"
#include "loader.h"
#include "elf.h"
+#include "exec-memory.h"
#define KERNEL_LOAD_ADDR 0x10000
#define AN5206_MBAR_ADDR 0x10000000
int kernel_size;
uint64_t elf_entry;
target_phys_addr_t entry;
+ MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *ram = g_new(MemoryRegion, 1);
+ MemoryRegion *sram = g_new(MemoryRegion, 1);
if (!cpu_model)
cpu_model = "m5206";
env->rambar0 = AN5206_RAMBAR_ADDR | 1;
/* DRAM at address zero */
- cpu_register_physical_memory(0, ram_size,
- qemu_ram_alloc(NULL, "an5206.ram", ram_size) | IO_MEM_RAM);
+ memory_region_init_ram(ram, NULL, "an5206.ram", ram_size);
+ memory_region_add_subregion(address_space_mem, 0, ram);
/* Internal SRAM. */
- cpu_register_physical_memory(AN5206_RAMBAR_ADDR, 512,
- qemu_ram_alloc(NULL, "an5206.sram", 512) | IO_MEM_RAM);
+ memory_region_init_ram(sram, NULL, "an5206.sram", 512);
+ memory_region_add_subregion(address_space_mem, AN5206_RAMBAR_ADDR, sram);
mcf5206_init(AN5206_MBAR_ADDR, env);
#ifndef ARM_MISC_H
#define ARM_MISC_H 1
+#include "memory.h"
+
/* The CPU is also modeled as an interrupt controller. */
#define ARM_PIC_CPU_IRQ 0
#define ARM_PIC_CPU_FIQ 1
qemu_irq *arm_pic_init_cpu(CPUState *env);
/* armv7m.c */
-qemu_irq *armv7m_init(int flash_size, int sram_size,
+qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
+ int flash_size, int sram_size,
const char *kernel_filename, const char *cpu_model);
/* arm_boot.c */
flash_size and sram_size are in kb.
Returns the NVIC array. */
-qemu_irq *armv7m_init(int flash_size, int sram_size,
+qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
+ int flash_size, int sram_size,
const char *kernel_filename, const char *cpu_model)
{
CPUState *env;
uint64_t lowaddr;
int i;
int big_endian;
+ MemoryRegion *sram = g_new(MemoryRegion, 1);
+ MemoryRegion *flash = g_new(MemoryRegion, 1);
+ MemoryRegion *hack = g_new(MemoryRegion, 1);
flash_size *= 1024;
sram_size *= 1024;
#endif
/* Flash programming is done via the SCU, so pretend it is ROM. */
- cpu_register_physical_memory(0, flash_size,
- qemu_ram_alloc(NULL, "armv7m.flash",
- flash_size) | IO_MEM_ROM);
- cpu_register_physical_memory(0x20000000, sram_size,
- qemu_ram_alloc(NULL, "armv7m.sram",
- sram_size) | IO_MEM_RAM);
+ memory_region_init_ram(flash, NULL, "armv7m.flash", flash_size);
+ memory_region_set_readonly(flash, true);
+ memory_region_add_subregion(address_space_mem, 0, flash);
+ memory_region_init_ram(sram, NULL, "armv7m.sram", sram_size);
+ memory_region_add_subregion(address_space_mem, 0x20000000, sram);
armv7m_bitband_init();
nvic = qdev_create(NULL, "armv7m_nvic");
/* Hack to map an additional page of ram at the top of the address
space. This stops qemu complaining about executing code outside RAM
when returning from an exception. */
- cpu_register_physical_memory(0xfffff000, 0x1000,
- qemu_ram_alloc(NULL, "armv7m.hack",
- 0x1000) | IO_MEM_RAM);
+ memory_region_init_ram(hack, NULL, "armv7m.hack", 0x1000);
+ memory_region_add_subregion(address_space_mem, 0xfffff000, hack);
qemu_register_reset(armv7m_reset, env);
return pic;
#include "elf.h"
#include "cris-boot.h"
#include "blockdev.h"
+#include "exec-memory.h"
#define D(x)
#define DNAND(x)
int i;
int nand_regs;
int gpio_regs;
- ram_addr_t phys_ram;
- ram_addr_t phys_intmem;
+ MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
+ MemoryRegion *phys_intmem = g_new(MemoryRegion, 1);
/* init CPUs */
if (cpu_model == NULL) {
env = cpu_init(cpu_model);
/* allocate RAM */
- phys_ram = qemu_ram_alloc(NULL, "axisdev88.ram", ram_size);
- cpu_register_physical_memory(0x40000000, ram_size, phys_ram | IO_MEM_RAM);
+ memory_region_init_ram(phys_ram, NULL, "axisdev88.ram", ram_size);
+ memory_region_add_subregion(address_space_mem, 0x40000000, phys_ram);
/* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the
internal memory. */
- phys_intmem = qemu_ram_alloc(NULL, "axisdev88.chipram", INTMEM_SIZE);
- cpu_register_physical_memory(0x38000000, INTMEM_SIZE,
- phys_intmem | IO_MEM_RAM);
-
+ memory_region_init_ram(phys_intmem, NULL, "axisdev88.chipram", INTMEM_SIZE);
+ memory_region_add_subregion(address_space_mem, 0x38000000, phys_intmem);
/* Attach a NAND flash to CS1. */
nand = drive_get(IF_MTD, 0, 0);
{
unsigned mode;
+ memory_region_transaction_begin();
if ((s->vga.sr[0x17] & 0x44) == 0x44) {
goto generic_io;
} else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
unmap_linear_vram(s);
}
}
+ memory_region_transaction_commit();
}
{
StrongARMState *s;
DriveInfo *dinfo;
- ram_addr_t phys_flash;
if (!cpu_model) {
cpu_model = "sa1110";
s = sa1110_init(collie_binfo.ram_size, cpu_model);
- phys_flash = qemu_ram_alloc(NULL, "collie.fl1", 0x02000000);
dinfo = drive_get(IF_PFLASH, 0, 0);
- pflash_cfi01_register(SA_CS0, phys_flash,
+ pflash_cfi01_register(SA_CS0, NULL, "collie.fl1", 0x02000000,
dinfo ? dinfo->bdrv : NULL, (64 * 1024),
512, 4, 0x00, 0x00, 0x00, 0x00, 0);
- phys_flash = qemu_ram_alloc(NULL, "collie.fl2", 0x02000000);
dinfo = drive_get(IF_PFLASH, 0, 1);
- pflash_cfi01_register(SA_CS1, phys_flash,
+ pflash_cfi01_register(SA_CS1, NULL, "collie.fl2", 0x02000000,
dinfo ? dinfo->bdrv : NULL, (64 * 1024),
512, 4, 0x00, 0x00, 0x00, 0x00, 0);
static int pci_dec_21154_init_device(SysBusDevice *dev)
{
DECState *s;
- int pci_mem_config, pci_mem_data;
s = FROM_SYSBUS(DECState, dev);
- pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
- DEVICE_LITTLE_ENDIAN);
- pci_mem_data = pci_host_data_register_mmio(&s->host_state,
- DEVICE_LITTLE_ENDIAN);
- sysbus_init_mmio(dev, 0x1000, pci_mem_config);
- sysbus_init_mmio(dev, 0x1000, pci_mem_data);
+ memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
+ &s->host_state, "pci-conf-idx", 0x1000);
+ memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
+ &s->host_state, "pci-data-idx", 0x1000);
+ sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
+ sysbus_init_mmio_region(dev, &s->host_state.data_mem);
return 0;
}
#include "boards.h"
#include "loader.h"
#include "elf.h"
+#include "exec-memory.h"
#define KERNEL_LOAD_ADDR 0x10000
const char *initrd_filename, const char *cpu_model)
{
CPUState *env;
+ MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *ram = g_new(MemoryRegion, 1);
int kernel_size;
uint64_t elf_entry;
target_phys_addr_t entry;
env->vbr = 0;
/* RAM at address zero */
- cpu_register_physical_memory(0, ram_size,
- qemu_ram_alloc(NULL, "dummy_m68k.ram", ram_size) | IO_MEM_RAM);
+ memory_region_init_ram(ram, NULL, "dummy_m68k.ram", ram_size);
+ memory_region_add_subregion(address_space_mem, 0, ram);
/* Load kernel. */
if (kernel_filename) {
NULL,
};
-static void fdrive_media_changed_pre_save(void *opaque)
-{
- FDrive *drive = opaque;
-
- drive->media_changed = drive->bs->media_changed;
-}
-
-static int fdrive_media_changed_post_load(void *opaque, int version_id)
-{
- FDrive *drive = opaque;
-
- if (drive->bs != NULL) {
- drive->bs->media_changed = drive->media_changed;
- }
-
- /* User ejected the floppy when drive->bs == NULL */
- return 0;
-}
-
static bool fdrive_media_changed_needed(void *opaque)
{
FDrive *drive = opaque;
- return (drive->bs != NULL && drive->bs->media_changed != 1);
+ return (drive->bs != NULL && drive->media_changed != 1);
}
static const VMStateDescription vmstate_fdrive_media_changed = {
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
- .pre_save = fdrive_media_changed_pre_save,
- .post_load = fdrive_media_changed_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT8(media_changed, FDrive),
VMSTATE_END_OF_LIST()
if (!drv->bs)
return 0;
- ret = bdrv_media_changed(drv->bs);
+ if (drv->media_changed) {
+ drv->media_changed = 0;
+ ret = 1;
+ } else {
+ ret = bdrv_media_changed(drv->bs);
+ if (ret < 0) {
+ ret = 0; /* we don't know, assume no */
+ }
+ }
if (ret) {
fd_revalidate(drv);
}
fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
}
+static void fdctrl_change_cb(void *opaque)
+{
+ FDrive *drive = opaque;
+
+ drive->media_changed = 1;
+}
+
+static const BlockDevOps fdctrl_block_ops = {
+ .change_media_cb = fdctrl_change_cb,
+};
+
/* Init functions */
static int fdctrl_connect_drives(FDCtrl *fdctrl)
{
fd_init(drive);
fd_revalidate(drive);
if (drive->bs) {
+ drive->media_changed = 1;
bdrv_set_removable(drive->bs, 1);
+ bdrv_set_dev_ops(drive->bs, &fdctrl_block_ops, drive);
}
}
return 0;
/* NOR flash devices */
+
+#include "memory.h"
+
typedef struct pflash_t pflash_t;
/* pflash_cfi01.c */
-pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
+pflash_t *pflash_cfi01_register(target_phys_addr_t base,
+ DeviceState *qdev, const char *name,
+ target_phys_addr_t size,
BlockDriverState *bs,
uint32_t sector_len, int nb_blocs, int width,
uint16_t id0, uint16_t id1,
uint16_t id2, uint16_t id3, int be);
/* pflash_cfi02.c */
-pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
+pflash_t *pflash_cfi02_register(target_phys_addr_t base,
+ DeviceState *qdev, const char *name,
+ target_phys_addr_t size,
BlockDriverState *bs, uint32_t sector_len,
int nb_blocs, int nb_mappings, int width,
uint16_t id0, uint16_t id1,
uint16_t unlock_addr0, uint16_t unlock_addr1,
int be);
+MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl);
+
/* nand.c */
DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id);
void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale,
static int pci_grackle_init_device(SysBusDevice *dev)
{
GrackleState *s;
- int pci_mem_config, pci_mem_data;
s = FROM_SYSBUS(GrackleState, dev);
- pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
- DEVICE_LITTLE_ENDIAN);
- pci_mem_data = pci_host_data_register_mmio(&s->host_state,
- DEVICE_LITTLE_ENDIAN);
- sysbus_init_mmio(dev, 0x1000, pci_mem_config);
- sysbus_init_mmio(dev, 0x1000, pci_mem_data);
+ memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
+ &s->host_state, "pci-conf-idx", 0x1000);
+ memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
+ &s->host_state, "pci-data-idx", 0x1000);
+ sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
+ sysbus_init_mmio_region(dev, &s->host_state.data_mem);
qemu_register_reset(pci_grackle_reset, &s->host_state);
return 0;
#else
be = 0;
#endif
- if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(NULL, "connext.rom",
- connex_rom),
+ if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom,
dinfo->bdrv, sector_len, connex_rom / sector_len,
2, 0, 0, 0, 0, be)) {
fprintf(stderr, "qemu: Error registering flash memory.\n");
#else
be = 0;
#endif
- if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(NULL, "verdex.rom",
- verdex_rom),
+ if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom,
dinfo->bdrv, sector_len, verdex_rom / sector_len,
2, 0, 0, 0, 0, be)) {
fprintf(stderr, "qemu: Error registering flash memory.\n");
}
/* called when the inserted state of the media has changed */
-static void cdrom_change_cb(void *opaque, int reason)
+static void ide_cd_change_cb(void *opaque)
{
IDEState *s = opaque;
uint64_t nb_sectors;
- if (!(reason & CHANGE_MEDIA)) {
- return;
- }
-
bdrv_get_geometry(s->bs, &nb_sectors);
s->nb_sectors = nb_sectors;
s->status = READY_STAT | SEEK_STAT;
ide_set_irq(s->bus);
break;
- case WIN_READ_EXT:
+ case WIN_READ_EXT:
lba48 = 1;
case WIN_READ:
case WIN_READ_ONCE:
s->req_nb_sectors = 1;
ide_sector_read(s);
break;
- case WIN_WRITE_EXT:
+ case WIN_WRITE_EXT:
lba48 = 1;
case WIN_WRITE:
case WIN_WRITE_ONCE:
ide_transfer_start(s, s->io_buffer, 512, ide_sector_write);
s->media_changed = 1;
break;
- case WIN_MULTREAD_EXT:
+ case WIN_MULTREAD_EXT:
lba48 = 1;
case WIN_MULTREAD:
if (!s->mult_sectors)
ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write);
s->media_changed = 1;
break;
- case WIN_READDMA_EXT:
+ case WIN_READDMA_EXT:
lba48 = 1;
case WIN_READDMA:
case WIN_READDMA_ONCE:
ide_cmd_lba48_transform(s, lba48);
ide_sector_start_dma(s, IDE_DMA_READ);
break;
- case WIN_WRITEDMA_EXT:
+ case WIN_WRITEDMA_EXT:
lba48 = 1;
case WIN_WRITEDMA:
case WIN_WRITEDMA_ONCE:
case WIN_STANDBYNOW1:
case WIN_STANDBYNOW2:
case WIN_IDLEIMMEDIATE:
- case CFA_IDLEIMMEDIATE:
+ case WIN_IDLEIMMEDIATE2:
case WIN_SETIDLE1:
case WIN_SETIDLE2:
case WIN_SLEEPNOW1:
*/
ide_set_irq(s->bus);
break;
- case WIN_SRST:
+ case WIN_DEVICE_RESET:
if (s->drive_kind != IDE_CD)
goto abort_cmd;
ide_set_signature(s);
ide_set_irq(s->bus);
break;
- case WIN_SMART:
+ case WIN_SMART:
if (s->drive_kind == IDE_CD)
goto abort_cmd;
if (s->hcyl != 0xc2 || s->lcyl != 0x4f)
bus->dma->ops->reset(bus->dma);
}
+static const BlockDevOps ide_cd_block_ops = {
+ .change_media_cb = ide_cd_change_cb,
+};
+
int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
const char *version, const char *serial)
{
s->smart_errors = 0;
s->smart_selftest_count = 0;
if (kind == IDE_CD) {
- bdrv_set_change_cb(bs, cdrom_change_cb, s);
+ bdrv_set_dev_ops(bs, &ide_cd_block_ops, s);
bs->buffer_alignment = 2048;
} else {
if (!bdrv_is_inserted(s->bs)) {
error_report("Can't set up IDE drive %s", dinfo->id);
exit(1);
}
+ bdrv_attach_dev_nofail(dinfo->bdrv, &bus->ifs[i]);
} else {
ide_reset(&bus->ifs[i]);
}
}
/* Fields for GET_EVENT_STATUS_NOTIFICATION ATAPI command */
-const VMStateDescription vmstate_ide_atapi_gesn_state = {
+static const VMStateDescription vmstate_ide_atapi_gesn_state = {
.name ="ide_drive/atapi/gesn_state",
.version_id = 1,
.minimum_version_id = 1,
}
};
-const VMStateDescription vmstate_ide_drive_pio_state = {
+static const VMStateDescription vmstate_ide_drive_pio_state = {
.name = "ide_drive/pio_state",
.version_id = 1,
.minimum_version_id = 1,
}
};
-const VMStateDescription vmstate_ide_error_status = {
+static const VMStateDescription vmstate_ide_error_status = {
.name ="ide_bus/error",
.version_id = 1,
.minimum_version_id = 1,
#define IDE_CMD_RESET 0x04
#define IDE_CMD_DISABLE_IRQ 0x02
-/* ATA/ATAPI Commands pre T13 Spec */
+/* ACS-2 T13/2015-D Table B.2 Command codes */
#define WIN_NOP 0x00
-/*
- * 0x01->0x02 Reserved
- */
+/* reserved 0x01..0x02 */
#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */
-/*
- * 0x04->0x05 Reserved
- */
+/* reserved 0x04..0x05 */
#define WIN_DSM 0x06
-/*
- * 0x07 Reserved
- */
-#define WIN_SRST 0x08 /* ATAPI soft reset command */
+/* reserved 0x07 */
#define WIN_DEVICE_RESET 0x08
-/*
- * 0x09->0x0F Reserved
- */
-#define WIN_RECAL 0x10
-#define WIN_RESTORE WIN_RECAL
-/*
- * 0x10->0x1F Reserved
- */
+/* reserved 0x09..0x0a */
+/* REQUEST SENSE DATA EXT 0x0B */
+/* reserved 0x0C..0x0F */
+#define WIN_RECAL 0x10 /* obsolete since ATA4 */
+/* obsolete since ATA3, retired in ATA4 0x11..0x1F */
#define WIN_READ 0x20 /* 28-Bit */
-#define WIN_READ_ONCE 0x21 /* 28-Bit without retries */
-#define WIN_READ_LONG 0x22 /* 28-Bit */
-#define WIN_READ_LONG_ONCE 0x23 /* 28-Bit without retries */
+#define WIN_READ_ONCE 0x21 /* 28-Bit w/o retries, obsolete since ATA5 */
+/* obsolete since ATA4 0x22..0x23 */
#define WIN_READ_EXT 0x24 /* 48-Bit */
#define WIN_READDMA_EXT 0x25 /* 48-Bit */
-#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */
+#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit, obsolete since ACS2 */
#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */
-/*
- * 0x28
- */
+/* reserved 0x28 */
#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */
-/*
- * 0x2A->0x2F Reserved
- */
+/* READ STREAM DMA EXT 0x2A */
+/* READ STREAM EXT 0x2B */
+/* reserved 0x2C..0x2E */
+/* READ LOG EXT 0x2F */
#define WIN_WRITE 0x30 /* 28-Bit */
-#define WIN_WRITE_ONCE 0x31 /* 28-Bit without retries */
-#define WIN_WRITE_LONG 0x32 /* 28-Bit */
-#define WIN_WRITE_LONG_ONCE 0x33 /* 28-Bit without retries */
+#define WIN_WRITE_ONCE 0x31 /* 28-Bit w/o retries, obsolete since ATA5 */
+/* obsolete since ATA4 0x32..0x33 */
#define WIN_WRITE_EXT 0x34 /* 48-Bit */
#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */
#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */
+#define WIN_SET_MAX_EXT 0x37 /* 48-Bit, obsolete since ACS2 */
#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */
#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */
#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */
-/*
- * 0x3A->0x3B Reserved
- */
-#define WIN_WRITE_VERIFY 0x3C /* 28-Bit */
-/*
- * 0x3D->0x3F Reserved
- */
+/* WRITE STREAM DMA EXT 0x3A */
+/* WRITE STREAM EXT 0x3B */
+#define WIN_WRITE_VERIFY 0x3C /* 28-Bit, obsolete since ATA4 */
+/* WRITE DMA FUA EXT 0x3D */
+/* obsolete since ACS2 0x3E */
+/* WRITE LOG EXT 0x3F */
#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */
-#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - without retries */
+#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - w/o retries, obsolete since ATA5 */
#define WIN_VERIFY_EXT 0x42 /* 48-Bit */
-/*
- * 0x43->0x4F Reserved
- */
-#define WIN_FORMAT 0x50
-/*
- * 0x51->0x5F Reserved
- */
-#define WIN_INIT 0x60
-/*
- * 0x61->0x5F Reserved
- */
-#define WIN_SEEK 0x70 /* 0x70-0x7F Reserved */
+/* reserved 0x43..0x44 */
+/* WRITE UNCORRECTABLE EXT 0x45 */
+/* reserved 0x46 */
+/* READ LOG DMA EXT 0x47 */
+/* reserved 0x48..0x4F */
+/* obsolete since ATA4 0x50 */
+/* CONFIGURE STREAM 0x51 */
+/* reserved 0x52..0x56 */
+/* WRITE LOG DMA EXT 0x57 */
+/* reserved 0x58..0x5A */
+/* TRUSTED NON DATA 0x5B */
+/* TRUSTED RECEIVE 0x5C */
+/* TRUSTED RECEIVE DMA 0x5D */
+/* TRUSTED SEND 0x5E */
+/* TRUSTED SEND DMA 0x5F */
+/* READ FPDMA QUEUED 0x60 */
+/* WRITE FPDMA QUEUED 0x61 */
+/* reserved 0x62->0x6F */
+#define WIN_SEEK 0x70 /* obsolete since ATA7 */
+/* reserved 0x71-0x7F */
+/* vendor specific 0x80-0x86 */
#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */
+/* vendor specific 0x88-0x8F */
#define WIN_DIAGNOSE 0x90
-#define WIN_SPECIFY 0x91 /* set drive geometry translation */
+#define WIN_SPECIFY 0x91 /* set drive geometry translation, obsolete since ATA6 */
#define WIN_DOWNLOAD_MICROCODE 0x92
-#define WIN_STANDBYNOW2 0x94
-#define CFA_IDLEIMMEDIATE 0x95 /* force drive to become "ready" */
-#define WIN_STANDBY2 0x96
-#define WIN_SETIDLE2 0x97
-#define WIN_CHECKPOWERMODE2 0x98
-#define WIN_SLEEPNOW2 0x99
-/*
- * 0x9A VENDOR
- */
+/* DOWNLOAD MICROCODE DMA 0x93 */
+#define WIN_STANDBYNOW2 0x94 /* retired in ATA4 */
+#define WIN_IDLEIMMEDIATE2 0x95 /* force drive to become "ready", retired in ATA4 */
+#define WIN_STANDBY2 0x96 /* retired in ATA4 */
+#define WIN_SETIDLE2 0x97 /* retired in ATA4 */
+#define WIN_CHECKPOWERMODE2 0x98 /* retired in ATA4 */
+#define WIN_SLEEPNOW2 0x99 /* retired in ATA4 */
+/* vendor specific 0x9A */
+/* reserved 0x9B..0x9F */
#define WIN_PACKETCMD 0xA0 /* Send a packet command. */
#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */
-#define WIN_QUEUED_SERVICE 0xA2
+#define WIN_QUEUED_SERVICE 0xA2 /* obsolete since ACS2 */
+/* reserved 0xA3..0xAF */
#define WIN_SMART 0xB0 /* self-monitoring and reporting */
+/* Device Configuration Overlay 0xB1 */
+/* reserved 0xB2..0xB3 */
+/* Sanitize Device 0xB4 */
+/* reserved 0xB5 */
+/* NV Cache 0xB6 */
+/* reserved for CFA 0xB7..0xBB */
#define CFA_ACCESS_METADATA_STORAGE 0xB8
+/* reserved 0xBC..0xBF */
#define CFA_ERASE_SECTORS 0xC0 /* microdrives implement as NOP */
+/* vendor specific 0xC1..0xC3 */
#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/
#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */
#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */
-#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */
+#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers, obsolete since ACS2 */
#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */
-#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - without retries */
+#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - w/o retries, obsolete since ATA5 */
#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */
-#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - without retries */
-#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */
+#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - w/o retries, obsolete since ATA5 */
+#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers, obsolete since ACS2 */
#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */
-#define WIN_GETMEDIASTATUS 0xDA
-#define WIN_ACKMEDIACHANGE 0xDB /* ATA-1, ATA-2 vendor */
-#define WIN_POSTBOOT 0xDC
-#define WIN_PREBOOT 0xDD
-#define WIN_DOORLOCK 0xDE /* lock door on removable drives */
-#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives */
+/* WRITE MULTIPLE FUA EXT 0xCE */
+/* reserved 0xCF..0xDO */
+/* CHECK MEDIA CARD TYPE 0xD1 */
+/* reserved for media card pass through 0xD2..0xD4 */
+/* reserved 0xD5..0xD9 */
+#define WIN_GETMEDIASTATUS 0xDA /* obsolete since ATA8 */
+/* obsolete since ATA3, retired in ATA4 0xDB..0xDD */
+#define WIN_DOORLOCK 0xDE /* lock door on removable drives, obsolete since ATA8 */
+#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives, obsolete since ATA8 */
#define WIN_STANDBYNOW1 0xE0
#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */
#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */
#define WIN_SLEEPNOW1 0xE6
#define WIN_FLUSH_CACHE 0xE7
#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */
-#define WIN_WRITE_SAME 0xE9 /* read ata-2 to use */
- /* SET_FEATURES 0x22 or 0xDD */
+/* READ BUFFER DMA 0xE9 */
#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */
+/* WRITE BUFFER DMA 0xEB */
#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */
-#define WIN_MEDIAEJECT 0xED
-#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */
+#define WIN_MEDIAEJECT 0xED /* obsolete since ATA8 */
+/* obsolete since ATA4 0xEE */
#define WIN_SETFEATURES 0xEF /* set special drive features */
-#define EXABYTE_ENABLE_NEST 0xF0
-#define IBM_SENSE_CONDITION 0xF0 /* measure disk temperature */
+#define IBM_SENSE_CONDITION 0xF0 /* measure disk temperature, vendor specific */
#define WIN_SECURITY_SET_PASS 0xF1
#define WIN_SECURITY_UNLOCK 0xF2
#define WIN_SECURITY_ERASE_PREPARE 0xF3
#define WIN_SECURITY_ERASE_UNIT 0xF4
#define WIN_SECURITY_FREEZE_LOCK 0xF5
-#define CFA_WEAR_LEVEL 0xF5 /* microdrives implement as NOP */
+#define CFA_WEAR_LEVEL 0xF5 /* microdrives implement as NOP; not specified in T13! */
#define WIN_SECURITY_DISABLE 0xF6
+/* vendor specific 0xF7 */
#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */
#define WIN_SET_MAX 0xF9
-#define DISABLE_SEAGATE 0xFB
+/* vendor specific 0xFA..0xFF */
/* set to 1 set disable mult support */
#define MAX_MULT_SECTORS 16
#include <hw/pci.h>
#include <hw/isa.h>
#include "block.h"
-#include "block_int.h"
#include "sysemu.h"
#include "dma.h"
for (; i < 3; i++) {
di = drive_get_by_index(IF_IDE, i);
- if (di != NULL && di->bdrv != NULL && !di->bdrv->removable) {
- DeviceState *ds = bdrv_get_attached(di->bdrv);
+ if (di != NULL && !di->media_cd) {
+ DeviceState *ds = bdrv_get_attached_dev(di->bdrv);
if (ds) {
- bdrv_detach(di->bdrv, ds);
+ bdrv_detach_dev(di->bdrv, ds);
}
bdrv_close(di->bdrv);
pci_ide->bus[di->bus].ifs[di->unit].bs = NULL;
#include "boards.h"
#include "arm-misc.h"
#include "net.h"
+#include "exec-memory.h"
typedef struct {
SysBusDevice busdev;
uint32_t memsz;
- uint32_t flash_offset;
+ MemoryRegion flash;
+ bool flash_mapped;
uint32_t cm_osc;
uint32_t cm_ctrl;
uint32_t cm_lock;
static void integratorcm_do_remap(integratorcm_state *s, int flash)
{
if (flash) {
- cpu_register_physical_memory(0, 0x100000, IO_MEM_RAM);
+ if (s->flash_mapped) {
+ sysbus_del_memory(&s->busdev, &s->flash);
+ s->flash_mapped = false;
+ }
} else {
- cpu_register_physical_memory(0, 0x100000, s->flash_offset | IO_MEM_RAM);
+ if (!s->flash_mapped) {
+ sysbus_add_memory_overlap(&s->busdev, 0, &s->flash, 1);
+ s->flash_mapped = true;
+ }
}
//??? tlb_flush (cpu_single_env, 1);
}
}
memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
s->cm_init = 0x00000112;
- s->flash_offset = qemu_ram_alloc(NULL, "integrator.flash", 0x100000);
+ memory_region_init_ram(&s->flash, NULL, "integrator.flash", 0x100000);
+ s->flash_mapped = false;
iomemtype = cpu_register_io_memory(integratorcm_readfn,
integratorcm_writefn, s,
const char *initrd_filename, const char *cpu_model)
{
CPUState *env;
- ram_addr_t ram_offset;
+ MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *ram = g_new(MemoryRegion, 1);
+ MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
qemu_irq pic[32];
qemu_irq *cpu_pic;
DeviceState *dev;
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
- ram_offset = qemu_ram_alloc(NULL, "integrator.ram", ram_size);
+ memory_region_init_ram(ram, NULL, "integrator.ram", ram_size);
/* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash. */
/* ??? RAM should repeat to fill physical memory space. */
/* SDRAM at address zero*/
- cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
+ memory_region_add_subregion(address_space_mem, 0, ram);
/* And again at address 0x80000000 */
- cpu_register_physical_memory(0x80000000, ram_size, ram_offset | IO_MEM_RAM);
+ memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size);
+ memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
dev = qdev_create(NULL, "integrator_core");
qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
#include "loader.h"
#include "elf.h"
#include "trace.h"
+#include "exec-memory.h"
#include "grlib.h"
const char *cpu_model)
{
CPUState *env;
- ram_addr_t ram_offset, prom_offset;
+ MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *ram = g_new(MemoryRegion, 1);
+ MemoryRegion *prom = g_new(MemoryRegion, 1);
int ret;
char *filename;
qemu_irq *cpu_irqs = NULL;
exit(1);
}
- ram_offset = qemu_ram_alloc(NULL, "leon3.ram", ram_size);
- cpu_register_physical_memory(0x40000000, ram_size, ram_offset | IO_MEM_RAM);
+ memory_region_init_ram(ram, NULL, "leon3.ram", ram_size);
+ memory_region_add_subregion(address_space_mem, 0x40000000, ram);
/* Allocate BIOS */
prom_size = 8 * 1024 * 1024; /* 8Mb */
- prom_offset = qemu_ram_alloc(NULL, "Leon3.bios", prom_size);
- cpu_register_physical_memory(0x00000000, prom_size,
- prom_offset | IO_MEM_ROM);
+ memory_region_init_ram(prom, NULL, "Leon3.bios", prom_size);
+ memory_region_set_readonly(prom, true);
+ memory_region_add_subregion(address_space_mem, 0x00000000, prom);
/* Load boot prom */
if (bios_name == NULL) {
#include "elf.h"
#include "lm32_hwsetup.h"
#include "lm32.h"
+#include "exec-memory.h"
typedef struct {
CPUState *env;
{
CPUState *env;
DriveInfo *dinfo;
- ram_addr_t phys_ram;
- ram_addr_t phys_flash;
+ MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
qemu_irq *cpu_irq, irq[32];
ResetInfo *reset_info;
int i;
reset_info->flash_base = flash_base;
- phys_ram = qemu_ram_alloc(NULL, "lm32_evr.sdram", ram_size);
- cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM);
+ memory_region_init_ram(phys_ram, NULL, "lm32_evr.sdram", ram_size);
+ memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
- phys_flash = qemu_ram_alloc(NULL, "lm32_evr.flash", flash_size);
dinfo = drive_get(IF_PFLASH, 0, 0);
/* Spansion S29NS128P */
- pflash_cfi02_register(flash_base, phys_flash,
+ pflash_cfi02_register(flash_base, NULL, "lm32_evr.flash", flash_size,
dinfo ? dinfo->bdrv : NULL, flash_sector_size,
flash_size / flash_sector_size, 1, 2,
0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
{
CPUState *env;
DriveInfo *dinfo;
- ram_addr_t phys_ram;
- ram_addr_t phys_flash;
+ MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
qemu_irq *cpu_irq, irq[32];
HWSetup *hw;
ResetInfo *reset_info;
reset_info->flash_base = flash_base;
- phys_ram = qemu_ram_alloc(NULL, "lm32_uclinux.sdram", ram_size);
- cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM);
+ memory_region_init_ram(phys_ram, NULL, "lm32_uclinux.sdram", ram_size);
+ memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
- phys_flash = qemu_ram_alloc(NULL, "lm32_uclinux.flash", flash_size);
dinfo = drive_get(IF_PFLASH, 0, 0);
/* Spansion S29NS128P */
- pflash_cfi02_register(flash_base, phys_flash,
+ pflash_cfi02_register(flash_base, NULL, "lm32_uclinux.flash", flash_size,
dinfo ? dinfo->bdrv : NULL, flash_sector_size,
flash_size / flash_sector_size, 1, 2,
0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
#include "flash.h"
#include "blockdev.h"
#include "sysbus.h"
+#include "exec-memory.h"
/* Device addresses */
#define MST_FPGA_PHYS 0x08000000
.ram_size = 0x04000000,
};
-static void mainstone_common_init(ram_addr_t ram_size,
+static void mainstone_common_init(MemoryRegion *address_space_mem,
+ ram_addr_t ram_size,
const char *kernel_filename,
const char *kernel_cmdline, const char *initrd_filename,
const char *cpu_model, enum mainstone_model_e model, int arm_id)
DriveInfo *dinfo;
int i;
int be;
+ MemoryRegion *rom = g_new(MemoryRegion, 1);
if (!cpu_model)
cpu_model = "pxa270-c5";
/* Setup CPU & memory */
cpu = pxa270_init(mainstone_binfo.ram_size, cpu_model);
- cpu_register_physical_memory(0, MAINSTONE_ROM,
- qemu_ram_alloc(NULL, "mainstone.rom",
- MAINSTONE_ROM) | IO_MEM_ROM);
+ memory_region_init_ram(rom, NULL, "mainstone.rom", MAINSTONE_ROM);
+ memory_region_set_readonly(rom, true);
+ memory_region_add_subregion(address_space_mem, 0, rom);
#ifdef TARGET_WORDS_BIGENDIAN
be = 1;
exit(1);
}
- if (!pflash_cfi01_register(mainstone_flash_base[i],
- qemu_ram_alloc(NULL, i ? "mainstone.flash1" :
- "mainstone.flash0",
- MAINSTONE_FLASH),
+ if (!pflash_cfi01_register(mainstone_flash_base[i], NULL,
+ i ? "mainstone.flash1" : "mainstone.flash0",
+ MAINSTONE_FLASH,
dinfo->bdrv, sector_len,
MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0,
be)) {
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
{
- mainstone_common_init(ram_size, kernel_filename,
+ mainstone_common_init(get_system_memory(), ram_size, kernel_filename,
kernel_cmdline, initrd_filename, cpu_model, mainstone, 0x196);
}
#include "boards.h"
#include "loader.h"
#include "elf.h"
+#include "exec-memory.h"
#define SYS_FREQ 66000000
#define PCSR_PRE_MASK 0x0f00
typedef struct {
+ MemoryRegion iomem;
qemu_irq irq;
ptimer_state *timer;
uint16_t pcsr;
}
static void m5208_timer_write(void *opaque, target_phys_addr_t offset,
- uint32_t value)
+ uint64_t value, unsigned size)
{
m5208_timer_state *s = (m5208_timer_state *)opaque;
int prescale;
m5208_timer_update(s);
}
-static uint32_t m5208_timer_read(void *opaque, target_phys_addr_t addr)
+static uint64_t m5208_timer_read(void *opaque, target_phys_addr_t addr,
+ unsigned size)
{
m5208_timer_state *s = (m5208_timer_state *)opaque;
switch (addr) {
}
}
-static CPUReadMemoryFunc * const m5208_timer_readfn[] = {
- m5208_timer_read,
- m5208_timer_read,
- m5208_timer_read
+static const MemoryRegionOps m5208_timer_ops = {
+ .read = m5208_timer_read,
+ .write = m5208_timer_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
-static CPUWriteMemoryFunc * const m5208_timer_writefn[] = {
- m5208_timer_write,
- m5208_timer_write,
- m5208_timer_write
-};
-
-static uint32_t m5208_sys_read(void *opaque, target_phys_addr_t addr)
+static uint64_t m5208_sys_read(void *opaque, target_phys_addr_t addr,
+ unsigned size)
{
switch (addr) {
case 0x110: /* SDCS0 */
}
static void m5208_sys_write(void *opaque, target_phys_addr_t addr,
- uint32_t value)
+ uint64_t value, unsigned size)
{
hw_error("m5208_sys_write: Bad offset 0x%x\n", (int)addr);
}
-static CPUReadMemoryFunc * const m5208_sys_readfn[] = {
- m5208_sys_read,
- m5208_sys_read,
- m5208_sys_read
-};
-
-static CPUWriteMemoryFunc * const m5208_sys_writefn[] = {
- m5208_sys_write,
- m5208_sys_write,
- m5208_sys_write
+static const MemoryRegionOps m5208_sys_ops = {
+ .read = m5208_sys_read,
+ .write = m5208_sys_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
-static void mcf5208_sys_init(qemu_irq *pic)
+static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
{
- int iomemtype;
+ MemoryRegion *iomem = g_new(MemoryRegion, 1);
m5208_timer_state *s;
QEMUBH *bh;
int i;
- iomemtype = cpu_register_io_memory(m5208_sys_readfn,
- m5208_sys_writefn, NULL,
- DEVICE_NATIVE_ENDIAN);
/* SDRAMC. */
- cpu_register_physical_memory(0xfc0a8000, 0x00004000, iomemtype);
+ memory_region_init_io(iomem, &m5208_sys_ops, NULL, "m5208-sys", 0x00004000);
+ memory_region_add_subregion(address_space, 0xfc0a8000, iomem);
/* Timers. */
for (i = 0; i < 2; i++) {
s = (m5208_timer_state *)g_malloc0(sizeof(m5208_timer_state));
bh = qemu_bh_new(m5208_timer_trigger, s);
s->timer = ptimer_init(bh);
- iomemtype = cpu_register_io_memory(m5208_timer_readfn,
- m5208_timer_writefn, s,
- DEVICE_NATIVE_ENDIAN);
- cpu_register_physical_memory(0xfc080000 + 0x4000 * i, 0x00004000,
- iomemtype);
+ memory_region_init_io(&s->iomem, &m5208_timer_ops, s,
+ "m5208-timer", 0x00004000);
+ memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i,
+ &s->iomem);
s->irq = pic[4 + i];
}
}
uint64_t elf_entry;
target_phys_addr_t entry;
qemu_irq *pic;
+ MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *ram = g_new(MemoryRegion, 1);
+ MemoryRegion *sram = g_new(MemoryRegion, 1);
if (!cpu_model)
cpu_model = "m5208";
/* TODO: Configure BARs. */
/* DRAM at 0x40000000 */
- cpu_register_physical_memory(0x40000000, ram_size,
- qemu_ram_alloc(NULL, "mcf5208.ram", ram_size) | IO_MEM_RAM);
+ memory_region_init_ram(ram, NULL, "mcf5208.ram", ram_size);
+ memory_region_add_subregion(address_space_mem, 0x40000000, ram);
/* Internal SRAM. */
- cpu_register_physical_memory(0x80000000, 16384,
- qemu_ram_alloc(NULL, "mcf5208.sram", 16384) | IO_MEM_RAM);
+ memory_region_init_ram(sram, NULL, "mcf5208.sram", 16384);
+ memory_region_add_subregion(address_space_mem, 0x80000000, sram);
/* Internal peripherals. */
pic = mcf_intc_init(0xfc048000, env);
mcf_uart_mm_init(0xfc064000, pic[27], serial_hds[1]);
mcf_uart_mm_init(0xfc068000, pic[28], serial_hds[2]);
- mcf5208_sys_init(pic);
+ mcf5208_sys_init(address_space_mem, pic);
if (nb_nics > 1) {
fprintf(stderr, "Too many NICs\n");
NICConf conf;
char *phy_model;
target_phys_addr_t buffers_base;
+ MemoryRegion buffers;
+ MemoryRegion regs_region;
qemu_irq rx_irq;
qemu_irq tx_irq;
return size;
}
-static uint32_t
-minimac2_read(void *opaque, target_phys_addr_t addr)
+static uint64_t
+minimac2_read(void *opaque, target_phys_addr_t addr, unsigned size)
{
MilkymistMinimac2State *s = opaque;
uint32_t r = 0;
}
static void
-minimac2_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+minimac2_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+ unsigned size)
{
MilkymistMinimac2State *s = opaque;
}
}
-static CPUReadMemoryFunc * const minimac2_read_fn[] = {
- NULL,
- NULL,
- &minimac2_read,
-};
-
-static CPUWriteMemoryFunc * const minimac2_write_fn[] = {
- NULL,
- NULL,
- &minimac2_write,
+static const MemoryRegionOps minimac2_ops = {
+ .read = minimac2_read,
+ .write = minimac2_write,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
static int minimac2_can_rx(VLANClientState *nc)
static int milkymist_minimac2_init(SysBusDevice *dev)
{
MilkymistMinimac2State *s = FROM_SYSBUS(typeof(*s), dev);
- int regs;
- ram_addr_t buffers;
size_t buffers_size = TARGET_PAGE_ALIGN(3 * MINIMAC2_BUFFER_SIZE);
sysbus_init_irq(dev, &s->rx_irq);
sysbus_init_irq(dev, &s->tx_irq);
- regs = cpu_register_io_memory(minimac2_read_fn, minimac2_write_fn, s,
- DEVICE_NATIVE_ENDIAN);
- sysbus_init_mmio(dev, R_MAX * 4, regs);
+ memory_region_init_io(&s->regs_region, &minimac2_ops, s,
+ "minimac2-mmio", R_MAX * 4);
+ sysbus_init_mmio_region(dev, &s->regs_region);
/* register buffers memory */
- buffers = qemu_ram_alloc(NULL, "milkymist_minimac2.buffers", buffers_size);
- s->rx0_buf = qemu_get_ram_ptr(buffers);
+ memory_region_init_ram(&s->buffers, NULL, "milkymist_minimac2.buffers",
+ buffers_size);
+ s->rx0_buf = memory_region_get_ram_ptr(&s->buffers);
s->rx1_buf = s->rx0_buf + MINIMAC2_BUFFER_SIZE;
s->tx_buf = s->rx1_buf + MINIMAC2_BUFFER_SIZE;
- cpu_register_physical_memory(s->buffers_base, buffers_size,
- buffers | IO_MEM_RAM);
+ sysbus_add_memory(dev, s->buffers_base, &s->buffers);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_milkymist_minimac2_info, &s->conf,
HIDState hid_kbd;
HIDState hid_mouse;
+ MemoryRegion regs_region;
+ MemoryRegion pmem;
+ MemoryRegion dmem;
qemu_irq irq;
/* device properties */
};
typedef struct MilkymistSoftUsbState MilkymistSoftUsbState;
-static uint32_t softusb_read(void *opaque, target_phys_addr_t addr)
+static uint64_t softusb_read(void *opaque, target_phys_addr_t addr,
+ unsigned size)
{
MilkymistSoftUsbState *s = opaque;
uint32_t r = 0;
}
static void
-softusb_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+softusb_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+ unsigned size)
{
MilkymistSoftUsbState *s = opaque;
}
}
-static CPUReadMemoryFunc * const softusb_read_fn[] = {
- NULL,
- NULL,
- &softusb_read,
-};
-
-static CPUWriteMemoryFunc * const softusb_write_fn[] = {
- NULL,
- NULL,
- &softusb_write,
+static const MemoryRegionOps softusb_mmio_ops = {
+ .read = softusb_read,
+ .write = softusb_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
};
static inline void softusb_read_dmem(MilkymistSoftUsbState *s,
static int milkymist_softusb_init(SysBusDevice *dev)
{
MilkymistSoftUsbState *s = FROM_SYSBUS(typeof(*s), dev);
- int softusb_regs;
- ram_addr_t pmem_ram;
- ram_addr_t dmem_ram;
sysbus_init_irq(dev, &s->irq);
- softusb_regs = cpu_register_io_memory(softusb_read_fn, softusb_write_fn, s,
- DEVICE_NATIVE_ENDIAN);
- sysbus_init_mmio(dev, R_MAX * 4, softusb_regs);
+ memory_region_init_io(&s->regs_region, &softusb_mmio_ops, s,
+ "milkymist-softusb", R_MAX * 4);
+ sysbus_init_mmio_region(dev, &s->regs_region);
/* register pmem and dmem */
- pmem_ram = qemu_ram_alloc(NULL, "milkymist_softusb.pmem", s->pmem_size);
- cpu_register_physical_memory(s->pmem_base, s->pmem_size,
- pmem_ram | IO_MEM_RAM);
- dmem_ram = qemu_ram_alloc(NULL, "milkymist_softusb.dmem", s->dmem_size);
- cpu_register_physical_memory(s->dmem_base, s->dmem_size,
- dmem_ram | IO_MEM_RAM);
+ memory_region_init_ram(&s->pmem, NULL, "milkymist_softusb.pmem",
+ s->pmem_size);
+ sysbus_add_memory(dev, s->pmem_base, &s->pmem);
+ memory_region_init_ram(&s->dmem, NULL, "milkymist_softusb.dmem",
+ s->dmem_size);
+ sysbus_add_memory(dev, s->dmem_base, &s->dmem);
hid_init(&s->hid_kbd, HID_KEYBOARD, softusb_kbd_hid_datain);
hid_init(&s->hid_mouse, HID_MOUSE, softusb_mouse_hid_datain);
#include "blockdev.h"
#include "milkymist-hw.h"
#include "lm32.h"
+#include "exec-memory.h"
#define BIOS_FILENAME "mmone-bios.bin"
#define BIOS_OFFSET 0x00860000
CPUState *env;
int kernel_size;
DriveInfo *dinfo;
- ram_addr_t phys_sdram;
- ram_addr_t phys_flash;
+ MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *phys_sdram = g_new(MemoryRegion, 1);
qemu_irq irq[32], *cpu_irq;
int i;
char *bios_filename;
cpu_lm32_set_phys_msb_ignore(env, 1);
- phys_sdram = qemu_ram_alloc(NULL, "milkymist.sdram", sdram_size);
- cpu_register_physical_memory(sdram_base, sdram_size,
- phys_sdram | IO_MEM_RAM);
+ memory_region_init_ram(phys_sdram, NULL, "milkymist.sdram", sdram_size);
+ memory_region_add_subregion(address_space_mem, sdram_base, phys_sdram);
- phys_flash = qemu_ram_alloc(NULL, "milkymist.flash", flash_size);
dinfo = drive_get(IF_PFLASH, 0, 0);
/* Numonyx JS28F256J3F105 */
- pflash_cfi01_register(flash_base, phys_flash,
+ pflash_cfi01_register(flash_base, NULL, "milkymist.flash", flash_size,
dinfo ? dinfo->bdrv : NULL, flash_sector_size,
flash_size / flash_sector_size, 2,
0x00, 0x89, 0x00, 0x1d, 1);
#include "vt82c686.h"
#include "mc146818rtc.h"
#include "blockdev.h"
+#include "exec-memory.h"
#define DEBUG_FULONG2E_INIT
const char *initrd_filename, const char *cpu_model)
{
char *filename;
- unsigned long ram_offset, bios_offset;
+ MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *ram = g_new(MemoryRegion, 1);
+ MemoryRegion *bios = g_new(MemoryRegion, 1);
long bios_size;
int64_t kernel_entry;
qemu_irq *i8259;
bios_size = 1024 * 1024;
/* allocate RAM */
- ram_offset = qemu_ram_alloc(NULL, "fulong2e.ram", ram_size);
- bios_offset = qemu_ram_alloc(NULL, "fulong2e.bios", bios_size);
+ memory_region_init_ram(ram, NULL, "fulong2e.ram", ram_size);
+ memory_region_init_ram(bios, NULL, "fulong2e.bios", bios_size);
+ memory_region_set_readonly(bios, true);
- cpu_register_physical_memory(0, ram_size, ram_offset);
- cpu_register_physical_memory(0x1fc00000LL,
- bios_size, bios_offset | IO_MEM_ROM);
+ memory_region_add_subregion(address_space_mem, 0, ram);
+ memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
/* We do not support flash operation, just loading pmon.bin as raw BIOS.
* Please use -L to set the BIOS path and -bios to set bios name. */
loaderparams.kernel_cmdline = kernel_cmdline;
loaderparams.initrd_filename = initrd_filename;
kernel_entry = load_kernel (env);
- write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry);
+ write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
} else {
if (bios_name == NULL) {
bios_name = FULONG_BIOSNAME;
#include "elf.h"
#include "mc146818rtc.h"
#include "blockdev.h"
+#include "exec-memory.h"
//#define DEBUG_BOARD_INIT
const char *initrd_filename, const char *cpu_model)
{
char *filename;
+ pflash_t *fl;
ram_addr_t ram_offset;
- ram_addr_t bios_offset;
+ MemoryRegion *system_memory = get_system_memory();
+ MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
target_long bios_size;
int64_t kernel_entry;
PCIBus *pci_bus;
exit(1);
}
ram_offset = qemu_ram_alloc(NULL, "mips_malta.ram", ram_size);
- bios_offset = qemu_ram_alloc(NULL, "mips_malta.bios", BIOS_SIZE);
-
cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
- /* Map the bios at two physical locations, as on the real board. */
- cpu_register_physical_memory(0x1e000000LL,
- BIOS_SIZE, bios_offset | IO_MEM_ROM);
- cpu_register_physical_memory(0x1fc00000LL,
- BIOS_SIZE, bios_offset | IO_MEM_ROM);
-
#ifdef TARGET_WORDS_BIGENDIAN
be = 1;
#else
/* Load firmware in flash / BIOS unless we boot directly into a kernel. */
if (kernel_filename) {
/* Write a small bootloader to the flash location. */
+ bios = g_new(MemoryRegion, 1);
+ memory_region_init_ram(bios, NULL, "mips_malta.bios", BIOS_SIZE);
+ memory_region_set_readonly(bios, true);
+ memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
+ /* Map the bios at two physical locations, as on the real board. */
+ memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
+ memory_region_add_subregion(system_memory, 0x1fc00000LL, bios_alias);
loaderparams.ram_size = ram_size;
loaderparams.kernel_filename = kernel_filename;
loaderparams.kernel_cmdline = kernel_cmdline;
loaderparams.initrd_filename = initrd_filename;
kernel_entry = load_kernel();
- write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry);
+ write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
} else {
dinfo = drive_get(IF_PFLASH, 0, fl_idx);
if (dinfo) {
fl_sectors = bios_size >> 16;
#ifdef DEBUG_BOARD_INIT
printf("Register parallel flash %d size " TARGET_FMT_lx " at "
- "offset %08lx addr %08llx '%s' %x\n",
- fl_idx, bios_size, bios_offset, 0x1e000000LL,
+ "addr %08llx '%s' %x\n",
+ fl_idx, bios_size, 0x1e000000LL,
bdrv_get_device_name(dinfo->bdrv), fl_sectors);
#endif
- pflash_cfi01_register(0x1e000000LL, bios_offset,
- dinfo->bdrv, 65536, fl_sectors,
- 4, 0x0000, 0x0000, 0x0000, 0x0000, be);
- fl_idx++;
+ fl = pflash_cfi01_register(0x1e000000LL,
+ NULL, "mips_malta.bios", BIOS_SIZE,
+ dinfo->bdrv, 65536, fl_sectors,
+ 4, 0x0000, 0x0000, 0x0000, 0x0000, be);
+ bios = pflash_cfi01_get_memory(fl);
+ /* Map the bios at two physical locations, as on the real board. */
+ memory_region_init_alias(bios_alias, "bios.1fc",
+ bios, 0, BIOS_SIZE);
+ memory_region_add_subregion(system_memory, 0x1fc00000LL,
+ bios_alias);
+ fl_idx++;
} else {
+ bios = g_new(MemoryRegion, 1);
+ memory_region_init_ram(bios, NULL, "mips_malta.bios", BIOS_SIZE);
+ memory_region_set_readonly(bios, true);
+ memory_region_init_alias(bios_alias, "bios.1fc",
+ bios, 0, BIOS_SIZE);
+ /* Map the bios at two physical locations, as on the real board. */
+ memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
+ memory_region_add_subregion(system_memory, 0x1fc00000LL,
+ bios_alias);
/* Load a BIOS image. */
if (bios_name == NULL)
bios_name = BIOS_FILENAME;
a neat trick which allows bi-endian firmware. */
#ifndef TARGET_WORDS_BIGENDIAN
{
- uint32_t *addr = qemu_get_ram_ptr(bios_offset);;
+ uint32_t *addr = memory_region_get_ram_ptr(bios);
uint32_t *end = addr + bios_size;
while (addr < end) {
bswap32s(addr);
/* Board ID = 0x420 (Malta Board with CoreLV)
XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
map to the board ID. */
- stl_p(qemu_get_ram_ptr(bios_offset) + 0x10, 0x00000420);
+ stl_p(memory_region_get_ram_ptr(bios) + 0x10, 0x00000420);
/* Init internal devices */
cpu_mips_irq_init_cpu(env);
#include "elf.h"
#include "mc146818rtc.h"
#include "blockdev.h"
+#include "exec-memory.h"
#define MAX_IDE_BUS 2
{
char *filename;
ram_addr_t ram_offset;
- ram_addr_t bios_offset;
+ MemoryRegion *bios;
int bios_size;
CPUState *env;
ResetData *reset_info;
be = 0;
#endif
if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
- bios_offset = qemu_ram_alloc(NULL, "mips_r4k.bios", BIOS_SIZE);
- cpu_register_physical_memory(0x1fc00000, BIOS_SIZE,
- bios_offset | IO_MEM_ROM);
+ bios = g_new(MemoryRegion, 1);
+ memory_region_init_ram(bios, NULL, "mips_r4k.bios", BIOS_SIZE);
+ memory_region_set_readonly(bios, true);
+ memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios);
load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
} else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
uint32_t mips_rom = 0x00400000;
- bios_offset = qemu_ram_alloc(NULL, "mips_r4k.bios", mips_rom);
- if (!pflash_cfi01_register(0x1fc00000, bios_offset,
+ if (!pflash_cfi01_register(0x1fc00000, NULL, "mips_r4k.bios", mips_rom,
dinfo->bdrv, sector_len,
mips_rom / sector_len,
4, 0, 0, 0, 0, be)) {
* image is smaller than 32 MB.
*/
#ifdef TARGET_WORDS_BIGENDIAN
- pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(NULL,
- "musicpal.flash", flash_size),
+ pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, NULL,
+ "musicpal.flash", flash_size,
dinfo->bdrv, 0x10000,
(flash_size + 0xffff) >> 16,
MP_FLASH_SIZE_MAX / flash_size,
2, 0x00BF, 0x236D, 0x0000, 0x0000,
0x5555, 0x2AAA, 1);
#else
- pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(NULL,
- "musicpal.flash", flash_size),
+ pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, NULL,
+ "musicpal.flash", flash_size,
dinfo->bdrv, 0x10000,
(flash_size + 0xffff) >> 16,
MP_FLASH_SIZE_MAX / flash_size,
#endif
if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
- if (!pflash_cfi01_register(OMAP_CS0_BASE, qemu_ram_alloc(NULL,
- "omap_sx1.flash0-1", flash_size),
+ if (!pflash_cfi01_register(OMAP_CS0_BASE, NULL,
+ "omap_sx1.flash0-1", flash_size,
dinfo->bdrv, sector_size,
flash_size / sector_size,
4, 0, 0, 0, 0, be)) {
cpu_register_physical_memory(OMAP_CS1_BASE + flash1_size,
OMAP_CS1_SIZE - flash1_size, io);
- if (!pflash_cfi01_register(OMAP_CS1_BASE, qemu_ram_alloc(NULL,
- "omap_sx1.flash1-1", flash1_size),
+ if (!pflash_cfi01_register(OMAP_CS1_BASE, NULL,
+ "omap_sx1.flash1-1", flash1_size,
dinfo->bdrv, sector_size,
flash1_size / sector_size,
4, 0, 0, 0, 0, be)) {
return val;
}
-static void pci_host_config_write(ReadWriteHandler *handler,
- pcibus_t addr, uint32_t val, int len)
+static void pci_host_config_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned len)
{
- PCIHostState *s = container_of(handler, PCIHostState, conf_handler);
+ PCIHostState *s = opaque;
- PCI_DPRINTF("%s addr %" FMT_PCIBUS " %d val %"PRIx32"\n",
+ PCI_DPRINTF("%s addr " TARGET_FMT_plx " len %d val %"PRIx64"\n",
__func__, addr, len, val);
s->config_reg = val;
}
-static uint32_t pci_host_config_read(ReadWriteHandler *handler,
- pcibus_t addr, int len)
+static uint64_t pci_host_config_read(void *opaque, target_phys_addr_t addr,
+ unsigned len)
{
- PCIHostState *s = container_of(handler, PCIHostState, conf_handler);
+ PCIHostState *s = opaque;
uint32_t val = s->config_reg;
- PCI_DPRINTF("%s addr %" FMT_PCIBUS " len %d val %"PRIx32"\n",
+ PCI_DPRINTF("%s addr " TARGET_FMT_plx " len %d val %"PRIx32"\n",
__func__, addr, len, val);
return val;
}
-static void pci_host_data_write(ReadWriteHandler *handler,
- pcibus_t addr, uint32_t val, int len)
+static void pci_host_data_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned len)
{
- PCIHostState *s = container_of(handler, PCIHostState, data_handler);
- PCI_DPRINTF("write addr %" FMT_PCIBUS " len %d val %x\n",
- addr, len, val);
+ PCIHostState *s = opaque;
+ PCI_DPRINTF("write addr " TARGET_FMT_plx " len %d val %x\n",
+ addr, len, (unsigned)val);
if (s->config_reg & (1u << 31))
pci_data_write(s->bus, s->config_reg | (addr & 3), val, len);
}
-static uint32_t pci_host_data_read(ReadWriteHandler *handler,
- pcibus_t addr, int len)
+static uint64_t pci_host_data_read(void *opaque,
+ target_phys_addr_t addr, unsigned len)
{
- PCIHostState *s = container_of(handler, PCIHostState, data_handler);
+ PCIHostState *s = opaque;
uint32_t val;
if (!(s->config_reg & (1 << 31)))
return 0xffffffff;
val = pci_data_read(s->bus, s->config_reg | (addr & 3), len);
- PCI_DPRINTF("read addr %" FMT_PCIBUS " len %d val %x\n",
+ PCI_DPRINTF("read addr " TARGET_FMT_plx " len %d val %x\n",
addr, len, val);
return val;
}
-static void pci_host_init(PCIHostState *s)
-{
- s->conf_handler.write = pci_host_config_write;
- s->conf_handler.read = pci_host_config_read;
- s->data_handler.write = pci_host_data_write;
- s->data_handler.read = pci_host_data_read;
-}
+const MemoryRegionOps pci_host_conf_le_ops = {
+ .read = pci_host_config_read,
+ .write = pci_host_config_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
-int pci_host_conf_register_mmio(PCIHostState *s, int endian)
-{
- pci_host_init(s);
- return cpu_register_io_memory_simple(&s->conf_handler, endian);
-}
+const MemoryRegionOps pci_host_conf_be_ops = {
+ .read = pci_host_config_read,
+ .write = pci_host_config_write,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
-void pci_host_conf_register_ioport(pio_addr_t ioport, PCIHostState *s)
-{
- pci_host_init(s);
- register_ioport_simple(&s->conf_handler, ioport, 4, 4);
- sysbus_init_ioports(&s->busdev, ioport, 4);
-}
+const MemoryRegionOps pci_host_data_le_ops = {
+ .read = pci_host_data_read,
+ .write = pci_host_data_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+const MemoryRegionOps pci_host_data_be_ops = {
+ .read = pci_host_data_read,
+ .write = pci_host_data_write,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
-int pci_host_data_register_mmio(PCIHostState *s, int endian)
-{
- pci_host_init(s);
- return cpu_register_io_memory_simple(&s->data_handler, endian);
-}
-void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s)
-{
- pci_host_init(s);
- register_ioport_simple(&s->data_handler, ioport, 4, 1);
- register_ioport_simple(&s->data_handler, ioport, 4, 2);
- register_ioport_simple(&s->data_handler, ioport, 4, 4);
- sysbus_init_ioports(&s->busdev, ioport, 4);
-}
#define PCI_HOST_H
#include "sysbus.h"
-#include "rwhandler.h"
struct PCIHostState {
SysBusDevice busdev;
- ReadWriteHandler conf_handler;
- ReadWriteHandler data_handler;
+ MemoryRegion conf_mem;
+ MemoryRegion data_mem;
MemoryRegion *address_space;
uint32_t config_reg;
PCIBus *bus;
void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len);
uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len);
-/* for mmio */
-int pci_host_conf_register_mmio(PCIHostState *s, int endian);
-int pci_host_data_register_mmio(PCIHostState *s, int endian);
-
-/* for ioio */
-void pci_host_conf_register_ioport(pio_addr_t ioport, PCIHostState *s);
-void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s);
+extern const MemoryRegionOps pci_host_conf_le_ops;
+extern const MemoryRegionOps pci_host_conf_be_ops;
+extern const MemoryRegionOps pci_host_data_le_ops;
+extern const MemoryRegionOps pci_host_data_be_ops;
#endif /* PCI_HOST_H */
target_phys_addr_t ddr_base = MEMORY_BASEADDR;
ram_addr_t phys_lmb_bram;
ram_addr_t phys_ram;
- ram_addr_t phys_flash;
qemu_irq irq[32], *cpu_irq;
/* init CPUs */
phys_ram = qemu_ram_alloc(NULL, "petalogix_ml605.ram", ram_size);
cpu_register_physical_memory(ddr_base, ram_size, phys_ram | IO_MEM_RAM);
- phys_flash = qemu_ram_alloc(NULL, "petalogix_ml605.flash", FLASH_SIZE);
dinfo = drive_get(IF_PFLASH, 0, 0);
/* 5th parameter 2 means bank-width
* 10th paremeter 0 means little-endian */
- pflash_cfi01_register(FLASH_BASEADDR, phys_flash,
+ pflash_cfi01_register(FLASH_BASEADDR,
+ NULL, "petalogix_ml605.flash", FLASH_SIZE,
dinfo ? dinfo->bdrv : NULL, (64 * 1024),
FLASH_SIZE >> 16,
2, 0x89, 0x18, 0x0000, 0x0, 0);
target_phys_addr_t ddr_base = 0x90000000;
ram_addr_t phys_lmb_bram;
ram_addr_t phys_ram;
- ram_addr_t phys_flash;
qemu_irq irq[32], *cpu_irq;
/* init CPUs */
phys_ram = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.ram", ram_size);
cpu_register_physical_memory(ddr_base, ram_size, phys_ram | IO_MEM_RAM);
- phys_flash = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE);
dinfo = drive_get(IF_PFLASH, 0, 0);
- pflash_cfi01_register(0xa0000000, phys_flash,
+ pflash_cfi01_register(0xa0000000,
+ NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE,
dinfo ? dinfo->bdrv : NULL, (64 * 1024),
FLASH_SIZE >> 16,
1, 0x89, 0x18, 0x0000, 0x0, 1);
#include "flash.h"
#include "block.h"
#include "qemu-timer.h"
+#include "exec-memory.h"
#define PFLASH_BUG(fmt, ...) \
do { \
target_phys_addr_t counter;
unsigned int writeblock_size;
QEMUTimer *timer;
- ram_addr_t off;
- int fl_mem;
+ MemoryRegion mem;
void *storage;
};
if (pfl->bypass) {
pfl->wcycle = 2;
} else {
- cpu_register_physical_memory(pfl->base, pfl->total_len,
- pfl->off | IO_MEM_ROMD | pfl->fl_mem);
+ memory_region_rom_device_set_readable(&pfl->mem, true);
pfl->wcycle = 0;
}
pfl->cmd = 0;
if (!pfl->wcycle) {
/* Set the device in I/O access mode */
- cpu_register_physical_memory(pfl->base, pfl->total_len, pfl->fl_mem);
+ memory_region_rom_device_set_readable(&pfl->mem, false);
}
switch (pfl->wcycle) {
__func__, offset, pfl->wcycle, pfl->cmd, value);
reset_flash:
- cpu_register_physical_memory(pfl->base, pfl->total_len,
- pfl->off | IO_MEM_ROMD | pfl->fl_mem);
+ memory_region_rom_device_set_readable(&pfl->mem, true);
pfl->bypass = 0;
pfl->wcycle = 0;
pflash_write(pfl, addr, value, 4, 0);
}
-static CPUWriteMemoryFunc * const pflash_write_ops_be[] = {
- &pflash_writeb_be,
- &pflash_writew_be,
- &pflash_writel_be,
+static const MemoryRegionOps pflash_cfi01_ops_be = {
+ .old_mmio = {
+ .read = { pflash_readb_be, pflash_readw_be, pflash_readl_be, },
+ .write = { pflash_writeb_be, pflash_writew_be, pflash_writel_be, },
+ },
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
-static CPUReadMemoryFunc * const pflash_read_ops_be[] = {
- &pflash_readb_be,
- &pflash_readw_be,
- &pflash_readl_be,
-};
-
-static CPUWriteMemoryFunc * const pflash_write_ops_le[] = {
- &pflash_writeb_le,
- &pflash_writew_le,
- &pflash_writel_le,
-};
-
-static CPUReadMemoryFunc * const pflash_read_ops_le[] = {
- &pflash_readb_le,
- &pflash_readw_le,
- &pflash_readl_le,
+static const MemoryRegionOps pflash_cfi01_ops_le = {
+ .old_mmio = {
+ .read = { pflash_readb_le, pflash_readw_le, pflash_readl_le, },
+ .write = { pflash_writeb_le, pflash_writew_le, pflash_writel_le, },
+ },
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
/* Count trailing zeroes of a 32 bits quantity */
return ret;
}
-pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
+pflash_t *pflash_cfi01_register(target_phys_addr_t base,
+ DeviceState *qdev, const char *name,
+ target_phys_addr_t size,
BlockDriverState *bs, uint32_t sector_len,
int nb_blocs, int width,
uint16_t id0, uint16_t id1,
- uint16_t id2, uint16_t id3,
- int be)
+ uint16_t id2, uint16_t id3, int be)
{
pflash_t *pfl;
target_phys_addr_t total_len;
pfl = g_malloc0(sizeof(pflash_t));
- /* FIXME: Allocate ram ourselves. */
- pfl->storage = qemu_get_ram_ptr(off);
- if (be) {
- pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_be,
- pflash_write_ops_be, pfl,
- DEVICE_NATIVE_ENDIAN);
- } else {
- pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_le,
- pflash_write_ops_le, pfl,
- DEVICE_NATIVE_ENDIAN);
- }
- pfl->off = off;
- cpu_register_physical_memory(base, total_len,
- off | pfl->fl_mem | IO_MEM_ROMD);
+ memory_region_init_rom_device(
+ &pfl->mem, be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl,
+ qdev, name, size);
+ pfl->storage = memory_region_get_ram_ptr(&pfl->mem);
+ memory_region_add_subregion(get_system_memory(), base, &pfl->mem);
pfl->bs = bs;
if (pfl->bs) {
/* read the initial flash content */
ret = bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9);
if (ret < 0) {
- cpu_unregister_io_memory(pfl->fl_mem);
+ memory_region_del_subregion(get_system_memory(), &pfl->mem);
+ memory_region_destroy(&pfl->mem);
g_free(pfl);
return NULL;
}
+ bdrv_attach_dev_nofail(pfl->bs, pfl);
}
#if 0 /* XXX: there should be a bit to set up read-only,
* the same way the hardware does (with WP pin).
return pfl;
}
+
+MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl)
+{
+ return &fl->mem;
+}
#include "flash.h"
#include "qemu-timer.h"
#include "block.h"
+#include "exec-memory.h"
//#define PFLASH_DEBUG
#ifdef PFLASH_DEBUG
uint8_t cfi_len;
uint8_t cfi_table[0x52];
QEMUTimer *timer;
- ram_addr_t off;
- int fl_mem;
+ /* The device replicates the flash memory across its memory space. Emulate
+ * that by having a container (.mem) filled with an array of aliases
+ * (.mem_mappings) pointing to the flash memory (.orig_mem).
+ */
+ MemoryRegion mem;
+ MemoryRegion *mem_mappings; /* array; one per mapping */
+ MemoryRegion orig_mem;
int rom_mode;
int read_counter; /* used for lazy switch-back to rom mode */
void *storage;
};
-static void pflash_register_memory(pflash_t *pfl, int rom_mode)
+/*
+ * Set up replicated mappings of the same region.
+ */
+static void pflash_setup_mappings(pflash_t *pfl)
{
- unsigned long phys_offset = pfl->fl_mem;
- int i;
-
- if (rom_mode)
- phys_offset |= pfl->off | IO_MEM_ROMD;
- pfl->rom_mode = rom_mode;
+ unsigned i;
+ target_phys_addr_t size = memory_region_size(&pfl->orig_mem);
+
+ memory_region_init(&pfl->mem, "pflash", pfl->mappings * size);
+ pfl->mem_mappings = g_new(MemoryRegion, pfl->mappings);
+ for (i = 0; i < pfl->mappings; ++i) {
+ memory_region_init_alias(&pfl->mem_mappings[i], "pflash-alias",
+ &pfl->orig_mem, 0, size);
+ memory_region_add_subregion(&pfl->mem, i * size, &pfl->mem_mappings[i]);
+ }
+}
- for (i = 0; i < pfl->mappings; i++)
- cpu_register_physical_memory(pfl->base + i * pfl->chip_len,
- pfl->chip_len, phys_offset);
+static void pflash_register_memory(pflash_t *pfl, int rom_mode)
+{
+ memory_region_rom_device_set_readable(&pfl->orig_mem, rom_mode);
}
static void pflash_timer (void *opaque)
pflash_write(pfl, addr, value, 4, 0);
}
-static CPUWriteMemoryFunc * const pflash_write_ops_be[] = {
- &pflash_writeb_be,
- &pflash_writew_be,
- &pflash_writel_be,
-};
-
-static CPUReadMemoryFunc * const pflash_read_ops_be[] = {
- &pflash_readb_be,
- &pflash_readw_be,
- &pflash_readl_be,
+static const MemoryRegionOps pflash_cfi02_ops_be = {
+ .old_mmio = {
+ .read = { pflash_readb_be, pflash_readw_be, pflash_readl_be, },
+ .write = { pflash_writeb_be, pflash_writew_be, pflash_writel_be, },
+ },
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
-static CPUWriteMemoryFunc * const pflash_write_ops_le[] = {
- &pflash_writeb_le,
- &pflash_writew_le,
- &pflash_writel_le,
-};
-
-static CPUReadMemoryFunc * const pflash_read_ops_le[] = {
- &pflash_readb_le,
- &pflash_readw_le,
- &pflash_readl_le,
+static const MemoryRegionOps pflash_cfi02_ops_le = {
+ .old_mmio = {
+ .read = { pflash_readb_le, pflash_readw_le, pflash_readl_le, },
+ .write = { pflash_writeb_le, pflash_writew_le, pflash_writel_le, },
+ },
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
/* Count trailing zeroes of a 32 bits quantity */
return ret;
}
-pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
+pflash_t *pflash_cfi02_register(target_phys_addr_t base,
+ DeviceState *qdev, const char *name,
+ target_phys_addr_t size,
BlockDriverState *bs, uint32_t sector_len,
int nb_blocs, int nb_mappings, int width,
uint16_t id0, uint16_t id1,
return NULL;
#endif
pfl = g_malloc0(sizeof(pflash_t));
- /* FIXME: Allocate ram ourselves. */
- pfl->storage = qemu_get_ram_ptr(off);
- if (be) {
- pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_be,
- pflash_write_ops_be,
- pfl, DEVICE_NATIVE_ENDIAN);
- } else {
- pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_le,
- pflash_write_ops_le,
- pfl, DEVICE_NATIVE_ENDIAN);
- }
- pfl->off = off;
+ memory_region_init_rom_device(
+ &pfl->orig_mem, be ? &pflash_cfi02_ops_be : &pflash_cfi02_ops_le, pfl,
+ qdev, name, size);
+ pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem);
pfl->base = base;
pfl->chip_len = chip_len;
pfl->mappings = nb_mappings;
- pflash_register_memory(pfl, 1);
pfl->bs = bs;
if (pfl->bs) {
/* read the initial flash content */
ret = bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9);
if (ret < 0) {
- cpu_unregister_io_memory(pfl->fl_mem);
g_free(pfl);
return NULL;
}
+ bdrv_attach_dev_nofail(pfl->bs, pfl);
}
+ pflash_setup_mappings(pfl);
+ pfl->rom_mode = 1;
+ memory_region_add_subregion(get_system_memory(), pfl->base, &pfl->mem);
#if 0 /* XXX: there should be a bit to set up read-only,
* the same way the hardware does (with WP pin).
*/
int i, r;
uint32_t smram;
+ memory_region_transaction_begin();
update_pam(d, 0xf0000, 0x100000, (d->dev.config[I440FX_PAM] >> 4) & 3,
&d->pam_regions[0]);
for(i = 0; i < 12; i++) {
d->smram_enabled = false;
}
}
+ memory_region_transaction_commit();
}
static void i440fx_set_smm(int val, void *arg)
{
I440FXState *s = FROM_SYSBUS(I440FXState, dev);
- pci_host_conf_register_ioport(0xcf8, s);
+ memory_region_init_io(&s->conf_mem, &pci_host_conf_le_ops, s,
+ "pci-conf-idx", 4);
+ sysbus_add_io(dev, 0xcf8, &s->conf_mem);
+ sysbus_init_ioports(&s->busdev, 0xcf8, 4);
+
+ memory_region_init_io(&s->data_mem, &pci_host_data_le_ops, s,
+ "pci-conf-data", 4);
+ sysbus_add_io(dev, 0xcfc, &s->data_mem);
+ sysbus_init_ioports(&s->busdev, 0xcfc, 4);
- pci_host_data_register_ioport(0xcfc, s);
return 0;
}
#include "qemu-log.h"
#include "loader.h"
#include "blockdev.h"
+#include "exec-memory.h"
#define BIOS_FILENAME "ppc405_rom.bin"
#define BIOS_SIZE (2048 * 1024)
ppc4xx_bd_info_t bd;
CPUPPCState *env;
qemu_irq *pic;
- ram_addr_t sram_offset, bios_offset, bdloc;
+ MemoryRegion *bios;
+ ram_addr_t sram_offset, bdloc;
MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
target_phys_addr_t ram_bases[2], ram_sizes[2];
target_ulong sram_size;
dinfo = drive_get(IF_PFLASH, 0, fl_idx);
if (dinfo) {
bios_size = bdrv_getlength(dinfo->bdrv);
- bios_offset = qemu_ram_alloc(NULL, "ef405ep.bios", bios_size);
fl_sectors = (bios_size + 65535) >> 16;
#ifdef DEBUG_BOARD_INIT
printf("Register parallel flash %d size %lx"
- " at offset %08lx addr %lx '%s' %d\n",
- fl_idx, bios_size, bios_offset, -bios_size,
+ " at addr %lx '%s' %d\n",
+ fl_idx, bios_size, -bios_size,
bdrv_get_device_name(dinfo->bdrv), fl_sectors);
#endif
- pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
+ pflash_cfi02_register((uint32_t)(-bios_size),
+ NULL, "ef405ep.bios", bios_size,
dinfo->bdrv, 65536, fl_sectors, 1,
2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
1);
#ifdef DEBUG_BOARD_INIT
printf("Load BIOS from file\n");
#endif
- bios_offset = qemu_ram_alloc(NULL, "ef405ep.bios", BIOS_SIZE);
+ bios = g_new(MemoryRegion, 1);
+ memory_region_init_ram(bios, NULL, "ef405ep.bios", BIOS_SIZE);
if (bios_name == NULL)
bios_name = BIOS_FILENAME;
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) {
- bios_size = load_image(filename, qemu_get_ram_ptr(bios_offset));
+ bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
g_free(filename);
} else {
bios_size = -1;
exit(1);
}
bios_size = (bios_size + 0xfff) & ~0xfff;
- cpu_register_physical_memory((uint32_t)(-bios_size),
- bios_size, bios_offset | IO_MEM_ROM);
+ memory_region_set_readonly(bios, true);
+ memory_region_add_subregion(get_system_memory(),
+ (uint32_t)(-bios_size), bios);
}
/* Register FPGA */
#ifdef DEBUG_BOARD_INIT
{
char *filename;
qemu_irq *pic;
- ram_addr_t bios_offset;
+ MemoryRegion *bios;
MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
target_phys_addr_t ram_bases[2], ram_sizes[2];
long bios_size;
/* XXX: should check that size is 2MB */
// bios_size = 2 * 1024 * 1024;
fl_sectors = (bios_size + 65535) >> 16;
- bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.bios", bios_size);
#ifdef DEBUG_BOARD_INIT
printf("Register parallel flash %d size %lx"
- " at offset %08lx addr %lx '%s' %d\n",
- fl_idx, bios_size, bios_offset, -bios_size,
+ " at addr %lx '%s' %d\n",
+ fl_idx, bios_size, -bios_size,
bdrv_get_device_name(dinfo->bdrv), fl_sectors);
#endif
- pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
+ pflash_cfi02_register((uint32_t)(-bios_size),
+ NULL, "taihu_405ep.bios", bios_size,
dinfo->bdrv, 65536, fl_sectors, 1,
4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
1);
#endif
if (bios_name == NULL)
bios_name = BIOS_FILENAME;
- bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.bios", BIOS_SIZE);
+ bios = g_new(MemoryRegion, 1);
+ memory_region_init_ram(bios, NULL, "taihu_405ep.bios", BIOS_SIZE);
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) {
- bios_size = load_image(filename, qemu_get_ram_ptr(bios_offset));
+ bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
g_free(filename);
} else {
bios_size = -1;
exit(1);
}
bios_size = (bios_size + 0xfff) & ~0xfff;
- cpu_register_physical_memory((uint32_t)(-bios_size),
- bios_size, bios_offset | IO_MEM_ROM);
+ memory_region_set_readonly(bios, true);
+ memory_region_add_subregion(get_system_memory(), (uint32_t)(-bios_size),
+ bios);
}
/* Register Linux flash */
dinfo = drive_get(IF_PFLASH, 0, fl_idx);
fl_sectors = (bios_size + 65535) >> 16;
#ifdef DEBUG_BOARD_INIT
printf("Register parallel flash %d size %lx"
- " at offset %08lx addr " TARGET_FMT_lx " '%s'\n",
- fl_idx, bios_size, bios_offset, (target_ulong)0xfc000000,
+ " at addr " TARGET_FMT_lx " '%s'\n",
+ fl_idx, bios_size, (target_ulong)0xfc000000,
bdrv_get_device_name(dinfo->bdrv));
#endif
- bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.flash", bios_size);
- pflash_cfi02_register(0xfc000000, bios_offset,
+ pflash_cfi02_register(0xfc000000, NULL, "taihu_405ep.flash", bios_size,
dinfo->bdrv, 65536, fl_sectors, 1,
4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
1);
cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index);
/* CFGDATA */
- index = pci_host_data_register_mmio(&controller->pci_state, 1);
- if (index < 0)
- goto free;
- cpu_register_physical_memory(config_space + PCIC0_CFGDATA, 4, index);
+ memory_region_init_io(&controller->pci_state.data_mem,
+ &pci_host_data_be_ops,
+ &controller->pci_state, "pci-conf-data", 4);
+ memory_region_add_subregion(get_system_memory(),
+ config_space + PCIC0_CFGDATA,
+ &controller->pci_state.data_mem);
/* Internal registers */
index = cpu_register_io_memory(pci_reg_read, pci_reg_write, controller,
uint32_t gasket_time;
qemu_irq irq[4];
/* mmio maps */
- int cfgaddr;
- int cfgdata;
int reg;
};
PCIHostState *h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
PPCE500PCIState *s = DO_UPCAST(PPCE500PCIState, pci_state, h);
- cpu_register_physical_memory(base + PCIE500_CFGADDR, 4, s->cfgaddr);
- cpu_register_physical_memory(base + PCIE500_CFGDATA, 4, s->cfgdata);
+ sysbus_add_memory(dev, base + PCIE500_CFGADDR, &h->conf_mem);
+ sysbus_add_memory(dev, base + PCIE500_CFGDATA, &h->data_mem);
cpu_register_physical_memory(base + PCIE500_REG_BASE, PCIE500_REG_SIZE,
s->reg);
}
static void e500_pci_unmap(SysBusDevice *dev, target_phys_addr_t base)
{
- cpu_register_physical_memory(base + PCIE500_CFGADDR, 4,
- IO_MEM_UNASSIGNED);
- cpu_register_physical_memory(base + PCIE500_CFGDATA, 4,
- IO_MEM_UNASSIGNED);
+ PCIHostState *h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
+
+ sysbus_del_memory(dev, &h->conf_mem);
+ sysbus_del_memory(dev, &h->data_mem);
cpu_register_physical_memory(base + PCIE500_REG_BASE, PCIE500_REG_SIZE,
IO_MEM_UNASSIGNED);
}
pci_create_simple(b, 0, "e500-host-bridge");
- s->cfgaddr = pci_host_conf_register_mmio(&s->pci_state, DEVICE_BIG_ENDIAN);
- s->cfgdata = pci_host_data_register_mmio(&s->pci_state,
- DEVICE_LITTLE_ENDIAN);
+ memory_region_init_io(&h->conf_mem, &pci_host_conf_be_ops, h,
+ "pci-conf-idx", 4);
+ memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h,
+ "pci-conf-data", 4);
s->reg = cpu_register_io_memory(e500_pci_reg_read, e500_pci_reg_write, s,
DEVICE_BIG_ENDIAN);
sysbus_init_mmio_cb2(dev, e500_pci_map, e500_pci_unmap);
address_space_io,
0, 4);
- pci_host_conf_register_ioport(0xcf8, s);
-
- pci_host_data_register_ioport(0xcfc, s);
+ memory_region_init_io(&s->conf_mem, &pci_host_conf_be_ops, s,
+ "pci-conf-idx", 1);
+ memory_region_add_subregion(address_space_io, 0xcf8, &s->conf_mem);
+ sysbus_init_ioports(&s->busdev, 0xcf8, 1);
+
+ memory_region_init_io(&s->conf_mem, &pci_host_data_be_ops, s,
+ "pci-conf-data", 1);
+ memory_region_add_subregion(address_space_io, 0xcfc, &s->data_mem);
+ sysbus_init_ioports(&s->busdev, 0xcfc, 1);
PPC_io_memory = cpu_register_io_memory(PPC_PCIIO_read,
PPC_PCIIO_write, s,
bs = bdrv_find(str);
if (bs == NULL)
return -ENOENT;
- if (bdrv_attach(bs, dev) < 0)
+ if (bdrv_attach_dev(bs, dev) < 0)
return -EEXIST;
*ptr = bs;
return 0;
BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
if (*ptr) {
- bdrv_detach(*ptr, dev);
+ bdrv_detach_dev(*ptr, dev);
blockdev_auto_del(*ptr);
}
}
{
int res;
- res = bdrv_attach(value, dev);
+ res = bdrv_attach_dev(value, dev);
if (res < 0) {
error_report("Can't attach drive %s to %s.%s: %s",
bdrv_get_device_name(value),
if (!qxl->cmdlog) {
return;
}
- fprintf(stderr, "%ld qxl-%d/%s:", qemu_get_clock_ns(vm_clock),
+ fprintf(stderr, "%" PRId64 " qxl-%d/%s:", qemu_get_clock_ns(vm_clock),
qxl->id, ring);
fprintf(stderr, " cmd @ 0x%" PRIx64 " %s%s", ext->cmd.data,
qxl_name(qxl_type, ext->cmd.type),
qxl_destroy_primary(d, QXL_SYNC);
}
-static void qxl_set_irq(PCIQXLDevice *d)
+static void qxl_update_irq(PCIQXLDevice *d)
{
uint32_t pending = le32_to_cpu(d->ram->int_pending);
uint32_t mask = le32_to_cpu(d->ram->int_mask);
memslot.generation = d->rom->slot_generation = 0;
qxl_rom_set_dirty(d);
- dprint(d, 1, "%s: slot %d: host virt 0x%" PRIx64 " - 0x%" PRIx64 "\n",
+ dprint(d, 1, "%s: slot %d: host virt 0x%lx - 0x%lx\n",
__FUNCTION__, memslot.slot_id,
memslot.virt_start, memslot.virt_end);
.mem = devmem + d->shadow_rom.draw_area_offset,
};
- dprint(d, 1, "%s: mode %d [ %d x %d @ %d bpp devmem 0x%lx ]\n", __FUNCTION__,
- modenr, mode->x_res, mode->y_res, mode->bits, devmem);
+ dprint(d, 1, "%s: mode %d [ %d x %d @ %d bpp devmem 0x%" PRIx64 " ]\n",
+ __func__, modenr, mode->x_res, mode->y_res, mode->bits, devmem);
if (!loadvm) {
qxl_hard_reset(d, 0);
}
qemu_spice_wakeup(&d->ssd);
break;
case QXL_IO_UPDATE_IRQ:
- qxl_set_irq(d);
+ qxl_update_irq(d);
break;
case QXL_IO_NOTIFY_OOM:
if (!SPICE_RING_IS_EMPTY(&d->ram->release_ring)) {
break;
case QXL_IO_LOG:
if (d->guestdebug) {
- fprintf(stderr, "qxl/guest-%d: %ld: %s", d->id,
+ fprintf(stderr, "qxl/guest-%d: %" PRId64 ": %s", d->id,
qemu_get_clock_ns(vm_clock), d->ram->log_buf);
}
break;
do {
len = read(d->pipe[0], &dummy, sizeof(dummy));
} while (len == sizeof(dummy));
- qxl_set_irq(d);
+ qxl_update_irq(d);
}
-/* called from spice server thread context only */
static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
{
uint32_t old_pending;
return;
}
if (pthread_self() == d->main) {
- qxl_set_irq(d);
+ qxl_update_irq(d);
} else {
if (write(d->pipe[1], d, 1) != 1) {
dprint(d, 1, "%s: write to pipe failed\n", __FUNCTION__);
PCIQXLDevice *qxl = opaque;
qemu_spice_vm_change_state_handler(&qxl->ssd, running, reason);
- if (!running && qxl->mode == QXL_MODE_NATIVE) {
+ if (running) {
+ /*
+ * if qxl_send_events was called from spice server context before
+ * migration ended, qxl_update_irq for these events might not have been
+ * called
+ */
+ qxl_update_irq(qxl);
+ } else if (qxl->mode == QXL_MODE_NATIVE) {
/* dirty all vram (which holds surfaces) and devram (primary surface)
* to make sure they are saved */
/* FIXME #1: should go out during "live" stage */
/* onboard flash memory */
dinfo = drive_get(IF_PFLASH, 0, 0);
- pflash_cfi02_register(0x0, qemu_ram_alloc(NULL, "r2d.flash", FLASH_SIZE),
+ pflash_cfi02_register(0x0, NULL, "r2d.flash", FLASH_SIZE,
dinfo ? dinfo->bdrv : NULL, (16 * 1024),
FLASH_SIZE >> 16,
1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
memset(req->sense, 0, 18);
req->sense[0] = 0xf0;
req->sense[2] = sense.key;
+ req->sense[7] = 10;
req->sense[12] = sense.asc;
req->sense[13] = sense.ascq;
req->sense_len = 18;
/* Return fixed format sense buffer */
buf[0] = 0xf0;
buf[2] = sense.key;
- buf[7] = 7;
+ buf[7] = 10;
buf[12] = sense.asc;
buf[13] = sense.ascq;
return MIN(len, 18);
[ LOCATE_16 ] = "LOCATE_16",
[ WRITE_SAME_16 ] = "WRITE_SAME_16",
[ ERASE_16 ] = "ERASE_16",
- [ SERVICE_ACTION_IN ] = "SERVICE_ACTION_IN",
+ [ SERVICE_ACTION_IN_16 ] = "SERVICE_ACTION_IN_16",
[ WRITE_LONG_16 ] = "WRITE_LONG_16",
[ REPORT_LUNS ] = "REPORT_LUNS",
[ BLANK ] = "BLANK",
[ LOAD_UNLOAD ] = "LOAD_UNLOAD",
[ READ_12 ] = "READ_12",
[ WRITE_12 ] = "WRITE_12",
+ [ SERVICE_ACTION_IN_12 ] = "SERVICE_ACTION_IN_12",
[ WRITE_VERIFY_12 ] = "WRITE_VERIFY_12",
[ VERIFY_12 ] = "VERIFY_12",
[ SEARCH_HIGH_12 ] = "SEARCH_HIGH_12",
#define LOCATE_16 0x92
#define WRITE_SAME_16 0x93
#define ERASE_16 0x93
-#define SERVICE_ACTION_IN 0x9e
+#define SERVICE_ACTION_IN_16 0x9e
#define WRITE_LONG_16 0x9f
#define REPORT_LUNS 0xa0
#define BLANK 0xa1
#define LOAD_UNLOAD 0xa6
#define READ_12 0xa8
#define WRITE_12 0xaa
+#define SERVICE_ACTION_IN_12 0xab
#define WRITE_VERIFY_12 0xae
#define VERIFY_12 0xaf
#define SEARCH_HIGH_12 0xb0
#define READ_DEFECT_DATA_12 0xb7
#define SET_CD_SPEED 0xbb
+/*
+ * SERVICE ACTION IN subcodes
+ */
+#define SAI_READ_CAPACITY_16 0x10
+
/*
* SAM Status codes
*/
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
int n;
- r->req.aiocb = NULL;
-
- bdrv_acct_done(s->bs, &r->acct);
+ if (r->req.aiocb != NULL) {
+ r->req.aiocb = NULL;
+ bdrv_acct_done(s->bs, &r->acct);
+ }
if (ret) {
if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_READ)) {
scsi_req_data(&r->req, r->iov.iov_len);
}
+static void scsi_flush_complete(void * opaque, int ret)
+{
+ SCSIDiskReq *r = (SCSIDiskReq *)opaque;
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
+
+ if (r->req.aiocb != NULL) {
+ r->req.aiocb = NULL;
+ bdrv_acct_done(s->bs, &r->acct);
+ }
+
+ if (ret < 0) {
+ if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) {
+ return;
+ }
+ }
+
+ scsi_req_complete(&r->req, GOOD);
+}
/* Read more data from scsi device into buffer. */
static void scsi_read_data(SCSIRequest *req)
uint32_t len;
uint32_t n;
- r->req.aiocb = NULL;
-
- bdrv_acct_done(s->bs, &r->acct);
+ if (r->req.aiocb != NULL) {
+ r->req.aiocb = NULL;
+ bdrv_acct_done(s->bs, &r->acct);
+ }
if (ret) {
if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_WRITE)) {
return buflen;
}
-static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p,
+static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
int page_control)
{
- SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
BlockDriverState *bdrv = s->bs;
int cylinders, heads, secs;
+ uint8_t *p = *p_outbuf;
/*
* If Changeable Values are requested, a mask denoting those mode parameters
*/
switch (page) {
case 4: /* Rigid disk device geometry page. */
+ if (s->qdev.type == TYPE_ROM) {
+ return -1;
+ }
p[0] = 4;
p[1] = 0x16;
if (page_control == 1) { /* Changeable Values */
- return p[1] + 2;
+ break;
}
/* if a geometry hint is available, use it */
bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
/* Medium rotation rate [rpm], 5400 rpm */
p[20] = (5400 >> 8) & 0xff;
p[21] = 5400 & 0xff;
- return p[1] + 2;
+ break;
case 5: /* Flexible disk device geometry page. */
+ if (s->qdev.type == TYPE_ROM) {
+ return -1;
+ }
p[0] = 5;
p[1] = 0x1e;
if (page_control == 1) { /* Changeable Values */
- return p[1] + 2;
+ break;
}
/* Transfer rate [kbit/s], 5Mbit/s */
p[2] = 5000 >> 8;
/* Medium rotation rate [rpm], 5400 rpm */
p[28] = (5400 >> 8) & 0xff;
p[29] = 5400 & 0xff;
- return p[1] + 2;
+ break;
case 8: /* Caching page. */
p[0] = 8;
p[1] = 0x12;
if (page_control == 1) { /* Changeable Values */
- return p[1] + 2;
+ break;
}
if (bdrv_enable_write_cache(s->bs)) {
p[2] = 4; /* WCE */
}
- return p[1] + 2;
+ break;
case 0x2a: /* CD Capabilities and Mechanical Status page. */
- if (s->qdev.type != TYPE_ROM)
- return 0;
+ if (s->qdev.type != TYPE_ROM) {
+ return -1;
+ }
p[0] = 0x2a;
p[1] = 0x14;
if (page_control == 1) { /* Changeable Values */
- return p[1] + 2;
+ break;
}
p[2] = 3; // CD-R & CD-RW read
p[3] = 0; // Writing not supported
p[19] = (16 * 176) & 0xff;
p[20] = (16 * 176) >> 8; // 16x write speed current
p[21] = (16 * 176) & 0xff;
- return p[1] + 2;
+ break;
default:
- return 0;
+ return -1;
}
+
+ *p_outbuf += p[1] + 2;
+ return p[1] + 2;
}
-static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
+static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
{
- SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
uint64_t nb_sectors;
- int page, dbd, buflen, page_control;
+ int page, dbd, buflen, ret, page_control;
uint8_t *p;
uint8_t dev_specific_param;
- dbd = req->cmd.buf[1] & 0x8;
- page = req->cmd.buf[2] & 0x3f;
- page_control = (req->cmd.buf[2] & 0xc0) >> 6;
+ dbd = r->req.cmd.buf[1] & 0x8;
+ page = r->req.cmd.buf[2] & 0x3f;
+ page_control = (r->req.cmd.buf[2] & 0xc0) >> 6;
DPRINTF("Mode Sense(%d) (page %d, xfer %zd, page_control %d)\n",
- (req->cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, req->cmd.xfer, page_control);
- memset(outbuf, 0, req->cmd.xfer);
+ (r->req.cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, r->req.cmd.xfer, page_control);
+ memset(outbuf, 0, r->req.cmd.xfer);
p = outbuf;
if (bdrv_is_read_only(s->bs)) {
dev_specific_param = 0x00;
}
- if (req->cmd.buf[0] == MODE_SENSE) {
+ if (r->req.cmd.buf[0] == MODE_SENSE) {
p[1] = 0; /* Default media type. */
p[2] = dev_specific_param;
p[3] = 0; /* Block descriptor length. */
bdrv_get_geometry(s->bs, &nb_sectors);
if (!dbd && nb_sectors) {
- if (req->cmd.buf[0] == MODE_SENSE) {
+ if (r->req.cmd.buf[0] == MODE_SENSE) {
outbuf[3] = 8; /* Block descriptor length */
} else { /* MODE_SENSE_10 */
outbuf[7] = 8; /* Block descriptor length */
p += 8;
}
- if (page_control == 3) { /* Saved Values */
- return -1; /* ILLEGAL_REQUEST */
+ if (page_control == 3) {
+ /* Saved Values */
+ scsi_check_condition(r, SENSE_CODE(SAVING_PARAMS_NOT_SUPPORTED));
+ return -1;
}
- switch (page) {
- case 0x04:
- case 0x05:
- case 0x08:
- case 0x2a:
- p += mode_sense_page(req, page, p, page_control);
- break;
- case 0x3f:
- p += mode_sense_page(req, 0x08, p, page_control);
- p += mode_sense_page(req, 0x2a, p, page_control);
- break;
- default:
- return -1; /* ILLEGAL_REQUEST */
+ if (page == 0x3f) {
+ for (page = 0; page <= 0x3e; page++) {
+ mode_sense_page(s, page, &p, page_control);
+ }
+ } else {
+ ret = mode_sense_page(s, page, &p, page_control);
+ if (ret == -1) {
+ return -1;
+ }
}
buflen = p - outbuf;
* following data that is available to be transferred. The mode data
* length does not include itself.
*/
- if (req->cmd.buf[0] == MODE_SENSE) {
+ if (r->req.cmd.buf[0] == MODE_SENSE) {
outbuf[0] = buflen - 1;
} else { /* MODE_SENSE_10 */
outbuf[0] = ((buflen - 2) >> 8) & 0xff;
outbuf[1] = (buflen - 2) & 0xff;
}
- if (buflen > req->cmd.xfer)
- buflen = req->cmd.xfer;
+ if (buflen > r->req.cmd.xfer)
+ buflen = r->req.cmd.xfer;
return buflen;
}
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
uint64_t nb_sectors;
int buflen = 0;
- int ret;
switch (req->cmd.buf[0]) {
case TEST_UNIT_READY:
break;
case MODE_SENSE:
case MODE_SENSE_10:
- buflen = scsi_disk_emulate_mode_sense(req, outbuf);
+ buflen = scsi_disk_emulate_mode_sense(r, outbuf);
if (buflen < 0)
goto illegal_request;
break;
outbuf[7] = 0;
buflen = 8;
break;
- case SYNCHRONIZE_CACHE:
- {
- BlockAcctCookie acct;
-
- bdrv_acct_start(s->bs, &acct, 0, BDRV_ACCT_FLUSH);
- ret = bdrv_flush(s->bs);
- bdrv_acct_done(s->bs, &acct);
- if (ret < 0) {
- if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) {
- return -1;
- }
- }
- break;
- }
case GET_CONFIGURATION:
memset(outbuf, 0, 8);
/* ??? This should probably return much more information. For now
outbuf[7] = 8; // CD-ROM
buflen = 8;
break;
- case SERVICE_ACTION_IN:
+ case SERVICE_ACTION_IN_16:
/* Service Action In subcommands. */
- if ((req->cmd.buf[1] & 31) == 0x10) {
+ if ((req->cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
DPRINTF("SAI READ CAPACITY(16)\n");
memset(outbuf, 0, req->cmd.xfer);
bdrv_get_geometry(s->bs, &nb_sectors);
return -1;
illegal_request:
- scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
+ if (r->req.status == -1) {
+ scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
+ }
return -1;
}
case START_STOP:
case ALLOW_MEDIUM_REMOVAL:
case READ_CAPACITY_10:
- case SYNCHRONIZE_CACHE:
case READ_TOC:
case GET_CONFIGURATION:
- case SERVICE_ACTION_IN:
+ case SERVICE_ACTION_IN_16:
case VERIFY_10:
rc = scsi_disk_emulate_command(r, outbuf);
if (rc < 0) {
r->iov.iov_len = rc;
break;
+ case SYNCHRONIZE_CACHE:
+ bdrv_acct_start(s->bs, &r->acct, 0, BDRV_ACCT_FLUSH);
+ r->req.aiocb = bdrv_aio_flush(s->bs, scsi_flush_complete, r);
+ if (r->req.aiocb == NULL) {
+ scsi_flush_complete(r, -EIO);
+ }
+ return 0;
case READ_6:
case READ_10:
case READ_12:
#include "hw.h"
#include "block.h"
-#include "block_int.h"
#include "sd.h"
//#define DEBUG_SD 1
sd->pwd_len = 0;
}
-static void sd_cardchange(void *opaque, int reason)
+static void sd_cardchange(void *opaque)
{
SDState *sd = opaque;
- if (!(reason & CHANGE_MEDIA)) {
- return;
- }
-
qemu_set_irq(sd->inserted_cb, bdrv_is_inserted(sd->bdrv));
if (bdrv_is_inserted(sd->bdrv)) {
sd_reset(sd, sd->bdrv);
}
}
+static const BlockDevOps sd_block_ops = {
+ .change_media_cb = sd_cardchange,
+};
+
/* We do not model the chip select pin, so allow the board to select
whether card should be in SSI or MMC/SD mode. It is also up to the
board to ensure that ssi transfers only occur when the chip select
sd->enable = 1;
sd_reset(sd, bs);
if (sd->bdrv) {
- bdrv_set_change_cb(sd->bdrv, sd_cardchange, sd);
+ bdrv_attach_dev_nofail(sd->bdrv, sd);
+ bdrv_set_dev_ops(sd->bdrv, &sd_block_ops, sd);
}
return sd;
}
sh_intc_register_source(desc, vect->enum_id, groups, nr_groups);
s = sh_intc_source(desc, vect->enum_id);
- if (s)
- s->vect = vect->vect;
+ if (s) {
+ s->vect = vect->vect;
#ifdef DEBUG_INTC_SOURCES
- printf("sh_intc: registered source %d -> 0x%04x (%d/%d)\n",
- vect->enum_id, s->vect, s->enable_count, s->enable_max);
+ printf("sh_intc: registered source %d -> 0x%04x (%d/%d)\n",
+ vect->enum_id, s->vect, s->enable_count, s->enable_max);
#endif
+ }
}
if (groups) {
static void spitz_microdrive_attach(PXA2xxState *cpu, int slot)
{
PCMCIACardState *md;
- BlockDriverState *bs;
DriveInfo *dinfo;
dinfo = drive_get(IF_IDE, 0, 0);
- if (!dinfo)
+ if (!dinfo || dinfo->media_cd)
return;
- bs = dinfo->bdrv;
- if (bdrv_is_inserted(bs) && !bdrv_is_removable(bs)) {
- md = dscm1xxxx_init(dinfo);
- pxa2xx_pcmcia_attach(cpu->pcmcia[slot], md);
- }
+ md = dscm1xxxx_init(dinfo);
+ pxa2xx_pcmcia_attach(cpu->pcmcia[slot], md);
}
/* Wm8750 and Max7310 on I2C */
#include "i2c.h"
#include "net.h"
#include "boards.h"
+#include "exec-memory.h"
#define GPIO_A 0
#define GPIO_B 1
0x40024000, 0x40025000, 0x40026000};
static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31};
+ MemoryRegion *address_space_mem = get_system_memory();
qemu_irq *pic;
DeviceState *gpio_dev[7];
qemu_irq gpio_in[7][8];
flash_size = ((board->dc0 & 0xffff) + 1) << 1;
sram_size = (board->dc0 >> 18) + 1;
- pic = armv7m_init(flash_size, sram_size, kernel_filename, cpu_model);
+ pic = armv7m_init(address_space_mem,
+ flash_size, sram_size, kernel_filename, cpu_model);
if (board->dc1 & (1 << 16)) {
dev = sysbus_create_varargs("stellaris-adc", 0x40038000,
NICState *nic;
NICConf conf;
qemu_irq irq;
- int mmio_index;
+ MemoryRegion mmio;
} stellaris_enet_state;
static void stellaris_enet_update(stellaris_enet_state *s)
return (s->np < 31);
}
-static uint32_t stellaris_enet_read(void *opaque, target_phys_addr_t offset)
+static uint64_t stellaris_enet_read(void *opaque, target_phys_addr_t offset,
+ unsigned size)
{
stellaris_enet_state *s = (stellaris_enet_state *)opaque;
uint32_t val;
}
static void stellaris_enet_write(void *opaque, target_phys_addr_t offset,
- uint32_t value)
+ uint64_t value, unsigned size)
{
stellaris_enet_state *s = (stellaris_enet_state *)opaque;
}
}
-static CPUReadMemoryFunc * const stellaris_enet_readfn[] = {
- stellaris_enet_read,
- stellaris_enet_read,
- stellaris_enet_read
+static const MemoryRegionOps stellaris_enet_ops = {
+ .read = stellaris_enet_read,
+ .write = stellaris_enet_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
-static CPUWriteMemoryFunc * const stellaris_enet_writefn[] = {
- stellaris_enet_write,
- stellaris_enet_write,
- stellaris_enet_write
-};
static void stellaris_enet_reset(stellaris_enet_state *s)
{
s->mdv = 0x80;
unregister_savevm(&s->busdev.qdev, "stellaris_enet", s);
- cpu_unregister_io_memory(s->mmio_index);
+ memory_region_destroy(&s->mmio);
g_free(s);
}
{
stellaris_enet_state *s = FROM_SYSBUS(stellaris_enet_state, dev);
- s->mmio_index = cpu_register_io_memory(stellaris_enet_readfn,
- stellaris_enet_writefn, s,
- DEVICE_NATIVE_ENDIAN);
- sysbus_init_mmio(dev, 0x1000, s->mmio_index);
+ memory_region_init_io(&s->mmio, &stellaris_enet_ops, s, "stellaris_enet",
+ 0x1000);
+ sysbus_init_mmio_region(dev, &s->mmio);
sysbus_init_irq(dev, &s->irq);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
return strdup(path);
}
+
+void sysbus_add_memory(SysBusDevice *dev, target_phys_addr_t addr,
+ MemoryRegion *mem)
+{
+ memory_region_add_subregion(get_system_memory(), addr, mem);
+}
+
+void sysbus_add_memory_overlap(SysBusDevice *dev, target_phys_addr_t addr,
+ MemoryRegion *mem, unsigned priority)
+{
+ memory_region_add_subregion_overlap(get_system_memory(), addr, mem,
+ priority);
+}
+
+void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem)
+{
+ memory_region_del_subregion(get_system_memory(), mem);
+}
+
+void sysbus_add_io(SysBusDevice *dev, target_phys_addr_t addr,
+ MemoryRegion *mem)
+{
+ memory_region_add_subregion(get_system_io(), addr, mem);
+}
+
+void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem)
+{
+ memory_region_del_subregion(get_system_io(), mem);
+}
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq);
void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr);
+void sysbus_add_memory(SysBusDevice *dev, target_phys_addr_t addr,
+ MemoryRegion *mem);
+void sysbus_add_memory_overlap(SysBusDevice *dev, target_phys_addr_t addr,
+ MemoryRegion *mem, unsigned priority);
+void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem);
+void sysbus_add_io(SysBusDevice *dev, target_phys_addr_t addr,
+ MemoryRegion *mem);
+void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem);
/* Legacy helper function for creating devices. */
DeviceState *sysbus_create_varargs(const char *name,
static void tosa_microdrive_attach(PXA2xxState *cpu)
{
PCMCIACardState *md;
- BlockDriverState *bs;
DriveInfo *dinfo;
dinfo = drive_get(IF_IDE, 0, 0);
- if (!dinfo)
+ if (!dinfo || dinfo->media_cd)
return;
- bs = dinfo->bdrv;
- if (bdrv_is_inserted(bs) && !bdrv_is_removable(bs)) {
- md = dscm1xxxx_init(dinfo);
- pxa2xx_pcmcia_attach(cpu->pcmcia[0], md);
- }
+ md = dscm1xxxx_init(dinfo);
+ pxa2xx_pcmcia_attach(cpu->pcmcia[0], md);
}
static void tosa_out_switch(void *opaque, int line, int level)
for (i = 0; i < 15; i++) {
s->rx_config[i] = s->tx_config[i] = 0;
}
+ musb_reset(s->musb);
}
static int tusb6010_init(SysBusDevice *dev)
{
TUSBState *s = FROM_SYSBUS(TUSBState, dev);
- qemu_irq *musb_irqs;
- int i;
s->otg_timer = qemu_new_timer_ns(vm_clock, tusb_otg_tick, s);
s->pwr_timer = qemu_new_timer_ns(vm_clock, tusb_power_tick, s);
memory_region_init_io(&s->iomem[1], &tusb_async_ops, s, "tusb-async",
sysbus_init_mmio_region(dev, &s->iomem[0]);
sysbus_init_mmio_region(dev, &s->iomem[1]);
sysbus_init_irq(dev, &s->irq);
- qdev_init_gpio_in(&dev->qdev, tusb6010_irq, __musb_irq_max + 1);
- musb_irqs = g_new0(qemu_irq, __musb_irq_max);
- for (i = 0; i < __musb_irq_max; i++) {
- musb_irqs[i] = qdev_get_gpio_in(&dev->qdev, i + 1);
- }
- s->musb = musb_init(musb_irqs);
+ qdev_init_gpio_in(&dev->qdev, tusb6010_irq, musb_irq_max + 1);
+ s->musb = musb_init(&dev->qdev, 1);
return 0;
}
typedef struct UNINState {
SysBusDevice busdev;
PCIHostState host_state;
- ReadWriteHandler data_handler;
} UNINState;
static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
return retval;
}
-static void unin_data_write(ReadWriteHandler *handler,
- pcibus_t addr, uint32_t val, int len)
+static void unin_data_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned len)
{
- UNINState *s = container_of(handler, UNINState, data_handler);
- UNIN_DPRINTF("write addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val);
+ UNINState *s = opaque;
+ UNIN_DPRINTF("write addr %" TARGET_FMT_plx " len %d val %"PRIx64"\n",
+ addr, len, val);
pci_data_write(s->host_state.bus,
unin_get_config_reg(s->host_state.config_reg, addr),
val, len);
}
-static uint32_t unin_data_read(ReadWriteHandler *handler,
- pcibus_t addr, int len)
+static uint64_t unin_data_read(void *opaque, target_phys_addr_t addr,
+ unsigned len)
{
- UNINState *s = container_of(handler, UNINState, data_handler);
+ UNINState *s = opaque;
uint32_t val;
val = pci_data_read(s->host_state.bus,
unin_get_config_reg(s->host_state.config_reg, addr),
len);
- UNIN_DPRINTF("read addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val);
+ UNIN_DPRINTF("read addr %" TARGET_FMT_plx " len %d val %x\n",
+ addr, len, val);
return val;
}
+static const MemoryRegionOps unin_data_ops = {
+ .read = unin_data_read,
+ .write = unin_data_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
static int pci_unin_main_init_device(SysBusDevice *dev)
{
UNINState *s;
- int pci_mem_config, pci_mem_data;
/* Use values found on a real PowerMac */
/* Uninorth main bus */
s = FROM_SYSBUS(UNINState, dev);
- pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
- DEVICE_LITTLE_ENDIAN);
- s->data_handler.read = unin_data_read;
- s->data_handler.write = unin_data_write;
- pci_mem_data = cpu_register_io_memory_simple(&s->data_handler,
- DEVICE_LITTLE_ENDIAN);
- sysbus_init_mmio(dev, 0x1000, pci_mem_config);
- sysbus_init_mmio(dev, 0x1000, pci_mem_data);
+ memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
+ &s->host_state, "pci-conf-idx", 0x1000);
+ memory_region_init_io(&s->host_state.data_mem, &unin_data_ops, s,
+ "pci-conf-data", 0x1000);
+ sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
+ sysbus_init_mmio_region(dev, &s->host_state.data_mem);
qemu_register_reset(pci_unin_reset, &s->host_state);
return 0;
}
+
static int pci_u3_agp_init_device(SysBusDevice *dev)
{
UNINState *s;
- int pci_mem_config, pci_mem_data;
/* Uninorth U3 AGP bus */
s = FROM_SYSBUS(UNINState, dev);
- pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
- DEVICE_LITTLE_ENDIAN);
- s->data_handler.read = unin_data_read;
- s->data_handler.write = unin_data_write;
- pci_mem_data = cpu_register_io_memory_simple(&s->data_handler,
- DEVICE_LITTLE_ENDIAN);
- sysbus_init_mmio(dev, 0x1000, pci_mem_config);
- sysbus_init_mmio(dev, 0x1000, pci_mem_data);
+ memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
+ &s->host_state, "pci-conf-idx", 0x1000);
+ memory_region_init_io(&s->host_state.data_mem, &unin_data_ops, s,
+ "pci-conf-data", 0x1000);
+ sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
+ sysbus_init_mmio_region(dev, &s->host_state.data_mem);
qemu_register_reset(pci_unin_reset, &s->host_state);
static int pci_unin_agp_init_device(SysBusDevice *dev)
{
UNINState *s;
- int pci_mem_config, pci_mem_data;
/* Uninorth AGP bus */
s = FROM_SYSBUS(UNINState, dev);
- pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
- DEVICE_LITTLE_ENDIAN);
- pci_mem_data = pci_host_data_register_mmio(&s->host_state,
- DEVICE_LITTLE_ENDIAN);
- sysbus_init_mmio(dev, 0x1000, pci_mem_config);
- sysbus_init_mmio(dev, 0x1000, pci_mem_data);
+ memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
+ &s->host_state, "pci-conf-idx", 0x1000);
+ memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
+ &s->host_state, "pci-conf-data", 0x1000);
+ sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
+ sysbus_init_mmio_region(dev, &s->host_state.data_mem);
return 0;
}
static int pci_unin_internal_init_device(SysBusDevice *dev)
{
UNINState *s;
- int pci_mem_config, pci_mem_data;
/* Uninorth internal bus */
s = FROM_SYSBUS(UNINState, dev);
- pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
- DEVICE_LITTLE_ENDIAN);
- pci_mem_data = pci_host_data_register_mmio(&s->host_state,
- DEVICE_LITTLE_ENDIAN);
- sysbus_init_mmio(dev, 0x1000, pci_mem_config);
- sysbus_init_mmio(dev, 0x1000, pci_mem_data);
+ memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
+ &s->host_state, "pci-conf-idx", 0x1000);
+ memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
+ &s->host_state, "pci-conf-data", 0x1000);
+ sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
+ sysbus_init_mmio_region(dev, &s->host_state.data_mem);
return 0;
}
#include "qdev.h"
#include "sysemu.h"
#include "monitor.h"
+#include "trace.h"
static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
dev->info = info;
dev->auto_attach = 1;
QLIST_INIT(&dev->strings);
- rc = dev->info->init(dev);
- if (rc == 0 && dev->auto_attach)
+ rc = usb_claim_port(dev);
+ if (rc == 0) {
+ rc = dev->info->init(dev);
+ }
+ if (rc == 0 && dev->auto_attach) {
rc = usb_device_attach(dev);
+ }
return rc;
}
if (dev->info->handle_destroy) {
dev->info->handle_destroy(dev);
}
+ if (dev->port) {
+ usb_release_port(dev);
+ }
return 0;
}
bus->nfree--;
}
-static int do_attach(USBDevice *dev)
+int usb_claim_port(USBDevice *dev)
{
USBBus *bus = usb_bus_from_device(dev);
USBPort *port;
- if (dev->attached) {
- error_report("Error: tried to attach usb device %s twice\n",
- dev->product_desc);
- return -1;
- }
- if (bus->nfree == 0) {
- error_report("Error: tried to attach usb device %s to a bus with no free ports\n",
- dev->product_desc);
- return -1;
- }
+ assert(dev->port == NULL);
+
if (dev->port_path) {
QTAILQ_FOREACH(port, &bus->free, next) {
if (strcmp(port->path, dev->port_path) == 0) {
}
}
if (port == NULL) {
- error_report("Error: usb port %s (bus %s) not found\n",
- dev->port_path, bus->qbus.name);
+ error_report("Error: usb port %s (bus %s) not found (in use?)\n",
+ dev->port_path, bus->qbus.name);
return -1;
}
} else {
+ if (bus->nfree == 1 && strcmp(dev->qdev.info->name, "usb-hub") != 0) {
+ /* Create a new hub and chain it on */
+ usb_create_simple(bus, "usb-hub");
+ }
+ if (bus->nfree == 0) {
+ error_report("Error: tried to attach usb device %s to a bus "
+ "with no free ports\n", dev->product_desc);
+ return -1;
+ }
port = QTAILQ_FIRST(&bus->free);
}
- if (!(port->speedmask & dev->speedmask)) {
- error_report("Warning: speed mismatch trying to attach usb device %s to bus %s\n",
- dev->product_desc, bus->qbus.name);
- return -1;
- }
+ trace_usb_port_claim(bus->busnr, port->path);
- dev->attached++;
QTAILQ_REMOVE(&bus->free, port, next);
bus->nfree--;
- usb_attach(port, dev);
+ dev->port = port;
+ port->dev = dev;
QTAILQ_INSERT_TAIL(&bus->used, port, next);
bus->nused++;
-
return 0;
}
-int usb_device_attach(USBDevice *dev)
+void usb_release_port(USBDevice *dev)
{
USBBus *bus = usb_bus_from_device(dev);
+ USBPort *port = dev->port;
- if (bus->nfree == 1 && dev->port_path == NULL) {
- /* Create a new hub and chain it on
- (unless a physical port location is specified). */
- usb_create_simple(bus, "usb-hub");
- }
- return do_attach(dev);
+ assert(port != NULL);
+ trace_usb_port_release(bus->busnr, port->path);
+
+ QTAILQ_REMOVE(&bus->used, port, next);
+ bus->nused--;
+
+ dev->port = NULL;
+ port->dev = NULL;
+
+ QTAILQ_INSERT_TAIL(&bus->free, port, next);
+ bus->nfree++;
}
-int usb_device_detach(USBDevice *dev)
+int usb_device_attach(USBDevice *dev)
{
USBBus *bus = usb_bus_from_device(dev);
- USBPort *port;
+ USBPort *port = dev->port;
- if (!dev->attached) {
- error_report("Error: tried to detach unattached usb device %s\n",
- dev->product_desc);
+ assert(port != NULL);
+ assert(!dev->attached);
+ trace_usb_port_attach(bus->busnr, port->path);
+
+ if (!(port->speedmask & dev->speedmask)) {
+ error_report("Warning: speed mismatch trying to attach "
+ "usb device %s to bus %s\n",
+ dev->product_desc, bus->qbus.name);
return -1;
}
- dev->attached--;
- QTAILQ_FOREACH(port, &bus->used, next) {
- if (port->dev == dev)
- break;
- }
- assert(port != NULL);
+ dev->attached++;
+ usb_attach(port);
- QTAILQ_REMOVE(&bus->used, port, next);
- bus->nused--;
+ return 0;
+}
+
+int usb_device_detach(USBDevice *dev)
+{
+ USBBus *bus = usb_bus_from_device(dev);
+ USBPort *port = dev->port;
- usb_attach(port, NULL);
+ assert(port != NULL);
+ assert(dev->attached);
+ trace_usb_port_detach(bus->busnr, port->path);
- QTAILQ_INSERT_TAIL(&bus->free, port, next);
- bus->nfree++;
+ usb_detach(port);
+ dev->attached--;
return 0;
}
#include "qemu-common.h"
#include "qemu-error.h"
#include "usb.h"
+#include "usb-desc.h"
#include "monitor.h"
#include "hw/ccid.h"
* 0dc3:1004 Athena Smartcard Solutions, Inc.
*/
-static const uint8_t qemu_ccid_dev_descriptor[] = {
- 0x12, /* u8 bLength; */
- USB_DT_DEVICE, /* u8 bDescriptorType; Device */
- 0x10, 0x01, /* u16 bcdUSB; v1.1 */
-
- 0x00, /* u8 bDeviceClass; */
- 0x00, /* u8 bDeviceSubClass; */
- 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
- 0x40, /* u8 bMaxPacketSize0; 8 Bytes (valid: 8,16,32,64) */
-
- /* Vendor and product id are arbitrary. */
- /* u16 idVendor */
- CCID_VENDOR_ID & 0xff, CCID_VENDOR_ID >> 8,
- /* u16 idProduct */
- CCID_PRODUCT_ID & 0xff, CCID_PRODUCT_ID >> 8,
- /* u16 bcdDevice */
- CCID_DEVICE_VERSION & 0xff, CCID_DEVICE_VERSION >> 8,
- 0x01, /* u8 iManufacturer; */
- 0x02, /* u8 iProduct; */
- 0x03, /* u8 iSerialNumber; */
- 0x01, /* u8 bNumConfigurations; */
-};
-
-static const uint8_t qemu_ccid_config_descriptor[] = {
-
- /* one configuration */
- 0x09, /* u8 bLength; */
- USB_DT_CONFIG, /* u8 bDescriptorType; Configuration */
- 0x5d, 0x00, /* u16 wTotalLength; 9+9+54+7+7+7 */
- 0x01, /* u8 bNumInterfaces; (1) */
- 0x01, /* u8 bConfigurationValue; */
- 0x00, /* u8 iConfiguration; */
- 0xe0, /* u8 bmAttributes;
- Bit 7: must be set,
- 6: Self-powered,
- 5: Remote wakeup,
- 4..0: resvd */
- 100/2, /* u8 MaxPower; 50 == 100mA */
-
- /* one interface */
- 0x09, /* u8 if_bLength; */
- USB_DT_INTERFACE, /* u8 if_bDescriptorType; Interface */
- 0x00, /* u8 if_bInterfaceNumber; */
- 0x00, /* u8 if_bAlternateSetting; */
- 0x03, /* u8 if_bNumEndpoints; */
- 0x0b, /* u8 if_bInterfaceClass; Smart Card Device Class */
- 0x00, /* u8 if_bInterfaceSubClass; Subclass code */
- 0x00, /* u8 if_bInterfaceProtocol; Protocol code */
- 0x04, /* u8 if_iInterface; Index of string descriptor */
-
+static const uint8_t qemu_ccid_descriptor[] = {
/* Smart Card Device Class Descriptor */
0x36, /* u8 bLength; */
0x21, /* u8 bDescriptorType; Functional */
* 02h PIN Modification
*/
0x01, /* u8 bMaxCCIDBusySlots; */
+};
- /* Interrupt-IN endpoint */
- 0x07, /* u8 ep_bLength; */
- /* u8 ep_bDescriptorType; Endpoint */
- USB_DT_ENDPOINT,
- /* u8 ep_bEndpointAddress; IN Endpoint 1 */
- 0x80 | CCID_INT_IN_EP,
- 0x03, /* u8 ep_bmAttributes; Interrupt */
- /* u16 ep_wMaxPacketSize; */
- CCID_MAX_PACKET_SIZE & 0xff, (CCID_MAX_PACKET_SIZE >> 8),
- 0xff, /* u8 ep_bInterval; */
-
- /* Bulk-In endpoint */
- 0x07, /* u8 ep_bLength; */
- /* u8 ep_bDescriptorType; Endpoint */
- USB_DT_ENDPOINT,
- /* u8 ep_bEndpointAddress; IN Endpoint 2 */
- 0x80 | CCID_BULK_IN_EP,
- 0x02, /* u8 ep_bmAttributes; Bulk */
- 0x40, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x00, /* u8 ep_bInterval; */
-
- /* Bulk-Out endpoint */
- 0x07, /* u8 ep_bLength; */
- /* u8 ep_bDescriptorType; Endpoint */
- USB_DT_ENDPOINT,
- /* u8 ep_bEndpointAddress; OUT Endpoint 3 */
- CCID_BULK_OUT_EP,
- 0x02, /* u8 ep_bmAttributes; Bulk */
- 0x40, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x00, /* u8 ep_bInterval; */
+enum {
+ STR_MANUFACTURER = 1,
+ STR_PRODUCT,
+ STR_SERIALNUMBER,
+ STR_INTERFACE,
+};
+static const USBDescStrings desc_strings = {
+ [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
+ [STR_PRODUCT] = "QEMU USB CCID",
+ [STR_SERIALNUMBER] = "1",
+ [STR_INTERFACE] = "CCID Interface",
+};
+
+static const USBDescIface desc_iface0 = {
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 3,
+ .bInterfaceClass = 0x0b,
+ .bInterfaceSubClass = 0x00,
+ .bInterfaceProtocol = 0x00,
+ .iInterface = STR_INTERFACE,
+ .ndesc = 1,
+ .descs = (USBDescOther[]) {
+ {
+ /* smartcard descriptor */
+ .data = qemu_ccid_descriptor,
+ },
+ },
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_IN | CCID_INT_IN_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .bInterval = 255,
+ .wMaxPacketSize = 64,
+ },{
+ .bEndpointAddress = USB_DIR_IN | CCID_BULK_IN_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 64,
+ },{
+ .bEndpointAddress = USB_DIR_OUT | CCID_BULK_OUT_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 64,
+ },
+ }
+};
+
+static const USBDescDevice desc_device = {
+ .bcdUSB = 0x0110,
+ .bMaxPacketSize0 = 64,
+ .bNumConfigurations = 1,
+ .confs = (USBDescConfig[]) {
+ {
+ .bNumInterfaces = 1,
+ .bConfigurationValue = 1,
+ .bmAttributes = 0xa0,
+ .bMaxPower = 50,
+ .nif = 1,
+ .ifs = &desc_iface0,
+ },
+ },
+};
+
+static const USBDesc desc_ccid = {
+ .id = {
+ .idVendor = CCID_VENDOR_ID,
+ .idProduct = CCID_PRODUCT_ID,
+ .bcdDevice = CCID_DEVICE_VERSION,
+ .iManufacturer = STR_MANUFACTURER,
+ .iProduct = STR_PRODUCT,
+ .iSerialNumber = STR_SERIALNUMBER,
+ },
+ .full = &desc_device,
+ .str = desc_strings,
};
static bool ccid_has_pending_answers(USBCCIDState *s)
int ret = 0;
DPRINTF(s, 1, "got control %x, value %x\n", request, value);
+ ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
+ if (ret >= 0) {
+ return ret;
+ }
+
switch (request) {
- case DeviceRequest | USB_REQ_GET_STATUS:
- data[0] = (1 << USB_DEVICE_SELF_POWERED) |
- (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
- data[1] = 0x00;
- ret = 2;
- break;
- case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
- if (value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->remote_wakeup = 0;
- } else {
- goto fail;
- }
- ret = 0;
- break;
- case DeviceOutRequest | USB_REQ_SET_FEATURE:
- if (value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->remote_wakeup = 1;
- } else {
- goto fail;
- }
- ret = 0;
- break;
- case DeviceOutRequest | USB_REQ_SET_ADDRESS:
- dev->addr = value;
- ret = 0;
- break;
- case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
- switch (value >> 8) {
- case USB_DT_DEVICE:
- memcpy(data, qemu_ccid_dev_descriptor,
- sizeof(qemu_ccid_dev_descriptor));
- ret = sizeof(qemu_ccid_dev_descriptor);
- break;
- case USB_DT_CONFIG:
- memcpy(data, qemu_ccid_config_descriptor,
- sizeof(qemu_ccid_config_descriptor));
- ret = sizeof(qemu_ccid_config_descriptor);
- break;
- case USB_DT_STRING:
- switch (value & 0xff) {
- case 0:
- /* language ids */
- data[0] = 4;
- data[1] = 3;
- data[2] = 0x09;
- data[3] = 0x04;
- ret = 4;
- break;
- case 1:
- /* vendor description */
- ret = set_usb_string(data, CCID_VENDOR_DESCRIPTION);
- break;
- case 2:
- /* product description */
- ret = set_usb_string(data, CCID_PRODUCT_DESCRIPTION);
- break;
- case 3:
- /* serial number */
- ret = set_usb_string(data, CCID_SERIAL_NUMBER_STRING);
- break;
- case 4:
- /* interface name */
- ret = set_usb_string(data, CCID_INTERFACE_NAME);
- break;
- default:
- goto fail;
- }
- break;
- default:
- goto fail;
- }
- break;
- case DeviceRequest | USB_REQ_GET_CONFIGURATION:
- data[0] = 1;
- ret = 1;
- break;
- case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
- /* Only one configuration - we just ignore the request */
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
ret = 0;
break;
- case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
- ret = 0;
- break;
/* Class specific requests. */
case InterfaceOutClass | CCID_CONTROL_ABORT:
ret = USB_RET_STALL;
break;
default:
-fail:
DPRINTF(s, 1, "got unsupported/bogus control %x, value %x\n",
request, value);
ret = USB_RET_STALL;
s->bmSlotICCState |= SLOT_0_CHANGED_MASK;
}
s->notify_slot_change = true;
+ usb_wakeup(&s->dev);
}
static void ccid_write_data_block_error(
break;
default:
DPRINTF(s, 1, "Bad endpoint\n");
+ ret = USB_RET_STALL;
break;
}
break;
{
USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+ usb_desc_init(dev);
qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL);
s->bus.qbus.allow_hotplug = 1;
s->card = NULL;
.qdev.desc = "CCID Rev 1.1 smartcard reader",
.qdev.size = sizeof(USBCCIDState),
.init = ccid_initfn,
+ .usb_desc = &desc_ccid,
.handle_packet = usb_generic_handle_packet,
.handle_reset = ccid_handle_reset,
.handle_control = ccid_handle_control,
struct USBDescOther {
uint8_t length;
- uint8_t *data;
+ const uint8_t *data;
};
typedef const char *USBDescStrings[256];
EST_FETCHENTRY,
EST_FETCHQH,
EST_FETCHITD,
+ EST_FETCHSITD,
EST_ADVANCEQUEUE,
EST_FETCHQTD,
EST_EXECUTE,
get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR));
}
+static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
+ EHCIsitd *sitd)
+{
+ trace_usb_ehci_sitd(addr, sitd->next,
+ (bool)(sitd->results & SITD_RESULTS_ACTIVE));
+}
+
/* queue management */
static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
*/
for(i = 0; i < NB_PORTS; i++) {
devs[i] = s->ports[i].dev;
- if (devs[i]) {
- usb_attach(&s->ports[i], NULL);
+ if (devs[i] && devs[i]->attached) {
+ usb_detach(&s->ports[i]);
}
}
} else {
s->portsc[i] = PORTSC_PPOWER;
}
- if (devs[i]) {
- usb_attach(&s->ports[i], devs[i]);
+ if (devs[i] && devs[i]->attached) {
+ usb_attach(&s->ports[i]);
}
}
ehci_queues_rip_all(s);
return;
}
- if (dev) {
- usb_attach(&s->ports[port], NULL);
+ if (dev && dev->attached) {
+ usb_detach(&s->ports[port]);
}
*portsc &= ~PORTSC_POWNER;
*portsc |= owner;
- if (dev) {
- usb_attach(&s->ports[port], dev);
+ if (dev && dev->attached) {
+ usb_attach(&s->ports[port]);
}
}
if (!(val & PORTSC_PRESET) &&(*portsc & PORTSC_PRESET)) {
trace_usb_ehci_port_reset(port, 0);
- if (dev) {
- usb_attach(&s->ports[port], dev);
+ if (dev && dev->attached) {
+ usb_attach(&s->ports[port]);
usb_send_msg(dev, USB_MSG_RESET);
*portsc &= ~PORTSC_CSC;
}
* Table 2.16 Set the enable bit(and enable bit change) to indicate
* to SW that this port has a high speed device attached
*/
- if (dev && (dev->speedmask & USB_SPEED_MASK_HIGH)) {
+ if (dev && dev->attached && (dev->speedmask & USB_SPEED_MASK_HIGH)) {
val |= PORTSC_PED;
}
}
again = 1;
break;
+ case NLPTR_TYPE_STITD:
+ ehci_set_state(ehci, async, EST_FETCHSITD);
+ again = 1;
+ break;
+
default:
- // TODO: handle siTD and FSTN types
+ /* TODO: handle FSTN type */
fprintf(stderr, "FETCHENTRY: entry at %X is of type %d "
"which is not supported yet\n", entry, NLPTR_TYPE_GET(entry));
return -1;
return 1;
}
+static int ehci_state_fetchsitd(EHCIState *ehci, int async)
+{
+ uint32_t entry;
+ EHCIsitd sitd;
+
+ assert(!async);
+ entry = ehci_get_fetch_addr(ehci, async);
+
+ get_dwords(NLPTR_GET(entry), (uint32_t *)&sitd,
+ sizeof(EHCIsitd) >> 2);
+ ehci_trace_sitd(ehci, entry, &sitd);
+
+ if (!(sitd.results & SITD_RESULTS_ACTIVE)) {
+ /* siTD is not active, nothing to do */;
+ } else {
+ /* TODO: split transfers are not implemented */
+ fprintf(stderr, "WARNING: Skipping active siTD\n");
+ }
+
+ ehci_set_fetch_addr(ehci, async, sitd.next);
+ ehci_set_state(ehci, async, EST_FETCHENTRY);
+ return 1;
+}
+
/* Section 4.10.2 - paragraph 3 */
static int ehci_state_advqueue(EHCIQueue *q, int async)
{
again = ehci_state_fetchitd(ehci, async);
break;
+ case EST_FETCHSITD:
+ again = ehci_state_fetchsitd(ehci, async);
+ break;
+
case EST_ADVANCEQUEUE:
again = ehci_state_advqueue(q, async);
break;
usb_packet_complete(&s->dev, packet);
}
-static void usb_hub_handle_attach(USBDevice *dev)
-{
- USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
- int i;
-
- for (i = 0; i < NUM_PORTS; i++) {
- usb_port_location(&s->ports[i].port, dev->port, i+1);
- }
-}
-
static void usb_hub_handle_reset(USBDevice *dev)
{
/* XXX: do it */
usb_register_port(usb_bus_from_device(dev),
&port->port, s, i, &usb_hub_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+ usb_port_location(&port->port, dev->port, i+1);
port->wPortStatus = PORT_STAT_POWER;
port->wPortChange = 0;
}
.usb_desc = &desc_hub,
.init = usb_hub_initfn,
.handle_packet = usb_hub_handle_packet,
- .handle_attach = usb_hub_handle_attach,
.handle_reset = usb_hub_handle_reset,
.handle_control = usb_hub_handle_control,
.handle_data = usb_hub_handle_data,
*
* The hack is probably a bad idea.
*/
- bdrv_detach(bs, &s->dev.qdev);
+ bdrv_detach_dev(bs, &s->dev.qdev);
s->conf.bs = NULL;
if (!s->serial) {
};
struct MUSBState {
- qemu_irq *irqs;
+ qemu_irq irqs[musb_irq_max];
USBBus bus;
USBPort port;
MUSBEndPoint ep[16];
};
-struct MUSBState *musb_init(qemu_irq *irqs)
+void musb_reset(MUSBState *s)
{
- MUSBState *s = g_malloc0(sizeof(*s));
int i;
- s->irqs = irqs;
-
s->faddr = 0x00;
+ s->devctl = 0;
s->power = MGC_M_POWER_HSENAB;
s->tx_intr = 0x0000;
s->rx_intr = 0x0000;
s->mask = 0x06;
s->idx = 0;
+ s->setup_len = 0;
+ s->session = 0;
+ memset(s->buf, 0, sizeof(s->buf));
+
/* TODO: _DW */
s->ep[0].config = MGC_M_CONFIGDATA_SOFTCONE | MGC_M_CONFIGDATA_DYNFIFO;
for (i = 0; i < 16; i ++) {
usb_packet_init(&s->ep[i].packey[0].p);
usb_packet_init(&s->ep[i].packey[1].p);
}
+}
+
+struct MUSBState *musb_init(DeviceState *parent_device, int gpio_base)
+{
+ MUSBState *s = g_malloc0(sizeof(*s));
+ int i;
+
+ for (i = 0; i < musb_irq_max; i++) {
+ s->irqs[i] = qdev_get_gpio_in(parent_device, gpio_base + i);
+ }
+
+ musb_reset(s);
- usb_bus_new(&s->bus, &musb_bus_ops, NULL /* FIXME */);
+ usb_bus_new(&s->bus, &musb_bus_ops, parent_device);
usb_register_port(&s->bus, &s->port, s, 0, &musb_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
{
port = &ohci->rhport[i];
port->ctrl = 0;
- if (port->port.dev) {
- usb_attach(&port->port, port->port.dev);
+ if (port->port.dev && port->port.dev->attached) {
+ usb_attach(&port->port);
}
}
if (ohci->async_td) {
for(i = 0; i < NB_PORTS; i++) {
port = &s->ports[i];
port->ctrl = 0x0080;
- if (port->port.dev) {
- usb_attach(&port->port, port->port.dev);
+ if (port->port.dev && port->port.dev->attached) {
+ usb_attach(&port->port);
}
}
for(i = 0; i < NB_PORTS; i++) {
port = &s->ports[i];
dev = port->port.dev;
- if (dev) {
+ if (dev && dev->attached) {
usb_send_msg(dev, USB_MSG_RESET);
}
}
return;
port = &s->ports[n];
dev = port->port.dev;
- if (dev) {
+ if (dev && dev->attached) {
/* port reset */
if ( (val & UHCI_PORT_RESET) &&
!(port->ctrl & UHCI_PORT_RESET) ) {
UHCIPort *port = &s->ports[i];
USBDevice *dev = port->port.dev;
- if (dev && (port->ctrl & UHCI_PORT_EN))
+ if (dev && dev->attached && (port->ctrl & UHCI_PORT_EN)) {
ret = usb_handle_packet(dev, p);
+ }
}
DPRINTF("uhci: packet exit. ret %d len %zd\n", ret, p->iov.size);
#include "usb.h"
#include "iov.h"
-void usb_attach(USBPort *port, USBDevice *dev)
+void usb_attach(USBPort *port)
{
- if (dev != NULL) {
- /* attach */
- if (port->dev) {
- usb_attach(port, NULL);
- }
- dev->port = port;
- port->dev = dev;
- port->ops->attach(port);
- usb_send_msg(dev, USB_MSG_ATTACH);
- } else {
- /* detach */
- dev = port->dev;
- assert(dev);
- port->ops->detach(port);
- usb_send_msg(dev, USB_MSG_DETACH);
- dev->port = NULL;
- port->dev = NULL;
- }
+ USBDevice *dev = port->dev;
+
+ assert(dev != NULL);
+ assert(dev->attached);
+ port->ops->attach(port);
+ usb_send_msg(dev, USB_MSG_ATTACH);
+}
+
+void usb_detach(USBPort *port)
+{
+ USBDevice *dev = port->dev;
+
+ assert(dev != NULL);
+ port->ops->detach(port);
+ usb_send_msg(dev, USB_MSG_DETACH);
}
void usb_wakeup(USBDevice *dev)
{
/* Note: p->owner != dev is possible in case dev is a hub */
assert(p->owner != NULL);
- dev->port->ops->complete(dev->port, p);
p->owner = NULL;
+ dev->port->ops->complete(dev->port, p);
}
/* Cancel an active packet. The packed must have been deferred by
void usb_packet_complete(USBDevice *dev, USBPacket *p);
void usb_cancel_packet(USBPacket * p);
-void usb_attach(USBPort *port, USBDevice *dev);
+void usb_attach(USBPort *port);
+void usb_detach(USBPort *port);
void usb_wakeup(USBDevice *dev);
int usb_generic_handle_packet(USBDevice *s, USBPacket *p);
void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p);
musb_irq_tx,
musb_set_vbus,
musb_set_session,
- __musb_irq_max,
+ /* Add new interrupts here */
+ musb_irq_max, /* total number of interrupts defined */
};
typedef struct MUSBState MUSBState;
-MUSBState *musb_init(qemu_irq *irqs);
+MUSBState *musb_init(DeviceState *parent_device, int gpio_base);
+void musb_reset(MUSBState *s);
uint32_t musb_core_intr_get(MUSBState *s);
void musb_core_intr_clear(MUSBState *s, uint32_t mask);
void musb_set_size(MUSBState *s, int epnum, int size, int is_tx);
void *opaque, USBPortOps *ops, int speedmask);
void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr);
void usb_unregister_port(USBBus *bus, USBPort *port);
+int usb_claim_port(USBDevice *dev);
+void usb_release_port(USBDevice *dev);
int usb_device_attach(USBDevice *dev);
int usb_device_detach(USBDevice *dev);
int usb_device_delete_addr(int busnr, int addr);
target_phys_addr_t ram_base = 0;
DriveInfo *dinfo;
ram_addr_t phys_ram;
- ram_addr_t phys_flash;
qemu_irq irq[32], *cpu_irq;
clk_setup_t clk_setup[7];
int kernel_size;
phys_ram = qemu_ram_alloc(NULL, "ram", ram_size);
cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM);
- phys_flash = qemu_ram_alloc(NULL, "virtex.flash", FLASH_SIZE);
dinfo = drive_get(IF_PFLASH, 0, 0);
- pflash_cfi01_register(0xfc000000, phys_flash,
+ pflash_cfi01_register(0xfc000000, NULL, "virtex.flash", FLASH_SIZE,
dinfo ? dinfo->bdrv : NULL, (64 * 1024),
FLASH_SIZE >> 16,
1, 0x89, 0x18, 0x0000, 0x0, 1);
return 0;
}
-static void virtio_blk_change_cb(void *opaque, int reason)
+static void virtio_blk_resize(void *opaque)
{
VirtIOBlock *s = opaque;
- if (reason & CHANGE_SIZE) {
- virtio_notify_config(&s->vdev);
- }
+ virtio_notify_config(&s->vdev);
}
+static const BlockDevOps virtio_block_ops = {
+ .resize_cb = virtio_blk_resize,
+};
+
VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
char **serial)
{
register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
virtio_blk_save, virtio_blk_load, s);
bdrv_set_removable(s->bs, 0);
- bdrv_set_change_cb(s->bs, virtio_blk_change_cb, s);
+ bdrv_set_dev_ops(s->bs, &virtio_block_ops, s);
s->bs->buffer_alignment = conf->logical_block_size;
add_boot_device_path(conf->bootindex, dev, "/disk@0,0");
xen_be_printf(&blkdev->xendev, 2, "get configured bdrv (cmdline setup)\n");
blkdev->bs = blkdev->dinfo->bdrv;
}
+ bdrv_attach_dev_nofail(blkdev->bs, blkdev);
blkdev->file_blk = BLOCK_SIZE;
blkdev->file_size = bdrv_getlength(blkdev->bs);
if (blkdev->file_size < 0) {
}
if (!pflash_cfi01_register(Z2_FLASH_BASE,
- qemu_ram_alloc(NULL, "z2.flash0", Z2_FLASH_SIZE),
+ NULL, "z2.flash0", Z2_FLASH_SIZE,
dinfo->bdrv, sector_len,
Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0,
be)) {
$(INSTALL_DIR) "$(DESTDIR)$(libcacard_includedir)"
$(INSTALL_DIR) "$(DESTDIR)$(bindir)"
$(LIBTOOL) --mode=install $(INSTALL_PROG) vscclient "$(DESTDIR)$(bindir)"
- $(LIBTOOL) --mode=install $(INSTALL_PROG) libcacard.la "$(DESTDIR)$(libdir)"
+ $(LIBTOOL) --mode=install $(INSTALL_DATA) libcacard.la "$(DESTDIR)$(libdir)"
$(LIBTOOL) --mode=install $(INSTALL_DATA) libcacard.pc "$(DESTDIR)$(libdir)/pkgconfig"
for inc in *.h; do \
$(LIBTOOL) --mode=install $(INSTALL_DATA) $(libcacard_srcpath)/$$inc "$(DESTDIR)$(libcacard_includedir)"; \
case QEMU_AIO_READ:
io_prep_preadv(iocbs, fd, qiov->iov, qiov->niov, offset);
break;
+ /* Currently Linux kernel does not support other operations */
default:
fprintf(stderr, "%s: invalid AIO request type 0x%x.\n",
__func__, type);
+++ /dev/null
-#include "rwhandler.h"
-#include "ioport.h"
-#include "cpu-all.h"
-
-#define RWHANDLER_WRITE(name, len, type) \
-static void name(void *opaque, type addr, uint32_t value) \
-{\
- struct ReadWriteHandler *handler = opaque;\
- handler->write(handler, addr, value, len);\
-}
-
-#define RWHANDLER_READ(name, len, type) \
-static uint32_t name(void *opaque, type addr) \
-{ \
- struct ReadWriteHandler *handler = opaque; \
- return handler->read(handler, addr, len); \
-}
-
-RWHANDLER_WRITE(cpu_io_memory_simple_writeb, 1, target_phys_addr_t);
-RWHANDLER_READ(cpu_io_memory_simple_readb, 1, target_phys_addr_t);
-RWHANDLER_WRITE(cpu_io_memory_simple_writew, 2, target_phys_addr_t);
-RWHANDLER_READ(cpu_io_memory_simple_readw, 2, target_phys_addr_t);
-RWHANDLER_WRITE(cpu_io_memory_simple_writel, 4, target_phys_addr_t);
-RWHANDLER_READ(cpu_io_memory_simple_readl, 4, target_phys_addr_t);
-
-static CPUWriteMemoryFunc * const cpu_io_memory_simple_write[] = {
- &cpu_io_memory_simple_writeb,
- &cpu_io_memory_simple_writew,
- &cpu_io_memory_simple_writel,
-};
-
-static CPUReadMemoryFunc * const cpu_io_memory_simple_read[] = {
- &cpu_io_memory_simple_readb,
- &cpu_io_memory_simple_readw,
- &cpu_io_memory_simple_readl,
-};
-
-int cpu_register_io_memory_simple(struct ReadWriteHandler *handler, int endian)
-{
- if (!handler->read || !handler->write) {
- return -1;
- }
- return cpu_register_io_memory(cpu_io_memory_simple_read,
- cpu_io_memory_simple_write,
- handler, endian);
-}
-
-RWHANDLER_WRITE(ioport_simple_writeb, 1, uint32_t);
-RWHANDLER_READ(ioport_simple_readb, 1, uint32_t);
-RWHANDLER_WRITE(ioport_simple_writew, 2, uint32_t);
-RWHANDLER_READ(ioport_simple_readw, 2, uint32_t);
-RWHANDLER_WRITE(ioport_simple_writel, 4, uint32_t);
-RWHANDLER_READ(ioport_simple_readl, 4, uint32_t);
-
-int register_ioport_simple(ReadWriteHandler* handler,
- pio_addr_t start, int length, int size)
-{
- IOPortWriteFunc *write;
- IOPortReadFunc *read;
- int r;
- switch (size) {
- case 1:
- write = ioport_simple_writeb;
- read = ioport_simple_readb;
- break;
- case 2:
- write = ioport_simple_writew;
- read = ioport_simple_readw;
- break;
- default:
- write = ioport_simple_writel;
- read = ioport_simple_readl;
- }
- if (handler->write) {
- r = register_ioport_write(start, length, size, write, handler);
- if (r < 0) {
- return r;
- }
- }
- if (handler->read) {
- r = register_ioport_read(start, length, size, read, handler);
- if (r < 0) {
- return r;
- }
- }
- return 0;
-}
+++ /dev/null
-#ifndef READ_WRITE_HANDLER_H
-#define READ_WRITE_HANDLER_H
-
-#include "qemu-common.h"
-#include "ioport.h"
-
-typedef struct ReadWriteHandler ReadWriteHandler;
-
-/* len is guaranteed to be one of 1, 2 or 4, addr is guaranteed to fit in an
- * appropriate type (io/memory/etc). They do not need to be range checked. */
-typedef void WriteHandlerFunc(ReadWriteHandler *, pcibus_t addr,
- uint32_t value, int len);
-typedef uint32_t ReadHandlerFunc(ReadWriteHandler *, pcibus_t addr, int len);
-
-struct ReadWriteHandler {
- WriteHandlerFunc *write;
- ReadHandlerFunc *read;
-};
-
-/* Helpers for when we want to use a single routine with length. */
-/* CPU memory handler: both read and write must be present. */
-int cpu_register_io_memory_simple(ReadWriteHandler *, int endian);
-/* io port handler: can supply only read or write handlers. */
-int register_ioport_simple(ReadWriteHandler *,
- pio_addr_t start, int length, int size);
-
-#endif
bs = NULL;
while ((bs = bdrv_next(bs))) {
- if (bdrv_is_removable(bs) || bdrv_is_read_only(bs)) {
+ if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
continue;
}
bs = NULL;
while ((bs = bdrv_next(bs))) {
- if (bdrv_is_removable(bs) || bdrv_is_read_only(bs)) {
+ if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
continue;
}
p += last_out;
}
- dprintf(scd, 3, "%s: %lu/%zd\n", __func__, out, len + out);
+ dprintf(scd, 3, "%s: %zu/%zd\n", __func__, out, len + out);
trace_spice_vmc_write(out, len + out);
return out;
}
void helper_daa(void)
{
- int al, af, cf;
+ int old_al, al, af, cf;
int eflags;
eflags = helper_cc_compute_all(CC_OP);
cf = eflags & CC_C;
af = eflags & CC_A;
- al = EAX & 0xff;
+ old_al = al = EAX & 0xff;
eflags = 0;
if (((al & 0x0f) > 9 ) || af) {
al = (al + 6) & 0xff;
eflags |= CC_A;
}
- if ((al > 0x9f) || cf) {
+ if ((old_al > 0x99) || cf) {
al = (al + 0x60) & 0xff;
eflags |= CC_C;
}
sun4m_iommu_translate_pa(uint64_t addr, uint64_t pa, uint32_t iopte) "xlate dva %"PRIx64" => pa %"PRIx64" iopte = %x"
sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64""
+# hw/usb-bus.c
+usb_port_claim(int bus, const char *port) "bus %d, port %s"
+usb_port_attach(int bus, const char *port) "bus %d, port %s"
+usb_port_detach(int bus, const char *port) "bus %d, port %s"
+usb_port_release(int bus, const char *port) "bus %d, port %s"
+
# hw/usb-ehci.c
usb_ehci_reset(void) "=== RESET ==="
usb_ehci_mmio_readl(uint32_t addr, const char *str, uint32_t val) "rd mmio %04x [%s] = %x"
usb_ehci_qtd_fields(uint32_t addr, int tbytes, int cpage, int cerr, int pid) "QTD @ %08x - tbytes %d, cpage %d, cerr %d, pid %d"
usb_ehci_qtd_bits(uint32_t addr, int ioc, int active, int halt, int babble, int xacterr) "QTD @ %08x - ioc %d, active %d, halt %d, babble %d, xacterr %d"
usb_ehci_itd(uint32_t addr, uint32_t nxt, uint32_t mplen, uint32_t mult, uint32_t ep, uint32_t devaddr) "ITD @ %08x: next %08x - mplen %d, mult %d, ep %d, dev %d"
+usb_ehci_sitd(uint32_t addr, uint32_t nxt, uint32_t active) "ITD @ %08x: next %08x - active %d"
usb_ehci_port_attach(uint32_t port, const char *device) "attach port #%d - %s"
usb_ehci_port_detach(uint32_t port) "detach port #%d"
usb_ehci_port_reset(uint32_t port, int enable) "reset port #%d - %d"
usb_clear_device_feature(int addr, int feature, int ret) "dev %d, feature %d, ret %d"
usb_set_device_feature(int addr, int feature, int ret) "dev %d, feature %d, ret %d"
+# usb-linux.c
+usb_host_open_started(int bus, int addr) "dev %d:%d"
+usb_host_open_success(int bus, int addr) "dev %d:%d"
+usb_host_open_failure(int bus, int addr) "dev %d:%d"
+usb_host_disconnect(int bus, int addr) "dev %d:%d"
+usb_host_close(int bus, int addr) "dev %d:%d"
+usb_host_set_address(int bus, int addr, int config) "dev %d:%d, address %d"
+usb_host_set_config(int bus, int addr, int config) "dev %d:%d, config %d"
+usb_host_set_interface(int bus, int addr, int interface, int alt) "dev %d:%d, interface %d, alt %d"
+usb_host_claim_interfaces(int bus, int addr, int config, int nif) "dev %d:%d, config %d, nif %d"
+usb_host_release_interfaces(int bus, int addr) "dev %d:%d"
+usb_host_req_control(int bus, int addr, int req, int value, int index) "dev %d:%d, req 0x%x, value %d, index %d"
+usb_host_req_data(int bus, int addr, int in, int ep, int size) "dev %d:%d, in %d, ep %d, size %d"
+usb_host_req_complete(int bus, int addr, int status) "dev %d:%d, status %d"
+usb_host_urb_submit(int bus, int addr, void *aurb, int length, int more) "dev %d:%d, aurb %p, length %d, more %d"
+usb_host_urb_complete(int bus, int addr, void *aurb, int status, int length, int more) "dev %d:%d, aurb %p, status %d, length %d, more %d"
+usb_host_ep_set_halt(int bus, int addr, int ep) "dev %d:%d, ep %d"
+usb_host_ep_clear_halt(int bus, int addr, int ep) "dev %d:%d, ep %d"
+usb_host_ep_start_iso(int bus, int addr, int ep) "dev %d:%d, ep %d"
+usb_host_ep_stop_iso(int bus, int addr, int ep) "dev %d:%d, ep %d"
+usb_host_reset(int bus, int addr) "dev %d:%d"
+usb_host_auto_scan_enabled(void)
+usb_host_auto_scan_disabled(void)
+usb_host_claim_port(int bus, int hub, int port) "bus %d, hub addr %d, port %d"
+
# hw/scsi-bus.c
scsi_req_alloc(int target, int lun, int tag) "target %d lun %d tag %d"
scsi_req_data(int target, int lun, int tag, int len) "target %d lun %d tag %d len %d"
#include <spice-experimental.h>
#include <netdb.h>
+#include <pthread.h>
#include "qemu-common.h"
#include "qemu-spice.h"
static time_t auth_expires = TIME_MAX;
int using_spice = 0;
+static pthread_t me;
+
struct SpiceTimer {
QEMUTimer *timer;
QTAILQ_ENTRY(SpiceTimer) next;
QDict *server, *client;
QObject *data;
+ /*
+ * Spice server might have called us from spice worker thread
+ * context (happens on display channel disconnects). Spice should
+ * not do that. It isn't that easy to fix it in spice and even
+ * when it is fixed we still should cover the already released
+ * spice versions. So detect that we've been called from another
+ * thread and grab the iothread lock if so before calling qemu
+ * functions.
+ */
+ bool need_lock = !pthread_equal(me, pthread_self());
+ if (need_lock) {
+ qemu_mutex_lock_iothread();
+ }
+
client = qdict_new();
add_addr_info(client, &info->paddr, info->plen);
QOBJECT(client), QOBJECT(server));
monitor_protocol_event(qevent[event], data);
qobject_decref(data);
+
+ if (need_lock) {
+ qemu_mutex_unlock_iothread();
+ }
}
#else /* SPICE_INTERFACE_CORE_MINOR >= 3 */
spice_image_compression_t compression;
spice_wan_compression_t wan_compr;
- if (!opts) {
+ me = pthread_self();
+
+ if (!opts) {
return;
}
port = qemu_opt_get_number(opts, "port", 0);
SimpleSpiceDisplay *ssd = opaque;
if (running) {
+ ssd->running = true;
qemu_spice_start(ssd);
} else {
qemu_spice_stop(ssd);
+ ssd->running = false;
}
- ssd->running = running;
}
void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds)
#include "qemu-timer.h"
#include "monitor.h"
#include "sysemu.h"
+#include "trace.h"
#include <dirent.h>
#include <sys/ioctl.h>
void *data;
};
-typedef int USBScanFunc(void *opaque, int bus_num, int addr, char *port,
+typedef int USBScanFunc(void *opaque, int bus_num, int addr, const char *port,
int class_id, int vendor_id, int product_id,
const char *product_name, int speed);
typedef struct USBHostDevice {
USBDevice dev;
int fd;
+ int hub_fd;
uint8_t descr[8192];
int descr_len;
uint32_t iso_urb_count;
Notifier exit;
- struct endp_data endp_table[MAX_ENDPOINTS];
+ struct endp_data ep_in[MAX_ENDPOINTS];
+ struct endp_data ep_out[MAX_ENDPOINTS];
QLIST_HEAD(, AsyncURB) aurbs;
/* Host side address */
int addr;
char port[MAX_PORTLEN];
struct USBAutoFilter match;
+ int seen, errcount;
QTAILQ_ENTRY(USBHostDevice) next;
} USBHostDevice;
static void usb_host_auto_check(void *unused);
static int usb_host_read_file(char *line, size_t line_size,
const char *device_file, const char *device_name);
+static int usb_linux_update_endp_table(USBHostDevice *s);
-static struct endp_data *get_endp(USBHostDevice *s, int ep)
+static struct endp_data *get_endp(USBHostDevice *s, int pid, int ep)
{
- return s->endp_table + ep - 1;
+ struct endp_data *eps = pid == USB_TOKEN_IN ? s->ep_in : s->ep_out;
+ assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT);
+ assert(ep > 0 && ep <= MAX_ENDPOINTS);
+ return eps + ep - 1;
}
-static int is_isoc(USBHostDevice *s, int ep)
+static int is_isoc(USBHostDevice *s, int pid, int ep)
{
- return get_endp(s, ep)->type == USBDEVFS_URB_TYPE_ISO;
+ return get_endp(s, pid, ep)->type == USBDEVFS_URB_TYPE_ISO;
}
-static int is_valid(USBHostDevice *s, int ep)
+static int is_valid(USBHostDevice *s, int pid, int ep)
{
- return get_endp(s, ep)->type != INVALID_EP_TYPE;
+ return get_endp(s, pid, ep)->type != INVALID_EP_TYPE;
}
-static int is_halted(USBHostDevice *s, int ep)
+static int is_halted(USBHostDevice *s, int pid, int ep)
{
- return get_endp(s, ep)->halted;
+ return get_endp(s, pid, ep)->halted;
}
-static void clear_halt(USBHostDevice *s, int ep)
+static void clear_halt(USBHostDevice *s, int pid, int ep)
{
- get_endp(s, ep)->halted = 0;
+ trace_usb_host_ep_clear_halt(s->bus_num, s->addr, ep);
+ get_endp(s, pid, ep)->halted = 0;
}
-static void set_halt(USBHostDevice *s, int ep)
+static void set_halt(USBHostDevice *s, int pid, int ep)
{
- get_endp(s, ep)->halted = 1;
+ if (ep != 0) {
+ trace_usb_host_ep_set_halt(s->bus_num, s->addr, ep);
+ get_endp(s, pid, ep)->halted = 1;
+ }
}
-static int is_iso_started(USBHostDevice *s, int ep)
+static int is_iso_started(USBHostDevice *s, int pid, int ep)
{
- return get_endp(s, ep)->iso_started;
+ return get_endp(s, pid, ep)->iso_started;
}
-static void clear_iso_started(USBHostDevice *s, int ep)
+static void clear_iso_started(USBHostDevice *s, int pid, int ep)
{
- get_endp(s, ep)->iso_started = 0;
+ trace_usb_host_ep_stop_iso(s->bus_num, s->addr, ep);
+ get_endp(s, pid, ep)->iso_started = 0;
}
-static void set_iso_started(USBHostDevice *s, int ep)
+static void set_iso_started(USBHostDevice *s, int pid, int ep)
{
- struct endp_data *e = get_endp(s, ep);
+ struct endp_data *e = get_endp(s, pid, ep);
+
+ trace_usb_host_ep_start_iso(s->bus_num, s->addr, ep);
if (!e->iso_started) {
e->iso_started = 1;
e->inflight = 0;
}
}
-static int change_iso_inflight(USBHostDevice *s, int ep, int value)
+static int change_iso_inflight(USBHostDevice *s, int pid, int ep, int value)
{
- struct endp_data *e = get_endp(s, ep);
+ struct endp_data *e = get_endp(s, pid, ep);
e->inflight += value;
return e->inflight;
}
-static void set_iso_urb(USBHostDevice *s, int ep, AsyncURB *iso_urb)
+static void set_iso_urb(USBHostDevice *s, int pid, int ep, AsyncURB *iso_urb)
{
- get_endp(s, ep)->iso_urb = iso_urb;
+ get_endp(s, pid, ep)->iso_urb = iso_urb;
}
-static AsyncURB *get_iso_urb(USBHostDevice *s, int ep)
+static AsyncURB *get_iso_urb(USBHostDevice *s, int pid, int ep)
{
- return get_endp(s, ep)->iso_urb;
+ return get_endp(s, pid, ep)->iso_urb;
}
-static void set_iso_urb_idx(USBHostDevice *s, int ep, int i)
+static void set_iso_urb_idx(USBHostDevice *s, int pid, int ep, int i)
{
- get_endp(s, ep)->iso_urb_idx = i;
+ get_endp(s, pid, ep)->iso_urb_idx = i;
}
-static int get_iso_urb_idx(USBHostDevice *s, int ep)
+static int get_iso_urb_idx(USBHostDevice *s, int pid, int ep)
{
- return get_endp(s, ep)->iso_urb_idx;
+ return get_endp(s, pid, ep)->iso_urb_idx;
}
-static void set_iso_buffer_used(USBHostDevice *s, int ep, int i)
+static void set_iso_buffer_used(USBHostDevice *s, int pid, int ep, int i)
{
- get_endp(s, ep)->iso_buffer_used = i;
+ get_endp(s, pid, ep)->iso_buffer_used = i;
}
-static int get_iso_buffer_used(USBHostDevice *s, int ep)
+static int get_iso_buffer_used(USBHostDevice *s, int pid, int ep)
{
- return get_endp(s, ep)->iso_buffer_used;
+ return get_endp(s, pid, ep)->iso_buffer_used;
}
-static void set_max_packet_size(USBHostDevice *s, int ep, uint8_t *descriptor)
+static void set_max_packet_size(USBHostDevice *s, int pid, int ep,
+ uint8_t *descriptor)
{
int raw = descriptor[4] + (descriptor[5] << 8);
int size, microframes;
case 2: microframes = 3; break;
default: microframes = 1; break;
}
- get_endp(s, ep)->max_packet_size = size * microframes;
+ get_endp(s, pid, ep)->max_packet_size = size * microframes;
}
-static int get_max_packet_size(USBHostDevice *s, int ep)
+static int get_max_packet_size(USBHostDevice *s, int pid, int ep)
{
- return get_endp(s, ep)->max_packet_size;
+ return get_endp(s, pid, ep)->max_packet_size;
}
/*
static void do_disconnect(USBHostDevice *s)
{
- printf("husb: device %d.%d disconnected\n",
- s->bus_num, s->addr);
usb_host_close(s);
usb_host_auto_check(NULL);
}
}
return;
}
- if (errno == ENODEV && !s->closing) {
- do_disconnect(s);
+ if (errno == ENODEV) {
+ if (!s->closing) {
+ trace_usb_host_disconnect(s->bus_num, s->addr);
+ do_disconnect(s);
+ }
return;
}
- DPRINTF("husb: async. reap urb failed errno %d\n", errno);
+ perror("USBDEVFS_REAPURBNDELAY");
return;
}
anything else (it is handled further in usb_host_handle_iso_data) */
if (aurb->iso_frame_idx == -1) {
int inflight;
+ int pid = (aurb->urb.endpoint & USB_DIR_IN) ?
+ USB_TOKEN_IN : USB_TOKEN_OUT;
+ int ep = aurb->urb.endpoint & 0xf;
if (aurb->urb.status == -EPIPE) {
- set_halt(s, aurb->urb.endpoint & 0xf);
+ set_halt(s, pid, ep);
}
aurb->iso_frame_idx = 0;
urbs++;
- inflight = change_iso_inflight(s, aurb->urb.endpoint & 0xf, -1);
- if (inflight == 0 && is_iso_started(s, aurb->urb.endpoint & 0xf)) {
+ inflight = change_iso_inflight(s, pid, ep, -1);
+ if (inflight == 0 && is_iso_started(s, pid, ep)) {
fprintf(stderr, "husb: out of buffers for iso stream\n");
}
continue;
}
p = aurb->packet;
+ trace_usb_host_urb_complete(s->bus_num, s->addr, aurb, aurb->urb.status,
+ aurb->urb.actual_length, aurb->more);
if (p) {
switch (aurb->urb.status) {
break;
case -EPIPE:
- set_halt(s, p->devep);
+ set_halt(s, p->pid, p->devep);
p->result = USB_RET_STALL;
break;
}
if (aurb->urb.type == USBDEVFS_URB_TYPE_CONTROL) {
+ trace_usb_host_req_complete(s->bus_num, s->addr, p->result);
usb_generic_async_ctrl_complete(&s->dev, p);
} else if (!aurb->more) {
+ trace_usb_host_req_complete(s->bus_num, s->addr, p->result);
usb_packet_complete(&s->dev, p);
}
}
int interface, nb_interfaces;
int ret, i;
- if (configuration == 0) /* address state - ignore */
+ if (configuration == 0) { /* address state - ignore */
+ dev->ninterfaces = 0;
+ dev->configuration = 0;
return 1;
+ }
DPRINTF("husb: claiming interfaces. config %d\n", configuration);
}
config_descr_len = dev->descr[i];
- printf("husb: config #%d need %d\n", dev->descr[i + 5], configuration);
+ DPRINTF("husb: config #%d need %d\n", dev->descr[i + 5], configuration);
- if (configuration < 0 || configuration == dev->descr[i + 5]) {
+ if (configuration == dev->descr[i + 5]) {
configuration = dev->descr[i + 5];
break;
}
op = "USBDEVFS_CLAIMINTERFACE";
ret = ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface);
if (ret < 0) {
- if (errno == EBUSY) {
- printf("husb: update iface. device already grabbed\n");
- } else {
- perror("husb: failed to claim interface");
- }
goto fail;
}
}
- printf("husb: %d interfaces claimed for configuration %d\n",
- nb_interfaces, configuration);
+ trace_usb_host_claim_interfaces(dev->bus_num, dev->addr,
+ nb_interfaces, configuration);
dev->ninterfaces = nb_interfaces;
dev->configuration = configuration;
{
int ret, i;
- DPRINTF("husb: releasing interfaces\n");
+ trace_usb_host_release_interfaces(s->bus_num, s->addr);
for (i = 0; i < s->ninterfaces; i++) {
ret = ioctl(s->fd, USBDEVFS_RELEASEINTERFACE, &i);
if (ret < 0) {
- perror("husb: failed to release interface");
+ perror("USBDEVFS_RELEASEINTERFACE");
return 0;
}
}
-
return 1;
}
{
USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
- DPRINTF("husb: reset device %u.%u\n", s->bus_num, s->addr);
+ trace_usb_host_reset(s->bus_num, s->addr);
ioctl(s->fd, USBDEVFS_RESET);
- usb_host_claim_interfaces(s, s->configuration);
+ usb_host_claim_interfaces(s, 0);
+ usb_linux_update_endp_table(s);
}
static void usb_host_handle_destroy(USBDevice *dev)
USBHostDevice *s = (USBHostDevice *)dev;
usb_host_close(s);
+ if (s->hub_fd != -1) {
+ close(s->hub_fd);
+ }
QTAILQ_REMOVE(&hostdevs, s, next);
qemu_remove_exit_notifier(&s->exit);
}
-static int usb_linux_update_endp_table(USBHostDevice *s);
-
/* iso data is special, we need to keep enough urbs in flight to make sure
that the controller never runs out of them, otherwise the device will
likely suffer a buffer underrun / overrun. */
-static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, uint8_t ep, int in)
+static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, int pid, uint8_t ep)
{
AsyncURB *aurb;
- int i, j, len = get_max_packet_size(s, ep);
+ int i, j, len = get_max_packet_size(s, pid, ep);
aurb = g_malloc0(s->iso_urb_count * sizeof(*aurb));
for (i = 0; i < s->iso_urb_count; i++) {
aurb[i].urb.number_of_packets = ISO_FRAME_DESC_PER_URB;
for (j = 0 ; j < ISO_FRAME_DESC_PER_URB; j++)
aurb[i].urb.iso_frame_desc[j].length = len;
- if (in) {
+ if (pid == USB_TOKEN_IN) {
aurb[i].urb.endpoint |= 0x80;
/* Mark as fully consumed (idle) */
aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB;
}
}
- set_iso_urb(s, ep, aurb);
+ set_iso_urb(s, pid, ep, aurb);
return aurb;
}
-static void usb_host_stop_n_free_iso(USBHostDevice *s, uint8_t ep)
+static void usb_host_stop_n_free_iso(USBHostDevice *s, int pid, uint8_t ep)
{
AsyncURB *aurb;
int i, ret, killed = 0, free = 1;
- aurb = get_iso_urb(s, ep);
+ aurb = get_iso_urb(s, pid, ep);
if (!aurb) {
return;
}
if (aurb[i].iso_frame_idx == -1) {
ret = ioctl(s->fd, USBDEVFS_DISCARDURB, &aurb[i]);
if (ret < 0) {
- printf("husb: discard isoc in urb failed errno %d\n", errno);
+ perror("USBDEVFS_DISCARDURB");
free = 0;
continue;
}
g_free(aurb);
else
printf("husb: leaking iso urbs because of discard failure\n");
- set_iso_urb(s, ep, NULL);
- set_iso_urb_idx(s, ep, 0);
- clear_iso_started(s, ep);
+ set_iso_urb(s, pid, ep, NULL);
+ set_iso_urb_idx(s, pid, ep, 0);
+ clear_iso_started(s, pid, ep);
}
static int urb_status_to_usb_ret(int status)
int i, j, ret, max_packet_size, offset, len = 0;
uint8_t *buf;
- max_packet_size = get_max_packet_size(s, p->devep);
+ max_packet_size = get_max_packet_size(s, p->pid, p->devep);
if (max_packet_size == 0)
return USB_RET_NAK;
- aurb = get_iso_urb(s, p->devep);
+ aurb = get_iso_urb(s, p->pid, p->devep);
if (!aurb) {
- aurb = usb_host_alloc_iso(s, p->devep, in);
+ aurb = usb_host_alloc_iso(s, p->pid, p->devep);
}
- i = get_iso_urb_idx(s, p->devep);
+ i = get_iso_urb_idx(s, p->pid, p->devep);
j = aurb[i].iso_frame_idx;
if (j >= 0 && j < ISO_FRAME_DESC_PER_URB) {
if (in) {
}
} else {
len = p->iov.size;
- offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->devep);
+ offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->pid, p->devep);
/* Check the frame fits */
if (len > max_packet_size) {
usb_packet_copy(p, aurb[i].urb.buffer + offset, len);
aurb[i].urb.iso_frame_desc[j].length = len;
offset += len;
- set_iso_buffer_used(s, p->devep, offset);
+ set_iso_buffer_used(s, p->pid, p->devep, offset);
/* Start the stream once we have buffered enough data */
- if (!is_iso_started(s, p->devep) && i == 1 && j == 8) {
- set_iso_started(s, p->devep);
+ if (!is_iso_started(s, p->pid, p->devep) && i == 1 && j == 8) {
+ set_iso_started(s, p->pid, p->devep);
}
}
aurb[i].iso_frame_idx++;
if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
i = (i + 1) % s->iso_urb_count;
- set_iso_urb_idx(s, p->devep, i);
+ set_iso_urb_idx(s, p->pid, p->devep, i);
}
} else {
if (in) {
- set_iso_started(s, p->devep);
+ set_iso_started(s, p->pid, p->devep);
} else {
DPRINTF("hubs: iso out error no free buffer, dropping packet\n");
}
}
- if (is_iso_started(s, p->devep)) {
+ if (is_iso_started(s, p->pid, p->devep)) {
/* (Re)-submit all fully consumed / filled urbs */
for (i = 0; i < s->iso_urb_count; i++) {
if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
ret = ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]);
if (ret < 0) {
- printf("husb error submitting iso urb %d: %d\n", i, errno);
+ perror("USBDEVFS_SUBMITURB");
if (!in || len == 0) {
switch(errno) {
case ETIMEDOUT:
break;
}
aurb[i].iso_frame_idx = -1;
- change_iso_inflight(s, p->devep, +1);
+ change_iso_inflight(s, p->pid, p->devep, 1);
}
}
}
uint8_t *pbuf;
uint8_t ep;
- if (!is_valid(s, p->devep)) {
+ trace_usb_host_req_data(s->bus_num, s->addr,
+ p->pid == USB_TOKEN_IN,
+ p->devep, p->iov.size);
+
+ if (!is_valid(s, p->pid, p->devep)) {
+ trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
return USB_RET_NAK;
}
ep = p->devep;
}
- if (is_halted(s, p->devep)) {
- ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &ep);
+ if (is_halted(s, p->pid, p->devep)) {
+ unsigned int arg = ep;
+ ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &arg);
if (ret < 0) {
- DPRINTF("husb: failed to clear halt. ep 0x%x errno %d\n",
- ep, errno);
+ perror("USBDEVFS_CLEAR_HALT");
+ trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
return USB_RET_NAK;
}
- clear_halt(s, p->devep);
+ clear_halt(s, p->pid, p->devep);
}
- if (is_isoc(s, p->devep)) {
+ if (is_isoc(s, p->pid, p->devep)) {
return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
}
aurb->more = 1;
}
+ trace_usb_host_urb_submit(s->bus_num, s->addr, aurb,
+ urb->buffer_length, aurb->more);
ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
DPRINTF("husb: data submit: ep 0x%x, len %u, more %d, packet %p, aurb %p\n",
urb->endpoint, urb->buffer_length, aurb->more, p, aurb);
if (ret < 0) {
- DPRINTF("husb: submit failed. errno %d\n", errno);
+ perror("USBDEVFS_SUBMITURB");
async_free(aurb);
switch(errno) {
case ETIMEDOUT:
+ trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
return USB_RET_NAK;
case EPIPE:
default:
+ trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_STALL);
return USB_RET_STALL;
}
}
static int usb_host_set_address(USBHostDevice *s, int addr)
{
- DPRINTF("husb: ctrl set addr %u\n", addr);
+ trace_usb_host_set_address(s->bus_num, s->addr, addr);
s->dev.addr = addr;
return 0;
}
static int usb_host_set_config(USBHostDevice *s, int config)
{
+ trace_usb_host_set_config(s->bus_num, s->addr, config);
+
usb_host_release_interfaces(s);
int ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config);
return ctrl_error();
}
usb_host_claim_interfaces(s, config);
+ usb_linux_update_endp_table(s);
return 0;
}
struct usbdevfs_setinterface si;
int i, ret;
+ trace_usb_host_set_interface(s->bus_num, s->addr, iface, alt);
+
for (i = 1; i <= MAX_ENDPOINTS; i++) {
- if (is_isoc(s, i)) {
- usb_host_stop_n_free_iso(s, i);
+ if (is_isoc(s, USB_TOKEN_IN, i)) {
+ usb_host_stop_n_free_iso(s, USB_TOKEN_IN, i);
+ }
+ if (is_isoc(s, USB_TOKEN_OUT, i)) {
+ usb_host_stop_n_free_iso(s, USB_TOKEN_OUT, i);
}
}
*/
/* Note request is (bRequestType << 8) | bRequest */
- DPRINTF("husb: ctrl type 0x%x req 0x%x val 0x%x index %u len %u\n",
- request >> 8, request & 0xff, value, index, length);
+ trace_usb_host_req_control(s->bus_num, s->addr, request, value, index);
switch (request) {
case DeviceOutRequest | USB_REQ_SET_ADDRESS:
urb->usercontext = s;
+ trace_usb_host_urb_submit(s->bus_num, s->addr, aurb,
+ urb->buffer_length, aurb->more);
ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
DPRINTF("husb: submit ctrl. len %u aurb %p\n", urb->buffer_length, aurb);
return USB_RET_ASYNC;
}
-static int usb_linux_get_configuration(USBHostDevice *s)
-{
- uint8_t configuration;
- struct usb_ctrltransfer ct;
- int ret;
-
- if (usb_fs_type == USB_FS_SYS) {
- char device_name[32], line[1024];
- int configuration;
-
- sprintf(device_name, "%d-%s", s->bus_num, s->port);
-
- if (!usb_host_read_file(line, sizeof(line), "bConfigurationValue",
- device_name)) {
- goto usbdevfs;
- }
- if (sscanf(line, "%d", &configuration) != 1) {
- goto usbdevfs;
- }
- return configuration;
- }
-
-usbdevfs:
- ct.bRequestType = USB_DIR_IN;
- ct.bRequest = USB_REQ_GET_CONFIGURATION;
- ct.wValue = 0;
- ct.wIndex = 0;
- ct.wLength = 1;
- ct.data = &configuration;
- ct.timeout = 50;
-
- ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
- if (ret < 0) {
- perror("usb_linux_get_configuration");
- return -1;
- }
-
- /* in address state */
- if (configuration == 0) {
- return -1;
- }
-
- return configuration;
-}
-
static uint8_t usb_linux_get_alt_setting(USBHostDevice *s,
uint8_t configuration, uint8_t interface)
{
static int usb_linux_update_endp_table(USBHostDevice *s)
{
uint8_t *descriptors;
- uint8_t devep, type, configuration, alt_interface;
- int interface, length, i;
+ uint8_t devep, type, alt_interface;
+ int interface, length, i, ep, pid;
+ struct endp_data *epd;
- for (i = 0; i < MAX_ENDPOINTS; i++)
- s->endp_table[i].type = INVALID_EP_TYPE;
+ for (i = 0; i < MAX_ENDPOINTS; i++) {
+ s->ep_in[i].type = INVALID_EP_TYPE;
+ s->ep_out[i].type = INVALID_EP_TYPE;
+ }
- i = usb_linux_get_configuration(s);
- if (i < 0)
- return 1;
- configuration = i;
+ if (s->configuration == 0) {
+ /* not configured yet -- leave all endpoints disabled */
+ return 0;
+ }
/* get the desired configuration, interface, and endpoint descriptors
* from device description */
i = 0;
if (descriptors[i + 1] != USB_DT_CONFIG ||
- descriptors[i + 5] != configuration) {
- DPRINTF("invalid descriptor data - configuration\n");
+ descriptors[i + 5] != s->configuration) {
+ fprintf(stderr, "invalid descriptor data - configuration %d\n",
+ s->configuration);
return 1;
}
i += descriptors[i];
}
interface = descriptors[i + 2];
- alt_interface = usb_linux_get_alt_setting(s, configuration, interface);
+ alt_interface = usb_linux_get_alt_setting(s, s->configuration,
+ interface);
/* the current interface descriptor is the active interface
* and has endpoints */
}
devep = descriptors[i + 2];
- if ((devep & 0x0f) == 0) {
+ pid = (devep & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT;
+ ep = devep & 0xf;
+ if (ep == 0) {
fprintf(stderr, "usb-linux: invalid ep descriptor, ep == 0\n");
return 1;
}
break;
case 0x01:
type = USBDEVFS_URB_TYPE_ISO;
- set_max_packet_size(s, (devep & 0xf), descriptors + i);
+ set_max_packet_size(s, pid, ep, descriptors + i);
break;
case 0x02:
type = USBDEVFS_URB_TYPE_BULK;
DPRINTF("usb_host: malformed endpoint type\n");
type = USBDEVFS_URB_TYPE_BULK;
}
- s->endp_table[(devep & 0xf) - 1].type = type;
- s->endp_table[(devep & 0xf) - 1].halted = 0;
+ epd = get_endp(s, pid, ep);
+ assert(epd->type == INVALID_EP_TYPE);
+ epd->type = type;
+ epd->halted = 0;
i += descriptors[i];
}
}
static int usb_host_open(USBHostDevice *dev, int bus_num,
- int addr, char *port, const char *prod_name, int speed)
+ int addr, const char *port,
+ const char *prod_name, int speed)
{
int fd = -1, ret;
char buf[1024];
+ trace_usb_host_open_started(bus_num, addr);
+
if (dev->fd != -1) {
goto fail;
}
- printf("husb: open device %d.%d\n", bus_num, addr);
if (!usb_host_device_path) {
perror("husb: USB Host Device Path not set");
#endif
- /*
- * Initial configuration is -1 which makes us claim first
- * available config. We used to start with 1, which does not
- * always work. I've seen devices where first config starts
- * with 2.
- */
- if (!usb_host_claim_interfaces(dev, -1)) {
+ /* start unconfigured -- we'll wait for the guest to set a configuration */
+ if (!usb_host_claim_interfaces(dev, 0)) {
goto fail;
}
dev->dev.speedmask |= USB_SPEED_MASK_FULL;
}
- printf("husb: grabbed usb device %d.%d\n", bus_num, addr);
+ trace_usb_host_open_success(bus_num, addr);
if (!prod_name || prod_name[0] == '\0') {
snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
return 0;
fail:
+ trace_usb_host_open_failure(bus_num, addr);
if (dev->fd != -1) {
close(dev->fd);
dev->fd = -1;
return -1;
}
+ trace_usb_host_close(dev->bus_num, dev->addr);
+
qemu_set_fd_handler(dev->fd, NULL, NULL, NULL);
dev->closing = 1;
for (i = 1; i <= MAX_ENDPOINTS; i++) {
- if (is_isoc(dev, i)) {
- usb_host_stop_n_free_iso(dev, i);
+ if (is_isoc(dev, USB_TOKEN_IN, i)) {
+ usb_host_stop_n_free_iso(dev, USB_TOKEN_IN, i);
+ }
+ if (is_isoc(dev, USB_TOKEN_OUT, i)) {
+ usb_host_stop_n_free_iso(dev, USB_TOKEN_OUT, i);
}
}
async_complete(dev);
dev->auto_attach = 0;
s->fd = -1;
+ s->hub_fd = -1;
+
QTAILQ_INSERT_TAIL(&hostdevs, s, next);
s->exit.notify = usb_host_exit_notifier;
qemu_add_exit_notifier(&s->exit);
usb_host_auto_check(NULL);
+
+#ifdef USBDEVFS_CLAIM_PORT
+ if (s->match.bus_num != 0 && s->match.port != NULL) {
+ char *h, hub_name[64], line[1024];
+ int hub_addr, portnr, ret;
+
+ snprintf(hub_name, sizeof(hub_name), "%d-%s",
+ s->match.bus_num, s->match.port);
+
+ /* try strip off last ".$portnr" to get hub */
+ h = strrchr(hub_name, '.');
+ if (h != NULL) {
+ portnr = atoi(h+1);
+ *h = '\0';
+ } else {
+ /* no dot in there -> it is the root hub */
+ snprintf(hub_name, sizeof(hub_name), "usb%d",
+ s->match.bus_num);
+ portnr = atoi(s->match.port);
+ }
+
+ if (!usb_host_read_file(line, sizeof(line), "devnum",
+ hub_name)) {
+ goto out;
+ }
+ if (sscanf(line, "%d", &hub_addr) != 1) {
+ goto out;
+ }
+
+ if (!usb_host_device_path) {
+ goto out;
+ }
+ snprintf(line, sizeof(line), "%s/%03d/%03d",
+ usb_host_device_path, s->match.bus_num, hub_addr);
+ s->hub_fd = open(line, O_RDWR | O_NONBLOCK);
+ if (s->hub_fd < 0) {
+ goto out;
+ }
+
+ ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &portnr);
+ if (ret < 0) {
+ close(s->hub_fd);
+ s->hub_fd = -1;
+ goto out;
+ }
+
+ trace_usb_host_claim_port(s->match.bus_num, hub_addr, portnr);
+ }
+out:
+#endif
+
return 0;
}
+static const VMStateDescription vmstate_usb_host = {
+ .name = "usb-host",
+ .unmigratable = 1,
+};
+
static struct USBDeviceInfo usb_host_dev_info = {
.product_desc = "USB Host Device",
.qdev.name = "usb-host",
.qdev.size = sizeof(USBHostDevice),
+ .qdev.vmsd = &vmstate_usb_host,
.init = usb_host_initfn,
.handle_packet = usb_generic_handle_packet,
.cancel_packet = usb_host_async_cancel,
FILE *f = NULL;
char line[1024];
char buf[1024];
- int bus_num, addr, speed, device_count, class_id, product_id, vendor_id;
+ int bus_num, addr, speed, device_count;
+ int class_id, product_id, vendor_id, port;
char product_name[512];
int ret = 0;
}
device_count = 0;
- bus_num = addr = class_id = product_id = vendor_id = 0;
+ bus_num = addr = class_id = product_id = vendor_id = port = 0;
speed = -1; /* Can't get the speed from /[proc|dev]/bus/usb/devices */
for(;;) {
if (fgets(line, sizeof(line), f) == NULL) {
goto fail;
}
bus_num = atoi(buf);
+ if (get_tag_value(buf, sizeof(buf), line, "Port=", " ") < 0) {
+ goto fail;
+ }
+ port = atoi(buf);
if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0) {
goto fail;
}
}
if (device_count && (vendor_id || product_id)) {
/* Add the last device. */
- ret = func(opaque, bus_num, addr, 0, class_id, vendor_id,
+ if (port > 0) {
+ snprintf(buf, sizeof(buf), "%d", port);
+ } else {
+ snprintf(buf, sizeof(buf), "?");
+ }
+ ret = func(opaque, bus_num, addr, buf, class_id, vendor_id,
product_id, product_name, speed);
}
the_end:
static QEMUTimer *usb_auto_timer;
-static int usb_host_auto_scan(void *opaque, int bus_num, int addr, char *port,
+static int usb_host_auto_scan(void *opaque, int bus_num,
+ int addr, const char *port,
int class_id, int vendor_id, int product_id,
const char *product_name, int speed)
{
continue;
}
/* We got a match */
+ s->seen++;
+ if (s->errcount >= 3) {
+ return 0;
+ }
/* Already attached ? */
if (s->fd != -1) {
}
DPRINTF("husb: auto open: bus_num %d addr %d\n", bus_num, addr);
- usb_host_open(s, bus_num, addr, port, product_name, speed);
+ if (usb_host_open(s, bus_num, addr, port, product_name, speed) < 0) {
+ s->errcount++;
+ }
break;
}
if (s->fd == -1) {
unconnected++;
}
+ if (s->seen == 0) {
+ s->errcount = 0;
+ }
+ s->seen = 0;
}
if (unconnected == 0) {
/* nothing to watch */
if (usb_auto_timer) {
qemu_del_timer(usb_auto_timer);
+ trace_usb_host_auto_scan_disabled();
}
return;
}
if (!usb_auto_timer) {
return;
}
+ trace_usb_host_auto_scan_enabled();
}
qemu_mod_timer(usb_auto_timer, qemu_get_clock_ms(rt_clock) + 2000);
}
return p->class_name;
}
-static void usb_info_device(Monitor *mon, int bus_num, int addr, char *port,
+static void usb_info_device(Monitor *mon, int bus_num,
+ int addr, const char *port,
int class_id, int vendor_id, int product_id,
const char *product_name,
int speed)
}
static int usb_host_info_device(void *opaque, int bus_num, int addr,
- char *path, int class_id,
+ const char *path, int class_id,
int vendor_id, int product_id,
const char *product_name,
int speed)