From 36476562d57a3b64bbe86db26e63677dd21907c5 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 22 Feb 2018 15:12:51 +0000 Subject: [PATCH 01/32] target/arm: Fix register definitions for VMIDR and VMPIDR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The register definitions for VMIDR and VMPIDR have separate reginfo structs for the AArch32 and AArch64 registers. However the 32-bit versions are wrong: * they use offsetof instead of offsetoflow32 to mark where the 32-bit value lives in the uint64_t CPU state field * they don't mark themselves as ARM_CP_ALIAS In particular this means that if you try to use an Arm guest CPU which enables EL2 on a big-endian host it will assert at reset: target/arm/cpu.c:114: cp_reg_check_reset: Assertion `oldvalue == newvalue' failed. because the reset of the 32-bit register writes to the top half of the uint64_t. Correct the errors in the structures. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé --- This is necessary for 'make check' to pass on big endian systems with the 'raspi3' board enabled, which is the first board which has an EL2-enabled-by-default CPU. --- target/arm/helper.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index 32e4fd4732..c5bc69b961 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -5069,8 +5069,8 @@ void register_cp_regs_for_features(ARMCPU *cpu) { .name = "VPIDR", .state = ARM_CP_STATE_AA32, .cp = 15, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 0, .access = PL2_RW, .accessfn = access_el3_aa32ns, - .resetvalue = cpu->midr, - .fieldoffset = offsetof(CPUARMState, cp15.vpidr_el2) }, + .resetvalue = cpu->midr, .type = ARM_CP_ALIAS, + .fieldoffset = offsetoflow32(CPUARMState, cp15.vpidr_el2) }, { .name = "VPIDR_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 0, .access = PL2_RW, .resetvalue = cpu->midr, @@ -5078,8 +5078,8 @@ void register_cp_regs_for_features(ARMCPU *cpu) { .name = "VMPIDR", .state = ARM_CP_STATE_AA32, .cp = 15, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 5, .access = PL2_RW, .accessfn = access_el3_aa32ns, - .resetvalue = vmpidr_def, - .fieldoffset = offsetof(CPUARMState, cp15.vmpidr_el2) }, + .resetvalue = vmpidr_def, .type = ARM_CP_ALIAS, + .fieldoffset = offsetoflow32(CPUARMState, cp15.vmpidr_el2) }, { .name = "VMPIDR_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 5, .access = PL2_RW, From 1c3db49d39d66646ff546ec26f36e3b9040f3504 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Thu, 22 Feb 2018 15:12:51 +0000 Subject: [PATCH 02/32] raspi: Add "raspi3" machine type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a "raspi3" machine type, which can now be selected as the machine to run on by users via the "-M" command line option to QEMU. The machine type does *not* ignore memory transaction failures so we likely need to add some dummy devices later when people run something more complicated than what I'm using for testing. Signed-off-by: Pekka Enberg [PMM: added #ifdef TARGET_AARCH64 so we don't provide the 64-bit board in the 32-bit only arm-softmmu build.] Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell --- hw/arm/raspi.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c index 93121c56bf..a37881433c 100644 --- a/hw/arm/raspi.c +++ b/hw/arm/raspi.c @@ -187,3 +187,26 @@ static void raspi2_machine_init(MachineClass *mc) mc->ignore_memory_transaction_failures = true; }; DEFINE_MACHINE("raspi2", raspi2_machine_init) + +#ifdef TARGET_AARCH64 +static void raspi3_init(MachineState *machine) +{ + raspi_init(machine, 3); +} + +static void raspi3_machine_init(MachineClass *mc) +{ + mc->desc = "Raspberry Pi 3"; + mc->init = raspi3_init; + mc->block_default_type = IF_SD; + mc->no_parallel = 1; + mc->no_floppy = 1; + mc->no_cdrom = 1; + mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a53"); + mc->max_cpus = BCM2836_NCPUS; + mc->min_cpus = BCM2836_NCPUS; + mc->default_cpus = BCM2836_NCPUS; + mc->default_ram_size = 1024 * 1024 * 1024; +} +DEFINE_MACHINE("raspi3", raspi3_machine_init) +#endif From f6bfe45af2a9bd1b929955ca3bf54726d1e68d88 Mon Sep 17 00:00:00 2001 From: Richard Braun Date: Thu, 22 Feb 2018 15:12:51 +0000 Subject: [PATCH 03/32] hw/char/stm32f2xx_usart: fix TXE/TC bit handling I/O currently being synchronous, there is no reason to ever clear the SR_TXE bit. However the SR_TC bit may be cleared by software writing to the SR register, so set it on each write. In addition, fix the reset value of the USART status register. Signed-off-by: Richard Braun Reviewed-by: Alistair Francis [PMM: removed XXX tag from comment, since it isn't something we need to come back and fix in QEMU] Signed-off-by: Peter Maydell --- hw/char/stm32f2xx_usart.c | 12 ++++++++---- include/hw/char/stm32f2xx_usart.h | 7 ++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/hw/char/stm32f2xx_usart.c b/hw/char/stm32f2xx_usart.c index 07b462d4b6..032b5fda13 100644 --- a/hw/char/stm32f2xx_usart.c +++ b/hw/char/stm32f2xx_usart.c @@ -96,12 +96,10 @@ static uint64_t stm32f2xx_usart_read(void *opaque, hwaddr addr, switch (addr) { case USART_SR: retvalue = s->usart_sr; - s->usart_sr &= ~USART_SR_TC; qemu_chr_fe_accept_input(&s->chr); return retvalue; case USART_DR: DB_PRINT("Value: 0x%" PRIx32 ", %c\n", s->usart_dr, (char) s->usart_dr); - s->usart_sr |= USART_SR_TXE; s->usart_sr &= ~USART_SR_RXNE; qemu_chr_fe_accept_input(&s->chr); qemu_set_irq(s->irq, 0); @@ -137,7 +135,9 @@ static void stm32f2xx_usart_write(void *opaque, hwaddr addr, switch (addr) { case USART_SR: if (value <= 0x3FF) { - s->usart_sr = value; + /* I/O being synchronous, TXE is always set. In addition, it may + only be set by hardware, so keep it set here. */ + s->usart_sr = value | USART_SR_TXE; } else { s->usart_sr &= value; } @@ -151,8 +151,12 @@ static void stm32f2xx_usart_write(void *opaque, hwaddr addr, /* XXX this blocks entire thread. Rewrite to use * qemu_chr_fe_write and background I/O callbacks */ qemu_chr_fe_write_all(&s->chr, &ch, 1); + /* XXX I/O are currently synchronous, making it impossible for + software to observe transient states where TXE or TC aren't + set. Unlike TXE however, which is read-only, software may + clear TC by writing 0 to the SR register, so set it again + on each write. */ s->usart_sr |= USART_SR_TC; - s->usart_sr &= ~USART_SR_TXE; } return; case USART_BRR: diff --git a/include/hw/char/stm32f2xx_usart.h b/include/hw/char/stm32f2xx_usart.h index 9d03a7527c..84c4029777 100644 --- a/include/hw/char/stm32f2xx_usart.h +++ b/include/hw/char/stm32f2xx_usart.h @@ -37,7 +37,12 @@ #define USART_CR3 0x14 #define USART_GTPR 0x18 -#define USART_SR_RESET 0x00C00000 +/* + * NB: The reset value mentioned in "24.6.1 Status register" seems bogus. + * Looking at "Table 98 USART register map and reset values", it seems it + * should be 0xc0, and that's how real hardware behaves. + */ +#define USART_SR_RESET (USART_SR_TXE | USART_SR_TC) #define USART_SR_TXE (1 << 7) #define USART_SR_TC (1 << 6) From 5c1d3a2b6e5c084696b57edc33aa4bb554e7c37b Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 22 Feb 2018 15:12:51 +0000 Subject: [PATCH 04/32] Fix ast2500 protection register emulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some register blocks of the ast2500 are protected by protection key registers which require the right magic value to be written to those registers to allow those registers to be mutated. Register manuals indicate that writing the correct magic value to these registers should cause subsequent reads from those values to return 1, and writing any other value should cause subsequent reads to return 0. Previously, qemu implemented these registers incorrectly: the registers were handled as simple memory, meaning that writing some value x to a protection key register would result in subsequent reads from that register returning the same value x. The protection was implemented by ensuring that the current value of that register equaled the magic value. This modifies qemu to have the correct behaviour: attempts to write to a ast2500 protection register results in a transition to 1 or 0 depending on whether the written value is the correct magic. The protection logic is updated to ensure that the value of the register is nonzero. This bug caused deadlocks with u-boot HEAD: when u-boot is done with a protectable register block, it attempts to lock it by writing the bitwise inverse of the correct magic value, and then spinning forever until the register reads as zero. Since qemu implemented writes to these registers as ordinary memory writes, writing the inverse of the magic value resulted in subsequent reads returning that value, leading to u-boot spinning forever. Signed-off-by: Hugo Landau Reviewed-by: Cédric Le Goater Acked-by: Andrew Jeffery Message-id: 20180220132627.4163-1-hlandau@devever.net [PMM: fixed incorrect code indentation] Signed-off-by: Peter Maydell --- hw/misc/aspeed_scu.c | 6 +++++- hw/misc/aspeed_sdmc.c | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c index 74537ce975..5e6d5744ee 100644 --- a/hw/misc/aspeed_scu.c +++ b/hw/misc/aspeed_scu.c @@ -191,7 +191,7 @@ static void aspeed_scu_write(void *opaque, hwaddr offset, uint64_t data, } if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 && - s->regs[PROT_KEY] != ASPEED_SCU_PROT_KEY) { + !s->regs[PROT_KEY]) { qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__); return; } @@ -199,6 +199,10 @@ static void aspeed_scu_write(void *opaque, hwaddr offset, uint64_t data, trace_aspeed_scu_write(offset, size, data); switch (reg) { + case PROT_KEY: + s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0; + return; + case FREQ_CNTR_EVAL: case VGA_SCRATCH1 ... VGA_SCRATCH8: case RNG_DATA: diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c index f0b3053fae..0df008e52a 100644 --- a/hw/misc/aspeed_sdmc.c +++ b/hw/misc/aspeed_sdmc.c @@ -110,7 +110,12 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data, return; } - if (addr != R_PROT && s->regs[R_PROT] != PROT_KEY_UNLOCK) { + if (addr == R_PROT) { + s->regs[addr] = (data == PROT_KEY_UNLOCK) ? 1 : 0; + return; + } + + if (!s->regs[R_PROT]) { qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__); return; } @@ -123,6 +128,7 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data, data &= ~ASPEED_SDMC_READONLY_MASK; break; case AST2500_A0_SILICON_REV: + case AST2500_A1_SILICON_REV: data &= ~ASPEED_SDMC_AST2500_READONLY_MASK; break; default: From d9f98aab67bd5e0de4d8a53139806337d6caf5b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:51 +0000 Subject: [PATCH 05/32] hw/sd/milkymist-memcard: use qemu_log_mask() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Acked-by: Michael Walle Message-id: 20180216022933.10945-2-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/milkymist-memcard.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c index 341da88552..1292c0c099 100644 --- a/hw/sd/milkymist-memcard.c +++ b/hw/sd/milkymist-memcard.c @@ -22,11 +22,12 @@ */ #include "qemu/osdep.h" +#include "qemu/log.h" #include "hw/hw.h" #include "hw/sysbus.h" #include "sysemu/sysemu.h" #include "trace.h" -#include "qemu/error-report.h" +#include "include/qapi/error.h" #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/sd/sd.h" @@ -138,8 +139,8 @@ static uint64_t memcard_read(void *opaque, hwaddr addr, } else { r = s->response[s->response_read_ptr++]; if (s->response_read_ptr > s->response_len) { - error_report("milkymist_memcard: " - "read more cmd bytes than available. Clipping."); + qemu_log_mask(LOG_GUEST_ERROR, "milkymist_memcard: " + "read more cmd bytes than available. Clipping."); s->response_read_ptr = 0; } } @@ -163,8 +164,9 @@ static uint64_t memcard_read(void *opaque, hwaddr addr, break; default: - error_report("milkymist_memcard: read access to unknown register 0x" - TARGET_FMT_plx, addr << 2); + qemu_log_mask(LOG_UNIMP, "milkymist_memcard: " + "read access to unknown register 0x%" HWADDR_PRIx "\n", + addr << 2); break; } @@ -220,8 +222,9 @@ static void memcard_write(void *opaque, hwaddr addr, uint64_t value, break; default: - error_report("milkymist_memcard: write access to unknown register 0x" - TARGET_FMT_plx, addr << 2); + qemu_log_mask(LOG_UNIMP, "milkymist_memcard: " + "write access to unknown register 0x%" HWADDR_PRIx " " + "(value 0x%" PRIx64 ")\n", addr << 2, value); break; } } From 85fd6e5db15173fcbf214e5667860e5d634156d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:51 +0000 Subject: [PATCH 06/32] hw/sd/milkymist-memcard: split realize() out of SysBusDevice init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create the SDCard in the realize() function. Suggested-by: Michael Walle Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Acked-by: Michael Walle Message-id: 20180216022933.10945-3-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/milkymist-memcard.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c index 1292c0c099..a8e65892c7 100644 --- a/hw/sd/milkymist-memcard.c +++ b/hw/sd/milkymist-memcard.c @@ -257,27 +257,31 @@ static void milkymist_memcard_reset(DeviceState *d) device_reset(DEVICE(s->card)); } -static int milkymist_memcard_init(SysBusDevice *dev) +static void milkymist_memcard_init(Object *obj) +{ + MilkymistMemcardState *s = MILKYMIST_MEMCARD(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->regs_region, OBJECT(s), &memcard_mmio_ops, s, + "milkymist-memcard", R_MAX * 4); + sysbus_init_mmio(dev, &s->regs_region); +} + +static void milkymist_memcard_realize(DeviceState *dev, Error **errp) { MilkymistMemcardState *s = MILKYMIST_MEMCARD(dev); - DriveInfo *dinfo; BlockBackend *blk; + DriveInfo *dinfo; /* FIXME use a qdev drive property instead of drive_get_next() */ dinfo = drive_get_next(IF_SD); blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; s->card = sd_init(blk, false); if (s->card == NULL) { - return -1; + error_setg(errp, "failed to init SD card"); + return; } - s->enabled = blk && blk_is_inserted(blk); - - memory_region_init_io(&s->regs_region, OBJECT(s), &memcard_mmio_ops, s, - "milkymist-memcard", R_MAX * 4); - sysbus_init_mmio(dev, &s->regs_region); - - return 0; } static const VMStateDescription vmstate_milkymist_memcard = { @@ -300,9 +304,8 @@ static const VMStateDescription vmstate_milkymist_memcard = { static void milkymist_memcard_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = milkymist_memcard_init; + dc->realize = milkymist_memcard_realize; dc->reset = milkymist_memcard_reset; dc->vmsd = &vmstate_milkymist_memcard; /* Reason: init() method uses drive_get_next() */ @@ -313,6 +316,7 @@ static const TypeInfo milkymist_memcard_info = { .name = TYPE_MILKYMIST_MEMCARD, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(MilkymistMemcardState), + .instance_init = milkymist_memcard_init, .class_init = milkymist_memcard_class_init, }; From 3d0369ba499866cc6a839f71212d97876500762d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:52 +0000 Subject: [PATCH 07/32] hw/sd/milkymist-memcard: expose a SDBus and connect the SDCard to it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit using the sdbus_*() API. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Acked-by: Michael Walle Message-id: 20180216022933.10945-4-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/milkymist-memcard.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c index a8e65892c7..5570c1e9a0 100644 --- a/hw/sd/milkymist-memcard.c +++ b/hw/sd/milkymist-memcard.c @@ -69,7 +69,7 @@ struct MilkymistMemcardState { SysBusDevice parent_obj; MemoryRegion regs_region; - SDState *card; + SDBus sdbus; int command_write_ptr; int response_read_ptr; @@ -105,7 +105,7 @@ static void memcard_sd_command(MilkymistMemcardState *s) req.crc = s->command[5]; s->response[0] = req.cmd; - s->response_len = sd_do_command(s->card, &req, s->response+1); + s->response_len = sdbus_do_command(&s->sdbus, &req, s->response + 1); s->response_read_ptr = 0; if (s->response_len == 16) { @@ -150,10 +150,10 @@ static uint64_t memcard_read(void *opaque, hwaddr addr, r = 0xffffffff; } else { r = 0; - r |= sd_read_data(s->card) << 24; - r |= sd_read_data(s->card) << 16; - r |= sd_read_data(s->card) << 8; - r |= sd_read_data(s->card); + r |= sdbus_read_data(&s->sdbus) << 24; + r |= sdbus_read_data(&s->sdbus) << 16; + r |= sdbus_read_data(&s->sdbus) << 8; + r |= sdbus_read_data(&s->sdbus); } break; case R_CLK2XDIV: @@ -207,10 +207,10 @@ static void memcard_write(void *opaque, hwaddr addr, uint64_t value, if (!s->enabled) { break; } - sd_write_data(s->card, (value >> 24) & 0xff); - sd_write_data(s->card, (value >> 16) & 0xff); - sd_write_data(s->card, (value >> 8) & 0xff); - sd_write_data(s->card, value & 0xff); + sdbus_write_data(&s->sdbus, (value >> 24) & 0xff); + sdbus_write_data(&s->sdbus, (value >> 16) & 0xff); + sdbus_write_data(&s->sdbus, (value >> 8) & 0xff); + sdbus_write_data(&s->sdbus, value & 0xff); break; case R_ENABLE: s->regs[addr] = value; @@ -251,10 +251,6 @@ static void milkymist_memcard_reset(DeviceState *d) for (i = 0; i < R_MAX; i++) { s->regs[i] = 0; } - /* Since we're still using the legacy SD API the card is not plugged - * into any bus, and we must reset it manually. - */ - device_reset(DEVICE(s->card)); } static void milkymist_memcard_init(Object *obj) @@ -270,15 +266,23 @@ static void milkymist_memcard_init(Object *obj) static void milkymist_memcard_realize(DeviceState *dev, Error **errp) { MilkymistMemcardState *s = MILKYMIST_MEMCARD(dev); + DeviceState *carddev; BlockBackend *blk; DriveInfo *dinfo; + Error *err = NULL; + qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS, + dev, "sd-bus"); + + /* Create and plug in the sd card */ /* FIXME use a qdev drive property instead of drive_get_next() */ dinfo = drive_get_next(IF_SD); blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; - s->card = sd_init(blk, false); - if (s->card == NULL) { - error_setg(errp, "failed to init SD card"); + carddev = qdev_create(&s->sdbus.qbus, TYPE_SD_CARD); + qdev_prop_set_drive(carddev, "drive", blk, &err); + object_property_set_bool(OBJECT(carddev), true, "realized", &err); + if (err) { + error_setg(errp, "failed to init SD card: %s", error_get_pretty(err)); return; } s->enabled = blk && blk_is_inserted(blk); From c3abd91309b476ca539b3ec73b30887d4759aba8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:52 +0000 Subject: [PATCH 08/32] hw/sd/ssi-sd: use the SDBus API, connect the SDCard to the bus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On reset the bus will reset the card, we can now drop the device_reset() call. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180216022933.10945-5-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/ssi-sd.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c index f88f509e0a..ae04b6641b 100644 --- a/hw/sd/ssi-sd.c +++ b/hw/sd/ssi-sd.c @@ -47,7 +47,7 @@ typedef struct { int32_t arglen; int32_t response_pos; int32_t stopping; - SDState *sd; + SDBus sdbus; } ssi_sd_state; #define TYPE_SSI_SD "ssi-sd" @@ -100,7 +100,7 @@ static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val) request.arg = (s->cmdarg[0] << 24) | (s->cmdarg[1] << 16) | (s->cmdarg[2] << 8) | s->cmdarg[3]; DPRINTF("CMD%d arg 0x%08x\n", s->cmd, request.arg); - s->arglen = sd_do_command(s->sd, &request, longresp); + s->arglen = sdbus_do_command(&s->sdbus, &request, longresp); if (s->arglen <= 0) { s->arglen = 1; s->response[0] = 4; @@ -177,7 +177,7 @@ static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val) DPRINTF("Response 0x%02x\n", s->response[s->response_pos]); return s->response[s->response_pos++]; } - if (sd_data_ready(s->sd)) { + if (sdbus_data_ready(&s->sdbus)) { DPRINTF("Data read\n"); s->mode = SSI_SD_DATA_START; } else { @@ -190,8 +190,8 @@ static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val) s->mode = SSI_SD_DATA_READ; return 0xfe; case SSI_SD_DATA_READ: - val = sd_read_data(s->sd); - if (!sd_data_ready(s->sd)) { + val = sdbus_read_data(&s->sdbus); + if (!sdbus_data_ready(&s->sdbus)) { DPRINTF("Data read end\n"); s->mode = SSI_SD_CMD; } @@ -242,13 +242,24 @@ static const VMStateDescription vmstate_ssi_sd = { static void ssi_sd_realize(SSISlave *d, Error **errp) { ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, d); + DeviceState *carddev; DriveInfo *dinfo; + Error *err = NULL; + qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS, + DEVICE(d), "sd-bus"); + + /* Create and plug in the sd card */ /* FIXME use a qdev drive property instead of drive_get_next() */ dinfo = drive_get_next(IF_SD); - s->sd = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, true); - if (s->sd == NULL) { - error_setg(errp, "Device initialization failed."); + carddev = qdev_create(&s->sdbus.qbus, TYPE_SD_CARD); + if (dinfo) { + qdev_prop_set_drive(carddev, "drive", blk_by_legacy_dinfo(dinfo), &err); + } + object_property_set_bool(OBJECT(carddev), true, "spi", &err); + object_property_set_bool(OBJECT(carddev), true, "realized", &err); + if (err) { + error_setg(errp, "failed to init SD card: %s", error_get_pretty(err)); return; } } @@ -264,11 +275,6 @@ static void ssi_sd_reset(DeviceState *dev) s->arglen = 0; s->response_pos = 0; s->stopping = 0; - - /* Since we're still using the legacy SD API the card is not plugged - * into any bus, and we must reset it manually. - */ - device_reset(DEVICE(s->sd)); } static void ssi_sd_class_init(ObjectClass *klass, void *data) From d49b1ce0a39ab5cf41c7bea33bbee973fc0e05f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:52 +0000 Subject: [PATCH 09/32] sdcard: reorder SDState struct members MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit place card registers first, this will ease further code movements. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215220540.6556-2-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 9ac9b63ff8..ce1f2fdf76 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -88,16 +88,21 @@ enum SDCardStates { struct SDState { DeviceState parent_obj; - uint32_t mode; /* current card mode, one of SDCardModes */ - int32_t state; /* current card state, one of SDCardStates */ + /* SD Memory Card Registers */ uint32_t ocr; - QEMUTimer *ocr_power_timer; uint8_t scr[8]; uint8_t cid[16]; uint8_t csd[16]; uint16_t rca; uint32_t card_status; uint8_t sd_status[64]; + + /* Configurable properties */ + BlockBackend *blk; + bool spi; + + uint32_t mode; /* current card mode, one of SDCardModes */ + int32_t state; /* current card state, one of SDCardStates */ uint32_t vhs; bool wp_switch; unsigned long *wp_groups; @@ -110,8 +115,6 @@ struct SDState { uint8_t pwd[16]; uint32_t pwd_len; uint8_t function_group[6]; - - bool spi; uint8_t current_cmd; /* True if we will handle the next command as an ACMD. Note that this does * *not* track the APP_CMD status bit! @@ -123,8 +126,7 @@ struct SDState { uint8_t data[512]; qemu_irq readonly_cb; qemu_irq inserted_cb; - BlockBackend *blk; - + QEMUTimer *ocr_power_timer; bool enable; uint8_t dat_lines; bool cmd_line; From 1b640aa9292bc00beb441e97d862ba322a7ba18d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:52 +0000 Subject: [PATCH 10/32] sdcard: replace DPRINTF() by trace events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215220540.6556-3-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 32 ++++++++++++++++++++++++++------ hw/sd/trace-events | 6 ++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index ce1f2fdf76..72e9b47e34 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -40,6 +40,7 @@ #include "qemu/error-report.h" #include "qemu/timer.h" #include "qemu/log.h" +#include "trace.h" //#define DEBUG_SD 1 @@ -132,6 +133,26 @@ struct SDState { bool cmd_line; }; +static const char *sd_state_name(enum SDCardStates state) +{ + static const char *state_name[] = { + [sd_idle_state] = "idle", + [sd_ready_state] = "ready", + [sd_identification_state] = "identification", + [sd_standby_state] = "standby", + [sd_transfer_state] = "transfer", + [sd_sendingdata_state] = "sendingdata", + [sd_receivingdata_state] = "receivingdata", + [sd_programming_state] = "programming", + [sd_disconnect_state] = "disconnect", + }; + if (state == sd_inactive_state) { + return "inactive"; + } + assert(state <= ARRAY_SIZE(state_name)); + return state_name[state]; +} + static uint8_t sd_get_dat_lines(SDState *sd) { return sd->enable ? sd->dat_lines : 0; @@ -776,6 +797,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, uint32_t rca = 0x0000; uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg; + trace_sdcard_normal_command(req.cmd, req.arg, sd_state_name(sd->state)); + /* Not interpreting this as an app command */ sd->card_status &= ~APP_CMD; @@ -790,7 +813,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, sd->multi_blk_cnt = 0; } - DPRINTF("CMD%d 0x%08x state %d\n", req.cmd, req.arg, sd->state); switch (req.cmd) { /* Basic commands (Class 0 and Class 1) */ case 0: /* CMD0: GO_IDLE_STATE */ @@ -1310,8 +1332,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, return sd_r1; case 56: /* CMD56: GEN_CMD */ - fprintf(stderr, "SD: GEN_CMD 0x%08x\n", req.arg); - switch (sd->state) { case sd_transfer_state: sd->data_offset = 0; @@ -1345,7 +1365,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, static sd_rsp_type_t sd_app_command(SDState *sd, SDRequest req) { - DPRINTF("ACMD%d 0x%08x\n", req.cmd, req.arg); + trace_sdcard_app_command(req.cmd, req.arg); sd->card_status |= APP_CMD; switch (req.cmd) { case 6: /* ACMD6: SET_BUS_WIDTH */ @@ -1606,8 +1626,7 @@ send_response: static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len) { - DPRINTF("sd_blk_read: addr = 0x%08llx, len = %d\n", - (unsigned long long) addr, len); + trace_sdcard_read_block(addr, len); if (!sd->blk || blk_pread(sd->blk, addr, sd->data, len) < 0) { fprintf(stderr, "sd_blk_read: read error on host side\n"); } @@ -1615,6 +1634,7 @@ static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len) static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len) { + trace_sdcard_write_block(addr, len); if (!sd->blk || blk_pwrite(sd->blk, addr, sd->data, len, 0) < 0) { fprintf(stderr, "sd_blk_write: write error on host side\n"); } diff --git a/hw/sd/trace-events b/hw/sd/trace-events index 0f8536db32..75dac5a2cd 100644 --- a/hw/sd/trace-events +++ b/hw/sd/trace-events @@ -23,6 +23,12 @@ sdhci_read_dataport(uint16_t data_count) "all %u bytes of data have been read fr sdhci_write_dataport(uint16_t data_count) "write buffer filled with %u bytes of data" sdhci_capareg(const char *desc, uint16_t val) "%s: %u" +# hw/sd/sd.c +sdcard_normal_command(uint8_t cmd, uint32_t arg, const char *state) "CMD%d arg 0x%08x (state %s)" +sdcard_app_command(uint8_t acmd, uint32_t arg) "ACMD%d arg 0x%08x" +sdcard_read_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x" +sdcard_write_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x" + # hw/sd/milkymist-memcard.c milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" From 55921932317ed8c1e073e876471c921a3b2a984f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:52 +0000 Subject: [PATCH 11/32] sdcard: add a trace event for command responses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Message-id: 20180215220540.6556-4-f4bug@amsat.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/sd/sd.c | 27 ++++++++++++++++++++++++--- hw/sd/trace-events | 1 + 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 72e9b47e34..8f72cde534 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -153,6 +153,27 @@ static const char *sd_state_name(enum SDCardStates state) return state_name[state]; } +static const char *sd_response_name(sd_rsp_type_t rsp) +{ + static const char *response_name[] = { + [sd_r0] = "RESP#0 (no response)", + [sd_r1] = "RESP#1 (normal cmd)", + [sd_r2_i] = "RESP#2 (CID reg)", + [sd_r2_s] = "RESP#2 (CSD reg)", + [sd_r3] = "RESP#3 (OCR reg)", + [sd_r6] = "RESP#6 (RCA)", + [sd_r7] = "RESP#7 (operating voltage)", + }; + if (rsp == sd_illegal) { + return "ILLEGAL RESP"; + } + if (rsp == sd_r1b) { + rsp = sd_r1; + } + assert(rsp <= ARRAY_SIZE(response_name)); + return response_name[rsp]; +} + static uint8_t sd_get_dat_lines(SDState *sd) { return sd->enable ? sd->dat_lines : 0; @@ -1596,10 +1617,12 @@ send_response: case sd_r0: case sd_illegal: - default: rsplen = 0; break; + default: + g_assert_not_reached(); } + trace_sdcard_response(sd_response_name(rtype), rsplen); if (rtype != sd_illegal) { /* Clear the "clear on valid command" status bits now we've @@ -1616,8 +1639,6 @@ send_response: DPRINTF(" %02x", response[i]); } DPRINTF(" state %d\n", sd->state); - } else { - DPRINTF("No response %d\n", sd->state); } #endif diff --git a/hw/sd/trace-events b/hw/sd/trace-events index 75dac5a2cd..b2aa19ec0d 100644 --- a/hw/sd/trace-events +++ b/hw/sd/trace-events @@ -26,6 +26,7 @@ sdhci_capareg(const char *desc, uint16_t val) "%s: %u" # hw/sd/sd.c sdcard_normal_command(uint8_t cmd, uint32_t arg, const char *state) "CMD%d arg 0x%08x (state %s)" sdcard_app_command(uint8_t acmd, uint32_t arg) "ACMD%d arg 0x%08x" +sdcard_response(const char *rspdesc, int rsplen) "%s (sz:%d)" sdcard_read_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x" sdcard_write_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x" From 5cd5e2e7e393a4104c6fd4bf6677ba00e70218e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:52 +0000 Subject: [PATCH 12/32] sdcard: replace fprintf() by qemu_hexdump() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215220540.6556-5-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 8f72cde534..ceab263970 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -44,13 +44,6 @@ //#define DEBUG_SD 1 -#ifdef DEBUG_SD -#define DPRINTF(fmt, ...) \ -do { fprintf(stderr, "SD: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) do {} while(0) -#endif - #define ACMD41_ENQUIRY_MASK 0x00ffffff #define OCR_POWER_UP 0x80000000 #define OCR_POWER_DELAY_NS 500000 /* 0.5ms */ @@ -1632,14 +1625,7 @@ send_response: } #ifdef DEBUG_SD - if (rsplen) { - int i; - DPRINTF("Response:"); - for (i = 0; i < rsplen; i++) { - DPRINTF(" %02x", response[i]); - } - DPRINTF(" state %d\n", sd->state); - } + qemu_hexdump((const char *)response, stderr, "Response", rsplen); #endif return rsplen; From 814b2adc1635336e1b8d1c5ec36dce5504ff0113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:52 +0000 Subject: [PATCH 13/32] sdcard: add more trace events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Acked-by: Alistair Francis Message-id: 20180215220540.6556-6-f4bug@amsat.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/sd/sd.c | 32 ++++++++++++++++++++++++++------ hw/sd/trace-events | 13 +++++++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index ceab263970..564f7a9bfd 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -179,6 +179,8 @@ static bool sd_get_cmd_line(SDState *sd) static void sd_set_voltage(SDState *sd, uint16_t millivolts) { + trace_sdcard_set_voltage(millivolts); + switch (millivolts) { case 3001 ... 3600: /* SD_VOLTAGE_3_3V */ case 2001 ... 3000: /* SD_VOLTAGE_3_0V */ @@ -274,6 +276,7 @@ static void sd_ocr_powerup(void *opaque) { SDState *sd = opaque; + trace_sdcard_powerup(); /* Set powered up bit in OCR */ assert(!(sd->ocr & OCR_POWER_UP)); sd->ocr |= OCR_POWER_UP; @@ -477,6 +480,7 @@ static void sd_reset(DeviceState *dev) uint64_t size; uint64_t sect; + trace_sdcard_reset(); if (sd->blk) { blk_get_geometry(sd->blk, §); } else { @@ -530,7 +534,10 @@ static void sd_cardchange(void *opaque, bool load, Error **errp) bool readonly = sd_get_readonly(sd); if (inserted) { + trace_sdcard_inserted(readonly); sd_reset(dev); + } else { + trace_sdcard_ejected(); } /* The IRQ notification is for legacy non-QOM SD controller devices; @@ -662,6 +669,7 @@ static void sd_erase(SDState *sd) uint64_t erase_start = sd->erase_start; uint64_t erase_end = sd->erase_end; + trace_sdcard_erase(); if (!sd->erase_start || !sd->erase_end) { sd->card_status |= ERASE_SEQ_ERROR; return; @@ -751,6 +759,11 @@ static void sd_lock_command(SDState *sd) else pwd_len = 0; + if (lock) { + trace_sdcard_lock(); + } else { + trace_sdcard_unlock(); + } if (erase) { if (!(sd->card_status & CARD_IS_LOCKED) || sd->blk_len > 1 || set_pwd || clr_pwd || lock || sd->wp_switch || @@ -1077,10 +1090,12 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, case 16: /* CMD16: SET_BLOCKLEN */ switch (sd->state) { case sd_transfer_state: - if (req.arg > (1 << HWBLOCK_SHIFT)) + if (req.arg > (1 << HWBLOCK_SHIFT)) { sd->card_status |= BLOCK_LEN_ERROR; - else + } else { + trace_sdcard_set_blocklen(req.arg); sd->blk_len = req.arg; + } return sd_r1; @@ -1452,10 +1467,13 @@ static sd_rsp_type_t sd_app_command(SDState *sd, if ((req.arg & ACMD41_ENQUIRY_MASK) != 0) { timer_del(sd->ocr_power_timer); sd_ocr_powerup(sd); - } else if (!timer_pending(sd->ocr_power_timer)) { - timer_mod_ns(sd->ocr_power_timer, - (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - + OCR_POWER_DELAY_NS)); + } else { + trace_sdcard_inquiry_cmd41(); + if (!timer_pending(sd->ocr_power_timer)) { + timer_mod_ns(sd->ocr_power_timer, + (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + OCR_POWER_DELAY_NS)); + } } } @@ -1668,6 +1686,7 @@ void sd_write_data(SDState *sd, uint8_t value) if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION)) return; + trace_sdcard_write_data(sd->current_cmd, value); switch (sd->current_cmd) { case 24: /* CMD24: WRITE_SINGLE_BLOCK */ sd->data[sd->data_offset ++] = value; @@ -1805,6 +1824,7 @@ uint8_t sd_read_data(SDState *sd) io_len = (sd->ocr & (1 << 30)) ? 512 : sd->blk_len; + trace_sdcard_read_data(sd->current_cmd, io_len); switch (sd->current_cmd) { case 6: /* CMD6: SWITCH_FUNCTION */ ret = sd->data[sd->data_offset ++]; diff --git a/hw/sd/trace-events b/hw/sd/trace-events index b2aa19ec0d..3040d32560 100644 --- a/hw/sd/trace-events +++ b/hw/sd/trace-events @@ -27,8 +27,21 @@ sdhci_capareg(const char *desc, uint16_t val) "%s: %u" sdcard_normal_command(uint8_t cmd, uint32_t arg, const char *state) "CMD%d arg 0x%08x (state %s)" sdcard_app_command(uint8_t acmd, uint32_t arg) "ACMD%d arg 0x%08x" sdcard_response(const char *rspdesc, int rsplen) "%s (sz:%d)" +sdcard_powerup(void) "" +sdcard_inquiry_cmd41(void) "" +sdcard_set_enable(bool current_state, bool new_state) "%u -> %u" +sdcard_reset(void) "" +sdcard_set_blocklen(uint16_t length) "0x%04x" +sdcard_inserted(bool readonly) "read_only: %u" +sdcard_ejected(void) "" +sdcard_erase(void) "" +sdcard_lock(void) "" +sdcard_unlock(void) "" sdcard_read_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x" sdcard_write_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x" +sdcard_write_data(uint8_t cmd, uint8_t value) "CMD%02d value 0x%02x" +sdcard_read_data(uint8_t cmd, int length) "CMD%02d len %d" +sdcard_set_voltage(uint16_t millivolts) "%u mV" # hw/sd/milkymist-memcard.c milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" From f250015be6e208dbb9c45873ad7abb96ac893927 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:52 +0000 Subject: [PATCH 14/32] sdcard: define SDMMC_CMD_MAX instead of using the magic '64' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215220540.6556-8-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 22 ++++++++++++++++------ hw/sd/sdmmc-internal.h | 15 +++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 hw/sd/sdmmc-internal.h diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 564f7a9bfd..90d1e27ee7 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -40,6 +40,7 @@ #include "qemu/error-report.h" #include "qemu/timer.h" #include "qemu/log.h" +#include "sdmmc-internal.h" #include "trace.h" //#define DEBUG_SD 1 @@ -215,18 +216,21 @@ static void sd_set_mode(SDState *sd) } } -static const sd_cmd_type_t sd_cmd_type[64] = { +static const sd_cmd_type_t sd_cmd_type[SDMMC_CMD_MAX] = { sd_bc, sd_none, sd_bcr, sd_bcr, sd_none, sd_none, sd_none, sd_ac, sd_bcr, sd_ac, sd_ac, sd_adtc, sd_ac, sd_ac, sd_none, sd_ac, + /* 16 */ sd_ac, sd_adtc, sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none, sd_adtc, sd_adtc, sd_adtc, sd_adtc, sd_ac, sd_ac, sd_adtc, sd_none, + /* 32 */ sd_ac, sd_ac, sd_none, sd_none, sd_none, sd_none, sd_ac, sd_none, sd_none, sd_none, sd_bc, sd_none, sd_none, sd_none, sd_none, sd_none, + /* 48 */ sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_ac, sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, }; -static const int sd_cmd_class[64] = { +static const int sd_cmd_class[SDMMC_CMD_MAX] = { 0, 0, 0, 0, 0, 9, 10, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 6, 6, 6, 6, 5, 5, 10, 10, 10, 10, 5, 9, 9, 9, 7, 7, 7, 7, 7, 7, @@ -829,8 +833,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, /* Not interpreting this as an app command */ sd->card_status &= ~APP_CMD; - if (sd_cmd_type[req.cmd & 0x3F] == sd_ac - || sd_cmd_type[req.cmd & 0x3F] == sd_adtc) { + if (sd_cmd_type[req.cmd] == sd_ac + || sd_cmd_type[req.cmd] == sd_adtc) { rca = req.arg >> 16; } @@ -1542,8 +1546,8 @@ static int cmd_valid_while_locked(SDState *sd, SDRequest *req) if (req->cmd == 16 || req->cmd == 55) { return 1; } - return sd_cmd_class[req->cmd & 0x3F] == 0 - || sd_cmd_class[req->cmd & 0x3F] == 7; + return sd_cmd_class[req->cmd] == 0 + || sd_cmd_class[req->cmd] == 7; } int sd_do_command(SDState *sd, SDRequest *req, @@ -1562,6 +1566,12 @@ int sd_do_command(SDState *sd, SDRequest *req, goto send_response; } + if (req->cmd >= SDMMC_CMD_MAX) { + qemu_log_mask(LOG_GUEST_ERROR, "SD: incorrect command 0x%02x\n", + req->cmd); + req->cmd &= 0x3f; + } + if (sd->card_status & CARD_IS_LOCKED) { if (!cmd_valid_while_locked(sd, req)) { sd->card_status |= ILLEGAL_COMMAND; diff --git a/hw/sd/sdmmc-internal.h b/hw/sd/sdmmc-internal.h new file mode 100644 index 0000000000..0e96cb0081 --- /dev/null +++ b/hw/sd/sdmmc-internal.h @@ -0,0 +1,15 @@ +/* + * SD/MMC cards common + * + * Copyright (c) 2018 Philippe Mathieu-Daudé + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef SD_INTERNAL_H +#define SD_INTERNAL_H + +#define SDMMC_CMD_MAX 64 + +#endif From 7af83490fe02e6ca4d97ef736e24d65a5fb1b1c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:52 +0000 Subject: [PATCH 15/32] sdcard: use G_BYTE from cutils MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit code is now easier to read. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215220540.6556-11-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 90d1e27ee7..b3698e34ad 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -36,6 +36,7 @@ #include "hw/sd/sd.h" #include "qapi/error.h" #include "qemu/bitmap.h" +#include "qemu/cutils.h" #include "hw/qdev-properties.h" #include "qemu/error-report.h" #include "qemu/timer.h" @@ -343,7 +344,7 @@ static void sd_set_csd(SDState *sd, uint64_t size) uint32_t sectsize = (1 << (SECTOR_SHIFT + 1)) - 1; uint32_t wpsize = (1 << (WPGROUP_SHIFT + 1)) - 1; - if (size <= 0x40000000) { /* Standard Capacity SD */ + if (size <= 1 * G_BYTE) { /* Standard Capacity SD */ sd->csd[0] = 0x00; /* CSD structure */ sd->csd[1] = 0x26; /* Data read access-time-1 */ sd->csd[2] = 0x00; /* Data read access-time-2 */ From 6f296421f8963bfd2cae13b4648b2c115f7562c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:52 +0000 Subject: [PATCH 16/32] sdcard: use the registerfields API to access the OCR register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215220540.6556-12-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 21 +++++++++++++-------- include/hw/sd/sd.h | 1 - 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index b3698e34ad..706cb52668 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -32,6 +32,7 @@ #include "qemu/osdep.h" #include "hw/qdev.h" #include "hw/hw.h" +#include "hw/registerfields.h" #include "sysemu/block-backend.h" #include "hw/sd/sd.h" #include "qapi/error.h" @@ -47,8 +48,6 @@ //#define DEBUG_SD 1 #define ACMD41_ENQUIRY_MASK 0x00ffffff -#define OCR_POWER_UP 0x80000000 -#define OCR_POWER_DELAY_NS 500000 /* 0.5ms */ typedef enum { sd_r0 = 0, /* no response */ @@ -271,6 +270,11 @@ static uint16_t sd_crc16(void *message, size_t width) return shift_reg; } +#define OCR_POWER_DELAY_NS 500000 /* 0.5ms */ + +FIELD(OCR, CARD_CAPACITY, 30, 1) /* 0:SDSC, 1:SDHC/SDXC */ +FIELD(OCR, CARD_POWER_UP, 31, 1) + static void sd_set_ocr(SDState *sd) { /* All voltages OK, Standard Capacity SD Memory Card, not yet powered up */ @@ -282,9 +286,10 @@ static void sd_ocr_powerup(void *opaque) SDState *sd = opaque; trace_sdcard_powerup(); - /* Set powered up bit in OCR */ - assert(!(sd->ocr & OCR_POWER_UP)); - sd->ocr |= OCR_POWER_UP; + assert(!FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP)); + + /* card power-up OK */ + sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_POWER_UP, 1); } static void sd_set_scr(SDState *sd) @@ -570,7 +575,7 @@ static bool sd_ocr_vmstate_needed(void *opaque) SDState *sd = opaque; /* Include the OCR state (and timer) if it is not yet powered up */ - return !(sd->ocr & OCR_POWER_UP); + return !FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP); } static const VMStateDescription sd_ocr_vmstate = { @@ -680,7 +685,7 @@ static void sd_erase(SDState *sd) return; } - if (extract32(sd->ocr, OCR_CCS_BITN, 1)) { + if (FIELD_EX32(sd->ocr, OCR, CARD_CAPACITY)) { /* High capacity memory card: erase units are 512 byte blocks */ erase_start *= 512; erase_end *= 512; @@ -1468,7 +1473,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd, * UEFI, which sends an initial enquiry ACMD41, but * assumes that the card is in ready state as soon as it * sees the power up bit set. */ - if (!(sd->ocr & OCR_POWER_UP)) { + if (!FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP)) { if ((req.arg & ACMD41_ENQUIRY_MASK) != 0) { timer_del(sd->ocr_power_timer); sd_ocr_powerup(sd); diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h index bf1eb0713c..9bdb3c9285 100644 --- a/include/hw/sd/sd.h +++ b/include/hw/sd/sd.h @@ -53,7 +53,6 @@ #define READY_FOR_DATA (1 << 8) #define APP_CMD (1 << 5) #define AKE_SEQ_ERROR (1 << 3) -#define OCR_CCS_BITN 30 typedef enum { SD_VOLTAGE_0_4V = 400, /* currently not supported */ From 9273ea6123f129a66c9d119c124af40419d57423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:52 +0000 Subject: [PATCH 17/32] sdcard: Don't always set the high capacity bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't set the high capacity bit by default as it will be set if required in the sd_set_csd() function. [based on a patch from Alistair Francis and Peter Ogden from qemu/xilinx tag xilinx-v2015.4] Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215221325.7611-2-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 706cb52668..cc347ff782 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -290,6 +290,10 @@ static void sd_ocr_powerup(void *opaque) /* card power-up OK */ sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_POWER_UP, 1); + + if (sd->size > 1 * G_BYTE) { + sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_CAPACITY, 1); + } } static void sd_set_scr(SDState *sd) @@ -394,7 +398,6 @@ static void sd_set_csd(SDState *sd, uint64_t size) sd->csd[13] = 0x40; sd->csd[14] = 0x00; sd->csd[15] = 0x00; - sd->ocr |= 1 << 30; /* High Capacity SD Memory Card */ } } From e8feec808e96163dd82754521383a203b8fe7bce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:53 +0000 Subject: [PATCH 18/32] sdcard: update the CSD CRC register regardless the CSD structure version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215221325.7611-3-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index cc347ff782..110f2f1d0a 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -378,7 +378,6 @@ static void sd_set_csd(SDState *sd, uint64_t size) sd->csd[13] = 0x20 | /* Max. write data block length */ ((HWBLOCK_SHIFT << 6) & 0xc0); sd->csd[14] = 0x00; /* File format group */ - sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1; } else { /* SDHC */ size /= 512 * 1024; size -= 1; @@ -397,8 +396,8 @@ static void sd_set_csd(SDState *sd, uint64_t size) sd->csd[12] = 0x0a; sd->csd[13] = 0x40; sd->csd[14] = 0x00; - sd->csd[15] = 0x00; } + sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1; } static void sd_set_rca(SDState *sd) From d7ecb8675298fefdaea35f6d7a558e91ec0b4138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:53 +0000 Subject: [PATCH 19/32] sdcard: fix the 'maximum data transfer rate' to 25MHz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To comply with Spec v1.10 (and 2.00, 3.01): . TRAN_SPEED for current SD Memory Cards that field must be always 0_0110_010b (032h) which is equal to 25MHz - the mandatory maximum operating frequency of SD Memory Card. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215221325.7611-4-f4bug@amsat.org [PMM: fixed comment indent] Signed-off-by: Peter Maydell --- hw/sd/sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 110f2f1d0a..3526269dbe 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -357,7 +357,7 @@ static void sd_set_csd(SDState *sd, uint64_t size) sd->csd[0] = 0x00; /* CSD structure */ sd->csd[1] = 0x26; /* Data read access-time-1 */ sd->csd[2] = 0x00; /* Data read access-time-2 */ - sd->csd[3] = 0x5a; /* Max. data transfer rate */ + sd->csd[3] = 0x32; /* Max. data transfer rate: 25 MHz */ sd->csd[4] = 0x5f; /* Card Command Classes */ sd->csd[5] = 0x50 | /* Max. read data block length */ HWBLOCK_SHIFT; From 9b7ec55c5c66ca466a8e34f7780f13a8e77b8a99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:53 +0000 Subject: [PATCH 20/32] sdcard: clean the SCR register and add few comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215221325.7611-5-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 3526269dbe..c87142d648 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -298,10 +298,13 @@ static void sd_ocr_powerup(void *opaque) static void sd_set_scr(SDState *sd) { - sd->scr[0] = 0x00; /* SCR Structure */ - sd->scr[1] = 0x2f; /* SD Security Support */ - sd->scr[2] = 0x00; + sd->scr[0] = (0 << 4) /* SCR version 1.0 */ + | 0; /* Spec Versions 1.0 and 1.01 */ + sd->scr[1] = (2 << 4) /* SDSC Card (Security Version 1.01) */ + | 0b0101; /* 1-bit or 4-bit width bus modes */ + sd->scr[2] = 0x00; /* Extended Security is not supported. */ sd->scr[3] = 0x00; + /* reserved for manufacturer usage */ sd->scr[4] = 0x00; sd->scr[5] = 0x00; sd->scr[6] = 0x00; From 0aad4fdfd4c030ab0d0db312e849c7e5fb696b26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:53 +0000 Subject: [PATCH 21/32] sdcard: remove commands from unsupported old MMC specification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This device does not model MMCA Specification previous to v4.2 Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215221325.7611-6-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index c87142d648..e55bf1fa75 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1037,24 +1037,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, } break; - case 11: /* CMD11: READ_DAT_UNTIL_STOP */ - if (sd->spi) - goto bad_cmd; - switch (sd->state) { - case sd_transfer_state: - sd->state = sd_sendingdata_state; - sd->data_start = req.arg; - sd->data_offset = 0; - - if (sd->data_start + sd->blk_len > sd->size) - sd->card_status |= ADDRESS_ERROR; - return sd_r0; - - default: - break; - } - break; - case 12: /* CMD12: STOP_TRANSMISSION */ switch (sd->state) { case sd_sendingdata_state: @@ -1862,21 +1844,6 @@ uint8_t sd_read_data(SDState *sd) sd->state = sd_transfer_state; break; - case 11: /* CMD11: READ_DAT_UNTIL_STOP */ - if (sd->data_offset == 0) - BLK_READ_BLOCK(sd->data_start, io_len); - ret = sd->data[sd->data_offset ++]; - - if (sd->data_offset >= io_len) { - sd->data_start += io_len; - sd->data_offset = 0; - if (sd->data_start + io_len > sd->size) { - sd->card_status |= ADDRESS_ERROR; - break; - } - } - break; - case 13: /* ACMD13: SD_STATUS */ ret = sd->sd_status[sd->data_offset ++]; From 67bfddd62b97a6cb9c1da14a148c161b1ff18661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:53 +0000 Subject: [PATCH 22/32] sdcard: simplify using the ldst API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the code is easier to review/refactor. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215221325.7611-7-f4bug@amsat.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/sd/sd.c | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index e55bf1fa75..3e1f7e51ad 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -431,57 +431,39 @@ static int sd_req_crc_validate(SDRequest *req) { uint8_t buffer[5]; buffer[0] = 0x40 | req->cmd; - buffer[1] = (req->arg >> 24) & 0xff; - buffer[2] = (req->arg >> 16) & 0xff; - buffer[3] = (req->arg >> 8) & 0xff; - buffer[4] = (req->arg >> 0) & 0xff; + stl_be_p(&buffer[1], req->arg); return 0; return sd_crc7(buffer, 5) != req->crc; /* TODO */ } static void sd_response_r1_make(SDState *sd, uint8_t *response) { - uint32_t status = sd->card_status; + stl_be_p(response, sd->card_status); + /* Clear the "clear on read" status bits */ sd->card_status &= ~CARD_STATUS_C; - - response[0] = (status >> 24) & 0xff; - response[1] = (status >> 16) & 0xff; - response[2] = (status >> 8) & 0xff; - response[3] = (status >> 0) & 0xff; } static void sd_response_r3_make(SDState *sd, uint8_t *response) { - response[0] = (sd->ocr >> 24) & 0xff; - response[1] = (sd->ocr >> 16) & 0xff; - response[2] = (sd->ocr >> 8) & 0xff; - response[3] = (sd->ocr >> 0) & 0xff; + stl_be_p(response, sd->ocr); } static void sd_response_r6_make(SDState *sd, uint8_t *response) { - uint16_t arg; uint16_t status; - arg = sd->rca; status = ((sd->card_status >> 8) & 0xc000) | ((sd->card_status >> 6) & 0x2000) | (sd->card_status & 0x1fff); sd->card_status &= ~(CARD_STATUS_C & 0xc81fff); - - response[0] = (arg >> 8) & 0xff; - response[1] = arg & 0xff; - response[2] = (status >> 8) & 0xff; - response[3] = status & 0xff; + stw_be_p(response + 0, sd->rca); + stw_be_p(response + 2, status); } static void sd_response_r7_make(SDState *sd, uint8_t *response) { - response[0] = (sd->vhs >> 24) & 0xff; - response[1] = (sd->vhs >> 16) & 0xff; - response[2] = (sd->vhs >> 8) & 0xff; - response[3] = (sd->vhs >> 0) & 0xff; + stl_be_p(response, sd->vhs); } static inline uint64_t sd_addr_to_wpnum(uint64_t addr) @@ -727,7 +709,7 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr) static void sd_function_switch(SDState *sd, uint32_t arg) { - int i, mode, new_func, crc; + int i, mode, new_func; mode = !!(arg & 0x80000000); sd->data[0] = 0x00; /* Maximum current consumption */ @@ -751,9 +733,7 @@ static void sd_function_switch(SDState *sd, uint32_t arg) sd->data[14 + (i >> 1)] = new_func << ((i * 4) & 4); } memset(&sd->data[17], 0, 47); - crc = sd_crc16(sd->data, 64); - sd->data[65] = crc >> 8; - sd->data[66] = crc & 0xff; + stw_be_p(sd->data + 65, sd_crc16(sd->data, 64)); } static inline bool sd_wp_addr(SDState *sd, uint64_t addr) From 3d42fb52b281cfba2c7e29a6973c0b1549c12ca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:53 +0000 Subject: [PATCH 23/32] sdcard: use the correct masked OCR in the R3 reply MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use the registerfields API to access the OCR register Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215221325.7611-8-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 3e1f7e51ad..5044a306e4 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -47,8 +47,6 @@ //#define DEBUG_SD 1 -#define ACMD41_ENQUIRY_MASK 0x00ffffff - typedef enum { sd_r0 = 0, /* no response */ sd_r1, /* normal response command */ @@ -272,13 +270,26 @@ static uint16_t sd_crc16(void *message, size_t width) #define OCR_POWER_DELAY_NS 500000 /* 0.5ms */ +FIELD(OCR, VDD_VOLTAGE_WINDOW, 0, 24) +FIELD(OCR, VDD_VOLTAGE_WIN_LO, 0, 8) +FIELD(OCR, DUAL_VOLTAGE_CARD, 7, 1) +FIELD(OCR, VDD_VOLTAGE_WIN_HI, 8, 16) +FIELD(OCR, ACCEPT_SWITCH_1V8, 24, 1) /* Only UHS-I */ +FIELD(OCR, UHS_II_CARD, 29, 1) /* Only UHS-II */ FIELD(OCR, CARD_CAPACITY, 30, 1) /* 0:SDSC, 1:SDHC/SDXC */ FIELD(OCR, CARD_POWER_UP, 31, 1) +#define ACMD41_ENQUIRY_MASK 0x00ffffff +#define ACMD41_R3_MASK (R_OCR_VDD_VOLTAGE_WIN_HI_MASK \ + | R_OCR_ACCEPT_SWITCH_1V8_MASK \ + | R_OCR_UHS_II_CARD_MASK \ + | R_OCR_CARD_CAPACITY_MASK \ + | R_OCR_CARD_POWER_UP_MASK) + static void sd_set_ocr(SDState *sd) { - /* All voltages OK, Standard Capacity SD Memory Card, not yet powered up */ - sd->ocr = 0x00ffff00; + /* All voltages OK */ + sd->ocr = R_OCR_VDD_VOLTAGE_WIN_HI_MASK; } static void sd_ocr_powerup(void *opaque) @@ -446,7 +457,7 @@ static void sd_response_r1_make(SDState *sd, uint8_t *response) static void sd_response_r3_make(SDState *sd, uint8_t *response) { - stl_be_p(response, sd->ocr); + stl_be_p(response, sd->ocr & ACMD41_R3_MASK); } static void sd_response_r6_make(SDState *sd, uint8_t *response) From da26e3f360c64478e15aa27c79a0acf833eaa436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:53 +0000 Subject: [PATCH 24/32] sdcard: use the registerfields API for the CARD_STATUS register masks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Acked-by: Alistair Francis Message-id: 20180215221325.7611-9-f4bug@amsat.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/sd/sd.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 5044a306e4..cc5caaf4f0 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -419,14 +419,56 @@ static void sd_set_rca(SDState *sd) sd->rca += 0x4567; } +FIELD(CSR, AKE_SEQ_ERROR, 3, 1) +FIELD(CSR, APP_CMD, 5, 1) +FIELD(CSR, FX_EVENT, 6, 1) +FIELD(CSR, READY_FOR_DATA, 8, 1) +FIELD(CSR, CURRENT_STATE, 9, 4) +FIELD(CSR, ERASE_RESET, 13, 1) +FIELD(CSR, CARD_ECC_DISABLED, 14, 1) +FIELD(CSR, WP_ERASE_SKIP, 15, 1) +FIELD(CSR, CSD_OVERWRITE, 16, 1) +FIELD(CSR, DEFERRED_RESPONSE, 17, 1) +FIELD(CSR, ERROR, 19, 1) +FIELD(CSR, CC_ERROR, 20, 1) +FIELD(CSR, CARD_ECC_FAILED, 21, 1) +FIELD(CSR, ILLEGAL_COMMAND, 22, 1) +FIELD(CSR, COM_CRC_ERROR, 23, 1) +FIELD(CSR, LOCK_UNLOCK_FAILED, 24, 1) +FIELD(CSR, CARD_IS_LOCKED, 25, 1) +FIELD(CSR, WP_VIOLATION, 26, 1) +FIELD(CSR, ERASE_PARAM, 27, 1) +FIELD(CSR, ERASE_SEQ_ERROR, 28, 1) +FIELD(CSR, BLOCK_LEN_ERROR, 29, 1) +FIELD(CSR, ADDRESS_ERROR, 30, 1) +FIELD(CSR, OUT_OF_RANGE, 31, 1) + /* Card status bits, split by clear condition: * A : According to the card current state * B : Always related to the previous command * C : Cleared by read */ -#define CARD_STATUS_A 0x02004100 -#define CARD_STATUS_B 0x00c01e00 -#define CARD_STATUS_C 0xfd39a028 +#define CARD_STATUS_A (R_CSR_READY_FOR_DATA_MASK \ + | R_CSR_CARD_ECC_DISABLED_MASK \ + | R_CSR_CARD_IS_LOCKED_MASK) +#define CARD_STATUS_B (R_CSR_CURRENT_STATE_MASK \ + | R_CSR_ILLEGAL_COMMAND_MASK \ + | R_CSR_COM_CRC_ERROR_MASK) +#define CARD_STATUS_C (R_CSR_AKE_SEQ_ERROR_MASK \ + | R_CSR_APP_CMD_MASK \ + | R_CSR_ERASE_RESET_MASK \ + | R_CSR_WP_ERASE_SKIP_MASK \ + | R_CSR_CSD_OVERWRITE_MASK \ + | R_CSR_ERROR_MASK \ + | R_CSR_CC_ERROR_MASK \ + | R_CSR_CARD_ECC_FAILED_MASK \ + | R_CSR_LOCK_UNLOCK_FAILED_MASK \ + | R_CSR_WP_VIOLATION_MASK \ + | R_CSR_ERASE_PARAM_MASK \ + | R_CSR_ERASE_SEQ_ERROR_MASK \ + | R_CSR_BLOCK_LEN_ERROR_MASK \ + | R_CSR_ADDRESS_ERROR_MASK \ + | R_CSR_OUT_OF_RANGE_MASK) static void sd_set_cardstatus(SDState *sd) { From 49fb7381b2c86e78ca117451f5602f2299fb726a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:53 +0000 Subject: [PATCH 25/32] sdcard: handle CMD54 (SDIO) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linux uses it to poll the bus before polling for a card. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215221325.7611-10-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index cc5caaf4f0..63da05eaef 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1371,9 +1371,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, } break; - case 52: - case 53: - /* CMD52, CMD53: reserved for SDIO cards + case 52 ... 54: + /* CMD52, CMD53, CMD54: reserved for SDIO cards * (see the SDIO Simplified Specification V2.0) * Handle as illegal command but do not complain * on stderr, as some OSes may use these in their From 688491c71adedcb349248ca467f2ddfc7c4cf566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:53 +0000 Subject: [PATCH 26/32] sdcard: handle the Security Specification commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit returning sd_illegal, since they are not implemented. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215221325.7611-11-f4bug@amsat.org [PMM: tweak multiline comment format] Signed-off-by: Peter Maydell --- hw/sd/sd.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 63da05eaef..f13f33efca 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1546,6 +1546,18 @@ static sd_rsp_type_t sd_app_command(SDState *sd, } break; + case 18: /* Reserved for SD security applications */ + case 25: + case 26: + case 38: + case 43 ... 49: + /* Refer to the "SD Specifications Part3 Security Specification" for + * information about the SD Security Features. + */ + qemu_log_mask(LOG_UNIMP, "SD: CMD%i Security not implemented\n", + req.cmd); + return sd_illegal; + default: /* Fall back to standard commands. */ return sd_normal_command(sd, req); From a21208646d28f642d32a5802463b1ad731bb9e92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:53 +0000 Subject: [PATCH 27/32] sdcard: use a more descriptive label 'unimplemented_spi_cmd' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suggested-by: Alistair Francis Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215221325.7611-12-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index f13f33efca..34080f0e4c 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1179,8 +1179,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, /* Block write commands (Class 4) */ case 24: /* CMD24: WRITE_SINGLE_BLOCK */ - if (sd->spi) - goto unimplemented_cmd; + if (sd->spi) { + goto unimplemented_spi_cmd; + } switch (sd->state) { case sd_transfer_state: /* Writing in SPI mode not implemented. */ @@ -1205,8 +1206,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, break; case 25: /* CMD25: WRITE_MULTIPLE_BLOCK */ - if (sd->spi) - goto unimplemented_cmd; + if (sd->spi) { + goto unimplemented_spi_cmd; + } switch (sd->state) { case sd_transfer_state: /* Writing in SPI mode not implemented. */ @@ -1246,8 +1248,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, break; case 27: /* CMD27: PROGRAM_CSD */ - if (sd->spi) - goto unimplemented_cmd; + if (sd->spi) { + goto unimplemented_spi_cmd; + } switch (sd->state) { case sd_transfer_state: sd->state = sd_receivingdata_state; @@ -1357,8 +1360,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, /* Lock card commands (Class 7) */ case 42: /* CMD42: LOCK_UNLOCK */ - if (sd->spi) - goto unimplemented_cmd; + if (sd->spi) { + goto unimplemented_spi_cmd; + } switch (sd->state) { case sd_transfer_state: sd->state = sd_receivingdata_state; @@ -1409,7 +1413,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, qemu_log_mask(LOG_GUEST_ERROR, "SD: Unknown CMD%i\n", req.cmd); return sd_illegal; - unimplemented_cmd: + unimplemented_spi_cmd: /* Commands that are recognised but not yet implemented in SPI mode. */ qemu_log_mask(LOG_UNIMP, "SD: CMD%i not implemented in SPI mode\n", req.cmd); From 946897ce1897d50a9a432828a44e80be746066f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:53 +0000 Subject: [PATCH 28/32] sdcard: handles more commands in SPI mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215221325.7611-13-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 34080f0e4c..ff7ace3491 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1386,9 +1386,11 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, /* Application specific commands (Class 8) */ case 55: /* CMD55: APP_CMD */ - if (sd->rca != rca) - return sd_r0; - + if (!sd->spi) { + if (sd->rca != rca) { + return sd_r0; + } + } sd->expecting_acmd = true; sd->card_status |= APP_CMD; return sd_r1; @@ -1408,6 +1410,18 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, } break; + case 58: /* CMD58: READ_OCR (SPI) */ + if (!sd->spi) { + goto bad_cmd; + } + return sd_r3; + + case 59: /* CMD59: CRC_ON_OFF (SPI) */ + if (!sd->spi) { + goto bad_cmd; + } + goto unimplemented_spi_cmd; + default: bad_cmd: qemu_log_mask(LOG_GUEST_ERROR, "SD: Unknown CMD%i\n", req.cmd); @@ -1431,6 +1445,9 @@ static sd_rsp_type_t sd_app_command(SDState *sd, sd->card_status |= APP_CMD; switch (req.cmd) { case 6: /* ACMD6: SET_BUS_WIDTH */ + if (sd->spi) { + goto unimplemented_spi_cmd; + } switch (sd->state) { case sd_transfer_state: sd->sd_status[0] &= 0x3f; @@ -1565,6 +1582,12 @@ static sd_rsp_type_t sd_app_command(SDState *sd, default: /* Fall back to standard commands. */ return sd_normal_command(sd, req); + + unimplemented_spi_cmd: + /* Commands that are recognised but not yet implemented in SPI mode. */ + qemu_log_mask(LOG_UNIMP, "SD: CMD%i not implemented in SPI mode\n", + req.cmd); + return sd_illegal; } qemu_log_mask(LOG_GUEST_ERROR, "SD: ACMD%i in a wrong state\n", req.cmd); From d6911486550b794f879584821a0ec4d40e61a47b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:54 +0000 Subject: [PATCH 29/32] sdcard: check the card is in correct state for APP CMD (CMD55) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215221325.7611-14-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index ff7ace3491..d6dd2b9a15 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1386,6 +1386,14 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, /* Application specific commands (Class 8) */ case 55: /* CMD55: APP_CMD */ + switch (sd->state) { + case sd_ready_state: + case sd_identification_state: + case sd_inactive_state: + return sd_illegal; + default: + break; + } if (!sd->spi) { if (sd->rca != rca) { return sd_r0; From 3116280040a7ca898b925651001962167433b084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:54 +0000 Subject: [PATCH 30/32] sdcard: warn if host uses an incorrect address for APP CMD (CMD55) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215221325.7611-15-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index d6dd2b9a15..c8351d4f0b 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1391,6 +1391,11 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, case sd_identification_state: case sd_inactive_state: return sd_illegal; + case sd_idle_state: + if (rca) { + qemu_log_mask(LOG_GUEST_ERROR, + "SD: illegal RCA 0x%04x for APP_CMD\n", req.cmd); + } default: break; } From ad0ade55479490fa57ffa31d50fb355e0084c61b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:54 +0000 Subject: [PATCH 31/32] sdcard: simplify SEND_IF_COND (CMD8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit replace switch(single case) -> if() Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215221325.7611-16-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index c8351d4f0b..25fce7d6b6 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1008,23 +1008,19 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, case 8: /* CMD8: SEND_IF_COND */ /* Physical Layer Specification Version 2.00 command */ - switch (sd->state) { - case sd_idle_state: - sd->vhs = 0; - - /* No response if not exactly one VHS bit is set. */ - if (!(req.arg >> 8) || (req.arg >> (ctz32(req.arg & ~0xff) + 1))) { - return sd->spi ? sd_r7 : sd_r0; - } - - /* Accept. */ - sd->vhs = req.arg; - return sd_r7; - - default: + if (sd->state != sd_idle_state) { break; } - break; + sd->vhs = 0; + + /* No response if not exactly one VHS bit is set. */ + if (!(req.arg >> 8) || (req.arg >> (ctz32(req.arg & ~0xff) + 1))) { + return sd->spi ? sd_r7 : sd_r0; + } + + /* Accept. */ + sd->vhs = req.arg; + return sd_r7; case 9: /* CMD9: SEND_CSD */ switch (sd->state) { From 4e5cc6756586e967993187657dfcdde4e00288d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 22 Feb 2018 15:12:54 +0000 Subject: [PATCH 32/32] sdcard: simplify SD_SEND_OP_COND (ACMD41) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit replace switch(single case) -> if() Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20180215221325.7611-17-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/sd/sd.c | 56 +++++++++++++++++++++++++----------------------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 25fce7d6b6..933890e86f 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1512,45 +1512,41 @@ static sd_rsp_type_t sd_app_command(SDState *sd, sd->state = sd_transfer_state; return sd_r1; } - switch (sd->state) { - case sd_idle_state: - /* If it's the first ACMD41 since reset, we need to decide - * whether to power up. If this is not an enquiry ACMD41, - * we immediately report power on and proceed below to the - * ready state, but if it is, we set a timer to model a - * delay for power up. This works around a bug in EDK2 - * UEFI, which sends an initial enquiry ACMD41, but - * assumes that the card is in ready state as soon as it - * sees the power up bit set. */ - if (!FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP)) { - if ((req.arg & ACMD41_ENQUIRY_MASK) != 0) { - timer_del(sd->ocr_power_timer); - sd_ocr_powerup(sd); - } else { - trace_sdcard_inquiry_cmd41(); - if (!timer_pending(sd->ocr_power_timer)) { - timer_mod_ns(sd->ocr_power_timer, - (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - + OCR_POWER_DELAY_NS)); - } + if (sd->state != sd_idle_state) { + break; + } + /* If it's the first ACMD41 since reset, we need to decide + * whether to power up. If this is not an enquiry ACMD41, + * we immediately report power on and proceed below to the + * ready state, but if it is, we set a timer to model a + * delay for power up. This works around a bug in EDK2 + * UEFI, which sends an initial enquiry ACMD41, but + * assumes that the card is in ready state as soon as it + * sees the power up bit set. */ + if (!FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP)) { + if ((req.arg & ACMD41_ENQUIRY_MASK) != 0) { + timer_del(sd->ocr_power_timer); + sd_ocr_powerup(sd); + } else { + trace_sdcard_inquiry_cmd41(); + if (!timer_pending(sd->ocr_power_timer)) { + timer_mod_ns(sd->ocr_power_timer, + (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + OCR_POWER_DELAY_NS)); } } + } + if (FIELD_EX32(sd->ocr & req.arg, OCR, VDD_VOLTAGE_WINDOW)) { /* We accept any voltage. 10000 V is nothing. * * Once we're powered up, we advance straight to ready state * unless it's an enquiry ACMD41 (bits 23:0 == 0). */ - if (req.arg & ACMD41_ENQUIRY_MASK) { - sd->state = sd_ready_state; - } - - return sd_r3; - - default: - break; + sd->state = sd_ready_state; } - break; + + return sd_r3; case 42: /* ACMD42: SET_CLR_CARD_DETECT */ switch (sd->state) {