mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-08 12:45:26 -05:00
FS#10113 - Sansa AMS : do not use unaligned buffers on ATA DMA by Rafaël Carré.
Fixes various storage related problems like stuttering audio, md5sum and test disk failure and Sansa Fuze's backdrop corruption by using aligned buffers. There's a speed penalty but stability has more priority. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20679 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
bac611868e
commit
ec797ed622
1 changed files with 24 additions and 5 deletions
|
|
@ -645,14 +645,18 @@ static int sd_select_bank(signed char bank)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define UNALIGNED_NUM_SECTORS 10
|
||||
static int32_t aligned_buffer[UNALIGNED_NUM_SECTORS* (SECTOR_SIZE / 4)];
|
||||
|
||||
static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
|
||||
int count, void* buf, bool write)
|
||||
int count, void* buf, const bool write)
|
||||
{
|
||||
#ifndef HAVE_MULTIVOLUME
|
||||
const int drive = 0;
|
||||
#endif
|
||||
int ret = 0;
|
||||
int bank;
|
||||
bool unaligned_transfer = (int)buf & 3;
|
||||
|
||||
/* skip SanDisk OF */
|
||||
if (drive == INTERNAL_AS3525)
|
||||
|
|
@ -706,17 +710,30 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
|
|||
|
||||
while(count)
|
||||
{
|
||||
/* Interrupt handler might set this to true during transfer */
|
||||
retry = false;
|
||||
/* 128 * 512 = 2^16, and doesn't fit in the 16 bits of DATA_LENGTH
|
||||
* register, so we have to transfer maximum 127 sectors at a time. */
|
||||
unsigned int transfer = (count >= 128) ? 127 : count; /* sectors */
|
||||
void *dma_buf;
|
||||
const int cmd =
|
||||
write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK;
|
||||
int arg = start;
|
||||
if(!(card_info[drive].ocr & (1<<30))) /* not SDHC */
|
||||
arg *= BLOCK_SIZE;
|
||||
|
||||
/* Interrupt handler might set this to true during transfer */
|
||||
retry = false;
|
||||
|
||||
if(unaligned_transfer)
|
||||
{
|
||||
dma_buf = aligned_buffer;
|
||||
if(transfer > UNALIGNED_NUM_SECTORS)
|
||||
transfer = UNALIGNED_NUM_SECTORS;
|
||||
if(write)
|
||||
memcpy(aligned_buffer, buf, transfer * SECTOR_SIZE);
|
||||
}
|
||||
else
|
||||
dma_buf = buf;
|
||||
|
||||
if(!send_cmd(drive, cmd, arg, MCI_ARG, NULL))
|
||||
{
|
||||
ret -= 3*20;
|
||||
|
|
@ -724,11 +741,11 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
|
|||
}
|
||||
|
||||
if(write)
|
||||
dma_enable_channel(0, buf, MCI_FIFO(drive),
|
||||
dma_enable_channel(0, dma_buf, MCI_FIFO(drive),
|
||||
(drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
|
||||
DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL);
|
||||
else
|
||||
dma_enable_channel(0, MCI_FIFO(drive), buf,
|
||||
dma_enable_channel(0, MCI_FIFO(drive), dma_buf,
|
||||
(drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
|
||||
DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL);
|
||||
|
||||
|
|
@ -743,6 +760,8 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
|
|||
wakeup_wait(&transfer_completion_signal, TIMEOUT_BLOCK);
|
||||
if(!retry)
|
||||
{
|
||||
if(unaligned_transfer && !write)
|
||||
memcpy(buf, aligned_buffer, transfer * SECTOR_SIZE);
|
||||
buf += transfer * SECTOR_SIZE;
|
||||
start += transfer;
|
||||
count -= transfer;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue