All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/35] SCSI uber-patch
@ 2011-10-13 11:03 Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 01/35] scsi: pass correct sense code for ENOMEDIUM Paolo Bonzini
                   ` (34 more replies)
  0 siblings, 35 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

Kevin,

the following changes since commit 77d5aa8ade3aac7ee3cec0ab05fb538055e01a48:

  block: split out bdrv_co_do_readv() and bdrv_co_do_writev() (2011-10-12 14:42:11 +0200)

are available in the git repository at:
  git://github.com/bonzini/qemu.git scsi-for-kevin

Patches 1-12 have been sent before as part of the "scsi-disk: Add DVD-ROM
support and media change + atapi: nitpicking" series (Sep 20 2011).  I
tested them with various versions of client operating systems, mostly
RHEL6 and Fedora 16.

Patches 13-18 have been sent before as part of the "introduce SCSI
channel/target/LUN addressing" series (Sep 30 2011).  I tested them
mostly with the pSeries machine.

Patches 19-22 have been sent before as part of the "scsi: miscellaneous
fixes" series (Oct 7 2011), and are rebased here.

Patches 23-35 have been sent yesterday as part of the "scsi: add
specialized block device passthrough", but are slightly different here
to support passthrough of 4k-sector disks, and to improve the behavior
of CD-ROM passthrough (both scsi-block and scsi-generic) when no disk
is present in the physical drive.

Paolo Bonzini (35):
      scsi: pass correct sense code for ENOMEDIUM
      atapi/scsi: unify definitions for MMC
      atapi: move GESN definitions to scsi-defs.h
      atapi: fill in AUDIO_CTL page correctly
      scsi: notify the device when unit attention is reported
      scsi-disk: report media changed via unit attention sense codes
      scsi-disk: add stubs for more MMC commands
      scsi-disk: store valid mode pages in a table
      atapi/scsi-disk: make mode page values coherent between the two
      scsi-disk: support DVD profile in GET CONFIGURATION
      scsi-disk: support READ DVD STRUCTURE
      scsi-disk: report media changed via GET EVENT STATUS NOTIFICATION
      scsi: move tcq/ndev to SCSIBusOps (now SCSIBusInfo)
      qdev: switch children device list to QTAILQ
      scsi: remove devs array from SCSIBus
      scsi: implement REPORT LUNS for arbitrary LUNs
      scsi: allow arbitrary LUNs
      scsi: add channel to addressing
      scsi-disk: fail READ CAPACITY if LBA != 0 but PMI == 0
      scsi-disk: do not complete requests twice
      scsi-disk: bump SCSIRequest reference count until aio completion runs
      scsi-disk: fix retrying a flush
      scsi-generic: drop SCSIGenericState
      scsi-generic: remove scsi_req_fixup
      scsi-generic: check ioctl statuses when SG_IO succeeds
      scsi-generic: look at host status
      scsi-generic: snoop READ CAPACITY commands to get block size
      scsi-disk: do not duplicate BlockDriverState member
      scsi-disk: remove cluster_size
      scsi-disk: small clean up to INQUIRY
      scsi: move max_lba to SCSIDevice
      scsi: make reqops const
      scsi: export scsi_generic_reqops
      scsi: pass cdb to alloc_req
      scsi-disk: add scsi-block for device passthrough

 hw/acpi_piix4.c      |    4 +-
 hw/esp.c             |   13 +-
 hw/i2c.c             |    2 +-
 hw/ide/atapi.c       |  109 +++-----
 hw/ide/core.c        |    4 +-
 hw/ide/internal.h    |   71 +------
 hw/ide/macio.c       |    2 +-
 hw/intel-hda.c       |    6 +-
 hw/lsi53c895a.c      |   30 +--
 hw/qdev.c            |   24 +-
 hw/qdev.h            |    4 +-
 hw/s390-virtio-bus.c |    4 +-
 hw/scsi-bus.c        |  204 +++++++++++-----
 hw/scsi-defs.h       |   90 +++++++
 hw/scsi-disk.c       |  674 ++++++++++++++++++++++++++++++++++++++++----------
 hw/scsi-generic.c    |  168 +++++--------
 hw/scsi.h            |   33 ++-
 hw/spapr_vio.c       |    6 +-
 hw/spapr_vscsi.c     |   54 +++-
 hw/ssi.c             |    6 +-
 hw/usb-msd.c         |    8 +-
 21 files changed, 997 insertions(+), 519 deletions(-)
-- 
1.7.6

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

* [Qemu-devel] [PATCH 01/35] scsi: pass correct sense code for ENOMEDIUM
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 02/35] atapi/scsi: unify definitions for MMC Paolo Bonzini
                   ` (33 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 6909578..9c62569 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -231,6 +231,9 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
         bdrv_iostatus_set_err(s->bs, error);
     } else {
         switch (error) {
+        case ENOMEDIUM:
+            scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
+            break;
         case ENOMEM:
             scsi_check_condition(r, SENSE_CODE(TARGET_FAILURE));
             break;
-- 
1.7.6

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

* [Qemu-devel] [PATCH 02/35] atapi/scsi: unify definitions for MMC
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 01/35] scsi: pass correct sense code for ENOMEDIUM Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 03/35] atapi: move GESN definitions to scsi-defs.h Paolo Bonzini
                   ` (32 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

The definitions in ide/internal.h are duplicates, since ATAPI commands
actually come from SCSI.  Use the ones in scsi-defs.h and move the
missing ones there.  Two exceptions:

- MODE_PAGE_WRITE_PARMS conflicts with the "flexible disk geometry"
page in scsi-disk.c.  It is unused, so pick the latter.

- GPCMD_* is left in ide/internal.h, at least for now.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/ide/atapi.c    |   52 +++++++++++++++++++-------------------
 hw/ide/core.c     |    4 +-
 hw/ide/internal.h |   71 +----------------------------------------------------
 hw/ide/macio.c    |    2 +-
 hw/scsi-bus.c     |    2 +-
 hw/scsi-defs.h    |   66 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/scsi-disk.c    |    8 +++---
 7 files changed, 101 insertions(+), 104 deletions(-)

diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index 3f909c3..be3b728 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -154,10 +154,10 @@ void ide_atapi_io_error(IDEState *s, int ret)
 {
     /* XXX: handle more errors */
     if (ret == -ENOMEDIUM) {
-        ide_atapi_cmd_error(s, SENSE_NOT_READY,
+        ide_atapi_cmd_error(s, NOT_READY,
                             ASC_MEDIUM_NOT_PRESENT);
     } else {
-        ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+        ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
                             ASC_LOGICAL_BLOCK_OOR);
     }
 }
@@ -282,7 +282,7 @@ static void ide_atapi_cmd_check_status(IDEState *s)
 #ifdef DEBUG_IDE_ATAPI
     printf("atapi_cmd_check_status\n");
 #endif
-    s->error = MC_ERR | (SENSE_UNIT_ATTENTION << 4);
+    s->error = MC_ERR | (UNIT_ATTENTION << 4);
     s->status = ERR_STAT;
     s->nsector = 0;
     ide_set_irq(s->bus);
@@ -354,7 +354,7 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
                                        ide_atapi_cmd_read_dma_cb, s);
     if (!s->bus->dma->aiocb) {
         /* Note: media not present is the most likely case */
-        ide_atapi_cmd_error(s, SENSE_NOT_READY,
+        ide_atapi_cmd_error(s, NOT_READY,
                             ASC_MEDIUM_NOT_PRESENT);
         goto eot;
     }
@@ -595,7 +595,7 @@ static void cmd_get_event_status_notification(IDEState *s,
     /* 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,
+        ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
                             ASC_INV_FIELD_IN_CMD_PACKET);
         return;
     }
@@ -643,8 +643,8 @@ static void cmd_request_sense(IDEState *s, uint8_t *buf)
     buf[7] = 10;
     buf[12] = s->asc;
 
-    if (s->sense_key == SENSE_UNIT_ATTENTION) {
-        s->sense_key = SENSE_NONE;
+    if (s->sense_key == UNIT_ATTENTION) {
+        s->sense_key = NO_SENSE;
     }
 
     ide_atapi_cmd_reply(s, 18, max_len);
@@ -676,7 +676,7 @@ static void cmd_get_configuration(IDEState *s, uint8_t *buf)
 
     /* only feature 0 is supported */
     if (buf[2] != 0 || buf[3] != 0) {
-        ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+        ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
                             ASC_INV_FIELD_IN_CMD_PACKET);
         return;
     }
@@ -733,7 +733,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
     switch(action) {
     case 0: /* current values */
         switch(code) {
-        case GPMODE_R_W_ERROR_PAGE: /* error recovery */
+        case MODE_PAGE_R_W_ERROR: /* error recovery */
             cpu_to_ube16(&buf[0], 16 + 6);
             buf[2] = 0x70;
             buf[3] = 0;
@@ -752,7 +752,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
             buf[15] = 0x00;
             ide_atapi_cmd_reply(s, 16, max_len);
             break;
-        case GPMODE_AUDIO_CTL_PAGE:
+        case MODE_PAGE_AUDIO_CTL:
             cpu_to_ube16(&buf[0], 24 + 6);
             buf[2] = 0x70;
             buf[3] = 0;
@@ -769,7 +769,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
 
             ide_atapi_cmd_reply(s, 24, max_len);
             break;
-        case GPMODE_CAPABILITIES_PAGE:
+        case MODE_PAGE_CAPABILITIES:
             cpu_to_ube16(&buf[0], 28 + 6);
             buf[2] = 0x70;
             buf[3] = 0;
@@ -813,14 +813,14 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
         goto error_cmd;
     default:
     case 3: /* saved values */
-        ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+        ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
                             ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
         break;
     }
     return;
 
 error_cmd:
-    ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
+    ide_atapi_cmd_error(s, ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
 }
 
 static void cmd_test_unit_ready(IDEState *s, uint8_t *buf)
@@ -883,7 +883,7 @@ static void cmd_read_cd(IDEState *s, uint8_t* buf)
         ide_atapi_cmd_read(s, lba, nb_sectors, 2352);
         break;
     default:
-        ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+        ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
                             ASC_INV_FIELD_IN_CMD_PACKET);
         break;
     }
@@ -896,7 +896,7 @@ static void cmd_seek(IDEState *s, uint8_t* buf)
 
     lba = ube32_to_cpu(buf + 2);
     if (lba >= total_sectors) {
-        ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR);
+        ide_atapi_cmd_error(s, ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR);
         return;
     }
 
@@ -912,7 +912,7 @@ static void cmd_start_stop_unit(IDEState *s, uint8_t* buf)
     if (loej) {
         if (!start && !s->tray_open && s->tray_locked) {
             sense = bdrv_is_inserted(s->bs)
-                ? SENSE_NOT_READY : SENSE_ILLEGAL_REQUEST;
+                ? NOT_READY : ILLEGAL_REQUEST;
             ide_atapi_cmd_error(s, sense, ASC_MEDIA_REMOVAL_PREVENTED);
             return;
         }
@@ -971,7 +971,7 @@ static void cmd_read_toc_pma_atip(IDEState *s, uint8_t* buf)
         break;
     default:
     error_cmd:
-        ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+        ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
                             ASC_INV_FIELD_IN_CMD_PACKET);
     }
 }
@@ -997,11 +997,11 @@ static void cmd_read_dvd_structure(IDEState *s, uint8_t* buf)
 
     if (format < 0xff) {
         if (media_is_cd(s)) {
-            ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+            ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
                                 ASC_INCOMPATIBLE_FORMAT);
             return;
         } else if (!media_present(s)) {
-            ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+            ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
                                 ASC_INV_FIELD_IN_CMD_PACKET);
             return;
         }
@@ -1017,7 +1017,7 @@ static void cmd_read_dvd_structure(IDEState *s, uint8_t* buf)
                 ret = ide_dvd_read_structure(s, format, buf, buf);
 
                 if (ret < 0) {
-                    ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, -ret);
+                    ide_atapi_cmd_error(s, ILLEGAL_REQUEST, -ret);
                 } else {
                     ide_atapi_cmd_reply(s, ret, max_len);
                 }
@@ -1034,7 +1034,7 @@ static void cmd_read_dvd_structure(IDEState *s, uint8_t* buf)
         case 0x90: /* TODO: List of recognized format layers */
         case 0xc0: /* TODO: Write protection status */
         default:
-            ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+            ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
                                 ASC_INV_FIELD_IN_CMD_PACKET);
             break;
     }
@@ -1106,7 +1106,7 @@ void ide_atapi_cmd(IDEState *s)
      * condition response unless a higher priority status, defined by the drive
      * here, is pending.
      */
-    if (s->sense_key == SENSE_UNIT_ATTENTION &&
+    if (s->sense_key == UNIT_ATTENTION &&
         !(atapi_cmd_table[s->io_buffer[0]].flags & ALLOW_UA)) {
         ide_atapi_cmd_check_status(s);
         return;
@@ -1119,10 +1119,10 @@ void ide_atapi_cmd(IDEState *s)
      * states rely on this behavior.
      */
     if (!s->tray_open && bdrv_is_inserted(s->bs) && s->cdrom_changed) {
-        ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+        ide_atapi_cmd_error(s, NOT_READY, ASC_MEDIUM_NOT_PRESENT);
 
         s->cdrom_changed = 0;
-        s->sense_key = SENSE_UNIT_ATTENTION;
+        s->sense_key = UNIT_ATTENTION;
         s->asc = ASC_MEDIUM_MAY_HAVE_CHANGED;
         return;
     }
@@ -1131,7 +1131,7 @@ void ide_atapi_cmd(IDEState *s)
     if ((atapi_cmd_table[s->io_buffer[0]].flags & CHECK_READY) &&
         (!media_present(s) || !bdrv_is_inserted(s->bs)))
     {
-        ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+        ide_atapi_cmd_error(s, NOT_READY, ASC_MEDIUM_NOT_PRESENT);
         return;
     }
 
@@ -1141,5 +1141,5 @@ void ide_atapi_cmd(IDEState *s)
         return;
     }
 
-    ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE);
+    ide_atapi_cmd_error(s, ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE);
 }
diff --git a/hw/ide/core.c b/hw/ide/core.c
index fbc0859..5b52116 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -798,7 +798,7 @@ static void ide_cd_change_cb(void *opaque, bool load)
      * First indicate to the guest that a CD has been removed.  That's
      * done on the next command the guest sends us.
      *
-     * Then we set SENSE_UNIT_ATTENTION, by which the guest will
+     * Then we set UNIT_ATTENTION, by which the guest will
      * detect a new CD in the drive.  See ide_atapi_cmd() for details.
      */
     s->cdrom_changed = 1;
@@ -2019,7 +2019,7 @@ static int ide_drive_post_load(void *opaque, int version_id)
     IDEState *s = opaque;
 
     if (version_id < 3) {
-        if (s->sense_key == SENSE_UNIT_ATTENTION &&
+        if (s->sense_key == UNIT_ATTENTION &&
             s->asc == ASC_MEDIUM_MAY_HAVE_CHANGED) {
             s->cdrom_changed = 1;
         }
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 9046e96..a88f75b 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -10,6 +10,7 @@
 #include "iorange.h"
 #include "dma.h"
 #include "sysemu.h"
+#include "hw/scsi-defs.h"
 
 /* debug IDE devices */
 //#define DEBUG_IDE
@@ -279,71 +280,6 @@ typedef struct IDEDMAOps IDEDMAOps;
 #define GPCMD_GET_MEDIA_STATUS		    0xda
 #define GPCMD_MODE_SENSE_6		    0x1a
 
-/* Mode page codes for mode sense/set */
-#define GPMODE_R_W_ERROR_PAGE		0x01
-#define GPMODE_WRITE_PARMS_PAGE		0x05
-#define GPMODE_AUDIO_CTL_PAGE		0x0e
-#define GPMODE_POWER_PAGE		0x1a
-#define GPMODE_FAULT_FAIL_PAGE		0x1c
-#define GPMODE_TO_PROTECT_PAGE		0x1d
-#define GPMODE_CAPABILITIES_PAGE	0x2a
-#define GPMODE_ALL_PAGES		0x3f
-/* Not in Mt. Fuji, but in ATAPI 2.6 -- depricated now in favor
- * of MODE_SENSE_POWER_PAGE */
-#define GPMODE_CDROM_PAGE		0x0d
-
-/*
- * Based on values from <linux/cdrom.h> but extending CD_MINS
- * to the maximum common size allowed by the Orange's Book ATIP
- *
- * 90 and 99 min CDs are also available but using them as the
- * upper limit reduces the effectiveness of the heuristic to
- * detect DVDs burned to less than 25% of their maximum capacity
- */
-
-/* Some generally useful CD-ROM information */
-#define CD_MINS                       80 /* max. minutes per CD */
-#define CD_SECS                       60 /* seconds per minute */
-#define CD_FRAMES                     75 /* frames per second */
-#define CD_FRAMESIZE                2048 /* bytes per frame, "cooked" mode */
-#define CD_MAX_BYTES       (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE)
-#define CD_MAX_SECTORS     (CD_MAX_BYTES / 512)
-
-/*
- * The MMC values are not IDE specific and might need to be moved
- * to a common header if they are also needed for the SCSI emulation
- */
-
-/* Profile list from MMC-6 revision 1 table 91 */
-#define MMC_PROFILE_NONE                0x0000
-#define MMC_PROFILE_CD_ROM              0x0008
-#define MMC_PROFILE_CD_R                0x0009
-#define MMC_PROFILE_CD_RW               0x000A
-#define MMC_PROFILE_DVD_ROM             0x0010
-#define MMC_PROFILE_DVD_R_SR            0x0011
-#define MMC_PROFILE_DVD_RAM             0x0012
-#define MMC_PROFILE_DVD_RW_RO           0x0013
-#define MMC_PROFILE_DVD_RW_SR           0x0014
-#define MMC_PROFILE_DVD_R_DL_SR         0x0015
-#define MMC_PROFILE_DVD_R_DL_JR         0x0016
-#define MMC_PROFILE_DVD_RW_DL           0x0017
-#define MMC_PROFILE_DVD_DDR             0x0018
-#define MMC_PROFILE_DVD_PLUS_RW         0x001A
-#define MMC_PROFILE_DVD_PLUS_R          0x001B
-#define MMC_PROFILE_DVD_PLUS_RW_DL      0x002A
-#define MMC_PROFILE_DVD_PLUS_R_DL       0x002B
-#define MMC_PROFILE_BD_ROM              0x0040
-#define MMC_PROFILE_BD_R_SRM            0x0041
-#define MMC_PROFILE_BD_R_RRM            0x0042
-#define MMC_PROFILE_BD_RE               0x0043
-#define MMC_PROFILE_HDDVD_ROM           0x0050
-#define MMC_PROFILE_HDDVD_R             0x0051
-#define MMC_PROFILE_HDDVD_RAM           0x0052
-#define MMC_PROFILE_HDDVD_RW            0x0053
-#define MMC_PROFILE_HDDVD_R_DL          0x0058
-#define MMC_PROFILE_HDDVD_RW_DL         0x005A
-#define MMC_PROFILE_INVALID             0xFFFF
-
 #define ATAPI_INT_REASON_CD             0x01 /* 0 = data transfer */
 #define ATAPI_INT_REASON_IO             0x02 /* 1 = transfer to the host */
 #define ATAPI_INT_REASON_REL            0x04
@@ -365,11 +301,6 @@ typedef struct IDEDMAOps IDEDMAOps;
 #define CFA_INVALID_ADDRESS     0x21
 #define CFA_ADDRESS_OVERFLOW    0x2f
 
-#define SENSE_NONE            0
-#define SENSE_NOT_READY       2
-#define SENSE_ILLEGAL_REQUEST 5
-#define SENSE_UNIT_ATTENTION  6
-
 #define SMART_READ_DATA       0xd0
 #define SMART_READ_THRESH     0xd1
 #define SMART_ATTR_AUTOSAVE   0xd2
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 37b8239..70b3342 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -87,7 +87,7 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
     if (!m->aiocb) {
         qemu_sglist_destroy(&s->sg);
         /* Note: media not present is the most likely case */
-        ide_atapi_cmd_error(s, SENSE_NOT_READY,
+        ide_atapi_cmd_error(s, NOT_READY,
                             ASC_MEDIUM_NOT_PRESENT);
         goto done;
     }
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index aca65a1..fc2f823 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -800,7 +800,7 @@ const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED = {
 };
 
 /* Illegal request, Incompatible medium installed */
-const struct SCSISense sense_code_INCOMPATIBLE_MEDIUM = {
+const struct SCSISense sense_code_INCOMPATIBLE_FORMAT = {
     .key = ILLEGAL_REQUEST, .asc = 0x30, .ascq = 0x00
 };
 
diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
index bfe9392..dfa3095 100644
--- a/hw/scsi-defs.h
+++ b/hw/scsi-defs.h
@@ -188,3 +188,69 @@
 #define TYPE_INACTIVE       0x20
 #define TYPE_NO_LUN         0x7f
 
+/* Mode page codes for mode sense/set */
+#define MODE_PAGE_R_W_ERROR		0x01
+#define MODE_PAGE_HD_GEOMETRY		0x04
+#define MODE_PAGE_FLEXIBLE_DISK_GEOMETRY	0x05
+#define MODE_PAGE_CACHING		0x08
+#define MODE_PAGE_AUDIO_CTL		0x0e
+#define MODE_PAGE_POWER			0x1a
+#define MODE_PAGE_FAULT_FAIL		0x1c
+#define MODE_PAGE_TO_PROTECT		0x1d
+#define MODE_PAGE_CAPABILITIES		0x2a
+#define MODE_PAGE_ALLS			0x3f
+/* Not in Mt. Fuji, but in ATAPI 2.6 -- depricated now in favor
+ * of MODE_PAGE_SENSE_POWER */
+#define MODE_PAGE_CDROM			0x0d
+
+/*
+ * Based on values from <linux/cdrom.h> but extending CD_MINS
+ * to the maximum common size allowed by the Orange's Book ATIP
+ *
+ * 90 and 99 min CDs are also available but using them as the
+ * upper limit reduces the effectiveness of the heuristic to
+ * detect DVDs burned to less than 25% of their maximum capacity
+ */
+
+/* Some generally useful CD-ROM information */
+#define CD_MINS                       80 /* max. minutes per CD */
+#define CD_SECS                       60 /* seconds per minute */
+#define CD_FRAMES                     75 /* frames per second */
+#define CD_FRAMESIZE                2048 /* bytes per frame, "cooked" mode */
+#define CD_MAX_BYTES       (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE)
+#define CD_MAX_SECTORS     (CD_MAX_BYTES / 512)
+
+/*
+ * The MMC values are not IDE specific and might need to be moved
+ * to a common header if they are also needed for the SCSI emulation
+ */
+
+/* Profile list from MMC-6 revision 1 table 91 */
+#define MMC_PROFILE_NONE                0x0000
+#define MMC_PROFILE_CD_ROM              0x0008
+#define MMC_PROFILE_CD_R                0x0009
+#define MMC_PROFILE_CD_RW               0x000A
+#define MMC_PROFILE_DVD_ROM             0x0010
+#define MMC_PROFILE_DVD_R_SR            0x0011
+#define MMC_PROFILE_DVD_RAM             0x0012
+#define MMC_PROFILE_DVD_RW_RO           0x0013
+#define MMC_PROFILE_DVD_RW_SR           0x0014
+#define MMC_PROFILE_DVD_R_DL_SR         0x0015
+#define MMC_PROFILE_DVD_R_DL_JR         0x0016
+#define MMC_PROFILE_DVD_RW_DL           0x0017
+#define MMC_PROFILE_DVD_DDR             0x0018
+#define MMC_PROFILE_DVD_PLUS_RW         0x001A
+#define MMC_PROFILE_DVD_PLUS_R          0x001B
+#define MMC_PROFILE_DVD_PLUS_RW_DL      0x002A
+#define MMC_PROFILE_DVD_PLUS_R_DL       0x002B
+#define MMC_PROFILE_BD_ROM              0x0040
+#define MMC_PROFILE_BD_R_SRM            0x0041
+#define MMC_PROFILE_BD_R_RRM            0x0042
+#define MMC_PROFILE_BD_RE               0x0043
+#define MMC_PROFILE_HDDVD_ROM           0x0050
+#define MMC_PROFILE_HDDVD_R             0x0051
+#define MMC_PROFILE_HDDVD_RAM           0x0052
+#define MMC_PROFILE_HDDVD_RW            0x0053
+#define MMC_PROFILE_HDDVD_R_DL          0x0058
+#define MMC_PROFILE_HDDVD_RW_DL         0x005A
+#define MMC_PROFILE_INVALID             0xFFFF
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 9c62569..a6ef060 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -576,7 +576,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
      * The buffer was already menset to zero by the caller of this function.
      */
     switch (page) {
-    case 4: /* Rigid disk device geometry page. */
+    case MODE_PAGE_HD_GEOMETRY:
         if (s->qdev.type == TYPE_ROM) {
             return -1;
         }
@@ -611,7 +611,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
         p[21] = 5400 & 0xff;
         break;
 
-    case 5: /* Flexible disk device geometry page. */
+    case MODE_PAGE_FLEXIBLE_DISK_GEOMETRY:
         if (s->qdev.type == TYPE_ROM) {
             return -1;
         }
@@ -653,7 +653,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
         p[29] = 5400 & 0xff;
         break;
 
-    case 8: /* Caching page.  */
+    case MODE_PAGE_CACHING:
         p[0] = 8;
         p[1] = 0x12;
         if (page_control == 1) { /* Changeable Values */
@@ -664,7 +664,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
         }
         break;
 
-    case 0x2a: /* CD Capabilities and Mechanical Status page. */
+    case MODE_PAGE_CAPABILITIES:
         if (s->qdev.type != TYPE_ROM) {
             return -1;
         }
-- 
1.7.6

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

* [Qemu-devel] [PATCH 03/35] atapi: move GESN definitions to scsi-defs.h
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 01/35] scsi: pass correct sense code for ENOMEDIUM Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 02/35] atapi/scsi: unify definitions for MMC Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-17 13:41   ` Kevin Wolf
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 04/35] atapi: fill in AUDIO_CTL page correctly Paolo Bonzini
                   ` (31 subsequent siblings)
  34 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

As a complement to the previous patch, move definitions for GET EVENT
STATUS NOTIFICATION from the two functions to scsi-defs.h.

The NCR_* constants are just bit values corresponding to the ENC_*
values, with no offsets even, so keep just one copy.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/ide/atapi.c |   43 ++++++-------------------------------------
 hw/scsi-defs.h |   21 +++++++++++++++++++++
 2 files changed, 27 insertions(+), 37 deletions(-)

diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index be3b728..347c38d 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -505,19 +505,6 @@ 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;
@@ -564,27 +551,6 @@ static void cmd_get_event_status_notification(IDEState *s,
         uint8_t notification_class;
         uint8_t supported_events;
     } QEMU_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;
@@ -606,8 +572,11 @@ static void cmd_get_event_status_notification(IDEState *s,
      * These are the supported events.
      *
      * We currently only support requests of the 'media' type.
+     * Notification class requests and supported event classes are bitmasks,
+     * but they are build from the same values as the "notification class"
+     * field.
      */
-    gesn_event_header->supported_events = NCR_MEDIA;
+    gesn_event_header->supported_events = 1 << GESN_MEDIA;
 
     /*
      * We use |= below to set the class field; other bits in this byte
@@ -621,8 +590,8 @@ static void cmd_get_event_status_notification(IDEState *s,
      * 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;
+    if (gesn_cdb->class & (1 << GESN_MEDIA)) {
+        gesn_event_header->notification_class |= GESN_MEDIA;
         used_len = event_status_media(s, buf);
     } else {
         gesn_event_header->notification_class = 0x80; /* No event available */
diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
index dfa3095..8094698 100644
--- a/hw/scsi-defs.h
+++ b/hw/scsi-defs.h
@@ -203,6 +203,27 @@
  * of MODE_PAGE_SENSE_POWER */
 #define MODE_PAGE_CDROM			0x0d
 
+/* Event notification classes for GET EVENT STATUS NOTIFICATION */
+#define GESN_NO_EVENTS			0
+#define GESN_OPERATIONAL_CHANGE		1
+#define GESN_POWER_MANAGEMENT		2
+#define GESN_EXTERNAL_REQUEST		3
+#define GESN_MEDIA			4
+#define GESN_MULTIPLE_HOSTS		5
+#define GESN_DEVICE_BUSY		6
+
+/* Event codes for MEDIA event status notification */
+#define MEC_NO_CHANGE		0
+#define MEC_EJECT_REQUESTED	1
+#define MEC_NEW_MEDIA		2
+#define MEC_MEDIA_REMOVAL	3 /* only for media changers */
+#define MEC_MEDIA_CHANGED	4 /* only for media changers */
+#define MEC_BG_FORMAT_COMPLETED	5 /* MRW or DVD+RW b/g format completed */
+#define MEC_BG_FORMAT_RESTARTED	6 /* MRW or DVD+RW b/g format restarted */
+
+#define MS_TRAY_OPEN		1
+#define MS_MEDIA_PRESENT	2
+
 /*
  * Based on values from <linux/cdrom.h> but extending CD_MINS
  * to the maximum common size allowed by the Orange's Book ATIP
-- 
1.7.6

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

* [Qemu-devel] [PATCH 04/35] atapi: fill in AUDIO_CTL page correctly
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (2 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 03/35] atapi: move GESN definitions to scsi-defs.h Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-17 14:05   ` Kevin Wolf
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 05/35] scsi: notify the device when unit attention is reported Paolo Bonzini
                   ` (30 subsequent siblings)
  34 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

The page is not anymore in MMC, but at least keep the values sane.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/ide/atapi.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index 347c38d..10f161f 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -731,6 +731,8 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
             buf[7] = 0;
 
             /* Fill with CDROM audio volume */
+            buf[8] = 0x0e;
+            buf[9] = 0x0e;
             buf[17] = 0;
             buf[19] = 0;
             buf[21] = 0;
-- 
1.7.6

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

* [Qemu-devel] [PATCH 05/35] scsi: notify the device when unit attention is reported
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (3 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 04/35] atapi: fill in AUDIO_CTL page correctly Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 06/35] scsi-disk: report media changed via unit attention sense codes Paolo Bonzini
                   ` (29 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

Reporting media change events via unit attention sense codes requires
a small state machine: first report "NO MEDIUM", then report "MEDIUM MAY
HAVE CHANGED".  Unfortunately there is no good hooking point for the
device to notice that its pending unit attention condition has been
reported.  This patch reworks the generic machinery to add one.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-bus.c |   32 +++++++++++++++++++++++++++-----
 hw/scsi.h     |    2 ++
 2 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index fc2f823..c190509 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -295,6 +295,13 @@ static int32_t scsi_target_send_command(SCSIRequest *req, uint8_t *buf)
         r->len = scsi_device_get_sense(r->req.dev, r->buf,
                                        MIN(req->cmd.xfer, sizeof r->buf),
                                        (req->cmd.buf[1] & 1) == 0);
+        if (r->req.dev->sense_is_ua) {
+            if (r->req.dev->info->unit_attention_reported) {
+                r->req.dev->info->unit_attention_reported(req->dev);
+            }
+            r->req.dev->sense_len = 0;
+            r->req.dev->sense_is_ua = false;
+        }
         break;
     default:
         scsi_req_build_sense(req, SENSE_CODE(LUN_NOT_SUPPORTED));
@@ -383,7 +390,13 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
             (buf[0] != INQUIRY &&
              buf[0] != REPORT_LUNS &&
              buf[0] != GET_CONFIGURATION &&
-             buf[0] != GET_EVENT_STATUS_NOTIFICATION)) {
+             buf[0] != GET_EVENT_STATUS_NOTIFICATION &&
+
+             /*
+              * If we already have a pending unit attention condition,
+              * report this one before triggering another one.
+              */
+             !(buf[0] == REQUEST_SENSE && d->sense_is_ua))) {
             req = scsi_req_alloc(&reqops_unit_attention, d, tag, lun,
                                  hba_private);
         } else if (lun != d->lun ||
@@ -479,10 +492,15 @@ int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len)
      *
      * We assume UA_INTLCK_CTRL to be 00b for HBAs that support autosense, and
      * 10b for HBAs that do not support it (do not call scsi_req_get_sense).
-     * In the latter case, scsi_req_complete clears unit attention conditions
-     * after moving them to the device's sense buffer.
+     * Here we handle unit attention clearing for UA_INTLCK_CTRL == 00b.
      */
-    scsi_clear_unit_attention(req);
+    if (req->dev->sense_is_ua) {
+        if (req->dev->info->unit_attention_reported) {
+            req->dev->info->unit_attention_reported(req->dev);
+        }
+        req->dev->sense_len = 0;
+        req->dev->sense_is_ua = false;
+    }
     return ret;
 }
 
@@ -1082,8 +1100,12 @@ void scsi_req_complete(SCSIRequest *req, int status)
 
     if (req->sense_len) {
         memcpy(req->dev->sense, req->sense, req->sense_len);
+        req->dev->sense_len = req->sense_len;
+        req->dev->sense_is_ua = (req->ops == &reqops_unit_attention);
+    } else {
+        req->dev->sense_len = 0;
+        req->dev->sense_is_ua = false;
     }
-    req->dev->sense_len = req->sense_len;
 
     /*
      * Unit attention state is now stored in the device's sense buffer
diff --git a/hw/scsi.h b/hw/scsi.h
index e8dcabf..6d40b8e 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -62,6 +62,7 @@ struct SCSIDevice
     BlockConf conf;
     SCSIDeviceInfo *info;
     SCSISense unit_attention;
+    bool sense_is_ua;
     uint8_t sense[SCSI_SENSE_BUF_SIZE];
     uint32_t sense_len;
     QTAILQ_HEAD(, SCSIRequest) requests;
@@ -92,6 +93,7 @@ struct SCSIDeviceInfo {
     void (*destroy)(SCSIDevice *s);
     SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
                               void *hba_private);
+    void (*unit_attention_reported)(SCSIDevice *s);
     SCSIReqOps reqops;
 };
 
-- 
1.7.6

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

* [Qemu-devel] [PATCH 06/35] scsi-disk: report media changed via unit attention sense codes
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (4 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 05/35] scsi: notify the device when unit attention is reported Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 07/35] scsi-disk: add stubs for more MMC commands Paolo Bonzini
                   ` (28 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

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

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-bus.c  |    5 +++++
 hw/scsi-disk.c |   29 ++++++++++++++++++++++++++++-
 hw/scsi.h      |    2 ++
 3 files changed, 35 insertions(+), 1 deletions(-)

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index c190509..867b1a8 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -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
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index a6ef060..880cb22 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -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),
diff --git a/hw/scsi.h b/hw/scsi.h
index 6d40b8e..7004aaa 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -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*/
-- 
1.7.6

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

* [Qemu-devel] [PATCH 07/35] scsi-disk: add stubs for more MMC commands
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (5 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 06/35] scsi-disk: report media changed via unit attention sense codes Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-17 14:27   ` Kevin Wolf
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 08/35] scsi-disk: store valid mode pages in a table Paolo Bonzini
                   ` (27 subsequent siblings)
  34 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

This patch adds a few stub implementations for MMC commands to
scsi-disk, to be filled in later in the series.  It also adds to
scsi-defs.h constants for commands implemented by ide/atapi.c,
when missing.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-defs.h |    3 ++
 hw/scsi-disk.c |   63 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 61 insertions(+), 5 deletions(-)

diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
index 8094698..030d4c2 100644
--- a/hw/scsi-defs.h
+++ b/hw/scsi-defs.h
@@ -113,6 +113,7 @@
 #define READ_12               0xa8
 #define WRITE_12              0xaa
 #define SERVICE_ACTION_IN_12  0xab
+#define READ_DVD_STRUCTURE    0xad
 #define WRITE_VERIFY_12       0xae
 #define VERIFY_12             0xaf
 #define SEARCH_HIGH_12        0xb0
@@ -122,6 +123,8 @@
 #define SEND_VOLUME_TAG       0xb6
 #define READ_DEFECT_DATA_12   0xb7
 #define SET_CD_SPEED          0xbb
