Skip to content

sigmastar: msc313e SD slot -- SDIO0 (FCIE5) host, -drive if=sd - #214

Merged
dimerr merged 2 commits into
OpenIPC:masterfrom
dimerr:sigmastar-i3-sd
Oct 27, 2026
Merged

dimerr merged 2 commits into
OpenIPC:masterfrom
dimerr:sigmastar-i3-sd

Conversation

@dimerr

@dimerr dimerr commented Oct 27, 2026

Copy link
Copy Markdown
Collaborator

sstar-fcie (hw/sd/sstar-fcie.c) is the infinity3's SDIO0, the FCIE5 on
its SDIO port that the vendor U-Boot and kernel drive the SD slot with
(drivers/mstar/sdmmc of the I3 SDK MSC3XX_SDK_V_1711291828:
hal_sdmmc_v5.c, hal_card_regs_v5.h, hal_card_platform_iNF3.c,
ms_sdmmc_ub.c), banks 0x1410-0x1411 at 0x1F282000, INT_IRQ_SDIO (SPI 51):

  • a job runs on the SD_CTL write with JOB_START, as
    Hal_SDMMC_SendCmdAndWaitProcess drives it: the command from the CMD
    FIFO to the card on the SD bus and its response back into the FIFO
    (the index, or 0x3F for R2, then MSB first), CMD_END or CMD_NORSP;
    the data by DMA between the card and DDR (MIU addresses) or, with
    DEST_R2N, 64 bytes at a time through the CIFD buffer; DATA_END. A
    write's data is a second job after the command, as the HAL issues it;
  • MIE_EVENT, SD_STS and CIFD_EVENT clear on written ones; DAT0-3 read
    high; FCIE_RST's reset states follow the reset bit inverted (what
    sstar-riu answered for the bank, now in the model);
  • the card is -drive if=sd; the machine sets sstar-i3-gpio's sd-card,
    so PM_SD_CDZ reads "card in", else the drivers find no card at once.

ADMA and the second host (FCIE, bank 0x1402, the NAND pads) are not
modelled.

Verified on msc313e with the retail camera's own U-Boot 2015.01 and its
vendor SD driver (bootcmd removed with sstar-env.py), an MBR + FAT16
64 MiB card: mmc info (4-bit, 64 MiB, "QEMU!"), fatls, fatload of a
300000-byte file with the right CRC32, mmc write of 512 blocks and of 1
block that read back identical and land in the image file; without a
card "Card Detect Fail!" at once. OpenIPC's U-Boot (openipc-sigmastar,
ms_sdmmc) lists and reads the same card. The camera dump still boots to
its shell with and without a card.

Used by OpenIPC/u-boot#86 (openipc-sigmastar), which tested with this model: SD recovery of the kernel and rootfs to flash, script.txt at boot, fatload, mmc write/read.

sstar-fcie (hw/sd/sstar-fcie.c) is the infinity3's SDIO0, the FCIE5 on
its SDIO port that the vendor U-Boot and kernel drive the SD slot with
(drivers/mstar/sdmmc of the I3 SDK MSC3XX_SDK_V_1711291828:
hal_sdmmc_v5.c, hal_card_regs_v5.h, hal_card_platform_iNF3.c,
ms_sdmmc_ub.c), banks 0x1410-0x1411 at 0x1F282000, INT_IRQ_SDIO (SPI 51):

* a job runs on the SD_CTL write with JOB_START, as
  Hal_SDMMC_SendCmdAndWaitProcess drives it: the command from the CMD
  FIFO to the card on the SD bus and its response back into the FIFO
  (the index, or 0x3F for R2, then MSB first), CMD_END or CMD_NORSP;
  the data by DMA between the card and DDR (MIU addresses) or, with
  DEST_R2N, 64 bytes at a time through the CIFD buffer; DATA_END. A
  write's data is a second job after the command, as the HAL issues it;
* MIE_EVENT, SD_STS and CIFD_EVENT clear on written ones; DAT0-3 read
  high; FCIE_RST's reset states follow the reset bit inverted (what
  sstar-riu answered for the bank, now in the model);
* the card is -drive if=sd; the machine sets sstar-i3-gpio's sd-card,
  so PM_SD_CDZ reads "card in", else the drivers find no card at once.

ADMA and the second host (FCIE, bank 0x1402, the NAND pads) are not
modelled.

Verified on msc313e with the retail camera's own U-Boot 2015.01 and its
vendor SD driver (bootcmd removed with sstar-env.py), an MBR + FAT16
64 MiB card: mmc info (4-bit, 64 MiB, "QEMU!"), fatls, fatload of a
300000-byte file with the right CRC32, mmc write of 512 blocks and of 1
block that read back identical and land in the image file; without a
card "Card Detect Fail!" at once. OpenIPC's U-Boot (openipc-sigmastar,
ms_sdmmc) lists and reads the same card. The camera dump still boots to
its shell with and without a card.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Add MSC313E SDIO0 host and SD card support

