When using host drive (e.g., /dev/fd0) qemu does not detect physical drive if 
it is empty. This causes a Windows guest, specifically w2k, to drop the 
floppy drive altogether at start-up.

The need to see the disk image before determining the emulated drive type 
makes sense for images, but not much for a host drive. The attached patch 
short-circuits the initialization process to allow host drive types to reach 
the emulated controller hardware. It has been tested and works for W98, W2k, 
and Linux guest images.

diff -Naur qemu-0.9.0/block-raw.c qemu-0.9.0-flpy2/block-raw.c
--- qemu-0.9.0/block-raw.c	2007-02-05 15:01:54.000000000 -0800
+++ qemu-0.9.0-flpy2/block-raw.c	2007-02-13 05:14:49.000000000 -0800
@@ -75,11 +75,17 @@
     int fd_open_flags;
     int64_t fd_open_time;
     int64_t fd_error_time;
-    int fd_got_error;
-    int fd_media_changed;
+    int fd_got_error:1;
+    int fd_media_changed:1;
+    int fd_have_probe:1;
+    int fd_drive_type:4;
 #endif
 } BDRVRawState;
 
+#if defined(__linux__) && !defined(QEMU_TOOL)
+extern int *global_floppy_hack_ptr;
+#endif
+
 static int fd_open(BlockDriverState *bs);
 
 static int raw_open(BlockDriverState *bs, const char *filename, int flags)
@@ -556,6 +562,9 @@
 {
     BDRVRawState *s = bs->opaque;
     int fd, open_flags, ret;
+#if defined(__linux__)
+    struct floppy_drive_params drive_info;
+#endif
 
 #ifdef CONFIG_COCOA
     if (strstart(filename, "/dev/cdrom", NULL)) {
@@ -593,6 +602,9 @@
 
     s->type = FTYPE_FILE;
 #if defined(__linux__)
+    s->fd_got_error     = 0;
+    s->fd_media_changed = 0;
+    s->fd_have_probe    = 0;
     if (strstart(filename, "/dev/cd", NULL)) {
         /* open will not fail even if no CD is inserted */
         open_flags |= O_NONBLOCK;
@@ -615,6 +627,17 @@
 #if defined(__linux__)
     /* close fd so that we can reopen it as needed */
     if (s->type == FTYPE_FD) {
+#if !defined(QEMU_TOOL)
+        if (s->fd_have_probe == 0) {
+            /* Find out what hardware we are dealing with */
+            if (ioctl(s->fd,FDGETDRVPRM,&drive_info) == 0) {
+                s->fd_have_probe = 1;
+                s->fd_drive_type = drive_info.cmos;
+                /* Tell emulated controller about the drive */
+		*global_floppy_hack_ptr = drive_info.cmos;
+            }
+        }
+#endif
         close(s->fd);
         s->fd = -1;
         s->fd_media_changed = 1;
diff -Naur qemu-0.9.0/hw/fdc.c qemu-0.9.0-flpy2/hw/fdc.c
--- qemu-0.9.0/hw/fdc.c	2007-02-05 15:01:54.000000000 -0800
+++ qemu-0.9.0-flpy2/hw/fdc.c	2007-02-13 19:17:11.000000000 -0800
@@ -93,11 +93,43 @@
     uint8_t ro;               /* Is read-only           */
 } fdrive_t;
 
+#ifdef __linux__
+#define FD_HACK_NO_DRIVE -1
+
+extern int global_fd_hack_tbl[];
+
+static void fd_init (fdrive_t *drv, BlockDriverState *bs, int dflt_drive_type)
+#else
 static void fd_init (fdrive_t *drv, BlockDriverState *bs)
+#endif
 {
     /* Drive */
     drv->bs = bs;
+#ifdef __linux__
+    switch(dflt_drive_type) {
+        /*XXX 
+            The DRIVE_NONE entries should probably be USER 
+            defined with appropriate hints entries.
+         XXX*/
+        case 0: /* unknown */
+            drv->drive = FDRIVE_DRV_NONE; break;
+        case 1: /* 360K PC */
+            drv->drive = FDRIVE_DRV_NONE; break;
+        case 2: /* 1.2M */
+            drv->drive = FDRIVE_DRV_120; break;
+        case 3: /* 720k */
+            drv->drive = FDRIVE_DRV_NONE; break;
+        case 4: /* 1.44M */
+            drv->drive = FDRIVE_DRV_144; break;
+        case 5: /* 2.88M */
+            drv->drive = FDRIVE_DRV_288; break;
+        default:
+        case FD_HACK_NO_DRIVE:
+            drv->drive = FDRIVE_DRV_NONE; break;
+    }
+#else
     drv->drive = FDRIVE_DRV_NONE;
+#endif
     drv->drflags = 0;
     drv->perpendicular = 0;
     /* Disk */
@@ -512,7 +544,11 @@
         fdctrl->dma_en = 0;
     }
     for (i = 0; i < 2; i++) {
+#ifdef __linux__
+        fd_init(&fdctrl->drives[i], fds[i], global_fd_hack_tbl[i]);
+#else
         fd_init(&fdctrl->drives[i], fds[i]);
+#endif
     }
     fdctrl_reset(fdctrl, 0);
     fdctrl->state = FD_CTRL_ACTIVE;
diff -Naur qemu-0.9.0/vl.c qemu-0.9.0-flpy2/vl.c
--- qemu-0.9.0/vl.c	2007-02-05 15:01:54.000000000 -0800
+++ qemu-0.9.0-flpy2/vl.c	2007-02-13 03:20:02.000000000 -0800
@@ -174,6 +174,12 @@
 int semihosting_enabled = 0;
 int autostart = 1;
 
+#ifdef __linux__
+#define FD_HACK_NO_DRIVE -1
+int global_fd_hack_tbl[MAX_FD];
+int *global_floppy_hack_ptr;
+#endif
+
 /***********************************************************/
 /* x86 ISA bus support */
 
@@ -7135,6 +7141,10 @@
                 bdrv_set_type_hint(fd_table[i], BDRV_TYPE_FLOPPY);
             }
             if (fd_filename[i] != '\0') {
+#ifdef __linux__
+                global_fd_hack_tbl[i] = FD_HACK_NO_DRIVE;
+                global_floppy_hack_ptr = &global_fd_hack_tbl[i];
+#endif
                 if (bdrv_open(fd_table[i], fd_filename[i],
                               snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
                     fprintf(stderr, "qemu: could not open floppy disk image '%s'\n",

Reply via email to