Merge branch 'master' of git://git.qemu.org/qemu

This commit is contained in:
malc 2011-07-23 00:50:37 +04:00
commit 670acc9bf2
207 changed files with 12416 additions and 3493 deletions

View File

@ -106,6 +106,8 @@ audio/audio.o audio/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS)
QEMU_CFLAGS+=$(CURL_CFLAGS)
QEMU_CFLAGS+=$(GLIB_CFLAGS)
ui/cocoa.o: ui/cocoa.m
ui/sdl.o audio/sdlaudio.o ui/sdl_zoom.o baum.o: QEMU_CFLAGS += $(SDL_CFLAGS)
@ -138,7 +140,7 @@ endif
######################################################################
qemu-img.o: qemu-img-cmds.h
qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o cmd.o: $(GENERATED_HEADERS)
qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o cmd.o qemu-ga.o: $(GENERATED_HEADERS)
qemu-img$(EXESUF): qemu-img.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o
@ -160,19 +162,54 @@ check-qlist: check-qlist.o qlist.o qint.o $(CHECK_PROG_DEPS)
check-qfloat: check-qfloat.o qfloat.o $(CHECK_PROG_DEPS)
check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o error.o qerror.o qemu-error.o $(CHECK_PROG_DEPS)
$(qapi-obj-y): $(GENERATED_HEADERS)
qapi-dir := qapi-generated
test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
$(qapi-dir)/test-qapi-types.c: $(qapi-dir)/test-qapi-types.h
$(qapi-dir)/test-qapi-types.h: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
$(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py -o "$(qapi-dir)" -p "test-" < $<, " GEN $@")
$(qapi-dir)/test-qapi-visit.c: $(qapi-dir)/test-qapi-visit.h
$(qapi-dir)/test-qapi-visit.h: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
$(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "test-" < $<, " GEN $@")
$(qapi-dir)/test-qmp-commands.h: $(qapi-dir)/test-qmp-marshal.c
$(qapi-dir)/test-qmp-marshal.c: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
$(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "test-" < $<, " GEN $@")
$(qapi-dir)/qga-qapi-types.c: $(qapi-dir)/qga-qapi-types.h
$(qapi-dir)/qga-qapi-types.h: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-types.py
$(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@")
$(qapi-dir)/qga-qapi-visit.c: $(qapi-dir)/qga-qapi-visit.h
$(qapi-dir)/qga-qapi-visit.h: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-visit.py
$(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@")
$(qapi-dir)/qga-qmp-marshal.c: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-commands.py
$(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@")
test-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
test-visitor: test-visitor.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h test-qmp-marshal.c test-qmp-commands.h) $(qapi-obj-y)
test-qmp-commands: test-qmp-commands.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
QGALIB=qga/guest-agent-command-state.o qga/guest-agent-commands.o
qemu-ga.o: $(addprefix $(qapi-dir)/, qga-qapi-types.c qga-qapi-types.h qga-qapi-visit.c qga-qmp-marshal.c) $(qapi-obj-y)
qemu-ga$(EXESUF): qemu-ga.o $(QGALIB) qemu-tool.o qemu-error.o error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) $(qapi-obj-y) qemu-timer-common.o qemu-sockets.o module.o qapi/qmp-dispatch.o qapi/qmp-registry.o $(qapi-dir)/qga-qapi-visit.o $(qapi-dir)/qga-qapi-types.o $(qapi-dir)/qga-qmp-marshal.o
QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
clean:
# avoid old build problems by removing potentially incorrect old files
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
rm -f qemu-options.def
rm -f *.o *.d *.a *.lo $(TOOLS) TAGS cscope.* *.pod *~ */*~
rm -f *.o *.d *.a *.lo $(TOOLS) qemu-ga TAGS cscope.* *.pod *~ */*~
rm -Rf .libs
rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d
rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d qapi/*.o qapi/*.d qga/*.o qga/*.d
rm -f qemu-img-cmds.h
rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp
rm -f trace-dtrace.dtrace trace-dtrace.dtrace-timestamp
rm -f trace-dtrace.h trace-dtrace.h-timestamp
rm -rf $(qapi-dir)
$(MAKE) -C tests clean
for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard; do \
if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
@ -361,4 +398,4 @@ tarbin:
$(mandir)/man8/qemu-nbd.8
# Include automatically generated dependency files
-include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d)
-include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d qapi/*.d qga/*.d)

View File

@ -155,8 +155,8 @@ slirp-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o
common-obj-$(CONFIG_SLIRP) += $(addprefix slirp/, $(slirp-obj-y))
# xen backend driver support
common-obj-$(CONFIG_XEN) += xen_backend.o xen_devconfig.o
common-obj-$(CONFIG_XEN) += xen_console.o xenfb.o xen_disk.o xen_nic.o
common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o xenfb.o xen_disk.o xen_nic.o
######################################################################
# libuser
@ -171,7 +171,7 @@ user-obj-y += cutils.o cache-utils.o
hw-obj-y =
hw-obj-y += vl.o loader.o
hw-obj-$(CONFIG_VIRTIO) += virtio.o virtio-console.o
hw-obj-$(CONFIG_VIRTIO) += virtio-console.o
hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
hw-obj-y += fw_cfg.o
hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o
@ -205,6 +205,7 @@ hw-obj-$(CONFIG_HPET) += hpet.o
hw-obj-$(CONFIG_APPLESMC) += applesmc.o
hw-obj-$(CONFIG_SMARTCARD) += usb-ccid.o ccid-card-passthru.o
hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
hw-obj-$(CONFIG_USB_REDIR) += usb-redir.o
# PPC devices
hw-obj-$(CONFIG_OPENPIC) += openpic.o
@ -372,7 +373,15 @@ endif
libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o card_7816.o
######################################################################
# qapi
qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o qapi-dealloc-visitor.o
qapi-nested-y += qmp-registry.o qmp-dispatch.o
qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
vl.o: QEMU_CFLAGS+=$(GLIB_CFLAGS)

View File

@ -3,6 +3,7 @@
GENERATED_HEADERS = config-target.h
CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
include ../config-host.mak
include config-devices.mak
@ -94,7 +95,7 @@ tcg/tcg.o: cpu.h
# HELPER_CFLAGS is used for all the code compiled with static register
# variables
%_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
op_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
# Note: this is a workaround. The real fix is to avoid compiling
# cpu_signal_handler() in user-exec.c.
@ -190,7 +191,7 @@ obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o
# virtio has to be here due to weird dependency between PCI and virtio-net.
# need to fix this properly
obj-$(CONFIG_NO_PCI) += pci-stub.o
obj-$(CONFIG_VIRTIO) += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
obj-y += vhost_net.o
obj-$(CONFIG_VHOST_NET) += vhost.o
obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
@ -203,21 +204,11 @@ QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
QEMU_CFLAGS += $(GLIB_CFLAGS)
# xen backend driver support
obj-i386-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
ifeq ($(TARGET_BASE_ARCH), i386)
CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
else
CONFIG_NO_XEN = y
endif
# xen support
CONFIG_NO_XEN_MAPCACHE = $(if $(subst n,,$(CONFIG_XEN_MAPCACHE)),n,y)
obj-i386-$(CONFIG_XEN) += xen-all.o
obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o xen-mapcache.o
obj-$(CONFIG_NO_XEN) += xen-stub.o
obj-i386-$(CONFIG_XEN_MAPCACHE) += xen-mapcache.o
obj-$(CONFIG_NO_XEN_MAPCACHE) += xen-mapcache-stub.o
obj-i386-$(CONFIG_XEN) += xen_platform.o
@ -260,7 +251,7 @@ endif
obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
obj-ppc-y += ppc440.o ppc440_bamboo.o
# PowerPC E500 boards
obj-ppc-y += ppce500_mpc8544ds.o
obj-ppc-y += ppce500_mpc8544ds.o mpc8544_guts.o
# PowerPC 440 Xilinx ML507 reference board.
obj-ppc-y += virtex_ml507.o
obj-ppc-$(CONFIG_KVM) += kvm_ppc.o

View File

@ -34,6 +34,7 @@
#else
#include "qemu-common.h"
#include "gdbstub.h"
#include "hw/arm-misc.h"
#endif
#define SYS_OPEN 0x01
@ -369,68 +370,88 @@ uint32_t do_arm_semihosting(CPUState *env)
return syscall_err;
#endif
case SYS_GET_CMDLINE:
#ifdef CONFIG_USER_ONLY
/* Build a commandline from the original argv. */
{
char *arm_cmdline_buffer;
const char *host_cmdline_buffer;
/* Build a command-line from the original argv.
*
* The inputs are:
* * ARG(0), pointer to a buffer of at least the size
* specified in ARG(1).
* * ARG(1), size of the buffer pointed to by ARG(0) in
* bytes.
*
* The outputs are:
* * ARG(0), pointer to null-terminated string of the
* command line.
* * ARG(1), length of the string pointed to by ARG(0).
*/
char *output_buffer;
size_t input_size = ARG(1);
size_t output_size;
int status = 0;
/* Compute the size of the output string. */
#if !defined(CONFIG_USER_ONLY)
output_size = strlen(ts->boot_info->kernel_filename)
+ 1 /* Separating space. */
+ strlen(ts->boot_info->kernel_cmdline)
+ 1; /* Terminating null byte. */
#else
unsigned int i;
unsigned int arm_cmdline_len = ARG(1);
unsigned int host_cmdline_len =
ts->info->arg_end-ts->info->arg_start;
if (!arm_cmdline_len || host_cmdline_len > arm_cmdline_len) {
return -1; /* not enough space to store command line */
}
if (!host_cmdline_len) {
output_size = ts->info->arg_end - ts->info->arg_start;
if (!output_size) {
/* We special-case the "empty command line" case (argc==0).
Just provide the terminating 0. */
arm_cmdline_buffer = lock_user(VERIFY_WRITE, ARG(0), 1, 0);
arm_cmdline_buffer[0] = 0;
unlock_user(arm_cmdline_buffer, ARG(0), 1);
/* Adjust the commandline length argument. */
SET_ARG(1, 0);
return 0;
output_size = 1;
}
/* lock the buffers on the ARM side */
arm_cmdline_buffer =
lock_user(VERIFY_WRITE, ARG(0), host_cmdline_len, 0);
host_cmdline_buffer =
lock_user(VERIFY_READ, ts->info->arg_start,
host_cmdline_len, 1);
if (arm_cmdline_buffer && host_cmdline_buffer)
{
/* the last argument is zero-terminated;
no need for additional termination */
memcpy(arm_cmdline_buffer, host_cmdline_buffer,
host_cmdline_len);
/* separate arguments by white spaces */
for (i = 0; i < host_cmdline_len-1; i++) {
if (arm_cmdline_buffer[i] == 0) {
arm_cmdline_buffer[i] = ' ';
}
}
/* Adjust the commandline length argument. */
SET_ARG(1, host_cmdline_len-1);
}
/* Unlock the buffers on the ARM side. */
unlock_user(arm_cmdline_buffer, ARG(0), host_cmdline_len);
unlock_user((void*)host_cmdline_buffer, ts->info->arg_start, 0);
/* Return success if we could return a commandline. */
return (arm_cmdline_buffer && host_cmdline_buffer) ? 0 : -1;
}
#else
return -1;
#endif
if (output_size > input_size) {
/* Not enough space to store command-line arguments. */
return -1;
}
/* Adjust the command-line length. */
SET_ARG(1, output_size - 1);
/* Lock the buffer on the ARM side. */
output_buffer = lock_user(VERIFY_WRITE, ARG(0), output_size, 0);
if (!output_buffer) {
return -1;
}
/* Copy the command-line arguments. */
#if !defined(CONFIG_USER_ONLY)
pstrcpy(output_buffer, output_size, ts->boot_info->kernel_filename);
pstrcat(output_buffer, output_size, " ");
pstrcat(output_buffer, output_size, ts->boot_info->kernel_cmdline);
#else
if (output_size == 1) {
/* Empty command-line. */
output_buffer[0] = '\0';
goto out;
}
if (copy_from_user(output_buffer, ts->info->arg_start,
output_size)) {
status = -1;
goto out;
}
/* Separate arguments by white spaces. */
for (i = 0; i < output_size - 1; i++) {
if (output_buffer[i] == 0) {
output_buffer[i] = ' ';
}
}
out:
#endif
/* Unlock the buffer on the ARM side. */
unlock_user(output_buffer, ARG(0), output_size);
return status;
}
case SYS_HEAPINFO:
{
uint32_t *ptr;

19
block.c
View File

@ -1146,6 +1146,25 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
return ret;
}
/**
* Length of a allocated file in bytes. Sparse files are counted by actual
* allocated space. Return < 0 if error or unknown.
*/
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs)
{
BlockDriver *drv = bs->drv;
if (!drv) {
return -ENOMEDIUM;
}
if (drv->bdrv_get_allocated_file_size) {
return drv->bdrv_get_allocated_file_size(bs);
}
if (bs->file) {
return bdrv_get_allocated_file_size(bs->file);
}
return -ENOTSUP;
}
/**
* Length of a file in bytes. Return < 0 if error or unknown.
*/

View File

@ -89,6 +89,7 @@ int bdrv_write_sync(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
int bdrv_truncate(BlockDriverState *bs, int64_t offset);
int64_t bdrv_getlength(BlockDriverState *bs);
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs);
int bdrv_commit(BlockDriverState *bs);

View File

@ -312,3 +312,15 @@ found:
c->entries[i].dirty = true;
}
bool qcow2_cache_set_writethrough(BlockDriverState *bs, Qcow2Cache *c,
bool enable)
{
bool old = c->writethrough;
if (!old && enable) {
qcow2_cache_flush(bs, c);
}
c->writethrough = enable;
return old;
}

View File

@ -705,8 +705,15 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
BDRVQcowState *s = bs->opaque;
uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, l1_allocated;
int64_t old_offset, old_l2_offset;
int i, j, l1_modified, nb_csectors, refcount;
int i, j, l1_modified = 0, nb_csectors, refcount;
int ret;
bool old_l2_writethrough, old_refcount_writethrough;
/* Switch caches to writeback mode during update */
old_l2_writethrough =
qcow2_cache_set_writethrough(bs, s->l2_table_cache, false);
old_refcount_writethrough =
qcow2_cache_set_writethrough(bs, s->refcount_block_cache, false);
l2_table = NULL;
l1_table = NULL;
@ -720,7 +727,11 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
l1_allocated = 1;
if (bdrv_pread(bs->file, l1_table_offset,
l1_table, l1_size2) != l1_size2)
{
ret = -EIO;
goto fail;
}
for(i = 0;i < l1_size; i++)
be64_to_cpus(&l1_table[i]);
} else {
@ -729,7 +740,6 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
l1_allocated = 0;
}
l1_modified = 0;
for(i = 0; i < l1_size; i++) {
l2_offset = l1_table[i];
if (l2_offset) {
@ -773,6 +783,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
}
if (refcount < 0) {
ret = -EIO;
goto fail;
}
}
@ -803,6 +814,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
refcount = get_refcount(bs, l2_offset >> s->cluster_bits);
}
if (refcount < 0) {
ret = -EIO;
goto fail;
} else if (refcount == 1) {
l2_offset |= QCOW_OFLAG_COPIED;
@ -813,6 +825,18 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
}
}
}
ret = 0;
fail:
if (l2_table) {
qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
}
/* Enable writethrough cache mode again */
qcow2_cache_set_writethrough(bs, s->l2_table_cache, old_l2_writethrough);
qcow2_cache_set_writethrough(bs, s->refcount_block_cache,
old_refcount_writethrough);
if (l1_modified) {
for(i = 0; i < l1_size; i++)
cpu_to_be64s(&l1_table[i]);
@ -824,15 +848,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
}
if (l1_allocated)
qemu_free(l1_table);
return 0;
fail:
if (l2_table) {
qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
}
if (l1_allocated)
qemu_free(l1_table);
return -EIO;
return ret;
}

View File

@ -228,6 +228,8 @@ int qcow2_read_snapshots(BlockDriverState *bs);
Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables,
bool writethrough);
int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c);
bool qcow2_cache_set_writethrough(BlockDriverState *bs, Qcow2Cache *c,
bool enable);
void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table);
int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);

View File

@ -46,6 +46,8 @@
#include <sys/dkio.h>
#endif
#ifdef __linux__
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <linux/cdrom.h>
@ -791,6 +793,17 @@ static int64_t raw_getlength(BlockDriverState *bs)
}
#endif
static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
{
struct stat st;
BDRVRawState *s = bs->opaque;
if (fstat(s->fd, &st) < 0) {
return -errno;
}
return (int64_t)st.st_blocks * 512;
}
static int raw_create(const char *filename, QEMUOptionParameter *options)
{
int fd;
@ -886,6 +899,8 @@ static BlockDriver bdrv_file = {
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
.create_options = raw_create_options,
};
@ -1154,6 +1169,8 @@ static BlockDriver bdrv_host_device = {
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_getlength = raw_getlength,
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
/* generic scsi device */
#ifdef __linux__
@ -1188,6 +1205,7 @@ static int floppy_probe_device(const char *filename)
int fd, ret;
int prio = 0;
struct floppy_struct fdparam;
struct stat st;
if (strstart(filename, "/dev/fd", NULL))
prio = 50;
@ -1196,12 +1214,17 @@ static int floppy_probe_device(const char *filename)
if (fd < 0) {
goto out;
}
ret = fstat(fd, &st);
if (ret == -1 || !S_ISBLK(st.st_mode)) {
goto outc;
}
/* Attempt to detect via a floppy specific ioctl */
ret = ioctl(fd, FDGETPRM, &fdparam);
if (ret >= 0)
prio = 100;
outc:
close(fd);
out:
return prio;
@ -1269,6 +1292,8 @@ static BlockDriver bdrv_host_floppy = {
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_getlength = raw_getlength,
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
/* removable device support */
.bdrv_is_inserted = floppy_is_inserted,
@ -1290,17 +1315,23 @@ static int cdrom_probe_device(const char *filename)
{
int fd, ret;
int prio = 0;
struct stat st;
fd = open(filename, O_RDONLY | O_NONBLOCK);
if (fd < 0) {
goto out;
}
ret = fstat(fd, &st);
if (ret == -1 || !S_ISBLK(st.st_mode)) {
goto outc;
}
/* Attempt to detect via a CDROM specific ioctl */
ret = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
if (ret >= 0)
prio = 100;
outc:
close(fd);
out:
return prio;
@ -1366,6 +1397,8 @@ static BlockDriver bdrv_host_cdrom = {
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_getlength = raw_getlength,
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
/* removable device support */
.bdrv_is_inserted = cdrom_is_inserted,
@ -1489,6 +1522,8 @@ static BlockDriver bdrv_host_cdrom = {
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_getlength = raw_getlength,
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
/* removable device support */
.bdrv_is_inserted = cdrom_is_inserted,

View File

@ -213,6 +213,31 @@ static int64_t raw_getlength(BlockDriverState *bs)
return l.QuadPart;
}
static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
{
typedef DWORD (WINAPI * get_compressed_t)(const char *filename,
DWORD * high);
get_compressed_t get_compressed;
struct _stati64 st;
const char *filename = bs->filename;
/* WinNT support GetCompressedFileSize to determine allocate size */
get_compressed =
(get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"),
"GetCompressedFileSizeA");
if (get_compressed) {
DWORD high, low;
low = get_compressed(filename, &high);
if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR) {
return (((int64_t) high) << 32) + low;
}
}
if (_stati64(filename, &st) < 0) {
return -1;
}
return st.st_size;
}
static int raw_create(const char *filename, QEMUOptionParameter *options)
{
int fd;
@ -257,6 +282,8 @@ static BlockDriver bdrv_file = {
.bdrv_write = raw_write,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
.create_options = raw_create_options,
};
@ -419,6 +446,8 @@ static BlockDriver bdrv_host_device = {
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_getlength = raw_getlength,
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
};
static void bdrv_file_init(void)

View File

@ -1286,6 +1286,49 @@ static int do_sd_create(char *filename, int64_t vdi_size,
return 0;
}
static int sd_prealloc(const char *filename)
{
BlockDriverState *bs = NULL;
uint32_t idx, max_idx;
int64_t vdi_size;
void *buf = qemu_mallocz(SD_DATA_OBJ_SIZE);
int ret;
ret = bdrv_file_open(&bs, filename, BDRV_O_RDWR);
if (ret < 0) {
goto out;
}
vdi_size = bdrv_getlength(bs);
if (vdi_size < 0) {
ret = vdi_size;
goto out;
}
max_idx = DIV_ROUND_UP(vdi_size, SD_DATA_OBJ_SIZE);
for (idx = 0; idx < max_idx; idx++) {
/*
* The created image can be a cloned image, so we need to read
* a data from the source image.
*/
ret = bdrv_pread(bs, idx * SD_DATA_OBJ_SIZE, buf, SD_DATA_OBJ_SIZE);
if (ret < 0) {
goto out;
}
ret = bdrv_pwrite(bs, idx * SD_DATA_OBJ_SIZE, buf, SD_DATA_OBJ_SIZE);
if (ret < 0) {
goto out;
}
}
out:
if (bs) {
bdrv_delete(bs);
}
qemu_free(buf);
return ret;
}
static int sd_create(const char *filename, QEMUOptionParameter *options)
{
int ret;
@ -1295,13 +1338,15 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
BDRVSheepdogState s;
char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
uint32_t snapid;
int prealloc = 0;
const char *vdiname;
strstart(filename, "sheepdog:", (const char **)&filename);
strstart(filename, "sheepdog:", &vdiname);
memset(&s, 0, sizeof(s));
memset(vdi, 0, sizeof(vdi));
memset(tag, 0, sizeof(tag));
if (parse_vdiname(&s, filename, vdi, &snapid, tag) < 0) {
if (parse_vdiname(&s, vdiname, vdi, &snapid, tag) < 0) {
error_report("invalid filename");
return -EINVAL;
}
@ -1311,6 +1356,16 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
vdi_size = options->value.n;
} else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
backing_file = options->value.s;
} else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
if (!options->value.s || !strcmp(options->value.s, "off")) {
prealloc = 0;
} else if (!strcmp(options->value.s, "full")) {
prealloc = 1;
} else {
error_report("Invalid preallocation mode: '%s'",
options->value.s);
return -EINVAL;
}
}
options++;
}
@ -1348,7 +1403,12 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
bdrv_delete(bs);
}
return do_sd_create((char *)vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port);
ret = do_sd_create(vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port);
if (!prealloc || ret) {
return ret;
}
return sd_prealloc(filename);
}
static void sd_close(BlockDriverState *bs)
@ -1984,6 +2044,11 @@ static QEMUOptionParameter sd_create_options[] = {
.type = OPT_STRING,
.help = "File name of a base image"
},
{
.name = BLOCK_OPT_PREALLOC,
.type = OPT_STRING,
.help = "Preallocation mode (allowed values: off, full)"
},
{ NULL }
};

File diff suppressed because it is too large Load Diff

View File

@ -39,6 +39,7 @@
#define BLOCK_OPT_CLUSTER_SIZE "cluster_size"
#define BLOCK_OPT_TABLE_SIZE "table_size"
#define BLOCK_OPT_PREALLOC "preallocation"
#define BLOCK_OPT_SUBFMT "subformat"
typedef struct AIOPool {
void (*cancel)(BlockDriverAIOCB *acb);
@ -85,6 +86,7 @@ struct BlockDriver {
const char *protocol_name;
int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
int64_t (*bdrv_getlength)(BlockDriverState *bs);
int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs);
int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);

View File

