Re: [PATCH v3] hw/pflash: fix block write start

2024-05-15 Thread Philippe Mathieu-Daudé

On 15/5/24 10:43, Gerd Hoffmann wrote:

Move the pflash_blk_write_start() call.  We need the offset of the
first data write, not the offset for the setup (number-of-bytes)
write.  Without this fix u-boot can do block writes to the first
flash block only.


Wow, that is a fast fix :) Thanks!


While being at it drop a leftover FIXME.

Resolves: #2343

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2343

I suppose we also need:
Cc: qemu-sta...@nongnu.org

Reviewed-by: Philippe Mathieu-Daudé 


Fixes: fcc79f2e0955 ("hw/pflash: implement update buffer for block writes")
Signed-off-by: Gerd Hoffmann 
---
  hw/block/pflash_cfi01.c | 8 +++-
  1 file changed, 3 insertions(+), 5 deletions(-)





Re: [PATCH v6 12/12] tests/qtest/vhost-user-test: add a test case for memory-backend-shm

2024-05-28 Thread Philippe Mathieu-Daudé

On 28/5/24 12:38, Stefano Garzarella wrote:

`memory-backend-shm` can be used with vhost-user devices, so let's
add a new test case for it.

Acked-by: Thomas Huth 
Acked-by: Stefan Hajnoczi 
Reviewed-by: David Hildenbrand 
Signed-off-by: Stefano Garzarella 
---
  tests/qtest/vhost-user-test.c | 23 +++
  1 file changed, 23 insertions(+)


Reviewed-by: Philippe Mathieu-Daudé 




Re: [RFC PATCH v2 21/22] qapi: Inline and remove QERR_UNSUPPORTED definition

2024-06-12 Thread Philippe Mathieu-Daudé

Michael, Konstantin, QERR_UNSUPPORTED is only used by QGA.

Do you mind giving our maintainer's position on Markus
analysis so we can know how to proceed with this definition?

Regards,

Phil.

On 5/10/23 13:22, Markus Armbruster wrote:

Philippe Mathieu-Daudé  writes:


Address the comment added in commit 4629ed1e98
("qerror: Finally unused, clean up"), from 2015:

   /*
* These macros will go away, please don't use
* in new code, and do not add new ones!
*/

Mechanical transformation using:

   $ sed -i -e 's/QERR_UNSUPPORTED/"this feature or command is not currently 
supported"/' \
 $(git grep -wl QERR_UNSUPPORTED)

then manually removing the definition in include/qapi/qmp/qerror.h.

Signed-off-by: Philippe Mathieu-Daudé 
---
RFC: Not sure what is the best way to change the comment
  in qga/qapi-schema.json...
---
  qga/qapi-schema.json  |  5 +++--
  include/qapi/qmp/qerror.h |  3 ---
  qga/commands-bsd.c|  8 +++
  qga/commands-posix.c  | 46 +++
  qga/commands-win32.c  | 22 +--
  5 files changed, 41 insertions(+), 43 deletions(-)

diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index b720dd4379..51683f4dc2 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -6,8 +6,9 @@

##
# = General note concerning the use of guest agent interfaces

  #
  # "unsupported" is a higher-level error than the errors that
  # individual commands might document.  The caller should always be
-# prepared to receive QERR_UNSUPPORTED, even if the given command
-# doesn't specify it, or doesn't document any failure mode at all.
+# prepared to receive the "this feature or command is not currently supported"
+# message, even if the given command doesn't specify it, or doesn't document
+# any failure mode at all.
  ##
  
  ##


The comment is problematic before the patch.  It's a doc comment,
i.e. it goes into the "QEMU Guest Agent Protocol Reference" manual,
where QERR_UNSUPPORTED is meaningless.  Back when the comment was added
(commit 9481ecd737b "qga schema: document generic QERR_UNSUPPORTED"), it
was still internal documentation, where QERR_UNSUPPORTED made sense.  It
became external documentation four years later (commit 56e8bdd46a8
"build-sys: add qapi doc generation targets")

I'm not sure how useful the comment is.

I guess we could instead simply point out that clients should always be
prepared for errors, even when the command doesn't document any, simply
because commands need not exist in all versions or builds of qemu-ga.


diff --git a/include/qapi/qmp/qerror.h b/include/qapi/qmp/qerror.h
index 840831cc6a..7606f4525d 100644
--- a/include/qapi/qmp/qerror.h
+++ b/include/qapi/qmp/qerror.h
@@ -17,7 +17,4 @@
   * add new ones!
   */
  
-#define QERR_UNSUPPORTED \

-"this feature or command is not currently supported"
-
  #endif /* QERROR_H */
diff --git a/qga/commands-bsd.c b/qga/commands-bsd.c
index 17bddda1cf..11536f148f 100644
--- a/qga/commands-bsd.c
+++ b/qga/commands-bsd.c
@@ -152,25 +152,25 @@ int qmp_guest_fsfreeze_do_thaw(Error **errp)
  
  GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)

  {
-error_setg(errp, QERR_UNSUPPORTED);
+error_setg(errp, "this feature or command is not currently supported");
  return NULL;
  }
  
  GuestDiskInfoList *qmp_guest_get_disks(Error **errp)

  {
-error_setg(errp, QERR_UNSUPPORTED);
+error_setg(errp, "this feature or command is not currently supported");
  return NULL;
  }
  
  GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error **errp)

  {
-error_setg(errp, QERR_UNSUPPORTED);
+error_setg(errp, "this feature or command is not currently supported");
  return NULL;
  }
  
  GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)

  {
-error_setg(errp, QERR_UNSUPPORTED);
+error_setg(errp, "this feature or command is not currently supported");
  return NULL;
  }


These are all commands that are not supported by this build of qemu-ga.
We could use the opportunity to improve the error message: scratch
"feature or ".  Or maybe change the message to "this command is not
supported in this version of qemu-ga".

More of the same below, marked [*].

Taking a step back...  Do we really need to make this a failure of its
own?  Why not fail exactly as if the command didn't exist?  Why would a
client ever care for the difference between "command doesn't exist in
this build of qemu-ga (but it does in other builds of this version of
qemu-ga)" and "command doesn't exist in this build of qemu-ga (and it
won't in any build of this version of qemu-ga)"?

If clients don't care, we could instead unregister these commands,
i.e. undo qmp_register_command().  The command will the

Re: [RFC PATCH v2 21/22] qapi: Inline and remove QERR_UNSUPPORTED definition

2024-06-12 Thread Philippe Mathieu-Daudé

On 12/6/24 15:07, Markus Armbruster wrote:

Philippe Mathieu-Daudé  writes:


Michael, Konstantin, QERR_UNSUPPORTED is only used by QGA.

Do you mind giving our maintainer's position on Markus
analysis so we can know how to proceed with this definition?


Daniel Berrangé recently posted patches that get rid of most instances
of QERR_UNSUPPORTED:

 [PATCH 00/20] qga: clean up command source locations and conditionals
 
https://lore.kernel.org/qemu-devel/20240604134933.220112-1-berra...@redhat.com/

I pointed out a possible opportunity to remove even more.

I think we should let the dust settle there, then figure out how to
eliminate remaining QERR_UNSUPPORTED, if any.


Ah great, thanks for the update :)




Re: [PATCH v8 01/13] qapi: clarify that the default is backend dependent

2024-06-18 Thread Philippe Mathieu-Daudé

On 18/6/24 12:00, Stefano Garzarella wrote:

The default value of the @share option of the @MemoryBackendProperties
really depends on the backend type, so let's document the default
values in the same place where we define the option to avoid
dispersing the information.

Cc: David Hildenbrand 
Suggested-by: Markus Armbruster 
Reviewed-by: Markus Armbruster 
Signed-off-by: Stefano Garzarella 
---
v2: https://patchew.org/QEMU/20240611130231.83152-1-sgarz...@redhat.com/
v1: https://patchew.org/QEMU/20240523133302.103858-1-sgarz...@redhat.com/
---
  qapi/qom.json | 8 +++-
  1 file changed, 3 insertions(+), 5 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 




Re: [PATCH] block: m25p80: Fix heap-buffer-overflow in flash_erase function

2024-06-18 Thread Philippe Mathieu-Daudé

Hi Zheyu,

On 18/6/24 17:23, Zheyu Ma wrote:

This patch fixes a heap-buffer-overflow issue in the flash_erase function
of the m25p80 flash memory emulation. The overflow occurs when the
combination of offset and length exceeds the allocated memory for the
storage. The patch adds a check to ensure that the erase length does not
exceed the storage size and adjusts the length accordingly if necessary.

Reproducer:
cat << EOF | qemu-system-aarch64 -display none \
-machine accel=qtest, -m 512M -machine kudo-bmc -qtest stdio
writeq 0xc010 0x6
writel 0xc00c 0x9
writeq 0xc010 0xf27f9412
writeq 0xc00f 0x2b5cdc26
writeq 0xc00c 0x
writeq 0xc00c 0x
writeq 0xc00c 0x
writel 0xc00c 0x9
writeq 0xc00c 0x9
EOF

ASan log:
==2614308==ERROR: AddressSanitizer: heap-buffer-overflow on address 
0x7fd3fb7fc000 at pc 0x55aa77a442dc bp 0x7fffaa155900 sp 0x7fffaa1550c8
WRITE of size 65536 at 0x7fd3fb7fc000 thread T0
 #0 0x55aa77a442db in __asan_memset 
