From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:53445) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UapuG-0007lO-Qw for qemu-devel@nongnu.org; Fri, 10 May 2013 12:10:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UapuB-0006Us-Aj for qemu-devel@nongnu.org; Fri, 10 May 2013 12:10:52 -0400 Received: from mail-lb0-f181.google.com ([209.85.217.181]:50453) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UapuA-0006U8-PN for qemu-devel@nongnu.org; Fri, 10 May 2013 12:10:47 -0400 Received: by mail-lb0-f181.google.com with SMTP id w10so4417195lbi.12 for ; Fri, 10 May 2013 09:10:45 -0700 (PDT) From: Igor Mitsyanko Date: Fri, 10 May 2013 20:10:23 +0400 Message-Id: <1368202225-45798-6-git-send-email-i.mitsyanko@gmail.com> In-Reply-To: <1368202225-45798-1-git-send-email-i.mitsyanko@gmail.com> References: <1368202225-45798-1-git-send-email-i.mitsyanko@gmail.com> Subject: [Qemu-devel] [RFC 5/7] sd.c: introduce async read operation List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, aliguori@us.ibm.com, i.mitsyanko@gmail.com, sw@weilnetz.de, peter.crosthwaite@xilinx.com, blauwirbel@gmail.com, paul@codesourcery.com, stefanha@redhat.com, pbonzini@redhat.com, afaerber@suse.de It will only be used if start bit and databusy callbacks were initialized by user of SD card model. Signed-off-by: Igor Mitsyanko --- hw/sd/sd.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 8 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index a0bbbaa..659ec56 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -685,6 +685,44 @@ static void sd_lock_command(SDState *sd) sd->card_status &= ~CARD_IS_LOCKED; } +static void sd_bdrv_read_done(void *opaque, int ret) +{ + SDState *sd = opaque; + uint32_t io_len, offset; + uint64_t end_sector; + + DPRINTF("sd_bdrv_read_done ret = %d, \n", ret); + sd->aiocb = NULL; + + if (ret != 0) { + return; + } + + if (sd->state != sd_sendingdata_state) { + DPRINTF("Transfer was aborted\n"); + return; + } + + io_len = (sd->ocr & (1 << 30)) ? 512 : sd->blk_len; + end_sector = (sd->data_start + io_len - 1) >> BDRV_SECTOR_BITS; + offset = (sd->data_start + sd->transf_cnt) & ~BDRV_SECTOR_MASK; + + if (end_sector > + (sd->data_start + sd->transf_cnt) >> BDRV_SECTOR_BITS) { + memcpy(sd->data, sd->buf + offset, BDRV_SECTOR_SIZE - offset); + sd->transf_cnt += BDRV_SECTOR_SIZE - offset; + sd->aiocb = bdrv_aio_readv(sd->bdrv, end_sector, &sd->qiov, 1, + sd_bdrv_read_done, sd); + return; + } else { + memcpy(sd->data + sd->transf_cnt, sd->buf + offset, + io_len - sd->transf_cnt); + sd->transf_cnt += io_len - sd->transf_cnt; + } + + qemu_irq_raise(sd->start_bit_cb); +} + static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) { @@ -891,8 +929,13 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, sd->data_start = req.arg; sd->data_offset = 0; - if (sd->data_start + sd->blk_len > sd->size) + if (sd->data_start + sd->blk_len > sd->size) { sd->card_status |= ADDRESS_ERROR; + } else if (sd->iov.iov_base) { + sd->aiocb = bdrv_aio_readv(sd->bdrv, + sd->data_start >> BDRV_SECTOR_BITS, + &sd->qiov, 1, sd_bdrv_read_done, sd); + } return sd_r0; default: @@ -904,6 +947,11 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, switch (sd->state) { case sd_sendingdata_state: sd->state = sd_transfer_state; + sd->transf_cnt = 0; + if (sd->aiocb) { + bdrv_aio_cancel(sd->aiocb); + sd->aiocb = NULL; + } return sd_r1b; case sd_receivingdata_state: @@ -969,8 +1017,13 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, sd->data_start = addr; sd->data_offset = 0; - if (sd->data_start + sd->blk_len > sd->size) + if (sd->data_start + sd->blk_len > sd->size) { sd->card_status |= ADDRESS_ERROR; + } else { + sd->aiocb = bdrv_aio_readv(sd->bdrv, + sd->data_start >> BDRV_SECTOR_BITS, + &sd->qiov, 1, sd_bdrv_read_done, sd); + } return sd_r1; default: @@ -985,8 +1038,13 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, sd->data_start = addr; sd->data_offset = 0; - if (sd->data_start + sd->blk_len > sd->size) + if (sd->data_start + sd->blk_len > sd->size) { sd->card_status |= ADDRESS_ERROR; + } else { + sd->aiocb = bdrv_aio_readv(sd->bdrv, + sd->data_start >> BDRV_SECTOR_BITS, + &sd->qiov, 1, sd_bdrv_read_done, sd); + } return sd_r1; default: @@ -1706,16 +1764,21 @@ uint8_t sd_read_data(SDState *sd) break; case 11: /* CMD11: READ_DAT_UNTIL_STOP */ - if (sd->data_offset == 0) + if (sd->data_offset == 0 && sd->iov.iov_base == NULL) { BLK_READ_BLOCK(sd->data_start, io_len); + } ret = sd->data[sd->data_offset ++]; if (sd->data_offset >= io_len) { sd->data_start += io_len; sd->data_offset = 0; + sd->transf_cnt = 0; if (sd->data_start + io_len > sd->size) { sd->card_status |= ADDRESS_ERROR; - break; + } else if (sd->iov.iov_base) { + sd->aiocb = bdrv_aio_readv(sd->bdrv, + sd->data_start >> BDRV_SECTOR_BITS, + &sd->qiov, 1, sd_bdrv_read_done, sd); } } break; @@ -1728,8 +1791,9 @@ uint8_t sd_read_data(SDState *sd) break; case 17: /* CMD17: READ_SINGLE_BLOCK */ - if (sd->data_offset == 0) + if (sd->data_offset == 0 && sd->iov.iov_base == NULL) { BLK_READ_BLOCK(sd->data_start, io_len); + } ret = sd->data[sd->data_offset ++]; if (sd->data_offset >= io_len) @@ -1737,16 +1801,21 @@ uint8_t sd_read_data(SDState *sd) break; case 18: /* CMD18: READ_MULTIPLE_BLOCK */ - if (sd->data_offset == 0) + if (sd->data_offset == 0 && sd->iov.iov_base == NULL) { BLK_READ_BLOCK(sd->data_start, io_len); + } ret = sd->data[sd->data_offset ++]; if (sd->data_offset >= io_len) { sd->data_start += io_len; sd->data_offset = 0; + sd->transf_cnt = 0; if (sd->data_start + io_len > sd->size) { sd->card_status |= ADDRESS_ERROR; - break; + } else if (sd->iov.iov_base) { + sd->aiocb = bdrv_aio_readv(sd->bdrv, + sd->data_start >> BDRV_SECTOR_BITS, + &sd->qiov, 1, sd_bdrv_read_done, sd); } } break; -- 1.8.1.4