* [Qemu-devel] [PATCH 01/30] scsi: add/fix header protection.
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
@ 2009-11-26 14:33 ` Gerd Hoffmann
2009-11-26 14:33 ` [Qemu-devel] [PATCH 02/30] scsi: create common SCSIRequest structure Gerd Hoffmann
` (28 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Also delete the leftover and unused scsi-disk.h file.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/esp.h | 5 ++++
hw/scsi-disk.h | 67 --------------------------------------------------------
hw/scsi.h | 4 +-
3 files changed, 7 insertions(+), 69 deletions(-)
delete mode 100644 hw/scsi-disk.h
diff --git a/hw/esp.h b/hw/esp.h
index 369998f..190bc2e 100644
--- a/hw/esp.h
+++ b/hw/esp.h
@@ -1,3 +1,6 @@
+#ifndef QEMU_HW_ESP_H
+#define QEMU_HW_ESP_H
+
/* esp.c */
#define ESP_MAX_DEVS 7
typedef void (*espdma_memory_read_write)(void *opaque, uint8_t *buf, int len);
@@ -5,3 +8,5 @@ void esp_init(target_phys_addr_t espaddr, int it_shift,
espdma_memory_read_write dma_memory_read,
espdma_memory_read_write dma_memory_write,
void *dma_opaque, qemu_irq irq, qemu_irq *reset);
+
+#endif
diff --git a/hw/scsi-disk.h b/hw/scsi-disk.h
deleted file mode 100644
index b6b6c12..0000000
--- a/hw/scsi-disk.h
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef SCSI_DISK_H
-#define SCSI_DISK_H
-
-#include "qdev.h"
-
-/* scsi-disk.c */
-enum scsi_reason {
- SCSI_REASON_DONE, /* Command complete. */
- SCSI_REASON_DATA /* Transfer complete, more data required. */
-};
-
-typedef struct SCSIBus SCSIBus;
-typedef struct SCSIDevice SCSIDevice;
-typedef struct SCSIDeviceInfo SCSIDeviceInfo;
-typedef void (*scsi_completionfn)(SCSIBus *bus, int reason, uint32_t tag,
- uint32_t arg);
-
-struct SCSIDevice
-{
- DeviceState qdev;
- uint32_t id;
- SCSIDeviceInfo *info;
-};
-
-/* cdrom.c */
-int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
-int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
-
-/* scsi-bus.c */
-typedef int (*scsi_qdev_initfn)(SCSIDevice *dev);
-struct SCSIDeviceInfo {
- DeviceInfo qdev;
- scsi_qdev_initfn init;
- void (*destroy)(SCSIDevice *s);
- int32_t (*send_command)(SCSIDevice *s, uint32_t tag, uint8_t *buf,
- int lun);
- void (*read_data)(SCSIDevice *s, uint32_t tag);
- int (*write_data)(SCSIDevice *s, uint32_t tag);
- void (*cancel_io)(SCSIDevice *s, uint32_t tag);
- uint8_t *(*get_buf)(SCSIDevice *s, uint32_t tag);
-};
-
-typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv,
- int unit);
-struct SCSIBus {
- BusState qbus;
- int busnr;
-
- int tcq, ndev;
- scsi_completionfn complete;
-
- SCSIDevice *devs[8];
-};
-
-void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev,
- scsi_completionfn complete);
-void scsi_qdev_register(SCSIDeviceInfo *info);
-
-static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
-{
- return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
-}
-
-SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, DriveInfo *dinfo, int unit);
-void scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
-
-#endif
diff --git a/hw/scsi.h b/hw/scsi.h
index b6b6c12..d2b274c 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -1,5 +1,5 @@
-#ifndef SCSI_DISK_H
-#define SCSI_DISK_H
+#ifndef QEMU_HW_SCSI_H
+#define QEMU_HW_SCSI_H
#include "qdev.h"
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 02/30] scsi: create common SCSIRequest structure.
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
2009-11-26 14:33 ` [Qemu-devel] [PATCH 01/30] scsi: add/fix header protection Gerd Hoffmann
@ 2009-11-26 14:33 ` Gerd Hoffmann
2009-11-26 14:33 ` [Qemu-devel] [PATCH 03/30] scsi: move request lists to QTAILQ Gerd Hoffmann
` (27 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Rename the SCSIRequest structs in scsi-disk.c and scsi-generic.c to
SCSIDiskReq and SCSIGenericReq. Create a SCSIRequest struct and move
the common elements over.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-disk.c | 109 ++++++++++++++++++++++++++---------------------------
hw/scsi-generic.c | 104 +++++++++++++++++++++++++-------------------------
hw/scsi.h | 8 ++++
3 files changed, 114 insertions(+), 107 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index a92b62f..142d81d 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -46,10 +46,8 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
typedef struct SCSIDiskState SCSIDiskState;
-typedef struct SCSIRequest {
- SCSIBus *bus;
- SCSIDiskState *dev;
- uint32_t tag;
+typedef struct SCSIDiskReq {
+ SCSIRequest req;
/* ??? We should probably keep track of whether the data transfer is
a read or a write. Currently we rely on the host getting it right. */
/* Both sector and sector_count are in terms of qemu 512 byte blocks. */
@@ -57,16 +55,15 @@ typedef struct SCSIRequest {
uint32_t sector_count;
struct iovec iov;
QEMUIOVector qiov;
- BlockDriverAIOCB *aiocb;
- struct SCSIRequest *next;
+ struct SCSIDiskReq *next;
uint32_t status;
-} SCSIRequest;
+} SCSIDiskReq;
struct SCSIDiskState
{
SCSIDevice qdev;
DriveInfo *dinfo;
- SCSIRequest *requests;
+ SCSIDiskReq *requests;
/* 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;
@@ -77,26 +74,26 @@ struct SCSIDiskState
};
/* Global pool of SCSIRequest structures. */
-static SCSIRequest *free_requests = NULL;
+static SCSIDiskReq *free_requests = NULL;
-static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag)
+static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
- SCSIRequest *r;
+ SCSIDiskReq *r;
if (free_requests) {
r = free_requests;
free_requests = r->next;
} else {
- r = qemu_malloc(sizeof(SCSIRequest));
+ r = qemu_malloc(sizeof(SCSIDiskReq));
r->iov.iov_base = qemu_memalign(512, SCSI_DMA_BUF_SIZE);
}
- r->bus = scsi_bus_from_device(d);
- r->dev = s;
- r->tag = tag;
+ r->req.bus = scsi_bus_from_device(d);
+ r->req.dev = d;
+ r->req.tag = tag;
r->sector_count = 0;
r->iov.iov_len = 0;
- r->aiocb = NULL;
+ r->req.aiocb = NULL;
r->status = 0;
r->next = s->requests;
@@ -104,10 +101,10 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag)
return r;
}
-static void scsi_remove_request(SCSIRequest *r)
+static void scsi_remove_request(SCSIDiskReq *r)
{
- SCSIRequest *last;
- SCSIDiskState *s = r->dev;
+ SCSIDiskReq *last;
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
if (s->requests == r) {
s->requests = r->next;
@@ -125,64 +122,65 @@ static void scsi_remove_request(SCSIRequest *r)
free_requests = r;
}
-static SCSIRequest *scsi_find_request(SCSIDiskState *s, uint32_t tag)
+static SCSIDiskReq *scsi_find_request(SCSIDiskState *s, uint32_t tag)
{
- SCSIRequest *r;
+ SCSIDiskReq *r;
r = s->requests;
- while (r && r->tag != tag)
+ while (r && r->req.tag != tag)
r = r->next;
return r;
}
/* Helper function for command completion. */
-static void scsi_command_complete(SCSIRequest *r, int status, int sense)
+static void scsi_command_complete(SCSIDiskReq *r, int status, int sense)
{
- SCSIDiskState *s = r->dev;
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
uint32_t tag;
- DPRINTF("Command complete tag=0x%x status=%d sense=%d\n", r->tag, status, sense);
+ DPRINTF("Command complete tag=0x%x status=%d sense=%d\n",
+ r->req.tag, status, sense);
s->sense = sense;
- tag = r->tag;
+ tag = r->req.tag;
scsi_remove_request(r);
- r->bus->complete(r->bus, SCSI_REASON_DONE, tag, status);
+ r->req.bus->complete(r->req.bus, SCSI_REASON_DONE, tag, status);
}
/* Cancel a pending data transfer. */
static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
- SCSIRequest *r;
+ SCSIDiskReq *r;
DPRINTF("Cancel tag=0x%x\n", tag);
r = scsi_find_request(s, tag);
if (r) {
- if (r->aiocb)
- bdrv_aio_cancel(r->aiocb);
- r->aiocb = NULL;
+ if (r->req.aiocb)
+ bdrv_aio_cancel(r->req.aiocb);
+ r->req.aiocb = NULL;
scsi_remove_request(r);
}
}
static void scsi_read_complete(void * opaque, int ret)
{
- SCSIRequest *r = (SCSIRequest *)opaque;
+ SCSIDiskReq *r = (SCSIDiskReq *)opaque;
if (ret) {
DPRINTF("IO error\n");
- r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, 0);
+ r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0);
scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NO_SENSE);
return;
}
- DPRINTF("Data ready tag=0x%x len=%" PRId64 "\n", r->tag, r->iov.iov_len);
+ DPRINTF("Data ready tag=0x%x len=%" PRId64 "\n", r->req.tag, r->iov.iov_len);
- r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, r->iov.iov_len);
+ r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->iov.iov_len);
}
/* Read more data from scsi device into buffer. */
static void scsi_read_data(SCSIDevice *d, uint32_t tag)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
- SCSIRequest *r;
+ SCSIDiskReq *r;
uint32_t n;
r = scsi_find_request(s, tag);
@@ -195,7 +193,7 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
if (r->sector_count == (uint32_t)-1) {
DPRINTF("Read buf_len=%" PRId64 "\n", r->iov.iov_len);
r->sector_count = 0;
- r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, r->iov.iov_len);
+ r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->iov.iov_len);
return;
}
DPRINTF("Read sector_count=%d\n", r->sector_count);
@@ -210,17 +208,18 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
r->iov.iov_len = n * 512;
qemu_iovec_init_external(&r->qiov, &r->iov, 1);
- r->aiocb = bdrv_aio_readv(s->dinfo->bdrv, r->sector, &r->qiov, n,
+ r->req.aiocb = bdrv_aio_readv(s->dinfo->bdrv, r->sector, &r->qiov, n,
scsi_read_complete, r);
- if (r->aiocb == NULL)
+ if (r->req.aiocb == NULL)
scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
r->sector += n;
r->sector_count -= n;
}
-static int scsi_handle_write_error(SCSIRequest *r, int error)
+static int scsi_handle_write_error(SCSIDiskReq *r, int error)
{
- BlockInterfaceErrorAction action = drive_get_onerror(r->dev->dinfo->bdrv);
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
+ BlockInterfaceErrorAction action = drive_get_onerror(s->dinfo->bdrv);
if (action == BLOCK_ERR_IGNORE)
return 0;
@@ -239,11 +238,11 @@ static int scsi_handle_write_error(SCSIRequest *r, int error)
static void scsi_write_complete(void * opaque, int ret)
{
- SCSIRequest *r = (SCSIRequest *)opaque;
+ SCSIDiskReq *r = (SCSIDiskReq *)opaque;
uint32_t len;
uint32_t n;
- r->aiocb = NULL;
+ r->req.aiocb = NULL;
if (ret) {
if (scsi_handle_write_error(r, -ret))
@@ -261,22 +260,22 @@ static void scsi_write_complete(void * opaque, int ret)
len = SCSI_DMA_BUF_SIZE;
}
r->iov.iov_len = len;
- DPRINTF("Write complete tag=0x%x more=%d\n", r->tag, len);
- r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, len);
+ DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, len);
+ r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, len);
}
}
-static void scsi_write_request(SCSIRequest *r)
+static void scsi_write_request(SCSIDiskReq *r)
{
- SCSIDiskState *s = r->dev;
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
uint32_t n;
n = r->iov.iov_len / 512;
if (n) {
qemu_iovec_init_external(&r->qiov, &r->iov, 1);
- r->aiocb = bdrv_aio_writev(s->dinfo->bdrv, r->sector, &r->qiov, n,
+ r->req.aiocb = bdrv_aio_writev(s->dinfo->bdrv, r->sector, &r->qiov, n,
scsi_write_complete, r);
- if (r->aiocb == NULL)
+ if (r->req.aiocb == NULL)
scsi_command_complete(r, STATUS_CHECK_CONDITION,
SENSE_HARDWARE_ERROR);
} else {
@@ -290,7 +289,7 @@ static void scsi_write_request(SCSIRequest *r)
static int scsi_write_data(SCSIDevice *d, uint32_t tag)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
- SCSIRequest *r;
+ SCSIDiskReq *r;
DPRINTF("Write data tag=0x%x\n", tag);
r = scsi_find_request(s, tag);
@@ -300,7 +299,7 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag)
return 1;
}
- if (r->aiocb)
+ if (r->req.aiocb)
BADF("Data transfer already in progress\n");
scsi_write_request(r);
@@ -311,7 +310,7 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag)
static void scsi_dma_restart_bh(void *opaque)
{
SCSIDiskState *s = opaque;
- SCSIRequest *r = s->requests;
+ SCSIDiskReq *r = s->requests;
qemu_bh_delete(s->bh);
s->bh = NULL;
@@ -342,7 +341,7 @@ static void scsi_dma_restart_cb(void *opaque, int running, int reason)
static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
- SCSIRequest *r;
+ SCSIDiskReq *r;
r = scsi_find_request(s, tag);
if (!r) {
@@ -368,7 +367,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
int is_write;
uint8_t command;
uint8_t *outbuf;
- SCSIRequest *r;
+ SCSIDiskReq *r;
command = buf[0];
r = scsi_find_request(s, tag);
@@ -606,7 +605,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
outbuf[3] = 2; /* Format 2 */
outbuf[4] = len - 5; /* Additional Length = (Len - 1) - 4 */
/* Sync data transfer and TCQ. */
- outbuf[7] = 0x10 | (r->bus->tcq ? 0x02 : 0);
+ outbuf[7] = 0x10 | (r->req.bus->tcq ? 0x02 : 0);
r->iov.iov_len = len;
break;
case 0x16:
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 92ef771..89f3080 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -54,24 +54,21 @@ do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
typedef struct SCSIGenericState SCSIGenericState;
-typedef struct SCSIRequest {
- BlockDriverAIOCB *aiocb;
- struct SCSIRequest *next;
- SCSIBus *bus;
- SCSIGenericState *dev;
- uint32_t tag;
+typedef struct SCSIGenericReq {
+ SCSIRequest req;
+ struct SCSIGenericReq *next;
uint8_t cmd[SCSI_CMD_BUF_SIZE];
int cmdlen;
uint8_t *buf;
int buflen;
int len;
sg_io_hdr_t io_header;
-} SCSIRequest;
+} SCSIGenericReq;
struct SCSIGenericState
{
SCSIDevice qdev;
- SCSIRequest *requests;
+ SCSIGenericReq *requests;
DriveInfo *dinfo;
int type;
int blocksize;
@@ -81,30 +78,30 @@ struct SCSIGenericState
uint8_t senselen;
};
-/* Global pool of SCSIRequest structures. */
-static SCSIRequest *free_requests = NULL;
+/* Global pool of SCSIGenericReq structures. */
+static SCSIGenericReq *free_requests = NULL;
-static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag)
+static SCSIGenericReq *scsi_new_request(SCSIDevice *d, uint32_t tag)
{
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
- SCSIRequest *r;
+ SCSIGenericReq *r;
if (free_requests) {
r = free_requests;
free_requests = r->next;
} else {
- r = qemu_malloc(sizeof(SCSIRequest));
+ r = qemu_malloc(sizeof(SCSIGenericReq));
r->buf = NULL;
r->buflen = 0;
}
- r->bus = scsi_bus_from_device(d);
- r->dev = s;
- r->tag = tag;
+ r->req.bus = scsi_bus_from_device(d);
+ r->req.dev = d;
+ r->req.tag = tag;
memset(r->cmd, 0, sizeof(r->cmd));
memset(&r->io_header, 0, sizeof(r->io_header));
r->cmdlen = 0;
r->len = 0;
- r->aiocb = NULL;
+ r->req.aiocb = NULL;
/* link */
@@ -113,10 +110,10 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag)
return r;
}
-static void scsi_remove_request(SCSIRequest *r)
+static void scsi_remove_request(SCSIGenericReq *r)
{
- SCSIRequest *last;
- SCSIGenericState *s = r->dev;
+ SCSIGenericReq *last;
+ SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
if (s->requests == r) {
s->requests = r->next;
@@ -134,12 +131,12 @@ static void scsi_remove_request(SCSIRequest *r)
free_requests = r;
}
-static SCSIRequest *scsi_find_request(SCSIGenericState *s, uint32_t tag)
+static SCSIGenericReq *scsi_find_request(SCSIGenericState *s, uint32_t tag)
{
- SCSIRequest *r;
+ SCSIGenericReq *r;
r = s->requests;
- while (r && r->tag != tag)
+ while (r && r->req.tag != tag)
r = r->next;
return r;
@@ -148,8 +145,8 @@ static SCSIRequest *scsi_find_request(SCSIGenericState *s, uint32_t tag)
/* Helper function for command completion. */
static void scsi_command_complete(void *opaque, int ret)
{
- SCSIRequest *r = (SCSIRequest *)opaque;
- SCSIGenericState *s = r->dev;
+ SCSIGenericReq *r = (SCSIGenericReq *)opaque;
+ SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
uint32_t tag;
int status;
@@ -171,10 +168,10 @@ static void scsi_command_complete(void *opaque, int ret)
status = GOOD << 1;
}
DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
- r, r->tag, status);
- tag = r->tag;
+ r, r->req.tag, status);
+ tag = r->req.tag;
scsi_remove_request(r);
- r->bus->complete(r->bus, SCSI_REASON_DONE, tag, status);
+ r->req.bus->complete(r->req.bus, SCSI_REASON_DONE, tag, status);
}
/* Cancel a pending data transfer. */
@@ -182,35 +179,37 @@ static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
{
DPRINTF("scsi_cancel_io 0x%x\n", tag);
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
- SCSIRequest *r;
+ SCSIGenericReq *r;
DPRINTF("Cancel tag=0x%x\n", tag);
r = scsi_find_request(s, tag);
if (r) {
- if (r->aiocb)
- bdrv_aio_cancel(r->aiocb);
- r->aiocb = NULL;
+ if (r->req.aiocb)
+ bdrv_aio_cancel(r->req.aiocb);
+ r->req.aiocb = NULL;
scsi_remove_request(r);
}
}
static int execute_command(BlockDriverState *bdrv,
- SCSIRequest *r, int direction,
+ SCSIGenericReq *r, int direction,
BlockDriverCompletionFunc *complete)
{
+ SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
+
r->io_header.interface_id = 'S';
r->io_header.dxfer_direction = direction;
r->io_header.dxferp = r->buf;
r->io_header.dxfer_len = r->buflen;
r->io_header.cmdp = r->cmd;
r->io_header.cmd_len = r->cmdlen;
- r->io_header.mx_sb_len = sizeof(r->dev->sensebuf);
- r->io_header.sbp = r->dev->sensebuf;
+ r->io_header.mx_sb_len = sizeof(s->sensebuf);
+ r->io_header.sbp = s->sensebuf;
r->io_header.timeout = MAX_UINT;
r->io_header.usr_ptr = r;
r->io_header.flags |= SG_FLAG_DIRECT_IO;
- r->aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
- if (r->aiocb == NULL) {
+ r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
+ if (r->req.aiocb == NULL) {
BADF("execute_command: read failed !\n");
return -1;
}
@@ -220,7 +219,7 @@ static int execute_command(BlockDriverState *bdrv,
static void scsi_read_complete(void * opaque, int ret)
{
- SCSIRequest *r = (SCSIRequest *)opaque;
+ SCSIGenericReq *r = (SCSIGenericReq *)opaque;
int len;
if (ret) {
@@ -229,10 +228,10 @@ static void scsi_read_complete(void * opaque, int ret)
return;
}
len = r->io_header.dxfer_len - r->io_header.resid;
- DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, len);
+ DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
r->len = -1;
- r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, len);
+ r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, len);
if (len == 0)
scsi_command_complete(r, 0);
}
@@ -241,7 +240,7 @@ static void scsi_read_complete(void * opaque, int ret)
static void scsi_read_data(SCSIDevice *d, uint32_t tag)
{
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
- SCSIRequest *r;
+ SCSIGenericReq *r;
int ret;
DPRINTF("scsi_read_data 0x%x\n", tag);
@@ -266,11 +265,11 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
r->io_header.status = 0;
r->io_header.dxfer_len = s->senselen;
r->len = -1;
- DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, s->senselen);
+ DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, s->senselen);
DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
r->buf[0], r->buf[1], r->buf[2], r->buf[3],
r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
- r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, s->senselen);
+ r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, s->senselen);
return;
}
@@ -283,7 +282,8 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
static void scsi_write_complete(void * opaque, int ret)
{
- SCSIRequest *r = (SCSIRequest *)opaque;
+ SCSIGenericReq *r = (SCSIGenericReq *)opaque;
+ SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
DPRINTF("scsi_write_complete() ret = %d\n", ret);
if (ret) {
@@ -293,9 +293,9 @@ static void scsi_write_complete(void * opaque, int ret)
}
if (r->cmd[0] == MODE_SELECT && r->cmd[4] == 12 &&
- r->dev->type == TYPE_TAPE) {
- r->dev->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
- DPRINTF("block size %d\n", r->dev->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);
@@ -306,7 +306,7 @@ static void scsi_write_complete(void * opaque, int ret)
static int scsi_write_data(SCSIDevice *d, uint32_t tag)
{
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
- SCSIRequest *r;
+ SCSIGenericReq *r;
int ret;
DPRINTF("scsi_write_data 0x%x\n", tag);
@@ -320,7 +320,7 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag)
if (r->len == 0) {
r->len = r->buflen;
- r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, r->len);
+ r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->len);
return 0;
}
@@ -337,7 +337,7 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag)
static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
{
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
- SCSIRequest *r;
+ SCSIGenericReq *r;
r = scsi_find_request(s, tag);
if (!r) {
BADF("Bad buffer tag 0x%x\n", tag);
@@ -512,7 +512,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
uint32_t len=0;
int cmdlen=0;
- SCSIRequest *r;
+ SCSIGenericReq *r;
SCSIBus *bus;
int ret;
@@ -653,7 +653,7 @@ static int get_stream_blocksize(BlockDriverState *bdrv)
static void scsi_destroy(SCSIDevice *d)
{
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
- SCSIRequest *r, *n;
+ SCSIGenericReq *r, *n;
r = s->requests;
while (r) {
diff --git a/hw/scsi.h b/hw/scsi.h
index d2b274c..7906877 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -2,6 +2,7 @@
#define QEMU_HW_SCSI_H
#include "qdev.h"
+#include "block.h"
/* scsi-disk.c */
enum scsi_reason {
@@ -15,6 +16,13 @@ typedef struct SCSIDeviceInfo SCSIDeviceInfo;
typedef void (*scsi_completionfn)(SCSIBus *bus, int reason, uint32_t tag,
uint32_t arg);
+typedef struct SCSIRequest {
+ SCSIBus *bus;
+ SCSIDevice *dev;
+ uint32_t tag;
+ BlockDriverAIOCB *aiocb;
+} SCSIRequest;
+
struct SCSIDevice
{
DeviceState qdev;
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 03/30] scsi: move request lists to QTAILQ.
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
2009-11-26 14:33 ` [Qemu-devel] [PATCH 01/30] scsi: add/fix header protection Gerd Hoffmann
2009-11-26 14:33 ` [Qemu-devel] [PATCH 02/30] scsi: create common SCSIRequest structure Gerd Hoffmann
@ 2009-11-26 14:33 ` Gerd Hoffmann
2009-11-26 14:33 ` [Qemu-devel] [PATCH 04/30] scsi: move SCSIRequest management to common code Gerd Hoffmann
` (26 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Changes:
* Move from open-coded lists to QTAILQ macros.
* Move the struct elements to the common data structures
(SCSIDevice + SCSIRequest).
* Drop free request pools.
* Fix request cleanup in the destroy callback.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-bus.c | 1 +
hw/scsi-disk.c | 67 +++++++++++++++-------------------------------
hw/scsi-generic.c | 76 +++++++++++-----------------------------------------
hw/scsi.h | 2 +
4 files changed, 41 insertions(+), 105 deletions(-)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 641db81..801922b 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -50,6 +50,7 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
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;
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 142d81d..997eef6 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -55,7 +55,6 @@ typedef struct SCSIDiskReq {
uint32_t sector_count;
struct iovec iov;
QEMUIOVector qiov;
- struct SCSIDiskReq *next;
uint32_t status;
} SCSIDiskReq;
@@ -63,7 +62,6 @@ struct SCSIDiskState
{
SCSIDevice qdev;
DriveInfo *dinfo;
- SCSIDiskReq *requests;
/* 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;
@@ -73,64 +71,37 @@ struct SCSIDiskState
QEMUBH *bh;
};
-/* Global pool of SCSIRequest structures. */
-static SCSIDiskReq *free_requests = NULL;
-
static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag)
{
- SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
SCSIDiskReq *r;
- if (free_requests) {
- r = free_requests;
- free_requests = r->next;
- } else {
- r = qemu_malloc(sizeof(SCSIDiskReq));
- r->iov.iov_base = qemu_memalign(512, SCSI_DMA_BUF_SIZE);
- }
+ r = qemu_mallocz(sizeof(SCSIDiskReq));
+ r->iov.iov_base = qemu_memalign(512, SCSI_DMA_BUF_SIZE);
r->req.bus = scsi_bus_from_device(d);
r->req.dev = d;
r->req.tag = tag;
- r->sector_count = 0;
- r->iov.iov_len = 0;
- r->req.aiocb = NULL;
- r->status = 0;
- r->next = s->requests;
- s->requests = r;
+ QTAILQ_INSERT_TAIL(&d->requests, &r->req, next);
return r;
}
static void scsi_remove_request(SCSIDiskReq *r)
{
- SCSIDiskReq *last;
- SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
-
- if (s->requests == r) {
- s->requests = r->next;
- } else {
- last = s->requests;
- while (last && last->next != r)
- last = last->next;
- if (last) {
- last->next = r->next;
- } else {
- BADF("Orphaned request\n");
- }
- }
- r->next = free_requests;
- free_requests = r;
+ qemu_free(r->iov.iov_base);
+ QTAILQ_REMOVE(&r->req.dev->requests, &r->req, next);
+ qemu_free(r);
}
static SCSIDiskReq *scsi_find_request(SCSIDiskState *s, uint32_t tag)
{
- SCSIDiskReq *r;
-
- r = s->requests;
- while (r && r->req.tag != tag)
- r = r->next;
+ SCSIRequest *req;
- return r;
+ QTAILQ_FOREACH(req, &s->qdev.requests, next) {
+ if (req->tag == tag) {
+ return DO_UPCAST(SCSIDiskReq, req, req);
+ }
+ }
+ return NULL;
}
/* Helper function for command completion. */
@@ -310,17 +281,18 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag)
static void scsi_dma_restart_bh(void *opaque)
{
SCSIDiskState *s = opaque;
- SCSIDiskReq *r = s->requests;
+ SCSIRequest *req;
+ SCSIDiskReq *r;
qemu_bh_delete(s->bh);
s->bh = NULL;
- while (r) {
+ QTAILQ_FOREACH(req, &s->qdev.requests, next) {
+ r = DO_UPCAST(SCSIDiskReq, req, req);
if (r->status & SCSI_REQ_STATUS_RETRY) {
r->status &= ~SCSI_REQ_STATUS_RETRY;
scsi_write_request(r);
}
- r = r->next;
}
}
@@ -959,7 +931,12 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
static void scsi_destroy(SCSIDevice *dev)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
+ SCSIDiskReq *r;
+ while (!QTAILQ_EMPTY(&s->qdev.requests)) {
+ r = DO_UPCAST(SCSIDiskReq, req, QTAILQ_FIRST(&s->qdev.requests));
+ scsi_remove_request(r);
+ }
drive_uninit(s->dinfo);
}
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 89f3080..1fa9d33 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -56,7 +56,6 @@ typedef struct SCSIGenericState SCSIGenericState;
typedef struct SCSIGenericReq {
SCSIRequest req;
- struct SCSIGenericReq *next;
uint8_t cmd[SCSI_CMD_BUF_SIZE];
int cmdlen;
uint8_t *buf;
@@ -68,7 +67,6 @@ typedef struct SCSIGenericReq {
struct SCSIGenericState
{
SCSIDevice qdev;
- SCSIGenericReq *requests;
DriveInfo *dinfo;
int type;
int blocksize;
@@ -78,68 +76,36 @@ struct SCSIGenericState
uint8_t senselen;
};
-/* Global pool of SCSIGenericReq structures. */
-static SCSIGenericReq *free_requests = NULL;
-
static SCSIGenericReq *scsi_new_request(SCSIDevice *d, uint32_t tag)
{
- SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
SCSIGenericReq *r;
- if (free_requests) {
- r = free_requests;
- free_requests = r->next;
- } else {
- r = qemu_malloc(sizeof(SCSIGenericReq));
- r->buf = NULL;
- r->buflen = 0;
- }
+ r = qemu_mallocz(sizeof(SCSIGenericReq));
r->req.bus = scsi_bus_from_device(d);
r->req.dev = d;
r->req.tag = tag;
- memset(r->cmd, 0, sizeof(r->cmd));
- memset(&r->io_header, 0, sizeof(r->io_header));
- r->cmdlen = 0;
- r->len = 0;
- r->req.aiocb = NULL;
- /* link */
-
- r->next = s->requests;
- s->requests = r;
+ QTAILQ_INSERT_TAIL(&d->requests, &r->req, next);
return r;
}
static void scsi_remove_request(SCSIGenericReq *r)
{
- SCSIGenericReq *last;
- SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
-
- if (s->requests == r) {
- s->requests = r->next;
- } else {
- last = s->requests;
- while (last && last->next != r)
- last = last->next;
- if (last) {
- last->next = r->next;
- } else {
- BADF("Orphaned request\n");
- }
- }
- r->next = free_requests;
- free_requests = r;
+ qemu_free(r->buf);
+ QTAILQ_REMOVE(&r->req.dev->requests, &r->req, next);
+ qemu_free(r);
}
static SCSIGenericReq *scsi_find_request(SCSIGenericState *s, uint32_t tag)
{
- SCSIGenericReq *r;
-
- r = s->requests;
- while (r && r->req.tag != tag)
- r = r->next;
+ SCSIRequest *req;
- return r;
+ QTAILQ_FOREACH(req, &s->qdev.requests, next) {
+ if (req->tag == tag) {
+ return DO_UPCAST(SCSIGenericReq, req, req);
+ }
+ }
+ return NULL;
}
/* Helper function for command completion. */
@@ -653,22 +619,12 @@ static int get_stream_blocksize(BlockDriverState *bdrv)
static void scsi_destroy(SCSIDevice *d)
{
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
- SCSIGenericReq *r, *n;
-
- r = s->requests;
- while (r) {
- n = r->next;
- qemu_free(r);
- r = n;
- }
+ SCSIGenericReq *r;
- r = free_requests;
- while (r) {
- n = r->next;
- qemu_free(r);
- r = n;
+ while (!QTAILQ_EMPTY(&s->qdev.requests)) {
+ r = DO_UPCAST(SCSIGenericReq, req, QTAILQ_FIRST(&s->qdev.requests));
+ scsi_remove_request(r);
}
-
drive_uninit(s->dinfo);
}
diff --git a/hw/scsi.h b/hw/scsi.h
index 7906877..a9b846c 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -21,6 +21,7 @@ typedef struct SCSIRequest {
SCSIDevice *dev;
uint32_t tag;
BlockDriverAIOCB *aiocb;
+ QTAILQ_ENTRY(SCSIRequest) next;
} SCSIRequest;
struct SCSIDevice
@@ -28,6 +29,7 @@ struct SCSIDevice
DeviceState qdev;
uint32_t id;
SCSIDeviceInfo *info;
+ QTAILQ_HEAD(, SCSIRequest) requests;
};
/* cdrom.c */
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 04/30] scsi: move SCSIRequest management to common code.
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (2 preceding siblings ...)
2009-11-26 14:33 ` [Qemu-devel] [PATCH 03/30] scsi: move request lists to QTAILQ Gerd Hoffmann
@ 2009-11-26 14:33 ` Gerd Hoffmann
2009-11-26 14:33 ` [Qemu-devel] [PATCH 05/30] scsi: move scsi command buffer from SCSIGenericReq to SCSIRequest Gerd Hoffmann
` (25 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Create generic functions to allocate, find and release SCSIRequest
structs. Make scsi-disk and scsi-generic use them.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-bus.c | 31 +++++++++++++++++++++++++++++++
hw/scsi-disk.c | 27 ++++++++-------------------
hw/scsi-generic.c | 29 ++++++++---------------------
hw/scsi.h | 5 +++++
4 files changed, 52 insertions(+), 40 deletions(-)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 801922b..cf445ce 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -111,3 +111,34 @@ void scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
scsi_bus_legacy_add_drive(bus, dinfo, unit);
}
}
+
+SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun)
+{
+ SCSIRequest *req;
+
+ req = qemu_mallocz(size);
+ req->bus = scsi_bus_from_device(d);
+ req->dev = d;
+ req->tag = tag;
+ req->lun = lun;
+ QTAILQ_INSERT_TAIL(&d->requests, req, next);
+ return req;
+}
+
+SCSIRequest *scsi_req_find(SCSIDevice *d, uint32_t tag)
+{
+ SCSIRequest *req;
+
+ QTAILQ_FOREACH(req, &d->requests, next) {
+ if (req->tag == tag) {
+ return req;
+ }
+ }
+ return NULL;
+}
+
+void scsi_req_free(SCSIRequest *req)
+{
+ QTAILQ_REMOVE(&req->dev->requests, req, next);
+ qemu_free(req);
+}
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 997eef6..c18b7f0 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -71,37 +71,26 @@ struct SCSIDiskState
QEMUBH *bh;
};
-static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag)
+static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
{
+ SCSIRequest *req;
SCSIDiskReq *r;
- r = qemu_mallocz(sizeof(SCSIDiskReq));
+ req = scsi_req_alloc(sizeof(SCSIDiskReq), d, tag, lun);
+ r = DO_UPCAST(SCSIDiskReq, req, req);
r->iov.iov_base = qemu_memalign(512, SCSI_DMA_BUF_SIZE);
- r->req.bus = scsi_bus_from_device(d);
- r->req.dev = d;
- r->req.tag = tag;
-
- QTAILQ_INSERT_TAIL(&d->requests, &r->req, next);
return r;
}
static void scsi_remove_request(SCSIDiskReq *r)
{
qemu_free(r->iov.iov_base);
- QTAILQ_REMOVE(&r->req.dev->requests, &r->req, next);
- qemu_free(r);
+ scsi_req_free(&r->req);
}
static SCSIDiskReq *scsi_find_request(SCSIDiskState *s, uint32_t tag)
{
- SCSIRequest *req;
-
- QTAILQ_FOREACH(req, &s->qdev.requests, next) {
- if (req->tag == tag) {
- return DO_UPCAST(SCSIDiskReq, req, req);
- }
- }
- return NULL;
+ return DO_UPCAST(SCSIDiskReq, req, scsi_req_find(&s->qdev, tag));
}
/* Helper function for command completion. */
@@ -113,8 +102,8 @@ static void scsi_command_complete(SCSIDiskReq *r, int status, int sense)
r->req.tag, status, sense);
s->sense = sense;
tag = r->req.tag;
- scsi_remove_request(r);
r->req.bus->complete(r->req.bus, SCSI_REASON_DONE, tag, status);
+ scsi_remove_request(r);
}
/* Cancel a pending data transfer. */
@@ -349,7 +338,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
}
/* ??? Tags are not unique for different luns. We only implement a
single lun, so this should not matter. */
- r = scsi_new_request(d, tag);
+ r = scsi_new_request(d, tag, lun);
outbuf = (uint8_t *)r->iov.iov_base;
is_write = 0;
DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 1fa9d33..f63d83d 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -76,36 +76,23 @@ struct SCSIGenericState
uint8_t senselen;
};
-static SCSIGenericReq *scsi_new_request(SCSIDevice *d, uint32_t tag)
+static SCSIGenericReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
{
- SCSIGenericReq *r;
-
- r = qemu_mallocz(sizeof(SCSIGenericReq));
- r->req.bus = scsi_bus_from_device(d);
- r->req.dev = d;
- r->req.tag = tag;
+ SCSIRequest *req;
- QTAILQ_INSERT_TAIL(&d->requests, &r->req, next);
- return r;
+ req = scsi_req_alloc(sizeof(SCSIGenericReq), d, tag, lun);
+ return DO_UPCAST(SCSIGenericReq, req, req);
}
static void scsi_remove_request(SCSIGenericReq *r)
{
qemu_free(r->buf);
- QTAILQ_REMOVE(&r->req.dev->requests, &r->req, next);
- qemu_free(r);
+ scsi_req_free(&r->req);
}
static SCSIGenericReq *scsi_find_request(SCSIGenericState *s, uint32_t tag)
{
- SCSIRequest *req;
-
- QTAILQ_FOREACH(req, &s->qdev.requests, next) {
- if (req->tag == tag) {
- return DO_UPCAST(SCSIGenericReq, req, req);
- }
- }
- return NULL;
+ return DO_UPCAST(SCSIGenericReq, req, scsi_req_find(&s->qdev, tag));
}
/* Helper function for command completion. */
@@ -136,8 +123,8 @@ static void scsi_command_complete(void *opaque, int ret)
DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
r, r->req.tag, status);
tag = r->req.tag;
- scsi_remove_request(r);
r->req.bus->complete(r->req.bus, SCSI_REASON_DONE, tag, status);
+ scsi_remove_request(r);
}
/* Cancel a pending data transfer. */
@@ -520,7 +507,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
BADF("Tag 0x%x already in use %p\n", tag, r);
scsi_cancel_io(d, tag);
}
- r = scsi_new_request(d, tag);
+ r = scsi_new_request(d, tag, lun);
memcpy(r->cmd, cmd, cmdlen);
r->cmdlen = cmdlen;
diff --git a/hw/scsi.h b/hw/scsi.h
index a9b846c..ceeb26a 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -20,6 +20,7 @@ typedef struct SCSIRequest {
SCSIBus *bus;
SCSIDevice *dev;
uint32_t tag;
+ uint32_t lun;
BlockDriverAIOCB *aiocb;
QTAILQ_ENTRY(SCSIRequest) next;
} SCSIRequest;
@@ -74,4 +75,8 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, DriveInfo *dinfo, int unit);
void scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
+SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun);
+SCSIRequest *scsi_req_find(SCSIDevice *d, uint32_t tag);
+void scsi_req_free(SCSIRequest *req);
+
#endif
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 05/30] scsi: move scsi command buffer from SCSIGenericReq to SCSIRequest.
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (3 preceding siblings ...)
2009-11-26 14:33 ` [Qemu-devel] [PATCH 04/30] scsi: move SCSIRequest management to common code Gerd Hoffmann
@ 2009-11-26 14:33 ` Gerd Hoffmann
2009-11-26 14:33 ` [Qemu-devel] [PATCH 06/30] scsi: move blocksize from SCSIGenericState to SCSIDevice Gerd Hoffmann
` (24 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-generic.c | 15 ++++++---------
hw/scsi.h | 6 ++++++
2 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index f63d83d..ac0b3ec 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -42,7 +42,6 @@ do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
#define SET_CD_SPEED 0xbb
#define BLANK 0xa1
-#define SCSI_CMD_BUF_SIZE 16
#define SCSI_SENSE_BUF_SIZE 96
#define SG_ERR_DRIVER_TIMEOUT 0x06
@@ -56,8 +55,6 @@ typedef struct SCSIGenericState SCSIGenericState;
typedef struct SCSIGenericReq {
SCSIRequest req;
- uint8_t cmd[SCSI_CMD_BUF_SIZE];
- int cmdlen;
uint8_t *buf;
int buflen;
int len;
@@ -153,8 +150,8 @@ static int execute_command(BlockDriverState *bdrv,
r->io_header.dxfer_direction = direction;
r->io_header.dxferp = r->buf;
r->io_header.dxfer_len = r->buflen;
- r->io_header.cmdp = r->cmd;
- r->io_header.cmd_len = r->cmdlen;
+ r->io_header.cmdp = r->req.cmd.buf;
+ r->io_header.cmd_len = r->req.cmd.len;
r->io_header.mx_sb_len = sizeof(s->sensebuf);
r->io_header.sbp = s->sensebuf;
r->io_header.timeout = MAX_UINT;
@@ -210,7 +207,7 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
return;
}
- if (r->cmd[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
+ if (r->req.cmd.buf[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
{
s->senselen = MIN(r->len, s->senselen);
memcpy(r->buf, s->sensebuf, s->senselen);
@@ -245,7 +242,7 @@ static void scsi_write_complete(void * opaque, int ret)
return;
}
- if (r->cmd[0] == MODE_SELECT && r->cmd[4] == 12 &&
+ if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
s->type == TYPE_TAPE) {
s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
DPRINTF("block size %d\n", s->blocksize);
@@ -509,8 +506,8 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
}
r = scsi_new_request(d, tag, lun);
- memcpy(r->cmd, cmd, cmdlen);
- r->cmdlen = cmdlen;
+ memcpy(r->req.cmd.buf, cmd, cmdlen);
+ r->req.cmd.len = cmdlen;
if (len == 0) {
if (r->buf != NULL)
diff --git a/hw/scsi.h b/hw/scsi.h
index ceeb26a..aec9c59 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -4,6 +4,8 @@
#include "qdev.h"
#include "block.h"
+#define SCSI_CMD_BUF_SIZE 16
+
/* scsi-disk.c */
enum scsi_reason {
SCSI_REASON_DONE, /* Command complete. */
@@ -21,6 +23,10 @@ typedef struct SCSIRequest {
SCSIDevice *dev;
uint32_t tag;
uint32_t lun;
+ struct {
+ uint8_t buf[SCSI_CMD_BUF_SIZE];
+ int len;
+ } cmd;
BlockDriverAIOCB *aiocb;
QTAILQ_ENTRY(SCSIRequest) next;
} SCSIRequest;
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 06/30] scsi: move blocksize from SCSIGenericState to SCSIDevice
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (4 preceding siblings ...)
2009-11-26 14:33 ` [Qemu-devel] [PATCH 05/30] scsi: move scsi command buffer from SCSIGenericReq to SCSIRequest Gerd Hoffmann
@ 2009-11-26 14:33 ` Gerd Hoffmann
2009-11-26 14:33 ` [Qemu-devel] [PATCH 07/30] scsi: add scsi-defs.h Gerd Hoffmann
` (23 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-disk.c | 1 +
hw/scsi-generic.c | 23 +++++++++++------------
hw/scsi.h | 1 +
3 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index c18b7f0..0a8b8bb 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -944,6 +944,7 @@ static int scsi_disk_initfn(SCSIDevice *dev)
} else {
s->cluster_size = 1;
}
+ s->qdev.blocksize = 512 * s->cluster_size;
bdrv_get_geometry(s->dinfo->bdrv, &nb_sectors);
nb_sectors /= s->cluster_size;
if (nb_sectors)
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index ac0b3ec..a925caa 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -66,7 +66,6 @@ struct SCSIGenericState
SCSIDevice qdev;
DriveInfo *dinfo;
int type;
- int blocksize;
int lun;
int driver_status;
uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
@@ -244,7 +243,7 @@ static void scsi_write_complete(void * opaque, int ret)
if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
s->type == TYPE_TAPE) {
- s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
+ s->qdev.blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
DPRINTF("block size %d\n", s->blocksize);
}
@@ -467,12 +466,12 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
int ret;
if (s->type == TYPE_TAPE) {
- if (scsi_stream_length(cmd, s->blocksize, &cmdlen, &len) == -1) {
+ if (scsi_stream_length(cmd, s->qdev.blocksize, &cmdlen, &len) == -1) {
BADF("Unsupported command length, command %x\n", cmd[0]);
return 0;
}
} else {
- if (scsi_length(cmd, s->blocksize, &cmdlen, &len) == -1) {
+ if (scsi_length(cmd, s->qdev.blocksize, &cmdlen, &len) == -1) {
BADF("Unsupported command length, command %x\n", cmd[0]);
return 0;
}
@@ -648,20 +647,20 @@ static int scsi_generic_initfn(SCSIDevice *dev)
s->type = scsiid.scsi_type;
DPRINTF("device type %d\n", s->type);
if (s->type == TYPE_TAPE) {
- s->blocksize = get_stream_blocksize(s->dinfo->bdrv);
- if (s->blocksize == -1)
- s->blocksize = 0;
+ s->qdev.blocksize = get_stream_blocksize(s->dinfo->bdrv);
+ if (s->qdev.blocksize == -1)
+ s->qdev.blocksize = 0;
} else {
- s->blocksize = get_blocksize(s->dinfo->bdrv);
+ s->qdev.blocksize = get_blocksize(s->dinfo->bdrv);
/* removable media returns 0 if not present */
- if (s->blocksize <= 0) {
+ if (s->qdev.blocksize <= 0) {
if (s->type == TYPE_ROM || s->type == TYPE_WORM)
- s->blocksize = 2048;
+ s->qdev.blocksize = 2048;
else
- s->blocksize = 512;
+ s->qdev.blocksize = 512;
}
}
- DPRINTF("block size %d\n", s->blocksize);
+ DPRINTF("block size %d\n", s->qdev.blocksize);
s->driver_status = 0;
memset(s->sensebuf, 0, sizeof(s->sensebuf));
return 0;
diff --git a/hw/scsi.h b/hw/scsi.h
index aec9c59..5eb5682 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -37,6 +37,7 @@ struct SCSIDevice
uint32_t id;
SCSIDeviceInfo *info;
QTAILQ_HEAD(, SCSIRequest) requests;
+ int blocksize;
};
/* cdrom.c */
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 07/30] scsi: add scsi-defs.h
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (5 preceding siblings ...)
2009-11-26 14:33 ` [Qemu-devel] [PATCH 06/30] scsi: move blocksize from SCSIGenericState to SCSIDevice Gerd Hoffmann
@ 2009-11-26 14:33 ` Gerd Hoffmann
2009-11-26 14:33 ` [Qemu-devel] [PATCH 08/30] scsi: move type from SCSIGenericState to SCSIDevice Gerd Hoffmann
` (22 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Largely based on <scsi/scsi.h> from linux. Added into the tree so we
can use the defines everywhere, not just in scsi-generic.c (which is
linux-specific).
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-defs.h | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/scsi-disk.c | 41 ++++++--------
hw/scsi-generic.c | 8 +---
3 files changed, 174 insertions(+), 31 deletions(-)
create mode 100644 hw/scsi-defs.h
diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
new file mode 100644
index 0000000..1701521
--- /dev/null
+++ b/hw/scsi-defs.h
@@ -0,0 +1,156 @@
+/* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/*
+ * This header file contains public constants and structures used by
+ * the scsi code for linux.
+ */
+
+/*
+ * SCSI opcodes
+ */
+
+#define TEST_UNIT_READY 0x00
+#define REZERO_UNIT 0x01
+#define REQUEST_SENSE 0x03
+#define FORMAT_UNIT 0x04
+#define READ_BLOCK_LIMITS 0x05
+#define REASSIGN_BLOCKS 0x07
+#define READ_6 0x08
+#define WRITE_6 0x0a
+#define SEEK_6 0x0b
+#define READ_REVERSE 0x0f
+#define WRITE_FILEMARKS 0x10
+#define SPACE 0x11
+#define INQUIRY 0x12
+#define RECOVER_BUFFERED_DATA 0x14
+#define MODE_SELECT 0x15
+#define RESERVE 0x16
+#define RELEASE 0x17
+#define COPY 0x18
+#define ERASE 0x19
+#define MODE_SENSE 0x1a
+#define START_STOP 0x1b
+#define RECEIVE_DIAGNOSTIC 0x1c
+#define SEND_DIAGNOSTIC 0x1d
+#define ALLOW_MEDIUM_REMOVAL 0x1e
+
+#define SET_WINDOW 0x24
+#define READ_CAPACITY 0x25
+#define READ_10 0x28
+#define WRITE_10 0x2a
+#define SEEK_10 0x2b
+#define WRITE_VERIFY 0x2e
+#define VERIFY 0x2f
+#define SEARCH_HIGH 0x30
+#define SEARCH_EQUAL 0x31
+#define SEARCH_LOW 0x32
+#define SET_LIMITS 0x33
+#define PRE_FETCH 0x34
+#define READ_POSITION 0x34
+#define SYNCHRONIZE_CACHE 0x35
+#define LOCK_UNLOCK_CACHE 0x36
+#define READ_DEFECT_DATA 0x37
+#define MEDIUM_SCAN 0x38
+#define COMPARE 0x39
+#define COPY_VERIFY 0x3a
+#define WRITE_BUFFER 0x3b
+#define READ_BUFFER 0x3c
+#define UPDATE_BLOCK 0x3d
+#define READ_LONG 0x3e
+#define WRITE_LONG 0x3f
+#define CHANGE_DEFINITION 0x40
+#define WRITE_SAME 0x41
+#define READ_TOC 0x43
+#define LOG_SELECT 0x4c
+#define LOG_SENSE 0x4d
+#define MODE_SELECT_10 0x55
+#define RESERVE_10 0x56
+#define RELEASE_10 0x57
+#define MODE_SENSE_10 0x5a
+#define PERSISTENT_RESERVE_IN 0x5e
+#define PERSISTENT_RESERVE_OUT 0x5f
+#define MOVE_MEDIUM 0xa5
+#define READ_12 0xa8
+#define WRITE_12 0xaa
+#define WRITE_VERIFY_12 0xae
+#define SEARCH_HIGH_12 0xb0
+#define SEARCH_EQUAL_12 0xb1
+#define SEARCH_LOW_12 0xb2
+#define READ_ELEMENT_STATUS 0xb8
+#define SEND_VOLUME_TAG 0xb6
+#define WRITE_LONG_2 0xea
+
+/* from hw/scsi-generic.c */
+#define REWIND 0x01
+#define REPORT_DENSITY_SUPPORT 0x44
+#define LOAD_UNLOAD 0xa6
+#define SET_CD_SPEED 0xbb
+#define BLANK 0xa1
+
+/*
+ * Status codes
+ */
+
+#define GOOD 0x00
+#define CHECK_CONDITION 0x01
+#define CONDITION_GOOD 0x02
+#define BUSY 0x04
+#define INTERMEDIATE_GOOD 0x08
+#define INTERMEDIATE_C_GOOD 0x0a
+#define RESERVATION_CONFLICT 0x0c
+#define COMMAND_TERMINATED 0x11
+#define QUEUE_FULL 0x14
+
+#define STATUS_MASK 0x3e
+
+/*
+ * SENSE KEYS
+ */
+
+#define NO_SENSE 0x00
+#define RECOVERED_ERROR 0x01
+#define NOT_READY 0x02
+#define MEDIUM_ERROR 0x03
+#define HARDWARE_ERROR 0x04
+#define ILLEGAL_REQUEST 0x05
+#define UNIT_ATTENTION 0x06
+#define DATA_PROTECT 0x07
+#define BLANK_CHECK 0x08
+#define COPY_ABORTED 0x0a
+#define ABORTED_COMMAND 0x0b
+#define VOLUME_OVERFLOW 0x0d
+#define MISCOMPARE 0x0e
+
+
+/*
+ * DEVICE TYPES
+ */
+
+#define TYPE_DISK 0x00
+#define TYPE_TAPE 0x01
+#define TYPE_PROCESSOR 0x03 /* HP scanners use this */
+#define TYPE_WORM 0x04 /* Treated as ROM by our system */
+#define TYPE_ROM 0x05
+#define TYPE_SCANNER 0x06
+#define TYPE_MOD 0x07 /* Magneto-optical disk -
+ * - treated as TYPE_DISK */
+#define TYPE_MEDIUM_CHANGER 0x08
+#define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */
+#define TYPE_NO_LUN 0x7f
+
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 0a8b8bb..b0eceaf 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -30,14 +30,7 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
#include "qemu-common.h"
#include "block.h"
#include "scsi.h"
-
-#define SENSE_NO_SENSE 0
-#define SENSE_NOT_READY 2
-#define SENSE_HARDWARE_ERROR 4
-#define SENSE_ILLEGAL_REQUEST 5
-
-#define STATUS_GOOD 0
-#define STATUS_CHECK_CONDITION 2
+#include "scsi-defs.h"
#define SCSI_DMA_BUF_SIZE 131072
#define SCSI_MAX_INQUIRY_LEN 256
@@ -128,7 +121,7 @@ static void scsi_read_complete(void * opaque, int ret)
if (ret) {
DPRINTF("IO error\n");
r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0);
- scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NO_SENSE);
+ scsi_command_complete(r, CHECK_CONDITION, NO_SENSE);
return;
}
DPRINTF("Data ready tag=0x%x len=%" PRId64 "\n", r->req.tag, r->iov.iov_len);
@@ -147,7 +140,7 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
if (!r) {
BADF("Bad read tag 0x%x\n", tag);
/* ??? This is the wrong error. */
- scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
+ scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
return;
}
if (r->sector_count == (uint32_t)-1) {
@@ -158,7 +151,7 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
}
DPRINTF("Read sector_count=%d\n", r->sector_count);
if (r->sector_count == 0) {
- scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE);
+ scsi_command_complete(r, GOOD, NO_SENSE);
return;
}
@@ -171,7 +164,7 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
r->req.aiocb = bdrv_aio_readv(s->dinfo->bdrv, r->sector, &r->qiov, n,
scsi_read_complete, r);
if (r->req.aiocb == NULL)
- scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
+ scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
r->sector += n;
r->sector_count -= n;
}
@@ -189,8 +182,8 @@ static int scsi_handle_write_error(SCSIDiskReq *r, int error)
r->status |= SCSI_REQ_STATUS_RETRY;
vm_stop(0);
} else {
- scsi_command_complete(r, STATUS_CHECK_CONDITION,
- SENSE_HARDWARE_ERROR);
+ scsi_command_complete(r, CHECK_CONDITION,
+ HARDWARE_ERROR);
}
return 1;
@@ -213,7 +206,7 @@ static void scsi_write_complete(void * opaque, int ret)
r->sector += n;
r->sector_count -= n;
if (r->sector_count == 0) {
- scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE);
+ scsi_command_complete(r, GOOD, NO_SENSE);
} else {
len = r->sector_count * 512;
if (len > SCSI_DMA_BUF_SIZE) {
@@ -236,8 +229,8 @@ static void scsi_write_request(SCSIDiskReq *r)
r->req.aiocb = bdrv_aio_writev(s->dinfo->bdrv, r->sector, &r->qiov, n,
scsi_write_complete, r);
if (r->req.aiocb == NULL)
- scsi_command_complete(r, STATUS_CHECK_CONDITION,
- SENSE_HARDWARE_ERROR);
+ scsi_command_complete(r, CHECK_CONDITION,
+ HARDWARE_ERROR);
} else {
/* Invoke completion routine to fetch data from host. */
scsi_write_complete(r, 0);
@@ -255,7 +248,7 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag)
r = scsi_find_request(s, tag);
if (!r) {
BADF("Bad write tag 0x%x\n", tag);
- scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
+ scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
return 1;
}
@@ -401,7 +394,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
goto fail;
memset(outbuf, 0, 4);
r->iov.iov_len = 4;
- if (s->sense == SENSE_NOT_READY && len >= 18) {
+ if (s->sense == NOT_READY && len >= 18) {
memset(outbuf, 0, 18);
r->iov.iov_len = 18;
outbuf[7] = 10;
@@ -767,7 +760,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
r->iov.iov_len = 8;
} else {
notready:
- scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NOT_READY);
+ scsi_command_complete(r, CHECK_CONDITION, NOT_READY);
return 0;
}
break;
@@ -877,7 +870,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
/* Protection, exponent and lowest lba field left blank. */
r->iov.iov_len = len;
} else {
- scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NOT_READY);
+ scsi_command_complete(r, CHECK_CONDITION, NOT_READY);
return 0;
}
break;
@@ -898,14 +891,14 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
default:
DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
fail:
- scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_ILLEGAL_REQUEST);
+ scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST);
return 0;
illegal_lba:
- scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
+ scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
return 0;
}
if (r->sector_count == 0 && r->iov.iov_len == 0) {
- scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE);
+ scsi_command_complete(r, GOOD, NO_SENSE);
}
len = r->sector_count * 512 + r->iov.iov_len;
if (is_write) {
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index a925caa..834d2d8 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -34,13 +34,7 @@ do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
#include <sys/stat.h>
#include <unistd.h>
#include <scsi/sg.h>
-#include <scsi/scsi.h>
-
-#define REWIND 0x01
-#define REPORT_DENSITY_SUPPORT 0x44
-#define LOAD_UNLOAD 0xa6
-#define SET_CD_SPEED 0xbb
-#define BLANK 0xa1
+#include "scsi-defs.h"
#define SCSI_SENSE_BUF_SIZE 96
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 08/30] scsi: move type from SCSIGenericState to SCSIDevice
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (6 preceding siblings ...)
2009-11-26 14:33 ` [Qemu-devel] [PATCH 07/30] scsi: add scsi-defs.h Gerd Hoffmann
@ 2009-11-26 14:33 ` Gerd Hoffmann
2009-11-26 14:33 ` [Qemu-devel] [PATCH 09/30] scsi: add request parsing helpers to common code Gerd Hoffmann
` (21 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-disk.c | 1 +
hw/scsi-generic.c | 13 ++++++-------
hw/scsi.h | 1 +
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index b0eceaf..6b5674b 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -938,6 +938,7 @@ static int scsi_disk_initfn(SCSIDevice *dev)
s->cluster_size = 1;
}
s->qdev.blocksize = 512 * s->cluster_size;
+ s->qdev.type = TYPE_DISK;
bdrv_get_geometry(s->dinfo->bdrv, &nb_sectors);
nb_sectors /= s->cluster_size;
if (nb_sectors)
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 834d2d8..20e1044 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -59,7 +59,6 @@ struct SCSIGenericState
{
SCSIDevice qdev;
DriveInfo *dinfo;
- int type;
int lun;
int driver_status;
uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
@@ -236,7 +235,7 @@ static void scsi_write_complete(void * opaque, int ret)
}
if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
- s->type == TYPE_TAPE) {
+ 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->blocksize);
}
@@ -459,7 +458,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
SCSIBus *bus;
int ret;
- if (s->type == TYPE_TAPE) {
+ if (s->qdev.type == TYPE_TAPE) {
if (scsi_stream_length(cmd, s->qdev.blocksize, &cmdlen, &len) == -1) {
BADF("Unsupported command length, command %x\n", cmd[0]);
return 0;
@@ -638,9 +637,9 @@ static int scsi_generic_initfn(SCSIDevice *dev)
/* define device state */
s->lun = scsiid.lun;
DPRINTF("LUN %d\n", s->lun);
- s->type = scsiid.scsi_type;
- DPRINTF("device type %d\n", s->type);
- if (s->type == TYPE_TAPE) {
+ 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->dinfo->bdrv);
if (s->qdev.blocksize == -1)
s->qdev.blocksize = 0;
@@ -648,7 +647,7 @@ static int scsi_generic_initfn(SCSIDevice *dev)
s->qdev.blocksize = get_blocksize(s->dinfo->bdrv);
/* removable media returns 0 if not present */
if (s->qdev.blocksize <= 0) {
- if (s->type == TYPE_ROM || s->type == TYPE_WORM)
+ if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM)
s->qdev.blocksize = 2048;
else
s->qdev.blocksize = 512;
diff --git a/hw/scsi.h b/hw/scsi.h
index 5eb5682..95838a4 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -38,6 +38,7 @@ struct SCSIDevice
SCSIDeviceInfo *info;
QTAILQ_HEAD(, SCSIRequest) requests;
int blocksize;
+ int type;
};
/* cdrom.c */
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 09/30] scsi: add request parsing helpers to common code.
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (7 preceding siblings ...)
2009-11-26 14:33 ` [Qemu-devel] [PATCH 08/30] scsi: move type from SCSIGenericState to SCSIDevice Gerd Hoffmann
@ 2009-11-26 14:33 ` Gerd Hoffmann
2009-11-26 14:33 ` [Qemu-devel] [PATCH 10/30] scsi: use command defines in scsi-disk.c Gerd Hoffmann
` (20 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Add helper functions for scsi request parsing to common code. Getting
command length, transfer size, and linear block address is handled.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-bus.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/scsi-generic.c | 156 ++++++++------------------------------------------
hw/scsi.h | 3 +
3 files changed, 191 insertions(+), 132 deletions(-)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index cf445ce..1580d60 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -1,6 +1,7 @@
#include "hw.h"
#include "sysemu.h"
#include "scsi.h"
+#include "scsi-defs.h"
#include "block.h"
#include "qdev.h"
@@ -142,3 +143,166 @@ void scsi_req_free(SCSIRequest *req)
QTAILQ_REMOVE(&req->dev->requests, req, next);
qemu_free(req);
}
+
+static int scsi_req_length(SCSIRequest *req, uint8_t *cmd)
+{
+ switch (cmd[0] >> 5) {
+ case 0:
+ req->cmd.xfer = cmd[4];
+ req->cmd.len = 6;
+ /* length 0 means 256 blocks */
+ if (req->cmd.xfer == 0)
+ req->cmd.xfer = 256;
+ break;
+ case 1:
+ case 2:
+ req->cmd.xfer = cmd[8] | (cmd[7] << 8);
+ req->cmd.len = 10;
+ break;
+ case 4:
+ req->cmd.xfer = cmd[13] | (cmd[12] << 8) | (cmd[11] << 16) | (cmd[10] << 24);
+ req->cmd.len = 16;
+ break;
+ case 5:
+ req->cmd.xfer = cmd[9] | (cmd[8] << 8) | (cmd[7] << 16) | (cmd[6] << 24);
+ req->cmd.len = 12;
+ break;
+ default:
+ return -1;
+ }
+
+ switch(cmd[0]) {
+ case TEST_UNIT_READY:
+ case REZERO_UNIT:
+ case START_STOP:
+ case SEEK_6:
+ case WRITE_FILEMARKS:
+ case SPACE:
+ case ERASE:
+ case ALLOW_MEDIUM_REMOVAL:
+ case VERIFY:
+ case SEEK_10:
+ case SYNCHRONIZE_CACHE:
+ case LOCK_UNLOCK_CACHE:
+ case LOAD_UNLOAD:
+ case SET_CD_SPEED:
+ case SET_LIMITS:
+ case WRITE_LONG:
+ case MOVE_MEDIUM:
+ case UPDATE_BLOCK:
+ req->cmd.xfer = 0;
+ break;
+ case MODE_SENSE:
+ break;
+ case WRITE_SAME:
+ req->cmd.xfer = 1;
+ break;
+ case READ_CAPACITY:
+ req->cmd.xfer = 8;
+ break;
+ case READ_BLOCK_LIMITS:
+ req->cmd.xfer = 6;
+ break;
+ case READ_POSITION:
+ req->cmd.xfer = 20;
+ break;
+ case SEND_VOLUME_TAG:
+ req->cmd.xfer *= 40;
+ break;
+ case MEDIUM_SCAN:
+ req->cmd.xfer *= 8;
+ break;
+ case WRITE_10:
+ case WRITE_VERIFY:
+ case WRITE_6:
+ case WRITE_12:
+ case WRITE_VERIFY_12:
+ req->cmd.xfer *= req->dev->blocksize;
+ break;
+ case READ_10:
+ case READ_6:
+ case READ_REVERSE:
+ case RECOVER_BUFFERED_DATA:
+ case READ_12:
+ req->cmd.xfer *= req->dev->blocksize;
+ break;
+ case INQUIRY:
+ req->cmd.xfer = cmd[4] | (cmd[3] << 8);
+ break;
+ }
+ return 0;
+}
+
+static int scsi_req_stream_length(SCSIRequest *req, uint8_t *cmd)
+{
+ switch(cmd[0]) {
+ /* stream commands */
+ case READ_6:
+ case READ_REVERSE:
+ case RECOVER_BUFFERED_DATA:
+ case WRITE_6:
+ req->cmd.len = 6;
+ req->cmd.xfer = cmd[4] | (cmd[3] << 8) | (cmd[2] << 16);
+ if (cmd[1] & 0x01) /* fixed */
+ req->cmd.xfer *= req->dev->blocksize;
+ break;
+ case REWIND:
+ case START_STOP:
+ req->cmd.len = 6;
+ req->cmd.xfer = 0;
+ break;
+ /* generic commands */
+ default:
+ return scsi_req_length(req, cmd);
+ }
+ return 0;
+}
+
+static uint64_t scsi_req_lba(SCSIRequest *req)
+{
+ uint8_t *buf = req->cmd.buf;
+ uint64_t lba;
+
+ switch (buf[0] >> 5) {
+ case 0:
+ lba = (uint64_t) buf[3] | ((uint64_t) buf[2] << 8) |
+ (((uint64_t) buf[1] & 0x1f) << 16);
+ break;
+ case 1:
+ case 2:
+ lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
+ ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
+ break;
+ case 4:
+ lba = (uint64_t) buf[9] | ((uint64_t) buf[8] << 8) |
+ ((uint64_t) buf[7] << 16) | ((uint64_t) buf[6] << 24) |
+ ((uint64_t) buf[5] << 32) | ((uint64_t) buf[4] << 40) |
+ ((uint64_t) buf[3] << 48) | ((uint64_t) buf[2] << 56);
+ break;
+ case 5:
+ lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
+ ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
+ break;
+ default:
+ lba = -1;
+
+ }
+ return lba;
+}
+
+int scsi_req_parse(SCSIRequest *req, uint8_t *buf)
+{
+ int rc;
+
+ if (req->dev->type == TYPE_TAPE) {
+ rc = scsi_req_stream_length(req, buf);
+ } else {
+ rc = scsi_req_length(req, buf);
+ }
+ if (rc != 0)
+ return rc;
+
+ memcpy(req->cmd.buf, buf, req->cmd.len);
+ req->cmd.lba = scsi_req_lba(req);
+ return 0;
+}
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 20e1044..3c7feac 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -288,121 +288,23 @@ static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
return r->buf;
}
-static int scsi_length(uint8_t *cmd, int blocksize, int *cmdlen, uint32_t *len)
+static void scsi_req_fixup(SCSIRequest *req)
{
- switch (cmd[0] >> 5) {
- case 0:
- *len = cmd[4];
- *cmdlen = 6;
- /* length 0 means 256 blocks */
- if (*len == 0)
- *len = 256;
- break;
- case 1:
- case 2:
- *len = cmd[8] | (cmd[7] << 8);
- *cmdlen = 10;
- break;
- case 4:
- *len = cmd[13] | (cmd[12] << 8) | (cmd[11] << 16) | (cmd[10] << 24);
- *cmdlen = 16;
- break;
- case 5:
- *len = cmd[9] | (cmd[8] << 8) | (cmd[7] << 16) | (cmd[6] << 24);
- *cmdlen = 12;
- break;
- default:
- return -1;
- }
-
- switch(cmd[0]) {
- case TEST_UNIT_READY:
- case REZERO_UNIT:
- case START_STOP:
- case SEEK_6:
- case WRITE_FILEMARKS:
- case SPACE:
- case ERASE:
- case ALLOW_MEDIUM_REMOVAL:
- case VERIFY:
- case SEEK_10:
- case SYNCHRONIZE_CACHE:
- case LOCK_UNLOCK_CACHE:
- case LOAD_UNLOAD:
- case SET_CD_SPEED:
- case SET_LIMITS:
- case WRITE_LONG:
- case MOVE_MEDIUM:
- case UPDATE_BLOCK:
- *len = 0;
- break;
- case MODE_SENSE:
- break;
- case WRITE_SAME:
- *len = 1;
- break;
- case READ_CAPACITY:
- *len = 8;
- break;
- case READ_BLOCK_LIMITS:
- *len = 6;
- break;
- case READ_POSITION:
- *len = 20;
- break;
- case SEND_VOLUME_TAG:
- *len *= 40;
- break;
- case MEDIUM_SCAN:
- *len *= 8;
- break;
+ switch(req->cmd.buf[0]) {
case WRITE_10:
- cmd[1] &= ~0x08; /* disable FUA */
- case WRITE_VERIFY:
- case WRITE_6:
- case WRITE_12:
- case WRITE_VERIFY_12:
- *len *= blocksize;
+ req->cmd.buf[1] &= ~0x08; /* disable FUA */
break;
case READ_10:
- cmd[1] &= ~0x08; /* disable FUA */
- case READ_6:
- case READ_REVERSE:
- case RECOVER_BUFFERED_DATA:
- case READ_12:
- *len *= blocksize;
- break;
- case INQUIRY:
- *len = cmd[4] | (cmd[3] << 8);
- break;
- }
- return 0;
-}
-
-static int scsi_stream_length(uint8_t *cmd, int blocksize, int *cmdlen, uint32_t *len)
-{
- switch(cmd[0]) {
- /* stream commands */
- case READ_6:
- case READ_REVERSE:
- case RECOVER_BUFFERED_DATA:
- case WRITE_6:
- *cmdlen = 6;
- *len = cmd[4] | (cmd[3] << 8) | (cmd[2] << 16);
- if (cmd[1] & 0x01) /* fixed */
- *len *= blocksize;
+ req->cmd.buf[1] &= ~0x08; /* disable FUA */
break;
case REWIND:
case START_STOP:
- *cmdlen = 6;
- *len = 0;
- cmd[1] = 0x01; /* force IMMED, otherwise qemu waits end of command */
+ if (req->dev->type == TYPE_TAPE) {
+ /* force IMMED, otherwise qemu waits end of command */
+ req->cmd.buf[1] = 0x01;
+ }
break;
- /* generic commands */
- default:
- return scsi_length(cmd, blocksize, cmdlen, len);
}
- return 0;
}
static int is_write(int command)
@@ -452,27 +354,10 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
uint8_t *cmd, int lun)
{
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
- uint32_t len=0;
- int cmdlen=0;
SCSIGenericReq *r;
SCSIBus *bus;
int ret;
- if (s->qdev.type == TYPE_TAPE) {
- if (scsi_stream_length(cmd, s->qdev.blocksize, &cmdlen, &len) == -1) {
- BADF("Unsupported command length, command %x\n", cmd[0]);
- return 0;
- }
- } else {
- if (scsi_length(cmd, s->qdev.blocksize, &cmdlen, &len) == -1) {
- BADF("Unsupported command length, command %x\n", cmd[0]);
- return 0;
- }
- }
-
- DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun, tag,
- cmd[0], len);
-
if (cmd[0] != REQUEST_SENSE &&
(lun != s->lun || (cmd[1] >> 5) != s->lun)) {
DPRINTF("Unimplemented LUN %d\n", lun ? lun : cmd[1] >> 5);
@@ -498,10 +383,17 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
}
r = scsi_new_request(d, tag, lun);
- memcpy(r->req.cmd.buf, cmd, cmdlen);
- r->req.cmd.len = cmdlen;
+ if (-1 == scsi_req_parse(&r->req, cmd)) {
+ BADF("Unsupported command length, command %x\n", cmd[0]);
+ scsi_remove_request(r);
+ return 0;
+ }
+ scsi_req_fixup(&r->req);
+
+ DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun, tag,
+ cmd[0], r->req.cmd.xfer);
- if (len == 0) {
+ if (r->req.cmd.xfer == 0) {
if (r->buf != NULL)
free(r->buf);
r->buflen = 0;
@@ -514,21 +406,21 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
return 0;
}
- if (r->buflen != len) {
+ if (r->buflen != r->req.cmd.xfer) {
if (r->buf != NULL)
free(r->buf);
- r->buf = qemu_malloc(len);
- r->buflen = len;
+ r->buf = qemu_malloc(r->req.cmd.xfer);
+ r->buflen = r->req.cmd.xfer;
}
memset(r->buf, 0, r->buflen);
- r->len = len;
+ r->len = r->req.cmd.xfer;
if (is_write(cmd[0])) {
r->len = 0;
- return -len;
+ return -r->req.cmd.xfer;
}
- return len;
+ return r->req.cmd.xfer;
}
static int get_blocksize(BlockDriverState *bdrv)
diff --git a/hw/scsi.h b/hw/scsi.h
index 95838a4..8c64067 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -26,6 +26,8 @@ typedef struct SCSIRequest {
struct {
uint8_t buf[SCSI_CMD_BUF_SIZE];
int len;
+ size_t xfer;
+ uint64_t lba;
} cmd;
BlockDriverAIOCB *aiocb;
QTAILQ_ENTRY(SCSIRequest) next;
@@ -86,5 +88,6 @@ void scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun);
SCSIRequest *scsi_req_find(SCSIDevice *d, uint32_t tag);
void scsi_req_free(SCSIRequest *req);
+int scsi_req_parse(SCSIRequest *req, uint8_t *buf);
#endif
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 10/30] scsi: use command defines in scsi-disk.c
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (8 preceding siblings ...)
2009-11-26 14:33 ` [Qemu-devel] [PATCH 09/30] scsi: add request parsing helpers to common code Gerd Hoffmann
@ 2009-11-26 14:33 ` Gerd Hoffmann
2009-11-26 14:33 ` [Qemu-devel] [PATCH 11/30] scsi: add xfer mode Gerd Hoffmann
` (19 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-disk.c | 40 ++++++++++++++++++++--------------------
1 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 6b5674b..4e92910 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -379,16 +379,16 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
if (lun || buf[1] >> 5) {
/* Only LUN 0 supported. */
DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
- if (command != 0x03 && command != 0x12) /* REQUEST SENSE and INQUIRY */
+ if (command != REQUEST_SENSE && command != INQUIRY)
goto fail;
}
switch (command) {
- case 0x0:
+ case TEST_UNIT_READY:
DPRINTF("Test Unit Ready\n");
if (!bdrv_is_inserted(s->dinfo->bdrv))
goto notready;
break;
- case 0x03:
+ case REQUEST_SENSE:
DPRINTF("Request Sense (len %d)\n", len);
if (len < 4)
goto fail;
@@ -406,7 +406,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
outbuf[1] = 0;
outbuf[2] = s->sense;
break;
- case 0x12:
+ case INQUIRY:
DPRINTF("Inquiry (len %d)\n", len);
if (buf[1] & 0x2) {
/* Command support data - optional, not implemented */
@@ -562,18 +562,18 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
outbuf[7] = 0x10 | (r->req.bus->tcq ? 0x02 : 0);
r->iov.iov_len = len;
break;
- case 0x16:
+ case RESERVE:
DPRINTF("Reserve(6)\n");
if (buf[1] & 1)
goto fail;
break;
- case 0x17:
+ case RELEASE:
DPRINTF("Release(6)\n");
if (buf[1] & 1)
goto fail;
break;
- case 0x1a:
- case 0x5a:
+ case MODE_SENSE:
+ case MODE_SENSE_10:
{
uint8_t *p;
int page;
@@ -724,18 +724,18 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
r->iov.iov_len = len;
}
break;
- case 0x1b:
+ case START_STOP:
DPRINTF("Start Stop Unit\n");
if (bdrv_get_type_hint(s->dinfo->bdrv) == BDRV_TYPE_CDROM &&
(buf[4] & 2))
/* load/eject medium */
bdrv_eject(s->dinfo->bdrv, !(buf[4] & 1));
break;
- case 0x1e:
+ case ALLOW_MEDIUM_REMOVAL:
DPRINTF("Prevent Allow Medium Removal (prevent = %d)\n", buf[4] & 3);
bdrv_set_locked(s->dinfo->bdrv, buf[4] & 1);
break;
- case 0x25:
+ case READ_CAPACITY:
DPRINTF("Read Capacity\n");
/* The normal LEN field for this command is zero. */
memset(outbuf, 0, 8);
@@ -764,8 +764,8 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
return 0;
}
break;
- case 0x08:
- case 0x28:
+ case READ_6:
+ case READ_10:
case 0x88:
DPRINTF("Read (sector %" PRId64 ", count %d)\n", lba, len);
if (lba > s->max_lba)
@@ -773,8 +773,8 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
r->sector = lba * s->cluster_size;
r->sector_count = len * s->cluster_size;
break;
- case 0x0a:
- case 0x2a:
+ case WRITE_6:
+ case WRITE_10:
case 0x8a:
DPRINTF("Write (sector %" PRId64 ", count %d)\n", lba, len);
if (lba > s->max_lba)
@@ -783,11 +783,11 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
r->sector_count = len * s->cluster_size;
is_write = 1;
break;
- case 0x35:
+ case SYNCHRONIZE_CACHE:
DPRINTF("Synchronise cache (sector %" PRId64 ", count %d)\n", lba, len);
bdrv_flush(s->dinfo->bdrv);
break;
- case 0x43:
+ case READ_TOC:
{
int start_track, format, msf, toclen;
@@ -833,12 +833,12 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
outbuf[7] = 8; // CD-ROM
r->iov.iov_len = 8;
break;
- case 0x56:
+ case RESERVE_10:
DPRINTF("Reserve(10)\n");
if (buf[1] & 3)
goto fail;
break;
- case 0x57:
+ case RELEASE_10:
DPRINTF("Release(10)\n");
if (buf[1] & 3)
goto fail;
@@ -885,7 +885,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
outbuf[3] = 8;
r->iov.iov_len = 16;
break;
- case 0x2f:
+ case VERIFY:
DPRINTF("Verify (sector %" PRId64 ", count %d)\n", lba, len);
break;
default:
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 11/30] scsi: add xfer mode
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (9 preceding siblings ...)
2009-11-26 14:33 ` [Qemu-devel] [PATCH 10/30] scsi: use command defines in scsi-disk.c Gerd Hoffmann
@ 2009-11-26 14:33 ` Gerd Hoffmann
2009-11-26 14:33 ` [Qemu-devel] [PATCH 12/30] scsi: move sense to SCSIDevice, create SCSISense struct Gerd Hoffmann
` (18 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-bus.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
hw/scsi-generic.c | 40 +---------------------------------------
hw/scsi.h | 7 +++++++
3 files changed, 54 insertions(+), 39 deletions(-)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 1580d60..e250e4f 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -258,6 +258,51 @@ static int scsi_req_stream_length(SCSIRequest *req, uint8_t *cmd)
return 0;
}
+static void scsi_req_xfer_mode(SCSIRequest *req)
+{
+ switch (req->cmd.buf[0]) {
+ case WRITE_6:
+ case WRITE_10:
+ case WRITE_VERIFY:
+ case WRITE_12:
+ case WRITE_VERIFY_12:
+ case COPY:
+ case COPY_VERIFY:
+ case COMPARE:
+ case CHANGE_DEFINITION:
+ case LOG_SELECT:
+ case MODE_SELECT:
+ case MODE_SELECT_10:
+ case SEND_DIAGNOSTIC:
+ case WRITE_BUFFER:
+ case FORMAT_UNIT:
+ case REASSIGN_BLOCKS:
+ case RESERVE:
+ case SEARCH_EQUAL:
+ case SEARCH_HIGH:
+ case SEARCH_LOW:
+ case UPDATE_BLOCK:
+ case WRITE_LONG:
+ case WRITE_SAME:
+ case SEARCH_HIGH_12:
+ case SEARCH_EQUAL_12:
+ case SEARCH_LOW_12:
+ case SET_WINDOW:
+ case MEDIUM_SCAN:
+ case SEND_VOLUME_TAG:
+ case WRITE_LONG_2:
+ req->cmd.mode = SCSI_XFER_TO_DEV;
+ break;
+ default:
+ if (req->cmd.xfer)
+ req->cmd.mode = SCSI_XFER_FROM_DEV;
+ else {
+ req->cmd.mode = SCSI_XFER_NONE;
+ }
+ break;
+ }
+}
+
static uint64_t scsi_req_lba(SCSIRequest *req)
{
uint8_t *buf = req->cmd.buf;
@@ -303,6 +348,7 @@ int scsi_req_parse(SCSIRequest *req, uint8_t *buf)
return rc;
memcpy(req->cmd.buf, buf, req->cmd.len);
+ scsi_req_xfer_mode(req);
req->cmd.lba = scsi_req_lba(req);
return 0;
}
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 3c7feac..38fb46a 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -307,44 +307,6 @@ static void scsi_req_fixup(SCSIRequest *req)
}
}
-static int is_write(int command)
-{
- switch (command) {
- case COPY:
- case COPY_VERIFY:
- case COMPARE:
- case CHANGE_DEFINITION:
- case LOG_SELECT:
- case MODE_SELECT:
- case MODE_SELECT_10:
- case SEND_DIAGNOSTIC:
- case WRITE_BUFFER:
- case FORMAT_UNIT:
- case REASSIGN_BLOCKS:
- case RESERVE:
- case SEARCH_EQUAL:
- case SEARCH_HIGH:
- case SEARCH_LOW:
- case WRITE_6:
- case WRITE_10:
- case WRITE_VERIFY:
- case UPDATE_BLOCK:
- case WRITE_LONG:
- case WRITE_SAME:
- case SEARCH_HIGH_12:
- case SEARCH_EQUAL_12:
- case SEARCH_LOW_12:
- case WRITE_12:
- case WRITE_VERIFY_12:
- case SET_WINDOW:
- case MEDIUM_SCAN:
- case SEND_VOLUME_TAG:
- case WRITE_LONG_2:
- return 1;
- }
- return 0;
-}
-
/* 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),
@@ -415,7 +377,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
memset(r->buf, 0, r->buflen);
r->len = r->req.cmd.xfer;
- if (is_write(cmd[0])) {
+ if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
r->len = 0;
return -r->req.cmd.xfer;
}
diff --git a/hw/scsi.h b/hw/scsi.h
index 8c64067..c5b30b8 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -18,6 +18,12 @@ typedef struct SCSIDeviceInfo SCSIDeviceInfo;
typedef void (*scsi_completionfn)(SCSIBus *bus, int reason, uint32_t tag,
uint32_t arg);
+enum SCSIXferMode {
+ SCSI_XFER_NONE, /* TEST_UNIT_READY, ... */
+ SCSI_XFER_FROM_DEV, /* READ, INQUIRY, MODE_SENSE, ... */
+ SCSI_XFER_TO_DEV, /* WRITE, MODE_SELECT, ... */
+};
+
typedef struct SCSIRequest {
SCSIBus *bus;
SCSIDevice *dev;
@@ -28,6 +34,7 @@ typedef struct SCSIRequest {
int len;
size_t xfer;
uint64_t lba;
+ enum SCSIXferMode mode;
} cmd;
BlockDriverAIOCB *aiocb;
QTAILQ_ENTRY(SCSIRequest) next;
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 12/30] scsi: move sense to SCSIDevice, create SCSISense struct.
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (10 preceding siblings ...)
2009-11-26 14:33 ` [Qemu-devel] [PATCH 11/30] scsi: add xfer mode Gerd Hoffmann
@ 2009-11-26 14:33 ` Gerd Hoffmann
2009-11-26 14:33 ` [Qemu-devel] [PATCH 13/30] scsi: move dinfo to SCSIDevice Gerd Hoffmann
` (17 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-bus.c | 10 ++++++++++
hw/scsi-disk.c | 8 ++++----
hw/scsi.h | 9 +++++++++
3 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index e250e4f..666ca3c 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -113,6 +113,16 @@ void scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
}
}
+void scsi_dev_clear_sense(SCSIDevice *dev)
+{
+ memset(&dev->sense, 0, sizeof(dev->sense));
+}
+
+void scsi_dev_set_sense(SCSIDevice *dev, uint8_t key)
+{
+ dev->sense.key = key;
+}
+
SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun)
{
SCSIRequest *req;
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 4e92910..2eac400 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -59,7 +59,6 @@ struct SCSIDiskState
This is the number of 512 byte blocks in a single scsi sector. */
int cluster_size;
uint64_t max_lba;
- int sense;
char drive_serial_str[21];
QEMUBH *bh;
};
@@ -93,7 +92,7 @@ static void scsi_command_complete(SCSIDiskReq *r, int status, int sense)
uint32_t tag;
DPRINTF("Command complete tag=0x%x status=%d sense=%d\n",
r->req.tag, status, sense);
- s->sense = sense;
+ scsi_dev_set_sense(&s->qdev, sense);
tag = r->req.tag;
r->req.bus->complete(r->req.bus, SCSI_REASON_DONE, tag, status);
scsi_remove_request(r);
@@ -394,7 +393,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
goto fail;
memset(outbuf, 0, 4);
r->iov.iov_len = 4;
- if (s->sense == NOT_READY && len >= 18) {
+ if (s->qdev.sense.key == NOT_READY && len >= 18) {
memset(outbuf, 0, 18);
r->iov.iov_len = 18;
outbuf[7] = 10;
@@ -404,7 +403,8 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
}
outbuf[0] = 0xf0;
outbuf[1] = 0;
- outbuf[2] = s->sense;
+ outbuf[2] = s->qdev.sense.key;
+ scsi_dev_clear_sense(&s->qdev);
break;
case INQUIRY:
DPRINTF("Inquiry (len %d)\n", len);
diff --git a/hw/scsi.h b/hw/scsi.h
index c5b30b8..f0aaed5 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -24,6 +24,10 @@ enum SCSIXferMode {
SCSI_XFER_TO_DEV, /* WRITE, MODE_SELECT, ... */
};
+typedef struct SCSISense {
+ uint8_t key;
+} SCSISense;
+
typedef struct SCSIRequest {
SCSIBus *bus;
SCSIDevice *dev;
@@ -48,6 +52,7 @@ struct SCSIDevice
QTAILQ_HEAD(, SCSIRequest) requests;
int blocksize;
int type;
+ struct SCSISense sense;
};
/* cdrom.c */
@@ -92,9 +97,13 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, DriveInfo *dinfo, int unit);
void scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
+void scsi_dev_clear_sense(SCSIDevice *dev);
+void scsi_dev_set_sense(SCSIDevice *dev, uint8_t key);
+
SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun);
SCSIRequest *scsi_req_find(SCSIDevice *d, uint32_t tag);
void scsi_req_free(SCSIRequest *req);
+
int scsi_req_parse(SCSIRequest *req, uint8_t *buf);
#endif
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 13/30] scsi: move dinfo to SCSIDevice
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (11 preceding siblings ...)
2009-11-26 14:33 ` [Qemu-devel] [PATCH 12/30] scsi: move sense to SCSIDevice, create SCSISense struct Gerd Hoffmann
@ 2009-11-26 14:33 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 14/30] scsi: move status to SCSIRequest Gerd Hoffmann
` (16 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-disk.c | 63 ++++++++++++++++++++++++++---------------------------
hw/scsi-generic.c | 23 +++++++++----------
hw/scsi.h | 1 +
3 files changed, 43 insertions(+), 44 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 2eac400..2fc6cf9 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -54,7 +54,6 @@ typedef struct SCSIDiskReq {
struct SCSIDiskState
{
SCSIDevice qdev;
- DriveInfo *dinfo;
/* 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;
@@ -160,7 +159,7 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
r->iov.iov_len = n * 512;
qemu_iovec_init_external(&r->qiov, &r->iov, 1);
- r->req.aiocb = bdrv_aio_readv(s->dinfo->bdrv, r->sector, &r->qiov, n,
+ r->req.aiocb = bdrv_aio_readv(s->qdev.dinfo->bdrv, r->sector, &r->qiov, n,
scsi_read_complete, r);
if (r->req.aiocb == NULL)
scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
@@ -171,7 +170,7 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
static int scsi_handle_write_error(SCSIDiskReq *r, int error)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
- BlockInterfaceErrorAction action = drive_get_onerror(s->dinfo->bdrv);
+ BlockInterfaceErrorAction action = drive_get_onerror(s->qdev.dinfo->bdrv);
if (action == BLOCK_ERR_IGNORE)
return 0;
@@ -225,7 +224,7 @@ static void scsi_write_request(SCSIDiskReq *r)
n = r->iov.iov_len / 512;
if (n) {
qemu_iovec_init_external(&r->qiov, &r->iov, 1);
- r->req.aiocb = bdrv_aio_writev(s->dinfo->bdrv, r->sector, &r->qiov, n,
+ r->req.aiocb = bdrv_aio_writev(s->qdev.dinfo->bdrv, r->sector, &r->qiov, n,
scsi_write_complete, r);
if (r->req.aiocb == NULL)
scsi_command_complete(r, CHECK_CONDITION,
@@ -384,7 +383,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
switch (command) {
case TEST_UNIT_READY:
DPRINTF("Test Unit Ready\n");
- if (!bdrv_is_inserted(s->dinfo->bdrv))
+ if (!bdrv_is_inserted(s->qdev.dinfo->bdrv))
goto notready;
break;
case REQUEST_SENSE:
@@ -431,7 +430,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
r->iov.iov_len = 0;
- if (bdrv_get_type_hint(s->dinfo->bdrv) == BDRV_TYPE_CDROM) {
+ if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM) {
outbuf[r->iov.iov_len++] = 5;
} else {
outbuf[r->iov.iov_len++] = 0;
@@ -462,7 +461,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
r->iov.iov_len = 0;
/* Supported page codes */
- if (bdrv_get_type_hint(s->dinfo->bdrv) == BDRV_TYPE_CDROM) {
+ if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM) {
outbuf[r->iov.iov_len++] = 5;
} else {
outbuf[r->iov.iov_len++] = 0;
@@ -480,14 +479,14 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
{
/* Device identification page, mandatory */
int max_len = 255 - 8;
- int id_len = strlen(bdrv_get_device_name(s->dinfo->bdrv));
+ int id_len = strlen(bdrv_get_device_name(s->qdev.dinfo->bdrv));
if (id_len > max_len)
id_len = max_len;
DPRINTF("Inquiry EVPD[Device identification] "
"buffer size %d\n", len);
r->iov.iov_len = 0;
- if (bdrv_get_type_hint(s->dinfo->bdrv) == BDRV_TYPE_CDROM) {
+ if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM) {
outbuf[r->iov.iov_len++] = 5;
} else {
outbuf[r->iov.iov_len++] = 0;
@@ -503,7 +502,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
outbuf[r->iov.iov_len++] = id_len; // length of data following
memcpy(&outbuf[r->iov.iov_len],
- bdrv_get_device_name(s->dinfo->bdrv), id_len);
+ bdrv_get_device_name(s->qdev.dinfo->bdrv), id_len);
r->iov.iov_len += id_len;
}
break;
@@ -543,7 +542,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
if (lun || buf[1] >> 5) {
outbuf[0] = 0x7f; /* LUN not supported */
- } else if (bdrv_get_type_hint(s->dinfo->bdrv) == BDRV_TYPE_CDROM) {
+ } else if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM) {
outbuf[0] = 5;
outbuf[1] = 0x80;
memcpy(&outbuf[16], "QEMU CD-ROM ", 16);
@@ -586,12 +585,12 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
memset(p, 0, 4);
outbuf[1] = 0; /* Default media type. */
outbuf[3] = 0; /* Block descriptor length. */
- if (bdrv_get_type_hint(s->dinfo->bdrv) == BDRV_TYPE_CDROM ||
- bdrv_is_read_only(s->dinfo->bdrv)) {
+ if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM ||
+ bdrv_is_read_only(s->qdev.dinfo->bdrv)) {
outbuf[2] = 0x80; /* Readonly. */
}
p += 4;
- bdrv_get_geometry(s->dinfo->bdrv, &nb_sectors);
+ bdrv_get_geometry(s->qdev.dinfo->bdrv, &nb_sectors);
if ((~dbd) & nb_sectors) {
nb_sectors /= s->cluster_size;
nb_sectors--;
@@ -616,7 +615,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
p[0] = 4;
p[1] = 0x16;
/* if a geometry hint is available, use it */
- bdrv_get_geometry_hint(s->dinfo->bdrv, &cylinders, &heads, &secs);
+ bdrv_get_geometry_hint(s->qdev.dinfo->bdrv, &cylinders, &heads, &secs);
p[2] = (cylinders >> 16) & 0xff;
p[3] = (cylinders >> 8) & 0xff;
p[4] = cylinders & 0xff;
@@ -650,7 +649,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
p[2] = 5000 >> 8;
p[3] = 5000 & 0xff;
/* if a geometry hint is available, use it */
- bdrv_get_geometry_hint(s->dinfo->bdrv, &cylinders, &heads, &secs);
+ bdrv_get_geometry_hint(s->qdev.dinfo->bdrv, &cylinders, &heads, &secs);
p[4] = heads & 0xff;
p[5] = secs & 0xff;
p[6] = s->cluster_size * 2;
@@ -683,13 +682,13 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
memset(p,0,20);
p[0] = 8;
p[1] = 0x12;
- if (bdrv_enable_write_cache(s->dinfo->bdrv)) {
+ if (bdrv_enable_write_cache(s->qdev.dinfo->bdrv)) {
p[2] = 4; /* WCE */
}
p += 20;
}
if ((page == 0x3f || page == 0x2a)
- && (bdrv_get_type_hint(s->dinfo->bdrv) == BDRV_TYPE_CDROM)) {
+ && (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM)) {
/* CD Capabilities and Mechanical Status page. */
p[0] = 0x2a;
p[1] = 0x14;
@@ -700,7 +699,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
p[5] = 0xff; /* CD DA, DA accurate, RW supported,
RW corrected, C2 errors, ISRC,
UPC, Bar code */
- p[6] = 0x2d | (bdrv_is_locked(s->dinfo->bdrv)? 2 : 0);
+ p[6] = 0x2d | (bdrv_is_locked(s->qdev.dinfo->bdrv)? 2 : 0);
/* Locking supported, jumper present, eject, tray */
p[7] = 0; /* no volume & mute control, no
changer */
@@ -726,20 +725,20 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
break;
case START_STOP:
DPRINTF("Start Stop Unit\n");
- if (bdrv_get_type_hint(s->dinfo->bdrv) == BDRV_TYPE_CDROM &&
+ if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM &&
(buf[4] & 2))
/* load/eject medium */
- bdrv_eject(s->dinfo->bdrv, !(buf[4] & 1));
+ bdrv_eject(s->qdev.dinfo->bdrv, !(buf[4] & 1));
break;
case ALLOW_MEDIUM_REMOVAL:
DPRINTF("Prevent Allow Medium Removal (prevent = %d)\n", buf[4] & 3);
- bdrv_set_locked(s->dinfo->bdrv, buf[4] & 1);
+ bdrv_set_locked(s->qdev.dinfo->bdrv, buf[4] & 1);
break;
case READ_CAPACITY:
DPRINTF("Read Capacity\n");
/* The normal LEN field for this command is zero. */
memset(outbuf, 0, 8);
- bdrv_get_geometry(s->dinfo->bdrv, &nb_sectors);
+ bdrv_get_geometry(s->qdev.dinfo->bdrv, &nb_sectors);
nb_sectors /= s->cluster_size;
/* Returned value is the address of the last sector. */
if (nb_sectors) {
@@ -785,7 +784,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
break;
case SYNCHRONIZE_CACHE:
DPRINTF("Synchronise cache (sector %" PRId64 ", count %d)\n", lba, len);
- bdrv_flush(s->dinfo->bdrv);
+ bdrv_flush(s->qdev.dinfo->bdrv);
break;
case READ_TOC:
{
@@ -794,7 +793,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
msf = buf[1] & 2;
format = buf[2] & 0xf;
start_track = buf[6];
- bdrv_get_geometry(s->dinfo->bdrv, &nb_sectors);
+ bdrv_get_geometry(s->qdev.dinfo->bdrv, &nb_sectors);
DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
nb_sectors /= s->cluster_size;
switch(format) {
@@ -848,7 +847,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
if ((buf[1] & 31) == 0x10) {
DPRINTF("SAI READ CAPACITY(16)\n");
memset(outbuf, 0, len);
- bdrv_get_geometry(s->dinfo->bdrv, &nb_sectors);
+ bdrv_get_geometry(s->qdev.dinfo->bdrv, &nb_sectors);
nb_sectors /= s->cluster_size;
/* Returned value is the address of the last sector. */
if (nb_sectors) {
@@ -919,7 +918,7 @@ static void scsi_destroy(SCSIDevice *dev)
r = DO_UPCAST(SCSIDiskReq, req, QTAILQ_FIRST(&s->qdev.requests));
scsi_remove_request(r);
}
- drive_uninit(s->dinfo);
+ drive_uninit(s->qdev.dinfo);
}
static int scsi_disk_initfn(SCSIDevice *dev)
@@ -927,24 +926,24 @@ static int scsi_disk_initfn(SCSIDevice *dev)
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
uint64_t nb_sectors;
- if (!s->dinfo || !s->dinfo->bdrv) {
+ if (!s->qdev.dinfo || !s->qdev.dinfo->bdrv) {
qemu_error("scsi-disk: drive property not set\n");
return -1;
}
- if (bdrv_get_type_hint(s->dinfo->bdrv) == BDRV_TYPE_CDROM) {
+ if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM) {
s->cluster_size = 4;
} else {
s->cluster_size = 1;
}
s->qdev.blocksize = 512 * s->cluster_size;
s->qdev.type = TYPE_DISK;
- bdrv_get_geometry(s->dinfo->bdrv, &nb_sectors);
+ bdrv_get_geometry(s->qdev.dinfo->bdrv, &nb_sectors);
nb_sectors /= s->cluster_size;
if (nb_sectors)
nb_sectors--;
s->max_lba = nb_sectors;
- strncpy(s->drive_serial_str, drive_get_serial(s->dinfo->bdrv),
+ strncpy(s->drive_serial_str, drive_get_serial(s->qdev.dinfo->bdrv),
sizeof(s->drive_serial_str));
if (strlen(s->drive_serial_str) == 0)
pstrcpy(s->drive_serial_str, sizeof(s->drive_serial_str), "0");
@@ -964,7 +963,7 @@ static SCSIDeviceInfo scsi_disk_info = {
.cancel_io = scsi_cancel_io,
.get_buf = scsi_get_buf,
.qdev.props = (Property[]) {
- DEFINE_PROP_DRIVE("drive", SCSIDiskState, dinfo),
+ DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.dinfo),
DEFINE_PROP_END_OF_LIST(),
},
};
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 38fb46a..613d5a6 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -58,7 +58,6 @@ typedef struct SCSIGenericReq {
struct SCSIGenericState
{
SCSIDevice qdev;
- DriveInfo *dinfo;
int lun;
int driver_status;
uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
@@ -215,7 +214,7 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
return;
}
- ret = execute_command(s->dinfo->bdrv, r, SG_DXFER_FROM_DEV, scsi_read_complete);
+ ret = execute_command(s->qdev.dinfo->bdrv, r, SG_DXFER_FROM_DEV, scsi_read_complete);
if (ret == -1) {
scsi_command_complete(r, -EINVAL);
return;
@@ -266,7 +265,7 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag)
return 0;
}
- ret = execute_command(s->dinfo->bdrv, r, SG_DXFER_TO_DEV, scsi_write_complete);
+ ret = execute_command(s->qdev.dinfo->bdrv, r, SG_DXFER_TO_DEV, scsi_write_complete);
if (ret == -1) {
scsi_command_complete(r, -EINVAL);
return 1;
@@ -360,7 +359,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
free(r->buf);
r->buflen = 0;
r->buf = NULL;
- ret = execute_command(s->dinfo->bdrv, r, SG_DXFER_NONE, scsi_command_complete);
+ ret = execute_command(s->qdev.dinfo->bdrv, r, SG_DXFER_NONE, scsi_command_complete);
if (ret == -1) {
scsi_command_complete(r, -EINVAL);
return 0;
@@ -455,7 +454,7 @@ static void scsi_destroy(SCSIDevice *d)
r = DO_UPCAST(SCSIGenericReq, req, QTAILQ_FIRST(&s->qdev.requests));
scsi_remove_request(r);
}
- drive_uninit(s->dinfo);
+ drive_uninit(s->qdev.dinfo);
}
static int scsi_generic_initfn(SCSIDevice *dev)
@@ -464,26 +463,26 @@ static int scsi_generic_initfn(SCSIDevice *dev)
int sg_version;
struct sg_scsi_id scsiid;
- if (!s->dinfo || !s->dinfo->bdrv) {
+ if (!s->qdev.dinfo || !s->qdev.dinfo->bdrv) {
qemu_error("scsi-generic: drive property not set\n");
return -1;
}
/* check we are really using a /dev/sg* file */
- if (!bdrv_is_sg(s->dinfo->bdrv)) {
+ if (!bdrv_is_sg(s->qdev.dinfo->bdrv)) {
qemu_error("scsi-generic: not /dev/sg*\n");
return -1;
}
/* check we are using a driver managing SG_IO (version 3 and after */
- if (bdrv_ioctl(s->dinfo->bdrv, SG_GET_VERSION_NUM, &sg_version) < 0 ||
+ if (bdrv_ioctl(s->qdev.dinfo->bdrv, SG_GET_VERSION_NUM, &sg_version) < 0 ||
sg_version < 30000) {
qemu_error("scsi-generic: scsi generic interface too old\n");
return -1;
}
/* get LUN of the /dev/sg? */
- if (bdrv_ioctl(s->dinfo->bdrv, SG_GET_SCSI_ID, &scsiid)) {
+ if (bdrv_ioctl(s->qdev.dinfo->bdrv, SG_GET_SCSI_ID, &scsiid)) {
qemu_error("scsi-generic: SG_GET_SCSI_ID ioctl failed\n");
return -1;
}
@@ -494,11 +493,11 @@ static int scsi_generic_initfn(SCSIDevice *dev)
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->dinfo->bdrv);
+ s->qdev.blocksize = get_stream_blocksize(s->qdev.dinfo->bdrv);
if (s->qdev.blocksize == -1)
s->qdev.blocksize = 0;
} else {
- s->qdev.blocksize = get_blocksize(s->dinfo->bdrv);
+ s->qdev.blocksize = get_blocksize(s->qdev.dinfo->bdrv);
/* removable media returns 0 if not present */
if (s->qdev.blocksize <= 0) {
if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM)
@@ -525,7 +524,7 @@ static SCSIDeviceInfo scsi_generic_info = {
.cancel_io = scsi_cancel_io,
.get_buf = scsi_get_buf,
.qdev.props = (Property[]) {
- DEFINE_PROP_DRIVE("drive", SCSIGenericState, dinfo),
+ DEFINE_PROP_DRIVE("drive", SCSIGenericState, qdev.dinfo),
DEFINE_PROP_END_OF_LIST(),
},
};
diff --git a/hw/scsi.h b/hw/scsi.h
index f0aaed5..788c459 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -48,6 +48,7 @@ struct SCSIDevice
{
DeviceState qdev;
uint32_t id;
+ DriveInfo *dinfo;
SCSIDeviceInfo *info;
QTAILQ_HEAD(, SCSIRequest) requests;
int blocksize;
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 14/30] scsi: move status to SCSIRequest.
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (12 preceding siblings ...)
2009-11-26 14:33 ` [Qemu-devel] [PATCH 13/30] scsi: move dinfo to SCSIDevice Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 15/30] scsi: add scsi_req_print() Gerd Hoffmann
` (15 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Also add and use the scsi_req_complete() helper function for calling the
completion callback.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-bus.c | 9 +++++++++
hw/scsi-disk.c | 13 ++++++++-----
hw/scsi-generic.c | 18 ++++++++----------
hw/scsi.h | 2 ++
4 files changed, 27 insertions(+), 15 deletions(-)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 666ca3c..2e4fd38 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -132,6 +132,7 @@ SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t l
req->dev = d;
req->tag = tag;
req->lun = lun;
+ req->status = -1;
QTAILQ_INSERT_TAIL(&d->requests, req, next);
return req;
}
@@ -362,3 +363,11 @@ int scsi_req_parse(SCSIRequest *req, uint8_t *buf)
req->cmd.lba = scsi_req_lba(req);
return 0;
}
+
+void scsi_req_complete(SCSIRequest *req)
+{
+ assert(req->status != -1);
+ req->bus->complete(req->bus, SCSI_REASON_DONE,
+ req->tag,
+ req->status);
+}
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 2fc6cf9..bc8270c 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -84,16 +84,19 @@ static SCSIDiskReq *scsi_find_request(SCSIDiskState *s, uint32_t tag)
return DO_UPCAST(SCSIDiskReq, req, scsi_req_find(&s->qdev, tag));
}
+static void scsi_req_set_status(SCSIRequest *req, int status, int sense_code)
+{
+ req->status = status;
+ scsi_dev_set_sense(req->dev, sense_code);
+}
+
/* Helper function for command completion. */
static void scsi_command_complete(SCSIDiskReq *r, int status, int sense)
{
- SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
- uint32_t tag;
DPRINTF("Command complete tag=0x%x status=%d sense=%d\n",
r->req.tag, status, sense);
- scsi_dev_set_sense(&s->qdev, sense);
- tag = r->req.tag;
- r->req.bus->complete(r->req.bus, SCSI_REASON_DONE, tag, status);
+ scsi_req_set_status(&r->req, status, sense);
+ scsi_req_complete(&r->req);
scsi_remove_request(r);
}
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 613d5a6..c612abf 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -88,30 +88,28 @@ static void scsi_command_complete(void *opaque, int ret)
{
SCSIGenericReq *r = (SCSIGenericReq *)opaque;
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
- uint32_t tag;
- int status;
s->driver_status = r->io_header.driver_status;
if (s->driver_status & SG_ERR_DRIVER_SENSE)
s->senselen = r->io_header.sb_len_wr;
if (ret != 0)
- status = BUSY << 1;
+ r->req.status = BUSY << 1;
else {
if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
- status = BUSY << 1;
+ r->req.status = BUSY << 1;
BADF("Driver Timeout\n");
} else if (r->io_header.status)
- status = r->io_header.status;
+ r->req.status = r->io_header.status;
else if (s->driver_status & SG_ERR_DRIVER_SENSE)
- status = CHECK_CONDITION << 1;
+ r->req.status = CHECK_CONDITION << 1;
else
- status = GOOD << 1;
+ r->req.status = GOOD << 1;
}
DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
- r, r->req.tag, status);
- tag = r->req.tag;
- r->req.bus->complete(r->req.bus, SCSI_REASON_DONE, tag, status);
+ r, r->req.tag, r->req.status);
+
+ scsi_req_complete(&r->req);
scsi_remove_request(r);
}
diff --git a/hw/scsi.h b/hw/scsi.h
index 788c459..2fe8c12 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -33,6 +33,7 @@ typedef struct SCSIRequest {
SCSIDevice *dev;
uint32_t tag;
uint32_t lun;
+ uint32_t status;
struct {
uint8_t buf[SCSI_CMD_BUF_SIZE];
int len;
@@ -106,5 +107,6 @@ SCSIRequest *scsi_req_find(SCSIDevice *d, uint32_t tag);
void scsi_req_free(SCSIRequest *req);
int scsi_req_parse(SCSIRequest *req, uint8_t *buf);
+void scsi_req_complete(SCSIRequest *req);
#endif
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 15/30] scsi: add scsi_req_print()
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (13 preceding siblings ...)
2009-11-26 14:34 ` [Qemu-devel] [PATCH 14/30] scsi: move status to SCSIRequest Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 16/30] scsi-disk: restruct emulation: core + TEST_UNIT_READY Gerd Hoffmann
` (14 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Handy for debugging.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-bus.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/scsi.h | 1 +
2 files changed, 115 insertions(+), 0 deletions(-)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 2e4fd38..e362671 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -364,6 +364,120 @@ int scsi_req_parse(SCSIRequest *req, uint8_t *buf)
return 0;
}
+static const char *scsi_command_name(uint8_t cmd)
+{
+ static const char *names[] = {
+ [ TEST_UNIT_READY ] = "TEST_UNIT_READY",
+ [ REZERO_UNIT ] = "REZERO_UNIT",
+ [ REQUEST_SENSE ] = "REQUEST_SENSE",
+ [ FORMAT_UNIT ] = "FORMAT_UNIT",
+ [ READ_BLOCK_LIMITS ] = "READ_BLOCK_LIMITS",
+ [ REASSIGN_BLOCKS ] = "REASSIGN_BLOCKS",
+ [ READ_6 ] = "READ_6",
+ [ WRITE_6 ] = "WRITE_6",
+ [ SEEK_6 ] = "SEEK_6",
+ [ READ_REVERSE ] = "READ_REVERSE",
+ [ WRITE_FILEMARKS ] = "WRITE_FILEMARKS",
+ [ SPACE ] = "SPACE",
+ [ INQUIRY ] = "INQUIRY",
+ [ RECOVER_BUFFERED_DATA ] = "RECOVER_BUFFERED_DATA",
+ [ MODE_SELECT ] = "MODE_SELECT",
+ [ RESERVE ] = "RESERVE",
+ [ RELEASE ] = "RELEASE",
+ [ COPY ] = "COPY",
+ [ ERASE ] = "ERASE",
+ [ MODE_SENSE ] = "MODE_SENSE",
+ [ START_STOP ] = "START_STOP",
+ [ RECEIVE_DIAGNOSTIC ] = "RECEIVE_DIAGNOSTIC",
+ [ SEND_DIAGNOSTIC ] = "SEND_DIAGNOSTIC",
+ [ ALLOW_MEDIUM_REMOVAL ] = "ALLOW_MEDIUM_REMOVAL",
+
+ [ SET_WINDOW ] = "SET_WINDOW",
+ [ READ_CAPACITY ] = "READ_CAPACITY",
+ [ READ_10 ] = "READ_10",
+ [ WRITE_10 ] = "WRITE_10",
+ [ SEEK_10 ] = "SEEK_10",
+ [ WRITE_VERIFY ] = "WRITE_VERIFY",
+ [ VERIFY ] = "VERIFY",
+ [ SEARCH_HIGH ] = "SEARCH_HIGH",
+ [ SEARCH_EQUAL ] = "SEARCH_EQUAL",
+ [ SEARCH_LOW ] = "SEARCH_LOW",
+ [ SET_LIMITS ] = "SET_LIMITS",
+ [ PRE_FETCH ] = "PRE_FETCH",
+ [ READ_POSITION ] = "READ_POSITION",
+ [ SYNCHRONIZE_CACHE ] = "SYNCHRONIZE_CACHE",
+ [ LOCK_UNLOCK_CACHE ] = "LOCK_UNLOCK_CACHE",
+ [ READ_DEFECT_DATA ] = "READ_DEFECT_DATA",
+ [ MEDIUM_SCAN ] = "MEDIUM_SCAN",
+ [ COMPARE ] = "COMPARE",
+ [ COPY_VERIFY ] = "COPY_VERIFY",
+ [ WRITE_BUFFER ] = "WRITE_BUFFER",
+ [ READ_BUFFER ] = "READ_BUFFER",
+ [ UPDATE_BLOCK ] = "UPDATE_BLOCK",
+ [ READ_LONG ] = "READ_LONG",
+ [ WRITE_LONG ] = "WRITE_LONG",
+ [ CHANGE_DEFINITION ] = "CHANGE_DEFINITION",
+ [ WRITE_SAME ] = "WRITE_SAME",
+ [ READ_TOC ] = "READ_TOC",
+ [ LOG_SELECT ] = "LOG_SELECT",
+ [ LOG_SENSE ] = "LOG_SENSE",
+ [ MODE_SELECT_10 ] = "MODE_SELECT_10",
+ [ RESERVE_10 ] = "RESERVE_10",
+ [ RELEASE_10 ] = "RELEASE_10",
+ [ MODE_SENSE_10 ] = "MODE_SENSE_10",
+ [ PERSISTENT_RESERVE_IN ] = "PERSISTENT_RESERVE_IN",
+ [ PERSISTENT_RESERVE_OUT ] = "PERSISTENT_RESERVE_OUT",
+ [ MOVE_MEDIUM ] = "MOVE_MEDIUM",
+ [ READ_12 ] = "READ_12",
+ [ WRITE_12 ] = "WRITE_12",
+ [ WRITE_VERIFY_12 ] = "WRITE_VERIFY_12",
+ [ SEARCH_HIGH_12 ] = "SEARCH_HIGH_12",
+ [ SEARCH_EQUAL_12 ] = "SEARCH_EQUAL_12",
+ [ SEARCH_LOW_12 ] = "SEARCH_LOW_12",
+ [ READ_ELEMENT_STATUS ] = "READ_ELEMENT_STATUS",
+ [ SEND_VOLUME_TAG ] = "SEND_VOLUME_TAG",
+ [ WRITE_LONG_2 ] = "WRITE_LONG_2",
+
+ [ REWIND ] = "REWIND",
+ [ REPORT_DENSITY_SUPPORT ] = "REPORT_DENSITY_SUPPORT",
+ [ LOAD_UNLOAD ] = "LOAD_UNLOAD",
+ [ SET_CD_SPEED ] = "SET_CD_SPEED",
+ [ BLANK ] = "BLANK",
+ };
+
+ if (cmd >= ARRAY_SIZE(names) || names[cmd] == NULL)
+ return "*UNKNOWN*";
+ return names[cmd];
+}
+
+void scsi_req_print(SCSIRequest *req)
+{
+ FILE *fp = stderr;
+ int i;
+
+ fprintf(fp, "[%s id=%d] %s",
+ req->dev->qdev.parent_bus->name,
+ req->dev->id,
+ scsi_command_name(req->cmd.buf[0]));
+ for (i = 1; i < req->cmd.len; i++) {
+ fprintf(fp, " 0x%02x", req->cmd.buf[i]);
+ }
+ switch (req->cmd.mode) {
+ case SCSI_XFER_NONE:
+ fprintf(fp, " - none\n");
+ break;
+ case SCSI_XFER_FROM_DEV:
+ fprintf(fp, " - from-dev len=%zd\n", req->cmd.xfer);
+ break;
+ case SCSI_XFER_TO_DEV:
+ fprintf(fp, " - to-dev len=%zd\n", req->cmd.xfer);
+ break;
+ default:
+ fprintf(fp, " - Oops\n");
+ break;
+ }
+}
+
void scsi_req_complete(SCSIRequest *req)
{
assert(req->status != -1);
diff --git a/hw/scsi.h b/hw/scsi.h
index 2fe8c12..8f0200d 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -107,6 +107,7 @@ SCSIRequest *scsi_req_find(SCSIDevice *d, uint32_t tag);
void scsi_req_free(SCSIRequest *req);
int scsi_req_parse(SCSIRequest *req, uint8_t *buf);
+void scsi_req_print(SCSIRequest *req);
void scsi_req_complete(SCSIRequest *req);
#endif
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 16/30] scsi-disk: restruct emulation: core + TEST_UNIT_READY.
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (14 preceding siblings ...)
2009-11-26 14:34 ` [Qemu-devel] [PATCH 15/30] scsi: add scsi_req_print() Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 17/30] scsi-disk: restruct emulation: REQUEST_SENSE Gerd Hoffmann
` (13 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Add new scsi_disk_emulate_command() function, which will -- when
finished -- handle all scsi disk command emulation except actual I/O
(READ+WRITE commands) which goes to the block layer. The function
builds on top of the new SCSIRequest struct.
SCSI command emulation code is moved over from scsi_send_command() in
steps to ease review and make it easier to pin down regressions (if any)
using bisect. This patch moves over TEST_UNIT_READY only.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-disk.c | 47 ++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 42 insertions(+), 5 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index bc8270c..f851694 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -306,6 +306,31 @@ static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
return (uint8_t *)r->iov.iov_base;
}
+static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
+{
+ BlockDriverState *bdrv = req->dev->dinfo->bdrv;
+ int buflen = 0;
+
+ switch (req->cmd.buf[0]) {
+ case TEST_UNIT_READY:
+ if (!bdrv_is_inserted(bdrv))
+ goto not_ready;
+ break;
+ default:
+ goto illegal_request;
+ }
+ scsi_req_set_status(req, GOOD, NO_SENSE);
+ return buflen;
+
+not_ready:
+ scsi_req_set_status(req, CHECK_CONDITION, NOT_READY);
+ return 0;
+
+illegal_request:
+ scsi_req_set_status(req, CHECK_CONDITION, ILLEGAL_REQUEST);
+ return 0;
+}
+
/* 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),
@@ -323,6 +348,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
uint8_t command;
uint8_t *outbuf;
SCSIDiskReq *r;
+ int rc;
command = buf[0];
r = scsi_find_request(s, tag);
@@ -377,6 +403,14 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
printf("\n");
}
#endif
+
+ if (scsi_req_parse(&r->req, buf) != 0) {
+ BADF("Unsupported command length, command %x\n", command);
+ goto fail;
+ }
+ assert(r->req.cmd.len == cmdlen);
+ assert(r->req.cmd.lba == lba);
+
if (lun || buf[1] >> 5) {
/* Only LUN 0 supported. */
DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
@@ -385,10 +419,14 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
}
switch (command) {
case TEST_UNIT_READY:
- DPRINTF("Test Unit Ready\n");
- if (!bdrv_is_inserted(s->qdev.dinfo->bdrv))
- goto notready;
- break;
+ rc = scsi_disk_emulate_command(&r->req, outbuf);
+ if (rc > 0) {
+ r->iov.iov_len = rc;
+ } else {
+ scsi_req_complete(&r->req);
+ scsi_remove_request(r);
+ }
+ return rc;
case REQUEST_SENSE:
DPRINTF("Request Sense (len %d)\n", len);
if (len < 4)
@@ -761,7 +799,6 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
outbuf[7] = 0;
r->iov.iov_len = 8;
} else {
- notready:
scsi_command_complete(r, CHECK_CONDITION, NOT_READY);
return 0;
}
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 17/30] scsi-disk: restruct emulation: REQUEST_SENSE
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (15 preceding siblings ...)
2009-11-26 14:34 ` [Qemu-devel] [PATCH 16/30] scsi-disk: restruct emulation: core + TEST_UNIT_READY Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 18/30] scsi-disk: restruct emulation: INQUIRY Gerd Hoffmann
` (12 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Move REQUEST_SENSE emulation from scsi_send_command() to
scsi_disk_emulate_command().
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-disk.c | 38 +++++++++++++++++++-------------------
1 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index f851694..7597b52 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -316,6 +316,24 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
if (!bdrv_is_inserted(bdrv))
goto not_ready;
break;
+ case REQUEST_SENSE:
+ if (req->cmd.xfer < 4)
+ goto illegal_request;
+ memset(outbuf, 0, 4);
+ buflen = 4;
+ if (req->dev->sense.key == NOT_READY && req->cmd.xfer >= 18) {
+ memset(outbuf, 0, 18);
+ buflen = 18;
+ outbuf[7] = 10;
+ /* asc 0x3a, ascq 0: Medium not present */
+ outbuf[12] = 0x3a;
+ outbuf[13] = 0;
+ }
+ outbuf[0] = 0xf0;
+ outbuf[1] = 0;
+ outbuf[2] = req->dev->sense.key;
+ scsi_dev_clear_sense(req->dev);
+ break;
default:
goto illegal_request;
}
@@ -419,6 +437,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
}
switch (command) {
case TEST_UNIT_READY:
+ case REQUEST_SENSE:
rc = scsi_disk_emulate_command(&r->req, outbuf);
if (rc > 0) {
r->iov.iov_len = rc;
@@ -427,25 +446,6 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
scsi_remove_request(r);
}
return rc;
- case REQUEST_SENSE:
- DPRINTF("Request Sense (len %d)\n", len);
- if (len < 4)
- goto fail;
- memset(outbuf, 0, 4);
- r->iov.iov_len = 4;
- if (s->qdev.sense.key == NOT_READY && len >= 18) {
- memset(outbuf, 0, 18);
- r->iov.iov_len = 18;
- outbuf[7] = 10;
- /* asc 0x3a, ascq 0: Medium not present */
- outbuf[12] = 0x3a;
- outbuf[13] = 0;
- }
- outbuf[0] = 0xf0;
- outbuf[1] = 0;
- outbuf[2] = s->qdev.sense.key;
- scsi_dev_clear_sense(&s->qdev);
- break;
case INQUIRY:
DPRINTF("Inquiry (len %d)\n", len);
if (buf[1] & 0x2) {
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 18/30] scsi-disk: restruct emulation: INQUIRY
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (16 preceding siblings ...)
2009-11-26 14:34 ` [Qemu-devel] [PATCH 17/30] scsi-disk: restruct emulation: REQUEST_SENSE Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 19/30] scsi-disk: restruct emulation: RESERVE+RELEASE Gerd Hoffmann
` (11 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Move INQUIRY emulation from scsi_send_command() to
scsi_disk_emulate_command(). Also split the longish INQUITY emulation
code into the new scsi_disk_emulate_inquiry() function. Serial number
handling is slightly changed, we don't copy it any more but look it up
directly in DriveInfo which we have at hand anyway.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-disk.c | 305 ++++++++++++++++++++++++++------------------------------
1 files changed, 143 insertions(+), 162 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 7597b52..f94d513 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -58,7 +58,6 @@ struct SCSIDiskState
This is the number of 512 byte blocks in a single scsi sector. */
int cluster_size;
uint64_t max_lba;
- char drive_serial_str[21];
QEMUBH *bh;
};
@@ -306,6 +305,141 @@ static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
return (uint8_t *)r->iov.iov_base;
}
+static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
+{
+ BlockDriverState *bdrv = req->dev->dinfo->bdrv;
+ int buflen = 0;
+
+ if (req->cmd.buf[1] & 0x2) {
+ /* Command support data - optional, not implemented */
+ BADF("optional INQUIRY command support request not implemented\n");
+ return -1;
+ }
+
+ if (req->cmd.buf[1] & 0x1) {
+ /* Vital product data */
+ uint8_t page_code = req->cmd.buf[2];
+ if (req->cmd.xfer < 4) {
+ BADF("Error: Inquiry (EVPD[%02X]) buffer size %zd is "
+ "less than 4\n", page_code, req->cmd.xfer);
+ return -1;
+ }
+
+ if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM) {
+ outbuf[buflen++] = 5;
+ } else {
+ outbuf[buflen++] = 0;
+ }
+ outbuf[buflen++] = page_code ; // this page
+ outbuf[buflen++] = 0x00;
+
+ switch (page_code) {
+ case 0x00: /* Supported page codes, mandatory */
+ DPRINTF("Inquiry EVPD[Supported pages] "
+ "buffer size %zd\n", req->cmd.xfer);
+ outbuf[buflen++] = 3; // number of pages
+ outbuf[buflen++] = 0x00; // list of supported pages (this page)
+ outbuf[buflen++] = 0x80; // unit serial number
+ outbuf[buflen++] = 0x83; // device identification
+ break;
+
+ case 0x80: /* Device serial number, optional */
+ {
+ const char *serial = req->dev->dinfo->serial ?: "0";
+ int l = strlen(serial);
+
+ if (l > req->cmd.xfer)
+ l = req->cmd.xfer;
+ if (l > 20)
+ l = 20;
+
+ DPRINTF("Inquiry EVPD[Serial number] "
+ "buffer size %zd\n", req->cmd.xfer);
+ outbuf[buflen++] = l;
+ memcpy(outbuf+buflen, serial, l);
+ buflen += l;
+ break;
+ }
+
+ case 0x83: /* Device identification page, mandatory */
+ {
+ int max_len = 255 - 8;
+ int id_len = strlen(bdrv_get_device_name(bdrv));
+
+ if (id_len > max_len)
+ id_len = max_len;
+ DPRINTF("Inquiry EVPD[Device identification] "
+ "buffer size %zd\n", req->cmd.xfer);
+
+ outbuf[buflen++] = 3 + id_len;
+ outbuf[buflen++] = 0x2; // ASCII
+ outbuf[buflen++] = 0; // not officially assigned
+ outbuf[buflen++] = 0; // reserved
+ outbuf[buflen++] = id_len; // length of data following
+
+ memcpy(outbuf+buflen, bdrv_get_device_name(bdrv), id_len);
+ buflen += id_len;
+ break;
+ }
+ default:
+ BADF("Error: unsupported Inquiry (EVPD[%02X]) "
+ "buffer size %zd\n", page_code, req->cmd.xfer);
+ return -1;
+ }
+ /* done with EVPD */
+ return buflen;
+ }
+
+ /* Standard INQUIRY data */
+ if (req->cmd.buf[2] != 0) {
+ BADF("Error: Inquiry (STANDARD) page or code "
+ "is non-zero [%02X]\n", req->cmd.buf[2]);
+ return -1;
+ }
+
+ /* PAGE CODE == 0 */
+ if (req->cmd.xfer < 5) {
+ BADF("Error: Inquiry (STANDARD) buffer size %zd "
+ "is less than 5\n", req->cmd.xfer);
+ return -1;
+ }
+
+ if (req->cmd.xfer < 36) {
+ BADF("Error: Inquiry (STANDARD) buffer size %zd "
+ "is less than 36 (TODO: only 5 required)\n", req->cmd.xfer);
+ }
+
+ buflen = req->cmd.xfer;
+ if (buflen > SCSI_MAX_INQUIRY_LEN)
+ buflen = SCSI_MAX_INQUIRY_LEN;
+
+ memset(outbuf, 0, buflen);
+
+ if (req->lun || req->cmd.buf[1] >> 5) {
+ outbuf[0] = 0x7f; /* LUN not supported */
+ return buflen;
+ }
+
+ if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM) {
+ outbuf[0] = 5;
+ outbuf[1] = 0x80;
+ memcpy(&outbuf[16], "QEMU CD-ROM ", 16);
+ } else {
+ outbuf[0] = 0;
+ memcpy(&outbuf[16], "QEMU HARDDISK ", 16);
+ }
+ memcpy(&outbuf[8], "QEMU ", 8);
+ memcpy(&outbuf[32], QEMU_VERSION, 4);
+ /* Identify device as SCSI-3 rev 1.
+ Some later commands are also implemented. */
+ outbuf[2] = 3;
+ outbuf[3] = 2; /* Format 2 */
+ outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */
+ /* Sync data transfer and TCQ. */
+ outbuf[7] = 0x10 | (req->bus->tcq ? 0x02 : 0);
+ return buflen;
+}
+
static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
{
BlockDriverState *bdrv = req->dev->dinfo->bdrv;
@@ -334,6 +468,11 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
outbuf[2] = req->dev->sense.key;
scsi_dev_clear_sense(req->dev);
break;
+ case INQUIRY:
+ buflen = scsi_disk_emulate_inquiry(req, outbuf);
+ if (buflen < 0)
+ goto illegal_request;
+ break;
default:
goto illegal_request;
}
@@ -438,170 +577,16 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
switch (command) {
case TEST_UNIT_READY:
case REQUEST_SENSE:
+ case INQUIRY:
rc = scsi_disk_emulate_command(&r->req, outbuf);
if (rc > 0) {
r->iov.iov_len = rc;
} else {
scsi_req_complete(&r->req);
scsi_remove_request(r);
+ return 0;
}
- return rc;
- case INQUIRY:
- DPRINTF("Inquiry (len %d)\n", len);
- if (buf[1] & 0x2) {
- /* Command support data - optional, not implemented */
- BADF("optional INQUIRY command support request not implemented\n");
- goto fail;
- }
- else if (buf[1] & 0x1) {
- /* Vital product data */
- uint8_t page_code = buf[2];
- if (len < 4) {
- BADF("Error: Inquiry (EVPD[%02X]) buffer size %d is "
- "less than 4\n", page_code, len);
- goto fail;
- }
-
- switch (page_code) {
- case 0x00:
- {
- /* Supported page codes, mandatory */
- DPRINTF("Inquiry EVPD[Supported pages] "
- "buffer size %d\n", len);
-
- r->iov.iov_len = 0;
-
- if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM) {
- outbuf[r->iov.iov_len++] = 5;
- } else {
- outbuf[r->iov.iov_len++] = 0;
- }
-
- outbuf[r->iov.iov_len++] = 0x00; // this page
- outbuf[r->iov.iov_len++] = 0x00;
- outbuf[r->iov.iov_len++] = 3; // number of pages
- outbuf[r->iov.iov_len++] = 0x00; // list of supported pages (this page)
- outbuf[r->iov.iov_len++] = 0x80; // unit serial number
- outbuf[r->iov.iov_len++] = 0x83; // device identification
- }
- break;
- case 0x80:
- {
- int l;
-
- /* Device serial number, optional */
- if (len < 4) {
- BADF("Error: EVPD[Serial number] Inquiry buffer "
- "size %d too small, %d needed\n", len, 4);
- goto fail;
- }
-
- DPRINTF("Inquiry EVPD[Serial number] buffer size %d\n", len);
- l = MIN(len, strlen(s->drive_serial_str));
-
- r->iov.iov_len = 0;
-
- /* Supported page codes */
- if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM) {
- outbuf[r->iov.iov_len++] = 5;
- } else {
- outbuf[r->iov.iov_len++] = 0;
- }
-
- outbuf[r->iov.iov_len++] = 0x80; // this page
- outbuf[r->iov.iov_len++] = 0x00;
- outbuf[r->iov.iov_len++] = l;
- memcpy(&outbuf[r->iov.iov_len], s->drive_serial_str, l);
- r->iov.iov_len += l;
- }
-
- break;
- case 0x83:
- {
- /* Device identification page, mandatory */
- int max_len = 255 - 8;
- int id_len = strlen(bdrv_get_device_name(s->qdev.dinfo->bdrv));
- if (id_len > max_len)
- id_len = max_len;
-
- DPRINTF("Inquiry EVPD[Device identification] "
- "buffer size %d\n", len);
- r->iov.iov_len = 0;
- if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM) {
- outbuf[r->iov.iov_len++] = 5;
- } else {
- outbuf[r->iov.iov_len++] = 0;
- }
-
- outbuf[r->iov.iov_len++] = 0x83; // this page
- outbuf[r->iov.iov_len++] = 0x00;
- outbuf[r->iov.iov_len++] = 3 + id_len;
-
- outbuf[r->iov.iov_len++] = 0x2; // ASCII
- outbuf[r->iov.iov_len++] = 0; // not officially assigned
- outbuf[r->iov.iov_len++] = 0; // reserved
- outbuf[r->iov.iov_len++] = id_len; // length of data following
-
- memcpy(&outbuf[r->iov.iov_len],
- bdrv_get_device_name(s->qdev.dinfo->bdrv), id_len);
- r->iov.iov_len += id_len;
- }
- break;
- default:
- BADF("Error: unsupported Inquiry (EVPD[%02X]) "
- "buffer size %d\n", page_code, len);
- goto fail;
- }
- /* done with EVPD */
- break;
- }
- else {
- /* Standard INQUIRY data */
- if (buf[2] != 0) {
- BADF("Error: Inquiry (STANDARD) page or code "
- "is non-zero [%02X]\n", buf[2]);
- goto fail;
- }
-
- /* PAGE CODE == 0 */
- if (len < 5) {
- BADF("Error: Inquiry (STANDARD) buffer size %d "
- "is less than 5\n", len);
- goto fail;
- }
-
- if (len < 36) {
- BADF("Error: Inquiry (STANDARD) buffer size %d "
- "is less than 36 (TODO: only 5 required)\n", len);
- }
- }
-
- if(len > SCSI_MAX_INQUIRY_LEN)
- len = SCSI_MAX_INQUIRY_LEN;
-
- memset(outbuf, 0, len);
-
- if (lun || buf[1] >> 5) {
- outbuf[0] = 0x7f; /* LUN not supported */
- } else if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM) {
- outbuf[0] = 5;
- outbuf[1] = 0x80;
- memcpy(&outbuf[16], "QEMU CD-ROM ", 16);
- } else {
- outbuf[0] = 0;
- memcpy(&outbuf[16], "QEMU HARDDISK ", 16);
- }
- memcpy(&outbuf[8], "QEMU ", 8);
- memcpy(&outbuf[32], QEMU_VERSION, 4);
- /* Identify device as SCSI-3 rev 1.
- Some later commands are also implemented. */
- outbuf[2] = 3;
- outbuf[3] = 2; /* Format 2 */
- outbuf[4] = len - 5; /* Additional Length = (Len - 1) - 4 */
- /* Sync data transfer and TCQ. */
- outbuf[7] = 0x10 | (r->req.bus->tcq ? 0x02 : 0);
- r->iov.iov_len = len;
- break;
+ break;
case RESERVE:
DPRINTF("Reserve(6)\n");
if (buf[1] & 1)
@@ -983,10 +968,6 @@ static int scsi_disk_initfn(SCSIDevice *dev)
if (nb_sectors)
nb_sectors--;
s->max_lba = nb_sectors;
- strncpy(s->drive_serial_str, drive_get_serial(s->qdev.dinfo->bdrv),
- sizeof(s->drive_serial_str));
- if (strlen(s->drive_serial_str) == 0)
- pstrcpy(s->drive_serial_str, sizeof(s->drive_serial_str), "0");
qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
return 0;
}
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 19/30] scsi-disk: restruct emulation: RESERVE+RELEASE
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (17 preceding siblings ...)
2009-11-26 14:34 ` [Qemu-devel] [PATCH 18/30] scsi-disk: restruct emulation: INQUIRY Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 20/30] scsi-disk: restruct emulation: MODE_SENSE Gerd Hoffmann
` (10 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Move RESERVE+RELEASE emulation from scsi_send_command() to
scsi_disk_emulate_command().
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-disk.c | 40 ++++++++++++++++++++--------------------
1 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index f94d513..c67712a 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -473,6 +473,22 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
if (buflen < 0)
goto illegal_request;
break;
+ case RESERVE:
+ if (req->cmd.buf[1] & 1)
+ goto illegal_request;
+ break;
+ case RESERVE_10:
+ if (req->cmd.buf[1] & 3)
+ goto illegal_request;
+ break;
+ case RELEASE:
+ if (req->cmd.buf[1] & 1)
+ goto illegal_request;
+ break;
+ case RELEASE_10:
+ if (req->cmd.buf[1] & 3)
+ goto illegal_request;
+ break;
default:
goto illegal_request;
}
@@ -578,6 +594,10 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case TEST_UNIT_READY:
case REQUEST_SENSE:
case INQUIRY:
+ case RESERVE:
+ case RESERVE_10:
+ case RELEASE:
+ case RELEASE_10:
rc = scsi_disk_emulate_command(&r->req, outbuf);
if (rc > 0) {
r->iov.iov_len = rc;
@@ -587,16 +607,6 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
return 0;
}
break;
- case RESERVE:
- DPRINTF("Reserve(6)\n");
- if (buf[1] & 1)
- goto fail;
- break;
- case RELEASE:
- DPRINTF("Release(6)\n");
- if (buf[1] & 1)
- goto fail;
- break;
case MODE_SENSE:
case MODE_SENSE_10:
{
@@ -857,16 +867,6 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
outbuf[7] = 8; // CD-ROM
r->iov.iov_len = 8;
break;
- case RESERVE_10:
- DPRINTF("Reserve(10)\n");
- if (buf[1] & 3)
- goto fail;
- break;
- case RELEASE_10:
- DPRINTF("Release(10)\n");
- if (buf[1] & 3)
- goto fail;
- break;
case 0x9e:
/* Service Action In subcommands. */
if ((buf[1] & 31) == 0x10) {
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 20/30] scsi-disk: restruct emulation: MODE_SENSE
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (18 preceding siblings ...)
2009-11-26 14:34 ` [Qemu-devel] [PATCH 19/30] scsi-disk: restruct emulation: RESERVE+RELEASE Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 21/30] scsi-disk: restruct emulation: START_STOP Gerd Hoffmann
` (9 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Move MODE_SENSE emulation from scsi_send_command() to
scsi_disk_emulate_command(). Create two helper functions:
mode_sense_page() which writes the actual mode pages and
scsi_disk_emulate_mode_sense() which holds the longish MODE_SENSE
emulation code, calling into mode_sense_page() as needed.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-disk.c | 335 ++++++++++++++++++++++++++++++-------------------------
1 files changed, 183 insertions(+), 152 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index c67712a..06289c3 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -440,6 +440,181 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
return buflen;
}
+static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p)
+{
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
+ BlockDriverState *bdrv = req->dev->dinfo->bdrv;
+ int cylinders, heads, secs;
+
+ switch (page) {
+ case 4: /* Rigid disk device geometry page. */
+ p[0] = 4;
+ p[1] = 0x16;
+ /* if a geometry hint is available, use it */
+ bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
+ p[2] = (cylinders >> 16) & 0xff;
+ p[3] = (cylinders >> 8) & 0xff;
+ p[4] = cylinders & 0xff;
+ p[5] = heads & 0xff;
+ /* Write precomp start cylinder, disabled */
+ p[6] = (cylinders >> 16) & 0xff;
+ p[7] = (cylinders >> 8) & 0xff;
+ p[8] = cylinders & 0xff;
+ /* Reduced current start cylinder, disabled */
+ p[9] = (cylinders >> 16) & 0xff;
+ p[10] = (cylinders >> 8) & 0xff;
+ p[11] = cylinders & 0xff;
+ /* Device step rate [ns], 200ns */
+ p[12] = 0;
+ p[13] = 200;
+ /* Landing zone cylinder */
+ p[14] = 0xff;
+ p[15] = 0xff;
+ p[16] = 0xff;
+ /* Medium rotation rate [rpm], 5400 rpm */
+ p[20] = (5400 >> 8) & 0xff;
+ p[21] = 5400 & 0xff;
+ return 0x16;
+
+ case 5: /* Flexible disk device geometry page. */
+ p[0] = 5;
+ p[1] = 0x1e;
+ /* Transfer rate [kbit/s], 5Mbit/s */
+ p[2] = 5000 >> 8;
+ p[3] = 5000 & 0xff;
+ /* if a geometry hint is available, use it */
+ bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
+ p[4] = heads & 0xff;
+ p[5] = secs & 0xff;
+ p[6] = s->cluster_size * 2;
+ p[8] = (cylinders >> 8) & 0xff;
+ p[9] = cylinders & 0xff;
+ /* Write precomp start cylinder, disabled */
+ p[10] = (cylinders >> 8) & 0xff;
+ p[11] = cylinders & 0xff;
+ /* Reduced current start cylinder, disabled */
+ p[12] = (cylinders >> 8) & 0xff;
+ p[13] = cylinders & 0xff;
+ /* Device step rate [100us], 100us */
+ p[14] = 0;
+ p[15] = 1;
+ /* Device step pulse width [us], 1us */
+ p[16] = 1;
+ /* Device head settle delay [100us], 100us */
+ p[17] = 0;
+ p[18] = 1;
+ /* Motor on delay [0.1s], 0.1s */
+ p[19] = 1;
+ /* Motor off delay [0.1s], 0.1s */
+ p[20] = 1;
+ /* Medium rotation rate [rpm], 5400 rpm */
+ p[28] = (5400 >> 8) & 0xff;
+ p[29] = 5400 & 0xff;
+ return 0x1e;
+
+ case 8: /* Caching page. */
+ p[0] = 8;
+ p[1] = 0x12;
+ if (bdrv_enable_write_cache(s->qdev.dinfo->bdrv)) {
+ p[2] = 4; /* WCE */
+ }
+ return 20;
+
+ case 0x2a: /* CD Capabilities and Mechanical Status page. */
+ if (bdrv_get_type_hint(bdrv) != BDRV_TYPE_CDROM)
+ return 0;
+ p[0] = 0x2a;
+ p[1] = 0x14;
+ p[2] = 3; // 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,
+ RW corrected, C2 errors, ISRC,
+ UPC, Bar code */
+ p[6] = 0x2d | (bdrv_is_locked(s->qdev.dinfo->bdrv)? 2 : 0);
+ /* Locking supported, jumper present, eject, tray */
+ p[7] = 0; /* no volume & mute control, no
+ changer */
+ 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[13] = 2048 & 0xff;
+ p[14] = (16 * 176) >> 8; // 16x read speed current
+ p[15] = (16 * 176) & 0xff;
+ p[18] = (16 * 176) >> 8; // 16x write speed
+ p[19] = (16 * 176) & 0xff;
+ p[20] = (16 * 176) >> 8; // 16x write speed current
+ p[21] = (16 * 176) & 0xff;
+ return 22;
+
+ default:
+ return 0;
+ }
+}
+
+static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
+{
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
+ BlockDriverState *bdrv = req->dev->dinfo->bdrv;
+ uint64_t nb_sectors;
+ int page, dbd, buflen;
+ uint8_t *p;
+
+ dbd = req->cmd.buf[1] & 0x8;
+ page = req->cmd.buf[2] & 0x3f;
+ DPRINTF("Mode Sense (page %d, len %zd)\n", page, req->cmd.xfer);
+ memset(outbuf, 0, req->cmd.xfer);
+ p = outbuf;
+
+ p[1] = 0; /* Default media type. */
+ p[3] = 0; /* Block descriptor length. */
+ if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM ||
+ bdrv_is_read_only(bdrv)) {
+ p[2] = 0x80; /* Readonly. */
+ }
+ p += 4;
+
+ bdrv_get_geometry(bdrv, &nb_sectors);
+ if ((~dbd) & nb_sectors) {
+ outbuf[3] = 8; /* Block descriptor length */
+ nb_sectors /= s->cluster_size;
+ nb_sectors--;
+ if (nb_sectors > 0xffffff)
+ nb_sectors = 0xffffff;
+ p[0] = 0; /* media density code */
+ p[1] = (nb_sectors >> 16) & 0xff;
+ p[2] = (nb_sectors >> 8) & 0xff;
+ 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[7] = 0;
+ p += 8;
+ }
+
+ switch (page) {
+ case 0x04:
+ case 0x05:
+ case 0x08:
+ case 0x2a:
+ p += mode_sense_page(req, page, p);
+ break;
+ case 0x3f:
+ p += mode_sense_page(req, 0x08, p);
+ p += mode_sense_page(req, 0x2a, p);
+ break;
+ }
+
+ buflen = p - outbuf;
+ outbuf[0] = buflen - 4;
+ if (buflen > req->cmd.xfer)
+ buflen = req->cmd.xfer;
+ return buflen;
+}
+
static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
{
BlockDriverState *bdrv = req->dev->dinfo->bdrv;
@@ -473,6 +648,12 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
if (buflen < 0)
goto illegal_request;
break;
+ case MODE_SENSE:
+ case MODE_SENSE_10:
+ buflen = scsi_disk_emulate_mode_sense(req, outbuf);
+ if (buflen < 0)
+ goto illegal_request;
+ break;
case RESERVE:
if (req->cmd.buf[1] & 1)
goto illegal_request;
@@ -594,6 +775,8 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case TEST_UNIT_READY:
case REQUEST_SENSE:
case INQUIRY:
+ case MODE_SENSE:
+ case MODE_SENSE_10:
case RESERVE:
case RESERVE_10:
case RELEASE:
@@ -607,158 +790,6 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
return 0;
}
break;
- case MODE_SENSE:
- case MODE_SENSE_10:
- {
- uint8_t *p;
- int page;
- int dbd;
-
- dbd = buf[1] & 0x8;
- page = buf[2] & 0x3f;
- DPRINTF("Mode Sense (page %d, len %d)\n", page, len);
- p = outbuf;
- memset(p, 0, 4);
- outbuf[1] = 0; /* Default media type. */
- outbuf[3] = 0; /* Block descriptor length. */
- if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM ||
- bdrv_is_read_only(s->qdev.dinfo->bdrv)) {
- outbuf[2] = 0x80; /* Readonly. */
- }
- p += 4;
- bdrv_get_geometry(s->qdev.dinfo->bdrv, &nb_sectors);
- if ((~dbd) & nb_sectors) {
- nb_sectors /= s->cluster_size;
- nb_sectors--;
- if (nb_sectors > 0xffffff)
- nb_sectors = 0xffffff;
- outbuf[3] = 8; /* Block descriptor length */
- p[0] = 0; /* media density code */
- p[1] = (nb_sectors >> 16) & 0xff;
- p[2] = (nb_sectors >> 8) & 0xff;
- 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[7] = 0;
- p += 8;
- }
-
- if (page == 4) {
- int cylinders, heads, secs;
-
- /* Rigid disk device geometry page. */
- p[0] = 4;
- p[1] = 0x16;
- /* if a geometry hint is available, use it */
- bdrv_get_geometry_hint(s->qdev.dinfo->bdrv, &cylinders, &heads, &secs);
- p[2] = (cylinders >> 16) & 0xff;
- p[3] = (cylinders >> 8) & 0xff;
- p[4] = cylinders & 0xff;
- p[5] = heads & 0xff;
- /* Write precomp start cylinder, disabled */
- p[6] = (cylinders >> 16) & 0xff;
- p[7] = (cylinders >> 8) & 0xff;
- p[8] = cylinders & 0xff;
- /* Reduced current start cylinder, disabled */
- p[9] = (cylinders >> 16) & 0xff;
- p[10] = (cylinders >> 8) & 0xff;
- p[11] = cylinders & 0xff;
- /* Device step rate [ns], 200ns */
- p[12] = 0;
- p[13] = 200;
- /* Landing zone cylinder */
- p[14] = 0xff;
- p[15] = 0xff;
- p[16] = 0xff;
- /* Medium rotation rate [rpm], 5400 rpm */
- p[20] = (5400 >> 8) & 0xff;
- p[21] = 5400 & 0xff;
- p += 0x16;
- } else if (page == 5) {
- int cylinders, heads, secs;
-
- /* Flexible disk device geometry page. */
- p[0] = 5;
- p[1] = 0x1e;
- /* Transfer rate [kbit/s], 5Mbit/s */
- p[2] = 5000 >> 8;
- p[3] = 5000 & 0xff;
- /* if a geometry hint is available, use it */
- bdrv_get_geometry_hint(s->qdev.dinfo->bdrv, &cylinders, &heads, &secs);
- p[4] = heads & 0xff;
- p[5] = secs & 0xff;
- p[6] = s->cluster_size * 2;
- p[8] = (cylinders >> 8) & 0xff;
- p[9] = cylinders & 0xff;
- /* Write precomp start cylinder, disabled */
- p[10] = (cylinders >> 8) & 0xff;
- p[11] = cylinders & 0xff;
- /* Reduced current start cylinder, disabled */
- p[12] = (cylinders >> 8) & 0xff;
- p[13] = cylinders & 0xff;
- /* Device step rate [100us], 100us */
- p[14] = 0;
- p[15] = 1;
- /* Device step pulse width [us], 1us */
- p[16] = 1;
- /* Device head settle delay [100us], 100us */
- p[17] = 0;
- p[18] = 1;
- /* Motor on delay [0.1s], 0.1s */
- p[19] = 1;
- /* Motor off delay [0.1s], 0.1s */
- p[20] = 1;
- /* Medium rotation rate [rpm], 5400 rpm */
- p[28] = (5400 >> 8) & 0xff;
- p[29] = 5400 & 0xff;
- p += 0x1e;
- } else if ((page == 8 || page == 0x3f)) {
- /* Caching page. */
- memset(p,0,20);
- p[0] = 8;
- p[1] = 0x12;
- if (bdrv_enable_write_cache(s->qdev.dinfo->bdrv)) {
- p[2] = 4; /* WCE */
- }
- p += 20;
- }
- if ((page == 0x3f || page == 0x2a)
- && (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM)) {
- /* CD Capabilities and Mechanical Status page. */
- p[0] = 0x2a;
- p[1] = 0x14;
- p[2] = 3; // 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,
- RW corrected, C2 errors, ISRC,
- UPC, Bar code */
- p[6] = 0x2d | (bdrv_is_locked(s->qdev.dinfo->bdrv)? 2 : 0);
- /* Locking supported, jumper present, eject, tray */
- p[7] = 0; /* no volume & mute control, no
- changer */
- 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[13] = 2048 & 0xff;
- p[14] = (16 * 176) >> 8; // 16x read speed current
- p[15] = (16 * 176) & 0xff;
- p[18] = (16 * 176) >> 8; // 16x write speed
- p[19] = (16 * 176) & 0xff;
- p[20] = (16 * 176) >> 8; // 16x write speed current
- p[21] = (16 * 176) & 0xff;
- p += 22;
- }
- r->iov.iov_len = p - outbuf;
- outbuf[0] = r->iov.iov_len - 4;
- if (r->iov.iov_len > len)
- r->iov.iov_len = len;
- }
- break;
case START_STOP:
DPRINTF("Start Stop Unit\n");
if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM &&
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 21/30] scsi-disk: restruct emulation: START_STOP
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (19 preceding siblings ...)
2009-11-26 14:34 ` [Qemu-devel] [PATCH 20/30] scsi-disk: restruct emulation: MODE_SENSE Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 22/30] scsi-disk: restruct emulation: ALLOW_MEDIUM_REMOVAL Gerd Hoffmann
` (8 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Move START_STOP emulation from scsi_send_command() to
scsi_disk_emulate_command().
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-disk.c | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 06289c3..11e85f2 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -670,6 +670,12 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
if (req->cmd.buf[1] & 3)
goto illegal_request;
break;
+ case START_STOP:
+ if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM && (req->cmd.buf[4] & 2)) {
+ /* load/eject medium */
+ bdrv_eject(bdrv, !(req->cmd.buf[4] & 1));
+ }
+ break;
default:
goto illegal_request;
}
@@ -781,6 +787,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case RESERVE_10:
case RELEASE:
case RELEASE_10:
+ case START_STOP:
rc = scsi_disk_emulate_command(&r->req, outbuf);
if (rc > 0) {
r->iov.iov_len = rc;
@@ -790,13 +797,6 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
return 0;
}
break;
- case START_STOP:
- DPRINTF("Start Stop Unit\n");
- if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM &&
- (buf[4] & 2))
- /* load/eject medium */
- bdrv_eject(s->qdev.dinfo->bdrv, !(buf[4] & 1));
- break;
case ALLOW_MEDIUM_REMOVAL:
DPRINTF("Prevent Allow Medium Removal (prevent = %d)\n", buf[4] & 3);
bdrv_set_locked(s->qdev.dinfo->bdrv, buf[4] & 1);
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 22/30] scsi-disk: restruct emulation: ALLOW_MEDIUM_REMOVAL
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (20 preceding siblings ...)
2009-11-26 14:34 ` [Qemu-devel] [PATCH 21/30] scsi-disk: restruct emulation: START_STOP Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 23/30] scsi-disk: restruct emulation: READ_CAPACITY Gerd Hoffmann
` (7 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Move ALLOW_MEDIUM_REMOVAL emulation from scsi_send_command() to
scsi_disk_emulate_command().
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-disk.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 11e85f2..7d59998 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -676,6 +676,9 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
bdrv_eject(bdrv, !(req->cmd.buf[4] & 1));
}
break;
+ case ALLOW_MEDIUM_REMOVAL:
+ bdrv_set_locked(bdrv, req->cmd.buf[4] & 1);
+ break;
default:
goto illegal_request;
}
@@ -788,6 +791,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case RELEASE:
case RELEASE_10:
case START_STOP:
+ case ALLOW_MEDIUM_REMOVAL:
rc = scsi_disk_emulate_command(&r->req, outbuf);
if (rc > 0) {
r->iov.iov_len = rc;
@@ -797,10 +801,6 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
return 0;
}
break;
- case ALLOW_MEDIUM_REMOVAL:
- DPRINTF("Prevent Allow Medium Removal (prevent = %d)\n", buf[4] & 3);
- bdrv_set_locked(s->qdev.dinfo->bdrv, buf[4] & 1);
- break;
case READ_CAPACITY:
DPRINTF("Read Capacity\n");
/* The normal LEN field for this command is zero. */
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 23/30] scsi-disk: restruct emulation: READ_CAPACITY
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (21 preceding siblings ...)
2009-11-26 14:34 ` [Qemu-devel] [PATCH 22/30] scsi-disk: restruct emulation: ALLOW_MEDIUM_REMOVAL Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 24/30] scsi-disk: restruct emulation: SYNCHRONIZE_CACHE Gerd Hoffmann
` (6 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Move READ_CAPACITY emulation from scsi_send_command() to
scsi_disk_emulate_command().
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-disk.c | 55 +++++++++++++++++++++++++++----------------------------
1 files changed, 27 insertions(+), 28 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 7d59998..4f56a22 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -617,7 +617,9 @@ static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
{
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
BlockDriverState *bdrv = req->dev->dinfo->bdrv;
+ uint64_t nb_sectors;
int buflen = 0;
switch (req->cmd.buf[0]) {
@@ -679,6 +681,30 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
case ALLOW_MEDIUM_REMOVAL:
bdrv_set_locked(bdrv, req->cmd.buf[4] & 1);
break;
+ case READ_CAPACITY:
+ /* The normal LEN field for this command is zero. */
+ memset(outbuf, 0, 8);
+ bdrv_get_geometry(bdrv, &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)
+ nb_sectors = UINT32_MAX;
+ outbuf[0] = (nb_sectors >> 24) & 0xff;
+ outbuf[1] = (nb_sectors >> 16) & 0xff;
+ outbuf[2] = (nb_sectors >> 8) & 0xff;
+ outbuf[3] = nb_sectors & 0xff;
+ outbuf[4] = 0;
+ outbuf[5] = 0;
+ outbuf[6] = s->cluster_size * 2;
+ outbuf[7] = 0;
+ buflen = 8;
+ break;
default:
goto illegal_request;
}
@@ -792,6 +818,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case RELEASE_10:
case START_STOP:
case ALLOW_MEDIUM_REMOVAL:
+ case READ_CAPACITY:
rc = scsi_disk_emulate_command(&r->req, outbuf);
if (rc > 0) {
r->iov.iov_len = rc;
@@ -801,34 +828,6 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
return 0;
}
break;
- case READ_CAPACITY:
- DPRINTF("Read Capacity\n");
- /* The normal LEN field for this command is zero. */
- memset(outbuf, 0, 8);
- bdrv_get_geometry(s->qdev.dinfo->bdrv, &nb_sectors);
- nb_sectors /= s->cluster_size;
- /* Returned value is the address of the last sector. */
- if (nb_sectors) {
- 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)
- nb_sectors = UINT32_MAX;
- outbuf[0] = (nb_sectors >> 24) & 0xff;
- outbuf[1] = (nb_sectors >> 16) & 0xff;
- outbuf[2] = (nb_sectors >> 8) & 0xff;
- outbuf[3] = nb_sectors & 0xff;
- outbuf[4] = 0;
- outbuf[5] = 0;
- outbuf[6] = s->cluster_size * 2;
- outbuf[7] = 0;
- r->iov.iov_len = 8;
- } else {
- scsi_command_complete(r, CHECK_CONDITION, NOT_READY);
- return 0;
- }
- break;
case READ_6:
case READ_10:
case 0x88:
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 24/30] scsi-disk: restruct emulation: SYNCHRONIZE_CACHE
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (22 preceding siblings ...)
2009-11-26 14:34 ` [Qemu-devel] [PATCH 23/30] scsi-disk: restruct emulation: READ_CAPACITY Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 25/30] scsi-disk: restruct emulation: READ_TOC Gerd Hoffmann
` (5 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Move SYNCHRONIZE_CACHE emulation from scsi_send_command() to
scsi_disk_emulate_command().
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-disk.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 4f56a22..865c5db 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -705,6 +705,9 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
outbuf[7] = 0;
buflen = 8;
break;
+ case SYNCHRONIZE_CACHE:
+ bdrv_flush(bdrv);
+ break;
default:
goto illegal_request;
}
@@ -819,6 +822,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case START_STOP:
case ALLOW_MEDIUM_REMOVAL:
case READ_CAPACITY:
+ case SYNCHRONIZE_CACHE:
rc = scsi_disk_emulate_command(&r->req, outbuf);
if (rc > 0) {
r->iov.iov_len = rc;
@@ -847,10 +851,6 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
r->sector_count = len * s->cluster_size;
is_write = 1;
break;
- case SYNCHRONIZE_CACHE:
- DPRINTF("Synchronise cache (sector %" PRId64 ", count %d)\n", lba, len);
- bdrv_flush(s->qdev.dinfo->bdrv);
- break;
case READ_TOC:
{
int start_track, format, msf, toclen;
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 25/30] scsi-disk: restruct emulation: READ_TOC
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (23 preceding siblings ...)
2009-11-26 14:34 ` [Qemu-devel] [PATCH 24/30] scsi-disk: restruct emulation: SYNCHRONIZE_CACHE Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 26/30] scsi-disk: restruct emulation: GET_CONFIGURATION Gerd Hoffmann
` (4 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Move READ_TOC emulation from scsi_send_command() to
scsi_disk_emulate_command(). Add scsi_disk_emulate_read_toc() function
which holds the longisch READ_TOC emulation code.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-disk.c | 80 +++++++++++++++++++++++++++++--------------------------
1 files changed, 42 insertions(+), 38 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 865c5db..6ba8f85 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -615,6 +615,42 @@ static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
return buflen;
}
+static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
+{
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
+ BlockDriverState *bdrv = req->dev->dinfo->bdrv;
+ int start_track, format, msf, toclen;
+ uint64_t nb_sectors;
+
+ msf = req->cmd.buf[1] & 2;
+ format = req->cmd.buf[2] & 0xf;
+ start_track = req->cmd.buf[6];
+ bdrv_get_geometry(bdrv, &nb_sectors);
+ DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
+ nb_sectors /= s->cluster_size;
+ switch (format) {
+ case 0:
+ toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
+ break;
+ case 1:
+ /* multi session : only a single session defined */
+ toclen = 12;
+ memset(outbuf, 0, 12);
+ outbuf[1] = 0x0a;
+ outbuf[2] = 0x01;
+ outbuf[3] = 0x01;
+ break;
+ case 2:
+ toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
+ break;
+ default:
+ return -1;
+ }
+ if (toclen > req->cmd.xfer)
+ toclen = req->cmd.xfer;
+ return toclen;
+}
+
static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
@@ -656,6 +692,11 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
if (buflen < 0)
goto illegal_request;
break;
+ case READ_TOC:
+ buflen = scsi_disk_emulate_read_toc(req, outbuf);
+ if (buflen < 0)
+ goto illegal_request;
+ break;
case RESERVE:
if (req->cmd.buf[1] & 1)
goto illegal_request;
@@ -823,6 +864,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case ALLOW_MEDIUM_REMOVAL:
case READ_CAPACITY:
case SYNCHRONIZE_CACHE:
+ case READ_TOC:
rc = scsi_disk_emulate_command(&r->req, outbuf);
if (rc > 0) {
r->iov.iov_len = rc;
@@ -851,44 +893,6 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
r->sector_count = len * s->cluster_size;
is_write = 1;
break;
- case READ_TOC:
- {
- int start_track, format, msf, toclen;
-
- msf = buf[1] & 2;
- format = buf[2] & 0xf;
- start_track = buf[6];
- bdrv_get_geometry(s->qdev.dinfo->bdrv, &nb_sectors);
- DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
- nb_sectors /= s->cluster_size;
- switch(format) {
- case 0:
- toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
- break;
- case 1:
- /* multi session : only a single session defined */
- toclen = 12;
- memset(outbuf, 0, 12);
- outbuf[1] = 0x0a;
- outbuf[2] = 0x01;
- outbuf[3] = 0x01;
- break;
- case 2:
- toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
- break;
- default:
- goto error_cmd;
- }
- if (toclen > 0) {
- if (len > toclen)
- len = toclen;
- r->iov.iov_len = len;
- break;
- }
- error_cmd:
- DPRINTF("Read TOC error\n");
- goto fail;
- }
case 0x46:
DPRINTF("Get Configuration (rt %d, maxlen %d)\n", buf[1] & 3, len);
memset(outbuf, 0, 8);
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 26/30] scsi-disk: restruct emulation: GET_CONFIGURATION
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (24 preceding siblings ...)
2009-11-26 14:34 ` [Qemu-devel] [PATCH 25/30] scsi-disk: restruct emulation: READ_TOC Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 27/30] scsi-disk: restruct emulation: SERVICE_ACTION_IN Gerd Hoffmann
` (3 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Move GET_CONFIGURATION emulation from scsi_send_command() to
scsi_disk_emulate_command().
Also add GET_CONFIGURATION to scsi-defs.h and scsi_command_name().
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-bus.c | 1 +
hw/scsi-defs.h | 1 +
hw/scsi-disk.c | 16 ++++++++--------
3 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index e362671..09b6fa9 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -440,6 +440,7 @@ static const char *scsi_command_name(uint8_t cmd)
[ REWIND ] = "REWIND",
[ REPORT_DENSITY_SUPPORT ] = "REPORT_DENSITY_SUPPORT",
+ [ GET_CONFIGURATION ] = "GET_CONFIGURATION",
[ LOAD_UNLOAD ] = "LOAD_UNLOAD",
[ SET_CD_SPEED ] = "SET_CD_SPEED",
[ BLANK ] = "BLANK",
diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
index 1701521..fbcfaa6 100644
--- a/hw/scsi-defs.h
+++ b/hw/scsi-defs.h
@@ -99,6 +99,7 @@
/* from hw/scsi-generic.c */
#define REWIND 0x01
#define REPORT_DENSITY_SUPPORT 0x44
+#define GET_CONFIGURATION 0x46
#define LOAD_UNLOAD 0xa6
#define SET_CD_SPEED 0xbb
#define BLANK 0xa1
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 6ba8f85..4a3e6fe 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -749,6 +749,13 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
case SYNCHRONIZE_CACHE:
bdrv_flush(bdrv);
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;
+ break;
default:
goto illegal_request;
}
@@ -865,6 +872,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case READ_CAPACITY:
case SYNCHRONIZE_CACHE:
case READ_TOC:
+ case GET_CONFIGURATION:
rc = scsi_disk_emulate_command(&r->req, outbuf);
if (rc > 0) {
r->iov.iov_len = rc;
@@ -893,14 +901,6 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
r->sector_count = len * s->cluster_size;
is_write = 1;
break;
- case 0x46:
- DPRINTF("Get Configuration (rt %d, maxlen %d)\n", buf[1] & 3, len);
- 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
- r->iov.iov_len = 8;
- break;
case 0x9e:
/* Service Action In subcommands. */
if ((buf[1] & 31) == 0x10) {
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 27/30] scsi-disk: restruct emulation: SERVICE_ACTION_IN
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (25 preceding siblings ...)
2009-11-26 14:34 ` [Qemu-devel] [PATCH 26/30] scsi-disk: restruct emulation: GET_CONFIGURATION Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 28/30] scsi-disk: restruct emulation: REPORT_LUNS Gerd Hoffmann
` (2 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Move SERVICE_ACTION_IN emulation from scsi_send_command() to
scsi_disk_emulate_command().
Also add SERVICE_ACTION_IN to scsi-defs.h and scsi_command_name().
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-bus.c | 1 +
hw/scsi-defs.h | 1 +
hw/scsi-disk.c | 67 ++++++++++++++++++++++++++-----------------------------
3 files changed, 34 insertions(+), 35 deletions(-)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 09b6fa9..deb6b4f 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -441,6 +441,7 @@ static const char *scsi_command_name(uint8_t cmd)
[ REWIND ] = "REWIND",
[ REPORT_DENSITY_SUPPORT ] = "REPORT_DENSITY_SUPPORT",
[ GET_CONFIGURATION ] = "GET_CONFIGURATION",
+ [ SERVICE_ACTION_IN ] = "SERVICE_ACTION_IN",
[ LOAD_UNLOAD ] = "LOAD_UNLOAD",
[ SET_CD_SPEED ] = "SET_CD_SPEED",
[ BLANK ] = "BLANK",
diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
index fbcfaa6..4aeb667 100644
--- a/hw/scsi-defs.h
+++ b/hw/scsi-defs.h
@@ -100,6 +100,7 @@
#define REWIND 0x01
#define REPORT_DENSITY_SUPPORT 0x44
#define GET_CONFIGURATION 0x46
+#define SERVICE_ACTION_IN 0x9e
#define LOAD_UNLOAD 0xa6
#define SET_CD_SPEED 0xbb
#define BLANK 0xa1
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 4a3e6fe..b481c13 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -756,6 +756,37 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
outbuf[7] = 8; // CD-ROM
buflen = 8;
break;
+ case SERVICE_ACTION_IN:
+ /* Service Action In subcommands. */
+ if ((req->cmd.buf[1] & 31) == 0x10) {
+ DPRINTF("SAI READ CAPACITY(16)\n");
+ memset(outbuf, 0, req->cmd.xfer);
+ bdrv_get_geometry(bdrv, &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;
+ outbuf[0] = (nb_sectors >> 56) & 0xff;
+ outbuf[1] = (nb_sectors >> 48) & 0xff;
+ outbuf[2] = (nb_sectors >> 40) & 0xff;
+ outbuf[3] = (nb_sectors >> 32) & 0xff;
+ outbuf[4] = (nb_sectors >> 24) & 0xff;
+ outbuf[5] = (nb_sectors >> 16) & 0xff;
+ outbuf[6] = (nb_sectors >> 8) & 0xff;
+ outbuf[7] = nb_sectors & 0xff;
+ outbuf[8] = 0;
+ outbuf[9] = 0;
+ outbuf[10] = s->cluster_size * 2;
+ outbuf[11] = 0;
+ /* Protection, exponent and lowest lba field left blank. */
+ buflen = req->cmd.xfer;
+ break;
+ }
+ DPRINTF("Unsupported Service Action In\n");
+ goto illegal_request;
default:
goto illegal_request;
}
@@ -780,7 +811,6 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
uint8_t *buf, int lun)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
- uint64_t nb_sectors;
uint64_t lba;
uint32_t len;
int cmdlen;
@@ -873,6 +903,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case SYNCHRONIZE_CACHE:
case READ_TOC:
case GET_CONFIGURATION:
+ case SERVICE_ACTION_IN:
rc = scsi_disk_emulate_command(&r->req, outbuf);
if (rc > 0) {
r->iov.iov_len = rc;
@@ -901,40 +932,6 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
r->sector_count = len * s->cluster_size;
is_write = 1;
break;
- case 0x9e:
- /* Service Action In subcommands. */
- if ((buf[1] & 31) == 0x10) {
- DPRINTF("SAI READ CAPACITY(16)\n");
- memset(outbuf, 0, len);
- bdrv_get_geometry(s->qdev.dinfo->bdrv, &nb_sectors);
- nb_sectors /= s->cluster_size;
- /* Returned value is the address of the last sector. */
- if (nb_sectors) {
- nb_sectors--;
- /* Remember the new size for read/write sanity checking. */
- s->max_lba = nb_sectors;
- outbuf[0] = (nb_sectors >> 56) & 0xff;
- outbuf[1] = (nb_sectors >> 48) & 0xff;
- outbuf[2] = (nb_sectors >> 40) & 0xff;
- outbuf[3] = (nb_sectors >> 32) & 0xff;
- outbuf[4] = (nb_sectors >> 24) & 0xff;
- outbuf[5] = (nb_sectors >> 16) & 0xff;
- outbuf[6] = (nb_sectors >> 8) & 0xff;
- outbuf[7] = nb_sectors & 0xff;
- outbuf[8] = 0;
- outbuf[9] = 0;
- outbuf[10] = s->cluster_size * 2;
- outbuf[11] = 0;
- /* Protection, exponent and lowest lba field left blank. */
- r->iov.iov_len = len;
- } else {
- scsi_command_complete(r, CHECK_CONDITION, NOT_READY);
- return 0;
- }
- break;
- }
- DPRINTF("Unsupported Service Action In\n");
- goto fail;
case 0xa0:
DPRINTF("Report LUNs (len %d)\n", len);
if (len < 16)
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 28/30] scsi-disk: restruct emulation: REPORT_LUNS
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (26 preceding siblings ...)
2009-11-26 14:34 ` [Qemu-devel] [PATCH 27/30] scsi-disk: restruct emulation: SERVICE_ACTION_IN Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 29/30] scsi-disk: restruct emulation: VERIFY Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 30/30] scsi: add read/write 16 commands Gerd Hoffmann
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Move REPORT_LUNS emulation from scsi_send_command() to
scsi_disk_emulate_command().
Also add REPORT_LUNS to scsi-defs.h and scsi_command_name().
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-bus.c | 1 +
hw/scsi-defs.h | 1 +
hw/scsi-disk.c | 16 ++++++++--------
3 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index deb6b4f..b6de5c6 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -442,6 +442,7 @@ static const char *scsi_command_name(uint8_t cmd)
[ REPORT_DENSITY_SUPPORT ] = "REPORT_DENSITY_SUPPORT",
[ GET_CONFIGURATION ] = "GET_CONFIGURATION",
[ SERVICE_ACTION_IN ] = "SERVICE_ACTION_IN",
+ [ REPORT_LUNS ] = "REPORT_LUNS",
[ LOAD_UNLOAD ] = "LOAD_UNLOAD",
[ SET_CD_SPEED ] = "SET_CD_SPEED",
[ BLANK ] = "BLANK",
diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
index 4aeb667..cc7f35e 100644
--- a/hw/scsi-defs.h
+++ b/hw/scsi-defs.h
@@ -101,6 +101,7 @@
#define REPORT_DENSITY_SUPPORT 0x44
#define GET_CONFIGURATION 0x46
#define SERVICE_ACTION_IN 0x9e
+#define REPORT_LUNS 0xa0
#define LOAD_UNLOAD 0xa6
#define SET_CD_SPEED 0xbb
#define BLANK 0xa1
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index b481c13..1507bcd 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -787,6 +787,13 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
}
DPRINTF("Unsupported Service Action In\n");
goto illegal_request;
+ case REPORT_LUNS:
+ if (req->cmd.xfer < 16)
+ goto illegal_request;
+ memset(outbuf, 0, 16);
+ outbuf[3] = 8;
+ buflen = 16;
+ break;
default:
goto illegal_request;
}
@@ -904,6 +911,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case READ_TOC:
case GET_CONFIGURATION:
case SERVICE_ACTION_IN:
+ case REPORT_LUNS:
rc = scsi_disk_emulate_command(&r->req, outbuf);
if (rc > 0) {
r->iov.iov_len = rc;
@@ -932,14 +940,6 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
r->sector_count = len * s->cluster_size;
is_write = 1;
break;
- case 0xa0:
- DPRINTF("Report LUNs (len %d)\n", len);
- if (len < 16)
- goto fail;
- memset(outbuf, 0, 16);
- outbuf[3] = 8;
- r->iov.iov_len = 16;
- break;
case VERIFY:
DPRINTF("Verify (sector %" PRId64 ", count %d)\n", lba, len);
break;
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 29/30] scsi-disk: restruct emulation: VERIFY
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (27 preceding siblings ...)
2009-11-26 14:34 ` [Qemu-devel] [PATCH 28/30] scsi-disk: restruct emulation: REPORT_LUNS Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
2009-11-26 14:34 ` [Qemu-devel] [PATCH 30/30] scsi: add read/write 16 commands Gerd Hoffmann
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Move VERIFY emulation from scsi_send_command() to
scsi_disk_emulate_command().
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-disk.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 1507bcd..2910782 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -794,6 +794,8 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
outbuf[3] = 8;
buflen = 16;
break;
+ case VERIFY:
+ break;
default:
goto illegal_request;
}
@@ -912,6 +914,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case GET_CONFIGURATION:
case SERVICE_ACTION_IN:
case REPORT_LUNS:
+ case VERIFY:
rc = scsi_disk_emulate_command(&r->req, outbuf);
if (rc > 0) {
r->iov.iov_len = rc;
@@ -940,9 +943,6 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
r->sector_count = len * s->cluster_size;
is_write = 1;
break;
- case VERIFY:
- DPRINTF("Verify (sector %" PRId64 ", count %d)\n", lba, len);
- break;
default:
DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
fail:
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH 30/30] scsi: add read/write 16 commands.
2009-11-26 14:33 [Qemu-devel] [PATCH 00/30] scsi: data structures and cleanups Gerd Hoffmann
` (28 preceding siblings ...)
2009-11-26 14:34 ` [Qemu-devel] [PATCH 29/30] scsi-disk: restruct emulation: VERIFY Gerd Hoffmann
@ 2009-11-26 14:34 ` Gerd Hoffmann
29 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-11-26 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Add READ_16 + friends to scsi-defs.h, scsi_command_name() and the
request parsing helper functions.
Use them in scsi-disk.c too.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/scsi-bus.c | 8 ++++++++
hw/scsi-defs.h | 3 +++
hw/scsi-disk.c | 6 ++++--
3 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index b6de5c6..736e91e 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -228,6 +228,8 @@ static int scsi_req_length(SCSIRequest *req, uint8_t *cmd)
case WRITE_6:
case WRITE_12:
case WRITE_VERIFY_12:
+ case WRITE_16:
+ case WRITE_VERIFY_16:
req->cmd.xfer *= req->dev->blocksize;
break;
case READ_10:
@@ -235,6 +237,7 @@ static int scsi_req_length(SCSIRequest *req, uint8_t *cmd)
case READ_REVERSE:
case RECOVER_BUFFERED_DATA:
case READ_12:
+ case READ_16:
req->cmd.xfer *= req->dev->blocksize;
break;
case INQUIRY:
@@ -277,6 +280,8 @@ static void scsi_req_xfer_mode(SCSIRequest *req)
case WRITE_VERIFY:
case WRITE_12:
case WRITE_VERIFY_12:
+ case WRITE_16:
+ case WRITE_VERIFY_16:
case COPY:
case COPY_VERIFY:
case COMPARE:
@@ -441,6 +446,9 @@ static const char *scsi_command_name(uint8_t cmd)
[ REWIND ] = "REWIND",
[ REPORT_DENSITY_SUPPORT ] = "REPORT_DENSITY_SUPPORT",
[ GET_CONFIGURATION ] = "GET_CONFIGURATION",
+ [ READ_16 ] = "READ_16",
+ [ WRITE_16 ] = "WRITE_16",
+ [ WRITE_VERIFY_16 ] = "WRITE_VERIFY_16",
[ SERVICE_ACTION_IN ] = "SERVICE_ACTION_IN",
[ REPORT_LUNS ] = "REPORT_LUNS",
[ LOAD_UNLOAD ] = "LOAD_UNLOAD",
diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
index cc7f35e..4759d80 100644
--- a/hw/scsi-defs.h
+++ b/hw/scsi-defs.h
@@ -100,6 +100,9 @@
#define REWIND 0x01
#define REPORT_DENSITY_SUPPORT 0x44
#define GET_CONFIGURATION 0x46
+#define READ_16 0x88
+#define WRITE_16 0x8a
+#define WRITE_VERIFY_16 0x8e
#define SERVICE_ACTION_IN 0x9e
#define REPORT_LUNS 0xa0
#define LOAD_UNLOAD 0xa6
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 2910782..c802ccd 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -926,7 +926,8 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
break;
case READ_6:
case READ_10:
- case 0x88:
+ case READ_12:
+ case READ_16:
DPRINTF("Read (sector %" PRId64 ", count %d)\n", lba, len);
if (lba > s->max_lba)
goto illegal_lba;
@@ -935,7 +936,8 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
break;
case WRITE_6:
case WRITE_10:
- case 0x8a:
+ case WRITE_12:
+ case WRITE_16:
DPRINTF("Write (sector %" PRId64 ", count %d)\n", lba, len);
if (lba > s->max_lba)
goto illegal_lba;
--
1.6.2.5
^ permalink raw reply related [flat|nested] 31+ messages in thread