summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--firmware/target/arm/as3525/sd-as3525v2.c105
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,