diff --git a/block.c b/block.c index ad5ee7a170d737f994fe64734f093547782f507f..aca5a6d282fb0d5a0f3e6d14fc22f83067e40735 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 0acac63b8776a98516d84e1a400057da4c354f11..71e87fc9e1d7ec768fc4bb2b22f1a859961c6ae2 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 cc37e7880b874cd0febac29ad791d6da84f1e283..f3787f256c5b11fa7c17926f9ceb82d4807f99d2 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: