Index: debug-as3525.c
===================================================================
--- debug-as3525.c (revision 27164)
+++ debug-as3525.c (working copy)
@@ -268,6 +268,30 @@
{
while(1)
{
+ int i;
+ extern int sd_cmds_submitted[NUM_VOLUMES];
+ extern int sd_cmds_errors[NUM_VOLUMES];
+ extern int sd_transfers[NUM_VOLUMES];
+ extern int sd_transfer_errors[NUM_VOLUMES];
+ lcd_clear_display();
+ line = 0;
+ lcd_puts(0, line++, "[SD error stats]");
+ for (i=0; i<NUM_VOLUMES; i++) {
+ lcd_putsf(0, line++, "Drive %d errors:", i);
+ lcd_putsf(0, line++, "cmd %d of %d",
+ sd_cmds_errors[i], sd_cmds_submitted[i]);
+ lcd_putsf(0, line++, "r/w %d of %d",
+ sd_transfer_errors[i], sd_transfers[i]);
+ }
+ lcd_update();
+ int btn = button_get_w_tmo(HZ/10);
+ if(btn == (DEBUG_CANCEL|BUTTON_REL))
+ goto end;
+ else if(btn == (BUTTON_DOWN|BUTTON_REL))
+ break;
+ }
+ while(1)
+ {
#ifdef SANSA_C200V2
lcd_clear_display();
line = 0;
Index: sd-as3525.c
===================================================================
--- sd-as3525.c (revision 27165)
+++ sd-as3525.c (working copy)
@@ -126,6 +126,11 @@
static struct event_queue sd_queue;
bool sd_enabled = false;
+int sd_cmds_submitted[NUM_VOLUMES];
+int sd_cmds_errors[NUM_VOLUMES];
+int sd_transfers[NUM_VOLUMES];
+int sd_transfer_errors[NUM_VOLUMES];
+
#if defined(HAVE_MULTIDRIVE)
static bool hs_card = false;
#define EXT_SD_BITS (1<<2)
@@ -174,7 +179,7 @@
{
static struct timeout sd1_oneshot;
if (GPIOA_MIS & EXT_SD_BITS)
- timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0);
+ timeout_register(&sd1_oneshot, sd1_oneshot_callback, (9*HZ/10), 0);
/* acknowledge interrupt */
GPIOA_IC = EXT_SD_BITS;
}
@@ -207,6 +212,8 @@
{
int status;
+ sd_cmds_submitted[drive]++;
+
unsigned cmd_retries = 6;
while(cmd_retries--)
{
@@ -236,8 +243,10 @@
{
response[0] = MCI_RESP0(drive); /* Always prepare short response */
- if(status & MCI_RESPONSE_ERROR) /* timeout or crc failure */
+ if(status & MCI_RESPONSE_ERROR) {/* timeout or crc failure */
+ sd_cmds_errors[drive]++;
continue;
+ }
if(status & MCI_CMD_RESP_END) /* Response passed CRC check */
{
@@ -257,6 +266,32 @@
return false;
}
+static void sd_set_widebus_mode(IF_MD2(int drive,) int on) {
+#ifndef HAVE_MULTIDRIVE
+ const int drive = 0;
+#endif
+ long response = 0;
+ int ret;
+ if((ret = sd_wait_for_tran_state(drive)) < 0) {
+ int ret2 = send_cmd(drive, SD_SEND_STATUS, card_info[drive].rca,
+ MCI_RESP, &response);
+ panicf("sd_set_widebus(%d): tran: %d %d %lx %lx", on, ret, ret2, response, MCI_STATUS(drive));
+ }
+ /* CMD55 */ /* Response is requested due to timing issue */
+ if(!send_cmd(drive, SD_APP_CMD, card_info[drive].rca, MCI_RESP, &response))
+ panicf("sd_set_widebus(%d): app_cmd", on);
+ /* ACMD6 */
+ if(!send_cmd(drive, SD_SET_BUS_WIDTH, on ? 2 : 0, MCI_RESP, &response))
+ panicf("sd_set_widebus(%d): set_bus_width", on);
+ /* Now that card is widebus make controller aware */
+ if (on) {
+ MCI_CLOCK(drive) |= MCI_CLOCK_WIDEBUS;
+ } else {
+ MCI_CLOCK(drive) &= ~MCI_CLOCK_WIDEBUS;
+ }
+}
+
+
#define MCI_FULLSPEED (MCI_CLOCK_ENABLE | MCI_CLOCK_BYPASS) /* MCLK */
#define MCI_HALFSPEED (MCI_CLOCK_ENABLE) /* MCLK/2 */
#define MCI_QUARTERSPEED (MCI_CLOCK_ENABLE | 1) /* MCLK/4 */
@@ -362,24 +397,17 @@
if(!send_cmd(drive, SD_SELECT_CARD, card_info[drive].rca, MCI_RESP, &response))
return -10;
- /* Switch to to 4 bit widebus mode */
- if(sd_wait_for_tran_state(drive) < 0)
- return -11;
+ /* Disable card detect pullup, we don't need it */
/* CMD55 */ /* Response is requested due to timing issue */
if(!send_cmd(drive, SD_APP_CMD, card_info[drive].rca, MCI_RESP, &response))
return -14;
/* ACMD42 */
if(!send_cmd(drive, SD_SET_CLR_CARD_DETECT, 0, MCI_RESP, &response))
return -15;
- /* CMD55 */ /* Response is requested due to timing issue */
- if(!send_cmd(drive, SD_APP_CMD, card_info[drive].rca, MCI_RESP, &response))
- return -12;
- /* ACMD6 */
- if(!send_cmd(drive, SD_SET_BUS_WIDTH, 2, MCI_RESP, &response))
- return -13;
- /* Now that card is widebus make controller aware */
- MCI_CLOCK(drive) |= MCI_CLOCK_WIDEBUS;
+ /* Switch to to 4 bit widebus mode */
+ sd_set_widebus_mode(IF_MD2(drive,) 1);
+
/*
* enable bank switching
* without issuing this command, we only have access to 1/4 of the blocks
@@ -596,15 +624,17 @@
while (1)
{
- if(!send_cmd(drive, SD_SEND_STATUS, card_info[drive].rca, MCI_RESP,
- &response))
- return -1;
+ int ret = send_cmd(drive, SD_SEND_STATUS, card_info[drive].rca,
+ MCI_RESP, &response);
- if (((response >> 9) & 0xf) == SD_TRAN)
+ if (ret && ((response >> 9) & 0xf) == SD_TRAN)
return 0;
- if(TIME_AFTER(current_tick, timeout))
+ if(TIME_AFTER(current_tick, timeout)) {
+ if (!ret)
+ return -1;
return -2;
+ }
if (TIME_AFTER(current_tick, next_yield))
{
@@ -690,6 +720,7 @@
bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1));
mutex_lock(&sd_mtx);
+ sd_transfers[drive]++;
sd_enable(true);
led(true);
@@ -724,7 +755,7 @@
if(write)
clean_dcache_range(buf, count * SECTOR_SIZE);
else
- dump_dcache_range(buf, count * SECTOR_SIZE);
+ invalidate_dcache();
}
while(count)
@@ -853,9 +884,12 @@
count -= transfer;
loops = 0; /* reset errors counter */
}
- else if(loops++ > PL180_MAX_TRANSFER_ERRORS)
+ else {
+ sd_transfer_errors[drive]++;
+ if(loops++ > PL180_MAX_TRANSFER_ERRORS)
panicf("SD Xfer %s err:0x%x Disk%d", (write? "write": "read"),
transfer_error[drive], drive);
+ }
}
sd_transfer_error:
@@ -874,10 +908,35 @@
return ret;
}
+#define VERIFY_READ 1
+
int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int count,
void* buf)
{
- return sd_transfer_sectors(IF_MD2(drive,) start, count, buf, false);
+ int ret;
+
+ ret = sd_transfer_sectors(IF_MD2(drive,) start, count, buf, false);
+
+#ifdef VERIFY_READ
+ if (ret) /* read failed, no point in verifying? */
+ return ret;
+
+ while (count) {
+ int transfer = count;
+ if(transfer > UNALIGNED_NUM_SECTORS)
+ transfer = UNALIGNED_NUM_SECTORS;
+
+ sd_transfer_sectors(IF_MD2(drive,) start, transfer, aligned_buffer, false);
+ if (memcmp(buf, aligned_buffer, transfer * 512) != 0)
+ panicf("sd: read verify failed: sec=%ld n=%d!", start, transfer);
+
+ buf += transfer * 512;
+ count -= transfer;
+ start += transfer;
+ }
+
+#endif
+ return ret;
}
int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
@@ -908,7 +967,7 @@
if (memcmp(buf, aligned_buffer, transfer * 512) != 0) {
/* try the write again in the hope to repair the damage */
sd_transfer_sectors(IF_MD2(drive,) saved_start, saved_count, saved_buf, true);
- panicf("sd: verify failed: sec=%ld n=%d!", start, transfer);
+ panicf("sd: write verify failed: sec=%ld n=%d!", start, transfer);
}
buf += transfer * 512;