@ -240,14 +240,6 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
int ret;
translation = BIOS_ATA_TRANSLATION_AUTO;
if (default_to_scsi) {
type = IF_SCSI;
pstrcpy(devname, sizeof(devname), "scsi");
} else {
type = IF_IDE;
pstrcpy(devname, sizeof(devname), "ide");
}
media = MEDIA_DISK;
/* extract parameters */
@ -273,7 +265,11 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
error_report("unsupported bus type '%s'", buf);
return NULL;
}
} else {
type = default_to_scsi ? IF_SCSI : IF_IDE;
pstrcpy(devname, sizeof(devname), if_name[type]);
}
max_devs = if_max_devs[type];
if (cyls || heads || secs) {
@ -314,7 +310,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
media = MEDIA_DISK;
} else if (!strcmp(buf, "cdrom")) {
if (cyls || secs || heads) {
error_report("'%s' invalid physical CHS format", buf);
error_report("CHS can't be set with media=%s", buf);
return NULL;
}
media = MEDIA_CDROM;
@ -572,7 +568,7 @@ void do_commit(Monitor *mon, const QDict *qdict)
int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
const char *device = qdict_get_str(qdict, "device");
const char *filename = qdict_get_try_str(qdict, "snapshot_file");
const char *filename = qdict_get_try_str(qdict, "snapshot-file");
const char *format = qdict_get_try_str(qdict, "format");
BlockDriverState *bs;
BlockDriver *drv, *old_drv, *proto_drv;
@ -581,7 +577,7 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
char old_filename[1024];
if (!filename) {
qerror_report(QERR_MISSING_PARAMETER, "snapshot_file");
qerror_report(QERR_MISSING_PARAMETER, "snapshot-file");
ret = -1;
goto out;
}

View File

@ -866,7 +866,7 @@ int main(int argc, char **argv)
int mask;
const CPULogItem *item;
mask = cpu_str_to_log_mask(r);
mask = cpu_str_to_log_mask(log_mask);
if (!mask) {
printf("Log items (comma separated):\n");
for (item = cpu_log_items; item->mask != 0; item++) {

34
compiler.h Normal file
View File

@ -0,0 +1,34 @@
/* public domain */
#ifndef COMPILER_H
#define COMPILER_H
#include "config-host.h"
#define QEMU_NORETURN __attribute__ ((__noreturn__))
#ifdef CONFIG_GCC_ATTRIBUTE_WARN_UNUSED_RESULT
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
#define QEMU_WARN_UNUSED_RESULT
#endif
#define QEMU_BUILD_BUG_ON(x) \
typedef char qemu_build_bug_on__##__LINE__[(x)?-1:1];
#if defined __GNUC__
# if (__GNUC__ < 4) || \
defined(__GNUC_MINOR__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 4)
/* gcc versions before 4.4.x don't support gnu_printf, so use printf. */
# define GCC_ATTR __attribute__((__unused__, format(printf, 1, 2)))
# define GCC_FMT_ATTR(n, m) __attribute__((format(printf, n, m)))
# else
/* Use gnu_printf when supported (qemu uses standard format strings). */
# define GCC_ATTR __attribute__((__unused__, format(gnu_printf, 1, 2)))
# define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m)))
# endif
#else
#define GCC_ATTR /**/
#define GCC_FMT_ATTR(n, m)
#endif
#endif /* COMPILER_H */

46
configure vendored
View File

@ -177,6 +177,7 @@ spice=""
rbd=""
smartcard=""
smartcard_nss=""
usb_redir=""
opengl=""
# parse CC options first
@ -743,6 +744,10 @@ for opt do
;;
--enable-smartcard-nss) smartcard_nss="yes"
;;
--disable-usb-redir) usb_redir="no"
;;
--enable-usb-redir) usb_redir="yes"
;;
*) echo "ERROR: unknown option $opt"; show_help="yes"
;;
esac
@ -1018,6 +1023,8 @@ echo " --disable-smartcard disable smartcard support"
echo " --enable-smartcard enable smartcard support"
echo " --disable-smartcard-nss disable smartcard nss support"
echo " --enable-smartcard-nss enable smartcard nss support"
echo " --disable-usb-redir disable usb network redirection support"
echo " --enable-usb-redir enable usb network redirection support"
echo ""
echo "NOTE: The object files are built at the place where configure is launched"
exit 1
@ -1802,6 +1809,18 @@ EOF
fi
fi
##########################################
# glib support probe
if $pkg_config --modversion gthread-2.0 gio-2.0 > /dev/null 2>&1 ; then
glib_cflags=`$pkg_config --cflags gthread-2.0 gio-2.0 2>/dev/null`
glib_libs=`$pkg_config --libs gthread-2.0 gio-2.0 2>/dev/null`
libs_softmmu="$glib_libs $libs_softmmu"
libs_tools="$glib_libs $libs_tools"
else
echo "glib-2.0 required to compile QEMU"
exit 1
fi
##########################################
# pthread probe
PTHREADLIBS_LIST="-lpthread -lpthreadGC2"
@ -2371,6 +2390,22 @@ if test "$smartcard" = "no" ; then
smartcard_nss="no"
fi
# check for usbredirparser for usb network redirection support
if test "$usb_redir" != "no" ; then
if $pkg_config libusbredirparser >/dev/null 2>&1 ; then
usb_redir="yes"
usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null)
usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null)
QEMU_CFLAGS="$QEMU_CFLAGS $usb_redir_cflags"
LIBS="$LIBS $usb_redir_libs"
else
if test "$usb_redir" = "yes"; then
feature_not_found "usb-redir"
fi
usb_redir="no"
fi
fi
##########################################
##########################################
@ -2520,6 +2555,7 @@ if test "$softmmu" = yes ; then
tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
tools="qemu-nbd\$(EXESUF) $tools"
tools="qemu-ga\$(EXESUF) $tools"
if [ "$check_utests" = "yes" ]; then
tools="check-qint check-qstring check-qdict check-qlist $tools"
tools="check-qfloat check-qjson $tools"
@ -2617,6 +2653,7 @@ echo "spice support $spice"
echo "rbd support $rbd"
echo "xfsctl support $xfs"
echo "nss used $smartcard_nss"
echo "usb net redir $usb_redir"
echo "OpenGL support $opengl"
if test $sdl_too_old = "yes"; then
@ -2849,8 +2886,9 @@ if test "$bluez" = "yes" ; then
echo "CONFIG_BLUEZ=y" >> $config_host_mak
echo "BLUEZ_CFLAGS=$bluez_cflags" >> $config_host_mak
fi
echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
if test "$xen" = "yes" ; then
echo "CONFIG_XEN=y" >> $config_host_mak
echo "CONFIG_XEN_BACKEND=y" >> $config_host_mak
echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version" >> $config_host_mak
fi
if test "$io_thread" = "yes" ; then
@ -2910,6 +2948,10 @@ if test "$smartcard_nss" = "yes" ; then
echo "CONFIG_SMARTCARD_NSS=y" >> $config_host_mak
fi
if test "$usb_redir" = "yes" ; then
echo "CONFIG_USB_REDIR=y" >> $config_host_mak
fi
if test "$opengl" = "yes" ; then
echo "CONFIG_OPENGL=y" >> $config_host_mak
fi
@ -3473,6 +3515,8 @@ DIRS="tests tests/cris slirp audio block net pc-bios/optionrom"
DIRS="$DIRS pc-bios/spapr-rtas"
DIRS="$DIRS roms/seabios roms/vgabios"
DIRS="$DIRS fsdev ui"
DIRS="$DIRS qapi"
DIRS="$DIRS qga"
FILES="Makefile tests/Makefile"
FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"

View File

@ -65,7 +65,7 @@ void qemu_ram_free_from_ptr(ram_addr_t addr);
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
/* This should only be used for ram local to a device. */
void *qemu_get_ram_ptr(ram_addr_t addr);
void *qemu_ram_ptr_length(target_phys_addr_t addr, target_phys_addr_t *size);
void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size);
/* Same but slower, to use for migration, where the order of
* RAMBlocks must not change. */
void *qemu_safe_ram_ptr(ram_addr_t addr);
@ -134,15 +134,30 @@ void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size);
void qemu_flush_coalesced_mmio_buffer(void);
uint32_t ldub_phys(target_phys_addr_t addr);
uint32_t lduw_le_phys(target_phys_addr_t addr);
uint32_t lduw_be_phys(target_phys_addr_t addr);
uint32_t ldl_le_phys(target_phys_addr_t addr);
uint32_t ldl_be_phys(target_phys_addr_t addr);
uint64_t ldq_le_phys(target_phys_addr_t addr);
uint64_t ldq_be_phys(target_phys_addr_t addr);
void stb_phys(target_phys_addr_t addr, uint32_t val);
void stw_le_phys(target_phys_addr_t addr, uint32_t val);
void stw_be_phys(target_phys_addr_t addr, uint32_t val);
void stl_le_phys(target_phys_addr_t addr, uint32_t val);
void stl_be_phys(target_phys_addr_t addr, uint32_t val);
void stq_le_phys(target_phys_addr_t addr, uint64_t val);
void stq_be_phys(target_phys_addr_t addr, uint64_t val);
#ifdef NEED_CPU_H
uint32_t lduw_phys(target_phys_addr_t addr);
uint32_t ldl_phys(target_phys_addr_t addr);
uint64_t ldq_phys(target_phys_addr_t addr);
void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val);
void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val);
void stb_phys(target_phys_addr_t addr, uint32_t val);
void stw_phys(target_phys_addr_t addr, uint32_t val);
void stl_phys(target_phys_addr_t addr, uint32_t val);
void stq_phys(target_phys_addr_t addr, uint64_t val);
#endif
void cpu_physical_memory_write_rom(target_phys_addr_t addr,
const uint8_t *buf, int len);

View File

@ -587,6 +587,10 @@ int cpu_exec(CPUState *env)
/* reset soft MMU for next block (it can currently
only be set by a memory fault) */
} /* for(;;) */
} else {
/* Reload env after longjmp - the compiler may have smashed all
* local variables as longjmp is marked 'noreturn'. */
env = cpu_single_env;
}
} /* for(;;) */

12
cpus.c
View File

@ -396,12 +396,19 @@ static int qemu_signal_init(void)
sigaddset(&set, SIGUSR2);
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
/*
* SIG_IPI must be blocked in the main thread and must not be caught
* by sigwait() in the signal thread. Otherwise, the cpu thread will
* not catch it reliably.
*/
sigemptyset(&set);
sigaddset(&set, SIG_IPI);
pthread_sigmask(SIG_BLOCK, &set, NULL);
sigemptyset(&set);
sigaddset(&set, SIGIO);
sigaddset(&set, SIGALRM);
sigaddset(&set, SIG_IPI);
sigaddset(&set, SIGBUS);
pthread_sigmask(SIG_BLOCK, &set, NULL);
#else
sigemptyset(&set);
sigaddset(&set, SIGBUS);
@ -414,6 +421,7 @@ static int qemu_signal_init(void)
sigaddset(&set, SIGALRM);
}
#endif
pthread_sigmask(SIG_BLOCK, &set, NULL);
sigfd = qemu_signalfd(&set);
if (sigfd == -1) {

View File

@ -819,7 +819,7 @@ int main(int argc, char **argv)
int mask;
CPULogItem *item;
mask = cpu_str_to_log_mask(r);
mask = cpu_str_to_log_mask(log_mask);
if (!mask) {
printf("Log items (comma separated):\n");
for (item = cpu_log_items; item->mask != 0; item++) {

37
docs/ich9-ehci-uhci.cfg Normal file
View File

@ -0,0 +1,37 @@
###########################################################################
#
# You can pass this file directly to qemu using the -readconfig
# command line switch.
#
# This config file creates a EHCI adapter with companion UHCI
# controllers as multifunction device in PCI slot "1d".
#
# Specify "bus=ehci.0" when creating usb devices to hook them up
# there.
#
[device "ehci"]
driver = "ich9-usb-ehci1"
addr = "1d.7"
multifunction = "on"
[device "uhci-1"]
driver = "ich9-usb-uhci1"
addr = "1d.0"
multifunction = "on"
masterbus = "ehci.0"
firstport = "0"
[device "uhci-2"]
driver = "ich9-usb-uhci2"
addr = "1d.1"
multifunction = "on"
masterbus = "ehci.0"
firstport = "2"
[device "uhci-3"]
driver = "ich9-usb-uhci3"
addr = "1d.2"
multifunction = "on"
masterbus = "ehci.0"
firstport = "4"

316
docs/qapi-code-gen.txt Normal file
View File

@ -0,0 +1,316 @@
= How to use the QAPI code generator =
* Note: as of this writing, QMP does not use QAPI. Eventually QMP
commands will be converted to use QAPI internally. The following
information describes QMP/QAPI as it will exist after the
conversion.
QAPI is a native C API within QEMU which provides management-level
functionality to internal/external users. For external
users/processes, this interface is made available by a JSON-based
QEMU Monitor protocol that is provided by the QMP server.
To map QMP-defined interfaces to the native C QAPI implementations,
a JSON-based schema is used to define types and function
signatures, and a set of scripts is used to generate types/signatures,
and marshaling/dispatch code. The QEMU Guest Agent also uses these
scripts, paired with a seperate schema, to generate
marshaling/dispatch code for the guest agent server running in the
guest.
This document will describe how the schemas, scripts, and resulting
code is used.
== QMP/Guest agent schema ==
This file defines the types, commands, and events used by QMP. It should
fully describe the interface used by QMP.
This file is designed to be loosely based on JSON although it's technically
executable Python. While dictionaries are used, they are parsed as
OrderedDicts so that ordering is preserved.
There are two basic syntaxes used, type definitions and command definitions.
The first syntax defines a type and is represented by a dictionary. There are
two kinds of types that are supported: complex user-defined types, and enums.
A complex type is a dictionary containing a single key who's value is a
dictionary. This corresponds to a struct in C or an Object in JSON. An
example of a complex type is:
{ 'type': 'MyType',
'data' { 'member1': 'str', 'member2': 'int', '*member3': 'str } }
The use of '*' as a prefix to the name means the member is optional. Optional
members should always be added to the end of the dictionary to preserve
backwards compatibility.
An enumeration type is a dictionary containing a single key who's value is a
list of strings. An example enumeration is:
{ 'enum': 'MyEnum', 'data': [ 'value1', 'value2', 'value3' ] }
Generally speaking, complex types and enums should always use CamelCase for
the type names.
Commands are defined by using a list containing three members. The first
member is the command name, the second member is a dictionary containing
arguments, and the third member is the return type.
An example command is:
{ 'command': 'my-command',
'data': { 'arg1': 'str', '*arg2': 'str' },
'returns': 'str' ]
Command names should be all lower case with words separated by a hyphen.
== Code generation ==
Schemas are fed into 3 scripts to generate all the code/files that, paired
with the core QAPI libraries, comprise everything required to take JSON
commands read in by a QMP/guest agent server, unmarshal the arguments into
the underlying C types, call into the corresponding C function, and map the
response back to a QMP/guest agent response to be returned to the user.
As an example, we'll use the following schema, which describes a single
complex user-defined type (which will produce a C struct, along with a list
node structure that can be used to chain together a list of such types in
case we want to accept/return a list of this type with a command), and a
command which takes that type as a parameter and returns the same type:
mdroth@illuin:~/w/qemu2.git$ cat example-schema.json
{ 'type': 'UserDefOne',
'data': { 'integer': 'int', 'string': 'str' } }
{ 'command': 'my-command',
'data': {'arg1': 'UserDefOne'},
'returns': 'UserDefOne' }
mdroth@illuin:~/w/qemu2.git$
=== scripts/qapi-types.py ===
Used to generate the C types defined by a schema. The following files are
created:
$(prefix)qapi-types.h - C types corresponding to types defined in
the schema you pass in
$(prefix)qapi-types.c - Cleanup functions for the above C types
The $(prefix) is an optional parameter used as a namespace to keep the
generated code from one schema/code-generation separated from others so code
can be generated/used from multiple schemas without clobbering previously
created code.
Example:
mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-types.py \
--output-dir="qapi-generated" --prefix="example-" < example-schema.json
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.c
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
#include "qapi/qapi-dealloc-visitor.h"
#include "example-qapi-types.h"
#include "example-qapi-visit.h"
void qapi_free_UserDefOne(UserDefOne * obj)
{
QapiDeallocVisitor *md;
Visitor *v;
if (!obj) {
return;
}
md = qapi_dealloc_visitor_new();
v = qapi_dealloc_get_visitor(md);
visit_type_UserDefOne(v, &obj, NULL, NULL);
qapi_dealloc_visitor_cleanup(md);
}
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.h
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
#ifndef QAPI_GENERATED_EXAMPLE_QAPI_TYPES
#define QAPI_GENERATED_EXAMPLE_QAPI_TYPES
#include "qapi/qapi-types-core.h"
typedef struct UserDefOne UserDefOne;
typedef struct UserDefOneList
{
UserDefOne *value;
struct UserDefOneList *next;
} UserDefOneList;
struct UserDefOne
{
int64_t integer;
char * string;
};
void qapi_free_UserDefOne(UserDefOne * obj);
#endif
=== scripts/qapi-visit.py ===
Used to generate the visitor functions used to walk through and convert
a QObject (as provided by QMP) to a native C data structure and
vice-versa, as well as the visitor function used to dealloc a complex
schema-defined C type.
The following files are generated:
$(prefix)qapi-visit.c: visitor function for a particular C type, used
to automagically convert QObjects into the
corresponding C type and vice-versa, as well
as for deallocating memory for an existing C
type
$(prefix)qapi-visit.h: declarations for previously mentioned visitor
functions
Example:
mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-visit.py \
--output-dir="qapi-generated" --prefix="example-" < example-schema.json
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.c
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
#include "example-qapi-visit.h"
void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp)
{
visit_start_struct(m, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), errp);
visit_type_int(m, (obj && *obj) ? &(*obj)->integer : NULL, "integer", errp);
visit_type_str(m, (obj && *obj) ? &(*obj)->string : NULL, "string", errp);
visit_end_struct(m, errp);
}
void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp)
{
GenericList *i;
visit_start_list(m, name, errp);
for (i = visit_next_list(m, (GenericList **)obj, errp); i; i = visit_next_list(m, &i, errp)) {
UserDefOneList *native_i = (UserDefOneList *)i;
visit_type_UserDefOne(m, &native_i->value, NULL, errp);
}
visit_end_list(m, errp);
}
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.h
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
#ifndef QAPI_GENERATED_EXAMPLE_QAPI_VISIT
#define QAPI_GENERATED_EXAMPLE_QAPI_VISIT
#include "qapi/qapi-visit-core.h"
#include "example-qapi-types.h"
void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp);
void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp);
#endif
mdroth@illuin:~/w/qemu2.git$
=== scripts/qapi-commands.py ===
Used to generate the marshaling/dispatch functions for the commands defined
in the schema. The following files are generated:
$(prefix)qmp-marshal.c: command marshal/dispatch functions for each
QMP command defined in the schema. Functions
generated by qapi-visit.py are used to
convert QObjects recieved from the wire into
function parameters, and uses the same
visitor functions to convert native C return
values to QObjects from transmission back
over the wire.
$(prefix)qmp-commands.h: Function prototypes for the QMP commands
specified in the schema.
Example:
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-marshal.c
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
#include "qemu-objects.h"
#include "qapi/qmp-core.h"
#include "qapi/qapi-visit-core.h"
#include "qapi/qmp-output-visitor.h"
#include "qapi/qmp-input-visitor.h"
#include "qapi/qapi-dealloc-visitor.h"
#include "example-qapi-types.h"
#include "example-qapi-visit.h"
#include "example-qmp-commands.h"
static void qmp_marshal_output_my_command(UserDefOne * ret_in, QObject **ret_out, Error **errp)
{
QapiDeallocVisitor *md = qapi_dealloc_visitor_new();
QmpOutputVisitor *mo = qmp_output_visitor_new();
Visitor *v;
v = qmp_output_get_visitor(mo);
visit_type_UserDefOne(v, &ret_in, "unused", errp);
v = qapi_dealloc_get_visitor(md);
visit_type_UserDefOne(v, &ret_in, "unused", errp);
qapi_dealloc_visitor_cleanup(md);
*ret_out = qmp_output_get_qobject(mo);
}
static void qmp_marshal_input_my_command(QmpState *qmp__sess, QDict *args, QObject **ret, Error **errp)
{
UserDefOne * retval = NULL;
QmpInputVisitor *mi;
QapiDeallocVisitor *md;
Visitor *v;
UserDefOne * arg1 = NULL;
mi = qmp_input_visitor_new(QOBJECT(args));
v = qmp_input_get_visitor(mi);
visit_type_UserDefOne(v, &arg1, "arg1", errp);
if (error_is_set(errp)) {
goto out;
}
retval = qmp_my_command(arg1, errp);
qmp_marshal_output_my_command(retval, ret, errp);
out:
md = qapi_dealloc_visitor_new();
v = qapi_dealloc_get_visitor(md);
visit_type_UserDefOne(v, &arg1, "arg1", errp);
qapi_dealloc_visitor_cleanup(md);
return;
}
static void qmp_init_marshal(void)
{
qmp_register_command("my-command", qmp_marshal_input_my_command);
}
qapi_init(qmp_init_marshal);
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-commands.h
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
#ifndef QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
#define QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
#include "example-qapi-types.h"
#include "error.h"
UserDefOne * qmp_my_command(UserDefOne * arg1, Error **errp);
#endif
mdroth@illuin:~/w/qemu2.git$

View File

@ -2,11 +2,13 @@
USB 2.0 Quick Start
===================
The QEMU EHCI Adapter does *not* support companion controllers. That
implies there are two completely separate USB busses: One USB 1.1 bus
driven by the UHCI controller and one USB 2.0 bus driven by the EHCI
controller. Devices must be attached to the correct controller
manually.
The QEMU EHCI Adapter can be used with and without companion
controllers. See below for the companion controller mode.
When not running in companion controller mode there are two completely
separate USB busses: One USB 1.1 bus driven by the UHCI controller and
one USB 2.0 bus driven by the EHCI controller. Devices must be
attached to the correct controller manually.
The '-usb' switch will make qemu create the UHCI controller as part of
the PIIX3 chipset. The USB 1.1 bus will carry the name "usb.0".
@ -32,6 +34,27 @@ This attaches a usb tablet to the UHCI adapter and a usb mass storage
device to the EHCI adapter.
Companion controller support
----------------------------
Companion controller support has been added recently. The operational
model described above with two completely separate busses still works
fine. Additionally the UHCI and OHCI controllers got the ability to
attach to a usb bus created by EHCI as companion controllers. This is
done by specifying the masterbus and firstport properties. masterbus
specifies the bus name the controller should attach to. firstport
specifies the first port the controller should attach to, which is
needed as usually one ehci controller with six ports has three uhci
companion controllers with two ports each.
There is a config file in docs which will do all this for you, just
try ...
qemu -readconfig docs/ich9-ehci-uhci.cfg
... then use "bus=ehci.0" to assign your usb devices to that bus.
More USB tips & tricks
======================

View File

@ -12,6 +12,7 @@
#ifndef ERROR_H
#define ERROR_H
#include "compiler.h"
#include <stdbool.h>
/**

View File

@ -44,11 +44,7 @@ struct TranslationBlock;
typedef struct TranslationBlock TranslationBlock;
/* XXX: make safe guess about sizes */
#if (HOST_LONG_BITS == 32) && (TARGET_LONG_BITS == 64)
#define MAX_OP_PER_INSTR 128
#else
#define MAX_OP_PER_INSTR 96
#endif
#define MAX_OP_PER_INSTR 208
#if HOST_LONG_BITS == 32
#define MAX_OPC_PARAM_PER_ARG 2
@ -327,7 +323,7 @@ static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong add
pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK;
if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
do_unassigned_access(addr, 0, 1, 0, 4);
cpu_unassigned_access(env1, addr, 0, 1, 0, 4);
#else
cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
#endif

272
exec.c
View File

