Index: ioemu/xenstore.c
===================================================================
--- ioemu.orig/xenstore.c	2007-05-03 15:17:52.000000000 +0100
+++ ioemu/xenstore.c	2007-05-03 15:18:05.000000000 +0100
@@ -9,8 +9,15 @@
  */
 
 #include "vl.h"
+#include "block_int.h"
+#include <unistd.h>
 
 static struct xs_handle *xsh = NULL;
+static char *media_filename[MAX_DISKS];
+static QEMUTimer *insert_timer = NULL;
+
+#define UWAIT_MAX (30*1000000) /* thirty seconds */
+#define UWAIT     (100000)     /* 1/10th second  */
 
 static int pasprintf(char **buf, const char *fmt, ...)
 {
@@ -28,9 +35,54 @@
     return ret;
 }
 
+static void insert_media(void *opaque)
+{
+    int i;
+
+    for (i = 0; i < MAX_DISKS; i++) {
+        if (media_filename[i] && bs_table[i]) {
+            do_change(bs_table[i]->device_name, media_filename[i]);
+            free(media_filename[i]);
+            media_filename[i] = NULL;
+        }
+    }
+}
+
+void xenstore_check_new_media_present(int timeout)
+{
+
+    if (insert_timer == NULL)
+        insert_timer = qemu_new_timer(rt_clock, insert_media, NULL);
+    qemu_mod_timer(insert_timer, qemu_get_clock(rt_clock) + timeout);
+}
+
+static void waitForDevice(char *fn)
+{ 
+    struct stat sbuf;
+    int status;
+    int uwait = UWAIT_MAX;
+
+    do {
+        status = stat(fn, &sbuf);
+        if (!status) break;
+        usleep(UWAIT);
+        uwait -= UWAIT;
+    } while (uwait > 0);
+
+    return;
+}
+
 void xenstore_parse_domain_config(int domid)
 {
-    char *path;
+    char **e = NULL;
+    char *buf = NULL, *path;
+    char *fpath = NULL, *bpath = NULL,
+        *dev = NULL, *params = NULL, *type = NULL;
+    int i;
+    unsigned int len, num, hd_index;
+
+    for(i = 0; i < MAX_DISKS; i++)
+        media_filename[i] = NULL;
 
     xsh = xs_daemon_open();
     if (xsh == NULL) {
@@ -44,8 +96,91 @@
         goto out;
     }
 
+    if (pasprintf(&buf, "%s/device/vbd", path) == -1)
+        goto out;
+
+    e = xs_directory(xsh, XBT_NULL, buf, &num);
+    if (e == NULL)
+        goto out;
+
+    for (i = 0; i < num; i++) {
+        /* read the backend path */
+        if (pasprintf(&buf, "%s/device/vbd/%s/backend", path, e[i]) == -1)
+            continue;
+        free(bpath);
+        bpath = xs_read(xsh, XBT_NULL, buf, &len);
+        if (bpath == NULL)
+            continue;
+        /* read the name of the device */
+        if (pasprintf(&buf, "%s/dev", bpath) == -1)
+            continue;
+        free(dev);
+        dev = xs_read(xsh, XBT_NULL, buf, &len);
+        if (dev == NULL)
+            continue;
+        if (strncmp(dev, "hd", 2) || strlen(dev) != 3)
+            continue;
+        hd_index = dev[2] - 'a';
+        if (hd_index >= MAX_DISKS)
+            continue;
+        /* read the type of the device */
+        if (pasprintf(&buf, "%s/device/vbd/%s/device-type", path, e[i]) == -1)
+            continue;
+        free(type);
+        type = xs_read(xsh, XBT_NULL, buf, &len);
+        if (pasprintf(&buf, "%s/params", bpath) == -1)
+            continue;
+        free(params);
+        params = xs_read(xsh, XBT_NULL, buf, &len);
+        if (params == NULL)
+            continue;
+        /* 
+         * check if device has a phantom vbd; the phantom is hooked
+         * to the frontend device (for ease of cleanup), so lookup 
+         * the frontend device, and see if there is a phantom_vbd
+         * if there is, we will use resolution as the filename
+         */
+        if (pasprintf(&buf, "%s/device/vbd/%s/phantom_vbd", path, e[i]) == -1)
+            continue;
+        free(fpath);
+        fpath = xs_read(xsh, XBT_NULL, buf, &len);
+        if (fpath) {
+            if (pasprintf(&buf, "%s/dev", fpath) == -1)
+                continue;
+            free(params);
+            params = xs_read(xsh, XBT_NULL, buf , &len);
+            if (params) {
+                /* 
+                 * wait for device, on timeout silently fail because we will 
+                 * fail to open below
+                 */
+                waitForDevice(params);
+            }
+        }
+
+        bs_table[hd_index] = bdrv_new(dev);
+        /* check if it is a cdrom */
+        if (type && !strcmp(type, "cdrom")) {
+            bdrv_set_type_hint(bs_table[hd_index], BDRV_TYPE_CDROM);
+            if (pasprintf(&buf, "%s/params", bpath) != -1)
+                xs_watch(xsh, buf, dev);
+        }
+        /* open device now if media present */
+        if (params[0]) {
+            if (bdrv_open(bs_table[hd_index], params, 0 /* snapshot */) < 0)
+                fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
+                        params);
+        }
+    }
+
  out:
