mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-11 06:05:21 -05:00
Hopefully fixes the 'two byte inserted bug' of #FS8663. Combination of Martin Ritters and my findings on the issue.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19911 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
3cf148945e
commit
0852527d5f
1 changed files with 43 additions and 16 deletions
|
|
@ -481,15 +481,47 @@ static inline void copy_read_sectors_slow(unsigned char** buf)
|
||||||
/* Writes have to be kept slow for now */
|
/* Writes have to be kept slow for now */
|
||||||
static inline void copy_write_sectors(const unsigned char** buf)
|
static inline void copy_write_sectors(const unsigned char** buf)
|
||||||
{
|
{
|
||||||
int cnt = FIFO_LEN;
|
int cnt = FIFO_LEN - 1;
|
||||||
unsigned t;
|
unsigned t;
|
||||||
|
long time;
|
||||||
|
|
||||||
do
|
time = USEC_TIMER + 3;
|
||||||
|
if (((intptr_t)*buf & 3) == 0)
|
||||||
{
|
{
|
||||||
|
asm volatile (
|
||||||
|
"ldmia %[buf]!, { r3, r5, r7, r9 } \r\n"
|
||||||
|
"mov r4, r3, lsr #16 \r\n"
|
||||||
|
"mov r6, r5, lsr #16 \r\n"
|
||||||
|
"mov r8, r7, lsr #16 \r\n"
|
||||||
|
"mov r10, r9, lsr #16 \r\n"
|
||||||
|
"stmia %[data], { r3-r10 } \r\n"
|
||||||
|
"ldmia %[buf]!, { r3, r5, r7, r9 } \r\n"
|
||||||
|
"mov r4, r3, lsr #16 \r\n"
|
||||||
|
"mov r6, r5, lsr #16 \r\n"
|
||||||
|
"mov r8, r7, lsr #16 \r\n"
|
||||||
|
"mov %[t], r9, lsr #16 \r\n"
|
||||||
|
"stmia %[data], { r3-r9 } \r\n"
|
||||||
|
: [buf]"+&r"(*buf), [t]"=&r"(t)
|
||||||
|
: [data]"r"(&MMC_DATA_FIFO)
|
||||||
|
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
t = *(*buf)++;
|
||||||
|
t |= *(*buf)++ << 8;
|
||||||
|
MMC_DATA_FIFO = t;
|
||||||
|
} while (--cnt > 0); /* tail loop is faster */
|
||||||
t = *(*buf)++;
|
t = *(*buf)++;
|
||||||
t |= *(*buf)++ << 8;
|
t |= *(*buf)++ << 8;
|
||||||
MMC_DATA_FIFO = t;
|
}
|
||||||
} while (--cnt > 0); /* tail loop is faster */
|
/* Don't write the last word before at least 3 usec have elapsed since FIFO_EMPTY */
|
||||||
|
/* This prevents the 'two bytes inserted' bug. */
|
||||||
|
|
||||||
|
while (!TIME_AFTER(USEC_TIMER, time));
|
||||||
|
MMC_DATA_FIFO = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sd_select_bank(unsigned char bank)
|
static int sd_select_bank(unsigned char bank)
|
||||||
|
|
@ -988,15 +1020,13 @@ sd_write_retry:
|
||||||
{
|
{
|
||||||
/* SDHC */
|
/* SDHC */
|
||||||
ret = sd_command(SD_WRITE_MULTIPLE_BLOCK, start, NULL,
|
ret = sd_command(SD_WRITE_MULTIPLE_BLOCK, start, NULL,
|
||||||
0x1c00 | CMDAT_BUSY | CMDAT_WR_RD |
|
CMDAT_WR_RD | CMDAT_DATA_EN | CMDAT_RES_TYPE1);
|
||||||
CMDAT_DATA_EN | CMDAT_RES_TYPE1);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
ret = sd_command(SD_WRITE_MULTIPLE_BLOCK, start*BLOCK_SIZE, NULL,
|
ret = sd_command(SD_WRITE_MULTIPLE_BLOCK, start*BLOCK_SIZE, NULL,
|
||||||
0x1c00 | CMDAT_BUSY | CMDAT_WR_RD |
|
CMDAT_WR_RD | CMDAT_DATA_EN | CMDAT_RES_TYPE1);
|
||||||
CMDAT_DATA_EN | CMDAT_RES_TYPE1);
|
|
||||||
}
|
}
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto sd_write_error;
|
goto sd_write_error;
|
||||||
|
|
@ -1011,18 +1041,15 @@ sd_write_retry:
|
||||||
MMC_SD_STATE = SD_PRG;
|
MMC_SD_STATE = SD_PRG;
|
||||||
}
|
}
|
||||||
|
|
||||||
udelay(2); /* needed here (loop is too fast :-) */
|
copy_write_sectors(&buf); /* Copy one chunk of 16 words */
|
||||||
|
/* TODO: Switch bank if necessary */
|
||||||
|
|
||||||
/* Wait for the FIFO to empty */
|
/* Wait for the FIFO to empty */
|
||||||
if (sd_poll_status(STAT_XMIT_FIFO_EMPTY, 0x80000))
|
if (!sd_poll_status(STAT_XMIT_FIFO_EMPTY, 0x80000))
|
||||||
{
|
{
|
||||||
copy_write_sectors(&buf); /* Copy one chunk of 16 words */
|
ret = -EC_FIFO_WR_EMPTY;
|
||||||
/* TODO: Switch bank if necessary */
|
goto sd_write_error;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = -EC_FIFO_WR_EMPTY;
|
|
||||||
goto sd_write_error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
last_disk_activity = current_tick;
|
last_disk_activity = current_tick;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue