Implement set block count (CMD23) for x1000 target.

rockbox-gerrit-noreply--- via rockbox-cvs <[email protected]>
Newsgroups gmane.comp.systems.archos.rockbox.cvs
Message-ID <[email protected]>
commit 7327d9fb6cd4d8083777819ae7b5fb22763f7d53
Author: Ingmar Steen <[email protected]>
Date:   Sun Feb 8 00:05:31 2026 +0100

    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

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;
-- 
rockbox-cvs mailing list
[email protected]
https://lists.haxx.se/mailman/listinfo/rockbox-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.