qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 42/42] esp: add support for unaligned accesses


From: Laurent Vivier
Subject: Re: [PATCH v2 42/42] esp: add support for unaligned accesses
Date: Wed, 3 Mar 2021 21:22:49 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.7.0

Le 09/02/2021 à 20:30, Mark Cave-Ayland a écrit :
> 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>
> ---
>  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 ae9e265a5d..d2d6366525 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;
> @@ -532,12 +543,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;
>          }
>  
> @@ -612,12 +629,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);
> @@ -1168,7 +1202,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);
>      }
>  }
> @@ -1191,7 +1225,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;
> 

Reviewed-by: Laurent Vivier <laurent@vivier.eu>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]