]> Git Repo - qemu.git/blobdiff - hw/sd.c
Scale TSC2102 touchscreen pressure value more realistically (still could be better).
[qemu.git] / hw / sd.c
diff --git a/hw/sd.c b/hw/sd.c
index 08e8805e54cf82f626d66840092f020cb604c260..93ad3dab81a4d8990db898ec23db3ac502ea7d4c 100644 (file)
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -87,6 +87,7 @@ struct SDState {
     int pwd_len;
     int function_group[6];
 
+    int spi;
     int current_cmd;
     int blk_written;
     uint32_t data_start;
@@ -308,8 +309,8 @@ static int sd_req_crc_validate(struct sd_request_s *req)
     return sd_crc7(buffer, 5) != req->crc;     /* TODO */
 }
 
-void sd_response_r1_make(SDState *sd,
-                         uint8_t *response, uint32_t last_status)
+static void sd_response_r1_make(SDState *sd,
+                                uint8_t *response, uint32_t last_status)
 {
     uint32_t mask = CARD_STATUS_B ^ ILLEGAL_COMMAND;
     uint32_t status;
@@ -323,7 +324,7 @@ void sd_response_r1_make(SDState *sd,
     response[3] = (status >> 0) & 0xff;
 }
 
-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;
@@ -331,7 +332,7 @@ void sd_response_r3_make(SDState *sd, uint8_t *response)
     response[3] = (sd->ocr >> 0) & 0xff;
 }
 
-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;
@@ -377,7 +378,6 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv)
         qemu_free(sd->wp_groups);
     sd->wp_switch = bdrv_is_read_only(bdrv);
     sd->wp_groups = (int *) qemu_mallocz(sizeof(int) * sect);
-    memset(sd->wp_groups, 0, sizeof(int) * sect);
     memset(sd->function_group, 0, sizeof(int) * 6);
     sd->erase_start = 0;
     sd->erase_end = 0;
@@ -396,11 +396,16 @@ static void sd_cardchange(void *opaque)
     }
 }
 
-SDState *sd_init(BlockDriverState *bs)
+/* We do not model the chip select pin, so allow the board to select
+   whether card should be in SSI or MMC/SD mode.  It is also up to the
+   board to ensure that ssi transfers only occur when the chip select
+   is asserted.  */
+SDState *sd_init(BlockDriverState *bs, int is_spi)
 {
     SDState *sd;
 
     sd = (SDState *) qemu_mallocz(sizeof(SDState));
+    sd->spi = is_spi;
     sd_reset(sd, bs);
     bdrv_set_change_cb(sd->bdrv, sd_cardchange, sd);
     return sd;
@@ -568,16 +573,25 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
     case 0:    /* CMD0:   GO_IDLE_STATE */
         switch (sd->state) {
         case sd_inactive_state:
-            return sd_r0;
+            return sd->spi ? sd_r1 : sd_r0;
 
         default:
             sd->state = sd_idle_state;
             sd_reset(sd, sd->bdrv);
-            return sd_r0;
+            return sd->spi ? sd_r1 : sd_r0;
         }
         break;
 
+    case 1:    /* CMD1:   SEND_OP_CMD */
+        if (!sd->spi)
+            goto bad_cmd;
+
+        sd->state = sd_transfer_state;
+        return sd_r1;
+
     case 2:    /* CMD2:   ALL_SEND_CID */
+        if (sd->spi)
+            goto bad_cmd;
         switch (sd->state) {
         case sd_ready_state:
             sd->state = sd_identification_state;
@@ -589,6 +603,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
         break;
 
     case 3:    /* CMD3:   SEND_RELATIVE_ADDR */
+        if (sd->spi)
+            goto bad_cmd;
         switch (sd->state) {
         case sd_identification_state:
         case sd_standby_state:
@@ -602,6 +618,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
         break;
 
     case 4:    /* CMD4:   SEND_DSR */
+        if (sd->spi)
+            goto bad_cmd;
         switch (sd->state) {
         case sd_standby_state:
             break;
@@ -612,6 +630,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
         break;
 
     case 6:    /* CMD6:   SWITCH_FUNCTION */
+        if (sd->spi)
+            goto bad_cmd;
         switch (sd->mode) {
         case sd_data_transfer_mode:
             sd_function_switch(sd, req.arg);
@@ -626,6 +646,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
         break;
 
     case 7:    /* CMD7:   SELECT/DESELECT_CARD */
+        if (sd->spi)
+            goto bad_cmd;
         switch (sd->state) {
         case sd_standby_state:
             if (sd->rca != rca)
@@ -669,6 +691,15 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
 
             return sd_r2_s;
 
+        case sd_transfer_state:
+            if (!sd->spi)
+                break;
+            sd->state = sd_sendingdata_state;
+            memcpy(sd->data, sd->csd, 16);
+            sd->data_start = req.arg;
+            sd->data_offset = 0;
+            return sd_r1;
+
         default:
             break;
         }
@@ -682,12 +713,23 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
 
             return sd_r2_i;
 
+        case sd_transfer_state:
+            if (!sd->spi)
+                break;
+            sd->state = sd_sendingdata_state;
+            memcpy(sd->data, sd->cid, 16);
+            sd->data_start = req.arg;
+            sd->data_offset = 0;
+            return sd_r1;
+
         default:
             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;
@@ -734,6 +776,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
         break;
 
     case 15:   /* CMD15:  GO_INACTIVE_STATE */
+        if (sd->spi)
+            goto bad_cmd;
         switch (sd->mode) {
         case sd_data_transfer_mode:
             if (sd->rca != rca)
@@ -797,8 +841,13 @@ 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;
         switch (sd->state) {
         case sd_transfer_state:
+            /* Writing in SPI mode not implemented.  */
+            if (sd->spi)
+                break;
             sd->state = sd_receivingdata_state;
             sd->data_start = req.arg;
             sd->data_offset = 0;
@@ -818,8 +867,13 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
         break;
 
     case 25:   /* CMD25:  WRITE_MULTIPLE_BLOCK */
+        if (sd->spi)
+            goto unimplemented_cmd;
         switch (sd->state) {
         case sd_transfer_state:
+            /* Writing in SPI mode not implemented.  */
+            if (sd->spi)
+                break;
             sd->state = sd_receivingdata_state;
             sd->data_start = req.arg;
             sd->data_offset = 0;
@@ -839,6 +893,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
         break;
 
     case 26:   /* CMD26:  PROGRAM_CID */
+        if (sd->spi)
+            goto bad_cmd;
         switch (sd->state) {
         case sd_transfer_state:
             sd->state = sd_receivingdata_state;
@@ -852,6 +908,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
         break;
 
     case 27:   /* CMD27:  PROGRAM_CSD */
+        if (sd->spi)
+            goto unimplemented_cmd;
         switch (sd->state) {
         case sd_transfer_state:
             sd->state = sd_receivingdata_state;
@@ -963,6 +1021,8 @@ 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;
         switch (sd->state) {
         case sd_transfer_state:
             sd->state = sd_receivingdata_state;
@@ -1001,10 +1061,17 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
         break;
 
     default:
+    bad_cmd:
         sd->card_status |= ILLEGAL_COMMAND;
 
         printf("SD: Unknown CMD%i\n", req.cmd);
         return sd_r0;
+
+    unimplemented_cmd:
+        /* Commands that are recognised but not yet implemented in SPI mode.  */
+        sd->card_status |= ILLEGAL_COMMAND;
+        printf ("SD: CMD%i not implemented in SPI mode\n", req.cmd);
+        return sd_r0;
     }
 
     sd->card_status |= ILLEGAL_COMMAND;
@@ -1070,6 +1137,11 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
         break;
 
     case 41:   /* ACMD41: SD_APP_OP_COND */
+        if (sd->spi) {
+            /* SEND_OP_CMD */
+            sd->state = sd_transfer_state;
+            return sd_r1;
+        }
         switch (sd->state) {
         case sd_idle_state:
             /* We accept any voltage.  10000 V is nothing.  */
@@ -1415,6 +1487,14 @@ uint8_t sd_read_data(SDState *sd)
             sd->state = sd_transfer_state;
         break;
 
+    case 9:    /* CMD9:   SEND_CSD */
+    case 10:   /* CMD10:  SEND_CID */
+        ret = sd->data[sd->data_offset ++];
+
+        if (sd->data_offset >= 16)
+            sd->state = sd_transfer_state;
+        break;
+
     case 11:   /* CMD11:  READ_DAT_UNTIL_STOP */
         if (sd->data_offset == 0)
             BLK_READ_BLOCK(sd->data_start, sd->blk_len);
This page took 0.033374 seconds and 4 git commands to generate.