Every other command handler begins by latching the drive from the command
byte:
SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
fdctrl_handle_readid() does not, so it works on whichever drive happened to
be selected last. A guest that issues READ ID for a drive other than the
one currently selected gets an answer about the wrong one.
It has gone unnoticed because a driver normally writes the DOR to spin up
the motor first, and that write selects the drive as a side effect. The
controller does not require it, though, and the command carries the drive
number for a reason.
Reported-by: Kevin Wolf <[email protected]>
Signed-off-by: Christian Quante <[email protected]>
---
hw/block/fdc.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index 2c1681b7d0..9b2409cfa4 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -1936,7 +1936,10 @@ static void fdctrl_handle_save(FDCtrl *fdctrl, int
direction)
static void fdctrl_handle_readid(FDCtrl *fdctrl, int direction)
{
- FDrive *cur_drv = get_cur_drv(fdctrl);
+ FDrive *cur_drv;
+
+ SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
+ cur_drv = get_cur_drv(fdctrl);
cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
timer_mod(fdctrl->result_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
--
2.53.0