[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 2/3] scsi-disk: Remove drive_kind
From: |
Hannes Reinecke |
Subject: |
[Qemu-devel] [PATCH 2/3] scsi-disk: Remove drive_kind |
Date: |
Fri, 22 Jul 2011 14:31:07 +0200 |
Instead of using our own type structure we can be using the
SCSI type from the parent device.
Signed-off-by: Hannes Reinecke <address@hidden>
---
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