[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 3/4] fdc: rewrite seek and DSKCHG bit handling
From: |
Pavel Hrdina |
Subject: |
[Qemu-devel] [PATCH v3 3/4] fdc: rewrite seek and DSKCHG bit handling |
Date: |
Tue, 12 Jun 2012 13:19:36 +0200 |
This bit is cleared on every successful seek to a different track (cylinder).
The seek is also called on revalidate or on read/write/format commands which
also clear the DSKCHG bit.
Signed-off-by: Pavel Hrdina <address@hidden>
---
hw/fdc.c | 66 ++++++++++++++++++++++++++++++-------------------------------
1 files changed, 32 insertions(+), 34 deletions(-)
diff --git a/hw/fdc.c b/hw/fdc.c
index 096aefc..b658504 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -153,8 +153,11 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t
track, uint8_t sect,
}
#endif
drv->head = head;
- if (drv->track != track)
+ if (drv->track != track) {
ret = 1;
+ if (drv->bs != NULL && bdrv_is_inserted(drv->bs))
+ drv->media_changed = 0;
+ }
drv->track = track;
drv->sect = sect;
}
@@ -169,9 +172,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t
track, uint8_t sect,
static void fd_recalibrate(FDrive *drv)
{
FLOPPY_DPRINTF("recalibrate\n");
- drv->head = 0;
- drv->track = 0;
- drv->sect = 1;
+ fd_seek(drv, 0, 0, 1, 1);
}
/* Revalidate a disk drive after a disk change */
@@ -710,14 +711,6 @@ static void fdctrl_raise_irq(FDCtrl *fdctrl, uint8_t
status0)
qemu_set_irq(fdctrl->irq, 1);
fdctrl->sra |= FD_SRA_INTPEND;
}
- if (status0 & FD_SR0_SEEK) {
- FDrive *cur_drv;
- /* A seek clears the disk change line (if a disk is inserted) */
- cur_drv = get_cur_drv(fdctrl);
- if (cur_drv->bs != NULL && bdrv_is_inserted(cur_drv->bs)) {
- cur_drv->media_changed = 0;
- }
- }
fdctrl->reset_sensei = 0;
fdctrl->status0 = status0;
@@ -1003,30 +996,39 @@ static int fdctrl_seek_to_next_sect(FDCtrl *fdctrl,
FDrive *cur_drv)
fd_sector(cur_drv));
/* XXX: cur_drv->sect >= cur_drv->last_sect should be an
error in fact */
- if (cur_drv->sect >= cur_drv->last_sect ||
- cur_drv->sect == fdctrl->eot) {
- cur_drv->sect = 1;
+ uint8_t new_head = cur_drv->head;
+ uint8_t new_track = cur_drv->track;
+ uint8_t new_sect = cur_drv->sect;
+
+ int ret = 1;
+
+ if (new_sect >= cur_drv->last_sect ||
+ new_sect == fdctrl->eot) {
+ new_sect = 1;
if (FD_MULTI_TRACK(fdctrl->data_state)) {
- if (cur_drv->head == 0 &&
+ if (new_head == 0 &&
(cur_drv->flags & FDISK_DBL_SIDES) != 0) {
- cur_drv->head = 1;
+ new_head = 1;
} else {
- cur_drv->head = 0;
- cur_drv->track++;
+ new_head = 0;
+ new_track++;
if ((cur_drv->flags & FDISK_DBL_SIDES) == 0)
- return 0;
+ ret = 0;
}
} else {
- cur_drv->track++;
- return 0;
+ new_track++;
+ ret = 0;
}
- FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",
+ if (ret == 1) {
+ FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",
cur_drv->head, cur_drv->track,
cur_drv->sect, fd_sector(cur_drv));
+ }
} else {
- cur_drv->sect++;
+ new_sect++;
}
- return 1;
+ fd_seek(cur_drv, new_head, new_track, new_sect, 1);
+ return ret;
}
/* Callback for transfer end (stop or abort) */
@@ -1622,11 +1624,7 @@ static void fdctrl_handle_seek(FDCtrl *fdctrl, int
direction)
/* The seek command just sends step pulses to the drive and doesn't care if
* there is a medium inserted of if it's banging the head against the
drive.
*/
- if (fdctrl->fifo[2] > cur_drv->max_track) {
- cur_drv->track = cur_drv->max_track;
- } else {
- cur_drv->track = fdctrl->fifo[2];
- }
+ fd_seek(cur_drv, cur_drv->head, fdctrl->fifo[2], cur_drv->sect, 1);
/* Raise Interrupt */
fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
}
@@ -1691,9 +1689,9 @@ static void fdctrl_handle_relative_seek_out(FDCtrl
*fdctrl, int direction)
SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
cur_drv = get_cur_drv(fdctrl);
if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) {
- cur_drv->track = cur_drv->max_track - 1;
+ fd_seek(cur_drv, cur_drv->head, cur_drv->max_track - 1, cur_drv->sect,
1);
} else {
- cur_drv->track += fdctrl->fifo[2];
+ fd_seek(cur_drv, cur_drv->head, fdctrl->fifo[2], cur_drv->sect, 1);
}
fdctrl_reset_fifo(fdctrl);
/* Raise Interrupt */
@@ -1707,9 +1705,9 @@ static void fdctrl_handle_relative_seek_in(FDCtrl
*fdctrl, int direction)
SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
cur_drv = get_cur_drv(fdctrl);
if (fdctrl->fifo[2] > cur_drv->track) {
- cur_drv->track = 0;
+ fd_seek(cur_drv, cur_drv->head, 0, cur_drv->sect, 1);
} else {
- cur_drv->track -= fdctrl->fifo[2];
+ fd_seek(cur_drv, cur_drv->head, fdctrl->fifo[2], cur_drv->sect, 1);
}
fdctrl_reset_fifo(fdctrl);
/* Raise Interrupt */
--
1.7.7.6