summary refs log tree commit diff stats
path: root/hw/sd.c
diff options
context:
space:
mode:
authorDr. David Alan Gilbert <david.gilbert@linaro.org>2011-07-25 13:21:30 +0100
committerAnthony Liguori <aliguori@us.ibm.com>2011-07-29 09:33:48 -0500
commit33fa8234c3d642317583c992b7fdc67ce7fdd1b5 (patch)
tree92ffb14b9d902239e2ed4432469722ac9a7490d4 /hw/sd.c
parentcbbab9226da9572346837466a8770c117e7e65a2 (diff)
downloadfocaccia-qemu-33fa8234c3d642317583c992b7fdc67ce7fdd1b5.tar.gz
focaccia-qemu-33fa8234c3d642317583c992b7fdc67ce7fdd1b5.zip
Fix last sector write on sd card
    When writing the last sector of an SD card using WRITE_MULTIPLE_BLOCK
QEmu throws an error saying that we've run off the end, and leaves
itself in the wrong state.

    Tested on ARM Vexpress model.

Signed-off-by: Dr. David Alan Gilbert <david.gilbert@linaro.org>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/sd.c')
-rw-r--r--hw/sd.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/hw/sd.c b/hw/sd.c
index cedfb20249..219a0dd296 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -1450,14 +1450,8 @@ void sd_write_data(SDState *sd, uint8_t value)
         break;
 
     case 25:	/* CMD25:  WRITE_MULTIPLE_BLOCK */
-        sd->data[sd->data_offset ++] = value;
-        if (sd->data_offset >= sd->blk_len) {
-            /* TODO: Check CRC before committing */
-            sd->state = sd_programming_state;
-            BLK_WRITE_BLOCK(sd->data_start, sd->data_offset);
-            sd->blk_written ++;
-            sd->data_start += sd->blk_len;
-            sd->data_offset = 0;
+        if (sd->data_offset == 0) {
+            /* Start of the block - lets check the address is valid */
             if (sd->data_start + sd->blk_len > sd->size) {
                 sd->card_status |= ADDRESS_ERROR;
                 break;
@@ -1466,6 +1460,15 @@ void sd_write_data(SDState *sd, uint8_t value)
                 sd->card_status |= WP_VIOLATION;
                 break;
             }
+        }
+        sd->data[sd->data_offset++] = value;
+        if (sd->data_offset >= sd->blk_len) {
+            /* TODO: Check CRC before committing */
+            sd->state = sd_programming_state;
+            BLK_WRITE_BLOCK(sd->data_start, sd->data_offset);
+            sd->blk_written++;
+            sd->data_start += sd->blk_len;
+            sd->data_offset = 0;
             sd->csd[14] |= 0x40;
 
             /* Bzzzzzzztt .... Operation complete.  */