llvm/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:26:3
 #1 0x55aa77e7e6b3 in flash_erase hw/block/m25p80.c:631:5
 #2 0x55aa77e6f8b1 in complete_collecting_data hw/block/m25p80.c:773:9
 #3 0x55aa77e6aaa9 in m25p80_transfer8 hw/block/m25p80.c:1550:13
 #4 0x55aa78e9a691 in ssi_transfer_raw_default hw/ssi/ssi.c:92:16
 #5 0x55aa78e996c0 in ssi_transfer hw/ssi/ssi.c:165:14
 #6 0x55aa78e8d76a in npcm7xx_fiu_uma_transaction hw/ssi/npcm7xx_fiu.c:336:9
 #7 0x55aa78e8be4b in npcm7xx_fiu_ctrl_write hw/ssi/npcm7xx_fiu.c:428:13

Signed-off-by: Zheyu Ma 
---
  hw/block/m25p80.c | 6 ++
  1 file changed, 6 insertions(+)

diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 8dec134832..e9a59f6616 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -617,6 +617,12 @@ static void flash_erase(Flash *s, int offset, FlashCMD cmd)
  abort();
  }
  
+if (offset + len > s->size) {

+qemu_log_mask(LOG_GUEST_ERROR,
+  "M25P80: Erase exceeds storage size, adjusting 
length\n");


Usually hardware doesn't "adjust" but report error earlier.


+len = s->size - offset;
+}
+
  trace_m25p80_flash_erase(s, offset, len);
  
  if ((s->pi->flags & capa_to_assert) != capa_to_assert) {





Re: [PATCH] block: m25p80: Fix heap-buffer-overflow in flash_erase function

2024-06-18 Thread Philippe Mathieu-Daudé

On 18/6/24 21:11, Zheyu Ma wrote:

Thanks for your useful advice!

So how about report the issue and return:


We might report the issue to the user, but there should
be a way the hardware report the issue to the guest software
running. Usually signaled as error condition, irq, ...
We need to figure out what check wasn't properly done.
The spec is the source of truth.


diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 8dec134832..2121b43708 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -617,6 +617,12 @@ static void flash_erase(Flash *s, int offset, 
FlashCMD cmd)

          abort();
      }

+    if (offset + len > s->size) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "M25P80: Erase operation exceeds storage size\n");
+        return;
+    }
+
      trace_m25p80_flash_erase(s, offset, len);

      if ((s->pi->flags & capa_to_assert) != capa_to_assert) {

regards,
Zheyu

On Tue, Jun 18, 2024 at 5:35 PM Philippe Mathieu-Daudé 
mailto:phi...@linaro.org>> wrote:


Hi Zheyu,

On 18/6/24 17:23, Zheyu Ma wrote:
 > This patch fixes a heap-buffer-overflow issue in the flash_erase
function
 > of the m25p80 flash memory emulation. The overflow occurs when the
 > combination of offset and length exceeds the allocated memory for the
 > storage. The patch adds a check to ensure that the erase length
does not
 > exceed the storage size and adjusts the length accordingly if
necessary.
 >
 > Reproducer:
 > cat << EOF | qemu-system-aarch64 -display none \
 > -machine accel=qtest, -m 512M -machine kudo-bmc -qtest stdio
 > writeq 0xc010 0x6
 > writel 0xc00c 0x9
 > writeq 0xc010 0xf27f9412
 > writeq 0xc00f 0x2b5cdc26
 > writeq 0xc00c 0x
 > writeq 0xc00c 0x
 > writeq 0xc00c 0x
 > writel 0xc00c 0x9
 > writeq 0xc00c 0x9
 > EOF
 >
 > ASan log:
 > ==2614308==ERROR: AddressSanitizer: heap-buffer-overflow on
address 0x7fd3fb7fc000 at pc 0x55aa77a442dc bp 0x7fffaa155900 sp
0x7fffaa1550c8
 > WRITE of size 65536 at 0x7fd3fb7fc000 thread T0
 >      #0 0x55aa77a442db in __asan_memset
llvm/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:26:3
 >      #1 0x55aa77e7e6b3 in flash_erase hw/block/m25p80.c:631:5
 >      #2 0x55aa77e6f8b1 in complete_collecting_data
hw/block/m25p80.c:773:9
 >      #3 0x55aa77e6aaa9 in m25p80_transfer8 hw/block/m25p80.c:1550:13
 >      #4 0x55aa78e9a691 in ssi_transfer_raw_default hw/ssi/ssi.c:92:16
 >      #5 0x55aa78e996c0 in ssi_transfer hw/ssi/ssi.c:165:14
 >      #6 0x55aa78e8d76a in npcm7xx_fiu_uma_transaction
hw/ssi/npcm7xx_fiu.c:336:9
 >      #7 0x55aa78e8be4b in npcm7xx_fiu_ctrl_write
hw/ssi/npcm7xx_fiu.c:428:13
 >
 > Signed-off-by: Zheyu Ma mailto:zheyum...@gmail.com>>
 > ---
 >   hw/block/m25p80.c | 6 ++
 >   1 file changed, 6 insertions(+)
 >
 > diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
 > index 8dec134832..e9a59f6616 100644
 > --- a/hw/block/m25p80.c
 > +++ b/hw/block/m25p80.c
 > @@ -617,6 +617,12 @@ static void flash_erase(Flash *s, int
offset, FlashCMD cmd)
 >           abort();
 >       }
 >
 > +    if (offset + len > s->size) {
 > +        qemu_log_mask(LOG_GUEST_ERROR,
 > +                      "M25P80: Erase exceeds storage size,
adjusting length\n");

Usually hardware doesn't "adjust" but report error earlier.

 > +        len = s->size - offset;
 > +    }
 > +
 >       trace_m25p80_flash_erase(s, offset, len);
 >
 >       if ((s->pi->flags & capa_to_assert) != capa_to_assert) {






Re: [PATCH-for-9.0? 0/2] hw/sd/sdcard: Avoid OOB in sd_read_byte()

2024-06-20 Thread Philippe Mathieu-Daudé

On 8/4/24 16:17, Philippe Mathieu-Daudé wrote:

Since this is Fix day, I went over this old bug:
https://gitlab.com/qemu-project/qemu/-/issues/487
It happens to be a QEMU implementation detail not
really related to the spec.

Philippe Mathieu-Daudé (2):
   hw/sd/sdcard: Avoid OOB in sd_read_byte() during unexpected CMD switch


First patch queued.




[PATCH 03/23] hw/sd/sdcard: Fix typo in SEND_OP_COND command name

2024-06-21 Thread Philippe Mathieu-Daudé
There is no SEND_OP_CMD but SEND_OP_COND.

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

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index addeb1940f..331cef5779 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1035,7 +1035,7 @@ static sd_rsp_type_t sd_cmd_GO_IDLE_STATE(SDState *sd, 
SDRequest req)
 return sd_is_spi(sd) ? sd_r1 : sd_r0;
 }
 
-static sd_rsp_type_t sd_cmd_SEND_OP_CMD(SDState *sd, SDRequest req)
+static sd_rsp_type_t spi_cmd_SEND_OP_COND(SDState *sd, SDRequest req)
 {
 sd->state = sd_transfer_state;
 
@@ -2149,7 +2149,7 @@ static const SDProto sd_proto_spi = {
 .name = "SPI",
 .cmd = {
 [0] = sd_cmd_GO_IDLE_STATE,
-[1] = sd_cmd_SEND_OP_CMD,
+[1] = spi_cmd_SEND_OP_COND,
 [2 ... 4]   = sd_cmd_illegal,
 [5] = sd_cmd_illegal,
 [7] = sd_cmd_illegal,
@@ -2159,7 +2159,7 @@ static const SDProto sd_proto_spi = {
 },
 .acmd = {
 [6] = sd_cmd_unimplemented,
-[41]= sd_cmd_SEND_OP_CMD,
+[41]= spi_cmd_SEND_OP_COND,
 },
 };
 
diff --git a/hw/sd/sdmmc-internal.c b/hw/sd/sdmmc-internal.c
index 8648a7808d..c1d5508ae6 100644
--- a/hw/sd/sdmmc-internal.c
+++ b/hw/sd/sdmmc-internal.c
@@ -14,7 +14,7 @@
 const char *sd_cmd_name(uint8_t cmd)
 {
 static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
- [0]= "GO_IDLE_STATE",   [1]= "SEND_OP_CMD",
+ [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",
-- 
2.41.0




[PATCH 00/23] hw/sd/sdcard: Accumulation of cleanups and fixes

2024-06-21 Thread Philippe Mathieu-Daudé
Various SD card cleanups and fixes accumulated over
the years. Various have been useful to help integrating
eMMC support (which will come later).

Based-on: <20240621075607.17902-1-phi...@linaro.org> st24_be_p()

Philippe Mathieu-Daudé (23):
  hw/sd/sdcard: Correct code indentation
  hw/sd/sdcard: Rewrite sd_cmd_ALL_SEND_CID using switch case (CMD2)
  hw/sd/sdcard: Fix typo in SEND_OP_COND command name
  hw/sd/sdcard: Use HWBLOCK_SHIFT definition instead of magic values
  hw/sd/sdcard: Use registerfield CSR::CURRENT_STATE definition
  hw/sd/sdcard: Use Load/Store API to fill some CID/CSD registers
  hw/sd/sdcard: Remove ACMD6 handler for SPI mode
  hw/sd/sdcard: Remove explicit entries for illegal commands
  hw/sd/sdcard: Generate random RCA value
  hw/sd/sdcard: Track last command used to help logging
  hw/sd/sdcard: Trace update of block count (CMD23)
  hw/sd/sdcard: Trace block offset in READ/WRITE data accesses
  hw/sd/sdcard: Have cmd_valid_while_locked() return a boolean value
  hw/sd/sdcard: Factor sd_req_get_rca() method out
  hw/sd/sdcard: Only call sd_req_get_rca() where RCA is used
  hw/sd/sdcard: Factor sd_req_get_address() method out
  hw/sd/sdcard: Only call sd_req_get_address() where address is used
  hw/sd/sdcard: Add sd_invalid_mode_for_cmd to report invalid mode
switch
  hw/sd/sdcard: Inline BLK_READ_BLOCK / BLK_WRITE_BLOCK macros
  hw/sd/sdcard: Add comments around registers and commands
  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/sd.c | 278 +++--
 hw/sd/sdmmc-internal.c |   2 +-
 hw/sd/trace-events |   7 +-
 3 files changed, 159 insertions(+), 128 deletions(-)

-- 
2.41.0




[PATCH 02/23] hw/sd/sdcard: Rewrite sd_cmd_ALL_SEND_CID using switch case (CMD2)

2024-06-21 Thread Philippe Mathieu-Daudé
Keep this handler style in sync with other handlers by
using a switch() case, which might become handy to
handle other states.

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

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 626e99ecd6..addeb1940f 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1044,13 +1044,13 @@ static sd_rsp_type_t sd_cmd_SEND_OP_CMD(SDState *sd, 
SDRequest req)
 
 static sd_rsp_type_t sd_cmd_ALL_SEND_CID(SDState *sd, SDRequest req)
 {
-if (sd->state != sd_ready_state) {
+switch (sd->state) {
+case sd_ready_state:
+sd->state = sd_identification_state;
+return sd_r2_i;
+default:
 return sd_invalid_state_for_cmd(sd, req);
 }
-
-sd->state = sd_identification_state;
-
-return sd_r2_i;
 }
 
 static sd_rsp_type_t sd_cmd_SEND_RELATIVE_ADDR(SDState *sd, SDRequest req)
-- 
2.41.0




[PATCH 09/23] hw/sd/sdcard: Generate random RCA value

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

Signed-off-by: Philippe Mathieu-Daudé 
---
 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 30239b28bc..e1f13e316a 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"
@@ -469,11 +470,6 @@ static void sd_set_csd(SDState *sd, uint64_t size)
 sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1;
 }
 
-static void sd_set_rca(SDState *sd)
-{
-sd->rca += 0x4567;
-}
-
 FIELD(CSR, AKE_SEQ_ERROR,   3,  1)
 FIELD(CSR, APP_CMD, 5,  1)
 FIELD(CSR, FX_EVENT,6,  1)
@@ -1055,7 +1051,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




[PATCH 07/23] hw/sd/sdcard: Remove ACMD6 handler for SPI mode

2024-06-21 Thread Philippe Mathieu-Daudé
There is no ACMD6 command in SPI mode, remove the pointless
handler introduced in commit 946897ce18 ("sdcard: handles
more commands in SPI mode"). Keep sd_cmd_unimplemented()
since we'll reuse it later.

Signed-off-by: Philippe Mathieu-Daudé 
---
 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 b0cd30c657..e9af834a8c 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1012,6 +1012,7 @@ 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",
@@ -2153,7 +2154,6 @@ static const SDProto sd_proto_spi = {
 [52 ... 54] = sd_cmd_illegal,
 },
 .acmd = {
-[6] = sd_cmd_unimplemented,
 [41]= spi_cmd_SEND_OP_COND,
 },
 };
-- 
2.41.0




[PATCH 15/23] hw/sd/sdcard: Only call sd_req_get_rca() where RCA is used

2024-06-21 Thread Philippe Mathieu-Daudé
It will be useful later to assert only AC commands
(Addressed point-to-point Commands, defined as the
'sd_ac' enum) extract the RCA value from the command
argument.

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

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index bc47ae36bc..cb9d85bb11 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1102,7 +1102,7 @@ static sd_rsp_type_t sd_cmd_SET_BLOCK_COUNT(SDState *sd, 
SDRequest req)
 
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
-uint16_t rca = sd_req_get_rca(sd, req);
+uint16_t rca;
 uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg;
 
 sd->last_cmd_name = sd_cmd_name(req.cmd);
@@ -1160,6 +1160,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 break;
 
 case 7:  /* CMD7:   SELECT/DESELECT_CARD */
+rca = sd_req_get_rca(sd, req);
 switch (sd->state) {
 case sd_standby_state:
 if (sd->rca != rca)
@@ -1214,6 +1215,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 return sd_r7;
 
 case 9:  /* CMD9:   SEND_CSD */
+rca = sd_req_get_rca(sd, req);
 switch (sd->state) {
 case sd_standby_state:
 if (sd->rca != rca)
@@ -1237,6 +1239,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 break;
 
 case 10:  /* CMD10:  SEND_CID */
+rca = sd_req_get_rca(sd, req);
 switch (sd->state) {
 case sd_standby_state:
 if (sd->rca != rca)
@@ -1277,6 +1280,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 break;
 
 case 13:  /* CMD13:  SEND_STATUS */
+rca = sd_req_get_rca(sd, req);
 switch (sd->mode) {
 case sd_data_transfer_mode:
 if (!sd_is_spi(sd) && sd->rca != rca) {
@@ -1291,6 +1295,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 break;
 
 case 15:  /* CMD15:  GO_INACTIVE_STATE */
+rca = sd_req_get_rca(sd, req);
 switch (sd->mode) {
 case sd_data_transfer_mode:
 if (sd->rca != rca)
@@ -1523,6 +1528,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 
 /* 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:
-- 
2.41.0




[PATCH 05/23] hw/sd/sdcard: Use registerfield CSR::CURRENT_STATE definition

2024-06-21 Thread Philippe Mathieu-Daudé
Use registerfield-generated definitions to update card_status.

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

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index c528c30bcf..24415cb9f0 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1788,8 +1788,8 @@ int sd_do_command(SDState *sd, SDRequest *req,
  * (Do this now so they appear in r1 responses.)
  */
 sd->current_cmd = req->cmd;
-sd->card_status &= ~CURRENT_STATE;
-sd->card_status |= (last_state << 9);
+sd->card_status = FIELD_DP32(sd->card_status, CSR,
+ CURRENT_STATE, last_state);
 }
 
 send_response:
-- 
2.41.0




[PATCH 11/23] hw/sd/sdcard: Trace update of block count (CMD23)

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

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 4e378f7cf7..2586d15cbd 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1087,6 +1087,7 @@ static sd_rsp_type_t sd_cmd_SET_BLOCK_COUNT(SDState *sd, 
SDRequest req)
 }
 
 sd->multi_blk_cnt = req.arg;
+trace_sdcard_set_block_count(sd->multi_blk_cnt);
 
 return sd_r1;
 }
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index 94a00557b2..724365efc3 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -43,7 +43,8 @@ sdcard_response(const char *rspdesc, int rsplen) "%s (sz:%d)"
 sdcard_powerup(void) ""
 sdcard_inquiry_cmd41(void) ""
 sdcard_reset(void) ""
-sdcard_set_blocklen(uint16_t length) "0x%03x"
+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"
 sdcard_ejected(void) ""
 sdcard_erase(uint32_t first, uint32_t last) "addr first 0x%" PRIx32" last 0x%" 
PRIx32
-- 
2.41.0




[PATCH 10/23] hw/sd/sdcard: Track last command used to help logging

2024-06-21 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é 
---
 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 e1f13e316a..4e378f7cf7 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!
  */
@@ -1095,12 +1096,13 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 uint32_t rca = 0x;
 uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg;
 
+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));
 }
 
@@ -1571,7 +1573,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;
 
@@ -1863,7 +1866,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 */
@@ -2019,7 +2022,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 */
@@ -2163,6 +2166,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 17/23] hw/sd/sdcard: Only call sd_req_get_address() where address is used

2024-06-21 Thread Philippe Mathieu-Daudé
It will be useful later to assert only ADTC commands
(Addressed point-to-point Data Transfer Commands, defined
as the 'sd_adtc' enum) extract the address value from the
command argument.

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

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index a0193a46ea..1df16ce6a2 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -,7 +,7 @@ static sd_rsp_type_t sd_cmd_SET_BLOCK_COUNT(SDState *sd, 
SDRequest req)
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint16_t rca;
-uint64_t addr = sd_req_get_address(sd, req);
+uint64_t addr;
 
 sd->last_cmd_name = sd_cmd_name(req.cmd);
 /* CMD55 precedes an ACMD, so we are not interested in tracing it.
@@ -1237,7 +1237,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 }
 sd->state = sd_sendingdata_state;
 memcpy(sd->data, sd->csd, 16);
-sd->data_start = addr;
+sd->data_start = sd_req_get_address(sd, req);
 sd->data_offset = 0;
 return sd_r1;
 
@@ -1261,7 +1261,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 }
 sd->state = sd_sendingdata_state;
 memcpy(sd->data, sd->cid, 16);
-sd->data_start = addr;
+sd->data_start = sd_req_get_address(sd, req);
 sd->data_offset = 0;
 return sd_r1;
 
@@ -1337,6 +1337,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 
 case 17:  /* CMD17:  READ_SINGLE_BLOCK */
 case 18:  /* CMD18:  READ_MULTIPLE_BLOCK */
+addr = sd_req_get_address(sd, req);
 switch (sd->state) {
 case sd_transfer_state:
 
@@ -1357,6 +1358,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 /* Block write commands (Class 4) */
 case 24:  /* CMD24:  WRITE_SINGLE_BLOCK */
 case 25:  /* CMD25:  WRITE_MULTIPLE_BLOCK */
+addr = sd_req_get_address(sd, req);
 switch (sd->state) {
 case sd_transfer_state:
 
@@ -1415,7 +1417,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 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)) {
@@ -1437,7 +1439,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 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)) {
@@ -1459,7 +1461,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 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",
-- 
2.41.0




[PATCH 12/23] hw/sd/sdcard: Trace block offset in READ/WRITE data accesses

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

Signed-off-by: Philippe Mathieu-Daudé 
---
 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 2586d15cbd..c6cc1bab11 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1868,7 +1868,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;
@@ -2024,7 +2024,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 06/23] hw/sd/sdcard: Use Load/Store API to fill some CID/CSD registers

2024-06-21 Thread Philippe Mathieu-Daudé
The ld/st API helps noticing CID or CSD bytes refer
to the same field. Multi-bytes fields are stored MSB
first in CID / CSD.

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

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 24415cb9f0..b0cd30c657 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -393,10 +393,7 @@ static void sd_set_cid(SDState *sd)
 sd->cid[6] = PNM[3];
 sd->cid[7] = PNM[4];
 sd->cid[8] = PRV;   /* Fake product revision (PRV) */
-sd->cid[9] = 0xde;  /* Fake serial number (PSN) */
-sd->cid[10] = 0xad;
-sd->cid[11] = 0xbe;
-sd->cid[12] = 0xef;
+stl_be_p(&sd->cid[9], 0xdeadbeef); /* Fake serial number (PSN) */
 sd->cid[13] = 0x00 |/* Manufacture date (MDT) */
 ((MDT_YR - 2000) / 10);
 sd->cid[14] = ((MDT_YR % 10) << 4) | MDT_MON;
@@ -462,9 +459,7 @@ static void sd_set_csd(SDState *sd, uint64_t size)
 sd->csd[4] = 0x5b;
 sd->csd[5] = 0x59;
 sd->csd[6] = 0x00;
-sd->csd[7] = (size >> 16) & 0xff;
-sd->csd[8] = (size >> 8) & 0xff;
-sd->csd[9] = (size & 0xff);
+st24_be_p(&sd->csd[7], size);
 sd->csd[10] = 0x7f;
 sd->csd[11] = 0x80;
 sd->csd[12] = 0x0a;
-- 
2.41.0




[PATCH 21/23] hw/sd/sdcard: Do not store vendor data on block drive (CMD56)

2024-06-21 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é 
---
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 95e23abd30..712fbc0926 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()
 },
@@ -2019,9 +2022,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;
@@ -2155,12 +2157,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 08/23] hw/sd/sdcard: Remove explicit entries for illegal commands

2024-06-21 Thread Philippe Mathieu-Daudé
NULL handler is already handled as illegal, no need to
duplicate (that keeps this array simpler to maintain).

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

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index e9af834a8c..30239b28bc 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -2146,12 +2146,6 @@ static const SDProto sd_proto_spi = {
 .cmd = {
 [0] = sd_cmd_GO_IDLE_STATE,
 [1] = spi_cmd_SEND_OP_COND,
-[2 ... 4]   = sd_cmd_illegal,
-[5] = sd_cmd_illegal,
-[7] = sd_cmd_illegal,
-[15]= sd_cmd_illegal,
-[26]= sd_cmd_illegal,
-[52 ... 54] = sd_cmd_illegal,
 },
 .acmd = {
 [41]= spi_cmd_SEND_OP_COND,
@@ -2162,15 +2156,10 @@ static const SDProto sd_proto_sd = {
 .name = "SD",
 .cmd = {
 [0] = sd_cmd_GO_IDLE_STATE,
-[1] = sd_cmd_illegal,
 [2] = sd_cmd_ALL_SEND_CID,
 [3] = sd_cmd_SEND_RELATIVE_ADDR,
-[5] = sd_cmd_illegal,
 [19]= sd_cmd_SEND_TUNING_BLOCK,
 [23]= sd_cmd_SET_BLOCK_COUNT,
-[52 ... 54] = sd_cmd_illegal,
-[58]= sd_cmd_illegal,
-[59]= sd_cmd_illegal,
 },
 };
 
-- 
2.41.0




[PATCH 19/23] hw/sd/sdcard: Inline BLK_READ_BLOCK / BLK_WRITE_BLOCK macros

2024-06-21 Thread Philippe Mathieu-Daudé
These macros only save 3 chars and make the code harder
to maintain, simply remove them.

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

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 8d63a39a54..ca2c903c5b 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -816,8 +816,6 @@ static void sd_blk_write(SDState *sd, uint64_t addr, 
uint32_t len)
 }
 }
 
-#define BLK_READ_BLOCK(a, len)  sd_blk_read(sd, a, len)
-#define BLK_WRITE_BLOCK(a, len) sd_blk_write(sd, a, len)
 #define APP_READ_BLOCK(a, len)  memset(sd->data, 0xec, len)
 #define APP_WRITE_BLOCK(a, len)
 
@@ -869,7 +867,7 @@ static void sd_erase(SDState *sd)
 continue;
 }
 }
