aboutsummaryrefslogtreecommitdiffstats
path: root/hw/goldfish_mmc.c
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2009-09-14 14:32:27 -0700
committerDavid 'Digit' Turner <digit@google.com>2009-09-14 14:32:27 -0700
commit5d8f37ad78fc66901af50c762029a501561f3b23 (patch)
tree206790f8f21000850a98c4f9590a79e779106278 /hw/goldfish_mmc.c
parentcd059b15f2c7df69f4a087bd66900eb172e41d1c (diff)
downloadexternal_qemu-5d8f37ad78fc66901af50c762029a501561f3b23.zip
external_qemu-5d8f37ad78fc66901af50c762029a501561f3b23.tar.gz
external_qemu-5d8f37ad78fc66901af50c762029a501561f3b23.tar.bz2
Merge upstream QEMU 10.0.50 into the Android source tree.
This change integrates many changes from the upstream QEMU sources. Its main purpose is to enable correct ARMv6 and ARMv7 support to the Android emulator. Due to the nature of the upstream code base, this unfortunately also required changes to many other parts of the source. Note that to ensure easier integrations in the future, some source files and directories that have heavy Android-specific customization have been renamed with an -android suffix. The original files are still there for easier integration tracking, but *never* compiled. For example: net.c net-android.c qemu-char.c qemu-char-android.c slirp/ slirp-android/ etc... Tested on linux-x86, darwin-x86 and windows host machines.
Diffstat (limited to 'hw/goldfish_mmc.c')
-rw-r--r--hw/goldfish_mmc.c76
1 files changed, 62 insertions, 14 deletions
diff --git a/hw/goldfish_mmc.c b/hw/goldfish_mmc.c
index 272f403..2295d2d 100644
--- a/hw/goldfish_mmc.c
+++ b/hw/goldfish_mmc.c
@@ -63,7 +63,7 @@ struct goldfish_mmc_state {
struct goldfish_device dev;
BlockDriverState *bs;
// pointer to our buffer
- uint8_t* buffer;
+ uint32_t buffer_address;
// offsets for read and write operations
uint32_t read_offset, write_offset;
// buffer status flags
@@ -78,11 +78,14 @@ struct goldfish_mmc_state {
uint32_t block_length;
uint32_t block_count;
int is_SDHC;
+
+ uint8_t* buf;
};
-#define GOLDFISH_MMC_SAVE_VERSION 1
+#define GOLDFISH_MMC_SAVE_VERSION 2
#define QFIELD_STRUCT struct goldfish_mmc_state
QFIELD_BEGIN(goldfish_mmc_fields)
+ QFIELD_INT32(buffer_address),
QFIELD_INT32(read_offset),
QFIELD_INT32(write_offset),
QFIELD_INT32(int_status),
@@ -101,7 +104,6 @@ static void goldfish_mmc_save(QEMUFile* f, void* opaque)
{
struct goldfish_mmc_state* s = opaque;
- qemu_put_be32(f, s->buffer - phys_ram_base);
qemu_put_struct(f, goldfish_mmc_fields, s);
}
@@ -112,7 +114,6 @@ static int goldfish_mmc_load(QEMUFile* f, void* opaque, int version_id)
if (version_id != GOLDFISH_MMC_SAVE_VERSION)
return -1;
- s->buffer = qemu_get_be32(f) + phys_ram_base;
return qemu_get_struct(f, goldfish_mmc_fields, s);
}
@@ -169,6 +170,48 @@ static const char* get_command_name(int command)
}
#endif
+static int goldfish_mmc_bdrv_read(struct goldfish_mmc_state *s,
+ int64_t sector_number,
+ target_phys_addr_t dst_address,
+ int num_sectors)
+{
+ int ret;
+
+ while (num_sectors > 0) {
+ ret = bdrv_read(s->bs, sector_number, s->buf, 1);
+ if (ret < 0)
+ return ret;
+
+ cpu_physical_memory_write(dst_address, s->buf, 512);
+ dst_address += 512;
+ num_sectors -= 1;
+ sector_number += 1;
+ }
+ return 0;
+}
+
+static int goldfish_mmc_bdrv_write(struct goldfish_mmc_state *s,
+ int64_t sector_number,
+ target_phys_addr_t dst_address,
+ int num_sectors)
+{
+ int ret;
+
+ while (num_sectors > 0) {
+ cpu_physical_memory_read(dst_address, s->buf, 512);
+
+ ret = bdrv_write(s->bs, sector_number, s->buf, 1);
+ if (ret < 0)
+ return ret;
+
+ dst_address += 512;
+ num_sectors -= 1;
+ sector_number += 1;
+ }
+ return 0;
+}
+
+
static void goldfish_mmc_do_command(struct goldfish_mmc_state *s, uint32_t cmd, uint32_t arg)
{
int result;
@@ -269,9 +312,15 @@ static void goldfish_mmc_do_command(struct goldfish_mmc_state *s, uint32_t cmd,
case SD_APP_SEND_SCR:
{
- uint32_t* scr = (uint32_t*)s->buffer;
+#if 1 /* this code is actually endian-safe */
+ const uint8_t scr[8] = "\x02\x25\x00\x00\x00\x00\x00\x00";
+#else /* this original code wasn't */
+ uint32_t scr[2];
scr[0] = 0x00002502;
scr[1] = 0x00000000;
+#endif
+ cpu_physical_memory_write(s->buffer_address, (uint8_t*)scr, 8);
+
s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA | R1_APP_CMD; //2336
new_status |= MMC_STAT_END_OF_DATA;
break;
@@ -293,9 +342,10 @@ static void goldfish_mmc_do_command(struct goldfish_mmc_state *s, uint32_t cmd,
case MMC_SWITCH:
if (arg == 0x00FFFFF1 || arg == 0x80FFFFF1) {
- uint8_t* switchbuf = s->buffer;
- memset(switchbuf, 0, 64);
- switchbuf[13] = 2;
+ uint8_t buff0[64];
+ memset(buff0, 0, sizeof buff0);
+ buff0[13] = 2;
+ cpu_physical_memory_write(s->buffer_address, buff0, sizeof buff0);
new_status |= MMC_STAT_END_OF_DATA;
}
s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA | R1_APP_CMD; //2336
@@ -317,7 +367,7 @@ static void goldfish_mmc_do_command(struct goldfish_mmc_state *s, uint32_t cmd,
if (arg & 511) fprintf(stderr, "offset %d is not multiple of 512 when reading\n", arg);
arg /= s->block_length;
}
- result = bdrv_read(s->bs, arg, s->buffer, s->block_count);
+ result = goldfish_mmc_bdrv_read(s, arg, s->buffer_address, s->block_count);
new_status |= MMC_STAT_END_OF_DATA;
s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA; // 2304
break;
@@ -335,7 +385,7 @@ static void goldfish_mmc_do_command(struct goldfish_mmc_state *s, uint32_t cmd,
arg /= s->block_length;
}
// arg is byte offset
- result = bdrv_write(s->bs, arg, s->buffer, s->block_count);
+ result = goldfish_mmc_bdrv_write(s, arg, s->buffer_address, s->block_count);
// bdrv_flush(s->bs);
new_status |= MMC_STAT_END_OF_DATA;
s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA; // 2304
@@ -363,7 +413,6 @@ static uint32_t goldfish_mmc_read(void *opaque, target_phys_addr_t offset)
uint32_t ret;
struct goldfish_mmc_state *s = opaque;
- offset -= s->dev.base;
switch(offset) {
case MMC_INT_STATUS:
// return current buffer status flags
@@ -394,8 +443,6 @@ static void goldfish_mmc_write(void *opaque, target_phys_addr_t offset, uint32_t
struct goldfish_mmc_state *s = opaque;
int status, old_status;
- offset -= s->dev.base;
-
switch(offset) {
case MMC_INT_STATUS:
@@ -416,7 +463,7 @@ static void goldfish_mmc_write(void *opaque, target_phys_addr_t offset, uint32_t
break;
case MMC_SET_BUFFER:
/* save pointer to buffer 1 */
- s->buffer = phys_ram_base + val;
+ s->buffer_address = val;
break;
case MMC_CMD:
goldfish_mmc_do_command(s, val, s->arg);
@@ -459,6 +506,7 @@ void goldfish_mmc_init(uint32_t base, int id, BlockDriverState* bs)
s->dev.size = 0x1000;
s->dev.irq_count = 1;
s->bs = bs;
+ s->buf = qemu_memalign(512,512);
goldfish_device_add(&s->dev, goldfish_mmc_readfn, goldfish_mmc_writefn, s);