@ -555,8 +555,8 @@ static void code_gen_alloc(unsigned long tb_size)
#endif
#endif /* !USE_STATIC_CODE_GEN_BUFFER */
map_exec(code_gen_prologue, sizeof(code_gen_prologue));
code_gen_buffer_max_size = code_gen_buffer_size -
(TCG_MAX_OP_SIZE * OPC_MAX_SIZE);
code_gen_buffer_max_size = code_gen_buffer_size -
(TCG_MAX_OP_SIZE * OPC_BUF_SIZE);
code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
}
@ -2953,7 +2953,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
abort();
}
#else
if (xen_mapcache_enabled()) {
if (xen_enabled()) {
xen_ram_alloc(new_block->offset, size);
} else {
new_block->host = qemu_vmalloc(size);
@ -3019,8 +3019,8 @@ void qemu_ram_free(ram_addr_t addr)
#if defined(TARGET_S390X) && defined(CONFIG_KVM)
munmap(block->host, block->length);
#else
if (xen_mapcache_enabled()) {
qemu_invalidate_entry(block->host);
if (xen_enabled()) {
xen_invalidate_map_cache_entry(block->host);
} else {
qemu_vfree(block->host);
}
@ -3112,15 +3112,16 @@ void *qemu_get_ram_ptr(ram_addr_t addr)
QLIST_REMOVE(block, next);
QLIST_INSERT_HEAD(&ram_list.blocks, block, next);
}
if (xen_mapcache_enabled()) {
if (xen_enabled()) {
/* We need to check if the requested address is in the RAM
* because we don't want to map the entire memory in QEMU.
* In that case just map until the end of the page.
*/
if (block->offset == 0) {
return qemu_map_cache(addr, 0, 0);
return xen_map_cache(addr, 0, 0);
} else if (block->host == NULL) {
block->host = qemu_map_cache(block->offset, block->length, 1);
block->host =
xen_map_cache(block->offset, block->length, 1);
}
}
return block->host + (addr - block->offset);
@ -3142,15 +3143,16 @@ void *qemu_safe_ram_ptr(ram_addr_t addr)
QLIST_FOREACH(block, &ram_list.blocks, next) {
if (addr - block->offset < block->length) {
if (xen_mapcache_enabled()) {
if (xen_enabled()) {
/* We need to check if the requested address is in the RAM
* because we don't want to map the entire memory in QEMU.
* In that case just map until the end of the page.
*/
if (block->offset == 0) {
return qemu_map_cache(addr, 0, 0);
return xen_map_cache(addr, 0, 0);
} else if (block->host == NULL) {
block->host = qemu_map_cache(block->offset, block->length, 1);
block->host =
xen_map_cache(block->offset, block->length, 1);
}
}
return block->host + (addr - block->offset);
@ -3165,11 +3167,14 @@ void *qemu_safe_ram_ptr(ram_addr_t addr)
/* Return a host pointer to guest's ram. Similar to qemu_get_ram_ptr
* but takes a size argument */
void *qemu_ram_ptr_length(target_phys_addr_t addr, target_phys_addr_t *size)
void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size)
{
if (xen_mapcache_enabled())
return qemu_map_cache(addr, *size, 1);
else {
if (*size == 0) {
return NULL;
}
if (xen_enabled()) {
return xen_map_cache(addr, *size, 1);
} else {
RAMBlock *block;
QLIST_FOREACH(block, &ram_list.blocks, next) {
@ -3182,9 +3187,6 @@ void *qemu_ram_ptr_length(target_phys_addr_t addr, target_phys_addr_t *size)
fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
abort();
*size = 0;
return NULL;
}
}
@ -3198,8 +3200,8 @@ int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
RAMBlock *block;
uint8_t *host = ptr;
if (xen_mapcache_enabled()) {
*ram_addr = qemu_ram_addr_from_mapcache(ptr);
if (xen_enabled()) {
*ram_addr = xen_ram_addr_from_mapcache(ptr);
return 0;
}
@ -3236,7 +3238,7 @@ static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
#endif
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 0, 0, 0, 1);
cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 1);
#endif
return 0;
}
@ -3247,7 +3249,7 @@ static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
#endif
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 0, 0, 0, 2);
cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 2);
#endif
return 0;
}
@ -3258,7 +3260,7 @@ static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
#endif
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 0, 0, 0, 4);
cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 4);
#endif
return 0;
}
@ -3269,7 +3271,7 @@ static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_
printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
#endif
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 1, 0, 0, 1);
cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 1);
#endif
}
@ -3279,7 +3281,7 @@ static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_
printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
#endif
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 1, 0, 0, 2);
cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 2);
#endif
}
@ -3289,7 +3291,7 @@ static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_
printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
#endif
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 1, 0, 0, 4);
cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 4);
#endif
}
@ -4050,7 +4052,9 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
target_phys_addr_t page;
unsigned long pd;
PhysPageDesc *p;
target_phys_addr_t addr1 = addr;
ram_addr_t raddr = ULONG_MAX;
ram_addr_t rlen;
void *ret;
while (len > 0) {
page = addr & TARGET_PAGE_MASK;
@ -4078,13 +4082,18 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
*plen = l;
return bounce.buffer;
}
if (!todo) {
raddr = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
}
len -= l;
addr += l;
todo += l;
}
*plen = todo;
return qemu_ram_ptr_length(addr1, plen);
rlen = todo;
ret = qemu_ram_ptr_length(raddr, &rlen);
*plen = rlen;
return ret;
}
/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
@ -4113,8 +4122,8 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
access_len -= l;
}
}
if (xen_mapcache_enabled()) {
qemu_invalidate_entry(buffer);
if (xen_enabled()) {
xen_invalidate_map_cache_entry(buffer);
}
return;
}
@ -4127,7 +4136,8 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
}
/* warning: addr must be aligned */
uint32_t ldl_phys(target_phys_addr_t addr)
static inline uint32_t ldl_phys_internal(target_phys_addr_t addr,
enum device_endian endian)
{
int io_index;
uint8_t *ptr;
@ -4149,17 +4159,52 @@ uint32_t ldl_phys(target_phys_addr_t addr)
if (p)
addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
#if defined(TARGET_WORDS_BIGENDIAN)
if (endian == DEVICE_LITTLE_ENDIAN) {
val = bswap32(val);
}
#else
if (endian == DEVICE_BIG_ENDIAN) {
val = bswap32(val);
}
#endif
} else {
/* RAM case */
ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
(addr & ~TARGET_PAGE_MASK);
val = ldl_p(ptr);
switch (endian) {
case DEVICE_LITTLE_ENDIAN:
val = ldl_le_p(ptr);
break;
case DEVICE_BIG_ENDIAN:
val = ldl_be_p(ptr);
break;
default:
val = ldl_p(ptr);
break;
}
}
return val;
}
uint32_t ldl_phys(target_phys_addr_t addr)
{
return ldl_phys_internal(addr, DEVICE_NATIVE_ENDIAN);
}
uint32_t ldl_le_phys(target_phys_addr_t addr)
{
return ldl_phys_internal(addr, DEVICE_LITTLE_ENDIAN);
}
uint32_t ldl_be_phys(target_phys_addr_t addr)
{
return ldl_phys_internal(addr, DEVICE_BIG_ENDIAN);
}
/* warning: addr must be aligned */
uint64_t ldq_phys(target_phys_addr_t addr)
static inline uint64_t ldq_phys_internal(target_phys_addr_t addr,
enum device_endian endian)
{
int io_index;
uint8_t *ptr;
@ -4180,6 +4225,9 @@ uint64_t ldq_phys(target_phys_addr_t addr)
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
if (p)
addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
/* XXX This is broken when device endian != cpu endian.
Fix and add "endian" variable check */
#ifdef TARGET_WORDS_BIGENDIAN
val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
@ -4191,11 +4239,36 @@ uint64_t ldq_phys(target_phys_addr_t addr)
/* RAM case */
ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
(addr & ~TARGET_PAGE_MASK);
val = ldq_p(ptr);
switch (endian) {
case DEVICE_LITTLE_ENDIAN:
val = ldq_le_p(ptr);
break;
case DEVICE_BIG_ENDIAN:
val = ldq_be_p(ptr);
break;
default:
val = ldq_p(ptr);
break;
}
}
return val;
}
uint64_t ldq_phys(target_phys_addr_t addr)
{
return ldq_phys_internal(addr, DEVICE_NATIVE_ENDIAN);
}
uint64_t ldq_le_phys(target_phys_addr_t addr)
{
return ldq_phys_internal(addr, DEVICE_LITTLE_ENDIAN);
}
uint64_t ldq_be_phys(target_phys_addr_t addr)
{
return ldq_phys_internal(addr, DEVICE_BIG_ENDIAN);
}
/* XXX: optimize */
uint32_t ldub_phys(target_phys_addr_t addr)
{
@ -4205,7 +4278,8 @@ uint32_t ldub_phys(target_phys_addr_t addr)
}
/* warning: addr must be aligned */
uint32_t lduw_phys(target_phys_addr_t addr)
static inline uint32_t lduw_phys_internal(target_phys_addr_t addr,
enum device_endian endian)
{
int io_index;
uint8_t *ptr;
@ -4227,15 +4301,49 @@ uint32_t lduw_phys(target_phys_addr_t addr)
if (p)
addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
#if defined(TARGET_WORDS_BIGENDIAN)
if (endian == DEVICE_LITTLE_ENDIAN) {
val = bswap16(val);
}
#else
if (endian == DEVICE_BIG_ENDIAN) {
val = bswap16(val);
}
#endif
} else {
/* RAM case */
ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
(addr & ~TARGET_PAGE_MASK);
val = lduw_p(ptr);
switch (endian) {
case DEVICE_LITTLE_ENDIAN:
val = lduw_le_p(ptr);
break;
case DEVICE_BIG_ENDIAN:
val = lduw_be_p(ptr);
break;
default:
val = lduw_p(ptr);
break;
}
}
return val;
}
uint32_t lduw_phys(target_phys_addr_t addr)
{
return lduw_phys_internal(addr, DEVICE_NATIVE_ENDIAN);
}
uint32_t lduw_le_phys(target_phys_addr_t addr)
{
return lduw_phys_internal(addr, DEVICE_LITTLE_ENDIAN);
}
uint32_t lduw_be_phys(target_phys_addr_t addr)
{
return lduw_phys_internal(addr, DEVICE_BIG_ENDIAN);
}
/* warning: addr must be aligned. The ram page is not masked as dirty
and the code inside is not invalidated. It is useful if the dirty
bits are used to track modified PTEs */
@ -4308,7 +4416,8 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
}
/* warning: addr must be aligned */
void stl_phys(target_phys_addr_t addr, uint32_t val)
static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val,
enum device_endian endian)
{
int io_index;
uint8_t *ptr;
@ -4326,13 +4435,32 @@ void stl_phys(target_phys_addr_t addr, uint32_t val)
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
if (p)
addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
#if defined(TARGET_WORDS_BIGENDIAN)
if (endian == DEVICE_LITTLE_ENDIAN) {
val = bswap32(val);
}
#else
if (endian == DEVICE_BIG_ENDIAN) {
val = bswap32(val);
}
#endif
io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
} else {
unsigned long addr1;
addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
/* RAM case */
ptr = qemu_get_ram_ptr(addr1);
stl_p(ptr, val);
switch (endian) {
case DEVICE_LITTLE_ENDIAN:
stl_le_p(ptr, val);
break;
case DEVICE_BIG_ENDIAN:
stl_be_p(ptr, val);
break;
default:
stl_p(ptr, val);
break;
}
if (!cpu_physical_memory_is_dirty(addr1)) {
/* invalidate code */
tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
@ -4343,6 +4471,21 @@ void stl_phys(target_phys_addr_t addr, uint32_t val)
}
}
void stl_phys(target_phys_addr_t addr, uint32_t val)
{
stl_phys_internal(addr, val, DEVICE_NATIVE_ENDIAN);
}
void stl_le_phys(target_phys_addr_t addr, uint32_t val)
{
stl_phys_internal(addr, val, DEVICE_LITTLE_ENDIAN);
}
void stl_be_phys(target_phys_addr_t addr, uint32_t val)
{
stl_phys_internal(addr, val, DEVICE_BIG_ENDIAN);
}
/* XXX: optimize */
void stb_phys(target_phys_addr_t addr, uint32_t val)
{
@ -4351,7 +4494,8 @@ void stb_phys(target_phys_addr_t addr, uint32_t val)
}
/* warning: addr must be aligned */
void stw_phys(target_phys_addr_t addr, uint32_t val)
static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val,
enum device_endian endian)
{
int io_index;
uint8_t *ptr;
@ -4369,13 +4513,32 @@ void stw_phys(target_phys_addr_t addr, uint32_t val)
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
if (p)
addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
#if defined(TARGET_WORDS_BIGENDIAN)
if (endian == DEVICE_LITTLE_ENDIAN) {
val = bswap16(val);
}
#else
if (endian == DEVICE_BIG_ENDIAN) {
val = bswap16(val);
}
#endif
io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
} else {
unsigned long addr1;
addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
/* RAM case */
ptr = qemu_get_ram_ptr(addr1);
stw_p(ptr, val);
switch (endian) {
case DEVICE_LITTLE_ENDIAN:
stw_le_p(ptr, val);
break;
case DEVICE_BIG_ENDIAN:
stw_be_p(ptr, val);
break;
default:
stw_p(ptr, val);
break;
}
if (!cpu_physical_memory_is_dirty(addr1)) {
/* invalidate code */
tb_invalidate_phys_page_range(addr1, addr1 + 2, 0);
@ -4386,6 +4549,21 @@ void stw_phys(target_phys_addr_t addr, uint32_t val)
}
}
void stw_phys(target_phys_addr_t addr, uint32_t val)
{
stw_phys_internal(addr, val, DEVICE_NATIVE_ENDIAN);
}
void stw_le_phys(target_phys_addr_t addr, uint32_t val)
{
stw_phys_internal(addr, val, DEVICE_LITTLE_ENDIAN);
}
void stw_be_phys(target_phys_addr_t addr, uint32_t val)
{
stw_phys_internal(addr, val, DEVICE_BIG_ENDIAN);
}
/* XXX: optimize */
void stq_phys(target_phys_addr_t addr, uint64_t val)
{
@ -4393,6 +4571,18 @@ void stq_phys(target_phys_addr_t addr, uint64_t val)
cpu_physical_memory_write(addr, &val, 8);
}
void stq_le_phys(target_phys_addr_t addr, uint64_t val)
{
val = cpu_to_le64(val);
cpu_physical_memory_write(addr, &val, 8);
}
void stq_be_phys(target_phys_addr_t addr, uint64_t val)
{
val = cpu_to_be64(val);
cpu_physical_memory_write(addr, &val, 8);
}
/* virtual memory access for debug (includes writing to ROM) */
int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
uint8_t *buf, int len, int is_write)

View File

@ -840,7 +840,7 @@ ETEXI
{
.name = "snapshot_blkdev",
.args_type = "device:B,snapshot_file:s?,format:s?",
.args_type = "device:B,snapshot-file:s?,format:s?",
.params = "device [new-image-file] [format]",
.help = "initiates a live snapshot\n\t\t\t"
"of device. If a new image file is specified, the\n\t\t\t"

View File

@ -1771,13 +1771,13 @@ static const char *const add_compl_names[] = { 0, "", ",l", ",tsv" };
static void
fput_reg (unsigned reg, disassemble_info *info)
{
(*info->fprintf_func) (info->stream, reg ? reg_names[reg] : "r0");
(*info->fprintf_func) (info->stream, "%s", reg ? reg_names[reg] : "r0");
}
static void
fput_fp_reg (unsigned reg, disassemble_info *info)
{
(*info->fprintf_func) (info->stream, reg ? fp_reg_names[reg] : "fr0");
(*info->fprintf_func) (info->stream, "%s", reg ? fp_reg_names[reg] : "fr0");
}
static void
@ -1794,7 +1794,7 @@ fput_fp_reg_r (unsigned reg, disassemble_info *info)
static void
fput_creg (unsigned reg, disassemble_info *info)
{
(*info->fprintf_func) (info->stream, control_reg[reg]);
(*info->fprintf_func) (info->stream, "%s", control_reg[reg]);
}
/* Print constants with sign. */

View File

@ -31,7 +31,7 @@ struct arm_boot_info {
target_phys_addr_t smp_priv_base;
int nb_cpus;
int board_id;
int (*atag_board)(struct arm_boot_info *info, void *p);
int (*atag_board)(const struct arm_boot_info *info, void *p);
/* Used internally by arm_boot.c */
int is_linux;
target_phys_addr_t initrd_size;

View File

@ -49,7 +49,7 @@ static uint32_t smpboot[] = {
p += 4; \
} while (0)
static void set_kernel_args(struct arm_boot_info *info,
static void set_kernel_args(const struct arm_boot_info *info,
int initrd_size, target_phys_addr_t base)
{
target_phys_addr_t p;
@ -102,7 +102,7 @@ static void set_kernel_args(struct arm_boot_info *info,
WRITE_WORD(p, 0);
}
static void set_kernel_args_old(struct arm_boot_info *info,
static void set_kernel_args_old(const struct arm_boot_info *info,
int initrd_size, target_phys_addr_t base)
{
target_phys_addr_t p;
@ -178,7 +178,7 @@ static void set_kernel_args_old(struct arm_boot_info *info,
static void do_cpu_reset(void *opaque)
{
CPUState *env = opaque;
struct arm_boot_info *info = env->boot_info;
const struct arm_boot_info *info = env->boot_info;
cpu_reset(env);
if (info) {

View File

@ -22,31 +22,24 @@
* THE SOFTWARE.
*/
#include "hw.h"
#include "mips.h"
#include "nvram.h"
#include "sysbus.h"
#include "trace.h"
//#define DEBUG_NVRAM
typedef struct ds1225y_t
{
typedef struct {
DeviceState qdev;
uint32_t chip_size;
char *filename;
QEMUFile *file;
uint8_t *contents;
uint8_t protection;
} ds1225y_t;
} NvRamState;
static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
{
ds1225y_t *s = opaque;
NvRamState *s = opaque;
uint32_t val;
val = s->contents[addr];
#ifdef DEBUG_NVRAM
printf("nvram: read 0x%x at " TARGET_FMT_lx "\n", val, addr);
#endif
trace_nvram_read(addr, val);
return val;
}
@ -70,13 +63,12 @@ static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t val)
{
ds1225y_t *s = opaque;
NvRamState *s = opaque;
#ifdef DEBUG_NVRAM
printf("nvram: write 0x%x at " TARGET_FMT_lx "\n", val, addr);
#endif
val &= 0xff;
trace_nvram_write(addr, s->contents[addr], val);
s->contents[addr] = val & 0xff;
s->contents[addr] = val;
if (s->file) {
qemu_fseek(s->file, addr, SEEK_SET);
qemu_put_byte(s->file, (int)val);
@ -98,34 +90,6 @@ static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t val)
nvram_writeb(opaque, addr + 3, (val >> 24) & 0xff);
}
static void nvram_writeb_protected (void *opaque, target_phys_addr_t addr, uint32_t val)
{
ds1225y_t *s = opaque;
if (s->protection != 7) {
#ifdef DEBUG_NVRAM
printf("nvram: prevent write of 0x%x at " TARGET_FMT_lx "\n", val, addr);
#endif
return;
}
nvram_writeb(opaque, addr, val);
}
static void nvram_writew_protected (void *opaque, target_phys_addr_t addr, uint32_t val)
{
nvram_writeb_protected(opaque, addr, val & 0xff);
nvram_writeb_protected(opaque, addr + 1, (val >> 8) & 0xff);
}
static void nvram_writel_protected (void *opaque, target_phys_addr_t addr, uint32_t val)
{
nvram_writeb_protected(opaque, addr, val & 0xff);
nvram_writeb_protected(opaque, addr + 1, (val >> 8) & 0xff);
nvram_writeb_protected(opaque, addr + 2, (val >> 16) & 0xff);
nvram_writeb_protected(opaque, addr + 3, (val >> 24) & 0xff);
}
static CPUReadMemoryFunc * const nvram_read[] = {
&nvram_readb,
&nvram_readw,
@ -138,45 +102,83 @@ static CPUWriteMemoryFunc * const nvram_write[] = {
&nvram_writel,
};
static CPUWriteMemoryFunc * const nvram_write_protected[] = {
&nvram_writeb_protected,
&nvram_writew_protected,
&nvram_writel_protected,
};
/* Initialisation routine */
void *ds1225y_init(target_phys_addr_t mem_base, const char *filename)
static int nvram_post_load(void *opaque, int version_id)
{
ds1225y_t *s;
int mem_indexRW, mem_indexRP;
QEMUFile *file;
NvRamState *s = opaque;
s = qemu_mallocz(sizeof(ds1225y_t));
s->chip_size = 0x2000; /* Fixed for ds1225y chip: 8 KiB */
s->contents = qemu_mallocz(s->chip_size);
s->protection = 7;
/* Read current file */
file = qemu_fopen(filename, "rb");
if (file) {
/* Read nvram contents */
qemu_get_buffer(file, s->contents, s->chip_size);
qemu_fclose(file);
/* Close file, as filename may has changed in load/store process */
if (s->file) {
qemu_fclose(s->file);
}
s->file = qemu_fopen(filename, "wb");
/* Write back nvram contents */
s->file = qemu_fopen(s->filename, "wb");
if (s->file) {
/* Write back contents, as 'wb' mode cleaned the file */
qemu_put_buffer(s->file, s->contents, s->chip_size);
qemu_fflush(s->file);
}
/* Read/write memory */
mem_indexRW = cpu_register_io_memory(nvram_read, nvram_write, s,
DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(mem_base, s->chip_size, mem_indexRW);
/* Read/write protected memory */
mem_indexRP = cpu_register_io_memory(nvram_read, nvram_write_protected, s,
DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(mem_base + s->chip_size, s->chip_size, mem_indexRP);
return s;
return 0;
}
static const VMStateDescription vmstate_nvram = {
.name = "nvram",
.version_id = 0,
.minimum_version_id = 0,
.minimum_version_id_old = 0,
.post_load = nvram_post_load,
.fields = (VMStateField[]) {
VMSTATE_VARRAY_UINT32(contents, NvRamState, chip_size, 0,
vmstate_info_uint8, uint8_t),
VMSTATE_END_OF_LIST()
}
};
typedef struct {
SysBusDevice busdev;
NvRamState nvram;
} SysBusNvRamState;
static int nvram_sysbus_initfn(SysBusDevice *dev)
{
NvRamState *s = &FROM_SYSBUS(SysBusNvRamState, dev)->nvram;
QEMUFile *file;
int s_io;
s->contents = qemu_mallocz(s->chip_size);
s_io = cpu_register_io_memory(nvram_read, nvram_write, s,
DEVICE_NATIVE_ENDIAN);
sysbus_init_mmio(dev, s->chip_size, s_io);
/* Read current file */
file = qemu_fopen(s->filename, "rb");
if (file) {
/* Read nvram contents */
qemu_get_buffer(file, s->contents, s->chip_size);
qemu_fclose(file);
}
nvram_post_load(s, 0);
return 0;
}
static SysBusDeviceInfo nvram_sysbus_info = {
.qdev.name = "ds1225y",
.qdev.size = sizeof(SysBusNvRamState),
.qdev.vmsd = &vmstate_nvram,
.init = nvram_sysbus_initfn,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("size", SysBusNvRamState, nvram.chip_size, 0x2000),
DEFINE_PROP_STRING("filename", SysBusNvRamState, nvram.filename),
DEFINE_PROP_END_OF_LIST(),
},
};
static void nvram_register(void)
{
sysbus_register_withprop(&nvram_sysbus_info);
}
device_init(nvram_register)

View File

@ -211,7 +211,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
} else {
dmalen = s->ti_size;
memcpy(buf, s->ti_buf, dmalen);
buf[0] = 0;
buf[0] = buf[2] >> 5;
}
DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
@ -219,7 +219,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
s->ti_rptr = 0;
s->ti_wptr = 0;
if (s->current_dev) {
if (s->current_req) {
/* Started a new command before the old one finished. Cancel it. */
scsi_req_cancel(s->current_req);
s->async_len = 0;
@ -244,7 +244,7 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
DPRINTF("do_busid_cmd: busid 0x%x\n", busid);
lun = busid & 7;
s->current_req = scsi_req_new(s->current_dev, 0, lun);
s->current_req = scsi_req_new(s->current_dev, 0, lun, NULL);
datalen = scsi_req_enqueue(s->current_req, buf);
s->ti_size = datalen;
if (datalen != 0) {

View File

@ -190,15 +190,23 @@ static void serial_event(void *opaque, int event)
}
static int etraxfs_ser_init(SysBusDevice *dev)
static void etraxfs_ser_reset(DeviceState *d)
{
struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
int ser_regs;
struct etrax_serial *s = container_of(d, typeof(*s), busdev.qdev);
/* transmitter begins ready and idle. */
s->regs[RS_STAT_DIN] |= (1 << STAT_TR_RDY);
s->regs[RS_STAT_DIN] |= (1 << STAT_TR_IDLE);
s->regs[RW_REC_CTRL] = 0x10000;
}
static int etraxfs_ser_init(SysBusDevice *dev)
{
struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
int ser_regs;
sysbus_init_irq(dev, &s->irq);
ser_regs = cpu_register_io_memory(ser_read, ser_write, s,
DEVICE_NATIVE_ENDIAN);
@ -211,10 +219,16 @@ static int etraxfs_ser_init(SysBusDevice *dev)
return 0;
}
static SysBusDeviceInfo etraxfs_ser_info = {
.init = etraxfs_ser_init,
.qdev.name = "etraxfs,serial",
.qdev.size = sizeof(struct etrax_serial),
.qdev.reset = etraxfs_ser_reset,
};
static void etraxfs_serial_register(void)
{
sysbus_register_dev("etraxfs,serial", sizeof (struct etrax_serial),
etraxfs_ser_init);
sysbus_register_withprop(&etraxfs_ser_info);
}
device_init(etraxfs_serial_register)

View File

@ -78,6 +78,9 @@ void framebuffer_update_display(
dest = ds_get_data(ds);
if (dest_col_pitch < 0)
dest -= dest_col_pitch * (cols - 1);
if (dest_row_pitch < 0) {
dest -= dest_row_pitch * (rows - 1);
}
first = -1;
addr = pd;

View File

@ -192,7 +192,7 @@ static void update_irq(struct HPETTimer *timer, int set)
qemu_irq_lower(s->irqs[route]);
}
} else if (timer_fsb_route(timer)) {
stl_phys(timer->fsb >> 32, timer->fsb & 0xffffffff);
stl_le_phys(timer->fsb >> 32, timer->fsb & 0xffffffff);
} else if (timer->config & HPET_TN_TYPE_LEVEL) {
s->isr |= mask;
qemu_irq_raise(s->irqs[route]);

View File

@ -56,6 +56,7 @@ static const int smart_attributes[][12] = {
};
static int ide_handle_rw_error(IDEState *s, int error, int op);
static void ide_dummy_transfer_stop(IDEState *s);
static void padstr(char *str, const char *src, int len)
{
@ -1532,15 +1533,36 @@ void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val)
bus->cmd = val;
}
/*
* Returns true if the running PIO transfer is a PIO out (i.e. data is
* transferred from the device to the guest), false if it's a PIO in
*/
static bool ide_is_pio_out(IDEState *s)
{
if (s->end_transfer_func == ide_sector_write ||
s->end_transfer_func == ide_atapi_cmd) {
return false;
} else if (s->end_transfer_func == ide_sector_read ||
s->end_transfer_func == ide_transfer_stop ||
s->end_transfer_func == ide_atapi_cmd_reply_end ||
s->end_transfer_func == ide_dummy_transfer_stop) {
return true;
}
abort();
}
void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
{
IDEBus *bus = opaque;
IDEState *s = idebus_active_if(bus);
uint8_t *p;
/* PIO data access allowed only when DRQ bit is set */
if (!(s->status & DRQ_STAT))
/* PIO data access allowed only when DRQ bit is set. The result of a write
* during PIO out is indeterminate, just ignore it. */
if (!(s->status & DRQ_STAT) || ide_is_pio_out(s)) {
return;
}
p = s->data_ptr;
*(uint16_t *)p = le16_to_cpu(val);
@ -1557,9 +1579,11 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr)
uint8_t *p;
int ret;
/* PIO data access allowed only when DRQ bit is set */
if (!(s->status & DRQ_STAT))
/* PIO data access allowed only when DRQ bit is set. The result of a read
* during PIO in is indeterminate, return 0 and don't move forward. */
if (!(s->status & DRQ_STAT) || !ide_is_pio_out(s)) {
return 0;
}
p = s->data_ptr;
ret = cpu_to_le16(*(uint16_t *)p);
@ -1576,9 +1600,11 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
IDEState *s = idebus_active_if(bus);
uint8_t *p;
/* PIO data access allowed only when DRQ bit is set */
if (!(s->status & DRQ_STAT))
/* PIO data access allowed only when DRQ bit is set. The result of a write
* during PIO out is indeterminate, just ignore it. */
if (!(s->status & DRQ_STAT) || ide_is_pio_out(s)) {
return;
}
p = s->data_ptr;
*(uint32_t *)p = le32_to_cpu(val);
@ -1595,9 +1621,11 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr)
uint8_t *p;
int ret;
/* PIO data access allowed only when DRQ bit is set */
if (!(s->status & DRQ_STAT))
/* PIO data access allowed only when DRQ bit is set. The result of a read
* during PIO in is indeterminate, return 0 and don't move forward. */
if (!(s->status & DRQ_STAT) || !ide_is_pio_out(s)) {
return 0;
}
p = s->data_ptr;
ret = cpu_to_le32(*(uint32_t *)p);
@ -1761,9 +1789,13 @@ static void ide_init1(IDEBus *bus, int unit)
s->unit = unit;
s->drive_serial = drive_serial++;
/* we need at least 2k alignment for accessing CDROMs using O_DIRECT */
s->io_buffer = qemu_memalign(2048, IDE_DMA_BUF_SECTORS*512 + 4);
s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
s->io_buffer = qemu_memalign(2048, s->io_buffer_total_len);
memset(s->io_buffer, 0, s->io_buffer_total_len);
s->smart_selftest_data = qemu_blockalign(s->bs, 512);
memset(s->smart_selftest_data, 0, 512);
s->sector_write_timer = qemu_new_timer_ns(vm_clock,
ide_sector_write_timer_cb, s);
}

View File

@ -224,19 +224,6 @@ static target_phys_addr_t intel_hda_addr(uint32_t lbase, uint32_t ubase)
return addr;
}
static void stl_phys_le(target_phys_addr_t addr, uint32_t value)
{
uint32_t value_le = cpu_to_le32(value);
cpu_physical_memory_write(addr, (uint8_t*)(&value_le), sizeof(value_le));
}
static uint32_t ldl_phys_le(target_phys_addr_t addr)
{
uint32_t value_le;
cpu_physical_memory_read(addr, (uint8_t*)(&value_le), sizeof(value_le));
return le32_to_cpu(value_le);
}
static void intel_hda_update_int_sts(IntelHDAState *d)
{
uint32_t sts = 0;
@ -341,7 +328,7 @@ static void intel_hda_corb_run(IntelHDAState *d)
rp = (d->corb_rp + 1) & 0xff;
addr = intel_hda_addr(d->corb_lbase, d->corb_ubase);
verb = ldl_phys_le(addr + 4*rp);
verb = ldl_le_phys(addr + 4*rp);
d->corb_rp = rp;
dprint(d, 2, "%s: [rp 0x%x] verb 0x%08x\n", __FUNCTION__, rp, verb);
@ -373,8 +360,8 @@ static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t res
ex = (solicited ? 0 : (1 << 4)) | dev->cad;
wp = (d->rirb_wp + 1) & 0xff;
addr = intel_hda_addr(d->rirb_lbase, d->rirb_ubase);
stl_phys_le(addr + 8*wp, response);
stl_phys_le(addr + 8*wp + 4, ex);
stl_le_phys(addr + 8*wp, response);
stl_le_phys(addr + 8*wp + 4, ex);
d->rirb_wp = wp;
dprint(d, 2, "%s: [wp 0x%x] response 0x%x, extra 0x%x\n",
@ -461,7 +448,7 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
}
if (d->dp_lbase & 0x01) {
addr = intel_hda_addr(d->dp_lbase & ~0x01, d->dp_ubase);
stl_phys_le(addr + 8*s, st->lpib);
stl_le_phys(addr + 8*s, st->lpib);
}
dprint(d, 3, "dma: --\n");

View File

@ -661,7 +661,7 @@ static lsi_request *lsi_find_by_tag(LSIState *s, uint32_t tag)
static void lsi_request_cancelled(SCSIRequest *req)
{
LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
lsi_request *p;
lsi_request *p = req->hba_private;
if (s->current && req == s->current->req) {
scsi_req_unref(req);
@ -670,7 +670,6 @@ static void lsi_request_cancelled(SCSIRequest *req)
return;
}
p = lsi_find_by_tag(s, req->tag);
if (p) {
QTAILQ_REMOVE(&s->queue, p, next);
scsi_req_unref(req);
@ -680,18 +679,12 @@ static void lsi_request_cancelled(SCSIRequest *req)
/* Record that data is available for a queued command. Returns zero if
the device was reselected, nonzero if the IO is deferred. */
static int lsi_queue_tag(LSIState *s, uint32_t tag, uint32_t len)
static int lsi_queue_req(LSIState *s, SCSIRequest *req, uint32_t len)
{
lsi_request *p;
p = lsi_find_by_tag(s, tag);
if (!p) {
BADF("IO with unknown tag %d\n", tag);
return 1;
}
lsi_request *p = req->hba_private;
if (p->pending) {
BADF("Multiple IO pending for tag %d\n", tag);
BADF("Multiple IO pending for request %p\n", p);
}
p->pending = len;
/* Reselect if waiting for it, or if reselection triggers an IRQ
@ -743,9 +736,9 @@ static void lsi_transfer_data(SCSIRequest *req, uint32_t len)
LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
int out;
if (s->waiting == 1 || !s->current || req->tag != s->current->tag ||
if (s->waiting == 1 || !s->current || req->hba_private != s->current ||
(lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON))) {
if (lsi_queue_tag(s, req->tag, len)) {
if (lsi_queue_req(s, req, len)) {
return;
}
}
@ -789,7 +782,8 @@ static void lsi_do_command(LSIState *s)
assert(s->current == NULL);
s->current = qemu_mallocz(sizeof(lsi_request));
s->current->tag = s->select_tag;
s->current->req = scsi_req_new(dev, s->current->tag, s->current_lun);
s->current->req = scsi_req_new(dev, s->current->tag, s->current_lun,
s->current);
n = scsi_req_enqueue(s->current->req, buf);
if (n) {

View File

@ -247,16 +247,21 @@ static void softusb_attach(USBPort *port)
{
}
static void softusb_device_destroy(USBBus *bus, USBDevice *dev)
static void softusb_detach(USBPort *port)
{
}
static void softusb_child_detach(USBPort *port, USBDevice *child)
{
}
static USBPortOps softusb_ops = {
.attach = softusb_attach,
.detach = softusb_detach,
.child_detach = softusb_child_detach,
};
static USBBusOps softusb_bus_ops = {
.device_destroy = softusb_device_destroy,
};
static void milkymist_softusb_reset(DeviceState *d)

View File

@ -8,10 +8,6 @@ PCIBus *gt64120_register(qemu_irq *pic);
/* bonito.c */
PCIBus *bonito_init(qemu_irq *pic);
/* ds1225y.c */
void *ds1225y_init(target_phys_addr_t mem_base, const char *filename);
void ds1225y_set_protection(void *opaque, int protection);
/* g364fb.c */
int g364fb_mm_init(target_phys_addr_t vram_base,
target_phys_addr_t ctrl_base, int it_shift,

View File

@ -37,6 +37,7 @@
#include "loader.h"
#include "mc146818rtc.h"
#include "blockdev.h"
#include "sysbus.h"
enum jazz_model_e
{
@ -115,6 +116,8 @@ void mips_jazz_init (ram_addr_t ram_size,
void* rc4030_opaque;
int s_rtc, s_dma_dummy;
NICInfo *nd;
DeviceState *dev;
SysBusDevice *sysbus;
ISADevice *pit;
DriveInfo *fds[MAX_FD];
qemu_irq esp_reset, dma_enable;
@ -266,8 +269,11 @@ void mips_jazz_init (ram_addr_t ram_size,
/* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
audio_init(i8259, NULL);
/* NVRAM: Unprotected at 0x9000, Protected at 0xa000, Read only at 0xb000 */
ds1225y_init(0x80009000, "nvram");
/* NVRAM */
dev = qdev_create(NULL, "ds1225y");
qdev_init_nofail(dev);
sysbus = sysbus_from_qdev(dev);
sysbus_mmio_map(sysbus, 0, 0x80009000);
/* LED indicator */
jazz_led_init(0x8000f000);

135
hw/mpc8544_guts.c Normal file
View File

@ -0,0 +1,135 @@
/*
* QEMU PowerPC MPC8544 global util pseudo-device
*
* Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved.
*
* Author: Alexander Graf, <alex@csgraf.de>
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* *****************************************************************
*
* The documentation for this device is noted in the MPC8544 documentation,
* file name "MPC8544ERM.pdf". You can easily find it on the web.
*
*/
#include "hw.h"
#include "sysemu.h"
#include "sysbus.h"
#define MPC8544_GUTS_MMIO_SIZE 0x1000
#define MPC8544_GUTS_RSTCR_RESET 0x02
#define MPC8544_GUTS_ADDR_PORPLLSR 0x00
#define MPC8544_GUTS_ADDR_PORBMSR 0x04
#define MPC8544_GUTS_ADDR_PORIMPSCR 0x08
#define MPC8544_GUTS_ADDR_PORDEVSR 0x0C
#define MPC8544_GUTS_ADDR_PORDBGMSR 0x10
#define MPC8544_GUTS_ADDR_PORDEVSR2 0x14
#define MPC8544_GUTS_ADDR_GPPORCR 0x20
#define MPC8544_GUTS_ADDR_GPIOCR 0x30
#define MPC8544_GUTS_ADDR_GPOUTDR 0x40
#define MPC8544_GUTS_ADDR_GPINDR 0x50
#define MPC8544_GUTS_ADDR_PMUXCR 0x60
#define MPC8544_GUTS_ADDR_DEVDISR 0x70
#define MPC8544_GUTS_ADDR_POWMGTCSR 0x80
#define MPC8544_GUTS_ADDR_MCPSUMR 0x90
#define MPC8544_GUTS_ADDR_RSTRSCR 0x94
#define MPC8544_GUTS_ADDR_PVR 0xA0
#define MPC8544_GUTS_ADDR_SVR 0xA4
#define MPC8544_GUTS_ADDR_RSTCR 0xB0
#define MPC8544_GUTS_ADDR_IOVSELSR 0xC0
#define MPC8544_GUTS_ADDR_DDRCSR 0xB20
#define MPC8544_GUTS_ADDR_DDRCDR 0xB24
#define MPC8544_GUTS_ADDR_DDRCLKDR 0xB28
#define MPC8544_GUTS_ADDR_CLKOCR 0xE00
#define MPC8544_GUTS_ADDR_SRDS1CR1 0xF04
#define MPC8544_GUTS_ADDR_SRDS2CR1 0xF10
#define MPC8544_GUTS_ADDR_SRDS2CR3 0xF18
struct GutsState {
SysBusDevice busdev;
};
typedef struct GutsState GutsState;
static uint32_t mpc8544_guts_read32(void *opaque, target_phys_addr_t addr)
{
uint32_t value = 0;
CPUState *env = cpu_single_env;
addr &= MPC8544_GUTS_MMIO_SIZE - 1;
switch (addr) {
case MPC8544_GUTS_ADDR_PVR:
value = env->spr[SPR_PVR];
break;
case MPC8544_GUTS_ADDR_SVR:
value = env->spr[SPR_E500_SVR];
break;
default:
fprintf(stderr, "guts: Unknown register read: %x\n", (int)addr);
break;
}
return value;
}
static CPUReadMemoryFunc * const mpc8544_guts_read[] = {
NULL,
NULL,
&mpc8544_guts_read32,
};
static void mpc8544_guts_write32(void *opaque, target_phys_addr_t addr,
uint32_t value)
{
addr &= MPC8544_GUTS_MMIO_SIZE - 1;
switch (addr) {
case MPC8544_GUTS_ADDR_RSTCR:
if (value & MPC8544_GUTS_RSTCR_RESET) {
qemu_system_reset_request();
}
break;
default:
fprintf(stderr, "guts: Unknown register write: %x = %x\n",
(int)addr, value);
break;
}
}
static CPUWriteMemoryFunc * const mpc8544_guts_write[] = {
NULL,
NULL,
&mpc8544_guts_write32,
};
static int mpc8544_guts_initfn(SysBusDevice *dev)
{
GutsState *s;
int iomem;
s = FROM_SYSBUS(GutsState, sysbus_from_qdev(dev));
iomem = cpu_register_io_memory(mpc8544_guts_read, mpc8544_guts_write, s,
DEVICE_BIG_ENDIAN);
sysbus_init_mmio(dev, MPC8544_GUTS_MMIO_SIZE, iomem);
return 0;
}
static SysBusDeviceInfo mpc8544_guts_info = {
.init = mpc8544_guts_initfn,
.qdev.name = "mpc8544-guts",
.qdev.size = sizeof(GutsState),
};
static void mpc8544_guts_register(void)
{
sysbus_register_withprop(&mpc8544_guts_info);
}
device_init(mpc8544_guts_register);

View File

@ -249,7 +249,7 @@ void msi_notify(PCIDevice *dev, unsigned int vector)
"notify vector 0x%x"
" address: 0x%"PRIx64" data: 0x%"PRIx32"\n",
vector, address, data);
stl_phys(address, data);
stl_le_phys(address, data);
}
/* call this function after updating configs by pci_default_write_config(). */

View File

@ -359,7 +359,7 @@ void msix_notify(PCIDevice *dev, unsigned vector)
address = pci_get_quad(table_entry + PCI_MSIX_ENTRY_LOWER_ADDR);
data = pci_get_long(table_entry + PCI_MSIX_ENTRY_DATA);
stl_phys(address, data);
stl_le_phys(address, data);
}
void msix_reset(PCIDevice *dev)

View File

@ -1254,12 +1254,12 @@ static int n8x0_atag_setup(void *p, int model)
return (void *) w - p;
}
static int n800_atag_setup(struct arm_boot_info *info, void *p)
static int n800_atag_setup(const struct arm_boot_info *info, void *p)
{
return n8x0_atag_setup(p, 800);
}
static int n810_atag_setup(struct arm_boot_info *info, void *p)
static int n810_atag_setup(const struct arm_boot_info *info, void *p)
{
return n8x0_atag_setup(p, 810);
}

View File

@ -109,5 +109,14 @@
#define PCI_DEVICE_ID_INTEL_82371AB 0x7111
#define PCI_DEVICE_ID_INTEL_82371AB_2 0x7112
#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113
#define PCI_DEVICE_ID_INTEL_82801I_UHCI1 0x2934
#define PCI_DEVICE_ID_INTEL_82801I_UHCI2 0x2935
#define PCI_DEVICE_ID_INTEL_82801I_UHCI3 0x2936
#define PCI_DEVICE_ID_INTEL_82801I_UHCI4 0x2937
#define PCI_DEVICE_ID_INTEL_82801I_UHCI5 0x2938
#define PCI_DEVICE_ID_INTEL_82801I_UHCI6 0x2939
#define PCI_DEVICE_ID_INTEL_82801I_EHCI1 0x293a
#define PCI_DEVICE_ID_INTEL_82801I_EHCI2 0x293c
#define PCI_VENDOR_ID_XENSOURCE 0x5853
#define PCI_VENDOR_ID_XEN 0x5853
#define PCI_DEVICE_ID_XEN_PLATFORM 0x0001

View File

@ -478,6 +478,9 @@ static PCIDeviceInfo i440fx_info[] = {
.no_hotplug = 1,
.init = piix3_initfn,
.config_write = piix3_write_config_xen,
.vendor_id = PCI_VENDOR_ID_INTEL,
.device_id = PCI_DEVICE_ID_INTEL_82371SB_0, // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
.class_id = PCI_CLASS_BRIDGE_ISA,
},{
/* end of list */
}

View File

@ -199,10 +199,10 @@ again:
if (size == 0) {
/* Transfer complete. */
if (ch->lli) {
ch->src = ldl_phys(ch->lli);
ch->dest = ldl_phys(ch->lli + 4);
ch->ctrl = ldl_phys(ch->lli + 12);
ch->lli = ldl_phys(ch->lli + 8);
ch->src = ldl_le_phys(ch->lli);
ch->dest = ldl_le_phys(ch->lli + 4);
ch->ctrl = ldl_le_phys(ch->lli + 12);
ch->lli = ldl_le_phys(ch->lli + 8);
} else {
ch->conf &= ~PL080_CCONF_E;
}

View File

@ -51,39 +51,42 @@ ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
bdloc = 0x01000000UL - sizeof(struct ppc4xx_bd_info_t);
else
bdloc = bd->bi_memsize - sizeof(struct ppc4xx_bd_info_t);
stl_phys(bdloc + 0x00, bd->bi_memstart);
stl_phys(bdloc + 0x04, bd->bi_memsize);
stl_phys(bdloc + 0x08, bd->bi_flashstart);
stl_phys(bdloc + 0x0C, bd->bi_flashsize);
stl_phys(bdloc + 0x10, bd->bi_flashoffset);
stl_phys(bdloc + 0x14, bd->bi_sramstart);
stl_phys(bdloc + 0x18, bd->bi_sramsize);
stl_phys(bdloc + 0x1C, bd->bi_bootflags);
stl_phys(bdloc + 0x20, bd->bi_ipaddr);
for (i = 0; i < 6; i++)
stl_be_phys(bdloc + 0x00, bd->bi_memstart);
stl_be_phys(bdloc + 0x04, bd->bi_memsize);
stl_be_phys(bdloc + 0x08, bd->bi_flashstart);
stl_be_phys(bdloc + 0x0C, bd->bi_flashsize);
stl_be_phys(bdloc + 0x10, bd->bi_flashoffset);
stl_be_phys(bdloc + 0x14, bd->bi_sramstart);
stl_be_phys(bdloc + 0x18, bd->bi_sramsize);
stl_be_phys(bdloc + 0x1C, bd->bi_bootflags);
stl_be_phys(bdloc + 0x20, bd->bi_ipaddr);
for (i = 0; i < 6; i++) {
stb_phys(bdloc + 0x24 + i, bd->bi_enetaddr[i]);
stw_phys(bdloc + 0x2A, bd->bi_ethspeed);
stl_phys(bdloc + 0x2C, bd->bi_intfreq);
stl_phys(bdloc + 0x30, bd->bi_busfreq);
stl_phys(bdloc + 0x34, bd->bi_baudrate);
for (i = 0; i < 4; i++)
}
stw_be_phys(bdloc + 0x2A, bd->bi_ethspeed);
stl_be_phys(bdloc + 0x2C, bd->bi_intfreq);
stl_be_phys(bdloc + 0x30, bd->bi_busfreq);
stl_be_phys(bdloc + 0x34, bd->bi_baudrate);
for (i = 0; i < 4; i++) {
stb_phys(bdloc + 0x38 + i, bd->bi_s_version[i]);
}
for (i = 0; i < 32; i++) {
stb_phys(bdloc + 0x3C + i, bd->bi_r_version[i]);
}
stl_phys(bdloc + 0x5C, bd->bi_plb_busfreq);
stl_phys(bdloc + 0x60, bd->bi_pci_busfreq);
for (i = 0; i < 6; i++)
stl_be_phys(bdloc + 0x5C, bd->bi_plb_busfreq);
stl_be_phys(bdloc + 0x60, bd->bi_pci_busfreq);
for (i = 0; i < 6; i++) {
stb_phys(bdloc + 0x64 + i, bd->bi_pci_enetaddr[i]);
}
n = 0x6A;
if (flags & 0x00000001) {
for (i = 0; i < 6; i++)
stb_phys(bdloc + n++, bd->bi_pci_enetaddr2[i]);
}
stl_phys(bdloc + n, bd->bi_opbfreq);
stl_be_phys(bdloc + n, bd->bi_opbfreq);
n += 4;
for (i = 0; i < 2; i++) {
stl_phys(bdloc + n, bd->bi_iic_fast[i]);
stl_be_phys(bdloc + n, bd->bi_iic_fast[i]);
n += 4;
}

View File

@ -45,8 +45,9 @@ CPUState *ppc440ep_init(ram_addr_t *ram_size, PCIBus **pcip,
qemu_irq *irqs;
qemu_irq *pci_irqs;
if (cpu_model == NULL)
cpu_model = "405"; // XXX: should be 440EP
if (cpu_model == NULL) {
cpu_model = "440-Xilinx"; // XXX: should be 440EP
}
env = cpu_init(cpu_model);
if (!env) {
fprintf(stderr, "Unable to initialize CPU!\n");

View File

@ -35,8 +35,7 @@
#define PROM_ADDR 0xfff00000
#define KERNEL_LOAD_ADDR 0x01000000
#define CMDLINE_ADDR 0x027ff000
#define INITRD_LOAD_ADDR 0x02800000
#define KERNEL_GAP 0x00100000
#define ESCC_CLOCK 3686400

View File

@ -120,6 +120,11 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
}
static target_phys_addr_t round_page(target_phys_addr_t addr)
{
return (addr + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
}
/* PowerPC Mac99 hardware initialisation */
static void ppc_core99_init (ram_addr_t ram_size,
const char *boot_device,
@ -134,7 +139,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
int unin_memory;
int linux_boot, i;
ram_addr_t ram_offset, bios_offset;
uint32_t kernel_base, initrd_base;
target_phys_addr_t kernel_base, initrd_base, cmdline_base = 0;
long kernel_size, initrd_size;
PCIBus *pci_bus;
MacIONVRAMState *nvr;
@ -220,7 +225,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
}
/* load initrd */
if (initrd_filename) {
initrd_base = INITRD_LOAD_ADDR;
initrd_base = round_page(kernel_base + kernel_size + KERNEL_GAP);
initrd_size = load_image_targphys(initrd_filename, initrd_base,
ram_size - initrd_base);
if (initrd_size < 0) {
@ -228,9 +233,11 @@ static void ppc_core99_init (ram_addr_t ram_size,
initrd_filename);
exit(1);
}
cmdline_base = round_page(initrd_base + initrd_size);
} else {
initrd_base = 0;
initrd_size = 0;
cmdline_base = round_page(kernel_base + kernel_size + KERNEL_GAP);
}
ppc_boot_device = 'm';
} else {
@ -373,8 +380,8 @@ static void ppc_core99_init (ram_addr_t ram_size,
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base);
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
if (kernel_cmdline) {
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base);
pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline);
} else {
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
}

View File

@ -59,6 +59,11 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
}
static target_phys_addr_t round_page(target_phys_addr_t addr)
{
return (addr + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
}
static void ppc_heathrow_init (ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename,
@ -71,7 +76,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
qemu_irq *pic, **heathrow_irqs;
int linux_boot, i;
ram_addr_t ram_offset, bios_offset;
uint32_t kernel_base, initrd_base;
uint32_t kernel_base, initrd_base, cmdline_base = 0;
int32_t kernel_size, initrd_size;
PCIBus *pci_bus;
MacIONVRAMState *nvr;
@ -157,7 +162,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
}
/* load initrd */
if (initrd_filename) {
initrd_base = INITRD_LOAD_ADDR;
initrd_base = round_page(kernel_base + kernel_size + KERNEL_GAP);
initrd_size = load_image_targphys(initrd_filename, initrd_base,
ram_size - initrd_base);
if (initrd_size < 0) {
@ -165,9 +170,11 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
initrd_filename);
exit(1);
}
cmdline_base = round_page(initrd_base + initrd_size);
} else {
initrd_base = 0;
initrd_size = 0;
cmdline_base = round_page(kernel_base + kernel_size + KERNEL_GAP);
}
ppc_boot_device = 'm';
} else {
@ -278,8 +285,8 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base);
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
if (kernel_cmdline) {
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base);
pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline);
} else {
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
}

View File

@ -50,6 +50,7 @@
#define MPC8544_PCI_REGS_SIZE 0x1000
#define MPC8544_PCI_IO 0xE1000000
#define MPC8544_PCI_IOLEN 0x10000
#define MPC8544_UTIL_BASE (MPC8544_CCSRBAR_BASE + 0xe0000)
struct boot_info
{
@ -81,11 +82,12 @@ out:
}
#endif
static int mpc8544_load_device_tree(target_phys_addr_t addr,
uint32_t ramsize,
target_phys_addr_t initrd_base,
target_phys_addr_t initrd_size,
const char *kernel_cmdline)
static int mpc8544_load_device_tree(CPUState *env,
target_phys_addr_t addr,
uint32_t ramsize,
target_phys_addr_t initrd_base,
target_phys_addr_t initrd_size,
const char *kernel_cmdline)
{
int ret = -1;
#ifdef CONFIG_FDT
@ -93,6 +95,7 @@ static int mpc8544_load_device_tree(target_phys_addr_t addr,
char *filename;
int fdt_size;
void *fdt;
uint8_t hypercall[16];
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
if (!filename) {
@ -156,6 +159,13 @@ static int mpc8544_load_device_tree(target_phys_addr_t addr,
mpc8544_copy_soc_cell(fdt, buf, "clock-frequency");
mpc8544_copy_soc_cell(fdt, buf, "timebase-frequency");
/* indicate KVM hypercall interface */
qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible",
"linux,kvm");
kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions",
hypercall, sizeof(hypercall));
} else {
const uint32_t freq = 400000000;
@ -175,18 +185,23 @@ out:
}
/* Create -kernel TLB entries for BookE, linearly spanning 256MB. */
static inline target_phys_addr_t booke206_page_size_to_tlb(uint64_t size)
{
return (ffs(size >> 10) - 1) >> 1;
}
static void mmubooke_create_initial_mapping(CPUState *env,
target_ulong va,
target_phys_addr_t pa)
{
ppcemb_tlb_t *tlb = booke206_get_tlbe(env, 1, 0, 0);
ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0);
target_phys_addr_t size;
tlb->attr = 0;
tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
tlb->size = 256 * 1024 * 1024;
tlb->EPN = va & TARGET_PAGE_MASK;
tlb->RPN = pa & TARGET_PAGE_MASK;
tlb->PID = 0;
size = (booke206_page_size_to_tlb(256 * 1024 * 1024) << MAS1_TSIZE_SHIFT);
tlb->mas1 = MAS1_VALID | size;
tlb->mas2 = va & TARGET_PAGE_MASK;
tlb->mas7_3 = pa & TARGET_PAGE_MASK;
tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
}
static void mpc8544ds_cpu_reset(void *opaque)
@ -270,6 +285,9 @@ static void mpc8544ds_init(ram_addr_t ram_size,
serial_hds[0], 1, 1);
}
/* General Utility device */
sysbus_create_simple("mpc8544-guts", MPC8544_UTIL_BASE, NULL);
/* PCI */
dev = sysbus_create_varargs("e500-pcihost", MPC8544_PCI_REGS_BASE,
mpic[pci_irq_nrs[0]], mpic[pci_irq_nrs[1]],
@ -326,7 +344,7 @@ static void mpc8544ds_init(ram_addr_t ram_size,
cpu_abort(env, "Compiled without FDT support - can't load kernel\n");
#endif
dt_base = (kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
if (mpc8544_load_device_tree(dt_base, ram_size,
if (mpc8544_load_device_tree(env, dt_base, ram_size,
initrd_base, initrd_size, kernel_cmdline) < 0) {
fprintf(stderr, "couldn't load device tree\n");
exit(1);

View File

@ -665,7 +665,7 @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
}
}
static void pxa2xx_lcdc_dma0_redraw_horiz(PXA2xxLCDState *s,
static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
target_phys_addr_t addr, int *miny, int *maxy)
{
int src_width, dest_width;
@ -692,7 +692,7 @@ static void pxa2xx_lcdc_dma0_redraw_horiz(PXA2xxLCDState *s,
fn, s->dma_ch[0].palette, miny, maxy);
}
static void pxa2xx_lcdc_dma0_redraw_vert(PXA2xxLCDState *s,
static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
target_phys_addr_t addr, int *miny, int *maxy)
{
int src_width, dest_width;
@ -720,6 +720,67 @@ static void pxa2xx_lcdc_dma0_redraw_vert(PXA2xxLCDState *s,
miny, maxy);
}
static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
target_phys_addr_t addr, int *miny, int *maxy)
{
int src_width, dest_width;
drawfn fn = NULL;
if (s->dest_width) {
fn = s->line_fn[s->transp][s->bpp];
}
if (!fn) {
return;
}
src_width = (s->xres + 3) & ~3; /* Pad to a 4 pixels multiple */
if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) {
src_width *= 3;
} else if (s->bpp > pxa_lcdc_16bpp) {
src_width *= 4;
} else if (s->bpp > pxa_lcdc_8bpp) {
src_width *= 2;
}
dest_width = s->xres * s->dest_width;
*miny = 0;
framebuffer_update_display(s->ds,
addr, s->xres, s->yres,
src_width, -dest_width, -s->dest_width,
s->invalidated,
fn, s->dma_ch[0].palette, miny, maxy);
}
static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
target_phys_addr_t addr, int *miny, int *maxy)
{
int src_width, dest_width;
drawfn fn = NULL;
if (s->dest_width) {
fn = s->line_fn[s->transp][s->bpp];
}
if (!fn) {
return;
}
src_width = (s->xres + 3) & ~3; /* Pad to a 4 pixels multiple */
if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) {
src_width *= 3;
} else if (s->bpp > pxa_lcdc_16bpp) {
src_width *= 4;
} else if (s->bpp > pxa_lcdc_8bpp) {
src_width *= 2;
}
dest_width = s->yres * s->dest_width;
*miny = 0;
framebuffer_update_display(s->ds,
addr, s->xres, s->yres,
src_width, -s->dest_width, dest_width,
s->invalidated,
fn, s->dma_ch[0].palette,
miny, maxy);
}
static void pxa2xx_lcdc_resize(PXA2xxLCDState *s)
{
int width, height;
@ -730,10 +791,11 @@ static void pxa2xx_lcdc_resize(PXA2xxLCDState *s)
height = LCCR2_LPP(s->control[2]) + 1;
if (width != s->xres || height != s->yres) {
if (s->orientation)
if (s->orientation == 90 || s->orientation == 270) {
qemu_console_resize(s->ds, height, width);
else
} else {
qemu_console_resize(s->ds, width, height);
}
s->invalidated = 1;
s->xres = width;
s->yres = height;
@ -797,10 +859,24 @@ static void pxa2xx_update_display(void *opaque)
}
if (miny >= 0) {
if (s->orientation)
dpy_update(s->ds, miny, 0, maxy - miny, s->xres);
else
dpy_update(s->ds, 0, miny, s->xres, maxy - miny);
switch (s->orientation) {
case 0:
dpy_update(s->ds, 0, miny, s->xres, maxy - miny + 1);
break;
case 90:
dpy_update(s->ds, miny, 0, maxy - miny + 1, s->xres);
break;
case 180:
maxy = s->yres - maxy - 1;
miny = s->yres - miny - 1;
dpy_update(s->ds, 0, maxy, s->xres, miny - maxy + 1);
break;
case 270:
maxy = s->yres - maxy - 1;
miny = s->yres - miny - 1;
dpy_update(s->ds, maxy, 0, miny - maxy + 1, s->xres);
break;
}
}
pxa2xx_lcdc_int_update(s);
@ -822,10 +898,19 @@ static void pxa2xx_lcdc_orientation(void *opaque, int angle)
{
PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
if (angle) {
s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_vert;
} else {
s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_horiz;
switch (angle) {
case 0:
s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot0;
break;
case 90:
s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot90;
break;
case 180:
s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot180;
break;
case 270:
s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot270;
break;
}
s->orientation = angle;

View File

@ -19,6 +19,7 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu-timer.h"
#include "qxl.h"
static const char *qxl_type[] = {
@ -223,7 +224,8 @@ void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext)
if (!qxl->cmdlog) {
return;
}
fprintf(stderr, "qxl-%d/%s:", qxl->id, ring);
fprintf(stderr, "%ld 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),
compat ? "(compat)" : "");

View File

@ -336,6 +336,21 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
info->n_surfaces = NUM_SURFACES;
}
static const char *qxl_mode_to_string(int mode)
{
switch (mode) {
case QXL_MODE_COMPAT:
return "compat";
case QXL_MODE_NATIVE:
return "native";
case QXL_MODE_UNDEFINED:
return "undefined";
case QXL_MODE_VGA:
return "vga";
}
return "INVALID";
}
/* called from spice server thread context only */
static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
{
@ -358,18 +373,19 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
}
qemu_mutex_unlock(&qxl->ssd.lock);
if (ret) {
dprint(qxl, 2, "%s %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
qxl_log_command(qxl, "vga", ext);
}
return ret;
case QXL_MODE_COMPAT:
case QXL_MODE_NATIVE:
case QXL_MODE_UNDEFINED:
dprint(qxl, 2, "%s: %s\n", __FUNCTION__,
qxl->cmdflags ? "compat" : "native");
dprint(qxl, 4, "%s: %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
ring = &qxl->ram->cmd_ring;
if (SPICE_RING_IS_EMPTY(ring)) {
return false;
}
dprint(qxl, 2, "%s: %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
SPICE_RING_CONS_ITEM(ring, cmd);
ext->cmd = *cmd;
ext->group_id = MEMSLOT_GROUP_GUEST;
@ -640,8 +656,8 @@ static void qxl_reset_state(PCIQXLDevice *d)
QXLRam *ram = d->ram;
QXLRom *rom = d->rom;
assert(SPICE_RING_IS_EMPTY(&ram->cmd_ring));
assert(SPICE_RING_IS_EMPTY(&ram->cursor_ring));
assert(!d->ssd.running || SPICE_RING_IS_EMPTY(&ram->cmd_ring));
assert(!d->ssd.running || SPICE_RING_IS_EMPTY(&ram->cursor_ring));
d->shadow_rom.update_id = cpu_to_le32(0);
*rom = d->shadow_rom;
qxl_rom_set_dirty(d);
@ -926,6 +942,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
case QXL_IO_MEMSLOT_ADD:
case QXL_IO_MEMSLOT_DEL:
case QXL_IO_CREATE_PRIMARY:
case QXL_IO_UPDATE_IRQ:
case QXL_IO_LOG:
break;
default:
if (d->mode == QXL_MODE_NATIVE || d->mode == QXL_MODE_COMPAT)
@ -969,7 +987,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
break;
case QXL_IO_LOG:
if (d->guestdebug) {
fprintf(stderr, "qxl/guest: %s", d->ram->log_buf);
fprintf(stderr, "qxl/guest-%d: %ld: %s", d->id,
qemu_get_clock_ns(vm_clock), d->ram->log_buf);
}
break;
case QXL_IO_RESET:
@ -993,7 +1012,7 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
break;
case QXL_IO_DESTROY_PRIMARY:
PANIC_ON(val != 0);
dprint(d, 1, "QXL_IO_DESTROY_PRIMARY\n");
dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (%s)\n", qxl_mode_to_string(d->mode));
qxl_destroy_primary(d);
break;
case QXL_IO_DESTROY_SURFACE_WAIT:
@ -1167,11 +1186,14 @@ static void qxl_vm_change_state_handler(void *opaque, int running, int reason)
qemu_spice_vm_change_state_handler(&qxl->ssd, running, reason);
if (!running && qxl->mode == QXL_MODE_NATIVE) {
/* dirty all vram (which holds surfaces) to make sure it is saved */
/* dirty all vram (which holds surfaces) and devram (primary surface)
* to make sure they are saved */
/* FIXME #1: should go out during "live" stage */
/* FIXME #2: we only need to save the areas which are actually used */
ram_addr_t addr = qxl->vram_offset;
qxl_set_dirty(addr, addr + qxl->vram_size);
ram_addr_t vram_addr = qxl->vram_offset;
ram_addr_t surface0_addr = qxl->vga.vram_offset + qxl->shadow_rom.draw_area_offset;
qxl_set_dirty(vram_addr, vram_addr + qxl->vram_size);
qxl_set_dirty(surface0_addr, surface0_addr + qxl->shadow_rom.surface0_area_size);
}
}
@ -1207,7 +1229,6 @@ static DisplayChangeListener display_listener = {
static int qxl_init_common(PCIQXLDevice *qxl)
{
uint8_t* config = qxl->pci.config;
uint32_t pci_device_id;
uint32_t pci_device_rev;
uint32_t io_size;
@ -1218,20 +1239,14 @@ static int qxl_init_common(PCIQXLDevice *qxl)
switch (qxl->revision) {
case 1: /* spice 0.4 -- qxl-1 */
pci_device_id = QXL_DEVICE_ID_STABLE;
pci_device_rev = QXL_REVISION_STABLE_V04;
break;
case 2: /* spice 0.6 -- qxl-2 */
pci_device_id = QXL_DEVICE_ID_STABLE;
default:
pci_device_rev = QXL_REVISION_STABLE_V06;
break;
default: /* experimental */
pci_device_id = QXL_DEVICE_ID_DEVEL;
pci_device_rev = 1;
break;
}
pci_config_set_device_id(config, pci_device_id);
pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev);
pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
@ -1375,7 +1390,8 @@ static int qxl_post_load(void *opaque, int version)
d->modes = (QXLModes*)((uint8_t*)d->rom + d->rom->modes_offset);
dprint(d, 1, "%s: restore mode\n", __FUNCTION__);
dprint(d, 1, "%s: restore mode (%s)\n", __FUNCTION__,
qxl_mode_to_string(d->mode));
newmode = d->mode;
d->mode = QXL_MODE_UNDEFINED;
switch (newmode) {
@ -1492,6 +1508,7 @@ static PCIDeviceInfo qxl_info_primary = {
.config_write = qxl_write_config,
.romfile = "vgabios-qxl.bin",
.vendor_id = REDHAT_PCI_VENDOR_ID,
.device_id = QXL_DEVICE_ID_STABLE,
.class_id = PCI_CLASS_DISPLAY_VGA,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024),
@ -1512,6 +1529,7 @@ static PCIDeviceInfo qxl_info_secondary = {
.qdev.vmsd = &qxl_vmstate,
.init = qxl_init_secondary,
.vendor_id = REDHAT_PCI_VENDOR_ID,
.device_id = QXL_DEVICE_ID_STABLE,
.class_id = PCI_CLASS_DISPLAY_OTHER,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024),

View File

@ -128,7 +128,8 @@ static int s390_virtio_blk_init(VirtIOS390Device *dev)
{
VirtIODevice *vdev;
vdev = virtio_blk_init((DeviceState *)dev, &dev->block);
vdev = virtio_blk_init((DeviceState *)dev, &dev->block,
&dev->block_serial);
if (!vdev) {
return -1;
}
@ -165,7 +166,7 @@ static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)
(vq * VIRTIO_VQCONFIG_LEN) +
VIRTIO_VQCONFIG_OFFS_TOKEN;
return ldq_phys(token_off);
return ldq_be_phys(token_off);
}
static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev)
@ -219,8 +220,8 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
vring = s390_virtio_next_ring(bus);
virtio_queue_set_addr(dev->vdev, i, vring);
virtio_queue_set_vector(dev->vdev, i, i);
stq_phys(vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring);
stw_phys(vq + VIRTIO_VQCONFIG_OFFS_NUM, virtio_queue_get_num(dev->vdev, i));
stq_be_phys(vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring);
stw_be_phys(vq + VIRTIO_VQCONFIG_OFFS_NUM, virtio_queue_get_num(dev->vdev, i));
}
cur_offs = dev->dev_offs;
@ -228,7 +229,7 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
cur_offs += num_vq * VIRTIO_VQCONFIG_LEN;
/* Sync feature bitmap */
stl_phys(cur_offs, bswap32(dev->host_features));
stl_le_phys(cur_offs, dev->host_features);
dev->feat_offs = cur_offs + dev->feat_len;
cur_offs += dev->feat_len * 2;
@ -252,7 +253,7 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev)
/* Update guest supported feature bitmap */
features = bswap32(ldl_phys(dev->feat_offs));
features = bswap32(ldl_be_phys(dev->feat_offs));
if (vdev->set_features) {
vdev->set_features(vdev, features);
}
@ -355,6 +356,7 @@ static VirtIOS390DeviceInfo s390_virtio_blk = {
.qdev.size = sizeof(VirtIOS390Device),
.qdev.props = (Property[]) {
DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, block),
DEFINE_PROP_STRING("serial", VirtIOS390Device, block_serial),
DEFINE_PROP_END_OF_LIST(),
},
};

View File

@ -42,6 +42,7 @@ typedef struct VirtIOS390Device {
uint8_t feat_len;
VirtIODevice *vdev;
BlockConf block;
char *block_serial;
NICConf nic;
uint32_t host_features;
virtio_serial_conf serial;

View File

@ -193,7 +193,7 @@ static void s390_init(ram_addr_t my_ram_size,
if (kernel_filename) {
kernel_size = load_image(kernel_filename, qemu_get_ram_ptr(0));
if (lduw_phys(KERN_IMAGE_START) != 0x0dd0) {
if (lduw_be_phys(KERN_IMAGE_START) != 0x0dd0) {
fprintf(stderr, "Specified image is not an s390 boot image\n");
exit(1);
}
@ -232,8 +232,8 @@ static void s390_init(ram_addr_t my_ram_size,
}
initrd_size = load_image(initrd_filename, qemu_get_ram_ptr(initrd_offset));
stq_phys(INITRD_PARM_START, initrd_offset);
stq_phys(INITRD_PARM_SIZE, initrd_size);
stq_be_phys(INITRD_PARM_START, initrd_offset);
stq_be_phys(INITRD_PARM_SIZE, initrd_size);
}
if (kernel_cmdline) {

View File

@ -131,7 +131,8 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
return res;
}
SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun)
SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag,
uint32_t lun, void *hba_private)
{
SCSIRequest *req;
@ -141,14 +142,16 @@ SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t l
req->dev = d;
req->tag = tag;
req->lun = lun;
req->hba_private = hba_private;
req->status = -1;
trace_scsi_req_alloc(req->dev->id, req->lun, req->tag);
return req;
}
SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun)
SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
void *hba_private)
{
return d->info->alloc_req(d, tag, lun);
return d->info->alloc_req(d, tag, lun, hba_private);
}
uint8_t *scsi_req_get_buf(SCSIRequest *req)

View File

@ -81,13 +81,13 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type);
static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf);
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag,
uint32_t lun)
uint32_t lun, void *hba_private)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
SCSIRequest *req;
SCSIDiskReq *r;
req = scsi_req_alloc(sizeof(SCSIDiskReq), &s->qdev, tag, lun);
req = scsi_req_alloc(sizeof(SCSIDiskReq), &s->qdev, tag, lun, hba_private);
r = DO_UPCAST(SCSIDiskReq, req, req);
r->iov.iov_base = qemu_blockalign(s->bs, SCSI_DMA_BUF_SIZE);
return req;
@ -398,7 +398,8 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
"buffer size %zd\n", req->cmd.xfer);
pages = buflen++;
outbuf[buflen++] = 0x00; // list of supported pages (this page)
outbuf[buflen++] = 0x80; // unit serial number
if (s->serial)
outbuf[buflen++] = 0x80; // unit serial number
outbuf[buflen++] = 0x83; // device identification
if (s->drive_kind == SCSI_HD) {
outbuf[buflen++] = 0xb0; // block limits
@ -409,8 +410,14 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
}
case 0x80: /* Device serial number, optional */
{
int l = strlen(s->serial);
int l;
if (!s->serial) {
DPRINTF("Inquiry (EVPD[Serial number] not supported\n");
return -1;
}
l = strlen(s->serial);
if (l > req->cmd.xfer)
l = req->cmd.xfer;
if (l > 20)
@ -1007,7 +1014,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
command = buf[0];
outbuf = (uint8_t *)r->iov.iov_base;
DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", req->lun, req->tag, buf[0]);
if (scsi_req_parse(&r->req, buf) != 0) {
BADF("Unsupported command length, command %x\n", command);
@ -1203,7 +1210,9 @@ static int scsi_initfn(SCSIDevice *dev, SCSIDriveKind kind)
if (!s->serial) {
/* try to fall back to value set with legacy -drive serial=... */
dinfo = drive_get_by_blockdev(s->bs);
s->serial = qemu_strdup(*dinfo->serial ? dinfo->serial : "0");
if (*dinfo->serial) {
s->serial = qemu_strdup(dinfo->serial);
}
}
if (!s->version) {

View File

@ -96,11 +96,12 @@ static int scsi_get_sense(SCSIRequest *req, uint8_t *outbuf, int len)
return size;
}
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
void *hba_private)
{
SCSIRequest *req;
req = scsi_req_alloc(sizeof(SCSIGenericReq), d, tag, lun);
req = scsi_req_alloc(sizeof(SCSIGenericReq), d, tag, lun, hba_private);
return req;
}

View File

@ -43,6 +43,7 @@ struct SCSIRequest {
} cmd;
BlockDriverAIOCB *aiocb;
bool enqueued;
void *hba_private;
QTAILQ_ENTRY(SCSIRequest) next;
};
@ -67,7 +68,8 @@ struct SCSIDeviceInfo {
DeviceInfo qdev;
scsi_qdev_initfn init;
void (*destroy)(SCSIDevice *s);
SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun);
SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
void *hba_private);
void (*free_req)(SCSIRequest *req);
int32_t (*send_command)(SCSIRequest *req, uint8_t *buf);
void (*read_data)(SCSIRequest *req);
@ -138,8 +140,10 @@ extern const struct SCSISense sense_code_LUN_FAILURE;
int scsi_build_sense(SCSISense sense, uint8_t *buf, int len, int fixed);
int scsi_sense_valid(SCSISense sense);
SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun);
SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun);
SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag,
uint32_t lun, void *hba_private);
SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
void *hba_private);
int32_t scsi_req_enqueue(SCSIRequest *req, uint8_t *buf);
void scsi_req_free(SCSIRequest *req);
SCSIRequest *scsi_req_ref(SCSIRequest *req);

View File

@ -280,12 +280,12 @@ target_ulong spapr_hypercall(CPUState *env, target_ulong opcode,
static inline uint32_t rtas_ld(target_ulong phys, int n)
{
return ldl_phys(phys + 4*n);
return ldl_be_phys(phys + 4*n);
}
static inline void rtas_st(target_ulong phys, int n, uint32_t val)
{
stl_phys(phys + 4*n, val);
stl_be_phys(phys + 4*n, val);
}
typedef void (*spapr_rtas_fn)(sPAPREnvironment *spapr, uint32_t token,

View File

@ -278,7 +278,7 @@ static target_ulong register_vpa(CPUState *env, target_ulong vpa)
}
/* FIXME: bounds check the address */
size = lduw_phys(vpa + 0x4);
size = lduw_be_phys(vpa + 0x4);
if (size < VPA_MIN_SIZE) {
return H_PARAMETER;
@ -321,7 +321,7 @@ static target_ulong register_slb_shadow(CPUState *env, target_ulong addr)
return H_HARDWARE;
}
size = ldl_phys(addr + 0x4);
size = ldl_be_phys(addr + 0x4);
if (size < 0x8) {
return H_PARAMETER;
}
@ -354,7 +354,7 @@ static target_ulong register_dtl(CPUState *env, target_ulong addr)
return H_HARDWARE;
}
size = ldl_phys(addr + 0x4);
size = ldl_be_phys(addr + 0x4);
if (size < 48) {
return H_PARAMETER;
@ -441,9 +441,9 @@ static target_ulong h_rtas(CPUState *env, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong rtas_r3 = args[0];
uint32_t token = ldl_phys(rtas_r3);
uint32_t nargs = ldl_phys(rtas_r3 + 4);
uint32_t nret = ldl_phys(rtas_r3 + 8);
uint32_t token = ldl_be_phys(rtas_r3);
uint32_t nargs = ldl_be_phys(rtas_r3 + 4);
uint32_t nret = ldl_be_phys(rtas_r3 + 8);
return spapr_rtas_call(spapr, token, nargs, rtas_r3 + 12,
nret, rtas_r3 + 12 + 4*nargs);

View File

@ -121,7 +121,7 @@ static struct vscsi_req *vscsi_get_req(VSCSIState *s)
return NULL;
}
static void vscsi_put_req(VSCSIState *s, vscsi_req *req)
static void vscsi_put_req(vscsi_req *req)
{
if (req->sreq != NULL) {
scsi_req_unref(req->sreq);
@ -130,15 +130,6 @@ static void vscsi_put_req(VSCSIState *s, vscsi_req *req)
req->active = 0;
}
static vscsi_req *vscsi_find_req(VSCSIState *s, SCSIRequest *req)
{
uint32_t tag = req->tag;
if (tag >= VSCSI_REQ_LIMIT || !s->reqs[tag].active) {
return NULL;
}
return &s->reqs[tag];
}
static void vscsi_decode_id_lun(uint64_t srp_lun, int *id, int *lun)
{
/* XXX Figure that one out properly ! This is crackpot */
@ -454,7 +445,7 @@ static void vscsi_send_request_sense(VSCSIState *s, vscsi_req *req)
if (n) {
req->senselen = n;
vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
vscsi_put_req(s, req);
vscsi_put_req(req);
return;
}
@ -483,7 +474,7 @@ static void vscsi_send_request_sense(VSCSIState *s, vscsi_req *req)
static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len)
{
VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
vscsi_req *req = vscsi_find_req(s, sreq);
vscsi_req *req = sreq->hba_private;
uint8_t *buf;
int rc = 0;
@ -531,7 +522,7 @@ static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len)
static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status)
{
VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
vscsi_req *req = vscsi_find_req(s, sreq);
vscsi_req *req = sreq->hba_private;
int32_t res_in = 0, res_out = 0;
dprintf("VSCSI: SCSI cmd complete, r=0x%x tag=0x%x status=0x%x, req=%p\n",
@ -563,15 +554,14 @@ static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status)
}
}
vscsi_send_rsp(s, req, 0, res_in, res_out);
vscsi_put_req(s, req);
vscsi_put_req(req);
}
static void vscsi_request_cancelled(SCSIRequest *sreq)
{
VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
vscsi_req *req = vscsi_find_req(s, sreq);
vscsi_req *req = sreq->hba_private;
vscsi_put_req(s, req);
vscsi_put_req(req);
}
static void vscsi_process_login(VSCSIState *s, vscsi_req *req)
@ -659,7 +649,7 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
}
req->lun = lun;
req->sreq = scsi_req_new(sdev, req->qtag, lun);
req->sreq = scsi_req_new(sdev, req->qtag, lun, req);
n = scsi_req_enqueue(req->sreq, srp->cmd.cdb);
dprintf("VSCSI: Queued command tag 0x%x CMD 0x%x ID %d LUN %d ret: %d\n",
@ -858,7 +848,7 @@ static void vscsi_got_payload(VSCSIState *s, vscsi_crq *crq)
}
if (done) {
vscsi_put_req(s, req);
vscsi_put_req(req);
}
}

View File

@ -99,13 +99,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
.eps = (USBDescEndpoint[]) {
{
.bEndpointAddress = USB_DIR_OUT | USB_SCO_EP,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = 0,
.bInterval = 0x01,
},
{
.bEndpointAddress = USB_DIR_IN | USB_SCO_EP,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = 0,
.bInterval = 0x01,
},
@ -120,13 +120,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
.eps = (USBDescEndpoint[]) {
{
.bEndpointAddress = USB_DIR_OUT | USB_SCO_EP,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = 0x09,
.bInterval = 0x01,
},
{
.bEndpointAddress = USB_DIR_IN | USB_SCO_EP,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = 0x09,
.bInterval = 0x01,
},
@ -141,13 +141,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
.eps = (USBDescEndpoint[]) {
{
.bEndpointAddress = USB_DIR_OUT | USB_SCO_EP,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = 0x11,
.bInterval = 0x01,
},
{
.bEndpointAddress = USB_DIR_IN | USB_SCO_EP,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = 0x11,
.bInterval = 0x01,
},
@ -162,13 +162,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
.eps = (USBDescEndpoint[]) {
{
.bEndpointAddress = USB_DIR_OUT | USB_SCO_EP,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = 0x19,
.bInterval = 0x01,
},
{
.bEndpointAddress = USB_DIR_IN | USB_SCO_EP,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = 0x19,
.bInterval = 0x01,
},
@ -183,13 +183,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
.eps = (USBDescEndpoint[]) {
{
.bEndpointAddress = USB_DIR_OUT | USB_SCO_EP,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = 0x21,
.bInterval = 0x01,
},
{
.bEndpointAddress = USB_DIR_IN | USB_SCO_EP,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = 0x21,
.bInterval = 0x01,
},
@ -204,13 +204,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
.eps = (USBDescEndpoint[]) {
{
.bEndpointAddress = USB_DIR_OUT | USB_SCO_EP,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = 0x31,
.bInterval = 0x01,
},
{
.bEndpointAddress = USB_DIR_IN | USB_SCO_EP,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = 0x31,
.bInterval = 0x01,
},

View File

@ -82,12 +82,10 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
static int usb_qdev_exit(DeviceState *qdev)
{
USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
USBBus *bus = usb_bus_from_device(dev);
if (dev->attached) {
usb_device_detach(dev);
}
bus->ops->device_destroy(bus, dev);
if (dev->info->handle_destroy) {
dev->info->handle_destroy(dev);
}
@ -140,19 +138,55 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name)
return dev;
}
void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
USBPortOps *ops, int speedmask)
static void usb_fill_port(USBPort *port, void *opaque, int index,
USBPortOps *ops, int speedmask)
{
port->opaque = opaque;
port->index = index;
port->opaque = opaque;
port->index = index;
port->ops = ops;
port->speedmask = speedmask;
usb_port_location(port, NULL, index + 1);
}
void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
USBPortOps *ops, int speedmask)
{
usb_fill_port(port, opaque, index, ops, speedmask);
QTAILQ_INSERT_TAIL(&bus->free, port, next);
bus->nfree++;
}
int usb_register_companion(const char *masterbus, USBPort *ports[],
uint32_t portcount, uint32_t firstport,
void *opaque, USBPortOps *ops, int speedmask)
{
USBBus *bus;
int i;
QTAILQ_FOREACH(bus, &busses, next) {
if (strcmp(bus->qbus.name, masterbus) == 0) {
break;
}
}
if (!bus || !bus->ops->register_companion) {
qerror_report(QERR_INVALID_PARAMETER_VALUE, "masterbus",
"an USB masterbus");
if (bus) {
error_printf_unless_qmp(
"USB bus '%s' does not allow companion controllers\n",
masterbus);
}
return -1;
}
for (i = 0; i < portcount; i++) {
usb_fill_port(ports[i], opaque, i, ops, speedmask);
}
return bus->ops->register_companion(bus, ports, portcount, firstport);
}
void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr)
{
if (upstream) {

View File

@ -20,9 +20,6 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* TODO:
* o Downstream port handoff
*/
#include "hw.h"
@ -103,10 +100,10 @@
#define PORTSC_BEGIN PORTSC
#define PORTSC_END (PORTSC + 4 * NB_PORTS)
/*
* Bits that are reserverd or are read-only are masked out of values
* Bits that are reserved or are read-only are masked out of values
* written to us by software
*/
#define PORTSC_RO_MASK 0x007021c5
#define PORTSC_RO_MASK 0x007001c0
#define PORTSC_RWC_MASK 0x0000002a
#define PORTSC_WKOC_E (1 << 22) // Wake on Over Current Enable
#define PORTSC_WKDS_E (1 << 21) // Wake on Disconnect Enable
@ -133,7 +130,7 @@
#define FRAME_TIMER_NS (1000000000 / FRAME_TIMER_FREQ)
#define NB_MAXINTRATE 8 // Max rate at which controller issues ints
#define NB_PORTS 4 // Number of downstream ports
#define NB_PORTS 6 // Number of downstream ports
#define BUFF_SIZE 5*4096 // Max bytes to transfer per transaction
#define MAX_ITERATIONS 20 // Max number of QH before we break the loop
#define MAX_QH 100 // Max allowable queue heads in a chain
@ -373,7 +370,7 @@ struct EHCIState {
qemu_irq irq;
target_phys_addr_t mem_base;
int mem;
int num_ports;
int companion_count;
/* properties */
uint32_t freq;
@ -409,6 +406,7 @@ struct EHCIState {
int astate; // Current state in asynchronous schedule
int pstate; // Current state in periodic schedule
USBPort ports[NB_PORTS];
USBPort *companion_ports[NB_PORTS];
uint32_t usbsts_pending;
QTAILQ_HEAD(, EHCIQueue) queues;
@ -731,17 +729,17 @@ static void ehci_attach(USBPort *port)
trace_usb_ehci_port_attach(port->index, port->dev->product_desc);
if (*portsc & PORTSC_POWNER) {
USBPort *companion = s->companion_ports[port->index];
companion->dev = port->dev;
companion->ops->attach(companion);
return;
}
*portsc |= PORTSC_CONNECT;
*portsc |= PORTSC_CSC;
/*
* If a high speed device is attached then we own this port(indicated
* by zero in the PORTSC_POWNER bit field) so set the status bit
* and set an interrupt if enabled.
*/
if ( !(*portsc & PORTSC_POWNER)) {
ehci_set_interrupt(s, USBSTS_PCD);
}
ehci_set_interrupt(s, USBSTS_PCD);
}
static void ehci_detach(USBPort *port)
@ -751,17 +749,88 @@ static void ehci_detach(USBPort *port)
trace_usb_ehci_port_detach(port->index);
*portsc &= ~PORTSC_CONNECT;
if (*portsc & PORTSC_POWNER) {
USBPort *companion = s->companion_ports[port->index];
companion->ops->detach(companion);
companion->dev = NULL;
return;
}
ehci_queues_rip_device(s, port->dev);
*portsc &= ~(PORTSC_CONNECT|PORTSC_PED);
*portsc |= PORTSC_CSC;
/*
* If a high speed device is attached then we own this port(indicated
* by zero in the PORTSC_POWNER bit field) so set the status bit
* and set an interrupt if enabled.
*/
if ( !(*portsc & PORTSC_POWNER)) {
ehci_set_interrupt(s, USBSTS_PCD);
ehci_set_interrupt(s, USBSTS_PCD);
}
static void ehci_child_detach(USBPort *port, USBDevice *child)
{
EHCIState *s = port->opaque;
uint32_t portsc = s->portsc[port->index];
if (portsc & PORTSC_POWNER) {
USBPort *companion = s->companion_ports[port->index];
companion->ops->child_detach(companion, child);
companion->dev = NULL;
return;
}
ehci_queues_rip_device(s, child);
}
static void ehci_wakeup(USBPort *port)
{
EHCIState *s = port->opaque;
uint32_t portsc = s->portsc[port->index];
if (portsc & PORTSC_POWNER) {
USBPort *companion = s->companion_ports[port->index];
if (companion->ops->wakeup) {
companion->ops->wakeup(companion);
}
}
}
static int ehci_register_companion(USBBus *bus, USBPort *ports[],
uint32_t portcount, uint32_t firstport)
{
EHCIState *s = container_of(bus, EHCIState, bus);
uint32_t i;
if (firstport + portcount > NB_PORTS) {
qerror_report(QERR_INVALID_PARAMETER_VALUE, "firstport",
"firstport on masterbus");
error_printf_unless_qmp(
"firstport value of %u makes companion take ports %u - %u, which "
"is outside of the valid range of 0 - %u\n", firstport, firstport,
firstport + portcount - 1, NB_PORTS - 1);
return -1;
}
for (i = 0; i < portcount; i++) {
if (s->companion_ports[firstport + i]) {
qerror_report(QERR_INVALID_PARAMETER_VALUE, "masterbus",
"an USB masterbus");
error_printf_unless_qmp(
"port %u on masterbus %s already has a companion assigned\n",
firstport + i, bus->qbus.name);
return -1;
}
}
for (i = 0; i < portcount; i++) {
s->companion_ports[firstport + i] = ports[i];
s->ports[firstport + i].speedmask |=
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL;
/* Ensure devs attached before the initial reset go to the companion */
s->portsc[firstport + i] = PORTSC_POWNER;
}
s->companion_count++;
s->mmio[0x05] = (s->companion_count << 4) | portcount;
return 0;
}
/* 4.1 host controller initialization */
@ -769,9 +838,21 @@ static void ehci_reset(void *opaque)
{
EHCIState *s = opaque;
int i;
USBDevice *devs[NB_PORTS];
trace_usb_ehci_reset();
/*
* Do the detach before touching portsc, so that it correctly gets send to
* us or to our companion based on PORTSC_POWNER before the reset.
*/
for(i = 0; i < NB_PORTS; i++) {
devs[i] = s->ports[i].dev;
if (devs[i]) {
usb_attach(&s->ports[i], NULL);
}
}
memset(&s->mmio[OPREGBASE], 0x00, MMIO_SIZE - OPREGBASE);
s->usbcmd = NB_MAXINTRATE << USBCMD_ITC_SH;
@ -783,10 +864,13 @@ static void ehci_reset(void *opaque)
s->attach_poll_counter = 0;
for(i = 0; i < NB_PORTS; i++) {
s->portsc[i] = PORTSC_POWNER | PORTSC_PPOWER;
if (s->ports[i].dev) {
usb_attach(&s->ports[i], s->ports[i].dev);
if (s->companion_ports[i]) {
s->portsc[i] = PORTSC_POWNER | PORTSC_PPOWER;
} else {
s->portsc[i] = PORTSC_PPOWER;
}
if (devs[i]) {
usb_attach(&s->ports[i], devs[i]);
}
}
ehci_queues_rip_all(s);
@ -836,43 +920,67 @@ static void ehci_mem_writew(void *ptr, target_phys_addr_t addr, uint32_t val)
exit(1);
}
static void handle_port_owner_write(EHCIState *s, int port, uint32_t owner)
{
USBDevice *dev = s->ports[port].dev;
uint32_t *portsc = &s->portsc[port];
uint32_t orig;
if (s->companion_ports[port] == NULL)
return;
owner = owner & PORTSC_POWNER;
orig = *portsc & PORTSC_POWNER;
if (!(owner ^ orig)) {
return;
}
if (dev) {
usb_attach(&s->ports[port], NULL);
}
*portsc &= ~PORTSC_POWNER;
*portsc |= owner;
if (dev) {
usb_attach(&s->ports[port], dev);
}
}
static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
{
uint32_t *portsc = &s->portsc[port];
int rwc;
USBDevice *dev = s->ports[port].dev;
rwc = val & PORTSC_RWC_MASK;
/* Clear rwc bits */
*portsc &= ~(val & PORTSC_RWC_MASK);
/* The guest may clear, but not set the PED bit */
*portsc &= val | ~PORTSC_PED;
/* POWNER is masked out by RO_MASK as it is RO when we've no companion */
handle_port_owner_write(s, port, val);
/* And finally apply RO_MASK */
val &= PORTSC_RO_MASK;
// handle_read_write_clear(&val, portsc, PORTSC_PEDC | PORTSC_CSC);
*portsc &= ~rwc;
if ((val & PORTSC_PRESET) && !(*portsc & PORTSC_PRESET)) {
trace_usb_ehci_port_reset(port, 1);
}
if (!(val & PORTSC_PRESET) &&(*portsc & PORTSC_PRESET)) {
trace_usb_ehci_port_reset(port, 0);
usb_attach(&s->ports[port], dev);
// TODO how to handle reset of ports with no device
if (dev) {
usb_attach(&s->ports[port], dev);
usb_send_msg(dev, USB_MSG_RESET);
}
if (s->ports[port].dev) {
*portsc &= ~PORTSC_CSC;
}
/* Table 2.16 Set the enable bit(and enable bit change) to indicate
/*
* Table 2.16 Set the enable bit(and enable bit change) to indicate
* to SW that this port has a high speed device attached
*
* TODO - when to disable?
*/
val |= PORTSC_PED;
val |= PORTSC_PEDC;
if (dev && (dev->speedmask & USB_SPEED_MASK_HIGH)) {
val |= PORTSC_PED;
}
}
*portsc &= ~PORTSC_RO_MASK;
@ -955,7 +1063,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
val &= 0x1;
if (val) {
for(i = 0; i < NB_PORTS; i++)
s->portsc[i] &= ~PORTSC_POWNER;
handle_port_owner_write(s, i, 0);
}
break;
@ -1111,10 +1219,19 @@ static int ehci_buffer_rw(EHCIQueue *q, int bytes, int rw)
return 0;
}
static void ehci_async_complete_packet(USBDevice *dev, USBPacket *packet)
static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
{
EHCIQueue *q = container_of(packet, EHCIQueue, packet);
EHCIQueue *q;
EHCIState *s = port->opaque;
uint32_t portsc = s->portsc[port->index];
if (portsc & PORTSC_POWNER) {
USBPort *companion = s->companion_ports[port->index];
companion->ops->complete(companion, packet);
return;
}
q = container_of(packet, EHCIQueue, packet);
trace_usb_ehci_queue_action(q, "wakeup");
assert(q->async == EHCI_ASYNC_INFLIGHT);
q->async = EHCI_ASYNC_FINISHED;
@ -1244,8 +1361,6 @@ static int ehci_execute(EHCIQueue *q)
port = &q->ehci->ports[i];
dev = port->dev;
// TODO sometime we will also need to check if we are the port owner
if (!(q->ehci->portsc[i] &(PORTSC_CONNECT))) {
DPRINTF("Port %d, no exec, not connected(%08X)\n",
i, q->ehci->portsc[i]);
@ -1338,8 +1453,6 @@ static int ehci_process_itd(EHCIState *ehci,
port = &ehci->ports[j];
dev = port->dev;
// TODO sometime we will also need to check if we are the port owner
if (!(ehci->portsc[j] &(PORTSC_CONNECT))) {
continue;
}
@ -2117,38 +2230,48 @@ static void ehci_map(PCIDevice *pci_dev, int region_num,
cpu_register_physical_memory(addr, size, s->mem);
}
static void ehci_device_destroy(USBBus *bus, USBDevice *dev)
{
EHCIState *s = container_of(bus, EHCIState, bus);
ehci_queues_rip_device(s, dev);
}
static int usb_ehci_initfn(PCIDevice *dev);
static USBPortOps ehci_port_ops = {
.attach = ehci_attach,
.detach = ehci_detach,
.child_detach = ehci_child_detach,
.wakeup = ehci_wakeup,
.complete = ehci_async_complete_packet,
};
static USBBusOps ehci_bus_ops = {
.device_destroy = ehci_device_destroy,
.register_companion = ehci_register_companion,
};
static PCIDeviceInfo ehci_info = {
.qdev.name = "usb-ehci",
.qdev.size = sizeof(EHCIState),
.init = usb_ehci_initfn,
.vendor_id = PCI_VENDOR_ID_INTEL,
.device_id = PCI_DEVICE_ID_INTEL_82801D,
.revision = 0x10,
.class_id = PCI_CLASS_SERIAL_USB,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("freq", EHCIState, freq, FRAME_TIMER_FREQ),
DEFINE_PROP_UINT32("maxframes", EHCIState, maxframes, 128),
DEFINE_PROP_END_OF_LIST(),
},
static Property ehci_properties[] = {
DEFINE_PROP_UINT32("freq", EHCIState, freq, FRAME_TIMER_FREQ),
DEFINE_PROP_UINT32("maxframes", EHCIState, maxframes, 128),
DEFINE_PROP_END_OF_LIST(),
};
static PCIDeviceInfo ehci_info[] = {
{
.qdev.name = "usb-ehci",
.qdev.size = sizeof(EHCIState),
.init = usb_ehci_initfn,
.vendor_id = PCI_VENDOR_ID_INTEL,
.device_id = PCI_DEVICE_ID_INTEL_82801D, /* ich4 */
.revision = 0x10,
.class_id = PCI_CLASS_SERIAL_USB,
.qdev.props = ehci_properties,
},{
.qdev.name = "ich9-usb-ehci1",
.qdev.size = sizeof(EHCIState),
.init = usb_ehci_initfn,
.vendor_id = PCI_VENDOR_ID_INTEL,
.device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1,
.revision = 0x03,
.class_id = PCI_CLASS_SERIAL_USB,
.qdev.props = ehci_properties,
},{
/* end of list */
}
};
static int usb_ehci_initfn(PCIDevice *dev)
@ -2206,7 +2329,6 @@ static int usb_ehci_initfn(PCIDevice *dev)
for(i = 0; i < NB_PORTS; i++) {
usb_register_port(&s->bus, &s->ports[i], s, i, &ehci_port_ops,
USB_SPEED_MASK_HIGH);
usb_port_location(&s->ports[i], NULL, i+1);
s->ports[i].dev = 0;
}
@ -2228,7 +2350,7 @@ static int usb_ehci_initfn(PCIDevice *dev)
static void ehci_register(void)
{
pci_qdev_register(&ehci_info);
pci_qdev_register_many(ehci_info);
}
device_init(ehci_register);

View File

@ -531,18 +531,15 @@ static void usb_keyboard_process_keycode(USBHIDState *hs)
case 0xe0:
if (s->modifiers & (1 << 9)) {
s->modifiers ^= 3 << 8;
usb_hid_changed(hs);
return;
}
case 0xe1 ... 0xe7:
if (keycode & (1 << 7)) {
s->modifiers &= ~(1 << (hid_code & 0x0f));
usb_hid_changed(hs);
return;
}
case 0xe8 ... 0xef:
s->modifiers |= 1 << (hid_code & 0x0f);
usb_hid_changed(hs);
return;
}
@ -769,10 +766,12 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
}
break;
case GET_REPORT:
if (s->kind == USB_MOUSE || s->kind == USB_TABLET)
if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
ret = usb_pointer_poll(s, data, length);
else if (s->kind == USB_KEYBOARD)
} else if (s->kind == USB_KEYBOARD) {
ret = usb_keyboard_poll(s, data, length);
}
s->changed = s->n > 0;
break;
case SET_REPORT:
if (s->kind == USB_KEYBOARD)

View File

@ -138,74 +138,6 @@ static const USBDesc desc_hub = {
.str = desc_strings,
};
static const uint8_t qemu_hub_dev_descriptor[] = {
0x12, /* u8 bLength; */
0x01, /* u8 bDescriptorType; Device */
0x10, 0x01, /* u16 bcdUSB; v1.1 */
0x09, /* u8 bDeviceClass; HUB_CLASSCODE */
0x00, /* u8 bDeviceSubClass; */
0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
0x08, /* u8 bMaxPacketSize0; 8 Bytes */
0x00, 0x00, /* u16 idVendor; */
0x00, 0x00, /* u16 idProduct; */
0x01, 0x01, /* u16 bcdDevice */
0x03, /* u8 iManufacturer; */
0x02, /* u8 iProduct; */
0x01, /* u8 iSerialNumber; */
0x01 /* u8 bNumConfigurations; */
};
/* XXX: patch interrupt size */
static const uint8_t qemu_hub_config_descriptor[] = {
/* one configuration */
0x09, /* u8 bLength; */
0x02, /* u8 bDescriptorType; Configuration */
0x19, 0x00, /* u16 wTotalLength; */
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 */
0x00, /* u8 MaxPower; */
/* USB 1.1:
* USB 2.0, single TT organization (mandatory):
* one interface, protocol 0
*
* USB 2.0, multiple TT organization (optional):
* two interfaces, protocols 1 (like single TT)
* and 2 (multiple TT mode) ... config is
* sometimes settable
* NOT IMPLEMENTED
*/
/* one interface */
0x09, /* u8 if_bLength; */
0x04, /* u8 if_bDescriptorType; Interface */
0x00, /* u8 if_bInterfaceNumber; */
0x00, /* u8 if_bAlternateSetting; */
0x01, /* u8 if_bNumEndpoints; */
0x09, /* u8 if_bInterfaceClass; HUB_CLASSCODE */
0x00, /* u8 if_bInterfaceSubClass; */
0x00, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
0x00, /* u8 if_iInterface; */
/* one endpoint (status change endpoint) */
0x07, /* u8 ep_bLength; */
0x05, /* u8 ep_bDescriptorType; Endpoint */
0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
0x03, /* u8 ep_bmAttributes; Interrupt */
0x02, 0x00, /* u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
0xff /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
};
static const uint8_t qemu_hub_hub_descriptor[] =
{
0x00, /* u8 bLength; patched in later */
@ -238,6 +170,9 @@ static void usb_hub_detach(USBPort *port1)
USBHubState *s = port1->opaque;
USBHubPort *port = &s->ports[port1->index];
/* Let upstream know the device on this port is gone */
s->dev.port->ops->child_detach(s->dev.port, port1->dev);
port->wPortStatus &= ~PORT_STAT_CONNECTION;
port->wPortChange |= PORT_STAT_C_CONNECTION;
if (port->wPortStatus & PORT_STAT_ENABLE) {
@ -246,10 +181,18 @@ static void usb_hub_detach(USBPort *port1)
}
}
static void usb_hub_wakeup(USBDevice *dev)
static void usb_hub_child_detach(USBPort *port1, USBDevice *child)
{
USBHubState *s = dev->port->opaque;
USBHubPort *port = &s->ports[dev->port->index];
USBHubState *s = port1->opaque;
/* Pass along upstream */
s->dev.port->ops->child_detach(s->dev.port, child);
}
static void usb_hub_wakeup(USBPort *port1)
{
USBHubState *s = port1->opaque;
USBHubPort *port = &s->ports[port1->index];
if (port->wPortStatus & PORT_STAT_SUSPEND) {
port->wPortChange |= PORT_STAT_C_SUSPEND;
@ -257,9 +200,9 @@ static void usb_hub_wakeup(USBDevice *dev)
}
}
static void usb_hub_complete(USBDevice *dev, USBPacket *packet)
static void usb_hub_complete(USBPort *port, USBPacket *packet)
{
USBHubState *s = dev->port->opaque;
USBHubState *s = port->opaque;
/*
* Just pass it along upstream for now.
@ -537,6 +480,7 @@ static void usb_hub_handle_destroy(USBDevice *dev)
static USBPortOps usb_hub_port_ops = {
.attach = usb_hub_attach,
.detach = usb_hub_detach,
.child_detach = usb_hub_child_detach,
.wakeup = usb_hub_wakeup,
.complete = usb_hub_complete,
};

View File

@ -216,10 +216,6 @@ static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
USBPacket *p = s->packet;
if (req->tag != s->tag) {
fprintf(stderr, "usb-msd: Unexpected SCSI Tag 0x%x\n", req->tag);
}
assert((s->mode == USB_MSDM_DATAOUT) == (req->cmd.mode == SCSI_XFER_TO_DEV));
s->scsi_len = len;
s->scsi_buf = scsi_req_get_buf(req);
@ -241,9 +237,6 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status)
MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
USBPacket *p = s->packet;
if (req->tag != s->tag) {
fprintf(stderr, "usb-msd: Unexpected SCSI Tag 0x%x\n", req->tag);
}
DPRINTF("Command complete %d\n", status);
s->residue = s->data_len;
s->result = status != 0;
@ -387,7 +380,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
s->tag, cbw.flags, cbw.cmd_len, s->data_len);
s->residue = 0;
s->scsi_len = 0;
s->req = scsi_req_new(s->scsi_dev, s->tag, 0);
s->req = scsi_req_new(s->scsi_dev, s->tag, 0, NULL);
scsi_req_enqueue(s->req, cbw.cmd);
/* ??? Should check that USB and SCSI data transfer
directions match. */

View File

@ -261,17 +261,18 @@
static void musb_attach(USBPort *port);
static void musb_detach(USBPort *port);
static void musb_schedule_cb(USBDevice *dev, USBPacket *p);
static void musb_device_destroy(USBBus *bus, USBDevice *dev);
static void musb_child_detach(USBPort *port, USBDevice *child);
static void musb_schedule_cb(USBPort *port, USBPacket *p);
static void musb_async_cancel_device(MUSBState *s, USBDevice *dev);
static USBPortOps musb_port_ops = {
.attach = musb_attach,
.detach = musb_detach,
.child_detach = musb_child_detach,
.complete = musb_schedule_cb,
};
static USBBusOps musb_bus_ops = {
.device_destroy = musb_device_destroy,
};
typedef struct MUSBPacket MUSBPacket;
@ -369,7 +370,6 @@ struct MUSBState *musb_init(qemu_irq *irqs)
usb_bus_new(&s->bus, &musb_bus_ops, NULL /* FIXME */);
usb_register_port(&s->bus, &s->port, s, 0, &musb_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
usb_port_location(&s->port, NULL, 1);
return s;
}
@ -498,10 +498,19 @@ static void musb_detach(USBPort *port)
{
MUSBState *s = (MUSBState *) port->opaque;
musb_async_cancel_device(s, port->dev);
musb_intr_set(s, musb_irq_disconnect, 1);
musb_session_update(s, 1, s->session);
}
static void musb_child_detach(USBPort *port, USBDevice *child)
{
MUSBState *s = (MUSBState *) port->opaque;
musb_async_cancel_device(s, child);
}
static void musb_cb_tick0(void *opaque)
{
MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
@ -518,7 +527,7 @@ static void musb_cb_tick1(void *opaque)
#define musb_cb_tick (dir ? musb_cb_tick1 : musb_cb_tick0)
static void musb_schedule_cb(USBDevice *dev, USBPacket *packey)
static void musb_schedule_cb(USBPort *port, USBPacket *packey)
{
MUSBPacket *p = container_of(packey, MUSBPacket, p);
MUSBEndPoint *ep = p->ep;
@ -616,7 +625,7 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
}
ep->status[dir] = ret;
usb_packet_complete(s->port.dev, &ep->packey[dir].p);
musb_schedule_cb(&s->port, &ep->packey[dir].p);
}
static void musb_tx_packet_complete(USBPacket *packey, void *opaque)
@ -783,9 +792,8 @@ static void musb_rx_packet_complete(USBPacket *packey, void *opaque)
musb_rx_intr_set(s, epnum, 1);
}
static void musb_device_destroy(USBBus *bus, USBDevice *dev)
static void musb_async_cancel_device(MUSBState *s, USBDevice *dev)
{
MUSBState *s = container_of(bus, MUSBState, bus);
int ep, dir;
for (ep = 0; ep < 16; ep++) {

View File

@ -124,6 +124,7 @@ struct ohci_hcca {
};
static void ohci_bus_stop(OHCIState *ohci);
static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev);
/* Bitfields for the first word of an Endpoint Desciptor. */
#define OHCI_ED_FA_SHIFT 0
@ -326,6 +327,7 @@ static void ohci_attach(USBPort *port1)
{
OHCIState *s = port1->opaque;
OHCIPort *port = &s->rhport[port1->index];
uint32_t old_state = port->ctrl;
/* set connect status */
port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
@ -343,6 +345,10 @@ static void ohci_attach(USBPort *port1)
}
DPRINTF("usb-ohci: Attached port %d\n", port1->index);
if (old_state != port->ctrl) {
ohci_set_interrupt(s, OHCI_INTR_RHSC);
}
}
static void ohci_detach(USBPort *port1)
@ -351,6 +357,8 @@ static void ohci_detach(USBPort *port1)
OHCIPort *port = &s->rhport[port1->index];
uint32_t old_state = port->ctrl;
ohci_async_cancel_device(s, port1->dev);
/* set connect status */
if (port->ctrl & OHCI_PORT_CCS) {
port->ctrl &= ~OHCI_PORT_CCS;
@ -363,19 +371,18 @@ static void ohci_detach(USBPort *port1)
}
DPRINTF("usb-ohci: Detached port %d\n", port1->index);
if (old_state != port->ctrl)
if (old_state != port->ctrl) {
ohci_set_interrupt(s, OHCI_INTR_RHSC);
}
}
static void ohci_wakeup(USBDevice *dev)
static void ohci_wakeup(USBPort *port1)
{
USBBus *bus = usb_bus_from_device(dev);
OHCIState *s = container_of(bus, OHCIState, bus);
int portnum = dev->port->index;
OHCIPort *port = &s->rhport[portnum];
OHCIState *s = port1->opaque;
OHCIPort *port = &s->rhport[port1->index];
uint32_t intr = 0;
if (port->ctrl & OHCI_PORT_PSS) {
DPRINTF("usb-ohci: port %d: wakeup\n", portnum);
DPRINTF("usb-ohci: port %d: wakeup\n", port1->index);
port->ctrl |= OHCI_PORT_PSSC;
port->ctrl &= ~OHCI_PORT_PSS;
intr = OHCI_INTR_RHSC;
@ -394,6 +401,13 @@ static void ohci_wakeup(USBDevice *dev)
ohci_set_interrupt(s, intr);
}
static void ohci_child_detach(USBPort *port1, USBDevice *child)
{
OHCIState *s = port1->opaque;
ohci_async_cancel_device(s, child);
}
/* Reset the controller */
static void ohci_reset(void *opaque)
{
@ -602,7 +616,7 @@ static void ohci_copy_iso_td(OHCIState *ohci,
static void ohci_process_lists(OHCIState *ohci, int completion);
static void ohci_async_complete_packet(USBDevice *dev, USBPacket *packet)
static void ohci_async_complete_packet(USBPort *port, USBPacket *packet)
{
OHCIState *ohci = container_of(packet, OHCIState, usb_packet);
#ifdef DEBUG_PACKET
@ -1675,10 +1689,8 @@ static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val)
}
}
static void ohci_device_destroy(USBBus *bus, USBDevice *dev)
static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
{
OHCIState *ohci = container_of(bus, OHCIState, bus);
if (ohci->async_td && ohci->usb_packet.owner == dev) {
usb_cancel_packet(&ohci->usb_packet);
ohci->async_td = 0;
@ -1702,16 +1714,17 @@ static CPUWriteMemoryFunc * const ohci_writefn[3]={
static USBPortOps ohci_port_ops = {
.attach = ohci_attach,
.detach = ohci_detach,
.child_detach = ohci_child_detach,
.wakeup = ohci_wakeup,
.complete = ohci_async_complete_packet,
};
static USBBusOps ohci_bus_ops = {
.device_destroy = ohci_device_destroy,
};
static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
int num_ports, uint32_t localmem_base)
static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
int num_ports, uint32_t localmem_base,
char *masterbus, uint32_t firstport)
{
int i;
@ -1731,39 +1744,58 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
usb_frame_time, usb_bit_time);
}
ohci->num_ports = num_ports;
if (masterbus) {
USBPort *ports[OHCI_MAX_PORTS];
for(i = 0; i < num_ports; i++) {
ports[i] = &ohci->rhport[i].port;
}
if (usb_register_companion(masterbus, ports, num_ports,
firstport, ohci, &ohci_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL) != 0) {
return -1;
}
} else {
usb_bus_new(&ohci->bus, &ohci_bus_ops, dev);
for (i = 0; i < num_ports; i++) {
usb_register_port(&ohci->bus, &ohci->rhport[i].port,
ohci, i, &ohci_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
}
}
ohci->mem = cpu_register_io_memory(ohci_readfn, ohci_writefn, ohci,
DEVICE_LITTLE_ENDIAN);
ohci->localmem_base = localmem_base;
ohci->name = dev->info->name;
usb_bus_new(&ohci->bus, &ohci_bus_ops, dev);
ohci->num_ports = num_ports;
for (i = 0; i < num_ports; i++) {
usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, &ohci_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
usb_port_location(&ohci->rhport[i].port, NULL, i+1);
}
ohci->async_td = 0;
qemu_register_reset(ohci_reset, ohci);
return 0;
}
typedef struct {
PCIDevice pci_dev;
OHCIState state;
char *masterbus;
uint32_t num_ports;
uint32_t firstport;
} OHCIPCIState;
static int usb_ohci_initfn_pci(struct PCIDevice *dev)
{
OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, dev);
int num_ports = 3;
ohci->pci_dev.config[PCI_CLASS_PROG] = 0x10; /* OHCI */
/* TODO: RST# value should be 0. */
ohci->pci_dev.config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */
usb_ohci_init(&ohci->state, &dev->qdev, num_ports, 0);
if (usb_ohci_init(&ohci->state, &dev->qdev, ohci->num_ports, 0,
ohci->masterbus, ohci->firstport) != 0) {
return -1;
}
ohci->state.irq = ohci->pci_dev.irq[0];
/* TODO: avoid cast below by using dev */
@ -1787,7 +1819,8 @@ static int ohci_init_pxa(SysBusDevice *dev)
{
OHCISysBusState *s = FROM_SYSBUS(OHCISysBusState, dev);
usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset);
/* Cannot fail as we pass NULL for masterbus */
usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0);
sysbus_init_irq(dev, &s->ohci.irq);
sysbus_init_mmio(dev, 0x1000, s->ohci.mem);
@ -1802,6 +1835,12 @@ static PCIDeviceInfo ohci_pci_info = {
.vendor_id = PCI_VENDOR_ID_APPLE,
.device_id = PCI_DEVICE_ID_APPLE_IPID_USB,
.class_id = PCI_CLASS_SERIAL_USB,
.qdev.props = (Property[]) {
DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus),
DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3),
DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0),
DEFINE_PROP_END_OF_LIST(),
},
};
static SysBusDeviceInfo ohci_sysbus_info = {

View File

@ -132,7 +132,7 @@ typedef struct UHCIPort {
struct UHCIState {
PCIDevice dev;
USBBus bus;
USBBus bus; /* Note unused when we're a companion controller */
uint16_t cmd; /* cmd register */
uint16_t status;
uint16_t intr; /* interrupt enable register */
@ -150,6 +150,10 @@ struct UHCIState {
/* Active packets */
QTAILQ_HEAD(,UHCIAsync) async_pending;
uint8_t num_ports_vmstate;
/* Properties */
char *masterbus;
uint32_t firstport;
};
typedef struct UHCI_TD {
@ -606,6 +610,8 @@ static void uhci_detach(USBPort *port1)
UHCIState *s = port1->opaque;
UHCIPort *port = &s->ports[port1->index];
uhci_async_cancel_device(s, port1->dev);
/* set connect status */
if (port->ctrl & UHCI_PORT_CCS) {
port->ctrl &= ~UHCI_PORT_CCS;
@ -620,11 +626,17 @@ static void uhci_detach(USBPort *port1)
uhci_resume(s);
}
static void uhci_wakeup(USBDevice *dev)
static void uhci_child_detach(USBPort *port1, USBDevice *child)
{
USBBus *bus = usb_bus_from_device(dev);
UHCIState *s = container_of(bus, UHCIState, bus);
UHCIPort *port = s->ports + dev->port->index;
UHCIState *s = port1->opaque;
uhci_async_cancel_device(s, child);
}
static void uhci_wakeup(USBPort *port1)
{
UHCIState *s = port1->opaque;
UHCIPort *port = &s->ports[port1->index];
if (port->ctrl & UHCI_PORT_SUSPEND && !(port->ctrl & UHCI_PORT_RD)) {
port->ctrl |= UHCI_PORT_RD;
@ -657,7 +669,7 @@ static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
return ret;
}
static void uhci_async_complete(USBDevice *dev, USBPacket *packet);
static void uhci_async_complete(USBPort *port, USBPacket *packet);
static void uhci_process_frame(UHCIState *s);
/* return -1 if fatal error (frame must be stopped)
@ -718,6 +730,9 @@ out:
td->ctrl |= TD_CTRL_STALL;
td->ctrl &= ~TD_CTRL_ACTIVE;
s->status |= UHCI_STS_USBERR;
if (td->ctrl & TD_CTRL_IOC) {
*int_mask |= 0x01;
}
uhci_update_irq(s);
return 1;
@ -725,6 +740,9 @@ out:
td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
td->ctrl &= ~TD_CTRL_ACTIVE;
s->status |= UHCI_STS_USBERR;
if (td->ctrl & TD_CTRL_IOC) {
*int_mask |= 0x01;
}
uhci_update_irq(s);
/* frame interrupted */
return -1;
@ -849,7 +867,7 @@ done:
return len;
}
static void uhci_async_complete(USBDevice *dev, USBPacket *packet)
static void uhci_async_complete(USBPort *port, USBPacket *packet)
{
UHCIAsync *async = container_of(packet, UHCIAsync, packet);
UHCIState *s = async->uhci;
@ -1096,22 +1114,15 @@ static void uhci_map(PCIDevice *pci_dev, int region_num,
register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
}
static void uhci_device_destroy(USBBus *bus, USBDevice *dev)
{
UHCIState *s = container_of(bus, UHCIState, bus);
uhci_async_cancel_device(s, dev);
}
static USBPortOps uhci_port_ops = {
.attach = uhci_attach,
.detach = uhci_detach,
.child_detach = uhci_child_detach,
.wakeup = uhci_wakeup,
.complete = uhci_async_complete,
};
static USBBusOps uhci_bus_ops = {
.device_destroy = uhci_device_destroy,
};
static int usb_uhci_common_initfn(PCIDevice *dev)
@ -1125,11 +1136,22 @@ static int usb_uhci_common_initfn(PCIDevice *dev)
pci_conf[PCI_INTERRUPT_PIN] = 4; // interrupt pin 3
pci_conf[USB_SBRN] = USB_RELEASE_1; // release number
usb_bus_new(&s->bus, &uhci_bus_ops, &s->dev.qdev);
for(i = 0; i < NB_PORTS; i++) {
usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
usb_port_location(&s->ports[i].port, NULL, i+1);
if (s->masterbus) {
USBPort *ports[NB_PORTS];
for(i = 0; i < NB_PORTS; i++) {
ports[i] = &s->ports[i].port;
}
if (usb_register_companion(s->masterbus, ports, NB_PORTS,
s->firstport, s, &uhci_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL) != 0) {
return -1;
}
} else {
usb_bus_new(&s->bus, &uhci_bus_ops, &s->dev.qdev);
for (i = 0; i < NB_PORTS; i++) {
usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
}
}
s->frame_timer = qemu_new_timer_ns(vm_clock, uhci_frame_timer, s);
s->num_ports_vmstate = NB_PORTS;
@ -1160,6 +1182,12 @@ static int usb_uhci_vt82c686b_initfn(PCIDevice *dev)
return usb_uhci_common_initfn(dev);
}
static Property uhci_properties[] = {
DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
DEFINE_PROP_END_OF_LIST(),
};
static PCIDeviceInfo uhci_info[] = {
{
.qdev.name = "piix3-usb-uhci",
@ -1170,6 +1198,7 @@ static PCIDeviceInfo uhci_info[] = {
.device_id = PCI_DEVICE_ID_INTEL_82371SB_2,
.revision = 0x01,
.class_id = PCI_CLASS_SERIAL_USB,
.qdev.props = uhci_properties,
},{
.qdev.name = "piix4-usb-uhci",
.qdev.size = sizeof(UHCIState),
@ -1179,6 +1208,7 @@ static PCIDeviceInfo uhci_info[] = {
.device_id = PCI_DEVICE_ID_INTEL_82371AB_2,
.revision = 0x01,
.class_id = PCI_CLASS_SERIAL_USB,
.qdev.props = uhci_properties,
},{
.qdev.name = "vt82c686b-usb-uhci",
.qdev.size = sizeof(UHCIState),
@ -1188,6 +1218,37 @@ static PCIDeviceInfo uhci_info[] = {
.device_id = PCI_DEVICE_ID_VIA_UHCI,
.revision = 0x01,
.class_id = PCI_CLASS_SERIAL_USB,
.qdev.props = uhci_properties,
},{
.qdev.name = "ich9-usb-uhci1",
.qdev.size = sizeof(UHCIState),
.qdev.vmsd = &vmstate_uhci,
.init = usb_uhci_common_initfn,
.vendor_id = PCI_VENDOR_ID_INTEL,
.device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI1,
.revision = 0x03,
.class_id = PCI_CLASS_SERIAL_USB,
.qdev.props = uhci_properties,
},{
.qdev.name = "ich9-usb-uhci2",
.qdev.size = sizeof(UHCIState),
.qdev.vmsd = &vmstate_uhci,
.init = usb_uhci_common_initfn,
.vendor_id = PCI_VENDOR_ID_INTEL,
.device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI2,
.revision = 0x03,
.class_id = PCI_CLASS_SERIAL_USB,
.qdev.props = uhci_properties,
},{
.qdev.name = "ich9-usb-uhci3",
.qdev.size = sizeof(UHCIState),
.qdev.vmsd = &vmstate_uhci,
.init = usb_uhci_common_initfn,
.vendor_id = PCI_VENDOR_ID_INTEL,
.device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI3,
.revision = 0x03,
.class_id = PCI_CLASS_SERIAL_USB,
.qdev.props = uhci_properties,
},{
/* end of list */
}

View File

@ -40,19 +40,18 @@ void usb_attach(USBPort *port, USBDevice *dev)
} else {
/* detach */
dev = port->dev;
assert(dev);
port->ops->detach(port);
if (dev) {
usb_send_msg(dev, USB_MSG_DETACH);
dev->port = NULL;
port->dev = NULL;
}
usb_send_msg(dev, USB_MSG_DETACH);
dev->port = NULL;
port->dev = NULL;
}
}
void usb_wakeup(USBDevice *dev)
{
if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
dev->port->ops->wakeup(dev);
dev->port->ops->wakeup(dev->port);
}
}
@ -335,7 +334,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
{
/* Note: p->owner != dev is possible in case dev is a hub */
assert(p->owner != NULL);
dev->port->ops->complete(dev, p);
dev->port->ops->complete(dev->port, p);
p->owner = NULL;
}

View File

@ -252,8 +252,18 @@ struct USBDeviceInfo {
typedef struct USBPortOps {
void (*attach)(USBPort *port);
void (*detach)(USBPort *port);
void (*wakeup)(USBDevice *dev);
void (*complete)(USBDevice *dev, USBPacket *p);
/*
* This gets called when a device downstream from the device attached to
* the port (iow attached through a hub) gets detached.
*/
void (*child_detach)(USBPort *port, USBDevice *child);
void (*wakeup)(USBPort *port);
/*
* Note that port->dev will be different then the device from which
* the packet originated when a hub is involved, if you want the orginating
* device use p->owner
*/
void (*complete)(USBPort *port, USBPacket *p);
} USBPortOps;
/* USB port on which a device can be connected */
@ -344,7 +354,8 @@ struct USBBus {
};
struct USBBusOps {
void (*device_destroy)(USBBus *bus, USBDevice *dev);
int (*register_companion)(USBBus *bus, USBPort *ports[],
uint32_t portcount, uint32_t firstport);
};
void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host);
@ -356,6 +367,9 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name);
USBDevice *usbdevice_create(const char *cmdline);
void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
USBPortOps *ops, int speedmask);
int usb_register_companion(const char *masterbus, USBPort *ports[],
uint32_t portcount, uint32_t firstport,
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_device_attach(USBDevice *dev);

View File

@ -784,5 +784,6 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
hdev->started = false;
qemu_free(hdev->log);
hdev->log = NULL;
hdev->log_size = 0;
}

View File

@ -60,7 +60,7 @@ static void mmubooke_create_initial_mapping(CPUState *env,
target_ulong va,
target_phys_addr_t pa)
{
ppcemb_tlb_t *tlb = &env->tlb[0].tlbe;
ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
tlb->attr = 0;
tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
@ -69,7 +69,7 @@ static void mmubooke_create_initial_mapping(CPUState *env,
tlb->RPN = pa & TARGET_PAGE_MASK;
tlb->PID = 0;
tlb = &env->tlb[1].tlbe;
tlb = &env->tlb.tlbe[1];
tlb->attr = 0;
tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
tlb->size = 1 << 31; /* up to 0xffffffff */

View File

@ -28,8 +28,8 @@ typedef struct VirtIOBlock
void *rq;
QEMUBH *bh;
BlockConf *conf;
char *serial;
unsigned short sector_mask;
char sn[BLOCK_SERIAL_STRLEN];
DeviceState *qdev;
} VirtIOBlock;
@ -362,8 +362,13 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
} else if (type & VIRTIO_BLK_T_GET_ID) {
VirtIOBlock *s = req->dev;
memcpy(req->elem.in_sg[0].iov_base, s->sn,
MIN(req->elem.in_sg[0].iov_len, sizeof(s->sn)));
/*
* NB: per existing s/n string convention the string is
* terminated by '\0' only when shorter than buffer.
*/
strncpy(req->elem.in_sg[0].iov_base,
s->serial ? s->serial : "",
MIN(req->elem.in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES));
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
} else if (type & VIRTIO_BLK_T_OUT) {
qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
@ -531,7 +536,8 @@ static void virtio_blk_change_cb(void *opaque, int reason)
}
}
VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
char **serial)
{
VirtIOBlock *s;
int cylinders, heads, secs;
@ -547,6 +553,14 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
return NULL;
}
if (!*serial) {
/* try to fall back to value set with legacy -drive serial=... */
dinfo = drive_get_by_blockdev(conf->bs);
if (*dinfo->serial) {
*serial = strdup(dinfo->serial);
}
}
s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
sizeof(struct virtio_blk_config),
sizeof(VirtIOBlock));
@ -556,16 +570,11 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
s->vdev.reset = virtio_blk_reset;
s->bs = conf->bs;
s->conf = conf;
s->serial = *serial;
s->rq = NULL;
s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
/* NB: per existing s/n string convention the string is terminated
* by '\0' only when less than sizeof (s->sn)
*/
dinfo = drive_get_by_blockdev(s->bs);
strncpy(s->sn, dinfo->serial, sizeof (s->sn));
s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);

View File

@ -34,6 +34,8 @@
#define VIRTIO_BLK_F_WCACHE 9 /* write cache enabled */
#define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */
#define VIRTIO_BLK_ID_BYTES 20 /* ID string length */
struct virtio_blk_config
{
uint64_t capacity;

View File

@ -12,6 +12,7 @@
#include "qemu-char.h"
#include "qemu-error.h"
#include "trace.h"
#include "virtio-serial.h"
typedef struct VirtConsole {
@ -24,8 +25,26 @@ typedef struct VirtConsole {
static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
{
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
ssize_t ret;
return qemu_chr_write(vcon->chr, buf, len);
ret = qemu_chr_write(vcon->chr, buf, len);
trace_virtio_console_flush_buf(port->id, len, ret);
if (ret < 0) {
/*
* Ideally we'd get a better error code than just -1, but
* that's what the chardev interface gives us right now. If
* we had a finer-grained message, like -EPIPE, we could close
* this connection. Absent such error messages, the most we
* can do is to return 0 here.
*
* This will prevent stray -1 values to go to
* virtio-serial-bus.c and cause abort()s in
* do_flush_queued_data().
*/
ret = 0;
}
return ret;
}
/* Callback function that's called when the guest opens the port */
@ -57,6 +76,7 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
{
VirtConsole *vcon = opaque;
trace_virtio_console_chr_read(vcon->port.id, size);
virtio_serial_write(&vcon->port, buf, size);
}
@ -64,6 +84,7 @@ static void chr_event(void *opaque, int event)
{
VirtConsole *vcon = opaque;
trace_virtio_console_chr_event(vcon->port.id, event);
switch (event) {
case CHR_EVENT_OPENED:
virtio_serial_open(&vcon->port);

View File

@ -657,7 +657,7 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
/* copy in packet. ugh */
len = iov_from_buf(sg, elem.in_num,
buf + offset, size - offset);
buf + offset, 0, size - offset);
total += len;
offset += len;
/* If buffers can't be merged, at this point we

View File

@ -700,7 +700,8 @@ static int virtio_blk_init_pci(PCIDevice *pci_dev)
proxy->class_code != PCI_CLASS_STORAGE_OTHER)
proxy->class_code = PCI_CLASS_STORAGE_SCSI;
vdev = virtio_blk_init(&pci_dev->qdev, &proxy->block);
vdev = virtio_blk_init(&pci_dev->qdev, &proxy->block,
&proxy->block_serial);
if (!vdev) {
return -1;
}
@ -805,6 +806,7 @@ static PCIDeviceInfo virtio_info[] = {
.qdev.props = (Property[]) {
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
DEFINE_PROP_STRING("serial", VirtIOPCIProxy, block_serial),
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),

View File

@ -26,6 +26,7 @@ typedef struct {
uint32_t class_code;
uint32_t nvectors;
BlockConf block;
char *block_serial;
NICConf nic;
uint32_t host_features;
#ifdef CONFIG_LINUX

View File

@ -19,6 +19,7 @@
#include "monitor.h"
#include "qemu-queue.h"
#include "sysbus.h"
#include "trace.h"
#include "virtio-serial.h"
/* The virtio-serial bus on top of which the ports will ride as devices */
@ -103,7 +104,7 @@ static size_t write_to_port(VirtIOSerialPort *port,
}
len = iov_from_buf(elem.in_sg, elem.in_num,
buf + offset, size - offset);
buf + offset, 0, size - offset);
offset += len;
virtqueue_push(vq, &elem, len);
@ -221,6 +222,7 @@ static size_t send_control_event(VirtIOSerialPort *port, uint16_t event,
stw_p(&cpkt.event, event);
stw_p(&cpkt.value, value);
trace_virtio_serial_send_control_event(port->id, event, value);
return send_control_msg(port, &cpkt, sizeof(cpkt));
}
@ -302,6 +304,7 @@ void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle)
return;
}
trace_virtio_serial_throttle_port(port->id, throttle);
port->throttled = throttle;
if (throttle) {
return;
@ -328,6 +331,8 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
cpkt.event = lduw_p(&gcpkt->event);
cpkt.value = lduw_p(&gcpkt->value);
trace_virtio_serial_handle_control_message(cpkt.event, cpkt.value);
if (cpkt.event == VIRTIO_CONSOLE_DEVICE_READY) {
if (!cpkt.value) {
error_report("virtio-serial-bus: Guest failure in adding device %s",
@ -346,11 +351,13 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
port = find_port_by_id(vser, ldl_p(&gcpkt->id));
if (!port) {
error_report("virtio-serial-bus: Unexpected port id %u for device %s\n",
error_report("virtio-serial-bus: Unexpected port id %u for device %s",
ldl_p(&gcpkt->id), vser->bus.qbus.name);
return;
}
trace_virtio_serial_handle_control_message_port(port->id);
info = DO_UPCAST(VirtIOSerialPortInfo, qdev, port->dev.info);
switch(cpkt.event) {

View File

@ -449,9 +449,17 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
struct iovec *sg;
if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) {
if (elem->in_num >= ARRAY_SIZE(elem->in_sg)) {
error_report("Too many write descriptors in indirect table");
exit(1);
}
elem->in_addr[elem->in_num] = vring_desc_addr(desc_pa, i);
sg = &elem->in_sg[elem->in_num++];
} else {
if (elem->out_num >= ARRAY_SIZE(elem->out_sg)) {
error_report("Too many read descriptors in indirect table");
exit(1);
}
elem->out_addr[elem->out_num] = vring_desc_addr(desc_pa, i);
sg = &elem->out_sg[elem->out_num++];
}

View File

@ -197,7 +197,8 @@ void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
void *opaque);
/* Base devices. */
VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf);
VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
char **serial);
struct virtio_net_conf;
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
struct virtio_net_conf *net);

View File

@ -31,15 +31,6 @@ static inline int xen_enabled(void)
#endif
}
static inline int xen_mapcache_enabled(void)
{
#ifdef CONFIG_XEN_MAPCACHE
return xen_enabled();
#else
return 0;
#endif
}
int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num);
void xen_piix3_set_irq(void *opaque, int irq_num, int level);
void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len);
@ -50,6 +41,7 @@ qemu_irq *xen_interrupt_controller_init(void);
int xen_init(void);
int xen_hvm_init(void);
void xen_vcpu_init(void);
void xenstore_store_pv_console_info(int i, struct CharDriverState *chr);
#if defined(NEED_CPU_H) && !defined(CONFIG_USER_ONLY)
void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size);

