hw/sd/sdcard: Introduce sd_cmd_to_sendingdata and sd_generic_read_byte

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é <philmd@linaro.org>
Tested-by: Cédric Le Goater <clg@redhat.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Message-Id: <4c9f7f51-83ee-421a-8690-9af2e80b134b@linaro.org>
This commit is contained in:
Philippe Mathieu-Daudé 2024-06-13 16:21:12 +02:00
parent d45c3d7e1a
commit f486bf7d10
1 changed files with 39 additions and 0 deletions

View File

@ -141,8 +141,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];
qemu_irq readonly_cb;
qemu_irq inserted_cb;
@ -1078,6 +1080,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 > 0 && size <= sizeof(sd->data));
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)
{
@ -1912,6 +1937,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;