-BLK_WRITE_BLOCK(erase_addr, erase_len);
+sd_blk_write(sd, erase_addr, erase_len);
 }
 }
 
@@ -1901,7 +1899,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
 if (sd->data_offset >= sd->blk_len) {
 /* TODO: Check CRC before committing */
 sd->state = sd_programming_state;
-BLK_WRITE_BLOCK(sd->data_start, sd->data_offset);
+sd_blk_write(sd, sd->data_start, sd->data_offset);
 sd->blk_written ++;
 sd->csd[14] |= 0x40;
 /* Bzzztt  Operation complete.  */
@@ -1927,7 +1925,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
 if (sd->data_offset >= sd->blk_len) {
 /* TODO: Check CRC before committing */
 sd->state = sd_programming_state;
-BLK_WRITE_BLOCK(sd->data_start, sd->data_offset);
+sd_blk_read(sd, sd->data_start, sd->data_offset);
 sd->blk_written++;
 sd->data_start += sd->blk_len;
 sd->data_offset = 0;
@@ -2075,8 +2073,9 @@ uint8_t sd_read_byte(SDState *sd)
 break;
 
 case 17:  /* CMD17:  READ_SINGLE_BLOCK */
-if (sd->data_offset == 0)
-BLK_READ_BLOCK(sd->data_start, io_len);
+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)
@@ -2089,7 +2088,7 @@ uint8_t sd_read_byte(SDState *sd)
   sd->data_start, io_len)) {
 return 0x00;
 }
