diff mbox

[v3,4/4] fdc: fix interrupt handling

Message ID 83fb3a579f13cec8bd6a62a486911627f36e7185.1339499796.git.phrdina@redhat.com
State New
Headers show

Commit Message

Pavel Hrdina June 12, 2012, 11:19 a.m. UTC
If you call the SENSE INTERRUPT STATUS commad while there is no interrupt
waiting you get as reasult unknown command.

Fixed status0 register handling for read/write/format commands.

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
 hw/fdc.c |   30 ++++++++++++++++--------------
 1 files changed, 16 insertions(+), 14 deletions(-)

Comments

Paolo Bonzini June 12, 2012, 12:59 p.m. UTC | #1
Il 12/06/2012 13:19, Pavel Hrdina ha scritto:
>      } 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->fifo[0] = (fdctrl->status0 & ~FD_SR0_HEAD) | GET_CUR_DRV(fdctrl);

Should bit 0 be cleared also, before ORing GET_CUR_DRV(fdctrl)?

Paolo
Pavel Hrdina June 13, 2012, 11:43 a.m. UTC | #2
On 06/12/2012 02:59 PM, Paolo Bonzini wrote:
> Il 12/06/2012 13:19, Pavel Hrdina ha scritto:
>>       } 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->fifo[0] = (fdctrl->status0&  ~FD_SR0_HEAD) | GET_CUR_DRV(fdctrl);
> Should bit 0 be cleared also, before ORing GET_CUR_DRV(fdctrl)?
>
> Paolo
According to the code bits 0 and 1 don't have to be cleared, but it 
would be probably better clear them too. Good point.

Pavel
diff mbox

Patch

diff --git a/hw/fdc.c b/hw/fdc.c
index b658504..1bc90c9 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -305,6 +305,7 @@  enum {
 };
 
 enum {
+    FD_SR0_HEAD     = 0x04,
     FD_SR0_EQPMT    = 0x10,
     FD_SR0_SEEK     = 0x20,
     FD_SR0_ABNTERM  = 0x40,
@@ -970,14 +971,14 @@  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);
 }
 
 /* Set an error: unimplemented/unknown command */
@@ -1038,10 +1039,11 @@  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;
@@ -1054,7 +1056,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) */
@@ -1168,7 +1170,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;
 }
@@ -1596,16 +1598,16 @@  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->fifo[0] = (fdctrl->status0 & ~FD_SR0_HEAD) | GET_CUR_DRV(fdctrl);
     }
 
     fdctrl->fifo[1] = cur_drv->track;