Commit bec9c64e authored by Peter Maydell's avatar Peter Maydell

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: 's avatarPeter Maydell <peter.maydell@linaro.org>
parents b734ed9d 7524a39d
......@@ -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
......
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/
\ No newline at end of file
......@@ -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) {
......
......@@ -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);
......
......@@ -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]);
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_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);
for (n = 0; n < 2; n++) {
int hci_irq = n ? 79 : 56;
hwaddr hci_addr = n ? 0xE0101000 : 0xE0100000;
DriveInfo *di;
BlockBackend *blk;
DeviceState *carddev;
/* 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]);
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);
......
......@@ -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;
object_property_set_bool(OBJECT(&s->sdhci[i]), true,
"realized", &err);
char *bus_name = g_strdup_printf("sd-bus%d", i);
SysBusDevice *sbd = SYS_BUS_DEVICE(&s->sdhci[i]);
Object *sdhci = OBJECT(&s->sdhci[i]);
/* 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;
......
......@@ -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/
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
/*
* 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,