qemu-devel
[Top][All Lists]
Advanced

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

Re: [PATCH v2 27/42] esp: fix PDMA target selection


From: Laurent Vivier
Subject: Re: [PATCH v2 27/42] esp: fix PDMA target selection
Date: Tue, 2 Mar 2021 22:57:42 +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 :
> Currently the target selection for PDMA is done after the SCSI command has 
> been
> delivered which is not correct. Perform target selection as part of the 
> initial
> get_cmd() call when the command is submitted: if no target is present, don't
> raise DRQ.
> 
> If the target is present then switch to the command phase since the MacOS 
> toolbox
> ROM checks for this before attempting to submit the SCSI command.
> 
> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
> ---
>  hw/scsi/esp.c | 53 +++++++++++++++++++++++++++++++++------------------
>  1 file changed, 34 insertions(+), 19 deletions(-)
> 
> diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
> index 6736e7142c..b7ab5a5592 100644
> --- a/hw/scsi/esp.c
> +++ b/hw/scsi/esp.c
> @@ -243,6 +243,9 @@ static uint32_t get_cmd(ESPState *s)
>              s->dma_memory_read(s->dma_opaque, buf, dmalen);
>          } else {
>              set_pdma(s, TI);
> +            if (esp_select(s) < 0) {
> +                return -1;
> +            }
>              esp_raise_drq(s);
>              return 0;
>          }
> @@ -257,7 +260,7 @@ static uint32_t get_cmd(ESPState *s)
>      trace_esp_get_cmd(dmalen, target);
>  
>      if (esp_select(s) < 0) {
> -        return 0;
> +        return -1;
>      }
>      return dmalen;
>  }
> @@ -299,9 +302,6 @@ static void do_cmd(ESPState *s)
>  
>  static void satn_pdma_cb(ESPState *s)
>  {
> -    if (esp_select(s) < 0) {
> -        return;
> -    }
>      s->do_cmd = 0;
>      if (s->cmdlen) {
>          do_cmd(s);
> @@ -310,24 +310,28 @@ static void satn_pdma_cb(ESPState *s)
>  
>  static void handle_satn(ESPState *s)
>  {
> +    int32_t cmdlen;
> +
>      if (s->dma && !s->dma_enabled) {
>          s->dma_cb = handle_satn;
>          return;
>      }
>      s->pdma_cb = satn_pdma_cb;
> -    s->cmdlen = get_cmd(s);
> -    if (s->cmdlen) {
> +    cmdlen = get_cmd(s);
> +    if (cmdlen > 0) {
> +        s->cmdlen = cmdlen;
>          do_cmd(s);
> -    } else {
> +    } else if (cmdlen == 0) {
> +        s->cmdlen = 0;
>          s->do_cmd = 1;
> +        /* Target present, but no cmd yet - switch to command phase */
> +        s->rregs[ESP_RSEQ] = SEQ_CD;
> +        s->rregs[ESP_RSTAT] = STAT_CD;
>      }
>  }
>  
>  static void s_without_satn_pdma_cb(ESPState *s)
>  {
> -    if (esp_select(s) < 0) {
> -        return;
> -    }
>      s->do_cmd = 0;
>      if (s->cmdlen) {
>          do_busid_cmd(s, s->cmdbuf, 0);
> @@ -336,24 +340,28 @@ static void s_without_satn_pdma_cb(ESPState *s)
>  
>  static void handle_s_without_atn(ESPState *s)
>  {
> +    int32_t cmdlen;
> +
>      if (s->dma && !s->dma_enabled) {
>          s->dma_cb = handle_s_without_atn;
>          return;
>      }
>      s->pdma_cb = s_without_satn_pdma_cb;
> -    s->cmdlen = get_cmd(s);
> -    if (s->cmdlen) {
> +    cmdlen = get_cmd(s);
> +    if (cmdlen > 0) {
> +        s->cmdlen = cmdlen;
>          do_busid_cmd(s, s->cmdbuf, 0);
> -    } else {
> +    } else if (cmdlen == 0) {
> +        s->cmdlen = 0;
>          s->do_cmd = 1;
> +        /* Target present, but no cmd yet - switch to command phase */
> +        s->rregs[ESP_RSEQ] = SEQ_CD;
> +        s->rregs[ESP_RSTAT] = STAT_CD;
>      }
>  }
>  
>  static void satn_stop_pdma_cb(ESPState *s)
>  {
> -    if (esp_select(s) < 0) {
> -        return;
> -    }
>      s->do_cmd = 0;
>      if (s->cmdlen) {
>          trace_esp_handle_satn_stop(s->cmdlen);
> @@ -367,21 +375,28 @@ static void satn_stop_pdma_cb(ESPState *s)
>  
>  static void handle_satn_stop(ESPState *s)
>  {
> +    int32_t cmdlen;
> +
>      if (s->dma && !s->dma_enabled) {
>          s->dma_cb = handle_satn_stop;
>          return;
>      }
>      s->pdma_cb = satn_stop_pdma_cb;
> -    s->cmdlen = get_cmd(s);
> -    if (s->cmdlen) {
> +    cmdlen = get_cmd(s);
> +    if (cmdlen > 0) {
>          trace_esp_handle_satn_stop(s->cmdlen);
> +        s->cmdlen = cmdlen;
>          s->do_cmd = 1;
>          s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
>          s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
>          s->rregs[ESP_RSEQ] = SEQ_CD;
>          esp_raise_irq(s);
> -    } else {
> +    } else if (cmdlen == 0) {
> +        s->cmdlen = 0;
>          s->do_cmd = 1;
> +        /* Target present, but no cmd yet - switch to command phase */
> +        s->rregs[ESP_RSEQ] = SEQ_CD;
> +        s->rregs[ESP_RSTAT] = STAT_CD;
>      }
>  }
>  
> 

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



reply via email to

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