[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 22/25] esp: fix PDMA target selection
From: |
Mark Cave-Ayland |
Subject: |
[PATCH 22/25] esp: fix PDMA target selection |
Date: |
Wed, 30 Dec 2020 15:37:42 +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>
---
hw/scsi/esp.c | 55 ++++++++++++++++++++++++++++++++-------------------
1 file changed, 35 insertions(+), 20 deletions(-)
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 50bddc7d68..69c03e59f0 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -227,7 +227,7 @@ static int esp_select(ESPState *s)
return 0;
}
-static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t buflen)
+static int32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t buflen)
{
uint32_t dmalen;
int target;
@@ -242,6 +242,9 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t
buflen)
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;
}
@@ -256,7 +259,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t
buflen)
trace_esp_get_cmd(dmalen, target);
if (esp_select(s) < 0) {
- return 0;
+ return -1;
}
return dmalen;
}
@@ -297,9 +300,6 @@ static void do_cmd(ESPState *s, uint8_t *buf)
static void satn_pdma_cb(ESPState *s)
{
- if (esp_select(s) < 0) {
- return;
- }
s->do_cmd = 0;
if (s->cmdlen) {
do_cmd(s, s->cmdbuf);
@@ -308,24 +308,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, s->cmdbuf, sizeof(s->cmdbuf));
- if (s->cmdlen) {
+ cmdlen = get_cmd(s, s->cmdbuf, sizeof(s->cmdbuf));
+ if (cmdlen > 0) {
+ s->cmdlen = cmdlen;
do_cmd(s, s->cmdbuf);
- } 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);
@@ -334,24 +338,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, s->cmdbuf, sizeof(s->cmdbuf));
- if (s->cmdlen) {
+ cmdlen = get_cmd(s, s->cmdbuf, sizeof(s->cmdbuf));
+ 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);
@@ -365,21 +373,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, s->cmdbuf, sizeof(s->cmdbuf));
- if (s->cmdlen) {
+ cmdlen = get_cmd(s, s->cmdbuf, sizeof(s->cmdbuf));
+ 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 12/25] esp: introduce esp_pdma_read() and esp_pdma_write() functions, (continued)
- [PATCH 12/25] esp: introduce esp_pdma_read() and esp_pdma_write() functions, Mark Cave-Ayland, 2020/12/30
- [PATCH 14/25] esp: move pdma_len and TC logic into esp_pdma_read()/esp_pdma_write(), Mark Cave-Ayland, 2020/12/30
- [PATCH 13/25] esp: use pdma_origin directly in esp_pdma_read()/esp_pdma_write(), Mark Cave-Ayland, 2020/12/30
- [PATCH 16/25] esp: remove redundant pdma_start from ESPState, Mark Cave-Ayland, 2020/12/30
- [PATCH 15/25] esp: accumulate SCSI commands for PDMA transfers in cmdbuf instead of pdma_buf, Mark Cave-Ayland, 2020/12/30
- [PATCH 17/25] esp: move PDMA length adjustments into esp_pdma_read()/esp_pdma_write(), Mark Cave-Ayland, 2020/12/30
- [PATCH 18/25] esp: use ti_wptr/ti_rptr to manage the current FIFO position for PDMA, Mark Cave-Ayland, 2020/12/30
- [PATCH 19/25] esp: use in-built TC to determine PDMA transfer length, Mark Cave-Ayland, 2020/12/30
- [PATCH 20/25] esp: remove CMD pdma_origin, Mark Cave-Ayland, 2020/12/30
- [PATCH 21/25] esp: rename get_cmd_cb() to esp_select(), Mark Cave-Ayland, 2020/12/30
- [PATCH 22/25] esp: fix PDMA target selection,
Mark Cave-Ayland <=
- [PATCH 23/25] esp: use FIFO for PDMA transfers between initiator and device, Mark Cave-Ayland, 2020/12/30
- [PATCH 24/25] esp: remove pdma_origin from ESPState, Mark Cave-Ayland, 2020/12/30
- [PATCH 25/25] esp: add 4 byte PDMA read and write transfers, Mark Cave-Ayland, 2020/12/30