✨ Enhancement 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Model the MSC313E FCIE5 SDIO0 host so vendor firmware can access an SD card.
• Attach -drive if=sd through QEMU’s SD bus and reflect card presence through GPIO.
• Register the device in the QEMU build and document supported transfers and limitations.
Diagram

graph TD
  M["MSC313E machine"] --> F["FCIE5 host"] --> B["SD bus"] --> C["SD card"] --> I[("SD image")]
  M --> G["Card detect GPIO"]
  F --> D[("Guest DDR")]
  F --> Q["GIC SPI 51"]
Loading
High-Level Assessment

A dedicated FCIE register model backed by QEMU’s existing SD bus and card is appropriate: it preserves the vendor firmware’s MMIO interface without reimplementing SD card behavior. A generic SD host would not expose the FCIE registers or job and CIFD handshakes the firmware expects.

Files changed (4) +524 / -6

Enhancement (2) +499 / -0
sigmastar.cWire the FCIE5 host and SD card into the MSC313E machine +27/-0

Wire the FCIE5 host and SD card into the MSC313E machine

• Maps SDIO0 to its RIU banks and SPI 51, attaches an SD card from '-drive if=sd', and sets the existing GPIO card-presence property accordingly.

qemu/hw/arm/sigmastar.c

sstar-fcie.cModel the FCIE5 SDIO0 controller +472/-0

Model the FCIE5 SDIO0 controller

• Adds register and job handling for SD commands, responses, DMA and CIFD data transfers, status, and interrupts. Includes reset behavior and migration state; ADMA is explicitly unsupported.

qemu/hw/sd/sstar-fcie.c

Documentation (1) +21 / -4
sigmastar.mdDocument the SDIO0 slot and remaining limitations +21/-4

Document the SDIO0 slot and remaining limitations

• Describes the FCIE5 register-level behavior, SD image option, card detection, and supported firmware operations. Clarifies that the second host and ADMA remain unmodeled.

docs/sigmastar.md

Other (1) +4 / -2
setup.shInclude the FCIE device in QEMU setup and builds +4/-2

Include the FCIE device in QEMU setup and builds

• Copies the new source into QEMU, selects the SD Kconfig dependency, and registers the device in the Meson build.

qemu/setup.sh

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. SD transfers lack regression coverage ✓ Resolved
Description
sstar-fcie adds register-level SD command, DMA, CIFD, reset, and interrupt behavior without a
corresponding automated test. Changes to these paths can therefore regress firmware-visible SD
operations without a register-level test detecting the failure.
Code

qemu/hw/sd/sstar-fcie.c[R335-339]

+    case R_SD_CTL:
+        s->regs[reg] = val & ~CTL_JOB_START;
+        if (val & CTL_JOB_START) {
+            fcie_job(s, val);
+        }
Evidence
PR Compliance ID 6 requires applicable register-level regression tests for new device behavior. The
PR adds a new FCIE device with SD_CTL-triggered jobs and associated register behavior, but the diff
contains no test additions covering this implementation.

CLAUDE.md: Test New Machine and Device Behavior Without Flaky Getty Automation: CLAUDE.md: Test New Machine and Device Behavior Without Flaky Getty Automation: CLAUDE.md: Test New Machine and Device Behavior Without Flaky Getty Automation: CLAUDE.md: Test New Machine and Device Behavior Without Flaky Getty Automation
qemu/hw/sd/sstar-fcie.c[335-354]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new SD host implements command execution, data transfers, CIFD handshakes, and interrupt behavior, but the PR adds no applicable register-level regression coverage.
## Fix Focus Areas
- qemu/hw/sd/sstar-fcie.c[335-339]
## Recommended Fix
Add automated register-level tests for SD command completion and response handling, DMA reads and writes, CIFD transfers, W1C status behavior, reset state, card removal, and interrupt assertion/clearing. Include both card-present and no-card cases where applicable.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Short buffered reads never finish ✓ Resolved
Description
fcie_cifd_fill() consumes a read of at most 64 bytes but sets only CIFD_WBUF_FULL, leaving
MIE_DATA_END unset. When the guest acknowledges that buffer, fcie_cifd_event() sees `r2n_left ==
0` and returns before its completion path, so the transfer never reports data completion.
Code

qemu/hw/sd/sstar-fcie.c[R203-205]

+    sdbus_read_data(&s->sdbus, s->cifd[0], n);
+    s->r2n_left -= n;
+    s->regs[R_CIFD_EVENT] |= CIFD_WBUF_FULL;
Evidence
The read path fills its first chunk immediately; that fill can reduce the remaining count to zero.
The event handler then returns on a zero count before reaching its sole buffered-transfer completion
assignment.

