diff -r dc213d745642 tools/ioemu/block.c
--- a/tools/ioemu/block.c	Mon May 15 16:32:09 2006 +0100
+++ b/tools/ioemu/block.c	Thu May 25 14:57:13 2006 -0600
@@ -1,8 +1,8 @@
 /*
  * QEMU System Emulator block driver
- * 
+ *
  * Copyright (c) 2003 Fabrice Bellard
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
@@ -41,6 +41,7 @@ BlockDriverState *bdrv_new(const char *d
     bs = qemu_mallocz(sizeof(BlockDriverState));
     if(!bs)
         return NULL;
+
     pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
     if (device_name[0] != '\0') {
         /* insert at the end */
@@ -62,7 +63,7 @@ BlockDriver *bdrv_find_format(const char
     return NULL;
 }
 
-int bdrv_create(BlockDriver *drv, 
+int bdrv_create(BlockDriver *drv,
                 const char *filename, int64_t size_in_sectors,
                 const char *backing_file, int flags)
 {
@@ -86,7 +87,7 @@ static BlockDriver *find_image_format(co
         return NULL;
     }
     close(fd);
-    
+
     drv = NULL;
     score_max = 0;
     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
@@ -108,12 +109,13 @@ int bdrv_open2(BlockDriverState *bs, con
                BlockDriver *drv)
 {
     int ret;
-    
+
+    pstrcpy(bs->filename, sizeof(bs->filename), filename);
+
     bs->read_only = 0;
     bs->is_temporary = 0;
     bs->encrypted = 0;
-    
-    pstrcpy(bs->filename, sizeof(bs->filename), filename);
+
     if (!drv) {
         drv = find_image_format(filename);
         if (!drv)
@@ -123,7 +125,7 @@ int bdrv_open2(BlockDriverState *bs, con
     bs->opaque = qemu_mallocz(drv->instance_size);
     if (bs->opaque == NULL && drv->instance_size > 0)
         return -1;
-    
+
     ret = drv->bdrv_open(bs, filename);
     if (ret < 0) {
         qemu_free(bs->opaque);
@@ -146,6 +148,8 @@ int bdrv_open2(BlockDriverState *bs, con
             goto fail;
     }
 
+    shdev_set_media_instance(bs);
+
     bs->inserted = 1;
 
     /* call the change callback */
@@ -170,6 +174,7 @@ void bdrv_close(BlockDriverState *bs)
         bs->opaque = NULL;
         bs->drv = NULL;
         bs->inserted = 0;
+        bs->media_instance = 0;
 
         /* call the change callback */
         if (bs->change_cb)
@@ -222,7 +227,7 @@ int bdrv_commit(BlockDriverState *bs)
 }
 
 /* return -1 if error */
-int bdrv_read(BlockDriverState *bs, int64_t sector_num, 
+int bdrv_read(BlockDriverState *bs, int64_t sector_num,
               uint8_t *buf, int nb_sectors)
 {
     int ret, n;
@@ -261,7 +266,7 @@ int bdrv_read(BlockDriverState *bs, int6
 }
 
 /* return -1 if error */
-int bdrv_write(BlockDriverState *bs, int64_t sector_num, 
+int bdrv_write(BlockDriverState *bs, int64_t sector_num,
                const uint8_t *buf, int nb_sectors)
 {
     if (!bs->inserted)
@@ -286,7 +291,7 @@ void bdrv_set_boot_sector(BlockDriverSta
     memset(bs->boot_sector_data + size, 0, 512 - size);
 }
 
-void bdrv_set_geometry_hint(BlockDriverState *bs, 
+void bdrv_set_geometry_hint(BlockDriverState *bs,
                             int cyls, int heads, int secs)
 {
     bs->cyls = cyls;
@@ -301,7 +306,7 @@ void bdrv_set_type_hint(BlockDriverState
                       type == BDRV_TYPE_FLOPPY));
 }
 
-void bdrv_get_geometry_hint(BlockDriverState *bs, 
+void bdrv_get_geometry_hint(BlockDriverState *bs,
                             int *pcyls, int *pheads, int *psecs)
 {
     *pcyls = bs->cyls;
@@ -339,7 +344,7 @@ void bdrv_set_locked(BlockDriverState *b
     bs->locked = locked;
 }
 
-void bdrv_set_change_cb(BlockDriverState *bs, 
+void bdrv_set_change_cb(BlockDriverState *bs,
                         void (*change_cb)(void *opaque), void *opaque)
 {
     bs->change_cb = change_cb;
@@ -377,7 +382,7 @@ void bdrv_get_format(BlockDriverState *b
     }
 }
 
-void bdrv_iterate_format(void (*it)(void *opaque, const char *name), 
+void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
                          void *opaque)
 {
     BlockDriver *drv;
@@ -387,7 +392,7 @@ void bdrv_iterate_format(void (*it)(void
     }
 }
 
-BlockDriverState *bdrv_find(const char *name)
+BlockDriverState *bdrv_find_by_device(const char *name)
 {
     BlockDriverState *bs;
 
@@ -396,6 +401,15 @@ BlockDriverState *bdrv_find(const char *
             return bs;
     }
     return NULL;
+}
+
+BlockDriverState *bdrv_find_bs(int (*it)(BlockDriverState *, void *), void *opaque)
+{
+    BlockDriverState *bs;
+
+    for (bs = bdrv_first; bs != NULL && !it(bs, opaque); bs = bs->next);
+
+    return( bs );
 }
 
 void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
@@ -481,28 +495,28 @@ static int raw_open(BlockDriverState *bs
     return 0;
 }
 
-static int raw_read(BlockDriverState *bs, int64_t sector_num, 
+static int raw_read(BlockDriverState *bs, int64_t sector_num,
                     uint8_t *buf, int nb_sectors)
 {
     BDRVRawState *s = bs->opaque;
     int ret;
-    
+
     lseek(s->fd, sector_num * 512, SEEK_SET);
     ret = read(s->fd, buf, nb_sectors * 512);
-    if (ret != nb_sectors * 512) 
-        return -1;
-    return 0;
-}
-
-static int raw_write(BlockDriverState *bs, int64_t sector_num, 
+    if (ret != nb_sectors * 512)
+        return -1;
+    return 0;
+}
+
+static int raw_write(BlockDriverState *bs, int64_t sector_num,
                      const uint8_t *buf, int nb_sectors)
 {
     BDRVRawState *s = bs->opaque;
     int ret;
-    
+
     lseek(s->fd, sector_num * 512, SEEK_SET);
     ret = write(s->fd, buf, nb_sectors * 512);
-    if (ret != nb_sectors * 512) 
+    if (ret != nb_sectors * 512)
         return -1;
     return 0;
 }
@@ -521,7 +535,7 @@ static int raw_create(const char *filena
     if (flags || backing_file)
         return -ENOTSUP;
 
-    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 
+    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
               0644);
     if (fd < 0)
         return -EIO;
diff -r dc213d745642 tools/ioemu/block_int.h
--- a/tools/ioemu/block_int.h	Mon May 15 16:32:09 2006 +0100
+++ b/tools/ioemu/block_int.h	Thu May 25 14:57:13 2006 -0600
@@ -1,8 +1,8 @@
 /*
  * QEMU System Emulator block driver
- * 
+ *
  * Copyright (c) 2003 Fabrice Bellard
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
@@ -24,36 +24,22 @@
 #ifndef BLOCK_INT_H
 #define BLOCK_INT_H
 
-struct BlockDriver {
-    const char *format_name;
-    int instance_size;
-    int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
-    int (*bdrv_open)(BlockDriverState *bs, const char *filename);
-    int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num, 
-                     uint8_t *buf, int nb_sectors);
-    int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num, 
-                      const uint8_t *buf, int nb_sectors);
-    void (*bdrv_close)(BlockDriverState *bs);
-    int (*bdrv_create)(const char *filename, int64_t total_sectors, 
-                       const char *backing_file, int flags);
-    int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
-                             int nb_sectors, int *pnum);
-    int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
-    struct BlockDriver *next;
-};
+struct BlockDriver;
 
-struct BlockDriverState {
+typedef struct BlockDriverState {
     int64_t total_sectors;
     int read_only; /* if true, the media is read only */
     int inserted; /* if true, the media is present */
     int removable; /* if true, the media can be removed */
     int locked;    /* if true, the media cannot temporarily be ejected */
     int encrypted; /* if true, the media is encrypted */
+    int media_instance;
+    int shdev_el;
     /* event callback when inserting/removing */
     void (*change_cb)(void *opaque);
     void *change_opaque;
 
-    BlockDriver *drv;
+    struct BlockDriver *drv;
     void *opaque;
 
     int boot_sector_enabled;
@@ -63,15 +49,34 @@ struct BlockDriverState {
     char backing_file[1024]; /* if non zero, the image is a diff of
                                 this file image */
     int is_temporary;
-    
-    BlockDriverState *backing_hd;
-    
+
+    struct BlockDriverState *backing_hd;
+
     /* NOTE: the following infos are only hints for real hardware
        drivers. They are not used by the block driver */
     int cyls, heads, secs;
     int type;
     char device_name[32];
-    BlockDriverState *next;
-};
+    struct BlockDriverState *next;
+} BlockDriverState;
+
+typedef struct BlockDriver {
+    const char *format_name;
+    int instance_size;
+    int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
+    int (*bdrv_open)(BlockDriverState *bs, const char *filename);
+    int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
+                     uint8_t *buf, int nb_sectors);
+    int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
+                      const uint8_t *buf, int nb_sectors);
+    void (*bdrv_close)(BlockDriverState *bs);
+    int (*bdrv_create)(const char *filename, int64_t total_sectors,
+                       const char *backing_file, int flags);
+    int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
+                             int nb_sectors, int *pnum);
+    int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
+    struct BlockDriver *next;
+} BlockDriver;
+
 
 #endif /* BLOCK_INT_H */
diff -r dc213d745642 tools/ioemu/hw/ide.c
--- a/tools/ioemu/hw/ide.c	Mon May 15 16:32:09 2006 +0100
+++ b/tools/ioemu/hw/ide.c	Thu May 25 14:57:13 2006 -0600
@@ -278,6 +278,7 @@
 #define ASC_ILLEGAL_OPCODE                   0x20
 #define ASC_LOGICAL_BLOCK_OOR                0x21
 #define ASC_INV_FIELD_IN_CMD_PACKET          0x24
+#define ASC_MEDIA_CHANGED		     0x28
 #define ASC_MEDIUM_NOT_PRESENT               0x3a
 #define ASC_SAVING_PARAMETERS_NOT_SUPPORTED  0x39
 
@@ -294,6 +295,7 @@ typedef struct IDEState {
 typedef struct IDEState {
     /* ide config */
     int is_cdrom;
+    int media_changed;
     int cylinders, heads, sectors;
     int64_t nb_sectors;
     int mult_sectors;
@@ -1132,11 +1134,34 @@ static int cdrom_read_toc_raw(IDEState *
     return len;
 }
 
+static int cd_media_inserted(IDEState *s)
+{
+    int h, x = 0;
+
+    if (s->bs->removable) {
+        h = open(s->bs->filename, O_NONBLOCK, O_RDONLY);
+
+        if (h >= 0) {
+	    x = fcntl(h, F_GETFL);
+            x &= ~O_NONBLOCK;
+            fcntl(h, F_SETFL, x);
+
+	    x = read(h, &x, sizeof(x));
+	    close(h);
+        }
+    }
+    else 
+	x = sizeof( x );
+
+    return((x == sizeof(x)));
+}
+	
 static void ide_atapi_cmd(IDEState *s)
 {
     const uint8_t *packet;
     uint8_t *buf;
     int max_len;
+
 
     packet = s->io_buffer;
     buf = s->io_buffer;
@@ -1150,13 +1175,28 @@ static void ide_atapi_cmd(IDEState *s)
         printf("\n");
     }
 #endif
+
     switch(s->io_buffer[0]) {
     case GPCMD_TEST_UNIT_READY:
         if (bdrv_is_inserted(s->bs)) {
-            ide_atapi_cmd_ok(s);
+	    if (s->media_changed) {
+		s->media_changed = 0;
+            	ide_atapi_cmd_error(s, SENSE_UNIT_ATTENTION, ASC_MEDIA_CHANGED);
+	    }
+            else {
+		if (!cd_media_inserted(s) || shdev_media_check(s->bs)) {
+		    bdrv_close(s->bs);
+                    ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+                }
+                else 
+                    ide_atapi_cmd_ok(s);
+	    }
         } else {
-            ide_atapi_cmd_error(s, SENSE_NOT_READY, 
-                                ASC_MEDIUM_NOT_PRESENT);
+            ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+
+            if (cd_media_inserted(s)) {
+		    do_insert_request();
+	    }
         }
         break;
     case GPCMD_MODE_SENSE_10:
@@ -1288,6 +1328,13 @@ static void ide_atapi_cmd(IDEState *s)
                                     ASC_MEDIUM_NOT_PRESENT);
                 break;
             }
+
+            if (shdev_media_check(s->bs)) {
+		bdrv_close(s->bs);
+                ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+                break;
+            }
+
             nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8];
             lba = ube32_to_cpu(packet + 2);
             if (nb_sectors == 0) {
@@ -1345,7 +1392,7 @@ static void ide_atapi_cmd(IDEState *s)
             
             if (eject && !start) {
                 /* eject the disk */
-                bdrv_close(s->bs);
+                do_eject(1, s->bs->device_name);
             }
             ide_atapi_cmd_ok(s);
         }
@@ -1372,6 +1419,13 @@ static void ide_atapi_cmd(IDEState *s)
                                     ASC_MEDIUM_NOT_PRESENT);
                 break;
             }
+
+            if (shdev_media_check(s->bs)) {
+		bdrv_close(s->bs);
+                ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+                break;
+            }
+
             max_len = ube16_to_cpu(packet + 7);
             format = packet[9] >> 6;
             msf = (packet[1] >> 1) & 1;
@@ -1444,9 +1498,9 @@ static void cdrom_change_cb(void *opaque
     IDEState *s = opaque;
     int64_t nb_sectors;
 
-    /* XXX: send interrupt too */
     bdrv_get_geometry(s->bs, &nb_sectors);
     s->nb_sectors = nb_sectors;
+    s->media_changed = 1;
 }
 
 static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
@@ -1631,6 +1685,7 @@ static void ide_ioport_write(void *opaqu
             ide_set_signature(s);
             s->status = 0x00; /* NOTE: READY is _not_ set */
             s->error = 0x01;
+	    s->media_changed = 0;
             break;
         case WIN_PACKETCMD:
             if (!s->is_cdrom)
diff -r dc213d745642 tools/ioemu/monitor.c
--- a/tools/ioemu/monitor.c	Mon May 15 16:32:09 2006 +0100
+++ b/tools/ioemu/monitor.c	Thu May 25 14:57:13 2006 -0600
@@ -1,8 +1,8 @@
 /*
  * QEMU monitor
- * 
+ *
  * Copyright (c) 2003-2004 Fabrice Bellard
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
@@ -23,6 +23,7 @@
  */
 #include "vl.h"
 #include <dirent.h>
+#include <sys/shm.h>
 
 //#define DEBUG
 //#define DEBUG_COMPLETION
@@ -33,7 +34,7 @@
 
 /*
  * Supported types:
- * 
+ *
  * 'F'          filename
  * 'B'          block device name
  * 's'          string (accept optional quote)
@@ -66,7 +67,7 @@ void term_flush(void)
 {
     if (term_outbuf_index > 0) {
 	if(monitor_hd)
-        qemu_chr_write(monitor_hd, term_outbuf, term_outbuf_index);
+        qemu_chr_write(monitor_hd, (const uint8_t *)term_outbuf, term_outbuf_index);
 	else
 	    fwrite(term_outbuf, term_outbuf_index, 1, stderr);
         term_outbuf_index = 0;
@@ -240,7 +241,7 @@ static const KeyDef key_defs[] = {
 static const KeyDef key_defs[] = {
     { 0x2a, "shift" },
     { 0x36, "shift_r" },
-    
+
     { 0x38, "alt" },
     { 0xb8, "alt_r" },
     { 0x1d, "ctrl" },
@@ -293,7 +294,7 @@ static const KeyDef key_defs[] = {
     { 0x30, "b" },
     { 0x31, "n" },
     { 0x32, "m" },
-    
+
     { 0x39, "spc" },
     { 0x3a, "caps_lock" },
     { 0x3b, "f1" },
@@ -348,7 +349,7 @@ static void do_send_key(const char *stri
     uint8_t keycodes[16];
     const char *p;
     int nb_keycodes, keycode, i;
-    
+
     nb_keycodes = 0;
     p = string;
     while (*p != '\0') {
@@ -387,7 +388,7 @@ static void do_send_key(const char *stri
 }
 
 
-static int eject_device(BlockDriverState *bs, int force)
+static int eject_logical_device(BlockDriverState *bs, int force)
 {
     if (bdrv_is_inserted(bs)) {
         if (!force) {
@@ -405,23 +406,57 @@ static int eject_device(BlockDriverState
     return 0;
 }
 
-static void do_eject(int force, const char *filename)
+void do_eject(int force, const char *device)
 {
     char cmd[1024];
     BlockDriverState *bs;
 
-    bs = bdrv_find(filename);
+    bs = bdrv_find_by_device(device);
+
     if (!bs) {
-        term_printf("device not found\n");
+        term_printf("'%s' not found\n", device);
         return;
     }
-    eject_device(bs, force);
-    sprintf(cmd, "eject %s", filename);
-    system(cmd);
-
-}
-
-static void do_change(const char *device, const char *filename)
+
+    if (eject_logical_device(bs, force) == 0) {
+        shdev_eject_notice(bs);
+        sprintf(cmd, "eject %s", bs->filename);
+        system(cmd);
+    }
+}
+
+void do_insert(const char *device)
+{
+    BlockDriverState *bs;
+
+    bs = bdrv_find_by_device(device);
+
+    if (!bs) {
+        term_printf("'%s' not found\n", device);
+        return;
+    }
+
+    if (!bs->removable) {
+        term_printf("'%s' not removable\n", device);
+        return;
+    }
+
+    if (bs->inserted) {
+        term_printf("'%s' is already inserted\n", device);
+        return;
+    }
+
+    bdrv_open(bs, bs->filename, 0);
+}
+
+static int find_bs_by_type(BlockDriverState *bs, void *opaque)
+{
+   int *type = (int *)opaque;
+
+   return( (bs->type == *type) );
+}
+
+static void do_change_source(const char *device, const char *filename)
 {
     BlockDriverState *bs;
 #if 0
@@ -429,14 +464,18 @@ static void do_change(const char *device
     char password[256];
 #endif
 
-    bs = bdrv_find(device);
+    bs = bdrv_find_by_device(device);
+
     if (!bs) {
         term_printf("device not found\n");
         return;
     }
-    if (eject_device(bs, 0) < 0)
+
+    if (eject_logical_device(bs, 0) < 0)
         return;
-    bdrv_open(bs, filename, 0);
+
+    do_insert(bs->device_name);
+
 #if 0
     if (bdrv_is_encrypted(bs)) {
         term_printf("%s is encrypted.\n", device);
@@ -448,6 +487,20 @@ static void do_change(const char *device
         }
     }
 #endif
+}
+
+void do_insert_request()
+{
+    BlockDriverState *bs = NULL;
+    int type = BDRV_TYPE_CDROM;
+
+    bs = bdrv_find_bs(find_bs_by_type, &type);
+
+    if (bs) {
+        do_change_source(bs->device_name, bs->filename);
+    }
+    else
+        term_printf("Did not find cdrom bs.\n");
 }
 
 static void do_screen_dump(const char *filename)
@@ -482,17 +535,19 @@ static term_cmd_t term_cmds[] = {
       "", "quit the emulator" },
     { "eject", "-fB", do_eject,
       "[-f] device", "eject a removable media (use -f to force it)" },
-    { "change", "BF", do_change,
-      "device filename", "change a removable media" },
+    { "insert", "B", do_insert,
+      "device", "notifies qemu of inserted removable media." },
+    { "change", "BF", do_change_source,
+      "device filename", "change source for virtual removable-media device." },
     { "screendump", "F", do_screen_dump,
       "filename", "save screen into PPM image 'filename'" },
     { "log", "s", do_log,
       "item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" },
     { "q|quit", "", do_quit,
       "", "quit the emulator" },
-    { "sendkey", "s", do_send_key, 
+    { "sendkey", "s", do_send_key,
       "keys", "send keys to the VM (e.g. 'sendkey ctrl-alt-f1')" },
-    { NULL, NULL, }, 
+    { NULL, NULL, },
 };
 
 static term_cmd_t info_cmds[] = {
@@ -596,7 +651,7 @@ static void monitor_handle_command(const
 #ifdef DEBUG
     term_printf("command='%s'\n", cmdline);
 #endif
-    
+
     /* extract the command name */
     p = cmdline;
     q = cmdname;
@@ -612,10 +667,10 @@ static void monitor_handle_command(const
         len = sizeof(cmdname) - 1;
     memcpy(cmdname, pstart, len);
     cmdname[len] = '\0';
-    
+
     /* find the command */
     for(cmd = term_cmds; cmd->name != NULL; cmd++) {
-        if (compare_cmd(cmdname, cmd->name)) 
+        if (compare_cmd(cmdname, cmd->name))
             goto found;
     }
     term_printf("unknown command: '%s'\n", cmdname);
@@ -624,7 +679,7 @@ static void monitor_handle_command(const
 
     for(i = 0; i < MAX_ARGS; i++)
         str_allocated[i] = NULL;
-    
+
     /* parse the parameters */
     typestr = cmd->args_type;
     nb_args = 0;
@@ -717,7 +772,7 @@ static void monitor_handle_command(const
     while (isspace(*p))
         p++;
     if (*p != '\0') {
-        term_printf("%s: extraneous characters at the end of line\n", 
+        term_printf("%s: extraneous characters at the end of line\n",
                     cmdname);
         goto fail;
     }
diff -r dc213d745642 tools/ioemu/target-i386-dm/Makefile
--- a/tools/ioemu/target-i386-dm/Makefile	Mon May 15 16:32:09 2006 +0100
+++ b/tools/ioemu/target-i386-dm/Makefile	Thu May 25 14:57:13 2006 -0600
@@ -250,7 +250,7 @@ endif
 endif
 
 # must use static linking to avoid leaving stuff in virtual address space
-VL_OBJS=vl.o exec.o monitor.o osdep.o block.o readline.o pci.o console.o 
+VL_OBJS=vl.o exec.o monitor.o shdev.o osdep.o block.o readline.o pci.o console.o 
 VL_OBJS+=block-cow.o block-qcow.o block-vmdk.o block-cloop.o aes.o
 #VL_OBJS+= block-cloop.o
 
diff -r dc213d745642 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c	Mon May 15 16:32:09 2006 +0100
+++ b/tools/ioemu/vl.c	Thu May 25 14:57:13 2006 -0600
@@ -818,7 +818,7 @@ static void init_timers(void)
     {
         /* get times() syscall frequency */
         timer_freq = sysconf(_SC_CLK_TCK);
-      
+
 #ifndef TARGET_HVM
         /* timer signal */
         sigfillset(&act.sa_mask);
@@ -887,7 +887,7 @@ void qemu_chr_printf(CharDriverState *s,
     va_list ap;
     va_start(ap, fmt);
     vsnprintf(buf, sizeof(buf), fmt, ap);
-    qemu_chr_write(s, buf, strlen(buf));
+    qemu_chr_write(s, (uint8_t *) buf, strlen(buf));
     va_end(ap);
 }
 
@@ -954,7 +954,7 @@ static int unix_write(int fd, const uint
     fd_set writefds;
     struct timeval timeout;
 
-    max_fd = fd;  
+    max_fd = fd;
 
     len = len1;
     while (len > 0) {
@@ -1900,7 +1900,7 @@ int qemu_savevm(const char *filename)
         /* ID string */
         len = strlen(se->idstr);
         qemu_put_byte(f, len);
-        qemu_put_buffer(f, se->idstr, len);
+        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
 
         qemu_put_be32(f, se->instance_id);
         qemu_put_be32(f, se->version_id);
@@ -1974,7 +1974,7 @@ int qemu_loadvm(const char *filename)
         len = qemu_get_byte(f);
         if (feof(f))
             break;
-        qemu_get_buffer(f, idstr, len);
+        qemu_get_buffer(f, (uint8_t *)idstr, len);
         idstr[len] = '\0';
         instance_id = qemu_get_be32(f);
         version_id = qemu_get_be32(f);
@@ -2533,7 +2533,7 @@ int main(int argc, char **argv)
 #ifdef CONFIG_GDBSTUB
     int use_gdbstub, gdbstub_port;
 #endif
-    int i, has_cdrom;
+    int i, has_cdrom = 0;
     int snapshot, linux_boot;
     CPUState *env;
     const char *initrd_filename;
@@ -2553,6 +2553,8 @@ int main(int argc, char **argv)
     char qemu_dm_logfilename[64];
     const char *loadvm = NULL;
     unsigned long nr_pages, *page_array;
+    int dev_type;
+    char buf[64];
     extern void *shared_page;
 
 #if !defined(CONFIG_SOFTMMU)
@@ -2579,7 +2581,6 @@ int main(int argc, char **argv)
     vncconnect=NULL;
     kernel_filename = NULL;
     kernel_cmdline = "";
-    has_cdrom = 1;
     cyls = heads = secs = 0;
     pstrcpy(monitor_device, sizeof(monitor_device), "vc");
 
@@ -2642,12 +2643,6 @@ int main(int argc, char **argv)
             case QEMU_OPTION_initrd:
                 initrd_filename = optarg;
                 break;
-            case QEMU_OPTION_hda:
-                hd_filename[0] = optarg;
-                break;
-            case QEMU_OPTION_hdb:
-                hd_filename[1] = optarg;
-                break;
             case QEMU_OPTION_snapshot:
                 snapshot = 1;
                 break;
@@ -2720,15 +2715,56 @@ int main(int argc, char **argv)
                     }
                 }
                 break;
+            case QEMU_OPTION_hda:
+                if (hd_filename[0]) {
+                    fprintf(stderr,
+                            "qemu: virtual device 'hd%c' already defined as %s\n",
+                            'a',
+                            hd_filename[0] );
+                    break;
+                }
+                hd_filename[0] = optarg;
+                break;
+            case QEMU_OPTION_hdb:
+                if (hd_filename[1]) {
+                    fprintf(stderr,
+                            "qemu: virtual device 'hd%c' already defined as %s\n",
+                            'b',
+                            hd_filename[1] );
+                    break;
+                }
+                hd_filename[1] = optarg;
+                break;
             case QEMU_OPTION_hdc:
+                if (hd_filename[2]) {
+                    fprintf(stderr,
+                            "qemu: virtual device 'hd%c' already defined as %s\n",
+                            'c',
+                            hd_filename[2] );
+                    break;
+                }
                 hd_filename[2] = optarg;
-                has_cdrom = 0;
                 break;
             case QEMU_OPTION_hdd:
+                if (hd_filename[3]) {
+                    fprintf(stderr,
+                            "qemu: virtual device 'hd%c' already defined as %s\n",
+                            'd',
+                            hd_filename[3] );
+                    break;
+                }
                 hd_filename[3] = optarg;
                 break;
             case QEMU_OPTION_cdrom:
-                hd_filename[2] = optarg;
+                if (hd_filename[CDROM_DISK_POSITION]) {
+                    fprintf(stderr,
+                            "qemu: virtual device 'hd%c' for cdrom "
+                            "is already defined as %s\n",
+                            'a' + CDROM_DISK_POSITION,
+                            hd_filename[CDROM_DISK_POSITION] );
+                    break;
+                }
+                hd_filename[CDROM_DISK_POSITION] = optarg;
                 has_cdrom = 1;
                 break;
             case QEMU_OPTION_boot:
@@ -2944,7 +2980,7 @@ int main(int argc, char **argv)
     linux_boot = (kernel_filename != NULL);
 
     if ( !linux_boot && hd_filename[0] == '\0' &&
-         hd_filename[2] == '\0' && fd_filename[0] == '\0' )
+         hd_filename[CDROM_DISK_POSITION] == '\0' && fd_filename[0] == '\0' )
         help();
 
     /* boot to cd by default if no hard disk */
@@ -3074,59 +3110,55 @@ int main(int argc, char **argv)
     fprintf(logfile, "shared page at pfn:%lx, mfn: %lx\n", (nr_pages-1),
            (page_array[nr_pages - 1]));
 
-    /* we always create the cdrom drive, even if no disk is there */
     bdrv_init();
-    if (has_cdrom) {
-        int fd;
-        if ( (fd = open(hd_filename[2], O_RDONLY | O_BINARY)) < 0) {
-                hd_filename[2]=NULL;
-                bs_table[2]=NULL;
-                fprintf(logfile, "Could not open CD %s.\n", hd_filename[i]);
-        }
-        else {
-                close(fd);
-                bs_table[2] = bdrv_new("cdrom");
-                bdrv_set_type_hint(bs_table[2], BDRV_TYPE_CDROM);
-        }
-    }
+
+    shdev_init();
 
     /* open the virtual block devices */
     for(i = 0; i < MAX_DISKS; i++) {
         if (hd_filename[i]) {
-            if (!bs_table[i]) {
-                char buf[64];
+            if ((i == CDROM_DISK_POSITION) && has_cdrom) {
+                snprintf(buf, sizeof(buf), "cdrom");
+                dev_type = BDRV_TYPE_CDROM;
+            }
+            else {
                 snprintf(buf, sizeof(buf), "hd%c", i + 'a');
-                bs_table[i] = bdrv_new(buf);
+                dev_type = BDRV_TYPE_HD;
             }
+
+            bs_table[i] = bdrv_new(buf);
+
+            bdrv_set_type_hint(bs_table[i], dev_type);
+
+            if (bs_table[i]->removable)
+                shdev_report_device(bs_table[i], hd_filename[i]);
+
             if (bdrv_open(bs_table[i], hd_filename[i], snapshot) < 0) {
+                if (bs_table[i]->removable)
+                    continue;
+
                 fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
                         hd_filename[i]);
                 exit(1);
             }
+
             if (i == 0 && cyls != 0)
                 bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs);
         }
     }
 
-    /* we always create at least one floppy disk */
-    fd_table[0] = bdrv_new("fda");
-    bdrv_set_type_hint(fd_table[0], BDRV_TYPE_FLOPPY);
-
     for(i = 0; i < MAX_FD; i++) {
         if (fd_filename[i]) {
             if (!fd_table[i]) {
-                char buf[64];
                 snprintf(buf, sizeof(buf), "fd%c", i + 'a');
                 fd_table[i] = bdrv_new(buf);
                 bdrv_set_type_hint(fd_table[i], BDRV_TYPE_FLOPPY);
+                shdev_report_device(fd_table[i], fd_filename[i]);
             }
-            if (fd_filename[i] != '\0') {
-                if (bdrv_open(fd_table[i], fd_filename[i], snapshot) < 0) {
-                    fprintf(stderr, "qemu: could not open floppy disk image '%s'\n",
+
+            if (bdrv_open(fd_table[i], fd_filename[i], snapshot) < 0)
+                fprintf(stderr, "qemu: could not open floppy disk '%s'\n",
                             fd_filename[i]);
-                    exit(1);
-                }
-            }
         }
     }
 
diff -r dc213d745642 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h	Mon May 15 16:32:09 2006 +0100
+++ b/tools/ioemu/vl.h	Thu May 25 14:57:13 2006 -0600
@@ -1,8 +1,8 @@
 /*
  * QEMU System Emulator header
- * 
+ *
  * Copyright (c) 2003 Fabrice Bellard
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
@@ -37,9 +37,11 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/stat.h>
+#include <block_int.h>
 #include "audio/audio.h"
 #include "xenctrl.h"
 #include "xs.h"
+
 
 #ifndef O_LARGEFILE
 #define O_LARGEFILE 0
@@ -147,6 +149,8 @@ extern int graphic_depth;
 #define BIOS_SIZE ((256 + 64) * 1024)
 #endif
 
+#define CDROM_DISK_POSITION 2
+
 /* keyboard/mouse support */
 
 #define MOUSE_EVENT_LBUTTON 0x01
@@ -192,9 +196,9 @@ typedef void IOReadHandler(void *opaque,
 typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
 typedef int IOCanRWHandler(void *opaque);
 
-int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read, 
+int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read,
                              IOReadHandler *fd_read, void *opaque);
-int qemu_add_fd_event_read_handler(int fd, IOCanRWHandler *fd_can_read, 
+int qemu_add_fd_event_read_handler(int fd, IOCanRWHandler *fd_can_read,
                              IOReadHandler *fd_read, void *opaque);
 void qemu_del_fd_read_handler(int fd);
 
@@ -207,8 +211,8 @@ typedef void IOEventHandler(void *opaque
 
 typedef struct CharDriverState {
     int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
-    void (*chr_add_read_handler)(struct CharDriverState *s, 
-                                 IOCanRWHandler *fd_can_read, 
+    void (*chr_add_read_handler)(struct CharDriverState *s,
+                                 IOCanRWHandler *fd_can_read,
                                  IOReadHandler *fd_read, void *opaque);
     IOEventHandler *chr_event;
     void (*chr_send_event)(struct CharDriverState *chr, int event);
@@ -218,11 +222,11 @@ void qemu_chr_printf(CharDriverState *s,
 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);
 int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
 void qemu_chr_send_event(CharDriverState *s, int event);
-void qemu_chr_add_read_handler(CharDriverState *s, 
-                               IOCanRWHandler *fd_can_read, 
+void qemu_chr_add_read_handler(CharDriverState *s,
+                               IOCanRWHandler *fd_can_read,
                                IOReadHandler *fd_read, void *opaque);
 void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event);
-                               
+
 /* consoles */
 
 typedef struct DisplayState DisplayState;
@@ -250,10 +254,10 @@ typedef struct NetDriverState {
     int index; /* index number in QEMU */
     uint8_t macaddr[6];
     char ifname[16];
-    void (*send_packet)(struct NetDriverState *nd, 
+    void (*send_packet)(struct NetDriverState *nd,
                         const uint8_t *buf, int size);
-    void (*add_read_packet)(struct NetDriverState *nd, 
-                            IOCanRWHandler *fd_can_read, 
+    void (*add_read_packet)(struct NetDriverState *nd,
+                            IOCanRWHandler *fd_can_read,
                             IOReadHandler *fd_read, void *opaque);
     /* tun specific data */
     int fd;
@@ -264,7 +268,7 @@ extern NetDriverState nd_table[MAX_NICS]
 extern NetDriverState nd_table[MAX_NICS];
 
 void qemu_send_packet(NetDriverState *nd, const uint8_t *buf, int size);
-void qemu_add_read_packet(NetDriverState *nd, IOCanRWHandler *fd_can_read, 
+void qemu_add_read_packet(NetDriverState *nd, IOCanRWHandler *fd_can_read,
                           IOReadHandler *fd_read, void *opaque);
 
 /* timers */
@@ -361,8 +365,8 @@ typedef int LoadStateHandler(QEMUFile *f
 
 int qemu_loadvm(const char *filename);
 int qemu_savevm(const char *filename);
-int register_savevm(const char *idstr, 
-                    int instance_id, 
+int register_savevm(const char *idstr,
+                    int instance_id,
                     int version_id,
                     SaveStateHandler *save_state,
                     LoadStateHandler *load_state,
@@ -374,8 +378,6 @@ void port_e9_init(void);
 void port_e9_init(void);
 
 /* block.c */
-typedef struct BlockDriverState BlockDriverState;
-typedef struct BlockDriver BlockDriver;
 
 extern BlockDriver bdrv_raw;
 extern BlockDriver bdrv_cow;
@@ -385,7 +387,7 @@ extern BlockDriver bdrv_cloop;
 
 void bdrv_init(void);
 BlockDriver *bdrv_find_format(const char *format_name);
-int bdrv_create(BlockDriver *drv, 
+int bdrv_create(BlockDriver *drv,
                 const char *filename, int64_t size_in_sectors,
                 const char *backing_file, int flags);
 BlockDriverState *bdrv_new(const char *device_name);
@@ -394,9 +396,9 @@ int bdrv_open2(BlockDriverState *bs, con
 int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
                BlockDriver *drv);
 void bdrv_close(BlockDriverState *bs);
-int bdrv_read(BlockDriverState *bs, int64_t sector_num, 
+int bdrv_read(BlockDriverState *bs, int64_t sector_num,
               uint8_t *buf, int nb_sectors);
-int bdrv_write(BlockDriverState *bs, int64_t sector_num, 
+int bdrv_write(BlockDriverState *bs, int64_t sector_num,
                const uint8_t *buf, int nb_sectors);
 void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr);
 int bdrv_commit(BlockDriverState *bs);
@@ -406,10 +408,10 @@ void bdrv_set_boot_sector(BlockDriverSta
 #define BDRV_TYPE_CDROM  1
 #define BDRV_TYPE_FLOPPY 2
 
-void bdrv_set_geometry_hint(BlockDriverState *bs, 
+void bdrv_set_geometry_hint(BlockDriverState *bs,
                             int cyls, int heads, int secs);
 void bdrv_set_type_hint(BlockDriverState *bs, int type);
-void bdrv_get_geometry_hint(BlockDriverState *bs, 
+void bdrv_get_geometry_hint(BlockDriverState *bs,
                             int *pcyls, int *pheads, int *psecs);
 int bdrv_get_type_hint(BlockDriverState *bs);
 int bdrv_is_removable(BlockDriverState *bs);
@@ -417,15 +419,17 @@ int bdrv_is_inserted(BlockDriverState *b
 int bdrv_is_inserted(BlockDriverState *bs);
 int bdrv_is_locked(BlockDriverState *bs);
 void bdrv_set_locked(BlockDriverState *bs, int locked);
-void bdrv_set_change_cb(BlockDriverState *bs, 
+void bdrv_set_change_cb(BlockDriverState *bs,
                         void (*change_cb)(void *opaque), void *opaque);
 void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size);
 void bdrv_info(void);
-BlockDriverState *bdrv_find(const char *name);
+BlockDriverState *bdrv_find_bs(int (*it)(BlockDriverState *bs, void *opaque), void *opaque);
+BlockDriverState *bdrv_find_by_device(const char *name);
+BlockDriverState *bdrv_find_by_filename(const char *name);
 void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque);
 int bdrv_is_encrypted(BlockDriverState *bs);
 int bdrv_set_key(BlockDriverState *bs, const char *key);
-void bdrv_iterate_format(void (*it)(void *opaque, const char *name), 
+void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
                          void *opaque);
 const char *bdrv_get_device_name(BlockDriverState *bs);
 
@@ -441,9 +445,9 @@ typedef void (IOPortWriteFunc)(void *opa
 typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data);
 typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address);
 
-int register_ioport_read(int start, int length, int size, 
+int register_ioport_read(int start, int length, int size,
                          IOPortReadFunc *func, void *opaque);
-int register_ioport_write(int start, int length, int size, 
+int register_ioport_write(int start, int length, int size,
                           IOPortWriteFunc *func, void *opaque);
 void isa_unassign_ioport(int start, int length);
 
@@ -456,11 +460,11 @@ typedef struct PCIBus PCIBus;
 typedef struct PCIBus PCIBus;
 typedef struct PCIDevice PCIDevice;
 
-typedef void PCIConfigWriteFunc(PCIDevice *pci_dev, 
+typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
                                 uint32_t address, uint32_t data, int len);
-typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev, 
+typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev,
                                    uint32_t address, int len);
-typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num, 
+typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
                                 uint32_t addr, uint32_t size, int type);
 
 #define PCI_ADDRESS_SPACE_MEM		0x00
@@ -485,7 +489,7 @@ struct PCIDevice {
     int devfn;
     char name[64];
     PCIIORegion io_regions[PCI_NUM_REGIONS];
-    
+
     /* do not access the following fields */
     PCIConfigReadFunc *config_read;
     PCIConfigWriteFunc *config_write;
@@ -494,18 +498,18 @@ struct PCIDevice {
 
 PCIDevice *pci_register_device(PCIBus *bus, const char *name,
                                int instance_size, int devfn,
-                               PCIConfigReadFunc *config_read, 
+                               PCIConfigReadFunc *config_read,
                                PCIConfigWriteFunc *config_write);
 
-void pci_register_io_region(PCIDevice *pci_dev, int region_num, 
-                            uint32_t size, int type, 
+void pci_register_io_region(PCIDevice *pci_dev, int region_num,
+                            uint32_t size, int type,
                             PCIMapIORegionFunc *map_func);
 
 void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level);
 
-uint32_t pci_default_read_config(PCIDevice *d, 
+uint32_t pci_default_read_config(PCIDevice *d,
                                  uint32_t address, int len);
-void pci_default_write_config(PCIDevice *d, 
+void pci_default_write_config(PCIDevice *d,
                               uint32_t address, uint32_t val, int len);
 void generic_pci_save(QEMUFile* f, void *opaque);
 int generic_pci_load(QEMUFile* f, void *opaque, int version_id);
@@ -553,7 +557,7 @@ static inline void dpy_resize(DisplaySta
     s->dpy_resize(s, w, h);
 }
 
-int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
+int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
                    unsigned long vga_ram_offset, int vga_ram_size);
 void vga_update_display(void);
 void vga_invalidate_display(void);
@@ -564,9 +568,9 @@ void vnc_display_init(DisplayState *ds, 
                       long port, const char* connect);
 
 /* cirrus_vga.c */
-void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
+void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
                          unsigned long vga_ram_offset, int vga_ram_size);
-void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
+void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
                          unsigned long vga_ram_offset, int vga_ram_size);
 
 /* sdl.c */
@@ -612,7 +616,7 @@ extern BlockDriverState *fd_table[MAX_FD
 
 typedef struct fdctrl_t fdctrl_t;
 
-fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, 
+fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
                        uint32_t io_base,
                        BlockDriverState **fds);
 int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num);
@@ -783,9 +787,9 @@ int adb_request(ADBBusState *s, uint8_t 
                 const uint8_t *buf, int len);
 int adb_poll(ADBBusState *s, uint8_t *buf_out);
 
-ADBDevice *adb_register_device(ADBBusState *s, int devaddr, 
-                               ADBDeviceRequest *devreq, 
-                               ADBDeviceReset *devreset, 
+ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
+                               ADBDeviceRequest *devreq,
+                               ADBDeviceReset *devreset,
                                void *opaque);
 void adb_kbd_init(ADBBusState *bus);
 void adb_mouse_init(ADBBusState *bus);
@@ -796,6 +800,15 @@ int cuda_init(openpic_t *openpic, int ir
 int cuda_init(openpic_t *openpic, int irq);
 
 #endif /* defined(QEMU_TOOL) */
+
+/* shdev.h */
+
+int shdev_init(void);
+int shdev_report_device(BlockDriverState *bs, const char *name);
+void shdev_set_media_instance(BlockDriverState *bs);
+void shdev_eject_notice(BlockDriverState *bs);
+inline int shdev_media_check(BlockDriverState *bs);
+void do_info_shdev(void);
 
 /* monitor.c */
 void monitor_init(CharDriverState *hd, int show_banner);
@@ -804,6 +817,8 @@ void term_printf(const char *fmt, ...) _
 void term_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
 void term_flush(void);
 void term_print_help(void);
+void do_insert_request(void);
+void do_eject(int force, const char *device);
 
 /* readline.c */
 typedef void ReadLineFunc(void *opaque, const char *str);
