target-arm queue:
* add Cortex-A7 CPU
  * new ast2500 SoC model and evaluation board
  * palmetto-bmc: remove stray double assignment
  * aspeed: clean up RAM size handling
  * ptimer: framework for defining policy bits to change
    behaviour choices for different timer devices
  * ptimer: add some test cases
  * cadence_gem: add queue support
  * loader: support loading images to specified address spaces
  * loader: support auto-detect of ELF architecture from file
  * dma: xlnx-zynq-devcfg: Fix up XLNX_ZYNQ_DEVCFG_R_MAX
  * vmstateify ssd0323
  * vmstateify ssi-sd
  * disas/arm.c: remove unused macros
  * imx: use 'const char', not 'char const'
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCAAGBQJX5BLWAAoJEDwlJe0UNgzedDEP/0eyPOuB4VLDdPGxnd/JbExh
 WZfXZ43CzgYQqiSlRtS+rmDSsVHXV7xlPuV5VV4FkuPPdk/+ek3pw11Ou5Tv+98T
 BP4ucRmL5D58koMqrwJb9GAf3a606D1Gk1NaOcl4XthdiuMRi8ARj98GwltHZmkg
 vjYY6ouYhGYeoJwblQ9N9466VcenrhXgL0fOSPWT48ymO9tqNHFvek267QTL3EyN
 6WkrS7nak7tN2V8UyXk7oGtei54BaWjW65bMcJO6UaVbXck3u3HRdjMZhyXbXyKE
 6H6bIav3Y4k+qmyFXkiA9PgsA9ZdAVge0LRwLIFDmGD6ELOwzTe+/C5sxAuZVjuO
 vcQv7wLPy/1gSR9yNy95mTiMJ79DvdQbnciOfSmVbm8bAglBCiiVOiCswEPjWIcp
 1XrQlK7j0ZKfR7+U2Ggu6f89ruiQmIgiJmGvxeb51EbVoNLQjR8VsN+podCTX7B+
 BmGx8dZYZ3DacqcaTmixdY5cnyu7AP5GXEGmOzgYvpe/vvgkpbs7xphBynFq+4j4
 1CUlDlvCBZqRmy4G1zeQCl8dOLpYOMPMrYYg/2GHcYsEn+GfKTjBrTyEpcpSo889
 XKCNdgLBd+bzVIpXn5GFuoHyG/M0p/OQKWx8hhxNazfAUfYpLkrGgCh++7p7UjRP
 yIcvj0asSHYM+HL9uIX0
 =qIm/
 -----END PGP SIGNATURE-----
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20160922' into staging
target-arm queue:
 * add Cortex-A7 CPU
 * new ast2500 SoC model and evaluation board
 * palmetto-bmc: remove stray double assignment
 * aspeed: clean up RAM size handling
 * ptimer: framework for defining policy bits to change
   behaviour choices for different timer devices
 * ptimer: add some test cases
 * cadence_gem: add queue support
 * loader: support loading images to specified address spaces
 * loader: support auto-detect of ELF architecture from file
 * dma: xlnx-zynq-devcfg: Fix up XLNX_ZYNQ_DEVCFG_R_MAX
 * vmstateify ssd0323
 * vmstateify ssi-sd
 * disas/arm.c: remove unused macros
 * imx: use 'const char', not 'char const'
# gpg: Signature made Thu 22 Sep 2016 18:20:22 BST
# gpg:                using RSA key 0x3C2525ED14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>"
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE
* remotes/pmaydell/tags/pull-target-arm-20160922: (36 commits)
  imx: Use 'const char', not 'char const'
  disas/arm.c: Remove unused macro definitions
  vmstateify ssi-sd
  vmstateify ssd0323 display
  dma: xlnx-zynq-devcfg: Fix up XLNX_ZYNQ_DEVCFG_R_MAX
  loader: Add AddressSpace loading support to targphys
  loader: Add AddressSpace loading support to uImages
  loader: Add AddressSpace loading support to ELFs
  loader: Allow a custom AddressSpace when loading ROMs
  loader: Use the specified MemoryRegion
  loader: Allow ELF loader to auto-detect the ELF arch
  xlnx-zynqmp: Set the number of priority queues
  cadence_gem: Correct indentation
  cadence_gem: Add queue support
  cadence_gem: Add support for screening
  cadence_gem: Add the num-priority-queues property
  cadence_gem: QOMify Cadence GEM
  tests: Add ptimer tests
  hw/ptimer: Suppress error messages under qtest
  hw/ptimer: Introduce timer policy feature
  ...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
			
			
This commit is contained in:
		
						commit
						e678c56f16
					
				
							
								
								
									
										11
									
								
								disas/arm.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								disas/arm.c
									
									
									
									
									
								
							@ -24,7 +24,6 @@
 | 
			
		||||
 | 
			
		||||
#include "qemu/osdep.h"
 | 
			
		||||
#include "disas/bfd.h"
 | 
			
		||||
#define ISSPACE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n')
 | 
			
		||||
 | 
			
		||||
#define ARM_EXT_V1	 0
 | 
			
		||||
#define ARM_EXT_V2	 0
 | 
			
		||||
@ -73,15 +72,6 @@ static void floatformat_to_double (unsigned char *data, double *dest)
 | 
			
		||||
 | 
			
		||||
/* End of qemu specific additions.  */
 | 
			
		||||
 | 
			
		||||
/* FIXME: Belongs in global header.  */
 | 
			
		||||
#ifndef strneq
 | 
			
		||||
#define strneq(a,b,n)	(strncmp ((a), (b), (n)) == 0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef NUM_ELEM
 | 
			
		||||
#define NUM_ELEM(a)     (sizeof (a) / sizeof (a)[0])
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct opcode32
 | 
			
		||||
{
 | 
			
		||||
  unsigned long arch;		/* Architecture defining this insn.  */
 | 
			
		||||
@ -1528,7 +1518,6 @@ static const char *const iwmmxt_cregnames[] =
 | 
			
		||||
/* Default to GCC register name set.  */
 | 
			
		||||
static unsigned int regname_selected = 1;
 | 
			
		||||
 | 
			
		||||
#define NUM_ARM_REGNAMES  NUM_ELEM (regnames)
 | 
			
		||||
#define arm_regnames      regnames[regname_selected].reg_names
 | 
			
		||||
 | 
			
		||||
static bfd_boolean force_thumb = false;
 | 
			
		||||
 | 
			
		||||
@ -17,4 +17,4 @@ obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o
 | 
			
		||||
obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
 | 
			
		||||
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
 | 
			
		||||
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
 | 
			
		||||
obj-$(CONFIG_ASPEED_SOC) += ast2400.o palmetto-bmc.o
 | 
			
		||||
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										197
									
								
								hw/arm/aspeed.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								hw/arm/aspeed.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,197 @@
 | 
			
		||||
/*
 | 
			
		||||
 * OpenPOWER Palmetto BMC
 | 
			
		||||
 *
 | 
			
		||||
 * Andrew Jeffery <andrew@aj.id.au>
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2016 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * This code is licensed under the GPL version 2 or later.  See
 | 
			
		||||
 * the COPYING file in the top-level directory.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "qemu/osdep.h"
 | 
			
		||||
#include "qapi/error.h"
 | 
			
		||||
#include "qemu-common.h"
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
#include "exec/address-spaces.h"
 | 
			
		||||
#include "hw/arm/arm.h"
 | 
			
		||||
#include "hw/arm/aspeed_soc.h"
 | 
			
		||||
#include "hw/boards.h"
 | 
			
		||||
#include "qemu/log.h"
 | 
			
		||||
#include "sysemu/block-backend.h"
 | 
			
		||||
#include "sysemu/blockdev.h"
 | 
			
		||||
 | 
			
		||||
static struct arm_boot_info aspeed_board_binfo = {
 | 
			
		||||
    .board_id = -1, /* device-tree-only board */
 | 
			
		||||
    .nb_cpus = 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct AspeedBoardState {
 | 
			
		||||
    AspeedSoCState soc;
 | 
			
		||||
    MemoryRegion ram;
 | 
			
		||||
} AspeedBoardState;
 | 
			
		||||
 | 
			
		||||
typedef struct AspeedBoardConfig {
 | 
			
		||||
    const char *soc_name;
 | 
			
		||||
    uint32_t hw_strap1;
 | 
			
		||||
} AspeedBoardConfig;
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    PALMETTO_BMC,
 | 
			
		||||
    AST2500_EVB,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define PALMETTO_BMC_HW_STRAP1 (                                        \
 | 
			
		||||
        SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_256MB) |               \
 | 
			
		||||
        SCU_AST2400_HW_STRAP_DRAM_CONFIG(2 /* DDR3 with CL=6, CWL=5 */) | \
 | 
			
		||||
        SCU_AST2400_HW_STRAP_ACPI_DIS |                                 \
 | 
			
		||||
        SCU_AST2400_HW_STRAP_SET_CLK_SOURCE(AST2400_CLK_48M_IN) |       \
 | 
			
		||||
        SCU_HW_STRAP_VGA_CLASS_CODE |                                   \
 | 
			
		||||
        SCU_HW_STRAP_LPC_RESET_PIN |                                    \
 | 
			
		||||
        SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_M_S_EN) |                \
 | 
			
		||||
        SCU_AST2400_HW_STRAP_SET_CPU_AHB_RATIO(AST2400_CPU_AHB_RATIO_2_1) | \
 | 
			
		||||
        SCU_HW_STRAP_SPI_WIDTH |                                        \
 | 
			
		||||
        SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) |                       \
 | 
			
		||||
        SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT))
 | 
			
		||||
 | 
			
		||||
#define AST2500_EVB_HW_STRAP1 ((                                        \
 | 
			
		||||
        AST2500_HW_STRAP1_DEFAULTS |                                    \
 | 
			
		||||
        SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE |                     \
 | 
			
		||||
        SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE |                        \
 | 
			
		||||
        SCU_AST2500_HW_STRAP_UART_DEBUG |                               \
 | 
			
		||||
        SCU_AST2500_HW_STRAP_DDR4_ENABLE |                              \
 | 
			
		||||
        SCU_HW_STRAP_MAC1_RGMII |                                       \
 | 
			
		||||
        SCU_HW_STRAP_MAC0_RGMII) &                                      \
 | 
			
		||||
        ~SCU_HW_STRAP_2ND_BOOT_WDT)
 | 
			
		||||
 | 
			
		||||
static const AspeedBoardConfig aspeed_boards[] = {
 | 
			
		||||
    [PALMETTO_BMC] = { "ast2400-a0", PALMETTO_BMC_HW_STRAP1 },
 | 
			
		||||
    [AST2500_EVB]  = { "ast2500-a1", AST2500_EVB_HW_STRAP1 },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
 | 
			
		||||
                                      Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    int i ;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < s->num_cs; ++i) {
 | 
			
		||||
        AspeedSMCFlash *fl = &s->flashes[i];
 | 
			
		||||
        DriveInfo *dinfo = drive_get_next(IF_MTD);
 | 
			
		||||
        qemu_irq cs_line;
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * FIXME: check that we are not using a flash module exceeding
 | 
			
		||||
         * the controller segment size
 | 
			
		||||
         */
 | 
			
		||||
        fl->flash = ssi_create_slave_no_init(s->spi, flashtype);
 | 
			
		||||
        if (dinfo) {
 | 
			
		||||
            qdev_prop_set_drive(fl->flash, "drive", blk_by_legacy_dinfo(dinfo),
 | 
			
		||||
                                errp);
 | 
			
		||||
        }
 | 
			
		||||
        qdev_init_nofail(fl->flash);
 | 
			
		||||
 | 
			
		||||
        cs_line = qdev_get_gpio_in_named(fl->flash, SSI_GPIO_CS, 0);
 | 
			
		||||
        sysbus_connect_irq(SYS_BUS_DEVICE(s), i + 1, cs_line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void aspeed_board_init(MachineState *machine,
 | 
			
		||||
                              const AspeedBoardConfig *cfg)
 | 
			
		||||
{
 | 
			
		||||
    AspeedBoardState *bmc;
 | 
			
		||||
    AspeedSoCClass *sc;
 | 
			
		||||
 | 
			
		||||
    bmc = g_new0(AspeedBoardState, 1);
 | 
			
		||||
    object_initialize(&bmc->soc, (sizeof(bmc->soc)), cfg->soc_name);
 | 
			
		||||
    object_property_add_child(OBJECT(machine), "soc", OBJECT(&bmc->soc),
 | 
			
		||||
                              &error_abort);
 | 
			
		||||
 | 
			
		||||
    sc = ASPEED_SOC_GET_CLASS(&bmc->soc);
 | 
			
		||||
 | 
			
		||||
    object_property_set_int(OBJECT(&bmc->soc), ram_size, "ram-size",
 | 
			
		||||
                           &error_abort);
 | 
			
		||||
    object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1",
 | 
			
		||||
                            &error_abort);
 | 
			
		||||
    object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
 | 
			
		||||
                             &error_abort);
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Allocate RAM after the memory controller has checked the size
 | 
			
		||||
     * was valid. If not, a default value is used.
 | 
			
		||||
     */
 | 
			
		||||
    ram_size = object_property_get_int(OBJECT(&bmc->soc), "ram-size",
 | 
			
		||||
                                       &error_abort);
 | 
			
		||||
 | 
			
		||||
    memory_region_allocate_system_memory(&bmc->ram, NULL, "ram", ram_size);
 | 
			
		||||
    memory_region_add_subregion(get_system_memory(), sc->info->sdram_base,
 | 
			
		||||
                                &bmc->ram);
 | 
			
		||||
    object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
 | 
			
		||||
                                   &error_abort);
 | 
			
		||||
 | 
			
		||||
    aspeed_board_init_flashes(&bmc->soc.smc, "n25q256a", &error_abort);
 | 
			
		||||
    aspeed_board_init_flashes(&bmc->soc.spi, "mx25l25635e", &error_abort);
 | 
			
		||||
 | 
			
		||||
    aspeed_board_binfo.kernel_filename = machine->kernel_filename;
 | 
			
		||||
    aspeed_board_binfo.initrd_filename = machine->initrd_filename;
 | 
			
		||||
    aspeed_board_binfo.kernel_cmdline = machine->kernel_cmdline;
 | 
			
		||||
    aspeed_board_binfo.ram_size = ram_size;
 | 
			
		||||
    aspeed_board_binfo.loader_start = sc->info->sdram_base;
 | 
			
		||||
 | 
			
		||||
    arm_load_kernel(ARM_CPU(first_cpu), &aspeed_board_binfo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void palmetto_bmc_init(MachineState *machine)
 | 
			
		||||
{
 | 
			
		||||
    aspeed_board_init(machine, &aspeed_boards[PALMETTO_BMC]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void palmetto_bmc_class_init(ObjectClass *oc, void *data)
 | 
			
		||||
{
 | 
			
		||||
    MachineClass *mc = MACHINE_CLASS(oc);
 | 
			
		||||
 | 
			
		||||
    mc->desc = "OpenPOWER Palmetto BMC (ARM926EJ-S)";
 | 
			
		||||
    mc->init = palmetto_bmc_init;
 | 
			
		||||
    mc->max_cpus = 1;
 | 
			
		||||
    mc->no_sdcard = 1;
 | 
			
		||||
    mc->no_floppy = 1;
 | 
			
		||||
    mc->no_cdrom = 1;
 | 
			
		||||
    mc->no_parallel = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo palmetto_bmc_type = {
 | 
			
		||||
    .name = MACHINE_TYPE_NAME("palmetto-bmc"),
 | 
			
		||||
    .parent = TYPE_MACHINE,
 | 
			
		||||
    .class_init = palmetto_bmc_class_init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void ast2500_evb_init(MachineState *machine)
 | 
			
		||||
{
 | 
			
		||||
    aspeed_board_init(machine, &aspeed_boards[AST2500_EVB]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ast2500_evb_class_init(ObjectClass *oc, void *data)
 | 
			
		||||
{
 | 
			
		||||
    MachineClass *mc = MACHINE_CLASS(oc);
 | 
			
		||||
 | 
			
		||||
    mc->desc = "Aspeed AST2500 EVB (ARM1176)";
 | 
			
		||||
    mc->init = ast2500_evb_init;
 | 
			
		||||
    mc->max_cpus = 1;
 | 
			
		||||
    mc->no_sdcard = 1;
 | 
			
		||||
    mc->no_floppy = 1;
 | 
			
		||||
    mc->no_cdrom = 1;
 | 
			
		||||
    mc->no_parallel = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo ast2500_evb_type = {
 | 
			
		||||
    .name = MACHINE_TYPE_NAME("ast2500-evb"),
 | 
			
		||||
    .parent = TYPE_MACHINE,
 | 
			
		||||
    .class_init = ast2500_evb_class_init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void aspeed_machine_init(void)
 | 
			
		||||
{
 | 
			
		||||
    type_register_static(&palmetto_bmc_type);
 | 
			
		||||
    type_register_static(&ast2500_evb_type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type_init(aspeed_machine_init)
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * AST2400 SoC
 | 
			
		||||
 * ASPEED SoC family
 | 
			
		||||
 *
 | 
			
		||||
 * Andrew Jeffery <andrew@aj.id.au>
 | 
			
		||||
 * Jeremy Kerr <jk@ozlabs.org>
 | 
			
		||||
@ -15,59 +15,68 @@
 | 
			
		||||
#include "qemu-common.h"
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
#include "exec/address-spaces.h"
 | 
			
		||||
#include "hw/arm/ast2400.h"
 | 
			
		||||
#include "hw/arm/aspeed_soc.h"
 | 
			
		||||
#include "hw/char/serial.h"
 | 
			
		||||
#include "qemu/log.h"
 | 
			
		||||
#include "hw/i2c/aspeed_i2c.h"
 | 
			
		||||
 | 
			
		||||
#define AST2400_UART_5_BASE      0x00184000
 | 
			
		||||
#define AST2400_IOMEM_SIZE       0x00200000
 | 
			
		||||
#define AST2400_IOMEM_BASE       0x1E600000
 | 
			
		||||
#define AST2400_SMC_BASE         AST2400_IOMEM_BASE /* Legacy SMC */
 | 
			
		||||
#define AST2400_FMC_BASE         0X1E620000
 | 
			
		||||
#define AST2400_SPI_BASE         0X1E630000
 | 
			
		||||
#define AST2400_VIC_BASE         0x1E6C0000
 | 
			
		||||
#define AST2400_SDMC_BASE        0x1E6E0000
 | 
			
		||||
#define AST2400_SCU_BASE         0x1E6E2000
 | 
			
		||||
#define AST2400_TIMER_BASE       0x1E782000
 | 
			
		||||
#define AST2400_I2C_BASE         0x1E78A000
 | 
			
		||||
#define ASPEED_SOC_UART_5_BASE      0x00184000
 | 
			
		||||
#define ASPEED_SOC_IOMEM_SIZE       0x00200000
 | 
			
		||||
#define ASPEED_SOC_IOMEM_BASE       0x1E600000
 | 
			
		||||
#define ASPEED_SOC_FMC_BASE         0x1E620000
 | 
			
		||||
#define ASPEED_SOC_SPI_BASE         0x1E630000
 | 
			
		||||
#define ASPEED_SOC_VIC_BASE         0x1E6C0000
 | 
			
		||||
#define ASPEED_SOC_SDMC_BASE        0x1E6E0000
 | 
			
		||||
#define ASPEED_SOC_SCU_BASE         0x1E6E2000
 | 
			
		||||
#define ASPEED_SOC_TIMER_BASE       0x1E782000
 | 
			
		||||
#define ASPEED_SOC_I2C_BASE         0x1E78A000
 | 
			
		||||
 | 
			
		||||
#define AST2400_FMC_FLASH_BASE   0x20000000
 | 
			
		||||
#define AST2400_SPI_FLASH_BASE   0x30000000
 | 
			
		||||
#define ASPEED_SOC_FMC_FLASH_BASE   0x20000000
 | 
			
		||||
#define ASPEED_SOC_SPI_FLASH_BASE   0x30000000
 | 
			
		||||
 | 
			
		||||
static const int uart_irqs[] = { 9, 32, 33, 34, 10 };
 | 
			
		||||
static const int timer_irqs[] = { 16, 17, 18, 35, 36, 37, 38, 39, };
 | 
			
		||||
 | 
			
		||||
#define AST2400_SDRAM_BASE       0x40000000
 | 
			
		||||
#define AST2500_SDRAM_BASE       0x80000000
 | 
			
		||||
 | 
			
		||||
static const AspeedSoCInfo aspeed_socs[] = {
 | 
			
		||||
    { "ast2400-a0", "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE },
 | 
			
		||||
    { "ast2400",    "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE },
 | 
			
		||||
    { "ast2500-a1", "arm1176", AST2500_A1_SILICON_REV, AST2500_SDRAM_BASE },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * IO handlers: simply catch any reads/writes to IO addresses that aren't
 | 
			
		||||
 * handled by a device mapping.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static uint64_t ast2400_io_read(void *p, hwaddr offset, unsigned size)
 | 
			
		||||
static uint64_t aspeed_soc_io_read(void *p, hwaddr offset, unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n",
 | 
			
		||||
                  __func__, offset, size);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ast2400_io_write(void *opaque, hwaddr offset, uint64_t value,
 | 
			
		||||
static void aspeed_soc_io_write(void *opaque, hwaddr offset, uint64_t value,
 | 
			
		||||
                unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " [%u]\n",
 | 
			
		||||
                  __func__, offset, value, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const MemoryRegionOps ast2400_io_ops = {
 | 
			
		||||
    .read = ast2400_io_read,
 | 
			
		||||
    .write = ast2400_io_write,
 | 
			
		||||
static const MemoryRegionOps aspeed_soc_io_ops = {
 | 
			
		||||
    .read = aspeed_soc_io_read,
 | 
			
		||||
    .write = aspeed_soc_io_write,
 | 
			
		||||
    .endianness = DEVICE_LITTLE_ENDIAN,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void ast2400_init(Object *obj)
 | 
			
		||||
static void aspeed_soc_init(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    AST2400State *s = AST2400(obj);
 | 
			
		||||
    AspeedSoCState *s = ASPEED_SOC(obj);
 | 
			
		||||
    AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 | 
			
		||||
 | 
			
		||||
    s->cpu = cpu_arm_init("arm926");
 | 
			
		||||
    s->cpu = cpu_arm_init(sc->info->cpu_model);
 | 
			
		||||
 | 
			
		||||
    object_initialize(&s->vic, sizeof(s->vic), TYPE_ASPEED_VIC);
 | 
			
		||||
    object_property_add_child(obj, "vic", OBJECT(&s->vic), NULL);
 | 
			
		||||
@ -85,7 +94,7 @@ static void ast2400_init(Object *obj)
 | 
			
		||||
    object_property_add_child(obj, "scu", OBJECT(&s->scu), NULL);
 | 
			
		||||
    qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default());
 | 
			
		||||
    qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
 | 
			
		||||
                         AST2400_A0_SILICON_REV);
 | 
			
		||||
                         sc->info->silicon_rev);
 | 
			
		||||
    object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu),
 | 
			
		||||
                              "hw-strap1", &error_abort);
 | 
			
		||||
    object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
 | 
			
		||||
@ -103,20 +112,22 @@ static void ast2400_init(Object *obj)
 | 
			
		||||
    object_property_add_child(obj, "sdmc", OBJECT(&s->sdmc), NULL);
 | 
			
		||||
    qdev_set_parent_bus(DEVICE(&s->sdmc), sysbus_get_default());
 | 
			
		||||
    qdev_prop_set_uint32(DEVICE(&s->sdmc), "silicon-rev",
 | 
			
		||||
                         AST2400_A0_SILICON_REV);
 | 
			
		||||
                         sc->info->silicon_rev);
 | 
			
		||||
    object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
 | 
			
		||||
                              "ram-size", &error_abort);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ast2400_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
static void aspeed_soc_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    AST2400State *s = AST2400(dev);
 | 
			
		||||
    AspeedSoCState *s = ASPEED_SOC(dev);
 | 
			
		||||
    Error *err = NULL, *local_err = NULL;
 | 
			
		||||
 | 
			
		||||
    /* IO space */
 | 
			
		||||
    memory_region_init_io(&s->iomem, NULL, &ast2400_io_ops, NULL,
 | 
			
		||||
            "ast2400.io", AST2400_IOMEM_SIZE);
 | 
			
		||||
    memory_region_add_subregion_overlap(get_system_memory(), AST2400_IOMEM_BASE,
 | 
			
		||||
            &s->iomem, -1);
 | 
			
		||||
    memory_region_init_io(&s->iomem, NULL, &aspeed_soc_io_ops, NULL,
 | 
			
		||||
            "aspeed_soc.io", ASPEED_SOC_IOMEM_SIZE);
 | 
			
		||||
    memory_region_add_subregion_overlap(get_system_memory(),
 | 
			
		||||
                                        ASPEED_SOC_IOMEM_BASE, &s->iomem, -1);
 | 
			
		||||
 | 
			
		||||
    /* VIC */
 | 
			
		||||
    object_property_set_bool(OBJECT(&s->vic), true, "realized", &err);
 | 
			
		||||
@ -124,7 +135,7 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
        error_propagate(errp, err);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, AST2400_VIC_BASE);
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, ASPEED_SOC_VIC_BASE);
 | 
			
		||||
    sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 0,
 | 
			
		||||
                       qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
 | 
			
		||||
    sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 1,
 | 
			
		||||
@ -136,7 +147,7 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
        error_propagate(errp, err);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->timerctrl), 0, AST2400_TIMER_BASE);
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->timerctrl), 0, ASPEED_SOC_TIMER_BASE);
 | 
			
		||||
    for (i = 0; i < ARRAY_SIZE(timer_irqs); i++) {
 | 
			
		||||
        qemu_irq irq = qdev_get_gpio_in(DEVICE(&s->vic), timer_irqs[i]);
 | 
			
		||||
        sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
 | 
			
		||||
@ -148,12 +159,12 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
        error_propagate(errp, err);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, AST2400_SCU_BASE);
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, ASPEED_SOC_SCU_BASE);
 | 
			
		||||
 | 
			
		||||
    /* UART - attach an 8250 to the IO space as our UART5 */
 | 
			
		||||
    if (serial_hds[0]) {
 | 
			
		||||
        qemu_irq uart5 = qdev_get_gpio_in(DEVICE(&s->vic), uart_irqs[4]);
 | 
			
		||||
        serial_mm_init(&s->iomem, AST2400_UART_5_BASE, 2,
 | 
			
		||||
        serial_mm_init(&s->iomem, ASPEED_SOC_UART_5_BASE, 2,
 | 
			
		||||
                       uart5, 38400, serial_hds[0], DEVICE_LITTLE_ENDIAN);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -163,7 +174,7 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
        error_propagate(errp, err);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, AST2400_I2C_BASE);
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, ASPEED_SOC_I2C_BASE);
 | 
			
		||||
    sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
 | 
			
		||||
                       qdev_get_gpio_in(DEVICE(&s->vic), 12));
 | 
			
		||||
 | 
			
		||||
@ -175,8 +186,8 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
        error_propagate(errp, err);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 0, AST2400_FMC_BASE);
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 1, AST2400_FMC_FLASH_BASE);
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 0, ASPEED_SOC_FMC_BASE);
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 1, ASPEED_SOC_FMC_FLASH_BASE);
 | 
			
		||||
    sysbus_connect_irq(SYS_BUS_DEVICE(&s->smc), 0,
 | 
			
		||||
                       qdev_get_gpio_in(DEVICE(&s->vic), 19));
 | 
			
		||||
 | 
			
		||||
