mirror of https://github.com/xemu-project/xemu.git
Misc HW & UI patches
- Remove deprecated SH4 SHIX machine TC58128 NAND EEPROM (Phil) - Remove deprecated CRIS target (Phil) - Remove deprecated RISC-V 'any' CPU type (Phil) - Add fifo8_peek_buf() to correctly handle FIFO wraparound (Mark) - Minor cleanups in Designware PCIe, PL011 and loongson IPI models (Phil) - Fixes in TI TMP105 temperature (Guenter) - Convert Sun ESCC and ADB mouses to QemuInputHandler (Mark) - Prevent heap overflow in VIRTIO sound device (Volker) - Cleanups around g_assert_not_reached() call (Pierrick) - Add Clément as VT-d reviewer (Clément) - Prevent stuck modifier keys and unexpected text input on Windows (Volker) - Explicitly set SDL2 swap interval when OpenGL is enabled (Gert) -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmbkoOUACgkQ4+MsLN6t wN56SBAA1nYl5YTI0BwvToKysoNIJ5aTgDEbT87XYTatKYyWYlN5W1yrAeMcuwFO Rw8edtn2YY89ZMG/LPcY1h6+nI2qVMpuOzNP3ve4D+eM6AMUMX0bzeqXndUind7c 1kTcV7Wctfk34zzs5B9GIU0WswSSbL3FeETS47ySNg6J7GbVWIu41dh52oeg8XWa Zfw0FZDt7hSAbsUckBIC9/Nbh0hucxBnQevQLkVb6u8O0yX3wV2OZRIC7+NkvHkH ZLPT8lg197PitH0NouUJI5oMv5Ty3PXGHtrIAKvts+fGBpWL+XzEtQmT8RzqgxTl 9Z6C/PvfMHNtA7BE66D4iLOKBPpV0RCUDOAGsfcWy5GuklzeUy03DxZ/2xO8XERm TP0EP0nt2YddnELX7H65b78gJkPvnhME/MtA6Y6R7uxAA8gawZVWZQ1oDGUBNGDI zJ62Cu4nYPwpGiewwb+ZTkjeiaYddJsPNsE8f8d4XZCpTwpIM/oYzJapxedBwjrg a4eAWiy7xIvvGPxWN7IQPosGYcyO6zhbI+iAbxp1xmWsX0TPgLUcJtK9+pklqWS7 9ucrvkq5XRZSJMaGF0LZuZH7Qx6us7m0rik5wG96d8qrIXRpi8kXfWxI17SWQkGa cG91u+FrKmfBr+yD7Q1gVbaYzkD+X1hPkQmSVmnlNS+5axrnSYQ= =sPwb -----END PGP SIGNATURE----- Merge tag 'hw-misc-20240913' of https://github.com/philmd/qemu into staging Misc HW & UI patches - Remove deprecated SH4 SHIX machine TC58128 NAND EEPROM (Phil) - Remove deprecated CRIS target (Phil) - Remove deprecated RISC-V 'any' CPU type (Phil) - Add fifo8_peek_buf() to correctly handle FIFO wraparound (Mark) - Minor cleanups in Designware PCIe, PL011 and loongson IPI models (Phil) - Fixes in TI TMP105 temperature (Guenter) - Convert Sun ESCC and ADB mouses to QemuInputHandler (Mark) - Prevent heap overflow in VIRTIO sound device (Volker) - Cleanups around g_assert_not_reached() call (Pierrick) - Add Clément as VT-d reviewer (Clément) - Prevent stuck modifier keys and unexpected text input on Windows (Volker) - Explicitly set SDL2 swap interval when OpenGL is enabled (Gert) # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmbkoOUACgkQ4+MsLN6t # wN56SBAA1nYl5YTI0BwvToKysoNIJ5aTgDEbT87XYTatKYyWYlN5W1yrAeMcuwFO # Rw8edtn2YY89ZMG/LPcY1h6+nI2qVMpuOzNP3ve4D+eM6AMUMX0bzeqXndUind7c # 1kTcV7Wctfk34zzs5B9GIU0WswSSbL3FeETS47ySNg6J7GbVWIu41dh52oeg8XWa # Zfw0FZDt7hSAbsUckBIC9/Nbh0hucxBnQevQLkVb6u8O0yX3wV2OZRIC7+NkvHkH # ZLPT8lg197PitH0NouUJI5oMv5Ty3PXGHtrIAKvts+fGBpWL+XzEtQmT8RzqgxTl # 9Z6C/PvfMHNtA7BE66D4iLOKBPpV0RCUDOAGsfcWy5GuklzeUy03DxZ/2xO8XERm # TP0EP0nt2YddnELX7H65b78gJkPvnhME/MtA6Y6R7uxAA8gawZVWZQ1oDGUBNGDI # zJ62Cu4nYPwpGiewwb+ZTkjeiaYddJsPNsE8f8d4XZCpTwpIM/oYzJapxedBwjrg # a4eAWiy7xIvvGPxWN7IQPosGYcyO6zhbI+iAbxp1xmWsX0TPgLUcJtK9+pklqWS7 # 9ucrvkq5XRZSJMaGF0LZuZH7Qx6us7m0rik5wG96d8qrIXRpi8kXfWxI17SWQkGa # cG91u+FrKmfBr+yD7Q1gVbaYzkD+X1hPkQmSVmnlNS+5axrnSYQ= # =sPwb # -----END PGP SIGNATURE----- # gpg: Signature made Fri 13 Sep 2024 21:30:29 BST # gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE # gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full] # Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE * tag 'hw-misc-20240913' of https://github.com/philmd/qemu: (60 commits) ui: remove break after g_assert_not_reached() ui/sdl2: set swap interval explicitly when OpenGL is enabled ui/sdl2: ignore GUI keys in SDL_TEXTINPUT handler ui/sdl2: release all modifiers system: replace assert(0) with g_assert_not_reached() hw/pci-host: remove break after g_assert_not_reached() hw/misc: remove break after g_assert_not_reached() hw/gpio: remove break after g_assert_not_reached() hw/watchdog: replace assert(0) with g_assert_not_reached() hw/core: replace assert(0) with g_assert_not_reached() hw/char: replace assert(0) with g_assert_not_reached() hw/input/adb-mouse: convert to use QemuInputHandler hw/char/escc: convert Sun mouse to use QemuInputHandler hw/sensor/tmp105: Lower 4 bit of limit registers are always 0 hw/sensor/tmp105: OS (one-shot) bit in config register always returns 0 hw/sensor/tmp105: Pass 'oneshot' argument to tmp105_alarm_update() hw/sensor/tmp105: Use registerfields API hw/sensor/tmp105: Coding style fixes tests/unit: Comment FIFO8 tests tests/unit: Expand test_fifo8_peek_buf_wrap() coverage ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
ea9cdbcf3a
|
@ -675,7 +675,7 @@ build-without-defaults:
|
|||
--disable-pie
|
||||
--disable-qom-cast-debug
|
||||
--disable-strip
|
||||
TARGETS: alpha-softmmu avr-softmmu cris-softmmu hppa-softmmu m68k-softmmu
|
||||
TARGETS: alpha-softmmu avr-softmmu hppa-softmmu m68k-softmmu
|
||||
mips-softmmu mips64-softmmu mipsel-softmmu mips64el-softmmu
|
||||
ppc-softmmu s390x-softmmu sh4-softmmu sh4eb-softmmu sparc-softmmu
|
||||
sparc64-softmmu tricore-softmmu xtensa-softmmu xtensaeb-softmmu
|
||||
|
|
|
@ -90,11 +90,6 @@ xtensa-debian-cross-container:
|
|||
variables:
|
||||
NAME: debian-xtensa-cross
|
||||
|
||||
cris-fedora-cross-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
NAME: fedora-cris-cross
|
||||
|
||||
win64-fedora-cross-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
- ccache --zero-stats
|
||||
- ../configure --enable-werror --disable-docs --enable-fdt=system
|
||||
--disable-user $QEMU_CONFIGURE_OPTS $EXTRA_CONFIGURE_OPTS
|
||||
--target-list-exclude="arm-softmmu cris-softmmu
|
||||
--target-list-exclude="arm-softmmu
|
||||
i386-softmmu microblaze-softmmu mips-softmmu mipsel-softmmu
|
||||
mips64-softmmu ppc-softmmu riscv32-softmmu sh4-softmmu
|
||||
sparc-softmmu xtensa-softmmu $CROSS_SKIP_TARGETS"
|
||||
|
@ -73,7 +73,7 @@
|
|||
- cd build
|
||||
- ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||
--disable-system --target-list-exclude="aarch64_be-linux-user
|
||||
alpha-linux-user cris-linux-user m68k-linux-user microblazeel-linux-user
|
||||
alpha-linux-user m68k-linux-user microblazeel-linux-user
|
||||
or1k-linux-user ppc-linux-user sparc-linux-user
|
||||
xtensa-linux-user $CROSS_SKIP_TARGETS"
|
||||
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
|
||||
|
|
24
MAINTAINERS
24
MAINTAINERS
|
@ -227,10 +227,6 @@ F: tests/functional/test_avr_mega2560.py
|
|||
CRIS TCG CPUs
|
||||
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||
S: Maintained
|
||||
F: target/cris/
|
||||
F: hw/cris/
|
||||
F: include/hw/cris/
|
||||
F: tests/tcg/cris/
|
||||
F: disas/cris.c
|
||||
|
||||
Hexagon TCG CPUs
|
||||
|
@ -1215,14 +1211,6 @@ M: Philippe Mathieu-Daudé <philmd@linaro.org>
|
|||
S: Maintained
|
||||
F: hw/avr/arduino.c
|
||||
|
||||
CRIS Machines
|
||||
-------------
|
||||
Axis Dev88
|
||||
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||
S: Maintained
|
||||
F: hw/cris/axis_dev88.c
|
||||
F: hw/*/etraxfs_*.c
|
||||
|
||||
HP-PARISC Machines
|
||||
------------------
|
||||
HP B160L, HP C3700
|
||||
|
@ -1688,17 +1676,6 @@ F: hw/timer/sh_timer.c
|
|||
F: include/hw/sh4/sh_intc.h
|
||||
F: include/hw/timer/tmu012.h
|
||||
|
||||
Shix
|
||||
R: Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
R: Magnus Damm <magnus.damm@gmail.com>
|
||||
S: Odd Fixes
|
||||
F: hw/block/tc58128.c
|
||||
F: hw/char/sh_serial.c
|
||||
F: hw/sh4/shix.c
|
||||
F: hw/intc/sh_intc.c
|
||||
F: hw/timer/sh_timer.c
|
||||
F: include/hw/sh4/sh_intc.h
|
||||
|
||||
SPARC Machines
|
||||
--------------
|
||||
Sun4m
|
||||
|
@ -3690,6 +3667,7 @@ VT-d Emulation
|
|||
M: Michael S. Tsirkin <mst@redhat.com>
|
||||
R: Jason Wang <jasowang@redhat.com>
|
||||
R: Yi Liu <yi.l.liu@intel.com>
|
||||
R: Clément Mathieu--Drif <clement.mathieu--drif@eviden.com>
|
||||
S: Supported
|
||||
F: hw/i386/intel_iommu.c
|
||||
F: hw/i386/intel_iommu_internal.h
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
# Default configuration for cris-softmmu
|
||||
|
||||
# Boards are selected by default, uncomment to keep out of the build.
|
||||
# CONFIG_AXIS=n
|
|
@ -7,4 +7,3 @@
|
|||
|
||||
# Boards are selected by default, uncomment to keep out of the build.
|
||||
# CONFIG_R2D=n
|
||||
# CONFIG_SHIX=n
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
TARGET_ARCH=cris
|
|
@ -1 +0,0 @@
|
|||
TARGET_ARCH=cris
|
|
@ -1250,7 +1250,6 @@ probe_target_compiler() {
|
|||
aarch64) container_hosts="x86_64 aarch64" ;;
|
||||
alpha) container_hosts=x86_64 ;;
|
||||
arm) container_hosts="x86_64 aarch64" ;;
|
||||
cris) container_hosts=x86_64 ;;
|
||||
hexagon) container_hosts=x86_64 ;;
|
||||
hppa) container_hosts=x86_64 ;;
|
||||
i386) container_hosts=x86_64 ;;
|
||||
|
@ -1309,9 +1308,6 @@ probe_target_compiler() {
|
|||
container_image=debian-armhf-cross
|
||||
container_cross_prefix=arm-linux-gnueabihf-
|
||||
;;
|
||||
cris)
|
||||
container_image=fedora-cris-cross
|
||||
;;
|
||||
hexagon)
|
||||
container_cross_prefix=hexagon-unknown-linux-musl-
|
||||
container_cross_cc=${container_cross_prefix}clang
|
||||
|
|
|
@ -206,14 +206,6 @@ in the QEMU object model anymore. ``Sun-UltraSparc-IIIi+`` and
|
|||
but for consistency these will get removed in a future release, too.
|
||||
Use ``Sun-UltraSparc-IIIi-plus`` and ``Sun-UltraSparc-IV-plus`` instead.
|
||||
|
||||
CRIS CPU architecture (since 9.0)
|
||||
'''''''''''''''''''''''''''''''''
|
||||
|
||||
The CRIS architecture was pulled from Linux in 4.17 and the compiler
|
||||
is no longer packaged in any distro making it harder to run the
|
||||
``check-tcg`` tests. Unless we can improve the testing situation there
|
||||
is a chance the code will bitrot without anyone noticing.
|
||||
|
||||
System emulator machines
|
||||
------------------------
|
||||
|
||||
|
@ -232,12 +224,6 @@ These old machine types are quite neglected nowadays and thus might have
|
|||
various pitfalls with regards to live migration. Use a newer machine type
|
||||
instead.
|
||||
|
||||
``shix`` (since 9.0)
|
||||
''''''''''''''''''''
|
||||
|
||||
The machine is no longer in existence and has been long unmaintained
|
||||
in QEMU. This also holds for the TC51828 16MiB flash that it uses.
|
||||
|
||||
``pseries-2.1`` up to ``pseries-2.12`` (since 9.0)
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
|
@ -347,19 +333,6 @@ QEMU's ``vhost`` feature, which would eliminate the high latency costs under
|
|||
which the 9p ``proxy`` backend currently suffers. However as of to date nobody
|
||||
has indicated plans for such kind of reimplementation unfortunately.
|
||||
|
||||
RISC-V 'any' CPU type ``-cpu any`` (since 8.2)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The 'any' CPU type was introduced back in 2018 and has been around since the
|
||||
initial RISC-V QEMU port. Its usage has always been unclear: users don't know
|
||||
what to expect from a CPU called 'any', and in fact the CPU does not do anything
|
||||
special that isn't already done by the default CPUs rv32/rv64.
|
||||
|
||||
After the introduction of the 'max' CPU type, RISC-V now has a good coverage
|
||||
of generic CPUs: rv32 and rv64 as default CPUs and 'max' as a feature complete
|
||||
CPU for both 32 and 64 bit builds. Users are then discouraged to use the 'any'
|
||||
CPU type starting in 8.2.
|
||||
|
||||
RISC-V CPU properties which start with capital 'Z' (since 8.2)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -26,10 +26,6 @@ depending on the guest architecture.
|
|||
- :ref:`Yes<AVR-System-emulator>`
|
||||
- No
|
||||
- 8 bit micro controller, often used in maker projects
|
||||
* - Cris
|
||||
- Yes
|
||||
- Yes
|
||||
- Embedded RISC chip developed by AXIS
|
||||
* - Hexagon
|
||||
- No
|
||||
- Yes
|
||||
|
|
|
@ -850,6 +850,14 @@ The RISC-V no MMU cpus have been removed. The two CPUs: ``rv32imacu-nommu`` and
|
|||
``rv64imacu-nommu`` can no longer be used. Instead the MMU status can be specified
|
||||
via the CPU ``mmu`` option when using the ``rv32`` or ``rv64`` CPUs.
|
||||
|
||||
RISC-V 'any' CPU type ``-cpu any`` (removed in 9.2)
|
||||
'''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
The 'any' CPU type was introduced back in 2018 and was around since the
|
||||
initial RISC-V QEMU port. Its usage was always been unclear: users don't know
|
||||
what to expect from a CPU called 'any', and in fact the CPU does not do anything
|
||||
special that isn't already done by the default CPUs rv32/rv64.
|
||||
|
||||
``compat`` property of server class POWER CPUs (removed in 6.0)
|
||||
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
|
@ -889,6 +897,13 @@ Nios II CPU (removed in 9.1)
|
|||
QEMU Nios II architecture was orphan; Intel has EOL'ed the Nios II
|
||||
processor IP (see `Intel discontinuance notification`_).
|
||||
|
||||
CRIS CPU architecture (removed in 9.2)
|
||||
''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
The CRIS architecture was pulled from Linux in 4.17 and the compiler
|
||||
was no longer packaged in any distro making it harder to run the
|
||||
``check-tcg`` tests.
|
||||
|
||||
System accelerators
|
||||
-------------------
|
||||
|
||||
|
@ -978,6 +993,11 @@ Nios II ``10m50-ghrd`` and ``nios2-generic-nommu`` machines (removed in 9.1)
|
|||
|
||||
The Nios II architecture was orphan.
|
||||
|
||||
``shix`` (removed in 9.2)
|
||||
'''''''''''''''''''''''''
|
||||
|
||||
The machine was unmaintained.
|
||||
|
||||
linux-user mode CPUs
|
||||
--------------------
|
||||
|
||||
|
|
|
@ -130,10 +130,6 @@ Other binaries
|
|||
|
||||
The binary format is detected automatically.
|
||||
|
||||
- user mode (Cris)
|
||||
|
||||
* ``qemu-cris`` TODO.
|
||||
|
||||
- user mode (i386)
|
||||
|
||||
* ``qemu-i386`` TODO.
|
||||
|
|
|
@ -151,8 +151,8 @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
|
|||
#else
|
||||
/*
|
||||
* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
|
||||
* S390, SH4, TriCore, and Xtensa. Our other supported targets,
|
||||
* such CRIS, do not have floating-point.
|
||||
* S390, SH4, TriCore, and Xtensa. Our other supported targets
|
||||
* do not have floating-point.
|
||||
*/
|
||||
if (snan_bit_is_one(status)) {
|
||||
/* set all bits other than msb */
|
||||
|
|
|
@ -50,7 +50,6 @@ source arm/Kconfig
|
|||
source cpu/Kconfig
|
||||
source alpha/Kconfig
|
||||
source avr/Kconfig
|
||||
source cris/Kconfig
|
||||
source hppa/Kconfig
|
||||
source i386/Kconfig
|
||||
source loongarch/Kconfig
|
||||
|
|
|
@ -28,9 +28,6 @@ config ECC
|
|||
config ONENAND
|
||||
bool
|
||||
|
||||
config TC58128
|
||||
bool
|
||||
|
||||
config VIRTIO_BLK
|
||||
bool
|
||||
default y
|
||||
|
|
|
@ -15,7 +15,6 @@ system_ss.add(when: 'CONFIG_SSI_M25P80', if_true: files('m25p80.c'))
|
|||
system_ss.add(when: 'CONFIG_SSI_M25P80', if_true: files('m25p80_sfdp.c'))
|
||||
system_ss.add(when: 'CONFIG_SWIM', if_true: files('swim.c'))
|
||||
system_ss.add(when: 'CONFIG_XEN_BUS', if_true: files('xen-block.c'))
|
||||
system_ss.add(when: 'CONFIG_TC58128', if_true: files('tc58128.c'))
|
||||
|
||||
specific_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk.c', 'virtio-blk-common.c'))
|
||||
specific_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('vhost-user-blk.c', 'virtio-blk-common.c'))
|
||||
|
|
|
@ -1,211 +0,0 @@
|
|||
/*
|
||||
* TC58128 NAND EEPROM emulation
|
||||
*
|
||||
* Copyright (c) 2005 Samuel Tardieu
|
||||
*
|
||||
* 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 (including the next
|
||||
* paragraph) 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.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/units.h"
|
||||
#include "hw/sh4/sh.h"
|
||||
#include "hw/loader.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#define CE1 0x0100
|
||||
#define CE2 0x0200
|
||||
#define RE 0x0400
|
||||
#define WE 0x0800
|
||||
#define ALE 0x1000
|
||||
#define CLE 0x2000
|
||||
#define RDY1 0x4000
|
||||
#define RDY2 0x8000
|
||||
#define RDY(n) ((n) == 0 ? RDY1 : RDY2)
|
||||
|
||||
typedef enum { WAIT, READ1, READ2, READ3 } state_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *flash_contents;
|
||||
state_t state;
|
||||
uint32_t address;
|
||||
uint8_t address_cycle;
|
||||
} tc58128_dev;
|
||||
|
||||
static tc58128_dev tc58128_devs[2];
|
||||
|
||||
#define FLASH_SIZE (16 * MiB)
|
||||
|
||||
static void init_dev(tc58128_dev * dev, const char *filename)
|
||||
{
|
||||
int ret, blocks;
|
||||
|
||||
dev->state = WAIT;
|
||||
dev->flash_contents = g_malloc(FLASH_SIZE);
|
||||
memset(dev->flash_contents, 0xff, FLASH_SIZE);
|
||||
if (filename) {
|
||||
/* Load flash image skipping the first block */
|
||||
ret = load_image_size(filename, dev->flash_contents + 528 * 32,
|
||||
FLASH_SIZE - 528 * 32);
|
||||
if (ret < 0) {
|
||||
if (!qtest_enabled()) {
|
||||
error_report("Could not load flash image %s", filename);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
/* Build first block with number of blocks */
|
||||
blocks = DIV_ROUND_UP(ret, 528 * 32);
|
||||
dev->flash_contents[0] = blocks & 0xff;
|
||||
dev->flash_contents[1] = (blocks >> 8) & 0xff;
|
||||
dev->flash_contents[2] = (blocks >> 16) & 0xff;
|
||||
dev->flash_contents[3] = (blocks >> 24) & 0xff;
|
||||
fprintf(stderr, "loaded %d bytes for %s into flash\n", ret,
|
||||
filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_command(tc58128_dev * dev, uint8_t command)
|
||||
{
|
||||
switch (command) {
|
||||
case 0xff:
|
||||
fprintf(stderr, "reset flash device\n");
|
||||
dev->state = WAIT;
|
||||
break;
|
||||
case 0x00:
|
||||
fprintf(stderr, "read mode 1\n");
|
||||
dev->state = READ1;
|
||||
dev->address_cycle = 0;
|
||||
break;
|
||||
case 0x01:
|
||||
fprintf(stderr, "read mode 2\n");
|
||||
dev->state = READ2;
|
||||
dev->address_cycle = 0;
|
||||
break;
|
||||
case 0x50:
|
||||
fprintf(stderr, "read mode 3\n");
|
||||
dev->state = READ3;
|
||||
dev->address_cycle = 0;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown flash command 0x%02x\n", command);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_address(tc58128_dev * dev, uint8_t data)
|
||||
{
|
||||
switch (dev->state) {
|
||||
case READ1:
|
||||
case READ2:
|
||||
case READ3:
|
||||
switch (dev->address_cycle) {
|
||||
case 0:
|
||||
dev->address = data;
|
||||
if (dev->state == READ2)
|
||||
dev->address |= 0x100;
|
||||
else if (dev->state == READ3)
|
||||
dev->address |= 0x200;
|
||||
break;
|
||||
case 1:
|
||||
dev->address += data * 528 * 0x100;
|
||||
break;
|
||||
case 2:
|
||||
dev->address += data * 528;
|
||||
fprintf(stderr, "address pointer in flash: 0x%08x\n",
|
||||
dev->address);
|
||||
break;
|
||||
default:
|
||||
/* Invalid data */
|
||||
abort();
|
||||
}
|
||||
dev->address_cycle++;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t handle_read(tc58128_dev * dev)
|
||||
{
|
||||
#if 0
|
||||
if (dev->address % 0x100000 == 0)
|
||||
fprintf(stderr, "reading flash at address 0x%08x\n", dev->address);
|
||||
#endif
|
||||
return dev->flash_contents[dev->address++];
|
||||
}
|
||||
|
||||
/* We never mark the device as busy, so interrupts cannot be triggered
|
||||
XXXXX */
|
||||
|
||||
static int tc58128_cb(uint16_t porta, uint16_t portb,
|
||||
uint16_t * periph_pdtra, uint16_t * periph_portadir,
|
||||
uint16_t * periph_pdtrb, uint16_t * periph_portbdir)
|
||||
{
|
||||
int dev;
|
||||
|
||||
if ((porta & CE1) == 0)
|
||||
dev = 0;
|
||||
else if ((porta & CE2) == 0)
|
||||
dev = 1;
|
||||
else
|
||||
return 0; /* No device selected */
|
||||
|
||||
if ((porta & RE) && (porta & WE)) {
|
||||
/* Nothing to do, assert ready and return to input state */
|
||||
*periph_portadir &= 0xff00;
|
||||
*periph_portadir |= RDY(dev);
|
||||
*periph_pdtra |= RDY(dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (porta & CLE) {
|
||||
/* Command */
|
||||
assert((porta & WE) == 0);
|
||||
handle_command(&tc58128_devs[dev], porta & 0x00ff);
|
||||
} else if (porta & ALE) {
|
||||
assert((porta & WE) == 0);
|
||||
handle_address(&tc58128_devs[dev], porta & 0x00ff);
|
||||
} else if ((porta & RE) == 0) {
|
||||
*periph_portadir |= 0x00ff;
|
||||
*periph_pdtra &= 0xff00;
|
||||
*periph_pdtra |= handle_read(&tc58128_devs[dev]);
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static sh7750_io_device tc58128 = {
|
||||
RE | WE, /* Port A triggers */
|
||||
0, /* Port B triggers */
|
||||
tc58128_cb /* Callback */
|
||||
};
|
||||
|
||||
int tc58128_init(struct SH7750State *s, const char *zone1, const char *zone2)
|
||||
{
|
||||
if (!qtest_enabled()) {
|
||||
warn_report_once("The TC58128 flash device is deprecated");
|
||||
}
|
||||
init_dev(&tc58128_devs[0], zone1);
|
||||
init_dev(&tc58128_devs[1], zone2);
|
||||
return sh7750_register_io_device(s, &tc58128);
|
||||
}
|
|
@ -86,7 +86,7 @@ static void update_char_mask(AVRUsartState *usart)
|
|||
usart->char_mask = 0b11111111;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -287,6 +287,7 @@ static void escc_reset_chn(ESCCChannelState *s)
|
|||
s->rxint = s->txint = 0;
|
||||
s->rxint_under_svc = s->txint_under_svc = 0;
|
||||
s->e0_mode = s->led_mode = s->caps_lock_mode = s->num_lock_mode = 0;
|
||||
s->sunmouse_dx = s->sunmouse_dy = s->sunmouse_buttons = 0;
|
||||
clear_queue(s);
|
||||
}
|
||||
|
||||
|
@ -952,53 +953,96 @@ static void handle_kbd_command(ESCCChannelState *s, int val)
|
|||
}
|
||||
}
|
||||
|
||||
static void sunmouse_event(void *opaque,
|
||||
int dx, int dy, int dz, int buttons_state)
|
||||
static void sunmouse_handle_event(DeviceState *dev, QemuConsole *src,
|
||||
InputEvent *evt)
|
||||
{
|
||||
ESCCChannelState *s = opaque;
|
||||
ESCCChannelState *s = (ESCCChannelState *)dev;
|
||||
InputMoveEvent *move;
|
||||
InputBtnEvent *btn;
|
||||
static const int bmap[INPUT_BUTTON__MAX] = {
|
||||
[INPUT_BUTTON_LEFT] = 0x4,
|
||||
[INPUT_BUTTON_MIDDLE] = 0x2,
|
||||
[INPUT_BUTTON_RIGHT] = 0x1,
|
||||
};
|
||||
|
||||
switch (evt->type) {
|
||||
case INPUT_EVENT_KIND_REL:
|
||||
move = evt->u.rel.data;
|
||||
if (move->axis == INPUT_AXIS_X) {
|
||||
s->sunmouse_dx += move->value;
|
||||
} else if (move->axis == INPUT_AXIS_Y) {
|
||||
s->sunmouse_dy -= move->value;
|
||||
}
|
||||
break;
|
||||
|
||||
case INPUT_EVENT_KIND_BTN:
|
||||
btn = evt->u.btn.data;
|
||||
if (bmap[btn->button]) {
|
||||
if (btn->down) {
|
||||
s->sunmouse_buttons |= bmap[btn->button];
|
||||
} else {
|
||||
s->sunmouse_buttons &= ~bmap[btn->button];
|
||||
}
|
||||
/* Indicate we have a supported button event */
|
||||
s->sunmouse_buttons |= 0x80;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* keep gcc happy */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void sunmouse_sync(DeviceState *dev)
|
||||
{
|
||||
ESCCChannelState *s = (ESCCChannelState *)dev;
|
||||
int ch;
|
||||
|
||||
trace_escc_sunmouse_event(dx, dy, buttons_state);
|
||||
if (s->sunmouse_dx == 0 && s->sunmouse_dy == 0 &&
|
||||
(s->sunmouse_buttons & 0x80) == 0) {
|
||||
/* Nothing to do after button event filter */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clear our button event flag */
|
||||
s->sunmouse_buttons &= ~0x80;
|
||||
trace_escc_sunmouse_event(s->sunmouse_dx, s->sunmouse_dy,
|
||||
s->sunmouse_buttons);
|
||||
ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */
|
||||
|
||||
if (buttons_state & MOUSE_EVENT_LBUTTON) {
|
||||
ch ^= 0x4;
|
||||
}
|
||||
if (buttons_state & MOUSE_EVENT_MBUTTON) {
|
||||
ch ^= 0x2;
|
||||
}
|
||||
if (buttons_state & MOUSE_EVENT_RBUTTON) {
|
||||
ch ^= 0x1;
|
||||
}
|
||||
|
||||
ch ^= s->sunmouse_buttons;
|
||||
put_queue(s, ch);
|
||||
|
||||
ch = dx;
|
||||
|
||||
ch = s->sunmouse_dx;
|
||||
if (ch > 127) {
|
||||
ch = 127;
|
||||
} else if (ch < -127) {
|
||||
ch = -127;
|
||||
}
|
||||
|
||||
put_queue(s, ch & 0xff);
|
||||
s->sunmouse_dx -= ch;
|
||||
|
||||
ch = -dy;
|
||||
|
||||
ch = s->sunmouse_dy;
|
||||
if (ch > 127) {
|
||||
ch = 127;
|
||||
} else if (ch < -127) {
|
||||
ch = -127;
|
||||
}
|
||||
|
||||
put_queue(s, ch & 0xff);
|
||||
s->sunmouse_dy -= ch;
|
||||
|
||||
/* MSC protocol specifies two extra motion bytes */
|
||||
|
||||
put_queue(s, 0);
|
||||
put_queue(s, 0);
|
||||
}
|
||||
|
||||
static const QemuInputHandler sunmouse_handler = {
|
||||
.name = "QEMU Sun Mouse",
|
||||
.mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
|
||||
.event = sunmouse_handle_event,
|
||||
.sync = sunmouse_sync,
|
||||
};
|
||||
|
||||
static void escc_init1(Object *obj)
|
||||
{
|
||||
ESCCState *s = ESCC(obj);
|
||||
|
@ -1036,8 +1080,8 @@ static void escc_realize(DeviceState *dev, Error **errp)
|
|||
}
|
||||
|
||||
if (s->chn[0].type == escc_mouse) {
|
||||
qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,
|
||||
"QEMU Sun Mouse");
|
||||
s->chn[0].hs = qemu_input_handler_register((DeviceState *)(&s->chn[0]),
|
||||
&sunmouse_handler);
|
||||
}
|
||||
if (s->chn[1].type == escc_kbd) {
|
||||
s->chn[1].hs = qemu_input_handler_register((DeviceState *)(&s->chn[1]),
|
||||
|
|
|
@ -1,267 +0,0 @@
|
|||
/*
|
||||
* QEMU ETRAX System Emulator
|
||||
*
|
||||
* Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
|
||||
*
|
||||
* 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 "hw/irq.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/qdev-properties-system.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "chardev/char-fe.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define D(x)
|
||||
|
||||
#define RW_TR_CTRL (0x00 / 4)
|
||||
#define RW_TR_DMA_EN (0x04 / 4)
|
||||
#define RW_REC_CTRL (0x08 / 4)
|
||||
#define RW_DOUT (0x1c / 4)
|
||||
#define RS_STAT_DIN (0x20 / 4)
|
||||
#define R_STAT_DIN (0x24 / 4)
|
||||
#define RW_INTR_MASK (0x2c / 4)
|
||||
#define RW_ACK_INTR (0x30 / 4)
|
||||
#define R_INTR (0x34 / 4)
|
||||
#define R_MASKED_INTR (0x38 / 4)
|
||||
#define R_MAX (0x3c / 4)
|
||||
|
||||
#define STAT_DAV 16
|
||||
#define STAT_TR_IDLE 22
|
||||
#define STAT_TR_RDY 24
|
||||
|
||||
#define TYPE_ETRAX_FS_SERIAL "etraxfs-serial"
|
||||
typedef struct ETRAXSerial ETRAXSerial;
|
||||
DECLARE_INSTANCE_CHECKER(ETRAXSerial, ETRAX_SERIAL,
|
||||
TYPE_ETRAX_FS_SERIAL)
|
||||
|
||||
struct ETRAXSerial {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion mmio;
|
||||
CharBackend chr;
|
||||
qemu_irq irq;
|
||||
|
||||
int pending_tx;
|
||||
|
||||
uint8_t rx_fifo[16];
|
||||
unsigned int rx_fifo_pos;
|
||||
unsigned int rx_fifo_len;
|
||||
|
||||
/* Control registers. */
|
||||
uint32_t regs[R_MAX];
|
||||
};
|
||||
|
||||
static void ser_update_irq(ETRAXSerial *s)
|
||||
{
|
||||
|
||||
if (s->rx_fifo_len) {
|
||||
s->regs[R_INTR] |= 8;
|
||||
} else {
|
||||
s->regs[R_INTR] &= ~8;
|
||||
}
|
||||
|
||||
s->regs[R_MASKED_INTR] = s->regs[R_INTR] & s->regs[RW_INTR_MASK];
|
||||
qemu_set_irq(s->irq, !!s->regs[R_MASKED_INTR]);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
ser_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
{
|
||||
ETRAXSerial *s = opaque;
|
||||
uint32_t r = 0;
|
||||
|
||||
addr >>= 2;
|
||||
switch (addr)
|
||||
{
|
||||
case R_STAT_DIN:
|
||||
r = s->rx_fifo[(s->rx_fifo_pos - s->rx_fifo_len) & 15];
|
||||
if (s->rx_fifo_len) {
|
||||
r |= 1 << STAT_DAV;
|
||||
}
|
||||
r |= 1 << STAT_TR_RDY;
|
||||
r |= 1 << STAT_TR_IDLE;
|
||||
break;
|
||||
case RS_STAT_DIN:
|
||||
r = s->rx_fifo[(s->rx_fifo_pos - s->rx_fifo_len) & 15];
|
||||
if (s->rx_fifo_len) {
|
||||
r |= 1 << STAT_DAV;
|
||||
s->rx_fifo_len--;
|
||||
}
|
||||
r |= 1 << STAT_TR_RDY;
|
||||
r |= 1 << STAT_TR_IDLE;
|
||||
break;
|
||||
default:
|
||||
r = s->regs[addr];
|
||||
D(qemu_log("%s " HWADDR_FMT_plx "=%x\n", __func__, addr, r));
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
ser_write(void *opaque, hwaddr addr,
|
||||
uint64_t val64, unsigned int size)
|
||||
{
|
||||
ETRAXSerial *s = opaque;
|
||||
uint32_t value = val64;
|
||||
unsigned char ch = val64;
|
||||
|
||||
D(qemu_log("%s " HWADDR_FMT_plx "=%x\n", __func__, addr, value));
|
||||
addr >>= 2;
|
||||
switch (addr)
|
||||
{
|
||||
case RW_DOUT:
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
s->regs[R_INTR] |= 3;
|
||||
s->pending_tx = 1;
|
||||
s->regs[addr] = value;
|
||||
break;
|
||||
case RW_ACK_INTR:
|
||||
if (s->pending_tx) {
|
||||
value &= ~1;
|
||||
s->pending_tx = 0;
|
||||
D(qemu_log("fixedup value=%x r_intr=%x\n",
|
||||
value, s->regs[R_INTR]));
|
||||
}
|
||||
s->regs[addr] = value;
|
||||
s->regs[R_INTR] &= ~value;
|
||||
D(printf("r_intr=%x\n", s->regs[R_INTR]));
|
||||
break;
|
||||
default:
|
||||
s->regs[addr] = value;
|
||||
break;
|
||||
}
|
||||
ser_update_irq(s);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps ser_ops = {
|
||||
.read = ser_read,
|
||||
.write = ser_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4
|
||||
}
|
||||
};
|
||||
|
||||
static Property etraxfs_ser_properties[] = {
|
||||
DEFINE_PROP_CHR("chardev", ETRAXSerial, chr),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void serial_receive(void *opaque, const uint8_t *buf, int size)
|
||||
{
|
||||
ETRAXSerial *s = opaque;
|
||||
int i;
|
||||
|
||||
/* Got a byte. */
|
||||
if (s->rx_fifo_len >= 16) {
|
||||
D(qemu_log("WARNING: UART dropped char.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
s->rx_fifo[s->rx_fifo_pos] = buf[i];
|
||||
s->rx_fifo_pos++;
|
||||
s->rx_fifo_pos &= 15;
|
||||
s->rx_fifo_len++;
|
||||
}
|
||||
|
||||
ser_update_irq(s);
|
||||
}
|
||||
|
||||
static int serial_can_receive(void *opaque)
|
||||
{
|
||||
ETRAXSerial *s = opaque;
|
||||
|
||||
/* Is the receiver enabled? */
|
||||
if (!(s->regs[RW_REC_CTRL] & (1 << 3))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sizeof(s->rx_fifo) - s->rx_fifo_len;
|
||||
}
|
||||
|
||||
static void serial_event(void *opaque, QEMUChrEvent event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void etraxfs_ser_reset(DeviceState *d)
|
||||
{
|
||||
ETRAXSerial *s = ETRAX_SERIAL(d);
|
||||
|
||||
/* transmitter begins ready and idle. */
|
||||
s->regs[RS_STAT_DIN] |= (1 << STAT_TR_RDY);
|
||||
s->regs[RS_STAT_DIN] |= (1 << STAT_TR_IDLE);
|
||||
|
||||
s->regs[RW_REC_CTRL] = 0x10000;
|
||||
|
||||
}
|
||||
|
||||
static void etraxfs_ser_init(Object *obj)
|
||||
{
|
||||
ETRAXSerial *s = ETRAX_SERIAL(obj);
|
||||
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
|
||||
|
||||
sysbus_init_irq(dev, &s->irq);
|
||||
memory_region_init_io(&s->mmio, obj, &ser_ops, s,
|
||||
"etraxfs-serial", R_MAX * 4);
|
||||
sysbus_init_mmio(dev, &s->mmio);
|
||||
}
|
||||
|
||||
static void etraxfs_ser_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ETRAXSerial *s = ETRAX_SERIAL(dev);
|
||||
|
||||
qemu_chr_fe_set_handlers(&s->chr,
|
||||
serial_can_receive, serial_receive,
|
||||
serial_event, NULL, s, NULL, true);
|
||||
}
|
||||
|
||||
static void etraxfs_ser_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
device_class_set_legacy_reset(dc, etraxfs_ser_reset);
|
||||
device_class_set_props(dc, etraxfs_ser_properties);
|
||||
dc->realize = etraxfs_ser_realize;
|
||||
}
|
||||
|
||||
static const TypeInfo etraxfs_ser_info = {
|
||||
.name = TYPE_ETRAX_FS_SERIAL,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(ETRAXSerial),
|
||||
.instance_init = etraxfs_ser_init,
|
||||
.class_init = etraxfs_ser_class_init,
|
||||
};
|
||||
|
||||
static void etraxfs_serial_register_types(void)
|
||||
{
|
||||
type_register_static(&etraxfs_ser_info);
|
||||
}
|
||||
|
||||
type_init(etraxfs_serial_register_types)
|
|
@ -1,7 +1,6 @@
|
|||
system_ss.add(when: 'CONFIG_CADENCE', if_true: files('cadence_uart.c'))
|
||||
system_ss.add(when: 'CONFIG_CMSDK_APB_UART', if_true: files('cmsdk-apb-uart.c'))
|
||||
system_ss.add(when: 'CONFIG_ESCC', if_true: files('escc.c'))
|
||||
system_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_ser.c'))
|
||||
system_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_apbuart.c'))
|
||||
system_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_uart.c'))
|
||||
system_ss.add(when: 'CONFIG_IMX', if_true: files('imx_serial.c'))
|
||||
|
|
209
hw/char/pl011.c
209
hw/char/pl011.c
|
@ -85,7 +85,9 @@ DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr)
|
|||
#define CR_OUT1 (1 << 12)
|
||||
#define CR_RTS (1 << 11)
|
||||
#define CR_DTR (1 << 10)
|
||||
#define CR_TXE (1 << 8)
|
||||
#define CR_LBE (1 << 7)
|
||||
#define CR_UARTEN (1 << 0)
|
||||
|
||||
/* Integer Baud Rate Divider, UARTIBRD */
|
||||
#define IBRD_MASK 0x3f
|
||||
|
@ -138,6 +140,11 @@ static void pl011_update(PL011State *s)
|
|||
}
|
||||
}
|
||||
|
||||
static bool pl011_loopback_enabled(PL011State *s)
|
||||
{
|
||||
return !!(s->cr & CR_LBE);
|
||||
}
|
||||
|
||||
static bool pl011_is_fifo_enabled(PL011State *s)
|
||||
{
|
||||
return (s->lcr & LCR_FEN) != 0;
|
||||
|
@ -149,41 +156,126 @@ static inline unsigned pl011_get_fifo_depth(PL011State *s)
|
|||
return pl011_is_fifo_enabled(s) ? PL011_FIFO_DEPTH : 1;
|
||||
}
|
||||
|
||||
static inline void pl011_reset_fifo(PL011State *s)
|
||||
static inline void pl011_reset_rx_fifo(PL011State *s)
|
||||
{
|
||||
s->read_count = 0;
|
||||
s->read_pos = 0;
|
||||
|
||||
/* Reset FIFO flags */
|
||||
s->flags &= ~(PL011_FLAG_RXFF | PL011_FLAG_TXFF);
|
||||
s->flags |= PL011_FLAG_RXFE | PL011_FLAG_TXFE;
|
||||
s->flags &= ~PL011_FLAG_RXFF;
|
||||
s->flags |= PL011_FLAG_RXFE;
|
||||
}
|
||||
|
||||
static inline void pl011_reset_tx_fifo(PL011State *s)
|
||||
{
|
||||
/* Reset FIFO flags */
|
||||
s->flags &= ~PL011_FLAG_TXFF;
|
||||
s->flags |= PL011_FLAG_TXFE;
|
||||
}
|
||||
|
||||
static void pl011_fifo_rx_put(void *opaque, uint32_t value)
|
||||
{
|
||||
PL011State *s = (PL011State *)opaque;
|
||||
int slot;
|
||||
unsigned pipe_depth;
|
||||
|
||||
pipe_depth = pl011_get_fifo_depth(s);
|
||||
slot = (s->read_pos + s->read_count) & (pipe_depth - 1);
|
||||
s->read_fifo[slot] = value;
|
||||
s->read_count++;
|
||||
s->flags &= ~PL011_FLAG_RXFE;
|
||||
trace_pl011_fifo_rx_put(value, s->read_count);
|
||||
if (s->read_count == pipe_depth) {
|
||||
trace_pl011_fifo_rx_full();
|
||||
s->flags |= PL011_FLAG_RXFF;
|
||||
}
|
||||
if (s->read_count == s->read_trigger) {
|
||||
s->int_level |= INT_RX;
|
||||
pl011_update(s);
|
||||
}
|
||||
}
|
||||
|
||||
static void pl011_loopback_tx(PL011State *s, uint32_t value)
|
||||
{
|
||||
if (!pl011_loopback_enabled(s)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Caveat:
|
||||
*
|
||||
* In real hardware, TX loopback happens at the serial-bit level
|
||||
* and then reassembled by the RX logics back into bytes and placed
|
||||
* into the RX fifo. That is, loopback happens after TX fifo.
|
||||
*
|
||||
* Because the real hardware TX fifo is time-drained at the frame
|
||||
* rate governed by the configured serial format, some loopback
|
||||
* bytes in TX fifo may still be able to get into the RX fifo
|
||||
* that could be full at times while being drained at software
|
||||
* pace.
|
||||
*
|
||||
* In such scenario, the RX draining pace is the major factor
|
||||
* deciding which loopback bytes get into the RX fifo, unless
|
||||
* hardware flow-control is enabled.
|
||||
*
|
||||
* For simplicity, the above described is not emulated.
|
||||
*/
|
||||
pl011_fifo_rx_put(s, value);
|
||||
}
|
||||
|
||||
static void pl011_write_txdata(PL011State *s, uint8_t data)
|
||||
{
|
||||
if (!(s->cr & CR_UARTEN)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"PL011 data written to disabled UART\n");
|
||||
}
|
||||
if (!(s->cr & CR_TXE)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"PL011 data written to disabled TX UART\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks
|
||||
*/
|
||||
qemu_chr_fe_write_all(&s->chr, &data, 1);
|
||||
pl011_loopback_tx(s, data);
|
||||
s->int_level |= INT_TX;
|
||||
pl011_update(s);
|
||||
}
|
||||
|
||||
static uint32_t pl011_read_rxdata(PL011State *s)
|
||||
{
|
||||
uint32_t c;
|
||||
|
||||
s->flags &= ~PL011_FLAG_RXFF;
|
||||
c = s->read_fifo[s->read_pos];
|
||||
if (s->read_count > 0) {
|
||||
s->read_count--;
|
||||
s->read_pos = (s->read_pos + 1) & (pl011_get_fifo_depth(s) - 1);
|
||||
}
|
||||
if (s->read_count == 0) {
|
||||
s->flags |= PL011_FLAG_RXFE;
|
||||
}
|
||||
if (s->read_count == s->read_trigger - 1) {
|
||||
s->int_level &= ~INT_RX;
|
||||
}
|
||||
trace_pl011_read_fifo(s->read_count);
|
||||
s->rsr = c >> 8;
|
||||
pl011_update(s);
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
return c;
|
||||
}
|
||||
|
||||
static uint64_t pl011_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
{
|
||||
PL011State *s = (PL011State *)opaque;
|
||||
uint32_t c;
|
||||
uint64_t r;
|
||||
|
||||
switch (offset >> 2) {
|
||||
case 0: /* UARTDR */
|
||||
s->flags &= ~PL011_FLAG_RXFF;
|
||||
c = s->read_fifo[s->read_pos];
|
||||
if (s->read_count > 0) {
|
||||
s->read_count--;
|
||||
s->read_pos = (s->read_pos + 1) & (pl011_get_fifo_depth(s) - 1);
|
||||
}
|
||||
if (s->read_count == 0) {
|
||||
s->flags |= PL011_FLAG_RXFE;
|
||||
}
|
||||
if (s->read_count == s->read_trigger - 1)
|
||||
s->int_level &= ~ INT_RX;
|
||||
trace_pl011_read_fifo(s->read_count);
|
||||
s->rsr = c >> 8;
|
||||
pl011_update(s);
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
r = c;
|
||||
r = pl011_read_rxdata(s);
|
||||
break;
|
||||
case 1: /* UARTRSR */
|
||||
r = s->rsr;
|
||||
|
@ -268,11 +360,6 @@ static void pl011_trace_baudrate_change(const PL011State *s)
|
|||
s->ibrd, s->fbrd);
|
||||
}
|
||||
|
||||
static bool pl011_loopback_enabled(PL011State *s)
|
||||
{
|
||||
return !!(s->cr & CR_LBE);
|
||||
}
|
||||
|
||||
static void pl011_loopback_mdmctrl(PL011State *s)
|
||||
{
|
||||
uint32_t cr, fr, il;
|
||||
|
@ -314,36 +401,6 @@ static void pl011_loopback_mdmctrl(PL011State *s)
|
|||
pl011_update(s);
|
||||
}
|
||||
|
||||
static void pl011_put_fifo(void *opaque, uint32_t value);
|
||||
|
||||
static void pl011_loopback_tx(PL011State *s, uint32_t value)
|
||||
{
|
||||
if (!pl011_loopback_enabled(s)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Caveat:
|
||||
*
|
||||
* In real hardware, TX loopback happens at the serial-bit level
|
||||
* and then reassembled by the RX logics back into bytes and placed
|
||||
* into the RX fifo. That is, loopback happens after TX fifo.
|
||||
*
|
||||
* Because the real hardware TX fifo is time-drained at the frame
|
||||
* rate governed by the configured serial format, some loopback
|
||||
* bytes in TX fifo may still be able to get into the RX fifo
|
||||
* that could be full at times while being drained at software
|
||||
* pace.
|
||||
*
|
||||
* In such scenario, the RX draining pace is the major factor
|
||||
* deciding which loopback bytes get into the RX fifo, unless
|
||||
* hardware flow-control is enabled.
|
||||
*
|
||||
* For simplicity, the above described is not emulated.
|
||||
*/
|
||||
pl011_put_fifo(s, value);
|
||||
}
|
||||
|
||||
static void pl011_loopback_break(PL011State *s, int brk_enable)
|
||||
{
|
||||
if (brk_enable) {
|
||||
|
@ -361,14 +418,8 @@ static void pl011_write(void *opaque, hwaddr offset,
|
|||
|
||||
switch (offset >> 2) {
|
||||
case 0: /* UARTDR */
|
||||
/* ??? Check if transmitter is enabled. */
|
||||
ch = value;
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
pl011_loopback_tx(s, ch);
|
||||
s->int_level |= INT_TX;
|
||||
pl011_update(s);
|
||||
pl011_write_txdata(s, ch);
|
||||
break;
|
||||
case 1: /* UARTRSR/UARTECR */
|
||||
s->rsr = 0;
|
||||
|
@ -390,7 +441,8 @@ static void pl011_write(void *opaque, hwaddr offset,
|
|||
case 11: /* UARTLCR_H */
|
||||
/* Reset the FIFO state on FIFO enable or disable */
|
||||
if ((s->lcr ^ value) & LCR_FEN) {
|
||||
pl011_reset_fifo(s);
|
||||
pl011_reset_rx_fifo(s);
|
||||
pl011_reset_tx_fifo(s);
|
||||
}
|
||||
if ((s->lcr ^ value) & LCR_BRK) {
|
||||
int break_enable = value & LCR_BRK;
|
||||
|
@ -440,28 +492,6 @@ static int pl011_can_receive(void *opaque)
|
|||
return r;
|
||||
}
|
||||
|
||||
static void pl011_put_fifo(void *opaque, uint32_t value)
|
||||
{
|
||||
PL011State *s = (PL011State *)opaque;
|
||||
int slot;
|
||||
unsigned pipe_depth;
|
||||
|
||||
pipe_depth = pl011_get_fifo_depth(s);
|
||||
slot = (s->read_pos + s->read_count) & (pipe_depth - 1);
|
||||
s->read_fifo[slot] = value;
|
||||
s->read_count++;
|
||||
s->flags &= ~PL011_FLAG_RXFE;
|
||||
trace_pl011_put_fifo(value, s->read_count);
|
||||
if (s->read_count == pipe_depth) {
|
||||
trace_pl011_put_fifo_full();
|
||||
s->flags |= PL011_FLAG_RXFF;
|
||||
}
|
||||
if (s->read_count == s->read_trigger) {
|
||||
s->int_level |= INT_RX;
|
||||
pl011_update(s);
|
||||
}
|
||||
}
|
||||
|
||||
static void pl011_receive(void *opaque, const uint8_t *buf, int size)
|
||||
{
|
||||
/*
|
||||
|
@ -473,13 +503,13 @@ static void pl011_receive(void *opaque, const uint8_t *buf, int size)
|
|||
return;
|
||||
}
|
||||
|
||||
pl011_put_fifo(opaque, *buf);
|
||||
pl011_fifo_rx_put(opaque, *buf);
|
||||
}
|
||||
|
||||
static void pl011_event(void *opaque, QEMUChrEvent event)
|
||||
{
|
||||
if (event == CHR_EVENT_BREAK && !pl011_loopback_enabled(opaque)) {
|
||||
pl011_put_fifo(opaque, DR_BE);
|
||||
pl011_fifo_rx_put(opaque, DR_BE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -549,7 +579,7 @@ static const VMStateDescription vmstate_pl011 = {
|
|||
.minimum_version_id = 2,
|
||||
.post_load = pl011_post_load,
|
||||
.fields = (const VMStateField[]) {
|
||||
VMSTATE_UINT32(readbuff, PL011State),
|
||||
VMSTATE_UNUSED(sizeof(uint32_t)),
|
||||
VMSTATE_UINT32(flags, PL011State),
|
||||
VMSTATE_UINT32(lcr, PL011State),
|
||||
VMSTATE_UINT32(rsr, PL011State),
|
||||
|
@ -621,7 +651,8 @@ static void pl011_reset(DeviceState *dev)
|
|||
s->ifl = 0x12;
|
||||
s->cr = 0x300;
|
||||
s->flags = 0;
|
||||
pl011_reset_fifo(s);
|
||||
pl011_reset_rx_fifo(s);
|
||||
pl011_reset_tx_fifo(s);
|
||||
}
|
||||
|
||||
static void pl011_class_init(ObjectClass *oc, void *data)
|
||||
|
|
|
@ -58,8 +58,8 @@ pl011_read(uint32_t addr, uint32_t value, const char *regname) "addr 0x%03x valu
|
|||
pl011_read_fifo(int read_count) "FIFO read, read_count now %d"
|
||||
pl011_write(uint32_t addr, uint32_t value, const char *regname) "addr 0x%03x value 0x%08x reg %s"
|
||||
pl011_can_receive(uint32_t lcr, int read_count, int r) "LCR 0x%08x read_count %d returning %d"
|
||||
pl011_put_fifo(uint32_t c, int read_count) "new char 0x%x read_count now %d"
|
||||
pl011_put_fifo_full(void) "FIFO now full, RXFF set"
|
||||
pl011_fifo_rx_put(uint32_t c, int read_count) "new char 0x%02x read_count now %d"
|
||||
pl011_fifo_rx_full(void) "RX FIFO now full, RXFF set"
|
||||
pl011_baudrate_change(unsigned int baudrate, uint64_t clock, uint32_t ibrd, uint32_t fbrd) "new baudrate %u (clk: %" PRIu64 "hz, ibrd: %" PRIu32 ", fbrd: %" PRIu32 ")"
|
||||
|
||||
# cmsdk-apb-uart.c
|
||||
|
|
|
@ -380,7 +380,7 @@ void parse_numa_hmat_lb(NumaState *numa_state, NumaHmatLBOptions *node,
|
|||
}
|
||||
lb_data.data = node->bandwidth;
|
||||
} else {
|
||||
assert(0);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
g_array_append_val(hmat_lb->list, lb_data);
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
config AXIS
|
||||
bool
|
||||
default y
|
||||
depends on CRIS
|
||||
select ETRAXFS
|
||||
select PFLASH_CFI02
|
||||
select NAND
|
||||
|
||||
config ETRAXFS
|
||||
bool
|
||||
select PTIMER
|
|
@ -1,351 +0,0 @@
|
|||
/*
|
||||
* QEMU model for the AXIS devboard 88.
|
||||
*
|
||||
* Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB.
|
||||
*
|
||||
* 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/units.h"
|
||||
#include "qapi/error.h"
|
||||
#include "cpu.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "net/net.h"
|
||||
#include "hw/block/flash.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/cris/etraxfs.h"
|
||||
#include "hw/loader.h"
|
||||
#include "elf.h"
|
||||
#include "boot.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
#define D(x)
|
||||
#define DNAND(x)
|
||||
|
||||
struct nand_state_t
|
||||
{
|
||||
DeviceState *nand;
|
||||
MemoryRegion iomem;
|
||||
unsigned int rdy:1;
|
||||
unsigned int ale:1;
|
||||
unsigned int cle:1;
|
||||
unsigned int ce:1;
|
||||
};
|
||||
|
||||
static struct nand_state_t nand_state;
|
||||
static uint64_t nand_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
struct nand_state_t *s = opaque;
|
||||
uint32_t r;
|
||||
int rdy;
|
||||
|
||||
r = nand_getio(s->nand);
|
||||
nand_getpins(s->nand, &rdy);
|
||||
s->rdy = rdy;
|
||||
|
||||
DNAND(printf("%s addr=%x r=%x\n", __func__, addr, r));
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
nand_write(void *opaque, hwaddr addr, uint64_t value,
|
||||
unsigned size)
|
||||
{
|
||||
struct nand_state_t *s = opaque;
|
||||
int rdy;
|
||||
|
||||
DNAND(printf("%s addr=%x v=%x\n", __func__, addr, (unsigned)value));
|
||||
nand_setpins(s->nand, s->cle, s->ale, s->ce, 1, 0);
|
||||
nand_setio(s->nand, value);
|
||||
nand_getpins(s->nand, &rdy);
|
||||
s->rdy = rdy;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps nand_ops = {
|
||||
.read = nand_read,
|
||||
.write = nand_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
struct tempsensor_t
|
||||
{
|
||||
unsigned int shiftreg;
|
||||
unsigned int count;
|
||||
enum {
|
||||
ST_OUT, ST_IN, ST_Z
|
||||
} state;
|
||||
|
||||
uint16_t regs[3];
|
||||
};
|
||||
|
||||
static void tempsensor_clkedge(struct tempsensor_t *s,
|
||||
unsigned int clk, unsigned int data_in)
|
||||
{
|
||||
D(printf("%s clk=%d state=%d sr=%x\n", __func__,
|
||||
clk, s->state, s->shiftreg));
|
||||
if (s->count == 0) {
|
||||
s->count = 16;
|
||||
s->state = ST_OUT;
|
||||
}
|
||||
switch (s->state) {
|
||||
case ST_OUT:
|
||||
/* Output reg is clocked at negedge. */
|
||||
if (!clk) {
|
||||
s->count--;
|
||||
s->shiftreg <<= 1;
|
||||
if (s->count == 0) {
|
||||
s->shiftreg = 0;
|
||||
s->state = ST_IN;
|
||||
s->count = 16;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ST_Z:
|
||||
if (clk) {
|
||||
s->count--;
|
||||
if (s->count == 0) {
|
||||
s->shiftreg = 0;
|
||||
s->state = ST_OUT;
|
||||
s->count = 16;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ST_IN:
|
||||
/* Indata is sampled at posedge. */
|
||||
if (clk) {
|
||||
s->count--;
|
||||
s->shiftreg <<= 1;
|
||||
s->shiftreg |= data_in & 1;
|
||||
if (s->count == 0) {
|
||||
D(printf("%s cfgreg=%x\n", __func__, s->shiftreg));
|
||||
s->regs[0] = s->shiftreg;
|
||||
s->state = ST_OUT;
|
||||
s->count = 16;
|
||||
|
||||
if ((s->regs[0] & 0xff) == 0) {
|
||||
/* 25 degrees celsius. */
|
||||
s->shiftreg = 0x0b9f;
|
||||
} else if ((s->regs[0] & 0xff) == 0xff) {
|
||||
/* Sensor ID, 0x8100 LM70. */
|
||||
s->shiftreg = 0x8100;
|
||||
} else
|
||||
printf("Invalid tempsens state %x\n", s->regs[0]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define RW_PA_DOUT 0x00
|
||||
#define R_PA_DIN 0x01
|
||||
#define RW_PA_OE 0x02
|
||||
#define RW_PD_DOUT 0x10
|
||||
#define R_PD_DIN 0x11
|
||||
#define RW_PD_OE 0x12
|
||||
|
||||
static struct gpio_state_t
|
||||
{
|
||||
MemoryRegion iomem;
|
||||
struct nand_state_t *nand;
|
||||
struct tempsensor_t tempsensor;
|
||||
uint32_t regs[0x5c / 4];
|
||||
} gpio_state;
|
||||
|
||||
static uint64_t gpio_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
struct gpio_state_t *s = opaque;
|
||||
uint32_t r = 0;
|
||||
|
||||
addr >>= 2;
|
||||
switch (addr)
|
||||
{
|
||||
case R_PA_DIN:
|
||||
r = s->regs[RW_PA_DOUT] & s->regs[RW_PA_OE];
|
||||
|
||||
/* Encode pins from the nand. */
|
||||
r |= s->nand->rdy << 7;
|
||||
break;
|
||||
case R_PD_DIN:
|
||||
r = s->regs[RW_PD_DOUT] & s->regs[RW_PD_OE];
|
||||
|
||||
/* Encode temp sensor pins. */
|
||||
r |= (!!(s->tempsensor.shiftreg & 0x10000)) << 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
r = s->regs[addr];
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
D(printf("%s %x=%x\n", __func__, addr, r));
|
||||
}
|
||||
|
||||
static void gpio_write(void *opaque, hwaddr addr, uint64_t value,
|
||||
unsigned size)
|
||||
{
|
||||
struct gpio_state_t *s = opaque;
|
||||
D(printf("%s %x=%x\n", __func__, addr, (unsigned)value));
|
||||
|
||||
addr >>= 2;
|
||||
switch (addr)
|
||||
{
|
||||
case RW_PA_DOUT:
|
||||
/* Decode nand pins. */
|
||||
s->nand->ale = !!(value & (1 << 6));
|
||||
s->nand->cle = !!(value & (1 << 5));
|
||||
s->nand->ce = !!(value & (1 << 4));
|
||||
|
||||
s->regs[addr] = value;
|
||||
break;
|
||||
|
||||
case RW_PD_DOUT:
|
||||
/* Temp sensor clk. */
|
||||
if ((s->regs[addr] ^ value) & 2)
|
||||
tempsensor_clkedge(&s->tempsensor, !!(value & 2),
|
||||
!!(value & 16));
|
||||
s->regs[addr] = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
s->regs[addr] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps gpio_ops = {
|
||||
.read = gpio_read,
|
||||
.write = gpio_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4,
|
||||
},
|
||||
};
|
||||
|
||||
#define INTMEM_SIZE (128 * KiB)
|
||||
|
||||
static struct cris_load_info li;
|
||||
|
||||
static
|
||||
void axisdev88_init(MachineState *machine)
|
||||
{
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||
CRISCPU *cpu;
|
||||
DeviceState *dev;
|
||||
SysBusDevice *s;
|
||||
DriveInfo *nand;
|
||||
qemu_irq irq[30], nmi[2];
|
||||
void *etraxfs_dmac;
|
||||
struct etraxfs_dma_client *dma_eth;
|
||||
int i;
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
MemoryRegion *phys_intmem = g_new(MemoryRegion, 1);
|
||||
|
||||
/* init CPUs */
|
||||
cpu = CRIS_CPU(cpu_create(machine->cpu_type));
|
||||
|
||||
memory_region_add_subregion(address_space_mem, 0x40000000, machine->ram);
|
||||
|
||||
/* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the
|
||||
internal memory. */
|
||||
memory_region_init_ram(phys_intmem, NULL, "axisdev88.chipram",
|
||||
INTMEM_SIZE, &error_fatal);
|
||||
memory_region_add_subregion(address_space_mem, 0x38000000, phys_intmem);
|
||||
|
||||
/* Attach a NAND flash to CS1. */
|
||||
nand = drive_get(IF_MTD, 0, 0);
|
||||
nand_state.nand = nand_init(nand ? blk_by_legacy_dinfo(nand) : NULL,
|
||||
NAND_MFR_STMICRO, 0x39);
|
||||
memory_region_init_io(&nand_state.iomem, NULL, &nand_ops, &nand_state,
|
||||
"nand", 0x05000000);
|
||||
memory_region_add_subregion(address_space_mem, 0x10000000,
|
||||
&nand_state.iomem);
|
||||
|
||||
gpio_state.nand = &nand_state;
|
||||
memory_region_init_io(&gpio_state.iomem, NULL, &gpio_ops, &gpio_state,
|
||||
"gpio", 0x5c);
|
||||
memory_region_add_subregion(address_space_mem, 0x3001a000,
|
||||
&gpio_state.iomem);
|
||||
|
||||
|
||||
dev = qdev_new("etraxfs-pic");
|
||||
s = SYS_BUS_DEVICE(dev);
|
||||
sysbus_realize_and_unref(s, &error_fatal);
|
||||
sysbus_mmio_map(s, 0, 0x3001c000);
|
||||
sysbus_connect_irq(s, 0, qdev_get_gpio_in(DEVICE(cpu), CRIS_CPU_IRQ));
|
||||
sysbus_connect_irq(s, 1, qdev_get_gpio_in(DEVICE(cpu), CRIS_CPU_NMI));
|
||||
for (i = 0; i < 30; i++) {
|
||||
irq[i] = qdev_get_gpio_in(dev, i);
|
||||
}
|
||||
nmi[0] = qdev_get_gpio_in(dev, 30);
|
||||
nmi[1] = qdev_get_gpio_in(dev, 31);
|
||||
|
||||
etraxfs_dmac = etraxfs_dmac_init(0x30000000, 10);
|
||||
for (i = 0; i < 10; i++) {
|
||||
/* On ETRAX, odd numbered channels are inputs. */
|
||||
etraxfs_dmac_connect(etraxfs_dmac, i, irq + 7 + i, i & 1);
|
||||
}
|
||||
|
||||
/* Add the two ethernet blocks. */
|
||||
dma_eth = g_malloc0(sizeof dma_eth[0] * 4); /* Allocate 4 channels. */
|
||||
|
||||
etraxfs_eth_init(0x30034000, 1, &dma_eth[0], &dma_eth[1]);
|
||||
/* The DMA Connector block is missing, hardwire things for now. */
|
||||
etraxfs_dmac_connect_client(etraxfs_dmac, 0, &dma_eth[0]);
|
||||
etraxfs_dmac_connect_client(etraxfs_dmac, 1, &dma_eth[1]);
|
||||
|
||||
if (qemu_find_nic_info("etraxfs-eth", true, "fseth")) {
|
||||
etraxfs_eth_init(0x30036000, 2, &dma_eth[2], &dma_eth[3]);
|
||||
etraxfs_dmac_connect_client(etraxfs_dmac, 6, &dma_eth[2]);
|
||||
etraxfs_dmac_connect_client(etraxfs_dmac, 7, &dma_eth[3]);
|
||||
}
|
||||
|
||||
/* 2 timers. */
|
||||
sysbus_create_varargs("etraxfs-timer", 0x3001e000, irq[0x1b], nmi[1], NULL);
|
||||
sysbus_create_varargs("etraxfs-timer", 0x3005e000, irq[0x1b], nmi[1], NULL);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
etraxfs_ser_create(0x30026000 + i * 0x2000, irq[0x14 + i], serial_hd(i));
|
||||
}
|
||||
|
||||
if (kernel_filename) {
|
||||
li.image_filename = kernel_filename;
|
||||
li.cmdline = kernel_cmdline;
|
||||
li.ram_size = machine->ram_size;
|
||||
cris_load_image(cpu, &li);
|
||||
} else if (!qtest_enabled()) {
|
||||
fprintf(stderr, "Kernel image must be specified\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void axisdev88_machine_init(MachineClass *mc)
|
||||
{
|
||||
mc->desc = "AXIS devboard 88";
|
||||
mc->init = axisdev88_init;
|
||||
mc->is_default = true;
|
||||
mc->default_cpu_type = CRIS_CPU_TYPE_NAME("crisv32");
|
||||
mc->default_ram_id = "axisdev88.ram";
|
||||
}
|
||||
|
||||
DEFINE_MACHINE("axis-dev88", axisdev88_machine_init)
|
102
hw/cris/boot.c
102
hw/cris/boot.c
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
* CRIS image loading.
|
||||
*
|
||||
* Copyright (c) 2010 Edgar E. Iglesias, Axis Communications AB.
|
||||
*
|
||||
* 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 "cpu.h"
|
||||
#include "hw/loader.h"
|
||||
#include "elf.h"
|
||||
#include "boot.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "sysemu/reset.h"
|
||||
|
||||
static void main_cpu_reset(void *opaque)
|
||||
{
|
||||
CRISCPU *cpu = opaque;
|
||||
CPUCRISState *env = &cpu->env;
|
||||
struct cris_load_info *li;
|
||||
|
||||
li = env->load_info;
|
||||
|
||||
cpu_reset(CPU(cpu));
|
||||
|
||||
if (!li) {
|
||||
/* nothing more to do. */
|
||||
return;
|
||||
}
|
||||
|
||||
env->pc = li->entry;
|
||||
|
||||
if (li->image_filename) {
|
||||
env->regs[8] = 0x56902387; /* RAM boot magic. */
|
||||
env->regs[9] = 0x40004000 + li->image_size;
|
||||
}
|
||||
|
||||
if (li->cmdline) {
|
||||
/* Let the kernel know we are modifying the cmdline. */
|
||||
env->regs[10] = 0x87109563;
|
||||
env->regs[11] = 0x40000000;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
|
||||
{
|
||||
return addr - 0x80000000LL;
|
||||
}
|
||||
|
||||
void cris_load_image(CRISCPU *cpu, struct cris_load_info *li)
|
||||
{
|
||||
CPUCRISState *env = &cpu->env;
|
||||
uint64_t entry;
|
||||
int kcmdline_len;
|
||||
int image_size;
|
||||
|
||||
env->load_info = li;
|
||||
/* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis
|
||||
devboard SDK. */
|
||||
image_size = load_elf(li->image_filename, NULL,
|
||||
translate_kernel_address, NULL,
|
||||
&entry, NULL, NULL, NULL, 0, EM_CRIS, 0, 0);
|
||||
li->entry = entry;
|
||||
if (image_size < 0) {
|
||||
/* Takes a kimage from the axis devboard SDK. */
|
||||
image_size = load_image_targphys(li->image_filename, 0x40004000,
|
||||
li->ram_size);
|
||||
li->entry = 0x40004000;
|
||||
}
|
||||
|
||||
if (image_size < 0) {
|
||||
fprintf(stderr, "qemu: could not load kernel '%s'\n",
|
||||
li->image_filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (li->cmdline && (kcmdline_len = strlen(li->cmdline))) {
|
||||
if (kcmdline_len > 256) {
|
||||
fprintf(stderr, "Too long CRIS kernel cmdline (max 256)\n");
|
||||
exit(1);
|
||||
}
|
||||
pstrcpy_targphys("cmdline", 0x40000000, 256, li->cmdline);
|
||||
}
|
||||
qemu_register_reset(main_cpu_reset, cpu);
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef HW_CRIS_BOOT_H
|
||||
#define HW_CRIS_BOOT_H
|
||||
|
||||
struct cris_load_info
|
||||
{
|
||||
const char *image_filename;
|
||||
const char *cmdline;
|
||||
int image_size;
|
||||
ram_addr_t ram_size;
|
||||
|
||||
hwaddr entry;
|
||||
};
|
||||
|
||||
void cris_load_image(CRISCPU *cpu, struct cris_load_info *li);
|
||||
|
||||
#endif
|
|
@ -1,5 +0,0 @@
|
|||
cris_ss = ss.source_set()
|
||||
cris_ss.add(files('boot.c'))
|
||||
cris_ss.add(when: 'CONFIG_AXIS', if_true: files('axis_dev88.c'))
|
||||
|
||||
hw_arch += {'cris': cris_ss}
|
|
@ -1,781 +0,0 @@
|
|||
/*
|
||||
* QEMU ETRAX DMA Controller.
|
||||
*
|
||||
* Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
|
||||
*
|
||||
* 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 "hw/hw.h"
|
||||
#include "hw/irq.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "exec/memory.h"
|
||||
|
||||
#include "hw/cris/etraxfs_dma.h"
|
||||
|
||||
#define D(x)
|
||||
|
||||
#define RW_DATA (0x0 / 4)
|
||||
#define RW_SAVED_DATA (0x58 / 4)
|
||||
#define RW_SAVED_DATA_BUF (0x5c / 4)
|
||||
#define RW_GROUP (0x60 / 4)
|
||||
#define RW_GROUP_DOWN (0x7c / 4)
|
||||
#define RW_CMD (0x80 / 4)
|
||||
#define RW_CFG (0x84 / 4)
|
||||
#define RW_STAT (0x88 / 4)
|
||||
#define RW_INTR_MASK (0x8c / 4)
|
||||
#define RW_ACK_INTR (0x90 / 4)
|
||||
#define R_INTR (0x94 / 4)
|
||||
#define R_MASKED_INTR (0x98 / 4)
|
||||
#define RW_STREAM_CMD (0x9c / 4)
|
||||
|
||||
#define DMA_REG_MAX (0x100 / 4)
|
||||
|
||||
/* descriptors */
|
||||
|
||||
// ------------------------------------------------------------ dma_descr_group
|
||||
typedef struct dma_descr_group {
|
||||
uint32_t next;
|
||||
unsigned eol : 1;
|
||||
unsigned tol : 1;
|
||||
unsigned bol : 1;
|
||||
unsigned : 1;
|
||||
unsigned intr : 1;
|
||||
unsigned : 2;
|
||||
unsigned en : 1;
|
||||
unsigned : 7;
|
||||
unsigned dis : 1;
|
||||
unsigned md : 16;
|
||||
struct dma_descr_group *up;
|
||||
union {
|
||||
struct dma_descr_context *context;
|
||||
struct dma_descr_group *group;
|
||||
} down;
|
||||
} dma_descr_group;
|
||||
|
||||
// ---------------------------------------------------------- dma_descr_context
|
||||
typedef struct dma_descr_context {
|
||||
uint32_t next;
|
||||
unsigned eol : 1;
|
||||
unsigned : 3;
|
||||
unsigned intr : 1;
|
||||
unsigned : 1;
|
||||
unsigned store_mode : 1;
|
||||
unsigned en : 1;
|
||||
unsigned : 7;
|
||||
unsigned dis : 1;
|
||||
unsigned md0 : 16;
|
||||
unsigned md1;
|
||||
unsigned md2;
|
||||
unsigned md3;
|
||||
unsigned md4;
|
||||
uint32_t saved_data;
|
||||
uint32_t saved_data_buf;
|
||||
} dma_descr_context;
|
||||
|
||||
// ------------------------------------------------------------- dma_descr_data
|
||||
typedef struct dma_descr_data {
|
||||
uint32_t next;
|
||||
uint32_t buf;
|
||||
unsigned eol : 1;
|
||||
unsigned : 2;
|
||||
unsigned out_eop : 1;
|
||||
unsigned intr : 1;
|
||||
unsigned wait : 1;
|
||||
unsigned : 2;
|
||||
unsigned : 3;
|
||||
unsigned in_eop : 1;
|
||||
unsigned : 4;
|
||||
unsigned md : 16;
|
||||
uint32_t after;
|
||||
} dma_descr_data;
|
||||
|
||||
/* Constants */
|
||||
enum {
|
||||
regk_dma_ack_pkt = 0x00000100,
|
||||
regk_dma_anytime = 0x00000001,
|
||||
regk_dma_array = 0x00000008,
|
||||
regk_dma_burst = 0x00000020,
|
||||
regk_dma_client = 0x00000002,
|
||||
regk_dma_copy_next = 0x00000010,
|
||||
regk_dma_copy_up = 0x00000020,
|
||||
regk_dma_data_at_eol = 0x00000001,
|
||||
regk_dma_dis_c = 0x00000010,
|
||||
regk_dma_dis_g = 0x00000020,
|
||||
regk_dma_idle = 0x00000001,
|
||||
regk_dma_intern = 0x00000004,
|
||||
regk_dma_load_c = 0x00000200,
|
||||
regk_dma_load_c_n = 0x00000280,
|
||||
regk_dma_load_c_next = 0x00000240,
|
||||
regk_dma_load_d = 0x00000140,
|
||||
regk_dma_load_g = 0x00000300,
|
||||
regk_dma_load_g_down = 0x000003c0,
|
||||
regk_dma_load_g_next = 0x00000340,
|
||||
regk_dma_load_g_up = 0x00000380,
|
||||
regk_dma_next_en = 0x00000010,
|
||||
regk_dma_next_pkt = 0x00000010,
|
||||
regk_dma_no = 0x00000000,
|
||||
regk_dma_only_at_wait = 0x00000000,
|
||||
regk_dma_restore = 0x00000020,
|
||||
regk_dma_rst = 0x00000001,
|
||||
regk_dma_running = 0x00000004,
|
||||
regk_dma_rw_cfg_default = 0x00000000,
|
||||
regk_dma_rw_cmd_default = 0x00000000,
|
||||
regk_dma_rw_intr_mask_default = 0x00000000,
|
||||
regk_dma_rw_stat_default = 0x00000101,
|
||||
regk_dma_rw_stream_cmd_default = 0x00000000,
|
||||
regk_dma_save_down = 0x00000020,
|
||||
regk_dma_save_up = 0x00000020,
|
||||
regk_dma_set_reg = 0x00000050,
|
||||
regk_dma_set_w_size1 = 0x00000190,
|
||||
regk_dma_set_w_size2 = 0x000001a0,
|
||||
regk_dma_set_w_size4 = 0x000001c0,
|
||||
regk_dma_stopped = 0x00000002,
|
||||
regk_dma_store_c = 0x00000002,
|
||||
regk_dma_store_descr = 0x00000000,
|
||||
regk_dma_store_g = 0x00000004,
|
||||
regk_dma_store_md = 0x00000001,
|
||||
regk_dma_sw = 0x00000008,
|
||||
regk_dma_update_down = 0x00000020,
|
||||
regk_dma_yes = 0x00000001
|
||||
};
|
||||
|
||||
enum dma_ch_state
|
||||
{
|
||||
RST = 1,
|
||||
STOPPED = 2,
|
||||
RUNNING = 4
|
||||
};
|
||||
|
||||
struct fs_dma_channel
|
||||
{
|
||||
qemu_irq irq;
|
||||
struct etraxfs_dma_client *client;
|
||||
|
||||
/* Internal status. */
|
||||
int stream_cmd_src;
|
||||
enum dma_ch_state state;
|
||||
|
||||
unsigned int input : 1;
|
||||
unsigned int eol : 1;
|
||||
|
||||
struct dma_descr_group current_g;
|
||||
struct dma_descr_context current_c;
|
||||
struct dma_descr_data current_d;
|
||||
|
||||
/* Control registers. */
|
||||
uint32_t regs[DMA_REG_MAX];
|
||||
};
|
||||
|
||||
struct fs_dma_ctrl
|
||||
{
|
||||
MemoryRegion mmio;
|
||||
int nr_channels;
|
||||
struct fs_dma_channel *channels;
|
||||
|
||||
QEMUBH *bh;
|
||||
};
|
||||
|
||||
static void DMA_run(void *opaque);
|
||||
static int channel_out_run(struct fs_dma_ctrl *ctrl, int c);
|
||||
|
||||
static inline uint32_t channel_reg(struct fs_dma_ctrl *ctrl, int c, int reg)
|
||||
{
|
||||
return ctrl->channels[c].regs[reg];
|
||||
}
|
||||
|
||||
static inline int channel_stopped(struct fs_dma_ctrl *ctrl, int c)
|
||||
{
|
||||
return channel_reg(ctrl, c, RW_CFG) & 2;
|
||||
}
|
||||
|
||||
static inline int channel_en(struct fs_dma_ctrl *ctrl, int c)
|
||||
{
|
||||
return (channel_reg(ctrl, c, RW_CFG) & 1)
|
||||
&& ctrl->channels[c].client;
|
||||
}
|
||||
|
||||
static inline int fs_channel(hwaddr addr)
|
||||
{
|
||||
/* Every channel has a 0x2000 ctrl register map. */
|
||||
return addr >> 13;
|
||||
}
|
||||
|
||||
#ifdef USE_THIS_DEAD_CODE
|
||||
static void channel_load_g(struct fs_dma_ctrl *ctrl, int c)
|
||||
{
|
||||
hwaddr addr = channel_reg(ctrl, c, RW_GROUP);
|
||||
|
||||
/* Load and decode. FIXME: handle endianness. */
|
||||
cpu_physical_memory_read(addr, &ctrl->channels[c].current_g,
|
||||
sizeof(ctrl->channels[c].current_g));
|
||||
}
|
||||
|
||||
static void dump_c(int ch, struct dma_descr_context *c)
|
||||
{
|
||||
printf("%s ch=%d\n", __func__, ch);
|
||||
printf("next=%x\n", c->next);
|
||||
printf("saved_data=%x\n", c->saved_data);
|
||||
printf("saved_data_buf=%x\n", c->saved_data_buf);
|
||||
printf("eol=%x\n", (uint32_t) c->eol);
|
||||
}
|
||||
|
||||
static void dump_d(int ch, struct dma_descr_data *d)
|
||||
{
|
||||
printf("%s ch=%d\n", __func__, ch);
|
||||
printf("next=%x\n", d->next);
|
||||
printf("buf=%x\n", d->buf);
|
||||
printf("after=%x\n", d->after);
|
||||
printf("intr=%x\n", (uint32_t) d->intr);
|
||||
printf("out_eop=%x\n", (uint32_t) d->out_eop);
|
||||
printf("in_eop=%x\n", (uint32_t) d->in_eop);
|
||||
printf("eol=%x\n", (uint32_t) d->eol);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void channel_load_c(struct fs_dma_ctrl *ctrl, int c)
|
||||
{
|
||||
hwaddr addr = channel_reg(ctrl, c, RW_GROUP_DOWN);
|
||||
|
||||
/* Load and decode. FIXME: handle endianness. */
|
||||
cpu_physical_memory_read(addr, &ctrl->channels[c].current_c,
|
||||
sizeof(ctrl->channels[c].current_c));
|
||||
|
||||
D(dump_c(c, &ctrl->channels[c].current_c));
|
||||
/* I guess this should update the current pos. */
|
||||
ctrl->channels[c].regs[RW_SAVED_DATA] =
|
||||
(uint32_t)(unsigned long)ctrl->channels[c].current_c.saved_data;
|
||||
ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
|
||||
(uint32_t)(unsigned long)ctrl->channels[c].current_c.saved_data_buf;
|
||||
}
|
||||
|
||||
static void channel_load_d(struct fs_dma_ctrl *ctrl, int c)
|
||||
{
|
||||
hwaddr addr = channel_reg(ctrl, c, RW_SAVED_DATA);
|
||||
|
||||
/* Load and decode. FIXME: handle endianness. */
|
||||
D(printf("%s ch=%d addr=" HWADDR_FMT_plx "\n", __func__, c, addr));
|
||||
cpu_physical_memory_read(addr, &ctrl->channels[c].current_d,
|
||||
sizeof(ctrl->channels[c].current_d));
|
||||
|
||||
D(dump_d(c, &ctrl->channels[c].current_d));
|
||||
ctrl->channels[c].regs[RW_DATA] = addr;
|
||||
}
|
||||
|
||||
static void channel_store_c(struct fs_dma_ctrl *ctrl, int c)
|
||||
{
|
||||
hwaddr addr = channel_reg(ctrl, c, RW_GROUP_DOWN);
|
||||
|
||||
/* Encode and store. FIXME: handle endianness. */
|
||||
D(printf("%s ch=%d addr=" HWADDR_FMT_plx "\n", __func__, c, addr));
|
||||
D(dump_d(c, &ctrl->channels[c].current_d));
|
||||
cpu_physical_memory_write(addr, &ctrl->channels[c].current_c,
|
||||
sizeof(ctrl->channels[c].current_c));
|
||||
}
|
||||
|
||||
static void channel_store_d(struct fs_dma_ctrl *ctrl, int c)
|
||||
{
|
||||
hwaddr addr = channel_reg(ctrl, c, RW_SAVED_DATA);
|
||||
|
||||
/* Encode and store. FIXME: handle endianness. */
|
||||
D(printf("%s ch=%d addr=" HWADDR_FMT_plx "\n", __func__, c, addr));
|
||||
cpu_physical_memory_write(addr, &ctrl->channels[c].current_d,
|
||||
sizeof(ctrl->channels[c].current_d));
|
||||
}
|
||||
|
||||
static inline void channel_stop(struct fs_dma_ctrl *ctrl, int c)
|
||||
{
|
||||
/* FIXME: */
|
||||
}
|
||||
|
||||
static inline void channel_start(struct fs_dma_ctrl *ctrl, int c)
|
||||
{
|
||||
if (ctrl->channels[c].client)
|
||||
{
|
||||
ctrl->channels[c].eol = 0;
|
||||
ctrl->channels[c].state = RUNNING;
|
||||
if (!ctrl->channels[c].input)
|
||||
channel_out_run(ctrl, c);
|
||||
} else
|
||||
printf("WARNING: starting DMA ch %d with no client\n", c);
|
||||
|
||||
qemu_bh_schedule_idle(ctrl->bh);
|
||||
}
|
||||
|
||||
static void channel_continue(struct fs_dma_ctrl *ctrl, int c)
|
||||
{
|
||||
if (!channel_en(ctrl, c)
|
||||
|| channel_stopped(ctrl, c)
|
||||
|| ctrl->channels[c].state != RUNNING
|
||||
/* Only reload the current data descriptor if it has eol set. */
|
||||
|| !ctrl->channels[c].current_d.eol) {
|
||||
D(printf("continue failed ch=%d state=%d stopped=%d en=%d eol=%d\n",
|
||||
c, ctrl->channels[c].state,
|
||||
channel_stopped(ctrl, c),
|
||||
channel_en(ctrl,c),
|
||||
ctrl->channels[c].eol));
|
||||
D(dump_d(c, &ctrl->channels[c].current_d));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reload the current descriptor. */
|
||||
channel_load_d(ctrl, c);
|
||||
|
||||
/* If the current descriptor cleared the eol flag and we had already
|
||||
reached eol state, do the continue. */
|
||||
if (!ctrl->channels[c].current_d.eol && ctrl->channels[c].eol) {
|
||||
D(printf("continue %d ok %x\n", c,
|
||||
ctrl->channels[c].current_d.next));
|
||||
ctrl->channels[c].regs[RW_SAVED_DATA] =
|
||||
(uint32_t)(unsigned long)ctrl->channels[c].current_d.next;
|
||||
channel_load_d(ctrl, c);
|
||||
ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
|
||||
(uint32_t)(unsigned long)ctrl->channels[c].current_d.buf;
|
||||
|
||||
channel_start(ctrl, c);
|
||||
}
|
||||
ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
|
||||
(uint32_t)(unsigned long)ctrl->channels[c].current_d.buf;
|
||||
}
|
||||
|
||||
static void channel_stream_cmd(struct fs_dma_ctrl *ctrl, int c, uint32_t v)
|
||||
{
|
||||
unsigned int cmd = v & ((1 << 10) - 1);
|
||||
|
||||
D(printf("%s ch=%d cmd=%x\n",
|
||||
__func__, c, cmd));
|
||||
if (cmd & regk_dma_load_d) {
|
||||
channel_load_d(ctrl, c);
|
||||
if (cmd & regk_dma_burst)
|
||||
channel_start(ctrl, c);
|
||||
}
|
||||
|
||||
if (cmd & regk_dma_load_c) {
|
||||
channel_load_c(ctrl, c);
|
||||
}
|
||||
}
|
||||
|
||||
static void channel_update_irq(struct fs_dma_ctrl *ctrl, int c)
|
||||
{
|
||||
D(printf("%s %d\n", __func__, c));
|
||||
ctrl->channels[c].regs[R_INTR] &=
|
||||
~(ctrl->channels[c].regs[RW_ACK_INTR]);
|
||||
|
||||
ctrl->channels[c].regs[R_MASKED_INTR] =
|
||||
ctrl->channels[c].regs[R_INTR]
|
||||
& ctrl->channels[c].regs[RW_INTR_MASK];
|
||||
|
||||
D(printf("%s: chan=%d masked_intr=%x\n", __func__,
|
||||
c,
|
||||
ctrl->channels[c].regs[R_MASKED_INTR]));
|
||||
|
||||
qemu_set_irq(ctrl->channels[c].irq,
|
||||
!!ctrl->channels[c].regs[R_MASKED_INTR]);
|
||||
}
|
||||
|
||||
static int channel_out_run(struct fs_dma_ctrl *ctrl, int c)
|
||||
{
|
||||
uint32_t len;
|
||||
uint32_t saved_data_buf;
|
||||
unsigned char buf[2 * 1024];
|
||||
|
||||
struct dma_context_metadata meta;
|
||||
bool send_context = true;
|
||||
|
||||
if (ctrl->channels[c].eol)
|
||||
return 0;
|
||||
|
||||
do {
|
||||
bool out_eop;
|
||||
D(printf("ch=%d buf=%x after=%x\n",
|
||||
c,
|
||||
(uint32_t)ctrl->channels[c].current_d.buf,
|
||||
(uint32_t)ctrl->channels[c].current_d.after));
|
||||
|
||||
if (send_context) {
|
||||
if (ctrl->channels[c].client->client.metadata_push) {
|
||||
meta.metadata = ctrl->channels[c].current_d.md;
|
||||
ctrl->channels[c].client->client.metadata_push(
|
||||
ctrl->channels[c].client->client.opaque,
|
||||
&meta);
|
||||
}
|
||||
send_context = false;
|
||||
}
|
||||
|
||||
channel_load_d(ctrl, c);
|
||||
saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
|
||||
len = (uint32_t)(unsigned long)
|
||||
ctrl->channels[c].current_d.after;
|
||||
len -= saved_data_buf;
|
||||
|
||||
if (len > sizeof buf)
|
||||
len = sizeof buf;
|
||||
cpu_physical_memory_read (saved_data_buf, buf, len);
|
||||
|
||||
out_eop = ((saved_data_buf + len) ==
|
||||
ctrl->channels[c].current_d.after) &&
|
||||
ctrl->channels[c].current_d.out_eop;
|
||||
|
||||
D(printf("channel %d pushes %x %u bytes eop=%u\n", c,
|
||||
saved_data_buf, len, out_eop));
|
||||
|
||||
if (ctrl->channels[c].client->client.push) {
|
||||
if (len > 0) {
|
||||
ctrl->channels[c].client->client.push(
|
||||
ctrl->channels[c].client->client.opaque,
|
||||
buf, len, out_eop);
|
||||
}
|
||||
} else {
|
||||
printf("WARNING: DMA ch%d dataloss,"
|
||||
" no attached client.\n", c);
|
||||
}
|
||||
|
||||
saved_data_buf += len;
|
||||
|
||||
if (saved_data_buf == (uint32_t)(unsigned long)
|
||||
ctrl->channels[c].current_d.after) {
|
||||
/* Done. Step to next. */
|
||||
if (ctrl->channels[c].current_d.out_eop) {
|
||||
send_context = true;
|
||||
}
|
||||
if (ctrl->channels[c].current_d.intr) {
|
||||
/* data intr. */
|
||||
D(printf("signal intr %d eol=%d\n",
|
||||
len, ctrl->channels[c].current_d.eol));
|
||||
ctrl->channels[c].regs[R_INTR] |= (1 << 2);
|
||||
channel_update_irq(ctrl, c);
|
||||
}
|
||||
channel_store_d(ctrl, c);
|
||||
if (ctrl->channels[c].current_d.eol) {
|
||||
D(printf("channel %d EOL\n", c));
|
||||
ctrl->channels[c].eol = 1;
|
||||
|
||||
/* Mark the context as disabled. */
|
||||
ctrl->channels[c].current_c.dis = 1;
|
||||
channel_store_c(ctrl, c);
|
||||
|
||||
channel_stop(ctrl, c);
|
||||
} else {
|
||||
ctrl->channels[c].regs[RW_SAVED_DATA] =
|
||||
(uint32_t)(unsigned long)ctrl->
|
||||
channels[c].current_d.next;
|
||||
/* Load new descriptor. */
|
||||
channel_load_d(ctrl, c);
|
||||
saved_data_buf = (uint32_t)(unsigned long)
|
||||
ctrl->channels[c].current_d.buf;
|
||||
}
|
||||
|
||||
ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
|
||||
saved_data_buf;
|
||||
D(dump_d(c, &ctrl->channels[c].current_d));
|
||||
}
|
||||
ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
|
||||
} while (!ctrl->channels[c].eol);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int channel_in_process(struct fs_dma_ctrl *ctrl, int c,
|
||||
unsigned char *buf, int buflen, int eop)
|
||||
{
|
||||
uint32_t len;
|
||||
uint32_t saved_data_buf;
|
||||
|
||||
if (ctrl->channels[c].eol == 1)
|
||||
return 0;
|
||||
|
||||
channel_load_d(ctrl, c);
|
||||
saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
|
||||
len = (uint32_t)(unsigned long)ctrl->channels[c].current_d.after;
|
||||
len -= saved_data_buf;
|
||||
|
||||
if (len > buflen)
|
||||
len = buflen;
|
||||
|
||||
cpu_physical_memory_write (saved_data_buf, buf, len);
|
||||
saved_data_buf += len;
|
||||
|
||||
if (saved_data_buf ==
|
||||
(uint32_t)(unsigned long)ctrl->channels[c].current_d.after
|
||||
|| eop) {
|
||||
uint32_t r_intr = ctrl->channels[c].regs[R_INTR];
|
||||
|
||||
D(printf("in dscr end len=%d\n",
|
||||
ctrl->channels[c].current_d.after
|
||||
- ctrl->channels[c].current_d.buf));
|
||||
ctrl->channels[c].current_d.after = saved_data_buf;
|
||||
|
||||
/* Done. Step to next. */
|
||||
if (ctrl->channels[c].current_d.intr) {
|
||||
/* TODO: signal eop to the client. */
|
||||
/* data intr. */
|
||||
ctrl->channels[c].regs[R_INTR] |= 3;
|
||||
}
|
||||
if (eop) {
|
||||
ctrl->channels[c].current_d.in_eop = 1;
|
||||
ctrl->channels[c].regs[R_INTR] |= 8;
|
||||
}
|
||||
if (r_intr != ctrl->channels[c].regs[R_INTR])
|
||||
channel_update_irq(ctrl, c);
|
||||
|
||||
channel_store_d(ctrl, c);
|
||||
D(dump_d(c, &ctrl->channels[c].current_d));
|
||||
|
||||
if (ctrl->channels[c].current_d.eol) {
|
||||
D(printf("channel %d EOL\n", c));
|
||||
ctrl->channels[c].eol = 1;
|
||||
|
||||
/* Mark the context as disabled. */
|
||||
ctrl->channels[c].current_c.dis = 1;
|
||||
channel_store_c(ctrl, c);
|
||||
|
||||
channel_stop(ctrl, c);
|
||||
} else {
|
||||
ctrl->channels[c].regs[RW_SAVED_DATA] =
|
||||
(uint32_t)(unsigned long)ctrl->
|
||||
channels[c].current_d.next;
|
||||
/* Load new descriptor. */
|
||||
channel_load_d(ctrl, c);
|
||||
saved_data_buf = (uint32_t)(unsigned long)
|
||||
ctrl->channels[c].current_d.buf;
|
||||
}
|
||||
}
|
||||
|
||||
ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
|
||||
return len;
|
||||
}
|
||||
|
||||
static inline int channel_in_run(struct fs_dma_ctrl *ctrl, int c)
|
||||
{
|
||||
if (ctrl->channels[c].client->client.pull) {
|
||||
ctrl->channels[c].client->client.pull(
|
||||
ctrl->channels[c].client->client.opaque);
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t dma_rinvalid (void *opaque, hwaddr addr)
|
||||
{
|
||||
hw_error("Unsupported short raccess. reg=" HWADDR_FMT_plx "\n", addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
dma_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
{
|
||||
struct fs_dma_ctrl *ctrl = opaque;
|
||||
int c;
|
||||
uint32_t r = 0;
|
||||
|
||||
if (size != 4) {
|
||||
dma_rinvalid(opaque, addr);
|
||||
}
|
||||
|
||||
/* Make addr relative to this channel and bounded to nr regs. */
|
||||
c = fs_channel(addr);
|
||||
addr &= 0xff;
|
||||
addr >>= 2;
|
||||
switch (addr)
|
||||
{
|
||||
case RW_STAT:
|
||||
r = ctrl->channels[c].state & 7;
|
||||
r |= ctrl->channels[c].eol << 5;
|
||||
r |= ctrl->channels[c].stream_cmd_src << 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
r = ctrl->channels[c].regs[addr];
|
||||
D(printf("%s c=%d addr=" HWADDR_FMT_plx "\n",
|
||||
__func__, c, addr));
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
dma_winvalid (void *opaque, hwaddr addr, uint32_t value)
|
||||
{
|
||||
hw_error("Unsupported short waccess. reg=" HWADDR_FMT_plx "\n", addr);
|
||||
}
|
||||
|
||||
static void
|
||||
dma_update_state(struct fs_dma_ctrl *ctrl, int c)
|
||||
{
|
||||
if (ctrl->channels[c].regs[RW_CFG] & 2)
|
||||
ctrl->channels[c].state = STOPPED;
|
||||
if (!(ctrl->channels[c].regs[RW_CFG] & 1))
|
||||
ctrl->channels[c].state = RST;
|
||||
}
|
||||
|
||||
static void
|
||||
dma_write(void *opaque, hwaddr addr,
|
||||
uint64_t val64, unsigned int size)
|
||||
{
|
||||
struct fs_dma_ctrl *ctrl = opaque;
|
||||
uint32_t value = val64;
|
||||
int c;
|
||||
|
||||
if (size != 4) {
|
||||
dma_winvalid(opaque, addr, value);
|
||||
}
|
||||
|
||||
/* Make addr relative to this channel and bounded to nr regs. */
|
||||
c = fs_channel(addr);
|
||||
addr &= 0xff;
|
||||
addr >>= 2;
|
||||
switch (addr)
|
||||
{
|
||||
case RW_DATA:
|
||||
ctrl->channels[c].regs[addr] = value;
|
||||
break;
|
||||
|
||||
case RW_CFG:
|
||||
ctrl->channels[c].regs[addr] = value;
|
||||
dma_update_state(ctrl, c);
|
||||
break;
|
||||
case RW_CMD:
|
||||
/* continue. */
|
||||
if (value & ~1)
|
||||
printf("Invalid store to ch=%d RW_CMD %x\n",
|
||||
c, value);
|
||||
ctrl->channels[c].regs[addr] = value;
|
||||
channel_continue(ctrl, c);
|
||||
break;
|
||||
|
||||
case RW_SAVED_DATA:
|
||||
case RW_SAVED_DATA_BUF:
|
||||
case RW_GROUP:
|
||||
case RW_GROUP_DOWN:
|
||||
ctrl->channels[c].regs[addr] = value;
|
||||
break;
|
||||
|
||||
case RW_ACK_INTR:
|
||||
case RW_INTR_MASK:
|
||||
ctrl->channels[c].regs[addr] = value;
|
||||
channel_update_irq(ctrl, c);
|
||||
if (addr == RW_ACK_INTR)
|
||||
ctrl->channels[c].regs[RW_ACK_INTR] = 0;
|
||||
break;
|
||||
|
||||
case RW_STREAM_CMD:
|
||||
if (value & ~1023)
|
||||
printf("Invalid store to ch=%d "
|
||||
"RW_STREAMCMD %x\n",
|
||||
c, value);
|
||||
ctrl->channels[c].regs[addr] = value;
|
||||
D(printf("stream_cmd ch=%d\n", c));
|
||||
channel_stream_cmd(ctrl, c, value);
|
||||
break;
|
||||
|
||||
default:
|
||||
D(printf("%s c=%d " HWADDR_FMT_plx "\n",
|
||||
__func__, c, addr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps dma_ops = {
|
||||
.read = dma_read,
|
||||
.write = dma_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 4
|
||||
}
|
||||
};
|
||||
|
||||
static int etraxfs_dmac_run(void *opaque)
|
||||
{
|
||||
struct fs_dma_ctrl *ctrl = opaque;
|
||||
int i;
|
||||
int p = 0;
|
||||
|
||||
for (i = 0;
|
||||
i < ctrl->nr_channels;
|
||||
i++)
|
||||
{
|
||||
if (ctrl->channels[i].state == RUNNING)
|
||||
{
|
||||
if (ctrl->channels[i].input) {
|
||||
p += channel_in_run(ctrl, i);
|
||||
} else {
|
||||
p += channel_out_run(ctrl, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
int etraxfs_dmac_input(struct etraxfs_dma_client *client,
|
||||
void *buf, int len, int eop)
|
||||
{
|
||||
return channel_in_process(client->ctrl, client->channel,
|
||||
buf, len, eop);
|
||||
}
|
||||
|
||||
/* Connect an IRQ line with a channel. */
|
||||
void etraxfs_dmac_connect(void *opaque, int c, qemu_irq *line, int input)
|
||||
{
|
||||
struct fs_dma_ctrl *ctrl = opaque;
|
||||
ctrl->channels[c].irq = *line;
|
||||
ctrl->channels[c].input = input;
|
||||
}
|
||||
|
||||
void etraxfs_dmac_connect_client(void *opaque, int c,
|
||||
struct etraxfs_dma_client *cl)
|
||||
{
|
||||
struct fs_dma_ctrl *ctrl = opaque;
|
||||
cl->ctrl = ctrl;
|
||||
cl->channel = c;
|
||||
ctrl->channels[c].client = cl;
|
||||
}
|
||||
|
||||
|
||||
static void DMA_run(void *opaque)
|
||||
{
|
||||
struct fs_dma_ctrl *etraxfs_dmac = opaque;
|
||||
int p = 1;
|
||||
|
||||
if (runstate_is_running())
|
||||
p = etraxfs_dmac_run(etraxfs_dmac);
|
||||
|
||||
if (p)
|
||||
qemu_bh_schedule_idle(etraxfs_dmac->bh);
|
||||
}
|
||||
|
||||
void *etraxfs_dmac_init(hwaddr base, int nr_channels)
|
||||
{
|
||||
struct fs_dma_ctrl *ctrl = NULL;
|
||||
|
||||
ctrl = g_malloc0(sizeof *ctrl);
|
||||
|
||||
ctrl->bh = qemu_bh_new(DMA_run, ctrl);
|
||||
|
||||
ctrl->nr_channels = nr_channels;
|
||||
ctrl->channels = g_malloc0(sizeof ctrl->channels[0] * nr_channels);
|
||||
|
||||
memory_region_init_io(&ctrl->mmio, NULL, &dma_ops, ctrl, "etraxfs-dma",
|
||||
nr_channels * 0x2000);
|
||||
memory_region_add_subregion(get_system_memory(), base, &ctrl->mmio);
|
||||
|
||||
return ctrl;
|
||||
}
|
|
@ -5,7 +5,6 @@ system_ss.add(when: 'CONFIG_I82374', if_true: files('i82374.c'))
|
|||
system_ss.add(when: 'CONFIG_I8257', if_true: files('i8257.c'))
|
||||
system_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('xilinx_axidma.c'))
|
||||
system_ss.add(when: 'CONFIG_ZYNQ_DEVCFG', if_true: files('xlnx-zynq-devcfg.c'))
|
||||
system_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_dma.c'))
|
||||
system_ss.add(when: 'CONFIG_STP2000', if_true: files('sparc32_dma.c'))
|
||||
system_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx_dpdma.c'))
|
||||
system_ss.add(when: 'CONFIG_XLNX_ZDMA', if_true: files('xlnx-zdma.c'))
|
||||
|
|
|
@ -40,7 +40,6 @@ static bool is_connected(uint32_t config, uint32_t level)
|
|||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
|
||||
return state;
|
||||
|
|
|
@ -38,6 +38,7 @@ struct MouseState {
|
|||
ADBDevice parent_obj;
|
||||
/*< private >*/
|
||||
|
||||
QemuInputHandlerState *hs;
|
||||
int buttons_state, last_buttons_state;
|
||||
int dx, dy, dz;
|
||||
};
|
||||
|
@ -51,17 +52,57 @@ struct ADBMouseClass {
|
|||
DeviceRealize parent_realize;
|
||||
};
|
||||
|
||||
static void adb_mouse_event(void *opaque,
|
||||
int dx1, int dy1, int dz1, int buttons_state)
|
||||
{
|
||||
MouseState *s = opaque;
|
||||
#define ADB_MOUSE_BUTTON_LEFT 0x01
|
||||
#define ADB_MOUSE_BUTTON_RIGHT 0x02
|
||||
|
||||
s->dx += dx1;
|
||||
s->dy += dy1;
|
||||
s->dz += dz1;
|
||||
s->buttons_state = buttons_state;
|
||||
static void adb_mouse_handle_event(DeviceState *dev, QemuConsole *src,
|
||||
InputEvent *evt)
|
||||
{
|
||||
MouseState *s = (MouseState *)dev;
|
||||
InputMoveEvent *move;
|
||||
InputBtnEvent *btn;
|
||||
static const int bmap[INPUT_BUTTON__MAX] = {
|
||||
[INPUT_BUTTON_LEFT] = ADB_MOUSE_BUTTON_LEFT,
|
||||
[INPUT_BUTTON_RIGHT] = ADB_MOUSE_BUTTON_RIGHT,
|
||||
};
|
||||
|
||||
switch (evt->type) {
|
||||
case INPUT_EVENT_KIND_REL:
|
||||
move = evt->u.rel.data;
|
||||
if (move->axis == INPUT_AXIS_X) {
|
||||
s->dx += move->value;
|
||||
} else if (move->axis == INPUT_AXIS_Y) {
|
||||
s->dy += move->value;
|
||||
}
|
||||
break;
|
||||
|
||||
case INPUT_EVENT_KIND_BTN:
|
||||
btn = evt->u.btn.data;
|
||||
if (bmap[btn->button]) {
|
||||
if (btn->down) {
|
||||
s->buttons_state |= bmap[btn->button];
|
||||
} else {
|
||||
s->buttons_state &= ~bmap[btn->button];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* keep gcc happy */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const QemuInputHandler adb_mouse_handler = {
|
||||
.name = "QEMU ADB Mouse",
|
||||
.mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
|
||||
.event = adb_mouse_handle_event,
|
||||
/*
|
||||
* We do not need the .sync handler because unlike e.g. PS/2 where async
|
||||
* mouse events are sent over the serial port, an ADB mouse is constantly
|
||||
* polled by the host via the adb_mouse_poll() callback.
|
||||
*/
|
||||
};
|
||||
|
||||
static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
|
||||
{
|
||||
|
@ -94,10 +135,10 @@ static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
|
|||
dx &= 0x7f;
|
||||
dy &= 0x7f;
|
||||
|
||||
if (!(s->buttons_state & MOUSE_EVENT_LBUTTON)) {
|
||||
if (!(s->buttons_state & ADB_MOUSE_BUTTON_LEFT)) {
|
||||
dy |= 0x80;
|
||||
}
|
||||
if (!(s->buttons_state & MOUSE_EVENT_RBUTTON)) {
|
||||
if (!(s->buttons_state & ADB_MOUSE_BUTTON_RIGHT)) {
|
||||
dx |= 0x80;
|
||||
}
|
||||
|
||||
|
@ -236,7 +277,7 @@ static void adb_mouse_realizefn(DeviceState *dev, Error **errp)
|
|||
|
||||
amc->parent_realize(dev, errp);
|
||||
|
||||
qemu_add_mouse_event_handler(adb_mouse_event, s, 0, "QEMU ADB Mouse");
|
||||
s->hs = qemu_input_handler_register(dev, &adb_mouse_handler);
|
||||
}
|
||||
|
||||
static void adb_mouse_initfn(Object *obj)
|
||||
|
|
|
@ -1,172 +0,0 @@
|
|||
/*
|
||||
* QEMU ETRAX Interrupt Controller.
|
||||
*
|
||||
* Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
|
||||
*
|
||||
* 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 "hw/sysbus.h"
|
||||
#include "qemu/module.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define D(x)
|
||||
|
||||
#define R_RW_MASK 0
|
||||
#define R_R_VECT 1
|
||||
#define R_R_MASKED_VECT 2
|
||||
#define R_R_NMI 3
|
||||
#define R_R_GURU 4
|
||||
#define R_MAX 5
|
||||
|
||||
#define TYPE_ETRAX_FS_PIC "etraxfs-pic"
|
||||
DECLARE_INSTANCE_CHECKER(struct etrax_pic, ETRAX_FS_PIC,
|
||||
TYPE_ETRAX_FS_PIC)
|
||||
|
||||
struct etrax_pic
|
||||
{
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion mmio;
|
||||
qemu_irq parent_irq;
|
||||
qemu_irq parent_nmi;
|
||||
uint32_t regs[R_MAX];
|
||||
};
|
||||
|
||||
static void pic_update(struct etrax_pic *fs)
|
||||
{
|
||||
uint32_t vector = 0;
|
||||
int i;
|
||||
|
||||
fs->regs[R_R_MASKED_VECT] = fs->regs[R_R_VECT] & fs->regs[R_RW_MASK];
|
||||
|
||||
/* The ETRAX interrupt controller signals interrupts to the core
|
||||
through an interrupt request wire and an irq vector bus. If
|
||||
multiple interrupts are simultaneously active it chooses vector
|
||||
0x30 and lets the sw choose the priorities. */
|
||||
if (fs->regs[R_R_MASKED_VECT]) {
|
||||
uint32_t mv = fs->regs[R_R_MASKED_VECT];
|
||||
for (i = 0; i < 31; i++) {
|
||||
if (mv & 1) {
|
||||
vector = 0x31 + i;
|
||||
/* Check for multiple interrupts. */
|
||||
if (mv > 1)
|
||||
vector = 0x30;
|
||||
break;
|
||||
}
|
||||
mv >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
qemu_set_irq(fs->parent_irq, vector);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
pic_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
{
|
||||
struct etrax_pic *fs = opaque;
|
||||
uint32_t rval;
|
||||
|
||||
rval = fs->regs[addr >> 2];
|
||||
D(printf("%s %x=%x\n", __func__, addr, rval));
|
||||
return rval;
|
||||
}
|
||||
|
||||
static void pic_write(void *opaque, hwaddr addr,
|
||||
uint64_t value, unsigned int size)
|
||||
{
|
||||
struct etrax_pic *fs = opaque;
|
||||
D(printf("%s addr=%x val=%x\n", __func__, addr, value));
|
||||
|
||||
if (addr == R_RW_MASK) {
|
||||
fs->regs[R_RW_MASK] = value;
|
||||
pic_update(fs);
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps pic_ops = {
|
||||
.read = pic_read,
|
||||
.write = pic_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4
|
||||
}
|
||||
};
|
||||
|
||||
static void nmi_handler(void *opaque, int irq, int level)
|
||||
{
|
||||
struct etrax_pic *fs = (void *)opaque;
|
||||
uint32_t mask;
|
||||
|
||||
mask = 1 << irq;
|
||||
if (level)
|
||||
fs->regs[R_R_NMI] |= mask;
|
||||
else
|
||||
fs->regs[R_R_NMI] &= ~mask;
|
||||
|
||||
qemu_set_irq(fs->parent_nmi, !!fs->regs[R_R_NMI]);
|
||||
}
|
||||
|
||||
static void irq_handler(void *opaque, int irq, int level)
|
||||
{
|
||||
struct etrax_pic *fs = (void *)opaque;
|
||||
|
||||
if (irq >= 30) {
|
||||
nmi_handler(opaque, irq, level);
|
||||
return;
|
||||
}
|
||||
|
||||
irq -= 1;
|
||||
fs->regs[R_R_VECT] &= ~(1 << irq);
|
||||
fs->regs[R_R_VECT] |= (!!level << irq);
|
||||
pic_update(fs);
|
||||
}
|
||||
|
||||
static void etraxfs_pic_init(Object *obj)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
struct etrax_pic *s = ETRAX_FS_PIC(obj);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
|
||||
qdev_init_gpio_in(dev, irq_handler, 32);
|
||||
sysbus_init_irq(sbd, &s->parent_irq);
|
||||
sysbus_init_irq(sbd, &s->parent_nmi);
|
||||
|
||||
memory_region_init_io(&s->mmio, obj, &pic_ops, s,
|
||||
"etraxfs-pic", R_MAX * 4);
|
||||
sysbus_init_mmio(sbd, &s->mmio);
|
||||
}
|
||||
|
||||
static const TypeInfo etraxfs_pic_info = {
|
||||
.name = TYPE_ETRAX_FS_PIC,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(struct etrax_pic),
|
||||
.instance_init = etraxfs_pic_init,
|
||||
};
|
||||
|
||||
static void etraxfs_pic_register_types(void)
|
||||
{
|
||||
type_register_static(&etraxfs_pic_info);
|
||||
}
|
||||
|
||||
type_init(etraxfs_pic_register_types)
|
|
@ -6,18 +6,9 @@
|
|||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/intc/loongson_ipi.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/log.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "exec/memory.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "target/mips/cpu.h"
|
||||
#include "trace.h"
|
||||
|
||||
static AddressSpace *get_iocsr_as(CPUState *cpu)
|
||||
{
|
||||
|
|
|
@ -15,7 +15,6 @@ system_ss.add(when: 'CONFIG_ARM_GICV3_TCG', if_true: files(
|
|||
system_ss.add(when: 'CONFIG_ALLWINNER_A10_PIC', if_true: files('allwinner-a10-pic.c'))
|
||||
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_vic.c'))
|
||||
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_intc.c'))
|
||||
system_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_pic.c'))
|
||||
system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_gic.c', 'exynos4210_combiner.c'))
|
||||
system_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: files('goldfish_pic.c'))
|
||||
system_ss.add(when: 'CONFIG_HEATHROW_PIC', if_true: files('heathrow_pic.c'))
|
||||
|
|
|
@ -48,7 +48,6 @@ subdir('fsi')
|
|||
subdir('alpha')
|
||||
subdir('arm')
|
||||
subdir('avr')
|
||||
subdir('cris')
|
||||
subdir('hppa')
|
||||
subdir('i386')
|
||||
subdir('loongarch')
|
||||
|
|
|
@ -301,7 +301,6 @@ static uint64_t imx6_analog_get_periph_clk(IMX6CCMState *dev)
|
|||
default:
|
||||
/* We should never get there */
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
|
||||
trace_imx6_analog_get_periph_clk(freq);
|
||||
|
|
|
@ -495,7 +495,6 @@ static void via1_rtc_update(MOS6522Q800VIA1State *v1s)
|
|||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -556,7 +555,6 @@ static void via1_rtc_update(MOS6522Q800VIA1State *v1s)
|
|||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,688 +0,0 @@
|
|||
/*
|
||||
* QEMU ETRAX Ethernet Controller.
|
||||
*
|
||||
* Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
|
||||
*
|
||||
* 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 "qapi/error.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "net/net.h"
|
||||
#include "hw/cris/etraxfs.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/module.h"
|
||||
#include "trace.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define D(x)
|
||||
|
||||
/* Advertisement control register. */
|
||||
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
|
||||
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
|
||||
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
|
||||
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
|
||||
|
||||
/*
|
||||
* The MDIO extensions in the TDK PHY model were reversed engineered from the
|
||||
* linux driver (PHYID and Diagnostics reg).
|
||||
* TODO: Add friendly names for the register nums.
|
||||
*/
|
||||
struct qemu_phy
|
||||
{
|
||||
uint32_t regs[32];
|
||||
|
||||
int link;
|
||||
|
||||
unsigned int (*read)(struct qemu_phy *phy, unsigned int req);
|
||||
void (*write)(struct qemu_phy *phy, unsigned int req, unsigned int data);
|
||||
};
|
||||
|
||||
static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req)
|
||||
{
|
||||
int regnum;
|
||||
unsigned r = 0;
|
||||
|
||||
regnum = req & 0x1f;
|
||||
|
||||
switch (regnum) {
|
||||
case 1:
|
||||
if (!phy->link) {
|
||||
break;
|
||||
}
|
||||
/* MR1. */
|
||||
/* Speeds and modes. */
|
||||
r |= (1 << 13) | (1 << 14);
|
||||
r |= (1 << 11) | (1 << 12);
|
||||
r |= (1 << 5); /* Autoneg complete. */
|
||||
r |= (1 << 3); /* Autoneg able. */
|
||||
r |= (1 << 2); /* link. */
|
||||
break;
|
||||
case 5:
|
||||
/* Link partner ability.
|
||||
We are kind; always agree with whatever best mode
|
||||
the guest advertises. */
|
||||
r = 1 << 14; /* Success. */
|
||||
/* Copy advertised modes. */
|
||||
r |= phy->regs[4] & (15 << 5);
|
||||
/* Autoneg support. */
|
||||
r |= 1;
|
||||
break;
|
||||
case 18:
|
||||
{
|
||||
/* Diagnostics reg. */
|
||||
int duplex = 0;
|
||||
int speed_100 = 0;
|
||||
|
||||
if (!phy->link) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Are we advertising 100 half or 100 duplex ? */
|
||||
speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF);
|
||||
speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL);
|
||||
|
||||
/* Are we advertising 10 duplex or 100 duplex ? */
|
||||
duplex = !!(phy->regs[4] & ADVERTISE_100FULL);
|
||||
duplex |= !!(phy->regs[4] & ADVERTISE_10FULL);
|
||||
r = (speed_100 << 10) | (duplex << 11);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
r = phy->regs[regnum];
|
||||
break;
|
||||
}
|
||||
trace_mdio_phy_read(regnum, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
tdk_write(struct qemu_phy *phy, unsigned int req, unsigned int data)
|
||||
{
|
||||
int regnum;
|
||||
|
||||
regnum = req & 0x1f;
|
||||
trace_mdio_phy_write(regnum, data);
|
||||
switch (regnum) {
|
||||
default:
|
||||
phy->regs[regnum] = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tdk_reset(struct qemu_phy *phy)
|
||||
{
|
||||
phy->regs[0] = 0x3100;
|
||||
/* PHY Id. */
|
||||
phy->regs[2] = 0x0300;
|
||||
phy->regs[3] = 0xe400;
|
||||
/* Autonegotiation advertisement reg. */
|
||||
phy->regs[4] = 0x01E1;
|
||||
phy->link = 1;
|
||||
}
|
||||
|
||||
struct qemu_mdio
|
||||
{
|
||||
/* bus. */
|
||||
int mdc;
|
||||
int mdio;
|
||||
|
||||
/* decoder. */
|
||||
enum {
|
||||
PREAMBLE,
|
||||
SOF,
|
||||
OPC,
|
||||
ADDR,
|
||||
REQ,
|
||||
TURNAROUND,
|
||||
DATA
|
||||
} state;
|
||||
unsigned int drive;
|
||||
|
||||
unsigned int cnt;
|
||||
unsigned int addr;
|
||||
unsigned int opc;
|
||||
unsigned int req;
|
||||
unsigned int data;
|
||||
|
||||
struct qemu_phy *devs[32];
|
||||
};
|
||||
|
||||
static void
|
||||
mdio_attach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr)
|
||||
{
|
||||
bus->devs[addr & 0x1f] = phy;
|
||||
}
|
||||
|
||||
#ifdef USE_THIS_DEAD_CODE
|
||||
static void
|
||||
mdio_detach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr)
|
||||
{
|
||||
bus->devs[addr & 0x1f] = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void mdio_read_req(struct qemu_mdio *bus)
|
||||
{
|
||||
struct qemu_phy *phy;
|
||||
|
||||
phy = bus->devs[bus->addr];
|
||||
if (phy && phy->read) {
|
||||
bus->data = phy->read(phy, bus->req);
|
||||
} else {
|
||||
bus->data = 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
static void mdio_write_req(struct qemu_mdio *bus)
|
||||
{
|
||||
struct qemu_phy *phy;
|
||||
|
||||
phy = bus->devs[bus->addr];
|
||||
if (phy && phy->write) {
|
||||
phy->write(phy, bus->req, bus->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void mdio_cycle(struct qemu_mdio *bus)
|
||||
{
|
||||
bus->cnt++;
|
||||
|
||||
trace_mdio_bitbang(bus->mdc, bus->mdio, bus->state, bus->cnt, bus->drive);
|
||||
#if 0
|
||||
if (bus->mdc) {
|
||||
printf("%d", bus->mdio);
|
||||
}
|
||||
#endif
|
||||
switch (bus->state) {
|
||||
case PREAMBLE:
|
||||
if (bus->mdc) {
|
||||
if (bus->cnt >= (32 * 2) && !bus->mdio) {
|
||||
bus->cnt = 0;
|
||||
bus->state = SOF;
|
||||
bus->data = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SOF:
|
||||
if (bus->mdc) {
|
||||
if (bus->mdio != 1) {
|
||||
printf("WARNING: no SOF\n");
|
||||
}
|
||||
if (bus->cnt == 1*2) {
|
||||
bus->cnt = 0;
|
||||
bus->opc = 0;
|
||||
bus->state = OPC;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OPC:
|
||||
if (bus->mdc) {
|
||||
bus->opc <<= 1;
|
||||
bus->opc |= bus->mdio & 1;
|
||||
if (bus->cnt == 2*2) {
|
||||
bus->cnt = 0;
|
||||
bus->addr = 0;
|
||||
bus->state = ADDR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ADDR:
|
||||
if (bus->mdc) {
|
||||
bus->addr <<= 1;
|
||||
bus->addr |= bus->mdio & 1;
|
||||
|
||||
if (bus->cnt == 5*2) {
|
||||
bus->cnt = 0;
|
||||
bus->req = 0;
|
||||
bus->state = REQ;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case REQ:
|
||||
if (bus->mdc) {
|
||||
bus->req <<= 1;
|
||||
bus->req |= bus->mdio & 1;
|
||||
if (bus->cnt == 5*2) {
|
||||
bus->cnt = 0;
|
||||
bus->state = TURNAROUND;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TURNAROUND:
|
||||
if (bus->mdc && bus->cnt == 2*2) {
|
||||
bus->mdio = 0;
|
||||
bus->cnt = 0;
|
||||
|
||||
if (bus->opc == 2) {
|
||||
bus->drive = 1;
|
||||
mdio_read_req(bus);
|
||||
bus->mdio = bus->data & 1;
|
||||
}
|
||||
bus->state = DATA;
|
||||
}
|
||||
break;
|
||||
case DATA:
|
||||
if (!bus->mdc) {
|
||||
if (bus->drive) {
|
||||
bus->mdio = !!(bus->data & (1 << 15));
|
||||
bus->data <<= 1;
|
||||
}
|
||||
} else {
|
||||
if (!bus->drive) {
|
||||
bus->data <<= 1;
|
||||
bus->data |= bus->mdio;
|
||||
}
|
||||
if (bus->cnt == 16 * 2) {
|
||||
bus->cnt = 0;
|
||||
bus->state = PREAMBLE;
|
||||
if (!bus->drive) {
|
||||
mdio_write_req(bus);
|
||||
}
|
||||
bus->drive = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* ETRAX-FS Ethernet MAC block starts here. */
|
||||
|
||||
#define RW_MA0_LO 0x00
|
||||
#define RW_MA0_HI 0x01
|
||||
#define RW_MA1_LO 0x02
|
||||
#define RW_MA1_HI 0x03
|
||||
#define RW_GA_LO 0x04
|
||||
#define RW_GA_HI 0x05
|
||||
#define RW_GEN_CTRL 0x06
|
||||
#define RW_REC_CTRL 0x07
|
||||
#define RW_TR_CTRL 0x08
|
||||
#define RW_CLR_ERR 0x09
|
||||
#define RW_MGM_CTRL 0x0a
|
||||
#define R_STAT 0x0b
|
||||
#define FS_ETH_MAX_REGS 0x17
|
||||
|
||||
#define TYPE_ETRAX_FS_ETH "etraxfs-eth"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(ETRAXFSEthState, ETRAX_FS_ETH)
|
||||
|
||||
struct ETRAXFSEthState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion mmio;
|
||||
NICState *nic;
|
||||
NICConf conf;
|
||||
|
||||
/* Two addrs in the filter. */
|
||||
uint8_t macaddr[2][6];
|
||||
uint32_t regs[FS_ETH_MAX_REGS];
|
||||
|
||||
struct etraxfs_dma_client *dma_out;
|
||||
struct etraxfs_dma_client *dma_in;
|
||||
|
||||
/* MDIO bus. */
|
||||
struct qemu_mdio mdio_bus;
|
||||
unsigned int phyaddr;
|
||||
int duplex_mismatch;
|
||||
|
||||
/* PHY. */
|
||||
struct qemu_phy phy;
|
||||
};
|
||||
|
||||
static void eth_validate_duplex(ETRAXFSEthState *eth)
|
||||
{
|
||||
struct qemu_phy *phy;
|
||||
unsigned int phy_duplex;
|
||||
unsigned int mac_duplex;
|
||||
int new_mm = 0;
|
||||
|
||||
phy = eth->mdio_bus.devs[eth->phyaddr];
|
||||
phy_duplex = !!(phy->read(phy, 18) & (1 << 11));
|
||||
mac_duplex = !!(eth->regs[RW_REC_CTRL] & 128);
|
||||
|
||||
if (mac_duplex != phy_duplex) {
|
||||
new_mm = 1;
|
||||
}
|
||||
|
||||
if (eth->regs[RW_GEN_CTRL] & 1) {
|
||||
if (new_mm != eth->duplex_mismatch) {
|
||||
if (new_mm) {
|
||||
printf("HW: WARNING ETH duplex mismatch MAC=%d PHY=%d\n",
|
||||
mac_duplex, phy_duplex);
|
||||
} else {
|
||||
printf("HW: ETH duplex ok.\n");
|
||||
}
|
||||
}
|
||||
eth->duplex_mismatch = new_mm;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
eth_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
{
|
||||
ETRAXFSEthState *eth = opaque;
|
||||
uint32_t r = 0;
|
||||
|
||||
addr >>= 2;
|
||||
|
||||
switch (addr) {
|
||||
case R_STAT:
|
||||
r = eth->mdio_bus.mdio & 1;
|
||||
break;
|
||||
default:
|
||||
r = eth->regs[addr];
|
||||
D(printf("%s %x\n", __func__, addr * 4));
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static void eth_update_ma(ETRAXFSEthState *eth, int ma)
|
||||
{
|
||||
int reg;
|
||||
int i = 0;
|
||||
|
||||
ma &= 1;
|
||||
|
||||
reg = RW_MA0_LO;
|
||||
if (ma) {
|
||||
reg = RW_MA1_LO;
|
||||
}
|
||||
|
||||
eth->macaddr[ma][i++] = eth->regs[reg];
|
||||
eth->macaddr[ma][i++] = eth->regs[reg] >> 8;
|
||||
eth->macaddr[ma][i++] = eth->regs[reg] >> 16;
|
||||
eth->macaddr[ma][i++] = eth->regs[reg] >> 24;
|
||||
eth->macaddr[ma][i++] = eth->regs[reg + 1];
|
||||
eth->macaddr[ma][i] = eth->regs[reg + 1] >> 8;
|
||||
|
||||
D(printf("set mac%d=%x.%x.%x.%x.%x.%x\n", ma,
|
||||
eth->macaddr[ma][0], eth->macaddr[ma][1],
|
||||
eth->macaddr[ma][2], eth->macaddr[ma][3],
|
||||
eth->macaddr[ma][4], eth->macaddr[ma][5]));
|
||||
}
|
||||
|
||||
static void
|
||||
eth_write(void *opaque, hwaddr addr,
|
||||
uint64_t val64, unsigned int size)
|
||||
{
|
||||
ETRAXFSEthState *eth = opaque;
|
||||
uint32_t value = val64;
|
||||
|
||||
addr >>= 2;
|
||||
switch (addr) {
|
||||
case RW_MA0_LO:
|
||||
case RW_MA0_HI:
|
||||
eth->regs[addr] = value;
|
||||
eth_update_ma(eth, 0);
|
||||
break;
|
||||
case RW_MA1_LO:
|
||||
case RW_MA1_HI:
|
||||
eth->regs[addr] = value;
|
||||
eth_update_ma(eth, 1);
|
||||
break;
|
||||
|
||||
case RW_MGM_CTRL:
|
||||
/* Attach an MDIO/PHY abstraction. */
|
||||
if (value & 2) {
|
||||
eth->mdio_bus.mdio = value & 1;
|
||||
}
|
||||
if (eth->mdio_bus.mdc != (value & 4)) {
|
||||
mdio_cycle(ð->mdio_bus);
|
||||
eth_validate_duplex(eth);
|
||||
}
|
||||
eth->mdio_bus.mdc = !!(value & 4);
|
||||
eth->regs[addr] = value;
|
||||
break;
|
||||
|
||||
case RW_REC_CTRL:
|
||||
eth->regs[addr] = value;
|
||||
eth_validate_duplex(eth);
|
||||
break;
|
||||
|
||||
default:
|
||||
eth->regs[addr] = value;
|
||||
D(printf("%s %x %x\n", __func__, addr, value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* The ETRAX FS has a groupt address table (GAT) which works like a k=1 bloom
|
||||
filter dropping group addresses we have not joined. The filter has 64
|
||||
bits (m). The has function is a simple nible xor of the group addr. */
|
||||
static int eth_match_groupaddr(ETRAXFSEthState *eth, const unsigned char *sa)
|
||||
{
|
||||
unsigned int hsh;
|
||||
int m_individual = eth->regs[RW_REC_CTRL] & 4;
|
||||
int match;
|
||||
|
||||
/* First bit on the wire of a MAC address signals multicast or
|
||||
physical address. */
|
||||
if (!m_individual && !(sa[0] & 1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate the hash index for the GA registers. */
|
||||
hsh = 0;
|
||||
hsh ^= (*sa) & 0x3f;
|
||||
hsh ^= ((*sa) >> 6) & 0x03;
|
||||
++sa;
|
||||
hsh ^= ((*sa) << 2) & 0x03c;
|
||||
hsh ^= ((*sa) >> 4) & 0xf;
|
||||
++sa;
|
||||
hsh ^= ((*sa) << 4) & 0x30;
|
||||
hsh ^= ((*sa) >> 2) & 0x3f;
|
||||
++sa;
|
||||
hsh ^= (*sa) & 0x3f;
|
||||
hsh ^= ((*sa) >> 6) & 0x03;
|
||||
++sa;
|
||||
hsh ^= ((*sa) << 2) & 0x03c;
|
||||
hsh ^= ((*sa) >> 4) & 0xf;
|
||||
++sa;
|
||||
hsh ^= ((*sa) << 4) & 0x30;
|
||||
hsh ^= ((*sa) >> 2) & 0x3f;
|
||||
|
||||
hsh &= 63;
|
||||
if (hsh > 31) {
|
||||
match = eth->regs[RW_GA_HI] & (1 << (hsh - 32));
|
||||
} else {
|
||||
match = eth->regs[RW_GA_LO] & (1 << hsh);
|
||||
}
|
||||
D(printf("hsh=%x ga=%x.%x mtch=%d\n", hsh,
|
||||
eth->regs[RW_GA_HI], eth->regs[RW_GA_LO], match));
|
||||
return match;
|
||||
}
|
||||
|
||||
static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size)
|
||||
{
|
||||
unsigned char sa_bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
ETRAXFSEthState *eth = qemu_get_nic_opaque(nc);
|
||||
int use_ma0 = eth->regs[RW_REC_CTRL] & 1;
|
||||
int use_ma1 = eth->regs[RW_REC_CTRL] & 2;
|
||||
int r_bcast = eth->regs[RW_REC_CTRL] & 8;
|
||||
|
||||
if (size < 12) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
D(printf("%x.%x.%x.%x.%x.%x ma=%d %d bc=%d\n",
|
||||
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
|
||||
use_ma0, use_ma1, r_bcast));
|
||||
|
||||
/* Does the frame get through the address filters? */
|
||||
if ((!use_ma0 || memcmp(buf, eth->macaddr[0], 6))
|
||||
&& (!use_ma1 || memcmp(buf, eth->macaddr[1], 6))
|
||||
&& (!r_bcast || memcmp(buf, sa_bcast, 6))
|
||||
&& !eth_match_groupaddr(eth, buf)) {
|
||||
return size;
|
||||
}
|
||||
|
||||
/* FIXME: Find another way to pass on the fake csum. */
|
||||
etraxfs_dmac_input(eth->dma_in, (void *)buf, size + 4, 1);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int eth_tx_push(void *opaque, unsigned char *buf, int len, bool eop)
|
||||
{
|
||||
ETRAXFSEthState *eth = opaque;
|
||||
|
||||
D(printf("%s buf=%p len=%d\n", __func__, buf, len));
|
||||
qemu_send_packet(qemu_get_queue(eth->nic), buf, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
static void eth_set_link(NetClientState *nc)
|
||||
{
|
||||
ETRAXFSEthState *eth = qemu_get_nic_opaque(nc);
|
||||
D(printf("%s %d\n", __func__, nc->link_down));
|
||||
eth->phy.link = !nc->link_down;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps eth_ops = {
|
||||
.read = eth_read,
|
||||
.write = eth_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4
|
||||
}
|
||||
};
|
||||
|
||||
static NetClientInfo net_etraxfs_info = {
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = eth_receive,
|
||||
.link_status_changed = eth_set_link,
|
||||
};
|
||||
|
||||
static void etraxfs_eth_reset(DeviceState *dev)
|
||||
{
|
||||
ETRAXFSEthState *s = ETRAX_FS_ETH(dev);
|
||||
|
||||
memset(s->regs, 0, sizeof(s->regs));
|
||||
memset(s->macaddr, 0, sizeof(s->macaddr));
|
||||
s->duplex_mismatch = 0;
|
||||
|
||||
s->mdio_bus.mdc = 0;
|
||||
s->mdio_bus.mdio = 0;
|
||||
s->mdio_bus.state = 0;
|
||||
s->mdio_bus.drive = 0;
|
||||
s->mdio_bus.cnt = 0;
|
||||
s->mdio_bus.addr = 0;
|
||||
s->mdio_bus.opc = 0;
|
||||
s->mdio_bus.req = 0;
|
||||
s->mdio_bus.data = 0;
|
||||
|
||||
tdk_reset(&s->phy);
|
||||
}
|
||||
|
||||
static void etraxfs_eth_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
ETRAXFSEthState *s = ETRAX_FS_ETH(dev);
|
||||
|
||||
if (!s->dma_out || !s->dma_in) {
|
||||
error_setg(errp, "Unconnected ETRAX-FS Ethernet MAC");
|
||||
return;
|
||||
}
|
||||
|
||||
s->dma_out->client.push = eth_tx_push;
|
||||
s->dma_out->client.opaque = s;
|
||||
s->dma_in->client.opaque = s;
|
||||
s->dma_in->client.pull = NULL;
|
||||
|
||||
memory_region_init_io(&s->mmio, OBJECT(dev), ð_ops, s,
|
||||
"etraxfs-eth", 0x5c);
|
||||
sysbus_init_mmio(sbd, &s->mmio);
|
||||
|
||||
qemu_macaddr_default_if_unset(&s->conf.macaddr);
|
||||
s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf,
|
||||
object_get_typename(OBJECT(s)), dev->id,
|
||||
&dev->mem_reentrancy_guard, s);
|
||||
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
|
||||
|
||||
s->phy.read = tdk_read;
|
||||
s->phy.write = tdk_write;
|
||||
mdio_attach(&s->mdio_bus, &s->phy, s->phyaddr);
|
||||
}
|
||||
|
||||
static Property etraxfs_eth_properties[] = {
|
||||
DEFINE_PROP_UINT32("phyaddr", ETRAXFSEthState, phyaddr, 1),
|
||||
DEFINE_NIC_PROPERTIES(ETRAXFSEthState, conf),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void etraxfs_eth_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = etraxfs_eth_realize;
|
||||
device_class_set_legacy_reset(dc, etraxfs_eth_reset);
|
||||
device_class_set_props(dc, etraxfs_eth_properties);
|
||||
/* Reason: dma_out, dma_in are not user settable */
|
||||
dc->user_creatable = false;
|
||||
}
|
||||
|
||||
|
||||
/* Instantiate an ETRAXFS Ethernet MAC. */
|
||||
DeviceState *
|
||||
etraxfs_eth_init(hwaddr base, int phyaddr,
|
||||
struct etraxfs_dma_client *dma_out,
|
||||
struct etraxfs_dma_client *dma_in)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
||||
dev = qdev_new("etraxfs-eth");
|
||||
qemu_configure_nic_device(dev, true, "fseth");
|
||||
qdev_prop_set_uint32(dev, "phyaddr", phyaddr);
|
||||
|
||||
/*
|
||||
* TODO: QOM design, define a QOM interface for "I am an etraxfs
|
||||
* DMA client" (which replaces the current 'struct
|
||||
* etraxfs_dma_client' ad-hoc interface), implement it on the
|
||||
* ethernet device, and then have QOM link properties on the DMA
|
||||
* controller device so that you can pass the interface
|
||||
* implementations to it.
|
||||
*/
|
||||
ETRAX_FS_ETH(dev)->dma_out = dma_out;
|
||||
ETRAX_FS_ETH(dev)->dma_in = dma_in;
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
static const TypeInfo etraxfs_eth_info = {
|
||||
.name = TYPE_ETRAX_FS_ETH,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(ETRAXFSEthState),
|
||||
.class_init = etraxfs_eth_class_init,
|
||||
};
|
||||
|
||||
static void etraxfs_eth_register_types(void)
|
||||
{
|
||||
type_register_static(&etraxfs_eth_info);
|
||||
}
|
||||
|
||||
type_init(etraxfs_eth_register_types)
|
|
@ -40,7 +40,6 @@ system_ss.add(when: 'CONFIG_FTGMAC100', if_true: files('ftgmac100.c'))
|
|||
system_ss.add(when: 'CONFIG_SUNGEM', if_true: files('sungem.c'))
|
||||
system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_emc.c', 'npcm_gmac.c'))
|
||||
|
||||
system_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_eth.c'))
|
||||
system_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_fec.c'))
|
||||
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_llan.c'))
|
||||
system_ss.add(when: 'CONFIG_XILINX_ETHLITE', if_true: files('xilinx_ethlite.c'))
|
||||
|
|
|
@ -10,11 +10,6 @@ allwinner_sun8i_emac_set_link(bool active) "Set link: active=%u"
|
|||
allwinner_sun8i_emac_read(uint64_t offset, uint64_t val) "MMIO read: offset=0x%" PRIx64 " value=0x%" PRIx64
|
||||
allwinner_sun8i_emac_write(uint64_t offset, uint64_t val) "MMIO write: offset=0x%" PRIx64 " value=0x%" PRIx64
|
||||
|
||||
# etraxfs_eth.c
|
||||
mdio_phy_read(int regnum, uint16_t value) "read phy_reg:%d value:0x%04x"
|
||||
mdio_phy_write(int regnum, uint16_t value) "write phy_reg:%d value:0x%04x"
|
||||
mdio_bitbang(bool mdc, bool mdio, int state, uint16_t cnt, unsigned int drive) "bitbang mdc=%u mdio=%u state=%d cnt=%u drv=%d"
|
||||
|
||||
# lance.c
|
||||
lance_mem_readw(uint64_t addr, uint32_t ret) "addr=0x%"PRIx64"val=0x%04x"
|
||||
lance_mem_writew(uint64_t addr, uint32_t val) "addr=0x%"PRIx64"val=0x%04x"
|
||||
|
|
|
@ -395,6 +395,7 @@ static void designware_pcie_root_realize(PCIDevice *dev, Error **errp)
|
|||
{
|
||||
DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(dev);
|
||||
DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
|
||||
MemoryRegion *host_mem = get_system_memory();
|
||||
MemoryRegion *address_space = &host->pci.memory;
|
||||
PCIBridge *br = PCI_BRIDGE(dev);
|
||||
DesignwarePCIEViewport *viewport;
|
||||
|
@ -435,7 +436,7 @@ static void designware_pcie_root_realize(PCIDevice *dev, Error **errp)
|
|||
viewport->cr[0] = DESIGNWARE_PCIE_ATU_TYPE_MEM;
|
||||
|
||||
source = &host->pci.address_space_root;
|
||||
destination = get_system_memory();
|
||||
destination = host_mem;
|
||||
direction = "Inbound";
|
||||
|
||||
/*
|
||||
|
@ -460,7 +461,7 @@ static void designware_pcie_root_realize(PCIDevice *dev, Error **errp)
|
|||
|
||||
destination = &host->pci.memory;
|
||||
direction = "Outbound";
|
||||
source = get_system_memory();
|
||||
source = host_mem;
|
||||
|
||||
/*
|
||||
* Configure MemoryRegion implementing CPU -> PCI memory
|
||||
|
@ -752,28 +753,23 @@ static void designware_pcie_host_init(Object *obj)
|
|||
qdev_prop_set_bit(DEVICE(root), "multifunction", false);
|
||||
}
|
||||
|
||||
static const TypeInfo designware_pcie_root_info = {
|
||||
.name = TYPE_DESIGNWARE_PCIE_ROOT,
|
||||
.parent = TYPE_PCI_BRIDGE,
|
||||
.instance_size = sizeof(DesignwarePCIERoot),
|
||||
.class_init = designware_pcie_root_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ INTERFACE_PCIE_DEVICE },
|
||||
{ }
|
||||
static const TypeInfo designware_pcie_types[] = {
|
||||
{
|
||||
.name = TYPE_DESIGNWARE_PCIE_HOST,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(DesignwarePCIEHost),
|
||||
.instance_init = designware_pcie_host_init,
|
||||
.class_init = designware_pcie_host_class_init,
|
||||
}, {
|
||||
.name = TYPE_DESIGNWARE_PCIE_ROOT,
|
||||
.parent = TYPE_PCI_BRIDGE,
|
||||
.instance_size = sizeof(DesignwarePCIERoot),
|
||||
.class_init = designware_pcie_root_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ INTERFACE_PCIE_DEVICE },
|
||||
{ }
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const TypeInfo designware_pcie_host_info = {
|
||||
.name = TYPE_DESIGNWARE_PCIE_HOST,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(DesignwarePCIEHost),
|
||||
.instance_init = designware_pcie_host_init,
|
||||
.class_init = designware_pcie_host_class_init,
|
||||
};
|
||||
|
||||
static void designware_pcie_register(void)
|
||||
{
|
||||
type_register_static(&designware_pcie_root_info);
|
||||
type_register_static(&designware_pcie_host_info);
|
||||
}
|
||||
type_init(designware_pcie_register)
|
||||
DEFINE_TYPES(designware_pcie_types)
|
||||
|
|
|
@ -689,7 +689,6 @@ static void gt64120_writel(void *opaque, hwaddr addr,
|
|||
case GT_PCI0_CFGDATA:
|
||||
/* Mapped via in gt64120_pci_mapping() */
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
|
||||
/* Interrupts */
|
||||
case GT_INTRCAUSE:
|
||||
|
@ -933,7 +932,6 @@ static uint64_t gt64120_readl(void *opaque,
|
|||
case GT_PCI0_CFGDATA:
|
||||
/* Mapped via in gt64120_pci_mapping() */
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
|
||||
case GT_PCI0_CMD:
|
||||
case GT_PCI0_TOR:
|
||||
|
|
|
@ -26,22 +26,27 @@
|
|||
#include "qapi/error.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qemu/module.h"
|
||||
#include "hw/registerfields.h"
|
||||
|
||||
FIELD(CONFIG, SHUTDOWN_MODE, 0, 1)
|
||||
FIELD(CONFIG, THERMOSTAT_MODE, 1, 1)
|
||||
FIELD(CONFIG, POLARITY, 2, 1)
|
||||
FIELD(CONFIG, FAULT_QUEUE, 3, 2)
|
||||
FIELD(CONFIG, CONVERTER_RESOLUTION, 5, 2)
|
||||
FIELD(CONFIG, ONE_SHOT, 7, 1)
|
||||
|
||||
static void tmp105_interrupt_update(TMP105State *s)
|
||||
{
|
||||
qemu_set_irq(s->pin, s->alarm ^ ((~s->config >> 2) & 1)); /* POL */
|
||||
qemu_set_irq(s->pin, s->alarm ^ FIELD_EX8(~s->config, CONFIG, POLARITY));
|
||||
}
|
||||
|
||||
static void tmp105_alarm_update(TMP105State *s)
|
||||
static void tmp105_alarm_update(TMP105State *s, bool one_shot)
|
||||
{
|
||||
if ((s->config >> 0) & 1) { /* SD */
|
||||
if ((s->config >> 7) & 1) /* OS */
|
||||
s->config &= ~(1 << 7); /* OS */
|
||||
else
|
||||
return;
|
||||
if (FIELD_EX8(s->config, CONFIG, SHUTDOWN_MODE) && !one_shot) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->config >> 1 & 1) {
|
||||
if (FIELD_EX8(s->config, CONFIG, THERMOSTAT_MODE)) {
|
||||
/*
|
||||
* TM == 1 : Interrupt mode. We signal Alert when the
|
||||
* temperature rises above T_high, and expect the guest to clear
|
||||
|
@ -89,7 +94,8 @@ static void tmp105_get_temperature(Object *obj, Visitor *v, const char *name,
|
|||
visit_type_int(v, name, &value, errp);
|
||||
}
|
||||
|
||||
/* Units are 0.001 centigrades relative to 0 C. s->temperature is 8.8
|
||||
/*
|
||||
* Units are 0.001 centigrades relative to 0 C. s->temperature is 8.8
|
||||
* fixed point, so units are 1/256 centigrades. A simple ratio will do.
|
||||
*/
|
||||
static void tmp105_set_temperature(Object *obj, Visitor *v, const char *name,
|
||||
|
@ -109,7 +115,7 @@ static void tmp105_set_temperature(Object *obj, Visitor *v, const char *name,
|
|||
|
||||
s->temperature = (int16_t) (temp * 256 / 1000);
|
||||
|
||||
tmp105_alarm_update(s);
|
||||
tmp105_alarm_update(s, false);
|
||||
}
|
||||
|
||||
static const int tmp105_faultq[4] = { 1, 2, 4, 6 };
|
||||
|
@ -118,30 +124,30 @@ static void tmp105_read(TMP105State *s)
|
|||
{
|
||||
s->len = 0;
|
||||
|
||||
if ((s->config >> 1) & 1) { /* TM */
|
||||
if (FIELD_EX8(s->config, CONFIG, THERMOSTAT_MODE)) {
|
||||
s->alarm = 0;
|
||||
tmp105_interrupt_update(s);
|
||||
}
|
||||
|
||||
switch (s->pointer & 3) {
|
||||
case TMP105_REG_TEMPERATURE:
|
||||
s->buf[s->len ++] = (((uint16_t) s->temperature) >> 8);
|
||||
s->buf[s->len ++] = (((uint16_t) s->temperature) >> 0) &
|
||||
(0xf0 << ((~s->config >> 5) & 3)); /* R */
|
||||
s->buf[s->len++] = (((uint16_t) s->temperature) >> 8);
|
||||
s->buf[s->len++] = (((uint16_t) s->temperature) >> 0) &
|
||||
(0xf0 << (FIELD_EX8(~s->config, CONFIG, CONVERTER_RESOLUTION)));
|
||||
break;
|
||||
|
||||
case TMP105_REG_CONFIG:
|
||||
s->buf[s->len ++] = s->config;
|
||||
s->buf[s->len++] = s->config;
|
||||
break;
|
||||
|
||||
case TMP105_REG_T_LOW:
|
||||
s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 8;
|
||||
s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 0;
|
||||
s->buf[s->len++] = ((uint16_t) s->limit[0]) >> 8;
|
||||
s->buf[s->len++] = ((uint16_t) s->limit[0]) >> 0;
|
||||
break;
|
||||
|
||||
case TMP105_REG_T_HIGH:
|
||||
s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 8;
|
||||
s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 0;
|
||||
s->buf[s->len++] = ((uint16_t) s->limit[1]) >> 8;
|
||||
s->buf[s->len++] = ((uint16_t) s->limit[1]) >> 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -153,19 +159,21 @@ static void tmp105_write(TMP105State *s)
|
|||
break;
|
||||
|
||||
case TMP105_REG_CONFIG:
|
||||
if (s->buf[0] & ~s->config & (1 << 0)) /* SD */
|
||||
if (FIELD_EX8(s->buf[0] & ~s->config, CONFIG, SHUTDOWN_MODE)) {
|
||||
printf("%s: TMP105 shutdown\n", __func__);
|
||||
s->config = s->buf[0];
|
||||
s->faults = tmp105_faultq[(s->config >> 3) & 3]; /* F */
|
||||
tmp105_alarm_update(s);
|
||||
}
|
||||
s->config = FIELD_DP8(s->buf[0], CONFIG, ONE_SHOT, 0);
|
||||
s->faults = tmp105_faultq[FIELD_EX8(s->config, CONFIG, FAULT_QUEUE)];
|
||||
tmp105_alarm_update(s, FIELD_EX8(s->buf[0], CONFIG, ONE_SHOT));
|
||||
break;
|
||||
|
||||
case TMP105_REG_T_LOW:
|
||||
case TMP105_REG_T_HIGH:
|
||||
if (s->len >= 3)
|
||||
if (s->len >= 3) {
|
||||
s->limit[s->pointer & 1] = (int16_t)
|
||||
((((uint16_t) s->buf[0]) << 8) | s->buf[1]);
|
||||
tmp105_alarm_update(s);
|
||||
((((uint16_t) s->buf[0]) << 8) | (s->buf[1] & 0xf0));
|
||||
}
|
||||
tmp105_alarm_update(s, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -175,7 +183,7 @@ static uint8_t tmp105_rx(I2CSlave *i2c)
|
|||
TMP105State *s = TMP105(i2c);
|
||||
|
||||
if (s->len < 2) {
|
||||
return s->buf[s->len ++];
|
||||
return s->buf[s->len++];
|
||||
} else {
|
||||
return 0xff;
|
||||
}
|
||||
|
@ -215,7 +223,7 @@ static int tmp105_post_load(void *opaque, int version_id)
|
|||
{
|
||||
TMP105State *s = opaque;
|
||||
|
||||
s->faults = tmp105_faultq[(s->config >> 3) & 3]; /* F */
|
||||
s->faults = tmp105_faultq[FIELD_EX8(s->config, CONFIG, FAULT_QUEUE)];
|
||||
|
||||
tmp105_interrupt_update(s);
|
||||
return 0;
|
||||
|
@ -273,7 +281,7 @@ static void tmp105_reset(I2CSlave *i2c)
|
|||
s->temperature = 0;
|
||||
s->pointer = 0;
|
||||
s->config = 0;
|
||||
s->faults = tmp105_faultq[(s->config >> 3) & 3];
|
||||
s->faults = tmp105_faultq[FIELD_EX8(s->config, CONFIG, FAULT_QUEUE)];
|
||||
s->alarm = 0;
|
||||
s->detect_falling = false;
|
||||
|
||||
|
|
|
@ -13,13 +13,6 @@ config R2D
|
|||
select SH7750
|
||||
select SH_PCI
|
||||
|
||||
config SHIX
|
||||
bool
|
||||
default y
|
||||
depends on SH4
|
||||
select SH7750
|
||||
select TC58128
|
||||
|
||||
config SH7750
|
||||
bool
|
||||
select SH_INTC
|
||||
|
|
|
@ -4,6 +4,5 @@ sh4_ss.add(when: 'CONFIG_SH7750', if_true: files(
|
|||
'sh7750_regnames.c',
|
||||
))
|
||||
sh4_ss.add(when: 'CONFIG_R2D', if_true: files('r2d.c'))
|
||||
sh4_ss.add(when: 'CONFIG_SHIX', if_true: files('shix.c'))
|
||||
|
||||
hw_arch += {'sh4': sh4_ss}
|
||||
|
|
|
@ -38,8 +38,6 @@
|
|||
#include "exec/exec-all.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define NB_DEVICES 4
|
||||
|
||||
typedef struct SH7750State {
|
||||
MemoryRegion iomem;
|
||||
MemoryRegion iomem_1f0;
|
||||
|
@ -75,7 +73,6 @@ typedef struct SH7750State {
|
|||
uint16_t periph_portdira; /* Direction seen from the peripherals */
|
||||
uint16_t periph_pdtrb; /* Imposed by the peripherals */
|
||||
uint16_t periph_portdirb; /* Direction seen from the peripherals */
|
||||
sh7750_io_device *devices[NB_DEVICES]; /* External peripherals */
|
||||
|
||||
/* Cache */
|
||||
uint32_t ccr;
|
||||
|
@ -92,19 +89,6 @@ static inline int has_bcr3_and_bcr4(SH7750State *s)
|
|||
* I/O ports
|
||||
*/
|
||||
|
||||
int sh7750_register_io_device(SH7750State *s, sh7750_io_device *device)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NB_DEVICES; i++) {
|
||||
if (s->devices[i] == NULL) {
|
||||
s->devices[i] = device;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint16_t portdir(uint32_t v)
|
||||
{
|
||||
#define EVENPORTMASK(n) ((v & (1 << ((n) << 1))) >> (n))
|
||||
|
@ -142,63 +126,26 @@ static uint16_t portb_lines(SH7750State *s)
|
|||
(~(s->portdirb | s->periph_portdirb) & s->portpullupb); /* Pullups */
|
||||
}
|
||||
|
||||
static void gen_port_interrupts(SH7750State *s)
|
||||
{
|
||||
/* XXXXX interrupts not generated */
|
||||
}
|
||||
|
||||
static void porta_changed(SH7750State *s, uint16_t prev)
|
||||
{
|
||||
uint16_t currenta, changes;
|
||||
int i, r = 0;
|
||||
uint16_t currenta;
|
||||
|
||||
currenta = porta_lines(s);
|
||||
if (currenta == prev) {
|
||||
return;
|
||||
}
|
||||
trace_sh7750_porta(prev, currenta, s->pdtra, s->pctra);
|
||||
changes = currenta ^ prev;
|
||||
|
||||
for (i = 0; i < NB_DEVICES; i++) {
|
||||
if (s->devices[i] && (s->devices[i]->portamask_trigger & changes)) {
|
||||
r |= s->devices[i]->port_change_cb(currenta, portb_lines(s),
|
||||
&s->periph_pdtra,
|
||||
&s->periph_portdira,
|
||||
&s->periph_pdtrb,
|
||||
&s->periph_portdirb);
|
||||
}
|
||||
}
|
||||
|
||||
if (r) {
|
||||
gen_port_interrupts(s);
|
||||
}
|
||||
}
|
||||
|
||||
static void portb_changed(SH7750State *s, uint16_t prev)
|
||||
{
|
||||
uint16_t currentb, changes;
|
||||
int i, r = 0;
|
||||
uint16_t currentb;
|
||||
|
||||
currentb = portb_lines(s);
|
||||
if (currentb == prev) {
|
||||
return;
|
||||
}
|
||||
trace_sh7750_portb(prev, currentb, s->pdtrb, s->pctrb);
|
||||
changes = currentb ^ prev;
|
||||
|
||||
for (i = 0; i < NB_DEVICES; i++) {
|
||||
if (s->devices[i] && (s->devices[i]->portbmask_trigger & changes)) {
|
||||
r |= s->devices[i]->port_change_cb(portb_lines(s), currentb,
|
||||
&s->periph_pdtra,
|
||||
&s->periph_portdira,
|
||||
&s->periph_pdtrb,
|
||||
&s->periph_portdirb);
|
||||
}
|
||||
}
|
||||
|
||||
if (r) {
|
||||
gen_port_interrupts(s);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* SHIX 2.0 board description
|
||||
*
|
||||
* Copyright (c) 2005 Samuel Tardieu
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* Shix 2.0 board by Alexis Polti, described at
|
||||
* https://web.archive.org/web/20070917001736/perso.enst.fr/~polti/realisations/shix20
|
||||
*
|
||||
* More information in target/sh4/README.sh4
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "cpu.h"
|
||||
#include "hw/sh4/sh.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/loader.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#define BIOS_FILENAME "shix_bios.bin"
|
||||
#define BIOS_ADDRESS 0xA0000000
|
||||
|
||||
static void shix_init(MachineState *machine)
|
||||
{
|
||||
int ret;
|
||||
SuperHCPU *cpu;
|
||||
struct SH7750State *s;
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
MemoryRegion *rom = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *sdram = g_new(MemoryRegion, 2);
|
||||
const char *bios_name = machine->firmware ?: BIOS_FILENAME;
|
||||
|
||||
cpu = SUPERH_CPU(cpu_create(machine->cpu_type));
|
||||
|
||||
/* Allocate memory space */
|
||||
memory_region_init_rom(rom, NULL, "shix.rom", 0x4000, &error_fatal);
|
||||
memory_region_add_subregion(sysmem, 0x00000000, rom);
|
||||
memory_region_init_ram(&sdram[0], NULL, "shix.sdram1", 0x01000000,
|
||||
&error_fatal);
|
||||
memory_region_add_subregion(sysmem, 0x08000000, &sdram[0]);
|
||||
memory_region_init_ram(&sdram[1], NULL, "shix.sdram2", 0x01000000,
|
||||
&error_fatal);
|
||||
memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]);
|
||||
|
||||
/* Load BIOS in 0 (and access it through P2, 0xA0000000) */
|
||||
ret = load_image_targphys(bios_name, 0, 0x4000);
|
||||
if (ret < 0 && !qtest_enabled()) {
|
||||
error_report("Could not load SHIX bios '%s'", bios_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Register peripherals */
|
||||
s = sh7750_init(cpu, sysmem);
|
||||
/* XXXXX Check success */
|
||||
tc58128_init(s, "shix_linux_nand.bin", NULL);
|
||||
}
|
||||
|
||||
static void shix_machine_init(MachineClass *mc)
|
||||
{
|
||||
mc->desc = "shix card";
|
||||
mc->init = shix_init;
|
||||
mc->is_default = true;
|
||||
mc->default_cpu_type = TYPE_SH7750R_CPU;
|
||||
mc->deprecation_reason = "old and unmaintained";
|
||||
}
|
||||
|
||||
DEFINE_MACHINE("shix", shix_machine_init)
|
|
@ -1,407 +0,0 @@
|
|||
/*
|
||||
* QEMU ETRAX Timers
|
||||
*
|
||||
* Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
|
||||
*
|
||||
* 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 "hw/sysbus.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/ptimer.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define D(x)
|
||||
|
||||
#define RW_TMR0_DIV 0x00
|
||||
#define R_TMR0_DATA 0x04
|
||||
#define RW_TMR0_CTRL 0x08
|
||||
#define RW_TMR1_DIV 0x10
|
||||
#define R_TMR1_DATA 0x14
|
||||
#define RW_TMR1_CTRL 0x18
|
||||
#define R_TIME 0x38
|
||||
#define RW_WD_CTRL 0x40
|
||||
#define R_WD_STAT 0x44
|
||||
#define RW_INTR_MASK 0x48
|
||||
#define RW_ACK_INTR 0x4c
|
||||
#define R_INTR 0x50
|
||||
#define R_MASKED_INTR 0x54
|
||||
|
||||
#define TYPE_ETRAX_FS_TIMER "etraxfs-timer"
|
||||
typedef struct ETRAXTimerState ETRAXTimerState;
|
||||
DECLARE_INSTANCE_CHECKER(ETRAXTimerState, ETRAX_TIMER,
|
||||
TYPE_ETRAX_FS_TIMER)
|
||||
|
||||
struct ETRAXTimerState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion mmio;
|
||||
qemu_irq irq;
|
||||
qemu_irq nmi;
|
||||
|
||||
ptimer_state *ptimer_t0;
|
||||
ptimer_state *ptimer_t1;
|
||||
ptimer_state *ptimer_wd;
|
||||
|
||||
uint32_t wd_hits;
|
||||
|
||||
/* Control registers. */
|
||||
uint32_t rw_tmr0_div;
|
||||
uint32_t r_tmr0_data;
|
||||
uint32_t rw_tmr0_ctrl;
|
||||
|
||||
uint32_t rw_tmr1_div;
|
||||
uint32_t r_tmr1_data;
|
||||
uint32_t rw_tmr1_ctrl;
|
||||
|
||||
uint32_t rw_wd_ctrl;
|
||||
|
||||
uint32_t rw_intr_mask;
|
||||
uint32_t rw_ack_intr;
|
||||
uint32_t r_intr;
|
||||
uint32_t r_masked_intr;
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_etraxfs = {
|
||||
.name = "etraxfs",
|
||||
.version_id = 0,
|
||||
.minimum_version_id = 0,
|
||||
.fields = (const VMStateField[]) {
|
||||
VMSTATE_PTIMER(ptimer_t0, ETRAXTimerState),
|
||||
VMSTATE_PTIMER(ptimer_t1, ETRAXTimerState),
|
||||
VMSTATE_PTIMER(ptimer_wd, ETRAXTimerState),
|
||||
|
||||
VMSTATE_UINT32(wd_hits, ETRAXTimerState),
|
||||
|
||||
VMSTATE_UINT32(rw_tmr0_div, ETRAXTimerState),
|
||||
VMSTATE_UINT32(r_tmr0_data, ETRAXTimerState),
|
||||
VMSTATE_UINT32(rw_tmr0_ctrl, ETRAXTimerState),
|
||||
|
||||
VMSTATE_UINT32(rw_tmr1_div, ETRAXTimerState),
|
||||
VMSTATE_UINT32(r_tmr1_data, ETRAXTimerState),
|
||||
VMSTATE_UINT32(rw_tmr1_ctrl, ETRAXTimerState),
|
||||
|
||||
VMSTATE_UINT32(rw_wd_ctrl, ETRAXTimerState),
|
||||
|
||||
VMSTATE_UINT32(rw_intr_mask, ETRAXTimerState),
|
||||
VMSTATE_UINT32(rw_ack_intr, ETRAXTimerState),
|
||||
VMSTATE_UINT32(r_intr, ETRAXTimerState),
|
||||
VMSTATE_UINT32(r_masked_intr, ETRAXTimerState),
|
||||
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static uint64_t
|
||||
timer_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
{
|
||||
ETRAXTimerState *t = opaque;
|
||||
uint32_t r = 0;
|
||||
|
||||
switch (addr) {
|
||||
case R_TMR0_DATA:
|
||||
r = ptimer_get_count(t->ptimer_t0);
|
||||
break;
|
||||
case R_TMR1_DATA:
|
||||
r = ptimer_get_count(t->ptimer_t1);
|
||||
break;
|
||||
case R_TIME:
|
||||
r = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / 10;
|
||||
break;
|
||||
case RW_INTR_MASK:
|
||||
r = t->rw_intr_mask;
|
||||
break;
|
||||
case R_MASKED_INTR:
|
||||
r = t->r_intr & t->rw_intr_mask;
|
||||
break;
|
||||
default:
|
||||
D(printf ("%s %x\n", __func__, addr));
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static void update_ctrl(ETRAXTimerState *t, int tnum)
|
||||
{
|
||||
unsigned int op;
|
||||
unsigned int freq;
|
||||
unsigned int freq_hz;
|
||||
unsigned int div;
|
||||
uint32_t ctrl;
|
||||
|
||||
ptimer_state *timer;
|
||||
|
||||
if (tnum == 0) {
|
||||
ctrl = t->rw_tmr0_ctrl;
|
||||
div = t->rw_tmr0_div;
|
||||
timer = t->ptimer_t0;
|
||||
} else {
|
||||
ctrl = t->rw_tmr1_ctrl;
|
||||
div = t->rw_tmr1_div;
|
||||
timer = t->ptimer_t1;
|
||||
}
|
||||
|
||||
|
||||
op = ctrl & 3;
|
||||
freq = ctrl >> 2;
|
||||
freq_hz = 32000000;
|
||||
|
||||
switch (freq)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
D(printf ("extern or disabled timer clock?\n"));
|
||||
break;
|
||||
case 4: freq_hz = 29493000; break;
|
||||
case 5: freq_hz = 32000000; break;
|
||||
case 6: freq_hz = 32768000; break;
|
||||
case 7: freq_hz = 100000000; break;
|
||||
default:
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
|
||||
D(printf ("freq_hz=%d div=%d\n", freq_hz, div));
|
||||
ptimer_transaction_begin(timer);
|
||||
ptimer_set_freq(timer, freq_hz);
|
||||
ptimer_set_limit(timer, div, 0);
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case 0:
|
||||
/* Load. */
|
||||
ptimer_set_limit(timer, div, 1);
|
||||
break;
|
||||
case 1:
|
||||
/* Hold. */
|
||||
ptimer_stop(timer);
|
||||
break;
|
||||
case 2:
|
||||
/* Run. */
|
||||
ptimer_run(timer, 0);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
ptimer_transaction_commit(timer);
|
||||
}
|
||||
|
||||
static void timer_update_irq(ETRAXTimerState *t)
|
||||
{
|
||||
t->r_intr &= ~(t->rw_ack_intr);
|
||||
t->r_masked_intr = t->r_intr & t->rw_intr_mask;
|
||||
|
||||
D(printf("%s: masked_intr=%x\n", __func__, t->r_masked_intr));
|
||||
qemu_set_irq(t->irq, !!t->r_masked_intr);
|
||||
}
|
||||
|
||||
static void timer0_hit(void *opaque)
|
||||
{
|
||||
ETRAXTimerState *t = opaque;
|
||||
t->r_intr |= 1;
|
||||
timer_update_irq(t);
|
||||
}
|
||||
|
||||
static void timer1_hit(void *opaque)
|
||||
{
|
||||
ETRAXTimerState *t = opaque;
|
||||
t->r_intr |= 2;
|
||||
timer_update_irq(t);
|
||||
}
|
||||
|
||||
static void watchdog_hit(void *opaque)
|
||||
{
|
||||
ETRAXTimerState *t = opaque;
|
||||
if (t->wd_hits == 0) {
|
||||
/* real hw gives a single tick before resetting but we are
|
||||
a bit friendlier to compensate for our slower execution. */
|
||||
ptimer_set_count(t->ptimer_wd, 10);
|
||||
ptimer_run(t->ptimer_wd, 1);
|
||||
qemu_irq_raise(t->nmi);
|
||||
}
|
||||
else
|
||||
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
|
||||
|
||||
t->wd_hits++;
|
||||
}
|
||||
|
||||
static inline void timer_watchdog_update(ETRAXTimerState *t, uint32_t value)
|
||||
{
|
||||
unsigned int wd_en = t->rw_wd_ctrl & (1 << 8);
|
||||
unsigned int wd_key = t->rw_wd_ctrl >> 9;
|
||||
unsigned int wd_cnt = t->rw_wd_ctrl & 511;
|
||||
unsigned int new_key = value >> 9 & ((1 << 7) - 1);
|
||||
unsigned int new_cmd = (value >> 8) & 1;
|
||||
|
||||
/* If the watchdog is enabled, they written key must match the
|
||||
complement of the previous. */
|
||||
wd_key = ~wd_key & ((1 << 7) - 1);
|
||||
|
||||
if (wd_en && wd_key != new_key)
|
||||
return;
|
||||
|
||||
D(printf("en=%d new_key=%x oldkey=%x cmd=%d cnt=%d\n",
|
||||
wd_en, new_key, wd_key, new_cmd, wd_cnt));
|
||||
|
||||
if (t->wd_hits)
|
||||
qemu_irq_lower(t->nmi);
|
||||
|
||||
t->wd_hits = 0;
|
||||
|
||||
ptimer_transaction_begin(t->ptimer_wd);
|
||||
ptimer_set_freq(t->ptimer_wd, 760);
|
||||
if (wd_cnt == 0)
|
||||
wd_cnt = 256;
|
||||
ptimer_set_count(t->ptimer_wd, wd_cnt);
|
||||
if (new_cmd)
|
||||
ptimer_run(t->ptimer_wd, 1);
|
||||
else
|
||||
ptimer_stop(t->ptimer_wd);
|
||||
|
||||
t->rw_wd_ctrl = value;
|
||||
ptimer_transaction_commit(t->ptimer_wd);
|
||||
}
|
||||
|
||||
static void
|
||||
timer_write(void *opaque, hwaddr addr,
|
||||
uint64_t val64, unsigned int size)
|
||||
{
|
||||
ETRAXTimerState *t = opaque;
|
||||
uint32_t value = val64;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case RW_TMR0_DIV:
|
||||
t->rw_tmr0_div = value;
|
||||
break;
|
||||
case RW_TMR0_CTRL:
|
||||
D(printf ("RW_TMR0_CTRL=%x\n", value));
|
||||
t->rw_tmr0_ctrl = value;
|
||||
update_ctrl(t, 0);
|
||||
break;
|
||||
case RW_TMR1_DIV:
|
||||
t->rw_tmr1_div = value;
|
||||
break;
|
||||
case RW_TMR1_CTRL:
|
||||
D(printf ("RW_TMR1_CTRL=%x\n", value));
|
||||
t->rw_tmr1_ctrl = value;
|
||||
update_ctrl(t, 1);
|
||||
break;
|
||||
case RW_INTR_MASK:
|
||||
D(printf ("RW_INTR_MASK=%x\n", value));
|
||||
t->rw_intr_mask = value;
|
||||
timer_update_irq(t);
|
||||
break;
|
||||
case RW_WD_CTRL:
|
||||
timer_watchdog_update(t, value);
|
||||
break;
|
||||
case RW_ACK_INTR:
|
||||
t->rw_ack_intr = value;
|
||||
timer_update_irq(t);
|
||||
t->rw_ack_intr = 0;
|
||||
break;
|
||||
default:
|
||||
printf("%s " HWADDR_FMT_plx " %x\n", __func__, addr, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps timer_ops = {
|
||||
.read = timer_read,
|
||||
.write = timer_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4
|
||||
}
|
||||
};
|
||||
|
||||
static void etraxfs_timer_reset_enter(Object *obj, ResetType type)
|
||||
{
|
||||
ETRAXTimerState *t = ETRAX_TIMER(obj);
|
||||
|
||||
ptimer_transaction_begin(t->ptimer_t0);
|
||||
ptimer_stop(t->ptimer_t0);
|
||||
ptimer_transaction_commit(t->ptimer_t0);
|
||||
ptimer_transaction_begin(t->ptimer_t1);
|
||||
ptimer_stop(t->ptimer_t1);
|
||||
ptimer_transaction_commit(t->ptimer_t1);
|
||||
ptimer_transaction_begin(t->ptimer_wd);
|
||||
ptimer_stop(t->ptimer_wd);
|
||||
ptimer_transaction_commit(t->ptimer_wd);
|
||||
t->rw_wd_ctrl = 0;
|
||||
t->r_intr = 0;
|
||||
t->rw_intr_mask = 0;
|
||||
}
|
||||
|
||||
static void etraxfs_timer_reset_hold(Object *obj, ResetType type)
|
||||
{
|
||||
ETRAXTimerState *t = ETRAX_TIMER(obj);
|
||||
|
||||
qemu_irq_lower(t->irq);
|
||||
}
|
||||
|
||||
static void etraxfs_timer_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ETRAXTimerState *t = ETRAX_TIMER(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
|
||||
t->ptimer_t0 = ptimer_init(timer0_hit, t, PTIMER_POLICY_LEGACY);
|
||||
t->ptimer_t1 = ptimer_init(timer1_hit, t, PTIMER_POLICY_LEGACY);
|
||||
t->ptimer_wd = ptimer_init(watchdog_hit, t, PTIMER_POLICY_LEGACY);
|
||||
|
||||
sysbus_init_irq(sbd, &t->irq);
|
||||
sysbus_init_irq(sbd, &t->nmi);
|
||||
|
||||
memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t,
|
||||
"etraxfs-timer", 0x5c);
|
||||
sysbus_init_mmio(sbd, &t->mmio);
|
||||
}
|
||||
|
||||
static void etraxfs_timer_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
ResettableClass *rc = RESETTABLE_CLASS(klass);
|
||||
|
||||
dc->realize = etraxfs_timer_realize;
|
||||
dc->vmsd = &vmstate_etraxfs;
|
||||
rc->phases.enter = etraxfs_timer_reset_enter;
|
||||
rc->phases.hold = etraxfs_timer_reset_hold;
|
||||
}
|
||||
|
||||
static const TypeInfo etraxfs_timer_info = {
|
||||
.name = TYPE_ETRAX_FS_TIMER,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(ETRAXTimerState),
|
||||
.class_init = etraxfs_timer_class_init,
|
||||
};
|
||||
|
||||
static void etraxfs_timer_register_types(void)
|
||||
{
|
||||
type_register_static(&etraxfs_timer_info);
|
||||
}
|
||||
|
||||
type_init(etraxfs_timer_register_types)
|
|
@ -10,7 +10,6 @@ system_ss.add(when: 'CONFIG_CMSDK_APB_TIMER', if_true: files('cmsdk-apb-timer.c'
|
|||
system_ss.add(when: 'CONFIG_RENESAS_TMR', if_true: files('renesas_tmr.c'))
|
||||
system_ss.add(when: 'CONFIG_RENESAS_CMT', if_true: files('renesas_cmt.c'))
|
||||
system_ss.add(when: 'CONFIG_DIGIC', if_true: files('digic-timer.c'))
|
||||
system_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_timer.c'))
|
||||
system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_mct.c'))
|
||||
system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_pwm.c'))
|
||||
system_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_gptimer.c'))
|
||||
|
|
|
@ -85,7 +85,7 @@ void watchdog_perform_action(void)
|
|||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#pragma GCC poison TARGET_AARCH64
|
||||
#pragma GCC poison TARGET_ALPHA
|
||||
#pragma GCC poison TARGET_ARM
|
||||
#pragma GCC poison TARGET_CRIS
|
||||
#pragma GCC poison TARGET_HEXAGON
|
||||
#pragma GCC poison TARGET_HPPA
|
||||
#pragma GCC poison TARGET_LOONGARCH64
|
||||
|
|
|
@ -46,6 +46,9 @@ typedef struct ESCCChannelState {
|
|||
uint8_t rx, tx;
|
||||
QemuInputHandlerState *hs;
|
||||
char *sunkbd_layout;
|
||||
int sunmouse_dx;
|
||||
int sunmouse_dy;
|
||||
int sunmouse_buttons;
|
||||
} ESCCChannelState;
|
||||
|
||||
struct ESCCState {
|
||||
|
|
|
@ -32,7 +32,6 @@ struct PL011State {
|
|||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion iomem;
|
||||
uint32_t readbuff;
|
||||
uint32_t flags;
|
||||
uint32_t lcr;
|
||||
uint32_t rsr;
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* QEMU ETRAX System Emulator
|
||||
*
|
||||
* Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef HW_ETRAXFS_H
|
||||
#define HW_ETRAXFS_H
|
||||
|
||||
#include "net/net.h"
|
||||
#include "hw/cris/etraxfs_dma.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
DeviceState *etraxfs_eth_init(hwaddr base, int phyaddr,
|
||||
struct etraxfs_dma_client *dma_out,
|
||||
struct etraxfs_dma_client *dma_in);
|
||||
|
||||
static inline DeviceState *etraxfs_ser_create(hwaddr addr,
|
||||
qemu_irq irq,
|
||||
Chardev *chr)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *s;
|
||||
|
||||
dev = qdev_new("etraxfs-serial");
|
||||
s = SYS_BUS_DEVICE(dev);
|
||||
qdev_prop_set_chr(dev, "chardev", chr);
|
||||
sysbus_realize_and_unref(s, &error_fatal);
|
||||
sysbus_mmio_map(s, 0, addr);
|
||||
sysbus_connect_irq(s, 0, irq);
|
||||
return dev;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,36 +0,0 @@
|
|||
#ifndef HW_ETRAXFS_DMA_H
|
||||
#define HW_ETRAXFS_DMA_H
|
||||
|
||||
#include "exec/hwaddr.h"
|
||||
|
||||
struct dma_context_metadata {
|
||||
/* data descriptor md */
|
||||
uint16_t metadata;
|
||||
};
|
||||
|
||||
struct etraxfs_dma_client
|
||||
{
|
||||
/* DMA controller. */
|
||||
int channel;
|
||||
void *ctrl;
|
||||
|
||||
/* client. */
|
||||
struct {
|
||||
int (*push)(void *opaque, unsigned char *buf,
|
||||
int len, bool eop);
|
||||
void (*pull)(void *opaque);
|
||||
void (*metadata_push)(void *opaque,
|
||||
const struct dma_context_metadata *md);
|
||||
void *opaque;
|
||||
} client;
|
||||
};
|
||||
|
||||
void *etraxfs_dmac_init(hwaddr base, int nr_channels);
|
||||
void etraxfs_dmac_connect(void *opaque, int channel, qemu_irq *line,
|
||||
int input);
|
||||
void etraxfs_dmac_connect_client(void *opaque, int c,
|
||||
struct etraxfs_dma_client *cl);
|
||||
int etraxfs_dmac_input(struct etraxfs_dma_client *client,
|
||||
void *buf, int len, int eop);
|
||||
|
||||
#endif
|
|
@ -31,8 +31,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIEHost, DESIGNWARE_PCIE_HOST)
|
|||
#define TYPE_DESIGNWARE_PCIE_ROOT "designware-pcie-root"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIERoot, DESIGNWARE_PCIE_ROOT)
|
||||
|
||||
struct DesignwarePCIERoot;
|
||||
|
||||
typedef struct DesignwarePCIEViewport {
|
||||
DesignwarePCIERoot *root;
|
||||
|
||||
|
|
|
@ -38,29 +38,10 @@ struct SH7750State;
|
|||
|
||||
struct SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem);
|
||||
|
||||
typedef struct {
|
||||
/* The callback will be triggered if any of the designated lines change */
|
||||
uint16_t portamask_trigger;
|
||||
uint16_t portbmask_trigger;
|
||||
/* Return 0 if no action was taken */
|
||||
int (*port_change_cb) (uint16_t porta, uint16_t portb,
|
||||
uint16_t *periph_pdtra,
|
||||
uint16_t *periph_portdira,
|
||||
uint16_t *periph_pdtrb,
|
||||
uint16_t *periph_portdirb);
|
||||
} sh7750_io_device;
|
||||
|
||||
int sh7750_register_io_device(struct SH7750State *s,
|
||||
sh7750_io_device *device);
|
||||
|
||||
/* sh_serial.c */
|
||||
#define TYPE_SH_SERIAL "sh-serial"
|
||||
#define SH_SERIAL_FEAT_SCIF (1 << 0)
|
||||
|
||||
/* sh7750.c */
|
||||
qemu_irq sh7750_irl(struct SH7750State *s);
|
||||
|
||||
/* tc58128.c */
|
||||
int tc58128_init(struct SH7750State *s, const char *zone1, const char *zone2);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -62,6 +62,17 @@ void fifo8_push_all(Fifo8 *fifo, const uint8_t *data, uint32_t num);
|
|||
*/
|
||||
uint8_t fifo8_pop(Fifo8 *fifo);
|
||||
|
||||
/**
|
||||
* fifo8_peek:
|
||||
* @fifo: fifo to peek from
|
||||
*
|
||||
* Peek the data byte at the current head of the FIFO. Clients are responsible
|
||||
* for checking for emptyness using fifo8_is_empty().
|
||||
*
|
||||
* Returns: The peeked data byte.
|
||||
*/
|
||||
uint8_t fifo8_peek(Fifo8 *fifo);
|
||||
|
||||
/**
|
||||
* fifo8_pop_buf:
|
||||
* @fifo: FIFO to pop from
|
||||
|
@ -76,6 +87,20 @@ uint8_t fifo8_pop(Fifo8 *fifo);
|
|||
*/
|
||||
uint32_t fifo8_pop_buf(Fifo8 *fifo, uint8_t *dest, uint32_t destlen);
|
||||
|
||||
/**
|
||||
* fifo8_peek_buf:
|
||||
* @fifo: FIFO to read from
|
||||
* @dest: the buffer to write the data into (can be NULL)
|
||||
* @destlen: size of @dest and maximum number of bytes to peek
|
||||
*
|
||||
* Peek a number of elements from the FIFO up to a maximum of @destlen.
|
||||
* The peeked data is copied into the @dest buffer.
|
||||
* Care is taken when the data wraps around in the ring buffer.
|
||||
*
|
||||
* Returns: number of bytes peeked.
|
||||
*/
|
||||
uint32_t fifo8_peek_buf(Fifo8 *fifo, uint8_t *dest, uint32_t destlen);
|
||||
|
||||
/**
|
||||
* fifo8_pop_bufptr:
|
||||
* @fifo: FIFO to pop from
|
||||
|
|
|
@ -6,7 +6,6 @@ enum {
|
|||
QEMU_ARCH_ALL = -1,
|
||||
QEMU_ARCH_ALPHA = (1 << 0),
|
||||
QEMU_ARCH_ARM = (1 << 1),
|
||||
QEMU_ARCH_CRIS = (1 << 2),
|
||||
QEMU_ARCH_I386 = (1 << 3),
|
||||
QEMU_ARCH_M68K = (1 << 4),
|
||||
QEMU_ARCH_MICROBLAZE = (1 << 6),
|
||||
|
|
|
@ -42,6 +42,7 @@ struct sdl2_console {
|
|||
int updates;
|
||||
int idle_counter;
|
||||
int ignore_hotkeys;
|
||||
bool gui_keysym;
|
||||
SDL_GLContext winctx;
|
||||
QKbdState *kbd;
|
||||
#ifdef CONFIG_OPENGL
|
||||
|
@ -60,6 +61,7 @@ void sdl2_poll_events(struct sdl2_console *scon);
|
|||
|
||||
void sdl2_process_key(struct sdl2_console *scon,
|
||||
SDL_KeyboardEvent *ev);
|
||||
void sdl2_release_modifiers(struct sdl2_console *scon);
|
||||
|
||||
void sdl2_2d_update(DisplayChangeListener *dcl,
|
||||
int x, int y, int w, int h);
|
||||
|
|
|
@ -21,13 +21,6 @@
|
|||
#define ABI_LLONG_ALIGNMENT 2
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_CRIS
|
||||
#define ABI_SHORT_ALIGNMENT 1
|
||||
#define ABI_INT_ALIGNMENT 1
|
||||
#define ABI_LONG_ALIGNMENT 1
|
||||
#define ABI_LLONG_ALIGNMENT 1
|
||||
#endif
|
||||
|
||||
#if (defined(TARGET_I386) && !defined(TARGET_X86_64)) \
|
||||
|| defined(TARGET_SH4) \
|
||||
|| defined(TARGET_OPENRISC) \
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* qemu user cpu loop
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
*
|
||||
* 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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 "qemu/osdep.h"
|
||||
#include "qemu.h"
|
||||
#include "user-internals.h"
|
||||
#include "cpu_loop-common.h"
|
||||
#include "signal-common.h"
|
||||
|
||||
void cpu_loop(CPUCRISState *env)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
int trapnr, ret;
|
||||
|
||||
while (1) {
|
||||
cpu_exec_start(cs);
|
||||
trapnr = cpu_exec(cs);
|
||||
cpu_exec_end(cs);
|
||||
process_queued_cpu_work(cs);
|
||||
|
||||
switch (trapnr) {
|
||||
case EXCP_INTERRUPT:
|
||||
/* just indicate that signals should be handled asap */
|
||||
break;
|
||||
case EXCP_BREAK:
|
||||
ret = do_syscall(env,
|
||||
env->regs[9],
|
||||
env->regs[10],
|
||||
env->regs[11],
|
||||
env->regs[12],
|
||||
env->regs[13],
|
||||
env->pregs[7],
|
||||
env->pregs[11],
|
||||
0, 0);
|
||||
if (ret == -QEMU_ERESTARTSYS) {
|
||||
env->pc -= 2;
|
||||
} else if (ret != -QEMU_ESIGRETURN) {
|
||||
env->regs[10] = ret;
|
||||
}
|
||||
break;
|
||||
case EXCP_DEBUG:
|
||||
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
|
||||
break;
|
||||
case EXCP_ATOMIC:
|
||||
cpu_exec_step_atomic(cs);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr);
|
||||
cpu_dump_state(cs, stderr, 0);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
process_pending_signals (env);
|
||||
}
|
||||
}
|
||||
|
||||
void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
|
||||
{
|
||||
CPUState *cpu = env_cpu(env);
|
||||
TaskState *ts = get_task_state(cpu);
|
||||
struct image_info *info = ts->info;
|
||||
|
||||
env->regs[0] = regs->r0;
|
||||
env->regs[1] = regs->r1;
|
||||
env->regs[2] = regs->r2;
|
||||
env->regs[3] = regs->r3;
|
||||
env->regs[4] = regs->r4;
|
||||
env->regs[5] = regs->r5;
|
||||
env->regs[6] = regs->r6;
|
||||
env->regs[7] = regs->r7;
|
||||
env->regs[8] = regs->r8;
|
||||
env->regs[9] = regs->r9;
|
||||
env->regs[10] = regs->r10;
|
||||
env->regs[11] = regs->r11;
|
||||
env->regs[12] = regs->r12;
|
||||
env->regs[13] = regs->r13;
|
||||
env->regs[14] = info->start_stack;
|
||||
env->regs[15] = regs->acr;
|
||||
env->pc = regs->erp;
|
||||
}
|
|
@ -1,194 +0,0 @@
|
|||
/*
|
||||
* Emulation of Linux signals
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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 "qemu/osdep.h"
|
||||
#include "qemu.h"
|
||||
#include "user-internals.h"
|
||||
#include "signal-common.h"
|
||||
#include "linux-user/trace.h"
|
||||
|
||||
struct target_sigcontext {
|
||||
struct target_pt_regs regs; /* needs to be first */
|
||||
uint32_t oldmask;
|
||||
uint32_t usp; /* usp before stacking this gunk on it */
|
||||
};
|
||||
|
||||
/* Signal frames. */
|
||||
struct target_signal_frame {
|
||||
struct target_sigcontext sc;
|
||||
uint32_t extramask[TARGET_NSIG_WORDS - 1];
|
||||
uint16_t retcode[4]; /* Trampoline code. */
|
||||
};
|
||||
|
||||
static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
|
||||
{
|
||||
__put_user(env->regs[0], &sc->regs.r0);
|
||||
__put_user(env->regs[1], &sc->regs.r1);
|
||||
__put_user(env->regs[2], &sc->regs.r2);
|
||||
__put_user(env->regs[3], &sc->regs.r3);
|
||||
__put_user(env->regs[4], &sc->regs.r4);
|
||||
__put_user(env->regs[5], &sc->regs.r5);
|
||||
__put_user(env->regs[6], &sc->regs.r6);
|
||||
__put_user(env->regs[7], &sc->regs.r7);
|
||||
__put_user(env->regs[8], &sc->regs.r8);
|
||||
__put_user(env->regs[9], &sc->regs.r9);
|
||||
__put_user(env->regs[10], &sc->regs.r10);
|
||||
__put_user(env->regs[11], &sc->regs.r11);
|
||||
__put_user(env->regs[12], &sc->regs.r12);
|
||||
__put_user(env->regs[13], &sc->regs.r13);
|
||||
__put_user(env->regs[14], &sc->usp);
|
||||
__put_user(env->regs[15], &sc->regs.acr);
|
||||
__put_user(env->pregs[PR_MOF], &sc->regs.mof);
|
||||
__put_user(env->pregs[PR_SRP], &sc->regs.srp);
|
||||
__put_user(env->pc, &sc->regs.erp);
|
||||
}
|
||||
|
||||
static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
|
||||
{
|
||||
__get_user(env->regs[0], &sc->regs.r0);
|
||||
__get_user(env->regs[1], &sc->regs.r1);
|
||||
__get_user(env->regs[2], &sc->regs.r2);
|
||||
__get_user(env->regs[3], &sc->regs.r3);
|
||||
__get_user(env->regs[4], &sc->regs.r4);
|
||||
__get_user(env->regs[5], &sc->regs.r5);
|
||||
__get_user(env->regs[6], &sc->regs.r6);
|
||||
__get_user(env->regs[7], &sc->regs.r7);
|
||||
__get_user(env->regs[8], &sc->regs.r8);
|
||||
__get_user(env->regs[9], &sc->regs.r9);
|
||||
__get_user(env->regs[10], &sc->regs.r10);
|
||||
__get_user(env->regs[11], &sc->regs.r11);
|
||||
__get_user(env->regs[12], &sc->regs.r12);
|
||||
__get_user(env->regs[13], &sc->regs.r13);
|
||||
__get_user(env->regs[14], &sc->usp);
|
||||
__get_user(env->regs[15], &sc->regs.acr);
|
||||
__get_user(env->pregs[PR_MOF], &sc->regs.mof);
|
||||
__get_user(env->pregs[PR_SRP], &sc->regs.srp);
|
||||
__get_user(env->pc, &sc->regs.erp);
|
||||
}
|
||||
|
||||
static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
|
||||
{
|
||||
abi_ulong sp;
|
||||
/* Align the stack downwards to 4. */
|
||||
sp = (env->regs[R_SP] & ~3);
|
||||
return sp - framesize;
|
||||
}
|
||||
|
||||
static void setup_sigreturn(uint16_t *retcode)
|
||||
{
|
||||
/* This is movu.w __NR_sigreturn, r9; break 13; */
|
||||
__put_user(0x9c5f, retcode + 0);
|
||||
__put_user(TARGET_NR_sigreturn, retcode + 1);
|
||||
__put_user(0xe93d, retcode + 2);
|
||||
}
|
||||
|
||||
void setup_frame(int sig, struct target_sigaction *ka,
|
||||
target_sigset_t *set, CPUCRISState *env)
|
||||
{
|
||||
struct target_signal_frame *frame;
|
||||
abi_ulong frame_addr;
|
||||
int i;
|
||||
|
||||
frame_addr = get_sigframe(env, sizeof *frame);
|
||||
trace_user_setup_frame(env, frame_addr);
|
||||
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
|
||||
goto badframe;
|
||||
|
||||
/*
|
||||
* The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
|
||||
* use this trampoline anymore but it sets it up for GDB.
|
||||
*/
|
||||
setup_sigreturn(frame->retcode);
|
||||
|
||||
/* Save the mask. */
|
||||
__put_user(set->sig[0], &frame->sc.oldmask);
|
||||
|
||||
for(i = 1; i < TARGET_NSIG_WORDS; i++) {
|
||||
__put_user(set->sig[i], &frame->extramask[i - 1]);
|
||||
}
|
||||
|
||||
setup_sigcontext(&frame->sc, env);
|
||||
|
||||
/* Move the stack and setup the arguments for the handler. */
|
||||
env->regs[R_SP] = frame_addr;
|
||||
env->regs[10] = sig;
|
||||
env->pc = (unsigned long) ka->_sa_handler;
|
||||
/* Link SRP so the guest returns through the trampoline. */
|
||||
env->pregs[PR_SRP] = default_sigreturn;
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
return;
|
||||
badframe:
|
||||
force_sigsegv(sig);
|
||||
}
|
||||
|
||||
void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
target_siginfo_t *info,
|
||||
target_sigset_t *set, CPUCRISState *env)
|
||||
{
|
||||
qemu_log_mask(LOG_UNIMP, "setup_rt_frame: not implemented\n");
|
||||
}
|
||||
|
||||
long do_sigreturn(CPUCRISState *env)
|
||||
{
|
||||
struct target_signal_frame *frame;
|
||||
abi_ulong frame_addr;
|
||||
target_sigset_t target_set;
|
||||
sigset_t set;
|
||||
int i;
|
||||
|
||||
frame_addr = env->regs[R_SP];
|
||||
trace_user_do_sigreturn(env, frame_addr);
|
||||
/* Make sure the guest isn't playing games. */
|
||||
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
|
||||
goto badframe;
|
||||
}
|
||||
|
||||
/* Restore blocked signals */
|
||||
__get_user(target_set.sig[0], &frame->sc.oldmask);
|
||||
for(i = 1; i < TARGET_NSIG_WORDS; i++) {
|
||||
__get_user(target_set.sig[i], &frame->extramask[i - 1]);
|
||||
}
|
||||
target_to_host_sigset_internal(&set, &target_set);
|
||||
set_sigmask(&set);
|
||||
|
||||
restore_sigcontext(&frame->sc, env);
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -QEMU_ESIGRETURN;
|
||||
badframe:
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
long do_rt_sigreturn(CPUCRISState *env)
|
||||
{
|
||||
trace_user_do_rt_sigreturn(env, 0);
|
||||
qemu_log_mask(LOG_UNIMP, "do_rt_sigreturn: not implemented\n");
|
||||
return -TARGET_ENOSYS;
|
||||
}
|
||||
|
||||
void setup_sigtramp(abi_ulong sigtramp_page)
|
||||
{
|
||||
uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 6, 0);
|
||||
assert(tramp != NULL);
|
||||
|
||||
default_sigreturn = sigtramp_page;
|
||||
setup_sigreturn(tramp);
|
||||
|
||||
unlock_user(tramp, sigtramp_page, 6);
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
#include "../generic/sockbits.h"
|
|
@ -1,367 +0,0 @@
|
|||
/*
|
||||
* This file contains the system call numbers, and stub macros for libc.
|
||||
*/
|
||||
|
||||
#ifndef LINUX_USER_CRIS_SYSCALL_NR_H
|
||||
#define LINUX_USER_CRIS_SYSCALL_NR_H
|
||||
|
||||
#define TARGET_NR_restart_syscall 0
|
||||
#define TARGET_NR_exit 1
|
||||
#define TARGET_NR_fork 2
|
||||
#define TARGET_NR_read 3
|
||||
#define TARGET_NR_write 4
|
||||
#define TARGET_NR_open 5
|
||||
#define TARGET_NR_close 6
|
||||
#define TARGET_NR_waitpid 7
|
||||
#define TARGET_NR_creat 8
|
||||
#define TARGET_NR_link 9
|
||||
#define TARGET_NR_unlink 10
|
||||
#define TARGET_NR_execve 11
|
||||
#define TARGET_NR_chdir 12
|
||||
#define TARGET_NR_time 13
|
||||
#define TARGET_NR_mknod 14
|
||||
#define TARGET_NR_chmod 15
|
||||
#define TARGET_NR_lchown 16
|
||||
#define TARGET_NR_break 17
|
||||
#define TARGET_NR_oldstat 18
|
||||
#define TARGET_NR_lseek 19
|
||||
#define TARGET_NR_getpid 20
|
||||
#define TARGET_NR_mount 21
|
||||
#define TARGET_NR_umount 22
|
||||
#define TARGET_NR_setuid 23
|
||||
#define TARGET_NR_getuid 24
|
||||
#define TARGET_NR_stime 25
|
||||
#define TARGET_NR_ptrace 26
|
||||
#define TARGET_NR_alarm 27
|
||||
#define TARGET_NR_oldfstat 28
|
||||
#define TARGET_NR_pause 29
|
||||
#define TARGET_NR_utime 30
|
||||
#define TARGET_NR_stty 31
|
||||
#define TARGET_NR_gtty 32
|
||||
#define TARGET_NR_access 33
|
||||
#define TARGET_NR_nice 34
|
||||
#define TARGET_NR_ftime 35
|
||||
#define TARGET_NR_sync 36
|
||||
#define TARGET_NR_kill 37
|
||||
#define TARGET_NR_rename 38
|
||||
#define TARGET_NR_mkdir 39
|
||||
#define TARGET_NR_rmdir 40
|
||||
#define TARGET_NR_dup 41
|
||||
#define TARGET_NR_pipe 42
|
||||
#define TARGET_NR_times 43
|
||||
#define TARGET_NR_prof 44
|
||||
#define TARGET_NR_brk 45
|
||||
#define TARGET_NR_setgid 46
|
||||
#define TARGET_NR_getgid 47
|
||||
#define TARGET_NR_signal 48
|
||||
#define TARGET_NR_geteuid 49
|
||||
#define TARGET_NR_getegid 50
|
||||
#define TARGET_NR_acct 51
|
||||
#define TARGET_NR_umount2 52
|
||||
#define TARGET_NR_lock 53
|
||||
#define TARGET_NR_ioctl 54
|
||||
#define TARGET_NR_fcntl 55
|
||||
#define TARGET_NR_mpx 56
|
||||
#define TARGET_NR_setpgid 57
|
||||
#define TARGET_NR_ulimit 58
|
||||
#define TARGET_NR_oldolduname 59
|
||||
#define TARGET_NR_umask 60
|
||||
#define TARGET_NR_chroot 61
|
||||
#define TARGET_NR_ustat 62
|
||||
#define TARGET_NR_dup2 63
|
||||
#define TARGET_NR_getppid 64
|
||||
#define TARGET_NR_getpgrp 65
|
||||
#define TARGET_NR_setsid 66
|
||||
#define TARGET_NR_sigaction 67
|
||||
#define TARGET_NR_sgetmask 68
|
||||
#define TARGET_NR_ssetmask 69
|
||||
#define TARGET_NR_setreuid 70
|
||||
#define TARGET_NR_setregid 71
|
||||
#define TARGET_NR_sigsuspend 72
|
||||
#define TARGET_NR_sigpending 73
|
||||
#define TARGET_NR_sethostname 74
|
||||
#define TARGET_NR_setrlimit 75
|
||||
#define TARGET_NR_getrlimit 76
|
||||
#define TARGET_NR_getrusage 77
|
||||
#define TARGET_NR_gettimeofday 78
|
||||
#define TARGET_NR_settimeofday 79
|
||||
#define TARGET_NR_getgroups 80
|
||||
#define TARGET_NR_setgroups 81
|
||||
#define TARGET_NR_select 82
|
||||
#define TARGET_NR_symlink 83
|
||||
#define TARGET_NR_oldlstat 84
|
||||
#define TARGET_NR_readlink 85
|
||||
#define TARGET_NR_uselib 86
|
||||
#define TARGET_NR_swapon 87
|
||||
#define TARGET_NR_reboot 88
|
||||
#define TARGET_NR_readdir 89
|
||||
#define TARGET_NR_mmap 90
|
||||
#define TARGET_NR_munmap 91
|
||||
#define TARGET_NR_truncate 92
|
||||
#define TARGET_NR_ftruncate 93
|
||||
#define TARGET_NR_fchmod 94
|
||||
#define TARGET_NR_fchown 95
|
||||
#define TARGET_NR_getpriority 96
|
||||
#define TARGET_NR_setpriority 97
|
||||
#define TARGET_NR_profil 98
|
||||
#define TARGET_NR_statfs 99
|
||||
#define TARGET_NR_fstatfs 100
|
||||
#define TARGET_NR_ioperm 101
|
||||
#define TARGET_NR_socketcall 102
|
||||
#define TARGET_NR_syslog 103
|
||||
#define TARGET_NR_setitimer 104
|
||||
#define TARGET_NR_getitimer 105
|
||||
#define TARGET_NR_stat 106
|
||||
#define TARGET_NR_lstat 107
|
||||
#define TARGET_NR_fstat 108
|
||||
#define TARGET_NR_olduname 109
|
||||
#define TARGET_NR_iopl 110
|
||||
#define TARGET_NR_vhangup 111
|
||||
#define TARGET_NR_idle 112
|
||||
#define TARGET_NR_vm86 113
|
||||
#define TARGET_NR_wait4 114
|
||||
#define TARGET_NR_swapoff 115
|
||||
#define TARGET_NR_sysinfo 116
|
||||
#define TARGET_NR_ipc 117
|
||||
#define TARGET_NR_fsync 118
|
||||
#define TARGET_NR_sigreturn 119
|
||||
#define TARGET_NR_clone 120
|
||||
#define TARGET_NR_setdomainname 121
|
||||
#define TARGET_NR_uname 122
|
||||
#define TARGET_NR_modify_ldt 123
|
||||
#define TARGET_NR_adjtimex 124
|
||||
#define TARGET_NR_mprotect 125
|
||||
#define TARGET_NR_sigprocmask 126
|
||||
#define TARGET_NR_create_module 127
|
||||
#define TARGET_NR_init_module 128
|
||||
#define TARGET_NR_delete_module 129
|
||||
#define TARGET_NR_get_kernel_syms 130
|
||||
#define TARGET_NR_quotactl 131
|
||||
#define TARGET_NR_getpgid 132
|
||||
#define TARGET_NR_fchdir 133
|
||||
#define TARGET_NR_bdflush 134
|
||||
#define TARGET_NR_sysfs 135
|
||||
#define TARGET_NR_personality 136
|
||||
#define TARGET_NR_afs_syscall 137 /* Syscall for Andrew File System */
|
||||
#define TARGET_NR_setfsuid 138
|
||||
#define TARGET_NR_setfsgid 139
|
||||
#define TARGET_NR__llseek 140
|
||||
#define TARGET_NR_getdents 141
|
||||
#define TARGET_NR__newselect 142
|
||||
#define TARGET_NR_flock 143
|
||||
#define TARGET_NR_msync 144
|
||||
#define TARGET_NR_readv 145
|
||||
#define TARGET_NR_writev 146
|
||||
#define TARGET_NR_getsid 147
|
||||
#define TARGET_NR_fdatasync 148
|
||||
#define TARGET_NR__sysctl 149
|
||||
#define TARGET_NR_mlock 150
|
||||
#define TARGET_NR_munlock 151
|
||||
#define TARGET_NR_mlockall 152
|
||||
#define TARGET_NR_munlockall 153
|
||||
#define TARGET_NR_sched_setparam 154
|
||||
#define TARGET_NR_sched_getparam 155
|
||||
#define TARGET_NR_sched_setscheduler 156
|
||||
#define TARGET_NR_sched_getscheduler 157
|
||||
#define TARGET_NR_sched_yield 158
|
||||
#define TARGET_NR_sched_get_priority_max 159
|
||||
#define TARGET_NR_sched_get_priority_min 160
|
||||
#define TARGET_NR_sched_rr_get_interval 161
|
||||
#define TARGET_NR_nanosleep 162
|
||||
#define TARGET_NR_mremap 163
|
||||
#define TARGET_NR_setresuid 164
|
||||
#define TARGET_NR_getresuid 165
|
||||
|
||||
#define TARGET_NR_query_module 167
|
||||
#define TARGET_NR_poll 168
|
||||
#define TARGET_NR_nfsservctl 169
|
||||
#define TARGET_NR_setresgid 170
|
||||
#define TARGET_NR_getresgid 171
|
||||
#define TARGET_NR_prctl 172
|
||||
#define TARGET_NR_rt_sigreturn 173
|
||||
#define TARGET_NR_rt_sigaction 174
|
||||
#define TARGET_NR_rt_sigprocmask 175
|
||||
#define TARGET_NR_rt_sigpending 176
|
||||
#define TARGET_NR_rt_sigtimedwait 177
|
||||
#define TARGET_NR_rt_sigqueueinfo 178
|
||||
#define TARGET_NR_rt_sigsuspend 179
|
||||
#define TARGET_NR_pread64 180
|
||||
#define TARGET_NR_pwrite64 181
|
||||
#define TARGET_NR_chown 182
|
||||
#define TARGET_NR_getcwd 183
|
||||
#define TARGET_NR_capget 184
|
||||
#define TARGET_NR_capset 185
|
||||
#define TARGET_NR_sigaltstack 186
|
||||
#define TARGET_NR_sendfile 187
|
||||
#define TARGET_NR_getpmsg 188 /* some people actually want streams */
|
||||
#define TARGET_NR_putpmsg 189 /* some people actually want streams */
|
||||
#define TARGET_NR_vfork 190
|
||||
#define TARGET_NR_ugetrlimit 191 /* SuS compliant getrlimit */
|
||||
#define TARGET_NR_mmap2 192
|
||||
#define TARGET_NR_truncate64 193
|
||||
#define TARGET_NR_ftruncate64 194
|
||||
#define TARGET_NR_stat64 195
|
||||
#define TARGET_NR_lstat64 196
|
||||
#define TARGET_NR_fstat64 197
|
||||
#define TARGET_NR_lchown32 198
|
||||
#define TARGET_NR_getuid32 199
|
||||
#define TARGET_NR_getgid32 200
|
||||
#define TARGET_NR_geteuid32 201
|
||||
#define TARGET_NR_getegid32 202
|
||||
#define TARGET_NR_setreuid32 203
|
||||
#define TARGET_NR_setregid32 204
|
||||
#define TARGET_NR_getgroups32 205
|
||||
#define TARGET_NR_setgroups32 206
|
||||
#define TARGET_NR_fchown32 207
|
||||
#define TARGET_NR_setresuid32 208
|
||||
#define TARGET_NR_getresuid32 209
|
||||
#define TARGET_NR_setresgid32 210
|
||||
#define TARGET_NR_getresgid32 211
|
||||
#define TARGET_NR_chown32 212
|
||||
#define TARGET_NR_setuid32 213
|
||||
#define TARGET_NR_setgid32 214
|
||||
#define TARGET_NR_setfsuid32 215
|
||||
#define TARGET_NR_setfsgid32 216
|
||||
#define TARGET_NR_pivot_root 217
|
||||
#define TARGET_NR_mincore 218
|
||||
#define TARGET_NR_madvise 219
|
||||
#define TARGET_NR_getdents64 220
|
||||
#define TARGET_NR_fcntl64 221
|
||||
/* 223 is unused */
|
||||
#define TARGET_NR_gettid 224
|
||||
#define TARGET_NR_readahead 225
|
||||
#define TARGET_NR_setxattr 226
|
||||
#define TARGET_NR_lsetxattr 227
|
||||
#define TARGET_NR_fsetxattr 228
|
||||
#define TARGET_NR_getxattr 229
|
||||
#define TARGET_NR_lgetxattr 230
|
||||
#define TARGET_NR_fgetxattr 231
|
||||
#define TARGET_NR_listxattr 232
|
||||
#define TARGET_NR_llistxattr 233
|
||||
#define TARGET_NR_flistxattr 234
|
||||
#define TARGET_NR_removexattr 235
|
||||
#define TARGET_NR_lremovexattr 236
|
||||
#define TARGET_NR_fremovexattr 237
|
||||
#define TARGET_NR_tkill 238
|
||||
#define TARGET_NR_sendfile64 239
|
||||
#define TARGET_NR_futex 240
|
||||
#define TARGET_NR_sched_setaffinity 241
|
||||
#define TARGET_NR_sched_getaffinity 242
|
||||
#define TARGET_NR_set_thread_area 243
|
||||
#define TARGET_NR_get_thread_area 244
|
||||
#define TARGET_NR_io_setup 245
|
||||
#define TARGET_NR_io_destroy 246
|
||||
#define TARGET_NR_io_getevents 247
|
||||
#define TARGET_NR_io_submit 248
|
||||
#define TARGET_NR_io_cancel 249
|
||||
#define TARGET_NR_fadvise64 250
|
||||
#define TARGET_NR_exit_group 252
|
||||
#define TARGET_NR_lookup_dcookie 253
|
||||
#define TARGET_NR_epoll_create 254
|
||||
#define TARGET_NR_epoll_ctl 255
|
||||
#define TARGET_NR_epoll_wait 256
|
||||
#define TARGET_NR_remap_file_pages 257
|
||||
#define TARGET_NR_set_tid_address 258
|
||||
#define TARGET_NR_timer_create 259
|
||||
#define TARGET_NR_timer_settime (TARGET_NR_timer_create+1)
|
||||
#define TARGET_NR_timer_gettime (TARGET_NR_timer_create+2)
|
||||
#define TARGET_NR_timer_getoverrun (TARGET_NR_timer_create+3)
|
||||
#define TARGET_NR_timer_delete (TARGET_NR_timer_create+4)
|
||||
#define TARGET_NR_clock_settime (TARGET_NR_timer_create+5)
|
||||
#define TARGET_NR_clock_gettime (TARGET_NR_timer_create+6)
|
||||
#define TARGET_NR_clock_getres (TARGET_NR_timer_create+7)
|
||||
#define TARGET_NR_clock_nanosleep (TARGET_NR_timer_create+8)
|
||||
#define TARGET_NR_statfs64 268
|
||||
#define TARGET_NR_fstatfs64 269
|
||||
#define TARGET_NR_tgkill 270
|
||||
#define TARGET_NR_utimes 271
|
||||
#define TARGET_NR_fadvise64_64 272
|
||||
#define TARGET_NR_vserver 273
|
||||
#define TARGET_NR_mbind 274
|
||||
#define TARGET_NR_get_mempolicy 275
|
||||
#define TARGET_NR_set_mempolicy 276
|
||||
#define TARGET_NR_mq_open 277
|
||||
#define TARGET_NR_mq_unlink (TARGET_NR_mq_open+1)
|
||||
#define TARGET_NR_mq_timedsend (TARGET_NR_mq_open+2)
|
||||
#define TARGET_NR_mq_timedreceive (TARGET_NR_mq_open+3)
|
||||
#define TARGET_NR_mq_notify (TARGET_NR_mq_open+4)
|
||||
#define TARGET_NR_mq_getsetattr (TARGET_NR_mq_open+5)
|
||||
#define TARGET_NR_kexec_load 283
|
||||
#define TARGET_NR_waitid 284
|
||||
/* #define TARGET_NR_sys_setaltroot 285 */
|
||||
#define TARGET_NR_add_key 286
|
||||
#define TARGET_NR_request_key 287
|
||||
#define TARGET_NR_keyctl 288
|
||||
#define TARGET_NR_ioprio_set 289
|
||||
#define TARGET_NR_ioprio_get 290
|
||||
#define TARGET_NR_inotify_init 291
|
||||
#define TARGET_NR_inotify_add_watch 292
|
||||
#define TARGET_NR_inotify_rm_watch 293
|
||||
#define TARGET_NR_migrate_pages 294
|
||||
#define TARGET_NR_openat 295
|
||||
#define TARGET_NR_mkdirat 296
|
||||
#define TARGET_NR_mknodat 297
|
||||
#define TARGET_NR_fchownat 298
|
||||
#define TARGET_NR_futimesat 299
|
||||
#define TARGET_NR_fstatat64 300
|
||||
#define TARGET_NR_unlinkat 301
|
||||
#define TARGET_NR_renameat 302
|
||||
#define TARGET_NR_linkat 303
|
||||
#define TARGET_NR_symlinkat 304
|
||||
#define TARGET_NR_readlinkat 305
|
||||
#define TARGET_NR_fchmodat 306
|
||||
#define TARGET_NR_faccessat 307
|
||||
#define TARGET_NR_pselect6 308
|
||||
#define TARGET_NR_ppoll 309
|
||||
#define TARGET_NR_unshare 310
|
||||
#define TARGET_NR_set_robust_list 311
|
||||
#define TARGET_NR_get_robust_list 312
|
||||
#define TARGET_NR_splice 313
|
||||
#define TARGET_NR_sync_file_range 314
|
||||
#define TARGET_NR_tee 315
|
||||
#define TARGET_NR_vmsplice 316
|
||||
#define TARGET_NR_move_pages 317
|
||||
#define TARGET_NR_getcpu 318
|
||||
#define TARGET_NR_epoll_pwait 319
|
||||
#define TARGET_NR_utimensat 320
|
||||
#define TARGET_NR_signalfd 321
|
||||
#define TARGET_NR_timerfd_create 322
|
||||
#define TARGET_NR_eventfd 323
|
||||
#define TARGET_NR_fallocate 324
|
||||
#define TARGET_NR_timerfd_settime 325
|
||||
#define TARGET_NR_timerfd_gettime 326
|
||||
#define TARGET_NR_signalfd4 327
|
||||
#define TARGET_NR_eventfd2 328
|
||||
#define TARGET_NR_epoll_create1 329
|
||||
#define TARGET_NR_dup3 330
|
||||
#define TARGET_NR_pipe2 331
|
||||
#define TARGET_NR_inotify_init1 332
|
||||
#define TARGET_NR_preadv 333
|
||||
#define TARGET_NR_pwritev 334
|
||||
#define TARGET_NR_setns 335
|
||||
#define TARGET_NR_name_to_handle_at 336
|
||||
#define TARGET_NR_open_by_handle_at 337
|
||||
#define TARGET_NR_rt_tgsigqueueinfo 338
|
||||
#define TARGET_NR_perf_event_open 339
|
||||
#define TARGET_NR_recvmmsg 340
|
||||
#define TARGET_NR_accept4 341
|
||||
#define TARGET_NR_fanotify_init 342
|
||||
#define TARGET_NR_fanotify_mark 343
|
||||
#define TARGET_NR_prlimit64 344
|
||||
#define TARGET_NR_clock_adjtime 345
|
||||
#define TARGET_NR_syncfs 346
|
||||
#define TARGET_NR_sendmmsg 347
|
||||
#define TARGET_NR_process_vm_readv 348
|
||||
#define TARGET_NR_process_vm_writev 349
|
||||
#define TARGET_NR_kcmp 350
|
||||
#define TARGET_NR_finit_module 351
|
||||
#define TARGET_NR_sched_setattr 352
|
||||
#define TARGET_NR_sched_getattr 353
|
||||
#define TARGET_NR_renameat2 354
|
||||
#define TARGET_NR_seccomp 355
|
||||
#define TARGET_NR_getrandom 356
|
||||
#define TARGET_NR_memfd_create 357
|
||||
#define TARGET_NR_bpf 358
|
||||
#define TARGET_NR_execveat 359
|
||||
|
||||
#endif
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* CRIS specific CPU ABI and functions for linux-user
|
||||
*
|
||||
* Copyright (c) 2007 AXIS Communications AB
|
||||
* Written by Edgar E. Iglesias
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef CRIS_TARGET_CPU_H
|
||||
#define CRIS_TARGET_CPU_H
|
||||
|
||||
static inline void cpu_clone_regs_child(CPUCRISState *env, target_ulong newsp,
|
||||
unsigned flags)
|
||||
{
|
||||
if (newsp) {
|
||||
env->regs[14] = newsp;
|
||||
}
|
||||
env->regs[10] = 0;
|
||||
}
|
||||
|
||||
static inline void cpu_clone_regs_parent(CPUCRISState *env, unsigned flags)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void cpu_set_tls(CPUCRISState *env, target_ulong newtls)
|
||||
{
|
||||
env->pregs[PR_PID] = (env->pregs[PR_PID] & 0xff) | newtls;
|
||||
}
|
||||
|
||||
static inline abi_ulong get_sp_from_cpustate(CPUCRISState *state)
|
||||
{
|
||||
return state->regs[14];
|
||||
}
|
||||
#endif
|
|
@ -1,14 +0,0 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or (at your option) any
|
||||
* later version. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef CRIS_TARGET_ELF_H
|
||||
#define CRIS_TARGET_ELF_H
|
||||
static inline const char *cpu_get_model(uint32_t eflags)
|
||||
{
|
||||
return "any";
|
||||
}
|
||||
#endif
|
|
@ -1,7 +0,0 @@
|
|||
#ifndef CRIS_TARGET_ERRNO_DEFS_H
|
||||
#define CRIS_TARGET_ERRNO_DEFS_H
|
||||
|
||||
/* Target uses generic errno */
|
||||
#include "../generic/target_errno_defs.h"
|
||||
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or (at your option) any
|
||||
* later version. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef CRIS_TARGET_FCNTL_H
|
||||
#define CRIS_TARGET_FCNTL_H
|
||||
#include "../generic/fcntl.h"
|
||||
#endif
|
|
@ -1,13 +0,0 @@
|
|||
/*
|
||||
* arch/cris/include/asm/processor.h:
|
||||
* TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
|
||||
*
|
||||
* arch/cris/include/arch-v32/arch/processor.h
|
||||
* TASK_SIZE 0xb0000000
|
||||
*/
|
||||
#define TASK_UNMAPPED_BASE TARGET_PAGE_ALIGN(0xb0000000 / 3)
|
||||
|
||||
/* arch/cris/include/uapi/asm/elf.h */
|
||||
#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE * 2)
|
||||
|
||||
#include "../generic/target_mman.h"
|
|
@ -1 +0,0 @@
|
|||
/* No special prctl support required. */
|
|
@ -1 +0,0 @@
|
|||
/* No target-specific /proc support */
|
|
@ -1 +0,0 @@
|
|||
#include "../generic/target_resource.h"
|
|
@ -1,9 +0,0 @@
|
|||
#ifndef CRIS_TARGET_SIGNAL_H
|
||||
#define CRIS_TARGET_SIGNAL_H
|
||||
|
||||
#include "../generic/signal.h"
|
||||
|
||||
#define TARGET_ARCH_HAS_SETUP_FRAME
|
||||
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
|
||||
|
||||
#endif /* CRIS_TARGET_SIGNAL_H */
|
|
@ -1 +0,0 @@
|
|||
#include "../generic/target_structs.h"
|
|
@ -1,46 +0,0 @@
|
|||
#ifndef CRIS_TARGET_SYSCALL_H
|
||||
#define CRIS_TARGET_SYSCALL_H
|
||||
|
||||
#define UNAME_MACHINE "cris"
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
||||
/* pt_regs not only specifies the format in the user-struct during
|
||||
* ptrace but is also the frame format used in the kernel prologue/epilogues
|
||||
* themselves
|
||||
*/
|
||||
|
||||
struct target_pt_regs {
|
||||
unsigned long orig_r10;
|
||||
/* pushed by movem r13, [sp] in SAVE_ALL. */
|
||||
unsigned long r0;
|
||||
unsigned long r1;
|
||||
unsigned long r2;
|
||||
unsigned long r3;
|
||||
unsigned long r4;
|
||||
unsigned long r5;
|
||||
unsigned long r6;
|
||||
unsigned long r7;
|
||||
unsigned long r8;
|
||||
unsigned long r9;
|
||||
unsigned long r10;
|
||||
unsigned long r11;
|
||||
unsigned long r12;
|
||||
unsigned long r13;
|
||||
unsigned long acr;
|
||||
unsigned long srs;
|
||||
unsigned long mof;
|
||||
unsigned long spc;
|
||||
unsigned long ccs;
|
||||
unsigned long srp;
|
||||
unsigned long erp; /* This is actually the debugged process's PC */
|
||||
/* For debugging purposes; saved only when needed. */
|
||||
unsigned long exs;
|
||||
unsigned long eda;
|
||||
};
|
||||
|
||||
#define TARGET_CLONE_BACKWARDS2
|
||||
#define TARGET_MCL_CURRENT 1
|
||||
#define TARGET_MCL_FUTURE 2
|
||||
#define TARGET_MCL_ONFAULT 4
|
||||
|
||||
#endif
|
|
@ -1,225 +0,0 @@
|
|||
/* from asm/termbits.h */
|
||||
|
||||
#ifndef LINUX_USER_CRIS_TERMBITS_H
|
||||
#define LINUX_USER_CRIS_TERMBITS_H
|
||||
|
||||
#define TARGET_NCCS 19
|
||||
|
||||
typedef unsigned char target_cc_t; /* cc_t */
|
||||
typedef unsigned int target_speed_t; /* speed_t */
|
||||
typedef unsigned int target_tcflag_t; /* tcflag_t */
|
||||
|
||||
struct target_termios {
|
||||
target_tcflag_t c_iflag; /* input mode flags */
|
||||
target_tcflag_t c_oflag; /* output mode flags */
|
||||
target_tcflag_t c_cflag; /* control mode flags */
|
||||
target_tcflag_t c_lflag; /* local mode flags */
|
||||
target_cc_t c_line; /* line discipline */
|
||||
target_cc_t c_cc[TARGET_NCCS]; /* control characters */
|
||||
};
|
||||
|
||||
/* c_iflag bits */
|
||||
#define TARGET_IGNBRK 0000001
|
||||
#define TARGET_BRKINT 0000002
|
||||
#define TARGET_IGNPAR 0000004
|
||||
#define TARGET_PARMRK 0000010
|
||||
#define TARGET_INPCK 0000020
|
||||
#define TARGET_ISTRIP 0000040
|
||||
#define TARGET_INLCR 0000100
|
||||
#define TARGET_IGNCR 0000200
|
||||
#define TARGET_ICRNL 0000400
|
||||
#define TARGET_IUCLC 0001000
|
||||
#define TARGET_IXON 0002000
|
||||
#define TARGET_IXANY 0004000
|
||||
#define TARGET_IXOFF 0010000
|
||||
#define TARGET_IMAXBEL 0020000
|
||||
#define TARGET_IUTF8 0040000
|
||||
|
||||
/* c_oflag bits */
|
||||
#define TARGET_OPOST 0000001
|
||||
#define TARGET_OLCUC 0000002
|
||||
#define TARGET_ONLCR 0000004
|
||||
#define TARGET_OCRNL 0000010
|
||||
#define TARGET_ONOCR 0000020
|
||||
#define TARGET_ONLRET 0000040
|
||||
#define TARGET_OFILL 0000100
|
||||
#define TARGET_OFDEL 0000200
|
||||
#define TARGET_NLDLY 0000400
|
||||
#define TARGET_NL0 0000000
|
||||
#define TARGET_NL1 0000400
|
||||
#define TARGET_CRDLY 0003000
|
||||
#define TARGET_CR0 0000000
|
||||
#define TARGET_CR1 0001000
|
||||
#define TARGET_CR2 0002000
|
||||
#define TARGET_CR3 0003000
|
||||
#define TARGET_TABDLY 0014000
|
||||
#define TARGET_TAB0 0000000
|
||||
#define TARGET_TAB1 0004000
|
||||
#define TARGET_TAB2 0010000
|
||||
#define TARGET_TAB3 0014000
|
||||
#define TARGET_XTABS 0014000
|
||||
#define TARGET_BSDLY 0020000
|
||||
#define TARGET_BS0 0000000
|
||||
#define TARGET_BS1 0020000
|
||||
#define TARGET_VTDLY 0040000
|
||||
#define TARGET_VT0 0000000
|
||||
#define TARGET_VT1 0040000
|
||||
#define TARGET_FFDLY 0100000
|
||||
#define TARGET_FF0 0000000
|
||||
#define TARGET_FF1 0100000
|
||||
|
||||
/* c_cflag bit meaning */
|
||||
#define TARGET_CBAUD 0010017
|
||||
#define TARGET_B0 0000000 /* hang up */
|
||||
#define TARGET_B50 0000001
|
||||
#define TARGET_B75 0000002
|
||||
#define TARGET_B110 0000003
|
||||
#define TARGET_B134 0000004
|
||||
#define TARGET_B150 0000005
|
||||
#define TARGET_B200 0000006
|
||||
#define TARGET_B300 0000007
|
||||
#define TARGET_B600 0000010
|
||||
#define TARGET_B1200 0000011
|
||||
#define TARGET_B1800 0000012
|
||||
#define TARGET_B2400 0000013
|
||||
#define TARGET_B4800 0000014
|
||||
#define TARGET_B9600 0000015
|
||||
#define TARGET_B19200 0000016
|
||||
#define TARGET_B38400 0000017
|
||||
#define TARGET_EXTA B19200
|
||||
#define TARGET_EXTB B38400
|
||||
#define TARGET_CSIZE 0000060
|
||||
#define TARGET_CS5 0000000
|
||||
#define TARGET_CS6 0000020
|
||||
#define TARGET_CS7 0000040
|
||||
#define TARGET_CS8 0000060
|
||||
#define TARGET_CSTOPB 0000100
|
||||
#define TARGET_CREAD 0000200
|
||||
#define TARGET_PARENB 0000400
|
||||
#define TARGET_PARODD 0001000
|
||||
#define TARGET_HUPCL 0002000
|
||||
#define TARGET_CLOCAL 0004000
|
||||
#define TARGET_CBAUDEX 0010000
|
||||
#define TARGET_B57600 0010001
|
||||
#define TARGET_B115200 0010002
|
||||
#define TARGET_B230400 0010003
|
||||
#define TARGET_B460800 0010004
|
||||
#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */
|
||||
#define TARGET_CRTSCTS 020000000000 /* flow control */
|
||||
|
||||
/* c_lflag bits */
|
||||
#define TARGET_ISIG 0000001
|
||||
#define TARGET_ICANON 0000002
|
||||
#define TARGET_XCASE 0000004
|
||||
#define TARGET_ECHO 0000010
|
||||
#define TARGET_ECHOE 0000020
|
||||
#define TARGET_ECHOK 0000040
|
||||
#define TARGET_ECHONL 0000100
|
||||
#define TARGET_NOFLSH 0000200
|
||||
#define TARGET_TOSTOP 0000400
|
||||
#define TARGET_ECHOCTL 0001000
|
||||
#define TARGET_ECHOPRT 0002000
|
||||
#define TARGET_ECHOKE 0004000
|
||||
#define TARGET_FLUSHO 0010000
|
||||
#define TARGET_PENDIN 0040000
|
||||
#define TARGET_IEXTEN 0100000
|
||||
#define TARGET_EXTPROC 0200000
|
||||
|
||||
/* c_cc character offsets */
|
||||
#define TARGET_VINTR 0
|
||||
#define TARGET_VQUIT 1
|
||||
#define TARGET_VERASE 2
|
||||
#define TARGET_VKILL 3
|
||||
#define TARGET_VEOF 4
|
||||
#define TARGET_VTIME 5
|
||||
#define TARGET_VMIN 6
|
||||
#define TARGET_VSWTC 7
|
||||
#define TARGET_VSTART 8
|
||||
#define TARGET_VSTOP 9
|
||||
#define TARGET_VSUSP 10
|
||||
#define TARGET_VEOL 11
|
||||
#define TARGET_VREPRINT 12
|
||||
#define TARGET_VDISCARD 13
|
||||
#define TARGET_VWERASE 14
|
||||
#define TARGET_VLNEXT 15
|
||||
#define TARGET_VEOL2 16
|
||||
|
||||
/* ioctls */
|
||||
|
||||
#define TARGET_TCGETS 0x5401
|
||||
#define TARGET_TCSETS 0x5402
|
||||
#define TARGET_TCSETSW 0x5403
|
||||
#define TARGET_TCSETSF 0x5404
|
||||
#define TARGET_TCGETA 0x5405
|
||||
#define TARGET_TCSETA 0x5406
|
||||
#define TARGET_TCSETAW 0x5407
|
||||
#define TARGET_TCSETAF 0x5408
|
||||
#define TARGET_TCSBRK 0x5409
|
||||
#define TARGET_TCXONC 0x540A
|
||||
#define TARGET_TCFLSH 0x540B
|
||||
|
||||
#define TARGET_TIOCEXCL 0x540C
|
||||
#define TARGET_TIOCNXCL 0x540D
|
||||
#define TARGET_TIOCSCTTY 0x540E
|
||||
#define TARGET_TIOCGPGRP 0x540F
|
||||
#define TARGET_TIOCSPGRP 0x5410
|
||||
#define TARGET_TIOCOUTQ 0x5411
|
||||
#define TARGET_TIOCSTI 0x5412
|
||||
#define TARGET_TIOCGWINSZ 0x5413
|
||||
#define TARGET_TIOCSWINSZ 0x5414
|
||||
#define TARGET_TIOCMGET 0x5415
|
||||
#define TARGET_TIOCMBIS 0x5416
|
||||
#define TARGET_TIOCMBIC 0x5417
|
||||
#define TARGET_TIOCMSET 0x5418
|
||||
#define TARGET_TIOCGSOFTCAR 0x5419
|
||||
#define TARGET_TIOCSSOFTCAR 0x541A
|
||||
#define TARGET_FIONREAD 0x541B
|
||||
#define TARGET_TIOCINQ TARGET_FIONREAD
|
||||
#define TARGET_TIOCLINUX 0x541C
|
||||
#define TARGET_TIOCCONS 0x541D
|
||||
#define TARGET_TIOCGSERIAL 0x541E
|
||||
#define TARGET_TIOCSSERIAL 0x541F
|
||||
#define TARGET_TIOCPKT 0x5420
|
||||
#define TARGET_FIONBIO 0x5421
|
||||
#define TARGET_TIOCNOTTY 0x5422
|
||||
#define TARGET_TIOCSETD 0x5423
|
||||
#define TARGET_TIOCGETD 0x5424
|
||||
#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
|
||||
#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */
|
||||
#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */
|
||||
#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */
|
||||
#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */
|
||||
#define TARGET_TIOCGPTN TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
|
||||
#define TARGET_TIOCSPTLCK TARGET_IOW('T',0x31, int) /* Lock/unlock Pty */
|
||||
#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) /* Safely open the slave */
|
||||
|
||||
#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */
|
||||
#define TARGET_FIOCLEX 0x5451
|
||||
#define TARGET_FIOASYNC 0x5452
|
||||
#define TARGET_TIOCSERCONFIG 0x5453
|
||||
#define TARGET_TIOCSERGWILD 0x5454
|
||||
#define TARGET_TIOCSERSWILD 0x5455
|
||||
#define TARGET_TIOCGLCKTRMIOS 0x5456
|
||||
#define TARGET_TIOCSLCKTRMIOS 0x5457
|
||||
#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */
|
||||
#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */
|
||||
#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */
|
||||
#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
|
||||
|
||||
#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
|
||||
#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
|
||||
#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
|
||||
#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
|
||||
|
||||
/* Used for packet mode */
|
||||
#define TARGET_TIOCPKT_DATA 0
|
||||
#define TARGET_TIOCPKT_FLUSHREAD 1
|
||||
#define TARGET_TIOCPKT_FLUSHWRITE 2
|
||||
#define TARGET_TIOCPKT_STOP 4
|
||||
#define TARGET_TIOCPKT_START 8
|
||||
#define TARGET_TIOCPKT_NOSTOP 16
|
||||
#define TARGET_TIOCPKT_DOSTOP 32
|
||||
|
||||
#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
||||
|
||||
#endif
|
|
@ -1647,21 +1647,6 @@ static uint32_t get_elf_hwcap(void)
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_CRIS
|
||||
|
||||
#define ELF_CLASS ELFCLASS32
|
||||
#define ELF_ARCH EM_CRIS
|
||||
|
||||
static inline void init_thread(struct target_pt_regs *regs,
|
||||
struct image_info *infop)
|
||||
{
|
||||
regs->erp = infop->entry;
|
||||
}
|
||||
|
||||
#define ELF_EXEC_PAGESIZE 8192
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_M68K
|
||||
|
||||
#define ELF_CLASS ELFCLASS32
|
||||
|
|
|
@ -10484,7 +10484,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
|
|||
case TARGET_NR_mmap:
|
||||
#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
|
||||
(defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
|
||||
defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
|
||||
defined(TARGET_M68K) || defined(TARGET_MICROBLAZE) \
|
||||
|| defined(TARGET_S390X)
|
||||
{
|
||||
abi_ulong *v;
|
||||
|
@ -12638,14 +12638,6 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
|
|||
#if defined(TARGET_MIPS)
|
||||
cpu_env->active_tc.CP0_UserLocal = arg1;
|
||||
return 0;
|
||||
#elif defined(TARGET_CRIS)
|
||||
if (arg1 & 0xff)
|
||||
ret = -TARGET_EINVAL;
|
||||
else {
|
||||
cpu_env->pregs[PR_PID] = arg1;
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
#elif defined(TARGET_I386) && defined(TARGET_ABI32)
|
||||
return do_set_thread_area(cpu_env, arg1);
|
||||
#elif defined(TARGET_M68K)
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
#if (defined(TARGET_I386) && defined(TARGET_ABI32)) \
|
||||
|| (defined(TARGET_ARM) && defined(TARGET_ABI32)) \
|
||||
|| (defined(TARGET_SPARC) && defined(TARGET_ABI32)) \
|
||||
|| defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
|
||||
|| defined(TARGET_M68K) || defined(TARGET_SH4)
|
||||
/* 16 bit uid wrappers emulation */
|
||||
#define USE_UID16
|
||||
#define target_id uint16_t
|
||||
|
@ -71,7 +71,7 @@
|
|||
#endif
|
||||
|
||||
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \
|
||||
|| defined(TARGET_M68K) || defined(TARGET_CRIS) \
|
||||
|| defined(TARGET_M68K) \
|
||||
|| defined(TARGET_S390X) || defined(TARGET_OPENRISC) \
|
||||
|| defined(TARGET_RISCV) \
|
||||
|| defined(TARGET_XTENSA) || defined(TARGET_LOONGARCH64)
|
||||
|
@ -1234,8 +1234,7 @@ struct target_winsize {
|
|||
#include "target_mman.h"
|
||||
|
||||
#if (defined(TARGET_I386) && defined(TARGET_ABI32)) \
|
||||
|| (defined(TARGET_ARM) && defined(TARGET_ABI32)) \
|
||||
|| defined(TARGET_CRIS)
|
||||
|| (defined(TARGET_ARM) && defined(TARGET_ABI32))
|
||||
#define TARGET_STAT_HAVE_NSEC
|
||||
struct target_stat {
|
||||
abi_ushort st_dev;
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
# Since: 3.0
|
||||
##
|
||||
{ 'enum' : 'SysEmuTarget',
|
||||
'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'cris', 'hppa', 'i386',
|
||||
'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'hppa', 'i386',
|
||||
'loongarch64', 'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64',
|
||||
'mips64el', 'mipsel', 'or1k', 'ppc',
|
||||
'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4',
|
||||
|
|
|
@ -9,9 +9,6 @@ arm
|
|||
avr
|
||||
~ .*/qemu((/include)?/hw/avr/.*|/target/avr/.*)
|
||||
|
||||
cris
|
||||
~ .*/qemu((/include)?/hw/cris/.*|/target/cris/.*)
|
||||
|
||||
hexagon-gen (component should be ignored in analysis)
|
||||
~ .*/qemu(/target/hexagon/.*generated.*)
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ mappings = {
|
|||
"armv7": "arm",
|
||||
"armv8-a" : ["aarch64", "aarch64_be"],
|
||||
"avr" : "avr",
|
||||
"cris" : "cris",
|
||||
# no hexagon in upstream gdb
|
||||
"hppa1.0" : "hppa",
|
||||
"i386" : "i386",
|
||||
|
|
|
@ -47,10 +47,10 @@ const struct scmp_arg_cmp sched_setscheduler_arg[] = {
|
|||
};
|
||||
|
||||
/*
|
||||
* See 'NOTES' in 'man 2 clone' - s390 & cross have 'flags' in
|
||||
* See 'NOTES' in 'man 2 clone' - s390 has 'flags' in
|
||||
* different position to other architectures
|
||||
*/
|
||||
#if defined(HOST_S390X) || defined(HOST_S390) || defined(HOST_CRIS)
|
||||
#if defined(HOST_S390X) || defined(HOST_S390)
|
||||
#define CLONE_FLAGS_ARG 1
|
||||
#else
|
||||
#define CLONE_FLAGS_ARG 0
|
||||
|
|
|
@ -62,7 +62,7 @@ static time_t qemu_ref_timedate(QEMUClockType clock)
|
|||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
source alpha/Kconfig
|
||||
source arm/Kconfig
|
||||
source avr/Kconfig
|
||||
source cris/Kconfig
|
||||
source hppa/Kconfig
|
||||
source i386/Kconfig
|
||||
source loongarch/Kconfig
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
config CRIS
|
||||
bool
|
|
@ -1,16 +0,0 @@
|
|||
/*
|
||||
* CRIS cpu parameters for qemu.
|
||||
*
|
||||
* Copyright (c) 2007 AXIS Communications AB
|
||||
* SPDX-License-Identifier: LGPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef CRIS_CPU_PARAM_H
|
||||
#define CRIS_CPU_PARAM_H
|
||||
|
||||
#define TARGET_LONG_BITS 32
|
||||
#define TARGET_PAGE_BITS 13
|
||||
#define TARGET_PHYS_ADDR_SPACE_BITS 32
|
||||
#define TARGET_VIRT_ADDR_SPACE_BITS 32
|
||||
|
||||
#endif
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* QEMU CRIS CPU QOM header (target agnostic)
|
||||
*
|
||||
* Copyright (c) 2012 SUSE LINUX Products GmbH
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
#ifndef QEMU_CRIS_CPU_QOM_H
|
||||
#define QEMU_CRIS_CPU_QOM_H
|
||||
|
||||
#include "hw/core/cpu.h"
|
||||
|
||||
#define TYPE_CRIS_CPU "cris-cpu"
|
||||
|
||||
OBJECT_DECLARE_CPU_TYPE(CRISCPU, CRISCPUClass, CRIS_CPU)
|
||||
|
||||
#define CRIS_CPU_TYPE_SUFFIX "-" TYPE_CRIS_CPU
|
||||
#define CRIS_CPU_TYPE_NAME(name) (name CRIS_CPU_TYPE_SUFFIX)
|
||||
|
||||
#endif
|
|
@ -1,323 +0,0 @@
|
|||
/*
|
||||
* QEMU CRIS CPU
|
||||
*
|
||||
* Copyright (c) 2008 AXIS Communications AB
|
||||
* Written by Edgar E. Iglesias.
|
||||
*
|
||||
* Copyright (c) 2012 SUSE LINUX Products GmbH
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "cpu.h"
|
||||
#include "mmu.h"
|
||||
|
||||
|
||||
static void cris_cpu_set_pc(CPUState *cs, vaddr value)
|
||||
{
|
||||
CRISCPU *cpu = CRIS_CPU(cs);
|
||||
|
||||
cpu->env.pc = value;
|
||||
}
|
||||
|
||||
static vaddr cris_cpu_get_pc(CPUState *cs)
|
||||
{
|
||||
CRISCPU *cpu = CRIS_CPU(cs);
|
||||
|
||||
return cpu->env.pc;
|
||||
}
|
||||
|
||||
static void cris_restore_state_to_opc(CPUState *cs,
|
||||
const TranslationBlock *tb,
|
||||
const uint64_t *data)
|
||||
{
|
||||
CRISCPU *cpu = CRIS_CPU(cs);
|
||||
|
||||
cpu->env.pc = data[0];
|
||||
}
|
||||
|
||||
static bool cris_cpu_has_work(CPUState *cs)
|
||||
{
|
||||
return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
|
||||
}
|
||||
|
||||
static int cris_cpu_mmu_index(CPUState *cs, bool ifetch)
|
||||
{
|
||||
return !!(cpu_env(cs)->pregs[PR_CCS] & U_FLAG);
|
||||
}
|
||||
|
||||
static void cris_cpu_reset_hold(Object *obj, ResetType type)
|
||||
{
|
||||
CPUState *cs = CPU(obj);
|
||||
CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(obj);
|
||||
CPUCRISState *env = cpu_env(cs);
|
||||
uint32_t vr;
|
||||
|
||||
if (ccc->parent_phases.hold) {
|
||||
ccc->parent_phases.hold(obj, type);
|
||||
}
|
||||
|
||||
vr = env->pregs[PR_VR];
|
||||
memset(env, 0, offsetof(CPUCRISState, end_reset_fields));
|
||||
env->pregs[PR_VR] = vr;
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
/* start in user mode with interrupts enabled. */
|
||||
env->pregs[PR_CCS] |= U_FLAG | I_FLAG | P_FLAG;
|
||||
#else
|
||||
cris_mmu_init(env);
|
||||
env->pregs[PR_CCS] = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static ObjectClass *cris_cpu_class_by_name(const char *cpu_model)
|
||||
{
|
||||
ObjectClass *oc;
|
||||
char *typename;
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
if (strcasecmp(cpu_model, "any") == 0) {
|
||||
return object_class_by_name(CRIS_CPU_TYPE_NAME("crisv32"));
|
||||
}
|
||||
#endif
|
||||
|
||||
typename = g_strdup_printf(CRIS_CPU_TYPE_NAME("%s"), cpu_model);
|
||||
oc = object_class_by_name(typename);
|
||||
g_free(typename);
|
||||
|
||||
return oc;
|
||||
}
|
||||
|
||||
static void cris_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(dev);
|
||||
Error *local_err = NULL;
|
||||
|
||||
cpu_exec_realizefn(cs, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
cpu_reset(cs);
|
||||
qemu_init_vcpu(cs);
|
||||
|
||||
ccc->parent_realize(dev, errp);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static void cris_cpu_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
CRISCPU *cpu = opaque;
|
||||
CPUState *cs = CPU(cpu);
|
||||
int type = irq == CRIS_CPU_IRQ ? CPU_INTERRUPT_HARD : CPU_INTERRUPT_NMI;
|
||||
|
||||
if (irq == CRIS_CPU_IRQ) {
|
||||
/*
|
||||
* The PIC passes us the vector for the IRQ as the value it sends
|
||||
* over the qemu_irq line
|
||||
*/
|
||||
cpu->env.interrupt_vector = level;
|
||||
}
|
||||
|
||||
if (level) {
|
||||
cpu_interrupt(cs, type);
|
||||
} else {
|
||||
cpu_reset_interrupt(cs, type);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void cris_disas_set_info(CPUState *cpu, disassemble_info *info)
|
||||
{
|
||||
if (cpu_env(cpu)->pregs[PR_VR] != 32) {
|
||||
info->mach = bfd_mach_cris_v0_v10;
|
||||
info->print_insn = print_insn_crisv10;
|
||||
} else {
|
||||
info->mach = bfd_mach_cris_v32;
|
||||
info->print_insn = print_insn_crisv32;
|
||||
}
|
||||
}
|
||||
|
||||
static void cris_cpu_initfn(Object *obj)
|
||||
{
|
||||
CRISCPU *cpu = CRIS_CPU(obj);
|
||||
CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(obj);
|
||||
CPUCRISState *env = &cpu->env;
|
||||
|
||||
env->pregs[PR_VR] = ccc->vr;
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* IRQ and NMI lines. */
|
||||
qdev_init_gpio_in(DEVICE(cpu), cris_cpu_set_irq, 2);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "hw/core/sysemu-cpu-ops.h"
|
||||
|
||||
static const struct SysemuCPUOps cris_sysemu_ops = {
|
||||
.get_phys_page_debug = cris_cpu_get_phys_page_debug,
|
||||
};
|
||||
#endif
|
||||
|
||||
#include "hw/core/tcg-cpu-ops.h"
|
||||
|
||||
static const TCGCPUOps crisv10_tcg_ops = {
|
||||
.initialize = cris_initialize_crisv10_tcg,
|
||||
.restore_state_to_opc = cris_restore_state_to_opc,
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
.tlb_fill = cris_cpu_tlb_fill,
|
||||
.cpu_exec_interrupt = cris_cpu_exec_interrupt,
|
||||
.cpu_exec_halt = cris_cpu_has_work,
|
||||
.do_interrupt = crisv10_cpu_do_interrupt,
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
};
|
||||
|
||||
static const TCGCPUOps crisv32_tcg_ops = {
|
||||
.initialize = cris_initialize_tcg,
|
||||
.restore_state_to_opc = cris_restore_state_to_opc,
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
.tlb_fill = cris_cpu_tlb_fill,
|
||||
.cpu_exec_interrupt = cris_cpu_exec_interrupt,
|
||||
.cpu_exec_halt = cris_cpu_has_work,
|
||||
.do_interrupt = cris_cpu_do_interrupt,
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
};
|
||||
|
||||
static void crisv8_cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
CPUClass *cc = CPU_CLASS(oc);
|
||||
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
|
||||
|
||||
ccc->vr = 8;
|
||||
cc->gdb_read_register = crisv10_cpu_gdb_read_register;
|
||||
cc->tcg_ops = &crisv10_tcg_ops;
|
||||
}
|
||||
|
||||
static void crisv9_cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
CPUClass *cc = CPU_CLASS(oc);
|
||||
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
|
||||
|
||||
ccc->vr = 9;
|
||||
cc->gdb_read_register = crisv10_cpu_gdb_read_register;
|
||||
cc->tcg_ops = &crisv10_tcg_ops;
|
||||
}
|
||||
|
||||
static void crisv10_cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
CPUClass *cc = CPU_CLASS(oc);
|
||||
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
|
||||
|
||||
ccc->vr = 10;
|
||||
cc->gdb_read_register = crisv10_cpu_gdb_read_register;
|
||||
cc->tcg_ops = &crisv10_tcg_ops;
|
||||
}
|
||||
|
||||
static void crisv11_cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
CPUClass *cc = CPU_CLASS(oc);
|
||||
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
|
||||
|
||||
ccc->vr = 11;
|
||||
cc->gdb_read_register = crisv10_cpu_gdb_read_register;
|
||||
cc->tcg_ops = &crisv10_tcg_ops;
|
||||
}
|
||||
|
||||
static void crisv17_cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
CPUClass *cc = CPU_CLASS(oc);
|
||||
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
|
||||
|
||||
ccc->vr = 17;
|
||||
cc->gdb_read_register = crisv10_cpu_gdb_read_register;
|
||||
cc->tcg_ops = &crisv10_tcg_ops;
|
||||
}
|
||||
|
||||
static void crisv32_cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
CPUClass *cc = CPU_CLASS(oc);
|
||||
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
|
||||
|
||||
ccc->vr = 32;
|
||||
cc->tcg_ops = &crisv32_tcg_ops;
|
||||
}
|
||||
|
||||
static void cris_cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
CPUClass *cc = CPU_CLASS(oc);
|
||||
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
|
||||
ResettableClass *rc = RESETTABLE_CLASS(oc);
|
||||
|
||||
device_class_set_parent_realize(dc, cris_cpu_realizefn,
|
||||
&ccc->parent_realize);
|
||||
|
||||
resettable_class_set_parent_phases(rc, NULL, cris_cpu_reset_hold, NULL,
|
||||
&ccc->parent_phases);
|
||||
|
||||
cc->class_by_name = cris_cpu_class_by_name;
|
||||
cc->has_work = cris_cpu_has_work;
|
||||
cc->mmu_index = cris_cpu_mmu_index;
|
||||
cc->dump_state = cris_cpu_dump_state;
|
||||
cc->set_pc = cris_cpu_set_pc;
|
||||
cc->get_pc = cris_cpu_get_pc;
|
||||
cc->gdb_read_register = cris_cpu_gdb_read_register;
|
||||
cc->gdb_write_register = cris_cpu_gdb_write_register;
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
dc->vmsd = &vmstate_cris_cpu;
|
||||
cc->sysemu_ops = &cris_sysemu_ops;
|
||||
#endif
|
||||
|
||||
cc->gdb_num_core_regs = 49;
|
||||
cc->gdb_stop_before_watchpoint = true;
|
||||
|
||||
cc->disas_set_info = cris_disas_set_info;
|
||||
}
|
||||
|
||||
#define DEFINE_CRIS_CPU_TYPE(cpu_model, initfn) \
|
||||
{ \
|
||||
.parent = TYPE_CRIS_CPU, \
|
||||
.class_init = initfn, \
|
||||
.name = CRIS_CPU_TYPE_NAME(cpu_model), \
|
||||
}
|
||||
|
||||
static const TypeInfo cris_cpu_model_type_infos[] = {
|
||||
{
|
||||
.name = TYPE_CRIS_CPU,
|
||||
.parent = TYPE_CPU,
|
||||
.instance_size = sizeof(CRISCPU),
|
||||
.instance_align = __alignof(CRISCPU),
|
||||
.instance_init = cris_cpu_initfn,
|
||||
.abstract = true,
|
||||
.class_size = sizeof(CRISCPUClass),
|
||||
.class_init = cris_cpu_class_init,
|
||||
},
|
||||
DEFINE_CRIS_CPU_TYPE("crisv8", crisv8_cpu_class_init),
|
||||
DEFINE_CRIS_CPU_TYPE("crisv9", crisv9_cpu_class_init),
|
||||
DEFINE_CRIS_CPU_TYPE("crisv10", crisv10_cpu_class_init),
|
||||
DEFINE_CRIS_CPU_TYPE("crisv11", crisv11_cpu_class_init),
|
||||
DEFINE_CRIS_CPU_TYPE("crisv17", crisv17_cpu_class_init),
|
||||
DEFINE_CRIS_CPU_TYPE("crisv32", crisv32_cpu_class_init),
|
||||
};
|
||||
|
||||
DEFINE_TYPES(cris_cpu_model_type_infos)
|
|
@ -1,286 +0,0 @@
|
|||
/*
|
||||
* CRIS virtual CPU header
|
||||
*
|
||||
* Copyright (c) 2007 AXIS Communications AB
|
||||
* Written by Edgar E. Iglesias
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CRIS_CPU_H
|
||||
#define CRIS_CPU_H
|
||||
|
||||
#include "cpu-qom.h"
|
||||
#include "exec/cpu-defs.h"
|
||||
|
||||
#define EXCP_NMI 1
|
||||
#define EXCP_GURU 2
|
||||
#define EXCP_BUSFAULT 3
|
||||
#define EXCP_IRQ 4
|
||||
#define EXCP_BREAK 5
|
||||
|
||||
/* CRIS-specific interrupt pending bits. */
|
||||
#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3
|
||||
|
||||
/* CRUS CPU device objects interrupt lines. */
|
||||
/* PIC passes the vector for the IRQ as the value of it sends over qemu_irq */
|
||||
#define CRIS_CPU_IRQ 0
|
||||
#define CRIS_CPU_NMI 1
|
||||
|
||||
/* Register aliases. R0 - R15 */
|
||||
#define R_FP 8
|
||||
#define R_SP 14
|
||||
#define R_ACR 15
|
||||
|
||||
/* Support regs, P0 - P15 */
|
||||
#define PR_BZ 0
|
||||
#define PR_VR 1
|
||||
#define PR_PID 2
|
||||
#define PR_SRS 3
|
||||
#define PR_WZ 4
|
||||
#define PR_EXS 5
|
||||
#define PR_EDA 6
|
||||
#define PR_PREFIX 6 /* On CRISv10 P6 is reserved, we use it as prefix. */
|
||||
#define PR_MOF 7
|
||||
#define PR_DZ 8
|
||||
#define PR_EBP 9
|
||||
#define PR_ERP 10
|
||||
#define PR_SRP 11
|
||||
#define PR_NRP 12
|
||||
#define PR_CCS 13
|
||||
#define PR_USP 14
|
||||
#define PRV10_BRP 14
|
||||
#define PR_SPC 15
|
||||
|
||||
/* CPU flags. */
|
||||
#define Q_FLAG 0x80000000
|
||||
#define M_FLAG_V32 0x40000000
|
||||
#define PFIX_FLAG 0x800 /* CRISv10 Only. */
|
||||
#define F_FLAG_V10 0x400
|
||||
#define P_FLAG_V10 0x200
|
||||
#define S_FLAG 0x200
|
||||
#define R_FLAG 0x100
|
||||
#define P_FLAG 0x80
|
||||
#define M_FLAG_V10 0x80
|
||||
#define U_FLAG 0x40
|
||||
#define I_FLAG 0x20
|
||||
#define X_FLAG 0x10
|
||||
#define N_FLAG 0x08
|
||||
#define Z_FLAG 0x04
|
||||
#define V_FLAG 0x02
|
||||
#define C_FLAG 0x01
|
||||
#define ALU_FLAGS 0x1F
|
||||
|
||||
/* Condition codes. */
|
||||
#define CC_CC 0
|
||||
#define CC_CS 1
|
||||
#define CC_NE 2
|
||||
#define CC_EQ 3
|
||||
#define CC_VC 4
|
||||
#define CC_VS 5
|
||||
#define CC_PL 6
|
||||
#define CC_MI 7
|
||||
#define CC_LS 8
|
||||
#define CC_HI 9
|
||||
#define CC_GE 10
|
||||
#define CC_LT 11
|
||||
#define CC_GT 12
|
||||
#define CC_LE 13
|
||||
#define CC_A 14
|
||||
#define CC_P 15
|
||||
|
||||
typedef struct {
|
||||
uint32_t hi;
|
||||
uint32_t lo;
|
||||
} TLBSet;
|
||||
|
||||
typedef struct CPUArchState {
|
||||
uint32_t regs[16];
|
||||
/* P0 - P15 are referred to as special registers in the docs. */
|
||||
uint32_t pregs[16];
|
||||
|
||||
/* Pseudo register for the PC. Not directly accessible on CRIS. */
|
||||
uint32_t pc;
|
||||
|
||||
/* Pseudo register for the kernel stack. */
|
||||
uint32_t ksp;
|
||||
|
||||
/* Branch. */
|
||||
int dslot;
|
||||
int btaken;
|
||||
uint32_t btarget;
|
||||
|
||||
/* Condition flag tracking. */
|
||||
uint32_t cc_op;
|
||||
uint32_t cc_mask;
|
||||
uint32_t cc_dest;
|
||||
uint32_t cc_src;
|
||||
uint32_t cc_result;
|
||||
/* size of the operation, 1 = byte, 2 = word, 4 = dword. */
|
||||
int cc_size;
|
||||
/* X flag at the time of cc snapshot. */
|
||||
int cc_x;
|
||||
|
||||
/* CRIS has certain insns that lockout interrupts. */
|
||||
int locked_irq;
|
||||
int interrupt_vector;
|
||||
int fault_vector;
|
||||
int trap_vector;
|
||||
|
||||
/* FIXME: add a check in the translator to avoid writing to support
|
||||
register sets beyond the 4th. The ISA allows up to 256! but in
|
||||
practice there is no core that implements more than 4.
|
||||
|
||||
Support function registers are used to control units close to the
|
||||
core. Accesses do not pass down the normal hierarchy.
|
||||
*/
|
||||
uint32_t sregs[4][16];
|
||||
|
||||
/* Linear feedback shift reg in the mmu. Used to provide pseudo
|
||||
randomness for the 'hint' the mmu gives to sw for choosing valid
|
||||
sets on TLB refills. */
|
||||
uint32_t mmu_rand_lfsr;
|
||||
|
||||
/*
|
||||
* We just store the stores to the tlbset here for later evaluation
|
||||
* when the hw needs access to them.
|
||||
*
|
||||
* One for I and another for D.
|
||||
*/
|
||||
TLBSet tlbsets[2][4][16];
|
||||
|
||||
/* Fields up to this point are cleared by a CPU reset */
|
||||
struct {} end_reset_fields;
|
||||
|
||||
/* Members from load_info on are preserved across resets. */
|
||||
void *load_info;
|
||||
} CPUCRISState;
|
||||
|
||||
/**
|
||||
* CRISCPU:
|
||||
* @env: #CPUCRISState
|
||||
*
|
||||
* A CRIS CPU.
|
||||
*/
|
||||
struct ArchCPU {
|
||||
CPUState parent_obj;
|
||||
|
||||
CPUCRISState env;
|
||||
};
|
||||
|
||||
/**
|
||||
* CRISCPUClass:
|
||||
* @parent_realize: The parent class' realize handler.
|
||||
* @parent_phases: The parent class' reset phase handlers.
|
||||
* @vr: Version Register value.
|
||||
*
|
||||
* A CRIS CPU model.
|
||||
*/
|
||||
struct CRISCPUClass {
|
||||
CPUClass parent_class;
|
||||
|
||||
DeviceRealize parent_realize;
|
||||
ResettablePhases parent_phases;
|
||||
|
||||
uint32_t vr;
|
||||
};
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
extern const VMStateDescription vmstate_cris_cpu;
|
||||
|
||||
void cris_cpu_do_interrupt(CPUState *cpu);
|
||||
void crisv10_cpu_do_interrupt(CPUState *cpu);
|
||||
bool cris_cpu_exec_interrupt(CPUState *cpu, int int_req);
|
||||
|
||||
bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool probe, uintptr_t retaddr);
|
||||
hwaddr cris_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
|
||||
#endif
|
||||
|
||||
void cris_cpu_dump_state(CPUState *cs, FILE *f, int flags);
|
||||
|
||||
int crisv10_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||
int cris_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||
int cris_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
|
||||
void cris_initialize_tcg(void);
|
||||
void cris_initialize_crisv10_tcg(void);
|
||||
|
||||
/* Instead of computing the condition codes after each CRIS instruction,
|
||||
* QEMU just stores one operand (called CC_SRC), the result
|
||||
* (called CC_DEST) and the type of operation (called CC_OP). When the
|
||||
* condition codes are needed, the condition codes can be calculated
|
||||
* using this information. Condition codes are not generated if they
|
||||
* are only needed for conditional branches.
|
||||
*/
|
||||
enum {
|
||||
CC_OP_DYNAMIC, /* Use env->cc_op */
|
||||
CC_OP_FLAGS,
|
||||
CC_OP_CMP,
|
||||
CC_OP_MOVE,
|
||||
CC_OP_ADD,
|
||||
CC_OP_ADDC,
|
||||
CC_OP_MCP,
|
||||
CC_OP_ADDU,
|
||||
CC_OP_SUB,
|
||||
CC_OP_SUBU,
|
||||
CC_OP_NEG,
|
||||
CC_OP_BTST,
|
||||
CC_OP_MULS,
|
||||
CC_OP_MULU,
|
||||
CC_OP_DSTEP,
|
||||
CC_OP_MSTEP,
|
||||
CC_OP_BOUND,
|
||||
|
||||
CC_OP_OR,
|
||||
CC_OP_AND,
|
||||
CC_OP_XOR,
|
||||
CC_OP_LSL,
|
||||
CC_OP_LSR,
|
||||
CC_OP_ASR,
|
||||
CC_OP_LZ
|
||||
};
|
||||
|
||||
/* CRIS uses 8k pages. */
|
||||
#define MMAP_SHIFT TARGET_PAGE_BITS
|
||||
|
||||
#define CPU_RESOLVING_TYPE TYPE_CRIS_CPU
|
||||
|
||||
/* MMU modes definitions */
|
||||
#define MMU_USER_IDX 1
|
||||
|
||||
/* Support function regs. */
|
||||
#define SFR_RW_GC_CFG 0][0
|
||||
#define SFR_RW_MM_CFG env->pregs[PR_SRS]][0
|
||||
#define SFR_RW_MM_KBASE_LO env->pregs[PR_SRS]][1
|
||||
#define SFR_RW_MM_KBASE_HI env->pregs[PR_SRS]][2
|
||||
#define SFR_R_MM_CAUSE env->pregs[PR_SRS]][3
|
||||
#define SFR_RW_MM_TLB_SEL env->pregs[PR_SRS]][4
|
||||
#define SFR_RW_MM_TLB_LO env->pregs[PR_SRS]][5
|
||||
#define SFR_RW_MM_TLB_HI env->pregs[PR_SRS]][6
|
||||
|
||||
#include "exec/cpu-all.h"
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUCRISState *env, vaddr *pc,
|
||||
uint64_t *cs_base, uint32_t *flags)
|
||||
{
|
||||
*pc = env->pc;
|
||||
*cs_base = 0;
|
||||
*flags = env->dslot |
|
||||
(env->pregs[PR_CCS] & (S_FLAG | P_FLAG | U_FLAG
|
||||
| X_FLAG | PFIX_FLAG));
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* CRISv10 insn decoding macros.
|
||||
*
|
||||
* Copyright (c) 2010 AXIS Communications AB
|
||||
* Written by Edgar E. Iglesias.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TARGET_CRIS_CRISV10_DECODE_H
|
||||
#define TARGET_CRIS_CRISV10_DECODE_H
|
||||
|
||||
#define CRISV10_MODE_QIMMEDIATE 0
|
||||
#define CRISV10_MODE_REG 1
|
||||
#define CRISV10_MODE_INDIRECT 2
|
||||
#define CRISV10_MODE_AUTOINC 3
|
||||
|
||||
/* Quick Immediate. */
|
||||
#define CRISV10_QIMM_BCC_R0 0
|
||||
#define CRISV10_QIMM_BCC_R1 1
|
||||
#define CRISV10_QIMM_BCC_R2 2
|
||||
#define CRISV10_QIMM_BCC_R3 3
|
||||
|
||||
#define CRISV10_QIMM_BDAP_R0 4
|
||||
#define CRISV10_QIMM_BDAP_R1 5
|
||||
#define CRISV10_QIMM_BDAP_R2 6
|
||||
#define CRISV10_QIMM_BDAP_R3 7
|
||||
|
||||
#define CRISV10_QIMM_ADDQ 8
|
||||
#define CRISV10_QIMM_MOVEQ 9
|
||||
#define CRISV10_QIMM_SUBQ 10
|
||||
#define CRISV10_QIMM_CMPQ 11
|
||||
#define CRISV10_QIMM_ANDQ 12
|
||||
#define CRISV10_QIMM_ORQ 13
|
||||
#define CRISV10_QIMM_ASHQ 14
|
||||
#define CRISV10_QIMM_LSHQ 15
|
||||
|
||||
|
||||
#define CRISV10_REG_ADDX 0
|
||||
#define CRISV10_REG_MOVX 1
|
||||
#define CRISV10_REG_SUBX 2
|
||||
#define CRISV10_REG_LSL 3
|
||||
#define CRISV10_REG_ADDI 4
|
||||
#define CRISV10_REG_BIAP 5
|
||||
#define CRISV10_REG_NEG 6
|
||||
#define CRISV10_REG_BOUND 7
|
||||
#define CRISV10_REG_ADD 8
|
||||
#define CRISV10_REG_MOVE_R 9
|
||||
#define CRISV10_REG_MOVE_SPR_R 9
|
||||
#define CRISV10_REG_MOVE_R_SPR 8
|
||||
#define CRISV10_REG_SUB 10
|
||||
#define CRISV10_REG_CMP 11
|
||||
#define CRISV10_REG_AND 12
|
||||
#define CRISV10_REG_OR 13
|
||||
#define CRISV10_REG_ASR 14
|
||||
#define CRISV10_REG_LSR 15
|
||||
|
||||
#define CRISV10_REG_BTST 3
|
||||
#define CRISV10_REG_SCC 4
|
||||
#define CRISV10_REG_SETF 6
|
||||
#define CRISV10_REG_CLEARF 7
|
||||
#define CRISV10_REG_BIAP 5
|
||||
#define CRISV10_REG_ABS 10
|
||||
#define CRISV10_REG_DSTEP 11
|
||||
#define CRISV10_REG_LZ 12
|
||||
#define CRISV10_REG_NOT 13
|
||||
#define CRISV10_REG_SWAP 13
|
||||
#define CRISV10_REG_XOR 14
|
||||
#define CRISV10_REG_MSTEP 15
|
||||
|
||||
/* Indirect, var size. */
|
||||
#define CRISV10_IND_TEST 14
|
||||
#define CRISV10_IND_MUL 4
|
||||
#define CRISV10_IND_BDAP_M 5
|
||||
#define CRISV10_IND_ADD 8
|
||||
#define CRISV10_IND_MOVE_M_R 9
|
||||
|
||||
|
||||
/* indirect fixed size. */
|
||||
#define CRISV10_IND_ADDX 0
|
||||
#define CRISV10_IND_MOVX 1
|
||||
#define CRISV10_IND_SUBX 2
|
||||
#define CRISV10_IND_CMPX 3
|
||||
#define CRISV10_IND_JUMP_M 4
|
||||
#define CRISV10_IND_DIP 5
|
||||
#define CRISV10_IND_JUMP_R 6
|
||||
#define CRISV17_IND_ADDC 6
|
||||
#define CRISV10_IND_BOUND 7
|
||||
#define CRISV10_IND_BCC_M 7
|
||||
#define CRISV10_IND_MOVE_M_SPR 8
|
||||
#define CRISV10_IND_MOVE_SPR_M 9
|
||||
#define CRISV10_IND_SUB 10
|
||||
#define CRISV10_IND_CMP 11
|
||||
#define CRISV10_IND_AND 12
|
||||
#define CRISV10_IND_OR 13
|
||||
#define CRISV10_IND_MOVE_R_M 15
|
||||
|
||||
#define CRISV10_IND_MOVEM_M_R 14
|
||||
#define CRISV10_IND_MOVEM_R_M 15
|
||||
|
||||
#endif
|
|
@ -1,133 +0,0 @@
|
|||
/*
|
||||
* CRIS insn decoding macros.
|
||||
*
|
||||
* Copyright (c) 2007 AXIS Communications AB
|
||||
* Written by Edgar E. Iglesias.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CRISV32_DECODE_H
|
||||
#define CRISV32_DECODE_H
|
||||
|
||||
/* Convenient binary macros. */
|
||||
#define HEX__(n) 0x##n##LU
|
||||
#define B8__(x) ((x&0x0000000FLU)?1:0) \
|
||||
+ ((x&0x000000F0LU)?2:0) \
|
||||
+ ((x&0x00000F00LU)?4:0) \
|
||||
+ ((x&0x0000F000LU)?8:0) \
|
||||
+ ((x&0x000F0000LU)?16:0) \
|
||||
+ ((x&0x00F00000LU)?32:0) \
|
||||
+ ((x&0x0F000000LU)?64:0) \
|
||||
+ ((x&0xF0000000LU)?128:0)
|
||||
#define B8(d) ((unsigned char)B8__(HEX__(d)))
|
||||
|
||||
/* Quick imm. */
|
||||
#define DEC_BCCQ {B8(00000000), B8(11110000)}
|
||||
#define DEC_ADDOQ {B8(00010000), B8(11110000)}
|
||||
#define DEC_ADDQ {B8(00100000), B8(11111100)}
|
||||
#define DEC_MOVEQ {B8(00100100), B8(11111100)}
|
||||
#define DEC_SUBQ {B8(00101000), B8(11111100)}
|
||||
#define DEC_CMPQ {B8(00101100), B8(11111100)}
|
||||
#define DEC_ANDQ {B8(00110000), B8(11111100)}
|
||||
#define DEC_ORQ {B8(00110100), B8(11111100)}
|
||||
#define DEC_BTSTQ {B8(00111000), B8(11111110)}
|
||||
#define DEC_ASRQ {B8(00111010), B8(11111110)}
|
||||
#define DEC_LSLQ {B8(00111100), B8(11111110)}
|
||||
#define DEC_LSRQ {B8(00111110), B8(11111110)}
|
||||
|
||||
/* Register. */
|
||||
#define DEC_MOVU_R {B8(01000100), B8(11111110)}
|
||||
#define DEC_MOVU_R {B8(01000100), B8(11111110)}
|
||||
#define DEC_MOVS_R {B8(01000110), B8(11111110)}
|
||||
#define DEC_MOVE_R {B8(01100100), B8(11111100)}
|
||||
#define DEC_MOVE_RP {B8(01100011), B8(11111111)}
|
||||
#define DEC_MOVE_PR {B8(01100111), B8(11111111)}
|
||||
#define DEC_DSTEP_R {B8(01101111), B8(11111111)}
|
||||
#define DEC_MOVE_RS {B8(10110111), B8(11111111)}
|
||||
#define DEC_MOVE_SR {B8(11110111), B8(11111111)}
|
||||
#define DEC_ADDU_R {B8(01000000), B8(11111110)}
|
||||
#define DEC_ADDS_R {B8(01000010), B8(11111110)}
|
||||
#define DEC_ADD_R {B8(01100000), B8(11111100)}
|
||||
#define DEC_ADDI_R {B8(01010000), B8(11111100)}
|
||||
#define DEC_MULS_R {B8(11010000), B8(11111100)}
|
||||
#define DEC_MULU_R {B8(10010000), B8(11111100)}
|
||||
#define DEC_ADDI_ACR {B8(01010100), B8(11111100)}
|
||||
#define DEC_NEG_R {B8(01011000), B8(11111100)}
|
||||
#define DEC_BOUND_R {B8(01011100), B8(11111100)}
|
||||
#define DEC_SUBU_R {B8(01001000), B8(11111110)}
|
||||
#define DEC_SUBS_R {B8(01001010), B8(11111110)}
|
||||
#define DEC_SUB_R {B8(01101000), B8(11111100)}
|
||||
#define DEC_CMP_R {B8(01101100), B8(11111100)}
|
||||
#define DEC_AND_R {B8(01110000), B8(11111100)}
|
||||
#define DEC_ABS_R {B8(01101011), B8(11111111)}
|
||||
#define DEC_LZ_R {B8(01110011), B8(11111111)}
|
||||
#define DEC_MCP_R {B8(01111111), B8(11111111)}
|
||||
#define DEC_SWAP_R {B8(01110111), B8(11111111)}
|
||||
#define DEC_XOR_R {B8(01111011), B8(11111111)}
|
||||
#define DEC_LSL_R {B8(01001100), B8(11111100)}
|
||||
#define DEC_LSR_R {B8(01111100), B8(11111100)}
|
||||
#define DEC_ASR_R {B8(01111000), B8(11111100)}
|
||||
#define DEC_OR_R {B8(01110100), B8(11111100)}
|
||||
#define DEC_BTST_R {B8(01001111), B8(11111111)}
|
||||
|
||||
/* Fixed. */
|
||||
#define DEC_SETF {B8(01011011), B8(11111111)}
|
||||
#define DEC_CLEARF {B8(01011111), B8(11111111)}
|
||||
|
||||
/* Memory. */
|
||||
#define DEC_ADDU_M {B8(10000000), B8(10111110)}
|
||||
#define DEC_ADDS_M {B8(10000010), B8(10111110)}
|
||||
#define DEC_MOVU_M {B8(10000100), B8(10111110)}
|
||||
#define DEC_MOVS_M {B8(10000110), B8(10111110)}
|
||||
#define DEC_SUBU_M {B8(10001000), B8(10111110)}
|
||||
#define DEC_SUBS_M {B8(10001010), B8(10111110)}
|
||||
#define DEC_CMPU_M {B8(10001100), B8(10111110)}
|
||||
#define DEC_CMPS_M {B8(10001110), B8(10111110)}
|
||||
#define DEC_ADDO_M {B8(10010100), B8(10111100)}
|
||||
#define DEC_BOUND_M {B8(10011100), B8(10111100)}
|
||||
#define DEC_ADD_M {B8(10100000), B8(10111100)}
|
||||
#define DEC_MOVE_MR {B8(10100100), B8(10111100)}
|
||||
#define DEC_SUB_M {B8(10101000), B8(10111100)}
|
||||
#define DEC_CMP_M {B8(10101100), B8(10111100)}
|
||||
#define DEC_AND_M {B8(10110000), B8(10111100)}
|
||||
#define DEC_OR_M {B8(10110100), B8(10111100)}
|
||||
#define DEC_TEST_M {B8(10111000), B8(10111100)}
|
||||
#define DEC_MOVE_RM {B8(10111100), B8(10111100)}
|
||||
|
||||
#define DEC_ADDC_R {B8(01010111), B8(11111111)}
|
||||
#define DEC_ADDC_MR {B8(10011010), B8(10111111)}
|
||||
#define DEC_LAPCQ {B8(10010111), B8(11111111)}
|
||||
#define DEC_LAPC_IM {B8(11010111), B8(11111111)}
|
||||
|
||||
#define DEC_MOVE_MP {B8(10100011), B8(10111111)}
|
||||
#define DEC_MOVE_PM {B8(10100111), B8(10111111)}
|
||||
|
||||
#define DEC_SCC_R {B8(01010011), B8(11111111)}
|
||||
#define DEC_RFE_ETC {B8(10010011), B8(11111111)}
|
||||
#define DEC_JUMP_P {B8(10011111), B8(11111111)}
|
||||
#define DEC_BCC_IM {B8(11011111), B8(11111111)}
|
||||
#define DEC_JAS_R {B8(10011011), B8(11111111)}
|
||||
#define DEC_JASC_R {B8(10110011), B8(11111111)}
|
||||
#define DEC_JAS_IM {B8(11011011), B8(11111111)}
|
||||
#define DEC_JASC_IM {B8(11110011), B8(11111111)}
|
||||
#define DEC_BAS_IM {B8(11101011), B8(11111111)}
|
||||
#define DEC_BASC_IM {B8(11101111), B8(11111111)}
|
||||
#define DEC_MOVEM_MR {B8(10111011), B8(10111111)}
|
||||
#define DEC_MOVEM_RM {B8(10111111), B8(10111111)}
|
||||
|
||||
#define DEC_FTAG_FIDX_D_M {B8(10101011), B8(11111111)}
|
||||
#define DEC_FTAG_FIDX_I_M {B8(11010011), B8(11111111)}
|
||||
|
||||
#endif
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
* CRIS gdb server stub
|
||||
*
|
||||
* Copyright (c) 2003-2005 Fabrice Bellard
|
||||
* Copyright (c) 2013 SUSE LINUX Products GmbH
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "gdbstub/helpers.h"
|
||||
|
||||
int crisv10_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||
{
|
||||
CPUCRISState *env = cpu_env(cs);
|
||||
|
||||
if (n < 15) {
|
||||
return gdb_get_reg32(mem_buf, env->regs[n]);
|
||||
}
|
||||
|
||||
if (n == 15) {
|
||||
return gdb_get_reg32(mem_buf, env->pc);
|
||||
}
|
||||
|
||||
if (n < 32) {
|
||||
switch (n) {
|
||||
case 16:
|
||||
return gdb_get_reg8(mem_buf, env->pregs[n - 16]);
|
||||
case 17:
|
||||
return gdb_get_reg8(mem_buf, env->pregs[n - 16]);
|
||||
case 20:
|
||||
case 21:
|
||||
return gdb_get_reg16(mem_buf, env->pregs[n - 16]);
|
||||
default:
|
||||
if (n >= 23) {
|
||||
return gdb_get_reg32(mem_buf, env->pregs[n - 16]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cris_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||
{
|
||||
CPUCRISState *env = cpu_env(cs);
|
||||
uint8_t srs;
|
||||
|
||||
srs = env->pregs[PR_SRS];
|
||||
if (n < 16) {
|
||||
return gdb_get_reg32(mem_buf, env->regs[n]);
|
||||
}
|
||||
|
||||
if (n >= 21 && n < 32) {
|
||||
return gdb_get_reg32(mem_buf, env->pregs[n - 16]);
|
||||
}
|
||||
if (n >= 33 && n < 49) {
|
||||
return gdb_get_reg32(mem_buf, env->sregs[srs][n - 33]);
|
||||
}
|
||||
switch (n) {
|
||||
case 16:
|
||||
return gdb_get_reg8(mem_buf, env->pregs[0]);
|
||||
case 17:
|
||||
return gdb_get_reg8(mem_buf, env->pregs[1]);
|
||||
case 18:
|
||||
return gdb_get_reg32(mem_buf, env->pregs[2]);
|
||||
case 19:
|
||||
return gdb_get_reg8(mem_buf, srs);
|
||||
case 20:
|
||||
return gdb_get_reg16(mem_buf, env->pregs[4]);
|
||||
case 32:
|
||||
return gdb_get_reg32(mem_buf, env->pc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cris_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
{
|
||||
CPUCRISState *env = cpu_env(cs);
|
||||
uint32_t tmp;
|
||||
|
||||
if (n > 49) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmp = ldl_p(mem_buf);
|
||||
|
||||
if (n < 16) {
|
||||
env->regs[n] = tmp;
|
||||
}
|
||||
|
||||
if (n >= 21 && n < 32) {
|
||||
env->pregs[n - 16] = tmp;
|
||||
}
|
||||
|
||||
/* FIXME: Should support function regs be writable? */
|
||||
switch (n) {
|
||||
case 16:
|
||||
return 1;
|
||||
case 17:
|
||||
return 1;
|
||||
case 18:
|
||||
env->pregs[PR_PID] = tmp;
|
||||
break;
|
||||
case 19:
|
||||
return 1;
|
||||
case 20:
|
||||
return 2;
|
||||
case 32:
|
||||
env->pc = tmp;
|
||||
break;
|
||||
}
|
||||
|
||||
return 4;
|
||||
}
|
|
@ -1,287 +0,0 @@
|
|||
/*
|
||||
* CRIS helper routines.
|
||||
*
|
||||
* Copyright (c) 2007 AXIS Communications AB
|
||||
* Written by Edgar E. Iglesias.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "cpu.h"
|
||||
#include "hw/core/tcg-cpu-ops.h"
|
||||
#include "mmu.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
|
||||
//#define CRIS_HELPER_DEBUG
|
||||
|
||||
|
||||
#ifdef CRIS_HELPER_DEBUG
|
||||
#define D(x) x
|
||||
#define D_LOG(...) qemu_log(__VA_ARGS__)
|
||||
#else
|
||||
#define D(x)
|
||||
#define D_LOG(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
static void cris_shift_ccs(CPUCRISState *env)
|
||||
{
|
||||
uint32_t ccs;
|
||||
/* Apply the ccs shift. */
|
||||
ccs = env->pregs[PR_CCS];
|
||||
ccs = ((ccs & 0xc0000000) | ((ccs << 12) >> 2)) & ~0x3ff;
|
||||
env->pregs[PR_CCS] = ccs;
|
||||
}
|
||||
|
||||
bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool probe, uintptr_t retaddr)
|
||||
{
|
||||
CPUCRISState *env = cpu_env(cs);
|
||||
struct cris_mmu_result res;
|
||||
int prot, miss;
|
||||
target_ulong phy;
|
||||
|
||||
miss = cris_mmu_translate(&res, env, address & TARGET_PAGE_MASK,
|
||||
access_type, mmu_idx, 0);
|
||||
if (likely(!miss)) {
|
||||
/*
|
||||
* Mask off the cache selection bit. The ETRAX busses do not
|
||||
* see the top bit.
|
||||
*/
|
||||
phy = res.phy & ~0x80000000;
|
||||
prot = res.prot;
|
||||
tlb_set_page(cs, address & TARGET_PAGE_MASK, phy,
|
||||
prot, mmu_idx, TARGET_PAGE_SIZE);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (probe) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cs->exception_index == EXCP_BUSFAULT) {
|
||||
cpu_abort(cs, "CRIS: Illegal recursive bus fault."
|
||||
"addr=%" VADDR_PRIx " access_type=%d\n",
|
||||
address, access_type);
|
||||
}
|
||||
|
||||
env->pregs[PR_EDA] = address;
|
||||
cs->exception_index = EXCP_BUSFAULT;
|
||||
env->fault_vector = res.bf_vec;
|
||||
if (retaddr) {
|
||||
if (cpu_restore_state(cs, retaddr)) {
|
||||
/* Evaluate flags after retranslation. */
|
||||
helper_top_evaluate_flags(env);
|
||||
}
|
||||
}
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
|
||||
void crisv10_cpu_do_interrupt(CPUState *cs)
|
||||
{
|
||||
CPUCRISState *env = cpu_env(cs);
|
||||
int ex_vec = -1;
|
||||
|
||||
D_LOG("exception index=%d interrupt_req=%d\n",
|
||||
cs->exception_index,
|
||||
cs->interrupt_request);
|
||||
|
||||
if (env->dslot) {
|
||||
/* CRISv10 never takes interrupts while in a delay-slot. */
|
||||
cpu_abort(cs, "CRIS: Interrupt on delay-slot\n");
|
||||
}
|
||||
|
||||
assert(!(env->pregs[PR_CCS] & PFIX_FLAG));
|
||||
switch (cs->exception_index) {
|
||||
case EXCP_BREAK:
|
||||
/* These exceptions are generated by the core itself.
|
||||
ERP should point to the insn following the brk. */
|
||||
ex_vec = env->trap_vector;
|
||||
env->pregs[PRV10_BRP] = env->pc;
|
||||
break;
|
||||
|
||||
case EXCP_NMI:
|
||||
/* NMI is hardwired to vector zero. */
|
||||
ex_vec = 0;
|
||||
env->pregs[PR_CCS] &= ~M_FLAG_V10;
|
||||
env->pregs[PRV10_BRP] = env->pc;
|
||||
break;
|
||||
|
||||
case EXCP_BUSFAULT:
|
||||
cpu_abort(cs, "Unhandled busfault");
|
||||
break;
|
||||
|
||||
default:
|
||||
/* The interrupt controller gives us the vector. */
|
||||
ex_vec = env->interrupt_vector;
|
||||
/* Normal interrupts are taken between
|
||||
TB's. env->pc is valid here. */
|
||||
env->pregs[PR_ERP] = env->pc;
|
||||
break;
|
||||
}
|
||||
|
||||
if (env->pregs[PR_CCS] & U_FLAG) {
|
||||
/* Swap stack pointers. */
|
||||
env->pregs[PR_USP] = env->regs[R_SP];
|
||||
env->regs[R_SP] = env->ksp;
|
||||
}
|
||||
|
||||
/* Now that we are in kernel mode, load the handlers address. */
|
||||
env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
|
||||
env->locked_irq = 1;
|
||||
env->pregs[PR_CCS] |= F_FLAG_V10; /* set F. */
|
||||
|
||||
qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
|
||||
__func__, env->pc, ex_vec,
|
||||
env->pregs[PR_CCS],
|
||||
env->pregs[PR_PID],
|
||||
env->pregs[PR_ERP]);
|
||||
}
|
||||
|
||||
void cris_cpu_do_interrupt(CPUState *cs)
|
||||
{
|
||||
CPUCRISState *env = cpu_env(cs);
|
||||
int ex_vec = -1;
|
||||
|
||||
D_LOG("exception index=%d interrupt_req=%d\n",
|
||||
cs->exception_index,
|
||||
cs->interrupt_request);
|
||||
|
||||
switch (cs->exception_index) {
|
||||
case EXCP_BREAK:
|
||||
/* These exceptions are generated by the core itself.
|
||||
ERP should point to the insn following the brk. */
|
||||
ex_vec = env->trap_vector;
|
||||
env->pregs[PR_ERP] = env->pc;
|
||||
break;
|
||||
|
||||
case EXCP_NMI:
|
||||
/* NMI is hardwired to vector zero. */
|
||||
ex_vec = 0;
|
||||
env->pregs[PR_CCS] &= ~M_FLAG_V32;
|
||||
env->pregs[PR_NRP] = env->pc;
|
||||
break;
|
||||
|
||||
case EXCP_BUSFAULT:
|
||||
ex_vec = env->fault_vector;
|
||||
env->pregs[PR_ERP] = env->pc;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* The interrupt controller gives us the vector. */
|
||||
ex_vec = env->interrupt_vector;
|
||||
/* Normal interrupts are taken between
|
||||
TB's. env->pc is valid here. */
|
||||
env->pregs[PR_ERP] = env->pc;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fill in the IDX field. */
|
||||
env->pregs[PR_EXS] = (ex_vec & 0xff) << 8;
|
||||
|
||||
if (env->dslot) {
|
||||
D_LOG("excp isr=%x PC=%x ds=%d SP=%x"
|
||||
" ERP=%x pid=%x ccs=%x cc=%d %x\n",
|
||||
ex_vec, env->pc, env->dslot,
|
||||
env->regs[R_SP],
|
||||
env->pregs[PR_ERP], env->pregs[PR_PID],
|
||||
env->pregs[PR_CCS],
|
||||
env->cc_op, env->cc_mask);
|
||||
/* We loose the btarget, btaken state here so rexec the
|
||||
branch. */
|
||||
env->pregs[PR_ERP] -= env->dslot;
|
||||
/* Exception starts with dslot cleared. */
|
||||
env->dslot = 0;
|
||||
}
|
||||
|
||||
if (env->pregs[PR_CCS] & U_FLAG) {
|
||||
/* Swap stack pointers. */
|
||||
env->pregs[PR_USP] = env->regs[R_SP];
|
||||
env->regs[R_SP] = env->ksp;
|
||||
}
|
||||
|
||||
/* Apply the CRIS CCS shift. Clears U if set. */
|
||||
cris_shift_ccs(env);
|
||||
|
||||
/* Now that we are in kernel mode, load the handlers address.
|
||||
This load may not fault, real hw leaves that behaviour as
|
||||
undefined. */
|
||||
env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
|
||||
|
||||
/* Clear the excption_index to avoid spurious hw_aborts for recursive
|
||||
bus faults. */
|
||||
cs->exception_index = -1;
|
||||
|
||||
D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
|
||||
__func__, env->pc, ex_vec,
|
||||
env->pregs[PR_CCS],
|
||||
env->pregs[PR_PID],
|
||||
env->pregs[PR_ERP]);
|
||||
}
|
||||
|
||||
hwaddr cris_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
||||
{
|
||||
CRISCPU *cpu = CRIS_CPU(cs);
|
||||
uint32_t phy = addr;
|
||||
struct cris_mmu_result res;
|
||||
int miss;
|
||||
|
||||
miss = cris_mmu_translate(&res, &cpu->env, addr, MMU_DATA_LOAD, 0, 1);
|
||||
/* If D TLB misses, try I TLB. */
|
||||
if (miss) {
|
||||
miss = cris_mmu_translate(&res, &cpu->env, addr, MMU_INST_FETCH, 0, 1);
|
||||
}
|
||||
|
||||
if (!miss) {
|
||||
phy = res.phy;
|
||||
}
|
||||
D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy));
|
||||
return phy;
|
||||
}
|
||||
|
||||
bool cris_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
{
|
||||
CPUClass *cc = CPU_GET_CLASS(cs);
|
||||
CPUCRISState *env = cpu_env(cs);
|
||||
bool ret = false;
|
||||
|
||||
if (interrupt_request & CPU_INTERRUPT_HARD
|
||||
&& (env->pregs[PR_CCS] & I_FLAG)
|
||||
&& !env->locked_irq) {
|
||||
cs->exception_index = EXCP_IRQ;
|
||||
cc->tcg_ops->do_interrupt(cs);
|
||||
ret = true;
|
||||
}
|
||||
if (interrupt_request & CPU_INTERRUPT_NMI) {
|
||||
unsigned int m_flag_archval;
|
||||
if (env->pregs[PR_VR] < 32) {
|
||||
m_flag_archval = M_FLAG_V10;
|
||||
} else {
|
||||
m_flag_archval = M_FLAG_V32;
|
||||
}
|
||||
if ((env->pregs[PR_CCS] & m_flag_archval)) {
|
||||
cs->exception_index = EXCP_NMI;
|
||||
cc->tcg_ops->do_interrupt(cs);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
DEF_HELPER_2(raise_exception, noreturn, env, i32)
|
||||
DEF_HELPER_2(tlb_flush_pid, void, env, i32)
|
||||
DEF_HELPER_2(spc_write, void, env, i32)
|
||||
DEF_HELPER_1(rfe, void, env)
|
||||
DEF_HELPER_1(rfn, void, env)
|
||||
|
||||
DEF_HELPER_3(movl_sreg_reg, void, env, i32, i32)
|
||||
DEF_HELPER_3(movl_reg_sreg, void, env, i32, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(btst, TCG_CALL_NO_SE, i32, env, i32, i32, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(evaluate_flags_muls, TCG_CALL_NO_SE, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_4(evaluate_flags_mulu, TCG_CALL_NO_SE, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_5(evaluate_flags_mcp, TCG_CALL_NO_SE, i32, env,
|
||||
i32, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_5(evaluate_flags_alu_4, TCG_CALL_NO_SE, i32, env,
|
||||
i32, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_5(evaluate_flags_sub_4, TCG_CALL_NO_SE, i32, env,
|
||||
i32, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_3(evaluate_flags_move_4, TCG_CALL_NO_SE, i32, env, i32, i32)
|
||||
DEF_HELPER_FLAGS_3(evaluate_flags_move_2, TCG_CALL_NO_SE, i32, env, i32, i32)
|
||||
DEF_HELPER_1(evaluate_flags, void, env)
|
||||
DEF_HELPER_1(top_evaluate_flags, void, env)
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* CRIS virtual CPU state save/load support
|
||||
*
|
||||
* Copyright (c) 2012 Red Hat, Inc.
|
||||
* Written by Juan Quintela <quintela@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "migration/cpu.h"
|
||||
|
||||
static const VMStateDescription vmstate_tlbset = {
|
||||
.name = "cpu/tlbset",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (const VMStateField[]) {
|
||||
VMSTATE_UINT32(lo, TLBSet),
|
||||
VMSTATE_UINT32(hi, TLBSet),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_cris_env = {
|
||||
.name = "env",
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.fields = (const VMStateField[]) {
|
||||
VMSTATE_UINT32_ARRAY(regs, CPUCRISState, 16),
|
||||
VMSTATE_UINT32_ARRAY(pregs, CPUCRISState, 16),
|
||||
VMSTATE_UINT32(pc, CPUCRISState),
|
||||
VMSTATE_UINT32(ksp, CPUCRISState),
|
||||
VMSTATE_INT32(dslot, CPUCRISState),
|
||||
VMSTATE_INT32(btaken, CPUCRISState),
|
||||
VMSTATE_UINT32(btarget, CPUCRISState),
|
||||
VMSTATE_UINT32(cc_op, CPUCRISState),
|
||||
VMSTATE_UINT32(cc_mask, CPUCRISState),
|
||||
VMSTATE_UINT32(cc_dest, CPUCRISState),
|
||||
VMSTATE_UINT32(cc_src, CPUCRISState),
|
||||
VMSTATE_UINT32(cc_result, CPUCRISState),
|
||||
VMSTATE_INT32(cc_size, CPUCRISState),
|
||||
VMSTATE_INT32(cc_x, CPUCRISState),
|
||||
VMSTATE_INT32(locked_irq, CPUCRISState),
|
||||
VMSTATE_INT32(interrupt_vector, CPUCRISState),
|
||||
VMSTATE_INT32(fault_vector, CPUCRISState),
|
||||
VMSTATE_INT32(trap_vector, CPUCRISState),
|
||||
VMSTATE_UINT32_ARRAY(sregs[0], CPUCRISState, 16),
|
||||
VMSTATE_UINT32_ARRAY(sregs[1], CPUCRISState, 16),
|
||||
VMSTATE_UINT32_ARRAY(sregs[2], CPUCRISState, 16),
|
||||
VMSTATE_UINT32_ARRAY(sregs[3], CPUCRISState, 16),
|
||||
VMSTATE_UINT32(mmu_rand_lfsr, CPUCRISState),
|
||||
VMSTATE_STRUCT_ARRAY(tlbsets[0][0], CPUCRISState, 16, 0,
|
||||
vmstate_tlbset, TLBSet),
|
||||
VMSTATE_STRUCT_ARRAY(tlbsets[0][1], CPUCRISState, 16, 0,
|
||||
vmstate_tlbset, TLBSet),
|
||||
VMSTATE_STRUCT_ARRAY(tlbsets[0][2], CPUCRISState, 16, 0,
|
||||
vmstate_tlbset, TLBSet),
|
||||
VMSTATE_STRUCT_ARRAY(tlbsets[0][3], CPUCRISState, 16, 0,
|
||||
vmstate_tlbset, TLBSet),
|
||||
VMSTATE_STRUCT_ARRAY(tlbsets[1][0], CPUCRISState, 16, 0,
|
||||
vmstate_tlbset, TLBSet),
|
||||
VMSTATE_STRUCT_ARRAY(tlbsets[1][1], CPUCRISState, 16, 0,
|
||||
vmstate_tlbset, TLBSet),
|
||||
VMSTATE_STRUCT_ARRAY(tlbsets[1][2], CPUCRISState, 16, 0,
|
||||
vmstate_tlbset, TLBSet),
|
||||
VMSTATE_STRUCT_ARRAY(tlbsets[1][3], CPUCRISState, 16, 0,
|
||||
vmstate_tlbset, TLBSet),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
const VMStateDescription vmstate_cris_cpu = {
|
||||
.name = "cpu",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (const VMStateField[]) {
|
||||
VMSTATE_CPU(),
|
||||
VMSTATE_STRUCT(env, CRISCPU, 1, vmstate_cris_env, CPUCRISState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue