Revisiting this.
At the suggestion of Ant123, I've ran ML under the Xilinx version of QEMU, which also emulates UHS. This revealed the missing bits from my previous patch: on 5D3, although it was printing a message about 96MHz, the card interface was set up in the same way as for... 24 MHz (which explains
the previous benchmark results).
Took the missing register configurations from 700D and...


Now the details.
Xilinx QEMU includes UHS emulation (along with some other nice stuff) and is based on QEMU 2.6.x (at the time of writing). Currently we have patches for QEMU 2.5.0 and 2.9.0, and for the Xilinx version, it will be something in-between. If there is interest, I can commit the patches.
First, I've ran 5D3 1.2.3 from the dm-spy-experiments branch on both the camera and QEMU 2.5.0.
Result.
The problem:
CSMgrTask:ff6bdb7c:23:05: Set Hi-Speed Mode( 48MHz ) ; real hardware
[ CSMgrTask:ff6bdb9c ] (23:05) Set Normal-Speed Mode( 24MHz ) ; QEMU 2.5.0
That's where the Xilinx QEMU comes in.
Result: after a minor patch to the SCR structure (first field - SpecVersion - changed from 0 to 1), both the log from camera and Xilinx QEMU now have:
CSMgrTask:ff6bdb44:23:05: SD_GetAccessMode=3
CSMgrTask:ff6bdb7c:23:05: Set Hi-Speed Mode( 48MHz )
Also, besides a minor difference in handling CMD1, and the card capacity, the emulation matches the reality pretty well. There's even some nice debug info if you uncomment DEBUG_SD in hw/sd/sd.c and use the "-d sd" switch on the command line.
Result - in particular, these lines:
CSMgrTask:ff6b8fec:23:01: sdSetFunction( 16776961 ) Start
CSMgrTask:000aea50:00:00: *** sd_setup_mode(0x2), from ff484738
sd: CMD16 0x00000040 state 4
sd: Response: 00 00 09 00 state 4
CSMgrTask:000aea50:00:00: *** sd_setup_mode(0x2), from ff6b8300
sd: CMD6 0x80ffff01 state 4
sd: Function default selected (fn grp 2)
sd: Function high-speed/SDR25 selected (fn grp 1)
sd: Response: 00 00 09 00 state 5
sd: CMD13 0x45670000 state 4
sd: Response: 00 00 09 00 state 4
sd: CMD16 0x00000200 state 4
sd: Response: 00 00 09 00 state 4
CSMgrTask:ff6b91c8:23:01: sdSetFunction( 16776961 ) End
Now we can analyze how the SD initialization code configures the hardware (MMIO registers). This is as easy as specifying "-d io" in QEMU's command-line.
Result.
At this point I've applied the
old patch and tried to figure out whether there's any obvious trouble.
Result:
Without hack:
CSMgrTask:ff6bdb7c:23:05: Set Hi-Speed Mode( 48MHz )
CSMgrTask:000aeed0:00:00: *** sd_set_mode(0x1, 0x3), from ff6bdb88
(some registers)
CSMgrTask:000aeed0:00:00: *** sd_setup_mode(0x3), from ff484738
(some more registers)
CSMgrTask:ff6bc87c:23:01: sdReadBlk: st=0, num=1, buf=0x40983808
With hack:
CSMgrTask:ff6bdb5c:23:05: Set Hi-Speed Mode( 96MHz )
CSMgrTask:000aeef0:00:00: *** sd_set_mode(0x1, 0x4), from ff6bdb88
(some registers)
CSMgrTask:000aeef0:00:00: *** sd_setup_mode(0x4), from ff484738
(a few more registers, but many of them missing!)
CSMgrTask:ff6bc87c:23:01: sdReadBlk: st=0, num=1, buf=0x409837bc
In other words, sd_setup_mode(4) appears to skip some hardware configuration it might be supposed to perform. With other arguments, it sets a bunch of registers, and the argument appears to be related to SD clock speed (3 = 48MHz, 2 = 24MHz, 4 = 96MHz).
Let's see what it does on 700D.
Result (also with a
zoomed-in view).
Notice some additional registers on 700D (highlighted in red on the zoomed-in view). What's up with them?
The 0xC04004xx range is never set on 5D3, so these registers are probably specific to 700D hardware. Same for 0xC040063x and 0xC040064x. I didn't touch them.
The remaining registers, 0xC04006[012]x, are also set on 5D3, at other speed modes. In these other modes, their values are the same on 700D. You can see them here:
sd_setup_mode(2),
sd_setup_mode(4).
My hypothesis was that 5D3's SD controller is UHS-capable, but for some unknown reason (could be even problems during the initial tests), Canon decided not to include it in the firmware. As a result, some of the UHS initialization code (hopefully a small part) was optimized out.
So I've tried to take the missing register configurations from 700D.
Therefore, the patch for 5D3 1.2.3 becomes:
/* in dm-spy.c, right before dm_spy_extra_install() */
patch_instruction(0xff48446c, 0xe3a00000, 0xe3a00001, "SD 1.8V");
/* in dm-spy-extra.c */
static void sd_setup_mode_log(uint32_t* regs, uint32_t* stack, uint32_t pc)
{
/* log the original call as usual */
generic_log(regs, stack, pc);
if (regs[0] == 4)
{
MEM(0xC0400600) = 3;
MEM(0xC0400610) = 4;
MEM(0xC0400614) = 0x1D000301;
MEM(0xC0400618) = 0;
MEM(0xC0400624) = 0x201;
MEM(0xC0400628) = 0x201;
MEM(0xC040061C) = 0x100;
MEM(0xC0400620) = 4;
MEM(0xC0400604) = 3;
}
}
/* under CONFIG_5D3_123 */
{ 0xFF4844A0, "sd_setup_mode", 1, sd_setup_mode_log },
If you decide to try it, make sure you don't have any important data on your card. Otherwise, you will be playing Russian Roulette with your data (just like with
my other SD patch).
Does this apply to DIGIC 4 cameras?I'm afraid not - the hardware configuration of these cameras is different (and a lot simpler). You now know where to look, so you can play with it, attempt to change the clock speed and report your findings.
Can the clock speed be pushed even further?I have no idea. Feel free to play with these registers, run the benchmarks and report.
Can this be included in a module, to be used on a regular ML build?That's hard, because the hack must be applied before the SD card gets initialized by Canon firmware (in other words, before loading any module, and also before loading the config file). So, even if we include it in ML core, it will be hard to create an option for it.
At the moment, the easiest way to try it would be a custom build. Probably best to start from the crop_rec_4k branch, as the backend support is there, and there is little reason to try this hack outside that branch.
It might be possible to switch the SD to a higher speed on the fly. Didn't investigate this approach.
How's this useful in practice?Other than raw video recording on both CF and SD at the same time (aka card spanning), it's probably not very useful.
What's the maximum total speed (CF+SD)?Load the benchmarks module (bench.mo) to find out.
How can I get similar results in QEMU?Take a look at
this post. In a nutshell, it's the dm-spy-experiments branch compiled with CONFIG_DEBUG_INTERCEPT_STARTUP=y for the camera, and additionally with CONFIG_QEMU=y for running it under the emulator. These two will give logs that can be directly compared, and with the logging options from QEMU, you can get additional details. Then, look for CSMgrTask in the logs, compare them and try to understand what it does. Also refer to SD docs (summarized nicely by nikfreak earlier in this thread) to understand the initialization protocol. That's it. If you get stuck, just ask (here or on IRC).
If there is interest, I can commit the patch for Xilinx QEMU and write a walkthrough
similar to this one.
Please note I no longer have the UHS card to do more tests (it wasn't mine), so from now on, what will happen with this hack is entirely up to you.