+    free(type);
+    free(params);
+    free(dev);
+    free(bpath);
+    free(buf);
     free(path);
+    free(e);
     return;
 }
 
@@ -58,14 +193,35 @@
 
 void xenstore_process_event(void *opaque)
 {
-    char **vec;
-    unsigned int num;
+    char **vec, *image = NULL;
+    unsigned int len, num, hd_index;
 
     vec = xs_read_watch(xsh, &num);
     if (!vec)
         return;
 
+    if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) ||
+        strlen(vec[XS_WATCH_TOKEN]) != 3)
+        goto out;
+    hd_index = vec[XS_WATCH_TOKEN][2] - 'a';
+    image = xs_read(xsh, XBT_NULL, vec[XS_WATCH_PATH], &len);
+    if (image == NULL || !strcmp(image, bs_table[hd_index]->filename))
+        goto out;  /* gone or identical */
+
+    do_eject(0, vec[XS_WATCH_TOKEN]);
+    bs_table[hd_index]->filename[0] = 0;
+    if (media_filename[hd_index]) {
+        free(media_filename[hd_index]);
+        media_filename[hd_index] = NULL;
+    }
+
+    if (image[0]) {
+        media_filename[hd_index] = strdup(image);
+        xenstore_check_new_media_present(5000);
+    }
+
  out:
+    free(image);
     free(vec);
 }
 
Index: ioemu/vl.c
===================================================================
--- ioemu.orig/vl.c	2007-05-03 15:17:52.000000000 +0100
+++ ioemu/vl.c	2007-05-03 15:18:05.000000000 +0100
@@ -5331,9 +5331,11 @@
            "Standard options:\n"
            "-M machine      select emulated machine (-M ? for list)\n"
            "-fda/-fdb file  use 'file' as floppy disk 0/1 image\n"
+#ifndef CONFIG_DM
            "-hda/-hdb file  use 'file' as IDE hard disk 0/1 image\n"
            "-hdc/-hdd file  use 'file' as IDE hard disk 2/3 image\n"
            "-cdrom file     use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
+#endif /* !CONFIG_DM */
            "-boot [a|c|d]   boot on floppy (a), hard disk (c) or CD-ROM (d)\n"
 	   "-snapshot       write to temporary files instead of disk image files\n"
 #ifdef TARGET_I386
@@ -5460,11 +5462,13 @@
     QEMU_OPTION_M,
     QEMU_OPTION_fda,
     QEMU_OPTION_fdb,
+#ifndef CONFIG_DM
     QEMU_OPTION_hda,
     QEMU_OPTION_hdb,
     QEMU_OPTION_hdc,
     QEMU_OPTION_hdd,
     QEMU_OPTION_cdrom,
+#endif /* !CONFIG_DM */
     QEMU_OPTION_boot,
     QEMU_OPTION_snapshot,
 #ifdef TARGET_I386
@@ -5536,11 +5540,13 @@
     { "M", HAS_ARG, QEMU_OPTION_M },
     { "fda", HAS_ARG, QEMU_OPTION_fda },
     { "fdb", HAS_ARG, QEMU_OPTION_fdb },
+#ifndef CONFIG_DM
     { "hda", HAS_ARG, QEMU_OPTION_hda },
     { "hdb", HAS_ARG, QEMU_OPTION_hdb },
     { "hdc", HAS_ARG, QEMU_OPTION_hdc },
     { "hdd", HAS_ARG, QEMU_OPTION_hdd },
     { "cdrom", HAS_ARG, QEMU_OPTION_cdrom },
+#endif /* !CONFIG_DM */
     { "boot", HAS_ARG, QEMU_OPTION_boot },
     { "snapshot", 0, QEMU_OPTION_snapshot },
 #ifdef TARGET_I386
@@ -5882,10 +5888,16 @@
 #ifdef CONFIG_GDBSTUB
     int use_gdbstub, gdbstub_port;
 #endif
-    int i, cdrom_index;
+    int i;
+#ifndef CONFIG_DM
+    int cdrom_index;
+#endif /* !CONFIG_DM */
     int snapshot, linux_boot;
     const char *initrd_filename;
-    const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
+#ifndef CONFIG_DM
+    const char *hd_filename[MAX_DISKS];
+#endif /* !CONFIG_DM */
+    const char *fd_filename[MAX_FD];
     const char *kernel_filename, *kernel_cmdline;
     DisplayState *ds = &display_state;
     int cyls, heads, secs, translation;
@@ -5946,8 +5958,10 @@
     initrd_filename = NULL;
     for(i = 0; i < MAX_FD; i++)
         fd_filename[i] = NULL;
+#ifndef CONFIG_DM
     for(i = 0; i < MAX_DISKS; i++)
         hd_filename[i] = NULL;
+#endif /* !CONFIG_DM */
     ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
     vga_ram_size = VGA_RAM_SIZE;
     bios_size = BIOS_SIZE;
@@ -5961,11 +5975,13 @@
     vncunused = 0;
     kernel_filename = NULL;
     kernel_cmdline = "";
+#ifndef CONFIG_DM
 #ifdef TARGET_PPC
     cdrom_index = 1;
 #else
     cdrom_index = 2;
 #endif
+#endif /* !CONFIG_DM */
     cyls = heads = secs = 0;
     translation = BIOS_ATA_TRANSLATION_AUTO;
     pstrcpy(monitor_device, sizeof(monitor_device), "null");
@@ -6004,7 +6020,11 @@
             break;
         r = argv[optind];
         if (r[0] != '-') {
+#ifndef CONFIG_DM
             hd_filename[0] = argv[optind++];
+#else
+            help();
+#endif /* !CONFIG_DM */
         } else {
             const QEMUOption *popt;
 
@@ -6048,6 +6068,7 @@
             case QEMU_OPTION_initrd:
                 initrd_filename = optarg;
                 break;
+#ifndef CONFIG_DM
             case QEMU_OPTION_hda:
             case QEMU_OPTION_hdb:
             case QEMU_OPTION_hdc:
@@ -6060,6 +6081,7 @@
                         cdrom_index = -1;
                 }
                 break;
+#endif /* !CONFIG_DM */
             case QEMU_OPTION_snapshot:
                 snapshot = 1;
                 break;
@@ -6112,11 +6134,13 @@
             case QEMU_OPTION_append:
                 kernel_cmdline = optarg;
                 break;
+#ifndef CONFIG_DM
             case QEMU_OPTION_cdrom:
                 if (cdrom_index >= 0) {
                     hd_filename[cdrom_index] = optarg;
                 }
                 break;
+#endif /* !CONFIG_DM */
             case QEMU_OPTION_boot:
                 boot_device = optarg[0];
                 if (boot_device != 'a' && 
@@ -6372,6 +6396,7 @@
     }
 
 #ifdef CONFIG_DM
+    bdrv_init();
     xenstore_parse_domain_config(domid);
 #endif /* CONFIG_DM */
 
@@ -6381,6 +6406,7 @@
 #endif
     linux_boot = (kernel_filename != NULL);
         
+#ifndef CONFIG_DM
     if (!linux_boot && 
         hd_filename[0] == '\0' && 
         (cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') &&
@@ -6394,6 +6420,7 @@
         else
             boot_device = 'd';
     }
+#endif /* !CONFIG_DM */
 
     setvbuf(stdout, NULL, _IOLBF, 0);
     
@@ -6514,6 +6541,7 @@
 
 #endif /* !CONFIG_DM */
 
+#ifndef CONFIG_DM
     /* we always create the cdrom drive, even if no disk is there */
     bdrv_init();
     if (cdrom_index >= 0) {
@@ -6540,6 +6568,7 @@
             }
         }
     }
+#endif /* !CONFIG_DM */
 
     /* we always create at least one floppy disk */
     fd_table[0] = bdrv_new("fda");
Index: ioemu/monitor.c
===================================================================
--- ioemu.orig/monitor.c	2007-05-03 15:17:52.000000000 +0100
+++ ioemu/monitor.c	2007-05-03 15:18:05.000000000 +0100
@@ -24,6 +24,7 @@
 #include "vl.h"
 #include "disas.h"
 #include <dirent.h>
+#include "block_int.h"
 
 //#define DEBUG
 //#define DEBUG_COMPLETION
@@ -330,7 +331,7 @@
     return 0;
 }
 
-static void do_eject(int force, const char *filename)
+void do_eject(int force, const char *filename)
 {
     BlockDriverState *bs;
 
@@ -342,7 +343,7 @@
     eject_device(bs, force);
 }
 
-static void do_change(const char *device, const char *filename)
+void do_change(const char *device, const char *filename)
 {
     BlockDriverState *bs;
     int i;
Index: ioemu/block.c
===================================================================
--- ioemu.orig/block.c	2007-05-03 15:17:52.000000000 +0100
+++ ioemu/block.c	2007-05-03 15:18:05.000000000 +0100
@@ -758,6 +758,7 @@
 static void raw_close(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
+    bs->total_sectors = 0;
     close(s->fd);
 }
 
Index: ioemu/vl.h
===================================================================
--- ioemu.orig/vl.h	2007-05-03 15:18:00.000000000 +0100
+++ ioemu/vl.h	2007-05-03 15:18:05.000000000 +0100
@@ -1192,6 +1192,8 @@
 void term_print_help(void);
 void monitor_readline(const char *prompt, int is_password,
                       char *buf, int buf_size);
+void do_eject(int force, const char *filename);
+void do_change(const char *device, const char *filename);
 
 /* readline.c */
 typedef void ReadLineFunc(void *opaque, const char *str);
@@ -1206,6 +1208,9 @@
 
 /* xenstore.c */
 void xenstore_parse_domain_config(int domid);
+int xenstore_fd(void);
+void xenstore_process_event(void *opaque);
+void xenstore_check_new_media_present(int timeout);
 
 int xenstore_vm_write(int domid, char *key, char *val);
 char *xenstore_vm_read(int domid, char *key, int *len);
Index: ioemu/hw/ide.c
===================================================================
--- ioemu.orig/hw/ide.c	2007-05-03 15:17:52.000000000 +0100
+++ ioemu/hw/ide.c	2007-05-03 15:18:05.000000000 +0100
@@ -1199,6 +1199,7 @@
         } else {
             ide_atapi_cmd_error(s, SENSE_NOT_READY, 
                                 ASC_MEDIUM_NOT_PRESENT);
+            xenstore_check_new_media_present(1000);
         }
         break;
     case GPCMD_MODE_SENSE_10:
