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