Paths that use sd_generic_write/read_data can now write/read multiple bytes with one call.
Signed-off-by: Christian Speich <[email protected]> --- hw/sd/sd.c | 62 +++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 135113add29b5ee3cb11d9d535355eba8f6cb3f7..2c81776df316feda75f97e15cc9bbd1538f1a21c 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1609,7 +1609,7 @@ static sd_rsp_type_t sd_cmd_optional(SDState *sd, SDRequest req) return sd_illegal; } -/* Configure fields for following sd_generic_write_byte() calls */ +/* Configure fields for following sd_generic_write_data() calls */ static sd_rsp_type_t sd_cmd_to_receivingdata(SDState *sd, SDRequest req, uint64_t start, size_t size) { @@ -1624,7 +1624,7 @@ static sd_rsp_type_t sd_cmd_to_receivingdata(SDState *sd, SDRequest req, return sd_r1; } -/* Configure fields for following sd_generic_read_byte() calls */ +/* Configure fields for following sd_generic_read_data() calls */ static sd_rsp_type_t sd_cmd_to_sendingdata(SDState *sd, SDRequest req, uint64_t start, const void *data, size_t size) @@ -2614,11 +2614,15 @@ send_response: } /* Return true if buffer is consumed. Configured by sd_cmd_to_receivingdata() */ -static bool sd_generic_write_byte(SDState *sd, uint8_t value) +static bool sd_generic_write_data(SDState *sd, const void *buf, size_t *len) { - sd->data[sd->data_offset] = value; + size_t to_write = MIN(sd->data_size - sd->data_offset, *len); - if (++sd->data_offset >= sd->data_size) { + memcpy(sd->data, buf, to_write); + sd->data_offset += to_write; + *len = to_write; + + if (sd->data_offset >= sd->data_size) { sd->state = sd_transfer_state; return true; } @@ -2626,11 +2630,15 @@ static bool sd_generic_write_byte(SDState *sd, uint8_t value) } /* Return true when buffer is consumed. Configured by sd_cmd_to_sendingdata() */ -static bool sd_generic_read_byte(SDState *sd, uint8_t *value) +static bool sd_generic_read_data(SDState *sd, void *buf, size_t *len) { - *value = sd->data[sd->data_offset]; + size_t to_read = MIN(sd->data_size - sd->data_offset, *len); + + memcpy(buf, sd->data, to_read); + sd->data_offset += to_read; + *len = to_read; - if (++sd->data_offset >= sd->data_size) { + if (sd->data_offset >= sd->data_size) { sd->state = sd_transfer_state; return true; } @@ -2657,18 +2665,12 @@ static size_t sd_write_data(SDState *sd, const void *buf, size_t length) if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION)) return length; - /* - * Only read one byte at a time. We will be called again with the - * remaining. - */ - length = 1; - trace_sdcard_write_data(sd->proto->name, sd->last_cmd_name, sd->current_cmd, sd->data_offset, value[0]); switch (sd->current_cmd) { case 24: /* CMD24: WRITE_SINGLE_BLOCK */ - if (sd_generic_write_byte(sd, value[0])) { + if (sd_generic_write_data(sd, buf, &length)) { /* TODO: Check CRC before committing */ sd->state = sd_programming_state; sd_blk_write(sd, sd->data_start, sd->data_offset); @@ -2680,6 +2682,12 @@ static size_t sd_write_data(SDState *sd, const void *buf, size_t length) break; case 25: /* CMD25: WRITE_MULTIPLE_BLOCK */ + /* + * Only read one byte at a time. We will be called again with the + * remaining. + */ + length = 1; + if (sd->data_offset == 0) { /* Start of the block - let's check the address is valid */ if (!address_in_range(sd, "WRITE_MULTIPLE_BLOCK", @@ -2723,7 +2731,7 @@ static size_t sd_write_data(SDState *sd, const void *buf, size_t length) break; case 26: /* CMD26: PROGRAM_CID */ - if (sd_generic_write_byte(sd, value[0])) { + if (sd_generic_write_data(sd, buf, &length)) { /* TODO: Check CRC before committing */ sd->state = sd_programming_state; for (i = 0; i < sizeof(sd->cid); i ++) @@ -2741,7 +2749,7 @@ static size_t sd_write_data(SDState *sd, const void *buf, size_t length) break; case 27: /* CMD27: PROGRAM_CSD */ - if (sd_generic_write_byte(sd, value[0])) { + if (sd_generic_write_data(sd, buf, &length)) { /* TODO: Check CRC before committing */ sd->state = sd_programming_state; for (i = 0; i < sizeof(sd->csd); i ++) @@ -2764,7 +2772,7 @@ static size_t sd_write_data(SDState *sd, const void *buf, size_t length) break; case 42: /* CMD42: LOCK_UNLOCK */ - if (sd_generic_write_byte(sd, value[0])) { + if (sd_generic_write_data(sd, buf, &length)) { /* TODO: Check CRC before committing */ sd->state = sd_programming_state; sd_lock_command(sd); @@ -2774,7 +2782,7 @@ static size_t sd_write_data(SDState *sd, const void *buf, size_t length) break; case 56: /* CMD56: GEN_CMD */ - sd_generic_write_byte(sd, value[0]); + sd_generic_write_data(sd, buf, &length); break; default: @@ -2809,12 +2817,6 @@ static size_t sd_read_data(SDState *sd, void *buf, size_t length) return length; } - /* - * We will only read one byte at a time. We will be called again with the - * remaining buffer. - */ - length = 1; - io_len = sd_blk_len(sd); trace_sdcard_read_data(sd->proto->name, @@ -2832,10 +2834,16 @@ static size_t sd_read_data(SDState *sd, void *buf, size_t length) case 30: /* CMD30: SEND_WRITE_PROT */ case 51: /* ACMD51: SEND_SCR */ case 56: /* CMD56: GEN_CMD */ - sd_generic_read_byte(sd, value); + sd_generic_read_data(sd, buf, &length); break; case 18: /* CMD18: READ_MULTIPLE_BLOCK */ + /* + * We will only read one byte at a time. We will be called again with + * the remaining buffer. + */ + length = 1; + if (sd->data_offset == 0) { if (!address_in_range(sd, "READ_MULTIPLE_BLOCK", sd->data_start, io_len)) { @@ -2868,7 +2876,7 @@ static size_t sd_read_data(SDState *sd, void *buf, size_t length) default: qemu_log_mask(LOG_GUEST_ERROR, "%s: DAT read illegal for command %s\n", __func__, sd->last_cmd_name); - *value = dummy_byte; + memset(buf, dummy_byte, length); } return length; -- 2.43.0
