diff options
author | Pavel Hrdina <phrdina@redhat.com> | 2012-06-22 12:33:55 +0200 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2012-07-09 15:53:03 +0200 |
commit | 2fee00885a9ea4db69bbfc1ba8ccf95f2ae9aec6 (patch) | |
tree | a9885b86d8172cb4c6294e8cf4adf15be57595b8 /hw | |
parent | 6be01b1e0b14ad4809c9aec273c6109b91d2df1c (diff) | |
download | qemu-2fee00885a9ea4db69bbfc1ba8ccf95f2ae9aec6.tar.gz qemu-2fee00885a9ea4db69bbfc1ba8ccf95f2ae9aec6.tar.bz2 qemu-2fee00885a9ea4db69bbfc1ba8ccf95f2ae9aec6.zip |
fdc: fix interrupt handling
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 <phrdina@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/fdc.c | 34 |
1 files changed, 21 insertions, 13 deletions
@@ -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); + } } /* 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); } fdctrl->fifo[1] = cur_drv->track; |