summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafaël Carré <rafael.carre@gmail.com>2009-05-26 21:08:47 +0000
committerRafaël Carré <rafael.carre@gmail.com>2009-05-26 21:08:47 +0000
commit83eb479732879e9852064644942ca36a7fd986a9 (patch)
treeaf8f86de1c1829da8f13c6ca7f4dc963ca01c2b5
parent3ca0614de9a3c4dc633e4c9f9ba459d89e44dd92 (diff)
downloadrockbox-83eb479732879e9852064644942ca36a7fd986a9.zip
rockbox-83eb479732879e9852064644942ca36a7fd986a9.tar.gz
rockbox-83eb479732879e9852064644942ca36a7fd986a9.tar.bz2
rockbox-83eb479732879e9852064644942ca36a7fd986a9.tar.xz
FS#10216 : Sansa AMS : Do not cross a bank boundary in a single transfer (Only for 8GB or more -if they exist- players)
Also add a few comments in the code git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21096 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/as3525/ata_sd_as3525.c66
1 files changed, 36 insertions, 30 deletions
diff --git a/firmware/target/arm/as3525/ata_sd_as3525.c b/firmware/target/arm/as3525/ata_sd_as3525.c
index 03a6a8b..a0b9b13 100644
--- a/firmware/target/arm/as3525/ata_sd_as3525.c
+++ b/firmware/target/arm/as3525/ata_sd_as3525.c
@@ -142,8 +142,8 @@ void INT_GPIOA(void)
GPIOA_IC = (1<<2);
timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0);
}
-#endif
-#endif
+#endif /* defined(SANSA_E200V2) || defined(SANSA_FUZE) */
+#endif /* HAVE_HOTSWAP */
void INT_NAND(void)
{
@@ -211,7 +211,7 @@ static bool send_cmd(const int drive, const int cmd, const int arg,
{ /* resp received */
if(flags & MCI_LONG_RESP)
{
- /* store the response in little endian order for the words */
+ /* store the response in reverse words order */
response[0] = MCI_RESP3(drive);
response[1] = MCI_RESP2(drive);
response[2] = MCI_RESP1(drive);
@@ -322,7 +322,7 @@ static int sd_init_card(const int drive)
card_info[drive].initialized = 1;
- MCI_CLOCK(drive) |= MCI_CLOCK_BYPASS; /* full speed */
+ MCI_CLOCK(drive) |= MCI_CLOCK_BYPASS; /* full speed for controller clock */
mci_delay();
/*
@@ -626,7 +626,6 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
const int drive = 0;
#endif
int ret = 0;
- int bank;
bool unaligned_transfer = (int)buf & 3;
/* skip SanDisk OF */
@@ -647,29 +646,10 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
last_disk_activity = current_tick;
- /* Only switch banks for internal storage */
- if(drive == INTERNAL_AS3525)
- {
- bank = start / BLOCKS_PER_BANK;
-
- if(card_info[INTERNAL_AS3525].current_bank != bank)
- {
- ret = sd_select_bank(bank);
- if (ret < 0)
- {
- ret -= 20;
- goto sd_transfer_error;
- }
- }
-
- start -= bank * BLOCKS_PER_BANK;
- }
-
-
ret = sd_wait_for_state(drive, SD_TRAN);
if (ret < 0)
{
- ret -= 2*20;
+ ret -= 20;
goto sd_transfer_error;
}
@@ -683,13 +663,35 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
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;
+ unsigned long bank_start = start;
/* Interrupt handler might set this to true during transfer */
retry = false;
+ /* Only switch banks for internal storage */
+ if(drive == INTERNAL_AS3525)
+ {
+ int bank = start / BLOCKS_PER_BANK; /* Current bank */
+
+ /* Switch bank if needed */
+ if(card_info[INTERNAL_AS3525].current_bank != bank)
+ {
+ ret = sd_select_bank(bank);
+ if (ret < 0)
+ {
+ ret -= 2*20;
+ goto sd_transfer_error;
+ }
+ }
+
+ /* Adjust start block in current bank */
+ bank_start -= bank * BLOCKS_PER_BANK;
+
+ /* Do not cross a bank boundary in a single transfer loop */
+ if((transfer + bank_start) >= BLOCKS_PER_BANK)
+ transfer = BLOCKS_PER_BANK - bank_start;
+ }
+
if(unaligned_transfer)
{
dma_buf = aligned_buffer;
@@ -698,10 +700,14 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
if(write)
memcpy(aligned_buffer, buf, transfer * SECTOR_SIZE);
}
- else
+ else /* Aligned transfers are faster : no memcpy */
dma_buf = buf;
- if(!send_cmd(drive, cmd, arg, MCI_ARG, NULL))
+ /* Set bank_start to the correct unit (blocks or bytes) */
+ if(!(card_info[drive].ocr & (1<<30))) /* not SDHC */
+ bank_start *= BLOCK_SIZE;
+
+ if(!send_cmd(drive, cmd, bank_start, MCI_ARG, NULL))
{
ret -= 3*20;
goto sd_transfer_error;