From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LS1Nh-0000J2-KY for qemu-devel@nongnu.org; Tue, 27 Jan 2009 22:46:25 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LS1Nf-0000Fh-Mn for qemu-devel@nongnu.org; Tue, 27 Jan 2009 22:46:24 -0500 Received: from [199.232.76.173] (port=52566 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LS1Nf-0000FU-I0 for qemu-devel@nongnu.org; Tue, 27 Jan 2009 22:46:23 -0500 Received: from mx2.redhat.com ([66.187.237.31]:43268) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LS1Ne-0000K7-Vl for qemu-devel@nongnu.org; Tue, 27 Jan 2009 22:46:23 -0500 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n0S3kLFQ021283 for ; Tue, 27 Jan 2009 22:46:21 -0500 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n0S3kLrX029703 for ; Tue, 27 Jan 2009 22:46:21 -0500 Received: from bree.surriel.com (vpn-10-4.bos.redhat.com [10.16.10.4]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n0S3kLpU021280 for ; Tue, 27 Jan 2009 22:46:21 -0500 Date: Tue, 27 Jan 2009 22:46:19 -0500 From: Rik van Riel Message-ID: <20090127224619.3ae16173@bree.surriel.com> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH] support >2TB SCSI disks 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 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. This patch depends on the sector overflow fix patch I mailed yesterday. Signed-off-by: Rik van Riel Index: trunk/hw/scsi-disk.c =================================================================== --- trunk/hw/scsi-disk.c (revision 6465) +++ trunk/hw/scsi-disk.c (working copy) @@ -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; @@ -747,13 +753,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; @@ -817,6 +825,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)