summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2005-02-14 23:42:32 +0000
committerJens Arnold <amiconn@rockbox.org>2005-02-14 23:42:32 +0000
commit4d6e482e5664a76ee61d065d4d49e3e385572c99 (patch)
tree322bce51794e39cd30dd6064d84465961f1499f7 /firmware
parent672092c6dcf61831044762d37096ce4170cf6904 (diff)
Some MMCs don't like reading their very last sector with the read_multiple_blocks command, so always read it with read_single_block. Slight optimisation.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5942 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/ata_mmc.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/firmware/drivers/ata_mmc.c b/firmware/drivers/ata_mmc.c
index 7149e111cd..7ba6dac296 100644
--- a/firmware/drivers/ata_mmc.c
+++ b/firmware/drivers/ata_mmc.c
@@ -626,7 +626,7 @@ int ata_read_sectors(IF_MV2(int drive,)
void* inbuf)
{
int ret = 0;
- int i;
+ int last_sector;
unsigned long addr;
unsigned char response;
void *inbuf_prev = NULL;
@@ -645,38 +645,44 @@ int ata_read_sectors(IF_MV2(int drive,)
if (start + incount > card->numsectors)
panicf("Reading past end of card\n");
+ /* some cards don't like reading the very last sector with
+ * CMD_READ_MULTIPLE_BLOCK, so make sure this sector is always
+ * read with CMD_READ_SINGLE_BLOCK. */
+ last_sector = (start + incount == card->numsectors) ? 1 : 0;
+
if (ret == 0)
{
- if (incount == 1)
- {
- ret = send_cmd(CMD_READ_SINGLE_BLOCK, addr, &response);
- if (ret == 0)
+ if (incount > 1)
+ {
+ ret = send_cmd(CMD_READ_MULTIPLE_BLOCK, addr, &response);
+ for (; (incount > last_sector) && (ret == 0); incount--)
{
ret = receive_sector(inbuf, inbuf_prev, card->read_timeout);
inbuf_prev = inbuf;
+ inbuf += SECTOR_SIZE;
last_disk_activity = current_tick;
}
+ if (ret == 0)
+ ret = send_cmd(CMD_STOP_TRANSMISSION, 0, &response);
}
- else
+ if (incount && (ret == 0))
{
- ret = send_cmd(CMD_READ_MULTIPLE_BLOCK, addr, &response);
- for (i = 0; (i < incount) && (ret == 0); i++)
+ ret = send_cmd(CMD_READ_SINGLE_BLOCK, addr, &response);
+ if (ret == 0)
{
ret = receive_sector(inbuf, inbuf_prev, card->read_timeout);
inbuf_prev = inbuf;
- inbuf += SECTOR_SIZE;
last_disk_activity = current_tick;
}
- if (ret == 0)
- ret = send_cmd(CMD_STOP_TRANSMISSION, 0, &response);
}
+
if (ret == 0)
bitswap(inbuf_prev, SECTOR_SIZE);
}
deselect_card();
mutex_unlock(&mmc_mutex);
-
+
/* only flush if reading went ok */
if ( (ret == 0) && delayed_write )
ata_flush();
@@ -690,7 +696,6 @@ int ata_write_sectors(IF_MV2(int drive,)
const void* buf)
{
int ret = 0;
- int i;
unsigned long addr;
unsigned char response;
tCardInfo *card;
@@ -724,7 +729,7 @@ int ata_write_sectors(IF_MV2(int drive,)
{
swapcopy_sector(buf); /* prepare first sector */
ret = send_cmd(CMD_WRITE_MULTIPLE_BLOCK, addr, &response);
- for (i = 1; (i < count) && (ret == 0); i++)
+ for (; (count > 1) && (ret == 0); count--)
{
buf += SECTOR_SIZE;
ret = send_sector(buf, card->write_timeout);