Index: firmware/target/arm/ata-sd-pp.c =================================================================== --- firmware/target/arm/ata-sd-pp.c (Revision 17715) +++ firmware/target/arm/ata-sd-pp.c (Arbeitskopie) @@ -464,18 +464,49 @@ ); } -/* Writes have to be kept slow for now */ static inline void copy_write_sectors(const unsigned char** buf) { + if ( (((intptr_t)*buf & 3 ) == 0) ) + { + asm volatile ( + "ldmia %[buf]!, { r2, r4, r6, r8 } \r\n" + "mov r3, r2, lsr #16 \r\n" + "mov r5, r4, lsr #16 \r\n" + "mov r7, r6, lsr #16 \r\n" + "mov r9, r8, lsr #16 \r\n" + "stmia %[data], { r2-r9 } \r\n" + "ldmia %[buf]!, { r2, r4, r6, r8 } \r\n" + "mov r3, r2, lsr #16 \r\n" + "mov r5, r4, lsr #16 \r\n" + "mov r7, r6, lsr #16 \r\n" + "mov r9, r8, lsr #16 \r\n" + "stmia %[data], { r2-r9 } \r\n" + : [buf]"+&r"(*buf) + : [data]"r"(&DATA_REG) + : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); + } + else + { + /* Do we ever have an unaligned buffer? */ + +#ifdef SANSA_E200 + /* On the card slot we need another udelay here to prevent the 'two bytes inserted' bug. */ + /* But on the internal flash, there must be no udelay! */ + if (currcard == &card_info[1]) + udelay(2); +#endif + int cnt = FIFO_LEN; unsigned t; do - { - t = *(*buf)++; - t |= *(*buf)++ << 8; - DATA_REG = t; - } while (--cnt > 0); /* tail loop is faster */ + { + t = *(*buf)++; + t |= *(*buf)++ << 8; + DATA_REG = t; + } while (--cnt > 0); /* tail loop is faster */ + } } static int sd_select_bank(unsigned char bank) @@ -983,11 +1014,14 @@ SD_STATE_REG = PRG; } - udelay(2); /* needed here (loop is too fast :-) */ - /* Wait for the FIFO to empty */ if (sd_poll_status(FIFO_EMPTY, 0x80000)) { + + udelay(3); /* Needed on e200. Maybe has to be adjusted for c200 and GoGear. */ + /* Too short delay will cause lockup or corruption, */ + /* too long delay will raise the 'two bytes inserted' bug. */ + copy_write_sectors(&buf); /* Copy one chunk of 16 words */ /* TODO: Switch bank if necessary */ continue;