From: Hannes Reinecke <hare@suse.de>
To: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
Markus Armbruster <armbru@redhat.com>,
kvm@vger.kernel.org, Alexander Graf <agraf@suse.de>,
Hannes Reinecke <hare@suse.de>
Subject: [PATCH 2/3] scsi-disk: Remove drive_kind
Date: Fri, 22 Jul 2011 14:31:07 +0200 [thread overview]
Message-ID: <1311337868-20746-3-git-send-email-hare@suse.de> (raw)
In-Reply-To: <1311337868-20746-1-git-send-email-hare@suse.de>
Instead of using our own type structure we can be using the
SCSI type from the parent device.
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
hw/scsi-disk.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 129 insertions(+), 27 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 2f7e0c9..8ad90c0 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -74,7 +74,6 @@ struct SCSIDiskState
char *version;
char *serial;
SCSISense sense;
- SCSIDriveKind drive_kind;
};
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type);
@@ -362,13 +361,107 @@ static int scsi_get_sense(SCSIRequest *req, uint8_t *outbuf, int len)
return scsi_build_sense(s->sense, outbuf, len, len > 14);
}
+#define GENERIC_CMD (uint32_t)0xFFFFFFFF
+#define DISK_CMD (1u << TYPE_DISK)
+#define TAPE_CMD (1u << TYPE_TAPE)
+#define PRINTER_CMD (1u << TYPE_PRINTER)
+#define PROCESSOR_CMD (1u << TYPE_PROCESSOR)
+#define WORM_CMD (1u << TYPE_WORM)
+#define ROM_CMD (1u << TYPE_ROM)
+#define SCANNER_CMD (1u << TYPE_SCANNER)
+#define MOD_CMD (1u << TYPE_MOD)
+#define MEDIUM_CHANGER_CMD (1u << TYPE_MEDIUM_CHANGER)
+#define ARRAY_CMD (1u << TYPE_STORAGE_ARRAY)
+#define ENCLOSURE_CMD (1u << TYPE_ENCLOSURE)
+#define RBC_CMD (1u << TYPE_RBC)
+#define OSD_CMD (1u << TYPE_OSD)
+
+#define NO_ROM_CMD (GENERIC_CMD | ~ROM_CMD)
+
+uint32_t scsi_cmd_table[0x100] = {
+ [TEST_UNIT_READY] = GENERIC_CMD,
+ [REWIND] = TAPE_CMD,
+ [REQUEST_SENSE] = GENERIC_CMD,
+ [FORMAT_UNIT] = DISK_CMD|ROM_CMD,
+ [READ_BLOCK_LIMITS] = TAPE_CMD,
+ [REASSIGN_BLOCKS] = DISK_CMD|WORM_CMD|MOD_CMD,
+ [READ_6] = DISK_CMD|TAPE_CMD|WORM_CMD|ROM_CMD|MOD_CMD,
+ [WRITE_6] = DISK_CMD|TAPE_CMD|WORM_CMD|MOD_CMD,
+ [READ_REVERSE] = TAPE_CMD,
+ [WRITE_FILEMARKS] = TAPE_CMD,
+ [SPACE] = TAPE_CMD,
+ [INQUIRY] = GENERIC_CMD,
+ [MODE_SELECT] = GENERIC_CMD,
+ [RESERVE] = TAPE_CMD|PRINTER_CMD,
+ [RELEASE] = TAPE_CMD|PRINTER_CMD,
+ [ERASE] = TAPE_CMD,
+ [MODE_SENSE] = GENERIC_CMD,
+ [START_STOP] = GENERIC_CMD,
+ [RECEIVE_DIAGNOSTIC] = GENERIC_CMD,
+ [SEND_DIAGNOSTIC] = GENERIC_CMD,
+ [ALLOW_MEDIUM_REMOVAL] = GENERIC_CMD,
+ [READ_CAPACITY_10] = DISK_CMD|WORM_CMD|MOD_CMD,
+ [READ_10] = DISK_CMD|WORM_CMD|ROM_CMD|MOD_CMD,
+ [WRITE_10] = DISK_CMD|WORM_CMD|ROM_CMD|MOD_CMD,
+ [SEEK_10] = TAPE_CMD|WORM_CMD|ROM_CMD|MOD_CMD,
+ [WRITE_VERIFY_10] = DISK_CMD|WORM_CMD|ROM_CMD|MOD_CMD,
+ [VERIFY_10] = DISK_CMD|WORM_CMD|ROM_CMD|MOD_CMD,
+ [READ_POSITION] = TAPE_CMD,
+ [SYNCHRONIZE_CACHE] = DISK_CMD|WORM_CMD|ROM_CMD|MOD_CMD|RBC_CMD,
+ [WRITE_BUFFER] = GENERIC_CMD,
+ [READ_BUFFER] = GENERIC_CMD,
+ [READ_LONG_10] = DISK_CMD|WORM_CMD|MOD_CMD,
+ [WRITE_LONG_10] = DISK_CMD|WORM_CMD|MOD_CMD,
+ [WRITE_SAME_10] = DISK_CMD,
+ [UNMAP] = DISK_CMD,
+ [READ_TOC] = ROM_CMD,
+ [REPORT_DENSITY_SUPPORT] = TAPE_CMD,
+ [GET_CONFIGURATION] = ROM_CMD,
+ [LOG_SELECT] = GENERIC_CMD,
+ [LOG_SENSE] = GENERIC_CMD,
+ [MODE_SELECT_10] = GENERIC_CMD,
+ [RESERVE_10] = PRINTER_CMD,
+ [RELEASE_10] = PRINTER_CMD,
+ [MODE_SENSE_10] = GENERIC_CMD,
+ [PERSISTENT_RESERVE_IN] = GENERIC_CMD,
+ [PERSISTENT_RESERVE_OUT] = GENERIC_CMD,
+ [VARLENGTH_CDB] = OSD_CMD,
+ [WRITE_FILEMARKS_16] = TAPE_CMD,
+ [ATA_PASSTHROUGH] = DISK_CMD|ROM_CMD|RBC_CMD,
+ [READ_16] = DISK_CMD|TAPE_CMD|WORM_CMD|MOD_CMD|RBC_CMD,
+ [WRITE_16] = DISK_CMD|TAPE_CMD|WORM_CMD|MOD_CMD|RBC_CMD,
+ [WRITE_VERIFY_16] = DISK_CMD|WORM_CMD|MOD_CMD|RBC_CMD,
+ [SYNCHRONIZE_CACHE_16] = DISK_CMD|TAPE_CMD|WORM_CMD|MOD_CMD|RBC_CMD,
+ [LOCATE_16] = TAPE_CMD,
+ [WRITE_SAME_16] = DISK_CMD|TAPE_CMD,
+ [SERVICE_ACTION_IN] = GENERIC_CMD,
+ [REPORT_LUNS] = NO_ROM_CMD,
+ [BLANK] = ROM_CMD,
+ [MAINTENANCE_IN] = NO_ROM_CMD,
+ [MAINTENANCE_OUT] = NO_ROM_CMD,
+ [MOVE_MEDIUM] = MEDIUM_CHANGER_CMD,
+ [LOAD_UNLOAD] = ROM_CMD|MEDIUM_CHANGER_CMD,
+ [READ_12] = DISK_CMD|WORM_CMD|ROM_CMD|MOD_CMD,
+ [WRITE_12] = DISK_CMD|WORM_CMD|ROM_CMD|MOD_CMD,
+ [WRITE_VERIFY_12] = DISK_CMD|WORM_CMD|MOD_CMD,
+ [VERIFY_12] = DISK_CMD|WORM_CMD|MOD_CMD,
+ [READ_ELEMENT_STATUS] = WORM_CMD|MOD_CMD,
+ [SET_CD_SPEED] = ROM_CMD
+};
+
+static bool scsi_command_supported(uint8_t scsi_type, uint8_t cmd)
+{
+ uint32_t mask = (1u << scsi_type);
+ return scsi_cmd_table[cmd] & mask;
+}
+
static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
int buflen = 0;
if (req->cmd.buf[1] & 0x2) {
- /* Command support data - optional, not implemented */
+ /* Command support data - obsolete */
BADF("optional INQUIRY command support request not implemented\n");
return -1;
}
@@ -382,7 +475,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
return -1;
}
- if (s->drive_kind == SCSI_CD) {
+ if (s->qdev.type == TYPE_ROM) {
outbuf[buflen++] = 5;
} else {
outbuf[buflen++] = 0;
@@ -401,7 +494,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
if (s->serial)
outbuf[buflen++] = 0x80; // unit serial number
outbuf[buflen++] = 0x83; // device identification
- if (s->drive_kind == SCSI_HD) {
+ if (s->qdev.type == TYPE_DISK) {
outbuf[buflen++] = 0xb0; // block limits
outbuf[buflen++] = 0xb2; // thin provisioning
}
@@ -460,7 +553,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
unsigned int opt_io_size =
s->qdev.conf.opt_io_size / s->qdev.blocksize;
- if (s->drive_kind == SCSI_CD) {
+ if (s->qdev.type == TYPE_ROM) {
DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
page_code);
return -1;
@@ -526,16 +619,15 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
memset(outbuf, 0, buflen);
if (req->lun) {
- outbuf[0] = 0x7f; /* LUN not supported */
+ outbuf[0] = 0x7f; /* LUN not supported */
return buflen;
}
- if (s->drive_kind == SCSI_CD) {
- outbuf[0] = 5;
+ outbuf[0] = s->qdev.type & 0x1f;
+ if (s->qdev.type == TYPE_ROM) {
outbuf[1] = 0x80;
memcpy(&outbuf[16], "QEMU CD-ROM ", 16);
} else {
- outbuf[0] = 0;
outbuf[1] = s->removable ? 0x80 : 0;
memcpy(&outbuf[16], "QEMU HARDDISK ", 16);
}
@@ -661,7 +753,7 @@ static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p,
return p[1] + 2;
case 0x2a: /* CD Capabilities and Mechanical Status page. */
- if (s->drive_kind != SCSI_CD)
+ if (s->qdev.type != TYPE_ROM)
return 0;
p[0] = 0x2a;
p[1] = 0x14;
@@ -877,7 +969,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
goto illegal_request;
break;
case START_STOP:
- if (s->drive_kind == SCSI_CD && (req->cmd.buf[4] & 2)) {
+ if (s->qdev.type == TYPE_ROM && (req->cmd.buf[4] & 2)) {
/* load/eject medium */
bdrv_eject(s->bs, !(req->cmd.buf[4] & 1));
}
@@ -885,7 +977,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
case ALLOW_MEDIUM_REMOVAL:
bdrv_set_locked(s->bs, req->cmd.buf[4] & 1);
break;
- case READ_CAPACITY:
+ case READ_CAPACITY_10:
/* The normal LEN field for this command is zero. */
memset(outbuf, 0, 8);
bdrv_get_geometry(s->bs, &nb_sectors);
@@ -1034,6 +1126,14 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
return 0;
}
}
+ if (!scsi_command_supported(command, s->qdev.type)) {
+ DPRINTF("Command %02x not supported for type %02x\n",
+ command, s->qdev.type);
+ scsi_command_complete(r, CHECK_CONDITION,
+ SENSE_CODE(INVALID_OPCODE));
+ return 0;
+ }
+
switch (command) {
case TEST_UNIT_READY:
case REQUEST_SENSE:
@@ -1183,7 +1283,7 @@ static void scsi_destroy(SCSIDevice *dev)
blockdev_mark_auto_del(s->qdev.conf.bs);
}
-static int scsi_initfn(SCSIDevice *dev, SCSIDriveKind kind)
+static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
DriveInfo *dinfo;
@@ -1193,9 +1293,8 @@ static int scsi_initfn(SCSIDevice *dev, SCSIDriveKind kind)
return -1;
}
s->bs = s->qdev.conf.bs;
- s->drive_kind = kind;
- if (kind == SCSI_HD && !bdrv_is_inserted(s->bs)) {
+ if (scsi_type == TYPE_DISK && !bdrv_is_inserted(s->bs)) {
error_report("Device needs media, but drive is empty");
return -1;
}
@@ -1217,44 +1316,47 @@ static int scsi_initfn(SCSIDevice *dev, SCSIDriveKind kind)
return -1;
}
- if (kind == SCSI_CD) {
+ if (scsi_type == TYPE_ROM) {
s->qdev.blocksize = 2048;
- } else {
+ } 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;
}
s->cluster_size = s->qdev.blocksize / 512;
s->bs->buffer_alignment = s->qdev.blocksize;
- s->qdev.type = TYPE_DISK;
+ s->qdev.type = scsi_type;
qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
- bdrv_set_removable(s->bs, kind == SCSI_CD);
+ bdrv_set_removable(s->bs, scsi_type == TYPE_ROM);
add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0");
return 0;
}
static int scsi_hd_initfn(SCSIDevice *dev)
{
- return scsi_initfn(dev, SCSI_HD);
+ return scsi_initfn(dev, TYPE_DISK);
}
static int scsi_cd_initfn(SCSIDevice *dev)
{
- return scsi_initfn(dev, SCSI_CD);
+ return scsi_initfn(dev, TYPE_ROM);
}
static int scsi_disk_initfn(SCSIDevice *dev)
{
- SCSIDriveKind kind;
DriveInfo *dinfo;
+ uint8_t scsi_type = TYPE_DISK;
- if (!dev->conf.bs) {
- kind = SCSI_HD; /* will die in scsi_initfn() */
- } else {
+ if (dev->conf.bs) {
dinfo = drive_get_by_blockdev(dev->conf.bs);
- kind = dinfo->media_cd ? SCSI_CD : SCSI_HD;
+ if (dinfo->media_cd) {
+ scsi_type = TYPE_ROM;
+ }
}
- return scsi_initfn(dev, kind);
+ return scsi_initfn(dev, scsi_type);
}
#define DEFINE_SCSI_DISK_PROPERTIES() \
--
1.7.3.4
WARNING: multiple messages have this Message-ID (diff)
From: Hannes Reinecke <hare@suse.de>
To: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>, Hannes Reinecke <hare@suse.de>,
Markus Armbruster <armbru@redhat.com>,
kvm@vger.kernel.org, Alexander Graf <agraf@suse.de>
Subject: [Qemu-devel] [PATCH 2/3] scsi-disk: Remove drive_kind
Date: Fri, 22 Jul 2011 14:31:07 +0200 [thread overview]
Message-ID: <1311337868-20746-3-git-send-email-hare@suse.de> (raw)
In-Reply-To: <1311337868-20746-1-git-send-email-hare@suse.de>
Instead of using our own type structure we can be using the
SCSI type from the parent device.
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
hw/scsi-disk.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 129 insertions(+), 27 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 2f7e0c9..8ad90c0 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -74,7 +74,6 @@ struct SCSIDiskState
char *version;
char *serial;
SCSISense sense;
- SCSIDriveKind drive_kind;
};
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type);
@@ -362,13 +361,107 @@ static int scsi_get_sense(SCSIRequest *req, uint8_t *outbuf, int len)
return scsi_build_sense(s->sense, outbuf, len, len > 14);
}
+#define GENERIC_CMD (uint32_t)0xFFFFFFFF
+#define DISK_CMD (1u << TYPE_DISK)
+#define TAPE_CMD (1u << TYPE_TAPE)
+#define PRINTER_CMD (1u << TYPE_PRINTER)
+#define PROCESSOR_CMD (1u << TYPE_PROCESSOR)
+#define WORM_CMD (1u << TYPE_WORM)
+#define ROM_CMD (1u << TYPE_ROM)
+#define SCANNER_CMD (1u << TYPE_SCANNER)
+#define MOD_CMD (1u << TYPE_MOD)
+#define MEDIUM_CHANGER_CMD (1u << TYPE_MEDIUM_CHANGER)
+#define ARRAY_CMD (1u << TYPE_STORAGE_ARRAY)
+#define ENCLOSURE_CMD (1u << TYPE_ENCLOSURE)
+#define RBC_CMD (1u << TYPE_RBC)
+#define OSD_CMD (1u << TYPE_OSD)
+
+#define NO_ROM_CMD (GENERIC_CMD | ~ROM_CMD)
+
+uint32_t scsi_cmd_table[0x100] = {
+ [TEST_UNIT_READY] = GENERIC_CMD,
+ [REWIND] = TAPE_CMD,
+ [REQUEST_SENSE] = GENERIC_CMD,
+ [FORMAT_UNIT] = DISK_CMD|ROM_CMD,
+ [READ_BLOCK_LIMITS] = TAPE_CMD,
+ [REASSIGN_BLOCKS] = DISK_CMD|WORM_CMD|MOD_CMD,
+ [READ_6] = DISK_CMD|TAPE_CMD|WORM_CMD|ROM_CMD|MOD_CMD,
+ [WRITE_6] = DISK_CMD|TAPE_CMD|WORM_CMD|MOD_CMD,
+ [READ_REVERSE] = TAPE_CMD,
+ [WRITE_FILEMARKS] = TAPE_CMD,
+ [SPACE] = TAPE_CMD,
+ [INQUIRY] = GENERIC_CMD,
+ [MODE_SELECT] = GENERIC_CMD,
+ [RESERVE] = TAPE_CMD|PRINTER_CMD,
+ [RELEASE] = TAPE_CMD|PRINTER_CMD,
+ [ERASE] = TAPE_CMD,
+ [MODE_SENSE] = GENERIC_CMD,
+ [START_STOP] = GENERIC_CMD,
+ [RECEIVE_DIAGNOSTIC] = GENERIC_CMD,
+ [SEND_DIAGNOSTIC] = GENERIC_CMD,
+ [ALLOW_MEDIUM_REMOVAL] = GENERIC_CMD,
+ [READ_CAPACITY_10] = DISK_CMD|WORM_CMD|MOD_CMD,
+ [READ_10] = DISK_CMD|WORM_CMD|ROM_CMD|MOD_CMD,
+ [WRITE_10] = DISK_CMD|WORM_CMD|ROM_CMD|MOD_CMD,
+ [SEEK_10] = TAPE_CMD|WORM_CMD|ROM_CMD|MOD_CMD,
+ [WRITE_VERIFY_10] = DISK_CMD|WORM_CMD|ROM_CMD|MOD_CMD,
+ [VERIFY_10] = DISK_CMD|WORM_CMD|ROM_CMD|MOD_CMD,
+ [READ_POSITION] = TAPE_CMD,
+ [SYNCHRONIZE_CACHE] = DISK_CMD|WORM_CMD|ROM_CMD|MOD_CMD|RBC_CMD,
+ [WRITE_BUFFER] = GENERIC_CMD,
+ [READ_BUFFER] = GENERIC_CMD,
+ [READ_LONG_10] = DISK_CMD|WORM_CMD|MOD_CMD,
+ [WRITE_LONG_10] = DISK_CMD|WORM_CMD|MOD_CMD,
+ [WRITE_SAME_10] = DISK_CMD,
+ [UNMAP] = DISK_CMD,
+ [READ_TOC] = ROM_CMD,
+ [REPORT_DENSITY_SUPPORT] = TAPE_CMD,
+ [GET_CONFIGURATION] = ROM_CMD,
+ [LOG_SELECT] = GENERIC_CMD,
+ [LOG_SENSE] = GENERIC_CMD,
+ [MODE_SELECT_10] = GENERIC_CMD,
+ [RESERVE_10] = PRINTER_CMD,
+ [RELEASE_10] = PRINTER_CMD,
+ [MODE_SENSE_10] = GENERIC_CMD,
+ [PERSISTENT_RESERVE_IN] = GENERIC_CMD,
+ [PERSISTENT_RESERVE_OUT] = GENERIC_CMD,
+ [VARLENGTH_CDB] = OSD_CMD,
+ [WRITE_FILEMARKS_16] = TAPE_CMD,
+ [ATA_PASSTHROUGH] = DISK_CMD|ROM_CMD|RBC_CMD,
+ [READ_16] = DISK_CMD|TAPE_CMD|WORM_CMD|MOD_CMD|RBC_CMD,
+ [WRITE_16] = DISK_CMD|TAPE_CMD|WORM_CMD|MOD_CMD|RBC_CMD,
+ [WRITE_VERIFY_16] = DISK_CMD|WORM_CMD|MOD_CMD|RBC_CMD,
+ [SYNCHRONIZE_CACHE_16] = DISK_CMD|TAPE_CMD|WORM_CMD|MOD_CMD|RBC_CMD,
+ [LOCATE_16] = TAPE_CMD,
+ [WRITE_SAME_16] = DISK_CMD|TAPE_CMD,
+ [SERVICE_ACTION_IN] = GENERIC_CMD,
+ [REPORT_LUNS] = NO_ROM_CMD,
+ [BLANK] = ROM_CMD,
+ [MAINTENANCE_IN] = NO_ROM_CMD,
+ [MAINTENANCE_OUT] = NO_ROM_CMD,
+ [MOVE_MEDIUM] = MEDIUM_CHANGER_CMD,
+ [LOAD_UNLOAD] = ROM_CMD|MEDIUM_CHANGER_CMD,
+ [READ_12] = DISK_CMD|WORM_CMD|ROM_CMD|MOD_CMD,
+ [WRITE_12] = DISK_CMD|WORM_CMD|ROM_CMD|MOD_CMD,
+ [WRITE_VERIFY_12] = DISK_CMD|WORM_CMD|MOD_CMD,
+ [VERIFY_12] = DISK_CMD|WORM_CMD|MOD_CMD,
+ [READ_ELEMENT_STATUS] = WORM_CMD|MOD_CMD,
+ [SET_CD_SPEED] = ROM_CMD
+};
+
+static bool scsi_command_supported(uint8_t scsi_type, uint8_t cmd)
+{
+ uint32_t mask = (1u << scsi_type);
+ return scsi_cmd_table[cmd] & mask;
+}
+
static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
int buflen = 0;
if (req->cmd.buf[1] & 0x2) {
- /* Command support data - optional, not implemented */
+ /* Command support data - obsolete */
BADF("optional INQUIRY command support request not implemented\n");
return -1;
}
@@ -382,7 +475,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
return -1;
}
- if (s->drive_kind == SCSI_CD) {
+ if (s->qdev.type == TYPE_ROM) {
outbuf[buflen++] = 5;
} else {
outbuf[buflen++] = 0;
@@ -401,7 +494,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
if (s->serial)
outbuf[buflen++] = 0x80; // unit serial number
outbuf[buflen++] = 0x83; // device identification
- if (s->drive_kind == SCSI_HD) {
+ if (s->qdev.type == TYPE_DISK) {
outbuf[buflen++] = 0xb0; // block limits
outbuf[buflen++] = 0xb2; // thin provisioning
}
@@ -460,7 +553,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
unsigned int opt_io_size =
s->qdev.conf.opt_io_size / s->qdev.blocksize;
- if (s->drive_kind == SCSI_CD) {
+ if (s->qdev.type == TYPE_ROM) {
DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
page_code);
return -1;
@@ -526,16 +619,15 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
memset(outbuf, 0, buflen);
if (req->lun) {
- outbuf[0] = 0x7f; /* LUN not supported */
+ outbuf[0] = 0x7f; /* LUN not supported */
return buflen;
}
- if (s->drive_kind == SCSI_CD) {
- outbuf[0] = 5;
+ outbuf[0] = s->qdev.type & 0x1f;
+ if (s->qdev.type == TYPE_ROM) {
outbuf[1] = 0x80;
memcpy(&outbuf[16], "QEMU CD-ROM ", 16);
} else {
- outbuf[0] = 0;
outbuf[1] = s->removable ? 0x80 : 0;
memcpy(&outbuf[16], "QEMU HARDDISK ", 16);
}
@@ -661,7 +753,7 @@ static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p,
return p[1] + 2;
case 0x2a: /* CD Capabilities and Mechanical Status page. */
- if (s->drive_kind != SCSI_CD)
+ if (s->qdev.type != TYPE_ROM)
return 0;
p[0] = 0x2a;
p[1] = 0x14;
@@ -877,7 +969,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
goto illegal_request;
break;
case START_STOP:
- if (s->drive_kind == SCSI_CD && (req->cmd.buf[4] & 2)) {
+ if (s->qdev.type == TYPE_ROM && (req->cmd.buf[4] & 2)) {
/* load/eject medium */
bdrv_eject(s->bs, !(req->cmd.buf[4] & 1));
}
@@ -885,7 +977,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
case ALLOW_MEDIUM_REMOVAL:
bdrv_set_locked(s->bs, req->cmd.buf[4] & 1);
break;
- case READ_CAPACITY:
+ case READ_CAPACITY_10:
/* The normal LEN field for this command is zero. */
memset(outbuf, 0, 8);
bdrv_get_geometry(s->bs, &nb_sectors);
@@ -1034,6 +1126,14 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
return 0;
}
}
+ if (!scsi_command_supported(command, s->qdev.type)) {
+ DPRINTF("Command %02x not supported for type %02x\n",
+ command, s->qdev.type);
+ scsi_command_complete(r, CHECK_CONDITION,
+ SENSE_CODE(INVALID_OPCODE));
+ return 0;
+ }
+
switch (command) {
case TEST_UNIT_READY:
case REQUEST_SENSE:
@@ -1183,7 +1283,7 @@ static void scsi_destroy(SCSIDevice *dev)
blockdev_mark_auto_del(s->qdev.conf.bs);
}
-static int scsi_initfn(SCSIDevice *dev, SCSIDriveKind kind)
+static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
DriveInfo *dinfo;
@@ -1193,9 +1293,8 @@ static int scsi_initfn(SCSIDevice *dev, SCSIDriveKind kind)
return -1;
}
s->bs = s->qdev.conf.bs;
- s->drive_kind = kind;
- if (kind == SCSI_HD && !bdrv_is_inserted(s->bs)) {
+ if (scsi_type == TYPE_DISK && !bdrv_is_inserted(s->bs)) {
error_report("Device needs media, but drive is empty");
return -1;
}
@@ -1217,44 +1316,47 @@ static int scsi_initfn(SCSIDevice *dev, SCSIDriveKind kind)
return -1;
}
- if (kind == SCSI_CD) {
+ if (scsi_type == TYPE_ROM) {
s->qdev.blocksize = 2048;
- } else {
+ } 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;
}
s->cluster_size = s->qdev.blocksize / 512;
s->bs->buffer_alignment = s->qdev.blocksize;
- s->qdev.type = TYPE_DISK;
+ s->qdev.type = scsi_type;
qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
- bdrv_set_removable(s->bs, kind == SCSI_CD);
+ bdrv_set_removable(s->bs, scsi_type == TYPE_ROM);
add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0");
return 0;
}
static int scsi_hd_initfn(SCSIDevice *dev)
{
- return scsi_initfn(dev, SCSI_HD);
+ return scsi_initfn(dev, TYPE_DISK);
}
static int scsi_cd_initfn(SCSIDevice *dev)
{
- return scsi_initfn(dev, SCSI_CD);
+ return scsi_initfn(dev, TYPE_ROM);
}
static int scsi_disk_initfn(SCSIDevice *dev)
{
- SCSIDriveKind kind;
DriveInfo *dinfo;
+ uint8_t scsi_type = TYPE_DISK;
- if (!dev->conf.bs) {
- kind = SCSI_HD; /* will die in scsi_initfn() */
- } else {
+ if (dev->conf.bs) {
dinfo = drive_get_by_blockdev(dev->conf.bs);
- kind = dinfo->media_cd ? SCSI_CD : SCSI_HD;
+ if (dinfo->media_cd) {
+ scsi_type = TYPE_ROM;
+ }
}
- return scsi_initfn(dev, kind);
+ return scsi_initfn(dev, scsi_type);
}
#define DEFINE_SCSI_DISK_PROPERTIES() \
--
1.7.3.4
next prev parent reply other threads:[~2011-07-22 12:31 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-07-22 12:31 [PATCH 0/3] Check for supported SCSI commands Hannes Reinecke
2011-07-22 12:31 ` [Qemu-devel] " Hannes Reinecke
2011-07-22 12:31 ` [PATCH 1/3] scsi: Sanitize command definitions Hannes Reinecke
2011-07-22 12:31 ` [Qemu-devel] " Hannes Reinecke
2011-07-22 14:07 ` Markus Armbruster
2011-07-22 14:07 ` Markus Armbruster
2011-07-22 14:14 ` Hannes Reinecke
2011-07-22 14:14 ` Hannes Reinecke
2011-07-22 12:31 ` Hannes Reinecke [this message]
2011-07-22 12:31 ` [Qemu-devel] [PATCH 2/3] scsi-disk: Remove drive_kind Hannes Reinecke
2011-07-22 12:31 ` [PATCH 3/3] scsi-disk: Check for supported commands Hannes Reinecke
2011-07-22 12:31 ` [Qemu-devel] " Hannes Reinecke
2011-07-22 14:09 ` Markus Armbruster
2011-07-22 14:09 ` Markus Armbruster
2011-07-22 14:15 ` Hannes Reinecke
2011-07-22 14:15 ` Hannes Reinecke
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1311337868-20746-3-git-send-email-hare@suse.de \
--to=hare@suse.de \
--cc=agraf@suse.de \
--cc=armbru@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.