summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorFrank Gevaerts <frank@gevaerts.be>2008-07-09 19:56:09 +0000
committerFrank Gevaerts <frank@gevaerts.be>2008-07-09 19:56:09 +0000
commit3f3bb75d6a3e919460d369ba95e1518f622e18ea (patch)
tree7c25f5feb1b592b25c578ccd69fe1c84379b2a1c /firmware
parent1acd5355873b77ff0422cdad4fb6b549652265ec (diff)
downloadrockbox-3f3bb75d6a3e919460d369ba95e1518f622e18ea.tar.gz
rockbox-3f3bb75d6a3e919460d369ba95e1518f622e18ea.zip
Don't do overlapping USB transactions and SD writes. This seems to avoid FS#8663
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17997 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/usbstack/usb_storage.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
index 3ee7acfab5..f233549a2b 100644
--- a/firmware/usbstack/usb_storage.c
+++ b/firmware/usbstack/usb_storage.c
@@ -34,6 +34,14 @@
#ifdef USB_STORAGE
+/* The SD card driver on Sansa c200 and e200 can cause write corruption,
+ * often triggered by simultaneous USB activity. This can be largely avoided
+ * by not overlapping ata_write_sector() with USB transfers. This does reduce
+ * write performance, so we only do it for the affected DAPs
+ */
+#if defined(SANSA_C200) || defined(SANSA_E200)
+#define SERIALIZE_WRITES
+#endif
/* Enable the following define to export only the SD card slot. This
* is useful for USBCV MSC tests, as those are destructive.
* This won't work right if the device doesn't have a card slot.
@@ -408,12 +416,15 @@ void usb_storage_transfer_complete(int ep,bool in,int status,int length)
(BUFFER_SIZE/SECTOR_SIZE);
unsigned int next_count = cur_cmd.count -
MIN(cur_cmd.count,BUFFER_SIZE/SECTOR_SIZE);
+ int next_select = !cur_cmd.data_select;
+#ifndef SERIALIZE_WRITES
if(next_count!=0) {
/* Ask the host to send more, to the other buffer */
- receive_block_data(cur_cmd.data[!cur_cmd.data_select],
+ receive_block_data(cur_cmd.data[next_select],
MIN(BUFFER_SIZE,next_count*SECTOR_SIZE));
}
+#endif
/* Now write the data that just came in, while the host is
sending the next bit */
@@ -429,6 +440,13 @@ void usb_storage_transfer_complete(int ep,bool in,int status,int length)
cur_sense_data.ascq=0;
break;
}
+#ifdef SERIALIZE_WRITES
+ if(next_count!=0) {
+ /* Ask the host to send more, to the other buffer */
+ receive_block_data(cur_cmd.data[next_select],
+ MIN(BUFFER_SIZE,next_count*SECTOR_SIZE));
+ }
+#endif
if(next_count==0) {
send_csw(UMS_STATUS_GOOD);