From patchwork Thu Feb 18 14:34:59 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 8350991 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 61FFCC0553 for ; Thu, 18 Feb 2016 14:45:24 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B8F34202A1 for ; Thu, 18 Feb 2016 14:45:23 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E646620306 for ; Thu, 18 Feb 2016 14:45:22 +0000 (UTC) Received: from localhost ([::1]:41924 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aWPpa-00077F-2f for patchwork-qemu-devel@patchwork.kernel.org; Thu, 18 Feb 2016 09:45:22 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60359) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aWPft-0005IM-Om for qemu-devel@nongnu.org; Thu, 18 Feb 2016 09:35:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aWPfs-0007xc-Pq for qemu-devel@nongnu.org; Thu, 18 Feb 2016 09:35:21 -0500 Received: from mnementh.archaic.org.uk ([2001:8b0:1d0::1]:38427) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aWPfs-0007rP-Ik for qemu-devel@nongnu.org; Thu, 18 Feb 2016 09:35:20 -0500 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.84) (envelope-from ) id 1aWPfi-0001qv-Al for qemu-devel@nongnu.org; Thu, 18 Feb 2016 14:35:10 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Thu, 18 Feb 2016 14:34:59 +0000 Message-Id: <1455806108-6961-28-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1455806108-6961-1-git-send-email-peter.maydell@linaro.org> References: <1455806108-6961-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2001:8b0:1d0::1 Subject: [Qemu-devel] [PULL 27/36] hw/sd: implement CMD23 (SET_BLOCK_COUNT) for MMC compatibility X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Andrew Baumann CMD23 is optional for SD but required for MMC, and the UEFI bootloader used for Windows on Raspberry Pi 2 issues it. Reviewed-by: Peter Crosthwaite Signed-off-by: Andrew Baumann Message-id: 1454902521-21164-2-git-send-email-Andrew.Baumann@microsoft.com Signed-off-by: Peter Maydell --- hw/sd/sd.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 8902cd8..8dd6f39 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -98,6 +98,7 @@ struct SDState { int32_t wpgrps_size; uint64_t size; uint32_t blk_len; + uint32_t multi_blk_cnt; uint32_t erase_start; uint32_t erase_end; uint8_t pwd[16]; @@ -430,6 +431,7 @@ static void sd_reset(DeviceState *dev) sd->blk_len = 0x200; sd->pwd_len = 0; sd->expecting_acmd = false; + sd->multi_blk_cnt = 0; } static bool sd_get_inserted(SDState *sd) @@ -489,6 +491,7 @@ static const VMStateDescription sd_vmstate = { VMSTATE_UINT32(vhs, SDState), VMSTATE_BITMAP(wp_groups, SDState, 0, wpgrps_size), VMSTATE_UINT32(blk_len, SDState), + VMSTATE_UINT32(multi_blk_cnt, SDState), VMSTATE_UINT32(erase_start, SDState), VMSTATE_UINT32(erase_end, SDState), VMSTATE_UINT8_ARRAY(pwd, SDState, 16), @@ -699,6 +702,12 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 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)) { + sd->multi_blk_cnt = 0; + } + DPRINTF("CMD%d 0x%08x state %d\n", req.cmd, req.arg, sd->state); switch (req.cmd) { /* Basic commands (Class 0 and Class 1) */ @@ -994,6 +1003,17 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, } break; + case 23: /* CMD23: SET_BLOCK_COUNT */ + switch (sd->state) { + case sd_transfer_state: + sd->multi_blk_cnt = req.arg; + return sd_r1; + + default: + break; + } + break; + /* Block write commands (Class 4) */ case 24: /* CMD24: WRITE_SINGLE_BLOCK */ if (sd->spi) @@ -1594,6 +1614,14 @@ void sd_write_data(SDState *sd, uint8_t value) sd->csd[14] |= 0x40; /* Bzzzzzzztt .... Operation complete. */ + if (sd->multi_blk_cnt != 0) { + if (--sd->multi_blk_cnt == 0) { + /* Stop! */ + sd->state = sd_transfer_state; + break; + } + } + sd->state = sd_receivingdata_state; } break; @@ -1740,6 +1768,15 @@ uint8_t sd_read_data(SDState *sd) if (sd->data_offset >= io_len) { sd->data_start += io_len; sd->data_offset = 0; + + if (sd->multi_blk_cnt != 0) { + if (--sd->multi_blk_cnt == 0) { + /* Stop! */ + sd->state = sd_transfer_state; + break; + } + } + if (sd->data_start + io_len > sd->size) { sd->card_status |= ADDRESS_ERROR; break;