2016-01-30 01:50:38 +03:00
|
|
|
/*
|
|
|
|
* Raspberry Pi emulation (c) 2012 Gregory Estrade
|
2020-03-23 20:22:30 +03:00
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
|
|
* See the COPYING file in the top-level directory.
|
2016-01-30 01:50:38 +03:00
|
|
|
*/
|
|
|
|
|
2016-02-08 22:01:23 +03:00
|
|
|
#include "qemu/osdep.h"
|
include/qemu/osdep.h: Don't include qapi/error.h
Commit 57cb38b included qapi/error.h into qemu/osdep.h to get the
Error typedef. Since then, we've moved to include qemu/osdep.h
everywhere. Its file comment explains: "To avoid getting into
possible circular include dependencies, this file should not include
any other QEMU headers, with the exceptions of config-host.h,
compiler.h, os-posix.h and os-win32.h, all of which are doing a
similar job to this file and are under similar constraints."
qapi/error.h doesn't do a similar job, and it doesn't adhere to
similar constraints: it includes qapi-types.h. That's in excess of
100KiB of crap most .c files don't actually need.
Add the typedef to qemu/typedefs.h, and include that instead of
qapi/error.h. Include qapi/error.h in .c files that need it and don't
get it now. Include qapi-types.h in qom/object.h for uint16List.
Update scripts/clean-includes accordingly. Update it further to match
reality: replace config.h by config-target.h, add sysemu/os-posix.h,
sysemu/os-win32.h. Update the list of includes in the qemu/osdep.h
comment quoted above similarly.
This reduces the number of objects depending on qapi/error.h from "all
of them" to less than a third. Unfortunately, the number depending on
qapi-types.h shrinks only a little. More work is needed for that one.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
[Fix compilation without the spice devel packages. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2016-03-14 11:01:28 +03:00
|
|
|
#include "qapi/error.h"
|
2016-01-30 01:50:38 +03:00
|
|
|
#include "hw/misc/bcm2835_property.h"
|
2019-08-12 08:23:51 +03:00
|
|
|
#include "hw/qdev-properties.h"
|
2019-08-12 08:23:45 +03:00
|
|
|
#include "migration/vmstate.h"
|
2019-08-12 08:23:42 +03:00
|
|
|
#include "hw/irq.h"
|
2016-01-30 01:50:38 +03:00
|
|
|
#include "hw/misc/bcm2835_mbox_defs.h"
|
2023-10-12 10:34:58 +03:00
|
|
|
#include "hw/arm/raspberrypi-fw-defs.h"
|
2016-01-30 01:50:38 +03:00
|
|
|
#include "sysemu/dma.h"
|
2015-12-15 15:16:16 +03:00
|
|
|
#include "qemu/log.h"
|
2019-05-23 17:35:07 +03:00
|
|
|
#include "qemu/module.h"
|
2019-09-26 20:34:15 +03:00
|
|
|
#include "trace.h"
|
2023-06-13 01:34:55 +03:00
|
|
|
#include "hw/arm/raspi_platform.h"
|
2016-01-30 01:50:38 +03:00
|
|
|
|
2024-02-26 03:02:57 +03:00
|
|
|
#define VCHI_BUSADDR_SIZE sizeof(uint32_t)
|
|
|
|
|
2016-01-30 01:50:38 +03:00
|
|
|
/* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */
|
|
|
|
|
|
|
|
static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
|
|
|
|
{
|
|
|
|
uint32_t tag;
|
|
|
|
uint32_t bufsize;
|
|
|
|
uint32_t tot_len;
|
|
|
|
size_t resplen;
|
|
|
|
uint32_t tmp;
|
2016-03-16 20:06:01 +03:00
|
|
|
int n;
|
|
|
|
uint32_t offset, length, color;
|
2018-08-24 15:17:48 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy the current state of the framebuffer config; we will update
|
|
|
|
* this copy as we process tags and then ask the framebuffer to use
|
|
|
|
* it at the end.
|
|
|
|
*/
|
|
|
|
BCM2835FBConfig fbconfig = s->fbdev->config;
|
|
|
|
bool fbconfig_updated = false;
|
2016-01-30 01:50:38 +03:00
|
|
|
|
|
|
|
value &= ~0xf;
|
|
|
|
|
|
|
|
s->addr = value;
|
|
|
|
|
2016-03-04 14:30:18 +03:00
|
|
|
tot_len = ldl_le_phys(&s->dma_as, value);
|
2016-01-30 01:50:38 +03:00
|
|
|
|
|
|
|
/* @(addr + 4) : Buffer response code */
|
|
|
|
value = s->addr + 8;
|
|
|
|
while (value + 8 <= s->addr + tot_len) {
|
2016-03-04 14:30:18 +03:00
|
|
|
tag = ldl_le_phys(&s->dma_as, value);
|
|
|
|
bufsize = ldl_le_phys(&s->dma_as, value + 4);
|
2016-01-30 01:50:38 +03:00
|
|
|
/* @(value + 8) : Request/response indicator */
|
|
|
|
resplen = 0;
|
|
|
|
switch (tag) {
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_PROPERTY_END:
|
2016-01-30 01:50:38 +03:00
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_GET_FIRMWARE_REVISION:
|
2016-03-04 14:30:18 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 12, 346337);
|
2016-01-30 01:50:38 +03:00
|
|
|
resplen = 4;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_GET_BOARD_MODEL:
|
2016-01-30 01:50:38 +03:00
|
|
|
qemu_log_mask(LOG_UNIMP,
|
2019-09-26 20:34:10 +03:00
|
|
|
"bcm2835_property: 0x%08x get board model NYI\n",
|
|
|
|
tag);
|
2016-01-30 01:50:38 +03:00
|
|
|
resplen = 4;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_GET_BOARD_REVISION:
|
2016-03-04 14:30:18 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 12, s->board_rev);
|
2016-01-30 01:50:38 +03:00
|
|
|
resplen = 4;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_GET_BOARD_MAC_ADDRESS:
|
2016-01-30 01:50:38 +03:00
|
|
|
resplen = sizeof(s->macaddr.a);
|
dma: Let dma_memory_read/write() take MemTxAttrs argument
Let devices specify transaction attributes when calling
dma_memory_read() or dma_memory_write().
Patch created mechanically using spatch with this script:
@@
expression E1, E2, E3, E4;
@@
(
- dma_memory_read(E1, E2, E3, E4)
+ dma_memory_read(E1, E2, E3, E4, MEMTXATTRS_UNSPECIFIED)
|
- dma_memory_write(E1, E2, E3, E4)
+ dma_memory_write(E1, E2, E3, E4, MEMTXATTRS_UNSPECIFIED)
)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Li Qiang <liq3ea@gmail.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <20211223115554.3155328-6-philmd@redhat.com>
2020-09-03 11:08:29 +03:00
|
|
|
dma_memory_write(&s->dma_as, value + 12, s->macaddr.a, resplen,
|
|
|
|
MEMTXATTRS_UNSPECIFIED);
|
2016-01-30 01:50:38 +03:00
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_GET_BOARD_SERIAL:
|
2016-01-30 01:50:38 +03:00
|
|
|
qemu_log_mask(LOG_UNIMP,
|
2019-09-26 20:34:10 +03:00
|
|
|
"bcm2835_property: 0x%08x get board serial NYI\n",
|
|
|
|
tag);
|
2016-01-30 01:50:38 +03:00
|
|
|
resplen = 8;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_GET_ARM_MEMORY:
|
2016-01-30 01:50:38 +03:00
|
|
|
/* base */
|
2016-03-04 14:30:18 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 12, 0);
|
2016-01-30 01:50:38 +03:00
|
|
|
/* size */
|
2016-03-16 20:06:01 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_base);
|
|
|
|
resplen = 8;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_GET_VC_MEMORY:
|
2016-03-16 20:06:01 +03:00
|
|
|
/* base */
|
|
|
|
stl_le_phys(&s->dma_as, value + 12, s->fbdev->vcram_base);
|
|
|
|
/* size */
|
|
|
|
stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_size);
|
2016-01-30 01:50:38 +03:00
|
|
|
resplen = 8;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_SET_POWER_STATE:
|
2016-01-30 01:50:38 +03:00
|
|
|
/* Assume that whatever device they asked for exists,
|
|
|
|
* and we'll just claim we set it to the desired state
|
|
|
|
*/
|
2016-03-04 14:30:18 +03:00
|
|
|
tmp = ldl_le_phys(&s->dma_as, value + 16);
|
|
|
|
stl_le_phys(&s->dma_as, value + 16, (tmp & 1));
|
2016-01-30 01:50:38 +03:00
|
|
|
resplen = 8;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Clocks */
|
|
|
|
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_GET_CLOCK_STATE:
|
2016-03-04 14:30:18 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 16, 0x1);
|
2016-01-30 01:50:38 +03:00
|
|
|
resplen = 8;
|
|
|
|
break;
|
|
|
|
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_SET_CLOCK_STATE:
|
2016-01-30 01:50:38 +03:00
|
|
|
qemu_log_mask(LOG_UNIMP,
|
2019-09-26 20:34:10 +03:00
|
|
|
"bcm2835_property: 0x%08x set clock state NYI\n",
|
|
|
|
tag);
|
2016-01-30 01:50:38 +03:00
|
|
|
resplen = 8;
|
|
|
|
break;
|
|
|
|
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_GET_CLOCK_RATE:
|
|
|
|
case RPI_FWREQ_GET_MAX_CLOCK_RATE:
|
|
|
|
case RPI_FWREQ_GET_MIN_CLOCK_RATE:
|
2016-03-04 14:30:18 +03:00
|
|
|
switch (ldl_le_phys(&s->dma_as, value + 12)) {
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FIRMWARE_EMMC_CLK_ID:
|
2023-06-13 01:34:55 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_EMMC_CLK_RATE);
|
2016-01-30 01:50:38 +03:00
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FIRMWARE_UART_CLK_ID:
|
2023-06-13 01:34:55 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_UART_CLK_RATE);
|
2016-01-30 01:50:38 +03:00
|
|
|
break;
|
2023-06-13 01:34:56 +03:00
|
|
|
case RPI_FIRMWARE_CORE_CLK_ID:
|
|
|
|
stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_CORE_CLK_RATE);
|
|
|
|
break;
|
2016-01-30 01:50:38 +03:00
|
|
|
default:
|
2023-06-13 01:34:55 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 16,
|
|
|
|
RPI_FIRMWARE_DEFAULT_CLK_RATE);
|
2016-01-30 01:50:38 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
resplen = 8;
|
|
|
|
break;
|
|
|
|
|
2024-02-26 03:02:57 +03:00
|
|
|
case RPI_FWREQ_GET_CLOCKS:
|
|
|
|
/* TODO: add more clock IDs if needed */
|
|
|
|
stl_le_phys(&s->dma_as, value + 12, 0);
|
|
|
|
stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_ARM_CLK_ID);
|
|
|
|
resplen = 8;
|
|
|
|
break;
|
|
|
|
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_SET_CLOCK_RATE:
|
|
|
|
case RPI_FWREQ_SET_MAX_CLOCK_RATE:
|
|
|
|
case RPI_FWREQ_SET_MIN_CLOCK_RATE:
|
2016-01-30 01:50:38 +03:00
|
|
|
qemu_log_mask(LOG_UNIMP,
|
2019-09-26 20:34:10 +03:00
|
|
|
"bcm2835_property: 0x%08x set clock rate NYI\n",
|
|
|
|
tag);
|
2016-01-30 01:50:38 +03:00
|
|
|
resplen = 8;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Temperature */
|
|
|
|
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_GET_TEMPERATURE:
|
2016-03-04 14:30:18 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 16, 25000);
|
2016-01-30 01:50:38 +03:00
|
|
|
resplen = 8;
|
|
|
|
break;
|
|
|
|
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_GET_MAX_TEMPERATURE:
|
2016-03-04 14:30:18 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 16, 99000);
|
2016-01-30 01:50:38 +03:00
|
|
|
resplen = 8;
|
|
|
|
break;
|
|
|
|
|
2016-03-16 20:06:01 +03:00
|
|
|
/* Frame buffer */
|
|
|
|
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_ALLOCATE:
|
2018-08-24 15:17:48 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 12, fbconfig.base);
|
2016-05-12 15:22:25 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 16,
|
2018-08-24 15:17:49 +03:00
|
|
|
bcm2835_fb_get_size(&fbconfig));
|
2016-03-16 20:06:01 +03:00
|
|
|
resplen = 8;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_RELEASE:
|
2016-03-16 20:06:01 +03:00
|
|
|
resplen = 0;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_BLANK:
|
2016-03-16 20:06:01 +03:00
|
|
|
resplen = 4;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT:
|
|
|
|
case RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT:
|
2018-08-24 15:17:49 +03:00
|
|
|
resplen = 8;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT:
|
2018-08-24 15:17:48 +03:00
|
|
|
fbconfig.xres = ldl_le_phys(&s->dma_as, value + 12);
|
|
|
|
fbconfig.yres = ldl_le_phys(&s->dma_as, value + 16);
|
2018-08-24 15:17:50 +03:00
|
|
|
bcm2835_fb_validate_config(&fbconfig);
|
2018-08-24 15:17:48 +03:00
|
|
|
fbconfig_updated = true;
|
2018-08-24 15:17:50 +03:00
|
|
|
/* fall through */
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT:
|
2018-08-24 15:17:50 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 12, fbconfig.xres);
|
|
|
|
stl_le_phys(&s->dma_as, value + 16, fbconfig.yres);
|
2016-03-16 20:06:01 +03:00
|
|
|
resplen = 8;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT:
|
2018-08-24 15:17:49 +03:00
|
|
|
fbconfig.xres_virtual = ldl_le_phys(&s->dma_as, value + 12);
|
|
|
|
fbconfig.yres_virtual = ldl_le_phys(&s->dma_as, value + 16);
|
2018-08-24 15:17:50 +03:00
|
|
|
bcm2835_fb_validate_config(&fbconfig);
|
2018-08-24 15:17:49 +03:00
|
|
|
fbconfig_updated = true;
|
2018-08-24 15:17:50 +03:00
|
|
|
/* fall through */
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT:
|
2018-08-24 15:17:50 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 12, fbconfig.xres_virtual);
|
|
|
|
stl_le_phys(&s->dma_as, value + 16, fbconfig.yres_virtual);
|
2018-08-24 15:17:49 +03:00
|
|
|
resplen = 8;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_TEST_DEPTH:
|
2016-03-16 20:06:01 +03:00
|
|
|
resplen = 4;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_SET_DEPTH:
|
2018-08-24 15:17:48 +03:00
|
|
|
fbconfig.bpp = ldl_le_phys(&s->dma_as, value + 12);
|
2018-08-24 15:17:50 +03:00
|
|
|
bcm2835_fb_validate_config(&fbconfig);
|
2018-08-24 15:17:48 +03:00
|
|
|
fbconfig_updated = true;
|
2018-08-24 15:17:50 +03:00
|
|
|
/* fall through */
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_GET_DEPTH:
|
2018-08-24 15:17:50 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 12, fbconfig.bpp);
|
2016-03-16 20:06:01 +03:00
|
|
|
resplen = 4;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_TEST_PIXEL_ORDER:
|
2016-03-16 20:06:01 +03:00
|
|
|
resplen = 4;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_SET_PIXEL_ORDER:
|
2018-08-24 15:17:48 +03:00
|
|
|
fbconfig.pixo = ldl_le_phys(&s->dma_as, value + 12);
|
2018-08-24 15:17:50 +03:00
|
|
|
bcm2835_fb_validate_config(&fbconfig);
|
2018-08-24 15:17:48 +03:00
|
|
|
fbconfig_updated = true;
|
2018-08-24 15:17:50 +03:00
|
|
|
/* fall through */
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_GET_PIXEL_ORDER:
|
2018-08-24 15:17:50 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 12, fbconfig.pixo);
|
2016-03-16 20:06:01 +03:00
|
|
|
resplen = 4;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_TEST_ALPHA_MODE:
|
2016-03-16 20:06:01 +03:00
|
|
|
resplen = 4;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_SET_ALPHA_MODE:
|
2018-08-24 15:17:48 +03:00
|
|
|
fbconfig.alpha = ldl_le_phys(&s->dma_as, value + 12);
|
2018-08-24 15:17:50 +03:00
|
|
|
bcm2835_fb_validate_config(&fbconfig);
|
2018-08-24 15:17:48 +03:00
|
|
|
fbconfig_updated = true;
|
2018-08-24 15:17:50 +03:00
|
|
|
/* fall through */
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_GET_ALPHA_MODE:
|
2018-08-24 15:17:50 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 12, fbconfig.alpha);
|
2016-03-16 20:06:01 +03:00
|
|
|
resplen = 4;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_GET_PITCH:
|
2018-08-24 15:17:48 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 12,
|
2018-08-24 15:17:49 +03:00
|
|
|
bcm2835_fb_get_pitch(&fbconfig));
|
2016-03-16 20:06:01 +03:00
|
|
|
resplen = 4;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_OFFSET:
|
2016-03-16 20:06:01 +03:00
|
|
|
resplen = 8;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_OFFSET:
|
2018-08-24 15:17:48 +03:00
|
|
|
fbconfig.xoffset = ldl_le_phys(&s->dma_as, value + 12);
|
|
|
|
fbconfig.yoffset = ldl_le_phys(&s->dma_as, value + 16);
|
2018-08-24 15:17:50 +03:00
|
|
|
bcm2835_fb_validate_config(&fbconfig);
|
2018-08-24 15:17:48 +03:00
|
|
|
fbconfig_updated = true;
|
2018-08-24 15:17:50 +03:00
|
|
|
/* fall through */
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_OFFSET:
|
2018-08-24 15:17:50 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 12, fbconfig.xoffset);
|
|
|
|
stl_le_phys(&s->dma_as, value + 16, fbconfig.yoffset);
|
2016-03-16 20:06:01 +03:00
|
|
|
resplen = 8;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_GET_OVERSCAN:
|
|
|
|
case RPI_FWREQ_FRAMEBUFFER_TEST_OVERSCAN:
|
|
|
|
case RPI_FWREQ_FRAMEBUFFER_SET_OVERSCAN:
|
2016-03-16 20:06:01 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 12, 0);
|
|
|
|
stl_le_phys(&s->dma_as, value + 16, 0);
|
|
|
|
stl_le_phys(&s->dma_as, value + 20, 0);
|
|
|
|
stl_le_phys(&s->dma_as, value + 24, 0);
|
|
|
|
resplen = 16;
|
|
|
|
break;
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_SET_PALETTE:
|
2016-03-16 20:06:01 +03:00
|
|
|
offset = ldl_le_phys(&s->dma_as, value + 12);
|
|
|
|
length = ldl_le_phys(&s->dma_as, value + 16);
|
|
|
|
n = 0;
|
|
|
|
while (n < length - offset) {
|
|
|
|
color = ldl_le_phys(&s->dma_as, value + 20 + (n << 2));
|
|
|
|
stl_le_phys(&s->dma_as,
|
|
|
|
s->fbdev->vcram_base + ((offset + n) << 2), color);
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
stl_le_phys(&s->dma_as, value + 12, 0);
|
|
|
|
resplen = 4;
|
|
|
|
break;
|
2024-02-26 03:02:57 +03:00
|
|
|
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS:
|
2022-08-12 17:35:19 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 12, 1);
|
|
|
|
resplen = 4;
|
|
|
|
break;
|
2016-01-30 01:50:38 +03:00
|
|
|
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_GET_DMA_CHANNELS:
|
2016-01-30 01:50:38 +03:00
|
|
|
/* channels 2-5 */
|
2016-03-04 14:30:18 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 12, 0x003C);
|
2016-01-30 01:50:38 +03:00
|
|
|
resplen = 4;
|
|
|
|
break;
|
|
|
|
|
2023-06-13 01:34:54 +03:00
|
|
|
case RPI_FWREQ_GET_COMMAND_LINE:
|
2023-04-25 13:34:31 +03:00
|
|
|
/*
|
|
|
|
* We follow the firmware behaviour: no NUL terminator is
|
|
|
|
* written to the buffer, and if the buffer is too short
|
|
|
|
* we report the required length in the response header
|
|
|
|
* and copy nothing to the buffer.
|
|
|
|
*/
|
|
|
|
resplen = strlen(s->command_line);
|
|
|
|
if (bufsize >= resplen)
|
|
|
|
address_space_write(&s->dma_as, value + 12,
|
|
|
|
MEMTXATTRS_UNSPECIFIED, s->command_line,
|
|
|
|
resplen);
|
2016-01-30 01:50:38 +03:00
|
|
|
break;
|
|
|
|
|
2024-02-26 03:02:57 +03:00
|
|
|
case RPI_FWREQ_GET_THROTTLED:
|
|
|
|
stl_le_phys(&s->dma_as, value + 12, 0);
|
|
|
|
resplen = 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RPI_FWREQ_VCHIQ_INIT:
|
|
|
|
stl_le_phys(&s->dma_as,
|
|
|
|
value + offsetof(rpi_firmware_prop_request_t, payload),
|
|
|
|
0);
|
|
|
|
resplen = VCHI_BUSADDR_SIZE;
|
|
|
|
break;
|
2016-01-30 01:50:38 +03:00
|
|
|
default:
|
2019-09-26 20:34:10 +03:00
|
|
|
qemu_log_mask(LOG_UNIMP,
|
|
|
|
"bcm2835_property: unhandled tag 0x%08x\n", tag);
|
2016-01-30 01:50:38 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-09-26 20:34:15 +03:00
|
|
|
trace_bcm2835_mbox_property(tag, bufsize, resplen);
|
2016-01-30 01:50:38 +03:00
|
|
|
if (tag == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-03-04 14:30:18 +03:00
|
|
|
stl_le_phys(&s->dma_as, value + 8, (1 << 31) | resplen);
|
2016-01-30 01:50:38 +03:00
|
|
|
value += bufsize + 12;
|
|
|
|
}
|
|
|
|
|
2016-03-16 20:06:01 +03:00
|
|
|
/* Reconfigure framebuffer if required */
|
2018-08-24 15:17:48 +03:00
|
|
|
if (fbconfig_updated) {
|
|
|
|
bcm2835_fb_reconfigure(s->fbdev, &fbconfig);
|
2016-03-16 20:06:01 +03:00
|
|
|
}
|
|
|
|
|
2016-01-30 01:50:38 +03:00
|
|
|
/* Buffer response code */
|
2016-03-04 14:30:18 +03:00
|
|
|
stl_le_phys(&s->dma_as, s->addr + 4, (1 << 31));
|
2016-01-30 01:50:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static uint64_t bcm2835_property_read(void *opaque, hwaddr offset,
|
|
|
|
unsigned size)
|
|
|
|
{
|
|
|
|
BCM2835PropertyState *s = opaque;
|
|
|
|
uint32_t res = 0;
|
|
|
|
|
|
|
|
switch (offset) {
|
|
|
|
case MBOX_AS_DATA:
|
|
|
|
res = MBOX_CHAN_PROPERTY | s->addr;
|
|
|
|
s->pending = false;
|
|
|
|
qemu_set_irq(s->mbox_irq, 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MBOX_AS_PENDING:
|
|
|
|
res = s->pending;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
|
|
|
|
__func__, offset);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void bcm2835_property_write(void *opaque, hwaddr offset,
|
|
|
|
uint64_t value, unsigned size)
|
|
|
|
{
|
|
|
|
BCM2835PropertyState *s = opaque;
|
|
|
|
|
|
|
|
switch (offset) {
|
|
|
|
case MBOX_AS_DATA:
|
|
|
|
/* bcm2835_mbox should check our pending status before pushing */
|
|
|
|
assert(!s->pending);
|
|
|
|
s->pending = true;
|
|
|
|
bcm2835_property_mbox_push(s, value);
|
|
|
|
qemu_set_irq(s->mbox_irq, 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
|
|
|
|
__func__, offset);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const MemoryRegionOps bcm2835_property_ops = {
|
|
|
|
.read = bcm2835_property_read,
|
|
|
|
.write = bcm2835_property_write,
|
|
|
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
|
|
|
.valid.min_access_size = 4,
|
|
|
|
.valid.max_access_size = 4,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const VMStateDescription vmstate_bcm2835_property = {
|
|
|
|
.name = TYPE_BCM2835_PROPERTY,
|
|
|
|
.version_id = 1,
|
|
|
|
.minimum_version_id = 1,
|
2023-12-21 06:16:21 +03:00
|
|
|
.fields = (const VMStateField[]) {
|
2016-01-30 01:50:38 +03:00
|
|
|
VMSTATE_MACADDR(macaddr, BCM2835PropertyState),
|
|
|
|
VMSTATE_UINT32(addr, BCM2835PropertyState),
|
|
|
|
VMSTATE_BOOL(pending, BCM2835PropertyState),
|
|
|
|
VMSTATE_END_OF_LIST()
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static void bcm2835_property_init(Object *obj)
|
|
|
|
{
|
|
|
|
BCM2835PropertyState *s = BCM2835_PROPERTY(obj);
|
|
|
|
|
|
|
|
memory_region_init_io(&s->iomem, OBJECT(s), &bcm2835_property_ops, s,
|
|
|
|
TYPE_BCM2835_PROPERTY, 0x10);
|
2023-04-28 00:10:11 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* bcm2835_property_ops call into bcm2835_mbox, which in-turn reads from
|
|
|
|
* iomem. As such, mark iomem as re-entracy safe.
|
|
|
|
*/
|
|
|
|
s->iomem.disable_reentrancy_guard = true;
|
|
|
|
|
2016-01-30 01:50:38 +03:00
|
|
|
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
|
|
|
|
sysbus_init_irq(SYS_BUS_DEVICE(s), &s->mbox_irq);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void bcm2835_property_reset(DeviceState *dev)
|
|
|
|
{
|
|
|
|
BCM2835PropertyState *s = BCM2835_PROPERTY(dev);
|
|
|
|
|
|
|
|
s->pending = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void bcm2835_property_realize(DeviceState *dev, Error **errp)
|
|
|
|
{
|
|
|
|
BCM2835PropertyState *s = BCM2835_PROPERTY(dev);
|
|
|
|
Object *obj;
|
2016-03-16 20:06:01 +03:00
|
|
|
|
2020-07-07 19:05:52 +03:00
|
|
|
obj = object_property_get_link(OBJECT(dev), "fb", &error_abort);
|
2016-03-16 20:06:01 +03:00
|
|
|
s->fbdev = BCM2835_FB(obj);
|
|
|
|
|
2020-07-07 19:05:52 +03:00
|
|
|
obj = object_property_get_link(OBJECT(dev), "dma-mr", &error_abort);
|
2016-01-30 01:50:38 +03:00
|
|
|
s->dma_mr = MEMORY_REGION(obj);
|
hw/arm/bcm2835_peripherals: Name various address spaces
Various address spaces from the BCM2835 are reported as
'anonymous' in memory tree:
(qemu) info mtree
address-space: anonymous
0000000000000000-000000000000008f (prio 0, i/o): bcm2835-mbox
0000000000000010-000000000000001f (prio 0, i/o): bcm2835-fb
0000000000000080-000000000000008f (prio 0, i/o): bcm2835-property
address-space: anonymous
0000000000000000-00000000ffffffff (prio 0, i/o): bcm2835-gpu
0000000000000000-000000003fffffff (prio 0, i/o): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff
0000000040000000-000000007fffffff (prio 0, i/o): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff
000000007e000000-000000007effffff (prio 1, i/o): alias bcm2835-peripherals @bcm2835-peripherals 0000000000000000-0000000000ffffff
0000000080000000-00000000bfffffff (prio 0, i/o): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff
00000000c0000000-00000000ffffffff (prio 0, i/o): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff
[...]
Since the address_space_init() function takes a 'name' argument,
set it to correctly describe each address space:
(qemu) info mtree
address-space: bcm2835-mbox-memory
0000000000000000-000000000000008f (prio 0, i/o): bcm2835-mbox
0000000000000010-000000000000001f (prio 0, i/o): bcm2835-fb
0000000000000080-000000000000008f (prio 0, i/o): bcm2835-property
address-space: bcm2835-fb-memory
0000000000000000-00000000ffffffff (prio 0, i/o): bcm2835-gpu
0000000000000000-000000003fffffff (prio 0, i/o): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff
0000000040000000-000000007fffffff (prio 0, i/o): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff
000000007e000000-000000007effffff (prio 1, i/o): alias bcm2835-peripherals @bcm2835-peripherals 0000000000000000-0000000000ffffff
0000000080000000-00000000bfffffff (prio 0, i/o): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff
00000000c0000000-00000000ffffffff (prio 0, i/o): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff
address-space: bcm2835-property-memory
0000000000000000-00000000ffffffff (prio 0, i/o): bcm2835-gpu
0000000000000000-000000003fffffff (prio 0, i/o): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff
0000000040000000-000000007fffffff (prio 0, i/o): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff
000000007e000000-000000007effffff (prio 1, i/o): alias bcm2835-peripherals @bcm2835-peripherals 0000000000000000-0000000000ffffff
0000000080000000-00000000bfffffff (prio 0, i/o): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff
00000000c0000000-00000000ffffffff (prio 0, i/o): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff
address-space: bcm2835-dma-memory
0000000000000000-00000000ffffffff (prio 0, i/o): bcm2835-gpu
0000000000000000-000000003fffffff (prio 0, i/o): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff
0000000040000000-000000007fffffff (prio 0, i/o): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff
000000007e000000-000000007effffff (prio 1, i/o): alias bcm2835-peripherals @bcm2835-peripherals 0000000000000000-0000000000ffffff
0000000080000000-00000000bfffffff (prio 0, i/o): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff
00000000c0000000-00000000ffffffff (prio 0, i/o): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Cleber Rosa <crosa@redhat.com>
Message-id: 20190926173428.10713-4-f4bug@amsat.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2019-09-26 20:34:11 +03:00
|
|
|
address_space_init(&s->dma_as, s->dma_mr, TYPE_BCM2835_PROPERTY "-memory");
|
2016-01-30 01:50:38 +03:00
|
|
|
|
|
|
|
/* TODO: connect to MAC address of USB NIC device, once we emulate it */
|
|
|
|
qemu_macaddr_default_if_unset(&s->macaddr);
|
|
|
|
|
|
|
|
bcm2835_property_reset(dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Property bcm2835_property_props[] = {
|
2016-02-11 14:17:32 +03:00
|
|
|
DEFINE_PROP_UINT32("board-rev", BCM2835PropertyState, board_rev, 0),
|
2023-04-25 13:34:31 +03:00
|
|
|
DEFINE_PROP_STRING("command-line", BCM2835PropertyState, command_line),
|
2016-01-30 01:50:38 +03:00
|
|
|
DEFINE_PROP_END_OF_LIST()
|
|
|
|
};
|
|
|
|
|
|
|
|
static void bcm2835_property_class_init(ObjectClass *klass, void *data)
|
|
|
|
{
|
|
|
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
|
|
|
|
2020-01-10 18:30:32 +03:00
|
|
|
device_class_set_props(dc, bcm2835_property_props);
|
2016-01-30 01:50:38 +03:00
|
|
|
dc->realize = bcm2835_property_realize;
|
|
|
|
dc->vmsd = &vmstate_bcm2835_property;
|
|
|
|
}
|
|
|
|
|
2022-01-17 17:58:04 +03:00
|
|
|
static const TypeInfo bcm2835_property_info = {
|
2016-01-30 01:50:38 +03:00
|
|
|
.name = TYPE_BCM2835_PROPERTY,
|
|
|
|
.parent = TYPE_SYS_BUS_DEVICE,
|
|
|
|
.instance_size = sizeof(BCM2835PropertyState),
|
|
|
|
.class_init = bcm2835_property_class_init,
|
|
|
|
.instance_init = bcm2835_property_init,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void bcm2835_property_register_types(void)
|
|
|
|
{
|
|
|
|
type_register_static(&bcm2835_property_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
type_init(bcm2835_property_register_types)
|