I have been trying to get Minolta Multi Pro SCSI film scanner working
with Qemu in Linux and WinXP guests.  With Linux guest and virtio
interface the scanner works out of the box. Unfortunately I haven't
been able to find virtio SCSI driver for Win XP.

With Linux guest and pvscsi driver additional patches are needed to
add support for some missing commands. The same patches are also
needed with WinXP guest with virtual LSI SCSI adapter drivers.

With these patches I am able to do index scan, frame selection,
prescan, focus, scanner calibration,main scan (35mm and medium format)
and do the transport lockup. What is still missing is the real
implementation of REQUEST SENSE command with extra bytes which the
scanner application use with focusing.

Few times the scans start return nothing but black in XP but native
Vuescan in Linux works just right and I have to restart the scanner to
fix this.

I've also seen soft lockups while scanning with Test Unit Ready / Mode
Sense in loop with kernel watchdog nagging. Could be that too verbose
SCSI debugging is choking the system. I haven't touched the kernel
(4.4.14) only written 022000" or 022022 (not the octal number but
decimal value) to /proc/sys/dev/scsi/logging_level.

But these patches are still a proof of concept. I am able to use the
SCSI scanner with virtual LSI adapter from Qemu with XP or Linux guest
and and almost everything works. With VMware and VirtualBox not much
or almost nothing works.

Jarkko Lavinen
>From 9358393e19dc1fcf85e9371cb50b6dfb9c640d42 Mon Sep 17 00:00:00 2001
From: Jarkko Lavinen <jarkko.lavi...@iki.fi>
Date: Tue, 28 Jun 2016 17:26:58 +0300
Subject: [PATCH 1/2] scsi-bus: Use correct transfer lengths for common SCSI
 commands

Fix the transfer lenghts as per ANSI spec section 8. The change for
INQUIRY and REQUEST_SENSE are cosmetic and have no effect when commands
are emulated.

Signed-off-by: Jarkko Lavinen <jarkko.lavi...@iki.fi>
---
 hw/scsi/scsi-bus.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index ad6f398..045594a 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -949,7 +949,15 @@ static int scsi_req_xfer(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
         }
         cmd->xfer *= dev->blocksize;
         break;
+    case INQUIRY:
     case MODE_SENSE:
+    case MODE_SELECT:
+    case REQUEST_SENSE:
+        cmd->xfer = buf[4];
+        break;
+    case MODE_SENSE_10:
+    case MODE_SELECT_10:
+        cmd->xfer = (buf[7] << 8) | buf[8];
         break;
     case WRITE_SAME_10:
     case WRITE_SAME_16:
@@ -1004,7 +1012,6 @@ static int scsi_req_xfer(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
             cmd->xfer = (buf[1] & 16) == 0 ? 0 : (buf[1] & 32 ? 8 : 4);
         }
         break;
-    case INQUIRY:
     case RECEIVE_DIAGNOSTIC:
     case SEND_DIAGNOSTIC:
         cmd->xfer = buf[4] | (buf[3] << 8);
@@ -1132,7 +1139,6 @@ static int scsi_req_medium_changer_xfer(SCSICommand *cmd, SCSIDevice *dev, uint8
     return 0;
 }
 
-
 static void scsi_cmd_xfer_mode(SCSICommand *cmd)
 {
     if (!cmd->xfer) {
-- 
2.1.4

>From e78b81f02cb53369499a0cc70495f1b84f6dbfc8 Mon Sep 17 00:00:00 2001
From: Jarkko Lavinen <jarkko.lavi...@iki.fi>
Date: Tue, 28 Jun 2016 17:49:41 +0300
Subject: [PATCH 2/2] scsi-bus: Add SCSI scanner support

Add support for missing scanner specific SCSI commands and their xfer
lenghts as per ANSI spec section 15.

Signed-off-by: Jarkko Lavinen <jarkko.lavi...@iki.fi>
---
 hw/scsi/scsi-bus.c   | 31 +++++++++++++++++++++++++++++++
 include/block/scsi.h |  6 ++++++
 2 files changed, 37 insertions(+)

diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 045594a..2f8da49 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -1139,6 +1139,32 @@ static int scsi_req_medium_changer_xfer(SCSICommand *cmd, SCSIDevice *dev, uint8
     return 0;
 }
 
+static int scsi_req_scanner_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
+{
+    switch (buf[0]) {
+    /* Scanner commands */
+    case OBJECT_POSITION:
+        cmd->xfer = 0;
+        break;
+    case GET_DATA_BUFFER_STATUS:
+        cmd->xfer = buf[8] | (buf[7] << 8);
+        break;
+    case SCAN:
+        cmd->xfer = buf[4];
+        break;
+    case READ_10:
+    case SEND:
+    case GET_WINDOW:
+    case SET_WINDOW:
+        cmd->xfer = buf[8] | (buf[7] << 8) | (buf[6] << 16);
+        break;
+    default:
+        return scsi_req_xfer(cmd, dev, buf);
+    }
+
+    return 0;
+}
+
 static void scsi_cmd_xfer_mode(SCSICommand *cmd)
 {
     if (!cmd->xfer) {
@@ -1184,6 +1210,8 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd)
     case SEND_DVD_STRUCTURE:
     case PERSISTENT_RESERVE_OUT:
     case MAINTENANCE_OUT:
+    case SET_WINDOW:
+    case SCAN:
         cmd->mode = SCSI_XFER_TO_DEV;
         break;
     case ATA_PASSTHROUGH_12:
@@ -1264,6 +1292,9 @@ int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf)
     case TYPE_MEDIUM_CHANGER:
         rc = scsi_req_medium_changer_xfer(cmd, dev, buf);
         break;
+    case TYPE_SCANNER:
+        rc = scsi_req_scanner_length(cmd, dev, buf);
+        break;
     default:
         rc = scsi_req_xfer(cmd, dev, buf);
         break;
diff --git a/include/block/scsi.h b/include/block/scsi.h
index a311341..8b966d7 100644
--- a/include/block/scsi.h
+++ b/include/block/scsi.h
@@ -48,13 +48,17 @@
 #define ERASE                 0x19
 #define MODE_SENSE            0x1a
 #define LOAD_UNLOAD           0x1b
+#define SCAN                  0x1b
 #define START_STOP            0x1b
 #define RECEIVE_DIAGNOSTIC    0x1c
 #define SEND_DIAGNOSTIC       0x1d
 #define ALLOW_MEDIUM_REMOVAL  0x1e
+#define SET_WINDOW            0x24
 #define READ_CAPACITY_10      0x25
+#define GET_WINDOW            0x25
 #define READ_10               0x28
 #define WRITE_10              0x2a
+#define SEND                  0x2a
 #define SEEK_10               0x2b
 #define LOCATE_10             0x2b
 #define POSITION_TO_ELEMENT   0x2b
@@ -62,10 +66,12 @@
 #define VERIFY_10             0x2f
 #define SEARCH_HIGH           0x30
 #define SEARCH_EQUAL          0x31
+#define OBJECT_POSITION       0x31
 #define SEARCH_LOW            0x32
 #define SET_LIMITS            0x33
 #define PRE_FETCH             0x34
 #define READ_POSITION         0x34
+#define GET_DATA_BUFFER_STATUS 0x34
 #define SYNCHRONIZE_CACHE     0x35
 #define LOCK_UNLOCK_CACHE     0x36
 #define INITIALIZE_ELEMENT_STATUS_WITH_RANGE 0x37
-- 
2.1.4

Reply via email to