-BLK_READ_BLOCK(sd->data_start, io_len);
+sd_blk_read(sd, sd->data_start, io_len);
 }
 ret = sd->data[sd->data_offset ++];
 
-- 
2.41.0




[PATCH 20/23] hw/sd/sdcard: Add comments around registers and commands

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

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

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index ca2c903c5b..95e23abd30 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -317,6 +317,8 @@ static uint8_t sd_crc7(const void *message, size_t width)
 return shift_reg;
 }
 
+/* Operation Conditions register */
+
 #define OCR_POWER_DELAY_NS  50 /* 0.5ms */
 
 FIELD(OCR, VDD_VOLTAGE_WINDOW,  0, 24)
@@ -366,6 +368,8 @@ static void sd_set_ocr(SDState *sd)
 }
 }
 
+/* SD Configuration register */
+
 static void sd_set_scr(SDState *sd)
 {
 sd->scr[0] = 0 << 4;/* SCR structure version 1.0 */
@@ -388,6 +392,8 @@ static void sd_set_scr(SDState *sd)
 sd->scr[7] = 0x00;
 }
 
+/* Card IDentification register */
+
 #define MID 0xaa
 #define OID "XY"
 #define PNM "QEMU!"
@@ -413,6 +419,8 @@ static void sd_set_cid(SDState *sd)
 sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1;
 }
 
+/* Card-Specific Data register */
+
 #define HWBLOCK_SHIFT   9/* 512 bytes */
 #define SECTOR_SHIFT5/* 16 kilobytes */
 #define WPGROUP_SHIFT   7/* 2 megs */
@@ -482,6 +490,8 @@ static void sd_set_csd(SDState *sd, uint64_t size)
 sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1;
 }
 
+/* Relative Card Address register */
+
 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) {
@@ -490,6 +500,8 @@ static uint16_t sd_req_get_rca(SDState *s, SDRequest req)
 return 0;
 }
 
+/* Card Status register */
+
 FIELD(CSR, AKE_SEQ_ERROR,   3,  1)
 FIELD(CSR, APP_CMD, 5,  1)
 FIELD(CSR, FX_EVENT,6,  1)
@@ -620,6 +632,8 @@ static void sd_reset(DeviceState *dev)
 sect = sd_addr_to_wpnum(size) + 1;
 
 sd->state = sd_idle_state;
+
+/* card registers */
 sd->rca = 0x;
 sd->size = size;
 sd_set_ocr(sd);
@@ -1052,6 +1066,7 @@ static sd_rsp_type_t sd_cmd_unimplemented(SDState *sd, 
SDRequest req)
 return sd_illegal;
 }
 
+/* CMD0 */
 static sd_rsp_type_t sd_cmd_GO_IDLE_STATE(SDState *sd, SDRequest req)
 {
 if (sd->state != sd_inactive_state) {
@@ -1062,6 +1077,7 @@ static sd_rsp_type_t sd_cmd_GO_IDLE_STATE(SDState *sd, 
SDRequest req)
 return sd_is_spi(sd) ? sd_r1 : sd_r0;
 }
 
+/* CMD1 */
 static sd_rsp_type_t spi_cmd_SEND_OP_COND(SDState *sd, SDRequest req)
 {
 sd->state = sd_transfer_state;
@@ -1069,6 +1085,7 @@ static sd_rsp_type_t spi_cmd_SEND_OP_COND(SDState *sd, 
SDRequest req)
 return sd_r1;
 }
 
+/* CMD2 */
 static sd_rsp_type_t sd_cmd_ALL_SEND_CID(SDState *sd, SDRequest req)
 {
 switch (sd->state) {
@@ -1080,6 +1097,7 @@ 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)
 {
 switch (sd->state) {
@@ -1094,6 +1112,7 @@ static sd_rsp_type_t sd_cmd_SEND_RELATIVE_ADDR(SDState 
*sd, SDRequest req)
 }
 }
 
+/* CMD19 */
 static sd_rsp_type_t sd_cmd_SEND_TUNING_BLOCK(SDState *sd, SDRequest req)
 {
 if (sd->spec_version < SD_PHY_SPECv3_01_VERS) {
@@ -1110,6 +1129,7 @@ static sd_rsp_type_t sd_cmd_SEND_TUNING_BLOCK(SDState 
*sd, SDRequest req)
 return sd_r1;
 }
 
+/* CMD23 */
 static sd_rsp_type_t sd_cmd_SET_BLOCK_COUNT(SDState *sd, SDRequest req)
 {
 if (sd->spec_version < SD_PHY_SPECv3_01_VERS) {
-- 
2.41.0




[PATCH 18/23] hw/sd/sdcard: Add sd_invalid_mode_for_cmd to report invalid mode switch

2024-06-21 Thread Philippe Mathieu-Daudé
Having the mode switch displayed help to track incomplete
command implementations.

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

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 1df16ce6a2..8d63a39a54 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -180,6 +180,17 @@ static const char *sd_version_str(enum 
SDPhySpecificationVersion version)
 return sdphy_version[version];
 }
 
+static const char *sd_mode_name(enum SDCardModes mode)
+{
+static const char *mode_name[] = {
+[sd_inactive]   = "inactive",
+[sd_card_identification_mode]   = "identification",
+[sd_data_transfer_mode] = "transfer",
+};
+assert(mode < ARRAY_SIZE(mode_name));
+return mode_name[mode];
+}
+
 static const char *sd_state_name(enum SDCardStates state)
 {
 static const char *state_name[] = {
@@ -1015,6 +1026,15 @@ static sd_rsp_type_t sd_invalid_state_for_cmd(SDState 
*sd, SDRequest req)
 return sd_illegal;
 }
 
+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_version_str(sd->spec_version));
+
+return sd_illegal;
+}
+
 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",
@@ -1154,18 +1174,14 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 break;
 
 case 6:  /* CMD6:   SWITCH_FUNCTION */
-switch (sd->mode) {
-case sd_data_transfer_mode:
-sd_function_switch(sd, req.arg);
-sd->state = sd_sendingdata_state;
-sd->data_start = 0;
-sd->data_offset = 0;
-return sd_r1;
-
-default:
-break;
+if (sd->mode != sd_data_transfer_mode) {
+return sd_invalid_mode_for_cmd(sd, req);
 }
-break;
+sd_function_switch(sd, req.arg);
+sd->state = sd_sendingdata_state;
+sd->data_start = 0;
+sd->data_offset = 0;
+return sd_r1;
 
 case 7:  /* CMD7:   SELECT/DESELECT_CARD */
 rca = sd_req_get_rca(sd, req);
@@ -1289,33 +1305,24 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 
 case 13:  /* CMD13:  SEND_STATUS */
 rca = sd_req_get_rca(sd, req);
-switch (sd->mode) {
-case sd_data_transfer_mode:
-if (!sd_is_spi(sd) && sd->rca != rca) {
-return sd_r0;
-}
-
-return sd_r1;
-
-default:
-break;
+if (sd->mode != sd_data_transfer_mode) {
+return sd_invalid_mode_for_cmd(sd, req);
 }
-break;
+if (!sd_is_spi(sd) && sd->rca != rca) {
+return sd_r0;
+}
+
+return sd_r1;
 
 case 15:  /* CMD15:  GO_INACTIVE_STATE */
-rca = sd_req_get_rca(sd, req);
-switch (sd->mode) {
-case sd_data_transfer_mode:
-if (sd->rca != rca)
-return sd_r0;
-
-sd->state = sd_inactive_state;
-return sd_r0;
-
-default:
-break;
+if (sd->mode != sd_data_transfer_mode) {
+return sd_invalid_mode_for_cmd(sd, req);
 }
-break;
+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 */
-- 
2.41.0




[PATCH 01/23] hw/sd/sdcard: Correct code indentation

2024-06-21 Thread Philippe Mathieu-Daudé
Fix mis-alignment from commits 793d04f495 and 6380cd2052
("Add sd_cmd_SEND_TUNING_BLOCK" and "Add sd_cmd_SET_BLOCK_COUNT").

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

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 16d8d52a78..626e99ecd6 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1069,33 +1069,33 @@ static sd_rsp_type_t sd_cmd_SEND_RELATIVE_ADDR(SDState 
*sd, SDRequest req)
 
 static sd_rsp_type_t sd_cmd_SEND_TUNING_BLOCK(SDState *sd, SDRequest req)
 {
-if (sd->spec_version < SD_PHY_SPECv3_01_VERS) {
-return sd_cmd_illegal(sd, req);
-}
+if (sd->spec_version < SD_PHY_SPECv3_01_VERS) {
+return sd_cmd_illegal(sd, req);
+}
 
-if (sd->state != sd_transfer_state) {
-return sd_invalid_state_for_cmd(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;
+sd->state = sd_sendingdata_state;
+sd->data_offset = 0;
 
-return sd_r1;
+return sd_r1;
 }
 
 static sd_rsp_type_t sd_cmd_SET_BLOCK_COUNT(SDState *sd, SDRequest req)
 {
-if (sd->spec_version < SD_PHY_SPECv3_01_VERS) {
-return sd_cmd_illegal(sd, req);
-}
+if (sd->spec_version < SD_PHY_SPECv3_01_VERS) {
+return sd_cmd_illegal(sd, req);
+}
 
-if (sd->state != sd_transfer_state) {
-return sd_invalid_state_for_cmd(sd, req);
-}
+if (sd->state != sd_transfer_state) {
+return sd_invalid_state_for_cmd(sd, req);
+}
 
-sd->multi_blk_cnt = req.arg;
+sd->multi_blk_cnt = req.arg;
 
-return sd_r1;
+return sd_r1;
 }
 
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
-- 
2.41.0




[PATCH 14/23] hw/sd/sdcard: Factor sd_req_get_rca() method out

2024-06-21 Thread Philippe Mathieu-Daudé
Extract sd_req_get_rca() so we can re-use it in various
SDProto handlers. Return a 16-bit value since RCA is 16-bit.

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

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 510784fc82..bc47ae36bc 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -471,6 +471,14 @@ static void sd_set_csd(SDState *sd, uint64_t size)
 sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1;
 }
 
+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) {
+return req.arg >> 16;
+}
+return 0;
+}
+
 FIELD(CSR, AKE_SEQ_ERROR,   3,  1)
 FIELD(CSR, APP_CMD, 5,  1)
 FIELD(CSR, FX_EVENT,6,  1)
@@ -1094,7 +1102,7 @@ static sd_rsp_type_t sd_cmd_SET_BLOCK_COUNT(SDState *sd, 
SDRequest req)
 
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
-uint32_t rca = 0x;
+uint16_t rca = sd_req_get_rca(sd, req);
 uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg;
 
 sd->last_cmd_name = sd_cmd_name(req.cmd);
@@ -1110,11 +1118,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 /* Not interpreting this as an app command */
 sd->card_status &= ~APP_CMD;
 
-if (sd_cmd_type[req.cmd] == sd_ac
-|| sd_cmd_type[req.cmd] == sd_adtc) {
-rca = req.arg >> 16;
-}
-
 /* CMD23 (set block count) must be immediately followed by CMD18 or CMD25
  * if not, its effects are cancelled */
 if (sd->multi_blk_cnt != 0 && !(req.cmd == 18 || req.cmd == 25)) {
-- 
2.41.0




[PATCH 16/23] hw/sd/sdcard: Factor sd_req_get_address() method out

2024-06-21 Thread Philippe Mathieu-Daudé
Extract sd_cmd_get_address() so we can re-use it
in various SDProto handlers. Use CARD_CAPACITY and
HWBLOCK_SHIFT definitions instead of magic values.

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 cb9d85bb11..a0193a46ea 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -579,6 +579,14 @@ static void sd_response_r7_make(SDState *sd, uint8_t 
*response)
 stl_be_p(response, sd->vhs);
 }
 
+static uint64_t sd_req_get_address(SDState *sd, SDRequest req)
+{
+if (FIELD_EX32(sd->ocr, OCR, CARD_CAPACITY)) {
+return (uint64_t) req.arg << HWBLOCK_SHIFT;
+}
+return req.arg;
+}
+
 static inline uint64_t sd_addr_to_wpnum(uint64_t addr)
 {
 return addr >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT);
@@ -1103,7 +,7 @@ static sd_rsp_type_t sd_cmd_SET_BLOCK_COUNT(SDState *sd, 
SDRequest req)
 static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint16_t rca;
-uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg;
+uint64_t addr = sd_req_get_address(sd, req);
 
 sd->last_cmd_name = sd_cmd_name(req.cmd);
 /* CMD55 precedes an ACMD, so we are not interested in tracing it.
-- 
2.41.0




[PATCH 22/23] hw/sd/sdcard: Send WRITE_PROT bits MSB first (CMD30)

2024-06-21 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é 
---
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 712fbc0926..601a6908aa 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




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

2024-06-21 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é 
---
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 601a6908aa..5d572ad13c 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




[PATCH 13/23] hw/sd/sdcard: Have cmd_valid_while_locked() return a boolean value

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

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index c6cc1bab11..510784fc82 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1716,7 +1716,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 return sd_illegal;
 }
 
-static int cmd_valid_while_locked(SDState *sd, const uint8_t cmd)
+static bool cmd_valid_while_locked(SDState *sd, unsigned cmd)
 {
 /* Valid commands in locked state:
  * basic class (0)
@@ -1730,7 +1730,7 @@ static int cmd_valid_while_locked(SDState *sd, const 
uint8_t cmd)
 return cmd == 41 || cmd == 42;
 }
 if (cmd == 16 || cmd == 55) {
-return 1;
+return true;
 }
 return sd_cmd_class[cmd] == 0 || sd_cmd_class[cmd] == 7;
 }
-- 
2.41.0




[PATCH 04/23] hw/sd/sdcard: Use HWBLOCK_SHIFT definition instead of magic values

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

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

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 331cef5779..c528c30bcf 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -596,7 +596,7 @@ static void sd_reset(DeviceState *dev)
 } else {
 sect = 0;
 }
-size = sect << 9;
+size = sect << HWBLOCK_SHIFT;
 
 sect = sd_addr_to_wpnum(size) + 1;
 
@@ -822,8 +822,8 @@ static void sd_erase(SDState *sd)
 
 if (FIELD_EX32(sd->ocr, OCR, CARD_CAPACITY)) {
 /* High capacity memory card: erase units are 512 byte blocks */
-erase_start *= 512;
-erase_end *= 512;
+erase_start <<= HWBLOCK_SHIFT;
+erase_end <<= HWBLOCK_SHIFT;
 sdsc = false;
 }
 
-- 
2.41.0




Re: [PATCH 09/23] hw/sd/sdcard: Generate random RCA value

2024-06-21 Thread Philippe Mathieu-Daudé

On 21/6/24 10:05, Philippe Mathieu-Daudé wrote:

Rather than using the obscure 0x4567 magic value,
use a real random one.

Signed-off-by: Philippe Mathieu-Daudé 
---
  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 30239b28bc..e1f13e316a 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"
@@ -469,11 +470,6 @@ static void sd_set_csd(SDState *sd, uint64_t size)
  sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1;
  }
  
-static void sd_set_rca(SDState *sd)

-{
-sd->rca += 0x4567;
-}
-
  FIELD(CSR, AKE_SEQ_ERROR,   3,  1)
  FIELD(CSR, APP_CMD, 5,  1)
  FIELD(CSR, FX_EVENT,6,  1)
@@ -1055,7 +1051,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;


Hmm the NPCM7xx test is failing:

▶  58/450 ERROR:../tests/qtest/npcm7xx_sdhci-test.c:101:sdwrite_read: 
assertion failed: (!memcmp(rmsg, msg, len)) ERROR


But booting various Linux / FreeBSD guests on SD cards works,
so I suppose the test (or TYPE_NPCM7XX_SDHCI model) need some
rework.

$ git grep 0x4567
tests/qtest/npcm7xx_sdhci-test.c:47:sdhci_cmd_regs(qts, 
NPCM7XX_MMC_BA, 0, 0, 0x4567, 0,
tests/qtest/npcm7xx_sdhci-test.c-48- 
SDHC_SELECT_DESELECT_CARD);


In tests/qtest/libqos/sdhci-cmd.h:

/* CMD Reg */
#define SDHC_SEND_RELATIVE_ADDR (3 << 8)
#define SDHC_SELECT_DESELECT_CARD (7 << 8)

IIUC setup_sd_card():

card address is queried ...:

sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0,
   SDHC_SEND_RELATIVE_ADDR);

... but then ignored and magic 0x4567 is used instead:

sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x4567, 0,
   SDHC_SELECT_DESELECT_CARD);

OK, so this test need rework. I see the sdhci_read_cmd()
method but it reads the SDHC_BDATA FIFO register, not sure
this is what should be used to read the RCA from R6 command
response.

Shengtan, Nuvoton folks, what do you think?

Thanks,

Phil.



Re: [PATCH 00/23] hw/sd/sdcard: Accumulation of cleanups and fixes

2024-06-24 Thread Philippe Mathieu-Daudé

On 21/6/24 10:05, Philippe Mathieu-Daudé wrote:

Various SD card cleanups and fixes accumulated over
the years. Various have been useful to help integrating
eMMC support (which will come later).

Based-on: <20240621075607.17902-1-phi...@linaro.org> st24_be_p()

Philippe Mathieu-Daudé (23):
   hw/sd/sdcard: Correct code indentation
   hw/sd/sdcard: Rewrite sd_cmd_ALL_SEND_CID using switch case (CMD2)
   hw/sd/sdcard: Fix typo in SEND_OP_COND command name
   hw/sd/sdcard: Use HWBLOCK_SHIFT definition instead of magic values
   hw/sd/sdcard: Use registerfield CSR::CURRENT_STATE definition
   hw/sd/sdcard: Use Load/Store API to fill some CID/CSD registers
   hw/sd/sdcard: Remove ACMD6 handler for SPI mode
   hw/sd/sdcard: Remove explicit entries for illegal commands



   hw/sd/sdcard: Have cmd_valid_while_locked() return a boolean value
   hw/sd/sdcard: Factor sd_req_get_rca() method out
   hw/sd/sdcard: Only call sd_req_get_rca() where RCA is used
   hw/sd/sdcard: Factor sd_req_get_address() method out
   hw/sd/sdcard: Only call sd_req_get_address() where address is used
   hw/sd/sdcard: Add sd_invalid_mode_for_cmd to report invalid mode
 switch
   hw/sd/sdcard: Inline BLK_READ_BLOCK / BLK_WRITE_BLOCK macros
   hw/sd/sdcard: Add comments around registers and commands


Patches 1-8, 13-20 queued.




[PATCH v2 02/12] hw/sd/sdcard: Generate random RCA value

2024-06-24 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 | 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




[PATCH v2 01/12] tests/qtest: Disable npcm7xx_sdhci tests using hardcoded RCA

2024-06-24 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 
---
 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 v2 00/12] hw/sd/sdcard: Accumulation of cleanups and fixes

2024-06-24 Thread Philippe Mathieu-Daudé
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(-)

-- 
2.41.0




[PATCH v2 05/12] hw/sd/sdcard: Do not store vendor data on block drive (CMD56)

2024-06-24 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 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




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

2024-06-24 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é 
---
 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




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

2024-06-24 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 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




[PATCH v2 07/12] hw/sd/sdcard: Send NUM_WR_BLOCKS bits MSB first (ACMD22)

2024-06-24 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 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




[PATCH v2 08/12] hw/sd/sdcard: Use READY_FOR_DATA definition instead of magic value

2024-06-24 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 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 = 0x0100;
+sd->card_status = READY_FOR_DATA;
 }
 
 static void sd_set_sdstatus(SDState *sd)
-- 
2.41.0




[PATCH v2 12/12] hw/sd/sdcard: Add direct reference to SDProto in SDState

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

Signed-off-by: Philippe Mathieu-Daudé 
---
 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,

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

2024-06-24 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 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




[PATCH v2 09/12] hw/sd/sdcard: Assign SDCardStates enum values

2024-06-24 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é 
---
 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




[PATCH v2 06/12] hw/sd/sdcard: Send WRITE_PROT bits MSB first (CMD30)

2024-06-24 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 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




[PATCH v2 10/12] hw/sd/sdcard: Simplify sd_inactive_state handling

2024-06-24 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é 
---
 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




[PATCH 00/11] hw/sd/sd: Introduce sd_cmd_to_sendingdata() and sd_generic_read_byte()

2024-06-24 Thread Philippe Mathieu-Daudé
Consolitate reading bytes on the DAT lines by introducing
a pair of helpers to reuse in all commands sending data.

Based-on: <20240625055354.23273-1-phi...@linaro.org>

Philippe Mathieu-Daudé (11):
  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/sd.c | 223 -
 1 file changed, 100 insertions(+), 123 deletions(-)

-- 
2.41.0




[PATCH 02/11] hw/sd/sdcard: Convert SWITCH_FUNCTION to generic_read_byte (CMD6)

2024-06-24 Thread 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 89006ba1b6..0011aa86da 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1220,10 +1220,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);
@@ -1922,7 +1919,6 @@ send_response:
 return rsplen;
 }
 
-__attribute__((unused))
 /* Return true when buffer consumed */
 static bool sd_generic_read_byte(SDState *sd, uint8_t *value)
 {
@@ -2112,10 +2108,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 03/11] hw/sd/sdcard: Convert SEND_CSD/SEND_CID to generic_read_byte (CMD9 & 10)

2024-06-24 Thread 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 0011aa86da..346bd657a7 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1290,11 +1290,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;
@@ -1314,11 +1311,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;
@@ -2108,15 +2102,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 01/11] hw/sd/sdcard: Introduce sd_cmd_to_sendingdata and sd_generic_read_byte

2024-06-24 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 | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 6685fba4bb..89006ba1b6 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];
 
@@ -1064,6 +1066,28 @@ static sd_rsp_type_t sd_cmd_unimplemented(SDState *sd, 
SDRequest req)
 return sd_illegal;
 }
 
+__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)
 {
@@ -1898,6 +1922,20 @@ send_response:
 return rsplen;
 }
 
+__attribute__((unused))
+/* Return true when buffer consumed */
+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 04/11] hw/sd/sdcard: Duplicate READ_SINGLE_BLOCK / READ_MULTIPLE_BLOCK cases

2024-06-24 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 346bd657a7..9aaa78a334 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1376,6 +1376,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 06/11] hw/sd/sdcard: Convert SEND_TUNING_BLOCK to generic_read_byte (CMD19)

2024-06-24 Thread 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 6af7b3f034..3d341495e9 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -562,6 +562,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];
@@ -1139,14 +1154,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 */
@@ -2078,20 +2088,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 */
@@ -2120,6 +2116,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;
 
@@ -2154,13 +2151,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 09/11] hw/sd/sdcard: Convert SD_STATUS to generic_read_byte (ACMD13)

2024-06-24 Thread 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 bf78f06b5c..2f00184bb3 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1681,10 +1681,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;
@@ -2114,6 +2113,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 */
@@ -2121,13 +2121,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 07/11] hw/sd/sdcard: Convert SEND_WRITE_PROT to generic_read_byte (CMD30)

2024-06-24 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 3d341495e9..6e6b37bd2d 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1180,6 +1180,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.
@@ -1533,12 +1534,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;
@@ -2117,6 +2114,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;
 
@@ -2158,13 +2156,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 08/11] hw/sd/sdcard: Convert GEN_CMD to generic_read_byte (CMD56)

2024-06-24 Thread 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 6e6b37bd2d..bf78f06b5c 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1626,10 +1626,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:
@@ -2115,6 +2117,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;
 
@@ -2163,14 +2166,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 11/11] hw/sd/sdcard: Convert SEND_SCR to generic_read_byte (ACMD51)

2024-06-24 Thread 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 023fcc63ac..af3a46373f 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1763,10 +1763,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;
@@ -2116,6 +2113,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;
@@ -2144,13 +2142,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 10/11] hw/sd/sdcard: Convert SEND_NUM_WR_BLOCKS to generic_read_byte (ACMD22)

2024-06-24 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 2f00184bb3..023fcc63ac 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1693,11 +1693,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;
@@ -2116,6 +2114,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);
@@ -2145,13 +2144,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 05/11] hw/sd/sdcard: Convert READ_SINGLE_BLOCK to generic_read_byte (CMD17)

2024-06-24 Thread 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 9aaa78a334..6af7b3f034 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1383,11 +1383,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;
@@ -2122,6 +2119,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;
 
@@ -2132,16 +2130,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




Re: [PATCH 02/11] hw/sd/sdcard: Convert SWITCH_FUNCTION to generic_read_byte (CMD6)

2024-06-24 Thread Philippe Mathieu-Daudé

On 25/6/24 08:10, Philippe Mathieu-Daudé wrote:

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 89006ba1b6..0011aa86da 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1220,10 +1220,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);


Oops, missing:

-- >8 --
@@ -1068,3 +1068,2 @@ static sd_rsp_type_t sd_cmd_unimplemented(SDState 
*sd, SDRequest req)


-__attribute__((unused))
 static sd_rsp_type_t sd_cmd_to_sendingdata(SDState *sd, SDRequest req,
---


@@ -1922,7 +1919,6 @@ send_response:
  return rsplen;
  }
  
-__attribute__((unused))

  /* Return true when buffer consumed */
  static bool sd_generic_read_byte(SDState *sd, uint8_t *value)
  {
@@ -2112,10 +2108,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 */





[PATCH 0/7] hw/sd/sd: Introduce sd_cmd_to_receivingdata() / sd_generic_write_byte()

2024-06-25 Thread Philippe Mathieu-Daudé
Consolitate writing bytes on the DAT lines by introducing
a pair of helpers to reuse in all commands receiving data.

Based-on: <20240625061015.24095-1-phi...@linaro.org>

Philippe Mathieu-Daudé (7):
  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/sd.c | 108 ++---
 1 file changed, 61 insertions(+), 47 deletions(-)

-- 
2.41.0




[PATCH 4/7] hw/sd/sdcard: Convert PROGRAM_CID to generic_write_byte (CMD26)

2024-06-25 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 fff4be3ae2..9db3b32b0b 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1491,17 +1491,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) {
@@ -2064,8 +2054,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 1/7] hw/sd/sdcard: Introduce sd_cmd_to_receivingdata / sd_generic_write_byte

2024-06-25 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 | 28 
 1 file changed, 28 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 2df3c28cb7..7fea0afb62 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1081,6 +1081,21 @@ static sd_rsp_type_t sd_cmd_unimplemented(SDState *sd, 
SDRequest req)
 return sd_illegal;
 }
 
+__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;
+}
+
 static sd_rsp_type_t sd_cmd_to_sendingdata(SDState *sd, SDRequest req,
uint64_t start,
const void *data, size_t size)
@@ -1930,6 +1945,19 @@ send_response:
 return rsplen;
 }
 
+/* Return true when buffer consumed */
+__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 consumed */
 static bool sd_generic_read_byte(SDState *sd, uint8_t *value)
 {
-- 
2.41.0




[PATCH 6/7] hw/sd/sdcard: Convert LOCK_UNLOCK to generic_write_byte (CMD42)

2024-06-25 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 b0f29034c0..82b44b65e0 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1604,17 +1604,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 */
@@ -2085,8 +2075,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 7/7] hw/sd/sdcard: Convert GEN_CMD to generic_write_byte (CMD56)

2024-06-25 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 82b44b65e0..fe2210d65a 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1633,14 +1633,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;
@@ -2085,9 +2083,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 5/7] hw/sd/sdcard: Convert PROGRAM_CSD to generic_write_byte (CMD27)

2024-06-25 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 9db3b32b0b..b0f29034c0 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1494,17 +1494,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 */
@@ -2072,8 +2062,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 2/7] hw/sd/sdcard: Duplicate WRITE_SINGLE_BLOCK / WRITE_MULTIPLE_BLOCK cases

2024-06-25 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 7fea0afb62..8c30826754 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1437,6 +1437,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 3/7] hw/sd/sdcard: Convert WRITE_SINGLE_BLOCK to generic_write_byte (CMD24)

2024-06-25 Thread 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 8c30826754..fff4be3ae2 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1081,7 +1081,6 @@ static sd_rsp_type_t sd_cmd_unimplemented(SDState *sd, 
SDRequest req)
 return sd_illegal;
 }
 
-__attribute__((unused))
 static sd_rsp_type_t sd_cmd_to_receivingdata(SDState *sd, SDRequest req,
  uint64_t start, size_t size)
 {
@@ -1446,10 +1445,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;
@@ -1459,7 +1454,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;
@@ -1975,7 +1970,6 @@ send_response:
 }
 
 /* Return true when buffer consumed */
-__attribute__((unused))
 static bool sd_generic_write_byte(SDState *sd, uint8_t value)
 {
 sd->data[sd->data_offset] = value;
@@ -2021,8 +2015,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




Re: [PATCH 04/14] spapr: Free stdout path

2024-06-26 Thread Philippe Mathieu-Daudé

On 26/6/24 13:06, Akihiko Odaki wrote:

This suppresses LeakSanitizer warnings.

Signed-off-by: Akihiko Odaki 
---
  hw/ppc/spapr_vof.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)


Reviewed-by: Philippe Mathieu-Daudé 




Re: [PATCH 05/14] ppc/vof: Fix unaligned FDT property access

2024-06-26 Thread Philippe Mathieu-Daudé

On 26/6/24 13:06, Akihiko Odaki wrote:

FDT properties are aligned by 4 bytes, not 8 bytes.

Signed-off-by: Akihiko Odaki 
---
  hw/ppc/vof.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/ppc/vof.c b/hw/ppc/vof.c
index e3b430a81f4f..b5b6514d79fc 100644
--- a/hw/ppc/vof.c
+++ b/hw/ppc/vof.c
@@ -646,7 +646,7 @@ static void vof_dt_memory_available(void *fdt, GArray 
*claimed, uint64_t base)
  mem0_reg = fdt_getprop(fdt, offset, "reg", &proplen);
  g_assert(mem0_reg && proplen == sizeof(uint32_t) * (ac + sc));
  if (sc == 2) {
-mem0_end = be64_to_cpu(*(uint64_t *)(mem0_reg + sizeof(uint32_t) * 
ac));
+mem0_end = ldq_be_p(mem0_reg + sizeof(uint32_t) * ac);
  } else {
  mem0_end = be32_to_cpu(*(uint32_t *)(mem0_reg + sizeof(uint32_t) * 
ac));


OK but please keep API uses consistent, so convert other uses please.


  }






Re: [PATCH 01/14] hw/core: Free CPUState allocations

2024-06-26 Thread Philippe Mathieu-Daudé

On 26/6/24 13:06, Akihiko Odaki wrote:

This suppresses LeakSanitizer warnings.

Signed-off-by: Akihiko Odaki 
---
  hw/core/cpu-common.c | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
index 0f0a247f5642..42f38b01a97f 100644
--- a/hw/core/cpu-common.c
+++ b/hw/core/cpu-common.c
@@ -274,6 +274,9 @@ static void cpu_common_finalize(Object *obj)
  {
  CPUState *cpu = CPU(obj);
  
+g_free(cpu->thread);

+g_free(cpu->halt_cond);
+g_free(cpu->cpu_ases);
  g_array_free(cpu->gdb_regs, TRUE);
  qemu_lockcnt_destroy(&cpu->in_ioctl_lock);
  qemu_mutex_destroy(&cpu->work_mutex);



Similar patch queued via trivial tree:
https://lore.kernel.org/qemu-devel/3ad18bc590ef28e1526e8053568086b453e7ffde.1718211878.git.quic_mathb...@quicinc.com/




[PATCH 2/3] hw/sd/sdcard: Use spec v3.01 by default

2024-06-27 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é 
---
 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 0/3] hw/sd/sdcard: Deprecate support for spec v1.10

2024-06-27 Thread Philippe Mathieu-Daudé
Deprecate SD spec v1.10, use v3.01 as new default.

