qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH v6 4/6] fdc: fix interrupt handling


From: Kevin Wolf
Subject: Re: [Qemu-devel] [PATCH v6 4/6] fdc: fix interrupt handling
Date: Mon, 25 Jun 2012 14:41:57 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20120430 Thunderbird/12.0.1

Am 22.06.2012 12:33, schrieb Pavel Hrdina:
> If you call the SENSE INTERRUPT STATUS command while there is no interrupt
> waiting you get as result unknown command.
> 
> Fixed status0 register handling for read/write/format commands.
> 
> Signed-off-by: Pavel Hrdina <address@hidden>
> ---
>  hw/fdc.c |   34 +++++++++++++++++++++-------------
>  1 files changed, 21 insertions(+), 13 deletions(-)
> 
> diff --git a/hw/fdc.c b/hw/fdc.c
> index 0270264..e28841c 100644
> --- a/hw/fdc.c
> +++ b/hw/fdc.c
> @@ -307,6 +307,9 @@ enum {
>  };
>  
>  enum {
> +    FD_SR0_DS0      = 0x01,
> +    FD_SR0_DS1      = 0x02,
> +    FD_SR0_HEAD     = 0x04,
>      FD_SR0_EQPMT    = 0x10,
>      FD_SR0_SEEK     = 0x20,
>      FD_SR0_ABNTERM  = 0x40,
> @@ -972,14 +975,15 @@ static void fdctrl_reset_fifo(FDCtrl *fdctrl)
>  }
>  
>  /* Set FIFO status for the host to read */
> -static void fdctrl_set_fifo(FDCtrl *fdctrl, int fifo_len, int do_irq)
> +static void fdctrl_set_fifo(FDCtrl *fdctrl, int fifo_len, uint8_t status0)
>  {
>      fdctrl->data_dir = FD_DIR_READ;
>      fdctrl->data_len = fifo_len;
>      fdctrl->data_pos = 0;
>      fdctrl->msr |= FD_MSR_CMDBUSY | FD_MSR_RQM | FD_MSR_DIO;
> -    if (do_irq)
> -        fdctrl_raise_irq(fdctrl, 0x00);
> +    if (status0) {
> +        fdctrl_raise_irq(fdctrl, status0);
> +    }

Is status0 != 0 the real condition or is it just what we have here and
what happens to give the right result with our implementation?

>  }
>  
>  /* Set an error: unimplemented/unknown command */
> @@ -1044,10 +1048,12 @@ static void fdctrl_stop_transfer(FDCtrl *fdctrl, 
> uint8_t status0,
>      FDrive *cur_drv;
>  
>      cur_drv = get_cur_drv(fdctrl);
> +    fdctrl->status0 = status0 | FD_SR0_SEEK | (cur_drv->head << 2) |
> +                      GET_CUR_DRV(fdctrl);
> +
>      FLOPPY_DPRINTF("transfer status: %02x %02x %02x (%02x)\n",
> -                   status0, status1, status2,
> -                   status0 | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl));
> -    fdctrl->fifo[0] = status0 | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
> +                   status0, status1, status2, fdctrl->status0);
> +    fdctrl->fifo[0] = fdctrl->status0;
>      fdctrl->fifo[1] = status1;
>      fdctrl->fifo[2] = status2;
>      fdctrl->fifo[3] = cur_drv->track;
> @@ -1060,7 +1066,7 @@ static void fdctrl_stop_transfer(FDCtrl *fdctrl, 
> uint8_t status0,
>      }
>      fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
>      fdctrl->msr &= ~FD_MSR_NONDMA;
> -    fdctrl_set_fifo(fdctrl, 7, 1);
> +    fdctrl_set_fifo(fdctrl, 7, fdctrl->status0);
>  }
>  
>  /* Prepare a data transfer (either DMA or FIFO) */
> @@ -1175,7 +1181,7 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int 
> direction)
>      if (direction != FD_DIR_WRITE)
>          fdctrl->msr |= FD_MSR_DIO;
>      /* IO based transfer: calculate len */
> -    fdctrl_raise_irq(fdctrl, 0x00);
> +    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
>  
>      return;
>  }
> @@ -1604,16 +1610,18 @@ static void 
> fdctrl_handle_sense_interrupt_status(FDCtrl *fdctrl, int direction)
>  {
>      FDrive *cur_drv = get_cur_drv(fdctrl);
>  
> -    if(fdctrl->reset_sensei > 0) {
> +    if (fdctrl->reset_sensei > 0) {
>          fdctrl->fifo[0] =
>              FD_SR0_RDYCHG + FD_RESET_SENSEI_COUNT - fdctrl->reset_sensei;
>          fdctrl->reset_sensei--;
> +    } else if (!(fdctrl->sra & FD_SRA_INTPEND)) {
> +        fdctrl->fifo[0] = FD_SR0_INVCMD;
> +        fdctrl_set_fifo(fdctrl, 1, 0);
> +        return;
>      } else {
> -        /* XXX: status0 handling is broken for read/write
> -           commands, so we do this hack. It should be suppressed
> -           ASAP */
>          fdctrl->fifo[0] =
> -            FD_SR0_SEEK | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
> +                (fdctrl->status0 & ~(FD_SR0_HEAD | FD_SR0_DS1 | FD_SR0_DS0))
> +                | GET_CUR_DRV(fdctrl);

Why isn't fdctrl->status0 already right?

In any case, I think if you're masking out the head number from status0,
you need to or it back, even if from a different source.

Kevin



reply via email to

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