[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 84/88] esp.c: implement DMA Transfer Pad command for DATA phases
|
From: |
Mark Cave-Ayland |
|
Subject: |
[PATCH 84/88] esp.c: implement DMA Transfer Pad command for DATA phases |
|
Date: |
Fri, 12 Jan 2024 12:54:16 +0000 |
The Transfer Pad command is used to either drop incoming FIFO data during the
DATA IN phase or generate a series of zero bytes in the FIFO during the DATA
OUT phase.
Implement the DMA Transfer Pad command for the DATA phases which is used by
the NeXTCube firmware in the DATA IN phase to ignore part of the incoming SCSI
data as it is copied into memory.
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
---
hw/scsi/esp.c | 97 ++++++++++++++++++++++++++++++++++++---------------
1 file changed, 69 insertions(+), 28 deletions(-)
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 73379a3c65..5583b3eb56 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -387,6 +387,15 @@ static void handle_satn_stop(ESPState *s)
}
}
+static void handle_pad(ESPState *s)
+{
+ if (s->dma) {
+ esp_do_dma(s);
+ } else {
+ esp_do_nodma(s);
+ }
+}
+
static void write_response(ESPState *s)
{
trace_esp_write_response(s->status);
@@ -518,20 +527,38 @@ static void esp_do_dma(ESPState *s)
len = s->async_len;
}
- if (s->dma_memory_read) {
- s->dma_memory_read(s->dma_opaque, s->async_buf, len);
- esp_set_tc(s, esp_get_tc(s) - len);
- } else {
- /* Copy FIFO data to device */
- len = MIN(s->async_len, ESP_FIFO_SZ);
- len = MIN(len, fifo8_num_used(&s->fifo));
- len = esp_fifo_pop_buf(&s->fifo, s->async_buf, len);
- esp_raise_drq(s);
- }
+ switch (s->rregs[ESP_CMD]) {
+ case CMD_TI | CMD_DMA:
+ if (s->dma_memory_read) {
+ s->dma_memory_read(s->dma_opaque, s->async_buf, len);
+ esp_set_tc(s, esp_get_tc(s) - len);
+ } else {
+ /* Copy FIFO data to device */
+ len = MIN(s->async_len, ESP_FIFO_SZ);
+ len = MIN(len, fifo8_num_used(&s->fifo));
+ len = esp_fifo_pop_buf(&s->fifo, s->async_buf, len);
+ esp_raise_drq(s);
+ }
- s->async_buf += len;
- s->async_len -= len;
- s->ti_size += len;
+ s->async_buf += len;
+ s->async_len -= len;
+ s->ti_size += len;
+ break;
+
+ case CMD_PAD | CMD_DMA:
+ /* Copy TC zero bytes into the incoming stream */
+ if (!s->dma_memory_read) {
+ len = MIN(s->async_len, ESP_FIFO_SZ);
+ len = MIN(len, fifo8_num_free(&s->fifo));
+ }
+
+ memset(s->async_buf, 0, len);
+
+ s->async_buf += len;
+ s->async_len -= len;
+ s->ti_size += len;
+ break;
+ }
if (s->async_len == 0 && fifo8_num_used(&s->fifo) < 2) {
/* Defer until the scsi layer has completed */
@@ -554,19 +581,35 @@ static void esp_do_dma(ESPState *s)
len = s->async_len;
}
- if (s->dma_memory_write) {
- s->dma_memory_write(s->dma_opaque, s->async_buf, len);
- } else {
- /* Copy device data to FIFO */
- len = MIN(len, fifo8_num_free(&s->fifo));
- fifo8_push_all(&s->fifo, s->async_buf, len);
- esp_raise_drq(s);
- }
+ switch (s->rregs[ESP_CMD]) {
+ case CMD_TI | CMD_DMA:
+ if (s->dma_memory_write) {
+ s->dma_memory_write(s->dma_opaque, s->async_buf, len);
+ } else {
+ /* Copy device data to FIFO */
+ len = MIN(len, fifo8_num_free(&s->fifo));
+ fifo8_push_all(&s->fifo, s->async_buf, len);
+ esp_raise_drq(s);
+ }
+
+ s->async_buf += len;
+ s->async_len -= len;
+ s->ti_size -= len;
+ esp_set_tc(s, esp_get_tc(s) - len);
+ break;
+
+ case CMD_PAD | CMD_DMA:
+ /* Drop TC bytes from the incoming stream */
+ if (!s->dma_memory_write) {
+ len = MIN(len, fifo8_num_free(&s->fifo));
+ }
- s->async_buf += len;
- s->async_len -= len;
- s->ti_size -= len;
- esp_set_tc(s, esp_get_tc(s) - len);
+ s->async_buf += len;
+ s->async_len -= len;
+ s->ti_size -= len;
+ esp_set_tc(s, esp_get_tc(s) - len);
+ break;
+ }
if (s->async_len == 0 && s->ti_size == 0 && esp_get_tc(s)) {
/* If the guest underflows TC then terminate SCSI request */
@@ -1087,9 +1130,7 @@ static void esp_run_cmd(ESPState *s)
break;
case CMD_PAD:
trace_esp_mem_writeb_cmd_pad(cmd);
- s->rregs[ESP_RSTAT] = STAT_TC;
- s->rregs[ESP_RINTR] |= INTR_FC;
- s->rregs[ESP_RSEQ] = 0;
+ handle_pad(s);
break;
case CMD_SATN:
trace_esp_mem_writeb_cmd_satn(cmd);
--
2.39.2
- [PATCH 79/88] esp.c: consolidate DMA and PDMA logic in DATA IN phase, (continued)
- [PATCH 79/88] esp.c: consolidate DMA and PDMA logic in DATA IN phase, Mark Cave-Ayland, 2024/01/12
- [PATCH 71/88] esp.c: don't clear the SCSI phase when reading ESP_RINTR, Mark Cave-Ayland, 2024/01/12
- [PATCH 55/88] esp.c: always use esp_do_dma() in pdma_cb(), Mark Cave-Ayland, 2024/01/12
- [PATCH 70/88] esp.c: ensure that STAT_INT is cleared when reading ESP_RINTR, Mark Cave-Ayland, 2024/01/12
- [PATCH 80/88] esp.c: consolidate DMA and PDMA logic in MESSAGE OUT phase, Mark Cave-Ayland, 2024/01/12
- [PATCH 51/88] esp.c: don't use get_cmd() for CMD_SEL DMA commands, Mark Cave-Ayland, 2024/01/12
- [PATCH 65/88] esp.c: move non-DMA TI logic to separate esp_nodma_ti_dataout() function, Mark Cave-Ayland, 2024/01/12
- [PATCH 78/88] esp.c: consolidate DMA and PDMA logic in DATA OUT phase, Mark Cave-Ayland, 2024/01/12
- [PATCH 59/88] esp.c: separate logic based upon ESP command in esp_transfer_data(), Mark Cave-Ayland, 2024/01/12
- [PATCH 73/88] esp.c: remove restriction on FIFO read access when DMA memory routines defined, Mark Cave-Ayland, 2024/01/12
- [PATCH 84/88] esp.c: implement DMA Transfer Pad command for DATA phases,
Mark Cave-Ayland <=
- [PATCH 53/88] esp.c: replace do_dma_pdma_cb() with esp_do_dma(), Mark Cave-Ayland, 2024/01/12
- [PATCH 58/88] esp.c: separate logic based upon ESP command in esp_command_complete(), Mark Cave-Ayland, 2024/01/12
- [PATCH 61/88] esp.c: remove DATA IN phase logic when reading from FIFO, Mark Cave-Ayland, 2024/01/12
- [PATCH 77/88] esp.c: only transfer non-DMA MESSAGE OUT phase data for specific commands, Mark Cave-Ayland, 2024/01/12
- [PATCH 62/88] esp.c: zero command register when TI command terminates due to phase change, Mark Cave-Ayland, 2024/01/12
- [PATCH 63/88] esp.c: remove unneeded ti_cmd field, Mark Cave-Ayland, 2024/01/12
- [PATCH 82/88] esp.c: consolidate DMA and PDMA logic in STATUS and MESSAGE IN phases, Mark Cave-Ayland, 2024/01/12
- [PATCH 69/88] esp.c: consolidate end of command sequence after ICCS command, Mark Cave-Ayland, 2024/01/12
- [PATCH 52/88] esp.c: move CMD_SELATNS end of command logic to esp_do_dma() and do_dma_pdma_cb(), Mark Cave-Ayland, 2024/01/12
- [PATCH 68/88] esp.c: move write_response() non-DMA logic to esp_do_nodma(), Mark Cave-Ayland, 2024/01/12