qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Igor Kovalenko" <igor.v.kovalenko@gmail.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH] implement more INQUIRY command replies for scsi disk
Date: Tue, 29 Jan 2008 08:12:12 +0300	[thread overview]
Message-ID: <b2fa41d60801282112u6897bb94k333e8e794094d05e@mail.gmail.com> (raw)

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

>From what I see there are more bits of scsi INQUIRY command which are mandatory,
and this patch adds two mandatory and one optional scsi VPD page to that command
reply. Also handled optional "command support data" request, with error reply.

Please apply qemu-scsi-disk-inquiry-20080129-2.patch attached.

With this patch I'm able to install openSUSE x86 on 10Gb scsi disk
(emulated, image).
Without this patch I see the following emulation error messages:
scsi-disk: Orphaned request
lsi_scsi: error: IO with unknown tag 65579 (tag number varies)
and once
lsi_scsi: error: Reselect with pending DMA
Seems like Linux sym driver really does not like missing VPD replies,
or there is some problem with lsi emulation in qemu.

-- 
Kind regards,
Igor V. Kovalenko

[-- Attachment #2: qemu-scsi-disk-inquiry-20080129-2.patch --]
[-- Type: application/octet-stream, Size: 5442 bytes --]

Index: hw/scsi-disk.c
===================================================================
RCS file: /cvsroot/qemu/qemu/hw/scsi-disk.c,v
retrieving revision 1.19
diff -u -p -r1.19 scsi-disk.c
--- hw/scsi-disk.c	24 Dec 2007 14:33:24 -0000	1.19
+++ hw/scsi-disk.c	29 Jan 2008 05:06:59 -0000
@@ -362,8 +362,121 @@ static int32_t scsi_send_command(SCSIDev
         break;
     case 0x12:
         DPRINTF("Inquiry (len %d)\n", len);
-        if (len < 36) {
-            BADF("Inquiry buffer too small (%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->buf_len = 0;
+
+                        if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
+                            outbuf[r->buf_len++] = 5;
+                        } else {
+                            outbuf[r->buf_len++] = 0;
+                        }
+
+                        outbuf[r->buf_len++] = 0x00; // this page
+                        outbuf[r->buf_len++] = 0x00;
+                        outbuf[r->buf_len++] = 3;    // number of pages
+                        outbuf[r->buf_len++] = 0x00; // list of supported pages (this page)
+                        outbuf[r->buf_len++] = 0x80; // unit serial number
+                        outbuf[r->buf_len++] = 0x83; // device identification
+                    }
+                    break;
+                case 0x80:
+                    {
+                        // 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);
+
+                        r->buf_len = 0;
+
+                        // supported page codes
+                        if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
+                            outbuf[r->buf_len++] = 5;
+                        } else {
+                            outbuf[r->buf_len++] = 0;
+                        }
+
+                        outbuf[r->buf_len++] = 0x80; // this page
+                        outbuf[r->buf_len++] = 0x00;
+                        outbuf[r->buf_len++] = 0x01; // 1 byte data follow
+
+                        outbuf[r->buf_len++] = '0'; // 1 byte data follow
+                    }
+
+                    break;
+                case 0x83:
+                    {
+                        // device identification page, mandatory
+                        int max_len = 255 - 8;
+                        int id_len = strlen(bdrv_get_device_name(s->bdrv));
+                        if (id_len > max_len)
+                            id_len = max_len;
+
+                        DPRINTF("Inquiry EVPD[Device identification] buffer size %d\n", len);
+                        r->buf_len = 0;
+                        if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
+                            outbuf[r->buf_len++] = 5;
+                        } else {
+                            outbuf[r->buf_len++] = 0;
+                        }
+
+                        outbuf[r->buf_len++] = 0x83; // this page
+                        outbuf[r->buf_len++] = 0x00;
+                        outbuf[r->buf_len++] = 3 + id_len;
+
+                        outbuf[r->buf_len++] = 0x2; // ASCII
+                        outbuf[r->buf_len++] = 0;   // not officially assigned
+                        outbuf[r->buf_len++] = 0;   // reserved
+                        outbuf[r->buf_len++] = id_len; // length of data following
+
+                        memcpy(&outbuf[r->buf_len], bdrv_get_device_name(s->bdrv), id_len);
+                        r->buf_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);
+            }
         }
 	memset(outbuf, 0, 36);
 	if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {

                 reply	other threads:[~2008-01-29  5:12 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=b2fa41d60801282112u6897bb94k333e8e794094d05e@mail.gmail.com \
    --to=igor.v.kovalenko@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

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

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).