View File

@ -85,6 +85,18 @@ static inline int xc_domain_add_to_physmap(int xc_handle, uint32_t domid,
return xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp);
}
static inline struct xs_handle *xs_open(unsigned long flags)
{
return xs_daemon_open();
}
static inline void xs_close(struct xs_handle *xsh)
{
if (xsh != NULL) {
xs_daemon_close(xsh);
}
}
/* Xen 4.1 */
#else

View File

@ -179,7 +179,9 @@ static void xencons_send(struct XenConsole *con)
static int con_init(struct XenDevice *xendev)
{
struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
char *type, *dom;
char *type, *dom, label[32];
int ret = 0;
const char *output;
/* setup */
dom = xs_get_domain_path(xenstore, con->xendev.dom);
@ -189,16 +191,25 @@ static int con_init(struct XenDevice *xendev)
type = xenstore_read_str(con->console, "type");
if (!type || strcmp(type, "ioemu") != 0) {
xen_be_printf(xendev, 1, "not for me (type=%s)\n", type);
return -1;
ret = -1;
goto out;
}
if (!serial_hds[con->xendev.dev])
xen_be_printf(xendev, 1, "WARNING: serial line %d not configured\n",
con->xendev.dev);
else
con->chr = serial_hds[con->xendev.dev];
output = xenstore_read_str(con->console, "output");
return 0;
/* no Xen override, use qemu output device */
if (output == NULL) {
con->chr = serial_hds[con->xendev.dev];
} else {
snprintf(label, sizeof(label), "xencons%d", con->xendev.dev);
con->chr = qemu_chr_open(label, output, NULL);
}
xenstore_store_pv_console_info(con->xendev.dev, con->chr);
out:
qemu_free(type);
return ret;
}
static int con_connect(struct XenDevice *xendev)

