qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/10] Block patches
@ 2011-04-13 12:05 Kevin Wolf
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 01/10] docs: Describe zero data clusters in QED specification Kevin Wolf
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Kevin Wolf @ 2011-04-13 12:05 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

The following changes since commit 9df38c47d01eb1fd7eb9d60ac70a4170e638b4a2:

  target-arm: Detect tininess before rounding for FP operations (2011-04-12 23:33:33 +0200)

are available in the git repository at:
  git://repo.or.cz/qemu/kevin.git for-anthony

Amit Shah (7):
      atapi: Drives can be locked without media present
      atapi: Report correct errors on guest eject request
      atapi: Allow GET_EVENT_STATUS_NOTIFICATION after media change
      atapi: Move GET_EVENT_STATUS_NOTIFICATION command handling to its own function
      atapi: GESN: Use structs for commonly-used field types
      atapi: GESN: Standardise event response handling for future additions
      atapi: GESN: implement 'media' subcommand

Anthony Liguori (1):
      qed: Add support for zero clusters

Mitnick Lyu (1):
      vpc.c: Use get_option_parameter() does the search

Stefan Hajnoczi (1):
      docs: Describe zero data clusters in QED specification

 block/qed-check.c       |    5 +-
 block/qed-cluster.c     |   31 +++++---
 block/qed.c             |   21 ++++-
 block/qed.h             |   26 ++++++
 block/vpc.c             |    8 +--
 docs/specs/qed_spec.txt |    8 ++
 hw/ide/core.c           |  204 ++++++++++++++++++++++++++++++++++++++++-------
 hw/ide/internal.h       |    6 ++
 8 files changed, 258 insertions(+), 51 deletions(-)

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 01/10] docs: Describe zero data clusters in QED specification
  2011-04-13 12:05 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
@ 2011-04-13 12:05 ` Kevin Wolf
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 02/10] qed: Add support for zero clusters Kevin Wolf
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Kevin Wolf @ 2011-04-13 12:05 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>

Zero data clusters are a space-efficient way of storing zeroed regions
of the image.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 docs/specs/qed_spec.txt |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/docs/specs/qed_spec.txt b/docs/specs/qed_spec.txt
index 1d5fa87..7982e05 100644
--- a/docs/specs/qed_spec.txt
+++ b/docs/specs/qed_spec.txt
@@ -89,6 +89,7 @@ L1, L2, and data cluster offsets must be aligned to header.cluster_size.  The fo
 
 ===Data cluster offsets===
 * 0 - unallocated.  The data cluster is not yet allocated.
+* 1 - zero.  The data cluster contents are all zeroes and no cluster is allocated.
 
 Future format extensions may wish to store per-offset information.  The least significant 12 bits of an offset are reserved for this purpose and must be set to zero.  Image files with cluster_size > 2^12 will have more unused bits which should also be zeroed.
 
@@ -97,6 +98,13 @@ Reads to an unallocated area of the image file access the backing file.  If ther
 
 Writes to an unallocated area cause a new data clusters to be allocated, and a new L2 table if that is also unallocated.  The new data cluster is populated with data from the backing file (or zeroes if no backing file) and the data being written.
 
+===Zero data clusters===
+Zero data clusters are a space-efficient way of storing zeroed regions of the image.
+
+Reads to a zero data cluster produce zeroes.  Note that the difference between an unallocated and a zero data cluster is that zero data clusters stop the reading of contents from the backing file.
+
+Writes to a zero data cluster cause a new data cluster to be allocated.  The new data cluster is populated with zeroes and the data being written.
+
 ===Logical offset translation===
 Logical offsets are translated into cluster offsets as follows:
 
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 02/10] qed: Add support for zero clusters
  2011-04-13 12:05 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 01/10] docs: Describe zero data clusters in QED specification Kevin Wolf
@ 2011-04-13 12:05 ` Kevin Wolf
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 03/10] atapi: Drives can be locked without media present Kevin Wolf
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Kevin Wolf @ 2011-04-13 12:05 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Anthony Liguori <aliguori@us.ibm.com>

Zero clusters are similar to unallocated clusters except instead of reading
their value from a backing file when one is available, the cluster is always
read as zero.

This implements read support only.  At this stage, QED will never write a
zero cluster.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qed-check.c   |    5 +++--
 block/qed-cluster.c |   31 +++++++++++++++++++++----------
 block/qed.c         |   21 ++++++++++++++++-----
 block/qed.h         |   26 ++++++++++++++++++++++++++
 4 files changed, 66 insertions(+), 17 deletions(-)

