.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
int cluster_size;
uint32_t removable;
uint64_t max_lba;
+ bool media_changed;
QEMUBH *bh;
char *version;
char *serial;
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)
.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);
.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),
.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(),
.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),
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*/