Index: firmware/target/arm/ata-sd-pp.c =================================================================== --- firmware/target/arm/ata-sd-pp.c (Revision 19889) +++ firmware/target/arm/ata-sd-pp.c (Arbeitskopie) @@ -54,6 +54,7 @@ #define DATA_REG (*(volatile unsigned int *)(0x70008280)) /* STATUS_REG bits */ +#define DATA_TRAN_DONE (1 << 11) #define DATA_DONE (1 << 12) #define CMD_DONE (1 << 13) #define ERROR_BITS (0x3f) @@ -89,6 +90,8 @@ #define EC_COMMAND 19 #define NUM_EC 20 + +static int wait_loop; /* for compatibility */ static long last_disk_activity = -1; @@ -423,15 +426,46 @@ /* Writes have to be kept slow for now */ static inline void copy_write_sectors(const unsigned char** buf) { - int cnt = FIFO_LEN; + int cnt = FIFO_LEN - 1; unsigned t; + long time; - do + time = USEC_TIMER + 3; + if (((intptr_t)*buf & 3) == 0) { + asm volatile ( + "ldmia %[buf]!, { r3, r5, r7, r9 } \r\n" + "mov r4, r3, lsr #16 \r\n" + "mov r6, r5, lsr #16 \r\n" + "mov r8, r7, lsr #16 \r\n" + "mov r10, r9, lsr #16 \r\n" + "stmia %[data], { r3-r10 } \r\n" + "ldmia %[buf]!, { r3, r5, r7, r9 } \r\n" + "mov r4, r3, lsr #16 \r\n" + "mov r6, r5, lsr #16 \r\n" + "mov r8, r7, lsr #16 \r\n" + "mov %[t], r9, lsr #16 \r\n" + "stmia %[data], { r3-r9 } \r\n" + : [buf]"+&r"(*buf), [t]"=&r"(t) + : [data]"r"(&DATA_REG) + : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); + } + else + { + 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 */ + } + /* Don't write the last word before at least 3 usec have elapsed since FIFO_EMPTY */ + /* This prevents the 'two bytes inserted' bug. */ + while (!TIME_AFTER(USEC_TIMER, time)); + DATA_REG = t; } static int sd_select_bank(unsigned char bank) @@ -920,12 +954,12 @@ if(currcard->ocr & (1<<30) ) { /* SDHC */ - ret = sd_command(SD_WRITE_MULTIPLE_BLOCK, start, NULL, 0x1c2d); + ret = sd_command(SD_WRITE_MULTIPLE_BLOCK, start, NULL, 0xd); } else #endif { - ret = sd_command(SD_WRITE_MULTIPLE_BLOCK, start*BLOCK_SIZE, NULL, 0x1c2d); + ret = sd_command(SD_WRITE_MULTIPLE_BLOCK, start*BLOCK_SIZE, NULL, 0xd); } if (ret < 0) goto sd_write_error; @@ -940,18 +974,24 @@ SD_STATE_REG = SD_PRG; } - udelay(2); /* needed here (loop is too fast :-) */ + { int cnt = wait_loop; + asm volatile ( + "1: \n" + "subs %[cnt], %[cnt], #1 \n" + "bgt 1b \n" + : [cnt]"+&r"(cnt) ); + } + + copy_write_sectors(&buf); /* Copy one chunk of 16 words */ + /* TODO: Switch bank if necessary */ + /* Wait for the FIFO to empty */ - if (sd_poll_status(FIFO_EMPTY, 0x80000)) + if(sd_poll_status(FIFO_EMPTY, 0x80000) == 0) { - copy_write_sectors(&buf); /* Copy one chunk of 16 words */ - /* TODO: Switch bank if necessary */ - continue; + ret = -EC_FIFO_WR_EMPTY; + goto sd_write_error; } - - ret = -EC_FIFO_WR_EMPTY; - goto sd_write_error; } last_disk_activity = current_tick; Index: firmware/usbstack/usb_storage.c =================================================================== --- firmware/usbstack/usb_storage.c (Revision 19889) +++ firmware/usbstack/usb_storage.c (Arbeitskopie) @@ -39,9 +39,12 @@ * by not overlapping storage_write_sector() with USB transfers. This does reduce * write performance, so we only do it for the affected DAPs */ -#if (CONFIG_STORAGE & STORAGE_SD) + +#if (CONFIG_STORAGE & STORAGE_SD) && !defined(CPU_PP) #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.