diff mbox series

[v2,19/25] sdcard: check if the card capacity is supported

Message ID 20180103212436.15762-20-f4bug@amsat.org
State New
Headers show
Series SDCard: housekeeping, improve SPI, introduce new Specs | expand

Commit Message

Philippe Mathieu-Daudé Jan. 3, 2018, 9:24 p.m. UTC
The current Spec (v2.00) does not support SDXC cards (> 32GB).

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/sd.c         | 41 +++++++++++++++++++++++++++++++++++++++++
 hw/sd/trace-events |  1 +
 2 files changed, 42 insertions(+)
diff mbox series

Patch

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index ed5874e4d6..a7cede8da6 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -63,6 +63,13 @@  typedef enum {
     SD_PHY_SPEC_VER_3_01 = 301, /* not yet supported */
 } sd_phy_spec_ver_t;
 
+typedef enum {
+    sd_capacity_unknown,
+    sd_capacity_sdsc,           /* not well supported */
+    sd_capacity_sdhc,
+    sd_capacity_sdxc,           /* not yet supported */
+} sd_card_capacity_t;
+
 typedef enum {
     sd_r0 = 0,    /* no response */
     sd_r1,        /* normal response command */
@@ -121,6 +128,7 @@  struct SDState {
 
     int spec_version;
     bool spi;
+    sd_card_capacity_t capacity;
 
     uint32_t mode;    /* current card mode, one of SDCardModes */
     int32_t state;    /* current card state, one of SDCardStates */
@@ -161,6 +169,17 @@  static const char *sd_state_name(enum SDCardStates state)
     return state_name[state];
 }
 
+static const char *sd_capacity(sd_card_capacity_t capacity)
+{
+    static const char *capacity_name[] = {
+        [sd_capacity_unknown]   = "UNKN",
+        [sd_capacity_sdsc]      = "SDSC",
+        [sd_capacity_sdhc]      = "SDHC",
+        [sd_capacity_sdxc]      = "SDXC",
+    };
+    return capacity_name[capacity];
+}
+
 static const char *sd_cmd_abbreviation(uint8_t cmd)
 {
     static const char *cmd_abbrev[SDCARD_CMD_MAX] = {
@@ -1991,11 +2010,33 @@  static void sd_realize(DeviceState *dev, Error **errp)
     }
 
     if (sd->blk) {
+        int64_t size;
+
         ret = blk_set_perm(sd->blk, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE,
                            BLK_PERM_ALL, errp);
         if (ret < 0) {
             return;
         }
+
+        size = blk_getlength(sd->blk);
+        if (size < 0 || size <= 2 * G_BYTE) {
+            sd->capacity = sd_capacity_sdsc;
+        } else if (size <= 32 * G_BYTE) {
+            sd->capacity = sd_capacity_sdhc;
+        } else if (size <= 2 * T_BYTE) {
+            sd->capacity = sd_capacity_sdxc;
+        } else {
+            error_setg(errp, "block size unsupported: %lld TB", size / T_BYTE);
+            return;
+        }
+        trace_sdcard_capacity(sd_capacity(sd->capacity), size);
+
+        if (sd->capacity == sd_capacity_sdxc
+                && sd->spec_version < SD_PHY_SPEC_VER_3_01) {
+            error_setg(errp, "capacity SDHC requires at least Spec v3.01");
+            return;
+        }
+
         blk_set_dev_ops(sd->blk, &sd_block_ops, sd);
     }
 }
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index 25ab339f97..215e0eec3a 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -28,6 +28,7 @@  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 value) "value 0x%02x"
 sdcard_read_data(int length) "len %d"
+sdcard_capacity(const char *capacity, int64_t size) "%s card (%ld B)"
 
 # hw/sd/milkymist-memcard.c
 milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"