Philippe Mathieu-Daudé (3):
  hw/sd/sdcard: Deprecate support for spec v1.10
  hw/sd/sdcard: Use spec v3.01 by default
  hw/sd/sdcard: Remove support for spec v1.10

 docs/about/removed-features.rst |  5 +
 include/hw/sd/sd.h  |  1 -
 hw/sd/sd.c  | 14 +++---
 3 files changed, 8 insertions(+), 12 deletions(-)

-- 
2.41.0




[PATCH-for-10.0 3/3] hw/sd/sdcard: Remove support for spec v1.10

2024-06-27 Thread Philippe Mathieu-Daudé
Support for spec v1.10 was deprecated in QEMU v9.1.

Signed-off-by: Philippe Mathieu-Daudé 
---
 docs/about/deprecated.rst   |  6 --
 docs/about/removed-features.rst |  5 +
 include/hw/sd/sd.h  |  1 -
 hw/sd/sd.c  | 12 ++--
 4 files changed, 7 insertions(+), 17 deletions(-)

diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index 02cdef14aa..ff3da68208 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -362,12 +362,6 @@ 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
 ''''''''''''''''''''
 
diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst
index fc7b28e637..dfe04b0555 100644
--- a/docs/about/removed-features.rst
+++ b/docs/about/removed-features.rst
@@ -1056,6 +1056,11 @@ by using ``-machine graphics=off``.
 
 The 'pvrdma' device and the whole RDMA subsystem have been removed.
 
+``-device sd-card,spec_version=1`` (since 10.0)
+'''''''''''''''''''''''''''''''''''''''''''''''
+
+SD physical layer specification v2.00 supersedes the v1.10 one.
+
 Related binaries
 
 
diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index 2c8748fb9b..362e149360 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -56,7 +56,6 @@
 #define AKE_SEQ_ERROR   (1 << 3)
 
 enum SDPhySpecificationVersion {
-SD_PHY_SPECv1_10_VERS = 1,
 SD_PHY_SPECv2_00_VERS = 2,
 SD_PHY_SPECv3_01_VERS = 3,
 };
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index d0a1d5db18..37a6a989ee 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -168,7 +168,6 @@ static bool sd_is_spi(SDState *sd)
 static const char *sd_version_str(enum SDPhySpecificationVersion version)
 {
 static const char *sdphy_version[] = {
-[SD_PHY_SPECv1_10_VERS] = "v1.10",
 [SD_PHY_SPECv2_00_VERS] = "v2.00",
 [SD_PHY_SPECv3_01_VERS] = "v3.01",
 };
@@ -371,11 +370,7 @@ static void sd_set_ocr(SDState *sd)
 static void sd_set_scr(SDState *sd)
 {
 sd->scr[0] = 0 << 4;/* SCR structure version 1.0 */
-if (sd->spec_version == SD_PHY_SPECv1_10_VERS) {
-sd->scr[0] |= 1;/* Spec Version 1.10 */
-} else {
-sd->scr[0] |= 2;/* Spec Version 2.00 or Version 3.0X */
-}
+sd->scr[0] |= 2;/* Spec Version 2.00 or Version 3.0X */
 sd->scr[1] = (2 << 4)   /* SDSC Card (Security Version 1.01) */
  | 0b0101;  /* 1-bit or 4-bit width bus modes */
 sd->scr[2] = 0x00;  /* Extended Security is not supported. */
@@ -1241,9 +1236,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 break;
 
 case 8:  /* CMD8:   SEND_IF_COND */
-if (sd->spec_version < SD_PHY_SPECv2_00_VERS) {
-break;
-}
 if (sd->state != sd_idle_state) {
 break;
 }
@@ -2231,7 +2223,7 @@ static void sd_realize(DeviceState *dev, Error **errp)
 int ret;
 
 switch (sd->spec_version) {
-case SD_PHY_SPECv1_10_VERS
+case SD_PHY_SPECv2_00_VERS
  ... SD_PHY_SPECv3_01_VERS:
 break;
 default:
-- 
2.41.0




[PATCH 1/3] hw/sd/sdcard: Deprecate support for spec v1.10

2024-06-27 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é 
---
 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




Re: [PATCH 05/14] ppc/vof: Fix unaligned FDT property access

2024-06-27 Thread Philippe Mathieu-Daudé

On 27/6/24 15:12, Akihiko Odaki wrote:

On 2024/06/26 21:03, Philippe Mathieu-Daudé wrote:

On 26/6/24 13:06, Akihiko Odaki wrote:

FDT properties are aligned by 4 bytes, not 8 bytes.

Signed-off-by: Akihiko Odaki 
---
  hw/ppc/vof.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/ppc/vof.c b/hw/ppc/vof.c
index e3b430a81f4f..b5b6514d79fc 100644
--- a/hw/ppc/vof.c
+++ b/hw/ppc/vof.c
@@ -646,7 +646,7 @@ static void vof_dt_memory_available(void *fdt, 
GArray *claimed, uint64_t base)

  mem0_reg = fdt_getprop(fdt, offset, "reg", &proplen);
  g_assert(mem0_reg && proplen == sizeof(uint32_t) * (ac + sc));
  if (sc == 2) {
-    mem0_end = be64_to_cpu(*(uint64_t *)(mem0_reg + 
sizeof(uint32_t) * ac));

+    mem0_end = ldq_be_p(mem0_reg + sizeof(uint32_t) * ac);
  } else {
  mem0_end = be32_to_cpu(*(uint32_t *)(mem0_reg + 
sizeof(uint32_t) * ac));


OK but please keep API uses consistent, so convert other uses please.


This is the only unaligned access.


What I mean with consistent API use is either use the be64_to_cpu and
be32_to_cpu API, or ldq_be_p and ldl_be_p. A mix of both makes review
more confusing.



[PATCH v3 00/17] hw/sd/sdcard: Accumulation of cleanups and fixes

2024-06-27 Thread Philippe Mathieu-Daudé
Since v2:
- Tested-by from Cédric recorded
- more patches added :S
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).

Full series for testing:
https://gitlab.com/philmd/qemu/-/tags/emmc-v4

Cédric Le Goater (1):
  hw/sd/sdcard: Introduce definitions for EXT_CSD register

Philippe Mathieu-Daudé (16):
  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

 docs/about/deprecated.rst|   6 ++
 hw/sd/sdmmc-internal.h   |  97 +
 hw/sd/sd.c   | 145 ++-
 tests/qtest/npcm7xx_sdhci-test.c |   7 ++
 hw/sd/trace-events   |   6 +-
 5 files changed, 199 insertions(+), 62 deletions(-)

-- 
2.41.0




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

2024-06-27 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 v3 01/17] hw/sd/sdcard: Deprecate support for spec v1.10

2024-06-27 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 v3 04/17] hw/sd/sdcard: Trace block offset in READ/WRITE data accesses

2024-06-27 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 v3 03/17] hw/sd/sdcard: Track last command used to help logging

2024-06-27 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 v3 06/17] hw/sd/sdcard: Do not store vendor data on block drive (CMD56)

2024-06-27 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 v3 05/17] hw/sd/sdcard: Trace requested address computed by sd_req_get_address()

2024-06-27 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 v3 08/17] hw/sd/sdcard: Send NUM_WR_BLOCKS bits MSB first (ACMD22)

2024-06-27 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 v3 09/17] hw/sd/sdcard: Use READY_FOR_DATA definition instead of magic value

2024-06-27 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 v3 07/17] hw/sd/sdcard: Send WRITE_PROT bits MSB first (CMD30)

2024-06-27 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 v3 10/17] hw/sd/sdcard: Assign SDCardStates enum values

2024-06-27 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 v3 11/17] hw/sd/sdcard: Simplify sd_inactive_state handling

2024-06-27 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




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

2024-06-27 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 v3 13/17] hw/sd/sdcard: Add direct reference to SDProto in SDState

2024-06-27 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

[PATCH v3 14/17] hw/sd/sdcard: Extract sd_blk_len() helper

2024-06-27 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 v3 16/17] hw/sd/sdcard: Generate random RCA value

2024-06-27 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 v3 15/17] tests/qtest: Disable npcm7xx_sdhci tests using hardcoded RCA

2024-06-27 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 
---
 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 v3 17/17] hw/sd/sdcard: Introduce definitions for EXT_CSD register

2024-06-27 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

[PATCH v2 00/11] hw/sd/sd: Introduce sd_cmd_to_sendingdata() and sd_generic_read_byte()

2024-06-27 Thread Philippe Mathieu-Daudé
Consolitate reading bytes on the DAT lines by introducing
a pair of helpers to reuse in all commands sending data.

Full series for testing:
https://gitlab.com/philmd/qemu/-/tags/emmc-v4

Based-on: <20240627162232.80428-1-phi...@linaro.org>

Philippe Mathieu-Daudé (11):
  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/sd.c | 223 -
 1 file changed, 100 insertions(+), 123 deletions(-)

-- 
2.41.0




[PATCH v2 03/11] hw/sd/sdcard: Convert SEND_CSD/SEND_CID to generic_read_byte (CMD9 & 10)

2024-06-27 Thread 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 v2 01/11] hw/sd/sdcard: Introduce sd_cmd_to_sendingdata and sd_generic_read_byte

2024-06-27 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 v2 02/11] hw/sd/sdcard: Convert SWITCH_FUNCTION to generic_read_byte (CMD6)

2024-06-27 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 v2 04/11] hw/sd/sdcard: Duplicate READ_SINGLE_BLOCK / READ_MULTIPLE_BLOCK cases

2024-06-27 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 v2 05/11] hw/sd/sdcard: Convert READ_SINGLE_BLOCK to generic_read_byte (CMD17)

2024-06-27 Thread 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




  1   2   3   4   5   6   7   8   9   10   >