qemu/hw/sd/sstar-fcie.c[230-237]
qemu/hw/sd/sstar-fcie.c[198-205]
qemu/hw/sd/sstar-fcie.c[269-289]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A buffered read that fits in the initial 64-byte fill exhausts `r2n_left` without ever raising `MIE_DATA_END`.
## Fix Focus Areas
- qemu/hw/sd/sstar-fcie.c[198-205]
- qemu/hw/sd/sstar-fcie.c[269-289]
## Recommended Fix
Raise data completion when the final buffered read chunk has been delivered, including when that chunk is the initial fill. Preserve the buffer-full handshake so the guest can still retrieve the data.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Large transfers can terminate the emulator ✓ Resolved
Description
fcie_data() passes the unchecked product of two guest-writable 16-bit registers directly to
g_malloc(). With a ready card and DMA mode selected, a guest can request an allocation approaching
4 GiB in one job, causing process termination if allocation fails.
Code

qemu/hw/sd/sstar-fcie.c[239]

+    buf = g_malloc(len);
Evidence
Both length registers accept guest-supplied values, their product can reach 0xfffe0001, and only
zero length is rejected before allocation. The existing SD host illustrates a bounded-chunk transfer
path.

qemu/hw/sd/sstar-fcie.c[158-161]
qemu/hw/sd/sstar-fcie.c[208-249]
qemu/hw/sd/sstar-fcie.c[349-354]
qemu/hw/sd/nvt-sdio.c[143-174]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Guest-controlled transfer dimensions can make one DMA job allocate almost 4 GiB of host memory.
## Fix Focus Areas
- qemu/hw/sd/sstar-fcie.c[158-161]
- qemu/hw/sd/sstar-fcie.c[208-249]
## Recommended Fix
Move DMA data between guest memory and the SD bus in bounded chunks instead of allocating the entire requested length. Report a transfer error if a chunk cannot be moved.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View action required (1)
4. Invalid DMA addresses can corrupt SD data ✓ Resolved
Description
fcie_data() ignores the result of dma_memory_read() before passing its buffer to
sdbus_write_data(), and likewise reports completion after a failed guest-memory write. If a guest
supplies an unmapped DMA address, a card write can receive uninitialized buffer contents, while a
card read can consume data without delivering it to guest memory.
Code

qemu/hw/sd/sstar-fcie.c[R241-243]

+        dma_memory_read(&address_space_memory, fcie_dma_addr(s), buf, len,
+                        MEMTXATTRS_UNSPECIFIED);
+        sdbus_write_data(&s->sdbus, buf, len);
Evidence
The machine maps RAM within a bounded DRAM range, but the FCIE DMA address comes directly from
writable address registers. Both DMA calls discard their status and execution proceeds to data
transfer or completion; the other SD host checks DMA results before writing to its card.

qemu/hw/sd/sstar-fcie.c[163-166]
qemu/hw/sd/sstar-fcie.c[239-249]
qemu/hw/arm/sigmastar.c[650-665]
qemu/hw/sd/nvt-sdio.c[143-174]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Failed guest-memory DMA operations are treated as successful SD transfers, allowing incorrect card writes and false read completions.
## Fix Focus Areas
- qemu/hw/sd/sstar-fcie.c[239-249]
## Recommended Fix
Check each DMA operation's result. Do not send a failed guest-memory read's buffer to the card, and report a guest-visible transfer error rather than `MIE_DATA_END` when either DMA direction fails.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can describe a rule in plain language on the Rules page and Qodo drafts it for you

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread qemu/hw/sd/sstar-fcie.c Resolved
Comment thread qemu/hw/sd/sstar-fcie.c Resolved
Comment thread qemu/hw/sd/sstar-fcie.c Resolved
Comment thread qemu/hw/sd/sstar-fcie.c Resolved
…IFD reads end; SD register tests

Three fixes to the msc313e SDIO0 model, from Qodo's review of OpenIPC#214:

* a DMA job moved its whole length (BLK_SIZE x JOB_BLK_CNT, up to
  0xFFFF x 0xFFFF) through one g_malloc'd buffer; it now goes 4 KiB at
  a time and ends in RD_TOUT/WR_TOUT when the card stops sending or
  taking data before the job's length, as the host would time out;
* a failed dma_memory_read/write was ignored: a card write got whatever
  the buffer held, a card read reported DATA_END; now the job stops
  there with the timeout bit and ERR_STS, and nothing reaches the card;
* a DEST_R2N (CIFD) read that fit the first 64-byte buffer never raised
  DATA_END; it does once the card has sent the last byte.

test-sigmastar.py gains test_msc313e_sd, register-level through qtest,
with and without -drive if=sd: card detect, CMD8/ACMD41/CMD2 (R2) and
responses, a two-block DMA read checked against the card image, a DMA
write read back, a one-buffer CIFD read, a ~4 GiB job on a one-block
read, and DMA to and from MIU 0x50000000 (nothing behind it) leaving
the card's block unchanged. Against the previous model: the CIFD and
both DMA-error checks fail, and the 4 GiB job hangs qemu; with this
change the whole test-sigmastar.py passes (219 checks). OpenIPC's
U-Boot (openipc-sigmastar, ms_sdmmc) still reads, writes and recovers
from the card.
@dimerr
dimerr merged commit 41538f0 into OpenIPC:master Oct 27, 2026
27 checks passed
@dimerr
dimerr deleted the sigmastar-i3-sd branch October 27, 2026 11:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant