Commit 86106e5920d90a92d72ca50ca5aadafd6c1f6c80

Authored by aliguori
1 parent e035b43d

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>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6468 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 46 additions and 7 deletions
hw/scsi-disk.c
@@ -346,7 +346,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, @@ -346,7 +346,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
346 { 346 {
347 SCSIDeviceState *s = d->state; 347 SCSIDeviceState *s = d->state;
348 uint64_t nb_sectors; 348 uint64_t nb_sectors;
349 - uint32_t lba; 349 + uint64_t lba;
350 uint32_t len; 350 uint32_t len;
351 int cmdlen; 351 int cmdlen;
352 int is_write; 352 int is_write;
@@ -368,23 +368,29 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, @@ -368,23 +368,29 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
368 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]); 368 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
369 switch (command >> 5) { 369 switch (command >> 5) {
370 case 0: 370 case 0:
371 - lba = buf[3] | (buf[2] << 8) | ((buf[1] & 0x1f) << 16); 371 + lba = (uint64_t) buf[3] | ((uint64_t) buf[2] << 8) |
  372 + (((uint64_t) buf[1] & 0x1f) << 16);
372 len = buf[4]; 373 len = buf[4];
373 cmdlen = 6; 374 cmdlen = 6;
374 break; 375 break;
375 case 1: 376 case 1:
376 case 2: 377 case 2:
377 - lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24); 378 + lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
  379 + ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
378 len = buf[8] | (buf[7] << 8); 380 len = buf[8] | (buf[7] << 8);
379 cmdlen = 10; 381 cmdlen = 10;
380 break; 382 break;
381 case 4: 383 case 4:
382 - lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24); 384 + lba = (uint64_t) buf[9] | ((uint64_t) buf[8] << 8) |
  385 + ((uint64_t) buf[7] << 16) | ((uint64_t) buf[6] << 24) |
  386 + ((uint64_t) buf[5] << 32) | ((uint64_t) buf[4] << 40) |
  387 + ((uint64_t) buf[3] << 48) | ((uint64_t) buf[2] << 56);
383 len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24); 388 len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
384 cmdlen = 16; 389 cmdlen = 16;
385 break; 390 break;
386 case 5: 391 case 5:
387 - lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24); 392 + lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
  393 + ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
388 len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24); 394 len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
389 cmdlen = 12; 395 cmdlen = 12;
390 break; 396 break;
@@ -750,13 +756,15 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, @@ -750,13 +756,15 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
750 break; 756 break;
751 case 0x08: 757 case 0x08:
752 case 0x28: 758 case 0x28:
753 - DPRINTF("Read (sector %d, count %d)\n", lba, len); 759 + case 0x88:
  760 + DPRINTF("Read (sector %lld, count %d)\n", lba, len);
754 r->sector = lba * s->cluster_size; 761 r->sector = lba * s->cluster_size;
755 r->sector_count = len * s->cluster_size; 762 r->sector_count = len * s->cluster_size;
756 break; 763 break;
757 case 0x0a: 764 case 0x0a:
758 case 0x2a: 765 case 0x2a:
759 - DPRINTF("Write (sector %d, count %d)\n", lba, len); 766 + case 0x8a:
  767 + DPRINTF("Write (sector %lld, count %d)\n", lba, len);
760 r->sector = lba * s->cluster_size; 768 r->sector = lba * s->cluster_size;
761 r->sector_count = len * s->cluster_size; 769 r->sector_count = len * s->cluster_size;
762 is_write = 1; 770 is_write = 1;
@@ -820,6 +828,37 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, @@ -820,6 +828,37 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
820 if (buf[1] & 3) 828 if (buf[1] & 3)
821 goto fail; 829 goto fail;
822 break; 830 break;
  831 + case 0x9e:
  832 + /* Service Action In subcommands. */
  833 + if ((buf[1] & 31) == 0x10) {
  834 + DPRINTF("SAI READ CAPACITY(16)\n");
  835 + memset(outbuf, 0, len);
  836 + bdrv_get_geometry(s->bdrv, &nb_sectors);
  837 + /* Returned value is the address of the last sector. */
  838 + if (nb_sectors) {
  839 + nb_sectors--;
  840 + outbuf[0] = (nb_sectors >> 56) & 0xff;
  841 + outbuf[1] = (nb_sectors >> 48) & 0xff;
  842 + outbuf[2] = (nb_sectors >> 40) & 0xff;
  843 + outbuf[3] = (nb_sectors >> 32) & 0xff;
  844 + outbuf[4] = (nb_sectors >> 24) & 0xff;
  845 + outbuf[5] = (nb_sectors >> 16) & 0xff;
  846 + outbuf[6] = (nb_sectors >> 8) & 0xff;
  847 + outbuf[7] = nb_sectors & 0xff;
  848 + outbuf[8] = 0;
  849 + outbuf[9] = 0;
  850 + outbuf[10] = s->cluster_size * 2;
  851 + outbuf[11] = 0;
  852 + /* Protection, exponent and lowest lba field left blank. */
  853 + r->buf_len = len;
  854 + } else {
  855 + scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NOT_READY);
  856 + return 0;
  857 + }
  858 + break;
  859 + }
  860 + DPRINTF("Unsupported Service Action In\n");
  861 + goto fail;
823 case 0xa0: 862 case 0xa0:
824 DPRINTF("Report LUNs (len %d)\n", len); 863 DPRINTF("Report LUNs (len %d)\n", len);
825 if (len < 16) 864 if (len < 16)