From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Ki3dD-0005Fa-Hh for qemu-devel@nongnu.org; Tue, 23 Sep 2008 04:52:27 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Ki3dB-0005Ec-7Y for qemu-devel@nongnu.org; Tue, 23 Sep 2008 04:52:26 -0400 Received: from [199.232.76.173] (port=47887 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Ki3dA-0005EG-IP for qemu-devel@nongnu.org; Tue, 23 Sep 2008 04:52:24 -0400 Received: from ecfrec.frec.bull.fr ([129.183.4.8]:41926) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1Ki3d9-0000Tc-JO for qemu-devel@nongnu.org; Tue, 23 Sep 2008 04:52:24 -0400 Received: from localhost (localhost [127.0.0.1]) by ecfrec.frec.bull.fr (Postfix) with ESMTP id 991761A19A6 for ; Tue, 23 Sep 2008 10:52:15 +0200 (CEST) Received: from ecfrec.frec.bull.fr ([127.0.0.1]) by localhost (ecfrec.frec.bull.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 06190-06 for ; Tue, 23 Sep 2008 10:52:11 +0200 (CEST) Received: from cyclope.frec.bull.fr (cyclope.frec.bull.fr [129.183.4.9]) by ecfrec.frec.bull.fr (Postfix) with ESMTP id A5A9D1A197C for ; Tue, 23 Sep 2008 10:51:19 +0200 (CEST) Received: from [129.183.101.63] (frecb007144.frec.bull.fr [129.183.101.63]) by cyclope.frec.bull.fr (Postfix) with ESMTP id C64EA2728D for ; Tue, 23 Sep 2008 10:51:17 +0200 (CEST) From: Laurent Vivier In-Reply-To: <48D7F021.5040102@codemonkey.ws> References: <1222099458.4151.20.camel@frecb07144> <48D7F021.5040102@codemonkey.ws> Content-Type: multipart/mixed; boundary="=-akolBqZNvVq78c4xfL+y" Date: Tue, 23 Sep 2008 10:51:25 +0200 Message-Id: <1222159885.4166.7.camel@frecb07144> Mime-Version: 1.0 Subject: [Qemu-devel] [PATCH][v2] scsi-generic: decode correctly SCSI tape commands Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org --=-akolBqZNvVq78c4xfL+y Content-Type: text/plain Content-Transfer-Encoding: 7bit --=-akolBqZNvVq78c4xfL+y Content-Disposition: inline; filename=scsi-generic-tape.patch Content-Type: text/x-patch; name=scsi-generic-tape.patch; charset=UTF-8 Content-Transfer-Encoding: 7bit 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 remain 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 --- hw/scsi-generic.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 9 deletions(-) Index: qemu/hw/scsi-generic.c =================================================================== --- qemu.orig/hw/scsi-generic.c 2008-09-23 10:04:06.000000000 +0200 +++ qemu/hw/scsi-generic.c 2008-09-23 10:38:45.000000000 +0200 @@ -44,12 +44,14 @@ do { fprintf(stderr, "scsi-generic: " fm #include #include +#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,14 @@ 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 = MIN(r->len, SCSI_SENSE_BUF_SIZE); + 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 +441,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 +528,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 +673,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 */ --=-akolBqZNvVq78c4xfL+y--