summaryrefslogtreecommitdiffstats
path: root/hw
diff options
context:
space:
mode:
authorMark Cave-Ayland2021-05-19 12:08:03 +0200
committerPaolo Bonzini2021-06-15 17:17:09 +0200
commitc348458f357784629c36a6eb1493c0c0c33b74e7 (patch)
tree44604148588b8d04c97dce2d1a7f43943508bed6 /hw
parentesp: revert 75ef849696 "esp: correctly fill bus id with requested lun" (diff)
downloadqemu-c348458f357784629c36a6eb1493c0c0c33b74e7.tar.gz
qemu-c348458f357784629c36a6eb1493c0c0c33b74e7.tar.xz
qemu-c348458f357784629c36a6eb1493c0c0c33b74e7.zip
esp: correctly accumulate extended messages for PDMA
Commit 799d90d818 "esp: transition to message out phase after SATN and stop command" added logic to correctly handle extended messages for DMA requests but not for PDMA requests. Apply the same logic in esp_do_dma() to do_dma_pdma_cb() so that extended messages terminated with a PDMA request are accumulated correctly. This allows the ESP device to respond correctly to the SDTR negotiation initiated by the NetBSD ESP driver without causing errors and timeouts on boot. Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Message-Id: <20210519100803.10293-6-mark.cave-ayland@ilande.co.uk> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/scsi/esp.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 16e4b7ead6..3e6f4094fc 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -492,9 +492,26 @@ static void do_dma_pdma_cb(ESPState *s)
}
s->ti_size = 0;
- s->do_cmd = 0;
- do_cmd(s);
- esp_lower_drq(s);
+ if ((s->rregs[ESP_RSTAT] & 7) == STAT_CD) {
+ /* No command received */
+ if (s->cmdfifo_cdb_offset == fifo8_num_used(&s->cmdfifo)) {
+ return;
+ }
+
+ /* Command has been received */
+ s->do_cmd = 0;
+ do_cmd(s);
+ } else {
+ /*
+ * Extra message out bytes received: update cmdfifo_cdb_offset
+ * and then switch to commmand phase
+ */
+ s->cmdfifo_cdb_offset = fifo8_num_used(&s->cmdfifo);
+ s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
+ s->rregs[ESP_RSEQ] = SEQ_CD;
+ s->rregs[ESP_RINTR] |= INTR_BS;
+ esp_raise_irq(s);
+ }
return;
}