All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Vivier <Laurent.Vivier@bull.net>
To: "qemu-devel@nongnu.org" <qemu-devel@nongnu.org>
Subject: [Qemu-devel] [PATCH] scsi-generic: decode correctly SCSI tape commands
Date: Mon, 22 Sep 2008 18:04:18 +0200	[thread overview]
Message-ID: <1222099458.4151.20.camel@frecb07144> (raw)

This patch allows to use a "real" SCSI tape with qemu using
"-drive /dev/sgX,if=scsi".

It allows to decode correctly transfer length when the type of the
device is a tape.

Some issues subsist when the application reading the tape tries to go
beyond the end of the stream (but they must be corrected at the SCSI
controller level).

Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net>
---
 hw/scsi-generic.c |   64 ++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 55 insertions(+), 9 deletions(-)

Index: qemu/hw/scsi-generic.c
===================================================================
--- qemu.orig/hw/scsi-generic.c	2008-09-22 17:40:54.000000000 +0200
+++ qemu/hw/scsi-generic.c	2008-09-22 17:44:52.000000000 +0200
@@ -44,12 +44,14 @@ do { fprintf(stderr, "scsi-generic: " fm
 #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
 
 #define SCSI_CMD_BUF_SIZE     16
-#define SCSI_SENSE_BUF_SIZE 32
+#define SCSI_SENSE_BUF_SIZE 96
 
 #define SG_ERR_DRIVER_TIMEOUT 0x06
 #define SG_ERR_DRIVER_SENSE 0x08
@@ -75,6 +77,7 @@ struct SCSIDeviceState
 {
     SCSIRequest *requests;
     BlockDriverState *bdrv;
+    int type;
     int blocksize;
     int lun;
     scsi_completionfn completion;
@@ -163,7 +166,7 @@ static void scsi_command_complete(void *
         } else if ((s->driver_status & SG_ERR_DRIVER_SENSE) == 0)
             sense = NO_SENSE;
         else
-            sense = s->sensebuf[2] & 0x0f;
+            sense = s->sensebuf[2];
     }
 
     DPRINTF("Command complete 0x%p tag=0x%x sense=%d\n", r, r->tag, sense);
@@ -273,10 +276,15 @@ static void scsi_read_data(SCSIDevice *d
 
     if (r->cmd[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
     {
-        memcpy(r->buf, s->sensebuf, 16);
+	int len;
+        len = r->len > SCSI_SENSE_BUF_SIZE ? SCSI_SENSE_BUF_SIZE : r->len;
+        memcpy(r->buf, s->sensebuf, len);
         r->io_header.driver_status = 0;
         r->len = -1;
-        s->completion(s->opaque, SCSI_REASON_DATA, r->tag, 16);
+        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]);
+        s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len);
         return;
     }
 
@@ -434,6 +442,32 @@ static int scsi_length(uint8_t *cmd, int
     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;
+        break;
+    case REWIND:
+    case START_STOP:
+        *cmdlen = 6;
+        *len = 0;
+        cmd[1] = 0x01;	/* force IMMED, otherwise qemu waits end of command */
+        break;
+    /* generic commands */
+    default:
+        return scsi_length(cmd, blocksize, cmdlen, len);
+    }
+    return 0;
+}
+
 static int is_write(int command)
 {
     switch (command) {
@@ -495,9 +529,16 @@ static int32_t scsi_send_command(SCSIDev
         return 0;
     }
 
-    if (scsi_length(cmd, s->blocksize, &cmdlen, &len) == -1) {
-        BADF("Unsupported command length, command %x\n", cmd[0]);
-        return 0;
+    if (s->type == TYPE_TAPE) {
+        if (scsi_stream_length(cmd, s->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) {
+            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,
@@ -633,12 +674,17 @@ SCSIDevice *scsi_generic_init(BlockDrive
     s->completion = completion;
     s->opaque = opaque;
     s->lun = scsiid.lun;
+    s->type = scsiid.scsi_type;
     s->blocksize = get_blocksize(s->bdrv);
     s->driver_status = 0;
     memset(s->sensebuf, 0, sizeof(s->sensebuf));
     /* removable media returns 0 if not present */
-    if (s->blocksize <= 0)
-        s->blocksize = 2048;
+    if (s->blocksize <= 0) {
+        if (s->type == TYPE_ROM || s->type  == TYPE_WORM)
+            s->blocksize = 2048;
+        else
+            s->blocksize = 512;
+    }
 
     /* define function to manage device */
 

             reply	other threads:[~2008-09-22 16:04 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-22 16:04 Laurent Vivier [this message]
2008-09-22 19:21 ` [Qemu-devel] [PATCH] scsi-generic: decode correctly SCSI tape commands Anthony Liguori
2008-09-23  8:51   ` [Qemu-devel] [PATCH][v2] " Laurent Vivier
2008-09-23 13:38     ` Anthony Liguori

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1222099458.4151.20.camel@frecb07144 \
    --to=laurent.vivier@bull.net \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.