From nobody Mon Feb 9 18:56:24 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1615120681; cv=none; d=zohomail.com; s=zohoarc; b=F30taOJiYONmFoGyN/kTBusMVOU09f5hSHMBXabZOTVloZ3lcyTlWCk95XNtHy0iQyxZtVsDS2D2VvN4EhlJRw2bKOZw/wD3LbcI2D3ZApFAqmDYQAfB5zWBp3Yhx2xXo5FtrpvyRvxUUJZnSHz6hQucxhSWvm8CkP/KyHWKt8U= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1615120681; h=Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=xjcIwZuM2BzbVKv4Ad/r3LZXXNVphPYRz/kAOVRgpkI=; b=OO1n33YIneVErqkqo5Bj8Kq71cjJwZ5KOEEmExcNBVKwYkbBkSMlPx/eTJOA77Tm5GuC21YogV9zTRXF9ppIhs9MOUbPIq2D3lXy4oaA6amhiig4qGbNVFaPyK6au0nDZGI4260rNPaFiXJV8rgFC+Q9qihbJWoS1suyRltUM54= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 161512068162652.03799097220906; Sun, 7 Mar 2021 04:38:01 -0800 (PST) Received: from localhost ([::1]:47168 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lIsfY-0003my-DZ for importer@patchew.org; Sun, 07 Mar 2021 07:38:00 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:41942) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lIsGT-0003GJ-8K for qemu-devel@nongnu.org; Sun, 07 Mar 2021 07:12:07 -0500 Received: from mail.ilande.co.uk ([2001:41c9:1:41f::167]:43748 helo=mail.default.ilande.uk0.bigv.io) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lIsGO-0008EK-Ph for qemu-devel@nongnu.org; Sun, 07 Mar 2021 07:12:05 -0500 Received: from host86-148-34-47.range86-148.btcentralplus.com ([86.148.34.47] helo=kentang.home) by mail.default.ilande.uk0.bigv.io with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lIsG9-0002V5-MM; Sun, 07 Mar 2021 12:11:50 +0000 From: Mark Cave-Ayland To: qemu-devel@nongnu.org, peter.maydell@linaro.org Date: Sun, 7 Mar 2021 12:08:41 +0000 Message-Id: <20210307120850.10418-34-mark.cave-ayland@ilande.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210307120850.10418-1-mark.cave-ayland@ilande.co.uk> References: <20210307120850.10418-1-mark.cave-ayland@ilande.co.uk> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-SA-Exim-Connect-IP: 86.148.34.47 X-SA-Exim-Mail-From: mark.cave-ayland@ilande.co.uk Subject: [PULL 33/42] esp: defer command completion interrupt on incoming data transfers X-SA-Exim-Version: 4.2.1 (built Wed, 08 May 2019 21:11:16 +0000) X-SA-Exim-Scanned: Yes (on mail.default.ilande.uk0.bigv.io) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2001:41c9:1:41f::167; envelope-from=mark.cave-ayland@ilande.co.uk; helo=mail.default.ilande.uk0.bigv.io X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" The MacOS toolbox ROM issues a command to the ESP controller as part of its "FAST" SCSI routines and then proceeds to read the incoming data soon after receiving the command completion interrupt. Unfortunately due to SCSI block transfers being asynchronous the incoming d= ata may not yet be present causing an underflow error. Resolve this by waiting = for the SCSI subsystem transfer_data callback before raising the command comple= tion interrupt. Signed-off-by: Mark Cave-Ayland Reviewed-by: Laurent Vivier Message-Id: <20210304221103.6369-34-mark.cave-ayland@ilande.co.uk> --- hw/scsi/esp.c | 66 ++++++++++++++++++++++++++++++++++--------- include/hw/scsi/esp.h | 1 + 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 54d008c609..0eecc1d05c 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -183,6 +183,14 @@ static int esp_select(ESPState *s) esp_raise_irq(s); return -1; } + + /* + * Note that we deliberately don't raise the IRQ here: this will be do= ne + * either in do_busid_cmd() for DATA OUT transfers or by the deferred + * IRQ mechanism in esp_transfer_data() for DATA IN transfers + */ + s->rregs[ESP_RINTR] |=3D INTR_FC; + s->rregs[ESP_RSEQ] =3D SEQ_CD; return 0; } =20 @@ -237,18 +245,24 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, u= int8_t busid) s->ti_size =3D datalen; if (datalen !=3D 0) { s->rregs[ESP_RSTAT] =3D STAT_TC; + s->rregs[ESP_RSEQ] =3D SEQ_CD; esp_set_tc(s, 0); if (datalen > 0) { + /* + * Switch to DATA IN phase but wait until initial data xfer is + * complete before raising the command completion interrupt + */ + s->data_in_ready =3D false; s->rregs[ESP_RSTAT] |=3D STAT_DI; } else { s->rregs[ESP_RSTAT] |=3D STAT_DO; + s->rregs[ESP_RINTR] |=3D INTR_BS | INTR_FC; + esp_raise_irq(s); + esp_lower_drq(s); } scsi_req_continue(s->current_req); + return; } - s->rregs[ESP_RINTR] |=3D INTR_BS | INTR_FC; - s->rregs[ESP_RSEQ] =3D SEQ_CD; - esp_raise_irq(s); - esp_lower_drq(s); } =20 static void do_cmd(ESPState *s) @@ -439,17 +453,11 @@ static void do_dma_pdma_cb(ESPState *s) } else { if (s->async_len =3D=3D 0) { if (s->current_req) { + /* Defer until the scsi layer has completed */ scsi_req_continue(s->current_req); + s->data_in_ready =3D false; } - - /* - * If there is still data to be read from the device then - * complete the DMA operation immediately. Otherwise defer - * until the scsi layer has completed. - */ - if (esp_get_tc(s) !=3D 0 || s->ti_size =3D=3D 0) { - return; - } + return; } =20 if (esp_get_tc(s) !=3D 0) { @@ -602,12 +610,35 @@ void esp_command_complete(SCSIRequest *req, size_t re= sid) void esp_transfer_data(SCSIRequest *req, uint32_t len) { ESPState *s =3D req->hba_private; + int to_device =3D ((s->rregs[ESP_RSTAT] & 7) =3D=3D STAT_DO); uint32_t dmalen =3D esp_get_tc(s); =20 assert(!s->do_cmd); trace_esp_transfer_data(dmalen, s->ti_size); s->async_len =3D len; s->async_buf =3D scsi_req_get_buf(req); + + if (!to_device && !s->data_in_ready) { + /* + * Initial incoming data xfer is complete so raise command + * completion interrupt + */ + s->data_in_ready =3D true; + s->rregs[ESP_RSTAT] |=3D STAT_TC; + s->rregs[ESP_RINTR] |=3D INTR_BS; + esp_raise_irq(s); + + /* + * If data is ready to transfer and the TI command has already + * been executed, start DMA immediately. Otherwise DMA will start + * when host sends the TI command + */ + if (s->ti_size && (s->rregs[ESP_CMD] =3D=3D (CMD_TI | CMD_DMA))) { + esp_do_dma(s); + } + return; + } + if (dmalen) { esp_do_dma(s); } else if (s->ti_size <=3D 0) { @@ -869,6 +900,14 @@ static bool esp_is_before_version_5(void *opaque, int = version_id) return version_id < 5; } =20 +static bool esp_is_version_5(void *opaque, int version_id) +{ + ESPState *s =3D ESP(opaque); + + version_id =3D MIN(version_id, s->mig_version_id); + return version_id =3D=3D 5; +} + static int esp_pre_save(void *opaque) { ESPState *s =3D ESP(opaque); @@ -913,6 +952,7 @@ const VMStateDescription vmstate_esp =3D { VMSTATE_UINT32(cmdlen, ESPState), VMSTATE_UINT32(do_cmd, ESPState), VMSTATE_UINT32_TEST(mig_dma_left, ESPState, esp_is_before_version_= 5), + VMSTATE_BOOL_TEST(data_in_ready, ESPState, esp_is_version_5), VMSTATE_END_OF_LIST() }, }; diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h index 91f8ffd6c8..61bc317a4c 100644 --- a/include/hw/scsi/esp.h +++ b/include/hw/scsi/esp.h @@ -41,6 +41,7 @@ struct ESPState { uint32_t cmdlen; uint32_t do_cmd; =20 + bool data_in_ready; int dma_enabled; =20 uint32_t async_len; --=20 2.20.1