|
@@ -32,28 +32,21 @@
|
|
#include "qemu/osdep.h"
|
|
#include "qemu/osdep.h"
|
|
#include "hw/qdev.h"
|
|
#include "hw/qdev.h"
|
|
#include "hw/hw.h"
|
|
#include "hw/hw.h"
|
|
|
|
+#include "hw/registerfields.h"
|
|
#include "sysemu/block-backend.h"
|
|
#include "sysemu/block-backend.h"
|
|
#include "hw/sd/sd.h"
|
|
#include "hw/sd/sd.h"
|
|
#include "qapi/error.h"
|
|
#include "qapi/error.h"
|
|
#include "qemu/bitmap.h"
|
|
#include "qemu/bitmap.h"
|
|
|
|
+#include "qemu/cutils.h"
|
|
#include "hw/qdev-properties.h"
|
|
#include "hw/qdev-properties.h"
|
|
#include "qemu/error-report.h"
|
|
#include "qemu/error-report.h"
|
|
#include "qemu/timer.h"
|
|
#include "qemu/timer.h"
|
|
#include "qemu/log.h"
|
|
#include "qemu/log.h"
|
|
|
|
+#include "sdmmc-internal.h"
|
|
|
|
+#include "trace.h"
|
|
|
|
|
|
//#define DEBUG_SD 1
|
|
//#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 {
|
|
typedef enum {
|
|
sd_r0 = 0, /* no response */
|
|
sd_r0 = 0, /* no response */
|
|
sd_r1, /* normal response command */
|
|
sd_r1, /* normal response command */
|
|
@@ -88,16 +81,21 @@ enum SDCardStates {
|
|
struct SDState {
|
|
struct SDState {
|
|
DeviceState parent_obj;
|
|
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;
|
|
uint32_t ocr;
|
|
- QEMUTimer *ocr_power_timer;
|
|
|
|
uint8_t scr[8];
|
|
uint8_t scr[8];
|
|
uint8_t cid[16];
|
|
uint8_t cid[16];
|
|
uint8_t csd[16];
|
|
uint8_t csd[16];
|
|
uint16_t rca;
|
|
uint16_t rca;
|
|
uint32_t card_status;
|
|
uint32_t card_status;
|
|
uint8_t sd_status[64];
|
|
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;
|
|
uint32_t vhs;
|
|
bool wp_switch;
|
|
bool wp_switch;
|
|
unsigned long *wp_groups;
|
|
unsigned long *wp_groups;
|
|
@@ -110,8 +108,6 @@ struct SDState {
|
|
uint8_t pwd[16];
|
|
uint8_t pwd[16];
|
|
uint32_t pwd_len;
|
|
uint32_t pwd_len;
|
|
uint8_t function_group[6];
|
|
uint8_t function_group[6];
|
|
-
|
|
|
|
- bool spi;
|
|
|
|
uint8_t current_cmd;
|
|
uint8_t current_cmd;
|
|
/* True if we will handle the next command as an ACMD. Note that this does
|
|
/* True if we will handle the next command as an ACMD. Note that this does
|
|
* *not* track the APP_CMD status bit!
|
|
* *not* track the APP_CMD status bit!
|
|
@@ -123,13 +119,53 @@ struct SDState {
|
|
uint8_t data[512];
|
|
uint8_t data[512];
|
|
qemu_irq readonly_cb;
|
|
qemu_irq readonly_cb;
|
|
qemu_irq inserted_cb;
|
|
qemu_irq inserted_cb;
|
|
- BlockBackend *blk;
|
|
|
|
-
|
|
|
|
|
|
+ QEMUTimer *ocr_power_timer;
|
|
bool enable;
|
|
bool enable;
|
|
uint8_t dat_lines;
|
|
uint8_t dat_lines;
|
|
bool cmd_line;
|
|
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)
|
|
static uint8_t sd_get_dat_lines(SDState *sd)
|
|
{
|
|
{
|
|
return sd->enable ? sd->dat_lines : 0;
|
|
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)
|
|
static void sd_set_voltage(SDState *sd, uint16_t millivolts)
|
|
{
|
|
{
|
|
|
|
+ trace_sdcard_set_voltage(millivolts);
|
|
|
|
+
|
|
switch (millivolts) {
|
|
switch (millivolts) {
|
|
case 3001 ... 3600: /* SD_VOLTAGE_3_3V */
|
|
case 3001 ... 3600: /* SD_VOLTAGE_3_3V */
|
|
case 2001 ... 3000: /* SD_VOLTAGE_3_0V */
|
|
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_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,
|
|
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_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,
|
|
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_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,
|
|
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_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,
|
|
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,
|
|
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,
|
|
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,
|
|
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;
|
|
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)
|
|
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)
|
|
static void sd_ocr_powerup(void *opaque)
|
|
{
|
|
{
|
|
SDState *sd = 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)
|
|
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;
|
|
sd->scr[3] = 0x00;
|
|
|
|
+ /* reserved for manufacturer usage */
|
|
sd->scr[4] = 0x00;
|
|
sd->scr[4] = 0x00;
|
|
sd->scr[5] = 0x00;
|
|
sd->scr[5] = 0x00;
|
|
sd->scr[6] = 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 sectsize = (1 << (SECTOR_SHIFT + 1)) - 1;
|
|
uint32_t wpsize = (1 << (WPGROUP_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[0] = 0x00; /* CSD structure */
|
|
sd->csd[1] = 0x26; /* Data read access-time-1 */
|
|
sd->csd[1] = 0x26; /* Data read access-time-1 */
|
|
sd->csd[2] = 0x00; /* Data read access-time-2 */
|
|
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[4] = 0x5f; /* Card Command Classes */
|
|
sd->csd[5] = 0x50 | /* Max. read data block length */
|
|
sd->csd[5] = 0x50 | /* Max. read data block length */
|
|
HWBLOCK_SHIFT;
|
|
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 */
|
|
sd->csd[13] = 0x20 | /* Max. write data block length */
|
|
((HWBLOCK_SHIFT << 6) & 0xc0);
|
|
((HWBLOCK_SHIFT << 6) & 0xc0);
|
|
sd->csd[14] = 0x00; /* File format group */
|
|
sd->csd[14] = 0x00; /* File format group */
|
|
- sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1;
|
|
|
|
} else { /* SDHC */
|
|
} else { /* SDHC */
|
|
size /= 512 * 1024;
|
|
size /= 512 * 1024;
|
|
size -= 1;
|
|
size -= 1;
|
|
@@ -343,9 +410,8 @@ static void sd_set_csd(SDState *sd, uint64_t size)
|
|
sd->csd[12] = 0x0a;
|
|
sd->csd[12] = 0x0a;
|
|
sd->csd[13] = 0x40;
|
|
sd->csd[13] = 0x40;
|
|
sd->csd[14] = 0x00;
|
|
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)
|
|
static void sd_set_rca(SDState *sd)
|
|
@@ -353,14 +419,56 @@ static void sd_set_rca(SDState *sd)
|
|
sd->rca += 0x4567;
|
|
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:
|
|
/* Card status bits, split by clear condition:
|
|
* A : According to the card current state
|
|
* A : According to the card current state
|
|
* B : Always related to the previous command
|
|
* B : Always related to the previous command
|
|
* C : Cleared by read
|
|
* 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)
|
|
static void sd_set_cardstatus(SDState *sd)
|
|
{
|
|
{
|
|
@@ -376,57 +484,39 @@ static int sd_req_crc_validate(SDRequest *req)
|
|
{
|
|
{
|
|
uint8_t buffer[5];
|
|
uint8_t buffer[5];
|
|
buffer[0] = 0x40 | req->cmd;
|
|
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 0;
|
|
return sd_crc7(buffer, 5) != req->crc; /* TODO */
|
|
return sd_crc7(buffer, 5) != req->crc; /* TODO */
|
|
}
|
|
}
|
|
|
|
|
|
static void sd_response_r1_make(SDState *sd, uint8_t *response)
|
|
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 */
|
|
/* Clear the "clear on read" status bits */
|
|
sd->card_status &= ~CARD_STATUS_C;
|
|
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)
|
|
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)
|
|
static void sd_response_r6_make(SDState *sd, uint8_t *response)
|
|
{
|
|
{
|
|
- uint16_t arg;
|
|
|
|
uint16_t status;
|
|
uint16_t status;
|
|
|
|
|
|
- arg = sd->rca;
|
|
|
|
status = ((sd->card_status >> 8) & 0xc000) |
|
|
status = ((sd->card_status >> 8) & 0xc000) |
|
|
((sd->card_status >> 6) & 0x2000) |
|
|
((sd->card_status >> 6) & 0x2000) |
|
|
(sd->card_status & 0x1fff);
|
|
(sd->card_status & 0x1fff);
|
|
sd->card_status &= ~(CARD_STATUS_C & 0xc81fff);
|
|
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)
|
|
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)
|
|
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 size;
|
|
uint64_t sect;
|
|
uint64_t sect;
|
|
|
|
|
|
|
|
+ trace_sdcard_reset();
|
|
if (sd->blk) {
|
|
if (sd->blk) {
|
|
blk_get_geometry(sd->blk, §);
|
|
blk_get_geometry(sd->blk, §);
|
|
} else {
|
|
} else {
|
|
@@ -493,7 +584,10 @@ static void sd_cardchange(void *opaque, bool load, Error **errp)
|
|
bool readonly = sd_get_readonly(sd);
|
|
bool readonly = sd_get_readonly(sd);
|
|
|
|
|
|
if (inserted) {
|
|
if (inserted) {
|
|
|
|
+ trace_sdcard_inserted(readonly);
|
|
sd_reset(dev);
|
|
sd_reset(dev);
|
|
|
|
+ } else {
|
|
|
|
+ trace_sdcard_ejected();
|
|
}
|
|
}
|
|
|
|
|
|
/* The IRQ notification is for legacy non-QOM SD controller devices;
|
|
/* 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;
|
|
SDState *sd = opaque;
|
|
|
|
|
|
/* Include the OCR state (and timer) if it is not yet powered up */
|
|
/* 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 = {
|
|
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_start = sd->erase_start;
|
|
uint64_t erase_end = sd->erase_end;
|
|
uint64_t erase_end = sd->erase_end;
|
|
|
|
|
|
|
|
+ trace_sdcard_erase();
|
|
if (!sd->erase_start || !sd->erase_end) {
|
|
if (!sd->erase_start || !sd->erase_end) {
|
|
sd->card_status |= ERASE_SEQ_ERROR;
|
|
sd->card_status |= ERASE_SEQ_ERROR;
|
|
return;
|
|
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 */
|
|
/* High capacity memory card: erase units are 512 byte blocks */
|
|
erase_start *= 512;
|
|
erase_start *= 512;
|
|
erase_end *= 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)
|
|
static void sd_function_switch(SDState *sd, uint32_t arg)
|
|
{
|
|
{
|
|
- int i, mode, new_func, crc;
|
|
|
|
|
|
+ int i, mode, new_func;
|
|
mode = !!(arg & 0x80000000);
|
|
mode = !!(arg & 0x80000000);
|
|
|
|
|
|
sd->data[0] = 0x00; /* Maximum current consumption */
|
|
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);
|
|
sd->data[14 + (i >> 1)] = new_func << ((i * 4) & 4);
|
|
}
|
|
}
|
|
memset(&sd->data[17], 0, 47);
|
|
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)
|
|
static inline bool sd_wp_addr(SDState *sd, uint64_t addr)
|
|
@@ -714,6 +807,11 @@ static void sd_lock_command(SDState *sd)
|
|
else
|
|
else
|
|
pwd_len = 0;
|
|
pwd_len = 0;
|
|
|
|
|
|
|
|
+ if (lock) {
|
|
|
|
+ trace_sdcard_lock();
|
|
|
|
+ } else {
|
|
|
|
+ trace_sdcard_unlock();
|
|
|
|
+ }
|
|
if (erase) {
|
|
if (erase) {
|
|
if (!(sd->card_status & CARD_IS_LOCKED) || sd->blk_len > 1 ||
|
|
if (!(sd->card_status & CARD_IS_LOCKED) || sd->blk_len > 1 ||
|
|
set_pwd || clr_pwd || lock || sd->wp_switch ||
|
|
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;
|
|
uint32_t rca = 0x0000;
|
|
uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg;
|
|
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 */
|
|
/* Not interpreting this as an app command */
|
|
sd->card_status &= ~APP_CMD;
|
|
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;
|
|
rca = req.arg >> 16;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -788,7 +888,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
|
|
sd->multi_blk_cnt = 0;
|
|
sd->multi_blk_cnt = 0;
|
|
}
|
|
}
|
|
|
|
|
|
- DPRINTF("CMD%d 0x%08x state %d\n", req.cmd, req.arg, sd->state);
|
|
|
|
switch (req.cmd) {
|
|
switch (req.cmd) {
|
|
/* Basic commands (Class 0 and Class 1) */
|
|
/* Basic commands (Class 0 and Class 1) */
|
|
case 0: /* CMD0: GO_IDLE_STATE */
|
|
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 */
|
|
case 8: /* CMD8: SEND_IF_COND */
|
|
/* Physical Layer Specification Version 2.00 command */
|
|
/* 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;
|
|
}
|
|
}
|
|
- 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 */
|
|
case 9: /* CMD9: SEND_CSD */
|
|
switch (sd->state) {
|
|
switch (sd->state) {
|
|
@@ -971,24 +1066,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
|
|
}
|
|
}
|
|
break;
|
|
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 */
|
|
case 12: /* CMD12: STOP_TRANSMISSION */
|
|
switch (sd->state) {
|
|
switch (sd->state) {
|
|
case sd_sendingdata_state:
|
|
case sd_sendingdata_state:
|
|
@@ -1039,10 +1116,12 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
|
|
case 16: /* CMD16: SET_BLOCKLEN */
|
|
case 16: /* CMD16: SET_BLOCKLEN */
|
|
switch (sd->state) {
|
|
switch (sd->state) {
|
|
case sd_transfer_state:
|
|
case sd_transfer_state:
|
|
- if (req.arg > (1 << HWBLOCK_SHIFT))
|
|
|
|
|
|
+ if (req.arg > (1 << HWBLOCK_SHIFT)) {
|
|
sd->card_status |= BLOCK_LEN_ERROR;
|
|
sd->card_status |= BLOCK_LEN_ERROR;
|
|
- else
|
|
|
|
|
|
+ } else {
|
|
|
|
+ trace_sdcard_set_blocklen(req.arg);
|
|
sd->blk_len = req.arg;
|
|
sd->blk_len = req.arg;
|
|
|
|
+ }
|
|
|
|
|
|
return sd_r1;
|
|
return sd_r1;
|
|
|
|
|
|
@@ -1096,8 +1175,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
|
|
|
|
|
|
/* Block write commands (Class 4) */
|
|
/* Block write commands (Class 4) */
|
|
case 24: /* CMD24: WRITE_SINGLE_BLOCK */
|
|
case 24: /* CMD24: WRITE_SINGLE_BLOCK */
|
|
- if (sd->spi)
|
|
|
|
- goto unimplemented_cmd;
|
|
|
|
|
|
+ if (sd->spi) {
|
|
|
|
+ goto unimplemented_spi_cmd;
|
|
|
|
+ }
|
|
switch (sd->state) {
|
|
switch (sd->state) {
|
|
case sd_transfer_state:
|
|
case sd_transfer_state:
|
|
/* Writing in SPI mode not implemented. */
|
|
/* Writing in SPI mode not implemented. */
|
|
@@ -1122,8 +1202,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
|
|
break;
|
|
break;
|
|
|
|
|
|
case 25: /* CMD25: WRITE_MULTIPLE_BLOCK */
|
|
case 25: /* CMD25: WRITE_MULTIPLE_BLOCK */
|
|
- if (sd->spi)
|
|
|
|
- goto unimplemented_cmd;
|
|
|
|
|
|
+ if (sd->spi) {
|
|
|
|
+ goto unimplemented_spi_cmd;
|
|
|
|
+ }
|
|
switch (sd->state) {
|
|
switch (sd->state) {
|
|
case sd_transfer_state:
|
|
case sd_transfer_state:
|
|
/* Writing in SPI mode not implemented. */
|
|
/* Writing in SPI mode not implemented. */
|
|
@@ -1163,8 +1244,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
|
|
break;
|
|
break;
|
|
|
|
|
|
case 27: /* CMD27: PROGRAM_CSD */
|
|
case 27: /* CMD27: PROGRAM_CSD */
|
|
- if (sd->spi)
|
|
|
|
- goto unimplemented_cmd;
|
|
|
|
|
|
+ if (sd->spi) {
|
|
|
|
+ goto unimplemented_spi_cmd;
|
|
|
|
+ }
|
|
switch (sd->state) {
|
|
switch (sd->state) {
|
|
case sd_transfer_state:
|
|
case sd_transfer_state:
|
|
sd->state = sd_receivingdata_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) */
|
|
/* Lock card commands (Class 7) */
|
|
case 42: /* CMD42: LOCK_UNLOCK */
|
|
case 42: /* CMD42: LOCK_UNLOCK */
|
|
- if (sd->spi)
|
|
|
|
- goto unimplemented_cmd;
|
|
|
|
|
|
+ if (sd->spi) {
|
|
|
|
+ goto unimplemented_spi_cmd;
|
|
|
|
+ }
|
|
switch (sd->state) {
|
|
switch (sd->state) {
|
|
case sd_transfer_state:
|
|
case sd_transfer_state:
|
|
sd->state = sd_receivingdata_state;
|
|
sd->state = sd_receivingdata_state;
|
|
@@ -1288,9 +1371,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
|
|
}
|
|
}
|
|
break;
|
|
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)
|
|
* (see the SDIO Simplified Specification V2.0)
|
|
* Handle as illegal command but do not complain
|
|
* Handle as illegal command but do not complain
|
|
* on stderr, as some OSes may use these in their
|
|
* 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) */
|
|
/* Application specific commands (Class 8) */
|
|
case 55: /* CMD55: APP_CMD */
|
|
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->expecting_acmd = true;
|
|
sd->card_status |= APP_CMD;
|
|
sd->card_status |= APP_CMD;
|
|
return sd_r1;
|
|
return sd_r1;
|
|
|
|
|
|
case 56: /* CMD56: GEN_CMD */
|
|
case 56: /* CMD56: GEN_CMD */
|
|
- fprintf(stderr, "SD: GEN_CMD 0x%08x\n", req.arg);
|
|
|
|
-
|
|
|
|
switch (sd->state) {
|
|
switch (sd->state) {
|
|
case sd_transfer_state:
|
|
case sd_transfer_state:
|
|
sd->data_offset = 0;
|
|
sd->data_offset = 0;
|
|
@@ -1324,12 +1419,24 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
|
|
}
|
|
}
|
|
break;
|
|
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:
|
|
default:
|
|
bad_cmd:
|
|
bad_cmd:
|
|
qemu_log_mask(LOG_GUEST_ERROR, "SD: Unknown CMD%i\n", req.cmd);
|
|
qemu_log_mask(LOG_GUEST_ERROR, "SD: Unknown CMD%i\n", req.cmd);
|
|
return sd_illegal;
|
|
return sd_illegal;
|
|
|
|
|
|
- unimplemented_cmd:
|
|
|
|
|
|
+ unimplemented_spi_cmd:
|
|
/* Commands that are recognised but not yet implemented in SPI mode. */
|
|
/* 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",
|
|
qemu_log_mask(LOG_UNIMP, "SD: CMD%i not implemented in SPI mode\n",
|
|
req.cmd);
|
|
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,
|
|
static sd_rsp_type_t sd_app_command(SDState *sd,
|
|
SDRequest req)
|
|
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;
|
|
sd->card_status |= APP_CMD;
|
|
switch (req.cmd) {
|
|
switch (req.cmd) {
|
|
case 6: /* ACMD6: SET_BUS_WIDTH */
|
|
case 6: /* ACMD6: SET_BUS_WIDTH */
|
|
|
|
+ if (sd->spi) {
|
|
|
|
+ goto unimplemented_spi_cmd;
|
|
|
|
+ }
|
|
switch (sd->state) {
|
|
switch (sd->state) {
|
|
case sd_transfer_state:
|
|
case sd_transfer_state:
|
|
sd->sd_status[0] &= 0x3f;
|
|
sd->sd_status[0] &= 0x3f;
|
|
@@ -1402,42 +1512,41 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
|
|
sd->state = sd_transfer_state;
|
|
sd->state = sd_transfer_state;
|
|
return sd_r1;
|
|
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,
|
|
timer_mod_ns(sd->ocr_power_timer,
|
|
(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
|
|
(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
|
|
+ OCR_POWER_DELAY_NS));
|
|
+ OCR_POWER_DELAY_NS));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ if (FIELD_EX32(sd->ocr & req.arg, OCR, VDD_VOLTAGE_WINDOW)) {
|
|
/* We accept any voltage. 10000 V is nothing.
|
|
/* We accept any voltage. 10000 V is nothing.
|
|
*
|
|
*
|
|
* Once we're powered up, we advance straight to ready state
|
|
* Once we're powered up, we advance straight to ready state
|
|
* unless it's an enquiry ACMD41 (bits 23:0 == 0).
|
|
* 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 */
|
|
case 42: /* ACMD42: SET_CLR_CARD_DETECT */
|
|
switch (sd->state) {
|
|
switch (sd->state) {
|
|
@@ -1463,9 +1572,27 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
|
|
}
|
|
}
|
|
break;
|
|
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:
|
|
default:
|
|
/* Fall back to standard commands. */
|
|
/* Fall back to standard commands. */
|
|
return sd_normal_command(sd, req);
|
|
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);
|
|
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) {
|
|
if (req->cmd == 16 || req->cmd == 55) {
|
|
return 1;
|
|
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,
|
|
int sd_do_command(SDState *sd, SDRequest *req,
|
|
@@ -1508,6 +1635,12 @@ int sd_do_command(SDState *sd, SDRequest *req,
|
|
goto send_response;
|
|
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 (sd->card_status & CARD_IS_LOCKED) {
|
|
if (!cmd_valid_while_locked(sd, req)) {
|
|
if (!cmd_valid_while_locked(sd, req)) {
|
|
sd->card_status |= ILLEGAL_COMMAND;
|
|
sd->card_status |= ILLEGAL_COMMAND;
|
|
@@ -1574,10 +1707,12 @@ send_response:
|
|
|
|
|
|
case sd_r0:
|
|
case sd_r0:
|
|
case sd_illegal:
|
|
case sd_illegal:
|
|
- default:
|
|
|
|
rsplen = 0;
|
|
rsplen = 0;
|
|
break;
|
|
break;
|
|
|
|
+ default:
|
|
|
|
+ g_assert_not_reached();
|
|
}
|
|
}
|
|
|
|
+ trace_sdcard_response(sd_response_name(rtype), rsplen);
|
|
|
|
|
|
if (rtype != sd_illegal) {
|
|
if (rtype != sd_illegal) {
|
|
/* Clear the "clear on valid command" status bits now we've
|
|
/* Clear the "clear on valid command" status bits now we've
|
|
@@ -1587,16 +1722,7 @@ send_response:
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef DEBUG_SD
|
|
#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
|
|
#endif
|
|
|
|
|
|
return rsplen;
|
|
return rsplen;
|
|
@@ -1604,8 +1730,7 @@ send_response:
|
|
|
|
|
|
static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len)
|
|
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) {
|
|
if (!sd->blk || blk_pread(sd->blk, addr, sd->data, len) < 0) {
|
|
fprintf(stderr, "sd_blk_read: read error on host side\n");
|
|
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)
|
|
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) {
|
|
if (!sd->blk || blk_pwrite(sd->blk, addr, sd->data, len, 0) < 0) {
|
|
fprintf(stderr, "sd_blk_write: write error on host side\n");
|
|
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))
|
|
if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION))
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
+ trace_sdcard_write_data(sd->current_cmd, value);
|
|
switch (sd->current_cmd) {
|
|
switch (sd->current_cmd) {
|
|
case 24: /* CMD24: WRITE_SINGLE_BLOCK */
|
|
case 24: /* CMD24: WRITE_SINGLE_BLOCK */
|
|
sd->data[sd->data_offset ++] = value;
|
|
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;
|
|
io_len = (sd->ocr & (1 << 30)) ? 512 : sd->blk_len;
|
|
|
|
|
|
|
|
+ trace_sdcard_read_data(sd->current_cmd, io_len);
|
|
switch (sd->current_cmd) {
|
|
switch (sd->current_cmd) {
|
|
case 6: /* CMD6: SWITCH_FUNCTION */
|
|
case 6: /* CMD6: SWITCH_FUNCTION */
|
|
ret = sd->data[sd->data_offset ++];
|
|
ret = sd->data[sd->data_offset ++];
|
|
@@ -1792,21 +1920,6 @@ uint8_t sd_read_data(SDState *sd)
|
|
sd->state = sd_transfer_state;
|
|
sd->state = sd_transfer_state;
|
|
break;
|
|
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 */
|
|
case 13: /* ACMD13: SD_STATUS */
|
|
ret = sd->sd_status[sd->data_offset ++];
|
|
ret = sd->sd_status[sd->data_offset ++];
|
|
|
|
|