scsi-disk: report media changed via unit attention sense codes

Building on the previous patch, this one adds a media change callback
to scsi-disk.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Paolo Bonzini 2011-09-13 16:26:06 +02:00 committed by Kevin Wolf
parent 3653d8c40e
commit 8a9c16f69e
3 changed files with 35 additions and 1 deletions

View File

@ -847,6 +847,11 @@ const struct SCSISense sense_code_RESET = {
.key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x00
};
/* Unit attention, No medium */
const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM = {
.key = UNIT_ATTENTION, .asc = 0x3a, .ascq = 0x00
};
/* Unit attention, Medium may have changed */
const struct SCSISense sense_code_MEDIUM_CHANGED = {
.key = UNIT_ATTENTION, .asc = 0x28, .ascq = 0x00

View File

@ -71,6 +71,7 @@ struct SCSIDiskState
int cluster_size;
uint32_t removable;
uint64_t max_lba;
bool media_changed;
QEMUBH *bh;
char *version;
char *serial;
@ -1198,7 +1199,21 @@ static void scsi_destroy(SCSIDevice *dev)
static void scsi_cd_change_media_cb(void *opaque, bool load)
{
((SCSIDiskState *)opaque)->tray_open = !load;
SCSIDiskState *s = opaque;
/*
* When a CD gets changed, we have to report an ejected state and
* then a loaded state to guests so that they detect tray
* open/close and media change events. Guests that do not use
* GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close
* states rely on this behavior.
*
* media_changed governs the state machine used for unit attention
* report. media_event is used by GET EVENT STATUS NOTIFICATION.
*/
s->media_changed = load;
s->tray_open = !load;
s->qdev.unit_attention = SENSE_CODE(UNIT_ATTENTION_NO_MEDIUM);
}
static bool scsi_cd_is_tray_open(void *opaque)
@ -1217,6 +1232,15 @@ static const BlockDevOps scsi_cd_block_ops = {
.is_medium_locked = scsi_cd_is_medium_locked,
};
static void scsi_disk_unit_attention_reported(SCSIDevice *dev)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
if (s->media_changed) {
s->media_changed = false;
s->qdev.unit_attention = SENSE_CODE(MEDIUM_CHANGED);
}
}
static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
@ -1329,6 +1353,7 @@ static SCSIDeviceInfo scsi_disk_info[] = {
.init = scsi_hd_initfn,
.destroy = scsi_destroy,
.alloc_req = scsi_new_request,
.unit_attention_reported = scsi_disk_unit_attention_reported,
.qdev.props = (Property[]) {
DEFINE_SCSI_DISK_PROPERTIES(),
DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
@ -1343,6 +1368,7 @@ static SCSIDeviceInfo scsi_disk_info[] = {
.init = scsi_cd_initfn,
.destroy = scsi_destroy,
.alloc_req = scsi_new_request,
.unit_attention_reported = scsi_disk_unit_attention_reported,
.qdev.props = (Property[]) {
DEFINE_SCSI_DISK_PROPERTIES(),
DEFINE_PROP_END_OF_LIST(),
@ -1356,6 +1382,7 @@ static SCSIDeviceInfo scsi_disk_info[] = {
.init = scsi_disk_initfn,
.destroy = scsi_destroy,
.alloc_req = scsi_new_request,
.unit_attention_reported = scsi_disk_unit_attention_reported,
.qdev.props = (Property[]) {
DEFINE_SCSI_DISK_PROPERTIES(),
DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),

View File

@ -161,6 +161,8 @@ extern const struct SCSISense sense_code_IO_ERROR;
extern const struct SCSISense sense_code_I_T_NEXUS_LOSS;
/* Command aborted, Logical Unit failure */
extern const struct SCSISense sense_code_LUN_FAILURE;
/* LUN not ready, Medium not present */
extern const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM;
/* Unit attention, Power on, reset or bus device reset occurred */
extern const struct SCSISense sense_code_RESET;
/* Unit attention, Medium may have changed*/