[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v3 27/42] esp: fix PDMA target selection
From: |
Mark Cave-Ayland |
Subject: |
[PATCH v3 27/42] esp: fix PDMA target selection |
Date: |
Thu, 4 Mar 2021 22:10:48 +0000 |
Currently the target selection for PDMA is done after the SCSI command has been
delivered which is not correct. Perform target selection as part of the initial
get_cmd() call when the command is submitted: if no target is present, don't
raise DRQ.
If the target is present then switch to the command phase since the MacOS
toolbox
ROM checks for this before attempting to submit the SCSI command.
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
---
hw/scsi/esp.c | 53 +++++++++++++++++++++++++++++++++------------------
1 file changed, 34 insertions(+), 19 deletions(-)
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index d8d7ede00a..10e63d1f62 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -243,6 +243,9 @@ static uint32_t get_cmd(ESPState *s)
s->dma_memory_read(s->dma_opaque, buf, dmalen);
} else {
set_pdma(s, TI);
+ if (esp_select(s) < 0) {
+ return -1;
+ }
esp_raise_drq(s);
return 0;
}
@@ -257,7 +260,7 @@ static uint32_t get_cmd(ESPState *s)
trace_esp_get_cmd(dmalen, target);
if (esp_select(s) < 0) {
- return 0;
+ return -1;
}
return dmalen;
}
@@ -299,9 +302,6 @@ static void do_cmd(ESPState *s)
static void satn_pdma_cb(ESPState *s)
{
- if (esp_select(s) < 0) {
- return;
- }
s->do_cmd = 0;
if (s->cmdlen) {
do_cmd(s);
@@ -310,24 +310,28 @@ static void satn_pdma_cb(ESPState *s)
static void handle_satn(ESPState *s)
{
+ int32_t cmdlen;
+
if (s->dma && !s->dma_enabled) {
s->dma_cb = handle_satn;
return;
}
s->pdma_cb = satn_pdma_cb;
- s->cmdlen = get_cmd(s);
- if (s->cmdlen) {
+ cmdlen = get_cmd(s);
+ if (cmdlen > 0) {
+ s->cmdlen = cmdlen;
do_cmd(s);
- } else {
+ } else if (cmdlen == 0) {
+ s->cmdlen = 0;
s->do_cmd = 1;
+ /* Target present, but no cmd yet - switch to command phase */
+ s->rregs[ESP_RSEQ] = SEQ_CD;
+ s->rregs[ESP_RSTAT] = STAT_CD;
}
}
static void s_without_satn_pdma_cb(ESPState *s)
{
- if (esp_select(s) < 0) {
- return;
- }
s->do_cmd = 0;
if (s->cmdlen) {
do_busid_cmd(s, s->cmdbuf, 0);
@@ -336,24 +340,28 @@ static void s_without_satn_pdma_cb(ESPState *s)
static void handle_s_without_atn(ESPState *s)
{
+ int32_t cmdlen;
+
if (s->dma && !s->dma_enabled) {
s->dma_cb = handle_s_without_atn;
return;
}
s->pdma_cb = s_without_satn_pdma_cb;
- s->cmdlen = get_cmd(s);
- if (s->cmdlen) {
+ cmdlen = get_cmd(s);
+ if (cmdlen > 0) {
+ s->cmdlen = cmdlen;
do_busid_cmd(s, s->cmdbuf, 0);
- } else {
+ } else if (cmdlen == 0) {
+ s->cmdlen = 0;
s->do_cmd = 1;
+ /* Target present, but no cmd yet - switch to command phase */
+ s->rregs[ESP_RSEQ] = SEQ_CD;
+ s->rregs[ESP_RSTAT] = STAT_CD;
}
}
static void satn_stop_pdma_cb(ESPState *s)
{
- if (esp_select(s) < 0) {
- return;
- }
s->do_cmd = 0;
if (s->cmdlen) {
trace_esp_handle_satn_stop(s->cmdlen);
@@ -367,21 +375,28 @@ static void satn_stop_pdma_cb(ESPState *s)
static void handle_satn_stop(ESPState *s)
{
+ int32_t cmdlen;
+
if (s->dma && !s->dma_enabled) {
s->dma_cb = handle_satn_stop;
return;
}
s->pdma_cb = satn_stop_pdma_cb;
- s->cmdlen = get_cmd(s);
- if (s->cmdlen) {
+ cmdlen = get_cmd(s);
+ if (cmdlen > 0) {
trace_esp_handle_satn_stop(s->cmdlen);
+ s->cmdlen = cmdlen;
s->do_cmd = 1;
s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
s->rregs[ESP_RSEQ] = SEQ_CD;
esp_raise_irq(s);
- } else {
+ } else if (cmdlen == 0) {
+ s->cmdlen = 0;
s->do_cmd = 1;
+ /* Target present, but no cmd yet - switch to command phase */
+ s->rregs[ESP_RSEQ] = SEQ_CD;
+ s->rregs[ESP_RSTAT] = STAT_CD;
}
}
--
2.20.1
- [PATCH v3 17/42] esp: move pdma_len and TC logic into esp_pdma_read()/esp_pdma_write(), (continued)
- [PATCH v3 17/42] esp: move pdma_len and TC logic into esp_pdma_read()/esp_pdma_write(), Mark Cave-Ayland, 2021/03/04
- [PATCH v3 18/42] esp: accumulate SCSI commands for PDMA transfers in cmdbuf instead of pdma_buf, Mark Cave-Ayland, 2021/03/04
- [PATCH v3 19/42] esp: remove buf parameter from do_cmd(), Mark Cave-Ayland, 2021/03/04
- [PATCH v3 20/42] esp: remove the buf and buflen parameters from get_cmd(), Mark Cave-Ayland, 2021/03/04
- [PATCH v3 21/42] esp: remove redundant pdma_start from ESPState, Mark Cave-Ayland, 2021/03/04
- [PATCH v3 22/42] esp: move PDMA length adjustments into esp_pdma_read()/esp_pdma_write(), Mark Cave-Ayland, 2021/03/04
- [PATCH v3 23/42] esp: use ti_wptr/ti_rptr to manage the current FIFO position for PDMA, Mark Cave-Ayland, 2021/03/04
- [PATCH v3 24/42] esp: use in-built TC to determine PDMA transfer length, Mark Cave-Ayland, 2021/03/04
- [PATCH v3 25/42] esp: remove CMD pdma_origin, Mark Cave-Ayland, 2021/03/04
- [PATCH v3 26/42] esp: rename get_cmd_cb() to esp_select(), Mark Cave-Ayland, 2021/03/04
- [PATCH v3 27/42] esp: fix PDMA target selection,
Mark Cave-Ayland <=
- [PATCH v3 28/42] esp: use FIFO for PDMA transfers between initiator and device, Mark Cave-Ayland, 2021/03/04
- [PATCH v3 29/42] esp: remove pdma_origin from ESPState, Mark Cave-Ayland, 2021/03/04
- [PATCH v3 30/42] esp: add 4 byte PDMA read and write transfers, Mark Cave-Ayland, 2021/03/04
- [PATCH v3 31/42] esp: implement FIFO flush command, Mark Cave-Ayland, 2021/03/04
- [PATCH v3 32/42] esp: latch individual bits in ESP_RINTR register, Mark Cave-Ayland, 2021/03/04
- [PATCH v3 33/42] esp: defer command completion interrupt on incoming data transfers, Mark Cave-Ayland, 2021/03/04
- [PATCH v3 34/42] esp: remove old deferred command completion mechanism, Mark Cave-Ayland, 2021/03/04
- [PATCH v3 35/42] esp: raise interrupt after every non-DMA byte transferred to the FIFO, Mark Cave-Ayland, 2021/03/04
- [PATCH v3 36/42] esp: add maxlen parameter to get_cmd(), Mark Cave-Ayland, 2021/03/04
- [PATCH v3 37/42] esp: transition to message out phase after SATN and stop command, Mark Cave-Ayland, 2021/03/04