diff --git a/block.c b/block.c index b68a8da09c1c80fc05ec1b1bd45830bf950b0027..e5cd23d34a376be0875ff1b1bd671068df5b11f7 100644 --- a/block.c +++ b/block.c @@ -1664,11 +1664,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 { @@ -1677,7 +1681,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 979781a12e8f69fd72f21950e258f4a9f6aa5ae4..e1070e9c344325af37ef5413476958d946e8262f 100644 --- a/block.h +++ b/block.h @@ -132,7 +132,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 6ad1d081a6d41e6e3ce2ef3a5c1da23d8464734b..9b93e7f678de9f1e149932fce46769f784dc9f49 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 @@ -1818,18 +1819,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: