mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* CAN bus (will be under network maintainner) * scsi-block opblockers (myself) * Dirty log bitmap cleanup (myself) * SDHCI improvements and tests (Philippe) * HAX support for larger guest sizese (Yu Ning) # gpg: Signature made Tue 13 Feb 2018 15:37:14 GMT # gpg: using RSA key BFFBD25F78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: (48 commits) travis: use libgcc-4.8-dev (libgcc-6-dev is not available on Ubuntu 14.04) memory: unify loops to sync dirty log bitmap memory: hide memory_region_sync_dirty_bitmap behind DirtyBitmapSnapshot memory: remove memory_region_test_and_clear_dirty g364fb: switch to using DirtyBitmapSnapshot sdhci: add Spec v4.2 register definitions sdhci: add a check_capab_v3() qtest sdhci: check Spec v3 capabilities qtest hw/arm/xilinx_zynqmp: enable the UHS-I mode hw/arm/xilinx_zynqmp: fix the capabilities/spec version to match the datasheet hw/arm/fsl-imx6: implement SDHCI Spec. v3 hw/arm/bcm2835_peripherals: change maximum block size to 1kB hw/arm/bcm2835_peripherals: implement SDHCI Spec v3 sdhci: implement CMD/DAT[] fields in the Present State register sdhci: implement UHS-I voltage switch sdbus: add trace events sdhci: implement the Host Control 2 register (tuning sequence) sdhci: rename the hostctl1 register sdhci: add support for v3 capabilities hw/arm/xilinx_zynq: fix the capabilities register to match the datasheet ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+1
-1
@@ -13,7 +13,7 @@ addons:
|
||||
- libattr1-dev
|
||||
- libbrlapi-dev
|
||||
- libcap-ng-dev
|
||||
- libgcc-6-dev
|
||||
- libgcc-4.8-dev
|
||||
- libgnutls-dev
|
||||
- libgtk-3-dev
|
||||
- libiscsi-dev
|
||||
|
||||
@@ -294,7 +294,7 @@ else
|
||||
DOCS=
|
||||
endif
|
||||
|
||||
SUBDIR_MAKEFLAGS=BUILD_DIR=$(BUILD_DIR)
|
||||
SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory --quiet) BUILD_DIR=$(BUILD_DIR)
|
||||
SUBDIR_DEVICES_MAK=$(patsubst %, %/config-devices.mak, $(TARGET_DIRS))
|
||||
SUBDIR_DEVICES_MAK_DEP=$(patsubst %, %-config-devices.mak.d, $(TARGET_DIRS))
|
||||
|
||||
@@ -958,4 +958,5 @@ ifdef QEMU_GA_MSI_ENABLED
|
||||
endif
|
||||
@echo ''
|
||||
endif
|
||||
@echo ' $(MAKE) V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'
|
||||
@echo ' $(MAKE) [targets] (quiet build, default)'
|
||||
@echo ' $(MAKE) V=1 [targets] (verbose build)'
|
||||
|
||||
@@ -471,10 +471,8 @@ for opt do
|
||||
--cpu=*) cpu="$optarg"
|
||||
;;
|
||||
--extra-cflags=*) QEMU_CFLAGS="$QEMU_CFLAGS $optarg"
|
||||
EXTRA_CFLAGS="$optarg"
|
||||
;;
|
||||
--extra-cxxflags=*) QEMU_CXXFLAGS="$QEMU_CXXFLAGS $optarg"
|
||||
EXTRA_CXXFLAGS="$optarg"
|
||||
;;
|
||||
--extra-ldflags=*) LDFLAGS="$LDFLAGS $optarg"
|
||||
EXTRA_LDFLAGS="$optarg"
|
||||
@@ -1424,7 +1422,6 @@ case "$cpu" in
|
||||
esac
|
||||
|
||||
QEMU_CFLAGS="$CPU_CFLAGS $QEMU_CFLAGS"
|
||||
EXTRA_CFLAGS="$CPU_CFLAGS $EXTRA_CFLAGS"
|
||||
|
||||
# For user-mode emulation the host arch has to be one we explicitly
|
||||
# support, even if we're using TCI.
|
||||
@@ -5309,7 +5306,15 @@ fi
|
||||
##########################################
|
||||
# checks for sanitizers
|
||||
|
||||
write_c_skeleton
|
||||
# we could use a simple skeleton for flags checks, but this also
|
||||
# detect the static linking issue of ubsan, see also:
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84285
|
||||
cat > $TMPC << EOF
|
||||
#include <stdint.h>
|
||||
int main(void) {
|
||||
return INT32_MIN / -1;
|
||||
}
|
||||
EOF
|
||||
|
||||
have_asan=no
|
||||
have_ubsan=no
|
||||
@@ -5877,9 +5882,6 @@ if test "$mingw32" = "no" ; then
|
||||
echo "qemu_localstatedir=$local_statedir" >> $config_host_mak
|
||||
fi
|
||||
echo "qemu_helperdir=$libexecdir" >> $config_host_mak
|
||||
echo "extra_cflags=$EXTRA_CFLAGS" >> $config_host_mak
|
||||
echo "extra_cxxflags=$EXTRA_CXXFLAGS" >> $config_host_mak
|
||||
echo "extra_ldflags=$EXTRA_LDFLAGS" >> $config_host_mak
|
||||
echo "qemu_localedir=$qemu_localedir" >> $config_host_mak
|
||||
echo "libs_softmmu=$libs_softmmu" >> $config_host_mak
|
||||
echo "GIT=$git" >> $config_host_mak
|
||||
|
||||
@@ -31,6 +31,9 @@ CONFIG_ESP_PCI=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_SERIAL_ISA=y
|
||||
CONFIG_SERIAL_PCI=y
|
||||
CONFIG_CAN_BUS=y
|
||||
CONFIG_CAN_SJA1000=y
|
||||
CONFIG_CAN_PCI=y
|
||||
CONFIG_IPACK=y
|
||||
CONFIG_WDT_IB6300ESB=y
|
||||
CONFIG_PCI_TESTDEV=y
|
||||
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
QEMU CAN bus emulation support
|
||||
==============================
|
||||
|
||||
The CAN bus emulation provides mechanism to connect multiple
|
||||
emulated CAN controller chips together by one or multiple CAN busses
|
||||
(the controller device "canbus" parameter). The individual busses
|
||||
can be connected to host system CAN API (at this time only Linux
|
||||
SocketCAN is supported).
|
||||
|
||||
The concept of busses is generic and different CAN controllers
|
||||
can be implemented for it but at this time only SJA1000 chip
|
||||
controller is implemented.
|
||||
|
||||
The PCI addon card hardware has been selected as the first CAN
|
||||
interface to implement because such device can be easily connected
|
||||
to systems with different CPU architectures (x86, PowerPC, ARM, etc.).
|
||||
|
||||
The project has been initially started in frame of RTEMS GSoC 2013
|
||||
slot by Jin Yang under our mentoring The initial idea was to provide generic
|
||||
CAN subsystem for RTEMS. But lack of common environment for code and RTEMS
|
||||
testing lead to goal change to provide environment which provides complete
|
||||
emulated environment for testing and RTEMS GSoC slot has been donated
|
||||
to work on CAN hardware emulation on QEMU.
|
||||
|
||||
Examples how to use CAN emulation
|
||||
=================================
|
||||
|
||||
When QEMU with CAN PCI support is compiled then one of the next
|
||||
CAN boards can be selected
|
||||
|
||||
(1) CAN bus Kvaser PCI CAN-S (single SJA1000 channel) boad. QEMU startup options
|
||||
-object can-bus,id=canbus0
|
||||
-device kvaser_pci,canbus=canbus0
|
||||
Add "can-host-socketcan" object to connect device to host system CAN bus
|
||||
-object can-host-socketcan,id=canhost0,if=can0,canbus=canbus0
|
||||
|
||||
(2) CAN bus PCM-3680I PCI (dual SJA1000 channel) emulation
|
||||
-object can-bus,id=canbus0
|
||||
-device pcm3680_pci,canbus0=canbus0,canbus1=canbus0
|
||||
|
||||
another example:
|
||||
-object can-bus,id=canbus0
|
||||
-object can-bus,id=canbus1
|
||||
-device pcm3680_pci,canbus0=canbus0,canbus1=canbus1
|
||||
|
||||
(3) CAN bus MIOe-3680 PCI (dual SJA1000 channel) emulation
|
||||
-device mioe3680_pci,canbus0=canbus0
|
||||
|
||||
|
||||
The ''kvaser_pci'' board/device model is compatible with and has been tested with
|
||||
''kvaser_pci'' driver included in mainline Linux kernel.
|
||||
The tested setup was Linux 4.9 kernel on the host and guest side.
|
||||
Example for qemu-system-x86_64:
|
||||
|
||||
qemu-system-x86_64 -enable-kvm -kernel /boot/vmlinuz-4.9.0-4-amd64 \
|
||||
-initrd ramdisk.cpio \
|
||||
-virtfs local,path=shareddir,security_model=none,mount_tag=shareddir \
|
||||
-object can-bus,id=canbus0 \
|
||||
-object can-host-socketcan,id=canhost0,if=can0,canbus=canbus0 \
|
||||
-device kvaser_pci,canbus=canbus0 \
|
||||
-nographic -append "console=ttyS0"
|
||||
|
||||
Example for qemu-system-arm:
|
||||
|
||||
qemu-system-arm -cpu arm1176 -m 256 -M versatilepb \
|
||||
-kernel kernel-qemu-arm1176-versatilepb \
|
||||
-hda rpi-wheezy-overlay \
|
||||
-append "console=ttyAMA0 root=/dev/sda2 ro init=/sbin/init-overlay" \
|
||||
-nographic \
|
||||
-virtfs local,path=shareddir,security_model=none,mount_tag=shareddir \
|
||||
-object can-bus,id=canbus0 \
|
||||
-object can-host-socketcan,id=canhost0,if=can0,canbus=canbus0 \
|
||||
-device kvaser_pci,canbus=canbus0,host=can0 \
|
||||
|
||||
The CAN interface of the host system has to be configured for proper
|
||||
bitrate and set up. Configuration is not propagated from emulated
|
||||
devices through bus to the physical host device. Example configuration
|
||||
for 1 Mbit/s
|
||||
|
||||
ip link set can0 type can bitrate 1000000
|
||||
ip link set can0 up
|
||||
|
||||
Virtual (host local only) can interface can be used on the host
|
||||
side instead of physical interface
|
||||
|
||||
ip link add dev can0 type vcan
|
||||
|
||||
The CAN interface on the host side can be used to analyze CAN
|
||||
traffic with "candump" command which is included in "can-utils".
|
||||
|
||||
candump can0
|
||||
|
||||
Links to other resources
|
||||
========================
|
||||
|
||||
(1) Repository with development branch can-pci at Czech Technical University
|
||||
https://gitlab.fel.cvut.cz/canbus/qemu-canbus
|
||||
(2) GitHub repository with can-pci and our other changes included
|
||||
https://gitlab.fel.cvut.cz/canbus/qemu-canbus
|
||||
(3) RTEMS page describing project
|
||||
https://devel.rtems.org/wiki/Developer/Simulators/QEMU/CANEmulation
|
||||
(4) RTLWS 2015 article about the projevt and its use with CANopen emulation
|
||||
http://rtime.felk.cvut.cz/publications/public/rtlws2015-qemu-can.pdf
|
||||
Slides
|
||||
http://rtime.felk.cvut.cz/publications/public/rtlws2015-qemu-can-slides.pdf
|
||||
(5) Linux SocketCAN utilities
|
||||
https://github.com/linux-can/can-utils/
|
||||
@@ -19,7 +19,7 @@
|
||||
#define BCM2835_VC_PERI_BASE 0x7e000000
|
||||
|
||||
/* Capabilities for SD controller: no DMA, high-speed, default clocks etc. */
|
||||
#define BCM2835_SDHC_CAPAREG 0x52034b4
|
||||
#define BCM2835_SDHC_CAPAREG 0x52134b4
|
||||
|
||||
static void bcm2835_peripherals_init(Object *obj)
|
||||
{
|
||||
@@ -254,14 +254,19 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
|
||||
memory_region_add_subregion(&s->peri_mr, RNG_OFFSET,
|
||||
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0));
|
||||
|
||||
/* Extended Mass Media Controller */
|
||||
object_property_set_int(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg",
|
||||
&err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Extended Mass Media Controller
|
||||
*
|
||||
* Compatible with:
|
||||
* - SD Host Controller Specification Version 3.0 Draft 1.0
|
||||
* - SDIO Specification Version 3.0
|
||||
* - MMC Specification Version 4.4
|
||||
*
|
||||
* For the exact details please refer to the Arasan documentation:
|
||||
* SD3.0_Host_AHB_eMMC4.4_Usersguide_ver5.9_jan11_10.pdf
|
||||
*/
|
||||
object_property_set_uint(OBJECT(&s->sdhci), 3, "sd-spec-version", &err);
|
||||
object_property_set_uint(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg",
|
||||
&err);
|
||||
object_property_set_bool(OBJECT(&s->sdhci), true, "pending-insert-quirk",
|
||||
&err);
|
||||
if (err) {
|
||||
|
||||
+13
-1
@@ -377,8 +377,20 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem)
|
||||
BlockBackend *blk;
|
||||
DriveInfo *di;
|
||||
|
||||
/* Compatible with:
|
||||
* - SD Host Controller Specification Version 2.0
|
||||
* - SDIO Specification Version 2.0
|
||||
* - MMC Specification Version 4.3
|
||||
* - SDMA
|
||||
* - ADMA2
|
||||
*
|
||||
* As this part of the Exynos4210 is not publically available,
|
||||
* we used the "HS-MMC Controller S3C2416X RISC Microprocessor"
|
||||
* public datasheet which is very similar (implementing
|
||||
* MMC Specification Version 4.0 being the only difference noted)
|
||||
*/
|
||||
dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
|
||||
qdev_prop_set_uint32(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES);
|
||||
qdev_prop_set_uint64(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES);
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
busdev = SYS_BUS_DEVICE(dev);
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "chardev/char.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#define IMX6_ESDHC_CAPABILITIES 0x057834b4
|
||||
|
||||
#define NAME_SIZE 20
|
||||
|
||||
static void fsl_imx6_init(Object *obj)
|
||||
@@ -348,6 +350,11 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
|
||||
{ FSL_IMX6_uSDHC4_ADDR, FSL_IMX6_uSDHC4_IRQ },
|
||||
};
|
||||
|
||||
/* UHS-I SDIO3.0 SDR104 1.8V ADMA */
|
||||
object_property_set_uint(OBJECT(&s->esdhc[i]), 3, "sd-spec-version",
|
||||
&err);
|
||||
object_property_set_uint(OBJECT(&s->esdhc[i]), IMX6_ESDHC_CAPABILITIES,
|
||||
"capareg", &err);
|
||||
object_property_set_bool(OBJECT(&s->esdhc[i]), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
|
||||
+27
-22
@@ -61,6 +61,8 @@ static const int dma_irqs[8] = {
|
||||
#define SLCR_XILINX_UNLOCK_KEY 0xdf0d
|
||||
#define SLCR_XILINX_LOCK_KEY 0x767b
|
||||
|
||||
#define ZYNQ_SDHCI_CAPABILITIES 0x69ec0080 /* Datasheet: UG585 (v1.12.1) */
|
||||
|
||||
#define ARMV7_IMM16(x) (extract32((x), 0, 12) | \
|
||||
extract32((x), 12, 4) << 16)
|
||||
|
||||
@@ -165,10 +167,8 @@ static void zynq_init(MachineState *machine)
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
MemoryRegion *ext_ram = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
|
||||
DeviceState *dev, *carddev;
|
||||
DeviceState *dev;
|
||||
SysBusDevice *busdev;
|
||||
DriveInfo *di;
|
||||
BlockBackend *blk;
|
||||
qemu_irq pic[64];
|
||||
int n;
|
||||
|
||||
@@ -247,27 +247,32 @@ static void zynq_init(MachineState *machine)
|
||||
gem_init(&nd_table[0], 0xE000B000, pic[54-IRQ_OFFSET]);
|
||||
gem_init(&nd_table[1], 0xE000C000, pic[77-IRQ_OFFSET]);
|
||||
|
||||
dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
|
||||
qdev_init_nofail(dev);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0100000);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[56-IRQ_OFFSET]);
|
||||
for (n = 0; n < 2; n++) {
|
||||
int hci_irq = n ? 79 : 56;
|
||||
hwaddr hci_addr = n ? 0xE0101000 : 0xE0100000;
|
||||
DriveInfo *di;
|
||||
BlockBackend *blk;
|
||||
DeviceState *carddev;
|
||||
|
||||
di = drive_get_next(IF_SD);
|
||||
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
||||
carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
|
||||
qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
|
||||
object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
|
||||
/* Compatible with:
|
||||
* - SD Host Controller Specification Version 2.0 Part A2
|
||||
* - SDIO Specification Version 2.0
|
||||
* - MMC Specification Version 3.31
|
||||
*/
|
||||
dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
|
||||
qdev_prop_set_uint8(dev, "sd-spec-version", 2);
|
||||
qdev_prop_set_uint64(dev, "capareg", ZYNQ_SDHCI_CAPABILITIES);
|
||||
qdev_init_nofail(dev);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, hci_addr);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[hci_irq - IRQ_OFFSET]);
|
||||
|
||||
dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
|
||||
qdev_init_nofail(dev);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]);
|
||||
|
||||
di = drive_get_next(IF_SD);
|
||||
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
||||
carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
|
||||
qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
|
||||
object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
|
||||
di = drive_get_next(IF_SD);
|
||||
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
||||
carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
|
||||
qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
|
||||
object_property_set_bool(OBJECT(carddev), true, "realized",
|
||||
&error_fatal);
|
||||
}
|
||||
|
||||
dev = qdev_create(NULL, TYPE_ZYNQ_XADC);
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
+18
-10
@@ -53,6 +53,8 @@
|
||||
#define IPI_ADDR 0xFF300000
|
||||
#define IPI_IRQ 64
|
||||
|
||||
#define SDHCI_CAPABILITIES 0x280737ec6481 /* Datasheet: UG1085 (v1.7) */
|
||||
|
||||
static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
|
||||
0xFF0B0000, 0xFF0C0000, 0xFF0D0000, 0xFF0E0000,
|
||||
};
|
||||
@@ -387,22 +389,28 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sata), 0, gic_spi[SATA_INTR]);
|
||||
|
||||
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
|
||||
char *bus_name;
|
||||
char *bus_name = g_strdup_printf("sd-bus%d", i);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(&s->sdhci[i]);
|
||||
Object *sdhci = OBJECT(&s->sdhci[i]);
|
||||
|
||||
object_property_set_bool(OBJECT(&s->sdhci[i]), true,
|
||||
"realized", &err);
|
||||
/* Compatible with:
|
||||
* - SD Host Controller Specification Version 3.00
|
||||
* - SDIO Specification Version 3.0
|
||||
* - eMMC Specification Version 4.51
|
||||
*/
|
||||
object_property_set_uint(sdhci, 3, "sd-spec-version", &err);
|
||||
object_property_set_uint(sdhci, SDHCI_CAPABILITIES, "capareg", &err);
|
||||
object_property_set_uint(sdhci, UHS_I, "uhs", &err);
|
||||
object_property_set_bool(sdhci, true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci[i]), 0,
|
||||
sdhci_addr[i]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci[i]), 0,
|
||||
gic_spi[sdhci_intr[i]]);
|
||||
sysbus_mmio_map(sbd, 0, sdhci_addr[i]);
|
||||
sysbus_connect_irq(sbd, 0, gic_spi[sdhci_intr[i]]);
|
||||
|
||||
/* Alias controller SD bus to the SoC itself */
|
||||
bus_name = g_strdup_printf("sd-bus%d", i);
|
||||
object_property_add_alias(OBJECT(s), bus_name,
|
||||
OBJECT(&s->sdhci[i]), "sd-bus",
|
||||
object_property_add_alias(OBJECT(s), bus_name, sdhci, "sd-bus",
|
||||
&error_abort);
|
||||
g_free(bus_name);
|
||||
}
|
||||
|
||||
@@ -108,7 +108,6 @@ static void cg3_update_display(void *opaque)
|
||||
data = (uint32_t *)surface_data(surface);
|
||||
|
||||
if (!s->full_update) {
|
||||
memory_region_sync_dirty_bitmap(&s->vram_mem);
|
||||
snap = memory_region_snapshot_and_clear_dirty(&s->vram_mem, 0x0,
|
||||
memory_region_size(&s->vram_mem),
|
||||
DIRTY_MEMORY_VGA);
|
||||
|
||||
@@ -1289,7 +1289,6 @@ static void exynos4210_fimd_update(void *opaque)
|
||||
scrn_width = w->virtpage_width;
|
||||
/* Total width of virtual screen page in bytes */
|
||||
inc_size = scrn_width + w->virtpage_offsize;
|
||||
memory_region_sync_dirty_bitmap(w->mem_section.mr);
|
||||
host_fb_addr = w->host_fb_addr;
|
||||
fb_line_addr = w->mem_section.offset_within_region;
|
||||
snap = memory_region_snapshot_and_clear_dirty(w->mem_section.mr,
|
||||
|
||||
@@ -83,7 +83,6 @@ void framebuffer_update_display(
|
||||
if (!mem) {
|
||||
return;
|
||||
}
|
||||
memory_region_sync_dirty_bitmap(mem);
|
||||
|
||||
addr = mem_section->offset_within_region;
|
||||
src = memory_region_get_ram_ptr(mem) + addr;
|
||||
|
||||
+6
-5
@@ -62,15 +62,15 @@ typedef struct G364State {
|
||||
|
||||
#define G364_PAGE_SIZE 4096
|
||||
|
||||
static inline int check_dirty(G364State *s, ram_addr_t page)
|
||||
static inline int check_dirty(G364State *s, DirtyBitmapSnapshot *snap, ram_addr_t page)
|
||||
{
|
||||
return memory_region_test_and_clear_dirty(&s->mem_vram, page, G364_PAGE_SIZE,
|
||||
DIRTY_MEMORY_VGA);
|
||||
return memory_region_snapshot_get_dirty(&s->mem_vram, snap, page, G364_PAGE_SIZE);
|
||||
}
|
||||
|
||||
static void g364fb_draw_graphic8(G364State *s)
|
||||
{
|
||||
DisplaySurface *surface = qemu_console_surface(s->con);
|
||||
DirtyBitmapSnapshot *snap;
|
||||
int i, w;
|
||||
uint8_t *vram;
|
||||
uint8_t *data_display, *dd;
|
||||
@@ -122,8 +122,10 @@ static void g364fb_draw_graphic8(G364State *s)
|
||||
vram = s->vram + s->top_of_screen;
|
||||
/* XXX: out of range in vram? */
|
||||
data_display = dd = surface_data(surface);
|
||||
snap = memory_region_snapshot_and_clear_dirty(&s->mem_vram, 0, s->vram_size,
|
||||
DIRTY_MEMORY_VGA);
|
||||
while (y < s->height) {
|
||||
if (check_dirty(s, page)) {
|
||||
if (check_dirty(s, snap, page)) {
|
||||
if (y < ymin)
|
||||
ymin = ymax = y;
|
||||
if (x < xmin)
|
||||
@@ -244,7 +246,6 @@ static void g364fb_update_display(void *opaque)
|
||||
qemu_console_resize(s->con, s->width, s->height);
|
||||
}
|
||||
|
||||
memory_region_sync_dirty_bitmap(&s->mem_vram);
|
||||
if (s->ctla & CTLA_FORCE_BLANK) {
|
||||
g364fb_draw_blank(s);
|
||||
} else if (s->depth == 8) {
|
||||
|
||||
@@ -1508,7 +1508,6 @@ static void sm501_update_display(void *opaque)
|
||||
}
|
||||
|
||||
/* draw each line according to conditions */
|
||||
memory_region_sync_dirty_bitmap(&s->local_mem_region);
|
||||
snap = memory_region_snapshot_and_clear_dirty(&s->local_mem_region,
|
||||
offset, width * height * src_bpp, DIRTY_MEMORY_VGA);
|
||||
for (y = 0, offset = 0; y < height; y++, offset += width * src_bpp) {
|
||||
|
||||
@@ -236,7 +236,6 @@ static void tcx_update_display(void *opaque)
|
||||
dd = surface_stride(surface);
|
||||
ds = 1024;
|
||||
|
||||
memory_region_sync_dirty_bitmap(&ts->vram_mem);
|
||||
snap = memory_region_snapshot_and_clear_dirty(&ts->vram_mem, 0x0,
|
||||
memory_region_size(&ts->vram_mem),
|
||||
DIRTY_MEMORY_VGA);
|
||||
@@ -292,7 +291,6 @@ static void tcx24_update_display(void *opaque)
|
||||
dd = surface_stride(surface);
|
||||
ds = 1024;
|
||||
|
||||
memory_region_sync_dirty_bitmap(&ts->vram_mem);
|
||||
snap = memory_region_snapshot_and_clear_dirty(&ts->vram_mem, 0x0,
|
||||
memory_region_size(&ts->vram_mem),
|
||||
DIRTY_MEMORY_VGA);
|
||||
|
||||
@@ -1444,11 +1444,6 @@ static bool vga_scanline_invalidated(VGACommonState *s, int y)
|
||||
return s->invalidated_y_table[y >> 5] & (1 << (y & 0x1f));
|
||||
}
|
||||
|
||||
void vga_sync_dirty_bitmap(VGACommonState *s)
|
||||
{
|
||||
memory_region_sync_dirty_bitmap(&s->vram);
|
||||
}
|
||||
|
||||
void vga_dirty_log_start(VGACommonState *s)
|
||||
{
|
||||
memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
|
||||
@@ -1638,7 +1633,6 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
||||
y1 = 0;
|
||||
|
||||
if (!full_update) {
|
||||
vga_sync_dirty_bitmap(s);
|
||||
if (s->line_compare < height) {
|
||||
/* split screen mode */
|
||||
region_start = 0;
|
||||
|
||||
@@ -46,3 +46,5 @@ common-obj-$(CONFIG_ROCKER) += rocker/rocker.o rocker/rocker_fp.o \
|
||||
rocker/rocker_desc.o rocker/rocker_world.o \
|
||||
rocker/rocker_of_dpa.o
|
||||
obj-$(call lnot,$(CONFIG_ROCKER)) += rocker/qmp-norocker.o
|
||||
|
||||
common-obj-$(CONFIG_CAN_BUS) += can/
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
common-obj-$(CONFIG_CAN_SJA1000) += can_sja1000.o
|
||||
common-obj-$(CONFIG_CAN_PCI) += can_kvaser_pci.o
|
||||
common-obj-$(CONFIG_CAN_PCI) += can_pcm3680_pci.o
|
||||
common-obj-$(CONFIG_CAN_PCI) += can_mioe3680_pci.o
|
||||
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Kvaser PCI CAN device (SJA1000 based) emulation
|
||||
*
|
||||
* Copyright (c) 2013-2014 Jin Yang
|
||||
* Copyright (c) 2014-2018 Pavel Pisa
|
||||
*
|
||||
* Partially based on educational PCIexpress APOHW hardware
|
||||
* emulator used fro class A0B36APO at CTU FEE course by
|
||||
* Rostislav Lisovy and Pavel Pisa
|
||||
*
|
||||
* Initial development supported by Google GSoC 2013 from RTEMS project slot
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/event_notifier.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "qapi/error.h"
|
||||
#include "chardev/char.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "net/can_emu.h"
|
||||
|
||||
#include "can_sja1000.h"
|
||||
|
||||
#define TYPE_CAN_PCI_DEV "kvaser_pci"
|
||||
|
||||
#define KVASER_PCI_DEV(obj) \
|
||||
OBJECT_CHECK(KvaserPCIState, (obj), TYPE_CAN_PCI_DEV)
|
||||
|
||||
#ifndef KVASER_PCI_VENDOR_ID1
|
||||
#define KVASER_PCI_VENDOR_ID1 0x10e8 /* the PCI device and vendor IDs */
|
||||
#endif
|
||||
|
||||
#ifndef KVASER_PCI_DEVICE_ID1
|
||||
#define KVASER_PCI_DEVICE_ID1 0x8406
|
||||
#endif
|
||||
|
||||
#define KVASER_PCI_S5920_RANGE 0x80
|
||||
#define KVASER_PCI_SJA_RANGE 0x80
|
||||
#define KVASER_PCI_XILINX_RANGE 0x8
|
||||
|
||||
#define KVASER_PCI_BYTES_PER_SJA 0x20
|
||||
|
||||
#define S5920_OMB 0x0C
|
||||
#define S5920_IMB 0x1C
|
||||
#define S5920_MBEF 0x34
|
||||
#define S5920_INTCSR 0x38
|
||||
#define S5920_RCR 0x3C
|
||||
#define S5920_PTCR 0x60
|
||||
|
||||
#define S5920_INTCSR_ADDON_INTENABLE_M 0x2000
|
||||
#define S5920_INTCSR_INTERRUPT_ASSERTED_M 0x800000
|
||||
|
||||
#define KVASER_PCI_XILINX_VERINT 7 /* Lower nibble simulate interrupts,
|
||||
high nibble version number. */
|
||||
|
||||
#define KVASER_PCI_XILINX_VERSION_NUMBER 13
|
||||
|
||||
typedef struct KvaserPCIState {
|
||||
/*< private >*/
|
||||
PCIDevice dev;
|
||||
/*< public >*/
|
||||
MemoryRegion s5920_io;
|
||||
MemoryRegion sja_io;
|
||||
MemoryRegion xilinx_io;
|
||||
|
||||
CanSJA1000State sja_state;
|
||||
qemu_irq irq;
|
||||
|
||||
uint32_t s5920_intcsr;
|
||||
uint32_t s5920_irqstate;
|
||||
|
||||
CanBusState *canbus;
|
||||
} KvaserPCIState;
|
||||
|
||||
static void kvaser_pci_irq_handler(void *opaque, int irq_num, int level)
|
||||
{
|
||||
KvaserPCIState *d = (KvaserPCIState *)opaque;
|
||||
|
||||
d->s5920_irqstate = level;
|
||||
if (d->s5920_intcsr & S5920_INTCSR_ADDON_INTENABLE_M) {
|
||||
pci_set_irq(&d->dev, level);
|
||||
}
|
||||
}
|
||||
|
||||
static void kvaser_pci_reset(DeviceState *dev)
|
||||
{
|
||||
KvaserPCIState *d = KVASER_PCI_DEV(dev);
|
||||
CanSJA1000State *s = &d->sja_state;
|
||||
|
||||
can_sja_hardware_reset(s);
|
||||
}
|
||||
|
||||
static uint64_t kvaser_pci_s5920_io_read(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
{
|
||||
KvaserPCIState *d = opaque;
|
||||
uint64_t val;
|
||||
|
||||
switch (addr) {
|
||||
case S5920_INTCSR:
|
||||
val = d->s5920_intcsr;
|
||||
val &= ~S5920_INTCSR_INTERRUPT_ASSERTED_M;
|
||||
if (d->s5920_irqstate) {
|
||||
val |= S5920_INTCSR_INTERRUPT_ASSERTED_M;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kvaser_pci_s5920_io_write(void *opaque, hwaddr addr, uint64_t data,
|
||||
unsigned size)
|
||||
{
|
||||
KvaserPCIState *d = opaque;
|
||||
|
||||
switch (addr) {
|
||||
case S5920_INTCSR:
|
||||
if (d->s5920_irqstate &&
|
||||
((d->s5920_intcsr ^ data) & S5920_INTCSR_ADDON_INTENABLE_M)) {
|
||||
pci_set_irq(&d->dev, !!(data & S5920_INTCSR_ADDON_INTENABLE_M));
|
||||
}
|
||||
d->s5920_intcsr = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t kvaser_pci_sja_io_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
KvaserPCIState *d = opaque;
|
||||
CanSJA1000State *s = &d->sja_state;
|
||||
|
||||
if (addr >= KVASER_PCI_BYTES_PER_SJA) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return can_sja_mem_read(s, addr, size);
|
||||
}
|
||||
|
||||
static void kvaser_pci_sja_io_write(void *opaque, hwaddr addr, uint64_t data,
|
||||
unsigned size)
|
||||
{
|
||||
KvaserPCIState *d = opaque;
|
||||
CanSJA1000State *s = &d->sja_state;
|
||||
|
||||
if (addr >= KVASER_PCI_BYTES_PER_SJA) {
|
||||
return;
|
||||
}
|
||||
|
||||
can_sja_mem_write(s, addr, data, size);
|
||||
}
|
||||
|
||||
static uint64_t kvaser_pci_xilinx_io_read(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
{
|
||||
switch (addr) {
|
||||
case KVASER_PCI_XILINX_VERINT:
|
||||
return (KVASER_PCI_XILINX_VERSION_NUMBER << 4) | 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kvaser_pci_xilinx_io_write(void *opaque, hwaddr addr, uint64_t data,
|
||||
unsigned size)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static const MemoryRegionOps kvaser_pci_s5920_io_ops = {
|
||||
.read = kvaser_pci_s5920_io_read,
|
||||
.write = kvaser_pci_s5920_io_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.impl = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4,
|
||||
},
|
||||
};
|
||||
|
||||
static const MemoryRegionOps kvaser_pci_sja_io_ops = {
|
||||
.read = kvaser_pci_sja_io_read,
|
||||
.write = kvaser_pci_sja_io_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.impl = {
|
||||
.max_access_size = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static const MemoryRegionOps kvaser_pci_xilinx_io_ops = {
|
||||
.read = kvaser_pci_xilinx_io_read,
|
||||
.write = kvaser_pci_xilinx_io_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.impl = {
|
||||
.max_access_size = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static void kvaser_pci_realize(PCIDevice *pci_dev, Error **errp)
|
||||
{
|
||||
KvaserPCIState *d = KVASER_PCI_DEV(pci_dev);
|
||||
CanSJA1000State *s = &d->sja_state;
|
||||
uint8_t *pci_conf;
|
||||
|
||||
pci_conf = pci_dev->config;
|
||||
pci_conf[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
|
||||
|
||||
d->irq = qemu_allocate_irq(kvaser_pci_irq_handler, d, 0);
|
||||
|
||||
can_sja_init(s, d->irq);
|
||||
|
||||
if (can_sja_connect_to_bus(s, d->canbus) < 0) {
|
||||
error_setg(errp, "can_sja_connect_to_bus failed");
|
||||
return;
|
||||
}
|
||||
|
||||
memory_region_init_io(&d->s5920_io, OBJECT(d), &kvaser_pci_s5920_io_ops,
|
||||
d, "kvaser_pci-s5920", KVASER_PCI_S5920_RANGE);
|
||||
memory_region_init_io(&d->sja_io, OBJECT(d), &kvaser_pci_sja_io_ops,
|
||||
d, "kvaser_pci-sja", KVASER_PCI_SJA_RANGE);
|
||||
memory_region_init_io(&d->xilinx_io, OBJECT(d), &kvaser_pci_xilinx_io_ops,
|
||||
d, "kvaser_pci-xilinx", KVASER_PCI_XILINX_RANGE);
|
||||
|
||||
pci_register_bar(&d->dev, /*BAR*/ 0, PCI_BASE_ADDRESS_SPACE_IO,
|
||||
&d->s5920_io);
|
||||
pci_register_bar(&d->dev, /*BAR*/ 1, PCI_BASE_ADDRESS_SPACE_IO,
|
||||
&d->sja_io);
|
||||
pci_register_bar(&d->dev, /*BAR*/ 2, PCI_BASE_ADDRESS_SPACE_IO,
|
||||
&d->xilinx_io);
|
||||
}
|
||||
|
||||
static void kvaser_pci_exit(PCIDevice *pci_dev)
|
||||
{
|
||||
KvaserPCIState *d = KVASER_PCI_DEV(pci_dev);
|
||||
CanSJA1000State *s = &d->sja_state;
|
||||
|
||||
can_sja_disconnect(s);
|
||||
|
||||
qemu_free_irq(d->irq);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_kvaser_pci = {
|
||||
.name = "kvaser_pci",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.minimum_version_id_old = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_PCI_DEVICE(dev, KvaserPCIState),
|
||||
/* Load this before sja_state. */
|
||||
VMSTATE_UINT32(s5920_intcsr, KvaserPCIState),
|
||||
VMSTATE_STRUCT(sja_state, KvaserPCIState, 0, vmstate_can_sja,
|
||||
CanSJA1000State),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void kvaser_pci_instance_init(Object *obj)
|
||||
{
|
||||
KvaserPCIState *d = KVASER_PCI_DEV(obj);
|
||||
|
||||
object_property_add_link(obj, "canbus", TYPE_CAN_BUS,
|
||||
(Object **)&d->canbus,
|
||||
qdev_prop_allow_set_link_before_realize,
|
||||
0, &error_abort);
|
||||
}
|
||||
|
||||
static void kvaser_pci_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
k->realize = kvaser_pci_realize;
|
||||
k->exit = kvaser_pci_exit;
|
||||
k->vendor_id = KVASER_PCI_VENDOR_ID1;
|
||||
k->device_id = KVASER_PCI_DEVICE_ID1;
|
||||
k->revision = 0x00;
|
||||
k->class_id = 0x00ff00;
|
||||
dc->desc = "Kvaser PCICANx";
|
||||
dc->vmsd = &vmstate_kvaser_pci;
|
||||
dc->reset = kvaser_pci_reset;
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo kvaser_pci_info = {
|
||||
.name = TYPE_CAN_PCI_DEV,
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(KvaserPCIState),
|
||||
.class_init = kvaser_pci_class_init,
|
||||
.instance_init = kvaser_pci_instance_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static void kvaser_pci_register_types(void)
|
||||
{
|
||||
type_register_static(&kvaser_pci_info);
|
||||
}
|
||||
|
||||
type_init(kvaser_pci_register_types)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user