* [PATCH v2 01/12] tests/qtest: Disable npcm7xx_sdhci tests using hardcoded RCA
2024-06-25 5:53 [PATCH v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes Philippe Mathieu-Daudé
@ 2024-06-25 5:53 ` Philippe Mathieu-Daudé
2024-06-25 5:53 ` [PATCH v2 02/12] hw/sd/sdcard: Generate random RCA value Philippe Mathieu-Daudé
` (11 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-06-25 5:53 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-block, Philippe Mathieu-Daudé, Cédric Le Goater,
Bin Meng, Hao Wu, Shengtan Mao, Tyrone Ting
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-14984351d803@linaro.org/
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
Cc: Hao Wu <wuhaotsh@google.com>
Cc: Shengtan Mao <stmao@google.com>
Cc: Tyrone Ting <kfting@nuvoton.com>
---
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, 0x41200000, 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, 0x45670000, 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
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 02/12] hw/sd/sdcard: Generate random RCA value
2024-06-25 5:53 [PATCH v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes Philippe Mathieu-Daudé
2024-06-25 5:53 ` [PATCH v2 01/12] tests/qtest: Disable npcm7xx_sdhci tests using hardcoded RCA Philippe Mathieu-Daudé
@ 2024-06-25 5:53 ` Philippe Mathieu-Daudé
2024-06-25 5:53 ` [PATCH v2 03/12] hw/sd/sdcard: Track last command used to help logging Philippe Mathieu-Daudé
` (10 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-06-25 5:53 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-block, Philippe Mathieu-Daudé, Cédric Le Goater,
Bin Meng
Rather than using the obscure 0x4567 magic value,
use a real random one.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Cédric Le Goater <clg@redhat.com>
---
hw/sd/sd.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index a48010cfc1..ec58c5e2a6 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"
@@ -490,11 +491,6 @@ static void sd_set_csd(SDState *sd, uint64_t size)
/* Relative Card Address register */
-static void sd_set_rca(SDState *sd)
-{
- sd->rca += 0x4567;
-}
-
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) {
@@ -1107,7 +1103,7 @@ static sd_rsp_type_t sd_cmd_SEND_RELATIVE_ADDR(SDState *sd, SDRequest req)
case sd_identification_state:
case sd_standby_state:
sd->state = sd_standby_state;
- sd_set_rca(sd);
+ qemu_guest_getrandom_nofail(&sd->rca, sizeof(sd->rca));
return sd_r6;
default:
--
2.41.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 03/12] hw/sd/sdcard: Track last command used to help logging
2024-06-25 5:53 [PATCH v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes Philippe Mathieu-Daudé
2024-06-25 5:53 ` [PATCH v2 01/12] tests/qtest: Disable npcm7xx_sdhci tests using hardcoded RCA Philippe Mathieu-Daudé
2024-06-25 5:53 ` [PATCH v2 02/12] hw/sd/sdcard: Generate random RCA value Philippe Mathieu-Daudé
@ 2024-06-25 5:53 ` Philippe Mathieu-Daudé
2024-06-25 5:53 ` [PATCH v2 04/12] hw/sd/sdcard: Trace block offset in READ/WRITE data accesses Philippe Mathieu-Daudé
` (9 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-06-25 5:53 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-block, Philippe Mathieu-Daudé, Cédric Le Goater,
Bin Meng
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é <philmd@linaro.org>
Tested-by: Cédric Le Goater <clg@redhat.com>
---
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 ec58c5e2a6..14bfcc5d6b 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -134,6 +134,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!
*/
@@ -1150,12 +1151,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));
}
@@ -1616,7 +1618,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;
@@ -1909,7 +1912,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 */
@@ -2065,7 +2068,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 */
@@ -2210,6 +2213,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
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 04/12] hw/sd/sdcard: Trace block offset in READ/WRITE data accesses
2024-06-25 5:53 [PATCH v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes Philippe Mathieu-Daudé
` (2 preceding siblings ...)
2024-06-25 5:53 ` [PATCH v2 03/12] hw/sd/sdcard: Track last command used to help logging Philippe Mathieu-Daudé
@ 2024-06-25 5:53 ` Philippe Mathieu-Daudé
2024-06-25 5:53 ` [PATCH v2 05/12] hw/sd/sdcard: Do not store vendor data on block drive (CMD56) Philippe Mathieu-Daudé
` (8 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-06-25 5:53 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-block, Philippe Mathieu-Daudé, Cédric Le Goater,
Bin Meng
Useful to detect out of bound accesses.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Cédric Le Goater <clg@redhat.com>
---
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 14bfcc5d6b..e4587a0a37 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1913,7 +1913,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;
@@ -2069,7 +2069,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
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 05/12] hw/sd/sdcard: Do not store vendor data on block drive (CMD56)
2024-06-25 5:53 [PATCH v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes Philippe Mathieu-Daudé
` (3 preceding siblings ...)
2024-06-25 5:53 ` [PATCH v2 04/12] hw/sd/sdcard: Trace block offset in READ/WRITE data accesses Philippe Mathieu-Daudé
@ 2024-06-25 5:53 ` Philippe Mathieu-Daudé
2024-06-25 5:53 ` [PATCH v2 06/12] hw/sd/sdcard: Send WRITE_PROT bits MSB first (CMD30) Philippe Mathieu-Daudé
` (7 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-06-25 5:53 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-block, Philippe Mathieu-Daudé, Cédric Le Goater,
Bin Meng, Peter Xu, Fabiano Rosas
"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é <philmd@linaro.org>
Tested-by: Cédric Le Goater <clg@redhat.com>
---
RFC: Is it safe to reuse VMSTATE_UNUSED_V() (which happens
to be the same size)?
Cc: Peter Xu <peterx@redhat.com>
Cc: Fabiano Rosas <farosas@suse.de>
---
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 e4587a0a37..0f8440efcc 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -143,6 +143,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;
@@ -647,6 +649,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;
@@ -762,7 +765,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()
},
@@ -2020,9 +2023,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;
@@ -2156,12 +2158,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
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 06/12] hw/sd/sdcard: Send WRITE_PROT bits MSB first (CMD30)
2024-06-25 5:53 [PATCH v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes Philippe Mathieu-Daudé
` (4 preceding siblings ...)
2024-06-25 5:53 ` [PATCH v2 05/12] hw/sd/sdcard: Do not store vendor data on block drive (CMD56) Philippe Mathieu-Daudé
@ 2024-06-25 5:53 ` Philippe Mathieu-Daudé
2024-06-25 5:53 ` [PATCH v2 07/12] hw/sd/sdcard: Send NUM_WR_BLOCKS bits MSB first (ACMD22) Philippe Mathieu-Daudé
` (6 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-06-25 5:53 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-block, Philippe Mathieu-Daudé, Cédric Le Goater,
Bin Meng, Peter Maydell
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é <philmd@linaro.org>
Tested-by: Cédric Le Goater <clg@redhat.com>
---
RFC because I'm surprised this has been unnoticed for 17 years
(commit a1bb27b1e9 "initial SD card emulation", April 2007).
Cc: Peter Maydell <peter.maydell@linaro.org>
---
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 0f8440efcc..b604b8e71f 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1498,7 +1498,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
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 07/12] hw/sd/sdcard: Send NUM_WR_BLOCKS bits MSB first (ACMD22)
2024-06-25 5:53 [PATCH v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes Philippe Mathieu-Daudé
` (5 preceding siblings ...)
2024-06-25 5:53 ` [PATCH v2 06/12] hw/sd/sdcard: Send WRITE_PROT bits MSB first (CMD30) Philippe Mathieu-Daudé
@ 2024-06-25 5:53 ` Philippe Mathieu-Daudé
2024-06-25 5:53 ` [PATCH v2 08/12] hw/sd/sdcard: Use READY_FOR_DATA definition instead of magic value Philippe Mathieu-Daudé
` (5 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-06-25 5:53 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-block, Philippe Mathieu-Daudé, Cédric Le Goater,
Bin Meng, Peter Maydell
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é <philmd@linaro.org>
Tested-by: Cédric Le Goater <clg@redhat.com>
---
RFC because I'm surprised this has been unnoticed for 17 years
(commit a1bb27b1e9 "initial SD card emulation", April 2007).
Cc: Peter Maydell <peter.maydell@linaro.org>
---
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 b604b8e71f..0742ba8b38 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1659,8 +1659,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
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 08/12] hw/sd/sdcard: Use READY_FOR_DATA definition instead of magic value
2024-06-25 5:53 [PATCH v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes Philippe Mathieu-Daudé
` (6 preceding siblings ...)
2024-06-25 5:53 ` [PATCH v2 07/12] hw/sd/sdcard: Send NUM_WR_BLOCKS bits MSB first (ACMD22) Philippe Mathieu-Daudé
@ 2024-06-25 5:53 ` Philippe Mathieu-Daudé
2024-06-25 5:53 ` [PATCH v2 09/12] hw/sd/sdcard: Assign SDCardStates enum values Philippe Mathieu-Daudé
` (4 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-06-25 5:53 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-block, Philippe Mathieu-Daudé, Cédric Le Goater,
Bin Meng
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
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 0742ba8b38..8816bd6671 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -557,7 +557,7 @@ FIELD(CSR, OUT_OF_RANGE, 31, 1)
static void sd_set_cardstatus(SDState *sd)
{
- sd->card_status = 0x00000100;
+ sd->card_status = READY_FOR_DATA;
}
static void sd_set_sdstatus(SDState *sd)
--
2.41.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 09/12] hw/sd/sdcard: Assign SDCardStates enum values
2024-06-25 5:53 [PATCH v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes Philippe Mathieu-Daudé
` (7 preceding siblings ...)
2024-06-25 5:53 ` [PATCH v2 08/12] hw/sd/sdcard: Use READY_FOR_DATA definition instead of magic value Philippe Mathieu-Daudé
@ 2024-06-25 5:53 ` Philippe Mathieu-Daudé
2024-06-25 5:53 ` [PATCH v2 10/12] hw/sd/sdcard: Simplify sd_inactive_state handling Philippe Mathieu-Daudé
` (3 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-06-25 5:53 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-block, Philippe Mathieu-Daudé, Cédric Le Goater,
Bin Meng
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é <philmd@linaro.org>
---
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 8816bd6671..36955189e8 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -76,16 +76,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
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 10/12] hw/sd/sdcard: Simplify sd_inactive_state handling
2024-06-25 5:53 [PATCH v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes Philippe Mathieu-Daudé
` (8 preceding siblings ...)
2024-06-25 5:53 ` [PATCH v2 09/12] hw/sd/sdcard: Assign SDCardStates enum values Philippe Mathieu-Daudé
@ 2024-06-25 5:53 ` Philippe Mathieu-Daudé
2024-06-25 5:53 ` [PATCH v2 11/12] hw/sd/sdcard: Restrict SWITCH_FUNCTION to sd_transfer_state (CMD6) Philippe Mathieu-Daudé
` (2 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-06-25 5:53 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-block, Philippe Mathieu-Daudé, Cédric Le Goater,
Bin Meng
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é <philmd@linaro.org>
---
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 36955189e8..fce99d655d 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1072,10 +1072,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;
}
@@ -1570,7 +1568,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) {
@@ -1791,6 +1788,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
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 11/12] hw/sd/sdcard: Restrict SWITCH_FUNCTION to sd_transfer_state (CMD6)
2024-06-25 5:53 [PATCH v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes Philippe Mathieu-Daudé
` (9 preceding siblings ...)
2024-06-25 5:53 ` [PATCH v2 10/12] hw/sd/sdcard: Simplify sd_inactive_state handling Philippe Mathieu-Daudé
@ 2024-06-25 5:53 ` Philippe Mathieu-Daudé
2024-06-25 5:53 ` [PATCH v2 12/12] hw/sd/sdcard: Add direct reference to SDProto in SDState Philippe Mathieu-Daudé
2024-06-25 7:03 ` [PATCH v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes Cédric Le Goater
12 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-06-25 5:53 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-block, Philippe Mathieu-Daudé, Cédric Le Goater,
Bin Meng
SWITCH_FUNCTION is only allowed in TRANSFER state
(See 4.8 "Card State Transition Table).
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
hw/sd/sd.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index fce99d655d..3b885ba8a0 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1196,6 +1196,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
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 12/12] hw/sd/sdcard: Add direct reference to SDProto in SDState
2024-06-25 5:53 [PATCH v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes Philippe Mathieu-Daudé
` (10 preceding siblings ...)
2024-06-25 5:53 ` [PATCH v2 11/12] hw/sd/sdcard: Restrict SWITCH_FUNCTION to sd_transfer_state (CMD6) Philippe Mathieu-Daudé
@ 2024-06-25 5:53 ` Philippe Mathieu-Daudé
2024-06-25 7:03 ` [PATCH v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes Cédric Le Goater
12 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-06-25 5:53 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-block, Philippe Mathieu-Daudé, Cédric Le Goater,
Bin Meng
Keep direct reference to SDProto in SDState,
remove then unnecessary sd_proto().
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
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 3b885ba8a0..6685fba4bb 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -117,6 +117,8 @@ struct SDState {
uint8_t spec_version;
BlockBackend *blk;
+ const SDProto *proto;
+
/* Runtime changeables */
uint32_t mode; /* current card mode, one of SDCardModes */
@@ -155,18 +157,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)
@@ -1035,7 +1030,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;
@@ -1044,7 +1039,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;
@@ -1053,7 +1048,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;
@@ -1064,7 +1059,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;
}
@@ -1157,7 +1152,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));
}
@@ -1176,8 +1171,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) {
@@ -1623,12 +1618,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) {
@@ -1919,7 +1914,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) {
@@ -2074,7 +2069,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) {
@@ -2218,7 +2213,9 @@ static const SDProto sd_proto_sd = {
static void sd_instance_init(Object *obj)
{
SDState *sd = SD_CARD(obj);
+ SDCardClass *sc = SD_CARD_GET_CLASS(sd);
+ sd->proto = sc->proto;
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
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes
2024-06-25 5:53 [PATCH v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes Philippe Mathieu-Daudé
` (11 preceding siblings ...)
2024-06-25 5:53 ` [PATCH v2 12/12] hw/sd/sdcard: Add direct reference to SDProto in SDState Philippe Mathieu-Daudé
@ 2024-06-25 7:03 ` Cédric Le Goater
12 siblings, 0 replies; 14+ messages in thread
From: Cédric Le Goater @ 2024-06-25 7:03 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel; +Cc: qemu-block, Bin Meng
On 6/25/24 7:53 AM, Philippe Mathieu-Daudé wrote:
> Since v1:
> - various patches merged, few more added
>
> Various SD card cleanups and fixes accumulated over
> the years. Various have been useful to help integrating
> eMMC support (which will come later).
>
> Philippe Mathieu-Daudé (12):
> tests/qtest: Disable npcm7xx_sdhci tests using hardcoded RCA
> hw/sd/sdcard: Generate random RCA value
> hw/sd/sdcard: Track last command used to help logging
> hw/sd/sdcard: Trace block offset in READ/WRITE data accesses
> 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/sd.c | 119 ++++++++++++++++---------------
> tests/qtest/npcm7xx_sdhci-test.c | 7 ++
> hw/sd/trace-events | 4 +-
> 3 files changed, 70 insertions(+), 60 deletions(-)
>
Tested-by: Cédric Le Goater <clg@redhat.com>
Thanks,
C.
^ permalink raw reply [flat|nested] 14+ messages in thread