qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] implement more INQUIRY command replies for scsi disk
@ 2008-01-29  5:12 Igor Kovalenko
  0 siblings, 0 replies; only message in thread
From: Igor Kovalenko @ 2008-01-29  5:12 UTC (permalink / raw)
  To: qemu-devel

[-- 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) {

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2008-01-29  5:12 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-29  5:12 [Qemu-devel] [PATCH] implement more INQUIRY command replies for scsi disk Igor Kovalenko

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).