summaryrefslogtreecommitdiff
path: root/qemu
diff options
context:
space:
mode:
authorbalrog <balrog>2007-12-24 14:41:39 +0000
committerbalrog <balrog>2007-12-24 14:41:39 +0000
commit3769e5686bdf40b9de4f4bbc16e50df8e6e082ec (patch)
treec16dfc990363719b9e366edf1a431a9b06f76559 /qemu
parent4f22e0b88d7c86eb46e23908470ea6bf8122f11d (diff)
Implement SD CMD8 and R7 from the newer SD Physical Spec Version 2.00.
Remove bogus setting of bits 63 of R2 type responses. Make some constants static to allow definitions by the same name for SDIO.
Diffstat (limited to 'qemu')
-rw-r--r--qemu/hw/sd.c43
1 files changed, 38 insertions, 5 deletions
diff --git a/qemu/hw/sd.c b/qemu/hw/sd.c
index e6e80db0..1f71d85a 100644
--- a/qemu/hw/sd.c
+++ b/qemu/hw/sd.c
@@ -49,6 +49,7 @@ typedef enum {
sd_r2_s, /* CSD register */
sd_r3, /* OCR register */
sd_r6 = 6, /* Published RCA response */
+ sd_r7, /* Operating voltage */
sd_r1b = -1,
} sd_rsp_type_t;
@@ -77,6 +78,7 @@ struct SDState {
uint16_t rca;
uint32_t card_status;
uint8_t sd_status[64];
+ uint32_t vhs;
int wp_switch;
int *wp_groups;
uint32_t size;
@@ -126,9 +128,9 @@ static void sd_set_status(SDState *sd)
sd->card_status |= sd->state << 9;
}
-const sd_cmd_type_t sd_cmd_type[64] = {
+static const sd_cmd_type_t sd_cmd_type[64] = {
sd_bc, sd_none, sd_bcr, sd_bcr, sd_none, sd_none, sd_none, sd_ac,
- sd_none, 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,
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_ac, sd_ac, sd_none, sd_none, sd_none, sd_none, sd_ac, sd_none,
@@ -137,7 +139,7 @@ const sd_cmd_type_t sd_cmd_type[64] = {
sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
};
-const sd_cmd_type_t sd_acmd_type[64] = {
+static const sd_cmd_type_t sd_acmd_type[64] = {
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_adtc, sd_none, sd_none,
sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_adtc, sd_ac,
@@ -190,6 +192,7 @@ static uint16_t sd_crc16(void *message, size_t width)
static void sd_set_ocr(SDState *sd)
{
+ /* All voltages OK, card power-up OK, Standard Capacity SD Memory Card */
sd->ocr = 0x80ffff80;
}
@@ -349,6 +352,14 @@ static void sd_response_r6_make(SDState *sd, uint8_t *response)
response[3] = status & 0xff;
}
+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;
+}
+
static void sd_reset(SDState *sd, BlockDriverState *bdrv)
{
uint32_t size;
@@ -685,6 +696,25 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
}
break;
+ 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 >> ffs(req.arg & ~0xff)))
+ return sd->spi ? sd_r7 : sd_r0;
+
+ /* Accept. */
+ sd->vhs = req.arg;
+ return sd_r7;
+
+ default:
+ break;
+ }
+ break;
+
case 9: /* CMD9: SEND_CSD */
switch (sd->state) {
case sd_standby_state:
@@ -1238,13 +1268,11 @@ int sd_do_command(SDState *sd, struct sd_request_s *req,
case sd_r2_i:
memcpy(response, sd->cid, sizeof(sd->cid));
- response[7] |= 1;
rsplen = 16;
break;
case sd_r2_s:
memcpy(response, sd->csd, sizeof(sd->csd));
- response[7] |= 1;
rsplen = 16;
break;
@@ -1258,6 +1286,11 @@ int sd_do_command(SDState *sd, struct sd_request_s *req,
rsplen = 4;
break;
+ case sd_r7:
+ sd_response_r7_make(sd, response);
+ rsplen = 4;
+ break;
+
case sd_r0:
default:
rsplen = 0;