+#define MECHANISM_STATUS      0xbd
+#define READ_CD               0xbe
 
 /*
  * SERVICE ACTION IN subcodes
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 880cb22..95a6b77 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -563,6 +563,43 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
     return buflen;
 }
 
+static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
+                                   uint8_t *outbuf)
+{
+    scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
+    return -1;
+}
+
+static int scsi_get_event_status_notification(SCSIDiskState *s,
+                                              SCSIDiskReq *r, uint8_t *outbuf)
+{
+    scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
+    return -1;
+}
+
+static int scsi_get_configuration(SCSIDiskState *s, SCSIDiskReq *r,
+                                  uint8_t *outbuf)
+{
+    if (s->qdev.type != TYPE_ROM) {
+        return -1;
+    }
+    memset(outbuf, 0, 8);
+    /* ??? This should probably return much more information.  For now
+       just return the basic header indicating the CD-ROM profile.  */
+    outbuf[7] = 8; // CD-ROM
+    return 8;
+}
+
+static int scsi_emulate_mechanism_status(SCSIDiskState *s, uint8_t *outbuf)
+{
+    if (s->qdev.type != TYPE_ROM) {
+        return -1;
+    }
+    memset(outbuf, 0, 8);
+    outbuf[5] = 1; // CD-ROM
+    return 8;
+}
+
 static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
                            int page_control)
 {
@@ -947,12 +984,25 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
         outbuf[7] = 0;
         buflen = 8;
         break;
+    case MECHANISM_STATUS:
+        buflen = scsi_emulate_mechanism_status(s, outbuf);
+        if (buflen < 0)
+            goto illegal_request;
+        break;
     case GET_CONFIGURATION:
-        memset(outbuf, 0, 8);
-        /* ??? This should probably return much more information.  For now
-           just return the basic header indicating the CD-ROM profile.  */
-        outbuf[7] = 8; // CD-ROM
-        buflen = 8;
+        buflen = scsi_get_configuration(s, r, outbuf);
+        if (buflen < 0)
+            goto illegal_request;
+        break;
+    case GET_EVENT_STATUS_NOTIFICATION:
+        buflen = scsi_get_event_status_notification(s, r, outbuf);
+        if (buflen < 0)
+            goto illegal_request;
+        break;
+    case READ_DVD_STRUCTURE:
+        buflen = scsi_read_dvd_structure(s, r, outbuf);
+        if (buflen < 0)
+            goto illegal_request;
         break;
     case SERVICE_ACTION_IN_16:
         /* Service Action In subcommands. */
@@ -1055,7 +1105,10 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
     case ALLOW_MEDIUM_REMOVAL:
     case READ_CAPACITY_10:
     case READ_TOC:
+    case READ_DVD_STRUCTURE:
     case GET_CONFIGURATION:
+    case GET_EVENT_STATUS_NOTIFICATION:
+    case MECHANISM_STATUS:
     case SERVICE_ACTION_IN_16:
     case VERIFY_10:
         rc = scsi_disk_emulate_command(r);
-- 
1.7.6

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

* [Qemu-devel] [PATCH 08/35] scsi-disk: store valid mode pages in a table
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (6 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 07/35] scsi-disk: add stubs for more MMC commands Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 09/35] atapi/scsi-disk: make mode page values coherent between the two Paolo Bonzini
                   ` (26 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

A small refactoring of the MODE SENSE implementation in scsi-disk.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |   25 +++++++++++++------------
 1 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 95a6b77..a4aadf2 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -603,10 +603,23 @@ static int scsi_emulate_mechanism_status(SCSIDiskState *s, uint8_t *outbuf)
 static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
                            int page_control)
 {
+    static const int mode_sense_valid[0x3f] = {
+        [MODE_PAGE_HD_GEOMETRY]            = (1 << TYPE_DISK),
+        [MODE_PAGE_FLEXIBLE_DISK_GEOMETRY] = (1 << TYPE_DISK),
+        [MODE_PAGE_CACHING]                = (1 << TYPE_DISK) | (1 << TYPE_ROM),
+        [MODE_PAGE_CAPABILITIES]           = (1 << TYPE_ROM),
+    };
+
     BlockDriverState *bdrv = s->bs;
     int cylinders, heads, secs;
     uint8_t *p = *p_outbuf;
 
+    if ((mode_sense_valid[page] & (1 << s->qdev.type)) == 0) {
+        return -1;
+    }
+
+    p[0] = page;
+
     /*
      * If Changeable Values are requested, a mask denoting those mode parameters
      * that are changeable shall be returned. As we currently don't support
@@ -615,10 +628,6 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
      */
     switch (page) {
     case MODE_PAGE_HD_GEOMETRY:
-        if (s->qdev.type == TYPE_ROM) {
-            return -1;
-        }
-        p[0] = 4;
         p[1] = 0x16;
         if (page_control == 1) { /* Changeable Values */
             break;
@@ -650,10 +659,6 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
         break;
 
     case MODE_PAGE_FLEXIBLE_DISK_GEOMETRY:
-        if (s->qdev.type == TYPE_ROM) {
-            return -1;
-        }
-        p[0] = 5;
         p[1] = 0x1e;
         if (page_control == 1) { /* Changeable Values */
             break;
@@ -703,10 +708,6 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
         break;
 
     case MODE_PAGE_CAPABILITIES:
-        if (s->qdev.type != TYPE_ROM) {
-            return -1;
-        }
-        p[0] = 0x2a;
         p[1] = 0x14;
         if (page_control == 1) { /* Changeable Values */
             break;
-- 
1.7.6

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

* [Qemu-devel] [PATCH 09/35] atapi/scsi-disk: make mode page values coherent between the two
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (7 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 08/35] scsi-disk: store valid mode pages in a table Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-17 15:05   ` Kevin Wolf
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 10/35] scsi-disk: support DVD profile in GET CONFIGURATION Paolo Bonzini
                   ` (25 subsequent siblings)
  34 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

This patch adds to scsi-disk the missing mode page 0x01 for both disk
and CD-ROM drives, and mode page 0x0e for CD drives only.

A few offsets were wrong in atapi.c.  Also change the 2Ah mode page to
expose DVD media read capabilities in the IDE cdrom.  This lets you run
dvd+rw-mediainfo on the virtual DVD drives.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/ide/atapi.c |   12 ++++++------
 hw/scsi-disk.c |   33 ++++++++++++++++++++++++---------
 2 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index 10f161f..c6eb8f0 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -751,7 +751,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
 
             buf[8] = 0x2a;
             buf[9] = 0x12;
-            buf[10] = 0x00;
+            buf[10] = 0x3b; /* read CDR/CDRW/DVDROM/DVDR/DVDRAM */
             buf[11] = 0x00;
 
             /* Claim PLAY_AUDIO capability (0x01) since some Linux
@@ -760,14 +760,14 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
             buf[13] = 3 << 5;
             buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
             if (s->tray_locked) {
-                buf[6] |= 1 << 1;
+                buf[14] |= 1 << 1;
             }
-            buf[15] = 0x00;
-            cpu_to_ube16(&buf[16], 706);
+            buf[15] = 0x00; /* No volume & mute control, no changer */
+            cpu_to_ube16(&buf[16], 704); /* 4x read speed */
             buf[18] = 0;
             buf[19] = 2;
-            cpu_to_ube16(&buf[20], 512);
-            cpu_to_ube16(&buf[22], 706);
+            cpu_to_ube16(&buf[20], 512); /* 512k buffer */
+            cpu_to_ube16(&buf[22], 704); /* 4x read speed current */
             buf[24] = 0;
             buf[25] = 0;
             buf[26] = 0;
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index a4aadf2..837747f 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -607,6 +607,8 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
         [MODE_PAGE_HD_GEOMETRY]            = (1 << TYPE_DISK),
         [MODE_PAGE_FLEXIBLE_DISK_GEOMETRY] = (1 << TYPE_DISK),
         [MODE_PAGE_CACHING]                = (1 << TYPE_DISK) | (1 << TYPE_ROM),
+        [MODE_PAGE_R_W_ERROR]              = (1 << TYPE_DISK) | (1 << TYPE_ROM),
+        [MODE_PAGE_AUDIO_CTL]              = (1 << TYPE_ROM),
         [MODE_PAGE_CAPABILITIES]           = (1 << TYPE_ROM),
     };
 
@@ -707,13 +709,26 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
         }
         break;
 
+    case MODE_PAGE_R_W_ERROR:
+        p[1] = 10;
+        p[2] = 0x80; /* Automatic Write Reallocation Enabled */
+        if (s->qdev.type == TYPE_ROM) {
+            p[3] = 0x20; /* Read Retry Count */
+        }
+        break;
+
+    case MODE_PAGE_AUDIO_CTL:
+        p[1] = 14;
+        break;
+
     case MODE_PAGE_CAPABILITIES:
         p[1] = 0x14;
         if (page_control == 1) { /* Changeable Values */
             break;
         }
-        p[2] = 3; // CD-R & CD-RW read
-        p[3] = 0; // Writing not supported
+
+        p[2] = 0x3b; /* CD-R & CD-RW read */
+        p[3] = 0; /* Writing not supported */
         p[4] = 0x7f; /* Audio, composite, digital out,
                         mode 2 form 1&2, multi session */
         p[5] = 0xff; /* CD DA, DA accurate, RW supported,
@@ -723,17 +738,17 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
         /* Locking supported, jumper present, eject, tray */
         p[7] = 0; /* no volume & mute control, no
                      changer */
-        p[8] = (50 * 176) >> 8; // 50x read speed
+        p[8] = (50 * 176) >> 8; /* 50x read speed */
         p[9] = (50 * 176) & 0xff;
-        p[10] = 0 >> 8; // No volume
-        p[11] = 0 & 0xff;
-        p[12] = 2048 >> 8; // 2M buffer
+        p[10] = 0 >> 8; /* Volume */
+        p[11] = 2 & 0xff;
+        p[12] = 2048 >> 8; /* 2M buffer */
         p[13] = 2048 & 0xff;
-        p[14] = (16 * 176) >> 8; // 16x read speed current
+        p[14] = (16 * 176) >> 8; /* 16x read speed current */
         p[15] = (16 * 176) & 0xff;
-        p[18] = (16 * 176) >> 8; // 16x write speed
+        p[18] = (16 * 176) >> 8; /* 16x write speed */
         p[19] = (16 * 176) & 0xff;
-        p[20] = (16 * 176) >> 8; // 16x write speed current
+        p[20] = (16 * 176) >> 8; /* 16x write speed current */
         p[21] = (16 * 176) & 0xff;
         break;
 
-- 
1.7.6

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

* [Qemu-devel] [PATCH 10/35] scsi-disk: support DVD profile in GET CONFIGURATION
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (8 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 09/35] atapi/scsi-disk: make mode page values coherent between the two Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-17 15:20   ` Kevin Wolf
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 11/35] scsi-disk: support READ DVD STRUCTURE Paolo Bonzini
                   ` (24 subsequent siblings)
  34 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |   50 ++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 42 insertions(+), 8 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 837747f..1786c37 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -563,6 +563,19 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
     return buflen;
 }
 
+static inline bool media_is_dvd(SCSIDiskState *s)
+{
+    uint64_t nb_sectors;
+    if (s->qdev.type != TYPE_ROM) {
+        return false;
+    }
+    if (!bdrv_is_inserted(s->bs)) {
+        return false;
+    }
+    bdrv_get_geometry(s->bs, &nb_sectors);
+    return nb_sectors > CD_MAX_SECTORS;
+}
+
 static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
                                    uint8_t *outbuf)
 {
@@ -577,17 +590,38 @@ static int scsi_get_event_status_notification(SCSIDiskState *s,
     return -1;
 }
 
-static int scsi_get_configuration(SCSIDiskState *s, SCSIDiskReq *r,
-                                  uint8_t *outbuf)
+static int scsi_get_configuration(SCSIDiskState *s, uint8_t *outbuf)
 {
+    int current;
+
     if (s->qdev.type != TYPE_ROM) {
         return -1;
     }
-    memset(outbuf, 0, 8);
-    /* ??? This should probably return much more information.  For now
-       just return the basic header indicating the CD-ROM profile.  */
-    outbuf[7] = 8; // CD-ROM
-    return 8;
+    current = media_is_dvd(s) ? MMC_PROFILE_DVD_ROM : MMC_PROFILE_CD_ROM;
+    memset(outbuf, 0, 40);
+    stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */
+    /* outbuf[4] - outbuf[19]: Feature 0 - Profile list */
+    stw_be_p(&outbuf[6], current);
+    outbuf[10] = 0x03; /* persistent, current */
+    outbuf[11] = 8; /* two profiles */
+    stw_be_p(&outbuf[12], MMC_PROFILE_DVD_ROM);
+    outbuf[14] = (current == MMC_PROFILE_DVD_ROM);
+    stw_be_p(&outbuf[16], MMC_PROFILE_CD_ROM);
+    outbuf[18] = (current == MMC_PROFILE_CD_ROM);
+    /* outbuf[20] - outbuf[31]: Feature 1 - Core feature */
+    stw_be_p(&outbuf[20], 1);
+    outbuf[22] = 0x08 | 0x03; /* version 2, persistent, current */
+    outbuf[23] = 8;
+    stl_be_p(&outbuf[24], 1); /* SCSI */
+    outbuf[28] = 1; /* DBE = 1, mandatory */
+    /* outbuf[32] - outbuf[39]: Feature 3 - Removable media feature */
+    stw_be_p(&outbuf[32], 3);
+    outbuf[34] = 0x08 | 0x03; /* version 2, persistent, current */
+    outbuf[35] = 4;
+    outbuf[36] = 0x39; /* tray, load=1, eject=1, unlocked at powerup, lock=1 */
+    /* TODO: Random readable, CD read, DVD read, drive serial number,
+       power management */
+    return 40;
 }
 
 static int scsi_emulate_mechanism_status(SCSIDiskState *s, uint8_t *outbuf)
@@ -1006,7 +1040,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
             goto illegal_request;
         break;
     case GET_CONFIGURATION:
-        buflen = scsi_get_configuration(s, r, outbuf);
+        buflen = scsi_get_configuration(s, outbuf);
         if (buflen < 0)
             goto illegal_request;
         break;
-- 
1.7.6

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

* [Qemu-devel] [PATCH 11/35] scsi-disk: support READ DVD STRUCTURE
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (9 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 10/35] scsi-disk: support DVD profile in GET CONFIGURATION Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-21 11:42   ` Kevin Wolf
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 12/35] scsi-disk: report media changed via GET EVENT STATUS NOTIFICATION Paolo Bonzini
                   ` (23 subsequent siblings)
  34 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |  101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 100 insertions(+), 1 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 1786c37..14db6a0 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -576,10 +576,109 @@ static inline bool media_is_dvd(SCSIDiskState *s)
     return nb_sectors > CD_MAX_SECTORS;
 }
 
+static inline bool media_is_cd(SCSIDiskState *s)
+{
+    uint64_t nb_sectors;
+    if (s->qdev.type != TYPE_ROM) {
+        return false;
+    }
+    if (!bdrv_is_inserted(s->bs)) {
+        return false;
+    }
+    bdrv_get_geometry(s->bs, &nb_sectors);
+    return nb_sectors <= CD_MAX_SECTORS;
+}
+
 static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
                                    uint8_t *outbuf)
 {
-    scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
+    static const int rds_caps_size[5] = {
+        [0] = 2048 + 4,
+        [1] = 4 + 4,
+        [3] = 188 + 4,
+        [4] = 2048 + 4,
+    };
+
+    uint8_t media = r->req.cmd.buf[1];
+    uint8_t layer = r->req.cmd.buf[6];
+    uint8_t format = r->req.cmd.buf[7];
+    int size = -1;
+
+    if (s->qdev.type != TYPE_ROM || !bdrv_is_inserted(s->bs)) {
+        return -1;
+    }
+    if (s->tray_open || !bdrv_is_inserted(s->bs)) {
+        scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
+        return -1;
+    }
+    if (media_is_cd(s)) {
+        scsi_check_condition(r, SENSE_CODE(INCOMPATIBLE_FORMAT));
+        return -1;
+    }
+    if (media != 0) {
+        scsi_check_condition(r, SENSE_CODE(INCOMPATIBLE_FORMAT));
+        return -1;
+    }
+
+    if (format != 0xff) {
+        if (format >= sizeof(rds_caps_size) / sizeof(rds_caps_size[0])) {
+            return -1;
+        }
+        size = rds_caps_size[format];
+        memset(outbuf, 0, size);
+    }
+
+    switch (format) {
+    case 0x00: {
+        /* Physical format information */
+        uint64_t nb_sectors;
+        if (layer != 0)
+            goto fail;
+        bdrv_get_geometry(s->bs, &nb_sectors);
+
+        outbuf[4] = 1;   /* DVD-ROM, part version 1 */
+        outbuf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
+        outbuf[6] = 1;   /* one layer, read-only (per MMC-2 spec) */
+        outbuf[7] = 0;   /* default densities */
+
+        stl_be_p(&outbuf[12], (nb_sectors >> 2) - 1); /* end sector */
+        stl_be_p(&outbuf[16], (nb_sectors >> 2) - 1); /* l0 end sector */
+        break;
+    }
+
+    case 0x01: /* DVD copyright information, all zeros */
+        break;
+
+    case 0x03: /* BCA information - invalid field for no BCA info */
+        return -1;
+
+    case 0x04: /* DVD disc manufacturing information, all zeros */
+        break;
+
+    case 0xff: { /* List capabilities */
+        int i;
+        size = 4;
+        for (i = 0; i < sizeof(rds_caps_size) / sizeof(rds_caps_size[0]); i++) {
+            if (!rds_caps_size[i]) {
+                continue;
+            }
+            outbuf[size] = i;
+            outbuf[size + 1] = 0x40; /* Not writable, readable */
+            stw_be_p(&outbuf[size + 2], rds_caps_size[i]);
+            size += 4;
+        }
+        break;
+     }
+
+    default:
+        return -1;
+    }
+
+    /* Size of buffer, not including 2 byte size field */
+    stw_be_p(outbuf, size - 2);
+    return size;
+
+fail:
     return -1;
 }
 
-- 
1.7.6

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

* [Qemu-devel] [PATCH 12/35] scsi-disk: report media changed via GET EVENT STATUS NOTIFICATION
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (10 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 11/35] scsi-disk: support READ DVD STRUCTURE Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-21 11:54   ` Kevin Wolf
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 13/35] scsi: move tcq/ndev to SCSIBusOps (now SCSIBusInfo) Paolo Bonzini
                   ` (22 subsequent siblings)
  34 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

This adds support for media change notification via the GET EVENT STATUS
NOTIFICATION command, used by Linux versions 2.6.38 and newer.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |   57 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 14db6a0..ce71df4 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -72,6 +72,7 @@ struct SCSIDiskState
     uint32_t removable;
     uint64_t max_lba;
     bool media_changed;
+    bool media_event;
     QEMUBH *bh;
     char *version;
     char *serial;
@@ -682,11 +683,58 @@ fail:
     return -1;
 }
 
-static int scsi_get_event_status_notification(SCSIDiskState *s,
-                                              SCSIDiskReq *r, uint8_t *outbuf)
+static int scsi_event_status_media(SCSIDiskState *s, uint8_t *outbuf)
 {
-    scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
-    return -1;
+    uint8_t event_code, media_status;
+
+    media_status = 0;
+    if (s->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->media_event) {
+        event_code = MEC_NEW_MEDIA;
+        s->media_event = false;
+    }
+
+    outbuf[0] = event_code;
+    outbuf[1] = media_status;
+
+    /* These fields are reserved, just clear them. */
+    outbuf[2] = 0;
+    outbuf[3] = 0;
+    return 4;
+}
+
+static int scsi_get_event_status_notification(SCSIDiskState *s, SCSIDiskReq *r,
+                                              uint8_t *outbuf)
+{
+    int size;
+    uint8_t *buf = r->req.cmd.buf;
+    uint8_t notification_class_request = buf[4];
+    if (s->qdev.type != TYPE_ROM) {
+        return -1;
+    }
+    if ((buf[1] & 1) == 0) {
+        /* asynchronous */
+        return -1;
+    }
+
+    size = 4;
+    outbuf[0] = outbuf[1] = 0;
+    outbuf[3] = 1 << GESN_MEDIA; /* supported events */
+    if (notification_class_request & (1 << GESN_MEDIA)) {
+        outbuf[2] = GESN_MEDIA;
+        size += scsi_event_status_media(s, &outbuf[size]);
+    } else {
+        outbuf[2] = 0x80;
+    }
+    stw_be_p(outbuf, size - 4);
+    return size;
 }
 
 static int scsi_get_configuration(SCSIDiskState *s, uint8_t *outbuf)
@@ -1416,6 +1464,7 @@ static void scsi_cd_change_media_cb(void *opaque, bool load)
     s->media_changed = load;
     s->tray_open = !load;
     s->qdev.unit_attention = SENSE_CODE(UNIT_ATTENTION_NO_MEDIUM);
+    s->media_event = true;
 }
 
 static bool scsi_cd_is_tray_open(void *opaque)
-- 
1.7.6

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

* [Qemu-devel] [PATCH 13/35] scsi: move tcq/ndev to SCSIBusOps (now SCSIBusInfo)
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (11 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 12/35] scsi-disk: report media changed via GET EVENT STATUS NOTIFICATION Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-21 12:01   ` Kevin Wolf
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 14/35] qdev: switch children device list to QTAILQ Paolo Bonzini
                   ` (21 subsequent siblings)
  34 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/esp.c         |    7 +++++--
 hw/lsi53c895a.c  |    9 ++++++---
 hw/scsi-bus.c    |   27 ++++++++++++---------------
 hw/scsi-disk.c   |    2 +-
 hw/scsi.h        |   11 +++++------
 hw/spapr_vscsi.c |    8 +++++---
 hw/usb-msd.c     |    7 +++++--
 7 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/hw/esp.c b/hw/esp.c
index 697c2c5..d3fb1c6 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -720,7 +720,10 @@ void esp_init(target_phys_addr_t espaddr, int it_shift,
     *dma_enable = qdev_get_gpio_in(dev, 1);
 }
 
-static const struct SCSIBusOps esp_scsi_ops = {
+static const struct SCSIBusInfo esp_scsi_info = {
+    .tcq = false,
+    .ndev = ESP_MAX_DEVS,
+
     .transfer_data = esp_transfer_data,
     .complete = esp_command_complete,
     .cancel = esp_request_cancelled
@@ -740,7 +743,7 @@ static int esp_init1(SysBusDevice *dev)
 
     qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);
 
-    scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, &esp_scsi_ops);
+    scsi_bus_new(&s->bus, &dev->qdev, &esp_scsi_info);
     return scsi_bus_legacy_handle_cmdline(&s->bus);
 }
 
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index e077ec0..4eeb496 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -1686,7 +1686,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
                 DeviceState *dev;
                 int id;
 
-                for (id = 0; id < s->bus.ndev; id++) {
+                for (id = 0; id < LSI_MAX_DEVS; id++) {
                     if (s->bus.devs[id]) {
                         dev = &s->bus.devs[id]->qdev;
                         dev->info->reset(dev);
@@ -2091,7 +2091,10 @@ static int lsi_scsi_uninit(PCIDevice *d)
     return 0;
 }
 
-static const struct SCSIBusOps lsi_scsi_ops = {
+static const struct SCSIBusInfo lsi_scsi_info = {
+    .tcq = true,
+    .ndev = LSI_MAX_DEVS,
+
     .transfer_data = lsi_transfer_data,
     .complete = lsi_command_complete,
     .cancel = lsi_request_cancelled
@@ -2118,7 +2121,7 @@ static int lsi_scsi_init(PCIDevice *dev)
     pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_io);
     QTAILQ_INIT(&s->queue);
 
-    scsi_bus_new(&s->bus, &dev->qdev, 1, LSI_MAX_DEVS, &lsi_scsi_ops);
+    scsi_bus_new(&s->bus, &dev->qdev, &lsi_scsi_info);
     if (!dev->qdev.hotplugged) {
         return scsi_bus_legacy_handle_cmdline(&s->bus);
     }
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 867b1a8..d9d4e18 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -24,14 +24,11 @@ static struct BusInfo scsi_bus_info = {
 static int next_scsi_bus;
 
 /* Create a scsi bus, and attach devices to it.  */
-void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev,
-                  const SCSIBusOps *ops)
+void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info)
 {
     qbus_create_inplace(&bus->qbus, &scsi_bus_info, host, NULL);
     bus->busnr = next_scsi_bus++;
-    bus->tcq = tcq;
-    bus->ndev = ndev;
-    bus->ops = ops;
+    bus->info = info;
     bus->qbus.allow_hotplug = 1;
 }
 
@@ -43,12 +40,12 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
     int rc = -1;
 
     if (dev->id == -1) {
-        for (dev->id = 0; dev->id < bus->ndev; dev->id++) {
+        for (dev->id = 0; dev->id < bus->info->ndev; dev->id++) {
             if (bus->devs[dev->id] == NULL)
                 break;
         }
     }
-    if (dev->id >= bus->ndev) {
+    if (dev->id >= bus->info->ndev) {
         error_report("bad scsi device id: %d", dev->id);
         goto err;
     }
@@ -120,7 +117,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
     int res = 0, unit;
 
     loc_push_none(&loc);
-    for (unit = 0; unit < bus->ndev; unit++) {
+    for (unit = 0; unit < bus->info->ndev; unit++) {
         dinfo = drive_get(IF_SCSI, bus->busnr, unit);
         if (dinfo == NULL) {
             continue;
@@ -265,7 +262,7 @@ static bool scsi_target_emulate_inquiry(SCSITargetReq *r)
         r->buf[2] = 5; /* Version */
         r->buf[3] = 2 | 0x10; /* HiSup, response data format */
         r->buf[4] = r->len - 5; /* Additional Length = (Len - 1) - 4 */
-        r->buf[7] = 0x10 | (r->req.bus->tcq ? 0x02 : 0); /* Sync, TCQ.  */
+        r->buf[7] = 0x10 | (r->req.bus->info->tcq ? 0x02 : 0); /* Sync, TCQ.  */
         memcpy(&r->buf[8], "QEMU    ", 8);
         memcpy(&r->buf[16], "QEMU TARGET     ", 16);
         strncpy((char *) &r->buf[32], QEMU_VERSION, 4);
@@ -1062,7 +1059,7 @@ void scsi_req_continue(SCSIRequest *req)
 void scsi_req_data(SCSIRequest *req, int len)
 {
     trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
-    req->bus->ops->transfer_data(req, len);
+    req->bus->info->transfer_data(req, len);
 }
 
 void scsi_req_print(SCSIRequest *req)
@@ -1121,7 +1118,7 @@ void scsi_req_complete(SCSIRequest *req, int status)
 
     scsi_req_ref(req);
     scsi_req_dequeue(req);
-    req->bus->ops->complete(req, req->status);
+    req->bus->info->complete(req, req->status);
     scsi_req_unref(req);
 }
 
@@ -1132,8 +1129,8 @@ void scsi_req_cancel(SCSIRequest *req)
     }
     scsi_req_ref(req);
     scsi_req_dequeue(req);
-    if (req->bus->ops->cancel) {
-        req->bus->ops->cancel(req);
+    if (req->bus->info->cancel) {
+        req->bus->info->cancel(req);
     }
     scsi_req_unref(req);
 }
@@ -1164,13 +1161,13 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
     char path[100];
     int i;
 
-    for (i = 0; i < bus->ndev; i++) {
+    for (i = 0; i < bus->info->ndev; i++) {
         if (bus->devs[i] == d) {
             break;
         }
     }
 
-    assert(i != bus->ndev);
+    assert(i != bus->info->ndev);
 
     snprintf(path, sizeof(path), "%s@%x", qdev_fw_name(dev), i);
 
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index ce71df4..97a7335 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -560,7 +560,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
     }
 
     /* Sync data transfer and TCQ.  */
-    outbuf[7] = 0x10 | (req->bus->tcq ? 0x02 : 0);
+    outbuf[7] = 0x10 | (req->bus->info->tcq ? 0x02 : 0);
     return buflen;
 }
 
diff --git a/hw/scsi.h b/hw/scsi.h
index 7004aaa..b76c4ee 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -9,7 +9,7 @@
 #define SCSI_CMD_BUF_SIZE     16
 
 typedef struct SCSIBus SCSIBus;
-typedef struct SCSIBusOps SCSIBusOps;
+typedef struct SCSIBusInfo SCSIBusInfo;
 typedef struct SCSICommand SCSICommand;
 typedef struct SCSIDevice SCSIDevice;
 typedef struct SCSIDeviceInfo SCSIDeviceInfo;
@@ -97,7 +97,8 @@ struct SCSIDeviceInfo {
     SCSIReqOps reqops;
 };
 
-struct SCSIBusOps {
+struct SCSIBusInfo {
+    int tcq, ndev;
     void (*transfer_data)(SCSIRequest *req, uint32_t arg);
     void (*complete)(SCSIRequest *req, uint32_t arg);
     void (*cancel)(SCSIRequest *req);
@@ -108,14 +109,12 @@ struct SCSIBus {
     int busnr;
 
     SCSISense unit_attention;
-    int tcq, ndev;
-    const SCSIBusOps *ops;
+    const SCSIBusInfo *info;
 
     SCSIDevice *devs[MAX_SCSI_DEVS];
 };
 
-void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev,
-                  const SCSIBusOps *ops);
+void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info);
 void scsi_qdev_register(SCSIDeviceInfo *info);
 
 static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index e8426d7..6c5faf2 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -862,7 +862,10 @@ static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
     return 0;
 }
 
-static const struct SCSIBusOps vscsi_scsi_ops = {
+static const struct SCSIBusInfo vscsi_scsi_info = {
+    .tcq = true,
+    .ndev = 63, /* logical unit addressing format */
+
     .transfer_data = vscsi_transfer_data,
     .complete = vscsi_command_complete,
     .cancel = vscsi_request_cancelled
@@ -883,8 +886,7 @@ static int spapr_vscsi_init(VIOsPAPRDevice *dev)
 
     dev->crq.SendFunc = vscsi_do_crq;
 
-    scsi_bus_new(&s->bus, &dev->qdev, 1, VSCSI_REQ_LIMIT,
-                 &vscsi_scsi_ops);
+    scsi_bus_new(&s->bus, &dev->qdev, &vscsi_scsi_info);
     if (!dev->qdev.hotplugged) {
         scsi_bus_legacy_handle_cmdline(&s->bus);
     }
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index e92434c..d0e0cd3 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -492,7 +492,10 @@ static void usb_msd_password_cb(void *opaque, int err)
         qdev_unplug(&s->dev.qdev);
 }
 
-static const struct SCSIBusOps usb_msd_scsi_ops = {
+static const struct SCSIBusInfo usb_msd_scsi_info = {
+    .tcq = false,
+    .ndev = 1,
+
     .transfer_data = usb_msd_transfer_data,
     .complete = usb_msd_command_complete,
     .cancel = usb_msd_request_cancelled
@@ -533,7 +536,7 @@ static int usb_msd_initfn(USBDevice *dev)
     }
 
     usb_desc_init(dev);
-    scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, &usb_msd_scsi_ops);
+    scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info);
     s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable);
     if (!s->scsi_dev) {
         return -1;
-- 
1.7.6

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

* [Qemu-devel] [PATCH 14/35] qdev: switch children device list to QTAILQ
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (12 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 13/35] scsi: move tcq/ndev to SCSIBusOps (now SCSIBusInfo) Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 15/35] scsi: remove devs array from SCSIBus Paolo Bonzini
                   ` (20 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

SCSI buses will need to read the children list first-to-last.  This
requires using a QTAILQ, because hell breaks loose if you just try
inserting at the tail (thus reversing the order of all existing
visits from last-to-first to first-to-tail).

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/acpi_piix4.c      |    4 ++--
 hw/i2c.c             |    2 +-
 hw/intel-hda.c       |    6 +++---
 hw/qdev.c            |   24 ++++++++++++------------
 hw/qdev.h            |    4 ++--
 hw/s390-virtio-bus.c |    4 ++--
 hw/spapr_vio.c       |    6 +++---
 hw/ssi.c             |    6 +++---
 8 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 29f0f76..d9075e6 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -276,7 +276,7 @@ static void piix4_update_hotplug(PIIX4PMState *s)
 
     s->pci0_hotplug_enable = ~0;
 
-    QLIST_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
+    QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
         PCIDeviceInfo *info = container_of(qdev->info, PCIDeviceInfo, qdev);
         PCIDevice *pdev = DO_UPCAST(PCIDevice, qdev, qdev);
         int slot = PCI_SLOT(pdev->devfn);
@@ -486,7 +486,7 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
     PCIDeviceInfo *info;
     int slot = ffs(val) - 1;
 
-    QLIST_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
+    QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
         dev = DO_UPCAST(PCIDevice, qdev, qdev);
         info = container_of(qdev->info, PCIDeviceInfo, qdev);
         if (PCI_SLOT(dev->devfn) == slot && !info->no_hotplug) {
diff --git a/hw/i2c.c b/hw/i2c.c
index 49b9ecb..9bcf3e1 100644
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -84,7 +84,7 @@ int i2c_start_transfer(i2c_bus *bus, uint8_t address, int recv)
     DeviceState *qdev;
     i2c_slave *slave = NULL;
 
-    QLIST_FOREACH(qdev, &bus->qbus.children, sibling) {
+    QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) {
         i2c_slave *candidate = I2C_SLAVE_FROM_QDEV(qdev);
         if (candidate->address == address) {
             slave = candidate;
diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index 4272204..c4e8c51 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -86,7 +86,7 @@ HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
     DeviceState *qdev;
     HDACodecDevice *cdev;
 
-    QLIST_FOREACH(qdev, &bus->qbus.children, sibling) {
+    QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) {
         cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
         if (cdev->cad == cad) {
             return cdev;
@@ -489,7 +489,7 @@ static void intel_hda_notify_codecs(IntelHDAState *d, uint32_t stream, bool runn
     DeviceState *qdev;
     HDACodecDevice *cdev;
 
-    QLIST_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
+    QTAILQ_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
         cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
         if (cdev->info->stream) {
             cdev->info->stream(cdev, stream, running);
@@ -1112,7 +1112,7 @@ static void intel_hda_reset(DeviceState *dev)
     d->wall_base_ns = qemu_get_clock_ns(vm_clock);
 
     /* reset codecs */
-    QLIST_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
+    QTAILQ_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
         cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
         if (qdev->info->reset) {
             qdev->info->reset(qdev);
diff --git a/hw/qdev.c b/hw/qdev.c
index a223d41..50976dd 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -91,7 +91,7 @@ static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
     qdev_prop_set_defaults(dev, dev->info->props);
     qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
     qdev_prop_set_globals(dev);
-    QLIST_INSERT_HEAD(&bus->children, dev, sibling);
+    QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
     if (qdev_hotplug) {
         assert(bus->allow_hotplug);
         dev->hotplugged = 1;
@@ -408,7 +408,7 @@ void qdev_free(DeviceState *dev)
         if (dev->opts)
             qemu_opts_del(dev->opts);
     }
-    QLIST_REMOVE(dev, sibling);
+    QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
     for (prop = dev->info->props; prop && prop->name; prop++) {
         if (prop->info->free) {
             prop->info->free(dev, prop);
@@ -510,7 +510,7 @@ int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
         }
     }
 
-    QLIST_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(dev, &bus->children, sibling) {
         err = qdev_walk_children(dev, devfn, busfn, opaque);
         if (err < 0) {
             return err;
@@ -560,7 +560,7 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name,
         return bus;
     }
 
-    QLIST_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(dev, &bus->children, sibling) {
         QLIST_FOREACH(child, &dev->child_bus, sibling) {
             ret = qbus_find_recursive(child, name, info);
             if (ret) {
@@ -576,7 +576,7 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id)
     DeviceState *dev, *ret;
     BusState *child;
 
-    QLIST_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(dev, &bus->children, sibling) {
         if (dev->id && strcmp(dev->id, id) == 0)
             return dev;
         QLIST_FOREACH(child, &dev->child_bus, sibling) {
@@ -609,7 +609,7 @@ static void qbus_list_dev(BusState *bus)
     const char *sep = " ";
 
     error_printf("devices at \"%s\":", bus->name);
-    QLIST_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(dev, &bus->children, sibling) {
         error_printf("%s\"%s\"", sep, dev->info->name);
         if (dev->id)
             error_printf("/\"%s\"", dev->id);
@@ -640,17 +640,17 @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem)
      *   (2) driver name
      *   (3) driver alias, if present
      */
-    QLIST_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(dev, &bus->children, sibling) {
         if (dev->id  &&  strcmp(dev->id, elem) == 0) {
             return dev;
         }
     }
-    QLIST_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(dev, &bus->children, sibling) {
         if (strcmp(dev->info->name, elem) == 0) {
             return dev;
         }
     }
-    QLIST_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(dev, &bus->children, sibling) {
         if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
             return dev;
         }
@@ -774,7 +774,7 @@ void qbus_create_inplace(BusState *bus, BusInfo *info,
         bus->name = buf;
     }
 
-    QLIST_INIT(&bus->children);
+    QTAILQ_INIT(&bus->children);
     if (parent) {
         QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
         parent->num_child_bus++;
@@ -809,7 +809,7 @@ void qbus_free(BusState *bus)
 {
     DeviceState *dev;
 
-    while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
+    while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
         qdev_free(dev);
     }
     if (bus->parent) {
@@ -878,7 +878,7 @@ static void qbus_print(Monitor *mon, BusState *bus, int indent)
     qdev_printf("bus: %s\n", bus->name);
     indent += 2;
     qdev_printf("type %s\n", bus->info->name);
-    QLIST_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(dev, &bus->children, sibling) {
         qdev_print(mon, dev, indent);
     }
 }
diff --git a/hw/qdev.h b/hw/qdev.h
index 8a13ec9..ff524cb 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -42,7 +42,7 @@ struct DeviceState {
     qemu_irq *gpio_in;
     QLIST_HEAD(, BusState) child_bus;
     int num_child_bus;
-    QLIST_ENTRY(DeviceState) sibling;
+    QTAILQ_ENTRY(DeviceState) sibling;
     int instance_id_alias;
     int alias_required_for_version;
 };
@@ -73,7 +73,7 @@ struct BusState {
     const char *name;
     int allow_hotplug;
     int qdev_allocated;
-    QLIST_HEAD(, DeviceState) children;
+    QTAILQ_HEAD(, DeviceState) children;
     QLIST_ENTRY(BusState) sibling;
 };
 
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index e2f3e32..0ce6406 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -274,7 +274,7 @@ VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
     DeviceState *dev;
     int i;
 
-    QLIST_FOREACH(dev, &bus->bus.children, sibling) {
+    QTAILQ_FOREACH(dev, &bus->bus.children, sibling) {
         _dev = (VirtIOS390Device *)dev;
         for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
             if (!virtio_queue_get_addr(_dev->vdev, i))
@@ -297,7 +297,7 @@ VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem)
     VirtIOS390Device *_dev;
     DeviceState *dev;
 
-    QLIST_FOREACH(dev, &bus->bus.children, sibling) {
+    QTAILQ_FOREACH(dev, &bus->bus.children, sibling) {
         _dev = (VirtIOS390Device *)dev;
         if (_dev->dev_offs == mem) {
             return _dev;
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 35818e1..977603f 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -63,7 +63,7 @@ VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
     DeviceState *qdev;
     VIOsPAPRDevice *dev = NULL;
 
-    QLIST_FOREACH(qdev, &bus->bus.children, sibling) {
+    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
         dev = (VIOsPAPRDevice *)qdev;
         if (dev->reg == reg) {
             break;
@@ -588,7 +588,7 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
         return;
     }
 
-    QLIST_FOREACH(qdev, &bus->bus.children, sibling) {
+    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
         dev = (VIOsPAPRDevice *)qdev;
         spapr_vio_quiesce_one(dev);
     }
@@ -726,7 +726,7 @@ int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
     DeviceState *qdev;
     int ret = 0;
 
-    QLIST_FOREACH(qdev, &bus->bus.children, sibling) {
+    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
         VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
 
         ret = vio_make_devnode(dev, fdt);
diff --git a/hw/ssi.c b/hw/ssi.c
index 3f4c5f9..9842fe7 100644
--- a/hw/ssi.c
+++ b/hw/ssi.c
@@ -25,8 +25,8 @@ static int ssi_slave_init(DeviceState *dev, DeviceInfo *base_info)
     SSIBus *bus;
 
     bus = FROM_QBUS(SSIBus, qdev_get_parent_bus(dev));
-    if (QLIST_FIRST(&bus->qbus.children) != dev
-        || QLIST_NEXT(dev, sibling) != NULL) {
+    if (QTAILQ_FIRST(&bus->qbus.children) != dev
+        || QTAILQ_NEXT(dev, sibling) != NULL) {
         hw_error("Too many devices on SSI bus");
     }
 
@@ -61,7 +61,7 @@ uint32_t ssi_transfer(SSIBus *bus, uint32_t val)
 {
     DeviceState *dev;
     SSISlave *slave;
-    dev = QLIST_FIRST(&bus->qbus.children);
+    dev = QTAILQ_FIRST(&bus->qbus.children);
     if (!dev) {
         return 0;
     }
-- 
1.7.6

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

* [Qemu-devel] [PATCH 15/35] scsi: remove devs array from SCSIBus
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (13 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 14/35] qdev: switch children device list to QTAILQ Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-21 12:31   ` Kevin Wolf
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 16/35] scsi: implement REPORT LUNS for arbitrary LUNs Paolo Bonzini
                   ` (19 subsequent siblings)
  34 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

Change the devs array into a linked list, and add a scsi_device_find
function to navigate the children list instead.  This lets the SCSI
bus use more complex addressing.

scsi_device_find may return another LUN on the same target if none is
found that matches exactly.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/esp.c         |    5 +++--
 hw/lsi53c895a.c  |   22 +++++++---------------
 hw/qdev.h        |    2 +-
 hw/scsi-bus.c    |   53 ++++++++++++++++++++++++++++++-----------------------
 hw/scsi.h        |    3 +--
 hw/spapr_vscsi.c |   14 ++++++--------
 6 files changed, 48 insertions(+), 51 deletions(-)

diff --git a/hw/esp.c b/hw/esp.c
index d3fb1c6..8e17005 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -217,7 +217,8 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
         s->async_len = 0;
     }
 
-    if (target >= ESP_MAX_DEVS || !s->bus.devs[target]) {
+    s->current_dev = scsi_device_find(&s->bus, target, 0);
+    if (!s->current_dev) {
         // No such drive
         s->rregs[ESP_RSTAT] = 0;
         s->rregs[ESP_RINTR] = INTR_DC;
@@ -225,7 +226,6 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
         esp_raise_irq(s);
         return 0;
     }
-    s->current_dev = s->bus.devs[target];
     return dmalen;
 }
 
@@ -236,6 +236,7 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
 
     trace_esp_do_busid_cmd(busid);
     lun = busid & 7;
+    s->current_dev = scsi_device_find(&s->bus, s->current_dev->id, lun);
     s->current_req = scsi_req_new(s->current_dev, 0, lun, buf, NULL);
     datalen = scsi_req_enqueue(s->current_req);
     s->ti_size = datalen;
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 4eeb496..c15f167 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -531,7 +531,7 @@ static void lsi_bad_selection(LSIState *s, uint32_t id)
 /* Initiate a SCSI layer data transfer.  */
 static void lsi_do_dma(LSIState *s, int out)
 {
-    uint32_t count, id;
+    uint32_t count;
     target_phys_addr_t addr;
     SCSIDevice *dev;
 
@@ -542,12 +542,8 @@ static void lsi_do_dma(LSIState *s, int out)
         return;
     }
 
-    id = (s->current->tag >> 8) & 0xf;
-    dev = s->bus.devs[id];
-    if (!dev) {
-        lsi_bad_selection(s, id);
-        return;
-    }
+    dev = s->current->req->dev;
+    assert(dev);
 
     count = s->dbc;
     if (count > s->current->dma_len)
@@ -771,7 +767,7 @@ static void lsi_do_command(LSIState *s)
     s->command_complete = 0;
 
     id = (s->select_tag >> 8) & 0xf;
-    dev = s->bus.devs[id];
+    dev = scsi_device_find(&s->bus, id, s->current_lun);
     if (!dev) {
         lsi_bad_selection(s, id);
         return;
@@ -1202,7 +1198,7 @@ again:
                 }
                 s->sstat0 |= LSI_SSTAT0_WOA;
                 s->scntl1 &= ~LSI_SCNTL1_IARB;
-                if (id >= LSI_MAX_DEVS || !s->bus.devs[id]) {
+                if (!scsi_device_find(&s->bus, id, 0)) {
                     lsi_bad_selection(s, id);
                     break;
                 }
@@ -1684,13 +1680,9 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
         if (val & LSI_SCNTL1_RST) {
             if (!(s->sstat0 & LSI_SSTAT0_RST)) {
                 DeviceState *dev;
-                int id;
 
-                for (id = 0; id < LSI_MAX_DEVS; id++) {
-                    if (s->bus.devs[id]) {
-                        dev = &s->bus.devs[id]->qdev;
-                        dev->info->reset(dev);
-                    }
+                QTAILQ_FOREACH(dev, &s->bus.qbus.children, sibling) {
+                    dev->info->reset(dev);
                 }
                 s->sstat0 |= LSI_SSTAT0_RST;
                 lsi_script_scsi_interrupt(s, LSI_SIST0_RST, 0);
diff --git a/hw/qdev.h b/hw/qdev.h
index ff524cb..e5ad781 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -73,7 +73,7 @@ struct BusState {
     const char *name;
     int allow_hotplug;
     int qdev_allocated;
-    QTAILQ_HEAD(, DeviceState) children;
+    QTAILQ_HEAD(ChildrenHead, DeviceState) children;
     QLIST_ENTRY(BusState) sibling;
 };
 
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index d9d4e18..7104e98 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -37,12 +37,16 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
     SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
     SCSIDeviceInfo *info = DO_UPCAST(SCSIDeviceInfo, qdev, base);
     SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
+    SCSIDevice *olddev;
     int rc = -1;
 
     if (dev->id == -1) {
-        for (dev->id = 0; dev->id < bus->info->ndev; dev->id++) {
-            if (bus->devs[dev->id] == NULL)
+        int id;
+        for (id = 0; id < bus->info->ndev; id++) {
+            if (!scsi_device_find(bus, id, 0)) {
+                dev->id = id;
                 break;
+            }
         }
     }
     if (dev->id >= bus->info->ndev) {
@@ -50,17 +54,14 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
         goto err;
     }
 
-    if (bus->devs[dev->id]) {
-        qdev_free(&bus->devs[dev->id]->qdev);
+    olddev = scsi_device_find(bus, dev->id, dev->lun);
+    if (olddev && dev->lun == olddev->lun) {
+        qdev_free(&olddev->qdev);
     }
-    bus->devs[dev->id] = dev;
 
     dev->info = info;
     QTAILQ_INIT(&dev->requests);
     rc = dev->info->init(dev);
-    if (rc != 0) {
-        bus->devs[dev->id] = NULL;
-    }
 
 err:
     return rc;
@@ -69,13 +70,10 @@ err:
 static int scsi_qdev_exit(DeviceState *qdev)
 {
     SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
-    SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
 
-    assert(bus->devs[dev->id] != NULL);
-    if (bus->devs[dev->id]->info->destroy) {
-        bus->devs[dev->id]->info->destroy(bus->devs[dev->id]);
+    if (dev->info->destroy) {
+        dev->info->destroy(dev);
     }
-    bus->devs[dev->id] = NULL;
     return 0;
 }
 
@@ -1157,19 +1155,28 @@ void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense)
 static char *scsibus_get_fw_dev_path(DeviceState *dev)
 {
     SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev);
-    SCSIBus *bus = scsi_bus_from_device(d);
     char path[100];
-    int i;
 
-    for (i = 0; i < bus->info->ndev; i++) {
-        if (bus->devs[i] == d) {
-            break;
-        }
-    }
+    snprintf(path, sizeof(path), "%s@%d:%d:%d", qdev_fw_name(dev),
+             0, d->id, d->lun);
 
-    assert(i != bus->info->ndev);
+    return strdup(path);
+}
+
+SCSIDevice *scsi_device_find(SCSIBus *bus, int id, int lun)
+{
+    DeviceState *qdev;
+    SCSIDevice *target_dev = NULL;
 
-    snprintf(path, sizeof(path), "%s@%x", qdev_fw_name(dev), i);
+    QTAILQ_FOREACH_REVERSE(qdev, &bus->qbus.children, ChildrenHead, sibling) {
+        SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
 
-    return strdup(path);
+        if (dev->id == id) {
+            if (dev->lun == lun) {
+                return dev;
+            }
+            target_dev = dev;
+        }
+    }
+    return target_dev;
 }
diff --git a/hw/scsi.h b/hw/scsi.h
index b76c4ee..add3d2d 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -110,8 +110,6 @@ struct SCSIBus {
 
     SCSISense unit_attention;
     const SCSIBusInfo *info;
-
-    SCSIDevice *devs[MAX_SCSI_DEVS];
 };
 
 void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info);
@@ -195,5 +193,6 @@ void scsi_req_abort(SCSIRequest *req, int status);
 void scsi_req_cancel(SCSIRequest *req);
 void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
 int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
+SCSIDevice *scsi_device_find(SCSIBus *bus, int target, int lun);
 
 #endif
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index 6c5faf2..aae845a 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -129,11 +129,12 @@ static void vscsi_put_req(vscsi_req *req)
     req->active = 0;
 }
 
-static void vscsi_decode_id_lun(uint64_t srp_lun, int *id, int *lun)
+static SCSIDevice *vscsi_device_find(SCSIBus *bus, uint64_t srp_lun, int *lun)
 {
     /* XXX Figure that one out properly ! This is crackpot */
-    *id = (srp_lun >> 56) & 0x7f;
+    int id = (srp_lun >> 56) & 0x7f;
     *lun = (srp_lun >> 48) & 0xff;
+    return scsi_device_find (bus, id, *lun);
 }
 
 static int vscsi_send_iu(VSCSIState *s, vscsi_req *req,
@@ -582,14 +583,11 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
 {
     union srp_iu *srp = &req->iu.srp;
     SCSIDevice *sdev;
-    int n, id, lun;
+    int n, lun;
 
-    vscsi_decode_id_lun(be64_to_cpu(srp->cmd.lun), &id, &lun);
-
-    /* Qemu vs. linux issue with LUNs to be sorted out ... */
-    sdev = (id < 8 && lun < 16) ? s->bus.devs[id] : NULL;
+    sdev = vscsi_device_find(&s->bus, be64_to_cpu(srp->cmd.lun), &lun);
     if (!sdev) {
-        dprintf("VSCSI: Command for id %d with no drive\n", id);
+        dprintf("VSCSI: Command for lun %08" PRIx64 " with no drive\n", be64_to_cpu(srp->cmd.lun));
         if (srp->cmd.cdb[0] == INQUIRY) {
             vscsi_inquiry_no_target(s, req);
         } else {
-- 
1.7.6

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

* [Qemu-devel] [PATCH 16/35] scsi: implement REPORT LUNS for arbitrary LUNs
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (14 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 15/35] scsi: remove devs array from SCSIBus Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 17/35] scsi: allow " Paolo Bonzini
                   ` (18 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-bus.c |   49 +++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 7104e98..a2d57a7 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -170,7 +170,7 @@ typedef struct SCSITargetReq SCSITargetReq;
 struct SCSITargetReq {
     SCSIRequest req;
     int len;
-    uint8_t buf[64];
+    uint8_t buf[2056];
 };
 
 static void store_lun(uint8_t *outbuf, int lun)
@@ -185,23 +185,52 @@ static void store_lun(uint8_t *outbuf, int lun)
 
 static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
 {
-    int len;
+    DeviceState *qdev;
+    int i, len, n;
+    int id;
+    bool found_lun0;
+
     if (r->req.cmd.xfer < 16) {
         return false;
     }
     if (r->req.cmd.buf[2] > 2) {
         return false;
     }
-    len = MIN(sizeof r->buf, r->req.cmd.xfer);
+    id = r->req.dev->id;
+    found_lun0 = false;
+    n = 0;
+    QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) {
+        SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
+
+        if (dev->id == id) {
+            if (dev->lun == 0) {
+                found_lun0 = true;
+            }
+            n += 8;
+        }
+    }
+    if (!found_lun0) {
+        n += 8;
+    }
+    len = MIN(n + 8, r->req.cmd.xfer & ~7);
+    if (len > sizeof(r->buf)) {
+        /* TODO: > 256 LUNs? */
+        return false;
+    }
+
     memset(r->buf, 0, len);
-    if (r->req.dev->lun != 0) {
-        r->buf[3] = 16;
-        r->len = 24;
-        store_lun(&r->buf[16], r->req.dev->lun);
-    } else {
-        r->buf[3] = 8;
-        r->len = 16;
+    stl_be_p(&r->buf, n);
+    i = found_lun0 ? 8 : 16;
+    QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) {
+        SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
+
+        if (dev->id == id) {
+            store_lun(&r->buf[i], dev->lun);
+            i += 8;
+        }
     }
+    assert(i == n + 8);
+    r->len = len;
     return true;
 }
 
-- 
1.7.6

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

* [Qemu-devel] [PATCH 17/35] scsi: allow arbitrary LUNs
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (15 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 16/35] scsi: implement REPORT LUNS for arbitrary LUNs Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 18/35] scsi: add channel to addressing Paolo Bonzini
                   ` (17 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

This only requires changes in two places: in SCSIBus, we need to look
for a free LUN if somebody creates a device with a pre-existing scsi-id
but the default LUN (-1, meaning "search for a free spot"); in vSCSI,
we need to actually parse the LUN according to the SCSI spec.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/esp.c         |    3 ++-
 hw/lsi53c895a.c  |    3 ++-
 hw/scsi-bus.c    |   48 ++++++++++++++++++++++++++++++++----------------
 hw/scsi.h        |    3 ++-
 hw/spapr_vscsi.c |   39 +++++++++++++++++++++++++++++++++++----
 hw/usb-msd.c     |    3 ++-
 6 files changed, 75 insertions(+), 24 deletions(-)

diff --git a/hw/esp.c b/hw/esp.c
index 8e17005..0ebc181 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -723,7 +723,8 @@ void esp_init(target_phys_addr_t espaddr, int it_shift,
 
 static const struct SCSIBusInfo esp_scsi_info = {
     .tcq = false,
-    .ndev = ESP_MAX_DEVS,
+    .max_target = ESP_MAX_DEVS,
+    .max_lun = 7,
 
     .transfer_data = esp_transfer_data,
     .complete = esp_command_complete,
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index c15f167..d26e442 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -2085,7 +2085,8 @@ static int lsi_scsi_uninit(PCIDevice *d)
 
 static const struct SCSIBusInfo lsi_scsi_info = {
     .tcq = true,
-    .ndev = LSI_MAX_DEVS,
+    .max_target = LSI_MAX_DEVS,
+    .max_lun = 0,  /* LUN support is buggy */
 
     .transfer_data = lsi_transfer_data,
     .complete = lsi_command_complete,
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index a2d57a7..cec06db 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -17,7 +17,7 @@ static struct BusInfo scsi_bus_info = {
     .get_fw_dev_path = scsibus_get_fw_dev_path,
     .props = (Property[]) {
         DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1),
-        DEFINE_PROP_UINT32("lun", SCSIDevice, lun, 0),
+        DEFINE_PROP_UINT32("lun", SCSIDevice, lun, -1),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
@@ -37,26 +37,42 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
     SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
     SCSIDeviceInfo *info = DO_UPCAST(SCSIDeviceInfo, qdev, base);
     SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
-    SCSIDevice *olddev;
+    SCSIDevice *d;
     int rc = -1;
 
-    if (dev->id == -1) {
-        int id;
-        for (id = 0; id < bus->info->ndev; id++) {
-            if (!scsi_device_find(bus, id, 0)) {
-                dev->id = id;
-                break;
-            }
-        }
-    }
-    if (dev->id >= bus->info->ndev) {
+    if (dev->id != -1 && dev->id > bus->info->max_target) {
         error_report("bad scsi device id: %d", dev->id);
         goto err;
     }
 
-    olddev = scsi_device_find(bus, dev->id, dev->lun);
-    if (olddev && dev->lun == olddev->lun) {
-        qdev_free(&olddev->qdev);
+    if (dev->id == -1) {
+        int id = -1;
+        if (dev->lun == -1) {
+            dev->lun = 0;
+        }
+        do {
+            d = scsi_device_find(bus, ++id, dev->lun);
+        } while (d && d->lun == dev->lun && id <= bus->info->max_target);
+        if (id > bus->info->max_target) {
+            error_report("no free target");
+            goto err;
+        }
+        dev->id = id;
+    } else if (dev->lun == -1) {
+        int lun = -1;
+        do {
+            d = scsi_device_find(bus, dev->id, ++lun);
+        } while (d && d->lun == lun && lun < bus->info->max_lun);
+        if (lun > bus->info->max_lun) {
+            error_report("no free lun");
+            goto err;
+        }
+        dev->lun = lun;
+    } else {
+        d = scsi_device_find(bus, dev->id, dev->lun);
+        if (dev->lun == d->lun && dev != d) {
+            qdev_free(&d->qdev);
+        }
     }
 
     dev->info = info;
@@ -115,7 +131,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
     int res = 0, unit;
 
     loc_push_none(&loc);
-    for (unit = 0; unit < bus->info->ndev; unit++) {
+    for (unit = 0; unit < bus->info->max_target; unit++) {
         dinfo = drive_get(IF_SCSI, bus->busnr, unit);
         if (dinfo == NULL) {
             continue;
diff --git a/hw/scsi.h b/hw/scsi.h
index add3d2d..401d8d3 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -98,7 +98,8 @@ struct SCSIDeviceInfo {
 };
 
 struct SCSIBusInfo {
-    int tcq, ndev;
+    int tcq;
+    int max_target, max_lun;
     void (*transfer_data)(SCSIRequest *req, uint32_t arg);
     void (*complete)(SCSIRequest *req, uint32_t arg);
     void (*cancel)(SCSIRequest *req);
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index aae845a..334b2e6 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -131,9 +131,39 @@ static void vscsi_put_req(vscsi_req *req)
 
 static SCSIDevice *vscsi_device_find(SCSIBus *bus, uint64_t srp_lun, int *lun)
 {
-    /* XXX Figure that one out properly ! This is crackpot */
-    int id = (srp_lun >> 56) & 0x7f;
-    *lun = (srp_lun >> 48) & 0xff;
+    int channel = 0, id = 0;
+
+retry:
+    switch (srp_lun >> 62) {
+    case 0:
+        if ((srp_lun >> 56) != 0) {
+            channel = (srp_lun >> 56) & 0x3f;
+            id = (srp_lun >> 48) & 0xff;
+            srp_lun <<= 16;
+            goto retry;
+        }
+        *lun = (srp_lun >> 48) & 0xff;
+        break;
+
+    case 1:
+        *lun = (srp_lun >> 48) & 0x3fff;
+        break;
+    case 2:
+        channel = (srp_lun >> 53) & 0x7;
+        id = (srp_lun >> 56) & 0x3f;
+        *lun = (srp_lun >> 48) & 0x1f;
+        break;
+    case 3:
+        *lun = -1;
+        return NULL;
+    default:
+        abort();
+    }
+
+    if (channel) {
+        *lun = -1;
+        return NULL;
+    }
     return scsi_device_find (bus, id, *lun);
 }
 
@@ -862,7 +892,8 @@ static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
 
 static const struct SCSIBusInfo vscsi_scsi_info = {
     .tcq = true,
-    .ndev = 63, /* logical unit addressing format */
+    .max_target = 63, /* logical unit addressing format */
+    .max_lun = 31,
 
     .transfer_data = vscsi_transfer_data,
     .complete = vscsi_command_complete,
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index d0e0cd3..2d88596 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -494,7 +494,8 @@ static void usb_msd_password_cb(void *opaque, int err)
 
 static const struct SCSIBusInfo usb_msd_scsi_info = {
     .tcq = false,
-    .ndev = 1,
+    .max_target = 0,
+    .max_lun = 0,
 
     .transfer_data = usb_msd_transfer_data,
     .complete = usb_msd_command_complete,
-- 
1.7.6

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

* [Qemu-devel] [PATCH 18/35] scsi: add channel to addressing
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (16 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 17/35] scsi: allow " Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 19/35] scsi-disk: fail READ CAPACITY if LBA != 0 but PMI == 0 Paolo Bonzini
                   ` (16 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

This also requires little more than adding the new argument to
scsi_device_find, and the qdev property.  All devices by default
end up on channel 0.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/esp.c         |    4 ++--
 hw/lsi53c895a.c  |    4 ++--
 hw/scsi-bus.c    |   24 +++++++++++++++---------
 hw/scsi.h        |    5 +++--
 hw/spapr_vscsi.c |    9 +++------
 5 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/hw/esp.c b/hw/esp.c
index 0ebc181..9b97a84 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -217,7 +217,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
         s->async_len = 0;
     }
 
-    s->current_dev = scsi_device_find(&s->bus, target, 0);
+    s->current_dev = scsi_device_find(&s->bus, 0, target, 0);
     if (!s->current_dev) {
         // No such drive
         s->rregs[ESP_RSTAT] = 0;
@@ -236,7 +236,7 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
 
     trace_esp_do_busid_cmd(busid);
     lun = busid & 7;
-    s->current_dev = scsi_device_find(&s->bus, s->current_dev->id, lun);
+    s->current_dev = scsi_device_find(&s->bus, 0, s->current_dev->id, lun);
     s->current_req = scsi_req_new(s->current_dev, 0, lun, buf, NULL);
     datalen = scsi_req_enqueue(s->current_req);
     s->ti_size = datalen;
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index d26e442..2984cea 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -767,7 +767,7 @@ static void lsi_do_command(LSIState *s)
     s->command_complete = 0;
 
     id = (s->select_tag >> 8) & 0xf;
-    dev = scsi_device_find(&s->bus, id, s->current_lun);
+    dev = scsi_device_find(&s->bus, 0, id, s->current_lun);
     if (!dev) {
         lsi_bad_selection(s, id);
         return;
@@ -1198,7 +1198,7 @@ again:
                 }
                 s->sstat0 |= LSI_SSTAT0_WOA;
                 s->scntl1 &= ~LSI_SCNTL1_IARB;
-                if (!scsi_device_find(&s->bus, id, 0)) {
+                if (!scsi_device_find(&s->bus, 0, id, 0)) {
                     lsi_bad_selection(s, id);
                     break;
                 }
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index cec06db..bdd6e94 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -16,6 +16,7 @@ static struct BusInfo scsi_bus_info = {
     .size  = sizeof(SCSIBus),
     .get_fw_dev_path = scsibus_get_fw_dev_path,
     .props = (Property[]) {
+        DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0),
         DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1),
         DEFINE_PROP_UINT32("lun", SCSIDevice, lun, -1),
         DEFINE_PROP_END_OF_LIST(),
@@ -40,6 +41,10 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
     SCSIDevice *d;
     int rc = -1;
 
+    if (dev->channel > bus->info->max_channel) {
+        error_report("bad scsi channel id: %d", dev->channel);
+        goto err;
+    }
     if (dev->id != -1 && dev->id > bus->info->max_target) {
         error_report("bad scsi device id: %d", dev->id);
         goto err;
@@ -51,7 +56,7 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
             dev->lun = 0;
         }
         do {
-            d = scsi_device_find(bus, ++id, dev->lun);
+            d = scsi_device_find(bus, dev->channel, ++id, dev->lun);
         } while (d && d->lun == dev->lun && id <= bus->info->max_target);
         if (id > bus->info->max_target) {
             error_report("no free target");
@@ -61,7 +66,7 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
     } else if (dev->lun == -1) {
         int lun = -1;
         do {
-            d = scsi_device_find(bus, dev->id, ++lun);
+            d = scsi_device_find(bus, dev->channel, dev->id, ++lun);
         } while (d && d->lun == lun && lun < bus->info->max_lun);
         if (lun > bus->info->max_lun) {
             error_report("no free lun");
@@ -69,7 +74,7 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
         }
         dev->lun = lun;
     } else {
-        d = scsi_device_find(bus, dev->id, dev->lun);
+        d = scsi_device_find(bus, dev->channel, dev->id, dev->lun);
         if (dev->lun == d->lun && dev != d) {
             qdev_free(&d->qdev);
         }
@@ -203,7 +208,7 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
 {
     DeviceState *qdev;
     int i, len, n;
-    int id;
+    int channel, id;
     bool found_lun0;
 
     if (r->req.cmd.xfer < 16) {
@@ -212,13 +217,14 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
     if (r->req.cmd.buf[2] > 2) {
         return false;
     }
+    channel = r->req.dev->channel;
     id = r->req.dev->id;
     found_lun0 = false;
     n = 0;
     QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) {
         SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
 
-        if (dev->id == id) {
+        if (dev->channel == channel && dev->id == id) {
             if (dev->lun == 0) {
                 found_lun0 = true;
             }
@@ -240,7 +246,7 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
     QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) {
         SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
 
-        if (dev->id == id) {
+        if (dev->channel == channel && dev->id == id) {
             store_lun(&r->buf[i], dev->lun);
             i += 8;
         }
@@ -1203,12 +1209,12 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
     char path[100];
 
     snprintf(path, sizeof(path), "%s@%d:%d:%d", qdev_fw_name(dev),
-             0, d->id, d->lun);
+             d->channel, d->id, d->lun);
 
     return strdup(path);
 }
 
-SCSIDevice *scsi_device_find(SCSIBus *bus, int id, int lun)
+SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
 {
     DeviceState *qdev;
     SCSIDevice *target_dev = NULL;
@@ -1216,7 +1222,7 @@ SCSIDevice *scsi_device_find(SCSIBus *bus, int id, int lun)
     QTAILQ_FOREACH_REVERSE(qdev, &bus->qbus.children, ChildrenHead, sibling) {
         SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
 
-        if (dev->id == id) {
+        if (dev->channel == channel && dev->id == id) {
             if (dev->lun == lun) {
                 return dev;
             }
diff --git a/hw/scsi.h b/hw/scsi.h
index 401d8d3..c8649cf 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -66,6 +66,7 @@ struct SCSIDevice
     uint8_t sense[SCSI_SENSE_BUF_SIZE];
     uint32_t sense_len;
     QTAILQ_HEAD(, SCSIRequest) requests;
+    uint32_t channel;
     uint32_t lun;
     int blocksize;
     int type;
@@ -99,7 +100,7 @@ struct SCSIDeviceInfo {
 
 struct SCSIBusInfo {
     int tcq;
-    int max_target, max_lun;
+    int max_channel, max_target, max_lun;
     void (*transfer_data)(SCSIRequest *req, uint32_t arg);
     void (*complete)(SCSIRequest *req, uint32_t arg);
     void (*cancel)(SCSIRequest *req);
@@ -194,6 +195,6 @@ void scsi_req_abort(SCSIRequest *req, int status);
 void scsi_req_cancel(SCSIRequest *req);
 void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
 int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
-SCSIDevice *scsi_device_find(SCSIBus *bus, int target, int lun);
+SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
 
 #endif
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index 334b2e6..2f9cbc8 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -160,11 +160,7 @@ retry:
         abort();
     }
 
-    if (channel) {
-        *lun = -1;
-        return NULL;
-    }
-    return scsi_device_find (bus, id, *lun);
+    return scsi_device_find (bus, channel, id, *lun);
 }
 
 static int vscsi_send_iu(VSCSIState *s, vscsi_req *req,
@@ -892,7 +888,8 @@ static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
 
 static const struct SCSIBusInfo vscsi_scsi_info = {
     .tcq = true,
-    .max_target = 63, /* logical unit addressing format */
+    .max_channel = 7, /* logical unit addressing format */
+    .max_target = 63,
     .max_lun = 31,
 
     .transfer_data = vscsi_transfer_data,
-- 
1.7.6

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

* [Qemu-devel] [PATCH 19/35] scsi-disk: fail READ CAPACITY if LBA != 0 but PMI == 0
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (17 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 18/35] scsi: add channel to addressing Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 20/35] scsi-disk: do not complete requests twice Paolo Bonzini
                   ` (15 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

Tested by the Windows Logo Kit SCSI Compliance test. From SBC-3, paragraph
5.25: "The LOGICAL BLOCK ADDRESS field shall be set to zero if the PMI
bit is set to zero. If the PMI bit is set to zero and the LOGICAL BLOCK
ADDRESS field is not set to zero, then the device server shall terminate
the command with CHECK CONDITION status with the sense key set to ILLEGAL
REQUEST and the additional sense code set to INVALID FIELD IN CDB".

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 97a7335..b041fd5 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1161,8 +1161,12 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
         /* The normal LEN field for this command is zero.  */
         memset(outbuf, 0, 8);
         bdrv_get_geometry(s->bs, &nb_sectors);
-        if (!nb_sectors)
+        if (!nb_sectors) {
             goto not_ready;
+        }
+        if ((req->cmd.buf[8] & 1) == 0 && req->cmd.lba) {
+            goto illegal_request;
+        }
         nb_sectors /= s->cluster_size;
         /* Returned value is the address of the last sector.  */
         nb_sectors--;
@@ -1207,8 +1211,12 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
             DPRINTF("SAI READ CAPACITY(16)\n");
             memset(outbuf, 0, req->cmd.xfer);
             bdrv_get_geometry(s->bs, &nb_sectors);
-            if (!nb_sectors)
+            if (!nb_sectors) {
                 goto not_ready;
+            }
+            if ((req->cmd.buf[14] & 1) == 0 && req->cmd.lba) {
+                goto illegal_request;
+            }
             nb_sectors /= s->cluster_size;
             /* Returned value is the address of the last sector.  */
             nb_sectors--;
-- 
1.7.6

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

* [Qemu-devel] [PATCH 20/35] scsi-disk: do not complete requests twice
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (18 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 19/35] scsi-disk: fail READ CAPACITY if LBA != 0 but PMI == 0 Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-19 13:13   ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 21/35] scsi-disk: bump SCSIRequest reference count until aio completion runs Paolo Bonzini
                   ` (14 subsequent siblings)
  34 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

When scsi_handle_rw_error reports a CHECK CONDITION code, the
owner should not call scsi_req_complete.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index b041fd5..d4f773f 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -231,6 +231,7 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
         bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
         vm_stop(RUN_STATE_IO_ERROR);
         bdrv_iostatus_set_err(s->bs, error);
+        return 1;
     } else {
         switch (error) {
         case ENOMEDIUM:
@@ -247,8 +248,8 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
             break;
         }
         bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read);
+        return 0;
     }
-    return 1;
 }
 
 static void scsi_write_complete(void * opaque, int ret)
-- 
1.7.6

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

* [Qemu-devel] [PATCH 21/35] scsi-disk: bump SCSIRequest reference count until aio completion runs
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (19 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 20/35] scsi-disk: do not complete requests twice Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-17 15:37   ` [Qemu-devel] [PATCH v2 " Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 22/35] scsi-disk: fix retrying a flush Paolo Bonzini
                   ` (13 subsequent siblings)
  34 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

In some cases a request may be canceled before the completion
callback runs.  Keep a reference to the request between starting
an AIO operation, and let scsi_*_complete remove it.

Since scsi_handle_rw_error returns whether something else has to
be done for the request by the caller, it makes sense to transfer
ownership of the ref to scsi_handle_rw_error when it returns 1;
scsi_dma_restart_bh will then free the reference after restarting
the operation.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index d4f773f..3f54891 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -139,6 +139,7 @@ static void scsi_read_complete(void * opaque, int ret)
 
     if (ret) {
         if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_READ)) {
+            /* Leave in ref for scsi_dma_restart_bh.  */
             return;
         }
     }
@@ -149,6 +150,7 @@ static void scsi_read_complete(void * opaque, int ret)
     r->sector += n;
     r->sector_count -= n;
     scsi_req_data(&r->req, r->qiov.size);
+    scsi_req_unref(&r->req);
 }
 
 static void scsi_flush_complete(void * opaque, int ret)
@@ -163,11 +165,13 @@ static void scsi_flush_complete(void * opaque, int ret)
 
     if (ret < 0) {
         if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) {
+            /* Leave in ref for scsi_dma_restart_bh.  */
             return;
         }
     }
 
     scsi_req_complete(&r->req, GOOD);
+    scsi_req_unref(&r->req);
 }
 
 /* Read more data from scsi device into buffer.  */
@@ -202,6 +206,9 @@ static void scsi_read_data(SCSIRequest *req)
     if (s->tray_open) {
         scsi_read_complete(r, -ENOMEDIUM);
     }
+
+    /* Save a ref for scsi_read_complete, in case r is canceled.  */
+    scsi_req_ref(&r->req);
     n = scsi_init_iovec(r);
     bdrv_acct_start(s->bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
     r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n,
@@ -279,6 +286,7 @@ static void scsi_write_complete(void * opaque, int ret)
         DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, r->qiov.size);
         scsi_req_data(&r->req, r->qiov.size);
     }
+    scsi_req_unref(&r->req);
 }
 
 static void scsi_write_data(SCSIRequest *req)
@@ -296,6 +304,8 @@ static void scsi_write_data(SCSIRequest *req)
         return;
     }
 
+    /* Save a ref for scsi_write_complete, in case r is canceled.  */
+    scsi_req_ref(&r->req);
     n = r->qiov.size / 512;
     if (n) {
         if (s->tray_open) {
@@ -344,6 +354,8 @@ static void scsi_dma_restart_bh(void *opaque)
                     scsi_req_complete(&r->req, GOOD);
                 }
             }
+            /* This reference was left in by scsi_handle_rw_error.  */
+            scsi_req_unref(&r->req);
         }
     }
 }
@@ -1325,6 +1337,8 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
         r->iov.iov_len = rc;
         break;
     case SYNCHRONIZE_CACHE:
+        /* Save a ref for scsi_flush_complete, in case r is canceled.  */
+        scsi_req_ref(&r->req);
         bdrv_acct_start(s->bs, &r->acct, 0, BDRV_ACCT_FLUSH);
         r->req.aiocb = bdrv_aio_flush(s->bs, scsi_flush_complete, r);
         if (r->req.aiocb == NULL) {
-- 
1.7.6

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

* [Qemu-devel] [PATCH 22/35] scsi-disk: fix retrying a flush
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (20 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 21/35] scsi-disk: bump SCSIRequest reference count until aio completion runs Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 23/35] scsi-generic: drop SCSIGenericState Paolo Bonzini
                   ` (12 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

Flush does not go anymore through scsi_disk_emulate_command.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 3f54891..860a3bf 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -81,7 +81,7 @@ struct SCSIDiskState
 };
 
 static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type);
-static int scsi_disk_emulate_command(SCSIDiskReq *r);
+static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf);
 
 static void scsi_free_request(SCSIRequest *req)
 {
@@ -336,7 +336,6 @@ static void scsi_dma_restart_bh(void *opaque)
         r = DO_UPCAST(SCSIDiskReq, req, req);
         if (r->status & SCSI_REQ_STATUS_RETRY) {
             int status = r->status;
-            int ret;
 
             r->status &=
                 ~(SCSI_REQ_STATUS_RETRY | SCSI_REQ_STATUS_RETRY_TYPE_MASK);
@@ -349,10 +348,8 @@ static void scsi_dma_restart_bh(void *opaque)
                 scsi_write_data(&r->req);
                 break;
             case SCSI_REQ_STATUS_RETRY_FLUSH:
-                ret = scsi_disk_emulate_command(r);
-                if (ret == 0) {
-                    scsi_req_complete(&r->req, GOOD);
-                }
+                scsi_send_command(&r->req, r->req.cmd.buf);
+                break;
             }
             /* This reference was left in by scsi_handle_rw_error.  */
             scsi_req_unref(&r->req);
-- 
1.7.6

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

* [Qemu-devel] [PATCH 23/35] scsi-generic: drop SCSIGenericState
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (21 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 22/35] scsi-disk: fix retrying a flush Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 24/35] scsi-generic: remove scsi_req_fixup Paolo Bonzini
                   ` (11 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

It is not needed, because s->bs is already stored in SCSIDevice, and
can be reached from the conf.bs member.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-generic.c |   85 +++++++++++++++++++++++------------------------------
 1 files changed, 37 insertions(+), 48 deletions(-)

diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 8f6b70d..cea4fca 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -46,8 +46,6 @@ do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
 #define MAX_UINT ((unsigned int)-1)
 #endif
 
-typedef struct SCSIGenericState SCSIGenericState;
-
 typedef struct SCSIGenericReq {
     SCSIRequest req;
     uint8_t *buf;
@@ -56,12 +54,6 @@ typedef struct SCSIGenericReq {
     sg_io_hdr_t io_header;
 } SCSIGenericReq;
 
-struct SCSIGenericState
-{
-    SCSIDevice qdev;
-    BlockDriverState *bs;
-};
-
 static void scsi_free_request(SCSIRequest *req)
 {
     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
@@ -174,7 +166,7 @@ static void scsi_read_complete(void * opaque, int ret)
 static void scsi_read_data(SCSIRequest *req)
 {
     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
-    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
+    SCSIDevice *s = r->req.dev;
     int ret;
 
     DPRINTF("scsi_read_data 0x%x\n", req->tag);
@@ -183,7 +175,7 @@ static void scsi_read_data(SCSIRequest *req)
         return;
     }
 
-    ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
+    ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
     if (ret < 0) {
         scsi_command_complete(r, ret);
         return;
@@ -193,7 +185,7 @@ static void scsi_read_data(SCSIRequest *req)
 static void scsi_write_complete(void * opaque, int ret)
 {
     SCSIGenericReq *r = (SCSIGenericReq *)opaque;
-    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
+    SCSIDevice *s = r->req.dev;
 
     DPRINTF("scsi_write_complete() ret = %d\n", ret);
     r->req.aiocb = NULL;
@@ -204,9 +196,9 @@ static void scsi_write_complete(void * opaque, int ret)
     }
 
     if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
-        s->qdev.type == TYPE_TAPE) {
-        s->qdev.blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
-        DPRINTF("block size %d\n", s->qdev.blocksize);
+        s->type == TYPE_TAPE) {
+        s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
+        DPRINTF("block size %d\n", s->blocksize);
     }
 
     scsi_command_complete(r, ret);
@@ -216,8 +208,8 @@ static void scsi_write_complete(void * opaque, int ret)
    The transfer may complete asynchronously.  */
 static void scsi_write_data(SCSIRequest *req)
 {
-    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
+    SCSIDevice *s = r->req.dev;
     int ret;
 
     DPRINTF("scsi_write_data 0x%x\n", req->tag);
@@ -227,7 +219,7 @@ static void scsi_write_data(SCSIRequest *req)
         return;
     }
 
-    ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
+    ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
     if (ret < 0) {
         scsi_command_complete(r, ret);
     }
@@ -261,8 +253,8 @@ static void scsi_req_fixup(SCSIRequest *req)
 
 static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
 {
-    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
+    SCSIDevice *s = r->req.dev;
     int ret;
 
     scsi_req_fixup(&r->req);
@@ -285,7 +277,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
             g_free(r->buf);
         r->buflen = 0;
         r->buf = NULL;
-        ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
+        ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete);
         if (ret < 0) {
             scsi_command_complete(r, ret);
             return 0;
@@ -373,77 +365,74 @@ static int get_stream_blocksize(BlockDriverState *bdrv)
 
 static void scsi_generic_reset(DeviceState *dev)
 {
-    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
+    SCSIDevice *s = DO_UPCAST(SCSIDevice, qdev, dev);
 
-    scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
+    scsi_device_purge_requests(s, SENSE_CODE(RESET));
 }
 
-static void scsi_destroy(SCSIDevice *d)
+static void scsi_destroy(SCSIDevice *s)
 {
-    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
-
-    scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE));
-    blockdev_mark_auto_del(s->qdev.conf.bs);
+    scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
+    blockdev_mark_auto_del(s->conf.bs);
 }
 
-static int scsi_generic_initfn(SCSIDevice *dev)
+static int scsi_generic_initfn(SCSIDevice *s)
 {
-    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
     int sg_version;
     struct sg_scsi_id scsiid;
 
-    if (!s->qdev.conf.bs) {
+    if (!s->conf.bs) {
         error_report("scsi-generic: drive property not set");
         return -1;
     }
-    s->bs = s->qdev.conf.bs;
 
     /* check we are really using a /dev/sg* file */
-    if (!bdrv_is_sg(s->bs)) {
+    if (!bdrv_is_sg(s->conf.bs)) {
         error_report("scsi-generic: not /dev/sg*");
         return -1;
     }
 
-    if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
+    if (bdrv_get_on_error(s->conf.bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
         error_report("Device doesn't support drive option werror");
         return -1;
     }
-    if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
+    if (bdrv_get_on_error(s->conf.bs, 1) != BLOCK_ERR_REPORT) {
         error_report("Device doesn't support drive option rerror");
         return -1;
     }
 
     /* check we are using a driver managing SG_IO (version 3 and after */
-    if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
+    if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
         sg_version < 30000) {
         error_report("scsi-generic: scsi generic interface too old");
         return -1;
     }
 
     /* get LUN of the /dev/sg? */
-    if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
+    if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) {
         error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
         return -1;
     }
 
     /* define device state */
-    s->qdev.type = scsiid.scsi_type;
-    DPRINTF("device type %d\n", s->qdev.type);
-    if (s->qdev.type == TYPE_TAPE) {
-        s->qdev.blocksize = get_stream_blocksize(s->bs);
-        if (s->qdev.blocksize == -1)
-            s->qdev.blocksize = 0;
+    s->type = scsiid.scsi_type;
+    DPRINTF("device type %d\n", s->type);
+    if (s->type == TYPE_TAPE) {
+        s->blocksize = get_stream_blocksize(s->conf.bs);
+        if (s->blocksize == -1)
+            s->blocksize = 0;
     } else {
-        s->qdev.blocksize = get_blocksize(s->bs);
+        s->blocksize = get_blocksize(s->conf.bs);
         /* removable media returns 0 if not present */
-        if (s->qdev.blocksize <= 0) {
-            if (s->qdev.type == TYPE_ROM || s->qdev.type  == TYPE_WORM)
-                s->qdev.blocksize = 2048;
+        if (s->blocksize <= 0) {
+            if (s->type == TYPE_ROM || s->type  == TYPE_WORM)
+                s->blocksize = 2048;
             else
-                s->qdev.blocksize = 512;
+                s->blocksize = 512;
         }
     }
-    DPRINTF("block size %d\n", s->qdev.blocksize);
+
+    DPRINTF("block size %d\n", s->blocksize);
     return 0;
 }
 
@@ -469,13 +458,13 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
 static SCSIDeviceInfo scsi_generic_info = {
     .qdev.name    = "scsi-generic",
     .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
-    .qdev.size    = sizeof(SCSIGenericState),
+    .qdev.size    = sizeof(SCSIDevice),
     .qdev.reset   = scsi_generic_reset,
     .init         = scsi_generic_initfn,
     .destroy      = scsi_destroy,
     .alloc_req    = scsi_new_request,
     .qdev.props   = (Property[]) {
-        DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
+        DEFINE_BLOCK_PROPERTIES(SCSIDevice, conf),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
-- 
1.7.6

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

* [Qemu-devel] [PATCH 24/35] scsi-generic: remove scsi_req_fixup
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (22 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 23/35] scsi-generic: drop SCSIGenericState Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 25/35] scsi-generic: check ioctl statuses when SG_IO succeeds Paolo Bonzini
                   ` (10 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

This is not needed anymore, since asynchronous ioctls were introduced
by commit 221f715 (new scsi-generic abstraction, use SG_IO, 2009-03-28).

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-generic.c |   15 ---------------
 1 files changed, 0 insertions(+), 15 deletions(-)

diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index cea4fca..da104a6 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -233,19 +233,6 @@ static uint8_t *scsi_get_buf(SCSIRequest *req)
     return r->buf;
 }
 
-static void scsi_req_fixup(SCSIRequest *req)
-{
-    switch(req->cmd.buf[0]) {
-    case REWIND:
-    case START_STOP:
-        if (req->dev->type == TYPE_TAPE) {
-            /* force IMMED, otherwise qemu waits end of command */
-            req->cmd.buf[1] = 0x01;
-        }
-        break;
-    }
-}
-
 /* Execute a scsi command.  Returns the length of the data expected by the
    command.  This will be Positive for data transfers from the device
    (eg. disk reads), negative for transfers to the device (eg. disk writes),
@@ -257,8 +244,6 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
     SCSIDevice *s = r->req.dev;
     int ret;
 
-    scsi_req_fixup(&r->req);
-
     DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
             r->req.cmd.xfer, cmd[0]);
 
-- 
1.7.6

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

* [Qemu-devel] [PATCH 25/35] scsi-generic: check ioctl statuses when SG_IO succeeds
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (23 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 24/35] scsi-generic: remove scsi_req_fixup Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 26/35] scsi-generic: look at host status Paolo Bonzini
                   ` (9 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

A succeeding ioctl does not imply that the SCSI command succeeded.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-generic.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index da104a6..9043eea 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -311,7 +311,7 @@ static int get_blocksize(BlockDriverState *bdrv)
     io_header.timeout = 6000; /* XXX */
 
     ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
-    if (ret < 0)
+    if (ret < 0 || io_header.driver_status || io_header.host_status)
         return -1;
 
     return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
@@ -342,7 +342,7 @@ static int get_stream_blocksize(BlockDriverState *bdrv)
     io_header.timeout = 6000; /* XXX */
 
     ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
-    if (ret < 0)
+    if (ret < 0 || io_header.driver_status || io_header.host_status)
         return -1;
 
     return (buf[9] << 16) | (buf[10] << 8) | buf[11];
-- 
1.7.6

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

* [Qemu-devel] [PATCH 26/35] scsi-generic: look at host status
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (24 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 25/35] scsi-generic: check ioctl statuses when SG_IO succeeds Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 27/35] scsi-generic: snoop READ CAPACITY commands to get block size Paolo Bonzini
                   ` (8 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

Pass down the host status so that failing transport can be detected
by the guest.  Similar treatment of host status could be done in
virtio-blk, too.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-generic.c |   20 ++++++++++++++++----
 1 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 9043eea..787c581 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -39,8 +39,13 @@ do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
 
 #define SCSI_SENSE_BUF_SIZE 96
 
-#define SG_ERR_DRIVER_TIMEOUT 0x06
-#define SG_ERR_DRIVER_SENSE 0x08
+#define SG_ERR_DRIVER_TIMEOUT  0x06
+#define SG_ERR_DRIVER_SENSE    0x08
+
+#define SG_ERR_DID_OK          0x00
+#define SG_ERR_DID_NO_CONNECT  0x01
+#define SG_ERR_DID_BUS_BUSY    0x02
+#define SG_ERR_DID_TIME_OUT    0x03
 
 #ifndef MAX_UINT
 #define MAX_UINT ((unsigned int)-1)
@@ -68,8 +73,9 @@ static void scsi_command_complete(void *opaque, int ret)
     SCSIGenericReq *r = (SCSIGenericReq *)opaque;
 
     r->req.aiocb = NULL;
-    if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE)
+    if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
         r->req.sense_len = r->io_header.sb_len_wr;
+    }
 
     if (ret != 0) {
         switch (ret) {
@@ -86,9 +92,15 @@ static void scsi_command_complete(void *opaque, int ret)
             break;
         }
     } else {
-        if (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT) {
+        if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
+            r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
+            r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
+            (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
             status = BUSY;
             BADF("Driver Timeout\n");
+        } else if (r->io_header.host_status) {
+            status = CHECK_CONDITION;
+            scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
         } else if (r->io_header.status) {
             status = r->io_header.status;
         } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
-- 
1.7.6

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

* [Qemu-devel] [PATCH 27/35] scsi-generic: snoop READ CAPACITY commands to get block size
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (25 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 26/35] scsi-generic: look at host status Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 28/35] scsi-disk: do not duplicate BlockDriverState member Paolo Bonzini
                   ` (7 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

Instead of "guessing" the block size when there is no medium in the
drive, wait for the guest to send a READ CAPACITY command and retrieve
it from there.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-generic.c |   50 +++++++++++---------------------------------------
 1 files changed, 11 insertions(+), 39 deletions(-)

diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 787c581..cb02a7e 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -155,6 +155,7 @@ static int execute_command(BlockDriverState *bdrv,
 static void scsi_read_complete(void * opaque, int ret)
 {
     SCSIGenericReq *r = (SCSIGenericReq *)opaque;
+    SCSIDevice *s = r->req.dev;
     int len;
 
     r->req.aiocb = NULL;
@@ -170,6 +171,15 @@ static void scsi_read_complete(void * opaque, int ret)
     if (len == 0) {
         scsi_command_complete(r, 0);
     } else {
+        /* Snoop READ CAPACITY output to set the blocksize.  */
+        if (r->req.cmd.buf[0] == READ_CAPACITY_10) {
+            s->blocksize = ldl_be_p(&r->buf[4]);
+        } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
+                   (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
+            s->blocksize = ldl_be_p(&r->buf[8]);
+        }
+        bdrv_set_buffer_alignment(s->conf.bs, s->blocksize);
+
         scsi_req_data(&r->req, len);
     }
 }
@@ -299,36 +309,6 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
     }
 }
 
-static int get_blocksize(BlockDriverState *bdrv)
-{
-    uint8_t cmd[10];
-    uint8_t buf[8];
-    uint8_t sensebuf[8];
-    sg_io_hdr_t io_header;
-    int ret;
-
-    memset(cmd, 0, sizeof(cmd));
-    memset(buf, 0, sizeof(buf));
-    cmd[0] = READ_CAPACITY_10;
-
-    memset(&io_header, 0, sizeof(io_header));
-    io_header.interface_id = 'S';
-    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
-    io_header.dxfer_len = sizeof(buf);
-    io_header.dxferp = buf;
-    io_header.cmdp = cmd;
-    io_header.cmd_len = sizeof(cmd);
-    io_header.mx_sb_len = sizeof(sensebuf);
-    io_header.sbp = sensebuf;
-    io_header.timeout = 6000; /* XXX */
-
-    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
-    if (ret < 0 || io_header.driver_status || io_header.host_status)
-        return -1;
-
-    return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
-}
-
 static int get_stream_blocksize(BlockDriverState *bdrv)
 {
     uint8_t cmd[6];
@@ -413,20 +393,12 @@ static int scsi_generic_initfn(SCSIDevice *s)
 
     /* define device state */
     s->type = scsiid.scsi_type;
+    s->blocksize = 0;
     DPRINTF("device type %d\n", s->type);
     if (s->type == TYPE_TAPE) {
         s->blocksize = get_stream_blocksize(s->conf.bs);
         if (s->blocksize == -1)
             s->blocksize = 0;
-    } else {
-        s->blocksize = get_blocksize(s->conf.bs);
-        /* removable media returns 0 if not present */
-        if (s->blocksize <= 0) {
-            if (s->type == TYPE_ROM || s->type  == TYPE_WORM)
-                s->blocksize = 2048;
-            else
-                s->blocksize = 512;
-        }
     }
 
     DPRINTF("block size %d\n", s->blocksize);
-- 
1.7.6

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

* [Qemu-devel] [PATCH 28/35] scsi-disk: do not duplicate BlockDriverState member
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (26 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 27/35] scsi-generic: snoop READ CAPACITY commands to get block size Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 29/35] scsi-disk: remove cluster_size Paolo Bonzini
                   ` (6 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

Same as for scsi-generic, avoid duplication even if it causes longer
lines.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |   94 +++++++++++++++++++++++++++----------------------------
 1 files changed, 46 insertions(+), 48 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 860a3bf..5e3ef51 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -65,7 +65,6 @@ typedef struct SCSIDiskReq {
 struct SCSIDiskState
 {
     SCSIDevice qdev;
-    BlockDriverState *bs;
     /* The qemu block layer uses a fixed 512 byte sector size.
        This is the number of 512 byte blocks in a single scsi sector.  */
     int cluster_size;
@@ -119,7 +118,7 @@ static uint32_t scsi_init_iovec(SCSIDiskReq *r)
 
     if (!r->iov.iov_base) {
         r->buflen = SCSI_DMA_BUF_SIZE;
-        r->iov.iov_base = qemu_blockalign(s->bs, r->buflen);
+        r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
     }
     r->iov.iov_len = MIN(r->sector_count * 512, r->buflen);
     qemu_iovec_init_external(&r->qiov, &r->iov, 1);
@@ -134,7 +133,7 @@ static void scsi_read_complete(void * opaque, int ret)
 
     if (r->req.aiocb != NULL) {
         r->req.aiocb = NULL;
-        bdrv_acct_done(s->bs, &r->acct);
+        bdrv_acct_done(s->qdev.conf.bs, &r->acct);
     }
 
     if (ret) {
@@ -160,7 +159,7 @@ static void scsi_flush_complete(void * opaque, int ret)
 
     if (r->req.aiocb != NULL) {
         r->req.aiocb = NULL;
-        bdrv_acct_done(s->bs, &r->acct);
+        bdrv_acct_done(s->qdev.conf.bs, &r->acct);
     }
 
     if (ret < 0) {
@@ -210,8 +209,8 @@ static void scsi_read_data(SCSIRequest *req)
     /* Save a ref for scsi_read_complete, in case r is canceled.  */
     scsi_req_ref(&r->req);
     n = scsi_init_iovec(r);
-    bdrv_acct_start(s->bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
-    r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n,
+    bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
+    r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
                               scsi_read_complete, r);
     if (r->req.aiocb == NULL) {
         scsi_read_complete(r, -EIO);
@@ -222,10 +221,10 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
 {
     int is_read = (type == SCSI_REQ_STATUS_RETRY_READ);
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
-    BlockErrorAction action = bdrv_get_on_error(s->bs, is_read);
+    BlockErrorAction action = bdrv_get_on_error(s->qdev.conf.bs, is_read);
 
     if (action == BLOCK_ERR_IGNORE) {
-        bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, is_read);
+        bdrv_mon_event(s->qdev.conf.bs, BDRV_ACTION_IGNORE, is_read);
         return 0;
     }
 
@@ -235,9 +234,9 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
         type &= SCSI_REQ_STATUS_RETRY_TYPE_MASK;
         r->status |= SCSI_REQ_STATUS_RETRY | type;
 
-        bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
+        bdrv_mon_event(s->qdev.conf.bs, BDRV_ACTION_STOP, is_read);
         vm_stop(RUN_STATE_IO_ERROR);
-        bdrv_iostatus_set_err(s->bs, error);
+        bdrv_iostatus_set_err(s->qdev.conf.bs, error);
         return 1;
     } else {
         switch (error) {
@@ -254,7 +253,7 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
             scsi_check_condition(r, SENSE_CODE(IO_ERROR));
             break;
         }
-        bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read);
+        bdrv_mon_event(s->qdev.conf.bs, BDRV_ACTION_REPORT, is_read);
         return 0;
     }
 }
@@ -267,7 +266,7 @@ static void scsi_write_complete(void * opaque, int ret)
 
     if (r->req.aiocb != NULL) {
         r->req.aiocb = NULL;
-        bdrv_acct_done(s->bs, &r->acct);
+        bdrv_acct_done(s->qdev.conf.bs, &r->acct);
     }
 
     if (ret) {
@@ -311,8 +310,8 @@ static void scsi_write_data(SCSIRequest *req)
         if (s->tray_open) {
             scsi_write_complete(r, -ENOMEDIUM);
         }
-        bdrv_acct_start(s->bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
-        r->req.aiocb = bdrv_aio_writev(s->bs, r->sector, &r->qiov, n,
+        bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
+        r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, r->sector, &r->qiov, n,
                                        scsi_write_complete, r);
         if (r->req.aiocb == NULL) {
             scsi_write_complete(r, -ENOMEM);
@@ -450,7 +449,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
         case 0x83: /* Device identification page, mandatory */
         {
             int max_len = 255 - 8;
-            int id_len = strlen(bdrv_get_device_name(s->bs));
+            int id_len = strlen(bdrv_get_device_name(s->qdev.conf.bs));
 
             if (id_len > max_len)
                 id_len = max_len;
@@ -463,7 +462,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
             outbuf[buflen++] = 0;   // reserved
             outbuf[buflen++] = id_len; // length of data following
 
-            memcpy(outbuf+buflen, bdrv_get_device_name(s->bs), id_len);
+            memcpy(outbuf+buflen, bdrv_get_device_name(s->qdev.conf.bs), id_len);
             buflen += id_len;
             break;
         }
@@ -580,10 +579,10 @@ static inline bool media_is_dvd(SCSIDiskState *s)
     if (s->qdev.type != TYPE_ROM) {
         return false;
     }
-    if (!bdrv_is_inserted(s->bs)) {
+    if (!bdrv_is_inserted(s->qdev.conf.bs)) {
         return false;
     }
-    bdrv_get_geometry(s->bs, &nb_sectors);
+    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
     return nb_sectors > CD_MAX_SECTORS;
 }
 
@@ -593,10 +592,10 @@ static inline bool media_is_cd(SCSIDiskState *s)
     if (s->qdev.type != TYPE_ROM) {
         return false;
     }
-    if (!bdrv_is_inserted(s->bs)) {
+    if (!bdrv_is_inserted(s->qdev.conf.bs)) {
         return false;
     }
-    bdrv_get_geometry(s->bs, &nb_sectors);
+    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
     return nb_sectors <= CD_MAX_SECTORS;
 }
 
@@ -615,10 +614,10 @@ static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
     uint8_t format = r->req.cmd.buf[7];
     int size = -1;
 
-    if (s->qdev.type != TYPE_ROM || !bdrv_is_inserted(s->bs)) {
+    if (s->qdev.type != TYPE_ROM || !bdrv_is_inserted(s->qdev.conf.bs)) {
         return -1;
     }
-    if (s->tray_open || !bdrv_is_inserted(s->bs)) {
+    if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
         scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
         return -1;
     }
@@ -645,7 +644,7 @@ static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
         uint64_t nb_sectors;
         if (layer != 0)
             goto fail;
-        bdrv_get_geometry(s->bs, &nb_sectors);
+        bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
 
         outbuf[4] = 1;   /* DVD-ROM, part version 1 */
         outbuf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
@@ -700,7 +699,7 @@ static int scsi_event_status_media(SCSIDiskState *s, uint8_t *outbuf)
     media_status = 0;
     if (s->tray_open) {
         media_status = MS_TRAY_OPEN;
-    } else if (bdrv_is_inserted(s->bs)) {
+    } else if (bdrv_is_inserted(s->qdev.conf.bs)) {
         media_status = MS_MEDIA_PRESENT;
     }
 
@@ -803,7 +802,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
         [MODE_PAGE_CAPABILITIES]           = (1 << TYPE_ROM),
     };
 
-    BlockDriverState *bdrv = s->bs;
+    BlockDriverState *bdrv = s->qdev.conf.bs;
     int cylinders, heads, secs;
     uint8_t *p = *p_outbuf;
 
@@ -895,7 +894,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
         if (page_control == 1) { /* Changeable Values */
             break;
         }
-        if (bdrv_enable_write_cache(s->bs)) {
+        if (bdrv_enable_write_cache(s->qdev.conf.bs)) {
             p[2] = 4; /* WCE */
         }
         break;
@@ -967,7 +966,7 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
     memset(outbuf, 0, r->req.cmd.xfer);
     p = outbuf;
 
-    if (bdrv_is_read_only(s->bs)) {
+    if (bdrv_is_read_only(s->qdev.conf.bs)) {
         dev_specific_param = 0x80; /* Readonly.  */
     } else {
         dev_specific_param = 0x00;
@@ -985,7 +984,7 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
         p += 8;
     }
 
-    bdrv_get_geometry(s->bs, &nb_sectors);
+    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
     if (!dbd && nb_sectors) {
         if (r->req.cmd.buf[0] == MODE_SENSE) {
             outbuf[3] = 8; /* Block descriptor length  */
@@ -1049,7 +1048,7 @@ static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
     msf = req->cmd.buf[1] & 2;
     format = req->cmd.buf[2] & 0xf;
     start_track = req->cmd.buf[6];
-    bdrv_get_geometry(s->bs, &nb_sectors);
+    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
     DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
     nb_sectors /= s->cluster_size;
     switch (format) {
@@ -1085,12 +1084,12 @@ static int scsi_disk_emulate_start_stop(SCSIDiskReq *r)
     if (s->qdev.type == TYPE_ROM && loej) {
         if (!start && !s->tray_open && s->tray_locked) {
             scsi_check_condition(r,
-                                 bdrv_is_inserted(s->bs)
+                                 bdrv_is_inserted(s->qdev.conf.bs)
                                  ? SENSE_CODE(ILLEGAL_REQ_REMOVAL_PREVENTED)
                                  : SENSE_CODE(NOT_READY_REMOVAL_PREVENTED));
             return -1;
         }
-        bdrv_eject(s->bs, !start);
+        bdrv_eject(s->qdev.conf.bs, !start);
         s->tray_open = !start;
     }
     return 0;
@@ -1117,13 +1116,13 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
             goto illegal_request;
         }
         r->buflen = MAX(4096, req->cmd.xfer);
-        r->iov.iov_base = qemu_blockalign(s->bs, r->buflen);
+        r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
     }
 
     outbuf = r->iov.iov_base;
     switch (req->cmd.buf[0]) {
     case TEST_UNIT_READY:
-        if (s->tray_open || !bdrv_is_inserted(s->bs))
+        if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs))
             goto not_ready;
         break;
     case INQUIRY:
@@ -1165,12 +1164,12 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
         break;
     case ALLOW_MEDIUM_REMOVAL:
         s->tray_locked = req->cmd.buf[4] & 1;
-        bdrv_lock_medium(s->bs, req->cmd.buf[4] & 1);
+        bdrv_lock_medium(s->qdev.conf.bs, req->cmd.buf[4] & 1);
         break;
     case READ_CAPACITY_10:
         /* The normal LEN field for this command is zero.  */
         memset(outbuf, 0, 8);
-        bdrv_get_geometry(s->bs, &nb_sectors);
+        bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
         if (!nb_sectors) {
             goto not_ready;
         }
@@ -1220,7 +1219,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
         if ((req->cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
             DPRINTF("SAI READ CAPACITY(16)\n");
             memset(outbuf, 0, req->cmd.xfer);
-            bdrv_get_geometry(s->bs, &nb_sectors);
+            bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
             if (!nb_sectors) {
                 goto not_ready;
             }
@@ -1267,7 +1266,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
     return buflen;
 
 not_ready:
-    if (s->tray_open || !bdrv_is_inserted(s->bs)) {
+    if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
         scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
     } else {
         scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
@@ -1336,8 +1335,8 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
     case SYNCHRONIZE_CACHE:
         /* Save a ref for scsi_flush_complete, in case r is canceled.  */
         scsi_req_ref(&r->req);
-        bdrv_acct_start(s->bs, &r->acct, 0, BDRV_ACCT_FLUSH);
-        r->req.aiocb = bdrv_aio_flush(s->bs, scsi_flush_complete, r);
+        bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
+        r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_flush_complete, r);
         if (r->req.aiocb == NULL) {
             scsi_flush_complete(r, -EIO);
         }
@@ -1410,7 +1409,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
             goto fail;
         }
 
-        rc = bdrv_discard(s->bs, r->req.cmd.lba * s->cluster_size,
+        rc = bdrv_discard(s->qdev.conf.bs, r->req.cmd.lba * s->cluster_size,
                           len * s->cluster_size);
         if (rc < 0) {
             /* XXX: better error code ?*/
@@ -1451,7 +1450,7 @@ static void scsi_disk_reset(DeviceState *dev)
 
     scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
 
-    bdrv_get_geometry(s->bs, &nb_sectors);
+    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
     nb_sectors /= s->cluster_size;
     if (nb_sectors) {
         nb_sectors--;
@@ -1521,16 +1520,15 @@ static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
         error_report("scsi-disk: drive property not set");
         return -1;
     }
-    s->bs = s->qdev.conf.bs;
 
-    if (scsi_type == TYPE_DISK && !bdrv_is_inserted(s->bs)) {
+    if (scsi_type == TYPE_DISK && !bdrv_is_inserted(s->qdev.conf.bs)) {
         error_report("Device needs media, but drive is empty");
         return -1;
     }
 
     if (!s->serial) {
         /* try to fall back to value set with legacy -drive serial=... */
-        dinfo = drive_get_by_blockdev(s->bs);
+        dinfo = drive_get_by_blockdev(s->qdev.conf.bs);
         if (*dinfo->serial) {
             s->serial = g_strdup(dinfo->serial);
         }
@@ -1540,13 +1538,13 @@ static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
         s->version = g_strdup(QEMU_VERSION);
     }
 
-    if (bdrv_is_sg(s->bs)) {
+    if (bdrv_is_sg(s->qdev.conf.bs)) {
         error_report("scsi-disk: unwanted /dev/sg*");
         return -1;
     }
 
     if (scsi_type == TYPE_ROM) {
-        bdrv_set_dev_ops(s->bs, &scsi_cd_block_ops, s);
+        bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_cd_block_ops, s);
         s->qdev.blocksize = 2048;
     } else if (scsi_type == TYPE_DISK) {
         s->qdev.blocksize = s->qdev.conf.logical_block_size;
@@ -1555,11 +1553,11 @@ static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
         return -1;
     }
     s->cluster_size = s->qdev.blocksize / 512;
-    bdrv_set_buffer_alignment(s->bs, s->qdev.blocksize);
+    bdrv_set_buffer_alignment(s->qdev.conf.bs, s->qdev.blocksize);
 
     s->qdev.type = scsi_type;
     qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
-    bdrv_iostatus_enable(s->bs);
+    bdrv_iostatus_enable(s->qdev.conf.bs);
     add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0");
     return 0;
 }
-- 
1.7.6

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

* [Qemu-devel] [PATCH 29/35] scsi-disk: remove cluster_size
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (27 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 28/35] scsi-disk: do not duplicate BlockDriverState member Paolo Bonzini
@ 2011-10-13 11:03 ` Paolo Bonzini
  2011-10-24 15:10   ` Kevin Wolf
  2011-10-13 11:04 ` [Qemu-devel] [PATCH 30/35] scsi-disk: small clean up to INQUIRY Paolo Bonzini
                   ` (5 subsequent siblings)
  34 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:03 UTC (permalink / raw)
  To: qemu-devel

This field is redundant, and its presence makes it more complicated
to share reqops between the upcoming scsi-block and scsi-generic.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |   45 ++++++++++++++++++++++-----------------------
 1 files changed, 22 insertions(+), 23 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 5e3ef51..7f2f67f 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -65,9 +65,6 @@ typedef struct SCSIDiskReq {
 struct SCSIDiskState
 {
     SCSIDevice qdev;
-    /* The qemu block layer uses a fixed 512 byte sector size.
-       This is the number of 512 byte blocks in a single scsi sector.  */
-    int cluster_size;
     uint32_t removable;
     uint64_t max_lba;
     bool media_changed;
@@ -862,7 +859,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
         bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
         p[4] = heads & 0xff;
         p[5] = secs & 0xff;
-        p[6] = s->cluster_size * 2;
+        p[6] = s->qdev.blocksize >> 8;
         p[8] = (cylinders >> 8) & 0xff;
         p[9] = cylinders & 0xff;
         /* Write precomp start cylinder, disabled */
@@ -991,7 +988,7 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
         } else { /* MODE_SENSE_10 */
             outbuf[7] = 8; /* Block descriptor length  */
         }
-        nb_sectors /= s->cluster_size;
+        nb_sectors /= (s->qdev.blocksize / 512);
         if (nb_sectors > 0xffffff)
             nb_sectors = 0;
         p[0] = 0; /* media density code */
@@ -1000,7 +997,7 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
         p[3] = nb_sectors & 0xff;
         p[4] = 0; /* reserved */
         p[5] = 0; /* bytes 5-7 are the sector size in bytes */
-        p[6] = s->cluster_size * 2;
+        p[6] = s->qdev.blocksize >> 8;
         p[7] = 0;
         p += 8;
     }
@@ -1050,7 +1047,7 @@ static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
     start_track = req->cmd.buf[6];
     bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
     DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
-    nb_sectors /= s->cluster_size;
+    nb_sectors /= s->qdev.blocksize / 512;
     switch (format) {
     case 0:
         toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
@@ -1176,7 +1173,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
         if ((req->cmd.buf[8] & 1) == 0 && req->cmd.lba) {
             goto illegal_request;
         }
-        nb_sectors /= s->cluster_size;
+        nb_sectors /= s->qdev.blocksize / 512;
         /* Returned value is the address of the last sector.  */
         nb_sectors--;
         /* Remember the new size for read/write sanity checking. */
@@ -1190,7 +1187,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
         outbuf[3] = nb_sectors & 0xff;
         outbuf[4] = 0;
         outbuf[5] = 0;
-        outbuf[6] = s->cluster_size * 2;
+        outbuf[6] = s->qdev.blocksize >> 8;
         outbuf[7] = 0;
         buflen = 8;
         break;
@@ -1226,7 +1223,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
             if ((req->cmd.buf[14] & 1) == 0 && req->cmd.lba) {
                 goto illegal_request;
             }
-            nb_sectors /= s->cluster_size;
+            nb_sectors /= s->qdev.blocksize / 512;
             /* Returned value is the address of the last sector.  */
             nb_sectors--;
             /* Remember the new size for read/write sanity checking. */
@@ -1241,7 +1238,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
             outbuf[7] = nb_sectors & 0xff;
             outbuf[8] = 0;
             outbuf[9] = 0;
-            outbuf[10] = s->cluster_size * 2;
+            outbuf[10] = s->qdev.blocksize >> 8;
             outbuf[11] = 0;
             outbuf[12] = 0;
             outbuf[13] = get_physical_block_exp(&s->qdev.conf);
@@ -1349,8 +1346,8 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
         DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len);
         if (r->req.cmd.lba > s->max_lba)
             goto illegal_lba;
-        r->sector = r->req.cmd.lba * s->cluster_size;
-        r->sector_count = len * s->cluster_size;
+        r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
+        r->sector_count = len * (s->qdev.blocksize / 512);
         break;
     case WRITE_6:
     case WRITE_10:
@@ -1365,8 +1362,8 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
                 r->req.cmd.lba, len);
         if (r->req.cmd.lba > s->max_lba)
             goto illegal_lba;
-        r->sector = r->req.cmd.lba * s->cluster_size;
-        r->sector_count = len * s->cluster_size;
+        r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
+        r->sector_count = len * (s->qdev.blocksize / 512);
         break;
     case MODE_SELECT:
         DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
@@ -1409,8 +1406,9 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
             goto fail;
         }
 
-        rc = bdrv_discard(s->qdev.conf.bs, r->req.cmd.lba * s->cluster_size,
-                          len * s->cluster_size);
+        rc = bdrv_discard(s->qdev.conf.bs,
+                          r->req.cmd.lba * (s->qdev.blocksize / 512),
+                          len * (s->qdev.blocksize / 512));
         if (rc < 0) {
             /* XXX: better error code ?*/
             goto fail;
@@ -1450,12 +1448,14 @@ static void scsi_disk_reset(DeviceState *dev)
 
     scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
 
-    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
-    nb_sectors /= s->cluster_size;
-    if (nb_sectors) {
-        nb_sectors--;
+    if (s->qdev.blocksize) {
+        bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
+        nb_sectors /= s->qdev.blocksize / 512;
+        if (nb_sectors) {
+            nb_sectors--;
+        }
+        s->max_lba = nb_sectors;
     }
-    s->max_lba = nb_sectors;
 }
 
 static void scsi_destroy(SCSIDevice *dev)
@@ -1552,7 +1552,6 @@ static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
         error_report("scsi-disk: Unhandled SCSI type %02x", scsi_type);
         return -1;
     }
-    s->cluster_size = s->qdev.blocksize / 512;
     bdrv_set_buffer_alignment(s->qdev.conf.bs, s->qdev.blocksize);
 
     s->qdev.type = scsi_type;
-- 
1.7.6

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

* [Qemu-devel] [PATCH 30/35] scsi-disk: small clean up to INQUIRY
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (28 preceding siblings ...)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 29/35] scsi-disk: remove cluster_size Paolo Bonzini
@ 2011-10-13 11:04 ` Paolo Bonzini
  2011-10-13 11:04 ` [Qemu-devel] [PATCH 31/35] scsi: move max_lba to SCSIDevice Paolo Bonzini
                   ` (4 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:04 UTC (permalink / raw)
  To: qemu-devel

Set s->removable, s->qdev.blocksize and s->qdev.type in the callers
of scsi_initfn.

With this in place, s->qdev.type is allowed, and we can just reuse it
as the first byte in VPD data (just like we do in standard INQUIRY data).
Also set s->removable is set consistently and we can use it.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |   46 +++++++++++++++++++++-------------------------
 1 files changed, 21 insertions(+), 25 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 7f2f67f..cc3998e 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -394,11 +394,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
             return -1;
         }
 
-        if (s->qdev.type == TYPE_ROM) {
-            outbuf[buflen++] = 5;
-        } else {
-            outbuf[buflen++] = 0;
-        }
+        outbuf[buflen++] = s->qdev.type & 0x1f;
         outbuf[buflen++] = page_code ; // this page
         outbuf[buflen++] = 0x00;
 
@@ -538,11 +534,10 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
     memset(outbuf, 0, buflen);
 
     outbuf[0] = s->qdev.type & 0x1f;
+    outbuf[1] = s->removable ? 0x80 : 0;
     if (s->qdev.type == TYPE_ROM) {
-        outbuf[1] = 0x80;
         memcpy(&outbuf[16], "QEMU CD-ROM     ", 16);
     } else {
-        outbuf[1] = s->removable ? 0x80 : 0;
         memcpy(&outbuf[16], "QEMU HARDDISK   ", 16);
     }
     memcpy(&outbuf[8], "QEMU    ", 8);
@@ -1511,7 +1506,7 @@ static void scsi_disk_unit_attention_reported(SCSIDevice *dev)
     }
 }
 
-static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
+static int scsi_initfn(SCSIDevice *dev)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
     DriveInfo *dinfo;
@@ -1521,7 +1516,7 @@ static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
         return -1;
     }
 
-    if (scsi_type == TYPE_DISK && !bdrv_is_inserted(s->qdev.conf.bs)) {
+    if (!s->removable && !bdrv_is_inserted(s->qdev.conf.bs)) {
         error_report("Device needs media, but drive is empty");
         return -1;
     }
@@ -1543,18 +1538,11 @@ static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
         return -1;
     }
 
-    if (scsi_type == TYPE_ROM) {
+    if (s->removable) {
         bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_cd_block_ops, s);
-        s->qdev.blocksize = 2048;
-    } else if (scsi_type == TYPE_DISK) {
-        s->qdev.blocksize = s->qdev.conf.logical_block_size;
-    } else {
-        error_report("scsi-disk: Unhandled SCSI type %02x", scsi_type);
-        return -1;
     }
     bdrv_set_buffer_alignment(s->qdev.conf.bs, s->qdev.blocksize);
 
-    s->qdev.type = scsi_type;
     qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
     bdrv_iostatus_enable(s->qdev.conf.bs);
     add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0");
@@ -1563,27 +1551,35 @@ static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
 
 static int scsi_hd_initfn(SCSIDevice *dev)
 {
-    return scsi_initfn(dev, TYPE_DISK);
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
+    s->qdev.blocksize = s->qdev.conf.logical_block_size;
+    s->qdev.type = TYPE_DISK;
+    return scsi_initfn(&s->qdev);
 }
 
 static int scsi_cd_initfn(SCSIDevice *dev)
 {
-    return scsi_initfn(dev, TYPE_ROM);
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
+    s->qdev.blocksize = 2048;
+    s->qdev.type = TYPE_ROM;
+    s->removable = true;
+    return scsi_initfn(&s->qdev);
 }
 
 static int scsi_disk_initfn(SCSIDevice *dev)
 {
     DriveInfo *dinfo;
-    uint8_t scsi_type;
 
     if (!dev->conf.bs) {
-        scsi_type = TYPE_DISK;  /* will die in scsi_initfn() */
-    } else {
-        dinfo = drive_get_by_blockdev(dev->conf.bs);
-        scsi_type = dinfo->media_cd ? TYPE_ROM : TYPE_DISK;
+        return scsi_initfn(dev);  /* ... and die there */
     }
 
-    return scsi_initfn(dev, scsi_type);
+    dinfo = drive_get_by_blockdev(dev->conf.bs);
+    if (dinfo->media_cd) {
+        return scsi_cd_initfn(dev);
+    } else {
+        return scsi_hd_initfn(dev);
+    }
 }
 
 static SCSIReqOps scsi_disk_reqops = {
-- 
1.7.6

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

* [Qemu-devel] [PATCH 31/35] scsi: move max_lba to SCSIDevice
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (29 preceding siblings ...)
  2011-10-13 11:04 ` [Qemu-devel] [PATCH 30/35] scsi-disk: small clean up to INQUIRY Paolo Bonzini
@ 2011-10-13 11:04 ` Paolo Bonzini
  2011-10-13 11:04 ` [Qemu-devel] [PATCH 32/35] scsi: make reqops static const Paolo Bonzini
                   ` (3 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:04 UTC (permalink / raw)
  To: qemu-devel

The field was only in scsi-disk until now.  Moving it up to SCSIDevice
will make it easier to reuse the scsi-generic reqops elsewhere.  In
the future, range checking of LBA arguments might also be pushed up
to SCSIDevice.

At the same time, make scsi-generic get max_lba from the guest's READ
CAPACITY commands, as well.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c    |   15 +++++++--------
 hw/scsi-generic.c |    2 ++
 hw/scsi.h         |    1 +
 3 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index cc3998e..26aa46a 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -66,7 +66,6 @@ struct SCSIDiskState
 {
     SCSIDevice qdev;
     uint32_t removable;
-    uint64_t max_lba;
     bool media_changed;
     bool media_event;
     QEMUBH *bh;
@@ -1172,7 +1171,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
         /* Returned value is the address of the last sector.  */
         nb_sectors--;
         /* Remember the new size for read/write sanity checking. */
-        s->max_lba = nb_sectors;
+        s->qdev.max_lba = nb_sectors;
         /* Clip to 2TB, instead of returning capacity modulo 2TB. */
         if (nb_sectors > UINT32_MAX)
             nb_sectors = UINT32_MAX;
@@ -1222,7 +1221,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
             /* Returned value is the address of the last sector.  */
             nb_sectors--;
             /* Remember the new size for read/write sanity checking. */
-            s->max_lba = nb_sectors;
+            s->qdev.max_lba = nb_sectors;
             outbuf[0] = (nb_sectors >> 56) & 0xff;
             outbuf[1] = (nb_sectors >> 48) & 0xff;
             outbuf[2] = (nb_sectors >> 40) & 0xff;
@@ -1339,7 +1338,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
     case READ_16:
         len = r->req.cmd.xfer / s->qdev.blocksize;
         DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len);
-        if (r->req.cmd.lba > s->max_lba)
+        if (r->req.cmd.lba > s->qdev.max_lba)
             goto illegal_lba;
         r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
         r->sector_count = len * (s->qdev.blocksize / 512);
@@ -1355,7 +1354,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
         DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",
                 (command & 0xe) == 0xe ? "And Verify " : "",
                 r->req.cmd.lba, len);
-        if (r->req.cmd.lba > s->max_lba)
+        if (r->req.cmd.lba > s->qdev.max_lba)
             goto illegal_lba;
         r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
         r->sector_count = len * (s->qdev.blocksize / 512);
@@ -1380,7 +1379,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
     case SEEK_10:
         DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10,
                 r->req.cmd.lba);
-        if (r->req.cmd.lba > s->max_lba) {
+        if (r->req.cmd.lba > s->qdev.max_lba) {
             goto illegal_lba;
         }
         break;
@@ -1390,7 +1389,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
         DPRINTF("WRITE SAME(16) (sector %" PRId64 ", count %d)\n",
                 r->req.cmd.lba, len);
 
-        if (r->req.cmd.lba > s->max_lba) {
+        if (r->req.cmd.lba > s->qdev.max_lba) {
             goto illegal_lba;
         }
 
@@ -1449,7 +1448,7 @@ static void scsi_disk_reset(DeviceState *dev)
         if (nb_sectors) {
             nb_sectors--;
         }
-        s->max_lba = nb_sectors;
+        s->qdev.max_lba = nb_sectors;
     }
 }
 
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index cb02a7e..06089ab 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -174,9 +174,11 @@ static void scsi_read_complete(void * opaque, int ret)
         /* Snoop READ CAPACITY output to set the blocksize.  */
         if (r->req.cmd.buf[0] == READ_CAPACITY_10) {
             s->blocksize = ldl_be_p(&r->buf[4]);
+            s->max_lba = ldl_be_p(&r->buf[0]);
         } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
                    (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
             s->blocksize = ldl_be_p(&r->buf[8]);
+            s->max_lba = ldq_be_p(&r->buf[0]);
         }
         bdrv_set_buffer_alignment(s->conf.bs, s->blocksize);
 
diff --git a/hw/scsi.h b/hw/scsi.h
index c8649cf..d56e875 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -70,6 +70,7 @@ struct SCSIDevice
     uint32_t lun;
     int blocksize;
     int type;
+    uint64_t max_lba;
 };
 
 /* cdrom.c */
-- 
1.7.6

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

* [Qemu-devel] [PATCH 32/35] scsi: make reqops static const
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (30 preceding siblings ...)
  2011-10-13 11:04 ` [Qemu-devel] [PATCH 31/35] scsi: move max_lba to SCSIDevice Paolo Bonzini
@ 2011-10-13 11:04 ` Paolo Bonzini
  2011-10-13 11:04 ` [Qemu-devel] [PATCH 33/35] scsi: export scsi_generic_reqops Paolo Bonzini
                   ` (2 subsequent siblings)
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:04 UTC (permalink / raw)
  To: qemu-devel

Also delete a stale occurrence of SCSIReqOps inside SCSIDeviceInfo.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-bus.c     |   10 +++++-----
 hw/scsi-disk.c    |    2 +-
 hw/scsi-generic.c |    2 +-
 hw/scsi.h         |    7 +++----
 4 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index bdd6e94..252e903 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -160,7 +160,7 @@ static int32_t scsi_invalid_command(SCSIRequest *req, uint8_t *buf)
     return 0;
 }
 
-struct SCSIReqOps reqops_invalid_opcode = {
+static const struct SCSIReqOps reqops_invalid_opcode = {
     .size         = sizeof(SCSIRequest),
     .send_command = scsi_invalid_command
 };
@@ -178,7 +178,7 @@ static int32_t scsi_unit_attention(SCSIRequest *req, uint8_t *buf)
     return 0;
 }
 
-struct SCSIReqOps reqops_unit_attention = {
+static const struct SCSIReqOps reqops_unit_attention = {
     .size         = sizeof(SCSIRequest),
     .send_command = scsi_unit_attention
 };
@@ -386,7 +386,7 @@ static uint8_t *scsi_target_get_buf(SCSIRequest *req)
     return r->buf;
 }
 
-struct SCSIReqOps reqops_target_command = {
+static const struct SCSIReqOps reqops_target_command = {
     .size         = sizeof(SCSITargetReq),
     .send_command = scsi_target_send_command,
     .read_data    = scsi_target_read_data,
@@ -394,8 +394,8 @@ struct SCSIReqOps reqops_target_command = {
 };
 
 
-SCSIRequest *scsi_req_alloc(SCSIReqOps *reqops, SCSIDevice *d, uint32_t tag,
-                            uint32_t lun, void *hba_private)
+SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
+                            uint32_t tag, uint32_t lun, void *hba_private)
 {
     SCSIRequest *req;
 
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 26aa46a..90676fe 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1581,7 +1581,7 @@ static int scsi_disk_initfn(SCSIDevice *dev)
     }
 }
 
-static SCSIReqOps scsi_disk_reqops = {
+static const SCSIReqOps scsi_disk_reqops = {
     .size         = sizeof(SCSIDiskReq),
     .free_req     = scsi_free_request,
     .send_command = scsi_send_command,
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 06089ab..abe92fa 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -407,7 +407,7 @@ static int scsi_generic_initfn(SCSIDevice *s)
     return 0;
 }
 
-static SCSIReqOps scsi_generic_req_ops = {
+static const SCSIReqOps scsi_generic_req_ops = {
     .size         = sizeof(SCSIGenericReq),
     .free_req     = scsi_free_request,
     .send_command = scsi_send_command,
diff --git a/hw/scsi.h b/hw/scsi.h
index d56e875..af558c3 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -41,7 +41,7 @@ struct SCSICommand {
 struct SCSIRequest {
     SCSIBus           *bus;
     SCSIDevice        *dev;
-    SCSIReqOps        *ops;
+    const SCSIReqOps  *ops;
     uint32_t          refcount;
     uint32_t          tag;
     uint32_t          lun;
@@ -96,7 +96,6 @@ struct SCSIDeviceInfo {
     SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
                               void *hba_private);
     void (*unit_attention_reported)(SCSIDevice *s);
-    SCSIReqOps reqops;
 };
 
 struct SCSIBusInfo {
@@ -176,8 +175,8 @@ extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET;
 
 int scsi_sense_valid(SCSISense sense);
 
-SCSIRequest *scsi_req_alloc(SCSIReqOps *reqops, SCSIDevice *d, uint32_t tag,
-                            uint32_t lun, void *hba_private);
+SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
+                            uint32_t tag, uint32_t lun, void *hba_private);
 SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
                           uint8_t *buf, void *hba_private);
 int32_t scsi_req_enqueue(SCSIRequest *req);
-- 
1.7.6

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

* [Qemu-devel] [PATCH 33/35] scsi: export scsi_generic_reqops
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (31 preceding siblings ...)
  2011-10-13 11:04 ` [Qemu-devel] [PATCH 32/35] scsi: make reqops static const Paolo Bonzini
@ 2011-10-13 11:04 ` Paolo Bonzini
  2011-10-13 11:04 ` [Qemu-devel] [PATCH 34/35] scsi: pass cdb to alloc_req Paolo Bonzini
  2011-10-13 11:04 ` [Qemu-devel] [PATCH 35/35] scsi-disk: add scsi-block for device passthrough Paolo Bonzini
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:04 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-generic.c |    2 +-
 hw/scsi.h         |    3 +++
 2 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index abe92fa..c4f928a 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -407,7 +407,7 @@ static int scsi_generic_initfn(SCSIDevice *s)
     return 0;
 }
 
-static const SCSIReqOps scsi_generic_req_ops = {
+const SCSIReqOps scsi_generic_req_ops = {
     .size         = sizeof(SCSIGenericReq),
     .free_req     = scsi_free_request,
     .send_command = scsi_send_command,
diff --git a/hw/scsi.h b/hw/scsi.h
index af558c3..01c6655 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -197,4 +197,7 @@ void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
 int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
 SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
 
+/* scsi-generic.c. */
+extern const SCSIReqOps scsi_generic_req_ops;
+
 #endif
-- 
1.7.6

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

* [Qemu-devel] [PATCH 34/35] scsi: pass cdb to alloc_req
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (32 preceding siblings ...)
  2011-10-13 11:04 ` [Qemu-devel] [PATCH 33/35] scsi: export scsi_generic_reqops Paolo Bonzini
@ 2011-10-13 11:04 ` Paolo Bonzini
  2011-10-13 11:04 ` [Qemu-devel] [PATCH 35/35] scsi-disk: add scsi-block for device passthrough Paolo Bonzini
  34 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:04 UTC (permalink / raw)
  To: qemu-devel

This will let scsi-block choose between passthrough and emulation.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-bus.c     |    2 +-
 hw/scsi-disk.c    |    4 ++--
 hw/scsi-generic.c |    2 +-
 hw/scsi.h         |    2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 252e903..72c0dd2 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -451,7 +451,7 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
             req = scsi_req_alloc(&reqops_target_command, d, tag, lun,
                                  hba_private);
         } else {
-            req = d->info->alloc_req(d, tag, lun, hba_private);
+            req = d->info->alloc_req(d, tag, lun, buf, hba_private);
         }
     }
 
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 90676fe..418b30d 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1591,8 +1591,8 @@ static const SCSIReqOps scsi_disk_reqops = {
     .get_buf      = scsi_get_buf,
 };
 
-static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag,
-                                     uint32_t lun, void *hba_private)
+static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
+                                     uint8_t *buf, void *hba_private)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
     SCSIRequest *req;
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index c4f928a..582d2a6 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -418,7 +418,7 @@ const SCSIReqOps scsi_generic_req_ops = {
 };
 
 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
-                                     void *hba_private)
+                                     uint8_t *buf, void *hba_private)
 {
     SCSIRequest *req;
 
diff --git a/hw/scsi.h b/hw/scsi.h
index 01c6655..8ea744a 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -94,7 +94,7 @@ struct SCSIDeviceInfo {
     scsi_qdev_initfn init;
     void (*destroy)(SCSIDevice *s);
     SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
-                              void *hba_private);
+                              uint8_t *buf, void *hba_private);
     void (*unit_attention_reported)(SCSIDevice *s);
 };
 
-- 
1.7.6

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

* [Qemu-devel] [PATCH 35/35] scsi-disk: add scsi-block for device passthrough
  2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
                   ` (33 preceding siblings ...)
  2011-10-13 11:04 ` [Qemu-devel] [PATCH 34/35] scsi: pass cdb to alloc_req Paolo Bonzini
@ 2011-10-13 11:04 ` Paolo Bonzini
  2011-10-24 15:28   ` Kevin Wolf
  34 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-13 11:04 UTC (permalink / raw)
  To: qemu-devel

scsi-block is a new device that supports device passthrough of Linux
block devices (i.e. /dev/sda, not /dev/sg0).  It uses SG_IO for commands
other than I/O commands, and regular AIO read/writes for I/O commands.
Besides being simpler to configure (no mapping required to scsi-generic
device names), this removes the need for a large bounce buffer and,
in the future, will get scatter/gather support for free from scsi-disk.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |  111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 111 insertions(+), 0 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 418b30d..b21fe1b 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -39,6 +39,10 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
 #include "blockdev.h"
 #include "block_int.h"
 
+#ifdef __linux
+#include <scsi/sg.h>
+#endif
+
 #define SCSI_DMA_BUF_SIZE    131072
 #define SCSI_MAX_INQUIRY_LEN 256
 
@@ -1601,6 +1605,98 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
     return req;
 }
 
+#ifdef __linux__
+static int get_device_type(SCSIDiskState *s)
+{
+    BlockDriverState *bdrv = s->qdev.conf.bs;
+    uint8_t cmd[16];
+    uint8_t buf[36];
+    uint8_t sensebuf[8];
+    sg_io_hdr_t io_header;
+    int ret;
+
+    memset(cmd, 0, sizeof(cmd));
+    memset(buf, 0, sizeof(buf));
+    cmd[0] = INQUIRY;
+    cmd[4] = sizeof(buf);
+
+    memset(&io_header, 0, sizeof(io_header));
+    io_header.interface_id = 'S';
+    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
+    io_header.dxfer_len = sizeof(buf);
+    io_header.dxferp = buf;
+    io_header.cmdp = cmd;
+    io_header.cmd_len = sizeof(cmd);
+    io_header.mx_sb_len = sizeof(sensebuf);
+    io_header.sbp = sensebuf;
+    io_header.timeout = 6000; /* XXX */
+
+    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
+    if (ret < 0 || io_header.driver_status || io_header.host_status) {
+        return -1;
+    }
+    s->qdev.type = buf[0];
+    s->removable = (buf[1] & 0x80) != 0;
+    s->qdev.blocksize = 0;
+    s->qdev.max_lba = 0;
+    return 0;
+}
+
+static int scsi_block_initfn(SCSIDevice *dev)
+{
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
+    int sg_version;
+    int rc;
+
+    if (!s->qdev.conf.bs) {
+        error_report("scsi-block: drive property not set");
+        return -1;
+    }
+
+    /* check we are using a driver managing SG_IO (version 3 and after) */
+    if (bdrv_ioctl(s->qdev.conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
+        sg_version < 30000) {
+        error_report("scsi-block: scsi generic interface too old");
+        return -1;
+    }
+
+    /* get device type from INQUIRY data */
+    rc = get_device_type(s);
+    if (rc < 0) {
+        error_report("scsi-block: INQUIRY failed");
+        return -1;
+    }
+
+    return scsi_initfn(&s->qdev);
+}
+
+static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
+                                           uint32_t lun, uint8_t *buf,
+                                           void *hba_private)
+{
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
+
+    switch (buf[0]) {
+    case READ_6:
+    case READ_10:
+    case READ_12:
+    case READ_16:
+    case WRITE_6:
+    case WRITE_10:
+    case WRITE_12:
+    case WRITE_16:
+    case WRITE_VERIFY_10:
+    case WRITE_VERIFY_12:
+    case WRITE_VERIFY_16:
+        return scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun,
+                              hba_private);
+    }
+
+    return scsi_req_alloc(&scsi_generic_req_ops, &s->qdev, tag, lun,
+                          hba_private);
+}
+#endif
+
 #define DEFINE_SCSI_DISK_PROPERTIES()                           \
     DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf),          \
     DEFINE_PROP_STRING("ver",  SCSIDiskState, version),         \
@@ -1636,6 +1732,21 @@ static SCSIDeviceInfo scsi_disk_info[] = {
             DEFINE_SCSI_DISK_PROPERTIES(),
             DEFINE_PROP_END_OF_LIST(),
         },
+#ifdef __linux__
+    },{
+        .qdev.name    = "scsi-block",
+        .qdev.fw_name = "disk",
+        .qdev.desc    = "SCSI block device passthrough",
+        .qdev.size    = sizeof(SCSIDiskState),
+        .qdev.reset   = scsi_disk_reset,
+        .init         = scsi_block_initfn,
+        .destroy      = scsi_destroy,
+        .alloc_req    = scsi_block_new_request,
+        .qdev.props   = (Property[]) {
+            DEFINE_SCSI_DISK_PROPERTIES(),
+            DEFINE_PROP_END_OF_LIST(),
+        },
+#endif
     },{
         .qdev.name    = "scsi-disk", /* legacy -device scsi-disk */
         .qdev.fw_name = "disk",
-- 
1.7.6

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

* Re: [Qemu-devel] [PATCH 03/35] atapi: move GESN definitions to scsi-defs.h
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 03/35] atapi: move GESN definitions to scsi-defs.h Paolo Bonzini
@ 2011-10-17 13:41   ` Kevin Wolf
  2011-10-17 13:53     ` Paolo Bonzini
  0 siblings, 1 reply; 68+ messages in thread
From: Kevin Wolf @ 2011-10-17 13:41 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Am 13.10.2011 13:03, schrieb Paolo Bonzini:
> As a complement to the previous patch, move definitions for GET EVENT
> STATUS NOTIFICATION from the two functions to scsi-defs.h.
> 
> The NCR_* constants are just bit values corresponding to the ENC_*
> values, with no offsets even, so keep just one copy.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

I'm not sure about the NCR_* constants. They happen to be shifted
values, but the spec doesn't define them as such but has two separate
tables for them.

> ---
>  hw/ide/atapi.c |   43 ++++++-------------------------------------
>  hw/scsi-defs.h |   21 +++++++++++++++++++++
>  2 files changed, 27 insertions(+), 37 deletions(-)

> diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
> index dfa3095..8094698 100644
> --- a/hw/scsi-defs.h
> +++ b/hw/scsi-defs.h
> @@ -203,6 +203,27 @@
>   * of MODE_PAGE_SENSE_POWER */
>  #define MODE_PAGE_CDROM			0x0d
>  
> +/* Event notification classes for GET EVENT STATUS NOTIFICATION */
> +#define GESN_NO_EVENTS			0
> +#define GESN_OPERATIONAL_CHANGE		1
> +#define GESN_POWER_MANAGEMENT		2
> +#define GESN_EXTERNAL_REQUEST		3
> +#define GESN_MEDIA			4
> +#define GESN_MULTIPLE_HOSTS		5
> +#define GESN_DEVICE_BUSY		6
> +
> +/* Event codes for MEDIA event status notification */
> +#define MEC_NO_CHANGE		0
> +#define MEC_EJECT_REQUESTED	1
> +#define MEC_NEW_MEDIA		2
> +#define MEC_MEDIA_REMOVAL	3 /* only for media changers */
> +#define MEC_MEDIA_CHANGED	4 /* only for media changers */
> +#define MEC_BG_FORMAT_COMPLETED	5 /* MRW or DVD+RW b/g format completed */
> +#define MEC_BG_FORMAT_RESTARTED	6 /* MRW or DVD+RW b/g format restarted */
> +
> +#define MS_TRAY_OPEN		1
> +#define MS_MEDIA_PRESENT	2

This should be spaces instead of tabs, the alignment is completely
broken for me.

Now that I looked for them I see that patch 2 has some tabs as well,
even though they are just moved. You could fix them anyway while
touching the code.

Kevin

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

* Re: [Qemu-devel] [PATCH 03/35] atapi: move GESN definitions to scsi-defs.h
  2011-10-17 13:41   ` Kevin Wolf
@ 2011-10-17 13:53     ` Paolo Bonzini
  0 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-17 13:53 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

On 10/17/2011 03:41 PM, Kevin Wolf wrote:
> I'm not sure about the NCR_* constants. They happen to be shifted
> values, but the spec doesn't define them as such but has two separate
> tables for them.

Yeah, on the other hand the spec has hints that they are really the same 
thing:

1) one is called notification class request, the other is called 
notification class.  Using the same name is surprising since the SCSI 
spec usually cannot praised for its consistency.  For example the 
returned header includes a field called "supported event classes" 
(rather than for example "supported notification classes"), but the 
description refers explicitly to the same table used for the 
"notification class request" field.

2) "bit 0 is perpetually reserved" in the notification class request 
field, and the notification class field value "000" means "no requested 
event classes are supported".

Paolo

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

* Re: [Qemu-devel] [PATCH 04/35] atapi: fill in AUDIO_CTL page correctly
  2011-10-17 14:05   ` Kevin Wolf
@ 2011-10-17 14:04     ` Paolo Bonzini
  2011-10-17 14:10       ` Kevin Wolf
  0 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-17 14:04 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

On 10/17/2011 04:05 PM, Kevin Wolf wrote:
>> >  diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
>> >  index 347c38d..10f161f 100644
>> >  --- a/hw/ide/atapi.c
>> >  +++ b/hw/ide/atapi.c
>> >  @@ -731,6 +731,8 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
>> >                buf[7] = 0;
>> >
>> >                /* Fill with CDROM audio volume */
>> >  +            buf[8] = 0x0e;
>
> 0x0e would be more readable if it was written as MODE_PAGE_AUDIO_CTL.
>
>> >  +            buf[9] = 0x0e;
>
> And this is really the length. But I'm not sure if writing it as 24 - 10
> would help a lot.

Yes, the coincidence is ugly.

> Of course the same is true for the other pages, so it could be done for
> all of them on top. Or maybe you actually have included it later in the
> series?

Only for SCSI.  I can queue it as a cleanup for ATAPI.

Paolo

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

* Re: [Qemu-devel] [PATCH 04/35] atapi: fill in AUDIO_CTL page correctly
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 04/35] atapi: fill in AUDIO_CTL page correctly Paolo Bonzini
@ 2011-10-17 14:05   ` Kevin Wolf
  2011-10-17 14:04     ` Paolo Bonzini
  0 siblings, 1 reply; 68+ messages in thread
From: Kevin Wolf @ 2011-10-17 14:05 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Am 13.10.2011 13:03, schrieb Paolo Bonzini:
> The page is not anymore in MMC, but at least keep the values sane.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/ide/atapi.c |    2 ++
>  1 files changed, 2 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
> index 347c38d..10f161f 100644
> --- a/hw/ide/atapi.c
> +++ b/hw/ide/atapi.c
> @@ -731,6 +731,8 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
>              buf[7] = 0;
>  
>              /* Fill with CDROM audio volume */
> +            buf[8] = 0x0e;

0x0e would be more readable if it was written as MODE_PAGE_AUDIO_CTL.

> +            buf[9] = 0x0e;

And this is really the length. But I'm not sure if writing it as 24 - 10
would help a lot.

>              buf[17] = 0;
>              buf[19] = 0;
>              buf[21] = 0;


Of course the same is true for the other pages, so it could be done for
all of them on top. Or maybe you actually have included it later in the
series?

Kevin

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

* Re: [Qemu-devel] [PATCH 04/35] atapi: fill in AUDIO_CTL page correctly
  2011-10-17 14:04     ` Paolo Bonzini
@ 2011-10-17 14:10       ` Kevin Wolf
  2011-10-17 14:22         ` Paolo Bonzini
  0 siblings, 1 reply; 68+ messages in thread
From: Kevin Wolf @ 2011-10-17 14:10 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Am 17.10.2011 16:04, schrieb Paolo Bonzini:
> On 10/17/2011 04:05 PM, Kevin Wolf wrote:
>>>>  diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
>>>>  index 347c38d..10f161f 100644
>>>>  --- a/hw/ide/atapi.c
>>>>  +++ b/hw/ide/atapi.c
>>>>  @@ -731,6 +731,8 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
>>>>                buf[7] = 0;
>>>>
>>>>                /* Fill with CDROM audio volume */
>>>>  +            buf[8] = 0x0e;
>>
>> 0x0e would be more readable if it was written as MODE_PAGE_AUDIO_CTL.
>>
>>>>  +            buf[9] = 0x0e;
>>
>> And this is really the length. But I'm not sure if writing it as 24 - 10
>> would help a lot.
> 
> Yes, the coincidence is ugly.

Maybe we should define structs for the mode pages so that you have real
names instead of just offsets into the output buffer?

>> Of course the same is true for the other pages, so it could be done for
>> all of them on top. Or maybe you actually have included it later in the
>> series?
> 
> Only for SCSI.  I can queue it as a cleanup for ATAPI.

That would be good.

Kevin

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

* Re: [Qemu-devel] [PATCH 04/35] atapi: fill in AUDIO_CTL page correctly
  2011-10-17 14:10       ` Kevin Wolf
@ 2011-10-17 14:22         ` Paolo Bonzini
  0 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-17 14:22 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

On 10/17/2011 04:10 PM, Kevin Wolf wrote:
>> >  Yes, the coincidence is ugly.
>
> Maybe we should define structs for the mode pages so that you have real
> names instead of just offsets into the output buffer?

Yeah, it would be nice to have a common place for all the structs 
defined by the SCSI spec (also the GET CONFIGURATION data is ugly).

Paolo

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

* Re: [Qemu-devel] [PATCH 07/35] scsi-disk: add stubs for more MMC commands
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 07/35] scsi-disk: add stubs for more MMC commands Paolo Bonzini
@ 2011-10-17 14:27   ` Kevin Wolf
  2011-10-17 14:28     ` Paolo Bonzini
  0 siblings, 1 reply; 68+ messages in thread
From: Kevin Wolf @ 2011-10-17 14:27 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Am 13.10.2011 13:03, schrieb Paolo Bonzini:
> This patch adds a few stub implementations for MMC commands to
> scsi-disk, to be filled in later in the series.  It also adds to
> scsi-defs.h constants for commands implemented by ide/atapi.c,
> when missing.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/scsi-defs.h |    3 ++
>  hw/scsi-disk.c |   63 +++++++++++++++++++++++++++++++++++++++++++++++++++----
>  2 files changed, 61 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
> index 8094698..030d4c2 100644
> --- a/hw/scsi-defs.h
> +++ b/hw/scsi-defs.h
> @@ -113,6 +113,7 @@
>  #define READ_12               0xa8
>  #define WRITE_12              0xaa
>  #define SERVICE_ACTION_IN_12  0xab
> +#define READ_DVD_STRUCTURE    0xad
>  #define WRITE_VERIFY_12       0xae
>  #define VERIFY_12             0xaf
>  #define SEARCH_HIGH_12        0xb0
> @@ -122,6 +123,8 @@
>  #define SEND_VOLUME_TAG       0xb6
>  #define READ_DEFECT_DATA_12   0xb7
>  #define SET_CD_SPEED          0xbb
> +#define MECHANISM_STATUS      0xbd
> +#define READ_CD               0xbe
>  
>  /*
>   * SERVICE ACTION IN subcodes
> diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
> index 880cb22..95a6b77 100644
> --- a/hw/scsi-disk.c
> +++ b/hw/scsi-disk.c
> @@ -563,6 +563,43 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
>      return buflen;
>  }
>  
> +static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
> +                                   uint8_t *outbuf)
> +{
> +    scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
> +    return -1;
> +}
> +
> +static int scsi_get_event_status_notification(SCSIDiskState *s,
> +                                              SCSIDiskReq *r, uint8_t *outbuf)
> +{
> +    scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
> +    return -1;
> +}
> +
> +static int scsi_get_configuration(SCSIDiskState *s, SCSIDiskReq *r,
> +                                  uint8_t *outbuf)
> +{
> +    if (s->qdev.type != TYPE_ROM) {
> +        return -1;
> +    }
> +    memset(outbuf, 0, 8);
> +    /* ??? This should probably return much more information.  For now
> +       just return the basic header indicating the CD-ROM profile.  */
> +    outbuf[7] = 8; // CD-ROM
> +    return 8;
> +}
> +
> +static int scsi_emulate_mechanism_status(SCSIDiskState *s, uint8_t *outbuf)
> +{
> +    if (s->qdev.type != TYPE_ROM) {
> +        return -1;
> +    }
> +    memset(outbuf, 0, 8);
> +    outbuf[5] = 1; // CD-ROM
> +    return 8;
> +}
> +
>  static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
>                             int page_control)
>  {
> @@ -947,12 +984,25 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
>          outbuf[7] = 0;
>          buflen = 8;
>          break;
> +    case MECHANISM_STATUS:
> +        buflen = scsi_emulate_mechanism_status(s, outbuf);
> +        if (buflen < 0)
> +            goto illegal_request;

Braces are missing here and in the other commands.

Kevin

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

* Re: [Qemu-devel] [PATCH 07/35] scsi-disk: add stubs for more MMC commands
  2011-10-17 14:27   ` Kevin Wolf
@ 2011-10-17 14:28     ` Paolo Bonzini
  2011-10-17 14:44       ` Paolo Bonzini
  0 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-17 14:28 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

On 10/17/2011 04:27 PM, Kevin Wolf wrote:
> Braces are missing here and in the other commands.

Yes, but that's consistent with the rest of scsi-disk.  I'll try to add 
them and see how bad the conflicts are.

Paolo

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

* Re: [Qemu-devel] [PATCH 07/35] scsi-disk: add stubs for more MMC commands
  2011-10-17 14:28     ` Paolo Bonzini
@ 2011-10-17 14:44       ` Paolo Bonzini
  0 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-17 14:44 UTC (permalink / raw)
  Cc: Kevin Wolf, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 388 bytes --]

On 10/17/2011 04:28 PM, Paolo Bonzini wrote:
> On 10/17/2011 04:27 PM, Kevin Wolf wrote:
>> Braces are missing here and in the other commands.
>
> Yes, but that's consistent with the rest of scsi-disk.  I'll try to add
> them and see how bad the conflicts are.

Ok, half a dozen patches have to be rebased, but nothing monumental. 
I'll include the attached patch before this one.

Paolo

[-- Attachment #2: 0001-scsi-disk-fix-coding-style-issues-braces.patch --]
[-- Type: text/x-patch, Size: 7956 bytes --]

>From e351ff2598c822d7fff79f4bbf394b35b8fa1841 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Mon, 17 Oct 2011 16:39:27 +0200
Subject: [PATCH] scsi-disk: fix coding style issues (braces)

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |   71 ++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 46 insertions(+), 25 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 880cb22..3a08848 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -350,9 +350,9 @@ static void scsi_dma_restart_cb(void *opaque, int running, RunState state)
 {
     SCSIDiskState *s = opaque;
 
-    if (!running)
+    if (!running) {
         return;
-
+    }
     if (!s->bh) {
         s->bh = qemu_bh_new(scsi_dma_restart_bh, s);
         qemu_bh_schedule(s->bh);
@@ -403,8 +403,9 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
                     "buffer size %zd\n", req->cmd.xfer);
             pages = buflen++;
             outbuf[buflen++] = 0x00; // list of supported pages (this page)
-            if (s->serial)
+            if (s->serial) {
                 outbuf[buflen++] = 0x80; // unit serial number
+            }
             outbuf[buflen++] = 0x83; // device identification
             if (s->qdev.type == TYPE_DISK) {
                 outbuf[buflen++] = 0xb0; // block limits
@@ -423,10 +424,12 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
             }
 
             l = strlen(s->serial);
-            if (l > req->cmd.xfer)
+            if (l > req->cmd.xfer) {
                 l = req->cmd.xfer;
-            if (l > 20)
+            }
+            if (l > 20) {
                 l = 20;
+            }
 
             DPRINTF("Inquiry EVPD[Serial number] "
                     "buffer size %zd\n", req->cmd.xfer);
@@ -441,8 +444,9 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
             int max_len = 255 - 8;
             int id_len = strlen(bdrv_get_device_name(s->bs));
 
-            if (id_len > max_len)
+            if (id_len > max_len) {
                 id_len = max_len;
+            }
             DPRINTF("Inquiry EVPD[Device identification] "
                     "buffer size %zd\n", req->cmd.xfer);
 
@@ -525,9 +529,9 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
     }
 
     buflen = req->cmd.xfer;
-    if (buflen > SCSI_MAX_INQUIRY_LEN)
+    if (buflen > SCSI_MAX_INQUIRY_LEN) {
         buflen = SCSI_MAX_INQUIRY_LEN;
-
+    }
     memset(outbuf, 0, buflen);
 
     outbuf[0] = s->qdev.type & 0x1f;
@@ -749,8 +753,9 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
             outbuf[7] = 8; /* Block descriptor length  */
         }
         nb_sectors /= s->cluster_size;
-        if (nb_sectors > 0xffffff)
+        if (nb_sectors > 0xffffff) {
             nb_sectors = 0;
+        }
         p[0] = 0; /* media density code */
         p[1] = (nb_sectors >> 16) & 0xff;
         p[2] = (nb_sectors >> 8) & 0xff;
@@ -791,8 +796,9 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
         outbuf[0] = ((buflen - 2) >> 8) & 0xff;
         outbuf[1] = (buflen - 2) & 0xff;
     }
-    if (buflen > r->req.cmd.xfer)
+    if (buflen > r->req.cmd.xfer) {
         buflen = r->req.cmd.xfer;
+    }
     return buflen;
 }
 
@@ -826,8 +832,9 @@ static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
     default:
         return -1;
     }
-    if (toclen > req->cmd.xfer)
+    if (toclen > req->cmd.xfer) {
         toclen = req->cmd.xfer;
+    }
     return toclen;
 }
 
@@ -879,40 +886,48 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
     outbuf = r->iov.iov_base;
     switch (req->cmd.buf[0]) {
     case TEST_UNIT_READY:
-        if (s->tray_open || !bdrv_is_inserted(s->bs))
+        if (s->tray_open || !bdrv_is_inserted(s->bs)) {
             goto not_ready;
+        }
         break;
     case INQUIRY:
         buflen = scsi_disk_emulate_inquiry(req, outbuf);
-        if (buflen < 0)
+        if (buflen < 0) {
             goto illegal_request;
+        }
         break;
     case MODE_SENSE:
     case MODE_SENSE_10:
         buflen = scsi_disk_emulate_mode_sense(r, outbuf);
-        if (buflen < 0)
+        if (buflen < 0) {
             goto illegal_request;
+        }
         break;
     case READ_TOC:
         buflen = scsi_disk_emulate_read_toc(req, outbuf);
-        if (buflen < 0)
+        if (buflen < 0) {
             goto illegal_request;
+        }
         break;
     case RESERVE:
-        if (req->cmd.buf[1] & 1)
+        if (req->cmd.buf[1] & 1) {
             goto illegal_request;
+        }
         break;
     case RESERVE_10:
-        if (req->cmd.buf[1] & 3)
+        if (req->cmd.buf[1] & 3) {
             goto illegal_request;
+        }
         break;
     case RELEASE:
-        if (req->cmd.buf[1] & 1)
+        if (req->cmd.buf[1] & 1) {
             goto illegal_request;
+        }
         break;
     case RELEASE_10:
-        if (req->cmd.buf[1] & 3)
+        if (req->cmd.buf[1] & 3) {
             goto illegal_request;
+        }
         break;
     case START_STOP:
         if (scsi_disk_emulate_start_stop(r) < 0) {
@@ -927,16 +942,18 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
         /* The normal LEN field for this command is zero.  */
         memset(outbuf, 0, 8);
         bdrv_get_geometry(s->bs, &nb_sectors);
-        if (!nb_sectors)
+        if (!nb_sectors) {
             goto not_ready;
+        }
         nb_sectors /= s->cluster_size;
         /* Returned value is the address of the last sector.  */
         nb_sectors--;
         /* Remember the new size for read/write sanity checking. */
         s->max_lba = nb_sectors;
         /* Clip to 2TB, instead of returning capacity modulo 2TB. */
-        if (nb_sectors > UINT32_MAX)
+        if (nb_sectors > UINT32_MAX) {
             nb_sectors = UINT32_MAX;
+        }
         outbuf[0] = (nb_sectors >> 24) & 0xff;
         outbuf[1] = (nb_sectors >> 16) & 0xff;
         outbuf[2] = (nb_sectors >> 8) & 0xff;
@@ -960,8 +977,9 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
             DPRINTF("SAI READ CAPACITY(16)\n");
             memset(outbuf, 0, req->cmd.xfer);
             bdrv_get_geometry(s->bs, &nb_sectors);
-            if (!nb_sectors)
+            if (!nb_sectors) {
                 goto not_ready;
+            }
             nb_sectors /= s->cluster_size;
             /* Returned value is the address of the last sector.  */
             nb_sectors--;
@@ -1078,8 +1096,9 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
     case READ_16:
         len = r->req.cmd.xfer / s->qdev.blocksize;
         DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len);
-        if (r->req.cmd.lba > s->max_lba)
+        if (r->req.cmd.lba > s->max_lba) {
             goto illegal_lba;
+        }
         r->sector = r->req.cmd.lba * s->cluster_size;
         r->sector_count = len * s->cluster_size;
         break;
@@ -1094,8 +1113,9 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
         DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",
                 (command & 0xe) == 0xe ? "And Verify " : "",
                 r->req.cmd.lba, len);
-        if (r->req.cmd.lba > s->max_lba)
+        if (r->req.cmd.lba > s->max_lba) {
             goto illegal_lba;
+        }
         r->sector = r->req.cmd.lba * s->cluster_size;
         r->sector_count = len * s->cluster_size;
         break;
@@ -1168,8 +1188,9 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
     if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
         return -len;
     } else {
-        if (!r->sector_count)
+        if (!r->sector_count) {
             r->sector_count = -1;
+        }
         return len;
     }
 }
-- 
1.7.6


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

* Re: [Qemu-devel] [PATCH 09/35] atapi/scsi-disk: make mode page values coherent between the two
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 09/35] atapi/scsi-disk: make mode page values coherent between the two Paolo Bonzini
@ 2011-10-17 15:05   ` Kevin Wolf
  2011-10-17 15:06     ` Paolo Bonzini
  0 siblings, 1 reply; 68+ messages in thread
From: Kevin Wolf @ 2011-10-17 15:05 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Am 13.10.2011 13:03, schrieb Paolo Bonzini:
> This patch adds to scsi-disk the missing mode page 0x01 for both disk
> and CD-ROM drives, and mode page 0x0e for CD drives only.
> 
> A few offsets were wrong in atapi.c.  Also change the 2Ah mode page to
> expose DVD media read capabilities in the IDE cdrom.  This lets you run
> dvd+rw-mediainfo on the virtual DVD drives.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/ide/atapi.c |   12 ++++++------
>  hw/scsi-disk.c |   33 ++++++++++++++++++++++++---------
>  2 files changed, 30 insertions(+), 15 deletions(-)
> 
> diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
> index 10f161f..c6eb8f0 100644
> --- a/hw/ide/atapi.c
> +++ b/hw/ide/atapi.c
> @@ -751,7 +751,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
>  
>              buf[8] = 0x2a;
>              buf[9] = 0x12;
> -            buf[10] = 0x00;
> +            buf[10] = 0x3b; /* read CDR/CDRW/DVDROM/DVDR/DVDRAM */
>              buf[11] = 0x00;
>  
>              /* Claim PLAY_AUDIO capability (0x01) since some Linux
> @@ -760,14 +760,14 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
>              buf[13] = 3 << 5;
>              buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
>              if (s->tray_locked) {
> -                buf[6] |= 1 << 1;
> +                buf[14] |= 1 << 1;
>              }
> -            buf[15] = 0x00;
> -            cpu_to_ube16(&buf[16], 706);
> +            buf[15] = 0x00; /* No volume & mute control, no changer */
> +            cpu_to_ube16(&buf[16], 704); /* 4x read speed */
>              buf[18] = 0;
>              buf[19] = 2;
> -            cpu_to_ube16(&buf[20], 512);
> -            cpu_to_ube16(&buf[22], 706);
> +            cpu_to_ube16(&buf[20], 512); /* 512k buffer */
> +            cpu_to_ube16(&buf[22], 704); /* 4x read speed current */
>              buf[24] = 0;
>              buf[25] = 0;
>              buf[26] = 0;
> diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
> index a4aadf2..837747f 100644
> --- a/hw/scsi-disk.c
> +++ b/hw/scsi-disk.c
> @@ -607,6 +607,8 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
>          [MODE_PAGE_HD_GEOMETRY]            = (1 << TYPE_DISK),
>          [MODE_PAGE_FLEXIBLE_DISK_GEOMETRY] = (1 << TYPE_DISK),
>          [MODE_PAGE_CACHING]                = (1 << TYPE_DISK) | (1 << TYPE_ROM),
> +        [MODE_PAGE_R_W_ERROR]              = (1 << TYPE_DISK) | (1 << TYPE_ROM),
> +        [MODE_PAGE_AUDIO_CTL]              = (1 << TYPE_ROM),
>          [MODE_PAGE_CAPABILITIES]           = (1 << TYPE_ROM),
>      };
>  
> @@ -707,13 +709,26 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
>          }
>          break;
>  
> +    case MODE_PAGE_R_W_ERROR:
> +        p[1] = 10;
> +        p[2] = 0x80; /* Automatic Write Reallocation Enabled */
> +        if (s->qdev.type == TYPE_ROM) {
> +            p[3] = 0x20; /* Read Retry Count */
> +        }
> +        break;
> +
> +    case MODE_PAGE_AUDIO_CTL:
> +        p[1] = 14;
> +        break;
> +
>      case MODE_PAGE_CAPABILITIES:
>          p[1] = 0x14;
>          if (page_control == 1) { /* Changeable Values */
>              break;
>          }
> -        p[2] = 3; // CD-R & CD-RW read
> -        p[3] = 0; // Writing not supported
> +
> +        p[2] = 0x3b; /* CD-R & CD-RW read */
> +        p[3] = 0; /* Writing not supported */
>          p[4] = 0x7f; /* Audio, composite, digital out,
>                          mode 2 form 1&2, multi session */
>          p[5] = 0xff; /* CD DA, DA accurate, RW supported,
> @@ -723,17 +738,17 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
>          /* Locking supported, jumper present, eject, tray */
>          p[7] = 0; /* no volume & mute control, no
>                       changer */
> -        p[8] = (50 * 176) >> 8; // 50x read speed
> +        p[8] = (50 * 176) >> 8; /* 50x read speed */
>          p[9] = (50 * 176) & 0xff;
> -        p[10] = 0 >> 8; // No volume
> -        p[11] = 0 & 0xff;
> -        p[12] = 2048 >> 8; // 2M buffer
> +        p[10] = 0 >> 8; /* Volume */
> +        p[11] = 2 & 0xff;

If I understand correctly what the internet says (I don't have a copy of
MMC-3 and MMC-5 doesn't describe it any more), this is still part of the
volume. I'm not sure why we should provide exactly two different volume
levels, but if you think this makes sense, please change p[10] to be 2 >> 8.

> +        p[12] = 2048 >> 8; /* 2M buffer */
>          p[13] = 2048 & 0xff;
> -        p[14] = (16 * 176) >> 8; // 16x read speed current
> +        p[14] = (16 * 176) >> 8; /* 16x read speed current */
>          p[15] = (16 * 176) & 0xff;
> -        p[18] = (16 * 176) >> 8; // 16x write speed
> +        p[18] = (16 * 176) >> 8; /* 16x write speed */
>          p[19] = (16 * 176) & 0xff;
> -        p[20] = (16 * 176) >> 8; // 16x write speed current
> +        p[20] = (16 * 176) >> 8; /* 16x write speed current */
>          p[21] = (16 * 176) & 0xff;
>          break;

Kevin

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

* Re: [Qemu-devel] [PATCH 09/35] atapi/scsi-disk: make mode page values coherent between the two
  2011-10-17 15:05   ` Kevin Wolf
@ 2011-10-17 15:06     ` Paolo Bonzini
  0 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-17 15:06 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

On 10/17/2011 05:05 PM, Kevin Wolf wrote:
> If I understand correctly what the internet says (I don't have a copy of
> MMC-3 and MMC-5 doesn't describe it any more), this is still part of the
> volume. I'm not sure why we should provide exactly two different volume
> levels, but if you think this makes sense, please change p[10] to be 2>>  8.

Because "If the Logical Unit only supports audio on and audio off, the 
Number of Volume Levels field shall be set to 2", so they say.

Paolo

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

* Re: [Qemu-devel] [PATCH 10/35] scsi-disk: support DVD profile in GET CONFIGURATION
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 10/35] scsi-disk: support DVD profile in GET CONFIGURATION Paolo Bonzini
@ 2011-10-17 15:20   ` Kevin Wolf
  2011-10-17 15:28     ` Paolo Bonzini
  0 siblings, 1 reply; 68+ messages in thread
From: Kevin Wolf @ 2011-10-17 15:20 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Am 13.10.2011 13:03, schrieb Paolo Bonzini:
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/scsi-disk.c |   50 ++++++++++++++++++++++++++++++++++++++++++--------
>  1 files changed, 42 insertions(+), 8 deletions(-)
> 
> diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
> index 837747f..1786c37 100644
> --- a/hw/scsi-disk.c
> +++ b/hw/scsi-disk.c
> @@ -563,6 +563,19 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
>      return buflen;
>  }
>  
> +static inline bool media_is_dvd(SCSIDiskState *s)
> +{
> +    uint64_t nb_sectors;
> +    if (s->qdev.type != TYPE_ROM) {
> +        return false;
> +    }
> +    if (!bdrv_is_inserted(s->bs)) {
> +        return false;
> +    }
> +    bdrv_get_geometry(s->bs, &nb_sectors);
> +    return nb_sectors > CD_MAX_SECTORS;
> +}
> +
>  static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
>                                     uint8_t *outbuf)
>  {
> @@ -577,17 +590,38 @@ static int scsi_get_event_status_notification(SCSIDiskState *s,
>      return -1;
>  }
>  
> -static int scsi_get_configuration(SCSIDiskState *s, SCSIDiskReq *r,
> -                                  uint8_t *outbuf)
> +static int scsi_get_configuration(SCSIDiskState *s, uint8_t *outbuf)
>  {
> +    int current;
> +
>      if (s->qdev.type != TYPE_ROM) {
>          return -1;
>      }
> -    memset(outbuf, 0, 8);
> -    /* ??? This should probably return much more information.  For now
> -       just return the basic header indicating the CD-ROM profile.  */
> -    outbuf[7] = 8; // CD-ROM
> -    return 8;
> +    current = media_is_dvd(s) ? MMC_PROFILE_DVD_ROM : MMC_PROFILE_CD_ROM;
> +    memset(outbuf, 0, 40);

Is the memset required at all? I seem to remember that the output buffer
was zeroed in generic code.

> +    stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */
> +    /* outbuf[4] - outbuf[19]: Feature 0 - Profile list */

Isn't it outbuf[8] - outbuf[19]?

> +    stw_be_p(&outbuf[6], current);
> +    outbuf[10] = 0x03; /* persistent, current */
> +    outbuf[11] = 8; /* two profiles */
> +    stw_be_p(&outbuf[12], MMC_PROFILE_DVD_ROM);
> +    outbuf[14] = (current == MMC_PROFILE_DVD_ROM);
> +    stw_be_p(&outbuf[16], MMC_PROFILE_CD_ROM);
> +    outbuf[18] = (current == MMC_PROFILE_CD_ROM);
> +    /* outbuf[20] - outbuf[31]: Feature 1 - Core feature */
> +    stw_be_p(&outbuf[20], 1);
> +    outbuf[22] = 0x08 | 0x03; /* version 2, persistent, current */
> +    outbuf[23] = 8;
> +    stl_be_p(&outbuf[24], 1); /* SCSI */
> +    outbuf[28] = 1; /* DBE = 1, mandatory */
> +    /* outbuf[32] - outbuf[39]: Feature 3 - Removable media feature */
> +    stw_be_p(&outbuf[32], 3);
> +    outbuf[34] = 0x08 | 0x03; /* version 2, persistent, current */

MMC-5 doesn't know version 2, so I can't check this.

> +    outbuf[35] = 4;
> +    outbuf[36] = 0x39; /* tray, load=1, eject=1, unlocked at powerup, lock=1 */
> +    /* TODO: Random readable, CD read, DVD read, drive serial number,
> +       power management */
> +    return 40;
>  }

And some blank lines wouldn't hurt. :-)

>  
>  static int scsi_emulate_mechanism_status(SCSIDiskState *s, uint8_t *outbuf)
> @@ -1006,7 +1040,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
>              goto illegal_request;
>          break;
>      case GET_CONFIGURATION:
> -        buflen = scsi_get_configuration(s, r, outbuf);
> +        buflen = scsi_get_configuration(s, outbuf);
>          if (buflen < 0)
>              goto illegal_request;
>          break;

Kevin

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

* Re: [Qemu-devel] [PATCH 10/35] scsi-disk: support DVD profile in GET CONFIGURATION
  2011-10-17 15:20   ` Kevin Wolf
@ 2011-10-17 15:28     ` Paolo Bonzini
  0 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-17 15:28 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

On 10/17/2011 05:20 PM, Kevin Wolf wrote:
>> >  +    current = media_is_dvd(s) ? MMC_PROFILE_DVD_ROM : MMC_PROFILE_CD_ROM;
>> >  +    memset(outbuf, 0, 40);
> Is the memset required at all? I seem to remember that the output buffer
> was zeroed in generic code.

No, it isn't.

>> >  +    stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */
>> >  +    /* outbuf[4] - outbuf[19]: Feature 0 - Profile list */
>
> Isn't it outbuf[8] - outbuf[19]?

Right.

Paolo

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

* [Qemu-devel] [PATCH v2 21/35] scsi-disk: bump SCSIRequest reference count until aio completion runs
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 21/35] scsi-disk: bump SCSIRequest reference count until aio completion runs Paolo Bonzini
@ 2011-10-17 15:37   ` Paolo Bonzini
  2011-10-19 13:13     ` Paolo Bonzini
  0 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-17 15:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

In some cases a request may be canceled before the completion
callback runs.  Keep a reference to the request between starting
an AIO operation, and let scsi_*_complete remove it.

Since scsi_handle_rw_error returns whether something else has to
be done for the request by the caller, it makes sense to transfer
ownership of the ref to scsi_handle_rw_error when it returns 1;
scsi_dma_restart_bh will then free the reference after restarting
the operation.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
        v1->v2: Add "return" after calling scsi_write_complete with
        ENOMEDIUM.  Bump refcount before testing data direction.

 hw/scsi-disk.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index e28c39d..702e6ca 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -139,6 +139,7 @@ static void scsi_read_complete(void * opaque, int ret)
 
     if (ret) {
         if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_READ)) {
+            /* Leave in ref for scsi_dma_restart_bh.  */
             return;
         }
     }
@@ -149,6 +150,7 @@ static void scsi_read_complete(void * opaque, int ret)
     r->sector += n;
     r->sector_count -= n;
     scsi_req_data(&r->req, r->qiov.size);
+    scsi_req_unref(&r->req);
 }
 
 static void scsi_flush_complete(void * opaque, int ret)
@@ -163,11 +165,13 @@ static void scsi_flush_complete(void * opaque, int ret)
 
     if (ret < 0) {
         if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) {
+            /* Leave in ref for scsi_dma_restart_bh.  */
             return;
         }
     }
 
     scsi_req_complete(&r->req, GOOD);
+    scsi_req_unref(&r->req);
 }
 
 /* Read more data from scsi device into buffer.  */
@@ -193,6 +197,8 @@ static void scsi_read_data(SCSIRequest *req)
     /* No data transfer may already be in progress */
     assert(r->req.aiocb == NULL);
 
+    /* Save a ref for scsi_read_complete, in case r is canceled.  */
+    scsi_req_ref(&r->req);
     if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
         DPRINTF("Data transfer direction invalid\n");
         scsi_read_complete(r, -EINVAL);
@@ -201,7 +207,9 @@ static void scsi_read_data(SCSIRequest *req)
 
     if (s->tray_open) {
         scsi_read_complete(r, -ENOMEDIUM);
+        return;
     }
+
     n = scsi_init_iovec(r);
     bdrv_acct_start(s->bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
     r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n,
@@ -279,6 +287,7 @@ static void scsi_write_complete(void * opaque, int ret)
         DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, r->qiov.size);
         scsi_req_data(&r->req, r->qiov.size);
     }
+    scsi_req_unref(&r->req);
 }
 
 static void scsi_write_data(SCSIRequest *req)
@@ -290,6 +299,8 @@ static void scsi_write_data(SCSIRequest *req)
     /* No data transfer may already be in progress */
     assert(r->req.aiocb == NULL);
 
+    /* Save a ref for scsi_write_complete, in case r is canceled.  */
+    scsi_req_ref(&r->req);
     if (r->req.cmd.mode != SCSI_XFER_TO_DEV) {
         DPRINTF("Data transfer direction invalid\n");
         scsi_write_complete(r, -EINVAL);
@@ -300,6 +311,7 @@ static void scsi_write_data(SCSIRequest *req)
     if (n) {
         if (s->tray_open) {
             scsi_write_complete(r, -ENOMEDIUM);
+            return;
         }
         bdrv_acct_start(s->bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
         r->req.aiocb = bdrv_aio_writev(s->bs, r->sector, &r->qiov, n,
@@ -344,6 +356,8 @@ static void scsi_dma_restart_bh(void *opaque)
                     scsi_req_complete(&r->req, GOOD);
                 }
             }
+            /* This reference was left in by scsi_handle_rw_error.  */
+            scsi_req_unref(&r->req);
         }
     }
 }
@@ -1345,6 +1359,8 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
         r->iov.iov_len = rc;
         break;
     case SYNCHRONIZE_CACHE:
+        /* Save a ref for scsi_flush_complete, in case r is canceled.  */
+        scsi_req_ref(&r->req);
         bdrv_acct_start(s->bs, &r->acct, 0, BDRV_ACCT_FLUSH);
         r->req.aiocb = bdrv_aio_flush(s->bs, scsi_flush_complete, r);
         if (r->req.aiocb == NULL) {
-- 
1.7.6

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

* Re: [Qemu-devel] [PATCH 20/35] scsi-disk: do not complete requests twice
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 20/35] scsi-disk: do not complete requests twice Paolo Bonzini
@ 2011-10-19 13:13   ` Paolo Bonzini
  0 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-19 13:13 UTC (permalink / raw)
  To: qemu-devel

On 10/13/2011 01:03 PM, Paolo Bonzini wrote:
> When scsi_handle_rw_error reports a CHECK CONDITION code, the
> owner should not call scsi_req_complete.
>
> Signed-off-by: Paolo Bonzini<pbonzini@redhat.com>
> ---
>   hw/scsi-disk.c |    3 ++-
>   1 files changed, 2 insertions(+), 1 deletions(-)
>
> diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
> index b041fd5..d4f773f 100644
> --- a/hw/scsi-disk.c
> +++ b/hw/scsi-disk.c
> @@ -231,6 +231,7 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
>           bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
>           vm_stop(RUN_STATE_IO_ERROR);
>           bdrv_iostatus_set_err(s->bs, error);
> +        return 1;
>       } else {
>           switch (error) {
>           case ENOMEDIUM:
> @@ -247,8 +248,8 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
>               break;
>           }
>           bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read);
> +        return 0;
>       }
> -    return 1;
>   }
>
>   static void scsi_write_complete(void * opaque, int ret)

Kevin mentioned on IRC that this patch is bogus, and I agreed.

Paolo

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

* Re: [Qemu-devel] [PATCH v2 21/35] scsi-disk: bump SCSIRequest reference count until aio completion runs
  2011-10-17 15:37   ` [Qemu-devel] [PATCH v2 " Paolo Bonzini
@ 2011-10-19 13:13     ` Paolo Bonzini
  0 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-19 13:13 UTC (permalink / raw)
  Cc: kwolf, qemu-devel

On 10/17/2011 05:37 PM, Paolo Bonzini wrote:
> In some cases a request may be canceled before the completion
> callback runs.  Keep a reference to the request between starting
> an AIO operation, and let scsi_*_complete remove it.
>
> Since scsi_handle_rw_error returns whether something else has to
> be done for the request by the caller, it makes sense to transfer
> ownership of the ref to scsi_handle_rw_error when it returns 1;
> scsi_dma_restart_bh will then free the reference after restarting
> the operation.
>
> Signed-off-by: Paolo Bonzini<pbonzini@redhat.com>
> ---
>          v1->v2: Add "return" after calling scsi_write_complete with
>          ENOMEDIUM.  Bump refcount before testing data direction.
>
>   hw/scsi-disk.c |   16 ++++++++++++++++
>   1 files changed, 16 insertions(+), 0 deletions(-)
>
> diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
> index e28c39d..702e6ca 100644
> --- a/hw/scsi-disk.c
> +++ b/hw/scsi-disk.c
> @@ -139,6 +139,7 @@ static void scsi_read_complete(void * opaque, int ret)
>
>       if (ret) {
>           if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_READ)) {
> +            /* Leave in ref for scsi_dma_restart_bh.  */
>               return;
>           }
>       }
> @@ -149,6 +150,7 @@ static void scsi_read_complete(void * opaque, int ret)
>       r->sector += n;
>       r->sector_count -= n;
>       scsi_req_data(&r->req, r->qiov.size);
> +    scsi_req_unref(&r->req);
>   }
>
>   static void scsi_flush_complete(void * opaque, int ret)
> @@ -163,11 +165,13 @@ static void scsi_flush_complete(void * opaque, int ret)
>
>       if (ret<  0) {
>           if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) {
> +            /* Leave in ref for scsi_dma_restart_bh.  */
>               return;
>           }
>       }
>
>       scsi_req_complete(&r->req, GOOD);
> +    scsi_req_unref(&r->req);
>   }
>
>   /* Read more data from scsi device into buffer.  */
> @@ -193,6 +197,8 @@ static void scsi_read_data(SCSIRequest *req)
>       /* No data transfer may already be in progress */
>       assert(r->req.aiocb == NULL);
>
> +    /* Save a ref for scsi_read_complete, in case r is canceled.  */
> +    scsi_req_ref(&r->req);
>       if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
>           DPRINTF("Data transfer direction invalid\n");
>           scsi_read_complete(r, -EINVAL);
> @@ -201,7 +207,9 @@ static void scsi_read_data(SCSIRequest *req)
>
>       if (s->tray_open) {
>           scsi_read_complete(r, -ENOMEDIUM);
> +        return;
>       }
> +
>       n = scsi_init_iovec(r);
>       bdrv_acct_start(s->bs,&r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
>       r->req.aiocb = bdrv_aio_readv(s->bs, r->sector,&r->qiov, n,
> @@ -279,6 +287,7 @@ static void scsi_write_complete(void * opaque, int ret)
>           DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, r->qiov.size);
>           scsi_req_data(&r->req, r->qiov.size);
>       }
> +    scsi_req_unref(&r->req);
>   }
>
>   static void scsi_write_data(SCSIRequest *req)
> @@ -290,6 +299,8 @@ static void scsi_write_data(SCSIRequest *req)
>       /* No data transfer may already be in progress */
>       assert(r->req.aiocb == NULL);
>
> +    /* Save a ref for scsi_write_complete, in case r is canceled.  */
> +    scsi_req_ref(&r->req);
>       if (r->req.cmd.mode != SCSI_XFER_TO_DEV) {
>           DPRINTF("Data transfer direction invalid\n");
>           scsi_write_complete(r, -EINVAL);
> @@ -300,6 +311,7 @@ static void scsi_write_data(SCSIRequest *req)
>       if (n) {
>           if (s->tray_open) {
>               scsi_write_complete(r, -ENOMEDIUM);
> +            return;
>           }
>           bdrv_acct_start(s->bs,&r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
>           r->req.aiocb = bdrv_aio_writev(s->bs, r->sector,&r->qiov, n,
> @@ -344,6 +356,8 @@ static void scsi_dma_restart_bh(void *opaque)
>                       scsi_req_complete(&r->req, GOOD);
>                   }
>               }
> +            /* This reference was left in by scsi_handle_rw_error.  */
> +            scsi_req_unref(&r->req);
>           }
>       }
>   }
> @@ -1345,6 +1359,8 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
>           r->iov.iov_len = rc;
>           break;
>       case SYNCHRONIZE_CACHE:
> +        /* Save a ref for scsi_flush_complete, in case r is canceled.  */
> +        scsi_req_ref(&r->req);
>           bdrv_acct_start(s->bs,&r->acct, 0, BDRV_ACCT_FLUSH);
>           r->req.aiocb = bdrv_aio_flush(s->bs, scsi_flush_complete, r);
>           if (r->req.aiocb == NULL) {

This needs to be redone after dropping 20/35.

Paolo

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

* Re: [Qemu-devel] [PATCH 11/35] scsi-disk: support READ DVD STRUCTURE
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 11/35] scsi-disk: support READ DVD STRUCTURE Paolo Bonzini
@ 2011-10-21 11:42   ` Kevin Wolf
  2011-10-21 13:11     ` Paolo Bonzini
  2011-10-21 13:12     ` Paolo Bonzini
  0 siblings, 2 replies; 68+ messages in thread
From: Kevin Wolf @ 2011-10-21 11:42 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Am 13.10.2011 13:03, schrieb Paolo Bonzini:
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/scsi-disk.c |  101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 100 insertions(+), 1 deletions(-)
> 
> diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
> index 1786c37..14db6a0 100644
> --- a/hw/scsi-disk.c
> +++ b/hw/scsi-disk.c
> @@ -576,10 +576,109 @@ static inline bool media_is_dvd(SCSIDiskState *s)
>      return nb_sectors > CD_MAX_SECTORS;
>  }
>  
> +static inline bool media_is_cd(SCSIDiskState *s)
> +{
> +    uint64_t nb_sectors;
> +    if (s->qdev.type != TYPE_ROM) {
> +        return false;
> +    }
> +    if (!bdrv_is_inserted(s->bs)) {
> +        return false;
> +    }
> +    bdrv_get_geometry(s->bs, &nb_sectors);
> +    return nb_sectors <= CD_MAX_SECTORS;
> +}
> +
>  static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
>                                     uint8_t *outbuf)
>  {
> -    scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
> +    static const int rds_caps_size[5] = {
> +        [0] = 2048 + 4,
> +        [1] = 4 + 4,
> +        [3] = 188 + 4,
> +        [4] = 2048 + 4,
> +    };
> +
> +    uint8_t media = r->req.cmd.buf[1];
> +    uint8_t layer = r->req.cmd.buf[6];
> +    uint8_t format = r->req.cmd.buf[7];
> +    int size = -1;
> +
> +    if (s->qdev.type != TYPE_ROM || !bdrv_is_inserted(s->bs)) {
> +        return -1;
> +    }
> +    if (s->tray_open || !bdrv_is_inserted(s->bs)) {
> +        scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
> +        return -1;
> +    }

You are checking twice for bdrv_is_inserted, which one do you really mean?

Also, format = 0xff should work even without a medium.

> +    if (media_is_cd(s)) {
> +        scsi_check_condition(r, SENSE_CODE(INCOMPATIBLE_FORMAT));
> +        return -1;
> +    }
> +    if (media != 0) {
> +        scsi_check_condition(r, SENSE_CODE(INCOMPATIBLE_FORMAT));
> +        return -1;
> +    }
> +
> +    if (format != 0xff) {
> +        if (format >= sizeof(rds_caps_size) / sizeof(rds_caps_size[0])) {

osdep.h has an ARRAY_SIZE() macro.

> +            return -1;
> +        }
> +        size = rds_caps_size[format];
> +        memset(outbuf, 0, size);
> +    }
> +
> +    switch (format) {
> +    case 0x00: {
> +        /* Physical format information */
> +        uint64_t nb_sectors;
> +        if (layer != 0)
> +            goto fail;

Braces

> +        bdrv_get_geometry(s->bs, &nb_sectors);
> +
> +        outbuf[4] = 1;   /* DVD-ROM, part version 1 */
> +        outbuf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
> +        outbuf[6] = 1;   /* one layer, read-only (per MMC-2 spec) */
> +        outbuf[7] = 0;   /* default densities */
> +
> +        stl_be_p(&outbuf[12], (nb_sectors >> 2) - 1); /* end sector */
> +        stl_be_p(&outbuf[16], (nb_sectors >> 2) - 1); /* l0 end sector */
> +        break;
> +    }
> +
> +    case 0x01: /* DVD copyright information, all zeros */
> +        break;
> +
> +    case 0x03: /* BCA information - invalid field for no BCA info */
> +        return -1;
> +
> +    case 0x04: /* DVD disc manufacturing information, all zeros */
> +        break;
> +
> +    case 0xff: { /* List capabilities */
> +        int i;
> +        size = 4;
> +        for (i = 0; i < sizeof(rds_caps_size) / sizeof(rds_caps_size[0]); i++) {

ARRAY_SIZE() again

> +            if (!rds_caps_size[i]) {
> +                continue;
> +            }
> +            outbuf[size] = i;
> +            outbuf[size + 1] = 0x40; /* Not writable, readable */
> +            stw_be_p(&outbuf[size + 2], rds_caps_size[i]);
> +            size += 4;
> +        }
> +        break;
> +     }
> +
> +    default:
> +        return -1;
> +    }
> +
> +    /* Size of buffer, not including 2 byte size field */
> +    stw_be_p(outbuf, size - 2);
> +    return size;
> +
> +fail:
>      return -1;
>  }

There is only one 'goto fail', all other places have a direct return -1.
It would be good to be consistent.

Also, as this is mostly a refactored copy from the ATAPI code, I wonder
what our long-term plan is. At which point will we be able to unify what
we're duplicating right now? Can we share some parts even now?

Kevin

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

* Re: [Qemu-devel] [PATCH 12/35] scsi-disk: report media changed via GET EVENT STATUS NOTIFICATION
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 12/35] scsi-disk: report media changed via GET EVENT STATUS NOTIFICATION Paolo Bonzini
@ 2011-10-21 11:54   ` Kevin Wolf
  2011-10-21 13:08     ` Paolo Bonzini
  0 siblings, 1 reply; 68+ messages in thread
From: Kevin Wolf @ 2011-10-21 11:54 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Am 13.10.2011 13:03, schrieb Paolo Bonzini:
> This adds support for media change notification via the GET EVENT STATUS
> NOTIFICATION command, used by Linux versions 2.6.38 and newer.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Looks good, but the ATAPI version of the code is somewhat nicer to read.

Kevin

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

* Re: [Qemu-devel] [PATCH 13/35] scsi: move tcq/ndev to SCSIBusOps (now SCSIBusInfo)
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 13/35] scsi: move tcq/ndev to SCSIBusOps (now SCSIBusInfo) Paolo Bonzini
@ 2011-10-21 12:01   ` Kevin Wolf
  2011-10-21 12:21     ` Paolo Bonzini
  0 siblings, 1 reply; 68+ messages in thread
From: Kevin Wolf @ 2011-10-21 12:01 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Am 13.10.2011 13:03, schrieb Paolo Bonzini:
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/esp.c         |    7 +++++--
>  hw/lsi53c895a.c  |    9 ++++++---
>  hw/scsi-bus.c    |   27 ++++++++++++---------------
>  hw/scsi-disk.c   |    2 +-
>  hw/scsi.h        |   11 +++++------
>  hw/spapr_vscsi.c |    8 +++++---
>  hw/usb-msd.c     |    7 +++++--
>  7 files changed, 39 insertions(+), 32 deletions(-)
> 
> diff --git a/hw/esp.c b/hw/esp.c
> index 697c2c5..d3fb1c6 100644
> --- a/hw/esp.c
> +++ b/hw/esp.c
> @@ -720,7 +720,10 @@ void esp_init(target_phys_addr_t espaddr, int it_shift,
>      *dma_enable = qdev_get_gpio_in(dev, 1);
>  }
>  
> -static const struct SCSIBusOps esp_scsi_ops = {
> +static const struct SCSIBusInfo esp_scsi_info = {
> +    .tcq = false,
> +    .ndev = ESP_MAX_DEVS,
> +
>      .transfer_data = esp_transfer_data,
>      .complete = esp_command_complete,
>      .cancel = esp_request_cancelled
> @@ -740,7 +743,7 @@ static int esp_init1(SysBusDevice *dev)
>  
>      qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);
>  
> -    scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, &esp_scsi_ops);
> +    scsi_bus_new(&s->bus, &dev->qdev, &esp_scsi_info);
>      return scsi_bus_legacy_handle_cmdline(&s->bus);
>  }
>  
> diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
> index e077ec0..4eeb496 100644
> --- a/hw/lsi53c895a.c
> +++ b/hw/lsi53c895a.c
> @@ -1686,7 +1686,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
>                  DeviceState *dev;
>                  int id;
>  
> -                for (id = 0; id < s->bus.ndev; id++) {
> +                for (id = 0; id < LSI_MAX_DEVS; id++) {
>                      if (s->bus.devs[id]) {
>                          dev = &s->bus.devs[id]->qdev;
>                          dev->info->reset(dev);
> @@ -2091,7 +2091,10 @@ static int lsi_scsi_uninit(PCIDevice *d)
>      return 0;
>  }
>  
> -static const struct SCSIBusOps lsi_scsi_ops = {
> +static const struct SCSIBusInfo lsi_scsi_info = {
> +    .tcq = true,
> +    .ndev = LSI_MAX_DEVS,
> +
>      .transfer_data = lsi_transfer_data,
>      .complete = lsi_command_complete,
>      .cancel = lsi_request_cancelled
> @@ -2118,7 +2121,7 @@ static int lsi_scsi_init(PCIDevice *dev)
>      pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_io);
>      QTAILQ_INIT(&s->queue);
>  
> -    scsi_bus_new(&s->bus, &dev->qdev, 1, LSI_MAX_DEVS, &lsi_scsi_ops);
> +    scsi_bus_new(&s->bus, &dev->qdev, &lsi_scsi_info);
>      if (!dev->qdev.hotplugged) {
>          return scsi_bus_legacy_handle_cmdline(&s->bus);
>      }
> diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
> index 867b1a8..d9d4e18 100644
> --- a/hw/scsi-bus.c
> +++ b/hw/scsi-bus.c
> @@ -24,14 +24,11 @@ static struct BusInfo scsi_bus_info = {
>  static int next_scsi_bus;
>  
>  /* Create a scsi bus, and attach devices to it.  */
> -void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev,
> -                  const SCSIBusOps *ops)
> +void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info)
>  {
>      qbus_create_inplace(&bus->qbus, &scsi_bus_info, host, NULL);
>      bus->busnr = next_scsi_bus++;
> -    bus->tcq = tcq;
> -    bus->ndev = ndev;
> -    bus->ops = ops;
> +    bus->info = info;
>      bus->qbus.allow_hotplug = 1;
>  }
>  
> @@ -43,12 +40,12 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
>      int rc = -1;
>  
>      if (dev->id == -1) {
> -        for (dev->id = 0; dev->id < bus->ndev; dev->id++) {
> +        for (dev->id = 0; dev->id < bus->info->ndev; dev->id++) {
>              if (bus->devs[dev->id] == NULL)
>                  break;
>          }
>      }
> -    if (dev->id >= bus->ndev) {
> +    if (dev->id >= bus->info->ndev) {
>          error_report("bad scsi device id: %d", dev->id);
>          goto err;
>      }
> @@ -120,7 +117,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
>      int res = 0, unit;
>  
>      loc_push_none(&loc);
> -    for (unit = 0; unit < bus->ndev; unit++) {
> +    for (unit = 0; unit < bus->info->ndev; unit++) {
>          dinfo = drive_get(IF_SCSI, bus->busnr, unit);
>          if (dinfo == NULL) {
>              continue;
> @@ -265,7 +262,7 @@ static bool scsi_target_emulate_inquiry(SCSITargetReq *r)
>          r->buf[2] = 5; /* Version */
>          r->buf[3] = 2 | 0x10; /* HiSup, response data format */
>          r->buf[4] = r->len - 5; /* Additional Length = (Len - 1) - 4 */
> -        r->buf[7] = 0x10 | (r->req.bus->tcq ? 0x02 : 0); /* Sync, TCQ.  */
> +        r->buf[7] = 0x10 | (r->req.bus->info->tcq ? 0x02 : 0); /* Sync, TCQ.  */
>          memcpy(&r->buf[8], "QEMU    ", 8);
>          memcpy(&r->buf[16], "QEMU TARGET     ", 16);
>          strncpy((char *) &r->buf[32], QEMU_VERSION, 4);
> @@ -1062,7 +1059,7 @@ void scsi_req_continue(SCSIRequest *req)
>  void scsi_req_data(SCSIRequest *req, int len)
>  {
>      trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
> -    req->bus->ops->transfer_data(req, len);
> +    req->bus->info->transfer_data(req, len);
>  }
>  
>  void scsi_req_print(SCSIRequest *req)
> @@ -1121,7 +1118,7 @@ void scsi_req_complete(SCSIRequest *req, int status)
>  
>      scsi_req_ref(req);
>      scsi_req_dequeue(req);
> -    req->bus->ops->complete(req, req->status);
> +    req->bus->info->complete(req, req->status);
>      scsi_req_unref(req);
>  }
>  
> @@ -1132,8 +1129,8 @@ void scsi_req_cancel(SCSIRequest *req)
>      }
>      scsi_req_ref(req);
>      scsi_req_dequeue(req);
> -    if (req->bus->ops->cancel) {
> -        req->bus->ops->cancel(req);
> +    if (req->bus->info->cancel) {
> +        req->bus->info->cancel(req);
>      }
>      scsi_req_unref(req);
>  }
> @@ -1164,13 +1161,13 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
>      char path[100];
>      int i;
>  
> -    for (i = 0; i < bus->ndev; i++) {
> +    for (i = 0; i < bus->info->ndev; i++) {
>          if (bus->devs[i] == d) {
>              break;
>          }
>      }
>  
> -    assert(i != bus->ndev);
> +    assert(i != bus->info->ndev);
>  
>      snprintf(path, sizeof(path), "%s@%x", qdev_fw_name(dev), i);
>  
> diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
> index ce71df4..97a7335 100644
> --- a/hw/scsi-disk.c
> +++ b/hw/scsi-disk.c
> @@ -560,7 +560,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
>      }
>  
>      /* Sync data transfer and TCQ.  */
> -    outbuf[7] = 0x10 | (req->bus->tcq ? 0x02 : 0);
> +    outbuf[7] = 0x10 | (req->bus->info->tcq ? 0x02 : 0);
>      return buflen;
>  }
>  
> diff --git a/hw/scsi.h b/hw/scsi.h
> index 7004aaa..b76c4ee 100644
> --- a/hw/scsi.h
> +++ b/hw/scsi.h
> @@ -9,7 +9,7 @@
>  #define SCSI_CMD_BUF_SIZE     16
>  
>  typedef struct SCSIBus SCSIBus;
> -typedef struct SCSIBusOps SCSIBusOps;
> +typedef struct SCSIBusInfo SCSIBusInfo;
>  typedef struct SCSICommand SCSICommand;
>  typedef struct SCSIDevice SCSIDevice;
>  typedef struct SCSIDeviceInfo SCSIDeviceInfo;
> @@ -97,7 +97,8 @@ struct SCSIDeviceInfo {
>      SCSIReqOps reqops;
>  };
>  
> -struct SCSIBusOps {
> +struct SCSIBusInfo {
> +    int tcq, ndev;
>      void (*transfer_data)(SCSIRequest *req, uint32_t arg);
>      void (*complete)(SCSIRequest *req, uint32_t arg);
>      void (*cancel)(SCSIRequest *req);
> @@ -108,14 +109,12 @@ struct SCSIBus {
>      int busnr;
>  
>      SCSISense unit_attention;
> -    int tcq, ndev;
> -    const SCSIBusOps *ops;
> +    const SCSIBusInfo *info;
>  
>      SCSIDevice *devs[MAX_SCSI_DEVS];
>  };
>  
> -void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev,
> -                  const SCSIBusOps *ops);
> +void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info);
>  void scsi_qdev_register(SCSIDeviceInfo *info);
>  
>  static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
> diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
> index e8426d7..6c5faf2 100644
> --- a/hw/spapr_vscsi.c
> +++ b/hw/spapr_vscsi.c
> @@ -862,7 +862,10 @@ static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
>      return 0;
>  }
>  
> -static const struct SCSIBusOps vscsi_scsi_ops = {
> +static const struct SCSIBusInfo vscsi_scsi_info = {
> +    .tcq = true,
> +    .ndev = 63, /* logical unit addressing format */

This is a change from VSCSI_REQ_LIMIT = 24. This may be a bugfix or not
- I don't know the hardware - but it's matter for a separate patch.

Kevin

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

* Re: [Qemu-devel] [PATCH 13/35] scsi: move tcq/ndev to SCSIBusOps (now SCSIBusInfo)
  2011-10-21 12:01   ` Kevin Wolf
@ 2011-10-21 12:21     ` Paolo Bonzini
  0 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-21 12:21 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

On 10/21/2011 02:01 PM, Kevin Wolf wrote:
>> >
>> >  -static const struct SCSIBusOps vscsi_scsi_ops = {
>> >  +static const struct SCSIBusInfo vscsi_scsi_info = {
>> >  +    .tcq = true,
>> >  +    .ndev = 63, /* logical unit addressing format */
> This is a change from VSCSI_REQ_LIMIT = 24. This may be a bugfix or not
> - I don't know the hardware - but it's matter for a separate patch.

Ok, will leave 24.

Paolo

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

* Re: [Qemu-devel] [PATCH 15/35] scsi: remove devs array from SCSIBus
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 15/35] scsi: remove devs array from SCSIBus Paolo Bonzini
@ 2011-10-21 12:31   ` Kevin Wolf
  2011-10-21 13:03     ` Paolo Bonzini
  0 siblings, 1 reply; 68+ messages in thread
From: Kevin Wolf @ 2011-10-21 12:31 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Am 13.10.2011 13:03, schrieb Paolo Bonzini:
> Change the devs array into a linked list, and add a scsi_device_find
> function to navigate the children list instead.  This lets the SCSI
> bus use more complex addressing.
> 
> scsi_device_find may return another LUN on the same target if none is
> found that matches exactly.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/esp.c         |    5 +++--
>  hw/lsi53c895a.c  |   22 +++++++---------------
>  hw/qdev.h        |    2 +-
>  hw/scsi-bus.c    |   53 ++++++++++++++++++++++++++++++-----------------------
>  hw/scsi.h        |    3 +--
>  hw/spapr_vscsi.c |   14 ++++++--------
>  6 files changed, 48 insertions(+), 51 deletions(-)
> 
> diff --git a/hw/esp.c b/hw/esp.c
> index d3fb1c6..8e17005 100644
> --- a/hw/esp.c
> +++ b/hw/esp.c
> @@ -217,7 +217,8 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
>          s->async_len = 0;
>      }
>  
> -    if (target >= ESP_MAX_DEVS || !s->bus.devs[target]) {
> +    s->current_dev = scsi_device_find(&s->bus, target, 0);
> +    if (!s->current_dev) {
>          // No such drive
>          s->rregs[ESP_RSTAT] = 0;
>          s->rregs[ESP_RINTR] = INTR_DC;
> @@ -225,7 +226,6 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
>          esp_raise_irq(s);
>          return 0;
>      }
> -    s->current_dev = s->bus.devs[target];
>      return dmalen;
>  }
>  
> @@ -236,6 +236,7 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
>  
>      trace_esp_do_busid_cmd(busid);
>      lun = busid & 7;
> +    s->current_dev = scsi_device_find(&s->bus, s->current_dev->id, lun);

This is new, and I can't see an explanation in the commit log.

Kevin

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

* Re: [Qemu-devel] [PATCH 15/35] scsi: remove devs array from SCSIBus
  2011-10-21 12:31   ` Kevin Wolf
@ 2011-10-21 13:03     ` Paolo Bonzini
  0 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-21 13:03 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

On 10/21/2011 02:31 PM, Kevin Wolf wrote:
>> >  diff --git a/hw/esp.c b/hw/esp.c
>> >  index d3fb1c6..8e17005 100644
>> >  --- a/hw/esp.c
>> >  +++ b/hw/esp.c
>> >  @@ -217,7 +217,8 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
>> >            s->async_len = 0;
>> >        }
>> >
>> >  -    if (target>= ESP_MAX_DEVS || !s->bus.devs[target]) {
>> >  +    s->current_dev = scsi_device_find(&s->bus, target, 0);
>> >  +    if (!s->current_dev) {
>> >            // No such drive
>> >            s->rregs[ESP_RSTAT] = 0;
>> >            s->rregs[ESP_RINTR] = INTR_DC;
>> >  @@ -225,7 +226,6 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
>> >            esp_raise_irq(s);
>> >            return 0;
>> >        }
>> >  -    s->current_dev = s->bus.devs[target];
>> >        return dmalen;
>> >    }
>> >
>> >  @@ -236,6 +236,7 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
>> >
>> >        trace_esp_do_busid_cmd(busid);
>> >        lun = busid&  7;
>> >  +    s->current_dev = scsi_device_find(&s->bus, s->current_dev->id, lun);
> This is new, and I can't see an explanation in the commit log.

It isn't really new; up until now the lun was hard-coded to zero and so 
s->current_dev could be set in get_cmd.  Now we have to delay it until 
do_busid_cmd because we actually have a place to pass the LUN.

That said, s->current_dev is never really used outside do_busid_cmd, so 
I can instead do something like:

-   s->current_req = scsi_req_new(s->current_dev, 0, lun, buf, NULL);
+   SCSIDevice *current_lun;
+
+   current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, lun);
+   s->current_req = scsi_req_new(current_lun, 0, lun, buf, NULL);

That would be the same as the code I have above.

Paolo

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

* Re: [Qemu-devel] [PATCH 12/35] scsi-disk: report media changed via GET EVENT STATUS NOTIFICATION
  2011-10-21 11:54   ` Kevin Wolf
@ 2011-10-21 13:08     ` Paolo Bonzini
  0 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-21 13:08 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

On 10/21/2011 01:54 PM, Kevin Wolf wrote:
>> This adds support for media change notification via the GET EVENT STATUS
>> >  NOTIFICATION command, used by Linux versions 2.6.38 and newer.
>> >
>> >  Signed-off-by: Paolo Bonzini<pbonzini@redhat.com>
> Looks good, but the ATAPI version of the code is somewhat nicer to read.

Yeah, on the other hand even the ATAPI version has a mix of structs and 
buffers (in event_status_media, which also assumes sizeof 
gesn_event_header == 4).

Paolo

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

* Re: [Qemu-devel] [PATCH 11/35] scsi-disk: support READ DVD STRUCTURE
  2011-10-21 11:42   ` Kevin Wolf
@ 2011-10-21 13:11     ` Paolo Bonzini
  2011-10-21 13:12     ` Paolo Bonzini
  1 sibling, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-21 13:11 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

On 10/21/2011 01:42 PM, Kevin Wolf wrote:
>> >  +    if (s->qdev.type != TYPE_ROM || !bdrv_is_inserted(s->bs)) {
>> >  +        return -1;
>> >  +    }
>> >  +    if (s->tray_open || !bdrv_is_inserted(s->bs)) {
>> >  +        scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
>> >  +        return -1;
>> >  +    }
> You are checking twice for bdrv_is_inserted, which one do you really mean?

The first is bogus.

> Also, format = 0xff should work even without a medium.

Will move the tray_open/bdrv_is_inserted/media_is_cd tests within the 
"if (format != 0xff)".

>> >  +    if (media_is_cd(s)) {
>> >  +        scsi_check_condition(r, SENSE_CODE(INCOMPATIBLE_FORMAT));
>> >  +        return -1;
>> >  +    }
>> >  +    if (media != 0) {
>> >  +        scsi_check_condition(r, SENSE_CODE(INCOMPATIBLE_FORMAT));
>> >  +        return -1;
>> >  +    }

media != 0 should return INVALID_FIELD too.

Paolo

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

* Re: [Qemu-devel] [PATCH 11/35] scsi-disk: support READ DVD STRUCTURE
  2011-10-21 11:42   ` Kevin Wolf
  2011-10-21 13:11     ` Paolo Bonzini
@ 2011-10-21 13:12     ` Paolo Bonzini
  2011-10-21 13:32       ` Kevin Wolf
  1 sibling, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-21 13:12 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

On 10/21/2011 01:42 PM, Kevin Wolf wrote:
> There is only one 'goto fail', all other places have a direct return -1.
> It would be good to be consistent.
>
> Also, as this is mostly a refactored copy from the ATAPI code, I wonder
> what our long-term plan is. At which point will we be able to unify what
> we're duplicating right now? Can we share some parts even now?

That's a tricky question.  I think there are three choices:

1) use SCSI as the sole interface exposed by the block layer (with an 
adaptor).  There would be a common implementation of SCSI for 
SCSI-oblivious devices, and other devices (hdev, sg, iscsi) could just 
reason in terms of SCSI.  You could stack the common implementations 
(hard drive and CD-ROM) on top of hdev/iscsi or use passthrough.  This 
however is wrong IMHO because some bits of SCSI code really do deal with 
guest state, for example the tray.

2) let ide-cd create its own SCSI bus and act as an adaptor, similar to 
USB devices.  There would still be duplication for commands that do DMA 
in multiple steps; I think READ CD is the only one.

3) create a separate API just for the purpose of sharing code between 
ATAPI and SCSI (your "can we share some parts even now", basically).


I think I'm leaning towards (3), but I don't think it makes sense to do 
it now unless someone is interested in implementing for example CD 
burning support.  However, I'm leaning towards that also because I 
honestly have no idea how hard (2) would be.

Paolo

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

* Re: [Qemu-devel] [PATCH 11/35] scsi-disk: support READ DVD STRUCTURE
  2011-10-21 13:12     ` Paolo Bonzini
@ 2011-10-21 13:32       ` Kevin Wolf
  2011-10-21 13:36         ` Paolo Bonzini
  0 siblings, 1 reply; 68+ messages in thread
From: Kevin Wolf @ 2011-10-21 13:32 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Am 21.10.2011 15:12, schrieb Paolo Bonzini:
> On 10/21/2011 01:42 PM, Kevin Wolf wrote:
>> There is only one 'goto fail', all other places have a direct return -1.
>> It would be good to be consistent.
>>
>> Also, as this is mostly a refactored copy from the ATAPI code, I wonder
>> what our long-term plan is. At which point will we be able to unify what
>> we're duplicating right now? Can we share some parts even now?
> 
> That's a tricky question.  I think there are three choices:
> 
> 1) use SCSI as the sole interface exposed by the block layer (with an 
> adaptor).  There would be a common implementation of SCSI for 
> SCSI-oblivious devices, and other devices (hdev, sg, iscsi) could just 
> reason in terms of SCSI.  You could stack the common implementations 
> (hard drive and CD-ROM) on top of hdev/iscsi or use passthrough.  This 
> however is wrong IMHO because some bits of SCSI code really do deal with 
> guest state, for example the tray.
> 
> 2) let ide-cd create its own SCSI bus and act as an adaptor, similar to 
> USB devices.  There would still be duplication for commands that do DMA 
> in multiple steps; I think READ CD is the only one.
> 
> 3) create a separate API just for the purpose of sharing code between 
> ATAPI and SCSI (your "can we share some parts even now", basically).
> 
> 
> I think I'm leaning towards (3), but I don't think it makes sense to do 
> it now unless someone is interested in implementing for example CD 
> burning support.  However, I'm leaning towards that also because I 
> honestly have no idea how hard (2) would be.

Which gives me the impression that your feeling is (as well as mine)
that (2) would give us the nicer result and is probably the Right Thing
to do long-term.

Though at the same time I agree that I don't have an idea of how hard
this would be and if it would be worth the effort. And with the current
qdev that doesn't allow device composition it might even get really ugly.

It's a hard question, but ignoring it is probably not a solution.

Kevin

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

* Re: [Qemu-devel] [PATCH 11/35] scsi-disk: support READ DVD STRUCTURE
  2011-10-21 13:32       ` Kevin Wolf
@ 2011-10-21 13:36         ` Paolo Bonzini
  0 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-21 13:36 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

On 10/21/2011 03:32 PM, Kevin Wolf wrote:
> 2) let ide-cd create its own SCSI bus and act as an adaptor, similar to
> >  USB devices.  There would still be duplication for commands that do DMA
> >  in multiple steps; I think READ CD is the only one.
> >
> >  3) create a separate API just for the purpose of sharing code between
> >  ATAPI and SCSI (your "can we share some parts even now", basically).
> >
> >  I think I'm leaning towards (3), but I don't think it makes sense to do
> >  it now unless someone is interested in implementing for example CD
> >  burning support.  However, I'm leaning towards that also because I
> >  honestly have no idea how hard (2) would be.
>
> Which gives me the impression that your feeling is (as well as mine)
> that (2) would give us the nicer result and is probably the Right Thing
> to do long-term.

Long term, yes.  Now, probably not (not until the QOM situation becomes 
clearer, that is).

It would also get you CD recorder passthrough, by composing scsi-generic 
or scsi-block within the IDE drive.

> Though at the same time I agree that I don't have an idea of how hard
> this would be and if it would be worth the effort. And with the current
> qdev that doesn't allow device composition it might even get really ugly.
>
> It's a hard question, but ignoring it is probably not a solution.

I agree.  On the other hand, the ATAPI code is changed rarely.  If it 
had been kept in sync in the past, I would not have touched it at all. 
I have never tried using >4.7 GB DVD images, but perhaps they just work 
and besides burning, they would be the only interesting use case.

Paolo

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

* Re: [Qemu-devel] [PATCH 29/35] scsi-disk: remove cluster_size
  2011-10-13 11:03 ` [Qemu-devel] [PATCH 29/35] scsi-disk: remove cluster_size Paolo Bonzini
@ 2011-10-24 15:10   ` Kevin Wolf
  2011-10-24 15:36     ` Paolo Bonzini
  0 siblings, 1 reply; 68+ messages in thread
From: Kevin Wolf @ 2011-10-24 15:10 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Am 13.10.2011 13:03, schrieb Paolo Bonzini:
> This field is redundant, and its presence makes it more complicated
> to share reqops between the upcoming scsi-block and scsi-generic.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/scsi-disk.c |   45 ++++++++++++++++++++++-----------------------
>  1 files changed, 22 insertions(+), 23 deletions(-)
> 
> diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
> index 5e3ef51..7f2f67f 100644
> --- a/hw/scsi-disk.c
> +++ b/hw/scsi-disk.c
> @@ -65,9 +65,6 @@ typedef struct SCSIDiskReq {
>  struct SCSIDiskState
>  {
>      SCSIDevice qdev;
> -    /* The qemu block layer uses a fixed 512 byte sector size.
> -       This is the number of 512 byte blocks in a single scsi sector.  */
> -    int cluster_size;
>      uint32_t removable;
>      uint64_t max_lba;
>      bool media_changed;
> @@ -862,7 +859,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
>          bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
>          p[4] = heads & 0xff;
>          p[5] = secs & 0xff;
> -        p[6] = s->cluster_size * 2;
> +        p[6] = s->qdev.blocksize >> 8;
>          p[8] = (cylinders >> 8) & 0xff;
>          p[9] = cylinders & 0xff;
>          /* Write precomp start cylinder, disabled */
> @@ -991,7 +988,7 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
>          } else { /* MODE_SENSE_10 */
>              outbuf[7] = 8; /* Block descriptor length  */
>          }
> -        nb_sectors /= s->cluster_size;
> +        nb_sectors /= (s->qdev.blocksize / 512);
>          if (nb_sectors > 0xffffff)
>              nb_sectors = 0;
>          p[0] = 0; /* media density code */
> @@ -1000,7 +997,7 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
>          p[3] = nb_sectors & 0xff;
>          p[4] = 0; /* reserved */
>          p[5] = 0; /* bytes 5-7 are the sector size in bytes */
> -        p[6] = s->cluster_size * 2;
> +        p[6] = s->qdev.blocksize >> 8;
>          p[7] = 0;
>          p += 8;
>      }
> @@ -1050,7 +1047,7 @@ static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
>      start_track = req->cmd.buf[6];
>      bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
>      DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
> -    nb_sectors /= s->cluster_size;
> +    nb_sectors /= s->qdev.blocksize / 512;
>      switch (format) {
>      case 0:
>          toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
> @@ -1176,7 +1173,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
>          if ((req->cmd.buf[8] & 1) == 0 && req->cmd.lba) {
>              goto illegal_request;
>          }
> -        nb_sectors /= s->cluster_size;
> +        nb_sectors /= s->qdev.blocksize / 512;
>          /* Returned value is the address of the last sector.  */
>          nb_sectors--;
>          /* Remember the new size for read/write sanity checking. */
> @@ -1190,7 +1187,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
>          outbuf[3] = nb_sectors & 0xff;
>          outbuf[4] = 0;
>          outbuf[5] = 0;
> -        outbuf[6] = s->cluster_size * 2;
> +        outbuf[6] = s->qdev.blocksize >> 8;
>          outbuf[7] = 0;
>          buflen = 8;
>          break;
> @@ -1226,7 +1223,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
>              if ((req->cmd.buf[14] & 1) == 0 && req->cmd.lba) {
>                  goto illegal_request;
>              }
> -            nb_sectors /= s->cluster_size;
> +            nb_sectors /= s->qdev.blocksize / 512;
>              /* Returned value is the address of the last sector.  */
>              nb_sectors--;
>              /* Remember the new size for read/write sanity checking. */
> @@ -1241,7 +1238,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
>              outbuf[7] = nb_sectors & 0xff;
>              outbuf[8] = 0;
>              outbuf[9] = 0;
> -            outbuf[10] = s->cluster_size * 2;
> +            outbuf[10] = s->qdev.blocksize >> 8;
>              outbuf[11] = 0;
>              outbuf[12] = 0;
>              outbuf[13] = get_physical_block_exp(&s->qdev.conf);
> @@ -1349,8 +1346,8 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
>          DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len);
>          if (r->req.cmd.lba > s->max_lba)
>              goto illegal_lba;
> -        r->sector = r->req.cmd.lba * s->cluster_size;
> -        r->sector_count = len * s->cluster_size;
> +        r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
> +        r->sector_count = len * (s->qdev.blocksize / 512);
>          break;
>      case WRITE_6:
>      case WRITE_10:
> @@ -1365,8 +1362,8 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
>                  r->req.cmd.lba, len);
>          if (r->req.cmd.lba > s->max_lba)
>              goto illegal_lba;
> -        r->sector = r->req.cmd.lba * s->cluster_size;
> -        r->sector_count = len * s->cluster_size;
> +        r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
> +        r->sector_count = len * (s->qdev.blocksize / 512);
>          break;
>      case MODE_SELECT:
>          DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
> @@ -1409,8 +1406,9 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
>              goto fail;
>          }
>  
> -        rc = bdrv_discard(s->qdev.conf.bs, r->req.cmd.lba * s->cluster_size,
> -                          len * s->cluster_size);
> +        rc = bdrv_discard(s->qdev.conf.bs,
> +                          r->req.cmd.lba * (s->qdev.blocksize / 512),
> +                          len * (s->qdev.blocksize / 512));
>          if (rc < 0) {
>              /* XXX: better error code ?*/
>              goto fail;
> @@ -1450,12 +1448,14 @@ static void scsi_disk_reset(DeviceState *dev)
>  
>      scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
>  
> -    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
> -    nb_sectors /= s->cluster_size;
> -    if (nb_sectors) {
> -        nb_sectors--;
> +    if (s->qdev.blocksize) {

When would it be 0? And wouldn't we crash with a zero blocksize anyway?

Kevin

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

* Re: [Qemu-devel] [PATCH 35/35] scsi-disk: add scsi-block for device passthrough
  2011-10-24 15:28   ` Kevin Wolf
@ 2011-10-24 15:28     ` Paolo Bonzini
  2011-10-24 15:38       ` Kevin Wolf
  0 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-24 15:28 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

On 10/24/2011 05:28 PM, Kevin Wolf wrote:
>> scsi-block is a new device that supports device passthrough of Linux
>> >  block devices (i.e. /dev/sda, not /dev/sg0).  It uses SG_IO for commands
>> >  other than I/O commands, and regular AIO read/writes for I/O commands.
>> >  Besides being simpler to configure (no mapping required to scsi-generic
>> >  device names), this removes the need for a large bounce buffer and,
>> >  in the future, will get scatter/gather support for free from scsi-disk.
>> >
>> >  Signed-off-by: Paolo Bonzini<pbonzini@redhat.com>
>
> This doesn't seem to use much of scsi-disk, so what about exporting
> &scsi_disk_reqops and adding a separate file scsi-block.c? Would make
> things a bit more symmetrical between scsi-disk and scsi-generic.
>
> Or will future patches add code that depends on internal interfaces of
> scsi-disk?

It already uses some internal interfaces: scsi_initfn, scsi_disk_reset, 
scsi_destroy, sizeof(SCSIDiskState).

Paolo

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

* Re: [Qemu-devel] [PATCH 35/35] scsi-disk: add scsi-block for device passthrough
  2011-10-13 11:04 ` [Qemu-devel] [PATCH 35/35] scsi-disk: add scsi-block for device passthrough Paolo Bonzini
@ 2011-10-24 15:28   ` Kevin Wolf
  2011-10-24 15:28     ` Paolo Bonzini
  0 siblings, 1 reply; 68+ messages in thread
From: Kevin Wolf @ 2011-10-24 15:28 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Am 13.10.2011 13:04, schrieb Paolo Bonzini:
> scsi-block is a new device that supports device passthrough of Linux
> block devices (i.e. /dev/sda, not /dev/sg0).  It uses SG_IO for commands
> other than I/O commands, and regular AIO read/writes for I/O commands.
> Besides being simpler to configure (no mapping required to scsi-generic
> device names), this removes the need for a large bounce buffer and,
> in the future, will get scatter/gather support for free from scsi-disk.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

This doesn't seem to use much of scsi-disk, so what about exporting
&scsi_disk_reqops and adding a separate file scsi-block.c? Would make
things a bit more symmetrical between scsi-disk and scsi-generic.

Or will future patches add code that depends on internal interfaces of
scsi-disk?

Kevin

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

* Re: [Qemu-devel] [PATCH 29/35] scsi-disk: remove cluster_size
  2011-10-24 15:10   ` Kevin Wolf
@ 2011-10-24 15:36     ` Paolo Bonzini
  0 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2011-10-24 15:36 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

On 10/24/2011 05:10 PM, Kevin Wolf wrote:
>> >  -    bdrv_get_geometry(s->qdev.conf.bs,&nb_sectors);
>> >  -    nb_sectors /= s->cluster_size;
>> >  -    if (nb_sectors) {
>> >  -        nb_sectors--;
>> >  +    if (s->qdev.blocksize) {
> When would it be 0? And wouldn't we crash with a zero blocksize anyway?

blocksize can be zero when passing through a removable medium and no 
medium has ever been inserted in the disk since the guest was started. 
In practice it won't crash because the guest will always send READ 
CAPACITY first, will see a unit attention condition, and will not 
attempt a read.

A more complete solution involves asking raw-posix for the logical block 
size (right now logical_block_size acts as both the emulated and host 
block size).  This would also be useful to make cache=none work with 
4k-sector disks without manually specifying logical_block_size. 
However, it's not 1.0 material.

Paolo

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

* Re: [Qemu-devel] [PATCH 35/35] scsi-disk: add scsi-block for device passthrough
  2011-10-24 15:28     ` Paolo Bonzini
@ 2011-10-24 15:38       ` Kevin Wolf
  0 siblings, 0 replies; 68+ messages in thread
From: Kevin Wolf @ 2011-10-24 15:38 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Am 24.10.2011 17:28, schrieb Paolo Bonzini:
> On 10/24/2011 05:28 PM, Kevin Wolf wrote:
>>> scsi-block is a new device that supports device passthrough of Linux
>>>>  block devices (i.e. /dev/sda, not /dev/sg0).  It uses SG_IO for commands
>>>>  other than I/O commands, and regular AIO read/writes for I/O commands.
>>>>  Besides being simpler to configure (no mapping required to scsi-generic
>>>>  device names), this removes the need for a large bounce buffer and,
>>>>  in the future, will get scatter/gather support for free from scsi-disk.
>>>>
>>>>  Signed-off-by: Paolo Bonzini<pbonzini@redhat.com>
>>
>> This doesn't seem to use much of scsi-disk, so what about exporting
>> &scsi_disk_reqops and adding a separate file scsi-block.c? Would make
>> things a bit more symmetrical between scsi-disk and scsi-generic.
>>
>> Or will future patches add code that depends on internal interfaces of
>> scsi-disk?
> 
> It already uses some internal interfaces: scsi_initfn, scsi_disk_reset, 
> scsi_destroy, sizeof(SCSIDiskState).

Right... I don't like it much in scsi-disk.c, but what can you do.
Exporting everything wouldn't be nicer.

Kevin

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

end of thread, other threads:[~2011-10-24 15:36 UTC | newest]

Thread overview: 68+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-10-13 11:03 [Qemu-devel] [PULL 00/35] SCSI uber-patch Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 01/35] scsi: pass correct sense code for ENOMEDIUM Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 02/35] atapi/scsi: unify definitions for MMC Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 03/35] atapi: move GESN definitions to scsi-defs.h Paolo Bonzini
2011-10-17 13:41   ` Kevin Wolf
2011-10-17 13:53     ` Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 04/35] atapi: fill in AUDIO_CTL page correctly Paolo Bonzini
2011-10-17 14:05   ` Kevin Wolf
2011-10-17 14:04     ` Paolo Bonzini
2011-10-17 14:10       ` Kevin Wolf
2011-10-17 14:22         ` Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 05/35] scsi: notify the device when unit attention is reported Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 06/35] scsi-disk: report media changed via unit attention sense codes Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 07/35] scsi-disk: add stubs for more MMC commands Paolo Bonzini
2011-10-17 14:27   ` Kevin Wolf
2011-10-17 14:28     ` Paolo Bonzini
2011-10-17 14:44       ` Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 08/35] scsi-disk: store valid mode pages in a table Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 09/35] atapi/scsi-disk: make mode page values coherent between the two Paolo Bonzini
2011-10-17 15:05   ` Kevin Wolf
2011-10-17 15:06     ` Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 10/35] scsi-disk: support DVD profile in GET CONFIGURATION Paolo Bonzini
2011-10-17 15:20   ` Kevin Wolf
2011-10-17 15:28     ` Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 11/35] scsi-disk: support READ DVD STRUCTURE Paolo Bonzini
2011-10-21 11:42   ` Kevin Wolf
2011-10-21 13:11     ` Paolo Bonzini
2011-10-21 13:12     ` Paolo Bonzini
2011-10-21 13:32       ` Kevin Wolf
2011-10-21 13:36         ` Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 12/35] scsi-disk: report media changed via GET EVENT STATUS NOTIFICATION Paolo Bonzini
2011-10-21 11:54   ` Kevin Wolf
2011-10-21 13:08     ` Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 13/35] scsi: move tcq/ndev to SCSIBusOps (now SCSIBusInfo) Paolo Bonzini
2011-10-21 12:01   ` Kevin Wolf
2011-10-21 12:21     ` Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 14/35] qdev: switch children device list to QTAILQ Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 15/35] scsi: remove devs array from SCSIBus Paolo Bonzini
2011-10-21 12:31   ` Kevin Wolf
2011-10-21 13:03     ` Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 16/35] scsi: implement REPORT LUNS for arbitrary LUNs Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 17/35] scsi: allow " Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 18/35] scsi: add channel to addressing Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 19/35] scsi-disk: fail READ CAPACITY if LBA != 0 but PMI == 0 Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 20/35] scsi-disk: do not complete requests twice Paolo Bonzini
2011-10-19 13:13   ` Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 21/35] scsi-disk: bump SCSIRequest reference count until aio completion runs Paolo Bonzini
2011-10-17 15:37   ` [Qemu-devel] [PATCH v2 " Paolo Bonzini
2011-10-19 13:13     ` Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 22/35] scsi-disk: fix retrying a flush Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 23/35] scsi-generic: drop SCSIGenericState Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 24/35] scsi-generic: remove scsi_req_fixup Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 25/35] scsi-generic: check ioctl statuses when SG_IO succeeds Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 26/35] scsi-generic: look at host status Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 27/35] scsi-generic: snoop READ CAPACITY commands to get block size Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 28/35] scsi-disk: do not duplicate BlockDriverState member Paolo Bonzini
2011-10-13 11:03 ` [Qemu-devel] [PATCH 29/35] scsi-disk: remove cluster_size Paolo Bonzini
2011-10-24 15:10   ` Kevin Wolf
2011-10-24 15:36     ` Paolo Bonzini
2011-10-13 11:04 ` [Qemu-devel] [PATCH 30/35] scsi-disk: small clean up to INQUIRY Paolo Bonzini
2011-10-13 11:04 ` [Qemu-devel] [PATCH 31/35] scsi: move max_lba to SCSIDevice Paolo Bonzini
2011-10-13 11:04 ` [Qemu-devel] [PATCH 32/35] scsi: make reqops static const Paolo Bonzini
2011-10-13 11:04 ` [Qemu-devel] [PATCH 33/35] scsi: export scsi_generic_reqops Paolo Bonzini
2011-10-13 11:04 ` [Qemu-devel] [PATCH 34/35] scsi: pass cdb to alloc_req Paolo Bonzini
2011-10-13 11:04 ` [Qemu-devel] [PATCH 35/35] scsi-disk: add scsi-block for device passthrough Paolo Bonzini
2011-10-24 15:28   ` Kevin Wolf
2011-10-24 15:28     ` Paolo Bonzini
2011-10-24 15:38       ` Kevin Wolf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.