aboutsummaryrefslogtreecommitdiff
path: root/hw/fdc.c
diff options
context:
space:
mode:
authorHervé Poussineau <hpoussin@reactos.org>2012-02-06 22:29:02 +0100
committerKevin Wolf <kwolf@redhat.com>2012-02-29 12:48:46 +0100
commit08388273a3c4e895bf7e10f356f66c2363cfe90b (patch)
treed1315f7ac981656f4e23cb001348588da160a789 /hw/fdc.c
parentb55c952aea6de024bf1a06357b49367fba045443 (diff)
downloadqemu-08388273a3c4e895bf7e10f356f66c2363cfe90b.zip
qemu-08388273a3c4e895bf7e10f356f66c2363cfe90b.tar.gz
qemu-08388273a3c4e895bf7e10f356f66c2363cfe90b.tar.bz2
fdc: take side count into account
Floppies can be simple or double-sided. However, current code was only taking the common case into account (ie 2 sides). This repairs single-sided floppies, which where totally broken before this patch : for track > 0, wrong sector number was calculated, and data was read/written at wrong place on underlying device. Fortunately, only some 360 kB floppies are single-sided, so this bug was probably not seen much. Signed-off-by: Hervé Poussineau <hpoussin@reactos.org> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'hw/fdc.c')
-rw-r--r--hw/fdc.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/hw/fdc.c b/hw/fdc.c
index 38fad58..64e635a 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -95,16 +95,19 @@ static void fd_init(FDrive *drv)
drv->max_track = 0;
}
+#define NUM_SIDES(drv) ((drv)->flags & FDISK_DBL_SIDES ? 2 : 1)
+
static int fd_sector_calc(uint8_t head, uint8_t track, uint8_t sect,
- uint8_t last_sect)
+ uint8_t last_sect, uint8_t num_sides)
{
- return (((track * 2) + head) * last_sect) + sect - 1;
+ return (((track * num_sides) + head) * last_sect) + sect - 1;
}
/* Returns current position, in sectors, for given drive */
static int fd_sector(FDrive *drv)
{
- return fd_sector_calc(drv->head, drv->track, drv->sect, drv->last_sect);
+ return fd_sector_calc(drv->head, drv->track, drv->sect, drv->last_sect,
+ NUM_SIDES(drv));
}
/* Seek to a new position:
@@ -135,7 +138,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect,
drv->max_track, drv->last_sect);
return 3;
}
- sector = fd_sector_calc(head, track, sect, drv->last_sect);
+ sector = fd_sector_calc(head, track, sect, drv->last_sect, NUM_SIDES(drv));
ret = 0;
if (sector != fd_sector(drv)) {
#if 0
@@ -1019,7 +1022,8 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
ks = fdctrl->fifo[4];
FLOPPY_DPRINTF("Start transfer at %d %d %02x %02x (%d)\n",
GET_CUR_DRV(fdctrl), kh, kt, ks,
- fd_sector_calc(kh, kt, ks, cur_drv->last_sect));
+ fd_sector_calc(kh, kt, ks, cur_drv->last_sect,
+ NUM_SIDES(cur_drv)));
switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) {
case 2:
/* sect too big */
@@ -1289,7 +1293,8 @@ static void fdctrl_format_sector(FDCtrl *fdctrl)
ks = fdctrl->fifo[8];
FLOPPY_DPRINTF("format sector at %d %d %02x %02x (%d)\n",
GET_CUR_DRV(fdctrl), kh, kt, ks,
- fd_sector_calc(kh, kt, ks, cur_drv->last_sect));
+ fd_sector_calc(kh, kt, ks, cur_drv->last_sect,
+ NUM_SIDES(cur_drv)));
switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) {
case 2:
/* sect too big */