diff --git a/hw/sd.c b/hw/sd.c
index 9888547..4d306af 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -81,7 +81,7 @@ struct SDState {
     uint32_t vhs;
     int wp_switch;
     int *wp_groups;
-    uint32_t size;
+    uint64_t size;
     int blk_len;
     uint32_t erase_start;
     uint32_t erase_end;
@@ -92,7 +92,7 @@ struct SDState {
     int spi;
     int current_cmd;
     int blk_written;
-    uint32_t data_start;
+    uint64_t data_start;
     uint32_t data_offset;
     uint8_t data[512];
     qemu_irq readonly_cb;
@@ -249,37 +249,59 @@ static const uint8_t sd_csd_rw_mask[16] = {
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfe,
 };
 
-static void sd_set_csd(SDState *sd, uint32_t size)
+static void sd_set_csd(SDState *sd, uint64_t size)
 {
     uint32_t csize = (size >> (CMULT_SHIFT + HWBLOCK_SHIFT)) - 1;
     uint32_t sectsize = (1 << (SECTOR_SHIFT + 1)) - 1;
     uint32_t wpsize = (1 << (WPGROUP_SHIFT + 1)) - 1;
 
-    sd->csd[0] = 0x00;		/* CSD structure */
-    sd->csd[1] = 0x26;		/* Data read access-time-1 */
-    sd->csd[2] = 0x00;		/* Data read access-time-2 */
-    sd->csd[3] = 0x5a;		/* Max. data transfer rate */
-    sd->csd[4] = 0x5f;		/* Card Command Classes */
-    sd->csd[5] = 0x50 |		/* Max. read data block length */
-        HWBLOCK_SHIFT;
-    sd->csd[6] = 0xe0 |		/* Partial block for read allowed */
-        ((csize >> 10) & 0x03);
-    sd->csd[7] = 0x00 |		/* Device size */
-        ((csize >> 2) & 0xff);
-    sd->csd[8] = 0x3f |		/* Max. read current */
-        ((csize << 6) & 0xc0);
-    sd->csd[9] = 0xfc |		/* Max. write current */
-        ((CMULT_SHIFT - 2) >> 1);
-    sd->csd[10] = 0x40 |	/* Erase sector size */
-        (((CMULT_SHIFT - 2) << 7) & 0x80) | (sectsize >> 1);
-    sd->csd[11] = 0x00 |	/* Write protect group size */
-        ((sectsize << 7) & 0x80) | wpsize;
-    sd->csd[12] = 0x90 |	/* Write speed factor */
-        (HWBLOCK_SHIFT >> 2);
-    sd->csd[13] = 0x20 |	/* Max. write data block length */
-        ((HWBLOCK_SHIFT << 6) & 0xc0);
-    sd->csd[14] = 0x00;		/* File format group */
-    sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1;
+    if (size <= 0x40000000) {
+	    sd->csd[0] = 0x00;		/* CSD structure */
+	    sd->csd[1] = 0x26;		/* Data read access-time-1 */
+	    sd->csd[2] = 0x00;		/* Data read access-time-2 */
+	    sd->csd[3] = 0x5a;		/* Max. data transfer rate */
+	    sd->csd[4] = 0x5f;		/* Card Command Classes */
+	    sd->csd[5] = 0x50 |		/* Max. read data block length */
+		HWBLOCK_SHIFT;
+	    sd->csd[6] = 0xe0 |		/* Partial block for read allowed */
+		((csize >> 10) & 0x03);
+	    sd->csd[7] = 0x00 |		/* Device size */
+		((csize >> 2) & 0xff);
+	    sd->csd[8] = 0x3f |		/* Max. read current */
+		((csize << 6) & 0xc0);
+	    sd->csd[9] = 0xfc |		/* Max. write current */
+		((CMULT_SHIFT - 2) >> 1);
+	    sd->csd[10] = 0x40 |	/* Erase sector size */
+		(((CMULT_SHIFT - 2) << 7) & 0x80) | (sectsize >> 1);
+	    sd->csd[11] = 0x00 |	/* Write protect group size */
+		((sectsize << 7) & 0x80) | wpsize;
+	    sd->csd[12] = 0x90 |	/* Write speed factor */
+		(HWBLOCK_SHIFT >> 2);
+	    sd->csd[13] = 0x20 |	/* Max. write data block length */
+		((HWBLOCK_SHIFT << 6) & 0xc0);
+	    sd->csd[14] = 0x00;		/* File format group */
+	    sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1;
+    } else {
+    	    size /= 512 * 1024;
+    	    size -= 1;
+    	    sd->csd[0] = 0x40;
+    	    sd->csd[1] = 0x0e;
+    	    sd->csd[2] = 0x00;
+    	    sd->csd[3] = 0x32;
+    	    sd->csd[4] = 0x5b;
+    	    sd->csd[5] = 0x59;
+    	    sd->csd[6] = 0x00;
+    	    sd->csd[7] = (size >> 16) & 0xff;
+    	    sd->csd[8] = (size >> 8) & 0xff;
+    	    sd->csd[9] = (size & 0xff);
+    	    sd->csd[10] = 0x7f;
+    	    sd->csd[11] = 0x80;
+    	    sd->csd[12] = 0x0a;
+    	    sd->csd[13] = 0x40;
+    	    sd->csd[14] = 0x00;
+    	    sd->csd[15] = 0x00;
+    	    sd->ocr |= (1 << 30);
+    }
 }
 
 static void sd_set_rca(SDState *sd)
@@ -362,7 +384,7 @@ static void sd_response_r7_make(SDState *sd, uint8_t
*response)
 
 static void sd_reset(SDState *sd, BlockDriverState *bdrv)
 {
-    uint32_t size;
+    uint64_t size;
     uint64_t sect;
 
