diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2011-01-29 16:54:36 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2011-01-29 16:54:36 +0000 |
commit | e9749d1b93f23b3bc36305ad1d39ca5e5c0cb3a8 (patch) | |
tree | a997eee450ed119bfb2b1c17a23759f1e72ccde2 /firmware/target/arm/as3525/sd-as3525v2.c | |
parent | 7436e7ab4112bbda3bd4e534fd6fc49a9286904e (diff) |
AMSv2 SD: Fix card insert lockups in USB mode. First, get rid of infinite loops and retry those a limited number of times-- no explaination for their dubious existence was offered in the source. Second, SD thread was no longer monitoring inserts (and it wouldn't really matter if it were). Thus, .initialized was reported as '1' despite the new card needing reinit.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29169 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/as3525/sd-as3525v2.c')
-rw-r--r-- | firmware/target/arm/as3525/sd-as3525v2.c | 105 |
1 files changed, 63 insertions, 42 deletions
diff --git a/firmware/target/arm/as3525/sd-as3525v2.c b/firmware/target/arm/as3525/sd-as3525v2.c index 929a036935..70d7c8fda1 100644 --- a/firmware/target/arm/as3525/sd-as3525v2.c +++ b/firmware/target/arm/as3525/sd-as3525v2.c @@ -334,9 +334,6 @@ static tCardInfo card_info[NUM_DRIVES]; /* for compatibility */ static long last_disk_activity = -1; -#define MIN_YIELD_PERIOD 5 /* ticks */ -static long next_yield = 0; - static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; static const char sd_thread_name[] = "ata/sd"; static struct mutex sd_mtx SHAREDBSS_ATTR; @@ -470,10 +467,18 @@ static int sd_wait_for_tran_state(const int drive) { unsigned long response; unsigned int timeout = current_tick + 5*HZ; + int cmd_retry = 10; while (1) { - while(!(send_cmd(drive, SD_SEND_STATUS, card_info[drive].rca, MCI_RESP, &response))); + while (!send_cmd(drive, SD_SEND_STATUS, card_info[drive].rca, MCI_RESP, + &response) && cmd_retry > 0) + { + cmd_retry--; + } + + if (cmd_retry <= 0) + return -1; if (((response >> 9) & 0xf) == SD_TRAN) return 0; @@ -481,11 +486,7 @@ static int sd_wait_for_tran_state(const int drive) if(TIME_AFTER(current_tick, timeout)) return -10 * ((response >> 9) & 0xf); - if (TIME_AFTER(current_tick, next_yield)) - { - yield(); - next_yield = current_tick + MIN_YIELD_PERIOD; - } + last_disk_activity = current_tick; } } @@ -669,11 +670,13 @@ static void sd_thread(void) */ if (microsd_init) queue_broadcast(SYS_FS_CHANGED, 0); + + sd_enable(false); + /* Access is now safe */ mutex_unlock(&sd_mtx); fat_unlock(); - sd_enable(false); - } + } break; #endif case SYS_TIMEOUT: @@ -681,16 +684,10 @@ static void sd_thread(void) { idle_notified = false; } - else + else if (!idle_notified) { - /* never let a timer wrap confuse us */ - next_yield = current_tick; - - if (!idle_notified) - { - call_storage_idle_notifys(false); - idle_notified = true; - } + call_storage_idle_notifys(false); + idle_notified = true; } break; @@ -825,7 +822,10 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start, const int drive = 0; #endif bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1)); - + int const retry_all_max = 1; + int retry_all = 0; + int const retry_data_max = 100; /* Generous, methinks */ + int retry_data; mutex_lock(&sd_mtx); #ifndef BOOTLOADER @@ -833,6 +833,21 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start, led(true); #endif + if(count < 0) /* XXX: why is it signed ? */ + { + ret = -18; + goto sd_transfer_error_no_dma; + } + + /* skip SanDisk OF */ + if (drive == INTERNAL_AS3525) + start += AMS_OF_SIZE; + + /* no need for complete retry on main, just SD */ + if (drive == SD_SLOT_AS3525) + retry_all = retry_all_max; + +sd_transfer_retry_with_reinit: if (card_info[drive].initialized <= 0) { ret = sd_init_card(drive); @@ -840,21 +855,12 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start, goto sd_transfer_error_no_dma; } - if(count < 0) /* XXX: why is it signed ? */ - { - ret = -18; - goto sd_transfer_error_no_dma; - } if((start+count) > card_info[drive].numblocks) { ret = -19; goto sd_transfer_error_no_dma; } - /* skip SanDisk OF */ - if (drive == INTERNAL_AS3525) - start += AMS_OF_SIZE; - /* CMD7 w/rca: Select card to put it in TRAN state */ if(!send_cmd(drive, SD_SELECT_CARD, card_info[drive].rca, MCI_NO_RESP, NULL)) { @@ -862,7 +868,6 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start, goto sd_transfer_error_no_dma; } - last_disk_activity = current_tick; dma_retain(); if(aligned) @@ -874,12 +879,15 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start, } const int cmd = write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK; + retry_data = retry_data_max; - do + while (1) { void *dma_buf; unsigned int transfer = count; + last_disk_activity = current_tick; + if(aligned) { dma_buf = AS3525_PHYSICAL_ADDR(buf); @@ -947,15 +955,21 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start, buf += transfer * SD_BLOCK_SIZE; start += transfer; count -= transfer; + + if (count > 0) + continue; } else /* reset controller if we had an error */ { MCI_CTRL |= (FIFO_RESET|DMA_RESET); while(MCI_CTRL & (FIFO_RESET|DMA_RESET)) ; + if (--retry_data >= 0) + continue; } - } while(retry || count); + break; + } dma_release(); @@ -967,22 +981,29 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start, goto sd_transfer_error; } + while (1) + { #ifndef BOOTLOADER - sd_enable(false); - led(false); + sd_enable(false); + led(false); #endif - mutex_unlock(&sd_mtx); - return 0; + mutex_unlock(&sd_mtx); + return ret; sd_transfer_error: - - dma_release(); + dma_release(); sd_transfer_error_no_dma: + card_info[drive].initialized = 0; - card_info[drive].initialized = 0; - mutex_unlock(&sd_mtx); - return ret; + /* .initialized might have been >= 0 but now stale if the ata sd thread + * isn't handling an insert because of USB */ + if (--retry_all >= 0) + { + ret = 0; + goto sd_transfer_retry_with_reinit; + } + } } int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int count, |