qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 0/3] ide/scsi: add support for CD-ROM EjectRequest


From: Paolo Bonzini
Subject: [Qemu-devel] [PATCH 0/3] ide/scsi: add support for CD-ROM EjectRequest
Date: Mon, 26 Sep 2011 13:45:17 +0200

Recent versions of udev always keep the tray locked so that the kernel
can observe "eject request" events (aka tray button presses).  Add
support for such events in the ATAPI and SCSI cd drive device models.

The SCSI part depends on the twelve patches at

    http://thread.gmane.org/gmane.comp.emulators.qemu/118126

This behavior of udev creates other problems.  In particular, we should
add an event for "tray opened" so that, after issuing a "change" command,
management can try polling until the guests actually reacts to an eject
monitor command (and reissue the command after the tray has been opened).
However, these patches at least makes it possible to do a manual two-step
eject+change sequence.

Paolo Bonzini (3):
  block: add eject request callback
  atapi: implement eject requests
  scsi-disk: implement eject requests

 block.c        |    7 +++++++
 block.h        |    7 +++++++
 blockdev.c     |    8 +++++---
 hw/ide/atapi.c |   11 ++++++++---
 hw/ide/core.c  |   13 +++++++++++++
 hw/scsi-disk.c |   24 +++++++++++++++++++++---
 6 files changed, 61 insertions(+), 9 deletions(-)

-- 
1.7.6

>From e9e12ca149527267e0cc07faaf4ccabc6c6d2e9d Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <address@hidden>
Date: Tue, 20 Sep 2011 16:48:52 +0200
Subject: [PATCH 1/3] block: add eject request callback

The callback is triggered by the eject monitor command when the
tray is closed & locked.

Signed-off-by: Paolo Bonzini <address@hidden>
---
 block.c    |    7 +++++++
 block.h    |    7 +++++++
 blockdev.c |    8 +++++---
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/block.c b/block.c
index e3fe97f..4f463e1 100644
--- a/block.c
+++ b/block.c
@@ -819,6 +819,13 @@ bool bdrv_dev_has_removable_media(BlockDriverState *bs)
     return !bs->dev || (bs->dev_ops && bs->dev_ops->change_media_cb);
 }
 
+void bdrv_dev_eject_request(BlockDriverState *bs, bool force)
+{
+    if (bs->dev_ops && bs->dev_ops->eject_request_cb) {
+        bs->dev_ops->eject_request_cb(bs->dev_opaque, force);
+    }
+}
+
 bool bdrv_dev_is_tray_open(BlockDriverState *bs)
 {
     if (bs->dev_ops && bs->dev_ops->is_tray_open) {
diff --git a/block.h b/block.h
index 16bfa0a..f4e3d48 100644
--- a/block.h
+++ b/block.h
@@ -39,6 +39,12 @@ typedef struct BlockDevOps {
      */
     void (*change_media_cb)(void *opaque, bool load);
     /*
+     * Runs when an eject request is issued from the monitor, the tray
+     * is closed, and the medium is locked.
+     * Device models with removable media must implement this callback.
+     */
+    void (*eject_request_cb)(void *opaque, bool force);
+    /*
      * Is the virtual tray open?
      * Device models implement this only when the device has a tray.
      */
@@ -106,6 +112,7 @@ void bdrv_detach_dev(BlockDriverState *bs, void *dev);
 void *bdrv_get_attached_dev(BlockDriverState *bs);
 void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops,
                       void *opaque);
+void bdrv_dev_eject_request(BlockDriverState *bs, bool force);
 bool bdrv_dev_has_removable_media(BlockDriverState *bs);
 bool bdrv_dev_is_tray_open(BlockDriverState *bs);
 bool bdrv_dev_is_medium_locked(BlockDriverState *bs);
diff --git a/blockdev.c b/blockdev.c
index 0827bf7..1679c9f 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -635,9 +635,11 @@ static int eject_device(Monitor *mon, BlockDriverState 
*bs, int force)
         qerror_report(QERR_DEVICE_NOT_REMOVABLE, bdrv_get_device_name(bs));
         return -1;
     }
-    if (!force && !bdrv_dev_is_tray_open(bs)
-        && bdrv_dev_is_medium_locked(bs)) {
-        qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
+    if (bdrv_dev_is_medium_locked(bs) && !bdrv_dev_is_tray_open(bs)) {
+        bdrv_dev_eject_request(bs, force);
+        if (!force) {
+            qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
+       }
         return -1;
     }
     bdrv_close(bs);
-- 
1.7.6


>From 48ceff104d07a9e9d89196f40750667b9287a840 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <address@hidden>
Date: Tue, 20 Sep 2011 16:56:56 +0200
Subject: [PATCH 2/3] atapi: implement eject requests

Use the new callback to properly report eject requests.

Also forcibly unlock the tray when doing an "eject -f", otherwise
the subsequent "change" command would fail due to finding an open
but locked tray.

Signed-off-by: Paolo Bonzini <address@hidden>
---
 hw/ide/atapi.c |   11 ++++++++---
 hw/ide/core.c  |   13 +++++++++++++
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index c6eb8f0..a1e1bc4 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -516,9 +516,14 @@ static unsigned int event_status_media(IDEState *s,
 
     /* Event notification descriptor */
     event_code = MEC_NO_CHANGE;
-    if (media_status != MS_TRAY_OPEN && s->events.new_media) {
-        event_code = MEC_NEW_MEDIA;
-        s->events.new_media = false;
+    if (media_status != MS_TRAY_OPEN) {
+       if (s->events.new_media) {
+            event_code = MEC_NEW_MEDIA;
+            s->events.new_media = false;
+        } else if (s->events.eject_request) {
+            event_code = MEC_EJECT_REQUESTED;
+            s->events.eject_request = false;
+       }
     }
 
     buf[4] = event_code;
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 72f926c..e4c82a1 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -802,6 +802,18 @@ static void ide_cd_change_cb(void *opaque, bool load)
      */
     s->cdrom_changed = 1;
     s->events.new_media = true;
+    s->events.eject_request = false;
+    ide_set_irq(s->bus);
+}
+
+static void ide_cd_eject_request_cb(void *opaque, bool force)
+{
+    IDEState *s = opaque;
+
+    s->events.eject_request = true;
+    if (force) {
+        s->tray_locked = false;
+    }
     ide_set_irq(s->bus);
 }
 
@@ -1809,6 +1821,7 @@ static bool ide_cd_is_medium_locked(void *opaque)
 
 static const BlockDevOps ide_cd_block_ops = {
     .change_media_cb = ide_cd_change_cb,
+    .eject_request_cb = ide_cd_eject_request_cb,
     .is_tray_open = ide_cd_is_tray_open,
     .is_medium_locked = ide_cd_is_medium_locked,
 };
-- 
1.7.6


>From ce9bb21bc1ae827a3e2412b6ae547189fa889b91 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <address@hidden>
Date: Tue, 20 Sep 2011 16:57:04 +0200
Subject: [PATCH 3/3] scsi-disk: implement eject requests

The logic is exactly the same as for the IDE CD-ROM.

Signed-off-by: Paolo Bonzini <address@hidden>
---
 hw/scsi-disk.c |   24 +++++++++++++++++++++---
 1 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 7b008cc..b24ebe6 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -74,6 +74,7 @@ struct SCSIDiskState
     uint64_t max_lba;
     bool media_changed;
     bool new_media;
+    bool eject_requested;
     QEMUBH *bh;
     char *version;
     char *serial;
@@ -732,9 +733,14 @@ static int scsi_event_status_media(SCSIDiskState *s, 
uint8_t *outbuf)
 
     /* Event notification descriptor */
     event_code = MEC_NO_CHANGE;
-    if (media_status != MS_TRAY_OPEN && s->new_media) {
-        event_code = MEC_NEW_MEDIA;
-        s->new_media = false;
+    if (media_status != MS_TRAY_OPEN) {
+        if (s->new_media) {
+            event_code = MEC_NEW_MEDIA;
+            s->new_media = false;
+        } else if (s->eject_requested) {
+            event_code = MEC_EJECT_REQUESTED;
+            s->eject_requested = false;
+        }
     }
 
     outbuf[0] = event_code;
@@ -1540,6 +1546,17 @@ static void scsi_cd_change_media_cb(void *opaque, bool 
load)
     s->tray_open = !load;
     s->qdev.unit_attention = SENSE_CODE(UNIT_ATTENTION_NO_MEDIUM);
     s->new_media = true;
+    s->eject_requested = false;
+}
+
+static void scsi_cd_eject_request_cb(void *opaque, bool force)
+{
+    SCSIDiskState *s = opaque;
+
+    s->eject_requested = true;
+    if (force) {
+        s->tray_locked = false;
+    }
 }
 
 static bool scsi_cd_is_tray_open(void *opaque)
@@ -1554,6 +1571,7 @@ static bool scsi_cd_is_medium_locked(void *opaque)
 
 static const BlockDevOps scsi_cd_block_ops = {
     .change_media_cb = scsi_cd_change_media_cb,
+    .eject_request_cb = scsi_cd_eject_request_cb,
     .is_tray_open = scsi_cd_is_tray_open,
     .is_medium_locked = scsi_cd_is_medium_locked,
 };
-- 
1.7.6




reply via email to

[Prev in Thread] Current Thread [Next in Thread]