@ -188,8 +199,8 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
        error_propagate(errp, err);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 0, AST2400_SPI_BASE);
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 1, AST2400_SPI_FLASH_BASE);
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 0, ASPEED_SOC_SPI_BASE);
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 1, ASPEED_SOC_SPI_FLASH_BASE);
 | 
			
		||||
 | 
			
		||||
    /* SDMC - SDRAM Memory Controller */
 | 
			
		||||
    object_property_set_bool(OBJECT(&s->sdmc), true, "realized", &err);
 | 
			
		||||
@ -197,14 +208,16 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
        error_propagate(errp, err);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, AST2400_SDMC_BASE);
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, ASPEED_SOC_SDMC_BASE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ast2400_class_init(ObjectClass *oc, void *data)
 | 
			
		||||
static void aspeed_soc_class_init(ObjectClass *oc, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(oc);
 | 
			
		||||
    AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc);
 | 
			
		||||
 | 
			
		||||
    dc->realize = ast2400_realize;
 | 
			
		||||
    sc->info = (AspeedSoCInfo *) data;
 | 
			
		||||
    dc->realize = aspeed_soc_realize;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Reason: creates an ARM CPU, thus use after free(), see
 | 
			
		||||
@ -213,17 +226,29 @@ static void ast2400_class_init(ObjectClass *oc, void *data)
 | 
			
		||||
    dc->cannot_destroy_with_object_finalize_yet = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo ast2400_type_info = {
 | 
			
		||||
    .name = TYPE_AST2400,
 | 
			
		||||
    .parent = TYPE_SYS_BUS_DEVICE,
 | 
			
		||||
    .instance_size = sizeof(AST2400State),
 | 
			
		||||
    .instance_init = ast2400_init,
 | 
			
		||||
    .class_init = ast2400_class_init,
 | 
			
		||||
static const TypeInfo aspeed_soc_type_info = {
 | 
			
		||||
    .name           = TYPE_ASPEED_SOC,
 | 
			
		||||
    .parent         = TYPE_DEVICE,
 | 
			
		||||
    .instance_init  = aspeed_soc_init,
 | 
			
		||||
    .instance_size  = sizeof(AspeedSoCState),
 | 
			
		||||
    .class_size     = sizeof(AspeedSoCClass),
 | 
			
		||||
    .abstract       = true,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void ast2400_register_types(void)
 | 
			
		||||
static void aspeed_soc_register_types(void)
 | 
			
		||||
{
 | 
			
		||||
    type_register_static(&ast2400_type_info);
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    type_register_static(&aspeed_soc_type_info);
 | 
			
		||||
    for (i = 0; i < ARRAY_SIZE(aspeed_socs); ++i) {
 | 
			
		||||
        TypeInfo ti = {
 | 
			
		||||
            .name       = aspeed_socs[i].name,
 | 
			
		||||
            .parent     = TYPE_ASPEED_SOC,
 | 
			
		||||
            .class_init = aspeed_soc_class_init,
 | 
			
		||||
            .class_data = (void *) &aspeed_socs[i],
 | 
			
		||||
        };
 | 
			
		||||
        type_register(&ti);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type_init(ast2400_register_types)
 | 
			
		||||
type_init(aspeed_soc_register_types)
 | 
			
		||||
@ -837,7 +837,7 @@ static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
 | 
			
		||||
    s->freq = freq;
 | 
			
		||||
 | 
			
		||||
    bh = qemu_bh_new(mv88w8618_timer_tick, s);
 | 
			
		||||
    s->ptimer = ptimer_init(bh);
 | 
			
		||||
    s->ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,
 | 
			
		||||
 | 
			
		||||
@ -1,102 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * OpenPOWER Palmetto BMC
 | 
			
		||||
 *
 | 
			
		||||
 * Andrew Jeffery <andrew@aj.id.au>
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2016 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * This code is licensed under the GPL version 2 or later.  See
 | 
			
		||||
 * the COPYING file in the top-level directory.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "qemu/osdep.h"
 | 
			
		||||
#include "qapi/error.h"
 | 
			
		||||
#include "qemu-common.h"
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
#include "exec/address-spaces.h"
 | 
			
		||||
#include "hw/arm/arm.h"
 | 
			
		||||
#include "hw/arm/ast2400.h"
 | 
			
		||||
#include "hw/boards.h"
 | 
			
		||||
#include "qemu/log.h"
 | 
			
		||||
#include "sysemu/block-backend.h"
 | 
			
		||||
#include "sysemu/blockdev.h"
 | 
			
		||||
 | 
			
		||||
static struct arm_boot_info palmetto_bmc_binfo = {
 | 
			
		||||
    .loader_start = AST2400_SDRAM_BASE,
 | 
			
		||||
    .board_id = 0,
 | 
			
		||||
    .nb_cpus = 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct PalmettoBMCState {
 | 
			
		||||
    AST2400State soc;
 | 
			
		||||
    MemoryRegion ram;
 | 
			
		||||
} PalmettoBMCState;
 | 
			
		||||
 | 
			
		||||
static void palmetto_bmc_init_flashes(AspeedSMCState *s, const char *flashtype,
 | 
			
		||||
                                      Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    int i ;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < s->num_cs; ++i) {
 | 
			
		||||
        AspeedSMCFlash *fl = &s->flashes[i];
 | 
			
		||||
        DriveInfo *dinfo = drive_get_next(IF_MTD);
 | 
			
		||||
        qemu_irq cs_line;
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * FIXME: check that we are not using a flash module exceeding
 | 
			
		||||
         * the controller segment size
 | 
			
		||||
         */
 | 
			
		||||
        fl->flash = ssi_create_slave_no_init(s->spi, flashtype);
 | 
			
		||||
        if (dinfo) {
 | 
			
		||||
            qdev_prop_set_drive(fl->flash, "drive", blk_by_legacy_dinfo(dinfo),
 | 
			
		||||
                                errp);
 | 
			
		||||
        }
 | 
			
		||||
        qdev_init_nofail(fl->flash);
 | 
			
		||||
 | 
			
		||||
        cs_line = qdev_get_gpio_in_named(fl->flash, SSI_GPIO_CS, 0);
 | 
			
		||||
        sysbus_connect_irq(SYS_BUS_DEVICE(s), i + 1, cs_line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void palmetto_bmc_init(MachineState *machine)
 | 
			
		||||
{
 | 
			
		||||
    PalmettoBMCState *bmc;
 | 
			
		||||
 | 
			
		||||
    bmc = g_new0(PalmettoBMCState, 1);
 | 
			
		||||
    object_initialize(&bmc->soc, (sizeof(bmc->soc)), TYPE_AST2400);
 | 
			
		||||
    object_property_add_child(OBJECT(machine), "soc", OBJECT(&bmc->soc),
 | 
			
		||||
                              &error_abort);
 | 
			
		||||
 | 
			
		||||
    memory_region_allocate_system_memory(&bmc->ram, NULL, "ram", ram_size);
 | 
			
		||||
    memory_region_add_subregion(get_system_memory(), AST2400_SDRAM_BASE,
 | 
			
		||||
                                &bmc->ram);
 | 
			
		||||
    object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
 | 
			
		||||
                                   &error_abort);
 | 
			
		||||
    object_property_set_int(OBJECT(&bmc->soc), 0x120CE416, "hw-strap1",
 | 
			
		||||
                            &error_abort);
 | 
			
		||||
    object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
 | 
			
		||||
                             &error_abort);
 | 
			
		||||
 | 
			
		||||
    palmetto_bmc_init_flashes(&bmc->soc.smc, "n25q256a", &error_abort);
 | 
			
		||||
    palmetto_bmc_init_flashes(&bmc->soc.spi, "mx25l25635e", &error_abort);
 | 
			
		||||
 | 
			
		||||
    palmetto_bmc_binfo.kernel_filename = machine->kernel_filename;
 | 
			
		||||
    palmetto_bmc_binfo.initrd_filename = machine->initrd_filename;
 | 
			
		||||
    palmetto_bmc_binfo.kernel_cmdline = machine->kernel_cmdline;
 | 
			
		||||
    palmetto_bmc_binfo.ram_size = ram_size;
 | 
			
		||||
    arm_load_kernel(ARM_CPU(first_cpu), &palmetto_bmc_binfo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void palmetto_bmc_machine_init(MachineClass *mc)
 | 
			
		||||
{
 | 
			
		||||
    mc->desc = "OpenPOWER Palmetto BMC";
 | 
			
		||||
    mc->init = palmetto_bmc_init;
 | 
			
		||||
    mc->max_cpus = 1;
 | 
			
		||||
    mc->no_sdcard = 1;
 | 
			
		||||
    mc->no_floppy = 1;
 | 
			
		||||
    mc->no_cdrom = 1;
 | 
			
		||||
    mc->no_sdcard = 1;
 | 
			
		||||
    mc->no_parallel = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFINE_MACHINE("palmetto-bmc", palmetto_bmc_machine_init);
 | 
			
		||||
@ -332,6 +332,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
            qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
 | 
			
		||||
            qdev_set_nic_properties(DEVICE(&s->gem[i]), nd);
 | 
			
		||||
        }
 | 
			
		||||
        object_property_set_int(OBJECT(&s->gem[i]), 2, "num-priority-queues",
 | 
			
		||||
                                  &error_abort);
 | 
			
		||||
        object_property_set_bool(OBJECT(&s->gem[i]), true, "realized", &err);
 | 
			
		||||
        if (err) {
 | 
			
		||||
            error_propagate(errp, err);
 | 
			
		||||
 | 
			
		||||
@ -133,9 +133,15 @@ ssize_t read_targphys(const char *name,
 | 
			
		||||
    return did;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* return the size or -1 if error */
 | 
			
		||||
int load_image_targphys(const char *filename,
 | 
			
		||||
                        hwaddr addr, uint64_t max_sz)
 | 
			
		||||
{
 | 
			
		||||
    return load_image_targphys_as(filename, addr, max_sz, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* return the size or -1 if error */
 | 
			
		||||
int load_image_targphys_as(const char *filename,
 | 
			
		||||
                           hwaddr addr, uint64_t max_sz, AddressSpace *as)
 | 
			
		||||
{
 | 
			
		||||
    int size;
 | 
			
		||||
 | 
			
		||||
@ -144,7 +150,7 @@ int load_image_targphys(const char *filename,
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    if (size > 0) {
 | 
			
		||||
        rom_add_file_fixed(filename, addr, -1);
 | 
			
		||||
        rom_add_file_fixed_as(filename, addr, -1, as);
 | 
			
		||||
    }
 | 
			
		||||
    return size;
 | 
			
		||||
}
 | 
			
		||||
@ -416,6 +422,18 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
 | 
			
		||||
             void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
 | 
			
		||||
             uint64_t *highaddr, int big_endian, int elf_machine,
 | 
			
		||||
             int clear_lsb, int data_swab)
 | 
			
		||||
{
 | 
			
		||||
    return load_elf_as(filename, translate_fn, translate_opaque, pentry,
 | 
			
		||||
                       lowaddr, highaddr, big_endian, elf_machine, clear_lsb,
 | 
			
		||||
                       data_swab, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* return < 0 if error, otherwise the number of bytes loaded in memory */
 | 
			
		||||
int load_elf_as(const char *filename,
 | 
			
		||||
                uint64_t (*translate_fn)(void *, uint64_t),
 | 
			
		||||
                void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
 | 
			
		||||
                uint64_t *highaddr, int big_endian, int elf_machine,
 | 
			
		||||
                int clear_lsb, int data_swab, AddressSpace *as)
 | 
			
		||||
{
 | 
			
		||||
    int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
 | 
			
		||||
    uint8_t e_ident[EI_NIDENT];
 | 
			
		||||
@ -455,11 +473,11 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
 | 
			
		||||
    if (e_ident[EI_CLASS] == ELFCLASS64) {
 | 
			
		||||
        ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab,
 | 
			
		||||
                         pentry, lowaddr, highaddr, elf_machine, clear_lsb,
 | 
			
		||||
                         data_swab);
 | 
			
		||||
                         data_swab, as);
 | 
			
		||||
    } else {
 | 
			
		||||
        ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
 | 
			
		||||
                         pentry, lowaddr, highaddr, elf_machine, clear_lsb,
 | 
			
		||||
                         data_swab);
 | 
			
		||||
                         data_swab, as);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 fail:
 | 
			
		||||
@ -569,7 +587,7 @@ static ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src,
 | 
			
		||||
static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr,
 | 
			
		||||
                            int *is_linux, uint8_t image_type,
 | 
			
		||||
                            uint64_t (*translate_fn)(void *, uint64_t),
 | 
			
		||||
                            void *translate_opaque)
 | 
			
		||||
                            void *translate_opaque, AddressSpace *as)
 | 
			
		||||
{
 | 
			
		||||
    int fd;
 | 
			
		||||
    int size;
 | 
			
		||||
@ -670,7 +688,7 @@ static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr,
 | 
			
		||||
        hdr->ih_size = bytes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rom_add_blob_fixed(filename, data, hdr->ih_size, address);
 | 
			
		||||
    rom_add_blob_fixed_as(filename, data, hdr->ih_size, address, as);
 | 
			
		||||
 | 
			
		||||
    ret = hdr->ih_size;
 | 
			
		||||
 | 
			
		||||
@ -686,14 +704,23 @@ int load_uimage(const char *filename, hwaddr *ep, hwaddr *loadaddr,
 | 
			
		||||
                void *translate_opaque)
 | 
			
		||||
{
 | 
			
		||||
    return load_uboot_image(filename, ep, loadaddr, is_linux, IH_TYPE_KERNEL,
 | 
			
		||||
                            translate_fn, translate_opaque);
 | 
			
		||||
                            translate_fn, translate_opaque, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int load_uimage_as(const char *filename, hwaddr *ep, hwaddr *loadaddr,
 | 
			
		||||
                   int *is_linux,
 | 
			
		||||
                   uint64_t (*translate_fn)(void *, uint64_t),
 | 
			
		||||
                   void *translate_opaque, AddressSpace *as)
 | 
			
		||||
{
 | 
			
		||||
    return load_uboot_image(filename, ep, loadaddr, is_linux, IH_TYPE_KERNEL,
 | 
			
		||||
                            translate_fn, translate_opaque, as);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Load a ramdisk.  */
 | 
			
		||||
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz)
 | 
			
		||||
{
 | 
			
		||||
    return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK,
 | 
			
		||||
                            NULL, NULL);
 | 
			
		||||
                            NULL, NULL, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Load a gzip-compressed kernel to a dynamically allocated buffer. */
 | 
			
		||||
@ -777,6 +804,7 @@ struct Rom {
 | 
			
		||||
 | 
			
		||||
    uint8_t *data;
 | 
			
		||||
    MemoryRegion *mr;
 | 
			
		||||
    AddressSpace *as;
 | 
			
		||||
    int isrom;
 | 
			
		||||
    char *fw_dir;
 | 
			
		||||
    char *fw_file;
 | 
			
		||||
@ -788,6 +816,12 @@ struct Rom {
 | 
			
		||||
static FWCfgState *fw_cfg;
 | 
			
		||||
static QTAILQ_HEAD(, Rom) roms = QTAILQ_HEAD_INITIALIZER(roms);
 | 
			
		||||
 | 
			
		||||
static inline bool rom_order_compare(Rom *rom, Rom *item)
 | 
			
		||||
{
 | 
			
		||||
    return (rom->as > item->as) ||
 | 
			
		||||
           (rom->as == item->as && rom->addr >= item->addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void rom_insert(Rom *rom)
 | 
			
		||||
{
 | 
			
		||||
    Rom *item;
 | 
			
		||||
@ -796,10 +830,16 @@ static void rom_insert(Rom *rom)
 | 
			
		||||
        hw_error ("ROM images must be loaded at startup\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* list is ordered by load address */
 | 
			
		||||
    /* The user didn't specify an address space, this is the default */
 | 
			
		||||
    if (!rom->as) {
 | 
			
		||||
        rom->as = &address_space_memory;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* List is ordered by load address in the same address space */
 | 
			
		||||
    QTAILQ_FOREACH(item, &roms, next) {
 | 
			
		||||
        if (rom->addr >= item->addr)
 | 
			
		||||
        if (rom_order_compare(rom, item)) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        QTAILQ_INSERT_BEFORE(item, rom, next);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
@ -833,16 +873,25 @@ static void *rom_set_mr(Rom *rom, Object *owner, const char *name)
 | 
			
		||||
 | 
			
		||||
int rom_add_file(const char *file, const char *fw_dir,
 | 
			
		||||
                 hwaddr addr, int32_t bootindex,
 | 
			
		||||
                 bool option_rom, MemoryRegion *mr)
 | 
			
		||||
                 bool option_rom, MemoryRegion *mr,
 | 
			
		||||
                 AddressSpace *as)
 | 
			
		||||
{
 | 
			
		||||
    MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
 | 
			
		||||
    Rom *rom;
 | 
			
		||||
    int rc, fd = -1;
 | 
			
		||||
    char devpath[100];
 | 
			
		||||
 | 
			
		||||
    if (as && mr) {
 | 
			
		||||
        fprintf(stderr, "Specifying an Address Space and Memory Region is " \
 | 
			
		||||
                "not valid when loading a rom\n");
 | 
			
		||||
        /* We haven't allocated anything so we don't need any cleanup */
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rom = g_malloc0(sizeof(*rom));
 | 
			
		||||
    rom->name = g_strdup(file);
 | 
			
		||||
    rom->path = qemu_find_file(QEMU_FILE_TYPE_BIOS, rom->name);
 | 
			
		||||
    rom->as = as;
 | 
			
		||||
    if (rom->path == NULL) {
 | 
			
		||||
        rom->path = g_strdup(file);
 | 
			
		||||
    }
 | 
			
		||||
@ -969,7 +1018,7 @@ MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
 | 
			
		||||
 * memory ownership of "data", so we don't have to allocate and copy the buffer.
 | 
			
		||||
 */
 | 
			
		||||
int rom_add_elf_program(const char *name, void *data, size_t datasize,
 | 
			
		||||
                        size_t romsize, hwaddr addr)
 | 
			
		||||
                        size_t romsize, hwaddr addr, AddressSpace *as)
 | 
			
		||||
{
 | 
			
		||||
    Rom *rom;
 | 
			
		||||
 | 
			
		||||
@ -979,18 +1028,19 @@ int rom_add_elf_program(const char *name, void *data, size_t datasize,
 | 
			
		||||
    rom->datasize = datasize;
 | 
			
		||||
    rom->romsize  = romsize;
 | 
			
		||||
    rom->data     = data;
 | 
			
		||||
    rom->as       = as;
 | 
			
		||||
    rom_insert(rom);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int rom_add_vga(const char *file)
 | 
			
		||||
{
 | 
			
		||||
    return rom_add_file(file, "vgaroms", 0, -1, true, NULL);
 | 
			
		||||
    return rom_add_file(file, "vgaroms", 0, -1, true, NULL, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int rom_add_option(const char *file, int32_t bootindex)
 | 
			
		||||
{
 | 
			
		||||
    return rom_add_file(file, "genroms", 0, bootindex, true, NULL);
 | 
			
		||||
    return rom_add_file(file, "genroms", 0, bootindex, true, NULL, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void rom_reset(void *unused)
 | 
			
		||||
@ -1008,8 +1058,8 @@ static void rom_reset(void *unused)
 | 
			
		||||
            void *host = memory_region_get_ram_ptr(rom->mr);
 | 
			
		||||
            memcpy(host, rom->data, rom->datasize);
 | 
			
		||||
        } else {
 | 
			
		||||
            cpu_physical_memory_write_rom(&address_space_memory,
 | 
			
		||||
                                          rom->addr, rom->data, rom->datasize);
 | 
			
		||||
            cpu_physical_memory_write_rom(rom->as, rom->addr, rom->data,
 | 
			
		||||
                                          rom->datasize);
 | 
			
		||||
        }
 | 
			
		||||
        if (rom->isrom) {
 | 
			
		||||
            /* rom needs to be written only once */
 | 
			
		||||
@ -1031,12 +1081,13 @@ int rom_check_and_register_reset(void)
 | 
			
		||||
    hwaddr addr = 0;
 | 
			
		||||
    MemoryRegionSection section;
 | 
			
		||||
    Rom *rom;
 | 
			
		||||
    AddressSpace *as = NULL;
 | 
			
		||||
 | 
			
		||||
    QTAILQ_FOREACH(rom, &roms, next) {
 | 
			
		||||
        if (rom->fw_file) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        if (addr > rom->addr) {
 | 
			
		||||
        if ((addr > rom->addr) && (as == rom->as)) {
 | 
			
		||||
            fprintf(stderr, "rom: requested regions overlap "
 | 
			
		||||
                    "(rom %s. free=0x" TARGET_FMT_plx
 | 
			
		||||
                    ", addr=0x" TARGET_FMT_plx ")\n",
 | 
			
		||||
@ -1045,9 +1096,11 @@ int rom_check_and_register_reset(void)
 | 
			
		||||
        }
 | 
			
		||||
        addr  = rom->addr;
 | 
			
		||||
        addr += rom->romsize;
 | 
			
		||||
        section = memory_region_find(get_system_memory(), rom->addr, 1);
 | 
			
		||||
        section = memory_region_find(rom->mr ? rom->mr : get_system_memory(),
 | 
			
		||||
                                     rom->addr, 1);
 | 
			
		||||
        rom->isrom = int128_nz(section.size) && memory_region_is_rom(section.mr);
 | 
			
		||||
        memory_region_unref(section.mr);
 | 
			
		||||
        as = rom->as;
 | 
			
		||||
    }
 | 
			
		||||
    qemu_register_reset(rom_reset, NULL);
 | 
			
		||||
    roms_loaded = 1;
 | 
			
		||||
 | 
			
		||||
@ -11,6 +11,7 @@
 | 
			
		||||
#include "hw/ptimer.h"
 | 
			
		||||
#include "qemu/host-utils.h"
 | 
			
		||||
#include "sysemu/replay.h"
 | 
			
		||||
#include "sysemu/qtest.h"
 | 
			
		||||
 | 
			
		||||
struct ptimer_state
 | 
			
		||||
{
 | 
			
		||||
@ -21,6 +22,7 @@ struct ptimer_state
 | 
			
		||||
    int64_t period;
 | 
			
		||||
    int64_t last_event;
 | 
			
		||||
    int64_t next_event;
 | 
			
		||||
    uint8_t policy_mask;
 | 
			
		||||
    QEMUBH *bh;
 | 
			
		||||
    QEMUTimer *timer;
 | 
			
		||||
};
 | 
			
		||||
@ -43,7 +45,10 @@ static void ptimer_reload(ptimer_state *s)
 | 
			
		||||
        s->delta = s->limit;
 | 
			
		||||
    }
 | 
			
		||||
    if (s->delta == 0 || s->period == 0) {
 | 
			
		||||
        fprintf(stderr, "Timer with period zero, disabling\n");
 | 
			
		||||
        if (!qtest_enabled()) {
 | 
			
		||||
            fprintf(stderr, "Timer with period zero, disabling\n");
 | 
			
		||||
        }
 | 
			
		||||
        timer_del(s->timer);
 | 
			
		||||
        s->enabled = 0;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
@ -161,7 +166,9 @@ void ptimer_run(ptimer_state *s, int oneshot)
 | 
			
		||||
    bool was_disabled = !s->enabled;
 | 
			
		||||
 | 
			
		||||
    if (was_disabled && s->period == 0) {
 | 
			
		||||
        fprintf(stderr, "Timer with period zero, disabling\n");
 | 
			
		||||
        if (!qtest_enabled()) {
 | 
			
		||||
            fprintf(stderr, "Timer with period zero, disabling\n");
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    s->enabled = oneshot ? 2 : 1;
 | 
			
		||||
@ -242,12 +249,13 @@ const VMStateDescription vmstate_ptimer = {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ptimer_state *ptimer_init(QEMUBH *bh)
 | 
			
		||||
ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask)
 | 
			
		||||
{
 | 
			
		||||
    ptimer_state *s;
 | 
			
		||||
 | 
			
		||||
    s = (ptimer_state *)g_malloc0(sizeof(ptimer_state));
 | 
			
		||||
    s->bh = bh;
 | 
			
		||||
    s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ptimer_tick, s);
 | 
			
		||||
    s->policy_mask = policy_mask;
 | 
			
		||||
    return s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -48,18 +48,18 @@ typedef struct {
 | 
			
		||||
    SSISlave ssidev;
 | 
			
		||||
    QemuConsole *con;
 | 
			
		||||
 | 
			
		||||
    int cmd_len;
 | 
			
		||||
    int cmd;
 | 
			
		||||
    int cmd_data[8];
 | 
			
		||||
    int row;
 | 
			
		||||
    int row_start;
 | 
			
		||||
    int row_end;
 | 
			
		||||
    int col;
 | 
			
		||||
    int col_start;
 | 
			
		||||
    int col_end;
 | 
			
		||||
    int redraw;
 | 
			
		||||
    int remap;
 | 
			
		||||
    enum ssd0323_mode mode;
 | 
			
		||||
    uint32_t cmd_len;
 | 
			
		||||
    int32_t cmd;
 | 
			
		||||
    int32_t cmd_data[8];
 | 
			
		||||
    int32_t row;
 | 
			
		||||
    int32_t row_start;
 | 
			
		||||
    int32_t row_end;
 | 
			
		||||
    int32_t col;
 | 
			
		||||
    int32_t col_start;
 | 
			
		||||
    int32_t col_end;
 | 
			
		||||
    int32_t redraw;
 | 
			
		||||
    int32_t remap;
 | 
			
		||||
    uint32_t mode;
 | 
			
		||||
    uint8_t framebuffer[128 * 80 / 2];
 | 
			
		||||
} ssd0323_state;
 | 
			
		||||
 | 
			
		||||
@ -279,83 +279,62 @@ static void ssd0323_cd(void *opaque, int n, int level)
 | 
			
		||||
    s->mode = level ? SSD0323_DATA : SSD0323_CMD;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ssd0323_save(QEMUFile *f, void *opaque)
 | 
			
		||||
static int ssd0323_post_load(void *opaque, int version_id)
 | 
			
		||||
{
 | 
			
		||||
    SSISlave *ss = SSI_SLAVE(opaque);
 | 
			
		||||
    ssd0323_state *s = (ssd0323_state *)opaque;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    qemu_put_be32(f, s->cmd_len);
 | 
			
		||||
    qemu_put_be32(f, s->cmd);
 | 
			
		||||
    for (i = 0; i < 8; i++)
 | 
			
		||||
        qemu_put_be32(f, s->cmd_data[i]);
 | 
			
		||||
    qemu_put_be32(f, s->row);
 | 
			
		||||
    qemu_put_be32(f, s->row_start);
 | 
			
		||||
    qemu_put_be32(f, s->row_end);
 | 
			
		||||
    qemu_put_be32(f, s->col);
 | 
			
		||||
    qemu_put_be32(f, s->col_start);
 | 
			
		||||
    qemu_put_be32(f, s->col_end);
 | 
			
		||||
    qemu_put_be32(f, s->redraw);
 | 
			
		||||
    qemu_put_be32(f, s->remap);
 | 
			
		||||
    qemu_put_be32(f, s->mode);
 | 
			
		||||
    qemu_put_buffer(f, s->framebuffer, sizeof(s->framebuffer));
 | 
			
		||||
 | 
			
		||||
    qemu_put_be32(f, ss->cs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ssd0323_load(QEMUFile *f, void *opaque, int version_id)
 | 
			
		||||
{
 | 
			
		||||
    SSISlave *ss = SSI_SLAVE(opaque);
 | 
			
		||||
    ssd0323_state *s = (ssd0323_state *)opaque;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    if (version_id != 1)
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
 | 
			
		||||
    s->cmd_len = qemu_get_be32(f);
 | 
			
		||||
    if (s->cmd_len < 0 || s->cmd_len > ARRAY_SIZE(s->cmd_data)) {
 | 
			
		||||
    if (s->cmd_len > ARRAY_SIZE(s->cmd_data)) {
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
    }
 | 
			
		||||
    s->cmd = qemu_get_be32(f);
 | 
			
		||||
    for (i = 0; i < 8; i++)
 | 
			
		||||
        s->cmd_data[i] = qemu_get_be32(f);
 | 
			
		||||
    s->row = qemu_get_be32(f);
 | 
			
		||||
    if (s->row < 0 || s->row >= 80) {
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
    }
 | 
			
		||||
    s->row_start = qemu_get_be32(f);
 | 
			
		||||
    if (s->row_start < 0 || s->row_start >= 80) {
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
    }
 | 
			
		||||
    s->row_end = qemu_get_be32(f);
 | 
			
		||||
    if (s->row_end < 0 || s->row_end >= 80) {
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
    }
 | 
			
		||||
    s->col = qemu_get_be32(f);
 | 
			
		||||
    if (s->col < 0 || s->col >= 64) {
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
    }
 | 
			
		||||
    s->col_start = qemu_get_be32(f);
 | 
			
		||||
    if (s->col_start < 0 || s->col_start >= 64) {
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
    }
 | 
			
		||||
    s->col_end = qemu_get_be32(f);
 | 
			
		||||
    if (s->col_end < 0 || s->col_end >= 64) {
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
    }
 | 
			
		||||
    s->redraw = qemu_get_be32(f);
 | 
			
		||||
    s->remap = qemu_get_be32(f);
 | 
			
		||||
    s->mode = qemu_get_be32(f);
 | 
			
		||||
    if (s->mode != SSD0323_CMD && s->mode != SSD0323_DATA) {
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
    }
 | 
			
		||||
    qemu_get_buffer(f, s->framebuffer, sizeof(s->framebuffer));
 | 
			
		||||
 | 
			
		||||
    ss->cs = qemu_get_be32(f);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const VMStateDescription vmstate_ssd0323 = {
 | 
			
		||||
    .name = "ssd0323_oled",
 | 
			
		||||
    .version_id = 2,
 | 
			
		||||
    .minimum_version_id = 2,
 | 
			
		||||
    .post_load = ssd0323_post_load,
 | 
			
		||||
    .fields      = (VMStateField []) {
 | 
			
		||||
        VMSTATE_UINT32(cmd_len, ssd0323_state),
 | 
			
		||||
        VMSTATE_INT32(cmd, ssd0323_state),
 | 
			
		||||
        VMSTATE_INT32_ARRAY(cmd_data, ssd0323_state, 8),
 | 
			
		||||
        VMSTATE_INT32(row, ssd0323_state),
 | 
			
		||||
        VMSTATE_INT32(row_start, ssd0323_state),
 | 
			
		||||
        VMSTATE_INT32(row_end, ssd0323_state),
 | 
			
		||||
        VMSTATE_INT32(col, ssd0323_state),
 | 
			
		||||
        VMSTATE_INT32(col_start, ssd0323_state),
 | 
			
		||||
        VMSTATE_INT32(col_end, ssd0323_state),
 | 
			
		||||
        VMSTATE_INT32(redraw, ssd0323_state),
 | 
			
		||||
        VMSTATE_INT32(remap, ssd0323_state),
 | 
			
		||||
        VMSTATE_UINT32(mode, ssd0323_state),
 | 
			
		||||
        VMSTATE_BUFFER(framebuffer, ssd0323_state),
 | 
			
		||||
        VMSTATE_SSI_SLAVE(ssidev, ssd0323_state),
 | 
			
		||||
        VMSTATE_END_OF_LIST()
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const GraphicHwOps ssd0323_ops = {
 | 
			
		||||
    .invalidate  = ssd0323_invalidate_display,
 | 
			
		||||
    .gfx_update  = ssd0323_update_display,
 | 
			
		||||
@ -372,18 +351,17 @@ static void ssd0323_realize(SSISlave *d, Error **errp)
 | 
			
		||||
    qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY);
 | 
			
		||||
 | 
			
		||||
    qdev_init_gpio_in(dev, ssd0323_cd, 1);
 | 
			
		||||
 | 
			
		||||
    register_savevm(dev, "ssd0323_oled", -1, 1,
 | 
			
		||||
                    ssd0323_save, ssd0323_load, s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ssd0323_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(klass);
 | 
			
		||||
    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    k->realize = ssd0323_realize;
 | 
			
		||||
    k->transfer = ssd0323_transfer;
 | 
			
		||||
    k->cs_polarity = SSI_CS_HIGH;
 | 
			
		||||
    dc->vmsd = &vmstate_ssd0323;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo ssd0323_info = {
 | 
			
		||||
 | 
			
		||||
@ -548,7 +548,7 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
 | 
			
		||||
        st->nr = i;
 | 
			
		||||
        st->bh = qemu_bh_new(timer_hit, st);
 | 
			
		||||
        st->ptimer = ptimer_init(st->bh);
 | 
			
		||||
        st->ptimer = ptimer_init(st->bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
        ptimer_set_freq(st->ptimer, s->freqhz);
 | 
			
		||||
    }
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
@ -139,7 +139,7 @@ static m5206_timer_state *m5206_timer_init(qemu_irq irq)
 | 
			
		||||
 | 
			
		||||
    s = (m5206_timer_state *)g_malloc0(sizeof(m5206_timer_state));
 | 
			
		||||
    bh = qemu_bh_new(m5206_timer_trigger, s);
 | 
			
		||||
    s->timer = ptimer_init(bh);
 | 
			
		||||
    s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
    s->irq = irq;
 | 
			
		||||
    m5206_timer_reset(s);
 | 
			
		||||
    return s;
 | 
			
		||||
 | 
			
		||||
@ -183,7 +183,7 @@ static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
 | 
			
		||||
    for (i = 0; i < 2; i++) {
 | 
			
		||||
        s = (m5208_timer_state *)g_malloc0(sizeof(m5208_timer_state));
 | 
			
		||||
        bh = qemu_bh_new(m5208_timer_trigger, s);
 | 
			
		||||
        s->timer = ptimer_init(bh);
 | 
			
		||||
        s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
        memory_region_init_io(&s->iomem, NULL, &m5208_timer_ops, s,
 | 
			
		||||
                              "m5208-timer", 0x00004000);
 | 
			
		||||
        memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i,
 | 
			
		||||
 | 
			
		||||
@ -120,6 +120,41 @@ static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
 | 
			
		||||
     [BMC_DEV_ID]      = 0x00002402U
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* SCU70 bit 23: 0 24Mhz. bit 11:9: 0b001 AXI:ABH ratio 2:1 */
 | 
			
		||||
/* AST2500 revision A1 */
 | 
			
		||||
 | 
			
		||||
static const uint32_t ast2500_a1_resets[ASPEED_SCU_NR_REGS] = {
 | 
			
		||||
     [SYS_RST_CTRL]    = 0xFFCFFEDCU,
 | 
			
		||||
     [CLK_SEL]         = 0xF3F40000U,
 | 
			
		||||
     [CLK_STOP_CTRL]   = 0x19FC3E8BU,
 | 
			
		||||
     [D2PLL_PARAM]     = 0x00026108U,
 | 
			
		||||
     [MPLL_PARAM]      = 0x00030291U,
 | 
			
		||||
     [HPLL_PARAM]      = 0x93000400U,
 | 
			
		||||
     [MISC_CTRL1]      = 0x00000010U,
 | 
			
		||||
     [PCI_CTRL1]       = 0x20001A03U,
 | 
			
		||||
     [PCI_CTRL2]       = 0x20001A03U,
 | 
			
		||||
     [PCI_CTRL3]       = 0x04000030U,
 | 
			
		||||
     [SYS_RST_STATUS]  = 0x00000001U,
 | 
			
		||||
     [SOC_SCRATCH1]    = 0x000000C0U, /* SoC completed DRAM init */
 | 
			
		||||
     [MISC_CTRL2]      = 0x00000023U,
 | 
			
		||||
     [RNG_CTRL]        = 0x0000000EU,
 | 
			
		||||
     [PINMUX_CTRL2]    = 0x0000F000U,
 | 
			
		||||
     [PINMUX_CTRL3]    = 0x03000000U,
 | 
			
		||||
     [PINMUX_CTRL4]    = 0x00000000U,
 | 
			
		||||
     [PINMUX_CTRL5]    = 0x0000A000U,
 | 
			
		||||
     [WDT_RST_CTRL]    = 0x023FFFF3U,
 | 
			
		||||
     [PINMUX_CTRL8]    = 0xFFFF0000U,
 | 
			
		||||
     [PINMUX_CTRL9]    = 0x000FFFFFU,
 | 
			
		||||
     [FREE_CNTR4]      = 0x000000FFU,
 | 
			
		||||
     [FREE_CNTR4_EXT]  = 0x000000FFU,
 | 
			
		||||
     [CPU2_BASE_SEG1]  = 0x80000000U,
 | 
			
		||||
     [CPU2_BASE_SEG4]  = 0x1E600000U,
 | 
			
		||||
     [CPU2_BASE_SEG5]  = 0xC0000000U,
 | 
			
		||||
     [UART_HPLL_CLK]   = 0x00001903U,
 | 
			
		||||
     [PCIE_CTRL]       = 0x0000007BU,
 | 
			
		||||
     [BMC_DEV_ID]      = 0x00002402U
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    AspeedSCUState *s = ASPEED_SCU(opaque);
 | 
			
		||||
@ -198,6 +233,10 @@ static void aspeed_scu_reset(DeviceState *dev)
 | 
			
		||||
    case AST2400_A0_SILICON_REV:
 | 
			
		||||
        reset = ast2400_a0_resets;
 | 
			
		||||
        break;
 | 
			
		||||
    case AST2500_A0_SILICON_REV:
 | 
			
		||||
    case AST2500_A1_SILICON_REV:
 | 
			
		||||
        reset = ast2500_a1_resets;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        g_assert_not_reached();
 | 
			
		||||
    }
 | 
			
		||||
@ -208,7 +247,11 @@ static void aspeed_scu_reset(DeviceState *dev)
 | 
			
		||||
    s->regs[HW_STRAP2] = s->hw_strap2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t aspeed_silicon_revs[] = { AST2400_A0_SILICON_REV, };
 | 
			
		||||
static uint32_t aspeed_silicon_revs[] = {
 | 
			
		||||
    AST2400_A0_SILICON_REV,
 | 
			
		||||
    AST2500_A0_SILICON_REV,
 | 
			
		||||
    AST2500_A1_SILICON_REV,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
bool is_supported_silicon_rev(uint32_t silicon_rev)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,7 @@
 | 
			
		||||
 | 
			
		||||
#include "qemu/osdep.h"
 | 
			
		||||
#include "qemu/log.h"
 | 
			
		||||
#include "qemu/error-report.h"
 | 
			
		||||
#include "hw/misc/aspeed_sdmc.h"
 | 
			
		||||
#include "hw/misc/aspeed_scu.h"
 | 
			
		||||
#include "hw/qdev-properties.h"
 | 
			
		||||
@ -139,9 +140,9 @@ static const MemoryRegionOps aspeed_sdmc_ops = {
 | 
			
		||||
    .valid.max_access_size = 4,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int ast2400_rambits(void)
 | 
			
		||||
static int ast2400_rambits(AspeedSDMCState *s)
 | 
			
		||||
{
 | 
			
		||||
    switch (ram_size >> 20) {
 | 
			
		||||
    switch (s->ram_size >> 20) {
 | 
			
		||||
    case 64:
 | 
			
		||||
        return ASPEED_SDMC_DRAM_64MB;
 | 
			
		||||
    case 128:
 | 
			
		||||
@ -151,18 +152,19 @@ static int ast2400_rambits(void)
 | 
			
		||||
    case 512:
 | 
			
		||||
        return ASPEED_SDMC_DRAM_512MB;
 | 
			
		||||
    default:
 | 
			
		||||
        qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid RAM size: 0x"
 | 
			
		||||
                      RAM_ADDR_FMT "\n", __func__, ram_size);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* set a minimum default */
 | 
			
		||||
    return ASPEED_SDMC_DRAM_64MB;
 | 
			
		||||
    /* use a common default */
 | 
			
		||||
    error_report("warning: Invalid RAM size 0x%" PRIx64
 | 
			
		||||
                 ". Using default 256M", s->ram_size);
 | 
			
		||||
    s->ram_size = 256 << 20;
 | 
			
		||||
    return ASPEED_SDMC_DRAM_256MB;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ast2500_rambits(void)
 | 
			
		||||
static int ast2500_rambits(AspeedSDMCState *s)
 | 
			
		||||
{
 | 
			
		||||
    switch (ram_size >> 20) {
 | 
			
		||||
    switch (s->ram_size >> 20) {
 | 
			
		||||
    case 128:
 | 
			
		||||
        return ASPEED_SDMC_AST2500_128MB;
 | 
			
		||||
    case 256:
 | 
			
		||||
@ -172,13 +174,14 @@ static int ast2500_rambits(void)
 | 
			
		||||
    case 1024:
 | 
			
		||||
        return ASPEED_SDMC_AST2500_1024MB;
 | 
			
		||||
    default:
 | 
			
		||||
        qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid RAM size: 0x"
 | 
			
		||||
                      RAM_ADDR_FMT "\n", __func__, ram_size);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* set a minimum default */
 | 
			
		||||
    return ASPEED_SDMC_AST2500_128MB;
 | 
			
		||||
    /* use a common default */
 | 
			
		||||
    error_report("warning: Invalid RAM size 0x%" PRIx64
 | 
			
		||||
                 ". Using default 512M", s->ram_size);
 | 
			
		||||
    s->ram_size = 512 << 20;
 | 
			
		||||
    return ASPEED_SDMC_AST2500_512MB;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void aspeed_sdmc_reset(DeviceState *dev)
 | 
			
		||||
@ -192,14 +195,15 @@ static void aspeed_sdmc_reset(DeviceState *dev)
 | 
			
		||||
    case AST2400_A0_SILICON_REV:
 | 
			
		||||
        s->regs[R_CONF] |=
 | 
			
		||||
            ASPEED_SDMC_VGA_COMPAT |
 | 
			
		||||
            ASPEED_SDMC_DRAM_SIZE(ast2400_rambits());
 | 
			
		||||
            ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case AST2500_A0_SILICON_REV:
 | 
			
		||||
    case AST2500_A1_SILICON_REV:
 | 
			
		||||
        s->regs[R_CONF] |=
 | 
			
		||||
            ASPEED_SDMC_HW_VERSION(1) |
 | 
			
		||||
            ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) |
 | 
			
		||||
            ASPEED_SDMC_DRAM_SIZE(ast2500_rambits());
 | 
			
		||||
            ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
@ -218,6 +222,18 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    switch (s->silicon_rev) {
 | 
			
		||||
    case AST2400_A0_SILICON_REV:
 | 
			
		||||
        s->ram_bits = ast2400_rambits(s);
 | 
			
		||||
        break;
 | 
			
		||||
    case AST2500_A0_SILICON_REV:
 | 
			
		||||
    case AST2500_A1_SILICON_REV:
 | 
			
		||||
        s->ram_bits = ast2500_rambits(s);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        g_assert_not_reached();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops, s,
 | 
			
		||||
                          TYPE_ASPEED_SDMC, 0x1000);
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->iomem);
 | 
			
		||||
@ -235,6 +251,7 @@ static const VMStateDescription vmstate_aspeed_sdmc = {
 | 
			
		||||
 | 
			
		||||
static Property aspeed_sdmc_properties[] = {
 | 
			
		||||
    DEFINE_PROP_UINT32("silicon-rev", AspeedSDMCState, silicon_rev, 0),
 | 
			
		||||
    DEFINE_PROP_UINT64("ram-size", AspeedSDMCState, ram_size, 0),
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -27,7 +27,7 @@
 | 
			
		||||
        } \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
static char const *imx25_ccm_reg_name(uint32_t reg)
 | 
			
		||||
static const char *imx25_ccm_reg_name(uint32_t reg)
 | 
			
		||||
{
 | 
			
		||||
    static char unknown[20];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -29,7 +29,7 @@
 | 
			
		||||
        } \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
static char const *imx31_ccm_reg_name(uint32_t reg)
 | 
			
		||||
static const char *imx31_ccm_reg_name(uint32_t reg)
 | 
			
		||||
{
 | 
			
		||||
    static char unknown[20];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,7 @@
 | 
			
		||||
        } \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
static char const *imx6_ccm_reg_name(uint32_t reg)
 | 
			
		||||
static const char *imx6_ccm_reg_name(uint32_t reg)
 | 
			
		||||
{
 | 
			
		||||
    static char unknown[20];
 | 
			
		||||
 | 
			
		||||
@ -99,7 +99,7 @@ static char const *imx6_ccm_reg_name(uint32_t reg)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char const *imx6_analog_reg_name(uint32_t reg)
 | 
			
		||||
static const char *imx6_analog_reg_name(uint32_t reg)
 | 
			
		||||
{
 | 
			
		||||
    static char unknown[20];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -27,7 +27,7 @@
 | 
			
		||||
        } \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
static char const *imx6_src_reg_name(uint32_t reg)
 | 
			
		||||
static const char *imx6_src_reg_name(uint32_t reg)
 | 
			
		||||
{
 | 
			
		||||
    static char unknown[20];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -26,6 +26,8 @@
 | 
			
		||||
#include <zlib.h> /* For crc32 */
 | 
			
		||||
 | 
			
		||||
#include "hw/net/cadence_gem.h"
 | 
			
		||||
#include "qapi/error.h"
 | 
			
		||||
#include "qemu/log.h"
 | 
			
		||||
#include "net/checksum.h"
 | 
			
		||||
 | 
			
		||||
#ifdef CADENCE_GEM_ERR_DEBUG
 | 
			
		||||
@ -141,6 +143,61 @@
 | 
			
		||||
#define GEM_DESCONF6      (0x00000294/4)
 | 
			
		||||
#define GEM_DESCONF7      (0x00000298/4)
 | 
			
		||||
 | 
			
		||||
#define GEM_INT_Q1_STATUS               (0x00000400 / 4)
 | 
			
		||||
#define GEM_INT_Q1_MASK                 (0x00000640 / 4)
 | 
			
		||||
 | 
			
		||||
#define GEM_TRANSMIT_Q1_PTR             (0x00000440 / 4)
 | 
			
		||||
#define GEM_TRANSMIT_Q15_PTR            (GEM_TRANSMIT_Q1_PTR + 14)
 | 
			
		||||
 | 
			
		||||
#define GEM_RECEIVE_Q1_PTR              (0x00000480 / 4)
 | 
			
		||||
#define GEM_RECEIVE_Q15_PTR             (GEM_RECEIVE_Q1_PTR + 14)
 | 
			
		||||
 | 
			
		||||
#define GEM_INT_Q1_ENABLE               (0x00000600 / 4)
 | 
			
		||||
#define GEM_INT_Q7_ENABLE               (GEM_INT_Q1_ENABLE + 6)
 | 
			
		||||
#define GEM_INT_Q8_ENABLE               (0x00000660 / 4)
 | 
			
		||||
#define GEM_INT_Q15_ENABLE              (GEM_INT_Q8_ENABLE + 7)
 | 
			
		||||
 | 
			
		||||
#define GEM_INT_Q1_DISABLE              (0x00000620 / 4)
 | 
			
		||||
#define GEM_INT_Q7_DISABLE              (GEM_INT_Q1_DISABLE + 6)
 | 
			
		||||
#define GEM_INT_Q8_DISABLE              (0x00000680 / 4)
 | 
			
		||||
#define GEM_INT_Q15_DISABLE             (GEM_INT_Q8_DISABLE + 7)
 | 
			
		||||
 | 
			
		||||
#define GEM_INT_Q1_MASK                 (0x00000640 / 4)
 | 
			
		||||
#define GEM_INT_Q7_MASK                 (GEM_INT_Q1_MASK + 6)
 | 
			
		||||
#define GEM_INT_Q8_MASK                 (0x000006A0 / 4)
 | 
			
		||||
#define GEM_INT_Q15_MASK                (GEM_INT_Q8_MASK + 7)
 | 
			
		||||
 | 
			
		||||
#define GEM_SCREENING_TYPE1_REGISTER_0  (0x00000500 / 4)
 | 
			
		||||
 | 
			
		||||
#define GEM_ST1R_UDP_PORT_MATCH_ENABLE  (1 << 29)
 | 
			
		||||
#define GEM_ST1R_DSTC_ENABLE            (1 << 28)
 | 
			
		||||
#define GEM_ST1R_UDP_PORT_MATCH_SHIFT   (12)
 | 
			
		||||
#define GEM_ST1R_UDP_PORT_MATCH_WIDTH   (27 - GEM_ST1R_UDP_PORT_MATCH_SHIFT + 1)
 | 
			
		||||
#define GEM_ST1R_DSTC_MATCH_SHIFT       (4)
 | 
			
		||||
#define GEM_ST1R_DSTC_MATCH_WIDTH       (11 - GEM_ST1R_DSTC_MATCH_SHIFT + 1)
 | 
			
		||||
#define GEM_ST1R_QUEUE_SHIFT            (0)
 | 
			
		||||
#define GEM_ST1R_QUEUE_WIDTH            (3 - GEM_ST1R_QUEUE_SHIFT + 1)
 | 
			
		||||
 | 
			
		||||
#define GEM_SCREENING_TYPE2_REGISTER_0  (0x00000540 / 4)
 | 
			
		||||
 | 
			
		||||
#define GEM_ST2R_COMPARE_A_ENABLE       (1 << 18)
 | 
			
		||||
#define GEM_ST2R_COMPARE_A_SHIFT        (13)
 | 
			
		||||
#define GEM_ST2R_COMPARE_WIDTH          (17 - GEM_ST2R_COMPARE_A_SHIFT + 1)
 | 
			
		||||
#define GEM_ST2R_ETHERTYPE_ENABLE       (1 << 12)
 | 
			
		||||
#define GEM_ST2R_ETHERTYPE_INDEX_SHIFT  (9)
 | 
			
		||||
#define GEM_ST2R_ETHERTYPE_INDEX_WIDTH  (11 - GEM_ST2R_ETHERTYPE_INDEX_SHIFT \
 | 
			
		||||
                                            + 1)
 | 
			
		||||
#define GEM_ST2R_QUEUE_SHIFT            (0)
 | 
			
		||||
#define GEM_ST2R_QUEUE_WIDTH            (3 - GEM_ST2R_QUEUE_SHIFT + 1)
 | 
			
		||||
 | 
			
		||||
#define GEM_SCREENING_TYPE2_ETHERTYPE_REG_0     (0x000006e0 / 4)
 | 
			
		||||
#define GEM_TYPE2_COMPARE_0_WORD_0              (0x00000700 / 4)
 | 
			
		||||
 | 
			
		||||
#define GEM_T2CW1_COMPARE_OFFSET_SHIFT  (7)
 | 
			
		||||
#define GEM_T2CW1_COMPARE_OFFSET_WIDTH  (8 - GEM_T2CW1_COMPARE_OFFSET_SHIFT + 1)
 | 
			
		||||
#define GEM_T2CW1_OFFSET_VALUE_SHIFT    (0)
 | 
			
		||||
#define GEM_T2CW1_OFFSET_VALUE_WIDTH    (6 - GEM_T2CW1_OFFSET_VALUE_SHIFT + 1)
 | 
			
		||||
 | 
			
		||||
/*****************************************/
 | 
			
		||||
#define GEM_NWCTRL_TXSTART     0x00000200 /* Transmit Enable */
 | 
			
		||||
#define GEM_NWCTRL_TXENA       0x00000008 /* Transmit Enable */
 | 
			
		||||
@ -284,9 +341,9 @@ static inline unsigned tx_desc_get_length(unsigned *desc)
 | 
			
		||||
    return desc[1] & DESC_1_LENGTH;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void print_gem_tx_desc(unsigned *desc)
 | 
			
		||||
static inline void print_gem_tx_desc(unsigned *desc, uint8_t queue)
 | 
			
		||||
{
 | 
			
		||||
    DB_PRINT("TXDESC:\n");
 | 
			
		||||
    DB_PRINT("TXDESC (queue %" PRId8 "):\n", queue);
 | 
			
		||||
    DB_PRINT("bufaddr: 0x%08x\n", *desc);
 | 
			
		||||
    DB_PRINT("used_hw: %d\n", tx_desc_get_used(desc));
 | 
			
		||||
    DB_PRINT("wrap:    %d\n", tx_desc_get_wrap(desc));
 | 
			
		||||
@ -416,6 +473,7 @@ static void phy_update_link(CadenceGEMState *s)
 | 
			
		||||
static int gem_can_receive(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    CadenceGEMState *s;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    s = qemu_get_nic_opaque(nc);
 | 
			
		||||
 | 
			
		||||
@ -428,18 +486,20 @@ static int gem_can_receive(NetClientState *nc)
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (rx_desc_get_ownership(s->rx_desc) == 1) {
 | 
			
		||||
        if (s->can_rx_state != 2) {
 | 
			
		||||
            s->can_rx_state = 2;
 | 
			
		||||
            DB_PRINT("can't receive - busy buffer descriptor 0x%x\n",
 | 
			
		||||
                     s->rx_desc_addr);
 | 
			
		||||
    for (i = 0; i < s->num_priority_queues; i++) {
 | 
			
		||||
        if (rx_desc_get_ownership(s->rx_desc[i]) == 1) {
 | 
			
		||||
            if (s->can_rx_state != 2) {
 | 
			
		||||
                s->can_rx_state = 2;
 | 
			
		||||
                DB_PRINT("can't receive - busy buffer descriptor (q%d) 0x%x\n",
 | 
			
		||||
                         i, s->rx_desc_addr[i]);
 | 
			
		||||
             }
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (s->can_rx_state != 0) {
 | 
			
		||||
        s->can_rx_state = 0;
 | 
			
		||||
        DB_PRINT("can receive 0x%x\n", s->rx_desc_addr);
 | 
			
		||||
        DB_PRINT("can receive\n");
 | 
			
		||||
    }
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
@ -450,9 +510,20 @@ static int gem_can_receive(NetClientState *nc)
 | 
			
		||||
 */
 | 
			
		||||
static void gem_update_int_status(CadenceGEMState *s)
 | 
			
		||||
{
 | 
			
		||||
    if (s->regs[GEM_ISR]) {
 | 
			
		||||
        DB_PRINT("asserting int. (0x%08x)\n", s->regs[GEM_ISR]);
 | 
			
		||||
        qemu_set_irq(s->irq, 1);
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    if ((s->num_priority_queues == 1) && s->regs[GEM_ISR]) {
 | 
			
		||||
        /* No priority queues, just trigger the interrupt */
 | 
			
		||||
        DB_PRINT("asserting int.\n", i);
 | 
			
		||||
        qemu_set_irq(s->irq[0], 1);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < s->num_priority_queues; ++i) {
 | 
			
		||||
        if (s->regs[GEM_INT_Q1_STATUS + i]) {
 | 
			
		||||
            DB_PRINT("asserting int. (q=%d)\n", i);
 | 
			
		||||
            qemu_set_irq(s->irq[i], 1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -601,17 +672,137 @@ static int gem_mac_address_filter(CadenceGEMState *s, const uint8_t *packet)
 | 
			
		||||
    return GEM_RX_REJECT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gem_get_rx_desc(CadenceGEMState *s)
 | 
			
		||||
/* Figure out which queue the received data should be sent to */
 | 
			
		||||
static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr,
 | 
			
		||||
                                 unsigned rxbufsize)
 | 
			
		||||
{
 | 
			
		||||
    DB_PRINT("read descriptor 0x%x\n", (unsigned)s->rx_desc_addr);
 | 
			
		||||
    uint32_t reg;
 | 
			
		||||
    bool matched, mismatched;
 | 
			
		||||
    int i, j;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < s->num_type1_screeners; i++) {
 | 
			
		||||
        reg = s->regs[GEM_SCREENING_TYPE1_REGISTER_0 + i];
 | 
			
		||||
        matched = false;
 | 
			
		||||
        mismatched = false;
 | 
			
		||||
 | 
			
		||||
        /* Screening is based on UDP Port */
 | 
			
		||||
        if (reg & GEM_ST1R_UDP_PORT_MATCH_ENABLE) {
 | 
			
		||||
            uint16_t udp_port = rxbuf_ptr[14 + 22] << 8 | rxbuf_ptr[14 + 23];
 | 
			
		||||
            if (udp_port == extract32(reg, GEM_ST1R_UDP_PORT_MATCH_SHIFT,
 | 
			
		||||
                                           GEM_ST1R_UDP_PORT_MATCH_WIDTH)) {
 | 
			
		||||
                matched = true;
 | 
			
		||||
            } else {
 | 
			
		||||
                mismatched = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Screening is based on DS/TC */
 | 
			
		||||
        if (reg & GEM_ST1R_DSTC_ENABLE) {
 | 
			
		||||
            uint8_t dscp = rxbuf_ptr[14 + 1];
 | 
			
		||||
            if (dscp == extract32(reg, GEM_ST1R_DSTC_MATCH_SHIFT,
 | 
			
		||||
                                       GEM_ST1R_DSTC_MATCH_WIDTH)) {
 | 
			
		||||
                matched = true;
 | 
			
		||||
            } else {
 | 
			
		||||
                mismatched = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (matched && !mismatched) {
 | 
			
		||||
            return extract32(reg, GEM_ST1R_QUEUE_SHIFT, GEM_ST1R_QUEUE_WIDTH);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < s->num_type2_screeners; i++) {
 | 
			
		||||
        reg = s->regs[GEM_SCREENING_TYPE2_REGISTER_0 + i];
 | 
			
		||||
        matched = false;
 | 
			
		||||
        mismatched = false;
 | 
			
		||||
 | 
			
		||||
        if (reg & GEM_ST2R_ETHERTYPE_ENABLE) {
 | 
			
		||||
            uint16_t type = rxbuf_ptr[12] << 8 | rxbuf_ptr[13];
 | 
			
		||||
            int et_idx = extract32(reg, GEM_ST2R_ETHERTYPE_INDEX_SHIFT,
 | 
			
		||||
                                        GEM_ST2R_ETHERTYPE_INDEX_WIDTH);
 | 
			
		||||
 | 
			
		||||
            if (et_idx > s->num_type2_screeners) {
 | 
			
		||||
                qemu_log_mask(LOG_GUEST_ERROR, "Out of range ethertype "
 | 
			
		||||
                              "register index: %d\n", et_idx);
 | 
			
		||||
            }
 | 
			
		||||
            if (type == s->regs[GEM_SCREENING_TYPE2_ETHERTYPE_REG_0 +
 | 
			
		||||
                                et_idx]) {
 | 
			
		||||
                matched = true;
 | 
			
		||||
            } else {
 | 
			
		||||
                mismatched = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Compare A, B, C */
 | 
			
		||||
        for (j = 0; j < 3; j++) {
 | 
			
		||||
            uint32_t cr0, cr1, mask;
 | 
			
		||||
            uint16_t rx_cmp;
 | 
			
		||||
            int offset;
 | 
			
		||||
            int cr_idx = extract32(reg, GEM_ST2R_COMPARE_A_SHIFT + j * 6,
 | 
			
		||||
                                        GEM_ST2R_COMPARE_WIDTH);
 | 
			
		||||
 | 
			
		||||
            if (!(reg & (GEM_ST2R_COMPARE_A_ENABLE << (j * 6)))) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (cr_idx > s->num_type2_screeners) {
 | 
			
		||||
                qemu_log_mask(LOG_GUEST_ERROR, "Out of range compare "
 | 
			
		||||
                              "register index: %d\n", cr_idx);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            cr0 = s->regs[GEM_TYPE2_COMPARE_0_WORD_0 + cr_idx * 2];
 | 
			
		||||
            cr1 = s->regs[GEM_TYPE2_COMPARE_0_WORD_0 + cr_idx * 2 + 1];
 | 
			
		||||
            offset = extract32(cr1, GEM_T2CW1_OFFSET_VALUE_SHIFT,
 | 
			
		||||
                                    GEM_T2CW1_OFFSET_VALUE_WIDTH);
 | 
			
		||||
 | 
			
		||||
            switch (extract32(cr1, GEM_T2CW1_COMPARE_OFFSET_SHIFT,
 | 
			
		||||
                                   GEM_T2CW1_COMPARE_OFFSET_WIDTH)) {
 | 
			
		||||
            case 3: /* Skip UDP header */
 | 
			
		||||
                qemu_log_mask(LOG_UNIMP, "TCP compare offsets"
 | 
			
		||||
                              "unimplemented - assuming UDP\n");
 | 
			
		||||
                offset += 8;
 | 
			
		||||
                /* Fallthrough */
 | 
			
		||||
            case 2: /* skip the IP header */
 | 
			
		||||
                offset += 20;
 | 
			
		||||
                /* Fallthrough */
 | 
			
		||||
            case 1: /* Count from after the ethertype */
 | 
			
		||||
                offset += 14;
 | 
			
		||||
                break;
 | 
			
		||||
            case 0:
 | 
			
		||||
                /* Offset from start of frame */
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            rx_cmp = rxbuf_ptr[offset] << 8 | rxbuf_ptr[offset];
 | 
			
		||||
            mask = extract32(cr0, 0, 16);
 | 
			
		||||
 | 
			
		||||
            if ((rx_cmp & mask) == (extract32(cr0, 16, 16) & mask)) {
 | 
			
		||||
                matched = true;
 | 
			
		||||
            } else {
 | 
			
		||||
                mismatched = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (matched && !mismatched) {
 | 
			
		||||
            return extract32(reg, GEM_ST2R_QUEUE_SHIFT, GEM_ST2R_QUEUE_WIDTH);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* We made it here, assume it's queue 0 */
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gem_get_rx_desc(CadenceGEMState *s, int q)
 | 
			
		||||
{
 | 
			
		||||
    DB_PRINT("read descriptor 0x%x\n", (unsigned)s->rx_desc_addr[q]);
 | 
			
		||||
    /* read current descriptor */
 | 
			
		||||
    cpu_physical_memory_read(s->rx_desc_addr,
 | 
			
		||||
                             (uint8_t *)s->rx_desc, sizeof(s->rx_desc));
 | 
			
		||||
    cpu_physical_memory_read(s->rx_desc_addr[0],
 | 
			
		||||
                             (uint8_t *)s->rx_desc[0], sizeof(s->rx_desc[0]));
 | 
			
		||||
 | 
			
		||||
    /* Descriptor owned by software ? */
 | 
			
		||||
    if (rx_desc_get_ownership(s->rx_desc) == 1) {
 | 
			
		||||
    if (rx_desc_get_ownership(s->rx_desc[q]) == 1) {
 | 
			
		||||
        DB_PRINT("descriptor 0x%x owned by sw.\n",
 | 
			
		||||
                 (unsigned)s->rx_desc_addr);
 | 
			
		||||
                 (unsigned)s->rx_desc_addr[q]);
 | 
			
		||||
        s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_NOBUF;
 | 
			
		||||
        s->regs[GEM_ISR] |= GEM_INT_RXUSED & ~(s->regs[GEM_IMR]);
 | 
			
		||||
        /* Handle interrupt consequences */
 | 
			
		||||
@ -632,6 +823,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
 | 
			
		||||
    uint8_t   *rxbuf_ptr;
 | 
			
		||||
    bool first_desc = true;
 | 
			
		||||
    int maf;
 | 
			
		||||
    int q = 0;
 | 
			
		||||
 | 
			
		||||
    s = qemu_get_nic_opaque(nc);
 | 
			
		||||
 | 
			
		||||
@ -710,6 +902,9 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
 | 
			
		||||
 | 
			
		||||
    DB_PRINT("config bufsize: %d packet size: %ld\n", rxbufsize, size);
 | 
			
		||||
 | 
			
		||||
    /* Find which queue we are targetting */
 | 
			
		||||
    q = get_queue_from_screen(s, rxbuf_ptr, rxbufsize);
 | 
			
		||||
 | 
			
		||||
    while (bytes_to_copy) {
 | 
			
		||||
        /* Do nothing if receive is not enabled. */
 | 
			
		||||
        if (!gem_can_receive(nc)) {
 | 
			
		||||
@ -718,56 +913,59 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        DB_PRINT("copy %d bytes to 0x%x\n", MIN(bytes_to_copy, rxbufsize),
 | 
			
		||||
                rx_desc_get_buffer(s->rx_desc));
 | 
			
		||||
                rx_desc_get_buffer(s->rx_desc[q]));
 | 
			
		||||
 | 
			
		||||
        /* Copy packet data to emulated DMA buffer */
 | 
			
		||||
        cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc) + rxbuf_offset,
 | 
			
		||||
        cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc[q]) +
 | 
			
		||||
                                                                 rxbuf_offset,
 | 
			
		||||
                                  rxbuf_ptr, MIN(bytes_to_copy, rxbufsize));
 | 
			
		||||
        rxbuf_ptr += MIN(bytes_to_copy, rxbufsize);
 | 
			
		||||
        bytes_to_copy -= MIN(bytes_to_copy, rxbufsize);
 | 
			
		||||
 | 
			
		||||
        /* Update the descriptor.  */
 | 
			
		||||
        if (first_desc) {
 | 
			
		||||
            rx_desc_set_sof(s->rx_desc);
 | 
			
		||||
            rx_desc_set_sof(s->rx_desc[q]);
 | 
			
		||||
            first_desc = false;
 | 
			
		||||
        }
 | 
			
		||||
        if (bytes_to_copy == 0) {
 | 
			
		||||
            rx_desc_set_eof(s->rx_desc);
 | 
			
		||||
            rx_desc_set_length(s->rx_desc, size);
 | 
			
		||||
            rx_desc_set_eof(s->rx_desc[q]);
 | 
			
		||||
            rx_desc_set_length(s->rx_desc[q], size);
 | 
			
		||||
        }
 | 
			
		||||
        rx_desc_set_ownership(s->rx_desc);
 | 
			
		||||
        rx_desc_set_ownership(s->rx_desc[q]);
 | 
			
		||||
 | 
			
		||||
        switch (maf) {
 | 
			
		||||
        case GEM_RX_PROMISCUOUS_ACCEPT:
 | 
			
		||||
            break;
 | 
			
		||||
        case GEM_RX_BROADCAST_ACCEPT:
 | 
			
		||||
            rx_desc_set_broadcast(s->rx_desc);
 | 
			
		||||
            rx_desc_set_broadcast(s->rx_desc[q]);
 | 
			
		||||
            break;
 | 
			
		||||
        case GEM_RX_UNICAST_HASH_ACCEPT:
 | 
			
		||||
            rx_desc_set_unicast_hash(s->rx_desc);
 | 
			
		||||
            rx_desc_set_unicast_hash(s->rx_desc[q]);
 | 
			
		||||
            break;
 | 
			
		||||
        case GEM_RX_MULTICAST_HASH_ACCEPT:
 | 
			
		||||
            rx_desc_set_multicast_hash(s->rx_desc);
 | 
			
		||||
            rx_desc_set_multicast_hash(s->rx_desc[q]);
 | 
			
		||||
            break;
 | 
			
		||||
        case GEM_RX_REJECT:
 | 
			
		||||
            abort();
 | 
			
		||||
        default: /* SAR */
 | 
			
		||||
            rx_desc_set_sar(s->rx_desc, maf);
 | 
			
		||||
            rx_desc_set_sar(s->rx_desc[q], maf);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Descriptor write-back.  */
 | 
			
		||||
        cpu_physical_memory_write(s->rx_desc_addr,
 | 
			
		||||
                                  (uint8_t *)s->rx_desc, sizeof(s->rx_desc));
 | 
			
		||||
        cpu_physical_memory_write(s->rx_desc_addr[q],
 | 
			
		||||
                                  (uint8_t *)s->rx_desc[q],
 | 
			
		||||
                                  sizeof(s->rx_desc[q]));
 | 
			
		||||
 | 
			
		||||
        /* Next descriptor */
 | 
			
		||||
        if (rx_desc_get_wrap(s->rx_desc)) {
 | 
			
		||||
        if (rx_desc_get_wrap(s->rx_desc[q])) {
 | 
			
		||||
            DB_PRINT("wrapping RX descriptor list\n");
 | 
			
		||||
            s->rx_desc_addr = s->regs[GEM_RXQBASE];
 | 
			
		||||
            s->rx_desc_addr[q] = s->regs[GEM_RXQBASE];
 | 
			
		||||
        } else {
 | 
			
		||||
            DB_PRINT("incrementing RX descriptor list\n");
 | 
			
		||||
            s->rx_desc_addr += 8;
 | 
			
		||||
            s->rx_desc_addr[q] += 8;
 | 
			
		||||
        }
 | 
			
		||||
        gem_get_rx_desc(s);
 | 
			
		||||
 | 
			
		||||
        gem_get_rx_desc(s, q);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Count it */
 | 
			
		||||
@ -839,6 +1037,7 @@ static void gem_transmit(CadenceGEMState *s)
 | 
			
		||||
    uint8_t     tx_packet[2048];
 | 
			
		||||
    uint8_t     *p;
 | 
			
		||||
    unsigned    total_bytes;
 | 
			
		||||
    int q = 0;
 | 
			
		||||
 | 
			
		||||
    /* Do nothing if transmit is not enabled. */
 | 
			
		||||
    if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_TXENA)) {
 | 
			
		||||
@ -854,110 +1053,123 @@ static void gem_transmit(CadenceGEMState *s)
 | 
			
		||||
    p = tx_packet;
 | 
			
		||||
    total_bytes = 0;
 | 
			
		||||
 | 
			
		||||
    /* read current descriptor */
 | 
			
		||||
    packet_desc_addr = s->tx_desc_addr;
 | 
			
		||||
    for (q = s->num_priority_queues - 1; q >= 0; q--) {
 | 
			
		||||
        /* read current descriptor */
 | 
			
		||||
        packet_desc_addr = s->tx_desc_addr[q];
 | 
			
		||||
 | 
			
		||||
    DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
 | 
			
		||||
    cpu_physical_memory_read(packet_desc_addr,
 | 
			
		||||
                             (uint8_t *)desc, sizeof(desc));
 | 
			
		||||
    /* Handle all descriptors owned by hardware */
 | 
			
		||||
    while (tx_desc_get_used(desc) == 0) {
 | 
			
		||||
 | 
			
		||||
        /* Do nothing if transmit is not enabled. */
 | 
			
		||||
        if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_TXENA)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        print_gem_tx_desc(desc);
 | 
			
		||||
 | 
			
		||||
        /* The real hardware would eat this (and possibly crash).
 | 
			
		||||
         * For QEMU let's lend a helping hand.
 | 
			
		||||
         */
 | 
			
		||||
        if ((tx_desc_get_buffer(desc) == 0) ||
 | 
			
		||||
            (tx_desc_get_length(desc) == 0)) {
 | 
			
		||||
            DB_PRINT("Invalid TX descriptor @ 0x%x\n",
 | 
			
		||||
                     (unsigned)packet_desc_addr);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (tx_desc_get_length(desc) > sizeof(tx_packet) - (p - tx_packet)) {
 | 
			
		||||
            DB_PRINT("TX descriptor @ 0x%x too large: size 0x%x space 0x%x\n",
 | 
			
		||||
                     (unsigned)packet_desc_addr,
 | 
			
		||||
                     (unsigned)tx_desc_get_length(desc),
 | 
			
		||||
                     sizeof(tx_packet) - (p - tx_packet));
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Gather this fragment of the packet from "dma memory" to our contig.
 | 
			
		||||
         * buffer.
 | 
			
		||||
         */
 | 
			
		||||
        cpu_physical_memory_read(tx_desc_get_buffer(desc), p,
 | 
			
		||||
                                 tx_desc_get_length(desc));
 | 
			
		||||
        p += tx_desc_get_length(desc);
 | 
			
		||||
        total_bytes += tx_desc_get_length(desc);
 | 
			
		||||
 | 
			
		||||
        /* Last descriptor for this packet; hand the whole thing off */
 | 
			
		||||
        if (tx_desc_get_last(desc)) {
 | 
			
		||||
            unsigned    desc_first[2];
 | 
			
		||||
 | 
			
		||||
            /* Modify the 1st descriptor of this packet to be owned by
 | 
			
		||||
             * the processor.
 | 
			
		||||
             */
 | 
			
		||||
            cpu_physical_memory_read(s->tx_desc_addr, (uint8_t *)desc_first,
 | 
			
		||||
                                     sizeof(desc_first));
 | 
			
		||||
            tx_desc_set_used(desc_first);
 | 
			
		||||
            cpu_physical_memory_write(s->tx_desc_addr, (uint8_t *)desc_first,
 | 
			
		||||
                                      sizeof(desc_first));
 | 
			
		||||
            /* Advance the hardware current descriptor past this packet */
 | 
			
		||||
            if (tx_desc_get_wrap(desc)) {
 | 
			
		||||
                s->tx_desc_addr = s->regs[GEM_TXQBASE];
 | 
			
		||||
            } else {
 | 
			
		||||
                s->tx_desc_addr = packet_desc_addr + 8;
 | 
			
		||||
            }
 | 
			
		||||
            DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr);
 | 
			
		||||
 | 
			
		||||
            s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_TXCMPL;
 | 
			
		||||
            s->regs[GEM_ISR] |= GEM_INT_TXCMPL & ~(s->regs[GEM_IMR]);
 | 
			
		||||
 | 
			
		||||
            /* Handle interrupt consequences */
 | 
			
		||||
            gem_update_int_status(s);
 | 
			
		||||
 | 
			
		||||
            /* Is checksum offload enabled? */
 | 
			
		||||
            if (s->regs[GEM_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) {
 | 
			
		||||
                net_checksum_calculate(tx_packet, total_bytes);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* Update MAC statistics */
 | 
			
		||||
            gem_transmit_updatestats(s, tx_packet, total_bytes);
 | 
			
		||||
 | 
			
		||||
            /* Send the packet somewhere */
 | 
			
		||||
            if (s->phy_loop || (s->regs[GEM_NWCTRL] & GEM_NWCTRL_LOCALLOOP)) {
 | 
			
		||||
                gem_receive(qemu_get_queue(s->nic), tx_packet, total_bytes);
 | 
			
		||||
            } else {
 | 
			
		||||
                qemu_send_packet(qemu_get_queue(s->nic), tx_packet,
 | 
			
		||||
                                 total_bytes);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* Prepare for next packet */
 | 
			
		||||
            p = tx_packet;
 | 
			
		||||
            total_bytes = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* read next descriptor */
 | 
			
		||||
        if (tx_desc_get_wrap(desc)) {
 | 
			
		||||
            tx_desc_set_last(desc);
 | 
			
		||||
            packet_desc_addr = s->regs[GEM_TXQBASE];
 | 
			
		||||
        } else {
 | 
			
		||||
            packet_desc_addr += 8;
 | 
			
		||||
        }
 | 
			
		||||
        DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
 | 
			
		||||
        cpu_physical_memory_read(packet_desc_addr,
 | 
			
		||||
                                 (uint8_t *)desc, sizeof(desc));
 | 
			
		||||
    }
 | 
			
		||||
        /* Handle all descriptors owned by hardware */
 | 
			
		||||
        while (tx_desc_get_used(desc) == 0) {
 | 
			
		||||
 | 
			
		||||
    if (tx_desc_get_used(desc)) {
 | 
			
		||||
        s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_USED;
 | 
			
		||||
        s->regs[GEM_ISR] |= GEM_INT_TXUSED & ~(s->regs[GEM_IMR]);
 | 
			
		||||
        gem_update_int_status(s);
 | 
			
		||||
            /* Do nothing if transmit is not enabled. */
 | 
			
		||||
            if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_TXENA)) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            print_gem_tx_desc(desc, q);
 | 
			
		||||
 | 
			
		||||
            /* The real hardware would eat this (and possibly crash).
 | 
			
		||||
             * For QEMU let's lend a helping hand.
 | 
			
		||||
             */
 | 
			
		||||
            if ((tx_desc_get_buffer(desc) == 0) ||
 | 
			
		||||
                (tx_desc_get_length(desc) == 0)) {
 | 
			
		||||
                DB_PRINT("Invalid TX descriptor @ 0x%x\n",
 | 
			
		||||
                         (unsigned)packet_desc_addr);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (tx_desc_get_length(desc) > sizeof(tx_packet) -
 | 
			
		||||
                                               (p - tx_packet)) {
 | 
			
		||||
                DB_PRINT("TX descriptor @ 0x%x too large: size 0x%x space " \
 | 
			
		||||
                         "0x%x\n", (unsigned)packet_desc_addr,
 | 
			
		||||
                         (unsigned)tx_desc_get_length(desc),
 | 
			
		||||
                         sizeof(tx_packet) - (p - tx_packet));
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* Gather this fragment of the packet from "dma memory" to our
 | 
			
		||||
             * contig buffer.
 | 
			
		||||
             */
 | 
			
		||||
            cpu_physical_memory_read(tx_desc_get_buffer(desc), p,
 | 
			
		||||
                                     tx_desc_get_length(desc));
 | 
			
		||||
            p += tx_desc_get_length(desc);
 | 
			
		||||
            total_bytes += tx_desc_get_length(desc);
 | 
			
		||||
 | 
			
		||||
            /* Last descriptor for this packet; hand the whole thing off */
 | 
			
		||||
            if (tx_desc_get_last(desc)) {
 | 
			
		||||
                unsigned    desc_first[2];
 | 
			
		||||
 | 
			
		||||
                /* Modify the 1st descriptor of this packet to be owned by
 | 
			
		||||
                 * the processor.
 | 
			
		||||
                 */
 | 
			
		||||
                cpu_physical_memory_read(s->tx_desc_addr[q],
 | 
			
		||||
                                         (uint8_t *)desc_first,
 | 
			
		||||
                                         sizeof(desc_first));
 | 
			
		||||
                tx_desc_set_used(desc_first);
 | 
			
		||||
                cpu_physical_memory_write(s->tx_desc_addr[q],
 | 
			
		||||
                                          (uint8_t *)desc_first,
 | 
			
		||||
                                          sizeof(desc_first));
 | 
			
		||||
                /* Advance the hardware current descriptor past this packet */
 | 
			
		||||
                if (tx_desc_get_wrap(desc)) {
 | 
			
		||||
                    s->tx_desc_addr[q] = s->regs[GEM_TXQBASE];
 | 
			
		||||
                } else {
 | 
			
		||||
                    s->tx_desc_addr[q] = packet_desc_addr + 8;
 | 
			
		||||
                }
 | 
			
		||||
                DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr[q]);
 | 
			
		||||
 | 
			
		||||
                s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_TXCMPL;
 | 
			
		||||
                s->regs[GEM_ISR] |= GEM_INT_TXCMPL & ~(s->regs[GEM_IMR]);
 | 
			
		||||
 | 
			
		||||
                /* Update queue interrupt status */
 | 
			
		||||
                if (s->num_priority_queues > 1) {
 | 
			
		||||
                    s->regs[GEM_INT_Q1_STATUS + q] |=
 | 
			
		||||
                            GEM_INT_TXCMPL & ~(s->regs[GEM_INT_Q1_MASK + q]);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /* Handle interrupt consequences */
 | 
			
		||||
                gem_update_int_status(s);
 | 
			
		||||
 | 
			
		||||
                /* Is checksum offload enabled? */
 | 
			
		||||
                if (s->regs[GEM_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) {
 | 
			
		||||
                    net_checksum_calculate(tx_packet, total_bytes);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /* Update MAC statistics */
 | 
			
		||||
                gem_transmit_updatestats(s, tx_packet, total_bytes);
 | 
			
		||||
 | 
			
		||||
                /* Send the packet somewhere */
 | 
			
		||||
                if (s->phy_loop || (s->regs[GEM_NWCTRL] &
 | 
			
		||||
                                    GEM_NWCTRL_LOCALLOOP)) {
 | 
			
		||||
                    gem_receive(qemu_get_queue(s->nic), tx_packet,
 | 
			
		||||
                                total_bytes);
 | 
			
		||||
                } else {
 | 
			
		||||
                    qemu_send_packet(qemu_get_queue(s->nic), tx_packet,
 | 
			
		||||
                                     total_bytes);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /* Prepare for next packet */
 | 
			
		||||
                p = tx_packet;
 | 
			
		||||
                total_bytes = 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* read next descriptor */
 | 
			
		||||
            if (tx_desc_get_wrap(desc)) {
 | 
			
		||||
                tx_desc_set_last(desc);
 | 
			
		||||
                packet_desc_addr = s->regs[GEM_TXQBASE];
 | 
			
		||||
            } else {
 | 
			
		||||
                packet_desc_addr += 8;
 | 
			
		||||
            }
 | 
			
		||||
            DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
 | 
			
		||||
            cpu_physical_memory_read(packet_desc_addr,
 | 
			
		||||
                                     (uint8_t *)desc, sizeof(desc));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (tx_desc_get_used(desc)) {
 | 
			
		||||
            s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_USED;
 | 
			
		||||
            s->regs[GEM_ISR] |= GEM_INT_TXUSED & ~(s->regs[GEM_IMR]);
 | 
			
		||||
            gem_update_int_status(s);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1065,7 +1277,7 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    CadenceGEMState *s;
 | 
			
		||||
    uint32_t retval;
 | 
			
		||||
 | 
			
		||||
    int i;
 | 
			
		||||
    s = (CadenceGEMState *)opaque;
 | 
			
		||||
 | 
			
		||||
    offset >>= 2;
 | 
			
		||||
@ -1075,8 +1287,10 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
 | 
			
		||||
 | 
			
		||||
    switch (offset) {
 | 
			
		||||
    case GEM_ISR:
 | 
			
		||||
        DB_PRINT("lowering irq on ISR read\n");
 | 
			
		||||
        qemu_set_irq(s->irq, 0);
 | 
			
		||||
        DB_PRINT("lowering irqs on ISR read\n");
 | 
			
		||||
        for (i = 0; i < s->num_priority_queues; ++i) {
 | 
			
		||||
            qemu_set_irq(s->irq[i], 0);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case GEM_PHYMNTNC:
 | 
			
		||||
        if (retval & GEM_PHYMNTNC_OP_R) {
 | 
			
		||||
@ -1101,6 +1315,7 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
 | 
			
		||||
    retval &= ~(s->regs_wo[offset]);
 | 
			
		||||
 | 
			
		||||
    DB_PRINT("0x%08x\n", retval);
 | 
			
		||||
    gem_update_int_status(s);
 | 
			
		||||
    return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1113,6 +1328,7 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
 | 
			
		||||
{
 | 
			
		||||
    CadenceGEMState *s = (CadenceGEMState *)opaque;
 | 
			
		||||
    uint32_t readonly;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    DB_PRINT("offset: 0x%04x write: 0x%08x ", (unsigned)offset, (unsigned)val);
 | 
			
		||||
    offset >>= 2;
 | 
			
		||||
@ -1132,14 +1348,18 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
 | 
			
		||||
    switch (offset) {
 | 
			
		||||
    case GEM_NWCTRL:
 | 
			
		||||
        if (val & GEM_NWCTRL_RXENA) {
 | 
			
		||||
            gem_get_rx_desc(s);
 | 
			
		||||
            for (i = 0; i < s->num_priority_queues; ++i) {
 | 
			
		||||
                gem_get_rx_desc(s, i);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (val & GEM_NWCTRL_TXSTART) {
 | 
			
		||||
            gem_transmit(s);
 | 
			
		||||
        }
 | 
			
		||||
        if (!(val & GEM_NWCTRL_TXENA)) {
 | 
			
		||||
            /* Reset to start of Q when transmit disabled. */
 | 
			
		||||
            s->tx_desc_addr = s->regs[GEM_TXQBASE];
 | 
			
		||||
            for (i = 0; i < s->num_priority_queues; i++) {
 | 
			
		||||
                s->tx_desc_addr[i] = s->regs[GEM_TXQBASE];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (gem_can_receive(qemu_get_queue(s->nic))) {
 | 
			
		||||
            qemu_flush_queued_packets(qemu_get_queue(s->nic));
 | 
			
		||||
@ -1150,10 +1370,16 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
 | 
			
		||||
        gem_update_int_status(s);
 | 
			
		||||
        break;
 | 
			
		||||
    case GEM_RXQBASE:
 | 
			
		||||
        s->rx_desc_addr = val;
 | 
			
		||||
        s->rx_desc_addr[0] = val;
 | 
			
		||||
        break;
 | 
			
		||||
    case GEM_RECEIVE_Q1_PTR ... GEM_RECEIVE_Q15_PTR:
 | 
			
		||||
        s->rx_desc_addr[offset - GEM_RECEIVE_Q1_PTR + 1] = val;
 | 
			
		||||
        break;
 | 
			
		||||
    case GEM_TXQBASE:
 | 
			
		||||
        s->tx_desc_addr = val;
 | 
			
		||||
        s->tx_desc_addr[0] = val;
 | 
			
		||||
        break;
 | 
			
		||||
    case GEM_TRANSMIT_Q1_PTR ... GEM_TRANSMIT_Q15_PTR:
 | 
			
		||||
        s->tx_desc_addr[offset - GEM_TRANSMIT_Q1_PTR + 1] = val;
 | 
			
		||||
        break;
 | 
			
		||||
    case GEM_RXSTATUS:
 | 
			
		||||
        gem_update_int_status(s);
 | 
			
		||||
@ -1162,10 +1388,26 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
 | 
			
		||||
        s->regs[GEM_IMR] &= ~val;
 | 
			
		||||
        gem_update_int_status(s);
 | 
			
		||||
        break;
 | 
			
		||||
    case GEM_INT_Q1_ENABLE ... GEM_INT_Q7_ENABLE:
 | 
			
		||||
        s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_ENABLE] &= ~val;
 | 
			
		||||
        gem_update_int_status(s);
 | 
			
		||||
        break;
 | 
			
		||||
    case GEM_INT_Q8_ENABLE ... GEM_INT_Q15_ENABLE:
 | 
			
		||||
        s->regs[GEM_INT_Q8_MASK + offset - GEM_INT_Q8_ENABLE] &= ~val;
 | 
			
		||||
        gem_update_int_status(s);
 | 
			
		||||
        break;
 | 
			
		||||
    case GEM_IDR:
 | 
			
		||||
        s->regs[GEM_IMR] |= val;
 | 
			
		||||
        gem_update_int_status(s);
 | 
			
		||||
        break;
 | 
			
		||||
    case GEM_INT_Q1_DISABLE ... GEM_INT_Q7_DISABLE:
 | 
			
		||||
        s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_DISABLE] |= val;
 | 
			
		||||
        gem_update_int_status(s);
 | 
			
		||||
        break;
 | 
			
		||||
    case GEM_INT_Q8_DISABLE ... GEM_INT_Q15_DISABLE:
 | 
			
		||||
        s->regs[GEM_INT_Q8_MASK + offset - GEM_INT_Q8_DISABLE] |= val;
 | 
			
		||||
        gem_update_int_status(s);
 | 
			
		||||
        break;
 | 
			
		||||
    case GEM_SPADDR1LO:
 | 
			
		||||
    case GEM_SPADDR2LO:
 | 
			
		||||
    case GEM_SPADDR3LO:
 | 
			
		||||
@ -1202,8 +1444,11 @@ static const MemoryRegionOps gem_ops = {
 | 
			
		||||
 | 
			
		||||
static void gem_set_link(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    CadenceGEMState *s = qemu_get_nic_opaque(nc);
 | 
			
		||||
 | 
			
		||||
    DB_PRINT("\n");
 | 
			
		||||
    phy_update_link(qemu_get_nic_opaque(nc));
 | 
			
		||||
    phy_update_link(s);
 | 
			
		||||
    gem_update_int_status(s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static NetClientInfo net_gem_info = {
 | 
			
		||||
@ -1214,36 +1459,62 @@ static NetClientInfo net_gem_info = {
 | 
			
		||||
    .link_status_changed = gem_set_link,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int gem_init(SysBusDevice *sbd)
 | 
			
		||||
static void gem_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    DeviceState *dev = DEVICE(sbd);
 | 
			
		||||
    CadenceGEMState *s = CADENCE_GEM(dev);
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    if (s->num_priority_queues == 0 ||
 | 
			
		||||
        s->num_priority_queues > MAX_PRIORITY_QUEUES) {
 | 
			
		||||
        error_setg(errp, "Invalid num-priority-queues value: %" PRIx8,
 | 
			
		||||
                   s->num_priority_queues);
 | 
			
		||||
        return;
 | 
			
		||||
    } else if (s->num_type1_screeners > MAX_TYPE1_SCREENERS) {
 | 
			
		||||
        error_setg(errp, "Invalid num-type1-screeners value: %" PRIx8,
 | 
			
		||||
                   s->num_type1_screeners);
 | 
			
		||||
        return;
 | 
			
		||||
    } else if (s->num_type2_screeners > MAX_TYPE2_SCREENERS) {
 | 
			
		||||
        error_setg(errp, "Invalid num-type2-screeners value: %" PRIx8,
 | 
			
		||||
                   s->num_type2_screeners);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < s->num_priority_queues; ++i) {
 | 
			
		||||
        sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qemu_macaddr_default_if_unset(&s->conf.macaddr);
 | 
			
		||||
 | 
			
		||||
    s->nic = qemu_new_nic(&net_gem_info, &s->conf,
 | 
			
		||||
                          object_get_typename(OBJECT(dev)), dev->id, s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gem_init(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    CadenceGEMState *s = CADENCE_GEM(obj);
 | 
			
		||||
    DeviceState *dev = DEVICE(obj);
 | 
			
		||||
 | 
			
		||||
    DB_PRINT("\n");
 | 
			
		||||
 | 
			
		||||
    gem_init_register_masks(s);
 | 
			
		||||
    memory_region_init_io(&s->iomem, OBJECT(s), &gem_ops, s,
 | 
			
		||||
                          "enet", sizeof(s->regs));
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->iomem);
 | 
			
		||||
    sysbus_init_irq(sbd, &s->irq);
 | 
			
		||||
    qemu_macaddr_default_if_unset(&s->conf.macaddr);
 | 
			
		||||
 | 
			
		||||
    s->nic = qemu_new_nic(&net_gem_info, &s->conf,
 | 
			
		||||
            object_get_typename(OBJECT(dev)), dev->id, s);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const VMStateDescription vmstate_cadence_gem = {
 | 
			
		||||
    .name = "cadence_gem",
 | 
			
		||||
    .version_id = 2,
 | 
			
		||||
    .minimum_version_id = 2,
 | 
			
		||||
    .version_id = 4,
 | 
			
		||||
    .minimum_version_id = 4,
 | 
			
		||||
    .fields = (VMStateField[]) {
 | 
			
		||||
        VMSTATE_UINT32_ARRAY(regs, CadenceGEMState, CADENCE_GEM_MAXREG),
 | 
			
		||||
        VMSTATE_UINT16_ARRAY(phy_regs, CadenceGEMState, 32),
 | 
			
		||||
        VMSTATE_UINT8(phy_loop, CadenceGEMState),
 | 
			
		||||
        VMSTATE_UINT32(rx_desc_addr, CadenceGEMState),
 | 
			
		||||
        VMSTATE_UINT32(tx_desc_addr, CadenceGEMState),
 | 
			
		||||
        VMSTATE_UINT32_ARRAY(rx_desc_addr, CadenceGEMState,
 | 
			
		||||
                             MAX_PRIORITY_QUEUES),
 | 
			
		||||
        VMSTATE_UINT32_ARRAY(tx_desc_addr, CadenceGEMState,
 | 
			
		||||
                             MAX_PRIORITY_QUEUES),
 | 
			
		||||
        VMSTATE_BOOL_ARRAY(sar_active, CadenceGEMState, 4),
 | 
			
		||||
        VMSTATE_END_OF_LIST(),
 | 
			
		||||
    }
 | 
			
		||||
@ -1251,15 +1522,20 @@ static const VMStateDescription vmstate_cadence_gem = {
 | 
			
		||||
 | 
			
		||||
static Property gem_properties[] = {
 | 
			
		||||
    DEFINE_NIC_PROPERTIES(CadenceGEMState, conf),
 | 
			
		||||
    DEFINE_PROP_UINT8("num-priority-queues", CadenceGEMState,
 | 
			
		||||
                      num_priority_queues, 1),
 | 
			
		||||
    DEFINE_PROP_UINT8("num-type1-screeners", CadenceGEMState,
 | 
			
		||||
                      num_type1_screeners, 4),
 | 
			
		||||
    DEFINE_PROP_UINT8("num-type2-screeners", CadenceGEMState,
 | 
			
		||||
                      num_type2_screeners, 4),
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void gem_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(klass);
 | 
			
		||||
    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    sdc->init = gem_init;
 | 
			
		||||
    dc->realize = gem_realize;
 | 
			
		||||
    dc->props = gem_properties;
 | 
			
		||||
    dc->vmsd = &vmstate_cadence_gem;
 | 
			
		||||
    dc->reset = gem_reset;
 | 
			
		||||
@ -1269,6 +1545,7 @@ static const TypeInfo gem_info = {
 | 
			
		||||
    .name  = TYPE_CADENCE_GEM,
 | 
			
		||||
    .parent = TYPE_SYS_BUS_DEVICE,
 | 
			
		||||
    .instance_size  = sizeof(CadenceGEMState),
 | 
			
		||||
    .instance_init = gem_init,
 | 
			
		||||
    .class_init = gem_class_init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -387,7 +387,7 @@ static void etsec_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    etsec->bh     = qemu_bh_new(etsec_timer_hit, etsec);
 | 
			
		||||
    etsec->ptimer = ptimer_init(etsec->bh);
 | 
			
		||||
    etsec->ptimer = ptimer_init(etsec->bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
    ptimer_set_freq(etsec->ptimer, 100);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1345,7 +1345,7 @@ static int lan9118_init1(SysBusDevice *sbd)
 | 
			
		||||
    s->txp = &s->tx_packet;
 | 
			
		||||
 | 
			
		||||
    bh = qemu_bh_new(lan9118_tick, s);
 | 
			
		||||
    s->timer = ptimer_init(bh);
 | 
			
		||||
    s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
    ptimer_set_freq(s->timer, 10000);
 | 
			
		||||
    ptimer_set_limit(s->timer, 0xffff, 1);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -31,7 +31,7 @@ do { fprintf(stderr, "ssi_sd: error: " fmt , ## __VA_ARGS__);} while (0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    SSI_SD_CMD,
 | 
			
		||||
    SSI_SD_CMD = 0,
 | 
			
		||||
    SSI_SD_CMDARG,
 | 
			
		||||
    SSI_SD_RESPONSE,
 | 
			
		||||
    SSI_SD_DATA_START,
 | 
			
		||||
@ -40,13 +40,13 @@ typedef enum {
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    SSISlave ssidev;
 | 
			
		||||
    ssi_sd_mode mode;
 | 
			
		||||
    uint32_t mode;
 | 
			
		||||
    int cmd;
 | 
			
		||||
    uint8_t cmdarg[4];
 | 
			
		||||
    uint8_t response[5];
 | 
			
		||||
    int arglen;
 | 
			
		||||
    int response_pos;
 | 
			
		||||
    int stopping;
 | 
			
		||||
    int32_t arglen;
 | 
			
		||||
    int32_t response_pos;
 | 
			
		||||
    int32_t stopping;
 | 
			
		||||
    SDState *sd;
 | 
			
		||||
} ssi_sd_state;
 | 
			
		||||
 | 
			
		||||
@ -198,61 +198,46 @@ static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val)
 | 
			
		||||
    return 0xff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ssi_sd_save(QEMUFile *f, void *opaque)
 | 
			
		||||
static int ssi_sd_post_load(void *opaque, int version_id)
 | 
			
		||||
{
 | 
			
		||||
    SSISlave *ss = SSI_SLAVE(opaque);
 | 
			
		||||
    ssi_sd_state *s = (ssi_sd_state *)opaque;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    qemu_put_be32(f, s->mode);
 | 
			
		||||
    qemu_put_be32(f, s->cmd);
 | 
			
		||||
    for (i = 0; i < 4; i++)
 | 
			
		||||
        qemu_put_be32(f, s->cmdarg[i]);
 | 
			
		||||
    for (i = 0; i < 5; i++)
 | 
			
		||||
        qemu_put_be32(f, s->response[i]);
 | 
			
		||||
    qemu_put_be32(f, s->arglen);
 | 
			
		||||
    qemu_put_be32(f, s->response_pos);
 | 
			
		||||
    qemu_put_be32(f, s->stopping);
 | 
			
		||||
 | 
			
		||||
    qemu_put_be32(f, ss->cs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id)
 | 
			
		||||
{
 | 
			
		||||
    SSISlave *ss = SSI_SLAVE(opaque);
 | 
			
		||||
    ssi_sd_state *s = (ssi_sd_state *)opaque;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    if (version_id != 1)
 | 
			
		||||
    if (s->mode > SSI_SD_DATA_READ) {
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
 | 
			
		||||
    s->mode = qemu_get_be32(f);
 | 
			
		||||
    s->cmd = qemu_get_be32(f);
 | 
			
		||||
    for (i = 0; i < 4; i++)
 | 
			
		||||
        s->cmdarg[i] = qemu_get_be32(f);
 | 
			
		||||
    for (i = 0; i < 5; i++)
 | 
			
		||||
        s->response[i] = qemu_get_be32(f);
 | 
			
		||||
    s->arglen = qemu_get_be32(f);
 | 
			
		||||
    }
 | 
			
		||||
    if (s->mode == SSI_SD_CMDARG &&
 | 
			
		||||
        (s->arglen < 0 || s->arglen >= ARRAY_SIZE(s->cmdarg))) {
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
    }
 | 
			
		||||
    s->response_pos = qemu_get_be32(f);
 | 
			
		||||
    s->stopping = qemu_get_be32(f);
 | 
			
		||||
    if (s->mode == SSI_SD_RESPONSE &&
 | 
			
		||||
        (s->response_pos < 0 || s->response_pos >= ARRAY_SIZE(s->response) ||
 | 
			
		||||
        (!s->stopping && s->arglen > ARRAY_SIZE(s->response)))) {
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ss->cs = qemu_get_be32(f);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const VMStateDescription vmstate_ssi_sd = {
 | 
			
		||||
    .name = "ssi_sd",
 | 
			
		||||
    .version_id = 2,
 | 
			
		||||
    .minimum_version_id = 2,
 | 
			
		||||
    .post_load = ssi_sd_post_load,
 | 
			
		||||
    .fields = (VMStateField []) {
 | 
			
		||||
        VMSTATE_UINT32(mode, ssi_sd_state),
 | 
			
		||||
        VMSTATE_INT32(cmd, ssi_sd_state),
 | 
			
		||||
        VMSTATE_UINT8_ARRAY(cmdarg, ssi_sd_state, 4),
 | 
			
		||||
        VMSTATE_UINT8_ARRAY(response, ssi_sd_state, 5),
 | 
			
		||||
        VMSTATE_INT32(arglen, ssi_sd_state),
 | 
			
		||||
        VMSTATE_INT32(response_pos, ssi_sd_state),
 | 
			
		||||
        VMSTATE_INT32(stopping, ssi_sd_state),
 | 
			
		||||
        VMSTATE_SSI_SLAVE(ssidev, ssi_sd_state),
 | 
			
		||||
        VMSTATE_END_OF_LIST()
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void ssi_sd_realize(SSISlave *d, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    DeviceState *dev = DEVICE(d);
 | 
			
		||||
    ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, d);
 | 
			
		||||
    DriveInfo *dinfo;
 | 
			
		||||
 | 
			
		||||
@ -264,16 +249,17 @@ static void ssi_sd_realize(SSISlave *d, Error **errp)
 | 
			
		||||
        error_setg(errp, "Device initialization failed.");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    register_savevm(dev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ssi_sd_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(klass);
 | 
			
		||||
    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    k->realize = ssi_sd_realize;
 | 
			
		||||
    k->transfer = ssi_sd_transfer;
 | 
			
		||||
    k->cs_polarity = SSI_CS_LOW;
 | 
			
		||||
    dc->vmsd = &vmstate_ssi_sd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo ssi_sd_info = {
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,7 @@
 | 
			
		||||
        } \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
static char const *imx_spi_reg_name(uint32_t reg)
 | 
			
		||||
static const char *imx_spi_reg_name(uint32_t reg)
 | 
			
		||||
{
 | 
			
		||||
    static char unknown[20];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -267,7 +267,7 @@ static void a10_pit_init(Object *obj)
 | 
			
		||||
        tc->container = s;
 | 
			
		||||
        tc->index = i;
 | 
			
		||||
        bh[i] = qemu_bh_new(a10_pit_timer_cb, tc);
 | 
			
		||||
        s->timer[i] = ptimer_init(bh[i]);
 | 
			
		||||
        s->timer[i] = ptimer_init(bh[i], PTIMER_POLICY_DEFAULT);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -171,7 +171,7 @@ static arm_timer_state *arm_timer_init(uint32_t freq)
 | 
			
		||||
    s->control = TIMER_CTRL_IE;
 | 
			
		||||
 | 
			
		||||
    bh = qemu_bh_new(arm_timer_tick, s);
 | 
			
		||||
    s->timer = ptimer_init(bh);
 | 
			
		||||
    s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
    vmstate_register(NULL, -1, &vmstate_arm_timer, s);
 | 
			
		||||
    return s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -127,7 +127,7 @@ static void digic_timer_init(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    DigicTimerState *s = DIGIC_TIMER(obj);
 | 
			
		||||
 | 
			
		||||
    s->ptimer = ptimer_init(NULL);
 | 
			
		||||
    s->ptimer = ptimer_init(NULL, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * FIXME: there is no documentation on Digic timer
 | 
			
		||||
 | 
			
		||||
@ -322,9 +322,9 @@ static int etraxfs_timer_init(SysBusDevice *dev)
 | 
			
		||||
    t->bh_t0 = qemu_bh_new(timer0_hit, t);
 | 
			
		||||
    t->bh_t1 = qemu_bh_new(timer1_hit, t);
 | 
			
		||||
    t->bh_wd = qemu_bh_new(watchdog_hit, t);
 | 
			
		||||
    t->ptimer_t0 = ptimer_init(t->bh_t0);
 | 
			
		||||
    t->ptimer_t1 = ptimer_init(t->bh_t1);
 | 
			
		||||
    t->ptimer_wd = ptimer_init(t->bh_wd);
 | 
			
		||||
    t->ptimer_t0 = ptimer_init(t->bh_t0, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
    t->ptimer_t1 = ptimer_init(t->bh_t1, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
    t->ptimer_wd = ptimer_init(t->bh_wd, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
 | 
			
		||||
    sysbus_init_irq(dev, &t->irq);
 | 
			
		||||
    sysbus_init_irq(dev, &t->nmi);
 | 
			
		||||
 | 
			
		||||
@ -1431,15 +1431,16 @@ static void exynos4210_mct_init(Object *obj)
 | 
			
		||||
 | 
			
		||||
    /* Global timer */
 | 
			
		||||
    bh[0] = qemu_bh_new(exynos4210_gfrc_event, s);
 | 
			
		||||
    s->g_timer.ptimer_frc = ptimer_init(bh[0]);
 | 
			
		||||
    s->g_timer.ptimer_frc = ptimer_init(bh[0], PTIMER_POLICY_DEFAULT);
 | 
			
		||||
    memset(&s->g_timer.reg, 0, sizeof(struct gregs));
 | 
			
		||||
 | 
			
		||||
    /* Local timers */
 | 
			
		||||
    for (i = 0; i < 2; i++) {
 | 
			
		||||
        bh[0] = qemu_bh_new(exynos4210_ltick_event, &s->l_timer[i]);
 | 
			
		||||
        bh[1] = qemu_bh_new(exynos4210_lfrc_event, &s->l_timer[i]);
 | 
			
		||||
        s->l_timer[i].tick_timer.ptimer_tick = ptimer_init(bh[0]);
 | 
			
		||||
        s->l_timer[i].ptimer_frc = ptimer_init(bh[1]);
 | 
			
		||||
        s->l_timer[i].tick_timer.ptimer_tick =
 | 
			
		||||
                                   ptimer_init(bh[0], PTIMER_POLICY_DEFAULT);
 | 
			
		||||
        s->l_timer[i].ptimer_frc = ptimer_init(bh[1], PTIMER_POLICY_DEFAULT);
 | 
			
		||||
        s->l_timer[i].id = i;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -390,7 +390,7 @@ static void exynos4210_pwm_init(Object *obj)
 | 
			
		||||
    for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
 | 
			
		||||
        bh = qemu_bh_new(exynos4210_pwm_tick, &s->timer[i]);
 | 
			
		||||
        sysbus_init_irq(dev, &s->timer[i].irq);
 | 
			
		||||
        s->timer[i].ptimer = ptimer_init(bh);
 | 
			
		||||
        s->timer[i].ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
        s->timer[i].id = i;
 | 
			
		||||
        s->timer[i].parent = s;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -555,12 +555,12 @@ static void exynos4210_rtc_init(Object *obj)
 | 
			
		||||
    QEMUBH *bh;
 | 
			
		||||
 | 
			
		||||
    bh = qemu_bh_new(exynos4210_rtc_tick, s);
 | 
			
		||||
    s->ptimer = ptimer_init(bh);
 | 
			
		||||
    s->ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
    ptimer_set_freq(s->ptimer, RTC_BASE_FREQ);
 | 
			
		||||
    exynos4210_rtc_update_freq(s, 0);
 | 
			
		||||
 | 
			
		||||
    bh = qemu_bh_new(exynos4210_rtc_1Hz_tick, s);
 | 
			
		||||
    s->ptimer_1Hz = ptimer_init(bh);
 | 
			
		||||
    s->ptimer_1Hz = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
    ptimer_set_freq(s->ptimer_1Hz, RTC_BASE_FREQ);
 | 
			
		||||
 | 
			
		||||
    sysbus_init_irq(dev, &s->alm_irq);
 | 
			
		||||
 | 
			
		||||
@ -363,7 +363,7 @@ static int grlib_gptimer_init(SysBusDevice *dev)
 | 
			
		||||
 | 
			
		||||
        timer->unit   = unit;
 | 
			
		||||
        timer->bh     = qemu_bh_new(grlib_gptimer_hit, timer);
 | 
			
		||||
        timer->ptimer = ptimer_init(timer->bh);
 | 
			
		||||
        timer->ptimer = ptimer_init(timer->bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
        timer->id     = i;
 | 
			
		||||
 | 
			
		||||
        /* One IRQ line for each timer */
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,7 @@
 | 
			
		||||
        } \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
static char const *imx_epit_reg_name(uint32_t reg)
 | 
			
		||||
static const char *imx_epit_reg_name(uint32_t reg)
 | 
			
		||||
{
 | 
			
		||||
    switch (reg) {
 | 
			
		||||
    case 0:
 | 
			
		||||
@ -314,10 +314,10 @@ static void imx_epit_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
                          0x00001000);
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->iomem);
 | 
			
		||||
 | 
			
		||||
    s->timer_reload = ptimer_init(NULL);
 | 
			
		||||
    s->timer_reload = ptimer_init(NULL, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
 | 
			
		||||
    bh = qemu_bh_new(imx_epit_cmp, s);
 | 
			
		||||
    s->timer_cmp = ptimer_init(bh);
 | 
			
		||||
    s->timer_cmp = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void imx_epit_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
 | 
			
		||||
@ -29,7 +29,7 @@
 | 
			
		||||
        } \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
static char const *imx_gpt_reg_name(uint32_t reg)
 | 
			
		||||
static const char *imx_gpt_reg_name(uint32_t reg)
 | 
			
		||||
{
 | 
			
		||||
    switch (reg) {
 | 
			
		||||
    case 0:
 | 
			
		||||
@ -461,7 +461,7 @@ static void imx_gpt_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->iomem);
 | 
			
		||||
 | 
			
		||||
    bh = qemu_bh_new(imx_gpt_timeout, s);
 | 
			
		||||
    s->timer = ptimer_init(bh);
 | 
			
		||||
    s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void imx_gpt_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
 | 
			
		||||
@ -184,7 +184,7 @@ static void lm32_timer_init(Object *obj)
 | 
			
		||||
    sysbus_init_irq(dev, &s->irq);
 | 
			
		||||
 | 
			
		||||
    s->bh = qemu_bh_new(timer_hit, s);
 | 
			
		||||
    s->ptimer = ptimer_init(s->bh);
 | 
			
		||||
    s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
 | 
			
		||||
    memory_region_init_io(&s->iomem, obj, &timer_ops, s,
 | 
			
		||||
                          "timer", R_MAX * 4);
 | 
			
		||||
 | 
			
		||||
@ -281,8 +281,8 @@ static void milkymist_sysctl_init(Object *obj)
 | 
			
		||||
 | 
			
		||||
    s->bh0 = qemu_bh_new(timer0_hit, s);
 | 
			
		||||
    s->bh1 = qemu_bh_new(timer1_hit, s);
 | 
			
		||||
    s->ptimer0 = ptimer_init(s->bh0);
 | 
			
		||||
    s->ptimer1 = ptimer_init(s->bh1);
 | 
			
		||||
    s->ptimer0 = ptimer_init(s->bh0, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
    s->ptimer1 = ptimer_init(s->bh1, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
 | 
			
		||||
    memory_region_init_io(&s->regs_region, obj, &sysctl_mmio_ops, s,
 | 
			
		||||
            "milkymist-sysctl", R_MAX * 4);
 | 
			
		||||
 | 
			
		||||
@ -125,7 +125,7 @@ static int puv3_ost_init(SysBusDevice *dev)
 | 
			
		||||
    sysbus_init_irq(dev, &s->irq);
 | 
			
		||||
 | 
			
		||||
    s->bh = qemu_bh_new(puv3_ost_tick, s);
 | 
			
		||||
    s->ptimer = ptimer_init(s->bh);
 | 
			
		||||
    s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
    ptimer_set_freq(s->ptimer, 50 * 1000 * 1000);
 | 
			
		||||
 | 
			
		||||
    memory_region_init_io(&s->iomem, OBJECT(s), &puv3_ost_ops, s, "puv3_ost",
 | 
			
		||||
 | 
			
		||||
@ -203,7 +203,7 @@ static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq)
 | 
			
		||||
    s->irq = irq;
 | 
			
		||||
 | 
			
		||||
    bh = qemu_bh_new(sh_timer_tick, s);
 | 
			
		||||
    s->timer = ptimer_init(bh);
 | 
			
		||||
    s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
 | 
			
		||||
    sh_timer_write(s, OFFSET_TCOR >> 2, s->tcor);
 | 
			
		||||
    sh_timer_write(s, OFFSET_TCNT >> 2, s->tcnt);
 | 
			
		||||
 | 
			
		||||
@ -389,7 +389,7 @@ static int slavio_timer_init1(SysBusDevice *dev)
 | 
			
		||||
        tc->timer_index = i;
 | 
			
		||||
 | 
			
		||||
        bh = qemu_bh_new(slavio_timer_irq, tc);
 | 
			
		||||
        s->cputimer[i].timer = ptimer_init(bh);
 | 
			
		||||
        s->cputimer[i].timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
        ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
 | 
			
		||||
 | 
			
		||||
        size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE;
 | 
			
		||||
 | 
			
		||||
@ -218,7 +218,7 @@ static void xilinx_timer_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
        xt->parent = t;
 | 
			
		||||
        xt->nr = i;
 | 
			
		||||
        xt->bh = qemu_bh_new(timer_hit, xt);
 | 
			
		||||
        xt->ptimer = ptimer_init(xt->bh);
 | 
			
		||||
        xt->ptimer = ptimer_init(xt->bh, PTIMER_POLICY_DEFAULT);
 | 
			
		||||
        ptimer_set_freq(xt->ptimer, t->freq_hz);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										59
									
								
								include/hw/arm/aspeed_soc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								include/hw/arm/aspeed_soc.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,59 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ASPEED SoC family
 | 
			
		||||
 *
 | 
			
		||||
 * Andrew Jeffery <andrew@aj.id.au>
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2016 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * This code is licensed under the GPL version 2 or later.  See
 | 
			
		||||
 * the COPYING file in the top-level directory.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef ASPEED_SOC_H
 | 
			
		||||
#define ASPEED_SOC_H
 | 
			
		||||
 | 
			
		||||
#include "hw/arm/arm.h"
 | 
			
		||||
#include "hw/intc/aspeed_vic.h"
 | 
			
		||||
#include "hw/misc/aspeed_scu.h"
 | 
			
		||||
#include "hw/misc/aspeed_sdmc.h"
 | 
			
		||||
#include "hw/timer/aspeed_timer.h"
 | 
			
		||||
#include "hw/i2c/aspeed_i2c.h"
 | 
			
		||||
#include "hw/ssi/aspeed_smc.h"
 | 
			
		||||
 | 
			
		||||
typedef struct AspeedSoCState {
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    DeviceState parent;
 | 
			
		||||
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
    ARMCPU *cpu;
 | 
			
		||||
    MemoryRegion iomem;
 | 
			
		||||
    AspeedVICState vic;
 | 
			
		||||
    AspeedTimerCtrlState timerctrl;
 | 
			
		||||
    AspeedI2CState i2c;
 | 
			
		||||
    AspeedSCUState scu;
 | 
			
		||||
    AspeedSMCState smc;
 | 
			
		||||
    AspeedSMCState spi;
 | 
			
		||||
    AspeedSDMCState sdmc;
 | 
			
		||||
} AspeedSoCState;
 | 
			
		||||
 | 
			
		||||
#define TYPE_ASPEED_SOC "aspeed-soc"
 | 
			
		||||
#define ASPEED_SOC(obj) OBJECT_CHECK(AspeedSoCState, (obj), TYPE_ASPEED_SOC)
 | 
			
		||||
 | 
			
		||||
typedef struct AspeedSoCInfo {
 | 
			
		||||
    const char *name;
 | 
			
		||||
    const char *cpu_model;
 | 
			
		||||
    uint32_t silicon_rev;
 | 
			
		||||
    hwaddr sdram_base;
 | 
			
		||||
} AspeedSoCInfo;
 | 
			
		||||
 | 
			
		||||
typedef struct AspeedSoCClass {
 | 
			
		||||
    DeviceClass parent_class;
 | 
			
		||||
    AspeedSoCInfo *info;
 | 
			
		||||
} AspeedSoCClass;
 | 
			
		||||
 | 
			
		||||
#define ASPEED_SOC_CLASS(klass)                                         \
 | 
			
		||||
    OBJECT_CLASS_CHECK(AspeedSoCClass, (klass), TYPE_ASPEED_SOC)
 | 
			
		||||
#define ASPEED_SOC_GET_CLASS(obj)                               \
 | 
			
		||||
    OBJECT_GET_CLASS(AspeedSoCClass, (obj), TYPE_ASPEED_SOC)
 | 
			
		||||
 | 
			
		||||
#endif /* ASPEED_SOC_H */
 | 
			
		||||
@ -1,44 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ASPEED AST2400 SoC
 | 
			
		||||
 *
 | 
			
		||||
 * Andrew Jeffery <andrew@aj.id.au>
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2016 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * This code is licensed under the GPL version 2 or later.  See
 | 
			
		||||
 * the COPYING file in the top-level directory.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef AST2400_H
 | 
			
		||||
#define AST2400_H
 | 
			
		||||
 | 
			
		||||
#include "hw/arm/arm.h"
 | 
			
		||||
#include "hw/intc/aspeed_vic.h"
 | 
			
		||||
#include "hw/misc/aspeed_scu.h"
 | 
			
		||||
#include "hw/misc/aspeed_sdmc.h"
 | 
			
		||||
#include "hw/timer/aspeed_timer.h"
 | 
			
		||||
#include "hw/i2c/aspeed_i2c.h"
 | 
			
		||||
#include "hw/ssi/aspeed_smc.h"
 | 
			
		||||
 | 
			
		||||
typedef struct AST2400State {
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    DeviceState parent;
 | 
			
		||||
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
    ARMCPU *cpu;
 | 
			
		||||
    MemoryRegion iomem;
 | 
			
		||||
    AspeedVICState vic;
 | 
			
		||||
    AspeedTimerCtrlState timerctrl;
 | 
			
		||||
    AspeedI2CState i2c;
 | 
			
		||||
    AspeedSCUState scu;
 | 
			
		||||
    AspeedSMCState smc;
 | 
			
		||||
    AspeedSMCState spi;
 | 
			
		||||
    AspeedSDMCState sdmc;
 | 
			
		||||
} AST2400State;
 | 
			
		||||
 | 
			
		||||
#define TYPE_AST2400 "ast2400"
 | 
			
		||||
#define AST2400(obj) OBJECT_CHECK(AST2400State, (obj), TYPE_AST2400)
 | 
			
		||||
 | 
			
		||||
#define AST2400_SDRAM_BASE       0x40000000
 | 
			
		||||
 | 
			
		||||
#endif /* AST2400_H */
 | 
			
		||||
@ -34,7 +34,7 @@
 | 
			
		||||
#define XLNX_ZYNQ_DEVCFG(obj) \
 | 
			
		||||
    OBJECT_CHECK(XlnxZynqDevcfg, (obj), TYPE_XLNX_ZYNQ_DEVCFG)
 | 
			
		||||
 | 
			
		||||
#define XLNX_ZYNQ_DEVCFG_R_MAX 0x118
 | 
			
		||||
#define XLNX_ZYNQ_DEVCFG_R_MAX (0x100 / 4)
 | 
			
		||||
 | 
			
		||||
#define XLNX_ZYNQ_DEVCFG_DMA_CMD_FIFO_LEN 10
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -263,7 +263,8 @@ static int glue(load_elf, SZ)(const char *name, int fd,
 | 
			
		||||
                              void *translate_opaque,
 | 
			
		||||
                              int must_swab, uint64_t *pentry,
 | 
			
		||||
                              uint64_t *lowaddr, uint64_t *highaddr,
 | 
			
		||||
                              int elf_machine, int clear_lsb, int data_swab)
 | 
			
		||||
                              int elf_machine, int clear_lsb, int data_swab,
 | 
			
		||||
                              AddressSpace *as)
 | 
			
		||||
{
 | 
			
		||||
    struct elfhdr ehdr;
 | 
			
		||||
    struct elf_phdr *phdr = NULL, *ph;
 | 
			
		||||
@ -280,6 +281,11 @@ static int glue(load_elf, SZ)(const char *name, int fd,
 | 
			
		||||
        glue(bswap_ehdr, SZ)(&ehdr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (elf_machine <= EM_NONE) {
 | 
			
		||||
        /* The caller didn't specify an ARCH, we can figure it out */
 | 
			
		||||
        elf_machine = ehdr.e_machine;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    switch (elf_machine) {
 | 
			
		||||
        case EM_PPC64:
 | 
			
		||||
            if (ehdr.e_machine != EM_PPC64) {
 | 
			
		||||
@ -400,7 +406,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
 | 
			
		||||
            snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
 | 
			
		||||
 | 
			
		||||
            /* rom_add_elf_program() seize the ownership of 'data' */
 | 
			
		||||
            rom_add_elf_program(label, data, file_size, mem_size, addr);
 | 
			
		||||
            rom_add_elf_program(label, data, file_size, mem_size, addr, as);
 | 
			
		||||
 | 
			
		||||
            total_size += mem_size;
 | 
			
		||||
            if (addr < low)
 | 
			
		||||
 | 
			
		||||
@ -14,8 +14,28 @@
 | 
			
		||||
int get_image_size(const char *filename);
 | 
			
		||||
int load_image(const char *filename, uint8_t *addr); /* deprecated */
 | 
			
		||||
ssize_t load_image_size(const char *filename, void *addr, size_t size);
 | 
			
		||||
 | 
			
		||||
/**load_image_targphys_as:
 | 
			
		||||
 * @filename: Path to the image file
 | 
			
		||||
 * @addr: Address to load the image to
 | 
			
		||||
 * @max_sz: The maximum size of the image to load
 | 
			
		||||
 * @as: The AddressSpace to load the ELF to. The value of address_space_memory
 | 
			
		||||
 *      is used if nothing is supplied here.
 | 
			
		||||
 *
 | 
			
		||||
 * Load a fixed image into memory.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns the size of the loaded image on success, -1 otherwise.
 | 
			
		||||
 */
 | 
			
		||||
int load_image_targphys_as(const char *filename,
 | 
			
		||||
                           hwaddr addr, uint64_t max_sz, AddressSpace *as);
 | 
			
		||||
 | 
			
		||||
/** load_image_targphys:
 | 
			
		||||
 * Same as load_image_targphys_as(), but doesn't allow the caller to specify
 | 
			
		||||
 * an AddressSpace.
 | 
			
		||||
 */
 | 
			
		||||
int load_image_targphys(const char *filename, hwaddr,
 | 
			
		||||
                        uint64_t max_sz);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * load_image_mr: load an image into a memory region
 | 
			
		||||
 * @filename: Path to the image file
 | 
			
		||||
@ -45,7 +65,7 @@ int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
 | 
			
		||||
#define ELF_LOAD_WRONG_ENDIAN -4
 | 
			
		||||
const char *load_elf_strerror(int error);
 | 
			
		||||
 | 
			
		||||
/** load_elf:
 | 
			
		||||
/** load_elf_as:
 | 
			
		||||
 * @filename: Path of ELF file
 | 
			
		||||
 * @translate_fn: optional function to translate load addresses
 | 
			
		||||
 * @translate_opaque: opaque data passed to @translate_fn
 | 
			
		||||
@ -59,6 +79,8 @@ const char *load_elf_strerror(int error);
 | 
			
		||||
 * @data_swab: Set to order of byte swapping for data. 0 for no swap, 1
 | 
			
		||||
 *             for swapping bytes within halfwords, 2 for bytes within
 | 
			
		||||
 *             words and 3 for within doublewords.
 | 
			
		||||
 * @as: The AddressSpace to load the ELF to. The value of address_space_memory
 | 
			
		||||
 *      is used if nothing is supplied here.
 | 
			
		||||
 *
 | 
			
		||||
 * Load an ELF file's contents to the emulated system's address space.
 | 
			
		||||
 * Clients may optionally specify a callback to perform address
 | 
			
		||||
@ -68,8 +90,19 @@ const char *load_elf_strerror(int error);
 | 
			
		||||
 * load will fail if the target ELF does not match. Some architectures
 | 
			
		||||
 * have some architecture-specific behaviours that come into effect when
 | 
			
		||||
 * their particular values for @elf_machine are set.
 | 
			
		||||
 * If @elf_machine is EM_NONE then the machine type will be read from the
 | 
			
		||||
 * ELF header and no checks will be carried out against the machine type.
 | 
			
		||||
 */
 | 
			
		||||
int load_elf_as(const char *filename,
 | 
			
		||||
                uint64_t (*translate_fn)(void *, uint64_t),
 | 
			
		||||
                void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
 | 
			
		||||
                uint64_t *highaddr, int big_endian, int elf_machine,
 | 
			
		||||
                int clear_lsb, int data_swab, AddressSpace *as);
 | 
			
		||||
 | 
			
		||||
/** load_elf:
 | 
			
		||||
 * Same as load_elf_as(), but doesn't allow the caller to specify an
 | 
			
		||||
 * AddressSpace.
 | 
			
		||||
 */
 | 
			
		||||
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
 | 
			
		||||
             void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
 | 
			
		||||
             uint64_t *highaddr, int big_endian, int elf_machine,
 | 
			
		||||
@ -89,6 +122,30 @@ void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
 | 
			
		||||
 | 
			
		||||
int load_aout(const char *filename, hwaddr addr, int max_sz,
 | 
			
		||||
              int bswap_needed, hwaddr target_page_size);
 | 
			
		||||
 | 
			
		||||
/** load_uimage_as:
 | 
			
		||||
 * @filename: Path of uimage file
 | 
			
		||||
 * @ep: Populated with program entry point. Ignored if NULL.
 | 
			
		||||
 * @loadaddr: Populated with the load address. Ignored if NULL.
 | 
			
		||||
 * @is_linux: Is set to true if the image loaded is Linux. Ignored if NULL.
 | 
			
		||||
 * @translate_fn: optional function to translate load addresses
 | 
			
		||||
 * @translate_opaque: opaque data passed to @translate_fn
 | 
			
		||||
 * @as: The AddressSpace to load the ELF to. The value of address_space_memory
 | 
			
		||||
 *      is used if nothing is supplied here.
 | 
			
		||||
 *
 | 
			
		||||
 * Loads a u-boot image into memory.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns the size of the loaded image on success, -1 otherwise.
 | 
			
		||||
 */
 | 
			
		||||
int load_uimage_as(const char *filename, hwaddr *ep,
 | 
			
		||||
                   hwaddr *loadaddr, int *is_linux,
 | 
			
		||||
                   uint64_t (*translate_fn)(void *, uint64_t),
 | 
			
		||||
                   void *translate_opaque, AddressSpace *as);
 | 
			
		||||
 | 
			
		||||
/** load_uimage:
 | 
			
		||||
 * Same as load_uimage_as(), but doesn't allow the caller to specify an
 | 
			
		||||
 * AddressSpace.
 | 
			
		||||
 */
 | 
			
		||||
int load_uimage(const char *filename, hwaddr *ep,
 | 
			
		||||
                hwaddr *loadaddr, int *is_linux,
 | 
			
		||||
                uint64_t (*translate_fn)(void *, uint64_t),
 | 
			
		||||
@ -118,14 +175,14 @@ extern bool rom_file_has_mr;
 | 
			
		||||
 | 
			
		||||
int rom_add_file(const char *file, const char *fw_dir,
 | 
			
		||||
                 hwaddr addr, int32_t bootindex,
 | 
			
		||||
                 bool option_rom, MemoryRegion *mr);
 | 
			
		||||
                 bool option_rom, MemoryRegion *mr, AddressSpace *as);
 | 
			
		||||
MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
 | 
			
		||||
                           size_t max_len, hwaddr addr,
 | 
			
		||||
                           const char *fw_file_name,
 | 
			
		||||
                           FWCfgReadCallback fw_callback,
 | 
			
		||||
                           void *callback_opaque);
 | 
			
		||||
int rom_add_elf_program(const char *name, void *data, size_t datasize,
 | 
			
		||||
                        size_t romsize, hwaddr addr);
 | 
			
		||||
                        size_t romsize, hwaddr addr, AddressSpace *as);
 | 
			
		||||
int rom_check_and_register_reset(void);
 | 
			
		||||
void rom_set_fw(FWCfgState *f);
 | 
			
		||||
void rom_set_order_override(int order);
 | 
			
		||||
@ -135,11 +192,17 @@ void *rom_ptr(hwaddr addr);
 | 
			
		||||
void hmp_info_roms(Monitor *mon, const QDict *qdict);
 | 
			
		||||
 | 
			
		||||
#define rom_add_file_fixed(_f, _a, _i)          \
 | 
			
		||||
    rom_add_file(_f, NULL, _a, _i, false, NULL)
 | 
			
		||||
    rom_add_file(_f, NULL, _a, _i, false, NULL, NULL)
 | 
			
		||||
#define rom_add_blob_fixed(_f, _b, _l, _a)      \
 | 
			
		||||
    rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, NULL)
 | 
			
		||||
#define rom_add_file_mr(_f, _mr, _i)            \
 | 
			
		||||
    rom_add_file(_f, NULL, 0, _i, false, _mr)
 | 
			
		||||
    rom_add_file(_f, NULL, 0, _i, false, _mr, NULL)
 | 
			
		||||
#define rom_add_file_as(_f, _as, _i)            \
 | 
			
		||||
    rom_add_file(_f, NULL, 0, _i, false, NULL, _as)
 | 
			
		||||
#define rom_add_file_fixed_as(_f, _a, _i, _as)          \
 | 
			
		||||
    rom_add_file(_f, NULL, _a, _i, false, NULL, _as)
 | 
			
		||||
#define rom_add_blob_fixed_as(_f, _b, _l, _a, _as)      \
 | 
			
		||||
    rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, _as)
 | 
			
		||||
 | 
			
		||||
#define PC_ROM_MIN_VGA     0xc0000
 | 
			
		||||
#define PC_ROM_MIN_OPTION  0xc8000
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,200 @@ typedef struct AspeedSCUState {
 | 
			
		||||
 | 
			
		||||
#define AST2400_A0_SILICON_REV   0x02000303U
 | 
			
		||||
#define AST2500_A0_SILICON_REV   0x04000303U
 | 
			
		||||
#define AST2500_A1_SILICON_REV   0x04010303U
 | 
			
		||||
 | 
			
		||||
extern bool is_supported_silicon_rev(uint32_t silicon_rev);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Extracted from Aspeed SDK v00.03.21. Fixes and extra definitions
 | 
			
		||||
 * were added.
 | 
			
		||||
 *
 | 
			
		||||
 * Original header file :
 | 
			
		||||
 *    arch/arm/mach-aspeed/include/mach/regs-scu.h
 | 
			
		||||
 *
 | 
			
		||||
 *    Copyright (C) 2012-2020  ASPEED Technology Inc.
 | 
			
		||||
 *
 | 
			
		||||
 *    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.
 | 
			
		||||
 *
 | 
			
		||||
 *      History      :
 | 
			
		||||
 *       1. 2012/12/29 Ryan Chen Create
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Hardware Strapping Register definition (for Aspeed AST2400 SOC)
 | 
			
		||||
 *
 | 
			
		||||
 * 31:29  Software defined strapping registers
 | 
			
		||||
 * 28:27  DRAM size setting (for VGA driver use)
 | 
			
		||||
 * 26:24  DRAM configuration setting
 | 
			
		||||
 * 23     Enable 25 MHz reference clock input
 | 
			
		||||
 * 22     Enable GPIOE pass-through mode
 | 
			
		||||
 * 21     Enable GPIOD pass-through mode
 | 
			
		||||
 * 20     Disable LPC to decode SuperIO 0x2E/0x4E address
 | 
			
		||||
 * 19     Disable ACPI function
 | 
			
		||||
 * 23,18  Clock source selection
 | 
			
		||||
 * 17     Enable BMC 2nd boot watchdog timer
 | 
			
		||||
 * 16     SuperIO configuration address selection
 | 
			
		||||
 * 15     VGA Class Code selection
 | 
			
		||||
 * 14     Enable LPC dedicated reset pin function
 | 
			
		||||
 * 13:12  SPI mode selection
 | 
			
		||||
 * 11:10  CPU/AHB clock frequency ratio selection
 | 
			
		||||
 * 9:8    H-PLL default clock frequency selection
 | 
			
		||||
 * 7      Define MAC#2 interface
 | 
			
		||||
 * 6      Define MAC#1 interface
 | 
			
		||||
 * 5      Enable VGA BIOS ROM
 | 
			
		||||
 * 4      Boot flash memory extended option
 | 
			
		||||
 * 3:2    VGA memory size selection
 | 
			
		||||
 * 1:0    BMC CPU boot code selection
 | 
			
		||||
 */
 | 
			
		||||
#define SCU_AST2400_HW_STRAP_SW_DEFINE(x)          ((x) << 29)
 | 
			
		||||
#define SCU_AST2400_HW_STRAP_SW_DEFINE_MASK        (0x7 << 29)
 | 
			
		||||
 | 
			
		||||
#define SCU_AST2400_HW_STRAP_DRAM_SIZE(x)          ((x) << 27)
 | 
			
		||||
#define SCU_AST2400_HW_STRAP_DRAM_SIZE_MASK        (0x3 << 27)
 | 
			
		||||
#define     DRAM_SIZE_64MB                             0
 | 
			
		||||
#define     DRAM_SIZE_128MB                            1
 | 
			
		||||
#define     DRAM_SIZE_256MB                            2
 | 
			
		||||
#define     DRAM_SIZE_512MB                            3
 | 
			
		||||
 | 
			
		||||
#define SCU_AST2400_HW_STRAP_DRAM_CONFIG(x)        ((x) << 24)
 | 
			
		||||
#define SCU_AST2400_HW_STRAP_DRAM_CONFIG_MASK      (0x7 << 24)
 | 
			
		||||
 | 
			
		||||
#define SCU_HW_STRAP_GPIOE_PT_EN                   (0x1 << 22)
 | 
			
		||||
#define SCU_HW_STRAP_GPIOD_PT_EN                   (0x1 << 21)
 | 
			
		||||
#define SCU_HW_STRAP_LPC_DEC_SUPER_IO              (0x1 << 20)
 | 
			
		||||
#define SCU_AST2400_HW_STRAP_ACPI_DIS              (0x1 << 19)
 | 
			
		||||
 | 
			
		||||
/* bit 23, 18 [1,0] */
 | 
			
		||||
#define SCU_AST2400_HW_STRAP_SET_CLK_SOURCE(x)     (((((x) & 0x3) >> 1) << 23) \
 | 
			
		||||
                                                    | (((x) & 0x1) << 18))
 | 
			
		||||
#define SCU_AST2400_HW_STRAP_GET_CLK_SOURCE(x)     (((((x) >> 23) & 0x1) << 1) \
 | 
			
		||||
                                                    | (((x) >> 18) & 0x1))
 | 
			
		||||
#define SCU_AST2400_HW_STRAP_CLK_SOURCE_MASK       ((0x1 << 23) | (0x1 << 18))
 | 
			
		||||
#define     AST2400_CLK_25M_IN                         (0x1 << 23)
 | 
			
		||||
#define     AST2400_CLK_24M_IN                         0
 | 
			
		||||
#define     AST2400_CLK_48M_IN                         1
 | 
			
		||||
#define     AST2400_CLK_25M_IN_24M_USB_CKI             2
 | 
			
		||||
#define     AST2400_CLK_25M_IN_48M_USB_CKI             3
 | 
			
		||||
 | 
			
		||||
#define SCU_HW_STRAP_2ND_BOOT_WDT                  (0x1 << 17)
 | 
			
		||||
#define SCU_HW_STRAP_SUPER_IO_CONFIG               (0x1 << 16)
 | 
			
		||||
#define SCU_HW_STRAP_VGA_CLASS_CODE                (0x1 << 15)
 | 
			
		||||
#define SCU_HW_STRAP_LPC_RESET_PIN                 (0x1 << 14)
 | 
			
		||||
 | 
			
		||||
#define SCU_HW_STRAP_SPI_MODE(x)                   ((x) << 12)
 | 
			
		||||
#define SCU_HW_STRAP_SPI_MODE_MASK                 (0x3 << 12)
 | 
			
		||||
#define     SCU_HW_STRAP_SPI_DIS                       0
 | 
			
		||||
#define     SCU_HW_STRAP_SPI_MASTER                    1
 | 
			
		||||
#define     SCU_HW_STRAP_SPI_M_S_EN                    2
 | 
			
		||||
#define     SCU_HW_STRAP_SPI_PASS_THROUGH              3
 | 
			
		||||
 | 
			
		||||
#define SCU_AST2400_HW_STRAP_SET_CPU_AHB_RATIO(x)  ((x) << 10)
 | 
			
		||||
#define SCU_AST2400_HW_STRAP_GET_CPU_AHB_RATIO(x)  (((x) >> 10) & 3)
 | 
			
		||||
#define SCU_AST2400_HW_STRAP_CPU_AHB_RATIO_MASK    (0x3 << 10)
 | 
			
		||||
#define     AST2400_CPU_AHB_RATIO_1_1                  0
 | 
			
		||||
#define     AST2400_CPU_AHB_RATIO_2_1                  1
 | 
			
		||||
#define     AST2400_CPU_AHB_RATIO_4_1                  2
 | 
			
		||||
#define     AST2400_CPU_AHB_RATIO_3_1                  3
 | 
			
		||||
 | 
			
		||||
#define SCU_AST2400_HW_STRAP_GET_H_PLL_CLK(x)      (((x) >> 8) & 0x3)
 | 
			
		||||
#define SCU_AST2400_HW_STRAP_H_PLL_CLK_MASK        (0x3 << 8)
 | 
			
		||||
#define     AST2400_CPU_384MHZ                         0
 | 
			
		||||
#define     AST2400_CPU_360MHZ                         1
 | 
			
		||||
#define     AST2400_CPU_336MHZ                         2
 | 
			
		||||
#define     AST2400_CPU_408MHZ                         3
 | 
			
		||||
 | 
			
		||||
#define SCU_HW_STRAP_MAC1_RGMII                    (0x1 << 7)
 | 
			
		||||
#define SCU_HW_STRAP_MAC0_RGMII                    (0x1 << 6)
 | 
			
		||||
#define SCU_HW_STRAP_VGA_BIOS_ROM                  (0x1 << 5)
 | 
			
		||||
#define SCU_HW_STRAP_SPI_WIDTH                     (0x1 << 4)
 | 
			
		||||
 | 
			
		||||
#define SCU_HW_STRAP_VGA_SIZE_GET(x)               (((x) >> 2) & 0x3)
 | 
			
		||||
#define SCU_HW_STRAP_VGA_MASK                      (0x3 << 2)
 | 
			
		||||
#define SCU_HW_STRAP_VGA_SIZE_SET(x)               ((x) << 2)
 | 
			
		||||
#define     VGA_8M_DRAM                                0
 | 
			
		||||
#define     VGA_16M_DRAM                               1
 | 
			
		||||
#define     VGA_32M_DRAM                               2
 | 
			
		||||
#define     VGA_64M_DRAM                               3
 | 
			
		||||
 | 
			
		||||
#define SCU_AST2400_HW_STRAP_BOOT_MODE(x)          (x)
 | 
			
		||||
#define     AST2400_NOR_BOOT                           0
 | 
			
		||||
#define     AST2400_NAND_BOOT                          1
 | 
			
		||||
#define     AST2400_SPI_BOOT                           2
 | 
			
		||||
#define     AST2400_DIS_BOOT                           3
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Hardware strapping register definition (for Aspeed AST2500 SoC and
 | 
			
		||||
 * higher)
 | 
			
		||||
 *
 | 
			
		||||
 * 31     Enable SPI Flash Strap Auto Fetch Mode
 | 
			
		||||
 * 30     Enable GPIO Strap Mode
 | 
			
		||||
 * 29     Select UART Debug Port
 | 
			
		||||
 * 28     Reserved (1)
 | 
			
		||||
 * 27     Enable fast reset mode for ARM ICE debugger
 | 
			
		||||
 * 26     Enable eSPI flash mode
 | 
			
		||||
 * 25     Enable eSPI mode
 | 
			
		||||
 * 24     Select DDR4 SDRAM
 | 
			
		||||
 * 23     Select 25 MHz reference clock input mode
 | 
			
		||||
 * 22     Enable GPIOE pass-through mode
 | 
			
		||||
 * 21     Enable GPIOD pass-through mode
 | 
			
		||||
 * 20     Disable LPC to decode SuperIO 0x2E/0x4E address
 | 
			
		||||
 * 19     Enable ACPI function
 | 
			
		||||
 * 18     Select USBCKI input frequency
 | 
			
		||||
 * 17     Enable BMC 2nd boot watchdog timer
 | 
			
		||||
 * 16     SuperIO configuration address selection
 | 
			
		||||
 * 15     VGA Class Code selection
 | 
			
		||||
 * 14     Select dedicated LPC reset input
 | 
			
		||||
 * 13:12  SPI mode selection
 | 
			
		||||
 * 11:9   AXI/AHB clock frequency ratio selection
 | 
			
		||||
 * 8      Reserved (0)
 | 
			
		||||
 * 7      Define MAC#2 interface
 | 
			
		||||
 * 6      Define MAC#1 interface
 | 
			
		||||
 * 5      Enable dedicated VGA BIOS ROM
 | 
			
		||||
 * 4      Reserved (0)
 | 
			
		||||
 * 3:2    VGA memory size selection
 | 
			
		||||
 * 1      Reserved (1)
 | 
			
		||||
 * 0      Disable CPU boot
 | 
			
		||||
 */
 | 
			
		||||
#define SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE  (0x1 << 31)
 | 
			
		||||
#define SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE     (0x1 << 30)
 | 
			
		||||
#define SCU_AST2500_HW_STRAP_UART_DEBUG            (0x1 << 29)
 | 
			
		||||
#define     UART_DEBUG_UART1                           0
 | 
			
		||||
#define     UART_DEBUG_UART5                           1
 | 
			
		||||
#define SCU_AST2500_HW_STRAP_RESERVED28            (0x1 << 28)
 | 
			
		||||
 | 
			
		||||
#define SCU_AST2500_HW_STRAP_FAST_RESET_DBG        (0x1 << 27)
 | 
			
		||||
#define SCU_AST2500_HW_STRAP_ESPI_FLASH_ENABLE     (0x1 << 26)
 | 
			
		||||
#define SCU_AST2500_HW_STRAP_ESPI_ENABLE           (0x1 << 25)
 | 
			
		||||
#define SCU_AST2500_HW_STRAP_DDR4_ENABLE           (0x1 << 24)
 | 
			
		||||
 | 
			
		||||
#define SCU_AST2500_HW_STRAP_ACPI_ENABLE           (0x1 << 19)
 | 
			
		||||
#define SCU_AST2500_HW_STRAP_USBCKI_FREQ           (0x1 << 18)
 | 
			
		||||
#define     USBCKI_FREQ_24MHZ                          0
 | 
			
		||||
#define     USBCKI_FREQ_28MHZ                          1
 | 
			
		||||
 | 
			
		||||
#define SCU_AST2500_HW_STRAP_SET_AXI_AHB_RATIO(x)  ((x) << 9)
 | 
			
		||||
#define SCU_AST2500_HW_STRAP_GET_AXI_AHB_RATIO(x)  (((x) >> 9) & 7)
 | 
			
		||||
#define SCU_AST2500_HW_STRAP_CPU_AXI_RATIO_MASK    (0x7 << 9)
 | 
			
		||||
#define     AXI_AHB_RATIO_UNDEFINED                    0
 | 
			
		||||
#define     AXI_AHB_RATIO_2_1                          1
 | 
			
		||||
#define     AXI_AHB_RATIO_3_1                          2
 | 
			
		||||
#define     AXI_AHB_RATIO_4_1                          3
 | 
			
		||||
#define     AXI_AHB_RATIO_5_1                          4
 | 
			
		||||
#define     AXI_AHB_RATIO_6_1                          5
 | 
			
		||||
#define     AXI_AHB_RATIO_7_1                          6
 | 
			
		||||
#define     AXI_AHB_RATIO_8_1                          7
 | 
			
		||||
 | 
			
		||||
#define SCU_AST2500_HW_STRAP_RESERVED1             (0x1 << 1)
 | 
			
		||||
#define SCU_AST2500_HW_STRAP_DIS_BOOT              (0x1 << 0)
 | 
			
		||||
 | 
			
		||||
#define AST2500_HW_STRAP1_DEFAULTS (                                    \
 | 
			
		||||
        SCU_AST2500_HW_STRAP_RESERVED28 |                               \
 | 
			
		||||
        SCU_HW_STRAP_2ND_BOOT_WDT |                                     \
 | 
			
		||||
        SCU_HW_STRAP_VGA_CLASS_CODE |                                   \
 | 
			
		||||
        SCU_HW_STRAP_LPC_RESET_PIN |                                    \
 | 
			
		||||
        SCU_AST2500_HW_STRAP_SET_AXI_AHB_RATIO(AXI_AHB_RATIO_2_1) |     \
 | 
			
		||||
        SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) |                       \
 | 
			
		||||
        SCU_AST2500_HW_STRAP_RESERVED1)
 | 
			
		||||
 | 
			
		||||
#endif /* ASPEED_SCU_H */
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,8 @@ typedef struct AspeedSDMCState {
 | 
			
		||||
 | 
			
		||||
    uint32_t regs[ASPEED_SDMC_NR_REGS];
 | 
			
		||||
    uint32_t silicon_rev;
 | 
			
		||||
    uint32_t ram_bits;
 | 
			
		||||
    uint64_t ram_size;
 | 
			
		||||
 | 
			
		||||
} AspeedSDMCState;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,11 @@
 | 
			
		||||
#include "net/net.h"
 | 
			
		||||
#include "hw/sysbus.h"
 | 
			
		||||
 | 
			
		||||
#define CADENCE_GEM_MAXREG        (0x00000640/4) /* Last valid GEM address */
 | 
			
		||||
#define CADENCE_GEM_MAXREG        (0x00000800 / 4) /* Last valid GEM address */
 | 
			
		||||
 | 
			
		||||
#define MAX_PRIORITY_QUEUES             8
 | 
			
		||||
#define MAX_TYPE1_SCREENERS             16
 | 
			
		||||
#define MAX_TYPE2_SCREENERS             16
 | 
			
		||||
 | 
			
		||||
typedef struct CadenceGEMState {
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
@ -40,7 +44,12 @@ typedef struct CadenceGEMState {
 | 
			
		||||
    MemoryRegion iomem;
 | 
			
		||||
    NICState *nic;
 | 
			
		||||
    NICConf conf;
 | 
			
		||||
    qemu_irq irq;
 | 
			
		||||
    qemu_irq irq[MAX_PRIORITY_QUEUES];
 | 
			
		||||
 | 
			
		||||
    /* Static properties */
 | 
			
		||||
    uint8_t num_priority_queues;
 | 
			
		||||
    uint8_t num_type1_screeners;
 | 
			
		||||
    uint8_t num_type2_screeners;
 | 
			
		||||
 | 
			
		||||
    /* GEM registers backing store */
 | 
			
		||||
    uint32_t regs[CADENCE_GEM_MAXREG];
 | 
			
		||||
@ -59,12 +68,12 @@ typedef struct CadenceGEMState {
 | 
			
		||||
    uint8_t phy_loop; /* Are we in phy loopback? */
 | 
			
		||||
 | 
			
		||||
    /* The current DMA descriptor pointers */
 | 
			
		||||
    uint32_t rx_desc_addr;
 | 
			
		||||
    uint32_t tx_desc_addr;
 | 
			
		||||
    uint32_t rx_desc_addr[MAX_PRIORITY_QUEUES];
 | 
			
		||||
    uint32_t tx_desc_addr[MAX_PRIORITY_QUEUES];
 | 
			
		||||
 | 
			
		||||
    uint8_t can_rx_state; /* Debug only */
 | 
			
		||||
 | 
			
		||||
    unsigned rx_desc[2];
 | 
			
		||||
    unsigned rx_desc[MAX_PRIORITY_QUEUES][2];
 | 
			
		||||
 | 
			
		||||
    bool sar_active[4];
 | 
			
		||||
} CadenceGEMState;
 | 
			
		||||
 | 
			
		||||
@ -12,11 +12,34 @@
 | 
			
		||||
#include "qemu/timer.h"
 | 
			
		||||
#include "migration/vmstate.h"
 | 
			
		||||
 | 
			
		||||
/* The default ptimer policy retains backward compatibility with the legacy
 | 
			
		||||
 * timers. Custom policies are adjusting the default one. Consider providing
 | 
			
		||||
 * a correct policy for your timer.
 | 
			
		||||
 *
 | 
			
		||||
 * The rough edges of the default policy:
 | 
			
		||||
 *  - Starting to run with a period = 0 emits error message and stops the
 | 
			
		||||
 *    timer without a trigger.
 | 
			
		||||
 *
 | 
			
		||||
 *  - Setting period to 0 of the running timer emits error message and
 | 
			
		||||
 *    stops the timer without a trigger.
 | 
			
		||||
 *
 | 
			
		||||
 *  - Starting to run with counter = 0 or setting it to "0" while timer
 | 
			
		||||
 *    is running causes a trigger and reloads counter with a limit value.
 | 
			
		||||
 *    If limit = 0, ptimer emits error message and stops the timer.
 | 
			
		||||
 *
 | 
			
		||||
 *  - Counter value of the running timer is one less than the actual value.
 | 
			
		||||
 *
 | 
			
		||||
 *  - Changing period/frequency of the running timer loses time elapsed
 | 
			
		||||
 *    since the last period, effectively restarting the timer with a
 | 
			
		||||
 *    counter = counter value at the moment of change (.i.e. one less).
 | 
			
		||||
 */
 | 
			
		||||
#define PTIMER_POLICY_DEFAULT               0
 | 
			
		||||
 | 
			
		||||
/* ptimer.c */
 | 
			
		||||
typedef struct ptimer_state ptimer_state;
 | 
			
		||||
typedef void (*ptimer_cb)(void *opaque);
 | 
			
		||||
 | 
			
		||||
ptimer_state *ptimer_init(QEMUBH *bh);
 | 
			
		||||
ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask);
 | 
			
		||||
void ptimer_set_period(ptimer_state *s, int64_t period);
 | 
			
		||||
void ptimer_set_freq(ptimer_state *s, uint32_t freq);
 | 
			
		||||
uint64_t ptimer_get_limit(ptimer_state *s);
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,11 @@
 | 
			
		||||
#include "migration/vmstate.h"
 | 
			
		||||
 | 
			
		||||
const VMStateDescription vmstate_dummy = {};
 | 
			
		||||
const VMStateInfo vmstate_info_uint8;
 | 
			
		||||
const VMStateInfo vmstate_info_uint32;
 | 
			
		||||
const VMStateInfo vmstate_info_uint64;
 | 
			
		||||
const VMStateInfo vmstate_info_int64;
 | 
			
		||||
const VMStateInfo vmstate_info_timer;
 | 
			
		||||
 | 
			
		||||
int vmstate_register_with_alias_id(DeviceState *dev,
 | 
			
		||||
                                   int instance_id,
 | 
			
		||||
 | 
			
		||||
@ -1129,6 +1129,51 @@ static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
 | 
			
		||||
    REGINFO_SENTINEL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void cortex_a7_initfn(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
			
		||||
 | 
			
		||||
    cpu->dtb_compatible = "arm,cortex-a7";
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_V7);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_VFP4);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_NEON);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_LPAE);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_EL3);
 | 
			
		||||
    cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7;
 | 
			
		||||
    cpu->midr = 0x410fc075;
 | 
			
		||||
    cpu->reset_fpsid = 0x41023075;
 | 
			
		||||
    cpu->mvfr0 = 0x10110222;
 | 
			
		||||
    cpu->mvfr1 = 0x11111111;
 | 
			
		||||
    cpu->ctr = 0x84448003;
 | 
			
		||||
    cpu->reset_sctlr = 0x00c50078;
 | 
			
		||||
    cpu->id_pfr0 = 0x00001131;
 | 
			
		||||
    cpu->id_pfr1 = 0x00011011;
 | 
			
		||||
    cpu->id_dfr0 = 0x02010555;
 | 
			
		||||
    cpu->pmceid0 = 0x00000000;
 | 
			
		||||
    cpu->pmceid1 = 0x00000000;
 | 
			
		||||
    cpu->id_afr0 = 0x00000000;
 | 
			
		||||
    cpu->id_mmfr0 = 0x10101105;
 | 
			
		||||
    cpu->id_mmfr1 = 0x40000000;
 | 
			
		||||
    cpu->id_mmfr2 = 0x01240000;
 | 
			
		||||
    cpu->id_mmfr3 = 0x02102211;
 | 
			
		||||
    cpu->id_isar0 = 0x01101110;
 | 
			
		||||
    cpu->id_isar1 = 0x13112111;
 | 
			
		||||
    cpu->id_isar2 = 0x21232041;
 | 
			
		||||
    cpu->id_isar3 = 0x11112131;
 | 
			
		||||
    cpu->id_isar4 = 0x10011142;
 | 
			
		||||
    cpu->dbgdidr = 0x3515f005;
 | 
			
		||||
    cpu->clidr = 0x0a200023;
 | 
			
		||||
    cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
 | 
			
		||||
    cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
 | 
			
		||||
    cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
 | 
			
		||||
    define_arm_cp_regs(cpu, cortexa15_cp_reginfo); /* Same as A15 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void cortex_a15_initfn(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
			
		||||
@ -1385,6 +1430,7 @@ static const ARMCPUInfo arm_cpus[] = {
 | 
			
		||||
    { .name = "cortex-m4",   .initfn = cortex_m4_initfn,
 | 
			
		||||
                             .class_init = arm_v7m_class_init },
 | 
			
		||||
    { .name = "cortex-r5",   .initfn = cortex_r5_initfn },
 | 
			
		||||
    { .name = "cortex-a7",   .initfn = cortex_a7_initfn },
 | 
			
		||||
    { .name = "cortex-a8",   .initfn = cortex_a8_initfn },
 | 
			
		||||
    { .name = "cortex-a9",   .initfn = cortex_a9_initfn },
 | 
			
		||||
    { .name = "cortex-a15",  .initfn = cortex_a15_initfn },
 | 
			
		||||
 | 
			
		||||
@ -296,6 +296,7 @@ check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
 | 
			
		||||
check-qtest-s390x-y = tests/boot-serial-test$(EXESUF)
 | 
			
		||||
 | 
			
		||||
check-qtest-generic-y += tests/qom-test$(EXESUF)
 | 
			
		||||
check-qtest-generic-y += tests/ptimer-test$(EXESUF)
 | 
			
		||||
 | 
			
		||||
qapi-schema += alternate-any.json
 | 
			
		||||
qapi-schema += alternate-array.json
 | 
			
		||||
@ -658,6 +659,7 @@ tests/test-filter-mirror$(EXESUF): tests/test-filter-mirror.o $(qtest-obj-y)
 | 
			
		||||
tests/test-filter-redirector$(EXESUF): tests/test-filter-redirector.o $(qtest-obj-y)
 | 
			
		||||
tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o contrib/ivshmem-server/ivshmem-server.o $(libqos-pc-obj-y)
 | 
			
		||||
tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o
 | 
			
		||||
tests/ptimer-test$(EXESUF): tests/ptimer-test.o tests/ptimer-test-stubs.o hw/core/ptimer.o
 | 
			
		||||
 | 
			
		||||
tests/migration/stress$(EXESUF): tests/migration/stress.o
 | 
			
		||||
	$(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ,"  LINK  $(TARGET_DIR)$@")
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										107
									
								
								tests/ptimer-test-stubs.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								tests/ptimer-test-stubs.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,107 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Stubs for the ptimer-test
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Dmitry Osipenko <digetx@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | 
			
		||||
 * See the COPYING file in the top-level directory.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "qemu/osdep.h"
 | 
			
		||||
#include "qemu/main-loop.h"
 | 
			
		||||
#include "sysemu/replay.h"
 | 
			
		||||
 | 
			
		||||
#include "ptimer-test.h"
 | 
			
		||||
 | 
			
		||||
struct QEMUBH {
 | 
			
		||||
    QEMUBHFunc *cb;
 | 
			
		||||
    void *opaque;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
QEMUTimerListGroup main_loop_tlg;
 | 
			
		||||
 | 
			
		||||
int64_t ptimer_test_time_ns;
 | 
			
		||||
 | 
			
		||||
void timer_init_tl(QEMUTimer *ts,
 | 
			
		||||
                   QEMUTimerList *timer_list, int scale,
 | 
			
		||||
                   QEMUTimerCB *cb, void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    ts->timer_list = timer_list;
 | 
			
		||||
    ts->cb = cb;
 | 
			
		||||
    ts->opaque = opaque;
 | 
			
		||||
    ts->scale = scale;
 | 
			
		||||
    ts->expire_time = -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void timer_mod(QEMUTimer *ts, int64_t expire_time)
 | 
			
		||||
{
 | 
			
		||||
    QEMUTimerList *timer_list = ts->timer_list;
 | 
			
		||||
    QEMUTimer *t = &timer_list->active_timers;
 | 
			
		||||
 | 
			
		||||
    while (t->next != NULL) {
 | 
			
		||||
        if (t->next == ts) {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        t = t->next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ts->expire_time = MAX(expire_time * ts->scale, 0);
 | 
			
		||||
    ts->next = NULL;
 | 
			
		||||
    t->next = ts;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void timer_del(QEMUTimer *ts)
 | 
			
		||||
{
 | 
			
		||||
    QEMUTimerList *timer_list = ts->timer_list;
 | 
			
		||||
    QEMUTimer *t = &timer_list->active_timers;
 | 
			
		||||
 | 
			
		||||
    while (t->next != NULL) {
 | 
			
		||||
        if (t->next == ts) {
 | 
			
		||||
            t->next = ts->next;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        t = t->next;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int64_t qemu_clock_get_ns(QEMUClockType type)
 | 
			
		||||
{
 | 
			
		||||
    return ptimer_test_time_ns;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int64_t qemu_clock_deadline_ns_all(QEMUClockType type)
 | 
			
		||||
{
 | 
			
		||||
    QEMUTimerList *timer_list = main_loop_tlg.tl[type];
 | 
			
		||||
    QEMUTimer *t = timer_list->active_timers.next;
 | 
			
		||||
    int64_t deadline = -1;
 | 
			
		||||
 | 
			
		||||
    while (t != NULL) {
 | 
			
		||||
        if (deadline == -1) {
 | 
			
		||||
            deadline = t->expire_time;
 | 
			
		||||
        } else {
 | 
			
		||||
            deadline = MIN(deadline, t->expire_time);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        t = t->next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return deadline;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    QEMUBH *bh = g_new(QEMUBH, 1);
 | 
			
		||||
 | 
			
		||||
    bh->cb = cb;
 | 
			
		||||
    bh->opaque = opaque;
 | 
			
		||||
 | 
			
		||||
    return bh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void replay_bh_schedule_event(QEMUBH *bh)
 | 
			
		||||
{
 | 
			
		||||
    bh->cb(bh->opaque);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										568
									
								
								tests/ptimer-test.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										568
									
								
								tests/ptimer-test.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,568 @@
 | 
			
		||||
/*
 | 
			
		||||
 * QTest testcase for the ptimer
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Dmitry Osipenko <digetx@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | 
			
		||||
 * See the COPYING file in the top-level directory.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <glib/gprintf.h>
 | 
			
		||||
 | 
			
		||||
#include "qemu/osdep.h"
 | 
			
		||||
#include "qemu/main-loop.h"
 | 
			
		||||
#include "hw/ptimer.h"
 | 
			
		||||
 | 
			
		||||
#include "libqtest.h"
 | 
			
		||||
#include "ptimer-test.h"
 | 
			
		||||
 | 
			
		||||
static bool triggered;
 | 
			
		||||
 | 
			
		||||
static void ptimer_trigger(void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    triggered = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ptimer_test_expire_qemu_timers(int64_t expire_time,
 | 
			
		||||
                                           QEMUClockType type)
 | 
			
		||||
{
 | 
			
		||||
    QEMUTimerList *timer_list = main_loop_tlg.tl[type];
 | 
			
		||||
    QEMUTimer *t = timer_list->active_timers.next;
 | 
			
		||||
 | 
			
		||||
    while (t != NULL) {
 | 
			
		||||
        if (t->expire_time == expire_time) {
 | 
			
		||||
            timer_del(t);
 | 
			
		||||
 | 
			
		||||
            if (t->cb != NULL) {
 | 
			
		||||
                t->cb(t->opaque);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        t = t->next;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ptimer_test_set_qemu_time_ns(int64_t ns)
 | 
			
		||||
{
 | 
			
		||||
    ptimer_test_time_ns = ns;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void qemu_clock_step(uint64_t ns)
 | 
			
		||||
{
 | 
			
		||||
    int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
 | 
			
		||||
    int64_t advanced_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns;
 | 
			
		||||
 | 
			
		||||
    while (deadline != -1 && deadline <= advanced_time) {
 | 
			
		||||
        ptimer_test_set_qemu_time_ns(deadline);
 | 
			
		||||
        ptimer_test_expire_qemu_timers(deadline, QEMU_CLOCK_VIRTUAL);
 | 
			
		||||
        deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ptimer_test_set_qemu_time_ns(advanced_time);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_set_count(gconstpointer arg)
 | 
			
		||||
{
 | 
			
		||||
    const uint8_t *policy = arg;
 | 
			
		||||
    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
 | 
			
		||||
    ptimer_state *ptimer = ptimer_init(bh, *policy);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    ptimer_set_count(ptimer, 1000);
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 1000);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_set_limit(gconstpointer arg)
 | 
			
		||||
{
 | 
			
		||||
    const uint8_t *policy = arg;
 | 
			
		||||
    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
 | 
			
		||||
    ptimer_state *ptimer = ptimer_init(bh, *policy);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    ptimer_set_limit(ptimer, 1000, 0);
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_limit(ptimer), ==, 1000);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_set_limit(ptimer, 2000, 1);
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 2000);
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_limit(ptimer), ==, 2000);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_oneshot(gconstpointer arg)
 | 
			
		||||
{
 | 
			
		||||
    const uint8_t *policy = arg;
 | 
			
		||||
    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
 | 
			
		||||
    ptimer_state *ptimer = ptimer_init(bh, *policy);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    ptimer_set_period(ptimer, 2000000);
 | 
			
		||||
    ptimer_set_count(ptimer, 10);
 | 
			
		||||
    ptimer_run(ptimer, 1);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 2 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_stop(ptimer);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 11);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_run(ptimer, 1);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 7 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(4000000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_set_count(ptimer, 10);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(20000000 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_set_limit(ptimer, 9, 1);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(20000000 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_run(ptimer, 1);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_set_count(ptimer, 20);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 19 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_stop(ptimer);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 12 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_periodic(gconstpointer arg)
 | 
			
		||||
{
 | 
			
		||||
    const uint8_t *policy = arg;
 | 
			
		||||
    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
 | 
			
		||||
    ptimer_state *ptimer = ptimer_init(bh, *policy);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    ptimer_set_period(ptimer, 2000000);
 | 
			
		||||
    ptimer_set_limit(ptimer, 10, 1);
 | 
			
		||||
    ptimer_run(ptimer, 0);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 10 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_set_count(ptimer, 20);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 11 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 10);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_stop(ptimer);
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_set_count(ptimer, 3);
 | 
			
		||||
    ptimer_run(ptimer, 0);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 3 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_set_count(ptimer, 0);
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 12 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_stop(ptimer);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 12 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_run(ptimer, 0);
 | 
			
		||||
    ptimer_set_period(ptimer, 0);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_on_the_fly_mode_change(gconstpointer arg)
 | 
			
		||||
{
 | 
			
		||||
    const uint8_t *policy = arg;
 | 
			
		||||
    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
 | 
			
		||||
    ptimer_state *ptimer = ptimer_init(bh, *policy);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    ptimer_set_period(ptimer, 2000000);
 | 
			
		||||
    ptimer_set_limit(ptimer, 10, 1);
 | 
			
		||||
    ptimer_run(ptimer, 1);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 9 + 100000);
 | 
			
		||||
 | 
			
		||||
    ptimer_run(ptimer, 0);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 9);
 | 
			
		||||
 | 
			
		||||
    ptimer_run(ptimer, 1);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 3);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_on_the_fly_period_change(gconstpointer arg)
 | 
			
		||||
{
 | 
			
		||||
    const uint8_t *policy = arg;
 | 
			
		||||
    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
 | 
			
		||||
    ptimer_state *ptimer = ptimer_init(bh, *policy);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    ptimer_set_period(ptimer, 2000000);
 | 
			
		||||
    ptimer_set_limit(ptimer, 8, 1);
 | 
			
		||||
    ptimer_run(ptimer, 1);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 4 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_set_period(ptimer, 4000000);
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(4000000 * 2 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(4000000 * 2);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_on_the_fly_freq_change(gconstpointer arg)
 | 
			
		||||
{
 | 
			
		||||
    const uint8_t *policy = arg;
 | 
			
		||||
    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
 | 
			
		||||
    ptimer_state *ptimer = ptimer_init(bh, *policy);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    ptimer_set_freq(ptimer, 500);
 | 
			
		||||
    ptimer_set_limit(ptimer, 8, 1);
 | 
			
		||||
    ptimer_run(ptimer, 1);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 4 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_set_freq(ptimer, 250);
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 4 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 4);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_run_with_period_0(gconstpointer arg)
 | 
			
		||||
{
 | 
			
		||||
    const uint8_t *policy = arg;
 | 
			
		||||
    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
 | 
			
		||||
    ptimer_state *ptimer = ptimer_init(bh, *policy);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    ptimer_set_count(ptimer, 99);
 | 
			
		||||
    ptimer_run(ptimer, 1);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(10 * NANOSECONDS_PER_SECOND);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 99);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_run_with_delta_0(gconstpointer arg)
 | 
			
		||||
{
 | 
			
		||||
    const uint8_t *policy = arg;
 | 
			
		||||
    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
 | 
			
		||||
    ptimer_state *ptimer = ptimer_init(bh, *policy);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    ptimer_set_period(ptimer, 2000000);
 | 
			
		||||
    ptimer_set_limit(ptimer, 99, 0);
 | 
			
		||||
    ptimer_run(ptimer, 1);
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 99);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 97);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 97);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 2);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    ptimer_set_count(ptimer, 0);
 | 
			
		||||
    ptimer_run(ptimer, 0);
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 99);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 97);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 * 98);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 98);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_stop(ptimer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_periodic_with_load_0(gconstpointer arg)
 | 
			
		||||
{
 | 
			
		||||
    const uint8_t *policy = arg;
 | 
			
		||||
    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
 | 
			
		||||
    ptimer_state *ptimer = ptimer_init(bh, *policy);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    ptimer_set_period(ptimer, 2000000);
 | 
			
		||||
    ptimer_run(ptimer, 0);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    ptimer_stop(ptimer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_oneshot_with_load_0(gconstpointer arg)
 | 
			
		||||
{
 | 
			
		||||
    const uint8_t *policy = arg;
 | 
			
		||||
    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
 | 
			
		||||
    ptimer_state *ptimer = ptimer_init(bh, *policy);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    ptimer_set_period(ptimer, 2000000);
 | 
			
		||||
    ptimer_run(ptimer, 1);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_true(triggered);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
 | 
			
		||||
    triggered = false;
 | 
			
		||||
 | 
			
		||||
    qemu_clock_step(2000000 + 100000);
 | 
			
		||||
 | 
			
		||||
    g_assert_false(triggered);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void add_ptimer_tests(uint8_t policy)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *ppolicy = g_malloc(1);
 | 
			
		||||
    char *policy_name = g_malloc(64);
 | 
			
		||||
 | 
			
		||||
    *ppolicy = policy;
 | 
			
		||||
 | 
			
		||||
    if (policy == PTIMER_POLICY_DEFAULT) {
 | 
			
		||||
        g_sprintf(policy_name, "default");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qtest_add_data_func(
 | 
			
		||||
        g_strdup_printf("/ptimer/set_count policy=%s", policy_name),
 | 
			
		||||
        ppolicy, check_set_count);
 | 
			
		||||
 | 
			
		||||
    qtest_add_data_func(
 | 
			
		||||
        g_strdup_printf("/ptimer/set_limit policy=%s", policy_name),
 | 
			
		||||
        ppolicy, check_set_limit);
 | 
			
		||||
 | 
			
		||||
    qtest_add_data_func(
 | 
			
		||||
        g_strdup_printf("/ptimer/oneshot policy=%s", policy_name),
 | 
			
		||||
        ppolicy, check_oneshot);
 | 
			
		||||
 | 
			
		||||
    qtest_add_data_func(
 | 
			
		||||
        g_strdup_printf("/ptimer/periodic policy=%s", policy_name),
 | 
			
		||||
        ppolicy, check_periodic);
 | 
			
		||||
 | 
			
		||||
    qtest_add_data_func(
 | 
			
		||||
        g_strdup_printf("/ptimer/on_the_fly_mode_change policy=%s", policy_name),
 | 
			
		||||
        ppolicy, check_on_the_fly_mode_change);
 | 
			
		||||
 | 
			
		||||
    qtest_add_data_func(
 | 
			
		||||
        g_strdup_printf("/ptimer/on_the_fly_period_change policy=%s", policy_name),
 | 
			
		||||
        ppolicy, check_on_the_fly_period_change);
 | 
			
		||||
 | 
			
		||||
    qtest_add_data_func(
 | 
			
		||||
        g_strdup_printf("/ptimer/on_the_fly_freq_change policy=%s", policy_name),
 | 
			
		||||
        ppolicy, check_on_the_fly_freq_change);
 | 
			
		||||
 | 
			
		||||
    qtest_add_data_func(
 | 
			
		||||
        g_strdup_printf("/ptimer/run_with_period_0 policy=%s", policy_name),
 | 
			
		||||
        ppolicy, check_run_with_period_0);
 | 
			
		||||
 | 
			
		||||
    qtest_add_data_func(
 | 
			
		||||
        g_strdup_printf("/ptimer/run_with_delta_0 policy=%s", policy_name),
 | 
			
		||||
        ppolicy, check_run_with_delta_0);
 | 
			
		||||
 | 
			
		||||
    qtest_add_data_func(
 | 
			
		||||
        g_strdup_printf("/ptimer/periodic_with_load_0 policy=%s", policy_name),
 | 
			
		||||
        ppolicy, check_periodic_with_load_0);
 | 
			
		||||
 | 
			
		||||
    qtest_add_data_func(
 | 
			
		||||
        g_strdup_printf("/ptimer/oneshot_with_load_0 policy=%s", policy_name),
 | 
			
		||||
        ppolicy, check_oneshot_with_load_0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    g_test_init(&argc, &argv, NULL);
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < QEMU_CLOCK_MAX; i++) {
 | 
			
		||||
        main_loop_tlg.tl[i] = g_new0(QEMUTimerList, 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    add_ptimer_tests(PTIMER_POLICY_DEFAULT);
 | 
			
		||||
 | 
			
		||||
    qtest_allowed = true;
 | 
			
		||||
 | 
			
		||||
    return g_test_run();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								tests/ptimer-test.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								tests/ptimer-test.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
/*
 | 
			
		||||
 * QTest testcase for the ptimer
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Dmitry Osipenko <digetx@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | 
			
		||||
 * See the COPYING file in the top-level directory.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef PTIMER_TEST_H
 | 
			
		||||
#define PTIMER_TEST_H
 | 
			
		||||
 | 
			
		||||
extern bool qtest_allowed;
 | 
			
		||||
 | 
			
		||||
extern int64_t ptimer_test_time_ns;
 | 
			
		||||
 | 
			
		||||
struct QEMUTimerList {
 | 
			
		||||
    QEMUTimer active_timers;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user