View File

@ -616,12 +616,14 @@ static int blk_init(struct XenDevice *xendev)
{
struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
int index, qflags, have_barriers, info = 0;
char *h;
/* read xenstore entries */
if (blkdev->params == NULL) {
char *h = NULL;
blkdev->params = xenstore_read_be_str(&blkdev->xendev, "params");
h = strchr(blkdev->params, ':');
if (blkdev->params != NULL) {
h = strchr(blkdev->params, ':');
}
if (h != NULL) {
blkdev->fileproto = blkdev->params;
blkdev->filename = h+1;
@ -631,6 +633,9 @@ static int blk_init(struct XenDevice *xendev)
blkdev->filename = blkdev->params;
}
}
if (!strcmp("aio", blkdev->fileproto)) {
blkdev->fileproto = "raw";
}
if (blkdev->mode == NULL) {
blkdev->mode = xenstore_read_be_str(&blkdev->xendev, "mode");
}
@ -649,7 +654,7 @@ static int blk_init(struct XenDevice *xendev)
blkdev->mode == NULL ||
blkdev->type == NULL ||
blkdev->dev == NULL) {
return -1;
goto out_error;
}
/* read-only ? */
@ -672,10 +677,15 @@ static int blk_init(struct XenDevice *xendev)
/* setup via xenbus -> create new block driver instance */
xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
blkdev->bs = bdrv_new(blkdev->dev);
if (bdrv_open(blkdev->bs, blkdev->filename, qflags,
bdrv_find_whitelisted_format(blkdev->fileproto)) != 0) {
bdrv_delete(blkdev->bs);
return -1;
if (blkdev->bs) {
if (bdrv_open(blkdev->bs, blkdev->filename, qflags,
bdrv_find_whitelisted_format(blkdev->fileproto)) != 0) {
bdrv_delete(blkdev->bs);
blkdev->bs = NULL;
}
}
if (!blkdev->bs) {
goto out_error;
}
} else {
/* setup via qemu cmdline -> already setup for us */
@ -704,6 +714,19 @@ static int blk_init(struct XenDevice *xendev)
xenstore_write_be_int(&blkdev->xendev, "sectors",
blkdev->file_size / blkdev->file_blk);
return 0;
out_error:
qemu_free(blkdev->params);
blkdev->params = NULL;
qemu_free(blkdev->mode);
blkdev->mode = NULL;
qemu_free(blkdev->type);
blkdev->type = NULL;
qemu_free(blkdev->dev);
blkdev->dev = NULL;
qemu_free(blkdev->devtype);
blkdev->devtype = NULL;
return -1;
}
static int blk_connect(struct XenDevice *xendev)

View File

@ -290,18 +290,10 @@ static int xen_platform_initfn(PCIDevice *dev)
pci_conf = d->pci_dev.config;
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_XENSOURCE);
pci_config_set_device_id(pci_conf, 0x0001);
pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, PCI_VENDOR_ID_XENSOURCE);
pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, 0x0001);
pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
pci_config_set_revision(pci_conf, 1);
pci_config_set_prog_interface(pci_conf, 0);
pci_config_set_class(pci_conf, PCI_CLASS_OTHERS << 8 | 0x80);
pci_conf[PCI_INTERRUPT_PIN] = 1;
pci_register_bar(&d->pci_dev, 0, 0x100,
@ -330,6 +322,13 @@ static PCIDeviceInfo xen_platform_info = {
.qdev.size = sizeof(PCIXenPlatformState),
.qdev.vmsd = &vmstate_xen_platform,
.qdev.reset = platform_reset,
.vendor_id = PCI_VENDOR_ID_XEN,
.device_id = PCI_DEVICE_ID_XEN_PLATFORM,
.class_id = PCI_CLASS_OTHERS << 8 | 0x80,
.subsystem_vendor_id = PCI_VENDOR_ID_XEN,
.subsystem_id = PCI_DEVICE_ID_XEN_PLATFORM,
.revision = 1,
};
static void xen_platform_register(void)

View File

@ -347,13 +347,6 @@ static void xenfb_mouse_event(void *opaque,
static int input_init(struct XenDevice *xendev)
{
struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
if (!in->c.ds) {
xen_be_printf(xendev, 1, "ds not set (yet)\n");
return -1;
}
xenstore_write_be_int(xendev, "feature-abs-pointer", 1);
return 0;
}
@ -367,6 +360,18 @@ static int input_connect(struct XenDevice *xendev)
&in->abs_pointer_wanted) == -1)
in->abs_pointer_wanted = 0;
if (!in->c.ds) {
char *vfb = xenstore_read_str(NULL, "device/vfb");
if (vfb == NULL) {
/* there is no vfb, run vkbd on its own */
in->c.ds = get_displaystate();
} else {
qemu_free(vfb);
xen_be_printf(xendev, 1, "ds not set (yet)\n");
return -1;
}
}
rc = common_bind(&in->c);
if (rc != 0)
return rc;

34
input.c
View File

@ -148,7 +148,7 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
QEMUPutMouseEntry *entry;
QEMUPutMouseEvent *mouse_event;
void *mouse_event_opaque;
int width;
int width, height;
if (QTAILQ_EMPTY(&mouse_handlers)) {
return;
@ -160,15 +160,31 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
mouse_event_opaque = entry->qemu_put_mouse_event_opaque;
if (mouse_event) {
if (graphic_rotate) {
if (entry->qemu_put_mouse_event_absolute) {
width = 0x7fff;
} else {
width = graphic_width - 1;
}
mouse_event(mouse_event_opaque, width - dy, dx, dz, buttons_state);
if (entry->qemu_put_mouse_event_absolute) {
width = 0x7fff;
height = 0x7fff;
} else {
mouse_event(mouse_event_opaque, dx, dy, dz, buttons_state);
width = graphic_width - 1;
height = graphic_height - 1;
}
switch (graphic_rotate) {
case 0:
mouse_event(mouse_event_opaque,
dx, dy, dz, buttons_state);
break;
case 90:
mouse_event(mouse_event_opaque,
width - dy, dx, dz, buttons_state);
break;
case 180:
mouse_event(mouse_event_opaque,
width - dx, height - dy, dz, buttons_state);
break;
case 270:
mouse_event(mouse_event_opaque,
dy, height - dx, dz, buttons_state);
break;
}
}
}

69
iov.c
View File

@ -14,56 +14,61 @@
#include "iov.h"
size_t iov_from_buf(struct iovec *iov, unsigned int iovcnt,
const void *buf, size_t size)
size_t iov_from_buf(struct iovec *iov, unsigned int iov_cnt,
const void *buf, size_t iov_off, size_t size)
{
size_t offset;
size_t iovec_off, buf_off;
unsigned int i;
offset = 0;
for (i = 0; offset < size && i < iovcnt; i++) {
size_t len;
len = MIN(iov[i].iov_len, size - offset);
memcpy(iov[i].iov_base, buf + offset, len);
offset += len;
}
return offset;
}
size_t iov_to_buf(const struct iovec *iov, const unsigned int iovcnt,
void *buf, size_t offset, size_t size)
{
uint8_t *ptr;
size_t iov_off, buf_off;
unsigned int i;
ptr = buf;
iov_off = 0;
iovec_off = 0;
buf_off = 0;
for (i = 0; i < iovcnt && size; i++) {
if (offset < (iov_off + iov[i].iov_len)) {
size_t len = MIN((iov_off + iov[i].iov_len) - offset , size);
for (i = 0; i < iov_cnt && size; i++) {
if (iov_off < (iovec_off + iov[i].iov_len)) {
size_t len = MIN((iovec_off + iov[i].iov_len) - iov_off, size);
memcpy(ptr + buf_off, iov[i].iov_base + (offset - iov_off), len);
memcpy(iov[i].iov_base + (iov_off - iovec_off), buf + buf_off, len);
buf_off += len;
offset += len;
iov_off += len;
size -= len;
}
iov_off += iov[i].iov_len;
iovec_off += iov[i].iov_len;
}
return buf_off;
}
size_t iov_size(const struct iovec *iov, const unsigned int iovcnt)
size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt,
void *buf, size_t iov_off, size_t size)
{
uint8_t *ptr;
size_t iovec_off, buf_off;
unsigned int i;
ptr = buf;
iovec_off = 0;
buf_off = 0;
for (i = 0; i < iov_cnt && size; i++) {
if (iov_off < (iovec_off + iov[i].iov_len)) {
size_t len = MIN((iovec_off + iov[i].iov_len) - iov_off , size);
memcpy(ptr + buf_off, iov[i].iov_base + (iov_off - iovec_off), len);
buf_off += len;
iov_off += len;
size -= len;
}
iovec_off += iov[i].iov_len;
}
return buf_off;
}
size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt)
{
size_t len;
unsigned int i;
len = 0;
for (i = 0; i < iovcnt; i++) {
for (i = 0; i < iov_cnt; i++) {
len += iov[i].iov_len;
}
return len;

10
iov.h
View File

@ -12,8 +12,8 @@
#include "qemu-common.h"
size_t iov_from_buf(struct iovec *iov, unsigned int iovcnt,
const void *buf, size_t size);
size_t iov_to_buf(const struct iovec *iov, const unsigned int iovcnt,
void *buf, size_t offset, size_t size);
size_t iov_size(const struct iovec *iov, const unsigned int iovcnt);
size_t iov_from_buf(struct iovec *iov, unsigned int iov_cnt,
const void *buf, size_t iov_off, size_t size);
size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt,
void *buf, size_t iov_off, size_t size);
size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt);

Some files were not shown because too many files have changed in this diff Show More