[PATCH v42 06/98] hw/sd/sdcard: Do not store vendor data on block drive (CMD56)

2024-06-28 Thread Philippe Mathieu-Daudé
"General command" (GEN_CMD, CMD56) is described as:

  GEN_CMD is the same as the single block read or write
  commands (CMD24 or CMD17). The difference is that [...]
  the data block is not a memory payload data but has a
  vendor specific format and meaning.

Thus this block must not be stored overwriting data block
on underlying storage drive. Keep it in a dedicated
'vendor_data[]' array.

Signed-off-by: Philippe Mathieu-Daudé 
Tested-by: Cédric Le Goater 
---
RFC: Is it safe to reuse VMSTATE_UNUSED_V() (which happens
to be the same size)?

Cc: Peter Xu 
Cc: Fabiano Rosas 
---
 hw/sd/sd.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 464576751a..1f3eea6e84 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -142,6 +142,8 @@ struct SDState {
 uint64_t data_start;
 uint32_t data_offset;
 uint8_t data[512];
+uint8_t vendor_data[512];
+
 qemu_irq readonly_cb;
 qemu_irq inserted_cb;
 QEMUTimer *ocr_power_timer;
@@ -656,6 +658,7 @@ static void sd_reset(DeviceState *dev)
 sd->wp_switch = sd->blk ? !blk_is_writable(sd->blk) : false;
 sd->wp_group_bits = sect;
 sd->wp_group_bmap = bitmap_new(sd->wp_group_bits);
+memset(sd->vendor_data, 0xec, sizeof(sd->vendor_data));
 memset(sd->function_group, 0, sizeof(sd->function_group));
 sd->erase_start = INVALID_ADDRESS;
 sd->erase_end = INVALID_ADDRESS;
@@ -771,7 +774,7 @@ static const VMStateDescription sd_vmstate = {
 VMSTATE_UINT64(data_start, SDState),
 VMSTATE_UINT32(data_offset, SDState),
 VMSTATE_UINT8_ARRAY(data, SDState, 512),
-VMSTATE_UNUSED_V(1, 512),
+VMSTATE_UINT8_ARRAY(vendor_data, SDState, 512),
 VMSTATE_BOOL(enable, SDState),
 VMSTATE_END_OF_LIST()
 },
@@ -2029,9 +2032,8 @@ void sd_write_byte(SDState *sd, uint8_t value)
 break;
 
 case 56:  /* CMD56:  GEN_CMD */
-sd->data[sd->data_offset ++] = value;
-if (sd->data_offset >= sd->blk_len) {
-APP_WRITE_BLOCK(sd->data_start, sd->data_offset);
+sd->vendor_data[sd->data_offset ++] = value;
+if (sd->data_offset >= sizeof(sd->vendor_data)) {
 sd->state = sd_transfer_state;
 }
 break;
@@ -2165,12 +2167,11 @@ uint8_t sd_read_byte(SDState *sd)
 break;
 
 case 56:  /* CMD56:  GEN_CMD */
-if (sd->data_offset == 0)
-APP_READ_BLOCK(sd->data_start, sd->blk_len);
-ret = sd->data[sd->data_offset ++];
+ret = sd->vendor_data[sd->data_offset ++];
 
-if (sd->data_offset >= sd->blk_len)
+if (sd->data_offset >= sizeof(sd->vendor_data)) {
 sd->state = sd_transfer_state;
+}
 break;
 
 default:
-- 
2.41.0




[PATCH v42 03/98] hw/sd/sdcard: Track last command used to help logging

2024-06-28 Thread Philippe Mathieu-Daudé
The command is selected on the I/O lines, and further
processing might be done on the DAT lines via the
sd_read_byte() and sd_write_byte() handlers. Since
these methods can't distinct between normal and APP
commands, keep the name of the current command in
the SDState and use it in the DAT handlers. This
fixes a bug that all normal commands were displayed
as APP commands.

Fixes: 2ed61fb57b ("sdcard: Display command name when tracing CMD/ACMD")
Signed-off-by: Philippe Mathieu-Daudé 
Tested-by: Cédric Le Goater 
---
 hw/sd/sd.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index d0a1d5db18..bc87807793 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -133,6 +133,7 @@ struct SDState {
 uint32_t pwd_len;
 uint8_t function_group[6];
 uint8_t current_cmd;
+const char *last_cmd_name;
 /* True if we will handle the next command as an ACMD. Note that this does
  * *not* track the APP_CMD status bit!
  */
@@ -1154,12 +1155,13 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 uint16_t rca;
 uint64_t addr;
 
+sd->last_cmd_name = sd_cmd_name(req.cmd);
 /* CMD55 precedes an ACMD, so we are not interested in tracing it.
  * However there is no ACMD55, so we want to trace this particular case.
  */
 if (req.cmd != 55 || sd->expecting_acmd) {
 trace_sdcard_normal_command(sd_proto(sd)->name,
-sd_cmd_name(req.cmd), req.cmd,
+sd->last_cmd_name, req.cmd,
 req.arg, sd_state_name(sd->state));
 }
 
@@ -1620,7 +1622,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 static sd_rsp_type_t sd_app_command(SDState *sd,
 SDRequest req)
 {
-trace_sdcard_app_command(sd_proto(sd)->name, sd_acmd_name(req.cmd),
+sd->last_cmd_name = sd_acmd_name(req.cmd);
+trace_sdcard_app_command(sd_proto(sd)->name, sd->last_cmd_name,
  req.cmd, req.arg, sd_state_name(sd->state));
 sd->card_status |= APP_CMD;
 
@@ -1913,7 +1916,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
 return;
 
 trace_sdcard_write_data(sd_proto(sd)->name,
-sd_acmd_name(sd->current_cmd),
+sd->last_cmd_name,
 sd->current_cmd, value);
 switch (sd->current_cmd) {
 case 24:  /* CMD24:  WRITE_SINGLE_BLOCK */
@@ -2069,7 +2072,7 @@ uint8_t sd_read_byte(SDState *sd)
 io_len = (sd->ocr & (1 << 30)) ? 512 : sd->blk_len;
 
 trace_sdcard_read_data(sd_proto(sd)->name,
-   sd_acmd_name(sd->current_cmd),
+   sd->last_cmd_name,
sd->current_cmd, io_len);
 switch (sd->current_cmd) {
 case 6:  /* CMD6:   SWITCH_FUNCTION */
@@ -2214,6 +2217,7 @@ static void sd_instance_init(Object *obj)
 {
 SDState *sd = SD_CARD(obj);
 
+sd->last_cmd_name = "UNSET";
 sd->enable = true;
 sd->ocr_power_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sd_ocr_powerup, sd);
 }
-- 
2.41.0




[PATCH v42 07/98] hw/sd/sdcard: Send WRITE_PROT bits MSB first (CMD30)

2024-06-28 Thread Philippe Mathieu-Daudé
Per sections 3.6.1 (SD Bus Protocol) and 7.3.2 (Responses):

  In the CMD line the Most Significant Bit is transmitted first.

Use the stl_be_p() helper to store the value in big-endian.

Signed-off-by: Philippe Mathieu-Daudé 
Tested-by: Cédric Le Goater 
---
RFC because I'm surprised this has been unnoticed for 17 years
(commit a1bb27b1e9 "initial SD card emulation", April 2007).

Cc: Peter Maydell 
---
 hw/sd/sd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 1f3eea6e84..4e09640852 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1507,7 +1507,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 }
 
 sd->state = sd_sendingdata_state;
-*(uint32_t *) sd->data = sd_wpbits(sd, req.arg);
+stl_be_p(sd->data, sd_wpbits(sd, req.arg));
 sd->data_start = addr;
 sd->data_offset = 0;
 return sd_r1;
-- 
2.41.0




[PATCH v42 02/98] hw/sd/sdcard: Use spec v3.01 by default

2024-06-28 Thread Philippe Mathieu-Daudé
Recent SDHCI expect cards to support the v3.01 spec
to negociate lower I/O voltage. Select it by default.

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Cédric Le Goater 
---
 hw/sd/sd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index a48010cfc1..d0a1d5db18 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -2280,7 +2280,7 @@ static void sd_realize(DeviceState *dev, Error **errp)
 
 static Property sd_properties[] = {
 DEFINE_PROP_UINT8("spec_version", SDState,
-  spec_version, SD_PHY_SPECv2_00_VERS),
+  spec_version, SD_PHY_SPECv3_01_VERS),
 DEFINE_PROP_DRIVE("drive", SDState, blk),
 /* We do not model the chip select pin, so allow the board to select
  * whether card should be in SSI or MMC/SD mode.  It is also up to the
-- 
2.41.0




[PATCH v42 10/98] hw/sd/sdcard: Assign SDCardStates enum values

2024-06-28 Thread Philippe Mathieu-Daudé
SDCardStates enum values are specified, so assign them
correspondingly. It will be useful later when we add
states from later specs, which might not be continuous.

See CURRENT_STATE bits in section 4.10.1 "Card Status".

Signed-off-by: Philippe Mathieu-Daudé 
Tested-by: Cédric Le Goater 
---
 hw/sd/sd.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 135b7d2e23..fbdfafa3a6 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -75,16 +75,16 @@ enum SDCardModes {
 };
 
 enum SDCardStates {
-sd_inactive_state = -1,
-sd_idle_state = 0,
-sd_ready_state,
-sd_identification_state,
-sd_standby_state,
-sd_transfer_state,
-sd_sendingdata_state,
-sd_receivingdata_state,
-sd_programming_state,
-sd_disconnect_state,
+sd_inactive_state   = -1,
+sd_idle_state   = 0,
+sd_ready_state  = 1,
+sd_identification_state = 2,
+sd_standby_state= 3,
+sd_transfer_state   = 4,
+sd_sendingdata_state= 5,
+sd_receivingdata_state  = 6,
+sd_programming_state= 7,
+sd_disconnect_state = 8,
 };
 
 typedef sd_rsp_type_t (*sd_cmd_handler)(SDState *sd, SDRequest req);
-- 
2.41.0




[PATCH v42 11/98] hw/sd/sdcard: Simplify sd_inactive_state handling

2024-06-28 Thread Philippe Mathieu-Daudé
Card entering sd_inactive_state powers off, and won't respond
anymore. Handle that once when entering sd_do_command().

Remove condition always true in sd_cmd_GO_IDLE_STATE().

Signed-off-by: Philippe Mathieu-Daudé 
Tested-by: Cédric Le Goater 
---
 hw/sd/sd.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index fbdfafa3a6..7533a78cf6 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1081,10 +1081,8 @@ static sd_rsp_type_t sd_cmd_unimplemented(SDState *sd, 
SDRequest req)
 /* CMD0 */
 static sd_rsp_type_t sd_cmd_GO_IDLE_STATE(SDState *sd, SDRequest req)
 {
-if (sd->state != sd_inactive_state) {
-sd->state = sd_idle_state;
-sd_reset(DEVICE(sd));
-}
+sd->state = sd_idle_state;
+sd_reset(DEVICE(sd));
 
 return sd_is_spi(sd) ? sd_r1 : sd_r0;
 }
@@ -1579,7 +1577,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 switch (sd->state) {
 case sd_ready_state:
 case sd_identification_state:
-case sd_inactive_state:
 return sd_illegal;
 case sd_idle_state:
 if (rca) {
@@ -1800,6 +1797,11 @@ int sd_do_command(SDState *sd, SDRequest *req,
 return 0;
 }
 
+if (sd->state == sd_inactive_state) {
+rtype = sd_illegal;
+goto send_response;
+}
+
 if (sd_req_crc_validate(req)) {
 sd->card_status |= COM_CRC_ERROR;
 rtype = sd_illegal;
-- 
2.41.0




[NOTFORMERGE PATCH v42 15/98] tests/qtest: Disable npcm7xx_sdhci tests using hardcoded RCA

2024-06-28 Thread Philippe Mathieu-Daudé
Disable tests using 0x4567 hardcoded RCA otherwise when
using random RCA we get:

  ERROR:../../tests/qtest/npcm7xx_sdhci-test.c:69:write_sdread: assertion 
failed: (ret == len)
  not ok /arm/npcm7xx_sdhci/read_sd - 
ERROR:../../tests/qtest/npcm7xx_sdhci-test.c:69:write_sdread: assertion failed: 
(ret == len)
  Bail out!

See 
https://lore.kernel.org/qemu-devel/37f83be9-deb5-42a1-b704-14984351d...@linaro.org/

Signed-off-by: Philippe Mathieu-Daudé 
---
Cc: Hao Wu 
Cc: Shengtan Mao 
Cc: Tyrone Ting 

See also discussion with Thomas:
https://lore.kernel.org/qemu-devel/484dce48-286a-4a2b-9040-98c45bcfb...@linaro.org/
---
 tests/qtest/npcm7xx_sdhci-test.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/tests/qtest/npcm7xx_sdhci-test.c b/tests/qtest/npcm7xx_sdhci-test.c
index 5d68540e52..6a42b142ad 100644
--- a/tests/qtest/npcm7xx_sdhci-test.c
+++ b/tests/qtest/npcm7xx_sdhci-test.c
@@ -44,6 +44,7 @@ static QTestState *setup_sd_card(void)
 sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x4120, 0, (41 << 8));
 sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_ALL_SEND_CID);
 sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_SEND_RELATIVE_ADDR);
+g_test_skip("hardcoded 0x4567 card address");
 sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x4567, 0,
SDHC_SELECT_DESELECT_CARD);
 
@@ -76,6 +77,9 @@ static void test_read_sd(void)
 {
 QTestState *qts = setup_sd_card();
 
+g_test_skip("hardcoded 0x4567 card address used in setup_sd_card()");
+return;
+
 write_sdread(qts, "hello world");
 write_sdread(qts, "goodbye");
 
@@ -108,6 +112,9 @@ static void test_write_sd(void)
 {
 QTestState *qts = setup_sd_card();
 
+g_test_skip("hardcoded 0x4567 card address used in setup_sd_card()");
+return;
+
 sdwrite_read(qts, "hello world");
 sdwrite_read(qts, "goodbye");
 
-- 
2.41.0




[PATCH v42 14/98] hw/sd/sdcard: Extract sd_blk_len() helper

2024-06-28 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

Extract sd_blk_len() helper, use definitions instead
of magic values.

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index aaa50ab2c5..5997e13107 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -603,6 +603,14 @@ static void sd_response_r7_make(SDState *sd, uint8_t 
*response)
 stl_be_p(response, sd->vhs);
 }
 
+static uint32_t sd_blk_len(SDState *sd)
+{
+if (FIELD_EX32(sd->ocr, OCR, CARD_CAPACITY)) {
+return 1 << HWBLOCK_SHIFT;
+}
+return sd->blk_len;
+}
+
 static uint64_t sd_req_get_address(SDState *sd, SDRequest req)
 {
 uint64_t addr;
@@ -2076,7 +2084,7 @@ uint8_t sd_read_byte(SDState *sd)
 if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION))
 return 0x00;
 
-io_len = (sd->ocr & (1 << 30)) ? 512 : sd->blk_len;
+io_len = sd_blk_len(sd);
 
 trace_sdcard_read_data(sd->proto->name,
sd->last_cmd_name,
-- 
2.41.0




[PATCH v42 05/98] hw/sd/sdcard: Trace requested address computed by sd_req_get_address()

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 9 +++--
 hw/sd/trace-events | 1 +
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 090a6fdcdb..464576751a 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -608,10 +608,15 @@ static void sd_response_r7_make(SDState *sd, uint8_t 
*response)
 
 static uint64_t sd_req_get_address(SDState *sd, SDRequest req)
 {
+uint64_t addr;
+
 if (FIELD_EX32(sd->ocr, OCR, CARD_CAPACITY)) {
-return (uint64_t) req.arg << HWBLOCK_SHIFT;
+addr = (uint64_t) req.arg << HWBLOCK_SHIFT;
+} else {
+addr = req.arg;
 }
-return req.arg;
+trace_sdcard_req_addr(req.arg, addr);
+return addr;
 }
 
 static inline uint64_t sd_addr_to_wpnum(uint64_t addr)
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index 0eee98a646..43eaeba149 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -50,6 +50,7 @@ sdcard_ejected(void) ""
 sdcard_erase(uint32_t first, uint32_t last) "addr first 0x%" PRIx32" last 0x%" 
PRIx32
 sdcard_lock(void) ""
 sdcard_unlock(void) ""
+sdcard_req_addr(uint32_t req_arg, uint64_t addr) "req 0x%" PRIx32 " addr 0x%" 
PRIx64
 sdcard_read_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
 sdcard_write_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
 sdcard_write_data(const char *proto, const char *cmd_desc, uint8_t cmd, 
uint32_t offset, uint8_t value) "%s %20s/ CMD%02d ofs %"PRIu32" value 0x%02x"
-- 
2.41.0




[PATCH v42 09/98] hw/sd/sdcard: Use READY_FOR_DATA definition instead of magic value

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
Tested-by: Cédric Le Goater 
---
 hw/sd/sd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 1f37d9c93a..135b7d2e23 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -561,7 +561,7 @@ FIELD(CSR, OUT_OF_RANGE,   31,  1)
 
 static void sd_set_cardstatus(SDState *sd)
 {
-sd->card_status = 0x0100;
+sd->card_status = READY_FOR_DATA;
 }
 
 static void sd_set_sdstatus(SDState *sd)
-- 
2.41.0




[PATCH v42 08/98] hw/sd/sdcard: Send NUM_WR_BLOCKS bits MSB first (ACMD22)

2024-06-28 Thread Philippe Mathieu-Daudé
Per sections 3.6.1 (SD Bus Protocol), 4.3.4 "Data Write"
and 7.3.2 (Responses):

  In the CMD line the Most Significant Bit is transmitted first.

Use the stl_be_p() helper to store the value in big-endian.

Signed-off-by: Philippe Mathieu-Daudé 
Tested-by: Cédric Le Goater 
---
RFC because I'm surprised this has been unnoticed for 17 years
(commit a1bb27b1e9 "initial SD card emulation", April 2007).

Cc: Peter Maydell 
---
 hw/sd/sd.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 4e09640852..1f37d9c93a 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1668,8 +1668,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 case 22:  /* ACMD22: SEND_NUM_WR_BLOCKS */
 switch (sd->state) {
 case sd_transfer_state:
-*(uint32_t *) sd->data = sd->blk_written;
-
+stl_be_p(sd->data, sd->blk_written);
 sd->state = sd_sendingdata_state;
 sd->data_start = 0;
 sd->data_offset = 0;
-- 
2.41.0




[PATCH v42 17/98] hw/sd/sdcard: Introduce definitions for EXT_CSD register

2024-06-28 Thread Philippe Mathieu-Daudé
From: Cédric Le Goater 

Signed-off-by: Cédric Le Goater 
Signed-off-by: Cédric Le Goater 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sdmmc-internal.h | 97 ++
 1 file changed, 97 insertions(+)

diff --git a/hw/sd/sdmmc-internal.h b/hw/sd/sdmmc-internal.h
index d8bf17d204..306ffa7f53 100644
--- a/hw/sd/sdmmc-internal.h
+++ b/hw/sd/sdmmc-internal.h
@@ -11,6 +11,103 @@
 #ifndef SDMMC_INTERNAL_H
 #define SDMMC_INTERNAL_H
 
+/*
+ * EXT_CSD fields
+ */
+
+#define EXT_CSD_CMDQ_MODE_EN15  /* R/W */
+#define EXT_CSD_FLUSH_CACHE 32  /* W */
+#define EXT_CSD_CACHE_CTRL  33  /* R/W */
+#define EXT_CSD_POWER_OFF_NOTIFICATION  34  /* R/W */
+#define EXT_CSD_PACKED_FAILURE_INDEX35  /* RO */
+#define EXT_CSD_PACKED_CMD_STATUS   36  /* RO */
+#define EXT_CSD_EXP_EVENTS_STATUS   54  /* RO, 2 bytes */
+#define EXT_CSD_EXP_EVENTS_CTRL 56  /* R/W, 2 bytes */
+#define EXT_CSD_DATA_SECTOR_SIZE61  /* R */
+#define EXT_CSD_GP_SIZE_MULT143 /* R/W */
+#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */
+#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */
+#define EXT_CSD_PARTITION_SUPPORT   160 /* RO */
+#define EXT_CSD_HPI_MGMT161 /* R/W */
+#define EXT_CSD_RST_N_FUNCTION  162 /* R/W */
+#define EXT_CSD_BKOPS_EN163 /* R/W */
+#define EXT_CSD_BKOPS_START 164 /* W */
+#define EXT_CSD_SANITIZE_START  165 /* W */
+#define EXT_CSD_WR_REL_PARAM166 /* RO */
+#define EXT_CSD_RPMB_MULT   168 /* RO */
+#define EXT_CSD_FW_CONFIG   169 /* R/W */
+#define EXT_CSD_BOOT_WP 173 /* R/W */
+#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */
+#define EXT_CSD_PART_CONFIG 179 /* R/W */
+#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */
+#define EXT_CSD_BUS_WIDTH   183 /* R/W */
+#define EXT_CSD_STROBE_SUPPORT  184 /* RO */
+#define EXT_CSD_HS_TIMING   185 /* R/W */
+#define EXT_CSD_POWER_CLASS 187 /* R/W */
+#define EXT_CSD_REV 192 /* RO */
+#define EXT_CSD_STRUCTURE   194 /* RO */
+#define EXT_CSD_CARD_TYPE   196 /* RO */
+#define EXT_CSD_DRIVER_STRENGTH 197 /* RO */
+#define EXT_CSD_OUT_OF_INTERRUPT_TIME   198 /* RO */
+#define EXT_CSD_PART_SWITCH_TIME199 /* RO */
+#define EXT_CSD_PWR_CL_52_195   200 /* RO */
+#define EXT_CSD_PWR_CL_26_195   201 /* RO */
+#define EXT_CSD_PWR_CL_52_360   202 /* RO */
+#define EXT_CSD_PWR_CL_26_360   203 /* RO */
+#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
+#define EXT_CSD_S_A_TIMEOUT 217 /* RO */
+#define EXT_CSD_S_C_VCCQ219 /* RO */
+#define EXT_CSD_S_C_VCC 220 /* RO */
+#define EXT_CSD_REL_WR_SEC_C222 /* RO */
+#define EXT_CSD_HC_WP_GRP_SIZE  221 /* RO */
+#define EXT_CSD_ERASE_TIMEOUT_MULT  223 /* RO */
+#define EXT_CSD_HC_ERASE_GRP_SIZE   224 /* RO */
+#define EXT_CSD_ACC_SIZE225 /* RO */
+#define EXT_CSD_BOOT_MULT   226 /* RO */
+#define EXT_CSD_BOOT_INFO   228 /* RO */
+#define EXT_CSD_SEC_TRIM_MULT   229 /* RO */
+#define EXT_CSD_SEC_ERASE_MULT  230 /* RO */
+#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */
+#define EXT_CSD_TRIM_MULT   232 /* RO */
+#define EXT_CSD_PWR_CL_200_195  236 /* RO */
+#define EXT_CSD_PWR_CL_200_360  237 /* RO */
+#define EXT_CSD_PWR_CL_DDR_52_195   238 /* RO */
+#define EXT_CSD_PWR_CL_DDR_52_360   239 /* RO */
+#define EXT_CSD_BKOPS_STATUS246 /* RO */
+#define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */
+#define EXT_CSD_GENERIC_CMD6_TIME   248 /* RO */
+#define EXT_CSD_CACHE_SIZE  249 /* RO, 4 bytes */
+#define EXT_CSD_PWR_CL_DDR_200_360  253 /* RO */
+#define EXT_CSD_FIRMWARE_VERSION254 /* RO, 8 bytes */
+#define EXT_CSD_PRE_EOL_INFO267 /* RO */
+#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A  268 /* RO */
+#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B  269 /* RO */
+#define EXT_CSD_CMDQ_DEPTH  307 /* RO */
+#define EXT_CSD_CMDQ_SUPPORT308 /* RO */
+#define EXT_CSD_SUPPORTED_MODE  493 /* RO */
+#define EXT_CSD_TAG_UNIT_SIZE   498 /* RO */
+#define EXT_CSD_DATA_TAG_SUPPORT499 /* RO */
+#define EXT_CSD_MAX_PACKED_WRITES   500 /* RO */
+#define EXT_CSD_MAX_PACKED_READS501 /* RO */
+#define EXT_CSD_BKOPS_SUPPORT   502 /* RO */
+#define EXT_CSD_HPI_FEATURES503 /* RO */
+#define EXT_CSD_

[PATCH v42 16/98] hw/sd/sdcard: Generate random RCA value

2024-06-28 Thread Philippe Mathieu-Daudé
Rather than using the obscure 0x4567 magic value,
use a real random one.

Signed-off-by: Philippe Mathieu-Daudé 
Tested-by: Cédric Le Goater 
---
 hw/sd/sd.c | 11 ---
 hw/sd/trace-events |  1 +
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 5997e13107..d85b2906f4 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -46,6 +46,7 @@
 #include "qemu/error-report.h"
 #include "qemu/timer.h"
 #include "qemu/log.h"
+#include "qemu/guest-random.h"
 #include "qemu/module.h"
 #include "sdmmc-internal.h"
 #include "trace.h"
@@ -488,9 +489,10 @@ static void sd_set_csd(SDState *sd, uint64_t size)
 
 /* Relative Card Address register */
 
-static void sd_set_rca(SDState *sd)
+static void sd_set_rca(SDState *sd, uint16_t value)
 {
-sd->rca += 0x4567;
+trace_sdcard_set_rca(value);
+sd->rca = value;
 }
 
 static uint16_t sd_req_get_rca(SDState *s, SDRequest req)
@@ -1113,11 +1115,14 @@ static sd_rsp_type_t sd_cmd_ALL_SEND_CID(SDState *sd, 
SDRequest req)
 /* CMD3 */
 static sd_rsp_type_t sd_cmd_SEND_RELATIVE_ADDR(SDState *sd, SDRequest req)
 {
+uint16_t random_rca;
+
 switch (sd->state) {
 case sd_identification_state:
 case sd_standby_state:
 sd->state = sd_standby_state;
-sd_set_rca(sd);
+qemu_guest_getrandom_nofail(&random_rca, sizeof(random_rca));
+sd_set_rca(sd, random_rca);
 return sd_r6;
 
 default:
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index 43eaeba149..6a51b0e906 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -43,6 +43,7 @@ sdcard_response(const char *rspdesc, int rsplen) "%s (sz:%d)"
 sdcard_powerup(void) ""
 sdcard_inquiry_cmd41(void) ""
 sdcard_reset(void) ""
+sdcard_set_rca(uint16_t value) "new RCA: 0x%04x"
 sdcard_set_blocklen(uint16_t length) "block len 0x%03x"
 sdcard_set_block_count(uint32_t cnt) "block cnt 0x%"PRIx32
 sdcard_inserted(bool readonly) "read_only: %u"
-- 
2.41.0




[PATCH v42 18/98] hw/sd/sdcard: Introduce sd_cmd_to_sendingdata and sd_generic_read_byte

2024-06-28 Thread Philippe Mathieu-Daudé
All commands switching from TRANSFER state to (sending)DATA
do the same: send stream of data on the DAT lines. Instead
of duplicating the same code many times, introduce 2 helpers:
- sd_cmd_to_sendingdata() on the I/O line setup the data to
  be transferred,
- sd_generic_read_byte() on the DAT lines to fetch the data.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 39 +++
 1 file changed, 39 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index d85b2906f4..1a8d06804d 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -142,8 +142,10 @@ struct SDState {
  */
 bool expecting_acmd;
 uint32_t blk_written;
+
 uint64_t data_start;
 uint32_t data_offset;
+size_t data_size;
 uint8_t data[512];
 uint8_t vendor_data[512];
 
@@ -1083,6 +1085,29 @@ static sd_rsp_type_t sd_cmd_unimplemented(SDState *sd, 
SDRequest req)
 return sd_illegal;
 }
 
+/* Configure fields for following sd_generic_read_byte() calls */
+__attribute__((unused))
+static sd_rsp_type_t sd_cmd_to_sendingdata(SDState *sd, SDRequest req,
+   uint64_t start,
+   const void *data, size_t size)
+{
+if (sd->state != sd_transfer_state) {
+sd_invalid_state_for_cmd(sd, req);
+}
+
+sd->state = sd_sendingdata_state;
+sd->data_start = start;
+sd->data_offset = 0;
+if (data) {
+assert(size);
+memcpy(sd->data, data, size);
+}
+if (size) {
+sd->data_size = size;
+}
+return sd_r1;
+}
+
 /* CMD0 */
 static sd_rsp_type_t sd_cmd_GO_IDLE_STATE(SDState *sd, SDRequest req)
 {
@@ -1920,6 +1945,20 @@ send_response:
 return rsplen;
 }
 
+/* Return true when buffer is consumed. Configured by sd_cmd_to_sendingdata() 
*/
+__attribute__((unused))
+static bool sd_generic_read_byte(SDState *sd, uint8_t *value)
+{
+*value = sd->data[sd->data_offset];
+
+if (++sd->data_offset >= sd->data_size) {
+sd->state = sd_transfer_state;
+return true;
+}
+
+return false;
+}
+
 void sd_write_byte(SDState *sd, uint8_t value)
 {
 int i;
-- 
2.41.0




[PATCH v42 34/98] hw/sd/sdcard: Convert LOCK_UNLOCK to generic_write_byte (CMD42)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 15 ++-
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index bdd5f3486a..0cb528b0b2 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1628,17 +1628,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 
 /* Lock card commands (Class 7) */
 case 42:  /* CMD42:  LOCK_UNLOCK */
-switch (sd->state) {
-case sd_transfer_state:
-sd->state = sd_receivingdata_state;
-sd->data_start = 0;
-sd->data_offset = 0;
-return sd_r1;
-
-default:
-break;
-}
-break;
+return sd_cmd_to_receivingdata(sd, req, 0, 0);
 
 /* Application specific commands (Class 8) */
 case 55:  /* CMD55:  APP_CMD */
@@ -2109,8 +2099,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
 break;
 
 case 42:  /* CMD42:  LOCK_UNLOCK */
-sd->data[sd->data_offset ++] = value;
-if (sd->data_offset >= sd->blk_len) {
+if (sd_generic_write_byte(sd, value)) {
 /* TODO: Check CRC before committing */
 sd->state = sd_programming_state;
 sd_lock_command(sd);
-- 
2.41.0




[PATCH v42 23/98] hw/sd/sdcard: Convert SEND_TUNING_BLOCK to generic_read_byte (CMD19)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 48 +++-
 1 file changed, 19 insertions(+), 29 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 605269163d..eece33194a 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -568,6 +568,21 @@ static void sd_set_sdstatus(SDState *sd)
 memset(sd->sd_status, 0, 64);
 }
 
+static const uint8_t sd_tuning_block_pattern4[64] = {
+/*
+ * See: Physical Layer Simplified Specification Version 3.01,
+ * Table 4-2.
+ */
+0xff, 0x0f, 0xff, 0x00, 0x0f, 0xfc, 0xc3, 0xcc,
+0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
+0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
+0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
+0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
+0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
+0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
+0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde
+};
+
 static int sd_req_crc_validate(SDRequest *req)
 {
 uint8_t buffer[5];
@@ -1161,14 +1176,9 @@ static sd_rsp_type_t sd_cmd_SEND_TUNING_BLOCK(SDState 
*sd, SDRequest req)
 return sd_cmd_illegal(sd, req);
 }
 
-if (sd->state != sd_transfer_state) {
-return sd_invalid_state_for_cmd(sd, req);
-}
-
-sd->state = sd_sendingdata_state;
-sd->data_offset = 0;
-
-return sd_r1;
+return sd_cmd_to_sendingdata(sd, req, 0,
+ sd_tuning_block_pattern4,
+ sizeof(sd_tuning_block_pattern4));
 }
 
 /* CMD23 */
@@ -2100,20 +2110,6 @@ void sd_write_byte(SDState *sd, uint8_t value)
 }
 }
 
-#define SD_TUNING_BLOCK_SIZE64
-
-static const uint8_t sd_tuning_block_pattern[SD_TUNING_BLOCK_SIZE] = {
-/* See: Physical Layer Simplified Specification Version 3.01, Table 4-2 */
-0xff, 0x0f, 0xff, 0x00, 0x0f, 0xfc, 0xc3, 0xcc,
-0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
-0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
-0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
-0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
-0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
-0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
-0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
-};
-
 uint8_t sd_read_byte(SDState *sd)
 {
 /* TODO: Append CRCs */
@@ -2142,6 +2138,7 @@ uint8_t sd_read_byte(SDState *sd)
 case 9:  /* CMD9:   SEND_CSD */
 case 10: /* CMD10:  SEND_CID */
 case 17: /* CMD17:  READ_SINGLE_BLOCK */
+case 19: /* CMD19:  SEND_TUNING_BLOCK (SD) */
 sd_generic_read_byte(sd, &ret);
 break;
 
@@ -2176,13 +2173,6 @@ uint8_t sd_read_byte(SDState *sd)
 }
 break;
 
-case 19:/* CMD19:  SEND_TUNING_BLOCK (SD) */
-if (sd->data_offset >= SD_TUNING_BLOCK_SIZE - 1) {
-sd->state = sd_transfer_state;
-}
-ret = sd_tuning_block_pattern[sd->data_offset++];
-break;
-
 case 22:  /* ACMD22: SEND_NUM_WR_BLOCKS */
 ret = sd->data[sd->data_offset ++];
 
-- 
2.41.0




[PATCH v42 21/98] hw/sd/sdcard: Duplicate READ_SINGLE_BLOCK / READ_MULTIPLE_BLOCK cases

2024-06-28 Thread Philippe Mathieu-Daudé
In order to modify the READ_SINGLE_BLOCK case in the
next commit, duplicate it first.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 8201f3245c..dfcb213aa9 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1398,6 +1398,24 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 break;
 
 case 17:  /* CMD17:  READ_SINGLE_BLOCK */
+addr = sd_req_get_address(sd, req);
+switch (sd->state) {
+case sd_transfer_state:
+
+if (!address_in_range(sd, "READ_SINGLE_BLOCK", addr, sd->blk_len)) 
{
+return sd_r1;
+}
+
+sd->state = sd_sendingdata_state;
+sd->data_start = addr;
+sd->data_offset = 0;
+return sd_r1;
+
+default:
+break;
+}
+break;
+
 case 18:  /* CMD18:  READ_MULTIPLE_BLOCK */
 addr = sd_req_get_address(sd, req);
 switch (sd->state) {
-- 
2.41.0




[PATCH v42 13/98] hw/sd/sdcard: Add direct reference to SDProto in SDState

2024-06-28 Thread Philippe Mathieu-Daudé
Keep direct reference to SDProto in SDState,
remove then unnecessary sd_proto().

Signed-off-by: Philippe Mathieu-Daudé 
Tested-by: Cédric Le Goater 
---
 hw/sd/sd.c | 37 +
 1 file changed, 17 insertions(+), 20 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 8f441e418c..aaa50ab2c5 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -116,6 +116,8 @@ struct SDState {
 uint8_t spec_version;
 BlockBackend *blk;
 
+const SDProto *proto;
+
 /* Runtime changeables */
 
 uint32_t mode;/* current card mode, one of SDCardModes */
@@ -154,18 +156,11 @@ struct SDState {
 
 static void sd_realize(DeviceState *dev, Error **errp);
 
-static const struct SDProto *sd_proto(SDState *sd)
-{
-SDCardClass *sc = SD_CARD_GET_CLASS(sd);
-
-return sc->proto;
-}
-
 static const SDProto sd_proto_spi;
 
 static bool sd_is_spi(SDState *sd)
 {
-return sd_proto(sd) == &sd_proto_spi;
+return sd->proto == &sd_proto_spi;
 }
 
 static const char *sd_version_str(enum SDPhySpecificationVersion version)
@@ -1044,7 +1039,7 @@ static bool address_in_range(SDState *sd, const char 
*desc,
 static sd_rsp_type_t sd_invalid_state_for_cmd(SDState *sd, SDRequest req)
 {
 qemu_log_mask(LOG_GUEST_ERROR, "%s: CMD%i in a wrong state: %s (spec 
%s)\n",
-  sd_proto(sd)->name, req.cmd, sd_state_name(sd->state),
+  sd->proto->name, req.cmd, sd_state_name(sd->state),
   sd_version_str(sd->spec_version));
 
 return sd_illegal;
@@ -1053,7 +1048,7 @@ static sd_rsp_type_t sd_invalid_state_for_cmd(SDState 
*sd, SDRequest req)
 static sd_rsp_type_t sd_invalid_mode_for_cmd(SDState *sd, SDRequest req)
 {
 qemu_log_mask(LOG_GUEST_ERROR, "%s: CMD%i in a wrong mode: %s (spec %s)\n",
-  sd_proto(sd)->name, req.cmd, sd_mode_name(sd->mode),
+  sd->proto->name, req.cmd, sd_mode_name(sd->mode),
   sd_version_str(sd->spec_version));
 
 return sd_illegal;
@@ -1062,7 +1057,7 @@ static sd_rsp_type_t sd_invalid_mode_for_cmd(SDState *sd, 
SDRequest req)
 static sd_rsp_type_t sd_cmd_illegal(SDState *sd, SDRequest req)
 {
 qemu_log_mask(LOG_GUEST_ERROR, "%s: Unknown CMD%i for spec %s\n",
-  sd_proto(sd)->name, req.cmd,
+  sd->proto->name, req.cmd,
   sd_version_str(sd->spec_version));
 
 return sd_illegal;
@@ -1073,7 +1068,7 @@ __attribute__((unused))
 static sd_rsp_type_t sd_cmd_unimplemented(SDState *sd, SDRequest req)
 {
 qemu_log_mask(LOG_UNIMP, "%s: CMD%i not implemented\n",
-  sd_proto(sd)->name, req.cmd);
+  sd->proto->name, req.cmd);
 
 return sd_illegal;
 }
@@ -1166,7 +1161,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
  * However there is no ACMD55, so we want to trace this particular case.
  */
 if (req.cmd != 55 || sd->expecting_acmd) {
-trace_sdcard_normal_command(sd_proto(sd)->name,
+trace_sdcard_normal_command(sd->proto->name,
 sd->last_cmd_name, req.cmd,
 req.arg, sd_state_name(sd->state));
 }
@@ -1185,8 +1180,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 return sd_illegal;
 }
 
-if (sd_proto(sd)->cmd[req.cmd]) {
-return sd_proto(sd)->cmd[req.cmd](sd, req);
+if (sd->proto->cmd[req.cmd]) {
+return sd->proto->cmd[req.cmd](sd, req);
 }
 
 switch (req.cmd) {
@@ -1632,12 +1627,12 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 SDRequest req)
 {
 sd->last_cmd_name = sd_acmd_name(req.cmd);
-trace_sdcard_app_command(sd_proto(sd)->name, sd->last_cmd_name,
+trace_sdcard_app_command(sd->proto->name, sd->last_cmd_name,
  req.cmd, req.arg, sd_state_name(sd->state));
 sd->card_status |= APP_CMD;
 
-if (sd_proto(sd)->acmd[req.cmd]) {
-return sd_proto(sd)->acmd[req.cmd](sd, req);
+if (sd->proto->acmd[req.cmd]) {
+return sd->proto->acmd[req.cmd](sd, req);
 }
 
 switch (req.cmd) {
@@ -1928,7 +1923,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
 if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION))
 return;
 
-trace_sdcard_write_data(sd_proto(sd)->name,
+trace_sdcard_write_data(sd->proto->name,
 sd->last_cmd_name,
 sd->current_cmd, sd->data_offset, value);
 switch (sd->current_cmd) {
@@ -2083,7 +2078,7 @@ uint8_t sd_read_byte(SDState *sd)
 
 io_len = (sd->ocr & (1 << 30)) ? 512 : sd->blk_len;
 
-trace_sdcard_read_data(sd_proto(sd)->name,
+trace_sdcard_read_data(sd->proto->name,
sd->last_cmd_name,
sd->current_cmd, sd->data_offset, io_len);
 switch (sd->current_cmd) {
@@ -2227,7 +,9 @@ static const SDProto sd_proto_sd = {
 static void sd_

[PATCH v42 27/98] hw/sd/sdcard: Convert SEND_NUM_WR_BLOCKS to generic_read_byte (ACMD22)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 16 
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 1c4811f410..8d02cd9a26 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1715,11 +1715,9 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 case 22:  /* ACMD22: SEND_NUM_WR_BLOCKS */
 switch (sd->state) {
 case sd_transfer_state:
-stl_be_p(sd->data, sd->blk_written);
-sd->state = sd_sendingdata_state;
-sd->data_start = 0;
-sd->data_offset = 0;
-return sd_r1;
+return sd_cmd_to_sendingdata(sd, req, 0,
+ &sd->blk_written,
+ sizeof(sd->blk_written));
 
 default:
 break;
@@ -2138,6 +2136,7 @@ uint8_t sd_read_byte(SDState *sd)
 case 13: /* ACMD13: SD_STATUS */
 case 17: /* CMD17:  READ_SINGLE_BLOCK */
 case 19: /* CMD19:  SEND_TUNING_BLOCK (SD) */
+case 22: /* ACMD22: SEND_NUM_WR_BLOCKS */
 case 30: /* CMD30:  SEND_WRITE_PROT */
 case 56: /* CMD56:  GEN_CMD */
 sd_generic_read_byte(sd, &ret);
@@ -2167,13 +2166,6 @@ uint8_t sd_read_byte(SDState *sd)
 }
 break;
 
-case 22:  /* ACMD22: SEND_NUM_WR_BLOCKS */
-ret = sd->data[sd->data_offset ++];
-
-if (sd->data_offset >= 4)
-sd->state = sd_transfer_state;
-break;
-
 case 51:  /* ACMD51: SEND_SCR */
 ret = sd->scr[sd->data_offset ++];
 
-- 
2.41.0




[PATCH v42 29/98] hw/sd/sdcard: Introduce sd_cmd_to_receivingdata / sd_generic_write_byte

2024-06-28 Thread Philippe Mathieu-Daudé
All commands switching from TRANSFER state to (receiving)DATA
do the same: receive stream of data from the DAT lines. Instead
of duplicating the same code many times, introduce 2 helpers:
- sd_cmd_to_receivingdata() on the I/O line setup the data to
  be received on the data[] buffer,
- sd_generic_write_byte() on the DAT lines to push the data.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index cd308e9a89..690a3f275e 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1100,6 +1100,22 @@ static sd_rsp_type_t sd_cmd_unimplemented(SDState *sd, 
SDRequest req)
 return sd_illegal;
 }
 
+/* Configure fields for following sd_generic_write_byte() calls */
+__attribute__((unused))
+static sd_rsp_type_t sd_cmd_to_receivingdata(SDState *sd, SDRequest req,
+ uint64_t start, size_t size)
+{
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+sd->state = sd_receivingdata_state;
+sd->data_start = start;
+sd->data_offset = 0;
+/* sd->data[] used as receive buffer */
+sd->data_size = size ?: sizeof(sd->data);
+return sd_r1;
+}
+
 /* Configure fields for following sd_generic_read_byte() calls */
 static sd_rsp_type_t sd_cmd_to_sendingdata(SDState *sd, SDRequest req,
uint64_t start,
@@ -1953,6 +1969,19 @@ send_response:
 return rsplen;
 }
 
+/* Return true if buffer is consumed. Configured by sd_cmd_to_receivingdata() 
*/
+__attribute__((unused))
+static bool sd_generic_write_byte(SDState *sd, uint8_t value)
+{
+sd->data[sd->data_offset] = value;
+
+if (++sd->data_offset >= sd->data_size) {
+sd->state = sd_transfer_state;
+return true;
+}
+return false;
+}
+
 /* Return true when buffer is consumed. Configured by sd_cmd_to_sendingdata() 
*/
 static bool sd_generic_read_byte(SDState *sd, uint8_t *value)
 {
-- 
2.41.0




[PATCH v42 36/98] hw/sd/sdcard: Move sd_[a]cmd_name() methods to sd.c

2024-06-28 Thread Philippe Mathieu-Daudé
Merge sdmmc-internal.c into sd.c by moving
sd_cmd_name() and sd_acmd_name() and updating
meson.build.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sdmmc-internal.h | 26 ---
 hw/sd/sd.c | 62 
 hw/sd/sdmmc-internal.c | 72 --
 hw/sd/meson.build  |  2 +-
 4 files changed, 63 insertions(+), 99 deletions(-)
 delete mode 100644 hw/sd/sdmmc-internal.c

diff --git a/hw/sd/sdmmc-internal.h b/hw/sd/sdmmc-internal.h
index 306ffa7f53..20d85aea6d 100644
--- a/hw/sd/sdmmc-internal.h
+++ b/hw/sd/sdmmc-internal.h
@@ -108,30 +108,4 @@
 #define EXT_CSD_PART_CONFIG_EN_BOOT0(0x1 << 3)
 #define EXT_CSD_PART_CONFIG_EN_USER (0x7 << 3)
 
-#define SDMMC_CMD_MAX 64
-
-/**
- * sd_cmd_name:
- * @cmd: A SD "normal" command, up to SDMMC_CMD_MAX.
- *
- * Returns a human-readable name describing the command.
- * The return value is always a static string which does not need
- * to be freed after use.
- *
- * Returns: The command name of @cmd or "UNKNOWN_CMD".
- */
-const char *sd_cmd_name(uint8_t cmd);
-
-/**
- * sd_acmd_name:
- * @cmd: A SD "Application-Specific" command, up to SDMMC_CMD_MAX.
- *
- * Returns a human-readable name describing the application command.
- * The return value is always a static string which does not need
- * to be freed after use.
- *
- * Returns: The application command name of @cmd or "UNKNOWN_ACMD".
- */
-const char *sd_acmd_name(uint8_t cmd);
-
 #endif
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index f9708064d0..93a4a4e1b4 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -88,6 +88,8 @@ enum SDCardStates {
 sd_disconnect_state = 8,
 };
 
+#define SDMMC_CMD_MAX 64
+
 typedef sd_rsp_type_t (*sd_cmd_handler)(SDState *sd, SDRequest req);
 
 typedef struct SDProto {
@@ -231,6 +233,66 @@ static const char *sd_response_name(sd_rsp_type_t rsp)
 return response_name[rsp];
 }
 
+static const char *sd_cmd_name(uint8_t cmd)
+{
+static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
+ [0]= "GO_IDLE_STATE",   [1]= "SEND_OP_COND",
+ [2]= "ALL_SEND_CID",[3]= "SEND_RELATIVE_ADDR",
+ [4]= "SET_DSR", [5]= "IO_SEND_OP_COND",
+ [6]= "SWITCH_FUNC", [7]= "SELECT/DESELECT_CARD",
+ [8]= "SEND_IF_COND",[9]= "SEND_CSD",
+[10]= "SEND_CID",   [11]= "VOLTAGE_SWITCH",
+[12]= "STOP_TRANSMISSION",  [13]= "SEND_STATUS",
+[15]= "GO_INACTIVE_STATE",
+[16]= "SET_BLOCKLEN",   [17]= "READ_SINGLE_BLOCK",
+[18]= "READ_MULTIPLE_BLOCK",[19]= "SEND_TUNING_BLOCK",
+[20]= "SPEED_CLASS_CONTROL",[21]= "DPS_spec",
+[23]= "SET_BLOCK_COUNT",
+[24]= "WRITE_BLOCK",[25]= "WRITE_MULTIPLE_BLOCK",
+[26]= "MANUF_RSVD", [27]= "PROGRAM_CSD",
+[28]= "SET_WRITE_PROT", [29]= "CLR_WRITE_PROT",
+[30]= "SEND_WRITE_PROT",
+[32]= "ERASE_WR_BLK_START", [33]= "ERASE_WR_BLK_END",
+[34]= "SW_FUNC_RSVD",   [35]= "SW_FUNC_RSVD",
+[36]= "SW_FUNC_RSVD",   [37]= "SW_FUNC_RSVD",
+[38]= "ERASE",
+[40]= "DPS_spec",
+[42]= "LOCK_UNLOCK",[43]= "Q_MANAGEMENT",
+[44]= "Q_TASK_INFO_A",  [45]= "Q_TASK_INFO_B",
+[46]= "Q_RD_TASK",  [47]= "Q_WR_TASK",
+[48]= "READ_EXTR_SINGLE",   [49]= "WRITE_EXTR_SINGLE",
+[50]= "SW_FUNC_RSVD",
+[52]= "IO_RW_DIRECT",   [53]= "IO_RW_EXTENDED",
+[54]= "SDIO_RSVD",  [55]= "APP_CMD",
+[56]= "GEN_CMD",[57]= "SW_FUNC_RSVD",
+[58]= "READ_EXTR_MULTI",[59]= "WRITE_EXTR_MULTI",
+[60]= "MANUF_RSVD", [61]= "MANUF_RSVD",
+[62]= "MANUF_RSVD", [63]= "MANUF_RSVD",
+};
+return cmd_abbrev[cmd] ? cmd_abbrev[cmd] : "UNKNOWN_CMD";
+}
+
+static const char *sd_acmd_name(uint8_t cmd)
+{
+static const char *acmd_abbrev[SDMMC_CMD_MAX] = {
+ [6] = "SET_BUS_WIDTH",
+[13] = "SD_STATUS",
+[14] = "DPS_spec",  [15] = "DPS_spec",
+[16] = "DPS_spec",
+[18] = "SECU_spec",
+[22] = "SEND_NUM_WR_BLOCKS",[23] = "SET_WR_BLK_ERASE_COUNT",
+[41] = "SD_SEND_OP_COND",
+[42] = "SET_CLR_CARD_DETECT",
+[51] = "SEND_SCR",
+[52] = "SECU_spec", [53] = "SECU_spec",
+[54] = "SECU_spec",
+[56] = "SECU_spec", [57] = "SECU_spec",
+[58] = "SECU_spec", [59] = "SECU_spec",
+};
+
+return acmd_abbrev[cmd] ? acmd_abbrev[

[PATCH v42 12/98] hw/sd/sdcard: Restrict SWITCH_FUNCTION to sd_transfer_state (CMD6)

2024-06-28 Thread Philippe Mathieu-Daudé
SWITCH_FUNCTION is only allowed in TRANSFER state
(See 4.8 "Card State Transition Table).

Signed-off-by: Philippe Mathieu-Daudé 
Tested-by: Cédric Le Goater 
---
 hw/sd/sd.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 7533a78cf6..8f441e418c 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1205,6 +1205,10 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 if (sd->mode != sd_data_transfer_mode) {
 return sd_invalid_mode_for_cmd(sd, req);
 }
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+
 sd_function_switch(sd, req.arg);
 sd->state = sd_sendingdata_state;
 sd->data_start = 0;
-- 
2.41.0




[PATCH v42 32/98] hw/sd/sdcard: Convert PROGRAM_CID to generic_write_byte (CMD26)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 15 ++-
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 4a03f41086..b9c72a0128 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1515,17 +1515,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 break;
 
 case 26:  /* CMD26:  PROGRAM_CID */
-switch (sd->state) {
-case sd_transfer_state:
-sd->state = sd_receivingdata_state;
-sd->data_start = 0;
-sd->data_offset = 0;
-return sd_r1;
-
-default:
-break;
-}
-break;
+return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid));
 
 case 27:  /* CMD27:  PROGRAM_CSD */
 switch (sd->state) {
@@ -2088,8 +2078,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
 break;
 
 case 26:  /* CMD26:  PROGRAM_CID */
-sd->data[sd->data_offset ++] = value;
-if (sd->data_offset >= sizeof(sd->cid)) {
+if (sd_generic_write_byte(sd, value)) {
 /* TODO: Check CRC before committing */
 sd->state = sd_programming_state;
 for (i = 0; i < sizeof(sd->cid); i ++)
-- 
2.41.0




[PATCH v42 42/98] hw/sd/sdcard: Remove SEND_DSR dead case (CMD4)

2024-06-28 Thread Philippe Mathieu-Daudé
The CSD::CSR_IMP bit defines whether the Driver Stage
Register (DSR) is implemented or not. We do not set
this bit in CSD:

static void sd_set_csd(SDState *sd, uint64_t size)
{
...
if (size <= SDSC_MAX_CAPACITY) { /* Standard Capacity SD */
...
sd->csd[6] = 0xe0 | /* Partial block for read allowed */
((csize >> 10) & 0x03);
...
} else {/* SDHC */
...
sd->csd[6] = 0x00;
...
}
...
}

The sd_normal_command() switch case for the SEND_DSR
command do nothing and fallback to "illegal command".
Since the command is mandatory (although the register
isn't...) call the sd_cmd_unimplemented() handler.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 14 ++
 1 file changed, 2 insertions(+), 12 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index a816493d37..097cb0f2e2 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -240,7 +240,7 @@ static const char *sd_response_name(sd_rsp_type_t rsp)
 static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 {
 static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
- [4]= "SET_DSR", [5]= "IO_SEND_OP_COND",
+ [5]= "IO_SEND_OP_COND",
  [6]= "SWITCH_FUNC", [7]= "SELECT/DESELECT_CARD",
  [8]= "SEND_IF_COND",[9]= "SEND_CSD",
 [10]= "SEND_CID",   [11]= "VOLTAGE_SWITCH",
@@ -1153,7 +1153,6 @@ static sd_rsp_type_t sd_cmd_illegal(SDState *sd, 
SDRequest req)
 }
 
 /* Commands that are recognised but not yet implemented. */
-__attribute__((unused))
 static sd_rsp_type_t sd_cmd_unimplemented(SDState *sd, SDRequest req)
 {
 qemu_log_mask(LOG_UNIMP, "%s: CMD%i not implemented\n",
@@ -1312,16 +1311,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 
 switch (req.cmd) {
 /* Basic commands (Class 0 and Class 1) */
-case 4:  /* CMD4:   SEND_DSR */
-switch (sd->state) {
-case sd_standby_state:
-break;
-
-default:
-break;
-}
-break;
-
 case 6:  /* CMD6:   SWITCH_FUNCTION */
 if (sd->mode != sd_data_transfer_mode) {
 return sd_invalid_mode_for_cmd(sd, req);
@@ -2289,6 +2278,7 @@ static const SDProto sd_proto_sd = {
 [0]  = {0,  sd_bc,   "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
 [2]  = {0,  sd_bcr,  "ALL_SEND_CID", sd_cmd_ALL_SEND_CID},
 [3]  = {0,  sd_bcr,  "SEND_RELATIVE_ADDR", sd_cmd_SEND_RELATIVE_ADDR},
+[4]  = {0,  sd_bc,   "SEND_DSR", sd_cmd_unimplemented},
 [19] = {2,  sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
 [23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
 },
-- 
2.41.0




[PATCH v42 25/98] hw/sd/sdcard: Convert GEN_CMD to generic_read_byte (CMD56)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 19 +++
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index bf922da2cc..ccf81b9e59 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1648,10 +1648,12 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 switch (sd->state) {
 case sd_transfer_state:
 sd->data_offset = 0;
-if (req.arg & 1)
-sd->state = sd_sendingdata_state;
-else
-sd->state = sd_receivingdata_state;
+if (req.arg & 1) {
+return sd_cmd_to_sendingdata(sd, req, 0,
+ sd->vendor_data,
+ sizeof(sd->vendor_data));
+}
+sd->state = sd_receivingdata_state;
 return sd_r1;
 
 default:
@@ -2137,6 +2139,7 @@ uint8_t sd_read_byte(SDState *sd)
 case 17: /* CMD17:  READ_SINGLE_BLOCK */
 case 19: /* CMD19:  SEND_TUNING_BLOCK (SD) */
 case 30: /* CMD30:  SEND_WRITE_PROT */
+case 56: /* CMD56:  GEN_CMD */
 sd_generic_read_byte(sd, &ret);
 break;
 
@@ -2185,14 +2188,6 @@ uint8_t sd_read_byte(SDState *sd)
 sd->state = sd_transfer_state;
 break;
 
-case 56:  /* CMD56:  GEN_CMD */
-ret = sd->vendor_data[sd->data_offset ++];
-
-if (sd->data_offset >= sizeof(sd->vendor_data)) {
-sd->state = sd_transfer_state;
-}
-break;
-
 default:
 qemu_log_mask(LOG_GUEST_ERROR, "%s: unknown command\n", __func__);
 return 0x00;
-- 
2.41.0




[PATCH v42 35/98] hw/sd/sdcard: Convert GEN_CMD to generic_write_byte (CMD56)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 0cb528b0b2..f9708064d0 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1657,14 +1657,12 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 case 56:  /* CMD56:  GEN_CMD */
 switch (sd->state) {
 case sd_transfer_state:
-sd->data_offset = 0;
 if (req.arg & 1) {
 return sd_cmd_to_sendingdata(sd, req, 0,
  sd->vendor_data,
  sizeof(sd->vendor_data));
 }
-sd->state = sd_receivingdata_state;
-return sd_r1;
+return sd_cmd_to_receivingdata(sd, req, 0, 
sizeof(sd->vendor_data));
 
 default:
 break;
@@ -2109,9 +2107,8 @@ void sd_write_byte(SDState *sd, uint8_t value)
 break;
 
 case 56:  /* CMD56:  GEN_CMD */
-sd->vendor_data[sd->data_offset ++] = value;
-if (sd->data_offset >= sizeof(sd->vendor_data)) {
-sd->state = sd_transfer_state;
+if (sd_generic_write_byte(sd, value)) {
+memcpy(sd->vendor_data, sd->data, sizeof(sd->vendor_data));
 }
 break;
 
-- 
2.41.0




[PATCH v42 20/98] hw/sd/sdcard: Convert SEND_CSD/SEND_CID to generic_read_byte (CMD9 & 10)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 24 ++--
 1 file changed, 6 insertions(+), 18 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index f7735c39a8..8201f3245c 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1312,11 +1312,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 if (!sd_is_spi(sd)) {
 break;
 }
-sd->state = sd_sendingdata_state;
-memcpy(sd->data, sd->csd, 16);
-sd->data_start = sd_req_get_address(sd, req);
-sd->data_offset = 0;
-return sd_r1;
+return sd_cmd_to_sendingdata(sd, req, sd_req_get_address(sd, req),
+ sd->csd, 16);
 
 default:
 break;
@@ -1336,11 +1333,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 if (!sd_is_spi(sd)) {
 break;
 }
-sd->state = sd_sendingdata_state;
-memcpy(sd->data, sd->cid, 16);
-sd->data_start = sd_req_get_address(sd, req);
-sd->data_offset = 0;
-return sd_r1;
+return sd_cmd_to_sendingdata(sd, req, sd_req_get_address(sd, req),
+ sd->cid, 16);
 
 default:
 break;
@@ -2130,15 +2124,9 @@ uint8_t sd_read_byte(SDState *sd)
sd->current_cmd, sd->data_offset, io_len);
 switch (sd->current_cmd) {
 case 6:  /* CMD6:   SWITCH_FUNCTION */
-sd_generic_read_byte(sd, &ret);
-break;
-
 case 9:  /* CMD9:   SEND_CSD */
-case 10:  /* CMD10:  SEND_CID */
-ret = sd->data[sd->data_offset ++];
-
-if (sd->data_offset >= 16)
-sd->state = sd_transfer_state;
+case 10: /* CMD10:  SEND_CID */
+sd_generic_read_byte(sd, &ret);
 break;
 
 case 13:  /* ACMD13: SD_STATUS */
-- 
2.41.0




[PATCH v42 40/98] hw/sd/sdcard: Store command type in SDProto

2024-06-28 Thread Philippe Mathieu-Daudé
Store the command type altogether with the command handler and name.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/sd/sd.h |  5 +++--
 hw/sd/sd.c | 44 
 2 files changed, 23 insertions(+), 26 deletions(-)

diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index 2c8748fb9b..29c76935a0 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -76,8 +76,9 @@ typedef enum  {
 } sd_uhs_mode_t;
 
 typedef enum {
-sd_none = -1,
-sd_bc = 0, /* broadcast -- no response */
+sd_none = 0,
+sd_spi,
+sd_bc, /* broadcast -- no response */
 sd_bcr,/* broadcast with response */
 sd_ac, /* addressed -- no data transfer */
 sd_adtc,   /* addressed with data transfer */
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 97fb3785ee..c4cc48926d 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -95,6 +95,7 @@ typedef sd_rsp_type_t (*sd_cmd_handler)(SDState *sd, 
SDRequest req);
 typedef struct SDProto {
 const char *name;
 struct {
+const sd_cmd_type_t type;
 const char *name;
 sd_cmd_handler handler;
 } cmd[SDMMC_CMD_MAX], acmd[SDMMC_CMD_MAX];
@@ -351,20 +352,6 @@ static void sd_set_mode(SDState *sd)
 }
 }
 
-static const sd_cmd_type_t sd_cmd_type[SDMMC_CMD_MAX] = {
-sd_bc,   sd_none, sd_bcr,  sd_bcr,  sd_none, sd_none, sd_none, sd_ac,
-sd_bcr,  sd_ac,   sd_ac,   sd_adtc, sd_ac,   sd_ac,   sd_none, sd_ac,
-/* 16 */
-sd_ac,   sd_adtc, sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none,
-sd_adtc, sd_adtc, sd_adtc, sd_adtc, sd_ac,   sd_ac,   sd_adtc, sd_none,
-/* 32 */
-sd_ac,   sd_ac,   sd_none, sd_none, sd_none, sd_none, sd_ac,   sd_none,
-sd_none, sd_none, sd_bc,   sd_none, sd_none, sd_none, sd_none, sd_none,
-/* 48 */
-sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_ac,
-sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
-};
-
 static const int sd_cmd_class[SDMMC_CMD_MAX] = {
 0,  0,  0,  0,  0,  9, 10,  0,  0,  0,  0,  1,  0,  0,  0,  0,
 2,  2,  2,  2,  3,  3,  3,  3,  4,  4,  4,  4,  6,  6,  6,  6,
@@ -571,10 +558,19 @@ static void sd_set_rca(SDState *sd, uint16_t value)
 
 static uint16_t sd_req_get_rca(SDState *s, SDRequest req)
 {
-if (sd_cmd_type[req.cmd] == sd_ac || sd_cmd_type[req.cmd] == sd_adtc) {
+switch (s->proto->cmd[req.cmd].type) {
+case sd_none:
+/* Called from legacy code not ported to SDProto array */
+assert(!s->proto->cmd[req.cmd].handler);
+/* fall-through */
+case sd_ac:
+case sd_adtc:
 return req.arg >> 16;
+case sd_spi:
+g_assert_not_reached();
+default:
+return 0;
 }
-return 0;
 }
 
 /* Card Status register */
@@ -2277,22 +2273,22 @@ void sd_enable(SDState *sd, bool enable)
 static const SDProto sd_proto_spi = {
 .name = "SPI",
 .cmd = {
-[0]  = {"GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
-[1]  = {"SEND_OP_COND", spi_cmd_SEND_OP_COND},
+[0]  = {sd_spi, "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
+[1]  = {sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
 },
 .acmd = {
-[41] = {"SEND_OP_COND", spi_cmd_SEND_OP_COND},
+[41] = {sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
 },
 };
 
 static const SDProto sd_proto_sd = {
 .name = "SD",
 .cmd = {
-[0]  = { "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
-[2]  = { "ALL_SEND_CID", sd_cmd_ALL_SEND_CID},
-[3]  = { "SEND_RELATIVE_ADDR", sd_cmd_SEND_RELATIVE_ADDR},
-[19] = { "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
-[23] = { "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
+[0]  = {sd_bc,   "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
+[2]  = {sd_bcr,  "ALL_SEND_CID", sd_cmd_ALL_SEND_CID},
+[3]  = {sd_bcr,  "SEND_RELATIVE_ADDR", sd_cmd_SEND_RELATIVE_ADDR},
+[19] = {sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
+[23] = {sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
 },
 };
 
-- 
2.41.0




[PATCH v42 01/98] hw/sd/sdcard: Deprecate support for spec v1.10

2024-06-28 Thread Philippe Mathieu-Daudé
We use the v2.00 spec by default since commit 2f0939c234
("sdcard: Add a 'spec_version' property, default to Spec v2.00").
Time to deprecate the v1.10 which doesn't bring much, and
is not tested.

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Cédric Le Goater 
---
 docs/about/deprecated.rst | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index ff3da68208..02cdef14aa 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -362,6 +362,12 @@ recommending to switch to their stable counterparts:
 - "Zve64f" should be replaced with "zve64f"
 - "Zve64d" should be replaced with "zve64d"
 
+``-device sd-card,spec_version=1`` (since 9.1)
+^^
+
+SD physical layer specification v2.00 supersedes the v1.10 one.
+v2.00 is the default since QEMU 3.0.0.
+
 Block device options
 
 
-- 
2.41.0




[PATCH v42 19/98] hw/sd/sdcard: Convert SWITCH_FUNCTION to generic_read_byte (CMD6)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 12 ++--
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 1a8d06804d..f7735c39a8 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1086,7 +1086,6 @@ static sd_rsp_type_t sd_cmd_unimplemented(SDState *sd, 
SDRequest req)
 }
 
 /* Configure fields for following sd_generic_read_byte() calls */
-__attribute__((unused))
 static sd_rsp_type_t sd_cmd_to_sendingdata(SDState *sd, SDRequest req,
uint64_t start,
const void *data, size_t size)
@@ -1243,10 +1242,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 }
 
 sd_function_switch(sd, req.arg);
-sd->state = sd_sendingdata_state;
-sd->data_start = 0;
-sd->data_offset = 0;
-return sd_r1;
+return sd_cmd_to_sendingdata(sd, req, 0, NULL, 64);
 
 case 7:  /* CMD7:   SELECT/DESELECT_CARD */
 rca = sd_req_get_rca(sd, req);
@@ -1946,7 +1942,6 @@ send_response:
 }
 
 /* Return true when buffer is consumed. Configured by sd_cmd_to_sendingdata() 
*/
-__attribute__((unused))
 static bool sd_generic_read_byte(SDState *sd, uint8_t *value)
 {
 *value = sd->data[sd->data_offset];
@@ -2135,10 +2130,7 @@ uint8_t sd_read_byte(SDState *sd)
sd->current_cmd, sd->data_offset, io_len);
 switch (sd->current_cmd) {
 case 6:  /* CMD6:   SWITCH_FUNCTION */
-ret = sd->data[sd->data_offset ++];
-
-if (sd->data_offset >= 64)
-sd->state = sd_transfer_state;
+sd_generic_read_byte(sd, &ret);
 break;
 
 case 9:  /* CMD9:   SEND_CSD */
-- 
2.41.0




[PATCH v42 04/98] hw/sd/sdcard: Trace block offset in READ/WRITE data accesses

2024-06-28 Thread Philippe Mathieu-Daudé
Useful to detect out of bound accesses.

Signed-off-by: Philippe Mathieu-Daudé 
Tested-by: Cédric Le Goater 
---
 hw/sd/sd.c | 4 ++--
 hw/sd/trace-events | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index bc87807793..090a6fdcdb 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1917,7 +1917,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
 
 trace_sdcard_write_data(sd_proto(sd)->name,
 sd->last_cmd_name,
-sd->current_cmd, value);
+sd->current_cmd, sd->data_offset, value);
 switch (sd->current_cmd) {
 case 24:  /* CMD24:  WRITE_SINGLE_BLOCK */
 sd->data[sd->data_offset ++] = value;
@@ -2073,7 +2073,7 @@ uint8_t sd_read_byte(SDState *sd)
 
 trace_sdcard_read_data(sd_proto(sd)->name,
sd->last_cmd_name,
-   sd->current_cmd, io_len);
+   sd->current_cmd, sd->data_offset, io_len);
 switch (sd->current_cmd) {
 case 6:  /* CMD6:   SWITCH_FUNCTION */
 ret = sd->data[sd->data_offset ++];
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index 724365efc3..0eee98a646 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -52,8 +52,8 @@ sdcard_lock(void) ""
 sdcard_unlock(void) ""
 sdcard_read_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
 sdcard_write_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
-sdcard_write_data(const char *proto, const char *cmd_desc, uint8_t cmd, 
uint8_t value) "%s %20s/ CMD%02d value 0x%02x"
-sdcard_read_data(const char *proto, const char *cmd_desc, uint8_t cmd, 
uint32_t length) "%s %20s/ CMD%02d len %" PRIu32
+sdcard_write_data(const char *proto, const char *cmd_desc, uint8_t cmd, 
uint32_t offset, uint8_t value) "%s %20s/ CMD%02d ofs %"PRIu32" value 0x%02x"
+sdcard_read_data(const char *proto, const char *cmd_desc, uint8_t cmd, 
uint32_t offset, uint32_t length) "%s %20s/ CMD%02d ofs %"PRIu32" len %" PRIu32
 sdcard_set_voltage(uint16_t millivolts) "%u mV"
 
 # pxa2xx_mmci.c
-- 
2.41.0




[PATCH v42 28/98] hw/sd/sdcard: Convert SEND_SCR to generic_read_byte (ACMD51)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 13 ++---
 1 file changed, 2 insertions(+), 11 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 8d02cd9a26..cd308e9a89 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1785,10 +1785,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 case 51:  /* ACMD51: SEND_SCR */
 switch (sd->state) {
 case sd_transfer_state:
-sd->state = sd_sendingdata_state;
-sd->data_start = 0;
-sd->data_offset = 0;
-return sd_r1;
+return sd_cmd_to_sendingdata(sd, req, 0, sd->scr, sizeof(sd->scr));
 
 default:
 break;
@@ -2138,6 +2135,7 @@ uint8_t sd_read_byte(SDState *sd)
 case 19: /* CMD19:  SEND_TUNING_BLOCK (SD) */
 case 22: /* ACMD22: SEND_NUM_WR_BLOCKS */
 case 30: /* CMD30:  SEND_WRITE_PROT */
+case 51: /* ACMD51: SEND_SCR */
 case 56: /* CMD56:  GEN_CMD */
 sd_generic_read_byte(sd, &ret);
 break;
@@ -2166,13 +2164,6 @@ uint8_t sd_read_byte(SDState *sd)
 }
 break;
 
-case 51:  /* ACMD51: SEND_SCR */
-ret = sd->scr[sd->data_offset ++];
-
-if (sd->data_offset >= sizeof(sd->scr))
-sd->state = sd_transfer_state;
-break;
-
 default:
 qemu_log_mask(LOG_GUEST_ERROR, "%s: unknown command\n", __func__);
 return 0x00;
-- 
2.41.0




[PATCH v42 44/98] hw/sd/sdcard: Register optional handlers from spec v6.00

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 15 ++-
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 74aa38a442..406fadb3b4 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -258,15 +258,11 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 [36]= "SW_FUNC_RSVD",   [37]= "SW_FUNC_RSVD",
 [38]= "ERASE",
 [40]= "DPS_spec",
-[42]= "LOCK_UNLOCK",[43]= "Q_MANAGEMENT",
-[44]= "Q_TASK_INFO_A",  [45]= "Q_TASK_INFO_B",
-[46]= "Q_RD_TASK",  [47]= "Q_WR_TASK",
-[48]= "READ_EXTR_SINGLE",   [49]= "WRITE_EXTR_SINGLE",
+[42]= "LOCK_UNLOCK",
 [50]= "SW_FUNC_RSVD",
 [52]= "IO_RW_DIRECT",   [53]= "IO_RW_EXTENDED",
 [54]= "SDIO_RSVD",  [55]= "APP_CMD",
 [56]= "GEN_CMD",[57]= "SW_FUNC_RSVD",
-[58]= "READ_EXTR_MULTI",[59]= "WRITE_EXTR_MULTI",
 [60]= "MANUF_RSVD", [61]= "MANUF_RSVD",
 [62]= "MANUF_RSVD", [63]= "MANUF_RSVD",
 };
@@ -2291,6 +2287,15 @@ static const SDProto sd_proto_sd = {
 [19] = {2,  sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
 [20] = {2,  sd_ac,   "SPEED_CLASS_CONTROL", sd_cmd_optional},
 [23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
+[43] = {1,  sd_ac,   "Q_MANAGEMENT", sd_cmd_optional},
+[44] = {1,  sd_ac,   "Q_TASK_INFO_A", sd_cmd_optional},
+[45] = {1,  sd_ac,   "Q_TASK_INFO_B", sd_cmd_optional},
+[46] = {1,  sd_adtc, "Q_RD_TASK", sd_cmd_optional},
+[47] = {1,  sd_adtc, "Q_WR_TASK", sd_cmd_optional},
+[48] = {1,  sd_adtc, "READ_EXTR_SINGLE", sd_cmd_optional},
+[49] = {1,  sd_adtc, "WRITE_EXTR_SINGLE", sd_cmd_optional},
+[58] = {11, sd_adtc, "READ_EXTR_MULTI", sd_cmd_optional},
+[59] = {11, sd_adtc, "WRITE_EXTR_MULTI", sd_cmd_optional},
 },
 };
 
-- 
2.41.0




[PATCH v42 22/98] hw/sd/sdcard: Convert READ_SINGLE_BLOCK to generic_read_byte (CMD17)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 18 +++---
 1 file changed, 3 insertions(+), 15 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index dfcb213aa9..605269163d 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1405,11 +1405,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 if (!address_in_range(sd, "READ_SINGLE_BLOCK", addr, sd->blk_len)) 
{
 return sd_r1;
 }
-
-sd->state = sd_sendingdata_state;
-sd->data_start = addr;
-sd->data_offset = 0;
-return sd_r1;
+sd_blk_read(sd, addr, sd->blk_len);
+return sd_cmd_to_sendingdata(sd, req, addr, NULL, sd->blk_len);
 
 default:
 break;
@@ -2144,6 +2141,7 @@ uint8_t sd_read_byte(SDState *sd)
 case 6:  /* CMD6:   SWITCH_FUNCTION */
 case 9:  /* CMD9:   SEND_CSD */
 case 10: /* CMD10:  SEND_CID */
+case 17: /* CMD17:  READ_SINGLE_BLOCK */
 sd_generic_read_byte(sd, &ret);
 break;
 
@@ -2154,16 +2152,6 @@ uint8_t sd_read_byte(SDState *sd)
 sd->state = sd_transfer_state;
 break;
 
-case 17:  /* CMD17:  READ_SINGLE_BLOCK */
-if (sd->data_offset == 0) {
-sd_blk_read(sd, sd->data_start, io_len);
-}
-ret = sd->data[sd->data_offset ++];
-
-if (sd->data_offset >= io_len)
-sd->state = sd_transfer_state;
-break;
-
 case 18:  /* CMD18:  READ_MULTIPLE_BLOCK */
 if (sd->data_offset == 0) {
 if (!address_in_range(sd, "READ_MULTIPLE_BLOCK",
-- 
2.41.0




[PATCH v42 00/98] hw/sd/sdcard: Add eMMC support

2024-06-28 Thread Philippe Mathieu-Daudé
Cédric asked for one big series to review instead of
various tiny ones...

I plan to send a pull request before v9.1 soft freeze
with at least patches 1-81 (prerequisistes before the
"Basis for eMMC support" patch) except qtest patch #15.

Also available as:
https://gitlab.com/philmd/qemu/-/commits/emmc-testing/

Cédric Le Goater (5):
  hw/sd/sdcard: Introduce definitions for EXT_CSD register
  hw/sd/sdcard: Add emmc_cmd_SET_RELATIVE_ADDR() handler
  hw/sd/sdcard: Fix SET_BLOCK_COUNT command argument on eMMC (CMD23)
  hw/sd/sdcard: Adapt sd_cmd_ALL_SEND_CID handler for eMMC (CMD2)
  hw/sd/sdcard: Adapt sd_cmd_APP_CMD handler for eMMC (CMD55)

Joel Stanley (3):
  hw/sd/sdcard: Support boot area in emmc image
  hw/sd/sdcard: Subtract bootarea size from blk
  hw/sd/sdcard: Add boot config support

Luc Michel (1):
  hw/sd/sdcard: Implement eMMC sleep state (CMD5)

Philippe Mathieu-Daudé (85):
  hw/sd/sdcard: Deprecate support for spec v1.10
  hw/sd/sdcard: Use spec v3.01 by default
  hw/sd/sdcard: Track last command used to help logging
  hw/sd/sdcard: Trace block offset in READ/WRITE data accesses
  hw/sd/sdcard: Trace requested address computed by sd_req_get_address()
  hw/sd/sdcard: Do not store vendor data on block drive (CMD56)
  hw/sd/sdcard: Send WRITE_PROT bits MSB first (CMD30)
  hw/sd/sdcard: Send NUM_WR_BLOCKS bits MSB first (ACMD22)
  hw/sd/sdcard: Use READY_FOR_DATA definition instead of magic value
  hw/sd/sdcard: Assign SDCardStates enum values
  hw/sd/sdcard: Simplify sd_inactive_state handling
  hw/sd/sdcard: Restrict SWITCH_FUNCTION to sd_transfer_state (CMD6)
  hw/sd/sdcard: Add direct reference to SDProto in SDState
  hw/sd/sdcard: Extract sd_blk_len() helper
  tests/qtest: Disable npcm7xx_sdhci tests using hardcoded RCA
  hw/sd/sdcard: Generate random RCA value
  hw/sd/sdcard: Introduce sd_cmd_to_sendingdata and sd_generic_read_byte
  hw/sd/sdcard: Convert SWITCH_FUNCTION to generic_read_byte (CMD6)
  hw/sd/sdcard: Convert SEND_CSD/SEND_CID to generic_read_byte (CMD9 &
10)
  hw/sd/sdcard: Duplicate READ_SINGLE_BLOCK / READ_MULTIPLE_BLOCK cases
  hw/sd/sdcard: Convert READ_SINGLE_BLOCK to generic_read_byte (CMD17)
  hw/sd/sdcard: Convert SEND_TUNING_BLOCK to generic_read_byte (CMD19)
  hw/sd/sdcard: Convert SEND_WRITE_PROT to generic_read_byte (CMD30)
  hw/sd/sdcard: Convert GEN_CMD to generic_read_byte (CMD56)
  hw/sd/sdcard: Convert SD_STATUS to generic_read_byte (ACMD13)
  hw/sd/sdcard: Convert SEND_NUM_WR_BLOCKS to generic_read_byte (ACMD22)
  hw/sd/sdcard: Convert SEND_SCR to generic_read_byte (ACMD51)
  hw/sd/sdcard: Introduce sd_cmd_to_receivingdata /
sd_generic_write_byte
  hw/sd/sdcard: Duplicate WRITE_SINGLE_BLOCK / WRITE_MULTIPLE_BLOCK
cases
  hw/sd/sdcard: Convert WRITE_SINGLE_BLOCK to generic_write_byte (CMD24)
  hw/sd/sdcard: Convert PROGRAM_CID to generic_write_byte (CMD26)
  hw/sd/sdcard: Convert PROGRAM_CSD to generic_write_byte (CMD27)
  hw/sd/sdcard: Convert LOCK_UNLOCK to generic_write_byte (CMD42)
  hw/sd/sdcard: Convert GEN_CMD to generic_write_byte (CMD56)
  hw/sd/sdcard: Move sd_[a]cmd_name() methods to sd.c
  hw/sd/sdcard: Pass SDState as argument to sd_[a]cmd_name()
  hw/sd/sdcard: Prepare SDProto to contain more fields
  hw/sd/sdcard: Store command name in SDProto
  hw/sd/sdcard: Store command type in SDProto
  hw/sd/sdcard: Store command class in SDProto
  hw/sd/sdcard: Remove SEND_DSR dead case (CMD4)
  hw/sd/sdcard: Register generic optional handlers (CMD11 and CMD20)
  hw/sd/sdcard: Register optional handlers from spec v6.00
  hw/sd/sdcard: Register SDIO optional handlers
  hw/sd/sdcard: Register Security Extension optional handlers
  hw/sd/sdcard: Add sd_cmd_SWITCH_FUNCTION handler (CMD6)
  hw/sd/sdcard: Add sd_cmd_DE/SELECT_CARD handler (CMD7)
  hw/sd/sdcard: Add sd_cmd_SEND_IF_COND handler (CMD8)
  hw/sd/sdcard: Add sd_cmd_SEND_CSD/CID handlers (CMD9 & CMD10)
  hw/sd/sdcard: Add spi_cmd_SEND_CSD/CID handlers (CMD9 & CMD10)
  hw/sd/sdcard: Add sd_cmd_STOP_TRANSMISSION handler (CMD12)
  hw/sd/sdcard: Add sd_cmd_SEND_STATUS handler (CMD13)
  hw/sd/sdcard: Add sd_cmd_GO_INACTIVE_STATE handler (CMD15)
  hw/sd/sdcard: Add sd_cmd_SET_BLOCKLEN handler (CMD16)
  hw/sd/sdcard: Add sd_cmd_READ_SINGLE_BLOCK handler (CMD17)
  hw/sd/sdcard: Add sd_cmd_WRITE_SINGLE_BLOCK handler (CMD24)
  hw/sd/sdcard: Add sd_cmd_PROGRAM_CSD handler (CMD27)
  hw/sd/sdcard: Add sd_cmd_SET/CLR_WRITE_PROT handler (CMD28 & CMD29)
  hw/sd/sdcard: Add sd_cmd_SEND_WRITE_PROT handler (CMD30)
  hw/sd/sdcard: Add sd_cmd_ERASE_WR_BLK_START/END handlers (CMD32 &
CMD33)
  hw/sd/sdcard: Add sd_cmd_ERASE handler (CMD38)
  hw/sd/sdcard: Add sd_cmd_LOCK_UNLOCK handler (CMD42)
  hw/sd/sdcard: Add sd_cmd_APP_CMD handler (CMD55)
  hw/sd/sdcard: Add sd_cmd_GEN_CMD handler (CMD56)
  hw/sd/sdcard: Add spi_cmd_READ_OCR handler (CMD58)
  hw/sd/sdcard: Add spi_cmd_CRC_ON_OFF handler (CMD59)
  hw/sd/sdcard: Add sd_acmd_SET_BUS_WIDTH handler (ACMD6)
  hw/sd/sdcard: Add sd_acmd_SD_STATUS handler (ACMD

[PATCH v42 30/98] hw/sd/sdcard: Duplicate WRITE_SINGLE_BLOCK / WRITE_MULTIPLE_BLOCK cases

2024-06-28 Thread Philippe Mathieu-Daudé
In order to modify the WRITE_SINGLE_BLOCK case in the
next commit, duplicate it first.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 690a3f275e..5dbfc8000b 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1461,6 +1461,35 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 
 /* Block write commands (Class 4) */
 case 24:  /* CMD24:  WRITE_SINGLE_BLOCK */
+addr = sd_req_get_address(sd, req);
+switch (sd->state) {
+case sd_transfer_state:
+
+if (!address_in_range(sd, "WRITE_SINGLE_BLOCK", addr,
+  sd->blk_len)) {
+return sd_r1;
+}
+
+sd->state = sd_receivingdata_state;
+sd->data_start = addr;
+sd->data_offset = 0;
+
+if (sd->size <= SDSC_MAX_CAPACITY) {
+if (sd_wp_addr(sd, sd->data_start)) {
+sd->card_status |= WP_VIOLATION;
+}
+}
+if (sd->csd[14] & 0x30) {
+sd->card_status |= WP_VIOLATION;
+}
+sd->blk_written = 0;
+return sd_r1;
+
+default:
+break;
+}
+break;
+
 case 25:  /* CMD25:  WRITE_MULTIPLE_BLOCK */
 addr = sd_req_get_address(sd, req);
 switch (sd->state) {
-- 
2.41.0




[PATCH v42 26/98] hw/sd/sdcard: Convert SD_STATUS to generic_read_byte (ACMD13)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 15 ---
 1 file changed, 4 insertions(+), 11 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index ccf81b9e59..1c4811f410 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1703,10 +1703,9 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 case 13:  /* ACMD13: SD_STATUS */
 switch (sd->state) {
 case sd_transfer_state:
-sd->state = sd_sendingdata_state;
-sd->data_start = 0;
-sd->data_offset = 0;
-return sd_r1;
+return sd_cmd_to_sendingdata(sd, req, 0,
+ sd->sd_status,
+ sizeof(sd->sd_status));
 
 default:
 break;
@@ -2136,6 +2135,7 @@ uint8_t sd_read_byte(SDState *sd)
 case 6:  /* CMD6:   SWITCH_FUNCTION */
 case 9:  /* CMD9:   SEND_CSD */
 case 10: /* CMD10:  SEND_CID */
+case 13: /* ACMD13: SD_STATUS */
 case 17: /* CMD17:  READ_SINGLE_BLOCK */
 case 19: /* CMD19:  SEND_TUNING_BLOCK (SD) */
 case 30: /* CMD30:  SEND_WRITE_PROT */
@@ -2143,13 +2143,6 @@ uint8_t sd_read_byte(SDState *sd)
 sd_generic_read_byte(sd, &ret);
 break;
 
-case 13:  /* ACMD13: SD_STATUS */
-ret = sd->sd_status[sd->data_offset ++];
-
-if (sd->data_offset >= sizeof(sd->sd_status))
-sd->state = sd_transfer_state;
-break;
-
 case 18:  /* CMD18:  READ_MULTIPLE_BLOCK */
 if (sd->data_offset == 0) {
 if (!address_in_range(sd, "READ_MULTIPLE_BLOCK",
-- 
2.41.0




[PATCH v42 47/98] hw/sd/sdcard: Add sd_cmd_SWITCH_FUNCTION handler (CMD6)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 29 +
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index e4941cfdab..61c9aff2fb 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -240,7 +240,7 @@ static const char *sd_response_name(sd_rsp_type_t rsp)
 static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 {
 static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
- [6]= "SWITCH_FUNC", [7]= "SELECT/DESELECT_CARD",
+ [7]= "SELECT/DESELECT_CARD",
  [8]= "SEND_IF_COND",[9]= "SEND_CSD",
 [10]= "SEND_CID",
 [12]= "STOP_TRANSMISSION",  [13]= "SEND_STATUS",
@@ -1244,6 +1244,20 @@ static sd_rsp_type_t sd_cmd_SEND_RELATIVE_ADDR(SDState 
*sd, SDRequest req)
 }
 }
 
+/* CMD6 */
+static sd_rsp_type_t sd_cmd_SWITCH_FUNCTION(SDState *sd, SDRequest req)
+{
+if (sd->mode != sd_data_transfer_mode) {
+return sd_invalid_mode_for_cmd(sd, req);
+}
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+
+sd_function_switch(sd, req.arg);
+return sd_cmd_to_sendingdata(sd, req, 0, NULL, 64);
+}
+
 /* CMD19 */
 static sd_rsp_type_t sd_cmd_SEND_TUNING_BLOCK(SDState *sd, SDRequest req)
 {
@@ -1310,17 +1324,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 
 switch (req.cmd) {
 /* Basic commands (Class 0 and Class 1) */
-case 6:  /* CMD6:   SWITCH_FUNCTION */
-if (sd->mode != sd_data_transfer_mode) {
-return sd_invalid_mode_for_cmd(sd, req);
-}
-if (sd->state != sd_transfer_state) {
-return sd_invalid_state_for_cmd(sd, req);
-}
-
-sd_function_switch(sd, req.arg);
-return sd_cmd_to_sendingdata(sd, req, 0, NULL, 64);
-
 case 7:  /* CMD7:   SELECT/DESELECT_CARD */
 rca = sd_req_get_rca(sd, req);
 switch (sd->state) {
@@ -2266,6 +2269,7 @@ static const SDProto sd_proto_spi = {
 [0]  = {0,  sd_spi, "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
 [1]  = {0,  sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
 [5]  = {9,  sd_spi, "IO_SEND_OP_COND", sd_cmd_optional},
+[6]  = {10, sd_spi, "SWITCH_FUNCTION", sd_cmd_SWITCH_FUNCTION},
 [34] = {10, sd_spi, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_spi, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_spi, "SEND_PSI", sd_cmd_optional},
@@ -2288,6 +2292,7 @@ static const SDProto sd_proto_sd = {
 [3]  = {0,  sd_bcr,  "SEND_RELATIVE_ADDR", sd_cmd_SEND_RELATIVE_ADDR},
 [4]  = {0,  sd_bc,   "SEND_DSR", sd_cmd_unimplemented},
 [5]  = {9,  sd_bc,   "IO_SEND_OP_COND", sd_cmd_optional},
+[6]  = {10, sd_adtc, "SWITCH_FUNCTION", sd_cmd_SWITCH_FUNCTION},
 [11] = {0,  sd_ac,   "VOLTAGE_SWITCH", sd_cmd_optional},
 [19] = {2,  sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
 [20] = {2,  sd_ac,   "SPEED_CLASS_CONTROL", sd_cmd_optional},
-- 
2.41.0




[PATCH v42 54/98] hw/sd/sdcard: Add sd_cmd_GO_INACTIVE_STATE handler (CMD15)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 37 +
 1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index bb80d11f87..d7ed8aee73 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -240,7 +240,6 @@ static const char *sd_response_name(sd_rsp_type_t rsp)
 static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 {
 static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
-[15]= "GO_INACTIVE_STATE",
 [16]= "SET_BLOCKLEN",   [17]= "READ_SINGLE_BLOCK",
 [18]= "READ_MULTIPLE_BLOCK",
 [21]= "DPS_spec",
@@ -1402,6 +1401,30 @@ static sd_rsp_type_t sd_cmd_SEND_STATUS(SDState *sd, 
SDRequest req)
 return sd_req_rca_same(sd, req) ? sd_r1 : sd_r0;
 }
 
+/* CMD15 */
+static sd_rsp_type_t sd_cmd_GO_INACTIVE_STATE(SDState *sd, SDRequest req)
+{
+if (sd->mode != sd_data_transfer_mode) {
+return sd_invalid_mode_for_cmd(sd, req);
+}
+switch (sd->state) {
+case sd_standby_state:
+case sd_transfer_state:
+case sd_sendingdata_state:
+case sd_receivingdata_state:
+case sd_programming_state:
+case sd_disconnect_state:
+break;
+default:
+return sd_invalid_state_for_cmd(sd, req);
+}
+if (sd_req_rca_same(sd, req)) {
+sd->state = sd_inactive_state;
+}
+
+return sd_r0;
+}
+
 /* CMD19 */
 static sd_rsp_type_t sd_cmd_SEND_TUNING_BLOCK(SDState *sd, SDRequest req)
 {
@@ -1467,17 +1490,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 }
 
 switch (req.cmd) {
-/* Basic commands (Class 0 and Class 1) */
-case 15:  /* CMD15:  GO_INACTIVE_STATE */
-if (sd->mode != sd_data_transfer_mode) {
-return sd_invalid_mode_for_cmd(sd, req);
-}
-rca = sd_req_get_rca(sd, req);
-if (sd->rca == rca) {
-sd->state = sd_inactive_state;
-}
-return sd_r0;
-
 /* Block read commands (Class 2) */
 case 16:  /* CMD16:  SET_BLOCKLEN */
 switch (sd->state) {
@@ -2324,6 +2336,7 @@ static const SDProto sd_proto_sd = {
 [11] = {0,  sd_ac,   "VOLTAGE_SWITCH", sd_cmd_optional},
 [12] = {0,  sd_ac,   "STOP_TRANSMISSION", sd_cmd_STOP_TRANSMISSION},
 [13] = {0,  sd_ac,   "SEND_STATUS", sd_cmd_SEND_STATUS},
+[15] = {0,  sd_ac,   "GO_INACTIVE_STATE", sd_cmd_GO_INACTIVE_STATE},
 [19] = {2,  sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
 [20] = {2,  sd_ac,   "SPEED_CLASS_CONTROL", sd_cmd_optional},
 [23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
-- 
2.41.0




[PATCH v42 52/98] hw/sd/sdcard: Add sd_cmd_STOP_TRANSMISSION handler (CMD12)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 38 --
 1 file changed, 20 insertions(+), 18 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 564e08709b..1c092ab43c 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -240,7 +240,7 @@ static const char *sd_response_name(sd_rsp_type_t rsp)
 static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 {
 static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
-[12]= "STOP_TRANSMISSION",  [13]= "SEND_STATUS",
+[13]= "SEND_STATUS",
 [15]= "GO_INACTIVE_STATE",
 [16]= "SET_BLOCKLEN",   [17]= "READ_SINGLE_BLOCK",
 [18]= "READ_MULTIPLE_BLOCK",
@@ -1360,6 +1360,23 @@ static sd_rsp_type_t sd_cmd_SEND_CID(SDState *sd, 
SDRequest req)
 return sd_req_rca_same(sd, req) ? sd_r2_i : sd_r0;
 }
 
+/* CMD12 */
+static sd_rsp_type_t sd_cmd_STOP_TRANSMISSION(SDState *sd, SDRequest req)
+{
+switch (sd->state) {
+case sd_sendingdata_state:
+sd->state = sd_transfer_state;
+return sd_r1b;
+case sd_receivingdata_state:
+sd->state = sd_programming_state;
+/* Bzzztt  Operation complete.  */
+sd->state = sd_transfer_state;
+return sd_r1;
+default:
+return sd_invalid_state_for_cmd(sd, req);
+}
+}
+
 /* CMD19 */
 static sd_rsp_type_t sd_cmd_SEND_TUNING_BLOCK(SDState *sd, SDRequest req)
 {
@@ -1426,23 +1443,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 
 switch (req.cmd) {
 /* Basic commands (Class 0 and Class 1) */
-case 12:  /* CMD12:  STOP_TRANSMISSION */
-switch (sd->state) {
-case sd_sendingdata_state:
-sd->state = sd_transfer_state;
-return sd_r1b;
-
-case sd_receivingdata_state:
-sd->state = sd_programming_state;
-/* Bzzztt  Operation complete.  */
-sd->state = sd_transfer_state;
-return sd_r1b;
-
-default:
-break;
-}
-break;
-
 case 13:  /* CMD13:  SEND_STATUS */
 rca = sd_req_get_rca(sd, req);
 if (sd->mode != sd_data_transfer_mode) {
@@ -2278,6 +2278,7 @@ static const SDProto sd_proto_spi = {
 [8]  = {0,  sd_spi, "SEND_IF_COND", sd_cmd_SEND_IF_COND},
 [9]  = {0,  sd_spi, "SEND_CSD", spi_cmd_SEND_CSD},
 [10] = {0,  sd_spi, "SEND_CID", spi_cmd_SEND_CID},
+[12] = {0,  sd_spi, "STOP_TRANSMISSION", sd_cmd_STOP_TRANSMISSION},
 [34] = {10, sd_spi, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_spi, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_spi, "SEND_PSI", sd_cmd_optional},
@@ -2306,6 +2307,7 @@ static const SDProto sd_proto_sd = {
 [9]  = {0,  sd_ac,   "SEND_CSD", sd_cmd_SEND_CSD},
 [10] = {0,  sd_ac,   "SEND_CID", sd_cmd_SEND_CID},
 [11] = {0,  sd_ac,   "VOLTAGE_SWITCH", sd_cmd_optional},
+[12] = {0,  sd_ac,   "STOP_TRANSMISSION", sd_cmd_STOP_TRANSMISSION},
 [19] = {2,  sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
 [20] = {2,  sd_ac,   "SPEED_CLASS_CONTROL", sd_cmd_optional},
 [23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
-- 
2.41.0




[PATCH v42 31/98] hw/sd/sdcard: Convert WRITE_SINGLE_BLOCK to generic_write_byte (CMD24)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 5dbfc8000b..4a03f41086 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1101,7 +1101,6 @@ static sd_rsp_type_t sd_cmd_unimplemented(SDState *sd, 
SDRequest req)
 }
 
 /* Configure fields for following sd_generic_write_byte() calls */
-__attribute__((unused))
 static sd_rsp_type_t sd_cmd_to_receivingdata(SDState *sd, SDRequest req,
  uint64_t start, size_t size)
 {
@@ -1470,10 +1469,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 return sd_r1;
 }
 
-sd->state = sd_receivingdata_state;
-sd->data_start = addr;
-sd->data_offset = 0;
-
 if (sd->size <= SDSC_MAX_CAPACITY) {
 if (sd_wp_addr(sd, sd->data_start)) {
 sd->card_status |= WP_VIOLATION;
@@ -1483,7 +1478,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 sd->card_status |= WP_VIOLATION;
 }
 sd->blk_written = 0;
-return sd_r1;
+return sd_cmd_to_receivingdata(sd, req, addr, sd->blk_len);
 
 default:
 break;
@@ -1999,7 +1994,6 @@ send_response:
 }
 
 /* Return true if buffer is consumed. Configured by sd_cmd_to_receivingdata() 
*/
-__attribute__((unused))
 static bool sd_generic_write_byte(SDState *sd, uint8_t value)
 {
 sd->data[sd->data_offset] = value;
@@ -2045,8 +2039,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
 sd->current_cmd, sd->data_offset, value);
 switch (sd->current_cmd) {
 case 24:  /* CMD24:  WRITE_SINGLE_BLOCK */
-sd->data[sd->data_offset ++] = value;
-if (sd->data_offset >= sd->blk_len) {
+if (sd_generic_write_byte(sd, value)) {
 /* TODO: Check CRC before committing */
 sd->state = sd_programming_state;
 sd_blk_write(sd, sd->data_start, sd->data_offset);
-- 
2.41.0




[PATCH v42 46/98] hw/sd/sdcard: Register Security Extension optional handlers

2024-06-28 Thread Philippe Mathieu-Daudé
See "Advanced Security SD Extension Specification" v2.00.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 17 +
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 87bfd0fd56..e4941cfdab 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -253,14 +253,11 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 [28]= "SET_WRITE_PROT", [29]= "CLR_WRITE_PROT",
 [30]= "SEND_WRITE_PROT",
 [32]= "ERASE_WR_BLK_START", [33]= "ERASE_WR_BLK_END",
-[34]= "SW_FUNC_RSVD",   [35]= "SW_FUNC_RSVD",
-[36]= "SW_FUNC_RSVD",   [37]= "SW_FUNC_RSVD",
 [38]= "ERASE",
 [40]= "DPS_spec",
 [42]= "LOCK_UNLOCK",
-[50]= "SW_FUNC_RSVD",
 [54]= "SDIO_RSVD",  [55]= "APP_CMD",
-[56]= "GEN_CMD",[57]= "SW_FUNC_RSVD",
+[56]= "GEN_CMD",
 [60]= "MANUF_RSVD", [61]= "MANUF_RSVD",
 [62]= "MANUF_RSVD", [63]= "MANUF_RSVD",
 };
@@ -2269,8 +2266,14 @@ static const SDProto sd_proto_spi = {
 [0]  = {0,  sd_spi, "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
 [1]  = {0,  sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
 [5]  = {9,  sd_spi, "IO_SEND_OP_COND", sd_cmd_optional},
+[34] = {10, sd_spi, "READ_SEC_CMD", sd_cmd_optional},
+[35] = {10, sd_spi, "WRITE_SEC_CMD", sd_cmd_optional},
+[36] = {10, sd_spi, "SEND_PSI", sd_cmd_optional},
+[37] = {10, sd_spi, "CONTROL_ASSD_SYSTEM", sd_cmd_optional},
+[50] = {10, sd_spi, "DIRECT_SECURE_READ", sd_cmd_optional},
 [52] = {9,  sd_spi, "IO_RW_DIRECT", sd_cmd_optional},
 [53] = {9,  sd_spi, "IO_RW_EXTENDED", sd_cmd_optional},
+[57] = {10, sd_spi, "DIRECT_SECURE_WRITE", sd_cmd_optional},
 },
 .acmd = {
 [41] = {8,  sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
@@ -2289,6 +2292,10 @@ static const SDProto sd_proto_sd = {
 [19] = {2,  sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
 [20] = {2,  sd_ac,   "SPEED_CLASS_CONTROL", sd_cmd_optional},
 [23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
+[34] = {10, sd_adtc, "READ_SEC_CMD", sd_cmd_optional},
+[35] = {10, sd_adtc, "WRITE_SEC_CMD", sd_cmd_optional},
+[36] = {10, sd_adtc, "SEND_PSI", sd_cmd_optional},
+[37] = {10, sd_ac,   "CONTROL_ASSD_SYSTEM", sd_cmd_optional},
 [43] = {1,  sd_ac,   "Q_MANAGEMENT", sd_cmd_optional},
 [44] = {1,  sd_ac,   "Q_TASK_INFO_A", sd_cmd_optional},
 [45] = {1,  sd_ac,   "Q_TASK_INFO_B", sd_cmd_optional},
@@ -2296,8 +2303,10 @@ static const SDProto sd_proto_sd = {
 [47] = {1,  sd_adtc, "Q_WR_TASK", sd_cmd_optional},
 [48] = {1,  sd_adtc, "READ_EXTR_SINGLE", sd_cmd_optional},
 [49] = {1,  sd_adtc, "WRITE_EXTR_SINGLE", sd_cmd_optional},
+[50] = {10, sd_adtc, "DIRECT_SECURE_READ", sd_cmd_optional},
 [52] = {9,  sd_bc,   "IO_RW_DIRECT", sd_cmd_optional},
 [53] = {9,  sd_bc,   "IO_RW_EXTENDED", sd_cmd_optional},
+[57] = {10, sd_adtc, "DIRECT_SECURE_WRITE", sd_cmd_optional},
 [58] = {11, sd_adtc, "READ_EXTR_MULTI", sd_cmd_optional},
 [59] = {11, sd_adtc, "WRITE_EXTR_MULTI", sd_cmd_optional},
 },
-- 
2.41.0




[PATCH v42 41/98] hw/sd/sdcard: Store command class in SDProto

2024-06-28 Thread Philippe Mathieu-Daudé
Store the command class altogether with the other command
fields (handler, name and type).

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 36 +++-
 1 file changed, 19 insertions(+), 17 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index c4cc48926d..a816493d37 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -95,6 +95,7 @@ typedef sd_rsp_type_t (*sd_cmd_handler)(SDState *sd, 
SDRequest req);
 typedef struct SDProto {
 const char *name;
 struct {
+const unsigned class;
 const sd_cmd_type_t type;
 const char *name;
 sd_cmd_handler handler;
@@ -352,13 +353,6 @@ static void sd_set_mode(SDState *sd)
 }
 }
 
-static const int sd_cmd_class[SDMMC_CMD_MAX] = {
-0,  0,  0,  0,  0,  9, 10,  0,  0,  0,  0,  1,  0,  0,  0,  0,
-2,  2,  2,  2,  3,  3,  3,  3,  4,  4,  4,  4,  6,  6,  6,  6,
-5,  5, 10, 10, 10, 10,  5,  9,  9,  9,  7,  7,  7,  7,  7,  7,
-7,  7, 10,  7,  9,  9,  9,  8,  8, 10,  8,  8,  8,  8,  8,  8,
-};
-
 static uint8_t sd_crc7(const void *message, size_t width)
 {
 int i, bit;
@@ -1306,7 +1300,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 sd->multi_blk_cnt = 0;
 }
 
-if (sd_cmd_class[req.cmd] == 6 && FIELD_EX32(sd->ocr, OCR, CARD_CAPACITY)) 
{
+if (sd->proto->cmd[req.cmd].class == 6 && FIELD_EX32(sd->ocr, OCR,
+ CARD_CAPACITY)) {
 /* Only Standard Capacity cards support class 6 commands */
 return sd_illegal;
 }
@@ -1891,6 +1886,8 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 
 static bool cmd_valid_while_locked(SDState *sd, unsigned cmd)
 {
+unsigned cmd_class;
+
 /* Valid commands in locked state:
  * basic class (0)
  * lock card class (7)
@@ -1905,7 +1902,12 @@ static bool cmd_valid_while_locked(SDState *sd, unsigned 
cmd)
 if (cmd == 16 || cmd == 55) {
 return true;
 }
-return sd_cmd_class[cmd] == 0 || sd_cmd_class[cmd] == 7;
+if (!sd->proto->cmd[cmd].handler) {
+return false;
+}
+cmd_class = sd->proto->cmd[cmd].class;
+
+return cmd_class == 0 || cmd_class == 7;
 }
 
 int sd_do_command(SDState *sd, SDRequest *req,
@@ -2273,22 +2275,22 @@ void sd_enable(SDState *sd, bool enable)
 static const SDProto sd_proto_spi = {
 .name = "SPI",
 .cmd = {
-[0]  = {sd_spi, "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
-[1]  = {sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
+[0]  = {0,  sd_spi, "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
+[1]  = {0,  sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
 },
 .acmd = {
-[41] = {sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
+[41] = {8,  sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
 },
 };
 
 static const SDProto sd_proto_sd = {
 .name = "SD",
 .cmd = {
-[0]  = {sd_bc,   "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
-[2]  = {sd_bcr,  "ALL_SEND_CID", sd_cmd_ALL_SEND_CID},
-[3]  = {sd_bcr,  "SEND_RELATIVE_ADDR", sd_cmd_SEND_RELATIVE_ADDR},
-[19] = {sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
-[23] = {sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
+[0]  = {0,  sd_bc,   "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
+[2]  = {0,  sd_bcr,  "ALL_SEND_CID", sd_cmd_ALL_SEND_CID},
+[3]  = {0,  sd_bcr,  "SEND_RELATIVE_ADDR", sd_cmd_SEND_RELATIVE_ADDR},
+[19] = {2,  sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
+[23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
 },
 };
 
-- 
2.41.0




[PATCH v42 51/98] hw/sd/sdcard: Add spi_cmd_SEND_CSD/CID handlers (CMD9 & CMD10)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 50 --
 1 file changed, 20 insertions(+), 30 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index bd7c7cf518..564e08709b 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1323,6 +1323,15 @@ static sd_rsp_type_t sd_cmd_SEND_IF_COND(SDState *sd, 
SDRequest req)
 }
 
 /* CMD9 */
+static sd_rsp_type_t spi_cmd_SEND_CSD(SDState *sd, SDRequest req)
+{
+if (sd->state != sd_standby_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+return sd_cmd_to_sendingdata(sd, req, sd_req_get_address(sd, req),
+ sd->csd, 16);
+}
+
 static sd_rsp_type_t sd_cmd_SEND_CSD(SDState *sd, SDRequest req)
 {
 if (sd->state != sd_standby_state) {
@@ -1333,6 +1342,15 @@ static sd_rsp_type_t sd_cmd_SEND_CSD(SDState *sd, 
SDRequest req)
 }
 
 /* CMD10 */
+static sd_rsp_type_t spi_cmd_SEND_CID(SDState *sd, SDRequest req)
+{
+if (sd->state != sd_standby_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+return sd_cmd_to_sendingdata(sd, req, sd_req_get_address(sd, req),
+ sd->cid, 16);
+}
+
 static sd_rsp_type_t sd_cmd_SEND_CID(SDState *sd, SDRequest req)
 {
 if (sd->state != sd_standby_state) {
@@ -1408,36 +1426,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 
 switch (req.cmd) {
 /* Basic commands (Class 0 and Class 1) */
-case 9:  /* CMD9:   SEND_CSD */
-rca = sd_req_get_rca(sd, req);
-switch (sd->state) {
-case sd_transfer_state:
-if (!sd_is_spi(sd)) {
-break;
-}
-return sd_cmd_to_sendingdata(sd, req, sd_req_get_address(sd, req),
- sd->csd, 16);
-
-default:
-break;
-}
-break;
-
-case 10:  /* CMD10:  SEND_CID */
-rca = sd_req_get_rca(sd, req);
-switch (sd->state) {
-case sd_transfer_state:
-if (!sd_is_spi(sd)) {
-break;
-}
-return sd_cmd_to_sendingdata(sd, req, sd_req_get_address(sd, req),
- sd->cid, 16);
-
-default:
-break;
-}
-break;
-
 case 12:  /* CMD12:  STOP_TRANSMISSION */
 switch (sd->state) {
 case sd_sendingdata_state:
@@ -2288,6 +2276,8 @@ static const SDProto sd_proto_spi = {
 [5]  = {9,  sd_spi, "IO_SEND_OP_COND", sd_cmd_optional},
 [6]  = {10, sd_spi, "SWITCH_FUNCTION", sd_cmd_SWITCH_FUNCTION},
 [8]  = {0,  sd_spi, "SEND_IF_COND", sd_cmd_SEND_IF_COND},
+[9]  = {0,  sd_spi, "SEND_CSD", spi_cmd_SEND_CSD},
+[10] = {0,  sd_spi, "SEND_CID", spi_cmd_SEND_CID},
 [34] = {10, sd_spi, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_spi, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_spi, "SEND_PSI", sd_cmd_optional},
-- 
2.41.0




[PATCH v42 43/98] hw/sd/sdcard: Register generic optional handlers (CMD11 and CMD20)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 097cb0f2e2..74aa38a442 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -243,12 +243,12 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
  [5]= "IO_SEND_OP_COND",
  [6]= "SWITCH_FUNC", [7]= "SELECT/DESELECT_CARD",
  [8]= "SEND_IF_COND",[9]= "SEND_CSD",
-[10]= "SEND_CID",   [11]= "VOLTAGE_SWITCH",
+[10]= "SEND_CID",
 [12]= "STOP_TRANSMISSION",  [13]= "SEND_STATUS",
 [15]= "GO_INACTIVE_STATE",
 [16]= "SET_BLOCKLEN",   [17]= "READ_SINGLE_BLOCK",
 [18]= "READ_MULTIPLE_BLOCK",
-[20]= "SPEED_CLASS_CONTROL",[21]= "DPS_spec",
+[21]= "DPS_spec",
 [24]= "WRITE_BLOCK",[25]= "WRITE_MULTIPLE_BLOCK",
 [26]= "MANUF_RSVD", [27]= "PROGRAM_CSD",
 [28]= "SET_WRITE_PROT", [29]= "CLR_WRITE_PROT",
@@ -1161,6 +1161,14 @@ static sd_rsp_type_t sd_cmd_unimplemented(SDState *sd, 
SDRequest req)
 return sd_illegal;
 }
 
+static sd_rsp_type_t sd_cmd_optional(SDState *sd, SDRequest req)
+{
+qemu_log_mask(LOG_UNIMP, "%s: Optional CMD%i not implemented\n",
+  sd->proto->name, req.cmd);
+
+return sd_illegal;
+}
+
 /* Configure fields for following sd_generic_write_byte() calls */
 static sd_rsp_type_t sd_cmd_to_receivingdata(SDState *sd, SDRequest req,
  uint64_t start, size_t size)
@@ -2279,7 +2287,9 @@ static const SDProto sd_proto_sd = {
 [2]  = {0,  sd_bcr,  "ALL_SEND_CID", sd_cmd_ALL_SEND_CID},
 [3]  = {0,  sd_bcr,  "SEND_RELATIVE_ADDR", sd_cmd_SEND_RELATIVE_ADDR},
 [4]  = {0,  sd_bc,   "SEND_DSR", sd_cmd_unimplemented},
+[11] = {0,  sd_ac,   "VOLTAGE_SWITCH", sd_cmd_optional},
 [19] = {2,  sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
+[20] = {2,  sd_ac,   "SPEED_CLASS_CONTROL", sd_cmd_optional},
 [23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
 },
 };
-- 
2.41.0




[PATCH v42 33/98] hw/sd/sdcard: Convert PROGRAM_CSD to generic_write_byte (CMD27)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 15 ++-
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index b9c72a0128..bdd5f3486a 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1518,17 +1518,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid));
 
 case 27:  /* CMD27:  PROGRAM_CSD */
-switch (sd->state) {
-case sd_transfer_state:
-sd->state = sd_receivingdata_state;
-sd->data_start = 0;
-sd->data_offset = 0;
-return sd_r1;
-
-default:
-break;
-}
-break;
+return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->csd));
 
 /* Write protection (Class 6) */
 case 28:  /* CMD28:  SET_WRITE_PROT */
@@ -2096,8 +2086,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
 break;
 
 case 27:  /* CMD27:  PROGRAM_CSD */
-sd->data[sd->data_offset ++] = value;
-if (sd->data_offset >= sizeof(sd->csd)) {
+if (sd_generic_write_byte(sd, value)) {
 /* TODO: Check CRC before committing */
 sd->state = sd_programming_state;
 for (i = 0; i < sizeof(sd->csd); i ++)
-- 
2.41.0




[PATCH v42 55/98] hw/sd/sdcard: Add sd_cmd_SET_BLOCKLEN handler (CMD16)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 37 +++--
 1 file changed, 19 insertions(+), 18 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index d7ed8aee73..d731c3df58 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -240,7 +240,7 @@ static const char *sd_response_name(sd_rsp_type_t rsp)
 static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 {
 static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
-[16]= "SET_BLOCKLEN",   [17]= "READ_SINGLE_BLOCK",
+[17]= "READ_SINGLE_BLOCK",
 [18]= "READ_MULTIPLE_BLOCK",
 [21]= "DPS_spec",
 [24]= "WRITE_BLOCK",[25]= "WRITE_MULTIPLE_BLOCK",
@@ -1425,6 +1425,22 @@ static sd_rsp_type_t sd_cmd_GO_INACTIVE_STATE(SDState 
*sd, SDRequest req)
 return sd_r0;
 }
 
+/* CMD16 */
+static sd_rsp_type_t sd_cmd_SET_BLOCKLEN(SDState *sd, SDRequest req)
+{
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+if (req.arg > (1 << HWBLOCK_SHIFT)) {
+sd->card_status |= BLOCK_LEN_ERROR;
+} else {
+trace_sdcard_set_blocklen(req.arg);
+sd->blk_len = req.arg;
+}
+
+return sd_r1;
+}
+
 /* CMD19 */
 static sd_rsp_type_t sd_cmd_SEND_TUNING_BLOCK(SDState *sd, SDRequest req)
 {
@@ -1491,23 +1507,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 
 switch (req.cmd) {
 /* Block read commands (Class 2) */
-case 16:  /* CMD16:  SET_BLOCKLEN */
-switch (sd->state) {
-case sd_transfer_state:
-if (req.arg > (1 << HWBLOCK_SHIFT)) {
-sd->card_status |= BLOCK_LEN_ERROR;
-} else {
-trace_sdcard_set_blocklen(req.arg);
-sd->blk_len = req.arg;
-}
-
-return sd_r1;
-
-default:
-break;
-}
-break;
-
 case 17:  /* CMD17:  READ_SINGLE_BLOCK */
 addr = sd_req_get_address(sd, req);
 switch (sd->state) {
@@ -2306,6 +2305,7 @@ static const SDProto sd_proto_spi = {
 [10] = {0,  sd_spi, "SEND_CID", spi_cmd_SEND_CID},
 [12] = {0,  sd_spi, "STOP_TRANSMISSION", sd_cmd_STOP_TRANSMISSION},
 [13] = {0,  sd_spi, "SEND_STATUS", sd_cmd_SEND_STATUS},
+[16] = {2,  sd_spi, "SET_BLOCKLEN", sd_cmd_SET_BLOCKLEN},
 [34] = {10, sd_spi, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_spi, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_spi, "SEND_PSI", sd_cmd_optional},
@@ -2337,6 +2337,7 @@ static const SDProto sd_proto_sd = {
 [12] = {0,  sd_ac,   "STOP_TRANSMISSION", sd_cmd_STOP_TRANSMISSION},
 [13] = {0,  sd_ac,   "SEND_STATUS", sd_cmd_SEND_STATUS},
 [15] = {0,  sd_ac,   "GO_INACTIVE_STATE", sd_cmd_GO_INACTIVE_STATE},
+[16] = {2,  sd_ac,   "SET_BLOCKLEN", sd_cmd_SET_BLOCKLEN},
 [19] = {2,  sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
 [20] = {2,  sd_ac,   "SPEED_CLASS_CONTROL", sd_cmd_optional},
 [23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
-- 
2.41.0




[PATCH v42 63/98] hw/sd/sdcard: Add sd_cmd_LOCK_UNLOCK handler (CMD42)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 17fec612eb..4d78ac5b59 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -245,7 +245,6 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 [25]= "WRITE_MULTIPLE_BLOCK",
 [26]= "MANUF_RSVD",
 [40]= "DPS_spec",
-[42]= "LOCK_UNLOCK",
 [54]= "SDIO_RSVD",  [55]= "APP_CMD",
 [56]= "GEN_CMD",
 [60]= "MANUF_RSVD", [61]= "MANUF_RSVD",
@@ -1619,6 +1618,12 @@ static sd_rsp_type_t sd_cmd_ERASE(SDState *sd, SDRequest 
req)
 return sd_r1b;
 }
 
+/* CMD42 */
+static sd_rsp_type_t sd_cmd_LOCK_UNLOCK(SDState *sd, SDRequest req)
+{
+return sd_cmd_to_receivingdata(sd, req, 0, 0);
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint16_t rca;
@@ -1707,10 +1712,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 case 26:  /* CMD26:  PROGRAM_CID */
 return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid));
 
-/* Lock card commands (Class 7) */
-case 42:  /* CMD42:  LOCK_UNLOCK */
-return sd_cmd_to_receivingdata(sd, req, 0, 0);
-
 /* Application specific commands (Class 8) */
 case 55:  /* CMD55:  APP_CMD */
 rca = sd_req_get_rca(sd, req);
@@ -2316,6 +2317,7 @@ static const SDProto sd_proto_spi = {
 [36] = {10, sd_spi, "SEND_PSI", sd_cmd_optional},
 [37] = {10, sd_spi, "CONTROL_ASSD_SYSTEM", sd_cmd_optional},
 [38] = {5,  sd_spi, "ERASE", sd_cmd_ERASE},
+[42] = {7,  sd_spi, "LOCK_UNLOCK", sd_cmd_LOCK_UNLOCK},
 [50] = {10, sd_spi, "DIRECT_SECURE_READ", sd_cmd_optional},
 [52] = {9,  sd_spi, "IO_RW_DIRECT", sd_cmd_optional},
 [53] = {9,  sd_spi, "IO_RW_EXTENDED", sd_cmd_optional},
@@ -2360,6 +2362,7 @@ static const SDProto sd_proto_sd = {
 [36] = {10, sd_adtc, "SEND_PSI", sd_cmd_optional},
 [37] = {10, sd_ac,   "CONTROL_ASSD_SYSTEM", sd_cmd_optional},
 [38] = {5,  sd_ac,   "ERASE", sd_cmd_ERASE},
+[42] = {7,  sd_adtc, "LOCK_UNLOCK", sd_cmd_LOCK_UNLOCK},
 [43] = {1,  sd_ac,   "Q_MANAGEMENT", sd_cmd_optional},
 [44] = {1,  sd_ac,   "Q_TASK_INFO_A", sd_cmd_optional},
 [45] = {1,  sd_ac,   "Q_TASK_INFO_B", sd_cmd_optional},
-- 
2.41.0




[PATCH v42 64/98] hw/sd/sdcard: Add sd_cmd_APP_CMD handler (CMD55)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 53 -
 1 file changed, 28 insertions(+), 25 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 4d78ac5b59..5461e56e17 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -245,7 +245,6 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 [25]= "WRITE_MULTIPLE_BLOCK",
 [26]= "MANUF_RSVD",
 [40]= "DPS_spec",
-[54]= "SDIO_RSVD",  [55]= "APP_CMD",
 [56]= "GEN_CMD",
 [60]= "MANUF_RSVD", [61]= "MANUF_RSVD",
 [62]= "MANUF_RSVD", [63]= "MANUF_RSVD",
@@ -1624,9 +1623,34 @@ static sd_rsp_type_t sd_cmd_LOCK_UNLOCK(SDState *sd, 
SDRequest req)
 return sd_cmd_to_receivingdata(sd, req, 0, 0);
 }
 
+/* CMD55 */
+static sd_rsp_type_t sd_cmd_APP_CMD(SDState *sd, SDRequest req)
+{
+switch (sd->state) {
+case sd_ready_state:
+case sd_identification_state:
+case sd_inactive_state:
+return sd_invalid_state_for_cmd(sd, req);
+case sd_idle_state:
+if (!sd_is_spi(sd) && sd_req_get_rca(sd, req) != 0x) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "SD: illegal RCA 0x%04x for APP_CMD\n", req.cmd);
+}
+/* fall-through */
+default:
+break;
+}
+if (!sd_is_spi(sd) && !sd_req_rca_same(sd, req)) {
+return sd_r0;
+}
+sd->expecting_acmd = true;
+sd->card_status |= APP_CMD;
+
+return sd_r1;
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
-uint16_t rca;
 uint64_t addr;
 
 sd->last_cmd_name = sd_cmd_name(sd, req.cmd);
@@ -1713,29 +1737,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid));
 
 /* Application specific commands (Class 8) */
-case 55:  /* CMD55:  APP_CMD */
-rca = sd_req_get_rca(sd, req);
-switch (sd->state) {
-case sd_ready_state:
-case sd_identification_state:
-return sd_illegal;
-case sd_idle_state:
-if (rca) {
-qemu_log_mask(LOG_GUEST_ERROR,
-  "SD: illegal RCA 0x%04x for APP_CMD\n", req.cmd);
-}
-default:
-break;
-}
-if (!sd_is_spi(sd)) {
-if (sd->rca != rca) {
-return sd_r0;
-}
-}
-sd->expecting_acmd = true;
-sd->card_status |= APP_CMD;
-return sd_r1;
-
 case 56:  /* CMD56:  GEN_CMD */
 switch (sd->state) {
 case sd_transfer_state:
@@ -2321,6 +2322,7 @@ static const SDProto sd_proto_spi = {
 [50] = {10, sd_spi, "DIRECT_SECURE_READ", sd_cmd_optional},
 [52] = {9,  sd_spi, "IO_RW_DIRECT", sd_cmd_optional},
 [53] = {9,  sd_spi, "IO_RW_EXTENDED", sd_cmd_optional},
+[55] = {8,  sd_spi, "APP_CMD", sd_cmd_APP_CMD},
 [57] = {10, sd_spi, "DIRECT_SECURE_WRITE", sd_cmd_optional},
 },
 .acmd = {
@@ -2373,6 +2375,7 @@ static const SDProto sd_proto_sd = {
 [50] = {10, sd_adtc, "DIRECT_SECURE_READ", sd_cmd_optional},
 [52] = {9,  sd_bc,   "IO_RW_DIRECT", sd_cmd_optional},
 [53] = {9,  sd_bc,   "IO_RW_EXTENDED", sd_cmd_optional},
+[55] = {8,  sd_ac,   "APP_CMD", sd_cmd_APP_CMD},
 [57] = {10, sd_adtc, "DIRECT_SECURE_WRITE", sd_cmd_optional},
 [58] = {11, sd_adtc, "READ_EXTR_MULTI", sd_cmd_optional},
 [59] = {11, sd_adtc, "WRITE_EXTR_MULTI", sd_cmd_optional},
-- 
2.41.0




[PATCH v42 24/98] hw/sd/sdcard: Convert SEND_WRITE_PROT to generic_read_byte (CMD30)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 17 -
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index eece33194a..bf922da2cc 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1202,6 +1202,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 {
 uint16_t rca;
 uint64_t addr;
+uint32_t data;
 
 sd->last_cmd_name = sd_cmd_name(req.cmd);
 /* CMD55 precedes an ACMD, so we are not interested in tracing it.
@@ -1555,12 +1556,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
   req.arg, sd->blk_len)) {
 return sd_r1;
 }
-
-sd->state = sd_sendingdata_state;
-stl_be_p(sd->data, sd_wpbits(sd, req.arg));
-sd->data_start = addr;
-sd->data_offset = 0;
-return sd_r1;
+data = sd_wpbits(sd, req.arg);
+return sd_cmd_to_sendingdata(sd, req, addr, &data, sizeof(data));
 
 default:
 break;
@@ -2139,6 +2136,7 @@ uint8_t sd_read_byte(SDState *sd)
 case 10: /* CMD10:  SEND_CID */
 case 17: /* CMD17:  READ_SINGLE_BLOCK */
 case 19: /* CMD19:  SEND_TUNING_BLOCK (SD) */
+case 30: /* CMD30:  SEND_WRITE_PROT */
 sd_generic_read_byte(sd, &ret);
 break;
 
@@ -2180,13 +2178,6 @@ uint8_t sd_read_byte(SDState *sd)
 sd->state = sd_transfer_state;
 break;
 
-case 30:  /* CMD30:  SEND_WRITE_PROT */
-ret = sd->data[sd->data_offset ++];
-
-if (sd->data_offset >= 4)
-sd->state = sd_transfer_state;
-break;
-
 case 51:  /* ACMD51: SEND_SCR */
 ret = sd->scr[sd->data_offset ++];
 
-- 
2.41.0




[PATCH v42 50/98] hw/sd/sdcard: Add sd_cmd_SEND_CSD/CID handlers (CMD9 & CMD10)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 36 ++--
 1 file changed, 22 insertions(+), 14 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index e2f7e99ea2..bd7c7cf518 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -240,8 +240,6 @@ static const char *sd_response_name(sd_rsp_type_t rsp)
 static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 {
 static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
- [9]= "SEND_CSD",
-[10]= "SEND_CID",
 [12]= "STOP_TRANSMISSION",  [13]= "SEND_STATUS",
 [15]= "GO_INACTIVE_STATE",
 [16]= "SET_BLOCKLEN",   [17]= "READ_SINGLE_BLOCK",
@@ -1324,6 +1322,26 @@ static sd_rsp_type_t sd_cmd_SEND_IF_COND(SDState *sd, 
SDRequest req)
 return sd_r7;
 }
 
+/* CMD9 */
+static sd_rsp_type_t sd_cmd_SEND_CSD(SDState *sd, SDRequest req)
+{
+if (sd->state != sd_standby_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+
+return sd_req_rca_same(sd, req) ? sd_r2_s : sd_r0;
+}
+
+/* CMD10 */
+static sd_rsp_type_t sd_cmd_SEND_CID(SDState *sd, SDRequest req)
+{
+if (sd->state != sd_standby_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+
+return sd_req_rca_same(sd, req) ? sd_r2_i : sd_r0;
+}
+
 /* CMD19 */
 static sd_rsp_type_t sd_cmd_SEND_TUNING_BLOCK(SDState *sd, SDRequest req)
 {
@@ -1393,12 +1411,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 case 9:  /* CMD9:   SEND_CSD */
 rca = sd_req_get_rca(sd, req);
 switch (sd->state) {
-case sd_standby_state:
-if (sd->rca != rca)
-return sd_r0;
-
-return sd_r2_s;
-
 case sd_transfer_state:
 if (!sd_is_spi(sd)) {
 break;
@@ -1414,12 +1426,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 case 10:  /* CMD10:  SEND_CID */
 rca = sd_req_get_rca(sd, req);
 switch (sd->state) {
-case sd_standby_state:
-if (sd->rca != rca)
-return sd_r0;
-
-return sd_r2_i;
-
 case sd_transfer_state:
 if (!sd_is_spi(sd)) {
 break;
@@ -2307,6 +2313,8 @@ static const SDProto sd_proto_sd = {
 [6]  = {10, sd_adtc, "SWITCH_FUNCTION", sd_cmd_SWITCH_FUNCTION},
 [7]  = {0,  sd_ac,   "(DE)SELECT_CARD", sd_cmd_DE_SELECT_CARD},
 [8]  = {0,  sd_bcr,  "SEND_IF_COND", sd_cmd_SEND_IF_COND},
+[9]  = {0,  sd_ac,   "SEND_CSD", sd_cmd_SEND_CSD},
+[10] = {0,  sd_ac,   "SEND_CID", sd_cmd_SEND_CID},
 [11] = {0,  sd_ac,   "VOLTAGE_SWITCH", sd_cmd_optional},
 [19] = {2,  sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
 [20] = {2,  sd_ac,   "SPEED_CLASS_CONTROL", sd_cmd_optional},
-- 
2.41.0




[PATCH v42 83/98] hw/sd/sdcard: Register generic command handlers

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 249fad0468..ebcd8c1e43 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -2383,6 +2383,28 @@ static const SDProto sd_proto_emmc = {
 /* Only v4.5 is supported */
 .name = "eMMC",
 .cmd = {
+[0]  = {0,  sd_bc,   "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
+[2]  = {0,  sd_bcr,  "ALL_SEND_CID", sd_cmd_ALL_SEND_CID},
+[7]  = {0,  sd_ac,   "(DE)SELECT_CARD", sd_cmd_DE_SELECT_CARD},
+[9]  = {0,  sd_ac,   "SEND_CSD", sd_cmd_SEND_CSD},
+[10] = {0,  sd_ac,   "SEND_CID", sd_cmd_SEND_CID},
+[12] = {0,  sd_ac,   "STOP_TRANSMISSION", sd_cmd_STOP_TRANSMISSION},
+[13] = {0,  sd_ac,   "SEND_STATUS", sd_cmd_SEND_STATUS},
+[15] = {0,  sd_ac,   "GO_INACTIVE_STATE", sd_cmd_GO_INACTIVE_STATE},
+[16] = {2,  sd_ac,   "SET_BLOCKLEN", sd_cmd_SET_BLOCKLEN},
+[17] = {2,  sd_adtc, "READ_SINGLE_BLOCK", sd_cmd_READ_SINGLE_BLOCK},
+[23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
+[24] = {4,  sd_adtc, "WRITE_SINGLE_BLOCK", sd_cmd_WRITE_SINGLE_BLOCK},
+[27] = {4,  sd_adtc, "PROGRAM_CSD", sd_cmd_PROGRAM_CSD},
+[28] = {6,  sd_ac,   "SET_WRITE_PROT", sd_cmd_SET_WRITE_PROT},
+[29] = {6,  sd_ac,   "CLR_WRITE_PROT", sd_cmd_CLR_WRITE_PROT},
+[30] = {6,  sd_adtc, "SEND_WRITE_PROT", sd_cmd_SEND_WRITE_PROT},
+[35] = {5,  sd_ac,   "ERASE_WR_BLK_START", sd_cmd_ERASE_WR_BLK_START},
+[36] = {5,  sd_ac,   "ERASE_WR_BLK_END", sd_cmd_ERASE_WR_BLK_END},
+[38] = {5,  sd_ac,   "ERASE", sd_cmd_ERASE},
+[42] = {7,  sd_adtc, "LOCK_UNLOCK", sd_cmd_LOCK_UNLOCK},
+[55] = {8,  sd_ac,   "APP_CMD", sd_cmd_APP_CMD},
+[56] = {8,  sd_adtc, "GEN_CMD", sd_cmd_GEN_CMD},
 },
 };
 
-- 
2.41.0




[RFC PATCH v42 90/98] hw/sd/sdcard: Add experimental 'x-aspeed-emmc-kludge' property

2024-06-28 Thread Philippe Mathieu-Daudé
When booting U-boot/Linux on Aspeed boards via eMMC,
some commands don't behave as expected from the spec.

Add the 'x-aspeed-emmc-kludge' property to allow non
standard uses until we figure out the reasons.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index bd77853419..dc692fe1fa 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -127,6 +127,7 @@ struct SDState {
 
 uint8_t spec_version;
 BlockBackend *blk;
+bool aspeed_emmc_kludge;
 
 const SDProto *proto;
 
@@ -2567,6 +2568,8 @@ static Property sd_properties[] = {
 DEFINE_PROP_UINT8("spec_version", SDState,
   spec_version, SD_PHY_SPECv3_01_VERS),
 DEFINE_PROP_DRIVE("drive", SDState, blk),
+DEFINE_PROP_BOOL("x-aspeed-emmc-kludge", SDState,
+ aspeed_emmc_kludge, false),
 /* We do not model the chip select pin, so allow the board to select
  * whether card should be in SSI or MMC/SD mode.  It is also up to the
  * board to ensure that ssi transfers only occur when the chip select
-- 
2.41.0




[PATCH v42 39/98] hw/sd/sdcard: Store command name in SDProto

2024-06-28 Thread Philippe Mathieu-Daudé
We already have a const array where command handlers
are listed. Store the command name there too.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 35 ++-
 1 file changed, 22 insertions(+), 13 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 558c39419d..97fb3785ee 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -95,6 +95,7 @@ typedef sd_rsp_type_t (*sd_cmd_handler)(SDState *sd, 
SDRequest req);
 typedef struct SDProto {
 const char *name;
 struct {
+const char *name;
 sd_cmd_handler handler;
 } cmd[SDMMC_CMD_MAX], acmd[SDMMC_CMD_MAX];
 } SDProto;
@@ -237,8 +238,6 @@ static const char *sd_response_name(sd_rsp_type_t rsp)
 static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 {
 static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
- [0]= "GO_IDLE_STATE",   [1]= "SEND_OP_COND",
- [2]= "ALL_SEND_CID",[3]= "SEND_RELATIVE_ADDR",
  [4]= "SET_DSR", [5]= "IO_SEND_OP_COND",
  [6]= "SWITCH_FUNC", [7]= "SELECT/DESELECT_CARD",
  [8]= "SEND_IF_COND",[9]= "SEND_CSD",
@@ -246,9 +245,8 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 [12]= "STOP_TRANSMISSION",  [13]= "SEND_STATUS",
 [15]= "GO_INACTIVE_STATE",
 [16]= "SET_BLOCKLEN",   [17]= "READ_SINGLE_BLOCK",
-[18]= "READ_MULTIPLE_BLOCK",[19]= "SEND_TUNING_BLOCK",
+[18]= "READ_MULTIPLE_BLOCK",
 [20]= "SPEED_CLASS_CONTROL",[21]= "DPS_spec",
-[23]= "SET_BLOCK_COUNT",
 [24]= "WRITE_BLOCK",[25]= "WRITE_MULTIPLE_BLOCK",
 [26]= "MANUF_RSVD", [27]= "PROGRAM_CSD",
 [28]= "SET_WRITE_PROT", [29]= "CLR_WRITE_PROT",
@@ -270,6 +268,12 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 [60]= "MANUF_RSVD", [61]= "MANUF_RSVD",
 [62]= "MANUF_RSVD", [63]= "MANUF_RSVD",
 };
+const SDProto *sdp = sd->proto;
+
+if (sdp->cmd[cmd].handler) {
+assert(!cmd_abbrev[cmd]);
+return sdp->cmd[cmd].name;
+}
 return cmd_abbrev[cmd] ? cmd_abbrev[cmd] : "UNKNOWN_CMD";
 }
 
@@ -282,7 +286,6 @@ static const char *sd_acmd_name(SDState *sd, uint8_t cmd)
 [16] = "DPS_spec",
 [18] = "SECU_spec",
 [22] = "SEND_NUM_WR_BLOCKS",[23] = "SET_WR_BLK_ERASE_COUNT",
-[41] = "SD_SEND_OP_COND",
 [42] = "SET_CLR_CARD_DETECT",
 [51] = "SEND_SCR",
 [52] = "SECU_spec", [53] = "SECU_spec",
@@ -290,6 +293,12 @@ static const char *sd_acmd_name(SDState *sd, uint8_t cmd)
 [56] = "SECU_spec", [57] = "SECU_spec",
 [58] = "SECU_spec", [59] = "SECU_spec",
 };
+const SDProto *sdp = sd->proto;
+
+if (sdp->acmd[cmd].handler) {
+assert(!acmd_abbrev[cmd]);
+return sdp->acmd[cmd].name;
+}
 
 return acmd_abbrev[cmd] ? acmd_abbrev[cmd] : "UNKNOWN_ACMD";
 }
@@ -2268,22 +2277,22 @@ void sd_enable(SDState *sd, bool enable)
 static const SDProto sd_proto_spi = {
 .name = "SPI",
 .cmd = {
-[0]  = {sd_cmd_GO_IDLE_STATE},
-[1]  = {spi_cmd_SEND_OP_COND},
+[0]  = {"GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
+[1]  = {"SEND_OP_COND", spi_cmd_SEND_OP_COND},
 },
 .acmd = {
-[41] = {spi_cmd_SEND_OP_COND},
+[41] = {"SEND_OP_COND", spi_cmd_SEND_OP_COND},
 },
 };
 
 static const SDProto sd_proto_sd = {
 .name = "SD",
 .cmd = {
-[0]  = {sd_cmd_GO_IDLE_STATE},
-[2]  = {sd_cmd_ALL_SEND_CID},
-[3]  = {sd_cmd_SEND_RELATIVE_ADDR},
-[19] = {sd_cmd_SEND_TUNING_BLOCK},
-[23] = {sd_cmd_SET_BLOCK_COUNT},
+[0]  = { "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
+[2]  = { "ALL_SEND_CID", sd_cmd_ALL_SEND_CID},
+[3]  = { "SEND_RELATIVE_ADDR", sd_cmd_SEND_RELATIVE_ADDR},
+[19] = { "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
+[23] = { "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
 },
 };
 
-- 
2.41.0




[PATCH v42 58/98] hw/sd/sdcard: Add sd_cmd_PROGRAM_CSD handler (CMD27)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 4650d20ee7..9d33113f11 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -243,7 +243,7 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 [18]= "READ_MULTIPLE_BLOCK",
 [21]= "DPS_spec",
 [25]= "WRITE_MULTIPLE_BLOCK",
-[26]= "MANUF_RSVD", [27]= "PROGRAM_CSD",
+[26]= "MANUF_RSVD",
 [28]= "SET_WRITE_PROT", [29]= "CLR_WRITE_PROT",
 [30]= "SEND_WRITE_PROT",
 [32]= "ERASE_WR_BLK_START", [33]= "ERASE_WR_BLK_END",
@@ -1514,6 +1514,12 @@ static sd_rsp_type_t sd_cmd_WRITE_SINGLE_BLOCK(SDState 
*sd, SDRequest req)
 return sd_cmd_to_receivingdata(sd, req, addr, sd->blk_len);
 }
 
+/* CMD27 */
+static sd_rsp_type_t sd_cmd_PROGRAM_CSD(SDState *sd, SDRequest req)
+{
+return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->csd));
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint16_t rca;
@@ -1603,9 +1609,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 case 26:  /* CMD26:  PROGRAM_CID */
 return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid));
 
-case 27:  /* CMD27:  PROGRAM_CSD */
-return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->csd));
-
 /* Write protection (Class 6) */
 case 28:  /* CMD28:  SET_WRITE_PROT */
 if (sd->size > SDSC_MAX_CAPACITY) {
@@ -2310,6 +2313,7 @@ static const SDProto sd_proto_spi = {
 [16] = {2,  sd_spi, "SET_BLOCKLEN", sd_cmd_SET_BLOCKLEN},
 [17] = {2,  sd_spi, "READ_SINGLE_BLOCK", sd_cmd_READ_SINGLE_BLOCK},
 [24] = {4,  sd_spi, "WRITE_SINGLE_BLOCK", sd_cmd_WRITE_SINGLE_BLOCK},
+[27] = {4,  sd_spi, "PROGRAM_CSD", sd_cmd_PROGRAM_CSD},
 [34] = {10, sd_spi, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_spi, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_spi, "SEND_PSI", sd_cmd_optional},
@@ -2347,6 +2351,7 @@ static const SDProto sd_proto_sd = {
 [20] = {2,  sd_ac,   "SPEED_CLASS_CONTROL", sd_cmd_optional},
 [23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
 [24] = {4,  sd_adtc, "WRITE_SINGLE_BLOCK", sd_cmd_WRITE_SINGLE_BLOCK},
+[27] = {4,  sd_adtc, "PROGRAM_CSD", sd_cmd_PROGRAM_CSD},
 [34] = {10, sd_adtc, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_adtc, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_adtc, "SEND_PSI", sd_cmd_optional},
-- 
2.41.0




[PATCH v42 60/98] hw/sd/sdcard: Add sd_cmd_SEND_WRITE_PROT handler (CMD30)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 47 +--
 1 file changed, 25 insertions(+), 22 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index a63213613b..bf9975e9b1 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -244,7 +244,6 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 [21]= "DPS_spec",
 [25]= "WRITE_MULTIPLE_BLOCK",
 [26]= "MANUF_RSVD",
-[30]= "SEND_WRITE_PROT",
 [32]= "ERASE_WR_BLK_START", [33]= "ERASE_WR_BLK_END",
 [38]= "ERASE",
 [40]= "DPS_spec",
@@ -1561,11 +1560,33 @@ static sd_rsp_type_t sd_cmd_CLR_WRITE_PROT(SDState *sd, 
SDRequest req)
 return sd_cmd_SET_CLR_WRITE_PROT(sd, req, false);
 }
 
+/* CMD30 */
+static sd_rsp_type_t sd_cmd_SEND_WRITE_PROT(SDState *sd, SDRequest req)
+{
+uint64_t addr;
+uint32_t data;
+
+if (sd->size > SDSC_MAX_CAPACITY) {
+return sd_illegal;
+}
+
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+
+addr = sd_req_get_address(sd, req);
+if (!address_in_range(sd, "SEND_WRITE_PROT", addr, sd->blk_len)) {
+return sd_r1;
+}
+
+data = sd_wpbits(sd, req.arg);
+return sd_cmd_to_sendingdata(sd, req, addr, &data, sizeof(data));
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint16_t rca;
 uint64_t addr;
-uint32_t data;
 
 sd->last_cmd_name = sd_cmd_name(sd, req.cmd);
 /* CMD55 precedes an ACMD, so we are not interested in tracing it.
@@ -1650,26 +1671,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 case 26:  /* CMD26:  PROGRAM_CID */
 return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid));
 
-/* Write protection (Class 6) */
-case 30:  /* CMD30:  SEND_WRITE_PROT */
-if (sd->size > SDSC_MAX_CAPACITY) {
-return sd_illegal;
-}
-addr = sd_req_get_address(sd, req);
-switch (sd->state) {
-case sd_transfer_state:
-if (!address_in_range(sd, "SEND_WRITE_PROT",
-  req.arg, sd->blk_len)) {
-return sd_r1;
-}
-data = sd_wpbits(sd, req.arg);
-return sd_cmd_to_sendingdata(sd, req, addr, &data, sizeof(data));
-
-default:
-break;
-}
-break;
-
 /* Erase commands (Class 5) */
 case 32:  /* CMD32:  ERASE_WR_BLK_START */
 switch (sd->state) {
@@ -2313,6 +2314,7 @@ static const SDProto sd_proto_spi = {
 [27] = {4,  sd_spi, "PROGRAM_CSD", sd_cmd_PROGRAM_CSD},
 [28] = {6,  sd_spi, "SET_WRITE_PROT", sd_cmd_SET_WRITE_PROT},
 [29] = {6,  sd_spi, "CLR_WRITE_PROT", sd_cmd_CLR_WRITE_PROT},
+[30] = {6,  sd_spi, "SEND_WRITE_PROT", sd_cmd_SEND_WRITE_PROT},
 [34] = {10, sd_spi, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_spi, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_spi, "SEND_PSI", sd_cmd_optional},
@@ -2353,6 +2355,7 @@ static const SDProto sd_proto_sd = {
 [27] = {4,  sd_adtc, "PROGRAM_CSD", sd_cmd_PROGRAM_CSD},
 [28] = {6,  sd_ac,   "SET_WRITE_PROT", sd_cmd_SET_WRITE_PROT},
 [29] = {6,  sd_ac,   "CLR_WRITE_PROT", sd_cmd_CLR_WRITE_PROT},
+[30] = {6,  sd_adtc, "SEND_WRITE_PROT", sd_cmd_SEND_WRITE_PROT},
 [34] = {10, sd_adtc, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_adtc, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_adtc, "SEND_PSI", sd_cmd_optional},
-- 
2.41.0




[PATCH v42 89/98] hw/sd/sdcard: Implement eMMC sleep state (CMD5)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Luc Michel 

The JEDEC standards specifies a sleep state where the eMMC won't answer
any command appart from RESET and WAKEUP and go to low power state.
Implement this state and the corresponding command number 5.

Signed-off-by: Luc Michel 
Signed-off-by: Francisco Iglesias 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 47 +--
 1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 0f9bab105e..bd77853419 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1182,8 +1182,19 @@ static sd_rsp_type_t sd_cmd_to_sendingdata(SDState *sd, 
SDRequest req,
 /* CMD0 */
 static sd_rsp_type_t sd_cmd_GO_IDLE_STATE(SDState *sd, SDRequest req)
 {
-sd->state = sd_idle_state;
-sd_reset(DEVICE(sd));
+if (sd->state == sd_sleep_state) {
+switch (req.arg) {
+case 0x:
+case 0xf0f0f0f0:
+break;
+default:
+return sd_r0;
+}
+}
+if (sd->state != sd_inactive_state) {
+sd->state = sd_idle_state;
+sd_reset(DEVICE(sd));
+}
 
 return sd_is_spi(sd) ? sd_r1 : sd_r0;
 }
@@ -1246,6 +1257,30 @@ static sd_rsp_type_t emmc_cmd_SET_RELATIVE_ADDR(SDState 
*sd, SDRequest req)
 }
 }
 
+/* CMD5 */
+static sd_rsp_type_t emmc_cmd_sleep_awake(SDState *sd, SDRequest req)
+{
+bool do_sleep = extract32(req.arg, 15, 1);
+
+switch (sd->state) {
+case sd_sleep_state:
+if (!do_sleep) {
+/* Awake */
+sd->state = sd_standby_state;
+}
+return sd_r1b;
+
+case sd_standby_state:
+if (do_sleep) {
+sd->state = sd_sleep_state;
+}
+return sd_r1b;
+
+default:
+return sd_invalid_state_for_cmd(sd, req);
+}
+}
+
 /* CMD6 */
 static sd_rsp_type_t sd_cmd_SWITCH_FUNCTION(SDState *sd, SDRequest req)
 {
@@ -1648,6 +1683,7 @@ static sd_rsp_type_t sd_cmd_APP_CMD(SDState *sd, 
SDRequest req)
 case sd_ready_state:
 case sd_identification_state:
 case sd_inactive_state:
+case sd_sleep_state:
 return sd_invalid_state_for_cmd(sd, req);
 case sd_idle_state:
 if (!sd_is_spi(sd) && sd_req_get_rca(sd, req) != 0x) {
@@ -1969,6 +2005,12 @@ int sd_do_command(SDState *sd, SDRequest *req,
 req->cmd &= 0x3f;
 }
 
+if (sd->state == sd_sleep_state && req->cmd) {
+qemu_log_mask(LOG_GUEST_ERROR, "SD: Card is sleeping\n");
+rtype = sd_r0;
+goto send_response;
+}
+
 if (sd->card_status & CARD_IS_LOCKED) {
 if (!cmd_valid_while_locked(sd, req->cmd)) {
 sd->card_status |= ILLEGAL_COMMAND;
@@ -2420,6 +2462,7 @@ static const SDProto sd_proto_emmc = {
 [2]  = {0,  sd_bcr,  "ALL_SEND_CID", sd_cmd_ALL_SEND_CID},
 [3]  = {0,  sd_ac,   "SET_RELATIVE_ADDR", emmc_cmd_SET_RELATIVE_ADDR},
 [4]  = {0,  sd_bc,   "SEND_DSR", sd_cmd_unimplemented},
+[5]  = {0,  sd_ac,   "SLEEP/AWAKE", emmc_cmd_sleep_awake},
 [7]  = {0,  sd_ac,   "(DE)SELECT_CARD", sd_cmd_DE_SELECT_CARD},
 [9]  = {0,  sd_ac,   "SEND_CSD", sd_cmd_SEND_CSD},
 [10] = {0,  sd_ac,   "SEND_CID", sd_cmd_SEND_CID},
-- 
2.41.0




[PATCH v42 61/98] hw/sd/sdcard: Add sd_cmd_ERASE_WR_BLK_START/END handlers (CMD32 & CMD33)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 47 ---
 1 file changed, 24 insertions(+), 23 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index bf9975e9b1..4e31dfe18f 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -244,7 +244,6 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 [21]= "DPS_spec",
 [25]= "WRITE_MULTIPLE_BLOCK",
 [26]= "MANUF_RSVD",
-[32]= "ERASE_WR_BLK_START", [33]= "ERASE_WR_BLK_END",
 [38]= "ERASE",
 [40]= "DPS_spec",
 [42]= "LOCK_UNLOCK",
@@ -1583,6 +1582,26 @@ static sd_rsp_type_t sd_cmd_SEND_WRITE_PROT(SDState *sd, 
SDRequest req)
 return sd_cmd_to_sendingdata(sd, req, addr, &data, sizeof(data));
 }
 
+/* CMD32 */
+static sd_rsp_type_t sd_cmd_ERASE_WR_BLK_START(SDState *sd, SDRequest req)
+{
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+sd->erase_start = req.arg;
+return sd_r1;
+}
+
+/* CMD33 */
+static sd_rsp_type_t sd_cmd_ERASE_WR_BLK_END(SDState *sd, SDRequest req)
+{
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+sd->erase_end = req.arg;
+return sd_r1;
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint16_t rca;
@@ -1672,28 +1691,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid));
 
 /* Erase commands (Class 5) */
-case 32:  /* CMD32:  ERASE_WR_BLK_START */
-switch (sd->state) {
-case sd_transfer_state:
-sd->erase_start = req.arg;
-return sd_r1;
-
-default:
-break;
-}
-break;
-
-case 33:  /* CMD33:  ERASE_WR_BLK_END */
-switch (sd->state) {
-case sd_transfer_state:
-sd->erase_end = req.arg;
-return sd_r1;
-
-default:
-break;
-}
-break;
-
 case 38:  /* CMD38:  ERASE */
 switch (sd->state) {
 case sd_transfer_state:
@@ -2315,6 +2312,8 @@ static const SDProto sd_proto_spi = {
 [28] = {6,  sd_spi, "SET_WRITE_PROT", sd_cmd_SET_WRITE_PROT},
 [29] = {6,  sd_spi, "CLR_WRITE_PROT", sd_cmd_CLR_WRITE_PROT},
 [30] = {6,  sd_spi, "SEND_WRITE_PROT", sd_cmd_SEND_WRITE_PROT},
+[32] = {5,  sd_spi, "ERASE_WR_BLK_START", sd_cmd_ERASE_WR_BLK_START},
+[33] = {5,  sd_spi, "ERASE_WR_BLK_END", sd_cmd_ERASE_WR_BLK_END},
 [34] = {10, sd_spi, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_spi, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_spi, "SEND_PSI", sd_cmd_optional},
@@ -2356,6 +2355,8 @@ static const SDProto sd_proto_sd = {
 [28] = {6,  sd_ac,   "SET_WRITE_PROT", sd_cmd_SET_WRITE_PROT},
 [29] = {6,  sd_ac,   "CLR_WRITE_PROT", sd_cmd_CLR_WRITE_PROT},
 [30] = {6,  sd_adtc, "SEND_WRITE_PROT", sd_cmd_SEND_WRITE_PROT},
+[32] = {5,  sd_ac,   "ERASE_WR_BLK_START", sd_cmd_ERASE_WR_BLK_START},
+[33] = {5,  sd_ac,   "ERASE_WR_BLK_END", sd_cmd_ERASE_WR_BLK_END},
 [34] = {10, sd_adtc, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_adtc, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_adtc, "SEND_PSI", sd_cmd_optional},
-- 
2.41.0




[PATCH v42 62/98] hw/sd/sdcard: Add sd_cmd_ERASE handler (CMD38)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 41 -
 1 file changed, 20 insertions(+), 21 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 4e31dfe18f..17fec612eb 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -244,7 +244,6 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 [21]= "DPS_spec",
 [25]= "WRITE_MULTIPLE_BLOCK",
 [26]= "MANUF_RSVD",
-[38]= "ERASE",
 [40]= "DPS_spec",
 [42]= "LOCK_UNLOCK",
 [54]= "SDIO_RSVD",  [55]= "APP_CMD",
@@ -1602,6 +1601,24 @@ static sd_rsp_type_t sd_cmd_ERASE_WR_BLK_END(SDState 
*sd, SDRequest req)
 return sd_r1;
 }
 
+/* CMD38 */
+static sd_rsp_type_t sd_cmd_ERASE(SDState *sd, SDRequest req)
+{
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+if (sd->csd[14] & 0x30) {
+sd->card_status |= WP_VIOLATION;
+return sd_r1b;
+}
+
+sd->state = sd_programming_state;
+sd_erase(sd);
+/* Bzzztt  Operation complete.  */
+sd->state = sd_transfer_state;
+return sd_r1b;
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint16_t rca;
@@ -1690,26 +1707,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 case 26:  /* CMD26:  PROGRAM_CID */
 return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid));
 
-/* Erase commands (Class 5) */
-case 38:  /* CMD38:  ERASE */
-switch (sd->state) {
-case sd_transfer_state:
-if (sd->csd[14] & 0x30) {
-sd->card_status |= WP_VIOLATION;
-return sd_r1b;
-}
-
-sd->state = sd_programming_state;
-sd_erase(sd);
-/* Bzzztt  Operation complete.  */
-sd->state = sd_transfer_state;
-return sd_r1b;
-
-default:
-break;
-}
-break;
-
 /* Lock card commands (Class 7) */
 case 42:  /* CMD42:  LOCK_UNLOCK */
 return sd_cmd_to_receivingdata(sd, req, 0, 0);
@@ -2318,6 +2315,7 @@ static const SDProto sd_proto_spi = {
 [35] = {10, sd_spi, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_spi, "SEND_PSI", sd_cmd_optional},
 [37] = {10, sd_spi, "CONTROL_ASSD_SYSTEM", sd_cmd_optional},
+[38] = {5,  sd_spi, "ERASE", sd_cmd_ERASE},
 [50] = {10, sd_spi, "DIRECT_SECURE_READ", sd_cmd_optional},
 [52] = {9,  sd_spi, "IO_RW_DIRECT", sd_cmd_optional},
 [53] = {9,  sd_spi, "IO_RW_EXTENDED", sd_cmd_optional},
@@ -2361,6 +2359,7 @@ static const SDProto sd_proto_sd = {
 [35] = {10, sd_adtc, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_adtc, "SEND_PSI", sd_cmd_optional},
 [37] = {10, sd_ac,   "CONTROL_ASSD_SYSTEM", sd_cmd_optional},
+[38] = {5,  sd_ac,   "ERASE", sd_cmd_ERASE},
 [43] = {1,  sd_ac,   "Q_MANAGEMENT", sd_cmd_optional},
 [44] = {1,  sd_ac,   "Q_TASK_INFO_A", sd_cmd_optional},
 [45] = {1,  sd_ac,   "Q_TASK_INFO_B", sd_cmd_optional},
-- 
2.41.0




[PATCH v42 38/98] hw/sd/sdcard: Prepare SDProto to contain more fields

2024-06-28 Thread Philippe Mathieu-Daudé
Convert array of command handlers to array of structures.
The structure contains the command handler. No logical
change intended.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 29 +++--
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index f4bdd12b26..558c39419d 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -94,8 +94,9 @@ typedef sd_rsp_type_t (*sd_cmd_handler)(SDState *sd, 
SDRequest req);
 
 typedef struct SDProto {
 const char *name;
-sd_cmd_handler cmd[SDMMC_CMD_MAX];
-sd_cmd_handler acmd[SDMMC_CMD_MAX];
+struct {
+sd_cmd_handler handler;
+} cmd[SDMMC_CMD_MAX], acmd[SDMMC_CMD_MAX];
 } SDProto;
 
 struct SDState {
@@ -1305,8 +1306,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 return sd_illegal;
 }
 
-if (sd->proto->cmd[req.cmd]) {
-return sd->proto->cmd[req.cmd](sd, req);
+if (sd->proto->cmd[req.cmd].handler) {
+return sd->proto->cmd[req.cmd].handler(sd, req);
 }
 
 switch (req.cmd) {
@@ -1753,8 +1754,8 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
  req.cmd, req.arg, sd_state_name(sd->state));
 sd->card_status |= APP_CMD;
 
-if (sd->proto->acmd[req.cmd]) {
-return sd->proto->acmd[req.cmd](sd, req);
+if (sd->proto->acmd[req.cmd].handler) {
+return sd->proto->acmd[req.cmd].handler(sd, req);
 }
 
 switch (req.cmd) {
@@ -2267,22 +2268,22 @@ void sd_enable(SDState *sd, bool enable)
 static const SDProto sd_proto_spi = {
 .name = "SPI",
 .cmd = {
-[0] = sd_cmd_GO_IDLE_STATE,
-[1] = spi_cmd_SEND_OP_COND,
+[0]  = {sd_cmd_GO_IDLE_STATE},
+[1]  = {spi_cmd_SEND_OP_COND},
 },
 .acmd = {
-[41]= spi_cmd_SEND_OP_COND,
+[41] = {spi_cmd_SEND_OP_COND},
 },
 };
 
 static const SDProto sd_proto_sd = {
 .name = "SD",
 .cmd = {
-[0] = sd_cmd_GO_IDLE_STATE,
-[2] = sd_cmd_ALL_SEND_CID,
-[3] = sd_cmd_SEND_RELATIVE_ADDR,
-[19]= sd_cmd_SEND_TUNING_BLOCK,
-[23]= sd_cmd_SET_BLOCK_COUNT,
+[0]  = {sd_cmd_GO_IDLE_STATE},
+[2]  = {sd_cmd_ALL_SEND_CID},
+[3]  = {sd_cmd_SEND_RELATIVE_ADDR},
+[19] = {sd_cmd_SEND_TUNING_BLOCK},
+[23] = {sd_cmd_SET_BLOCK_COUNT},
 },
 };
 
-- 
2.41.0




[PATCH v42 73/98] hw/sd/sdcard: Add sd_acmd_SET_CLR_CARD_DETECT handler (ACMD42)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 25 +
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 167e1c517a..a27a7e0f24 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -263,7 +263,6 @@ static const char *sd_acmd_name(SDState *sd, uint8_t cmd)
 [14] = "DPS_spec",  [15] = "DPS_spec",
 [16] = "DPS_spec",
 [18] = "SECU_spec",
-[42] = "SET_CLR_CARD_DETECT",
 [51] = "SEND_SCR",
 [52] = "SECU_spec", [53] = "SECU_spec",
 [54] = "SECU_spec",
@@ -1748,6 +1747,17 @@ static sd_rsp_type_t sd_acmd_SD_APP_OP_COND(SDState *sd, 
SDRequest req)
 return sd_r3;
 }
 
+/* ACMD42 */
+static sd_rsp_type_t sd_acmd_SET_CLR_CARD_DETECT(SDState *sd, SDRequest req)
+{
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+
+/* Bringing in the 50KOhm pull-up resistor... Done.  */
+return sd_r1;
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint64_t addr;
@@ -1856,17 +1866,6 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 }
 
 switch (req.cmd) {
-case 42:  /* ACMD42: SET_CLR_CARD_DETECT */
-switch (sd->state) {
-case sd_transfer_state:
-/* Bringing in the 50KOhm pull-up resistor... Done.  */
-return sd_r1;
-
-default:
-break;
-}
-break;
-
 case 51:  /* ACMD51: SEND_SCR */
 switch (sd->state) {
 case sd_transfer_state:
@@ -2327,6 +2326,7 @@ static const SDProto sd_proto_spi = {
 [22] = {8,  sd_spi, "SEND_NUM_WR_BLOCKS", sd_acmd_SEND_NUM_WR_BLOCKS},
 [23] = {8,  sd_spi, "SET_WR_BLK_ERASE_COUNT", 
sd_acmd_SET_WR_BLK_ERASE_COUNT},
 [41] = {8,  sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
+[42] = {8,  sd_spi, "SET_CLR_CARD_DETECT", 
sd_acmd_SET_CLR_CARD_DETECT},
 },
 };
 
@@ -2387,6 +2387,7 @@ static const SDProto sd_proto_sd = {
 [22] = {8,  sd_adtc, "SEND_NUM_WR_BLOCKS", sd_acmd_SEND_NUM_WR_BLOCKS},
 [23] = {8,  sd_ac,   "SET_WR_BLK_ERASE_COUNT", 
sd_acmd_SET_WR_BLK_ERASE_COUNT},
 [41] = {8,  sd_bcr,  "SD_APP_OP_COND", sd_acmd_SD_APP_OP_COND},
+[42] = {8,  sd_ac,   "SET_CLR_CARD_DETECT", 
sd_acmd_SET_CLR_CARD_DETECT},
 },
 };
 
-- 
2.41.0




Re: [PATCH v6 01/11] gdbstub: Clean up process_string_cmd

2024-06-28 Thread Philippe Mathieu-Daudé

On 28/6/24 07:08, Gustavo Romero wrote:

Change 'process_string_cmd' to return true on success and false on
failure, instead of 0 and -1.

Signed-off-by: Gustavo Romero 
Reviewed-by: Alex Bennée 
Reviewed-by: Richard Henderson 
---
  gdbstub/gdbstub.c | 40 
  1 file changed, 20 insertions(+), 20 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 




[PATCH v42 56/98] hw/sd/sdcard: Add sd_cmd_READ_SINGLE_BLOCK handler (CMD17)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 37 -
 1 file changed, 20 insertions(+), 17 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index d731c3df58..e2a7ed8b45 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -240,7 +240,6 @@ static const char *sd_response_name(sd_rsp_type_t rsp)
 static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 {
 static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
-[17]= "READ_SINGLE_BLOCK",
 [18]= "READ_MULTIPLE_BLOCK",
 [21]= "DPS_spec",
 [24]= "WRITE_BLOCK",[25]= "WRITE_MULTIPLE_BLOCK",
@@ -1441,6 +1440,24 @@ static sd_rsp_type_t sd_cmd_SET_BLOCKLEN(SDState *sd, 
SDRequest req)
 return sd_r1;
 }
 
+/* CMD17 */
+static sd_rsp_type_t sd_cmd_READ_SINGLE_BLOCK(SDState *sd, SDRequest req)
+{
+uint64_t addr;
+
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+
+addr = sd_req_get_address(sd, req);
+if (!address_in_range(sd, "READ_SINGLE_BLOCK", addr, sd->blk_len)) {
+return sd_r1;
+}
+
+sd_blk_read(sd, addr, sd->blk_len);
+return sd_cmd_to_sendingdata(sd, req, addr, NULL, sd->blk_len);
+}
+
 /* CMD19 */
 static sd_rsp_type_t sd_cmd_SEND_TUNING_BLOCK(SDState *sd, SDRequest req)
 {
@@ -1507,22 +1524,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 
 switch (req.cmd) {
 /* Block read commands (Class 2) */
-case 17:  /* CMD17:  READ_SINGLE_BLOCK */
-addr = sd_req_get_address(sd, req);
-switch (sd->state) {
-case sd_transfer_state:
-
-if (!address_in_range(sd, "READ_SINGLE_BLOCK", addr, sd->blk_len)) 
{
-return sd_r1;
-}
-sd_blk_read(sd, addr, sd->blk_len);
-return sd_cmd_to_sendingdata(sd, req, addr, NULL, sd->blk_len);
-
-default:
-break;
-}
-break;
-
 case 18:  /* CMD18:  READ_MULTIPLE_BLOCK */
 addr = sd_req_get_address(sd, req);
 switch (sd->state) {
@@ -2306,6 +2307,7 @@ static const SDProto sd_proto_spi = {
 [12] = {0,  sd_spi, "STOP_TRANSMISSION", sd_cmd_STOP_TRANSMISSION},
 [13] = {0,  sd_spi, "SEND_STATUS", sd_cmd_SEND_STATUS},
 [16] = {2,  sd_spi, "SET_BLOCKLEN", sd_cmd_SET_BLOCKLEN},
+[17] = {2,  sd_spi, "READ_SINGLE_BLOCK", sd_cmd_READ_SINGLE_BLOCK},
 [34] = {10, sd_spi, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_spi, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_spi, "SEND_PSI", sd_cmd_optional},
@@ -2338,6 +2340,7 @@ static const SDProto sd_proto_sd = {
 [13] = {0,  sd_ac,   "SEND_STATUS", sd_cmd_SEND_STATUS},
 [15] = {0,  sd_ac,   "GO_INACTIVE_STATE", sd_cmd_GO_INACTIVE_STATE},
 [16] = {2,  sd_ac,   "SET_BLOCKLEN", sd_cmd_SET_BLOCKLEN},
+[17] = {2,  sd_adtc, "READ_SINGLE_BLOCK", sd_cmd_READ_SINGLE_BLOCK},
 [19] = {2,  sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
 [20] = {2,  sd_ac,   "SPEED_CLASS_CONTROL", sd_cmd_optional},
 [23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
-- 
2.41.0




[PATCH v42 37/98] hw/sd/sdcard: Pass SDState as argument to sd_[a]cmd_name()

2024-06-28 Thread Philippe Mathieu-Daudé
In order to access SDState::SDProto from sd_[a]cmd_name(),
pass SDState as argument.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 93a4a4e1b4..f4bdd12b26 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -233,7 +233,7 @@ static const char *sd_response_name(sd_rsp_type_t rsp)
 return response_name[rsp];
 }
 
-static const char *sd_cmd_name(uint8_t cmd)
+static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 {
 static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
  [0]= "GO_IDLE_STATE",   [1]= "SEND_OP_COND",
@@ -272,7 +272,7 @@ static const char *sd_cmd_name(uint8_t cmd)
 return cmd_abbrev[cmd] ? cmd_abbrev[cmd] : "UNKNOWN_CMD";
 }
 
-static const char *sd_acmd_name(uint8_t cmd)
+static const char *sd_acmd_name(SDState *sd, uint8_t cmd)
 {
 static const char *acmd_abbrev[SDMMC_CMD_MAX] = {
  [6] = "SET_BUS_WIDTH",
@@ -1281,7 +1281,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 uint64_t addr;
 uint32_t data;
 
-sd->last_cmd_name = sd_cmd_name(req.cmd);
+sd->last_cmd_name = sd_cmd_name(sd, req.cmd);
 /* CMD55 precedes an ACMD, so we are not interested in tracing it.
  * However there is no ACMD55, so we want to trace this particular case.
  */
@@ -1748,7 +1748,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 static sd_rsp_type_t sd_app_command(SDState *sd,
 SDRequest req)
 {
-sd->last_cmd_name = sd_acmd_name(req.cmd);
+sd->last_cmd_name = sd_acmd_name(sd, req.cmd);
 trace_sdcard_app_command(sd->proto->name, sd->last_cmd_name,
  req.cmd, req.arg, sd_state_name(sd->state));
 sd->card_status |= APP_CMD;
-- 
2.41.0




[PATCH v42 66/98] hw/sd/sdcard: Add spi_cmd_READ_OCR handler (CMD58)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 50cee5ac40..b3b4cd5a3a 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1660,6 +1660,12 @@ static sd_rsp_type_t sd_cmd_GEN_CMD(SDState *sd, 
SDRequest req)
 }
 }
 
+/* CMD58 */
+static sd_rsp_type_t spi_cmd_READ_OCR(SDState *sd, SDRequest req)
+{
+return sd_r3;
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint64_t addr;
@@ -1748,9 +1754,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid));
 
 /* Application specific commands (Class 8) */
-case 58:/* CMD58:   READ_OCR (SPI) */
-return sd_r3;
-
 case 59:/* CMD59:   CRC_ON_OFF (SPI) */
 return sd_r1;
 
@@ -2321,6 +2324,7 @@ static const SDProto sd_proto_spi = {
 [55] = {8,  sd_spi, "APP_CMD", sd_cmd_APP_CMD},
 [56] = {8,  sd_spi, "GEN_CMD", sd_cmd_GEN_CMD},
 [57] = {10, sd_spi, "DIRECT_SECURE_WRITE", sd_cmd_optional},
+[58] = {0,  sd_spi, "READ_OCR", spi_cmd_READ_OCR},
 },
 .acmd = {
 [41] = {8,  sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
-- 
2.41.0




[PATCH v42 77/98] hw/sd/sdcard: Remove noise from sd_cmd_name()

2024-06-28 Thread Philippe Mathieu-Daudé
These CMD names weren't really useful, "UNKNOWN_CMD" is simpler.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 19322c558f..0a7b422b2c 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -241,12 +241,7 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 {
 static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
 [18]= "READ_MULTIPLE_BLOCK",
-[21]= "DPS_spec",
 [25]= "WRITE_MULTIPLE_BLOCK",
-[26]= "MANUF_RSVD",
-[40]= "DPS_spec",
-[60]= "MANUF_RSVD", [61]= "MANUF_RSVD",
-[62]= "MANUF_RSVD", [63]= "MANUF_RSVD",
 };
 const SDProto *sdp = sd->proto;
 
-- 
2.41.0




[RFC PATCH v42 92/98] hw/sd/sdcard: Adapt sd_cmd_APP_CMD handler for eMMC (CMD55)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Cédric Le Goater 

Signed-off-by: Cédric Le Goater 
[PMD: Use aspeed_emmc_kludge]
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index f875fcd741..82e0b5838f 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1693,6 +1693,9 @@ static sd_rsp_type_t sd_cmd_APP_CMD(SDState *sd, 
SDRequest req)
 case sd_sleep_state:
 return sd_invalid_state_for_cmd(sd, req);
 case sd_idle_state:
+if (sd_is_emmc(sd)) {
+return sd_invalid_state_for_cmd(sd, req);
+}
 if (!sd_is_spi(sd) && sd_req_get_rca(sd, req) != 0x) {
 qemu_log_mask(LOG_GUEST_ERROR,
   "SD: illegal RCA 0x%04x for APP_CMD\n", req.cmd);
@@ -1707,7 +1710,7 @@ static sd_rsp_type_t sd_cmd_APP_CMD(SDState *sd, 
SDRequest req)
 sd->expecting_acmd = true;
 sd->card_status |= APP_CMD;
 
-return sd_r1;
+return sd->aspeed_emmc_kludge ? sd_r0 : sd_r1;
 }
 
 /* CMD56 */
-- 
2.41.0




[PATCH v42 74/98] hw/sd/sdcard: Add sd_acmd_SEND_SCR handler (ACMD51)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index a27a7e0f24..6a9d611429 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -263,7 +263,6 @@ static const char *sd_acmd_name(SDState *sd, uint8_t cmd)
 [14] = "DPS_spec",  [15] = "DPS_spec",
 [16] = "DPS_spec",
 [18] = "SECU_spec",
-[51] = "SEND_SCR",
 [52] = "SECU_spec", [53] = "SECU_spec",
 [54] = "SECU_spec",
 [56] = "SECU_spec", [57] = "SECU_spec",
@@ -1758,6 +1757,12 @@ static sd_rsp_type_t sd_acmd_SET_CLR_CARD_DETECT(SDState 
*sd, SDRequest req)
 return sd_r1;
 }
 
+/* ACMD51 */
+static sd_rsp_type_t sd_acmd_SEND_SCR(SDState *sd, SDRequest req)
+{
+return sd_cmd_to_sendingdata(sd, req, 0, sd->scr, sizeof(sd->scr));
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint64_t addr;
@@ -1866,16 +1871,6 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 }
 
 switch (req.cmd) {
-case 51:  /* ACMD51: SEND_SCR */
-switch (sd->state) {
-case sd_transfer_state:
-return sd_cmd_to_sendingdata(sd, req, 0, sd->scr, sizeof(sd->scr));
-
-default:
-break;
-}
-break;
-
 case 18:/* Reserved for SD security applications */
 case 25:
 case 26:
@@ -2327,6 +2322,7 @@ static const SDProto sd_proto_spi = {
 [23] = {8,  sd_spi, "SET_WR_BLK_ERASE_COUNT", 
sd_acmd_SET_WR_BLK_ERASE_COUNT},
 [41] = {8,  sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
 [42] = {8,  sd_spi, "SET_CLR_CARD_DETECT", 
sd_acmd_SET_CLR_CARD_DETECT},
+[51] = {8,  sd_spi, "SEND_SCR", sd_acmd_SEND_SCR},
 },
 };
 
@@ -2388,6 +2384,7 @@ static const SDProto sd_proto_sd = {
 [23] = {8,  sd_ac,   "SET_WR_BLK_ERASE_COUNT", 
sd_acmd_SET_WR_BLK_ERASE_COUNT},
 [41] = {8,  sd_bcr,  "SD_APP_OP_COND", sd_acmd_SD_APP_OP_COND},
 [42] = {8,  sd_ac,   "SET_CLR_CARD_DETECT", 
sd_acmd_SET_CLR_CARD_DETECT},
+[51] = {8,  sd_adtc, "SEND_SCR", sd_acmd_SEND_SCR},
 },
 };
 
-- 
2.41.0




[PATCH v42 65/98] hw/sd/sdcard: Add sd_cmd_GEN_CMD handler (CMD56)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 36 +---
 1 file changed, 17 insertions(+), 19 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 5461e56e17..50cee5ac40 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -245,7 +245,6 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 [25]= "WRITE_MULTIPLE_BLOCK",
 [26]= "MANUF_RSVD",
 [40]= "DPS_spec",
-[56]= "GEN_CMD",
 [60]= "MANUF_RSVD", [61]= "MANUF_RSVD",
 [62]= "MANUF_RSVD", [63]= "MANUF_RSVD",
 };
@@ -910,9 +909,6 @@ static void sd_blk_write(SDState *sd, uint64_t addr, 
uint32_t len)
 }
 }
 
-#define APP_READ_BLOCK(a, len)  memset(sd->data, 0xec, len)
-#define APP_WRITE_BLOCK(a, len)
-
 static void sd_erase(SDState *sd)
 {
 uint64_t erase_start = sd->erase_start;
@@ -1649,6 +1645,21 @@ static sd_rsp_type_t sd_cmd_APP_CMD(SDState *sd, 
SDRequest req)
 return sd_r1;
 }
 
+/* CMD56 */
+static sd_rsp_type_t sd_cmd_GEN_CMD(SDState *sd, SDRequest req)
+{
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+
+if (req.arg & 1) {
+return sd_cmd_to_sendingdata(sd, req, 0,
+ sd->vendor_data, sizeof(sd->vendor_data));
+} else {
+return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->vendor_data));
+}
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint64_t addr;
@@ -1737,21 +1748,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid));
 
 /* Application specific commands (Class 8) */
-case 56:  /* CMD56:  GEN_CMD */
-switch (sd->state) {
-case sd_transfer_state:
-if (req.arg & 1) {
-return sd_cmd_to_sendingdata(sd, req, 0,
- sd->vendor_data,
- sizeof(sd->vendor_data));
-}
-return sd_cmd_to_receivingdata(sd, req, 0, 
sizeof(sd->vendor_data));
-
-default:
-break;
-}
-break;
-
 case 58:/* CMD58:   READ_OCR (SPI) */
 return sd_r3;
 
@@ -2323,6 +2319,7 @@ static const SDProto sd_proto_spi = {
 [52] = {9,  sd_spi, "IO_RW_DIRECT", sd_cmd_optional},
 [53] = {9,  sd_spi, "IO_RW_EXTENDED", sd_cmd_optional},
 [55] = {8,  sd_spi, "APP_CMD", sd_cmd_APP_CMD},
+[56] = {8,  sd_spi, "GEN_CMD", sd_cmd_GEN_CMD},
 [57] = {10, sd_spi, "DIRECT_SECURE_WRITE", sd_cmd_optional},
 },
 .acmd = {
@@ -2376,6 +2373,7 @@ static const SDProto sd_proto_sd = {
 [52] = {9,  sd_bc,   "IO_RW_DIRECT", sd_cmd_optional},
 [53] = {9,  sd_bc,   "IO_RW_EXTENDED", sd_cmd_optional},
 [55] = {8,  sd_ac,   "APP_CMD", sd_cmd_APP_CMD},
+[56] = {8,  sd_adtc, "GEN_CMD", sd_cmd_GEN_CMD},
 [57] = {10, sd_adtc, "DIRECT_SECURE_WRITE", sd_cmd_optional},
 [58] = {11, sd_adtc, "READ_EXTR_MULTI", sd_cmd_optional},
 [59] = {11, sd_adtc, "WRITE_EXTR_MULTI", sd_cmd_optional},
-- 
2.41.0




Re: [PATCH v6 06/11] target/arm: Factor out code for setting MTE TCF0 field

2024-06-28 Thread Philippe Mathieu-Daudé

On 28/6/24 07:08, Gustavo Romero wrote:

Factor out the code used for setting the MTE TCF0 field from the prctl
code into a convenient function. Other subsystems, like gdbstub, need to
set this field as well, so keep it as a separate function to avoid
duplication and ensure consistency in how this field is set across the
board.

Signed-off-by: Gustavo Romero 
---
  linux-user/aarch64/meson.build   |  2 ++
  linux-user/aarch64/mte_user_helper.c | 34 
  linux-user/aarch64/mte_user_helper.h | 25 
  linux-user/aarch64/target_prctl.h| 22 ++
  4 files changed, 63 insertions(+), 20 deletions(-)
  create mode 100644 linux-user/aarch64/mte_user_helper.c
  create mode 100644 linux-user/aarch64/mte_user_helper.h

diff --git a/linux-user/aarch64/meson.build b/linux-user/aarch64/meson.build
index 248c578d15..f75bb3cd75 100644
--- a/linux-user/aarch64/meson.build
+++ b/linux-user/aarch64/meson.build
@@ -9,3 +9,5 @@ vdso_le_inc = gen_vdso.process('vdso-le.so',
 extra_args: ['-r', '__kernel_rt_sigreturn'])
  
  linux_user_ss.add(when: 'TARGET_AARCH64', if_true: [vdso_be_inc, vdso_le_inc])

+
+linux_user_ss.add(when: 'TARGET_AARCH64', if_true: 
[files('mte_user_helper.c')])
diff --git a/linux-user/aarch64/mte_user_helper.c 
b/linux-user/aarch64/mte_user_helper.c
new file mode 100644
index 00..8be6deaf03
--- /dev/null
+++ b/linux-user/aarch64/mte_user_helper.c
@@ -0,0 +1,34 @@
+/*
+ * ARM MemTag convenience functions.
+ *
+ * This code is licensed under the GNU GPL v2 or later.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+


  #include "qemu/osdep.h"
  #include "qemu.h"


+#include 
+#include "mte_user_helper.h"
+
+void arm_set_mte_tcf0(CPUArchState *env, abi_long value)
+{
+/*
+ * Write PR_MTE_TCF to SCTLR_EL1[TCF0].
+ *
+ * The kernel has a per-cpu configuration for the sysadmin,
+ * /sys/devices/system/cpu/cpu/mte_tcf_preferred,
+ * which qemu does not implement.
+ *
+ * Because there is no performance difference between the modes, and
+ * because SYNC is most useful for debugging MTE errors, choose SYNC
+ * as the preferred mode.  With this preference, and the way the API
+ * uses only two bits, there is no way for the program to select
+ * ASYMM mode.
+ */
+unsigned tcf = 0;
+if (value & PR_MTE_TCF_SYNC) {
+tcf = 1;
+} else if (value & PR_MTE_TCF_ASYNC) {
+tcf = 2;
+}
+env->cp15.sctlr_el[1] = deposit64(env->cp15.sctlr_el[1], 38, 2, tcf);
+}
diff --git a/linux-user/aarch64/mte_user_helper.h 
b/linux-user/aarch64/mte_user_helper.h
new file mode 100644
index 00..ee3f6b190a
--- /dev/null
+++ b/linux-user/aarch64/mte_user_helper.h
@@ -0,0 +1,25 @@
+/*
+ * ARM MemTag convenience functions.
+ *
+ * This code is licensed under the GNU GPL v2 or later.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef AARCH64_MTE_USER_HELPER_H
+#define AARCH64_MTE USER_HELPER_H
+
+#include "qemu/osdep.h"
+#include "qemu.h"


NACK. See my comment on v5.




[RFC PATCH v42 96/98] hw/sd/sdcard: Support boot area in emmc image

2024-06-28 Thread Philippe Mathieu-Daudé
From: Joel Stanley 

This assumes a specially constructed image:

  dd if=/dev/zero of=mmc-bootarea.img count=2 bs=1M
  dd if=u-boot-spl.bin of=mmc-bootarea.img conv=notrunc
  dd if=u-boot.bin of=mmc-bootarea.img conv=notrunc count=64 bs=1K
  cat mmc-bootarea.img obmc-phosphor-image.wic > mmc.img
  truncate --size 16GB mmc.img
  truncate --size 128MB mmc-bootarea.img

For now this still requires a mtd image to load the SPL:

  qemu-system-arm -M tacoma-bmc -nographic \
   -global driver=sd-card,property=emmc,value=true \
   -drive file=mmc.img,if=sd,index=2 \
   -drive file=mmc-bootarea.img,if=mtd,format=raw

Signed-off-by: Joel Stanley 
Signed-off-by: Cédric Le Goater 
Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/sd/sd.h |  1 +
 hw/sd/sd.c | 39 +++
 2 files changed, 40 insertions(+)

diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index d35a839f5e..07435d2e17 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -132,6 +132,7 @@ struct SDCardClass {
 bool (*get_readonly)(SDState *sd);
 void (*set_cid)(SDState *sd);
 void (*set_csd)(SDState *sd, uint64_t size);
+uint32_t (*bootpart_offset)(SDState *sd);
 
 const struct SDProto *proto;
 };
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index e7d8b9c0fb..2d49be61f6 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -783,6 +783,12 @@ static inline uint64_t sd_addr_to_wpnum(uint64_t addr)
 return addr >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT);
 }
 
+
+static unsigned sd_boot_capacity_bytes(SDState *sd)
+{
+return sd->ext_csd[EXT_CSD_BOOT_MULT] << 17;
+}
+
 static void sd_reset(DeviceState *dev)
 {
 SDState *sd = SD_CARD(dev);
@@ -984,9 +990,40 @@ void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq 
insert)
 qemu_set_irq(insert, sd->blk ? blk_is_inserted(sd->blk) : 0);
 }
 
+/*
+ * This requires a disk image that has two boot partitions inserted at the
+ * beginning of it. The size of the boot partitions are configured in the
+ * ext_csd structure, which is hardcoded in qemu. They are currently set to
+ * 1MB each.
+ */
+static uint32_t sd_emmc_bootpart_offset(SDState *sd)
+{
+unsigned int access = sd->ext_csd[EXT_CSD_PART_CONFIG] &
+EXT_CSD_PART_CONFIG_ACC_MASK;
+unsigned int boot_capacity = sd_boot_capacity_bytes(sd);
+
+switch (access) {
+case EXT_CSD_PART_CONFIG_ACC_DEFAULT:
+return boot_capacity * 2;
+case EXT_CSD_PART_CONFIG_ACC_BOOT0:
+return 0;
+case EXT_CSD_PART_CONFIG_ACC_BOOT0 + 1:
+return boot_capacity * 1;
+default:
+ g_assert_not_reached();
+}
+}
+
+static uint32_t sd_bootpart_offset(SDState *sd)
+{
+SDCardClass *sc = SD_CARD_GET_CLASS(sd);
+return sc->bootpart_offset ? sc->bootpart_offset(sd) : 0;
+}
+
 static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len)
 {
 trace_sdcard_read_block(addr, len);
+addr += sd_bootpart_offset(sd);
 if (!sd->blk || blk_pread(sd->blk, addr, len, sd->data, 0) < 0) {
 fprintf(stderr, "sd_blk_read: read error on host side\n");
 }
@@ -995,6 +1032,7 @@ static void sd_blk_read(SDState *sd, uint64_t addr, 
uint32_t len)
 static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len)
 {
 trace_sdcard_write_block(addr, len);
+addr += sd_bootpart_offset(sd);
 if (!sd->blk || blk_pwrite(sd->blk, addr, len, sd->data, 0) < 0) {
 fprintf(stderr, "sd_blk_write: write error on host side\n");
 }
@@ -2833,6 +2871,7 @@ static void emmc_class_init(ObjectClass *klass, void 
*data)
 dc->realize = emmc_realize;
 sc->proto = &sd_proto_emmc;
 sc->set_csd = sd_emmc_set_csd;
+sc->bootpart_offset = sd_emmc_bootpart_offset;
 }
 
 static const TypeInfo sd_types[] = {
-- 
2.41.0




[PATCH v42 85/98] hw/sd/sdcard: Add emmc_cmd_SET_RELATIVE_ADDR() handler

2024-06-28 Thread Philippe Mathieu-Daudé
From: Cédric Le Goater 

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Cédric Le Goater 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 9a2bfeaab6..c6e5c93acb 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1220,6 +1220,20 @@ static sd_rsp_type_t sd_cmd_SEND_RELATIVE_ADDR(SDState 
*sd, SDRequest req)
 }
 }
 
+static sd_rsp_type_t emmc_cmd_SET_RELATIVE_ADDR(SDState *sd, SDRequest req)
+{
+switch (sd->state) {
+case sd_identification_state:
+case sd_standby_state:
+sd->state = sd_standby_state;
+sd_set_rca(sd, req.arg >> 16);
+return sd_r1;
+
+default:
+return sd_invalid_state_for_cmd(sd, req);
+}
+}
+
 /* CMD6 */
 static sd_rsp_type_t sd_cmd_SWITCH_FUNCTION(SDState *sd, SDRequest req)
 {
@@ -2385,6 +2399,7 @@ static const SDProto sd_proto_emmc = {
 .cmd = {
 [0]  = {0,  sd_bc,   "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
 [2]  = {0,  sd_bcr,  "ALL_SEND_CID", sd_cmd_ALL_SEND_CID},
+[3]  = {0,  sd_ac,   "SET_RELATIVE_ADDR", emmc_cmd_SET_RELATIVE_ADDR},
 [4]  = {0,  sd_bc,   "SEND_DSR", sd_cmd_unimplemented},
 [7]  = {0,  sd_ac,   "(DE)SELECT_CARD", sd_cmd_DE_SELECT_CARD},
 [9]  = {0,  sd_ac,   "SEND_CSD", sd_cmd_SEND_CSD},
-- 
2.41.0




[RFC PATCH v42 97/98] hw/sd/sdcard: Subtract bootarea size from blk

2024-06-28 Thread Philippe Mathieu-Daudé
From: Joel Stanley 

The userdata size is derived from the file the user passes on the
command line, but we must take into account the boot areas.

Signed-off-by: Joel Stanley 
Signed-off-by: Cédric Le Goater 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 2d49be61f6..bbf054ea1e 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -804,6 +804,10 @@ static void sd_reset(DeviceState *dev)
 }
 size = sect << HWBLOCK_SHIFT;
 
+if (sc->bootpart_offset) {
+size -= sd_boot_capacity_bytes(sd) * 2;
+}
+
 sect = sd_addr_to_wpnum(size) + 1;
 
 sd->state = sd_idle_state;
-- 
2.41.0




[PATCH v42 87/98] hw/sd/sdcard: Fix SET_BLOCK_COUNT command argument on eMMC (CMD23)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Cédric Le Goater 

The number of blocks is defined in the lower bits [15:0].

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Cédric Le Goater 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 2dc0209482..7c6f5ccc72 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -171,12 +171,18 @@ struct SDState {
 static void sd_realize(DeviceState *dev, Error **errp);
 
 static const SDProto sd_proto_spi;
+static const SDProto sd_proto_emmc;
 
 static bool sd_is_spi(SDState *sd)
 {
 return sd->proto == &sd_proto_spi;
 }
 
+static bool sd_is_emmc(SDState *sd)
+{
+return sd->proto == &sd_proto_emmc;
+}
+
 static const char *sd_version_str(enum SDPhySpecificationVersion version)
 {
 static const char *sdphy_version[] = {
@@ -1479,6 +1485,9 @@ static sd_rsp_type_t sd_cmd_SET_BLOCK_COUNT(SDState *sd, 
SDRequest req)
 }
 
 sd->multi_blk_cnt = req.arg;
+if (sd_is_emmc(sd)) {
+sd->multi_blk_cnt &= 0x;
+}
 trace_sdcard_set_block_count(sd->multi_blk_cnt);
 
 return sd_r1;
-- 
2.41.0




[PATCH v42 68/98] hw/sd/sdcard: Add sd_acmd_SET_BUS_WIDTH handler (ACMD6)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 28 +++-
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 2f853a89d1..0310a5a3a1 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -260,7 +260,6 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 static const char *sd_acmd_name(SDState *sd, uint8_t cmd)
 {
 static const char *acmd_abbrev[SDMMC_CMD_MAX] = {
- [6] = "SET_BUS_WIDTH",
 [13] = "SD_STATUS",
 [14] = "DPS_spec",  [15] = "DPS_spec",
 [16] = "DPS_spec",
@@ -1672,6 +1671,18 @@ static sd_rsp_type_t spi_cmd_CRC_ON_OFF(SDState *sd, 
SDRequest req)
 return sd_r1;
 }
 
+/* ACMD6 */
+static sd_rsp_type_t sd_acmd_SET_BUS_WIDTH(SDState *sd, SDRequest req)
+{
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+
+sd->sd_status[0] &= 0x3f;
+sd->sd_status[0] |= (req.arg & 0x03) << 6;
+return sd_r1;
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint64_t addr;
@@ -1780,18 +1791,6 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 }
 
 switch (req.cmd) {
-case 6:  /* ACMD6:  SET_BUS_WIDTH */
-switch (sd->state) {
-case sd_transfer_state:
-sd->sd_status[0] &= 0x3f;
-sd->sd_status[0] |= (req.arg & 0x03) << 6;
-return sd_r1;
-
-default:
-break;
-}
-break;
-
 case 13:  /* ACMD13: SD_STATUS */
 switch (sd->state) {
 case sd_transfer_state:
@@ -2385,6 +2384,9 @@ static const SDProto sd_proto_sd = {
 [58] = {11, sd_adtc, "READ_EXTR_MULTI", sd_cmd_optional},
 [59] = {11, sd_adtc, "WRITE_EXTR_MULTI", sd_cmd_optional},
 },
+.acmd = {
+[6]  = {8,  sd_ac,   "SET_BUS_WIDTH", sd_acmd_SET_BUS_WIDTH},
+},
 };
 
 static void sd_instance_init(Object *obj)
-- 
2.41.0




[PATCH v42 84/98] hw/sd/sdcard: Register unimplemented command handlers

2024-06-28 Thread Philippe Mathieu-Daudé
Per the spec v4.5 these commands are mandatory,
but we don't implement them.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index ebcd8c1e43..9a2bfeaab6 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -2385,24 +2385,30 @@ static const SDProto sd_proto_emmc = {
 .cmd = {
 [0]  = {0,  sd_bc,   "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
 [2]  = {0,  sd_bcr,  "ALL_SEND_CID", sd_cmd_ALL_SEND_CID},
+[4]  = {0,  sd_bc,   "SEND_DSR", sd_cmd_unimplemented},
 [7]  = {0,  sd_ac,   "(DE)SELECT_CARD", sd_cmd_DE_SELECT_CARD},
 [9]  = {0,  sd_ac,   "SEND_CSD", sd_cmd_SEND_CSD},
 [10] = {0,  sd_ac,   "SEND_CID", sd_cmd_SEND_CID},
 [12] = {0,  sd_ac,   "STOP_TRANSMISSION", sd_cmd_STOP_TRANSMISSION},
 [13] = {0,  sd_ac,   "SEND_STATUS", sd_cmd_SEND_STATUS},
+[14] = {0,  sd_adtc, "BUSTEST_R", sd_cmd_unimplemented},
 [15] = {0,  sd_ac,   "GO_INACTIVE_STATE", sd_cmd_GO_INACTIVE_STATE},
 [16] = {2,  sd_ac,   "SET_BLOCKLEN", sd_cmd_SET_BLOCKLEN},
 [17] = {2,  sd_adtc, "READ_SINGLE_BLOCK", sd_cmd_READ_SINGLE_BLOCK},
+[19] = {0,  sd_adtc, "BUSTEST_W", sd_cmd_unimplemented},
 [23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
 [24] = {4,  sd_adtc, "WRITE_SINGLE_BLOCK", sd_cmd_WRITE_SINGLE_BLOCK},
 [27] = {4,  sd_adtc, "PROGRAM_CSD", sd_cmd_PROGRAM_CSD},
 [28] = {6,  sd_ac,   "SET_WRITE_PROT", sd_cmd_SET_WRITE_PROT},
 [29] = {6,  sd_ac,   "CLR_WRITE_PROT", sd_cmd_CLR_WRITE_PROT},
 [30] = {6,  sd_adtc, "SEND_WRITE_PROT", sd_cmd_SEND_WRITE_PROT},
+[31] = {6,  sd_adtc, "SEND_WRITE_PROT_TYPE", sd_cmd_unimplemented},
 [35] = {5,  sd_ac,   "ERASE_WR_BLK_START", sd_cmd_ERASE_WR_BLK_START},
 [36] = {5,  sd_ac,   "ERASE_WR_BLK_END", sd_cmd_ERASE_WR_BLK_END},
 [38] = {5,  sd_ac,   "ERASE", sd_cmd_ERASE},
+[39] = {9,  sd_ac,   "FAST_IO", sd_cmd_unimplemented},
 [42] = {7,  sd_adtc, "LOCK_UNLOCK", sd_cmd_LOCK_UNLOCK},
+[49] = {0,  sd_adtc, "SET_TIME", sd_cmd_unimplemented},
 [55] = {8,  sd_ac,   "APP_CMD", sd_cmd_APP_CMD},
 [56] = {8,  sd_adtc, "GEN_CMD", sd_cmd_GEN_CMD},
 },
-- 
2.41.0




[RFC PATCH v42 98/98] hw/sd/sdcard: Add boot config support

2024-06-28 Thread Philippe Mathieu-Daudé
From: Joel Stanley 

Introduced "boot-config" property to set CSD 179, the boot config
register.

With this correctly set we can use the enable bit to detect if
partition support is enabled.

Signed-off-by: Joel Stanley 
Signed-off-by: Cédric Le Goater 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index bbf054ea1e..b598974bbf 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -129,6 +129,7 @@ struct SDState {
 uint8_t spec_version;
 BlockBackend *blk;
 bool aspeed_emmc_kludge;
+uint8_t boot_config;
 
 const SDProto *proto;
 
@@ -505,6 +506,8 @@ static void mmc_set_ext_csd(SDState *sd, uint64_t size)
 sd->ext_csd[159] = 0x00; /* Max enhanced area size */
 sd->ext_csd[158] = 0x00; /* ... */
 sd->ext_csd[157] = 0xEC; /* ... */
+
+sd->ext_csd[EXT_CSD_PART_CONFIG] = sd->boot_config;
 }
 
 static void sd_emmc_set_csd(SDState *sd, uint64_t size)
@@ -1004,8 +1007,14 @@ static uint32_t sd_emmc_bootpart_offset(SDState *sd)
 {
 unsigned int access = sd->ext_csd[EXT_CSD_PART_CONFIG] &
 EXT_CSD_PART_CONFIG_ACC_MASK;
+unsigned int enable = sd->ext_csd[EXT_CSD_PART_CONFIG] &
+ EXT_CSD_PART_CONFIG_EN_MASK;
 unsigned int boot_capacity = sd_boot_capacity_bytes(sd);
 
+if (!enable) {
+return 0;
+}
+
 switch (access) {
 case EXT_CSD_PART_CONFIG_ACC_DEFAULT:
 return boot_capacity * 2;
@@ -2808,6 +2817,7 @@ static Property sd_properties[] = {
  * whether card should be in SSI or MMC/SD mode.  It is also up to the
  * board to ensure that ssi transfers only occur when the chip select
  * is asserted.  */
+DEFINE_PROP_UINT8("boot-config", SDState, boot_config, 0x0),
 DEFINE_PROP_END_OF_LIST()
 };
 
-- 
2.41.0




[PATCH v42 78/98] hw/sd/sdcard: Remove default case in read/write on DAT lines

2024-06-28 Thread Philippe Mathieu-Daudé
All read/write on DAT lines are explicitly handled.
Reaching this point would be a programming error:
replace by an assertion.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 0a7b422b2c..64621d4340 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1951,7 +1951,6 @@ int sd_do_command(SDState *sd, SDRequest *req,
 /* Valid command, we can update the 'state before command' bits.
  * (Do this now so they appear in r1 responses.)
  */
-sd->current_cmd = req->cmd;
 sd->card_status = FIELD_DP32(sd->card_status, CSR,
  CURRENT_STATE, last_state);
 }
@@ -2016,6 +2015,8 @@ send_response:
 qemu_hexdump(stderr, "Response", response, rsplen);
 #endif
 
+sd->current_cmd = rtype == sd_illegal ? 0 : req->cmd;
+
 return rsplen;
 }
 
@@ -2171,8 +2172,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
 break;
 
 default:
-qemu_log_mask(LOG_GUEST_ERROR, "%s: unknown command\n", __func__);
-break;
+g_assert_not_reached();
 }
 }
 
@@ -2238,8 +2238,7 @@ uint8_t sd_read_byte(SDState *sd)
 break;
 
 default:
-qemu_log_mask(LOG_GUEST_ERROR, "%s: unknown command\n", __func__);
-return 0x00;
+g_assert_not_reached();
 }
 
 return ret;
-- 
2.41.0




[PATCH v42 76/98] hw/sd/sdcard: Remove noise from sd_acmd_name()

2024-06-28 Thread Philippe Mathieu-Daudé
These ACMD names weren't really useful, "UNKNOWN_ACMD" is simpler.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 12 +---
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 7f93d363c7..19322c558f 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -259,23 +259,13 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 
 static const char *sd_acmd_name(SDState *sd, uint8_t cmd)
 {
-static const char *acmd_abbrev[SDMMC_CMD_MAX] = {
-[14] = "DPS_spec",  [15] = "DPS_spec",
-[16] = "DPS_spec",
-[18] = "SECU_spec",
-[52] = "SECU_spec", [53] = "SECU_spec",
-[54] = "SECU_spec",
-[56] = "SECU_spec", [57] = "SECU_spec",
-[58] = "SECU_spec", [59] = "SECU_spec",
-};
 const SDProto *sdp = sd->proto;
 
 if (sdp->acmd[cmd].handler) {
-assert(!acmd_abbrev[cmd]);
 return sdp->acmd[cmd].name;
 }
 
-return acmd_abbrev[cmd] ? acmd_abbrev[cmd] : "UNKNOWN_ACMD";
+return "UNKNOWN_ACMD";
 }
 
 static uint8_t sd_get_dat_lines(SDState *sd)
-- 
2.41.0




[PATCH v42 72/98] hw/sd/sdcard: Add sd_acmd_SD_APP_OP_COND handler (ACMD41)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 82 ++
 1 file changed, 45 insertions(+), 37 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index cd207a3090..167e1c517a 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1704,6 +1704,50 @@ static sd_rsp_type_t 
sd_acmd_SET_WR_BLK_ERASE_COUNT(SDState *sd, SDRequest req)
 return sd_r1;
 }
 
+/* ACMD41 */
+static sd_rsp_type_t sd_acmd_SD_APP_OP_COND(SDState *sd, SDRequest req)
+{
+if (sd->state != sd_idle_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+
+/*
+ * If it's the first ACMD41 since reset, we need to decide
+ * whether to power up. If this is not an enquiry ACMD41,
+ * we immediately report power on and proceed below to the
+ * ready state, but if it is, we set a timer to model a
+ * delay for power up. This works around a bug in EDK2
+ * UEFI, which sends an initial enquiry ACMD41, but
+ * assumes that the card is in ready state as soon as it
+ * sees the power up bit set.
+ */
+if (!FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP)) {
+if ((req.arg & ACMD41_ENQUIRY_MASK) != 0) {
+timer_del(sd->ocr_power_timer);
+sd_ocr_powerup(sd);
+} else {
+trace_sdcard_inquiry_cmd41();
+if (!timer_pending(sd->ocr_power_timer)) {
+timer_mod_ns(sd->ocr_power_timer,
+ (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
+  + OCR_POWER_DELAY_NS));
+}
+}
+}
+
+if (FIELD_EX32(sd->ocr & req.arg, OCR, VDD_VOLTAGE_WINDOW)) {
+/*
+ * We accept any voltage.  1 V is nothing.
+ *
+ * Once we're powered up, we advance straight to ready state
+ * unless it's an enquiry ACMD41 (bits 23:0 == 0).
+ */
+sd->state = sd_ready_state;
+}
+
+return sd_r3;
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint64_t addr;
@@ -1812,43 +1856,6 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 }
 
 switch (req.cmd) {
-case 41:  /* ACMD41: SD_APP_OP_COND */
-if (sd->state != sd_idle_state) {
-break;
-}
-/* If it's the first ACMD41 since reset, we need to decide
- * whether to power up. If this is not an enquiry ACMD41,
- * we immediately report power on and proceed below to the
- * ready state, but if it is, we set a timer to model a
- * delay for power up. This works around a bug in EDK2
- * UEFI, which sends an initial enquiry ACMD41, but
- * assumes that the card is in ready state as soon as it
- * sees the power up bit set. */
-if (!FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP)) {
-if ((req.arg & ACMD41_ENQUIRY_MASK) != 0) {
-timer_del(sd->ocr_power_timer);
-sd_ocr_powerup(sd);
-} else {
-trace_sdcard_inquiry_cmd41();
-if (!timer_pending(sd->ocr_power_timer)) {
-timer_mod_ns(sd->ocr_power_timer,
- (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
-  + OCR_POWER_DELAY_NS));
-}
-}
-}
-
-if (FIELD_EX32(sd->ocr & req.arg, OCR, VDD_VOLTAGE_WINDOW)) {
-/* We accept any voltage.  1 V is nothing.
- *
- * Once we're powered up, we advance straight to ready state
- * unless it's an enquiry ACMD41 (bits 23:0 == 0).
- */
-sd->state = sd_ready_state;
-}
-
-return sd_r3;
-
 case 42:  /* ACMD42: SET_CLR_CARD_DETECT */
 switch (sd->state) {
 case sd_transfer_state:
@@ -2379,6 +2386,7 @@ static const SDProto sd_proto_sd = {
 [13] = {8,  sd_adtc, "SD_STATUS", sd_acmd_SD_STATUS},
 [22] = {8,  sd_adtc, "SEND_NUM_WR_BLOCKS", sd_acmd_SEND_NUM_WR_BLOCKS},
 [23] = {8,  sd_ac,   "SET_WR_BLK_ERASE_COUNT", 
sd_acmd_SET_WR_BLK_ERASE_COUNT},
+[41] = {8,  sd_bcr,  "SD_APP_OP_COND", sd_acmd_SD_APP_OP_COND},
 },
 };
 
-- 
2.41.0




Re: [PATCH 02/14] hw/ide: Free macio-ide IRQs

2024-06-28 Thread Mark Cave-Ayland

On 26/06/2024 13:59, Peter Maydell wrote:


On Wed, 26 Jun 2024 at 12:09, Akihiko Odaki  wrote:


This suppresses LeakSanitizer warnings.

Signed-off-by: Akihiko Odaki 
---
  hw/ide/macio.c | 9 +
  1 file changed, 9 insertions(+)

diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index aca90d04f0e8..d8fbc1a17ba6 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -464,6 +464,14 @@ static void macio_ide_initfn(Object *obj)
   qdev_prop_allow_set_link_before_realize, 0);
  }

+static void macio_ide_finalize(Object *obj)
+{
+MACIOIDEState *s = MACIO_IDE(obj);
+
+qemu_free_irq(s->dma_irq);
+qemu_free_irq(s->ide_irq);
+}
+
  static Property macio_ide_properties[] = {
  DEFINE_PROP_UINT32("channel", MACIOIDEState, channel, 0),
  DEFINE_PROP_UINT32("addr", MACIOIDEState, addr, -1),
@@ -486,6 +494,7 @@ static const TypeInfo macio_ide_type_info = {
  .parent = TYPE_SYS_BUS_DEVICE,
  .instance_size = sizeof(MACIOIDEState),
  .instance_init = macio_ide_initfn,
+.instance_finalize = macio_ide_finalize,
  .class_init = macio_ide_class_init,
  };


Rather than this, I suspect macio_ide_initfn() should not
be using qemu_allocate_irq() in the first place. Looks like
maybe a QOM conversion that left a loose end un-tidied-up.


This is definitely old code: there used to be problems interfacing the IDE code with 
qdev due to the hard-coded bus IRQs but I think this may is now possible with the 
advent of ide_bus_init_output_irq().


I'll have a quick look and see what has changed in this area.


ATB,

Mark.




[PATCH v42 82/98] hw/sd/sdcard: Basis for eMMC support

2024-06-28 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Cédric Le Goater 
Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/sd/sd.h |  3 +++
 hw/sd/sd.c | 34 ++
 2 files changed, 37 insertions(+)

diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index 0d6d9e452b..d35a839f5e 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -96,6 +96,9 @@ OBJECT_DECLARE_TYPE(SDState, SDCardClass, SD_CARD)
 #define TYPE_SD_CARD_SPI "sd-card-spi"
 DECLARE_INSTANCE_CHECKER(SDState, SD_CARD_SPI, TYPE_SD_CARD_SPI)
 
+#define TYPE_EMMC "emmc"
+DECLARE_INSTANCE_CHECKER(SDState, EMMC, TYPE_EMMC)
+
 struct SDCardClass {
 /*< private >*/
 DeviceClass parent_class;
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 92ac57a648..249fad0468 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -2379,6 +2379,13 @@ static const SDProto sd_proto_sd = {
 },
 };
 
+static const SDProto sd_proto_emmc = {
+/* Only v4.5 is supported */
+.name = "eMMC",
+.cmd = {
+},
+};
+
 static void sd_instance_init(Object *obj)
 {
 SDState *sd = SD_CARD(obj);
@@ -2504,6 +2511,28 @@ static void sd_spi_class_init(ObjectClass *klass, void 
*data)
 sc->proto = &sd_proto_spi;
 }
 
+static void emmc_realize(DeviceState *dev, Error **errp)
+{
+SDState *sd = SD_CARD(dev);
+
+if (sd->spec_version == SD_PHY_SPECv2_00_VERS) {
+error_setg(errp, "eMMC can not use spec v2.00");
+return;
+}
+
+sd_realize(dev, errp);
+}
+
+static void emmc_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+SDCardClass *sc = SD_CARD_CLASS(klass);
+
+dc->desc = "eMMC";
+dc->realize = emmc_realize;
+sc->proto = &sd_proto_emmc;
+}
+
 static const TypeInfo sd_types[] = {
 {
 .name   = TYPE_SD_CARD,
@@ -2519,6 +2548,11 @@ static const TypeInfo sd_types[] = {
 .parent = TYPE_SD_CARD,
 .class_init = sd_spi_class_init,
 },
+{
+.name = TYPE_EMMC,
+.parent = TYPE_SD_CARD,
+.class_init = emmc_class_init,
+},
 };
 
 DEFINE_TYPES(sd_types)
-- 
2.41.0




[RFC PATCH v42 86/98] hw/sd/sdcard: Add emmc_cmd_SEND_OP_COND handler (CMD1)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Sai Pavan Boddu 

Add support to Power up the card and send response r3 in case of MMC.

Signed-off-by: Sai Pavan Boddu 
Signed-off-by: Edgar E. Iglesias 
Signed-off-by: Cédric Le Goater 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index c6e5c93acb..2dc0209482 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1190,6 +1190,12 @@ static sd_rsp_type_t spi_cmd_SEND_OP_COND(SDState *sd, 
SDRequest req)
 return sd_r1;
 }
 
+static sd_rsp_type_t emmc_cmd_SEND_OP_COND(SDState *sd, SDRequest req)
+{
+sd_ocr_powerup(sd);
+return sd->state == sd_idle_state ? sd_r3 : sd_r0;
+}
+
 /* CMD2 */
 static sd_rsp_type_t sd_cmd_ALL_SEND_CID(SDState *sd, SDRequest req)
 {
@@ -2398,6 +2404,7 @@ static const SDProto sd_proto_emmc = {
 .name = "eMMC",
 .cmd = {
 [0]  = {0,  sd_bc,   "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
+[1]  = {0,  sd_bcr,  "SEND_OP_COND", emmc_cmd_SEND_OP_COND},
 [2]  = {0,  sd_bcr,  "ALL_SEND_CID", sd_cmd_ALL_SEND_CID},
 [3]  = {0,  sd_ac,   "SET_RELATIVE_ADDR", emmc_cmd_SET_RELATIVE_ADDR},
 [4]  = {0,  sd_bc,   "SEND_DSR", sd_cmd_unimplemented},
-- 
2.41.0




[PATCH v42 67/98] hw/sd/sdcard: Add spi_cmd_CRC_ON_OFF handler (CMD59)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index b3b4cd5a3a..2f853a89d1 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1666,6 +1666,12 @@ static sd_rsp_type_t spi_cmd_READ_OCR(SDState *sd, 
SDRequest req)
 return sd_r3;
 }
 
+/* CMD59 */
+static sd_rsp_type_t spi_cmd_CRC_ON_OFF(SDState *sd, SDRequest req)
+{
+return sd_r1;
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint64_t addr;
@@ -1753,10 +1759,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 case 26:  /* CMD26:  PROGRAM_CID */
 return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid));
 
-/* Application specific commands (Class 8) */
-case 59:/* CMD59:   CRC_ON_OFF (SPI) */
-return sd_r1;
-
 default:
 qemu_log_mask(LOG_GUEST_ERROR, "SD: Unknown CMD%i\n", req.cmd);
 return sd_illegal;
@@ -2325,6 +2327,7 @@ static const SDProto sd_proto_spi = {
 [56] = {8,  sd_spi, "GEN_CMD", sd_cmd_GEN_CMD},
 [57] = {10, sd_spi, "DIRECT_SECURE_WRITE", sd_cmd_optional},
 [58] = {0,  sd_spi, "READ_OCR", spi_cmd_READ_OCR},
+[59] = {0,  sd_spi, "CRC_ON_OFF", spi_cmd_CRC_ON_OFF},
 },
 .acmd = {
 [41] = {8,  sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
-- 
2.41.0




[PATCH v42 59/98] hw/sd/sdcard: Add sd_cmd_SET/CLR_WRITE_PROT handler (CMD28 & CMD29)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 91 +++---
 1 file changed, 46 insertions(+), 45 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 9d33113f11..a63213613b 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -244,7 +244,6 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 [21]= "DPS_spec",
 [25]= "WRITE_MULTIPLE_BLOCK",
 [26]= "MANUF_RSVD",
-[28]= "SET_WRITE_PROT", [29]= "CLR_WRITE_PROT",
 [30]= "SEND_WRITE_PROT",
 [32]= "ERASE_WR_BLK_START", [33]= "ERASE_WR_BLK_END",
 [38]= "ERASE",
@@ -1520,6 +1519,48 @@ static sd_rsp_type_t sd_cmd_PROGRAM_CSD(SDState *sd, 
SDRequest req)
 return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->csd));
 }
 
+static sd_rsp_type_t sd_cmd_SET_CLR_WRITE_PROT(SDState *sd, SDRequest req,
+   bool is_write)
+{
+uint64_t addr;
+
+if (sd->size > SDSC_MAX_CAPACITY) {
+return sd_illegal;
+}
+
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+
+addr = sd_req_get_address(sd, req);
+if (!address_in_range(sd, is_write ? "SET_WRITE_PROT" : "CLR_WRITE_PROT",
+  addr, 1)) {
+return sd_r1b;
+}
+
+sd->state = sd_programming_state;
+if (is_write) {
+set_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap);
+} else {
+clear_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap);
+}
+/* Bzzztt  Operation complete.  */
+sd->state = sd_transfer_state;
+return sd_r1;
+}
+
+/* CMD28 */
+static sd_rsp_type_t sd_cmd_SET_WRITE_PROT(SDState *sd, SDRequest req)
+{
+return sd_cmd_SET_CLR_WRITE_PROT(sd, req, true);
+}
+
+/* CMD29 */
+static sd_rsp_type_t sd_cmd_CLR_WRITE_PROT(SDState *sd, SDRequest req)
+{
+return sd_cmd_SET_CLR_WRITE_PROT(sd, req, false);
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint16_t rca;
@@ -1610,50 +1651,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid));
 
 /* Write protection (Class 6) */
-case 28:  /* CMD28:  SET_WRITE_PROT */
-if (sd->size > SDSC_MAX_CAPACITY) {
-return sd_illegal;
-}
-addr = sd_req_get_address(sd, req);
-switch (sd->state) {
-case sd_transfer_state:
-if (!address_in_range(sd, "SET_WRITE_PROT", addr, 1)) {
-return sd_r1b;
-}
-
-sd->state = sd_programming_state;
-set_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap);
-/* Bzzztt  Operation complete.  */
-sd->state = sd_transfer_state;
-return sd_r1b;
-
-default:
-break;
-}
-break;
-
-case 29:  /* CMD29:  CLR_WRITE_PROT */
-if (sd->size > SDSC_MAX_CAPACITY) {
-return sd_illegal;
-}
-addr = sd_req_get_address(sd, req);
-switch (sd->state) {
-case sd_transfer_state:
-if (!address_in_range(sd, "CLR_WRITE_PROT", addr, 1)) {
-return sd_r1b;
-}
-
-sd->state = sd_programming_state;
-clear_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap);
-/* Bzzztt  Operation complete.  */
-sd->state = sd_transfer_state;
-return sd_r1b;
-
-default:
-break;
-}
-break;
-
 case 30:  /* CMD30:  SEND_WRITE_PROT */
 if (sd->size > SDSC_MAX_CAPACITY) {
 return sd_illegal;
@@ -2314,6 +2311,8 @@ static const SDProto sd_proto_spi = {
 [17] = {2,  sd_spi, "READ_SINGLE_BLOCK", sd_cmd_READ_SINGLE_BLOCK},
 [24] = {4,  sd_spi, "WRITE_SINGLE_BLOCK", sd_cmd_WRITE_SINGLE_BLOCK},
 [27] = {4,  sd_spi, "PROGRAM_CSD", sd_cmd_PROGRAM_CSD},
+[28] = {6,  sd_spi, "SET_WRITE_PROT", sd_cmd_SET_WRITE_PROT},
+[29] = {6,  sd_spi, "CLR_WRITE_PROT", sd_cmd_CLR_WRITE_PROT},
 [34] = {10, sd_spi, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_spi, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_spi, "SEND_PSI", sd_cmd_optional},
@@ -2352,6 +2351,8 @@ static const SDProto sd_proto_sd = {
 [23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
 [24] = {4,  sd_adtc, "WRITE_SINGLE_BLOCK", sd_cmd_WRITE_SINGLE_BLOCK},
 [27] = {4,  sd_adtc, "PROGRAM_CSD", sd_cmd_PROGRAM_CSD},
+[28] = {6,  sd_ac,   "SET_WRITE_PROT", sd_cmd_SET_WRITE_PROT},
+[29] = {6,  sd_ac,   "CLR_WRITE_PROT", sd_cmd_CLR_WRITE_PROT},
 [34] = {10, sd_adtc, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_adtc, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_adtc, "SEND_P

[PATCH v42 80/98] hw/sd/sdcard: Introduce set_csd/set_cid handlers

2024-06-28 Thread Philippe Mathieu-Daudé
In preparation of introducing eMMC support which have
different CSD/CID structures, introduce a pair of handlers
in SDCardClass.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/sd/sd.h | 2 ++
 hw/sd/sd.c | 7 +--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index c1a35ab420..0d6d9e452b 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -127,6 +127,8 @@ struct SDCardClass {
 void (*enable)(SDState *sd, bool enable);
 bool (*get_inserted)(SDState *sd);
 bool (*get_readonly)(SDState *sd);
+void (*set_cid)(SDState *sd);
+void (*set_csd)(SDState *sd, uint64_t size);
 
 const struct SDProto *proto;
 };
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index a0da06e017..b0ef252001 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -671,6 +671,7 @@ static inline uint64_t sd_addr_to_wpnum(uint64_t addr)
 static void sd_reset(DeviceState *dev)
 {
 SDState *sd = SD_CARD(dev);
+SDCardClass *sc = SD_CARD_GET_CLASS(sd);
 uint64_t size;
 uint64_t sect;
 
@@ -691,8 +692,8 @@ static void sd_reset(DeviceState *dev)
 sd->size = size;
 sd_set_ocr(sd);
 sd_set_scr(sd);
-sd_set_cid(sd);
-sd_set_csd(sd, size);
+sc->set_cid(sd);
+sc->set_csd(sd, size);
 sd_set_cardstatus(sd);
 sd_set_sdstatus(sd);
 
@@ -2472,6 +2473,8 @@ static void sd_class_init(ObjectClass *klass, void *data)
 sc->enable = sd_enable;
 sc->get_inserted = sd_get_inserted;
 sc->get_readonly = sd_get_readonly;
+sc->set_cid = sd_set_cid;
+sc->set_csd = sd_set_csd;
 sc->proto = &sd_proto_sd;
 }
 
-- 
2.41.0




[PATCH v42 70/98] hw/sd/sdcard: Add sd_acmd_SEND_NUM_WR_BLOCKS handler (ACMD22)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 23 ++-
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 5323a42df2..9d66c3715a 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -263,7 +263,7 @@ static const char *sd_acmd_name(SDState *sd, uint8_t cmd)
 [14] = "DPS_spec",  [15] = "DPS_spec",
 [16] = "DPS_spec",
 [18] = "SECU_spec",
-[22] = "SEND_NUM_WR_BLOCKS",[23] = "SET_WR_BLK_ERASE_COUNT",
+[23] = "SET_WR_BLK_ERASE_COUNT",
 [42] = "SET_CLR_CARD_DETECT",
 [51] = "SEND_SCR",
 [52] = "SECU_spec", [53] = "SECU_spec",
@@ -1689,6 +1689,13 @@ static sd_rsp_type_t sd_acmd_SD_STATUS(SDState *sd, 
SDRequest req)
  sd->sd_status, sizeof(sd->sd_status));
 }
 
+/* ACMD22 */
+static sd_rsp_type_t sd_acmd_SEND_NUM_WR_BLOCKS(SDState *sd, SDRequest req)
+{
+return sd_cmd_to_sendingdata(sd, req, 0,
+ &sd->blk_written, sizeof(sd->blk_written));
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint64_t addr;
@@ -1797,18 +1804,6 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 }
 
 switch (req.cmd) {
-case 22:  /* ACMD22: SEND_NUM_WR_BLOCKS */
-switch (sd->state) {
-case sd_transfer_state:
-return sd_cmd_to_sendingdata(sd, req, 0,
- &sd->blk_written,
- sizeof(sd->blk_written));
-
-default:
-break;
-}
-break;
-
 case 23:  /* ACMD23: SET_WR_BLK_ERASE_COUNT */
 switch (sd->state) {
 case sd_transfer_state:
@@ -2324,6 +2319,7 @@ static const SDProto sd_proto_spi = {
 },
 .acmd = {
 [13] = {8,  sd_spi, "SD_STATUS", sd_acmd_SD_STATUS},
+[22] = {8,  sd_spi, "SEND_NUM_WR_BLOCKS", sd_acmd_SEND_NUM_WR_BLOCKS},
 [41] = {8,  sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
 },
 };
@@ -2382,6 +2378,7 @@ static const SDProto sd_proto_sd = {
 .acmd = {
 [6]  = {8,  sd_ac,   "SET_BUS_WIDTH", sd_acmd_SET_BUS_WIDTH},
 [13] = {8,  sd_adtc, "SD_STATUS", sd_acmd_SD_STATUS},
+[22] = {8,  sd_adtc, "SEND_NUM_WR_BLOCKS", sd_acmd_SEND_NUM_WR_BLOCKS},
 },
 };
 
-- 
2.41.0




[PATCH v42 49/98] hw/sd/sdcard: Add sd_cmd_SEND_IF_COND handler (CMD8)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 43 ---
 1 file changed, 24 insertions(+), 19 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 6ad98db981..e2f7e99ea2 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -240,7 +240,7 @@ static const char *sd_response_name(sd_rsp_type_t rsp)
 static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 {
 static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
- [8]= "SEND_IF_COND",[9]= "SEND_CSD",
+ [9]= "SEND_CSD",
 [10]= "SEND_CID",
 [12]= "STOP_TRANSMISSION",  [13]= "SEND_STATUS",
 [15]= "GO_INACTIVE_STATE",
@@ -1303,6 +1303,27 @@ static sd_rsp_type_t sd_cmd_DE_SELECT_CARD(SDState *sd, 
SDRequest req)
 return sd_invalid_state_for_cmd(sd, req);
 }
 
+/* CMD8 */
+static sd_rsp_type_t sd_cmd_SEND_IF_COND(SDState *sd, SDRequest req)
+{
+if (sd->spec_version < SD_PHY_SPECv2_00_VERS) {
+return sd_cmd_illegal(sd, req);
+}
+if (sd->state != sd_idle_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+sd->vhs = 0;
+
+/* No response if not exactly one VHS bit is set.  */
+if (!(req.arg >> 8) || (req.arg >> (ctz32(req.arg & ~0xff) + 1))) {
+return sd_is_spi(sd) ? sd_r7 : sd_r0;
+}
+
+/* Accept.  */
+sd->vhs = req.arg;
+return sd_r7;
+}
+
 /* CMD19 */
 static sd_rsp_type_t sd_cmd_SEND_TUNING_BLOCK(SDState *sd, SDRequest req)
 {
@@ -1369,24 +1390,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 
 switch (req.cmd) {
 /* Basic commands (Class 0 and Class 1) */
-case 8:  /* CMD8:   SEND_IF_COND */
-if (sd->spec_version < SD_PHY_SPECv2_00_VERS) {
-break;
-}
-if (sd->state != sd_idle_state) {
-break;
-}
-sd->vhs = 0;
-
-/* No response if not exactly one VHS bit is set.  */
-if (!(req.arg >> 8) || (req.arg >> (ctz32(req.arg & ~0xff) + 1))) {
-return sd_is_spi(sd) ? sd_r7 : sd_r0;
-}
-
-/* Accept.  */
-sd->vhs = req.arg;
-return sd_r7;
-
 case 9:  /* CMD9:   SEND_CSD */
 rca = sd_req_get_rca(sd, req);
 switch (sd->state) {
@@ -2278,6 +2281,7 @@ static const SDProto sd_proto_spi = {
 [1]  = {0,  sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
 [5]  = {9,  sd_spi, "IO_SEND_OP_COND", sd_cmd_optional},
 [6]  = {10, sd_spi, "SWITCH_FUNCTION", sd_cmd_SWITCH_FUNCTION},
+[8]  = {0,  sd_spi, "SEND_IF_COND", sd_cmd_SEND_IF_COND},
 [34] = {10, sd_spi, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_spi, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_spi, "SEND_PSI", sd_cmd_optional},
@@ -2302,6 +2306,7 @@ static const SDProto sd_proto_sd = {
 [5]  = {9,  sd_bc,   "IO_SEND_OP_COND", sd_cmd_optional},
 [6]  = {10, sd_adtc, "SWITCH_FUNCTION", sd_cmd_SWITCH_FUNCTION},
 [7]  = {0,  sd_ac,   "(DE)SELECT_CARD", sd_cmd_DE_SELECT_CARD},
+[8]  = {0,  sd_bcr,  "SEND_IF_COND", sd_cmd_SEND_IF_COND},
 [11] = {0,  sd_ac,   "VOLTAGE_SWITCH", sd_cmd_optional},
 [19] = {2,  sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
 [20] = {2,  sd_ac,   "SPEED_CLASS_CONTROL", sd_cmd_optional},
-- 
2.41.0




[PATCH v42 95/98] hw/sd/sdcard: Add mmc SWITCH function support (CMD6)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Sai Pavan Boddu 

switch operation in mmc cards, updated the ext_csd register to
request changes in card operations. Here we implement similar
sequence but requests are mostly dummy and make no change.

Implement SWITCH_ERROR if the write operation offset goes beyond
length of ext_csd.

Signed-off-by: Sai Pavan Boddu 
Signed-off-by: Edgar E. Iglesias 
Signed-off-by: Cédric Le Goater 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 52 
 1 file changed, 52 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index ae5e73175e..e7d8b9c0fb 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -625,6 +625,7 @@ static bool sd_req_rca_same(SDState *s, SDRequest req)
 FIELD(CSR, AKE_SEQ_ERROR,   3,  1)
 FIELD(CSR, APP_CMD, 5,  1)
 FIELD(CSR, FX_EVENT,6,  1)
+FIELD(CSR, SWITCH_ERROR,7,  1)
 FIELD(CSR, READY_FOR_DATA,  8,  1)
 FIELD(CSR, CURRENT_STATE,   9,  4)
 FIELD(CSR, ERASE_RESET,13,  1)
@@ -1075,6 +1076,43 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr)
 return ret;
 }
 
+enum {
+MMC_CMD6_ACCESS_COMMAND_SET = 0,
+MMC_CMD6_ACCESS_SET_BITS,
+MMC_CMD6_ACCESS_CLEAR_BITS,
+MMC_CMD6_ACCESS_WRITE_BYTE,
+};
+
+static void mmc_function_switch(SDState *sd, uint32_t arg)
+{
+uint32_t access = extract32(arg, 24, 2);
+uint32_t index = extract32(arg, 16, 8);
+uint32_t value = extract32(arg, 8, 8);
+uint8_t b = sd->ext_csd[index];
+
+switch (access) {
+case MMC_CMD6_ACCESS_COMMAND_SET:
+qemu_log_mask(LOG_UNIMP, "MMC Command set switching not supported\n");
+return;
+case MMC_CMD6_ACCESS_SET_BITS:
+b |= value;
+break;
+case MMC_CMD6_ACCESS_CLEAR_BITS:
+b &= ~value;
+break;
+case MMC_CMD6_ACCESS_WRITE_BYTE:
+b = value;
+break;
+}
+
+if (index >= 192) {
+sd->card_status |= R_CSR_SWITCH_ERROR_MASK;
+return;
+}
+
+sd->ext_csd[index] = b;
+}
+
 static void sd_function_switch(SDState *sd, uint32_t arg)
 {
 int i, mode, new_func;
@@ -1398,6 +1436,19 @@ static sd_rsp_type_t sd_cmd_SWITCH_FUNCTION(SDState *sd, 
SDRequest req)
 return sd_cmd_to_sendingdata(sd, req, 0, NULL, 64);
 }
 
+static sd_rsp_type_t emmc_cmd_SWITCH(SDState *sd, SDRequest req)
+{
+switch (sd->state) {
+case sd_transfer_state:
+sd->state = sd_programming_state;
+mmc_function_switch(sd, req.arg);
+sd->state = sd_transfer_state;
+return sd_r1b;
+default:
+return sd_invalid_state_for_cmd(sd, req);
+}
+}
+
 /* CMD7 */
 static sd_rsp_type_t sd_cmd_DE_SELECT_CARD(SDState *sd, SDRequest req)
 {
@@ -2602,6 +2653,7 @@ static const SDProto sd_proto_emmc = {
 [3]  = {0,  sd_ac,   "SET_RELATIVE_ADDR", emmc_cmd_SET_RELATIVE_ADDR},
 [4]  = {0,  sd_bc,   "SEND_DSR", sd_cmd_unimplemented},
 [5]  = {0,  sd_ac,   "SLEEP/AWAKE", emmc_cmd_sleep_awake},
+[6]  = {10, sd_adtc, "SWITCH", emmc_cmd_SWITCH},
 [7]  = {0,  sd_ac,   "(DE)SELECT_CARD", sd_cmd_DE_SELECT_CARD},
 [8]  = {0,  sd_adtc, "SEND_EXT_CSD", emmc_cmd_SEND_EXT_CSD},
 [9]  = {0,  sd_ac,   "SEND_CSD", sd_cmd_SEND_CSD},
-- 
2.41.0




[PATCH v42 45/98] hw/sd/sdcard: Register SDIO optional handlers

2024-06-28 Thread Philippe Mathieu-Daudé
See "SD Input/Output Card Specification" v1.00.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 406fadb3b4..87bfd0fd56 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -240,7 +240,6 @@ static const char *sd_response_name(sd_rsp_type_t rsp)
 static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 {
 static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
- [5]= "IO_SEND_OP_COND",
  [6]= "SWITCH_FUNC", [7]= "SELECT/DESELECT_CARD",
  [8]= "SEND_IF_COND",[9]= "SEND_CSD",
 [10]= "SEND_CID",
@@ -260,7 +259,6 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 [40]= "DPS_spec",
 [42]= "LOCK_UNLOCK",
 [50]= "SW_FUNC_RSVD",
-[52]= "IO_RW_DIRECT",   [53]= "IO_RW_EXTENDED",
 [54]= "SDIO_RSVD",  [55]= "APP_CMD",
 [56]= "GEN_CMD",[57]= "SW_FUNC_RSVD",
 [60]= "MANUF_RSVD", [61]= "MANUF_RSVD",
@@ -2270,6 +2268,9 @@ static const SDProto sd_proto_spi = {
 .cmd = {
 [0]  = {0,  sd_spi, "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
 [1]  = {0,  sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
+[5]  = {9,  sd_spi, "IO_SEND_OP_COND", sd_cmd_optional},
+[52] = {9,  sd_spi, "IO_RW_DIRECT", sd_cmd_optional},
+[53] = {9,  sd_spi, "IO_RW_EXTENDED", sd_cmd_optional},
 },
 .acmd = {
 [41] = {8,  sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
@@ -2283,6 +2284,7 @@ static const SDProto sd_proto_sd = {
 [2]  = {0,  sd_bcr,  "ALL_SEND_CID", sd_cmd_ALL_SEND_CID},
 [3]  = {0,  sd_bcr,  "SEND_RELATIVE_ADDR", sd_cmd_SEND_RELATIVE_ADDR},
 [4]  = {0,  sd_bc,   "SEND_DSR", sd_cmd_unimplemented},
+[5]  = {9,  sd_bc,   "IO_SEND_OP_COND", sd_cmd_optional},
 [11] = {0,  sd_ac,   "VOLTAGE_SWITCH", sd_cmd_optional},
 [19] = {2,  sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
 [20] = {2,  sd_ac,   "SPEED_CLASS_CONTROL", sd_cmd_optional},
@@ -2294,6 +2296,8 @@ static const SDProto sd_proto_sd = {
 [47] = {1,  sd_adtc, "Q_WR_TASK", sd_cmd_optional},
 [48] = {1,  sd_adtc, "READ_EXTR_SINGLE", sd_cmd_optional},
 [49] = {1,  sd_adtc, "WRITE_EXTR_SINGLE", sd_cmd_optional},
+[52] = {9,  sd_bc,   "IO_RW_DIRECT", sd_cmd_optional},
+[53] = {9,  sd_bc,   "IO_RW_EXTENDED", sd_cmd_optional},
 [58] = {11, sd_adtc, "READ_EXTR_MULTI", sd_cmd_optional},
 [59] = {11, sd_adtc, "WRITE_EXTR_MULTI", sd_cmd_optional},
 },
-- 
2.41.0




[PATCH v42 57/98] hw/sd/sdcard: Add sd_cmd_WRITE_SINGLE_BLOCK handler (CMD24)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 57 --
 1 file changed, 30 insertions(+), 27 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index e2a7ed8b45..4650d20ee7 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -242,7 +242,7 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
 [18]= "READ_MULTIPLE_BLOCK",
 [21]= "DPS_spec",
-[24]= "WRITE_BLOCK",[25]= "WRITE_MULTIPLE_BLOCK",
+[25]= "WRITE_MULTIPLE_BLOCK",
 [26]= "MANUF_RSVD", [27]= "PROGRAM_CSD",
 [28]= "SET_WRITE_PROT", [29]= "CLR_WRITE_PROT",
 [30]= "SEND_WRITE_PROT",
@@ -1487,6 +1487,33 @@ static sd_rsp_type_t sd_cmd_SET_BLOCK_COUNT(SDState *sd, 
SDRequest req)
 return sd_r1;
 }
 
+/* CMD24 */
+static sd_rsp_type_t sd_cmd_WRITE_SINGLE_BLOCK(SDState *sd, SDRequest req)
+{
+uint64_t addr;
+
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+
+addr = sd_req_get_address(sd, req);
+if (!address_in_range(sd, "WRITE_SINGLE_BLOCK", addr, sd->blk_len)) {
+return sd_r1;
+}
+
+if (sd->size <= SDSC_MAX_CAPACITY) {
+if (sd_wp_addr(sd, addr)) {
+sd->card_status |= WP_VIOLATION;
+}
+}
+if (sd->csd[14] & 0x30) {
+sd->card_status |= WP_VIOLATION;
+}
+
+sd->blk_written = 0;
+return sd_cmd_to_receivingdata(sd, req, addr, sd->blk_len);
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint16_t rca;
@@ -1544,32 +1571,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 break;
 
 /* Block write commands (Class 4) */
-case 24:  /* CMD24:  WRITE_SINGLE_BLOCK */
-addr = sd_req_get_address(sd, req);
-switch (sd->state) {
-case sd_transfer_state:
-
-if (!address_in_range(sd, "WRITE_SINGLE_BLOCK", addr,
-  sd->blk_len)) {
-return sd_r1;
-}
-
-if (sd->size <= SDSC_MAX_CAPACITY) {
-if (sd_wp_addr(sd, sd->data_start)) {
-sd->card_status |= WP_VIOLATION;
-}
-}
-if (sd->csd[14] & 0x30) {
-sd->card_status |= WP_VIOLATION;
-}
-sd->blk_written = 0;
-return sd_cmd_to_receivingdata(sd, req, addr, sd->blk_len);
-
-default:
-break;
-}
-break;
-
 case 25:  /* CMD25:  WRITE_MULTIPLE_BLOCK */
 addr = sd_req_get_address(sd, req);
 switch (sd->state) {
@@ -2308,6 +2309,7 @@ static const SDProto sd_proto_spi = {
 [13] = {0,  sd_spi, "SEND_STATUS", sd_cmd_SEND_STATUS},
 [16] = {2,  sd_spi, "SET_BLOCKLEN", sd_cmd_SET_BLOCKLEN},
 [17] = {2,  sd_spi, "READ_SINGLE_BLOCK", sd_cmd_READ_SINGLE_BLOCK},
+[24] = {4,  sd_spi, "WRITE_SINGLE_BLOCK", sd_cmd_WRITE_SINGLE_BLOCK},
 [34] = {10, sd_spi, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_spi, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_spi, "SEND_PSI", sd_cmd_optional},
@@ -2344,6 +2346,7 @@ static const SDProto sd_proto_sd = {
 [19] = {2,  sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
 [20] = {2,  sd_ac,   "SPEED_CLASS_CONTROL", sd_cmd_optional},
 [23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
+[24] = {4,  sd_adtc, "WRITE_SINGLE_BLOCK", sd_cmd_WRITE_SINGLE_BLOCK},
 [34] = {10, sd_adtc, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_adtc, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_adtc, "SEND_PSI", sd_cmd_optional},
-- 
2.41.0




[PATCH v42 75/98] hw/sd/sdcard: Remove sd_none enum from sd_cmd_type_t

2024-06-28 Thread Philippe Mathieu-Daudé
All handlers using the 'sd_none' enum got converted,
remove it.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/sd/sd.h | 1 -
 hw/sd/sd.c | 7 +--
 2 files changed, 1 insertion(+), 7 deletions(-)

diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index 29c76935a0..c1a35ab420 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -76,7 +76,6 @@ typedef enum  {
 } sd_uhs_mode_t;
 
 typedef enum {
-sd_none = 0,
 sd_spi,
 sd_bc, /* broadcast -- no response */
 sd_bcr,/* broadcast with response */
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 6a9d611429..7f93d363c7 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -526,17 +526,12 @@ static void sd_set_rca(SDState *sd, uint16_t value)
 static uint16_t sd_req_get_rca(SDState *s, SDRequest req)
 {
 switch (s->proto->cmd[req.cmd].type) {
-case sd_none:
-/* Called from legacy code not ported to SDProto array */
-assert(!s->proto->cmd[req.cmd].handler);
-/* fall-through */
 case sd_ac:
 case sd_adtc:
 return req.arg >> 16;
 case sd_spi:
-g_assert_not_reached();
 default:
-return 0;
+g_assert_not_reached();
 }
 }
 
-- 
2.41.0




[PATCH v42 88/98] hw/sd/sdcard: Add mmc_cmd_PROGRAM_CID handler (CMD26)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 7c6f5ccc72..0f9bab105e 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1520,6 +1520,12 @@ static sd_rsp_type_t sd_cmd_WRITE_SINGLE_BLOCK(SDState 
*sd, SDRequest req)
 return sd_cmd_to_receivingdata(sd, req, addr, sd->blk_len);
 }
 
+/* CMD26 */
+static sd_rsp_type_t mmc_cmd_PROGRAM_CID(SDState *sd, SDRequest req)
+{
+return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid));
+}
+
 /* CMD27 */
 static sd_rsp_type_t sd_cmd_PROGRAM_CSD(SDState *sd, SDRequest req)
 {
@@ -1868,9 +1874,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 }
 break;
 
-case 26:  /* CMD26:  PROGRAM_CID */
-return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid));
-
 default:
 qemu_log_mask(LOG_GUEST_ERROR, "SD: Unknown CMD%i\n", req.cmd);
 return sd_illegal;
@@ -2429,6 +2432,7 @@ static const SDProto sd_proto_emmc = {
 [19] = {0,  sd_adtc, "BUSTEST_W", sd_cmd_unimplemented},
 [23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
 [24] = {4,  sd_adtc, "WRITE_SINGLE_BLOCK", sd_cmd_WRITE_SINGLE_BLOCK},
+[26] = {4,  sd_adtc, "PROGRAM_CID", mmc_cmd_PROGRAM_CID},
 [27] = {4,  sd_adtc, "PROGRAM_CSD", sd_cmd_PROGRAM_CSD},
 [28] = {6,  sd_ac,   "SET_WRITE_PROT", sd_cmd_SET_WRITE_PROT},
 [29] = {6,  sd_ac,   "CLR_WRITE_PROT", sd_cmd_CLR_WRITE_PROT},
-- 
2.41.0




[PATCH v42 94/98] hw/sd/sdcard: add emmc_cmd_SEND_TUNING_BLOCK handler (CMD21)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Sai Pavan Boddu 

MMC cards support different tuning sequence for entering HS200 mode.

Signed-off-by: Sai Pavan Boddu 
Signed-off-by: Edgar E. Iglesias 
Signed-off-by: Cédric Le Goater 
Signed-off-by: Cédric Le Goater 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sdmmc-internal.h |  3 +++
 hw/sd/sd.c | 41 +
 2 files changed, 44 insertions(+)

diff --git a/hw/sd/sdmmc-internal.h b/hw/sd/sdmmc-internal.h
index 20d85aea6d..a2769a80aa 100644
--- a/hw/sd/sdmmc-internal.h
+++ b/hw/sd/sdmmc-internal.h
@@ -108,4 +108,7 @@
 #define EXT_CSD_PART_CONFIG_EN_BOOT0(0x1 << 3)
 #define EXT_CSD_PART_CONFIG_EN_USER (0x7 << 3)
 
+#define EXT_CSD_BUS_WIDTH_8_MASK0x4
+#define EXT_CSD_BUS_WIDTH_4_MASK0x2
+
 #endif
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 0561079eff..ae5e73175e 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -698,6 +698,25 @@ static const uint8_t sd_tuning_block_pattern4[64] = {
 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde
 };
 
+static const uint8_t mmc_tuning_block_pattern8[128] = {
+0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
+0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
+0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
+0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
+0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
+0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
+0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
+0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
+0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
+0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
+0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
+0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
+0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
+0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
+0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee
+};
+
 static int sd_req_crc_validate(SDRequest *req)
 {
 uint8_t buffer[5];
@@ -1603,6 +1622,26 @@ static sd_rsp_type_t sd_cmd_SEND_TUNING_BLOCK(SDState 
*sd, SDRequest req)
  sizeof(sd_tuning_block_pattern4));
 }
 
+/* CMD21 */
+static sd_rsp_type_t emmc_cmd_SEND_TUNING_BLOCK(SDState *sd, SDRequest req)
+{
+const uint8_t *buf;
+size_t size;
+
+if (sd->state != sd_transfer_state) {
+sd_invalid_state_for_cmd(sd, req);
+}
+
+if (sd->ext_csd[EXT_CSD_BUS_WIDTH] & EXT_CSD_BUS_WIDTH_8_MASK) {
+buf = mmc_tuning_block_pattern8;
+size = sizeof(mmc_tuning_block_pattern8);
+} else {
+buf = sd_tuning_block_pattern4;
+size = sizeof(sd_tuning_block_pattern4);
+}
+return sd_cmd_to_sendingdata(sd, req, 0, buf, size);
+}
+
 /* CMD23 */
 static sd_rsp_type_t sd_cmd_SET_BLOCK_COUNT(SDState *sd, SDRequest req)
 {
@@ -2391,6 +2430,7 @@ uint8_t sd_read_byte(SDState *sd)
 case 13: /* ACMD13: SD_STATUS */
 case 17: /* CMD17:  READ_SINGLE_BLOCK */
 case 19: /* CMD19:  SEND_TUNING_BLOCK (SD) */
+case 21: /* CMD21:  SEND_TUNING_BLOCK (MMC) */
 case 22: /* ACMD22: SEND_NUM_WR_BLOCKS */
 case 30: /* CMD30:  SEND_WRITE_PROT */
 case 51: /* ACMD51: SEND_SCR */
@@ -2573,6 +2613,7 @@ static const SDProto sd_proto_emmc = {
 [16] = {2,  sd_ac,   "SET_BLOCKLEN", sd_cmd_SET_BLOCKLEN},
 [17] = {2,  sd_adtc, "READ_SINGLE_BLOCK", sd_cmd_READ_SINGLE_BLOCK},
 [19] = {0,  sd_adtc, "BUSTEST_W", sd_cmd_unimplemented},
+[21] = {2,  sd_adtc, "SEND_TUNING_BLOCK", emmc_cmd_SEND_TUNING_BLOCK},
 [23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
 [24] = {4,  sd_adtc, "WRITE_SINGLE_BLOCK", sd_cmd_WRITE_SINGLE_BLOCK},
 [26] = {4,  sd_adtc, "PROGRAM_CID", mmc_cmd_PROGRAM_CID},
-- 
2.41.0




[PATCH v42 71/98] hw/sd/sdcard: Add sd_acmd_SET_WR_BLK_ERASE_COUNT handler (ACMD23)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 9d66c3715a..cd207a3090 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -263,7 +263,6 @@ static const char *sd_acmd_name(SDState *sd, uint8_t cmd)
 [14] = "DPS_spec",  [15] = "DPS_spec",
 [16] = "DPS_spec",
 [18] = "SECU_spec",
-[23] = "SET_WR_BLK_ERASE_COUNT",
 [42] = "SET_CLR_CARD_DETECT",
 [51] = "SEND_SCR",
 [52] = "SECU_spec", [53] = "SECU_spec",
@@ -1696,6 +1695,15 @@ static sd_rsp_type_t sd_acmd_SEND_NUM_WR_BLOCKS(SDState 
*sd, SDRequest req)
  &sd->blk_written, sizeof(sd->blk_written));
 }
 
+/* ACMD23 */
+static sd_rsp_type_t sd_acmd_SET_WR_BLK_ERASE_COUNT(SDState *sd, SDRequest req)
+{
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+return sd_r1;
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint64_t addr;
@@ -1804,16 +1812,6 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 }
 
 switch (req.cmd) {
-case 23:  /* ACMD23: SET_WR_BLK_ERASE_COUNT */
-switch (sd->state) {
-case sd_transfer_state:
-return sd_r1;
-
-default:
-break;
-}
-break;
-
 case 41:  /* ACMD41: SD_APP_OP_COND */
 if (sd->state != sd_idle_state) {
 break;
@@ -2320,6 +2318,7 @@ static const SDProto sd_proto_spi = {
 .acmd = {
 [13] = {8,  sd_spi, "SD_STATUS", sd_acmd_SD_STATUS},
 [22] = {8,  sd_spi, "SEND_NUM_WR_BLOCKS", sd_acmd_SEND_NUM_WR_BLOCKS},
+[23] = {8,  sd_spi, "SET_WR_BLK_ERASE_COUNT", 
sd_acmd_SET_WR_BLK_ERASE_COUNT},
 [41] = {8,  sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
 },
 };
@@ -2379,6 +2378,7 @@ static const SDProto sd_proto_sd = {
 [6]  = {8,  sd_ac,   "SET_BUS_WIDTH", sd_acmd_SET_BUS_WIDTH},
 [13] = {8,  sd_adtc, "SD_STATUS", sd_acmd_SD_STATUS},
 [22] = {8,  sd_adtc, "SEND_NUM_WR_BLOCKS", sd_acmd_SEND_NUM_WR_BLOCKS},
+[23] = {8,  sd_ac,   "SET_WR_BLK_ERASE_COUNT", 
sd_acmd_SET_WR_BLK_ERASE_COUNT},
 },
 };
 
-- 
2.41.0




[PATCH v42 53/98] hw/sd/sdcard: Add sd_cmd_SEND_STATUS handler (CMD13)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 40 
 1 file changed, 28 insertions(+), 12 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 1c092ab43c..bb80d11f87 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -240,7 +240,6 @@ static const char *sd_response_name(sd_rsp_type_t rsp)
 static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 {
 static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
-[13]= "SEND_STATUS",
 [15]= "GO_INACTIVE_STATE",
 [16]= "SET_BLOCKLEN",   [17]= "READ_SINGLE_BLOCK",
 [18]= "READ_MULTIPLE_BLOCK",
@@ -1377,6 +1376,32 @@ static sd_rsp_type_t sd_cmd_STOP_TRANSMISSION(SDState 
*sd, SDRequest req)
 }
 }
 
+/* CMD13 */
+static sd_rsp_type_t sd_cmd_SEND_STATUS(SDState *sd, SDRequest req)
+{
+if (sd->mode != sd_data_transfer_mode) {
+return sd_invalid_mode_for_cmd(sd, req);
+}
+
+switch (sd->state) {
+case sd_standby_state:
+case sd_transfer_state:
+case sd_sendingdata_state:
+case sd_receivingdata_state:
+case sd_programming_state:
+case sd_disconnect_state:
+break;
+default:
+return sd_invalid_state_for_cmd(sd, req);
+}
+
+if (sd_is_spi(sd)) {
+return sd_r2_s;
+}
+
+return sd_req_rca_same(sd, req) ? sd_r1 : sd_r0;
+}
+
 /* CMD19 */
 static sd_rsp_type_t sd_cmd_SEND_TUNING_BLOCK(SDState *sd, SDRequest req)
 {
@@ -1443,17 +1468,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 
 switch (req.cmd) {
 /* Basic commands (Class 0 and Class 1) */
-case 13:  /* CMD13:  SEND_STATUS */
-rca = sd_req_get_rca(sd, req);
-if (sd->mode != sd_data_transfer_mode) {
-return sd_invalid_mode_for_cmd(sd, req);
-}
-if (!sd_is_spi(sd) && sd->rca != rca) {
-return sd_r0;
-}
-
-return sd_r1;
-
 case 15:  /* CMD15:  GO_INACTIVE_STATE */
 if (sd->mode != sd_data_transfer_mode) {
 return sd_invalid_mode_for_cmd(sd, req);
@@ -2279,6 +2293,7 @@ static const SDProto sd_proto_spi = {
 [9]  = {0,  sd_spi, "SEND_CSD", spi_cmd_SEND_CSD},
 [10] = {0,  sd_spi, "SEND_CID", spi_cmd_SEND_CID},
 [12] = {0,  sd_spi, "STOP_TRANSMISSION", sd_cmd_STOP_TRANSMISSION},
+[13] = {0,  sd_spi, "SEND_STATUS", sd_cmd_SEND_STATUS},
 [34] = {10, sd_spi, "READ_SEC_CMD", sd_cmd_optional},
 [35] = {10, sd_spi, "WRITE_SEC_CMD", sd_cmd_optional},
 [36] = {10, sd_spi, "SEND_PSI", sd_cmd_optional},
@@ -2308,6 +2323,7 @@ static const SDProto sd_proto_sd = {
 [10] = {0,  sd_ac,   "SEND_CID", sd_cmd_SEND_CID},
 [11] = {0,  sd_ac,   "VOLTAGE_SWITCH", sd_cmd_optional},
 [12] = {0,  sd_ac,   "STOP_TRANSMISSION", sd_cmd_STOP_TRANSMISSION},
+[13] = {0,  sd_ac,   "SEND_STATUS", sd_cmd_SEND_STATUS},
 [19] = {2,  sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
 [20] = {2,  sd_ac,   "SPEED_CLASS_CONTROL", sd_cmd_optional},
 [23] = {2,  sd_ac,   "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
-- 
2.41.0




[PATCH v42 69/98] hw/sd/sdcard: Add sd_acmd_SD_STATUS handler (ACMD13)

2024-06-28 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 22 +-
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 0310a5a3a1..5323a42df2 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -260,7 +260,6 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
 static const char *sd_acmd_name(SDState *sd, uint8_t cmd)
 {
 static const char *acmd_abbrev[SDMMC_CMD_MAX] = {
-[13] = "SD_STATUS",
 [14] = "DPS_spec",  [15] = "DPS_spec",
 [16] = "DPS_spec",
 [18] = "SECU_spec",
@@ -1683,6 +1682,13 @@ static sd_rsp_type_t sd_acmd_SET_BUS_WIDTH(SDState *sd, 
SDRequest req)
 return sd_r1;
 }
 
+/* ACMD13 */
+static sd_rsp_type_t sd_acmd_SD_STATUS(SDState *sd, SDRequest req)
+{
+return sd_cmd_to_sendingdata(sd, req, 0,
+ sd->sd_status, sizeof(sd->sd_status));
+}
+
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint64_t addr;
@@ -1791,18 +1797,6 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 }
 
 switch (req.cmd) {
-case 13:  /* ACMD13: SD_STATUS */
-switch (sd->state) {
-case sd_transfer_state:
-return sd_cmd_to_sendingdata(sd, req, 0,
- sd->sd_status,
- sizeof(sd->sd_status));
-
-default:
-break;
-}
-break;
-
 case 22:  /* ACMD22: SEND_NUM_WR_BLOCKS */
 switch (sd->state) {
 case sd_transfer_state:
@@ -2329,6 +2323,7 @@ static const SDProto sd_proto_spi = {
 [59] = {0,  sd_spi, "CRC_ON_OFF", spi_cmd_CRC_ON_OFF},
 },
 .acmd = {
+[13] = {8,  sd_spi, "SD_STATUS", sd_acmd_SD_STATUS},
 [41] = {8,  sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND},
 },
 };
@@ -2386,6 +2381,7 @@ static const SDProto sd_proto_sd = {
 },
 .acmd = {
 [6]  = {8,  sd_ac,   "SET_BUS_WIDTH", sd_acmd_SET_BUS_WIDTH},
+[13] = {8,  sd_adtc, "SD_STATUS", sd_acmd_SD_STATUS},
 },
 };
 
-- 
2.41.0




[RFC PATCH v42 91/98] hw/sd/sdcard: Adapt sd_cmd_ALL_SEND_CID handler for eMMC (CMD2)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Cédric Le Goater 

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Cédric Le Goater 
[PMD: Use aspeed_emmc_kludge]
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index dc692fe1fa..f875fcd741 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1218,7 +1218,13 @@ static sd_rsp_type_t emmc_cmd_SEND_OP_COND(SDState *sd, 
SDRequest req)
 static sd_rsp_type_t sd_cmd_ALL_SEND_CID(SDState *sd, SDRequest req)
 {
 switch (sd->state) {
+case sd_idle_state:
+if (!sd->aspeed_emmc_kludge) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+/* fall-through */
 case sd_ready_state:
+/* Bus always won */
 sd->state = sd_identification_state;
 return sd_r2_i;
 default:
-- 
2.41.0




[RFC PATCH v42 93/98] hw/sd/sdcard: Add emmc_cmd_SEND_EXT_CSD handler (CMD8)

2024-06-28 Thread Philippe Mathieu-Daudé
From: Vincent Palatin 

The parameters mimick a real 4GB eMMC, but it can be set to various
sizes. Initially from Vincent Palatin 

eMMC CSD is similar to SD with an option to refer EXT_CSD for larger
devices.

Signed-off-by: Vincent Palatin 
Signed-off-by: Cédric Le Goater 
Signed-off-by: Sai Pavan Boddu 
Signed-off-by: Edgar E. Iglesias 
Signed-off-by: Cédric Le Goater 
Signed-off-by: Philippe Mathieu-Daudé 
---
TODO simplify params, see:
https://lore.kernel.org/qemu-devel/54bc25fd-acea-44a3-b696-c261e7e97...@kaod.org/
---
 hw/sd/sd.c | 91 ++
 1 file changed, 91 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 82e0b5838f..0561079eff 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -122,6 +122,7 @@ struct SDState {
 uint16_t rca;
 uint32_t card_status;
 uint8_t sd_status[64];
+uint8_t ext_csd[512];
 
 /* Static properties */
 
@@ -460,6 +461,82 @@ static const uint8_t sd_csd_rw_mask[16] = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfe,
 };
 
+static void mmc_set_ext_csd(SDState *sd, uint64_t size)
+{
+uint32_t sectcount = size >> HWBLOCK_SHIFT;
+
+memset(sd->ext_csd, 0, sizeof(sd->ext_csd));
+
+sd->ext_csd[EXT_CSD_S_CMD_SET] = 0x1; /* supported command sets */
+sd->ext_csd[EXT_CSD_HPI_FEATURES] = 0x3; /* HPI features  */
+sd->ext_csd[EXT_CSD_BKOPS_SUPPORT] = 0x1; /* Background operations */
+sd->ext_csd[241] = 0xA; /* 1st initialization time after partitioning */
+sd->ext_csd[EXT_CSD_TRIM_MULT] = 0x1; /* Trim multiplier */
+sd->ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT] = 0x15; /* Secure feature */
+sd->ext_csd[EXT_CSD_SEC_ERASE_MULT] = 0x96; /* Secure erase support */
+sd->ext_csd[EXT_CSD_SEC_TRIM_MULT] = 0x96; /* Secure TRIM multiplier */
+sd->ext_csd[EXT_CSD_BOOT_INFO] = 0x7; /* Boot information */
+sd->ext_csd[EXT_CSD_BOOT_MULT] = 0x8; /* Boot partition size. 128KB unit */
+sd->ext_csd[EXT_CSD_ACC_SIZE] = 0x6; /* Access size */
+sd->ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] = 0x4; /* HC Erase unit size */
+sd->ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT] = 0x1; /* HC erase timeout */
+sd->ext_csd[EXT_CSD_REL_WR_SEC_C] = 0x1; /* Reliable write sector count */
+sd->ext_csd[EXT_CSD_HC_WP_GRP_SIZE] = 0x4; /* HC write protect group size 
*/
+sd->ext_csd[EXT_CSD_S_C_VCC] = 0x8; /* Sleep current VCC  */
+sd->ext_csd[EXT_CSD_S_C_VCCQ] = 0x7; /* Sleep current VCCQ */
+sd->ext_csd[EXT_CSD_S_A_TIMEOUT] = 0x11; /* Sleep/Awake timeout */
+sd->ext_csd[215] = (sectcount >> 24) & 0xff; /* Sector count */
+sd->ext_csd[214] = (sectcount >> 16) & 0xff; /* ... */
+sd->ext_csd[213] = (sectcount >> 8) & 0xff;  /* ... */
+sd->ext_csd[EXT_CSD_SEC_CNT] = (sectcount & 0xff);   /* ... */
+sd->ext_csd[210] = 0xa; /* Min write perf for 8bit@52Mhz */
+sd->ext_csd[209] = 0xa; /* Min read perf for 8bit@52Mhz  */
+sd->ext_csd[208] = 0xa; /* Min write perf for 4bit@52Mhz */
+sd->ext_csd[207] = 0xa; /* Min read perf for 4bit@52Mhz */
+sd->ext_csd[206] = 0xa; /* Min write perf for 4bit@26Mhz */
+sd->ext_csd[205] = 0xa; /* Min read perf for 4bit@26Mhz */
+sd->ext_csd[EXT_CSD_PART_SWITCH_TIME] = 0x1;
+sd->ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME] = 0x1;
+sd->ext_csd[EXT_CSD_CARD_TYPE] = 0x7;
+sd->ext_csd[EXT_CSD_STRUCTURE] = 0x2;
+sd->ext_csd[EXT_CSD_REV] = 0x5;
+sd->ext_csd[EXT_CSD_RPMB_MULT] = 0x1; /* RPMB size */
+sd->ext_csd[EXT_CSD_PARTITION_SUPPORT] = 0x3;
+sd->ext_csd[159] = 0x00; /* Max enhanced area size */
+sd->ext_csd[158] = 0x00; /* ... */
+sd->ext_csd[157] = 0xEC; /* ... */
+}
+
+static void sd_emmc_set_csd(SDState *sd, uint64_t size)
+{
+sd->csd[0] = 0xd0;
+sd->csd[1] = 0x0f;
+sd->csd[2] = 0x00;
+sd->csd[3] = 0x32;
+sd->csd[4] = 0x0f;
+if (size <= 2 * GiB) {
+/* use 1k blocks */
+uint32_t csize1k = (size >> (CMULT_SHIFT + 10)) - 1;
+sd->csd[5] = 0x5a;
+sd->csd[6] = 0x80 | ((csize1k >> 10) & 0xf);
+sd->csd[7] = (csize1k >> 2) & 0xff;
+} else { /* >= 2GB : size stored in ext CSD, block addressing */
+sd->csd[5] = 0x59;
+sd->csd[6] = 0x8f;
+sd->csd[7] = 0xff;
+sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_CAPACITY, 1);
+}
+sd->csd[8] = 0xff;
+sd->csd[9] = 0xff;
+sd->csd[10] = 0xf7;
+sd->csd[11] = 0xfe;
+sd->csd[12] = 0x49;
+sd->csd[13] = 0x10;
+sd->csd[14] = 0x00;
+sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1;
+mmc_set_ext_csd(sd, size);
+}
+
 static void sd_set_csd(SDState *sd, uint64_t size)
 {
 int hwblock_shift = HWBLOCK_SHIFT;
@@ -1364,6 +1441,17 @@ static sd_rsp_type_t sd_cmd_SEND_IF_COND(SDState *sd, 
SDRequest req)
 return sd_r7;
 }
 
+/* CMD8 */
+static sd_rsp_type_t emmc_cmd_SEND_EXT_CSD(SDState *sd, SDRequest req)
+{
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
+
+return sd_cmd_to_sendingdata(sd, req

[PATCH v42 79/98] hw/sd/sdcard: Trace length of data read on DAT lines

2024-06-28 Thread Philippe Mathieu-Daudé
Some commands expect less than BLOCK_LENGTH.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 4 ++--
 hw/sd/trace-events | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 64621d4340..a0da06e017 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -2197,8 +2197,8 @@ uint8_t sd_read_byte(SDState *sd)
 io_len = sd_blk_len(sd);
 
 trace_sdcard_read_data(sd->proto->name,
-   sd->last_cmd_name,
-   sd->current_cmd, sd->data_offset, io_len);
+   sd->last_cmd_name, sd->current_cmd,
+   sd->data_offset, sd->data_size, io_len);
 switch (sd->current_cmd) {
 case 6:  /* CMD6:   SWITCH_FUNCTION */
 case 9:  /* CMD9:   SEND_CSD */
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index 6a51b0e906..5dfe6be7b7 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -55,7 +55,7 @@ sdcard_req_addr(uint32_t req_arg, uint64_t addr) "req 0x%" 
PRIx32 " addr 0x%" PR
 sdcard_read_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
 sdcard_write_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
 sdcard_write_data(const char *proto, const char *cmd_desc, uint8_t cmd, 
uint32_t offset, uint8_t value) "%s %20s/ CMD%02d ofs %"PRIu32" value 0x%02x"
-sdcard_read_data(const char *proto, const char *cmd_desc, uint8_t cmd, 
uint32_t offset, uint32_t length) "%s %20s/ CMD%02d ofs %"PRIu32" len %" PRIu32
+sdcard_read_data(const char *proto, const char *cmd_desc, uint8_t cmd, 
uint32_t offset, uint64_t size, uint32_t blklen) "%s %20s/ CMD%02d ofs 
%"PRIu32" size %"PRIu64" blklen %" PRIu32
 sdcard_set_voltage(uint16_t millivolts) "%u mV"
 
 # pxa2xx_mmci.c
-- 
2.41.0




  1   2   3   4   >