Merge remote branch 'origin/master' into pci

Conflicts:
	Makefile.objs
	hw/virtio.c
master
Michael S. Tsirkin 2010-12-01 07:11:51 +02:00
commit c924f36a30
123 changed files with 2984 additions and 1199 deletions

2
.gitignore vendored
View File

@ -4,6 +4,8 @@ config-host.*
config-target.*
trace.h
trace.c
trace-dtrace.h
trace-dtrace.dtrace
*-timestamp
*-softmmu
*-darwin-user

View File

@ -1,88 +1,428 @@
QEMU Maintainers
================
Project leaders:
----------------
The intention of this file is not to establish who owns what portions of the
code base, but to provide a set of names that developers can consult when they
have a question about a particular subset and also to provide a set of names
to be CC'd when submitting a patch to obtain appropriate review.
Fabrice Bellard
Paul Brook
In general, if you have a question about inclusion of a patch, you should
consult qemu-devel and not any specific individual privately.
CPU cores:
----------
Descriptions of section entries:
x86 Fabrice Bellard
ARM Paul Brook
SPARC Blue Swirl
MIPS ?
PowerPC Alexander Graf
M68K Paul Brook
SH4 ?
CRIS Edgar E. Iglesias
Alpha ?
MicroBlaze Edgar E. Iglesias
S390 ?
M: Mail patches to: FullName <address@domain>
L: Mailing list that is relevant to this area
W: Web-page with status/info
Q: Patchwork web based patch tracking system site
T: SCM tree type and location. Type is one of: git, hg, quilt, stgit.
S: Status, one of the following:
Supported: Someone is actually paid to look after this.
Maintained: Someone actually looks after it.
Odd Fixes: It has a maintainer but they don't have time to do
much other than throw the odd patch in. See below..
Orphan: No current maintainer [but maybe you could take the
role as you write your new code].
Obsolete: Old code. Something tagged obsolete generally means
it has been replaced by a better system and you
should be using that.
F: Files and directories with wildcard patterns.
A trailing slash includes all files and subdirectory files.
F: drivers/net/ all files in and below drivers/net
F: drivers/net/* all files in drivers/net, but not below
F: */net/* all files in "any top level directory"/net
One pattern per line. Multiple F: lines acceptable.
X: Files and directories that are NOT maintained, same rules as F:
Files exclusions are tested before file matches.
Can be useful for excluding a specific subdirectory, for instance:
F: net/
X: net/ipv6/
matches all files in and below net excluding net/ipv6/
K: Keyword perl extended regex pattern to match content in a
patch or file. For instance:
K: of_get_profile
matches patches or files that contain "of_get_profile"
K: \b(printk|pr_(info|err))\b
matches patches or files that contain one or more of the words
printk, pr_info or pr_err
One regex pattern per line. Multiple K: lines acceptable.
Machines (sorted by CPU):
-------------------------
x86
pc.c Fabrice Bellard (new maintainer needed)
ARM
integratorcp.c Paul Brook
versatilepb.c Paul Brook
Real View Paul Brook
spitz.c Andrzej Zaborowski
palm.c Andrzej Zaborowski
nseries.c Andrzej Zaborowski
stellaris.c Paul Brook
gumstix.c Thorsten Zitterell
mainstone.c Armin Kuster
musicpal.c Jan Kiszka
SPARC
sun4u.c Blue Swirl
sun4m.c Blue Swirl
MIPS
mips_r4k.c Aurelien Jarno
mips_malta.c Aurelien Jarno
mips_jazz.c Hervé Poussineau
mips_mipssim.c ?
PowerPC
ppc_prep.c ?
ppc_oldworld.c Alexander Graf
ppc_newworld.c Alexander Graf
ppc405_boards.c Alexander Graf
M86K
mcf5208.c Paul Brook
an5206.c Paul Brook
dummy_m68k.c Paul Brook
SH4
shix.c ?
r2d.c Magnus Damm
CRIS
etraxfs.c Edgar E. Iglesias
axis_dev88.c Edgar E. Iglesias
General Project Administration
------------------------------
M: Anthony Liguori <aliguori@us.ibm.com>
M: Paul Brook <paul@codesourcery.com>
Guest CPU cores (TCG):
----------------------
Alpha
M: qemu-devel@nongnu.org
S: Orphan
F: target-alpha/
ARM
M: Paul Brook <paul@codesourcery.com>
S: Maintained
F: target-arm/
CRIS
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
S: Maintained
F: target-cris/
M68K
M: Paul Brook <paul@codesourcery.com>
S: Maintained
F: target-m68k/
MicroBlaze
petalogix_s3adsp1800.c Edgar E. Iglesias
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
S: Maintained
F: target-microblaze/
MIPS
M: qemu-devel@nongnu.org
S: Orphan
F: target-mips/
PowerPC
M: Alexander Graf <agraf@suse.de>
S: Maintained
F: target-ppc/
S390
s390-*.c Alexander Graf
M: Alexander Graf <agraf@suse.de>
S: Maintained
F: target-s390x/
Generic Subsystems:
-------------------
SH4
M: qemu-devel@nongnu.org
S: Orphan
F: target-sh4/
Dynamic translator Fabrice Bellard
Main loop Fabrice Bellard (new maintainer needed)
TCG Fabrice Bellard
IDE device ?
SCSI device Paul Brook
PCI layer Michael S. Tsirkin
USB layer ?
Block layer ?
Graphic layer ?
Audio device layer Vassili Karpov (malc)
Character device layer ?
Network device layer ?
GDB stub ?
Linux user ?
Darwin user ?
SLIRP ?
SPARC
M: Blue Swirl <blauwirbel@gmail.com>
S: Maintained
F: target-sparc/
X86
M: qemu-devel@nongnu.org
S: Odd Fixes
F: target-i386/
Guest CPU Cores (KVM):
----------------------
Overall
M: Avi Kivity <avi@redhat.com>
M: Marcelo Tosatti <mtosatti@redhat.com>
L: kvm@vger.kernel.org
S: Supported
F: kvm-*
F: */kvm.*
PPC
M: Alexander Graf <agraf@suse.de>
S: Maintained
F: target-ppc/kvm.c
S390
M: Alexander Graf <agraf@suse.de>
S: Maintained
F: target-s390x/kvm.c
X86
M: Avi Kivity <avi@redhat.com>
M: Marcelo Tosatti <mtosatti@redhat.com>
L: kvm@vger.kernel.org
S: Supported
F: target-i386/kvm.c
ARM Machines
------------
Gumstix
M: qemu-devel@nongnu.org
S: Orphan
F: hw/gumstix.c
Integrator CP
M: Paul Brook <paul@codesourcery.com>
S: Maintained
F: hw/integratorcp.c
Mainstone
M: qemu-devel@nongnu.org
S: Orphan
F: hw/mainstone.c
Musicpal
M: Jan Kiszka <jan.kiszka@web.de>
S: Maintained
F: hw/musicpal.c
nSeries
M: Andrzej Zaborowski <balrogg@gmail.com>
S: Maintained
F: hw/nseries.c
Palm
M: Andrzej Zaborowski <balrogg@gmail.com>
S: Maintained
F: hw/palm.c
Real View
M: Paul Brook <paul@codesourcery.com>
S: Maintained
F: hw/realview*
Spitz
M: Andrzej Zaborowski <balrogg@gmail.com>
S: Maintained
F: hw/spitz.c
Stellaris
M: Paul Brook <paul@codesourcery.com>
S: Maintained
F: hw/stellaris.c
Versatile PB
M: Paul Brook <paul@codesourcery.com>
S: Maintained
F: hw/versatilepb.c
CRIS Machines
-------------
Axis Dev88
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
S: Maintained
F: hw/axis_dev88.c
etraxfs
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
S: Maintained
F: hw/etraxfs.c
M86K Machines
-------------
an5206
M: Paul Brook <paul@codesourcery.com>
S: Maintained
F: hw/an5206.c
dummy_m68k
M: Paul Brook <paul@codesourcery.com>
S: Maintained
F: hw/dummy_m68k.c
mcf5208
M: Paul Brook <paul@codesourcery.com>
S: Maintained
F: hw/mcf5208.c
MicroBlaze Machines
-------------------
petalogix_s3adsp1800
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
S: Maintained
F: hw/petalogix_s3adsp1800.c
MIPS Machines
-------------
Jazz
M: Hervé Poussineau <hpoussin@reactos.org>
S: Maintained
F: hw/mips_jazz.c
Malta
M: Aurelien Jarno <aurelien@aurel32.net>
S: Maintained
F: hw/mips_malta.c
Mipssim
M: qemu-devel@nongnu.org
S: Orphan
F: hw/mips_mipssim.c
R4000
M: Aurelien Jarno <aurelien@aurel32.net>
S: Maintained
F: hw/mips_r4k.c
PowerPC Machines
----------------
405
M: Alexander Graf <agraf@suse.de>
S: Maintained
F: hw/ppc405_boards.c
New World
M: Alexander Graf <agraf@suse.de>
S: Maintained
F: hw/ppc_newworld.c
Old World
M: Alexander Graf <agraf@suse.de>
S: Maintained
F: hw/ppc_oldworld.c
Prep
M: qemu-devel@nongnu.org
S: Orphan
F: hw/ppc_prep.c
SH4 Machines
------------
R2D
M: Magnus Damm <magnus.damm@gmail.com>
S: Maintained
F: hw/r2d.c
Shix
M: Magnus Damm <magnus.damm@gmail.com>
S: Oprhan
F: hw/shix.c
SPARC Machines
--------------
Sun4m
M: Blue Swirl <blauwirbel@gmail.com>
S: Maintained
F: hw/sun4m.c
Sun4u
M: Blue Swirl <blauwirbel@gmail.com>
S: Maintained
F: hw/sun4u.c
S390 Machines
-------------
S390 Virtio
M: Alexander Graf <agraf@suse.de>
S: Maintained
F: hw/s390-*.c
X86 Machines
------------
PC
M: Anthony Liguori <aliguori@us.ibm.com>
S: Supported
F: hw/pc.[ch] hw/pc_piix.c
Devices
-------
IDE
M: Kevin Wolf <kwolf@redhat.com>
S: Odd Fixes
F: hw/ide/
PCI
M: Michael S. Tsirkin <mst@redhat.com>
S: Supported
F: hw/pci*
F: hw/piix*
SCSI
M: Paul Brook <paul@codesourcery.com>
M: Kevin Wolf <kwolf@redhat.com>
S: Odd Fixes
F: hw/lsi53c895a.c
F: hw/scsi*
USB
M: qemu-devel@nongnu.org
S: Odd Fixes
F: hw/usb*
vhost
M: Michael S. Tsirkin <mst@redhat.com>
S: Supported
F: hw/vhost*
virtio
M: Anthony Liguori <aliguori@us.ibm.com>
S: Supported
F: hw/virtio*
virtio-9p
M: Venkateswararao Jujjuri (JV) <jvrao@linux.vnet.ibm.com>
S: Supported
F: hw/virtio-9p*
virtio-blk
M: Kevin Wolf <kwolf@redhat.com>
S: Supported
F: hw/virtio-blk*
virtio-serial
M: Amit Shah <amit.shah@redhat.com>
S: Supported
F: hw/virtio-serial*
F: hw/virtio-console*
Subsystems
----------
Audio
M: Vassili Karpov (malc) <av1474@comtv.ru>
S: Maintained
F: audio/
Block
M: Kevin Wolf <kwolf@redhat.com>
S: Supported
F: block*
F: block/
Character Devices
M: Anthony Liguori <aliguori@us.ibm.com>
S: Maintained
F: qemu-char.c
GDB stub
M: qemu-devel@nongnu.org
S: Odd Fixes
F: gdbstub*
F: gdb-xml/
Graphics
M: Anthony Liguori <aliguori@us.ibm.com>
S: Maintained
F: ui/
Main loop
M: Anthony Liguori <aliguori@us.ibm.com>
S: Supported
F: vl.c
Monitor (QMP/HMP)
M: Luiz Capitulino <lcapitulino@redhat.com>
M: Markus Armbruster <armbru@redhat.com>
S: Supported
F: monitor.c
Network device layer
M: Anthony Liguori <aliguori@us.ibm.com>
M: Mark McLoughlin <markmc@redhat.com>
S: Maintained
F: net/
SLIRP
M: qemu-devel@nongnu.org
S: Orphan
F: slirp/
Usermode Emulation
------------------
BSD user
M: Blue Swirl <blauwirbel@gmail.com>
S: Maintained
F: bsd-user/
Darwin user
M: qemu-devel@nongnu.org
S: Orphan
F: darwin-user/
Linux user
M: Riku Voipio <riku.voipio@iki.fi>
S: Maintained
F: linux-user/

View File

@ -1,6 +1,9 @@
# Makefile for QEMU.
GENERATED_HEADERS = config-host.h trace.h qemu-options.def
ifeq ($(TRACE_BACKEND),dtrace)
GENERATED_HEADERS += trace-dtrace.h
endif
ifneq ($(wildcard config-host.mak),)
# Put the all: rule here so that config-host.mak can contain dependencies.
@ -36,18 +39,19 @@ endif
SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory)
SUBDIR_DEVICES_MAK=$(patsubst %, %/config-devices.mak, $(TARGET_DIRS))
SUBDIR_DEVICES_MAK_DEP=$(patsubst %, %/config-devices.mak.d, $(TARGET_DIRS))
config-all-devices.mak: $(SUBDIR_DEVICES_MAK)
$(call quiet-command,cat $(SUBDIR_DEVICES_MAK) | grep =y | sort -u > $@," GEN $@")
-include $(SUBDIR_DEVICES_MAK_DEP)
%/config-devices.mak: default-configs/%.mak
$(call quiet-command,cat $< > $@.tmp, " GEN $@")
$(call quiet-command,$(SHELL) $(SRC_PATH)/make_device_config.sh $@ $<, " GEN $@")
@if test -f $@; then \
if cmp -s $@.old $@; then \
if ! cmp -s $@ $@.tmp; then \
mv $@.tmp $@; \
cp -p $@ $@.old; \
fi; \
mv $@.tmp $@; \
cp -p $@ $@.old; \
else \
if test -f $@.old; then \
echo "WARNING: $@ (user modified) out of date.";\
@ -108,7 +112,11 @@ ui/vnc.o: QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
ifeq ($(TRACE_BACKEND),dtrace)
trace.h: trace.h-timestamp trace-dtrace.h
else
trace.h: trace.h-timestamp
endif
trace.h-timestamp: $(SRC_PATH)/trace-events config-host.mak
$(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -h < $< > $@," GEN trace.h")
@cmp -s $@ trace.h || cp $@ trace.h
@ -120,6 +128,20 @@ trace.c-timestamp: $(SRC_PATH)/trace-events config-host.mak
trace.o: trace.c $(GENERATED_HEADERS)
trace-dtrace.h: trace-dtrace.dtrace
$(call quiet-command,dtrace -o $@ -h -s $<, " GEN trace-dtrace.h")
# Normal practice is to name DTrace probe file with a '.d' extension
# but that gets picked up by QEMU's Makefile as an external dependancy
# rule file. So we use '.dtrace' instead
trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp
trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events config-host.mak
$(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -d < $< > $@," GEN trace-dtrace.dtrace")
@cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace
trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS)
$(call quiet-command,dtrace -o $@ -G -s $<, " GEN trace-dtrace.o")
simpletrace.o: simpletrace.c $(GENERATED_HEADERS)
version.o: $(SRC_PATH)/version.rc config-host.mak
@ -129,7 +151,7 @@ version-obj-$(CONFIG_WIN32) += version.o
######################################################################
qemu-img.o: qemu-img-cmds.h
qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o: $(GENERATED_HEADERS)
qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o cmd.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
@ -142,12 +164,14 @@ qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o: $(GENERATED_HEADERS)
check-qint: check-qint.o qint.o qemu-malloc.o $(trace-obj-y)
check-qstring: check-qstring.o qstring.o qemu-malloc.o $(trace-obj-y)
check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qemu-malloc.o qlist.o $(trace-obj-y)
check-qlist: check-qlist.o qlist.o qint.o qemu-malloc.o $(trace-obj-y)
check-qfloat: check-qfloat.o qfloat.o qemu-malloc.o $(trace-obj-y)
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 qemu-malloc.o $(trace-obj-y)
CHECK_PROG_DEPS = qemu-malloc.o $(oslib-obj-y) $(trace-obj-y)
check-qint: check-qint.o qint.o $(CHECK_PROG_DEPS)
check-qstring: check-qstring.o qstring.o $(CHECK_PROG_DEPS)
check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(CHECK_PROG_DEPS)
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 $(CHECK_PROG_DEPS)
clean:
# avoid old build problems by removing potentially incorrect old files
@ -157,6 +181,8 @@ clean:
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 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
$(MAKE) -C tests clean
for d in $(ALL_SUBDIRS) libhw32 libhw64 libuser libdis libdis-user; do \
if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
@ -178,8 +204,9 @@ ar de en-us fi fr-be hr it lv nl pl ru th \
common de-ch es fo fr-ca hu ja mk nl-be pt sl tr
ifdef INSTALL_BLOBS
BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
openbios-sparc32 openbios-sparc64 openbios-ppc \
BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin \
vgabios-stdvga.bin vgabios-vmware.bin \
ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \
gpxe-eepro100-80861209.rom \
pxe-e1000.bin \
pxe-ne2k_pci.bin pxe-pcnet.bin \

View File

@ -42,6 +42,11 @@ net-nested-$(CONFIG_SLIRP) += slirp.o
net-nested-$(CONFIG_VDE) += vde.o
net-obj-y += $(addprefix net/, $(net-nested-y))
ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS),yy)
# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
# only pull in the actual virtio-9p device if we also enabled virtio.
CONFIG_REALLY_VIRTFS=y
endif
fsdev-nested-$(CONFIG_VIRTFS) = qemu-fsdev.o
fsdev-obj-$(CONFIG_VIRTFS) += $(addprefix fsdev/, $(fsdev-nested-y))
@ -102,6 +107,7 @@ common-obj-$(CONFIG_SPICE) += ui/spice-core.o ui/spice-input.o ui/spice-display.
audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
audio-obj-$(CONFIG_SDL) += sdlaudio.o
audio-obj-$(CONFIG_OSS) += ossaudio.o
audio-obj-$(CONFIG_SPICE) += spiceaudio.o
audio-obj-$(CONFIG_COREAUDIO) += coreaudio.o
audio-obj-$(CONFIG_ALSA) += alsaaudio.o
audio-obj-$(CONFIG_DSOUND) += dsoundaudio.o
@ -158,9 +164,13 @@ user-obj-y += cutils.o cache-utils.o
hw-obj-y =
hw-obj-y += vl.o loader.o
hw-obj-y += virtio.o virtio-console.o
hw-obj-y += fw_cfg.o pci.o pci_host.o pcie_host.o pci_bridge.o
hw-obj-y += ioh3420.o xio3130_upstream.o xio3130_downstream.o
hw-obj-$(CONFIG_VIRTIO) += virtio.o virtio-console.o
hw-obj-y += fw_cfg.o
# FIXME: Core PCI code and its direct dependencies are required by the
# QMP query-pci command.
hw-obj-y += pci.o pci_bridge.o msix.o msi.o
hw-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
hw-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
hw-obj-y += watchdog.o
hw-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
hw-obj-$(CONFIG_ECC) += ecc.o
@ -205,15 +215,16 @@ hw-obj-$(CONFIG_PPCE500_PCI) += ppce500_pci.o
hw-obj-$(CONFIG_PIIX4) += piix4.o
# PCI watchdog devices
hw-obj-y += wdt_i6300esb.o
hw-obj-$(CONFIG_PCI) += wdt_i6300esb.o
hw-obj-y += pcie.o pcie_aer.o pcie_port.o
hw-obj-y += msix.o msi.o
hw-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
hw-obj-$(CONFIG_PCI) += msix.o msi.o
# PCI network cards
hw-obj-y += ne2000.o
hw-obj-y += eepro100.o
hw-obj-y += pcnet.o
hw-obj-$(CONFIG_NE2000_PCI) += ne2000.o
hw-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o
hw-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o
hw-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
hw-obj-$(CONFIG_SMC91C111) += smc91c111.o
hw-obj-$(CONFIG_LAN9118) += lan9118.o
@ -230,7 +241,7 @@ hw-obj-$(CONFIG_IDE_MACIO) += ide/macio.o
hw-obj-$(CONFIG_IDE_VIA) += ide/via.o
# SCSI layer
hw-obj-y += lsi53c895a.o
hw-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o
hw-obj-$(CONFIG_ESP) += esp.o
hw-obj-y += dma-helpers.o sysbus.o isa-bus.o
@ -260,7 +271,8 @@ sound-obj-$(CONFIG_HDA) += intel-hda.o hda-audio.o
adlib.o fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0
hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
hw-obj-$(CONFIG_VIRTFS) += virtio-9p-debug.o virtio-9p-local.o virtio-9p-xattr.o
hw-obj-$(CONFIG_REALLY_VIRTFS) += virtio-9p-debug.o
hw-obj-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o
hw-obj-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
######################################################################
@ -285,11 +297,15 @@ libdis-$(CONFIG_SPARC_DIS) += sparc-dis.o
######################################################################
# trace
ifeq ($(TRACE_BACKEND),dtrace)
trace-obj-y = trace-dtrace.o
else
trace-obj-y = trace.o
ifeq ($(TRACE_BACKEND),simple)
trace-obj-y += simpletrace.o
user-obj-y += qemu-timer-common.o
endif
endif
vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)

View File

@ -30,6 +30,7 @@ endif
endif
PROGS=$(QEMU_PROG)
STPFILES=
ifndef CONFIG_HAIKU
LIBS+=-lm
@ -40,7 +41,27 @@ kvm.o kvm-all.o vhost.o vhost_net.o: QEMU_CFLAGS+=$(KVM_CFLAGS)
config-target.h: config-target.h-timestamp
config-target.h-timestamp: config-target.mak
all: $(PROGS)
ifdef CONFIG_SYSTEMTAP_TRACE
stap: $(QEMU_PROG).stp
ifdef CONFIG_USER_ONLY
TARGET_TYPE=user
else
TARGET_TYPE=system
endif
$(QEMU_PROG).stp:
$(call quiet-command,sh $(SRC_PATH)/tracetool \
--$(TRACE_BACKEND) \
--binary $(bindir)/$(QEMU_PROG) \
--target-arch $(TARGET_ARCH) \
--target-type $(TARGET_TYPE) \
--stap < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_PROG).stp")
else
stap:
endif
all: $(PROGS) stap
# Dummy command so that make thinks it has done something
@true
@ -167,11 +188,11 @@ ifdef CONFIG_SOFTMMU
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-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
obj-$(CONFIG_VIRTIO) += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
obj-y += vhost_net.o
obj-$(CONFIG_VHOST_NET) += vhost.o
obj-$(CONFIG_VIRTFS) += virtio-9p.o
obj-$(CONFIG_REALLY_VIRTFS) += virtio-9p.o
obj-y += rwhandler.o
obj-$(CONFIG_KVM) += kvm.o kvm-all.o
obj-$(CONFIG_NO_KVM) += kvm-stub.o
@ -189,8 +210,8 @@ obj-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
obj-$(CONFIG_USB_OHCI) += usb-ohci.o
# PCI network cards
obj-y += rtl8139.o
obj-y += e1000.o
obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
obj-$(CONFIG_E1000_PCI) += e1000.o
# Inter-VM PCI shared memory
obj-$(CONFIG_KVM) += ivshmem.o
@ -340,6 +361,9 @@ clean:
rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o
rm -f *.d */*.d tcg/*.o ide/*.o
rm -f hmp-commands.h qmp-commands.h gdbstub-xml.c
ifdef CONFIG_SYSTEMTAP_TRACE
rm -f *.stp
endif
install: all
ifneq ($(PROGS),)
@ -348,6 +372,10 @@ ifneq ($(STRIP),)
$(STRIP) $(patsubst %,"$(DESTDIR)$(bindir)/%",$(PROGS))
endif
endif
ifdef CONFIG_SYSTEMTAP_TRACE
$(INSTALL_DIR) "$(DESTDIR)$(datadir)/../systemtap/tapset"
$(INSTALL_DATA) $(QEMU_PROG).stp "$(DESTDIR)$(datadir)/../systemtap/tapset"
endif
# Include automatically generated dependency files
-include $(wildcard *.d */*.d)

View File

@ -19,10 +19,7 @@ o qmp-spec.txt QEMU Monitor Protocol current specification
o qmp-commands.txt QMP supported commands (auto-generated at build-time)
o qmp-events.txt List of available asynchronous events
There are also two simple Python scripts available:
o qmp-shell A shell
o vm-info Show some information about the Virtual Machine
There is also a simple Python script called 'qmp-shell' available.
IMPORTANT: It's strongly recommended to read the 'Stability Considerations'
section in the qmp-commands.txt file before making any serious use of QMP.

View File

@ -1,8 +1,8 @@
#!/usr/bin/python
#
# Simple QEMU shell on top of QMP
# Low-level QEMU shell on top of QMP.
#
# Copyright (C) 2009 Red Hat Inc.
# Copyright (C) 2009, 2010 Red Hat Inc.
#
# Authors:
# Luiz Capitulino <lcapitulino@redhat.com>
@ -14,60 +14,246 @@
#
# Start QEMU with:
#
# $ qemu [...] -monitor control,unix:./qmp,server
# # qemu [...] -qmp unix:./qmp-sock,server
#
# Run the shell:
#
# $ qmp-shell ./qmp
# $ qmp-shell ./qmp-sock
#
# Commands have the following format:
#
# < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ]
# < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ]
#
# For example:
#
# (QEMU) info item=network
# (QEMU) device_add driver=e1000 id=net1
# {u'return': {}}
# (QEMU)
import qmp
import readline
from sys import argv,exit
import sys
def shell_help():
print 'bye exit from the shell'
class QMPCompleter(list):
def complete(self, text, state):
for cmd in self:
if cmd.startswith(text):
if not state:
return cmd
else:
state -= 1
def main():
if len(argv) != 2:
print 'qemu-shell <unix-socket>'
exit(1)
class QMPShellError(Exception):
pass
qemu = qmp.QEMUMonitorProtocol(argv[1])
qemu.connect()
qemu.send("qmp_capabilities")
class QMPShellBadPort(QMPShellError):
pass
print 'Connected!'
# TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and
# _execute_cmd()). Let's design a better one.
class QMPShell(qmp.QEMUMonitorProtocol):
def __init__(self, address):
qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address))
self._greeting = None
self._completer = None
while True:
def __get_address(self, arg):
"""
Figure out if the argument is in the port:host form, if it's not it's
probably a file path.
"""
addr = arg.split(':')
if len(addr) == 2:
try:
port = int(addr[1])
except ValueError:
raise QMPShellBadPort
return ( addr[0], port )
# socket path
return arg
def _fill_completion(self):
for cmd in self.cmd('query-commands')['return']:
self._completer.append(cmd['name'])
def __completer_setup(self):
self._completer = QMPCompleter()
self._fill_completion()
readline.set_completer(self._completer.complete)
readline.parse_and_bind("tab: complete")
# XXX: default delimiters conflict with some command names (eg. query-),
# clearing everything as it doesn't seem to matter
readline.set_completer_delims('')
def __build_cmd(self, cmdline):
"""
Build a QMP input object from a user provided command-line in the
following format:
< command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ]
"""
cmdargs = cmdline.split()
qmpcmd = { 'execute': cmdargs[0], 'arguments': {} }
for arg in cmdargs[1:]:
opt = arg.split('=')
try:
value = int(opt[1])
except ValueError:
value = opt[1]
qmpcmd['arguments'][opt[0]] = value
return qmpcmd
def _execute_cmd(self, cmdline):
try:
cmd = raw_input('(QEMU) ')
qmpcmd = self.__build_cmd(cmdline)
except:
print 'command format: <command-name> ',
print '[arg-name1=arg1] ... [arg-nameN=argN]'
return True
resp = self.cmd_obj(qmpcmd)
if resp is None:
print 'Disconnected'
return False
print resp
return True
def connect(self):
self._greeting = qmp.QEMUMonitorProtocol.connect(self)
self.__completer_setup()
def show_banner(self, msg='Welcome to the QMP low-level shell!'):
print msg
version = self._greeting['QMP']['version']['qemu']
print 'Connected to QEMU %d.%d.%d\n' % (version['major'],version['minor'],version['micro'])
def read_exec_command(self, prompt):
"""
Read and execute a command.
@return True if execution was ok, return False if disconnected.
"""
try:
cmdline = raw_input(prompt)
except EOFError:
print
break
if cmd == '':
continue
elif cmd == 'bye':
break
elif cmd == 'help':
shell_help()
return False
if cmdline == '':
for ev in self.get_events():
print ev
self.clear_events()
return True
else:
return self._execute_cmd(cmdline)
class HMPShell(QMPShell):
def __init__(self, address):
QMPShell.__init__(self, address)
self.__cpu_index = 0
def __cmd_completion(self):
for cmd in self.__cmd_passthrough('help')['return'].split('\r\n'):
if cmd and cmd[0] != '[' and cmd[0] != '\t':
name = cmd.split()[0] # drop help text
if name == 'info':
continue
if name.find('|') != -1:
# Command in the form 'foobar|f' or 'f|foobar', take the
# full name
opt = name.split('|')
if len(opt[0]) == 1:
name = opt[1]
else:
name = opt[0]
self._completer.append(name)
self._completer.append('help ' + name) # help completion
def __info_completion(self):
for cmd in self.__cmd_passthrough('info')['return'].split('\r\n'):
if cmd:
self._completer.append('info ' + cmd.split()[1])
def __other_completion(self):
# special cases
self._completer.append('help info')
def _fill_completion(self):
self.__cmd_completion()
self.__info_completion()
self.__other_completion()
def __cmd_passthrough(self, cmdline, cpu_index = 0):
return self.cmd_obj({ 'execute': 'human-monitor-command', 'arguments':
{ 'command-line': cmdline,
'cpu-index': cpu_index } })
def _execute_cmd(self, cmdline):
if cmdline.split()[0] == "cpu":
# trap the cpu command, it requires special setting
try:
resp = qemu.send(cmd)
if resp == None:
print 'Disconnected'
break
print resp
except IndexError:
print '-> command format: <command-name> ',
print '[arg-name1=arg1] ... [arg-nameN=argN]'
idx = int(cmdline.split()[1])
if not 'return' in self.__cmd_passthrough('info version', idx):
print 'bad CPU index'
return True
self.__cpu_index = idx
except ValueError:
print 'cpu command takes an integer argument'
return True
resp = self.__cmd_passthrough(cmdline, self.__cpu_index)
if resp is None:
print 'Disconnected'
return False
assert 'return' in resp or 'error' in resp
if 'return' in resp:
# Success
if len(resp['return']) > 0:
print resp['return'],
else:
# Error
print '%s: %s' % (resp['error']['class'], resp['error']['desc'])
return True
def show_banner(self):
QMPShell.show_banner(self, msg='Welcome to the HMP shell!')
def die(msg):
sys.stderr.write('ERROR: %s\n' % msg)
sys.exit(1)
def fail_cmdline(option=None):
if option:
sys.stderr.write('ERROR: bad command-line option \'%s\'\n' % option)
sys.stderr.write('qemu-shell [ -H ] < UNIX socket path> | < TCP address:port >\n')
sys.exit(1)
def main():
addr = ''
try:
if len(sys.argv) == 2:
qemu = QMPShell(sys.argv[1])
addr = sys.argv[1]
elif len(sys.argv) == 3:
if sys.argv[1] != '-H':
fail_cmdline(sys.argv[1])
qemu = HMPShell(sys.argv[2])
addr = sys.argv[2]
else:
fail_cmdline()
except QMPShellBadPort:
die('bad port number in command-line')
try:
qemu.connect()
except qmp.QMPConnectError:
die('Didn\'t get QMP greeting message')
except qmp.QMPCapabilitiesError:
die('Could not negotiate capabilities')
except qemu.error:
die('Could not connect to %s' % addr)
qemu.show_banner()
while qemu.read_exec_command('(QEMU) '):
pass
qemu.close()
if __name__ == '__main__':
main()

View File

@ -1,6 +1,6 @@
# QEMU Monitor Protocol Python class
#
# Copyright (C) 2009 Red Hat Inc.
# Copyright (C) 2009, 2010 Red Hat Inc.
#
# Authors:
# Luiz Capitulino <lcapitulino@redhat.com>
@ -8,7 +8,9 @@
# This work is licensed under the terms of the GNU GPL, version 2. See
# the COPYING file in the top-level directory.
import socket, json
import json
import errno
import socket
class QMPError(Exception):
pass
@ -16,61 +18,114 @@ class QMPError(Exception):
class QMPConnectError(QMPError):
pass
class QMPCapabilitiesError(QMPError):
pass
class QEMUMonitorProtocol:
def connect(self):
self.sock.connect(self.filename)
data = self.__json_read()
if data == None:
raise QMPConnectError
if not data.has_key('QMP'):
raise QMPConnectError
return data['QMP']['capabilities']
def __init__(self, address):
"""
Create a QEMUMonitorProtocol class.
def close(self):
self.sock.close()
@param address: QEMU address, can be either a unix socket path (string)
or a tuple in the form ( address, port ) for a TCP
connection
@note No connection is established, this is done by the connect() method
"""
self.__events = []
self.__address = address
self.__sock = self.__get_sock()
self.__sockfile = self.__sock.makefile()
def send_raw(self, line):
self.sock.send(str(line))
return self.__json_read()
def send(self, cmdline):
cmd = self.__build_cmd(cmdline)
self.__json_send(cmd)
resp = self.__json_read()
if resp == None:
return
elif resp.has_key('error'):
return resp['error']
def __get_sock(self):
if isinstance(self.__address, tuple):
family = socket.AF_INET
else:
return resp['return']
def __build_cmd(self, cmdline):
cmdargs = cmdline.split()
qmpcmd = { 'execute': cmdargs[0], 'arguments': {} }
for arg in cmdargs[1:]:
opt = arg.split('=')
try:
value = int(opt[1])
except ValueError:
value = opt[1]
qmpcmd['arguments'][opt[0]] = value
return qmpcmd
def __json_send(self, cmd):
# XXX: We have to send any additional char, otherwise
# the Server won't read our input
self.sock.send(json.dumps(cmd) + ' ')
family = socket.AF_UNIX
return socket.socket(family, socket.SOCK_STREAM)
def __json_read(self):
try:
while True:
line = json.loads(self.sockfile.readline())
if not 'event' in line:
return line
except ValueError:
return
while True:
data = self.__sockfile.readline()
if not data:
return
resp = json.loads(data)
if 'event' in resp:
self.__events.append(resp)
continue
return resp
def __init__(self, filename):
self.filename = filename
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.sockfile = self.sock.makefile()
error = socket.error
def connect(self):
"""
Connect to the QMP Monitor and perform capabilities negotiation.
@return QMP greeting dict
@raise socket.error on socket connection errors
@raise QMPConnectError if the greeting is not received
@raise QMPCapabilitiesError if fails to negotiate capabilities
"""
self.__sock.connect(self.__address)
greeting = self.__json_read()
if greeting is None or not greeting.has_key('QMP'):
raise QMPConnectError
# Greeting seems ok, negotiate capabilities
resp = self.cmd('qmp_capabilities')
if "return" in resp:
return greeting
raise QMPCapabilitiesError
def cmd_obj(self, qmp_cmd):
"""
Send a QMP command to the QMP Monitor.
@param qmp_cmd: QMP command to be sent as a Python dict
@return QMP response as a Python dict or None if the connection has
been closed
"""
try:
self.__sock.sendall(json.dumps(qmp_cmd))
except socket.error, err:
if err[0] == errno.EPIPE:
return
raise socket.error(err)
return self.__json_read()
def cmd(self, name, args=None, id=None):
"""
Build a QMP command and send it to the QMP Monitor.
@param name: command name (string)
@param args: command arguments (dict)
@param id: command id (dict, list, string or int)
"""
qmp_cmd = { 'execute': name }
if args:
qmp_cmd['arguments'] = args
if id:
qmp_cmd['id'] = id
return self.cmd_obj(qmp_cmd)
def get_events(self):
"""
Get a list of available QMP events.
"""
self.__sock.setblocking(0)
try:
self.__json_read()
except socket.error, err:
if err[0] == errno.EAGAIN:
# No data available
pass
self.__sock.setblocking(1)
return self.__events
def clear_events(self):
"""
Clear current list of pending events.
"""
self.__events = []
def close(self):
self.__sock.close()
self.__sockfile.close()

View File

@ -1,33 +0,0 @@
#!/usr/bin/python
#
# Print Virtual Machine information
#
# Usage:
#
# Start QEMU with:
#
# $ qemu [...] -monitor control,unix:./qmp,server
#
# Run vm-info:
#
# $ vm-info ./qmp
#
# Luiz Capitulino <lcapitulino@redhat.com>
import qmp
from sys import argv,exit
def main():
if len(argv) != 2:
print 'vm-info <unix-socket>'
exit(1)
qemu = qmp.QEMUMonitorProtocol(argv[1])
qemu.connect()
qemu.send("qmp_capabilities")
for cmd in [ 'version', 'kvm', 'status', 'uuid', 'balloon' ]:
print cmd + ': ' + str(qemu.send('query-' + cmd))
if __name__ == '__main__':
main()

View File

@ -44,6 +44,9 @@
that we generate the list.
*/
static struct audio_driver *drvtab[] = {
#ifdef CONFIG_SPICE
&spice_audio_driver,
#endif
CONFIG_AUDIO_DRIVERS
&no_audio_driver,
&wav_audio_driver
@ -1093,15 +1096,6 @@ static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info)
/*
* Timer
*/
static void audio_timer (void *opaque)
{
AudioState *s = opaque;
audio_run ("timer");
qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
}
static int audio_is_timer_needed (void)
{
HWVoiceIn *hwi = NULL;
@ -1116,10 +1110,8 @@ static int audio_is_timer_needed (void)
return 0;
}
static void audio_reset_timer (void)
static void audio_reset_timer (AudioState *s)
{
AudioState *s = &glob_audio_state;
if (audio_is_timer_needed ()) {
qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
}
@ -1128,6 +1120,12 @@ static void audio_reset_timer (void)
}
}
static void audio_timer (void *opaque)
{
audio_run ("timer");
audio_reset_timer (opaque);
}
/*
* Public API
*/
@ -1192,7 +1190,7 @@ void AUD_set_active_out (SWVoiceOut *sw, int on)
hw->enabled = 1;
if (s->vm_running) {
hw->pcm_ops->ctl_out (hw, VOICE_ENABLE, conf.try_poll_out);
audio_reset_timer ();
audio_reset_timer (s);
}
}
}
@ -1237,6 +1235,7 @@ void AUD_set_active_in (SWVoiceIn *sw, int on)
hw->enabled = 1;
if (s->vm_running) {
hw->pcm_ops->ctl_in (hw, VOICE_ENABLE, conf.try_poll_in);
audio_reset_timer (s);
}
}
sw->total_hw_samples_acquired = hw->total_samples_captured;
@ -1758,7 +1757,7 @@ static void audio_vm_change_state_handler (void *opaque, int running,
while ((hwi = audio_pcm_hw_find_any_enabled_in (hwi))) {
hwi->pcm_ops->ctl_in (hwi, op, conf.try_poll_in);
}
audio_reset_timer ();
audio_reset_timer (s);
}
static void audio_atexit (void)

View File

@ -209,6 +209,7 @@ extern struct audio_driver coreaudio_audio_driver;
extern struct audio_driver dsound_audio_driver;
extern struct audio_driver esd_audio_driver;
extern struct audio_driver pa_audio_driver;
extern struct audio_driver spice_audio_driver;
extern struct audio_driver winwave_audio_driver;
extern struct mixeng_volume nominal_volume;

346
audio/spiceaudio.c Normal file
View File

@ -0,0 +1,346 @@
/*
* Copyright (C) 2010 Red Hat, Inc.
*
* maintained by Gerd Hoffmann <kraxel@redhat.com>
*
* This program 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 or
* (at your option) version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "hw/hw.h"
#include "qemu-timer.h"
#include "ui/qemu-spice.h"
#define AUDIO_CAP "spice"
#include "audio.h"
#include "audio_int.h"
#define LINE_IN_SAMPLES 1024
#define LINE_OUT_SAMPLES 1024
typedef struct SpiceRateCtl {
int64_t start_ticks;
int64_t bytes_sent;
} SpiceRateCtl;
typedef struct SpiceVoiceOut {
HWVoiceOut hw;
SpicePlaybackInstance sin;
SpiceRateCtl rate;
int active;
uint32_t *frame;
uint32_t *fpos;
uint32_t fsize;
} SpiceVoiceOut;
typedef struct SpiceVoiceIn {
HWVoiceIn hw;
SpiceRecordInstance sin;
SpiceRateCtl rate;
int active;
uint32_t samples[LINE_IN_SAMPLES];
} SpiceVoiceIn;
static const SpicePlaybackInterface playback_sif = {
.base.type = SPICE_INTERFACE_PLAYBACK,
.base.description = "playback",
.base.major_version = SPICE_INTERFACE_PLAYBACK_MAJOR,
.base.minor_version = SPICE_INTERFACE_PLAYBACK_MINOR,
};
static const SpiceRecordInterface record_sif = {
.base.type = SPICE_INTERFACE_RECORD,
.base.description = "record",
.base.major_version = SPICE_INTERFACE_RECORD_MAJOR,
.base.minor_version = SPICE_INTERFACE_RECORD_MINOR,
};
static void *spice_audio_init (void)
{
if (!using_spice) {
return NULL;
}
return &spice_audio_init;
}
static void spice_audio_fini (void *opaque)
{
/* nothing */
}
static void rate_start (SpiceRateCtl *rate)
{
memset (rate, 0, sizeof (*rate));
rate->start_ticks = qemu_get_clock (vm_clock);
}
static int rate_get_samples (struct audio_pcm_info *info, SpiceRateCtl *rate)
{
int64_t now;
int64_t ticks;
int64_t bytes;
int64_t samples;
now = qemu_get_clock (vm_clock);
ticks = now - rate->start_ticks;
bytes = muldiv64 (ticks, info->bytes_per_second, get_ticks_per_sec ());
samples = (bytes - rate->bytes_sent) >> info->shift;
if (samples < 0 || samples > 65536) {
fprintf (stderr, "Resetting rate control (%" PRId64 " samples)\n", samples);
rate_start (rate);
samples = 0;
}
rate->bytes_sent += samples << info->shift;
return samples;
}
/* playback */
static int line_out_init (HWVoiceOut *hw, struct audsettings *as)
{
SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw);
struct audsettings settings;
settings.freq = SPICE_INTERFACE_PLAYBACK_FREQ;
settings.nchannels = SPICE_INTERFACE_PLAYBACK_CHAN;
settings.fmt = AUD_FMT_S16;
settings.endianness = AUDIO_HOST_ENDIANNESS;
audio_pcm_init_info (&hw->info, &settings);
hw->samples = LINE_OUT_SAMPLES;
out->active = 0;
out->sin.base.sif = &playback_sif.base;
qemu_spice_add_interface (&out->sin.base);
return 0;
}
static void line_out_fini (HWVoiceOut *hw)
{
SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw);
spice_server_remove_interface (&out->sin.base);
}
static int line_out_run (HWVoiceOut *hw, int live)
{
SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw);
int rpos, decr;
int samples;
if (!live) {
return 0;
}
decr = rate_get_samples (&hw->info, &out->rate);
decr = audio_MIN (live, decr);
samples = decr;
rpos = hw->rpos;
while (samples) {
int left_till_end_samples = hw->samples - rpos;
int len = audio_MIN (samples, left_till_end_samples);
if (!out->frame) {
spice_server_playback_get_buffer (&out->sin, &out->frame, &out->fsize);
out->fpos = out->frame;
}
if (out->frame) {
len = audio_MIN (len, out->fsize);
hw->clip (out->fpos, hw->mix_buf + rpos, len);
out->fsize -= len;
out->fpos += len;
if (out->fsize == 0) {
spice_server_playback_put_samples (&out->sin, out->frame);
out->frame = out->fpos = NULL;
}
}
rpos = (rpos + len) % hw->samples;
samples -= len;
}
hw->rpos = rpos;
return decr;
}
static int line_out_write (SWVoiceOut *sw, void *buf, int len)
{
return audio_pcm_sw_write (sw, buf, len);
}
static int line_out_ctl (HWVoiceOut *hw, int cmd, ...)
{
SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw);
switch (cmd) {
case VOICE_ENABLE:
if (out->active) {
break;
}
out->active = 1;
rate_start (&out->rate);
spice_server_playback_start (&out->sin);
break;
case VOICE_DISABLE:
if (!out->active) {
break;
}
out->active = 0;
if (out->frame) {
memset (out->fpos, 0, out->fsize << 2);
spice_server_playback_put_samples (&out->sin, out->frame);
out->frame = out->fpos = NULL;
}
spice_server_playback_stop (&out->sin);
break;
}
return 0;
}
/* record */
static int line_in_init (HWVoiceIn *hw, struct audsettings *as)
{
SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw);
struct audsettings settings;
settings.freq = SPICE_INTERFACE_RECORD_FREQ;
settings.nchannels = SPICE_INTERFACE_RECORD_CHAN;
settings.fmt = AUD_FMT_S16;
settings.endianness = AUDIO_HOST_ENDIANNESS;
audio_pcm_init_info (&hw->info, &settings);
hw->samples = LINE_IN_SAMPLES;
in->active = 0;
in->sin.base.sif = &record_sif.base;
qemu_spice_add_interface (&in->sin.base);
return 0;
}
static void line_in_fini (HWVoiceIn *hw)
{
SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw);
spice_server_remove_interface (&in->sin.base);
}
static int line_in_run (HWVoiceIn *hw)
{
SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw);
int num_samples;
int ready;
int len[2];
uint64_t delta_samp;
const uint32_t *samples;
if (!(num_samples = hw->samples - audio_pcm_hw_get_live_in (hw))) {
return 0;
}
delta_samp = rate_get_samples (&hw->info, &in->rate);
num_samples = audio_MIN (num_samples, delta_samp);
ready = spice_server_record_get_samples (&in->sin, in->samples, num_samples);
samples = in->samples;
if (ready == 0) {
static const uint32_t silence[LINE_IN_SAMPLES];
samples = silence;
ready = LINE_IN_SAMPLES;
}
num_samples = audio_MIN (ready, num_samples);
if (hw->wpos + num_samples > hw->samples) {
len[0] = hw->samples - hw->wpos;
len[1] = num_samples - len[0];
} else {
len[0] = num_samples;
len[1] = 0;
}
hw->conv (hw->conv_buf + hw->wpos, samples, len[0], &nominal_volume);
if (len[1]) {
hw->conv (hw->conv_buf, samples + len[0], len[1],
&nominal_volume);
}
hw->wpos = (hw->wpos + num_samples) % hw->samples;
return num_samples;
}
static int line_in_read (SWVoiceIn *sw, void *buf, int size)
{
return audio_pcm_sw_read (sw, buf, size);
}
static int line_in_ctl (HWVoiceIn *hw, int cmd, ...)
{
SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw);
switch (cmd) {
case VOICE_ENABLE:
if (in->active) {
break;
}
in->active = 1;
rate_start (&in->rate);
spice_server_record_start (&in->sin);
break;
case VOICE_DISABLE:
if (!in->active) {
break;
}
in->active = 0;
spice_server_record_stop (&in->sin);
break;
}
return 0;
}
static struct audio_option audio_options[] = {
{ /* end of list */ },
};
static struct audio_pcm_ops audio_callbacks = {
.init_out = line_out_init,
.fini_out = line_out_fini,
.run_out = line_out_run,
.write = line_out_write,
.ctl_out = line_out_ctl,
.init_in = line_in_init,
.fini_in = line_in_fini,
.run_in = line_in_run,
.read = line_in_read,
.ctl_in = line_in_ctl,
};
struct audio_driver spice_audio_driver = {
.name = "spice",
.descr = "spice audio driver",
.options = audio_options,
.init = spice_audio_init,
.fini = spice_audio_fini,
.pcm_ops = &audio_callbacks,
.max_voices_out = 1,
.max_voices_in = 1,
.voice_size_out = sizeof (SpiceVoiceOut),
.voice_size_in = sizeof (SpiceVoiceIn),
};
void qemu_spice_audio_init (void)
{
spice_audio_driver.can_be_default = 1;
}

View File

@ -49,12 +49,14 @@ typedef struct BlkMigDevState {
int64_t total_sectors;
int64_t dirty;
QSIMPLEQ_ENTRY(BlkMigDevState) entry;
unsigned long *aio_bitmap;
} BlkMigDevState;
typedef struct BlkMigBlock {
uint8_t *buf;
BlkMigDevState *bmds;
int64_t sector;
int nr_sectors;
struct iovec iov;
QEMUIOVector qiov;
BlockDriverAIOCB *aiocb;
@ -140,6 +142,52 @@ static inline long double compute_read_bwidth(void)
return (block_mig_state.reads * BLOCK_SIZE)/ block_mig_state.total_time;
}
static int bmds_aio_inflight(BlkMigDevState *bmds, int64_t sector)
{
int64_t chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK;
if ((sector << BDRV_SECTOR_BITS) < bdrv_getlength(bmds->bs)) {
return !!(bmds->aio_bitmap[chunk / (sizeof(unsigned long) * 8)] &
(1UL << (chunk % (sizeof(unsigned long) * 8))));
} else {
return 0;
}
}
static void bmds_set_aio_inflight(BlkMigDevState *bmds, int64_t sector_num,
int nb_sectors, int set)
{
int64_t start, end;
unsigned long val, idx, bit;
start = sector_num / BDRV_SECTORS_PER_DIRTY_CHUNK;
end = (sector_num + nb_sectors - 1) / BDRV_SECTORS_PER_DIRTY_CHUNK;
for (; start <= end; start++) {
idx = start / (sizeof(unsigned long) * 8);
bit = start % (sizeof(unsigned long) * 8);
val = bmds->aio_bitmap[idx];
if (set) {
val |= 1UL << bit;
} else {
val &= ~(1UL << bit);
}
bmds->aio_bitmap[idx] = val;
}
}
static void alloc_aio_bitmap(BlkMigDevState *bmds)
{
BlockDriverState *bs = bmds->bs;
int64_t bitmap_size;
bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS) +
BDRV_SECTORS_PER_DIRTY_CHUNK * 8 - 1;
bitmap_size /= BDRV_SECTORS_PER_DIRTY_CHUNK * 8;
bmds->aio_bitmap = qemu_mallocz(bitmap_size);
}
static void blk_mig_read_cb(void *opaque, int ret)
{
BlkMigBlock *blk = opaque;
@ -151,6 +199,7 @@ static void blk_mig_read_cb(void *opaque, int ret)
add_avg_read_time(blk->time);
QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry);
bmds_set_aio_inflight(blk->bmds, blk->sector, blk->nr_sectors, 0);
block_mig_state.submitted--;
block_mig_state.read_done++;
@ -194,6 +243,7 @@ static int mig_save_device_bulk(Monitor *mon, QEMUFile *f,
blk->buf = qemu_malloc(BLOCK_SIZE);
blk->bmds = bmds;
blk->sector = cur_sector;
blk->nr_sectors = nr_sectors;
blk->iov.iov_base = blk->buf;
blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
@ -248,6 +298,7 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
bmds->total_sectors = sectors;
bmds->completed_sectors = 0;
bmds->shared_base = block_mig_state.shared_base;
alloc_aio_bitmap(bmds);
block_mig_state.total_sector_sum += sectors;
@ -329,6 +380,9 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
int nr_sectors;
for (sector = bmds->cur_dirty; sector < bmds->total_sectors;) {
if (bmds_aio_inflight(bmds, sector)) {
qemu_aio_flush();
}
if (bdrv_get_dirty(bmds->bs, sector)) {
if (total_sectors - sector < BDRV_SECTORS_PER_DIRTY_CHUNK) {
@ -340,6 +394,7 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
blk->buf = qemu_malloc(BLOCK_SIZE);
blk->bmds = bmds;
blk->sector = sector;
blk->nr_sectors = nr_sectors;
if (is_async) {
blk->iov.iov_base = blk->buf;
@ -354,6 +409,7 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
goto error;
}
block_mig_state.submitted++;
bmds_set_aio_inflight(bmds, sector, nr_sectors, 1);
} else {
if (bdrv_read(bmds->bs, sector, blk->buf,
nr_sectors) < 0) {
@ -474,6 +530,7 @@ static void blk_mig_cleanup(Monitor *mon)
while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
qemu_free(bmds->aio_bitmap);
qemu_free(bmds);
}

75
block.c
View File

@ -930,14 +930,14 @@ static void set_dirty_bitmap(BlockDriverState *bs, int64_t sector_num,
bit = start % (sizeof(unsigned long) * 8);
val = bs->dirty_bitmap[idx];
if (dirty) {
if (!(val & (1 << bit))) {
if (!(val & (1UL << bit))) {
bs->dirty_count++;
val |= 1 << bit;
val |= 1UL << bit;
}
} else {
if (val & (1 << bit)) {
if (val & (1UL << bit)) {
bs->dirty_count--;
val &= ~(1 << bit);
val &= ~(1UL << bit);
}
}
bs->dirty_bitmap[idx] = val;
@ -1453,14 +1453,27 @@ const char *bdrv_get_device_name(BlockDriverState *bs)
return bs->device_name;
}
void bdrv_flush(BlockDriverState *bs)
int bdrv_flush(BlockDriverState *bs)
{
if (bs->open_flags & BDRV_O_NO_FLUSH) {
return;
return 0;
}
if (bs->drv && bs->drv->bdrv_flush)
bs->drv->bdrv_flush(bs);
if (bs->drv && bs->drv->bdrv_flush) {
return bs->drv->bdrv_flush(bs);
}
/*
* Some block drivers always operate in either writethrough or unsafe mode
* and don't support bdrv_flush therefore. Usually qemu doesn't know how
* the server works (because the behaviour is hardcoded or depends on
* server-side configuration), so we can't ensure that everything is safe
* on disk. Returning an error doesn't work because that would break guests
* even if the server operates in writethrough mode.
*
* Let's hope the user knows what he's doing.
*/
return 0;
}
void bdrv_flush_all(void)
@ -2018,12 +2031,49 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
return ret;
}
typedef struct BlockCompleteData {
BlockDriverCompletionFunc *cb;
void *opaque;
BlockDriverState *bs;
int64_t sector_num;
int nb_sectors;
} BlockCompleteData;
static void block_complete_cb(void *opaque, int ret)
{
BlockCompleteData *b = opaque;
if (b->bs->dirty_bitmap) {
set_dirty_bitmap(b->bs, b->sector_num, b->nb_sectors, 1);
}
b->cb(b->opaque, ret);
qemu_free(b);
}
static BlockCompleteData *blk_dirty_cb_alloc(BlockDriverState *bs,
int64_t sector_num,
int nb_sectors,
BlockDriverCompletionFunc *cb,
void *opaque)
{
BlockCompleteData *blkdata = qemu_mallocz(sizeof(BlockCompleteData));
blkdata->bs = bs;
blkdata->cb = cb;
blkdata->opaque = opaque;
blkdata->sector_num = sector_num;
blkdata->nb_sectors = nb_sectors;
return blkdata;
}
BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
BlockDriver *drv = bs->drv;
BlockDriverAIOCB *ret;
BlockCompleteData *blk_cb_data;
trace_bdrv_aio_writev(bs, sector_num, nb_sectors, opaque);
@ -2035,7 +2085,10 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
return NULL;
if (bs->dirty_bitmap) {
set_dirty_bitmap(bs, sector_num, nb_sectors, 1);
blk_cb_data = blk_dirty_cb_alloc(bs, sector_num, nb_sectors, cb,
opaque);
cb = &block_complete_cb;
opaque = blk_cb_data;
}
ret = drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors,
@ -2672,8 +2725,8 @@ int bdrv_get_dirty(BlockDriverState *bs, int64_t sector)
if (bs->dirty_bitmap &&
(sector << BDRV_SECTOR_BITS) < bdrv_getlength(bs)) {
return bs->dirty_bitmap[chunk / (sizeof(unsigned long) * 8)] &
(1 << (chunk % (sizeof(unsigned long) * 8)));
return !!(bs->dirty_bitmap[chunk / (sizeof(unsigned long) * 8)] &
(1UL << (chunk % (sizeof(unsigned long) * 8))));
} else {
return 0;
}

View File

@ -142,7 +142,7 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
BlockDriverCompletionFunc *cb, void *opaque);
/* Ensure contents are flushed to disk. */
void bdrv_flush(BlockDriverState *bs);
int bdrv_flush(BlockDriverState *bs);
void bdrv_flush_all(void);
void bdrv_close_all(void);

View File

@ -397,9 +397,9 @@ static void blkdebug_close(BlockDriverState *bs)
}
}
static void blkdebug_flush(BlockDriverState *bs)
static int blkdebug_flush(BlockDriverState *bs)
{
bdrv_flush(bs->file);
return bdrv_flush(bs->file);
}
static BlockDriverAIOCB *blkdebug_aio_flush(BlockDriverState *bs,

View File

@ -116,12 +116,12 @@ static void blkverify_close(BlockDriverState *bs)
s->test_file = NULL;
}
static void blkverify_flush(BlockDriverState *bs)
static int blkverify_flush(BlockDriverState *bs)
{
BDRVBlkverifyState *s = bs->opaque;
/* Only flush test file, the raw file is not important */
bdrv_flush(s->test_file);
return bdrv_flush(s->test_file);
}
static int64_t blkverify_getlength(BlockDriverState *bs)
@ -300,8 +300,8 @@ static void blkverify_verify_readv(BlkverifyAIOCB *acb)
{
ssize_t offset = blkverify_iovec_compare(acb->qiov, &acb->raw_qiov);
if (offset != -1) {
blkverify_err(acb, "contents mismatch in sector %lld",
acb->sector_num + (offset / BDRV_SECTOR_SIZE));
blkverify_err(acb, "contents mismatch in sector %" PRId64,
acb->sector_num + (int64_t)(offset / BDRV_SECTOR_SIZE));
}
}

View File

@ -282,9 +282,9 @@ exit:
return ret;
}
static void cow_flush(BlockDriverState *bs)
static int cow_flush(BlockDriverState *bs)
{
bdrv_flush(bs->file);
return bdrv_flush(bs->file);
}
static QEMUOptionParameter cow_create_options[] = {

View File

@ -54,7 +54,6 @@ typedef struct QCowHeader {
#define L2_CACHE_SIZE 16
typedef struct BDRVQcowState {
BlockDriverState *hd;
int cluster_bits;
int cluster_size;
int cluster_sectors;
@ -910,9 +909,9 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
return 0;
}
static void qcow_flush(BlockDriverState *bs)
static int qcow_flush(BlockDriverState *bs)
{
bdrv_flush(bs->file);
return bdrv_flush(bs->file);
}
static BlockDriverAIOCB *qcow_aio_flush(BlockDriverState *bs,

View File

@ -188,6 +188,7 @@ static int l2_load(BlockDriverState *bs, uint64_t l2_offset,
ret = bdrv_pread(bs->file, l2_offset, *l2_table,
s->l2_size * sizeof(uint64_t));
if (ret < 0) {
qcow2_l2_cache_reset(bs);
return ret;
}

View File

@ -103,6 +103,7 @@ static int load_refcount_block(BlockDriverState *bs,
ret = bdrv_pread(bs->file, refcount_block_offset, s->refcount_block_cache,
s->cluster_size);
if (ret < 0) {
s->refcount_block_cache_offset = 0;
return ret;
}

View File

@ -1148,9 +1148,9 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
return 0;
}
static void qcow_flush(BlockDriverState *bs)
static int qcow_flush(BlockDriverState *bs)
{
bdrv_flush(bs->file);
return bdrv_flush(bs->file);
}
static BlockDriverAIOCB *qcow_aio_flush(BlockDriverState *bs,

View File

@ -79,7 +79,6 @@ typedef struct QCowSnapshot {
} QCowSnapshot;
typedef struct BDRVQcowState {
BlockDriverState *hd;
int cluster_bits;
int cluster_size;
int cluster_sectors;

View File

@ -463,7 +463,7 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset,
count -= ret;
sum += ret;
}
/* here, count < 512 because (count & ~sector_mask) == 0 */
/* here, count < sector_size because (count & ~sector_mask) == 0 */
if (count) {
ret = raw_pread_aligned(bs, offset, s->aligned_buf,
bs->buffer_alignment);
@ -734,10 +734,10 @@ static int raw_create(const char *filename, QEMUOptionParameter *options)
return result;
}
static void raw_flush(BlockDriverState *bs)
static int raw_flush(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
qemu_fdatasync(s->fd);
return qemu_fdatasync(s->fd);
}

View File

@ -147,10 +147,17 @@ static int raw_write(BlockDriverState *bs, int64_t sector_num,
return ret_count;
}
static void raw_flush(BlockDriverState *bs)
static int raw_flush(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
FlushFileBuffers(s->hfile);
int ret;
ret = FlushFileBuffers(s->hfile);
if (ret != 0) {
return -EIO;
}
return 0;
}
static void raw_close(BlockDriverState *bs)

View File

@ -39,9 +39,9 @@ static void raw_close(BlockDriverState *bs)
{
}
static void raw_flush(BlockDriverState *bs)
static int raw_flush(BlockDriverState *bs)
{
bdrv_flush(bs->file);
return bdrv_flush(bs->file);
}
static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,

View File

@ -186,7 +186,6 @@ typedef struct {
} VdiHeader;
typedef struct {
BlockDriverState *hd;
/* The block map entries are little endian (even in memory). */
uint32_t *bmap;
/* Size of block (bytes). */
@ -900,10 +899,10 @@ static void vdi_close(BlockDriverState *bs)
{
}
static void vdi_flush(BlockDriverState *bs)
static int vdi_flush(BlockDriverState *bs)
{
logout("\n");
bdrv_flush(bs->file);
return bdrv_flush(bs->file);
}

View File

@ -61,7 +61,6 @@ typedef struct {
#define L2_CACHE_SIZE 16
typedef struct BDRVVmdkState {
BlockDriverState *hd;
int64_t l1_table_offset;
int64_t l1_backup_table_offset;
uint32_t *l1_table;
@ -823,9 +822,9 @@ static void vmdk_close(BlockDriverState *bs)
qemu_free(s->l2_cache);
}
static void vmdk_flush(BlockDriverState *bs)
static int vmdk_flush(BlockDriverState *bs)
{
bdrv_flush(bs->file);
return bdrv_flush(bs->file);
}

View File

@ -110,8 +110,6 @@ struct vhd_dyndisk_header {
};
typedef struct BDRVVPCState {
BlockDriverState *hd;
uint8_t footer_buf[HEADER_SIZE];
uint64_t free_data_block_offset;
int max_table_entries;
@ -439,6 +437,10 @@ static int vpc_write(BlockDriverState *bs, int64_t sector_num,
return 0;
}
static int vpc_flush(BlockDriverState *bs)
{
return bdrv_flush(bs->file);
}
/*
* Calculates the number of cylinders, heads and sectors per cylinder
@ -618,14 +620,15 @@ static QEMUOptionParameter vpc_create_options[] = {
};
static BlockDriver bdrv_vpc = {
.format_name = "vpc",
.instance_size = sizeof(BDRVVPCState),
.bdrv_probe = vpc_probe,
.bdrv_open = vpc_open,
.bdrv_read = vpc_read,
.bdrv_write = vpc_write,
.bdrv_close = vpc_close,
.bdrv_create = vpc_create,
.format_name = "vpc",
.instance_size = sizeof(BDRVVPCState),
.bdrv_probe = vpc_probe,
.bdrv_open = vpc_open,
.bdrv_read = vpc_read,
.bdrv_write = vpc_write,
.bdrv_flush = vpc_flush,
.bdrv_close = vpc_close,
.bdrv_create = vpc_create,
.create_options = vpc_create_options,
};

View File

@ -59,7 +59,7 @@ struct BlockDriver {
const uint8_t *buf, int nb_sectors);
void (*bdrv_close)(BlockDriverState *bs);
int (*bdrv_create)(const char *filename, QEMUOptionParameter *options);
void (*bdrv_flush)(BlockDriverState *bs);
int (*bdrv_flush)(BlockDriverState *bs);
int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum);
int (*bdrv_set_key)(BlockDriverState *bs, const char *key);

View File

@ -14,6 +14,8 @@
#include "qemu-option.h"
#include "qemu-config.h"
#include "sysemu.h"
#include "hw/qdev.h"
#include "block_int.h"
static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
@ -314,7 +316,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
on_write_error = BLOCK_ERR_STOP_ENOSPC;
if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
fprintf(stderr, "werror is no supported by this format\n");
fprintf(stderr, "werror is not supported by this format\n");
return NULL;
}
@ -326,8 +328,8 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
on_read_error = BLOCK_ERR_REPORT;
if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) {
fprintf(stderr, "rerror is no supported by this format\n");
if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI && type != IF_NONE) {
fprintf(stderr, "rerror is not supported by this format\n");
return NULL;
}
@ -597,3 +599,40 @@ int do_change_block(Monitor *mon, const char *device,
}
return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
}
int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
const char *id = qdict_get_str(qdict, "id");
BlockDriverState *bs;
BlockDriverState **ptr;
Property *prop;
bs = bdrv_find(id);
if (!bs) {
qerror_report(QERR_DEVICE_NOT_FOUND, id);
return -1;
}
/* quiesce block driver; prevent further io */
qemu_aio_flush();
bdrv_flush(bs);
bdrv_close(bs);
/* clean up guest state from pointing to host resource by
* finding and removing DeviceState "drive" property */
for (prop = bs->peer->info->props; prop && prop->name; prop++) {
if (prop->info->type == PROP_TYPE_DRIVE) {
ptr = qdev_get_prop_ptr(bs->peer, prop);
if ((*ptr) == bs) {
bdrv_detach(bs, bs->peer);
*ptr = NULL;
break;
}
}
}
/* clean up host side */
drive_uninit(drive_get_by_blockdev(bs));
return 0;
}

View File

@ -32,7 +32,7 @@ struct DriveInfo {
};
#define MAX_IDE_DEVS 2
#define MAX_SCSI_DEVS 7
#define MAX_SCSI_DEVS 255
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
int drive_get_max_bus(BlockInterfaceType type);
@ -51,5 +51,6 @@ int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data);
int do_block_set_passwd(Monitor *mon, const QDict *qdict, QObject **ret_data);
int do_change_block(Monitor *mon, const char *device,
const char *filename, const char *fmt);
int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
#endif

21
configure vendored
View File

@ -929,7 +929,7 @@ echo " --enable-docs enable documentation build"
echo " --disable-docs disable documentation build"
echo " --disable-vhost-net disable vhost-net acceleration support"
echo " --enable-vhost-net enable vhost-net acceleration support"
echo " --trace-backend=B Trace backend nop simple ust"
echo " --trace-backend=B Trace backend nop simple ust dtrace"
echo " --trace-file=NAME Full PATH,NAME of file to store traces"
echo " Default:trace-<pid>"
echo " --disable-spice disable spice"
@ -2193,6 +2193,22 @@ EOF
exit 1
fi
fi
##########################################
# For 'dtrace' backend, test if 'dtrace' command is present
if test "$trace_backend" = "dtrace"; then
if ! has 'dtrace' ; then
echo
echo "Error: dtrace command is not found in PATH $PATH"
echo
exit 1
fi
trace_backend_stap="no"
if has 'stap' ; then
trace_backend_stap="yes"
fi
fi
##########################################
# End of CC checks
# After here, no more $cc or $ld runs
@ -2633,6 +2649,9 @@ fi
if test "$trace_backend" = "simple"; then
trace_file="\"$trace_file-%u\""
fi
if test "$trace_backend" = "dtrace" -a "$trace_backend_stap" = "yes" ; then
echo "CONFIG_SYSTEMTAP_TRACE=y" >> $config_host_mak
fi
echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak
echo "TOOLS=$tools" >> $config_host_mak

View File

@ -1,7 +1,7 @@
# Default configuration for arm-softmmu
include pci.mak
CONFIG_GDBSTUB_XML=y
CONFIG_USB_OHCI=y
CONFIG_ISA_MMIO=y
CONFIG_NAND=y
CONFIG_ECC=y
@ -25,6 +25,5 @@ CONFIG_SSI_SD=y
CONFIG_LAN9118=y
CONFIG_SMC91C111=y
CONFIG_DS1338=y
CONFIG_VIRTIO_PCI=y
CONFIG_PFLASH_CFI01=y
CONFIG_PFLASH_CFI02=y

View File

@ -2,5 +2,4 @@
CONFIG_NAND=y
CONFIG_PTIMER=y
CONFIG_VIRTIO_PCI=y
CONFIG_PFLASH_CFI02=y

View File

@ -1,6 +1,6 @@
# Default configuration for i386-softmmu
CONFIG_USB_OHCI=y
include pci.mak
CONFIG_VGA_PCI=y
CONFIG_VGA_ISA=y
CONFIG_VMWARE_VGA=y
@ -9,7 +9,6 @@ CONFIG_PARALLEL=y
CONFIG_I8254=y
CONFIG_PCSPK=y
CONFIG_PCKBD=y
CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
CONFIG_APM=y
@ -22,4 +21,3 @@ CONFIG_IDE_PIIX=y
CONFIG_NE2000_ISA=y
CONFIG_PIIX_PCI=y
CONFIG_SOUND=y
CONFIG_VIRTIO_PCI=y

View File

@ -1,5 +1,5 @@
# Default configuration for m68k-softmmu
include pci.mak
CONFIG_GDBSTUB_XML=y
CONFIG_PTIMER=y
CONFIG_VIRTIO_PCI=y

View File

@ -1,5 +1,4 @@
# Default configuration for microblaze-softmmu
CONFIG_PTIMER=y
CONFIG_VIRTIO_PCI=y
CONFIG_PFLASH_CFI01=y

View File

@ -1,5 +1,6 @@
# Default configuration for mips-softmmu
include pci.mak
CONFIG_ISA_MMIO=y
CONFIG_ESP=y
CONFIG_VGA_PCI=y
@ -11,7 +12,6 @@ CONFIG_PARALLEL=y
CONFIG_I8254=y
CONFIG_PCSPK=y
CONFIG_PCKBD=y
CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
CONFIG_APM=y
@ -24,7 +24,6 @@ CONFIG_IDE_ISA=y
CONFIG_IDE_PIIX=y
CONFIG_NE2000_ISA=y
CONFIG_SOUND=y
CONFIG_VIRTIO_PCI=y
CONFIG_RC4030=y
CONFIG_DP8393X=y
CONFIG_DS1225Y=y

View File

@ -1,5 +1,6 @@
# Default configuration for mips64-softmmu
include pci.mak
CONFIG_ISA_MMIO=y
CONFIG_ESP=y
CONFIG_VGA_PCI=y
@ -11,7 +12,6 @@ CONFIG_PARALLEL=y
CONFIG_I8254=y
CONFIG_PCSPK=y
CONFIG_PCKBD=y
CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
CONFIG_APM=y
@ -24,7 +24,6 @@ CONFIG_IDE_ISA=y
CONFIG_IDE_PIIX=y
CONFIG_NE2000_ISA=y
CONFIG_SOUND=y
CONFIG_VIRTIO_PCI=y
CONFIG_RC4030=y
CONFIG_DP8393X=y
CONFIG_DS1225Y=y

View File

@ -1,5 +1,6 @@
# Default configuration for mips64el-softmmu
include pci.mak
CONFIG_ISA_MMIO=y
CONFIG_ESP=y
CONFIG_VGA_PCI=y
@ -11,7 +12,6 @@ CONFIG_PARALLEL=y
CONFIG_I8254=y
CONFIG_PCSPK=y
CONFIG_PCKBD=y
CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
CONFIG_APM=y
@ -25,7 +25,6 @@ CONFIG_IDE_PIIX=y
CONFIG_IDE_VIA=y
CONFIG_NE2000_ISA=y
CONFIG_SOUND=y
CONFIG_VIRTIO_PCI=y
CONFIG_RC4030=y
CONFIG_DP8393X=y
CONFIG_DS1225Y=y

View File

@ -1,5 +1,6 @@
# Default configuration for mipsel-softmmu
include pci.mak
CONFIG_ISA_MMIO=y
CONFIG_ESP=y
CONFIG_VGA_PCI=y
@ -11,7 +12,6 @@ CONFIG_PARALLEL=y
CONFIG_I8254=y
CONFIG_PCSPK=y
CONFIG_PCKBD=y
CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
CONFIG_APM=y
@ -24,7 +24,6 @@ CONFIG_IDE_ISA=y
CONFIG_IDE_PIIX=y
CONFIG_NE2000_ISA=y
CONFIG_SOUND=y
CONFIG_VIRTIO_PCI=y
CONFIG_RC4030=y
CONFIG_DP8393X=y
CONFIG_DS1225Y=y

12
default-configs/pci.mak Normal file
View File

@ -0,0 +1,12 @@
CONFIG_PCI=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO=y
CONFIG_USB_UHCI=y
CONFIG_USB_OHCI=y
CONFIG_NE2000_PCI=y
CONFIG_EEPRO100_PCI=y
CONFIG_PCNET_PCI=y
CONFIG_PCNET_COMMON=y
CONFIG_LSI_SCSI_PCI=y
CONFIG_RTL8139_PCI=y
CONFIG_E1000_PCI=y

View File

@ -1,7 +1,7 @@
# Default configuration for ppc-softmmu
include pci.mak
CONFIG_GDBSTUB_XML=y
CONFIG_USB_OHCI=y
CONFIG_ISA_MMIO=y
CONFIG_ESCC=y
CONFIG_M48T59=y
@ -31,7 +31,6 @@ CONFIG_IDE_CMD646=y
CONFIG_IDE_MACIO=y
CONFIG_NE2000_ISA=y
CONFIG_SOUND=y
CONFIG_VIRTIO_PCI=y
CONFIG_PFLASH_CFI01=y
CONFIG_PFLASH_CFI02=y
CONFIG_PTIMER=y

View File

@ -1,7 +1,7 @@
# Default configuration for ppc64-softmmu
include pci.mak
CONFIG_GDBSTUB_XML=y
CONFIG_USB_OHCI=y
CONFIG_ISA_MMIO=y
CONFIG_ESCC=y
CONFIG_M48T59=y
@ -31,7 +31,6 @@ CONFIG_IDE_CMD646=y
CONFIG_IDE_MACIO=y
CONFIG_NE2000_ISA=y
CONFIG_SOUND=y
CONFIG_VIRTIO_PCI=y
CONFIG_PFLASH_CFI01=y
CONFIG_PFLASH_CFI02=y
CONFIG_PTIMER=y

View File

@ -1,7 +1,7 @@
# Default configuration for ppcemb-softmmu
include pci.mak
CONFIG_GDBSTUB_XML=y
CONFIG_USB_OHCI=y
CONFIG_ISA_MMIO=y
CONFIG_ESCC=y
CONFIG_M48T59=y
@ -31,7 +31,6 @@ CONFIG_IDE_CMD646=y
CONFIG_IDE_MACIO=y
CONFIG_NE2000_ISA=y
CONFIG_SOUND=y
CONFIG_VIRTIO_PCI=y
CONFIG_PFLASH_CFI01=y
CONFIG_PFLASH_CFI02=y
CONFIG_PTIMER=y

View File

@ -0,0 +1 @@
CONFIG_VIRTIO=y

View File

@ -1,9 +1,8 @@
# Default configuration for sh4-softmmu
CONFIG_USB_OHCI=y
include pci.mak
CONFIG_SERIAL=y
CONFIG_PTIMER=y
CONFIG_VIRTIO_PCI=y
CONFIG_IDE_CORE=y
CONFIG_PFLASH_CFI02=y
CONFIG_ISA_MMIO=y

View File

@ -1,9 +1,8 @@
# Default configuration for sh4eb-softmmu
CONFIG_USB_OHCI=y
include pci.mak
CONFIG_SERIAL=y
CONFIG_PTIMER=y
CONFIG_VIRTIO_PCI=y
CONFIG_IDE_CORE=y
CONFIG_PFLASH_CFI02=y
CONFIG_ISA_MMIO=y

View File

@ -6,5 +6,5 @@ CONFIG_ESCC=y
CONFIG_M48T59=y
CONFIG_PTIMER=y
CONFIG_FDC=y
CONFIG_VIRTIO_PCI=y
CONFIG_EMPTY_SLOT=y
CONFIG_PCNET_COMMON=y

View File

@ -1,5 +1,6 @@
# Default configuration for sparc64-softmmu
include pci.mak
CONFIG_ISA_MMIO=y
CONFIG_M48T59=y
CONFIG_PTIMER=y
@ -13,4 +14,3 @@ CONFIG_IDE_QDEV=y
CONFIG_IDE_PCI=y
CONFIG_IDE_ISA=y
CONFIG_IDE_CMD646=y
CONFIG_VIRTIO_PCI=y

View File

@ -1,6 +1,6 @@
# Default configuration for x86_64-softmmu
CONFIG_USB_OHCI=y
include pci.mak
CONFIG_VGA_PCI=y
CONFIG_VGA_ISA=y
CONFIG_VMWARE_VGA=y
@ -9,7 +9,6 @@ CONFIG_PARALLEL=y
CONFIG_I8254=y
CONFIG_PCSPK=y
CONFIG_PCKBD=y
CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
CONFIG_APM=y
@ -22,4 +21,3 @@ CONFIG_IDE_PIIX=y
CONFIG_NE2000_ISA=y
CONFIG_PIIX_PCI=y
CONFIG_SOUND=y
CONFIG_VIRTIO_PCI=y

View File

@ -65,6 +65,24 @@ STEXI
@item eject [-f] @var{device}
@findex eject
Eject a removable medium (use -f to force it).
ETEXI
{
.name = "drive_del",
.args_type = "id:s",
.params = "device",
.help = "remove host block device",
.user_print = monitor_user_noop,
.mhandler.cmd_new = do_drive_del,
},
STEXI
@item drive_del @var{device}
@findex drive_del
Remove host block device. The result is that guest generated IO is no longer
submitted against the host device underlying the disk. Once a drive has
been deleted, the QEMU Block layer returns -EIO which results in IO
errors in the guest for applications that are reading/writing to the device.
ETEXI
{

View File

@ -52,6 +52,7 @@ struct pci_status {
typedef struct PIIX4PMState {
PCIDevice dev;
IORange ioport;
uint16_t pmsts;
uint16_t pmen;
uint16_t pmcntrl;
@ -128,10 +129,16 @@ static void pm_tmr_timer(void *opaque)
pm_update_sci(s);
}
static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width,
uint64_t val)
{
PIIX4PMState *s = opaque;
addr &= 0x3f;
PIIX4PMState *s = container_of(ioport, PIIX4PMState, ioport);
if (width != 2) {
PIIX4_DPRINTF("PM write port=0x%04x width=%d val=0x%08x\n",
(unsigned)addr, width, (unsigned)val);
}
switch(addr) {
case 0x00:
{
@ -184,12 +191,12 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
PIIX4_DPRINTF("PM writew port=0x%04x val=0x%04x\n", addr, val);
}
static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width,
uint64_t *data)
{
PIIX4PMState *s = opaque;
PIIX4PMState *s = container_of(ioport, PIIX4PMState, ioport);
uint32_t val;
addr &= 0x3f;
switch(addr) {
case 0x00:
val = get_pmsts(s);
@ -200,27 +207,6 @@ static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
case 0x04:
val = s->pmcntrl;
break;
default:
val = 0;
break;
}
PIIX4_DPRINTF("PM readw port=0x%04x val=0x%04x\n", addr, val);
return val;
}
static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
{
// PIIX4PMState *s = opaque;
PIIX4_DPRINTF("PM writel port=0x%04x val=0x%08x\n", addr & 0x3f, val);
}
static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
{
PIIX4PMState *s = opaque;
uint32_t val;
addr &= 0x3f;
switch(addr) {
case 0x08:
val = get_pmtmr(s);
break;
@ -228,10 +214,15 @@ static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
val = 0;
break;
}
PIIX4_DPRINTF("PM readl port=0x%04x val=0x%08x\n", addr, val);
return val;
PIIX4_DPRINTF("PM readw port=0x%04x val=0x%04x\n", addr, val);
*data = val;
}
static const IORangeOps pm_iorange_ops = {
.read = pm_ioport_read,
.write = pm_ioport_write,
};
static void apm_ctrl_changed(uint32_t val, void *arg)
{
PIIX4PMState *s = arg;
@ -265,10 +256,8 @@ static void pm_io_space_update(PIIX4PMState *s)
/* XXX: need to improve memory and ioport allocation */
PIIX4_DPRINTF("PM: mapping to 0x%x\n", pm_io_base);
register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s);
register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s);
register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s);
register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s);
iorange_init(&s->ioport, &pm_iorange_ops, pm_io_base, 64);
ioport_register(&s->ioport);
}
}

View File

@ -437,6 +437,8 @@ static int apic_find_dest(uint8_t dest)
apic = local_apics[i];
if (apic && apic->id == dest)
return i;
if (!apic)
break;
}
return -1;
@ -472,6 +474,8 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
set_bit(deliver_bitmask, i);
}
}
} else {
break;
}
}
}

View File

@ -447,9 +447,10 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
// data descriptor
tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8;
tp->cptse = ( txd_lower & E1000_TXD_CMD_TSE ) ? 1 : 0;
} else
} else {
// legacy descriptor
tp->cptse = 0;
}
if (vlan_enabled(s) && is_vlan_txd(txd_lower) &&
(tp->cptse || txd_lower & E1000_TXD_CMD_EOP)) {
@ -685,8 +686,9 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
(void *)(buf + vlan_offset), size);
desc.length = cpu_to_le16(size + fcs_len(s));
desc.status |= E1000_RXD_STAT_EOP|E1000_RXD_STAT_IXSM;
} else // as per intel docs; skip descriptors with null buf addr
} else { // as per intel docs; skip descriptors with null buf addr
DBGOUT(RX, "Null RX descriptor!!\n");
}
cpu_physical_memory_write(base, (void *)&desc, sizeof(desc));
if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN])
@ -858,13 +860,14 @@ e1000_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
if (index < NWRITEOPS && macreg_writeops[index])
if (index < NWRITEOPS && macreg_writeops[index]) {
macreg_writeops[index](s, index, val);
else if (index < NREADOPS && macreg_readops[index])
} else if (index < NREADOPS && macreg_readops[index]) {
DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04x\n", index<<2, val);
else
} else {
DBGOUT(UNKNOWN, "MMIO unknown write addr=0x%08x,val=0x%08x\n",
index<<2, val);
}
}
static void

View File

@ -808,6 +808,28 @@ static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc)
return 0;
}
static int hda_audio_exit(HDACodecDevice *hda)
{
HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
HDAAudioStream *st;
int i;
dprint(a, 1, "%s\n", __FUNCTION__);
for (i = 0; i < ARRAY_SIZE(a->st); i++) {
st = a->st + i;
if (st->node == NULL) {
continue;
}
if (st->output) {
AUD_close_out(&a->card, st->voice.out);
} else {
AUD_close_in(&a->card, st->voice.in);
}
}
AUD_remove_card(&a->card);
return 0;
}
static int hda_audio_post_load(void *opaque, int version)
{
HDAAudioState *a = opaque;
@ -879,6 +901,7 @@ static HDACodecDeviceInfo hda_audio_info_output = {
.qdev.vmsd = &vmstate_hda_audio,
.qdev.props = hda_audio_properties,
.init = hda_audio_init_output,
.exit = hda_audio_exit,
.command = hda_audio_command,
.stream = hda_audio_stream,
};
@ -890,6 +913,7 @@ static HDACodecDeviceInfo hda_audio_info_duplex = {
.qdev.vmsd = &vmstate_hda_audio,
.qdev.props = hda_audio_properties,
.init = hda_audio_init_duplex,
.exit = hda_audio_exit,
.command = hda_audio_command,
.stream = hda_audio_stream,
};

View File

@ -179,12 +179,8 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
register_ioport_read(addr, 4, 1, bmdma_readb_1, d);
}
register_ioport_write(addr + 4, 4, 1, bmdma_addr_writeb, bm);
register_ioport_read(addr + 4, 4, 1, bmdma_addr_readb, bm);
register_ioport_write(addr + 4, 4, 2, bmdma_addr_writew, bm);
register_ioport_read(addr + 4, 4, 2, bmdma_addr_readw, bm);
register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm);
register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm);
iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4);
ioport_register(&bm->addr_ioport);
addr += 8;
}
}

View File

@ -473,11 +473,21 @@ static void dma_buf_commit(IDEState *s, int is_write)
qemu_sglist_destroy(&s->sg);
}
static void ide_dma_set_inactive(BMDMAState *bm)
{
bm->status &= ~BM_STATUS_DMAING;
bm->dma_cb = NULL;
bm->unit = -1;
bm->aiocb = NULL;
}
void ide_dma_error(IDEState *s)
{
ide_transfer_stop(s);
s->error = ABRT_ERR;
s->status = READY_STAT | ERR_STAT;
ide_dma_set_inactive(s->bus->bmdma);
s->bus->bmdma->status |= BM_STATUS_INT;
ide_set_irq(s->bus);
}
@ -587,11 +597,8 @@ static void ide_read_dma_cb(void *opaque, int ret)
s->status = READY_STAT | SEEK_STAT;
ide_set_irq(s->bus);
eot:
bm->status &= ~BM_STATUS_DMAING;
bm->status |= BM_STATUS_INT;
bm->dma_cb = NULL;
bm->unit = -1;
bm->aiocb = NULL;
ide_dma_set_inactive(bm);
return;
}
@ -733,11 +740,8 @@ static void ide_write_dma_cb(void *opaque, int ret)
s->status = READY_STAT | SEEK_STAT;
ide_set_irq(s->bus);
eot:
bm->status &= ~BM_STATUS_DMAING;
bm->status |= BM_STATUS_INT;
bm->dma_cb = NULL;
bm->unit = -1;
bm->aiocb = NULL;
ide_dma_set_inactive(bm);
return;
}
@ -811,10 +815,16 @@ static void ide_flush_cb(void *opaque, int ret)
static void ide_flush_cache(IDEState *s)
{
if (s->bs) {
bdrv_aio_flush(s->bs, ide_flush_cb, s);
} else {
BlockDriverAIOCB *acb;
if (s->bs == NULL) {
ide_flush_cb(s, 0);
return;
}
acb = bdrv_aio_flush(s->bs, ide_flush_cb, s);
if (acb == NULL) {
ide_flush_cb(s, -EIO);
}
}
@ -1055,11 +1065,8 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
ide_set_irq(s->bus);
eot:
bm->status &= ~BM_STATUS_DMAING;
bm->status |= BM_STATUS_INT;
bm->dma_cb = NULL;
bm->unit = -1;
bm->aiocb = NULL;
ide_dma_set_inactive(bm);
return;
}
@ -2948,12 +2955,10 @@ void ide_dma_cancel(BMDMAState *bm)
printf("aio_cancel\n");
#endif
bdrv_aio_cancel(bm->aiocb);
bm->aiocb = NULL;
}
bm->status &= ~BM_STATUS_DMAING;
/* cancel DMA request */
bm->unit = -1;
bm->dma_cb = NULL;
ide_dma_set_inactive(bm);
}
}

View File

@ -8,6 +8,7 @@
*/
#include <hw/ide.h>
#include "block_int.h"
#include "iorange.h"
/* debug IDE devices */
//#define DEBUG_IDE
@ -496,6 +497,7 @@ struct BMDMAState {
QEMUIOVector qiov;
int64_t sector_num;
uint32_t nsector;
IORange addr_ioport;
QEMUBH *bh;
};

View File

@ -39,106 +39,75 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
#ifdef DEBUG_IDE
printf("%s: 0x%08x\n", __func__, val);
#endif
if (!(val & BM_CMD_START)) {
/*
* We can't cancel Scatter Gather DMA in the middle of the
* operation or a partial (not full) DMA transfer would reach
* the storage so we wait for completion instead (we beahve
* like if the DMA was completed by the time the guest trying
* to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
* set).
*
* In the future we'll be able to safely cancel the I/O if the
* whole DMA operation will be submitted to disk with a single
* aio operation with preadv/pwritev.
*/
if (bm->aiocb) {
qemu_aio_flush();
/* Ignore writes to SSBM if it keeps the old value */
if ((val & BM_CMD_START) != (bm->cmd & BM_CMD_START)) {
if (!(val & BM_CMD_START)) {
/*
* We can't cancel Scatter Gather DMA in the middle of the
* operation or a partial (not full) DMA transfer would reach
* the storage so we wait for completion instead (we beahve
* like if the DMA was completed by the time the guest trying
* to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
* set).
*
* In the future we'll be able to safely cancel the I/O if the
* whole DMA operation will be submitted to disk with a single
* aio operation with preadv/pwritev.
*/
if (bm->aiocb) {
qemu_aio_flush();
#ifdef DEBUG_IDE
if (bm->aiocb)
printf("ide_dma_cancel: aiocb still pending");
if (bm->status & BM_STATUS_DMAING)
printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
if (bm->aiocb)
printf("ide_dma_cancel: aiocb still pending");
if (bm->status & BM_STATUS_DMAING)
printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
#endif
}
} else {
bm->cur_addr = bm->addr;
if (!(bm->status & BM_STATUS_DMAING)) {
bm->status |= BM_STATUS_DMAING;
/* start dma transfer if possible */
if (bm->dma_cb)
bm->dma_cb(bm, 0);
}
}
bm->cmd = val & 0x09;
} else {
if (!(bm->status & BM_STATUS_DMAING)) {
bm->status |= BM_STATUS_DMAING;
/* start dma transfer if possible */
if (bm->dma_cb)
bm->dma_cb(bm, 0);
}
bm->cmd = val & 0x09;
}
bm->cmd = val & 0x09;
}
uint32_t bmdma_addr_readb(void *opaque, uint32_t addr)
static void bmdma_addr_read(IORange *ioport, uint64_t addr,
unsigned width, uint64_t *data)
{
BMDMAState *bm = opaque;
uint32_t val;
val = (bm->addr >> ((addr & 3) * 8)) & 0xff;
BMDMAState *bm = container_of(ioport, BMDMAState, addr_ioport);
uint32_t mask = (1ULL << (width * 8)) - 1;
*data = (bm->addr >> (addr * 8)) & mask;
#ifdef DEBUG_IDE
printf("%s: 0x%08x\n", __func__, val);
printf("%s: 0x%08x\n", __func__, (unsigned)*data);
#endif
return val;
}
void bmdma_addr_writeb(void *opaque, uint32_t addr, uint32_t val)
static void bmdma_addr_write(IORange *ioport, uint64_t addr,
unsigned width, uint64_t data)
{
BMDMAState *bm = opaque;
int shift = (addr & 3) * 8;
BMDMAState *bm = container_of(ioport, BMDMAState, addr_ioport);
int shift = addr * 8;
uint32_t mask = (1ULL << (width * 8)) - 1;
#ifdef DEBUG_IDE
printf("%s: 0x%08x\n", __func__, val);
printf("%s: 0x%08x\n", __func__, (unsigned)data);
#endif
bm->addr &= ~(0xFF << shift);
bm->addr |= ((val & 0xFF) << shift) & ~3;
bm->cur_addr = bm->addr;
bm->addr &= ~(mask << shift);
bm->addr |= ((data & mask) << shift) & ~3;
}
uint32_t bmdma_addr_readw(void *opaque, uint32_t addr)
{
BMDMAState *bm = opaque;
uint32_t val;
val = (bm->addr >> ((addr & 3) * 8)) & 0xffff;
#ifdef DEBUG_IDE
printf("%s: 0x%08x\n", __func__, val);
#endif
return val;
}
void bmdma_addr_writew(void *opaque, uint32_t addr, uint32_t val)
{
BMDMAState *bm = opaque;
int shift = (addr & 3) * 8;
#ifdef DEBUG_IDE
printf("%s: 0x%08x\n", __func__, val);
#endif
bm->addr &= ~(0xFFFF << shift);
bm->addr |= ((val & 0xFFFF) << shift) & ~3;
bm->cur_addr = bm->addr;
}
uint32_t bmdma_addr_readl(void *opaque, uint32_t addr)
{
BMDMAState *bm = opaque;
uint32_t val;
val = bm->addr;
#ifdef DEBUG_IDE
printf("%s: 0x%08x\n", __func__, val);
#endif
return val;
}
void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val)
{
BMDMAState *bm = opaque;
#ifdef DEBUG_IDE
printf("%s: 0x%08x\n", __func__, val);
#endif
bm->addr = val & ~3;
bm->cur_addr = bm->addr;
}
const IORangeOps bmdma_addr_ioport_ops = {
.read = bmdma_addr_read,
.write = bmdma_addr_write,
};
static bool ide_bmdma_current_needed(void *opaque)
{

View File

@ -11,12 +11,7 @@ typedef struct PCIIDEState {
} PCIIDEState;
void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val);
uint32_t bmdma_addr_readb(void *opaque, uint32_t addr);
void bmdma_addr_writeb(void *opaque, uint32_t addr, uint32_t val);
uint32_t bmdma_addr_readw(void *opaque, uint32_t addr);
void bmdma_addr_writew(void *opaque, uint32_t addr, uint32_t val);
uint32_t bmdma_addr_readl(void *opaque, uint32_t addr);
void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val);
extern const IORangeOps bmdma_addr_ioport_ops;
void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table);
extern const VMStateDescription vmstate_ide_pci;

View File

@ -85,12 +85,8 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm);
register_ioport_read(addr, 4, 1, bmdma_readb, bm);
register_ioport_write(addr + 4, 4, 1, bmdma_addr_writeb, bm);
register_ioport_read(addr + 4, 4, 1, bmdma_addr_readb, bm);
register_ioport_write(addr + 4, 4, 2, bmdma_addr_writew, bm);
register_ioport_read(addr + 4, 4, 2, bmdma_addr_readw, bm);
register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm);
register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm);
iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4);
ioport_register(&bm->addr_ioport);
addr += 8;
}
}

View File

@ -87,12 +87,8 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm);
register_ioport_read(addr, 4, 1, bmdma_readb, bm);
register_ioport_write(addr + 4, 4, 1, bmdma_addr_writeb, bm);
register_ioport_read(addr + 4, 4, 1, bmdma_addr_readb, bm);
register_ioport_write(addr + 4, 4, 2, bmdma_addr_writew, bm);
register_ioport_read(addr + 4, 4, 2, bmdma_addr_readw, bm);
register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm);
register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm);
iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4);
ioport_register(&bm->addr_ioport);
addr += 8;
}
}

View File

@ -19,6 +19,7 @@
#include "hw.h"
#include "pci.h"
#include "msi.h"
#include "qemu-timer.h"
#include "audiodev.h"
#include "intel-hda.h"
@ -55,15 +56,27 @@ static int hda_codec_dev_init(DeviceState *qdev, DeviceInfo *base)
if (dev->cad == -1) {
dev->cad = bus->next_cad;
}
if (dev->cad > 15)
if (dev->cad >= 15) {
return -1;
}
bus->next_cad = dev->cad + 1;
return info->init(dev);
}
static int hda_codec_dev_exit(DeviceState *qdev)
{
HDACodecDevice *dev = DO_UPCAST(HDACodecDevice, qdev, qdev);
if (dev->info->exit) {
dev->info->exit(dev);
}
return 0;
}
void hda_codec_register(HDACodecDeviceInfo *info)
{
info->qdev.init = hda_codec_dev_init;
info->qdev.exit = hda_codec_dev_exit;
info->qdev.bus_info = &hda_codec_bus_info;
qdev_register(&info->qdev);
}
@ -177,6 +190,7 @@ struct IntelHDAState {
/* properties */
uint32_t debug;
uint32_t msi;
};
struct IntelHDAReg {
@ -235,7 +249,7 @@ static void intel_hda_update_int_sts(IntelHDAState *d)
if (d->rirb_sts & ICH6_RBSTS_OVERRUN) {
sts |= (1 << 30);
}
if (d->state_sts) {
if (d->state_sts & d->wake_en) {
sts |= (1 << 30);
}
@ -257,6 +271,7 @@ static void intel_hda_update_int_sts(IntelHDAState *d)
static void intel_hda_update_irq(IntelHDAState *d)
{
int msi = d->msi && msi_enabled(&d->pci);
int level;
intel_hda_update_int_sts(d);
@ -265,8 +280,15 @@ static void intel_hda_update_irq(IntelHDAState *d)
} else {
level = 0;
}
dprint(d, 2, "%s: level %d\n", __FUNCTION__, level);
qemu_set_irq(d->pci.irq[0], level);
dprint(d, 2, "%s: level %d [%s]\n", __FUNCTION__,
level, msi ? "msi" : "intx");
if (msi) {
if (level) {
msi_notify(&d->pci, 0);
}
} else {
qemu_set_irq(d->pci.irq[0], level);
}
}
static int intel_hda_send_command(IntelHDAState *d, uint32_t verb)
@ -497,6 +519,11 @@ static void intel_hda_set_g_ctl(IntelHDAState *d, const IntelHDAReg *reg, uint32
}
}
static void intel_hda_set_wake_en(IntelHDAState *d, const IntelHDAReg *reg, uint32_t old)
{
intel_hda_update_irq(d);
}
static void intel_hda_set_state_sts(IntelHDAState *d, const IntelHDAReg *reg, uint32_t old)
{
intel_hda_update_irq(d);
@ -617,13 +644,15 @@ static const struct IntelHDAReg regtab[] = {
[ ICH6_REG_WAKEEN ] = {
.name = "WAKEEN",
.size = 2,
.wmask = 0x7fff,
.offset = offsetof(IntelHDAState, wake_en),
.whandler = intel_hda_set_wake_en,
},
[ ICH6_REG_STATESTS ] = {
.name = "STATESTS",
.size = 2,
.wmask = 0x3fff,
.wclear = 0x3fff,
.wmask = 0x7fff,
.wclear = 0x7fff,
.offset = offsetof(IntelHDAState, state_sts),
.whandler = intel_hda_set_state_sts,
},
@ -1130,6 +1159,9 @@ static int intel_hda_init(PCIDevice *pci)
intel_hda_mmio_write, d);
pci_register_bar(&d->pci, 0, 0x4000, PCI_BASE_ADDRESS_SPACE_MEMORY,
intel_hda_map);
if (d->msi) {
msi_init(&d->pci, 0x50, 1, true, false);
}
hda_codec_bus_init(&d->pci.qdev, &d->codecs,
intel_hda_response, intel_hda_xfer);
@ -1137,6 +1169,28 @@ static int intel_hda_init(PCIDevice *pci)
return 0;
}
static int intel_hda_exit(PCIDevice *pci)
{
IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci);
if (d->msi) {
msi_uninit(&d->pci);
}
cpu_unregister_io_memory(d->mmio_addr);
return 0;
}
static void intel_hda_write_config(PCIDevice *pci, uint32_t addr,
uint32_t val, int len)
{
IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci);
pci_default_write_config(pci, addr, val, len);
if (d->msi) {
msi_write_config(pci, addr, val, len);
}
}
static int intel_hda_post_load(void *opaque, int version)
{
IntelHDAState* d = opaque;
@ -1219,8 +1273,11 @@ static PCIDeviceInfo intel_hda_info = {
.qdev.vmsd = &vmstate_intel_hda,
.qdev.reset = intel_hda_reset,
.init = intel_hda_init,
.exit = intel_hda_exit,
.config_write = intel_hda_write_config,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("debug", IntelHDAState, debug, 0),
DEFINE_PROP_UINT32("msi", IntelHDAState, msi, 1),
DEFINE_PROP_END_OF_LIST(),
}
};

View File

@ -32,6 +32,7 @@ struct HDACodecDevice {
struct HDACodecDeviceInfo {
DeviceInfo qdev;
int (*init)(HDACodecDevice *dev);
int (*exit)(HDACodecDevice *dev);
void (*command)(HDACodecDevice *dev, uint32_t nid, uint32_t data);
void (*stream)(HDACodecDevice *dev, uint32_t stnr, bool running);
};

View File

@ -977,7 +977,7 @@ void mips_malta_init (ram_addr_t ram_size,
} else if (vmsvga_enabled) {
pci_vmsvga_init(pci_bus);
} else if (std_vga_enabled) {
pci_vga_init(pci_bus, 0, 0);
pci_vga_init(pci_bus);
}
}

View File

@ -171,6 +171,12 @@ int load_multiboot(void *fw_cfg,
uint64_t elf_low, elf_high;
int kernel_size;
fclose(f);
if (((struct elf64_hdr*)header)->e_machine == EM_X86_64) {
fprintf(stderr, "Cannot load x86-64 image, give a 32bit one.\n");
exit(1);
}
kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
&elf_low, &elf_high, 0, ELF_MACHINE, 0);
if (kernel_size < 0) {

24
hw/pc.c
View File

@ -75,12 +75,12 @@ struct e820_entry {
uint64_t address;
uint64_t length;
uint32_t type;
};
} __attribute((__packed__, __aligned__(4)));
struct e820_table {
uint32_t count;
struct e820_entry entry[E820_NR_ENTRIES];
};
} __attribute((__packed__, __aligned__(4)));
static struct e820_table e820_table;
@ -430,8 +430,8 @@ static void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val)
/* Bochs BIOS messages */
case 0x400:
case 0x401:
fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val);
exit(1);
/* used to be panic, now unused */
break;
case 0x402:
case 0x403:
#ifdef DEBUG_BIOS
@ -467,19 +467,19 @@ static void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val)
int e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
{
int index = e820_table.count;
int index = le32_to_cpu(e820_table.count);
struct e820_entry *entry;
if (index >= E820_NR_ENTRIES)
return -EBUSY;
entry = &e820_table.entry[index];
entry = &e820_table.entry[index++];
entry->address = address;
entry->length = length;
entry->type = type;
entry->address = cpu_to_le64(address);
entry->length = cpu_to_le64(length);
entry->type = cpu_to_le32(type);
e820_table.count++;
return e820_table.count;
e820_table.count = cpu_to_le32(index);
return index;
}
static void *bochs_bios_init(void)
@ -993,7 +993,7 @@ void pc_vga_init(PCIBus *pci_bus)
fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
} else if (std_vga_enabled) {
if (pci_bus) {
pci_vga_init(pci_bus, 0, 0);
pci_vga_init(pci_bus);
} else {
isa_vga_init();
}

View File

@ -154,8 +154,7 @@ enum vga_retrace_method {
extern enum vga_retrace_method vga_retrace_method;
int isa_vga_init(void);
int pci_vga_init(PCIBus *bus,
unsigned long vga_bios_offset, int vga_bios_size);
int pci_vga_init(PCIBus *bus);
int isa_vga_mm_init(target_phys_addr_t vram_base,
target_phys_addr_t ctrl_base, int it_shift);

View File

@ -212,7 +212,7 @@ static void pc_init_isa(ram_addr_t ram_size,
}
static QEMUMachine pc_machine = {
.name = "pc-0.13",
.name = "pc-0.14",
.alias = "pc",
.desc = "Standard PC",
.init = pc_init_pci,
@ -220,6 +220,29 @@ static QEMUMachine pc_machine = {
.is_default = 1,
};
static QEMUMachine pc_machine_v0_13 = {
.name = "pc-0.13",
.desc = "Standard PC",
.init = pc_init_pci,
.max_cpus = 255,
.compat_props = (GlobalProperty[]) {
{
.driver = "virtio-9p-pci",
.property = "vectors",
.value = stringify(0),
},{
.driver = "VGA",
.property = "rombar",
.value = stringify(0),
},{
.driver = "vmware-svga",
.property = "rombar",
.value = stringify(0),
},
{ /* end of list */ }
},
};
static QEMUMachine pc_machine_v0_12 = {
.name = "pc-0.12",
.desc = "Standard PC",
@ -234,6 +257,14 @@ static QEMUMachine pc_machine_v0_12 = {
.driver = "virtio-serial-pci",
.property = "vectors",
.value = stringify(0),
},{
.driver = "VGA",
.property = "rombar",
.value = stringify(0),
},{
.driver = "vmware-svga",
.property = "rombar",
.value = stringify(0),
},
{ /* end of list */ }
}
@ -331,6 +362,7 @@ static QEMUMachine isapc_machine = {
static void pc_machine_init(void)
{
qemu_register_machine(&pc_machine);
qemu_register_machine(&pc_machine_v0_13);
qemu_register_machine(&pc_machine_v0_12);
qemu_register_machine(&pc_machine_v0_11);
qemu_register_machine(&pc_machine_v0_10);

345
hw/pcnet-pci.c Normal file
View File

@ -0,0 +1,345 @@
/*
* QEMU AMD PC-Net II (Am79C970A) PCI emulation
*
* Copyright (c) 2004 Antony T Curtis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/* This software was written to be compatible with the specification:
* AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet
* AMD Publication# 19436 Rev:E Amendment/0 Issue Date: June 2000
*/
#include "pci.h"
#include "net.h"
#include "loader.h"
#include "qemu-timer.h"
#include "pcnet.h"
//#define PCNET_DEBUG
//#define PCNET_DEBUG_IO
//#define PCNET_DEBUG_BCR
//#define PCNET_DEBUG_CSR
//#define PCNET_DEBUG_RMD
//#define PCNET_DEBUG_TMD
//#define PCNET_DEBUG_MATCH
typedef struct {
PCIDevice pci_dev;
PCNetState state;
} PCIPCNetState;
static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
{
PCNetState *s = opaque;
#ifdef PCNET_DEBUG
printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);
#endif
/* Check APROMWE bit to enable write access */
if (pcnet_bcr_readw(s,2) & 0x100)
s->prom[addr & 15] = val;
}
static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
{
PCNetState *s = opaque;
uint32_t val = s->prom[addr & 15];
#ifdef PCNET_DEBUG
printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);
#endif
return val;
}
static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
PCNetState *d = &DO_UPCAST(PCIPCNetState, pci_dev, pci_dev)->state;
#ifdef PCNET_DEBUG_IO
printf("pcnet_ioport_map addr=0x%04"FMT_PCIBUS" size=0x%04"FMT_PCIBUS"\n",
addr, size);
#endif
register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d);
register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d);
register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d);
register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d);
register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d);
}
static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
PCNetState *d = opaque;
#ifdef PCNET_DEBUG_IO
printf("pcnet_mmio_writeb addr=0x" TARGET_FMT_plx" val=0x%02x\n", addr,
val);
#endif
if (!(addr & 0x10))
pcnet_aprom_writeb(d, addr & 0x0f, val);
}
static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr)
{
PCNetState *d = opaque;
uint32_t val = -1;
if (!(addr & 0x10))
val = pcnet_aprom_readb(d, addr & 0x0f);
#ifdef PCNET_DEBUG_IO
printf("pcnet_mmio_readb addr=0x" TARGET_FMT_plx " val=0x%02x\n", addr,
val & 0xff);
#endif
return val;
}
static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
{
PCNetState *d = opaque;
#ifdef PCNET_DEBUG_IO
printf("pcnet_mmio_writew addr=0x" TARGET_FMT_plx " val=0x%04x\n", addr,
val);
#endif
if (addr & 0x10)
pcnet_ioport_writew(d, addr & 0x0f, val);
else {
addr &= 0x0f;
pcnet_aprom_writeb(d, addr, val & 0xff);
pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
}
}
static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr)
{
PCNetState *d = opaque;
uint32_t val = -1;
if (addr & 0x10)
val = pcnet_ioport_readw(d, addr & 0x0f);
else {
addr &= 0x0f;
val = pcnet_aprom_readb(d, addr+1);
val <<= 8;
val |= pcnet_aprom_readb(d, addr);
}
#ifdef PCNET_DEBUG_IO
printf("pcnet_mmio_readw addr=0x" TARGET_FMT_plx" val = 0x%04x\n", addr,
val & 0xffff);
#endif
return val;
}
static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
PCNetState *d = opaque;
#ifdef PCNET_DEBUG_IO
printf("pcnet_mmio_writel addr=0x" TARGET_FMT_plx" val=0x%08x\n", addr,
val);
#endif
if (addr & 0x10)
pcnet_ioport_writel(d, addr & 0x0f, val);
else {
addr &= 0x0f;
pcnet_aprom_writeb(d, addr, val & 0xff);
pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16);
pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24);
}
}
static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr)
{
PCNetState *d = opaque;
uint32_t val;
if (addr & 0x10)
val = pcnet_ioport_readl(d, addr & 0x0f);
else {
addr &= 0x0f;
val = pcnet_aprom_readb(d, addr+3);
val <<= 8;
val |= pcnet_aprom_readb(d, addr+2);
val <<= 8;
val |= pcnet_aprom_readb(d, addr+1);
val <<= 8;
val |= pcnet_aprom_readb(d, addr);
}
#ifdef PCNET_DEBUG_IO
printf("pcnet_mmio_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr,
val);
#endif
return val;
}
static const VMStateDescription vmstate_pci_pcnet = {
.name = "pcnet",
.version_id = 3,
.minimum_version_id = 2,
.minimum_version_id_old = 2,
.fields = (VMStateField []) {
VMSTATE_PCI_DEVICE(pci_dev, PCIPCNetState),
VMSTATE_STRUCT(state, PCIPCNetState, 0, vmstate_pcnet, PCNetState),
VMSTATE_END_OF_LIST()
}
};
/* PCI interface */
static CPUWriteMemoryFunc * const pcnet_mmio_write[] = {
&pcnet_mmio_writeb,
&pcnet_mmio_writew,
&pcnet_mmio_writel
};
static CPUReadMemoryFunc * const pcnet_mmio_read[] = {
&pcnet_mmio_readb,
&pcnet_mmio_readw,
&pcnet_mmio_readl
};
static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
#ifdef PCNET_DEBUG_IO
printf("pcnet_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n",
addr, size);
#endif
cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->state.mmio_index);
}
static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
uint8_t *buf, int len, int do_bswap)
{
cpu_physical_memory_write(addr, buf, len);
}
static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr,
uint8_t *buf, int len, int do_bswap)
{
cpu_physical_memory_read(addr, buf, len);
}
static void pci_pcnet_cleanup(VLANClientState *nc)
{
PCNetState *d = DO_UPCAST(NICState, nc, nc)->opaque;
pcnet_common_cleanup(d);
}
static int pci_pcnet_uninit(PCIDevice *dev)
{
PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, dev);
cpu_unregister_io_memory(d->state.mmio_index);
qemu_del_timer(d->state.poll_timer);
qemu_free_timer(d->state.poll_timer);
qemu_del_vlan_client(&d->state.nic->nc);
return 0;
}
static NetClientInfo net_pci_pcnet_info = {
.type = NET_CLIENT_TYPE_NIC,
.size = sizeof(NICState),
.can_receive = pcnet_can_receive,
.receive = pcnet_receive,
.cleanup = pci_pcnet_cleanup,
};
static int pci_pcnet_init(PCIDevice *pci_dev)
{
PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
PCNetState *s = &d->state;
uint8_t *pci_conf;
#if 0
printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n",
sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD));
#endif
pci_conf = pci_dev->config;
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_AMD);
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_AMD_LANCE);
pci_set_word(pci_conf + PCI_STATUS,
PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
pci_conf[PCI_REVISION_ID] = 0x10;
pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, 0x0);
pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, 0x0);
pci_conf[PCI_INTERRUPT_PIN] = 1; // interrupt pin 0
pci_conf[PCI_MIN_GNT] = 0x06;
pci_conf[PCI_MAX_LAT] = 0xff;
/* Handler for memory-mapped I/O */
s->mmio_index =
cpu_register_io_memory(pcnet_mmio_read, pcnet_mmio_write, &d->state);
pci_register_bar(pci_dev, 0, PCNET_IOPORT_SIZE,
PCI_BASE_ADDRESS_SPACE_IO, pcnet_ioport_map);
pci_register_bar(pci_dev, 1, PCNET_PNPMMIO_SIZE,
PCI_BASE_ADDRESS_SPACE_MEMORY, pcnet_mmio_map);
s->irq = pci_dev->irq[0];
s->phys_mem_read = pci_physical_memory_read;
s->phys_mem_write = pci_physical_memory_write;
if (!pci_dev->qdev.hotplugged) {
static int loaded = 0;
if (!loaded) {
rom_add_option("pxe-pcnet.bin");
loaded = 1;
}
}
return pcnet_common_init(&pci_dev->qdev, s, &net_pci_pcnet_info);
}
static void pci_reset(DeviceState *dev)
{
PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev.qdev, dev);
pcnet_h_reset(&d->state);
}
static PCIDeviceInfo pcnet_info = {
.qdev.name = "pcnet",
.qdev.size = sizeof(PCIPCNetState),
.qdev.reset = pci_reset,
.qdev.vmsd = &vmstate_pci_pcnet,
.init = pci_pcnet_init,
.exit = pci_pcnet_uninit,
.qdev.props = (Property[]) {
DEFINE_NIC_PROPERTIES(PCIPCNetState, state.conf),
DEFINE_PROP_END_OF_LIST(),
}
};
static void pci_pcnet_register_devices(void)
{
pci_qdev_register(&pcnet_info);
}
device_init(pci_pcnet_register_devices)

View File

@ -35,9 +35,8 @@
* http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt
*/
#include "pci.h"
#include "qdev.h"
#include "net.h"
#include "loader.h"
#include "qemu-timer.h"
#include "qemu_socket.h"
@ -52,11 +51,6 @@
//#define PCNET_DEBUG_MATCH
typedef struct {
PCIDevice pci_dev;
PCNetState state;
} PCIPCNetState;
struct qemu_ether_header {
uint8_t ether_dhost[6];
uint8_t ether_shost[6];
@ -704,7 +698,6 @@ static void pcnet_poll_timer(void *opaque);
static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap);
static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value);
static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val);
static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
static void pcnet_s_reset(PCNetState *s)
{
@ -1048,9 +1041,10 @@ ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_)
int crc_err = 0;
int size = size_;
if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size)
if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size ||
(CSR_LOOP(s) && !s->looptest)) {
return -1;
}
#ifdef PCNET_DEBUG
printf("pcnet_receive size=%d\n", size);
#endif
@ -1537,7 +1531,7 @@ static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
}
}
static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
{
uint32_t val;
rap &= 127;
@ -1594,27 +1588,6 @@ void pcnet_h_reset(void *opaque)
pcnet_poll_timer(s);
}
static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
{
PCNetState *s = opaque;
#ifdef PCNET_DEBUG
printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);
#endif
/* Check APROMWE bit to enable write access */
if (pcnet_bcr_readw(s,2) & 0x100)
s->prom[addr & 15] = val;
}
static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
{
PCNetState *s = opaque;
uint32_t val = s->prom[addr & 15];
#ifdef PCNET_DEBUG
printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);
#endif
return val;
}
void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
{
PCNetState *s = opaque;
@ -1667,7 +1640,7 @@ uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
return val;
}
static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
{
PCNetState *s = opaque;
pcnet_poll_timer(s);
@ -1697,7 +1670,7 @@ static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
pcnet_update_irq(s);
}
static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
{
PCNetState *s = opaque;
uint32_t val = -1;
@ -1726,125 +1699,6 @@ static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
return val;
}
static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
PCNetState *d = &DO_UPCAST(PCIPCNetState, pci_dev, pci_dev)->state;
#ifdef PCNET_DEBUG_IO
printf("pcnet_ioport_map addr=0x%04"FMT_PCIBUS" size=0x%04"FMT_PCIBUS"\n",
addr, size);
#endif
register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d);
register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d);
register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d);
register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d);
register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d);
}
static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
PCNetState *d = opaque;
#ifdef PCNET_DEBUG_IO
printf("pcnet_mmio_writeb addr=0x" TARGET_FMT_plx" val=0x%02x\n", addr,
val);
#endif
if (!(addr & 0x10))
pcnet_aprom_writeb(d, addr & 0x0f, val);
}
static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr)
{
PCNetState *d = opaque;
uint32_t val = -1;
if (!(addr & 0x10))
val = pcnet_aprom_readb(d, addr & 0x0f);
#ifdef PCNET_DEBUG_IO
printf("pcnet_mmio_readb addr=0x" TARGET_FMT_plx " val=0x%02x\n", addr,
val & 0xff);
#endif
return val;
}
static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
{
PCNetState *d = opaque;
#ifdef PCNET_DEBUG_IO
printf("pcnet_mmio_writew addr=0x" TARGET_FMT_plx " val=0x%04x\n", addr,
val);
#endif
if (addr & 0x10)
pcnet_ioport_writew(d, addr & 0x0f, val);
else {
addr &= 0x0f;
pcnet_aprom_writeb(d, addr, val & 0xff);
pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
}
}
static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr)
{
PCNetState *d = opaque;
uint32_t val = -1;
if (addr & 0x10)
val = pcnet_ioport_readw(d, addr & 0x0f);
else {
addr &= 0x0f;
val = pcnet_aprom_readb(d, addr+1);
val <<= 8;
val |= pcnet_aprom_readb(d, addr);
}
#ifdef PCNET_DEBUG_IO
printf("pcnet_mmio_readw addr=0x" TARGET_FMT_plx" val = 0x%04x\n", addr,
val & 0xffff);
#endif
return val;
}
static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
PCNetState *d = opaque;
#ifdef PCNET_DEBUG_IO
printf("pcnet_mmio_writel addr=0x" TARGET_FMT_plx" val=0x%08x\n", addr,
val);
#endif
if (addr & 0x10)
pcnet_ioport_writel(d, addr & 0x0f, val);
else {
addr &= 0x0f;
pcnet_aprom_writeb(d, addr, val & 0xff);
pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16);
pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24);
}
}
static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr)
{
PCNetState *d = opaque;
uint32_t val;
if (addr & 0x10)
val = pcnet_ioport_readl(d, addr & 0x0f);
else {
addr &= 0x0f;
val = pcnet_aprom_readb(d, addr+3);
val <<= 8;
val |= pcnet_aprom_readb(d, addr+2);
val <<= 8;
val |= pcnet_aprom_readb(d, addr+1);
val <<= 8;
val |= pcnet_aprom_readb(d, addr);
}
#ifdef PCNET_DEBUG_IO
printf("pcnet_mmio_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr,
val);
#endif
return val;
}
static bool is_version_2(void *opaque, int version_id)
{
return version_id == 2;
@ -1874,18 +1728,6 @@ const VMStateDescription vmstate_pcnet = {
}
};
static const VMStateDescription vmstate_pci_pcnet = {
.name = "pcnet",
.version_id = 3,
.minimum_version_id = 2,
.minimum_version_id_old = 2,
.fields = (VMStateField []) {
VMSTATE_PCI_DEVICE(pci_dev, PCIPCNetState),
VMSTATE_STRUCT(state, PCIPCNetState, 0, vmstate_pcnet, PCNetState),
VMSTATE_END_OF_LIST()
}
};
void pcnet_common_cleanup(PCNetState *d)
{
d->nic = NULL;
@ -1900,147 +1742,3 @@ int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
return 0;
}
/* PCI interface */
static CPUWriteMemoryFunc * const pcnet_mmio_write[] = {
&pcnet_mmio_writeb,
&pcnet_mmio_writew,
&pcnet_mmio_writel
};
static CPUReadMemoryFunc * const pcnet_mmio_read[] = {
&pcnet_mmio_readb,
&pcnet_mmio_readw,
&pcnet_mmio_readl
};
static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
#ifdef PCNET_DEBUG_IO
printf("pcnet_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n",
addr, size);
#endif
cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->state.mmio_index);
}
static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
uint8_t *buf, int len, int do_bswap)
{
cpu_physical_memory_write(addr, buf, len);
}
static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr,
uint8_t *buf, int len, int do_bswap)
{
cpu_physical_memory_read(addr, buf, len);
}
static void pci_pcnet_cleanup(VLANClientState *nc)
{
PCNetState *d = DO_UPCAST(NICState, nc, nc)->opaque;
pcnet_common_cleanup(d);
}
static int pci_pcnet_uninit(PCIDevice *dev)
{
PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, dev);
cpu_unregister_io_memory(d->state.mmio_index);
qemu_del_timer(d->state.poll_timer);
qemu_free_timer(d->state.poll_timer);
qemu_del_vlan_client(&d->state.nic->nc);
return 0;
}
static NetClientInfo net_pci_pcnet_info = {
.type = NET_CLIENT_TYPE_NIC,
.size = sizeof(NICState),
.can_receive = pcnet_can_receive,
.receive = pcnet_receive,
.cleanup = pci_pcnet_cleanup,
};
static int pci_pcnet_init(PCIDevice *pci_dev)
{
PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
PCNetState *s = &d->state;
uint8_t *pci_conf;
#if 0
printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n",
sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD));
#endif
pci_conf = pci_dev->config;
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_AMD);
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_AMD_LANCE);
pci_set_word(pci_conf + PCI_STATUS,
PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
pci_conf[PCI_REVISION_ID] = 0x10;
pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, 0x0);
pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, 0x0);
pci_conf[PCI_INTERRUPT_PIN] = 1; // interrupt pin 0
pci_conf[PCI_MIN_GNT] = 0x06;
pci_conf[PCI_MAX_LAT] = 0xff;
/* Handler for memory-mapped I/O */
s->mmio_index =
cpu_register_io_memory(pcnet_mmio_read, pcnet_mmio_write, &d->state);
pci_register_bar(pci_dev, 0, PCNET_IOPORT_SIZE,
PCI_BASE_ADDRESS_SPACE_IO, pcnet_ioport_map);
pci_register_bar(pci_dev, 1, PCNET_PNPMMIO_SIZE,
PCI_BASE_ADDRESS_SPACE_MEMORY, pcnet_mmio_map);
s->irq = pci_dev->irq[0];
s->phys_mem_read = pci_physical_memory_read;
s->phys_mem_write = pci_physical_memory_write;
if (!pci_dev->qdev.hotplugged) {
static int loaded = 0;
if (!loaded) {
rom_add_option("pxe-pcnet.bin");
loaded = 1;
}
}
return pcnet_common_init(&pci_dev->qdev, s, &net_pci_pcnet_info);
}
static void pci_reset(DeviceState *dev)
{
PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev.qdev, dev);
pcnet_h_reset(&d->state);
}
static PCIDeviceInfo pcnet_info = {
.qdev.name = "pcnet",
.qdev.size = sizeof(PCIPCNetState),
.qdev.reset = pci_reset,
.qdev.vmsd = &vmstate_pci_pcnet,
.init = pci_pcnet_init,
.exit = pci_pcnet_uninit,
.qdev.props = (Property[]) {
DEFINE_NIC_PROPERTIES(PCIPCNetState, state.conf),
DEFINE_PROP_END_OF_LIST(),
}
};
static void pcnet_register_devices(void)
{
pci_qdev_register(&pcnet_info);
}
device_init(pcnet_register_devices)

View File

@ -32,6 +32,9 @@ struct PCNetState_st {
void pcnet_h_reset(void *opaque);
void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val);
uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr);
void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val);
uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr);
uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
int pcnet_can_receive(VLANClientState *nc);
ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_);
void pcnet_common_cleanup(PCNetState *d);

View File

@ -316,7 +316,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
machine_arch = ARCH_MAC99;
}
/* init basic PC hardware */
pci_vga_init(pci_bus, 0, 0);
pci_vga_init(pci_bus);
escc_mem_index = escc_init(0x80013000, pic[0x25], pic[0x24],
serial_hds[0], serial_hds[1], ESCC_CLOCK, 4);

View File

@ -227,7 +227,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
}
pic = heathrow_pic_init(&pic_mem_index, 1, heathrow_irqs);
pci_bus = pci_grackle_init(0xfec00000, pic);
pci_vga_init(pci_bus, 0, 0);
pci_vga_init(pci_bus);
escc_mem_index = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0],
serial_hds[1], ESCC_CLOCK, 4);

View File

@ -694,7 +694,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
cpu_register_physical_memory(0x80000000, 0x00800000, PPC_io_memory);
/* init basic PC hardware */
pci_vga_init(pci_bus, 0, 0);
pci_vga_init(pci_bus);
// openpic = openpic_init(0x00000000, 0xF0000000, 1);
// pit = pit_init(0x40, i8259[0]);
rtc_init(2000, NULL);

View File

@ -108,7 +108,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
int res = 0, unit;
loc_push_none(&loc);
for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
for (unit = 0; unit < bus->ndev; unit++) {
dinfo = drive_get(IF_SCSI, bus->busnr, unit);
if (dinfo == NULL) {
continue;
@ -123,16 +123,6 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
return res;
}
void scsi_dev_clear_sense(SCSIDevice *dev)
{
memset(&dev->sense, 0, sizeof(dev->sense));
}
void scsi_dev_set_sense(SCSIDevice *dev, uint8_t key)
{
dev->sense.key = key;
}
SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun)
{
SCSIRequest *req;

View File

@ -111,18 +111,20 @@
#define BLANK 0xa1
/*
* Status codes
* SAM Status codes
*/
#define GOOD 0x00
#define CHECK_CONDITION 0x01
#define CONDITION_GOOD 0x02
#define BUSY 0x04
#define INTERMEDIATE_GOOD 0x08
#define INTERMEDIATE_C_GOOD 0x0a
#define RESERVATION_CONFLICT 0x0c
#define COMMAND_TERMINATED 0x11
#define QUEUE_FULL 0x14
#define CHECK_CONDITION 0x02
#define CONDITION_GOOD 0x04
#define BUSY 0x08
#define INTERMEDIATE_GOOD 0x10
#define INTERMEDIATE_C_GOOD 0x14
#define RESERVATION_CONFLICT 0x18
#define COMMAND_TERMINATED 0x22
#define TASK_SET_FULL 0x28
#define ACA_ACTIVE 0x30
#define TASK_ABORTED 0x40
#define STATUS_MASK 0x3e

View File

@ -41,10 +41,18 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
#define SCSI_DMA_BUF_SIZE 131072
#define SCSI_MAX_INQUIRY_LEN 256
#define SCSI_REQ_STATUS_RETRY 0x01
#define SCSI_REQ_STATUS_RETRY 0x01
#define SCSI_REQ_STATUS_RETRY_TYPE_MASK 0x06
#define SCSI_REQ_STATUS_RETRY_READ 0x00
#define SCSI_REQ_STATUS_RETRY_WRITE 0x02
#define SCSI_REQ_STATUS_RETRY_FLUSH 0x04
typedef struct SCSIDiskState SCSIDiskState;
typedef struct SCSISense {
uint8_t key;
} SCSISense;
typedef struct SCSIDiskReq {
SCSIRequest req;
/* ??? We should probably keep track of whether the data transfer is
@ -68,8 +76,12 @@ struct SCSIDiskState
QEMUBH *bh;
char *version;
char *serial;
SCSISense sense;
};
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type);
static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf);
static SCSIDiskReq *scsi_new_request(SCSIDiskState *s, uint32_t tag,
uint32_t lun)
{
@ -93,10 +105,22 @@ static SCSIDiskReq *scsi_find_request(SCSIDiskState *s, uint32_t tag)
return DO_UPCAST(SCSIDiskReq, req, scsi_req_find(&s->qdev, tag));
}
static void scsi_req_set_status(SCSIRequest *req, int status, int sense_code)
static void scsi_disk_clear_sense(SCSIDiskState *s)
{
req->status = status;
scsi_dev_set_sense(req->dev, sense_code);
memset(&s->sense, 0, sizeof(s->sense));
}
static void scsi_disk_set_sense(SCSIDiskState *s, uint8_t key)
{
s->sense.key = key;
}
static void scsi_req_set_status(SCSIDiskReq *r, int status, int sense_code)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
r->req.status = status;
scsi_disk_set_sense(s, sense_code);
}
/* Helper function for command completion. */
@ -104,7 +128,7 @@ static void scsi_command_complete(SCSIDiskReq *r, int status, int sense)
{
DPRINTF("Command complete tag=0x%x status=%d sense=%d\n",
r->req.tag, status, sense);
scsi_req_set_status(&r->req, status, sense);
scsi_req_set_status(r, status, sense);
scsi_req_complete(&r->req);
scsi_remove_request(r);
}
@ -127,34 +151,30 @@ static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
static void scsi_read_complete(void * opaque, int ret)
{
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
int n;
r->req.aiocb = NULL;
if (ret) {
DPRINTF("IO error\n");
r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0);
scsi_command_complete(r, CHECK_CONDITION, NO_SENSE);
return;
if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_READ)) {
return;
}
}
DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->iov.iov_len);
n = r->iov.iov_len / 512;
r->sector += n;
r->sector_count -= n;
r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->iov.iov_len);
}
/* Read more data from scsi device into buffer. */
static void scsi_read_data(SCSIDevice *d, uint32_t tag)
static void scsi_read_request(SCSIDiskReq *r)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
SCSIDiskReq *r;
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
uint32_t n;
r = scsi_find_request(s, tag);
if (!r) {
BADF("Bad read tag 0x%x\n", tag);
/* ??? This is the wrong error. */
scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
return;
}
if (r->sector_count == (uint32_t)-1) {
DPRINTF("Read buf_len=%zd\n", r->iov.iov_len);
r->sector_count = 0;
@ -167,6 +187,9 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
return;
}
/* No data transfer may already be in progress */
assert(r->req.aiocb == NULL);
n = r->sector_count;
if (n > SCSI_DMA_BUF_SIZE / 512)
n = SCSI_DMA_BUF_SIZE / 512;
@ -175,31 +198,54 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
qemu_iovec_init_external(&r->qiov, &r->iov, 1);
r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n,
scsi_read_complete, r);
if (r->req.aiocb == NULL)
scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
r->sector += n;
r->sector_count -= n;
if (r->req.aiocb == NULL) {
scsi_read_complete(r, -EIO);
}
}
static int scsi_handle_write_error(SCSIDiskReq *r, int error)
/* Read more data from scsi device into buffer. */
static void scsi_read_data(SCSIDevice *d, uint32_t tag)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
SCSIDiskReq *r;
r = scsi_find_request(s, tag);
if (!r) {
BADF("Bad read tag 0x%x\n", tag);
/* ??? This is the wrong error. */
scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
return;
}
scsi_read_request(r);
}
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
{
int is_read = (type == SCSI_REQ_STATUS_RETRY_READ);
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
BlockErrorAction action = bdrv_get_on_error(s->bs, 0);
BlockErrorAction action = bdrv_get_on_error(s->bs, is_read);
if (action == BLOCK_ERR_IGNORE) {
bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, 0);
bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, is_read);
return 0;
}
if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
|| action == BLOCK_ERR_STOP_ANY) {
r->status |= SCSI_REQ_STATUS_RETRY;
bdrv_mon_event(s->bs, BDRV_ACTION_STOP, 0);
type &= SCSI_REQ_STATUS_RETRY_TYPE_MASK;
r->status |= SCSI_REQ_STATUS_RETRY | type;
bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
vm_stop(0);
} else {
if (type == SCSI_REQ_STATUS_RETRY_READ) {
r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0);
}
scsi_command_complete(r, CHECK_CONDITION,
HARDWARE_ERROR);
bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, 0);
bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read);
}
return 1;
@ -214,8 +260,9 @@ static void scsi_write_complete(void * opaque, int ret)
r->req.aiocb = NULL;
if (ret) {
if (scsi_handle_write_error(r, -ret))
if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_WRITE)) {
return;
}
}
n = r->iov.iov_len / 512;
@ -239,14 +286,17 @@ static void scsi_write_request(SCSIDiskReq *r)
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
uint32_t n;
/* No data transfer may already be in progress */
assert(r->req.aiocb == NULL);
n = r->iov.iov_len / 512;
if (n) {
qemu_iovec_init_external(&r->qiov, &r->iov, 1);
r->req.aiocb = bdrv_aio_writev(s->bs, r->sector, &r->qiov, n,
scsi_write_complete, r);
if (r->req.aiocb == NULL)
scsi_command_complete(r, CHECK_CONDITION,
HARDWARE_ERROR);
if (r->req.aiocb == NULL) {
scsi_write_complete(r, -EIO);
}
} else {
/* Invoke completion routine to fetch data from host. */
scsi_write_complete(r, 0);
@ -268,9 +318,6 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag)
return 1;
}
if (r->req.aiocb)
BADF("Data transfer already in progress\n");
scsi_write_request(r);
return 0;
@ -288,8 +335,25 @@ static void scsi_dma_restart_bh(void *opaque)
QTAILQ_FOREACH(req, &s->qdev.requests, next) {
r = DO_UPCAST(SCSIDiskReq, req, req);
if (r->status & SCSI_REQ_STATUS_RETRY) {
r->status &= ~SCSI_REQ_STATUS_RETRY;
scsi_write_request(r);
int status = r->status;
int ret;
r->status &=
~(SCSI_REQ_STATUS_RETRY | SCSI_REQ_STATUS_RETRY_TYPE_MASK);
switch (status & SCSI_REQ_STATUS_RETRY_TYPE_MASK) {
case SCSI_REQ_STATUS_RETRY_READ:
scsi_read_request(r);
break;
case SCSI_REQ_STATUS_RETRY_WRITE:
scsi_write_request(r);
break;
case SCSI_REQ_STATUS_RETRY_FLUSH:
ret = scsi_disk_emulate_command(r, r->iov.iov_base);
if (ret == 0) {
scsi_command_complete(r, GOOD, NO_SENSE);
}
}
}
}
}
@ -351,15 +415,20 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
switch (page_code) {
case 0x00: /* Supported page codes, mandatory */
{
int pages;
DPRINTF("Inquiry EVPD[Supported pages] "
"buffer size %zd\n", req->cmd.xfer);
outbuf[buflen++] = 4; // number of pages
pages = buflen++;
outbuf[buflen++] = 0x00; // list of supported pages (this page)
outbuf[buflen++] = 0x80; // unit serial number
outbuf[buflen++] = 0x83; // device identification
outbuf[buflen++] = 0xb0; // block device characteristics
if (bdrv_get_type_hint(s->bs) != BDRV_TYPE_CDROM) {
outbuf[buflen++] = 0xb0; // block device characteristics
}
outbuf[pages] = buflen - pages - 1; // number of pages
break;
}
case 0x80: /* Device serial number, optional */
{
int l = strlen(s->serial);
@ -387,7 +456,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
DPRINTF("Inquiry EVPD[Device identification] "
"buffer size %zd\n", req->cmd.xfer);
outbuf[buflen++] = 3 + id_len;
outbuf[buflen++] = 4 + id_len;
outbuf[buflen++] = 0x2; // ASCII
outbuf[buflen++] = 0; // not officially assigned
outbuf[buflen++] = 0; // reserved
@ -404,6 +473,11 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
unsigned int opt_io_size =
s->qdev.conf.opt_io_size / s->qdev.blocksize;
if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
page_code);
return -1;
}
/* required VPD size with unmap support */
outbuf[3] = buflen = 0x3c;
@ -747,11 +821,13 @@ static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
return toclen;
}
static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
{
SCSIRequest *req = &r->req;
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
uint64_t nb_sectors;
int buflen = 0;
int ret;
switch (req->cmd.buf[0]) {
case TEST_UNIT_READY:
@ -763,7 +839,7 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
goto illegal_request;
memset(outbuf, 0, 4);
buflen = 4;
if (req->dev->sense.key == NOT_READY && req->cmd.xfer >= 18) {
if (s->sense.key == NOT_READY && req->cmd.xfer >= 18) {
memset(outbuf, 0, 18);
buflen = 18;
outbuf[7] = 10;
@ -773,8 +849,8 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
}
outbuf[0] = 0xf0;
outbuf[1] = 0;
outbuf[2] = req->dev->sense.key;
scsi_dev_clear_sense(req->dev);
outbuf[2] = s->sense.key;
scsi_disk_clear_sense(s);
break;
case INQUIRY:
buflen = scsi_disk_emulate_inquiry(req, outbuf);
@ -842,7 +918,12 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
buflen = 8;
break;
case SYNCHRONIZE_CACHE:
bdrv_flush(s->bs);
ret = bdrv_flush(s->bs);
if (ret < 0) {
if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) {
return -1;
}
}
break;
case GET_CONFIGURATION:
memset(outbuf, 0, 8);
@ -902,16 +983,16 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
default:
goto illegal_request;
}
scsi_req_set_status(req, GOOD, NO_SENSE);
scsi_req_set_status(r, GOOD, NO_SENSE);
return buflen;
not_ready:
scsi_req_set_status(req, CHECK_CONDITION, NOT_READY);
return 0;
scsi_command_complete(r, CHECK_CONDITION, NOT_READY);
return -1;
illegal_request:
scsi_req_set_status(req, CHECK_CONDITION, ILLEGAL_REQUEST);
return 0;
scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST);
return -1;
}
/* Execute a scsi command. Returns the length of the data expected by the
@ -923,9 +1004,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
uint8_t *buf, int lun)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
uint64_t lba;
uint32_t len;
int cmdlen;
int is_write;
uint8_t command;
uint8_t *outbuf;
@ -944,55 +1023,21 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
outbuf = (uint8_t *)r->iov.iov_base;
is_write = 0;
DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
switch (command >> 5) {
case 0:
lba = (uint64_t) buf[3] | ((uint64_t) buf[2] << 8) |
(((uint64_t) buf[1] & 0x1f) << 16);
len = buf[4];
cmdlen = 6;
break;
case 1:
case 2:
lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
len = buf[8] | (buf[7] << 8);
cmdlen = 10;
break;
case 4:
lba = (uint64_t) buf[9] | ((uint64_t) buf[8] << 8) |
((uint64_t) buf[7] << 16) | ((uint64_t) buf[6] << 24) |
((uint64_t) buf[5] << 32) | ((uint64_t) buf[4] << 40) |
((uint64_t) buf[3] << 48) | ((uint64_t) buf[2] << 56);
len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
cmdlen = 16;
break;
case 5:
lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
cmdlen = 12;
break;
default:
if (scsi_req_parse(&r->req, buf) != 0) {
BADF("Unsupported command length, command %x\n", command);
goto fail;
}
#ifdef DEBUG_SCSI
{
int i;
for (i = 1; i < cmdlen; i++) {
for (i = 1; i < r->req.cmd.len; i++) {
printf(" 0x%02x", buf[i]);
}
printf("\n");
}
#endif
if (scsi_req_parse(&r->req, buf) != 0) {
BADF("Unsupported command length, command %x\n", command);
goto fail;
}
assert(r->req.cmd.len == cmdlen);
assert(r->req.cmd.lba == lba);
if (lun || buf[1] >> 5) {
/* Only LUN 0 supported. */
DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
@ -1019,23 +1064,22 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case REPORT_LUNS:
case VERIFY:
case REZERO_UNIT:
rc = scsi_disk_emulate_command(&r->req, outbuf);
if (rc > 0) {
r->iov.iov_len = rc;
} else {
scsi_req_complete(&r->req);
scsi_remove_request(r);
rc = scsi_disk_emulate_command(r, outbuf);
if (rc < 0) {
return 0;
}
r->iov.iov_len = rc;
break;
case READ_6:
case READ_10:
case READ_12:
case READ_16:
DPRINTF("Read (sector %" PRId64 ", count %d)\n", lba, len);
if (lba > s->max_lba)
len = r->req.cmd.xfer / d->blocksize;
DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len);
if (r->req.cmd.lba > s->max_lba)
goto illegal_lba;
r->sector = lba * s->cluster_size;
r->sector = r->req.cmd.lba * s->cluster_size;
r->sector_count = len * s->cluster_size;
break;
case WRITE_6:
@ -1045,42 +1089,45 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case WRITE_VERIFY:
case WRITE_VERIFY_12:
case WRITE_VERIFY_16:
len = r->req.cmd.xfer / d->blocksize;
DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",
(command & 0xe) == 0xe ? "And Verify " : "", lba, len);
if (lba > s->max_lba)
(command & 0xe) == 0xe ? "And Verify " : "",
r->req.cmd.lba, len);
if (r->req.cmd.lba > s->max_lba)
goto illegal_lba;
r->sector = lba * s->cluster_size;
r->sector = r->req.cmd.lba * s->cluster_size;
r->sector_count = len * s->cluster_size;
is_write = 1;
break;
case MODE_SELECT:
DPRINTF("Mode Select(6) (len %d)\n", len);
DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
/* We don't support mode parameter changes.
Allow the mode parameter header + block descriptors only. */
if (len > 12) {
if (r->req.cmd.xfer > 12) {
goto fail;
}
break;
case MODE_SELECT_10:
DPRINTF("Mode Select(10) (len %d)\n", len);
DPRINTF("Mode Select(10) (len %lu)\n", (long)r->req.cmd.xfer);
/* We don't support mode parameter changes.
Allow the mode parameter header + block descriptors only. */
if (len > 16) {
if (r->req.cmd.xfer > 16) {
goto fail;
}
break;
case SEEK_6:
case SEEK_10:
DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10, lba);
if (lba > s->max_lba) {
DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10,
r->req.cmd.lba);
if (r->req.cmd.lba > s->max_lba) {
goto illegal_lba;
}
break;
default:
DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
fail:
scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST);
return 0;
return 0;
illegal_lba:
scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
return 0;
@ -1152,11 +1199,6 @@ static int scsi_disk_initfn(SCSIDevice *dev)
return -1;
}
if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
error_report("Device doesn't support drive option rerror");
return -1;
}
if (!s->serial) {
/* try to fall back to value set with legacy -drive serial=... */
dinfo = drive_get_by_blockdev(s->bs);

View File

@ -96,17 +96,17 @@ static void scsi_command_complete(void *opaque, int ret)
s->senselen = r->io_header.sb_len_wr;
if (ret != 0)
r->req.status = BUSY << 1;
r->req.status = BUSY;
else {
if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
r->req.status = BUSY << 1;
r->req.status = BUSY;
BADF("Driver Timeout\n");
} else if (r->io_header.status)
r->req.status = r->io_header.status;
else if (s->driver_status & SG_ERR_DRIVER_SENSE)
r->req.status = CHECK_CONDITION << 1;
r->req.status = CHECK_CONDITION;
else
r->req.status = GOOD << 1;
r->req.status = GOOD;
}
DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
r, r->req.tag, r->req.status);
@ -333,7 +333,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
s->senselen = 7;
s->driver_status = SG_ERR_DRIVER_SENSE;
bus = scsi_bus_from_device(d);
bus->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION << 1);
bus->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION);
return 0;
}

View File

@ -3,6 +3,7 @@
#include "qdev.h"
#include "block.h"
#include "blockdev.h"
#include "block_int.h"
#define SCSI_CMD_BUF_SIZE 16
@ -25,10 +26,6 @@ enum SCSIXferMode {
SCSI_XFER_TO_DEV, /* WRITE, MODE_SELECT, ... */
};
typedef struct SCSISense {
uint8_t key;
} SCSISense;
typedef struct SCSIRequest {
SCSIBus *bus;
SCSIDevice *dev;
@ -56,7 +53,6 @@ struct SCSIDevice
QTAILQ_HEAD(, SCSIRequest) requests;
int blocksize;
int type;
struct SCSISense sense;
};
/* cdrom.c */
@ -86,7 +82,7 @@ struct SCSIBus {
int tcq, ndev;
scsi_completionfn complete;
SCSIDevice *devs[8];
SCSIDevice *devs[MAX_SCSI_DEVS];
};
void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev,
@ -101,9 +97,6 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, int unit);
int scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
void scsi_dev_clear_sense(SCSIDevice *dev);
void scsi_dev_set_sense(SCSIDevice *dev, uint8_t key);
SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun);
SCSIRequest *scsi_req_find(SCSIDevice *d, uint32_t tag);
void scsi_req_free(SCSIRequest *req);

View File

@ -767,7 +767,7 @@ static void sun4uv_init(ram_addr_t RAM_size,
pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, irq, &pci_bus2,
&pci_bus3);
isa_mem_base = APB_PCI_IO_BASE;
pci_vga_init(pci_bus, 0, 0);
pci_vga_init(pci_bus);
// XXX Should be pci_bus3
pci_ebus_init(pci_bus, -1);

View File

@ -1142,7 +1142,7 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
break;
default:
if (usb_net_stringtable[value & 0xff]) {
if (ARRAY_SIZE(usb_net_stringtable) > (value & 0xff)) {
ret = set_usb_string(data,
usb_net_stringtable[value & 0xff]);
break;

View File

@ -52,14 +52,11 @@ static void vga_map(PCIDevice *pci_dev, int region_num,
{
PCIVGAState *d = (PCIVGAState *)pci_dev;
VGACommonState *s = &d->vga;
if (region_num == PCI_ROM_SLOT) {
cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
} else {
cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
s->map_addr = addr;
s->map_end = addr + s->vram_size;
vga_dirty_log_start(s);
}
cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
s->map_addr = addr;
s->map_end = addr + s->vram_size;
vga_dirty_log_start(s);
}
static void pci_vga_write_config(PCIDevice *d,
@ -95,32 +92,17 @@ static int pci_vga_initfn(PCIDevice *dev)
pci_register_bar(&d->dev, 0, VGA_RAM_SIZE,
PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map);
if (s->bios_size) {
unsigned int bios_total_size;
/* must be a power of two */
bios_total_size = 1;
while (bios_total_size < s->bios_size)
bios_total_size <<= 1;
pci_register_bar(&d->dev, PCI_ROM_SLOT, bios_total_size,
PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map);
if (!dev->rom_bar) {
/* compatibility with pc-0.13 and older */
vga_init_vbe(s);
}
vga_init_vbe(s);
/* ROM BIOS */
rom_add_vga(VGABIOS_FILENAME);
return 0;
}
int pci_vga_init(PCIBus *bus,
unsigned long vga_bios_offset, int vga_bios_size)
int pci_vga_init(PCIBus *bus)
{
PCIDevice *dev;
dev = pci_create(bus, -1, "VGA");
qdev_prop_set_uint32(&dev->qdev, "bios-offset", vga_bios_offset);
qdev_prop_set_uint32(&dev->qdev, "bios-size", vga_bios_size);
qdev_init_nofail(&dev->qdev);
pci_create_simple(bus, -1, "VGA");
return 0;
}
@ -130,11 +112,7 @@ static PCIDeviceInfo vga_info = {
.qdev.vmsd = &vmstate_vga_pci,
.init = pci_vga_initfn,
.config_write = pci_vga_write_config,
.qdev.props = (Property[]) {
DEFINE_PROP_HEX32("bios-offset", PCIVGAState, vga.bios_offset, 0),
DEFINE_PROP_HEX32("bios-size", PCIVGAState, vga.bios_size, 0),
DEFINE_PROP_END_OF_LIST(),
}
.romfile = "vgabios-stdvga.bin",
};
static void vga_register(void)

View File

@ -1934,8 +1934,6 @@ void vga_common_reset(VGACommonState *s)
s->map_addr = 0;
s->map_end = 0;
s->lfb_vram_mapped = 0;
s->bios_offset = 0;
s->bios_size = 0;
s->sr_index = 0;
memset(s->sr, '\0', sizeof(s->sr));
s->gr_index = 0;

View File

@ -112,8 +112,6 @@ typedef struct VGACommonState {
uint32_t map_addr;
uint32_t map_end;
uint32_t lfb_vram_mapped; /* whether 0xa0000 is mapped as ram */
uint32_t bios_offset;
uint32_t bios_size;
uint32_t latch;
uint8_t sr_index;
uint8_t sr[256];

View File

@ -273,7 +273,7 @@ static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
acb = bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
if (!acb) {
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
virtio_blk_flush_complete(req, -EIO);
}
}
@ -324,13 +324,13 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
MultiReqBuffer *mrb)
{
if (req->elem.out_num < 1 || req->elem.in_num < 1) {
fprintf(stderr, "virtio-blk missing headers\n");
error_report("virtio-blk missing headers");
exit(1);
}
if (req->elem.out_sg[0].iov_len < sizeof(*req->out) ||
req->elem.in_sg[req->elem.in_num - 1].iov_len < sizeof(*req->in)) {
fprintf(stderr, "virtio-blk header not in correct element\n");
error_report("virtio-blk header not in correct element");
exit(1);
}

View File

@ -120,8 +120,8 @@ static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
if (!n->vhost_started) {
int r = vhost_net_start(tap_get_vhost_net(n->nic->nc.peer), &n->vdev);
if (r < 0) {
fprintf(stderr, "unable to start vhost net: %d: "
"falling back on userspace virtio\n", -r);
error_report("unable to start vhost net: %d: "
"falling back on userspace virtio", -r);
} else {
n->vhost_started = 1;
}
@ -271,7 +271,7 @@ static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd,
uint8_t on;
if (elem->out_num != 2 || elem->out_sg[1].iov_len != sizeof(on)) {
fprintf(stderr, "virtio-net ctrl invalid rx mode command\n");
error_report("virtio-net ctrl invalid rx mode command");
exit(1);
}
@ -353,7 +353,7 @@ static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd,
uint16_t vid;
if (elem->out_num != 2 || elem->out_sg[1].iov_len != sizeof(vid)) {
fprintf(stderr, "virtio-net ctrl invalid vlan command\n");
error_report("virtio-net ctrl invalid vlan command");
return VIRTIO_NET_ERR;
}
@ -381,13 +381,13 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
while (virtqueue_pop(vq, &elem)) {
if ((elem.in_num < 1) || (elem.out_num < 1)) {
fprintf(stderr, "virtio-net ctrl missing headers\n");
error_report("virtio-net ctrl missing headers");
exit(1);
}
if (elem.out_sg[0].iov_len < sizeof(ctrl) ||
elem.in_sg[elem.in_num - 1].iov_len < sizeof(status)) {
fprintf(stderr, "virtio-net ctrl header not in correct element\n");
error_report("virtio-net ctrl header not in correct element");
exit(1);
}
@ -591,21 +591,21 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
if (virtqueue_pop(n->rx_vq, &elem) == 0) {
if (i == 0)
return -1;
fprintf(stderr, "virtio-net unexpected empty queue: "
error_report("virtio-net unexpected empty queue: "
"i %zd mergeable %d offset %zd, size %zd, "
"guest hdr len %zd, host hdr len %zd guest features 0x%x\n",
"guest hdr len %zd, host hdr len %zd guest features 0x%x",
i, n->mergeable_rx_bufs, offset, size,
guest_hdr_len, host_hdr_len, n->vdev.guest_features);
exit(1);
}
if (elem.in_num < 1) {
fprintf(stderr, "virtio-net receive queue contains no in buffers\n");
error_report("virtio-net receive queue contains no in buffers");
exit(1);
}
if (!n->mergeable_rx_bufs && elem.in_sg[0].iov_len != guest_hdr_len) {
fprintf(stderr, "virtio-net header not in first element\n");
error_report("virtio-net header not in first element");
exit(1);
}
@ -630,12 +630,11 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
* Otherwise, drop it. */
if (!n->mergeable_rx_bufs && offset < size) {
#if 0
fprintf(stderr, "virtio-net truncated non-mergeable packet: "
"i %zd mergeable %d offset %zd, size %zd, "
"guest hdr len %zd, host hdr len %zd\n",
i, n->mergeable_rx_bufs,
offset, size, guest_hdr_len, host_hdr_len);
error_report("virtio-net truncated non-mergeable packet: "
"i %zd mergeable %d offset %zd, size %zd, "
"guest hdr len %zd, host hdr len %zd",
i, n->mergeable_rx_bufs,
offset, size, guest_hdr_len, host_hdr_len);
#endif
return size;
}
@ -695,7 +694,7 @@ static int32_t virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
sizeof(struct virtio_net_hdr);
if (out_num < 1 || out_sg->iov_len != hdr_len) {
fprintf(stderr, "virtio-net header not in first element\n");
error_report("virtio-net header not in first element");
exit(1);
}
@ -981,10 +980,10 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
if (net->tx && strcmp(net->tx, "timer") && strcmp(net->tx, "bh")) {
fprintf(stderr, "virtio-net: "
"Unknown option tx=%s, valid options: \"timer\" \"bh\"\n",
net->tx);
fprintf(stderr, "Defaulting to \"bh\"\n");
error_report("virtio-net: "
"Unknown option tx=%s, valid options: \"timer\" \"bh\"",
net->tx);
error_report("Defaulting to \"bh\"");
}
if (net->tx && !strcmp(net->tx, "timer")) {

View File

@ -254,8 +254,8 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
virtio_queue_set_vector(vdev, vdev->queue_sel, val);
break;
default:
fprintf(stderr, "%s: unexpected address 0x%x value 0x%x\n",
__func__, addr, val);
error_report("%s: unexpected address 0x%x value 0x%x",
__func__, addr, val);
break;
}
}
@ -684,12 +684,14 @@ static int virtio_9p_init_pci(PCIDevice *pci_dev)
VirtIODevice *vdev;
vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
vdev->nvectors = proxy->nvectors;
virtio_init_pci(proxy, vdev,
PCI_VENDOR_ID_REDHAT_QUMRANET,
0x1009,
0x2,
0x00);
/* make the actual value visible */
proxy->nvectors = vdev->nvectors;
return 0;
}
#endif
@ -758,6 +760,7 @@ static PCIDeviceInfo virtio_info[] = {
.qdev.size = sizeof(VirtIOPCIProxy),
.init = virtio_9p_init_pci,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),

View File

@ -114,14 +114,12 @@ struct pci_vmsvga_state_s {
# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT
# define SVGA_IO_MUL 1
# define SVGA_FIFO_SIZE 0x10000
# define SVGA_MEM_BASE 0xe0000000
# define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA2
#else
# define SVGA_ID SVGA_ID_1
# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT
# define SVGA_IO_MUL 4
# define SVGA_FIFO_SIZE 0x10000
# define SVGA_MEM_BASE 0xe0000000
# define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA
#endif
@ -1219,10 +1217,6 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
vga_init(&s->vga);
vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
vga_init_vbe(&s->vga);
rom_add_vga(VGABIOS_FILENAME);
vmsvga_reset(s);
}
@ -1307,6 +1301,11 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
vmsvga_init(&s->chip, VGA_RAM_SIZE);
if (!dev->rom_bar) {
/* compatibility with pc-0.13 and older */
vga_init_vbe(&s->chip.vga);
}
return 0;
}
@ -1320,6 +1319,7 @@ static PCIDeviceInfo vmsvga_info = {
.qdev.size = sizeof(struct pci_vmsvga_state_s),
.qdev.vmsd = &vmstate_vmware_vga,
.init = pci_vmsvga_initfn,
.romfile = "vgabios-vmware.bin",
};
static void vmsvga_register(void)

View File

@ -181,6 +181,10 @@ static int ioreq_parse(struct ioreq *ioreq)
ioreq->prot = PROT_WRITE; /* to memory */
break;
case BLKIF_OP_WRITE_BARRIER:
if (!ioreq->req.nr_segments) {
ioreq->presync = 1;
return 0;
}
if (!syncwrite)
ioreq->presync = ioreq->postsync = 1;
/* fall through */
@ -305,7 +309,7 @@ static int ioreq_runio_qemu_sync(struct ioreq *ioreq)
int i, rc, len = 0;
off_t pos;
if (ioreq_map(ioreq) == -1)
if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1)
goto err;
if (ioreq->presync)
bdrv_flush(blkdev->bs);
@ -329,6 +333,8 @@ static int ioreq_runio_qemu_sync(struct ioreq *ioreq)
break;
case BLKIF_OP_WRITE:
case BLKIF_OP_WRITE_BARRIER:
if (!ioreq->req.nr_segments)
break;
pos = ioreq->start;
for (i = 0; i < ioreq->v.niov; i++) {
rc = bdrv_write(blkdev->bs, pos / BLOCK_SIZE,
@ -386,7 +392,7 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
{
struct XenBlkDev *blkdev = ioreq->blkdev;
if (ioreq_map(ioreq) == -1)
if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1)
goto err;
ioreq->aio_inflight++;
@ -403,6 +409,8 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
case BLKIF_OP_WRITE:
case BLKIF_OP_WRITE_BARRIER:
ioreq->aio_inflight++;
if (!ioreq->req.nr_segments)
break;
bdrv_aio_writev(blkdev->bs, ioreq->start / BLOCK_SIZE,
&ioreq->v, ioreq->v.size / BLOCK_SIZE,
qemu_aio_complete, ioreq);

View File

@ -174,6 +174,70 @@ int register_ioport_write(pio_addr_t start, int length, int size,
return 0;
}
static uint32_t ioport_readb_thunk(void *opaque, uint32_t addr)
{
IORange *ioport = opaque;
uint64_t data;
ioport->ops->read(ioport, addr - ioport->base, 1, &data);
return data;
}
static uint32_t ioport_readw_thunk(void *opaque, uint32_t addr)
{
IORange *ioport = opaque;
uint64_t data;
ioport->ops->read(ioport, addr - ioport->base, 2, &data);
return data;
}
static uint32_t ioport_readl_thunk(void *opaque, uint32_t addr)
{
IORange *ioport = opaque;
uint64_t data;
ioport->ops->read(ioport, addr - ioport->base, 4, &data);
return data;
}
static void ioport_writeb_thunk(void *opaque, uint32_t addr, uint32_t data)
{
IORange *ioport = opaque;
ioport->ops->write(ioport, addr - ioport->base, 1, data);
}
static void ioport_writew_thunk(void *opaque, uint32_t addr, uint32_t data)
{
IORange *ioport = opaque;
ioport->ops->write(ioport, addr - ioport->base, 2, data);
}
static void ioport_writel_thunk(void *opaque, uint32_t addr, uint32_t data)
{
IORange *ioport = opaque;
ioport->ops->write(ioport, addr - ioport->base, 4, data);
}
void ioport_register(IORange *ioport)
{
register_ioport_read(ioport->base, ioport->len, 1,
ioport_readb_thunk, ioport);
register_ioport_read(ioport->base, ioport->len, 2,
ioport_readw_thunk, ioport);
register_ioport_read(ioport->base, ioport->len, 4,
ioport_readl_thunk, ioport);
register_ioport_write(ioport->base, ioport->len, 1,
ioport_writeb_thunk, ioport);
register_ioport_write(ioport->base, ioport->len, 2,
ioport_writew_thunk, ioport);
register_ioport_write(ioport->base, ioport->len, 4,
ioport_writel_thunk, ioport);
}
void isa_unassign_ioport(pio_addr_t start, int length)
{
int i;

View File

@ -25,6 +25,7 @@
#define IOPORT_H
#include "qemu-common.h"
#include "iorange.h"
typedef uint32_t pio_addr_t;
#define FMT_pioaddr PRIx32
@ -36,6 +37,7 @@ typedef uint32_t pio_addr_t;
typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data);
typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address);
void ioport_register(IORange *iorange);
int register_ioport_read(pio_addr_t start, int length, int size,
IOPortReadFunc *func, void *opaque);
int register_ioport_write(pio_addr_t start, int length, int size,

30
iorange.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef IORANGE_H
#define IORANGE_H
#include <stdint.h>
typedef struct IORange IORange;
typedef struct IORangeOps IORangeOps;
struct IORangeOps {
void (*read)(IORange *iorange, uint64_t offset, unsigned width,
uint64_t *data);
void (*write)(IORange *iorange, uint64_t offset, unsigned width,
uint64_t data);
};
struct IORange {
const IORangeOps *ops;
uint64_t base;
uint64_t len;
};
static inline void iorange_init(IORange *iorange, const IORangeOps *ops,
uint64_t base, uint64_t len)
{
iorange->ops = ops;
iorange->base = base;
iorange->len = len;
}
#endif

View File

@ -3071,11 +3071,11 @@ struct target_stack_t {
};
struct target_ucontext {
abi_ulong uc_flags;
abi_ulong uc_link;
struct target_stack_t uc_stack;
struct target_sigcontext sc;
uint32_t extramask[TARGET_NSIG_WORDS - 1];
abi_ulong tuc_flags;
abi_ulong tuc_link;
struct target_stack_t tuc_stack;
struct target_sigcontext tuc_mcontext;
uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
};
/* Signal frames. */
@ -3189,7 +3189,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
goto badframe;
/* Save the mask. */
err |= __put_user(set->sig[0], &frame->uc.sc.oldmask);
err |= __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
if (err)
goto badframe;
@ -3198,7 +3198,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
goto badframe;
}
setup_sigcontext(&frame->uc.sc, env);
setup_sigcontext(&frame->uc.tuc_mcontext, env);
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
@ -3261,7 +3261,7 @@ long do_sigreturn(CPUState *env)
goto badframe;
/* Restore blocked signals */
if (__get_user(target_set.sig[0], &frame->uc.sc.oldmask))
if (__get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask))
goto badframe;
for(i = 1; i < TARGET_NSIG_WORDS; i++) {
if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
@ -3270,7 +3270,7 @@ long do_sigreturn(CPUState *env)
target_to_host_sigset_internal(&set, &target_set);
sigprocmask(SIG_SETMASK, &set, NULL);
restore_sigcontext(&frame->uc.sc, env);
restore_sigcontext(&frame->uc.tuc_mcontext, env);
/* We got here through a sigreturn syscall, our path back is via an
rtb insn so setup r14 for that. */
env->regs[14] = env->sregs[SR_PC];

28
make_device_config.sh Normal file
View File

@ -0,0 +1,28 @@
#! /bin/sh
# Construct a target device config file from a default, pulling in any
# files from include directives.
dest=$1.tmp
dep=$1.d
src=$2
src_dir=`dirname $src`
all_includes=
process_includes () {
cat $1 | grep '^include' | \
while read include file ; do
all_includes="$all_includes $src_dir/$file"
process_includes $src_dir/$file
done
}
f=$src
while [ -n "$f" ] ; do
f=`awk '/^include / {ORS=" " ; print "'$src_dir'/" $2}' $f`
[ $? = 0 ] || exit 1
all_includes="$all_includes $f"
done
process_includes $src > $dest
cat $src $all_includes | grep -v '^include' > $dest
echo "$1: $all_includes" > $dep

View File

@ -491,6 +491,44 @@ static int do_qmp_capabilities(Monitor *mon, const QDict *params,
return 0;
}
static int mon_set_cpu(int cpu_index);
static void handle_user_command(Monitor *mon, const char *cmdline);
static int do_hmp_passthrough(Monitor *mon, const QDict *params,
QObject **ret_data)
{
int ret = 0;
Monitor *old_mon, hmp;
CharDriverState mchar;
memset(&hmp, 0, sizeof(hmp));
qemu_chr_init_mem(&mchar);
hmp.chr = &mchar;
old_mon = cur_mon;
cur_mon = &hmp;
if (qdict_haskey(params, "cpu-index")) {
ret = mon_set_cpu(qdict_get_int(params, "cpu-index"));
if (ret < 0) {
cur_mon = old_mon;
qerror_report(QERR_INVALID_PARAMETER_VALUE, "cpu-index", "a CPU number");
goto out;
}
}
handle_user_command(&hmp, qdict_get_str(params, "command-line"));
cur_mon = old_mon;
if (qemu_chr_mem_osize(hmp.chr) > 0) {
*ret_data = QOBJECT(qemu_chr_mem_to_qs(hmp.chr));
}
out:
qemu_chr_close_mem(hmp.chr);
return ret;
}
static int compare_cmd(const char *name, const char *list)
{
const char *p, *pstart;

View File

@ -31,14 +31,13 @@ x=`dd if="$1" bs=1 count=1 skip=2 2>/dev/null | od -t u1 -A n`
size=$(( $x * 512 - 1 ))
# now get the checksum
nums=`od -A n -t u1 -v "$1"`
nums=`od -A n -t u1 -v -N $size "$1"`
for i in ${nums}; do
# add each byte's value to sum
sum=`expr $sum + $i`
sum=`expr \( $sum + $i \) % 256`
done
sum=$(( $sum % 256 ))
sum=$(( 256 - $sum ))
sum=$(( (256 - $sum) % 256 ))
sum_octal=$( printf "%o" $sum )
# and write the output file

Binary file not shown.

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