From: Anthony Liguori <anthony@codemonkey.ws>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [6468] support >2TB SCSI disks (Rik van Riel)
Date: Wed, 28 Jan 2009 21:58:26 +0000 [thread overview]
Message-ID: <E1LSIQU-000442-5y@cvs.savannah.gnu.org> (raw)
Revision: 6468
http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=6468
Author: aliguori
Date: 2009-01-28 21:58:25 +0000 (Wed, 28 Jan 2009)
Log Message:
-----------
support >2TB SCSI disks (Rik van Riel)
Implement SCSI READ(16), WRITE(16) and SAI READ CAPACITY(16) commands,
so SCSI disks larger than 2TB can work with guests that support these
newer SCSI commands.
The cast to (uint64_t) is needed because otherwise gcc will use a
signed int, which gets sign extended into uint64_t lba, resulting
in bad block numbers for READ 10 and READ 16 with block numbers
larger than 2^31.
Signed-off-by: Rik van Riel <riel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Modified Paths:
--------------
trunk/hw/scsi-disk.c
Modified: trunk/hw/scsi-disk.c
===================================================================
--- trunk/hw/scsi-disk.c 2009-01-28 21:58:22 UTC (rev 6467)
+++ trunk/hw/scsi-disk.c 2009-01-28 21:58:25 UTC (rev 6468)
@@ -346,7 +346,7 @@
{
SCSIDeviceState *s = d->state;
uint64_t nb_sectors;
- uint32_t lba;
+ uint64_t lba;
uint32_t len;
int cmdlen;
int is_write;
@@ -368,23 +368,29 @@
DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
switch (command >> 5) {
case 0:
- lba = buf[3] | (buf[2] << 8) | ((buf[1] & 0x1f) << 16);
+ lba = (uint64_t) buf[3] | ((uint64_t) buf[2] << 8) |
+ (((uint64_t) buf[1] & 0x1f) << 16);
len = buf[4];
cmdlen = 6;
break;
case 1:
case 2:
- lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
+ lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
+ ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
len = buf[8] | (buf[7] << 8);
cmdlen = 10;
break;
case 4:
- lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
+ lba = (uint64_t) buf[9] | ((uint64_t) buf[8] << 8) |
+ ((uint64_t) buf[7] << 16) | ((uint64_t) buf[6] << 24) |
+ ((uint64_t) buf[5] << 32) | ((uint64_t) buf[4] << 40) |
+ ((uint64_t) buf[3] << 48) | ((uint64_t) buf[2] << 56);
len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
cmdlen = 16;
break;
case 5:
- lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
+ lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
+ ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
cmdlen = 12;
break;
@@ -750,13 +756,15 @@
break;
case 0x08:
case 0x28:
- DPRINTF("Read (sector %d, count %d)\n", lba, len);
+ case 0x88:
+ DPRINTF("Read (sector %lld, count %d)\n", lba, len);
r->sector = lba * s->cluster_size;
r->sector_count = len * s->cluster_size;
break;
case 0x0a:
case 0x2a:
- DPRINTF("Write (sector %d, count %d)\n", lba, len);
+ case 0x8a:
+ DPRINTF("Write (sector %lld, count %d)\n", lba, len);
r->sector = lba * s->cluster_size;
r->sector_count = len * s->cluster_size;
is_write = 1;
@@ -820,6 +828,37 @@
if (buf[1] & 3)
goto fail;
break;
+ case 0x9e:
+ /* Service Action In subcommands. */
+ if ((buf[1] & 31) == 0x10) {
+ DPRINTF("SAI READ CAPACITY(16)\n");
+ memset(outbuf, 0, len);
+ bdrv_get_geometry(s->bdrv, &nb_sectors);
+ /* Returned value is the address of the last sector. */
+ if (nb_sectors) {
+ nb_sectors--;
+ outbuf[0] = (nb_sectors >> 56) & 0xff;
+ outbuf[1] = (nb_sectors >> 48) & 0xff;
+ outbuf[2] = (nb_sectors >> 40) & 0xff;
+ outbuf[3] = (nb_sectors >> 32) & 0xff;
+ outbuf[4] = (nb_sectors >> 24) & 0xff;
+ outbuf[5] = (nb_sectors >> 16) & 0xff;
+ outbuf[6] = (nb_sectors >> 8) & 0xff;
+ outbuf[7] = nb_sectors & 0xff;
+ outbuf[8] = 0;
+ outbuf[9] = 0;
+ outbuf[10] = s->cluster_size * 2;
+ outbuf[11] = 0;
+ /* Protection, exponent and lowest lba field left blank. */
+ r->buf_len = len;
+ } else {
+ scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NOT_READY);
+ return 0;
+ }
+ break;
+ }
+ DPRINTF("Unsupported Service Action In\n");
+ goto fail;
case 0xa0:
DPRINTF("Report LUNs (len %d)\n", len);
if (len < 16)
reply other threads:[~2009-01-28 21:58 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=E1LSIQU-000442-5y@cvs.savannah.gnu.org \
--to=anthony@codemonkey.ws \
--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).