diff --git a/block/qed-check.c b/block/qed-check.c
index 4600932..ea4ebc8 100644
--- a/block/qed-check.c
+++ b/block/qed-check.c
@@ -72,7 +72,8 @@ static unsigned int qed_check_l2_table(QEDCheck *check, QEDTable *table)
     for (i = 0; i < s->table_nelems; i++) {
         uint64_t offset = table->offsets[i];
 
-        if (!offset) {
+        if (qed_offset_is_unalloc_cluster(offset) ||
+            qed_offset_is_zero_cluster(offset)) {
             continue;
         }
 
@@ -111,7 +112,7 @@ static int qed_check_l1_table(QEDCheck *check, QEDTable *table)
         unsigned int num_invalid_l2;
         uint64_t offset = table->offsets[i];
 
-        if (!offset) {
+        if (qed_offset_is_unalloc_cluster(offset)) {
             continue;
         }
 
diff --git a/block/qed-cluster.c b/block/qed-cluster.c
index 0ec864b..3e19ad1 100644
--- a/block/qed-cluster.c
+++ b/block/qed-cluster.c
@@ -23,7 +23,8 @@
  * @n:              Maximum number of clusters
  * @offset:         Set to first cluster offset
  *
- * This function scans tables for contiguous allocated or free clusters.
+ * This function scans tables for contiguous clusters.  A contiguous run of
+ * clusters may be allocated, unallocated, or zero.
  */
 static unsigned int qed_count_contiguous_clusters(BDRVQEDState *s,
                                                   QEDTable *table,
@@ -38,9 +39,14 @@ static unsigned int qed_count_contiguous_clusters(BDRVQEDState *s,
     *offset = last;
 
     for (i = index + 1; i < end; i++) {
-        if (last == 0) {
-            /* Counting free clusters */
-            if (table->offsets[i] != 0) {
+        if (qed_offset_is_unalloc_cluster(last)) {
+            /* Counting unallocated clusters */
+            if (!qed_offset_is_unalloc_cluster(table->offsets[i])) {
+                break;
+            }
+        } else if (qed_offset_is_zero_cluster(last)) {
+            /* Counting zero clusters */
+            if (!qed_offset_is_zero_cluster(table->offsets[i])) {
                 break;
             }
         } else {
@@ -87,14 +93,19 @@ static void qed_find_cluster_cb(void *opaque, int ret)
     n = qed_count_contiguous_clusters(s, request->l2_table->table,
                                       index, n, &offset);
 
-    ret = offset ? QED_CLUSTER_FOUND : QED_CLUSTER_L2;
-    len = MIN(find_cluster_cb->len, n * s->header.cluster_size -
-              qed_offset_into_cluster(s, find_cluster_cb->pos));
-
-    if (offset && !qed_check_cluster_offset(s, offset)) {
+    if (qed_offset_is_unalloc_cluster(offset)) {
+        ret = QED_CLUSTER_L2;
+    } else if (qed_offset_is_zero_cluster(offset)) {
+        ret = QED_CLUSTER_ZERO;
+    } else if (qed_check_cluster_offset(s, offset)) {
+        ret = QED_CLUSTER_FOUND;
+    } else {
         ret = -EINVAL;
     }
 
+    len = MIN(find_cluster_cb->len, n * s->header.cluster_size -
+              qed_offset_into_cluster(s, find_cluster_cb->pos));
+
 out:
     find_cluster_cb->cb(find_cluster_cb->opaque, ret, offset, len);
     qemu_free(find_cluster_cb);
@@ -132,7 +143,7 @@ void qed_find_cluster(BDRVQEDState *s, QEDRequest *request, uint64_t pos,
     len = MIN(len, (((pos >> s->l1_shift) + 1) << s->l1_shift) - pos);
 
     l2_offset = s->l1_table->offsets[qed_l1_index(s, pos)];
-    if (!l2_offset) {
+    if (qed_offset_is_unalloc_cluster(l2_offset)) {
         cb(opaque, QED_CLUSTER_L1, 0, len);
         return;
     }
diff --git a/block/qed.c b/block/qed.c
index 75ae244..c8c5930 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -573,7 +573,7 @@ static void qed_is_allocated_cb(void *opaque, int ret, uint64_t offset, size_t l
 {
     QEDIsAllocatedCB *cb = opaque;
     *cb->pnum = len / BDRV_SECTOR_SIZE;
-    cb->is_allocated = ret == QED_CLUSTER_FOUND;
+    cb->is_allocated = (ret == QED_CLUSTER_FOUND || ret == QED_CLUSTER_ZERO);
 }
 
 static int bdrv_qed_is_allocated(BlockDriverState *bs, int64_t sector_num,
@@ -745,7 +745,10 @@ static void qed_copy_from_backing_file(BDRVQEDState *s, uint64_t pos,
  * @table:          L2 table
  * @index:          First cluster index
  * @n:              Number of contiguous clusters
- * @cluster:        First cluster byte offset in image file
+ * @cluster:        First cluster offset
+ *
+ * The cluster offset may be an allocated byte offset in the image file, the
+ * zero cluster marker, or the unallocated cluster marker.
  */
 static void qed_update_l2_table(BDRVQEDState *s, QEDTable *table, int index,
                                 unsigned int n, uint64_t cluster)
@@ -753,7 +756,10 @@ static void qed_update_l2_table(BDRVQEDState *s, QEDTable *table, int index,
     int i;
     for (i = index; i < index + n; i++) {
         table->offsets[i] = cluster;
-        cluster += s->header.cluster_size;
+        if (!qed_offset_is_unalloc_cluster(cluster) &&
+            !qed_offset_is_zero_cluster(cluster)) {
+            cluster += s->header.cluster_size;
+        }
     }
 }
 
@@ -1075,6 +1081,7 @@ static void qed_aio_write_data(void *opaque, int ret,
 
     case QED_CLUSTER_L2:
     case QED_CLUSTER_L1:
+    case QED_CLUSTER_ZERO:
         qed_aio_write_alloc(acb, len);
         break;
 
@@ -1114,8 +1121,12 @@ static void qed_aio_read_data(void *opaque, int ret,
 
     qemu_iovec_copy(&acb->cur_qiov, acb->qiov, acb->qiov_offset, len);
 
-    /* Handle backing file and unallocated sparse hole reads */
-    if (ret != QED_CLUSTER_FOUND) {
+    /* Handle zero cluster and backing file reads */
+    if (ret == QED_CLUSTER_ZERO) {
+        qemu_iovec_memset(&acb->cur_qiov, 0, acb->cur_qiov.size);
+        qed_aio_next_io(acb, 0);
+        return;
+    } else if (ret != QED_CLUSTER_FOUND) {
         qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov,
                               qed_aio_next_io, acb);
         return;
diff --git a/block/qed.h b/block/qed.h
index 2925e37..3e1ab84 100644
--- a/block/qed.h
+++ b/block/qed.h
@@ -161,6 +161,7 @@ typedef struct {
 
 enum {
     QED_CLUSTER_FOUND,         /* cluster found */
+    QED_CLUSTER_ZERO,          /* zero cluster found */
     QED_CLUSTER_L2,            /* cluster missing in L2 */
     QED_CLUSTER_L1,            /* cluster missing in L1 */
 };
@@ -298,4 +299,29 @@ static inline bool qed_check_table_offset(BDRVQEDState *s, uint64_t offset)
            qed_check_cluster_offset(s, end_offset);
 }
 
+static inline bool qed_offset_is_cluster_aligned(BDRVQEDState *s,
+                                                 uint64_t offset)
+{
+    if (qed_offset_into_cluster(s, offset)) {
+        return false;
+    }
+    return true;
+}
+
+static inline bool qed_offset_is_unalloc_cluster(uint64_t offset)
+{
+    if (offset == 0) {
+        return true;
+    }
+    return false;
+}
+
+static inline bool qed_offset_is_zero_cluster(uint64_t offset)
+{
+    if (offset == 1) {
+        return true;
+    }
+    return false;
+}
+
 #endif /* BLOCK_QED_H */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 03/10] atapi: Drives can be locked without media present
  2011-04-13 12:05 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 01/10] docs: Describe zero data clusters in QED specification Kevin Wolf
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 02/10] qed: Add support for zero clusters Kevin Wolf
@ 2011-04-13 12:05 ` Kevin Wolf
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 04/10] atapi: Report correct errors on guest eject request Kevin Wolf
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Kevin Wolf @ 2011-04-13 12:05 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Amit Shah <amit.shah@redhat.com>

Drivers are free to lock drives without any media present.  Such a
condition should not result in an error condition.

See Table 341 in MMC-5 spec for details.

Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 hw/ide/core.c |    9 ++-------
 1 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index c11d457..a290142 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1230,13 +1230,8 @@ static void ide_atapi_cmd(IDEState *s)
         ide_atapi_cmd_reply(s, 18, max_len);
         break;
     case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
-        if (bdrv_is_inserted(s->bs)) {
-            bdrv_set_locked(s->bs, packet[4] & 1);
-            ide_atapi_cmd_ok(s);
-        } else {
-            ide_atapi_cmd_error(s, SENSE_NOT_READY,
-                                ASC_MEDIUM_NOT_PRESENT);
-        }
+        bdrv_set_locked(s->bs, packet[4] & 1);
+        ide_atapi_cmd_ok(s);
         break;
     case GPCMD_READ_10:
     case GPCMD_READ_12:
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 04/10] atapi: Report correct errors on guest eject request
  2011-04-13 12:05 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
                   ` (2 preceding siblings ...)
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 03/10] atapi: Drives can be locked without media present Kevin Wolf
@ 2011-04-13 12:05 ` Kevin Wolf
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 05/10] atapi: Allow GET_EVENT_STATUS_NOTIFICATION after media change Kevin Wolf
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Kevin Wolf @ 2011-04-13 12:05 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Amit Shah <amit.shah@redhat.com>

Table 629 of the MMC-5 spec mentions two different error conditions when
a CDROM eject is requested: a) while a disc is inserted and b) while a
disc is not inserted.

Ensure we return the appropriate error for the present condition of the
drive and disc status.

Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 hw/ide/core.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index a290142..b5de22e 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1304,7 +1304,7 @@ static void ide_atapi_cmd(IDEState *s)
         break;
     case GPCMD_START_STOP_UNIT:
         {
-            int start, eject, err = 0;
+            int start, eject, sense, err = 0;
             start = packet[4] & 1;
             eject = (packet[4] >> 1) & 1;
 
@@ -1317,7 +1317,11 @@ static void ide_atapi_cmd(IDEState *s)
                 ide_atapi_cmd_ok(s);
                 break;
             case -EBUSY:
-                ide_atapi_cmd_error(s, SENSE_NOT_READY,
+                sense = SENSE_NOT_READY;
+                if (bdrv_is_inserted(s->bs)) {
+                    sense = SENSE_ILLEGAL_REQUEST;
+                }
+                ide_atapi_cmd_error(s, sense,
                                     ASC_MEDIA_REMOVAL_PREVENTED);
                 break;
             default:
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 05/10] atapi: Allow GET_EVENT_STATUS_NOTIFICATION after media change
  2011-04-13 12:05 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
                   ` (3 preceding siblings ...)
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 04/10] atapi: Report correct errors on guest eject request Kevin Wolf
@ 2011-04-13 12:05 ` Kevin Wolf
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 06/10] atapi: Move GET_EVENT_STATUS_NOTIFICATION command handling to its own function Kevin Wolf
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Kevin Wolf @ 2011-04-13 12:05 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Amit Shah <amit.shah@redhat.com>

After a media change, the only commands allowed from the guest were
REQUEST_SENSE and INQUIRY.  The guest may also issue
GET_EVENT_STATUS_NOTIFICATION commands to get media
changed notification.

Signed-off-by: Amit Shah <amit.shah@redhat.com>
Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 hw/ide/core.c |   20 ++++++++++++++------
 1 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index b5de22e..f0da95d 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1102,13 +1102,21 @@ static void ide_atapi_cmd(IDEState *s)
         printf("\n");
     }
 #endif
-    /* If there's a UNIT_ATTENTION condition pending, only
-       REQUEST_SENSE and INQUIRY commands are allowed to complete. */
+    /*
+     * If there's a UNIT_ATTENTION condition pending, only
+     * REQUEST_SENSE, INQUIRY, GET_CONFIGURATION and
+     * GET_EVENT_STATUS_NOTIFICATION commands are allowed to complete.
+     * MMC-5, section 4.1.6.1 lists only these commands being allowed
+     * to complete, with other commands getting a CHECK condition
+     * response unless a higher priority status, defined by the drive
+     * here, is pending.
+     */
     if (s->sense_key == SENSE_UNIT_ATTENTION &&
-	s->io_buffer[0] != GPCMD_REQUEST_SENSE &&
-	s->io_buffer[0] != GPCMD_INQUIRY) {
-	ide_atapi_cmd_check_status(s);
-	return;
+        s->io_buffer[0] != GPCMD_REQUEST_SENSE &&
+        s->io_buffer[0] != GPCMD_INQUIRY &&
+        s->io_buffer[0] != GPCMD_GET_EVENT_STATUS_NOTIFICATION) {
+        ide_atapi_cmd_check_status(s);
+        return;
     }
     switch(s->io_buffer[0]) {
     case GPCMD_TEST_UNIT_READY:
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 06/10] atapi: Move GET_EVENT_STATUS_NOTIFICATION command handling to its own function
  2011-04-13 12:05 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
                   ` (4 preceding siblings ...)
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 05/10] atapi: Allow GET_EVENT_STATUS_NOTIFICATION after media change Kevin Wolf
@ 2011-04-13 12:05 ` Kevin Wolf
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 07/10] atapi: GESN: Use structs for commonly-used field types Kevin Wolf
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Kevin Wolf @ 2011-04-13 12:05 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Amit Shah <amit.shah@redhat.com>

This makes the code more readable.

Also, there's a block like:

if () {
  ...
} else {
  ...
}

Split that into

if () {
  ...
  return;
}
...

Signed-off-by: Amit Shah <amit.shah@redhat.com>
Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 hw/ide/core.c |   37 ++++++++++++++++++++++++-------------
 1 files changed, 24 insertions(+), 13 deletions(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index f0da95d..4e4ade2 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1084,6 +1084,29 @@ static int ide_dvd_read_structure(IDEState *s, int format,
     }
 }
 
+static void handle_get_event_status_notification(IDEState *s,
+                                                 uint8_t *buf,
+                                                 const uint8_t *packet)
+{
+    unsigned int max_len;
+
+    max_len = ube16_to_cpu(packet + 7);
+
+    if (!(packet[1] & 0x01)) { /* asynchronous mode */
+        /* Only polling is supported, asynchronous mode is not. */
+        ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+                            ASC_INV_FIELD_IN_CMD_PACKET);
+        return;
+    }
+
+    /* polling */
+    /* We don't support any event class (yet). */
+    cpu_to_ube16(buf, 0x00); /* No event descriptor returned */
+    buf[2] = 0x80;           /* No Event Available (NEA) */
+    buf[3] = 0x00;           /* Empty supported event classes */
+    ide_atapi_cmd_reply(s, 4, max_len);
+}
+
 static void ide_atapi_cmd(IDEState *s)
 {
     const uint8_t *packet;
@@ -1529,19 +1552,7 @@ static void ide_atapi_cmd(IDEState *s)
             break;
         }
     case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
-        max_len = ube16_to_cpu(packet + 7);
-
-        if (packet[1] & 0x01) { /* polling */
-            /* We don't support any event class (yet). */
-            cpu_to_ube16(buf, 0x00); /* No event descriptor returned */
-            buf[2] = 0x80;           /* No Event Available (NEA) */
-            buf[3] = 0x00;           /* Empty supported event classes */
-            ide_atapi_cmd_reply(s, 4, max_len);
-        } else { /* asynchronous mode */
-            /* Only polling is supported, asynchronous mode is not. */
-            ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
-                                ASC_INV_FIELD_IN_CMD_PACKET);
-        }
+        handle_get_event_status_notification(s, buf, packet);
         break;
     default:
         ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 07/10] atapi: GESN: Use structs for commonly-used field types
  2011-04-13 12:05 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
                   ` (5 preceding siblings ...)
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 06/10] atapi: Move GET_EVENT_STATUS_NOTIFICATION command handling to its own function Kevin Wolf
@ 2011-04-13 12:05 ` Kevin Wolf
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 08/10] atapi: GESN: Standardise event response handling for future additions Kevin Wolf
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Kevin Wolf @ 2011-04-13 12:05 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Amit Shah <amit.shah@redhat.com>

Instead of using magic numbers, use structs that are more descriptive of
the fields being used.

Signed-off-by: Amit Shah <amit.shah@redhat.com>
Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 hw/ide/core.c |   16 ++++++++++++++--
 1 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 4e4ade2..f976947 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1088,11 +1088,23 @@ static void handle_get_event_status_notification(IDEState *s,
                                                  uint8_t *buf,
                                                  const uint8_t *packet)
 {
+    struct {
+        uint8_t opcode;
+        uint8_t polled;        /* lsb bit is polled; others are reserved */
+        uint8_t reserved2[2];
+        uint8_t class;
+        uint8_t reserved3[2];
+        uint16_t len;
+        uint8_t control;
+    } __attribute__((packed)) *gesn_cdb;
+
     unsigned int max_len;
 
-    max_len = ube16_to_cpu(packet + 7);
+    gesn_cdb = (void *)packet;
+    max_len = be16_to_cpu(gesn_cdb->len);
 
-    if (!(packet[1] & 0x01)) { /* asynchronous mode */
+    /* It is fine by the MMC spec to not support async mode operations */
+    if (!(gesn_cdb->polled & 0x01)) { /* asynchronous mode */
         /* Only polling is supported, asynchronous mode is not. */
         ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
                             ASC_INV_FIELD_IN_CMD_PACKET);
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 08/10] atapi: GESN: Standardise event response handling for future additions
  2011-04-13 12:05 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
                   ` (6 preceding siblings ...)
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 07/10] atapi: GESN: Use structs for commonly-used field types Kevin Wolf
@ 2011-04-13 12:05 ` Kevin Wolf
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 09/10] atapi: GESN: implement 'media' subcommand Kevin Wolf
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 10/10] vpc.c: Use get_option_parameter() does the search Kevin Wolf
  9 siblings, 0 replies; 11+ messages in thread
From: Kevin Wolf @ 2011-04-13 12:05 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Amit Shah <amit.shah@redhat.com>

Handle GET_EVENT_STATUS_NOTIFICATION's No Event Available response in a
generic way so that future additions to the code to handle other
response types is easier.

Signed-off-by: Amit Shah <amit.shah@redhat.com>
Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 hw/ide/core.c |   25 +++++++++++++++++++------
 1 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index f976947..a38cc14 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1098,9 +1098,17 @@ static void handle_get_event_status_notification(IDEState *s,
         uint8_t control;
     } __attribute__((packed)) *gesn_cdb;
 
-    unsigned int max_len;
+    struct {
+        uint16_t len;
+        uint8_t notification_class;
+        uint8_t supported_events;
+    } __attribute((packed)) *gesn_event_header;
+
+    unsigned int max_len, used_len;
 
     gesn_cdb = (void *)packet;
+    gesn_event_header = (void *)buf;
+
     max_len = be16_to_cpu(gesn_cdb->len);
 
     /* It is fine by the MMC spec to not support async mode operations */
@@ -1111,12 +1119,17 @@ static void handle_get_event_status_notification(IDEState *s,
         return;
     }
 
-    /* polling */
+    /* polling mode operation */
+
     /* We don't support any event class (yet). */
-    cpu_to_ube16(buf, 0x00); /* No event descriptor returned */
-    buf[2] = 0x80;           /* No Event Available (NEA) */
-    buf[3] = 0x00;           /* Empty supported event classes */
-    ide_atapi_cmd_reply(s, 4, max_len);
+    gesn_event_header->supported_events = 0;
+
+    gesn_event_header->notification_class = 0x80; /* No event available */
+    used_len = sizeof(*gesn_event_header);
+
+    gesn_event_header->len = cpu_to_be16(used_len
+                                         - sizeof(*gesn_event_header));
+    ide_atapi_cmd_reply(s, used_len, max_len);
 }
 
 static void ide_atapi_cmd(IDEState *s)
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 09/10] atapi: GESN: implement 'media' subcommand
  2011-04-13 12:05 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
                   ` (7 preceding siblings ...)
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 08/10] atapi: GESN: Standardise event response handling for future additions Kevin Wolf
@ 2011-04-13 12:05 ` Kevin Wolf
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 10/10] vpc.c: Use get_option_parameter() does the search Kevin Wolf
  9 siblings, 0 replies; 11+ messages in thread
From: Kevin Wolf @ 2011-04-13 12:05 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Amit Shah <amit.shah@redhat.com>

Implement the 'media' sub-command of the GET_EVENT_STATUS_NOTIFICATION
command.  This helps us report tray open, tray closed, no media, media
present states to the guest.

Newer Linux kernels (2.6.38+) rely on this command to revalidate discs
after media change.

This patch also sends out tray open/closed status to the guest driver
when requested e.g. via the CDROM_DRIVE_STATUS ioctl (thanks Markus).
Without such notification, the guest and qemu's tray open/close status
was frequently out of sync, causing installers like Anaconda detecting
no disc instead of tray open, confusing them terribly.

Signed-off-by: Amit Shah <amit.shah@redhat.com>
Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 hw/ide/core.c     |  113 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 hw/ide/internal.h |    6 +++
 2 files changed, 115 insertions(+), 4 deletions(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index a38cc14..f028ddb 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1084,6 +1084,48 @@ static int ide_dvd_read_structure(IDEState *s, int format,
     }
 }
 
+static unsigned int event_status_media(IDEState *s,
+                                       uint8_t *buf)
+{
+    enum media_event_code {
+        MEC_NO_CHANGE = 0,       /* Status unchanged */
+        MEC_EJECT_REQUESTED,     /* received a request from user to eject */
+        MEC_NEW_MEDIA,           /* new media inserted and ready for access */
+        MEC_MEDIA_REMOVAL,       /* only for media changers */
+        MEC_MEDIA_CHANGED,       /* only for media changers */
+        MEC_BG_FORMAT_COMPLETED, /* MRW or DVD+RW b/g format completed */
+        MEC_BG_FORMAT_RESTARTED, /* MRW or DVD+RW b/g format restarted */
+    };
+    enum media_status {
+        MS_TRAY_OPEN = 1,
+        MS_MEDIA_PRESENT = 2,
+    };
+    uint8_t event_code, media_status;
+
+    media_status = 0;
+    if (s->bs->tray_open) {
+        media_status = MS_TRAY_OPEN;
+    } else if (bdrv_is_inserted(s->bs)) {
+        media_status = MS_MEDIA_PRESENT;
+    }
+
+    /* 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;
+    }
+
+    buf[4] = event_code;
+    buf[5] = media_status;
+
+    /* These fields are reserved, just clear them. */
+    buf[6] = 0;
+    buf[7] = 0;
+
+    return 8; /* We wrote to 4 extra bytes from the header */
+}
+
 static void handle_get_event_status_notification(IDEState *s,
                                                  uint8_t *buf,
                                                  const uint8_t *packet)
@@ -1104,6 +1146,26 @@ static void handle_get_event_status_notification(IDEState *s,
         uint8_t supported_events;
     } __attribute((packed)) *gesn_event_header;
 
+    enum notification_class_request_type {
+        NCR_RESERVED1 = 1 << 0,
+        NCR_OPERATIONAL_CHANGE = 1 << 1,
+        NCR_POWER_MANAGEMENT = 1 << 2,
+        NCR_EXTERNAL_REQUEST = 1 << 3,
+        NCR_MEDIA = 1 << 4,
+        NCR_MULTI_HOST = 1 << 5,
+        NCR_DEVICE_BUSY = 1 << 6,
+        NCR_RESERVED2 = 1 << 7,
+    };
+    enum event_notification_class_field {
+        ENC_NO_EVENTS = 0,
+        ENC_OPERATIONAL_CHANGE,
+        ENC_POWER_MANAGEMENT,
+        ENC_EXTERNAL_REQUEST,
+        ENC_MEDIA,
+        ENC_MULTIPLE_HOSTS,
+        ENC_DEVICE_BUSY,
+        ENC_RESERVED,
+    };
     unsigned int max_len, used_len;
 
     gesn_cdb = (void *)packet;
@@ -1121,12 +1183,32 @@ static void handle_get_event_status_notification(IDEState *s,
 
     /* polling mode operation */
 
-    /* We don't support any event class (yet). */
-    gesn_event_header->supported_events = 0;
+    /*
+     * These are the supported events.
+     *
+     * We currently only support requests of the 'media' type.
+     */
+    gesn_event_header->supported_events = NCR_MEDIA;
 
-    gesn_event_header->notification_class = 0x80; /* No event available */
-    used_len = sizeof(*gesn_event_header);
+    /*
+     * We use |= below to set the class field; other bits in this byte
+     * are reserved now but this is useful to do if we have to use the
+     * reserved fields later.
+     */
+    gesn_event_header->notification_class = 0;
 
+    /*
+     * Responses to requests are to be based on request priority.  The
+     * notification_class_request_type enum above specifies the
+     * priority: upper elements are higher prio than lower ones.
+     */
+    if (gesn_cdb->class & NCR_MEDIA) {
+        gesn_event_header->notification_class |= ENC_MEDIA;
+        used_len = event_status_media(s, buf);
+    } else {
+        gesn_event_header->notification_class = 0x80; /* No event available */
+        used_len = sizeof(*gesn_event_header);
+    }
     gesn_event_header->len = cpu_to_be16(used_len
                                          - sizeof(*gesn_event_header));
     ide_atapi_cmd_reply(s, used_len, max_len);
@@ -1655,6 +1737,7 @@ static void cdrom_change_cb(void *opaque, int reason)
     s->sense_key = SENSE_UNIT_ATTENTION;
     s->asc = ASC_MEDIUM_MAY_HAVE_CHANGED;
     s->cdrom_changed = 1;
+    s->events.new_media = true;
     ide_set_irq(s->bus);
 }
 
@@ -2799,6 +2882,25 @@ static bool ide_drive_pio_state_needed(void *opaque)
     return (s->status & DRQ_STAT) != 0;
 }
 
+static bool ide_atapi_gesn_needed(void *opaque)
+{
+    IDEState *s = opaque;
+
+    return s->events.new_media || s->events.eject_request;
+}
+
+/* Fields for GET_EVENT_STATUS_NOTIFICATION ATAPI command */
+const VMStateDescription vmstate_ide_atapi_gesn_state = {
+    .name ="ide_drive/atapi/gesn_state",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_BOOL(events.new_media, IDEState),
+        VMSTATE_BOOL(events.eject_request, IDEState),
+    }
+};
+
 const VMStateDescription vmstate_ide_drive_pio_state = {
     .name = "ide_drive/pio_state",
     .version_id = 1,
@@ -2853,6 +2955,9 @@ const VMStateDescription vmstate_ide_drive = {
             .vmsd = &vmstate_ide_drive_pio_state,
             .needed = ide_drive_pio_state_needed,
         }, {
+            .vmsd = &vmstate_ide_atapi_gesn_state,
+            .needed = ide_atapi_gesn_needed,
+        }, {
             /* empty */
         }
     }
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index d533fb6..ba7e9a8 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -373,6 +373,11 @@ typedef int DMAFunc(IDEDMA *);
 typedef int DMAIntFunc(IDEDMA *, int);
 typedef void DMARestartFunc(void *, int, int);
 
+struct unreported_events {
+    bool eject_request;
+    bool new_media;
+};
+
 /* NOTE: IDEState represents in fact one drive */
 struct IDEState {
     IDEBus *bus;
@@ -408,6 +413,7 @@ struct IDEState {
     BlockDriverState *bs;
     char version[9];
     /* ATAPI specific */
+    struct unreported_events events;
     uint8_t sense_key;
     uint8_t asc;
     uint8_t cdrom_changed;
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 10/10] vpc.c: Use get_option_parameter() does the search
  2011-04-13 12:05 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
                   ` (8 preceding siblings ...)
  2011-04-13 12:05 ` [Qemu-devel] [PATCH 09/10] atapi: GESN: implement 'media' subcommand Kevin Wolf
@ 2011-04-13 12:05 ` Kevin Wolf
  9 siblings, 0 replies; 11+ messages in thread
From: Kevin Wolf @ 2011-04-13 12:05 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Mitnick Lyu <mitnick.lyu@gmail.com>

Use get_option_parameter() to instead of duplicating the loop, and
use BDRV_SECTOR_SIZE to instead of 512

Signed-off-by: Mitnick Lyu <mitnick.lyu@gmail.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/vpc.c |    8 ++------
 1 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/block/vpc.c b/block/vpc.c
index 7b025be..56865da 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -505,12 +505,8 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
     int ret = -EIO;
 
     // Read out options
-    while (options && options->name) {
-        if (!strcmp(options->name, "size")) {
-            total_sectors = options->value.n / 512;
-        }
-        options++;
-    }
+    total_sectors = get_option_parameter(options, BLOCK_OPT_SIZE)->value.n /
+                    BDRV_SECTOR_SIZE;
 
     // Create the file
     fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2011-04-13 12:03 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-13 12:05 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
2011-04-13 12:05 ` [Qemu-devel] [PATCH 01/10] docs: Describe zero data clusters in QED specification Kevin Wolf
2011-04-13 12:05 ` [Qemu-devel] [PATCH 02/10] qed: Add support for zero clusters Kevin Wolf
2011-04-13 12:05 ` [Qemu-devel] [PATCH 03/10] atapi: Drives can be locked without media present Kevin Wolf
2011-04-13 12:05 ` [Qemu-devel] [PATCH 04/10] atapi: Report correct errors on guest eject request Kevin Wolf
2011-04-13 12:05 ` [Qemu-devel] [PATCH 05/10] atapi: Allow GET_EVENT_STATUS_NOTIFICATION after media change Kevin Wolf
2011-04-13 12:05 ` [Qemu-devel] [PATCH 06/10] atapi: Move GET_EVENT_STATUS_NOTIFICATION command handling to its own function Kevin Wolf
2011-04-13 12:05 ` [Qemu-devel] [PATCH 07/10] atapi: GESN: Use structs for commonly-used field types Kevin Wolf
2011-04-13 12:05 ` [Qemu-devel] [PATCH 08/10] atapi: GESN: Standardise event response handling for future additions Kevin Wolf
2011-04-13 12:05 ` [Qemu-devel] [PATCH 09/10] atapi: GESN: implement 'media' subcommand Kevin Wolf
2011-04-13 12:05 ` [Qemu-devel] [PATCH 10/10] vpc.c: Use get_option_parameter() does the search Kevin Wolf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).