diff options
author | Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> | 2024-01-12 12:53:38 +0000 |
---|---|---|
committer | Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> | 2024-02-13 19:37:28 +0000 |
commit | 46b0c361254497769f1b4935dc5e7031b84db251 (patch) | |
tree | fd903a4f1e8bd413ed5d0fd0931c36303ae1c73e /hw/scsi | |
parent | 6d97f5acbf029b9c3cbf75fb7102931c2afe8dd3 (diff) |
esp.c: untangle MESSAGE OUT and COMMAND phase logic in esp_do_dma()
This makes it clearer that ATN is asserted until the end of the next TI command
in the MESSAGE OUT phase.
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Tested-by: Helge Deller <deller@gmx.de>
Tested-by: Thomas Huth <thuth@redhat.com>
Message-Id: <20240112125420.514425-47-mark.cave-ayland@ilande.co.uk>
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Diffstat (limited to 'hw/scsi')
-rw-r--r-- | hw/scsi/esp.c | 48 |
1 files changed, 26 insertions, 22 deletions
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 1f7dff4ca6..2f54fd1285 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -629,6 +629,31 @@ static void esp_do_dma(ESPState *s) switch (esp_get_phase(s)) { case STAT_MO: + if (s->dma_memory_read) { + len = MIN(len, fifo8_num_free(&s->cmdfifo)); + s->dma_memory_read(s->dma_opaque, buf, len); + fifo8_push_all(&s->cmdfifo, buf, len); + esp_set_tc(s, esp_get_tc(s) - len); + s->cmdfifo_cdb_offset += len; + } else { + n = esp_fifo_pop_buf(&s->fifo, buf, fifo8_num_used(&s->fifo)); + n = MIN(fifo8_num_free(&s->cmdfifo), n); + fifo8_push_all(&s->cmdfifo, buf, n); + s->cmdfifo_cdb_offset += n; + } + + esp_set_pdma_cb(s, DO_DMA_PDMA_CB); + esp_raise_drq(s); + + /* ATN remains asserted until TC == 0 */ + if (esp_get_tc(s) == 0) { + esp_set_phase(s, STAT_CD); + s->rregs[ESP_RSEQ] = SEQ_CD; + s->rregs[ESP_RINTR] |= INTR_BS; + esp_raise_irq(s); + } + break; + case STAT_CD: cmdlen = fifo8_num_used(&s->cmdfifo); trace_esp_do_dma(cmdlen, len); @@ -641,36 +666,15 @@ static void esp_do_dma(ESPState *s) n = esp_fifo_pop_buf(&s->fifo, buf, fifo8_num_used(&s->fifo)); n = MIN(fifo8_num_free(&s->cmdfifo), n); fifo8_push_all(&s->cmdfifo, buf, n); - esp_set_tc(s, esp_get_tc(s) - n); esp_set_pdma_cb(s, DO_DMA_PDMA_CB); esp_raise_drq(s); - - /* Ensure we have received complete command after SATN and stop */ - if (esp_get_tc(s) || fifo8_is_empty(&s->cmdfifo)) { - return; - } } trace_esp_handle_ti_cmd(cmdlen); s->ti_size = 0; - if (esp_get_phase(s) == STAT_CD) { - /* No command received */ - if (s->cmdfifo_cdb_offset == fifo8_num_used(&s->cmdfifo)) { - return; - } - + if (esp_get_tc(s) == 0) { /* Command has been received */ do_cmd(s); - } else { - /* - * Extra message out bytes received: update cmdfifo_cdb_offset - * and then switch to command phase - */ - s->cmdfifo_cdb_offset = fifo8_num_used(&s->cmdfifo); - esp_set_phase(s, STAT_CD); - s->rregs[ESP_RSEQ] = SEQ_CD; - s->rregs[ESP_RINTR] |= INTR_BS; - esp_raise_irq(s); } break; |