From: "Ross Maxfield" <rmaxfiel@novell.com>
To: xen-devel@lists.xensource.com
Subject: [PATCH][RFC] Sharing removable media patch
Date: Fri, 26 May 2006 11:28:06 -0600 [thread overview]
Message-ID: <4476E448.DD28.00D3.0@novell.com> (raw)
In-Reply-To: <44686ECF.DD28.00D3.0@novell.com>
[-- Attachment #1: Type: text/plain, Size: 4536 bytes --]
Attached is a patch that I created to make HVM virtual cdroms behave
more like their physical counterparts.
Problem: When cd media is ejected, and worse, replaced, the guest is
not made aware until the you enter the qemu monitor and type 'change
<device> <name>'. This 'change' command must also be done for each
guest that has access to the media, i.e., has the 'cdrom =' line its
config file. When a guest is not made aware of media changes then the
guest continues on the assumption that all is well returns previously
cached data for media not present, or worse, reads non-cached from the
new media believing that it is still the previous media.
Recognizing that the patch is large I will spend a moment explaining
the theory of operations. The objective was to get each guest to be
aware of media ejects and inerts regardless from which domain the event
occurred, including Dom0.
The foundation for this work is the creation of a very small amount of
memory shared between all guests. This shared memory contains a list of
shared removable media devices, as defined by the 'cdrom=' line that may
exist is each guest's config file. There is one entry in this shared
memory for each unique device name. Accompanying the device name is
media instance number. This instance number is incremented each time
media is ejected from any guest.
The current value of the instance number is stored in the
BlockDriverState structure when a guest is initialized. This instance
number kept by the guest is compared against the value in the shared
memory in the TEST_UNIT_READY routine and the cdrom read routine found
in qemu's ide.c. If the values are not equal then is is assumed that
the media has been ejected by another guest and a ASC_MEDIA_CHANGED
error is returned to each quest's routine that is polling for removable
media device status. If polling is not employed by the guest then the
media changed notification will occur on the next IO request and the
guest OS will respond appropriately.
In addition to comparing the guest's media instance number against the
value in shared memory the TEST_UNIT_READY routine checks the
accessibility of the media. It does so by opening the the device with
the O_NONBLOCK flag, clearing the flag with fcntl() and checking the
value returned by a read() from the device. Using O_NONBLOCK prevents
the automatic draw-in of the cd tray should it be ejected. If the guest
believes that the media should be present then TEST_UNIT_READY returns
ok, otherwise, it reports MEDIA_CHANGED and then MEDIA_NOT_PRESENT for
all following TEST_UNIT_READY until it determined that media is once
again present. This is determined by TEST_UNIT_READY when it believes
that media is not present and the open() and read() succeed.
When it is discovered that media has become present then qemu responds
essentially as if qemu's 'change' command had been entered at the qemu's
monitor screen. The device is opened and made available to the quest.
The guest's media polling routines discover the new media and respond
appropriately. Having the TEST_UNIT_READY check the media also allows
the guests to respond properly when media is ejected manually or from
Dom0.
This implementation is stateless meaning that there is nothing to
cleanup when a domain terminates, nicely or otherwise. The shared
memory is not created until there is at least one guest and is removed
when the last guest terminates, providing it did so nicely. Even if the
memory should not be freed when the last domain terminates, it is not
much memory and is never reallocated but simply reused by the next
guest(s).
It was suggested that xenstore be used in place of the shared memory.
After considering this it was decided to stay with the shared memory
approach because of the frequency at which the memory was accessed and
by the fact that it is not data that is managed or even interesting.
Also, there is no measurable difference in cd IO performance with this
implementation, nor any visible signs, i.e., no spinning up, lights
blinking, trays unexpectedly moving, etc.
This implementation does nothing to protect against simultaneous writes
to shared media. It is recognized that in the future there will need to
be a comprehensive solution for the management of shared removable
devices of all types. This patch simply satisfies the expectation that
when media is present, or not, each guest responds appropriately.
This patch applies to change set 10162.
Signed off by Ross Maxfield <rmaxfiel@novell.com>
[-- Attachment #2: cdroms.patch --]
[-- Type: application/octet-stream, Size: 42753 bytes --]
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);
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
next prev parent reply other threads:[~2006-05-26 17:28 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-05-15 17:55 Testing status of fully virtualized guests (Intel VT) on 64bit XEN unstable Ed Smith
2006-05-15 18:14 ` [PATCH] opps in blockback when missing media Ross Maxfield
2006-05-16 8:30 ` Keir Fraser
2006-05-26 17:28 ` Ross Maxfield [this message]
2006-05-26 18:52 ` [PATCH][RFC] Sharing removable media patch Ross Maxfield
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4476E448.DD28.00D3.0@novell.com \
--to=rmaxfiel@novell.com \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.