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


Reply via email to