From 7327d9fb6cd4d8083777819ae7b5fb22763f7d53 Mon Sep 17 00:00:00 2001 From: Ingmar Steen Date: Sun, 8 Feb 2026 00:05:31 +0100 Subject: [PATCH] Implement set block count (CMD23) for x1000 target. I have a 1TB SD card that gets filesystem corruption when writing large amounts of data when using Rockbox in USB storage mode. The card doesn't show this behaviour when using the original firmware or when using an external SD card writer. This is on an Aigo Eros Q device. Same brand 512GB card does not exhibit this behaviour. Whether this specific SD card explicitly requires CMD23 or if there's a problem with the controller's timing of auto-CMD12 in combination with this card is currently unknown, but implementing it does solve the problem. This change request implements CMD23 by first probing if SBC is supported by the SD card and then using it instead of AUTO_CMD12. Change-Id: Ib2dc8e179b0fab98ca59c348061cb7d5850884dd --- docs/CREDITS | 1 + .../target/mips/ingenic_x1000/msc-x1000.h | 1 + firmware/target/mips/ingenic_x1000/sd-x1000.c | 51 ++++++++++++++++--- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/docs/CREDITS b/docs/CREDITS index b2e8465938..6088aac312 100644 --- a/docs/CREDITS +++ b/docs/CREDITS @@ -754,6 +754,7 @@ Melissa Autumn Sho Tanimoto Nyx Guan Arin Kim +Ingmar Steen The libmad team The wavpack team diff --git a/firmware/target/mips/ingenic_x1000/msc-x1000.h b/firmware/target/mips/ingenic_x1000/msc-x1000.h index 3ebdd3adc3..119b754358 100644 --- a/firmware/target/mips/ingenic_x1000/msc-x1000.h +++ b/firmware/target/mips/ingenic_x1000/msc-x1000.h @@ -48,6 +48,7 @@ #define MSC_DF_READY (1 << 1) #define MSC_DF_HCS_CARD (1 << 2) #define MSC_DF_V2_CARD (1 << 3) +#define MSC_DF_HAS_SBC (1 << 4) /* Request status codes */ #define MSC_REQ_SUCCESS 0 diff --git a/firmware/target/mips/ingenic_x1000/sd-x1000.c b/firmware/target/mips/ingenic_x1000/sd-x1000.c index c1aec59aa3..f7313cebfa 100644 --- a/firmware/target/mips/ingenic_x1000/sd-x1000.c +++ b/firmware/target/mips/ingenic_x1000/sd-x1000.c @@ -19,6 +19,7 @@ * ****************************************************************************/ +#include "system.h" #include "storage.h" #include "sdmmc.h" #include "sd.h" @@ -32,6 +33,25 @@ static msc_drv* sd_to_msc[MSC_COUNT]; static long _sd_last_disk_activity = 0; +static void sd_probe_set_block_count(msc_drv* d) +{ + uint8_t scr[CACHEALIGN_SIZE] CACHEALIGN_ATTR; + msc_req req = {0}; + req.command = SD_SEND_SCR; + req.resptype = MSC_RESP_R1; + req.flags = MSC_RF_DATA; + req.data = scr; + req.nr_blocks = 1; + req.block_len = 8; + + if(msc_app_cmd_exec(d, &req) == MSC_REQ_SUCCESS) { + if(scr[3] & 0x02) + d->driver_flags |= MSC_DF_HAS_SBC; + else + d->driver_flags &= ~MSC_DF_HAS_SBC; + } +} + static int sd_init_card(msc_drv* d) { int s; @@ -45,6 +65,7 @@ static int sd_init_card(msc_drv* d) if(s = msc_cmd_set_clr_card_detect(d, 0)) return -170 - s; if(s = msc_cmd_set_bus_width(d, 4)) return -180 - s; if(s = msc_cmd_switch_freq(d)) return -190 - s; + sd_probe_set_block_count(d); d->driver_flags |= MSC_DF_READY; d->cardinfo.initialized = 1; return 0; @@ -92,19 +113,35 @@ static int sd_transfer(msc_drv* d, bool write, if(status = msc_cmd_set_block_len(d, SD_BLOCK_SIZE)) goto _exit; - /* TODO - look into using CMD23 to improve transfer performance. - * This specifies the number of blocks ahead of time, instead of - * relying on CMD12 to stop transmission. CMD12 is still needed - * in the event of errors though. - */ + bool use_sbc = false; + if(xfer_count > 1 && (d->driver_flags & MSC_DF_HAS_SBC)) { + msc_req sbc_req = {0}; + sbc_req.command = 23; /* CMD23: SET_BLOCK_COUNT (SBC) */ + sbc_req.argument = xfer_count; + sbc_req.resptype = MSC_RESP_R1; + status = msc_cmd_exec(d, &sbc_req); + if(status == MSC_REQ_SUCCESS) { + use_sbc = true; + } else if(status == MSC_REQ_CARD_ERR && + (sbc_req.response[0] & SD_R1_ILLEGAL_COMMAND)) { + d->driver_flags &= ~MSC_DF_HAS_SBC; + } else { + goto _exit; + } + } + msc_req req = {0}; req.data = buf; req.nr_blocks = xfer_count; req.block_len = SD_BLOCK_SIZE; req.resptype = MSC_RESP_R1; req.flags = MSC_RF_DATA; - if(xfer_count > 1) - req.flags |= MSC_RF_AUTO_CMD12; + if(xfer_count > 1) { + if(use_sbc) + req.flags |= MSC_RF_ERR_CMD12; + else + req.flags |= MSC_RF_AUTO_CMD12; + } if(write) { req.command = xfer_count == 1 ? SD_WRITE_BLOCK : SD_WRITE_MULTIPLE_BLOCK;