aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-02-22 15:41:24 +0000
committerPeter Maydell <peter.maydell@linaro.org>2018-02-22 15:41:24 +0000
commit205e3e78d23422fb58163772aba76940d998975c (patch)
tree1bdb6297ba13619a5f87d2394fddaec77b8c4fcb
parent0ce9cb913e32d7efed64dc1191a7a490d97cf56e (diff)
parent4e5cc6756586e967993187657dfcdde4e00288d9 (diff)
downloadqemu-205e3e78d23422fb58163772aba76940d998975c.zip
qemu-205e3e78d23422fb58163772aba76940d998975c.tar.gz
qemu-205e3e78d23422fb58163772aba76940d998975c.tar.bz2
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180222' into staging
* New "raspi3" machine emulating RaspberryPi 3 * Fix bad register definitions for VMIDR and VMPIDR (which caused assertions for 64-bit guest CPUs with EL2 on big-endian hosts) * hw/char/stm32f2xx_usart: fix TXE/TC bit handling * Fix ast2500 protection register emulation * Lots of SD card emulation cleanups and bugfixes # gpg: Signature made Thu 22 Feb 2018 15:18:53 GMT # gpg: using RSA key 3C2525ED14360CDE # 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-20180222: (32 commits) sdcard: simplify SD_SEND_OP_COND (ACMD41) sdcard: simplify SEND_IF_COND (CMD8) sdcard: warn if host uses an incorrect address for APP CMD (CMD55) sdcard: check the card is in correct state for APP CMD (CMD55) sdcard: handles more commands in SPI mode sdcard: use a more descriptive label 'unimplemented_spi_cmd' sdcard: handle the Security Specification commands sdcard: handle CMD54 (SDIO) sdcard: use the registerfields API for the CARD_STATUS register masks sdcard: use the correct masked OCR in the R3 reply sdcard: simplify using the ldst API sdcard: remove commands from unsupported old MMC specification sdcard: clean the SCR register and add few comments sdcard: fix the 'maximum data transfer rate' to 25MHz sdcard: update the CSD CRC register regardless the CSD structure version sdcard: Don't always set the high capacity bit sdcard: use the registerfields API to access the OCR register sdcard: use G_BYTE from cutils sdcard: define SDMMC_CMD_MAX instead of using the magic '64' sdcard: add more trace events ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/arm/raspi.c23
-rw-r--r--hw/char/stm32f2xx_usart.c12
-rw-r--r--hw/misc/aspeed_scu.c6
-rw-r--r--hw/misc/aspeed_sdmc.c8
-rw-r--r--hw/sd/milkymist-memcard.c81
-rw-r--r--hw/sd/sd.c467
-rw-r--r--hw/sd/sdmmc-internal.h15
-rw-r--r--hw/sd/ssi-sd.c32
-rw-r--r--hw/sd/trace-events20
-rw-r--r--include/hw/char/stm32f2xx_usart.h7
-rw-r--r--include/hw/sd/sd.h1
-rw-r--r--target/arm/helper.c8
12 files changed, 443 insertions, 237 deletions
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index 93121c5..a378814 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
diff --git a/hw/char/stm32f2xx_usart.c b/hw/char/stm32f2xx_usart.c
index 07b462d..032b5fd 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/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 74537ce..5e6d574 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 f0b3053..0df008e 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:
diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index 341da88..5570c1e 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"
@@ -68,7 +69,7 @@ struct MilkymistMemcardState {
SysBusDevice parent_obj;
MemoryRegion regs_region;
- SDState *card;
+ SDBus sdbus;
int command_write_ptr;
int response_read_ptr;
@@ -104,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) {
@@ -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;
}
}
@@ -149,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:
@@ -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;
}
@@ -205,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;
@@ -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;
}
}
@@ -248,33 +251,41 @@ 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 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;
+ 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) {
- return -1;
+ 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);
-
- 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 = {
@@ -297,9 +308,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() */
@@ -310,6 +320,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,
};
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 9ac9b63..933890e 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -32,28 +32,21 @@
#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"
#include "qemu/bitmap.h"
+#include "qemu/cutils.h"
#include "hw/qdev-properties.h"
#include "qemu/error-report.h"
#include "qemu/timer.h"
#include "qemu/log.h"
+#include "sdmmc-internal.h"
+#include "trace.h"
//#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 */
-
typedef enum {
sd_r0 = 0, /* no response */
sd_r1, /* normal response command */
@@ -88,16 +81,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 +108,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,13 +119,53 @@ 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;
};
+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 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;
@@ -142,6 +178,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 */
@@ -176,18 +214,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,
@@ -227,27 +268,54 @@ static uint16_t sd_crc16(void *message, size_t width)
return shift_reg;
}
+#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)
{
SDState *sd = opaque;
- /* Set powered up bit in OCR */
- assert(!(sd->ocr & OCR_POWER_UP));
- sd->ocr |= OCR_POWER_UP;
+ trace_sdcard_powerup();
+ assert(!FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP));
+
+ /* 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)
{
- 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;
@@ -299,11 +367,11 @@ 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 */
- 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;
@@ -324,7 +392,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;
@@ -343,9 +410,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->ocr |= 1 << 30; /* High Capacity SD Memory Card */
}
+ sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1;
}
static void sd_set_rca(SDState *sd)
@@ -353,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)
{
@@ -376,57 +484,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 & ACMD41_R3_MASK);
}
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)
@@ -440,6 +530,7 @@ static void sd_reset(DeviceState *dev)
uint64_t size;
uint64_t sect;
+ trace_sdcard_reset();
if (sd->blk) {
blk_get_geometry(sd->blk, &sect);
} else {
@@ -493,7 +584,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;
@@ -521,7 +615,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 = {
@@ -625,12 +719,13 @@ 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;
}
- 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;
@@ -667,7 +762,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 */
@@ -691,9 +786,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)
@@ -714,6 +807,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 ||
@@ -774,11 +872,13 @@ 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;
- 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;
}
@@ -788,7 +888,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 */
@@ -909,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) {
@@ -971,24 +1066,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:
@@ -1039,10 +1116,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;
@@ -1096,8 +1175,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. */
@@ -1122,8 +1202,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. */
@@ -1163,8 +1244,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;
@@ -1274,8 +1356,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;
@@ -1288,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
@@ -1300,16 +1382,29 @@ 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;
-
+ switch (sd->state) {
+ case sd_ready_state:
+ 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;
+ }
+ if (!sd->spi) {
+ if (sd->rca != rca) {
+ return sd_r0;
+ }
+ }
sd->expecting_acmd = true;
sd->card_status |= APP_CMD;
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;
@@ -1324,12 +1419,24 @@ 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);
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);
@@ -1343,10 +1450,13 @@ 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 */
+ if (sd->spi) {
+ goto unimplemented_spi_cmd;
+ }
switch (sd->state) {
case sd_transfer_state:
sd->sd_status[0] &= 0x3f;
@@ -1402,42 +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 (!(sd->ocr & OCR_POWER_UP)) {
- 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)) {
+ 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) {
@@ -1463,9 +1572,27 @@ 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);
+
+ 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);
@@ -1488,8 +1615,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,
@@ -1508,6 +1635,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;
@@ -1574,10 +1707,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
@@ -1587,16 +1722,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);
- } else {
- DPRINTF("No response %d\n", sd->state);
- }
+ qemu_hexdump((const char *)response, stderr, "Response", rsplen);
#endif
return rsplen;
@@ -1604,8 +1730,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");
}
@@ -1613,6 +1738,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");
}
@@ -1639,6 +1765,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;
@@ -1776,6 +1903,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 ++];
@@ -1792,21 +1920,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 ++];
diff --git a/hw/sd/sdmmc-internal.h b/hw/sd/sdmmc-internal.h
new file mode 100644
index 0000000..0e96cb0
--- /dev/null
+++ b/hw/sd/sdmmc-internal.h
@@ -0,0 +1,15 @@
+/*
+ * SD/MMC cards common
+ *
+ * Copyright (c) 2018 Philippe Mathieu-Daudé <f4bug@amsat.org>
+ *
+ * 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
diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index f88f509..ae04b66 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)
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index 0f8536d..3040d32 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -23,6 +23,26 @@ 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_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"
milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
diff --git a/include/hw/char/stm32f2xx_usart.h b/include/hw/char/stm32f2xx_usart.h
index 9d03a75..84c4029 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)
diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index bf1eb07..9bdb3c9 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 */
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 32e4fd4..c5bc69b 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,