aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block.c9
-rw-r--r--block.h2
-rw-r--r--hw/ide.c26
3 files changed, 27 insertions, 10 deletions
diff --git a/block.c b/block.c
index ad5ee7a170..aca5a6d282 100644
--- a/block.c
+++ b/block.c
@@ -1566,11 +1566,15 @@ int bdrv_media_changed(BlockDriverState *bs)
/**
* If eject_flag is TRUE, eject the media. Otherwise, close the tray
*/
-void bdrv_eject(BlockDriverState *bs, int eject_flag)
+int bdrv_eject(BlockDriverState *bs, int eject_flag)
{
BlockDriver *drv = bs->drv;
int ret;
+ if (bs->locked) {
+ return -EBUSY;
+ }
+
if (!drv || !drv->bdrv_eject) {
ret = -ENOTSUP;
} else {
@@ -1579,7 +1583,10 @@ void bdrv_eject(BlockDriverState *bs, int eject_flag)
if (ret == -ENOTSUP) {
if (eject_flag)
bdrv_close(bs);
+ ret = 0;
}
+
+ return ret;
}
int bdrv_is_locked(BlockDriverState *bs)
diff --git a/block.h b/block.h
index 0acac63b87..71e87fc9e1 100644
--- a/block.h
+++ b/block.h
@@ -124,7 +124,7 @@ int bdrv_is_inserted(BlockDriverState *bs);
int bdrv_media_changed(BlockDriverState *bs);
int bdrv_is_locked(BlockDriverState *bs);
void bdrv_set_locked(BlockDriverState *bs, int locked);
-void bdrv_eject(BlockDriverState *bs, int eject_flag);
+int bdrv_eject(BlockDriverState *bs, int eject_flag);
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);
diff --git a/hw/ide.c b/hw/ide.c
index cc37e7880b..f3787f256c 100644
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -359,6 +359,7 @@
#define ASC_INCOMPATIBLE_FORMAT 0x30
#define ASC_MEDIUM_NOT_PRESENT 0x3a
#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39
+#define ASC_MEDIA_REMOVAL_PREVENTED 0x53
#define CFA_NO_ERROR 0x00
#define CFA_MISC_ERROR 0x09
@@ -1822,18 +1823,27 @@ static void ide_atapi_cmd(IDEState *s)
break;
case GPCMD_START_STOP_UNIT:
{
- int start, eject;
+ int start, eject, err = 0;
start = packet[4] & 1;
eject = (packet[4] >> 1) & 1;
- if (eject && !start) {
- /* eject the disk */
- bdrv_eject(s->bs, 1);
- } else if (eject && start) {
- /* close the tray */
- bdrv_eject(s->bs, 0);
+ if (eject) {
+ err = bdrv_eject(s->bs, !start);
+ }
+
+ switch (err) {
+ case 0:
+ ide_atapi_cmd_ok(s);
+ break;
+ case -EBUSY:
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ASC_MEDIA_REMOVAL_PREVENTED);
+ break;
+ default:
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ASC_MEDIUM_NOT_PRESENT);
+ break;
}
- ide_atapi_cmd_ok(s);
}
break;
case GPCMD_MECHANISM_STATUS: