[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 42/42] esp: add support for unaligned accesses
From: |
Mark Cave-Ayland |
Subject: |
[PULL 42/42] esp: add support for unaligned accesses |
Date: |
Sun, 7 Mar 2021 12:08:50 +0000 |
When the MacOS toolbox ROM transfers data from a target device to an unaligned
memory address, the first/last byte of a 16-bit transfer needs to be handled
separately. This means that the first byte is preloaded into the FIFO before
the transfer, or the last byte remains in the FIFO after the transfer.
The result of this is that the PDMA routines must be updated so that the FIFO
is loaded/unloaded if the last 16-bit word is used (rather than the last byte)
and any remaining byte from a FIFO wraparound is handled correctly.
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20210304221103.6369-43-mark.cave-ayland@ilande.co.uk>
---
hw/scsi/esp.c | 48 +++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 41 insertions(+), 7 deletions(-)
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index f828e70865..507ab363bc 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -498,11 +498,22 @@ static void do_dma_pdma_cb(ESPState *s)
if (to_device) {
/* Copy FIFO data to device */
- len = MIN(fifo8_num_used(&s->fifo), ESP_FIFO_SZ);
+ len = MIN(s->async_len, ESP_FIFO_SZ);
+ len = MIN(len, fifo8_num_used(&s->fifo));
memcpy(s->async_buf, fifo8_pop_buf(&s->fifo, len, &n), len);
- s->async_buf += len;
- s->async_len -= len;
- s->ti_size += len;
+ s->async_buf += n;
+ s->async_len -= n;
+ s->ti_size += n;
+
+ if (n < len) {
+ /* Unaligned accesses can cause FIFO wraparound */
+ len = len - n;
+ memcpy(s->async_buf, fifo8_pop_buf(&s->fifo, len, &n), len);
+ s->async_buf += n;
+ s->async_len -= n;
+ s->ti_size += n;
+ }
+
if (s->async_len == 0) {
scsi_req_continue(s->current_req);
return;
@@ -526,12 +537,18 @@ static void do_dma_pdma_cb(ESPState *s)
if (esp_get_tc(s) != 0) {
/* Copy device data to FIFO */
- len = MIN(s->async_len, fifo8_num_free(&s->fifo));
+ len = MIN(s->async_len, esp_get_tc(s));
+ len = MIN(len, fifo8_num_free(&s->fifo));
fifo8_push_all(&s->fifo, s->async_buf, len);
s->async_buf += len;
s->async_len -= len;
s->ti_size -= len;
esp_set_tc(s, esp_get_tc(s) - len);
+
+ if (esp_get_tc(s) == 0) {
+ /* Indicate transfer to FIFO is complete */
+ s->rregs[ESP_RSTAT] |= STAT_TC;
+ }
return;
}
@@ -606,12 +623,29 @@ static void esp_do_dma(ESPState *s)
if (s->dma_memory_write) {
s->dma_memory_write(s->dma_opaque, s->async_buf, len);
} else {
+ /* Adjust TC for any leftover data in the FIFO */
+ if (!fifo8_is_empty(&s->fifo)) {
+ esp_set_tc(s, esp_get_tc(s) - fifo8_num_used(&s->fifo));
+ }
+
/* Copy device data to FIFO */
len = MIN(len, fifo8_num_free(&s->fifo));
fifo8_push_all(&s->fifo, s->async_buf, len);
s->async_buf += len;
s->async_len -= len;
s->ti_size -= len;
+
+ /*
+ * MacOS toolbox uses a TI length of 16 bytes for all commands, so
+ * commands shorter than this must be padded accordingly
+ */
+ if (len < esp_get_tc(s) && esp_get_tc(s) <= ESP_FIFO_SZ) {
+ while (fifo8_num_used(&s->fifo) < ESP_FIFO_SZ) {
+ esp_fifo_push(s, 0);
+ len++;
+ }
+ }
+
esp_set_tc(s, esp_get_tc(s) - len);
s->pdma_cb = do_dma_pdma_cb;
esp_raise_drq(s);
@@ -1160,7 +1194,7 @@ static void sysbus_esp_pdma_write(void *opaque, hwaddr
addr,
break;
}
dmalen = esp_get_tc(s);
- if (dmalen == 0 || fifo8_is_full(&s->fifo)) {
+ if (dmalen == 0 || fifo8_num_free(&s->fifo) < 2) {
s->pdma_cb(s);
}
}
@@ -1183,7 +1217,7 @@ static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr
addr,
val = (val << 8) | esp_pdma_read(s);
break;
}
- if (fifo8_is_empty(&s->fifo)) {
+ if (fifo8_num_used(&s->fifo) < 2) {
s->pdma_cb(s);
}
return val;
--
2.20.1
- [PULL 32/42] esp: latch individual bits in ESP_RINTR register, (continued)
- [PULL 32/42] esp: latch individual bits in ESP_RINTR register, Mark Cave-Ayland, 2021/03/07
- [PULL 33/42] esp: defer command completion interrupt on incoming data transfers, Mark Cave-Ayland, 2021/03/07
- [PULL 34/42] esp: remove old deferred command completion mechanism, Mark Cave-Ayland, 2021/03/07
- [PULL 35/42] esp: raise interrupt after every non-DMA byte transferred to the FIFO, Mark Cave-Ayland, 2021/03/07
- [PULL 36/42] esp: add maxlen parameter to get_cmd(), Mark Cave-Ayland, 2021/03/07
- [PULL 37/42] esp: transition to message out phase after SATN and stop command, Mark Cave-Ayland, 2021/03/07
- [PULL 38/42] esp: convert ti_buf from array to Fifo8, Mark Cave-Ayland, 2021/03/07
- [PULL 39/42] esp: convert cmdbuf from array to Fifo8, Mark Cave-Ayland, 2021/03/07
- [PULL 40/42] esp: add trivial implementation of the ESP_RFLAGS register, Mark Cave-Ayland, 2021/03/07
- [PULL 41/42] esp: implement non-DMA transfers in PDMA mode, Mark Cave-Ayland, 2021/03/07
- [PULL 42/42] esp: add support for unaligned accesses,
Mark Cave-Ayland <=
- Re: [PULL 00/42] qemu-sparc queue 20210307, Peter Maydell, 2021/03/09